diff --git a/CHANGELOG.md b/CHANGELOG.md index f890804a6f..eb90a9ec3b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -55,6 +55,7 @@ Ref: https://keepachangelog.com/en/1.0.0/ ### Bug Fixes +* (evm) [tharsis#579](https://github.com/tharsis/ethermint/pull/579) Update `DeriveChainID` function to handle `v` signature values `< 35`. * (encoding) [tharsis#478](https://github.com/tharsis/ethermint/pull/478) Register `Evidence` to amino codec. * (rpc) [tharsis#478](https://github.com/tharsis/ethermint/pull/481) Getting the node configuration when calling the `miner` rpc methods. * (cli) [tharsis#561](https://github.com/tharsis/ethermint/pull/561) `Export` and `Start` commands now use the same home directory. diff --git a/x/evm/types/tx_data.go b/x/evm/types/tx_data.go index b9c841ef79..7e76aeee6b 100644 --- a/x/evm/types/tx_data.go +++ b/x/evm/types/tx_data.go @@ -54,9 +54,15 @@ func NewTxDataFromTx(tx *ethtypes.Transaction) TxData { return txData } -// DeriveChainID derives the chain id from the given v parameter +// DeriveChainID derives the chain id from the given v parameter. +// +// CONTRACT: v value is either: +// +// - {0,1} + CHAIN_ID * 2 + 35, if EIP155 is used +// - {0,1} + 27, otherwise +// Ref: https://github.com/ethereum/EIPs/blob/master/EIPS/eip-155.md func DeriveChainID(v *big.Int) *big.Int { - if v == nil { + if v == nil || v.Sign() < 1 { return nil } @@ -65,6 +71,12 @@ func DeriveChainID(v *big.Int) *big.Int { if v == 27 || v == 28 { return new(big.Int) } + + if v < 35 { + return nil + } + + // V MUST be of the form {0,1} + CHAIN_ID * 2 + 35 return new(big.Int).SetUint64((v - 35) / 2) } v = new(big.Int).Sub(v, big.NewInt(35)) diff --git a/x/evm/types/tx_data_test.go b/x/evm/types/tx_data_test.go index a21cf9a948..183ef69938 100644 --- a/x/evm/types/tx_data_test.go +++ b/x/evm/types/tx_data_test.go @@ -7,9 +7,6 @@ import ( "github.com/stretchr/testify/require" sdk "github.com/cosmos/cosmos-sdk/types" - "github.com/ethereum/go-ethereum/common" - - "github.com/tharsis/ethermint/tests" ) func TestTxData_chainID(t *testing.T) { @@ -38,26 +35,49 @@ func TestTxData_chainID(t *testing.T) { } func TestTxData_DeriveChainID(t *testing.T) { + bitLen64, ok := new(big.Int).SetString("0x8000000000000000", 0) + require.True(t, ok) + + bitLen80, ok := new(big.Int).SetString("0x80000000000000000000", 0) + require.True(t, ok) + + expBitLen80, ok := new(big.Int).SetString("302231454903657293676526", 0) + require.True(t, ok) + testCases := []struct { msg string data TxData expChainID *big.Int - from common.Address }{ { - "v = 0", &AccessListTx{V: big.NewInt(0).Bytes()}, nil, tests.GenerateAddress(), + "v = -1", &LegacyTx{V: big.NewInt(-1).Bytes()}, nil, + }, + { + "v = 0", &LegacyTx{V: big.NewInt(0).Bytes()}, nil, + }, + { + "v = 1", &LegacyTx{V: big.NewInt(1).Bytes()}, nil, + }, + { + "v = 27", &LegacyTx{V: big.NewInt(27).Bytes()}, new(big.Int), + }, + { + "v = 28", &LegacyTx{V: big.NewInt(28).Bytes()}, new(big.Int), + }, + { + "Ethereum mainnet", &LegacyTx{V: big.NewInt(37).Bytes()}, big.NewInt(1), }, { - "v = 1", &AccessListTx{V: big.NewInt(1).Bytes()}, big.NewInt(9223372036854775791), tests.GenerateAddress(), + "chain ID 9000", &LegacyTx{V: big.NewInt(18035).Bytes()}, big.NewInt(9000), }, { - "v = 27", &AccessListTx{V: big.NewInt(27).Bytes()}, new(big.Int), tests.GenerateAddress(), + "bit len 64", &LegacyTx{V: bitLen64.Bytes()}, big.NewInt(4611686018427387886), }, { - "v = 28", &AccessListTx{V: big.NewInt(28).Bytes()}, new(big.Int), tests.GenerateAddress(), + "bit len 80", &LegacyTx{V: bitLen80.Bytes()}, expBitLen80, }, { - "v = nil ", &AccessListTx{V: nil}, nil, tests.GenerateAddress(), + "v = nil ", &LegacyTx{V: nil}, nil, }, }