Building an event-based application with Amazon Managed Blockchain

Applications built on Amazon Managed Blockchain allow multiple parties to transact with one another in a trusted environment with the ability for each party to endorse transactions before they are committed to the blockchain. Blockchain events allow applications to respond to activity and updates to the smart contracts that have been deployed to the network, as well as updates to the blockchain network, such as the creation of a new block.

These events are very useful and can enable a diverse set of activities; for example, user notifications with Amazon Simple Notification Service (Amazon SNS) when a business event happens, or streaming data to business intelligence and analytics engines such as Amazon QuickSight or Amazon Redshift. You can also stream to purpose-built databases such as Amazon DynamoDB or Amazon Aurora, or use AWS Lambda for event-triggered applications.

A Hyperledger Fabric blockchain network can produce three event types that allow you to monitor blockchain network activity:

  • Block events – These occur when a new block gets added to the ledger. Block events contain information about the transactions included in the block.
  • Transaction events – These occur when a transaction is committed to the ledger.
  • Chaincode events – Chaincode is application code that runs on the blockchain network. It enables interaction with the ledger. You can define events within the chaincode and define the conditions that trigger these events. The event is triggered when a block containing the necessary conditions is committed to the ledger.

This post explores the use case of a transparent NGO donation application. For more information about creating the application and configuring it so donors can see how the NGO is spending their donations, see the Github repo. In this post, you continue to build on that application by notifying users via SMS of new donations. You walk through how to build this workflow using chaincode events with Amazon Managed Blockchain and send SMS messages using Amazon SNS.

Solution overview

The following diagram illustrates the architecture of this solution.

The solution involves the following steps:

  • Deploying a blockchain event listener as an AWS Fargate task
  • Connecting the listener to a peer node in the Managed Blockchain network to register and be notified of blockchain events
  • Sending blockchain events from the listener to Amazon Simple Queue Service (Amazon SQS), where a Lambda function processes them
  • Publishing these events as messages to Amazon SNS, which sends an SMS message

Blockchain event listener

The blockchain event listener is a Node.js application that uses the Node.js Fabric SDK to connect to a Fabric peer node and register for notifications of blockchain events. When a listener connects to the peer node, it specifies a Fabric user with which to connect and the event types it’s interested in. The user credentials consist of a private key and a public certificate, and are stored in AWS Secrets Manager.

For this use case, you register the event listener to listen for chaincode events, which trigger when an NGO receives a donation. The event listener publishes these events to an SQS queue.

The Node.js listener application is packaged as a container image and stored in Amazon Elastic Container Registry (Amazon ECR). It runs as a Fargate task in an Amazon Elastic Container Service (Amazon ECS) service. Running the listener as a Fargate task reduces operational overhead because it removes the need to provision and maintain Amazon Elastic Compute Cloud (Amazon EC2) instances, and running it within an ECS service allows for automatic restarting of the application in case of failure. For this use case, you run the Fargate task in a private subnet within your VPC because it doesn’t need to be directly accessible from the public internet.

When the Fargate task starts, it downloads the user’s credentials from Secrets Manager before connecting to the peer node.

By default, the listener is notified of all events that occurred on the blockchain since creation. This means that if the listener restarts, the same events are processed again. To handle this, the listener can persist the last block it processed (for example, in DynamoDB), and provide this block number when it restarts, which indicates the starting point for new event notifications. This is set using the startBlock attribute within the RegistrationOpts object that is provided during listener registration.

Lambda event handler

A Lambda function processes chaincode events published to the SQS queue. The function uses the event data to create the SMS message body and calls Amazon SNS to send the notification message.

Upgrading chaincode

The Fabric NGO chaincode is upgraded to emit a chaincode event when a donation occurs. You do this using the Node.js Fabric SDK. See the following code example:

function createEvent(stub, data = {}) {
  const eventObject = {
      createdAt: (new Date()).getTime(),
      createdBy: data.donor,
      donationAmount: data.amount
  }
  stub.setEvent(data.eventName, Buffer.from(JSON.stringify(eventObject)));
}

Upgrading the chaincode requires two steps:

  • Installing the chaincode on the peer node
  • Upgrading the chaincode on the channel

In this use case, you run a single peer node, but if you do this with multiple peer nodes or on a network with multiple members, you need to install the chaincode on each peer node. You still only need to perform the chaincode upgrade one time.

Prerequisites

Before starting the walkthrough, you should complete Part 1 and Part 2 of the nonprofit workshop in the GitHub repo. These parts include creating the Managed Blockchain network, enrolling the admin user, and deploying the NGO chaincode.

Walkthrough overview

For more information about each step in this process, see the GitHub repo. Each step listed in this post has a matching step in the repo where you run the script or command that completes that step. As you read each step, you can refer to the corresponding step in the repo to gain a more in-depth understanding.

The walkthrough includes the following steps:

  1. Create a Fabric user to listen for peer events
  2. Deploy the Node.js listener in a container image to Amazon ECR
  3. Deploy the SQS queue
  4. Deploy the ECS service that hosts the Fargate task
  5. Deploy the Fargate task to run the listener
  6. Create an SNS topic with an SMS subscription
  7. Deploy the Lambda function to publish every event to Amazon SNS
  8. Upgrade the chaincode to emit the chaincode event

Step 1: Creating a Fabric user to listen for peer events

Hyperledger Fabric peer nodes emit events as they process blocks and transactions, and event listeners register to receive notifications of these events. To register an event listener, you need to use user credentials to connect to the peer.

In this step, you register and enroll a user. Registering a user creates an entry for the user within their organization’s certificate authority. Enrolling the user generates the credentials that they use to sign transactions. You can also use these credentials to register an event listener with a peer node.

Enrolling a user generates the following artifacts:

  • A private key
  • A signing certificate (public key)

These artifacts are saved to Secrets Manager, and the Fargate task downloads them during its execution.

For more information, see Register and Enroll a User as an Administrator.

Step 2: Deploying the Node.js listener in a container image to Amazon ECR

The event listener needs to run continuously so it can receive event notifications as they occur. To run the listener, you package the listener into a container image that your ECS service manages. The container image is published to your private Amazon ECR repository, where the ECS service can pull it.

In a production environment, to provide high availability, you would run multiple instances of this container.

Step 3: Deploying the SQS queue

To provide durability of the blockchain events, the event listener writes blockchain events to an SQS queue that queues the events for a Lambda function to process. Storing the events as messages in an SQS queue facilitates error handling if the Lambda function fails to process the message. The message processing can try again, and if it fails again, Amazon SQS moves the message to a dead-letter queue (DLQ) where you can inspect it for further debugging.

You can send the blockchain event directly to an SNS topic, which removes the need for an SQS queue and reduces cost. Amazon SNS supports DLQs, which can make your application more resilient by storing messages if the subscription endpoint becomes unreachable. This is a more cost-effective approach and recommended in a production environment. For more information, see Configuring an Amazon SNS dead-letter queue for a subscription.

This post uses an SQS queue to illustrate how you could extend this to integrate with other services.

Step 4: Deploying the ECS service to host the Fargate task

Running the event listener as a Fargate task that an ECS service manages allows you to use a serverless architecture, which removes the need to manage and provision servers. The Fargate security model provides isolation of applications by design.

Step 5: Deploy the Fargate task to run the listener

Though Amazon ECS can scale the number of tasks in a service to meet demand, your listener is instantiated as a single task in the service. The service is defined with a minimum of one task, so the task restarts automatically in the event of failure. Because blockchain events persist on the blockchain, when the listener task restarts, it can begin consuming events from the most recent block it read from.

Create a Fargate task that uses the container image you uploaded in step 2. The task defines the configuration settings for the container that runs the image, including the logging options and the environment variables the Node.js event listener uses.

You now have a listener running as a Fargate task that listens for blockchain events and publishes every event to Amazon SQS. You can handle these events using a Lambda function. You can also invoke other AWS services from the Lambda function. For example, you can write the blockchain event data to DynamoDB or Amazon Simple Storage Service (Amazon S3) to deliver faster query times and drive Amazon QuickSight dashboards. For this use case, you use Amazon SNS to send an SMS notification of a new donation.

Step 6: Creating an SNS topic with an SMS subscription

Amazon SNS is a highly available and durable messaging service that you can use to exchange messages between decoupled microservices and send notifications to end-users with mobile push, SMS, and email. Messages are sent to a topic to which interested parties can subscribe. In this step, you create a topic for a “New donation” message and subscribe to receive SMS notifications using your mobile phone number. For more information, see Sending an SMS message.

For this use case, you receive an SMS for every donation event. However, in a real-world application, you would likely want to use filters to control which notifications go to which users.

Step 7: Deploying the Lambda function to publish every event to Amazon SNS

Each blockchain event on the SQS queue triggers the Lambda function. The function parses the event data and publishes a corresponding message to Amazon SNS. Amazon SNS forwards the message to SMS via the subscription.

Step 8: Upgrading the chaincode to emit the chaincode event

All the steps you have executed so far have been external to the blockchain network. In this final step, you upgrade the chaincode on the Fabric network to emit an event whenever the createDonation function is called. After the chaincode source code is updated, it must be installed on every peer node. A blockchain member typically has multiple peer nodes for high availability and fault tolerance, and you should deploy the chaincode to all the peer nodes.

After all the members have installed the chaincode on their peer nodes, you can upgrade the chaincode on the channel.

Testing

You’ve now provisioned all the components and are ready to test. To test the solution, complete the following steps:

  1. Create an NGO by issuing a blockchain transaction to invoke the createNGO function in your chaincode
  2. Make a donation by invoking the createDonation function, which is where you added the new code to emit the chaincode event
  3. If all is working correctly, you should receive an SMS within a short period of time

If you don’t receive the SMS, check the SQS queue. If you have messages in the DLQ, inspect those to see why the Lambda function is failing. If you don’t see any messages, your listener may be failing. Check the Fargate container’s Amazon CloudWatch Logs for details.

Summary

In this post, you walked through how to deploy a Hyperledger Fabric blockchain event listener running on AWS Fargate. You also deployed a Lambda function that processes the chaincode events and publishes Amazon SNS notifications to send SMS messages.

As a next step, you could write a different event listener and send event data to your Amazon S3 data lake to gain insights into the blockchain data using Amazon QuickSight. To begin building this, you would replace the Lambda function you deployed in step 7 with a Lambda function that writes event data to Amazon S3. Stay tuned for a later post that shows you how.

 


About the Author

 

Emile is a Senior Blockchain Architect at AWS. In his free time, he enjoys trail running in the hills north of San Francisco, and trying to keep up with his 18 month old daughter.