// 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)) }
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 } } }