aboutsummaryrefslogtreecommitdiffstats
path: root/core/block_processor.go
diff options
context:
space:
mode:
authorobscuren <geffobscura@gmail.com>2015-03-04 17:49:56 +0800
committerobscuren <geffobscura@gmail.com>2015-03-04 17:49:56 +0800
commit84a4f761f332b4aecc36c748bc4c9a4ce1c114e2 (patch)
tree5966338284ded703d77b4dba66b9876f64202963 /core/block_processor.go
parentd4d505c868fcd0f692ec3573bd6cfcb1c5230fe2 (diff)
downloadgo-tangerine-84a4f761f332b4aecc36c748bc4c9a4ce1c114e2.tar
go-tangerine-84a4f761f332b4aecc36c748bc4c9a4ce1c114e2.tar.gz
go-tangerine-84a4f761f332b4aecc36c748bc4c9a4ce1c114e2.tar.bz2
go-tangerine-84a4f761f332b4aecc36c748bc4c9a4ce1c114e2.tar.lz
go-tangerine-84a4f761f332b4aecc36c748bc4c9a4ce1c114e2.tar.xz
go-tangerine-84a4f761f332b4aecc36c748bc4c9a4ce1c114e2.tar.zst
go-tangerine-84a4f761f332b4aecc36c748bc4c9a4ce1c114e2.zip
uncle validation
Diffstat (limited to 'core/block_processor.go')
-rw-r--r--core/block_processor.go60
1 files changed, 38 insertions, 22 deletions
diff --git a/core/block_processor.go b/core/block_processor.go
index a6632fca7..c2799dc48 100644
--- a/core/block_processor.go
+++ b/core/block_processor.go
@@ -176,10 +176,15 @@ func (sm *BlockProcessor) processWithParent(block, parent *types.Block) (td *big
state := state.New(parent.Root(), sm.db)
// Block validation
- if err = sm.ValidateBlock(block, parent); err != nil {
+ if err = sm.ValidateHeader(block.Header(), parent.Header()); err != nil {
return
}
+ // There can be at most two uncles
+ if len(block.Uncles()) > 2 {
+ return nil, ValidationError("Block can only contain one uncle (contained %v)", len(block.Uncles()))
+ }
+
receipts, err := sm.TransitionState(state, parent, block, false)
if err != nil {
return
@@ -238,46 +243,41 @@ func (sm *BlockProcessor) processWithParent(block, parent *types.Block) (td *big
// Validates the current block. Returns an error if the block was invalid,
// an uncle or anything that isn't on the current block chain.
// Validation validates easy over difficult (dagger takes longer time = difficult)
-func (sm *BlockProcessor) ValidateBlock(block, parent *types.Block) error {
- if len(block.Header().Extra) > 1024 {
- return fmt.Errorf("Block extra data too long (%d)", len(block.Header().Extra))
+func (sm *BlockProcessor) ValidateHeader(block, parent *types.Header) error {
+ if len(block.Extra) > 1024 {
+ return fmt.Errorf("Block extra data too long (%d)", len(block.Extra))
}
expd := CalcDifficulty(block, parent)
- if expd.Cmp(block.Header().Difficulty) != 0 {
- return fmt.Errorf("Difficulty check failed for block %v, %v", block.Header().Difficulty, expd)
+ if expd.Cmp(block.Difficulty) != 0 {
+ return fmt.Errorf("Difficulty check failed for block %v, %v", block.Difficulty, expd)
}
//expl := CalcGasLimit(parent, block)
//if expl.Cmp(block.Header().GasLimit) != 0 {
// block.gasLimit - parent.gasLimit <= parent.gasLimit / 1024
- a := new(big.Int).Sub(block.Header().GasLimit, parent.Header().GasLimit)
- b := new(big.Int).Div(parent.Header().GasLimit, big.NewInt(1024))
+ a := new(big.Int).Sub(block.GasLimit, parent.GasLimit)
+ b := new(big.Int).Div(parent.GasLimit, big.NewInt(1024))
if a.Cmp(b) > 0 {
- return fmt.Errorf("GasLimit check failed for block %v (%v > %v)", block.Header().GasLimit, a, b)
- }
-
- // There can be at most one uncle
- if len(block.Uncles()) > 1 {
- return ValidationError("Block can only contain one uncle (contained %v)", len(block.Uncles()))
+ return fmt.Errorf("GasLimit check failed for block %v (%v > %v)", block.GasLimit, a, b)
}
- if block.Time() < parent.Time() {
- return ValidationError("Block timestamp not after prev block (%v - %v)", block.Header().Time, parent.Header().Time)
+ if block.Time < parent.Time {
+ return ValidationError("Block timestamp not after prev block (%v - %v)", block.Time, parent.Time)
}
- if block.Time() > time.Now().Unix() {
+ if int64(block.Time) > time.Now().Unix() {
return BlockFutureErr
}
- if new(big.Int).Sub(block.Number(), parent.Number()).Cmp(big.NewInt(1)) != 0 {
+ if new(big.Int).Sub(block.Number, parent.Number).Cmp(big.NewInt(1)) != 0 {
return BlockNumberErr
}
// Verify the nonce of the block. Return an error if it's not valid
- if !sm.Pow.Verify(block) {
- return ValidationError("Block's nonce is invalid (= %x)", block.Header().Nonce)
+ if !sm.Pow.Verify(types.NewBlockWithHeader(block)) {
+ return ValidationError("Block's nonce is invalid (= %x)", block.Nonce)
}
return nil
@@ -287,23 +287,39 @@ func (sm *BlockProcessor) AccumulateRewards(statedb *state.StateDB, block, paren
reward := new(big.Int).Set(BlockReward)
ancestors := set.New()
+ uncles := set.New()
+ ancestorHeaders := make(map[string]*types.Header)
for _, ancestor := range sm.bc.GetAncestors(block, 7) {
- ancestors.Add(string(ancestor.Hash()))
+ hash := string(ancestor.Hash())
+ ancestorHeaders[hash] = ancestor.Header()
+ ancestors.Add(hash)
+ // Include ancestors uncles in the uncle set. Uncles must be unique.
+ for _, uncle := range ancestor.Uncles() {
+ uncles.Add(string(uncle.Hash()))
+ }
}
- uncles := set.New()
uncles.Add(string(block.Hash()))
for _, uncle := range block.Uncles() {
if uncles.Has(string(uncle.Hash())) {
// Error not unique
return UncleError("Uncle not unique")
}
+
uncles.Add(string(uncle.Hash()))
+ if ancestors.Has(string(uncle.Hash())) {
+ return UncleError("Uncle is ancestor")
+ }
+
if !ancestors.Has(string(uncle.ParentHash)) {
return UncleError(fmt.Sprintf("Uncle's parent unknown (%x)", uncle.ParentHash[0:4]))
}
+ if err := sm.ValidateHeader(uncle, ancestorHeaders[string(uncle.ParentHash)]); err != nil {
+ return ValidationError(fmt.Sprintf("%v", err))
+ }
+
if !sm.Pow.Verify(types.NewBlockWithHeader(uncle)) {
return ValidationError("Uncle's nonce is invalid (= %x)", uncle.Nonce)
}