Install Golang 1.15+ following instructions from https://golang.org/doc/install.
Install Solidity Compiler following instructions from https://solidity.readthedocs.io/en/latest/installing-solidity.html#binary-packages.
Install solc
first to make CVM transactions.
-
Mechanically copied code (that we intend to copy again in the future) from external dependencies should be kept in original style as close as possible.
-
All exported definitions (types, methods, functions, variables, constants, etc.) should have whole sentence comments starting with the definition name.
-
Group imports in the following order, separated by an empty line in between.
- Standard packages
- Other 3rd-party packages
- Tendermint packages
- Cosmos SDK packages
- Burrow packages
- Shentu packages
-
Before creating pull requests of your changes, run the following commandlines for style and dependencies.
$ make tidy
Also make sure to fix linter and testing errors.
$ make lint $ make test
golangci-lint needs to be installed locally to run the linters.
To include the built binary to GOBIN
,
$ make install
To build for Windows, Linux, and macOS,
$ make release
Run unit test:
$ make test
Run unit test and view brief coverage in cli:
$ make test-cov
Run unit test and view detailed coverage report in browser:
$ make test-cov-html
$ make image
This builds the docker image for the shentu node daemon & client. (Note that this command needs to be run prior to the multi node testnet setup below.)
Run make image
first to build the images initially (no need to be rerun for usual code update).
Setup a localnet (per code change):
$ make localnet-start
This will run (four) testnet nodes in the background as well as an interactive client. If you want to see node output, do docker-compose logs -f
(in other terminal) which will display output from all four nodes until you exit the process. Stops the localnet by docker-compose down
.
To access the running localnet machine, you can list the running containers through
docker container ls --all
and access the specific container through
docker exec -it <container name> /bin/bash
Run the scripts for testing:
$ shentud query account $NODE0_KEY
$ shentud query bank total
# Create a new account
$ shentud keys add jack
$ JACK_KEY=$(shentud keys show jack -a)
# default password = jkljkljkl
$ shentud tx send node0 $JACK_KEY 100000uctk --gas-prices=0.025uctk --from node0
$ shentud query account $JACK_KEY
Finally, run make localnet-stop
to shutdown the localnet.
Please see e2e/README.md for instructions.
Recommend the use of the provided Docker containers for simplicity, but here are instructions for manually setting up a single node chain for testing purposes.
$ shentud unsafe-reset-all
$ rm -rf ~/.shentud
$ shentud init node0 --chain-id shentuchain
$ shentud keys add jack
$ shentud add-genesis-account $(shentud keys show jack -a) 10000000000000000uctk
$ shentud add-genesis-certifier $(shentud keys show jack -a)
$ shentud add-genesis-shield-admin $(shentud keys show jack -a)
Notification: Every transaction will need 5000uctk , so you'd better start with more than 5000uctk here.
$ shentud gentx jack 10000000000000000uctk --chain-id shentuchain
$ shentud collect-gentxs
$ shentud start
$ shentud query account $(shentud keys show jack -a)
$ shentud keys add alice
$ shentud tx send jack $(shentud keys show alice -a) 7000000000uctk --gas-prices=0.025uctk --from jack --chain-id shentuchain
$ shentud query account $(shentud keys show jack -a)
$ shentud query account $(shentud keys show alice -a)
We have a very simple storage setter / getter contract tests/sync/simple.sol
.
pragma solidity >=0.4.0 <0.7.0;
contract SimpleStorage {
uint storedData;
function set(uint x) public {
storedData = x;
}
function get() public view returns (uint) {
return storedData;
}
}
To deploy tests/sync/simple.sol
contract (be sure to have solc
installed), first compile it into a bytecode (.bin
file) and abi.
Assuming you have simple.sol
compiled into simple.bytecode
(.bin
file) and simple.abi
$ cd tests
$ shentud tx cvm deploy simple.bin --abi simple.abi --from node0
Printed on the main terminal
Response:
TxHash: 8067DBC001BE239E5A44843CCEF4C71A87B802352989F97664AF8F265E7B888E
Printed on the shentud node server terminals
I[2019-06-27|09:05:33.281] CVM Start module=main txHash=8067dbc001be239e5a44843ccef4c71a87b802352989f97664af8f265e7b888e
I[2019-06-27|09:05:33.282] CVM module=main log_channel=Trace scope=NewVM message="(1) (89203146CD64A945BE5B02B0C44FB0040855C02A) 07BC7F3C21C34643A90AA1138C950FAC5025B693 (code=229) gas: 1000000 (d) 608060405234801561001057600080FD5B5060C68061001F6000396000F3FE6080604052348015600F57600080FD5B506004361060325760003560E01C806360FE47B11460375780636D4CE63C146062575B600080FD5B606060048036036020811015604B57600080FD5B8101908080359060200190929190505050607E565B005B60686088565B6040518082815260200191505060405180910390F35B8060008190555050565B6000805490509056FEA265627A7A723058205FEC64D09C278453AB74A855DCC214EA05BF9541E35E851AF41570397593055564736F6C63430005090032\n" tag=DebugOpcodes
I[2019-06-27|09:05:33.283] CVM module=main log_channel=Trace scope=NewVM message="(pc) 0 (op) PUSH1 (st) 0 (gas) 1000000" tag=DebugOpcodes
I[2019-06-27|09:05:33.283] CVM module=main log_channel=Trace scope=NewVM message=" => 0x0000000000000000000000000000000000000000000000000000000000000080\n" tag=DebugOpcodes
I[2019-06-27|09:05:33.283] CVM module=main log_channel=Trace scope=NewVM message="(pc) 2 (op) PUSH1 (st) 1 (gas) 999999" tag=DebugOpcodes
I[2019-06-27|09:05:33.284] CVM module=main log_channel=Trace scope=NewVM message=" => 0x0000000000000000000000000000000000000000000000000000000000000040\n" tag=DebugOpcodes
I[2019-06-27|09:05:33.284] CVM module=main log_channel=Trace scope=NewVM message="(pc) 4 (op) MSTORE (st) 2 (gas) 999998" tag=DebugOpcodes
I[2019-06-27|09:05:33.284] CVM module=main log_channel=Trace scope=NewVM message=" => 0x0000000000000000000000000000000000000000000000000000000000000080 @ 0x40\n" tag=DebugOpcodes
I[2019-06-27|09:05:33.284] CVM module=main log_channel=Trace scope=NewVM message="(pc) 5 (op) CALLVALUE (st) 0 (gas) 999996" tag=DebugOpcodes
I[2019-06-27|09:05:33.284] CVM module=main log_channel=Trace scope=NewVM message=" => 0\n" tag=DebugOpcodes
I[2019-06-27|09:05:33.284] CVM module=main log_channel=Trace scope=NewVM message="(pc) 6 (op) DUP1 (st) 1 (gas) 999995" tag=DebugOpcodes
I[2019-06-27|09:05:33.284] CVM module=main log_channel=Trace scope=NewVM message=" => [1] 0x0000000000000000000000000000000000000000000000000000000000000000\n" tag=DebugOpcodes
I[2019-06-27|09:05:33.284] CVM module=main log_channel=Trace scope=NewVM message="(pc) 7 (op) ISZERO (st) 2 (gas) 999993" tag=DebugOpcodes
I[2019-06-27|09:05:33.285] CVM module=main log_channel=Trace scope=NewVM message=" 0000000000000000000000000000000000000000000000000000000000000000 == 0 = 1\n" tag=DebugOpcodes
I[2019-06-27|09:05:33.285] CVM module=main log_channel=Trace scope=NewVM message="(pc) 8 (op) PUSH2 (st) 2 (gas) 999991" tag=DebugOpcodes
I[2019-06-27|09:05:33.285] CVM module=main log_channel=Trace scope=NewVM message=" => 0x0000000000000000000000000000000000000000000000000000000000000010\n" tag=DebugOpcodes
I[2019-06-27|09:05:33.285] CVM module=main log_channel=Trace scope=NewVM message="(pc) 11 (op) JUMPI (st) 3 (gas) 999990" tag=DebugOpcodes
I[2019-06-27|09:05:33.285] CVM module=main log_channel=Trace scope=NewVM message=" ~> 16\n" tag=DebugOpcodes
I[2019-06-27|09:05:33.285] CVM module=main log_channel=Trace scope=NewVM message="(pc) 16 (op) JUMPDEST (st) 1 (gas) 999988" tag=DebugOpcodes
I[2019-06-27|09:05:33.285] CVM module=main log_channel=Trace scope=NewVM message="\n" tag=DebugOpcodes
I[2019-06-27|09:05:33.285] CVM module=main log_channel=Trace scope=NewVM message="(pc) 17 (op) POP (st) 1 (gas) 999988" tag=DebugOpcodes
I[2019-06-27|09:05:33.285] CVM module=main log_channel=Trace scope=NewVM message=" => 0x0000000000000000000000000000000000000000000000000000000000000000\n" tag=DebugOpcodes
I[2019-06-27|09:05:33.285] CVM module=main log_channel=Trace scope=NewVM message="(pc) 18 (op) PUSH1 (st) 0 (gas) 999987" tag=DebugOpcodes
I[2019-06-27|09:05:33.285] CVM module=main log_channel=Trace scope=NewVM message=" => 0x00000000000000000000000000000000000000000000000000000000000000C6\n" tag=DebugOpcodes
I[2019-06-27|09:05:33.285] CVM module=main log_channel=Trace scope=NewVM message="(pc) 20 (op) DUP1 (st) 1 (gas) 999986" tag=DebugOpcodes
I[2019-06-27|09:05:33.286] CVM module=main log_channel=Trace scope=NewVM message=" => [1] 0x00000000000000000000000000000000000000000000000000000000000000C6\n" tag=DebugOpcodes
I[2019-06-27|09:05:33.286] CVM module=main log_channel=Trace scope=NewVM message="(pc) 21 (op) PUSH2 (st) 2 (gas) 999984" tag=DebugOpcodes
I[2019-06-27|09:05:33.286] CVM module=main log_channel=Trace scope=NewVM message=" => 0x000000000000000000000000000000000000000000000000000000000000001F\n" tag=DebugOpcodes
I[2019-06-27|09:05:33.286] CVM module=main log_channel=Trace scope=NewVM message="(pc) 24 (op) PUSH1 (st) 3 (gas) 999983" tag=DebugOpcodes
I[2019-06-27|09:05:33.286] CVM module=main log_channel=Trace scope=NewVM message=" => 0x0000000000000000000000000000000000000000000000000000000000000000\n" tag=DebugOpcodes
I[2019-06-27|09:05:33.286] CVM module=main log_channel=Trace scope=NewVM message="(pc) 26 (op) CODECOPY (st) 4 (gas) 999982" tag=DebugOpcodes
I[2019-06-27|09:05:33.286] CVM module=main log_channel=Trace scope=NewVM message=" => [0, 31, 198] 6080604052348015600F57600080FD5B506004361060325760003560E01C806360FE47B11460375780636D4CE63C146062575B600080FD5B606060048036036020811015604B57600080FD5B8101908080359060200190929190505050607E565B005B60686088565B6040518082815260200191505060405180910390F35B8060008190555050565B6000805490509056FEA265627A7A723058205FEC64D09C278453AB74A855DCC214EA05BF9541E35E851AF41570397593055564736F6C63430005090032\n" tag=DebugOpcodes
I[2019-06-27|09:05:33.286] CVM module=main log_channel=Trace scope=NewVM message="(pc) 27 (op) PUSH1 (st) 1 (gas) 999979" tag=DebugOpcodes
I[2019-06-27|09:05:33.286] CVM module=main log_channel=Trace scope=NewVM message=" => 0x0000000000000000000000000000000000000000000000000000000000000000\n" tag=DebugOpcodes
I[2019-06-27|09:05:33.286] CVM module=main log_channel=Trace scope=NewVM message="(pc) 29 (op) RETURN (st) 2 (gas) 999978" tag=DebugOpcodes
I[2019-06-27|09:05:33.286] CVM module=main log_channel=Trace scope=NewVM message=" => [0, 198] (198) 0x6080604052348015600F57600080FD5B506004361060325760003560E01C806360FE47B11460375780636D4CE63C146062575B600080FD5B606060048036036020811015604B57600080FD5B8101908080359060200190929190505050607E565B005B60686088565B6040518082815260200191505060405180910390F35B8060008190555050565B6000805490509056FEA265627A7A723058205FEC64D09C278453AB74A855DCC214EA05BF9541E35E851AF41570397593055564736F6C63430005090032\n" tag=DebugOpcodes
I[2019-06-27|09:05:33.287] CVM Stop module=main result=07bc7f3c21c34643a90aa1138c950fac5025b693
To inspect deploy transaction details and to obtain Bech32 contract address
$ shentud query tx 8067DBC001BE239E5A44843CCEF4C71A87B802352989F97664AF8F265E7B888E
Response:
Height: 169
TxHash: 8067DBC001BE239E5A44843CCEF4C71A87B802352989F97664AF8F265E7B888E
Data: 07BC7F3C21C34643A90AA1138C950FAC5025B693
Raw Log: [{"msg_index":"0","success":true,"log":"shentu1q77870ppcdry82g25yfce9g043gztd5n99x7we"}]
Logs: [{"msg_index":0,"success":true,"log":"shentu1q77870ppcdry82g25yfce9g043gztd5n99x7we"}]
GasWanted: 200000
GasUsed: 41849
Tags:
- action = deploy
Timestamp: 2019-06-27T16:05:27Z
To inspect contract code bytes deployed at shentu1q77870ppcdry82g25yfce9g043gztd5n99x7we
$ shentud query cvm code shentu1q77870ppcdry82g25yfce9g043gztd5n99x7we
6080604052348015600F57600080FD5B506004361060325760003560E01C806360FE47B114603757
80636D4CE63C146062575B600080FD5B606060048036036020811015604B57600080FD5B81019080
80359060200190929190505050607E565B005B60686088565B604051808281526020019150506040
5180910390F35B8060008190555050565B6000805490509056FEA265627A7A723058205FEC64D09C
278453AB74A855DCC214EA05BF9541E35E851AF41570397593055564736F6C63430005090032
To call SimpleStorage.set(123)
at the contract
$ shentud tx cvm call shentu1q77870ppcdry82g25yfce9g043gztd5n99x7we set 123 --from node0
Then we can verify the storage setting by calling SimpleStorage.get()
at the
contract
$ shentud tx cvm call shentu1q77870ppcdry82g25yfce9g043gztd5n99x7we get --from node0
Response:
TxHash: 6EAABFDF5022F21F88D9DBBE8A0837F3CF6819F06F801BEF301188F22DF16C9B
We can inspect and verify the read out value is indeed 123 (0x7b) by either looking at the shentud node server terminal
I[2019-06-27|09:20:44.674] CVM Stop module=main result=000000000000000000000000000000000000000000000000000000000000007b
or query the get call transaction
$ shentud query tx 6EAABFDF5022F21F88D9DBBE8A0837F3CF6819F06F801BEF301188F22DF16C9B
Response:
Height: 333
TxHash: 6EAABFDF5022F21F88D9DBBE8A0837F3CF6819F06F801BEF301188F22DF16C9B
Data: 000000000000000000000000000000000000000000000000000000000000007B
Raw Log: [{"msg_index":"0","success":true,"log":""}]
Logs: [{"msg_index":0,"success":true,"log":""}]
GasWanted: 200000
GasUsed: 17677
Tags:
- action = call
Timestamp: 2019-06-27T16:20:38Z
Analogous to the steps above, a DeepSEA contract contract.ds
can be deployed with:
$ shentud tx cvm deploy contract.ds --from node0
Make sure that dsc
(DeepSEA compiler) is in your PATH
.
Start the rest-server
in another terminal window:
$ shentud rest-server --trust-node
Back to the previous terminal window where NODE0_KEY
is defined:
# Initiate Transaction: Burn 2 ctk from node0.
$ curl -XPOST -s http://localhost:1317/ctk/burn --data-binary '{"base_req":{"from":"'$NODE0_KEY'","chain_id":"shentuchain"},"src":"'$NODE0_KEY'","amount":"2"}' > unsignedTx.json
# Sign Transaction
# Note: sequence and account-number can be found in account information
$ shentud tx sign unsignedTx.json --from $NODE0_KEY --offline --chain-id shentuchain --sequence 5 --account-number 0 > signedTx.json
# Broadcast Transaction
$ shentud tx broadcast signedTx.json
# Check the balance of node0
$ curl -s http:/localhost:1317/ctk/balance/$NODE0_KEY