Persist data to the Ethereum blockchain using Python, Truffle, and Ganache
The previous post demonstrated how to write a simple smart contract with Solidity and deploy it to the Ethereum Blockchain. This tutorial will show how to update the contract to save some data in the blockchain as well as how to inspect the blockchain to see our transactions.
We'll work on the same files from the previous tutorial, which can be found here.
If not in the mood of going along with the tutorial, the finished code is available here.
TOC
1. Project setup
Open HelloWorld.sol
and add the following:
pragma solidity >= 0.5.0;
contract HelloWorld {
+ string public payload;
+
+ function setPayload(string memory content) public {
+ payload = content;
+ }
+
function sayHello() public pure returns (string memory) {
return 'Hello World!';
}
}
As we did before, spin up truffle
local blockchain with truffle develop
CLI:
$ truffle develop
Truffle Develop started at http://127.0.0.1:9545/
Accounts:
(0) 0x55660bb0918f9aade4db7b7ef7f71639750c2262
...
Private Keys:
(0) ead0d6b318832f278b9a2ee1a6a6ab0156ab439d898394b6887d023bc929159c
...
$ truffle(develop)>
Now, we need to update our contract, what under Truffle's Suite is performed with the migrate command. Write migrate
within Truffle's console.
Compiling your contracts...
===========================
> Compiling ./contracts/HelloWorld.sol
> Compiling ./contracts/Migrations.sol
...
2_deploy_contracts.js
=====================
Replacing 'HelloWorld'
----------------------
> transaction hash: 0x6f55fc4a165225c6911d6e0acda8b4ec75b0962370eab66ab94aefd0e0cfd084
> Blocks: 0 Seconds: 0
> contract address: 0x85534E0ec31b63d635CcBa1fb6b953a9C47a9022
...
The contract is now updated with a public method setPayload
deployed at 0x85534E0ec31b63d635CcBa1fb6b953a9C47a9022
(contract address). Write this address somewhere else, we will need it soon.
We can verify that the contract was properly updated by fetching the contract instance and checking for setPayload
method existence, as well as the value of payload
variable:
# We're still inside Truffle's console
$ truffle(develop)> let instance = await HelloWorld.deployed()
$ truffle(develop)> instance.setPayload
[Function] {
call: [Function],
sendTransaction: [Function],
estimateGas: [Function],
request: [Function]
}
$ truffle(develop)> instance.payload.call()
'' # Empty, as expected!
2. Executing a transaction
When we call
a function that only returns a value, such as sayHello
, the blockchain state is not altered. Since now we want to save a value to the blockchain, its state must be altered and it is done via a transaction
execution.
We want to execute this transaction from our Python
script, the same we used for calling the sayHello
method in the previous post.
Add the following to the bottom of app.py
:
# executes setPayload function
tx_hash = contract.functions.setPayload('abc').transact()
# waits for the specified transaction (tx_hash) to be confirmed
# (included in a mined block)
tx_receipt = web3.eth.waitForTransactionReceipt(tx_hash)
print('tx_hash: {}'.format(tx_hash.hex()))
Also, update the deployed_contract_address
in app.py
with the new contract address (output from migrate
). If you don't remember it, go back to the Truffle console and call instance.address
.
On another terminal session, execute our Python script:
python app.py
Hello World!
tx_hash: 0x2b7bf989fd0fc692d0ef976b3293c39958ab7de64a08a3f66c0d758b871ad8e6
Not fun, right? How do we know that the data was persisted? Go back to the Truffle console and call payload
variable:
$ truffle(develop)> instance.payload.call()
'abc' # cool! It changed!
This means that our transaction was mined, thus being added to a block that was successfully added to the blockchain.
3. Inspecting the blockchain with Ganache
There are various ways for inspecting the blockchain. For example, using the Truffle console:
# Fetch blockchain's latest mined block
$ truffle(develop)> block = await web3.eth.getBlock("latest")
$ truffle(develop)> block
{
number: 6, # YMMV
(...)
transactions: [
'0x2b7bf989fd0fc692d0ef976b3293c39958ab7de64a08a3f66c0d758b871ad8e6'
]
}
transactions
lists all the transactions that were added to this block. In this case, there is one transaction that should match tx_hash
that was printed when we ran app.py
.
To make our lives easier, there is a GUI tool for inspecting the blockchain and its transactions: Ganache. As per their website:
Quickly fire up a personal Ethereum blockchain which you can use to run tests, execute commands, and inspect state while controlling how the chain operates.
After successfully installing and opening it, you should see the following image:
Select "Quickstart" and you'll be welcomed with a screen listing some accounts and its respective addresses (very similar to how truffle develop
works). There will be also a RPC Server
address, such as http://127.0.0.1:8545
, write that down. Click "Save" (top-right corner) so this Ganache workspace is persisted.
When quick-starting Ganache, it created another local blockchain for us. We can now tell truffle
to use Ganache's blockchain (which has a nice UI). To do so, open truffle-config.js
and replace it with the following:
module.exports = {
networks: {
development: {
// host and port should match the RPC Server address
// as seen in Ganache
host: "127.0.0.1",
port: 8545,
network_id: "*"
}
}
};
Go to the Contracts tab, and select Link Truffle Projects
. Click Add Project
then select the truffle-config.js
file from hello-eth/
root project folder. Click Save and Restart
at the upper-right corner.
If you go to the Contracts tab now, you should see two contracts:
- HelloWorld: Not Deployed
- Migrations: Not Deployed
Open another terminal session, go to the project root level (where truffle-config.js
is located), and type truffle migrate
. It will deploy our contracts to Ganache's blockchain. Copy the HelloWorld
contract address and update the deployed_contract_address
in app.py
with its new value, as well as the variable blockchain_address
with http://127.0.0.1:8545
.
- blockchain_address = 'http://127.0.0.1:9545' # truffle blockchain
+ blockchain_address = 'http://127.0.0.1:8545' # ganache blockchain
- deployed_contract_address = '0x85534E0ec31b63d635CcBa1fb6b953a9C47a9022'
+ deployed_contract_address = '0x433D7E91B659CB4f1bbBb8dacd2B1cBBa7F82F1A'
Under Contracts tab now, both contracts (HelloWorld
and Migrations
) should have an address. It means they're deployed! woohoo!
Now, run app.py
again to execute a new transaction on our newest blockchain and then click on HelloWorld
contract:
Notice the TX HASH
, it should be the same as printed when you ran app.py
.
And if you click on the transaction itself: You can see both the function that was called and the inputs.
Run app.py
a few more times, change abc
(in tx_hash = contract.functions.setPayload('abc').transact()
) to something else, then inspect your contract again. It's YOUR blockchain now, act up to it!
Wrapping up
In this tutorial, you learned how to:
- Write a method that changes the blockchain state;
- Use Truffle CLI to interact with a deployed smart contract;
- Use Ganache app both as the blockchain provider as well as its inspector;