Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
G
Geth-Modification
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
张蕾
Geth-Modification
Commits
87c0ba92
Unverified
Commit
87c0ba92
authored
Aug 21, 2020
by
gary rong
Committed by
GitHub
Aug 21, 2020
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
core, eth, les, trie: add a prefix to contract code (#21080)
parent
b68929ca
Changes
42
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
42 changed files
with
579 additions
and
286 deletions
+579
-286
execution.go
cmd/evm/internal/t8ntool/execution.go
+3
-2
retesteth.go
cmd/geth/retesteth.go
+1
-1
clique.go
consensus/clique/clique.go
+2
-1
consensus.go
consensus/ethash/consensus.go
+2
-1
block_validator.go
core/block_validator.go
+3
-2
blockchain.go
core/blockchain.go
+23
-2
blockchain_test.go
core/blockchain_test.go
+3
-2
genesis.go
core/genesis.go
+2
-1
accessors_chain_test.go
core/rawdb/accessors_chain_test.go
+2
-2
accessors_indexes_test.go
core/rawdb/accessors_indexes_test.go
+27
-1
accessors_metadata.go
core/rawdb/accessors_metadata.go
+0
-17
accessors_state.go
core/rawdb/accessors_state.go
+96
-0
chain_iterator_test.go
core/rawdb/chain_iterator_test.go
+2
-2
database.go
core/rawdb/database.go
+4
-0
schema.go
core/rawdb/schema.go
+16
-0
database.go
core/state/database.go
+32
-3
iterator_test.go
core/state/iterator_test.go
+5
-1
statedb.go
core/state/statedb.go
+12
-9
sync.go
core/state/sync.go
+1
-1
sync_test.go
core/state/sync_test.go
+71
-24
tx_pool_test.go
core/tx_pool_test.go
+2
-1
block.go
core/types/block.go
+4
-4
block_test.go
core/types/block_test.go
+27
-1
derive_sha.go
core/types/derive_sha.go
+12
-5
downloader.go
eth/downloader/downloader.go
+1
-1
queue.go
eth/downloader/queue.go
+3
-2
statesync.go
eth/downloader/statesync.go
+4
-4
block_fetcher.go
eth/fetcher/block_fetcher.go
+3
-2
block_fetcher_test.go
eth/fetcher/block_fetcher_test.go
+2
-1
handler.go
eth/handler.go
+9
-2
odr_requests.go
les/odr_requests.go
+2
-2
server_handler.go
les/server_handler.go
+1
-1
odr.go
light/odr.go
+1
-1
odr_test.go
light/odr_test.go
+1
-1
trie.go
light/trie.go
+3
-1
worker.go
miner/worker.go
+2
-0
database.go
trie/database.go
+38
-91
secure_trie.go
trie/secure_trie.go
+1
-2
sync.go
trie/sync.go
+113
-74
sync_bloom.go
trie/sync_bloom.go
+13
-6
sync_test.go
trie/sync_test.go
+24
-12
trie.go
trie/trie.go
+6
-0
No files found.
cmd/evm/internal/t8ntool/execution.go
View file @
87c0ba92
...
...
@@ -34,6 +34,7 @@ import (
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/rlp"
"github.com/ethereum/go-ethereum/trie"
"golang.org/x/crypto/sha3"
)
...
...
@@ -220,8 +221,8 @@ func (pre *Prestate) Apply(vmConfig vm.Config, chainConfig *params.ChainConfig,
}
execRs
:=
&
ExecutionResult
{
StateRoot
:
root
,
TxRoot
:
types
.
DeriveSha
(
includedTxs
),
ReceiptRoot
:
types
.
DeriveSha
(
receipts
),
TxRoot
:
types
.
DeriveSha
(
includedTxs
,
new
(
trie
.
Trie
)
),
ReceiptRoot
:
types
.
DeriveSha
(
receipts
,
new
(
trie
.
Trie
)
),
Bloom
:
types
.
CreateBloom
(
receipts
),
LogsHash
:
rlpHash
(
statedb
.
Logs
()),
Receipts
:
receipts
,
...
...
cmd/geth/retesteth.go
View file @
87c0ba92
...
...
@@ -248,7 +248,7 @@ func (e *NoRewardEngine) FinalizeAndAssemble(chain consensus.ChainHeaderReader,
header
.
Root
=
statedb
.
IntermediateRoot
(
chain
.
Config
()
.
IsEIP158
(
header
.
Number
))
// Header seems complete, assemble into a block and return
return
types
.
NewBlock
(
header
,
txs
,
uncles
,
receipts
),
nil
return
types
.
NewBlock
(
header
,
txs
,
uncles
,
receipts
,
new
(
trie
.
Trie
)
),
nil
}
}
...
...
consensus/clique/clique.go
View file @
87c0ba92
...
...
@@ -39,6 +39,7 @@ import (
"github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/rlp"
"github.com/ethereum/go-ethereum/rpc"
"github.com/ethereum/go-ethereum/trie"
lru
"github.com/hashicorp/golang-lru"
"golang.org/x/crypto/sha3"
)
...
...
@@ -565,7 +566,7 @@ func (c *Clique) FinalizeAndAssemble(chain consensus.ChainHeaderReader, header *
header
.
UncleHash
=
types
.
CalcUncleHash
(
nil
)
// Assemble and return the final block for sealing
return
types
.
NewBlock
(
header
,
txs
,
nil
,
receipts
),
nil
return
types
.
NewBlock
(
header
,
txs
,
nil
,
receipts
,
new
(
trie
.
Trie
)
),
nil
}
// Authorize injects a private key into the consensus engine to mint new blocks
...
...
consensus/ethash/consensus.go
View file @
87c0ba92
...
...
@@ -33,6 +33,7 @@ import (
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/rlp"
"github.com/ethereum/go-ethereum/trie"
"golang.org/x/crypto/sha3"
)
...
...
@@ -583,7 +584,7 @@ func (ethash *Ethash) FinalizeAndAssemble(chain consensus.ChainHeaderReader, hea
header
.
Root
=
state
.
IntermediateRoot
(
chain
.
Config
()
.
IsEIP158
(
header
.
Number
))
// Header seems complete, assemble into a block and return
return
types
.
NewBlock
(
header
,
txs
,
uncles
,
receipts
),
nil
return
types
.
NewBlock
(
header
,
txs
,
uncles
,
receipts
,
new
(
trie
.
Trie
)
),
nil
}
// SealHash returns the hash of a block prior to it being sealed.
...
...
core/block_validator.go
View file @
87c0ba92
...
...
@@ -23,6 +23,7 @@ import (
"github.com/ethereum/go-ethereum/core/state"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/trie"
)
// BlockValidator is responsible for validating block headers, uncles and
...
...
@@ -61,7 +62,7 @@ func (v *BlockValidator) ValidateBody(block *types.Block) error {
if
hash
:=
types
.
CalcUncleHash
(
block
.
Uncles
());
hash
!=
header
.
UncleHash
{
return
fmt
.
Errorf
(
"uncle root hash mismatch: have %x, want %x"
,
hash
,
header
.
UncleHash
)
}
if
hash
:=
types
.
DeriveSha
(
block
.
Transactions
());
hash
!=
header
.
TxHash
{
if
hash
:=
types
.
DeriveSha
(
block
.
Transactions
()
,
new
(
trie
.
Trie
)
);
hash
!=
header
.
TxHash
{
return
fmt
.
Errorf
(
"transaction root hash mismatch: have %x, want %x"
,
hash
,
header
.
TxHash
)
}
if
!
v
.
bc
.
HasBlockAndState
(
block
.
ParentHash
(),
block
.
NumberU64
()
-
1
)
{
...
...
@@ -89,7 +90,7 @@ func (v *BlockValidator) ValidateState(block *types.Block, statedb *state.StateD
return
fmt
.
Errorf
(
"invalid bloom (remote: %x local: %x)"
,
header
.
Bloom
,
rbloom
)
}
// Tre receipt Trie's root (R = (Tr [[H1, R1], ... [Hn, R1]]))
receiptSha
:=
types
.
DeriveSha
(
receipts
)
receiptSha
:=
types
.
DeriveSha
(
receipts
,
new
(
trie
.
Trie
)
)
if
receiptSha
!=
header
.
ReceiptHash
{
return
fmt
.
Errorf
(
"invalid receipt root hash (remote: %x local: %x)"
,
header
.
ReceiptHash
,
receiptSha
)
}
...
...
core/blockchain.go
View file @
87c0ba92
...
...
@@ -112,7 +112,10 @@ const (
// - Version 7
// The following incompatible database changes were added:
// * Use freezer as the ancient database to maintain all ancient data
BlockChainVersion
uint64
=
7
// - Version 8
// The following incompatible database changes were added:
// * New scheme for contract code in order to separate the codes and trie nodes
BlockChainVersion
uint64
=
8
)
// CacheConfig contains the configuration values for the trie caching/pruning
...
...
@@ -895,12 +898,30 @@ func (bc *BlockChain) GetUnclesInChain(block *types.Block, length int) []*types.
return
uncles
}
// TrieNode retrieves a blob of data associated with a trie node
(or code hash)
// TrieNode retrieves a blob of data associated with a trie node
// either from ephemeral in-memory cache, or from persistent storage.
func
(
bc
*
BlockChain
)
TrieNode
(
hash
common
.
Hash
)
([]
byte
,
error
)
{
return
bc
.
stateCache
.
TrieDB
()
.
Node
(
hash
)
}
// ContractCode retrieves a blob of data associated with a contract hash
// either from ephemeral in-memory cache, or from persistent storage.
func
(
bc
*
BlockChain
)
ContractCode
(
hash
common
.
Hash
)
([]
byte
,
error
)
{
return
bc
.
stateCache
.
ContractCode
(
common
.
Hash
{},
hash
)
}
// ContractCodeWithPrefix retrieves a blob of data associated with a contract
// hash either from ephemeral in-memory cache, or from persistent storage.
//
// If the code doesn't exist in the in-memory cache, check the storage with
// new code scheme.
func
(
bc
*
BlockChain
)
ContractCodeWithPrefix
(
hash
common
.
Hash
)
([]
byte
,
error
)
{
type
codeReader
interface
{
ContractCodeWithPrefix
(
addrHash
,
codeHash
common
.
Hash
)
([]
byte
,
error
)
}
return
bc
.
stateCache
.
(
codeReader
)
.
ContractCodeWithPrefix
(
common
.
Hash
{},
hash
)
}
// Stop stops the blockchain service. If any imports are currently in progress
// it will abort them using the procInterrupt.
func
(
bc
*
BlockChain
)
Stop
()
{
...
...
core/blockchain_test.go
View file @
87c0ba92
...
...
@@ -36,6 +36,7 @@ import (
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/trie"
)
// So we can deterministically seed different blockchains
...
...
@@ -681,12 +682,12 @@ func TestFastVsFullChains(t *testing.T) {
}
if
fblock
,
arblock
,
anblock
:=
fast
.
GetBlockByHash
(
hash
),
archive
.
GetBlockByHash
(
hash
),
ancient
.
GetBlockByHash
(
hash
);
fblock
.
Hash
()
!=
arblock
.
Hash
()
||
anblock
.
Hash
()
!=
arblock
.
Hash
()
{
t
.
Errorf
(
"block #%d [%x]: block mismatch: fastdb %v, ancientdb %v, archivedb %v"
,
num
,
hash
,
fblock
,
anblock
,
arblock
)
}
else
if
types
.
DeriveSha
(
fblock
.
Transactions
()
)
!=
types
.
DeriveSha
(
arblock
.
Transactions
())
||
types
.
DeriveSha
(
anblock
.
Transactions
())
!=
types
.
DeriveSha
(
arblock
.
Transactions
(
))
{
}
else
if
types
.
DeriveSha
(
fblock
.
Transactions
()
,
new
(
trie
.
Trie
))
!=
types
.
DeriveSha
(
arblock
.
Transactions
(),
new
(
trie
.
Trie
))
||
types
.
DeriveSha
(
anblock
.
Transactions
(),
new
(
trie
.
Trie
))
!=
types
.
DeriveSha
(
arblock
.
Transactions
(),
new
(
trie
.
Trie
))
{
t
.
Errorf
(
"block #%d [%x]: transactions mismatch: fastdb %v, ancientdb %v, archivedb %v"
,
num
,
hash
,
fblock
.
Transactions
(),
anblock
.
Transactions
(),
arblock
.
Transactions
())
}
else
if
types
.
CalcUncleHash
(
fblock
.
Uncles
())
!=
types
.
CalcUncleHash
(
arblock
.
Uncles
())
||
types
.
CalcUncleHash
(
anblock
.
Uncles
())
!=
types
.
CalcUncleHash
(
arblock
.
Uncles
())
{
t
.
Errorf
(
"block #%d [%x]: uncles mismatch: fastdb %v, ancientdb %v, archivedb %v"
,
num
,
hash
,
fblock
.
Uncles
(),
anblock
,
arblock
.
Uncles
())
}
if
freceipts
,
anreceipts
,
areceipts
:=
rawdb
.
ReadReceipts
(
fastDb
,
hash
,
*
rawdb
.
ReadHeaderNumber
(
fastDb
,
hash
),
fast
.
Config
()),
rawdb
.
ReadReceipts
(
ancientDb
,
hash
,
*
rawdb
.
ReadHeaderNumber
(
ancientDb
,
hash
),
fast
.
Config
()),
rawdb
.
ReadReceipts
(
archiveDb
,
hash
,
*
rawdb
.
ReadHeaderNumber
(
archiveDb
,
hash
),
fast
.
Config
());
types
.
DeriveSha
(
freceipts
)
!=
types
.
DeriveSha
(
areceipts
)
{
if
freceipts
,
anreceipts
,
areceipts
:=
rawdb
.
ReadReceipts
(
fastDb
,
hash
,
*
rawdb
.
ReadHeaderNumber
(
fastDb
,
hash
),
fast
.
Config
()),
rawdb
.
ReadReceipts
(
ancientDb
,
hash
,
*
rawdb
.
ReadHeaderNumber
(
ancientDb
,
hash
),
fast
.
Config
()),
rawdb
.
ReadReceipts
(
archiveDb
,
hash
,
*
rawdb
.
ReadHeaderNumber
(
archiveDb
,
hash
),
fast
.
Config
());
types
.
DeriveSha
(
freceipts
,
new
(
trie
.
Trie
))
!=
types
.
DeriveSha
(
areceipts
,
new
(
trie
.
Trie
)
)
{
t
.
Errorf
(
"block #%d [%x]: receipts mismatch: fastdb %v, ancientdb %v, archivedb %v"
,
num
,
hash
,
freceipts
,
anreceipts
,
areceipts
)
}
}
...
...
core/genesis.go
View file @
87c0ba92
...
...
@@ -36,6 +36,7 @@ import (
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/rlp"
"github.com/ethereum/go-ethereum/trie"
)
//go:generate gencodec -type Genesis -field-override genesisSpecMarshaling -out gen_genesis.go
...
...
@@ -287,7 +288,7 @@ func (g *Genesis) ToBlock(db ethdb.Database) *types.Block {
statedb
.
Commit
(
false
)
statedb
.
Database
()
.
TrieDB
()
.
Commit
(
root
,
true
,
nil
)
return
types
.
NewBlock
(
head
,
nil
,
nil
,
nil
)
return
types
.
NewBlock
(
head
,
nil
,
nil
,
nil
,
new
(
trie
.
Trie
)
)
}
// Commit writes the block and state of a genesis specification to the database.
...
...
core/rawdb/accessors_chain_test.go
View file @
87c0ba92
...
...
@@ -84,7 +84,7 @@ func TestBodyStorage(t *testing.T) {
WriteBody
(
db
,
hash
,
0
,
body
)
if
entry
:=
ReadBody
(
db
,
hash
,
0
);
entry
==
nil
{
t
.
Fatalf
(
"Stored body not found"
)
}
else
if
types
.
DeriveSha
(
types
.
Transactions
(
entry
.
Transactions
)
)
!=
types
.
DeriveSha
(
types
.
Transactions
(
body
.
Transactions
))
||
types
.
CalcUncleHash
(
entry
.
Uncles
)
!=
types
.
CalcUncleHash
(
body
.
Uncles
)
{
}
else
if
types
.
DeriveSha
(
types
.
Transactions
(
entry
.
Transactions
)
,
newHasher
())
!=
types
.
DeriveSha
(
types
.
Transactions
(
body
.
Transactions
),
newHasher
(
))
||
types
.
CalcUncleHash
(
entry
.
Uncles
)
!=
types
.
CalcUncleHash
(
body
.
Uncles
)
{
t
.
Fatalf
(
"Retrieved body mismatch: have %v, want %v"
,
entry
,
body
)
}
if
entry
:=
ReadBodyRLP
(
db
,
hash
,
0
);
entry
==
nil
{
...
...
@@ -138,7 +138,7 @@ func TestBlockStorage(t *testing.T) {
}
if
entry
:=
ReadBody
(
db
,
block
.
Hash
(),
block
.
NumberU64
());
entry
==
nil
{
t
.
Fatalf
(
"Stored body not found"
)
}
else
if
types
.
DeriveSha
(
types
.
Transactions
(
entry
.
Transactions
)
)
!=
types
.
DeriveSha
(
block
.
Transactions
())
||
types
.
CalcUncleHash
(
entry
.
Uncles
)
!=
types
.
CalcUncleHash
(
block
.
Uncles
())
{
}
else
if
types
.
DeriveSha
(
types
.
Transactions
(
entry
.
Transactions
)
,
newHasher
())
!=
types
.
DeriveSha
(
block
.
Transactions
(),
newHasher
())
||
types
.
CalcUncleHash
(
entry
.
Uncles
)
!=
types
.
CalcUncleHash
(
block
.
Uncles
())
{
t
.
Fatalf
(
"Retrieved body mismatch: have %v, want %v"
,
entry
,
block
.
Body
())
}
// Delete the block and verify the execution
...
...
core/rawdb/accessors_indexes_test.go
View file @
87c0ba92
...
...
@@ -18,6 +18,7 @@ package rawdb
import
(
"bytes"
"hash"
"math/big"
"testing"
...
...
@@ -26,8 +27,33 @@ import (
"github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/rlp"
"golang.org/x/crypto/sha3"
)
// testHasher is the helper tool for transaction/receipt list hashing.
// The original hasher is trie, in order to get rid of import cycle,
// use the testing hasher instead.
type
testHasher
struct
{
hasher
hash
.
Hash
}
func
newHasher
()
*
testHasher
{
return
&
testHasher
{
hasher
:
sha3
.
NewLegacyKeccak256
()}
}
func
(
h
*
testHasher
)
Reset
()
{
h
.
hasher
.
Reset
()
}
func
(
h
*
testHasher
)
Update
(
key
,
val
[]
byte
)
{
h
.
hasher
.
Write
(
key
)
h
.
hasher
.
Write
(
val
)
}
func
(
h
*
testHasher
)
Hash
()
common
.
Hash
{
return
common
.
BytesToHash
(
h
.
hasher
.
Sum
(
nil
))
}
// Tests that positional lookup metadata can be stored and retrieved.
func
TestLookupStorage
(
t
*
testing
.
T
)
{
tests
:=
[]
struct
{
...
...
@@ -73,7 +99,7 @@ func TestLookupStorage(t *testing.T) {
tx3
:=
types
.
NewTransaction
(
3
,
common
.
BytesToAddress
([]
byte
{
0x33
}),
big
.
NewInt
(
333
),
3333
,
big
.
NewInt
(
33333
),
[]
byte
{
0x33
,
0x33
,
0x33
})
txs
:=
[]
*
types
.
Transaction
{
tx1
,
tx2
,
tx3
}
block
:=
types
.
NewBlock
(
&
types
.
Header
{
Number
:
big
.
NewInt
(
314
)},
txs
,
nil
,
nil
)
block
:=
types
.
NewBlock
(
&
types
.
Header
{
Number
:
big
.
NewInt
(
314
)},
txs
,
nil
,
nil
,
newHasher
()
)
// Check that no transactions entries are in a pristine database
for
i
,
tx
:=
range
txs
{
...
...
core/rawdb/accessors_metadata.go
View file @
87c0ba92
...
...
@@ -79,20 +79,3 @@ func WriteChainConfig(db ethdb.KeyValueWriter, hash common.Hash, cfg *params.Cha
log
.
Crit
(
"Failed to store chain config"
,
"err"
,
err
)
}
}
// ReadPreimage retrieves a single preimage of the provided hash.
func
ReadPreimage
(
db
ethdb
.
KeyValueReader
,
hash
common
.
Hash
)
[]
byte
{
data
,
_
:=
db
.
Get
(
preimageKey
(
hash
))
return
data
}
// WritePreimages writes the provided set of preimages to the database.
func
WritePreimages
(
db
ethdb
.
KeyValueWriter
,
preimages
map
[
common
.
Hash
][]
byte
)
{
for
hash
,
preimage
:=
range
preimages
{
if
err
:=
db
.
Put
(
preimageKey
(
hash
),
preimage
);
err
!=
nil
{
log
.
Crit
(
"Failed to store trie preimage"
,
"err"
,
err
)
}
}
preimageCounter
.
Inc
(
int64
(
len
(
preimages
)))
preimageHitCounter
.
Inc
(
int64
(
len
(
preimages
)))
}
core/rawdb/accessors_state.go
0 → 100644
View file @
87c0ba92
// Copyright 2020 The go-ethereum Authors
// This file is part of the go-ethereum library.
//
// The go-ethereum library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// The go-ethereum library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
package
rawdb
import
(
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/log"
)
// ReadPreimage retrieves a single preimage of the provided hash.
func
ReadPreimage
(
db
ethdb
.
KeyValueReader
,
hash
common
.
Hash
)
[]
byte
{
data
,
_
:=
db
.
Get
(
preimageKey
(
hash
))
return
data
}
// WritePreimages writes the provided set of preimages to the database.
func
WritePreimages
(
db
ethdb
.
KeyValueWriter
,
preimages
map
[
common
.
Hash
][]
byte
)
{
for
hash
,
preimage
:=
range
preimages
{
if
err
:=
db
.
Put
(
preimageKey
(
hash
),
preimage
);
err
!=
nil
{
log
.
Crit
(
"Failed to store trie preimage"
,
"err"
,
err
)
}
}
preimageCounter
.
Inc
(
int64
(
len
(
preimages
)))
preimageHitCounter
.
Inc
(
int64
(
len
(
preimages
)))
}
// ReadCode retrieves the contract code of the provided code hash.
func
ReadCode
(
db
ethdb
.
KeyValueReader
,
hash
common
.
Hash
)
[]
byte
{
// Try with the legacy code scheme first, if not then try with current
// scheme. Since most of the code will be found with legacy scheme.
//
// todo(rjl493456442) change the order when we forcibly upgrade the code
// scheme with snapshot.
data
,
_
:=
db
.
Get
(
hash
[
:
])
if
len
(
data
)
!=
0
{
return
data
}
return
ReadCodeWithPrefix
(
db
,
hash
)
}
// ReadCodeWithPrefix retrieves the contract code of the provided code hash.
// The main difference between this function and ReadCode is this function
// will only check the existence with latest scheme(with prefix).
func
ReadCodeWithPrefix
(
db
ethdb
.
KeyValueReader
,
hash
common
.
Hash
)
[]
byte
{
data
,
_
:=
db
.
Get
(
codeKey
(
hash
))
return
data
}
// WriteCode writes the provided contract code database.
func
WriteCode
(
db
ethdb
.
KeyValueWriter
,
hash
common
.
Hash
,
code
[]
byte
)
{
if
err
:=
db
.
Put
(
codeKey
(
hash
),
code
);
err
!=
nil
{
log
.
Crit
(
"Failed to store contract code"
,
"err"
,
err
)
}
}
// DeleteCode deletes the specified contract code from the database.
func
DeleteCode
(
db
ethdb
.
KeyValueWriter
,
hash
common
.
Hash
)
{
if
err
:=
db
.
Delete
(
codeKey
(
hash
));
err
!=
nil
{
log
.
Crit
(
"Failed to delete contract code"
,
"err"
,
err
)
}
}
// ReadTrieNode retrieves the trie node of the provided hash.
func
ReadTrieNode
(
db
ethdb
.
KeyValueReader
,
hash
common
.
Hash
)
[]
byte
{
data
,
_
:=
db
.
Get
(
hash
.
Bytes
())
return
data
}
// WriteTrieNode writes the provided trie node database.
func
WriteTrieNode
(
db
ethdb
.
KeyValueWriter
,
hash
common
.
Hash
,
node
[]
byte
)
{
if
err
:=
db
.
Put
(
hash
.
Bytes
(),
node
);
err
!=
nil
{
log
.
Crit
(
"Failed to store trie node"
,
"err"
,
err
)
}
}
// DeleteTrieNode deletes the specified trie node from the database.
func
DeleteTrieNode
(
db
ethdb
.
KeyValueWriter
,
hash
common
.
Hash
)
{
if
err
:=
db
.
Delete
(
hash
.
Bytes
());
err
!=
nil
{
log
.
Crit
(
"Failed to delete trie node"
,
"err"
,
err
)
}
}
core/rawdb/chain_iterator_test.go
View file @
87c0ba92
...
...
@@ -34,11 +34,11 @@ func TestChainIterator(t *testing.T) {
var
txs
[]
*
types
.
Transaction
for
i
:=
uint64
(
0
);
i
<=
10
;
i
++
{
if
i
==
0
{
block
=
types
.
NewBlock
(
&
types
.
Header
{
Number
:
big
.
NewInt
(
int64
(
i
))},
nil
,
nil
,
nil
)
// Empty genesis block
block
=
types
.
NewBlock
(
&
types
.
Header
{
Number
:
big
.
NewInt
(
int64
(
i
))},
nil
,
nil
,
nil
,
newHasher
()
)
// Empty genesis block
}
else
{
tx
:=
types
.
NewTransaction
(
i
,
common
.
BytesToAddress
([]
byte
{
0x11
}),
big
.
NewInt
(
111
),
1111
,
big
.
NewInt
(
11111
),
[]
byte
{
0x11
,
0x11
,
0x11
})
txs
=
append
(
txs
,
tx
)
block
=
types
.
NewBlock
(
&
types
.
Header
{
Number
:
big
.
NewInt
(
int64
(
i
))},
[]
*
types
.
Transaction
{
tx
},
nil
,
nil
)
block
=
types
.
NewBlock
(
&
types
.
Header
{
Number
:
big
.
NewInt
(
int64
(
i
))},
[]
*
types
.
Transaction
{
tx
},
nil
,
nil
,
newHasher
()
)
}
WriteBlock
(
chainDb
,
block
)
WriteCanonicalHash
(
chainDb
,
block
.
Hash
(),
block
.
NumberU64
())
...
...
core/rawdb/database.go
View file @
87c0ba92
...
...
@@ -258,6 +258,7 @@ func InspectDatabase(db ethdb.Database) error {
numHashPairing
common
.
StorageSize
hashNumPairing
common
.
StorageSize
trieSize
common
.
StorageSize
codeSize
common
.
StorageSize
txlookupSize
common
.
StorageSize
accountSnapSize
common
.
StorageSize
storageSnapSize
common
.
StorageSize
...
...
@@ -316,6 +317,8 @@ func InspectDatabase(db ethdb.Database) error {
chtTrieNodes
+=
size
case
bytes
.
HasPrefix
(
key
,
[]
byte
(
"blt-"
))
&&
len
(
key
)
==
4
+
common
.
HashLength
:
bloomTrieNodes
+=
size
case
bytes
.
HasPrefix
(
key
,
codePrefix
)
&&
len
(
key
)
==
len
(
codePrefix
)
+
common
.
HashLength
:
codeSize
+=
size
case
len
(
key
)
==
common
.
HashLength
:
trieSize
+=
size
default
:
...
...
@@ -355,6 +358,7 @@ func InspectDatabase(db ethdb.Database) error {
{
"Key-Value store"
,
"Block hash->number"
,
hashNumPairing
.
String
()},
{
"Key-Value store"
,
"Transaction index"
,
txlookupSize
.
String
()},
{
"Key-Value store"
,
"Bloombit index"
,
bloomBitsSize
.
String
()},
{
"Key-Value store"
,
"Contract codes"
,
codeSize
.
String
()},
{
"Key-Value store"
,
"Trie nodes"
,
trieSize
.
String
()},
{
"Key-Value store"
,
"Trie preimages"
,
preimageSize
.
String
()},
{
"Key-Value store"
,
"Account snapshot"
,
accountSnapSize
.
String
()},
...
...
core/rawdb/schema.go
View file @
87c0ba92
...
...
@@ -18,6 +18,7 @@
package
rawdb
import
(
"bytes"
"encoding/binary"
"github.com/ethereum/go-ethereum/common"
...
...
@@ -69,6 +70,7 @@ var (
bloomBitsPrefix
=
[]
byte
(
"B"
)
// bloomBitsPrefix + bit (uint16 big endian) + section (uint64 big endian) + hash -> bloom bits
SnapshotAccountPrefix
=
[]
byte
(
"a"
)
// SnapshotAccountPrefix + account hash -> account trie value
SnapshotStoragePrefix
=
[]
byte
(
"o"
)
// SnapshotStoragePrefix + account hash + storage hash -> storage trie value
codePrefix
=
[]
byte
(
"c"
)
// codePrefix + code hash -> account code
preimagePrefix
=
[]
byte
(
"secure-key-"
)
// preimagePrefix + hash -> preimage
configPrefix
=
[]
byte
(
"ethereum-config-"
)
// config prefix for the db
...
...
@@ -192,6 +194,20 @@ func preimageKey(hash common.Hash) []byte {
return
append
(
preimagePrefix
,
hash
.
Bytes
()
...
)
}
// codeKey = codePrefix + hash
func
codeKey
(
hash
common
.
Hash
)
[]
byte
{
return
append
(
codePrefix
,
hash
.
Bytes
()
...
)
}
// IsCodeKey reports whether the given byte slice is the key of contract code,
// if so return the raw code hash as well.
func
IsCodeKey
(
key
[]
byte
)
(
bool
,
[]
byte
)
{
if
bytes
.
HasPrefix
(
key
,
codePrefix
)
&&
len
(
key
)
==
common
.
HashLength
+
len
(
codePrefix
)
{
return
true
,
key
[
len
(
codePrefix
)
:
]
}
return
false
,
nil
}
// configKey = configPrefix + hash
func
configKey
(
hash
common
.
Hash
)
[]
byte
{
return
append
(
configPrefix
,
hash
.
Bytes
()
...
)
...
...
core/state/database.go
View file @
87c0ba92
...
...
@@ -17,9 +17,12 @@
package
state
import
(
"errors"
"fmt"
"github.com/VictoriaMetrics/fastcache"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/rawdb"
"github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/trie"
lru
"github.com/hashicorp/golang-lru"
...
...
@@ -28,6 +31,9 @@ import (
const
(
// Number of codehash->size associations to keep.
codeSizeCacheSize
=
100000
// Cache size granted for caching clean code.
codeCacheSize
=
64
*
1024
*
1024
)
// Database wraps access to tries and contract code.
...
...
@@ -111,12 +117,14 @@ func NewDatabaseWithCache(db ethdb.Database, cache int, journal string) Database
return
&
cachingDB
{
db
:
trie
.
NewDatabaseWithCache
(
db
,
cache
,
journal
),
codeSizeCache
:
csc
,
codeCache
:
fastcache
.
New
(
codeCacheSize
),
}
}
type
cachingDB
struct
{
db
*
trie
.
Database
codeSizeCache
*
lru
.
Cache
codeCache
*
fastcache
.
Cache
}
// OpenTrie opens the main account trie at a specific root hash.
...
...
@@ -141,11 +149,32 @@ func (db *cachingDB) CopyTrie(t Trie) Trie {
// ContractCode retrieves a particular contract's code.
func
(
db
*
cachingDB
)
ContractCode
(
addrHash
,
codeHash
common
.
Hash
)
([]
byte
,
error
)
{
code
,
err
:=
db
.
db
.
Node
(
codeHash
)
if
err
==
nil
{
if
code
:=
db
.
codeCache
.
Get
(
nil
,
codeHash
.
Bytes
());
len
(
code
)
>
0
{
return
code
,
nil
}
code
:=
rawdb
.
ReadCode
(
db
.
db
.
DiskDB
(),
codeHash
)
if
len
(
code
)
>
0
{
db
.
codeCache
.
Set
(
codeHash
.
Bytes
(),
code
)
db
.
codeSizeCache
.
Add
(
codeHash
,
len
(
code
))
return
code
,
nil
}
return
nil
,
errors
.
New
(
"not found"
)
}
// ContractCodeWithPrefix retrieves a particular contract's code. If the
// code can't be found in the cache, then check the existence with **new**
// db scheme.
func
(
db
*
cachingDB
)
ContractCodeWithPrefix
(
addrHash
,
codeHash
common
.
Hash
)
([]
byte
,
error
)
{
if
code
:=
db
.
codeCache
.
Get
(
nil
,
codeHash
.
Bytes
());
len
(
code
)
>
0
{
return
code
,
nil
}
code
:=
rawdb
.
ReadCodeWithPrefix
(
db
.
db
.
DiskDB
(),
codeHash
)
if
len
(
code
)
>
0
{
db
.
codeCache
.
Set
(
codeHash
.
Bytes
(),
code
)
db
.
codeSizeCache
.
Add
(
codeHash
,
len
(
code
))
return
code
,
nil
}
return
code
,
err
return
nil
,
errors
.
New
(
"not found"
)
}
// ContractCodeSize retrieves a particular contracts code's size.
...
...
core/state/iterator_test.go
View file @
87c0ba92
...
...
@@ -28,6 +28,7 @@ import (
func
TestNodeIteratorCoverage
(
t
*
testing
.
T
)
{
// Create some arbitrary test state to iterate
db
,
root
,
_
:=
makeTestState
()
db
.
TrieDB
()
.
Commit
(
root
,
false
,
nil
)
state
,
err
:=
New
(
root
,
db
,
nil
)
if
err
!=
nil
{
...
...
@@ -42,7 +43,10 @@ func TestNodeIteratorCoverage(t *testing.T) {
}
// Cross check the iterated hashes and the database/nodepool content
for
hash
:=
range
hashes
{
if
_
,
err
:=
db
.
TrieDB
()
.
Node
(
hash
);
err
!=
nil
{
if
_
,
err
=
db
.
TrieDB
()
.
Node
(
hash
);
err
!=
nil
{
_
,
err
=
db
.
ContractCode
(
common
.
Hash
{},
hash
)
}
if
err
!=
nil
{
t
.
Errorf
(
"failed to retrieve reported node %x"
,
hash
)
}
}
...
...
core/state/statedb.go
View file @
87c0ba92
...
...
@@ -25,6 +25,7 @@ import (
"time"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/rawdb"
"github.com/ethereum/go-ethereum/core/state/snapshot"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/crypto"
...
...
@@ -42,9 +43,6 @@ type revision struct {
var
(
// emptyRoot is the known root hash of an empty trie.
emptyRoot
=
common
.
HexToHash
(
"56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421"
)
// emptyCode is the known hash of the empty EVM bytecode.
emptyCode
=
crypto
.
Keccak256Hash
(
nil
)
)
type
proofList
[][]
byte
...
...
@@ -589,7 +587,10 @@ func (s *StateDB) createObject(addr common.Address) (newobj, prev *stateObject)
s
.
journal
.
append
(
resetObjectChange
{
prev
:
prev
,
prevdestruct
:
prevdestruct
})
}
s
.
setStateObject
(
newobj
)
return
newobj
,
prev
if
prev
!=
nil
&&
!
prev
.
deleted
{
return
newobj
,
prev
}
return
newobj
,
nil
}
// CreateAccount explicitly creates a state object. If a state object with the address
...
...
@@ -816,11 +817,12 @@ func (s *StateDB) Commit(deleteEmptyObjects bool) (common.Hash, error) {
s
.
IntermediateRoot
(
deleteEmptyObjects
)
// Commit objects to the trie, measuring the elapsed time
codeWriter
:=
s
.
db
.
TrieDB
()
.
DiskDB
()
.
NewBatch
()
for
addr
:=
range
s
.
stateObjectsDirty
{
if
obj
:=
s
.
stateObjects
[
addr
];
!
obj
.
deleted
{
// Write any contract code associated with the state object
if
obj
.
code
!=
nil
&&
obj
.
dirtyCode
{
s
.
db
.
TrieDB
()
.
InsertBlob
(
common
.
BytesToHash
(
obj
.
CodeHash
()),
obj
.
code
)
rawdb
.
WriteCode
(
codeWriter
,
common
.
BytesToHash
(
obj
.
CodeHash
()),
obj
.
code
)
obj
.
dirtyCode
=
false
}
// Write any storage changes in the state object to its storage trie
...
...
@@ -832,6 +834,11 @@ func (s *StateDB) Commit(deleteEmptyObjects bool) (common.Hash, error) {
if
len
(
s
.
stateObjectsDirty
)
>
0
{
s
.
stateObjectsDirty
=
make
(
map
[
common
.
Address
]
struct
{})
}
if
codeWriter
.
ValueSize
()
>
0
{
if
err
:=
codeWriter
.
Write
();
err
!=
nil
{
log
.
Crit
(
"Failed to commit dirty codes"
,
"error"
,
err
)
}
}
// Write the account trie changes, measuing the amount of wasted time
var
start
time
.
Time
if
metrics
.
EnabledExpensive
{
...
...
@@ -847,10 +854,6 @@ func (s *StateDB) Commit(deleteEmptyObjects bool) (common.Hash, error) {
if
account
.
Root
!=
emptyRoot
{
s
.
db
.
TrieDB
()
.
Reference
(
account
.
Root
,
parent
)
}
code
:=
common
.
BytesToHash
(
account
.
CodeHash
)
if
code
!=
emptyCode
{
s
.
db
.
TrieDB
()
.
Reference
(
code
,
parent
)
}
return
nil
})
if
metrics
.
EnabledExpensive
{
...
...
core/state/sync.go
View file @
87c0ba92
...
...
@@ -34,7 +34,7 @@ func NewStateSync(root common.Hash, database ethdb.KeyValueReader, bloom *trie.S
return
err
}
syncer
.
AddSubTrie
(
obj
.
Root
,
64
,
parent
,
nil
)
syncer
.
Add
Raw
Entry
(
common
.
BytesToHash
(
obj
.
CodeHash
),
64
,
parent
)
syncer
.
Add
Code
Entry
(
common
.
BytesToHash
(
obj
.
CodeHash
),
64
,
parent
)
return
nil
}
syncer
=
trie
.
NewSync
(
root
,
database
,
callback
,
bloom
)
...
...
core/state/sync_test.go
View file @
87c0ba92
...
...
@@ -133,13 +133,17 @@ func TestEmptyStateSync(t *testing.T) {
// Tests that given a root hash, a state can sync iteratively on a single thread,
// requesting retrieval tasks and returning all of them in one go.
func
TestIterativeStateSyncIndividual
(
t
*
testing
.
T
)
{
testIterativeStateSync
(
t
,
1
)
}
func
TestIterativeStateSyncBatched
(
t
*
testing
.
T
)
{
testIterativeStateSync
(
t
,
100
)
}
func
TestIterativeStateSyncIndividual
(
t
*
testing
.
T
)
{
testIterativeStateSync
(
t
,
1
,
false
)
}
func
TestIterativeStateSyncBatched
(
t
*
testing
.
T
)
{
testIterativeStateSync
(
t
,
100
,
false
)
}
func
TestIterativeStateSyncIndividualFromDisk
(
t
*
testing
.
T
)
{
testIterativeStateSync
(
t
,
1
,
true
)
}
func
TestIterativeStateSyncBatchedFromDisk
(
t
*
testing
.
T
)
{
testIterativeStateSync
(
t
,
100
,
true
)
}
func
testIterativeStateSync
(
t
*
testing
.
T
,
count
int
)
{
func
testIterativeStateSync
(
t
*
testing
.
T
,
count
int
,
commit
bool
)
{
// Create a random state to copy
srcDb
,
srcRoot
,
srcAccounts
:=
makeTestState
()
if
commit
{
srcDb
.
TrieDB
()
.
Commit
(
srcRoot
,
false
,
nil
)
}
// Create a destination state and sync with the scheduler
dstDb
:=
rawdb
.
NewMemoryDatabase
()
sched
:=
NewStateSync
(
srcRoot
,
dstDb
,
trie
.
NewSyncBloom
(
1
,
dstDb
))
...
...
@@ -149,13 +153,18 @@ func testIterativeStateSync(t *testing.T, count int) {
results
:=
make
([]
trie
.
SyncResult
,
len
(
queue
))
for
i
,
hash
:=
range
queue
{
data
,
err
:=
srcDb
.
TrieDB
()
.
Node
(
hash
)
if
err
!=
nil
{
data
,
err
=
srcDb
.
ContractCode
(
common
.
Hash
{},
hash
)
}
if
err
!=
nil
{
t
.
Fatalf
(
"failed to retrieve node data for %x"
,
hash
)
}
results
[
i
]
=
trie
.
SyncResult
{
Hash
:
hash
,
Data
:
data
}
}
if
_
,
index
,
err
:=
sched
.
Process
(
results
);
err
!=
nil
{
t
.
Fatalf
(
"failed to process result #%d: %v"
,
index
,
err
)
for
_
,
result
:=
range
results
{
if
err
:=
sched
.
Process
(
result
);
err
!=
nil
{
t
.
Fatalf
(
"failed to process result %v"
,
err
)
}
}
batch
:=
dstDb
.
NewBatch
()
if
err
:=
sched
.
Commit
(
batch
);
err
!=
nil
{
...
...
@@ -184,13 +193,18 @@ func TestIterativeDelayedStateSync(t *testing.T) {
results
:=
make
([]
trie
.
SyncResult
,
len
(
queue
)
/
2
+
1
)
for
i
,
hash
:=
range
queue
[
:
len
(
results
)]
{
data
,
err
:=
srcDb
.
TrieDB
()
.
Node
(
hash
)
if
err
!=
nil
{
data
,
err
=
srcDb
.
ContractCode
(
common
.
Hash
{},
hash
)
}
if
err
!=
nil
{
t
.
Fatalf
(
"failed to retrieve node data for %x"
,
hash
)
}
results
[
i
]
=
trie
.
SyncResult
{
Hash
:
hash
,
Data
:
data
}
}
if
_
,
index
,
err
:=
sched
.
Process
(
results
);
err
!=
nil
{
t
.
Fatalf
(
"failed to process result #%d: %v"
,
index
,
err
)
for
_
,
result
:=
range
results
{
if
err
:=
sched
.
Process
(
result
);
err
!=
nil
{
t
.
Fatalf
(
"failed to process result %v"
,
err
)
}
}
batch
:=
dstDb
.
NewBatch
()
if
err
:=
sched
.
Commit
(
batch
);
err
!=
nil
{
...
...
@@ -226,14 +240,19 @@ func testIterativeRandomStateSync(t *testing.T, count int) {
results
:=
make
([]
trie
.
SyncResult
,
0
,
len
(
queue
))
for
hash
:=
range
queue
{
data
,
err
:=
srcDb
.
TrieDB
()
.
Node
(
hash
)
if
err
!=
nil
{
data
,
err
=
srcDb
.
ContractCode
(
common
.
Hash
{},
hash
)
}
if
err
!=
nil
{
t
.
Fatalf
(
"failed to retrieve node data for %x"
,
hash
)
}
results
=
append
(
results
,
trie
.
SyncResult
{
Hash
:
hash
,
Data
:
data
})
}
// Feed the retrieved results back and queue new tasks
if
_
,
index
,
err
:=
sched
.
Process
(
results
);
err
!=
nil
{
t
.
Fatalf
(
"failed to process result #%d: %v"
,
index
,
err
)
for
_
,
result
:=
range
results
{
if
err
:=
sched
.
Process
(
result
);
err
!=
nil
{
t
.
Fatalf
(
"failed to process result %v"
,
err
)
}
}
batch
:=
dstDb
.
NewBatch
()
if
err
:=
sched
.
Commit
(
batch
);
err
!=
nil
{
...
...
@@ -270,6 +289,9 @@ func TestIterativeRandomDelayedStateSync(t *testing.T) {
delete
(
queue
,
hash
)
data
,
err
:=
srcDb
.
TrieDB
()
.
Node
(
hash
)
if
err
!=
nil
{
data
,
err
=
srcDb
.
ContractCode
(
common
.
Hash
{},
hash
)
}
if
err
!=
nil
{
t
.
Fatalf
(
"failed to retrieve node data for %x"
,
hash
)
}
...
...
@@ -280,8 +302,10 @@ func TestIterativeRandomDelayedStateSync(t *testing.T) {
}
}
// Feed the retrieved results back and queue new tasks
if
_
,
index
,
err
:=
sched
.
Process
(
results
);
err
!=
nil
{
t
.
Fatalf
(
"failed to process result #%d: %v"
,
index
,
err
)
for
_
,
result
:=
range
results
{
if
err
:=
sched
.
Process
(
result
);
err
!=
nil
{
t
.
Fatalf
(
"failed to process result %v"
,
err
)
}
}
batch
:=
dstDb
.
NewBatch
()
if
err
:=
sched
.
Commit
(
batch
);
err
!=
nil
{
...
...
@@ -302,6 +326,15 @@ func TestIncompleteStateSync(t *testing.T) {
// Create a random state to copy
srcDb
,
srcRoot
,
srcAccounts
:=
makeTestState
()
// isCode reports whether the hash is contract code hash.
isCode
:=
func
(
hash
common
.
Hash
)
bool
{
for
_
,
acc
:=
range
srcAccounts
{
if
hash
==
crypto
.
Keccak256Hash
(
acc
.
code
)
{
return
true
}
}
return
false
}
checkTrieConsistency
(
srcDb
.
TrieDB
()
.
DiskDB
()
.
(
ethdb
.
Database
),
srcRoot
)
// Create a destination state and sync with the scheduler
...
...
@@ -315,14 +348,19 @@ func TestIncompleteStateSync(t *testing.T) {
results
:=
make
([]
trie
.
SyncResult
,
len
(
queue
))
for
i
,
hash
:=
range
queue
{
data
,
err
:=
srcDb
.
TrieDB
()
.
Node
(
hash
)
if
err
!=
nil
{
data
,
err
=
srcDb
.
ContractCode
(
common
.
Hash
{},
hash
)
}
if
err
!=
nil
{
t
.
Fatalf
(
"failed to retrieve node data for %x"
,
hash
)
}
results
[
i
]
=
trie
.
SyncResult
{
Hash
:
hash
,
Data
:
data
}
}
// Process each of the state nodes
if
_
,
index
,
err
:=
sched
.
Process
(
results
);
err
!=
nil
{
t
.
Fatalf
(
"failed to process result #%d: %v"
,
index
,
err
)
for
_
,
result
:=
range
results
{
if
err
:=
sched
.
Process
(
result
);
err
!=
nil
{
t
.
Fatalf
(
"failed to process result %v"
,
err
)
}
}
batch
:=
dstDb
.
NewBatch
()
if
err
:=
sched
.
Commit
(
batch
);
err
!=
nil
{
...
...
@@ -333,12 +371,9 @@ func TestIncompleteStateSync(t *testing.T) {
added
=
append
(
added
,
result
.
Hash
)
}
// Check that all known sub-tries added so far are complete or missing entirely.
checkSubtries
:
for
_
,
hash
:=
range
added
{
for
_
,
acc
:=
range
srcAccounts
{
if
hash
==
crypto
.
Keccak256Hash
(
acc
.
code
)
{
continue
checkSubtries
// skip trie check of code nodes.
}
if
isCode
(
hash
)
{
continue
}
// Can't use checkStateConsistency here because subtrie keys may have odd
// length and crash in LeafKey.
...
...
@@ -351,13 +386,25 @@ func TestIncompleteStateSync(t *testing.T) {
}
// Sanity check that removing any node from the database is detected
for
_
,
node
:=
range
added
[
1
:
]
{
key
:=
node
.
Bytes
()
value
,
_
:=
dstDb
.
Get
(
key
)
dstDb
.
Delete
(
key
)
var
(
key
=
node
.
Bytes
()
code
=
isCode
(
node
)
val
[]
byte
)
if
code
{
val
=
rawdb
.
ReadCode
(
dstDb
,
node
)
rawdb
.
DeleteCode
(
dstDb
,
node
)
}
else
{
val
=
rawdb
.
ReadTrieNode
(
dstDb
,
node
)
rawdb
.
DeleteTrieNode
(
dstDb
,
node
)
}
if
err
:=
checkStateConsistency
(
dstDb
,
added
[
0
]);
err
==
nil
{
t
.
Fatalf
(
"trie inconsistency not caught, missing: %x"
,
key
)
}
dstDb
.
Put
(
key
,
value
)
if
code
{
rawdb
.
WriteCode
(
dstDb
,
node
,
val
)
}
else
{
rawdb
.
WriteTrieNode
(
dstDb
,
node
,
val
)
}
}
}
core/tx_pool_test.go
View file @
87c0ba92
...
...
@@ -34,6 +34,7 @@ import (
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/event"
"github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/trie"
)
// testTxPoolConfig is a transaction pool configuration without stateful disk
...
...
@@ -54,7 +55,7 @@ type testBlockChain struct {
func
(
bc
*
testBlockChain
)
CurrentBlock
()
*
types
.
Block
{
return
types
.
NewBlock
(
&
types
.
Header
{
GasLimit
:
bc
.
gasLimit
,
},
nil
,
nil
,
nil
)
},
nil
,
nil
,
nil
,
new
(
trie
.
Trie
)
)
}
func
(
bc
*
testBlockChain
)
GetBlock
(
hash
common
.
Hash
,
number
uint64
)
*
types
.
Block
{
...
...
core/types/block.go
View file @
87c0ba92
...
...
@@ -35,7 +35,7 @@ import (
)
var
(
EmptyRootHash
=
DeriveSha
(
Transactions
{}
)
EmptyRootHash
=
common
.
HexToHash
(
"56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421"
)
EmptyUncleHash
=
rlpHash
([]
*
Header
(
nil
))
)
...
...
@@ -221,14 +221,14 @@ type storageblock struct {
// The values of TxHash, UncleHash, ReceiptHash and Bloom in header
// are ignored and set to values derived from the given txs, uncles
// and receipts.
func
NewBlock
(
header
*
Header
,
txs
[]
*
Transaction
,
uncles
[]
*
Header
,
receipts
[]
*
Receipt
)
*
Block
{
func
NewBlock
(
header
*
Header
,
txs
[]
*
Transaction
,
uncles
[]
*
Header
,
receipts
[]
*
Receipt
,
hasher
Hasher
)
*
Block
{
b
:=
&
Block
{
header
:
CopyHeader
(
header
),
td
:
new
(
big
.
Int
)}
// TODO: panic if len(txs) != len(receipts)
if
len
(
txs
)
==
0
{
b
.
header
.
TxHash
=
EmptyRootHash
}
else
{
b
.
header
.
TxHash
=
DeriveSha
(
Transactions
(
txs
))
b
.
header
.
TxHash
=
DeriveSha
(
Transactions
(
txs
)
,
hasher
)
b
.
transactions
=
make
(
Transactions
,
len
(
txs
))
copy
(
b
.
transactions
,
txs
)
}
...
...
@@ -236,7 +236,7 @@ func NewBlock(header *Header, txs []*Transaction, uncles []*Header, receipts []*
if
len
(
receipts
)
==
0
{
b
.
header
.
ReceiptHash
=
EmptyRootHash
}
else
{
b
.
header
.
ReceiptHash
=
DeriveSha
(
Receipts
(
receipts
))
b
.
header
.
ReceiptHash
=
DeriveSha
(
Receipts
(
receipts
)
,
hasher
)
b
.
header
.
Bloom
=
CreateBloom
(
receipts
)
}
...
...
core/types/block_test.go
View file @
87c0ba92
...
...
@@ -18,6 +18,7 @@ package types
import
(
"bytes"
"hash"
"math/big"
"reflect"
"testing"
...
...
@@ -27,6 +28,7 @@ import (
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/rlp"
"golang.org/x/crypto/sha3"
)
// from bcValidBlockTest.json, "SimpleTx"
...
...
@@ -90,6 +92,30 @@ func BenchmarkEncodeBlock(b *testing.B) {
}
}
// testHasher is the helper tool for transaction/receipt list hashing.
// The original hasher is trie, in order to get rid of import cycle,
// use the testing hasher instead.
type
testHasher
struct
{
hasher
hash
.
Hash
}
func
newHasher
()
*
testHasher
{
return
&
testHasher
{
hasher
:
sha3
.
NewLegacyKeccak256
()}
}
func
(
h
*
testHasher
)
Reset
()
{
h
.
hasher
.
Reset
()
}
func
(
h
*
testHasher
)
Update
(
key
,
val
[]
byte
)
{
h
.
hasher
.
Write
(
key
)
h
.
hasher
.
Write
(
val
)
}
func
(
h
*
testHasher
)
Hash
()
common
.
Hash
{
return
common
.
BytesToHash
(
h
.
hasher
.
Sum
(
nil
))
}
func
makeBenchBlock
()
*
Block
{
var
(
key
,
_
=
crypto
.
GenerateKey
()
...
...
@@ -128,5 +154,5 @@ func makeBenchBlock() *Block {
Extra
:
[]
byte
(
"benchmark uncle"
),
}
}
return
NewBlock
(
header
,
txs
,
uncles
,
receipts
)
return
NewBlock
(
header
,
txs
,
uncles
,
receipts
,
newHasher
()
)
}
core/types/derive_sha.go
View file @
87c0ba92
...
...
@@ -21,21 +21,28 @@ import (
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/rlp"
"github.com/ethereum/go-ethereum/trie"
)
// DerivableList is the interface which can derive the hash.
type
DerivableList
interface
{
Len
()
int
GetRlp
(
i
int
)
[]
byte
}
func
DeriveSha
(
list
DerivableList
)
common
.
Hash
{
// Hasher is the tool used to calculate the hash of derivable list.
type
Hasher
interface
{
Reset
()
Update
([]
byte
,
[]
byte
)
Hash
()
common
.
Hash
}
func
DeriveSha
(
list
DerivableList
,
hasher
Hasher
)
common
.
Hash
{
hasher
.
Reset
()
keybuf
:=
new
(
bytes
.
Buffer
)
trie
:=
new
(
trie
.
Trie
)
for
i
:=
0
;
i
<
list
.
Len
();
i
++
{
keybuf
.
Reset
()
rlp
.
Encode
(
keybuf
,
uint
(
i
))
trie
.
Update
(
keybuf
.
Bytes
(),
list
.
GetRlp
(
i
))
hasher
.
Update
(
keybuf
.
Bytes
(),
list
.
GetRlp
(
i
))
}
return
trie
.
Hash
()
return
hasher
.
Hash
()
}
eth/downloader/downloader.go
View file @
87c0ba92
...
...
@@ -109,7 +109,7 @@ type Downloader struct {
peers
*
peerSet
// Set of active peers from which download can proceed
stateDB
ethdb
.
Database
// Database to state sync into (and deduplicate via)
stateBloom
*
trie
.
SyncBloom
// Bloom filter for fast trie node existence checks
stateBloom
*
trie
.
SyncBloom
// Bloom filter for fast trie node
and contract code
existence checks
// Statistics
syncStatsChainOrigin
uint64
// Origin block number where syncing started at
...
...
eth/downloader/queue.go
View file @
87c0ba92
...
...
@@ -31,6 +31,7 @@ import (
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/metrics"
"github.com/ethereum/go-ethereum/trie"
)
const
(
...
...
@@ -771,7 +772,7 @@ func (q *queue) DeliverBodies(id string, txLists [][]*types.Transaction, uncleLi
q
.
lock
.
Lock
()
defer
q
.
lock
.
Unlock
()
validate
:=
func
(
index
int
,
header
*
types
.
Header
)
error
{
if
types
.
DeriveSha
(
types
.
Transactions
(
txLists
[
index
]))
!=
header
.
TxHash
{
if
types
.
DeriveSha
(
types
.
Transactions
(
txLists
[
index
])
,
new
(
trie
.
Trie
)
)
!=
header
.
TxHash
{
return
errInvalidBody
}
if
types
.
CalcUncleHash
(
uncleLists
[
index
])
!=
header
.
UncleHash
{
...
...
@@ -796,7 +797,7 @@ func (q *queue) DeliverReceipts(id string, receiptList [][]*types.Receipt) (int,
q
.
lock
.
Lock
()
defer
q
.
lock
.
Unlock
()
validate
:=
func
(
index
int
,
header
*
types
.
Header
)
error
{
if
types
.
DeriveSha
(
types
.
Receipts
(
receiptList
[
index
]))
!=
header
.
ReceiptHash
{
if
types
.
DeriveSha
(
types
.
Receipts
(
receiptList
[
index
])
,
new
(
trie
.
Trie
)
)
!=
header
.
ReceiptHash
{
return
errInvalidReceipt
}
return
nil
...
...
eth/downloader/statesync.go
View file @
87c0ba92
...
...
@@ -474,7 +474,7 @@ func (s *stateSync) process(req *stateReq) (int, error) {
// Iterate over all the delivered data and inject one-by-one into the trie
for
_
,
blob
:=
range
req
.
response
{
_
,
hash
,
err
:=
s
.
processNodeData
(
blob
)
hash
,
err
:=
s
.
processNodeData
(
blob
)
switch
err
{
case
nil
:
s
.
numUncommitted
++
...
...
@@ -512,13 +512,13 @@ func (s *stateSync) process(req *stateReq) (int, error) {
// 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
)
{
func
(
s
*
stateSync
)
processNodeData
(
blob
[]
byte
)
(
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
err
:=
s
.
sched
.
Process
(
res
)
return
res
.
Hash
,
err
}
// updateStats bumps the various state sync progress counters and displays a log
...
...
eth/fetcher/block_fetcher.go
View file @
87c0ba92
...
...
@@ -28,6 +28,7 @@ import (
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/metrics"
"github.com/ethereum/go-ethereum/trie"
)
const
(
...
...
@@ -540,7 +541,7 @@ func (f *BlockFetcher) loop() {
announce
.
time
=
task
.
time
// If the block is empty (header only), short circuit into the final import queue
if
header
.
TxHash
==
types
.
DeriveSha
(
types
.
Transactions
{})
&&
header
.
UncleHash
==
types
.
CalcUncleHash
([]
*
types
.
Header
{})
{
if
header
.
TxHash
==
types
.
EmptyRootHash
&&
header
.
UncleHash
==
types
.
EmptyUncleHash
{
log
.
Trace
(
"Block empty, skipping body retrieval"
,
"peer"
,
announce
.
origin
,
"number"
,
header
.
Number
,
"hash"
,
header
.
Hash
())
block
:=
types
.
NewBlockWithHeader
(
header
)
...
...
@@ -619,7 +620,7 @@ func (f *BlockFetcher) loop() {
continue
}
if
txnHash
==
(
common
.
Hash
{})
{
txnHash
=
types
.
DeriveSha
(
types
.
Transactions
(
task
.
transactions
[
i
]))
txnHash
=
types
.
DeriveSha
(
types
.
Transactions
(
task
.
transactions
[
i
])
,
new
(
trie
.
Trie
)
)
}
if
txnHash
!=
announce
.
header
.
TxHash
{
continue
...
...
eth/fetcher/block_fetcher_test.go
View file @
87c0ba92
...
...
@@ -31,6 +31,7 @@ import (
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/trie"
)
var
(
...
...
@@ -38,7 +39,7 @@ var (
testKey
,
_
=
crypto
.
HexToECDSA
(
"b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291"
)
testAddress
=
crypto
.
PubkeyToAddress
(
testKey
.
PublicKey
)
genesis
=
core
.
GenesisBlockForTesting
(
testdb
,
testAddress
,
big
.
NewInt
(
1000000000
))
unknownBlock
=
types
.
NewBlock
(
&
types
.
Header
{
GasLimit
:
params
.
GenesisGasLimit
},
nil
,
nil
,
nil
)
unknownBlock
=
types
.
NewBlock
(
&
types
.
Header
{
GasLimit
:
params
.
GenesisGasLimit
},
nil
,
nil
,
nil
,
new
(
trie
.
Trie
)
)
)
// makeChain creates a chain of n blocks starting at and including parent.
...
...
eth/handler.go
View file @
87c0ba92
...
...
@@ -608,7 +608,14 @@ func (pm *ProtocolManager) handleMsg(p *peer) error {
return
errResp
(
ErrDecode
,
"msg %v: %v"
,
msg
,
err
)
}
// Retrieve the requested state entry, stopping if enough was found
if
entry
,
err
:=
pm
.
blockchain
.
TrieNode
(
hash
);
err
==
nil
{
// todo now the code and trienode is mixed in the protocol level,
// separate these two types.
entry
,
err
:=
pm
.
blockchain
.
TrieNode
(
hash
)
if
len
(
entry
)
==
0
||
err
!=
nil
{
// Read the contract code with prefix only to save unnecessary lookups.
entry
,
err
=
pm
.
blockchain
.
ContractCodeWithPrefix
(
hash
)
}
if
err
==
nil
&&
len
(
entry
)
>
0
{
data
=
append
(
data
,
entry
)
bytes
+=
len
(
entry
)
}
...
...
@@ -703,7 +710,7 @@ func (pm *ProtocolManager) handleMsg(p *peer) error {
log
.
Warn
(
"Propagated block has invalid uncles"
,
"have"
,
hash
,
"exp"
,
request
.
Block
.
UncleHash
())
break
// TODO(karalabe): return error eventually, but wait a few releases
}
if
hash
:=
types
.
DeriveSha
(
request
.
Block
.
Transactions
());
hash
!=
request
.
Block
.
TxHash
()
{
if
hash
:=
types
.
DeriveSha
(
request
.
Block
.
Transactions
()
,
new
(
trie
.
Trie
)
);
hash
!=
request
.
Block
.
TxHash
()
{
log
.
Warn
(
"Propagated block has invalid body"
,
"have"
,
hash
,
"exp"
,
request
.
Block
.
TxHash
())
break
// TODO(karalabe): return error eventually, but wait a few releases
}
...
...
les/odr_requests.go
View file @
87c0ba92
...
...
@@ -116,7 +116,7 @@ func (r *BlockRequest) Validate(db ethdb.Database, msg *Msg) error {
if
r
.
Header
==
nil
{
return
errHeaderUnavailable
}
if
r
.
Header
.
TxHash
!=
types
.
DeriveSha
(
types
.
Transactions
(
body
.
Transactions
))
{
if
r
.
Header
.
TxHash
!=
types
.
DeriveSha
(
types
.
Transactions
(
body
.
Transactions
)
,
new
(
trie
.
Trie
)
)
{
return
errTxHashMismatch
}
if
r
.
Header
.
UncleHash
!=
types
.
CalcUncleHash
(
body
.
Uncles
)
{
...
...
@@ -174,7 +174,7 @@ func (r *ReceiptsRequest) Validate(db ethdb.Database, msg *Msg) error {
if
r
.
Header
==
nil
{
return
errHeaderUnavailable
}
if
r
.
Header
.
ReceiptHash
!=
types
.
DeriveSha
(
receipt
)
{
if
r
.
Header
.
ReceiptHash
!=
types
.
DeriveSha
(
receipt
,
new
(
trie
.
Trie
)
)
{
return
errReceiptHashMismatch
}
// Validations passed, store and return
...
...
les/server_handler.go
View file @
87c0ba92
...
...
@@ -489,7 +489,7 @@ func (h *serverHandler) handleMsg(p *clientPeer, wg *sync.WaitGroup) error {
p
.
bumpInvalid
()
continue
}
code
,
err
:=
triedb
.
Node
(
common
.
BytesToHash
(
account
.
CodeHash
))
code
,
err
:=
h
.
blockchain
.
StateCache
()
.
ContractCode
(
common
.
BytesToHash
(
request
.
AccKey
),
common
.
BytesToHash
(
account
.
CodeHash
))
if
err
!=
nil
{
p
.
Log
()
.
Warn
(
"Failed to retrieve account code"
,
"block"
,
header
.
Number
,
"hash"
,
header
.
Hash
(),
"account"
,
common
.
BytesToHash
(
request
.
AccKey
),
"codehash"
,
common
.
BytesToHash
(
account
.
CodeHash
),
"err"
,
err
)
continue
...
...
light/odr.go
View file @
87c0ba92
...
...
@@ -101,7 +101,7 @@ type CodeRequest struct {
// StoreResult stores the retrieved data in local database
func
(
req
*
CodeRequest
)
StoreResult
(
db
ethdb
.
Database
)
{
db
.
Put
(
req
.
Hash
[
:
]
,
req
.
Data
)
rawdb
.
WriteCode
(
db
,
req
.
Hash
,
req
.
Data
)
}
// BlockRequest is the ODR request type for retrieving block bodies
...
...
light/odr_test.go
View file @
87c0ba92
...
...
@@ -87,7 +87,7 @@ func (odr *testOdr) Retrieve(ctx context.Context, req OdrRequest) error {
t
.
Prove
(
req
.
Key
,
0
,
nodes
)
req
.
Proof
=
nodes
case
*
CodeRequest
:
req
.
Data
,
_
=
odr
.
sdb
.
Get
(
req
.
Hash
[
:
]
)
req
.
Data
=
rawdb
.
ReadCode
(
odr
.
sdb
,
req
.
Hash
)
}
req
.
StoreResult
(
odr
.
ldb
)
return
nil
...
...
light/trie.go
View file @
87c0ba92
...
...
@@ -22,6 +22,7 @@ import (
"fmt"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/rawdb"
"github.com/ethereum/go-ethereum/core/state"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/crypto"
...
...
@@ -70,7 +71,8 @@ func (db *odrDatabase) ContractCode(addrHash, codeHash common.Hash) ([]byte, err
if
codeHash
==
sha3Nil
{
return
nil
,
nil
}
if
code
,
err
:=
db
.
backend
.
Database
()
.
Get
(
codeHash
[
:
]);
err
==
nil
{
code
:=
rawdb
.
ReadCode
(
db
.
backend
.
Database
(),
codeHash
)
if
len
(
code
)
!=
0
{
return
code
,
nil
}
id
:=
*
db
.
id
...
...
miner/worker.go
View file @
87c0ba92
...
...
@@ -34,6 +34,7 @@ import (
"github.com/ethereum/go-ethereum/event"
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/trie"
)
const
(
...
...
@@ -711,6 +712,7 @@ func (w *worker) updateSnapshot() {
w
.
current
.
txs
,
uncles
,
w
.
current
.
receipts
,
new
(
trie
.
Trie
),
)
w
.
snapshotState
=
w
.
current
.
state
.
Copy
()
...
...
trie/database.go
View file @
87c0ba92
This diff is collapsed.
Click to expand it.
trie/secure_trie.go
View file @
87c0ba92
...
...
@@ -130,8 +130,7 @@ func (t *SecureTrie) GetKey(shaKey []byte) []byte {
if
key
,
ok
:=
t
.
getSecKeyCache
()[
string
(
shaKey
)];
ok
{
return
key
}
key
,
_
:=
t
.
trie
.
db
.
preimage
(
common
.
BytesToHash
(
shaKey
))
return
key
return
t
.
trie
.
db
.
preimage
(
common
.
BytesToHash
(
shaKey
))
}
// Commit writes all nodes and the secure hash pre-images to the trie's database.
...
...
trie/sync.go
View file @
87c0ba92
This diff is collapsed.
Click to expand it.
trie/sync_bloom.go
View file @
87c0ba92
...
...
@@ -25,6 +25,7 @@ import (
"time"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/rawdb"
"github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/metrics"
...
...
@@ -41,8 +42,8 @@ var (
)
// syncBloomHasher is a wrapper around a byte blob to satisfy the interface API
// requirements of the bloom library used. It's used to convert a trie hash
into
// a 64 bit mini hash.
// requirements of the bloom library used. It's used to convert a trie hash
or
//
contract code hash into
a 64 bit mini hash.
type
syncBloomHasher
[]
byte
func
(
f
syncBloomHasher
)
Write
(
p
[]
byte
)
(
n
int
,
err
error
)
{
panic
(
"not implemented"
)
}
...
...
@@ -53,9 +54,9 @@ func (f syncBloomHasher) Size() int { return 8 }
func
(
f
syncBloomHasher
)
Sum64
()
uint64
{
return
binary
.
BigEndian
.
Uint64
(
f
)
}
// SyncBloom is a bloom filter used during fast sync to quickly decide if a trie
// node
already exists on disk or not. It self populates from the provided disk
//
database on creation in a background thread and will only start returning live
// results once that's finished.
// node
or contract code already exists on disk or not. It self populates from the
//
provided disk database on creation in a background thread and will only start
// re
turning live re
sults once that's finished.
type
SyncBloom
struct
{
bloom
*
bloomfilter
.
Filter
inited
uint32
...
...
@@ -107,10 +108,16 @@ func (b *SyncBloom) init(database ethdb.Iteratee) {
)
for
it
.
Next
()
&&
atomic
.
LoadUint32
(
&
b
.
closed
)
==
0
{
// If the database entry is a trie node, add it to the bloom
if
key
:=
it
.
Key
();
len
(
key
)
==
common
.
HashLength
{
key
:=
it
.
Key
()
if
len
(
key
)
==
common
.
HashLength
{
b
.
bloom
.
Add
(
syncBloomHasher
(
key
))
bloomLoadMeter
.
Mark
(
1
)
}
// If the database entry is a contract code, add it to the bloom
if
ok
,
hash
:=
rawdb
.
IsCodeKey
(
key
);
ok
{
b
.
bloom
.
Add
(
syncBloomHasher
(
hash
))
bloomLoadMeter
.
Mark
(
1
)
}
// If enough time elapsed since the last iterator swap, restart
if
time
.
Since
(
swap
)
>
8
*
time
.
Second
{
key
:=
common
.
CopyBytes
(
it
.
Key
())
...
...
trie/sync_test.go
View file @
87c0ba92
...
...
@@ -124,8 +124,10 @@ func testIterativeSync(t *testing.T, count int) {
}
results
[
i
]
=
SyncResult
{
hash
,
data
}
}
if
_
,
index
,
err
:=
sched
.
Process
(
results
);
err
!=
nil
{
t
.
Fatalf
(
"failed to process result #%d: %v"
,
index
,
err
)
for
_
,
result
:=
range
results
{
if
err
:=
sched
.
Process
(
result
);
err
!=
nil
{
t
.
Fatalf
(
"failed to process result %v"
,
err
)
}
}
batch
:=
diskdb
.
NewBatch
()
if
err
:=
sched
.
Commit
(
batch
);
err
!=
nil
{
...
...
@@ -160,8 +162,10 @@ func TestIterativeDelayedSync(t *testing.T) {
}
results
[
i
]
=
SyncResult
{
hash
,
data
}
}
if
_
,
index
,
err
:=
sched
.
Process
(
results
);
err
!=
nil
{
t
.
Fatalf
(
"failed to process result #%d: %v"
,
index
,
err
)
for
_
,
result
:=
range
results
{
if
err
:=
sched
.
Process
(
result
);
err
!=
nil
{
t
.
Fatalf
(
"failed to process result %v"
,
err
)
}
}
batch
:=
diskdb
.
NewBatch
()
if
err
:=
sched
.
Commit
(
batch
);
err
!=
nil
{
...
...
@@ -204,8 +208,10 @@ func testIterativeRandomSync(t *testing.T, count int) {
results
=
append
(
results
,
SyncResult
{
hash
,
data
})
}
// Feed the retrieved results back and queue new tasks
if
_
,
index
,
err
:=
sched
.
Process
(
results
);
err
!=
nil
{
t
.
Fatalf
(
"failed to process result #%d: %v"
,
index
,
err
)
for
_
,
result
:=
range
results
{
if
err
:=
sched
.
Process
(
result
);
err
!=
nil
{
t
.
Fatalf
(
"failed to process result %v"
,
err
)
}
}
batch
:=
diskdb
.
NewBatch
()
if
err
:=
sched
.
Commit
(
batch
);
err
!=
nil
{
...
...
@@ -251,8 +257,10 @@ func TestIterativeRandomDelayedSync(t *testing.T) {
}
}
// Feed the retrieved results back and queue new tasks
if
_
,
index
,
err
:=
sched
.
Process
(
results
);
err
!=
nil
{
t
.
Fatalf
(
"failed to process result #%d: %v"
,
index
,
err
)
for
_
,
result
:=
range
results
{
if
err
:=
sched
.
Process
(
result
);
err
!=
nil
{
t
.
Fatalf
(
"failed to process result %v"
,
err
)
}
}
batch
:=
diskdb
.
NewBatch
()
if
err
:=
sched
.
Commit
(
batch
);
err
!=
nil
{
...
...
@@ -298,8 +306,10 @@ func TestDuplicateAvoidanceSync(t *testing.T) {
results
[
i
]
=
SyncResult
{
hash
,
data
}
}
if
_
,
index
,
err
:=
sched
.
Process
(
results
);
err
!=
nil
{
t
.
Fatalf
(
"failed to process result #%d: %v"
,
index
,
err
)
for
_
,
result
:=
range
results
{
if
err
:=
sched
.
Process
(
result
);
err
!=
nil
{
t
.
Fatalf
(
"failed to process result %v"
,
err
)
}
}
batch
:=
diskdb
.
NewBatch
()
if
err
:=
sched
.
Commit
(
batch
);
err
!=
nil
{
...
...
@@ -336,8 +346,10 @@ func TestIncompleteSync(t *testing.T) {
results
[
i
]
=
SyncResult
{
hash
,
data
}
}
// Process each of the trie nodes
if
_
,
index
,
err
:=
sched
.
Process
(
results
);
err
!=
nil
{
t
.
Fatalf
(
"failed to process result #%d: %v"
,
index
,
err
)
for
_
,
result
:=
range
results
{
if
err
:=
sched
.
Process
(
result
);
err
!=
nil
{
t
.
Fatalf
(
"failed to process result %v"
,
err
)
}
}
batch
:=
diskdb
.
NewBatch
()
if
err
:=
sched
.
Commit
(
batch
);
err
!=
nil
{
...
...
trie/trie.go
View file @
87c0ba92
...
...
@@ -473,3 +473,9 @@ func (t *Trie) hashRoot(db *Database) (node, node, error) {
t
.
unhashed
=
0
return
hashed
,
cached
,
nil
}
// Reset drops the referenced root node and cleans all internal state.
func
(
t
*
Trie
)
Reset
()
{
t
.
root
=
nil
t
.
unhashed
=
0
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment