aboutsummaryrefslogtreecommitdiffstats
path: root/core/blockchain_insert.go
diff options
context:
space:
mode:
authorPéter Szilágyi <peterke@gmail.com>2019-04-02 22:03:12 +0800
committerGitHub <noreply@github.com>2019-04-02 22:03:12 +0800
commite14f8a408c17fd6c57d769cd4635ad6cc8bde769 (patch)
treeba0d75fe1d1797be2322366e3d74cc54f77a6184 /core/blockchain_insert.go
parent88d7119ebb7bcb38e16f0feb571c98f2197d7cf3 (diff)
parented34a5e08a475fdf1b3116b1f17879411bfe411d (diff)
downloadgo-tangerine-e14f8a408c17fd6c57d769cd4635ad6cc8bde769.tar
go-tangerine-e14f8a408c17fd6c57d769cd4635ad6cc8bde769.tar.gz
go-tangerine-e14f8a408c17fd6c57d769cd4635ad6cc8bde769.tar.bz2
go-tangerine-e14f8a408c17fd6c57d769cd4635ad6cc8bde769.tar.lz
go-tangerine-e14f8a408c17fd6c57d769cd4635ad6cc8bde769.tar.xz
go-tangerine-e14f8a408c17fd6c57d769cd4635ad6cc8bde769.tar.zst
go-tangerine-e14f8a408c17fd6c57d769cd4635ad6cc8bde769.zip
Merge pull request #19328 from karalabe/preload
core: prefetch next block state concurrently
Diffstat (limited to 'core/blockchain_insert.go')
-rw-r--r--core/blockchain_insert.go43
1 files changed, 37 insertions, 6 deletions
diff --git a/core/blockchain_insert.go b/core/blockchain_insert.go
index e2a385164..e4d758d4c 100644
--- a/core/blockchain_insert.go
+++ b/core/blockchain_insert.go
@@ -80,10 +80,13 @@ func (st *insertStats) report(chain []*types.Block, index int, dirty common.Stor
// insertIterator is a helper to assist during chain import.
type insertIterator struct {
- chain types.Blocks
- results <-chan error
- index int
- validator Validator
+ chain types.Blocks // Chain of blocks being iterated over
+
+ results <-chan error // Verification result sink from the consensus engine
+ errors []error // Header verification errors for the blocks
+
+ index int // Current offset of the iterator
+ validator Validator // Validator to run if verification succeeds
}
// newInsertIterator creates a new iterator based on the given blocks, which are
@@ -92,6 +95,7 @@ func newInsertIterator(chain types.Blocks, results <-chan error, validator Valid
return &insertIterator{
chain: chain,
results: results,
+ errors: make([]error, 0, len(chain)),
index: -1,
validator: validator,
}
@@ -100,17 +104,44 @@ func newInsertIterator(chain types.Blocks, results <-chan error, validator Valid
// next returns the next block in the iterator, along with any potential validation
// error for that block. When the end is reached, it will return (nil, nil).
func (it *insertIterator) next() (*types.Block, error) {
+ // If we reached the end of the chain, abort
if it.index+1 >= len(it.chain) {
it.index = len(it.chain)
return nil, nil
}
+ // Advance the iterator and wait for verification result if not yet done
it.index++
- if err := <-it.results; err != nil {
- return it.chain[it.index], err
+ if len(it.errors) <= it.index {
+ it.errors = append(it.errors, <-it.results)
+ }
+ if it.errors[it.index] != nil {
+ return it.chain[it.index], it.errors[it.index]
}
+ // Block header valid, run body validation and return
return it.chain[it.index], it.validator.ValidateBody(it.chain[it.index])
}
+// peek returns the next block in the iterator, along with any potential validation
+// error for that block, but does **not** advance the iterator.
+//
+// Both header and body validation errors (nil too) is cached into the iterator
+// to avoid duplicating work on the following next() call.
+func (it *insertIterator) peek() (*types.Block, error) {
+ // If we reached the end of the chain, abort
+ if it.index+1 >= len(it.chain) {
+ return nil, nil
+ }
+ // Wait for verification result if not yet done
+ if len(it.errors) <= it.index+1 {
+ it.errors = append(it.errors, <-it.results)
+ }
+ if it.errors[it.index+1] != nil {
+ return it.chain[it.index+1], it.errors[it.index+1]
+ }
+ // Block header valid, ignore body validation since we don't have a parent anyway
+ return it.chain[it.index+1], nil
+}
+
// previous returns the previous header that was being processed, or nil.
func (it *insertIterator) previous() *types.Header {
if it.index < 1 {