Skip to content

Commit 2d1ea1a

Browse files
fjlGustav Simonsson
authored andcommitted
Merge pull request ethereum#1711 from Gustav-Simonsson/timestamp_big_int
Add tests for uncle timestamps and refactor timestamp type (cherry picked from commit abce099) (cherry picked from commit fd512fa) Conflicts: core/vm/instructions.go core/vm/jit_test.go
1 parent 5c11d10 commit 2d1ea1a

19 files changed

+378
-41
lines changed

cmd/evm/main.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -152,7 +152,7 @@ type VMEnv struct {
152152

153153
depth int
154154
Gas *big.Int
155-
time uint64
155+
time *big.Int
156156
logs []vm.StructLog
157157
}
158158

@@ -161,15 +161,15 @@ func NewEnv(state *state.StateDB, transactor common.Address, value *big.Int) *VM
161161
state: state,
162162
transactor: &transactor,
163163
value: value,
164-
time: uint64(time.Now().Unix()),
164+
time: big.NewInt(time.Now().Unix()),
165165
}
166166
}
167167

168168
func (self *VMEnv) State() *state.StateDB { return self.state }
169169
func (self *VMEnv) Origin() common.Address { return *self.transactor }
170170
func (self *VMEnv) BlockNumber() *big.Int { return common.Big0 }
171171
func (self *VMEnv) Coinbase() common.Address { return *self.transactor }
172-
func (self *VMEnv) Time() uint64 { return self.time }
172+
func (self *VMEnv) Time() *big.Int { return self.time }
173173
func (self *VMEnv) Difficulty() *big.Int { return common.Big1 }
174174
func (self *VMEnv) BlockHash() []byte { return make([]byte, 32) }
175175
func (self *VMEnv) Value() *big.Int { return self.value }

core/block_processor.go

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -215,7 +215,7 @@ func (sm *BlockProcessor) processWithParent(block, parent *types.Block) (logs st
215215
txs := block.Transactions()
216216

217217
// Block validation
218-
if err = ValidateHeader(sm.Pow, header, parent, false); err != nil {
218+
if err = ValidateHeader(sm.Pow, header, parent, false, false); err != nil {
219219
return
220220
}
221221

@@ -339,7 +339,7 @@ func (sm *BlockProcessor) VerifyUncles(statedb *state.StateDB, block, parent *ty
339339
return UncleError("uncle[%d](%x)'s parent is not ancestor (%x)", i, hash[:4], uncle.ParentHash[0:4])
340340
}
341341

342-
if err := ValidateHeader(sm.Pow, uncle, ancestors[uncle.ParentHash], true); err != nil {
342+
if err := ValidateHeader(sm.Pow, uncle, ancestors[uncle.ParentHash], true, true); err != nil {
343343
return ValidationError(fmt.Sprintf("uncle[%d](%x) header invalid: %v", i, hash[:4], err))
344344
}
345345
}
@@ -382,19 +382,25 @@ func (sm *BlockProcessor) GetLogs(block *types.Block) (logs state.Logs, err erro
382382

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

390-
if block.Time > uint64(time.Now().Unix()) {
391-
return BlockFutureErr
390+
if uncle {
391+
if block.Time.Cmp(common.MaxBig) == 1 {
392+
return BlockTSTooBigErr
393+
}
394+
} else {
395+
if block.Time.Cmp(big.NewInt(time.Now().Unix())) == 1 {
396+
return BlockFutureErr
397+
}
392398
}
393-
if block.Time <= parent.Time() {
399+
if block.Time.Cmp(parent.Time()) != 1 {
394400
return BlockEqualTSErr
395401
}
396402

397-
expd := CalcDifficulty(block.Time, parent.Time(), parent.Number(), parent.Difficulty())
403+
expd := CalcDifficulty(block.Time.Uint64(), parent.Time().Uint64(), parent.Number(), parent.Difficulty())
398404
if expd.Cmp(block.Difficulty) != 0 {
399405
return fmt.Errorf("Difficulty check failed for block %v, %v", block.Difficulty, expd)
400406
}

core/block_processor_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,13 +48,13 @@ func TestNumber(t *testing.T) {
4848
statedb := state.New(chain.Genesis().Root(), chain.stateDb)
4949
header := makeHeader(chain.Genesis(), statedb)
5050
header.Number = big.NewInt(3)
51-
err := ValidateHeader(pow, header, chain.Genesis(), false)
51+
err := ValidateHeader(pow, header, chain.Genesis(), false, false)
5252
if err != BlockNumberErr {
5353
t.Errorf("expected block number error, got %q", err)
5454
}
5555

5656
header = makeHeader(chain.Genesis(), statedb)
57-
err = ValidateHeader(pow, header, chain.Genesis(), false)
57+
err = ValidateHeader(pow, header, chain.Genesis(), false, false)
5858
if err == BlockNumberErr {
5959
t.Errorf("didn't expect block number error")
6060
}

core/chain_makers.go

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -166,16 +166,21 @@ func GenerateChain(parent *types.Block, db common.Database, n int, gen func(int,
166166
}
167167

168168
func makeHeader(parent *types.Block, state *state.StateDB) *types.Header {
169-
time := parent.Time() + 10 // block time is fixed at 10 seconds
169+
var time *big.Int
170+
if parent.Time() == nil {
171+
time = big.NewInt(10)
172+
} else {
173+
time = new(big.Int).Add(parent.Time(), big.NewInt(10)) // block time is fixed at 10 seconds
174+
}
170175
return &types.Header{
171176
Root: state.Root(),
172177
ParentHash: parent.Hash(),
173178
Coinbase: parent.Coinbase(),
174-
Difficulty: CalcDifficulty(time, parent.Time(), parent.Number(), parent.Difficulty()),
179+
Difficulty: CalcDifficulty(time.Uint64(), new(big.Int).Sub(time, big.NewInt(10)).Uint64(), parent.Number(), parent.Difficulty()),
175180
GasLimit: CalcGasLimit(parent),
176181
GasUsed: new(big.Int),
177182
Number: new(big.Int).Add(parent.Number(), common.Big1),
178-
Time: uint64(time),
183+
Time: time,
179184
}
180185
}
181186

core/chain_manager.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -600,7 +600,8 @@ func (self *ChainManager) InsertChain(chain types.Blocks) (int, error) {
600600
// Allow up to MaxFuture second in the future blocks. If this limit
601601
// is exceeded the chain is discarded and processed at a later time
602602
// if given.
603-
if max := uint64(time.Now().Unix()) + maxTimeFutureBlocks; block.Time() > max {
603+
max := big.NewInt(time.Now().Unix() + maxTimeFutureBlocks)
604+
if block.Time().Cmp(max) == 1 {
604605
return i, fmt.Errorf("%v: BlockFutureErr, %v > %v", BlockFutureErr, block.Time(), max)
605606
}
606607

core/error.go

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,10 @@ import (
2525
)
2626

2727
var (
28-
BlockNumberErr = errors.New("block number invalid")
29-
BlockFutureErr = errors.New("block time is in the future")
30-
BlockEqualTSErr = errors.New("block time stamp equal to previous")
28+
BlockNumberErr = errors.New("block number invalid")
29+
BlockFutureErr = errors.New("block time is in the future")
30+
BlockTSTooBigErr = errors.New("block time too big")
31+
BlockEqualTSErr = errors.New("block time stamp equal to previous")
3132
)
3233

3334
// Parent error. In case a parent is unknown this error will be thrown

core/genesis.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ func WriteGenesisBlock(stateDb, blockDb common.Database, reader io.Reader) (*typ
7373
difficulty := common.String2Big(genesis.Difficulty)
7474
block := types.NewBlock(&types.Header{
7575
Nonce: types.EncodeNonce(common.String2Big(genesis.Nonce).Uint64()),
76-
Time: common.String2Big(genesis.Timestamp).Uint64(),
76+
Time: common.String2Big(genesis.Timestamp),
7777
ParentHash: common.HexToHash(genesis.ParentHash),
7878
Extra: common.FromHex(genesis.ExtraData),
7979
GasLimit: common.String2Big(genesis.GasLimit),

core/types/block.go

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ type Header struct {
6060
Number *big.Int // The block number
6161
GasLimit *big.Int // Gas limit
6262
GasUsed *big.Int // Gas used
63-
Time uint64 // Creation time
63+
Time *big.Int // Creation time
6464
Extra []byte // Extra data
6565
MixDigest common.Hash // for quick difficulty verification
6666
Nonce BlockNonce
@@ -94,7 +94,7 @@ func (h *Header) UnmarshalJSON(data []byte) error {
9494
Coinbase string
9595
Difficulty string
9696
GasLimit string
97-
Time uint64
97+
Time *big.Int
9898
Extra string
9999
}
100100
dec := json.NewDecoder(bytes.NewReader(data))
@@ -210,6 +210,9 @@ func NewBlockWithHeader(header *Header) *Block {
210210

211211
func copyHeader(h *Header) *Header {
212212
cpy := *h
213+
if cpy.Time = new(big.Int); h.Time != nil {
214+
cpy.Time.Set(h.Time)
215+
}
213216
if cpy.Difficulty = new(big.Int); h.Difficulty != nil {
214217
cpy.Difficulty.Set(h.Difficulty)
215218
}
@@ -301,13 +304,13 @@ func (b *Block) Number() *big.Int { return new(big.Int).Set(b.header.Number)
301304
func (b *Block) GasLimit() *big.Int { return new(big.Int).Set(b.header.GasLimit) }
302305
func (b *Block) GasUsed() *big.Int { return new(big.Int).Set(b.header.GasUsed) }
303306
func (b *Block) Difficulty() *big.Int { return new(big.Int).Set(b.header.Difficulty) }
307+
func (b *Block) Time() *big.Int { return new(big.Int).Set(b.header.Time) }
304308

305309
func (b *Block) NumberU64() uint64 { return b.header.Number.Uint64() }
306310
func (b *Block) MixDigest() common.Hash { return b.header.MixDigest }
307311
func (b *Block) Nonce() uint64 { return binary.BigEndian.Uint64(b.header.Nonce[:]) }
308312
func (b *Block) Bloom() Bloom { return b.header.Bloom }
309313
func (b *Block) Coinbase() common.Address { return b.header.Coinbase }
310-
func (b *Block) Time() uint64 { return b.header.Time }
311314
func (b *Block) Root() common.Hash { return b.header.Root }
312315
func (b *Block) ParentHash() common.Hash { return b.header.ParentHash }
313316
func (b *Block) TxHash() common.Hash { return b.header.TxHash }

core/types/block_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ func TestBlockEncoding(t *testing.T) {
4747
check("Root", block.Root(), common.HexToHash("ef1552a40b7165c3cd773806b9e0c165b75356e0314bf0706f279c729f51e017"))
4848
check("Hash", block.Hash(), common.HexToHash("0a5843ac1cb04865017cb35a57b50b07084e5fcee39b5acadade33149f4fff9e"))
4949
check("Nonce", block.Nonce(), uint64(0xa13a5a8c8f2bb1c4))
50-
check("Time", block.Time(), uint64(1426516743))
50+
check("Time", block.Time(), big.NewInt(1426516743))
5151
check("Size", block.Size(), common.StorageSize(len(blockEnc)))
5252

5353
tx1 := NewTransaction(0, common.HexToAddress("095e7baea6a6c7c4c2dfeb977efac326af552d87"), big.NewInt(10), big.NewInt(50000), big.NewInt(10), nil)

core/vm/environment.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ type Environment interface {
3333
BlockNumber() *big.Int
3434
GetHash(n uint64) common.Hash
3535
Coinbase() common.Address
36-
Time() uint64
36+
Time() *big.Int
3737
Difficulty() *big.Int
3838
GasLimit() *big.Int
3939
Transfer(from, to Account, amount *big.Int) error

core/vm/vm.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -461,7 +461,7 @@ func (self *Vm) Run(context *Context, input []byte) (ret []byte, err error) {
461461
case TIMESTAMP:
462462
time := self.env.Time()
463463

464-
stack.push(new(big.Int).SetUint64(time))
464+
stack.push(new(big.Int).Set(time))
465465

466466
case NUMBER:
467467
number := self.env.BlockNumber()

core/vm_env.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ func NewEnv(state *state.StateDB, chain *ChainManager, msg Message, header *type
4949
func (self *VMEnv) Origin() common.Address { f, _ := self.msg.From(); return f }
5050
func (self *VMEnv) BlockNumber() *big.Int { return self.header.Number }
5151
func (self *VMEnv) Coinbase() common.Address { return self.header.Coinbase }
52-
func (self *VMEnv) Time() uint64 { return self.header.Time }
52+
func (self *VMEnv) Time() *big.Int { return self.header.Time }
5353
func (self *VMEnv) Difficulty() *big.Int { return self.header.Difficulty }
5454
func (self *VMEnv) GasLimit() *big.Int { return self.header.GasLimit }
5555
func (self *VMEnv) Value() *big.Int { return self.msg.Value() }

eth/handler.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,7 @@ func NewProtocolManager(networkId int, mux *event.TypeMux, txpool txPool, pow po
117117
manager.downloader = downloader.New(manager.eventMux, manager.chainman.HasBlock, manager.chainman.GetBlock, manager.chainman.CurrentBlock, manager.chainman.InsertChain, manager.removePeer)
118118

119119
validator := func(block *types.Block, parent *types.Block) error {
120-
return core.ValidateHeader(pow, block.Header(), parent, true)
120+
return core.ValidateHeader(pow, block.Header(), parent, true, false)
121121
}
122122
heighter := func() uint64 {
123123
return manager.chainman.CurrentBlock().NumberU64()

miner/worker.go

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -278,7 +278,7 @@ func (self *worker) wait() {
278278
glog.V(logger.Error).Infoln("Invalid block found during mining")
279279
continue
280280
}
281-
if err := core.ValidateHeader(self.eth.BlockProcessor().Pow, block.Header(), parent, true); err != nil && err != core.BlockFutureErr {
281+
if err := core.ValidateHeader(self.eth.BlockProcessor().Pow, block.Header(), parent, true, false); err != nil && err != core.BlockFutureErr {
282282
glog.V(logger.Error).Infoln("Invalid header on mined block:", err)
283283
continue
284284
}
@@ -431,8 +431,8 @@ func (self *worker) commitNewWork() {
431431
tstart := time.Now()
432432
parent := self.chain.CurrentBlock()
433433
tstamp := tstart.Unix()
434-
if tstamp <= int64(parent.Time()) {
435-
tstamp = int64(parent.Time()) + 1
434+
if parent.Time().Cmp(new(big.Int).SetInt64(tstamp)) != 1 {
435+
tstamp = parent.Time().Int64() + 1
436436
}
437437
// this will ensure we're not going off too far in the future
438438
if now := time.Now().Unix(); tstamp > now+4 {
@@ -445,12 +445,12 @@ func (self *worker) commitNewWork() {
445445
header := &types.Header{
446446
ParentHash: parent.Hash(),
447447
Number: num.Add(num, common.Big1),
448-
Difficulty: core.CalcDifficulty(uint64(tstamp), parent.Time(), parent.Number(), parent.Difficulty()),
448+
Difficulty: core.CalcDifficulty(uint64(tstamp), parent.Time().Uint64(), parent.Number(), parent.Difficulty()),
449449
GasLimit: core.CalcGasLimit(parent),
450450
GasUsed: new(big.Int),
451451
Coinbase: self.coinbase,
452452
Extra: self.extra,
453-
Time: uint64(tstamp),
453+
Time: big.NewInt(tstamp),
454454
}
455455

456456
previous := self.current

tests/block_test.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,13 @@ func TestBcUncleHeaderValidityTests(t *testing.T) {
3535
}
3636
}
3737

38+
func TestBcUncleTests(t *testing.T) {
39+
err := RunBlockTest(filepath.Join(blockTestDir, "bcUncleTest.json"), BlockSkipTests)
40+
if err != nil {
41+
t.Fatal(err)
42+
}
43+
}
44+
3845
func TestBcInvalidHeaderTests(t *testing.T) {
3946
err := RunBlockTest(filepath.Join(blockTestDir, "bcInvalidHeaderTest.json"), BlockSkipTests)
4047
if err != nil {

tests/block_test_util.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -365,8 +365,8 @@ func (s *BlockTest) validateBlockHeader(h *btHeader, h2 *types.Header) error {
365365
return fmt.Errorf("GasUsed: expected: %v, decoded: %v", expectedGasUsed, h2.GasUsed)
366366
}
367367

368-
expectedTimestamp := mustConvertUint(h.Timestamp, 16)
369-
if expectedTimestamp != h2.Time {
368+
expectedTimestamp := mustConvertBigInt(h.Timestamp, 16)
369+
if expectedTimestamp.Cmp(h2.Time) != 0 {
370370
return fmt.Errorf("Timestamp: expected: %v, decoded: %v", expectedTimestamp, h2.Time)
371371
}
372372

@@ -461,7 +461,7 @@ func mustConvertHeader(in btHeader) *types.Header {
461461
GasUsed: mustConvertBigInt(in.GasUsed, 16),
462462
GasLimit: mustConvertBigInt(in.GasLimit, 16),
463463
Difficulty: mustConvertBigInt(in.Difficulty, 16),
464-
Time: mustConvertUint(in.Timestamp, 16),
464+
Time: mustConvertBigInt(in.Timestamp, 16),
465465
Nonce: types.EncodeNonce(mustConvertUint(in.Nonce, 16)),
466466
}
467467
return header

0 commit comments

Comments
 (0)