Run your private blockchain on AWS

Before the AWS re:Invent 2016, I did post tweets about my conviction that AWS would unveil a Blockchain as a Service during the event. As it was not the case, I decided to jump myself into the blockchain world and build my own private blockchain on AWS. This post covers my first steps in this world and will help you (at least I hope it will) to run you first blockchain too. At the end of this post, you should be able to run your own private blockchain, mine some crypto currency, exchange crypto currency between nodes, and see what’s in a transaction.

Once you browsed the web for available Blockchain solutions, you realize there are lots of them. I focused on the Multichain solution because it’s already packaged, looks quite easy to use and able to manage multiple chains on a single node. Before going further, I strongly advise you to read the documentation available on their site to understand the concept of blockchain and how it works.

As the goal of this post is not to deep dive into how to create an AWS infrastructure, the following script will do the job for you. It will create a VPC in the London region (eu-west-2). In this VPC, two subnets are created (one per Availability Zone), two instances are loaded with one EIP for each. A single Security Group is attached to the instances allowing SSH from Internet and inter-instance communication on any port. Here is a blueprint of what will be created by the script.

 

AWS Blockchain Infra

 

Before running the script, take care to change the keyPair variable value (line 11). If you need help about the AWS key pairs, here is what your are looking for.

If you change the region used, take care to also change the AMI as the AMI are not cross region available.

Feel free to change the instance type with what you think matches your testing requirements. I chose the c4.large because it’s the less expensive instance type in the range of the compute oriented instances. I did made some tests with the t2.micro, but it’s definitely too small to run your blockchain if you try to push the number of blockchain transactions per seconds.

 

import boto3
import time

#AWS Variables => Please check at least awsProfile, ami, instanceType and keyPair
awsProfile =    "default"
awsRegion   =   "eu-west-2"     #London
vpcCIDR     =   "10.0.0.0/24"
subnetAZaCIDR   =   "10.0.0.0/25"
subnetAZbCIDR   =   "10.0.0.128/25"
awsAccount = boto3.client('sts').get_caller_identity().get('Account')
keyPair = "ubuntu_home"   # => Don't forget to change it with the name of a key pair on which you have access on the region where the script will be executed
ami = "ami-ede2e889"      # => This is the lastest Ubuntu LTS in eu-west-2 region available (date: 2017/03/04). Don't forget to change it according your needs
instanceType = "c4.large" # => at the timing of writing this script, the c4.large instance type is the cheapest compute instance available

#Define which profile is used
session = boto3.Session(profile_name=awsProfile)


#VPC Creation without IPv6
ec2Client = session.client('ec2',region_name=awsRegion)
ec2Resource = session.resource('ec2',region_name=awsRegion)

vpc = ec2Client.create_vpc(
    CidrBlock=vpcCIDR,
    AmazonProvidedIpv6CidrBlock=False
)
tagResponse = ec2Client.create_tags(
    Resources=[
        vpc["Vpc"]["VpcId"],
    ],
    Tags=[
        {
            'Key': 'Name',
            'Value': 'BlockChainVpc'
        },
    ]
)

#Create Subnet in AZ a & b
subnetAZa = ec2Client.create_subnet(
    VpcId=vpc["Vpc"]["VpcId"],
    CidrBlock=subnetAZaCIDR,
    AvailabilityZone= awsRegion + "a"
)
tagResponse = ec2Client.create_tags(
    Resources=[
        subnetAZa["Subnet"]["SubnetId"],
    ],
    Tags=[
        {
            'Key': 'Name',
            'Value': 'BlockChainSubnetAZa'
        },
    ]
)
subnetAZb = ec2Client.create_subnet(
    VpcId=vpc["Vpc"]["VpcId"],
    CidrBlock=subnetAZbCIDR,
    AvailabilityZone= awsRegion + "b"
)
tagResponse = ec2Client.create_tags(
    Resources=[
        subnetAZb["Subnet"]["SubnetId"],
    ],
    Tags=[
        {
            'Key': 'Name',
            'Value': 'BlockChainSubnetAZb'
        },
    ]
)
#Create the Internet Gateway and attached it to the VPC
igw = ec2Client.create_internet_gateway()
tagResponse = ec2Client.create_tags(
    Resources=[
        igw["InternetGateway"]["InternetGatewayId"],
    ],
    Tags=[
        {
            'Key': 'Name',
            'Value': 'BlockChainInternetGateway'
        },
    ]
)
response = ec2Client.attach_internet_gateway(
    InternetGatewayId=igw["InternetGateway"]["InternetGatewayId"],
    VpcId=vpc["Vpc"]["VpcId"]
)

#Add route to 0.0.0.0/0 through the IGW
#As the VPC is just created, there is only route table whih exists is the main one, so we add the route to this one.
resourceVPC = ec2Resource.Vpc(id=vpc["Vpc"]["VpcId"])
resourceVPC.load()

for RouteTable in resourceVPC.route_tables.filter(Filters=[{'Name': 'association.main', 'Values': ["true"]}]):
    mainRouteTable = RouteTable
mainRouteTable.create_route(
        DestinationCidrBlock='0.0.0.0/0',
        GatewayId=igw["InternetGateway"]["InternetGatewayId"]
    )

#Create a security group wich allow connection from Internet through SSH (TCP 22) and any traffic between nodes
sgNodeCom = ec2Client.create_security_group(
    GroupName='BlockChain',
    Description='Allow communication between nodes on any TCP ports and SSH from internet',
    VpcId=vpc["Vpc"]["VpcId"]
)
tagResponse = ec2Client.create_tags(
    Resources=[
        sgNodeCom["GroupId"],
    ],
    Tags=[
        {
            'Key': 'Name',
            'Value': 'BlockChainSg'
        },
    ]
)
resSgNodeCom = ec2Resource.SecurityGroup(id=sgNodeCom["GroupId"])
response = resSgNodeCom.authorize_ingress(
    IpPermissions= [{
        'IpProtocol': '-1',
        'IpRanges':[{'CidrIp': vpcCIDR}]
     },
     {
         'IpProtocol': 'tcp',
         'FromPort'  : 22,
         'ToPort': 22,
         'IpRanges':[{'CidrIp': '0.0.0.0/0'}]
     }
    ]
)

#Function to create the nodes
def CreateNode(subnetID,nodeID):
    UserData = "#!/bin/bash -ex \n" \
               "exec > >(tee /var/log/user-data.log|logger -t user-data -s 2>/dev/console) 2>&1 \n" \
               "echo BEGIN \n" \
               "sudo apt-get update \n" \
               "cd /tmp \n" \
               "wget http://www.multichain.com/download/multichain-1.0-alpha-28.tar.gz \n" \
               "tar -xvzf multichain-1.0-alpha-28.tar.gz \n" \
               "cd multichain-1.0-alpha-28 \n" \
               "cp multichaind multichain-cli multichain-util /usr/local/bin \n" \
               "echo END"
    resSubnetAzA = ec2Resource.Subnet(id=subnetID)
    instances = resSubnetAzA.create_instances(
        ImageId=ami,
        MinCount=1,
        MaxCount=1,
        KeyName=keyPair,
        UserData=UserData,
        SecurityGroupIds=[
            sgNodeCom["GroupId"]
        ],
        InstanceType= instanceType,
        InstanceInitiatedShutdownBehavior='stop'
    )
    for instance in instances:
        instanceID=instance.id
    tagResponse = ec2Client.create_tags(
        Resources=[
            instanceID,
        ],
        Tags=[
            {
                'Key': 'Name',
                'Value': 'Node' + str(nodeID)
            },
        ]
    )

    Instance_Ready= False
    while(not Instance_Ready):
        time.sleep(5)
        instance = ec2Resource.Instance(id=instanceID)
        instance.load()
        if(instance.state["Code"]!=0):
            Instance_Ready = True
    eipNode1 = ec2Client.allocate_address(Domain='vpc')
    response = ec2Client.associate_address(
        InstanceId=instanceID,
        PublicIp=eipNode1["PublicIp"])
    print "to connect node "+ str(nodeID) +", use the command: ssh -i \"" + keyPair + "\" ubuntu@" + eipNode1["PublicIp"]

#Creation of the nodes
CreateNode(subnetAZa["Subnet"]["SubnetId"],1)
CreateNode(subnetAZb["Subnet"]["SubnetId"],2)

Once the script has run, it will give you the SSH command to connect node 1 and node 2. Connect both nodes and run the command as explained below on each node.  As the installation of Multichain on an instance is not challenging and will not bring any added knowledge on how the blockchain runs, I did include it in the script you just run, which means that Multichain is now available on both nodes. If you are interested on how to install it, here is this piece of information.

Step 0: Check the Multichain installation on both nodes

multichain-cli is the command line interface to manage your blockchain. If this command is available, it means that Multichain is properly installed on your node.

Enter the command:

multichain-cli

The result should be:

MultiChain Core RPC client build 1.0 alpha 28 protocol 10007


Usage:
 multichain-cli <blockchain-name> [options] <command> [params] Send command to MultiChain Core
 multichain-cli <blockchain-name> [options] help List commands
 multichain-cli <blockchain-name> [options] help <command> Get help for a command

Options:
 -? This help message
 -conf=<file> Specify configuration file (default: multichain.conf)
 -datadir=<dir> Specify data directory
 -requestout=<requestout> Send request to stderr, stdout or null (not print it at all), default stderr
 -saveclilog=<n> If <n>=0 multichain-cli history is not saved, default 1
 -rpcconnect=<ip> Send commands to node running on <ip> (default: 127.0.0.1)
 -rpcport=<port> Connect to JSON-RPC on <port> 
 -rpcwait Wait for RPC server to start
 -rpcuser=<user> Username for JSON-RPC connections
 -rpcpassword=<pw> Password for JSON-RPC connections

SSL options: 
 -rpcssl Use OpenSSL (https) for JSON-RPC connections

 

Step 1: Configure Multichain on node 1

The first step consists in defining your blockchain name. In this post, we will create a blockchain called “myblockchain”. As you will see later, the blockchain name is used on every command. Why? As I told you at the beginning of the post, Multichain is able to manage multiple blockchains on a single machine. For this reason, when you use the multichain tools (like multichain-cli), you must specify the blockchain on which you want to execute the command by adding the blockchain name as the first argument of the command.

On node 1, enter the command:

multichain-util create myblockchain

The result is:

MultiChain utilities build 1.0 alpha 28 protocol 10007

Blockchain parameter set was successfully generated.
You can edit it in /home/ubuntu/.multichain/myblockchain/params.dat before running multichaind for the first time.

To generate blockchain please run "multichaind myblockchain -daemon".

Before starting the blockchain, we have to edit the config file as stated (see just above) as the result of the previous command. In my case, the config file is located at: /home/ubuntu/.multichain/myblockchain/params.dat.

You find and change the following lines:

chain-description = my private blockchain
anyone-can-connect = true
initial-block-reward = 5000000
minimum-relay-fee = 1000

The chain-description is just used as a display description of the chain. This description will be available to any node connecting to the blockchain.

The anyone-can-connect = true gives anyone the permission to connect to the blockchain. The connect permission does not give any other permission unless explicitly declared on the blockchain.

The initial-block-reward = 5000000 is the “reward” given to the nodes which mined a new block. The value 5000000 gives a 0.05 unit in the blockchain crypto currency.

The minimum-relay-fee = 1000 is the minimum transaction fee.

 

Step 2: Start Multichain on node 1

Don’t forget to use the blockchain name you defined.

On node 1, enter the command:

 multichaind myblockchain -daemon 

The result is:

MultiChain Core Daemon build 1.0 alpha 28 protocol 10007

MultiChain server starting
Looking for genesis block...
Genesis block found

Other nodes can connect to this node using:
multichaind myblockchain@10.0.0.5:6717

Node started

Congrats! Your private blockchain is on the way! Let’s now see what’s happening behind the scene.

On node 1, enter the command:

 multichain-cli myblockchain getinfo 

The result is:

 {"method":"getinfo","params":[],"id":1,"chain_name":"myblockchain"} 

{
  "version" : "1.0 alpha 28",
  "nodeversion" : 10000128,
  "protocolversion" : 10007,
  "chainname" : "myblockchain",
  "description" : "my private blockChain",
  "protocol" : "multichain",
  "port" : 6717,
  "setupblocks" : 60,
  "nodeaddress" : "myblockchain@10.0.0.5:6717",
  "burnaddress" : "1XXXXXXXQXXXXXXXncXXXXXXZCXXXXXXdAqsaA",
  "incomingpaused" : false,
  "miningpaused" : false,
  "walletversion" : 60000,
  "balance" : 0.20000000,
  "walletdbversion" : 2,
  "reindex" : false,
  "blocks" : 5,
  "timeoffset" : 0,
  "connections" : 0,
  "proxy" : "",
  "difficulty" : 0.00000006,
  "testnet" : false,
  "keypoololdest" : 1488712880,
  "keypoolsize" : 2,
  "paytxfee" : 0.00000000,
  "relayfee" : 0.00001000,
  "errors" : ""
}

As we can see in this “getinfo” result, the current balance of the node is 0.2 which means that the node has started to mine. There is a strict relation between the number of blocks currently available and the balance. As we have put the “initial-block-reward” value to 5000000 (which means 0.05 in the crypto currency units) and we have actually 5 blocks (the first one is mined for free by the master node), we have 4 blocks mined. The balance is 4 * 0.05 => 0.2 crypto currency unit.

 

Step 3: Start the second node

We are starting a second node because a blockchain does not rely on a single node by design (beyond the fact that you need multiple nodes for availability best practices reasons).

The principle at the heart of a blockchain is to distribute the chain of blocks around a big number of nodes. The reliability of a blockchain is directly linked to the number of nodes available in the chain because a successful attack should take control of more than half of the nodes to be successful.

On node 2, enter the command:

(retrieve the exact command corresponding to your implementation on Step 2 and add ” -daemon”)

multichaind myblockchain@10.0.0.5:6717 -daemon

The result is:

MultiChain Core Daemon build 1.0 alpha 28 protocol 10007

MultiChain server starting
Retrieving blockchain parameters from the seed node 10.0.0.5:6717 ...
Other nodes can connect to this node using:
multichaind myblockchain@10.0.0.250:6717

Node started

Let’s get the info from this new node.

On node 2, enter the command:

multichain-cli myblockchain getinfo

The result is:

{"method":"getinfo","params":[],"id":1,"chain_name":"myblockchain"}

{
"version" : "1.0 alpha 28",
"nodeversion" : 10000128,
"protocolversion" : 10007,
"chainname" : "myblockchain",
"description" : "my private blockChain",
"protocol" : "multichain",
"port" : 6717,
"setupblocks" : 60,
"nodeaddress" : "myblockchain@10.0.0.250:6717",
"burnaddress" : "1XXXXXXXQXXXXXXXncXXXXXXZCXXXXXXdAqsaA",
"incomingpaused" : false,
"miningpaused" : false,
"walletversion" : 60000,
"balance" : 0.00000000,
"walletdbversion" : 2,
"reindex" : false,
"blocks" : 62,
"timeoffset" : 0,
"connections" : 1,
"proxy" : "",
"difficulty" : 0.00000006,
"testnet" : false,
"keypoololdest" : 1488713050,
"keypoolsize" : 2,
"paytxfee" : 0.00000000,
"relayfee" : 0.00001000,
"errors" : ""
}

As you can see in the result of the “getinfo”, the chain name is “myblockchain” as defined on node 1, which means that you are connected to the same blockchain.

 

Step 4: Give permissions to the second node.

If you look at the balance info of node 2, value is still 0 and it doesn’t change even if you wait, and wait and wait. Why? Just remember, when we configured the blockchain parameters on node 1, we put the setting “anyone-can-connect” to “true” which gives anyone the permission to connect to the blockchain but does not give any other permission, and that’s why node 2 can not mine. Before giving this permission to node 2 (and adding “send” and “receive” permissions too), we need to know its address.

On node 2, enter the command:

multichain-cli myblockchain getaddressesbyaccount ""

The result is:

{"method":"getaddressesbyaccount","params":[""],"id":1,"chain_name":"myblockchain"}

[
"1HeqmyJLGDEhme4yMbdURVZazcvyCuzDRqGQ1w"
]

In this case the node 2 address is 1HeqmyJLGDEhme4yMbdURVZazcvyCuzDRqGQ1w

On node 1, enter the command:

multichain-cli myblockchain grant 1HeqmyJLGDEhme4yMbdURVZazcvyCuzDRqGQ1w connect,send,receive,mine

The result is:

{"method":"grant","params":["1HeqmyJLGDEhme4yMbdURVZazcvyCuzDRqGQ1w","connect,send,receive,mine"],"id":1,"chain_name":"myblockchain"}

02274cdb202e574b67df2757f327f5747c167911d2c9b0fa9976bf2677e61cde

Now we can see that node 2 has started to mine.

On node 2, enter the command:

multichain-cli myblockchain getinfo

The result is:

{"method":"getinfo","params":[],"id":1,"chain_name":"myblockchain"}

{
"version" : "1.0 alpha 28",
"nodeversion" : 10000128,
"protocolversion" : 10007,
"chainname" : "myblockchain",
"description" : "my private blockChain",
"protocol" : "multichain",
"port" : 6717,
"setupblocks" : 60,
"nodeaddress" : "myblockchain@10.0.0.250:6717",
"burnaddress" : "1XXXXXXXQXXXXXXXncXXXXXXZCXXXXXXdAqsaA",
"incomingpaused" : false,
"miningpaused" : false,
"walletversion" : 60000,
"balance" : 0.05000000,
"walletdbversion" : 2,
"reindex" : false,
"blocks" : 73,
"timeoffset" : 0,
"connections" : 1,
"proxy" : "",
"difficulty" : 0.00000006,
"testnet" : false,
"keypoololdest" : 1488713050,
"keypoolsize" : 2,
"paytxfee" : 0.00000000,
"relayfee" : 0.00001000,
"errors" : ""
}

The balance of node 2 has started to increase.

 

Step 5: Send crypto currency from node 1 to node 2.

First, check the balance on node 1

On node 1, enter the command:

multichain-cli myblockchain getinfo


The result is:

{"method":"getinfo","params":[],"id":1,"chain_name":"myblockchain"}

{
 "version" : "1.0 alpha 28",
 "nodeversion" : 10000128,
 "protocolversion" : 10007,
 "chainname" : "myblockchain",
 "description" : "my private blockChain",
 "protocol" : "multichain",
 "port" : 6717,
 "setupblocks" : 60,
 "nodeaddress" : "myblockchain@10.0.0.5:6717",
 "burnaddress" : "1XXXXXXXQXXXXXXXncXXXXXXZCXXXXXXdAqsaA",
 "incomingpaused" : false,
 "miningpaused" : false,
 "walletversion" : 60000,
 "balance" : 3.55000000,
 "walletdbversion" : 2,
 "reindex" : false,
 "blocks" : 73,
 "timeoffset" : 0,
 "connections" : 1,
 "proxy" : "",
 "difficulty" : 0.00000006,
 "testnet" : false,
 "keypoololdest" : 1488712880,
 "keypoolsize" : 2,
 "paytxfee" : 0.00000000,
 "relayfee" : 0.00001000,
 "errors" : ""
}

 

The current balance for node 1 is 3.55 crypto currency units.
Remember on Step 4, we found  the address of node 2 is 1HeqmyJLGDEhme4yMbdURVZazcvyCuzDRqGQ1w.

Let’s send 2 crypto currency units from node 1 to node 2.

On node 1, enter the command:

multichain-cli myblockchain sendtoaddress 1HeqmyJLGDEhme4yMbdURVZazcvyCuzDRqGQ1w 2

The result is:

 {"method":"sendtoaddress","params":["1HeqmyJLGDEhme4yMbdURVZazcvyCuzDRqGQ1w",2],"id":1,"chain_name":"myblockchain"} aad0a680c65e24d2127d0e574ce29b972c794841a5d5154e435ee597e093cc83 

If you immediately check the balance on node 2, you will not find the added amount of crypto currency. This is because a transaction is only valid when at least confirmed by more than half of the nodes. Before the transaction is confirmed by enough nodes, the amount is in the unconfirmed balance.

On node 2 enter the command:

multichain-cli myblockchain getunconfirmedbalance


The result is:

{"method":"getunconfirmedbalance","params":[],"id":1,"chain_name":"myblockchain"}

2.00000000

After a few seconds, you should find the amount added to your balance.

On node 2 enter the command:

multichain-cli myblockchain getinfo

The result is:

{"method":"getinfo","params":[],"id":1,"chain_name":"myblockchain"}

{
"version" : "1.0 alpha 28",
"nodeversion" : 10000128,
"protocolversion" : 10007,
"chainname" : "myblockchain",
"description" : "my private blockChain",
"protocol" : "multichain",
"port" : 6717,
"setupblocks" : 60,
"nodeaddress" : "myblockchain@10.0.0.250:6717",
"burnaddress" : "1XXXXXXXQXXXXXXXncXXXXXXZCXXXXXXdAqsaA",
"incomingpaused" : false,
"miningpaused" : false,
"walletversion" : 60000,
"balance" : 2.05000000,
"walletdbversion" : 2,
"reindex" : false,
"blocks" : 74,
"timeoffset" : 0,
"connections" : 1,
"proxy" : "",
"difficulty" : 0.00000006,
"testnet" : false,
"keypoololdest" : 1488713050,
"keypoolsize" : 2,
"paytxfee" : 0.00000000,
"relayfee" : 0.00001000,
"errors" : ""
}

The balance of node 2 has received the 2 crypto currency units.

 

Step 6: How to check that the transaction is done

A blockchain gives you the ability to check any transaction done. If we go back to step 5 on the “sendtoaddress” command, in the result we found the hash of the transaction is aad0a680c65e24d2127d0e574ce29b972c794841a5d5154e435ee597e093cc83.

On node 1, enter the command:

multichain-cli myblockchain gettransaction aad0a680c65e24d2127d0e574ce29b972c794841a5d5154e435ee597e093cc83

The result is:

{"method":"gettransaction","params":["aad0a680c65e24d2127d0e574ce29b972c794841a5d5154e435ee597e093cc83"],"id":1,"chain_name":"myblockchain"}

{
 "amount" : -2.00000000,
 "fee" : -0.00000225,
 "confirmations" : 11,
 "blockhash" : "00b2343b7ed2f8dac945b52af84bc22a82ae7fc018de81249c32bcc20abf7a54",
 "blockindex" : 1,
 "blocktime" : 1488722613,
 "txid" : "aad0a680c65e24d2127d0e574ce29b972c794841a5d5154e435ee597e093cc83",
 "walletconflicts" : [
 ],
 "valid" : true,
 "time" : 1488722594,
 "timereceived" : 1488722594,
 "details" : [
 {
 "account" : "",
 "address" : "1HeqmyJLGDEhme4yMbdURVZazcvyCuzDRqGQ1w",
 "category" : "send",
 "amount" : -2.00000000,
 "vout" : 0,
 "fee" : -0.00000225
 }
 ],
 "hex" : "0100000001de1ce67726bf7699fab0c9d21179167c74f527f35727df674b572e20db4c2702010000006a4730440220756346c0850a1499b8739f90140002f2d3e2cd1b16e8f9f194a05cd0e09b86e402204d37e38a0dcdddbd740855abf86161f331e98a016bf4c6aa28e94497f4d5c7e4012102c69baee94470218d88b9f8086bcf2b78df83cbbf1dd3d557d11a3b0bba5970c6ffffffff0200c2eb0b000000001976a9147b35c8cdb229272f13b559230fa7a41c1ca5f2af88ac7ed1fa02000000001976a914a993bda4c573bcb1dcf76388f3fc373ec249de5888ac00000000"
}

This command gives you some details of the transaction.
You can see that the transaction is stored on block 1, the time of the transaction request and the time when the receiver received it.
If you need full transaction detail, use the last key/value of the answer where the key is “hex”.

On node 1, enter the command:

multichain-cli myblockchain decoderawtransaction 0100000001de1ce67726bf7699fab0c9d21179167c74f527f35727df674b572e20db4c2702010000006a4730440220756346c0850a1499b8739f90140002f2d3e2cd1b16e8f9f194a05cd0e09b86e402204d37e38a0dcdddbd740855abf86161f331e98a016bf4c6aa28e94497f4d5c7e4012102c69baee94470218d88b9f8086bcf2b78df83cbbf1dd3d557d11a3b0bba5970c6ffffffff0200c2eb0b000000001976a9147b35c8cdb229272f13b559230fa7a41c1ca5f2af88ac7ed1fa02000000001976a914a993bda4c573bcb1dcf76388f3fc373ec249de5888ac00000000


The result is:

{"method":"decoderawtransaction","params":["0100000001de1ce67726bf7699fab0c9d21179167c74f527f35727df674b572e20db4c2702010000006a4730440220756346c0850a1499b8739f90140002f2d3e2cd1b16e8f9f194a05cd0e09b86e402204d37e38a0dcdddbd740855abf86161f331e98a016bf4c6aa28e94497f4d5c7e4012102c69baee94470218d88b9f8086bcf2b78df83cbbf1dd3d557d11a3b0bba5970c6ffffffff0200c2eb0b000000001976a9147b35c8cdb229272f13b559230fa7a41c1ca5f2af88ac7ed1fa02000000001976a914a993bda4c573bcb1dcf76388f3fc373ec249de5888ac00000000"],"id":1,"chain_name":"myblockchain"}

{
 "txid" : "aad0a680c65e24d2127d0e574ce29b972c794841a5d5154e435ee597e093cc83",
 "version" : 1,
 "locktime" : 0,
 "vin" : [
 {
 "txid" : "02274cdb202e574b67df2757f327f5747c167911d2c9b0fa9976bf2677e61cde",
 "vout" : 1,
 "scriptSig" : {
 "asm" : "30440220756346c0850a1499b8739f90140002f2d3e2cd1b16e8f9f194a05cd0e09b86e402204d37e38a0dcdddbd740855abf86161f331e98a016bf4c6aa28e94497f4d5c7e401 02c69baee94470218d88b9f8086bcf2b78df83cbbf1dd3d557d11a3b0bba5970c6",
 "hex" : "4730440220756346c0850a1499b8739f90140002f2d3e2cd1b16e8f9f194a05cd0e09b86e402204d37e38a0dcdddbd740855abf86161f331e98a016bf4c6aa28e94497f4d5c7e4012102c69baee94470218d88b9f8086bcf2b78df83cbbf1dd3d557d11a3b0bba5970c6"
 },
 "sequence" : 4294967295
 }
 ],
 "vout" : [
 {
 "value" : 2.00000000,
 "n" : 0,
 "scriptPubKey" : {
 "asm" : "OP_DUP OP_HASH160 7b35c8cdb229272f13b559230fa7a41c1ca5f2af OP_EQUALVERIFY OP_CHECKSIG",
 "hex" : "76a9147b35c8cdb229272f13b559230fa7a41c1ca5f2af88ac",
 "reqSigs" : 1,
 "type" : "pubkeyhash",
 "addresses" : [
 "1HeqmyJLGDEhme4yMbdURVZazcvyCuzDRqGQ1w"
 ]
 },
 "assets" : [
 ],
 "permissions" : [
 ],
 "items" : [
 ]
 },
 {
 "value" : 0.49992062,
 "n" : 1,
 "scriptPubKey" : {
 "asm" : "OP_DUP OP_HASH160 a993bda4c573bcb1dcf76388f3fc373ec249de58 OP_EQUALVERIFY OP_CHECKSIG",
 "hex" : "76a914a993bda4c573bcb1dcf76388f3fc373ec249de5888ac",
 "reqSigs" : 1,
 "type" : "pubkeyhash",
 "addresses" : [
 "1PvK2oRRrAE8WZWiDeiQffvNfQciCeHcM3vHGZ"
 ]
 },
 "assets" : [
 ],
 "permissions" : [
 ],
 "items" : [
 ]
 }
 ],
 "data" : [
 ]
}

You can find in the first part of the “vout” value, the transaction on the sender level, and on the second part of the “vout” value, the transaction at the receiver level.

Conclusion

I hope that this post has helped you to understand how to start setting up your own private blockchain and that you feel more confident to go a step further and store your own data/transaction on your blockchain.