Skip to content
Merged
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
10 changes: 4 additions & 6 deletions vms/saevm/sae/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ load("@io_bazel_rules_go//go:def.bzl", "go_library")
load("//.bazel:defs.bzl", "go_test")

# gazelle:exclude accept_block_test.go
# gazelle:exclude worstcase_test.go

go_library(
name = "sae",
Expand Down Expand Up @@ -77,7 +78,6 @@ go_test(
"rpc_test.go",
"tx_test.go",
"vm_test.go",
"worstcase_test.go",
],
embed = [":sae"],
deps = [
Expand All @@ -104,15 +104,13 @@ go_test(
"//vms/saevm/gastime",
"//vms/saevm/hook",
"//vms/saevm/hook/hookstest",
"//vms/saevm/intmath",
"//vms/saevm/params",
"//vms/saevm/sae/rpc",
"//vms/saevm/saedb",
"//vms/saevm/saetest",
"//vms/saevm/saetest/escrow",
"//vms/saevm/txgossip/txgossiptest",
"//vms/saevm/types",
"//vms/saevm/worstcase",
"@com_github_arr4n_shed//testerr",
"@com_github_ava_labs_libevm//:libevm",
"@com_github_ava_labs_libevm//common",
Expand Down Expand Up @@ -145,7 +143,7 @@ go_test(
)

go_test(
name = "accept_block_test",
name = "flaky_tests",
srcs = [
"accept_block_test.go",
"always_test.go",
Expand All @@ -160,9 +158,9 @@ go_test(
"vm_test.go",
"worstcase_test.go",
],
args = ["-test.run=TestAcceptBlock"],
args = ["-test.run=TestAcceptBlock|TestWorstCase"],
embed = [":sae"],
env = {"SAEVM_TEST_ACCEPT_BLOCK": "1"},
env = {"SAEVM_TEST_FLAKY": "1"},
flaky = True,
deps = [
"//database",
Expand Down
4 changes: 2 additions & 2 deletions vms/saevm/sae/accept_block_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,8 @@ func TestAcceptBlock(t *testing.T) {
// TODO(JonathanOppenheimer): determine whether this test is actually flaky
// or whether there's a bug in the test. This test is enabled in Bazel and
// disabled in go test.
if os.Getenv("SAEVM_TEST_ACCEPT_BLOCK") == "" {
t.Skip("FLAKY: set SAEVM_TEST_ACCEPT_BLOCK to run")
if os.Getenv("SAEVM_TEST_FLAKY") == "" {
t.Skip("FLAKY: set SAEVM_TEST_FLAKY to run")
}

// We use a generous timeout because GC finalizers from previous tests take
Expand Down
42 changes: 30 additions & 12 deletions vms/saevm/sae/rpc_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -789,27 +789,45 @@ func TestGetReceipts(t *testing.T) {

timeOpt, vmTime := withVMTime(t, time.Unix(saeparams.TauSeconds, 0))
precompileOpt, unblock := withBlockingPrecompile(blockingPrecompile)
ctx, sut := newSUT(t, 1, timeOpt, precompileOpt)
ctx, sut := newSUT(t, 2, timeOpt, precompileOpt)
t.Cleanup(unblock)

var (
txs []*types.Transaction
want []*types.Receipt
)
for range 6 {
tx := sut.wallet.SetNonceAndSign(t, 0, &types.LegacyTx{
// The mempool cannot be relied on to mark a transaction as pending
// if there is already a pending transaction with the same account.
// To avoid this, we use two different accounts and price the
// transactions such that the builder will maintain ordering.
for range 3 {
tx1 := sut.wallet.SetNonceAndSign(t, 0, &types.LegacyTx{
To: &zeroAddr,
Gas: params.TxGas,
GasPrice: big.NewInt(1),
GasPrice: big.NewInt(2), // ensure this tx is first in block
Comment thread
JonathanOppenheimer marked this conversation as resolved.
})
txs = append(txs, tx)
want = append(want, &types.Receipt{
TxHash: tx.Hash(),
Status: types.ReceiptStatusSuccessful,
GasUsed: params.TxGas,
EffectiveGasPrice: big.NewInt(1),
Logs: []*types.Log{},
tx2 := sut.wallet.SetNonceAndSign(t, 1, &types.LegacyTx{
To: &zeroAddr,
Gas: params.TxGas,
GasPrice: big.NewInt(1),
})
txs = append(txs, tx1, tx2)
want = append(want, []*types.Receipt{
{
TxHash: tx1.Hash(),
Status: types.ReceiptStatusSuccessful,
GasUsed: params.TxGas,
EffectiveGasPrice: big.NewInt(2),
Logs: []*types.Log{},
},
{
TxHash: tx2.Hash(),
Status: types.ReceiptStatusSuccessful,
GasUsed: params.TxGas,
EffectiveGasPrice: big.NewInt(1),
Logs: []*types.Log{},
},
}...)
}

slice := func(t *testing.T, from, to int) (*blocks.Block, []*types.Receipt) {
Expand All @@ -834,7 +852,7 @@ func TestGetReceipts(t *testing.T) {
settled, wantSettled := slice(t, 2, 4)
vmTime.advanceToSettle(ctx, t, settled)
unsettled, wantUnsettled := slice(t, 4, 6)
require.NoError(t, unsettled.WaitUntilExecuted(ctx), "WaitUntilExecuted()")
require.NoErrorf(t, unsettled.WaitUntilExecuted(ctx), "%T.WaitUntilExecuted()", unsettled)

pending := sut.runConsensusLoop(t, sut.wallet.SetNonceAndSign(t, 0, &types.LegacyTx{
To: &blockingPrecompile,
Expand Down
13 changes: 9 additions & 4 deletions vms/saevm/sae/vm_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import (
"context"
"encoding/json"
"errors"
"flag"
"math/big"
"net/http/httptest"
"os"
Expand Down Expand Up @@ -64,9 +63,6 @@ import (
)

func TestMain(m *testing.M) {
createWorstCaseFuzzFlags(flag.CommandLine)
flag.Parse()

log.SetDefault(log.NewLogger(log.NewTerminalHandlerWithLevel(os.Stderr, log.LevelError, true)))

goleak.VerifyTestMain(
Expand Down Expand Up @@ -362,13 +358,22 @@ func (s *SUT) mustSendTx(tb testing.TB, txs ...*types.Transaction) {

// sendTxsAndWaitUntilPending sends all `txs` to the mempool, and waits for
// each to be marked as pending.
//
// WARNING: if there is a block executing concurrently with this method,
// the pending state of the transactions may not be accurately reflected,
// resulting in a timeout.
func (s *SUT) sendTxsAndWaitUntilPending(tb testing.TB, txs ...*types.Transaction) {
tb.Helper()

s.mustSendTx(tb, txs...)
s.waitUntilTxsPending(tb, txs...)
}

// waitUntilTxsPending waits until all `txs` are marked as pending in the mempool.
//
// WARNING: if there is a block executing concurrently with this method,
// the pending state of the transactions may not be accurately reflected,
// resulting in a timeout.
func (s *SUT) waitUntilTxsPending(tb testing.TB, txs ...*types.Transaction) {
tb.Helper()

Expand Down
26 changes: 21 additions & 5 deletions vms/saevm/sae/worstcase_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (
"math"
"math/big"
"math/rand/v2"
"os"
"runtime"
"testing"
"time"
Expand All @@ -31,7 +32,7 @@ import (
saeparams "github.com/ava-labs/avalanchego/vms/saevm/params"
)

var worstCaseFuzzFlags struct {
type worstCaseFlags struct {
numAccounts uint
balance uint256.Int
parallel uint
Expand All @@ -42,12 +43,13 @@ var worstCaseFuzzFlags struct {
rngSeed uint64
}

func createWorstCaseFuzzFlags(set *flag.FlagSet) {
Comment thread
alarso16 marked this conversation as resolved.
func parseWorstCaseFlags() *worstCaseFlags {
set := flag.NewFlagSet("worstcase", flag.ContinueOnError)
fs := &worstCaseFlags{}

name := func(n string) string {
return "worstcase.fuzz." + n
}
fs := &worstCaseFuzzFlags

set.UintVar(&fs.numAccounts, name("num_eoa"), 10, "Number of EOAs to send funds between")
set.TextVar(&fs.balance, name("eoa_balance"), uint256.NewInt(params.Ether), "Starting balance of EOAs")
set.UintVar(&fs.parallel, name("parallel"), uint(runtime.GOMAXPROCS(0)), "Number of parallel tests to run; defaults to GOMAXPROCS") //#nosec G115 -- Known to be positive
Expand All @@ -56,6 +58,12 @@ func createWorstCaseFuzzFlags(set *flag.FlagSet) {
set.Uint64Var(&fs.maxGasLimit, name("max_gas_limit"), 60e6, "Maximum gas limit per transaction (uniform distribution)")
set.Uint64Var(&fs.maxTxValue, name("max_tx_value"), params.Ether/1000, "Maximum tx value to send per transaction (uniform distribution)")
set.Uint64Var(&fs.rngSeed, name("rng_seed"), 0, "Seed for random-number generator; ignored if zero")

// Parse returns an error because the testing harness provides additional
// unregistered flags. [flag.ContinueOnError] allows the expected flags to
// be parsed anyways.
_ = set.Parse(os.Args[1:])
return fs
}

// A guzzler is both a [params.ChainConfigHooks] and [params.RulesHooks]. When
Expand Down Expand Up @@ -110,7 +118,15 @@ func (*guzzler) guzzle(env vm.PrecompileEnvironment, input []byte) ([]byte, erro
}

func TestWorstCase(t *testing.T) {
flags := worstCaseFuzzFlags
// TODO(alarso16): This test flakes due to a race in the legacypool. When
// a block executes, it sends an event to the pool, which causes an
// incorrect nonce update if the pool already had a pending transaction from
// the same account.
if os.Getenv("SAEVM_TEST_FLAKY") == "" {
t.Skip("FLAKY: set SAEVM_TEST_FLAKY to run")
}

flags := parseWorstCaseFlags()
t.Logf("Flags: %+v", flags)

guzzle := common.Address{'g', 'u', 'z', 'z', 'l', 'e'}
Expand Down
Loading