# 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.