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
b69476b3
Commit
b69476b3
authored
Aug 28, 2018
by
gary rong
Committed by
Péter Szilágyi
Aug 28, 2018
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
all: make indexer configurable (#17188)
parent
c64d72be
Changes
25
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
25 changed files
with
514 additions
and
322 deletions
+514
-322
chain_indexer.go
core/chain_indexer.go
+0
-1
backend.go
eth/backend.go
+2
-2
bloombits.go
eth/bloombits.go
+5
-10
api_backend.go
les/api_backend.go
+1
-1
backend.go
les/backend.go
+7
-6
bloombits.go
les/bloombits.go
+2
-2
commons.go
les/commons.go
+4
-2
handler.go
les/handler.go
+8
-5
handler_test.go
les/handler_test.go
+92
-87
helper_test.go
les/helper_test.go
+141
-18
odr.go
les/odr.go
+11
-4
odr_requests.go
les/odr_requests.go
+17
-3
odr_test.go
les/odr_test.go
+14
-31
peer.go
les/peer.go
+15
-15
request_test.go
les/request_test.go
+12
-31
server.go
les/server.go
+8
-6
lightchain.go
light/lightchain.go
+11
-9
lightchain_test.go
light/lightchain_test.go
+7
-2
odr.go
light/odr.go
+4
-1
odr_test.go
light/odr_test.go
+8
-3
odr_util.go
light/odr_util.go
+10
-8
postprocess.go
light/postprocess.go
+103
-71
trie_test.go
light/trie_test.go
+1
-1
txpool_test.go
light/txpool_test.go
+1
-1
network_params.go
params/network_params.go
+30
-2
No files found.
core/chain_indexer.go
View file @
b69476b3
...
@@ -322,7 +322,6 @@ func (c *ChainIndexer) updateLoop() {
...
@@ -322,7 +322,6 @@ func (c *ChainIndexer) updateLoop() {
updating
=
false
updating
=
false
c
.
log
.
Info
(
"Finished upgrading chain index"
)
c
.
log
.
Info
(
"Finished upgrading chain index"
)
}
}
c
.
cascadedHead
=
c
.
storedSections
*
c
.
sectionSize
-
1
c
.
cascadedHead
=
c
.
storedSections
*
c
.
sectionSize
-
1
for
_
,
child
:=
range
c
.
children
{
for
_
,
child
:=
range
c
.
children
{
c
.
log
.
Trace
(
"Cascading chain index update"
,
"head"
,
c
.
cascadedHead
)
c
.
log
.
Trace
(
"Cascading chain index update"
,
"head"
,
c
.
cascadedHead
)
...
...
eth/backend.go
View file @
b69476b3
...
@@ -136,7 +136,7 @@ func New(ctx *node.ServiceContext, config *Config) (*Ethereum, error) {
...
@@ -136,7 +136,7 @@ func New(ctx *node.ServiceContext, config *Config) (*Ethereum, error) {
gasPrice
:
config
.
MinerGasPrice
,
gasPrice
:
config
.
MinerGasPrice
,
etherbase
:
config
.
Etherbase
,
etherbase
:
config
.
Etherbase
,
bloomRequests
:
make
(
chan
chan
*
bloombits
.
Retrieval
),
bloomRequests
:
make
(
chan
chan
*
bloombits
.
Retrieval
),
bloomIndexer
:
NewBloomIndexer
(
chainDb
,
params
.
BloomBitsBlocks
,
b
loomConfirms
),
bloomIndexer
:
NewBloomIndexer
(
chainDb
,
params
.
BloomBitsBlocks
,
params
.
B
loomConfirms
),
}
}
log
.
Info
(
"Initialising Ethereum protocol"
,
"versions"
,
ProtocolVersions
,
"network"
,
config
.
NetworkId
)
log
.
Info
(
"Initialising Ethereum protocol"
,
"versions"
,
ProtocolVersions
,
"network"
,
config
.
NetworkId
)
...
@@ -426,7 +426,7 @@ func (s *Ethereum) Protocols() []p2p.Protocol {
...
@@ -426,7 +426,7 @@ func (s *Ethereum) Protocols() []p2p.Protocol {
// Ethereum protocol implementation.
// Ethereum protocol implementation.
func
(
s
*
Ethereum
)
Start
(
srvr
*
p2p
.
Server
)
error
{
func
(
s
*
Ethereum
)
Start
(
srvr
*
p2p
.
Server
)
error
{
// Start the bloom bits servicing goroutines
// Start the bloom bits servicing goroutines
s
.
startBloomHandlers
()
s
.
startBloomHandlers
(
params
.
BloomBitsBlocks
)
// Start the RPC service
// Start the RPC service
s
.
netRPCService
=
ethapi
.
NewPublicNetAPI
(
srvr
,
s
.
NetVersion
())
s
.
netRPCService
=
ethapi
.
NewPublicNetAPI
(
srvr
,
s
.
NetVersion
())
...
...
eth/bloombits.go
View file @
b69476b3
...
@@ -27,7 +27,6 @@ import (
...
@@ -27,7 +27,6 @@ import (
"github.com/ethereum/go-ethereum/core/rawdb"
"github.com/ethereum/go-ethereum/core/rawdb"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/params"
)
)
const
(
const
(
...
@@ -50,7 +49,7 @@ const (
...
@@ -50,7 +49,7 @@ const (
// startBloomHandlers starts a batch of goroutines to accept bloom bit database
// startBloomHandlers starts a batch of goroutines to accept bloom bit database
// retrievals from possibly a range of filters and serving the data to satisfy.
// retrievals from possibly a range of filters and serving the data to satisfy.
func
(
eth
*
Ethereum
)
startBloomHandlers
()
{
func
(
eth
*
Ethereum
)
startBloomHandlers
(
sectionSize
uint64
)
{
for
i
:=
0
;
i
<
bloomServiceThreads
;
i
++
{
for
i
:=
0
;
i
<
bloomServiceThreads
;
i
++
{
go
func
()
{
go
func
()
{
for
{
for
{
...
@@ -62,9 +61,9 @@ func (eth *Ethereum) startBloomHandlers() {
...
@@ -62,9 +61,9 @@ func (eth *Ethereum) startBloomHandlers() {
task
:=
<-
request
task
:=
<-
request
task
.
Bitsets
=
make
([][]
byte
,
len
(
task
.
Sections
))
task
.
Bitsets
=
make
([][]
byte
,
len
(
task
.
Sections
))
for
i
,
section
:=
range
task
.
Sections
{
for
i
,
section
:=
range
task
.
Sections
{
head
:=
rawdb
.
ReadCanonicalHash
(
eth
.
chainDb
,
(
section
+
1
)
*
params
.
BloomBitsBlocks
-
1
)
head
:=
rawdb
.
ReadCanonicalHash
(
eth
.
chainDb
,
(
section
+
1
)
*
sectionSize
-
1
)
if
compVector
,
err
:=
rawdb
.
ReadBloomBits
(
eth
.
chainDb
,
task
.
Bit
,
section
,
head
);
err
==
nil
{
if
compVector
,
err
:=
rawdb
.
ReadBloomBits
(
eth
.
chainDb
,
task
.
Bit
,
section
,
head
);
err
==
nil
{
if
blob
,
err
:=
bitutil
.
DecompressBytes
(
compVector
,
int
(
params
.
BloomBitsBlocks
)
/
8
);
err
==
nil
{
if
blob
,
err
:=
bitutil
.
DecompressBytes
(
compVector
,
int
(
sectionSize
/
8
)
);
err
==
nil
{
task
.
Bitsets
[
i
]
=
blob
task
.
Bitsets
[
i
]
=
blob
}
else
{
}
else
{
task
.
Error
=
err
task
.
Error
=
err
...
@@ -81,10 +80,6 @@ func (eth *Ethereum) startBloomHandlers() {
...
@@ -81,10 +80,6 @@ func (eth *Ethereum) startBloomHandlers() {
}
}
const
(
const
(
// bloomConfirms is the number of confirmation blocks before a bloom section is
// considered probably final and its rotated bits are calculated.
bloomConfirms
=
256
// bloomThrottling is the time to wait between processing two consecutive index
// bloomThrottling is the time to wait between processing two consecutive index
// sections. It's useful during chain upgrades to prevent disk overload.
// sections. It's useful during chain upgrades to prevent disk overload.
bloomThrottling
=
100
*
time
.
Millisecond
bloomThrottling
=
100
*
time
.
Millisecond
...
@@ -102,14 +97,14 @@ type BloomIndexer struct {
...
@@ -102,14 +97,14 @@ type BloomIndexer struct {
// NewBloomIndexer returns a chain indexer that generates bloom bits data for the
// NewBloomIndexer returns a chain indexer that generates bloom bits data for the
// canonical chain for fast logs filtering.
// canonical chain for fast logs filtering.
func
NewBloomIndexer
(
db
ethdb
.
Database
,
size
,
conf
Req
uint64
)
*
core
.
ChainIndexer
{
func
NewBloomIndexer
(
db
ethdb
.
Database
,
size
,
conf
irms
uint64
)
*
core
.
ChainIndexer
{
backend
:=
&
BloomIndexer
{
backend
:=
&
BloomIndexer
{
db
:
db
,
db
:
db
,
size
:
size
,
size
:
size
,
}
}
table
:=
ethdb
.
NewTable
(
db
,
string
(
rawdb
.
BloomBitsIndexPrefix
))
table
:=
ethdb
.
NewTable
(
db
,
string
(
rawdb
.
BloomBitsIndexPrefix
))
return
core
.
NewChainIndexer
(
db
,
table
,
backend
,
size
,
conf
Req
,
bloomThrottling
,
"bloombits"
)
return
core
.
NewChainIndexer
(
db
,
table
,
backend
,
size
,
conf
irms
,
bloomThrottling
,
"bloombits"
)
}
}
// Reset implements core.ChainIndexerBackend, starting a new bloombits index
// Reset implements core.ChainIndexerBackend, starting a new bloombits index
...
...
les/api_backend.go
View file @
b69476b3
...
@@ -192,7 +192,7 @@ func (b *LesApiBackend) BloomStatus() (uint64, uint64) {
...
@@ -192,7 +192,7 @@ func (b *LesApiBackend) BloomStatus() (uint64, uint64) {
return
0
,
0
return
0
,
0
}
}
sections
,
_
,
_
:=
b
.
eth
.
bloomIndexer
.
Sections
()
sections
,
_
,
_
:=
b
.
eth
.
bloomIndexer
.
Sections
()
return
light
.
BloomTrieFrequency
,
sections
return
params
.
BloomBitsBlocksClient
,
sections
}
}
func
(
b
*
LesApiBackend
)
ServiceFilter
(
ctx
context
.
Context
,
session
*
bloombits
.
MatcherSession
)
{
func
(
b
*
LesApiBackend
)
ServiceFilter
(
ctx
context
.
Context
,
session
*
bloombits
.
MatcherSession
)
{
...
...
les/backend.go
View file @
b69476b3
...
@@ -95,6 +95,7 @@ func New(ctx *node.ServiceContext, config *eth.Config) (*LightEthereum, error) {
...
@@ -95,6 +95,7 @@ func New(ctx *node.ServiceContext, config *eth.Config) (*LightEthereum, error) {
lesCommons
:
lesCommons
{
lesCommons
:
lesCommons
{
chainDb
:
chainDb
,
chainDb
:
chainDb
,
config
:
config
,
config
:
config
,
iConfig
:
light
.
DefaultClientIndexerConfig
,
},
},
chainConfig
:
chainConfig
,
chainConfig
:
chainConfig
,
eventMux
:
ctx
.
EventMux
,
eventMux
:
ctx
.
EventMux
,
...
@@ -105,16 +106,16 @@ func New(ctx *node.ServiceContext, config *eth.Config) (*LightEthereum, error) {
...
@@ -105,16 +106,16 @@ func New(ctx *node.ServiceContext, config *eth.Config) (*LightEthereum, error) {
shutdownChan
:
make
(
chan
bool
),
shutdownChan
:
make
(
chan
bool
),
networkId
:
config
.
NetworkId
,
networkId
:
config
.
NetworkId
,
bloomRequests
:
make
(
chan
chan
*
bloombits
.
Retrieval
),
bloomRequests
:
make
(
chan
chan
*
bloombits
.
Retrieval
),
bloomIndexer
:
eth
.
NewBloomIndexer
(
chainDb
,
light
.
BloomTrieFrequency
,
light
.
HelperTrieConfirmations
),
bloomIndexer
:
eth
.
NewBloomIndexer
(
chainDb
,
params
.
BloomBitsBlocksClient
,
params
.
HelperTrieConfirmations
),
}
}
leth
.
relay
=
NewLesTxRelay
(
peers
,
leth
.
reqDist
)
leth
.
relay
=
NewLesTxRelay
(
peers
,
leth
.
reqDist
)
leth
.
serverPool
=
newServerPool
(
chainDb
,
quitSync
,
&
leth
.
wg
)
leth
.
serverPool
=
newServerPool
(
chainDb
,
quitSync
,
&
leth
.
wg
)
leth
.
retriever
=
newRetrieveManager
(
peers
,
leth
.
reqDist
,
leth
.
serverPool
)
leth
.
retriever
=
newRetrieveManager
(
peers
,
leth
.
reqDist
,
leth
.
serverPool
)
leth
.
odr
=
NewLesOdr
(
chainDb
,
leth
.
retriever
)
leth
.
odr
=
NewLesOdr
(
chainDb
,
l
ight
.
DefaultClientIndexerConfig
,
l
eth
.
retriever
)
leth
.
chtIndexer
=
light
.
NewChtIndexer
(
chainDb
,
true
,
leth
.
odr
)
leth
.
chtIndexer
=
light
.
NewChtIndexer
(
chainDb
,
leth
.
odr
,
params
.
CHTFrequencyClient
,
params
.
HelperTrieConfirmations
)
leth
.
bloomTrieIndexer
=
light
.
NewBloomTrieIndexer
(
chainDb
,
true
,
leth
.
odr
)
leth
.
bloomTrieIndexer
=
light
.
NewBloomTrieIndexer
(
chainDb
,
leth
.
odr
,
params
.
BloomBitsBlocksClient
,
params
.
BloomTrieFrequency
)
leth
.
odr
.
SetIndexers
(
leth
.
chtIndexer
,
leth
.
bloomTrieIndexer
,
leth
.
bloomIndexer
)
leth
.
odr
.
SetIndexers
(
leth
.
chtIndexer
,
leth
.
bloomTrieIndexer
,
leth
.
bloomIndexer
)
// Note: NewLightChain adds the trusted checkpoint so it needs an ODR with
// Note: NewLightChain adds the trusted checkpoint so it needs an ODR with
...
@@ -135,7 +136,7 @@ func New(ctx *node.ServiceContext, config *eth.Config) (*LightEthereum, error) {
...
@@ -135,7 +136,7 @@ func New(ctx *node.ServiceContext, config *eth.Config) (*LightEthereum, error) {
}
}
leth
.
txPool
=
light
.
NewTxPool
(
leth
.
chainConfig
,
leth
.
blockchain
,
leth
.
relay
)
leth
.
txPool
=
light
.
NewTxPool
(
leth
.
chainConfig
,
leth
.
blockchain
,
leth
.
relay
)
if
leth
.
protocolManager
,
err
=
NewProtocolManager
(
leth
.
chainConfig
,
true
,
config
.
NetworkId
,
leth
.
eventMux
,
leth
.
engine
,
leth
.
peers
,
leth
.
blockchain
,
nil
,
chainDb
,
leth
.
odr
,
leth
.
relay
,
leth
.
serverPool
,
quitSync
,
&
leth
.
wg
);
err
!=
nil
{
if
leth
.
protocolManager
,
err
=
NewProtocolManager
(
leth
.
chainConfig
,
light
.
DefaultClientIndexerConfig
,
true
,
config
.
NetworkId
,
leth
.
eventMux
,
leth
.
engine
,
leth
.
peers
,
leth
.
blockchain
,
nil
,
chainDb
,
leth
.
odr
,
leth
.
relay
,
leth
.
serverPool
,
quitSync
,
&
leth
.
wg
);
err
!=
nil
{
return
nil
,
err
return
nil
,
err
}
}
leth
.
ApiBackend
=
&
LesApiBackend
{
leth
,
nil
}
leth
.
ApiBackend
=
&
LesApiBackend
{
leth
,
nil
}
...
@@ -230,8 +231,8 @@ func (s *LightEthereum) Protocols() []p2p.Protocol {
...
@@ -230,8 +231,8 @@ func (s *LightEthereum) Protocols() []p2p.Protocol {
// Start implements node.Service, starting all internal goroutines needed by the
// Start implements node.Service, starting all internal goroutines needed by the
// Ethereum protocol implementation.
// Ethereum protocol implementation.
func
(
s
*
LightEthereum
)
Start
(
srvr
*
p2p
.
Server
)
error
{
func
(
s
*
LightEthereum
)
Start
(
srvr
*
p2p
.
Server
)
error
{
s
.
startBloomHandlers
()
log
.
Warn
(
"Light client mode is an experimental feature"
)
log
.
Warn
(
"Light client mode is an experimental feature"
)
s
.
startBloomHandlers
(
params
.
BloomBitsBlocksClient
)
s
.
netRPCService
=
ethapi
.
NewPublicNetAPI
(
srvr
,
s
.
networkId
)
s
.
netRPCService
=
ethapi
.
NewPublicNetAPI
(
srvr
,
s
.
networkId
)
// clients are searching for the first advertised protocol in the list
// clients are searching for the first advertised protocol in the list
protocolVersion
:=
AdvertiseProtocolVersions
[
0
]
protocolVersion
:=
AdvertiseProtocolVersions
[
0
]
...
...
les/bloombits.go
View file @
b69476b3
...
@@ -43,7 +43,7 @@ const (
...
@@ -43,7 +43,7 @@ const (
// startBloomHandlers starts a batch of goroutines to accept bloom bit database
// startBloomHandlers starts a batch of goroutines to accept bloom bit database
// retrievals from possibly a range of filters and serving the data to satisfy.
// retrievals from possibly a range of filters and serving the data to satisfy.
func
(
eth
*
LightEthereum
)
startBloomHandlers
()
{
func
(
eth
*
LightEthereum
)
startBloomHandlers
(
sectionSize
uint64
)
{
for
i
:=
0
;
i
<
bloomServiceThreads
;
i
++
{
for
i
:=
0
;
i
<
bloomServiceThreads
;
i
++
{
go
func
()
{
go
func
()
{
for
{
for
{
...
@@ -57,7 +57,7 @@ func (eth *LightEthereum) startBloomHandlers() {
...
@@ -57,7 +57,7 @@ func (eth *LightEthereum) startBloomHandlers() {
compVectors
,
err
:=
light
.
GetBloomBits
(
task
.
Context
,
eth
.
odr
,
task
.
Bit
,
task
.
Sections
)
compVectors
,
err
:=
light
.
GetBloomBits
(
task
.
Context
,
eth
.
odr
,
task
.
Bit
,
task
.
Sections
)
if
err
==
nil
{
if
err
==
nil
{
for
i
:=
range
task
.
Sections
{
for
i
:=
range
task
.
Sections
{
if
blob
,
err
:=
bitutil
.
DecompressBytes
(
compVectors
[
i
],
int
(
light
.
BloomTrieFrequency
/
8
));
err
==
nil
{
if
blob
,
err
:=
bitutil
.
DecompressBytes
(
compVectors
[
i
],
int
(
sectionSize
/
8
));
err
==
nil
{
task
.
Bitsets
[
i
]
=
blob
task
.
Bitsets
[
i
]
=
blob
}
else
{
}
else
{
task
.
Error
=
err
task
.
Error
=
err
...
...
les/commons.go
View file @
b69476b3
...
@@ -33,6 +33,7 @@ import (
...
@@ -33,6 +33,7 @@ import (
// lesCommons contains fields needed by both server and client.
// lesCommons contains fields needed by both server and client.
type
lesCommons
struct
{
type
lesCommons
struct
{
config
*
eth
.
Config
config
*
eth
.
Config
iConfig
*
light
.
IndexerConfig
chainDb
ethdb
.
Database
chainDb
ethdb
.
Database
protocolManager
*
ProtocolManager
protocolManager
*
ProtocolManager
chtIndexer
,
bloomTrieIndexer
*
core
.
ChainIndexer
chtIndexer
,
bloomTrieIndexer
*
core
.
ChainIndexer
...
@@ -81,7 +82,7 @@ func (c *lesCommons) nodeInfo() interface{} {
...
@@ -81,7 +82,7 @@ func (c *lesCommons) nodeInfo() interface{} {
if
!
c
.
protocolManager
.
lightSync
{
if
!
c
.
protocolManager
.
lightSync
{
// convert to client section size if running in server mode
// convert to client section size if running in server mode
sections
/=
light
.
CHTFrequencyClient
/
light
.
CHTFrequencyServer
sections
/=
c
.
iConfig
.
PairChtSize
/
c
.
iConfig
.
ChtSize
}
}
if
sections2
<
sections
{
if
sections2
<
sections
{
...
@@ -94,7 +95,8 @@ func (c *lesCommons) nodeInfo() interface{} {
...
@@ -94,7 +95,8 @@ func (c *lesCommons) nodeInfo() interface{} {
if
c
.
protocolManager
.
lightSync
{
if
c
.
protocolManager
.
lightSync
{
chtRoot
=
light
.
GetChtRoot
(
c
.
chainDb
,
sectionIndex
,
sectionHead
)
chtRoot
=
light
.
GetChtRoot
(
c
.
chainDb
,
sectionIndex
,
sectionHead
)
}
else
{
}
else
{
chtRoot
=
light
.
GetChtV2Root
(
c
.
chainDb
,
sectionIndex
,
sectionHead
)
idxV2
:=
(
sectionIndex
+
1
)
*
c
.
iConfig
.
PairChtSize
/
c
.
iConfig
.
ChtSize
-
1
chtRoot
=
light
.
GetChtRoot
(
c
.
chainDb
,
idxV2
,
sectionHead
)
}
}
cht
=
light
.
TrustedCheckpoint
{
cht
=
light
.
TrustedCheckpoint
{
SectionIdx
:
sectionIndex
,
SectionIdx
:
sectionIndex
,
...
...
les/handler.go
View file @
b69476b3
...
@@ -94,6 +94,7 @@ type ProtocolManager struct {
...
@@ -94,6 +94,7 @@ type ProtocolManager struct {
txrelay
*
LesTxRelay
txrelay
*
LesTxRelay
networkId
uint64
networkId
uint64
chainConfig
*
params
.
ChainConfig
chainConfig
*
params
.
ChainConfig
iConfig
*
light
.
IndexerConfig
blockchain
BlockChain
blockchain
BlockChain
chainDb
ethdb
.
Database
chainDb
ethdb
.
Database
odr
*
LesOdr
odr
*
LesOdr
...
@@ -123,13 +124,14 @@ type ProtocolManager struct {
...
@@ -123,13 +124,14 @@ type ProtocolManager struct {
// NewProtocolManager returns a new ethereum sub protocol manager. The Ethereum sub protocol manages peers capable
// NewProtocolManager returns a new ethereum sub protocol manager. The Ethereum sub protocol manages peers capable
// with the ethereum network.
// with the ethereum network.
func
NewProtocolManager
(
chainConfig
*
params
.
ChainConfig
,
lightSync
bool
,
networkId
uint64
,
mux
*
event
.
TypeMux
,
engine
consensus
.
Engine
,
peers
*
peerSet
,
blockchain
BlockChain
,
txpool
txPool
,
chainDb
ethdb
.
Database
,
odr
*
LesOdr
,
txrelay
*
LesTxRelay
,
serverPool
*
serverPool
,
quitSync
chan
struct
{},
wg
*
sync
.
WaitGroup
)
(
*
ProtocolManager
,
error
)
{
func
NewProtocolManager
(
chainConfig
*
params
.
ChainConfig
,
indexerConfig
*
light
.
IndexerConfig
,
lightSync
bool
,
networkId
uint64
,
mux
*
event
.
TypeMux
,
engine
consensus
.
Engine
,
peers
*
peerSet
,
blockchain
BlockChain
,
txpool
txPool
,
chainDb
ethdb
.
Database
,
odr
*
LesOdr
,
txrelay
*
LesTxRelay
,
serverPool
*
serverPool
,
quitSync
chan
struct
{},
wg
*
sync
.
WaitGroup
)
(
*
ProtocolManager
,
error
)
{
// Create the protocol manager with the base fields
// Create the protocol manager with the base fields
manager
:=
&
ProtocolManager
{
manager
:=
&
ProtocolManager
{
lightSync
:
lightSync
,
lightSync
:
lightSync
,
eventMux
:
mux
,
eventMux
:
mux
,
blockchain
:
blockchain
,
blockchain
:
blockchain
,
chainConfig
:
chainConfig
,
chainConfig
:
chainConfig
,
iConfig
:
indexerConfig
,
chainDb
:
chainDb
,
chainDb
:
chainDb
,
odr
:
odr
,
odr
:
odr
,
networkId
:
networkId
,
networkId
:
networkId
,
...
@@ -882,7 +884,7 @@ func (pm *ProtocolManager) handleMsg(p *peer) error {
...
@@ -882,7 +884,7 @@ func (pm *ProtocolManager) handleMsg(p *peer) error {
trieDb
:=
trie
.
NewDatabase
(
ethdb
.
NewTable
(
pm
.
chainDb
,
light
.
ChtTablePrefix
))
trieDb
:=
trie
.
NewDatabase
(
ethdb
.
NewTable
(
pm
.
chainDb
,
light
.
ChtTablePrefix
))
for
_
,
req
:=
range
req
.
Reqs
{
for
_
,
req
:=
range
req
.
Reqs
{
if
header
:=
pm
.
blockchain
.
GetHeaderByNumber
(
req
.
BlockNum
);
header
!=
nil
{
if
header
:=
pm
.
blockchain
.
GetHeaderByNumber
(
req
.
BlockNum
);
header
!=
nil
{
sectionHead
:=
rawdb
.
ReadCanonicalHash
(
pm
.
chainDb
,
req
.
ChtNum
*
light
.
CHTFrequencyServer
-
1
)
sectionHead
:=
rawdb
.
ReadCanonicalHash
(
pm
.
chainDb
,
req
.
ChtNum
*
pm
.
iConfig
.
ChtSize
-
1
)
if
root
:=
light
.
GetChtRoot
(
pm
.
chainDb
,
req
.
ChtNum
-
1
,
sectionHead
);
root
!=
(
common
.
Hash
{})
{
if
root
:=
light
.
GetChtRoot
(
pm
.
chainDb
,
req
.
ChtNum
-
1
,
sectionHead
);
root
!=
(
common
.
Hash
{})
{
trie
,
err
:=
trie
.
New
(
root
,
trieDb
)
trie
,
err
:=
trie
.
New
(
root
,
trieDb
)
if
err
!=
nil
{
if
err
!=
nil
{
...
@@ -1137,10 +1139,11 @@ func (pm *ProtocolManager) getAccount(statedb *state.StateDB, root, hash common.
...
@@ -1137,10 +1139,11 @@ func (pm *ProtocolManager) getAccount(statedb *state.StateDB, root, hash common.
func
(
pm
*
ProtocolManager
)
getHelperTrie
(
id
uint
,
idx
uint64
)
(
common
.
Hash
,
string
)
{
func
(
pm
*
ProtocolManager
)
getHelperTrie
(
id
uint
,
idx
uint64
)
(
common
.
Hash
,
string
)
{
switch
id
{
switch
id
{
case
htCanonical
:
case
htCanonical
:
sectionHead
:=
rawdb
.
ReadCanonicalHash
(
pm
.
chainDb
,
(
idx
+
1
)
*
light
.
CHTFrequencyClient
-
1
)
idxV1
:=
(
idx
+
1
)
*
(
pm
.
iConfig
.
PairChtSize
/
pm
.
iConfig
.
ChtSize
)
-
1
return
light
.
GetChtV2Root
(
pm
.
chainDb
,
idx
,
sectionHead
),
light
.
ChtTablePrefix
sectionHead
:=
rawdb
.
ReadCanonicalHash
(
pm
.
chainDb
,
(
idxV1
+
1
)
*
pm
.
iConfig
.
ChtSize
-
1
)
return
light
.
GetChtRoot
(
pm
.
chainDb
,
idxV1
,
sectionHead
),
light
.
ChtTablePrefix
case
htBloomBits
:
case
htBloomBits
:
sectionHead
:=
rawdb
.
ReadCanonicalHash
(
pm
.
chainDb
,
(
idx
+
1
)
*
light
.
BloomTrieFrequency
-
1
)
sectionHead
:=
rawdb
.
ReadCanonicalHash
(
pm
.
chainDb
,
(
idx
+
1
)
*
pm
.
iConfig
.
BloomTrieSize
-
1
)
return
light
.
GetBloomTrieRoot
(
pm
.
chainDb
,
idx
,
sectionHead
),
light
.
BloomTrieTablePrefix
return
light
.
GetBloomTrieRoot
(
pm
.
chainDb
,
idx
,
sectionHead
),
light
.
BloomTrieTablePrefix
}
}
return
common
.
Hash
{},
""
return
common
.
Hash
{},
""
...
...
les/handler_test.go
View file @
b69476b3
This diff is collapsed.
Click to expand it.
les/helper_test.go
View file @
b69476b3
...
@@ -24,6 +24,7 @@ import (
...
@@ -24,6 +24,7 @@ import (
"math/big"
"math/big"
"sync"
"sync"
"testing"
"testing"
"time"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/consensus/ethash"
"github.com/ethereum/go-ethereum/consensus/ethash"
...
@@ -123,6 +124,15 @@ func testChainGen(i int, block *core.BlockGen) {
...
@@ -123,6 +124,15 @@ func testChainGen(i int, block *core.BlockGen) {
}
}
}
}
// testIndexers creates a set of indexers with specified params for testing purpose.
func
testIndexers
(
db
ethdb
.
Database
,
odr
light
.
OdrBackend
,
iConfig
*
light
.
IndexerConfig
)
(
*
core
.
ChainIndexer
,
*
core
.
ChainIndexer
,
*
core
.
ChainIndexer
)
{
chtIndexer
:=
light
.
NewChtIndexer
(
db
,
odr
,
iConfig
.
ChtSize
,
iConfig
.
ChtConfirms
)
bloomIndexer
:=
eth
.
NewBloomIndexer
(
db
,
iConfig
.
BloomSize
,
iConfig
.
BloomConfirms
)
bloomTrieIndexer
:=
light
.
NewBloomTrieIndexer
(
db
,
odr
,
iConfig
.
BloomSize
,
iConfig
.
BloomTrieSize
)
bloomIndexer
.
AddChildIndexer
(
bloomTrieIndexer
)
return
chtIndexer
,
bloomIndexer
,
bloomTrieIndexer
}
func
testRCL
()
RequestCostList
{
func
testRCL
()
RequestCostList
{
cl
:=
make
(
RequestCostList
,
len
(
reqList
))
cl
:=
make
(
RequestCostList
,
len
(
reqList
))
for
i
,
code
:=
range
reqList
{
for
i
,
code
:=
range
reqList
{
...
@@ -134,9 +144,9 @@ func testRCL() RequestCostList {
...
@@ -134,9 +144,9 @@ func testRCL() RequestCostList {
}
}
// newTestProtocolManager creates a new protocol manager for testing purposes,
// newTestProtocolManager creates a new protocol manager for testing purposes,
// with the given number of blocks already known,
and
potential notification
// with the given number of blocks already known, potential notification
// channels for different events.
// channels for different events
and relative chain indexers array
.
func
newTestProtocolManager
(
lightSync
bool
,
blocks
int
,
generator
func
(
int
,
*
core
.
BlockGen
),
peers
*
peerSet
,
odr
*
LesOdr
,
db
ethdb
.
Database
)
(
*
ProtocolManager
,
error
)
{
func
newTestProtocolManager
(
lightSync
bool
,
blocks
int
,
generator
func
(
int
,
*
core
.
BlockGen
),
odr
*
LesOdr
,
peers
*
peerSet
,
db
ethdb
.
Database
)
(
*
ProtocolManager
,
error
)
{
var
(
var
(
evmux
=
new
(
event
.
TypeMux
)
evmux
=
new
(
event
.
TypeMux
)
engine
=
ethash
.
NewFaker
()
engine
=
ethash
.
NewFaker
()
...
@@ -155,16 +165,6 @@ func newTestProtocolManager(lightSync bool, blocks int, generator func(int, *cor
...
@@ -155,16 +165,6 @@ func newTestProtocolManager(lightSync bool, blocks int, generator func(int, *cor
chain
,
_
=
light
.
NewLightChain
(
odr
,
gspec
.
Config
,
engine
)
chain
,
_
=
light
.
NewLightChain
(
odr
,
gspec
.
Config
,
engine
)
}
else
{
}
else
{
blockchain
,
_
:=
core
.
NewBlockChain
(
db
,
nil
,
gspec
.
Config
,
engine
,
vm
.
Config
{})
blockchain
,
_
:=
core
.
NewBlockChain
(
db
,
nil
,
gspec
.
Config
,
engine
,
vm
.
Config
{})
chtIndexer
:=
light
.
NewChtIndexer
(
db
,
false
,
nil
)
chtIndexer
.
Start
(
blockchain
)
bbtIndexer
:=
light
.
NewBloomTrieIndexer
(
db
,
false
,
nil
)
bloomIndexer
:=
eth
.
NewBloomIndexer
(
db
,
params
.
BloomBitsBlocks
,
light
.
HelperTrieProcessConfirmations
)
bloomIndexer
.
AddChildIndexer
(
bbtIndexer
)
bloomIndexer
.
Start
(
blockchain
)
gchain
,
_
:=
core
.
GenerateChain
(
gspec
.
Config
,
genesis
,
ethash
.
NewFaker
(),
db
,
blocks
,
generator
)
gchain
,
_
:=
core
.
GenerateChain
(
gspec
.
Config
,
genesis
,
ethash
.
NewFaker
(),
db
,
blocks
,
generator
)
if
_
,
err
:=
blockchain
.
InsertChain
(
gchain
);
err
!=
nil
{
if
_
,
err
:=
blockchain
.
InsertChain
(
gchain
);
err
!=
nil
{
panic
(
err
)
panic
(
err
)
...
@@ -172,7 +172,11 @@ func newTestProtocolManager(lightSync bool, blocks int, generator func(int, *cor
...
@@ -172,7 +172,11 @@ func newTestProtocolManager(lightSync bool, blocks int, generator func(int, *cor
chain
=
blockchain
chain
=
blockchain
}
}
pm
,
err
:=
NewProtocolManager
(
gspec
.
Config
,
lightSync
,
NetworkId
,
evmux
,
engine
,
peers
,
chain
,
nil
,
db
,
odr
,
nil
,
nil
,
make
(
chan
struct
{}),
new
(
sync
.
WaitGroup
))
indexConfig
:=
light
.
TestServerIndexerConfig
if
lightSync
{
indexConfig
=
light
.
TestClientIndexerConfig
}
pm
,
err
:=
NewProtocolManager
(
gspec
.
Config
,
indexConfig
,
lightSync
,
NetworkId
,
evmux
,
engine
,
peers
,
chain
,
nil
,
db
,
odr
,
nil
,
nil
,
make
(
chan
struct
{}),
new
(
sync
.
WaitGroup
))
if
err
!=
nil
{
if
err
!=
nil
{
return
nil
,
err
return
nil
,
err
}
}
...
@@ -193,11 +197,11 @@ func newTestProtocolManager(lightSync bool, blocks int, generator func(int, *cor
...
@@ -193,11 +197,11 @@ func newTestProtocolManager(lightSync bool, blocks int, generator func(int, *cor
}
}
// newTestProtocolManagerMust creates a new protocol manager for testing purposes,
// newTestProtocolManagerMust creates a new protocol manager for testing purposes,
// with the given number of blocks already known,
and
potential notification
// with the given number of blocks already known, potential notification
// channels for different events. In case of an error, the constructor force-
// channels for different events
and relative chain indexers array
. In case of an error, the constructor force-
// fails the test.
// fails the test.
func
newTestProtocolManagerMust
(
t
*
testing
.
T
,
lightSync
bool
,
blocks
int
,
generator
func
(
int
,
*
core
.
BlockGen
),
peers
*
peerSet
,
odr
*
LesOdr
,
db
ethdb
.
Database
)
*
ProtocolManager
{
func
newTestProtocolManagerMust
(
t
*
testing
.
T
,
lightSync
bool
,
blocks
int
,
generator
func
(
int
,
*
core
.
BlockGen
),
odr
*
LesOdr
,
peers
*
peerSet
,
db
ethdb
.
Database
)
*
ProtocolManager
{
pm
,
err
:=
newTestProtocolManager
(
lightSync
,
blocks
,
generator
,
peers
,
odr
,
db
)
pm
,
err
:=
newTestProtocolManager
(
lightSync
,
blocks
,
generator
,
odr
,
peers
,
db
)
if
err
!=
nil
{
if
err
!=
nil
{
t
.
Fatalf
(
"Failed to create protocol manager: %v"
,
err
)
t
.
Fatalf
(
"Failed to create protocol manager: %v"
,
err
)
}
}
...
@@ -320,3 +324,122 @@ func (p *testPeer) handshake(t *testing.T, td *big.Int, head common.Hash, headNu
...
@@ -320,3 +324,122 @@ func (p *testPeer) handshake(t *testing.T, td *big.Int, head common.Hash, headNu
func
(
p
*
testPeer
)
close
()
{
func
(
p
*
testPeer
)
close
()
{
p
.
app
.
Close
()
p
.
app
.
Close
()
}
}
// TestEntity represents a network entity for testing with necessary auxiliary fields.
type
TestEntity
struct
{
db
ethdb
.
Database
rPeer
*
peer
tPeer
*
testPeer
peers
*
peerSet
pm
*
ProtocolManager
// Indexers
chtIndexer
*
core
.
ChainIndexer
bloomIndexer
*
core
.
ChainIndexer
bloomTrieIndexer
*
core
.
ChainIndexer
}
// newServerEnv creates a server testing environment with a connected test peer for testing purpose.
func
newServerEnv
(
t
*
testing
.
T
,
blocks
int
,
protocol
int
,
waitIndexers
func
(
*
core
.
ChainIndexer
,
*
core
.
ChainIndexer
,
*
core
.
ChainIndexer
))
(
*
TestEntity
,
func
())
{
db
:=
ethdb
.
NewMemDatabase
()
cIndexer
,
bIndexer
,
btIndexer
:=
testIndexers
(
db
,
nil
,
light
.
TestServerIndexerConfig
)
pm
:=
newTestProtocolManagerMust
(
t
,
false
,
blocks
,
testChainGen
,
nil
,
nil
,
db
)
peer
,
_
:=
newTestPeer
(
t
,
"peer"
,
protocol
,
pm
,
true
)
cIndexer
.
Start
(
pm
.
blockchain
.
(
*
core
.
BlockChain
))
bIndexer
.
Start
(
pm
.
blockchain
.
(
*
core
.
BlockChain
))
// Wait until indexers generate enough index data.
if
waitIndexers
!=
nil
{
waitIndexers
(
cIndexer
,
bIndexer
,
btIndexer
)
}
return
&
TestEntity
{
db
:
db
,
tPeer
:
peer
,
pm
:
pm
,
chtIndexer
:
cIndexer
,
bloomIndexer
:
bIndexer
,
bloomTrieIndexer
:
btIndexer
,
},
func
()
{
peer
.
close
()
// Note bloom trie indexer will be closed by it parent recursively.
cIndexer
.
Close
()
bIndexer
.
Close
()
}
}
// newClientServerEnv creates a client/server arch environment with a connected les server and light client pair
// for testing purpose.
func
newClientServerEnv
(
t
*
testing
.
T
,
blocks
int
,
protocol
int
,
waitIndexers
func
(
*
core
.
ChainIndexer
,
*
core
.
ChainIndexer
,
*
core
.
ChainIndexer
),
newPeer
bool
)
(
*
TestEntity
,
*
TestEntity
,
func
())
{
db
,
ldb
:=
ethdb
.
NewMemDatabase
(),
ethdb
.
NewMemDatabase
()
peers
,
lPeers
:=
newPeerSet
(),
newPeerSet
()
dist
:=
newRequestDistributor
(
lPeers
,
make
(
chan
struct
{}))
rm
:=
newRetrieveManager
(
lPeers
,
dist
,
nil
)
odr
:=
NewLesOdr
(
ldb
,
light
.
TestClientIndexerConfig
,
rm
)
cIndexer
,
bIndexer
,
btIndexer
:=
testIndexers
(
db
,
nil
,
light
.
TestServerIndexerConfig
)
lcIndexer
,
lbIndexer
,
lbtIndexer
:=
testIndexers
(
ldb
,
odr
,
light
.
TestClientIndexerConfig
)
odr
.
SetIndexers
(
lcIndexer
,
lbtIndexer
,
lbIndexer
)
pm
:=
newTestProtocolManagerMust
(
t
,
false
,
blocks
,
testChainGen
,
nil
,
peers
,
db
)
lpm
:=
newTestProtocolManagerMust
(
t
,
true
,
0
,
nil
,
odr
,
lPeers
,
ldb
)
startIndexers
:=
func
(
clientMode
bool
,
pm
*
ProtocolManager
)
{
if
clientMode
{
lcIndexer
.
Start
(
pm
.
blockchain
.
(
*
light
.
LightChain
))
lbIndexer
.
Start
(
pm
.
blockchain
.
(
*
light
.
LightChain
))
}
else
{
cIndexer
.
Start
(
pm
.
blockchain
.
(
*
core
.
BlockChain
))
bIndexer
.
Start
(
pm
.
blockchain
.
(
*
core
.
BlockChain
))
}
}
startIndexers
(
false
,
pm
)
startIndexers
(
true
,
lpm
)
// Execute wait until function if it is specified.
if
waitIndexers
!=
nil
{
waitIndexers
(
cIndexer
,
bIndexer
,
btIndexer
)
}
var
(
peer
,
lPeer
*
peer
err1
,
err2
<-
chan
error
)
if
newPeer
{
peer
,
err1
,
lPeer
,
err2
=
newTestPeerPair
(
"peer"
,
protocol
,
pm
,
lpm
)
select
{
case
<-
time
.
After
(
time
.
Millisecond
*
100
)
:
case
err
:=
<-
err1
:
t
.
Fatalf
(
"peer 1 handshake error: %v"
,
err
)
case
err
:=
<-
err2
:
t
.
Fatalf
(
"peer 2 handshake error: %v"
,
err
)
}
}
return
&
TestEntity
{
db
:
db
,
pm
:
pm
,
rPeer
:
peer
,
peers
:
peers
,
chtIndexer
:
cIndexer
,
bloomIndexer
:
bIndexer
,
bloomTrieIndexer
:
btIndexer
,
},
&
TestEntity
{
db
:
ldb
,
pm
:
lpm
,
rPeer
:
lPeer
,
peers
:
lPeers
,
chtIndexer
:
lcIndexer
,
bloomIndexer
:
lbIndexer
,
bloomTrieIndexer
:
lbtIndexer
,
},
func
()
{
// Note bloom trie indexers will be closed by their parents recursively.
cIndexer
.
Close
()
bIndexer
.
Close
()
lcIndexer
.
Close
()
lbIndexer
.
Close
()
}
}
les/odr.go
View file @
b69476b3
...
@@ -28,16 +28,18 @@ import (
...
@@ -28,16 +28,18 @@ import (
// LesOdr implements light.OdrBackend
// LesOdr implements light.OdrBackend
type
LesOdr
struct
{
type
LesOdr
struct
{
db
ethdb
.
Database
db
ethdb
.
Database
indexerConfig
*
light
.
IndexerConfig
chtIndexer
,
bloomTrieIndexer
,
bloomIndexer
*
core
.
ChainIndexer
chtIndexer
,
bloomTrieIndexer
,
bloomIndexer
*
core
.
ChainIndexer
retriever
*
retrieveManager
retriever
*
retrieveManager
stop
chan
struct
{}
stop
chan
struct
{}
}
}
func
NewLesOdr
(
db
ethdb
.
Database
,
retriever
*
retrieveManager
)
*
LesOdr
{
func
NewLesOdr
(
db
ethdb
.
Database
,
config
*
light
.
IndexerConfig
,
retriever
*
retrieveManager
)
*
LesOdr
{
return
&
LesOdr
{
return
&
LesOdr
{
db
:
db
,
db
:
db
,
retriever
:
retriever
,
indexerConfig
:
config
,
stop
:
make
(
chan
struct
{}),
retriever
:
retriever
,
stop
:
make
(
chan
struct
{}),
}
}
}
}
...
@@ -73,6 +75,11 @@ func (odr *LesOdr) BloomIndexer() *core.ChainIndexer {
...
@@ -73,6 +75,11 @@ func (odr *LesOdr) BloomIndexer() *core.ChainIndexer {
return
odr
.
bloomIndexer
return
odr
.
bloomIndexer
}
}
// IndexerConfig returns the indexer config.
func
(
odr
*
LesOdr
)
IndexerConfig
()
*
light
.
IndexerConfig
{
return
odr
.
indexerConfig
}
const
(
const
(
MsgBlockBodies
=
iota
MsgBlockBodies
=
iota
MsgCode
MsgCode
...
...
les/odr_requests.go
View file @
b69476b3
...
@@ -365,7 +365,7 @@ func (r *ChtRequest) CanSend(peer *peer) bool {
...
@@ -365,7 +365,7 @@ func (r *ChtRequest) CanSend(peer *peer) bool {
peer
.
lock
.
RLock
()
peer
.
lock
.
RLock
()
defer
peer
.
lock
.
RUnlock
()
defer
peer
.
lock
.
RUnlock
()
return
peer
.
headInfo
.
Number
>=
light
.
HelperTrieConfirmations
&&
r
.
ChtNum
<=
(
peer
.
headInfo
.
Number
-
light
.
HelperTrieConfirmations
)
/
light
.
CHTFrequencyClient
return
peer
.
headInfo
.
Number
>=
r
.
Config
.
ChtConfirms
&&
r
.
ChtNum
<=
(
peer
.
headInfo
.
Number
-
r
.
Config
.
ChtConfirms
)
/
r
.
Config
.
ChtSize
}
}
// Request sends an ODR request to the LES network (implementation of LesOdrRequest)
// Request sends an ODR request to the LES network (implementation of LesOdrRequest)
...
@@ -379,7 +379,21 @@ func (r *ChtRequest) Request(reqID uint64, peer *peer) error {
...
@@ -379,7 +379,21 @@ func (r *ChtRequest) Request(reqID uint64, peer *peer) error {
Key
:
encNum
[
:
],
Key
:
encNum
[
:
],
AuxReq
:
auxHeader
,
AuxReq
:
auxHeader
,
}
}
return
peer
.
RequestHelperTrieProofs
(
reqID
,
r
.
GetCost
(
peer
),
[]
HelperTrieReq
{
req
})
switch
peer
.
version
{
case
lpv1
:
var
reqsV1
ChtReq
if
req
.
Type
!=
htCanonical
||
req
.
AuxReq
!=
auxHeader
||
len
(
req
.
Key
)
!=
8
{
return
fmt
.
Errorf
(
"Request invalid in LES/1 mode"
)
}
blockNum
:=
binary
.
BigEndian
.
Uint64
(
req
.
Key
)
// convert HelperTrie request to old CHT request
reqsV1
=
ChtReq
{
ChtNum
:
(
req
.
TrieIdx
+
1
)
*
(
r
.
Config
.
ChtSize
/
r
.
Config
.
PairChtSize
),
BlockNum
:
blockNum
,
FromLevel
:
req
.
FromLevel
}
return
peer
.
RequestHelperTrieProofs
(
reqID
,
r
.
GetCost
(
peer
),
[]
ChtReq
{
reqsV1
})
case
lpv2
:
return
peer
.
RequestHelperTrieProofs
(
reqID
,
r
.
GetCost
(
peer
),
[]
HelperTrieReq
{
req
})
default
:
panic
(
nil
)
}
}
}
// Valid processes an ODR request reply message from the LES network
// Valid processes an ODR request reply message from the LES network
...
@@ -484,7 +498,7 @@ func (r *BloomRequest) CanSend(peer *peer) bool {
...
@@ -484,7 +498,7 @@ func (r *BloomRequest) CanSend(peer *peer) bool {
if
peer
.
version
<
lpv2
{
if
peer
.
version
<
lpv2
{
return
false
return
false
}
}
return
peer
.
headInfo
.
Number
>=
light
.
HelperTrieConfirmations
&&
r
.
BloomTrieNum
<=
(
peer
.
headInfo
.
Number
-
light
.
HelperTrieConfirmations
)
/
light
.
BloomTrieFrequency
return
peer
.
headInfo
.
Number
>=
r
.
Config
.
BloomTrieConfirms
&&
r
.
BloomTrieNum
<=
(
peer
.
headInfo
.
Number
-
r
.
Config
.
BloomTrieConfirms
)
/
r
.
Config
.
BloomTrieSize
}
}
// Request sends an ODR request to the LES network (implementation of LesOdrRequest)
// Request sends an ODR request to the LES network (implementation of LesOdrRequest)
...
...
les/odr_test.go
View file @
b69476b3
...
@@ -30,7 +30,6 @@ import (
...
@@ -30,7 +30,6 @@ import (
"github.com/ethereum/go-ethereum/core/state"
"github.com/ethereum/go-ethereum/core/state"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/core/vm"
"github.com/ethereum/go-ethereum/core/vm"
"github.com/ethereum/go-ethereum/eth"
"github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/light"
"github.com/ethereum/go-ethereum/light"
"github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/params"
...
@@ -160,36 +159,21 @@ func odrContractCall(ctx context.Context, db ethdb.Database, config *params.Chai
...
@@ -160,36 +159,21 @@ func odrContractCall(ctx context.Context, db ethdb.Database, config *params.Chai
return
res
return
res
}
}
// testOdr tests odr requests whose validation guaranteed by block headers.
func
testOdr
(
t
*
testing
.
T
,
protocol
int
,
expFail
uint64
,
fn
odrTestFn
)
{
func
testOdr
(
t
*
testing
.
T
,
protocol
int
,
expFail
uint64
,
fn
odrTestFn
)
{
// Assemble the test environment
// Assemble the test environment
peers
:=
newPeerSet
()
server
,
client
,
tearDown
:=
newClientServerEnv
(
t
,
4
,
protocol
,
nil
,
true
)
dist
:=
newRequestDistributor
(
peers
,
make
(
chan
struct
{}))
defer
tearDown
()
rm
:=
newRetrieveManager
(
peers
,
dist
,
nil
)
client
.
pm
.
synchronise
(
client
.
rPeer
)
db
:=
ethdb
.
NewMemDatabase
()
ldb
:=
ethdb
.
NewMemDatabase
()
odr
:=
NewLesOdr
(
ldb
,
rm
)
odr
.
SetIndexers
(
light
.
NewChtIndexer
(
db
,
true
,
nil
),
light
.
NewBloomTrieIndexer
(
db
,
true
,
nil
),
eth
.
NewBloomIndexer
(
db
,
light
.
BloomTrieFrequency
,
light
.
HelperTrieConfirmations
))
pm
:=
newTestProtocolManagerMust
(
t
,
false
,
4
,
testChainGen
,
nil
,
nil
,
db
)
lpm
:=
newTestProtocolManagerMust
(
t
,
true
,
0
,
nil
,
peers
,
odr
,
ldb
)
_
,
err1
,
lpeer
,
err2
:=
newTestPeerPair
(
"peer"
,
protocol
,
pm
,
lpm
)
select
{
case
<-
time
.
After
(
time
.
Millisecond
*
100
)
:
case
err
:=
<-
err1
:
t
.
Fatalf
(
"peer 1 handshake error: %v"
,
err
)
case
err
:=
<-
err2
:
t
.
Fatalf
(
"peer 1 handshake error: %v"
,
err
)
}
lpm
.
synchronise
(
lpeer
)
test
:=
func
(
expFail
uint64
)
{
test
:=
func
(
expFail
uint64
)
{
for
i
:=
uint64
(
0
);
i
<=
pm
.
blockchain
.
CurrentHeader
()
.
Number
.
Uint64
();
i
++
{
for
i
:=
uint64
(
0
);
i
<=
server
.
pm
.
blockchain
.
CurrentHeader
()
.
Number
.
Uint64
();
i
++
{
bhash
:=
rawdb
.
ReadCanonicalHash
(
db
,
i
)
bhash
:=
rawdb
.
ReadCanonicalHash
(
server
.
db
,
i
)
b1
:=
fn
(
light
.
NoOdr
,
db
,
pm
.
chainConfig
,
pm
.
blockchain
.
(
*
core
.
BlockChain
),
nil
,
bhash
)
b1
:=
fn
(
light
.
NoOdr
,
server
.
db
,
server
.
pm
.
chainConfig
,
server
.
pm
.
blockchain
.
(
*
core
.
BlockChain
),
nil
,
bhash
)
ctx
,
cancel
:=
context
.
WithTimeout
(
context
.
Background
(),
200
*
time
.
Millisecond
)
ctx
,
cancel
:=
context
.
WithTimeout
(
context
.
Background
(),
200
*
time
.
Millisecond
)
defer
cancel
()
defer
cancel
()
b2
:=
fn
(
ctx
,
ldb
,
lpm
.
chainConfig
,
nil
,
l
pm
.
blockchain
.
(
*
light
.
LightChain
),
bhash
)
b2
:=
fn
(
ctx
,
client
.
db
,
client
.
pm
.
chainConfig
,
nil
,
client
.
pm
.
blockchain
.
(
*
light
.
LightChain
),
bhash
)
eq
:=
bytes
.
Equal
(
b1
,
b2
)
eq
:=
bytes
.
Equal
(
b1
,
b2
)
exp
:=
i
<
expFail
exp
:=
i
<
expFail
...
@@ -201,21 +185,20 @@ func testOdr(t *testing.T, protocol int, expFail uint64, fn odrTestFn) {
...
@@ -201,21 +185,20 @@ func testOdr(t *testing.T, protocol int, expFail uint64, fn odrTestFn) {
}
}
}
}
}
}
// temporarily remove peer to test odr fails
// temporarily remove peer to test odr fails
// expect retrievals to fail (except genesis block) without a les peer
// expect retrievals to fail (except genesis block) without a les peer
peers
.
Unregister
(
lp
eer
.
id
)
client
.
peers
.
Unregister
(
client
.
rP
eer
.
id
)
time
.
Sleep
(
time
.
Millisecond
*
10
)
// ensure that all peerSetNotify callbacks are executed
time
.
Sleep
(
time
.
Millisecond
*
10
)
// ensure that all peerSetNotify callbacks are executed
test
(
expFail
)
test
(
expFail
)
// expect all retrievals to pass
// expect all retrievals to pass
peers
.
Register
(
lp
eer
)
client
.
peers
.
Register
(
client
.
rP
eer
)
time
.
Sleep
(
time
.
Millisecond
*
10
)
// ensure that all peerSetNotify callbacks are executed
time
.
Sleep
(
time
.
Millisecond
*
10
)
// ensure that all peerSetNotify callbacks are executed
lpeer
.
lock
.
Lock
()
client
.
peers
.
lock
.
Lock
()
lp
eer
.
hasBlock
=
func
(
common
.
Hash
,
uint64
)
bool
{
return
true
}
client
.
rP
eer
.
hasBlock
=
func
(
common
.
Hash
,
uint64
)
bool
{
return
true
}
lpeer
.
lock
.
Unlock
()
client
.
peers
.
lock
.
Unlock
()
test
(
5
)
test
(
5
)
// still expect all retrievals to pass, now data should be cached locally
// still expect all retrievals to pass, now data should be cached locally
peers
.
Unregister
(
lp
eer
.
id
)
client
.
peers
.
Unregister
(
client
.
rP
eer
.
id
)
time
.
Sleep
(
time
.
Millisecond
*
10
)
// ensure that all peerSetNotify callbacks are executed
time
.
Sleep
(
time
.
Millisecond
*
10
)
// ensure that all peerSetNotify callbacks are executed
test
(
5
)
test
(
5
)
}
}
les/peer.go
View file @
b69476b3
...
@@ -19,7 +19,6 @@ package les
...
@@ -19,7 +19,6 @@ package les
import
(
import
(
"crypto/ecdsa"
"crypto/ecdsa"
"encoding/binary"
"errors"
"errors"
"fmt"
"fmt"
"math/big"
"math/big"
...
@@ -36,9 +35,10 @@ import (
...
@@ -36,9 +35,10 @@ import (
)
)
var
(
var
(
errClosed
=
errors
.
New
(
"peer set is closed"
)
errClosed
=
errors
.
New
(
"peer set is closed"
)
errAlreadyRegistered
=
errors
.
New
(
"peer is already registered"
)
errAlreadyRegistered
=
errors
.
New
(
"peer is already registered"
)
errNotRegistered
=
errors
.
New
(
"peer is not registered"
)
errNotRegistered
=
errors
.
New
(
"peer is not registered"
)
errInvalidHelpTrieReq
=
errors
.
New
(
"invalid help trie request"
)
)
)
const
maxResponseErrors
=
50
// number of invalid responses tolerated (makes the protocol less brittle but still avoids spam)
const
maxResponseErrors
=
50
// number of invalid responses tolerated (makes the protocol less brittle but still avoids spam)
...
@@ -284,21 +284,21 @@ func (p *peer) RequestProofs(reqID, cost uint64, reqs []ProofReq) error {
...
@@ -284,21 +284,21 @@ func (p *peer) RequestProofs(reqID, cost uint64, reqs []ProofReq) error {
}
}
// RequestHelperTrieProofs fetches a batch of HelperTrie merkle proofs from a remote node.
// RequestHelperTrieProofs fetches a batch of HelperTrie merkle proofs from a remote node.
func
(
p
*
peer
)
RequestHelperTrieProofs
(
reqID
,
cost
uint64
,
reqs
[]
HelperTrieReq
)
error
{
func
(
p
*
peer
)
RequestHelperTrieProofs
(
reqID
,
cost
uint64
,
data
interface
{})
error
{
p
.
Log
()
.
Debug
(
"Fetching batch of HelperTrie proofs"
,
"count"
,
len
(
reqs
))
switch
p
.
version
{
switch
p
.
version
{
case
lpv1
:
case
lpv1
:
reqsV1
:=
make
([]
ChtReq
,
len
(
reqs
))
reqs
,
ok
:=
data
.
([]
ChtReq
)
for
i
,
req
:=
range
reqs
{
if
!
ok
{
if
req
.
Type
!=
htCanonical
||
req
.
AuxReq
!=
auxHeader
||
len
(
req
.
Key
)
!=
8
{
return
errInvalidHelpTrieReq
return
fmt
.
Errorf
(
"Request invalid in LES/1 mode"
)
}
blockNum
:=
binary
.
BigEndian
.
Uint64
(
req
.
Key
)
// convert HelperTrie request to old CHT request
reqsV1
[
i
]
=
ChtReq
{
ChtNum
:
(
req
.
TrieIdx
+
1
)
*
(
light
.
CHTFrequencyClient
/
light
.
CHTFrequencyServer
),
BlockNum
:
blockNum
,
FromLevel
:
req
.
FromLevel
}
}
}
return
sendRequest
(
p
.
rw
,
GetHeaderProofsMsg
,
reqID
,
cost
,
reqsV1
)
p
.
Log
()
.
Debug
(
"Fetching batch of header proofs"
,
"count"
,
len
(
reqs
))
return
sendRequest
(
p
.
rw
,
GetHeaderProofsMsg
,
reqID
,
cost
,
reqs
)
case
lpv2
:
case
lpv2
:
reqs
,
ok
:=
data
.
([]
HelperTrieReq
)
if
!
ok
{
return
errInvalidHelpTrieReq
}
p
.
Log
()
.
Debug
(
"Fetching batch of HelperTrie proofs"
,
"count"
,
len
(
reqs
))
return
sendRequest
(
p
.
rw
,
GetHelperTrieProofsMsg
,
reqID
,
cost
,
reqs
)
return
sendRequest
(
p
.
rw
,
GetHelperTrieProofsMsg
,
reqID
,
cost
,
reqs
)
default
:
default
:
panic
(
nil
)
panic
(
nil
)
...
...
les/request_test.go
View file @
b69476b3
...
@@ -24,7 +24,6 @@ import (
...
@@ -24,7 +24,6 @@ import (
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/rawdb"
"github.com/ethereum/go-ethereum/core/rawdb"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/eth"
"github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/light"
"github.com/ethereum/go-ethereum/light"
)
)
...
@@ -84,35 +83,17 @@ func tfCodeAccess(db ethdb.Database, bhash common.Hash, num uint64) light.OdrReq
...
@@ -84,35 +83,17 @@ func tfCodeAccess(db ethdb.Database, bhash common.Hash, num uint64) light.OdrReq
func
testAccess
(
t
*
testing
.
T
,
protocol
int
,
fn
accessTestFn
)
{
func
testAccess
(
t
*
testing
.
T
,
protocol
int
,
fn
accessTestFn
)
{
// Assemble the test environment
// Assemble the test environment
peers
:=
newPeerSet
()
server
,
client
,
tearDown
:=
newClientServerEnv
(
t
,
4
,
protocol
,
nil
,
true
)
dist
:=
newRequestDistributor
(
peers
,
make
(
chan
struct
{}))
defer
tearDown
()
rm
:=
newRetrieveManager
(
peers
,
dist
,
nil
)
client
.
pm
.
synchronise
(
client
.
rPeer
)
db
:=
ethdb
.
NewMemDatabase
()
ldb
:=
ethdb
.
NewMemDatabase
()
odr
:=
NewLesOdr
(
ldb
,
rm
)
odr
.
SetIndexers
(
light
.
NewChtIndexer
(
db
,
true
,
nil
),
light
.
NewBloomTrieIndexer
(
db
,
true
,
nil
),
eth
.
NewBloomIndexer
(
db
,
light
.
BloomTrieFrequency
,
light
.
HelperTrieConfirmations
))
pm
:=
newTestProtocolManagerMust
(
t
,
false
,
4
,
testChainGen
,
nil
,
nil
,
db
)
lpm
:=
newTestProtocolManagerMust
(
t
,
true
,
0
,
nil
,
peers
,
odr
,
ldb
)
_
,
err1
,
lpeer
,
err2
:=
newTestPeerPair
(
"peer"
,
protocol
,
pm
,
lpm
)
select
{
case
<-
time
.
After
(
time
.
Millisecond
*
100
)
:
case
err
:=
<-
err1
:
t
.
Fatalf
(
"peer 1 handshake error: %v"
,
err
)
case
err
:=
<-
err2
:
t
.
Fatalf
(
"peer 1 handshake error: %v"
,
err
)
}
lpm
.
synchronise
(
lpeer
)
test
:=
func
(
expFail
uint64
)
{
test
:=
func
(
expFail
uint64
)
{
for
i
:=
uint64
(
0
);
i
<=
pm
.
blockchain
.
CurrentHeader
()
.
Number
.
Uint64
();
i
++
{
for
i
:=
uint64
(
0
);
i
<=
server
.
pm
.
blockchain
.
CurrentHeader
()
.
Number
.
Uint64
();
i
++
{
bhash
:=
rawdb
.
ReadCanonicalHash
(
db
,
i
)
bhash
:=
rawdb
.
ReadCanonicalHash
(
server
.
db
,
i
)
if
req
:=
fn
(
l
db
,
bhash
,
i
);
req
!=
nil
{
if
req
:=
fn
(
client
.
db
,
bhash
,
i
);
req
!=
nil
{
ctx
,
cancel
:=
context
.
WithTimeout
(
context
.
Background
(),
200
*
time
.
Millisecond
)
ctx
,
cancel
:=
context
.
WithTimeout
(
context
.
Background
(),
200
*
time
.
Millisecond
)
defer
cancel
()
defer
cancel
()
err
:=
client
.
pm
.
odr
.
Retrieve
(
ctx
,
req
)
err
:=
odr
.
Retrieve
(
ctx
,
req
)
got
:=
err
==
nil
got
:=
err
==
nil
exp
:=
i
<
expFail
exp
:=
i
<
expFail
if
exp
&&
!
got
{
if
exp
&&
!
got
{
...
@@ -126,16 +107,16 @@ func testAccess(t *testing.T, protocol int, fn accessTestFn) {
...
@@ -126,16 +107,16 @@ func testAccess(t *testing.T, protocol int, fn accessTestFn) {
}
}
// temporarily remove peer to test odr fails
// temporarily remove peer to test odr fails
peers
.
Unregister
(
lp
eer
.
id
)
client
.
peers
.
Unregister
(
client
.
rP
eer
.
id
)
time
.
Sleep
(
time
.
Millisecond
*
10
)
// ensure that all peerSetNotify callbacks are executed
time
.
Sleep
(
time
.
Millisecond
*
10
)
// ensure that all peerSetNotify callbacks are executed
// expect retrievals to fail (except genesis block) without a les peer
// expect retrievals to fail (except genesis block) without a les peer
test
(
0
)
test
(
0
)
peers
.
Register
(
lp
eer
)
client
.
peers
.
Register
(
client
.
rP
eer
)
time
.
Sleep
(
time
.
Millisecond
*
10
)
// ensure that all peerSetNotify callbacks are executed
time
.
Sleep
(
time
.
Millisecond
*
10
)
// ensure that all peerSetNotify callbacks are executed
lp
eer
.
lock
.
Lock
()
client
.
rP
eer
.
lock
.
Lock
()
lp
eer
.
hasBlock
=
func
(
common
.
Hash
,
uint64
)
bool
{
return
true
}
client
.
rP
eer
.
hasBlock
=
func
(
common
.
Hash
,
uint64
)
bool
{
return
true
}
lp
eer
.
lock
.
Unlock
()
client
.
rP
eer
.
lock
.
Unlock
()
// expect all retrievals to pass
// expect all retrievals to pass
test
(
5
)
test
(
5
)
}
}
les/server.go
View file @
b69476b3
...
@@ -34,6 +34,7 @@ import (
...
@@ -34,6 +34,7 @@ import (
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/p2p"
"github.com/ethereum/go-ethereum/p2p"
"github.com/ethereum/go-ethereum/p2p/discv5"
"github.com/ethereum/go-ethereum/p2p/discv5"
"github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/rlp"
"github.com/ethereum/go-ethereum/rlp"
)
)
...
@@ -50,7 +51,7 @@ type LesServer struct {
...
@@ -50,7 +51,7 @@ type LesServer struct {
func
NewLesServer
(
eth
*
eth
.
Ethereum
,
config
*
eth
.
Config
)
(
*
LesServer
,
error
)
{
func
NewLesServer
(
eth
*
eth
.
Ethereum
,
config
*
eth
.
Config
)
(
*
LesServer
,
error
)
{
quitSync
:=
make
(
chan
struct
{})
quitSync
:=
make
(
chan
struct
{})
pm
,
err
:=
NewProtocolManager
(
eth
.
BlockChain
()
.
Config
(),
false
,
config
.
NetworkId
,
eth
.
EventMux
(),
eth
.
Engine
(),
newPeerSet
(),
eth
.
BlockChain
(),
eth
.
TxPool
(),
eth
.
ChainDb
(),
nil
,
nil
,
nil
,
quitSync
,
new
(
sync
.
WaitGroup
))
pm
,
err
:=
NewProtocolManager
(
eth
.
BlockChain
()
.
Config
(),
light
.
DefaultServerIndexerConfig
,
false
,
config
.
NetworkId
,
eth
.
EventMux
(),
eth
.
Engine
(),
newPeerSet
(),
eth
.
BlockChain
(),
eth
.
TxPool
(),
eth
.
ChainDb
(),
nil
,
nil
,
nil
,
quitSync
,
new
(
sync
.
WaitGroup
))
if
err
!=
nil
{
if
err
!=
nil
{
return
nil
,
err
return
nil
,
err
}
}
...
@@ -64,8 +65,9 @@ func NewLesServer(eth *eth.Ethereum, config *eth.Config) (*LesServer, error) {
...
@@ -64,8 +65,9 @@ func NewLesServer(eth *eth.Ethereum, config *eth.Config) (*LesServer, error) {
lesCommons
:
lesCommons
{
lesCommons
:
lesCommons
{
config
:
config
,
config
:
config
,
chainDb
:
eth
.
ChainDb
(),
chainDb
:
eth
.
ChainDb
(),
chtIndexer
:
light
.
NewChtIndexer
(
eth
.
ChainDb
(),
false
,
nil
),
iConfig
:
light
.
DefaultServerIndexerConfig
,
bloomTrieIndexer
:
light
.
NewBloomTrieIndexer
(
eth
.
ChainDb
(),
false
,
nil
),
chtIndexer
:
light
.
NewChtIndexer
(
eth
.
ChainDb
(),
nil
,
params
.
CHTFrequencyServer
,
params
.
HelperTrieProcessConfirmations
),
bloomTrieIndexer
:
light
.
NewBloomTrieIndexer
(
eth
.
ChainDb
(),
nil
,
params
.
BloomBitsBlocks
,
params
.
BloomTrieFrequency
),
protocolManager
:
pm
,
protocolManager
:
pm
,
},
},
quitSync
:
quitSync
,
quitSync
:
quitSync
,
...
@@ -75,14 +77,14 @@ func NewLesServer(eth *eth.Ethereum, config *eth.Config) (*LesServer, error) {
...
@@ -75,14 +77,14 @@ func NewLesServer(eth *eth.Ethereum, config *eth.Config) (*LesServer, error) {
logger
:=
log
.
New
()
logger
:=
log
.
New
()
chtV1SectionCount
,
_
,
_
:=
srv
.
chtIndexer
.
Sections
()
// indexer still uses LES/1 4k section size for backwards server compatibility
chtV1SectionCount
,
_
,
_
:=
srv
.
chtIndexer
.
Sections
()
// indexer still uses LES/1 4k section size for backwards server compatibility
chtV2SectionCount
:=
chtV1SectionCount
/
(
light
.
CHTFrequencyClient
/
light
.
CHTFrequencyServer
)
chtV2SectionCount
:=
chtV1SectionCount
/
(
params
.
CHTFrequencyClient
/
params
.
CHTFrequencyServer
)
if
chtV2SectionCount
!=
0
{
if
chtV2SectionCount
!=
0
{
// convert to LES/2 section
// convert to LES/2 section
chtLastSection
:=
chtV2SectionCount
-
1
chtLastSection
:=
chtV2SectionCount
-
1
// convert last LES/2 section index back to LES/1 index for chtIndexer.SectionHead
// convert last LES/2 section index back to LES/1 index for chtIndexer.SectionHead
chtLastSectionV1
:=
(
chtLastSection
+
1
)
*
(
light
.
CHTFrequencyClient
/
light
.
CHTFrequencyServer
)
-
1
chtLastSectionV1
:=
(
chtLastSection
+
1
)
*
(
params
.
CHTFrequencyClient
/
params
.
CHTFrequencyServer
)
-
1
chtSectionHead
:=
srv
.
chtIndexer
.
SectionHead
(
chtLastSectionV1
)
chtSectionHead
:=
srv
.
chtIndexer
.
SectionHead
(
chtLastSectionV1
)
chtRoot
:=
light
.
GetCht
V2Root
(
pm
.
chainDb
,
chtLastSection
,
chtSectionHead
)
chtRoot
:=
light
.
GetCht
Root
(
pm
.
chainDb
,
chtLastSectionV1
,
chtSectionHead
)
logger
.
Info
(
"Loaded CHT"
,
"section"
,
chtLastSection
,
"head"
,
chtSectionHead
,
"root"
,
chtRoot
)
logger
.
Info
(
"Loaded CHT"
,
"section"
,
chtLastSection
,
"head"
,
chtSectionHead
,
"root"
,
chtRoot
)
}
}
bloomTrieSectionCount
,
_
,
_
:=
srv
.
bloomTrieIndexer
.
Sections
()
bloomTrieSectionCount
,
_
,
_
:=
srv
.
bloomTrieIndexer
.
Sections
()
...
...
light/lightchain.go
View file @
b69476b3
...
@@ -48,6 +48,7 @@ var (
...
@@ -48,6 +48,7 @@ var (
// interface. It only does header validation during chain insertion.
// interface. It only does header validation during chain insertion.
type
LightChain
struct
{
type
LightChain
struct
{
hc
*
core
.
HeaderChain
hc
*
core
.
HeaderChain
indexerConfig
*
IndexerConfig
chainDb
ethdb
.
Database
chainDb
ethdb
.
Database
odr
OdrBackend
odr
OdrBackend
chainFeed
event
.
Feed
chainFeed
event
.
Feed
...
@@ -81,13 +82,14 @@ func NewLightChain(odr OdrBackend, config *params.ChainConfig, engine consensus.
...
@@ -81,13 +82,14 @@ func NewLightChain(odr OdrBackend, config *params.ChainConfig, engine consensus.
blockCache
,
_
:=
lru
.
New
(
blockCacheLimit
)
blockCache
,
_
:=
lru
.
New
(
blockCacheLimit
)
bc
:=
&
LightChain
{
bc
:=
&
LightChain
{
chainDb
:
odr
.
Database
(),
chainDb
:
odr
.
Database
(),
odr
:
odr
,
indexerConfig
:
odr
.
IndexerConfig
(),
quit
:
make
(
chan
struct
{}),
odr
:
odr
,
bodyCache
:
bodyCache
,
quit
:
make
(
chan
struct
{}),
bodyRLPCache
:
bodyRLPCache
,
bodyCache
:
bodyCache
,
blockCache
:
blockCache
,
bodyRLPCache
:
bodyRLPCache
,
engine
:
engine
,
blockCache
:
blockCache
,
engine
:
engine
,
}
}
var
err
error
var
err
error
bc
.
hc
,
err
=
core
.
NewHeaderChain
(
odr
.
Database
(),
config
,
bc
.
engine
,
bc
.
getProcInterrupt
)
bc
.
hc
,
err
=
core
.
NewHeaderChain
(
odr
.
Database
(),
config
,
bc
.
engine
,
bc
.
getProcInterrupt
)
...
@@ -128,7 +130,7 @@ func (self *LightChain) addTrustedCheckpoint(cp TrustedCheckpoint) {
...
@@ -128,7 +130,7 @@ func (self *LightChain) addTrustedCheckpoint(cp TrustedCheckpoint) {
if
self
.
odr
.
BloomIndexer
()
!=
nil
{
if
self
.
odr
.
BloomIndexer
()
!=
nil
{
self
.
odr
.
BloomIndexer
()
.
AddKnownSectionHead
(
cp
.
SectionIdx
,
cp
.
SectionHead
)
self
.
odr
.
BloomIndexer
()
.
AddKnownSectionHead
(
cp
.
SectionIdx
,
cp
.
SectionHead
)
}
}
log
.
Info
(
"Added trusted checkpoint"
,
"chain"
,
cp
.
name
,
"block"
,
(
cp
.
SectionIdx
+
1
)
*
CHTFrequencyClient
-
1
,
"hash"
,
cp
.
SectionHead
)
log
.
Info
(
"Added trusted checkpoint"
,
"chain"
,
cp
.
name
,
"block"
,
(
cp
.
SectionIdx
+
1
)
*
self
.
indexerConfig
.
ChtSize
-
1
,
"hash"
,
cp
.
SectionHead
)
}
}
func
(
self
*
LightChain
)
getProcInterrupt
()
bool
{
func
(
self
*
LightChain
)
getProcInterrupt
()
bool
{
...
@@ -472,7 +474,7 @@ func (self *LightChain) SyncCht(ctx context.Context) bool {
...
@@ -472,7 +474,7 @@ func (self *LightChain) SyncCht(ctx context.Context) bool {
head
:=
self
.
CurrentHeader
()
.
Number
.
Uint64
()
head
:=
self
.
CurrentHeader
()
.
Number
.
Uint64
()
sections
,
_
,
_
:=
self
.
odr
.
ChtIndexer
()
.
Sections
()
sections
,
_
,
_
:=
self
.
odr
.
ChtIndexer
()
.
Sections
()
latest
:=
sections
*
CHTFrequencyClient
-
1
latest
:=
sections
*
self
.
indexerConfig
.
ChtSize
-
1
if
clique
:=
self
.
hc
.
Config
()
.
Clique
;
clique
!=
nil
{
if
clique
:=
self
.
hc
.
Config
()
.
Clique
;
clique
!=
nil
{
latest
-=
latest
%
clique
.
Epoch
// epoch snapshot for clique
latest
-=
latest
%
clique
.
Epoch
// epoch snapshot for clique
}
}
...
...
light/lightchain_test.go
View file @
b69476b3
...
@@ -55,7 +55,7 @@ func newCanonical(n int) (ethdb.Database, *LightChain, error) {
...
@@ -55,7 +55,7 @@ func newCanonical(n int) (ethdb.Database, *LightChain, error) {
db
:=
ethdb
.
NewMemDatabase
()
db
:=
ethdb
.
NewMemDatabase
()
gspec
:=
core
.
Genesis
{
Config
:
params
.
TestChainConfig
}
gspec
:=
core
.
Genesis
{
Config
:
params
.
TestChainConfig
}
genesis
:=
gspec
.
MustCommit
(
db
)
genesis
:=
gspec
.
MustCommit
(
db
)
blockchain
,
_
:=
NewLightChain
(
&
dummyOdr
{
db
:
db
},
gspec
.
Config
,
ethash
.
NewFaker
())
blockchain
,
_
:=
NewLightChain
(
&
dummyOdr
{
db
:
db
,
indexerConfig
:
TestClientIndexerConfig
},
gspec
.
Config
,
ethash
.
NewFaker
())
// Create and inject the requested chain
// Create and inject the requested chain
if
n
==
0
{
if
n
==
0
{
...
@@ -265,7 +265,8 @@ func makeHeaderChainWithDiff(genesis *types.Block, d []int, seed byte) []*types.
...
@@ -265,7 +265,8 @@ func makeHeaderChainWithDiff(genesis *types.Block, d []int, seed byte) []*types.
type
dummyOdr
struct
{
type
dummyOdr
struct
{
OdrBackend
OdrBackend
db
ethdb
.
Database
db
ethdb
.
Database
indexerConfig
*
IndexerConfig
}
}
func
(
odr
*
dummyOdr
)
Database
()
ethdb
.
Database
{
func
(
odr
*
dummyOdr
)
Database
()
ethdb
.
Database
{
...
@@ -276,6 +277,10 @@ func (odr *dummyOdr) Retrieve(ctx context.Context, req OdrRequest) error {
...
@@ -276,6 +277,10 @@ func (odr *dummyOdr) Retrieve(ctx context.Context, req OdrRequest) error {
return
nil
return
nil
}
}
func
(
odr
*
dummyOdr
)
IndexerConfig
()
*
IndexerConfig
{
return
odr
.
indexerConfig
}
// Tests that reorganizing a long difficult chain after a short easy one
// Tests that reorganizing a long difficult chain after a short easy one
// overwrites the canonical numbers and links in the database.
// overwrites the canonical numbers and links in the database.
func
TestReorgLongHeaders
(
t
*
testing
.
T
)
{
func
TestReorgLongHeaders
(
t
*
testing
.
T
)
{
...
...
light/odr.go
View file @
b69476b3
...
@@ -44,6 +44,7 @@ type OdrBackend interface {
...
@@ -44,6 +44,7 @@ type OdrBackend interface {
BloomTrieIndexer
()
*
core
.
ChainIndexer
BloomTrieIndexer
()
*
core
.
ChainIndexer
BloomIndexer
()
*
core
.
ChainIndexer
BloomIndexer
()
*
core
.
ChainIndexer
Retrieve
(
ctx
context
.
Context
,
req
OdrRequest
)
error
Retrieve
(
ctx
context
.
Context
,
req
OdrRequest
)
error
IndexerConfig
()
*
IndexerConfig
}
}
// OdrRequest is an interface for retrieval requests
// OdrRequest is an interface for retrieval requests
...
@@ -136,6 +137,7 @@ func (req *ReceiptsRequest) StoreResult(db ethdb.Database) {
...
@@ -136,6 +137,7 @@ func (req *ReceiptsRequest) StoreResult(db ethdb.Database) {
// ChtRequest is the ODR request type for state/storage trie entries
// ChtRequest is the ODR request type for state/storage trie entries
type
ChtRequest
struct
{
type
ChtRequest
struct
{
OdrRequest
OdrRequest
Config
*
IndexerConfig
ChtNum
,
BlockNum
uint64
ChtNum
,
BlockNum
uint64
ChtRoot
common
.
Hash
ChtRoot
common
.
Hash
Header
*
types
.
Header
Header
*
types
.
Header
...
@@ -155,6 +157,7 @@ func (req *ChtRequest) StoreResult(db ethdb.Database) {
...
@@ -155,6 +157,7 @@ func (req *ChtRequest) StoreResult(db ethdb.Database) {
// BloomRequest is the ODR request type for retrieving bloom filters from a CHT structure
// BloomRequest is the ODR request type for retrieving bloom filters from a CHT structure
type
BloomRequest
struct
{
type
BloomRequest
struct
{
OdrRequest
OdrRequest
Config
*
IndexerConfig
BloomTrieNum
uint64
BloomTrieNum
uint64
BitIdx
uint
BitIdx
uint
SectionIdxList
[]
uint64
SectionIdxList
[]
uint64
...
@@ -166,7 +169,7 @@ type BloomRequest struct {
...
@@ -166,7 +169,7 @@ type BloomRequest struct {
// StoreResult stores the retrieved data in local database
// StoreResult stores the retrieved data in local database
func
(
req
*
BloomRequest
)
StoreResult
(
db
ethdb
.
Database
)
{
func
(
req
*
BloomRequest
)
StoreResult
(
db
ethdb
.
Database
)
{
for
i
,
sectionIdx
:=
range
req
.
SectionIdxList
{
for
i
,
sectionIdx
:=
range
req
.
SectionIdxList
{
sectionHead
:=
rawdb
.
ReadCanonicalHash
(
db
,
(
sectionIdx
+
1
)
*
BloomTrieFrequency
-
1
)
sectionHead
:=
rawdb
.
ReadCanonicalHash
(
db
,
(
sectionIdx
+
1
)
*
req
.
Config
.
BloomTrieSize
-
1
)
// if we don't have the canonical hash stored for this section head number, we'll still store it under
// if we don't have the canonical hash stored for this section head number, we'll still store it under
// a key with a zero sectionHead. GetBloomBits will look there too if we still don't have the canonical
// a key with a zero sectionHead. GetBloomBits will look there too if we still don't have the canonical
// hash. In the unlikely case we've retrieved the section head hash since then, we'll just retrieve the
// hash. In the unlikely case we've retrieved the section head hash since then, we'll just retrieve the
...
...
light/odr_test.go
View file @
b69476b3
...
@@ -55,8 +55,9 @@ var (
...
@@ -55,8 +55,9 @@ var (
type
testOdr
struct
{
type
testOdr
struct
{
OdrBackend
OdrBackend
sdb
,
ldb
ethdb
.
Database
indexerConfig
*
IndexerConfig
disable
bool
sdb
,
ldb
ethdb
.
Database
disable
bool
}
}
func
(
odr
*
testOdr
)
Database
()
ethdb
.
Database
{
func
(
odr
*
testOdr
)
Database
()
ethdb
.
Database
{
...
@@ -92,6 +93,10 @@ func (odr *testOdr) Retrieve(ctx context.Context, req OdrRequest) error {
...
@@ -92,6 +93,10 @@ func (odr *testOdr) Retrieve(ctx context.Context, req OdrRequest) error {
return
nil
return
nil
}
}
func
(
odr
*
testOdr
)
IndexerConfig
()
*
IndexerConfig
{
return
odr
.
indexerConfig
}
type
odrTestFn
func
(
ctx
context
.
Context
,
db
ethdb
.
Database
,
bc
*
core
.
BlockChain
,
lc
*
LightChain
,
bhash
common
.
Hash
)
([]
byte
,
error
)
type
odrTestFn
func
(
ctx
context
.
Context
,
db
ethdb
.
Database
,
bc
*
core
.
BlockChain
,
lc
*
LightChain
,
bhash
common
.
Hash
)
([]
byte
,
error
)
func
TestOdrGetBlockLes1
(
t
*
testing
.
T
)
{
testChainOdr
(
t
,
1
,
odrGetBlock
)
}
func
TestOdrGetBlockLes1
(
t
*
testing
.
T
)
{
testChainOdr
(
t
,
1
,
odrGetBlock
)
}
...
@@ -258,7 +263,7 @@ func testChainOdr(t *testing.T, protocol int, fn odrTestFn) {
...
@@ -258,7 +263,7 @@ func testChainOdr(t *testing.T, protocol int, fn odrTestFn) {
t
.
Fatal
(
err
)
t
.
Fatal
(
err
)
}
}
odr
:=
&
testOdr
{
sdb
:
sdb
,
ldb
:
ldb
}
odr
:=
&
testOdr
{
sdb
:
sdb
,
ldb
:
ldb
,
indexerConfig
:
TestClientIndexerConfig
}
lightchain
,
err
:=
NewLightChain
(
odr
,
params
.
TestChainConfig
,
ethash
.
NewFullFaker
())
lightchain
,
err
:=
NewLightChain
(
odr
,
params
.
TestChainConfig
,
ethash
.
NewFullFaker
())
if
err
!=
nil
{
if
err
!=
nil
{
t
.
Fatal
(
err
)
t
.
Fatal
(
err
)
...
...
light/odr_util.go
View file @
b69476b3
...
@@ -53,16 +53,16 @@ func GetHeaderByNumber(ctx context.Context, odr OdrBackend, number uint64) (*typ
...
@@ -53,16 +53,16 @@ func GetHeaderByNumber(ctx context.Context, odr OdrBackend, number uint64) (*typ
for
chtCount
>
0
&&
canonicalHash
!=
sectionHead
&&
canonicalHash
!=
(
common
.
Hash
{})
{
for
chtCount
>
0
&&
canonicalHash
!=
sectionHead
&&
canonicalHash
!=
(
common
.
Hash
{})
{
chtCount
--
chtCount
--
if
chtCount
>
0
{
if
chtCount
>
0
{
sectionHeadNum
=
chtCount
*
CHTFrequencyClient
-
1
sectionHeadNum
=
chtCount
*
odr
.
IndexerConfig
()
.
ChtSize
-
1
sectionHead
=
odr
.
ChtIndexer
()
.
SectionHead
(
chtCount
-
1
)
sectionHead
=
odr
.
ChtIndexer
()
.
SectionHead
(
chtCount
-
1
)
canonicalHash
=
rawdb
.
ReadCanonicalHash
(
db
,
sectionHeadNum
)
canonicalHash
=
rawdb
.
ReadCanonicalHash
(
db
,
sectionHeadNum
)
}
}
}
}
}
}
if
number
>=
chtCount
*
CHTFrequencyClient
{
if
number
>=
chtCount
*
odr
.
IndexerConfig
()
.
ChtSize
{
return
nil
,
ErrNoTrustedCht
return
nil
,
ErrNoTrustedCht
}
}
r
:=
&
ChtRequest
{
ChtRoot
:
GetChtRoot
(
db
,
chtCount
-
1
,
sectionHead
),
ChtNum
:
chtCount
-
1
,
BlockNum
:
number
}
r
:=
&
ChtRequest
{
ChtRoot
:
GetChtRoot
(
db
,
chtCount
-
1
,
sectionHead
),
ChtNum
:
chtCount
-
1
,
BlockNum
:
number
,
Config
:
odr
.
IndexerConfig
()
}
if
err
:=
odr
.
Retrieve
(
ctx
,
r
);
err
!=
nil
{
if
err
:=
odr
.
Retrieve
(
ctx
,
r
);
err
!=
nil
{
return
nil
,
err
return
nil
,
err
}
}
...
@@ -175,9 +175,9 @@ func GetBlockLogs(ctx context.Context, odr OdrBackend, hash common.Hash, number
...
@@ -175,9 +175,9 @@ func GetBlockLogs(ctx context.Context, odr OdrBackend, hash common.Hash, number
// GetBloomBits retrieves a batch of compressed bloomBits vectors belonging to the given bit index and section indexes
// GetBloomBits retrieves a batch of compressed bloomBits vectors belonging to the given bit index and section indexes
func
GetBloomBits
(
ctx
context
.
Context
,
odr
OdrBackend
,
bitIdx
uint
,
sectionIdxList
[]
uint64
)
([][]
byte
,
error
)
{
func
GetBloomBits
(
ctx
context
.
Context
,
odr
OdrBackend
,
bitIdx
uint
,
sectionIdxList
[]
uint64
)
([][]
byte
,
error
)
{
db
:=
odr
.
Database
()
result
:=
make
([][]
byte
,
len
(
sectionIdxList
))
var
(
var
(
db
=
odr
.
Database
()
result
=
make
([][]
byte
,
len
(
sectionIdxList
))
reqList
[]
uint64
reqList
[]
uint64
reqIdx
[]
int
reqIdx
[]
int
)
)
...
@@ -193,7 +193,7 @@ func GetBloomBits(ctx context.Context, odr OdrBackend, bitIdx uint, sectionIdxLi
...
@@ -193,7 +193,7 @@ func GetBloomBits(ctx context.Context, odr OdrBackend, bitIdx uint, sectionIdxLi
for
bloomTrieCount
>
0
&&
canonicalHash
!=
sectionHead
&&
canonicalHash
!=
(
common
.
Hash
{})
{
for
bloomTrieCount
>
0
&&
canonicalHash
!=
sectionHead
&&
canonicalHash
!=
(
common
.
Hash
{})
{
bloomTrieCount
--
bloomTrieCount
--
if
bloomTrieCount
>
0
{
if
bloomTrieCount
>
0
{
sectionHeadNum
=
bloomTrieCount
*
BloomTrieFrequency
-
1
sectionHeadNum
=
bloomTrieCount
*
odr
.
IndexerConfig
()
.
BloomTrieSize
-
1
sectionHead
=
odr
.
BloomTrieIndexer
()
.
SectionHead
(
bloomTrieCount
-
1
)
sectionHead
=
odr
.
BloomTrieIndexer
()
.
SectionHead
(
bloomTrieCount
-
1
)
canonicalHash
=
rawdb
.
ReadCanonicalHash
(
db
,
sectionHeadNum
)
canonicalHash
=
rawdb
.
ReadCanonicalHash
(
db
,
sectionHeadNum
)
}
}
...
@@ -201,7 +201,7 @@ func GetBloomBits(ctx context.Context, odr OdrBackend, bitIdx uint, sectionIdxLi
...
@@ -201,7 +201,7 @@ func GetBloomBits(ctx context.Context, odr OdrBackend, bitIdx uint, sectionIdxLi
}
}
for
i
,
sectionIdx
:=
range
sectionIdxList
{
for
i
,
sectionIdx
:=
range
sectionIdxList
{
sectionHead
:=
rawdb
.
ReadCanonicalHash
(
db
,
(
sectionIdx
+
1
)
*
BloomTrieFrequency
-
1
)
sectionHead
:=
rawdb
.
ReadCanonicalHash
(
db
,
(
sectionIdx
+
1
)
*
odr
.
IndexerConfig
()
.
BloomSize
-
1
)
// if we don't have the canonical hash stored for this section head number, we'll still look for
// if we don't have the canonical hash stored for this section head number, we'll still look for
// an entry with a zero sectionHead (we store it with zero section head too if we don't know it
// an entry with a zero sectionHead (we store it with zero section head too if we don't know it
// at the time of the retrieval)
// at the time of the retrieval)
...
@@ -209,6 +209,7 @@ func GetBloomBits(ctx context.Context, odr OdrBackend, bitIdx uint, sectionIdxLi
...
@@ -209,6 +209,7 @@ func GetBloomBits(ctx context.Context, odr OdrBackend, bitIdx uint, sectionIdxLi
if
err
==
nil
{
if
err
==
nil
{
result
[
i
]
=
bloomBits
result
[
i
]
=
bloomBits
}
else
{
}
else
{
// TODO(rjl493456442) Convert sectionIndex to BloomTrie relative index
if
sectionIdx
>=
bloomTrieCount
{
if
sectionIdx
>=
bloomTrieCount
{
return
nil
,
ErrNoTrustedBloomTrie
return
nil
,
ErrNoTrustedBloomTrie
}
}
...
@@ -220,7 +221,8 @@ func GetBloomBits(ctx context.Context, odr OdrBackend, bitIdx uint, sectionIdxLi
...
@@ -220,7 +221,8 @@ func GetBloomBits(ctx context.Context, odr OdrBackend, bitIdx uint, sectionIdxLi
return
result
,
nil
return
result
,
nil
}
}
r
:=
&
BloomRequest
{
BloomTrieRoot
:
GetBloomTrieRoot
(
db
,
bloomTrieCount
-
1
,
sectionHead
),
BloomTrieNum
:
bloomTrieCount
-
1
,
BitIdx
:
bitIdx
,
SectionIdxList
:
reqList
}
r
:=
&
BloomRequest
{
BloomTrieRoot
:
GetBloomTrieRoot
(
db
,
bloomTrieCount
-
1
,
sectionHead
),
BloomTrieNum
:
bloomTrieCount
-
1
,
BitIdx
:
bitIdx
,
SectionIdxList
:
reqList
,
Config
:
odr
.
IndexerConfig
()}
if
err
:=
odr
.
Retrieve
(
ctx
,
r
);
err
!=
nil
{
if
err
:=
odr
.
Retrieve
(
ctx
,
r
);
err
!=
nil
{
return
nil
,
err
return
nil
,
err
}
else
{
}
else
{
...
...
light/postprocess.go
View file @
b69476b3
This diff is collapsed.
Click to expand it.
light/trie_test.go
View file @
b69476b3
...
@@ -47,7 +47,7 @@ func TestNodeIterator(t *testing.T) {
...
@@ -47,7 +47,7 @@ func TestNodeIterator(t *testing.T) {
}
}
ctx
:=
context
.
Background
()
ctx
:=
context
.
Background
()
odr
:=
&
testOdr
{
sdb
:
fulldb
,
ldb
:
lightdb
}
odr
:=
&
testOdr
{
sdb
:
fulldb
,
ldb
:
lightdb
,
indexerConfig
:
TestClientIndexerConfig
}
head
:=
blockchain
.
CurrentHeader
()
head
:=
blockchain
.
CurrentHeader
()
lightTrie
,
_
:=
NewStateDatabase
(
ctx
,
head
,
odr
)
.
OpenTrie
(
head
.
Root
)
lightTrie
,
_
:=
NewStateDatabase
(
ctx
,
head
,
odr
)
.
OpenTrie
(
head
.
Root
)
fullTrie
,
_
:=
state
.
NewDatabase
(
fulldb
)
.
OpenTrie
(
head
.
Root
)
fullTrie
,
_
:=
state
.
NewDatabase
(
fulldb
)
.
OpenTrie
(
head
.
Root
)
...
...
light/txpool_test.go
View file @
b69476b3
...
@@ -94,7 +94,7 @@ func TestTxPool(t *testing.T) {
...
@@ -94,7 +94,7 @@ func TestTxPool(t *testing.T) {
panic
(
err
)
panic
(
err
)
}
}
odr
:=
&
testOdr
{
sdb
:
sdb
,
ldb
:
ldb
}
odr
:=
&
testOdr
{
sdb
:
sdb
,
ldb
:
ldb
,
indexerConfig
:
TestClientIndexerConfig
}
relay
:=
&
testTxRelay
{
relay
:=
&
testTxRelay
{
send
:
make
(
chan
int
,
1
),
send
:
make
(
chan
int
,
1
),
discard
:
make
(
chan
int
,
1
),
discard
:
make
(
chan
int
,
1
),
...
...
params/network_params.go
View file @
b69476b3
...
@@ -17,10 +17,38 @@
...
@@ -17,10 +17,38 @@
package
params
package
params
// These are network parameters that need to be constant between clients, but
// These are network parameters that need to be constant between clients, but
// aren't neces
aril
ly consensus related.
// aren't neces
sari
ly consensus related.
const
(
const
(
// BloomBitsBlocks is the number of blocks a single bloom bit section vector
// BloomBitsBlocks is the number of blocks a single bloom bit section vector
// contains.
// contains
on the server side
.
BloomBitsBlocks
uint64
=
4096
BloomBitsBlocks
uint64
=
4096
// BloomBitsBlocksClient is the number of blocks a single bloom bit section vector
// contains on the light client side
BloomBitsBlocksClient
uint64
=
32768
// BloomConfirms is the number of confirmation blocks before a bloom section is
// considered probably final and its rotated bits are calculated.
BloomConfirms
=
256
// CHTFrequencyClient is the block frequency for creating CHTs on the client side.
CHTFrequencyClient
=
32768
// CHTFrequencyServer is the block frequency for creating CHTs on the server side.
// Eventually this can be merged back with the client version, but that requires a
// full database upgrade, so that should be left for a suitable moment.
CHTFrequencyServer
=
4096
// BloomTrieFrequency is the block frequency for creating BloomTrie on both
// server/client sides.
BloomTrieFrequency
=
32768
// HelperTrieConfirmations is the number of confirmations before a client is expected
// to have the given HelperTrie available.
HelperTrieConfirmations
=
2048
// HelperTrieProcessConfirmations is the number of confirmations before a HelperTrie
// is generated
HelperTrieProcessConfirmations
=
256
)
)
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