Blockchain is a distributed database used to maintain a growing list of records called blocks.
Each block has a timestamp and its own hashed identifier. It holds the hash to its predecessor and successor to create the chain. The last block in the chain, of course, has no successor hash code and there allows us to easily identify where to chain the next block. A blockchain is decentralized and distributed, meaning that all parties have their own copy and can verify that the chain has not been corrupted. This mechanism can be used to prevent internal modification that could happen in a centralized system. Blockchains can be used for, amongst others, financial ledgers, medical records and identity management. Last year Moody’s identified 25 potential use cases for blockchains.
So where does Cloud Spanner come into play? Cloud Spanner is Google’s own distributed relational database. Unlike conventional databases, it scales horizontally and not vertically. To ensure Availability, Cloud Spanner replicates data during its two-phase commit across several cloud zones. Cloud Spanner theoretically provides both Consistency and Availability whereas others distributed database systems must choose between Availability and Partitions or Consistency and Partitions. Google’s networks are both private and redundant meaning that a partition is highly unlikely. However in the eventuality of a network partition, Cloud Spanner will place Consistency above Availability. We therefore have our first criteria for the blockchain, a decentralized distributed database. The second criteria is TrueTime. In order to sequence transactions during the 2PC, Spanner uses atomic clocks that are found in Google data centers. Blockchain transactions are therefore guaranteed to be sequential and in chronological order. The third criteria is Spanner’s pessimistic transaction locking will guarantee that only one block is added to the end of the chain at any one time, regardless of the geographical location. For those who wish to have a copy of the blockchain, Cloud Spanner provides read-only snapshots where a read is done in the past.
We wrote a Go program of around 200 lines that put these principles into action. In this application, blocks are chained both to the previous and next blocks.
The code for the application that runs on AppEngine can be found here.
First we create a Cloud Spanner instance
gcloud spanner instances create test-instance --config=regional-us-central1 --description="My Instance" --nodes=1
Next we deploy the application on AppEngine
gcloud app deploy --version <version>
Now we create the database that will be used to store the blockchain. This command creates the database example-db and the table BLOCKS
curl https://AppID.appspot.com/create
This will execute the following code:
op, err := adminClient.CreateDatabase(ctx, &adminpb.CreateDatabaseRequest{ Parent: matches[1], CreateStatement: "CREATE DATABASE `" + matches[2] + "`", ExtraStatements: []string{ `CREATE TABLE Blocks ( BlockId INT64 NOT NULL, Message STRING(1024), MyHash STRING(1024), HashBefore STRING(1024), HashAfter STRING(1024) ) PRIMARY KEY (BlockId)`, }, })
As you can see, creating a database and a table is very straight forward.
You can select the first block from the chain:
gcloud spanner databases execute-sql example-db --instance=test-instance --sql='select * from BLOCKS'
Add new blocks to the chain using the following command:
curl https://AppId.appspot.com/write?message=<yourNewBlockMessage>
This will execute the following code:
_, err := client.ReadWriteTransaction(ctx, func(txn *spanner.ReadWriteTransaction) error { lastBlock, errFind := findLastBlock(txn, ctx) <CREATE_NEW_BLOCK/> <UPDATE_BLOCK_BEFORE/> txn.BufferWrite([]*spanner.Mutation{ spanner.InsertOrUpdate("Blocks", <BLOCK_BEFORE>), spanner.InsertOrUpdate("Blocks", <NEW_BLOCK>), }) return nil })
The program starts a read-write transaction. It fetches the last block in the chain (the one that doesn’t have a HashAfter code). A new MyHash is created from the new block Id and the VM timestamp. It then updates previous last block’s HashAfter to point to the new block’s MyHash code and points the new block’s HashBefore to the previous end block’s MyHash
We select the new lines that have been inserted and see that the blocks are chained to both the previous and next blocks.
gcloud spanner databases execute-sql example-db --instance=test-instance --sql='select * from BLOCKS'
We can stress the solution using Apache Benchmark (AB). First install AB.
sudo apt-get update sudo apt-get install apache2-utils
Launch AB to stress the solution with 5000 requests and 100 parallel threads.
ab -n 5000 -c 100 -v 1 https://AppId.appspot.com/ write?message=hello
List the blocks and check that they are correctly chained.
gcloud spanner databases execute-sql example-db --instance=test-instance --sql='select * from BLOCKS'
Before you finish, don’t forget to delete your Spanner instance.
gcloud spanner instances delete test-instance
Cloud Spanner is an exciting evolution in terms of relational databases. It is globally distributed and replicated and it scales horizontally, a first in the relational world. As it respects ACID transactions, has pessimistic locking and is both consistent and available, it allows us to implement complicated solutions such as blockchains far more easily than in the past.
The post Blockchain and Cloud Spanner: how does it work? appeared first on SFEIR Mag.