Refactored block & Transaction

* Includes new rlp decoder
This commit is contained in:
obscuren
2014-12-23 13:48:44 +01:00
parent 4b52cd512d
commit 4cd79d8ddd
19 changed files with 498 additions and 616 deletions

View File

@ -17,6 +17,7 @@ import (
"github.com/ethereum/go-ethereum/pow"
"github.com/ethereum/go-ethereum/pow/ezp"
"github.com/ethereum/go-ethereum/state"
"gopkg.in/fatih/set.v0"
)
var statelogger = logger.NewLogger("BLOCK")
@ -82,8 +83,8 @@ func NewBlockManager(txpool *TxPool, chainManager *ChainManager, eventMux *event
}
func (sm *BlockManager) TransitionState(statedb *state.StateDB, parent, block *types.Block) (receipts types.Receipts, err error) {
coinbase := statedb.GetOrNewStateObject(block.Coinbase)
coinbase.SetGasPool(block.CalcGasLimit(parent))
coinbase := statedb.GetOrNewStateObject(block.Header().Coinbase)
coinbase.SetGasPool(CalcGasLimit(parent, block))
// Process the transactions on to current block
receipts, _, _, _, err = sm.ApplyTransactions(coinbase, statedb, block, block.Transactions(), false)
@ -156,7 +157,7 @@ done:
}
block.Reward = cumulativeSum
block.GasUsed = totalUsedGas
block.Header().GasUsed = totalUsedGas
return receipts, handled, unhandled, erroneous, err
}
@ -166,14 +167,15 @@ func (sm *BlockManager) Process(block *types.Block) (td *big.Int, msgs state.Mes
sm.mutex.Lock()
defer sm.mutex.Unlock()
if sm.bc.HasBlock(block.Hash()) {
return nil, nil, &KnownBlockError{block.Number, block.Hash()}
header := block.Header()
if sm.bc.HasBlock(header.Hash()) {
return nil, nil, &KnownBlockError{header.Number, header.Hash()}
}
if !sm.bc.HasBlock(block.PrevHash) {
return nil, nil, ParentError(block.PrevHash)
if !sm.bc.HasBlock(header.ParentHash) {
return nil, nil, ParentError(header.ParentHash)
}
parent := sm.bc.GetBlock(block.PrevHash)
parent := sm.bc.GetBlock(header.ParentHash)
return sm.ProcessWithParent(block, parent)
}
@ -181,7 +183,7 @@ func (sm *BlockManager) Process(block *types.Block) (td *big.Int, msgs state.Mes
func (sm *BlockManager) ProcessWithParent(block, parent *types.Block) (td *big.Int, messages state.Messages, err error) {
sm.lastAttemptedBlock = block
state := parent.State().Copy()
state := state.New(parent.Trie().Copy())
// Defer the Undo on the Trie. If the block processing happened
// we don't want to undo but since undo only happens on dirty
@ -199,23 +201,23 @@ func (sm *BlockManager) ProcessWithParent(block, parent *types.Block) (td *big.I
return
}
header := block.Header()
rbloom := types.CreateBloom(receipts)
if bytes.Compare(rbloom, block.LogsBloom) != 0 {
if bytes.Compare(rbloom, header.Bloom) != 0 {
err = fmt.Errorf("unable to replicate block's bloom=%x", rbloom)
return
}
txSha := types.DeriveSha(block.Transactions())
if bytes.Compare(txSha, block.TxSha) != 0 {
err = fmt.Errorf("validating transaction root. received=%x got=%x", block.TxSha, txSha)
if bytes.Compare(txSha, header.TxHash) != 0 {
err = fmt.Errorf("validating transaction root. received=%x got=%x", header.TxHash, txSha)
return
}
receiptSha := types.DeriveSha(receipts)
if bytes.Compare(receiptSha, block.ReceiptSha) != 0 {
//chainlogger.Debugf("validating receipt root. received=%x got=%x", block.ReceiptSha, receiptSha)
fmt.Printf("%x\n", ethutil.Encode(receipts))
err = fmt.Errorf("validating receipt root. received=%x got=%x", block.ReceiptSha, receiptSha)
if bytes.Compare(receiptSha, header.ReceiptHash) != 0 {
err = fmt.Errorf("validating receipt root. received=%x got=%x", header.ReceiptHash, receiptSha)
return
}
@ -225,8 +227,8 @@ func (sm *BlockManager) ProcessWithParent(block, parent *types.Block) (td *big.I
state.Update(ethutil.Big0)
if !block.State().Cmp(state) {
err = fmt.Errorf("invalid merkle root. received=%x got=%x", block.Root(), state.Root())
if !bytes.Equal(header.Root, state.Root()) {
err = fmt.Errorf("invalid merkle root. received=%x got=%x", header.Root, state.Root())
return
}
@ -238,7 +240,7 @@ func (sm *BlockManager) ProcessWithParent(block, parent *types.Block) (td *big.I
messages := state.Manifest().Messages
state.Manifest().Reset()
chainlogger.Infof("Processed block #%d (%x...)\n", block.Number, block.Hash()[0:4])
chainlogger.Infof("Processed block #%d (%x...)\n", header.Number, block.Hash()[0:4])
sm.txpool.RemoveSet(block.Transactions())
@ -250,14 +252,14 @@ func (sm *BlockManager) ProcessWithParent(block, parent *types.Block) (td *big.I
func (sm *BlockManager) CalculateTD(block *types.Block) (*big.Int, bool) {
uncleDiff := new(big.Int)
for _, uncle := range block.Uncles {
for _, uncle := range block.Uncles() {
uncleDiff = uncleDiff.Add(uncleDiff, uncle.Difficulty)
}
// TD(genesis_block) = 0 and TD(B) = TD(B.parent) + sum(u.difficulty for u in B.uncles) + B.difficulty
td := new(big.Int)
td = td.Add(sm.bc.Td(), uncleDiff)
td = td.Add(td, block.Difficulty)
td = td.Add(td, block.Header().Difficulty)
// The new TD will only be accepted if the new difficulty is
// is greater than the previous.
@ -273,13 +275,13 @@ func (sm *BlockManager) CalculateTD(block *types.Block) (*big.Int, bool) {
// Validation validates easy over difficult (dagger takes longer time = difficult)
func (sm *BlockManager) ValidateBlock(block, parent *types.Block) error {
expd := CalcDifficulty(block, parent)
if expd.Cmp(block.Difficulty) < 0 {
return fmt.Errorf("Difficulty check failed for block %v, %v", block.Difficulty, expd)
if expd.Cmp(block.Header().Difficulty) < 0 {
return fmt.Errorf("Difficulty check failed for block %v, %v", block.Header().Difficulty, expd)
}
diff := block.Time - parent.Time
diff := block.Header().Time - parent.Header().Time
if diff < 0 {
return ValidationError("Block timestamp less then prev block %v (%v - %v)", diff, block.Time, sm.bc.CurrentBlock().Time)
return ValidationError("Block timestamp less then prev block %v (%v - %v)", diff, block.Header().Time, sm.bc.CurrentBlock().Header().Time)
}
/* XXX
@ -291,7 +293,7 @@ func (sm *BlockManager) ValidateBlock(block, parent *types.Block) error {
// Verify the nonce of the block. Return an error if it's not valid
if !sm.Pow.Verify(block /*block.HashNoNonce(), block.Difficulty, block.Nonce*/) {
return ValidationError("Block's nonce is invalid (= %v)", ethutil.Bytes2Hex(block.Nonce))
return ValidationError("Block's nonce is invalid (= %v)", ethutil.Bytes2Hex(block.Header().Nonce))
}
return nil
@ -300,24 +302,28 @@ func (sm *BlockManager) ValidateBlock(block, parent *types.Block) error {
func (sm *BlockManager) AccumelateRewards(statedb *state.StateDB, block, parent *types.Block) error {
reward := new(big.Int).Set(BlockReward)
knownUncles := ethutil.Set(parent.Uncles)
nonces := ethutil.NewSet(block.Nonce)
for _, uncle := range block.Uncles {
knownUncles := set.New()
for _, uncle := range parent.Uncles() {
knownUncles.Add(uncle.Hash())
}
nonces := ethutil.NewSet(block.Header().Nonce)
for _, uncle := range block.Uncles() {
if nonces.Include(uncle.Nonce) {
// Error not unique
return UncleError("Uncle not unique")
}
uncleParent := sm.bc.GetBlock(uncle.PrevHash)
uncleParent := sm.bc.GetBlock(uncle.ParentHash)
if uncleParent == nil {
return UncleError(fmt.Sprintf("Uncle's parent unknown (%x)", uncle.PrevHash[0:4]))
return UncleError(fmt.Sprintf("Uncle's parent unknown (%x)", uncle.ParentHash[0:4]))
}
if uncleParent.Number.Cmp(new(big.Int).Sub(parent.Number, big.NewInt(6))) < 0 {
if uncleParent.Header().Number.Cmp(new(big.Int).Sub(parent.Header().Number, big.NewInt(6))) < 0 {
return UncleError("Uncle too old")
}
if knownUncles.Include(uncle.Hash()) {
if knownUncles.Has(uncle.Hash()) {
return UncleError("Uncle in chain")
}
@ -333,15 +339,15 @@ func (sm *BlockManager) AccumelateRewards(statedb *state.StateDB, block, parent
}
// Get the account associated with the coinbase
account := statedb.GetAccount(block.Coinbase)
account := statedb.GetAccount(block.Header().Coinbase)
// Reward amount of ether to the coinbase address
account.AddAmount(reward)
statedb.Manifest().AddMessage(&state.Message{
To: block.Coinbase,
To: block.Header().Coinbase,
Input: nil,
Origin: nil,
Block: block.Hash(), Timestamp: block.Time, Coinbase: block.Coinbase, Number: block.Number,
Block: block.Hash(), Timestamp: int64(block.Header().Time), Coinbase: block.Header().Coinbase, Number: block.Header().Number,
Value: new(big.Int).Add(reward, block.Reward),
})
@ -349,15 +355,15 @@ func (sm *BlockManager) AccumelateRewards(statedb *state.StateDB, block, parent
}
func (sm *BlockManager) GetMessages(block *types.Block) (messages []*state.Message, err error) {
if !sm.bc.HasBlock(block.PrevHash) {
return nil, ParentError(block.PrevHash)
if !sm.bc.HasBlock(block.Header().ParentHash) {
return nil, ParentError(block.Header().ParentHash)
}
sm.lastAttemptedBlock = block
var (
parent = sm.bc.GetBlock(block.PrevHash)
state = parent.State().Copy()
parent = sm.bc.GetBlock(block.Header().ParentHash)
state = state.New(parent.Trie().Copy())
)
defer state.Reset()