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