block and tx logs bloom and tx receipt logs (#119)
* Add bloom filter to tx receipt * wip tx receipt logs to be tested * Added Bloom - Height Mapping * keeper.go sets <height:bloombits> * keeper.go gets <height> --> bloombits * updating and querying bloom by block (to be tested with real logs) * fix bug with contract address return * added error handling instead of logging
This commit is contained in:
parent
8bb8b40b32
commit
eab81bc578
@ -4,6 +4,7 @@ import (
|
|||||||
"bytes"
|
"bytes"
|
||||||
"fmt"
|
"fmt"
|
||||||
"math/big"
|
"math/big"
|
||||||
|
"strconv"
|
||||||
|
|
||||||
emintcrypto "github.com/cosmos/ethermint/crypto"
|
emintcrypto "github.com/cosmos/ethermint/crypto"
|
||||||
emintkeys "github.com/cosmos/ethermint/keys"
|
emintkeys "github.com/cosmos/ethermint/keys"
|
||||||
@ -18,6 +19,7 @@ import (
|
|||||||
"github.com/ethereum/go-ethereum/accounts/keystore"
|
"github.com/ethereum/go-ethereum/accounts/keystore"
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
"github.com/ethereum/go-ethereum/common/hexutil"
|
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||||
|
ethtypes "github.com/ethereum/go-ethereum/core/types"
|
||||||
"github.com/ethereum/go-ethereum/rlp"
|
"github.com/ethereum/go-ethereum/rlp"
|
||||||
|
|
||||||
"github.com/cosmos/cosmos-sdk/client/context"
|
"github.com/cosmos/cosmos-sdk/client/context"
|
||||||
@ -393,12 +395,20 @@ func (e *PublicEthAPI) getEthBlockByNumber(value int64, fullTx bool) (map[string
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return formatBlock(header, block.Block.Size(), gasLimit, gasUsed, transactions), nil
|
res, _, err := e.cliCtx.Query(fmt.Sprintf("custom/%s/%s/%s", types.ModuleName, evm.QueryLogsBloom, strconv.FormatInt(block.Block.Height, 10)))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var out types.QueryBloomFilter
|
||||||
|
e.cliCtx.Codec.MustUnmarshalJSON(res, &out)
|
||||||
|
|
||||||
|
return formatBlock(header, block.Block.Size(), gasLimit, gasUsed, transactions, out.Bloom), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func formatBlock(
|
func formatBlock(
|
||||||
header tmtypes.Header, size int, gasLimit int64,
|
header tmtypes.Header, size int, gasLimit int64,
|
||||||
gasUsed *big.Int, transactions []interface{},
|
gasUsed *big.Int, transactions []interface{}, bloom ethtypes.Bloom,
|
||||||
) map[string]interface{} {
|
) map[string]interface{} {
|
||||||
return map[string]interface{}{
|
return map[string]interface{}{
|
||||||
"number": hexutil.Uint64(header.Height),
|
"number": hexutil.Uint64(header.Height),
|
||||||
@ -406,7 +416,7 @@ func formatBlock(
|
|||||||
"parentHash": hexutil.Bytes(header.LastBlockID.Hash),
|
"parentHash": hexutil.Bytes(header.LastBlockID.Hash),
|
||||||
"nonce": nil, // PoW specific
|
"nonce": nil, // PoW specific
|
||||||
"sha3Uncles": nil, // No uncles in Tendermint
|
"sha3Uncles": nil, // No uncles in Tendermint
|
||||||
"logsBloom": "", // TODO: Complete with #55
|
"logsBloom": bloom,
|
||||||
"transactionsRoot": hexutil.Bytes(header.DataHash),
|
"transactionsRoot": hexutil.Bytes(header.DataHash),
|
||||||
"stateRoot": hexutil.Bytes(header.AppHash),
|
"stateRoot": hexutil.Bytes(header.AppHash),
|
||||||
"miner": hexutil.Bytes(header.ValidatorsHash),
|
"miner": hexutil.Bytes(header.ValidatorsHash),
|
||||||
@ -584,6 +594,17 @@ func (e *PublicEthAPI) GetTransactionReceipt(hash common.Hash) (map[string]inter
|
|||||||
status = hexutil.Uint(0)
|
status = hexutil.Uint(0)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
res, _, err := e.cliCtx.Query(fmt.Sprintf("custom/%s/%s/%s", types.ModuleName, evm.QueryTxLogs, hash.Hex()))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var logs types.QueryTxLogs
|
||||||
|
e.cliCtx.Codec.MustUnmarshalJSON(res, &logs)
|
||||||
|
|
||||||
|
// TODO: change hard coded indexing of bytes
|
||||||
|
bloomFilter := ethtypes.BytesToBloom(tx.TxResult.GetData()[20:])
|
||||||
|
|
||||||
fields := map[string]interface{}{
|
fields := map[string]interface{}{
|
||||||
"blockHash": blockHash,
|
"blockHash": blockHash,
|
||||||
"blockNumber": hexutil.Uint64(tx.Height),
|
"blockNumber": hexutil.Uint64(tx.Height),
|
||||||
@ -594,13 +615,15 @@ func (e *PublicEthAPI) GetTransactionReceipt(hash common.Hash) (map[string]inter
|
|||||||
"gasUsed": hexutil.Uint64(tx.TxResult.GasUsed),
|
"gasUsed": hexutil.Uint64(tx.TxResult.GasUsed),
|
||||||
"cumulativeGasUsed": nil, // ignore until needed
|
"cumulativeGasUsed": nil, // ignore until needed
|
||||||
"contractAddress": nil,
|
"contractAddress": nil,
|
||||||
"logs": nil, // TODO: Do with #55 (eth_getLogs output)
|
"logs": logs.Logs,
|
||||||
"logsBloom": nil,
|
"logsBloom": bloomFilter,
|
||||||
"status": status,
|
"status": status,
|
||||||
}
|
}
|
||||||
|
|
||||||
if common.BytesToAddress(tx.TxResult.GetData()) != (common.Address{}) {
|
contractAddress := common.BytesToAddress(tx.TxResult.GetData()[:20])
|
||||||
fields["contractAddress"] = hexutil.Bytes(tx.TxResult.GetData())
|
if contractAddress != (common.Address{}) {
|
||||||
|
// TODO: change hard coded indexing of first 20 bytes
|
||||||
|
fields["contractAddress"] = contractAddress
|
||||||
}
|
}
|
||||||
|
|
||||||
return fields, nil
|
return fields, nil
|
||||||
|
@ -47,6 +47,15 @@ func handleETHTxMsg(ctx sdk.Context, keeper Keeper, msg types.EthereumTxMsg) sdk
|
|||||||
return emint.ErrInvalidSender(err.Error()).Result()
|
return emint.ErrInvalidSender(err.Error()).Result()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Encode transaction by default Tx encoder
|
||||||
|
txEncoder := authutils.GetTxEncoder(types.ModuleCdc)
|
||||||
|
txBytes, err := txEncoder(msg)
|
||||||
|
if err != nil {
|
||||||
|
return sdk.ErrInternal(err.Error()).Result()
|
||||||
|
}
|
||||||
|
txHash := tm.Tx(txBytes).Hash()
|
||||||
|
ethHash := common.BytesToHash(txHash)
|
||||||
|
|
||||||
st := types.StateTransition{
|
st := types.StateTransition{
|
||||||
Sender: sender,
|
Sender: sender,
|
||||||
AccountNonce: msg.Data.AccountNonce,
|
AccountNonce: msg.Data.AccountNonce,
|
||||||
@ -57,21 +66,15 @@ func handleETHTxMsg(ctx sdk.Context, keeper Keeper, msg types.EthereumTxMsg) sdk
|
|||||||
Payload: msg.Data.Payload,
|
Payload: msg.Data.Payload,
|
||||||
Csdb: keeper.csdb,
|
Csdb: keeper.csdb,
|
||||||
ChainID: intChainID,
|
ChainID: intChainID,
|
||||||
|
THash: ðHash,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Encode transaction by default Tx encoder
|
|
||||||
txEncoder := authutils.GetTxEncoder(types.ModuleCdc)
|
|
||||||
txBytes, err := txEncoder(msg)
|
|
||||||
if err != nil {
|
|
||||||
return sdk.ErrInternal(err.Error()).Result()
|
|
||||||
}
|
|
||||||
txHash := tm.Tx(txBytes).Hash()
|
|
||||||
|
|
||||||
// Prepare db for logs
|
// Prepare db for logs
|
||||||
keeper.csdb.Prepare(common.BytesToHash(txHash), common.Hash{}, keeper.txCount.get())
|
keeper.csdb.Prepare(ethHash, common.Hash{}, keeper.txCount.get())
|
||||||
keeper.txCount.increment()
|
keeper.txCount.increment()
|
||||||
|
|
||||||
return st.TransitionCSDB(ctx)
|
res, bloom := st.TransitionCSDB(ctx)
|
||||||
|
keeper.bloom.Or(keeper.bloom, bloom)
|
||||||
|
return res
|
||||||
}
|
}
|
||||||
|
|
||||||
func handleEmintMsg(ctx sdk.Context, keeper Keeper, msg types.EmintMsg) sdk.Result {
|
func handleEmintMsg(ctx sdk.Context, keeper Keeper, msg types.EmintMsg) sdk.Result {
|
||||||
@ -105,5 +108,6 @@ func handleEmintMsg(ctx sdk.Context, keeper Keeper, msg types.EmintMsg) sdk.Resu
|
|||||||
keeper.csdb.Prepare(common.Hash{}, common.Hash{}, keeper.txCount.get()) // Cannot provide tx hash
|
keeper.csdb.Prepare(common.Hash{}, common.Hash{}, keeper.txCount.get()) // Cannot provide tx hash
|
||||||
keeper.txCount.increment()
|
keeper.txCount.increment()
|
||||||
|
|
||||||
return st.TransitionCSDB(ctx)
|
res, _ := st.TransitionCSDB(ctx)
|
||||||
|
return res
|
||||||
}
|
}
|
||||||
|
@ -24,6 +24,7 @@ type Keeper struct {
|
|||||||
cdc *codec.Codec
|
cdc *codec.Codec
|
||||||
blockKey sdk.StoreKey
|
blockKey sdk.StoreKey
|
||||||
txCount *count
|
txCount *count
|
||||||
|
bloom *big.Int
|
||||||
}
|
}
|
||||||
|
|
||||||
type count int
|
type count int
|
||||||
@ -48,6 +49,7 @@ func NewKeeper(ak auth.AccountKeeper, storageKey, codeKey sdk.StoreKey,
|
|||||||
cdc: cdc,
|
cdc: cdc,
|
||||||
blockKey: blockKey,
|
blockKey: blockKey,
|
||||||
txCount: new(count),
|
txCount: new(count),
|
||||||
|
bloom: big.NewInt(0),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -75,6 +77,31 @@ func (k *Keeper) GetBlockHashMapping(ctx sdk.Context, hash []byte) (height int64
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
// Block bloom bits mapping functions
|
||||||
|
// May be removed when using only as module (only required by rpc api)
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// SetBlockBloomMapping sets the mapping from block height to bloom bits
|
||||||
|
func (k *Keeper) SetBlockBloomMapping(ctx sdk.Context, bloom ethtypes.Bloom, height int64) {
|
||||||
|
store := ctx.KVStore(k.blockKey)
|
||||||
|
heightHash := k.cdc.MustMarshalBinaryLengthPrefixed(height)
|
||||||
|
if !bytes.Equal(heightHash, []byte{}) {
|
||||||
|
store.Set(heightHash, bloom.Bytes())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetBlockBloomMapping gets bloombits from block height
|
||||||
|
func (k *Keeper) GetBlockBloomMapping(ctx sdk.Context, height int64) ethtypes.Bloom {
|
||||||
|
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))
|
||||||
|
}
|
||||||
|
return ethtypes.BytesToBloom(bloom)
|
||||||
|
}
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
// Genesis
|
// Genesis
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
|
@ -14,6 +14,7 @@ import (
|
|||||||
evmtypes "github.com/cosmos/ethermint/x/evm/types"
|
evmtypes "github.com/cosmos/ethermint/x/evm/types"
|
||||||
|
|
||||||
ethcmn "github.com/ethereum/go-ethereum/common"
|
ethcmn "github.com/ethereum/go-ethereum/common"
|
||||||
|
ethtypes "github.com/ethereum/go-ethereum/core/types"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
|
|
||||||
abci "github.com/tendermint/tendermint/abci/types"
|
abci "github.com/tendermint/tendermint/abci/types"
|
||||||
@ -84,6 +85,10 @@ func TestDBStorage(t *testing.T) {
|
|||||||
ek.SetBlockHashMapping(ctx, ethcmn.FromHex("0x0d87a3a5f73140f46aac1bf419263e4e94e87c292f25007700ab7f2060e2af68"), 7)
|
ek.SetBlockHashMapping(ctx, ethcmn.FromHex("0x0d87a3a5f73140f46aac1bf419263e4e94e87c292f25007700ab7f2060e2af68"), 7)
|
||||||
ek.SetBlockHashMapping(ctx, []byte{0x43, 0x32}, 8)
|
ek.SetBlockHashMapping(ctx, []byte{0x43, 0x32}, 8)
|
||||||
|
|
||||||
|
// Test block height mapping functionality
|
||||||
|
testBloom := ethtypes.BytesToBloom([]byte{0x1, 0x3})
|
||||||
|
ek.SetBlockBloomMapping(ctx, testBloom, 4)
|
||||||
|
|
||||||
// Get those state transitions
|
// Get those state transitions
|
||||||
require.Equal(t, ek.GetBalance(ctx, address).Cmp(big.NewInt(5)), 0)
|
require.Equal(t, ek.GetBalance(ctx, address).Cmp(big.NewInt(5)), 0)
|
||||||
require.Equal(t, ek.GetNonce(ctx, address), uint64(4))
|
require.Equal(t, ek.GetNonce(ctx, address), uint64(4))
|
||||||
@ -93,6 +98,8 @@ func TestDBStorage(t *testing.T) {
|
|||||||
require.Equal(t, ek.GetBlockHashMapping(ctx, ethcmn.FromHex("0x0d87a3a5f73140f46aac1bf419263e4e94e87c292f25007700ab7f2060e2af68")), int64(7))
|
require.Equal(t, ek.GetBlockHashMapping(ctx, ethcmn.FromHex("0x0d87a3a5f73140f46aac1bf419263e4e94e87c292f25007700ab7f2060e2af68")), int64(7))
|
||||||
require.Equal(t, ek.GetBlockHashMapping(ctx, []byte{0x43, 0x32}), int64(8))
|
require.Equal(t, ek.GetBlockHashMapping(ctx, []byte{0x43, 0x32}), int64(8))
|
||||||
|
|
||||||
|
require.Equal(t, ek.GetBlockBloomMapping(ctx, 4), testBloom)
|
||||||
|
|
||||||
// commit stateDB
|
// commit stateDB
|
||||||
_, err = ek.Commit(ctx, false)
|
_, err = ek.Commit(ctx, false)
|
||||||
require.NoError(t, err, "failed to commit StateDB")
|
require.NoError(t, err, "failed to commit StateDB")
|
||||||
|
@ -2,6 +2,7 @@ package evm
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
"math/big"
|
||||||
|
|
||||||
"github.com/cosmos/cosmos-sdk/client/context"
|
"github.com/cosmos/cosmos-sdk/client/context"
|
||||||
"github.com/cosmos/cosmos-sdk/codec"
|
"github.com/cosmos/cosmos-sdk/codec"
|
||||||
@ -9,6 +10,7 @@ import (
|
|||||||
"github.com/cosmos/cosmos-sdk/types/module"
|
"github.com/cosmos/cosmos-sdk/types/module"
|
||||||
"github.com/cosmos/ethermint/x/evm/client/cli"
|
"github.com/cosmos/ethermint/x/evm/client/cli"
|
||||||
"github.com/cosmos/ethermint/x/evm/types"
|
"github.com/cosmos/ethermint/x/evm/types"
|
||||||
|
ethtypes "github.com/ethereum/go-ethereum/core/types"
|
||||||
"github.com/gorilla/mux"
|
"github.com/gorilla/mux"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
abci "github.com/tendermint/tendermint/abci/types"
|
abci "github.com/tendermint/tendermint/abci/types"
|
||||||
@ -106,7 +108,10 @@ func (am AppModule) NewQuerierHandler() sdk.Querier {
|
|||||||
// BeginBlock function for module at start of each block
|
// BeginBlock function for module at start of each block
|
||||||
func (am AppModule) BeginBlock(ctx sdk.Context, bl abci.RequestBeginBlock) {
|
func (am AppModule) BeginBlock(ctx sdk.Context, bl abci.RequestBeginBlock) {
|
||||||
// Consider removing this when using evm as module without web3 API
|
// Consider removing this when using evm as module without web3 API
|
||||||
|
bloom := ethtypes.BytesToBloom(am.keeper.bloom.Bytes())
|
||||||
|
am.keeper.SetBlockBloomMapping(ctx, bloom, bl.Header.GetHeight()-1)
|
||||||
am.keeper.SetBlockHashMapping(ctx, bl.Header.LastBlockId.GetHash(), bl.Header.GetHeight()-1)
|
am.keeper.SetBlockHashMapping(ctx, bl.Header.LastBlockId.GetHash(), bl.Header.GetHeight()-1)
|
||||||
|
am.keeper.bloom = big.NewInt(0)
|
||||||
am.keeper.txCount.reset()
|
am.keeper.txCount.reset()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
package evm
|
package evm
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"strconv"
|
||||||
|
|
||||||
"github.com/cosmos/cosmos-sdk/codec"
|
"github.com/cosmos/cosmos-sdk/codec"
|
||||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||||
"github.com/cosmos/ethermint/utils"
|
"github.com/cosmos/ethermint/utils"
|
||||||
@ -20,6 +22,8 @@ const (
|
|||||||
QueryCode = "code"
|
QueryCode = "code"
|
||||||
QueryNonce = "nonce"
|
QueryNonce = "nonce"
|
||||||
QueryHashToHeight = "hashToHeight"
|
QueryHashToHeight = "hashToHeight"
|
||||||
|
QueryTxLogs = "txLogs"
|
||||||
|
QueryLogsBloom = "logsBloom"
|
||||||
)
|
)
|
||||||
|
|
||||||
// NewQuerier is the module level router for state queries
|
// NewQuerier is the module level router for state queries
|
||||||
@ -40,6 +44,10 @@ func NewQuerier(keeper Keeper) sdk.Querier {
|
|||||||
return queryNonce(ctx, path, keeper)
|
return queryNonce(ctx, path, keeper)
|
||||||
case QueryHashToHeight:
|
case QueryHashToHeight:
|
||||||
return queryHashToHeight(ctx, path, keeper)
|
return queryHashToHeight(ctx, path, keeper)
|
||||||
|
case QueryTxLogs:
|
||||||
|
return queryTxLogs(ctx, path, keeper)
|
||||||
|
case QueryLogsBloom:
|
||||||
|
return queryBlockLogsBloom(ctx, path, keeper)
|
||||||
default:
|
default:
|
||||||
return nil, sdk.ErrUnknownRequest("unknown query endpoint")
|
return nil, sdk.ErrUnknownRequest("unknown query endpoint")
|
||||||
}
|
}
|
||||||
@ -129,3 +137,33 @@ func queryHashToHeight(ctx sdk.Context, path []string, keeper Keeper) ([]byte, s
|
|||||||
|
|
||||||
return res, nil
|
return res, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func queryBlockLogsBloom(ctx sdk.Context, path []string, keeper Keeper) ([]byte, sdk.Error) {
|
||||||
|
num, err := strconv.ParseInt(path[1], 10, 64)
|
||||||
|
if err != nil {
|
||||||
|
panic("could not unmarshall block number: " + err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
bloom := keeper.GetBlockBloomMapping(ctx, num)
|
||||||
|
|
||||||
|
bRes := types.QueryBloomFilter{Bloom: bloom}
|
||||||
|
res, err := codec.MarshalJSONIndent(keeper.cdc, bRes)
|
||||||
|
if err != nil {
|
||||||
|
panic("could not marshal result to JSON: " + err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
return res, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func queryTxLogs(ctx sdk.Context, path []string, keeper Keeper) ([]byte, sdk.Error) {
|
||||||
|
txHash := ethcmn.HexToHash(path[1])
|
||||||
|
logs := keeper.GetLogs(ctx, txHash)
|
||||||
|
|
||||||
|
bRes := types.QueryTxLogs{Logs: logs}
|
||||||
|
res, err := codec.MarshalJSONIndent(keeper.cdc, bRes)
|
||||||
|
if err != nil {
|
||||||
|
panic("could not marshal result to JSON: " + err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
return res, nil
|
||||||
|
}
|
||||||
|
@ -6,9 +6,12 @@ import (
|
|||||||
"math/big"
|
"math/big"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"github.com/cosmos/cosmos-sdk/codec"
|
||||||
"github.com/cosmos/ethermint/crypto"
|
"github.com/cosmos/ethermint/crypto"
|
||||||
"github.com/cosmos/ethermint/utils"
|
"github.com/cosmos/ethermint/utils"
|
||||||
|
"github.com/ethereum/go-ethereum/common"
|
||||||
ethcmn "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/rlp"
|
"github.com/ethereum/go-ethereum/rlp"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
)
|
)
|
||||||
@ -174,3 +177,38 @@ func TestMarshalAndUnmarshalData(t *testing.T) {
|
|||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.Equal(t, e, *e2)
|
require.Equal(t, e, *e2)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestMarshalAndUnmarshalLogs(t *testing.T) {
|
||||||
|
var cdc = codec.New()
|
||||||
|
|
||||||
|
logs := []*ethtypes.Log{
|
||||||
|
{
|
||||||
|
Address: common.BytesToAddress([]byte{0x11}),
|
||||||
|
TxHash: common.HexToHash("0x01"),
|
||||||
|
// May need to find workaround since Topics is required to unmarshal from JSON
|
||||||
|
Topics: []common.Hash{},
|
||||||
|
Removed: true,
|
||||||
|
},
|
||||||
|
{Address: common.BytesToAddress([]byte{0x01, 0x11}), Topics: []common.Hash{}},
|
||||||
|
}
|
||||||
|
|
||||||
|
raw, err := codec.MarshalJSONIndent(cdc, logs)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
var logs2 []*ethtypes.Log
|
||||||
|
err = cdc.UnmarshalJSON(raw, &logs2)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
require.Len(t, logs2, 2)
|
||||||
|
require.Equal(t, logs[0].Address, logs2[0].Address)
|
||||||
|
require.Equal(t, logs[0].TxHash, logs2[0].TxHash)
|
||||||
|
require.True(t, logs[0].Removed)
|
||||||
|
|
||||||
|
emptyLogs := []*ethtypes.Log{}
|
||||||
|
|
||||||
|
raw, err = codec.MarshalJSONIndent(cdc, emptyLogs)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
err = cdc.UnmarshalJSON(raw, &logs2)
|
||||||
|
require.NoError(t, err)
|
||||||
|
}
|
||||||
|
@ -1,5 +1,11 @@
|
|||||||
package types
|
package types
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
ethtypes "github.com/ethereum/go-ethereum/core/types"
|
||||||
|
)
|
||||||
|
|
||||||
// QueryResProtocolVersion is response type for protocol version query
|
// QueryResProtocolVersion is response type for protocol version query
|
||||||
type QueryResProtocolVersion struct {
|
type QueryResProtocolVersion struct {
|
||||||
Version string `json:"version"`
|
Version string `json:"version"`
|
||||||
@ -53,3 +59,21 @@ type QueryResNonce struct {
|
|||||||
func (q QueryResNonce) String() string {
|
func (q QueryResNonce) String() string {
|
||||||
return string(q.Nonce)
|
return string(q.Nonce)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// QueryTxLogs is response type for tx logs query
|
||||||
|
type QueryTxLogs struct {
|
||||||
|
Logs []*ethtypes.Log `json:"logs"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (q QueryTxLogs) String() string {
|
||||||
|
return string(fmt.Sprintf("%+v", q.Logs))
|
||||||
|
}
|
||||||
|
|
||||||
|
// QueryBloomFilter is response type for tx logs query
|
||||||
|
type QueryBloomFilter struct {
|
||||||
|
Bloom ethtypes.Bloom `json:"bloom"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (q QueryBloomFilter) String() string {
|
||||||
|
return string(q.Bloom.Bytes())
|
||||||
|
}
|
||||||
|
@ -6,6 +6,7 @@ import (
|
|||||||
|
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
"github.com/ethereum/go-ethereum/core"
|
"github.com/ethereum/go-ethereum/core"
|
||||||
|
ethtypes "github.com/ethereum/go-ethereum/core/types"
|
||||||
"github.com/ethereum/go-ethereum/core/vm"
|
"github.com/ethereum/go-ethereum/core/vm"
|
||||||
|
|
||||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||||
@ -23,10 +24,11 @@ type StateTransition struct {
|
|||||||
Payload []byte
|
Payload []byte
|
||||||
Csdb *CommitStateDB
|
Csdb *CommitStateDB
|
||||||
ChainID *big.Int
|
ChainID *big.Int
|
||||||
|
THash *common.Hash
|
||||||
}
|
}
|
||||||
|
|
||||||
// TransitionCSDB performs an evm state transition from a transaction
|
// TransitionCSDB performs an evm state transition from a transaction
|
||||||
func (st StateTransition) TransitionCSDB(ctx sdk.Context) sdk.Result {
|
func (st StateTransition) TransitionCSDB(ctx sdk.Context) (sdk.Result, *big.Int) {
|
||||||
contractCreation := st.Recipient == nil
|
contractCreation := st.Recipient == nil
|
||||||
|
|
||||||
// Create context for evm
|
// Create context for evm
|
||||||
@ -61,7 +63,7 @@ func (st StateTransition) TransitionCSDB(ctx sdk.Context) sdk.Result {
|
|||||||
|
|
||||||
// handle errors
|
// handle errors
|
||||||
if vmerr != nil {
|
if vmerr != nil {
|
||||||
return emint.ErrVMExecution(vmerr.Error()).Result()
|
return emint.ErrVMExecution(vmerr.Error()).Result(), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Refund remaining gas from tx (Check these values and ensure gas is being consumed correctly)
|
// Refund remaining gas from tx (Check these values and ensure gas is being consumed correctly)
|
||||||
@ -74,7 +76,19 @@ func (st StateTransition) TransitionCSDB(ctx sdk.Context) sdk.Result {
|
|||||||
|
|
||||||
// TODO: Consume gas from sender
|
// TODO: Consume gas from sender
|
||||||
|
|
||||||
return sdk.Result{Data: addr.Bytes(), GasUsed: st.GasLimit - leftOverGas}
|
// Generate bloom filter to be saved in tx receipt data
|
||||||
|
bloomInt := big.NewInt(0)
|
||||||
|
var bloomFilter ethtypes.Bloom
|
||||||
|
if st.THash != nil {
|
||||||
|
logs := st.Csdb.GetLogs(*st.THash)
|
||||||
|
bloomInt = ethtypes.LogsBloom(logs)
|
||||||
|
bloomFilter = ethtypes.BytesToBloom(bloomInt.Bytes())
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: coniditionally add either/ both of these to return data
|
||||||
|
returnData := append(addr.Bytes(), bloomFilter.Bytes()...)
|
||||||
|
|
||||||
|
return sdk.Result{Data: returnData, GasUsed: st.GasLimit - leftOverGas}, bloomInt
|
||||||
}
|
}
|
||||||
|
|
||||||
func refundGas(
|
func refundGas(
|
||||||
|
Loading…
Reference in New Issue
Block a user