Installing Go-Ethereum and Associated Developer Tools

First off, we need to install the Go bindings for the Ethereum protocol. Assuming you have Go installed and have GOPATH environment variable set appropriately, you can get bindings via:

$ go get -d github.com/ethereum/go-ethereum

Once we have the source code checked out, then we can go ahead and build geth (Geth is the main command line tool for running a full Go based implementation of an Ethereum node) along with all the developer tools:

$ cd $GOPATH/src/ github.com/ethereum

$ go install ./...

Setup Project Structure

We will write and deploy a simple Inbox contract. To do so, lets begin by setting up the following directory and file structure:

# Navigate to your Go src directory. Mine looks like:

# $GOPATH/src/ github.com/sabbas $ cd $GOPATH/src/ github.com/sabbas

$ mkdir -p inbox/contracts

$ touch contracts/inbox_test.go fetch.go update.go deploy.go $ tree inbox/

inbox/

├── contracts

│ └── inbox_test.go

├── deploy.go

├── fetch.go

└── update.go

We create a new project folder called inbox. Within this folder, we create a package folder called contracts. This folder will contain the Solidity code for our inbox contract along with its associated Go bindings (which we will be generating soon). Within the contracts package folder, we also have an inbox_test.go file. This file will contain all our tests. There are three additional files named deploy.go, fetch.go and update.go. We will use these additional files to write code to deploy and interact with an Ethereum contract on a public network. These files can be empty for now.

Creating a Simple Ethereum Contract

We are now ready to write some Solidity code for our Inbox contract. Navigate to the inbox/contracts folder and create a file with the name Inbox.sol.

$ tree inbox/

inbox/

└── contracts

└── Inbox.sol

Edit the inbox.sol file and add the following lines of Solidity code for our Inbox contract:

pragma solidity ^0.4.17;



contract Inbox {



string public message;



function Inbox(string initialMessage) public {

message = initialMessage;

}



function setMessage(string newMessage) public {

message = newMessage;

}

}

The Inbox contract is pretty straight forward. It has one public data variable called message which holds the contents of the most recent message string. The contract also defines a public setMessage method which updates the contents of the message data variable.

Using the Ethereum Contract from Go

Now that we our Inbox contract defined in Solidity, we would like to able to use this contract from within our Go application. To be more specific, we would like to have the ability to deploy this contract onto an Ethereum network and interact with it conveniently from within our Go application. Go-Ethereum makes this pretty simple by providing a code generator tool which can transform a Solidity contract file into a type-safe go package which we can import and use directly from within our Go application. This tool is called abigen and it was built and installed during our go-ethereum setup above. To use abigen, navigate to the inbox/contracts folder and execute:

$ abigen -sol inbox.sol -pkg contracts -out inbox.go $ tree inbox

inbox

└── contracts

├── Inbox.sol

└── inbox.go

We pass the name of the Solidity contract file we want to generate the Go package for to the sol command line argument. We also specify the Go package name and the output file name to the pkg and out command line arguments. Running abigen produces the inbox.go package file containing the Go bindings for the Inbox Solidity contract. Once we have these bindings, we are ready to begin testing the Inbox contract.

Testing the Ethereum Contract before Deploying to a Public Network

Before we deploy our contract to a public Ethereum network, we want to ensure that it is working as expected. In the case of the Inbox contract, we want to test that we can deploy the contract with an initial message, retrieve this initial message and update its value later on. Go-Ethereum provides a nice utility for a blockchain simulator which is extremely helpful with automated unit testing. In the code snippets that follow, we will see how to use the blockchain simulator utility to test the Inbox contract.

The TestDeployInbox method starts off by invoking crypto.GenerateKey to generate a private key. This key is used to create a transaction signer function used for authorizing transactions in the simulated blockchain. The transaction signer function along with an address which we can use to make transactions from is generated via a call to bind.NewKeyedTransactor. This address is then used to create a genesis block containing a single account with some initial balance (via calls to make(core.GenesisAlloc and core.GenesisAccount ). This genesis block is then used to seed the simulated blockchain. Finally, we “mine” the next block by explicitly committing all pending transactions and checking if the Inbox contract was deployed at a valid address.

We can navigate to inbox\contracts and execute go test to ensure that our deployment test passes

$ go test -v

=== RUN TestDeployInbox

--- PASS: TestDeployInbox (0.01s)

PASS

ok github.com/sabbas/inbox/contracts 0.042s

Next, we want to test that when we deploy the Inbox contract, it gets deployed with the correct initial message.

Similar to the TestDeployInbox function, the TestGetMessage function kicks off by setting up our simulated blockchain (the simulated block chain function can be refactored out into a separate re-usable function. I have avoided that here just to help with readability a bit). It then invokes the DeployInbox function created as part of the auto generated Go bindings for our Inbox Solidity contract. Note that the DeployInbox function returns a pointer to the instance of the deployed Inbox contract as the third return value. We can use this pointer to interact with our deployed Inbox contract(super cool!). And this is exactly what the test does to query and check the initial message stored in the instance of the inbox contract we just deployed.

We can navigate to inbox\contracts and execute go test to ensure that our tests pass

$ go test -v

=== RUN TestDeployInbox

--- PASS: TestDeployInbox (0.01s)

=== RUN TestGetMessage

--- PASS: TestGetMessage (0.00s)

PASS

ok github.com/sabbas/inbox/contracts 0.045s

Finally, we want to test that we can update the message data property in the deployed Inbox contract to a new value.

The TestSetMessage function begins with the same boiler plate code we saw earlier to setup a simulated blockchain and deploy the Inbox contract. As we saw before , a successful invocation of the DeployInbox function call returns a pointer to the instance of the deployed Inbox contract as the third return value. In the TestSetMessage function, we use this contract pointer to update the message data property of the Inbox contract by calling the SetMessage function. Since the SetMessage function modifies the Inbox contract, it actually generates a new transaction. As a result, we pass in a pointer to a TrasactOpts struct populated with the transaction authorization data. Since we dont need to send any funds along with the SetMessage invocation, we set the Value property of the TransactOpts struct to nil.

We can navigate to inbox\contracts and run go test one more time to ensure all is good.

$ go test -v

=== RUN TestDeployInbox

--- PASS: TestDeployInbox (0.01s)

=== RUN TestGetMessage

--- PASS: TestGetMessage (0.00s)

=== RUN TestSetMessage

--- PASS: TestSetMessage (0.01s)

PASS

ok github.com/sabbas/inbox/contracts 0.051s

Once our local tests are passing, our Inbox contract is ready for prime time. In the next section we will take a look at how we can take our Inbox contract and deploy it on a public Ethereum network.