Skip to content

Commit

Permalink
Merge pull request #1282 from obscuren/state-cleanup
Browse files Browse the repository at this point in the history
core/state: cleanup & optimisations
  • Loading branch information
obscuren committed Jun 18, 2015
2 parents 53a6145 + 430bcdb commit 2cea410
Show file tree
Hide file tree
Showing 14 changed files with 176 additions and 197 deletions.
4 changes: 4 additions & 0 deletions common/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,10 @@ func (h Hash) Generate(rand *rand.Rand, size int) reflect.Value {
return reflect.ValueOf(h)
}

func EmptyHash(h Hash) bool {
return h == Hash{}
}

/////////// Address
func BytesToAddress(b []byte) Address {
var a Address
Expand Down
139 changes: 65 additions & 74 deletions core/block_processor.go
Original file line number Diff line number Diff line change
Expand Up @@ -185,7 +185,7 @@ func (sm *BlockProcessor) processWithParent(block, parent *types.Block) (logs st
state := state.New(parent.Root(), sm.db)

// Block validation
if err = sm.ValidateHeader(block.Header(), parent.Header(), false); err != nil {
if err = ValidateHeader(sm.Pow, block.Header(), parent.Header(), false); err != nil {
return
}

Expand Down Expand Up @@ -246,12 +246,6 @@ func (sm *BlockProcessor) processWithParent(block, parent *types.Block) (logs st
return
}

// store the receipts
err = putReceipts(sm.extraDb, block.Hash(), receipts)
if err != nil {
return nil, err
}

// Sync the current block's state to the database
state.Sync()

Expand All @@ -260,76 +254,12 @@ func (sm *BlockProcessor) processWithParent(block, parent *types.Block) (logs st
putTx(sm.extraDb, tx, block, uint64(i))
}

receiptsRlp := receipts.RlpEncode()
/*if len(receipts) > 0 {
glog.V(logger.Info).Infof("Saving %v receipts, rlp len is %v\n", len(receipts), len(receiptsRlp))
}*/
sm.extraDb.Put(append(receiptsPre, block.Hash().Bytes()...), receiptsRlp)
// store the receipts
putReceipts(sm.extraDb, block.Hash(), receipts)

return state.Logs(), nil
}

// See YP section 4.3.4. "Block Header Validity"
// Validates a block. Returns an error if the block is invalid.
func (sm *BlockProcessor) ValidateHeader(block, parent *types.Header, checkPow bool) error {
if big.NewInt(int64(len(block.Extra))).Cmp(params.MaximumExtraDataSize) == 1 {
return fmt.Errorf("Block extra data too long (%d)", len(block.Extra))
}

expd := CalcDifficulty(block, parent)
if expd.Cmp(block.Difficulty) != 0 {
return fmt.Errorf("Difficulty check failed for block %v, %v", block.Difficulty, expd)
}

a := new(big.Int).Sub(block.GasLimit, parent.GasLimit)
a.Abs(a)
b := new(big.Int).Div(parent.GasLimit, params.GasLimitBoundDivisor)
if !(a.Cmp(b) < 0) || (block.GasLimit.Cmp(params.MinGasLimit) == -1) {
return fmt.Errorf("GasLimit check failed for block %v (%v > %v)", block.GasLimit, a, b)
}

if int64(block.Time) > time.Now().Unix() {
return BlockFutureErr
}

if new(big.Int).Sub(block.Number, parent.Number).Cmp(big.NewInt(1)) != 0 {
return BlockNumberErr
}

if block.Time <= parent.Time {
return BlockEqualTSErr //ValidationError("Block timestamp equal or less than previous block (%v - %v)", block.Time, parent.Time)
}

if checkPow {
// Verify the nonce of the block. Return an error if it's not valid
if !sm.Pow.Verify(types.NewBlockWithHeader(block)) {
return ValidationError("Block's nonce is invalid (= %x)", block.Nonce)
}
}

return nil
}

func AccumulateRewards(statedb *state.StateDB, block *types.Block) {
reward := new(big.Int).Set(BlockReward)

for _, uncle := range block.Uncles() {
num := new(big.Int).Add(big.NewInt(8), uncle.Number)
num.Sub(num, block.Number())

r := new(big.Int)
r.Mul(BlockReward, num)
r.Div(r, big.NewInt(8))

statedb.AddBalance(uncle.Coinbase, r)

reward.Add(reward, new(big.Int).Div(BlockReward, big.NewInt(32)))
}

// Get the account associated with the coinbase
statedb.AddBalance(block.Header().Coinbase, reward)
}

func (sm *BlockProcessor) VerifyUncles(statedb *state.StateDB, block, parent *types.Block) error {
ancestors := set.New()
uncles := set.New()
Expand Down Expand Up @@ -367,7 +297,7 @@ func (sm *BlockProcessor) VerifyUncles(statedb *state.StateDB, block, parent *ty
return UncleError("uncle[%d](%x)'s parent is not ancestor (%x)", i, hash[:4], uncle.ParentHash[0:4])
}

if err := sm.ValidateHeader(uncle, ancestorHeaders[uncle.ParentHash], true); err != nil {
if err := ValidateHeader(sm.Pow, uncle, ancestorHeaders[uncle.ParentHash], true); err != nil {
return ValidationError(fmt.Sprintf("uncle[%d](%x) header invalid: %v", i, hash[:4], err))
}
}
Expand Down Expand Up @@ -404,6 +334,67 @@ func (sm *BlockProcessor) GetLogs(block *types.Block) (logs state.Logs, err erro
return state.Logs(), nil
}

// See YP section 4.3.4. "Block Header Validity"
// Validates a block. Returns an error if the block is invalid.
func ValidateHeader(pow pow.PoW, block, parent *types.Header, checkPow bool) error {
if big.NewInt(int64(len(block.Extra))).Cmp(params.MaximumExtraDataSize) == 1 {
return fmt.Errorf("Block extra data too long (%d)", len(block.Extra))
}

expd := CalcDifficulty(block, parent)
if expd.Cmp(block.Difficulty) != 0 {
return fmt.Errorf("Difficulty check failed for block %v, %v", block.Difficulty, expd)
}

a := new(big.Int).Sub(block.GasLimit, parent.GasLimit)
a.Abs(a)
b := new(big.Int).Div(parent.GasLimit, params.GasLimitBoundDivisor)
if !(a.Cmp(b) < 0) || (block.GasLimit.Cmp(params.MinGasLimit) == -1) {
return fmt.Errorf("GasLimit check failed for block %v (%v > %v)", block.GasLimit, a, b)
}

if int64(block.Time) > time.Now().Unix() {
return BlockFutureErr
}

if new(big.Int).Sub(block.Number, parent.Number).Cmp(big.NewInt(1)) != 0 {
return BlockNumberErr
}

if block.Time <= parent.Time {
return BlockEqualTSErr //ValidationError("Block timestamp equal or less than previous block (%v - %v)", block.Time, parent.Time)
}

if checkPow {
// Verify the nonce of the block. Return an error if it's not valid
if !pow.Verify(types.NewBlockWithHeader(block)) {
return ValidationError("Block's nonce is invalid (= %x)", block.Nonce)
}
}

return nil
}

func AccumulateRewards(statedb *state.StateDB, block *types.Block) {
reward := new(big.Int).Set(BlockReward)

for _, uncle := range block.Uncles() {
num := new(big.Int).Add(big.NewInt(8), uncle.Number)
num.Sub(num, block.Number())

r := new(big.Int)
r.Mul(BlockReward, num)
r.Div(r, big.NewInt(8))

statedb.AddBalance(uncle.Coinbase, r)

reward.Add(reward, new(big.Int).Div(BlockReward, big.NewInt(32)))
}

// Get the account associated with the coinbase
statedb.AddBalance(block.Header().Coinbase, reward)
}

func getBlockReceipts(db common.Database, bhash common.Hash) (receipts types.Receipts, err error) {
var rdata []byte
rdata, err = db.Get(append(receiptsPre, bhash[:]...))
Expand Down
8 changes: 5 additions & 3 deletions core/block_processor_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,18 +26,20 @@ func proc() (*BlockProcessor, *ChainManager) {
}

func TestNumber(t *testing.T) {
bp, chain := proc()
_, chain := proc()
block1 := chain.NewBlock(common.Address{})
block1.Header().Number = big.NewInt(3)
block1.Header().Time--

err := bp.ValidateHeader(block1.Header(), chain.Genesis().Header(), false)
pow := ezp.New()

err := ValidateHeader(pow, block1.Header(), chain.Genesis().Header(), false)
if err != BlockNumberErr {
t.Errorf("expected block number error %v", err)
}

block1 = chain.NewBlock(common.Address{})
err = bp.ValidateHeader(block1.Header(), chain.Genesis().Header(), false)
err = ValidateHeader(pow, block1.Header(), chain.Genesis().Header(), false)
if err == BlockNumberErr {
t.Errorf("didn't expect block number error")
}
Expand Down
6 changes: 3 additions & 3 deletions core/state/dump.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ func (self *StateDB) RawDump() World {
account := Account{Balance: stateObject.balance.String(), Nonce: stateObject.nonce, Root: common.Bytes2Hex(stateObject.Root()), CodeHash: common.Bytes2Hex(stateObject.codeHash)}
account.Storage = make(map[string]string)

storageIt := stateObject.State.trie.Iterator()
storageIt := stateObject.trie.Iterator()
for storageIt.Next() {
account.Storage[common.Bytes2Hex(self.trie.GetKey(storageIt.Key))] = common.Bytes2Hex(storageIt.Value)
}
Expand All @@ -54,8 +54,8 @@ func (self *StateDB) Dump() []byte {

// Debug stuff
func (self *StateObject) CreateOutputForDiff() {
fmt.Printf("%x %x %x %x\n", self.Address(), self.State.Root(), self.balance.Bytes(), self.nonce)
it := self.State.trie.Iterator()
fmt.Printf("%x %x %x %x\n", self.Address(), self.Root(), self.balance.Bytes(), self.nonce)
it := self.trie.Iterator()
for it.Next() {
fmt.Printf("%x %x\n", it.Key, it.Value)
}
Expand Down
Loading

0 comments on commit 2cea410

Please sign in to comment.