github.com/darrenli6/fabric-sdk-example@v0.0.0-20220109053535-94b13b56df8c/orderer/sample_clients/single_tx_client/single_tx_client.go (about) 1 /* 2 Copyright Digital Asset Holdings, LLC 2016 All Rights Reserved. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package main 18 19 import ( 20 "fmt" 21 "math" 22 "time" 23 24 "github.com/hyperledger/fabric/common/configtx/tool/provisional" 25 cb "github.com/hyperledger/fabric/protos/common" 26 ab "github.com/hyperledger/fabric/protos/orderer" 27 "github.com/hyperledger/fabric/protos/utils" 28 29 "github.com/golang/protobuf/proto" 30 "github.com/op/go-logging" 31 "golang.org/x/net/context" 32 "google.golang.org/grpc" 33 ) 34 35 var logger = logging.MustGetLogger("single_tx_client") 36 37 var UPDATE byte = 0 38 var SEND byte = 1 39 40 var NEEDED_UPDATES = 2 41 var NEEDED_SENT = 1 42 43 func main() { 44 logger.Info("Creating an Atomic Broadcast GRPC connection.") 45 timeout := 4 * time.Second 46 clientconn, err := grpc.Dial(":7050", grpc.WithBlock(), grpc.WithTimeout(timeout), grpc.WithInsecure()) 47 if err != nil { 48 logger.Errorf("Failed to connect to GRPC: %s", err) 49 return 50 } 51 client := ab.NewAtomicBroadcastClient(clientconn) 52 53 resultch := make(chan byte) 54 errorch := make(chan error) 55 56 logger.Info("Starting a goroutine waiting for ledger updates.") 57 go updateReceiver(resultch, errorch, client) 58 59 logger.Info("Starting a single broadcast sender goroutine.") 60 go broadcastSender(resultch, errorch, client) 61 62 checkResults(resultch, errorch) 63 } 64 65 func checkResults(resultch chan byte, errorch chan error) { 66 l := len(errorch) 67 for i := 0; i < l; i++ { 68 errres := <-errorch 69 logger.Error(errres) 70 } 71 72 updates := 0 73 sentBroadcast := 0 74 for i := 0; i < 3; i++ { 75 select { 76 case result := <-resultch: 77 switch result { 78 case UPDATE: 79 updates++ 80 case SEND: 81 sentBroadcast++ 82 } 83 case <-time.After(30 * time.Second): 84 continue 85 } 86 } 87 if updates != NEEDED_UPDATES { 88 logger.Errorf("We did not get all the ledger updates.") 89 } else if sentBroadcast != NEEDED_SENT { 90 logger.Errorf("We were unable to send all the broadcasts.") 91 } else { 92 logger.Info("Successfully sent and received everything.") 93 } 94 } 95 96 func updateReceiver(resultch chan byte, errorch chan error, client ab.AtomicBroadcastClient) { 97 logger.Info("{Update Receiver} Creating a ledger update delivery stream.") 98 dstream, err := client.Deliver(context.Background()) 99 if err != nil { 100 errorch <- fmt.Errorf("Failed to get Deliver stream: %s", err) 101 return 102 } 103 dstream.Send(&cb.Envelope{ 104 Payload: utils.MarshalOrPanic(&cb.Payload{ 105 Header: &cb.Header{ 106 ChannelHeader: utils.MarshalOrPanic(&cb.ChannelHeader{ 107 ChannelId: provisional.TestChainID, 108 }), 109 SignatureHeader: utils.MarshalOrPanic(&cb.SignatureHeader{}), 110 }, 111 Data: utils.MarshalOrPanic(&ab.SeekInfo{ 112 Start: &ab.SeekPosition{Type: &ab.SeekPosition_Newest{ 113 Newest: &ab.SeekNewest{}}}, 114 Stop: &ab.SeekPosition{Type: &ab.SeekPosition_Specified{Specified: &ab.SeekSpecified{Number: math.MaxUint64}}}, 115 Behavior: ab.SeekInfo_BLOCK_UNTIL_READY, 116 }), 117 }), 118 }) 119 120 logger.Info("{Update Receiver} Listening to ledger updates.") 121 for i := 0; i < 3; i++ { 122 m, inerr := dstream.Recv() 123 if inerr != nil { 124 errorch <- fmt.Errorf("Failed to receive consensus: %s", inerr) 125 return 126 } 127 switch b := m.Type.(type) { 128 case *ab.DeliverResponse_Status: 129 fmt.Println("Got status ", b) 130 case *ab.DeliverResponse_Block: 131 logger.Info("{Update Receiver} Received a ledger update.") 132 for i, tx := range b.Block.Data.Data { 133 pl := &cb.Payload{} 134 e := &cb.Envelope{} 135 merr1 := proto.Unmarshal(tx, e) 136 merr2 := proto.Unmarshal(e.Payload, pl) 137 if merr1 == nil && merr2 == nil { 138 logger.Infof("{Update Receiver} %d - %v", i+1, pl.Data) 139 } 140 } 141 resultch <- UPDATE 142 } 143 } 144 logger.Info("{Update Receiver} Exiting...") 145 } 146 147 func broadcastSender(resultch chan byte, errorch chan error, client ab.AtomicBroadcastClient) { 148 logger.Info("{Broadcast Sender} Waiting before sending.") 149 <-time.After(5 * time.Second) 150 bstream, err := client.Broadcast(context.Background()) 151 if err != nil { 152 errorch <- fmt.Errorf("Failed to get broadcast stream: %s", err) 153 return 154 } 155 bs := []byte{0, 1, 2, 3} 156 pl := &cb.Payload{ 157 Header: &cb.Header{ 158 ChannelHeader: utils.MarshalOrPanic(&cb.ChannelHeader{ 159 ChannelId: provisional.TestChainID, 160 }), 161 }, 162 Data: bs, 163 } 164 mpl, err := proto.Marshal(pl) 165 if err != nil { 166 panic("Failed to marshal payload.") 167 } 168 bstream.Send(&cb.Envelope{Payload: mpl}) 169 logger.Infof("{Broadcast Sender} Broadcast sent: %v", bs) 170 logger.Info("{Broadcast Sender} Exiting...") 171 resultch <- SEND 172 }