Refactored block & Transaction
* Includes new rlp decoder
This commit is contained in:
@ -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()
|
||||
|
Reference in New Issue
Block a user