diff --git a/plugin/evm/block.go b/plugin/evm/block.go index c47fa02899..aa7ca8752d 100644 --- a/plugin/evm/block.go +++ b/plugin/evm/block.go @@ -175,7 +175,7 @@ func (b *Block) Reject(context.Context) error { log.Debug(fmt.Sprintf("Rejecting block %s (%s) at height %d", b.ID().Hex(), b.ID(), b.Height())) for _, tx := range b.atomicTxs { b.vm.mempool.RemoveTx(tx) - if err := b.vm.issueTx(tx, false /* set local to false when re-issuing */); err != nil { + if err := b.vm.mempool.AddTx(tx); err != nil { log.Debug("Failed to re-issue transaction in rejected block", "txID", tx.ID(), "err", err) } } diff --git a/plugin/evm/export_tx_test.go b/plugin/evm/export_tx_test.go index 319831c7d7..918cb711ef 100644 --- a/plugin/evm/export_tx_test.go +++ b/plugin/evm/export_tx_test.go @@ -59,7 +59,7 @@ func createExportTxOptions(t *testing.T, vm *VM, issuer chan engCommon.Message, t.Fatal(err) } - if err := vm.issueTx(importTx, true /*=local*/); err != nil { + if err := vm.mempool.AddLocalTx(importTx); err != nil { t.Fatal(err) } @@ -371,7 +371,7 @@ func TestExportTxEVMStateTransfer(t *testing.T) { t.Fatal(err) } - if err := vm.issueTx(tx, true /*=local*/); err != nil { + if err := vm.mempool.AddLocalTx(tx); err != nil { t.Fatal(err) } @@ -1726,7 +1726,7 @@ func TestNewExportTx(t *testing.T) { t.Fatal(err) } - if err := vm.issueTx(tx, true /*=local*/); err != nil { + if err := vm.mempool.AddLocalTx(tx); err != nil { t.Fatal(err) } @@ -1916,7 +1916,7 @@ func TestNewExportTxMulticoin(t *testing.T) { t.Fatal(err) } - if err := vm.issueTx(tx, false); err != nil { + if err := vm.mempool.AddTx(tx); err != nil { t.Fatal(err) } diff --git a/plugin/evm/gossip_mempool_test.go b/plugin/evm/gossip_mempool_test.go index b206219295..55435d37dd 100644 --- a/plugin/evm/gossip_mempool_test.go +++ b/plugin/evm/gossip_mempool_test.go @@ -92,7 +92,7 @@ func TestAtomicMempoolIterate(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { require := require.New(t) - m, err := NewMempool(ids.Empty, 10) + m, err := NewMempool(ids.Empty, 10, nil) require.NoError(err) for _, add := range tt.add { diff --git a/plugin/evm/gossiper.go b/plugin/evm/gossiper.go index 0f7d1a287d..712ee19415 100644 --- a/plugin/evm/gossiper.go +++ b/plugin/evm/gossiper.go @@ -465,7 +465,7 @@ func (h *GossipHandler) HandleAtomicTx(nodeID ids.NodeID, msg message.AtomicTxGo } h.stats.IncAtomicGossipReceivedNew() - if err := h.vm.issueTx(&tx, false /*=local*/); err != nil { + if err := h.vm.mempool.AddTx(&tx); err != nil { log.Trace( "AppGossip provided invalid transaction", "peerID", nodeID, diff --git a/plugin/evm/gossiper_atomic_gossiping_test.go b/plugin/evm/gossiper_atomic_gossiping_test.go index 6ded11967b..7cfbb55e17 100644 --- a/plugin/evm/gossiper_atomic_gossiping_test.go +++ b/plugin/evm/gossiper_atomic_gossiping_test.go @@ -60,7 +60,7 @@ func TestMempoolAtmTxsIssueTxAndGossiping(t *testing.T) { assert.NoError(vm.SetState(context.Background(), snow.NormalOp)) // Optimistically gossip raw tx - assert.NoError(vm.issueTx(tx, true /*=local*/)) + assert.NoError(vm.mempool.AddLocalTx(tx)) time.Sleep(500 * time.Millisecond) gossipedLock.Lock() assert.Equal(1, gossiped) @@ -74,7 +74,7 @@ func TestMempoolAtmTxsIssueTxAndGossiping(t *testing.T) { gossipedLock.Unlock() // Attempt to gossip conflicting tx - assert.ErrorIs(vm.issueTx(conflictingTx, true /*=local*/), errConflictingAtomicTx) + assert.ErrorIs(vm.mempool.AddLocalTx(conflictingTx), errConflictingAtomicTx) gossipedLock.Lock() assert.Equal(1, gossiped) gossipedLock.Unlock() diff --git a/plugin/evm/mempool.go b/plugin/evm/mempool.go index 8c1c56474e..d96c8feb81 100644 --- a/plugin/evm/mempool.go +++ b/plugin/evm/mempool.go @@ -75,10 +75,12 @@ type Mempool struct { bloom *gossip.BloomFilter metrics *mempoolMetrics + + verify func(tx *Tx) error } // NewMempool returns a Mempool with [maxSize] -func NewMempool(AVAXAssetID ids.ID, maxSize int) (*Mempool, error) { +func NewMempool(AVAXAssetID ids.ID, maxSize int, verify func(tx *Tx) error) (*Mempool, error) { bloom, err := gossip.NewBloomFilter(txGossipBloomMaxItems, txGossipBloomFalsePositiveRate) if err != nil { return nil, fmt.Errorf("failed to initialize bloom filter: %w", err) @@ -95,6 +97,7 @@ func NewMempool(AVAXAssetID ids.ID, maxSize int) (*Mempool, error) { utxoSpenders: make(map[ids.ID]*Tx), bloom: bloom, metrics: newMempoolMetrics(), + verify: verify, }, nil } @@ -145,6 +148,24 @@ func (m *Mempool) AddTx(tx *Tx) error { m.lock.Lock() defer m.lock.Unlock() + err := m.addTx(tx, false) + if err != nil { + // unlike local txs, invalid remote txs are recorded as discarded + // so that they won't be requested again + txID := tx.ID() + m.discardedTxs.Put(tx.ID(), tx) + log.Debug("failed to issue remote tx to mempool", + "txID", txID, + "err", err, + ) + } + return err +} + +func (m *Mempool) AddLocalTx(tx *Tx) error { + m.lock.Lock() + defer m.lock.Unlock() + return m.addTx(tx, false) } @@ -203,6 +224,11 @@ func (m *Mempool) addTx(tx *Tx, force bool) error { if _, exists := m.txHeap.Get(txID); exists { return nil } + if !force && m.verify != nil { + if err := m.verify(tx); err != nil { + return err + } + } utxoSet := tx.InputUTXOs() gasPrice, _ := m.atomicTxGasPrice(tx) diff --git a/plugin/evm/mempool_atomic_gossiping_test.go b/plugin/evm/mempool_atomic_gossiping_test.go index a0f82a8c01..741c177b90 100644 --- a/plugin/evm/mempool_atomic_gossiping_test.go +++ b/plugin/evm/mempool_atomic_gossiping_test.go @@ -5,16 +5,12 @@ package evm import ( "context" + "math/big" "testing" - "github.com/ava-labs/coreth/params" - "github.com/ava-labs/avalanchego/ids" - "github.com/ava-labs/avalanchego/utils" "github.com/ava-labs/avalanchego/utils/crypto/secp256k1" - "github.com/ava-labs/avalanchego/vms/components/avax" "github.com/ava-labs/avalanchego/vms/components/chain" - "github.com/ava-labs/avalanchego/vms/secp256k1fx" "github.com/stretchr/testify/assert" ) @@ -49,13 +45,13 @@ func TestMempoolAddLocallyCreateAtomicTx(t *testing.T) { conflictingTxID := conflictingTx.ID() // add a tx to the mempool - err := vm.issueTx(tx, true /*=local*/) + err := vm.mempool.AddLocalTx(tx) assert.NoError(err) has := mempool.has(txID) assert.True(has, "valid tx not recorded into mempool") // try to add a conflicting tx - err = vm.issueTx(conflictingTx, true /*=local*/) + err = vm.mempool.AddLocalTx(conflictingTx) assert.ErrorIs(err, errConflictingAtomicTx) has = mempool.has(conflictingTxID) assert.False(has, "conflicting tx in mempool") @@ -118,73 +114,16 @@ func TestMempoolMaxMempoolSizeHandling(t *testing.T) { assert.True(mempool.has(tx.ID())) } -func createImportTx(t *testing.T, vm *VM, txID ids.ID, feeAmount uint64) *Tx { - var importAmount uint64 = 10000000 - importTx := &UnsignedImportTx{ - NetworkID: testNetworkID, - BlockchainID: testCChainID, - SourceChain: testXChainID, - ImportedInputs: []*avax.TransferableInput{ - { - UTXOID: avax.UTXOID{ - TxID: txID, - OutputIndex: uint32(0), - }, - Asset: avax.Asset{ID: testAvaxAssetID}, - In: &secp256k1fx.TransferInput{ - Amt: importAmount, - Input: secp256k1fx.Input{ - SigIndices: []uint32{0}, - }, - }, - }, - { - UTXOID: avax.UTXOID{ - TxID: txID, - OutputIndex: uint32(1), - }, - Asset: avax.Asset{ID: testAvaxAssetID}, - In: &secp256k1fx.TransferInput{ - Amt: importAmount, - Input: secp256k1fx.Input{ - SigIndices: []uint32{0}, - }, - }, - }, - }, - Outs: []EVMOutput{ - { - Address: testEthAddrs[0], - Amount: importAmount - feeAmount, - AssetID: testAvaxAssetID, - }, - { - Address: testEthAddrs[1], - Amount: importAmount, - AssetID: testAvaxAssetID, - }, - }, - } - - // Sort the inputs and outputs to ensure the transaction is canonical - utils.Sort(importTx.ImportedInputs) - utils.Sort(importTx.Outs) - - tx := &Tx{UnsignedAtomicTx: importTx} - // Sign with the correct key - if err := tx.Sign(vm.codec, [][]*secp256k1.PrivateKey{{testKeys[0]}}); err != nil { - t.Fatal(err) - } - - return tx -} - // mempool will drop transaction with the lowest fee func TestMempoolPriorityDrop(t *testing.T) { assert := assert.New(t) // we use AP3 genesis here to not trip any block fees - _, vm, _, _, _ := GenesisVM(t, true, genesisJSONApricotPhase3, "", "") + importAmount := uint64(50000000) + _, vm, _, _, _ := GenesisVMWithUTXOs(t, true, genesisJSONApricotPhase3, "", "", map[ids.ShortID]uint64{ + testShortIDAddrs[0]: importAmount, + testShortIDAddrs[1]: importAmount, + }) defer func() { err := vm.Shutdown(context.Background()) assert.NoError(err) @@ -192,14 +131,25 @@ func TestMempoolPriorityDrop(t *testing.T) { mempool := vm.mempool mempool.maxSize = 1 - tx1 := createImportTx(t, vm, ids.ID{1}, params.AvalancheAtomicTxFee) + tx1, err := vm.newImportTx(vm.ctx.XChainID, testEthAddrs[0], initialBaseFee, []*secp256k1.PrivateKey{testKeys[0]}) + if err != nil { + t.Fatal(err) + } assert.NoError(mempool.AddTx(tx1)) assert.True(mempool.has(tx1.ID())) - tx2 := createImportTx(t, vm, ids.ID{2}, params.AvalancheAtomicTxFee) + + tx2, err := vm.newImportTx(vm.ctx.XChainID, testEthAddrs[1], initialBaseFee, []*secp256k1.PrivateKey{testKeys[1]}) + if err != nil { + t.Fatal(err) + } assert.ErrorIs(mempool.AddTx(tx2), errInsufficientAtomicTxFee) assert.True(mempool.has(tx1.ID())) assert.False(mempool.has(tx2.ID())) - tx3 := createImportTx(t, vm, ids.ID{3}, 2*params.AvalancheAtomicTxFee) + + tx3, err := vm.newImportTx(vm.ctx.XChainID, testEthAddrs[1], new(big.Int).Mul(initialBaseFee, big.NewInt(2)), []*secp256k1.PrivateKey{testKeys[1]}) + if err != nil { + t.Fatal(err) + } assert.NoError(mempool.AddTx(tx3)) assert.False(mempool.has(tx1.ID())) assert.False(mempool.has(tx2.ID())) diff --git a/plugin/evm/mempool_test.go b/plugin/evm/mempool_test.go index 6d719a0ee2..242f0e33c4 100644 --- a/plugin/evm/mempool_test.go +++ b/plugin/evm/mempool_test.go @@ -12,7 +12,7 @@ import ( func TestMempoolAddTx(t *testing.T) { require := require.New(t) - m, err := NewMempool(ids.Empty, 5_000) + m, err := NewMempool(ids.Empty, 5_000, nil) require.NoError(err) txs := make([]*GossipAtomicTx, 0) diff --git a/plugin/evm/service.go b/plugin/evm/service.go index 7cfc34db16..3a328fbd89 100644 --- a/plugin/evm/service.go +++ b/plugin/evm/service.go @@ -234,7 +234,7 @@ func (service *AvaxAPI) Import(_ *http.Request, args *ImportArgs, response *api. } response.TxID = tx.ID() - return service.vm.issueTx(tx, true /*=local*/) + return service.vm.mempool.AddLocalTx(tx) } // ExportAVAXArgs are the arguments to ExportAVAX @@ -343,7 +343,7 @@ func (service *AvaxAPI) Export(_ *http.Request, args *ExportArgs, response *api. } response.TxID = tx.ID() - return service.vm.issueTx(tx, true /*=local*/) + return service.vm.mempool.AddLocalTx(tx) } // GetUTXOs gets all utxos for passed in addresses @@ -449,7 +449,7 @@ func (service *AvaxAPI) IssueTx(r *http.Request, args *api.FormattedTx, response service.vm.ctx.Lock.Lock() defer service.vm.ctx.Lock.Unlock() - return service.vm.issueTx(tx, true /*=local*/) + return service.vm.mempool.AddLocalTx(tx) } // GetAtomicTxStatusReply defines the GetAtomicTxStatus replies returned from the API diff --git a/plugin/evm/syncervm_test.go b/plugin/evm/syncervm_test.go index dab0fd505a..34fd55023f 100644 --- a/plugin/evm/syncervm_test.go +++ b/plugin/evm/syncervm_test.go @@ -287,7 +287,7 @@ func createSyncServerAndClientVMs(t *testing.T, test syncTest) *syncVMSetup { // spend the UTXOs from shared memory importTx, err = serverVM.newImportTx(serverVM.ctx.XChainID, testEthAddrs[0], initialBaseFee, []*secp256k1.PrivateKey{testKeys[0]}) require.NoError(err) - require.NoError(serverVM.issueTx(importTx, true /*=local*/)) + require.NoError(serverVM.mempool.AddLocalTx(importTx)) case 1: // export some of the imported UTXOs to test exportTx is properly synced exportTx, err = serverVM.newExportTx( @@ -299,7 +299,7 @@ func createSyncServerAndClientVMs(t *testing.T, test syncTest) *syncVMSetup { []*secp256k1.PrivateKey{testKeys[0]}, ) require.NoError(err) - require.NoError(serverVM.issueTx(exportTx, true /*=local*/)) + require.NoError(serverVM.mempool.AddLocalTx(exportTx)) default: // Generate simple transfer transactions. pk := testKeys[0].ToECDSA() tx := types.NewTransaction(gen.TxNonce(testEthAddrs[0]), testEthAddrs[1], common.Big1, params.TxGas, initialBaseFee, nil) diff --git a/plugin/evm/tx_gossip_test.go b/plugin/evm/tx_gossip_test.go index ac3872a03a..2930839fd2 100644 --- a/plugin/evm/tx_gossip_test.go +++ b/plugin/evm/tx_gossip_test.go @@ -49,7 +49,7 @@ func TestEthTxGossip(t *testing.T) { importTx, err := vm.newImportTx(vm.ctx.XChainID, testEthAddrs[0], initialBaseFee, []*secp256k1.PrivateKey{testKeys[0]}) require.NoError(err) - require.NoError(vm.issueTx(importTx, true)) + require.NoError(vm.mempool.AddLocalTx(importTx)) <-issuer blk, err := vm.BuildBlock(context.Background()) @@ -228,7 +228,7 @@ func TestAtomicTxGossip(t *testing.T) { importTx, err := vm.newImportTx(vm.ctx.XChainID, testEthAddrs[0], initialBaseFee, []*secp256k1.PrivateKey{testKeys[0]}) require.NoError(err) - require.NoError(vm.issueTx(importTx, true /*=local*/)) + require.NoError(vm.mempool.AddLocalTx(importTx)) <-issuer // wait so we aren't throttled by the vm diff --git a/plugin/evm/tx_test.go b/plugin/evm/tx_test.go index 769690d272..e4d1dfd67b 100644 --- a/plugin/evm/tx_test.go +++ b/plugin/evm/tx_test.go @@ -155,7 +155,7 @@ func executeTxTest(t *testing.T, test atomicTxTest) { } } - if err := vm.issueTx(tx, true /*=local*/); err != nil { + if err := vm.mempool.AddLocalTx(tx); err != nil { t.Fatal(err) } <-issuer diff --git a/plugin/evm/vm.go b/plugin/evm/vm.go index 660c64d23a..930aa11d6f 100644 --- a/plugin/evm/vm.go +++ b/plugin/evm/vm.go @@ -542,7 +542,7 @@ func (vm *VM) Initialize( vm.codec = Codec // TODO: read size from settings - vm.mempool, err = NewMempool(chainCtx.AVAXAssetID, defaultMempoolSize) + vm.mempool, err = NewMempool(chainCtx.AVAXAssetID, defaultMempoolSize, vm.verifyTxAtTip) if err != nil { return fmt.Errorf("failed to initialize mempool: %w", err) } @@ -1449,44 +1449,19 @@ func (vm *VM) ParseAddress(addrStr string) (ids.ID, ids.ShortID, error) { return chainID, addr, nil } -// issueTx verifies [tx] as valid to be issued on top of the currently preferred block -// and then issues [tx] into the mempool if valid. -func (vm *VM) issueTx(tx *Tx, local bool) error { - if err := vm.verifyTxAtTip(tx); err != nil { - if !local { - // unlike local txs, invalid remote txs are recorded as discarded - // so that they won't be requested again - txID := tx.ID() - vm.mempool.discardedTxs.Put(txID, tx) - log.Debug("failed to verify remote tx being issued to the mempool", - "txID", txID, - "err", err, - ) - return nil - } - return err +// verifyTxAtTip verifies that [tx] is valid to be issued on top of the currently preferred block +func (vm *VM) verifyTxAtTip(tx *Tx) error { + if txByteLen := len(tx.SignedBytes()); txByteLen > targetAtomicTxsSize { + return fmt.Errorf("tx size (%d) exceeds total atomic txs size target (%d)", txByteLen, targetAtomicTxsSize) } - // add to mempool and possibly re-gossip - if err := vm.mempool.AddTx(tx); err != nil { - if !local { - // unlike local txs, invalid remote txs are recorded as discarded - // so that they won't be requested again - txID := tx.ID() - vm.mempool.discardedTxs.Put(tx.ID(), tx) - log.Debug("failed to issue remote tx to mempool", - "txID", txID, - "err", err, - ) - return nil - } + gasUsed, err := tx.GasUsed(true) + if err != nil { return err } + if new(big.Int).SetUint64(gasUsed).Cmp(params.AtomicGasLimit) > 0 { + return fmt.Errorf("tx gas usage (%d) exceeds atomic gas limit (%d)", gasUsed, params.AtomicGasLimit.Uint64()) + } - return nil -} - -// verifyTxAtTip verifies that [tx] is valid to be issued on top of the currently preferred block -func (vm *VM) verifyTxAtTip(tx *Tx) error { // Note: we fetch the current block and then the state at that block instead of the current state directly // since we need the header of the current block below. preferredBlock := vm.blockChain.CurrentBlock() diff --git a/plugin/evm/vm_test.go b/plugin/evm/vm_test.go index bd3792df26..20cbd4ff68 100644 --- a/plugin/evm/vm_test.go +++ b/plugin/evm/vm_test.go @@ -377,7 +377,7 @@ func TestCrossChainMessagestoVM(t *testing.T) { importTx, err := vm.newImportTx(vm.ctx.XChainID, testEthAddrs[0], initialBaseFee, []*secp256k1.PrivateKey{testKeys[0]}) require.NoError(err) - err = vm.issueTx(importTx, true /*=local*/) + err = vm.mempool.AddLocalTx(importTx) require.NoError(err) <-issuer @@ -661,7 +661,7 @@ func TestImportMissingUTXOs(t *testing.T) { importTx, err := vm.newImportTx(vm.ctx.XChainID, testEthAddrs[0], initialBaseFee, []*secp256k1.PrivateKey{testKeys[0]}) require.NoError(t, err) - err = vm.issueTx(importTx, true /*=local*/) + err = vm.mempool.AddLocalTx(importTx) require.NoError(t, err) <-issuer blk, err := vm.BuildBlock(context.Background()) @@ -704,7 +704,7 @@ func TestIssueAtomicTxs(t *testing.T) { t.Fatal(err) } - if err := vm.issueTx(importTx, true /*=local*/); err != nil { + if err := vm.mempool.AddLocalTx(importTx); err != nil { t.Fatal(err) } @@ -763,7 +763,7 @@ func TestIssueAtomicTxs(t *testing.T) { t.Fatal(err) } - if err := vm.issueTx(exportTx, true /*=local*/); err != nil { + if err := vm.mempool.AddLocalTx(exportTx); err != nil { t.Fatal(err) } @@ -830,7 +830,7 @@ func TestBuildEthTxBlock(t *testing.T) { t.Fatal(err) } - if err := vm.issueTx(importTx, true /*=local*/); err != nil { + if err := vm.mempool.AddLocalTx(importTx); err != nil { t.Fatal(err) } @@ -1005,7 +1005,7 @@ func testConflictingImportTxs(t *testing.T, genesis string) { t.Fatal(err) } for i, tx := range importTxs[:2] { - if err := vm.issueTx(tx, true /*=local*/); err != nil { + if err := vm.mempool.AddLocalTx(tx); err != nil { t.Fatal(err) } @@ -1039,7 +1039,7 @@ func testConflictingImportTxs(t *testing.T, genesis string) { // the VM returns an error when it attempts to issue the conflict into the mempool // and when it attempts to build a block with the conflict force added to the mempool. for i, tx := range conflictTxs[:2] { - if err := vm.issueTx(tx, true /*=local*/); err == nil { + if err := vm.mempool.AddLocalTx(tx); err == nil { t.Fatal("Expected issueTx to fail due to conflicting transaction") } // Force issue transaction directly to the mempool @@ -1061,7 +1061,7 @@ func testConflictingImportTxs(t *testing.T, genesis string) { // Generate one more valid block so that we can copy the header to create an invalid block // with modified extra data. This new block will be invalid for more than one reason (invalid merkle root) // so we check to make sure that the expected error is returned from block verification. - if err := vm.issueTx(importTxs[2], true); err != nil { + if err := vm.mempool.AddLocalTx(importTxs[2]); err != nil { t.Fatal(err) } <-issuer @@ -1169,10 +1169,10 @@ func TestReissueAtomicTxHigherGasPrice(t *testing.T) { t.Fatal(err) } - if err := vm.issueTx(tx1, true); err != nil { + if err := vm.mempool.AddLocalTx(tx1); err != nil { t.Fatal(err) } - if err := vm.issueTx(tx2, true); err != nil { + if err := vm.mempool.AddLocalTx(tx2); err != nil { t.Fatal(err) } @@ -1196,10 +1196,10 @@ func TestReissueAtomicTxHigherGasPrice(t *testing.T) { t.Fatal(err) } - if err := vm.issueTx(tx1, true); err != nil { + if err := vm.mempool.AddLocalTx(tx1); err != nil { t.Fatal(err) } - if err := vm.issueTx(tx2, true); err != nil { + if err := vm.mempool.AddLocalTx(tx2); err != nil { t.Fatal(err) } @@ -1229,15 +1229,15 @@ func TestReissueAtomicTxHigherGasPrice(t *testing.T) { if err != nil { t.Fatal(err) } - if err := vm.issueTx(importTx1, true /*=local*/); err != nil { + if err := vm.mempool.AddLocalTx(importTx1); err != nil { t.Fatal(err) } - if err := vm.issueTx(importTx2, true /*=local*/); err != nil { + if err := vm.mempool.AddLocalTx(importTx2); err != nil { t.Fatal(err) } - if err := vm.issueTx(reissuanceTx1, true /*=local*/); !errors.Is(err, errConflictingAtomicTx) { + if err := vm.mempool.AddLocalTx(reissuanceTx1); !errors.Is(err, errConflictingAtomicTx) { t.Fatalf("Expected to fail with err: %s, but found err: %s", errConflictingAtomicTx, err) } @@ -1249,7 +1249,7 @@ func TestReissueAtomicTxHigherGasPrice(t *testing.T) { if err != nil { t.Fatal(err) } - if err := vm.issueTx(reissuanceTx2, true /*=local*/); err != nil { + if err := vm.mempool.AddLocalTx(reissuanceTx2); err != nil { t.Fatal(err) } @@ -1329,7 +1329,7 @@ func TestSetPreferenceRace(t *testing.T) { t.Fatal(err) } - if err := vm1.issueTx(importTx, true /*=local*/); err != nil { + if err := vm1.mempool.AddLocalTx(importTx); err != nil { t.Fatal(err) } @@ -1578,7 +1578,7 @@ func TestConflictingTransitiveAncestryWithGap(t *testing.T) { t.Fatal(err) } - if err := vm.issueTx(importTx0A, true /*=local*/); err != nil { + if err := vm.mempool.AddLocalTx(importTx0A); err != nil { t.Fatalf("Failed to issue importTx0A: %s", err) } @@ -1636,7 +1636,7 @@ func TestConflictingTransitiveAncestryWithGap(t *testing.T) { t.Fatalf("Failed to issue importTx1 due to: %s", err) } - if err := vm.issueTx(importTx1, true /*=local*/); err != nil { + if err := vm.mempool.AddLocalTx(importTx1); err != nil { t.Fatal(err) } @@ -1655,7 +1655,7 @@ func TestConflictingTransitiveAncestryWithGap(t *testing.T) { t.Fatal(err) } - if err := vm.issueTx(importTx0B, true /*=local*/); err == nil { + if err := vm.mempool.AddLocalTx(importTx0B); err == nil { t.Fatalf("Should not have been able to issue import tx with conflict") } // Force issue transaction directly into the mempool @@ -1715,7 +1715,7 @@ func TestBonusBlocksTxs(t *testing.T) { t.Fatal(err) } - if err := vm.issueTx(importTx, true /*=local*/); err != nil { + if err := vm.mempool.AddLocalTx(importTx); err != nil { t.Fatal(err) } @@ -1808,7 +1808,7 @@ func TestReorgProtection(t *testing.T) { t.Fatal(err) } - if err := vm1.issueTx(importTx, true /*=local*/); err != nil { + if err := vm1.mempool.AddLocalTx(importTx); err != nil { t.Fatal(err) } @@ -1990,7 +1990,7 @@ func TestNonCanonicalAccept(t *testing.T) { t.Fatal(err) } - if err := vm1.issueTx(importTx, true /*=local*/); err != nil { + if err := vm1.mempool.AddLocalTx(importTx); err != nil { t.Fatal(err) } @@ -2165,7 +2165,7 @@ func TestStickyPreference(t *testing.T) { t.Fatal(err) } - if err := vm1.issueTx(importTx, true /*=local*/); err != nil { + if err := vm1.mempool.AddLocalTx(importTx); err != nil { t.Fatal(err) } @@ -2438,7 +2438,7 @@ func TestUncleBlock(t *testing.T) { t.Fatal(err) } - if err := vm1.issueTx(importTx, true /*=local*/); err != nil { + if err := vm1.mempool.AddLocalTx(importTx); err != nil { t.Fatal(err) } @@ -2621,7 +2621,7 @@ func TestEmptyBlock(t *testing.T) { t.Fatal(err) } - if err := vm.issueTx(importTx, true /*=local*/); err != nil { + if err := vm.mempool.AddLocalTx(importTx); err != nil { t.Fatal(err) } @@ -2702,7 +2702,7 @@ func TestAcceptReorg(t *testing.T) { t.Fatal(err) } - if err := vm1.issueTx(importTx, true /*=local*/); err != nil { + if err := vm1.mempool.AddLocalTx(importTx); err != nil { t.Fatal(err) } @@ -2897,7 +2897,7 @@ func TestFutureBlock(t *testing.T) { t.Fatal(err) } - if err := vm.issueTx(importTx, true /*=local*/); err != nil { + if err := vm.mempool.AddLocalTx(importTx); err != nil { t.Fatal(err) } @@ -2962,7 +2962,7 @@ func TestBuildApricotPhase1Block(t *testing.T) { t.Fatal(err) } - if err := vm.issueTx(importTx, true /*=local*/); err != nil { + if err := vm.mempool.AddLocalTx(importTx); err != nil { t.Fatal(err) } @@ -3078,7 +3078,7 @@ func TestLastAcceptedBlockNumberAllow(t *testing.T) { t.Fatal(err) } - if err := vm.issueTx(importTx, true /*=local*/); err != nil { + if err := vm.mempool.AddLocalTx(importTx); err != nil { t.Fatal(err) } @@ -3156,7 +3156,7 @@ func TestReissueAtomicTx(t *testing.T) { t.Fatal(err) } - if err := vm.issueTx(importTx, true /*=local*/); err != nil { + if err := vm.mempool.AddLocalTx(importTx); err != nil { t.Fatal(err) } @@ -3258,7 +3258,7 @@ func TestAtomicTxFailsEVMStateTransferBuildBlock(t *testing.T) { exportTxs := createExportTxOptions(t, vm, issuer, sharedMemory) exportTx1, exportTx2 := exportTxs[0], exportTxs[1] - if err := vm.issueTx(exportTx1, true /*=local*/); err != nil { + if err := vm.mempool.AddLocalTx(exportTx1); err != nil { t.Fatal(err) } <-issuer @@ -3274,7 +3274,7 @@ func TestAtomicTxFailsEVMStateTransferBuildBlock(t *testing.T) { t.Fatal(err) } - if err := vm.issueTx(exportTx2, true /*=local*/); err == nil { + if err := vm.mempool.AddLocalTx(exportTx2); err == nil { t.Fatal("Should have failed to issue due to an invalid export tx") } @@ -3337,11 +3337,11 @@ func TestBuildInvalidBlockHead(t *testing.T) { // Verify that the transaction fails verification when attempting to issue // it into the atomic mempool. - if err := vm.issueTx(tx, true /*=local*/); err == nil { + if err := vm.mempool.AddLocalTx(tx); err == nil { t.Fatal("Should have failed to issue invalid transaction") } // Force issue the transaction directly to the mempool - if err := vm.mempool.AddTx(tx); err != nil { + if err := vm.mempool.ForceAddTx(tx); err != nil { t.Fatal(err) } @@ -3485,7 +3485,7 @@ func TestBuildApricotPhase4Block(t *testing.T) { t.Fatal(err) } - if err := vm.issueTx(importTx, true /*=local*/); err != nil { + if err := vm.mempool.AddLocalTx(importTx); err != nil { t.Fatal(err) } @@ -3667,7 +3667,7 @@ func TestBuildApricotPhase5Block(t *testing.T) { t.Fatal(err) } - if err := vm.issueTx(importTx, true /*=local*/); err != nil { + if err := vm.mempool.AddLocalTx(importTx); err != nil { t.Fatal(err) } @@ -3807,7 +3807,7 @@ func TestConsecutiveAtomicTransactionsRevertSnapshot(t *testing.T) { importTxs := createImportTxOptions(t, vm, sharedMemory) // Issue the first import transaction, build, and accept the block. - if err := vm.issueTx(importTxs[0], true); err != nil { + if err := vm.mempool.AddLocalTx(importTxs[0]); err != nil { t.Fatal(err) } @@ -3873,7 +3873,7 @@ func TestAtomicTxBuildBlockDropsConflicts(t *testing.T) { if err != nil { t.Fatal(err) } - if err := vm.issueTx(importTx, true /*=local*/); err != nil { + if err := vm.mempool.AddLocalTx(importTx); err != nil { t.Fatal(err) } conflictSets[index].Add(importTx.ID()) @@ -3881,7 +3881,7 @@ func TestAtomicTxBuildBlockDropsConflicts(t *testing.T) { if err != nil { t.Fatal(err) } - if err := vm.issueTx(conflictTx, true /*=local*/); err == nil { + if err := vm.mempool.AddLocalTx(conflictTx); err == nil { t.Fatal("should conflict with the utxoSet in the mempool") } // force add the tx @@ -3942,7 +3942,7 @@ func TestBuildBlockDoesNotExceedAtomicGasLimit(t *testing.T) { if err != nil { t.Fatal(err) } - if err := vm.issueTx(importTx, true); err != nil { + if err := vm.mempool.AddLocalTx(importTx); err != nil { t.Fatal(err) } } @@ -4001,7 +4001,7 @@ func TestExtraStateChangeAtomicGasLimitExceeded(t *testing.T) { if err != nil { t.Fatal(err) } - if err := vm1.issueTx(importTx, true); err != nil { + if err := vm1.mempool.ForceAddTx(importTx); err != nil { t.Fatal(err) } @@ -4064,7 +4064,7 @@ func TestSkipChainConfigCheckCompatible(t *testing.T) { // accept one block to test the SkipUpgradeCheck functionality. importTx, err := vm.newImportTx(vm.ctx.XChainID, testEthAddrs[0], initialBaseFee, []*secp256k1.PrivateKey{testKeys[0]}) require.NoError(t, err) - require.NoError(t, vm.issueTx(importTx, true /*=local*/)) + require.NoError(t, vm.mempool.AddLocalTx(importTx)) <-issuer blk, err := vm.BuildBlock(context.Background())