aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJeffrey Wilcke <jeffrey@ethereum.org>2015-07-16 04:17:07 +0800
committerJeffrey Wilcke <jeffrey@ethereum.org>2015-07-16 04:17:07 +0800
commit9addb3df3a88ebfa5f54ca4cebb5850f0e4b21f7 (patch)
tree02571dfa0b85ea2e7fe23f25d062ee319300f1d9
parentcecc9cdd2f799ddaf189d62d9d43892f7dc82ebc (diff)
parente17d8ddbeb01a7e3eb745431d39c93661e167bbc (diff)
downloaddexon-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.go4
-rw-r--r--core/chain_manager.go7
-rw-r--r--core/transaction_util.go48
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
+}