pseudoyu

pseudoyu

Blockchain | Programming | Photography | Boyi
github
twitter
telegram
mastodon
bilibili
jike

Hyperledger Fabric Go SDK event analysis

Introduction#

Recently, while working on a cross-chain adapter, I needed to use the Go SDK to connect to a Fabric network on a local chain and listen for events. Therefore, I summarized the events supported by Fabric and the listening methods provided by the SDK.

Fabric Events#

hyperledger_fabric_application_interact

Events are a way for clients to interact with the Fabric network. As shown in the above diagram, after a transaction is executed on the Fabric network, the client cannot obtain the status of the submitted transaction (whether it is accepted) because it is asynchronous. Therefore, the Peer nodes of Fabric provide an event mechanism, and clients can listen to block events through the gRPC interface. Starting from Fabric v1.1, event registration occurs at the channel level rather than the Peer node, allowing for more fine-grained control.

Event Types#

Events are mainly triggered by the Ledger and containers that hold chaincode contracts. Fabric supports four types of events:

  1. BlockEvent: Used to monitor newly added blocks on Fabric.
  2. ChaincodeEvent: Used to monitor events published in chaincode, i.e., user-defined events.
  3. TxStatusEvent: Used to monitor the completion of transactions on nodes.
  4. FilteredBlockEvent: Used to monitor brief block information.

In the Fabric Go SDK, these events can be operated on using the following event listeners:

  1. func (c *Client) RegisterBlockEvent(filter ...fab.BlockFilter) (fab.Registration, <-chan *fab.BlockEvent, error)
  2. func (c *Client) RegisterChaincodeEvent(ccID, eventFilter string) (fab.Registration, <-chan *fab.CCEvent, error)
  3. func (c *Client) RegisterFilteredBlockEvent() (fab.Registration, <-chan *fab.FilteredBlockEvent, error)
  4. func (c *Client) RegisterTxStatusEvent(txID string) (fab.Registration, <-chan *fab.TxStatusEvent, error)

Once the listening is complete, the registration and event channel can be removed using func (c *Client) Unregister(reg fab.Registration).

gRPC Communication#

The SDK communicates with Peer nodes through gRPC. The source code can be found at fabric-protos/peer/events.proto.

The following message types are defined:

  1. FilteredBlock: Used by FilteredBlockEvent.
  2. FilteredTransaction and FilteredTransaction: Used by FilteredTransactionEvent.
  3. FilteredChaincodeAction: Used by ChaincodeEvent.
  4. BlockAndPrivateData: Used for private data.

The response is as follows:

// DeliverResponse
message DeliverResponse {
    oneof Type {
        common.Status status = 1;
        common.Block block = 2;
        FilteredBlock filtered_block = 3;
        BlockAndPrivateData block_and_private_data = 4;
    }
}

And three gRPC communication interfaces:

service Deliver {
    // Deliver first requires an Envelope of type ab.DELIVER_SEEK_INFO with
    // Payload data as a marshaled orderer.SeekInfo message,
    // then a stream of block replies is received
    rpc Deliver (stream common.Envelope) returns (stream DeliverResponse) {
    }
    // DeliverFiltered first requires an Envelope of type ab.DELIVER_SEEK_INFO with
    // Payload data as a marshaled orderer.SeekInfo message,
    // then a stream of **filtered** block replies is received
    rpc DeliverFiltered (stream common.Envelope) returns (stream DeliverResponse) {
    }
    // DeliverWithPrivateData first requires an Envelope of type ab.DELIVER_SEEK_INFO with
    // Payload data as a marshaled orderer.SeekInfo message,
    // then a stream of block and private data replies is received
    rpc DeliverWithPrivateData (stream common.Envelope) returns (stream DeliverResponse) {
    }
}

fabric_events

The entire process is shown in the above diagram. In the Go SDK, an application's event registration request is converted into an event subscription request by implementing a Dispatcher and sent to the Peer node through the DeliverClient. The DeliverServer in the Peer node receives the subscription request, calls deliverBlocks to enter a loop, reads blocks from the Ledger, generates events, and finally sends them to the client. The Dispatcher in the client then converts them into event responses subscribed by the application.

Event Implementation Process#

The event implementation process requires two steps:

  1. Call the SetEvent method in the chaincode.
  2. Implement event listeners using the Go SDK in the client.

SetEvent Method#

Method definition:

func (s *ChaincodeStub) SetEvent(name string, payload []byte) error

Example of calling the method:

func (s *SmartContract) Invoke(stub shim.ChaincodeStubInterface) sc.Response {

    err = stub.PutState(key, value)

    if err != nil {
        return shim.Error(fmt.Sprintf("unable put state (%s), error: %v", key, err))
    }

    // The payload needs to be converted to bytes
    eventPayload := "Event Information"
    payloadAsBytes := []byte(eventPayload)

    // The SetEvent method is usually called after operations that interact with the ledger, such as PutState or DelState
    err = stub.SetEvent("<event name>", payloadAsBytes)

    if (eventErr != nil) {
        return shim.Error(fmt.Sprintf("Failed to trigger event"))
    }

    return shim.Success(nil)
}

Client Event Listeners#

// Implement a chaincode event listener
// Pass the corresponding parameters, where eventId must match the <event name> in the chaincode to implement the listener
reg, eventChannel, err := eventClient.RegisterChaincodeEvent(chaincodeID, eventID)

if err != nil {
    log.Fatalf("Failed to regitser block event: %v\n", err)
    return
}

// Unregister and remove the event channel
defer eventClient.Unregister(reg)

Summary#

The above is a basic introduction to listening for events on a Fabric network using the Go SDK. I am currently studying the Fabric Go SDK source code and will provide further explanations in the future.

References#

  1. hyperledger/fabric-sdk-go
  2. Hyperledger Fabric Packages for Go Chaincode
  3. Channel-based Peer Node Event Services
  4. fabric-protos/peer/events.proto
  5. Fabric 1.4 Source Code Interpretation 3: Event Principle Interpretation
  6. Supported Events in Fabric
  7. How to Listen for Fabric Chaincode Events
Loading...
Ownership of this post data is guaranteed by blockchain and smart contracts to the creator alone.