proto, evm: use string for address and hash protobuf message fields (#23)

* proto, evm: use string for address and hash protobuf message fields

* fix tests

* msg test
This commit is contained in:
Federico Kunze 2021-05-14 02:52:18 -04:00 committed by GitHub
parent a952bc36d1
commit ba5bf33f19
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
18 changed files with 536 additions and 447 deletions

View File

@ -9,7 +9,6 @@
- [PubKey](#ethermint.crypto.v1alpha1.ethsecp256k1.PubKey) - [PubKey](#ethermint.crypto.v1alpha1.ethsecp256k1.PubKey)
- [ethermint/evm/v1alpha1/evm.proto](#ethermint/evm/v1alpha1/evm.proto) - [ethermint/evm/v1alpha1/evm.proto](#ethermint/evm/v1alpha1/evm.proto)
- [AccessList](#ethermint.evm.v1alpha1.AccessList)
- [AccessTuple](#ethermint.evm.v1alpha1.AccessTuple) - [AccessTuple](#ethermint.evm.v1alpha1.AccessTuple)
- [BytesList](#ethermint.evm.v1alpha1.BytesList) - [BytesList](#ethermint.evm.v1alpha1.BytesList)
- [ChainConfig](#ethermint.evm.v1alpha1.ChainConfig) - [ChainConfig](#ethermint.evm.v1alpha1.ChainConfig)
@ -126,21 +125,6 @@ key format.
<a name="ethermint.evm.v1alpha1.AccessList"></a>
### AccessList
AccessList is an EIP-2930 access list defined as a proto message.
| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| `tuples` | [AccessTuple](#ethermint.evm.v1alpha1.AccessTuple) | repeated | access list tuples |
<a name="ethermint.evm.v1alpha1.AccessTuple"></a> <a name="ethermint.evm.v1alpha1.AccessTuple"></a>
### AccessTuple ### AccessTuple
@ -301,10 +285,10 @@ solely as intended in Ethereum abiding by the protocol.
| `nonce` | [uint64](#uint64) | | nonce corresponds to the account nonce (transaction sequence). | | `nonce` | [uint64](#uint64) | | nonce corresponds to the account nonce (transaction sequence). |
| `gas_price` | [bytes](#bytes) | | price defines the unsigned integer value of the gas price in bytes. | | `gas_price` | [bytes](#bytes) | | price defines the unsigned integer value of the gas price in bytes. |
| `gas` | [uint64](#uint64) | | gas defines the gas limit defined for the transaction. | | `gas` | [uint64](#uint64) | | gas defines the gas limit defined for the transaction. |
| `to` | [bytes](#bytes) | | | | `to` | [string](#string) | | hex formatted address of the recipient |
| `value` | [bytes](#bytes) | | value defines the unsigned integer value of the transaction amount. | | `value` | [bytes](#bytes) | | value defines the unsigned integer value of the transaction amount. |
| `input` | [bytes](#bytes) | | input defines the data payload bytes of the transaction. | | `input` | [bytes](#bytes) | | input defines the data payload bytes of the transaction. |
| `accesses` | [AccessList](#ethermint.evm.v1alpha1.AccessList) | | | | `accesses` | [AccessTuple](#ethermint.evm.v1alpha1.AccessTuple) | repeated | |
| `v` | [bytes](#bytes) | | v defines the signature value | | `v` | [bytes](#bytes) | | v defines the signature value |
| `r` | [bytes](#bytes) | | r defines the signature value | | `r` | [bytes](#bytes) | | r defines the signature value |
| `s` | [bytes](#bytes) | | s define the signature value | | `s` | [bytes](#bytes) | | s define the signature value |
@ -322,13 +306,13 @@ TxReceipt defines the receipt type stored in KV for each EVM transaction.
| Field | Type | Label | Description | | Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- | | ----- | ---- | ----- | ----------- |
| `hash` | [bytes](#bytes) | | | | `hash` | [string](#string) | | |
| `from` | [bytes](#bytes) | | | | `from` | [string](#string) | | |
| `data` | [TxData](#ethermint.evm.v1alpha1.TxData) | | | | `data` | [TxData](#ethermint.evm.v1alpha1.TxData) | | |
| `result` | [TxResult](#ethermint.evm.v1alpha1.TxResult) | | | | `result` | [TxResult](#ethermint.evm.v1alpha1.TxResult) | | |
| `index` | [uint64](#uint64) | | | | `index` | [uint64](#uint64) | | |
| `block_height` | [uint64](#uint64) | | | | `block_height` | [uint64](#uint64) | | |
| `block_hash` | [bytes](#bytes) | | | | `block_hash` | [string](#string) | | |

View File

@ -148,14 +148,14 @@ func (e *EVMBackend) EthBlockFromTendermint(
ethRPCTxs := make([]interface{}, 0, len(txReceiptsResp.Receipts)) ethRPCTxs := make([]interface{}, 0, len(txReceiptsResp.Receipts))
for _, receipt := range txReceiptsResp.Receipts { for _, receipt := range txReceiptsResp.Receipts {
hash := common.BytesToHash(receipt.Hash) hash := common.HexToHash(receipt.Hash)
if fullTx { if fullTx {
// full txs from receipts // full txs from receipts
tx, err := types.NewTransactionFromData( tx, err := types.NewTransactionFromData(
receipt.Data, receipt.Data,
common.BytesToAddress(receipt.From), common.HexToAddress(receipt.From),
hash, hash,
common.BytesToHash(receipt.BlockHash), common.HexToHash(receipt.BlockHash),
receipt.BlockHeight, receipt.BlockHeight,
receipt.Index, receipt.Index,
) )

View File

@ -667,9 +667,9 @@ func (e *PublicEthAPI) GetTransactionByHash(hash common.Hash) (*types.RPCTransac
return types.NewTransactionFromData( return types.NewTransactionFromData(
resp.Receipt.Data, resp.Receipt.Data,
common.BytesToAddress(resp.Receipt.From), common.HexToAddress(resp.Receipt.From),
common.BytesToHash(resp.Receipt.Hash), common.HexToHash(resp.Receipt.Hash),
common.BytesToHash(resp.Receipt.BlockHash), common.HexToHash(resp.Receipt.BlockHash),
resp.Receipt.BlockHeight, resp.Receipt.BlockHeight,
resp.Receipt.Index, resp.Receipt.Index,
) )
@ -714,20 +714,19 @@ func (e *PublicEthAPI) getReceiptByIndex(receipts []*evmtypes.TxReceipt, blockHa
receipt := receipts[idx] receipt := receipts[idx]
if (blockHash != common.Hash{}) { if (blockHash != common.Hash{}) {
if !bytes.Equal(receipt.BlockHash, blockHash.Bytes()) { hexBlockHash := blockHash.Hex()
err := errors.Errorf("receipt found but block hashes don't match %s != %s", if receipt.BlockHash != hexBlockHash {
common.Bytes2Hex(receipt.BlockHash), return nil, errors.Errorf("receipt found but block hashes don't match %s != %s",
blockHash.Hex(), receipt.BlockHash,
hexBlockHash,
) )
return nil, err
} }
} }
return types.NewTransactionFromData( return types.NewTransactionFromData(
receipt.Data, receipt.Data,
common.BytesToAddress(receipt.From), common.HexToAddress(receipt.From),
common.BytesToHash(receipt.Hash), common.HexToHash(receipt.Hash),
blockHash, blockHash,
receipt.BlockHeight, receipt.BlockHeight,
uint64(idx), uint64(idx),
@ -769,7 +768,7 @@ func (e *PublicEthAPI) GetTransactionReceipt(hash common.Hash) (map[string]inter
toHex := common.Address{} toHex := common.Address{}
if len(tx.Receipt.Data.To) > 0 { if len(tx.Receipt.Data.To) > 0 {
toHex = common.BytesToAddress(tx.Receipt.Data.To) toHex = common.HexToAddress(tx.Receipt.Data.To)
} }
contractAddress := common.HexToAddress(tx.Receipt.Result.ContractAddress) contractAddress := common.HexToAddress(tx.Receipt.Result.ContractAddress)
@ -794,7 +793,7 @@ func (e *PublicEthAPI) GetTransactionReceipt(hash common.Hash) (map[string]inter
"transactionIndex": hexutil.Uint64(tx.Receipt.Index), "transactionIndex": hexutil.Uint64(tx.Receipt.Index),
// sender and receiver (contract or EOA) addreses // sender and receiver (contract or EOA) addreses
"from": common.BytesToAddress(tx.Receipt.From), "from": common.HexToAddress(tx.Receipt.From),
"to": toHex, "to": toHex,
} }

View File

@ -79,7 +79,7 @@ func (args *SendTxArgs) ToTransaction() *evmtypes.MsgEthereumTx {
} }
data := &evmtypes.TxData{ data := &evmtypes.TxData{
To: args.To.Bytes(), To: args.To.Hex(),
ChainID: args.ChainID.ToInt().Bytes(), ChainID: args.ChainID.ToInt().Bytes(),
Nonce: uint64(*args.Nonce), Nonce: uint64(*args.Nonce),
GasLimit: uint64(*args.Gas), GasLimit: uint64(*args.Gas),

View File

@ -304,7 +304,7 @@ func NewTransactionFromData(
var to *common.Address var to *common.Address
if len(txData.To) > 0 { if len(txData.To) > 0 {
recipient := common.BytesToAddress(txData.To) recipient := common.HexToAddress(txData.To)
to = &recipient to = &recipient
} }
@ -334,21 +334,3 @@ func NewTransactionFromData(
return rpcTx, nil return rpcTx, nil
} }
var zeroHash = hexutil.Bytes(make([]byte, 32))
func hashOrZero(data []byte) hexutil.Bytes {
if len(data) == 0 {
return zeroHash
}
return hexutil.Bytes(data)
}
func bigOrZero(i *big.Int) *hexutil.Big {
if i == nil {
return new(hexutil.Big)
}
return (*hexutil.Big)(i)
}

2
go.mod
View File

@ -43,7 +43,7 @@ require (
github.com/tyler-smith/go-bip39 v1.1.0 github.com/tyler-smith/go-bip39 v1.1.0
github.com/xlab/closer v0.0.0-20190328110542-03326addb7c2 github.com/xlab/closer v0.0.0-20190328110542-03326addb7c2
github.com/xlab/suplog v1.3.0 github.com/xlab/suplog v1.3.0
golang.org/x/crypto v0.0.0-20210506145944-38f3c27a63bf golang.org/x/crypto v0.0.0-20210513122933-cd7d49e622d5
golang.org/x/sys v0.0.0-20210503173754-0981d6026fa6 // indirect golang.org/x/sys v0.0.0-20210503173754-0981d6026fa6 // indirect
google.golang.org/genproto v0.0.0-20210510173355-fb37daa5cd7a google.golang.org/genproto v0.0.0-20210510173355-fb37daa5cd7a
google.golang.org/grpc v1.37.1 google.golang.org/grpc v1.37.1

4
go.sum
View File

@ -916,8 +916,8 @@ golang.org/x/crypto v0.0.0-20201016220609-9e8e0b390897/go.mod h1:LzIPMQfyMNhhGPh
golang.org/x/crypto v0.0.0-20201117144127-c1f2f97bffc9/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= golang.org/x/crypto v0.0.0-20201117144127-c1f2f97bffc9/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
golang.org/x/crypto v0.0.0-20210506145944-38f3c27a63bf h1:B2n+Zi5QeYRDAEodEu72OS36gmTWjgpXr2+cWcBW90o= golang.org/x/crypto v0.0.0-20210513122933-cd7d49e622d5 h1:N6Jp/LCiEoIBX56BZSR2bepK5GtbSC2DDOYT742mMfE=
golang.org/x/crypto v0.0.0-20210506145944-38f3c27a63bf/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8= golang.org/x/crypto v0.0.0-20210513122933-cd7d49e622d5/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8=
golang.org/x/exp v0.0.0-20180321215751-8460e604b9de/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20180321215751-8460e604b9de/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20180807140117-3d87b88a115f/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20180807140117-3d87b88a115f/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=

View File

@ -174,13 +174,13 @@ message Log {
message TxReceipt { message TxReceipt {
option (gogoproto.goproto_getters) = false; option (gogoproto.goproto_getters) = false;
bytes hash = 1; string hash = 1;
bytes from = 2; string from = 2;
TxData data = 3; TxData data = 3;
TxResult result = 4; TxResult result = 4;
uint64 index = 5; uint64 index = 5;
uint64 block_height = 6; uint64 block_height = 6;
bytes block_hash = 7; string block_hash = 7;
} }
// TxResult stores results of Tx execution. // TxResult stores results of Tx execution.
@ -220,12 +220,17 @@ message TxData {
bytes gas_price = 3 [(gogoproto.customname) = "GasPrice"]; bytes gas_price = 3 [(gogoproto.customname) = "GasPrice"];
// gas defines the gas limit defined for the transaction. // gas defines the gas limit defined for the transaction.
uint64 gas = 4 [(gogoproto.customname) = "GasLimit"]; uint64 gas = 4 [(gogoproto.customname) = "GasLimit"];
bytes to = 5; // hex formatted address of the recipient
string to = 5;
// value defines the unsigned integer value of the transaction amount. // value defines the unsigned integer value of the transaction amount.
bytes value = 6 [(gogoproto.customname) = "Amount"]; bytes value = 6 [(gogoproto.customname) = "Amount"];
// input defines the data payload bytes of the transaction. // input defines the data payload bytes of the transaction.
bytes input = 7; bytes input = 7;
AccessList accesses = 8 [(gogoproto.jsontag) = "accessList"]; repeated AccessTuple accesses = 8 [
(gogoproto.castrepeated) = "AccessList",
(gogoproto.jsontag) = "accessList",
(gogoproto.nullable) = false
];
// v defines the signature value // v defines the signature value
bytes v = 9; bytes v = 9;
// r defines the signature value // r defines the signature value
@ -240,13 +245,6 @@ message BytesList {
repeated bytes bytes = 1; repeated bytes bytes = 1;
} }
// AccessList is an EIP-2930 access list defined as a proto message.
message AccessList {
// access list tuples
repeated AccessTuple tuples = 1 [(gogoproto.nullable) = false];
}
// AccessTuple is the element type of an access list. // AccessTuple is the element type of an access list.
message AccessTuple { message AccessTuple {
option (gogoproto.goproto_getters) = false; option (gogoproto.goproto_getters) = false;

164
tests/importer/chain_ctx.go Normal file
View File

@ -0,0 +1,164 @@
package importer
import (
"math/big"
ethcmn "github.com/ethereum/go-ethereum/common"
ethcons "github.com/ethereum/go-ethereum/consensus"
ethstate "github.com/ethereum/go-ethereum/core/state"
ethtypes "github.com/ethereum/go-ethereum/core/types"
ethrpc "github.com/ethereum/go-ethereum/rpc"
)
// ChainContext implements Ethereum's core.ChainContext and consensus.Engine
// interfaces. It is needed in order to apply and process Ethereum
// transactions. There should only be a single implementation in Ethermint. For
// the purposes of Ethermint, it should be support retrieving headers and
// consensus parameters from the current blockchain to be used during
// transaction processing.
//
// NOTE: Ethermint will distribute the fees out to validators, so the structure
// and functionality of this is a WIP and subject to change.
type ChainContext struct {
Coinbase ethcmn.Address
headersByNumber map[uint64]*ethtypes.Header
}
// NewChainContext generates new ChainContext based on Ethereum's core.ChainContext and
// consensus.Engine interfaces in order to process Ethereum transactions.
func NewChainContext() *ChainContext {
return &ChainContext{
headersByNumber: make(map[uint64]*ethtypes.Header),
}
}
// Engine implements Ethereum's core.ChainContext interface. As a ChainContext
// implements the consensus.Engine interface, it is simply returned.
func (cc *ChainContext) Engine() ethcons.Engine {
return cc
}
// SetHeader implements Ethereum's core.ChainContext interface. It sets the
// header for the given block number.
func (cc *ChainContext) SetHeader(number uint64, header *ethtypes.Header) {
cc.headersByNumber[number] = header
}
// GetHeader implements Ethereum's core.ChainContext interface.
//
// TODO: The Cosmos SDK supports retreiving such information in contexts and
// multi-store, so this will be need to be integrated.
func (cc *ChainContext) GetHeader(_ ethcmn.Hash, number uint64) *ethtypes.Header {
if header, ok := cc.headersByNumber[number]; ok {
return header
}
return nil
}
// Author implements Ethereum's consensus.Engine interface. It is responsible
// for returned the address of the validtor to receive any fees. This function
// is only invoked if the given author in the ApplyTransaction call is nil.
//
// NOTE: Ethermint will distribute the fees out to validators, so the structure
// and functionality of this is a WIP and subject to change.
func (cc *ChainContext) Author(_ *ethtypes.Header) (ethcmn.Address, error) {
return cc.Coinbase, nil
}
// APIs implements Ethereum's consensus.Engine interface. It currently performs
// a no-op.
//
// TODO: Do we need to support such RPC APIs? This will tie into a bigger
// discussion on if we want to support web3.
func (cc *ChainContext) APIs(_ ethcons.ChainHeaderReader) []ethrpc.API {
return nil
}
// CalcDifficulty implements Ethereum's consensus.Engine interface. It currently
// performs a no-op.
func (cc *ChainContext) CalcDifficulty(_ ethcons.ChainHeaderReader, _ uint64, _ *ethtypes.Header) *big.Int {
return nil
}
// Finalize implements Ethereum's consensus.Engine interface. It currently
// performs a no-op.
//
// TODO: Figure out if this needs to be hooked up to any part of the ABCI?
func (cc *ChainContext) Finalize(
_ ethcons.ChainHeaderReader, _ *ethtypes.Header, _ *ethstate.StateDB,
_ []*ethtypes.Transaction, _ []*ethtypes.Header) {
}
// FinalizeAndAssemble runs any post-transaction state modifications (e.g. block
// rewards) and assembles the final block.
//
// Note: The block header and state database might be updated to reflect any
// consensus rules that happen at finalization (e.g. block rewards).
// TODO: Figure out if this needs to be hooked up to any part of the ABCI?
func (cc *ChainContext) FinalizeAndAssemble(_ ethcons.ChainHeaderReader, _ *ethtypes.Header, _ *ethstate.StateDB, _ []*ethtypes.Transaction,
_ []*ethtypes.Header, _ []*ethtypes.Receipt) (*ethtypes.Block, error) {
return nil, nil
}
// Prepare implements Ethereum's consensus.Engine interface. It currently
// performs a no-op.
//
// TODO: Figure out if this needs to be hooked up to any part of the ABCI?
func (cc *ChainContext) Prepare(_ ethcons.ChainHeaderReader, _ *ethtypes.Header) error {
return nil
}
// Seal implements Ethereum's consensus.Engine interface. It currently
// performs a no-op.
//
// TODO: Figure out if this needs to be hooked up to any part of the ABCI?
func (cc *ChainContext) Seal(_ ethcons.ChainHeaderReader, _ *ethtypes.Block, _ chan<- *ethtypes.Block, _ <-chan struct{}) error {
return nil
}
// SealHash implements Ethereum's consensus.Engine interface. It returns the
// hash of a block prior to it being sealed.
func (cc *ChainContext) SealHash(header *ethtypes.Header) ethcmn.Hash {
return ethcmn.Hash{}
}
// VerifyHeader implements Ethereum's consensus.Engine interface. It currently
// performs a no-op.
//
// TODO: Figure out if this needs to be hooked up to any part of the Cosmos SDK
// handlers?
func (cc *ChainContext) VerifyHeader(_ ethcons.ChainHeaderReader, _ *ethtypes.Header, _ bool) error {
return nil
}
// VerifyHeaders implements Ethereum's consensus.Engine interface. It
// currently performs a no-op.
//
// TODO: Figure out if this needs to be hooked up to any part of the Cosmos SDK
// handlers?
func (cc *ChainContext) VerifyHeaders(_ ethcons.ChainHeaderReader, _ []*ethtypes.Header, _ []bool) (chan<- struct{}, <-chan error) {
return nil, nil
}
// VerifySeal implements Ethereum's consensus.Engine interface. It currently
// performs a no-op.
//
// TODO: Figure out if this needs to be hooked up to any part of the Cosmos SDK
// handlers?
func (cc *ChainContext) VerifySeal(_ ethcons.ChainHeaderReader, _ *ethtypes.Header) error {
return nil
}
// VerifyUncles implements Ethereum's consensus.Engine interface. It currently
// performs a no-op.
func (cc *ChainContext) VerifyUncles(_ ethcons.ChainReader, _ *ethtypes.Block) error {
return nil
}
// Close implements Ethereum's consensus.Engine interface. It terminates any
// background threads maintained by the consensus engine. It currently performs
// a no-op.
func (cc *ChainContext) Close() error {
return nil
}

View File

@ -0,0 +1,119 @@
package importer
// NOTE: A bulk of these unit tests will change and evolve as the context and
// implementation of ChainConext evolves.
import (
"math/big"
"testing"
"github.com/stretchr/testify/require"
ethcmn "github.com/ethereum/go-ethereum/common"
ethcons "github.com/ethereum/go-ethereum/consensus"
ethcore "github.com/ethereum/go-ethereum/core"
ethtypes "github.com/ethereum/go-ethereum/core/types"
)
func TestChainContextInterface(t *testing.T) {
require.Implements(t, (*ethcore.ChainContext)(nil), new(ChainContext))
require.Implements(t, (*ethcons.Engine)(nil), new(ChainContext))
}
func TestNewChainContext(t *testing.T) {
cc := NewChainContext()
require.NotNil(t, cc.headersByNumber)
}
func TestChainContextEngine(t *testing.T) {
cc := NewChainContext()
require.Equal(t, cc, cc.Engine())
}
func TestChainContextSetHeader(t *testing.T) {
cc := NewChainContext()
header := &ethtypes.Header{
Number: big.NewInt(64),
}
cc.SetHeader(uint64(header.Number.Int64()), header)
require.Equal(t, header, cc.headersByNumber[uint64(header.Number.Int64())])
}
func TestChainContextGetHeader(t *testing.T) {
cc := NewChainContext()
header := &ethtypes.Header{
Number: big.NewInt(64),
}
cc.SetHeader(uint64(header.Number.Int64()), header)
require.Equal(t, header, cc.GetHeader(ethcmn.Hash{}, uint64(header.Number.Int64())))
require.Nil(t, cc.GetHeader(ethcmn.Hash{}, 0))
}
func TestChainContextAuthor(t *testing.T) {
cc := NewChainContext()
cb, err := cc.Author(nil)
require.Nil(t, err)
require.Equal(t, cc.Coinbase, cb)
}
func TestChainContextAPIs(t *testing.T) {
cc := NewChainContext()
require.Nil(t, cc.APIs(nil))
}
func TestChainContextCalcDifficulty(t *testing.T) {
cc := NewChainContext()
require.Nil(t, cc.CalcDifficulty(nil, 0, nil))
}
func TestChainContextFinalize(t *testing.T) {
cc := NewChainContext()
cc.Finalize(nil, nil, nil, nil, nil)
}
func TestChainContextPrepare(t *testing.T) {
cc := NewChainContext()
err := cc.Prepare(nil, nil)
require.Nil(t, err)
}
func TestChainContextSeal(t *testing.T) {
cc := NewChainContext()
err := cc.Seal(nil, nil, nil, nil)
require.Nil(t, err)
}
func TestChainContextVerifyHeader(t *testing.T) {
cc := NewChainContext()
err := cc.VerifyHeader(nil, nil, false)
require.Nil(t, err)
}
func TestChainContextVerifyHeaders(t *testing.T) {
cc := NewChainContext()
ch, err := cc.VerifyHeaders(nil, nil, []bool{false})
require.Nil(t, err)
require.Nil(t, ch)
}
func TestChainContextVerifySeal(t *testing.T) {
cc := NewChainContext()
err := cc.VerifySeal(nil, nil)
require.Nil(t, err)
}
func TestChainContextVerifyUncles(t *testing.T) {
cc := NewChainContext()
err := cc.VerifyUncles(nil, nil)
require.Nil(t, err)
}

View File

@ -29,7 +29,6 @@ import (
paramtypes "github.com/cosmos/cosmos-sdk/x/params/types" paramtypes "github.com/cosmos/cosmos-sdk/x/params/types"
"github.com/cosmos/ethermint/codec" "github.com/cosmos/ethermint/codec"
"github.com/cosmos/ethermint/core"
"github.com/cosmos/ethermint/types" "github.com/cosmos/ethermint/types"
evmkeeper "github.com/cosmos/ethermint/x/evm/keeper" evmkeeper "github.com/cosmos/ethermint/x/evm/keeper"
evmtypes "github.com/cosmos/ethermint/x/evm/types" evmtypes "github.com/cosmos/ethermint/x/evm/types"
@ -226,7 +225,7 @@ func TestImportBlocks(t *testing.T) {
}() }()
// ethereum mainnet config // ethereum mainnet config
chainContext := core.NewChainContext() chainContext := NewChainContext()
vmConfig := ethvm.Config{} vmConfig := ethvm.Config{}
chainConfig := ethparams.MainnetChainConfig chainConfig := ethparams.MainnetChainConfig

View File

@ -4,6 +4,8 @@ import (
"bytes" "bytes"
ethcmn "github.com/ethereum/go-ethereum/common" ethcmn "github.com/ethereum/go-ethereum/common"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
) )
// IsEmptyHash returns true if the hash corresponds to an empty ethereum hex hash. // IsEmptyHash returns true if the hash corresponds to an empty ethereum hex hash.
@ -15,3 +17,20 @@ func IsEmptyHash(hash string) bool {
func IsZeroAddress(address string) bool { func IsZeroAddress(address string) bool {
return bytes.Equal(ethcmn.HexToAddress(address).Bytes(), ethcmn.Address{}.Bytes()) return bytes.Equal(ethcmn.HexToAddress(address).Bytes(), ethcmn.Address{}.Bytes())
} }
// ValidateAddress returns an error if the provided string is either not a hex formatted string address
// the it matches the zero address 0x00000000000000000000.
func ValidateAddress(address string) error {
if !ethcmn.IsHexAddress(address) {
return sdkerrors.Wrapf(
sdkerrors.ErrInvalidAddress, "address '%s' is not a valid ethereum hex address",
address,
)
}
if IsZeroAddress(address) {
return sdkerrors.Wrap(sdkerrors.ErrInvalidAddress, "provided address cannot be the zero address")
}
return nil
}

View File

@ -98,14 +98,14 @@ func (k Keeper) SetBlockBloom(ctx sdk.Context, height int64, bloom ethtypes.Bloo
} }
// GetBlockHash gets block height from block consensus hash // GetBlockHash gets block height from block consensus hash
func (k Keeper) GetBlockHashFromHeight(ctx sdk.Context, height int64) ([]byte, bool) { func (k Keeper) GetBlockHashFromHeight(ctx sdk.Context, height int64) (common.Hash, bool) {
store := ctx.KVStore(k.storeKey) store := ctx.KVStore(k.storeKey)
bz := store.Get(types.KeyBlockHeightHash(uint64(height))) bz := store.Get(types.KeyBlockHeightHash(uint64(height)))
if len(bz) == 0 { if len(bz) == 0 {
return common.Hash{}.Bytes(), false return common.Hash{}, false
} }
return common.BytesToHash(bz).Bytes(), true return common.BytesToHash(bz), true
} }
// SetBlockHash sets the mapping from block consensus hash to block height // SetBlockHash sets the mapping from block consensus hash to block height

View File

@ -35,7 +35,6 @@ func (k *Keeper) EthereumTx(goCtx context.Context, msg *types.MsgEthereumTx) (*t
txHash := tmtypes.Tx(ctx.TxBytes()).Hash() txHash := tmtypes.Tx(ctx.TxBytes()).Hash()
ethHash := ethcmn.BytesToHash(txHash) ethHash := ethcmn.BytesToHash(txHash)
blockHash, _ := k.GetBlockHashFromHeight(ctx, ctx.BlockHeight()) blockHash, _ := k.GetBlockHashFromHeight(ctx, ctx.BlockHeight())
ethBlockHash := ethcmn.BytesToHash(blockHash)
st := &types.StateTransition{ st := &types.StateTransition{
Message: ethMsg, Message: ethMsg,
@ -50,7 +49,7 @@ func (k *Keeper) EthereumTx(goCtx context.Context, msg *types.MsgEthereumTx) (*t
// other nodes, causing a consensus error // other nodes, causing a consensus error
if !st.Simulate { if !st.Simulate {
// Prepare db for logs // Prepare db for logs
k.Prepare(ctx, ethHash, ethBlockHash, k.TxCount) k.Prepare(ctx, ethHash, blockHash, k.TxCount)
k.TxCount++ k.TxCount++
} }
@ -62,11 +61,11 @@ func (k *Keeper) EthereumTx(goCtx context.Context, msg *types.MsgEthereumTx) (*t
if !st.Simulate { if !st.Simulate {
k.SetTxReceiptToHash(ctx, ethHash, &types.TxReceipt{ k.SetTxReceiptToHash(ctx, ethHash, &types.TxReceipt{
Hash: ethHash.Bytes(), Hash: ethHash.Hex(),
From: sender.Bytes(), From: sender.Hex(),
Data: msg.Data, Data: msg.Data,
BlockHeight: uint64(ctx.BlockHeight()), BlockHeight: uint64(ctx.BlockHeight()),
BlockHash: blockHash, BlockHash: blockHash.Hex(),
Result: &types.TxResult{ Result: &types.TxResult{
ContractAddress: executionResult.Response.ContractAddress, ContractAddress: executionResult.Response.ContractAddress,
Bloom: executionResult.Response.Bloom, Bloom: executionResult.Response.Bloom,
@ -96,12 +95,12 @@ func (k *Keeper) EthereumTx(goCtx context.Context, msg *types.MsgEthereumTx) (*t
blockHash, _ := k.GetBlockHashFromHeight(ctx, ctx.BlockHeight()) blockHash, _ := k.GetBlockHashFromHeight(ctx, ctx.BlockHeight())
k.SetTxReceiptToHash(ctx, ethHash, &types.TxReceipt{ k.SetTxReceiptToHash(ctx, ethHash, &types.TxReceipt{
Hash: ethHash.Bytes(), Hash: ethHash.Hex(),
From: sender.Bytes(), From: sender.Hex(),
Data: msg.Data, Data: msg.Data,
Index: uint64(st.Csdb.TxIndex()), Index: uint64(st.Csdb.TxIndex()),
BlockHeight: uint64(ctx.BlockHeight()), BlockHeight: uint64(ctx.BlockHeight()),
BlockHash: blockHash, BlockHash: blockHash.Hex(),
Result: &types.TxResult{ Result: &types.TxResult{
ContractAddress: executionResult.Response.ContractAddress, ContractAddress: executionResult.Response.ContractAddress,
Bloom: executionResult.Response.Bloom, Bloom: executionResult.Response.Bloom,
@ -134,11 +133,10 @@ func (k *Keeper) EthereumTx(goCtx context.Context, msg *types.MsgEthereumTx) (*t
}) })
if len(msg.Data.To) > 0 { if len(msg.Data.To) > 0 {
ethAddr := ethcmn.BytesToAddress(msg.Data.To)
ctx.EventManager().EmitEvent( ctx.EventManager().EmitEvent(
sdk.NewEvent( sdk.NewEvent(
types.EventTypeEthereumTx, types.EventTypeEthereumTx,
sdk.NewAttribute(types.AttributeKeyRecipient, ethAddr.Hex()), sdk.NewAttribute(types.AttributeKeyRecipient, msg.Data.To),
), ),
) )
} }

View File

@ -135,14 +135,18 @@ func (al *accessList) DeleteAddress(address common.Address) {
delete(al.addresses, address) delete(al.addresses, address)
} }
// AccessList is an EIP-2930 access list that represents the slice of
// the protobuf AccessTuples.
type AccessList []AccessTuple
// NewAccessList creates a new protobuf-compatible AccessList from an ethereum // NewAccessList creates a new protobuf-compatible AccessList from an ethereum
// core AccessList type // core AccessList type
func NewAccessList(ethAccessList *ethtypes.AccessList) *AccessList { func NewAccessList(ethAccessList *ethtypes.AccessList) AccessList {
if ethAccessList == nil { if ethAccessList == nil {
return nil return nil
} }
var tuples []AccessTuple var accessList AccessList
for _, tuple := range *ethAccessList { for _, tuple := range *ethAccessList {
storageKeys := make([]string, len(tuple.StorageKeys)) storageKeys := make([]string, len(tuple.StorageKeys))
@ -150,15 +154,13 @@ func NewAccessList(ethAccessList *ethtypes.AccessList) *AccessList {
storageKeys[i] = tuple.StorageKeys[i].String() storageKeys[i] = tuple.StorageKeys[i].String()
} }
tuples = append(tuples, AccessTuple{ accessList = append(accessList, AccessTuple{
Address: tuple.Address.String(), Address: tuple.Address.String(),
StorageKeys: storageKeys, StorageKeys: storageKeys,
}) })
} }
return &AccessList{ return accessList
Tuples: tuples,
}
} }
// ToEthAccessList is an utility function to convert the protobuf compatible // ToEthAccessList is an utility function to convert the protobuf compatible
@ -166,7 +168,7 @@ func NewAccessList(ethAccessList *ethtypes.AccessList) *AccessList {
func (al AccessList) ToEthAccessList() *ethtypes.AccessList { func (al AccessList) ToEthAccessList() *ethtypes.AccessList {
var accessList ethtypes.AccessList var accessList ethtypes.AccessList
for _, tuple := range al.Tuples { for _, tuple := range al {
storageKeys := make([]ethcmn.Hash, len(tuple.StorageKeys)) storageKeys := make([]ethcmn.Hash, len(tuple.StorageKeys))
for i := range tuple.StorageKeys { for i := range tuple.StorageKeys {

View File

@ -421,13 +421,13 @@ func (m *Log) GetRemoved() bool {
// TxReceipt defines the receipt type stored in KV for each EVM transaction. // TxReceipt defines the receipt type stored in KV for each EVM transaction.
type TxReceipt struct { type TxReceipt struct {
Hash []byte `protobuf:"bytes,1,opt,name=hash,proto3" json:"hash,omitempty"` Hash string `protobuf:"bytes,1,opt,name=hash,proto3" json:"hash,omitempty"`
From []byte `protobuf:"bytes,2,opt,name=from,proto3" json:"from,omitempty"` From string `protobuf:"bytes,2,opt,name=from,proto3" json:"from,omitempty"`
Data *TxData `protobuf:"bytes,3,opt,name=data,proto3" json:"data,omitempty"` Data *TxData `protobuf:"bytes,3,opt,name=data,proto3" json:"data,omitempty"`
Result *TxResult `protobuf:"bytes,4,opt,name=result,proto3" json:"result,omitempty"` Result *TxResult `protobuf:"bytes,4,opt,name=result,proto3" json:"result,omitempty"`
Index uint64 `protobuf:"varint,5,opt,name=index,proto3" json:"index,omitempty"` Index uint64 `protobuf:"varint,5,opt,name=index,proto3" json:"index,omitempty"`
BlockHeight uint64 `protobuf:"varint,6,opt,name=block_height,json=blockHeight,proto3" json:"block_height,omitempty"` BlockHeight uint64 `protobuf:"varint,6,opt,name=block_height,json=blockHeight,proto3" json:"block_height,omitempty"`
BlockHash []byte `protobuf:"bytes,7,opt,name=block_hash,json=blockHash,proto3" json:"block_hash,omitempty"` BlockHash string `protobuf:"bytes,7,opt,name=block_hash,json=blockHash,proto3" json:"block_hash,omitempty"`
} }
func (m *TxReceipt) Reset() { *m = TxReceipt{} } func (m *TxReceipt) Reset() { *m = TxReceipt{} }
@ -526,12 +526,13 @@ type TxData struct {
GasPrice []byte `protobuf:"bytes,3,opt,name=gas_price,json=gasPrice,proto3" json:"gas_price,omitempty"` GasPrice []byte `protobuf:"bytes,3,opt,name=gas_price,json=gasPrice,proto3" json:"gas_price,omitempty"`
// gas defines the gas limit defined for the transaction. // gas defines the gas limit defined for the transaction.
GasLimit uint64 `protobuf:"varint,4,opt,name=gas,proto3" json:"gas,omitempty"` GasLimit uint64 `protobuf:"varint,4,opt,name=gas,proto3" json:"gas,omitempty"`
To []byte `protobuf:"bytes,5,opt,name=to,proto3" json:"to,omitempty"` // hex formatted address of the recipient
To string `protobuf:"bytes,5,opt,name=to,proto3" json:"to,omitempty"`
// value defines the unsigned integer value of the transaction amount. // value defines the unsigned integer value of the transaction amount.
Amount []byte `protobuf:"bytes,6,opt,name=value,proto3" json:"value,omitempty"` Amount []byte `protobuf:"bytes,6,opt,name=value,proto3" json:"value,omitempty"`
// input defines the data payload bytes of the transaction. // input defines the data payload bytes of the transaction.
Input []byte `protobuf:"bytes,7,opt,name=input,proto3" json:"input,omitempty"` Input []byte `protobuf:"bytes,7,opt,name=input,proto3" json:"input,omitempty"`
Accesses *AccessList `protobuf:"bytes,8,opt,name=accesses,proto3" json:"accessList"` Accesses AccessList `protobuf:"bytes,8,rep,name=accesses,proto3,castrepeated=AccessList" json:"accessList"`
// v defines the signature value // v defines the signature value
V []byte `protobuf:"bytes,9,opt,name=v,proto3" json:"v,omitempty"` V []byte `protobuf:"bytes,9,opt,name=v,proto3" json:"v,omitempty"`
// r defines the signature value // r defines the signature value
@ -610,52 +611,6 @@ func (m *BytesList) XXX_DiscardUnknown() {
var xxx_messageInfo_BytesList proto.InternalMessageInfo var xxx_messageInfo_BytesList proto.InternalMessageInfo
// AccessList is an EIP-2930 access list defined as a proto message.
type AccessList struct {
// access list tuples
Tuples []AccessTuple `protobuf:"bytes,1,rep,name=tuples,proto3" json:"tuples"`
}
func (m *AccessList) Reset() { *m = AccessList{} }
func (m *AccessList) String() string { return proto.CompactTextString(m) }
func (*AccessList) ProtoMessage() {}
func (*AccessList) Descriptor() ([]byte, []int) {
return fileDescriptor_98f00fcca8b6b943, []int{9}
}
func (m *AccessList) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
}
func (m *AccessList) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
if deterministic {
return xxx_messageInfo_AccessList.Marshal(b, m, deterministic)
} else {
b = b[:cap(b)]
n, err := m.MarshalToSizedBuffer(b)
if err != nil {
return nil, err
}
return b[:n], nil
}
}
func (m *AccessList) XXX_Merge(src proto.Message) {
xxx_messageInfo_AccessList.Merge(m, src)
}
func (m *AccessList) XXX_Size() int {
return m.Size()
}
func (m *AccessList) XXX_DiscardUnknown() {
xxx_messageInfo_AccessList.DiscardUnknown(m)
}
var xxx_messageInfo_AccessList proto.InternalMessageInfo
func (m *AccessList) GetTuples() []AccessTuple {
if m != nil {
return m.Tuples
}
return nil
}
// AccessTuple is the element type of an access list. // AccessTuple is the element type of an access list.
type AccessTuple struct { type AccessTuple struct {
// hex formatted ethereum address // hex formatted ethereum address
@ -668,7 +623,7 @@ func (m *AccessTuple) Reset() { *m = AccessTuple{} }
func (m *AccessTuple) String() string { return proto.CompactTextString(m) } func (m *AccessTuple) String() string { return proto.CompactTextString(m) }
func (*AccessTuple) ProtoMessage() {} func (*AccessTuple) ProtoMessage() {}
func (*AccessTuple) Descriptor() ([]byte, []int) { func (*AccessTuple) Descriptor() ([]byte, []int) {
return fileDescriptor_98f00fcca8b6b943, []int{10} return fileDescriptor_98f00fcca8b6b943, []int{9}
} }
func (m *AccessTuple) XXX_Unmarshal(b []byte) error { func (m *AccessTuple) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b) return m.Unmarshal(b)
@ -707,109 +662,108 @@ func init() {
proto.RegisterType((*TxResult)(nil), "ethermint.evm.v1alpha1.TxResult") proto.RegisterType((*TxResult)(nil), "ethermint.evm.v1alpha1.TxResult")
proto.RegisterType((*TxData)(nil), "ethermint.evm.v1alpha1.TxData") proto.RegisterType((*TxData)(nil), "ethermint.evm.v1alpha1.TxData")
proto.RegisterType((*BytesList)(nil), "ethermint.evm.v1alpha1.BytesList") proto.RegisterType((*BytesList)(nil), "ethermint.evm.v1alpha1.BytesList")
proto.RegisterType((*AccessList)(nil), "ethermint.evm.v1alpha1.AccessList")
proto.RegisterType((*AccessTuple)(nil), "ethermint.evm.v1alpha1.AccessTuple") proto.RegisterType((*AccessTuple)(nil), "ethermint.evm.v1alpha1.AccessTuple")
} }
func init() { proto.RegisterFile("ethermint/evm/v1alpha1/evm.proto", fileDescriptor_98f00fcca8b6b943) } func init() { proto.RegisterFile("ethermint/evm/v1alpha1/evm.proto", fileDescriptor_98f00fcca8b6b943) }
var fileDescriptor_98f00fcca8b6b943 = []byte{ var fileDescriptor_98f00fcca8b6b943 = []byte{
// 1516 bytes of a gzipped FileDescriptorProto // 1506 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xa4, 0x57, 0xcb, 0x6f, 0x1b, 0x45, 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xa4, 0x57, 0x4b, 0x6f, 0x1b, 0x47,
0x18, 0x8f, 0x1f, 0x71, 0xec, 0xf1, 0xc6, 0x31, 0xd3, 0x10, 0xdc, 0x56, 0x78, 0xcd, 0x22, 0xd1, 0x12, 0x16, 0x1f, 0xa2, 0x86, 0xcd, 0x11, 0xc5, 0x6d, 0x6b, 0xb5, 0xb4, 0x8d, 0xe5, 0x70, 0x67,
0x20, 0xb5, 0x49, 0xe3, 0x2a, 0x22, 0xaa, 0xc4, 0xc1, 0x6e, 0xd2, 0x26, 0x6a, 0xda, 0x46, 0xd3, 0x81, 0xb5, 0x16, 0xb0, 0x25, 0x4b, 0x86, 0xb0, 0x82, 0x81, 0x3d, 0x90, 0x96, 0x6c, 0x09, 0x96,
0xd0, 0x22, 0x2e, 0xd6, 0x78, 0x3d, 0x5d, 0x2f, 0xd9, 0xdd, 0x31, 0x3b, 0x63, 0xd7, 0x46, 0x42, 0x77, 0x85, 0xb6, 0xd6, 0x5e, 0xe4, 0x42, 0x34, 0x67, 0xda, 0xc3, 0x89, 0x66, 0xa6, 0x99, 0xe9,
0xe2, 0xc8, 0x11, 0x6e, 0x1c, 0xf9, 0x2b, 0xf8, 0x1b, 0x2a, 0x4e, 0x3d, 0x22, 0x0e, 0x2b, 0xe4, 0x26, 0x4d, 0x06, 0x08, 0x90, 0x63, 0x8e, 0xc9, 0x2d, 0xc7, 0x9c, 0xf3, 0x03, 0xf2, 0x1b, 0x8c,
0x72, 0xca, 0xd1, 0x67, 0x24, 0xd0, 0x3c, 0xd6, 0x8f, 0x3c, 0x2a, 0x59, 0x39, 0x79, 0xbe, 0x6f, 0x9c, 0x7c, 0x0c, 0x72, 0x98, 0x04, 0xf4, 0x4d, 0x47, 0x5e, 0x72, 0x09, 0x90, 0xa0, 0x1f, 0x43,
0xbe, 0xf9, 0xfd, 0xe6, 0x7b, 0xce, 0x1a, 0x54, 0x08, 0x6f, 0x93, 0xd0, 0x77, 0x03, 0xbe, 0x49, 0x91, 0x7a, 0x04, 0x20, 0x74, 0x62, 0x57, 0x75, 0xf5, 0xf7, 0x75, 0x55, 0x75, 0x55, 0x0d, 0x41,
0x7a, 0xfe, 0x66, 0x6f, 0x0b, 0x7b, 0x9d, 0x36, 0xde, 0x12, 0xc2, 0x46, 0x27, 0xa4, 0x9c, 0xc2, 0x9d, 0xf0, 0x0e, 0x89, 0x43, 0x3f, 0xe2, 0x9b, 0xa4, 0x1f, 0x6e, 0xf6, 0xb7, 0x70, 0xd0, 0xed,
0xb5, 0xb1, 0xc5, 0x86, 0x50, 0xc6, 0x16, 0x37, 0x56, 0x1d, 0xea, 0x50, 0x69, 0xb2, 0x29, 0x56, 0xe0, 0x2d, 0x21, 0x6c, 0x74, 0x63, 0xca, 0x29, 0x5c, 0x9b, 0x58, 0x6c, 0x08, 0x65, 0x6a, 0x71,
0xca, 0xda, 0xfa, 0x37, 0x01, 0x32, 0x47, 0x38, 0xc4, 0x3e, 0x83, 0x5b, 0x20, 0x47, 0x7a, 0x7e, 0x67, 0xd5, 0xa3, 0x1e, 0x95, 0x26, 0x9b, 0x62, 0xa5, 0xac, 0xed, 0x5f, 0x33, 0xa0, 0x70, 0x8c,
0xa3, 0x45, 0x02, 0xea, 0x97, 0x12, 0x95, 0xc4, 0x7a, 0xae, 0xbe, 0x3a, 0x8a, 0xcc, 0xe2, 0x00, 0x63, 0x1c, 0x32, 0xb8, 0x05, 0x8a, 0xa4, 0x1f, 0xb6, 0x5c, 0x12, 0xd1, 0xb0, 0x9a, 0xa9, 0x67,
0xfb, 0xde, 0x7d, 0x6b, 0xbc, 0x65, 0xa1, 0x2c, 0xe9, 0xf9, 0xbb, 0x62, 0x09, 0xbf, 0x04, 0xcb, 0xd6, 0x8b, 0xcd, 0xd5, 0x71, 0x62, 0x55, 0x86, 0x38, 0x0c, 0x1e, 0xdb, 0x93, 0x2d, 0x1b, 0x19,
0x24, 0xc0, 0x4d, 0x8f, 0x34, 0xec, 0x90, 0x60, 0x4e, 0x4a, 0xc9, 0x4a, 0x62, 0x3d, 0x5b, 0x2f, 0xa4, 0x1f, 0xee, 0x89, 0x25, 0xfc, 0x37, 0x58, 0x26, 0x11, 0x6e, 0x07, 0xa4, 0xe5, 0xc4, 0x04,
0x8d, 0x22, 0x73, 0x55, 0x1f, 0x9b, 0xde, 0xb6, 0x90, 0xa1, 0xe4, 0x07, 0x52, 0x84, 0x5f, 0x80, 0x73, 0x52, 0xcd, 0xd6, 0x33, 0xeb, 0x46, 0xb3, 0x3a, 0x4e, 0xac, 0x55, 0x7d, 0x6c, 0x7a, 0xdb,
0x7c, 0xbc, 0x8f, 0x3d, 0xaf, 0x94, 0x92, 0x87, 0xd7, 0x46, 0x91, 0x09, 0x67, 0x0f, 0x63, 0xcf, 0x46, 0xa6, 0x92, 0x9f, 0x48, 0x11, 0xfe, 0x0b, 0x94, 0xd2, 0x7d, 0x1c, 0x04, 0xd5, 0x9c, 0x3c,
0xb3, 0x10, 0xd0, 0x47, 0xb1, 0xe7, 0xc1, 0x1a, 0x00, 0xa4, 0xcf, 0x43, 0xdc, 0x20, 0x6e, 0x87, 0xbc, 0x36, 0x4e, 0x2c, 0x38, 0x7b, 0x18, 0x07, 0x81, 0x8d, 0x80, 0x3e, 0x8a, 0x83, 0x00, 0x36,
0x95, 0xd2, 0x95, 0xd4, 0x7a, 0xaa, 0x6e, 0x0d, 0x23, 0x33, 0xb7, 0x27, 0xb4, 0x7b, 0x07, 0x47, 0x00, 0x20, 0x03, 0x1e, 0xe3, 0x16, 0xf1, 0xbb, 0xac, 0x9a, 0xaf, 0xe7, 0xd6, 0x73, 0x4d, 0x7b,
0x6c, 0x14, 0x99, 0x1f, 0x68, 0x90, 0xb1, 0xa1, 0x85, 0x72, 0x52, 0xd8, 0x73, 0x3b, 0xec, 0x7e, 0x94, 0x58, 0xc5, 0x7d, 0xa1, 0xdd, 0x3f, 0x3c, 0x66, 0xe3, 0xc4, 0xfa, 0x93, 0x06, 0x99, 0x18,
0xfa, 0xd7, 0xdf, 0xcc, 0x05, 0xeb, 0xf7, 0x65, 0x90, 0x7f, 0xd0, 0xc6, 0x6e, 0xf0, 0x80, 0x06, 0xda, 0xa8, 0x28, 0x85, 0x7d, 0xbf, 0xcb, 0x1e, 0xe7, 0xbf, 0xfe, 0xc6, 0x5a, 0xb0, 0xbf, 0x5b,
0xaf, 0x5c, 0x07, 0x7e, 0x07, 0x56, 0xda, 0xd4, 0x27, 0x8c, 0x13, 0xdc, 0x6a, 0x34, 0x3d, 0x6a, 0x06, 0xa5, 0x27, 0x1d, 0xec, 0x47, 0x4f, 0x68, 0xf4, 0xc6, 0xf7, 0xe0, 0x27, 0x60, 0xa5, 0x43,
0x9f, 0xe8, 0x48, 0xec, 0xbf, 0x89, 0xcc, 0x85, 0xbf, 0x22, 0xf3, 0x33, 0xc7, 0xe5, 0xed, 0x6e, 0x43, 0xc2, 0x38, 0xc1, 0x6e, 0xab, 0x1d, 0x50, 0xe7, 0x54, 0x47, 0xe2, 0xe0, 0x5d, 0x62, 0x2d,
0x73, 0xc3, 0xa6, 0xfe, 0xa6, 0x4d, 0x99, 0x4f, 0x99, 0xfe, 0xb9, 0xc3, 0x5a, 0x27, 0x9b, 0x7c, 0xfc, 0x98, 0x58, 0xff, 0xf0, 0x7c, 0xde, 0xe9, 0xb5, 0x37, 0x1c, 0x1a, 0x6e, 0x3a, 0x94, 0x85,
0xd0, 0x21, 0x6c, 0xe3, 0x20, 0xe0, 0xa3, 0xc8, 0x5c, 0x53, 0xf4, 0x67, 0xe0, 0x2c, 0x54, 0x18, 0x94, 0xe9, 0x9f, 0x07, 0xcc, 0x3d, 0xdd, 0xe4, 0xc3, 0x2e, 0x61, 0x1b, 0x87, 0x11, 0x1f, 0x27,
0x6b, 0xea, 0x42, 0x01, 0x7f, 0x00, 0x85, 0x16, 0xa6, 0x8d, 0x57, 0x34, 0x3c, 0xd1, 0x8c, 0x49, 0xd6, 0x9a, 0xa2, 0xbf, 0x00, 0x67, 0xa3, 0xf2, 0x44, 0xd3, 0x14, 0x0a, 0xf8, 0x19, 0x28, 0xbb,
0xc9, 0xf8, 0x72, 0x3e, 0xc6, 0x61, 0x64, 0x1a, 0xbb, 0xb5, 0x67, 0x0f, 0x69, 0x78, 0x22, 0x71, 0x98, 0xb6, 0xde, 0xd0, 0xf8, 0x54, 0x33, 0x66, 0x25, 0xe3, 0xeb, 0xf9, 0x18, 0x47, 0x89, 0x65,
0x47, 0x91, 0xf9, 0xa1, 0xba, 0xc1, 0x2c, 0xba, 0x85, 0x8c, 0x16, 0xa6, 0x63, 0x33, 0xf8, 0x12, 0xee, 0x35, 0xfe, 0xfb, 0x94, 0xc6, 0xa7, 0x12, 0x77, 0x9c, 0x58, 0x7f, 0x56, 0x37, 0x98, 0x45,
0x14, 0xc7, 0x06, 0xac, 0xdb, 0xe9, 0xd0, 0x90, 0xeb, 0x44, 0xdc, 0x19, 0x46, 0x66, 0x41, 0x43, 0xb7, 0x91, 0xe9, 0x62, 0x3a, 0x31, 0x83, 0xaf, 0x41, 0x65, 0x62, 0xc0, 0x7a, 0xdd, 0x2e, 0x8d,
0x3e, 0x57, 0x3b, 0xa3, 0xc8, 0xfc, 0xe8, 0x0c, 0xa8, 0x3e, 0x63, 0xa1, 0x82, 0x86, 0xd5, 0xa6, 0xb9, 0x4e, 0xc4, 0x83, 0x51, 0x62, 0x95, 0x35, 0xe4, 0x4b, 0xb5, 0x33, 0x4e, 0xac, 0xbf, 0x5c,
0xf0, 0x35, 0x30, 0x88, 0xdb, 0xd9, 0xda, 0xbe, 0xab, 0xbd, 0x4a, 0x4b, 0xaf, 0x8e, 0xe7, 0xf6, 0x00, 0xd5, 0x67, 0x6c, 0x54, 0xd6, 0xb0, 0xda, 0x14, 0xbe, 0x05, 0x26, 0xf1, 0xbb, 0x5b, 0x3b,
0x2a, 0xbf, 0x77, 0x70, 0xb4, 0xb5, 0x7d, 0x37, 0x76, 0xea, 0x9a, 0xce, 0xea, 0x14, 0xb4, 0x85, 0x0f, 0xb5, 0x57, 0x79, 0xe9, 0xd5, 0xc9, 0xdc, 0x5e, 0x95, 0xf6, 0x0f, 0x8f, 0xb7, 0x76, 0x1e,
0xf2, 0x4a, 0x54, 0x1e, 0x1d, 0x00, 0x2d, 0x36, 0xda, 0x98, 0xb5, 0x4b, 0x8b, 0x92, 0x77, 0x7d, 0xa6, 0x4e, 0xdd, 0xd2, 0x59, 0x9d, 0x82, 0xb6, 0x51, 0x49, 0x89, 0xca, 0xa3, 0x43, 0xa0, 0xc5,
0x18, 0x99, 0x40, 0x21, 0xed, 0x63, 0xd6, 0x9e, 0xe4, 0xa7, 0x39, 0xf8, 0x1e, 0x07, 0xdc, 0xed, 0x56, 0x07, 0xb3, 0x4e, 0x75, 0x51, 0xf2, 0xae, 0x8f, 0x12, 0x0b, 0x28, 0xa4, 0x03, 0xcc, 0x3a,
0xfa, 0x31, 0x16, 0x50, 0x87, 0x85, 0xd5, 0xd8, 0x87, 0x6d, 0xed, 0x43, 0xe6, 0x4a, 0x3e, 0x6c, 0xe7, 0xf9, 0x69, 0x0f, 0x3f, 0xc5, 0x11, 0xf7, 0x7b, 0x61, 0x8a, 0x05, 0xd4, 0x61, 0x61, 0x35,
0x5f, 0xe4, 0xc3, 0xf6, 0xac, 0x0f, 0xca, 0x66, 0x4c, 0xbc, 0xa3, 0x89, 0x97, 0xae, 0x44, 0xbc, 0xf1, 0x61, 0x47, 0xfb, 0x50, 0xb8, 0x91, 0x0f, 0x3b, 0x57, 0xf9, 0xb0, 0x33, 0xeb, 0x83, 0xb2,
0x73, 0x11, 0xf1, 0xce, 0x2c, 0xb1, 0xb2, 0x11, 0x0d, 0x70, 0x26, 0x22, 0xa5, 0xec, 0xd5, 0x1a, 0x99, 0x10, 0xef, 0x6a, 0xe2, 0xa5, 0x1b, 0x11, 0xef, 0x5e, 0x45, 0xbc, 0x3b, 0x4b, 0xac, 0x6c,
0xe0, 0x5c, 0x80, 0x0b, 0x63, 0x8d, 0xa2, 0xfc, 0x31, 0x01, 0x56, 0x6d, 0x1a, 0x30, 0x2e, 0x94, 0x44, 0x01, 0x5c, 0x88, 0x48, 0xd5, 0xb8, 0x59, 0x01, 0x5c, 0x0a, 0x70, 0x79, 0xa2, 0x51, 0x94,
0x01, 0xed, 0x78, 0x44, 0x13, 0xe7, 0x24, 0xf1, 0x93, 0xb9, 0x89, 0x6f, 0x2a, 0xe2, 0x8b, 0x30, 0x9f, 0x67, 0xc0, 0xaa, 0x43, 0x23, 0xc6, 0x85, 0x32, 0xa2, 0xdd, 0x80, 0x68, 0xe2, 0xa2, 0x24,
0x2d, 0x74, 0x6d, 0x56, 0xad, 0xae, 0xc0, 0x41, 0xb1, 0x43, 0x38, 0x09, 0x59, 0xb3, 0x1b, 0x3a, 0x7e, 0x31, 0x37, 0xf1, 0x5d, 0x45, 0x7c, 0x15, 0xa6, 0x8d, 0x6e, 0xcd, 0xaa, 0xd5, 0x15, 0x38,
0x9a, 0x1d, 0x48, 0xf6, 0x83, 0xb9, 0xd9, 0x75, 0x83, 0x9c, 0xc5, 0xb3, 0xd0, 0xca, 0x44, 0xa5, 0xa8, 0x74, 0x09, 0x27, 0x31, 0x6b, 0xf7, 0x62, 0x4f, 0xb3, 0x03, 0xc9, 0x7e, 0x38, 0x37, 0xbb,
0x58, 0x03, 0x50, 0x70, 0xc5, 0x55, 0x9a, 0x5d, 0x4f, 0x73, 0xe6, 0x25, 0xe7, 0xa3, 0xb9, 0x39, 0x2e, 0x90, 0x8b, 0x78, 0x36, 0x5a, 0x39, 0x57, 0x29, 0xd6, 0x08, 0x94, 0x7d, 0x71, 0x95, 0x76,
0x75, 0xa7, 0xcf, 0xa2, 0x59, 0x68, 0x39, 0x56, 0x28, 0xbe, 0x01, 0x80, 0x7e, 0xd7, 0x0d, 0x1b, 0x2f, 0xd0, 0x9c, 0x25, 0xc9, 0xf9, 0x6c, 0x6e, 0x4e, 0x5d, 0xe9, 0xb3, 0x68, 0x36, 0x5a, 0x4e,
0x8e, 0x87, 0x6d, 0x97, 0x84, 0x9a, 0xd3, 0x90, 0x9c, 0x8f, 0xe7, 0xe6, 0xbc, 0xae, 0x38, 0xcf, 0x15, 0x8a, 0x6f, 0x08, 0x60, 0xd8, 0xf3, 0xe3, 0x96, 0x17, 0x60, 0xc7, 0x27, 0xb1, 0xe6, 0x34,
0x23, 0x5a, 0xa8, 0x28, 0x94, 0x8f, 0x94, 0x4e, 0x51, 0x7f, 0x0b, 0x96, 0x07, 0xd4, 0xa3, 0x8d, 0x25, 0xe7, 0xf3, 0xb9, 0x39, 0x6f, 0x2b, 0xce, 0xcb, 0x88, 0x36, 0xaa, 0x08, 0xe5, 0x33, 0xa5,
0xde, 0x3d, 0xcd, 0xba, 0x2c, 0x59, 0x1f, 0xce, 0xcd, 0xaa, 0x9f, 0x95, 0x19, 0x30, 0x0b, 0xe5, 0x53, 0xd4, 0x1f, 0x83, 0xe5, 0x21, 0x0d, 0x68, 0xab, 0xff, 0x48, 0xb3, 0x2e, 0x4b, 0xd6, 0xa7,
0x85, 0xfc, 0xe2, 0x9e, 0xe2, 0x62, 0x20, 0x4f, 0x5e, 0x63, 0x16, 0x97, 0x6f, 0x41, 0x32, 0xa1, 0x73, 0xb3, 0xea, 0xb1, 0x32, 0x03, 0x66, 0xa3, 0x92, 0x90, 0x5f, 0x3d, 0x52, 0x5c, 0x0c, 0x94,
0xb9, 0x5b, 0x07, 0xec, 0xbd, 0xac, 0x3d, 0x7f, 0x12, 0x77, 0x4e, 0xfc, 0x22, 0x4d, 0x80, 0xc5, 0xc8, 0x5b, 0xcc, 0xd2, 0xe7, 0x5b, 0x96, 0x4c, 0x68, 0xee, 0xd2, 0x01, 0xfb, 0xaf, 0x1b, 0x2f,
0xa4, 0x10, 0xd2, 0x38, 0x97, 0x36, 0xe6, 0xd8, 0x1b, 0x30, 0xae, 0x79, 0x57, 0xae, 0x96, 0xcb, 0x5f, 0xa4, 0x95, 0x93, 0x4e, 0xa4, 0x73, 0x60, 0xd1, 0x29, 0x84, 0x34, 0xc9, 0xa5, 0x83, 0x39,
0x59, 0x34, 0x0b, 0x2d, 0xc7, 0x0a, 0xc9, 0x67, 0x6d, 0x82, 0xc5, 0xe7, 0x5c, 0xbc, 0xa1, 0x45, 0x0e, 0x86, 0x8c, 0x6b, 0xde, 0x95, 0x9b, 0xe5, 0x72, 0x16, 0xcd, 0x46, 0xcb, 0xa9, 0x42, 0xf2,
0x90, 0x3a, 0x21, 0x03, 0xf5, 0x4a, 0x21, 0xb1, 0x84, 0xab, 0x60, 0xb1, 0x87, 0xbd, 0xae, 0x7a, 0xd9, 0x9b, 0x60, 0xf1, 0x25, 0x17, 0x33, 0xb4, 0x02, 0x72, 0xa7, 0x64, 0xa8, 0xa6, 0x14, 0x12,
0x8c, 0x73, 0x48, 0x09, 0xd6, 0x0b, 0xb0, 0x72, 0x1c, 0xe2, 0x80, 0x61, 0x9b, 0xbb, 0x34, 0x38, 0x4b, 0xb8, 0x0a, 0x16, 0xfb, 0x38, 0xe8, 0xa9, 0x61, 0x5c, 0x44, 0x4a, 0xb0, 0x5f, 0x81, 0x95,
0xa4, 0x0e, 0x83, 0x10, 0xa4, 0xe5, 0x84, 0x54, 0x67, 0xe5, 0x1a, 0x6e, 0x82, 0xb4, 0x47, 0x1d, 0x93, 0x18, 0x47, 0x0c, 0x3b, 0xdc, 0xa7, 0xd1, 0x11, 0xf5, 0x18, 0x84, 0x20, 0x2f, 0x3b, 0xa4,
0x56, 0x4a, 0x56, 0x52, 0xeb, 0xf9, 0xea, 0xcd, 0x8d, 0x8b, 0x3f, 0x26, 0x36, 0x0e, 0xa9, 0x83, 0x3a, 0x2b, 0xd7, 0x70, 0x13, 0xe4, 0x03, 0xea, 0xb1, 0x6a, 0xb6, 0x9e, 0x5b, 0x2f, 0x6d, 0xdf,
0xa4, 0xa1, 0xf5, 0x47, 0x12, 0xa4, 0x0e, 0xa9, 0x03, 0x4b, 0x60, 0x09, 0xb7, 0x5a, 0x21, 0x61, 0xdd, 0xb8, 0xfa, 0x63, 0x62, 0xe3, 0x88, 0x7a, 0x48, 0x1a, 0xda, 0xdf, 0x67, 0x41, 0xee, 0x88,
0x4c, 0xe3, 0xc5, 0x22, 0x5c, 0x03, 0x19, 0x4e, 0x3b, 0xae, 0xad, 0x40, 0x73, 0x48, 0x4b, 0x82, 0x7a, 0xb0, 0x0a, 0x96, 0xb0, 0xeb, 0xc6, 0x84, 0x31, 0x8d, 0x97, 0x8a, 0x70, 0x0d, 0x14, 0x38,
0xbe, 0x85, 0x39, 0x96, 0xaf, 0x8d, 0x81, 0xe4, 0x1a, 0x56, 0x81, 0x21, 0xfd, 0x6d, 0x04, 0x5d, 0xed, 0xfa, 0x8e, 0x02, 0x2d, 0x22, 0x2d, 0x09, 0x7a, 0x17, 0x73, 0x2c, 0xa7, 0x8d, 0x89, 0xe4,
0xbf, 0x49, 0x42, 0xf9, 0x68, 0xa4, 0xeb, 0x2b, 0xa7, 0x91, 0x99, 0x97, 0xfa, 0xa7, 0x52, 0x8d, 0x1a, 0x6e, 0x03, 0x53, 0xfa, 0xdb, 0x8a, 0x7a, 0x61, 0x9b, 0xc4, 0x72, 0x68, 0xe4, 0x9b, 0x2b,
0xa6, 0x05, 0x78, 0x1b, 0x2c, 0xf1, 0xfe, 0xf4, 0xac, 0xbf, 0x76, 0x1a, 0x99, 0x2b, 0x7c, 0xe2, 0x67, 0x89, 0x55, 0x92, 0xfa, 0xff, 0x48, 0x35, 0x9a, 0x16, 0xe0, 0x7d, 0xb0, 0xc4, 0x07, 0xd3,
0xac, 0x18, 0xe5, 0x28, 0xc3, 0xfb, 0xfb, 0xca, 0xc1, 0x2c, 0xef, 0x37, 0xdc, 0xa0, 0x45, 0xfa, 0xbd, 0xfe, 0xd6, 0x59, 0x62, 0xad, 0xf0, 0x73, 0x67, 0x45, 0x2b, 0x47, 0x05, 0x3e, 0x38, 0x50,
0x72, 0x9c, 0xa7, 0xeb, 0xab, 0xa7, 0x91, 0x59, 0x9c, 0x32, 0x3f, 0x10, 0x7b, 0x68, 0x89, 0xf7, 0x0e, 0x1a, 0x7c, 0xd0, 0xf2, 0x23, 0x97, 0x0c, 0x64, 0x3b, 0xcf, 0x37, 0x57, 0xcf, 0x12, 0xab,
0xe5, 0x02, 0xde, 0x06, 0x40, 0x5d, 0x49, 0x32, 0xa8, 0x41, 0xbc, 0x7c, 0x1a, 0x99, 0x39, 0xa9, 0x32, 0x65, 0x7e, 0x28, 0xf6, 0xd0, 0x12, 0x1f, 0xc8, 0x05, 0xbc, 0x0f, 0x80, 0xba, 0x92, 0x64,
0x95, 0xd8, 0x93, 0x25, 0xb4, 0xc0, 0xa2, 0xc2, 0xce, 0x4a, 0x6c, 0xe3, 0x34, 0x32, 0xb3, 0x1e, 0x50, 0x8d, 0x78, 0xf9, 0x2c, 0xb1, 0x8a, 0x52, 0x2b, 0xb1, 0xcf, 0x97, 0xd0, 0x06, 0x8b, 0x0a,
0x75, 0x14, 0xa6, 0xda, 0x12, 0xa1, 0x0a, 0x89, 0x4f, 0x7b, 0xa4, 0x25, 0x47, 0x5c, 0x16, 0xc5, 0xdb, 0x90, 0xd8, 0xe6, 0x59, 0x62, 0x19, 0x01, 0xf5, 0x14, 0xa6, 0xda, 0x12, 0xa1, 0x8a, 0x49,
0xa2, 0xf5, 0x5f, 0x02, 0xe4, 0x8e, 0xfb, 0x88, 0xd8, 0xc4, 0xed, 0xf0, 0x99, 0xfc, 0x18, 0x3a, 0x48, 0xfb, 0xc4, 0x95, 0x2d, 0xce, 0x40, 0xa9, 0x68, 0xff, 0x96, 0x01, 0xc5, 0x93, 0x01, 0x22,
0x3f, 0x10, 0xa4, 0x5f, 0x85, 0xd4, 0x97, 0xb9, 0x35, 0x90, 0x5c, 0xc3, 0xea, 0x54, 0x20, 0xf3, 0x0e, 0xf1, 0xbb, 0xfc, 0xca, 0xfc, 0x40, 0x90, 0x7f, 0x13, 0xd3, 0x50, 0xe7, 0x56, 0xae, 0xe1,
0xd5, 0xf2, 0x65, 0x39, 0x3b, 0xee, 0xef, 0x62, 0x8e, 0x75, 0xa0, 0x77, 0x40, 0x26, 0x24, 0xac, 0xf6, 0x54, 0x20, 0x4b, 0xdb, 0xb5, 0xeb, 0x72, 0x76, 0x32, 0xd8, 0xc3, 0x1c, 0xeb, 0x40, 0xef,
0xeb, 0x71, 0x19, 0xe2, 0x7c, 0xb5, 0x72, 0xf9, 0x29, 0x24, 0xed, 0x90, 0xb6, 0x17, 0xe5, 0xa5, 0x82, 0x42, 0x4c, 0x58, 0x2f, 0xe0, 0x32, 0xc4, 0xa5, 0xed, 0xfa, 0xf5, 0xa7, 0x90, 0xb4, 0x43,
0x3c, 0x14, 0xc1, 0x4e, 0xc7, 0x3e, 0x7d, 0x12, 0x27, 0xae, 0x4d, 0x5c, 0xa7, 0xcd, 0x55, 0x68, 0xda, 0x5e, 0x3c, 0x2f, 0xe5, 0xa1, 0x08, 0x76, 0x3e, 0xf5, 0xe9, 0x6f, 0x69, 0xe2, 0x3a, 0xc4,
0x75, 0x9e, 0xf6, 0xa5, 0x0a, 0x7e, 0x7c, 0x2e, 0x90, 0xc6, 0x54, 0xe4, 0xee, 0xa7, 0x7f, 0x12, 0xf7, 0x3a, 0x5c, 0x85, 0x56, 0xe7, 0xe9, 0x40, 0xaa, 0xe0, 0x5f, 0x2f, 0x07, 0x72, 0x2a, 0x72,
0x1f, 0x64, 0xbf, 0x24, 0x41, 0x36, 0xa6, 0x84, 0x0f, 0x41, 0xd1, 0xa6, 0x01, 0x0f, 0xb1, 0xcd, 0x8f, 0xf3, 0x5f, 0x88, 0x0f, 0xb2, 0xaf, 0xb2, 0xc0, 0x48, 0x29, 0xe1, 0x53, 0x50, 0x71, 0x68,
0x1b, 0x33, 0xc5, 0x55, 0xbf, 0x39, 0x19, 0xb4, 0x67, 0x2d, 0x2c, 0xb4, 0x12, 0xab, 0x6a, 0xba, 0xc4, 0x63, 0xec, 0xf0, 0xd6, 0xcc, 0xe3, 0x6a, 0xde, 0x3d, 0x6f, 0xb4, 0x17, 0x2d, 0x6c, 0xb4,
0x02, 0x57, 0xc1, 0x62, 0xd3, 0xa3, 0xe3, 0xa8, 0x29, 0x01, 0x7e, 0x2d, 0xeb, 0x46, 0x56, 0xbb, 0x92, 0xaa, 0x1a, 0xfa, 0x05, 0xae, 0x82, 0xc5, 0x76, 0x40, 0x75, 0xd4, 0x4c, 0xa4, 0x04, 0xf8,
0x8a, 0xdc, 0xad, 0x4b, 0x63, 0x30, 0xdb, 0x38, 0xf5, 0x35, 0xd1, 0xd4, 0xa3, 0xc8, 0x2c, 0xa8, 0x7f, 0xf9, 0x6e, 0xe4, 0x6b, 0x57, 0x91, 0xbb, 0x77, 0x6d, 0x0c, 0x66, 0x0b, 0xa7, 0xb9, 0x26,
0x1b, 0x68, 0x14, 0x4b, 0xd4, 0x98, 0x6c, 0xac, 0x22, 0x48, 0x85, 0x44, 0x45, 0xd6, 0x40, 0x62, 0x8a, 0x7a, 0x9c, 0x58, 0x65, 0x75, 0x03, 0x8d, 0x62, 0x8b, 0x37, 0x26, 0x0b, 0xab, 0x02, 0x72,
0x09, 0x6f, 0x80, 0x6c, 0x48, 0x7a, 0x24, 0xe4, 0xa4, 0x25, 0xe3, 0x96, 0x45, 0x63, 0x19, 0x5e, 0x31, 0x51, 0x91, 0x35, 0x91, 0x58, 0xc2, 0x3b, 0xc0, 0x88, 0x49, 0x9f, 0xc4, 0x9c, 0xb8, 0x32,
0x07, 0x59, 0x07, 0xb3, 0x46, 0x97, 0x91, 0x96, 0x0e, 0xdb, 0x92, 0x83, 0xd9, 0x57, 0x8c, 0xb4, 0x6e, 0x06, 0x9a, 0xc8, 0xf0, 0x36, 0x30, 0x3c, 0xcc, 0x5a, 0x3d, 0x46, 0x5c, 0x1d, 0xb6, 0x25,
0x74, 0x4c, 0xfe, 0x49, 0x82, 0x8c, 0x4a, 0x1e, 0xdc, 0x02, 0x59, 0x5b, 0x7c, 0xae, 0x36, 0xdc, 0x0f, 0xb3, 0xff, 0x31, 0xe2, 0xea, 0x98, 0xfc, 0x92, 0x05, 0x05, 0x95, 0x3c, 0xb8, 0x05, 0x0c,
0x96, 0x2a, 0x8b, 0xfa, 0xda, 0x30, 0x32, 0x97, 0xe4, 0x27, 0xec, 0xc1, 0xee, 0x69, 0x64, 0x2e, 0x47, 0x7c, 0xae, 0xb6, 0x7c, 0x57, 0x46, 0xc2, 0x6c, 0xae, 0x8d, 0x12, 0x6b, 0x49, 0x7e, 0xc2,
0xd9, 0x6a, 0x89, 0xf4, 0xa2, 0x25, 0x9c, 0x0f, 0x68, 0x60, 0xab, 0x71, 0x90, 0x46, 0x4a, 0x80, 0x1e, 0xee, 0x9d, 0x25, 0xd6, 0x92, 0xa3, 0x96, 0x48, 0x2f, 0x5c, 0xe1, 0x7c, 0x44, 0x23, 0x47,
0x9f, 0x83, 0x9c, 0x20, 0xed, 0x84, 0xae, 0x4d, 0x54, 0x07, 0xd6, 0x8d, 0x61, 0x64, 0x66, 0x1f, 0xb5, 0x83, 0x3c, 0x52, 0x02, 0xfc, 0x27, 0x28, 0x0a, 0xd2, 0x6e, 0xec, 0x3b, 0x44, 0x55, 0x60,
0x61, 0x76, 0x24, 0x74, 0x48, 0xdc, 0x49, 0xae, 0x60, 0x19, 0xa4, 0x1c, 0xcc, 0x74, 0x2b, 0xc6, 0xd3, 0x1c, 0x25, 0x96, 0xf1, 0x0c, 0xb3, 0x63, 0xa1, 0x43, 0xe2, 0x4e, 0x72, 0x05, 0x6b, 0x20,
0x46, 0x87, 0xae, 0xef, 0x72, 0x24, 0x36, 0x60, 0x01, 0x24, 0x39, 0x95, 0x5e, 0x19, 0x28, 0xc9, 0xe7, 0x61, 0xa6, 0x4b, 0x31, 0x35, 0x3a, 0xf2, 0x43, 0x9f, 0x23, 0xb1, 0x01, 0xcb, 0x20, 0xcb,
0x29, 0xac, 0xc4, 0xf3, 0x27, 0x23, 0x61, 0xc1, 0x30, 0x32, 0x33, 0x35, 0x9f, 0x76, 0x03, 0xae, 0xa9, 0x2a, 0x3d, 0x94, 0xe5, 0x14, 0xd6, 0xd3, 0xfe, 0x53, 0x90, 0xb0, 0x60, 0x94, 0x58, 0x85,
0x67, 0x91, 0x2a, 0xa1, 0x4e, 0x97, 0xeb, 0x22, 0x50, 0x02, 0x7c, 0x0a, 0xb2, 0xd8, 0xb6, 0x09, 0x46, 0x48, 0x7b, 0x11, 0xd7, 0xbd, 0x48, 0x3d, 0xa1, 0x6e, 0x8f, 0xcb, 0x47, 0x60, 0x22, 0x25,
0x63, 0x84, 0xc9, 0xee, 0xc9, 0x57, 0xad, 0xcb, 0x12, 0x52, 0x93, 0x76, 0x87, 0x2e, 0xe3, 0xf5, 0x40, 0x0c, 0x0c, 0xec, 0x38, 0x84, 0x31, 0xc2, 0xaa, 0x86, 0x6c, 0x3f, 0x7f, 0xbf, 0x2e, 0x21,
0xc2, 0x69, 0x64, 0x02, 0x3c, 0x96, 0xd1, 0x18, 0x03, 0x1a, 0x20, 0xd1, 0x93, 0x0d, 0x66, 0xa0, 0x0d, 0x69, 0x77, 0xd2, 0x13, 0x03, 0xbc, 0x2e, 0x92, 0x71, 0x96, 0x58, 0x40, 0x1d, 0x3e, 0xf2,
0x44, 0x4f, 0x48, 0xa1, 0x7c, 0xd3, 0x0d, 0x94, 0x08, 0x85, 0xc4, 0xe4, 0x6b, 0x6b, 0xa0, 0x04, 0x19, 0xff, 0xf6, 0x27, 0x0b, 0x34, 0x26, 0x12, 0x9a, 0xc0, 0x42, 0x13, 0x64, 0xfa, 0xb2, 0xe6,
0xd3, 0x61, 0xbe, 0x05, 0x72, 0xf5, 0x01, 0x27, 0x12, 0x46, 0x96, 0x8c, 0x10, 0x4a, 0x89, 0x4a, 0x4c, 0x94, 0xe9, 0x0b, 0x29, 0x96, 0x63, 0xde, 0x44, 0x99, 0x58, 0x48, 0x4c, 0x0e, 0x60, 0x13,
0x4a, 0x96, 0x8c, 0x10, 0xb4, 0xe1, 0x33, 0x00, 0x26, 0x17, 0x80, 0x35, 0x90, 0xe1, 0xdd, 0x8e, 0x65, 0x98, 0x8e, 0xfc, 0x3d, 0x50, 0x6c, 0x0e, 0x39, 0x91, 0x30, 0xf2, 0x15, 0x09, 0xa1, 0x9a,
0xa7, 0x4d, 0xf3, 0xd5, 0x4f, 0xdf, 0x7f, 0xe9, 0x63, 0x61, 0x5b, 0x4f, 0x8b, 0x0a, 0x42, 0xfa, 0xa9, 0xe7, 0xe4, 0x2b, 0x12, 0x82, 0x36, 0xc4, 0xa0, 0x34, 0x75, 0xa7, 0x3f, 0x68, 0x86, 0xdb,
0xa0, 0x85, 0x41, 0x7e, 0x6a, 0xf3, 0x3d, 0xa3, 0xb4, 0x0a, 0x0c, 0xc6, 0x69, 0x88, 0x1d, 0xd2, 0xc0, 0x64, 0x9c, 0xc6, 0xd8, 0x23, 0xad, 0x53, 0x32, 0xd4, 0x2d, 0x51, 0x35, 0x38, 0xad, 0x7f,
0x38, 0x21, 0x03, 0x3d, 0x50, 0xd5, 0x78, 0xd4, 0xfa, 0xc7, 0x64, 0xc0, 0xd0, 0xb4, 0xa0, 0xee, 0x4e, 0x86, 0x0c, 0x4d, 0x0b, 0x8a, 0xa2, 0xd9, 0x78, 0x37, 0xaa, 0x65, 0xde, 0x8f, 0x6a, 0x99,
0x5c, 0xaf, 0xbd, 0x19, 0x96, 0x13, 0x6f, 0x87, 0xe5, 0xc4, 0xdf, 0xc3, 0x72, 0xe2, 0xe7, 0x77, 0x9f, 0x47, 0xb5, 0xcc, 0x97, 0x1f, 0x6a, 0x0b, 0xef, 0x3f, 0xd4, 0x16, 0x7e, 0xf8, 0x50, 0x5b,
0xe5, 0x85, 0xb7, 0xef, 0xca, 0x0b, 0x7f, 0xbe, 0x2b, 0x2f, 0x7c, 0x73, 0xeb, 0xfc, 0xcb, 0x34, 0xf8, 0xe8, 0xde, 0xe5, 0xd9, 0x72, 0xfe, 0x2f, 0x71, 0x20, 0xff, 0x27, 0xca, 0x01, 0xd3, 0x2e,
0xf9, 0x8f, 0xd9, 0x97, 0xff, 0x32, 0xe5, 0xf3, 0xd4, 0xcc, 0xc8, 0x7f, 0x8c, 0xf7, 0xfe, 0x0f, 0xc8, 0xff, 0x7c, 0x8f, 0x7e, 0x0f, 0x00, 0x00, 0xff, 0xff, 0xf2, 0x3d, 0x7c, 0x52, 0x45, 0x0e,
0x00, 0x00, 0xff, 0xff, 0xfa, 0x12, 0x92, 0x0e, 0x83, 0x0e, 0x00, 0x00, 0x00, 0x00,
} }
func (m *Params) Marshal() (dAtA []byte, err error) { func (m *Params) Marshal() (dAtA []byte, err error) {
@ -1405,17 +1359,19 @@ func (m *TxData) MarshalToSizedBuffer(dAtA []byte) (int, error) {
i-- i--
dAtA[i] = 0x4a dAtA[i] = 0x4a
} }
if m.Accesses != nil { if len(m.Accesses) > 0 {
{ for iNdEx := len(m.Accesses) - 1; iNdEx >= 0; iNdEx-- {
size, err := m.Accesses.MarshalToSizedBuffer(dAtA[:i]) {
if err != nil { size, err := m.Accesses[iNdEx].MarshalToSizedBuffer(dAtA[:i])
return 0, err if err != nil {
return 0, err
}
i -= size
i = encodeVarintEvm(dAtA, i, uint64(size))
} }
i -= size i--
i = encodeVarintEvm(dAtA, i, uint64(size)) dAtA[i] = 0x42
} }
i--
dAtA[i] = 0x42
} }
if len(m.Input) > 0 { if len(m.Input) > 0 {
i -= len(m.Input) i -= len(m.Input)
@ -1497,43 +1453,6 @@ func (m *BytesList) MarshalToSizedBuffer(dAtA []byte) (int, error) {
return len(dAtA) - i, nil return len(dAtA) - i, nil
} }
func (m *AccessList) Marshal() (dAtA []byte, err error) {
size := m.Size()
dAtA = make([]byte, size)
n, err := m.MarshalToSizedBuffer(dAtA[:size])
if err != nil {
return nil, err
}
return dAtA[:n], nil
}
func (m *AccessList) MarshalTo(dAtA []byte) (int, error) {
size := m.Size()
return m.MarshalToSizedBuffer(dAtA[:size])
}
func (m *AccessList) MarshalToSizedBuffer(dAtA []byte) (int, error) {
i := len(dAtA)
_ = i
var l int
_ = l
if len(m.Tuples) > 0 {
for iNdEx := len(m.Tuples) - 1; iNdEx >= 0; iNdEx-- {
{
size, err := m.Tuples[iNdEx].MarshalToSizedBuffer(dAtA[:i])
if err != nil {
return 0, err
}
i -= size
i = encodeVarintEvm(dAtA, i, uint64(size))
}
i--
dAtA[i] = 0xa
}
}
return len(dAtA) - i, nil
}
func (m *AccessTuple) Marshal() (dAtA []byte, err error) { func (m *AccessTuple) Marshal() (dAtA []byte, err error) {
size := m.Size() size := m.Size()
dAtA = make([]byte, size) dAtA = make([]byte, size)
@ -1827,9 +1746,11 @@ func (m *TxData) Size() (n int) {
if l > 0 { if l > 0 {
n += 1 + l + sovEvm(uint64(l)) n += 1 + l + sovEvm(uint64(l))
} }
if m.Accesses != nil { if len(m.Accesses) > 0 {
l = m.Accesses.Size() for _, e := range m.Accesses {
n += 1 + l + sovEvm(uint64(l)) l = e.Size()
n += 1 + l + sovEvm(uint64(l))
}
} }
l = len(m.V) l = len(m.V)
if l > 0 { if l > 0 {
@ -1861,21 +1782,6 @@ func (m *BytesList) Size() (n int) {
return n return n
} }
func (m *AccessList) Size() (n int) {
if m == nil {
return 0
}
var l int
_ = l
if len(m.Tuples) > 0 {
for _, e := range m.Tuples {
l = e.Size()
n += 1 + l + sovEvm(uint64(l))
}
}
return n
}
func (m *AccessTuple) Size() (n int) { func (m *AccessTuple) Size() (n int) {
if m == nil { if m == nil {
return 0 return 0
@ -3210,7 +3116,7 @@ func (m *TxReceipt) Unmarshal(dAtA []byte) error {
if wireType != 2 { if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field Hash", wireType) return fmt.Errorf("proto: wrong wireType = %d for field Hash", wireType)
} }
var byteLen int var stringLen uint64
for shift := uint(0); ; shift += 7 { for shift := uint(0); ; shift += 7 {
if shift >= 64 { if shift >= 64 {
return ErrIntOverflowEvm return ErrIntOverflowEvm
@ -3220,31 +3126,29 @@ func (m *TxReceipt) Unmarshal(dAtA []byte) error {
} }
b := dAtA[iNdEx] b := dAtA[iNdEx]
iNdEx++ iNdEx++
byteLen |= int(b&0x7F) << shift stringLen |= uint64(b&0x7F) << shift
if b < 0x80 { if b < 0x80 {
break break
} }
} }
if byteLen < 0 { intStringLen := int(stringLen)
if intStringLen < 0 {
return ErrInvalidLengthEvm return ErrInvalidLengthEvm
} }
postIndex := iNdEx + byteLen postIndex := iNdEx + intStringLen
if postIndex < 0 { if postIndex < 0 {
return ErrInvalidLengthEvm return ErrInvalidLengthEvm
} }
if postIndex > l { if postIndex > l {
return io.ErrUnexpectedEOF return io.ErrUnexpectedEOF
} }
m.Hash = append(m.Hash[:0], dAtA[iNdEx:postIndex]...) m.Hash = string(dAtA[iNdEx:postIndex])
if m.Hash == nil {
m.Hash = []byte{}
}
iNdEx = postIndex iNdEx = postIndex
case 2: case 2:
if wireType != 2 { if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field From", wireType) return fmt.Errorf("proto: wrong wireType = %d for field From", wireType)
} }
var byteLen int var stringLen uint64
for shift := uint(0); ; shift += 7 { for shift := uint(0); ; shift += 7 {
if shift >= 64 { if shift >= 64 {
return ErrIntOverflowEvm return ErrIntOverflowEvm
@ -3254,25 +3158,23 @@ func (m *TxReceipt) Unmarshal(dAtA []byte) error {
} }
b := dAtA[iNdEx] b := dAtA[iNdEx]
iNdEx++ iNdEx++
byteLen |= int(b&0x7F) << shift stringLen |= uint64(b&0x7F) << shift
if b < 0x80 { if b < 0x80 {
break break
} }
} }
if byteLen < 0 { intStringLen := int(stringLen)
if intStringLen < 0 {
return ErrInvalidLengthEvm return ErrInvalidLengthEvm
} }
postIndex := iNdEx + byteLen postIndex := iNdEx + intStringLen
if postIndex < 0 { if postIndex < 0 {
return ErrInvalidLengthEvm return ErrInvalidLengthEvm
} }
if postIndex > l { if postIndex > l {
return io.ErrUnexpectedEOF return io.ErrUnexpectedEOF
} }
m.From = append(m.From[:0], dAtA[iNdEx:postIndex]...) m.From = string(dAtA[iNdEx:postIndex])
if m.From == nil {
m.From = []byte{}
}
iNdEx = postIndex iNdEx = postIndex
case 3: case 3:
if wireType != 2 { if wireType != 2 {
@ -3388,7 +3290,7 @@ func (m *TxReceipt) Unmarshal(dAtA []byte) error {
if wireType != 2 { if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field BlockHash", wireType) return fmt.Errorf("proto: wrong wireType = %d for field BlockHash", wireType)
} }
var byteLen int var stringLen uint64
for shift := uint(0); ; shift += 7 { for shift := uint(0); ; shift += 7 {
if shift >= 64 { if shift >= 64 {
return ErrIntOverflowEvm return ErrIntOverflowEvm
@ -3398,25 +3300,23 @@ func (m *TxReceipt) Unmarshal(dAtA []byte) error {
} }
b := dAtA[iNdEx] b := dAtA[iNdEx]
iNdEx++ iNdEx++
byteLen |= int(b&0x7F) << shift stringLen |= uint64(b&0x7F) << shift
if b < 0x80 { if b < 0x80 {
break break
} }
} }
if byteLen < 0 { intStringLen := int(stringLen)
if intStringLen < 0 {
return ErrInvalidLengthEvm return ErrInvalidLengthEvm
} }
postIndex := iNdEx + byteLen postIndex := iNdEx + intStringLen
if postIndex < 0 { if postIndex < 0 {
return ErrInvalidLengthEvm return ErrInvalidLengthEvm
} }
if postIndex > l { if postIndex > l {
return io.ErrUnexpectedEOF return io.ErrUnexpectedEOF
} }
m.BlockHash = append(m.BlockHash[:0], dAtA[iNdEx:postIndex]...) m.BlockHash = string(dAtA[iNdEx:postIndex])
if m.BlockHash == nil {
m.BlockHash = []byte{}
}
iNdEx = postIndex iNdEx = postIndex
default: default:
iNdEx = preIndex iNdEx = preIndex
@ -3806,7 +3706,7 @@ func (m *TxData) Unmarshal(dAtA []byte) error {
if wireType != 2 { if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field To", wireType) return fmt.Errorf("proto: wrong wireType = %d for field To", wireType)
} }
var byteLen int var stringLen uint64
for shift := uint(0); ; shift += 7 { for shift := uint(0); ; shift += 7 {
if shift >= 64 { if shift >= 64 {
return ErrIntOverflowEvm return ErrIntOverflowEvm
@ -3816,25 +3716,23 @@ func (m *TxData) Unmarshal(dAtA []byte) error {
} }
b := dAtA[iNdEx] b := dAtA[iNdEx]
iNdEx++ iNdEx++
byteLen |= int(b&0x7F) << shift stringLen |= uint64(b&0x7F) << shift
if b < 0x80 { if b < 0x80 {
break break
} }
} }
if byteLen < 0 { intStringLen := int(stringLen)
if intStringLen < 0 {
return ErrInvalidLengthEvm return ErrInvalidLengthEvm
} }
postIndex := iNdEx + byteLen postIndex := iNdEx + intStringLen
if postIndex < 0 { if postIndex < 0 {
return ErrInvalidLengthEvm return ErrInvalidLengthEvm
} }
if postIndex > l { if postIndex > l {
return io.ErrUnexpectedEOF return io.ErrUnexpectedEOF
} }
m.To = append(m.To[:0], dAtA[iNdEx:postIndex]...) m.To = string(dAtA[iNdEx:postIndex])
if m.To == nil {
m.To = []byte{}
}
iNdEx = postIndex iNdEx = postIndex
case 6: case 6:
if wireType != 2 { if wireType != 2 {
@ -3933,10 +3831,8 @@ func (m *TxData) Unmarshal(dAtA []byte) error {
if postIndex > l { if postIndex > l {
return io.ErrUnexpectedEOF return io.ErrUnexpectedEOF
} }
if m.Accesses == nil { m.Accesses = append(m.Accesses, AccessTuple{})
m.Accesses = &AccessList{} if err := m.Accesses[len(m.Accesses)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
}
if err := m.Accesses.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
return err return err
} }
iNdEx = postIndex iNdEx = postIndex
@ -4151,93 +4047,6 @@ func (m *BytesList) Unmarshal(dAtA []byte) error {
} }
return nil return nil
} }
func (m *AccessList) Unmarshal(dAtA []byte) error {
l := len(dAtA)
iNdEx := 0
for iNdEx < l {
preIndex := iNdEx
var wire uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowEvm
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
wire |= uint64(b&0x7F) << shift
if b < 0x80 {
break
}
}
fieldNum := int32(wire >> 3)
wireType := int(wire & 0x7)
if wireType == 4 {
return fmt.Errorf("proto: AccessList: wiretype end group for non-group")
}
if fieldNum <= 0 {
return fmt.Errorf("proto: AccessList: illegal tag %d (wire type %d)", fieldNum, wire)
}
switch fieldNum {
case 1:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field Tuples", wireType)
}
var msglen int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowEvm
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
msglen |= int(b&0x7F) << shift
if b < 0x80 {
break
}
}
if msglen < 0 {
return ErrInvalidLengthEvm
}
postIndex := iNdEx + msglen
if postIndex < 0 {
return ErrInvalidLengthEvm
}
if postIndex > l {
return io.ErrUnexpectedEOF
}
m.Tuples = append(m.Tuples, AccessTuple{})
if err := m.Tuples[len(m.Tuples)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
return err
}
iNdEx = postIndex
default:
iNdEx = preIndex
skippy, err := skipEvm(dAtA[iNdEx:])
if err != nil {
return err
}
if skippy < 0 {
return ErrInvalidLengthEvm
}
if (iNdEx + skippy) < 0 {
return ErrInvalidLengthEvm
}
if (iNdEx + skippy) > l {
return io.ErrUnexpectedEOF
}
iNdEx += skippy
}
}
if iNdEx > l {
return io.ErrUnexpectedEOF
}
return nil
}
func (m *AccessTuple) Unmarshal(dAtA []byte) error { func (m *AccessTuple) Unmarshal(dAtA []byte) error {
l := len(dAtA) l := len(dAtA)
iNdEx := 0 iNdEx := 0

View File

@ -8,6 +8,7 @@ import (
"github.com/cosmos/cosmos-sdk/crypto/keyring" "github.com/cosmos/cosmos-sdk/crypto/keyring"
sdk "github.com/cosmos/cosmos-sdk/types" sdk "github.com/cosmos/cosmos-sdk/types"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
"github.com/cosmos/ethermint/types"
ethcmn "github.com/ethereum/go-ethereum/common" ethcmn "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/core"
@ -52,9 +53,9 @@ func newMsgEthereumTx(
input = ethcmn.CopyBytes(input) input = ethcmn.CopyBytes(input)
} }
var toBz []byte var toHex string
if to != nil { if to != nil {
toBz = to.Bytes() toHex = to.Hex()
} }
var chainIDBz []byte var chainIDBz []byte
@ -65,7 +66,7 @@ func newMsgEthereumTx(
txData := &TxData{ txData := &TxData{
ChainID: chainIDBz, ChainID: chainIDBz,
Nonce: nonce, Nonce: nonce,
To: toBz, To: toHex,
Input: input, Input: input,
GasLimit: gasLimit, GasLimit: gasLimit,
Amount: []byte{}, Amount: []byte{},
@ -106,17 +107,29 @@ func (msg MsgEthereumTx) ValidateBasic() error {
return sdkerrors.Wrapf(ErrInvalidValue, "amount cannot be negative %s", amount) return sdkerrors.Wrapf(ErrInvalidValue, "amount cannot be negative %s", amount)
} }
if msg.Data.To != "" {
if err := types.ValidateAddress(msg.Data.To); err != nil {
return sdkerrors.Wrap(err, "invalid to address")
}
}
if msg.From != "" {
if err := types.ValidateAddress(msg.From); err != nil {
return sdkerrors.Wrap(err, "invalid from address")
}
}
return nil return nil
} }
// To returns the recipient address of the transaction. It returns nil if the // To returns the recipient address of the transaction. It returns nil if the
// transaction is a contract creation. // transaction is a contract creation.
func (msg MsgEthereumTx) To() *ethcmn.Address { func (msg MsgEthereumTx) To() *ethcmn.Address {
if len(msg.Data.To) == 0 { if msg.Data.To == "" {
return nil return nil
} }
recipient := ethcmn.BytesToAddress(msg.Data.To) recipient := ethcmn.HexToAddress(msg.Data.To)
return &recipient return &recipient
} }
@ -297,8 +310,8 @@ func (msg MsgEthereumTx) AsMessage() (core.Message, error) {
from := ethcmn.HexToAddress(msg.From) from := ethcmn.HexToAddress(msg.From)
var to *ethcmn.Address var to *ethcmn.Address
if msg.Data.To != nil { if msg.Data.To != "" {
toAddr := ethcmn.BytesToAddress(msg.Data.To) toAddr := ethcmn.HexToAddress(msg.Data.To)
to = &toAddr to = &toAddr
} }
@ -324,8 +337,8 @@ func (msg MsgEthereumTx) AsMessage() (core.Message, error) {
// TxData defined on the Cosmos EVM. // TxData defined on the Cosmos EVM.
func (data TxData) AsEthereumData() ethtypes.TxData { func (data TxData) AsEthereumData() ethtypes.TxData {
var to *ethcmn.Address var to *ethcmn.Address
if data.To != nil { if data.To != "" {
toAddr := ethcmn.BytesToAddress(data.To) toAddr := ethcmn.HexToAddress(data.To)
to = &toAddr to = &toAddr
} }

View File

@ -47,7 +47,7 @@ func (suite *MsgsTestSuite) SetupTest() {
func (suite *MsgsTestSuite) TestMsgEthereumTx_Constructor() { func (suite *MsgsTestSuite) TestMsgEthereumTx_Constructor() {
msg := NewMsgEthereumTx(nil, 0, &suite.to, nil, 100000, nil, []byte("test"), nil) msg := NewMsgEthereumTx(nil, 0, &suite.to, nil, 100000, nil, []byte("test"), nil)
suite.Require().Equal(msg.Data.To, suite.to.Bytes()) suite.Require().Equal(msg.Data.To, suite.to.Hex())
suite.Require().Equal(msg.Route(), RouterKey) suite.Require().Equal(msg.Route(), RouterKey)
suite.Require().Equal(msg.Type(), TypeMsgEthereumTx) suite.Require().Equal(msg.Type(), TypeMsgEthereumTx)
suite.Require().NotNil(msg.To()) suite.Require().NotNil(msg.To())
@ -57,27 +57,30 @@ func (suite *MsgsTestSuite) TestMsgEthereumTx_Constructor() {
msg = NewMsgEthereumTxContract(nil, 0, nil, 100000, nil, []byte("test"), nil) msg = NewMsgEthereumTxContract(nil, 0, nil, 100000, nil, []byte("test"), nil)
suite.Require().NotNil(msg) suite.Require().NotNil(msg)
suite.Require().Nil(msg.Data.To) suite.Require().Empty(msg.Data.To)
suite.Require().Nil(msg.To()) suite.Require().Nil(msg.To())
} }
func (suite *MsgsTestSuite) TestMsgEthereumTx_ValidateBasic() { func (suite *MsgsTestSuite) TestMsgEthereumTx_ValidateBasic() {
testCases := []struct { testCases := []struct {
msg string msg string
to *ethcmn.Address
amount *big.Int amount *big.Int
gasPrice *big.Int gasPrice *big.Int
expectPass bool expectPass bool
}{ }{
{msg: "pass", amount: big.NewInt(100), gasPrice: big.NewInt(100000), expectPass: true}, {msg: "pass with recipient", to: &suite.to, amount: big.NewInt(100), gasPrice: big.NewInt(100000), expectPass: true},
{msg: "pass contract", to: nil, amount: big.NewInt(100), gasPrice: big.NewInt(100000), expectPass: true},
{msg: "invalid recipient", to: &ethcmn.Address{}, amount: big.NewInt(-1), gasPrice: big.NewInt(1000), expectPass: true},
// NOTE: these can't be effectively tested because the SetBytes function from big.Int only sets // NOTE: these can't be effectively tested because the SetBytes function from big.Int only sets
// the absolute value // the absolute value
{msg: "negative amount", amount: big.NewInt(-1), gasPrice: big.NewInt(1000), expectPass: true}, {msg: "negative amount", to: &suite.to, amount: big.NewInt(-1), gasPrice: big.NewInt(1000), expectPass: true},
{msg: "negative gas price", amount: big.NewInt(100), gasPrice: big.NewInt(-1), expectPass: true}, {msg: "negative gas price", to: &suite.to, amount: big.NewInt(100), gasPrice: big.NewInt(-1), expectPass: true},
{msg: "zero gas price", amount: big.NewInt(100), gasPrice: big.NewInt(0), expectPass: true}, {msg: "zero gas price", to: &suite.to, amount: big.NewInt(100), gasPrice: big.NewInt(0), expectPass: true},
} }
for i, tc := range testCases { for i, tc := range testCases {
msg := NewMsgEthereumTx(suite.chainID, 0, nil, tc.amount, 0, tc.gasPrice, nil, nil) msg := NewMsgEthereumTx(suite.chainID, 0, tc.to, tc.amount, 0, tc.gasPrice, nil, nil)
err := msg.ValidateBasic() err := msg.ValidateBasic()
if tc.expectPass { if tc.expectPass {