AWS for Industries
Experimenting with Bitcoin Blockchain on AWS
In this blog post, we experiment with the Bitcoin Blockchain on AWS and demonstrate how to set up a Bitcoin Node on AWS that can be used to send and receive bitcoin from an external wallet. Before we start with the technical setup, let’s go over the potential of this technology.
The history and opportunity
The emergence of Bitcoin in 2008 marked a significant advancement in computer science and technology which up until that time had not been able to solve three critical challenges for digital payment infrastructure – decentralization, security and double spending.
Bitcoin presented a solution capable of tracking digital assets, securely and without the need for a centralized ledger controlled by an entity. As a decentralized system, Bitcoin needed a way to manage ownership and prevent double spends. To achieve this in a trust-less manner, Bitcoin uses what has come to be known as a blockchain, which is a public distributed ledger that stores a history of all transactions across independently operated nodes and establishes a mechanism to protect against bad actors. The Proof of Work consensus algorithm ensures the integrity of information in the blockchain database.
Since then, the sheer power of blockchain has inspired and fueled an entire ecosystem focused on unleashing its potential. This area has experienced exponential growth in the last several years leading to thousands of platforms, applications, startups, projects, and research.
How Bitcoin technology works
The Bitcoin protocol allows users to exchange bitcoin cryptocurrency (BTC) without any trusted third party using the decentralized, peer-to-peer Bitcoin network. The record of the transfer is maintained in a public blockchain, also known as the Bitcoin blockchain. The blockchain is replicated on every node that participates in the Bitcoin network. Each user in the Bitcoin network interfaces with a Bitcoin client, along with a Bitcoin wallet that stores the public/private keys generated for that user. The Bitcoin wallet stores the private keys locally on the users’ computing device and encrypts it with a password. Whenever the user wants to pay others using bitcoins, the wallet software allows the user to make a payment by specifying the payee’s Bitcoin address. The Bitcoin address for each Bitcoin user is derived by double hashing his public key.
Use cases in financial services
Although there are innumerable use cases and novel innovations occurring at a break neck pace, one of the most interesting use cases in the financial services industry is to leverage the Bitcoin network for global payments. This takes out intermediaries and avoids settlement risks. It often comes as a surprise that the Bitcoin protocol currently supports less than 7 transactions per second (with a 1 MB block limit) and does not achieve the transaction throughput of other traditional payment networks as it is optimized for decentralization and security. With these properties and a predefined monetary policy of creating a cap of 21 million bitcoins, the Bitcoin network is designed for use cases like store of value or digital gold.
As with many other systems that are built in layers where new functionality is built on top of the lower layers, the Bitcoin Lightning Network adds a layer on top of the Bitcoin network and supports scalable and instant payments while relying on the properties of the base layer protocol. This removes the restrictions on the transaction throughput and enables instant global payments. [2]
High-level architecture
In the technical setup, we interact with the Bitcoin Blockchain from a remote Electrum wallet that allows us to keep the private keys for our wallet in the Electrum wallet and avoid storing them in the cloud. The remote Electrum wallet is a light wallet that relies on a trusted Electrum server to send and receive transactions and uses Simplified Payment Verification (SPV) to verify transactions. The Electrum Server runs on AWS and acts as a server for the Electrum wallet. The Bitcoin Full Node stores and validates all transactions and has a full copy of the Bitcoin Blockchain. As of 12/20/2021 18:14:39 UTC, there are 714,978 blocks mined since the first Genesis block 0 created on 1/3/2009. Up to this block height, ~450 GB storage is required to run a Bitcoin Full Node containing all transactions. More details on SPV can be found in the Bitcoin Whitepaper. [1]
AWS infrastructure
For the infrastructure, we use Amazon Elastic Container Service (Amazon ECS) with AWS Fargate in a public/private VPC across two Availability Zones and spin up one AWS Fargate Service for the Bitcoin Node and the Electrum Server. All Blockchain data of the Bitcoin Core Full Node and the transaction data of the ElectrumX server are stored on a shared Amazon Elastic File System (Amazon EFS) that gets mounted to the running Fargate Service Task in one of the Private Subnets. This provides high availability for these services in one AWS region.
Deployment instructions
1. Create an AWS Cloud9 environment via the AWS console: https://console.aws.amazon.com/cloud9 with the following settings:
- Name: Specify a name (e.g. BitcoinIDE)
- Environment type: Create a new EC2 instance for environment (direct access)
- Instance type: Please select Other instance type and select t3.medium
- Platform: Amazon Linux 2
- Keep all other default settings
2. Open the provisioned AWS Cloud9 environment by clicking on “Open IDE”, then execute the following commands in the Terminal window.
3. Clone the AWS Samples GitHub Repository
- cd ~/environment
- git clone https://github.com/aws-samples/digital-assets-examples.git
- cd bitcoin_node
4. The ElectrumX server exposes an SSL port for the Electrum client and needs an SSL certificate in the configuration. The following commands generate a self-signed SSL certificate for testing.
- openssl genrsa -out server.key 2048
- openssl req -new -key server.key -out server.csr
- openssl x509 -req -days 1825 -in server.csr -signkey server.key -out server.crt
5. The base infrastructure (VPC, Subnets, Amazon ECR/ECS, NAT Gateway, NLB) can be deployed via SAM and CloudFormation.
- sam build –template-file template.yaml [if you want to deploy a more minimal version without NAT Gateway/NLB, specify: template-minimal.yaml]
- sam deploy –template-file template.yaml [specify the same template file as in the previous command]
6. For the Bitcoin Core server and the ElectrumX server, you can build one Docker image and store it into Amazon ECR.
- ./deploy_image.sh
7. The last step deploys the Docker container as a Fargate service and at any given time only one task is running in one of the configured private subnets. All data is stored on Amazon EFS:
- ./deploy_service.sh node-service.yaml [if the minimal template was selected, specify node-service-minimal.yaml]
8. Once the Fargate service is started, you can check the Amazon CloudWatch logs (here) for the running task and should see that the Bitcoin Core server is syncing with the public Bitcoin Blockchain and the ElectrumX server is syncing with transactions from the Bitcoin Core server. This initial process takes from several days to up to a week with the default configuration. You can shorten the initial block download time by increasing the assigned CPU/memory configuration in the node-service.yaml file and by optimizing the parameters in the bitcoin.conf file.
9. Verify in Amazon CloudWatch Log file that all blocks are downloaded from the Bitcoin Core and ElectrumX has synced all transactions. This step must be completed before we can connect to our node.
Receiving and sending a payment
We can interface securely with the Electrum Server and Full Bitcoin Node provisioned on AWS via a remote Electrum Wallet.
1. Install the Electrum wallet software on your local machine from here: https://electrum.org/. For other use cases, we can use any open-source Electrum client library and embed it in an application running on AWS. If the client is running on AWS, you can connect privately to the Electrum server.
2. Find out the public DNS name of the Network Load Balancer that points to the ElectrumX service (SSL port 50002). Go to AWS console (here) and note down the public DNS name.
3. Create a new Bitcoin wallet in Electrum. Open the Electrum Wallet application and select “Create New Wallet”, then select a name for the wallet (e.g. mywallet).
- Select “Standard wallet”. For more secure setups, select “multi-signature wallet”. A multi-sig wallet uses multiple keys for generating Bitcoin addresses and signing transactions. In a 2-of-3 multi-sig setup, only 2 keys are required to sign a transaction. This provides redundancy if one of the keys is not accessible anymore.
- Create a new seed. For more secure setups, use a hardware device that stores the seed on a dedicated device and is not connected online.
- Write down and confirm the seed phrase. Please note the warnings for the seed phrase and store it securely. With the seed phrase, the private and public keys for your wallet can be generated.
- Set a password for the wallet. This provides another layer of security and encrypts the wallet keys.
4. Configure Electrum wallet to use ElectrumX server on AWS. This provides privacy by not using public Electrum servers. Click on the circle in the bottom right of the Electrum wallet to configure the network settings.
- Specify the public DNS name of the NLB (noted down in step 2, e.g. “NLB1-xxx.elb.us-east-1.amazonaws.com”) and specify the server as “NLB1-xxx.elb.us-east-1.amazonaws.com:50002”. Please make sure to add the port 50002 at the end and uncheck “Select server automatically” as you don’t want to connect to other servers. If something is not connected properly, the circle in the bottom right of the previous screen turns red.
5. Receive bitcoin: To test our node, you can send some small BTC amount (e.g. 0.0002 BTC) from another wallet to our wallet. The tab “Addresses” list some initial receiving BTC addresses, e.g. starting with “bc1…”.
- After the BTC transaction is broadcasted from the other wallet to the Bitcoin network, you should see the transaction shortly after in the “History” tab. The current network traffic and the specified transaction fee determine how quickly a transaction is confirmed. Usually three confirmations are completed in 30-45 min.
6. Send bitcoin: To spend the received BTC, go to the “Send” tab and specify the receiving BTC address in the “Pay To” field and click “Pay…”.
Clean Up
To clean up all resources, delete the created CloudFormation stacks by following the instructions here and delete the AWS Cloud9 environment here.
Conclusion
In this blog post, we experimented with the Bitcoin Blockchain network and setup the required infrastructure on AWS. This allowed us to use an external Electrum wallet software for receiving and sending on-chain Bitcoin payments while keeping private keys locally and trusting only our own Bitcoin Node/ Electrum server. Companies that provide custodial services for Bitcoin use sophisticated procedures and methods for securing wallet configuration and private keys for their customers in the cloud and in offline storage. Using multi-sig wallets, shared custodial services can be provided, where one or more parties hold the keys and a certain number of keys are required to withdraw funds from a wallet.
References
[1] Satoshi Nakamoto’s Bitcoin Whitepaper: https://bitcoin.org/bitcoin.pdf
[2] Bitcoin Lightning Network Paper: https://lightning.network/lightning-network-paper.pdf