From 02d2646df4e8e7f12efae92cc941b014687c4553 Mon Sep 17 00:00:00 2001 From: JukLee0ira Date: Sat, 10 Aug 2024 15:48:03 +0800 Subject: [PATCH 1/3] core/rawdb: rearranging function order --- core/rawdb/accessors_chain.go | 54 +++++++++++++++++------------------ 1 file changed, 27 insertions(+), 27 deletions(-) diff --git a/core/rawdb/accessors_chain.go b/core/rawdb/accessors_chain.go index bb79f9b71a42..6790fe141c58 100644 --- a/core/rawdb/accessors_chain.go +++ b/core/rawdb/accessors_chain.go @@ -62,6 +62,27 @@ func WriteHeadBlockHash(db ethdb.KeyValueWriter, hash common.Hash) { } } +// WriteHeader stores a block header into the database and also stores the hash- +// to-number mapping. +func WriteHeader(db ethdb.KeyValueWriter, header *types.Header) { + var ( + hash = header.Hash() + number = header.Number.Uint64() + ) + // Write the hash -> number mapping + WriteHeaderNumber(db, hash, number) + + // Write the encoded header + data, err := rlp.EncodeToBytes(header) + if err != nil { + log.Crit("Failed to RLP encode header", "err", err) + } + key := headerKey(number, hash) + if err := db.Put(key, data); err != nil { + log.Crit("Failed to store header", "err", err) + } +} + // ReadBodyRLP retrieves the block body (transactions and uncles) in RLP encoding. func ReadBodyRLP(db ethdb.Reader, hash common.Hash, number uint64) rlp.RawValue { // First try to look up the data in ancient database. Extra hash @@ -123,27 +144,6 @@ func WriteBody(db ethdb.KeyValueWriter, hash common.Hash, number uint64, body *t WriteBodyRLP(db, hash, number, data) } -// WriteHeader stores a block header into the database and also stores the hash- -// to-number mapping. -func WriteHeader(db ethdb.KeyValueWriter, header *types.Header) { - var ( - hash = header.Hash() - number = header.Number.Uint64() - ) - // Write the hash -> number mapping - WriteHeaderNumber(db, hash, number) - - // Write the encoded header - data, err := rlp.EncodeToBytes(header) - if err != nil { - log.Crit("Failed to RLP encode header", "err", err) - } - key := headerKey(number, hash) - if err := db.Put(key, data); err != nil { - log.Crit("Failed to store header", "err", err) - } -} - // ReadReceiptsRLP retrieves all the transaction receipts belonging to a block in RLP encoding. func ReadReceiptsRLP(db ethdb.Reader, hash common.Hash, number uint64) rlp.RawValue { // First try to look up the data in ancient database. Extra hash @@ -239,12 +239,6 @@ func WriteReceipts(db ethdb.KeyValueWriter, hash common.Hash, number uint64, rec } } -// WriteBlock serializes a block into the database, header and body separately. -func WriteBlock(db ethdb.KeyValueWriter, block *types.Block) { - WriteBody(db, block.Hash(), block.NumberU64(), block.Body()) - WriteHeader(db, block.Header()) -} - // storedReceiptRLP is the storage encoding of a receipt. // Re-definition in core/types/receipt.go. type storedReceiptRLP struct { @@ -319,3 +313,9 @@ func ReadLogs(db ethdb.Reader, hash common.Hash, number uint64) [][]*types.Log { } return logs } + +// WriteBlock serializes a block into the database, header and body separately. +func WriteBlock(db ethdb.KeyValueWriter, block *types.Block) { + WriteBody(db, block.Hash(), block.NumberU64(), block.Body()) + WriteHeader(db, block.Header()) +} From a75c6d9cb11eab3ce415cfcff825ca1011164b84 Mon Sep 17 00:00:00 2001 From: JukLee0ira Date: Thu, 15 Aug 2024 13:37:00 +0800 Subject: [PATCH 2/3] miner: implement function updateSnapshot --- miner/worker.go | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/miner/worker.go b/miner/worker.go index 64b195b30fa1..447f5a1b8827 100644 --- a/miner/worker.go +++ b/miner/worker.go @@ -131,6 +131,7 @@ type worker struct { snapshotMu sync.RWMutex // The lock used to protect the block snapshot and state snapshot snapshotBlock *types.Block snapshotReceipts types.Receipts + snapshotState *state.StateDB currentMu sync.Mutex current *Work @@ -337,7 +338,15 @@ func (self *worker) update() { } feeCapacity := state.GetTRC21FeeCapacityFromState(self.current.state) txset, specialTxs := types.NewTransactionsByPriceAndNonce(self.current.signer, txs, nil, feeCapacity) + + tcount := self.current.tcount self.current.commitTransactions(self.mux, feeCapacity, txset, specialTxs, self.chain, self.coinbase, &self.pendingLogsFeed) + + // Only update the snapshot if any new transactions were added + // to the pending block + if tcount != self.current.tcount { + self.updateSnapshot() + } self.currentMu.Unlock() } else { // If we're mining, but nothing is being processed, wake on new transactions @@ -477,6 +486,32 @@ func (self *worker) push(work *Work) { } } +// copyReceipts makes a deep copy of the given receipts. +func copyReceipts(receipts []*types.Receipt) []*types.Receipt { + result := make([]*types.Receipt, len(receipts)) + for i, l := range receipts { + cpy := *l + result[i] = &cpy + } + return result +} + +// updateSnapshot updates pending snapshot block and state. +// Note this function assumes the current variable is thread safe. +func (w *worker) updateSnapshot() { + w.snapshotMu.Lock() + defer w.snapshotMu.Unlock() + + w.snapshotBlock = types.NewBlock( + w.current.header, + w.current.txs, + nil, + w.current.receipts, + ) + w.snapshotReceipts = copyReceipts(w.current.receipts) + w.snapshotState = w.current.state.Copy() +} + // makeCurrent creates a new environment for the current cycle. func (self *worker) makeCurrent(parent *types.Block, header *types.Header) error { // Retrieve the parent state to execute on top and start a prefetcher for @@ -814,6 +849,7 @@ func (self *worker) commitNewWork() { self.lastParentBlockCommit = parent.Hash().Hex() } self.push(work) + self.updateSnapshot() } func (env *Work) commitTransactions(mux *event.TypeMux, balanceFee map[common.Address]*big.Int, txs *types.TransactionsByPriceAndNonce, specialTxs types.Transactions, bc *core.BlockChain, coinbase common.Address, pendingLogsFeed *event.Feed) { From db869b7d72b446f798c2ca131a3a579ae3c3a4e6 Mon Sep 17 00:00:00 2001 From: JukLee0ira Date: Thu, 15 Aug 2024 13:40:08 +0800 Subject: [PATCH 3/3] miner: optimize function pending and pendingBlock --- miner/worker.go | 39 ++++++++++++++------------------------- 1 file changed, 14 insertions(+), 25 deletions(-) diff --git a/miner/worker.go b/miner/worker.go index 447f5a1b8827..0e341636d243 100644 --- a/miner/worker.go +++ b/miner/worker.go @@ -194,34 +194,23 @@ func (self *worker) setExtra(extra []byte) { self.extra = extra } -func (self *worker) pending() (*types.Block, *state.StateDB) { - self.currentMu.Lock() - defer self.currentMu.Unlock() - - if atomic.LoadInt32(&self.mining) == 0 { - return types.NewBlock( - self.current.header, - self.current.txs, - nil, - self.current.receipts, - ), self.current.state.Copy() +// pending returns the pending state and corresponding block. The returned +// values can be nil in case the pending block is not initialized. +func (w *worker) pending() (*types.Block, *state.StateDB) { + w.snapshotMu.RLock() + defer w.snapshotMu.RUnlock() + if w.snapshotState == nil { + return nil, nil } - return self.current.Block, self.current.state.Copy() + return w.snapshotBlock, w.snapshotState.Copy() } -func (self *worker) pendingBlock() *types.Block { - self.currentMu.Lock() - defer self.currentMu.Unlock() - - if atomic.LoadInt32(&self.mining) == 0 { - return types.NewBlock( - self.current.header, - self.current.txs, - nil, - self.current.receipts, - ) - } - return self.current.Block +// pendingBlock returns pending block. The returned block can be nil in case the +// pending block is not initialized. +func (w *worker) pendingBlock() *types.Block { + w.snapshotMu.RLock() + defer w.snapshotMu.RUnlock() + return w.snapshotBlock } // pendingBlockAndReceipts returns pending block and corresponding receipts.