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
049f5b35
Commit
049f5b35
authored
Jun 12, 2018
by
Felföldi Zsolt
Committed by
Péter Szilágyi
Jun 12, 2018
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
core, eth, les: more efficient hash-based header chain retrieval (#16946)
parent
02559515
Changes
5
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
106 additions
and
27 deletions
+106
-27
blockchain.go
core/blockchain.go
+12
-0
headerchain.go
core/headerchain.go
+37
-0
handler.go
eth/handler.go
+23
-14
handler.go
les/handler.go
+22
-13
lightchain.go
light/lightchain.go
+12
-0
No files found.
core/blockchain.go
View file @
049f5b35
...
@@ -1524,6 +1524,18 @@ func (bc *BlockChain) GetBlockHashesFromHash(hash common.Hash, max uint64) []com
...
@@ -1524,6 +1524,18 @@ func (bc *BlockChain) GetBlockHashesFromHash(hash common.Hash, max uint64) []com
return
bc
.
hc
.
GetBlockHashesFromHash
(
hash
,
max
)
return
bc
.
hc
.
GetBlockHashesFromHash
(
hash
,
max
)
}
}
// GetAncestor retrieves the Nth ancestor of a given block. It assumes that either the given block or
// a close ancestor of it is canonical. maxNonCanonical points to a downwards counter limiting the
// number of blocks to be individually checked before we reach the canonical chain.
//
// Note: ancestor == 0 returns the same block, 1 returns its parent and so on.
func
(
bc
*
BlockChain
)
GetAncestor
(
hash
common
.
Hash
,
number
,
ancestor
uint64
,
maxNonCanonical
*
uint64
)
(
common
.
Hash
,
uint64
)
{
bc
.
chainmu
.
Lock
()
defer
bc
.
chainmu
.
Unlock
()
return
bc
.
hc
.
GetAncestor
(
hash
,
number
,
ancestor
,
maxNonCanonical
)
}
// GetHeaderByNumber retrieves a block header from the database by number,
// GetHeaderByNumber retrieves a block header from the database by number,
// caching it (associated with its hash) if found.
// caching it (associated with its hash) if found.
func
(
bc
*
BlockChain
)
GetHeaderByNumber
(
number
uint64
)
*
types
.
Header
{
func
(
bc
*
BlockChain
)
GetHeaderByNumber
(
number
uint64
)
*
types
.
Header
{
...
...
core/headerchain.go
View file @
049f5b35
...
@@ -307,6 +307,43 @@ func (hc *HeaderChain) GetBlockHashesFromHash(hash common.Hash, max uint64) []co
...
@@ -307,6 +307,43 @@ func (hc *HeaderChain) GetBlockHashesFromHash(hash common.Hash, max uint64) []co
return
chain
return
chain
}
}
// GetAncestor retrieves the Nth ancestor of a given block. It assumes that either the given block or
// a close ancestor of it is canonical. maxNonCanonical points to a downwards counter limiting the
// number of blocks to be individually checked before we reach the canonical chain.
//
// Note: ancestor == 0 returns the same block, 1 returns its parent and so on.
func
(
hc
*
HeaderChain
)
GetAncestor
(
hash
common
.
Hash
,
number
,
ancestor
uint64
,
maxNonCanonical
*
uint64
)
(
common
.
Hash
,
uint64
)
{
if
ancestor
>
number
{
return
common
.
Hash
{},
0
}
if
ancestor
==
1
{
// in this case it is cheaper to just read the header
if
header
:=
hc
.
GetHeader
(
hash
,
number
);
header
!=
nil
{
return
header
.
ParentHash
,
number
-
1
}
else
{
return
common
.
Hash
{},
0
}
}
for
ancestor
!=
0
{
if
rawdb
.
ReadCanonicalHash
(
hc
.
chainDb
,
number
)
==
hash
{
number
-=
ancestor
return
rawdb
.
ReadCanonicalHash
(
hc
.
chainDb
,
number
),
number
}
if
*
maxNonCanonical
==
0
{
return
common
.
Hash
{},
0
}
*
maxNonCanonical
--
ancestor
--
header
:=
hc
.
GetHeader
(
hash
,
number
)
if
header
==
nil
{
return
common
.
Hash
{},
0
}
hash
=
header
.
ParentHash
number
--
}
return
hash
,
number
}
// GetTd retrieves a block's total difficulty in the canonical chain from the
// GetTd retrieves a block's total difficulty in the canonical chain from the
// database by hash and number, caching it if found.
// database by hash and number, caching it if found.
func
(
hc
*
HeaderChain
)
GetTd
(
hash
common
.
Hash
,
number
uint64
)
*
big
.
Int
{
func
(
hc
*
HeaderChain
)
GetTd
(
hash
common
.
Hash
,
number
uint64
)
*
big
.
Int
{
...
...
eth/handler.go
View file @
049f5b35
...
@@ -340,6 +340,8 @@ func (pm *ProtocolManager) handleMsg(p *peer) error {
...
@@ -340,6 +340,8 @@ func (pm *ProtocolManager) handleMsg(p *peer) error {
return
errResp
(
ErrDecode
,
"%v: %v"
,
msg
,
err
)
return
errResp
(
ErrDecode
,
"%v: %v"
,
msg
,
err
)
}
}
hashMode
:=
query
.
Origin
.
Hash
!=
(
common
.
Hash
{})
hashMode
:=
query
.
Origin
.
Hash
!=
(
common
.
Hash
{})
first
:=
true
maxNonCanonical
:=
uint64
(
100
)
// Gather headers until the fetch or network limits is reached
// Gather headers until the fetch or network limits is reached
var
(
var
(
...
@@ -351,31 +353,36 @@ func (pm *ProtocolManager) handleMsg(p *peer) error {
...
@@ -351,31 +353,36 @@ func (pm *ProtocolManager) handleMsg(p *peer) error {
// Retrieve the next header satisfying the query
// Retrieve the next header satisfying the query
var
origin
*
types
.
Header
var
origin
*
types
.
Header
if
hashMode
{
if
hashMode
{
origin
=
pm
.
blockchain
.
GetHeaderByHash
(
query
.
Origin
.
Hash
)
if
first
{
first
=
false
origin
=
pm
.
blockchain
.
GetHeaderByHash
(
query
.
Origin
.
Hash
)
if
origin
!=
nil
{
query
.
Origin
.
Number
=
origin
.
Number
.
Uint64
()
}
}
else
{
origin
=
pm
.
blockchain
.
GetHeader
(
query
.
Origin
.
Hash
,
query
.
Origin
.
Number
)
}
}
else
{
}
else
{
origin
=
pm
.
blockchain
.
GetHeaderByNumber
(
query
.
Origin
.
Number
)
origin
=
pm
.
blockchain
.
GetHeaderByNumber
(
query
.
Origin
.
Number
)
}
}
if
origin
==
nil
{
if
origin
==
nil
{
break
break
}
}
number
:=
origin
.
Number
.
Uint64
()
headers
=
append
(
headers
,
origin
)
headers
=
append
(
headers
,
origin
)
bytes
+=
estHeaderRlpSize
bytes
+=
estHeaderRlpSize
// Advance to the next header of the query
// Advance to the next header of the query
switch
{
switch
{
case
query
.
Origin
.
Hash
!=
(
common
.
Hash
{})
&&
query
.
Reverse
:
case
hashMode
&&
query
.
Reverse
:
// Hash based traversal towards the genesis block
// Hash based traversal towards the genesis block
for
i
:=
0
;
i
<
int
(
query
.
Skip
)
+
1
;
i
++
{
ancestor
:=
query
.
Skip
+
1
if
header
:=
pm
.
blockchain
.
GetHeader
(
query
.
Origin
.
Hash
,
number
);
header
!=
nil
{
if
ancestor
==
0
{
query
.
Origin
.
Hash
=
header
.
ParentHash
unknown
=
true
number
--
}
else
{
}
else
{
query
.
Origin
.
Hash
,
query
.
Origin
.
Number
=
pm
.
blockchain
.
GetAncestor
(
query
.
Origin
.
Hash
,
query
.
Origin
.
Number
,
ancestor
,
&
maxNonCanonical
)
unknown
=
true
unknown
=
(
query
.
Origin
.
Hash
==
common
.
Hash
{})
break
}
}
}
case
query
.
Origin
.
Hash
!=
(
common
.
Hash
{})
&&
!
query
.
Reverse
:
case
hashMode
&&
!
query
.
Reverse
:
// Hash based traversal towards the leaf block
// Hash based traversal towards the leaf block
var
(
var
(
current
=
origin
.
Number
.
Uint64
()
current
=
origin
.
Number
.
Uint64
()
...
@@ -387,8 +394,10 @@ func (pm *ProtocolManager) handleMsg(p *peer) error {
...
@@ -387,8 +394,10 @@ func (pm *ProtocolManager) handleMsg(p *peer) error {
unknown
=
true
unknown
=
true
}
else
{
}
else
{
if
header
:=
pm
.
blockchain
.
GetHeaderByNumber
(
next
);
header
!=
nil
{
if
header
:=
pm
.
blockchain
.
GetHeaderByNumber
(
next
);
header
!=
nil
{
if
pm
.
blockchain
.
GetBlockHashesFromHash
(
header
.
Hash
(),
query
.
Skip
+
1
)[
query
.
Skip
]
==
query
.
Origin
.
Hash
{
nextHash
:=
header
.
Hash
()
query
.
Origin
.
Hash
=
header
.
Hash
()
expOldHash
,
_
:=
pm
.
blockchain
.
GetAncestor
(
nextHash
,
next
,
query
.
Skip
+
1
,
&
maxNonCanonical
)
if
expOldHash
==
query
.
Origin
.
Hash
{
query
.
Origin
.
Hash
,
query
.
Origin
.
Number
=
nextHash
,
next
}
else
{
}
else
{
unknown
=
true
unknown
=
true
}
}
...
...
les/handler.go
View file @
049f5b35
...
@@ -83,7 +83,7 @@ type BlockChain interface {
...
@@ -83,7 +83,7 @@ type BlockChain interface {
InsertHeaderChain
(
chain
[]
*
types
.
Header
,
checkFreq
int
)
(
int
,
error
)
InsertHeaderChain
(
chain
[]
*
types
.
Header
,
checkFreq
int
)
(
int
,
error
)
Rollback
(
chain
[]
common
.
Hash
)
Rollback
(
chain
[]
common
.
Hash
)
GetHeaderByNumber
(
number
uint64
)
*
types
.
Header
GetHeaderByNumber
(
number
uint64
)
*
types
.
Header
Get
BlockHashesFromHash
(
hash
common
.
Hash
,
max
uint64
)
[]
common
.
Hash
Get
Ancestor
(
hash
common
.
Hash
,
number
,
ancestor
uint64
,
maxNonCanonical
*
uint64
)
(
common
.
Hash
,
uint64
)
Genesis
()
*
types
.
Block
Genesis
()
*
types
.
Block
SubscribeChainHeadEvent
(
ch
chan
<-
core
.
ChainHeadEvent
)
event
.
Subscription
SubscribeChainHeadEvent
(
ch
chan
<-
core
.
ChainHeadEvent
)
event
.
Subscription
}
}
...
@@ -419,6 +419,8 @@ func (pm *ProtocolManager) handleMsg(p *peer) error {
...
@@ -419,6 +419,8 @@ func (pm *ProtocolManager) handleMsg(p *peer) error {
}
}
hashMode
:=
query
.
Origin
.
Hash
!=
(
common
.
Hash
{})
hashMode
:=
query
.
Origin
.
Hash
!=
(
common
.
Hash
{})
first
:=
true
maxNonCanonical
:=
uint64
(
100
)
// Gather headers until the fetch or network limits is reached
// Gather headers until the fetch or network limits is reached
var
(
var
(
...
@@ -430,14 +432,21 @@ func (pm *ProtocolManager) handleMsg(p *peer) error {
...
@@ -430,14 +432,21 @@ func (pm *ProtocolManager) handleMsg(p *peer) error {
// Retrieve the next header satisfying the query
// Retrieve the next header satisfying the query
var
origin
*
types
.
Header
var
origin
*
types
.
Header
if
hashMode
{
if
hashMode
{
origin
=
pm
.
blockchain
.
GetHeaderByHash
(
query
.
Origin
.
Hash
)
if
first
{
first
=
false
origin
=
pm
.
blockchain
.
GetHeaderByHash
(
query
.
Origin
.
Hash
)
if
origin
!=
nil
{
query
.
Origin
.
Number
=
origin
.
Number
.
Uint64
()
}
}
else
{
origin
=
pm
.
blockchain
.
GetHeader
(
query
.
Origin
.
Hash
,
query
.
Origin
.
Number
)
}
}
else
{
}
else
{
origin
=
pm
.
blockchain
.
GetHeaderByNumber
(
query
.
Origin
.
Number
)
origin
=
pm
.
blockchain
.
GetHeaderByNumber
(
query
.
Origin
.
Number
)
}
}
if
origin
==
nil
{
if
origin
==
nil
{
break
break
}
}
number
:=
origin
.
Number
.
Uint64
()
headers
=
append
(
headers
,
origin
)
headers
=
append
(
headers
,
origin
)
bytes
+=
estHeaderRlpSize
bytes
+=
estHeaderRlpSize
...
@@ -445,14 +454,12 @@ func (pm *ProtocolManager) handleMsg(p *peer) error {
...
@@ -445,14 +454,12 @@ func (pm *ProtocolManager) handleMsg(p *peer) error {
switch
{
switch
{
case
hashMode
&&
query
.
Reverse
:
case
hashMode
&&
query
.
Reverse
:
// Hash based traversal towards the genesis block
// Hash based traversal towards the genesis block
for
i
:=
0
;
i
<
int
(
query
.
Skip
)
+
1
;
i
++
{
ancestor
:=
query
.
Skip
+
1
if
header
:=
pm
.
blockchain
.
GetHeader
(
query
.
Origin
.
Hash
,
number
);
header
!=
nil
{
if
ancestor
==
0
{
query
.
Origin
.
Hash
=
header
.
ParentHash
unknown
=
true
number
--
}
else
{
}
else
{
query
.
Origin
.
Hash
,
query
.
Origin
.
Number
=
pm
.
blockchain
.
GetAncestor
(
query
.
Origin
.
Hash
,
query
.
Origin
.
Number
,
ancestor
,
&
maxNonCanonical
)
unknown
=
true
unknown
=
(
query
.
Origin
.
Hash
==
common
.
Hash
{})
break
}
}
}
case
hashMode
&&
!
query
.
Reverse
:
case
hashMode
&&
!
query
.
Reverse
:
// Hash based traversal towards the leaf block
// Hash based traversal towards the leaf block
...
@@ -466,8 +473,10 @@ func (pm *ProtocolManager) handleMsg(p *peer) error {
...
@@ -466,8 +473,10 @@ func (pm *ProtocolManager) handleMsg(p *peer) error {
unknown
=
true
unknown
=
true
}
else
{
}
else
{
if
header
:=
pm
.
blockchain
.
GetHeaderByNumber
(
next
);
header
!=
nil
{
if
header
:=
pm
.
blockchain
.
GetHeaderByNumber
(
next
);
header
!=
nil
{
if
pm
.
blockchain
.
GetBlockHashesFromHash
(
header
.
Hash
(),
query
.
Skip
+
1
)[
query
.
Skip
]
==
query
.
Origin
.
Hash
{
nextHash
:=
header
.
Hash
()
query
.
Origin
.
Hash
=
header
.
Hash
()
expOldHash
,
_
:=
pm
.
blockchain
.
GetAncestor
(
nextHash
,
next
,
query
.
Skip
+
1
,
&
maxNonCanonical
)
if
expOldHash
==
query
.
Origin
.
Hash
{
query
.
Origin
.
Hash
,
query
.
Origin
.
Number
=
nextHash
,
next
}
else
{
}
else
{
unknown
=
true
unknown
=
true
}
}
...
...
light/lightchain.go
View file @
049f5b35
...
@@ -433,6 +433,18 @@ func (self *LightChain) GetBlockHashesFromHash(hash common.Hash, max uint64) []c
...
@@ -433,6 +433,18 @@ func (self *LightChain) GetBlockHashesFromHash(hash common.Hash, max uint64) []c
return
self
.
hc
.
GetBlockHashesFromHash
(
hash
,
max
)
return
self
.
hc
.
GetBlockHashesFromHash
(
hash
,
max
)
}
}
// GetAncestor retrieves the Nth ancestor of a given block. It assumes that either the given block or
// a close ancestor of it is canonical. maxNonCanonical points to a downwards counter limiting the
// number of blocks to be individually checked before we reach the canonical chain.
//
// Note: ancestor == 0 returns the same block, 1 returns its parent and so on.
func
(
bc
*
LightChain
)
GetAncestor
(
hash
common
.
Hash
,
number
,
ancestor
uint64
,
maxNonCanonical
*
uint64
)
(
common
.
Hash
,
uint64
)
{
bc
.
chainmu
.
Lock
()
defer
bc
.
chainmu
.
Unlock
()
return
bc
.
hc
.
GetAncestor
(
hash
,
number
,
ancestor
,
maxNonCanonical
)
}
// GetHeaderByNumber retrieves a block header from the database by number,
// GetHeaderByNumber retrieves a block header from the database by number,
// caching it (associated with its hash) if found.
// caching it (associated with its hash) if found.
func
(
self
*
LightChain
)
GetHeaderByNumber
(
number
uint64
)
*
types
.
Header
{
func
(
self
*
LightChain
)
GetHeaderByNumber
(
number
uint64
)
*
types
.
Header
{
...
...
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