light: light chain, VM env and tx pool

This commit is contained in:
Zsolt Felfoldi
2016-10-14 05:47:09 +02:00
committed by Felix Lange
parent 8b1df1a259
commit 760fd65487
15 changed files with 2645 additions and 127 deletions

View File

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

View File

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

View File

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