# Dappcon workshop: How to become ethereum core developer - https://git.io/fjN4L ## Workshop goal Impliment EIP-2028 [Transaction data gas cost reduction](https://eips.ethereum.org/EIPS/eip-2028) ## Requirements - golang https://golang.org/doc/install ## Prepare enveiroment ### For development - clone geth from `workshop` branch - https://github.com/JekaMas/go-ethereum/tree/workshop (there are some simplifications related to hardforks for workshop purposes) ``` mkdir -p $GOPATH/src/github.com/ethereum cd $GOPATH/src/github.com/ethereum git clone --branch workshop --recursive --single-branch --depth=1 https://github.com/JekaMas/go-ethereum.git ``` ### For testing - build retesteth ``` git clone --branch master --single-branch --depth=1 https://github.com/ethereum/retesteth.git cd retesteth mkdir build cd build cmake .. make -j4 cp retesteth/retesteth $GOPATH/bin/retesteth cd ../../ ``` - build lllc ``` git clone --branch develop --single-branch https://github.com/ethereum/solidity.git cd solidity/ git checkout 9709dfe0 mkdir build cd build/ cmake .. make lllc cp lllc/lllc $GOPATH/bin/lllc cd ../../ ``` ## Implementation 1) Add new constant to ` params/protocol_params.go` Example: before ``` TxDataNonZeroGas uint64 = 68 ``` after ``` TxDataNonZeroGas uint64 = 68 TxDataNonZeroGasIstanbul uint64 = 16 ``` 2) Add new logic to core/state_transition.go Example: before ``` if (math.MaxUint64-gas)/params.TxDataNonZeroGas < nz { return 0, vm.ErrOutOfGas } gas += nz * params.TxDataNonZeroGas ``` after ``` txDataNonZeroGas := params.TxDataNonZeroGas if ctx.GetForkFlag(params.IsIstanbulEnabled) { txDataNonZeroGas = params.TxDataNonZeroGasIstanbul } if (math.MaxUint64-gas)/txDataNonZeroGas < nz { return 0, vm.ErrOutOfGas } gas += nz * txDataNonZeroGas ``` 3) check that it can build `make geth` ## Testing 1) Add default retesteth config(go-ethereum/tests/testdata/Retesteth) config from `https://github.com/b00ris/retesteth_config` if you don't have it 2) Run geth in retesteth mode `./build/bin/geth retesteth --rpcport 8545` 3) Add new test to `tests/testdata/src/GeneralStateTestsFiller/stExample`(make a copy of add11Filler.json with your name(e.g. istambulgasFiller.json)) 4) Rename test name inside `add11` -> `your_test_name` eg `istambulgas` 6) Check that retesteth works well: ``` $ retesteth -t GeneralStateTests/stExample -- --singletest istambulgas --testpath $GOPATH/src/github.com/ethereum/go-ethereum/tests/testdata/ --filltests Running tests using path: "/Users/boris/go/src/github.com/ethereum/go-ethereum/tests/testdata/" Running 1 test case... Active client configurations: 'default ' Filter: 'istambulgas' Running tests for config 'Ethereum GO on TCP' 2 Test Case "stExample": 100% *** No errors detected ``` Where: `istambulgas` - is your test name `$GOPATH/src/github.com/ethereum/go-ethereum/tests/testdata/` - is a path to you test data 7) Check that lllc works well * in `pre` section for `095e7baea6a6c7c4c2dfeb977efac326af552d87` account remove compiled contract code `"code" : "0x6001600101600055"` * uncomment `"code" : "{ [[ 0 ]] (ADD 1 1) }",` 8) Define `pre section of account` ``` "pre" : { "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { "balance" : "1000000000000000000", "code" : "{ [[0]] (GAS) }", "nonce" : "0", "storage" : { } }, "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { "balance" : "1000000000000000000", "code" : "0x", "nonce" : "0", "storage" : { } } }, ``` To check gas used we need lllc code `[[0]] (GAS)` It put into the `095e7baea6a6c7c4c2dfeb977efac326af552d87` storage remaining gas. On Istanbul it should be greater by 52 (68-16). Note: If you have a problem with lllc you could use compiled version - `0x5a600055`, where: ``` 5a - GAS 60 - PUSH1 00 - 0 (operand of PUSH1) 55 - SSTORE ``` 9) Add data to transaction (single non-zero byte) ``` "data" : [ "0x01" ], ``` 10) Add expected section ``` "expect" : [ { "indexes" : { "data" : -1, "gas" : -1, "value" : -1 }, "network" : ["Constantinople"], "result" : { "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { "storage" : { } } } }, { "indexes" : { "data" : -1, "gas" : -1, "value" : -1 }, "network" : ["Istanbul"], "result" : { "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { "storage" : { } } } } ], ``` 11) Let's test ``` retesteth -t GeneralStateTests/stExample -- --singletest istambulgas --testpath /Users/boris/go/src/github.com/ethereum/go-ethereum/tests/testdata/ --filltests Running tests using path: "/Users/boris/go/src/github.com/ethereum/go-ethereum/tests/testdata/" Running 1 test case... Active client configurations: 'default ' Filter: 'istambulgas' Running tests for config 'Ethereum GO on TCP' 2 Test Case "stExample": 100% Error: istambulgas 0x095e7baea6a6c7c4c2dfeb977efac326af552d87 storage has more storage records then expected! (istambulgas) Error: incorrect storage [0x00] = 0x05c832, expected [0x00] = 0 (istambulgas) Error: CompareStates failed with errors: IncorrectStorage Network: Constantinople, TrInfo: d: 0, g: 0, v: 0, Test: istambulgas (istambulgas) -------- TestOutputHelper detected 3 errors during test execution! /Users/boris/workshop/retesteth/retesteth/TestOutputHelper.cpp:151: error: in "GeneralStateTests/stExample": *** 1 failure is detected in the test module "Master Test Suite" -------- *** TOTAL ERRORS DETECTED: 3 errors during all test execution! -------- ``` 12) Add expected storage to expected section * for Constantinople ``` "storage" : { "0x00" : "0x05c832" } ``` (`0x05c832` == `378930` ) * for Istanbul ``` "storage" : { "0x00" : "0x05c866" } ``` `0x05c866` == `378982` and 378982 - 378930 = 52 13) And test it again ``` retesteth -t GeneralStateTests/stExample -- --singletest istambulgas --testpath /Users/boris/go/src/github.com/ethereum/go-ethereum/tests/testdata/ --filltests Running tests using path: "/Users/boris/go/src/github.com/ethereum/go-ethereum/tests/testdata/" Running 1 test case... Active client configurations: 'default ' Filter: 'istambulgas' Running tests for config 'Ethereum GO on TCP' 2 Test Case "stExample": 100% *** No errors detected ``` 14) **Profit!!!** You became core ethereum developer. You first EIP is ready.