Skip to content
This repository has been archived by the owner on Nov 30, 2021. It is now read-only.

store logs in keeper after transition #210

Merged
merged 37 commits into from
Mar 18, 2020
Merged
Show file tree
Hide file tree
Changes from 34 commits
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
fe5cfe5
add some comments
noot Mar 4, 2020
d00e3c6
begin log handler test
noot Mar 9, 2020
496edc2
update TransitionCSDB to return ReturnData
noot Mar 11, 2020
57eaae2
use rlp for result data encode/decode
noot Mar 11, 2020
beaccb4
update tests
noot Mar 11, 2020
dec0d62
merge with development
noot Mar 11, 2020
b4df9f9
implement SetBlockLogs
noot Mar 13, 2020
11d7add
implement GetBlockLogs
noot Mar 13, 2020
5a6f4e1
test log set/get
noot Mar 13, 2020
ce5e4a4
Merge branch 'development' of github.com:ChainSafe/ethermint into noo…
noot Mar 13, 2020
7b0d0bf
update keeper get/set logs to use hash as key
noot Mar 13, 2020
5869475
fix test
noot Mar 13, 2020
d668e7b
move logsKey to csdb
noot Mar 13, 2020
1ed2483
attempt to fix test
noot Mar 13, 2020
a8fee1d
attempt to fix test
noot Mar 13, 2020
b5cf096
attempt to fix test
noot Mar 13, 2020
9114d47
lint
noot Mar 13, 2020
6741a87
lint
noot Mar 13, 2020
d5fce93
lint
noot Mar 13, 2020
5bbf735
save logs after handling msg
noot Mar 13, 2020
e66bf4c
update k.Logs
noot Mar 13, 2020
ebf52d3
cleanup
noot Mar 16, 2020
79e9b76
remove unused
noot Mar 16, 2020
bcbd905
fix issues
noot Mar 16, 2020
bd493e7
merge wtih development
noot Mar 16, 2020
0202547
merge with version bump
noot Mar 17, 2020
e285fd0
comment out handler test
noot Mar 17, 2020
e11b238
merge with development
noot Mar 17, 2020
045e41a
address comments
noot Mar 17, 2020
7f47916
lint
noot Mar 17, 2020
a22277e
fix handler test
noot Mar 17, 2020
6a9e1bf
address comments
noot Mar 17, 2020
5e615f4
use amino
noot Mar 17, 2020
22e16bf
lint
noot Mar 17, 2020
a9ecb7f
address comments
noot Mar 18, 2020
977f06f
merge
noot Mar 18, 2020
4a8e64a
merge
noot Mar 18, 2020
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ require (
github.com/fjl/memsize v0.0.0-20190710130421-bcb5799ab5e5 // indirect
github.com/gballet/go-libpcsclite v0.0.0-20190607065134-2772fd86a8ff // indirect
github.com/golang/mock v1.3.1 // indirect
github.com/gorilla/mux v1.7.3
github.com/gorilla/mux v1.7.4
github.com/huin/goupnp v1.0.0 // indirect
github.com/jackpal/go-nat-pmp v1.0.1 // indirect
github.com/karalabe/usb v0.0.0-20190703133951-9be757f914c0 // indirect
Expand Down
76 changes: 71 additions & 5 deletions go.sum

Large diffs are not rendered by default.

5 changes: 4 additions & 1 deletion importer/importer_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -363,7 +363,10 @@ func applyTransaction(config *ethparams.ChainConfig, bc ethcore.ChainContext, au
receipt.ContractAddress = ethcrypto.CreateAddress(vmenv.Context.Origin, tx.Nonce())
}
// Set the receipt logs and create a bloom for filtering
receipt.Logs = statedb.GetLogs(tx.Hash())
receipt.Logs, err = statedb.GetLogs(tx.Hash())
if err != nil {
return nil, 0, err
}
receipt.Bloom = ethtypes.CreateBloom(ethtypes.Receipts{receipt})
receipt.BlockHash = statedb.BlockHash()
receipt.BlockNumber = header.Number
Expand Down
15 changes: 9 additions & 6 deletions rpc/eth_api.go
Original file line number Diff line number Diff line change
Expand Up @@ -358,12 +358,12 @@ func (e *PublicEthAPI) Call(args CallArgs, blockNr rpc.BlockNumber, overrides *m
return []byte{}, err
}

_, _, ret, err := types.DecodeReturnData(result.Data)
data, err := types.DecodeResultData(result.Data)
if err != nil {
return []byte{}, err
}

return (hexutil.Bytes)(ret), nil
return (hexutil.Bytes)(data.Ret), nil
}

// account indicates the overriding fields of account during the execution of
Expand Down Expand Up @@ -745,7 +745,10 @@ func (e *PublicEthAPI) GetTransactionReceipt(hash common.Hash) (map[string]inter
e.cliCtx.Codec.MustUnmarshalJSON(res, &logs)

txData := tx.TxResult.GetData()
contractAddress, bloomFilter, _, _ := types.DecodeReturnData(txData)
data, err := types.DecodeResultData(txData)
if err != nil {
return nil, err
}

fields := map[string]interface{}{
"blockHash": blockHash,
Expand All @@ -758,12 +761,12 @@ func (e *PublicEthAPI) GetTransactionReceipt(hash common.Hash) (map[string]inter
"cumulativeGasUsed": nil, // ignore until needed
"contractAddress": nil,
"logs": logs.Logs,
"logsBloom": bloomFilter,
"logsBloom": data.Bloom,
"status": status,
}

if contractAddress != (common.Address{}) {
fields["contractAddress"] = contractAddress
if data.Address != (common.Address{}) {
fields["contractAddress"] = data.Address
}

return fields, nil
Expand Down
5 changes: 4 additions & 1 deletion x/evm/abci.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,10 @@ import (
func BeginBlock(k Keeper, ctx sdk.Context, req abci.RequestBeginBlock) {
// Consider removing this when using evm as module without web3 API
bloom := ethtypes.BytesToBloom(k.Bloom.Bytes())
k.SetBlockBloomMapping(ctx, bloom, req.Header.GetHeight()-1)
err := k.SetBlockBloomMapping(ctx, bloom, req.Header.GetHeight()-1)
if err != nil {
panic(err)
}
k.SetBlockHashMapping(ctx, req.Header.LastBlockId.GetHash(), req.Header.GetHeight()-1)
k.Bloom = big.NewInt(0)
k.TxCount = 0
Expand Down
39 changes: 25 additions & 14 deletions x/evm/handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,17 +19,17 @@ func NewHandler(k Keeper) sdk.Handler {
return func(ctx sdk.Context, msg sdk.Msg) (*sdk.Result, error) {
switch msg := msg.(type) {
case types.MsgEthereumTx:
return handleEthTxMsg(ctx, k, msg)
case *types.MsgEthermint:
return handleMsgEthermint(ctx, k, *msg)
return HandleEthTxMsg(ctx, k, msg)
case types.MsgEthermint:
return HandleMsgEthermint(ctx, k, msg)
default:
return nil, sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "unrecognized ethermint message type: %T", msg)
}
}
}

// handleEthTxMsg handles an Ethereum specific tx
func handleEthTxMsg(ctx sdk.Context, k Keeper, msg types.MsgEthereumTx) (*sdk.Result, error) {
// HandleEthTxMsg handles an Ethereum specific tx
func HandleEthTxMsg(ctx sdk.Context, k Keeper, msg types.MsgEthereumTx) (*sdk.Result, error) {
// parse the chainID from a string to a base-10 integer
intChainID, ok := new(big.Int).SetString(ctx.ChainID(), 10)
if !ok {
Expand Down Expand Up @@ -69,13 +69,24 @@ func handleEthTxMsg(ctx sdk.Context, k Keeper, msg types.MsgEthereumTx) (*sdk.Re
k.TxCount++

// TODO: move to keeper
bloom, res, err := st.TransitionCSDB(ctx)
returnData, err := st.TransitionCSDB(ctx)
if err != nil {
return nil, err
}

// update block bloom filter
k.Bloom.Or(k.Bloom, bloom)
k.Bloom.Or(k.Bloom, returnData.Bloom)

// update transaction logs in KVStore
err = k.SetTransactionLogs(ctx, returnData.Logs, txHash)
if err != nil {
return nil, err
}

signer, err := msg.VerifySig(big.NewInt(3))
if err != nil {
return nil, err
}
noot marked this conversation as resolved.
Show resolved Hide resolved

ctx.EventManager().EmitEvents(sdk.Events{
sdk.NewEvent(
Expand All @@ -85,7 +96,7 @@ func handleEthTxMsg(ctx sdk.Context, k Keeper, msg types.MsgEthereumTx) (*sdk.Re
sdk.NewEvent(
sdk.EventTypeMessage,
sdk.NewAttribute(sdk.AttributeKeyModule, types.AttributeValueCategory),
sdk.NewAttribute(sdk.AttributeKeySender, msg.GetSigners()[0].String()),
sdk.NewAttribute(sdk.AttributeKeySender, signer.String()),
noot marked this conversation as resolved.
Show resolved Hide resolved
),
})

Expand All @@ -99,11 +110,11 @@ func handleEthTxMsg(ctx sdk.Context, k Keeper, msg types.MsgEthereumTx) (*sdk.Re
}

// set the events to the result
res.Events = ctx.EventManager().Events()
return res, nil
returnData.Result.Events = ctx.EventManager().Events()
return returnData.Result, nil
}

func handleMsgEthermint(ctx sdk.Context, k Keeper, msg types.MsgEthermint) (*sdk.Result, error) {
func HandleMsgEthermint(ctx sdk.Context, k Keeper, msg types.MsgEthermint) (*sdk.Result, error) {
// parse the chainID from a string to a base-10 integer
intChainID, ok := new(big.Int).SetString(ctx.ChainID(), 10)
if !ok {
Expand Down Expand Up @@ -131,7 +142,7 @@ func handleMsgEthermint(ctx sdk.Context, k Keeper, msg types.MsgEthermint) (*sdk
k.CommitStateDB.Prepare(common.Hash{}, common.Hash{}, k.TxCount) // Cannot provide tx hash
k.TxCount++

_, res, err := st.TransitionCSDB(ctx)
returnData, err := st.TransitionCSDB(ctx)
if err != nil {
return nil, err
}
Expand All @@ -158,6 +169,6 @@ func handleMsgEthermint(ctx sdk.Context, k Keeper, msg types.MsgEthermint) (*sdk
}

// set the events to the result
res.Events = ctx.EventManager().Events()
return res, nil
returnData.Result.Events = ctx.EventManager().Events()
return returnData.Result, nil
}
90 changes: 90 additions & 0 deletions x/evm/handler_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
package evm_test

import (
"math/big"
"testing"
"time"

"github.com/stretchr/testify/suite"

sdk "github.com/cosmos/cosmos-sdk/types"

"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/crypto"

"github.com/cosmos/ethermint/app"
"github.com/cosmos/ethermint/x/evm"
"github.com/cosmos/ethermint/x/evm/keeper"
"github.com/cosmos/ethermint/x/evm/types"

abci "github.com/tendermint/tendermint/abci/types"
)

type EvmTestSuite struct {
suite.Suite

ctx sdk.Context
querier sdk.Querier
noot marked this conversation as resolved.
Show resolved Hide resolved
app *app.EthermintApp
}

func (suite *EvmTestSuite) SetupTest() {
checkTx := false

suite.app = app.Setup(checkTx)
suite.ctx = suite.app.BaseApp.NewContext(checkTx, abci.Header{Height: 1, ChainID: "3", Time: time.Now().UTC()})
suite.querier = keeper.NewQuerier(suite.app.EvmKeeper)
noot marked this conversation as resolved.
Show resolved Hide resolved
}

func TestEvmTestSuite(t *testing.T) {
suite.Run(t, new(EvmTestSuite))
}

func (suite *EvmTestSuite) TestHandler_Logs() {
// Test contract:

// pragma solidity ^0.5.1;

// contract Test {
// event Hello(uint256 indexed world);

// constructor() public {
// emit Hello(17);
// }
// }

// {
// "linkReferences": {},
// "object": "6080604052348015600f57600080fd5b5060117f775a94827b8fd9b519d36cd827093c664f93347070a554f65e4a6f56cd73889860405160405180910390a2603580604b6000396000f3fe6080604052600080fdfea165627a7a723058206cab665f0f557620554bb45adf266708d2bd349b8a4314bdff205ee8440e3c240029",
// "opcodes": "PUSH1 0x80 PUSH1 0x40 MSTORE CALLVALUE DUP1 ISZERO PUSH1 0xF JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH1 0x11 PUSH32 0x775A94827B8FD9B519D36CD827093C664F93347070A554F65E4A6F56CD738898 PUSH1 0x40 MLOAD PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 LOG2 PUSH1 0x35 DUP1 PUSH1 0x4B PUSH1 0x0 CODECOPY PUSH1 0x0 RETURN INVALID PUSH1 0x80 PUSH1 0x40 MSTORE PUSH1 0x0 DUP1 REVERT INVALID LOG1 PUSH6 0x627A7A723058 KECCAK256 PUSH13 0xAB665F0F557620554BB45ADF26 PUSH8 0x8D2BD349B8A4314 0xbd SELFDESTRUCT KECCAK256 0x5e 0xe8 DIFFICULTY 0xe EXTCODECOPY 0x24 STOP 0x29 ",
// "sourceMap": "25:119:0:-;;;90:52;8:9:-1;5:2;;;30:1;27;20:12;5:2;90:52:0;132:2;126:9;;;;;;;;;;25:119;;;;;;"
// }

gasLimit := uint64(100000)
gasPrice := big.NewInt(1000000)

priv, err := crypto.GenerateKey()
suite.Require().NoError(err, "failed to create key")

bytecode := common.FromHex("0x6080604052348015600f57600080fd5b5060117f775a94827b8fd9b519d36cd827093c664f93347070a554f65e4a6f56cd73889860405160405180910390a2603580604b6000396000f3fe6080604052600080fdfea165627a7a723058206cab665f0f557620554bb45adf266708d2bd349b8a4314bdff205ee8440e3c240029")
tx := types.NewMsgEthereumTx(1, nil, big.NewInt(0), gasLimit, gasPrice, bytecode)
tx.Sign(big.NewInt(3), priv)

result, err := evm.HandleEthTxMsg(suite.ctx, suite.app.EvmKeeper, *tx)
suite.Require().NoError(err, "failed to handle eth tx msg")

resultData, err := types.DecodeResultData(result.Data)
suite.Require().NoError(err, "failed to decode result data")

suite.Require().Equal(len(resultData.Logs), 1)
suite.Require().Equal(len(resultData.Logs[0].Topics), 2)

hash := []byte{1}
err = suite.app.EvmKeeper.SetTransactionLogs(suite.ctx, resultData.Logs, hash)
suite.Require().NoError(err, "failed to set logs")

logs, err := suite.app.EvmKeeper.GetTransactionLogs(suite.ctx, hash)
suite.Require().NoError(err, "failed to get logs")

suite.Require().Equal(logs, resultData.Logs)
}
62 changes: 49 additions & 13 deletions x/evm/keeper/keeper.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package keeper

import (
"bytes"
"errors"
"fmt"

"github.com/cosmos/cosmos-sdk/codec"
Expand Down Expand Up @@ -72,23 +73,53 @@ func (k *Keeper) GetBlockHashMapping(ctx sdk.Context, hash []byte) (height int64
// ----------------------------------------------------------------------------

// SetBlockBloomMapping sets the mapping from block height to bloom bits
func (k *Keeper) SetBlockBloomMapping(ctx sdk.Context, bloom ethtypes.Bloom, height int64) {
func (k *Keeper) SetBlockBloomMapping(ctx sdk.Context, bloom ethtypes.Bloom, height int64) error {
store := ctx.KVStore(k.blockKey)
heightHash := k.cdc.MustMarshalBinaryLengthPrefixed(height)
if !bytes.Equal(heightHash, []byte{}) {
store.Set(heightHash, bloom.Bytes())
if len(heightHash) == 0 {
return fmt.Errorf("block with bloombits %v not found", bloom)
}
store.Set(types.BloomKey(heightHash), bloom.Bytes())
return nil
}

// GetBlockBloomMapping gets bloombits from block height
func (k *Keeper) GetBlockBloomMapping(ctx sdk.Context, height int64) ethtypes.Bloom {
func (k *Keeper) GetBlockBloomMapping(ctx sdk.Context, height int64) (ethtypes.Bloom, error) {
store := ctx.KVStore(k.blockKey)
heightHash := k.cdc.MustMarshalBinaryLengthPrefixed(height)
bloom := store.Get(heightHash)
if bytes.Equal(heightHash, []byte{}) {
panic(fmt.Errorf("block with bloombits %s not found", bloom))
if len(heightHash) == 0 {
return ethtypes.BytesToBloom([]byte{}), fmt.Errorf("block with height %d not found", height)
}
return ethtypes.BytesToBloom(bloom)

bloom := store.Get(types.BloomKey(heightHash))
if len(bloom) == 0 {
return ethtypes.BytesToBloom([]byte{}), fmt.Errorf("block with bloombits %v not found", bloom)
}

return ethtypes.BytesToBloom(bloom), nil
}

// SetBlockLogs sets the transaction's logs in the KVStore
func (k *Keeper) SetTransactionLogs(ctx sdk.Context, logs []*ethtypes.Log, hash []byte) error {
store := ctx.KVStore(k.blockKey)
encLogs, err := types.EncodeLogs(logs)
if err != nil {
return err
}
store.Set(types.LogsKey(hash), encLogs)

return nil
}

// GetBlockLogs gets the logs for a transaction from the KVStore
func (k *Keeper) GetTransactionLogs(ctx sdk.Context, hash []byte) ([]*ethtypes.Log, error) {
store := ctx.KVStore(k.blockKey)
encLogs := store.Get(types.LogsKey(hash))
if len(encLogs) == 0 {
return nil, errors.New("cannot get transaction logs")
}

return types.DecodeLogs(encLogs)
}

// ----------------------------------------------------------------------------
Expand Down Expand Up @@ -210,13 +241,18 @@ func (k *Keeper) GetCommittedState(ctx sdk.Context, addr ethcmn.Address, hash et
}

// GetLogs calls CommitStateDB.GetLogs using the passed in context
func (k *Keeper) GetLogs(ctx sdk.Context, hash ethcmn.Hash) []*ethtypes.Log {
return k.CommitStateDB.WithContext(ctx).GetLogs(hash)
func (k *Keeper) GetLogs(ctx sdk.Context, hash ethcmn.Hash) ([]*ethtypes.Log, error) {
logs, err := k.CommitStateDB.WithContext(ctx).GetLogs(hash)
if err != nil {
return nil, err
}

return logs, nil
}

// Logs calls CommitStateDB.Logs using the passed in context
func (k *Keeper) Logs(ctx sdk.Context) []*ethtypes.Log {
return k.CommitStateDB.WithContext(ctx).Logs()
// AllLogs calls CommitStateDB.AllLogs using the passed in context
func (k *Keeper) AllLogs(ctx sdk.Context) []*ethtypes.Log {
return k.CommitStateDB.WithContext(ctx).AllLogs()
}

// GetRefund calls CommitStateDB.GetRefund using the passed in context
Expand Down
10 changes: 6 additions & 4 deletions x/evm/keeper/keeper_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,8 @@ func (suite *KeeperTestSuite) TestDBStorage() {

// Test block height mapping functionality
testBloom := ethtypes.BytesToBloom([]byte{0x1, 0x3})
suite.app.EvmKeeper.SetBlockBloomMapping(suite.ctx, testBloom, 4)
err := suite.app.EvmKeeper.SetBlockBloomMapping(suite.ctx, testBloom, 4)
suite.Require().NoError(err, "failed to set block bloom mapping")

// Get those state transitions
suite.Require().Equal(suite.app.EvmKeeper.GetBalance(suite.ctx, address).Cmp(big.NewInt(5)), 0)
Expand All @@ -64,11 +65,12 @@ func (suite *KeeperTestSuite) TestDBStorage() {

suite.Require().Equal(suite.app.EvmKeeper.GetBlockHashMapping(suite.ctx, ethcmn.FromHex("0x0d87a3a5f73140f46aac1bf419263e4e94e87c292f25007700ab7f2060e2af68")), int64(7))
suite.Require().Equal(suite.app.EvmKeeper.GetBlockHashMapping(suite.ctx, []byte{0x43, 0x32}), int64(8))

suite.Require().Equal(suite.app.EvmKeeper.GetBlockBloomMapping(suite.ctx, 4), testBloom)
bloom, err := suite.app.EvmKeeper.GetBlockBloomMapping(suite.ctx, 4)
suite.Require().NoError(err)
suite.Require().Equal(bloom, testBloom)

// commit stateDB
_, err := suite.app.EvmKeeper.Commit(suite.ctx, false)
_, err = suite.app.EvmKeeper.Commit(suite.ctx, false)
suite.Require().NoError(err, "failed to commit StateDB")

// simulate BaseApp EndBlocker commitment
Expand Down
Loading