Files
coreth/plugin/evm/gossiper_eth_gossiping_test.go

146 lines
3.3 KiB
Go

// Copyright (C) 2019-2025, Lux Industries, Inc. All rights reserved.
// See the file LICENSE for licensing terms.
//go:build ignore
// +build ignore
// TODO: Depends on vm_test.go fixtures (newVM, testVMConfig, etc.)
package evm
import (
"context"
"crypto/ecdsa"
"encoding/json"
"math/big"
"strings"
"sync"
"testing"
"time"
"github.com/luxfi/ids"
"github.com/luxfi/math/set"
"github.com/luxfi/warp"
"github.com/luxfi/crypto"
"github.com/luxfi/geth/common"
"github.com/stretchr/testify/assert"
"github.com/luxfi/coreth/core"
"github.com/luxfi/coreth/params"
"github.com/luxfi/geth/core/types"
)
func fundAddressByGenesis(addrs []common.Address) (string, error) {
balance := big.NewInt(0xffffffffffffff)
genesis := &core.Genesis{
Difficulty: common.Big0,
GasLimit: uint64(5000000),
}
funds := make(map[common.Address]types.Account)
for _, addr := range addrs {
funds[addr] = types.Account{
Balance: balance,
}
}
genesis.Alloc = funds
genesis.Config = params.TestChainConfig
bytes, err := json.Marshal(genesis)
return string(bytes), err
}
func getValidEthTxs(key *ecdsa.PrivateKey, count int, gasPrice *big.Int) []*types.Transaction {
res := make([]*types.Transaction, count)
to := common.Address{}
amount := big.NewInt(0)
gasLimit := uint64(37000)
for i := 0; i < count; i++ {
tx, _ := types.SignTx(
types.NewTransaction(
uint64(i),
to,
amount,
gasLimit,
gasPrice,
[]byte(strings.Repeat("aaaaaaaaaa", 100))),
types.HomesteadSigner{}, key)
tx.SetTime(time.Now().Add(-1 * time.Minute))
res[i] = tx
}
return res
}
// show that a geth tx discovered from gossip is requested to the same node that
// gossiped it
func TestMempoolEthTxsAppGossipHandling(t *testing.T) {
assert := assert.New(t)
key, err := crypto.GenerateKey()
assert.NoError(err)
cryptoAddr := crypto.PubkeyToAddress(key.PublicKey)
var addr common.Address
copy(addr[:], cryptoAddr[:])
genesisJSON, err := fundAddressByGenesis([]common.Address{addr})
assert.NoError(err)
tvm := newVM(t, testVMConfig{
genesisJSON: genesisJSON,
})
defer func() {
err := tvm.vm.Shutdown(context.Background())
assert.NoError(err)
}()
tvm.vm.txPool.SetGasTip(common.Big1)
tvm.vm.txPool.SetMinFee(common.Big0)
var (
wg sync.WaitGroup
txRequested bool
)
tvm.appSender.SendRequestF = func(context.Context, set.Set[ids.NodeID], uint32, []byte) error {
txRequested = true
return nil
}
wg.Add(1)
tvm.appSender.SendGossipF = func(context.Context, warp.SendConfig, []byte) error {
wg.Done()
return nil
}
// prepare a tx
tx := getValidEthTxs(key, 1, common.Big1)[0]
// Txs must be submitted over the API to be included in push gossip.
// (i.e., txs received via p2p are not included in push gossip)
err = tvm.vm.eth.APIBackend.SendTx(context.Background(), tx)
assert.NoError(err)
assert.False(txRequested, "tx should not be requested")
// wait for transaction to be re-gossiped
attemptAwait(t, &wg, 5*time.Second)
}
func attemptAwait(t *testing.T, wg *sync.WaitGroup, delay time.Duration) {
ticker := make(chan struct{})
// Wait for [wg] and then close [ticket] to indicate that
// the wait group has finished.
go func() {
wg.Wait()
close(ticker)
}()
select {
case <-time.After(delay):
t.Fatal("Timed out waiting for wait group to complete")
case <-ticker:
// The wait group completed without issue
}
}