diff --git a/core/blockchain.go b/core/blockchain.go index 56fb22df1f..eda23fac5c 100644 --- a/core/blockchain.go +++ b/core/blockchain.go @@ -2537,12 +2537,39 @@ func (bc *BlockChain) InsertBlockWithoutSetHead(block *types.Block, makeWitness } newHeader, err := bc.validator.ValidateState(block, statedb, res, false) + log.Info("New Header", "stateroot", newHeader.Root) if err != nil { return nil, nil, err } + // Create a new block with the updated header that contains the correct state root + log.Info("Block", "hash", block.Hash(), "number", block.Number()) + updatedBlock := block.WithSeal(newHeader) + // Print the hash of the updated block for debugging purposes + log.Info("Updated Block Hash", "hash", updatedBlock.Hash()) + + // If the block hash has changed, we need to update the hash-to-number mapping + if updatedBlock.Hash() != block.Hash() { + log.Info("Block hash changed, updating hash-to-number mapping", + "old_hash", block.Hash(), "new_hash", updatedBlock.Hash(), "number", updatedBlock.Number()) + + // Write the updated hash-to-number mapping and remove the old one + batch := bc.db.NewBatch() + rawdb.WriteHeaderNumber(batch, updatedBlock.Hash(), updatedBlock.NumberU64()) + rawdb.DeleteHeaderNumber(batch, block.Hash()) + + // Also clean up old receipts and body data if they exist + rawdb.DeleteReceipts(batch, block.Hash(), block.NumberU64()) + rawdb.DeleteBody(batch, block.Hash(), block.NumberU64()) + rawdb.DeleteHeader(batch, block.Hash(), block.NumberU64()) + + if err := batch.Write(); err != nil { + return nil, nil, fmt.Errorf("failed to update hash-to-number mapping: %w", err) + } + } + // Write the block with state - err = bc.writeBlockWithState(block, res.Receipts, statedb) + err = bc.writeBlockWithState(updatedBlock, res.Receipts, statedb) if err != nil { return nil, nil, err } @@ -2550,7 +2577,7 @@ func (bc *BlockChain) InsertBlockWithoutSetHead(block *types.Block, makeWitness // Generate witness if requested var witness *stateless.Witness if makeWitness && bc.chainConfig.IsByzantium(block.Number()) { - witness, err = stateless.NewWitness(block.Header(), bc) + witness, err = stateless.NewWitness(updatedBlock.Header(), bc) if err != nil { return nil, nil, err } diff --git a/core/blockchain_reader.go b/core/blockchain_reader.go index 7626e9e30d..cce22f14e6 100644 --- a/core/blockchain_reader.go +++ b/core/blockchain_reader.go @@ -30,6 +30,7 @@ import ( "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/vm" "github.com/ethereum/go-ethereum/event" + "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/rlp" "github.com/ethereum/go-ethereum/triedb" @@ -181,6 +182,7 @@ func (bc *BlockChain) GetBlock(hash common.Hash, number uint64) *types.Block { // GetBlockByHash retrieves a block from the database by hash, caching it if found. func (bc *BlockChain) GetBlockByHash(hash common.Hash) *types.Block { number := bc.hc.GetBlockNumber(hash) + log.Info("GetBlockByHash", "hash", hash, "number", number) if number == nil { return nil } diff --git a/core/headerchain.go b/core/headerchain.go index 6e70dfa865..db7b998022 100644 --- a/core/headerchain.go +++ b/core/headerchain.go @@ -99,9 +99,12 @@ func NewHeaderChain(chainDb ethdb.Database, config *params.ChainConfig, engine c // from the cache or database func (hc *HeaderChain) GetBlockNumber(hash common.Hash) *uint64 { if cached, ok := hc.numberCache.Get(hash); ok { + log.Info("GetBlockNumber", "hash", hash, "cached", cached) return &cached } + log.Info("GetBlockNumber", "hash", hash, "cached", "not cached") number := rawdb.ReadHeaderNumber(hc.chainDb, hash) + log.Info("ReadHeaderNumber", "hash", hash, "number", number) if number != nil { hc.numberCache.Add(hash, *number) } diff --git a/core/rawdb/accessors_chain.go b/core/rawdb/accessors_chain.go index 4426c6a9e7..cb497143d9 100644 --- a/core/rawdb/accessors_chain.go +++ b/core/rawdb/accessors_chain.go @@ -154,6 +154,7 @@ func ReadHeaderNumber(db ethdb.KeyValueReader, hash common.Hash) *uint64 { // WriteHeaderNumber stores the hash->number mapping. func WriteHeaderNumber(db ethdb.KeyValueWriter, hash common.Hash, number uint64) { + log.Info("WriteHeaderNumber", "hash", hash, "number", number) key := headerNumberKey(hash) enc := encodeBlockNumber(number) if err := db.Put(key, enc); err != nil { diff --git a/eth/catalyst/api.go b/eth/catalyst/api.go index 428089d905..d5921c4961 100644 --- a/eth/catalyst/api.go +++ b/eth/catalyst/api.go @@ -260,7 +260,7 @@ func (api *ConsensusAPI) forkchoiceUpdated(update engine.ForkchoiceStateV1, payl api.forkchoiceLock.Lock() defer api.forkchoiceLock.Unlock() - log.Trace("Engine API request received", "method", "ForkchoiceUpdated", "head", update.HeadBlockHash, "finalized", update.FinalizedBlockHash, "safe", update.SafeBlockHash) + log.Info("Engine API request received", "method", "ForkchoiceUpdated", "head", update.HeadBlockHash, "finalized", update.FinalizedBlockHash, "safe", update.SafeBlockHash) if update.HeadBlockHash == (common.Hash{}) { log.Warn("Forkchoice requested update to zero hash") return engine.STATUS_INVALID, nil // TODO(karalabe): Why does someone send us this? @@ -674,7 +674,7 @@ func (api *ConsensusAPI) newPayload(params engine.ExecutableData, versionedHashe api.newPayloadLock.Lock() defer api.newPayloadLock.Unlock() - log.Trace("Engine API request received", "method", "NewPayload", "number", params.Number, "hash", params.BlockHash) + log.Info("Engine API request received", "method", "NewPayload", "number", params.Number, "hash", params.BlockHash) block, err := engine.ExecutableDataToBlock(params, versionedHashes, beaconRoot, requests) if err != nil { bgu := "nil" @@ -712,11 +712,11 @@ func (api *ConsensusAPI) newPayload(params engine.ExecutableData, versionedHashe // If we already have the block locally, ignore the entire execution and just // return a fake success. - if block := api.eth.BlockChain().GetBlockByHash(params.BlockHash); block != nil { + /*if block := api.eth.BlockChain().GetBlockByHash(params.BlockHash); block != nil { log.Warn("Ignoring already known beacon payload", "number", params.Number, "hash", params.BlockHash, "age", common.PrettyAge(time.Unix(int64(block.Time()), 0))) hash := block.Hash() return engine.PayloadStatusV1{Status: engine.VALID, LatestValidHash: &hash}, nil - } + }*/ // If this block was rejected previously, keep rejecting it if res := api.checkInvalidAncestor(block.Hash(), block.Hash()); res != nil { return *res, nil @@ -747,7 +747,7 @@ func (api *ConsensusAPI) newPayload(params engine.ExecutableData, versionedHashe log.Warn("State not available, ignoring new payload") return engine.PayloadStatusV1{Status: engine.ACCEPTED}, nil } - log.Trace("Inserting block without sethead", "hash", block.Hash(), "number", block.Number()) + log.Info("Inserting block without sethead", "hash", block.Hash(), "number", block.Number()) newHeader, proofs, err := api.eth.BlockChain().InsertBlockWithoutSetHead(block, witness) if err != nil { log.Warn("NewPayload: inserting block failed", "error", err) @@ -760,6 +760,7 @@ func (api *ConsensusAPI) newPayload(params engine.ExecutableData, versionedHashe return api.invalid(err, parent.Header()), nil } hash := newHeader.Hash() + log.Info("NewHeader", "hash", hash, "root", newHeader.Root) // If witness collection was requested, inject that into the result too var ow *hexutil.Bytes diff --git a/miner/worker.go b/miner/worker.go index 198745ad27..7ff4f69b02 100644 --- a/miner/worker.go +++ b/miner/worker.go @@ -35,6 +35,7 @@ import ( "github.com/ethereum/go-ethereum/crypto/kzg4844" "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/params" + "github.com/ethereum/go-ethereum/trie" "github.com/holiman/uint256" ) @@ -100,6 +101,8 @@ func (miner *Miner) generateWork(params *generateParams, witness bool) *newPaylo if err != nil { return &newPayloadResult{err: err} } + + // Use gas limit for block creation instead of executing transactions if !params.noTxs { interrupt := new(atomic.Int32) timer := time.AfterFunc(miner.config.Recommit, func() { @@ -141,10 +144,9 @@ func (miner *Miner) generateWork(params *generateParams, witness bool) *newPaylo work.header.RequestsHash = &reqHash } - block, err := miner.engine.FinalizeAndAssemble(miner.chain, work.header, work.state, &body, work.receipts) - if err != nil { - return &newPayloadResult{err: err} - } + // Directly construct the block without calling FinalizeAndAssemble + // This returns a block with the current header, body, and receipts + block := types.NewBlock(work.header, &body, work.receipts, trie.NewStackTrie(nil)) return &newPayloadResult{ block: block, fees: totalFees(block, work.receipts), @@ -267,13 +269,36 @@ func (miner *Miner) commitTransaction(env *environment, tx *types.Transaction) e if tx.Type() == types.BlobTxType { return miner.commitBlobTransaction(env, tx) } - receipt, err := miner.applyTransaction(env, tx) - if err != nil { - return err + + // Set gas used to transaction's gas limit + gasUsed := tx.Gas() + + // Create a mock receipt for the transaction without execution + receipt := &types.Receipt{ + Type: tx.Type(), + PostState: nil, // No state changes + Status: 1, // Success status + CumulativeGasUsed: env.header.GasUsed + gasUsed, + Logs: []*types.Log{}, + TxHash: tx.Hash(), + ContractAddress: common.Address{}, + GasUsed: gasUsed, + BlockHash: env.header.Hash(), + BlockNumber: env.header.Number, + TransactionIndex: uint(env.tcount), } + + // Add transaction to block without execution env.txs = append(env.txs, tx) env.receipts = append(env.receipts, receipt) env.tcount++ + + // Accumulate gas used for this transaction + env.header.GasUsed += gasUsed + + // Consume transaction's gas limit from pool + env.gasPool.SubGas(gasUsed) + return nil } @@ -290,16 +315,41 @@ func (miner *Miner) commitBlobTransaction(env *environment, tx *types.Transactio if env.blobs+len(sc.Blobs) > maxBlobs { return errors.New("max data blobs reached") } - receipt, err := miner.applyTransaction(env, tx) - if err != nil { - return err + + // Set gas used to transaction's gas limit + gasUsed := tx.Gas() + blobGasUsed := uint64(len(sc.Blobs)) * params.BlobTxBlobGasPerBlob + + // Create a mock receipt for the blob transaction without execution + receipt := &types.Receipt{ + Type: tx.Type(), + PostState: nil, // No state changes + Status: 1, // Success status + CumulativeGasUsed: env.header.GasUsed + gasUsed, + Logs: []*types.Log{}, + TxHash: tx.Hash(), + ContractAddress: common.Address{}, + GasUsed: gasUsed, + BlobGasUsed: blobGasUsed, + BlockHash: env.header.Hash(), + BlockNumber: env.header.Number, + TransactionIndex: uint(env.tcount), } + + // Add transaction to block without execution env.txs = append(env.txs, tx.WithoutBlobTxSidecar()) env.receipts = append(env.receipts, receipt) env.sidecars = append(env.sidecars, sc) env.blobs += len(sc.Blobs) *env.header.BlobGasUsed += receipt.BlobGasUsed env.tcount++ + + // Accumulate gas used for this transaction + env.header.GasUsed += gasUsed + + // Consume transaction's gas limit from pool + env.gasPool.SubGas(gasUsed) + return nil } @@ -444,8 +494,8 @@ func (miner *Miner) commitTransactions(env *environment, plainTxs, blobTxs *tran } // fillTransactions retrieves the pending transactions from the txpool and fills them -// into the given sealing block. The transaction selection and ordering strategy can -// be customized with the plugin in the future. +// into the given sealing block based on gas limit without executing them. +// The transaction selection and ordering strategy can be customized with the plugin in the future. func (miner *Miner) fillTransactions(interrupt *atomic.Int32, env *environment) error { miner.confMu.RLock() tip := miner.config.GasPrice @@ -482,6 +532,7 @@ func (miner *Miner) fillTransactions(interrupt *atomic.Int32, env *environment) prioBlobTxs[account] = txs } } + // Fill the block with all available pending transactions. if len(prioPlainTxs) > 0 || len(prioBlobTxs) > 0 { plainTxs := newTransactionsByPriceAndNonce(env.signer, prioPlainTxs, env.header.BaseFee)