diff options
author | Jeffrey Wilcke <jeffrey@ethereum.org> | 2015-07-16 04:17:07 +0800 |
---|---|---|
committer | Jeffrey Wilcke <jeffrey@ethereum.org> | 2015-07-16 04:17:07 +0800 |
commit | 9addb3df3a88ebfa5f54ca4cebb5850f0e4b21f7 (patch) | |
tree | 02571dfa0b85ea2e7fe23f25d062ee319300f1d9 | |
parent | cecc9cdd2f799ddaf189d62d9d43892f7dc82ebc (diff) | |
parent | e17d8ddbeb01a7e3eb745431d39c93661e167bbc (diff) | |
download | dexon-9addb3df3a88ebfa5f54ca4cebb5850f0e4b21f7.tar.gz dexon-9addb3df3a88ebfa5f54ca4cebb5850f0e4b21f7.tar.zst dexon-9addb3df3a88ebfa5f54ca4cebb5850f0e4b21f7.zip |
Merge pull request #1475 from obscuren/issue1473
core: during chain reorg rewrite receipts and transactions
-rw-r--r-- | core/block_processor.go | 4 | ||||
-rw-r--r-- | core/chain_manager.go | 7 | ||||
-rw-r--r-- | core/transaction_util.go | 48 |
3 files changed, 46 insertions, 13 deletions
diff --git a/core/block_processor.go b/core/block_processor.go index f50ebb55a..e24b290dd 100644 --- a/core/block_processor.go +++ b/core/block_processor.go @@ -342,7 +342,7 @@ func (sm *BlockProcessor) VerifyUncles(statedb *state.StateDB, block, parent *ty // GetBlockReceipts returns the receipts beloniging to the block hash func (sm *BlockProcessor) GetBlockReceipts(bhash common.Hash) types.Receipts { if block := sm.ChainManager().GetBlock(bhash); block != nil { - return GetReceiptsFromBlock(sm.extraDb, block) + return GetBlockReceipts(sm.extraDb, block.Hash()) } return nil @@ -352,7 +352,7 @@ func (sm *BlockProcessor) GetBlockReceipts(bhash common.Hash) types.Receipts { // where it tries to get it from the (updated) method which gets them from the receipts or // the depricated way by re-processing the block. func (sm *BlockProcessor) GetLogs(block *types.Block) (logs state.Logs, err error) { - receipts := GetReceiptsFromBlock(sm.extraDb, block) + receipts := GetBlockReceipts(sm.extraDb, block.Hash()) if len(receipts) > 0 { // coalesce logs for _, receipt := range receipts { diff --git a/core/chain_manager.go b/core/chain_manager.go index 8fa13ddec..1a703d084 100644 --- a/core/chain_manager.go +++ b/core/chain_manager.go @@ -667,6 +667,8 @@ func (self *ChainManager) InsertChain(chain types.Blocks) (int, error) { queue[i] = ChainSplitEvent{block, logs} queueEvent.splitCount++ } + PutBlockReceipts(self.extraDb, block, receipts) + stats.processed++ } @@ -744,7 +746,12 @@ func (self *ChainManager) merge(oldBlock, newBlock *types.Block) error { // insert blocks. Order does not matter. Last block will be written in ImportChain itself which creates the new head properly self.mu.Lock() for _, block := range newChain { + // insert the block in the canonical way, re-writing history self.insert(block) + // write canonical receipts and transactions + PutTransactions(self.extraDb, block, block.Transactions()) + PutReceipts(self.extraDb, GetBlockReceipts(self.extraDb, block.Hash())) + } self.mu.Unlock() diff --git a/core/transaction_util.go b/core/transaction_util.go index 0efeddfde..752d4f088 100644 --- a/core/transaction_util.go +++ b/core/transaction_util.go @@ -24,7 +24,10 @@ import ( "github.com/ethereum/go-ethereum/rlp" ) -var receiptsPre = []byte("receipts-") +var ( + receiptsPre = []byte("receipts-") + blockReceiptsPre = []byte("receipts-block-") +) // PutTransactions stores the transactions in the given database func PutTransactions(db common.Database, block *types.Block, txs types.Transactions) { @@ -85,17 +88,40 @@ func GetReceipt(db common.Database, txHash common.Hash) *types.Receipt { return &receipt } -// GetReceiptFromBlock returns all receipts with the given block -func GetReceiptsFromBlock(db common.Database, block *types.Block) types.Receipts { - // at some point we want: - //receipts := make(types.Receipts, len(block.Transactions())) - // but since we need to support legacy, we can't (yet) - var receipts types.Receipts - for _, tx := range block.Transactions() { - if receipt := GetReceipt(db, tx.Hash()); receipt != nil { - receipts = append(receipts, receipt) - } +// GetBlockReceipts returns the receipts generated by the transactions +// included in block's given hash. +func GetBlockReceipts(db common.Database, hash common.Hash) types.Receipts { + data, _ := db.Get(append(blockReceiptsPre, hash[:]...)) + if len(data) == 0 { + return nil } + var receipts types.Receipts + err := rlp.DecodeBytes(data, &receipts) + if err != nil { + glog.V(logger.Core).Infoln("GetReceiptse err", err) + } return receipts } + +// PutBlockReceipts stores the block's transactions associated receipts +// and stores them by block hash in a single slice. This is required for +// forks and chain reorgs +func PutBlockReceipts(db common.Database, block *types.Block, receipts types.Receipts) error { + rs := make([]*types.ReceiptForStorage, len(receipts)) + for i, receipt := range receipts { + rs[i] = (*types.ReceiptForStorage)(receipt) + } + bytes, err := rlp.EncodeToBytes(rs) + if err != nil { + return err + } + + hash := block.Hash() + err = db.Put(append(blockReceiptsPre, hash[:]...), bytes) + if err != nil { + return err + } + + return nil +} |