mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-08-17 09:23:48 +00:00
core, eth, les, trie: expand trie sync with leaf mode
This commit is contained in:
parent
486e795d1b
commit
458e760066
41 changed files with 447 additions and 249 deletions
|
|
@ -58,7 +58,7 @@ type SimulatedBackend struct {
|
||||||
// NewSimulatedBackend creates a new binding backend using a simulated blockchain
|
// NewSimulatedBackend creates a new binding backend using a simulated blockchain
|
||||||
// for testing purposes.
|
// for testing purposes.
|
||||||
func NewSimulatedBackend(alloc core.GenesisAlloc) *SimulatedBackend {
|
func NewSimulatedBackend(alloc core.GenesisAlloc) *SimulatedBackend {
|
||||||
database, _ := ethdb.NewMemDatabase()
|
database := ethdb.NewMemDatabase()
|
||||||
genesis := core.Genesis{Config: params.AllProtocolChanges, Alloc: alloc}
|
genesis := core.Genesis{Config: params.AllProtocolChanges, Alloc: alloc}
|
||||||
genesis.MustCommit(database)
|
genesis.MustCommit(database)
|
||||||
blockchain, _ := core.NewBlockChain(database, genesis.Config, ethash.NewFaker(), vm.Config{})
|
blockchain, _ := core.NewBlockChain(database, genesis.Config, ethash.NewFaker(), vm.Config{})
|
||||||
|
|
|
||||||
|
|
@ -99,7 +99,7 @@ func runCmd(ctx *cli.Context) error {
|
||||||
_, statedb = gen.ToBlock()
|
_, statedb = gen.ToBlock()
|
||||||
chainConfig = gen.Config
|
chainConfig = gen.Config
|
||||||
} else {
|
} else {
|
||||||
db, _ := ethdb.NewMemDatabase()
|
db := ethdb.NewMemDatabase()
|
||||||
statedb, _ = state.New(common.Hash{}, state.NewDatabase(db))
|
statedb, _ = state.New(common.Hash{}, state.NewDatabase(db))
|
||||||
}
|
}
|
||||||
if ctx.GlobalString(SenderFlag.Name) != "" {
|
if ctx.GlobalString(SenderFlag.Name) != "" {
|
||||||
|
|
|
||||||
|
|
@ -351,7 +351,7 @@ func TestVoting(t *testing.T) {
|
||||||
copy(genesis.ExtraData[extraVanity+j*common.AddressLength:], signer[:])
|
copy(genesis.ExtraData[extraVanity+j*common.AddressLength:], signer[:])
|
||||||
}
|
}
|
||||||
// Create a pristine blockchain with the genesis injected
|
// Create a pristine blockchain with the genesis injected
|
||||||
db, _ := ethdb.NewMemDatabase()
|
db := ethdb.NewMemDatabase()
|
||||||
genesis.Commit(db)
|
genesis.Commit(db)
|
||||||
|
|
||||||
// Assemble a chain of headers from the cast votes
|
// Assemble a chain of headers from the cast votes
|
||||||
|
|
|
||||||
|
|
@ -149,7 +149,7 @@ func benchInsertChain(b *testing.B, disk bool, gen func(int, *BlockGen)) {
|
||||||
// Create the database in memory or in a temporary directory.
|
// Create the database in memory or in a temporary directory.
|
||||||
var db ethdb.Database
|
var db ethdb.Database
|
||||||
if !disk {
|
if !disk {
|
||||||
db, _ = ethdb.NewMemDatabase()
|
db = ethdb.NewMemDatabase()
|
||||||
} else {
|
} else {
|
||||||
dir, err := ioutil.TempDir("", "eth-core-bench")
|
dir, err := ioutil.TempDir("", "eth-core-bench")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
||||||
|
|
@ -32,7 +32,7 @@ import (
|
||||||
func TestHeaderVerification(t *testing.T) {
|
func TestHeaderVerification(t *testing.T) {
|
||||||
// Create a simple chain to verify
|
// Create a simple chain to verify
|
||||||
var (
|
var (
|
||||||
testdb, _ = ethdb.NewMemDatabase()
|
testdb = ethdb.NewMemDatabase()
|
||||||
gspec = &Genesis{Config: params.TestChainConfig}
|
gspec = &Genesis{Config: params.TestChainConfig}
|
||||||
genesis = gspec.MustCommit(testdb)
|
genesis = gspec.MustCommit(testdb)
|
||||||
blocks, _ = GenerateChain(params.TestChainConfig, genesis, testdb, 8, nil)
|
blocks, _ = GenerateChain(params.TestChainConfig, genesis, testdb, 8, nil)
|
||||||
|
|
@ -84,7 +84,7 @@ func TestHeaderConcurrentVerification32(t *testing.T) { testHeaderConcurrentVeri
|
||||||
func testHeaderConcurrentVerification(t *testing.T, threads int) {
|
func testHeaderConcurrentVerification(t *testing.T, threads int) {
|
||||||
// Create a simple chain to verify
|
// Create a simple chain to verify
|
||||||
var (
|
var (
|
||||||
testdb, _ = ethdb.NewMemDatabase()
|
testdb = ethdb.NewMemDatabase()
|
||||||
gspec = &Genesis{Config: params.TestChainConfig}
|
gspec = &Genesis{Config: params.TestChainConfig}
|
||||||
genesis = gspec.MustCommit(testdb)
|
genesis = gspec.MustCommit(testdb)
|
||||||
blocks, _ = GenerateChain(params.TestChainConfig, genesis, testdb, 8, nil)
|
blocks, _ = GenerateChain(params.TestChainConfig, genesis, testdb, 8, nil)
|
||||||
|
|
@ -156,7 +156,7 @@ func TestHeaderConcurrentAbortion32(t *testing.T) { testHeaderConcurrentAbortion
|
||||||
func testHeaderConcurrentAbortion(t *testing.T, threads int) {
|
func testHeaderConcurrentAbortion(t *testing.T, threads int) {
|
||||||
// Create a simple chain to verify
|
// Create a simple chain to verify
|
||||||
var (
|
var (
|
||||||
testdb, _ = ethdb.NewMemDatabase()
|
testdb = ethdb.NewMemDatabase()
|
||||||
gspec = &Genesis{Config: params.TestChainConfig}
|
gspec = &Genesis{Config: params.TestChainConfig}
|
||||||
genesis = gspec.MustCommit(testdb)
|
genesis = gspec.MustCommit(testdb)
|
||||||
blocks, _ = GenerateChain(params.TestChainConfig, genesis, testdb, 1024, nil)
|
blocks, _ = GenerateChain(params.TestChainConfig, genesis, testdb, 1024, nil)
|
||||||
|
|
|
||||||
|
|
@ -36,7 +36,7 @@ import (
|
||||||
|
|
||||||
// newTestBlockChain creates a blockchain without validation.
|
// newTestBlockChain creates a blockchain without validation.
|
||||||
func newTestBlockChain(fake bool) *BlockChain {
|
func newTestBlockChain(fake bool) *BlockChain {
|
||||||
db, _ := ethdb.NewMemDatabase()
|
db := ethdb.NewMemDatabase()
|
||||||
gspec := &Genesis{
|
gspec := &Genesis{
|
||||||
Config: params.TestChainConfig,
|
Config: params.TestChainConfig,
|
||||||
Difficulty: big.NewInt(1),
|
Difficulty: big.NewInt(1),
|
||||||
|
|
@ -577,11 +577,11 @@ func testInsertNonceError(t *testing.T, full bool) {
|
||||||
func TestFastVsFullChains(t *testing.T) {
|
func TestFastVsFullChains(t *testing.T) {
|
||||||
// Configure and generate a sample block chain
|
// Configure and generate a sample block chain
|
||||||
var (
|
var (
|
||||||
gendb, _ = ethdb.NewMemDatabase()
|
gendb = ethdb.NewMemDatabase()
|
||||||
key, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
|
key, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
|
||||||
address = crypto.PubkeyToAddress(key.PublicKey)
|
address = crypto.PubkeyToAddress(key.PublicKey)
|
||||||
funds = big.NewInt(1000000000)
|
funds = big.NewInt(1000000000)
|
||||||
gspec = &Genesis{
|
gspec = &Genesis{
|
||||||
Config: params.TestChainConfig,
|
Config: params.TestChainConfig,
|
||||||
Alloc: GenesisAlloc{address: {Balance: funds}},
|
Alloc: GenesisAlloc{address: {Balance: funds}},
|
||||||
}
|
}
|
||||||
|
|
@ -607,7 +607,7 @@ func TestFastVsFullChains(t *testing.T) {
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
// Import the chain as an archive node for the comparison baseline
|
// Import the chain as an archive node for the comparison baseline
|
||||||
archiveDb, _ := ethdb.NewMemDatabase()
|
archiveDb := ethdb.NewMemDatabase()
|
||||||
gspec.MustCommit(archiveDb)
|
gspec.MustCommit(archiveDb)
|
||||||
archive, _ := NewBlockChain(archiveDb, gspec.Config, ethash.NewFaker(), vm.Config{})
|
archive, _ := NewBlockChain(archiveDb, gspec.Config, ethash.NewFaker(), vm.Config{})
|
||||||
defer archive.Stop()
|
defer archive.Stop()
|
||||||
|
|
@ -616,7 +616,7 @@ func TestFastVsFullChains(t *testing.T) {
|
||||||
t.Fatalf("failed to process block %d: %v", n, err)
|
t.Fatalf("failed to process block %d: %v", n, err)
|
||||||
}
|
}
|
||||||
// Fast import the chain as a non-archive node to test
|
// Fast import the chain as a non-archive node to test
|
||||||
fastDb, _ := ethdb.NewMemDatabase()
|
fastDb := ethdb.NewMemDatabase()
|
||||||
gspec.MustCommit(fastDb)
|
gspec.MustCommit(fastDb)
|
||||||
fast, _ := NewBlockChain(fastDb, gspec.Config, ethash.NewFaker(), vm.Config{})
|
fast, _ := NewBlockChain(fastDb, gspec.Config, ethash.NewFaker(), vm.Config{})
|
||||||
defer fast.Stop()
|
defer fast.Stop()
|
||||||
|
|
@ -665,12 +665,12 @@ func TestFastVsFullChains(t *testing.T) {
|
||||||
func TestLightVsFastVsFullChainHeads(t *testing.T) {
|
func TestLightVsFastVsFullChainHeads(t *testing.T) {
|
||||||
// Configure and generate a sample block chain
|
// Configure and generate a sample block chain
|
||||||
var (
|
var (
|
||||||
gendb, _ = ethdb.NewMemDatabase()
|
gendb = ethdb.NewMemDatabase()
|
||||||
key, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
|
key, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
|
||||||
address = crypto.PubkeyToAddress(key.PublicKey)
|
address = crypto.PubkeyToAddress(key.PublicKey)
|
||||||
funds = big.NewInt(1000000000)
|
funds = big.NewInt(1000000000)
|
||||||
gspec = &Genesis{Config: params.TestChainConfig, Alloc: GenesisAlloc{address: {Balance: funds}}}
|
gspec = &Genesis{Config: params.TestChainConfig, Alloc: GenesisAlloc{address: {Balance: funds}}}
|
||||||
genesis = gspec.MustCommit(gendb)
|
genesis = gspec.MustCommit(gendb)
|
||||||
)
|
)
|
||||||
height := uint64(1024)
|
height := uint64(1024)
|
||||||
blocks, receipts := GenerateChain(gspec.Config, genesis, gendb, int(height), nil)
|
blocks, receipts := GenerateChain(gspec.Config, genesis, gendb, int(height), nil)
|
||||||
|
|
@ -693,7 +693,7 @@ func TestLightVsFastVsFullChainHeads(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Import the chain as an archive node and ensure all pointers are updated
|
// Import the chain as an archive node and ensure all pointers are updated
|
||||||
archiveDb, _ := ethdb.NewMemDatabase()
|
archiveDb := ethdb.NewMemDatabase()
|
||||||
gspec.MustCommit(archiveDb)
|
gspec.MustCommit(archiveDb)
|
||||||
|
|
||||||
archive, _ := NewBlockChain(archiveDb, gspec.Config, ethash.NewFaker(), vm.Config{})
|
archive, _ := NewBlockChain(archiveDb, gspec.Config, ethash.NewFaker(), vm.Config{})
|
||||||
|
|
@ -707,7 +707,7 @@ func TestLightVsFastVsFullChainHeads(t *testing.T) {
|
||||||
assert(t, "archive", archive, height/2, height/2, height/2)
|
assert(t, "archive", archive, height/2, height/2, height/2)
|
||||||
|
|
||||||
// Import the chain as a non-archive node and ensure all pointers are updated
|
// Import the chain as a non-archive node and ensure all pointers are updated
|
||||||
fastDb, _ := ethdb.NewMemDatabase()
|
fastDb := ethdb.NewMemDatabase()
|
||||||
gspec.MustCommit(fastDb)
|
gspec.MustCommit(fastDb)
|
||||||
fast, _ := NewBlockChain(fastDb, gspec.Config, ethash.NewFaker(), vm.Config{})
|
fast, _ := NewBlockChain(fastDb, gspec.Config, ethash.NewFaker(), vm.Config{})
|
||||||
defer fast.Stop()
|
defer fast.Stop()
|
||||||
|
|
@ -727,7 +727,7 @@ func TestLightVsFastVsFullChainHeads(t *testing.T) {
|
||||||
assert(t, "fast", fast, height/2, height/2, 0)
|
assert(t, "fast", fast, height/2, height/2, 0)
|
||||||
|
|
||||||
// Import the chain as a light node and ensure all pointers are updated
|
// Import the chain as a light node and ensure all pointers are updated
|
||||||
lightDb, _ := ethdb.NewMemDatabase()
|
lightDb := ethdb.NewMemDatabase()
|
||||||
gspec.MustCommit(lightDb)
|
gspec.MustCommit(lightDb)
|
||||||
|
|
||||||
light, _ := NewBlockChain(lightDb, gspec.Config, ethash.NewFaker(), vm.Config{})
|
light, _ := NewBlockChain(lightDb, gspec.Config, ethash.NewFaker(), vm.Config{})
|
||||||
|
|
@ -750,7 +750,7 @@ func TestChainTxReorgs(t *testing.T) {
|
||||||
addr1 = crypto.PubkeyToAddress(key1.PublicKey)
|
addr1 = crypto.PubkeyToAddress(key1.PublicKey)
|
||||||
addr2 = crypto.PubkeyToAddress(key2.PublicKey)
|
addr2 = crypto.PubkeyToAddress(key2.PublicKey)
|
||||||
addr3 = crypto.PubkeyToAddress(key3.PublicKey)
|
addr3 = crypto.PubkeyToAddress(key3.PublicKey)
|
||||||
db, _ = ethdb.NewMemDatabase()
|
db = ethdb.NewMemDatabase()
|
||||||
gspec = &Genesis{
|
gspec = &Genesis{
|
||||||
Config: params.TestChainConfig,
|
Config: params.TestChainConfig,
|
||||||
GasLimit: 3141592,
|
GasLimit: 3141592,
|
||||||
|
|
@ -862,7 +862,7 @@ func TestLogReorgs(t *testing.T) {
|
||||||
var (
|
var (
|
||||||
key1, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
|
key1, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
|
||||||
addr1 = crypto.PubkeyToAddress(key1.PublicKey)
|
addr1 = crypto.PubkeyToAddress(key1.PublicKey)
|
||||||
db, _ = ethdb.NewMemDatabase()
|
db = ethdb.NewMemDatabase()
|
||||||
// this code generates a log
|
// this code generates a log
|
||||||
code = common.Hex2Bytes("60606040525b7f24ec1d3ff24c2f6ff210738839dbc339cd45a5294d85c79361016243157aae7b60405180905060405180910390a15b600a8060416000396000f360606040526008565b00")
|
code = common.Hex2Bytes("60606040525b7f24ec1d3ff24c2f6ff210738839dbc339cd45a5294d85c79361016243157aae7b60405180905060405180910390a15b600a8060416000396000f360606040526008565b00")
|
||||||
gspec = &Genesis{Config: params.TestChainConfig, Alloc: GenesisAlloc{addr1: {Balance: big.NewInt(10000000000000)}}}
|
gspec = &Genesis{Config: params.TestChainConfig, Alloc: GenesisAlloc{addr1: {Balance: big.NewInt(10000000000000)}}}
|
||||||
|
|
@ -906,7 +906,7 @@ func TestLogReorgs(t *testing.T) {
|
||||||
|
|
||||||
func TestReorgSideEvent(t *testing.T) {
|
func TestReorgSideEvent(t *testing.T) {
|
||||||
var (
|
var (
|
||||||
db, _ = ethdb.NewMemDatabase()
|
db = ethdb.NewMemDatabase()
|
||||||
key1, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
|
key1, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
|
||||||
addr1 = crypto.PubkeyToAddress(key1.PublicKey)
|
addr1 = crypto.PubkeyToAddress(key1.PublicKey)
|
||||||
gspec = &Genesis{
|
gspec = &Genesis{
|
||||||
|
|
@ -1031,7 +1031,7 @@ func TestCanonicalBlockRetrieval(t *testing.T) {
|
||||||
func TestEIP155Transition(t *testing.T) {
|
func TestEIP155Transition(t *testing.T) {
|
||||||
// Configure and generate a sample block chain
|
// Configure and generate a sample block chain
|
||||||
var (
|
var (
|
||||||
db, _ = ethdb.NewMemDatabase()
|
db = ethdb.NewMemDatabase()
|
||||||
key, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
|
key, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
|
||||||
address = crypto.PubkeyToAddress(key.PublicKey)
|
address = crypto.PubkeyToAddress(key.PublicKey)
|
||||||
funds = big.NewInt(1000000000)
|
funds = big.NewInt(1000000000)
|
||||||
|
|
@ -1135,7 +1135,7 @@ func TestEIP155Transition(t *testing.T) {
|
||||||
func TestEIP161AccountRemoval(t *testing.T) {
|
func TestEIP161AccountRemoval(t *testing.T) {
|
||||||
// Configure and generate a sample block chain
|
// Configure and generate a sample block chain
|
||||||
var (
|
var (
|
||||||
db, _ = ethdb.NewMemDatabase()
|
db = ethdb.NewMemDatabase()
|
||||||
key, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
|
key, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
|
||||||
address = crypto.PubkeyToAddress(key.PublicKey)
|
address = crypto.PubkeyToAddress(key.PublicKey)
|
||||||
funds = big.NewInt(1000000000)
|
funds = big.NewInt(1000000000)
|
||||||
|
|
|
||||||
|
|
@ -46,7 +46,7 @@ func TestChainIndexerWithChildren(t *testing.T) {
|
||||||
// multiple backends. The section size and required confirmation count parameters
|
// multiple backends. The section size and required confirmation count parameters
|
||||||
// are randomized.
|
// are randomized.
|
||||||
func testChainIndexer(t *testing.T, count int) {
|
func testChainIndexer(t *testing.T, count int) {
|
||||||
db, _ := ethdb.NewMemDatabase()
|
db := ethdb.NewMemDatabase()
|
||||||
defer db.Close()
|
defer db.Close()
|
||||||
|
|
||||||
// Create a chain of indexers and ensure they all report empty
|
// Create a chain of indexers and ensure they all report empty
|
||||||
|
|
|
||||||
|
|
@ -232,7 +232,7 @@ func makeHeader(config *params.ChainConfig, parent *types.Block, state *state.St
|
||||||
func newCanonical(n int, full bool) (ethdb.Database, *BlockChain, error) {
|
func newCanonical(n int, full bool) (ethdb.Database, *BlockChain, error) {
|
||||||
// Initialize a fresh chain with only a genesis block
|
// Initialize a fresh chain with only a genesis block
|
||||||
gspec := new(Genesis)
|
gspec := new(Genesis)
|
||||||
db, _ := ethdb.NewMemDatabase()
|
db := ethdb.NewMemDatabase()
|
||||||
genesis := gspec.MustCommit(db)
|
genesis := gspec.MustCommit(db)
|
||||||
|
|
||||||
blockchain, _ := NewBlockChain(db, params.AllProtocolChanges, ethash.NewFaker(), vm.Config{})
|
blockchain, _ := NewBlockChain(db, params.AllProtocolChanges, ethash.NewFaker(), vm.Config{})
|
||||||
|
|
|
||||||
|
|
@ -36,7 +36,7 @@ func ExampleGenerateChain() {
|
||||||
addr1 = crypto.PubkeyToAddress(key1.PublicKey)
|
addr1 = crypto.PubkeyToAddress(key1.PublicKey)
|
||||||
addr2 = crypto.PubkeyToAddress(key2.PublicKey)
|
addr2 = crypto.PubkeyToAddress(key2.PublicKey)
|
||||||
addr3 = crypto.PubkeyToAddress(key3.PublicKey)
|
addr3 = crypto.PubkeyToAddress(key3.PublicKey)
|
||||||
db, _ = ethdb.NewMemDatabase()
|
db = ethdb.NewMemDatabase()
|
||||||
)
|
)
|
||||||
|
|
||||||
// Ensure that key1 has some funds in the genesis block.
|
// Ensure that key1 has some funds in the genesis block.
|
||||||
|
|
|
||||||
|
|
@ -32,13 +32,13 @@ func TestDAOForkRangeExtradata(t *testing.T) {
|
||||||
forkBlock := big.NewInt(32)
|
forkBlock := big.NewInt(32)
|
||||||
|
|
||||||
// Generate a common prefix for both pro-forkers and non-forkers
|
// Generate a common prefix for both pro-forkers and non-forkers
|
||||||
db, _ := ethdb.NewMemDatabase()
|
db := ethdb.NewMemDatabase()
|
||||||
gspec := new(Genesis)
|
gspec := new(Genesis)
|
||||||
genesis := gspec.MustCommit(db)
|
genesis := gspec.MustCommit(db)
|
||||||
prefix, _ := GenerateChain(params.TestChainConfig, genesis, db, int(forkBlock.Int64()-1), func(i int, gen *BlockGen) {})
|
prefix, _ := GenerateChain(params.TestChainConfig, genesis, db, int(forkBlock.Int64()-1), func(i int, gen *BlockGen) {})
|
||||||
|
|
||||||
// Create the concurrent, conflicting two nodes
|
// Create the concurrent, conflicting two nodes
|
||||||
proDb, _ := ethdb.NewMemDatabase()
|
proDb := ethdb.NewMemDatabase()
|
||||||
gspec.MustCommit(proDb)
|
gspec.MustCommit(proDb)
|
||||||
|
|
||||||
proConf := *params.TestChainConfig
|
proConf := *params.TestChainConfig
|
||||||
|
|
@ -48,7 +48,7 @@ func TestDAOForkRangeExtradata(t *testing.T) {
|
||||||
proBc, _ := NewBlockChain(proDb, &proConf, ethash.NewFaker(), vm.Config{})
|
proBc, _ := NewBlockChain(proDb, &proConf, ethash.NewFaker(), vm.Config{})
|
||||||
defer proBc.Stop()
|
defer proBc.Stop()
|
||||||
|
|
||||||
conDb, _ := ethdb.NewMemDatabase()
|
conDb := ethdb.NewMemDatabase()
|
||||||
gspec.MustCommit(conDb)
|
gspec.MustCommit(conDb)
|
||||||
|
|
||||||
conConf := *params.TestChainConfig
|
conConf := *params.TestChainConfig
|
||||||
|
|
@ -67,7 +67,7 @@ func TestDAOForkRangeExtradata(t *testing.T) {
|
||||||
// Try to expand both pro-fork and non-fork chains iteratively with other camp's blocks
|
// Try to expand both pro-fork and non-fork chains iteratively with other camp's blocks
|
||||||
for i := int64(0); i < params.DAOForkExtraRange.Int64(); i++ {
|
for i := int64(0); i < params.DAOForkExtraRange.Int64(); i++ {
|
||||||
// Create a pro-fork block, and try to feed into the no-fork chain
|
// Create a pro-fork block, and try to feed into the no-fork chain
|
||||||
db, _ = ethdb.NewMemDatabase()
|
db = ethdb.NewMemDatabase()
|
||||||
gspec.MustCommit(db)
|
gspec.MustCommit(db)
|
||||||
bc, _ := NewBlockChain(db, &conConf, ethash.NewFaker(), vm.Config{})
|
bc, _ := NewBlockChain(db, &conConf, ethash.NewFaker(), vm.Config{})
|
||||||
defer bc.Stop()
|
defer bc.Stop()
|
||||||
|
|
@ -89,7 +89,7 @@ func TestDAOForkRangeExtradata(t *testing.T) {
|
||||||
t.Fatalf("contra-fork chain didn't accepted no-fork block: %v", err)
|
t.Fatalf("contra-fork chain didn't accepted no-fork block: %v", err)
|
||||||
}
|
}
|
||||||
// Create a no-fork block, and try to feed into the pro-fork chain
|
// Create a no-fork block, and try to feed into the pro-fork chain
|
||||||
db, _ = ethdb.NewMemDatabase()
|
db = ethdb.NewMemDatabase()
|
||||||
gspec.MustCommit(db)
|
gspec.MustCommit(db)
|
||||||
bc, _ = NewBlockChain(db, &proConf, ethash.NewFaker(), vm.Config{})
|
bc, _ = NewBlockChain(db, &proConf, ethash.NewFaker(), vm.Config{})
|
||||||
defer bc.Stop()
|
defer bc.Stop()
|
||||||
|
|
@ -112,7 +112,7 @@ func TestDAOForkRangeExtradata(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Verify that contra-forkers accept pro-fork extra-datas after forking finishes
|
// Verify that contra-forkers accept pro-fork extra-datas after forking finishes
|
||||||
db, _ = ethdb.NewMemDatabase()
|
db = ethdb.NewMemDatabase()
|
||||||
gspec.MustCommit(db)
|
gspec.MustCommit(db)
|
||||||
bc, _ := NewBlockChain(db, &conConf, ethash.NewFaker(), vm.Config{})
|
bc, _ := NewBlockChain(db, &conConf, ethash.NewFaker(), vm.Config{})
|
||||||
defer bc.Stop()
|
defer bc.Stop()
|
||||||
|
|
@ -129,7 +129,7 @@ func TestDAOForkRangeExtradata(t *testing.T) {
|
||||||
t.Fatalf("contra-fork chain didn't accept pro-fork block post-fork: %v", err)
|
t.Fatalf("contra-fork chain didn't accept pro-fork block post-fork: %v", err)
|
||||||
}
|
}
|
||||||
// Verify that pro-forkers accept contra-fork extra-datas after forking finishes
|
// Verify that pro-forkers accept contra-fork extra-datas after forking finishes
|
||||||
db, _ = ethdb.NewMemDatabase()
|
db = ethdb.NewMemDatabase()
|
||||||
gspec.MustCommit(db)
|
gspec.MustCommit(db)
|
||||||
bc, _ = NewBlockChain(db, &proConf, ethash.NewFaker(), vm.Config{})
|
bc, _ = NewBlockChain(db, &proConf, ethash.NewFaker(), vm.Config{})
|
||||||
defer bc.Stop()
|
defer bc.Stop()
|
||||||
|
|
|
||||||
|
|
@ -30,7 +30,7 @@ import (
|
||||||
|
|
||||||
// Tests block header storage and retrieval operations.
|
// Tests block header storage and retrieval operations.
|
||||||
func TestHeaderStorage(t *testing.T) {
|
func TestHeaderStorage(t *testing.T) {
|
||||||
db, _ := ethdb.NewMemDatabase()
|
db := ethdb.NewMemDatabase()
|
||||||
|
|
||||||
// Create a test header to move around the database and make sure it's really new
|
// Create a test header to move around the database and make sure it's really new
|
||||||
header := &types.Header{Number: big.NewInt(42), Extra: []byte("test header")}
|
header := &types.Header{Number: big.NewInt(42), Extra: []byte("test header")}
|
||||||
|
|
@ -65,7 +65,7 @@ func TestHeaderStorage(t *testing.T) {
|
||||||
|
|
||||||
// Tests block body storage and retrieval operations.
|
// Tests block body storage and retrieval operations.
|
||||||
func TestBodyStorage(t *testing.T) {
|
func TestBodyStorage(t *testing.T) {
|
||||||
db, _ := ethdb.NewMemDatabase()
|
db := ethdb.NewMemDatabase()
|
||||||
|
|
||||||
// Create a test body to move around the database and make sure it's really new
|
// Create a test body to move around the database and make sure it's really new
|
||||||
body := &types.Body{Uncles: []*types.Header{{Extra: []byte("test header")}}}
|
body := &types.Body{Uncles: []*types.Header{{Extra: []byte("test header")}}}
|
||||||
|
|
@ -105,7 +105,7 @@ func TestBodyStorage(t *testing.T) {
|
||||||
|
|
||||||
// Tests block storage and retrieval operations.
|
// Tests block storage and retrieval operations.
|
||||||
func TestBlockStorage(t *testing.T) {
|
func TestBlockStorage(t *testing.T) {
|
||||||
db, _ := ethdb.NewMemDatabase()
|
db := ethdb.NewMemDatabase()
|
||||||
|
|
||||||
// Create a test block to move around the database and make sure it's really new
|
// Create a test block to move around the database and make sure it's really new
|
||||||
block := types.NewBlockWithHeader(&types.Header{
|
block := types.NewBlockWithHeader(&types.Header{
|
||||||
|
|
@ -157,7 +157,7 @@ func TestBlockStorage(t *testing.T) {
|
||||||
|
|
||||||
// Tests that partial block contents don't get reassembled into full blocks.
|
// Tests that partial block contents don't get reassembled into full blocks.
|
||||||
func TestPartialBlockStorage(t *testing.T) {
|
func TestPartialBlockStorage(t *testing.T) {
|
||||||
db, _ := ethdb.NewMemDatabase()
|
db := ethdb.NewMemDatabase()
|
||||||
block := types.NewBlockWithHeader(&types.Header{
|
block := types.NewBlockWithHeader(&types.Header{
|
||||||
Extra: []byte("test block"),
|
Extra: []byte("test block"),
|
||||||
UncleHash: types.EmptyUncleHash,
|
UncleHash: types.EmptyUncleHash,
|
||||||
|
|
@ -198,7 +198,7 @@ func TestPartialBlockStorage(t *testing.T) {
|
||||||
|
|
||||||
// Tests block total difficulty storage and retrieval operations.
|
// Tests block total difficulty storage and retrieval operations.
|
||||||
func TestTdStorage(t *testing.T) {
|
func TestTdStorage(t *testing.T) {
|
||||||
db, _ := ethdb.NewMemDatabase()
|
db := ethdb.NewMemDatabase()
|
||||||
|
|
||||||
// Create a test TD to move around the database and make sure it's really new
|
// Create a test TD to move around the database and make sure it's really new
|
||||||
hash, td := common.Hash{}, big.NewInt(314)
|
hash, td := common.Hash{}, big.NewInt(314)
|
||||||
|
|
@ -223,7 +223,7 @@ func TestTdStorage(t *testing.T) {
|
||||||
|
|
||||||
// Tests that canonical numbers can be mapped to hashes and retrieved.
|
// Tests that canonical numbers can be mapped to hashes and retrieved.
|
||||||
func TestCanonicalMappingStorage(t *testing.T) {
|
func TestCanonicalMappingStorage(t *testing.T) {
|
||||||
db, _ := ethdb.NewMemDatabase()
|
db := ethdb.NewMemDatabase()
|
||||||
|
|
||||||
// Create a test canonical number and assinged hash to move around
|
// Create a test canonical number and assinged hash to move around
|
||||||
hash, number := common.Hash{0: 0xff}, uint64(314)
|
hash, number := common.Hash{0: 0xff}, uint64(314)
|
||||||
|
|
@ -248,7 +248,7 @@ func TestCanonicalMappingStorage(t *testing.T) {
|
||||||
|
|
||||||
// Tests that head headers and head blocks can be assigned, individually.
|
// Tests that head headers and head blocks can be assigned, individually.
|
||||||
func TestHeadStorage(t *testing.T) {
|
func TestHeadStorage(t *testing.T) {
|
||||||
db, _ := ethdb.NewMemDatabase()
|
db := ethdb.NewMemDatabase()
|
||||||
|
|
||||||
blockHead := types.NewBlockWithHeader(&types.Header{Extra: []byte("test block header")})
|
blockHead := types.NewBlockWithHeader(&types.Header{Extra: []byte("test block header")})
|
||||||
blockFull := types.NewBlockWithHeader(&types.Header{Extra: []byte("test block full")})
|
blockFull := types.NewBlockWithHeader(&types.Header{Extra: []byte("test block full")})
|
||||||
|
|
@ -288,7 +288,7 @@ func TestHeadStorage(t *testing.T) {
|
||||||
|
|
||||||
// Tests that positional lookup metadata can be stored and retrieved.
|
// Tests that positional lookup metadata can be stored and retrieved.
|
||||||
func TestLookupStorage(t *testing.T) {
|
func TestLookupStorage(t *testing.T) {
|
||||||
db, _ := ethdb.NewMemDatabase()
|
db := ethdb.NewMemDatabase()
|
||||||
|
|
||||||
tx1 := types.NewTransaction(1, common.BytesToAddress([]byte{0x11}), big.NewInt(111), big.NewInt(1111), big.NewInt(11111), []byte{0x11, 0x11, 0x11})
|
tx1 := types.NewTransaction(1, common.BytesToAddress([]byte{0x11}), big.NewInt(111), big.NewInt(1111), big.NewInt(11111), []byte{0x11, 0x11, 0x11})
|
||||||
tx2 := types.NewTransaction(2, common.BytesToAddress([]byte{0x22}), big.NewInt(222), big.NewInt(2222), big.NewInt(22222), []byte{0x22, 0x22, 0x22})
|
tx2 := types.NewTransaction(2, common.BytesToAddress([]byte{0x22}), big.NewInt(222), big.NewInt(2222), big.NewInt(22222), []byte{0x22, 0x22, 0x22})
|
||||||
|
|
@ -333,7 +333,7 @@ func TestLookupStorage(t *testing.T) {
|
||||||
|
|
||||||
// Tests that receipts associated with a single block can be stored and retrieved.
|
// Tests that receipts associated with a single block can be stored and retrieved.
|
||||||
func TestBlockReceiptStorage(t *testing.T) {
|
func TestBlockReceiptStorage(t *testing.T) {
|
||||||
db, _ := ethdb.NewMemDatabase()
|
db := ethdb.NewMemDatabase()
|
||||||
|
|
||||||
receipt1 := &types.Receipt{
|
receipt1 := &types.Receipt{
|
||||||
Status: types.ReceiptStatusFailed,
|
Status: types.ReceiptStatusFailed,
|
||||||
|
|
|
||||||
|
|
@ -222,7 +222,7 @@ func (g *Genesis) configOrDefault(ghash common.Hash) *params.ChainConfig {
|
||||||
|
|
||||||
// ToBlock creates the block and state of a genesis specification.
|
// ToBlock creates the block and state of a genesis specification.
|
||||||
func (g *Genesis) ToBlock() (*types.Block, *state.StateDB) {
|
func (g *Genesis) ToBlock() (*types.Block, *state.StateDB) {
|
||||||
db, _ := ethdb.NewMemDatabase()
|
db := ethdb.NewMemDatabase()
|
||||||
statedb, _ := state.New(common.Hash{}, state.NewDatabase(db))
|
statedb, _ := state.New(common.Hash{}, state.NewDatabase(db))
|
||||||
for addr, account := range g.Alloc {
|
for addr, account := range g.Alloc {
|
||||||
statedb.AddBalance(addr, account.Balance)
|
statedb.AddBalance(addr, account.Balance)
|
||||||
|
|
|
||||||
|
|
@ -138,7 +138,7 @@ func TestSetupGenesis(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, test := range tests {
|
for _, test := range tests {
|
||||||
db, _ := ethdb.NewMemDatabase()
|
db := ethdb.NewMemDatabase()
|
||||||
config, hash, err := test.fn(db)
|
config, hash, err := test.fn(db)
|
||||||
// Check the return values.
|
// Check the return values.
|
||||||
if !reflect.DeepEqual(err, test.wantErr) {
|
if !reflect.DeepEqual(err, test.wantErr) {
|
||||||
|
|
|
||||||
|
|
@ -18,7 +18,6 @@ package core
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"container/list"
|
"container/list"
|
||||||
"fmt"
|
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/core/types"
|
"github.com/ethereum/go-ethereum/core/types"
|
||||||
"github.com/ethereum/go-ethereum/ethdb"
|
"github.com/ethereum/go-ethereum/ethdb"
|
||||||
|
|
@ -77,15 +76,9 @@ func (tm *TestManager) Db() ethdb.Database {
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewTestManager() *TestManager {
|
func NewTestManager() *TestManager {
|
||||||
db, err := ethdb.NewMemDatabase()
|
|
||||||
if err != nil {
|
|
||||||
fmt.Println("Could not create mem-db, failing")
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
testManager := &TestManager{}
|
testManager := &TestManager{}
|
||||||
testManager.eventMux = new(event.TypeMux)
|
testManager.eventMux = new(event.TypeMux)
|
||||||
testManager.db = db
|
testManager.db = ethdb.NewMemDatabase()
|
||||||
// testManager.txPool = NewTxPool(testManager)
|
// testManager.txPool = NewTxPool(testManager)
|
||||||
// testManager.blockChain = NewBlockChain(testManager)
|
// testManager.blockChain = NewBlockChain(testManager)
|
||||||
// testManager.stateManager = NewStateManager(testManager)
|
// testManager.stateManager = NewStateManager(testManager)
|
||||||
|
|
|
||||||
|
|
@ -26,7 +26,7 @@ import (
|
||||||
var addr = common.BytesToAddress([]byte("test"))
|
var addr = common.BytesToAddress([]byte("test"))
|
||||||
|
|
||||||
func create() (*ManagedState, *account) {
|
func create() (*ManagedState, *account) {
|
||||||
db, _ := ethdb.NewMemDatabase()
|
db := ethdb.NewMemDatabase()
|
||||||
statedb, _ := New(common.Hash{}, NewDatabase(db))
|
statedb, _ := New(common.Hash{}, NewDatabase(db))
|
||||||
ms := ManageState(statedb)
|
ms := ManageState(statedb)
|
||||||
ms.StateDB.SetNonce(addr, 100)
|
ms.StateDB.SetNonce(addr, 100)
|
||||||
|
|
|
||||||
|
|
@ -87,7 +87,7 @@ func (s *StateSuite) TestDump(c *checker.C) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *StateSuite) SetUpTest(c *checker.C) {
|
func (s *StateSuite) SetUpTest(c *checker.C) {
|
||||||
s.db, _ = ethdb.NewMemDatabase()
|
s.db = ethdb.NewMemDatabase()
|
||||||
s.state, _ = New(common.Hash{}, NewDatabase(s.db))
|
s.state, _ = New(common.Hash{}, NewDatabase(s.db))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -133,7 +133,7 @@ func (s *StateSuite) TestSnapshotEmpty(c *checker.C) {
|
||||||
// use testing instead of checker because checker does not support
|
// use testing instead of checker because checker does not support
|
||||||
// printing/logging in tests (-check.vv does not work)
|
// printing/logging in tests (-check.vv does not work)
|
||||||
func TestSnapshot2(t *testing.T) {
|
func TestSnapshot2(t *testing.T) {
|
||||||
db, _ := ethdb.NewMemDatabase()
|
db := ethdb.NewMemDatabase()
|
||||||
state, _ := New(common.Hash{}, NewDatabase(db))
|
state, _ := New(common.Hash{}, NewDatabase(db))
|
||||||
|
|
||||||
stateobjaddr0 := toAddr([]byte("so0"))
|
stateobjaddr0 := toAddr([]byte("so0"))
|
||||||
|
|
|
||||||
|
|
@ -39,7 +39,7 @@ import (
|
||||||
// actually committing the state.
|
// actually committing the state.
|
||||||
func TestUpdateLeaks(t *testing.T) {
|
func TestUpdateLeaks(t *testing.T) {
|
||||||
// Create an empty state database
|
// Create an empty state database
|
||||||
db, _ := ethdb.NewMemDatabase()
|
db := ethdb.NewMemDatabase()
|
||||||
state, _ := New(common.Hash{}, NewDatabase(db))
|
state, _ := New(common.Hash{}, NewDatabase(db))
|
||||||
|
|
||||||
// Update it with some accounts
|
// Update it with some accounts
|
||||||
|
|
@ -66,8 +66,8 @@ func TestUpdateLeaks(t *testing.T) {
|
||||||
// only the one right before the commit.
|
// only the one right before the commit.
|
||||||
func TestIntermediateLeaks(t *testing.T) {
|
func TestIntermediateLeaks(t *testing.T) {
|
||||||
// Create two state databases, one transitioning to the final state, the other final from the beginning
|
// Create two state databases, one transitioning to the final state, the other final from the beginning
|
||||||
transDb, _ := ethdb.NewMemDatabase()
|
transDb := ethdb.NewMemDatabase()
|
||||||
finalDb, _ := ethdb.NewMemDatabase()
|
finalDb := ethdb.NewMemDatabase()
|
||||||
transState, _ := New(common.Hash{}, NewDatabase(transDb))
|
transState, _ := New(common.Hash{}, NewDatabase(transDb))
|
||||||
finalState, _ := New(common.Hash{}, NewDatabase(finalDb))
|
finalState, _ := New(common.Hash{}, NewDatabase(finalDb))
|
||||||
|
|
||||||
|
|
@ -283,7 +283,7 @@ func (test *snapshotTest) String() string {
|
||||||
func (test *snapshotTest) run() bool {
|
func (test *snapshotTest) run() bool {
|
||||||
// Run all actions and create snapshots.
|
// Run all actions and create snapshots.
|
||||||
var (
|
var (
|
||||||
db, _ = ethdb.NewMemDatabase()
|
db = ethdb.NewMemDatabase()
|
||||||
state, _ = New(common.Hash{}, NewDatabase(db))
|
state, _ = New(common.Hash{}, NewDatabase(db))
|
||||||
snapshotRevs = make([]int, len(test.snapshots))
|
snapshotRevs = make([]int, len(test.snapshots))
|
||||||
sindex = 0
|
sindex = 0
|
||||||
|
|
|
||||||
|
|
@ -38,7 +38,7 @@ type testAccount struct {
|
||||||
// makeTestState create a sample test state to test node-wise reconstruction.
|
// makeTestState create a sample test state to test node-wise reconstruction.
|
||||||
func makeTestState() (Database, *ethdb.MemDatabase, common.Hash, []*testAccount) {
|
func makeTestState() (Database, *ethdb.MemDatabase, common.Hash, []*testAccount) {
|
||||||
// Create an empty state
|
// Create an empty state
|
||||||
mem, _ := ethdb.NewMemDatabase()
|
mem := ethdb.NewMemDatabase()
|
||||||
db := NewDatabase(mem)
|
db := NewDatabase(mem)
|
||||||
state, _ := New(common.Hash{}, db)
|
state, _ := New(common.Hash{}, db)
|
||||||
|
|
||||||
|
|
@ -125,7 +125,7 @@ func checkStateConsistency(db ethdb.Database, root common.Hash) error {
|
||||||
// Tests that an empty state is not scheduled for syncing.
|
// Tests that an empty state is not scheduled for syncing.
|
||||||
func TestEmptyStateSync(t *testing.T) {
|
func TestEmptyStateSync(t *testing.T) {
|
||||||
empty := common.HexToHash("56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421")
|
empty := common.HexToHash("56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421")
|
||||||
db, _ := ethdb.NewMemDatabase()
|
db := ethdb.NewMemDatabase()
|
||||||
if req := NewStateSync(empty, db).Missing(1); len(req) != 0 {
|
if req := NewStateSync(empty, db).Missing(1); len(req) != 0 {
|
||||||
t.Errorf("content requested for empty state: %v", req)
|
t.Errorf("content requested for empty state: %v", req)
|
||||||
}
|
}
|
||||||
|
|
@ -141,7 +141,7 @@ func testIterativeStateSync(t *testing.T, batch int) {
|
||||||
_, srcMem, srcRoot, srcAccounts := makeTestState()
|
_, srcMem, srcRoot, srcAccounts := makeTestState()
|
||||||
|
|
||||||
// Create a destination state and sync with the scheduler
|
// Create a destination state and sync with the scheduler
|
||||||
dstDb, _ := ethdb.NewMemDatabase()
|
dstDb := ethdb.NewMemDatabase()
|
||||||
sched := NewStateSync(srcRoot, dstDb)
|
sched := NewStateSync(srcRoot, dstDb)
|
||||||
|
|
||||||
queue := append([]common.Hash{}, sched.Missing(batch)...)
|
queue := append([]common.Hash{}, sched.Missing(batch)...)
|
||||||
|
|
@ -173,7 +173,7 @@ func TestIterativeDelayedStateSync(t *testing.T) {
|
||||||
_, srcMem, srcRoot, srcAccounts := makeTestState()
|
_, srcMem, srcRoot, srcAccounts := makeTestState()
|
||||||
|
|
||||||
// Create a destination state and sync with the scheduler
|
// Create a destination state and sync with the scheduler
|
||||||
dstDb, _ := ethdb.NewMemDatabase()
|
dstDb := ethdb.NewMemDatabase()
|
||||||
sched := NewStateSync(srcRoot, dstDb)
|
sched := NewStateSync(srcRoot, dstDb)
|
||||||
|
|
||||||
queue := append([]common.Hash{}, sched.Missing(0)...)
|
queue := append([]common.Hash{}, sched.Missing(0)...)
|
||||||
|
|
@ -210,7 +210,7 @@ func testIterativeRandomStateSync(t *testing.T, batch int) {
|
||||||
_, srcMem, srcRoot, srcAccounts := makeTestState()
|
_, srcMem, srcRoot, srcAccounts := makeTestState()
|
||||||
|
|
||||||
// Create a destination state and sync with the scheduler
|
// Create a destination state and sync with the scheduler
|
||||||
dstDb, _ := ethdb.NewMemDatabase()
|
dstDb := ethdb.NewMemDatabase()
|
||||||
sched := NewStateSync(srcRoot, dstDb)
|
sched := NewStateSync(srcRoot, dstDb)
|
||||||
|
|
||||||
queue := make(map[common.Hash]struct{})
|
queue := make(map[common.Hash]struct{})
|
||||||
|
|
@ -250,7 +250,7 @@ func TestIterativeRandomDelayedStateSync(t *testing.T) {
|
||||||
_, srcMem, srcRoot, srcAccounts := makeTestState()
|
_, srcMem, srcRoot, srcAccounts := makeTestState()
|
||||||
|
|
||||||
// Create a destination state and sync with the scheduler
|
// Create a destination state and sync with the scheduler
|
||||||
dstDb, _ := ethdb.NewMemDatabase()
|
dstDb := ethdb.NewMemDatabase()
|
||||||
sched := NewStateSync(srcRoot, dstDb)
|
sched := NewStateSync(srcRoot, dstDb)
|
||||||
|
|
||||||
queue := make(map[common.Hash]struct{})
|
queue := make(map[common.Hash]struct{})
|
||||||
|
|
@ -297,7 +297,7 @@ func TestIncompleteStateSync(t *testing.T) {
|
||||||
checkTrieConsistency(srcMem, srcRoot)
|
checkTrieConsistency(srcMem, srcRoot)
|
||||||
|
|
||||||
// Create a destination state and sync with the scheduler
|
// Create a destination state and sync with the scheduler
|
||||||
dstDb, _ := ethdb.NewMemDatabase()
|
dstDb := ethdb.NewMemDatabase()
|
||||||
sched := NewStateSync(srcRoot, dstDb)
|
sched := NewStateSync(srcRoot, dstDb)
|
||||||
|
|
||||||
added := []common.Hash{}
|
added := []common.Hash{}
|
||||||
|
|
|
||||||
|
|
@ -78,7 +78,7 @@ func pricedTransaction(nonce uint64, gaslimit, gasprice *big.Int, key *ecdsa.Pri
|
||||||
}
|
}
|
||||||
|
|
||||||
func setupTxPool() (*TxPool, *ecdsa.PrivateKey) {
|
func setupTxPool() (*TxPool, *ecdsa.PrivateKey) {
|
||||||
db, _ := ethdb.NewMemDatabase()
|
db := ethdb.NewMemDatabase()
|
||||||
statedb, _ := state.New(common.Hash{}, state.NewDatabase(db))
|
statedb, _ := state.New(common.Hash{}, state.NewDatabase(db))
|
||||||
blockchain := &testBlockChain{statedb, big.NewInt(1000000), new(event.Feed)}
|
blockchain := &testBlockChain{statedb, big.NewInt(1000000), new(event.Feed)}
|
||||||
|
|
||||||
|
|
@ -136,7 +136,7 @@ func (c *testChain) State() (*state.StateDB, error) {
|
||||||
// a state change between those fetches.
|
// a state change between those fetches.
|
||||||
stdb := c.statedb
|
stdb := c.statedb
|
||||||
if *c.trigger {
|
if *c.trigger {
|
||||||
db, _ := ethdb.NewMemDatabase()
|
db := ethdb.NewMemDatabase()
|
||||||
c.statedb, _ = state.New(common.Hash{}, state.NewDatabase(db))
|
c.statedb, _ = state.New(common.Hash{}, state.NewDatabase(db))
|
||||||
// simulate that the new head block included tx0 and tx1
|
// simulate that the new head block included tx0 and tx1
|
||||||
c.statedb.SetNonce(c.address, 2)
|
c.statedb.SetNonce(c.address, 2)
|
||||||
|
|
@ -151,7 +151,7 @@ func (c *testChain) State() (*state.StateDB, error) {
|
||||||
// block head event that initiated the resetState().
|
// block head event that initiated the resetState().
|
||||||
func TestStateChangeDuringPoolReset(t *testing.T) {
|
func TestStateChangeDuringPoolReset(t *testing.T) {
|
||||||
var (
|
var (
|
||||||
db, _ = ethdb.NewMemDatabase()
|
db = ethdb.NewMemDatabase()
|
||||||
key, _ = crypto.GenerateKey()
|
key, _ = crypto.GenerateKey()
|
||||||
address = crypto.PubkeyToAddress(key.PublicKey)
|
address = crypto.PubkeyToAddress(key.PublicKey)
|
||||||
statedb, _ = state.New(common.Hash{}, state.NewDatabase(db))
|
statedb, _ = state.New(common.Hash{}, state.NewDatabase(db))
|
||||||
|
|
@ -305,7 +305,7 @@ func TestTransactionChainFork(t *testing.T) {
|
||||||
|
|
||||||
addr := crypto.PubkeyToAddress(key.PublicKey)
|
addr := crypto.PubkeyToAddress(key.PublicKey)
|
||||||
resetState := func() {
|
resetState := func() {
|
||||||
db, _ := ethdb.NewMemDatabase()
|
db := ethdb.NewMemDatabase()
|
||||||
statedb, _ := state.New(common.Hash{}, state.NewDatabase(db))
|
statedb, _ := state.New(common.Hash{}, state.NewDatabase(db))
|
||||||
statedb.AddBalance(addr, big.NewInt(100000000000000))
|
statedb.AddBalance(addr, big.NewInt(100000000000000))
|
||||||
|
|
||||||
|
|
@ -333,7 +333,7 @@ func TestTransactionDoubleNonce(t *testing.T) {
|
||||||
|
|
||||||
addr := crypto.PubkeyToAddress(key.PublicKey)
|
addr := crypto.PubkeyToAddress(key.PublicKey)
|
||||||
resetState := func() {
|
resetState := func() {
|
||||||
db, _ := ethdb.NewMemDatabase()
|
db := ethdb.NewMemDatabase()
|
||||||
statedb, _ := state.New(common.Hash{}, state.NewDatabase(db))
|
statedb, _ := state.New(common.Hash{}, state.NewDatabase(db))
|
||||||
statedb.AddBalance(addr, big.NewInt(100000000000000))
|
statedb.AddBalance(addr, big.NewInt(100000000000000))
|
||||||
|
|
||||||
|
|
@ -633,7 +633,7 @@ func TestTransactionQueueGlobalLimitingNoLocals(t *testing.T) {
|
||||||
|
|
||||||
func testTransactionQueueGlobalLimiting(t *testing.T, nolocals bool) {
|
func testTransactionQueueGlobalLimiting(t *testing.T, nolocals bool) {
|
||||||
// Create the pool to test the limit enforcement with
|
// Create the pool to test the limit enforcement with
|
||||||
db, _ := ethdb.NewMemDatabase()
|
db := ethdb.NewMemDatabase()
|
||||||
statedb, _ := state.New(common.Hash{}, state.NewDatabase(db))
|
statedb, _ := state.New(common.Hash{}, state.NewDatabase(db))
|
||||||
blockchain := &testBlockChain{statedb, big.NewInt(1000000), new(event.Feed)}
|
blockchain := &testBlockChain{statedb, big.NewInt(1000000), new(event.Feed)}
|
||||||
|
|
||||||
|
|
@ -722,7 +722,7 @@ func testTransactionQueueTimeLimiting(t *testing.T, nolocals bool) {
|
||||||
evictionInterval = time.Second
|
evictionInterval = time.Second
|
||||||
|
|
||||||
// Create the pool to test the non-expiration enforcement
|
// Create the pool to test the non-expiration enforcement
|
||||||
db, _ := ethdb.NewMemDatabase()
|
db := ethdb.NewMemDatabase()
|
||||||
statedb, _ := state.New(common.Hash{}, state.NewDatabase(db))
|
statedb, _ := state.New(common.Hash{}, state.NewDatabase(db))
|
||||||
blockchain := &testBlockChain{statedb, big.NewInt(1000000), new(event.Feed)}
|
blockchain := &testBlockChain{statedb, big.NewInt(1000000), new(event.Feed)}
|
||||||
|
|
||||||
|
|
@ -860,7 +860,7 @@ func testTransactionLimitingEquivalency(t *testing.T, origin uint64) {
|
||||||
// attacks.
|
// attacks.
|
||||||
func TestTransactionPendingGlobalLimiting(t *testing.T) {
|
func TestTransactionPendingGlobalLimiting(t *testing.T) {
|
||||||
// Create the pool to test the limit enforcement with
|
// Create the pool to test the limit enforcement with
|
||||||
db, _ := ethdb.NewMemDatabase()
|
db := ethdb.NewMemDatabase()
|
||||||
statedb, _ := state.New(common.Hash{}, state.NewDatabase(db))
|
statedb, _ := state.New(common.Hash{}, state.NewDatabase(db))
|
||||||
blockchain := &testBlockChain{statedb, big.NewInt(1000000), new(event.Feed)}
|
blockchain := &testBlockChain{statedb, big.NewInt(1000000), new(event.Feed)}
|
||||||
|
|
||||||
|
|
@ -905,7 +905,7 @@ func TestTransactionPendingGlobalLimiting(t *testing.T) {
|
||||||
// Tests that if transactions start being capped, transactions are also removed from 'all'
|
// Tests that if transactions start being capped, transactions are also removed from 'all'
|
||||||
func TestTransactionCapClearsFromAll(t *testing.T) {
|
func TestTransactionCapClearsFromAll(t *testing.T) {
|
||||||
// Create the pool to test the limit enforcement with
|
// Create the pool to test the limit enforcement with
|
||||||
db, _ := ethdb.NewMemDatabase()
|
db := ethdb.NewMemDatabase()
|
||||||
statedb, _ := state.New(common.Hash{}, state.NewDatabase(db))
|
statedb, _ := state.New(common.Hash{}, state.NewDatabase(db))
|
||||||
blockchain := &testBlockChain{statedb, big.NewInt(1000000), new(event.Feed)}
|
blockchain := &testBlockChain{statedb, big.NewInt(1000000), new(event.Feed)}
|
||||||
|
|
||||||
|
|
@ -938,7 +938,7 @@ func TestTransactionCapClearsFromAll(t *testing.T) {
|
||||||
// the transactions are still kept.
|
// the transactions are still kept.
|
||||||
func TestTransactionPendingMinimumAllowance(t *testing.T) {
|
func TestTransactionPendingMinimumAllowance(t *testing.T) {
|
||||||
// Create the pool to test the limit enforcement with
|
// Create the pool to test the limit enforcement with
|
||||||
db, _ := ethdb.NewMemDatabase()
|
db := ethdb.NewMemDatabase()
|
||||||
statedb, _ := state.New(common.Hash{}, state.NewDatabase(db))
|
statedb, _ := state.New(common.Hash{}, state.NewDatabase(db))
|
||||||
blockchain := &testBlockChain{statedb, big.NewInt(1000000), new(event.Feed)}
|
blockchain := &testBlockChain{statedb, big.NewInt(1000000), new(event.Feed)}
|
||||||
|
|
||||||
|
|
@ -985,7 +985,7 @@ func TestTransactionPendingMinimumAllowance(t *testing.T) {
|
||||||
// Note, local transactions are never allowed to be dropped.
|
// Note, local transactions are never allowed to be dropped.
|
||||||
func TestTransactionPoolRepricing(t *testing.T) {
|
func TestTransactionPoolRepricing(t *testing.T) {
|
||||||
// Create the pool to test the pricing enforcement with
|
// Create the pool to test the pricing enforcement with
|
||||||
db, _ := ethdb.NewMemDatabase()
|
db := ethdb.NewMemDatabase()
|
||||||
statedb, _ := state.New(common.Hash{}, state.NewDatabase(db))
|
statedb, _ := state.New(common.Hash{}, state.NewDatabase(db))
|
||||||
blockchain := &testBlockChain{statedb, big.NewInt(1000000), new(event.Feed)}
|
blockchain := &testBlockChain{statedb, big.NewInt(1000000), new(event.Feed)}
|
||||||
|
|
||||||
|
|
@ -1065,7 +1065,7 @@ func TestTransactionPoolRepricing(t *testing.T) {
|
||||||
// remove local transactions.
|
// remove local transactions.
|
||||||
func TestTransactionPoolRepricingKeepsLocals(t *testing.T) {
|
func TestTransactionPoolRepricingKeepsLocals(t *testing.T) {
|
||||||
// Create the pool to test the pricing enforcement with
|
// Create the pool to test the pricing enforcement with
|
||||||
db, _ := ethdb.NewMemDatabase()
|
db := ethdb.NewMemDatabase()
|
||||||
statedb, _ := state.New(common.Hash{}, state.NewDatabase(db))
|
statedb, _ := state.New(common.Hash{}, state.NewDatabase(db))
|
||||||
blockchain := &testBlockChain{statedb, big.NewInt(1000000), new(event.Feed)}
|
blockchain := &testBlockChain{statedb, big.NewInt(1000000), new(event.Feed)}
|
||||||
|
|
||||||
|
|
@ -1126,7 +1126,7 @@ func TestTransactionPoolRepricingKeepsLocals(t *testing.T) {
|
||||||
// Note, local transactions are never allowed to be dropped.
|
// Note, local transactions are never allowed to be dropped.
|
||||||
func TestTransactionPoolUnderpricing(t *testing.T) {
|
func TestTransactionPoolUnderpricing(t *testing.T) {
|
||||||
// Create the pool to test the pricing enforcement with
|
// Create the pool to test the pricing enforcement with
|
||||||
db, _ := ethdb.NewMemDatabase()
|
db := ethdb.NewMemDatabase()
|
||||||
statedb, _ := state.New(common.Hash{}, state.NewDatabase(db))
|
statedb, _ := state.New(common.Hash{}, state.NewDatabase(db))
|
||||||
blockchain := &testBlockChain{statedb, big.NewInt(1000000), new(event.Feed)}
|
blockchain := &testBlockChain{statedb, big.NewInt(1000000), new(event.Feed)}
|
||||||
|
|
||||||
|
|
@ -1212,7 +1212,7 @@ func TestTransactionPoolUnderpricing(t *testing.T) {
|
||||||
// price bump required.
|
// price bump required.
|
||||||
func TestTransactionReplacement(t *testing.T) {
|
func TestTransactionReplacement(t *testing.T) {
|
||||||
// Create the pool to test the pricing enforcement with
|
// Create the pool to test the pricing enforcement with
|
||||||
db, _ := ethdb.NewMemDatabase()
|
db := ethdb.NewMemDatabase()
|
||||||
statedb, _ := state.New(common.Hash{}, state.NewDatabase(db))
|
statedb, _ := state.New(common.Hash{}, state.NewDatabase(db))
|
||||||
blockchain := &testBlockChain{statedb, big.NewInt(1000000), new(event.Feed)}
|
blockchain := &testBlockChain{statedb, big.NewInt(1000000), new(event.Feed)}
|
||||||
|
|
||||||
|
|
@ -1290,7 +1290,7 @@ func testTransactionJournaling(t *testing.T, nolocals bool) {
|
||||||
os.Remove(journal)
|
os.Remove(journal)
|
||||||
|
|
||||||
// Create the original pool to inject transaction into the journal
|
// Create the original pool to inject transaction into the journal
|
||||||
db, _ := ethdb.NewMemDatabase()
|
db := ethdb.NewMemDatabase()
|
||||||
statedb, _ := state.New(common.Hash{}, state.NewDatabase(db))
|
statedb, _ := state.New(common.Hash{}, state.NewDatabase(db))
|
||||||
blockchain := &testBlockChain{statedb, big.NewInt(1000000), new(event.Feed)}
|
blockchain := &testBlockChain{statedb, big.NewInt(1000000), new(event.Feed)}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -101,7 +101,7 @@ func Execute(code, input []byte, cfg *Config) ([]byte, *state.StateDB, error) {
|
||||||
setDefaults(cfg)
|
setDefaults(cfg)
|
||||||
|
|
||||||
if cfg.State == nil {
|
if cfg.State == nil {
|
||||||
db, _ := ethdb.NewMemDatabase()
|
db := ethdb.NewMemDatabase()
|
||||||
cfg.State, _ = state.New(common.Hash{}, state.NewDatabase(db))
|
cfg.State, _ = state.New(common.Hash{}, state.NewDatabase(db))
|
||||||
}
|
}
|
||||||
var (
|
var (
|
||||||
|
|
@ -132,7 +132,7 @@ func Create(input []byte, cfg *Config) ([]byte, common.Address, uint64, error) {
|
||||||
setDefaults(cfg)
|
setDefaults(cfg)
|
||||||
|
|
||||||
if cfg.State == nil {
|
if cfg.State == nil {
|
||||||
db, _ := ethdb.NewMemDatabase()
|
db := ethdb.NewMemDatabase()
|
||||||
cfg.State, _ = state.New(common.Hash{}, state.NewDatabase(db))
|
cfg.State, _ = state.New(common.Hash{}, state.NewDatabase(db))
|
||||||
}
|
}
|
||||||
var (
|
var (
|
||||||
|
|
|
||||||
|
|
@ -94,7 +94,7 @@ func TestExecute(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestCall(t *testing.T) {
|
func TestCall(t *testing.T) {
|
||||||
db, _ := ethdb.NewMemDatabase()
|
db := ethdb.NewMemDatabase()
|
||||||
state, _ := state.New(common.Hash{}, state.NewDatabase(db))
|
state, _ := state.New(common.Hash{}, state.NewDatabase(db))
|
||||||
address := common.HexToAddress("0x0a")
|
address := common.HexToAddress("0x0a")
|
||||||
state.SetCode(address, []byte{
|
state.SetCode(address, []byte{
|
||||||
|
|
|
||||||
|
|
@ -75,12 +75,13 @@ type downloadTester struct {
|
||||||
|
|
||||||
// newTester creates a new downloader test mocker.
|
// newTester creates a new downloader test mocker.
|
||||||
func newTester() *downloadTester {
|
func newTester() *downloadTester {
|
||||||
testdb, _ := ethdb.NewMemDatabase()
|
testdb := ethdb.NewMemDatabase()
|
||||||
genesis := core.GenesisBlockForTesting(testdb, testAddress, big.NewInt(1000000000))
|
genesis := core.GenesisBlockForTesting(testdb, testAddress, big.NewInt(1000000000))
|
||||||
|
|
||||||
tester := &downloadTester{
|
tester := &downloadTester{
|
||||||
genesis: genesis,
|
genesis: genesis,
|
||||||
peerDb: testdb,
|
peerDb: testdb,
|
||||||
|
stateDb: ethdb.NewMemDatabase(),
|
||||||
ownHashes: []common.Hash{genesis.Hash()},
|
ownHashes: []common.Hash{genesis.Hash()},
|
||||||
ownHeaders: map[common.Hash]*types.Header{genesis.Hash(): genesis.Header()},
|
ownHeaders: map[common.Hash]*types.Header{genesis.Hash(): genesis.Header()},
|
||||||
ownBlocks: map[common.Hash]*types.Block{genesis.Hash(): genesis},
|
ownBlocks: map[common.Hash]*types.Block{genesis.Hash(): genesis},
|
||||||
|
|
@ -93,7 +94,6 @@ func newTester() *downloadTester {
|
||||||
peerChainTds: make(map[string]map[common.Hash]*big.Int),
|
peerChainTds: make(map[string]map[common.Hash]*big.Int),
|
||||||
peerMissingStates: make(map[string]map[common.Hash]bool),
|
peerMissingStates: make(map[string]map[common.Hash]bool),
|
||||||
}
|
}
|
||||||
tester.stateDb, _ = ethdb.NewMemDatabase()
|
|
||||||
tester.stateDb.Put(genesis.Root().Bytes(), []byte{0x00})
|
tester.stateDb.Put(genesis.Root().Bytes(), []byte{0x00})
|
||||||
|
|
||||||
tester.downloader = New(FullSync, tester.stateDb, new(event.TypeMux), tester, nil, tester.dropPeer)
|
tester.downloader = New(FullSync, tester.stateDb, new(event.TypeMux), tester, nil, tester.dropPeer)
|
||||||
|
|
|
||||||
|
|
@ -18,14 +18,12 @@ package downloader
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"hash"
|
|
||||||
"sync"
|
"sync"
|
||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
"github.com/ethereum/go-ethereum/core/state"
|
"github.com/ethereum/go-ethereum/core/state"
|
||||||
"github.com/ethereum/go-ethereum/crypto/sha3"
|
|
||||||
"github.com/ethereum/go-ethereum/ethdb"
|
"github.com/ethereum/go-ethereum/ethdb"
|
||||||
"github.com/ethereum/go-ethereum/log"
|
"github.com/ethereum/go-ethereum/log"
|
||||||
"github.com/ethereum/go-ethereum/trie"
|
"github.com/ethereum/go-ethereum/trie"
|
||||||
|
|
@ -211,9 +209,8 @@ func (d *Downloader) runStateSync(s *stateSync) *stateSync {
|
||||||
type stateSync struct {
|
type stateSync struct {
|
||||||
d *Downloader // Downloader instance to access and manage current peerset
|
d *Downloader // Downloader instance to access and manage current peerset
|
||||||
|
|
||||||
sched *trie.TrieSync // State trie sync scheduler defining the tasks
|
sched *trie.TrieSync // State trie sync scheduler defining the tasks
|
||||||
keccak hash.Hash // Keccak256 hasher to verify deliveries with
|
tasks map[common.Hash]*stateTask // Set of tasks currently queued for retrieval
|
||||||
tasks map[common.Hash]*stateTask // Set of tasks currently queued for retrieval
|
|
||||||
|
|
||||||
numUncommitted int
|
numUncommitted int
|
||||||
bytesUncommitted int
|
bytesUncommitted int
|
||||||
|
|
@ -237,7 +234,6 @@ func newStateSync(d *Downloader, root common.Hash) *stateSync {
|
||||||
return &stateSync{
|
return &stateSync{
|
||||||
d: d,
|
d: d,
|
||||||
sched: state.NewStateSync(root, d.stateDB),
|
sched: state.NewStateSync(root, d.stateDB),
|
||||||
keccak: sha3.NewKeccak256(),
|
|
||||||
tasks: make(map[common.Hash]*stateTask),
|
tasks: make(map[common.Hash]*stateTask),
|
||||||
deliver: make(chan *stateReq),
|
deliver: make(chan *stateReq),
|
||||||
cancel: make(chan struct{}),
|
cancel: make(chan struct{}),
|
||||||
|
|
@ -401,7 +397,7 @@ func (s *stateSync) process(req *stateReq) (bool, error) {
|
||||||
progress, stale := false, len(req.response) > 0
|
progress, stale := false, len(req.response) > 0
|
||||||
|
|
||||||
for _, blob := range req.response {
|
for _, blob := range req.response {
|
||||||
prog, hash, err := s.processNodeData(blob)
|
prog, hash, err := s.sched.Process(&trie.SyncResult{Data: blob})
|
||||||
switch err {
|
switch err {
|
||||||
case nil:
|
case nil:
|
||||||
s.numUncommitted++
|
s.numUncommitted++
|
||||||
|
|
@ -446,18 +442,6 @@ func (s *stateSync) process(req *stateReq) (bool, error) {
|
||||||
return stale, nil
|
return stale, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// processNodeData tries to inject a trie node data blob delivered from a remote
|
|
||||||
// peer into the state trie, returning whether anything useful was written or any
|
|
||||||
// error occurred.
|
|
||||||
func (s *stateSync) processNodeData(blob []byte) (bool, common.Hash, error) {
|
|
||||||
res := trie.SyncResult{Data: blob}
|
|
||||||
s.keccak.Reset()
|
|
||||||
s.keccak.Write(blob)
|
|
||||||
s.keccak.Sum(res.Hash[:0])
|
|
||||||
committed, _, err := s.sched.Process([]trie.SyncResult{res})
|
|
||||||
return committed, res.Hash, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// updateStats bumps the various state sync progress counters and displays a log
|
// updateStats bumps the various state sync progress counters and displays a log
|
||||||
// message for the user to see.
|
// message for the user to see.
|
||||||
func (s *stateSync) updateStats(written, duplicate, unexpected int, duration time.Duration) {
|
func (s *stateSync) updateStats(written, duplicate, unexpected int, duration time.Duration) {
|
||||||
|
|
|
||||||
|
|
@ -368,7 +368,7 @@ func testGetNodeData(t *testing.T, protocol int) {
|
||||||
t.Errorf("data hash mismatch: have %x, want %x", hash, want)
|
t.Errorf("data hash mismatch: have %x, want %x", hash, want)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
statedb, _ := ethdb.NewMemDatabase()
|
statedb := ethdb.NewMemDatabase()
|
||||||
for i := 0; i < len(data); i++ {
|
for i := 0; i < len(data); i++ {
|
||||||
statedb.Put(hashes[i].Bytes(), data[i])
|
statedb.Put(hashes[i].Bytes(), data[i])
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -53,8 +53,7 @@ func TestLDB_PutGet(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestMemoryDB_PutGet(t *testing.T) {
|
func TestMemoryDB_PutGet(t *testing.T) {
|
||||||
db, _ := ethdb.NewMemDatabase()
|
testPutGet(ethdb.NewMemDatabase(), t)
|
||||||
testPutGet(db, t)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func testPutGet(db ethdb.Database, t *testing.T) {
|
func testPutGet(db ethdb.Database, t *testing.T) {
|
||||||
|
|
@ -131,8 +130,7 @@ func TestLDB_ParallelPutGet(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestMemoryDB_ParallelPutGet(t *testing.T) {
|
func TestMemoryDB_ParallelPutGet(t *testing.T) {
|
||||||
db, _ := ethdb.NewMemDatabase()
|
testParallelPutGet(ethdb.NewMemDatabase(), t)
|
||||||
testParallelPutGet(db, t)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func testParallelPutGet(db ethdb.Database, t *testing.T) {
|
func testParallelPutGet(db ethdb.Database, t *testing.T) {
|
||||||
|
|
|
||||||
|
|
@ -23,18 +23,15 @@ import (
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
)
|
)
|
||||||
|
|
||||||
/*
|
|
||||||
* This is a test memory database. Do not use for any production it does not get persisted
|
|
||||||
*/
|
|
||||||
type MemDatabase struct {
|
type MemDatabase struct {
|
||||||
db map[string][]byte
|
db map[string][]byte
|
||||||
lock sync.RWMutex
|
lock sync.RWMutex
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewMemDatabase() (*MemDatabase, error) {
|
func NewMemDatabase() *MemDatabase {
|
||||||
return &MemDatabase{
|
return &MemDatabase{
|
||||||
db: make(map[string][]byte),
|
db: make(map[string][]byte),
|
||||||
}, nil
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (db *MemDatabase) Put(key []byte, value []byte) error {
|
func (db *MemDatabase) Put(key []byte, value []byte) error {
|
||||||
|
|
|
||||||
|
|
@ -42,7 +42,7 @@ func expectResponse(r p2p.MsgReader, msgcode, reqID, bv uint64, data interface{}
|
||||||
func TestGetBlockHeadersLes1(t *testing.T) { testGetBlockHeaders(t, 1) }
|
func TestGetBlockHeadersLes1(t *testing.T) { testGetBlockHeaders(t, 1) }
|
||||||
|
|
||||||
func testGetBlockHeaders(t *testing.T, protocol int) {
|
func testGetBlockHeaders(t *testing.T, protocol int) {
|
||||||
db, _ := ethdb.NewMemDatabase()
|
db := ethdb.NewMemDatabase()
|
||||||
pm := newTestProtocolManagerMust(t, false, downloader.MaxHashFetch+15, nil, nil, nil, db)
|
pm := newTestProtocolManagerMust(t, false, downloader.MaxHashFetch+15, nil, nil, nil, db)
|
||||||
bc := pm.blockchain.(*core.BlockChain)
|
bc := pm.blockchain.(*core.BlockChain)
|
||||||
peer, _ := newTestPeer(t, "peer", protocol, pm, true)
|
peer, _ := newTestPeer(t, "peer", protocol, pm, true)
|
||||||
|
|
@ -171,7 +171,7 @@ func testGetBlockHeaders(t *testing.T, protocol int) {
|
||||||
func TestGetBlockBodiesLes1(t *testing.T) { testGetBlockBodies(t, 1) }
|
func TestGetBlockBodiesLes1(t *testing.T) { testGetBlockBodies(t, 1) }
|
||||||
|
|
||||||
func testGetBlockBodies(t *testing.T, protocol int) {
|
func testGetBlockBodies(t *testing.T, protocol int) {
|
||||||
db, _ := ethdb.NewMemDatabase()
|
db := ethdb.NewMemDatabase()
|
||||||
pm := newTestProtocolManagerMust(t, false, downloader.MaxBlockFetch+15, nil, nil, nil, db)
|
pm := newTestProtocolManagerMust(t, false, downloader.MaxBlockFetch+15, nil, nil, nil, db)
|
||||||
bc := pm.blockchain.(*core.BlockChain)
|
bc := pm.blockchain.(*core.BlockChain)
|
||||||
peer, _ := newTestPeer(t, "peer", protocol, pm, true)
|
peer, _ := newTestPeer(t, "peer", protocol, pm, true)
|
||||||
|
|
@ -248,7 +248,7 @@ func TestGetCodeLes1(t *testing.T) { testGetCode(t, 1) }
|
||||||
|
|
||||||
func testGetCode(t *testing.T, protocol int) {
|
func testGetCode(t *testing.T, protocol int) {
|
||||||
// Assemble the test environment
|
// Assemble the test environment
|
||||||
db, _ := ethdb.NewMemDatabase()
|
db := ethdb.NewMemDatabase()
|
||||||
pm := newTestProtocolManagerMust(t, false, 4, testChainGen, nil, nil, db)
|
pm := newTestProtocolManagerMust(t, false, 4, testChainGen, nil, nil, db)
|
||||||
bc := pm.blockchain.(*core.BlockChain)
|
bc := pm.blockchain.(*core.BlockChain)
|
||||||
peer, _ := newTestPeer(t, "peer", protocol, pm, true)
|
peer, _ := newTestPeer(t, "peer", protocol, pm, true)
|
||||||
|
|
@ -281,7 +281,7 @@ func TestGetReceiptLes1(t *testing.T) { testGetReceipt(t, 1) }
|
||||||
|
|
||||||
func testGetReceipt(t *testing.T, protocol int) {
|
func testGetReceipt(t *testing.T, protocol int) {
|
||||||
// Assemble the test environment
|
// Assemble the test environment
|
||||||
db, _ := ethdb.NewMemDatabase()
|
db := ethdb.NewMemDatabase()
|
||||||
pm := newTestProtocolManagerMust(t, false, 4, testChainGen, nil, nil, db)
|
pm := newTestProtocolManagerMust(t, false, 4, testChainGen, nil, nil, db)
|
||||||
bc := pm.blockchain.(*core.BlockChain)
|
bc := pm.blockchain.(*core.BlockChain)
|
||||||
peer, _ := newTestPeer(t, "peer", protocol, pm, true)
|
peer, _ := newTestPeer(t, "peer", protocol, pm, true)
|
||||||
|
|
@ -308,7 +308,7 @@ func TestGetProofsLes1(t *testing.T) { testGetProofs(t, 1) }
|
||||||
|
|
||||||
func testGetProofs(t *testing.T, protocol int) {
|
func testGetProofs(t *testing.T, protocol int) {
|
||||||
// Assemble the test environment
|
// Assemble the test environment
|
||||||
db, _ := ethdb.NewMemDatabase()
|
db := ethdb.NewMemDatabase()
|
||||||
pm := newTestProtocolManagerMust(t, false, 4, testChainGen, nil, nil, db)
|
pm := newTestProtocolManagerMust(t, false, 4, testChainGen, nil, nil, db)
|
||||||
bc := pm.blockchain.(*core.BlockChain)
|
bc := pm.blockchain.(*core.BlockChain)
|
||||||
peer, _ := newTestPeer(t, "peer", protocol, pm, true)
|
peer, _ := newTestPeer(t, "peer", protocol, pm, true)
|
||||||
|
|
|
||||||
|
|
@ -152,8 +152,8 @@ func testOdr(t *testing.T, protocol int, expFail uint64, fn odrTestFn) {
|
||||||
peers := newPeerSet()
|
peers := newPeerSet()
|
||||||
dist := newRequestDistributor(peers, make(chan struct{}))
|
dist := newRequestDistributor(peers, make(chan struct{}))
|
||||||
rm := newRetrieveManager(peers, dist, nil)
|
rm := newRetrieveManager(peers, dist, nil)
|
||||||
db, _ := ethdb.NewMemDatabase()
|
db := ethdb.NewMemDatabase()
|
||||||
ldb, _ := ethdb.NewMemDatabase()
|
ldb := ethdb.NewMemDatabase()
|
||||||
odr := NewLesOdr(ldb, rm)
|
odr := NewLesOdr(ldb, rm)
|
||||||
pm := newTestProtocolManagerMust(t, false, 4, testChainGen, nil, nil, db)
|
pm := newTestProtocolManagerMust(t, false, 4, testChainGen, nil, nil, db)
|
||||||
lpm := newTestProtocolManagerMust(t, true, 0, nil, peers, odr, ldb)
|
lpm := newTestProtocolManagerMust(t, true, 0, nil, peers, odr, ldb)
|
||||||
|
|
|
||||||
|
|
@ -71,8 +71,8 @@ func testAccess(t *testing.T, protocol int, fn accessTestFn) {
|
||||||
peers := newPeerSet()
|
peers := newPeerSet()
|
||||||
dist := newRequestDistributor(peers, make(chan struct{}))
|
dist := newRequestDistributor(peers, make(chan struct{}))
|
||||||
rm := newRetrieveManager(peers, dist, nil)
|
rm := newRetrieveManager(peers, dist, nil)
|
||||||
db, _ := ethdb.NewMemDatabase()
|
db := ethdb.NewMemDatabase()
|
||||||
ldb, _ := ethdb.NewMemDatabase()
|
ldb := ethdb.NewMemDatabase()
|
||||||
odr := NewLesOdr(ldb, rm)
|
odr := NewLesOdr(ldb, rm)
|
||||||
|
|
||||||
pm := newTestProtocolManagerMust(t, false, 4, testChainGen, nil, nil, db)
|
pm := newTestProtocolManagerMust(t, false, 4, testChainGen, nil, nil, db)
|
||||||
|
|
|
||||||
|
|
@ -51,7 +51,7 @@ func makeHeaderChain(parent *types.Header, n int, db ethdb.Database, seed int) [
|
||||||
// chain. Depending on the full flag, if creates either a full block chain or a
|
// chain. Depending on the full flag, if creates either a full block chain or a
|
||||||
// header only chain.
|
// header only chain.
|
||||||
func newCanonical(n int) (ethdb.Database, *LightChain, error) {
|
func newCanonical(n int) (ethdb.Database, *LightChain, error) {
|
||||||
db, _ := ethdb.NewMemDatabase()
|
db := ethdb.NewMemDatabase()
|
||||||
gspec := core.Genesis{Config: params.TestChainConfig}
|
gspec := core.Genesis{Config: params.TestChainConfig}
|
||||||
genesis := gspec.MustCommit(db)
|
genesis := gspec.MustCommit(db)
|
||||||
blockchain, _ := NewLightChain(&dummyOdr{db: db}, gspec.Config, ethash.NewFaker())
|
blockchain, _ := NewLightChain(&dummyOdr{db: db}, gspec.Config, ethash.NewFaker())
|
||||||
|
|
@ -68,7 +68,7 @@ func newCanonical(n int) (ethdb.Database, *LightChain, error) {
|
||||||
|
|
||||||
// newTestLightChain creates a LightChain that doesn't validate anything.
|
// newTestLightChain creates a LightChain that doesn't validate anything.
|
||||||
func newTestLightChain() *LightChain {
|
func newTestLightChain() *LightChain {
|
||||||
db, _ := ethdb.NewMemDatabase()
|
db := ethdb.NewMemDatabase()
|
||||||
gspec := &core.Genesis{
|
gspec := &core.Genesis{
|
||||||
Difficulty: big.NewInt(1),
|
Difficulty: big.NewInt(1),
|
||||||
Config: params.TestChainConfig,
|
Config: params.TestChainConfig,
|
||||||
|
|
|
||||||
|
|
@ -637,7 +637,7 @@ func (n *Node) EventMux() *event.TypeMux {
|
||||||
// ephemeral, a memory database is returned.
|
// ephemeral, a memory database is returned.
|
||||||
func (n *Node) OpenDatabase(name string, cache, handles int) (ethdb.Database, error) {
|
func (n *Node) OpenDatabase(name string, cache, handles int) (ethdb.Database, error) {
|
||||||
if n.config.DataDir == "" {
|
if n.config.DataDir == "" {
|
||||||
return ethdb.NewMemDatabase()
|
return ethdb.NewMemDatabase(), nil
|
||||||
}
|
}
|
||||||
return ethdb.NewLDBDatabase(n.config.resolvePath(name), cache, handles)
|
return ethdb.NewLDBDatabase(n.config.resolvePath(name), cache, handles)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -41,7 +41,7 @@ type ServiceContext struct {
|
||||||
// node is an ephemeral one, a memory database is returned.
|
// node is an ephemeral one, a memory database is returned.
|
||||||
func (ctx *ServiceContext) OpenDatabase(name string, cache int, handles int) (ethdb.Database, error) {
|
func (ctx *ServiceContext) OpenDatabase(name string, cache int, handles int) (ethdb.Database, error) {
|
||||||
if ctx.config.DataDir == "" {
|
if ctx.config.DataDir == "" {
|
||||||
return ethdb.NewMemDatabase()
|
return ethdb.NewMemDatabase(), nil
|
||||||
}
|
}
|
||||||
db, err := ethdb.NewLDBDatabase(ctx.config.resolvePath(name), cache, handles)
|
db, err := ethdb.NewLDBDatabase(ctx.config.resolvePath(name), cache, handles)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
||||||
|
|
@ -98,7 +98,7 @@ func (t *BlockTest) Run() error {
|
||||||
}
|
}
|
||||||
|
|
||||||
// import pre accounts & construct test genesis block & state root
|
// import pre accounts & construct test genesis block & state root
|
||||||
db, _ := ethdb.NewMemDatabase()
|
db := ethdb.NewMemDatabase()
|
||||||
gblock, err := t.genesis(config).Commit(db)
|
gblock, err := t.genesis(config).Commit(db)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
|
|
||||||
|
|
@ -126,7 +126,7 @@ func (t *StateTest) Run(subtest StateSubtest, vmconfig vm.Config) (*state.StateD
|
||||||
return nil, UnsupportedForkError{subtest.Fork}
|
return nil, UnsupportedForkError{subtest.Fork}
|
||||||
}
|
}
|
||||||
block, _ := t.genesis(config).ToBlock()
|
block, _ := t.genesis(config).ToBlock()
|
||||||
db, _ := ethdb.NewMemDatabase()
|
db := ethdb.NewMemDatabase()
|
||||||
statedb := makePreState(db, t.json.Pre)
|
statedb := makePreState(db, t.json.Pre)
|
||||||
|
|
||||||
post := t.json.Post[subtest.Fork][subtest.Index]
|
post := t.json.Post[subtest.Fork][subtest.Index]
|
||||||
|
|
|
||||||
|
|
@ -79,7 +79,7 @@ type vmExecMarshaling struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *VMTest) Run(vmconfig vm.Config) error {
|
func (t *VMTest) Run(vmconfig vm.Config) error {
|
||||||
db, _ := ethdb.NewMemDatabase()
|
db := ethdb.NewMemDatabase()
|
||||||
statedb := makePreState(db, t.json.Pre)
|
statedb := makePreState(db, t.json.Pre)
|
||||||
ret, gasRemaining, err := t.exec(statedb, vmconfig)
|
ret, gasRemaining, err := t.exec(statedb, vmconfig)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -279,7 +279,7 @@ func TestIteratorNoDups(t *testing.T) {
|
||||||
|
|
||||||
// This test checks that nodeIterator.Next can be retried after inserting missing trie nodes.
|
// This test checks that nodeIterator.Next can be retried after inserting missing trie nodes.
|
||||||
func TestIteratorContinueAfterError(t *testing.T) {
|
func TestIteratorContinueAfterError(t *testing.T) {
|
||||||
db, _ := ethdb.NewMemDatabase()
|
db := ethdb.NewMemDatabase()
|
||||||
tr, _ := New(common.Hash{}, db)
|
tr, _ := New(common.Hash{}, db)
|
||||||
for _, val := range testdata1 {
|
for _, val := range testdata1 {
|
||||||
tr.Update([]byte(val.k), []byte(val.v))
|
tr.Update([]byte(val.k), []byte(val.v))
|
||||||
|
|
@ -330,7 +330,7 @@ func TestIteratorContinueAfterError(t *testing.T) {
|
||||||
// should retry seeking before returning true for the first time.
|
// should retry seeking before returning true for the first time.
|
||||||
func TestIteratorContinueAfterSeekError(t *testing.T) {
|
func TestIteratorContinueAfterSeekError(t *testing.T) {
|
||||||
// Commit test trie to db, then remove the node containing "bars".
|
// Commit test trie to db, then remove the node containing "bars".
|
||||||
db, _ := ethdb.NewMemDatabase()
|
db := ethdb.NewMemDatabase()
|
||||||
ctr, _ := New(common.Hash{}, db)
|
ctr, _ := New(common.Hash{}, db)
|
||||||
for _, val := range testdata1 {
|
for _, val := range testdata1 {
|
||||||
ctr.Update([]byte(val.k), []byte(val.v))
|
ctr.Update([]byte(val.k), []byte(val.v))
|
||||||
|
|
|
||||||
|
|
@ -28,7 +28,7 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
func newEmptySecure() *SecureTrie {
|
func newEmptySecure() *SecureTrie {
|
||||||
db, _ := ethdb.NewMemDatabase()
|
db := ethdb.NewMemDatabase()
|
||||||
trie, _ := NewSecure(common.Hash{}, db, 0)
|
trie, _ := NewSecure(common.Hash{}, db, 0)
|
||||||
return trie
|
return trie
|
||||||
}
|
}
|
||||||
|
|
@ -36,7 +36,7 @@ func newEmptySecure() *SecureTrie {
|
||||||
// makeTestSecureTrie creates a large enough secure trie for testing.
|
// makeTestSecureTrie creates a large enough secure trie for testing.
|
||||||
func makeTestSecureTrie() (ethdb.Database, *SecureTrie, map[string][]byte) {
|
func makeTestSecureTrie() (ethdb.Database, *SecureTrie, map[string][]byte) {
|
||||||
// Create an empty trie
|
// Create an empty trie
|
||||||
db, _ := ethdb.NewMemDatabase()
|
db := ethdb.NewMemDatabase()
|
||||||
trie, _ := NewSecure(common.Hash{}, db, 0)
|
trie, _ := NewSecure(common.Hash{}, db, 0)
|
||||||
|
|
||||||
// Fill it with some arbitrary data
|
// Fill it with some arbitrary data
|
||||||
|
|
|
||||||
245
trie/sync.go
245
trie/sync.go
|
|
@ -17,10 +17,14 @@
|
||||||
package trie
|
package trie
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"hash"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
|
"github.com/ethereum/go-ethereum/crypto/sha3"
|
||||||
|
"github.com/ethereum/go-ethereum/ethdb"
|
||||||
"gopkg.in/karalabe/cookiejar.v2/collections/prque"
|
"gopkg.in/karalabe/cookiejar.v2/collections/prque"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -50,10 +54,10 @@ type request struct {
|
||||||
// be a batch of trie leaves (with associated merkle proofs) if returning batched
|
// be a batch of trie leaves (with associated merkle proofs) if returning batched
|
||||||
// results.
|
// results.
|
||||||
type SyncResult struct {
|
type SyncResult struct {
|
||||||
Hash common.Hash // Hash of the originally unknown trie node
|
Data []byte // Data content of the retrieved node, in node-sync mode
|
||||||
Data []byte // Data content of the retrieved node, in node-sync mode
|
Keys [][]byte // Trie keys rooted under the specified hash, in leaf-sync mode
|
||||||
Leaves [][]byte // Trie leaves rooted under the specified hash, in leaf-sync mode
|
Values [][]byte // Trie values rooted under the specified hash, in leaf-sync mode
|
||||||
Proofs [][]byte // Proofs to validate the leaves, in leaf-sync mode, if leaves are partial
|
Proof [][]byte // Proofs to validate the leaves, in leaf-sync mode, if leaves are partial
|
||||||
}
|
}
|
||||||
|
|
||||||
// syncMemBatch is an in-memory buffer of successfully downloaded but not yet
|
// syncMemBatch is an in-memory buffer of successfully downloaded but not yet
|
||||||
|
|
@ -84,6 +88,7 @@ type TrieSync struct {
|
||||||
membatch *syncMemBatch // Memory buffer to avoid frequest database writes
|
membatch *syncMemBatch // Memory buffer to avoid frequest database writes
|
||||||
requests map[common.Hash]*request // Pending requests pertaining to a key hash
|
requests map[common.Hash]*request // Pending requests pertaining to a key hash
|
||||||
queue *prque.Prque // Priority queue with the pending requests
|
queue *prque.Prque // Priority queue with the pending requests
|
||||||
|
keccak hash.Hash // Keccak256 hasher to verify deliveries with
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewTrieSync creates a new trie data download scheduler.
|
// NewTrieSync creates a new trie data download scheduler.
|
||||||
|
|
@ -93,6 +98,7 @@ func NewTrieSync(root common.Hash, database DatabaseReader, callback TrieSyncLea
|
||||||
membatch: newSyncMemBatch(),
|
membatch: newSyncMemBatch(),
|
||||||
requests: make(map[common.Hash]*request),
|
requests: make(map[common.Hash]*request),
|
||||||
queue: prque.New(),
|
queue: prque.New(),
|
||||||
|
keccak: sha3.NewKeccak256(),
|
||||||
}
|
}
|
||||||
ts.AddSubTrie(root, 0, common.Hash{}, callback)
|
ts.AddSubTrie(root, 0, common.Hash{}, callback)
|
||||||
return ts
|
return ts
|
||||||
|
|
@ -167,7 +173,10 @@ func (s *TrieSync) AddRawEntry(hash common.Hash, depth int, parent common.Hash)
|
||||||
func (s *TrieSync) Missing(max int) []common.Hash {
|
func (s *TrieSync) Missing(max int) []common.Hash {
|
||||||
requests := []common.Hash{}
|
requests := []common.Hash{}
|
||||||
for !s.queue.Empty() && (max == 0 || len(requests) < max) {
|
for !s.queue.Empty() && (max == 0 || len(requests) < max) {
|
||||||
requests = append(requests, s.queue.PopItem().(common.Hash))
|
hash := s.queue.PopItem().(common.Hash)
|
||||||
|
if s.requests[hash] != nil {
|
||||||
|
requests = append(requests, hash)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return requests
|
return requests
|
||||||
}
|
}
|
||||||
|
|
@ -175,48 +184,187 @@ func (s *TrieSync) Missing(max int) []common.Hash {
|
||||||
// Process injects a batch of retrieved trie nodes data, returning if something
|
// Process injects a batch of retrieved trie nodes data, returning if something
|
||||||
// was committed to the database and also the index of an entry if processing of
|
// was committed to the database and also the index of an entry if processing of
|
||||||
// it failed.
|
// it failed.
|
||||||
func (s *TrieSync) Process(results []SyncResult) (bool, int, error) {
|
func (s *TrieSync) Process(result *SyncResult) (bool, common.Hash, error) {
|
||||||
committed := false
|
// If it's a plain or full sub-trie delivery, inject and return
|
||||||
|
if len(result.Keys) == 0 && len(result.Proof) == 0 {
|
||||||
|
return s.processNode(result.Data)
|
||||||
|
}
|
||||||
|
if len(result.Proof) == 0 {
|
||||||
|
return s.processLeaves(result.Keys, result.Values)
|
||||||
|
}
|
||||||
|
// For partial depliveries, expand the keys and iteratively fulfil the sub-trie
|
||||||
|
for i, key := range result.Keys {
|
||||||
|
result.Keys[i] = keybytesToHex(key)
|
||||||
|
}
|
||||||
|
return s.processPartialLeaves(result.Keys, result.Values, result.Proof)
|
||||||
|
}
|
||||||
|
|
||||||
for i, item := range results {
|
// processNode verifies and processes a trie node, returning if anything was
|
||||||
// If the item was not requested, bail out
|
// committed and the hash of the node injected.
|
||||||
request := s.requests[item.Hash]
|
func (s *TrieSync) processNode(blob []byte) (bool, common.Hash, error) {
|
||||||
if request == nil {
|
// Derive the hash of the result based on its content
|
||||||
return committed, i, ErrNotRequested
|
var hash common.Hash
|
||||||
}
|
|
||||||
if request.data != nil {
|
|
||||||
return committed, i, ErrAlreadyProcessed
|
|
||||||
}
|
|
||||||
// If the item is a raw entry request, commit directly
|
|
||||||
if request.raw {
|
|
||||||
request.data = item.Data
|
|
||||||
s.commit(request)
|
|
||||||
committed = true
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
// Decode the node data content and update the request
|
|
||||||
node, err := decodeNode(item.Hash[:], item.Data, 0)
|
|
||||||
if err != nil {
|
|
||||||
return committed, i, err
|
|
||||||
}
|
|
||||||
request.data = item.Data
|
|
||||||
|
|
||||||
// Create and schedule a request for all the children nodes
|
s.keccak.Reset()
|
||||||
requests, err := s.children(request, node)
|
s.keccak.Write(blob)
|
||||||
if err != nil {
|
s.keccak.Sum(hash[:0])
|
||||||
return committed, i, err
|
|
||||||
}
|
// If the item was not requested, bail out
|
||||||
if len(requests) == 0 && request.deps == 0 {
|
request := s.requests[hash]
|
||||||
s.commit(request)
|
if request == nil {
|
||||||
committed = true
|
return false, hash, ErrNotRequested
|
||||||
continue
|
}
|
||||||
}
|
if request.data != nil {
|
||||||
request.deps += len(requests)
|
return false, hash, nil // TODO(karalabe): Why not ErrAlreadyProcessed
|
||||||
for _, child := range requests {
|
}
|
||||||
s.schedule(child)
|
// If the item is a raw entry request, commit directly
|
||||||
|
if request.raw {
|
||||||
|
request.data = blob
|
||||||
|
s.commit(request)
|
||||||
|
return true, hash, nil
|
||||||
|
}
|
||||||
|
// Decode and inject into the trie
|
||||||
|
node, err := decodeNode(hash[:], blob, 0)
|
||||||
|
if err != nil {
|
||||||
|
return false, hash, err
|
||||||
|
}
|
||||||
|
request.data = blob
|
||||||
|
|
||||||
|
// Create and schedule a request for all the children nodes
|
||||||
|
requests, err := s.children(request, node)
|
||||||
|
if err != nil {
|
||||||
|
return false, hash, err
|
||||||
|
}
|
||||||
|
if len(requests) == 0 && request.deps == 0 {
|
||||||
|
s.commit(request)
|
||||||
|
return true, hash, nil
|
||||||
|
}
|
||||||
|
request.deps += len(requests)
|
||||||
|
for _, child := range requests {
|
||||||
|
s.schedule(child)
|
||||||
|
}
|
||||||
|
return false, hash, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// processLeaves reconstructs a sub-trie from the given key-value pairs, returning
|
||||||
|
// the root of the sub-trie or an error on failure.
|
||||||
|
func (s *TrieSync) processLeaves(keys [][]byte, values [][]byte) (bool, common.Hash, error) {
|
||||||
|
// Inject all the leaves into a fresh trie and derive it's root hash
|
||||||
|
db := ethdb.NewMemDatabase()
|
||||||
|
trie, err := New(common.Hash{}, db)
|
||||||
|
if err != nil {
|
||||||
|
return false, common.Hash{}, err
|
||||||
|
}
|
||||||
|
for j := 0; j < len(keys); j++ {
|
||||||
|
trie.Update(keys[j], values[j])
|
||||||
|
}
|
||||||
|
root, err := trie.Commit()
|
||||||
|
if err != nil {
|
||||||
|
return false, common.Hash{}, err
|
||||||
|
}
|
||||||
|
// If the item was not requested, bail out
|
||||||
|
request := s.requests[root]
|
||||||
|
if request == nil {
|
||||||
|
return false, root, ErrNotRequested
|
||||||
|
}
|
||||||
|
if request.data != nil {
|
||||||
|
return false, root, ErrAlreadyProcessed
|
||||||
|
}
|
||||||
|
// Inject all key-values as is and complete the root
|
||||||
|
for _, key := range db.Keys() {
|
||||||
|
value, _ := db.Get(key)
|
||||||
|
if hash := common.BytesToHash(key); hash != root {
|
||||||
|
s.commitEntry(hash, value)
|
||||||
|
} else {
|
||||||
|
request.data = value
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return committed, 0, nil
|
s.commit(request)
|
||||||
|
|
||||||
|
return true, root, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// processPartialLeaves reconstructs a sub-trie from the Merkle proof and the
|
||||||
|
// available key-value pairs, commiting the available parts and scheduling the
|
||||||
|
// missing items for future retrival.
|
||||||
|
func (s *TrieSync) processPartialLeaves(keys [][]byte, values [][]byte, proof [][]byte) (bool, common.Hash, error) {
|
||||||
|
// Derive the hash of the topmost proof
|
||||||
|
var root common.Hash
|
||||||
|
|
||||||
|
s.keccak.Reset()
|
||||||
|
s.keccak.Write(proof[0])
|
||||||
|
s.keccak.Sum(root[:0])
|
||||||
|
|
||||||
|
// If the item was not requested, bail out
|
||||||
|
request := s.requests[root]
|
||||||
|
if request == nil {
|
||||||
|
return false, root, ErrNotRequested
|
||||||
|
}
|
||||||
|
if request.data != nil {
|
||||||
|
return false, root, ErrAlreadyProcessed
|
||||||
|
}
|
||||||
|
// Decode the root node and schedule missing children
|
||||||
|
node, err := decodeNode(root[:], proof[0], 0)
|
||||||
|
if err != nil {
|
||||||
|
return false, root, err
|
||||||
|
}
|
||||||
|
request.data = proof[0]
|
||||||
|
|
||||||
|
requests, err := s.children(request, node)
|
||||||
|
if err != nil {
|
||||||
|
return false, root, err
|
||||||
|
}
|
||||||
|
if len(requests) == 0 && request.deps == 0 {
|
||||||
|
s.commit(request)
|
||||||
|
return true, root, nil
|
||||||
|
}
|
||||||
|
request.deps += len(requests)
|
||||||
|
for _, child := range requests {
|
||||||
|
s.schedule(child)
|
||||||
|
}
|
||||||
|
// Fulfill any children satisfied by the key-value pairs
|
||||||
|
switch node := (node).(type) {
|
||||||
|
case *shortNode:
|
||||||
|
// All keys must have the short node's path as a prefix
|
||||||
|
for i, key := range keys {
|
||||||
|
if !bytes.HasPrefix(key, node.Key) {
|
||||||
|
return false, root, fmt.Errorf("key mismatch at proof %x", proof[0])
|
||||||
|
}
|
||||||
|
keys[i] = key[len(node.Key):]
|
||||||
|
}
|
||||||
|
// Recurse into the subtrie of the short node
|
||||||
|
commit, _, err := s.processPartialLeaves(keys, values, proof[1:])
|
||||||
|
return commit, root, err
|
||||||
|
|
||||||
|
case *fullNode:
|
||||||
|
// Split up the keyspace between the full node's children
|
||||||
|
for i := 0; i < 17; i++ {
|
||||||
|
if node.Children[i] != nil {
|
||||||
|
// Split off the keyspace for this child
|
||||||
|
var split int
|
||||||
|
for split < len(keys) && keys[split][0] == byte(i) {
|
||||||
|
keys[split] = keys[split][1:]
|
||||||
|
split++
|
||||||
|
}
|
||||||
|
// Only process this child if it's not fully embedded
|
||||||
|
if _, ok := node.Children[i].(hashNode); !ok {
|
||||||
|
// If we're at the last node, process it as a partial trie
|
||||||
|
if split == len(keys) && len(proof) != 1 {
|
||||||
|
commit, _, err := s.processPartialLeaves(keys[:split], values[:split], proof[1:])
|
||||||
|
return commit, root, err
|
||||||
|
}
|
||||||
|
// Otherwise we have a full sub-trie, parse in its entirety (if not already contained within the full node)
|
||||||
|
commit, _, err := s.processLeaves(keys[:split], values[:split])
|
||||||
|
if err != nil {
|
||||||
|
return commit, root, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
keys = keys[split:]
|
||||||
|
values = values[split:]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false, root, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Commit flushes the data stored in the internal membatch out to persistent
|
// Commit flushes the data stored in the internal membatch out to persistent
|
||||||
|
|
@ -320,9 +468,7 @@ func (s *TrieSync) children(req *request, object node) ([]*request, error) {
|
||||||
// committed themselves.
|
// committed themselves.
|
||||||
func (s *TrieSync) commit(req *request) (err error) {
|
func (s *TrieSync) commit(req *request) (err error) {
|
||||||
// Write the node content to the membatch
|
// Write the node content to the membatch
|
||||||
s.membatch.batch[req.hash] = req.data
|
s.commitEntry(req.hash, req.data)
|
||||||
s.membatch.order = append(s.membatch.order, req.hash)
|
|
||||||
|
|
||||||
delete(s.requests, req.hash)
|
delete(s.requests, req.hash)
|
||||||
|
|
||||||
// Check all parents for completion
|
// Check all parents for completion
|
||||||
|
|
@ -336,3 +482,10 @@ func (s *TrieSync) commit(req *request) (err error) {
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// commitEntry injects a raw database entry into the memory batch to be flushed
|
||||||
|
// out at a later point into the real database.
|
||||||
|
func (s *TrieSync) commitEntry(key common.Hash, blob []byte) {
|
||||||
|
s.membatch.batch[key] = blob
|
||||||
|
s.membatch.order = append(s.membatch.order, key)
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -18,6 +18,7 @@ package trie
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
"math/rand"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
|
|
@ -27,7 +28,7 @@ import (
|
||||||
// makeTestTrie create a sample test trie to test node-wise reconstruction.
|
// makeTestTrie create a sample test trie to test node-wise reconstruction.
|
||||||
func makeTestTrie() (ethdb.Database, *Trie, map[string][]byte) {
|
func makeTestTrie() (ethdb.Database, *Trie, map[string][]byte) {
|
||||||
// Create an empty trie
|
// Create an empty trie
|
||||||
db, _ := ethdb.NewMemDatabase()
|
db := ethdb.NewMemDatabase()
|
||||||
trie, _ := New(common.Hash{}, db)
|
trie, _ := New(common.Hash{}, db)
|
||||||
|
|
||||||
// Fill it with some arbitrary data
|
// Fill it with some arbitrary data
|
||||||
|
|
@ -92,7 +93,7 @@ func TestEmptyTrieSync(t *testing.T) {
|
||||||
emptyB, _ := New(emptyRoot, nil)
|
emptyB, _ := New(emptyRoot, nil)
|
||||||
|
|
||||||
for i, trie := range []*Trie{emptyA, emptyB} {
|
for i, trie := range []*Trie{emptyA, emptyB} {
|
||||||
db, _ := ethdb.NewMemDatabase()
|
db := ethdb.NewMemDatabase()
|
||||||
if req := NewTrieSync(common.BytesToHash(trie.Root()), db, nil).Missing(1); len(req) != 0 {
|
if req := NewTrieSync(common.BytesToHash(trie.Root()), db, nil).Missing(1); len(req) != 0 {
|
||||||
t.Errorf("test %d: content requested for empty trie: %v", i, req)
|
t.Errorf("test %d: content requested for empty trie: %v", i, req)
|
||||||
}
|
}
|
||||||
|
|
@ -109,21 +110,27 @@ func testIterativeTrieSync(t *testing.T, batch int) {
|
||||||
srcDb, srcTrie, srcData := makeTestTrie()
|
srcDb, srcTrie, srcData := makeTestTrie()
|
||||||
|
|
||||||
// Create a destination trie and sync with the scheduler
|
// Create a destination trie and sync with the scheduler
|
||||||
dstDb, _ := ethdb.NewMemDatabase()
|
dstDb := ethdb.NewMemDatabase()
|
||||||
sched := NewTrieSync(common.BytesToHash(srcTrie.Root()), dstDb, nil)
|
sched := NewTrieSync(common.BytesToHash(srcTrie.Root()), dstDb, nil)
|
||||||
|
|
||||||
queue := append([]common.Hash{}, sched.Missing(batch)...)
|
queue := append([]common.Hash{}, sched.Missing(batch)...)
|
||||||
for len(queue) > 0 {
|
for len(queue) > 0 {
|
||||||
results := make([]SyncResult, len(queue))
|
results := make([]*SyncResult, len(queue))
|
||||||
for i, hash := range queue {
|
for i, hash := range queue {
|
||||||
data, err := srcDb.Get(hash.Bytes())
|
if rand.Int()%2 == 0 {
|
||||||
if err != nil {
|
data, err := srcDb.Get(hash.Bytes())
|
||||||
t.Fatalf("failed to retrieve node data for %x: %v", hash, err)
|
if err != nil {
|
||||||
|
t.Fatalf("failed to retrieve node data for %x: %v", hash, err)
|
||||||
|
}
|
||||||
|
results[i] = &SyncResult{Data: data}
|
||||||
|
} else {
|
||||||
|
results[i], _ = srcTrie.FetchData(hash, 8192)
|
||||||
}
|
}
|
||||||
results[i] = SyncResult{Hash: hash, Data: data}
|
|
||||||
}
|
}
|
||||||
if _, index, err := sched.Process(results); err != nil {
|
for index, result := range results {
|
||||||
t.Fatalf("failed to process result #%d: %v", index, err)
|
if _, _, err := sched.Process(result); err != nil {
|
||||||
|
t.Fatalf("failed to process result #%d: %v", index, err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if index, err := sched.Commit(dstDb); err != nil {
|
if index, err := sched.Commit(dstDb); err != nil {
|
||||||
t.Fatalf("failed to commit data #%d: %v", index, err)
|
t.Fatalf("failed to commit data #%d: %v", index, err)
|
||||||
|
|
@ -141,22 +148,28 @@ func TestIterativeDelayedTrieSync(t *testing.T) {
|
||||||
srcDb, srcTrie, srcData := makeTestTrie()
|
srcDb, srcTrie, srcData := makeTestTrie()
|
||||||
|
|
||||||
// Create a destination trie and sync with the scheduler
|
// Create a destination trie and sync with the scheduler
|
||||||
dstDb, _ := ethdb.NewMemDatabase()
|
dstDb := ethdb.NewMemDatabase()
|
||||||
sched := NewTrieSync(common.BytesToHash(srcTrie.Root()), dstDb, nil)
|
sched := NewTrieSync(common.BytesToHash(srcTrie.Root()), dstDb, nil)
|
||||||
|
|
||||||
queue := append([]common.Hash{}, sched.Missing(10000)...)
|
queue := append([]common.Hash{}, sched.Missing(10000)...)
|
||||||
for len(queue) > 0 {
|
for len(queue) > 0 {
|
||||||
// Sync only half of the scheduled nodes
|
// Sync only half of the scheduled nodes
|
||||||
results := make([]SyncResult, len(queue)/2+1)
|
results := make([]*SyncResult, len(queue)/2+1)
|
||||||
for i, hash := range queue[:len(results)] {
|
for i, hash := range queue[:len(results)] {
|
||||||
data, err := srcDb.Get(hash.Bytes())
|
if rand.Int()%2 == 0 {
|
||||||
if err != nil {
|
data, err := srcDb.Get(hash.Bytes())
|
||||||
t.Fatalf("failed to retrieve node data for %x: %v", hash, err)
|
if err != nil {
|
||||||
|
t.Fatalf("failed to retrieve node data for %x: %v", hash, err)
|
||||||
|
}
|
||||||
|
results[i] = &SyncResult{Data: data}
|
||||||
|
} else {
|
||||||
|
results[i], _ = srcTrie.FetchData(hash, 8192)
|
||||||
}
|
}
|
||||||
results[i] = SyncResult{Hash: hash, Data: data}
|
|
||||||
}
|
}
|
||||||
if _, index, err := sched.Process(results); err != nil {
|
for index, result := range results {
|
||||||
t.Fatalf("failed to process result #%d: %v", index, err)
|
if _, _, err := sched.Process(result); err != nil {
|
||||||
|
t.Fatalf("failed to process result #%d: %v", index, err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if index, err := sched.Commit(dstDb); err != nil {
|
if index, err := sched.Commit(dstDb); err != nil {
|
||||||
t.Fatalf("failed to commit data #%d: %v", index, err)
|
t.Fatalf("failed to commit data #%d: %v", index, err)
|
||||||
|
|
@ -178,7 +191,7 @@ func testIterativeRandomTrieSync(t *testing.T, batch int) {
|
||||||
srcDb, srcTrie, srcData := makeTestTrie()
|
srcDb, srcTrie, srcData := makeTestTrie()
|
||||||
|
|
||||||
// Create a destination trie and sync with the scheduler
|
// Create a destination trie and sync with the scheduler
|
||||||
dstDb, _ := ethdb.NewMemDatabase()
|
dstDb := ethdb.NewMemDatabase()
|
||||||
sched := NewTrieSync(common.BytesToHash(srcTrie.Root()), dstDb, nil)
|
sched := NewTrieSync(common.BytesToHash(srcTrie.Root()), dstDb, nil)
|
||||||
|
|
||||||
queue := make(map[common.Hash]struct{})
|
queue := make(map[common.Hash]struct{})
|
||||||
|
|
@ -187,17 +200,24 @@ func testIterativeRandomTrieSync(t *testing.T, batch int) {
|
||||||
}
|
}
|
||||||
for len(queue) > 0 {
|
for len(queue) > 0 {
|
||||||
// Fetch all the queued nodes in a random order
|
// Fetch all the queued nodes in a random order
|
||||||
results := make([]SyncResult, 0, len(queue))
|
results := make([]*SyncResult, 0, len(queue))
|
||||||
for hash := range queue {
|
for hash := range queue {
|
||||||
data, err := srcDb.Get(hash.Bytes())
|
if rand.Int()%2 == 0 {
|
||||||
if err != nil {
|
data, err := srcDb.Get(hash.Bytes())
|
||||||
t.Fatalf("failed to retrieve node data for %x: %v", hash, err)
|
if err != nil {
|
||||||
|
t.Fatalf("failed to retrieve node data for %x: %v", hash, err)
|
||||||
|
}
|
||||||
|
results = append(results, &SyncResult{Data: data})
|
||||||
|
} else {
|
||||||
|
request, _ := srcTrie.FetchData(hash, 8192)
|
||||||
|
results = append(results, request)
|
||||||
}
|
}
|
||||||
results = append(results, SyncResult{Hash: hash, Data: data})
|
|
||||||
}
|
}
|
||||||
// Feed the retrieved results back and queue new tasks
|
// Feed the retrieved results back and queue new tasks
|
||||||
if _, index, err := sched.Process(results); err != nil {
|
for index, result := range results {
|
||||||
t.Fatalf("failed to process result #%d: %v", index, err)
|
if _, _, err := sched.Process(result); err != nil {
|
||||||
|
t.Fatalf("failed to process result #%d: %v", index, err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if index, err := sched.Commit(dstDb); err != nil {
|
if index, err := sched.Commit(dstDb); err != nil {
|
||||||
t.Fatalf("failed to commit data #%d: %v", index, err)
|
t.Fatalf("failed to commit data #%d: %v", index, err)
|
||||||
|
|
@ -218,7 +238,7 @@ func TestIterativeRandomDelayedTrieSync(t *testing.T) {
|
||||||
srcDb, srcTrie, srcData := makeTestTrie()
|
srcDb, srcTrie, srcData := makeTestTrie()
|
||||||
|
|
||||||
// Create a destination trie and sync with the scheduler
|
// Create a destination trie and sync with the scheduler
|
||||||
dstDb, _ := ethdb.NewMemDatabase()
|
dstDb := ethdb.NewMemDatabase()
|
||||||
sched := NewTrieSync(common.BytesToHash(srcTrie.Root()), dstDb, nil)
|
sched := NewTrieSync(common.BytesToHash(srcTrie.Root()), dstDb, nil)
|
||||||
|
|
||||||
queue := make(map[common.Hash]struct{})
|
queue := make(map[common.Hash]struct{})
|
||||||
|
|
@ -227,28 +247,33 @@ func TestIterativeRandomDelayedTrieSync(t *testing.T) {
|
||||||
}
|
}
|
||||||
for len(queue) > 0 {
|
for len(queue) > 0 {
|
||||||
// Sync only half of the scheduled nodes, even those in random order
|
// Sync only half of the scheduled nodes, even those in random order
|
||||||
results := make([]SyncResult, 0, len(queue)/2+1)
|
results := make([]*SyncResult, 0, len(queue)/2+1)
|
||||||
for hash := range queue {
|
for hash := range queue {
|
||||||
data, err := srcDb.Get(hash.Bytes())
|
if rand.Int()%2 == 0 {
|
||||||
if err != nil {
|
data, err := srcDb.Get(hash.Bytes())
|
||||||
t.Fatalf("failed to retrieve node data for %x: %v", hash, err)
|
if err != nil {
|
||||||
|
t.Fatalf("failed to retrieve node data for %x: %v", hash, err)
|
||||||
|
}
|
||||||
|
results = append(results, &SyncResult{Data: data})
|
||||||
|
} else {
|
||||||
|
request, _ := srcTrie.FetchData(hash, 8192)
|
||||||
|
results = append(results, request)
|
||||||
}
|
}
|
||||||
results = append(results, SyncResult{Hash: hash, Data: data})
|
|
||||||
|
|
||||||
if len(results) >= cap(results) {
|
if len(results) >= cap(results) {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Feed the retrieved results back and queue new tasks
|
// Feed the retrieved results back and queue new tasks
|
||||||
if _, index, err := sched.Process(results); err != nil {
|
for index, result := range results {
|
||||||
t.Fatalf("failed to process result #%d: %v", index, err)
|
_, hash, err := sched.Process(result)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("failed to process result #%d: %v", index, err)
|
||||||
|
}
|
||||||
|
delete(queue, hash)
|
||||||
}
|
}
|
||||||
if index, err := sched.Commit(dstDb); err != nil {
|
if index, err := sched.Commit(dstDb); err != nil {
|
||||||
t.Fatalf("failed to commit data #%d: %v", index, err)
|
t.Fatalf("failed to commit data #%d: %v", index, err)
|
||||||
}
|
}
|
||||||
for _, result := range results {
|
|
||||||
delete(queue, result.Hash)
|
|
||||||
}
|
|
||||||
for _, hash := range sched.Missing(10000) {
|
for _, hash := range sched.Missing(10000) {
|
||||||
queue[hash] = struct{}{}
|
queue[hash] = struct{}{}
|
||||||
}
|
}
|
||||||
|
|
@ -264,28 +289,34 @@ func TestDuplicateAvoidanceTrieSync(t *testing.T) {
|
||||||
srcDb, srcTrie, srcData := makeTestTrie()
|
srcDb, srcTrie, srcData := makeTestTrie()
|
||||||
|
|
||||||
// Create a destination trie and sync with the scheduler
|
// Create a destination trie and sync with the scheduler
|
||||||
dstDb, _ := ethdb.NewMemDatabase()
|
dstDb := ethdb.NewMemDatabase()
|
||||||
sched := NewTrieSync(common.BytesToHash(srcTrie.Root()), dstDb, nil)
|
sched := NewTrieSync(common.BytesToHash(srcTrie.Root()), dstDb, nil)
|
||||||
|
|
||||||
queue := append([]common.Hash{}, sched.Missing(0)...)
|
queue := append([]common.Hash{}, sched.Missing(0)...)
|
||||||
requested := make(map[common.Hash]struct{})
|
requested := make(map[common.Hash]struct{})
|
||||||
|
|
||||||
for len(queue) > 0 {
|
for len(queue) > 0 {
|
||||||
results := make([]SyncResult, len(queue))
|
results := make([]*SyncResult, len(queue))
|
||||||
for i, hash := range queue {
|
for i, hash := range queue {
|
||||||
data, err := srcDb.Get(hash.Bytes())
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("failed to retrieve node data for %x: %v", hash, err)
|
|
||||||
}
|
|
||||||
if _, ok := requested[hash]; ok {
|
if _, ok := requested[hash]; ok {
|
||||||
t.Errorf("hash %x already requested once", hash)
|
t.Errorf("hash %x already requested once", hash)
|
||||||
}
|
}
|
||||||
requested[hash] = struct{}{}
|
requested[hash] = struct{}{}
|
||||||
|
|
||||||
results[i] = SyncResult{Hash: hash, Data: data}
|
if rand.Int()%2 == 0 {
|
||||||
|
data, err := srcDb.Get(hash.Bytes())
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("failed to retrieve node data for %x: %v", hash, err)
|
||||||
|
}
|
||||||
|
results[i] = &SyncResult{Data: data}
|
||||||
|
} else {
|
||||||
|
results[i], _ = srcTrie.FetchData(hash, 8192)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if _, index, err := sched.Process(results); err != nil {
|
for index, result := range results {
|
||||||
t.Fatalf("failed to process result #%d: %v", index, err)
|
if _, _, err := sched.Process(result); err != nil {
|
||||||
|
t.Fatalf("failed to process result #%d: %v", index, err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if index, err := sched.Commit(dstDb); err != nil {
|
if index, err := sched.Commit(dstDb); err != nil {
|
||||||
t.Fatalf("failed to commit data #%d: %v", index, err)
|
t.Fatalf("failed to commit data #%d: %v", index, err)
|
||||||
|
|
@ -303,31 +334,36 @@ func TestIncompleteTrieSync(t *testing.T) {
|
||||||
srcDb, srcTrie, _ := makeTestTrie()
|
srcDb, srcTrie, _ := makeTestTrie()
|
||||||
|
|
||||||
// Create a destination trie and sync with the scheduler
|
// Create a destination trie and sync with the scheduler
|
||||||
dstDb, _ := ethdb.NewMemDatabase()
|
dstDb := ethdb.NewMemDatabase()
|
||||||
sched := NewTrieSync(common.BytesToHash(srcTrie.Root()), dstDb, nil)
|
sched := NewTrieSync(common.BytesToHash(srcTrie.Root()), dstDb, nil)
|
||||||
|
|
||||||
added := []common.Hash{}
|
added := []common.Hash{}
|
||||||
queue := append([]common.Hash{}, sched.Missing(1)...)
|
queue := append([]common.Hash{}, sched.Missing(1)...)
|
||||||
for len(queue) > 0 {
|
for len(queue) > 0 {
|
||||||
// Fetch a batch of trie nodes
|
// Fetch a batch of trie nodes
|
||||||
results := make([]SyncResult, len(queue))
|
results := make([]*SyncResult, len(queue))
|
||||||
for i, hash := range queue {
|
for i, hash := range queue {
|
||||||
data, err := srcDb.Get(hash.Bytes())
|
if rand.Int()%2 == 0 {
|
||||||
if err != nil {
|
data, err := srcDb.Get(hash.Bytes())
|
||||||
t.Fatalf("failed to retrieve node data for %x: %v", hash, err)
|
if err != nil {
|
||||||
|
t.Fatalf("failed to retrieve node data for %x: %v", hash, err)
|
||||||
|
}
|
||||||
|
results[i] = &SyncResult{Data: data}
|
||||||
|
} else {
|
||||||
|
results[i], _ = srcTrie.FetchData(hash, 8192)
|
||||||
}
|
}
|
||||||
results[i] = SyncResult{Hash: hash, Data: data}
|
|
||||||
}
|
}
|
||||||
// Process each of the trie nodes
|
// Process each of the trie nodes
|
||||||
if _, index, err := sched.Process(results); err != nil {
|
for index, result := range results {
|
||||||
t.Fatalf("failed to process result #%d: %v", index, err)
|
_, hash, err := sched.Process(result)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("failed to process result #%d: %v", index, err)
|
||||||
|
}
|
||||||
|
added = append(added, hash)
|
||||||
}
|
}
|
||||||
if index, err := sched.Commit(dstDb); err != nil {
|
if index, err := sched.Commit(dstDb); err != nil {
|
||||||
t.Fatalf("failed to commit data #%d: %v", index, err)
|
t.Fatalf("failed to commit data #%d: %v", index, err)
|
||||||
}
|
}
|
||||||
for _, result := range results {
|
|
||||||
added = append(added, result.Hash)
|
|
||||||
}
|
|
||||||
// Check that all known sub-tries in the synced trie are complete
|
// Check that all known sub-tries in the synced trie are complete
|
||||||
for _, root := range added {
|
for _, root := range added {
|
||||||
if err := checkTrieConsistency(dstDb, root); err != nil {
|
if err := checkTrieConsistency(dstDb, root); err != nil {
|
||||||
|
|
|
||||||
37
trie/trie.go
37
trie/trie.go
|
|
@ -504,3 +504,40 @@ func (t *Trie) hashRoot(db DatabaseWriter) (node, node, error) {
|
||||||
defer returnHasherToPool(h)
|
defer returnHasherToPool(h)
|
||||||
return h.hash(t.root, db, true)
|
return h.hash(t.root, db, true)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FetchData retrieves synchronization data from the trie to send to remote
|
||||||
|
// nodes.
|
||||||
|
func (t *Trie) FetchData(hash common.Hash, limit common.StorageSize) (res *SyncResult, fail error) {
|
||||||
|
// If this method panics, hash points to a non-iterable trie; return individual node
|
||||||
|
defer func() {
|
||||||
|
if r := recover(); r != nil {
|
||||||
|
blob, err := t.db.Get(hash[:])
|
||||||
|
if err != nil {
|
||||||
|
fail = err
|
||||||
|
} else {
|
||||||
|
res = &SyncResult{Data: blob}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
// Try to gather the necessary data as key-value pairs
|
||||||
|
result := new(SyncResult)
|
||||||
|
|
||||||
|
trie, _ := New(hash, t.db)
|
||||||
|
it := NewIterator(trie.NodeIterator(nil))
|
||||||
|
|
||||||
|
size := common.StorageSize(0)
|
||||||
|
for size < limit && it.Next() {
|
||||||
|
result.Keys = append(result.Keys, common.CopyBytes(it.Key))
|
||||||
|
result.Values = append(result.Values, common.CopyBytes(it.Value))
|
||||||
|
|
||||||
|
size += common.StorageSize(len(it.Key) + len(it.Value))
|
||||||
|
}
|
||||||
|
// If we've went past our data allowance, prove the partial data
|
||||||
|
if size >= limit {
|
||||||
|
result.Proof = it.Prove()
|
||||||
|
if !it.Next() {
|
||||||
|
result.Proof = nil // Overflowing item was the last after all
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -40,7 +40,7 @@ func init() {
|
||||||
|
|
||||||
// Used for testing
|
// Used for testing
|
||||||
func newEmpty() *Trie {
|
func newEmpty() *Trie {
|
||||||
db, _ := ethdb.NewMemDatabase()
|
db := ethdb.NewMemDatabase()
|
||||||
trie, _ := New(common.Hash{}, db)
|
trie, _ := New(common.Hash{}, db)
|
||||||
return trie
|
return trie
|
||||||
}
|
}
|
||||||
|
|
@ -65,7 +65,7 @@ func TestNull(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestMissingRoot(t *testing.T) {
|
func TestMissingRoot(t *testing.T) {
|
||||||
db, _ := ethdb.NewMemDatabase()
|
db := ethdb.NewMemDatabase()
|
||||||
trie, err := New(common.HexToHash("0beec7b5ea3f0fdbc95d0dd47f3c5bc275da8a33"), db)
|
trie, err := New(common.HexToHash("0beec7b5ea3f0fdbc95d0dd47f3c5bc275da8a33"), db)
|
||||||
if trie != nil {
|
if trie != nil {
|
||||||
t.Error("New returned non-nil trie for invalid root")
|
t.Error("New returned non-nil trie for invalid root")
|
||||||
|
|
@ -76,7 +76,7 @@ func TestMissingRoot(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestMissingNode(t *testing.T) {
|
func TestMissingNode(t *testing.T) {
|
||||||
db, _ := ethdb.NewMemDatabase()
|
db := ethdb.NewMemDatabase()
|
||||||
trie, _ := New(common.Hash{}, db)
|
trie, _ := New(common.Hash{}, db)
|
||||||
updateString(trie, "120000", "qwerqwerqwerqwerqwerqwerqwerqwer")
|
updateString(trie, "120000", "qwerqwerqwerqwerqwerqwerqwerqwer")
|
||||||
updateString(trie, "123456", "asdfasdfasdfasdfasdfasdfasdfasdf")
|
updateString(trie, "123456", "asdfasdfasdfasdfasdfasdfasdfasdf")
|
||||||
|
|
@ -404,7 +404,7 @@ func (randTest) Generate(r *rand.Rand, size int) reflect.Value {
|
||||||
}
|
}
|
||||||
|
|
||||||
func runRandTest(rt randTest) bool {
|
func runRandTest(rt randTest) bool {
|
||||||
db, _ := ethdb.NewMemDatabase()
|
db := ethdb.NewMemDatabase()
|
||||||
tr, _ := New(common.Hash{}, db)
|
tr, _ := New(common.Hash{}, db)
|
||||||
values := make(map[string]string) // tracks content of the trie
|
values := make(map[string]string) // tracks content of the trie
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue