Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix a bug in PR #583: snapshot is not updated #604

Merged
merged 3 commits into from
Aug 19, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
54 changes: 27 additions & 27 deletions core/rawdb/accessors_chain.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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 {
Expand Down Expand Up @@ -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())
}
75 changes: 50 additions & 25 deletions miner/worker.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -193,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.
Expand Down Expand Up @@ -337,7 +327,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
Expand Down Expand Up @@ -477,6 +475,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
Expand Down Expand Up @@ -814,6 +838,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) {
Expand Down