aboutsummaryrefslogtreecommitdiffstats
path: root/core
diff options
context:
space:
mode:
Diffstat (limited to 'core')
-rw-r--r--core/blockchain.go58
-rw-r--r--core/database_util.go44
-rw-r--r--core/types/json_test.go16
3 files changed, 91 insertions, 27 deletions
diff --git a/core/blockchain.go b/core/blockchain.go
index d806c143d..791a8b91d 100644
--- a/core/blockchain.go
+++ b/core/blockchain.go
@@ -632,6 +632,37 @@ func (self *BlockChain) Rollback(chain []common.Hash) {
}
}
+// SetReceiptsData computes all the non-consensus fields of the receipts
+func SetReceiptsData(block *types.Block, receipts types.Receipts) {
+ transactions, logIndex := block.Transactions(), uint(0)
+
+ for j := 0; j < len(receipts); j++ {
+ // The transaction hash can be retrieved from the transaction itself
+ receipts[j].TxHash = transactions[j].Hash()
+
+ // The contract address can be derived from the transaction itself
+ if MessageCreatesContract(transactions[j]) {
+ from, _ := transactions[j].From()
+ receipts[j].ContractAddress = crypto.CreateAddress(from, transactions[j].Nonce())
+ }
+ // The used gas can be calculated based on previous receipts
+ if j == 0 {
+ receipts[j].GasUsed = new(big.Int).Set(receipts[j].CumulativeGasUsed)
+ } else {
+ receipts[j].GasUsed = new(big.Int).Sub(receipts[j].CumulativeGasUsed, receipts[j-1].CumulativeGasUsed)
+ }
+ // The derived log fields can simply be set from the block and transaction
+ for k := 0; k < len(receipts[j].Logs); k++ {
+ receipts[j].Logs[k].BlockNumber = block.NumberU64()
+ receipts[j].Logs[k].BlockHash = block.Hash()
+ receipts[j].Logs[k].TxHash = receipts[j].TxHash
+ receipts[j].Logs[k].TxIndex = uint(j)
+ receipts[j].Logs[k].Index = logIndex
+ logIndex++
+ }
+ }
+}
+
// InsertReceiptChain attempts to complete an already existing header chain with
// transaction and receipt data.
func (self *BlockChain) InsertReceiptChain(blockChain types.Blocks, receiptChain []types.Receipts) (int, error) {
@@ -673,32 +704,7 @@ func (self *BlockChain) InsertReceiptChain(blockChain types.Blocks, receiptChain
continue
}
// Compute all the non-consensus fields of the receipts
- transactions, logIndex := block.Transactions(), uint(0)
- for j := 0; j < len(receipts); j++ {
- // The transaction hash can be retrieved from the transaction itself
- receipts[j].TxHash = transactions[j].Hash()
-
- // The contract address can be derived from the transaction itself
- if MessageCreatesContract(transactions[j]) {
- from, _ := transactions[j].From()
- receipts[j].ContractAddress = crypto.CreateAddress(from, transactions[j].Nonce())
- }
- // The used gas can be calculated based on previous receipts
- if j == 0 {
- receipts[j].GasUsed = new(big.Int).Set(receipts[j].CumulativeGasUsed)
- } else {
- receipts[j].GasUsed = new(big.Int).Sub(receipts[j].CumulativeGasUsed, receipts[j-1].CumulativeGasUsed)
- }
- // The derived log fields can simply be set from the block and transaction
- for k := 0; k < len(receipts[j].Logs); k++ {
- receipts[j].Logs[k].BlockNumber = block.NumberU64()
- receipts[j].Logs[k].BlockHash = block.Hash()
- receipts[j].Logs[k].TxHash = receipts[j].TxHash
- receipts[j].Logs[k].TxIndex = uint(j)
- receipts[j].Logs[k].Index = logIndex
- logIndex++
- }
- }
+ SetReceiptsData(block, receipts)
// Write all the data out into the database
if err := WriteBody(self.chainDb, block.Hash(), block.NumberU64(), block.Body()); err != nil {
errs[index] = fmt.Errorf("failed to write block body: %v", err)
diff --git a/core/database_util.go b/core/database_util.go
index 5f9afe6ba..0fb593554 100644
--- a/core/database_util.go
+++ b/core/database_util.go
@@ -347,8 +347,13 @@ func WriteBody(db ethdb.Database, hash common.Hash, number uint64, body *types.B
if err != nil {
return err
}
+ return WriteBodyRLP(db, hash, number, data)
+}
+
+// WriteBodyRLP writes a serialized body of a block into the database.
+func WriteBodyRLP(db ethdb.Database, hash common.Hash, number uint64, rlp rlp.RawValue) error {
key := append(append(bodyPrefix, encodeBlockNumber(number)...), hash.Bytes()...)
- if err := db.Put(key, data); err != nil {
+ if err := db.Put(key, rlp); err != nil {
glog.Fatalf("failed to store block body into database: %v", err)
}
glog.V(logger.Debug).Infof("stored block body [%x…]", hash.Bytes()[:4])
@@ -446,6 +451,16 @@ func WriteTransactions(db ethdb.Database, block *types.Block) error {
return nil
}
+// WriteReceipt stores a single transaction receipt into the database.
+func WriteReceipt(db ethdb.Database, receipt *types.Receipt) error {
+ storageReceipt := (*types.ReceiptForStorage)(receipt)
+ data, err := rlp.EncodeToBytes(storageReceipt)
+ if err != nil {
+ return err
+ }
+ return db.Put(append(receiptsPrefix, receipt.TxHash.Bytes()...), data)
+}
+
// WriteReceipts stores a batch of transaction receipts into the database.
func WriteReceipts(db ethdb.Database, receipts types.Receipts) error {
batch := db.NewBatch()
@@ -614,3 +629,30 @@ func GetChainConfig(db ethdb.Database, hash common.Hash) (*ChainConfig, error) {
return &config, nil
}
+
+// FindCommonAncestor returns the last common ancestor of two block headers
+func FindCommonAncestor(db ethdb.Database, a, b *types.Header) *types.Header {
+ for bn := b.Number.Uint64(); a.Number.Uint64() > bn; {
+ a = GetHeader(db, a.ParentHash, a.Number.Uint64()-1)
+ if a == nil {
+ return nil
+ }
+ }
+ for an := a.Number.Uint64(); an < b.Number.Uint64(); {
+ b = GetHeader(db, b.ParentHash, b.Number.Uint64()-1)
+ if b == nil {
+ return nil
+ }
+ }
+ for a.Hash() != b.Hash() {
+ a = GetHeader(db, a.ParentHash, a.Number.Uint64()-1)
+ if a == nil {
+ return nil
+ }
+ b = GetHeader(db, b.ParentHash, b.Number.Uint64()-1)
+ if b == nil {
+ return nil
+ }
+ }
+ return a
+}
diff --git a/core/types/json_test.go b/core/types/json_test.go
index e17424c82..a028b5d08 100644
--- a/core/types/json_test.go
+++ b/core/types/json_test.go
@@ -1,3 +1,19 @@
+// Copyright 2016 The go-ethereum Authors
+// This file is part of the go-ethereum library.
+//
+// The go-ethereum library is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// The go-ethereum library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
+
package types
import (