Merge pull request #1475 from obscuren/issue1473

core: during chain reorg rewrite receipts and transactions
pull/1476/head
Jeffrey Wilcke 9 years ago
commit 9addb3df3a
  1. 4
      core/block_processor.go
  2. 7
      core/chain_manager.go
  3. 48
      core/transaction_util.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 {

@ -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()

@ -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
}

Loading…
Cancel
Save