This project is divided in two parts: a byzantine consensus implementation, and a blockchain service.
There is also a client library that submits requests to the service for consensus and execution in the blockchain. For testing purposes, we developed a small TUI application using the blockchain library with some functionalities.
This README explains how to compile, test, and execute, and presents a small demo of the project.
The source of the solidity contracts are stored in blockchain/src/solidity/contracts
. If you want to compile the contracts into bytecode you can run:
mvn -pl blockchain web3j:generate-sources
The resulting bytecode will be stored at blockchain/target/generated-sources/solidity
.
Note 0: In addition to the IST Coin/Blacklist contract, we also created a contract that only keeps track of an integer and has functions to increment it and return its value, which is useful for testing purposes. This contract is also included in the genesis block. Although we didn't include straightforward options in the TUI to test this contract, you can use the option for custom contract execution and manually enter the address of this contract and the calldata for the function you want to execute.
The states of the blockchain are stored at blockchain/states
. It comes with the genesis block block0.json
, but as each block is executed, more states will be added.
If the states directory doesn't exist, it will be created and the genesis block will be automatically generated.
All public and private keys of the blockchain members are stored in keys
.
The public and private keys of the clients are stored in keys/clients
, and for convenience their addresses are also stored in the same place, although we never read from these files as we use the public keys to determine the addresses.
All the keys come pre-generated for convenience. If the keys
directory doesn't exist, it will be created and all the keys will be automatically generated.
In order to compile the whole project, including generating the necessary targets, and run the unit tests, go to the root of the project and type the following:
$ mvn clean install
If you want faster compilation and don't desire to run the tests, you can type:
$ mvn clean install -DskipTests
First, to run the blockchain members, we recommend you open 5 different terminals and run the following from the root of the project (one command for each terminal):
$ mvn -pl blockchain exec:java -Dexec.args="0 5"
$ mvn -pl blockchain exec:java -Dexec.args="1 5"
$ mvn -pl blockchain exec:java -Dexec.args="2 5"
$ mvn -pl blockchain exec:java -Dexec.args="3 5"
$ mvn -pl blockchain exec:java -Dexec.args="4 5"
Note 1: The first argument represents the ID of the member to be executed, and the second is the total number of clients.
Note 2: Please run the members in ascending order, and only start the next when the previous as already started (e.g. only start member 2 when 1 and 0 have already started). This is because the members need to share symmetric keys when they are run, and this is the order we have defined in the code.
Note 3: By default, member with ID 0 is the leader.
Next, to run the TUI app of the client, also from the root of the project:
$ mvn -pl client exec:java -Dexec.args="0"
Note 4: Here, the argument is the ID of the client.
Note 5: Client with ID 0 is the deployer of the IST Coin contract (owner of the blacklist) and starts with a big balance of Dep Coin and IST Coin, so it is particularly useful. You can run other clients with different IDs at the same time in other terminals.
- After the 5 blockchain members are running, open 2 clients in different terminals. A client with ID 0, and a client with ID 1.
- We will now test the most basic transaction, sending Dep Coin between the two:
- Go to the client with ID 0 and check its balance (menu option 1).
- Still in the client with ID 0, use menu option 2 to execute a transaction.
- Use as receipient the address of client with ID 1. If you are using the default keys the address should be
0xb47dc6ee9aba1b31dbe92933fe5a38f4df15b8d8
. - Type some amount to transfer.
- Check the balance of each client.
- Now, we will test smart contract execution. To transfer some IST Coin between the two:
- In client with ID 0 go to menu option 3.
- Check your current balance by using menu option 2 and typing your address. If using the default:
0x3a89a0f8dfaef2cad42e124049ee152bb01edc85
. - Go back into menu option 3 for contract execution and start a IST Coin transfer with menu option 1.
- Use as receipient the address of client with ID 1. Again, if you are using the default keys the address should be
0xb47dc6ee9aba1b31dbe92933fe5a38f4df15b8d8
. - Type some amount to transfer.
- Check the balance of each client.
- Finally, we will test the blacklist:
- With client 0 (owner of the blacklist), go into menu option 3.
- In the contract execution menu use option 3 to blacklist an account.
- Blacklist client 1. Again, the default address should be
0xb47dc6ee9aba1b31dbe92933fe5a38f4df15b8d8
. - Try to make a transfer of IST Coin as done before, and look at the balance again to check that the transfer didn't go through.
- Remove client 1 from the blacklist by going into the contract execution menu and selecting option 4 (with client 0).
- Try to make the transfer again (which now should work again) and check the balances.
Note 6: After each action, a return value is displayed. In the case of the transfer after blacklisting the client, although the transfer returns Done...
, what comes next is an error code that is returned by the EVM (because the client is blacklisted). In contrast, when it is successful, the return is 0x1
(true).