Discover Messages stored on Bitcoin Mainnet with Amazon Managed Blockchain Access

5 minute read
Content level: Intermediate
3

Learn how to leverage Amazon Managed Blockchain (AMB) Access Bitcoin to explore messages embedded on Bitcoin Mainnet, including the iconic message left by Satoshi Nakamoto in the genesis block.

Introduction

Have you ever been curious about the message Satoshi Nakamoto embedded in Bitcoin's genesis block? With Amazon Managed Blockchain (AMB) Access Bitcoin, you can explore this intriguing aspect of Web3 history. This tutorial guides you through extracting the coinbase transaction from Bitcoin's genesis block and decoding the original message that Satoshi left behind.

Additionally, you will learn how to extract messages from the OP_RETURN, an opcode in Bitcoin's scripting language used to mark a transaction output as invalid. This tutorial provides Python sample code to help you uncover "hidden" messages within both of these data structures.

Prerequisites
  • Installation of the AWS Command Line Interface (CLI).
    • Run the command aws configure to set the variables for your IAM User’s Access Key ID, Secret Access Key, and Region.
      • Ensure that this User has the appropriate IAM permissions for AMB Access Bitcoin. For this tutorial, you can use the AmazonManagedBlockchainFullAccess managed policy.
  • Installation of Python and the AWS SDK for Python (Boto3).

Step 1: Setting up the project

Create a new directory for your project and change into it by running the following command:

mkdir bitcoinMessages && cd bitcoinMessages

Step 2: Write the script to retrieve messages from the Bitcoin network

This script contains the following functionality:

  1. Request Signing: The get_signed_headers function generates the necessary AWS Signature Version 4 (SigV4) headers for authenticating the requests to the AWS Managed Blockchain service.
  2. Performing AMB Access Bitcoin JSON-RPC Requests: The btc_rpc function is used to make POST requests to the AMB Access Bitcoin RPC endpoint, passing in the request method and parameters. It uses the get_signed_headers function to add the necessary authentication headers.
  3. Retrieving embedded messages: The get_message function retrieves the message embedded in the coinbase transaction of a given block. If the op_return parameter is set to True, it instead retrieves the messages stored in the OP_RETURN outputs of the specified block.

The script includes examples to:

  1. Retrieve Satoshi’s hidden message in the genesis block (block 0).
  2. Extract the message embedded in the 440th OP_RETURN output in block 840,000, which corresponds to Bitcoin's fourth halving event on April 19, 2024.

Create a new file (e.g retrieveMessages.py) and copy the following code:

import json
import requests
import botocore.session
from botocore.awsrequest import AWSRequest

# Configuration for AWS Managed Blockchain service
SERVICE, REGION = 'managedblockchain', 'us-east-1'
ENDPOINT = 'https://mainnet.bitcoin.managedblockchain.us-east-1.amazonaws.com'

def get_signed_headers(url, payload):
    session = botocore.session.get_session()
    request = AWSRequest(method='POST', url=url, data=json.dumps(payload))
    botocore.auth.SigV4Auth(session.get_credentials(), SERVICE, REGION).add_auth(request)
    return dict(request.headers)

def btc_rpc(method, params):
    payload = {"jsonrpc": "2.0", "method": method, "params": params, "id": 1}
    response = requests.post(ENDPOINT, headers=get_signed_headers(ENDPOINT, payload), data=json.dumps(payload))
    return response.json() if response.ok else response.json()

# Extracts and decodes the coinbase transaction from the genesis block to retrieve the message embedded by Satoshi Nakamoto.
# For blocks other than genesis, extracts ASCII characters from coinbase hex data.
# For the parameter op_return is set to True, data is extracted from OP_RETURN transaction outputs.
def get_message(block_number, op_return=False):
    block_hash = btc_rpc("getblockhash", [block_number]).get('result') #Get the hash of the specified block number
    block_data = btc_rpc("getblock", [block_hash, 2]).get('result')  # Fetch the full block data with the block hash. The second parameter '2' indicates verbose mode with full transactions.
    if op_return == True: #Extract and decode messages from OP_RETURN outputs of transactions
        return [
            # Decode UTF-8 message from hex, ignoring non-decodable bytes, starting after the OP_RETURN opcode ('6a'). The slicing skips the first four characters (the OP_RETURN opcode and the length byte).
            bytes.fromhex(vout.get('scriptPubKey', {}).get('hex', '')[4:]).decode('utf-8', 'ignore') 
            for tx in block_data.get('tx', []) # Iterate over each transaction in the block
            for vout in tx.get('vout', []) # Iterate over each output in the transaction
            # Check if the output script starts with '6a' (OP_RETURN opcode) and return the encoded message. 
            if vout.get('scriptPubKey', {}).get('hex', '').startswith('6a') 
        ]
    else: #Extract and decode messages from coinbase transaction
        #Extract the coinbase from the first transaction in the block 
        coinbase_input = block_data['tx'][0]['vin'][0].get('coinbase', '') 
        # Decode and return readable ASCII characters from the hex-encoded coinbase transaction data.
        return ''.join(chr(c) for c in bytes.fromhex(coinbase_input) if 32 <= c < 127) 

# Example usage
# Genesis Block that contains Satoshi's message in the coinbase transaction
coinbase_tx_block_number = 0  
# Block with OP_RETURN data. This block was when Bitcoin's fourth halving occurred on April 19, 2024.
op_return_block_number = 840000 

print("Hidden message in block " + str(coinbase_tx_block_number) + ":")
print(get_message(coinbase_tx_block_number))

print("\nHidden messages in OP_RETURN data of block " + str(op_return_block_number) + ":")
#Prints the 440th message in the block for readability. Modify or remove the slicing operation if you would like to display more messages that are stored in the OP_RETURN of a specific block.
for msg in get_message(op_return_block_number, True)[439:440]: 
    print("OP_RETURN message:", msg)

Execute the script by running:

python retrieveMessages.py

Conclusion

You have utilized AMB Access Bitcoin to retrieve Satoshi’s historic message from the coinbase transaction of Bitcoin’s genesis block. You also fetched data from the OP_RETURN outputs related to the block that marked Bitcoin’s fourth halving. Please leave a comment below if you have any questions. If you would like to learn more about AMB Access Bitcoin, you can refer to the documentation. Remember to prioritize security, especially with your AWS credentials.

Please leave a comment below if you have any questions. To get started with Amazon Managed Blockchain (AMB), you can navigate to the AWS Console.