From 760fd65487614b7a61443cd9371015925795f40f Mon Sep 17 00:00:00 2001 From: Zsolt Felfoldi Date: Fri, 14 Oct 2016 05:47:09 +0200 Subject: light: light chain, VM env and tx pool --- core/blockchain.go | 58 ++++++++++++++++++++++++++++----------------------- core/database_util.go | 44 +++++++++++++++++++++++++++++++++++++- core/types/block.go | 9 ++++++++ 3 files changed, 84 insertions(+), 27 deletions(-) (limited to 'core') 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..73fac20aa 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 a.GetNumberU64() > b.GetNumberU64() { + a = GetHeader(db, a.ParentHash, a.GetNumberU64()-1) + if a == nil { + return nil + } + } + for a.GetNumberU64() < b.GetNumberU64() { + b = GetHeader(db, b.ParentHash, b.GetNumberU64()-1) + if b == nil { + return nil + } + } + for a.Hash() != b.Hash() { + a = GetHeader(db, a.ParentHash, a.GetNumberU64()-1) + if a == nil { + return nil + } + b = GetHeader(db, b.ParentHash, b.GetNumberU64()-1) + if b == nil { + return nil + } + } + return a +} diff --git a/core/types/block.go b/core/types/block.go index fedcfdbbe..4accb0ee3 100644 --- a/core/types/block.go +++ b/core/types/block.go @@ -116,6 +116,15 @@ type jsonHeader struct { Nonce *BlockNonce `json:"nonce"` } +func (h *Header) GetNumber() *big.Int { return new(big.Int).Set(h.Number) } +func (h *Header) GetGasLimit() *big.Int { return new(big.Int).Set(h.GasLimit) } +func (h *Header) GetGasUsed() *big.Int { return new(big.Int).Set(h.GasUsed) } +func (h *Header) GetDifficulty() *big.Int { return new(big.Int).Set(h.Difficulty) } +func (h *Header) GetTime() *big.Int { return new(big.Int).Set(h.Time) } +func (h *Header) GetNumberU64() uint64 { return h.Number.Uint64() } +func (h *Header) GetNonce() uint64 { return binary.BigEndian.Uint64(h.Nonce[:]) } +func (h *Header) GetExtra() []byte { return common.CopyBytes(h.Extra) } + // Hash returns the block hash of the header, which is simply the keccak256 hash of its // RLP encoding. func (h *Header) Hash() common.Hash { -- cgit v1.2.3 From be3865211c2d8f71e0733b17c469881502e89371 Mon Sep 17 00:00:00 2001 From: Felix Lange Date: Wed, 9 Nov 2016 01:20:49 +0100 Subject: core/types: remove header accessors These accessors were introduced by light client changes, but the only method that is actually used is GetNumberU64. This commit replaces all uses of .GetNumberU64 with .Number.Uint64. --- core/database_util.go | 12 ++++++------ core/types/block.go | 9 --------- 2 files changed, 6 insertions(+), 15 deletions(-) (limited to 'core') diff --git a/core/database_util.go b/core/database_util.go index 73fac20aa..0fb593554 100644 --- a/core/database_util.go +++ b/core/database_util.go @@ -632,24 +632,24 @@ func GetChainConfig(db ethdb.Database, hash common.Hash) (*ChainConfig, error) { // FindCommonAncestor returns the last common ancestor of two block headers func FindCommonAncestor(db ethdb.Database, a, b *types.Header) *types.Header { - for a.GetNumberU64() > b.GetNumberU64() { - a = GetHeader(db, a.ParentHash, a.GetNumberU64()-1) + for bn := b.Number.Uint64(); a.Number.Uint64() > bn; { + a = GetHeader(db, a.ParentHash, a.Number.Uint64()-1) if a == nil { return nil } } - for a.GetNumberU64() < b.GetNumberU64() { - b = GetHeader(db, b.ParentHash, b.GetNumberU64()-1) + 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.GetNumberU64()-1) + a = GetHeader(db, a.ParentHash, a.Number.Uint64()-1) if a == nil { return nil } - b = GetHeader(db, b.ParentHash, b.GetNumberU64()-1) + b = GetHeader(db, b.ParentHash, b.Number.Uint64()-1) if b == nil { return nil } diff --git a/core/types/block.go b/core/types/block.go index 4accb0ee3..fedcfdbbe 100644 --- a/core/types/block.go +++ b/core/types/block.go @@ -116,15 +116,6 @@ type jsonHeader struct { Nonce *BlockNonce `json:"nonce"` } -func (h *Header) GetNumber() *big.Int { return new(big.Int).Set(h.Number) } -func (h *Header) GetGasLimit() *big.Int { return new(big.Int).Set(h.GasLimit) } -func (h *Header) GetGasUsed() *big.Int { return new(big.Int).Set(h.GasUsed) } -func (h *Header) GetDifficulty() *big.Int { return new(big.Int).Set(h.Difficulty) } -func (h *Header) GetTime() *big.Int { return new(big.Int).Set(h.Time) } -func (h *Header) GetNumberU64() uint64 { return h.Number.Uint64() } -func (h *Header) GetNonce() uint64 { return binary.BigEndian.Uint64(h.Nonce[:]) } -func (h *Header) GetExtra() []byte { return common.CopyBytes(h.Extra) } - // Hash returns the block hash of the header, which is simply the keccak256 hash of its // RLP encoding. func (h *Header) Hash() common.Hash { -- cgit v1.2.3 From b8bd9a71c8b2722ec526ac5b0e35bf05d0fbd075 Mon Sep 17 00:00:00 2001 From: Felix Lange Date: Wed, 9 Nov 2016 02:01:56 +0100 Subject: all: update license information --- core/types/json_test.go | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) (limited to 'core') 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 . + package types import ( -- cgit v1.2.3