Building a Blockchain: Executing Smart Contracts

Angel Java Lopez
2 min readNov 25, 2020

I’m very proud of my favorite personal project BlockchainJ: build a Blockchain in Java, from scratch, using TDD (Test-Driven Development). Previous posts:

Building a Blockchain: Introduction
Building a Blockchain: Main Entities
Building a Blockchain: Serialization
Building a Blockchain: Key Value Stores
Building a Blockchain: Subroutines in the Virtual Machine
Building a Blockchain: Towards Beam Synchronization

It’s based in Ethereum, so it supports smart contracts. I’m using the same bytecodes, to keep compability with the ecosystem (like Solidity compilers and wallets).

Today, I want to describe my current implementation of how to execute an smart contract in the VirtualMachine.java class. A diagram:

Instances provided to Virtual Machine to execute smart contract code

The left classes are injected at constructor time. The right classes are injected when I want to execute the code. Using TDD, I could change the design at any moment, without pain. Really, I changed this design in the last week, without much effort. The instances injected at constructor time are:

BlockData.java: having the information of the current block under execution, like number, difficulty, chain id (yes, I added chain id to the block header)

MessageData.java: it has the information about the current call: sender address, origin (original transaction sender) address, receiver address (usually the current smart contract under execution), gas limit, gas price, etc. Maybe I could split this data in two: TransactionData, and MessageData. The first one would be inmutable ALONG the execution of the smart contract and its internal call. Remember: an smart contract could INVOKE ANOTHER smart contract, and again, having many levels of invocations. This instance is inmutable during the invocation of the current code under process.

ExecutionContext.java: an interface that allows the access and update of the world state: accounts and contract storages. The important thing to take into account: after execution of the code, its changes could be commited or rollbacked, depending on the success or failure of the execution (ie a revert should raise a rollback, so the world state is not changed; but only a rollback of this level: an smart contract A could call smart contract B, then B reverts, then the changes OF B (ONLY B) are rollbacked; then the smart contract A could decide to bubble up the revert or not).

At execution time I provide to the virtual machine two instances:

Storage.java: the current smart contract storage (a minor but critical detail: it should be provided by the current execution context, to live under the umbrella of rollback or commit; this coupling says to me something: I could review this design later, TDD rules!)

Code: a byte array with the bytecodes

At the end, the execution returns an ExecutionResult.java with information about the success or failure of the execution, error message, etc.

Keep tuned!

Angel “Java” Lopez

--

--