rpc, evm: remove tx Receipt (#81)

* rpc, evm: remove tc receipt

* rm receipt from gRPC query service

* update eth block

* update tx service response

* rpc tx fixes

* update bloom

* fix

* more fixes

* c++
This commit is contained in:
Federico Kunze 2021-06-08 07:11:37 -04:00 committed by GitHub
parent e3270aee5d
commit 6eadc8fdf8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
27 changed files with 458 additions and 1820 deletions

View File

@ -39,11 +39,16 @@ Ref: https://keepachangelog.com/en/1.0.0/
### State Machine Breaking
* (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#68](https://github.com/tharsis/ethermint/issues/68) Replace block hash storage map to use staking `HistoricalInfo`.
### API Breaking
* (proto, evm) [tharsis#81](https://github.com/tharsis/ethermint/pull/81) gRPC Query and Tx service changes:
* The `TxReceipt`, `TxReceiptsByBlockHeight` endpoints have been removed from the Query service.
* The `ContractAddress`, `Bloom` have been removed from the `MsgEthereumTxResponse` and the
response now contains the ethereum-formatted `Hash` in hex format.
* (eth) [\#845](https://github.com/cosmos/ethermint/pull/845) The `eth` namespace must be included in the list of API's as default to run the rpc server without error.
### Improvements
@ -53,6 +58,7 @@ Ref: https://keepachangelog.com/en/1.0.0/
### Bug Fixes
* (rpc) [tharsis#81](https://github.com/tharsis/ethermint/pull/81) Fix transaction hashing and decoding on `eth_sendTransaction`.
* (rpc) [tharsis#45](https://github.com/tharsis/ethermint/pull/45) Use `EmptyUncleHash` and `EmptyRootHash` for empty ethereum `Header` fields.
## [v0.4.1] - 2021-03-01

View File

@ -45,10 +45,6 @@
- [QueryStorageResponse](#ethermint.evm.v1alpha1.QueryStorageResponse)
- [QueryTxLogsRequest](#ethermint.evm.v1alpha1.QueryTxLogsRequest)
- [QueryTxLogsResponse](#ethermint.evm.v1alpha1.QueryTxLogsResponse)
- [QueryTxReceiptRequest](#ethermint.evm.v1alpha1.QueryTxReceiptRequest)
- [QueryTxReceiptResponse](#ethermint.evm.v1alpha1.QueryTxReceiptResponse)
- [QueryTxReceiptsByBlockHeightRequest](#ethermint.evm.v1alpha1.QueryTxReceiptsByBlockHeightRequest)
- [QueryTxReceiptsByBlockHeightResponse](#ethermint.evm.v1alpha1.QueryTxReceiptsByBlockHeightResponse)
- [Query](#ethermint.evm.v1alpha1.Query)
@ -708,61 +704,6 @@ QueryTxLogs is the response type for the Query/TxLogs RPC method.
<a name="ethermint.evm.v1alpha1.QueryTxReceiptRequest"></a>
### QueryTxReceiptRequest
QueryTxReceiptRequest is the request type for the Query/TxReceipt RPC method.
| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| `hash` | [string](#string) | | hash is the ethereum transaction hex hash to query the receipt for. |
<a name="ethermint.evm.v1alpha1.QueryTxReceiptResponse"></a>
### QueryTxReceiptResponse
QueryTxReceiptResponse is the response type for the Query/TxReceipt RPC method.
| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| `receipt` | [TxReceipt](#ethermint.evm.v1alpha1.TxReceipt) | | receipt represents the ethereum receipt for the given transaction. |
<a name="ethermint.evm.v1alpha1.QueryTxReceiptsByBlockHeightRequest"></a>
### QueryTxReceiptsByBlockHeightRequest
QueryTxReceiptsByBlockHeightRequest is the request type for the Query/TxReceiptsByBlockHeight RPC method.
<a name="ethermint.evm.v1alpha1.QueryTxReceiptsByBlockHeightResponse"></a>
### QueryTxReceiptsByBlockHeightResponse
QueryTxReceiptsByBlockHeightResponse is the response type for the Query/TxReceiptsByBlockHeight RPC method.
| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| `receipts` | [TxReceipt](#ethermint.evm.v1alpha1.TxReceipt) | repeated | tx receipts list for the block |
<!-- end messages -->
<!-- end enums -->
@ -783,8 +724,6 @@ Query defines the gRPC querier service.
| `Storage` | [QueryStorageRequest](#ethermint.evm.v1alpha1.QueryStorageRequest) | [QueryStorageResponse](#ethermint.evm.v1alpha1.QueryStorageResponse) | Storage queries the balance of all coins for a single account. | GET|/ethermint/evm/v1alpha1/storage/{address}/{key}|
| `Code` | [QueryCodeRequest](#ethermint.evm.v1alpha1.QueryCodeRequest) | [QueryCodeResponse](#ethermint.evm.v1alpha1.QueryCodeResponse) | Code queries the balance of all coins for a single account. | GET|/ethermint/evm/v1alpha1/codes/{address}|
| `TxLogs` | [QueryTxLogsRequest](#ethermint.evm.v1alpha1.QueryTxLogsRequest) | [QueryTxLogsResponse](#ethermint.evm.v1alpha1.QueryTxLogsResponse) | TxLogs queries ethereum logs from a transaction. | GET|/ethermint/evm/v1alpha1/tx_logs/{hash}|
| `TxReceipt` | [QueryTxReceiptRequest](#ethermint.evm.v1alpha1.QueryTxReceiptRequest) | [QueryTxReceiptResponse](#ethermint.evm.v1alpha1.QueryTxReceiptResponse) | TxReceipt queries a receipt by a transaction hash. | GET|/ethermint/evm/v1alpha1/tx_receipt/{hash}|
| `TxReceiptsByBlockHeight` | [QueryTxReceiptsByBlockHeightRequest](#ethermint.evm.v1alpha1.QueryTxReceiptsByBlockHeightRequest) | [QueryTxReceiptsByBlockHeightResponse](#ethermint.evm.v1alpha1.QueryTxReceiptsByBlockHeightResponse) | TxReceiptsByBlockHeight queries tx receipts by a block height. | GET|/ethermint/evm/v1alpha1/tx_receipts_block|
| `BlockLogs` | [QueryBlockLogsRequest](#ethermint.evm.v1alpha1.QueryBlockLogsRequest) | [QueryBlockLogsResponse](#ethermint.evm.v1alpha1.QueryBlockLogsResponse) | BlockLogs queries all the ethereum logs for a given block hash. | GET|/ethermint/evm/v1alpha1/block_logs/{hash}|
| `BlockBloom` | [QueryBlockBloomRequest](#ethermint.evm.v1alpha1.QueryBlockBloomRequest) | [QueryBlockBloomResponse](#ethermint.evm.v1alpha1.QueryBlockBloomResponse) | BlockBloom queries the block bloom filter bytes at a given height. | GET|/ethermint/evm/v1alpha1/block_bloom|
| `Params` | [QueryParamsRequest](#ethermint.evm.v1alpha1.QueryParamsRequest) | [QueryParamsResponse](#ethermint.evm.v1alpha1.QueryParamsResponse) | Params queries the parameters of x/evm module. | GET|/ethermint/evm/v1alpha1/params|
@ -849,10 +788,9 @@ MsgEthereumTxResponse defines the Msg/EthereumTx response type.
| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| `contract_address` | [string](#string) | | contract_address contains the ethereum address of the created contract (if any). If the state transition is an evm.Call, the contract address will be empty. |
| `bloom` | [bytes](#bytes) | | bloom represents the bloom filter bytes |
| `tx_logs` | [TransactionLogs](#ethermint.evm.v1alpha1.TransactionLogs) | | tx_logs contains the transaction hash and the proto-compatible ethereum logs. |
| `ret` | [bytes](#bytes) | | ret defines the bytes from the execution. |
| `hash` | [string](#string) | | ethereum transaction hash in hex format. This hash differs from the Tendermint sha256 hash of the transaction bytes. See https://github.com/tendermint/tendermint/issues/6539 for reference |
| `logs` | [Log](#ethermint.evm.v1alpha1.Log) | repeated | logs contains the transaction hash and the proto-compatible ethereum logs. |
| `ret` | [bytes](#bytes) | | returned data from evm function (result or data supplied with revert opcode) |
| `reverted` | [bool](#bool) | | reverted flag is set to true when the call has been reverted |

View File

@ -133,43 +133,44 @@ func (e *EVMBackend) EthBlockFromTendermint(
fullTx bool,
) (map[string]interface{}, error) {
req := &evmtypes.QueryTxReceiptsByBlockHeightRequest{}
txReceiptsResp, err := queryClient.TxReceiptsByBlockHeight(types.ContextWithHeight(block.Height), req)
if err != nil {
e.logger.WithError(err).Debugln("TxReceiptsByBlockHeight failed")
}
gasUsed := big.NewInt(0)
gasUsed := uint64(0)
ethRPCTxs := []interface{}{}
if txReceiptsResp != nil {
for i, txBz := range block.Txs {
// TODO: use msg.AsTransaction.Hash() for txHash once hashing is fixed on Tendermint
// https://github.com/tendermint/tendermint/issues/6539
hash := common.BytesToHash(txBz.Hash())
for _, receipt := range txReceiptsResp.Receipts {
hash := common.HexToHash(receipt.Hash)
if fullTx {
// full txs from receipts
tx, err := types.NewTransactionFromData(
receipt.Data,
common.HexToAddress(receipt.From),
hash,
common.HexToHash(receipt.BlockHash),
receipt.BlockHeight,
receipt.Index,
)
tx, gas := types.DecodeTx(e.clientCtx, txBz)
if err != nil {
e.logger.WithError(err).Warningf("NewTransactionFromData for receipt %s failed", hash)
continue
}
gasUsed += gas
ethRPCTxs = append(ethRPCTxs, tx)
gasUsed.Add(gasUsed, new(big.Int).SetUint64(receipt.Result.GasUsed))
} else {
// simply hashes
ethRPCTxs = append(ethRPCTxs, hash)
msg, isEthTx := tx.(*evmtypes.MsgEthereumTx)
if fullTx {
if !isEthTx {
// TODO: eventually support Cosmos txs in the block
continue
}
tx, err := types.NewTransactionFromData(
msg.Data,
common.HexToAddress(msg.From),
hash,
common.BytesToHash(block.Hash()),
uint64(block.Height),
uint64(i),
)
ethRPCTxs = append(ethRPCTxs, tx)
if err != nil {
e.logger.WithError(err).Debugln("NewTransactionFromData for receipt failed", "hash", hash.Hex)
continue
}
} else {
ethRPCTxs = append(ethRPCTxs, hash)
}
}
@ -181,7 +182,7 @@ func (e *EVMBackend) EthBlockFromTendermint(
}
bloom := ethtypes.BytesToBloom(blockBloomResp.Bloom)
formattedBlock := types.FormatBlock(block.Header, block.Size(), ethermint.DefaultRPCGasLimit, gasUsed, ethRPCTxs, bloom)
formattedBlock := types.FormatBlock(block.Header, block.Size(), ethermint.DefaultRPCGasLimit, new(big.Int).SetUint64(gasUsed), ethRPCTxs, bloom)
e.logger.Infoln(formattedBlock)
return formattedBlock, nil

View File

@ -21,13 +21,13 @@ import (
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
abci "github.com/tendermint/tendermint/abci/types"
"github.com/tendermint/tendermint/crypto/tmhash"
tmtypes "github.com/tendermint/tendermint/types"
"github.com/ethereum/go-ethereum/accounts/keystore"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
ethtypes "github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/rlp"
"github.com/ethereum/go-ethereum/crypto"
"github.com/cosmos/ethermint/crypto/hd"
rpctypes "github.com/cosmos/ethermint/ethereum/rpc/types"
@ -391,10 +391,14 @@ func (e *PublicEthAPI) SendTransaction(args rpctypes.SendTxArgs) (common.Hash, e
txEncoder := e.clientCtx.TxConfig.TxEncoder()
txBytes, err := txEncoder(tx)
if err != nil {
e.logger.WithError(err).Errorln("failed to encode eth tx using default encoder")
return common.Hash{}, err
}
txHash := common.BytesToHash(txBytes)
// TODO: use msg.AsTransaction.Hash() for txHash once hashing is fixed on Tendermint
// https://github.com/tendermint/tendermint/issues/6539
tmTx := tmtypes.Tx(txBytes)
txHash := common.BytesToHash(tmTx.Hash())
// Broadcast transaction in sync mode (default)
// NOTE: If error is encountered on the node, the broadcast will not return an error
@ -411,16 +415,21 @@ func (e *PublicEthAPI) SendTransaction(args rpctypes.SendTxArgs) (common.Hash, e
// SendRawTransaction send a raw Ethereum transaction.
func (e *PublicEthAPI) SendRawTransaction(data hexutil.Bytes) (common.Hash, error) {
e.logger.Debugln("eth_sendRawTransaction", "data_len", len(data))
ethereumTx := new(evmtypes.MsgEthereumTx)
// RLP decode raw transaction bytes
if err := rlp.DecodeBytes(data, ethereumTx); err != nil {
e.logger.WithError(err).Errorln("transaction RLP decode failed")
tx, err := e.clientCtx.TxConfig.TxDecoder()(data)
if err != nil {
e.logger.WithError(err).Errorln("transaction decoding failed")
// Return nil is for when gasLimit overflows uint64
return common.Hash{}, err
}
ethereumTx, isEthTx := tx.(*evmtypes.MsgEthereumTx)
if !isEthTx {
e.logger.Debugln("invalid transaction type", "type", fmt.Sprintf("%T", tx))
return common.Hash{}, fmt.Errorf("invalid transaction type %T", tx)
}
builder, ok := e.clientCtx.TxConfig.NewTxBuilder().(authtx.ExtensionOptionsTxBuilder)
if !ok {
e.logger.Panicln("clientCtx.TxConfig.NewTxBuilder returns unsupported builder")
@ -432,7 +441,7 @@ func (e *PublicEthAPI) SendRawTransaction(data hexutil.Bytes) (common.Hash, erro
}
builder.SetExtensionOptions(option)
err = builder.SetMsgs(ethereumTx.GetMsgs()...)
err = builder.SetMsgs(tx.GetMsgs()...)
if err != nil {
e.logger.WithError(err).Panicln("builder.SetMsgs failed")
}
@ -444,15 +453,19 @@ func (e *PublicEthAPI) SendRawTransaction(data hexutil.Bytes) (common.Hash, erro
// Encode transaction by default Tx encoder
txBytes, err := e.clientCtx.TxConfig.TxEncoder()(builder.GetTx())
if err != nil {
e.logger.WithError(err).Errorln("failed to encode Eth tx using default encoder")
e.logger.WithError(err).Errorln("failed to encode eth tx using default encoder")
return common.Hash{}, err
}
txHash := common.BytesToHash(tmhash.Sum(txBytes))
// TODO: use msg.AsTransaction.Hash() for txHash once hashing is fixed on Tendermint
// https://github.com/tendermint/tendermint/issues/6539
tmTx := tmtypes.Tx(txBytes)
txHash := common.BytesToHash(tmTx.Hash())
asyncCtx := e.clientCtx.WithBroadcastMode(flags.BroadcastAsync)
if _, err := asyncCtx.BroadcastTx(txBytes); err != nil {
e.logger.WithError(err).Errorln("failed to broadcast Eth tx")
e.logger.WithError(err).Errorln("failed to broadcast eth tx")
return txHash, err
}
@ -461,7 +474,7 @@ func (e *PublicEthAPI) SendRawTransaction(data hexutil.Bytes) (common.Hash, erro
// Call performs a raw contract call.
func (e *PublicEthAPI) Call(args rpctypes.CallArgs, blockNr rpctypes.BlockNumber, _ *rpctypes.StateOverride) (hexutil.Bytes, error) {
//e.logger.Debugln("eth_call", "args", args, "block number", blockNr)
e.logger.Debugln("eth_call", "args", args, "block number", blockNr)
simRes, err := e.doCall(args, blockNr, big.NewInt(ethermint.DefaultRPCGasLimit))
if err != nil {
return []byte{}, err
@ -561,8 +574,8 @@ func (e *PublicEthAPI) doCall(
txBuilder.SetFeeAmount(fees)
txBuilder.SetGasLimit(gas)
//doc about generate and transform tx into json, protobuf bytes
//https://github.com/cosmos/cosmos-sdk/blob/master/docs/run-node/txs.md
// doc about generate and transform tx into json, protobuf bytes
// https://github.com/cosmos/cosmos-sdk/blob/master/docs/run-node/txs.md
txBytes, err := e.clientCtx.TxConfig.TxEncoder()(txBuilder.GetTx())
if err != nil {
return nil, err
@ -636,79 +649,125 @@ func (e *PublicEthAPI) GetBlockByNumber(ethBlockNum rpctypes.BlockNumber, fullTx
func (e *PublicEthAPI) GetTransactionByHash(hash common.Hash) (*rpctypes.RPCTransaction, error) {
e.logger.Debugln("eth_getTransactionByHash", "hash", hash.Hex())
resp, err := e.queryClient.TxReceipt(e.ctx, &evmtypes.QueryTxReceiptRequest{
Hash: hash.Hex(),
})
res, err := e.clientCtx.Client.Tx(e.ctx, hash.Bytes(), false)
if err != nil {
e.logger.Debugf("failed to get tx info for %s: %s", hash.Hex(), err.Error())
e.logger.WithError(err).Debugln("tx not found", "hash", hash.Hex())
return nil, nil
}
resBlock, err := e.clientCtx.Client.Block(e.ctx, &res.Height)
if err != nil {
e.logger.WithError(err).Debugln("block not found", "height", res.Height)
return nil, nil
}
tx, err := e.clientCtx.TxConfig.TxDecoder()(res.Tx)
if err != nil {
e.logger.WithError(err).Debugln("decoding failed")
return nil, fmt.Errorf("failed to decode tx: %w", err)
}
msg, ok := tx.(*evmtypes.MsgEthereumTx)
if !ok {
e.logger.Debugln("invalid tx")
return nil, fmt.Errorf("invalid tx type: %T", tx)
}
// TODO: use msg.AsTransaction.Hash() for txHash once hashing is fixed on Tendermint
// https://github.com/tendermint/tendermint/issues/6539
return rpctypes.NewTransactionFromData(
resp.Receipt.Data,
common.HexToAddress(resp.Receipt.From),
common.HexToHash(resp.Receipt.Hash),
common.HexToHash(resp.Receipt.BlockHash),
resp.Receipt.BlockHeight,
resp.Receipt.Index,
msg.Data,
common.HexToAddress(msg.From),
hash,
common.BytesToHash(resBlock.Block.Hash()),
uint64(res.Height),
uint64(res.Index),
)
}
// GetTransactionByBlockHashAndIndex returns the transaction identified by hash and index.
func (e *PublicEthAPI) GetTransactionByBlockHashAndIndex(hash common.Hash, idx hexutil.Uint) (*rpctypes.RPCTransaction, error) {
e.logger.Debugln("eth_getTransactionByHashAndIndex", "hash", hash.Hex(), "index", idx)
e.logger.Debugln("eth_getTransactionByBlockHashAndIndex", "hash", hash.Hex(), "index", idx)
header, err := e.backend.HeaderByHash(hash)
resBlock, err := e.clientCtx.Client.BlockByHash(e.ctx, hash.Bytes())
if err != nil {
return nil, errors.Wrapf(err, "failed retrieve block from hash")
e.logger.WithError(err).Debugln("block not found", "hash", hash.Hex())
return nil, nil
}
resp, err := e.queryClient.TxReceiptsByBlockHeight(rpctypes.ContextWithHeight(header.Number.Int64()), &evmtypes.QueryTxReceiptsByBlockHeightRequest{})
if err != nil {
return nil, errors.Wrap(err, "failed to query tx receipts by block height")
i := int(idx)
if i >= len(resBlock.Block.Txs) {
e.logger.Debugln("block txs index out of bound", "index", i)
return nil, nil
}
return e.getReceiptByIndex(resp.Receipts, hash, idx)
txBz := resBlock.Block.Txs[i]
tx, err := e.clientCtx.TxConfig.TxDecoder()(txBz)
if err != nil {
e.logger.WithError(err).Debugln("decoding failed")
return nil, fmt.Errorf("failed to decode tx: %w", err)
}
msg, ok := tx.(*evmtypes.MsgEthereumTx)
if !ok {
e.logger.Debugln("invalid tx")
return nil, fmt.Errorf("invalid tx type: %T", tx)
}
// TODO: use msg.AsTransaction.Hash() for txHash once hashing is fixed on Tendermint
// https://github.com/tendermint/tendermint/issues/6539
txHash := common.BytesToHash(txBz.Hash())
return rpctypes.NewTransactionFromData(
msg.Data,
common.HexToAddress(msg.From),
txHash,
hash,
uint64(resBlock.Block.Height),
uint64(idx),
)
}
// GetTransactionByBlockNumberAndIndex returns the transaction identified by number and index.
func (e *PublicEthAPI) GetTransactionByBlockNumberAndIndex(blockNum rpctypes.BlockNumber, idx hexutil.Uint) (*rpctypes.RPCTransaction, error) {
e.logger.Debugln("eth_getTransactionByBlockNumberAndIndex", "number", blockNum, "index", idx)
req := &evmtypes.QueryTxReceiptsByBlockHeightRequest{}
resp, err := e.queryClient.TxReceiptsByBlockHeight(rpctypes.ContextWithHeight(blockNum.Int64()), req)
resBlock, err := e.clientCtx.Client.Block(e.ctx, blockNum.TmHeight())
if err != nil {
err = errors.Wrap(err, "failed to query tx receipts by block height")
return nil, err
}
return e.getReceiptByIndex(resp.Receipts, common.Hash{}, idx)
}
func (e *PublicEthAPI) getReceiptByIndex(receipts []*evmtypes.TxReceipt, blockHash common.Hash, idx hexutil.Uint) (*rpctypes.RPCTransaction, error) {
// return if index out of bounds
if uint64(idx) >= uint64(len(receipts)) {
e.logger.WithError(err).Debugln("block not found", "height", blockNum.Int64())
return nil, nil
}
receipt := receipts[idx]
if (blockHash != common.Hash{}) {
hexBlockHash := blockHash.Hex()
if receipt.BlockHash != hexBlockHash {
return nil, errors.Errorf("receipt found but block hashes don't match %s != %s",
receipt.BlockHash,
hexBlockHash,
)
}
i := int(idx)
if i >= len(resBlock.Block.Txs) {
e.logger.Debugln("block txs index out of bound", "index", i)
return nil, nil
}
txBz := resBlock.Block.Txs[i]
tx, err := e.clientCtx.TxConfig.TxDecoder()(txBz)
if err != nil {
e.logger.WithError(err).Debugln("decoding failed")
return nil, fmt.Errorf("failed to decode tx: %w", err)
}
msg, ok := tx.(*evmtypes.MsgEthereumTx)
if !ok {
e.logger.Debugln("invalid tx")
return nil, fmt.Errorf("invalid tx type: %T", tx)
}
// TODO: use msg.AsTransaction.Hash() for txHash once hashing is fixed on Tendermint
// https://github.com/tendermint/tendermint/issues/6539
txHash := common.BytesToHash(txBz.Hash())
return rpctypes.NewTransactionFromData(
receipt.Data,
common.HexToAddress(receipt.From),
common.HexToHash(receipt.Hash),
blockHash,
receipt.BlockHeight,
msg.Data,
common.HexToAddress(msg.From),
txHash,
common.BytesToHash(resBlock.Block.Hash()),
uint64(resBlock.Block.Height),
uint64(idx),
)
}
@ -717,64 +776,97 @@ func (e *PublicEthAPI) getReceiptByIndex(receipts []*evmtypes.TxReceipt, blockHa
func (e *PublicEthAPI) GetTransactionReceipt(hash common.Hash) (map[string]interface{}, error) {
e.logger.Debugln("eth_getTransactionReceipt", "hash", hash.Hex())
ctx := rpctypes.ContextWithHeight(int64(0))
tx, err := e.queryClient.TxReceipt(ctx, &evmtypes.QueryTxReceiptRequest{
Hash: hash.Hex(),
})
res, err := e.clientCtx.Client.Tx(e.ctx, hash.Bytes(), false)
if err != nil {
e.logger.Debugf("failed to get tx receipt for %s: %s", hash.Hex(), err.Error())
e.logger.WithError(err).Debugln("tx not found", "hash", hash.Hex())
return nil, nil
}
// Query block for consensus hash
height := int64(tx.Receipt.BlockHeight)
block, err := e.clientCtx.Client.Block(e.ctx, &height)
resBlock, err := e.clientCtx.Client.Block(e.ctx, &res.Height)
if err != nil {
e.logger.Warningln("didnt find block for tx height", height)
return nil, err
e.logger.WithError(err).Debugln("block not found", "height", res.Height)
return nil, nil
}
cumulativeGasUsed := tx.Receipt.Result.GasUsed
if tx.Receipt.Index != 0 {
cumulativeGasUsed += rpctypes.GetBlockCumulativeGas(e.clientCtx, block.Block, int(tx.Receipt.Index))
tx, err := e.clientCtx.TxConfig.TxDecoder()(res.Tx)
if err != nil {
e.logger.WithError(err).Debugln("decoding failed")
return nil, fmt.Errorf("failed to decode tx: %w", err)
}
msg, ok := tx.(*evmtypes.MsgEthereumTx)
if !ok {
e.logger.Debugln("invalid tx")
return nil, fmt.Errorf("invalid tx type: %T", tx)
}
cumulativeGasUsed := uint64(0)
blockRes, err := e.clientCtx.Client.BlockResults(e.ctx, &res.Height)
if err != nil {
e.logger.WithError(err).Debugln("failed to retrieve block results", "height", res.Height)
return nil, nil
}
for i := 0; i <= int(res.Index) && i < len(blockRes.TxsResults); i++ {
cumulativeGasUsed += uint64(blockRes.TxsResults[i].GasUsed)
}
var status hexutil.Uint
if tx.Receipt.Result.Reverted {
status = hexutil.Uint(0)
// NOTE: Response{Deliver/Check}Tx Code from Tendermint and the Ethereum receipt status are switched:
// | | Tendermint | Ethereum |
// | ------- | ---------- | -------- |
// | Success | 0 | 1 |
// | Fail | 1 | 0 |
if res.TxResult.Code == 0 {
status = hexutil.Uint(ethtypes.ReceiptStatusSuccessful)
} else {
status = hexutil.Uint(1)
status = hexutil.Uint(ethtypes.ReceiptStatusFailed)
}
toHex := common.Address{}
if len(tx.Receipt.Data.To) > 0 {
toHex = common.HexToAddress(tx.Receipt.Data.To)
from := common.HexToAddress(msg.From)
resLogs, err := e.queryClient.TxLogs(e.ctx, &evmtypes.QueryTxLogsRequest{Hash: hash.Hex()})
if err != nil {
e.logger.WithError(err).Debugln("logs not found", "hash", hash.Hex())
resLogs = &evmtypes.QueryTxLogsResponse{Logs: []*evmtypes.Log{}}
}
contractAddress := common.HexToAddress(tx.Receipt.Result.ContractAddress)
logsBloom := hexutil.Encode(ethtypes.BytesToBloom(tx.Receipt.Result.Bloom).Bytes())
logs := evmtypes.LogsToEthereum(resLogs.Logs)
receipt := map[string]interface{}{
// Consensus fields: These fields are defined by the Yellow Paper
"status": status,
"cumulativeGasUsed": hexutil.Uint64(cumulativeGasUsed),
"logsBloom": logsBloom,
"logs": tx.Receipt.Result.TxLogs.EthLogs(),
"logsBloom": ethtypes.BytesToBloom(ethtypes.LogsBloom(logs)),
"logs": logs,
// Implementation fields: These fields are added by geth when processing a transaction.
// They are stored in the chain database.
"transactionHash": hash.Hex(),
"contractAddress": contractAddress.Hex(),
"gasUsed": hexutil.Uint64(tx.Receipt.Result.GasUsed),
"transactionHash": hash,
"contractAddress": nil,
"gasUsed": hexutil.Uint64(res.TxResult.GasUsed),
"type": hexutil.Uint(ethtypes.AccessListTxType), // TODO: support legacy type
// Inclusion information: These fields provide information about the inclusion of the
// transaction corresponding to this receipt.
"blockHash": common.BytesToHash(block.Block.Header.Hash()).Hex(),
"blockNumber": hexutil.Uint64(tx.Receipt.BlockHeight),
"transactionIndex": hexutil.Uint64(tx.Receipt.Index),
"blockHash": common.BytesToHash(resBlock.Block.Header.Hash()).Hex(),
"blockNumber": hexutil.Uint64(res.Height),
"transactionIndex": hexutil.Uint64(res.Index),
// sender and receiver (contract or EOA) addreses
"from": common.HexToAddress(tx.Receipt.From),
"to": toHex,
"from": from,
"to": msg.To(),
}
if logs == nil {
receipt["logs"] = [][]*ethtypes.Log{}
}
// If the ContractAddress is 20 0x0 bytes, assume it is not a contract creation
if msg.To() == nil {
receipt["contractAddress"] = crypto.CreateAddress(from, msg.Data.Nonce)
}
return receipt, nil

View File

@ -371,7 +371,7 @@ func (api *PublicFilterAPI) Logs(ctx context.Context, crit filters.FilterCriteri
return
}
logs := filterLogs(txResponse.TxLogs.EthLogs(), crit.FromBlock, crit.ToBlock, crit.Addresses, crit.Topics)
logs := filterLogs(evmtypes.LogsToEthereum(txResponse.Logs), crit.FromBlock, crit.ToBlock, crit.Addresses, crit.Topics)
for _, log := range logs {
err = notifier.Notify(rpcSub.ID, log)
@ -448,7 +448,7 @@ func (api *PublicFilterAPI) NewFilter(criteria filters.FilterCriteria) (rpc.ID,
return
}
logs := filterLogs(txResponse.TxLogs.EthLogs(), criteria.FromBlock, criteria.ToBlock, criteria.Addresses, criteria.Topics)
logs := filterLogs(evmtypes.LogsToEthereum(txResponse.Logs), criteria.FromBlock, criteria.ToBlock, criteria.Addresses, criteria.Topics)
api.filtersMu.Lock()
if f, found := api.filters[filterID]; found {

View File

@ -25,8 +25,8 @@ import (
)
// RawTxToEthTx returns a evm MsgEthereum transaction from raw tx bytes.
func RawTxToEthTx(clientCtx client.Context, bz []byte) (*evmtypes.MsgEthereumTx, error) {
tx, err := clientCtx.TxConfig.TxDecoder()(bz)
func RawTxToEthTx(clientCtx client.Context, txBz tmtypes.Tx) (*evmtypes.MsgEthereumTx, error) {
tx, err := clientCtx.TxConfig.TxDecoder()(txBz)
if err != nil {
return nil, sdkerrors.Wrap(sdkerrors.ErrJSONUnmarshal, err.Error())
}
@ -246,28 +246,23 @@ func BuildEthereumTx(clientCtx client.Context, msg *evmtypes.MsgEthereumTx, accN
return txBytes, nil
}
// GetBlockCumulativeGas returns the cumulative gas used on a block up to a given
// transaction index. The returned gas used includes the gas from both the SDK and
// EVM module transactions.
func GetBlockCumulativeGas(clientCtx client.Context, block *tmtypes.Block, idx int) uint64 {
func DecodeTx(clientCtx client.Context, txBz tmtypes.Tx) (sdk.Tx, uint64) {
var gasUsed uint64
txDecoder := clientCtx.TxConfig.TxDecoder()
for i := 0; i < idx && i < len(block.Txs); i++ {
txi, err := txDecoder(block.Txs[i])
if err != nil {
continue
}
switch tx := txi.(type) {
case *evmtypes.MsgEthereumTx:
gasUsed += tx.GetGas()
case sdk.FeeTx:
// TODO: add internal txns
gasUsed += tx.GetGas()
}
tx, err := txDecoder(txBz)
if err != nil {
return nil, 0
}
return gasUsed
switch tx := tx.(type) {
case *evmtypes.MsgEthereumTx:
gasUsed = tx.GetGas() // NOTE: this doesn't include the gas refunded
case sdk.FeeTx:
gasUsed = tx.GetGas()
}
return tx, gasUsed
}
type DataError interface {

View File

@ -604,7 +604,7 @@ func (api *pubSubAPI) subscribeLogs(wsConn *wsConn, extra interface{}) (rpc.ID,
return
}
logs := filterLogs(txResponse.TxLogs.EthLogs(), crit.FromBlock, crit.ToBlock, crit.Addresses, crit.Topics)
logs := filterLogs(evmtypes.LogsToEthereum(txResponse.Logs), crit.FromBlock, crit.ToBlock, crit.Addresses, crit.Topics)
if len(logs) == 0 {
continue
}

2
go.mod
View File

@ -46,7 +46,7 @@ require (
github.com/xlab/closer v0.0.0-20190328110542-03326addb7c2
github.com/xlab/suplog v1.3.0
golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a
google.golang.org/genproto v0.0.0-20210524171403-669157292da3
google.golang.org/genproto v0.0.0-20210607140030-00d4fb20b1ae
google.golang.org/grpc v1.38.0
gopkg.in/yaml.v2 v2.4.0
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect

16
go.sum
View File

@ -876,6 +876,7 @@ github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:
github.com/xtaci/kcp-go v5.4.5+incompatible/go.mod h1:bN6vIwHQbfHaHtFpEssmWsN45a+AZwO7eyRCmEIbtvE=
github.com/xtaci/lossyconn v0.0.0-20190602105132-8df528c0c9ae/go.mod h1:gXtu8J62kEgmN++bm9BVICuT/e8yiLI2KFobd/TRFsE=
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
github.com/zondax/hid v0.9.0 h1:eiT3P6vNxAEVxXMw66eZUAAnU2zD33JBkfG/EnfAKl8=
github.com/zondax/hid v0.9.0/go.mod h1:l5wttcP0jwtdLjqjMMWFVEE7d1zO0jvSPA9OPZxWpEM=
go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
@ -945,7 +946,7 @@ golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHl
golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs=
golang.org/x/lint v0.0.0-20201208152925-83fdc39ff7b5/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
golang.org/x/lint v0.0.0-20210508222113-6edffad5e616/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE=
golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o=
golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc=
@ -991,8 +992,8 @@ golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwY
golang.org/x/net v0.0.0-20201202161906-c7110b5ffcbb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.0.0-20210220033124-5f55cee0dc0d/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4 h1:b0LrWgu8+q7z4J+0Y3Umo5q1dL7NXBkKBWkaVkAq17E=
golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc=
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4 h1:4nGaVu0QrbjT/AK2PRLuQfQuh6DJve+pELhqTdAj3x0=
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
@ -1062,9 +1063,8 @@ golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210309074719-68d13333faf2/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210315160823-c6e025ad8005/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210316164454-77fc1eacc6aa/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210420205809-ac73e9fd8988/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210510120138-977fb7262007 h1:gG67DSER+11cZvqIMb8S8bt0vZtiN6xWYARwirrOSfE=
golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
@ -1119,6 +1119,7 @@ golang.org/x/tools v0.0.0-20200110213125-a7a6caa82ab2/go.mod h1:TB2adYChydJhpapK
golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0=
golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
@ -1168,8 +1169,8 @@ google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6D
google.golang.org/genproto v0.0.0-20201111145450-ac7456db90a6/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20201119123407-9b1e624d6bc4/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20210114201628-6edceaf6022f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20210524171403-669157292da3 h1:xFyh6GBb+NO1L0xqb978I3sBPQpk6FrKO0jJGRvdj/0=
google.golang.org/genproto v0.0.0-20210524171403-669157292da3/go.mod h1:P3QM42oQyzQSnHPnZ/vqoCdDmzH28fzWByN9asMeM8A=
google.golang.org/genproto v0.0.0-20210607140030-00d4fb20b1ae h1:2dB4bZ/B7RJdKuvHk3mKTzL2xwrikb+Y/QQy7WdyBPk=
google.golang.org/genproto v0.0.0-20210607140030-00d4fb20b1ae/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0=
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.1/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
@ -1191,7 +1192,6 @@ google.golang.org/grpc v1.32.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM
google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0=
google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc=
google.golang.org/grpc v1.35.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU=
google.golang.org/grpc v1.36.1/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU=
google.golang.org/grpc v1.37.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM=
google.golang.org/grpc v1.38.0 h1:/9BgsAsa5nWe26HqOlvlgJnqBuktYOLCgjCPqsa56W0=
google.golang.org/grpc v1.38.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM=

View File

@ -102,12 +102,12 @@ message ChainConfig {
(gogoproto.moretags) = "yaml:\"muir_glacier_block\"",
(gogoproto.nullable) = false
];
// Berlin switch block (< 0 = no fork, 0 = already on berlin)
string berlin_block = 13 [
(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Int",
(gogoproto.moretags) = "yaml:\"berlin_block\"",
(gogoproto.nullable) = false
];
// Berlin switch block (< 0 = no fork, 0 = already on berlin)
string berlin_block = 13 [
(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Int",
(gogoproto.moretags) = "yaml:\"berlin_block\"",
(gogoproto.nullable) = false
];
// YOLO v3: Gas repricings
string yolo_v3_block = 14 [
(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Int",
@ -180,13 +180,13 @@ message Log {
message TxReceipt {
option (gogoproto.goproto_getters) = false;
string hash = 1;
string from = 2;
TxData data = 3;
TxResult result = 4;
uint64 index = 5;
string hash = 1;
string from = 2;
TxData data = 3;
TxResult result = 4;
uint64 index = 5;
uint64 block_height = 6;
string block_hash = 7;
string block_hash = 7;
}
// TxResult stores results of Tx execution.
@ -216,10 +216,7 @@ message TxData {
option (gogoproto.goproto_getters) = false;
// destination EVM chain ID
bytes chain_id = 1 [
(gogoproto.customname) = "ChainID",
(gogoproto.jsontag) = "chainID"
];
bytes chain_id = 1 [(gogoproto.customname) = "ChainID", (gogoproto.jsontag) = "chainID"];
// nonce corresponds to the account nonce (transaction sequence).
uint64 nonce = 2;
// price defines the unsigned integer value of the gas price in bytes.
@ -227,16 +224,13 @@ message TxData {
// gas defines the gas limit defined for the transaction.
uint64 gas = 4 [(gogoproto.customname) = "GasLimit"];
// hex formatted address of the recipient
string to = 5;
string to = 5;
// value defines the unsigned integer value of the transaction amount.
bytes value = 6 [(gogoproto.customname) = "Amount"];
// 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
];
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
@ -256,7 +250,7 @@ message AccessTuple {
option (gogoproto.goproto_getters) = false;
// hex formatted ethereum address
string address = 1;
string address = 1;
// hex formatted hashes of the storage keys
repeated string storage_keys = 2 [(gogoproto.jsontag) = "storageKeys"];
repeated string storage_keys = 2 [(gogoproto.jsontag) = "storageKeys"];
}

View File

@ -41,16 +41,6 @@ service Query {
option (google.api.http).get = "/ethermint/evm/v1alpha1/tx_logs/{hash}";
}
// TxReceipt queries a receipt by a transaction hash.
rpc TxReceipt(QueryTxReceiptRequest) returns (QueryTxReceiptResponse) {
option (google.api.http).get = "/ethermint/evm/v1alpha1/tx_receipt/{hash}";
}
// TxReceiptsByBlockHeight queries tx receipts by a block height.
rpc TxReceiptsByBlockHeight(QueryTxReceiptsByBlockHeightRequest) returns (QueryTxReceiptsByBlockHeightResponse) {
option (google.api.http).get = "/ethermint/evm/v1alpha1/tx_receipts_block";
}
// BlockLogs queries all the ethereum logs for a given block hash.
rpc BlockLogs(QueryBlockLogsRequest) returns (QueryBlockLogsResponse) {
option (google.api.http).get = "/ethermint/evm/v1alpha1/block_logs/{hash}";
@ -175,31 +165,6 @@ message QueryTxLogsResponse {
repeated Log logs = 1;
}
// QueryTxReceiptRequest is the request type for the Query/TxReceipt RPC method.
message QueryTxReceiptRequest {
option (gogoproto.equal) = false;
option (gogoproto.goproto_getters) = false;
// hash is the ethereum transaction hex hash to query the receipt for.
string hash = 1;
}
// QueryTxReceiptResponse is the response type for the Query/TxReceipt RPC method.
message QueryTxReceiptResponse {
// receipt represents the ethereum receipt for the given transaction.
TxReceipt receipt = 1;
}
// QueryTxReceiptsByBlockHeightRequest is the request type for the Query/TxReceiptsByBlockHeight RPC method.
message QueryTxReceiptsByBlockHeightRequest {
}
// QueryTxReceiptsByBlockHeightResponse is the response type for the Query/TxReceiptsByBlockHeight RPC method.
message QueryTxReceiptsByBlockHeightResponse {
// tx receipts list for the block
repeated TxReceipt receipts = 1;
}
// QueryBlockLogsRequest is the request type for the Query/BlockLogs RPC method.
message QueryBlockLogsRequest {
option (gogoproto.equal) = false;
@ -221,7 +186,7 @@ message QueryBlockLogsResponse {
// QueryBlockBloomRequest is the request type for the Query/BlockBloom RPC
// method.
message QueryBlockBloomRequest { }
message QueryBlockBloomRequest {}
// QueryBlockBloomResponse is the response type for the Query/BlockBloom RPC
// method.

View File

@ -42,34 +42,14 @@ message ExtensionOptionsWeb3Tx {
message MsgEthereumTxResponse {
option (gogoproto.goproto_getters) = false;
// contract_address contains the ethereum address of the created contract (if
// any). If the state transition is an evm.Call, the contract address will be
// empty.
string contract_address = 1 [(gogoproto.moretags) = "yaml:\"contract_address\""];
// bloom represents the bloom filter bytes
bytes bloom = 2;
// tx_logs contains the transaction hash and the proto-compatible ethereum
// ethereum transaction hash in hex format. This hash differs from the Tendermint sha256 hash of the transaction
// bytes. See https://github.com/tendermint/tendermint/issues/6539 for reference
string hash = 1;
// logs contains the transaction hash and the proto-compatible ethereum
// logs.
TransactionLogs tx_logs = 3 [(gogoproto.moretags) = "yaml:\"tx_logs\"", (gogoproto.nullable) = false];
// ret defines the bytes from the execution.
bytes ret = 4;
repeated Log logs = 2;
// returned data from evm function (result or data supplied with revert opcode)
bytes ret = 3;
// reverted flag is set to true when the call has been reverted
bool reverted = 5;
}
// // SigCache is used to cache the derived sender and contains the signer used
// // to derive it.
// message SigCache {
// option (gogoproto.goproto_getters) = false;
// EIP155Signer signer = 1;
// bytes address = 2;
// }
// // EIP155Transaction implements Signer using the EIP155 rules.
// message EIP155Signer {
// option (gogoproto.goproto_getters) = false;
// bytes chain_id = 1 [(gogoproto.customname) = "chainId"];
// bytes chain_id_mul = 2 [(gogoproto.customname) = "chainIdMul"];
// }
bool reverted = 4;
}

View File

@ -1,14 +1,12 @@
package evm
import (
"fmt"
"runtime/debug"
log "github.com/xlab/suplog"
sdk "github.com/cosmos/cosmos-sdk/types"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
ethcmn "github.com/ethereum/go-ethereum/common"
"github.com/cosmos/ethermint/x/evm/keeper"
"github.com/cosmos/ethermint/x/evm/types"
@ -25,42 +23,7 @@ func NewHandler(k *keeper.Keeper) sdk.Handler {
case *types.MsgEthereumTx:
// execute state transition
res, err := k.EthereumTx(sdk.WrapSDKContext(ctx), msg)
if err != nil {
return sdk.WrapServiceResult(ctx, res, err)
} else if result, err = sdk.WrapServiceResult(ctx, res, nil); err != nil {
return nil, err
}
// log state transition result
var recipientLog string
if res.ContractAddress != "" {
recipientLog = fmt.Sprintf("contract address %s", res.ContractAddress)
} else {
var recipient string
if to := msg.To(); to != nil {
recipient = to.Hex()
}
recipientLog = fmt.Sprintf("recipient address %s", recipient)
}
sender := ethcmn.BytesToAddress(msg.GetFrom().Bytes())
if res.Reverted {
result.Log = "transaction reverted"
log := fmt.Sprintf(
"reverted EVM state transition; sender address %s; %s", sender.Hex(), recipientLog,
)
k.Logger(ctx).Info(log)
} else {
log := fmt.Sprintf(
"executed EVM state transition; sender address %s; %s", sender.Hex(), recipientLog,
)
result.Log = log
k.Logger(ctx).Info(log)
}
return result, nil
return sdk.WrapServiceResult(ctx, res, err)
default:
err := sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "unrecognized %s message type: %T", types.ModuleName, msg)

View File

@ -14,6 +14,7 @@ import (
"github.com/ethereum/go-ethereum/common"
ethcmn "github.com/ethereum/go-ethereum/common"
ethtypes "github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/crypto"
"github.com/cosmos/cosmos-sdk/codec"
"github.com/cosmos/cosmos-sdk/crypto/keyring"
@ -98,7 +99,7 @@ func (suite *EvmTestSuite) TestHandleMsgEthereumTx() {
"insufficient balance",
func() {
tx = types.NewMsgEthereumTxContract(suite.chainID, 0, big.NewInt(100), 0, big.NewInt(10000), nil, nil)
tx.From = suite.from.Hex()
// sign transaction
err := tx.Sign(suite.ethSigner, suite.signer)
suite.Require().NoError(err)
@ -184,48 +185,17 @@ func (suite *EvmTestSuite) TestHandlerLogs() {
txResponse, err := types.DecodeTxResponse(result.Data)
suite.Require().NoError(err, "failed to decode result data")
suite.Require().Equal(len(txResponse.TxLogs.Logs), 1)
suite.Require().Equal(len(txResponse.TxLogs.Logs[0].Topics), 2)
suite.Require().Equal(len(txResponse.Logs), 1)
suite.Require().Equal(len(txResponse.Logs[0].Topics), 2)
hash := []byte{1}
err = suite.app.EvmKeeper.CommitStateDB.SetLogs(ethcmn.BytesToHash(hash), txResponse.TxLogs.EthLogs())
err = suite.app.EvmKeeper.CommitStateDB.SetLogs(ethcmn.BytesToHash(hash), types.LogsToEthereum(txResponse.Logs))
suite.Require().NoError(err)
logs, err := suite.app.EvmKeeper.CommitStateDB.GetLogs(ethcmn.BytesToHash(hash))
suite.Require().NoError(err, "failed to get logs")
suite.Require().Equal(logs, txResponse.TxLogs.Logs)
}
func (suite *EvmTestSuite) TestQueryTxLogs() {
gasLimit := uint64(100000)
gasPrice := big.NewInt(1000000)
// send contract deployment transaction with an event in the constructor
bytecode := common.FromHex("0x6080604052348015600f57600080fd5b5060117f775a94827b8fd9b519d36cd827093c664f93347070a554f65e4a6f56cd73889860405160405180910390a2603580604b6000396000f3fe6080604052600080fdfea165627a7a723058206cab665f0f557620554bb45adf266708d2bd349b8a4314bdff205ee8440e3c240029")
tx := types.NewMsgEthereumTx(suite.chainID, 1, nil, big.NewInt(0), gasLimit, gasPrice, bytecode, nil)
tx.From = suite.from.String()
err := tx.Sign(suite.ethSigner, suite.signer)
suite.Require().NoError(err)
result, err := suite.handler(suite.ctx, tx)
suite.Require().NoError(err)
suite.Require().NotNil(result)
txResponse, err := types.DecodeTxResponse(result.Data)
suite.Require().NoError(err, "failed to decode result data")
suite.Require().Equal(len(txResponse.TxLogs.Logs), 1)
suite.Require().Equal(len(txResponse.TxLogs.Logs[0].Topics), 2)
// get logs by tx hash
hash := txResponse.TxLogs.Hash
logs, err := suite.app.EvmKeeper.CommitStateDB.GetLogs(ethcmn.HexToHash(hash))
suite.Require().NoError(err, "failed to get logs")
suite.Require().Equal(logs, txResponse.TxLogs.EthLogs())
suite.Require().Equal(logs, txResponse.Logs)
}
func (suite *EvmTestSuite) TestDeployAndCallContract() {
@ -303,7 +273,7 @@ func (suite *EvmTestSuite) TestDeployAndCallContract() {
// store - changeOwner
gasLimit = uint64(100000000000)
gasPrice = big.NewInt(100)
receiver := common.HexToAddress(txResponse.ContractAddress)
receiver := crypto.CreateAddress(suite.from, 1)
storeAddr := "0xa6f9dae10000000000000000000000006a82e4a67715c8412a9114fbd2cbaefbc8181424"
bytecode = common.FromHex(storeAddr)

View File

@ -203,44 +203,6 @@ func (k Keeper) TxLogs(c context.Context, req *types.QueryTxLogsRequest) (*types
}, nil
}
// TxReceipt implements the Query/TxReceipt gRPC method
func (k Keeper) TxReceipt(c context.Context, req *types.QueryTxReceiptRequest) (*types.QueryTxReceiptResponse, error) {
if req == nil {
return nil, status.Error(codes.InvalidArgument, "empty request")
}
if ethermint.IsEmptyHash(req.Hash) {
return nil, status.Error(
codes.InvalidArgument,
types.ErrEmptyHash.Error(),
)
}
ctx := sdk.UnwrapSDKContext(c)
hash := ethcmn.HexToHash(req.Hash)
receipt, found := k.GetTxReceiptFromHash(ctx, hash)
if !found {
return nil, status.Errorf(
codes.NotFound, "%s: %s", types.ErrTxReceiptNotFound.Error(), req.Hash,
)
}
return &types.QueryTxReceiptResponse{
Receipt: receipt,
}, nil
}
// TxReceiptsByBlockHeight implements the Query/TxReceiptsByBlockHeight gRPC method
func (k Keeper) TxReceiptsByBlockHeight(c context.Context, _ *types.QueryTxReceiptsByBlockHeightRequest) (*types.QueryTxReceiptsByBlockHeightResponse, error) {
ctx := sdk.UnwrapSDKContext(c)
receipts := k.GetTxReceiptsByBlockHeight(ctx, uint64(ctx.BlockHeight()))
return &types.QueryTxReceiptsByBlockHeightResponse{
Receipts: receipts,
}, nil
}
// BlockLogs implements the Query/BlockLogs gRPC method
func (k Keeper) BlockLogs(c context.Context, req *types.QueryBlockLogsRequest) (*types.QueryBlockLogsResponse, error) {
if req == nil {

View File

@ -517,136 +517,6 @@ func (suite *KeeperTestSuite) TestQueryBlockLogs() {
}
}
func (suite *KeeperTestSuite) TestQueryTxReceipt() {
var (
req *types.QueryTxReceiptRequest
expRes *types.QueryTxReceiptResponse
)
testCases := []struct {
msg string
malleate func()
expPass bool
}{
{"empty hash",
func() {
req = &types.QueryTxReceiptRequest{}
},
false,
},
{"tx receipt not found for hash",
func() {
hash := ethcmn.BytesToHash([]byte("thash"))
req = &types.QueryTxReceiptRequest{
Hash: hash.Hex(),
}
},
false,
},
{"success",
func() {
hash := ethcmn.BytesToHash([]byte("thash"))
receipt := &types.TxReceipt{
Hash: hash.Hex(),
From: suite.address.Hex(),
BlockHeight: uint64(suite.ctx.BlockHeight()),
BlockHash: ethcmn.BytesToHash(suite.ctx.BlockHeader().DataHash).Hex(),
}
suite.app.EvmKeeper.SetTxReceiptToHash(suite.ctx, hash, receipt)
req = &types.QueryTxReceiptRequest{
Hash: hash.Hex(),
}
expRes = &types.QueryTxReceiptResponse{
Receipt: receipt,
}
},
true,
},
}
for _, tc := range testCases {
suite.Run(fmt.Sprintf("Case %s", tc.msg), func() {
suite.SetupTest() // reset
tc.malleate()
ctx := sdk.WrapSDKContext(suite.ctx)
res, err := suite.queryClient.TxReceipt(ctx, req)
if tc.expPass {
suite.Require().NoError(err)
suite.Require().NotNil(res)
suite.Require().Equal(expRes, res)
} else {
suite.Require().Error(err)
}
})
}
}
func (suite *KeeperTestSuite) TestQueryTxReceiptByBlockHeight() {
var (
req = &types.QueryTxReceiptsByBlockHeightRequest{}
expRes *types.QueryTxReceiptsByBlockHeightResponse
)
testCases := []struct {
msg string
malleate func()
expPass bool
}{
{"empty response",
func() {
expRes = &types.QueryTxReceiptsByBlockHeightResponse{
Receipts: nil,
}
},
true,
},
{"success",
func() {
hash := ethcmn.BytesToHash([]byte("thash"))
receipt := &types.TxReceipt{
Hash: hash.Hex(),
From: suite.address.Hex(),
BlockHeight: uint64(suite.ctx.BlockHeight()),
BlockHash: ethcmn.BytesToHash(suite.ctx.BlockHeader().DataHash).Hex(),
}
suite.app.EvmKeeper.AddTxHashToBlock(suite.ctx, suite.ctx.BlockHeight(), hash)
suite.app.EvmKeeper.SetTxReceiptToHash(suite.ctx, hash, receipt)
expRes = &types.QueryTxReceiptsByBlockHeightResponse{
Receipts: []*types.TxReceipt{receipt},
}
},
true,
},
}
for _, tc := range testCases {
suite.Run(fmt.Sprintf("Case %s", tc.msg), func() {
suite.SetupTest() // reset
tc.malleate()
ctx := sdk.WrapSDKContext(suite.ctx)
ctx = metadata.AppendToOutgoingContext(ctx, grpctypes.GRPCBlockHeightHeader, fmt.Sprintf("%d", suite.ctx.BlockHeight()))
res, err := suite.queryClient.TxReceiptsByBlockHeight(ctx, req)
if tc.expPass {
suite.Require().NoError(err)
suite.Require().NotNil(res)
suite.Require().Equal(expRes, res)
} else {
suite.Require().Error(err)
}
})
}
}
func (suite *KeeperTestSuite) TestQueryBlockBloom() {
var (
req *types.QueryBlockBloomRequest

View File

@ -144,20 +144,6 @@ func (k Keeper) SetBlockBloomTransient(bloom *big.Int) {
store.Set(types.KeyPrefixTransientBloom, bloom.Bytes())
}
// ----------------------------------------------------------------------------
// Block
// ----------------------------------------------------------------------------
// SetTxReceiptToHash sets the mapping from tx hash to tx receipt
func (k Keeper) SetTxReceiptToHash(ctx sdk.Context, hash common.Hash, receipt *types.TxReceipt) {
ctx = ctx.WithGasMeter(sdk.NewInfiniteGasMeter())
data := k.cdc.MustMarshalBinaryBare(receipt)
store := ctx.KVStore(k.storeKey)
store.Set(types.KeyHashTxReceipt(hash), data)
}
// ----------------------------------------------------------------------------
// Tx
// ----------------------------------------------------------------------------
@ -187,85 +173,6 @@ func (k Keeper) ResetRefundTransient(ctx sdk.Context) {
store.Delete(types.KeyPrefixTransientRefund)
}
// GetTxReceiptFromHash gets tx receipt by tx hash.
func (k Keeper) GetTxReceiptFromHash(ctx sdk.Context, hash common.Hash) (*types.TxReceipt, bool) {
store := ctx.KVStore(k.storeKey)
data := store.Get(types.KeyHashTxReceipt(hash))
if len(data) == 0 {
return nil, false
}
var receipt types.TxReceipt
k.cdc.MustUnmarshalBinaryBare(data, &receipt)
return &receipt, true
}
// AddTxHashToBlock stores tx hash in the list of tx for the block.
func (k Keeper) AddTxHashToBlock(ctx sdk.Context, blockHeight int64, txHash common.Hash) {
key := types.KeyBlockHeightTxs(uint64(blockHeight))
list := types.BytesList{}
store := ctx.KVStore(k.storeKey)
data := store.Get(key)
if len(data) > 0 {
k.cdc.MustUnmarshalBinaryBare(data, &list)
}
list.Bytes = append(list.Bytes, txHash.Bytes())
data = k.cdc.MustMarshalBinaryBare(&list)
store.Set(key, data)
}
// GetTxsFromBlock returns list of tx hash in the block by height.
func (k Keeper) GetTxsFromBlock(ctx sdk.Context, blockHeight uint64) []common.Hash {
key := types.KeyBlockHeightTxs(blockHeight)
store := ctx.KVStore(k.storeKey)
data := store.Get(key)
if len(data) > 0 {
list := types.BytesList{}
k.cdc.MustUnmarshalBinaryBare(data, &list)
txs := make([]common.Hash, 0, len(list.Bytes))
for _, b := range list.Bytes {
txs = append(txs, common.BytesToHash(b))
}
return txs
}
return nil
}
// GetTxReceiptsByBlockHeight gets tx receipts by block height.
func (k Keeper) GetTxReceiptsByBlockHeight(ctx sdk.Context, blockHeight uint64) []*types.TxReceipt {
txs := k.GetTxsFromBlock(ctx, blockHeight)
if len(txs) == 0 {
return nil
}
store := ctx.KVStore(k.storeKey)
receipts := make([]*types.TxReceipt, 0, len(txs))
for idx, txHash := range txs {
data := store.Get(types.KeyHashTxReceipt(txHash))
if len(data) == 0 {
continue
}
var receipt types.TxReceipt
k.cdc.MustUnmarshalBinaryBare(data, &receipt)
receipt.Index = uint64(idx)
receipts = append(receipts, &receipt)
}
return receipts
}
// ----------------------------------------------------------------------------
// Log
// ----------------------------------------------------------------------------

View File

@ -8,6 +8,7 @@ import (
"github.com/armon/go-metrics"
ethcmn "github.com/ethereum/go-ethereum/common"
ethtypes "github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/core/vm"
tmtypes "github.com/tendermint/tendermint/types"
@ -55,6 +56,9 @@ func (k *Keeper) EthereumTx(goCtx context.Context, msg *types.MsgEthereumTx) (*t
txHash := tmtypes.Tx(ctx.TxBytes()).Hash()
ethHash := ethcmn.BytesToHash(txHash)
// Ethereum formatted tx hash
etherumTxHash := msg.AsTransaction().Hash()
st := &types.StateTransition{
Message: ethMsg,
Csdb: k.CommitStateDB.WithContext(ctx),
@ -77,25 +81,6 @@ func (k *Keeper) EthereumTx(goCtx context.Context, msg *types.MsgEthereumTx) (*t
if errors.Is(err, vm.ErrExecutionReverted) && executionResult != nil {
// keep the execution result for revert reason
executionResult.Response.Reverted = true
if !st.Simulate {
k.SetTxReceiptToHash(ctx, ethHash, &types.TxReceipt{
Hash: ethHash.Hex(),
From: sender.Hex(),
Data: msg.Data,
BlockHeight: uint64(ctx.BlockHeight()),
BlockHash: k.headerHash.Hex(),
Result: &types.TxResult{
ContractAddress: executionResult.Response.ContractAddress,
Bloom: executionResult.Response.Bloom,
TxLogs: executionResult.Response.TxLogs,
Ret: executionResult.Response.Ret,
Reverted: executionResult.Response.Reverted,
GasUsed: executionResult.GasInfo.GasConsumed,
},
})
}
return executionResult.Response, nil
}
@ -108,33 +93,9 @@ func (k *Keeper) EthereumTx(goCtx context.Context, msg *types.MsgEthereumTx) (*t
bloom = big.NewInt(0)
}
// update block bloom filter
bloom = bloom.Or(bloom, executionResult.Bloom)
logsBloom := ethtypes.LogsBloom(executionResult.Logs)
bloom = bloom.Or(bloom, new(big.Int).SetBytes(logsBloom))
k.SetBlockBloomTransient(bloom)
// update transaction logs in KVStore
err = k.CommitStateDB.SetLogs(ethHash, executionResult.Logs)
if err != nil {
panic(err)
}
k.SetTxReceiptToHash(ctx, ethHash, &types.TxReceipt{
Hash: ethHash.Hex(),
From: sender.Hex(),
Data: msg.Data,
Index: uint64(st.Csdb.TxIndex()),
BlockHeight: uint64(ctx.BlockHeight()),
BlockHash: k.headerHash.Hex(),
Result: &types.TxResult{
ContractAddress: executionResult.Response.ContractAddress,
Bloom: executionResult.Response.Bloom,
TxLogs: executionResult.Response.TxLogs,
Ret: executionResult.Response.Ret,
Reverted: executionResult.Response.Reverted,
GasUsed: executionResult.GasInfo.GasConsumed,
},
})
k.AddTxHashToBlock(ctx, ctx.BlockHeight(), ethHash)
}
defer func() {
@ -155,6 +116,7 @@ func (k *Keeper) EthereumTx(goCtx context.Context, msg *types.MsgEthereumTx) (*t
attrs := []sdk.Attribute{
sdk.NewAttribute(sdk.AttributeKeyAmount, st.Message.Value().String()),
sdk.NewAttribute(types.AttributeKeyTxHash, ethcmn.BytesToHash(txHash).Hex()),
sdk.NewAttribute(types.AttributeKeyEthereumTxHash, etherumTxHash.Hex()),
}
if len(msg.Data.To) > 0 {
@ -174,5 +136,6 @@ func (k *Keeper) EthereumTx(goCtx context.Context, msg *types.MsgEthereumTx) (*t
),
})
executionResult.Response.Hash = etherumTxHash.Hex()
return executionResult.Response, nil
}

View File

@ -145,10 +145,8 @@ func (k *Keeper) TransitionDb(msg core.Message) (*types.ExecutionResult, error)
func (k *Keeper) ApplyMessage(evm *vm.EVM, msg core.Message) (*types.ExecutionResult, error) {
var (
ret []byte // return bytes from evm execution
contract common.Address
contractAddr string
vmErr, err error // vm errors do not effect consensus and are therefore not assigned to err
ret []byte // return bytes from evm execution
vmErr, err error // vm errors do not effect consensus and are therefore not assigned to err
)
sender := vm.AccountRef(msg.From())
@ -174,8 +172,7 @@ func (k *Keeper) ApplyMessage(evm *vm.EVM, msg core.Message) (*types.ExecutionRe
}
if contractCreation {
ret, contract, leftoverGas, vmErr = evm.Create(sender, msg.Data(), leftoverGas, msg.Value())
contractAddr = contract.Hex()
ret, _, leftoverGas, vmErr = evm.Create(sender, msg.Data(), leftoverGas, msg.Value())
} else {
ret, leftoverGas, vmErr = evm.Call(sender, *msg.To(), msg.Data(), leftoverGas, msg.Value())
}
@ -198,8 +195,7 @@ func (k *Keeper) ApplyMessage(evm *vm.EVM, msg core.Message) (*types.ExecutionRe
return &types.ExecutionResult{
Response: &types.MsgEthereumTxResponse{
ContractAddress: contractAddr,
Ret: ret,
Ret: ret,
},
GasInfo: types.GasInfo{
GasLimit: k.ctx.GasMeter().Limit(),

View File

@ -7,6 +7,7 @@ const (
AttributeKeyContractAddress = "contract"
AttributeKeyRecipient = "recipient"
AttributeKeyTxHash = "txHash"
AttributeKeyEthereumTxHash = "ethereumTxHash"
AttributeValueCategory = ModuleName
MetricKeyTransitionDB = "transition_db"

View File

@ -20,14 +20,9 @@ func NewTransactionLogs(hash ethcmn.Hash, logs []*Log) TransactionLogs { // noli
// NewTransactionLogsFromEth creates a new NewTransactionLogs instance using []*ethtypes.Log.
func NewTransactionLogsFromEth(hash ethcmn.Hash, ethlogs []*ethtypes.Log) TransactionLogs { // nolint: interfacer
logs := make([]*Log, len(ethlogs))
for i := range ethlogs {
logs[i] = NewLogFromEth(ethlogs[i])
}
return TransactionLogs{
Hash: hash.String(),
Logs: logs,
Logs: NewLogsFromEth(ethlogs),
}
}
@ -93,6 +88,15 @@ func (log *Log) ToEthereum() *ethtypes.Log {
}
}
func NewLogsFromEth(ethlogs []*ethtypes.Log) []*Log {
var logs []*Log
for _, ethlog := range ethlogs {
logs = append(logs, NewLogFromEth(ethlog))
}
return logs
}
// LogsToEthereum casts the Ethermint Logs to a slice of Ethereum Logs.
func LogsToEthereum(logs []*Log) []*ethtypes.Log {
var ethLogs []*ethtypes.Log // nolint: prealloc

View File

@ -113,6 +113,7 @@ func (msg *MsgEthereumTx) FromEthereumTx(tx *ethtypes.Transaction) {
}
msg.Size_ = float64(tx.Size())
msg.Hash = tx.Hash().Hex()
}
// Route returns the route value of an MsgEthereumTx.

File diff suppressed because it is too large Load Diff

View File

@ -377,78 +377,6 @@ func local_request_Query_TxLogs_0(ctx context.Context, marshaler runtime.Marshal
}
func request_Query_TxReceipt_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
var protoReq QueryTxReceiptRequest
var metadata runtime.ServerMetadata
var (
val string
ok bool
err error
_ = err
)
val, ok = pathParams["hash"]
if !ok {
return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "hash")
}
protoReq.Hash, err = runtime.String(val)
if err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "hash", err)
}
msg, err := client.TxReceipt(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
return msg, metadata, err
}
func local_request_Query_TxReceipt_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
var protoReq QueryTxReceiptRequest
var metadata runtime.ServerMetadata
var (
val string
ok bool
err error
_ = err
)
val, ok = pathParams["hash"]
if !ok {
return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "hash")
}
protoReq.Hash, err = runtime.String(val)
if err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "hash", err)
}
msg, err := server.TxReceipt(ctx, &protoReq)
return msg, metadata, err
}
func request_Query_TxReceiptsByBlockHeight_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
var protoReq QueryTxReceiptsByBlockHeightRequest
var metadata runtime.ServerMetadata
msg, err := client.TxReceiptsByBlockHeight(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
return msg, metadata, err
}
func local_request_Query_TxReceiptsByBlockHeight_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
var protoReq QueryTxReceiptsByBlockHeightRequest
var metadata runtime.ServerMetadata
msg, err := server.TxReceiptsByBlockHeight(ctx, &protoReq)
return msg, metadata, err
}
var (
filter_Query_BlockLogs_0 = &utilities.DoubleArray{Encoding: map[string]int{"hash": 0}, Base: []int{1, 1, 0}, Check: []int{0, 1, 2}}
)
@ -719,46 +647,6 @@ func RegisterQueryHandlerServer(ctx context.Context, mux *runtime.ServeMux, serv
})
mux.Handle("GET", pattern_Query_TxReceipt_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
ctx, cancel := context.WithCancel(req.Context())
defer cancel()
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req)
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
resp, md, err := local_request_Query_TxReceipt_0(rctx, inboundMarshaler, server, req, pathParams)
ctx = runtime.NewServerMetadataContext(ctx, md)
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
forward_Query_TxReceipt_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
})
mux.Handle("GET", pattern_Query_TxReceiptsByBlockHeight_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
ctx, cancel := context.WithCancel(req.Context())
defer cancel()
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req)
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
resp, md, err := local_request_Query_TxReceiptsByBlockHeight_0(rctx, inboundMarshaler, server, req, pathParams)
ctx = runtime.NewServerMetadataContext(ctx, md)
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
forward_Query_TxReceiptsByBlockHeight_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
})
mux.Handle("GET", pattern_Query_BlockLogs_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
ctx, cancel := context.WithCancel(req.Context())
defer cancel()
@ -1000,46 +888,6 @@ func RegisterQueryHandlerClient(ctx context.Context, mux *runtime.ServeMux, clie
})
mux.Handle("GET", pattern_Query_TxReceipt_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
ctx, cancel := context.WithCancel(req.Context())
defer cancel()
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
rctx, err := runtime.AnnotateContext(ctx, mux, req)
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
resp, md, err := request_Query_TxReceipt_0(rctx, inboundMarshaler, client, req, pathParams)
ctx = runtime.NewServerMetadataContext(ctx, md)
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
forward_Query_TxReceipt_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
})
mux.Handle("GET", pattern_Query_TxReceiptsByBlockHeight_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
ctx, cancel := context.WithCancel(req.Context())
defer cancel()
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
rctx, err := runtime.AnnotateContext(ctx, mux, req)
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
resp, md, err := request_Query_TxReceiptsByBlockHeight_0(rctx, inboundMarshaler, client, req, pathParams)
ctx = runtime.NewServerMetadataContext(ctx, md)
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
forward_Query_TxReceiptsByBlockHeight_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
})
mux.Handle("GET", pattern_Query_BlockLogs_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
ctx, cancel := context.WithCancel(req.Context())
defer cancel()
@ -1136,10 +984,6 @@ var (
pattern_Query_TxLogs_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 1, 0, 4, 1, 5, 4}, []string{"ethermint", "evm", "v1alpha1", "tx_logs", "hash"}, "", runtime.AssumeColonVerbOpt(true)))
pattern_Query_TxReceipt_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 1, 0, 4, 1, 5, 4}, []string{"ethermint", "evm", "v1alpha1", "tx_receipt", "hash"}, "", runtime.AssumeColonVerbOpt(true)))
pattern_Query_TxReceiptsByBlockHeight_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"ethermint", "evm", "v1alpha1", "tx_receipts_block"}, "", runtime.AssumeColonVerbOpt(true)))
pattern_Query_BlockLogs_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 1, 0, 4, 1, 5, 4}, []string{"ethermint", "evm", "v1alpha1", "block_logs", "hash"}, "", runtime.AssumeColonVerbOpt(true)))
pattern_Query_BlockBloom_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"ethermint", "evm", "v1alpha1", "block_bloom"}, "", runtime.AssumeColonVerbOpt(true)))
@ -1162,10 +1006,6 @@ var (
forward_Query_TxLogs_0 = runtime.ForwardResponseMessage
forward_Query_TxReceipt_0 = runtime.ForwardResponseMessage
forward_Query_TxReceiptsByBlockHeight_0 = runtime.ForwardResponseMessage
forward_Query_BlockLogs_0 = runtime.ForwardResponseMessage
forward_Query_BlockBloom_0 = runtime.ForwardResponseMessage

View File

@ -242,12 +242,8 @@ func (st *StateTransition) TransitionDb(ctx sdk.Context, config ChainConfig) (re
// Resets nonce to value pre state transition
csdb.SetNonce(st.Message.From(), currentNonce)
// Generate bloom filter to be saved in tx receipt data
bloomInt := big.NewInt(0)
var (
bloomFilter ethtypes.Bloom
logs []*ethtypes.Log
logs []*ethtypes.Log
)
if st.TxHash != nil && !st.Simulate {
@ -256,9 +252,6 @@ func (st *StateTransition) TransitionDb(ctx sdk.Context, config ChainConfig) (re
err = errors.Wrap(err, "failed to get logs")
return nil, err
}
bloomInt = big.NewInt(0).SetBytes(ethtypes.LogsBloom(logs))
bloomFilter = ethtypes.BytesToBloom(bloomInt.Bytes())
}
if !st.Simulate {
@ -270,15 +263,9 @@ func (st *StateTransition) TransitionDb(ctx sdk.Context, config ChainConfig) (re
}
resp.Logs = logs
resp.Bloom = bloomInt
resp.Response = &MsgEthereumTxResponse{
Bloom: bloomFilter.Bytes(),
TxLogs: NewTransactionLogsFromEth(*st.TxHash, logs),
Ret: ret,
}
if contractCreation {
resp.Response.ContractAddress = contractAddress.String()
Logs: NewLogsFromEth(logs),
Ret: ret,
}
// TODO: Refund unused gas here, if intended in future

View File

@ -150,19 +150,16 @@ var xxx_messageInfo_ExtensionOptionsWeb3Tx proto.InternalMessageInfo
// MsgEthereumTxResponse defines the Msg/EthereumTx response type.
type MsgEthereumTxResponse struct {
// contract_address contains the ethereum address of the created contract (if
// any). If the state transition is an evm.Call, the contract address will be
// empty.
ContractAddress string `protobuf:"bytes,1,opt,name=contract_address,json=contractAddress,proto3" json:"contract_address,omitempty" yaml:"contract_address"`
// bloom represents the bloom filter bytes
Bloom []byte `protobuf:"bytes,2,opt,name=bloom,proto3" json:"bloom,omitempty"`
// tx_logs contains the transaction hash and the proto-compatible ethereum
// ethereum transaction hash in hex format. This hash differs from the Tendermint sha256 hash of the transaction
// bytes. See https://github.com/tendermint/tendermint/issues/6539 for reference
Hash string `protobuf:"bytes,1,opt,name=hash,proto3" json:"hash,omitempty"`
// logs contains the transaction hash and the proto-compatible ethereum
// logs.
TxLogs TransactionLogs `protobuf:"bytes,3,opt,name=tx_logs,json=txLogs,proto3" json:"tx_logs" yaml:"tx_logs"`
// ret defines the bytes from the execution.
Ret []byte `protobuf:"bytes,4,opt,name=ret,proto3" json:"ret,omitempty"`
Logs []*Log `protobuf:"bytes,2,rep,name=logs,proto3" json:"logs,omitempty"`
// returned data from evm function (result or data supplied with revert opcode)
Ret []byte `protobuf:"bytes,3,opt,name=ret,proto3" json:"ret,omitempty"`
// reverted flag is set to true when the call has been reverted
Reverted bool `protobuf:"varint,5,opt,name=reverted,proto3" json:"reverted,omitempty"`
Reverted bool `protobuf:"varint,4,opt,name=reverted,proto3" json:"reverted,omitempty"`
}
func (m *MsgEthereumTxResponse) Reset() { *m = MsgEthereumTxResponse{} }
@ -208,37 +205,33 @@ func init() {
func init() { proto.RegisterFile("ethermint/evm/v1alpha1/tx.proto", fileDescriptor_6a305e80b084ab0e) }
var fileDescriptor_6a305e80b084ab0e = []byte{
// 476 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x8c, 0x92, 0x3f, 0x6f, 0xd3, 0x40,
0x18, 0xc6, 0x7d, 0x8d, 0xd3, 0x3f, 0x97, 0x02, 0xd5, 0xa9, 0x04, 0x63, 0x24, 0xdb, 0xb2, 0x84,
0x9a, 0x25, 0xb6, 0x9a, 0x6e, 0xd9, 0x6a, 0x51, 0x26, 0x2a, 0xa4, 0x53, 0x25, 0x10, 0x4b, 0x75,
0x76, 0x0e, 0xdb, 0x92, 0xed, 0xb3, 0xee, 0xae, 0x91, 0xcb, 0xca, 0xc2, 0xc8, 0xca, 0xc6, 0xc7,
0xe9, 0xd8, 0x91, 0xc9, 0x42, 0xc9, 0xc6, 0x98, 0x4f, 0x80, 0x7c, 0x6e, 0x52, 0x1a, 0x11, 0xa9,
0xdb, 0x7b, 0xef, 0xfb, 0xf3, 0xf9, 0x79, 0x9e, 0x7b, 0xa1, 0x4d, 0x65, 0x42, 0x79, 0x9e, 0x16,
0xd2, 0xa7, 0xd3, 0xdc, 0x9f, 0x1e, 0x93, 0xac, 0x4c, 0xc8, 0xb1, 0x2f, 0x2b, 0xaf, 0xe4, 0x4c,
0x32, 0xd4, 0x5f, 0x01, 0x1e, 0x9d, 0xe6, 0xde, 0x12, 0x30, 0x0f, 0x63, 0x16, 0x33, 0x85, 0xf8,
0x4d, 0xd5, 0xd2, 0xa6, 0xb3, 0xe1, 0xba, 0xe6, 0x53, 0x45, 0xb8, 0x3f, 0x00, 0x7c, 0x72, 0x2e,
0xe2, 0xb3, 0x86, 0xa3, 0x57, 0xf9, 0x45, 0x85, 0x46, 0x50, 0x9f, 0x10, 0x49, 0x0c, 0xe0, 0x80,
0x41, 0x6f, 0x64, 0x79, 0xff, 0xff, 0xa1, 0x77, 0x51, 0xbd, 0x21, 0x92, 0x60, 0xc5, 0xa2, 0x97,
0x50, 0x17, 0xe9, 0x17, 0x6a, 0x6c, 0x39, 0x60, 0x00, 0x82, 0xee, 0x9f, 0xda, 0x06, 0x43, 0xac,
0x5a, 0xc8, 0x86, 0x7a, 0x42, 0x44, 0x62, 0x74, 0x1c, 0x30, 0xd8, 0x0b, 0x7a, 0x8b, 0xda, 0xde,
0xe1, 0x59, 0x39, 0x76, 0x87, 0x2e, 0x56, 0x03, 0x84, 0xa0, 0xfe, 0x99, 0xb3, 0xdc, 0xd0, 0x1b,
0x00, 0xab, 0x7a, 0xac, 0x7f, 0xfb, 0x69, 0x6b, 0xae, 0x0b, 0xcd, 0xb3, 0x4a, 0xd2, 0x42, 0xa4,
0xac, 0x78, 0x5f, 0xca, 0x94, 0x15, 0xe2, 0x5e, 0xe7, 0x1d, 0x63, 0xc1, 0xfe, 0x3a, 0xf3, 0x81,
0x86, 0x27, 0xab, 0xf9, 0xd7, 0x2d, 0xf8, 0xfc, 0x81, 0x3f, 0x4c, 0x45, 0xc9, 0x0a, 0x41, 0xd1,
0x5b, 0x78, 0x10, 0xb1, 0x42, 0x72, 0x12, 0xc9, 0x4b, 0x32, 0x99, 0x70, 0x2a, 0x84, 0xf2, 0xbc,
0x17, 0xbc, 0x5a, 0xd4, 0xf6, 0x8b, 0x6b, 0x92, 0x67, 0x63, 0x77, 0x9d, 0x70, 0xf1, 0xb3, 0x65,
0xeb, 0xb4, 0xed, 0xa0, 0x43, 0xd8, 0x0d, 0x33, 0xc6, 0x72, 0x65, 0x7e, 0x1f, 0xb7, 0x07, 0xf4,
0x11, 0xee, 0xc8, 0xea, 0x32, 0x63, 0xb1, 0x50, 0xce, 0x7b, 0xa3, 0xa3, 0x8d, 0x41, 0x72, 0x52,
0x08, 0x12, 0x35, 0xd2, 0xdf, 0xb1, 0x58, 0x04, 0xfd, 0x9b, 0xda, 0xd6, 0x16, 0xb5, 0xfd, 0xb4,
0x55, 0x70, 0x77, 0x8b, 0x8b, 0xb7, 0x65, 0xd5, 0xcc, 0xd1, 0x01, 0xec, 0x70, 0x2a, 0x55, 0x5c,
0xfb, 0xb8, 0x29, 0x91, 0x09, 0x77, 0x39, 0x9d, 0x52, 0x2e, 0xe9, 0xc4, 0xe8, 0x3a, 0x60, 0xb0,
0x8b, 0x57, 0xe7, 0x36, 0x85, 0x51, 0x0a, 0x3b, 0xe7, 0x22, 0x46, 0x21, 0x84, 0xff, 0x3c, 0xf4,
0xeb, 0x4d, 0x8a, 0x1e, 0xe4, 0x65, 0x0e, 0x1f, 0x85, 0x2d, 0x63, 0x0d, 0x4e, 0x6f, 0x66, 0x16,
0xb8, 0x9d, 0x59, 0xe0, 0xf7, 0xcc, 0x02, 0xdf, 0xe7, 0x96, 0x76, 0x3b, 0xb7, 0xb4, 0x5f, 0x73,
0x4b, 0xfb, 0x74, 0x14, 0xa7, 0x32, 0xb9, 0x0a, 0xbd, 0x88, 0xe5, 0x7e, 0xc4, 0x44, 0xce, 0x84,
0x7f, 0xbf, 0x9e, 0x95, 0x5a, 0x50, 0x79, 0x5d, 0x52, 0x11, 0x6e, 0xab, 0xd5, 0x3c, 0xf9, 0x1b,
0x00, 0x00, 0xff, 0xff, 0x74, 0xe0, 0xdf, 0x68, 0x0d, 0x03, 0x00, 0x00,
// 404 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x8c, 0x92, 0x31, 0x6b, 0xdb, 0x40,
0x1c, 0xc5, 0x75, 0x96, 0xda, 0xba, 0xe7, 0x16, 0xca, 0xd1, 0x1a, 0x55, 0x85, 0x93, 0x10, 0x94,
0x6a, 0xb1, 0x84, 0xe5, 0xcd, 0x5b, 0x4d, 0xbd, 0xd5, 0x14, 0x0e, 0x43, 0xa1, 0x9b, 0x64, 0x5f,
0x25, 0x81, 0xa5, 0x13, 0xba, 0xb3, 0x50, 0xf2, 0x09, 0x32, 0x7a, 0xcd, 0x96, 0x8f, 0x93, 0xd1,
0x63, 0x26, 0x13, 0xec, 0x2d, 0x63, 0x3e, 0x41, 0xd0, 0x39, 0xb6, 0xe3, 0x10, 0x43, 0xb6, 0xbf,
0xf4, 0xff, 0xdd, 0xbd, 0xf7, 0x8e, 0x07, 0x4d, 0x2a, 0x62, 0x5a, 0xa4, 0x49, 0x26, 0x3c, 0x5a,
0xa6, 0x5e, 0xd9, 0x0d, 0x66, 0x79, 0x1c, 0x74, 0x3d, 0x51, 0xb9, 0x79, 0xc1, 0x04, 0x43, 0xed,
0x3d, 0xe0, 0xd2, 0x32, 0x75, 0x77, 0x80, 0xf1, 0x39, 0x62, 0x11, 0x93, 0x88, 0x57, 0x4f, 0x5b,
0xda, 0xb0, 0x4e, 0x5c, 0x57, 0x1f, 0x95, 0x84, 0x7d, 0x09, 0xe0, 0xc7, 0x11, 0x8f, 0x86, 0x35,
0x47, 0xe7, 0xe9, 0xb8, 0x42, 0x3e, 0xd4, 0xa6, 0x81, 0x08, 0x74, 0x60, 0x01, 0xa7, 0xe5, 0x63,
0xf7, 0x65, 0x41, 0x77, 0x5c, 0xfd, 0x0a, 0x44, 0x40, 0x24, 0x8b, 0xbe, 0x42, 0x8d, 0x27, 0xe7,
0x54, 0x6f, 0x58, 0xc0, 0x01, 0x83, 0x37, 0x77, 0x2b, 0x13, 0x74, 0x88, 0xfc, 0x85, 0x4c, 0xa8,
0xc5, 0x01, 0x8f, 0x75, 0xd5, 0x02, 0xce, 0xfb, 0x41, 0xeb, 0x7e, 0x65, 0xbe, 0x2b, 0x66, 0x79,
0xdf, 0xee, 0xd8, 0x44, 0x2e, 0x10, 0x82, 0xda, 0xff, 0x82, 0xa5, 0xba, 0x56, 0x03, 0x44, 0xce,
0x7d, 0xed, 0xe2, 0xca, 0x54, 0x6c, 0x1b, 0x1a, 0xc3, 0x4a, 0xd0, 0x8c, 0x27, 0x2c, 0xfb, 0x93,
0x8b, 0x84, 0x65, 0xfc, 0xe0, 0xf3, 0x91, 0xc1, 0xb0, 0xfd, 0x9c, 0xf9, 0x4b, 0xc3, 0xde, 0x7e,
0xbf, 0x00, 0xf0, 0xcb, 0x51, 0x3e, 0x42, 0x79, 0xce, 0x32, 0x4e, 0x6b, 0x5d, 0x69, 0x0c, 0x6c,
0x75, 0xa5, 0x17, 0x0f, 0x6a, 0x33, 0x16, 0x71, 0xbd, 0x61, 0xa9, 0x4e, 0xcb, 0xff, 0x76, 0x2a,
0xfb, 0x6f, 0x16, 0x11, 0x09, 0xa2, 0x4f, 0x50, 0x2d, 0xa8, 0x90, 0xe1, 0x3e, 0x90, 0x7a, 0x44,
0x06, 0x6c, 0x16, 0xb4, 0xa4, 0x85, 0xa0, 0x53, 0x19, 0xa9, 0x49, 0xf6, 0xdf, 0x5b, 0x4b, 0x7e,
0x02, 0xd5, 0x11, 0x8f, 0x50, 0x08, 0xe1, 0x93, 0x57, 0xff, 0x7e, 0x4a, 0xeb, 0xc8, 0xbc, 0xd1,
0x79, 0x15, 0xb6, 0xcb, 0x38, 0xf8, 0x79, 0xbd, 0xc6, 0x60, 0xb9, 0xc6, 0xe0, 0x76, 0x8d, 0xc1,
0x62, 0x83, 0x95, 0xe5, 0x06, 0x2b, 0x37, 0x1b, 0xac, 0xfc, 0xfb, 0x11, 0x25, 0x22, 0x9e, 0x87,
0xee, 0x84, 0xa5, 0xde, 0x84, 0xf1, 0x94, 0x71, 0xef, 0xd0, 0x95, 0x4a, 0xb6, 0x45, 0x9c, 0xe5,
0x94, 0x87, 0x6f, 0x65, 0x4f, 0x7a, 0x0f, 0x01, 0x00, 0x00, 0xff, 0xff, 0x9c, 0x61, 0x2c, 0xf2,
0x9a, 0x02, 0x00, 0x00,
}
// Reference imports to suppress errors if they are not otherwise used.
@ -452,36 +445,33 @@ func (m *MsgEthereumTxResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) {
dAtA[i] = 0
}
i--
dAtA[i] = 0x28
dAtA[i] = 0x20
}
if len(m.Ret) > 0 {
i -= len(m.Ret)
copy(dAtA[i:], m.Ret)
i = encodeVarintTx(dAtA, i, uint64(len(m.Ret)))
i--
dAtA[i] = 0x22
dAtA[i] = 0x1a
}
{
size, err := m.TxLogs.MarshalToSizedBuffer(dAtA[:i])
if err != nil {
return 0, err
if len(m.Logs) > 0 {
for iNdEx := len(m.Logs) - 1; iNdEx >= 0; iNdEx-- {
{
size, err := m.Logs[iNdEx].MarshalToSizedBuffer(dAtA[:i])
if err != nil {
return 0, err
}
i -= size
i = encodeVarintTx(dAtA, i, uint64(size))
}
i--
dAtA[i] = 0x12
}
i -= size
i = encodeVarintTx(dAtA, i, uint64(size))
}
i--
dAtA[i] = 0x1a
if len(m.Bloom) > 0 {
i -= len(m.Bloom)
copy(dAtA[i:], m.Bloom)
i = encodeVarintTx(dAtA, i, uint64(len(m.Bloom)))
i--
dAtA[i] = 0x12
}
if len(m.ContractAddress) > 0 {
i -= len(m.ContractAddress)
copy(dAtA[i:], m.ContractAddress)
i = encodeVarintTx(dAtA, i, uint64(len(m.ContractAddress)))
if len(m.Hash) > 0 {
i -= len(m.Hash)
copy(dAtA[i:], m.Hash)
i = encodeVarintTx(dAtA, i, uint64(len(m.Hash)))
i--
dAtA[i] = 0xa
}
@ -547,16 +537,16 @@ func (m *MsgEthereumTxResponse) Size() (n int) {
}
var l int
_ = l
l = len(m.ContractAddress)
l = len(m.Hash)
if l > 0 {
n += 1 + l + sovTx(uint64(l))
}
l = len(m.Bloom)
if l > 0 {
n += 1 + l + sovTx(uint64(l))
if len(m.Logs) > 0 {
for _, e := range m.Logs {
l = e.Size()
n += 1 + l + sovTx(uint64(l))
}
}
l = m.TxLogs.Size()
n += 1 + l + sovTx(uint64(l))
l = len(m.Ret)
if l > 0 {
n += 1 + l + sovTx(uint64(l))
@ -874,7 +864,7 @@ func (m *MsgEthereumTxResponse) Unmarshal(dAtA []byte) error {
switch fieldNum {
case 1:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field ContractAddress", wireType)
return fmt.Errorf("proto: wrong wireType = %d for field Hash", wireType)
}
var stringLen uint64
for shift := uint(0); ; shift += 7 {
@ -902,45 +892,11 @@ func (m *MsgEthereumTxResponse) Unmarshal(dAtA []byte) error {
if postIndex > l {
return io.ErrUnexpectedEOF
}
m.ContractAddress = string(dAtA[iNdEx:postIndex])
m.Hash = string(dAtA[iNdEx:postIndex])
iNdEx = postIndex
case 2:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field Bloom", wireType)
}
var byteLen int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowTx
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
byteLen |= int(b&0x7F) << shift
if b < 0x80 {
break
}
}
if byteLen < 0 {
return ErrInvalidLengthTx
}
postIndex := iNdEx + byteLen
if postIndex < 0 {
return ErrInvalidLengthTx
}
if postIndex > l {
return io.ErrUnexpectedEOF
}
m.Bloom = append(m.Bloom[:0], dAtA[iNdEx:postIndex]...)
if m.Bloom == nil {
m.Bloom = []byte{}
}
iNdEx = postIndex
case 3:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field TxLogs", wireType)
return fmt.Errorf("proto: wrong wireType = %d for field Logs", wireType)
}
var msglen int
for shift := uint(0); ; shift += 7 {
@ -967,11 +923,12 @@ func (m *MsgEthereumTxResponse) Unmarshal(dAtA []byte) error {
if postIndex > l {
return io.ErrUnexpectedEOF
}
if err := m.TxLogs.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
m.Logs = append(m.Logs, &Log{})
if err := m.Logs[len(m.Logs)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
return err
}
iNdEx = postIndex
case 4:
case 3:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field Ret", wireType)
}
@ -1005,7 +962,7 @@ func (m *MsgEthereumTxResponse) Unmarshal(dAtA []byte) error {
m.Ret = []byte{}
}
iNdEx = postIndex
case 5:
case 4:
if wireType != 0 {
return fmt.Errorf("proto: wrong wireType = %d for field Reverted", wireType)
}

View File

@ -8,7 +8,6 @@ import (
"github.com/stretchr/testify/require"
ethcmn "github.com/ethereum/go-ethereum/common"
ethtypes "github.com/ethereum/go-ethereum/core/types"
ethcrypto "github.com/ethereum/go-ethereum/crypto"
)
@ -23,20 +22,13 @@ func GenerateEthAddress() ethcmn.Address {
}
func TestEvmDataEncoding(t *testing.T) {
addr := "0x5dE8a020088a2D6d0a23c204FFbeD02790466B49"
bloom := ethtypes.BytesToBloom([]byte{0x1, 0x3})
ret := []byte{0x5, 0x8}
data := &MsgEthereumTxResponse{
ContractAddress: addr,
Bloom: bloom.Bytes(),
TxLogs: TransactionLogs{
Hash: ethcmn.BytesToHash([]byte{1, 2, 3, 4}).String(),
Logs: []*Log{{
Data: []byte{1, 2, 3, 4},
BlockNumber: 17,
}},
},
Logs: []*Log{{
Data: []byte{1, 2, 3, 4},
BlockNumber: 17,
}},
Ret: ret,
}
@ -46,8 +38,6 @@ func TestEvmDataEncoding(t *testing.T) {
res, err := DecodeTxResponse(enc)
require.NoError(t, err)
require.NotNil(t, res)
require.Equal(t, addr, res.ContractAddress)
require.Equal(t, bloom.Bytes(), res.Bloom)
require.Equal(t, data.TxLogs, res.TxLogs)
require.Equal(t, data.Logs, res.Logs)
require.Equal(t, ret, res.Ret)
}