-
Notifications
You must be signed in to change notification settings - Fork 20.9k
Add tests for uncle timestamps and refactor timestamp type #1711
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -203,7 +203,7 @@ func (sm *BlockProcessor) processWithParent(block, parent *types.Block) (logs st | |
txs := block.Transactions() | ||
|
||
// Block validation | ||
if err = ValidateHeader(sm.Pow, header, parent, false); err != nil { | ||
if err = ValidateHeader(sm.Pow, header, parent, false, false); err != nil { | ||
return | ||
} | ||
|
||
|
@@ -327,7 +327,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 := ValidateHeader(sm.Pow, uncle, ancestors[uncle.ParentHash], true); err != nil { | ||
if err := ValidateHeader(sm.Pow, uncle, ancestors[uncle.ParentHash], true, true); err != nil { | ||
return ValidationError(fmt.Sprintf("uncle[%d](%x) header invalid: %v", i, hash[:4], err)) | ||
} | ||
} | ||
|
@@ -358,19 +358,25 @@ func (sm *BlockProcessor) GetLogs(block *types.Block) (logs state.Logs, err erro | |
|
||
// 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 *types.Header, parent *types.Block, checkPow bool) error { | ||
func ValidateHeader(pow pow.PoW, block *types.Header, parent *types.Block, checkPow, uncle 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)) | ||
} | ||
|
||
if block.Time > uint64(time.Now().Unix()) { | ||
return BlockFutureErr | ||
if uncle { | ||
if block.Time.Cmp(common.MaxBig) == 1 { | ||
return BlockTSTooBigErr | ||
} | ||
} else { | ||
if block.Time.Cmp(big.NewInt(time.Now().Unix())) == 1 { | ||
return BlockFutureErr | ||
} | ||
} | ||
if block.Time <= parent.Time() { | ||
if block.Time.Cmp(parent.Time()) != 1 { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Use |
||
return BlockEqualTSErr | ||
} | ||
|
||
expd := CalcDifficulty(block.Time, parent.Time(), parent.Number(), parent.Difficulty()) | ||
expd := CalcDifficulty(block.Time.Uint64(), parent.Time().Uint64(), parent.Number(), parent.Difficulty()) | ||
if expd.Cmp(block.Difficulty) != 0 { | ||
return fmt.Errorf("Difficulty check failed for block %v, %v", block.Difficulty, expd) | ||
} | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -166,16 +166,21 @@ func GenerateChain(parent *types.Block, db common.Database, n int, gen func(int, | |
} | ||
|
||
func makeHeader(parent *types.Block, state *state.StateDB) *types.Header { | ||
time := parent.Time() + 10 // block time is fixed at 10 seconds | ||
var time *big.Int | ||
if parent.Time() == nil { | ||
time = big.NewInt(10) | ||
} else { | ||
time = new(big.Int).Add(parent.Time(), big.NewInt(10)) // block time is fixed at 10 seconds | ||
} | ||
return &types.Header{ | ||
Root: state.Root(), | ||
ParentHash: parent.Hash(), | ||
Coinbase: parent.Coinbase(), | ||
Difficulty: CalcDifficulty(time, parent.Time(), parent.Number(), parent.Difficulty()), | ||
Difficulty: CalcDifficulty(time.Uint64(), new(big.Int).Sub(time, big.NewInt(10)).Uint64(), parent.Number(), parent.Difficulty()), | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 2nd arg why not There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Some tests do not initialise parent in the first call to this function, and I wanted to avoid changing them just for this patch. |
||
GasLimit: CalcGasLimit(parent), | ||
GasUsed: new(big.Int), | ||
Number: new(big.Int).Add(parent.Number(), common.Big1), | ||
Time: uint64(time), | ||
Time: time, | ||
} | ||
} | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -60,7 +60,7 @@ type Header struct { | |
Number *big.Int // The block number | ||
GasLimit *big.Int // Gas limit | ||
GasUsed *big.Int // Gas used | ||
Time uint64 // Creation time | ||
Time *big.Int // Creation time | ||
Extra []byte // Extra data | ||
MixDigest common.Hash // for quick difficulty verification | ||
Nonce BlockNonce | ||
|
@@ -94,7 +94,7 @@ func (h *Header) UnmarshalJSON(data []byte) error { | |
Coinbase string | ||
Difficulty string | ||
GasLimit string | ||
Time uint64 | ||
Time *big.Int | ||
Extra string | ||
} | ||
dec := json.NewDecoder(bytes.NewReader(data)) | ||
|
@@ -210,6 +210,9 @@ func NewBlockWithHeader(header *Header) *Block { | |
|
||
func copyHeader(h *Header) *Header { | ||
cpy := *h | ||
if cpy.Time = new(big.Int); h.Time != nil { | ||
cpy.Time.Set(h.Time) | ||
} | ||
if cpy.Difficulty = new(big.Int); h.Difficulty != nil { | ||
cpy.Difficulty.Set(h.Difficulty) | ||
} | ||
|
@@ -301,13 +304,13 @@ func (b *Block) Number() *big.Int { return new(big.Int).Set(b.header.Number) | |
func (b *Block) GasLimit() *big.Int { return new(big.Int).Set(b.header.GasLimit) } | ||
func (b *Block) GasUsed() *big.Int { return new(big.Int).Set(b.header.GasUsed) } | ||
func (b *Block) Difficulty() *big.Int { return new(big.Int).Set(b.header.Difficulty) } | ||
func (b *Block) Time() *big.Int { return new(big.Int).Set(b.header.Time) } | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @Gustav-Simonsson please also update There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. done |
||
|
||
func (b *Block) NumberU64() uint64 { return b.header.Number.Uint64() } | ||
func (b *Block) MixDigest() common.Hash { return b.header.MixDigest } | ||
func (b *Block) Nonce() uint64 { return binary.BigEndian.Uint64(b.header.Nonce[:]) } | ||
func (b *Block) Bloom() Bloom { return b.header.Bloom } | ||
func (b *Block) Coinbase() common.Address { return b.header.Coinbase } | ||
func (b *Block) Time() uint64 { return b.header.Time } | ||
func (b *Block) Root() common.Hash { return b.header.Root } | ||
func (b *Block) ParentHash() common.Hash { return b.header.ParentHash } | ||
func (b *Block) TxHash() common.Hash { return b.header.TxHash } | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -49,7 +49,7 @@ func NewEnv(state *state.StateDB, chain *ChainManager, msg Message, header *type | |
func (self *VMEnv) Origin() common.Address { f, _ := self.msg.From(); return f } | ||
func (self *VMEnv) BlockNumber() *big.Int { return self.header.Number } | ||
func (self *VMEnv) Coinbase() common.Address { return self.header.Coinbase } | ||
func (self *VMEnv) Time() uint64 { return self.header.Time } | ||
func (self *VMEnv) Time() *big.Int { return self.header.Time } | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @fjl Here nonce of the big ints are immutable (i.e. copied). Shouldn't we update these too while at it? Or maybe in a follow up PR? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @karalabe nonce? The VMEnv is meant to be mutable afaik. |
||
func (self *VMEnv) Difficulty() *big.Int { return self.header.Difficulty } | ||
func (self *VMEnv) GasLimit() *big.Int { return self.header.GasLimit } | ||
func (self *VMEnv) Value() *big.Int { return self.msg.Value() } | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Although valid, comparing against 1 is a bit odd. Usually big int comparison is done as:
< 0
if the first is smaller== 0
if they are equal> 0
if the first one is greaterThis scheme makes it a bit more visible as the comparison operator already "symbolizes" the actual result vs. having to interpret -1, or 1. It is used like that throughout the entire standard lib too, so better to stick with the canonical use.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@karalabe I'd wait with this since the comparisons for extra data, difficulty and gas uses the "odd" convention - better we change this everywhere in a follow-up PR so we avoid touching unrelated code in this patch.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok with me then, but it would be nice to update them at a certain point. :)