Skip to content

Commit 161c467

Browse files
committed
Merge branch 'develop' into fast-node-fix
2 parents b978ed3 + 1aeadc1 commit 161c467

27 files changed

+564
-142
lines changed

.github/release.env

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
1-
MAINNET_FILE_URL="https://github.com/binance-chain/bsc/releases/download/v1.1.7/mainnet.zip"
2-
TESTNET_FILE_URL="https://github.com/binance-chain/bsc/releases/download/v1.1.7/testnet.zip"
1+
MAINNET_FILE_URL="https://github.com/binance-chain/bsc/releases/download/v1.1.8/mainnet.zip"
2+
TESTNET_FILE_URL="https://github.com/binance-chain/bsc/releases/download/v1.1.8/testnet.zip"

CHANGELOG.md

+19
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,24 @@
11
# Changelog
22

3+
## v1.1.9
4+
5+
IMPROVEMENT
6+
* [\#792](https://github.com/binance-chain/bsc/pull/792) add shared storage for prefetching state data
7+
* [\#795](https://github.com/binance-chain/bsc/pull/795) implement state verification pipeline in pipecommit
8+
* [\#803](https://github.com/binance-chain/bsc/pull/803) prefetch state data during the mining process
9+
* [\#812](https://github.com/bnb-chain/bsc/pull/812) skip verification on account storage root to tolerate with fastnode when doing diffsync
10+
* [\#818](https://github.com/bnb-chain/bsc/pull/818) add shared storage to the prefetcher of miner
11+
* [\#820](https://github.com/bnb-chain/bsc/pull/820) disable diffsync when pipecommit is enabled
12+
* [\#830](https://github.com/bnb-chain/bsc/pull/830) change the number of prefetch threads
13+
14+
BUGFIX
15+
* [\#797](https://github.com/bnb-chain/bsc/pull/797) fix race condition on preimage in pipecommit
16+
* [\#808](https://github.com/bnb-chain/bsc/pull/808) fix code of difflayer not assign when new smart contract created
17+
* [\#817](https://github.com/bnb-chain/bsc/pull/817) fix bugs of prune block tool
18+
* [\#834](https://github.com/bnb-chain/bsc/pull/834) fix deadlock when failed to verify state root in pipecommit
19+
* [\#835](https://github.com/bnb-chain/bsc/pull/835) fix deadlock on miner module when failed to commit trie
20+
* [\#842](https://github.com/bnb-chain/bsc/pull/842) fix invalid nil check of statedb in diffsync
21+
322
## v1.1.8
423
FEATURES
524
* [\#668](https://github.com/binance-chain/bsc/pull/668) implement State Verification && Snapshot Commit pipeline

cmd/geth/snapshot.go

+2-1
Original file line numberDiff line numberDiff line change
@@ -308,7 +308,8 @@ func pruneBlock(ctx *cli.Context) error {
308308
var newAncientPath string
309309
oldAncientPath := ctx.GlobalString(utils.AncientFlag.Name)
310310
if !filepath.IsAbs(oldAncientPath) {
311-
oldAncientPath = stack.ResolvePath(oldAncientPath)
311+
// force absolute paths, which often fail due to the splicing of relative paths
312+
return errors.New("datadir.ancient not abs path")
312313
}
313314

314315
path, _ := filepath.Split(oldAncientPath)

cmd/utils/flags.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -137,7 +137,7 @@ var (
137137
}
138138
PipeCommitFlag = cli.BoolFlag{
139139
Name: "pipecommit",
140-
Usage: "Enable MPT pipeline commit, it will improve syncing performance. It is an experimental feature(default is false)",
140+
Usage: "Enable MPT pipeline commit, it will improve syncing performance. It is an experimental feature(default is false), diffsync will be disable if pipeline commit is enabled",
141141
}
142142
RangeLimitFlag = cli.BoolFlag{
143143
Name: "rangelimit",

core/block_validator.go

+5-3
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,7 @@ func (v *BlockValidator) ValidateBody(block *types.Block) error {
115115
// transition, such as amount of used gas, the receipt roots and the state root
116116
// itself. ValidateState returns a database batch if the validation was a success
117117
// otherwise nil and an error is returned.
118-
func (v *BlockValidator) ValidateState(block *types.Block, statedb *state.StateDB, receipts types.Receipts, usedGas uint64, skipHeavyVerify bool) error {
118+
func (v *BlockValidator) ValidateState(block *types.Block, statedb *state.StateDB, receipts types.Receipts, usedGas uint64) error {
119119
header := block.Header()
120120
if block.GasUsed() != usedGas {
121121
return fmt.Errorf("invalid gas used (remote: %d local: %d)", block.GasUsed(), usedGas)
@@ -138,13 +138,15 @@ func (v *BlockValidator) ValidateState(block *types.Block, statedb *state.StateD
138138
return nil
139139
},
140140
}
141-
if skipHeavyVerify {
141+
if statedb.IsPipeCommit() {
142142
validateFuns = append(validateFuns, func() error {
143143
if err := statedb.WaitPipeVerification(); err != nil {
144144
return err
145145
}
146+
statedb.CorrectAccountsRoot()
146147
statedb.Finalise(v.config.IsEIP158(header.Number))
147-
statedb.AccountsIntermediateRoot()
148+
// State verification pipeline - accounts root are not calculated here, just populate needed fields for process
149+
statedb.PopulateSnapAccountAndStorage()
148150
return nil
149151
})
150152
} else {

core/blockchain.go

+7-2
Original file line numberDiff line numberDiff line change
@@ -873,6 +873,11 @@ func (bc *BlockChain) StateAt(root common.Hash) (*state.StateDB, error) {
873873
return state.New(root, bc.stateCache, bc.snaps)
874874
}
875875

876+
// StateAtWithSharedPool returns a new mutable state based on a particular point in time with sharedStorage
877+
func (bc *BlockChain) StateAtWithSharedPool(root common.Hash) (*state.StateDB, error) {
878+
return state.NewWithSharedPool(root, bc.stateCache, bc.snaps)
879+
}
880+
876881
// StateCache returns the caching database underpinning the blockchain instance.
877882
func (bc *BlockChain) StateCache() state.Database {
878883
return bc.stateCache
@@ -2151,7 +2156,7 @@ func (bc *BlockChain) insertChain(chain types.Blocks, verifySeals bool) (int, er
21512156
if parent == nil {
21522157
parent = bc.GetHeader(block.ParentHash(), block.NumberU64()-1)
21532158
}
2154-
statedb, err := state.New(parent.Root, bc.stateCache, bc.snaps)
2159+
statedb, err := state.NewWithSharedPool(parent.Root, bc.stateCache, bc.snaps)
21552160
if err != nil {
21562161
return it.index, err
21572162
}
@@ -2196,7 +2201,7 @@ func (bc *BlockChain) insertChain(chain types.Blocks, verifySeals bool) (int, er
21962201
// Validate the state using the default validator
21972202
substart = time.Now()
21982203
if !statedb.IsLightProcessed() {
2199-
if err := bc.validator.ValidateState(block, statedb, receipts, usedGas, bc.pipeCommit); err != nil {
2204+
if err := bc.validator.ValidateState(block, statedb, receipts, usedGas); err != nil {
22002205
log.Error("validate state failed", "error", err)
22012206
bc.reportBlock(block, receipts, err)
22022207
return it.index, err

core/blockchain_test.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -209,7 +209,7 @@ func testBlockChainImport(chain types.Blocks, pipelineCommit bool, blockchain *B
209209
blockchain.reportBlock(block, receipts, err)
210210
return err
211211
}
212-
err = blockchain.validator.ValidateState(block, statedb, receipts, usedGas, pipelineCommit)
212+
err = blockchain.validator.ValidateState(block, statedb, receipts, usedGas)
213213
if err != nil {
214214
blockchain.reportBlock(block, receipts, err)
215215
return err

core/headerchain.go

+3
Original file line numberDiff line numberDiff line change
@@ -250,6 +250,9 @@ func (hc *HeaderChain) writeHeaders(headers []*types.Header) (result *headerWrit
250250
headHeader = hc.GetHeader(headHash, headNumber)
251251
)
252252
for rawdb.ReadCanonicalHash(hc.chainDb, headNumber) != headHash {
253+
if frozen, _ := hc.chainDb.Ancients(); frozen == headNumber {
254+
break
255+
}
253256
rawdb.WriteCanonicalHash(markerBatch, headHash, headNumber)
254257
headHash = headHeader.ParentHash
255258
headNumber = headHeader.Number.Uint64() - 1

core/rawdb/chain_iterator.go

+4-1
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,10 @@ func iterateTransactions(db ethdb.Database, from uint64, to uint64, reverse bool
9595
number uint64
9696
rlp rlp.RawValue
9797
}
98-
if to == from {
98+
if offset := db.AncientOffSet(); offset > from {
99+
from = offset
100+
}
101+
if to <= from {
99102
return nil
100103
}
101104
threads := to - from

core/state/shared_pool.go

+39
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
package state
2+
3+
import (
4+
"sync"
5+
6+
"github.com/ethereum/go-ethereum/common"
7+
)
8+
9+
// sharedPool is used to store maps of originStorage of stateObjects
10+
type StoragePool struct {
11+
sync.RWMutex
12+
sharedMap map[common.Address]*sync.Map
13+
}
14+
15+
func NewStoragePool() *StoragePool {
16+
sharedMap := make(map[common.Address]*sync.Map)
17+
return &StoragePool{
18+
sync.RWMutex{},
19+
sharedMap,
20+
}
21+
}
22+
23+
// getStorage Check whether the storage exist in pool,
24+
// new one if not exist, the content of storage will be fetched in stateObjects.GetCommittedState()
25+
func (s *StoragePool) getStorage(address common.Address) *sync.Map {
26+
s.RLock()
27+
storageMap, ok := s.sharedMap[address]
28+
s.RUnlock()
29+
if !ok {
30+
s.Lock()
31+
defer s.Unlock()
32+
if storageMap, ok = s.sharedMap[address]; !ok {
33+
m := new(sync.Map)
34+
s.sharedMap[address] = m
35+
return m
36+
}
37+
}
38+
return storageMap
39+
}

core/state/snapshot/difflayer.go

+38-2
Original file line numberDiff line numberDiff line change
@@ -118,8 +118,9 @@ type diffLayer struct {
118118
storageList map[common.Hash][]common.Hash // List of storage slots for iterated retrievals, one per account. Any existing lists are sorted if non-nil
119119
storageData map[common.Hash]map[common.Hash][]byte // Keyed storage slots for direct retrieval. one per account (nil means deleted)
120120

121-
verifiedCh chan struct{} // the difflayer is verified when verifiedCh is nil or closed
122-
valid bool // mark the difflayer is valid or not.
121+
verifiedCh chan struct{} // the difflayer is verified when verifiedCh is nil or closed
122+
valid bool // mark the difflayer is valid or not.
123+
accountCorrected bool // mark the accountData has been corrected ort not
123124

124125
diffed *bloomfilter.Filter // Bloom filter tracking all the diffed items up to the disk layer
125126

@@ -182,6 +183,7 @@ func newDiffLayer(parent snapshot, root common.Hash, destructs map[common.Hash]s
182183
storageList: make(map[common.Hash][]common.Hash),
183184
verifiedCh: verified,
184185
}
186+
185187
switch parent := parent.(type) {
186188
case *diskLayer:
187189
dl.rebloom(parent)
@@ -190,6 +192,7 @@ func newDiffLayer(parent snapshot, root common.Hash, destructs map[common.Hash]s
190192
default:
191193
panic("unknown parent type")
192194
}
195+
193196
// Sanity check that accounts or storage slots are never nil
194197
for accountHash, blob := range accounts {
195198
if blob == nil {
@@ -286,6 +289,21 @@ func (dl *diffLayer) Verified() bool {
286289
}
287290
}
288291

292+
func (dl *diffLayer) CorrectAccounts(accounts map[common.Hash][]byte) {
293+
dl.lock.Lock()
294+
defer dl.lock.Unlock()
295+
296+
dl.accountData = accounts
297+
dl.accountCorrected = true
298+
}
299+
300+
func (dl *diffLayer) AccountsCorrected() bool {
301+
dl.lock.RLock()
302+
defer dl.lock.RUnlock()
303+
304+
return dl.accountCorrected
305+
}
306+
289307
// Parent returns the subsequent layer of a diff layer.
290308
func (dl *diffLayer) Parent() snapshot {
291309
return dl.parent
@@ -314,6 +332,24 @@ func (dl *diffLayer) Account(hash common.Hash) (*Account, error) {
314332
return account, nil
315333
}
316334

335+
// Accounts directly retrieves all accounts in current snapshot in
336+
// the snapshot slim data format.
337+
func (dl *diffLayer) Accounts() (map[common.Hash]*Account, error) {
338+
dl.lock.RLock()
339+
defer dl.lock.RUnlock()
340+
341+
accounts := make(map[common.Hash]*Account, len(dl.accountData))
342+
for hash, data := range dl.accountData {
343+
account := new(Account)
344+
if err := rlp.DecodeBytes(data, account); err != nil {
345+
return nil, err
346+
}
347+
accounts[hash] = account
348+
}
349+
350+
return accounts, nil
351+
}
352+
317353
// AccountRLP directly retrieves the account RLP associated with a particular
318354
// hash in the snapshot slim data format.
319355
//

core/state/snapshot/disklayer.go

+13
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,13 @@ func (dl *diskLayer) Verified() bool {
5959
return true
6060
}
6161

62+
func (dl *diskLayer) CorrectAccounts(map[common.Hash][]byte) {
63+
}
64+
65+
func (dl *diskLayer) AccountsCorrected() bool {
66+
return true
67+
}
68+
6269
// Parent always returns nil as there's no layer below the disk.
6370
func (dl *diskLayer) Parent() snapshot {
6471
return nil
@@ -73,6 +80,12 @@ func (dl *diskLayer) Stale() bool {
7380
return dl.stale
7481
}
7582

83+
// Accounts directly retrieves all accounts in current snapshot in
84+
// the snapshot slim data format.
85+
func (dl *diskLayer) Accounts() (map[common.Hash]*Account, error) {
86+
return nil, nil
87+
}
88+
7689
// Account directly retrieves the account associated with a particular hash in
7790
// the snapshot slim data format.
7891
func (dl *diskLayer) Account(hash common.Hash) (*Account, error) {

core/state/snapshot/journal.go

+1
Original file line numberDiff line numberDiff line change
@@ -293,6 +293,7 @@ func (dl *diffLayer) Journal(buffer *bytes.Buffer) (common.Hash, error) {
293293
if dl.Stale() {
294294
return common.Hash{}, ErrSnapshotStale
295295
}
296+
296297
// Everything below was journalled, persist this layer too
297298
if err := rlp.Encode(buffer, dl.root); err != nil {
298299
return common.Hash{}, err

core/state/snapshot/snapshot.go

+21-1
Original file line numberDiff line numberDiff line change
@@ -107,13 +107,23 @@ type Snapshot interface {
107107
// Verified returns whether the snapshot is verified
108108
Verified() bool
109109

110-
// Store the verification result
110+
// MarkValid stores the verification result
111111
MarkValid()
112112

113+
// CorrectAccounts updates account data for storing the correct data during pipecommit
114+
CorrectAccounts(map[common.Hash][]byte)
115+
116+
// AccountsCorrected checks whether the account data has been corrected during pipecommit
117+
AccountsCorrected() bool
118+
113119
// Account directly retrieves the account associated with a particular hash in
114120
// the snapshot slim data format.
115121
Account(hash common.Hash) (*Account, error)
116122

123+
// Accounts directly retrieves all accounts in current snapshot in
124+
// the snapshot slim data format.
125+
Accounts() (map[common.Hash]*Account, error)
126+
117127
// AccountRLP directly retrieves the account RLP associated with a particular
118128
// hash in the snapshot slim data format.
119129
AccountRLP(hash common.Hash) ([]byte, error)
@@ -240,6 +250,11 @@ func (t *Tree) waitBuild() {
240250
}
241251
}
242252

253+
// Layers returns the number of layers
254+
func (t *Tree) Layers() int {
255+
return len(t.layers)
256+
}
257+
243258
// Disable interrupts any pending snapshot generator, deletes all the snapshot
244259
// layers in memory and marks snapshots disabled globally. In order to resume
245260
// the snapshot functionality, the caller must invoke Rebuild.
@@ -666,6 +681,11 @@ func (t *Tree) Journal(root common.Hash) (common.Hash, error) {
666681
if snap == nil {
667682
return common.Hash{}, fmt.Errorf("snapshot [%#x] missing", root)
668683
}
684+
// Wait the snapshot(difflayer) is verified, it means the account data also been refreshed with the correct data
685+
if !snap.WaitAndGetVerifyRes() {
686+
return common.Hash{}, ErrSnapshotStale
687+
}
688+
669689
// Run the journaling
670690
t.lock.Lock()
671691
defer t.lock.Unlock()

0 commit comments

Comments
 (0)