| 
									
										
										
										
											2016-11-09 02:01:56 +01:00
										 |  |  | // Copyright 2016 The go-ethereum Authors | 
					
						
							| 
									
										
										
										
											2016-10-14 05:47:09 +02:00
										 |  |  | // This file is part of the go-ethereum library. | 
					
						
							|  |  |  | // | 
					
						
							|  |  |  | // The go-ethereum library is free software: you can redistribute it and/or modify | 
					
						
							|  |  |  | // it under the terms of the GNU Lesser General Public License as published by | 
					
						
							|  |  |  | // the Free Software Foundation, either version 3 of the License, or | 
					
						
							|  |  |  | // (at your option) any later version. | 
					
						
							|  |  |  | // | 
					
						
							|  |  |  | // The go-ethereum library is distributed in the hope that it will be useful, | 
					
						
							|  |  |  | // but WITHOUT ANY WARRANTY; without even the implied warranty of | 
					
						
							|  |  |  | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | 
					
						
							|  |  |  | // GNU Lesser General Public License for more details. | 
					
						
							|  |  |  | // | 
					
						
							|  |  |  | // You should have received a copy of the GNU Lesser General Public License | 
					
						
							|  |  |  | // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | package light | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | import ( | 
					
						
							| 
									
										
										
										
											2017-03-22 18:20:33 +01:00
										 |  |  | 	"context" | 
					
						
							| 
									
										
										
										
											2016-10-14 05:47:09 +02:00
										 |  |  | 	"math/big" | 
					
						
							|  |  |  | 	"testing" | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	"github.com/ethereum/go-ethereum/common" | 
					
						
							| 
									
										
										
										
											2017-04-05 01:16:29 +03:00
										 |  |  | 	"github.com/ethereum/go-ethereum/consensus/ethash" | 
					
						
							| 
									
										
										
										
											2016-10-14 05:47:09 +02:00
										 |  |  | 	"github.com/ethereum/go-ethereum/core" | 
					
						
							| 
									
										
										
										
											2018-05-07 14:35:06 +03:00
										 |  |  | 	"github.com/ethereum/go-ethereum/core/rawdb" | 
					
						
							| 
									
										
										
										
											2016-10-14 05:47:09 +02:00
										 |  |  | 	"github.com/ethereum/go-ethereum/core/types" | 
					
						
							|  |  |  | 	"github.com/ethereum/go-ethereum/ethdb" | 
					
						
							| 
									
										
										
										
											2016-10-20 13:36:29 +02:00
										 |  |  | 	"github.com/ethereum/go-ethereum/params" | 
					
						
							| 
									
										
										
										
											2016-10-14 05:47:09 +02:00
										 |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // So we can deterministically seed different blockchains | 
					
						
							|  |  |  | var ( | 
					
						
							|  |  |  | 	canonicalSeed = 1 | 
					
						
							|  |  |  | 	forkSeed      = 2 | 
					
						
							|  |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // makeHeaderChain creates a deterministic chain of headers rooted at parent. | 
					
						
							|  |  |  | func makeHeaderChain(parent *types.Header, n int, db ethdb.Database, seed int) []*types.Header { | 
					
						
							| 
									
										
										
										
											2017-12-22 20:37:50 +08:00
										 |  |  | 	blocks, _ := core.GenerateChain(params.TestChainConfig, types.NewBlockWithHeader(parent), ethash.NewFaker(), db, n, func(i int, b *core.BlockGen) { | 
					
						
							| 
									
										
										
										
											2016-10-14 05:47:09 +02:00
										 |  |  | 		b.SetCoinbase(common.Address{0: byte(seed), 19: byte(i)}) | 
					
						
							|  |  |  | 	}) | 
					
						
							|  |  |  | 	headers := make([]*types.Header, len(blocks)) | 
					
						
							|  |  |  | 	for i, block := range blocks { | 
					
						
							|  |  |  | 		headers[i] = block.Header() | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return headers | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // newCanonical creates a chain database, and injects a deterministic canonical | 
					
						
							|  |  |  | // chain. Depending on the full flag, if creates either a full block chain or a | 
					
						
							|  |  |  | // header only chain. | 
					
						
							|  |  |  | func newCanonical(n int) (ethdb.Database, *LightChain, error) { | 
					
						
							| 
									
										
										
										
											2018-09-24 15:57:49 +03:00
										 |  |  | 	db := rawdb.NewMemoryDatabase() | 
					
						
							| 
									
										
										
										
											2017-04-05 01:16:29 +03:00
										 |  |  | 	gspec := core.Genesis{Config: params.TestChainConfig} | 
					
						
							| 
									
										
										
										
											2017-03-02 14:03:33 +01:00
										 |  |  | 	genesis := gspec.MustCommit(db) | 
					
						
							| 
									
										
											  
											
												all: on-chain oracle checkpoint syncing (#19543)
* all: implement simple checkpoint syncing
cmd, les, node: remove callback mechanism
cmd, node: remove callback definition
les: simplify the registrar
les: expose checkpoint rpc services in the light client
les, light: don't store untrusted receipt
cmd, contracts, les: discard stale checkpoint
cmd, contracts/registrar: loose restriction of registeration
cmd, contracts: add replay-protection
all: off-chain multi-signature contract
params: deploy checkpoint contract for rinkeby
cmd/registrar: add raw signing mode for registrar
cmd/registrar, contracts/registrar, les: fixed messages
* cmd/registrar, contracts/registrar: fix lints
* accounts/abi/bind, les: address comments
* cmd, contracts, les, light, params: minor checkpoint sync cleanups
* cmd, eth, les, light: move checkpoint config to config file
* cmd, eth, les, params: address comments
* eth, les, params: address comments
* cmd: polish up the checkpoint admin CLI
* cmd, contracts, params: deploy new version contract
* cmd/checkpoint-admin: add another flag for clef mode signing
* cmd, contracts, les: rename and regen checkpoint oracle with abigen
											
										 
											2019-06-28 15:34:02 +08:00
										 |  |  | 	blockchain, _ := NewLightChain(&dummyOdr{db: db, indexerConfig: TestClientIndexerConfig}, gspec.Config, ethash.NewFaker(), nil) | 
					
						
							| 
									
										
										
										
											2017-04-05 01:16:29 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-10-14 05:47:09 +02:00
										 |  |  | 	// Create and inject the requested chain | 
					
						
							|  |  |  | 	if n == 0 { | 
					
						
							|  |  |  | 		return db, blockchain, nil | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	// Header-only chain requested | 
					
						
							|  |  |  | 	headers := makeHeaderChain(genesis.Header(), n, db, canonicalSeed) | 
					
						
							|  |  |  | 	_, err := blockchain.InsertHeaderChain(headers, 1) | 
					
						
							|  |  |  | 	return db, blockchain, err | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-02 14:03:33 +01:00
										 |  |  | // newTestLightChain creates a LightChain that doesn't validate anything. | 
					
						
							|  |  |  | func newTestLightChain() *LightChain { | 
					
						
							| 
									
										
										
										
											2018-09-24 15:57:49 +03:00
										 |  |  | 	db := rawdb.NewMemoryDatabase() | 
					
						
							| 
									
										
										
										
											2017-03-02 14:03:33 +01:00
										 |  |  | 	gspec := &core.Genesis{ | 
					
						
							|  |  |  | 		Difficulty: big.NewInt(1), | 
					
						
							| 
									
										
										
										
											2017-04-05 01:16:29 +03:00
										 |  |  | 		Config:     params.TestChainConfig, | 
					
						
							| 
									
										
										
										
											2017-03-02 14:03:33 +01:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	gspec.MustCommit(db) | 
					
						
							| 
									
										
											  
											
												all: on-chain oracle checkpoint syncing (#19543)
* all: implement simple checkpoint syncing
cmd, les, node: remove callback mechanism
cmd, node: remove callback definition
les: simplify the registrar
les: expose checkpoint rpc services in the light client
les, light: don't store untrusted receipt
cmd, contracts, les: discard stale checkpoint
cmd, contracts/registrar: loose restriction of registeration
cmd, contracts: add replay-protection
all: off-chain multi-signature contract
params: deploy checkpoint contract for rinkeby
cmd/registrar: add raw signing mode for registrar
cmd/registrar, contracts/registrar, les: fixed messages
* cmd/registrar, contracts/registrar: fix lints
* accounts/abi/bind, les: address comments
* cmd, contracts, les, light, params: minor checkpoint sync cleanups
* cmd, eth, les, light: move checkpoint config to config file
* cmd, eth, les, params: address comments
* eth, les, params: address comments
* cmd: polish up the checkpoint admin CLI
* cmd, contracts, params: deploy new version contract
* cmd/checkpoint-admin: add another flag for clef mode signing
* cmd, contracts, les: rename and regen checkpoint oracle with abigen
											
										 
											2019-06-28 15:34:02 +08:00
										 |  |  | 	lc, err := NewLightChain(&dummyOdr{db: db}, gspec.Config, ethash.NewFullFaker(), nil) | 
					
						
							| 
									
										
										
										
											2016-10-14 05:47:09 +02:00
										 |  |  | 	if err != nil { | 
					
						
							| 
									
										
										
										
											2017-03-02 14:03:33 +01:00
										 |  |  | 		panic(err) | 
					
						
							| 
									
										
										
										
											2016-10-14 05:47:09 +02:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2017-03-02 14:03:33 +01:00
										 |  |  | 	return lc | 
					
						
							| 
									
										
										
										
											2016-10-14 05:47:09 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Test fork of length N starting from block i | 
					
						
							|  |  |  | func testFork(t *testing.T, LightChain *LightChain, i, n int, comparator func(td1, td2 *big.Int)) { | 
					
						
							|  |  |  | 	// Copy old chain up to #i into a new db | 
					
						
							|  |  |  | 	db, LightChain2, err := newCanonical(i) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		t.Fatal("could not make new canonical in testFork", err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	// Assert the chains have the same header/block at #i | 
					
						
							|  |  |  | 	var hash1, hash2 common.Hash | 
					
						
							|  |  |  | 	hash1 = LightChain.GetHeaderByNumber(uint64(i)).Hash() | 
					
						
							|  |  |  | 	hash2 = LightChain2.GetHeaderByNumber(uint64(i)).Hash() | 
					
						
							|  |  |  | 	if hash1 != hash2 { | 
					
						
							|  |  |  | 		t.Errorf("chain content mismatch at %d: have hash %v, want hash %v", i, hash2, hash1) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	// Extend the newly created chain | 
					
						
							| 
									
										
										
										
											2017-08-07 18:25:18 +03:00
										 |  |  | 	headerChainB := makeHeaderChain(LightChain2.CurrentHeader(), n, db, forkSeed) | 
					
						
							| 
									
										
										
										
											2016-10-14 05:47:09 +02:00
										 |  |  | 	if _, err := LightChain2.InsertHeaderChain(headerChainB, 1); err != nil { | 
					
						
							|  |  |  | 		t.Fatalf("failed to insert forking chain: %v", err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	// Sanity check that the forked chain can be imported into the original | 
					
						
							|  |  |  | 	var tdPre, tdPost *big.Int | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	tdPre = LightChain.GetTdByHash(LightChain.CurrentHeader().Hash()) | 
					
						
							|  |  |  | 	if err := testHeaderChainImport(headerChainB, LightChain); err != nil { | 
					
						
							|  |  |  | 		t.Fatalf("failed to import forked header chain: %v", err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	tdPost = LightChain.GetTdByHash(headerChainB[len(headerChainB)-1].Hash()) | 
					
						
							|  |  |  | 	// Compare the total difficulties of the chains | 
					
						
							|  |  |  | 	comparator(tdPre, tdPost) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // testHeaderChainImport tries to process a chain of header, writing them into | 
					
						
							|  |  |  | // the database if successful. | 
					
						
							| 
									
										
										
										
											2017-04-05 01:16:29 +03:00
										 |  |  | func testHeaderChainImport(chain []*types.Header, lightchain *LightChain) error { | 
					
						
							| 
									
										
										
										
											2016-10-14 05:47:09 +02:00
										 |  |  | 	for _, header := range chain { | 
					
						
							|  |  |  | 		// Try and validate the header | 
					
						
							| 
									
										
										
										
											2017-04-05 01:16:29 +03:00
										 |  |  | 		if err := lightchain.engine.VerifyHeader(lightchain.hc, header, true); err != nil { | 
					
						
							| 
									
										
										
										
											2016-10-14 05:47:09 +02:00
										 |  |  | 			return err | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		// Manually insert the header into the database, but don't reorganize (allows subsequent testing) | 
					
						
							| 
									
										
										
										
											2019-01-11 15:27:47 +02:00
										 |  |  | 		lightchain.chainmu.Lock() | 
					
						
							| 
									
										
										
										
											2018-05-07 14:35:06 +03:00
										 |  |  | 		rawdb.WriteTd(lightchain.chainDb, header.Hash(), header.Number.Uint64(), new(big.Int).Add(header.Difficulty, lightchain.GetTdByHash(header.ParentHash))) | 
					
						
							|  |  |  | 		rawdb.WriteHeader(lightchain.chainDb, header) | 
					
						
							| 
									
										
										
										
											2019-01-11 15:27:47 +02:00
										 |  |  | 		lightchain.chainmu.Unlock() | 
					
						
							| 
									
										
										
										
											2016-10-14 05:47:09 +02:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	return nil | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Tests that given a starting canonical chain of a given size, it can be extended | 
					
						
							|  |  |  | // with various length chains. | 
					
						
							|  |  |  | func TestExtendCanonicalHeaders(t *testing.T) { | 
					
						
							|  |  |  | 	length := 5 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Make first chain starting from genesis | 
					
						
							|  |  |  | 	_, processor, err := newCanonical(length) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		t.Fatalf("failed to make new canonical chain: %v", err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	// Define the difficulty comparator | 
					
						
							|  |  |  | 	better := func(td1, td2 *big.Int) { | 
					
						
							|  |  |  | 		if td2.Cmp(td1) <= 0 { | 
					
						
							|  |  |  | 			t.Errorf("total difficulty mismatch: have %v, expected more than %v", td2, td1) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	// Start fork from current height | 
					
						
							|  |  |  | 	testFork(t, processor, length, 1, better) | 
					
						
							|  |  |  | 	testFork(t, processor, length, 2, better) | 
					
						
							|  |  |  | 	testFork(t, processor, length, 5, better) | 
					
						
							|  |  |  | 	testFork(t, processor, length, 10, better) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Tests that given a starting canonical chain of a given size, creating shorter | 
					
						
							|  |  |  | // forks do not take canonical ownership. | 
					
						
							|  |  |  | func TestShorterForkHeaders(t *testing.T) { | 
					
						
							|  |  |  | 	length := 10 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Make first chain starting from genesis | 
					
						
							|  |  |  | 	_, processor, err := newCanonical(length) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		t.Fatalf("failed to make new canonical chain: %v", err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	// Define the difficulty comparator | 
					
						
							|  |  |  | 	worse := func(td1, td2 *big.Int) { | 
					
						
							|  |  |  | 		if td2.Cmp(td1) >= 0 { | 
					
						
							|  |  |  | 			t.Errorf("total difficulty mismatch: have %v, expected less than %v", td2, td1) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	// Sum of numbers must be less than `length` for this to be a shorter fork | 
					
						
							|  |  |  | 	testFork(t, processor, 0, 3, worse) | 
					
						
							|  |  |  | 	testFork(t, processor, 0, 7, worse) | 
					
						
							|  |  |  | 	testFork(t, processor, 1, 1, worse) | 
					
						
							|  |  |  | 	testFork(t, processor, 1, 7, worse) | 
					
						
							|  |  |  | 	testFork(t, processor, 5, 3, worse) | 
					
						
							|  |  |  | 	testFork(t, processor, 5, 4, worse) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Tests that given a starting canonical chain of a given size, creating longer | 
					
						
							|  |  |  | // forks do take canonical ownership. | 
					
						
							|  |  |  | func TestLongerForkHeaders(t *testing.T) { | 
					
						
							|  |  |  | 	length := 10 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Make first chain starting from genesis | 
					
						
							|  |  |  | 	_, processor, err := newCanonical(length) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		t.Fatalf("failed to make new canonical chain: %v", err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	// Define the difficulty comparator | 
					
						
							|  |  |  | 	better := func(td1, td2 *big.Int) { | 
					
						
							|  |  |  | 		if td2.Cmp(td1) <= 0 { | 
					
						
							|  |  |  | 			t.Errorf("total difficulty mismatch: have %v, expected more than %v", td2, td1) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	// Sum of numbers must be greater than `length` for this to be a longer fork | 
					
						
							|  |  |  | 	testFork(t, processor, 0, 11, better) | 
					
						
							|  |  |  | 	testFork(t, processor, 0, 15, better) | 
					
						
							|  |  |  | 	testFork(t, processor, 1, 10, better) | 
					
						
							|  |  |  | 	testFork(t, processor, 1, 12, better) | 
					
						
							|  |  |  | 	testFork(t, processor, 5, 6, better) | 
					
						
							|  |  |  | 	testFork(t, processor, 5, 8, better) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Tests that given a starting canonical chain of a given size, creating equal | 
					
						
							|  |  |  | // forks do take canonical ownership. | 
					
						
							|  |  |  | func TestEqualForkHeaders(t *testing.T) { | 
					
						
							|  |  |  | 	length := 10 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Make first chain starting from genesis | 
					
						
							|  |  |  | 	_, processor, err := newCanonical(length) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		t.Fatalf("failed to make new canonical chain: %v", err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	// Define the difficulty comparator | 
					
						
							|  |  |  | 	equal := func(td1, td2 *big.Int) { | 
					
						
							|  |  |  | 		if td2.Cmp(td1) != 0 { | 
					
						
							|  |  |  | 			t.Errorf("total difficulty mismatch: have %v, want %v", td2, td1) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	// Sum of numbers must be equal to `length` for this to be an equal fork | 
					
						
							|  |  |  | 	testFork(t, processor, 0, 10, equal) | 
					
						
							|  |  |  | 	testFork(t, processor, 1, 9, equal) | 
					
						
							|  |  |  | 	testFork(t, processor, 2, 8, equal) | 
					
						
							|  |  |  | 	testFork(t, processor, 5, 5, equal) | 
					
						
							|  |  |  | 	testFork(t, processor, 6, 4, equal) | 
					
						
							|  |  |  | 	testFork(t, processor, 9, 1, equal) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Tests that chains missing links do not get accepted by the processor. | 
					
						
							|  |  |  | func TestBrokenHeaderChain(t *testing.T) { | 
					
						
							|  |  |  | 	// Make chain starting from genesis | 
					
						
							|  |  |  | 	db, LightChain, err := newCanonical(10) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		t.Fatalf("failed to make new canonical chain: %v", err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	// Create a forked chain, and try to insert with a missing link | 
					
						
							|  |  |  | 	chain := makeHeaderChain(LightChain.CurrentHeader(), 5, db, forkSeed)[1:] | 
					
						
							|  |  |  | 	if err := testHeaderChainImport(chain, LightChain); err == nil { | 
					
						
							|  |  |  | 		t.Errorf("broken header chain not reported") | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func makeHeaderChainWithDiff(genesis *types.Block, d []int, seed byte) []*types.Header { | 
					
						
							|  |  |  | 	var chain []*types.Header | 
					
						
							|  |  |  | 	for i, difficulty := range d { | 
					
						
							|  |  |  | 		header := &types.Header{ | 
					
						
							|  |  |  | 			Coinbase:    common.Address{seed}, | 
					
						
							|  |  |  | 			Number:      big.NewInt(int64(i + 1)), | 
					
						
							|  |  |  | 			Difficulty:  big.NewInt(int64(difficulty)), | 
					
						
							|  |  |  | 			UncleHash:   types.EmptyUncleHash, | 
					
						
							|  |  |  | 			TxHash:      types.EmptyRootHash, | 
					
						
							|  |  |  | 			ReceiptHash: types.EmptyRootHash, | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		if i == 0 { | 
					
						
							|  |  |  | 			header.ParentHash = genesis.Hash() | 
					
						
							|  |  |  | 		} else { | 
					
						
							|  |  |  | 			header.ParentHash = chain[i-1].Hash() | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		chain = append(chain, types.CopyHeader(header)) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return chain | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | type dummyOdr struct { | 
					
						
							|  |  |  | 	OdrBackend | 
					
						
							| 
									
										
										
										
											2018-08-28 15:08:16 +08:00
										 |  |  | 	db            ethdb.Database | 
					
						
							|  |  |  | 	indexerConfig *IndexerConfig | 
					
						
							| 
									
										
										
										
											2016-10-14 05:47:09 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (odr *dummyOdr) Database() ethdb.Database { | 
					
						
							|  |  |  | 	return odr.db | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (odr *dummyOdr) Retrieve(ctx context.Context, req OdrRequest) error { | 
					
						
							|  |  |  | 	return nil | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-08-28 15:08:16 +08:00
										 |  |  | func (odr *dummyOdr) IndexerConfig() *IndexerConfig { | 
					
						
							|  |  |  | 	return odr.indexerConfig | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-10-14 05:47:09 +02:00
										 |  |  | // Tests that reorganizing a long difficult chain after a short easy one | 
					
						
							|  |  |  | // overwrites the canonical numbers and links in the database. | 
					
						
							|  |  |  | func TestReorgLongHeaders(t *testing.T) { | 
					
						
							|  |  |  | 	testReorg(t, []int{1, 2, 4}, []int{1, 2, 3, 4}, 10) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Tests that reorganizing a short difficult chain after a long easy one | 
					
						
							|  |  |  | // overwrites the canonical numbers and links in the database. | 
					
						
							|  |  |  | func TestReorgShortHeaders(t *testing.T) { | 
					
						
							|  |  |  | 	testReorg(t, []int{1, 2, 3, 4}, []int{1, 10}, 11) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func testReorg(t *testing.T, first, second []int, td int64) { | 
					
						
							| 
									
										
										
										
											2017-03-02 14:03:33 +01:00
										 |  |  | 	bc := newTestLightChain() | 
					
						
							| 
									
										
										
										
											2016-10-14 05:47:09 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	// Insert an easy and a difficult chain afterwards | 
					
						
							| 
									
										
										
										
											2017-03-02 14:03:33 +01:00
										 |  |  | 	bc.InsertHeaderChain(makeHeaderChainWithDiff(bc.genesisBlock, first, 11), 1) | 
					
						
							|  |  |  | 	bc.InsertHeaderChain(makeHeaderChainWithDiff(bc.genesisBlock, second, 22), 1) | 
					
						
							| 
									
										
										
										
											2016-10-14 05:47:09 +02:00
										 |  |  | 	// Check that the chain is valid number and link wise | 
					
						
							|  |  |  | 	prev := bc.CurrentHeader() | 
					
						
							|  |  |  | 	for header := bc.GetHeaderByNumber(bc.CurrentHeader().Number.Uint64() - 1); header.Number.Uint64() != 0; prev, header = header, bc.GetHeaderByNumber(header.Number.Uint64()-1) { | 
					
						
							|  |  |  | 		if prev.ParentHash != header.Hash() { | 
					
						
							|  |  |  | 			t.Errorf("parent header hash mismatch: have %x, want %x", prev.ParentHash, header.Hash()) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	// Make sure the chain total difficulty is the correct one | 
					
						
							| 
									
										
										
										
											2017-03-02 14:03:33 +01:00
										 |  |  | 	want := new(big.Int).Add(bc.genesisBlock.Difficulty(), big.NewInt(td)) | 
					
						
							| 
									
										
										
										
											2016-10-14 05:47:09 +02:00
										 |  |  | 	if have := bc.GetTdByHash(bc.CurrentHeader().Hash()); have.Cmp(want) != 0 { | 
					
						
							|  |  |  | 		t.Errorf("total difficulty mismatch: have %v, want %v", have, want) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Tests that the insertion functions detect banned hashes. | 
					
						
							|  |  |  | func TestBadHeaderHashes(t *testing.T) { | 
					
						
							| 
									
										
										
										
											2017-03-02 14:03:33 +01:00
										 |  |  | 	bc := newTestLightChain() | 
					
						
							| 
									
										
										
										
											2016-10-14 05:47:09 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	// Create a chain, ban a hash and try to import | 
					
						
							|  |  |  | 	var err error | 
					
						
							| 
									
										
										
										
											2017-03-02 14:03:33 +01:00
										 |  |  | 	headers := makeHeaderChainWithDiff(bc.genesisBlock, []int{1, 2, 4}, 10) | 
					
						
							| 
									
										
										
										
											2016-10-14 05:47:09 +02:00
										 |  |  | 	core.BadHashes[headers[2].Hash()] = true | 
					
						
							| 
									
										
										
										
											2017-04-06 14:58:03 +03:00
										 |  |  | 	if _, err = bc.InsertHeaderChain(headers, 1); err != core.ErrBlacklistedHash { | 
					
						
							|  |  |  | 		t.Errorf("error mismatch: have: %v, want %v", err, core.ErrBlacklistedHash) | 
					
						
							| 
									
										
										
										
											2016-10-14 05:47:09 +02:00
										 |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Tests that bad hashes are detected on boot, and the chan rolled back to a | 
					
						
							|  |  |  | // good state prior to the bad hash. | 
					
						
							|  |  |  | func TestReorgBadHeaderHashes(t *testing.T) { | 
					
						
							| 
									
										
										
										
											2017-03-02 14:03:33 +01:00
										 |  |  | 	bc := newTestLightChain() | 
					
						
							| 
									
										
										
										
											2016-10-14 05:47:09 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-07-24 16:24:27 +08:00
										 |  |  | 	// Create a chain, import and ban afterwards | 
					
						
							| 
									
										
										
										
											2017-03-02 14:03:33 +01:00
										 |  |  | 	headers := makeHeaderChainWithDiff(bc.genesisBlock, []int{1, 2, 3, 4}, 10) | 
					
						
							| 
									
										
										
										
											2016-10-14 05:47:09 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	if _, err := bc.InsertHeaderChain(headers, 1); err != nil { | 
					
						
							|  |  |  | 		t.Fatalf("failed to import headers: %v", err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if bc.CurrentHeader().Hash() != headers[3].Hash() { | 
					
						
							|  |  |  | 		t.Errorf("last header hash mismatch: have: %x, want %x", bc.CurrentHeader().Hash(), headers[3].Hash()) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	core.BadHashes[headers[3].Hash()] = true | 
					
						
							|  |  |  | 	defer func() { delete(core.BadHashes, headers[3].Hash()) }() | 
					
						
							| 
									
										
										
										
											2017-03-02 14:03:33 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	// Create a new LightChain and check that it rolled back the state. | 
					
						
							| 
									
										
											  
											
												all: on-chain oracle checkpoint syncing (#19543)
* all: implement simple checkpoint syncing
cmd, les, node: remove callback mechanism
cmd, node: remove callback definition
les: simplify the registrar
les: expose checkpoint rpc services in the light client
les, light: don't store untrusted receipt
cmd, contracts, les: discard stale checkpoint
cmd, contracts/registrar: loose restriction of registeration
cmd, contracts: add replay-protection
all: off-chain multi-signature contract
params: deploy checkpoint contract for rinkeby
cmd/registrar: add raw signing mode for registrar
cmd/registrar, contracts/registrar, les: fixed messages
* cmd/registrar, contracts/registrar: fix lints
* accounts/abi/bind, les: address comments
* cmd, contracts, les, light, params: minor checkpoint sync cleanups
* cmd, eth, les, light: move checkpoint config to config file
* cmd, eth, les, params: address comments
* eth, les, params: address comments
* cmd: polish up the checkpoint admin CLI
* cmd, contracts, params: deploy new version contract
* cmd/checkpoint-admin: add another flag for clef mode signing
* cmd, contracts, les: rename and regen checkpoint oracle with abigen
											
										 
											2019-06-28 15:34:02 +08:00
										 |  |  | 	ncm, err := NewLightChain(&dummyOdr{db: bc.chainDb}, params.TestChainConfig, ethash.NewFaker(), nil) | 
					
						
							| 
									
										
										
										
											2016-10-14 05:47:09 +02:00
										 |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		t.Fatalf("failed to create new chain manager: %v", err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if ncm.CurrentHeader().Hash() != headers[2].Hash() { | 
					
						
							|  |  |  | 		t.Errorf("last header hash mismatch: have: %x, want %x", ncm.CurrentHeader().Hash(), headers[2].Hash()) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } |