コード例 #1
0
ファイル: eventhelper.go プロジェクト: hyperledger/fabric
// SendProducerBlockEvent sends block event to clients
func SendProducerBlockEvent(block *common.Block) error {
	bevent := &common.Block{}
	bevent.Header = block.Header
	bevent.Metadata = block.Metadata
	bevent.Data = &common.BlockData{}
	for _, d := range block.Data.Data {
		if d != nil {
			if env, err := utils.GetEnvelopeFromBlock(d); err != nil {
				logger.Errorf("Error getting tx from block(%s)\n", err)
			} else if env != nil {
				// get the payload from the envelope
				payload, err := utils.GetPayload(env)
				if err != nil {
					return fmt.Errorf("Could not extract payload from envelope, err %s", err)
				}

				if common.HeaderType(payload.Header.ChainHeader.Type) == common.HeaderType_ENDORSER_TRANSACTION {
					tx, err := utils.GetTransaction(payload.Data)
					if err != nil {
						logger.Errorf("Error unmarshalling transaction payload for block event: %s", err)
						continue
					}
					chaincodeActionPayload := &pb.ChaincodeActionPayload{}
					err = proto.Unmarshal(tx.Actions[0].Payload, chaincodeActionPayload)
					if err != nil {
						logger.Errorf("Error unmarshalling transaction action payload for block event: %s", err)
						continue
					}

					propRespPayload := &pb.ProposalResponsePayload{}
					err = proto.Unmarshal(chaincodeActionPayload.Action.ProposalResponsePayload, propRespPayload)
					if err != nil {
						logger.Errorf("Error unmarshalling proposal response payload for block event: %s", err)
						continue
					}
					//ENDORSER_ACTION, ProposalResponsePayload.Extension field contains ChaincodeAction
					caPayload := &pb.ChaincodeAction{}
					err = proto.Unmarshal(propRespPayload.Extension, caPayload)
					if err != nil {
						logger.Errorf("Error unmarshalling chaincode action for block event: %s", err)
						continue
					}
					// Drop read write set from transaction before sending block event
					caPayload.Results = nil
					propRespPayload.Extension, err = proto.Marshal(caPayload)
					if err != nil {
						logger.Errorf("Error marshalling tx proposal extension payload for block event: %s", err)
						continue
					}
					// Marshal Transaction again and append to block to be sent
					chaincodeActionPayload.Action.ProposalResponsePayload, err = proto.Marshal(propRespPayload)
					if err != nil {
						logger.Errorf("Error marshalling tx proposal payload for block event: %s", err)
						continue
					}
					tx.Actions[0].Payload, err = proto.Marshal(chaincodeActionPayload)
					if err != nil {
						logger.Errorf("Error marshalling tx action payload for block event: %s", err)
						continue
					}
					if t, err := proto.Marshal(tx); err == nil {
						bevent.Data.Data = append(bevent.Data.Data, t)
						logger.Infof("calling sendProducerBlockEvent\n")
					} else {
						logger.Infof("Cannot marshal transaction %s\n", err)
					}
				}
			}
		}
	}
	return Send(CreateBlockEvent(bevent))
}
コード例 #2
0
ファイル: client.go プロジェクト: hyperledger/fabric
func (d *DeliverService) readUntilClose() {
	for {
		msg, err := d.client.Recv()
		if err != nil {
			logger.Warningf("Receive error: %s", err.Error())
			return
		}
		switch t := msg.Type.(type) {
		case *orderer.DeliverResponse_Error:
			if t.Error == common.Status_SUCCESS {
				logger.Warning("ERROR! Received success in error field")
				return
			}
			logger.Warning("Got error ", t)
		case *orderer.DeliverResponse_Block:
			seqNum := t.Block.Header.Number
			block := &common.Block{}
			block.Header = t.Block.Header

			// Copy and initialize peer metadata
			putils.CopyBlockMetadata(t.Block, block)
			block.Data = &common.BlockData{}
			for _, d := range t.Block.Data.Data {
				if d != nil {
					if env, err := putils.GetEnvelopeFromBlock(d); err != nil {
						fmt.Printf("Error getting tx from block(%s)\n", err)
					} else if env != nil {
						// validate the transaction: here we check that the transaction
						// is properly formed, properly signed and that the security
						// chain binding proposal to endorsements to tx holds. We do
						// NOT check the validity of endorsements, though. That's a
						// job for VSCC below
						payload, _, err := peer.ValidateTransaction(env)
						if err != nil {
							// TODO: this code needs to receive a bit more attention and discussion:
							// it's not clear what it means if a transaction which causes a failure
							// in validation is just dropped on the floor
							logger.Errorf("Invalid transaction, error %s", err)
						} else {
							//the payload is used to get headers
							err = isTxValidForVscc(payload, d)
							if err != nil {
								// TODO: this code needs to receive a bit more attention and discussion:
								// it's not clear what it means if a transaction which causes a failure
								// in validation is just dropped on the floor
								logger.Errorf("isTxValidForVscc returned error %s", err)
								continue
							}

							if t, err := proto.Marshal(env); err == nil {
								block.Data.Data = append(block.Data.Data, t)
							} else {
								fmt.Printf("Cannot marshal transactoins %s\n", err)
							}
						}
					} else {
						logger.Warning("Nil tx from block")
					}
				}
			}

			numberOfPeers := len(service.GetGossipService().GetPeers())
			// Create payload with a block received
			payload := createPayload(seqNum, block)
			// Use payload to create gossip message
			gossipMsg := createGossipMsg(payload)
			logger.Debugf("Adding payload locally, buffer seqNum = [%d], peers number [%d]", seqNum, numberOfPeers)
			// Add payload to local state payloads buffer
			service.GetGossipService().AddPayload(d.chainID, payload)
			// Gossip messages with other nodes
			logger.Debugf("Gossiping block [%d], peers number [%d]", seqNum, numberOfPeers)
			service.GetGossipService().Gossip(gossipMsg)
			if err = producer.SendProducerBlockEvent(block); err != nil {
				logger.Errorf("Error sending block event %s", err)
			}

			d.unAcknowledged++
			if d.unAcknowledged >= d.windowSize/2 {
				logger.Warningf("Sending acknowledgement [%d]", t.Block.Header.Number)
				err = d.client.Send(&orderer.DeliverUpdate{
					Type: &orderer.DeliverUpdate_Acknowledgement{
						Acknowledgement: &orderer.Acknowledgement{
							Number: seqNum,
						},
					},
				})
				if err != nil {
					return
				}
				d.unAcknowledged = 0
			}
		default:
			logger.Warning("Received unknown: ", t)
			return
		}
	}
}