Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

exclude synthetic logs from eth endpoints #1875

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
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
1 change: 1 addition & 0 deletions .github/workflows/integration-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ on:
- main
- seiv2
- evm
- release/**

defaults:
run:
Expand Down
34 changes: 29 additions & 5 deletions contracts/test/ERC20toCW20PointerTest.js
Original file line number Diff line number Diff line change
Expand Up @@ -84,30 +84,32 @@ describe("ERC20 to CW20 Pointer", function () {
expect(await pointer.allowance(accounts[0].evmAddress, accounts[1].evmAddress)).to.equal(0);
});
});

describe("transfer()", function () {
it("should transfer", async function () {
it.only("should transfer", async function () {
let sender = accounts[0];
let recipient = accounts[1];

expect(await pointer.balanceOf(sender.evmAddress)).to.equal(balances.account0);
expect(await pointer.balanceOf(recipient.evmAddress)).to.equal(balances.account1);

const blockNumber = await ethers.provider.getBlockNumber();
// const blockNumber = await ethers.provider.getBlockNumber();
const tx = await pointer.transfer(recipient.evmAddress, 1);
await tx.wait();
const receipt = await tx.wait();
const blockNumber = receipt.blockNumber;

expect(await pointer.balanceOf(sender.evmAddress)).to.equal(balances.account0-1);
expect(await pointer.balanceOf(recipient.evmAddress)).to.equal(balances.account1+1);

console.log("blockNumber", blockNumber);

// check logs
const filter = {
fromBlock: '0x' + blockNumber.toString(16),
toBlock: 'latest',
address: await pointer.getAddress(),
topics: [ethers.id("Transfer(address,address,uint256)")]
};
// send via eth_ endpoint - synthetic event doesn't show up
// send via eth_ endpoint - the ERC20 Pointer contract does not emit Transfer events so should have no logs
const ethlogs = await ethers.provider.send('eth_getLogs', [filter]);
expect(ethlogs.length).to.equal(0);

Expand All @@ -122,6 +124,28 @@ describe("ERC20 to CW20 Pointer", function () {

const cleanupTx = await pointer.connect(recipient.signer).transfer(sender.evmAddress, 1);
await cleanupTx.wait();

// check eth_getBlockByNumber vs sei_getBlockByNumber
const ethBlock = await ethers.provider.send('eth_getBlockByNumber', ['0x' + blockNumber.toString(16), false]);
const seiBlock = await ethers.provider.send('sei_getBlockByNumber', ['0x' + blockNumber.toString(16), false]);
expect(ethBlock.transactions.length).to.equal(1);
expect(seiBlock.transactions.length).to.equal(1);

// check eth_getBlockByReceipts vs sei_getBlockByReceipts
const ethReceipts = await ethers.provider.send('eth_getBlockReceipts', ['0x' + blockNumber.toString(16)]);
const seiReceipts = await ethers.provider.send('sei_getBlockReceipts', ['0x' + blockNumber.toString(16)]);
expect(ethReceipts.length).to.equal(1);
expect(seiReceipts.length).to.equal(1);

// check eth_getTransactionReceipt vs sei_getTransactionReceipt
const ethTx = await ethers.provider.send('eth_getTransactionReceipt', [receipt.hash]);
const seiTx = await ethers.provider.send('sei_getTransactionReceipt', [receipt.hash]);
expect(ethTx.logs.length).to.equal(0); // synthetic event doesn't show up
expect(seiTx.logs.length).to.equal(1); // synthetic event shows up

// check eth_getTransactionByHash
const ethTxByHash = await ethers.provider.send('eth_getTransactionByHash', [tx.hash]);
expect(ethTxByHash).to.not.be.null;
});

it("should fail transfer() if sender has insufficient balance", async function () {
Expand Down
28 changes: 24 additions & 4 deletions contracts/test/ERC721toCW721PointerTest.js
Original file line number Diff line number Diff line change
Expand Up @@ -114,9 +114,12 @@ describe("ERC721 to CW721 Pointer", function () {
it("transfer from", async function () {
// accounts[0] should transfer token id 2 to accounts[1]
await mine(pointerAcc0.approve(accounts[1].evmAddress, 2));
const blockNumber = await ethers.provider.getBlockNumber();

transferTxResp = await pointerAcc1.transferFrom(accounts[0].evmAddress, accounts[1].evmAddress, 2);
await transferTxResp.wait();
const receipt = await transferTxResp.wait();

const blockNumber = receipt.blockNumber;

const filter = {
fromBlock: '0x' + blockNumber.toString(16),
toBlock: 'latest',
Expand All @@ -138,6 +141,22 @@ describe("ERC721 to CW721 Pointer", function () {
const balance1 = await pointerAcc0.balanceOf(accounts[1].evmAddress);
expect(balance1).to.equal(2);

// do same for eth_getBlockReceipts and sei_getBlockReceipts
const ethBlockReceipts = await ethers.provider.send('eth_getBlockReceipts', ['0x' + blockNumber.toString(16)]);
expect(ethBlockReceipts.length).to.equal(1);
const seiBlockReceipts = await ethers.provider.send('sei_getBlockReceipts', ['0x' + blockNumber.toString(16)]);
expect(seiBlockReceipts.length).to.equal(1);

// check eth_getTransactionReceipt vs sei_getTransactionReceipt
const ethTx = await ethers.provider.send('eth_getTransactionReceipt', [receipt.hash]);
const seiTx = await ethers.provider.send('sei_getTransactionReceipt', [receipt.hash]);
expect(ethTx.logs.length).to.equal(0); // synthetic event doesn't show up
expect(seiTx.logs.length).to.equal(1); // synthetic event shows up

// check eth_getTransactionByHash
const ethTxByHash = await ethers.provider.send('eth_getTransactionByHash', [receipt.hash]);
expect(ethTxByHash).to.not.be.null;

// return token id 2 back to accounts[0] using safe transfer from
await mine(pointerAcc1.approve(accounts[0].evmAddress, 2));
await mine(pointerAcc1.safeTransferFrom(accounts[1].evmAddress, accounts[0].evmAddress, 2));
Expand All @@ -149,9 +168,10 @@ describe("ERC721 to CW721 Pointer", function () {
await expect(pointerAcc0.transferFrom(accounts[0].evmAddress, accounts[1].evmAddress, 3)).to.be.reverted;
});

it("set approval for all", async function () {
it.only("set approval for all", async function () {
const setApprovalForAllTxResp = await pointerAcc0.setApprovalForAll(accounts[1].evmAddress, true);
await setApprovalForAllTxResp.wait();
const receipt = await setApprovalForAllTxResp.wait();
console.log(receipt)
await expect(setApprovalForAllTxResp)
.to.emit(pointerAcc0, 'ApprovalForAll')
.withArgs(accounts[0].evmAddress, accounts[1].evmAddress, true);
Expand Down
1 change: 1 addition & 0 deletions contracts/test/lib.js
Original file line number Diff line number Diff line change
Expand Up @@ -425,6 +425,7 @@ async function executeOnAllNodes(command, interaction=`printf "12345678\\n"`){
}

async function execute(command, interaction=`printf "12345678\\n"`){
console.log("command = ", command)
if (await isDocker()) {
command = command.replace(/\.\.\//g, "/sei-protocol/sei-chain/");
command = command.replace("/sei-protocol/sei-chain//sei-protocol/sei-chain/", "/sei-protocol/sei-chain/")
Expand Down
7 changes: 2 additions & 5 deletions evmrpc/block.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ type BlockAPI struct {
}

func NewBlockAPI(tmClient rpcclient.Client, k *keeper.Keeper, ctxProvider func(int64) sdk.Context, txConfig client.TxConfig, connectionType ConnectionType, namespace string) *BlockAPI {
return &BlockAPI{tmClient: tmClient, keeper: k, ctxProvider: ctxProvider, txConfig: txConfig, connectionType: connectionType, includeSyntheticTxs: shouldIncludeSynthetic(namespace)}
return &BlockAPI{tmClient: tmClient, keeper: k, ctxProvider: ctxProvider, txConfig: txConfig, connectionType: connectionType, namespace: namespace, includeSyntheticTxs: shouldIncludeSynthetic(namespace)}
}

func (a *BlockAPI) GetBlockTransactionCountByNumber(ctx context.Context, number rpc.BlockNumber) (result *hexutil.Uint, returnErr error) {
Expand Down Expand Up @@ -160,7 +160,7 @@ func (a *BlockAPI) GetBlockReceipts(ctx context.Context, blockNrOrHash rpc.Block
wg.Add(1)
go func(i int, hash common.Hash) {
defer wg.Done()
receipt, err := a.keeper.GetReceipt(a.ctxProvider(height), hash)
receipt, err := a.keeper.GetReceiptOptionalSyntheticLogs(a.ctxProvider(height), hash, a.includeSyntheticTxs)
if err != nil {
// When the transaction doesn't exist, skip it
if !strings.Contains(err.Error(), "not found") {
Expand All @@ -169,9 +169,6 @@ func (a *BlockAPI) GetBlockReceipts(ctx context.Context, blockNrOrHash rpc.Block
mtx.Unlock()
}
} else {
if !a.includeSyntheticTxs && len(receipt.Logs) > 0 && receipt.Logs[0].Synthetic {
return
}
encodedReceipt, err := encodeReceipt(receipt, a.txConfig.TxDecoder(), block, func(h common.Hash) bool {
_, err := a.keeper.GetReceipt(a.ctxProvider(height), h)
return err == nil
Expand Down
15 changes: 10 additions & 5 deletions evmrpc/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,9 +45,6 @@ func NewEVMHTTPServer(
sendAPI := NewSendAPI(tmClient, txConfig, &SendConfig{slow: config.Slow}, k, ctxProvider, homeDir, simulateConfig, ConnectionTypeHTTP)
ctx := ctxProvider(LatestCtxHeight)

txAPI := NewTransactionAPI(tmClient, k, ctxProvider, txConfig, homeDir, ConnectionTypeHTTP)
// filterAPI := NewFilterAPI(tmClient, &LogFetcher{tmClient: tmClient, k: k, ctxProvider: ctxProvider}, &FilterConfig{timeout: config.FilterTimeout, maxLog: config.MaxLogNoBlock, maxBlock: config.MaxBlocksForLog}, ConnectionTypeHTTP)

apis := []rpc.API{
{
Namespace: "echo",
Expand All @@ -63,7 +60,11 @@ func NewEVMHTTPServer(
},
{
Namespace: "eth",
Service: txAPI,
Service: NewTransactionAPI(tmClient, k, ctxProvider, txConfig, homeDir, ConnectionTypeHTTP, "eth"),
},
{
Namespace: "sei",
Service: NewTransactionAPI(tmClient, k, ctxProvider, txConfig, homeDir, ConnectionTypeHTTP, "sei"),
},
{
Namespace: "eth",
Expand Down Expand Up @@ -160,7 +161,11 @@ func NewEVMWebSocketServer(
},
{
Namespace: "eth",
Service: NewTransactionAPI(tmClient, k, ctxProvider, txConfig, homeDir, ConnectionTypeWS),
Service: NewTransactionAPI(tmClient, k, ctxProvider, txConfig, homeDir, ConnectionTypeWS, "eth"),
},
{
Namespace: "sei",
Service: NewTransactionAPI(tmClient, k, ctxProvider, txConfig, homeDir, ConnectionTypeWS, "sei"),
},
{
Namespace: "eth",
Expand Down
46 changes: 35 additions & 11 deletions evmrpc/tx.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
"context"
"crypto/sha256"
"errors"
"fmt"
"math/big"
"strings"
"time"
Expand All @@ -28,23 +29,25 @@
const UnconfirmedTxQueryPerPage = 30

type TransactionAPI struct {
tmClient rpcclient.Client
keeper *keeper.Keeper
ctxProvider func(int64) sdk.Context
txConfig client.TxConfig
homeDir string
connectionType ConnectionType
tmClient rpcclient.Client
keeper *keeper.Keeper
ctxProvider func(int64) sdk.Context
txConfig client.TxConfig
homeDir string
connectionType ConnectionType
namespace string
includeSynthetic bool
}

func NewTransactionAPI(tmClient rpcclient.Client, k *keeper.Keeper, ctxProvider func(int64) sdk.Context, txConfig client.TxConfig, homeDir string, connectionType ConnectionType) *TransactionAPI {
return &TransactionAPI{tmClient: tmClient, keeper: k, ctxProvider: ctxProvider, txConfig: txConfig, homeDir: homeDir, connectionType: connectionType}
func NewTransactionAPI(tmClient rpcclient.Client, k *keeper.Keeper, ctxProvider func(int64) sdk.Context, txConfig client.TxConfig, homeDir string, connectionType ConnectionType, namespace string) *TransactionAPI {
return &TransactionAPI{tmClient: tmClient, keeper: k, ctxProvider: ctxProvider, txConfig: txConfig, homeDir: homeDir, connectionType: connectionType, namespace: namespace, includeSynthetic: shouldIncludeSynthetic(namespace)}
}

func (t *TransactionAPI) GetTransactionReceipt(ctx context.Context, hash common.Hash) (result map[string]interface{}, returnErr error) {
startTime := time.Now()
defer recordMetrics("eth_getTransactionReceipt", t.connectionType, startTime, returnErr == nil)
defer recordMetrics(fmt.Sprintf("%s_getTransactionReceipt", t.namespace), t.connectionType, startTime, returnErr == nil)
sdkctx := t.ctxProvider(LatestCtxHeight)
receipt, err := t.keeper.GetReceipt(sdkctx, hash)
receipt, err := t.keeper.GetReceiptOptionalSyntheticLogs(sdkctx, hash, t.includeSynthetic)
if err != nil {
if strings.Contains(err.Error(), "not found") {
// When the transaction doesn't exist, the RPC method should return JSON null
Expand All @@ -65,6 +68,9 @@
}

func (t *TransactionAPI) GetVMError(hash common.Hash) (result string, returnErr error) {
if t.namespace != "eth" {

Check failure on line 71 in evmrpc/tx.go

View workflow job for this annotation

GitHub Actions / lint

string `eth` has 8 occurrences, make it a constant (goconst)
return "", errors.New("only supported for eth namespace")
}
startTime := time.Now()
defer recordMetrics("eth_getVMError", t.connectionType, startTime, true)
receipt, err := t.keeper.GetReceipt(t.ctxProvider(LatestCtxHeight), hash)
Expand All @@ -75,6 +81,9 @@
}

func (t *TransactionAPI) GetTransactionByBlockNumberAndIndex(ctx context.Context, blockNr rpc.BlockNumber, index hexutil.Uint) (result *ethapi.RPCTransaction, returnErr error) {
if t.namespace != "eth" {
return nil, errors.New("only supported for eth namespace")
}
startTime := time.Now()
defer recordMetrics("eth_getTransactionByBlockNumberAndIndex", t.connectionType, startTime, returnErr == nil)
blockNumber, err := getBlockNumber(ctx, t.tmClient, blockNr)
Expand All @@ -89,6 +98,9 @@
}

func (t *TransactionAPI) GetTransactionByBlockHashAndIndex(ctx context.Context, blockHash common.Hash, index hexutil.Uint) (result *ethapi.RPCTransaction, returnErr error) {
if t.namespace != "eth" {
return nil, errors.New("only supported for eth namespace")
}
startTime := time.Now()
defer recordMetrics("eth_getTransactionByBlockHashAndIndex", t.connectionType, startTime, returnErr == nil)
block, err := blockByHash(ctx, t.tmClient, blockHash[:])
Expand All @@ -99,8 +111,11 @@
}

func (t *TransactionAPI) GetTransactionByHash(ctx context.Context, hash common.Hash) (result *ethapi.RPCTransaction, returnErr error) {
if t.namespace != "eth" {
return nil, errors.New("only supported for eth namespace")
}
startTime := time.Now()
defer recordMetrics("eth_getTransactionByHash", t.connectionType, startTime, returnErr == nil)
defer recordMetrics(fmt.Sprintf("%s_getTransactionByHash", t.namespace), t.connectionType, startTime, returnErr == nil)
sdkCtx := t.ctxProvider(LatestCtxHeight)
// first try get from mempool
for page := 1; page <= UnconfirmedTxQueryMaxPage; page++ {
Expand Down Expand Up @@ -149,6 +164,9 @@
}

func (t *TransactionAPI) GetTransactionErrorByHash(_ context.Context, hash common.Hash) (result string, returnErr error) {
if t.namespace != "eth" {
return "", errors.New("only supported for eth namespace")
}
startTime := time.Now()
defer recordMetrics("eth_getTransactionErrorByHash", t.connectionType, startTime, returnErr == nil)
receipt, err := t.keeper.GetReceipt(t.ctxProvider(LatestCtxHeight), hash)
Expand All @@ -162,6 +180,9 @@
}

func (t *TransactionAPI) GetTransactionCount(ctx context.Context, address common.Address, blockNrOrHash rpc.BlockNumberOrHash) (result *hexutil.Uint64, returnErr error) {
if t.namespace != "eth" {
return nil, errors.New("only supported for eth namespace")
}
startTime := time.Now()
defer recordMetrics("eth_getTransactionCount", t.connectionType, startTime, returnErr == nil)
sdkCtx := t.ctxProvider(LatestCtxHeight)
Expand Down Expand Up @@ -210,6 +231,9 @@
}

func (t *TransactionAPI) Sign(addr common.Address, data hexutil.Bytes) (result hexutil.Bytes, returnErr error) {
if t.namespace != "eth" {
return nil, errors.New("only supported for eth namespace")
}
startTime := time.Now()
defer recordMetrics("eth_sign", t.connectionType, startTime, returnErr == nil)
kb, err := getTestKeyring(t.homeDir)
Expand Down
2 changes: 1 addition & 1 deletion evmrpc/tx_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -214,7 +214,7 @@ func TestGetTransactionError(t *testing.T) {

func TestSign(t *testing.T) {
homeDir := t.TempDir()
txApi := evmrpc.NewTransactionAPI(nil, nil, nil, nil, homeDir, evmrpc.ConnectionTypeHTTP)
txApi := evmrpc.NewTransactionAPI(nil, nil, nil, nil, homeDir, evmrpc.ConnectionTypeHTTP, "eth")
infoApi := evmrpc.NewInfoAPI(nil, nil, nil, nil, homeDir, 1024, evmrpc.ConnectionTypeHTTP)
clientCtx := client.Context{}.WithViper("").WithHomeDir(homeDir)
clientCtx, err := config.ReadFromClientConfig(clientCtx)
Expand Down
17 changes: 17 additions & 0 deletions x/evm/keeper/receipt.go
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,23 @@ func (k *Keeper) GetReceipt(ctx sdk.Context, txHash common.Hash) (*types.Receipt
return &r, nil
}

func (k *Keeper) GetReceiptOptionalSyntheticLogs(ctx sdk.Context, txHash common.Hash, includeSynthetic bool) (*types.Receipt, error) {
receipt, err := k.GetReceipt(ctx, txHash)
if err != nil {
return nil, err
}
if !includeSynthetic {
filteredLogs := make([]*types.Log, 0, len(receipt.Logs))
for _, log := range receipt.Logs {
if !log.Synthetic {
filteredLogs = append(filteredLogs, log)
}
}
receipt.Logs = filteredLogs
}
return receipt, nil
}

// MockReceipt sets a data structure that stores EVM specific transaction metadata.
//
// this is currently used by a number of tests to set receipts at the moment
Expand Down
Loading