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  }