Skip to content

Commit 66dd9ea

Browse files
committed
testcases for getting root by diff hash
1 parent 885aeb9 commit 66dd9ea

File tree

1 file changed

+160
-0
lines changed

1 file changed

+160
-0
lines changed

core/blockchain_diff_test.go

+160
Original file line numberDiff line numberDiff line change
@@ -484,3 +484,163 @@ func TestGetDiffAccounts(t *testing.T) {
484484
}
485485
}
486486
}
487+
488+
// newTwoForkedBlockchains returns two blockchains, these two chains are generated by different
489+
// generators, they have some same parent blocks, the number of same blocks are determined by
490+
// testBlocks, once chain1 inserted a non-default block, chain1 and chain2 get forked.
491+
func newTwoForkedBlockchains(len1, len2 int) (chain1 *BlockChain, chain2 *BlockChain) {
492+
signer := types.HomesteadSigner{}
493+
// Create a database pre-initialize with a genesis block
494+
db1 := rawdb.NewMemoryDatabase()
495+
db1.SetDiffStore(memorydb.New())
496+
(&Genesis{
497+
Config: params.TestChainConfig,
498+
Alloc: GenesisAlloc{testAddr: {Balance: big.NewInt(100000000000000000)}},
499+
}).MustCommit(db1)
500+
501+
chain1, _ = NewBlockChain(db1, nil, params.TestChainConfig, ethash.NewFaker(), vm.Config{}, nil, nil, EnablePersistDiff(860000))
502+
generator1 := func(i int, block *BlockGen) {
503+
// The chain maker doesn't have access to a chain, so the difficulty will be
504+
// lets unset (nil). Set it here to the correct value.
505+
block.SetCoinbase(testAddr)
506+
507+
for idx, testBlock := range testBlocks {
508+
// Specific block setting, the index in this generator has 1 diff from specified blockNr.
509+
if i+1 == testBlock.blockNr {
510+
for _, testTransaction := range testBlock.txs {
511+
var transaction *types.Transaction
512+
if testTransaction.to == nil {
513+
transaction = types.NewContractCreation(block.TxNonce(testAddr),
514+
testTransaction.value, uint64(commonGas), testTransaction.gasPrice, testTransaction.data)
515+
} else {
516+
transaction = types.NewTransaction(block.TxNonce(testAddr), *testTransaction.to,
517+
testTransaction.value, uint64(commonGas), testTransaction.gasPrice, testTransaction.data)
518+
}
519+
tx, err := types.SignTx(transaction, signer, testKey)
520+
if err != nil {
521+
panic(err)
522+
}
523+
block.AddTxWithChain(chain1, tx)
524+
}
525+
break
526+
}
527+
528+
// Default block setting.
529+
if idx == len(testBlocks)-1 {
530+
// We want to simulate an empty middle block, having the same state as the
531+
// first one. The last is needs a state change again to force a reorg.
532+
for _, testTransaction := range testBlocks[0].txs {
533+
tx, err := types.SignTx(types.NewTransaction(block.TxNonce(testAddr), *testTransaction.to,
534+
testTransaction.value, uint64(commonGas), testTransaction.gasPrice, testTransaction.data), signer, testKey)
535+
if err != nil {
536+
panic(err)
537+
}
538+
block.AddTxWithChain(chain1, tx)
539+
}
540+
}
541+
}
542+
543+
}
544+
bs1, _ := GenerateChain(params.TestChainConfig, chain1.Genesis(), ethash.NewFaker(), db1, len1, generator1)
545+
if _, err := chain1.InsertChain(bs1); err != nil {
546+
panic(err)
547+
}
548+
549+
// Create a database pre-initialize with a genesis block
550+
db2 := rawdb.NewMemoryDatabase()
551+
db2.SetDiffStore(memorydb.New())
552+
(&Genesis{
553+
Config: params.TestChainConfig,
554+
Alloc: GenesisAlloc{testAddr: {Balance: big.NewInt(100000000000000000)}},
555+
}).MustCommit(db2)
556+
chain2, _ = NewBlockChain(db2, nil, params.TestChainConfig, ethash.NewFaker(), vm.Config{}, nil, nil, EnablePersistDiff(860000))
557+
generator2 := func(i int, block *BlockGen) {
558+
// The chain maker doesn't have access to a chain, so the difficulty will be
559+
// lets unset (nil). Set it here to the correct value.
560+
block.SetCoinbase(testAddr)
561+
// We want to simulate an empty middle block, having the same state as the
562+
// first one. The last is needs a state change again to force a reorg.
563+
for _, testTransaction := range testBlocks[0].txs {
564+
tx, err := types.SignTx(types.NewTransaction(block.TxNonce(testAddr), *testTransaction.to,
565+
testTransaction.value, uint64(commonGas), testTransaction.gasPrice, testTransaction.data), signer, testKey)
566+
if err != nil {
567+
panic(err)
568+
}
569+
block.AddTxWithChain(chain1, tx)
570+
}
571+
}
572+
bs2, _ := GenerateChain(params.TestChainConfig, chain2.Genesis(), ethash.NewFaker(), db2, len2, generator2)
573+
if _, err := chain2.InsertChain(bs2); err != nil {
574+
panic(err)
575+
}
576+
577+
return chain1, chain2
578+
}
579+
580+
func testGetRootByDiffHash(t *testing.T, chain1, chain2 *BlockChain, blockNumber uint64, status types.VerifyStatus) {
581+
block2 := chain2.GetBlockByNumber(blockNumber)
582+
if block2 == nil {
583+
t.Fatalf("failed to find block, number: %v", blockNumber)
584+
}
585+
expect := types.VerifyResult{
586+
Status: status,
587+
BlockNumber: blockNumber,
588+
BlockHash: block2.Hash(),
589+
}
590+
if status.Code&0xff00 == types.StatusVerified.Code {
591+
expect.Root = block2.Root()
592+
}
593+
594+
diffLayer2 := chain2.GetTrustedDiffLayer(block2.Hash())
595+
if diffLayer2 == nil {
596+
t.Fatal("failed to find diff layer")
597+
}
598+
diffHash2 := types.EmptyRootHash
599+
if status != types.StatusDiffHashMismatch {
600+
var err error
601+
diffHash2, err = GetTrustedDiffHash(diffLayer2)
602+
if err != nil {
603+
t.Fatalf("failed to compute diff hash: %v", err)
604+
}
605+
}
606+
607+
if status == types.StatusUntrustedVerified {
608+
block1 := chain1.GetBlockByNumber(blockNumber)
609+
if block1 == nil {
610+
t.Fatalf("failed to find block, number: %v", blockNumber)
611+
}
612+
chain1.diffLayerCache.Remove(block1.Hash())
613+
}
614+
615+
result, _ := chain1.GetRootByDiffHash(blockNumber, block2.Hash(), diffHash2)
616+
if result.Status != expect.Status {
617+
t.Fatalf("failed to verify block, number: %v, expect status: %v, real status: %v", blockNumber, expect.Status, result.Status)
618+
}
619+
if result.Root != expect.Root {
620+
t.Fatalf("failed to verify block, number: %v, expect root: %v, real root: %v", blockNumber, expect.Root, result.Root)
621+
}
622+
}
623+
624+
func TestGetRootByDiffHash(t *testing.T) {
625+
len1 := 23 // length of blockchain1
626+
len2 := 35 // length of blockchain2
627+
plen := 11 // length of same parent blocks, which determined by testBlocks.
628+
629+
chain1, chain2 := newTwoForkedBlockchains(len1, len2)
630+
defer chain1.Stop()
631+
defer chain2.Stop()
632+
633+
hash1 := chain1.GetBlockByNumber(uint64(plen)).Hash()
634+
hash2 := chain2.GetBlockByNumber(uint64(plen)).Hash()
635+
if hash1 != hash2 {
636+
t.Errorf("chain content mismatch at %d: have hash %v, want hash %v", plen, hash2, hash1)
637+
}
638+
639+
testGetRootByDiffHash(t, chain1, chain2, 10, types.StatusFullVerified)
640+
testGetRootByDiffHash(t, chain1, chain2, 2, types.StatusUntrustedVerified)
641+
testGetRootByDiffHash(t, chain1, chain2, 10, types.StatusDiffHashMismatch)
642+
testGetRootByDiffHash(t, chain1, chain2, 12, types.StatusImpossibleFork)
643+
testGetRootByDiffHash(t, chain1, chain2, 20, types.StatusPossibleFork)
644+
testGetRootByDiffHash(t, chain1, chain2, 24, types.StatusBlockNewer)
645+
testGetRootByDiffHash(t, chain1, chain2, 35, types.StatusBlockTooNew)
646+
}

0 commit comments

Comments
 (0)