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