@@ -18,6 +18,7 @@ package core
1818
1919import (
2020 "crypto/ecdsa"
21+ "encoding/binary"
2122 "math"
2223 "math/big"
2324 "testing"
@@ -26,10 +27,12 @@ import (
2627 "github.com/XinFinOrg/XDPoSChain/consensus"
2728 "github.com/XinFinOrg/XDPoSChain/consensus/ethash"
2829 "github.com/XinFinOrg/XDPoSChain/core/rawdb"
30+ "github.com/XinFinOrg/XDPoSChain/core/state"
2931 "github.com/XinFinOrg/XDPoSChain/core/tracing"
3032 "github.com/XinFinOrg/XDPoSChain/core/types"
3133 "github.com/XinFinOrg/XDPoSChain/core/vm"
3234 "github.com/XinFinOrg/XDPoSChain/crypto"
35+ "github.com/XinFinOrg/XDPoSChain/ethdb/memorydb"
3336 "github.com/XinFinOrg/XDPoSChain/params"
3437 "github.com/XinFinOrg/XDPoSChain/trie"
3538 "github.com/holiman/uint256"
@@ -318,7 +321,7 @@ func GenerateBadBlock(t *testing.T, parent *types.Block, engine consensus.Engine
318321 header := & types.Header {
319322 ParentHash : parent .Hash (),
320323 Coinbase : parent .Coinbase (),
321- Difficulty : engine .CalcDifficulty (& fakeChainReader {config }, parent .Time ()+ 10 , & types.Header {
324+ Difficulty : engine .CalcDifficulty (& fakeChainReader {config : config , engine : engine }, parent .Time ()+ 10 , & types.Header {
322325 Number : parent .Number (),
323326 Time : parent .Time (),
324327 Difficulty : parent .Difficulty (),
@@ -489,3 +492,146 @@ func TestApplyTransactionWithEVMTracer(t *testing.T) {
489492 })
490493 }
491494}
495+
496+ func TestProcessParentBlockHash (t * testing.T ) {
497+ var (
498+ chainConfig = params .MergedTestChainConfig
499+ hashA = common.Hash {0x01 }
500+ hashB = common.Hash {0x02 }
501+ header = & types.Header {ParentHash : hashA , Number : big .NewInt (2 ), Difficulty : big .NewInt (0 )}
502+ parent = & types.Header {ParentHash : hashB , Number : big .NewInt (1 ), Difficulty : big .NewInt (0 )}
503+ coinbase = common.Address {}
504+ )
505+ test := func (statedb * state.StateDB ) {
506+ statedb .SetNonce (params .HistoryStorageAddress , 1 )
507+ statedb .SetCode (params .HistoryStorageAddress , params .HistoryStorageCode )
508+ statedb .IntermediateRoot (true )
509+
510+ vmContext := NewEVMBlockContext (header , nil , & coinbase )
511+ evm := vm .NewEVM (vmContext , vm.TxContext {}, statedb , nil , chainConfig , vm.Config {})
512+ ProcessParentBlockHash (header .ParentHash , evm , statedb )
513+
514+ vmContext = NewEVMBlockContext (parent , nil , & coinbase )
515+ evm = vm .NewEVM (vmContext , vm.TxContext {}, statedb , nil , chainConfig , vm.Config {})
516+ ProcessParentBlockHash (parent .ParentHash , evm , statedb )
517+
518+ // make sure that the state is correct
519+ if have := getParentBlockHash (statedb , 1 ); have != hashA {
520+ t .Errorf ("want parent hash %v, have %v" , hashA , have )
521+ }
522+ if have := getParentBlockHash (statedb , 0 ); have != hashB {
523+ t .Errorf ("want parent hash %v, have %v" , hashB , have )
524+ }
525+ }
526+ t .Run ("MPT" , func (t * testing.T ) {
527+ statedb , _ := state .New (types .EmptyRootHash , state .NewDatabase (rawdb .NewDatabase (memorydb .New ())))
528+ test (statedb )
529+ })
530+ }
531+
532+ func TestProcessParentBlockHashPragueGuard (t * testing.T ) {
533+ config := * params .MergedTestChainConfig
534+ config .PragueBlock = big .NewInt (10 )
535+
536+ statedb , _ := state .New (types .EmptyRootHash , state .NewDatabase (rawdb .NewDatabase (memorydb .New ())))
537+ blockNumber := big .NewInt (5 )
538+ random := common.Hash {}
539+ blockContext := vm.BlockContext {
540+ CanTransfer : CanTransfer ,
541+ Transfer : Transfer ,
542+ GetHash : func (uint64 ) common.Hash { return common.Hash {} },
543+ Coinbase : common.Address {},
544+ BlockNumber : blockNumber ,
545+ Time : 0 ,
546+ Difficulty : big .NewInt (0 ),
547+ GasLimit : 0 ,
548+ BaseFee : nil ,
549+ Random : & random ,
550+ }
551+ evmenv := vm .NewEVM (blockContext , vm.TxContext {}, statedb , nil , & config , vm.Config {})
552+ ProcessParentBlockHash (common.Hash {0x01 }, evmenv , statedb )
553+
554+ if code := statedb .GetCode (params .HistoryStorageAddress ); len (code ) != 0 {
555+ t .Fatalf ("unexpected history contract code predeploy: %x" , code )
556+ }
557+ if have := getParentBlockHash (statedb , 0 ); have != (common.Hash {}) {
558+ t .Fatalf ("expected empty history slot, have %v" , have )
559+ }
560+ }
561+
562+ func TestProcessParentBlockHashBackfillMissingHistory (t * testing.T ) {
563+ config := * params .MergedTestChainConfig
564+ statedb , _ := state .New (types .EmptyRootHash , state .NewDatabase (rawdb .NewDatabase (memorydb .New ())))
565+ blockNumber := big .NewInt (int64 (params .HistoryServeWindow + 1 ))
566+ available := map [uint64 ]common.Hash {
567+ 1 : {0x11 },
568+ 100 : {0x22 },
569+ }
570+
571+ random := common.Hash {}
572+ blockContext := vm.BlockContext {
573+ CanTransfer : CanTransfer ,
574+ Transfer : Transfer ,
575+ GetHash : func (n uint64 ) common.Hash {
576+ if hash , ok := available [n ]; ok {
577+ return hash
578+ }
579+ return common.Hash {}
580+ },
581+ Coinbase : common.Address {},
582+ BlockNumber : blockNumber ,
583+ Time : 0 ,
584+ Difficulty : big .NewInt (0 ),
585+ GasLimit : 0 ,
586+ BaseFee : nil ,
587+ Random : & random ,
588+ }
589+ evmenv := vm .NewEVM (blockContext , vm.TxContext {}, statedb , nil , & config , vm.Config {})
590+ ProcessParentBlockHash (common.Hash {0x01 }, evmenv , statedb )
591+
592+ if have := getParentBlockHash (statedb , 1 ); have != available [1 ] {
593+ t .Fatalf ("expected hash at slot 1, have %v" , have )
594+ }
595+ if have := getParentBlockHash (statedb , 100 ); have != available [100 ] {
596+ t .Fatalf ("expected hash at slot 100, have %v" , have )
597+ }
598+ if have := getParentBlockHash (statedb , 2 ); have != (common.Hash {}) {
599+ t .Fatalf ("expected empty history slot, have %v" , have )
600+ }
601+ }
602+
603+ func TestProcessParentBlockHashCodeMismatchPanics (t * testing.T ) {
604+ config := * params .MergedTestChainConfig
605+ statedb , _ := state .New (types .EmptyRootHash , state .NewDatabase (rawdb .NewDatabase (memorydb .New ())))
606+ statedb .SetCode (params .HistoryStorageAddress , []byte {0x01 })
607+
608+ blockNumber := big .NewInt (1 )
609+ random := common.Hash {}
610+ blockContext := vm.BlockContext {
611+ CanTransfer : CanTransfer ,
612+ Transfer : Transfer ,
613+ GetHash : func (uint64 ) common.Hash { return common.Hash {} },
614+ Coinbase : common.Address {},
615+ BlockNumber : blockNumber ,
616+ Time : 0 ,
617+ Difficulty : big .NewInt (0 ),
618+ GasLimit : 0 ,
619+ BaseFee : nil ,
620+ Random : & random ,
621+ }
622+ evmenv := vm .NewEVM (blockContext , vm.TxContext {}, statedb , nil , & config , vm.Config {})
623+
624+ defer func () {
625+ if recover () == nil {
626+ t .Fatal ("expected panic on history storage code mismatch" )
627+ }
628+ }()
629+ ProcessParentBlockHash (common.Hash {0x01 }, evmenv , statedb )
630+ }
631+
632+ func getParentBlockHash (statedb * state.StateDB , number uint64 ) common.Hash {
633+ ringIndex := number % params .HistoryServeWindow
634+ var key common.Hash
635+ binary .BigEndian .PutUint64 (key [24 :], ringIndex )
636+ return statedb .GetState (params .HistoryStorageAddress , key )
637+ }
0 commit comments