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

[wip] Fix nonce handling for failed tx #1773

Draft
wants to merge 2 commits into
base: main
Choose a base branch
from
Draft
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
2 changes: 0 additions & 2 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,6 @@ require (
github.com/fzipp/gocyclo v0.5.1 // indirect
github.com/gballet/go-libpcsclite v0.0.0-20190607065134-2772fd86a8ff // indirect
github.com/gballet/go-verkle v0.1.1-0.20231031103413-a67434b50f46 // indirect
github.com/ghodss/yaml v1.0.0 // indirect
github.com/go-critic/go-critic v0.6.3 // indirect
github.com/go-kit/kit v0.12.0 // indirect
github.com/go-kit/log v0.2.1 // indirect
Expand Down Expand Up @@ -173,7 +172,6 @@ require (
github.com/gostaticanalysis/nilerr v0.1.1 // indirect
github.com/grpc-ecosystem/go-grpc-middleware v1.3.0 // indirect
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 // indirect
github.com/grpc-ecosystem/grpc-gateway/v2 v2.20.0 // indirect
github.com/gsterjov/go-libsecret v0.0.0-20161001094733-a6f4afe4910c // indirect
github.com/hashicorp/errwrap v1.0.0 // indirect
github.com/hashicorp/go-bexpr v0.1.10 // indirect
Expand Down
3 changes: 0 additions & 3 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -457,7 +457,6 @@ github.com/gballet/go-verkle v0.1.1-0.20231031103413-a67434b50f46 h1:BAIP2Gihuqh
github.com/gballet/go-verkle v0.1.1-0.20231031103413-a67434b50f46/go.mod h1:QNpY22eby74jVhqH4WhDLDwxc/vqsern6pW+u2kbkpc=
github.com/getkin/kin-openapi v0.53.0/go.mod h1:7Yn5whZr5kJi6t+kShccXS8ae1APpYTW6yheSwk8Yi4=
github.com/ghemawat/stream v0.0.0-20171120220530-696b145b53b9/go.mod h1:106OIgooyS7OzLDOpUGgm9fA3bQENb/cFSyyBmMoJDs=
github.com/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk=
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
github.com/gin-contrib/sse v0.0.0-20190301062529-5545eab6dad3/go.mod h1:VJ0WA2NBN22VlZ2dKZQPAPnyWw5XTlK1KymzLKsr59s=
github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE=
Expand Down Expand Up @@ -766,8 +765,6 @@ github.com/grpc-ecosystem/grpc-gateway v1.9.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t
github.com/grpc-ecosystem/grpc-gateway v1.12.1/go.mod h1:8XEsbTttt/W+VvjtQhLACqCisSPWTxCZ7sBRjU6iH9c=
github.com/grpc-ecosystem/grpc-gateway v1.16.0 h1:gmcG1KaJ57LophUzW0Hy8NmPhnMZb4M0+kPpLofRdBo=
github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw=
github.com/grpc-ecosystem/grpc-gateway/v2 v2.20.0 h1:bkypFPDjIYGfCYD5mRBvpqxfYX1YCS1PXdKYWi8FsN0=
github.com/grpc-ecosystem/grpc-gateway/v2 v2.20.0/go.mod h1:P+Lt/0by1T8bfcF3z737NnSbmxQAppXMRziHUxPOC8k=
github.com/gsterjov/go-libsecret v0.0.0-20161001094733-a6f4afe4910c h1:6rhixN/i8ZofjG1Y75iExal34USq5p+wiN1tpie8IrU=
github.com/gsterjov/go-libsecret v0.0.0-20161001094733-a6f4afe4910c/go.mod h1:NMPJylDgVpX0MLRlPy15sqSwOFv/U1GZ2m21JhFfek0=
github.com/guptarohit/asciigraph v0.5.5/go.mod h1:dYl5wwK4gNsnFf9Zp+l06rFiDZ5YtXM6x7SRWZ3KGag=
Expand Down
28 changes: 19 additions & 9 deletions occ_tests/messages/test_msgs.go
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ func EVMTransferNonConflicting(tCtx *utils.TestContext, count int) []*utils.Test
var msgs []*utils.TestMessage
for i := 0; i < count; i++ {
testAcct := utils.NewSigner()
msgs = append(msgs, evmTransfer(testAcct, testAcct.EvmAddress, "EVMTransferNonConflicting"))
msgs = append(msgs, evmTransfer(testAcct, testAcct.EvmAddress, "EVMTransferNonConflicting", big.NewInt(1), 0))
}
return msgs
}
Expand All @@ -73,22 +73,31 @@ func EVMTransferConflicting(tCtx *utils.TestContext, count int) []*utils.TestMes
var msgs []*utils.TestMessage
for i := 0; i < count; i++ {
testAcct := utils.NewSigner()
msgs = append(msgs, evmTransfer(testAcct, tCtx.TestAccounts[0].EvmAddress, "EVMTransferConflicting"))
msgs = append(msgs, evmTransfer(testAcct, tCtx.TestAccounts[0].EvmAddress, "EVMTransferConflicting", big.NewInt(1), 0))
}
return msgs
}

func EVMTransferWithAmount(tCtx *utils.TestContext, amount *big.Int, count int) []*utils.TestMessage {
var msgs []*utils.TestMessage
testAcct := utils.NewSigner()
for i := 0; i < count; i++ {
msgs = append(msgs, evmTransfer(testAcct, tCtx.TestAccounts[0].EvmAddress, "EVMTransferOutOfFunds", amount, uint64(i)))
}
return msgs
}

// EVMTransferNonConflicting generates a list of EVM transfer messages that do not conflict with each other
// each message will have a brand new address
func evmTransfer(testAcct utils.TestAcct, to common.Address, scenario string) *utils.TestMessage {
func evmTransfer(testAcct utils.TestAcct, to common.Address, scenario string, amount *big.Int, nonce uint64) *utils.TestMessage {
signedTx, err := ethtypes.SignTx(ethtypes.NewTx(&ethtypes.DynamicFeeTx{
GasFeeCap: new(big.Int).SetUint64(1000000000000),
GasTipCap: new(big.Int).SetUint64(1000000000000),
Gas: 21000,
ChainID: big.NewInt(config.DefaultChainID),
To: &to,
Value: big.NewInt(1),
Nonce: 0,
Value: amount,
Nonce: nonce,
}), testAcct.EvmSigner, testAcct.EvmPrivateKey)

if err != nil {
Expand All @@ -106,10 +115,11 @@ func evmTransfer(testAcct utils.TestAcct, to common.Address, scenario string) *u
}

return &utils.TestMessage{
Msg: msg,
IsEVM: true,
EVMSigner: testAcct,
Type: scenario,
EVMTransaction: signedTx,
Msg: msg,
IsEVM: true,
EVMSigner: testAcct,
Type: scenario,
}
}

Expand Down
81 changes: 75 additions & 6 deletions occ_tests/occ_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,50 @@ package occ

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

"github.com/cosmos/cosmos-sdk/server/config"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/ethereum/go-ethereum/common"
"github.com/sei-protocol/sei-chain/occ_tests/messages"
"github.com/sei-protocol/sei-chain/occ_tests/utils"
"github.com/stretchr/testify/require"
"github.com/tendermint/tendermint/abci/types"
)

func assertReceiptStatuses(t *testing.T, tc *utils.TestContext, results []*types.ExecTxResult, txs []*utils.TestMessage) {
for i, tx := range txs {
if tx.IsEVM {
r, err := tc.TestApp.EvmKeeper.GetTransientReceipt(tc.Ctx, tx.EVMTransaction.Hash())
require.NoError(t, err)
if results[i].Code == 0 {
require.Equal(t, uint32(1), r.Status, "EVM transaction should have a successful receipt")
} else {
require.Equal(t, uint32(0), r.Status, "EVM transaction should have a failed receipt")
}
}
}
}

func assertNonces(t *testing.T, tc *utils.TestContext, txs []*utils.TestMessage) {
nonces := make(map[common.Address]uint64)
for _, tx := range txs {
if tx.IsEVM {
highest, _ := nonces[tx.EVMSigner.EvmAddress]
if tx.EVMTransaction.Nonce() > highest {
nonces[tx.EVMSigner.EvmAddress] = tx.EVMTransaction.Nonce()
}
}
}
for addr, latestNonce := range nonces {
nonce := tc.TestApp.EvmKeeper.GetNonce(tc.Ctx, addr)
require.Equal(t, latestNonce+1, nonce, "Nonce does not match for address %s", addr)
}
}

func assertEqualState(t *testing.T, expectedCtx sdk.Context, actualCtx sdk.Context, testName string) {
expectedStoreKeys := expectedCtx.MultiStore().StoreKeys()
actualStoreKeys := actualCtx.MultiStore().StoreKeys()
Expand Down Expand Up @@ -79,6 +111,13 @@ func assertExecTxResultCode(t *testing.T, expected, actual []*types.ExecTxResult
}
}

func assertSameResultCodes(t *testing.T, expected, actual []*types.ExecTxResult, testName string) {
require.Equal(t, len(expected), len(actual), testName)
for i, e := range expected {
require.Equal(t, e.Code, actual[i].Code, "%s: Expected code %d, got %d", testName, e.Code, e.Code)
}
}

// assertEqualExecTxResults checks if both slices have the same transaction results, regardless of order.
func assertEqualExecTxResults(t *testing.T, expected, actual []*types.ExecTxResult, testName string) {
require.Equal(t, len(expected), len(actual), "%s: Number of transaction results do not match", testName)
Expand All @@ -101,12 +140,14 @@ func assertEqualExecTxResults(t *testing.T, expected, actual []*types.ExecTxResu
// between both parallel and sequential executions
func TestParallelTransactions(t *testing.T) {
runs := 3

tests := []struct {
name string
runs int
shuffle bool
before func(tCtx *utils.TestContext)
txs func(tCtx *utils.TestContext) []*utils.TestMessage
name string
runs int
shuffle bool
expectFail bool
before func(tCtx *utils.TestContext)
txs func(tCtx *utils.TestContext) []*utils.TestMessage
}{
{
name: "Test wasm instantiations",
Expand Down Expand Up @@ -153,6 +194,20 @@ func TestParallelTransactions(t *testing.T) {
)
},
},
{
name: "Test evm out of funds",
runs: 1,
expectFail: true,
txs: func(tCtx *utils.TestContext) []*utils.TestMessage {
largeAmt := big.NewInt(0)
largeAmt.SetString("2500000000000000000000000000000", 10)

return utils.JoinMsgs(
// will produce one success, one out of funds and one nonce-too-high
messages.EVMTransferWithAmount(tCtx, largeAmt, 3),
)
},
},
{
name: "Test combinations",
runs: runs,
Expand Down Expand Up @@ -199,10 +254,24 @@ func TestParallelTransactions(t *testing.T) {
require.NoError(t, pErr, tt.name)
require.Len(t, pResults, len(txs))

assertExecTxResultCode(t, sResults, pResults, 0, tt.name)
if !tt.expectFail {
// should be zero (so if it fails on both this will discover it)
assertExecTxResultCode(t, sResults, pResults, 0, tt.name)
}

// should match synchronous & parallel results
assertSameResultCodes(t, sResults, pResults, tt.name)
assertEqualEvents(t, sEvts, pEvts, tt.name)
assertEqualExecTxResults(t, sResults, pResults, tt.name)
assertEqualState(t, sCtx.Ctx, pCtx.Ctx, tt.name)

// should have correct receipt status
assertReceiptStatuses(t, sCtx, sResults, txs)
assertReceiptStatuses(t, pCtx, pResults, txs)

// should always update nonce
assertNonces(t, pCtx, txs)
assertNonces(t, sCtx, txs)
}
})
}
Expand Down
9 changes: 5 additions & 4 deletions occ_tests/utils/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,10 +44,11 @@ var ignoredStoreKeys = map[string]struct{}{
}

type TestMessage struct {
Msg sdk.Msg
Type string
EVMSigner TestAcct
IsEVM bool
EVMTransaction *ethtypes.Transaction
Msg sdk.Msg
Type string
EVMSigner TestAcct
IsEVM bool
}

type TestContext struct {
Expand Down
Loading