evm: TxData as proto.Any (#220)

* evm: TxData as proto.Any

* proto message

* fix protobuf any generation

* Int pointer

* fix build and tests

* ante tests

* swagger

* cleanup

* c++
This commit is contained in:
Federico Kunze Küllmer 2021-07-05 12:39:08 -04:00 committed by GitHub
parent 79e7062250
commit 5f1f252361
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
36 changed files with 2483 additions and 1699 deletions

View File

@ -39,6 +39,7 @@ Ref: https://keepachangelog.com/en/1.0.0/
### State Machine Breaking ### State Machine Breaking
* (evm) [tharsis#175](https://github.com/tharsis/ethermint/issues/175) The msg `TxData` field is now represented as a `*proto.Any`.
* (evm) [tharsis#84](https://github.com/tharsis/ethermint/pull/84) Remove `journal`, `CommitStateDB` and `stateObjects`. * (evm) [tharsis#84](https://github.com/tharsis/ethermint/pull/84) Remove `journal`, `CommitStateDB` and `stateObjects`.
* (rpc, evm) [tharsis#81](https://github.com/tharsis/ethermint/pull/81) Remove tx `Receipt` from store and replace it with fields obtained from the Tendermint RPC client. * (rpc, evm) [tharsis#81](https://github.com/tharsis/ethermint/pull/81) Remove tx `Receipt` from store and replace it with fields obtained from the Tendermint RPC client.
* (evm) [tharsis#72](https://github.com/tharsis/ethermint/issues/72) Update `AccessList` to use `TransientStore` instead of map. * (evm) [tharsis#72](https://github.com/tharsis/ethermint/issues/72) Update `AccessList` to use `TransientStore` instead of map.

View File

@ -29,7 +29,7 @@ func (suite AnteTestSuite) TestAnteHandler() {
{ {
"success - DeliverTx (contract)", "success - DeliverTx (contract)",
func() sdk.Tx { func() sdk.Tx {
signedContractTx := evmtypes.NewMsgEthereumTxContract(suite.app.EvmKeeper.ChainID(), 1, big.NewInt(10), 100000, big.NewInt(1), nil, nil) signedContractTx := evmtypes.NewTxContract(suite.app.EvmKeeper.ChainID(), 1, big.NewInt(10), 100000, big.NewInt(1), nil, nil)
signedContractTx.From = addr.Hex() signedContractTx.From = addr.Hex()
tx := suite.CreateTestTx(signedContractTx, privKey, 1, true) tx := suite.CreateTestTx(signedContractTx, privKey, 1, true)
@ -40,7 +40,7 @@ func (suite AnteTestSuite) TestAnteHandler() {
{ {
"success - CheckTx (contract)", "success - CheckTx (contract)",
func() sdk.Tx { func() sdk.Tx {
signedContractTx := evmtypes.NewMsgEthereumTxContract(suite.app.EvmKeeper.ChainID(), 1, big.NewInt(10), 100000, big.NewInt(1), nil, nil) signedContractTx := evmtypes.NewTxContract(suite.app.EvmKeeper.ChainID(), 1, big.NewInt(10), 100000, big.NewInt(1), nil, nil)
signedContractTx.From = addr.Hex() signedContractTx.From = addr.Hex()
tx := suite.CreateTestTx(signedContractTx, privKey, 1, true) tx := suite.CreateTestTx(signedContractTx, privKey, 1, true)
@ -51,7 +51,7 @@ func (suite AnteTestSuite) TestAnteHandler() {
{ {
"success - ReCheckTx (contract)", "success - ReCheckTx (contract)",
func() sdk.Tx { func() sdk.Tx {
signedContractTx := evmtypes.NewMsgEthereumTxContract(suite.app.EvmKeeper.ChainID(), 1, big.NewInt(10), 100000, big.NewInt(1), nil, nil) signedContractTx := evmtypes.NewTxContract(suite.app.EvmKeeper.ChainID(), 1, big.NewInt(10), 100000, big.NewInt(1), nil, nil)
signedContractTx.From = addr.Hex() signedContractTx.From = addr.Hex()
tx := suite.CreateTestTx(signedContractTx, privKey, 1, true) tx := suite.CreateTestTx(signedContractTx, privKey, 1, true)
@ -62,7 +62,7 @@ func (suite AnteTestSuite) TestAnteHandler() {
{ {
"success - DeliverTx", "success - DeliverTx",
func() sdk.Tx { func() sdk.Tx {
signedTx := evmtypes.NewMsgEthereumTx(suite.app.EvmKeeper.ChainID(), 1, &to, big.NewInt(10), 100000, big.NewInt(1), nil, nil) signedTx := evmtypes.NewTx(suite.app.EvmKeeper.ChainID(), 1, &to, big.NewInt(10), 100000, big.NewInt(1), nil, nil)
signedTx.From = addr.Hex() signedTx.From = addr.Hex()
tx := suite.CreateTestTx(signedTx, privKey, 1, true) tx := suite.CreateTestTx(signedTx, privKey, 1, true)
@ -73,7 +73,7 @@ func (suite AnteTestSuite) TestAnteHandler() {
{ {
"success - CheckTx", "success - CheckTx",
func() sdk.Tx { func() sdk.Tx {
signedTx := evmtypes.NewMsgEthereumTx(suite.app.EvmKeeper.ChainID(), 2, &to, big.NewInt(10), 100000, big.NewInt(1), nil, nil) signedTx := evmtypes.NewTx(suite.app.EvmKeeper.ChainID(), 2, &to, big.NewInt(10), 100000, big.NewInt(1), nil, nil)
signedTx.From = addr.Hex() signedTx.From = addr.Hex()
tx := suite.CreateTestTx(signedTx, privKey, 1, true) tx := suite.CreateTestTx(signedTx, privKey, 1, true)
@ -84,7 +84,7 @@ func (suite AnteTestSuite) TestAnteHandler() {
{ {
"success - ReCheckTx", "success - ReCheckTx",
func() sdk.Tx { func() sdk.Tx {
signedTx := evmtypes.NewMsgEthereumTx(suite.app.EvmKeeper.ChainID(), 3, &to, big.NewInt(10), 100000, big.NewInt(1), nil, nil) signedTx := evmtypes.NewTx(suite.app.EvmKeeper.ChainID(), 3, &to, big.NewInt(10), 100000, big.NewInt(1), nil, nil)
signedTx.From = addr.Hex() signedTx.From = addr.Hex()
tx := suite.CreateTestTx(signedTx, privKey, 1, true) tx := suite.CreateTestTx(signedTx, privKey, 1, true)
@ -94,7 +94,7 @@ func (suite AnteTestSuite) TestAnteHandler() {
{ {
"success - CheckTx (cosmos tx not signed)", "success - CheckTx (cosmos tx not signed)",
func() sdk.Tx { func() sdk.Tx {
signedTx := evmtypes.NewMsgEthereumTx(suite.app.EvmKeeper.ChainID(), 4, &to, big.NewInt(10), 100000, big.NewInt(1), nil, nil) signedTx := evmtypes.NewTx(suite.app.EvmKeeper.ChainID(), 4, &to, big.NewInt(10), 100000, big.NewInt(1), nil, nil)
signedTx.From = addr.Hex() signedTx.From = addr.Hex()
tx := suite.CreateTestTx(signedTx, privKey, 1, false) tx := suite.CreateTestTx(signedTx, privKey, 1, false)
@ -104,7 +104,7 @@ func (suite AnteTestSuite) TestAnteHandler() {
{ {
"fail - CheckTx (cosmos tx is not valid)", "fail - CheckTx (cosmos tx is not valid)",
func() sdk.Tx { func() sdk.Tx {
signedTx := evmtypes.NewMsgEthereumTx(suite.app.EvmKeeper.ChainID(), 4, &to, big.NewInt(10), 100000, big.NewInt(1), nil, nil) signedTx := evmtypes.NewTx(suite.app.EvmKeeper.ChainID(), 4, &to, big.NewInt(10), 100000, big.NewInt(1), nil, nil)
signedTx.From = addr.Hex() signedTx.From = addr.Hex()
txBuilder := suite.CreateTestTxBuilder(signedTx, privKey, 1, false) txBuilder := suite.CreateTestTxBuilder(signedTx, privKey, 1, false)
@ -116,7 +116,7 @@ func (suite AnteTestSuite) TestAnteHandler() {
{ {
"fail - CheckTx (memo too long)", "fail - CheckTx (memo too long)",
func() sdk.Tx { func() sdk.Tx {
signedTx := evmtypes.NewMsgEthereumTx(suite.app.EvmKeeper.ChainID(), 5, &to, big.NewInt(10), 100000, big.NewInt(1), nil, nil) signedTx := evmtypes.NewTx(suite.app.EvmKeeper.ChainID(), 5, &to, big.NewInt(10), 100000, big.NewInt(1), nil, nil)
signedTx.From = addr.Hex() signedTx.From = addr.Hex()
txBuilder := suite.CreateTestTxBuilder(signedTx, privKey, 1, true) txBuilder := suite.CreateTestTxBuilder(signedTx, privKey, 1, true)

View File

@ -130,6 +130,11 @@ func (avd EthAccountVerificationDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx
) )
} }
txData, err := evmtypes.UnpackTxData(msgEthTx.Data)
if err != nil {
return ctx, stacktrace.Propagate(err, "failed to unpack tx data any for tx %d", i)
}
// sender address should be in the tx cache from the previous AnteHandle call // sender address should be in the tx cache from the previous AnteHandle call
from := msgEthTx.GetFrom() from := msgEthTx.GetFrom()
if from.Empty() { if from.Empty() {
@ -155,13 +160,15 @@ func (avd EthAccountVerificationDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx
// validate sender has enough funds to pay for tx cost // validate sender has enough funds to pay for tx cost
balance := avd.bankKeeper.GetBalance(ctx, from, evmDenom) balance := avd.bankKeeper.GetBalance(ctx, from, evmDenom)
if balance.Amount.BigInt().Cmp(msgEthTx.Cost()) < 0 { cost := txData.Cost()
if balance.Amount.BigInt().Cmp(cost) < 0 {
return ctx, stacktrace.Propagate( return ctx, stacktrace.Propagate(
sdkerrors.Wrapf( sdkerrors.Wrapf(
sdkerrors.ErrInsufficientFunds, sdkerrors.ErrInsufficientFunds,
"sender balance < tx cost (%s < %s%s)", balance, msgEthTx.Cost(), evmDenom, "sender balance < tx cost (%s < %s%s)", balance, txData.Cost(), evmDenom,
), ),
"sender should have had enough funds to pay for tx cost = fee + amount (%s = %s + amount)", msgEthTx.Cost(), msgEthTx.Fee(), "sender should have had enough funds to pay for tx cost = fee + amount (%s = %s + %s)", cost, txData.Fee(), txData.GetValue(),
) )
} }
@ -207,14 +214,19 @@ func (nvd EthNonceVerificationDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx,
return ctx, stacktrace.Propagate(err, "sequence not found for address %s", msgEthTx.From) return ctx, stacktrace.Propagate(err, "sequence not found for address %s", msgEthTx.From)
} }
txData, err := evmtypes.UnpackTxData(msgEthTx.Data)
if err != nil {
return ctx, stacktrace.Propagate(err, "failed to unpack tx data")
}
// if multiple transactions are submitted in succession with increasing nonces, // if multiple transactions are submitted in succession with increasing nonces,
// all will be rejected except the first, since the first needs to be included in a block // all will be rejected except the first, since the first needs to be included in a block
// before the sequence increments // before the sequence increments
if msgEthTx.Data.Nonce != seq { if txData.GetNonce() != seq {
return ctx, stacktrace.Propagate( return ctx, stacktrace.Propagate(
sdkerrors.Wrapf( sdkerrors.Wrapf(
sdkerrors.ErrInvalidSequence, sdkerrors.ErrInvalidSequence,
"invalid nonce; got %d, expected %d", msgEthTx.Data.Nonce, seq, "invalid nonce; got %d, expected %d", txData.GetNonce(), seq,
), ),
"", "",
) )
@ -279,7 +291,12 @@ func (egcd EthGasConsumeDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simula
) )
} }
isContractCreation := msgEthTx.To() == nil txData, err := evmtypes.UnpackTxData(msgEthTx.Data)
if err != nil {
return ctx, stacktrace.Propagate(err, "failed to unpack tx data")
}
isContractCreation := txData.GetTo() == nil
// fetch sender account from signature // fetch sender account from signature
signerAcc, err := authante.GetSignerAcc(ctx, egcd.ak, msgEthTx.GetFrom()) signerAcc, err := authante.GetSignerAcc(ctx, egcd.ak, msgEthTx.GetFrom())
@ -287,14 +304,14 @@ func (egcd EthGasConsumeDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simula
return ctx, stacktrace.Propagate(err, "account not found for sender %s", msgEthTx.From) return ctx, stacktrace.Propagate(err, "account not found for sender %s", msgEthTx.From)
} }
gasLimit := msgEthTx.GetGas() gasLimit := txData.GetGas()
var accessList ethtypes.AccessList var accessList ethtypes.AccessList
if msgEthTx.Data.Accesses != nil { if txData.GetAccessList() != nil {
accessList = *msgEthTx.Data.Accesses.ToEthAccessList() accessList = txData.GetAccessList()
} }
intrinsicGas, err := core.IntrinsicGas(msgEthTx.Data.Input, accessList, isContractCreation, homestead, istanbul) intrinsicGas, err := core.IntrinsicGas(txData.GetData(), accessList, isContractCreation, homestead, istanbul)
if err != nil { if err != nil {
return ctx, stacktrace.Propagate( return ctx, stacktrace.Propagate(
sdkerrors.Wrap(err, "failed to compute intrinsic gas cost"), sdkerrors.Wrap(err, "failed to compute intrinsic gas cost"),
@ -307,7 +324,7 @@ func (egcd EthGasConsumeDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simula
} }
// calculate the fees paid to validators based on gas limit and price // calculate the fees paid to validators based on gas limit and price
feeAmt := msgEthTx.Fee() // fee = gas limit * gas price feeAmt := txData.Fee() // fee = gas limit * gas price
evmDenom := egcd.evmKeeper.GetParams(ctx).EvmDenom evmDenom := egcd.evmKeeper.GetParams(ctx).EvmDenom
fees := sdk.Coins{sdk.NewCoin(evmDenom, sdk.NewIntFromBigInt(feeAmt))} fees := sdk.Coins{sdk.NewCoin(evmDenom, sdk.NewIntFromBigInt(feeAmt))}
@ -451,7 +468,12 @@ func (ald AccessListDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate b
sender := common.BytesToAddress(msgEthTx.GetFrom()) sender := common.BytesToAddress(msgEthTx.GetFrom())
ald.evmKeeper.PrepareAccessList(sender, msgEthTx.To(), vm.ActivePrecompiles(rules), *msgEthTx.Data.Accesses.ToEthAccessList()) txData, err := evmtypes.UnpackTxData(msgEthTx.Data)
if err != nil {
return ctx, stacktrace.Propagate(err, "failed to unpack tx data")
}
ald.evmKeeper.PrepareAccessList(sender, txData.GetTo(), vm.ActivePrecompiles(rules), txData.GetAccessList())
} }
// set the original gas meter // set the original gas meter
@ -485,9 +507,14 @@ func (issd EthIncrementSenderSequenceDecorator) AnteHandle(ctx sdk.Context, tx s
) )
} }
txData, err := evmtypes.UnpackTxData(msgEthTx.Data)
if err != nil {
return ctx, stacktrace.Propagate(err, "failed to unpack tx data")
}
// NOTE: on contract creation, the nonce is incremented within the EVM Create function during tx execution // NOTE: on contract creation, the nonce is incremented within the EVM Create function during tx execution
// and not previous to the state transition ¯\_(ツ)_/¯ // and not previous to the state transition ¯\_(ツ)_/¯
if msgEthTx.To() == nil { if txData.GetTo() == nil {
// contract creation, don't increment sequence on AnteHandler but on tx execution // contract creation, don't increment sequence on AnteHandler but on tx execution
// continue to the next item // continue to the next item
continue continue

View File

@ -21,7 +21,7 @@ func (suite AnteTestSuite) TestEthSigVerificationDecorator() {
dec := ante.NewEthSigVerificationDecorator(suite.app.EvmKeeper) dec := ante.NewEthSigVerificationDecorator(suite.app.EvmKeeper)
addr, privKey := newTestAddrKey() addr, privKey := newTestAddrKey()
signedTx := evmtypes.NewMsgEthereumTxContract(suite.app.EvmKeeper.ChainID(), 1, big.NewInt(10), 1000, big.NewInt(1), nil, nil) signedTx := evmtypes.NewTxContract(suite.app.EvmKeeper.ChainID(), 1, big.NewInt(10), 1000, big.NewInt(1), nil, nil)
signedTx.From = addr.Hex() signedTx.From = addr.Hex()
err := signedTx.Sign(suite.ethSigner, tests.NewSigner(privKey)) err := signedTx.Sign(suite.ethSigner, tests.NewSigner(privKey))
suite.Require().NoError(err) suite.Require().NoError(err)
@ -36,7 +36,7 @@ func (suite AnteTestSuite) TestEthSigVerificationDecorator() {
{"invalid transaction type", &invalidTx{}, false, false}, {"invalid transaction type", &invalidTx{}, false, false},
{ {
"invalid sender", "invalid sender",
evmtypes.NewMsgEthereumTx(suite.app.EvmKeeper.ChainID(), 1, &addr, big.NewInt(10), 1000, big.NewInt(1), nil, nil), evmtypes.NewTx(suite.app.EvmKeeper.ChainID(), 1, &addr, big.NewInt(10), 1000, big.NewInt(1), nil, nil),
false, false,
false, false,
}, },
@ -64,7 +64,7 @@ func (suite AnteTestSuite) TestNewEthAccountVerificationDecorator() {
addr, _ := newTestAddrKey() addr, _ := newTestAddrKey()
tx := evmtypes.NewMsgEthereumTxContract(suite.app.EvmKeeper.ChainID(), 1, big.NewInt(10), 1000, big.NewInt(1), nil, nil) tx := evmtypes.NewTxContract(suite.app.EvmKeeper.ChainID(), 1, big.NewInt(10), 1000, big.NewInt(1), nil, nil)
tx.From = addr.Hex() tx.From = addr.Hex()
testCases := []struct { testCases := []struct {
@ -78,7 +78,7 @@ func (suite AnteTestSuite) TestNewEthAccountVerificationDecorator() {
{"invalid transaction type", &invalidTx{}, func() {}, true, false}, {"invalid transaction type", &invalidTx{}, func() {}, true, false},
{ {
"sender not set to msg", "sender not set to msg",
evmtypes.NewMsgEthereumTxContract(suite.app.EvmKeeper.ChainID(), 1, big.NewInt(10), 1000, big.NewInt(1), nil, nil), evmtypes.NewTxContract(suite.app.EvmKeeper.ChainID(), 1, big.NewInt(10), 1000, big.NewInt(1), nil, nil),
func() {}, func() {},
true, true,
false, false,
@ -147,7 +147,7 @@ func (suite AnteTestSuite) TestEthNonceVerificationDecorator() {
addr, _ := newTestAddrKey() addr, _ := newTestAddrKey()
tx := evmtypes.NewMsgEthereumTxContract(suite.app.EvmKeeper.ChainID(), 1, big.NewInt(10), 1000, big.NewInt(1), nil, nil) tx := evmtypes.NewTxContract(suite.app.EvmKeeper.ChainID(), 1, big.NewInt(10), 1000, big.NewInt(1), nil, nil)
tx.From = addr.Hex() tx.From = addr.Hex()
testCases := []struct { testCases := []struct {
@ -206,10 +206,10 @@ func (suite AnteTestSuite) TestEthGasConsumeDecorator() {
addr, _ := newTestAddrKey() addr, _ := newTestAddrKey()
tx := evmtypes.NewMsgEthereumTxContract(suite.app.EvmKeeper.ChainID(), 1, big.NewInt(10), 1000, big.NewInt(1), nil, nil) tx := evmtypes.NewTxContract(suite.app.EvmKeeper.ChainID(), 1, big.NewInt(10), 1000, big.NewInt(1), nil, nil)
tx.From = addr.Hex() tx.From = addr.Hex()
tx2 := evmtypes.NewMsgEthereumTxContract(suite.app.EvmKeeper.ChainID(), 1, big.NewInt(10), 1000000, big.NewInt(1), nil, &ethtypes.AccessList{{Address: addr, StorageKeys: nil}}) tx2 := evmtypes.NewTxContract(suite.app.EvmKeeper.ChainID(), 1, big.NewInt(10), 1000000, big.NewInt(1), nil, &ethtypes.AccessList{{Address: addr, StorageKeys: nil}})
tx2.From = addr.Hex() tx2.From = addr.Hex()
testCases := []struct { testCases := []struct {
@ -222,7 +222,7 @@ func (suite AnteTestSuite) TestEthGasConsumeDecorator() {
{"invalid transaction type", &invalidTx{}, func() {}, false, false}, {"invalid transaction type", &invalidTx{}, func() {}, false, false},
{ {
"sender not found", "sender not found",
evmtypes.NewMsgEthereumTxContract(suite.app.EvmKeeper.ChainID(), 1, big.NewInt(10), 1000, big.NewInt(1), nil, nil), evmtypes.NewTxContract(suite.app.EvmKeeper.ChainID(), 1, big.NewInt(10), 1000, big.NewInt(1), nil, nil),
func() {}, func() {},
false, false, false, false,
}, },
@ -311,8 +311,8 @@ func (suite AnteTestSuite) TestCanTransferDecorator() {
addr, privKey := newTestAddrKey() addr, privKey := newTestAddrKey()
tx := evmtypes.NewMsgEthereumTxContract(suite.app.EvmKeeper.ChainID(), 1, big.NewInt(10), 1000, big.NewInt(1), nil, &ethtypes.AccessList{}) tx := evmtypes.NewTxContract(suite.app.EvmKeeper.ChainID(), 1, big.NewInt(10), 1000, big.NewInt(1), nil, &ethtypes.AccessList{})
tx2 := evmtypes.NewMsgEthereumTxContract(suite.app.EvmKeeper.ChainID(), 1, big.NewInt(10), 1000, big.NewInt(1), nil, &ethtypes.AccessList{}) tx2 := evmtypes.NewTxContract(suite.app.EvmKeeper.ChainID(), 1, big.NewInt(10), 1000, big.NewInt(1), nil, &ethtypes.AccessList{})
tx.From = addr.Hex() tx.From = addr.Hex()
@ -373,8 +373,8 @@ func (suite AnteTestSuite) TestAccessListDecorator() {
{Address: addr, StorageKeys: []common.Hash{{}}}, {Address: addr, StorageKeys: []common.Hash{{}}},
} }
tx := evmtypes.NewMsgEthereumTxContract(suite.app.EvmKeeper.ChainID(), 1, big.NewInt(10), 1000, big.NewInt(1), nil, nil) tx := evmtypes.NewTxContract(suite.app.EvmKeeper.ChainID(), 1, big.NewInt(10), 1000, big.NewInt(1), nil, nil)
tx2 := evmtypes.NewMsgEthereumTxContract(suite.app.EvmKeeper.ChainID(), 1, big.NewInt(10), 1000, big.NewInt(1), nil, al) tx2 := evmtypes.NewTxContract(suite.app.EvmKeeper.ChainID(), 1, big.NewInt(10), 1000, big.NewInt(1), nil, al)
tx.From = addr.Hex() tx.From = addr.Hex()
tx2.From = addr.Hex() tx2.From = addr.Hex()
@ -429,11 +429,11 @@ func (suite AnteTestSuite) TestEthIncrementSenderSequenceDecorator() {
dec := ante.NewEthIncrementSenderSequenceDecorator(suite.app.AccountKeeper) dec := ante.NewEthIncrementSenderSequenceDecorator(suite.app.AccountKeeper)
addr, privKey := newTestAddrKey() addr, privKey := newTestAddrKey()
contract := evmtypes.NewMsgEthereumTxContract(suite.app.EvmKeeper.ChainID(), 0, big.NewInt(10), 1000, big.NewInt(1), nil, nil) contract := evmtypes.NewTxContract(suite.app.EvmKeeper.ChainID(), 0, big.NewInt(10), 1000, big.NewInt(1), nil, nil)
contract.From = addr.Hex() contract.From = addr.Hex()
to := tests.GenerateAddress() to := tests.GenerateAddress()
tx := evmtypes.NewMsgEthereumTx(suite.app.EvmKeeper.ChainID(), 0, &to, big.NewInt(10), 1000, big.NewInt(1), nil, nil) tx := evmtypes.NewTx(suite.app.EvmKeeper.ChainID(), 0, &to, big.NewInt(10), 1000, big.NewInt(1), nil, nil)
tx.From = addr.Hex() tx.From = addr.Hex()
err := contract.Sign(suite.ethSigner, tests.NewSigner(privKey)) err := contract.Sign(suite.ethSigner, tests.NewSigner(privKey))
@ -457,7 +457,7 @@ func (suite AnteTestSuite) TestEthIncrementSenderSequenceDecorator() {
}, },
{ {
"no signers", "no signers",
evmtypes.NewMsgEthereumTx(suite.app.EvmKeeper.ChainID(), 1, &to, big.NewInt(10), 1000, big.NewInt(1), nil, nil), evmtypes.NewTx(suite.app.EvmKeeper.ChainID(), 1, &to, big.NewInt(10), 1000, big.NewInt(1), nil, nil),
func() {}, func() {},
false, true, false, true,
}, },
@ -501,11 +501,15 @@ func (suite AnteTestSuite) TestEthIncrementSenderSequenceDecorator() {
if tc.expPass { if tc.expPass {
suite.Require().NoError(err) suite.Require().NoError(err)
msg := tc.tx.(*evmtypes.MsgEthereumTx) msg := tc.tx.(*evmtypes.MsgEthereumTx)
txData, err := evmtypes.UnpackTxData(msg.Data)
suite.Require().NoError(err)
nonce := suite.app.EvmKeeper.GetNonce(addr) nonce := suite.app.EvmKeeper.GetNonce(addr)
if msg.To() == nil { if txData.GetTo() == nil {
suite.Require().Equal(msg.Data.Nonce, nonce) suite.Require().Equal(txData.GetNonce(), nonce)
} else { } else {
suite.Require().Equal(msg.Data.Nonce+1, nonce) suite.Require().Equal(txData.GetNonce()+1, nonce)
} }
} else { } else {
suite.Require().Error(err) suite.Require().Error(err)
@ -516,7 +520,7 @@ func (suite AnteTestSuite) TestEthIncrementSenderSequenceDecorator() {
func (suite AnteTestSuite) TestEthSetupContextDecorator() { func (suite AnteTestSuite) TestEthSetupContextDecorator() {
dec := ante.NewEthSetUpContextDecorator() dec := ante.NewEthSetUpContextDecorator()
tx := evmtypes.NewMsgEthereumTxContract(suite.app.EvmKeeper.ChainID(), 1, big.NewInt(10), 1000, big.NewInt(1), nil, nil) tx := evmtypes.NewTxContract(suite.app.EvmKeeper.ChainID(), 1, big.NewInt(10), 1000, big.NewInt(1), nil, nil)
testCases := []struct { testCases := []struct {
name string name string

View File

@ -78,7 +78,6 @@ func (suite *AnteTestSuite) CreateTestTx(
func (suite *AnteTestSuite) CreateTestTxBuilder( func (suite *AnteTestSuite) CreateTestTxBuilder(
msg *evmtypes.MsgEthereumTx, priv cryptotypes.PrivKey, accNum uint64, signCosmosTx bool, msg *evmtypes.MsgEthereumTx, priv cryptotypes.PrivKey, accNum uint64, signCosmosTx bool,
) client.TxBuilder { ) client.TxBuilder {
option, err := codectypes.NewAnyWithValue(&evmtypes.ExtensionOptionsEthereumTx{}) option, err := codectypes.NewAnyWithValue(&evmtypes.ExtensionOptionsEthereumTx{})
suite.Require().NoError(err) suite.Require().NoError(err)
@ -93,7 +92,11 @@ func (suite *AnteTestSuite) CreateTestTxBuilder(
err = builder.SetMsgs(msg) err = builder.SetMsgs(msg)
suite.Require().NoError(err) suite.Require().NoError(err)
fees := sdk.NewCoins(sdk.NewCoin(evmtypes.DefaultEVMDenom, sdk.NewIntFromBigInt(msg.Fee())))
txData, err := evmtypes.UnpackTxData(msg.Data)
suite.Require().NoError(err)
fees := sdk.NewCoins(sdk.NewCoin(evmtypes.DefaultEVMDenom, sdk.NewIntFromBigInt(txData.Fee())))
builder.SetFeeAmount(fees) builder.SetFeeAmount(fees)
builder.SetGasLimit(msg.GetGas()) builder.SetGasLimit(msg.GetGas())
@ -106,7 +109,7 @@ func (suite *AnteTestSuite) CreateTestTxBuilder(
SignMode: suite.clientCtx.TxConfig.SignModeHandler().DefaultMode(), SignMode: suite.clientCtx.TxConfig.SignModeHandler().DefaultMode(),
Signature: nil, Signature: nil,
}, },
Sequence: msg.Data.Nonce, Sequence: txData.GetNonce(),
} }
sigsV2 := []signing.SignatureV2{sigV2} sigsV2 := []signing.SignatureV2{sigV2}
@ -119,11 +122,11 @@ func (suite *AnteTestSuite) CreateTestTxBuilder(
signerData := authsigning.SignerData{ signerData := authsigning.SignerData{
ChainID: suite.ctx.ChainID(), ChainID: suite.ctx.ChainID(),
AccountNumber: accNum, AccountNumber: accNum,
Sequence: msg.Data.Nonce, Sequence: txData.GetNonce(),
} }
sigV2, err = tx.SignWithPrivKey( sigV2, err = tx.SignWithPrivKey(
suite.clientCtx.TxConfig.SignModeHandler().DefaultMode(), signerData, suite.clientCtx.TxConfig.SignModeHandler().DefaultMode(), signerData,
txBuilder, priv, suite.clientCtx.TxConfig, msg.Data.Nonce, txBuilder, priv, suite.clientCtx.TxConfig, txData.GetNonce(),
) )
suite.Require().NoError(err) suite.Require().NoError(err)

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

View File

@ -313,10 +313,7 @@ func (m *PubKey) Unmarshal(dAtA []byte) error {
if err != nil { if err != nil {
return err return err
} }
if skippy < 0 { if (skippy < 0) || (iNdEx+skippy) < 0 {
return ErrInvalidLengthKeys
}
if (iNdEx + skippy) < 0 {
return ErrInvalidLengthKeys return ErrInvalidLengthKeys
} }
if (iNdEx + skippy) > l { if (iNdEx + skippy) > l {
@ -400,10 +397,7 @@ func (m *PrivKey) Unmarshal(dAtA []byte) error {
if err != nil { if err != nil {
return err return err
} }
if skippy < 0 { if (skippy < 0) || (iNdEx+skippy) < 0 {
return ErrInvalidLengthKeys
}
if (iNdEx + skippy) < 0 {
return ErrInvalidLengthKeys return ErrInvalidLengthKeys
} }
if (iNdEx + skippy) > l { if (iNdEx + skippy) > l {

View File

@ -15,7 +15,6 @@
- [Params](#ethermint.evm.v1alpha1.Params) - [Params](#ethermint.evm.v1alpha1.Params)
- [State](#ethermint.evm.v1alpha1.State) - [State](#ethermint.evm.v1alpha1.State)
- [TransactionLogs](#ethermint.evm.v1alpha1.TransactionLogs) - [TransactionLogs](#ethermint.evm.v1alpha1.TransactionLogs)
- [TxData](#ethermint.evm.v1alpha1.TxData)
- [TxResult](#ethermint.evm.v1alpha1.TxResult) - [TxResult](#ethermint.evm.v1alpha1.TxResult)
- [ethermint/evm/v1alpha1/genesis.proto](#ethermint/evm/v1alpha1/genesis.proto) - [ethermint/evm/v1alpha1/genesis.proto](#ethermint/evm/v1alpha1/genesis.proto)
@ -49,8 +48,10 @@
- [Query](#ethermint.evm.v1alpha1.Query) - [Query](#ethermint.evm.v1alpha1.Query)
- [ethermint/evm/v1alpha1/tx.proto](#ethermint/evm/v1alpha1/tx.proto) - [ethermint/evm/v1alpha1/tx.proto](#ethermint/evm/v1alpha1/tx.proto)
- [AccessListTx](#ethermint.evm.v1alpha1.AccessListTx)
- [ExtensionOptionsEthereumTx](#ethermint.evm.v1alpha1.ExtensionOptionsEthereumTx) - [ExtensionOptionsEthereumTx](#ethermint.evm.v1alpha1.ExtensionOptionsEthereumTx)
- [ExtensionOptionsWeb3Tx](#ethermint.evm.v1alpha1.ExtensionOptionsWeb3Tx) - [ExtensionOptionsWeb3Tx](#ethermint.evm.v1alpha1.ExtensionOptionsWeb3Tx)
- [LegacyTx](#ethermint.evm.v1alpha1.LegacyTx)
- [MsgEthereumTx](#ethermint.evm.v1alpha1.MsgEthereumTx) - [MsgEthereumTx](#ethermint.evm.v1alpha1.MsgEthereumTx)
- [MsgEthereumTxResponse](#ethermint.evm.v1alpha1.MsgEthereumTxResponse) - [MsgEthereumTxResponse](#ethermint.evm.v1alpha1.MsgEthereumTxResponse)
@ -252,32 +253,6 @@ persisted on blockchain state after an upgrade.
<a name="ethermint.evm.v1alpha1.TxData"></a>
### TxData
TxData implements the Ethereum transaction data structure. It is used
solely as intended in Ethereum abiding by the protocol.
| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| `chain_id` | [string](#string) | | destination EVM chain ID |
| `nonce` | [uint64](#uint64) | | nonce corresponds to the account nonce (transaction sequence). |
| `gas_price` | [string](#string) | | gas price defines the value for each gas unit |
| `gas` | [uint64](#uint64) | | gas defines the gas limit defined for the transaction. |
| `to` | [string](#string) | | hex formatted address of the recipient |
| `value` | [string](#string) | | value defines the unsigned integer value of the transaction amount. |
| `input` | [bytes](#bytes) | | input defines the data payload bytes of the transaction. |
| `accesses` | [AccessTuple](#ethermint.evm.v1alpha1.AccessTuple) | repeated | |
| `v` | [bytes](#bytes) | | v defines the signature value |
| `r` | [bytes](#bytes) | | r defines the signature value |
| `s` | [bytes](#bytes) | | s define the signature value |
<a name="ethermint.evm.v1alpha1.TxResult"></a> <a name="ethermint.evm.v1alpha1.TxResult"></a>
### TxResult ### TxResult
@ -737,6 +712,31 @@ Query defines the gRPC querier service.
<a name="ethermint.evm.v1alpha1.AccessListTx"></a>
### AccessListTx
AccessListTx is the data of EIP-2930 access list transactions.
| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| `chain_id` | [string](#string) | | destination EVM chain ID |
| `nonce` | [uint64](#uint64) | | nonce corresponds to the account nonce (transaction sequence). |
| `gas_price` | [string](#string) | | gas price defines the value for each gas unit |
| `gas` | [uint64](#uint64) | | gas defines the gas limit defined for the transaction. |
| `to` | [string](#string) | | hex formatted address of the recipient |
| `value` | [string](#string) | | value defines the unsigned integer value of the transaction amount. |
| `data` | [bytes](#bytes) | | input defines the data payload bytes of the transaction. |
| `accesses` | [AccessTuple](#ethermint.evm.v1alpha1.AccessTuple) | repeated | |
| `v` | [bytes](#bytes) | | v defines the signature value |
| `r` | [bytes](#bytes) | | r defines the signature value |
| `s` | [bytes](#bytes) | | s define the signature value |
<a name="ethermint.evm.v1alpha1.ExtensionOptionsEthereumTx"></a> <a name="ethermint.evm.v1alpha1.ExtensionOptionsEthereumTx"></a>
### ExtensionOptionsEthereumTx ### ExtensionOptionsEthereumTx
@ -757,6 +757,29 @@ Query defines the gRPC querier service.
<a name="ethermint.evm.v1alpha1.LegacyTx"></a>
### LegacyTx
LegacyTx is the transaction data of regular Ethereum transactions.
| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| `nonce` | [uint64](#uint64) | | nonce corresponds to the account nonce (transaction sequence). |
| `gas_price` | [string](#string) | | gas price defines the value for each gas unit |
| `gas` | [uint64](#uint64) | | gas defines the gas limit defined for the transaction. |
| `to` | [string](#string) | | hex formatted address of the recipient |
| `value` | [string](#string) | | value defines the unsigned integer value of the transaction amount. |
| `data` | [bytes](#bytes) | | input defines the data payload bytes of the transaction. |
| `v` | [bytes](#bytes) | | v defines the signature value |
| `r` | [bytes](#bytes) | | r defines the signature value |
| `s` | [bytes](#bytes) | | s define the signature value |
<a name="ethermint.evm.v1alpha1.MsgEthereumTx"></a> <a name="ethermint.evm.v1alpha1.MsgEthereumTx"></a>
### MsgEthereumTx ### MsgEthereumTx
@ -765,7 +788,7 @@ MsgEthereumTx encapsulates an Ethereum transaction as an SDK message.
| Field | Type | Label | Description | | Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- | | ----- | ---- | ----- | ----------- |
| `data` | [TxData](#ethermint.evm.v1alpha1.TxData) | | inner transaction data | `data` | [google.protobuf.Any](#google.protobuf.Any) | | inner transaction data
caches | caches |
| `size` | [double](#double) | | encoded storage size of the transaction | | `size` | [double](#double) | | encoded storage size of the transaction |

View File

@ -18,7 +18,7 @@ func TestTxEncoding(t *testing.T) {
addr, key := tests.NewAddrKey() addr, key := tests.NewAddrKey()
signer := tests.NewSigner(key) signer := tests.NewSigner(key)
msg := evmtypes.NewMsgEthereumTxContract(big.NewInt(1), 1, big.NewInt(10), 100000, big.NewInt(1), []byte{}, nil) msg := evmtypes.NewTxContract(big.NewInt(1), 1, big.NewInt(10), 100000, big.NewInt(1), []byte{}, nil)
msg.From = addr.Hex() msg.From = addr.Hex()
ethSigner := ethtypes.LatestSignerForChainID(big.NewInt(1)) ethSigner := ethtypes.LatestSignerForChainID(big.NewInt(1))

View File

@ -2,6 +2,7 @@ package backend
import ( import (
"context" "context"
"fmt"
"math/big" "math/big"
"regexp" "regexp"
@ -156,29 +157,39 @@ func (e *EVMBackend) EthBlockFromTendermint(
} }
hash := msg.AsTransaction().Hash() hash := msg.AsTransaction().Hash()
if fullTx { if !fullTx {
from, err := msg.GetSender(e.chainID)
if err != nil {
from = common.HexToAddress(msg.From)
}
ethTx, err := types.NewTransactionFromData(
msg.Data,
from,
hash,
common.BytesToHash(block.Hash()),
uint64(block.Height),
uint64(i),
)
ethRPCTxs = append(ethRPCTxs, ethTx)
if err != nil {
e.logger.WithError(err).Debugln("NewTransactionFromData for receipt failed", "hash", hash.Hex)
continue
}
} else {
ethRPCTxs = append(ethRPCTxs, hash) ethRPCTxs = append(ethRPCTxs, hash)
continue
} }
// get full transaction from message data
from, err := msg.GetSender(e.chainID)
if err != nil {
from = common.HexToAddress(msg.From)
}
txData, err := evmtypes.UnpackTxData(msg.Data)
if err != nil {
e.logger.WithError(err).Debugln("decoding failed")
return nil, fmt.Errorf("failed to unpack tx data: %w", err)
}
ethTx, err := types.NewTransactionFromData(
txData,
from,
hash,
common.BytesToHash(block.Hash()),
uint64(block.Height),
uint64(i),
)
if err != nil {
e.logger.WithError(err).Debugln("NewTransactionFromData for receipt failed", "hash", hash.Hex)
continue
}
ethRPCTxs = append(ethRPCTxs, ethTx)
} }
blockBloomResp, err := queryClient.BlockBloom(types.ContextWithHeight(block.Height), &evmtypes.QueryBlockBloomRequest{}) blockBloomResp, err := queryClient.BlockBloom(types.ContextWithHeight(block.Height), &evmtypes.QueryBlockBloomRequest{})

View File

@ -369,9 +369,9 @@ func (e *PublicAPI) SendTransaction(args rpctypes.SendTxArgs) (common.Hash, erro
return common.Hash{}, err return common.Hash{}, err
} }
// creates a new EIP2929 signer // TODO: get from chain config
// TODO: support legacy txs
signer := ethtypes.LatestSignerForChainID(args.ChainID.ToInt()) signer := ethtypes.LatestSignerForChainID(args.ChainID.ToInt())
// Sign transaction // Sign transaction
if err := msg.Sign(signer, e.clientCtx.Keyring); err != nil { if err := msg.Sign(signer, e.clientCtx.Keyring); err != nil {
e.logger.Debugln("failed to sign tx", "error", err) e.logger.Debugln("failed to sign tx", "error", err)
@ -403,7 +403,13 @@ func (e *PublicAPI) SendTransaction(args rpctypes.SendTxArgs) (common.Hash, erro
return common.Hash{}, err return common.Hash{}, err
} }
fees := sdk.Coins{sdk.NewCoin(res.Params.EvmDenom, sdk.NewIntFromBigInt(msg.Fee()))} txData, err := evmtypes.UnpackTxData(msg.Data)
if err != nil {
e.logger.WithError(err).Errorln("failed to unpack tx data")
return common.Hash{}, err
}
fees := sdk.Coins{sdk.NewCoin(res.Params.EvmDenom, sdk.NewIntFromBigInt(txData.Fee()))}
builder.SetFeeAmount(fees) builder.SetFeeAmount(fees)
builder.SetGasLimit(msg.GetGas()) builder.SetGasLimit(msg.GetGas())
@ -451,6 +457,11 @@ func (e *PublicAPI) SendRawTransaction(data hexutil.Bytes) (common.Hash, error)
return common.Hash{}, fmt.Errorf("invalid transaction type %T", tx) return common.Hash{}, fmt.Errorf("invalid transaction type %T", tx)
} }
if err := ethereumTx.ValidateBasic(); err != nil {
e.logger.WithError(err).Debugln("tx failed basic validation")
return common.Hash{}, err
}
builder, ok := e.clientCtx.TxConfig.NewTxBuilder().(authtx.ExtensionOptionsTxBuilder) builder, ok := e.clientCtx.TxConfig.NewTxBuilder().(authtx.ExtensionOptionsTxBuilder)
if !ok { if !ok {
e.logger.Panicln("clientCtx.TxConfig.NewTxBuilder returns unsupported builder") e.logger.Panicln("clientCtx.TxConfig.NewTxBuilder returns unsupported builder")
@ -474,7 +485,13 @@ func (e *PublicAPI) SendRawTransaction(data hexutil.Bytes) (common.Hash, error)
return common.Hash{}, err return common.Hash{}, err
} }
fees := sdk.Coins{sdk.NewCoin(res.Params.EvmDenom, sdk.NewIntFromBigInt(ethereumTx.Fee()))} txData, err := evmtypes.UnpackTxData(ethereumTx.Data)
if err != nil {
e.logger.WithError(err).Errorln("failed to unpack tx data")
return common.Hash{}, err
}
fees := sdk.Coins{sdk.NewCoin(res.Params.EvmDenom, sdk.NewIntFromBigInt(txData.Fee()))}
builder.SetFeeAmount(fees) builder.SetFeeAmount(fees)
builder.SetGasLimit(ethereumTx.GetGas()) builder.SetGasLimit(ethereumTx.GetGas())
@ -571,8 +588,10 @@ func (e *PublicAPI) doCall(
} }
// Create new call message // Create new call message
msg := evmtypes.NewMsgEthereumTx(e.chainIDEpoch, seq, args.To, value, gas, gasPrice, data, accessList) msg := evmtypes.NewTx(e.chainIDEpoch, seq, args.To, value, gas, gasPrice, data, accessList)
msg.From = args.From.String() msg.From = args.From.String()
// TODO: get from chain config
signer := ethtypes.LatestSignerForChainID(e.chainIDEpoch) signer := ethtypes.LatestSignerForChainID(e.chainIDEpoch)
if err := msg.Sign(signer, e.clientCtx.Keyring); err != nil { if err := msg.Sign(signer, e.clientCtx.Keyring); err != nil {
return nil, err return nil, err
@ -605,7 +624,13 @@ func (e *PublicAPI) doCall(
return nil, err return nil, err
} }
fees := sdk.Coins{sdk.NewCoin(res.Params.EvmDenom, sdk.NewIntFromBigInt(msg.Fee()))} txData, err := evmtypes.UnpackTxData(msg.Data)
if err != nil {
e.logger.WithError(err).Errorln("failed to unpack tx data")
return nil, err
}
fees := sdk.Coins{sdk.NewCoin(res.Params.EvmDenom, sdk.NewIntFromBigInt(txData.Fee()))}
txBuilder.SetFeeAmount(fees) txBuilder.SetFeeAmount(fees)
txBuilder.SetGasLimit(gas) txBuilder.SetGasLimit(gas)
@ -727,8 +752,14 @@ func (e *PublicAPI) GetTransactionByHash(hash common.Hash) (*rpctypes.RPCTransac
if err != nil { if err != nil {
return nil, err return nil, err
} }
data, err := evmtypes.UnpackTxData(msg.Data)
if err != nil {
return nil, fmt.Errorf("failed to unpack tx data: %w", err)
}
return rpctypes.NewTransactionFromData( return rpctypes.NewTransactionFromData(
msg.Data, data,
from, from,
hash, hash,
common.BytesToHash(resBlock.Block.Hash()), common.BytesToHash(resBlock.Block.Hash()),
@ -772,8 +803,14 @@ func (e *PublicAPI) GetTransactionByBlockHashAndIndex(hash common.Hash, idx hexu
txHash := msg.AsTransaction().Hash() txHash := msg.AsTransaction().Hash()
txData, err := evmtypes.UnpackTxData(msg.Data)
if err != nil {
e.logger.WithError(err).Debugln("decoding failed")
return nil, fmt.Errorf("failed to unpack tx data: %w", err)
}
return rpctypes.NewTransactionFromData( return rpctypes.NewTransactionFromData(
msg.Data, txData,
common.HexToAddress(msg.From), common.HexToAddress(msg.From),
txHash, txHash,
hash, hash,
@ -817,8 +854,14 @@ func (e *PublicAPI) GetTransactionByBlockNumberAndIndex(blockNum rpctypes.BlockN
txHash := msg.AsTransaction().Hash() txHash := msg.AsTransaction().Hash()
txData, err := evmtypes.UnpackTxData(msg.Data)
if err != nil {
e.logger.WithError(err).Debugln("decoding failed")
return nil, fmt.Errorf("failed to unpack tx data: %w", err)
}
return rpctypes.NewTransactionFromData( return rpctypes.NewTransactionFromData(
msg.Data, txData,
common.HexToAddress(msg.From), common.HexToAddress(msg.From),
txHash, txHash,
common.BytesToHash(resBlock.Block.Hash()), common.BytesToHash(resBlock.Block.Hash()),
@ -853,12 +896,19 @@ func (e *PublicAPI) GetTransactionReceipt(hash common.Hash) (map[string]interfac
e.logger.Debugln("invalid tx") e.logger.Debugln("invalid tx")
return nil, fmt.Errorf("invalid tx type: %T", tx) return nil, fmt.Errorf("invalid tx type: %T", tx)
} }
msg, ok := tx.GetMsgs()[0].(*evmtypes.MsgEthereumTx) msg, ok := tx.GetMsgs()[0].(*evmtypes.MsgEthereumTx)
if !ok { if !ok {
e.logger.Debugln("invalid tx") e.logger.Debugln("invalid tx")
return nil, fmt.Errorf("invalid tx type: %T", tx) return nil, fmt.Errorf("invalid tx type: %T", tx)
} }
txData, err := evmtypes.UnpackTxData(msg.Data)
if err != nil {
e.logger.WithError(err).Errorln("failed to unpack tx data")
return nil, err
}
cumulativeGasUsed := uint64(0) cumulativeGasUsed := uint64(0)
blockRes, err := e.clientCtx.Client.BlockResults(e.ctx, &res.Height) blockRes, err := e.clientCtx.Client.BlockResults(e.ctx, &res.Height)
if err != nil { if err != nil {
@ -909,7 +959,7 @@ func (e *PublicAPI) GetTransactionReceipt(hash common.Hash) (map[string]interfac
"transactionHash": hash, "transactionHash": hash,
"contractAddress": nil, "contractAddress": nil,
"gasUsed": hexutil.Uint64(res.TxResult.GasUsed), "gasUsed": hexutil.Uint64(res.TxResult.GasUsed),
"type": hexutil.Uint(ethtypes.AccessListTxType), // TODO: support legacy type "type": hexutil.Uint(txData.TxType()),
// Inclusion information: These fields provide information about the inclusion of the // Inclusion information: These fields provide information about the inclusion of the
// transaction corresponding to this receipt. // transaction corresponding to this receipt.
@ -919,7 +969,7 @@ func (e *PublicAPI) GetTransactionReceipt(hash common.Hash) (map[string]interfac
// sender and receiver (contract or EOA) addreses // sender and receiver (contract or EOA) addreses
"from": from, "from": from,
"to": msg.To(), "to": txData.GetTo(),
} }
if logs == nil { if logs == nil {
@ -927,8 +977,8 @@ func (e *PublicAPI) GetTransactionReceipt(hash common.Hash) (map[string]interfac
} }
// If the ContractAddress is 20 0x0 bytes, assume it is not a contract creation // If the ContractAddress is 20 0x0 bytes, assume it is not a contract creation
if msg.To() == nil { if txData.GetTo() == nil {
receipt["contractAddress"] = crypto.CreateAddress(from, msg.Data.Nonce) receipt["contractAddress"] = crypto.CreateAddress(from, txData.GetNonce())
} }
return receipt, nil return receipt, nil
@ -961,6 +1011,7 @@ func (e *PublicAPI) GetProof(address common.Address, storageKeys []string, block
// query storage proofs // query storage proofs
storageProofs := make([]rpctypes.StorageResult, len(storageKeys)) storageProofs := make([]rpctypes.StorageResult, len(storageKeys))
for i, key := range storageKeys { for i, key := range storageKeys {
hexKey := common.HexToHash(key) hexKey := common.HexToHash(key)
valueBz, proof, err := e.queryClient.GetProof(clientCtx, evmtypes.StoreKey, evmtypes.StateKey(address, hexKey.Bytes())) valueBz, proof, err := e.queryClient.GetProof(clientCtx, evmtypes.StoreKey, evmtypes.StateKey(address, hexKey.Bytes()))

View File

@ -2,13 +2,12 @@ package types
import ( import (
"fmt" "fmt"
"math/big"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/common/hexutil"
ethtypes "github.com/ethereum/go-ethereum/core/types" ethtypes "github.com/ethereum/go-ethereum/core/types"
sdk "github.com/cosmos/cosmos-sdk/types"
evmtypes "github.com/tharsis/ethermint/x/evm/types" evmtypes "github.com/tharsis/ethermint/x/evm/types"
) )
@ -90,46 +89,42 @@ func (args *SendTxArgs) String() string {
// ToTransaction converts the arguments to an ethereum transaction. // ToTransaction converts the arguments to an ethereum transaction.
// This assumes that setTxDefaults has been called. // This assumes that setTxDefaults has been called.
func (args *SendTxArgs) ToTransaction() *evmtypes.MsgEthereumTx { func (args *SendTxArgs) ToTransaction() *evmtypes.MsgEthereumTx {
var input []byte var (
input []byte
chainID, value, gasPrice *big.Int
gas, nonce uint64
)
if args.Input != nil { if args.Input != nil {
input = *args.Input input = *args.Input
} else if args.Data != nil { } else if args.Data != nil {
input = *args.Data input = *args.Data
} }
data := &evmtypes.TxData{
Input: input,
Accesses: evmtypes.NewAccessList(args.AccessList),
}
if args.ChainID != nil { if args.ChainID != nil {
data.ChainID = sdk.NewIntFromBigInt(args.ChainID.ToInt()) chainID = args.ChainID.ToInt()
} }
if args.Nonce != nil { if args.Nonce != nil {
data.Nonce = uint64(*args.Nonce) nonce = uint64(*args.Nonce)
} }
if args.Gas != nil { if args.Gas != nil {
data.GasLimit = uint64(*args.Gas) gas = uint64(*args.Gas)
} }
if args.GasPrice != nil { if args.GasPrice != nil {
data.GasPrice = sdk.NewIntFromBigInt(args.GasPrice.ToInt()) gasPrice = args.GasPrice.ToInt()
} }
if args.Value != nil { if args.Value != nil {
data.Amount = sdk.NewIntFromBigInt(args.Value.ToInt()) value = args.Value.ToInt()
} }
if args.To != nil { tx := evmtypes.NewTx(chainID, nonce, args.To, value, gas, gasPrice, input, args.AccessList)
data.To = args.To.Hex() tx.From = args.From.Hex()
}
return &evmtypes.MsgEthereumTx{ return tx
Data: data,
From: args.From.String(),
}
} }
// CallArgs represents the arguments for a call. // CallArgs represents the arguments for a call.

View File

@ -139,8 +139,14 @@ func EthTransactionsFromTendermint(clientCtx client.Context, txs []tmtypes.Tx) (
// continue to next transaction in case it's not a MsgEthereumTx // continue to next transaction in case it's not a MsgEthereumTx
continue continue
} }
data, err := evmtypes.UnpackTxData(ethTx.Data)
if err != nil {
return nil, nil, fmt.Errorf("failed to unpack tx data: %w", err)
}
// TODO: Remove gas usage calculation if saving gasUsed per block // TODO: Remove gas usage calculation if saving gasUsed per block
gasUsed.Add(gasUsed, ethTx.Fee()) gasUsed.Add(gasUsed, data.Fee())
transactionHashes = append(transactionHashes, common.BytesToHash(tx.Hash())) transactionHashes = append(transactionHashes, common.BytesToHash(tx.Hash()))
} }
@ -253,35 +259,31 @@ func ErrRevertedWith(data []byte) DataError {
// NewTransactionFromData returns a transaction that will serialize to the RPC // NewTransactionFromData returns a transaction that will serialize to the RPC
// representation, with the given location metadata set (if available). // representation, with the given location metadata set (if available).
func NewTransactionFromData( func NewTransactionFromData(
txData *evmtypes.TxData, txData evmtypes.TxData,
from common.Address, from common.Address,
txHash, blockHash common.Hash, txHash, blockHash common.Hash,
blockNumber, index uint64, blockNumber, index uint64,
) (*RPCTransaction, error) { ) (*RPCTransaction, error) {
var to *common.Address
if len(txData.To) > 0 {
recipient := common.HexToAddress(txData.To)
to = &recipient
}
if txHash == (common.Hash{}) { if txHash == (common.Hash{}) {
txHash = ethtypes.EmptyRootHash txHash = ethtypes.EmptyRootHash
} }
v, r, s := txData.GetRawSignatureValues()
rpcTx := &RPCTransaction{ rpcTx := &RPCTransaction{
Type: hexutil.Uint64(txData.Type()), Type: hexutil.Uint64(txData.TxType()),
From: from, From: from,
Gas: hexutil.Uint64(txData.GasLimit), Gas: hexutil.Uint64(txData.GetGas()),
GasPrice: (*hexutil.Big)(txData.GasPrice.BigInt()), GasPrice: (*hexutil.Big)(txData.GetGasPrice()),
Hash: txHash, Hash: txHash,
Input: hexutil.Bytes(txData.Input), Input: hexutil.Bytes(txData.GetData()),
Nonce: hexutil.Uint64(txData.Nonce), Nonce: hexutil.Uint64(txData.GetNonce()),
To: to, To: txData.GetTo(),
Value: (*hexutil.Big)(txData.Amount.BigInt()), Value: (*hexutil.Big)(txData.GetValue()),
V: (*hexutil.Big)(new(big.Int).SetBytes(txData.V)), V: (*hexutil.Big)(v),
R: (*hexutil.Big)(new(big.Int).SetBytes(txData.R)), R: (*hexutil.Big)(r),
S: (*hexutil.Big)(new(big.Int).SetBytes(txData.S)), S: (*hexutil.Big)(s),
} }
if rpcTx.To == nil { if rpcTx.To == nil {
addr := common.Address{} addr := common.Address{}
@ -294,9 +296,10 @@ func NewTransactionFromData(
rpcTx.TransactionIndex = (*hexutil.Uint64)(&index) rpcTx.TransactionIndex = (*hexutil.Uint64)(&index)
} }
if txData.Type() == ethtypes.AccessListTxType { if txData.TxType() == ethtypes.AccessListTxType {
rpcTx.Accesses = txData.Accesses.ToEthAccessList() accesses := txData.GetAccessList()
rpcTx.ChainID = (*hexutil.Big)(txData.ChainID.BigInt()) rpcTx.Accesses = &accesses
rpcTx.ChainID = (*hexutil.Big)(txData.GetChainID())
} }
return rpcTx, nil return rpcTx, nil

4
go.mod
View File

@ -45,10 +45,10 @@ require (
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-20210616213533-5ff15b29337e // indirect golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e // indirect
google.golang.org/genproto v0.0.0-20210629200056-84d6f6074151 google.golang.org/genproto v0.0.0-20210701191553-46259e63a0a9
google.golang.org/grpc v1.38.0 google.golang.org/grpc v1.38.0
gopkg.in/yaml.v2 v2.4.0 gopkg.in/yaml.v2 v2.4.0
nhooyr.io/websocket v1.8.7 // indirect nhooyr.io/websocket v1.8.7 // indirect
) )
replace github.com/gogo/protobuf => github.com/regen-network/protobuf v1.3.2-alpha.regen.4 replace github.com/gogo/protobuf => github.com/regen-network/protobuf v1.3.3-alpha.regen.1

14
go.sum
View File

@ -614,7 +614,7 @@ github.com/kardianos/osext v0.0.0-20190222173326-2bc1f35cddc0/go.mod h1:1NbS8ALr
github.com/keybase/go-keychain v0.0.0-20190712205309-48d3d31d256d h1:Z+RDyXzjKE0i2sTjZ/b1uxiGtPhFy34Ou/Tk0qwN0kM= github.com/keybase/go-keychain v0.0.0-20190712205309-48d3d31d256d h1:Z+RDyXzjKE0i2sTjZ/b1uxiGtPhFy34Ou/Tk0qwN0kM=
github.com/keybase/go-keychain v0.0.0-20190712205309-48d3d31d256d/go.mod h1:JJNrCn9otv/2QP4D7SMJBgaleKpOf66PnW6F5WGNRIc= github.com/keybase/go-keychain v0.0.0-20190712205309-48d3d31d256d/go.mod h1:JJNrCn9otv/2QP4D7SMJBgaleKpOf66PnW6F5WGNRIc=
github.com/kilic/bls12-381 v0.0.0-20201226121925-69dacb279461/go.mod h1:vDTTHJONJ6G+P2R74EhnyotQDTliQDnFEwhdmfzw1ig= github.com/kilic/bls12-381 v0.0.0-20201226121925-69dacb279461/go.mod h1:vDTTHJONJ6G+P2R74EhnyotQDTliQDnFEwhdmfzw1ig=
github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23/go.mod h1:J+Gs4SYgM6CZQHDETBtE9HaSEkGmuNXF86RwHhHUvq4= github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23/go.mod h1:J+Gs4SYgM6CZQHDETBtE9HaSEkGmuNXF86RwHhHUvq4=
github.com/kkdai/bstream v1.0.0/go.mod h1:FDnDOHt5Yx4p3FaHcioFT0QjDOtgUpvjeZqAs+NVZZA= github.com/kkdai/bstream v1.0.0/go.mod h1:FDnDOHt5Yx4p3FaHcioFT0QjDOtgUpvjeZqAs+NVZZA=
@ -859,8 +859,8 @@ github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 h1:N/ElC8H3+5X
github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4=
github.com/regen-network/cosmos-proto v0.3.1 h1:rV7iM4SSFAagvy8RiyhiACbWEGotmqzywPxOvwMdxcg= github.com/regen-network/cosmos-proto v0.3.1 h1:rV7iM4SSFAagvy8RiyhiACbWEGotmqzywPxOvwMdxcg=
github.com/regen-network/cosmos-proto v0.3.1/go.mod h1:jO0sVX6a1B36nmE8C9xBFXpNwWejXC7QqCOnH3O0+YM= github.com/regen-network/cosmos-proto v0.3.1/go.mod h1:jO0sVX6a1B36nmE8C9xBFXpNwWejXC7QqCOnH3O0+YM=
github.com/regen-network/protobuf v1.3.2-alpha.regen.4 h1:c9jEnU+xm6vqyrQe3M94UFWqiXxRIKKnqBOh2EACmBE= github.com/regen-network/protobuf v1.3.3-alpha.regen.1 h1:OHEc+q5iIAXpqiqFKeLpu5NwTIkVXUs48vFMwzqpqY4=
github.com/regen-network/protobuf v1.3.2-alpha.regen.4/go.mod h1:/J8/bR1T/NXyIdQDLUaq15LjNE83nRzkyrLAMcPewig= github.com/regen-network/protobuf v1.3.3-alpha.regen.1/go.mod h1:2DjTFR1HhMQhiWC5sZ4OhQ3+NtdbZ6oBDKQwq5Ou+FI=
github.com/retailnext/hllpp v1.0.1-0.20180308014038-101a6d2f8b52/go.mod h1:RDpi1RftBQPUCDRw6SmxeaREsAaRKnOclghuzp/WRzc= github.com/retailnext/hllpp v1.0.1-0.20180308014038-101a6d2f8b52/go.mod h1:RDpi1RftBQPUCDRw6SmxeaREsAaRKnOclghuzp/WRzc=
github.com/rjeczalik/notify v0.9.1/go.mod h1:rKwnCoCGeuQnwBtTSPL9Dad03Vh2n40ePRrjvIXnJho= github.com/rjeczalik/notify v0.9.1/go.mod h1:rKwnCoCGeuQnwBtTSPL9Dad03Vh2n40ePRrjvIXnJho=
github.com/rjeczalik/notify v0.9.2 h1:MiTWrPj55mNDHEiIX5YUSKefw/+lCQVoAFmD6oQm5w8= github.com/rjeczalik/notify v0.9.2 h1:MiTWrPj55mNDHEiIX5YUSKefw/+lCQVoAFmD6oQm5w8=
@ -1321,7 +1321,6 @@ golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba/go.mod h1:tRJNPiyCQ0inRvYxb
golang.org/x/tools v0.0.0-20180525024113-a5b4c53f6e8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180525024113-a5b4c53f6e8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190206041539-40960b6deb8e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190206041539-40960b6deb8e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
@ -1350,7 +1349,6 @@ golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapK
golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200103221440-774c71fcf114/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200103221440-774c71fcf114/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200108203644-89082a384178/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200108203644-89082a384178/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200110213125-a7a6caa82ab2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200117012304-6edc0a871e69/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200117012304-6edc0a871e69/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200117161641-43d50277825c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200117161641-43d50277825c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200122220014-bf1340f18c4a/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200122220014-bf1340f18c4a/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
@ -1368,6 +1366,7 @@ golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roY
golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20200522201501-cb1345f3a375/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200522201501-cb1345f3a375/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20200717024301-6ddee64345a6/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= golang.org/x/tools v0.0.0-20200717024301-6ddee64345a6/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
@ -1377,6 +1376,7 @@ golang.org/x/tools v0.0.0-20201110124207-079ba7bd75cd/go.mod h1:emZCQorbCU4vsT4f
golang.org/x/tools v0.0.0-20201201161351-ac6f37ff4c2a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20201201161351-ac6f37ff4c2a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.0.0-20201208233053-a543418bbed2/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20201208233053-a543418bbed2/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0=
golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
@ -1473,8 +1473,8 @@ google.golang.org/genproto v0.0.0-20210310155132-4ce2db91004e/go.mod h1:FWY/as6D
google.golang.org/genproto v0.0.0-20210319143718-93e7006c17a6/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20210319143718-93e7006c17a6/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20210402141018-6c239bbf2bb1/go.mod h1:9lPAdzaEmUacj36I+k7YKbEc5CXzPIeORRgDAUOu28A= google.golang.org/genproto v0.0.0-20210402141018-6c239bbf2bb1/go.mod h1:9lPAdzaEmUacj36I+k7YKbEc5CXzPIeORRgDAUOu28A=
google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0=
google.golang.org/genproto v0.0.0-20210629200056-84d6f6074151 h1:H/uPzsolsGjhl3CVT6Wb7bK+mf+hmkEvUVu+FBKyNlc= google.golang.org/genproto v0.0.0-20210701191553-46259e63a0a9 h1:HBPuvo39L0DgfVn9eHR3ki/RjZoUFWa+em77e7KFDfs=
google.golang.org/genproto v0.0.0-20210629200056-84d6f6074151/go.mod h1:yiaVoXHpRzHGyxV3o4DktVWY4mSUErTKaeEOq6C3t3U= google.golang.org/genproto v0.0.0-20210701191553-46259e63a0a9/go.mod h1:yiaVoXHpRzHGyxV3o4DktVWY4mSUErTKaeEOq6C3t3U=
google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs= google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs=
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
google.golang.org/grpc v1.19.1/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.19.1/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=

View File

@ -197,47 +197,6 @@ message TxResult {
uint64 gas_used = 6; uint64 gas_used = 6;
} }
// TxData implements the Ethereum transaction data structure. It is used
// solely as intended in Ethereum abiding by the protocol.
message TxData {
option (gogoproto.goproto_getters) = false;
// destination EVM chain ID
string chain_id = 1 [
(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Int",
(gogoproto.customname) = "ChainID",
(gogoproto.jsontag) = "chainID",
(gogoproto.nullable) = false
];
// nonce corresponds to the account nonce (transaction sequence).
uint64 nonce = 2;
// gas price defines the value for each gas unit
string gas_price = 3 [
(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Int",
(gogoproto.nullable) = false
];
// gas defines the gas limit defined for the transaction.
uint64 gas = 4 [(gogoproto.customname) = "GasLimit"];
// hex formatted address of the recipient
string to = 5;
// value defines the unsigned integer value of the transaction amount.
string value = 6 [
(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Int",
(gogoproto.customname) = "Amount",
(gogoproto.nullable) = false
];
// input defines the data payload bytes of the transaction.
bytes input = 7;
repeated AccessTuple accesses = 8
[(gogoproto.castrepeated) = "AccessList", (gogoproto.jsontag) = "accessList", (gogoproto.nullable) = false];
// v defines the signature value
bytes v = 9;
// r defines the signature value
bytes r = 10;
// s define the signature value
bytes s = 11;
}
// 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;

View File

@ -2,6 +2,8 @@ syntax = "proto3";
package ethermint.evm.v1alpha1; package ethermint.evm.v1alpha1;
import "gogoproto/gogo.proto"; import "gogoproto/gogo.proto";
import "google/protobuf/any.proto";
import "cosmos_proto/cosmos.proto";
import "ethermint/evm/v1alpha1/evm.proto"; import "ethermint/evm/v1alpha1/evm.proto";
option go_package = "github.com/tharsis/ethermint/x/evm/types"; option go_package = "github.com/tharsis/ethermint/x/evm/types";
@ -17,7 +19,7 @@ message MsgEthereumTx {
option (gogoproto.goproto_getters) = false; option (gogoproto.goproto_getters) = false;
// inner transaction data // inner transaction data
TxData data = 1; google.protobuf.Any data = 1;
// caches // caches
// encoded storage size of the transaction // encoded storage size of the transaction
@ -30,6 +32,75 @@ message MsgEthereumTx {
string from = 4; string from = 4;
} }
// LegacyTx is the transaction data of regular Ethereum transactions.
message LegacyTx {
option (gogoproto.goproto_getters) = false;
option (cosmos_proto.implements_interface) = "TxDataI";
// nonce corresponds to the account nonce (transaction sequence).
uint64 nonce = 1;
// gas price defines the value for each gas unit
string gas_price = 2 [
(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Int"
];
// gas defines the gas limit defined for the transaction.
uint64 gas = 3 [(gogoproto.customname) = "GasLimit"];
// hex formatted address of the recipient
string to = 4;
// value defines the unsigned integer value of the transaction amount.
string value = 5 [
(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Int",
(gogoproto.customname) = "Amount"
];
// input defines the data payload bytes of the transaction.
bytes data = 6;
// v defines the signature value
bytes v = 7;
// r defines the signature value
bytes r = 8;
// s define the signature value
bytes s = 9;
}
// AccessListTx is the data of EIP-2930 access list transactions.
message AccessListTx {
option (gogoproto.goproto_getters) = false;
option (cosmos_proto.implements_interface) = "TxDataI";
// destination EVM chain ID
string chain_id = 1 [
(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Int",
(gogoproto.customname) = "ChainID",
(gogoproto.jsontag) = "chainID"
];
// nonce corresponds to the account nonce (transaction sequence).
uint64 nonce = 2;
// gas price defines the value for each gas unit
string gas_price = 3 [
(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Int"
];
// gas defines the gas limit defined for the transaction.
uint64 gas = 4 [(gogoproto.customname) = "GasLimit"];
// hex formatted address of the recipient
string to = 5;
// value defines the unsigned integer value of the transaction amount.
string value = 6 [
(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Int",
(gogoproto.customname) = "Amount"
];
// input defines the data payload bytes of the transaction.
bytes data = 7;
repeated AccessTuple accesses = 8
[(gogoproto.castrepeated) = "AccessList", (gogoproto.jsontag) = "accessList", (gogoproto.nullable) = false];
// v defines the signature value
bytes v = 9;
// r defines the signature value
bytes r = 10;
// s define the signature value
bytes s = 11;
}
message ExtensionOptionsEthereumTx { message ExtensionOptionsEthereumTx {
option (gogoproto.goproto_getters) = false; option (gogoproto.goproto_getters) = false;
} }

View File

@ -23,13 +23,8 @@ for dir in $proto_dirs; do
buf protoc \ buf protoc \
-I "proto" \ -I "proto" \
-I "third_party/proto" \ -I "third_party/proto" \
--gocosmos_out=plugins=interfacetype+grpc:. \ --gocosmos_out=plugins=interfacetype+grpc,\
$(find "${dir}" -maxdepth 1 -name '*.proto') Mgoogle/protobuf/any.proto=github.com/cosmos/cosmos-sdk/codec/types:. \
# command to generate gRPC gateway (*.pb.gw.go in respective modules) files
buf protoc \
-I "proto" \
-I "third_party/proto" \
--grpc-gateway_out=logtostderr=true:. \ --grpc-gateway_out=logtostderr=true:. \
$(find "${dir}" -maxdepth 1 -name '*.proto') $(find "${dir}" -maxdepth 1 -name '*.proto')
@ -42,7 +37,7 @@ buf protoc \
--doc_out=./docs/core \ --doc_out=./docs/core \
--doc_opt=./docs/protodoc-markdown.tmpl,proto-docs.md \ --doc_opt=./docs/protodoc-markdown.tmpl,proto-docs.md \
$(find "$(pwd)/proto" -maxdepth 5 -name '*.proto') $(find "$(pwd)/proto" -maxdepth 5 -name '*.proto')
go mod tidy # go mod tidy
# move proto files to the right places # move proto files to the right places
cp -r github.com/tharsis/ethermint/* ./ cp -r github.com/tharsis/ethermint/* ./

View File

@ -276,10 +276,7 @@ func (m *EthAccount) Unmarshal(dAtA []byte) error {
if err != nil { if err != nil {
return err return err
} }
if skippy < 0 { if (skippy < 0) || (iNdEx+skippy) < 0 {
return ErrInvalidLengthAccount
}
if (iNdEx + skippy) < 0 {
return ErrInvalidLengthAccount return ErrInvalidLengthAccount
} }
if (iNdEx + skippy) > l { if (iNdEx + skippy) > l {

View File

@ -78,7 +78,7 @@ func TestEvmTestSuite(t *testing.T) {
// "passed", // "passed",
// func() { // func() {
// to := ethcmn.BytesToAddress(suite.to) // to := ethcmn.BytesToAddress(suite.to)
// tx = types.NewMsgEthereumTx(suite.chainID, 0, &to, big.NewInt(100), 0, big.NewInt(10000), nil, nil) // tx = types.NewTx(suite.chainID, 0, &to, big.NewInt(100), 0, big.NewInt(10000), nil, nil)
// tx.From = suite.from.String() // tx.From = suite.from.String()
// // sign transaction // // sign transaction
@ -90,7 +90,7 @@ func TestEvmTestSuite(t *testing.T) {
// { // {
// "insufficient balance", // "insufficient balance",
// func() { // func() {
// tx = types.NewMsgEthereumTxContract(suite.chainID, 0, big.NewInt(100), 0, big.NewInt(10000), nil, nil) // tx = types.NewTxContract(suite.chainID, 0, big.NewInt(100), 0, big.NewInt(10000), nil, nil)
// tx.From = suite.from.Hex() // tx.From = suite.from.Hex()
// // sign transaction // // sign transaction
// err := tx.Sign(suite.ethSigner, suite.signer) // err := tx.Sign(suite.ethSigner, suite.signer)
@ -101,7 +101,7 @@ func TestEvmTestSuite(t *testing.T) {
// { // {
// "tx encoding failed", // "tx encoding failed",
// func() { // func() {
// tx = types.NewMsgEthereumTxContract(suite.chainID, 0, big.NewInt(100), 0, big.NewInt(10000), nil, nil) // tx = types.NewTxContract(suite.chainID, 0, big.NewInt(100), 0, big.NewInt(10000), nil, nil)
// }, // },
// false, // false,
// }, // },
@ -115,7 +115,7 @@ func TestEvmTestSuite(t *testing.T) {
// { // {
// "VerifySig failed", // "VerifySig failed",
// func() { // func() {
// tx = types.NewMsgEthereumTxContract(suite.chainID, 0, big.NewInt(100), 0, big.NewInt(10000), nil, nil) // tx = types.NewTxContract(suite.chainID, 0, big.NewInt(100), 0, big.NewInt(10000), nil, nil)
// }, // },
// false, // false,
// }, // },
@ -165,7 +165,7 @@ func TestEvmTestSuite(t *testing.T) {
// gasPrice := big.NewInt(1000000) // gasPrice := big.NewInt(1000000)
// bytecode := common.FromHex("0x6080604052348015600f57600080fd5b5060117f775a94827b8fd9b519d36cd827093c664f93347070a554f65e4a6f56cd73889860405160405180910390a2603580604b6000396000f3fe6080604052600080fdfea165627a7a723058206cab665f0f557620554bb45adf266708d2bd349b8a4314bdff205ee8440e3c240029") // bytecode := common.FromHex("0x6080604052348015600f57600080fd5b5060117f775a94827b8fd9b519d36cd827093c664f93347070a554f65e4a6f56cd73889860405160405180910390a2603580604b6000396000f3fe6080604052600080fdfea165627a7a723058206cab665f0f557620554bb45adf266708d2bd349b8a4314bdff205ee8440e3c240029")
// tx := types.NewMsgEthereumTx(suite.chainID, 1, nil, big.NewInt(0), gasLimit, gasPrice, bytecode, nil) // tx := types.NewTx(suite.chainID, 1, nil, big.NewInt(0), gasLimit, gasPrice, bytecode, nil)
// tx.From = suite.from.String() // tx.From = suite.from.String()
// err := tx.Sign(suite.ethSigner, suite.signer) // err := tx.Sign(suite.ethSigner, suite.signer)
@ -249,7 +249,7 @@ func TestEvmTestSuite(t *testing.T) {
// gasPrice := big.NewInt(10000) // gasPrice := big.NewInt(10000)
// bytecode := common.FromHex("0x608060405234801561001057600080fd5b50336000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167f342827c97908e5e2f71151c08502a66d44b6f758e3ac2f1de95f02eb95f0a73560405160405180910390a36102c4806100dc6000396000f3fe608060405234801561001057600080fd5b5060043610610053576000357c010000000000000000000000000000000000000000000000000000000090048063893d20e814610058578063a6f9dae1146100a2575b600080fd5b6100606100e6565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b6100e4600480360360208110156100b857600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919050505061010f565b005b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146101d1576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260138152602001807f43616c6c6572206973206e6f74206f776e65720000000000000000000000000081525060200191505060405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff166000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f342827c97908e5e2f71151c08502a66d44b6f758e3ac2f1de95f02eb95f0a73560405160405180910390a3806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505056fea265627a7a72315820f397f2733a89198bc7fed0764083694c5b828791f39ebcbc9e414bccef14b48064736f6c63430005100032") // bytecode := common.FromHex("0x608060405234801561001057600080fd5b50336000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167f342827c97908e5e2f71151c08502a66d44b6f758e3ac2f1de95f02eb95f0a73560405160405180910390a36102c4806100dc6000396000f3fe608060405234801561001057600080fd5b5060043610610053576000357c010000000000000000000000000000000000000000000000000000000090048063893d20e814610058578063a6f9dae1146100a2575b600080fd5b6100606100e6565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b6100e4600480360360208110156100b857600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919050505061010f565b005b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146101d1576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260138152602001807f43616c6c6572206973206e6f74206f776e65720000000000000000000000000081525060200191505060405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff166000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f342827c97908e5e2f71151c08502a66d44b6f758e3ac2f1de95f02eb95f0a73560405160405180910390a3806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505056fea265627a7a72315820f397f2733a89198bc7fed0764083694c5b828791f39ebcbc9e414bccef14b48064736f6c63430005100032")
// tx := types.NewMsgEthereumTx(suite.chainID, 1, nil, big.NewInt(0), gasLimit, gasPrice, bytecode, nil) // tx := types.NewTx(suite.chainID, 1, nil, big.NewInt(0), gasLimit, gasPrice, bytecode, nil)
// tx.From = suite.from.String() // tx.From = suite.from.String()
// err := tx.Sign(suite.ethSigner, suite.signer) // err := tx.Sign(suite.ethSigner, suite.signer)
@ -268,7 +268,7 @@ func TestEvmTestSuite(t *testing.T) {
// storeAddr := "0xa6f9dae10000000000000000000000006a82e4a67715c8412a9114fbd2cbaefbc8181424" // storeAddr := "0xa6f9dae10000000000000000000000006a82e4a67715c8412a9114fbd2cbaefbc8181424"
// bytecode = common.FromHex(storeAddr) // bytecode = common.FromHex(storeAddr)
// tx = types.NewMsgEthereumTx(suite.chainID, 2, &receiver, big.NewInt(0), gasLimit, gasPrice, bytecode, nil) // tx = types.NewTx(suite.chainID, 2, &receiver, big.NewInt(0), gasLimit, gasPrice, bytecode, nil)
// tx.From = suite.from.String() // tx.From = suite.from.String()
// err = tx.Sign(suite.ethSigner, suite.signer) // err = tx.Sign(suite.ethSigner, suite.signer)
@ -282,7 +282,7 @@ func TestEvmTestSuite(t *testing.T) {
// // query - getOwner // // query - getOwner
// bytecode = common.FromHex("0x893d20e8") // bytecode = common.FromHex("0x893d20e8")
// tx = types.NewMsgEthereumTx(suite.chainID, 2, &receiver, big.NewInt(0), gasLimit, gasPrice, bytecode, nil) // tx = types.NewTx(suite.chainID, 2, &receiver, big.NewInt(0), gasLimit, gasPrice, bytecode, nil)
// tx.From = suite.from.String() // tx.From = suite.from.String()
// err = tx.Sign(suite.ethSigner, suite.signer) // err = tx.Sign(suite.ethSigner, suite.signer)
// suite.Require().NoError(err) // suite.Require().NoError(err)
@ -302,7 +302,7 @@ func TestEvmTestSuite(t *testing.T) {
// gasPrice := big.NewInt(0x55ae82600) // gasPrice := big.NewInt(0x55ae82600)
// // send simple value transfer with gasLimit=21000 // // send simple value transfer with gasLimit=21000
// tx := types.NewMsgEthereumTx(suite.chainID, 1, &ethcmn.Address{0x1}, big.NewInt(1), gasLimit, gasPrice, nil, nil) // tx := types.NewTx(suite.chainID, 1, &ethcmn.Address{0x1}, big.NewInt(1), gasLimit, gasPrice, nil, nil)
// tx.From = suite.from.String() // tx.From = suite.from.String()
// err := tx.Sign(suite.ethSigner, suite.signer) // err := tx.Sign(suite.ethSigner, suite.signer)
// suite.Require().NoError(err) // suite.Require().NoError(err)
@ -373,7 +373,7 @@ func TestEvmTestSuite(t *testing.T) {
// gasPrice := big.NewInt(10000) // gasPrice := big.NewInt(10000)
// bytecode := common.FromHex("0x608060405234801561001057600080fd5b50336000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167f342827c97908e5e2f71151c08502a66d44b6f758e3ac2f1de95f02eb95f0a73560405160405180910390a36102c4806100dc6000396000f3fe608060405234801561001057600080fd5b5060043610610053576000357c010000000000000000000000000000000000000000000000000000000090048063893d20e814610058578063a6f9dae1146100a2575b600080fd5b6100606100e6565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b6100e4600480360360208110156100b857600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919050505061010f565b005b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146101d1576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260138152602001807f43616c6c6572206973206e6f74206f776e65720000000000000000000000000081525060200191505060405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff166000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f342827c97908e5e2f71151c08502a66d44b6f758e3ac2f1de95f02eb95f0a73560405160405180910390a3806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505056fea265627a7a72315820f397f2733a89198bc7fed0764083694c5b828791f39ebcbc9e414bccef14b48064736f6c63430005100032") // bytecode := common.FromHex("0x608060405234801561001057600080fd5b50336000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167f342827c97908e5e2f71151c08502a66d44b6f758e3ac2f1de95f02eb95f0a73560405160405180910390a36102c4806100dc6000396000f3fe608060405234801561001057600080fd5b5060043610610053576000357c010000000000000000000000000000000000000000000000000000000090048063893d20e814610058578063a6f9dae1146100a2575b600080fd5b6100606100e6565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b6100e4600480360360208110156100b857600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919050505061010f565b005b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146101d1576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260138152602001807f43616c6c6572206973206e6f74206f776e65720000000000000000000000000081525060200191505060405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff166000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f342827c97908e5e2f71151c08502a66d44b6f758e3ac2f1de95f02eb95f0a73560405160405180910390a3806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505056fea265627a7a72315820f397f2733a89198bc7fed0764083694c5b828791f39ebcbc9e414bccef14b48064736f6c63430005100032")
// tx := types.NewMsgEthereumTx(suite.chainID, 1, nil, big.NewInt(0), gasLimit, gasPrice, bytecode, nil) // tx := types.NewTx(suite.chainID, 1, nil, big.NewInt(0), gasLimit, gasPrice, bytecode, nil)
// tx.From = suite.from.String() // tx.From = suite.from.String()
// err := tx.Sign(suite.ethSigner, suite.signer) // err := tx.Sign(suite.ethSigner, suite.signer)
@ -402,7 +402,7 @@ func TestEvmTestSuite(t *testing.T) {
// bytecode := common.FromHex("0xa6f9dae10000000000000000000000006a82e4a67715c8412a9114fbd2cbaefbc8181424") // bytecode := common.FromHex("0xa6f9dae10000000000000000000000006a82e4a67715c8412a9114fbd2cbaefbc8181424")
// tx := types.NewMsgEthereumTx(suite.chainID, 1, nil, big.NewInt(0), gasLimit, gasPrice, bytecode, nil) // tx := types.NewTx(suite.chainID, 1, nil, big.NewInt(0), gasLimit, gasPrice, bytecode, nil)
// tx.From = suite.from.String() // tx.From = suite.from.String()
// err := tx.Sign(suite.ethSigner, suite.signer) // err := tx.Sign(suite.ethSigner, suite.signer)

View File

@ -314,7 +314,7 @@ func (k Keeper) StaticCall(c context.Context, req *types.QueryStaticCallRequest)
// so := k.GetOrNewStateObject(*recipient) // so := k.GetOrNewStateObject(*recipient)
// sender := ethcmn.HexToAddress("0xaDd00275E3d9d213654Ce5223f0FADE8b106b707") // sender := ethcmn.HexToAddress("0xaDd00275E3d9d213654Ce5223f0FADE8b106b707")
// msg := types.NewMsgEthereumTx( // msg := types.NewTx(
// chainIDEpoch, so.Nonce(), recipient, big.NewInt(0), 100000000, big.NewInt(0), req.Input, nil, // chainIDEpoch, so.Nonce(), recipient, big.NewInt(0), 100000000, big.NewInt(0), req.Input, nil,
// ) // )
// msg.From = sender.Hex() // msg.From = sender.Hex()

View File

@ -24,21 +24,21 @@ func (k *Keeper) EthereumTx(goCtx context.Context, msg *types.MsgEthereumTx) (*t
ctx := sdk.UnwrapSDKContext(goCtx) ctx := sdk.UnwrapSDKContext(goCtx)
k.WithContext(ctx) k.WithContext(ctx)
sender := msg.From
tx := msg.AsTransaction()
var labels []metrics.Label var labels []metrics.Label
if msg.To() == nil { if tx.To() == nil {
labels = []metrics.Label{ labels = []metrics.Label{
telemetry.NewLabel("execution", "create"), telemetry.NewLabel("execution", "create"),
} }
} else { } else {
labels = []metrics.Label{ labels = []metrics.Label{
telemetry.NewLabel("execution", "call"), telemetry.NewLabel("execution", "call"),
telemetry.NewLabel("to", msg.Data.To), // recipient address (contract or account) telemetry.NewLabel("to", tx.To().Hex()), // recipient address (contract or account)
} }
} }
sender := msg.From
tx := msg.AsTransaction()
response, err := k.ApplyTransaction(tx) response, err := k.ApplyTransaction(tx)
if err != nil { if err != nil {
return nil, stacktrace.Propagate(err, "failed to apply transaction") return nil, stacktrace.Propagate(err, "failed to apply transaction")
@ -71,8 +71,8 @@ func (k *Keeper) EthereumTx(goCtx context.Context, msg *types.MsgEthereumTx) (*t
attrs = append(attrs, sdk.NewAttribute(types.AttributeKeyTxHash, hash.String())) attrs = append(attrs, sdk.NewAttribute(types.AttributeKeyTxHash, hash.String()))
} }
if len(msg.Data.To) > 0 { if tx.To() != nil {
attrs = append(attrs, sdk.NewAttribute(types.AttributeKeyRecipient, msg.Data.To)) attrs = append(attrs, sdk.NewAttribute(types.AttributeKeyRecipient, tx.To().Hex()))
} }
// emit events // emit events

View File

@ -478,7 +478,7 @@ func (suite *KeeperTestSuite) CreateTestTx(msg *evmtypes.MsgEthereumTx, priv cry
func (suite *KeeperTestSuite) TestAddLog() { func (suite *KeeperTestSuite) TestAddLog() {
addr, privKey := tests.NewAddrKey() addr, privKey := tests.NewAddrKey()
msg := types.NewMsgEthereumTx(big.NewInt(1), 0, &suite.address, big.NewInt(1), 100000, big.NewInt(1), []byte("test"), nil) msg := types.NewTx(big.NewInt(1), 0, &suite.address, big.NewInt(1), 100000, big.NewInt(1), []byte("test"), nil)
msg.From = addr.Hex() msg.From = addr.Hex()
tx := suite.CreateTestTx(msg, privKey) tx := suite.CreateTestTx(msg, privKey)

View File

@ -0,0 +1,205 @@
package types
import (
"math/big"
sdk "github.com/cosmos/cosmos-sdk/types"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
"github.com/ethereum/go-ethereum/common"
ethtypes "github.com/ethereum/go-ethereum/core/types"
"github.com/tharsis/ethermint/types"
)
func newAccessListTx(tx *ethtypes.Transaction) *AccessListTx {
txData := &AccessListTx{
Nonce: tx.Nonce(),
Data: tx.Data(),
GasLimit: tx.Gas(),
}
v, r, s := tx.RawSignatureValues()
if tx.To() != nil {
txData.To = tx.To().Hex()
}
if tx.Value() != nil {
amountInt := sdk.NewIntFromBigInt(tx.Value())
txData.Amount = &amountInt
}
if tx.GasPrice() != nil {
gasPriceInt := sdk.NewIntFromBigInt(tx.GasPrice())
txData.GasPrice = &gasPriceInt
}
if tx.AccessList() != nil {
al := tx.AccessList()
txData.Accesses = NewAccessList(&al)
}
txData.SetSignatureValues(tx.ChainId(), v, r, s)
return txData
}
// TxType returns the tx type
func (tx *AccessListTx) TxType() uint8 {
return ethtypes.AccessListTxType
}
// Copy returns an instance with the same field values
func (tx *AccessListTx) Copy() TxData {
return &AccessListTx{
ChainID: tx.ChainID,
Nonce: tx.Nonce,
GasPrice: tx.GasPrice,
GasLimit: tx.GasLimit,
To: tx.To,
Amount: tx.Amount,
Data: common.CopyBytes(tx.Data),
Accesses: tx.Accesses,
V: common.CopyBytes(tx.V),
R: common.CopyBytes(tx.R),
S: common.CopyBytes(tx.S),
}
}
// GetChainID returns the chain id field from the AccessListTx
func (tx *AccessListTx) GetChainID() *big.Int {
if tx.ChainID == nil {
return nil
}
return tx.ChainID.BigInt()
}
// GetAccessList returns the AccessList field.
func (tx *AccessListTx) GetAccessList() ethtypes.AccessList {
if tx.Accesses == nil {
return nil
}
return *tx.Accesses.ToEthAccessList()
}
// GetData returns the a copy of the input data bytes.
func (tx *AccessListTx) GetData() []byte {
return common.CopyBytes(tx.Data)
}
// GetGas returns the gas limit.
func (tx *AccessListTx) GetGas() uint64 {
return tx.GasLimit
}
// GetGasPrice returns the gas price field.
func (tx *AccessListTx) GetGasPrice() *big.Int {
if tx.GasPrice == nil {
return nil
}
return tx.GasPrice.BigInt()
}
// GetValue returns the tx amount.
func (tx *AccessListTx) GetValue() *big.Int {
if tx.Amount == nil {
return nil
}
return tx.Amount.BigInt()
}
// GetNonce returns the account sequence for the transaction.
func (tx *AccessListTx) GetNonce() uint64 { return tx.Nonce }
// GetTo returns the pointer to the recipient address.
func (tx *AccessListTx) GetTo() *common.Address {
if tx.To == "" {
return nil
}
to := common.HexToAddress(tx.To)
return &to
}
// AsEthereumData returns an AccessListTx transaction tx from the proto-formatted
// TxData defined on the Cosmos EVM.
func (tx *AccessListTx) AsEthereumData() ethtypes.TxData {
v, r, s := tx.GetRawSignatureValues()
return &ethtypes.AccessListTx{
ChainID: tx.GetChainID(),
Nonce: tx.GetNonce(),
GasPrice: tx.GetGasPrice(),
Gas: tx.GetGas(),
To: tx.GetTo(),
Value: tx.GetValue(),
Data: tx.GetData(),
AccessList: tx.GetAccessList(),
V: v,
R: r,
S: s,
}
}
// GetRawSignatureValues returns the V, R, S signature values of the transaction.
// The return values should not be modified by the caller.
func (tx *AccessListTx) GetRawSignatureValues() (v, r, s *big.Int) {
return rawSignatureValues(tx.V, tx.R, tx.S)
}
// SetSignatureValues sets the signature values to the transaction.
func (tx *AccessListTx) SetSignatureValues(chainID, v, r, s *big.Int) {
if v != nil {
tx.V = v.Bytes()
}
if r != nil {
tx.R = r.Bytes()
}
if s != nil {
tx.S = s.Bytes()
}
if chainID != nil {
chainIDInt := sdk.NewIntFromBigInt(chainID)
tx.ChainID = &chainIDInt
}
}
// Validate performs a stateless validation of the tx fields.
func (tx AccessListTx) Validate() error {
gasPrice := tx.GetGasPrice()
if gasPrice == nil {
return sdkerrors.Wrap(ErrInvalidGasPrice, "cannot be nil")
}
if gasPrice.Sign() == -1 {
return sdkerrors.Wrapf(ErrInvalidGasPrice, "gas price cannot be negative %s", gasPrice)
}
amount := tx.GetValue()
// Amount can be 0
if amount != nil && amount.Sign() == -1 {
return sdkerrors.Wrapf(ErrInvalidAmount, "amount cannot be negative %s", amount)
}
if tx.To != "" {
if err := types.ValidateAddress(tx.To); err != nil {
return sdkerrors.Wrap(err, "invalid to address")
}
}
if tx.GetChainID() == nil {
return sdkerrors.Wrap(
sdkerrors.ErrInvalidChainID,
"chain ID must be present on AccessList txs",
)
}
return nil
}
// Fee returns gasprice * gaslimit.
func (tx AccessListTx) Fee() *big.Int {
return fee(tx.GetGasPrice(), tx.GetGas())
}
// Cost returns amount + gasprice * gaslimit.
func (tx AccessListTx) Cost() *big.Int {
return cost(tx.Fee(), tx.GetValue())
}

View File

@ -4,6 +4,13 @@ import (
"github.com/cosmos/cosmos-sdk/codec" "github.com/cosmos/cosmos-sdk/codec"
codectypes "github.com/cosmos/cosmos-sdk/codec/types" codectypes "github.com/cosmos/cosmos-sdk/codec/types"
sdk "github.com/cosmos/cosmos-sdk/types" sdk "github.com/cosmos/cosmos-sdk/types"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
"github.com/cosmos/cosmos-sdk/types/msgservice"
proto "github.com/gogo/protobuf/proto"
)
var (
ModuleCdc = codec.NewProtoCodec(codectypes.NewInterfaceRegistry())
) )
type ( type (
@ -27,8 +34,44 @@ func RegisterInterfaces(registry codectypes.InterfaceRegistry) {
(*ExtensionOptionsWeb3TxI)(nil), (*ExtensionOptionsWeb3TxI)(nil),
&ExtensionOptionsWeb3Tx{}, &ExtensionOptionsWeb3Tx{},
) )
registry.RegisterInterface(
"ethermint.evm.v1alpha1.TxData",
(*TxData)(nil),
&AccessListTx{},
&LegacyTx{},
)
msgservice.RegisterMsgServiceDesc(registry, &_Msg_serviceDesc)
} }
var ( // PackClientState constructs a new Any packed with the given tx data value. It returns
ModuleCdc = codec.NewProtoCodec(codectypes.NewInterfaceRegistry()) // an error if the client state can't be casted to a protobuf message or if the concrete
) // implemention is not registered to the protobuf codec.
func PackTxData(txData TxData) (*codectypes.Any, error) {
msg, ok := txData.(proto.Message)
if !ok {
return nil, sdkerrors.Wrapf(sdkerrors.ErrPackAny, "cannot proto marshal %T", txData)
}
anyTxData, err := codectypes.NewAnyWithValue(msg)
if err != nil {
return nil, sdkerrors.Wrap(sdkerrors.ErrPackAny, err.Error())
}
return anyTxData, nil
}
// UnpackTxData unpacks an Any into a TxData. It returns an error if the
// client state can't be unpacked into a TxData.
func UnpackTxData(any *codectypes.Any) (TxData, error) {
if any == nil {
return nil, sdkerrors.Wrap(sdkerrors.ErrUnpackAny, "protobuf Any message cannot be nil")
}
txData, ok := any.GetCachedValue().(TxData)
if !ok {
return nil, sdkerrors.Wrapf(sdkerrors.ErrUnpackAny, "cannot unpack Any into TxData %T", any)
}
return txData, nil
}

62
x/evm/types/codec_test.go Normal file
View File

@ -0,0 +1,62 @@
package types
import (
"testing"
codectypes "github.com/cosmos/cosmos-sdk/codec/types"
"github.com/stretchr/testify/require"
)
type caseAny struct {
name string
any *codectypes.Any
expPass bool
}
func TestPackTxData(t *testing.T) {
testCases := []struct {
name string
txData TxData
expPass bool
}{
{
"access list tx",
&AccessListTx{},
true,
},
{
"legacy tx",
&LegacyTx{},
true,
},
{
"nil",
nil,
false,
},
}
testCasesAny := []caseAny{}
for _, tc := range testCases {
txDataAny, err := PackTxData(tc.txData)
if tc.expPass {
require.NoError(t, err, tc.name)
} else {
require.Error(t, err, tc.name)
}
testCasesAny = append(testCasesAny, caseAny{tc.name, txDataAny, tc.expPass})
}
for i, tc := range testCasesAny {
cs, err := UnpackTxData(tc.any)
if tc.expPass {
require.NoError(t, err, tc.name)
require.Equal(t, testCases[i].txData, cs, tc.name)
} else {
require.Error(t, err, tc.name)
}
}
}

View File

@ -473,65 +473,6 @@ func (m *TxResult) XXX_DiscardUnknown() {
var xxx_messageInfo_TxResult proto.InternalMessageInfo var xxx_messageInfo_TxResult proto.InternalMessageInfo
// TxData implements the Ethereum transaction data structure. It is used
// solely as intended in Ethereum abiding by the protocol.
type TxData struct {
// destination EVM chain ID
ChainID github_com_cosmos_cosmos_sdk_types.Int `protobuf:"bytes,1,opt,name=chain_id,json=chainId,proto3,customtype=github.com/cosmos/cosmos-sdk/types.Int" json:"chainID"`
// nonce corresponds to the account nonce (transaction sequence).
Nonce uint64 `protobuf:"varint,2,opt,name=nonce,proto3" json:"nonce,omitempty"`
// gas price defines the value for each gas unit
GasPrice github_com_cosmos_cosmos_sdk_types.Int `protobuf:"bytes,3,opt,name=gas_price,json=gasPrice,proto3,customtype=github.com/cosmos/cosmos-sdk/types.Int" json:"gas_price"`
// gas defines the gas limit defined for the transaction.
GasLimit uint64 `protobuf:"varint,4,opt,name=gas,proto3" json:"gas,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.
Amount github_com_cosmos_cosmos_sdk_types.Int `protobuf:"bytes,6,opt,name=value,proto3,customtype=github.com/cosmos/cosmos-sdk/types.Int" json:"value"`
// input defines the data payload bytes of the transaction.
Input []byte `protobuf:"bytes,7,opt,name=input,proto3" json:"input,omitempty"`
Accesses AccessList `protobuf:"bytes,8,rep,name=accesses,proto3,castrepeated=AccessList" json:"accessList"`
// v defines the signature value
V []byte `protobuf:"bytes,9,opt,name=v,proto3" json:"v,omitempty"`
// r defines the signature value
R []byte `protobuf:"bytes,10,opt,name=r,proto3" json:"r,omitempty"`
// s define the signature value
S []byte `protobuf:"bytes,11,opt,name=s,proto3" json:"s,omitempty"`
}
func (m *TxData) Reset() { *m = TxData{} }
func (m *TxData) String() string { return proto.CompactTextString(m) }
func (*TxData) ProtoMessage() {}
func (*TxData) Descriptor() ([]byte, []int) {
return fileDescriptor_98f00fcca8b6b943, []int{6}
}
func (m *TxData) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
}
func (m *TxData) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
if deterministic {
return xxx_messageInfo_TxData.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 *TxData) XXX_Merge(src proto.Message) {
xxx_messageInfo_TxData.Merge(m, src)
}
func (m *TxData) XXX_Size() int {
return m.Size()
}
func (m *TxData) XXX_DiscardUnknown() {
xxx_messageInfo_TxData.DiscardUnknown(m)
}
var xxx_messageInfo_TxData proto.InternalMessageInfo
// 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
@ -544,7 +485,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{7} return fileDescriptor_98f00fcca8b6b943, []int{6}
} }
func (m *AccessTuple) XXX_Unmarshal(b []byte) error { func (m *AccessTuple) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b) return m.Unmarshal(b)
@ -580,104 +521,91 @@ func init() {
proto.RegisterType((*TransactionLogs)(nil), "ethermint.evm.v1alpha1.TransactionLogs") proto.RegisterType((*TransactionLogs)(nil), "ethermint.evm.v1alpha1.TransactionLogs")
proto.RegisterType((*Log)(nil), "ethermint.evm.v1alpha1.Log") proto.RegisterType((*Log)(nil), "ethermint.evm.v1alpha1.Log")
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((*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{
// 1431 bytes of a gzipped FileDescriptorProto // 1239 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xa4, 0x57, 0xbf, 0x6f, 0x1b, 0xb7, 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xa4, 0x96, 0xbd, 0x6f, 0xdb, 0xc6,
0x17, 0xb7, 0x2c, 0xd9, 0x3e, 0x51, 0x67, 0x59, 0x5f, 0xc6, 0x5f, 0x57, 0x49, 0x00, 0x9f, 0x71, 0x1b, 0xc7, 0x2d, 0x4b, 0xb6, 0xa5, 0x93, 0x2c, 0xe9, 0x77, 0xd1, 0xcf, 0x55, 0x12, 0xc0, 0x34,
0x05, 0x5a, 0x0f, 0x89, 0x14, 0x3b, 0x30, 0x6a, 0x04, 0xe8, 0x20, 0xc5, 0x4e, 0x22, 0xc4, 0x49, 0x6e, 0x68, 0x3d, 0x24, 0x56, 0xec, 0xc0, 0x68, 0x10, 0xa0, 0x83, 0x95, 0x38, 0x89, 0x91, 0xa4,
0x0d, 0xc6, 0x4d, 0x8a, 0x2e, 0x07, 0xea, 0x8e, 0x39, 0x5d, 0x7d, 0x77, 0x54, 0x8f, 0x94, 0x22, 0x0d, 0x2e, 0x6e, 0x52, 0x74, 0x21, 0x4e, 0xe4, 0x85, 0x62, 0x4d, 0xf2, 0x58, 0xde, 0x49, 0x91,
0x15, 0x28, 0xd0, 0xb1, 0x63, 0xbb, 0x75, 0xcc, 0xdc, 0xbf, 0x24, 0xe8, 0x94, 0xb1, 0xe8, 0x70, 0x0a, 0x14, 0xe8, 0xd8, 0xb1, 0xdd, 0x3a, 0xe6, 0xcf, 0x09, 0x3a, 0x65, 0x2c, 0x3a, 0x10, 0x85,
0x2d, 0x94, 0x4d, 0xa3, 0x80, 0x6e, 0x1d, 0x0a, 0xfe, 0xd0, 0x2f, 0xc7, 0x29, 0x20, 0x78, 0x12, 0xbc, 0x79, 0xd4, 0xdc, 0xa1, 0xb8, 0x17, 0xea, 0x2d, 0x6e, 0x01, 0xc1, 0x13, 0xef, 0x79, 0xee,
0x3f, 0x8f, 0x8f, 0x9f, 0x0f, 0xdf, 0xe3, 0x23, 0xdf, 0x09, 0xec, 0x10, 0xde, 0x22, 0x49, 0x14, 0xb9, 0xef, 0x87, 0xcf, 0xdd, 0x73, 0x7c, 0x08, 0x76, 0xa8, 0xe8, 0xd2, 0x24, 0xf4, 0x23, 0xd1,
0xc4, 0xbc, 0x4a, 0xba, 0x51, 0xb5, 0xbb, 0x87, 0xc3, 0x76, 0x0b, 0xef, 0x09, 0x50, 0x69, 0x27, 0xa2, 0xfd, 0xb0, 0xd5, 0xdf, 0x27, 0x41, 0xdc, 0x25, 0xfb, 0xd2, 0xd8, 0x8b, 0x13, 0x26, 0x18,
0x94, 0x53, 0xb8, 0x35, 0xf1, 0xa8, 0x08, 0xe3, 0xd8, 0xe3, 0xc6, 0xa6, 0x4f, 0x7d, 0x2a, 0x5d, 0xdc, 0x9a, 0x44, 0xec, 0x49, 0x67, 0x16, 0x71, 0xa3, 0xe1, 0x31, 0x8f, 0xa9, 0x90, 0x96, 0x1c,
0xaa, 0x62, 0xa4, 0xbc, 0xed, 0x7f, 0x32, 0x60, 0xf5, 0x14, 0x27, 0x38, 0x62, 0x70, 0x0f, 0xe4, 0xe9, 0x68, 0xf4, 0x77, 0x0e, 0xac, 0xbf, 0x20, 0x09, 0x09, 0x39, 0xdc, 0x07, 0x25, 0xda, 0x0f,
0x49, 0x37, 0x72, 0x3c, 0x12, 0xd3, 0xa8, 0x9c, 0xd9, 0xc9, 0xec, 0xe6, 0xeb, 0x9b, 0xa3, 0xd4, 0x6d, 0x97, 0x46, 0x2c, 0x6c, 0xe6, 0x76, 0x72, 0xbb, 0xa5, 0x76, 0x63, 0x9c, 0x5a, 0xf5, 0x21,
0x2a, 0xf5, 0x71, 0x14, 0xde, 0xb3, 0x27, 0x53, 0x36, 0x32, 0x48, 0x37, 0x3a, 0x12, 0x43, 0xf8, 0x09, 0x83, 0xfb, 0x68, 0x32, 0x85, 0x70, 0x91, 0xf6, 0xc3, 0x87, 0x72, 0x08, 0xbf, 0x00, 0x9b,
0x39, 0x58, 0x27, 0x31, 0x6e, 0x86, 0xc4, 0x71, 0x13, 0x82, 0x39, 0x29, 0x2f, 0xef, 0x64, 0x76, 0x34, 0x22, 0x9d, 0x80, 0xda, 0x4e, 0x42, 0x89, 0xa0, 0xcd, 0xd5, 0x9d, 0xdc, 0x6e, 0xb1, 0xdd,
0x8d, 0x7a, 0x79, 0x94, 0x5a, 0x9b, 0x7a, 0xd9, 0xec, 0xb4, 0x8d, 0x4c, 0x85, 0xef, 0x4b, 0x08, 0x1c, 0xa7, 0x56, 0xc3, 0x2c, 0x9b, 0x9d, 0x46, 0xb8, 0xa2, 0xed, 0x07, 0xca, 0x84, 0x9f, 0x83,
0x3f, 0x03, 0x85, 0xf1, 0x3c, 0x0e, 0xc3, 0x72, 0x56, 0x2e, 0xde, 0x1a, 0xa5, 0x16, 0x9c, 0x5f, 0x72, 0x36, 0x4f, 0x82, 0xa0, 0x99, 0x57, 0x8b, 0xb7, 0xc6, 0xa9, 0x05, 0xe7, 0x17, 0x93, 0x20,
0x8c, 0xc3, 0xd0, 0x46, 0x40, 0x2f, 0xc5, 0x61, 0x08, 0x6b, 0x00, 0x90, 0x1e, 0x4f, 0xb0, 0x43, 0x40, 0x18, 0x98, 0xa5, 0x24, 0x08, 0xe0, 0x11, 0x00, 0x74, 0x20, 0x12, 0x62, 0x53, 0x3f, 0xe6,
0x82, 0x36, 0x2b, 0xe7, 0x76, 0xb2, 0xbb, 0xd9, 0xba, 0x3d, 0x48, 0xad, 0xfc, 0xb1, 0xb0, 0x1e, 0xcd, 0xc2, 0x4e, 0x7e, 0x37, 0xdf, 0x46, 0xa3, 0xd4, 0x2a, 0x1d, 0x4b, 0xef, 0xf1, 0xc9, 0x0b,
0x37, 0x4e, 0xd9, 0x28, 0xb5, 0xfe, 0xa7, 0x49, 0x26, 0x8e, 0x36, 0xca, 0x4b, 0x70, 0x1c, 0xb4, 0x3e, 0x4e, 0xad, 0xff, 0x19, 0x91, 0x49, 0x20, 0xc2, 0x25, 0x65, 0x1c, 0xfb, 0x31, 0xbf, 0x5f,
0xd9, 0xbd, 0xdc, 0x2f, 0xaf, 0xad, 0x25, 0xfb, 0x75, 0x11, 0x14, 0xee, 0xb7, 0x70, 0x10, 0xdf, 0xf8, 0xed, 0x9d, 0xb5, 0x82, 0xde, 0x55, 0x41, 0xf9, 0x41, 0x97, 0xf8, 0xd1, 0x03, 0x16, 0xbd,
0xa7, 0xf1, 0xcb, 0xc0, 0x87, 0xdf, 0x82, 0x8d, 0x16, 0x8d, 0x08, 0xe3, 0x04, 0x7b, 0x4e, 0x33, 0xf1, 0x3d, 0xf8, 0x3d, 0xa8, 0x75, 0x59, 0x48, 0xb9, 0xa0, 0xc4, 0xb5, 0x3b, 0x01, 0x73, 0xce,
0xa4, 0xee, 0xb9, 0xce, 0xc4, 0xa3, 0x37, 0xa9, 0xb5, 0xf4, 0x47, 0x6a, 0x7d, 0xe2, 0x07, 0xbc, 0xcc, 0x4e, 0x3c, 0x79, 0x9f, 0x5a, 0x2b, 0x7f, 0xa6, 0xd6, 0xa7, 0x9e, 0x2f, 0xba, 0xbd, 0xce,
0xd5, 0x69, 0x56, 0x5c, 0x1a, 0x55, 0x5d, 0xca, 0x22, 0xca, 0xf4, 0xcf, 0x6d, 0xe6, 0x9d, 0x57, 0x9e, 0xc3, 0xc2, 0x96, 0xc3, 0x78, 0xc8, 0xb8, 0x79, 0xdc, 0xe6, 0xee, 0x59, 0x4b, 0x0c, 0x63,
0x79, 0xbf, 0x4d, 0x58, 0xa5, 0x11, 0xf3, 0x51, 0x6a, 0x6d, 0x29, 0xf9, 0x0b, 0x74, 0x36, 0x2a, 0xca, 0xf7, 0x4e, 0x22, 0x31, 0x4e, 0xad, 0x2d, 0x8d, 0x5f, 0x90, 0x43, 0xb8, 0x3a, 0xf1, 0xb4,
0x4e, 0x2c, 0x75, 0x61, 0x80, 0xdf, 0x83, 0xa2, 0x87, 0xa9, 0xf3, 0x92, 0x26, 0xe7, 0x5a, 0x71, 0xa5, 0x03, 0xfe, 0x08, 0xaa, 0x2e, 0x61, 0xf6, 0x1b, 0x96, 0x9c, 0x19, 0xe2, 0xaa, 0x22, 0xbe,
0x59, 0x2a, 0xbe, 0x58, 0x4c, 0x71, 0x90, 0x5a, 0xe6, 0x51, 0xed, 0x8b, 0x07, 0x34, 0x39, 0x97, 0x5e, 0x8e, 0x38, 0x4a, 0xad, 0xca, 0xc3, 0xa3, 0xaf, 0x1e, 0xb1, 0xe4, 0x4c, 0xe9, 0x8e, 0x53,
0xbc, 0xa3, 0xd4, 0xfa, 0xbf, 0xda, 0xc1, 0x3c, 0xbb, 0x8d, 0x4c, 0x0f, 0xd3, 0x89, 0x1b, 0x7c, 0xeb, 0xff, 0xfa, 0x0d, 0xe6, 0xd5, 0x11, 0xae, 0xb8, 0x84, 0x4d, 0xc2, 0xe0, 0x6b, 0x50, 0x9f,
0x01, 0x4a, 0x13, 0x07, 0xd6, 0x69, 0xb7, 0x69, 0xc2, 0xf5, 0x41, 0xdc, 0x1e, 0xa4, 0x56, 0x51, 0x04, 0xf0, 0x5e, 0x1c, 0xb3, 0x44, 0x98, 0x83, 0xb8, 0x3d, 0x4a, 0xad, 0xaa, 0x91, 0x7c, 0xa9,
0x53, 0x3e, 0x53, 0x33, 0xa3, 0xd4, 0xfa, 0xe8, 0x02, 0xa9, 0x5e, 0x63, 0xa3, 0xa2, 0xa6, 0xd5, 0x67, 0xc6, 0xa9, 0xf5, 0xc9, 0x82, 0xa8, 0x59, 0x83, 0x70, 0xd5, 0xc8, 0x9a, 0x50, 0xf8, 0x16,
0xae, 0xf0, 0x15, 0x30, 0x49, 0xd0, 0xde, 0x3b, 0xb8, 0xa3, 0xa3, 0xca, 0xc9, 0xa8, 0xce, 0x16, 0x54, 0xa8, 0x1f, 0xef, 0x1f, 0xde, 0x31, 0x59, 0x15, 0x54, 0x56, 0xa7, 0x4b, 0x67, 0x55, 0x3e,
0x8e, 0xaa, 0x70, 0xdc, 0x38, 0xdd, 0x3b, 0xb8, 0x33, 0x0e, 0xea, 0x9a, 0x3e, 0xd5, 0x19, 0x6a, 0x3e, 0x79, 0xb1, 0x7f, 0x78, 0x27, 0x4b, 0xea, 0x9a, 0x39, 0xd5, 0x19, 0x69, 0x84, 0xcb, 0xda,
0x1b, 0x15, 0x14, 0x54, 0x11, 0x35, 0x80, 0x86, 0x4e, 0x0b, 0xb3, 0x56, 0x79, 0x45, 0xea, 0xee, 0xd4, 0x19, 0x9d, 0x00, 0x63, 0xda, 0x5d, 0xc2, 0xbb, 0xcd, 0x35, 0xc5, 0xdd, 0x1d, 0xa5, 0x16,
0x0e, 0x52, 0x0b, 0x28, 0xa6, 0x47, 0x98, 0xb5, 0xa6, 0xe7, 0xd3, 0xec, 0x7f, 0x87, 0x63, 0x1e, 0xd0, 0x4a, 0x4f, 0x08, 0xef, 0x4e, 0xcf, 0xa7, 0x33, 0xfc, 0x81, 0x44, 0xc2, 0xef, 0x85, 0x99,
0x74, 0xa2, 0x31, 0x17, 0x50, 0x8b, 0x85, 0xd7, 0x24, 0x86, 0x03, 0x1d, 0xc3, 0xea, 0x95, 0x62, 0x16, 0xd0, 0x8b, 0x65, 0xd4, 0x24, 0x87, 0x43, 0x93, 0xc3, 0xfa, 0x95, 0x72, 0x38, 0xbc, 0x2c,
0x38, 0xb8, 0x2c, 0x86, 0x83, 0xf9, 0x18, 0x94, 0xcf, 0x44, 0xf8, 0x50, 0x0b, 0xaf, 0x5d, 0x49, 0x87, 0xc3, 0xf9, 0x1c, 0x74, 0xcc, 0x04, 0x7c, 0xcf, 0x80, 0x37, 0xae, 0x04, 0xbe, 0x77, 0x19,
0xf8, 0xf0, 0x32, 0xe1, 0xc3, 0x79, 0x61, 0xe5, 0x23, 0x2e, 0xc0, 0x85, 0x8c, 0x94, 0x8d, 0xab, 0xf8, 0xde, 0x3c, 0x58, 0xc7, 0xc8, 0x0b, 0xb0, 0xb0, 0x23, 0xcd, 0xe2, 0xd5, 0x2e, 0xc0, 0x47,
0x5d, 0x80, 0xf7, 0x12, 0x5c, 0x9c, 0x58, 0x94, 0xe4, 0x0f, 0x19, 0xb0, 0xe9, 0xd2, 0x98, 0x71, 0x1b, 0x5c, 0x9d, 0x78, 0x34, 0xf2, 0xa7, 0x1c, 0x68, 0x38, 0x2c, 0xe2, 0x42, 0x3a, 0x23, 0x16,
0x61, 0x8c, 0x69, 0x3b, 0x24, 0x5a, 0x38, 0x2f, 0x85, 0x9f, 0x2c, 0x2c, 0x7c, 0x53, 0x09, 0x5f, 0x07, 0xd4, 0x80, 0x4b, 0x0a, 0xfc, 0x7c, 0x69, 0xf0, 0x4d, 0x0d, 0xbe, 0x4c, 0x13, 0xe1, 0x6b,
0xc6, 0x69, 0xa3, 0x6b, 0xf3, 0x66, 0xb5, 0x05, 0x0e, 0x4a, 0x6d, 0xc2, 0x49, 0xc2, 0x9a, 0x9d, 0xf3, 0x6e, 0xfd, 0x0a, 0x02, 0xd4, 0x63, 0x2a, 0x68, 0xc2, 0x3b, 0xbd, 0xc4, 0x33, 0x74, 0xa0,
0xc4, 0xd7, 0xea, 0x40, 0xaa, 0x37, 0x16, 0x56, 0xd7, 0x17, 0xe4, 0x22, 0x9f, 0x8d, 0x36, 0xa6, 0xe8, 0x27, 0x4b, 0xd3, 0xcd, 0x05, 0x59, 0xd4, 0x43, 0xb8, 0x36, 0x75, 0x69, 0x6a, 0x04, 0xaa,
0x26, 0xa5, 0x1a, 0x83, 0x62, 0x20, 0xb6, 0xd2, 0xec, 0x84, 0x5a, 0xb3, 0x20, 0x35, 0x1f, 0x2e, 0xbe, 0x7c, 0x95, 0x4e, 0x2f, 0x30, 0xcc, 0xb2, 0x62, 0x3e, 0x5e, 0x9a, 0x69, 0x6e, 0xfa, 0xbc,
0xac, 0xa9, 0x6f, 0xfa, 0x3c, 0x9b, 0x8d, 0xd6, 0xc7, 0x06, 0xa5, 0xd7, 0x07, 0x30, 0xea, 0x04, 0x1a, 0xc2, 0x9b, 0x99, 0x43, 0xf3, 0x86, 0x00, 0x86, 0x3d, 0x3f, 0xb1, 0xbd, 0x80, 0x38, 0x3e,
0x89, 0xe3, 0x87, 0xd8, 0x0d, 0x48, 0xa2, 0x35, 0x4d, 0xa9, 0xf9, 0x78, 0x61, 0xcd, 0xeb, 0x4a, 0x4d, 0x0c, 0xb3, 0xa2, 0x98, 0x4f, 0x97, 0x66, 0x5e, 0xd7, 0xcc, 0x8f, 0x15, 0x11, 0xae, 0x4b,
0xf3, 0x7d, 0x46, 0x1b, 0x95, 0x84, 0xf1, 0xa1, 0xb2, 0x29, 0xe9, 0x16, 0x30, 0x9b, 0x24, 0x09, 0xe7, 0x63, 0xed, 0xd3, 0xe8, 0x2e, 0xa8, 0x74, 0x68, 0x12, 0xf8, 0x91, 0x81, 0x6e, 0x2a, 0xe8,
0x83, 0x58, 0x8b, 0xae, 0x4b, 0xd1, 0xe3, 0x85, 0x45, 0x75, 0x01, 0xcf, 0x72, 0xd9, 0xa8, 0xa0, 0xf1, 0xd2, 0x50, 0x53, 0xc0, 0xb3, 0x5a, 0x08, 0x97, 0xb5, 0xa9, 0x49, 0xdf, 0x81, 0xcd, 0x21,
0xa0, 0x52, 0xfa, 0x06, 0xac, 0xf7, 0x69, 0x48, 0x9d, 0xee, 0x5d, 0x2d, 0x55, 0x94, 0x52, 0x0f, 0x0b, 0x98, 0xdd, 0xbf, 0x6b, 0x50, 0x55, 0x85, 0x7a, 0xb4, 0x34, 0xca, 0x34, 0xb0, 0x39, 0x31,
0x16, 0x96, 0xd2, 0x0d, 0x6c, 0x8e, 0xcc, 0x46, 0x05, 0x81, 0x9f, 0xdf, 0x55, 0x5a, 0x0c, 0x14, 0x84, 0xcb, 0xd2, 0x7e, 0x75, 0x57, 0xb3, 0x38, 0x28, 0xd3, 0xb7, 0x84, 0x67, 0x17, 0xa5, 0xa6,
0xc8, 0x2b, 0xcc, 0xc6, 0x17, 0x65, 0x43, 0x2a, 0xa1, 0x85, 0x2f, 0x29, 0x38, 0x7e, 0x51, 0x7b, 0x48, 0x78, 0xe9, 0x4b, 0x0a, 0x8e, 0x5f, 0x1f, 0xbd, 0x7c, 0x9e, 0xdd, 0xd1, 0xac, 0xf7, 0x4d,
0xf6, 0x64, 0x7c, 0x47, 0xc7, 0xbd, 0x6f, 0x4a, 0x2c, 0xde, 0x24, 0x81, 0x26, 0x55, 0xe3, 0x62, 0x85, 0xe5, 0x37, 0x49, 0x5a, 0x93, 0xaa, 0x71, 0x88, 0x20, 0xc1, 0x90, 0x0b, 0xc3, 0xad, 0x5f,
0x8e, 0xc3, 0x3e, 0xe3, 0x5a, 0xb7, 0x74, 0xb5, 0xaa, 0x99, 0x67, 0xb3, 0xd1, 0xfa, 0xd8, 0x20, 0xad, 0x6a, 0xe6, 0xd5, 0x10, 0xde, 0xcc, 0x1c, 0x8a, 0x87, 0x5a, 0x60, 0xed, 0xa5, 0x90, 0xdd,
0xf5, 0xec, 0x2a, 0x58, 0x79, 0xc6, 0x45, 0xb7, 0x2e, 0x81, 0xec, 0x39, 0xe9, 0xab, 0x7e, 0x88, 0xba, 0x0e, 0xf2, 0x67, 0x74, 0xa8, 0xfb, 0x21, 0x96, 0x43, 0xd8, 0x00, 0x6b, 0x7d, 0x12, 0xf4,
0xc4, 0x10, 0x6e, 0x82, 0x95, 0x2e, 0x0e, 0x3b, 0xaa, 0xed, 0xe7, 0x91, 0x02, 0xf6, 0x73, 0xb0, 0x74, 0xdb, 0x2f, 0x61, 0x6d, 0xa0, 0x57, 0xa0, 0x76, 0x9a, 0x90, 0x88, 0x13, 0x47, 0xf8, 0x2c,
0x71, 0x96, 0xe0, 0x98, 0x61, 0x97, 0x07, 0x34, 0x3e, 0xa1, 0x3e, 0x83, 0x10, 0xe4, 0xe4, 0x5b, 0x7a, 0xc6, 0x3c, 0x0e, 0x21, 0x28, 0xa8, 0x6f, 0xb1, 0x5e, 0xab, 0xc6, 0xb0, 0x05, 0x0a, 0x01,
0xac, 0xd6, 0xca, 0x31, 0xac, 0x82, 0x5c, 0x48, 0x7d, 0x56, 0x5e, 0xde, 0xc9, 0xee, 0x16, 0xf6, 0xf3, 0x78, 0x73, 0x75, 0x27, 0xbf, 0x5b, 0x3e, 0xb8, 0xb9, 0x77, 0xf9, 0x6f, 0xcb, 0xde, 0x33,
0x6f, 0x56, 0x2e, 0xff, 0x6c, 0xa9, 0x9c, 0x50, 0x1f, 0x49, 0x47, 0xfb, 0xb7, 0x65, 0x90, 0x3d, 0xe6, 0x61, 0x15, 0x88, 0x7e, 0x5f, 0x05, 0xf9, 0x67, 0xcc, 0x83, 0x4d, 0xb0, 0x41, 0x5c, 0x37,
0xa1, 0x3e, 0x2c, 0x83, 0x35, 0xec, 0x79, 0x09, 0x61, 0x4c, 0xf3, 0x8d, 0x21, 0xdc, 0x02, 0xab, 0xa1, 0x9c, 0x1b, 0xbd, 0xcc, 0x84, 0x5b, 0x60, 0x5d, 0xb0, 0xd8, 0x77, 0xb4, 0x68, 0x09, 0x1b,
0x9c, 0xb6, 0x03, 0x57, 0x91, 0xe6, 0x91, 0x46, 0x42, 0xde, 0xc3, 0x1c, 0xcb, 0xbe, 0x66, 0x22, 0x4b, 0xe2, 0x5d, 0x22, 0x88, 0xea, 0x6b, 0x15, 0xac, 0xc6, 0xf0, 0x00, 0x54, 0x54, 0xbe, 0x76,
0x39, 0x86, 0xfb, 0xc0, 0x94, 0xf1, 0x3a, 0x71, 0x27, 0x6a, 0x92, 0x44, 0xb6, 0xa7, 0x5c, 0x7d, 0xd4, 0x0b, 0x3b, 0x34, 0x51, 0xed, 0xa9, 0xd0, 0xae, 0x5d, 0xa4, 0x56, 0x59, 0xf9, 0xbf, 0x54,
0x63, 0x98, 0x5a, 0x05, 0x69, 0x7f, 0x2a, 0xcd, 0x68, 0x16, 0xc0, 0x5b, 0x60, 0x8d, 0xf7, 0x66, 0x6e, 0x3c, 0x6b, 0xc0, 0x5b, 0x60, 0x43, 0x0c, 0x66, 0xbb, 0xca, 0xb5, 0x8b, 0xd4, 0xaa, 0x89,
0xbb, 0xca, 0xb5, 0x61, 0x6a, 0x6d, 0xf0, 0x69, 0xb0, 0xa2, 0x69, 0xa0, 0x55, 0xde, 0x7b, 0xa4, 0x69, 0xb2, 0xb2, 0x69, 0xe0, 0x75, 0x31, 0x78, 0xa2, 0x13, 0x2c, 0x8a, 0x81, 0xed, 0x47, 0x2e,
0x02, 0x34, 0x78, 0xcf, 0x09, 0x62, 0x8f, 0xf4, 0x64, 0xe3, 0xc8, 0xd5, 0x37, 0x87, 0xa9, 0x55, 0x1d, 0xa8, 0xc6, 0x51, 0x68, 0x37, 0x2e, 0x52, 0xab, 0x3e, 0x13, 0x7e, 0x22, 0xe7, 0xf0, 0x86,
0x9a, 0x71, 0x6f, 0x88, 0x39, 0xb4, 0xc6, 0x7b, 0x72, 0x00, 0x6f, 0x01, 0xa0, 0xb6, 0x24, 0x15, 0x18, 0xa8, 0x01, 0xbc, 0x05, 0x80, 0x7e, 0x25, 0x45, 0xd0, 0x9f, 0xfc, 0xcd, 0x8b, 0xd4, 0x2a,
0xd4, 0x93, 0xbf, 0x3e, 0x4c, 0xad, 0xbc, 0xb4, 0x4a, 0xee, 0xe9, 0x10, 0xda, 0x60, 0x45, 0x71, 0x29, 0xaf, 0xd2, 0x9e, 0x0e, 0x21, 0x02, 0x6b, 0x5a, 0xbb, 0xa8, 0xb4, 0x2b, 0x17, 0xa9, 0x55,
0x1b, 0x92, 0xdb, 0x1c, 0xa6, 0x96, 0x11, 0x52, 0x5f, 0x71, 0xaa, 0x29, 0x91, 0xaa, 0x84, 0x44, 0x0c, 0x98, 0xa7, 0x35, 0xf5, 0x94, 0xdc, 0xaa, 0x84, 0x86, 0xac, 0x4f, 0x5d, 0xf5, 0x31, 0x2d,
0xb4, 0x4b, 0x3c, 0xf9, 0x98, 0x1a, 0x68, 0x0c, 0xed, 0x9f, 0x97, 0x81, 0x71, 0xd6, 0x43, 0x84, 0xe2, 0xcc, 0x44, 0xbf, 0xae, 0x82, 0xe2, 0xe9, 0x00, 0x53, 0xde, 0x0b, 0x04, 0x7c, 0x04, 0xea,
0x75, 0x42, 0x0e, 0x1f, 0x80, 0x92, 0x4b, 0x63, 0x9e, 0x60, 0x97, 0x3b, 0x73, 0xa9, 0xad, 0xdf, 0x0e, 0x8b, 0x44, 0x42, 0x1c, 0x61, 0xcf, 0x6d, 0x6d, 0xfb, 0xe6, 0xf4, 0x83, 0xb6, 0x18, 0x81,
0x9c, 0x3e, 0x68, 0x17, 0x3d, 0x6c, 0xb4, 0x31, 0x36, 0xd5, 0x74, 0xfe, 0x37, 0xc1, 0x4a, 0x33, 0x70, 0x2d, 0x73, 0x1d, 0x99, 0xfd, 0x6f, 0x80, 0xb5, 0x4e, 0xc0, 0x58, 0xa8, 0xea, 0xa1, 0x82,
0xa4, 0x34, 0x92, 0xf5, 0x60, 0x22, 0x05, 0xe0, 0x57, 0x32, 0x6b, 0xf2, 0xac, 0xc5, 0x01, 0x14, 0xb5, 0x01, 0xbf, 0x51, 0xbb, 0xa6, 0xce, 0x5a, 0x1e, 0x40, 0xf9, 0xe0, 0xb3, 0x7f, 0x3b, 0xeb,
0xf6, 0x3f, 0xfd, 0xd0, 0x59, 0x5f, 0x28, 0x9b, 0xfa, 0x96, 0x28, 0xe9, 0x51, 0x6a, 0x15, 0xd5, 0x85, 0xb2, 0x69, 0x6f, 0xc9, 0x92, 0x1e, 0xa7, 0x56, 0x55, 0xbf, 0x81, 0x51, 0x41, 0x72, 0x87,
0x0e, 0x34, 0x8b, 0x2d, 0x32, 0x2c, 0xcb, 0xaa, 0x04, 0xb2, 0x09, 0xe1, 0xf2, 0xe8, 0x4c, 0x24, 0x55, 0x59, 0xd5, 0x41, 0x3e, 0xa1, 0x42, 0x1d, 0x5d, 0x05, 0xcb, 0x21, 0xbc, 0x01, 0x8a, 0x09,
0x86, 0xf0, 0x06, 0x30, 0x12, 0xd2, 0x25, 0x09, 0x27, 0x9e, 0x3c, 0x22, 0x03, 0x4d, 0x30, 0xbc, 0xed, 0xd3, 0x44, 0x50, 0x57, 0x1d, 0x51, 0x11, 0x4f, 0x6c, 0x78, 0x1d, 0x14, 0x3d, 0xc2, 0xed,
0x0e, 0x0c, 0x1f, 0x33, 0xa7, 0xc3, 0x88, 0xa7, 0xce, 0x03, 0xad, 0xf9, 0x98, 0x7d, 0xc9, 0x88, 0x1e, 0xa7, 0xae, 0x3e, 0x0f, 0xbc, 0xe1, 0x11, 0xfe, 0x35, 0xa7, 0xee, 0xfd, 0xc2, 0xcf, 0xf2,
0x77, 0x2f, 0xf7, 0xa3, 0xf8, 0x18, 0xfc, 0x3b, 0x0b, 0x56, 0xcf, 0x7a, 0x47, 0xa2, 0x3a, 0x1c, 0x67, 0x90, 0x80, 0xf2, 0x91, 0xe3, 0x50, 0xce, 0x4f, 0x7b, 0x71, 0x40, 0xff, 0xa3, 0xce, 0x0e,
0x60, 0xb8, 0xe2, 0xb3, 0xd0, 0x09, 0x3c, 0x9d, 0x89, 0xa3, 0x85, 0xaf, 0xf5, 0x9a, 0xfc, 0xb0, 0x40, 0x85, 0x0b, 0x96, 0x10, 0x8f, 0xda, 0x67, 0x74, 0x68, 0xaa, 0x4d, 0xd7, 0x8e, 0xf1, 0x3f,
0x6c, 0x1c, 0x0d, 0x53, 0x6b, 0xcd, 0x55, 0x43, 0xa4, 0x07, 0x9e, 0x48, 0x55, 0x4c, 0x63, 0x57, 0xa5, 0x43, 0x8e, 0x67, 0x0d, 0x8d, 0x68, 0xb7, 0xdf, 0x8f, 0xb6, 0x73, 0x1f, 0x46, 0xdb, 0xb9,
0x5d, 0x9d, 0x1c, 0x52, 0x00, 0x3e, 0x06, 0x79, 0xb1, 0xc5, 0x76, 0x12, 0xb8, 0x44, 0x26, 0x2b, 0xbf, 0x46, 0xdb, 0xb9, 0x5f, 0xce, 0xb7, 0x57, 0x3e, 0x9c, 0x6f, 0xaf, 0xfc, 0x71, 0xbe, 0xbd,
0x5f, 0xaf, 0x2c, 0xa6, 0x8b, 0x44, 0x8c, 0xa7, 0x62, 0x3d, 0xdc, 0x06, 0x59, 0x1f, 0x33, 0x5d, 0xf2, 0xed, 0xee, 0xcc, 0xb5, 0x15, 0x5d, 0x92, 0x70, 0x9f, 0xb7, 0xa6, 0xff, 0xfa, 0x03, 0xf5,
0xd8, 0xe6, 0x20, 0xb5, 0x8c, 0x87, 0x98, 0x9d, 0x04, 0x51, 0xc0, 0x91, 0x98, 0x80, 0x45, 0xb0, 0xb7, 0xaf, 0x2e, 0x6f, 0x67, 0x5d, 0xfd, 0xb9, 0xdf, 0xfd, 0x27, 0x00, 0x00, 0xff, 0xff, 0x17,
0xcc, 0xa9, 0x2a, 0x64, 0xb4, 0xcc, 0x29, 0x7c, 0x3a, 0xbe, 0xcd, 0xea, 0x2b, 0xe7, 0x70, 0xe1, 0xd8, 0xae, 0xb6, 0x0b, 0x0c, 0x00, 0x00,
0x80, 0x57, 0x6b, 0x11, 0xed, 0xc4, 0x5c, 0xbf, 0x03, 0x22, 0xc4, 0x20, 0x6e, 0x77, 0xb8, 0xac,
0x64, 0x13, 0x29, 0x00, 0x31, 0x30, 0xb0, 0xeb, 0x12, 0xc6, 0x08, 0x2b, 0x1b, 0xf2, 0xea, 0x7f,
0xfc, 0xa1, 0x72, 0xa8, 0x49, 0xbf, 0xb3, 0x8e, 0x68, 0xd3, 0x3b, 0x62, 0x37, 0xc3, 0xd4, 0x02,
0x6a, 0xf1, 0x49, 0xc0, 0xf8, 0xaf, 0x7f, 0x5a, 0xa0, 0x36, 0x41, 0x68, 0x42, 0x0b, 0x4d, 0x90,
0xe9, 0xca, 0x7a, 0x37, 0x51, 0xa6, 0x2b, 0x50, 0x22, 0x9b, 0xb9, 0x89, 0x32, 0x89, 0x40, 0x4c,
0xb6, 0x59, 0x13, 0x65, 0x98, 0x3e, 0x77, 0x0c, 0x0a, 0x33, 0x52, 0xff, 0xf1, 0xbe, 0xec, 0x03,
0x93, 0x71, 0x9a, 0x60, 0x9f, 0x38, 0xe7, 0xa4, 0xaf, 0x5f, 0x19, 0xf5, 0x66, 0x68, 0xfb, 0x63,
0xd2, 0x67, 0x68, 0x16, 0x28, 0x89, 0x7a, 0xfd, 0xcd, 0x60, 0x3b, 0xf3, 0x76, 0xb0, 0x9d, 0xf9,
0x6b, 0xb0, 0x9d, 0xf9, 0xe9, 0xdd, 0xf6, 0xd2, 0xdb, 0x77, 0xdb, 0x4b, 0xbf, 0xbf, 0xdb, 0x5e,
0xfa, 0x7a, 0x77, 0x26, 0xbd, 0xbc, 0x85, 0x13, 0x16, 0xb0, 0xea, 0xf4, 0x3f, 0x5e, 0x4f, 0xfe,
0xcb, 0x93, 0x49, 0x6e, 0xae, 0xca, 0x7f, 0x6c, 0x77, 0xff, 0x0d, 0x00, 0x00, 0xff, 0xff, 0x3c,
0xab, 0x3d, 0x9c, 0x03, 0x0e, 0x00, 0x00,
} }
func (m *Params) Marshal() (dAtA []byte, err error) { func (m *Params) Marshal() (dAtA []byte, err error) {
@ -1166,118 +1094,6 @@ func (m *TxResult) MarshalToSizedBuffer(dAtA []byte) (int, error) {
return len(dAtA) - i, nil return len(dAtA) - i, nil
} }
func (m *TxData) 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 *TxData) MarshalTo(dAtA []byte) (int, error) {
size := m.Size()
return m.MarshalToSizedBuffer(dAtA[:size])
}
func (m *TxData) MarshalToSizedBuffer(dAtA []byte) (int, error) {
i := len(dAtA)
_ = i
var l int
_ = l
if len(m.S) > 0 {
i -= len(m.S)
copy(dAtA[i:], m.S)
i = encodeVarintEvm(dAtA, i, uint64(len(m.S)))
i--
dAtA[i] = 0x5a
}
if len(m.R) > 0 {
i -= len(m.R)
copy(dAtA[i:], m.R)
i = encodeVarintEvm(dAtA, i, uint64(len(m.R)))
i--
dAtA[i] = 0x52
}
if len(m.V) > 0 {
i -= len(m.V)
copy(dAtA[i:], m.V)
i = encodeVarintEvm(dAtA, i, uint64(len(m.V)))
i--
dAtA[i] = 0x4a
}
if len(m.Accesses) > 0 {
for iNdEx := len(m.Accesses) - 1; iNdEx >= 0; iNdEx-- {
{
size, err := m.Accesses[iNdEx].MarshalToSizedBuffer(dAtA[:i])
if err != nil {
return 0, err
}
i -= size
i = encodeVarintEvm(dAtA, i, uint64(size))
}
i--
dAtA[i] = 0x42
}
}
if len(m.Input) > 0 {
i -= len(m.Input)
copy(dAtA[i:], m.Input)
i = encodeVarintEvm(dAtA, i, uint64(len(m.Input)))
i--
dAtA[i] = 0x3a
}
{
size := m.Amount.Size()
i -= size
if _, err := m.Amount.MarshalTo(dAtA[i:]); err != nil {
return 0, err
}
i = encodeVarintEvm(dAtA, i, uint64(size))
}
i--
dAtA[i] = 0x32
if len(m.To) > 0 {
i -= len(m.To)
copy(dAtA[i:], m.To)
i = encodeVarintEvm(dAtA, i, uint64(len(m.To)))
i--
dAtA[i] = 0x2a
}
if m.GasLimit != 0 {
i = encodeVarintEvm(dAtA, i, uint64(m.GasLimit))
i--
dAtA[i] = 0x20
}
{
size := m.GasPrice.Size()
i -= size
if _, err := m.GasPrice.MarshalTo(dAtA[i:]); err != nil {
return 0, err
}
i = encodeVarintEvm(dAtA, i, uint64(size))
}
i--
dAtA[i] = 0x1a
if m.Nonce != 0 {
i = encodeVarintEvm(dAtA, i, uint64(m.Nonce))
i--
dAtA[i] = 0x10
}
{
size := m.ChainID.Size()
i -= size
if _, err := m.ChainID.MarshalTo(dAtA[i:]); err != nil {
return 0, err
}
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)
@ -1506,53 +1322,6 @@ func (m *TxResult) Size() (n int) {
return n return n
} }
func (m *TxData) Size() (n int) {
if m == nil {
return 0
}
var l int
_ = l
l = m.ChainID.Size()
n += 1 + l + sovEvm(uint64(l))
if m.Nonce != 0 {
n += 1 + sovEvm(uint64(m.Nonce))
}
l = m.GasPrice.Size()
n += 1 + l + sovEvm(uint64(l))
if m.GasLimit != 0 {
n += 1 + sovEvm(uint64(m.GasLimit))
}
l = len(m.To)
if l > 0 {
n += 1 + l + sovEvm(uint64(l))
}
l = m.Amount.Size()
n += 1 + l + sovEvm(uint64(l))
l = len(m.Input)
if l > 0 {
n += 1 + l + sovEvm(uint64(l))
}
if len(m.Accesses) > 0 {
for _, e := range m.Accesses {
l = e.Size()
n += 1 + l + sovEvm(uint64(l))
}
}
l = len(m.V)
if l > 0 {
n += 1 + l + sovEvm(uint64(l))
}
l = len(m.R)
if l > 0 {
n += 1 + l + sovEvm(uint64(l))
}
l = len(m.S)
if l > 0 {
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
@ -1761,10 +1530,7 @@ func (m *Params) Unmarshal(dAtA []byte) error {
if err != nil { if err != nil {
return err return err
} }
if skippy < 0 { if (skippy < 0) || (iNdEx+skippy) < 0 {
return ErrInvalidLengthEvm
}
if (iNdEx + skippy) < 0 {
return ErrInvalidLengthEvm return ErrInvalidLengthEvm
} }
if (iNdEx + skippy) > l { if (iNdEx + skippy) > l {
@ -2342,10 +2108,7 @@ func (m *ChainConfig) Unmarshal(dAtA []byte) error {
if err != nil { if err != nil {
return err return err
} }
if skippy < 0 { if (skippy < 0) || (iNdEx+skippy) < 0 {
return ErrInvalidLengthEvm
}
if (iNdEx + skippy) < 0 {
return ErrInvalidLengthEvm return ErrInvalidLengthEvm
} }
if (iNdEx + skippy) > l { if (iNdEx + skippy) > l {
@ -2459,10 +2222,7 @@ func (m *State) Unmarshal(dAtA []byte) error {
if err != nil { if err != nil {
return err return err
} }
if skippy < 0 { if (skippy < 0) || (iNdEx+skippy) < 0 {
return ErrInvalidLengthEvm
}
if (iNdEx + skippy) < 0 {
return ErrInvalidLengthEvm return ErrInvalidLengthEvm
} }
if (iNdEx + skippy) > l { if (iNdEx + skippy) > l {
@ -2578,10 +2338,7 @@ func (m *TransactionLogs) Unmarshal(dAtA []byte) error {
if err != nil { if err != nil {
return err return err
} }
if skippy < 0 { if (skippy < 0) || (iNdEx+skippy) < 0 {
return ErrInvalidLengthEvm
}
if (iNdEx + skippy) < 0 {
return ErrInvalidLengthEvm return ErrInvalidLengthEvm
} }
if (iNdEx + skippy) > l { if (iNdEx + skippy) > l {
@ -2870,10 +2627,7 @@ func (m *Log) Unmarshal(dAtA []byte) error {
if err != nil { if err != nil {
return err return err
} }
if skippy < 0 { if (skippy < 0) || (iNdEx+skippy) < 0 {
return ErrInvalidLengthEvm
}
if (iNdEx + skippy) < 0 {
return ErrInvalidLengthEvm return ErrInvalidLengthEvm
} }
if (iNdEx + skippy) > l { if (iNdEx + skippy) > l {
@ -3095,405 +2849,7 @@ func (m *TxResult) Unmarshal(dAtA []byte) error {
if err != nil { if err != nil {
return err return err
} }
if skippy < 0 { if (skippy < 0) || (iNdEx+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 *TxData) 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: TxData: wiretype end group for non-group")
}
if fieldNum <= 0 {
return fmt.Errorf("proto: TxData: illegal tag %d (wire type %d)", fieldNum, wire)
}
switch fieldNum {
case 1:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field ChainID", wireType)
}
var stringLen uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowEvm
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
stringLen |= uint64(b&0x7F) << shift
if b < 0x80 {
break
}
}
intStringLen := int(stringLen)
if intStringLen < 0 {
return ErrInvalidLengthEvm
}
postIndex := iNdEx + intStringLen
if postIndex < 0 {
return ErrInvalidLengthEvm
}
if postIndex > l {
return io.ErrUnexpectedEOF
}
if err := m.ChainID.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
return err
}
iNdEx = postIndex
case 2:
if wireType != 0 {
return fmt.Errorf("proto: wrong wireType = %d for field Nonce", wireType)
}
m.Nonce = 0
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowEvm
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
m.Nonce |= uint64(b&0x7F) << shift
if b < 0x80 {
break
}
}
case 3:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field GasPrice", wireType)
}
var stringLen uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowEvm
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
stringLen |= uint64(b&0x7F) << shift
if b < 0x80 {
break
}
}
intStringLen := int(stringLen)
if intStringLen < 0 {
return ErrInvalidLengthEvm
}
postIndex := iNdEx + intStringLen
if postIndex < 0 {
return ErrInvalidLengthEvm
}
if postIndex > l {
return io.ErrUnexpectedEOF
}
if err := m.GasPrice.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
return err
}
iNdEx = postIndex
case 4:
if wireType != 0 {
return fmt.Errorf("proto: wrong wireType = %d for field GasLimit", wireType)
}
m.GasLimit = 0
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowEvm
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
m.GasLimit |= uint64(b&0x7F) << shift
if b < 0x80 {
break
}
}
case 5:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field To", wireType)
}
var stringLen uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowEvm
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
stringLen |= uint64(b&0x7F) << shift
if b < 0x80 {
break
}
}
intStringLen := int(stringLen)
if intStringLen < 0 {
return ErrInvalidLengthEvm
}
postIndex := iNdEx + intStringLen
if postIndex < 0 {
return ErrInvalidLengthEvm
}
if postIndex > l {
return io.ErrUnexpectedEOF
}
m.To = string(dAtA[iNdEx:postIndex])
iNdEx = postIndex
case 6:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field Amount", wireType)
}
var stringLen uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowEvm
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
stringLen |= uint64(b&0x7F) << shift
if b < 0x80 {
break
}
}
intStringLen := int(stringLen)
if intStringLen < 0 {
return ErrInvalidLengthEvm
}
postIndex := iNdEx + intStringLen
if postIndex < 0 {
return ErrInvalidLengthEvm
}
if postIndex > l {
return io.ErrUnexpectedEOF
}
if err := m.Amount.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
return err
}
iNdEx = postIndex
case 7:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field Input", wireType)
}
var byteLen int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowEvm
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
byteLen |= int(b&0x7F) << shift
if b < 0x80 {
break
}
}
if byteLen < 0 {
return ErrInvalidLengthEvm
}
postIndex := iNdEx + byteLen
if postIndex < 0 {
return ErrInvalidLengthEvm
}
if postIndex > l {
return io.ErrUnexpectedEOF
}
m.Input = append(m.Input[:0], dAtA[iNdEx:postIndex]...)
if m.Input == nil {
m.Input = []byte{}
}
iNdEx = postIndex
case 8:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field Accesses", 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.Accesses = append(m.Accesses, AccessTuple{})
if err := m.Accesses[len(m.Accesses)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
return err
}
iNdEx = postIndex
case 9:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field V", wireType)
}
var byteLen int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowEvm
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
byteLen |= int(b&0x7F) << shift
if b < 0x80 {
break
}
}
if byteLen < 0 {
return ErrInvalidLengthEvm
}
postIndex := iNdEx + byteLen
if postIndex < 0 {
return ErrInvalidLengthEvm
}
if postIndex > l {
return io.ErrUnexpectedEOF
}
m.V = append(m.V[:0], dAtA[iNdEx:postIndex]...)
if m.V == nil {
m.V = []byte{}
}
iNdEx = postIndex
case 10:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field R", wireType)
}
var byteLen int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowEvm
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
byteLen |= int(b&0x7F) << shift
if b < 0x80 {
break
}
}
if byteLen < 0 {
return ErrInvalidLengthEvm
}
postIndex := iNdEx + byteLen
if postIndex < 0 {
return ErrInvalidLengthEvm
}
if postIndex > l {
return io.ErrUnexpectedEOF
}
m.R = append(m.R[:0], dAtA[iNdEx:postIndex]...)
if m.R == nil {
m.R = []byte{}
}
iNdEx = postIndex
case 11:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field S", wireType)
}
var byteLen int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowEvm
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
byteLen |= int(b&0x7F) << shift
if b < 0x80 {
break
}
}
if byteLen < 0 {
return ErrInvalidLengthEvm
}
postIndex := iNdEx + byteLen
if postIndex < 0 {
return ErrInvalidLengthEvm
}
if postIndex > l {
return io.ErrUnexpectedEOF
}
m.S = append(m.S[:0], dAtA[iNdEx:postIndex]...)
if m.S == nil {
m.S = []byte{}
}
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 return ErrInvalidLengthEvm
} }
if (iNdEx + skippy) > l { if (iNdEx + skippy) > l {
@ -3607,10 +2963,7 @@ func (m *AccessTuple) Unmarshal(dAtA []byte) error {
if err != nil { if err != nil {
return err return err
} }
if skippy < 0 { if (skippy < 0) || (iNdEx+skippy) < 0 {
return ErrInvalidLengthEvm
}
if (iNdEx + skippy) < 0 {
return ErrInvalidLengthEvm return ErrInvalidLengthEvm
} }
if (iNdEx + skippy) > l { if (iNdEx + skippy) > l {

View File

@ -556,10 +556,7 @@ func (m *GenesisState) Unmarshal(dAtA []byte) error {
if err != nil { if err != nil {
return err return err
} }
if skippy < 0 { if (skippy < 0) || (iNdEx+skippy) < 0 {
return ErrInvalidLengthGenesis
}
if (iNdEx + skippy) < 0 {
return ErrInvalidLengthGenesis return ErrInvalidLengthGenesis
} }
if (iNdEx + skippy) > l { if (iNdEx + skippy) > l {
@ -707,10 +704,7 @@ func (m *GenesisAccount) Unmarshal(dAtA []byte) error {
if err != nil { if err != nil {
return err return err
} }
if skippy < 0 { if (skippy < 0) || (iNdEx+skippy) < 0 {
return ErrInvalidLengthGenesis
}
if (iNdEx + skippy) < 0 {
return ErrInvalidLengthGenesis return ErrInvalidLengthGenesis
} }
if (iNdEx + skippy) > l { if (iNdEx + skippy) > l {

178
x/evm/types/legacy_tx.go Normal file
View File

@ -0,0 +1,178 @@
package types
import (
"math/big"
sdk "github.com/cosmos/cosmos-sdk/types"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
"github.com/ethereum/go-ethereum/common"
ethtypes "github.com/ethereum/go-ethereum/core/types"
"github.com/tharsis/ethermint/types"
)
func newLegacyTx(tx *ethtypes.Transaction) *LegacyTx {
txData := &LegacyTx{
Nonce: tx.Nonce(),
Data: tx.Data(),
GasLimit: tx.Gas(),
}
v, r, s := tx.RawSignatureValues()
if tx.To() != nil {
txData.To = tx.To().Hex()
}
if tx.Value() != nil {
amountInt := sdk.NewIntFromBigInt(tx.Value())
txData.Amount = &amountInt
}
if tx.GasPrice() != nil {
gasPriceInt := sdk.NewIntFromBigInt(tx.GasPrice())
txData.GasPrice = &gasPriceInt
}
txData.SetSignatureValues(tx.ChainId(), v, r, s)
return txData
}
// TxType returns the tx type
func (tx *LegacyTx) TxType() uint8 {
return ethtypes.LegacyTxType
}
// Copy returns an instance with the same field values
func (tx *LegacyTx) Copy() TxData {
return &LegacyTx{
Nonce: tx.Nonce,
GasPrice: tx.GasPrice,
GasLimit: tx.GasLimit,
To: tx.To,
Amount: tx.Amount,
Data: common.CopyBytes(tx.Data),
V: common.CopyBytes(tx.V),
R: common.CopyBytes(tx.R),
S: common.CopyBytes(tx.S),
}
}
// GetChainID returns the chain id field from the derived signature values
func (tx *LegacyTx) GetChainID() *big.Int {
v, _, _ := tx.GetRawSignatureValues()
return DeriveChainID(v)
}
// GetAccessList returns nil
func (tx *LegacyTx) GetAccessList() ethtypes.AccessList {
return nil
}
// GetData returns the a copy of the input data bytes.
func (tx *LegacyTx) GetData() []byte {
return common.CopyBytes(tx.Data)
}
// GetGas returns the gas limit.
func (tx *LegacyTx) GetGas() uint64 {
return tx.GasLimit
}
// GetGasPrice returns the gas price field.
func (tx *LegacyTx) GetGasPrice() *big.Int {
if tx.GasPrice == nil {
return nil
}
return tx.GasPrice.BigInt()
}
// GetValue returns the tx amount.
func (tx *LegacyTx) GetValue() *big.Int {
if tx.Amount == nil {
return nil
}
return tx.Amount.BigInt()
}
// GetNonce returns the account sequence for the transaction.
func (tx *LegacyTx) GetNonce() uint64 { return tx.Nonce }
// GetTo returns the pointer to the recipient address.
func (tx *LegacyTx) GetTo() *common.Address {
if tx.To == "" {
return nil
}
to := common.HexToAddress(tx.To)
return &to
}
// AsEthereumData returns an AccessListTx transaction tx from the proto-formatted
// TxData defined on the Cosmos EVM.
func (tx *LegacyTx) AsEthereumData() ethtypes.TxData {
v, r, s := tx.GetRawSignatureValues()
return &ethtypes.LegacyTx{
Nonce: tx.GetNonce(),
GasPrice: tx.GetGasPrice(),
Gas: tx.GetGas(),
To: tx.GetTo(),
Value: tx.GetValue(),
Data: tx.GetData(),
V: v,
R: r,
S: s,
}
}
// GetRawSignatureValues returns the V, R, S signature values of the transaction.
// The return values should not be modified by the caller.
func (tx *LegacyTx) GetRawSignatureValues() (v, r, s *big.Int) {
return rawSignatureValues(tx.V, tx.R, tx.S)
}
// SetSignatureValues sets the signature values to the transaction.
func (tx *LegacyTx) SetSignatureValues(_, v, r, s *big.Int) {
if v != nil {
tx.V = v.Bytes()
}
if r != nil {
tx.R = r.Bytes()
}
if s != nil {
tx.S = s.Bytes()
}
}
// Validate performs a stateless validation of the tx fields.
func (tx LegacyTx) Validate() error {
gasPrice := tx.GetGasPrice()
if gasPrice == nil {
return sdkerrors.Wrap(ErrInvalidGasPrice, "cannot be nil")
}
if gasPrice.Sign() == -1 {
return sdkerrors.Wrapf(ErrInvalidGasPrice, "gas price cannot be negative %s", gasPrice)
}
amount := tx.GetValue()
// Amount can be 0
if amount != nil && amount.Sign() == -1 {
return sdkerrors.Wrapf(ErrInvalidAmount, "amount cannot be negative %s", amount)
}
if tx.To != "" {
if err := types.ValidateAddress(tx.To); err != nil {
return sdkerrors.Wrap(err, "invalid to address")
}
}
return nil
}
// Fee returns gasprice * gaslimit.
func (tx LegacyTx) Fee() *big.Int {
return fee(tx.GetGasPrice(), tx.GetGas())
}
// Cost returns amount + gasprice * gaslimit.
func (tx LegacyTx) Cost() *big.Int {
return cost(tx.Fee(), tx.GetValue())
}

View File

@ -4,6 +4,7 @@ import (
"fmt" "fmt"
"math/big" "math/big"
codectypes "github.com/cosmos/cosmos-sdk/codec/types"
"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"
@ -20,6 +21,8 @@ var (
_ sdk.Msg = &MsgEthereumTx{} _ sdk.Msg = &MsgEthereumTx{}
_ sdk.Tx = &MsgEthereumTx{} _ sdk.Tx = &MsgEthereumTx{}
_ ante.GasTx = &MsgEthereumTx{} _ ante.GasTx = &MsgEthereumTx{}
_ codectypes.UnpackInterfacesMessage = MsgEthereumTx{}
) )
// message type and route constants // message type and route constants
@ -28,17 +31,17 @@ const (
TypeMsgEthereumTx = "ethereum_tx" TypeMsgEthereumTx = "ethereum_tx"
) )
// NewMsgEthereumTx returns a reference to a new Ethereum transaction message. // NewTx returns a reference to a new Ethereum transaction message.
func NewMsgEthereumTx( func NewTx(
chainID *big.Int, nonce uint64, to *common.Address, amount *big.Int, chainID *big.Int, nonce uint64, to *common.Address, amount *big.Int,
gasLimit uint64, gasPrice *big.Int, input []byte, accesses *ethtypes.AccessList, gasLimit uint64, gasPrice *big.Int, input []byte, accesses *ethtypes.AccessList,
) *MsgEthereumTx { ) *MsgEthereumTx {
return newMsgEthereumTx(chainID, nonce, to, amount, gasLimit, gasPrice, input, accesses) return newMsgEthereumTx(chainID, nonce, to, amount, gasLimit, gasPrice, input, accesses)
} }
// NewMsgEthereumTxContract returns a reference to a new Ethereum transaction // NewTxContract returns a reference to a new Ethereum transaction
// message designated for contract creation. // message designated for contract creation.
func NewMsgEthereumTxContract( func NewTxContract(
chainID *big.Int, nonce uint64, amount *big.Int, chainID *big.Int, nonce uint64, amount *big.Int,
gasLimit uint64, gasPrice *big.Int, input []byte, accesses *ethtypes.AccessList, gasLimit uint64, gasPrice *big.Int, input []byte, accesses *ethtypes.AccessList,
) *MsgEthereumTx { ) *MsgEthereumTx {
@ -49,35 +52,71 @@ func newMsgEthereumTx(
chainID *big.Int, nonce uint64, to *common.Address, amount *big.Int, chainID *big.Int, nonce uint64, to *common.Address, amount *big.Int,
gasLimit uint64, gasPrice *big.Int, input []byte, accesses *ethtypes.AccessList, gasLimit uint64, gasPrice *big.Int, input []byte, accesses *ethtypes.AccessList,
) *MsgEthereumTx { ) *MsgEthereumTx {
txData := newTxData(chainID, nonce, to, amount, gasLimit, gasPrice, input, accesses) var (
return &MsgEthereumTx{Data: txData} cid, amt, gp *sdk.Int
toAddr string
txData TxData
)
if to != nil {
toAddr = to.Hex()
}
if amount != nil {
amountInt := sdk.NewIntFromBigInt(amount)
amt = &amountInt
}
if chainID != nil {
chainIDInt := sdk.NewIntFromBigInt(chainID)
cid = &chainIDInt
}
if gasPrice != nil {
gasPriceInt := sdk.NewIntFromBigInt(gasPrice)
gp = &gasPriceInt
}
if accesses == nil {
txData = &LegacyTx{
Nonce: nonce,
To: toAddr,
Amount: amt,
GasLimit: gasLimit,
GasPrice: gp,
Data: input,
}
} else {
txData = &AccessListTx{
ChainID: cid,
Nonce: nonce,
To: toAddr,
Amount: amt,
GasLimit: gasLimit,
GasPrice: gp,
Data: input,
Accesses: NewAccessList(accesses),
}
}
dataAny, err := PackTxData(txData)
if err != nil {
panic(err)
}
return &MsgEthereumTx{Data: dataAny}
} }
// fromEthereumTx populates the message fields from the given ethereum transaction // fromEthereumTx populates the message fields from the given ethereum transaction
func (msg *MsgEthereumTx) FromEthereumTx(tx *ethtypes.Transaction) { func (msg *MsgEthereumTx) FromEthereumTx(tx *ethtypes.Transaction) {
msg.Data = &TxData{ txData := NewTxDataFromTx(tx)
Nonce: tx.Nonce(),
Input: tx.Data(), anyTxData, err := PackTxData(txData)
GasLimit: tx.Gas(), if err != nil {
panic(err)
} }
v, r, s := tx.RawSignatureValues() msg.Data = anyTxData
if tx.To() != nil {
msg.Data.To = tx.To().Hex()
}
if tx.Value() != nil {
msg.Data.Amount = sdk.NewIntFromBigInt(tx.Value())
}
if tx.GasPrice() != nil {
msg.Data.GasPrice = sdk.NewIntFromBigInt(tx.GasPrice())
}
if tx.AccessList() != nil {
al := tx.AccessList()
msg.Data.Accesses = NewAccessList(&al)
}
msg.Data.setSignatureValues(tx.ChainId(), v, r, s)
msg.Size_ = float64(tx.Size()) msg.Size_ = float64(tx.Size())
msg.Hash = tx.Hash().Hex() msg.Hash = tx.Hash().Hex()
} }
@ -97,13 +136,12 @@ func (msg MsgEthereumTx) ValidateBasic() error {
} }
} }
return msg.Data.Validate() txData, err := UnpackTxData(msg.Data)
} if err != nil {
return sdkerrors.Wrap(err, "failed to unpack tx data")
}
// To returns the recipient address of the transaction. It returns nil if the return txData.Validate()
// transaction is a contract creation.
func (msg MsgEthereumTx) To() *common.Address {
return msg.Data.to()
} }
// GetMsgs returns a single MsgEthereumTx as an sdk.Msg. // GetMsgs returns a single MsgEthereumTx as an sdk.Msg.
@ -115,14 +153,18 @@ func (msg *MsgEthereumTx) GetMsgs() []sdk.Msg {
// For such a message, there should exist only a single 'signer'. // For such a message, there should exist only a single 'signer'.
// //
// NOTE: This method panics if 'Sign' hasn't been called first. // NOTE: This method panics if 'Sign' hasn't been called first.
func (msg MsgEthereumTx) GetSigners() []sdk.AccAddress { func (msg *MsgEthereumTx) GetSigners() []sdk.AccAddress {
v, r, s := msg.RawSignatureValues() data, err := UnpackTxData(msg.Data)
if err != nil {
if msg.From == "" || v == nil || r == nil || s == nil { panic(err)
panic("must use 'Sign' to get the signer address")
} }
signer := sdk.AccAddress(common.HexToAddress(msg.From).Bytes()) sender, err := msg.GetSender(data.GetChainID())
if err != nil {
panic(err)
}
signer := sdk.AccAddress(sender.Bytes())
return []sdk.AccAddress{signer} return []sdk.AccAddress{signer}
} }
@ -167,34 +209,11 @@ func (msg *MsgEthereumTx) Sign(ethSigner ethtypes.Signer, keyringSigner keyring.
// GetGas implements the GasTx interface. It returns the GasLimit of the transaction. // GetGas implements the GasTx interface. It returns the GasLimit of the transaction.
func (msg MsgEthereumTx) GetGas() uint64 { func (msg MsgEthereumTx) GetGas() uint64 {
return msg.Data.gas() txData, err := UnpackTxData(msg.Data)
} if err != nil {
return 0
// Fee returns gasprice * gaslimit.
func (msg MsgEthereumTx) Fee() *big.Int {
gasPrice := msg.Data.gasPrice()
gasLimit := new(big.Int).SetUint64(msg.Data.gas())
return new(big.Int).Mul(gasPrice, gasLimit)
}
// ChainID returns which chain id this transaction was signed for (if at all)
func (msg *MsgEthereumTx) ChainID() *big.Int {
return msg.Data.chainID()
}
// Cost returns amount + gasprice * gaslimit.
func (msg MsgEthereumTx) Cost() *big.Int {
total := msg.Fee()
if msg.Data.amount() != nil {
total.Add(total, msg.Data.amount())
} }
return total return txData.GetGas()
}
// RawSignatureValues returns the V, R, S signature values of the transaction.
// The return values should not be modified by the caller.
func (msg MsgEthereumTx) RawSignatureValues() (v, r, s *big.Int) {
return msg.Data.rawSignatureValues()
} }
// GetFrom loads the ethereum sender address from the sigcache and returns an // GetFrom loads the ethereum sender address from the sigcache and returns an
@ -209,7 +228,12 @@ func (msg *MsgEthereumTx) GetFrom() sdk.AccAddress {
// AsTransaction creates an Ethereum Transaction type from the msg fields // AsTransaction creates an Ethereum Transaction type from the msg fields
func (msg MsgEthereumTx) AsTransaction() *ethtypes.Transaction { func (msg MsgEthereumTx) AsTransaction() *ethtypes.Transaction {
return ethtypes.NewTx(msg.Data.AsEthereumData()) txData, err := UnpackTxData(msg.Data)
if err != nil {
return nil
}
return ethtypes.NewTx(txData.AsEthereumData())
} }
// AsMessage creates an Ethereum core.Message from the msg fields // AsMessage creates an Ethereum core.Message from the msg fields
@ -224,6 +248,12 @@ func (msg *MsgEthereumTx) GetSender(chainID *big.Int) (common.Address, error) {
if err != nil { if err != nil {
return common.Address{}, err return common.Address{}, err
} }
msg.From = from.Hex() msg.From = from.Hex()
return from, nil return from, nil
} }
// UnpackInterfaces implements UnpackInterfacesMesssage.UnpackInterfaces
func (msg MsgEthereumTx) UnpackInterfaces(unpacker codectypes.AnyUnpacker) error {
return unpacker.UnpackAny(msg.Data, new(TxData))
}

View File

@ -11,6 +11,7 @@ import (
"github.com/tharsis/ethermint/crypto/ethsecp256k1" "github.com/tharsis/ethermint/crypto/ethsecp256k1"
"github.com/tharsis/ethermint/tests" "github.com/tharsis/ethermint/tests"
"github.com/ethereum/go-ethereum/common"
ethcmn "github.com/ethereum/go-ethereum/common" ethcmn "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/types"
ethtypes "github.com/ethereum/go-ethereum/core/types" ethtypes "github.com/ethereum/go-ethereum/core/types"
@ -46,80 +47,79 @@ 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 := NewTx(nil, 0, &suite.to, nil, 100000, nil, []byte("test"), nil)
suite.Require().Equal(msg.Data.To, suite.to.Hex()) // 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())
suite.Require().Equal(msg.GetMsgs(), []sdk.Msg{msg}) suite.Require().Equal(msg.GetMsgs(), []sdk.Msg{msg})
suite.Require().Panics(func() { msg.GetSigners() }) suite.Require().Panics(func() { msg.GetSigners() })
suite.Require().Panics(func() { msg.GetSignBytes() }) suite.Require().Panics(func() { msg.GetSignBytes() })
msg = NewMsgEthereumTxContract(nil, 0, nil, 100000, nil, []byte("test"), nil) msg = NewTxContract(nil, 0, nil, 100000, nil, []byte("test"), nil)
suite.Require().NotNil(msg) suite.Require().NotNil(msg)
suite.Require().Empty(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() {
hundredInt := sdk.NewInt(100)
zeroInt := sdk.ZeroInt()
minusOneInt := sdk.NewInt(-1)
testCases := []struct { testCases := []struct {
msg string msg string
to string to string
amount sdk.Int amount *sdk.Int
gasPrice sdk.Int gasPrice *sdk.Int
from string from string
accessList *ethtypes.AccessList accessList *ethtypes.AccessList
chainID sdk.Int chainID *sdk.Int
expectPass bool expectPass bool
}{ }{
{msg: "pass with recipient - Legacy Tx", to: suite.to.Hex(), amount: sdk.NewInt(100), gasPrice: sdk.NewInt(100000), expectPass: true}, {msg: "pass with recipient - Legacy Tx", to: suite.to.Hex(), amount: &hundredInt, gasPrice: &hundredInt, expectPass: true},
{msg: "pass with recipient - AccessList Tx", to: suite.to.Hex(), amount: sdk.NewInt(100), gasPrice: sdk.ZeroInt(), accessList: &ethtypes.AccessList{}, chainID: sdk.OneInt(), expectPass: true}, {msg: "pass with recipient - AccessList Tx", to: suite.to.Hex(), amount: &hundredInt, gasPrice: &zeroInt, accessList: &ethtypes.AccessList{}, chainID: &hundredInt, expectPass: true},
{msg: "pass contract - Legacy Tx", to: "", amount: sdk.NewInt(100), gasPrice: sdk.NewInt(100000), expectPass: true}, {msg: "pass contract - Legacy Tx", to: "", amount: &hundredInt, gasPrice: &hundredInt, expectPass: true},
{msg: "invalid recipient", to: invalidFromAddress, amount: sdk.NewInt(-1), gasPrice: sdk.NewInt(1000), expectPass: false}, // {msg: "invalid recipient", to: invalidFromAddress, amount: &minusOneInt, gasPrice: &hundredInt, expectPass: false},
{msg: "nil amount", to: suite.to.Hex(), amount: sdk.Int{}, gasPrice: sdk.NewInt(1000), expectPass: true}, {msg: "nil amount - Legacy Tx", to: suite.to.Hex(), amount: nil, gasPrice: &hundredInt, expectPass: true},
{msg: "negative amount", to: suite.to.Hex(), amount: sdk.NewInt(-1), gasPrice: sdk.NewInt(1000), expectPass: false}, {msg: "negative amount - Legacy Tx", to: suite.to.Hex(), amount: &minusOneInt, gasPrice: &hundredInt, expectPass: false},
{msg: "nil gas price", to: suite.to.Hex(), amount: sdk.NewInt(100), gasPrice: sdk.Int{}, expectPass: false}, {msg: "nil gas price - Legacy Tx", to: suite.to.Hex(), amount: &hundredInt, gasPrice: nil, expectPass: false},
{msg: "negative gas price", to: suite.to.Hex(), amount: sdk.NewInt(100), gasPrice: sdk.NewInt(-1), expectPass: false}, {msg: "negative gas price - Legacy Tx", to: suite.to.Hex(), amount: &hundredInt, gasPrice: &minusOneInt, expectPass: false},
{msg: "zero gas price", to: suite.to.Hex(), amount: sdk.NewInt(100), gasPrice: sdk.ZeroInt(), expectPass: true}, {msg: "zero gas price - Legacy Tx", to: suite.to.Hex(), amount: &hundredInt, gasPrice: &zeroInt, expectPass: true},
{msg: "invalid from address", to: suite.to.Hex(), amount: sdk.NewInt(100), gasPrice: sdk.ZeroInt(), from: invalidFromAddress, expectPass: false}, {msg: "invalid from address - Legacy Tx", to: suite.to.Hex(), amount: &hundredInt, gasPrice: &zeroInt, from: invalidFromAddress, expectPass: false},
{msg: "chain ID not set on AccessListTx", to: suite.to.Hex(), amount: sdk.NewInt(100), gasPrice: sdk.ZeroInt(), accessList: &ethtypes.AccessList{}, chainID: sdk.Int{}, expectPass: false}, {msg: "nil amount - AccessListTx", to: suite.to.Hex(), amount: nil, gasPrice: &hundredInt, accessList: &ethtypes.AccessList{}, chainID: &hundredInt, expectPass: true},
{msg: "negative amount - AccessListTx", to: suite.to.Hex(), amount: &minusOneInt, gasPrice: &hundredInt, accessList: &ethtypes.AccessList{}, chainID: nil, expectPass: false},
{msg: "nil gas price - AccessListTx", to: suite.to.Hex(), amount: &hundredInt, gasPrice: nil, accessList: &ethtypes.AccessList{}, chainID: &hundredInt, expectPass: false},
{msg: "negative gas price - AccessListTx", to: suite.to.Hex(), amount: &hundredInt, gasPrice: &minusOneInt, accessList: &ethtypes.AccessList{}, chainID: nil, expectPass: false},
{msg: "zero gas price - AccessListTx", to: suite.to.Hex(), amount: &hundredInt, gasPrice: &zeroInt, accessList: &ethtypes.AccessList{}, chainID: &hundredInt, expectPass: true},
{msg: "invalid from address - AccessListTx", to: suite.to.Hex(), amount: &hundredInt, gasPrice: &zeroInt, from: invalidFromAddress, accessList: &ethtypes.AccessList{}, chainID: &hundredInt, expectPass: false},
{msg: "chain ID not set on AccessListTx", to: suite.to.Hex(), amount: &hundredInt, gasPrice: &zeroInt, accessList: &ethtypes.AccessList{}, chainID: nil, expectPass: false},
} }
for i, tc := range testCases { for i, tc := range testCases {
// recreate txData to := common.HexToAddress(tc.from)
txData := TxData{
Nonce: 0, var chainID, amount, gasPrice *big.Int
GasLimit: 0, if tc.chainID != nil {
To: tc.to, chainID = tc.chainID.BigInt()
}
if tc.amount != nil {
amount = tc.amount.BigInt()
}
if tc.gasPrice != nil {
gasPrice = tc.gasPrice.BigInt()
} }
if tc.accessList != nil { tx := NewTx(chainID, 1, &to, amount, 1000, gasPrice, nil, tc.accessList)
txData.Accesses = NewAccessList(tc.accessList) tx.From = tc.from
if !tc.chainID.IsNil() {
txData.ChainID = tc.chainID
}
}
if !tc.amount.IsNil() { err := tx.ValidateBasic()
txData.Amount = tc.amount
}
if !tc.gasPrice.IsNil() {
txData.GasPrice = tc.gasPrice
}
msg := MsgEthereumTx{
Data: &txData,
}
msg.From = tc.from
err := msg.ValidateBasic()
if tc.expectPass { if tc.expectPass {
suite.Require().NoError(err, "valid test %d failed: %s, %v", i, tc.msg, msg) suite.Require().NoError(err, "valid test %d failed: %s, %v", i, tc.msg)
} else { } else {
suite.Require().Error(err, "invalid test %d passed: %s, %v", i, tc.msg, msg.Data) suite.Require().Error(err, "invalid test %d passed: %s, %v", i, tc.msg)
} }
} }
} }
@ -134,42 +134,42 @@ func (suite *MsgsTestSuite) TestMsgEthereumTx_Sign() {
}{ }{
{ {
"pass - EIP2930 signer", "pass - EIP2930 signer",
NewMsgEthereumTx(suite.chainID, 0, &suite.to, nil, 100000, nil, []byte("test"), &types.AccessList{}), NewTx(suite.chainID, 0, &suite.to, nil, 100000, nil, []byte("test"), &types.AccessList{}),
ethtypes.NewEIP2930Signer(suite.chainID), ethtypes.NewEIP2930Signer(suite.chainID),
func(tx *MsgEthereumTx) { tx.From = suite.from.Hex() }, func(tx *MsgEthereumTx) { tx.From = suite.from.Hex() },
true, true,
}, },
{ {
"pass - EIP155 signer", "pass - EIP155 signer",
NewMsgEthereumTx(suite.chainID, 0, &suite.to, nil, 100000, nil, []byte("test"), nil), NewTx(suite.chainID, 0, &suite.to, nil, 100000, nil, []byte("test"), nil),
ethtypes.NewEIP155Signer(suite.chainID), ethtypes.NewEIP155Signer(suite.chainID),
func(tx *MsgEthereumTx) { tx.From = suite.from.Hex() }, func(tx *MsgEthereumTx) { tx.From = suite.from.Hex() },
true, true,
}, },
{ {
"pass - Homestead signer", "pass - Homestead signer",
NewMsgEthereumTx(suite.chainID, 0, &suite.to, nil, 100000, nil, []byte("test"), nil), NewTx(suite.chainID, 0, &suite.to, nil, 100000, nil, []byte("test"), nil),
ethtypes.HomesteadSigner{}, ethtypes.HomesteadSigner{},
func(tx *MsgEthereumTx) { tx.From = suite.from.Hex() }, func(tx *MsgEthereumTx) { tx.From = suite.from.Hex() },
true, true,
}, },
{ {
"pass - Frontier signer", "pass - Frontier signer",
NewMsgEthereumTx(suite.chainID, 0, &suite.to, nil, 100000, nil, []byte("test"), nil), NewTx(suite.chainID, 0, &suite.to, nil, 100000, nil, []byte("test"), nil),
ethtypes.FrontierSigner{}, ethtypes.FrontierSigner{},
func(tx *MsgEthereumTx) { tx.From = suite.from.Hex() }, func(tx *MsgEthereumTx) { tx.From = suite.from.Hex() },
true, true,
}, },
{ {
"no from address ", "no from address ",
NewMsgEthereumTx(suite.chainID, 0, &suite.to, nil, 100000, nil, []byte("test"), &types.AccessList{}), NewTx(suite.chainID, 0, &suite.to, nil, 100000, nil, []byte("test"), &types.AccessList{}),
ethtypes.NewEIP2930Signer(suite.chainID), ethtypes.NewEIP2930Signer(suite.chainID),
func(tx *MsgEthereumTx) { tx.From = "" }, func(tx *MsgEthereumTx) { tx.From = "" },
false, false,
}, },
{ {
"from address ≠ signer address", "from address ≠ signer address",
NewMsgEthereumTx(suite.chainID, 0, &suite.to, nil, 100000, nil, []byte("test"), &types.AccessList{}), NewTx(suite.chainID, 0, &suite.to, nil, 100000, nil, []byte("test"), &types.AccessList{}),
ethtypes.NewEIP2930Signer(suite.chainID), ethtypes.NewEIP2930Signer(suite.chainID),
func(tx *MsgEthereumTx) { tx.From = suite.to.Hex() }, func(tx *MsgEthereumTx) { tx.From = suite.to.Hex() },
false, false,

View File

@ -2746,10 +2746,7 @@ func (m *QueryAccountRequest) Unmarshal(dAtA []byte) error {
if err != nil { if err != nil {
return err return err
} }
if skippy < 0 { if (skippy < 0) || (iNdEx+skippy) < 0 {
return ErrInvalidLengthQuery
}
if (iNdEx + skippy) < 0 {
return ErrInvalidLengthQuery return ErrInvalidLengthQuery
} }
if (iNdEx + skippy) > l { if (iNdEx + skippy) > l {
@ -2882,10 +2879,7 @@ func (m *QueryAccountResponse) Unmarshal(dAtA []byte) error {
if err != nil { if err != nil {
return err return err
} }
if skippy < 0 { if (skippy < 0) || (iNdEx+skippy) < 0 {
return ErrInvalidLengthQuery
}
if (iNdEx + skippy) < 0 {
return ErrInvalidLengthQuery return ErrInvalidLengthQuery
} }
if (iNdEx + skippy) > l { if (iNdEx + skippy) > l {
@ -2967,10 +2961,7 @@ func (m *QueryCosmosAccountRequest) Unmarshal(dAtA []byte) error {
if err != nil { if err != nil {
return err return err
} }
if skippy < 0 { if (skippy < 0) || (iNdEx+skippy) < 0 {
return ErrInvalidLengthQuery
}
if (iNdEx + skippy) < 0 {
return ErrInvalidLengthQuery return ErrInvalidLengthQuery
} }
if (iNdEx + skippy) > l { if (iNdEx + skippy) > l {
@ -3090,10 +3081,7 @@ func (m *QueryCosmosAccountResponse) Unmarshal(dAtA []byte) error {
if err != nil { if err != nil {
return err return err
} }
if skippy < 0 { if (skippy < 0) || (iNdEx+skippy) < 0 {
return ErrInvalidLengthQuery
}
if (iNdEx + skippy) < 0 {
return ErrInvalidLengthQuery return ErrInvalidLengthQuery
} }
if (iNdEx + skippy) > l { if (iNdEx + skippy) > l {
@ -3175,10 +3163,7 @@ func (m *QueryValidatorAccountRequest) Unmarshal(dAtA []byte) error {
if err != nil { if err != nil {
return err return err
} }
if skippy < 0 { if (skippy < 0) || (iNdEx+skippy) < 0 {
return ErrInvalidLengthQuery
}
if (iNdEx + skippy) < 0 {
return ErrInvalidLengthQuery return ErrInvalidLengthQuery
} }
if (iNdEx + skippy) > l { if (iNdEx + skippy) > l {
@ -3298,10 +3283,7 @@ func (m *QueryValidatorAccountResponse) Unmarshal(dAtA []byte) error {
if err != nil { if err != nil {
return err return err
} }
if skippy < 0 { if (skippy < 0) || (iNdEx+skippy) < 0 {
return ErrInvalidLengthQuery
}
if (iNdEx + skippy) < 0 {
return ErrInvalidLengthQuery return ErrInvalidLengthQuery
} }
if (iNdEx + skippy) > l { if (iNdEx + skippy) > l {
@ -3383,10 +3365,7 @@ func (m *QueryBalanceRequest) Unmarshal(dAtA []byte) error {
if err != nil { if err != nil {
return err return err
} }
if skippy < 0 { if (skippy < 0) || (iNdEx+skippy) < 0 {
return ErrInvalidLengthQuery
}
if (iNdEx + skippy) < 0 {
return ErrInvalidLengthQuery return ErrInvalidLengthQuery
} }
if (iNdEx + skippy) > l { if (iNdEx + skippy) > l {
@ -3468,10 +3447,7 @@ func (m *QueryBalanceResponse) Unmarshal(dAtA []byte) error {
if err != nil { if err != nil {
return err return err
} }
if skippy < 0 { if (skippy < 0) || (iNdEx+skippy) < 0 {
return ErrInvalidLengthQuery
}
if (iNdEx + skippy) < 0 {
return ErrInvalidLengthQuery return ErrInvalidLengthQuery
} }
if (iNdEx + skippy) > l { if (iNdEx + skippy) > l {
@ -3585,10 +3561,7 @@ func (m *QueryStorageRequest) Unmarshal(dAtA []byte) error {
if err != nil { if err != nil {
return err return err
} }
if skippy < 0 { if (skippy < 0) || (iNdEx+skippy) < 0 {
return ErrInvalidLengthQuery
}
if (iNdEx + skippy) < 0 {
return ErrInvalidLengthQuery return ErrInvalidLengthQuery
} }
if (iNdEx + skippy) > l { if (iNdEx + skippy) > l {
@ -3670,10 +3643,7 @@ func (m *QueryStorageResponse) Unmarshal(dAtA []byte) error {
if err != nil { if err != nil {
return err return err
} }
if skippy < 0 { if (skippy < 0) || (iNdEx+skippy) < 0 {
return ErrInvalidLengthQuery
}
if (iNdEx + skippy) < 0 {
return ErrInvalidLengthQuery return ErrInvalidLengthQuery
} }
if (iNdEx + skippy) > l { if (iNdEx + skippy) > l {
@ -3755,10 +3725,7 @@ func (m *QueryCodeRequest) Unmarshal(dAtA []byte) error {
if err != nil { if err != nil {
return err return err
} }
if skippy < 0 { if (skippy < 0) || (iNdEx+skippy) < 0 {
return ErrInvalidLengthQuery
}
if (iNdEx + skippy) < 0 {
return ErrInvalidLengthQuery return ErrInvalidLengthQuery
} }
if (iNdEx + skippy) > l { if (iNdEx + skippy) > l {
@ -3842,10 +3809,7 @@ func (m *QueryCodeResponse) Unmarshal(dAtA []byte) error {
if err != nil { if err != nil {
return err return err
} }
if skippy < 0 { if (skippy < 0) || (iNdEx+skippy) < 0 {
return ErrInvalidLengthQuery
}
if (iNdEx + skippy) < 0 {
return ErrInvalidLengthQuery return ErrInvalidLengthQuery
} }
if (iNdEx + skippy) > l { if (iNdEx + skippy) > l {
@ -3927,10 +3891,7 @@ func (m *QueryTxLogsRequest) Unmarshal(dAtA []byte) error {
if err != nil { if err != nil {
return err return err
} }
if skippy < 0 { if (skippy < 0) || (iNdEx+skippy) < 0 {
return ErrInvalidLengthQuery
}
if (iNdEx + skippy) < 0 {
return ErrInvalidLengthQuery return ErrInvalidLengthQuery
} }
if (iNdEx + skippy) > l { if (iNdEx + skippy) > l {
@ -4014,10 +3975,7 @@ func (m *QueryTxLogsResponse) Unmarshal(dAtA []byte) error {
if err != nil { if err != nil {
return err return err
} }
if skippy < 0 { if (skippy < 0) || (iNdEx+skippy) < 0 {
return ErrInvalidLengthQuery
}
if (iNdEx + skippy) < 0 {
return ErrInvalidLengthQuery return ErrInvalidLengthQuery
} }
if (iNdEx + skippy) > l { if (iNdEx + skippy) > l {
@ -4135,10 +4093,7 @@ func (m *QueryBlockLogsRequest) Unmarshal(dAtA []byte) error {
if err != nil { if err != nil {
return err return err
} }
if skippy < 0 { if (skippy < 0) || (iNdEx+skippy) < 0 {
return ErrInvalidLengthQuery
}
if (iNdEx + skippy) < 0 {
return ErrInvalidLengthQuery return ErrInvalidLengthQuery
} }
if (iNdEx + skippy) > l { if (iNdEx + skippy) > l {
@ -4258,10 +4213,7 @@ func (m *QueryBlockLogsResponse) Unmarshal(dAtA []byte) error {
if err != nil { if err != nil {
return err return err
} }
if skippy < 0 { if (skippy < 0) || (iNdEx+skippy) < 0 {
return ErrInvalidLengthQuery
}
if (iNdEx + skippy) < 0 {
return ErrInvalidLengthQuery return ErrInvalidLengthQuery
} }
if (iNdEx + skippy) > l { if (iNdEx + skippy) > l {
@ -4311,10 +4263,7 @@ func (m *QueryBlockBloomRequest) Unmarshal(dAtA []byte) error {
if err != nil { if err != nil {
return err return err
} }
if skippy < 0 { if (skippy < 0) || (iNdEx+skippy) < 0 {
return ErrInvalidLengthQuery
}
if (iNdEx + skippy) < 0 {
return ErrInvalidLengthQuery return ErrInvalidLengthQuery
} }
if (iNdEx + skippy) > l { if (iNdEx + skippy) > l {
@ -4398,10 +4347,7 @@ func (m *QueryBlockBloomResponse) Unmarshal(dAtA []byte) error {
if err != nil { if err != nil {
return err return err
} }
if skippy < 0 { if (skippy < 0) || (iNdEx+skippy) < 0 {
return ErrInvalidLengthQuery
}
if (iNdEx + skippy) < 0 {
return ErrInvalidLengthQuery return ErrInvalidLengthQuery
} }
if (iNdEx + skippy) > l { if (iNdEx + skippy) > l {
@ -4451,10 +4397,7 @@ func (m *QueryParamsRequest) Unmarshal(dAtA []byte) error {
if err != nil { if err != nil {
return err return err
} }
if skippy < 0 { if (skippy < 0) || (iNdEx+skippy) < 0 {
return ErrInvalidLengthQuery
}
if (iNdEx + skippy) < 0 {
return ErrInvalidLengthQuery return ErrInvalidLengthQuery
} }
if (iNdEx + skippy) > l { if (iNdEx + skippy) > l {
@ -4537,10 +4480,7 @@ func (m *QueryParamsResponse) Unmarshal(dAtA []byte) error {
if err != nil { if err != nil {
return err return err
} }
if skippy < 0 { if (skippy < 0) || (iNdEx+skippy) < 0 {
return ErrInvalidLengthQuery
}
if (iNdEx + skippy) < 0 {
return ErrInvalidLengthQuery return ErrInvalidLengthQuery
} }
if (iNdEx + skippy) > l { if (iNdEx + skippy) > l {
@ -4656,10 +4596,7 @@ func (m *QueryStaticCallRequest) Unmarshal(dAtA []byte) error {
if err != nil { if err != nil {
return err return err
} }
if skippy < 0 { if (skippy < 0) || (iNdEx+skippy) < 0 {
return ErrInvalidLengthQuery
}
if (iNdEx + skippy) < 0 {
return ErrInvalidLengthQuery return ErrInvalidLengthQuery
} }
if (iNdEx + skippy) > l { if (iNdEx + skippy) > l {
@ -4743,10 +4680,7 @@ func (m *QueryStaticCallResponse) Unmarshal(dAtA []byte) error {
if err != nil { if err != nil {
return err return err
} }
if skippy < 0 { if (skippy < 0) || (iNdEx+skippy) < 0 {
return ErrInvalidLengthQuery
}
if (iNdEx + skippy) < 0 {
return ErrInvalidLengthQuery return ErrInvalidLengthQuery
} }
if (iNdEx + skippy) > l { if (iNdEx + skippy) > l {

File diff suppressed because it is too large Load Diff

View File

@ -3,200 +3,49 @@ package types
import ( import (
"math/big" "math/big"
sdk "github.com/cosmos/cosmos-sdk/types"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
ethtypes "github.com/ethereum/go-ethereum/core/types" ethtypes "github.com/ethereum/go-ethereum/core/types"
"github.com/tharsis/ethermint/types"
) )
// var _ ethtypes.TxData = &TxData{} var _ TxData = &AccessListTx{}
func newTxData( // TxData implements the Ethereum transaction tx structure. It is used
chainID *big.Int, nonce uint64, to *common.Address, amount *big.Int, // solely as intended in Ethereum abiding by the protocol.
gasLimit uint64, gasPrice *big.Int, input []byte, accesses *ethtypes.AccessList, type TxData interface {
) *TxData { // TODO: embed ethtypes.TxData. See https://github.com/ethereum/go-ethereum/issues/23154
txData := &TxData{
Nonce: nonce, TxType() byte
GasLimit: gasLimit, Copy() TxData
GetChainID() *big.Int
GetAccessList() ethtypes.AccessList
GetData() []byte
GetNonce() uint64
GetGas() uint64
GetGasPrice() *big.Int
GetValue() *big.Int
GetTo() *common.Address
GetRawSignatureValues() (v, r, s *big.Int)
SetSignatureValues(chainID, v, r, s *big.Int)
AsEthereumData() ethtypes.TxData
Validate() error
Fee() *big.Int
Cost() *big.Int
}
func NewTxDataFromTx(tx *ethtypes.Transaction) TxData {
var txData TxData
switch tx.Type() {
case ethtypes.AccessListTxType:
txData = newAccessListTx(tx)
default:
txData = newLegacyTx(tx)
} }
txData.Input = common.CopyBytes(input)
if to != nil {
txData.To = to.Hex()
}
if accesses != nil {
txData.Accesses = NewAccessList(accesses)
// NOTE: we don't populate chain id on LegacyTx type
if chainID != nil {
txData.ChainID = sdk.NewIntFromBigInt(chainID)
}
}
if amount != nil {
txData.Amount = sdk.NewIntFromBigInt(amount)
}
if gasPrice != nil {
txData.GasPrice = sdk.NewIntFromBigInt(gasPrice)
}
return txData return txData
} }
// Type returns the tx type
func (data TxData) Type() uint8 {
return data.txType()
}
func (data *TxData) txType() uint8 {
if data.Accesses == nil {
return ethtypes.LegacyTxType
}
return ethtypes.AccessListTxType
}
func (data *TxData) chainID() *big.Int {
if data.txType() == ethtypes.LegacyTxType {
v, _, _ := data.rawSignatureValues()
return DeriveChainID(v)
}
return data.ChainID.BigInt()
}
func (data *TxData) accessList() ethtypes.AccessList {
if data.Accesses == nil {
return nil
}
return *data.Accesses.ToEthAccessList()
}
func (data *TxData) data() []byte {
return common.CopyBytes(data.Input)
}
func (data *TxData) gas() uint64 {
return data.GasLimit
}
func (data *TxData) gasPrice() *big.Int {
return data.GasPrice.BigInt()
}
func (data *TxData) amount() *big.Int {
return data.Amount.BigInt()
}
func (data *TxData) nonce() uint64 { return data.Nonce }
func (data *TxData) to() *common.Address {
if data.To == "" {
return nil
}
to := common.HexToAddress(data.To)
return &to
}
// AsEthereumData returns an AccessListTx transaction data from the proto-formatted
// TxData defined on the Cosmos EVM.
func (data *TxData) AsEthereumData() ethtypes.TxData {
v, r, s := data.rawSignatureValues()
if data.Accesses == nil {
return &ethtypes.LegacyTx{
Nonce: data.nonce(),
GasPrice: data.gasPrice(),
Gas: data.gas(),
To: data.to(),
Value: data.amount(),
Data: data.data(),
V: v,
R: r,
S: s,
}
}
return &ethtypes.AccessListTx{
ChainID: data.chainID(),
Nonce: data.nonce(),
GasPrice: data.gasPrice(),
Gas: data.gas(),
To: data.to(),
Value: data.amount(),
Data: data.data(),
AccessList: data.accessList(),
V: v,
R: r,
S: s,
}
}
// rawSignatureValues returns the V, R, S signature values of the transaction.
// The return values should not be modified by the caller.
func (data *TxData) rawSignatureValues() (v, r, s *big.Int) {
if len(data.V) > 0 {
v = new(big.Int).SetBytes(data.V)
}
if len(data.R) > 0 {
r = new(big.Int).SetBytes(data.R)
}
if len(data.S) > 0 {
s = new(big.Int).SetBytes(data.S)
}
return v, r, s
}
func (data *TxData) setSignatureValues(chainID, v, r, s *big.Int) {
if v != nil {
data.V = v.Bytes()
}
if r != nil {
data.R = r.Bytes()
}
if s != nil {
data.S = s.Bytes()
}
if data.txType() == ethtypes.AccessListTxType && chainID != nil {
data.ChainID = sdk.NewIntFromBigInt(chainID)
}
}
// Validate performs a basic validation of the tx data fields.
func (data TxData) Validate() error {
gasPrice := data.gasPrice()
if gasPrice == nil {
return sdkerrors.Wrap(ErrInvalidGasPrice, "cannot be nil")
}
if gasPrice.Sign() == -1 {
return sdkerrors.Wrapf(ErrInvalidGasPrice, "gas price cannot be negative %s", gasPrice)
}
amount := data.amount()
// Amount can be 0
if amount != nil && amount.Sign() == -1 {
return sdkerrors.Wrapf(ErrInvalidAmount, "amount cannot be negative %s", amount)
}
if data.To != "" {
if err := types.ValidateAddress(data.To); err != nil {
return sdkerrors.Wrap(err, "invalid to address")
}
}
if data.txType() == ethtypes.AccessListTxType && data.chainID() == nil {
return sdkerrors.Wrap(
sdkerrors.ErrInvalidChainID,
"chain ID must be present on AccessList txs",
)
}
return nil
}
// DeriveChainID derives the chain id from the given v parameter // DeriveChainID derives the chain id from the given v parameter
func DeriveChainID(v *big.Int) *big.Int { func DeriveChainID(v *big.Int) *big.Int {
if v == nil { if v == nil {
@ -213,3 +62,28 @@ func DeriveChainID(v *big.Int) *big.Int {
v = new(big.Int).Sub(v, big.NewInt(35)) v = new(big.Int).Sub(v, big.NewInt(35))
return v.Div(v, big.NewInt(2)) return v.Div(v, big.NewInt(2))
} }
func rawSignatureValues(vBz, rBz, sBz []byte) (v, r, s *big.Int) {
if len(vBz) > 0 {
v = new(big.Int).SetBytes(vBz)
}
if len(rBz) > 0 {
r = new(big.Int).SetBytes(rBz)
}
if len(sBz) > 0 {
s = new(big.Int).SetBytes(sBz)
}
return v, r, s
}
func fee(gasPrice *big.Int, gas uint64) *big.Int {
gasLimit := new(big.Int).SetUint64(gas)
return new(big.Int).Mul(gasPrice, gasLimit)
}
func cost(fee, value *big.Int) *big.Int {
if value != nil {
return new(big.Int).Add(fee, value)
}
return fee
}

View File

@ -13,24 +13,26 @@ import (
) )
func TestTxData_chainID(t *testing.T) { func TestTxData_chainID(t *testing.T) {
chainID := sdk.NewInt(1)
testCases := []struct { testCases := []struct {
msg string msg string
data TxData data TxData
expChainID *big.Int expChainID *big.Int
}{ }{
{ {
"access list tx", TxData{Accesses: AccessList{}, ChainID: sdk.NewInt(1)}, big.NewInt(1), "access list tx", &AccessListTx{Accesses: AccessList{}, ChainID: &chainID}, big.NewInt(1),
}, },
{ {
"access list tx, nil chain ID", TxData{Accesses: AccessList{}}, nil, "access list tx, nil chain ID", &AccessListTx{Accesses: AccessList{}}, nil,
}, },
{ {
"legacy tx, derived", TxData{}, nil, "legacy tx, derived", &LegacyTx{}, nil,
}, },
} }
for _, tc := range testCases { for _, tc := range testCases {
chainID := tc.data.chainID() chainID := tc.data.GetChainID()
require.Equal(t, chainID, tc.expChainID, tc.msg) require.Equal(t, chainID, tc.expChainID, tc.msg)
} }
} }
@ -43,24 +45,24 @@ func TestTxData_DeriveChainID(t *testing.T) {
from common.Address from common.Address
}{ }{
{ {
"v = 0", TxData{V: big.NewInt(0).Bytes()}, nil, tests.GenerateAddress(), "v = 0", &AccessListTx{V: big.NewInt(0).Bytes()}, nil, tests.GenerateAddress(),
}, },
{ {
"v = 1", TxData{V: big.NewInt(1).Bytes()}, big.NewInt(9223372036854775791), tests.GenerateAddress(), "v = 1", &AccessListTx{V: big.NewInt(1).Bytes()}, big.NewInt(9223372036854775791), tests.GenerateAddress(),
}, },
{ {
"v = 27", TxData{V: big.NewInt(27).Bytes()}, new(big.Int), tests.GenerateAddress(), "v = 27", &AccessListTx{V: big.NewInt(27).Bytes()}, new(big.Int), tests.GenerateAddress(),
}, },
{ {
"v = 28", TxData{V: big.NewInt(28).Bytes()}, new(big.Int), tests.GenerateAddress(), "v = 28", &AccessListTx{V: big.NewInt(28).Bytes()}, new(big.Int), tests.GenerateAddress(),
}, },
{ {
"v = nil ", TxData{V: nil}, nil, tests.GenerateAddress(), "v = nil ", &AccessListTx{V: nil}, nil, tests.GenerateAddress(),
}, },
} }
for _, tc := range testCases { for _, tc := range testCases {
v, _, _ := tc.data.rawSignatureValues() v, _, _ := tc.data.GetRawSignatureValues()
chainID := DeriveChainID(v) chainID := DeriveChainID(v)
require.Equal(t, tc.expChainID, chainID, tc.msg) require.Equal(t, tc.expChainID, chainID, tc.msg)