Blockchain and Cloud Spanner: how does it work?

Blockchain and cloud spanner

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' 

Blockchain fig1

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' 

Blockchain fig2

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' 

Blockchain fig3

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.

Vous aimerez aussi...