github.com/kchristidis/fabric@v1.0.4-0.20171028114726-837acd08cde1/examples/events/block-listener/block-listener.go (about) 1 /* 2 Copyright IBM Corp 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 "errors" 21 "flag" 22 "fmt" 23 "os" 24 25 "github.com/hyperledger/fabric/core/ledger/util" 26 "github.com/hyperledger/fabric/events/consumer" 27 "github.com/hyperledger/fabric/msp/mgmt" 28 "github.com/hyperledger/fabric/msp/mgmt/testtools" 29 "github.com/hyperledger/fabric/protos/common" 30 pb "github.com/hyperledger/fabric/protos/peer" 31 "github.com/hyperledger/fabric/protos/utils" 32 ) 33 34 type adapter struct { 35 notfy chan *pb.Event_Block 36 } 37 38 //GetInterestedEvents implements consumer.EventAdapter interface for registering interested events 39 func (a *adapter) GetInterestedEvents() ([]*pb.Interest, error) { 40 return []*pb.Interest{{EventType: pb.EventType_BLOCK}}, nil 41 } 42 43 //Recv implements consumer.EventAdapter interface for receiving events 44 func (a *adapter) Recv(msg *pb.Event) (bool, error) { 45 if o, e := msg.Event.(*pb.Event_Block); e { 46 a.notfy <- o 47 return true, nil 48 } 49 return false, fmt.Errorf("Receive unknown type event: %v", msg) 50 } 51 52 //Disconnected implements consumer.EventAdapter interface for disconnecting 53 func (a *adapter) Disconnected(err error) { 54 fmt.Print("Disconnected...exiting\n") 55 os.Exit(1) 56 } 57 58 func createEventClient(eventAddress string, _ string) *adapter { 59 var obcEHClient *consumer.EventsClient 60 61 done := make(chan *pb.Event_Block) 62 adapter := &adapter{notfy: done} 63 obcEHClient, _ = consumer.NewEventsClient(eventAddress, 5, adapter) 64 if err := obcEHClient.Start(); err != nil { 65 fmt.Printf("could not start chat. err: %s\n", err) 66 obcEHClient.Stop() 67 return nil 68 } 69 70 return adapter 71 } 72 func getTxPayload(tdata []byte) (*common.Payload, error) { 73 if tdata == nil { 74 return nil, errors.New("Cannot extract payload from nil transaction") 75 } 76 77 if env, err := utils.GetEnvelopeFromBlock(tdata); err != nil { 78 return nil, fmt.Errorf("Error getting tx from block(%s)", err) 79 } else if env != nil { 80 // get the payload from the envelope 81 payload, err := utils.GetPayload(env) 82 if err != nil { 83 return nil, fmt.Errorf("Could not extract payload from envelope, err %s", err) 84 } 85 return payload, nil 86 } 87 return nil, nil 88 } 89 90 // getChainCodeEvents parses block events for chaincode events associated with individual transactions 91 func getChainCodeEvents(tdata []byte) (*pb.ChaincodeEvent, error) { 92 if tdata == nil { 93 return nil, errors.New("Cannot extract payload from nil transaction") 94 } 95 96 if env, err := utils.GetEnvelopeFromBlock(tdata); err != nil { 97 return nil, fmt.Errorf("Error getting tx from block(%s)", err) 98 } else if env != nil { 99 // get the payload from the envelope 100 payload, err := utils.GetPayload(env) 101 if err != nil { 102 return nil, fmt.Errorf("Could not extract payload from envelope, err %s", err) 103 } 104 105 chdr, err := utils.UnmarshalChannelHeader(payload.Header.ChannelHeader) 106 if err != nil { 107 return nil, fmt.Errorf("Could not extract channel header from envelope, err %s", err) 108 } 109 110 if common.HeaderType(chdr.Type) == common.HeaderType_ENDORSER_TRANSACTION { 111 tx, err := utils.GetTransaction(payload.Data) 112 if err != nil { 113 return nil, fmt.Errorf("Error unmarshalling transaction payload for block event: %s", err) 114 } 115 chaincodeActionPayload, err := utils.GetChaincodeActionPayload(tx.Actions[0].Payload) 116 if err != nil { 117 return nil, fmt.Errorf("Error unmarshalling transaction action payload for block event: %s", err) 118 } 119 propRespPayload, err := utils.GetProposalResponsePayload(chaincodeActionPayload.Action.ProposalResponsePayload) 120 if err != nil { 121 return nil, fmt.Errorf("Error unmarshalling proposal response payload for block event: %s", err) 122 } 123 caPayload, err := utils.GetChaincodeAction(propRespPayload.Extension) 124 if err != nil { 125 return nil, fmt.Errorf("Error unmarshalling chaincode action for block event: %s", err) 126 } 127 ccEvent, err := utils.GetChaincodeEvents(caPayload.Events) 128 129 if ccEvent != nil { 130 return ccEvent, nil 131 } 132 } 133 } 134 return nil, errors.New("No events found") 135 } 136 137 func main() { 138 var eventAddress string 139 var chaincodeID string 140 var mspDir string 141 var mspId string 142 flag.StringVar(&eventAddress, "events-address", "0.0.0.0:7053", "address of events server") 143 flag.StringVar(&chaincodeID, "events-from-chaincode", "", "listen to events from given chaincode") 144 flag.StringVar(&mspDir, "events-mspdir", "", "set up the msp direction") 145 flag.StringVar(&mspId, "events-mspid", "", "set up the mspid") 146 flag.Parse() 147 148 //if no msp info provided, we use the default MSP under fabric/sampleconfig 149 if mspDir == "" { 150 err := msptesttools.LoadMSPSetupForTesting() 151 if err != nil { 152 fmt.Printf("Could not initialize msp, err: %s\n", err) 153 os.Exit(-1) 154 } 155 } else { 156 //load msp info 157 err := mgmt.LoadLocalMsp(mspDir, nil, mspId) 158 if err != nil { 159 fmt.Printf("Could not initialize msp, err: %s\n", err) 160 os.Exit(-1) 161 } 162 } 163 164 fmt.Printf("Event Address: %s\n", eventAddress) 165 166 a := createEventClient(eventAddress, chaincodeID) 167 if a == nil { 168 fmt.Println("Error creating event client") 169 return 170 } 171 172 for { 173 select { 174 case b := <-a.notfy: 175 fmt.Println("") 176 fmt.Println("") 177 fmt.Println("Received block") 178 fmt.Println("--------------") 179 txsFltr := util.TxValidationFlags(b.Block.Metadata.Metadata[common.BlockMetadataIndex_TRANSACTIONS_FILTER]) 180 for i, r := range b.Block.Data.Data { 181 tx, _ := getTxPayload(r) 182 if tx != nil { 183 chdr, err := utils.UnmarshalChannelHeader(tx.Header.ChannelHeader) 184 if err != nil { 185 fmt.Print("Error extracting channel header\n") 186 return 187 } 188 if txsFltr.IsInvalid(i) { 189 fmt.Println("") 190 fmt.Println("") 191 fmt.Printf("Received invalid transaction from channel '%s'\n", chdr.ChannelId) 192 fmt.Println("--------------") 193 fmt.Printf("Transaction invalid: TxID: %s\n", chdr.TxId) 194 } else { 195 fmt.Printf("Received transaction from channel '%s': \n\t[%v]\n", chdr.ChannelId, tx) 196 if event, err := getChainCodeEvents(r); err == nil { 197 if len(chaincodeID) != 0 && event.ChaincodeId == chaincodeID { 198 fmt.Println("") 199 fmt.Println("") 200 fmt.Printf("Received chaincode event from channel '%s'\n", chdr.ChannelId) 201 fmt.Println("------------------------") 202 fmt.Printf("Chaincode Event:%+v\n", event) 203 } 204 } 205 } 206 } 207 } 208 } 209 } 210 }