diff --git a/consensus/dummy/consensus.go b/consensus/dummy/consensus.go index 1452335a95..eb8e20b159 100644 --- a/consensus/dummy/consensus.go +++ b/consensus/dummy/consensus.go @@ -450,42 +450,39 @@ func (eng *DummyEngine) FinalizeAndAssemble(chain consensus.ChainHeaderReader, h return nil, err } } - if chain.Config().IsApricotPhase4(header.Time) { - header.ExtDataGasUsed = extDataGasUsed - if header.ExtDataGasUsed == nil { - header.ExtDataGasUsed = new(big.Int).Set(common.Big0) - } - blockGasCostStep := ApricotPhase4BlockGasCostStep - if chain.Config().IsApricotPhase5(header.Time) { - blockGasCostStep = ApricotPhase5BlockGasCostStep - } - // Calculate the required block gas cost for this block. - header.BlockGasCost = calcBlockGasCost( - ApricotPhase4TargetBlockRate, - ApricotPhase4MinBlockGasCost, - ApricotPhase4MaxBlockGasCost, - blockGasCostStep, - parent.BlockGasCost, - parent.Time, header.Time, - ) - // Verify that this block covers the block fee. - if err := eng.verifyBlockFee( - header.BaseFee, - header.BlockGasCost, - txs, - receipts, - contribution, - ); err != nil { - return nil, err - } + + header.ExtDataGasUsed = extDataGasUsed + if header.ExtDataGasUsed == nil { + header.ExtDataGasUsed = new(big.Int).Set(common.Big0) } + blockGasCostStep := ApricotPhase5BlockGasCostStep + // Calculate the required block gas cost for this block. + header.BlockGasCost = calcBlockGasCost( + ApricotPhase4TargetBlockRate, + ApricotPhase4MinBlockGasCost, + ApricotPhase4MaxBlockGasCost, + blockGasCostStep, + parent.BlockGasCost, + parent.Time, header.Time, + ) + // Verify that this block covers the block fee. + if err := eng.verifyBlockFee( + header.BaseFee, + header.BlockGasCost, + txs, + receipts, + contribution, + ); err != nil { + return nil, err + } + // commit the final state root - header.Root = state.IntermediateRoot(chain.Config().IsEIP158(header.Number)) + header.Root = state.IntermediateRoot(true) // Header seems complete, assemble into a block and return return types.NewBlockWithExtData( header, txs, uncles, receipts, trie.NewStackTrie(nil), - extraData, chain.Config().IsApricotPhase1(header.Time), + extraData, true, ), nil } diff --git a/consensus/dummy/dynamic_fees.go b/consensus/dummy/dynamic_fees.go index de273fbbb5..5e750af19e 100644 --- a/consensus/dummy/dynamic_fees.go +++ b/consensus/dummy/dynamic_fees.go @@ -329,12 +329,7 @@ func calcBlockGasCost( // subsidize the inclusion of low tip paying transactions. The only // correctness check performed is that the sum of all tips is >= the // required block fee. -// -// This function will return nil for all return values prior to Apricot Phase 4. func MinRequiredTip(config *params.ChainConfig, header *types.Header) (*big.Int, error) { - if !config.IsApricotPhase4(header.Time) { - return nil, nil - } if header.BaseFee == nil { return nil, errBaseFeeNil } diff --git a/miner/worker.go b/miner/worker.go index 96ab02c23d..e53836ea44 100644 --- a/miner/worker.go +++ b/miner/worker.go @@ -330,18 +330,14 @@ func (w *worker) applyTransaction(env *environment, tx *types.Transaction, coinb blockContext vm.BlockContext ) - if env.rules.IsDurango { - results, err := core.CheckPredicates(env.rules, env.predicateContext, tx) - if err != nil { - log.Debug("Transaction predicate failed verification in miner", "tx", tx.Hash(), "err", err) - return nil, err - } - env.predicateResults.SetTxResults(tx.Hash(), results) - - blockContext = core.NewEVMBlockContextWithPredicateResults(env.header, w.chain, &coinbase, env.predicateResults) - } else { - blockContext = core.NewEVMBlockContext(env.header, w.chain, &coinbase) + results, err := core.CheckPredicates(env.rules, env.predicateContext, tx) + if err != nil { + log.Debug("Transaction predicate failed verification in miner", "tx", tx.Hash(), "err", err) + return nil, err } + env.predicateResults.SetTxResults(tx.Hash(), results) + + blockContext = core.NewEVMBlockContextWithPredicateResults(env.header, w.chain, &coinbase, env.predicateResults) receipt, err := core.ApplyTransaction(w.chainConfig, w.chain, blockContext, env.gasPool, env.state, env.header, tx, &env.header.GasUsed, *w.chain.GetVMConfig()) if err != nil { @@ -460,13 +456,11 @@ func (w *worker) commitTransactions(env *environment, plainTxs, blobTxs *transac // commit runs any post-transaction state modifications, assembles the final block // and commits new work if consensus engine is running. func (w *worker) commit(env *environment) (*types.Block, error) { - if env.rules.IsDurango { - predicateResultsBytes, err := env.predicateResults.Bytes() - if err != nil { - return nil, fmt.Errorf("failed to marshal predicate results: %w", err) - } - env.header.Extra = append(env.header.Extra, predicateResultsBytes...) + predicateResultsBytes, err := env.predicateResults.Bytes() + if err != nil { + return nil, fmt.Errorf("failed to marshal predicate results: %w", err) } + env.header.Extra = append(env.header.Extra, predicateResultsBytes...) // Deep copy receipts here to avoid interaction between different tasks. receipts := copyReceipts(env.receipts) block, err := w.engine.FinalizeAndAssemble(w.chain, env.header, env.parent, env.state, env.txs, nil, receipts) diff --git a/plugin/evm/atomic/export_tx.go b/plugin/evm/atomic/export_tx.go index 3b61ea71b8..2ce90d769f 100644 --- a/plugin/evm/atomic/export_tx.go +++ b/plugin/evm/atomic/export_tx.go @@ -31,8 +31,8 @@ import ( var ( _ UnsignedAtomicTx = &UnsignedExportTx{} _ secp256k1fx.UnsignedTx = &UnsignedExportTx{} - ErrExportNonAVAXInputBanff = errors.New("export input cannot contain non-AVAX in Banff") - ErrExportNonAVAXOutputBanff = errors.New("export output cannot contain non-AVAX in Banff") + ErrExportNonAVAXInput = errors.New("export input cannot contain non-AVAX") + ErrExportNonAVAXOutput = errors.New("export output cannot contain non-AVAX") ErrNoExportOutputs = errors.New("tx has no export outputs") errPublicKeySignatureMismatch = errors.New("signature doesn't match public key") errOverflowExport = errors.New("overflow when computing export amount + txFee") @@ -103,8 +103,8 @@ func (utx *UnsignedExportTx) Verify( if err := in.Verify(); err != nil { return err } - if rules.IsBanff && in.AssetID != ctx.AVAXAssetID { - return ErrExportNonAVAXInputBanff + if in.AssetID != ctx.AVAXAssetID { + return ErrExportNonAVAXInput } } @@ -116,8 +116,8 @@ func (utx *UnsignedExportTx) Verify( if assetID != ctx.AVAXAssetID && utx.DestinationChain == constants.PlatformChainID { return ErrWrongChainID } - if rules.IsBanff && assetID != ctx.AVAXAssetID { - return ErrExportNonAVAXOutputBanff + if assetID != ctx.AVAXAssetID { + return ErrExportNonAVAXOutput } } if !avax.IsSortedTransferableOutputs(utx.ExportedOutputs, Codec) { @@ -311,35 +311,26 @@ func NewExportTx( err error ) - switch { - case rules.IsApricotPhase3: - utx := &UnsignedExportTx{ - NetworkID: ctx.NetworkID, - BlockchainID: ctx.ChainID, - DestinationChain: chainID, - Ins: ins, - ExportedOutputs: outs, - } - tx := &Tx{UnsignedAtomicTx: utx} - if err := tx.Sign(Codec, nil); err != nil { - return nil, err - } - - var cost uint64 - cost, err = tx.GasUsed(rules.IsApricotPhase5) - if err != nil { - return nil, err - } + // Create the temp transaction to get the cost + tempUtx := &UnsignedExportTx{ + NetworkID: ctx.NetworkID, + BlockchainID: ctx.ChainID, + DestinationChain: chainID, + Ins: ins, + ExportedOutputs: outs, + } + tempTx := &Tx{UnsignedAtomicTx: tempUtx} + if err := tempTx.Sign(Codec, nil); err != nil { + return nil, err + } - avaxIns, avaxSigners, err = GetSpendableAVAXWithFee(ctx, state, keys, amount, cost, baseFee) - default: - var avaxNeeded uint64 - avaxNeeded, err = math.Add(amount, params.AvalancheAtomicTxFee) - if err != nil { - return nil, errOverflowExport - } - avaxIns, avaxSigners, err = GetSpendableFunds(ctx, state, keys, avaxNeeded) + var cost uint64 + cost, err = tempTx.GasUsed(true) + if err != nil { + return nil, err } + + avaxIns, avaxSigners, err = GetSpendableAVAXWithFee(ctx, state, keys, amount, cost, baseFee) if err != nil { return nil, fmt.Errorf("couldn't generate tx inputs/signers: %w", err) } diff --git a/plugin/evm/atomic/import_tx.go b/plugin/evm/atomic/import_tx.go index f1df990839..3f96b8faaa 100644 --- a/plugin/evm/atomic/import_tx.go +++ b/plugin/evm/atomic/import_tx.go @@ -28,21 +28,21 @@ import ( ) var ( - _ UnsignedAtomicTx = &UnsignedImportTx{} - _ secp256k1fx.UnsignedTx = &UnsignedImportTx{} - ErrImportNonAVAXInputBanff = errors.New("import input cannot contain non-AVAX in Banff") - ErrImportNonAVAXOutputBanff = errors.New("import output cannot contain non-AVAX in Banff") - ErrNoImportInputs = errors.New("tx has no imported inputs") - ErrConflictingAtomicInputs = errors.New("invalid block due to conflicting atomic inputs") - ErrWrongChainID = errors.New("tx has wrong chain ID") - ErrNoEVMOutputs = errors.New("tx has no EVM outputs") - ErrInputsNotSortedUnique = errors.New("inputs not sorted and unique") - ErrOutputsNotSortedUnique = errors.New("outputs not sorted and unique") - ErrOutputsNotSorted = errors.New("tx outputs not sorted") - ErrAssetIDMismatch = errors.New("asset IDs in the input don't match the utxo") - errNilBaseFeeApricotPhase3 = errors.New("nil base fee is invalid after apricotPhase3") - errInsufficientFundsForFee = errors.New("insufficient AVAX funds to pay transaction fee") - errRejectedParent = errors.New("rejected parent") + _ UnsignedAtomicTx = &UnsignedImportTx{} + _ secp256k1fx.UnsignedTx = &UnsignedImportTx{} + ErrImportNonAVAXInput = errors.New("import input cannot contain non-AVAX") + ErrImportNonAVAXOutput = errors.New("import output cannot contain non-AVAX") + ErrNoImportInputs = errors.New("tx has no imported inputs") + ErrConflictingAtomicInputs = errors.New("invalid block due to conflicting atomic inputs") + ErrWrongChainID = errors.New("tx has wrong chain ID") + ErrNoEVMOutputs = errors.New("tx has no EVM outputs") + ErrInputsNotSortedUnique = errors.New("inputs not sorted and unique") + ErrOutputsNotSortedUnique = errors.New("outputs not sorted and unique") + ErrOutputsNotSorted = errors.New("tx outputs not sorted") + ErrAssetIDMismatch = errors.New("asset IDs in the input don't match the utxo") + errNilBaseFeeApricotPhase3 = errors.New("nil base fee is invalid after apricotPhase3") + errInsufficientFundsForFee = errors.New("insufficient AVAX funds to pay transaction fee") + errRejectedParent = errors.New("rejected parent") ) // UnsignedImportTx is an unsigned ImportTx @@ -104,8 +104,8 @@ func (utx *UnsignedImportTx) Verify( if err := out.Verify(); err != nil { return fmt.Errorf("EVM Output failed verification: %w", err) } - if rules.IsBanff && out.AssetID != ctx.AVAXAssetID { - return ErrImportNonAVAXOutputBanff + if out.AssetID != ctx.AVAXAssetID { + return ErrImportNonAVAXOutput } } @@ -113,8 +113,8 @@ func (utx *UnsignedImportTx) Verify( if err := in.Verify(); err != nil { return fmt.Errorf("atomic input failed verification: %w", err) } - if rules.IsBanff && in.AssetID() != ctx.AVAXAssetID { - return ErrImportNonAVAXInputBanff + if in.AssetID() != ctx.AVAXAssetID { + return ErrImportNonAVAXInput } } if !utils.IsSortedAndUnique(utx.ImportedInputs) { @@ -345,40 +345,34 @@ func NewImportTx( txFeeWithoutChange uint64 txFeeWithChange uint64 ) - switch { - case rules.IsApricotPhase3: - if baseFee == nil { - return nil, errNilBaseFeeApricotPhase3 - } - utx := &UnsignedImportTx{ - NetworkID: ctx.NetworkID, - BlockchainID: ctx.ChainID, - Outs: outs, - ImportedInputs: importedInputs, - SourceChain: chainID, - } - tx := &Tx{UnsignedAtomicTx: utx} - if err := tx.Sign(Codec, nil); err != nil { - return nil, err - } + if baseFee == nil { + return nil, errNilBaseFeeApricotPhase3 + } + tempUtx := &UnsignedImportTx{ + NetworkID: ctx.NetworkID, + BlockchainID: ctx.ChainID, + Outs: outs, + ImportedInputs: importedInputs, + SourceChain: chainID, + } + tempTx := &Tx{UnsignedAtomicTx: tempUtx} + if err := tempTx.Sign(Codec, nil); err != nil { + return nil, err + } - gasUsedWithoutChange, err := tx.GasUsed(rules.IsApricotPhase5) - if err != nil { - return nil, err - } - gasUsedWithChange := gasUsedWithoutChange + EVMOutputGas + gasUsedWithoutChange, err := tempTx.GasUsed(true) + if err != nil { + return nil, err + } + gasUsedWithChange := gasUsedWithoutChange + EVMOutputGas - txFeeWithoutChange, err = CalculateDynamicFee(gasUsedWithoutChange, baseFee) - if err != nil { - return nil, err - } - txFeeWithChange, err = CalculateDynamicFee(gasUsedWithChange, baseFee) - if err != nil { - return nil, err - } - case rules.IsApricotPhase2: - txFeeWithoutChange = params.AvalancheAtomicTxFee - txFeeWithChange = params.AvalancheAtomicTxFee + txFeeWithoutChange, err = CalculateDynamicFee(gasUsedWithoutChange, baseFee) + if err != nil { + return nil, err + } + txFeeWithChange, err = CalculateDynamicFee(gasUsedWithChange, baseFee) + if err != nil { + return nil, err } // AVAX output diff --git a/plugin/evm/import_tx_test.go b/plugin/evm/import_tx_test.go index da8a5c9db6..b6360b2bc6 100644 --- a/plugin/evm/import_tx_test.go +++ b/plugin/evm/import_tx_test.go @@ -398,7 +398,7 @@ func TestImportTxVerify(t *testing.T) { }, ctx: ctx, rules: banffRules, - expectedErr: atomic.ErrImportNonAVAXInputBanff.Error(), + expectedErr: atomic.ErrImportNonAVAXInput.Error(), }, "non-AVAX output Banff": { generate: func(t *testing.T) atomic.UnsignedAtomicTx { @@ -414,7 +414,7 @@ func TestImportTxVerify(t *testing.T) { }, ctx: ctx, rules: banffRules, - expectedErr: atomic.ErrImportNonAVAXOutputBanff.Error(), + expectedErr: atomic.ErrImportNonAVAXOutput.Error(), }, } for name, test := range tests { diff --git a/plugin/evm/vm.go b/plugin/evm/vm.go index 3a96816ae0..b34e4f08fd 100644 --- a/plugin/evm/vm.go +++ b/plugin/evm/vm.go @@ -770,52 +770,6 @@ func (vm *VM) createConsensusCallbacks() dummy.ConsensusCallbacks { } } -func (vm *VM) preBatchOnFinalizeAndAssemble(header *types.Header, state *state.StateDB, txs []*types.Transaction) ([]byte, *big.Int, *big.Int, error) { - for { - tx, exists := vm.mempool.NextTx() - if !exists { - break - } - // Take a snapshot of [state] before calling verifyTx so that if the transaction fails verification - // we can revert to [snapshot]. - // Note: snapshot is taken inside the loop because you cannot revert to the same snapshot more than - // once. - snapshot := state.Snapshot() - rules := vm.chainConfig.Rules(header.Number, header.Time) - if err := vm.verifyTx(tx, header.ParentHash, header.BaseFee, state, rules); err != nil { - // Discard the transaction from the mempool on failed verification. - log.Debug("discarding tx from mempool on failed verification", "txID", tx.ID(), "err", err) - vm.mempool.DiscardCurrentTx(tx.ID()) - state.RevertToSnapshot(snapshot) - continue - } - - atomicTxBytes, err := atomic.Codec.Marshal(atomic.CodecVersion, tx) - if err != nil { - // Discard the transaction from the mempool and error if the transaction - // cannot be marshalled. This should never happen. - log.Debug("discarding tx due to unmarshal err", "txID", tx.ID(), "err", err) - vm.mempool.DiscardCurrentTx(tx.ID()) - return nil, nil, nil, fmt.Errorf("failed to marshal atomic transaction %s due to %w", tx.ID(), err) - } - var contribution, gasUsed *big.Int - if rules.IsApricotPhase4 { - contribution, gasUsed, err = tx.BlockFeeContribution(rules.IsApricotPhase5, vm.ctx.AVAXAssetID, header.BaseFee) - if err != nil { - return nil, nil, nil, err - } - } - return atomicTxBytes, contribution, gasUsed, nil - } - - if len(txs) == 0 { - // this could happen due to the async logic of geth tx pool - return nil, nil, nil, errEmptyBlock - } - - return nil, nil, nil, nil -} - // assumes that we are in at least Apricot Phase 5. func (vm *VM) postBatchOnFinalizeAndAssemble(header *types.Header, state *state.StateDB, txs []*types.Transaction) ([]byte, *big.Int, *big.Int, error) { var ( @@ -918,9 +872,6 @@ func (vm *VM) postBatchOnFinalizeAndAssemble(header *types.Header, state *state. } func (vm *VM) onFinalizeAndAssemble(header *types.Header, state *state.StateDB, txs []*types.Transaction) ([]byte, *big.Int, *big.Int, error) { - if !vm.chainConfig.IsApricotPhase5(header.Time) { - return vm.preBatchOnFinalizeAndAssemble(header, state, txs) - } return vm.postBatchOnFinalizeAndAssemble(header, state, txs) } @@ -1583,12 +1534,10 @@ func (vm *VM) verifyTxAtTip(tx *atomic.Tx) error { parentHeader := preferredBlock var nextBaseFee *big.Int timestamp := uint64(vm.clock.Time().Unix()) - if vm.chainConfig.IsApricotPhase3(timestamp) { - _, nextBaseFee, err = dummy.EstimateNextBaseFee(vm.chainConfig, parentHeader, timestamp) - if err != nil { - // Return extremely detailed error since CalcBaseFee should never encounter an issue here - return fmt.Errorf("failed to calculate base fee with parent timestamp (%d), parent ExtraData: (0x%x), and current timestamp (%d): %w", parentHeader.Time, parentHeader.Extra, timestamp, err) - } + _, nextBaseFee, err = dummy.EstimateNextBaseFee(vm.chainConfig, parentHeader, timestamp) + if err != nil { + // Return extremely detailed error since CalcBaseFee should never encounter an issue here + return fmt.Errorf("failed to calculate base fee with parent timestamp (%d), parent ExtraData: (0x%x), and current timestamp (%d): %w", parentHeader.Time, parentHeader.Extra, timestamp, err) } // We don’t need to revert the state here in case verifyTx errors, because