forked from cerc-io/plugeth
les, light: fix CHT trie retrievals (#16039)
* les, light: fix CHT trie retrievals * les, light: minor polishes, test remote CHT retrievals * les, light: deterministic nodeset rlp, bloombits test skeleton * les: add an event emission to the les bloombits test * les: drop dead tester code
This commit is contained in:
parent
5cf75a30c1
commit
7a0019c63b
@ -790,10 +790,9 @@ func (pm *ProtocolManager) handleMsg(p *peer) error {
|
|||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
proofs := nodes.NodeList()
|
|
||||||
bv, rcost := p.fcClient.RequestProcessed(costs.baseCost + uint64(reqCnt)*costs.reqCost)
|
bv, rcost := p.fcClient.RequestProcessed(costs.baseCost + uint64(reqCnt)*costs.reqCost)
|
||||||
pm.server.fcCostStats.update(msg.Code, uint64(reqCnt), rcost)
|
pm.server.fcCostStats.update(msg.Code, uint64(reqCnt), rcost)
|
||||||
return p.SendProofsV2(req.ReqID, bv, proofs)
|
return p.SendProofsV2(req.ReqID, bv, nodes.NodeList())
|
||||||
|
|
||||||
case ProofsV1Msg:
|
case ProofsV1Msg:
|
||||||
if pm.odr == nil {
|
if pm.odr == nil {
|
||||||
@ -856,15 +855,12 @@ func (pm *ProtocolManager) handleMsg(p *peer) error {
|
|||||||
if reject(uint64(reqCnt), MaxHelperTrieProofsFetch) {
|
if reject(uint64(reqCnt), MaxHelperTrieProofsFetch) {
|
||||||
return errResp(ErrRequestRejected, "")
|
return errResp(ErrRequestRejected, "")
|
||||||
}
|
}
|
||||||
|
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 := core.GetCanonicalHash(pm.chainDb, req.ChtNum*light.ChtV1Frequency-1)
|
sectionHead := core.GetCanonicalHash(pm.chainDb, req.ChtNum*light.CHTFrequencyServer-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{}) {
|
||||||
statedb, err := pm.blockchain.State()
|
trie, err := trie.New(root, trieDb)
|
||||||
if err != nil {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
trie, err := statedb.Database().OpenTrie(root)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
@ -878,7 +874,6 @@ func (pm *ProtocolManager) handleMsg(p *peer) error {
|
|||||||
if bytes += proof.DataSize() + estHeaderRlpSize; bytes >= softResponseLimit {
|
if bytes += proof.DataSize() + estHeaderRlpSize; bytes >= softResponseLimit {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -910,20 +905,16 @@ func (pm *ProtocolManager) handleMsg(p *peer) error {
|
|||||||
lastIdx uint64
|
lastIdx uint64
|
||||||
lastType uint
|
lastType uint
|
||||||
root common.Hash
|
root common.Hash
|
||||||
statedb *state.StateDB
|
auxTrie *trie.Trie
|
||||||
trie state.Trie
|
|
||||||
)
|
)
|
||||||
|
|
||||||
nodes := light.NewNodeSet()
|
nodes := light.NewNodeSet()
|
||||||
|
|
||||||
for _, req := range req.Reqs {
|
for _, req := range req.Reqs {
|
||||||
if trie == nil || req.HelperTrieType != lastType || req.TrieIdx != lastIdx {
|
if auxTrie == nil || req.Type != lastType || req.TrieIdx != lastIdx {
|
||||||
statedb, trie, lastType, lastIdx = nil, nil, req.HelperTrieType, req.TrieIdx
|
auxTrie, lastType, lastIdx = nil, req.Type, req.TrieIdx
|
||||||
|
|
||||||
if root, _ = pm.getHelperTrie(req.HelperTrieType, req.TrieIdx); root != (common.Hash{}) {
|
var prefix string
|
||||||
if statedb, _ = pm.blockchain.State(); statedb != nil {
|
if root, prefix = pm.getHelperTrie(req.Type, req.TrieIdx); root != (common.Hash{}) {
|
||||||
trie, _ = statedb.Database().OpenTrie(root)
|
auxTrie, _ = trie.New(root, trie.NewDatabase(ethdb.NewTable(pm.chainDb, prefix)))
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if req.AuxReq == auxRoot {
|
if req.AuxReq == auxRoot {
|
||||||
@ -934,8 +925,8 @@ func (pm *ProtocolManager) handleMsg(p *peer) error {
|
|||||||
auxData = append(auxData, data)
|
auxData = append(auxData, data)
|
||||||
auxBytes += len(data)
|
auxBytes += len(data)
|
||||||
} else {
|
} else {
|
||||||
if trie != nil {
|
if auxTrie != nil {
|
||||||
trie.Prove(req.Key, req.FromLevel, nodes)
|
auxTrie.Prove(req.Key, req.FromLevel, nodes)
|
||||||
}
|
}
|
||||||
if req.AuxReq != 0 {
|
if req.AuxReq != 0 {
|
||||||
data := pm.getHelperTrieAuxData(req)
|
data := pm.getHelperTrieAuxData(req)
|
||||||
@ -947,10 +938,9 @@ func (pm *ProtocolManager) handleMsg(p *peer) error {
|
|||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
proofs := nodes.NodeList()
|
|
||||||
bv, rcost := p.fcClient.RequestProcessed(costs.baseCost + uint64(reqCnt)*costs.reqCost)
|
bv, rcost := p.fcClient.RequestProcessed(costs.baseCost + uint64(reqCnt)*costs.reqCost)
|
||||||
pm.server.fcCostStats.update(msg.Code, uint64(reqCnt), rcost)
|
pm.server.fcCostStats.update(msg.Code, uint64(reqCnt), rcost)
|
||||||
return p.SendHelperTrieProofs(req.ReqID, bv, HelperTrieResps{Proofs: proofs, AuxData: auxData})
|
return p.SendHelperTrieProofs(req.ReqID, bv, HelperTrieResps{Proofs: nodes.NodeList(), AuxData: auxData})
|
||||||
|
|
||||||
case HeaderProofsMsg:
|
case HeaderProofsMsg:
|
||||||
if pm.odr == nil {
|
if pm.odr == nil {
|
||||||
@ -1123,7 +1113,7 @@ 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 := core.GetCanonicalHash(pm.chainDb, (idx+1)*light.ChtFrequency-1)
|
sectionHead := core.GetCanonicalHash(pm.chainDb, (idx+1)*light.CHTFrequencyClient-1)
|
||||||
return light.GetChtV2Root(pm.chainDb, idx, sectionHead), light.ChtTablePrefix
|
return light.GetChtV2Root(pm.chainDb, idx, sectionHead), light.ChtTablePrefix
|
||||||
case htBloomBits:
|
case htBloomBits:
|
||||||
sectionHead := core.GetCanonicalHash(pm.chainDb, (idx+1)*light.BloomTrieFrequency-1)
|
sectionHead := core.GetCanonicalHash(pm.chainDb, (idx+1)*light.BloomTrieFrequency-1)
|
||||||
@ -1134,10 +1124,8 @@ func (pm *ProtocolManager) getHelperTrie(id uint, idx uint64) (common.Hash, stri
|
|||||||
|
|
||||||
// getHelperTrieAuxData returns requested auxiliary data for the given HelperTrie request
|
// getHelperTrieAuxData returns requested auxiliary data for the given HelperTrie request
|
||||||
func (pm *ProtocolManager) getHelperTrieAuxData(req HelperTrieReq) []byte {
|
func (pm *ProtocolManager) getHelperTrieAuxData(req HelperTrieReq) []byte {
|
||||||
if req.HelperTrieType == htCanonical && req.AuxReq == auxHeader {
|
switch {
|
||||||
if len(req.Key) != 8 {
|
case req.Type == htCanonical && req.AuxReq == auxHeader && len(req.Key) == 8:
|
||||||
return nil
|
|
||||||
}
|
|
||||||
blockNum := binary.BigEndian.Uint64(req.Key)
|
blockNum := binary.BigEndian.Uint64(req.Key)
|
||||||
hash := core.GetCanonicalHash(pm.chainDb, blockNum)
|
hash := core.GetCanonicalHash(pm.chainDb, blockNum)
|
||||||
return core.GetHeaderRLP(pm.chainDb, hash, blockNum)
|
return core.GetHeaderRLP(pm.chainDb, hash, blockNum)
|
||||||
|
@ -17,7 +17,7 @@
|
|||||||
package les
|
package les
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"encoding/binary"
|
||||||
"math/big"
|
"math/big"
|
||||||
"math/rand"
|
"math/rand"
|
||||||
"testing"
|
"testing"
|
||||||
@ -45,27 +45,8 @@ func expectResponse(r p2p.MsgReader, msgcode, reqID, bv uint64, data interface{}
|
|||||||
return p2p.ExpectMsg(r, msgcode, resp{reqID, bv, data})
|
return p2p.ExpectMsg(r, msgcode, resp{reqID, bv, data})
|
||||||
}
|
}
|
||||||
|
|
||||||
func testCheckProof(t *testing.T, exp *light.NodeSet, got light.NodeList) {
|
|
||||||
if exp.KeyCount() > len(got) {
|
|
||||||
t.Errorf("proof has fewer nodes than expected")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if exp.KeyCount() < len(got) {
|
|
||||||
t.Errorf("proof has more nodes than expected")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
for _, node := range got {
|
|
||||||
n, _ := exp.Get(crypto.Keccak256(node))
|
|
||||||
if !bytes.Equal(n, node) {
|
|
||||||
t.Errorf("proof contents mismatch")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Tests that block headers can be retrieved from a remote chain based on user queries.
|
// Tests that block headers can be retrieved from a remote chain based on user queries.
|
||||||
func TestGetBlockHeadersLes1(t *testing.T) { testGetBlockHeaders(t, 1) }
|
func TestGetBlockHeadersLes1(t *testing.T) { testGetBlockHeaders(t, 1) }
|
||||||
|
|
||||||
func TestGetBlockHeadersLes2(t *testing.T) { testGetBlockHeaders(t, 2) }
|
func TestGetBlockHeadersLes2(t *testing.T) { testGetBlockHeaders(t, 2) }
|
||||||
|
|
||||||
func testGetBlockHeaders(t *testing.T, protocol int) {
|
func testGetBlockHeaders(t *testing.T, protocol int) {
|
||||||
@ -196,7 +177,6 @@ func testGetBlockHeaders(t *testing.T, protocol int) {
|
|||||||
|
|
||||||
// Tests that block contents can be retrieved from a remote chain based on their hashes.
|
// Tests that block contents can be retrieved from a remote chain based on their hashes.
|
||||||
func TestGetBlockBodiesLes1(t *testing.T) { testGetBlockBodies(t, 1) }
|
func TestGetBlockBodiesLes1(t *testing.T) { testGetBlockBodies(t, 1) }
|
||||||
|
|
||||||
func TestGetBlockBodiesLes2(t *testing.T) { testGetBlockBodies(t, 2) }
|
func TestGetBlockBodiesLes2(t *testing.T) { testGetBlockBodies(t, 2) }
|
||||||
|
|
||||||
func testGetBlockBodies(t *testing.T, protocol int) {
|
func testGetBlockBodies(t *testing.T, protocol int) {
|
||||||
@ -274,7 +254,6 @@ func testGetBlockBodies(t *testing.T, protocol int) {
|
|||||||
|
|
||||||
// Tests that the contract codes can be retrieved based on account addresses.
|
// Tests that the contract codes can be retrieved based on account addresses.
|
||||||
func TestGetCodeLes1(t *testing.T) { testGetCode(t, 1) }
|
func TestGetCodeLes1(t *testing.T) { testGetCode(t, 1) }
|
||||||
|
|
||||||
func TestGetCodeLes2(t *testing.T) { testGetCode(t, 2) }
|
func TestGetCodeLes2(t *testing.T) { testGetCode(t, 2) }
|
||||||
|
|
||||||
func testGetCode(t *testing.T, protocol int) {
|
func testGetCode(t *testing.T, protocol int) {
|
||||||
@ -309,7 +288,6 @@ func testGetCode(t *testing.T, protocol int) {
|
|||||||
|
|
||||||
// Tests that the transaction receipts can be retrieved based on hashes.
|
// Tests that the transaction receipts can be retrieved based on hashes.
|
||||||
func TestGetReceiptLes1(t *testing.T) { testGetReceipt(t, 1) }
|
func TestGetReceiptLes1(t *testing.T) { testGetReceipt(t, 1) }
|
||||||
|
|
||||||
func TestGetReceiptLes2(t *testing.T) { testGetReceipt(t, 2) }
|
func TestGetReceiptLes2(t *testing.T) { testGetReceipt(t, 2) }
|
||||||
|
|
||||||
func testGetReceipt(t *testing.T, protocol int) {
|
func testGetReceipt(t *testing.T, protocol int) {
|
||||||
@ -338,7 +316,6 @@ func testGetReceipt(t *testing.T, protocol int) {
|
|||||||
|
|
||||||
// Tests that trie merkle proofs can be retrieved
|
// Tests that trie merkle proofs can be retrieved
|
||||||
func TestGetProofsLes1(t *testing.T) { testGetProofs(t, 1) }
|
func TestGetProofsLes1(t *testing.T) { testGetProofs(t, 1) }
|
||||||
|
|
||||||
func TestGetProofsLes2(t *testing.T) { testGetProofs(t, 2) }
|
func TestGetProofsLes2(t *testing.T) { testGetProofs(t, 2) }
|
||||||
|
|
||||||
func testGetProofs(t *testing.T, protocol int) {
|
func testGetProofs(t *testing.T, protocol int) {
|
||||||
@ -389,27 +366,126 @@ func testGetProofs(t *testing.T, protocol int) {
|
|||||||
case 2:
|
case 2:
|
||||||
cost := peer.GetRequestCost(GetProofsV2Msg, len(proofreqs))
|
cost := peer.GetRequestCost(GetProofsV2Msg, len(proofreqs))
|
||||||
sendRequest(peer.app, GetProofsV2Msg, 42, cost, proofreqs)
|
sendRequest(peer.app, GetProofsV2Msg, 42, cost, proofreqs)
|
||||||
msg, err := peer.app.ReadMsg()
|
if err := expectResponse(peer.app, ProofsV2Msg, 42, testBufLimit, proofsV2.NodeList()); err != nil {
|
||||||
if err != nil {
|
t.Errorf("proofs mismatch: %v", err)
|
||||||
t.Errorf("Message read error: %v", err)
|
|
||||||
}
|
}
|
||||||
var resp struct {
|
}
|
||||||
ReqID, BV uint64
|
}
|
||||||
Data light.NodeList
|
|
||||||
|
// Tests that CHT proofs can be correctly retrieved.
|
||||||
|
func TestGetCHTProofsLes1(t *testing.T) { testGetCHTProofs(t, 1) }
|
||||||
|
func TestGetCHTProofsLes2(t *testing.T) { testGetCHTProofs(t, 2) }
|
||||||
|
|
||||||
|
func testGetCHTProofs(t *testing.T, protocol int) {
|
||||||
|
// Figure out the client's CHT frequency
|
||||||
|
frequency := uint64(light.CHTFrequencyClient)
|
||||||
|
if protocol == 1 {
|
||||||
|
frequency = uint64(light.CHTFrequencyServer)
|
||||||
|
}
|
||||||
|
// Assemble the test environment
|
||||||
|
db, _ := ethdb.NewMemDatabase()
|
||||||
|
pm := newTestProtocolManagerMust(t, false, int(frequency)+light.HelperTrieProcessConfirmations, testChainGen, nil, nil, db)
|
||||||
|
bc := pm.blockchain.(*core.BlockChain)
|
||||||
|
peer, _ := newTestPeer(t, "peer", protocol, pm, true)
|
||||||
|
defer peer.close()
|
||||||
|
|
||||||
|
// Wait a while for the CHT indexer to process the new headers
|
||||||
|
time.Sleep(100 * time.Millisecond * time.Duration(frequency/light.CHTFrequencyServer)) // Chain indexer throttling
|
||||||
|
time.Sleep(250 * time.Millisecond) // CI tester slack
|
||||||
|
|
||||||
|
// Assemble the proofs from the different protocols
|
||||||
|
header := bc.GetHeaderByNumber(frequency)
|
||||||
|
rlp, _ := rlp.EncodeToBytes(header)
|
||||||
|
|
||||||
|
key := make([]byte, 8)
|
||||||
|
binary.BigEndian.PutUint64(key, frequency)
|
||||||
|
|
||||||
|
proofsV1 := []ChtResp{{
|
||||||
|
Header: header,
|
||||||
|
}}
|
||||||
|
proofsV2 := HelperTrieResps{
|
||||||
|
AuxData: [][]byte{rlp},
|
||||||
|
}
|
||||||
|
switch protocol {
|
||||||
|
case 1:
|
||||||
|
root := light.GetChtRoot(db, 0, bc.GetHeaderByNumber(frequency-1).Hash())
|
||||||
|
trie, _ := trie.New(root, trie.NewDatabase(ethdb.NewTable(db, light.ChtTablePrefix)))
|
||||||
|
|
||||||
|
var proof light.NodeList
|
||||||
|
trie.Prove(key, 0, &proof)
|
||||||
|
proofsV1[0].Proof = proof
|
||||||
|
|
||||||
|
case 2:
|
||||||
|
root := light.GetChtV2Root(db, 0, bc.GetHeaderByNumber(frequency-1).Hash())
|
||||||
|
trie, _ := trie.New(root, trie.NewDatabase(ethdb.NewTable(db, light.ChtTablePrefix)))
|
||||||
|
trie.Prove(key, 0, &proofsV2.Proofs)
|
||||||
|
}
|
||||||
|
// Assemble the requests for the different protocols
|
||||||
|
requestsV1 := []ChtReq{{
|
||||||
|
ChtNum: 1,
|
||||||
|
BlockNum: frequency,
|
||||||
|
}}
|
||||||
|
requestsV2 := []HelperTrieReq{{
|
||||||
|
Type: htCanonical,
|
||||||
|
TrieIdx: 0,
|
||||||
|
Key: key,
|
||||||
|
AuxReq: auxHeader,
|
||||||
|
}}
|
||||||
|
// Send the proof request and verify the response
|
||||||
|
switch protocol {
|
||||||
|
case 1:
|
||||||
|
cost := peer.GetRequestCost(GetHeaderProofsMsg, len(requestsV1))
|
||||||
|
sendRequest(peer.app, GetHeaderProofsMsg, 42, cost, requestsV1)
|
||||||
|
if err := expectResponse(peer.app, HeaderProofsMsg, 42, testBufLimit, proofsV1); err != nil {
|
||||||
|
t.Errorf("proofs mismatch: %v", err)
|
||||||
}
|
}
|
||||||
if err := msg.Decode(&resp); err != nil {
|
case 2:
|
||||||
t.Errorf("reply decode error: %v", err)
|
cost := peer.GetRequestCost(GetHelperTrieProofsMsg, len(requestsV2))
|
||||||
|
sendRequest(peer.app, GetHelperTrieProofsMsg, 42, cost, requestsV2)
|
||||||
|
if err := expectResponse(peer.app, HelperTrieProofsMsg, 42, testBufLimit, proofsV2); err != nil {
|
||||||
|
t.Errorf("proofs mismatch: %v", err)
|
||||||
}
|
}
|
||||||
if msg.Code != ProofsV2Msg {
|
}
|
||||||
t.Errorf("Message code mismatch")
|
}
|
||||||
|
|
||||||
|
// Tests that bloombits proofs can be correctly retrieved.
|
||||||
|
func TestGetBloombitsProofs(t *testing.T) {
|
||||||
|
// Assemble the test environment
|
||||||
|
db, _ := ethdb.NewMemDatabase()
|
||||||
|
pm := newTestProtocolManagerMust(t, false, light.BloomTrieFrequency+256, testChainGen, nil, nil, db)
|
||||||
|
bc := pm.blockchain.(*core.BlockChain)
|
||||||
|
peer, _ := newTestPeer(t, "peer", 2, pm, true)
|
||||||
|
defer peer.close()
|
||||||
|
|
||||||
|
// Wait a while for the bloombits indexer to process the new headers
|
||||||
|
time.Sleep(100 * time.Millisecond * time.Duration(light.BloomTrieFrequency/4096)) // Chain indexer throttling
|
||||||
|
time.Sleep(250 * time.Millisecond) // CI tester slack
|
||||||
|
|
||||||
|
// Request and verify each bit of the bloom bits proofs
|
||||||
|
for bit := 0; bit < 2048; bit++ {
|
||||||
|
// Assemble therequest and proofs for the bloombits
|
||||||
|
key := make([]byte, 10)
|
||||||
|
|
||||||
|
binary.BigEndian.PutUint16(key[:2], uint16(bit))
|
||||||
|
binary.BigEndian.PutUint64(key[2:], uint64(light.BloomTrieFrequency))
|
||||||
|
|
||||||
|
requests := []HelperTrieReq{{
|
||||||
|
Type: htBloomBits,
|
||||||
|
TrieIdx: 0,
|
||||||
|
Key: key,
|
||||||
|
}}
|
||||||
|
var proofs HelperTrieResps
|
||||||
|
|
||||||
|
root := light.GetBloomTrieRoot(db, 0, bc.GetHeaderByNumber(light.BloomTrieFrequency-1).Hash())
|
||||||
|
trie, _ := trie.New(root, trie.NewDatabase(ethdb.NewTable(db, light.BloomTrieTablePrefix)))
|
||||||
|
trie.Prove(key, 0, &proofs.Proofs)
|
||||||
|
|
||||||
|
// Send the proof request and verify the response
|
||||||
|
cost := peer.GetRequestCost(GetHelperTrieProofsMsg, len(requests))
|
||||||
|
sendRequest(peer.app, GetHelperTrieProofsMsg, 42, cost, requests)
|
||||||
|
if err := expectResponse(peer.app, HelperTrieProofsMsg, 42, testBufLimit, proofs); err != nil {
|
||||||
|
t.Errorf("bit %d: proofs mismatch: %v", bit, err)
|
||||||
}
|
}
|
||||||
if resp.ReqID != 42 {
|
|
||||||
t.Errorf("ReqID mismatch")
|
|
||||||
}
|
|
||||||
if resp.BV != testBufLimit {
|
|
||||||
t.Errorf("BV mismatch")
|
|
||||||
}
|
|
||||||
testCheckProof(t, proofsV2, resp.Data)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -31,6 +31,7 @@ import (
|
|||||||
"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/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/event"
|
"github.com/ethereum/go-ethereum/event"
|
||||||
"github.com/ethereum/go-ethereum/les/flowcontrol"
|
"github.com/ethereum/go-ethereum/les/flowcontrol"
|
||||||
@ -55,6 +56,9 @@ var (
|
|||||||
testContractCodeDeployed = testContractCode[16:]
|
testContractCodeDeployed = testContractCode[16:]
|
||||||
testContractDeployed = uint64(2)
|
testContractDeployed = uint64(2)
|
||||||
|
|
||||||
|
testEventEmitterCode = common.Hex2Bytes("60606040523415600e57600080fd5b7f57050ab73f6b9ebdd9f76b8d4997793f48cf956e965ee070551b9ca0bb71584e60405160405180910390a160358060476000396000f3006060604052600080fd00a165627a7a723058203f727efcad8b5811f8cb1fc2620ce5e8c63570d697aef968172de296ea3994140029")
|
||||||
|
testEventEmitterAddr common.Address
|
||||||
|
|
||||||
testBufLimit = uint64(100)
|
testBufLimit = uint64(100)
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -85,15 +89,19 @@ func testChainGen(i int, block *core.BlockGen) {
|
|||||||
// In block 2, the test bank sends some more ether to account #1.
|
// In block 2, the test bank sends some more ether to account #1.
|
||||||
// acc1Addr passes it on to account #2.
|
// acc1Addr passes it on to account #2.
|
||||||
// acc1Addr creates a test contract.
|
// acc1Addr creates a test contract.
|
||||||
tx1, _ := types.SignTx(types.NewTransaction(block.TxNonce(testBankAddress), acc1Addr, big.NewInt(1000), params.TxGas, nil, nil), signer, testBankKey)
|
// acc1Addr creates a test event.
|
||||||
nonce := block.TxNonce(acc1Addr)
|
nonce := block.TxNonce(acc1Addr)
|
||||||
|
|
||||||
|
tx1, _ := types.SignTx(types.NewTransaction(block.TxNonce(testBankAddress), acc1Addr, big.NewInt(1000), params.TxGas, nil, nil), signer, testBankKey)
|
||||||
tx2, _ := types.SignTx(types.NewTransaction(nonce, acc2Addr, big.NewInt(1000), params.TxGas, nil, nil), signer, acc1Key)
|
tx2, _ := types.SignTx(types.NewTransaction(nonce, acc2Addr, big.NewInt(1000), params.TxGas, nil, nil), signer, acc1Key)
|
||||||
nonce++
|
tx3, _ := types.SignTx(types.NewContractCreation(nonce+1, big.NewInt(0), 200000, big.NewInt(0), testContractCode), signer, acc1Key)
|
||||||
tx3, _ := types.SignTx(types.NewContractCreation(nonce, big.NewInt(0), 200000, big.NewInt(0), testContractCode), signer, acc1Key)
|
testContractAddr = crypto.CreateAddress(acc1Addr, nonce+1)
|
||||||
testContractAddr = crypto.CreateAddress(acc1Addr, nonce)
|
tx4, _ := types.SignTx(types.NewContractCreation(nonce+2, big.NewInt(0), 200000, big.NewInt(0), testEventEmitterCode), signer, acc1Key)
|
||||||
|
testEventEmitterAddr = crypto.CreateAddress(acc1Addr, nonce+2)
|
||||||
block.AddTx(tx1)
|
block.AddTx(tx1)
|
||||||
block.AddTx(tx2)
|
block.AddTx(tx2)
|
||||||
block.AddTx(tx3)
|
block.AddTx(tx3)
|
||||||
|
block.AddTx(tx4)
|
||||||
case 2:
|
case 2:
|
||||||
// Block 3 is empty but was mined by account #2.
|
// Block 3 is empty but was mined by account #2.
|
||||||
block.SetCoinbase(acc2Addr)
|
block.SetCoinbase(acc2Addr)
|
||||||
@ -147,6 +155,16 @@ 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)
|
||||||
|
chtIndexer.Start(blockchain)
|
||||||
|
|
||||||
|
bbtIndexer := light.NewBloomTrieIndexer(db, false)
|
||||||
|
|
||||||
|
bloomIndexer := eth.NewBloomIndexer(db, params.BloomBitsBlocks)
|
||||||
|
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)
|
||||||
|
@ -321,7 +321,7 @@ const (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type HelperTrieReq struct {
|
type HelperTrieReq struct {
|
||||||
HelperTrieType uint
|
Type uint
|
||||||
TrieIdx uint64
|
TrieIdx uint64
|
||||||
Key []byte
|
Key []byte
|
||||||
FromLevel, AuxReq uint
|
FromLevel, AuxReq uint
|
||||||
@ -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.ChtFrequency
|
return peer.headInfo.Number >= light.HelperTrieConfirmations && r.ChtNum <= (peer.headInfo.Number-light.HelperTrieConfirmations)/light.CHTFrequencyClient
|
||||||
}
|
}
|
||||||
|
|
||||||
// Request sends an ODR request to the LES network (implementation of LesOdrRequest)
|
// Request sends an ODR request to the LES network (implementation of LesOdrRequest)
|
||||||
@ -374,10 +374,10 @@ func (r *ChtRequest) Request(reqID uint64, peer *peer) error {
|
|||||||
var encNum [8]byte
|
var encNum [8]byte
|
||||||
binary.BigEndian.PutUint64(encNum[:], r.BlockNum)
|
binary.BigEndian.PutUint64(encNum[:], r.BlockNum)
|
||||||
req := HelperTrieReq{
|
req := HelperTrieReq{
|
||||||
HelperTrieType: htCanonical,
|
Type: htCanonical,
|
||||||
TrieIdx: r.ChtNum,
|
TrieIdx: r.ChtNum,
|
||||||
Key: encNum[:],
|
Key: encNum[:],
|
||||||
AuxReq: auxHeader,
|
AuxReq: auxHeader,
|
||||||
}
|
}
|
||||||
return peer.RequestHelperTrieProofs(reqID, r.GetCost(peer), []HelperTrieReq{req})
|
return peer.RequestHelperTrieProofs(reqID, r.GetCost(peer), []HelperTrieReq{req})
|
||||||
}
|
}
|
||||||
@ -493,14 +493,14 @@ func (r *BloomRequest) Request(reqID uint64, peer *peer) error {
|
|||||||
reqs := make([]HelperTrieReq, len(r.SectionIdxList))
|
reqs := make([]HelperTrieReq, len(r.SectionIdxList))
|
||||||
|
|
||||||
var encNumber [10]byte
|
var encNumber [10]byte
|
||||||
binary.BigEndian.PutUint16(encNumber[0:2], uint16(r.BitIdx))
|
binary.BigEndian.PutUint16(encNumber[:2], uint16(r.BitIdx))
|
||||||
|
|
||||||
for i, sectionIdx := range r.SectionIdxList {
|
for i, sectionIdx := range r.SectionIdxList {
|
||||||
binary.BigEndian.PutUint64(encNumber[2:10], sectionIdx)
|
binary.BigEndian.PutUint64(encNumber[2:], sectionIdx)
|
||||||
reqs[i] = HelperTrieReq{
|
reqs[i] = HelperTrieReq{
|
||||||
HelperTrieType: htBloomBits,
|
Type: htBloomBits,
|
||||||
TrieIdx: r.BloomTrieNum,
|
TrieIdx: r.BloomTrieNum,
|
||||||
Key: common.CopyBytes(encNumber[:]),
|
Key: common.CopyBytes(encNumber[:]),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return peer.RequestHelperTrieProofs(reqID, r.GetCost(peer), reqs)
|
return peer.RequestHelperTrieProofs(reqID, r.GetCost(peer), reqs)
|
||||||
@ -525,10 +525,10 @@ func (r *BloomRequest) Validate(db ethdb.Database, msg *Msg) error {
|
|||||||
|
|
||||||
// Verify the proofs
|
// Verify the proofs
|
||||||
var encNumber [10]byte
|
var encNumber [10]byte
|
||||||
binary.BigEndian.PutUint16(encNumber[0:2], uint16(r.BitIdx))
|
binary.BigEndian.PutUint16(encNumber[:2], uint16(r.BitIdx))
|
||||||
|
|
||||||
for i, idx := range r.SectionIdxList {
|
for i, idx := range r.SectionIdxList {
|
||||||
binary.BigEndian.PutUint64(encNumber[2:10], idx)
|
binary.BigEndian.PutUint64(encNumber[2:], idx)
|
||||||
value, err, _ := trie.VerifyProof(r.BloomTrieRoot, encNumber[:], reads)
|
value, err, _ := trie.VerifyProof(r.BloomTrieRoot, encNumber[:], reads)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -281,7 +281,6 @@ func (p *peer) RequestProofs(reqID, cost uint64, reqs []ProofReq) error {
|
|||||||
default:
|
default:
|
||||||
panic(nil)
|
panic(nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// RequestHelperTrieProofs fetches a batch of HelperTrie merkle proofs from a remote node.
|
// RequestHelperTrieProofs fetches a batch of HelperTrie merkle proofs from a remote node.
|
||||||
@ -291,12 +290,12 @@ func (p *peer) RequestHelperTrieProofs(reqID, cost uint64, reqs []HelperTrieReq)
|
|||||||
case lpv1:
|
case lpv1:
|
||||||
reqsV1 := make([]ChtReq, len(reqs))
|
reqsV1 := make([]ChtReq, len(reqs))
|
||||||
for i, req := range reqs {
|
for i, req := range reqs {
|
||||||
if req.HelperTrieType != htCanonical || req.AuxReq != auxHeader || len(req.Key) != 8 {
|
if req.Type != htCanonical || req.AuxReq != auxHeader || len(req.Key) != 8 {
|
||||||
return fmt.Errorf("Request invalid in LES/1 mode")
|
return fmt.Errorf("Request invalid in LES/1 mode")
|
||||||
}
|
}
|
||||||
blockNum := binary.BigEndian.Uint64(req.Key)
|
blockNum := binary.BigEndian.Uint64(req.Key)
|
||||||
// convert HelperTrie request to old CHT request
|
// convert HelperTrie request to old CHT request
|
||||||
reqsV1[i] = ChtReq{ChtNum: (req.TrieIdx + 1) * (light.ChtFrequency / light.ChtV1Frequency), BlockNum: blockNum, FromLevel: req.FromLevel}
|
reqsV1[i] = ChtReq{ChtNum: (req.TrieIdx + 1) * (light.CHTFrequencyClient / light.CHTFrequencyServer), BlockNum: blockNum, FromLevel: req.FromLevel}
|
||||||
}
|
}
|
||||||
return sendRequest(p.rw, GetHeaderProofsMsg, reqID, cost, reqsV1)
|
return sendRequest(p.rw, GetHeaderProofsMsg, reqID, cost, reqsV1)
|
||||||
case lpv2:
|
case lpv2:
|
||||||
|
@ -20,7 +20,6 @@ package les
|
|||||||
import (
|
import (
|
||||||
"crypto/ecdsa"
|
"crypto/ecdsa"
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
"fmt"
|
|
||||||
"math"
|
"math"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
@ -73,23 +72,22 @@ 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.ChtFrequency / light.ChtV1Frequency)
|
chtV2SectionCount := chtV1SectionCount / (light.CHTFrequencyClient / light.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.ChtFrequency/light.ChtV1Frequency) - 1
|
chtLastSectionV1 := (chtLastSection+1)*(light.CHTFrequencyClient/light.CHTFrequencyServer) - 1
|
||||||
chtSectionHead := srv.chtIndexer.SectionHead(chtLastSectionV1)
|
chtSectionHead := srv.chtIndexer.SectionHead(chtLastSectionV1)
|
||||||
chtRoot := light.GetChtV2Root(pm.chainDb, chtLastSection, chtSectionHead)
|
chtRoot := light.GetChtV2Root(pm.chainDb, chtLastSection, chtSectionHead)
|
||||||
logger.Info("CHT", "section", chtLastSection, "sectionHead", fmt.Sprintf("%064x", chtSectionHead), "root", fmt.Sprintf("%064x", chtRoot))
|
logger.Info("Loaded CHT", "section", chtLastSection, "head", chtSectionHead, "root", chtRoot)
|
||||||
}
|
}
|
||||||
|
|
||||||
bloomTrieSectionCount, _, _ := srv.bloomTrieIndexer.Sections()
|
bloomTrieSectionCount, _, _ := srv.bloomTrieIndexer.Sections()
|
||||||
if bloomTrieSectionCount != 0 {
|
if bloomTrieSectionCount != 0 {
|
||||||
bloomTrieLastSection := bloomTrieSectionCount - 1
|
bloomTrieLastSection := bloomTrieSectionCount - 1
|
||||||
bloomTrieSectionHead := srv.bloomTrieIndexer.SectionHead(bloomTrieLastSection)
|
bloomTrieSectionHead := srv.bloomTrieIndexer.SectionHead(bloomTrieLastSection)
|
||||||
bloomTrieRoot := light.GetBloomTrieRoot(pm.chainDb, bloomTrieLastSection, bloomTrieSectionHead)
|
bloomTrieRoot := light.GetBloomTrieRoot(pm.chainDb, bloomTrieLastSection, bloomTrieSectionHead)
|
||||||
logger.Info("BloomTrie", "section", bloomTrieLastSection, "sectionHead", fmt.Sprintf("%064x", bloomTrieSectionHead), "root", fmt.Sprintf("%064x", bloomTrieRoot))
|
logger.Info("Loaded bloom trie", "section", bloomTrieLastSection, "head", bloomTrieSectionHead, "root", bloomTrieRoot)
|
||||||
}
|
}
|
||||||
|
|
||||||
srv.chtIndexer.Start(eth.BlockChain())
|
srv.chtIndexer.Start(eth.BlockChain())
|
||||||
|
@ -127,7 +127,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)*ChtFrequency-1, "hash", cp.sectionHead)
|
log.Info("Added trusted checkpoint", "chain", cp.name, "block", (cp.sectionIdx+1)*CHTFrequencyClient-1, "hash", cp.sectionHead)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *LightChain) getProcInterrupt() bool {
|
func (self *LightChain) getProcInterrupt() bool {
|
||||||
@ -453,8 +453,8 @@ func (self *LightChain) SyncCht(ctx context.Context) bool {
|
|||||||
}
|
}
|
||||||
headNum := self.CurrentHeader().Number.Uint64()
|
headNum := self.CurrentHeader().Number.Uint64()
|
||||||
chtCount, _, _ := self.odr.ChtIndexer().Sections()
|
chtCount, _, _ := self.odr.ChtIndexer().Sections()
|
||||||
if headNum+1 < chtCount*ChtFrequency {
|
if headNum+1 < chtCount*CHTFrequencyClient {
|
||||||
num := chtCount*ChtFrequency - 1
|
num := chtCount*CHTFrequencyClient - 1
|
||||||
header, err := GetHeaderByNumber(ctx, self.odr, num)
|
header, err := GetHeaderByNumber(ctx, self.odr, num)
|
||||||
if header != nil && err == nil {
|
if header != nil && err == nil {
|
||||||
self.mu.Lock()
|
self.mu.Lock()
|
||||||
|
@ -29,7 +29,9 @@ import (
|
|||||||
// NodeSet stores a set of trie nodes. It implements trie.Database and can also
|
// NodeSet stores a set of trie nodes. It implements trie.Database and can also
|
||||||
// act as a cache for another trie.Database.
|
// act as a cache for another trie.Database.
|
||||||
type NodeSet struct {
|
type NodeSet struct {
|
||||||
db map[string][]byte
|
nodes map[string][]byte
|
||||||
|
order []string
|
||||||
|
|
||||||
dataSize int
|
dataSize int
|
||||||
lock sync.RWMutex
|
lock sync.RWMutex
|
||||||
}
|
}
|
||||||
@ -37,7 +39,7 @@ type NodeSet struct {
|
|||||||
// NewNodeSet creates an empty node set
|
// NewNodeSet creates an empty node set
|
||||||
func NewNodeSet() *NodeSet {
|
func NewNodeSet() *NodeSet {
|
||||||
return &NodeSet{
|
return &NodeSet{
|
||||||
db: make(map[string][]byte),
|
nodes: make(map[string][]byte),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -46,10 +48,15 @@ func (db *NodeSet) Put(key []byte, value []byte) error {
|
|||||||
db.lock.Lock()
|
db.lock.Lock()
|
||||||
defer db.lock.Unlock()
|
defer db.lock.Unlock()
|
||||||
|
|
||||||
if _, ok := db.db[string(key)]; !ok {
|
if _, ok := db.nodes[string(key)]; ok {
|
||||||
db.db[string(key)] = common.CopyBytes(value)
|
return nil
|
||||||
db.dataSize += len(value)
|
|
||||||
}
|
}
|
||||||
|
keystr := string(key)
|
||||||
|
|
||||||
|
db.nodes[keystr] = common.CopyBytes(value)
|
||||||
|
db.order = append(db.order, keystr)
|
||||||
|
db.dataSize += len(value)
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -58,7 +65,7 @@ func (db *NodeSet) Get(key []byte) ([]byte, error) {
|
|||||||
db.lock.RLock()
|
db.lock.RLock()
|
||||||
defer db.lock.RUnlock()
|
defer db.lock.RUnlock()
|
||||||
|
|
||||||
if entry, ok := db.db[string(key)]; ok {
|
if entry, ok := db.nodes[string(key)]; ok {
|
||||||
return entry, nil
|
return entry, nil
|
||||||
}
|
}
|
||||||
return nil, errors.New("not found")
|
return nil, errors.New("not found")
|
||||||
@ -75,7 +82,7 @@ func (db *NodeSet) KeyCount() int {
|
|||||||
db.lock.RLock()
|
db.lock.RLock()
|
||||||
defer db.lock.RUnlock()
|
defer db.lock.RUnlock()
|
||||||
|
|
||||||
return len(db.db)
|
return len(db.nodes)
|
||||||
}
|
}
|
||||||
|
|
||||||
// DataSize returns the aggregated data size of nodes in the set
|
// DataSize returns the aggregated data size of nodes in the set
|
||||||
@ -92,8 +99,8 @@ func (db *NodeSet) NodeList() NodeList {
|
|||||||
defer db.lock.RUnlock()
|
defer db.lock.RUnlock()
|
||||||
|
|
||||||
var values NodeList
|
var values NodeList
|
||||||
for _, value := range db.db {
|
for _, key := range db.order {
|
||||||
values = append(values, value)
|
values = append(values, db.nodes[key])
|
||||||
}
|
}
|
||||||
return values
|
return values
|
||||||
}
|
}
|
||||||
@ -103,7 +110,7 @@ func (db *NodeSet) Store(target ethdb.Putter) {
|
|||||||
db.lock.RLock()
|
db.lock.RLock()
|
||||||
defer db.lock.RUnlock()
|
defer db.lock.RUnlock()
|
||||||
|
|
||||||
for key, value := range db.db {
|
for key, value := range db.nodes {
|
||||||
target.Put([]byte(key), value)
|
target.Put([]byte(key), value)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -52,13 +52,13 @@ 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*ChtFrequency - 1
|
sectionHeadNum = chtCount*CHTFrequencyClient - 1
|
||||||
sectionHead = odr.ChtIndexer().SectionHead(chtCount - 1)
|
sectionHead = odr.ChtIndexer().SectionHead(chtCount - 1)
|
||||||
canonicalHash = core.GetCanonicalHash(db, sectionHeadNum)
|
canonicalHash = core.GetCanonicalHash(db, sectionHeadNum)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if number >= chtCount*ChtFrequency {
|
if number >= chtCount*CHTFrequencyClient {
|
||||||
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}
|
||||||
|
@ -19,7 +19,6 @@ package light
|
|||||||
import (
|
import (
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
|
||||||
"math/big"
|
"math/big"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
@ -35,8 +34,14 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
ChtFrequency = 32768
|
// CHTFrequencyClient is the block frequency for creating CHTs on the client side.
|
||||||
ChtV1Frequency = 4096 // as long as we want to retain LES/1 compatibility, servers generate CHTs with the old, higher frequency
|
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
|
||||||
|
|
||||||
HelperTrieConfirmations = 2048 // number of confirmations before a server is expected to have the given HelperTrie available
|
HelperTrieConfirmations = 2048 // number of confirmations before a server is expected to have the given HelperTrie available
|
||||||
HelperTrieProcessConfirmations = 256 // number of confirmations before a HelperTrie is generated
|
HelperTrieProcessConfirmations = 256 // number of confirmations before a HelperTrie is generated
|
||||||
)
|
)
|
||||||
@ -100,7 +105,7 @@ func GetChtRoot(db ethdb.Database, sectionIdx uint64, sectionHead common.Hash) c
|
|||||||
// GetChtV2Root reads the CHT root assoctiated to the given section from the database
|
// GetChtV2Root reads the CHT root assoctiated to the given section from the database
|
||||||
// Note that sectionIdx is specified according to LES/2 CHT section size
|
// Note that sectionIdx is specified according to LES/2 CHT section size
|
||||||
func GetChtV2Root(db ethdb.Database, sectionIdx uint64, sectionHead common.Hash) common.Hash {
|
func GetChtV2Root(db ethdb.Database, sectionIdx uint64, sectionHead common.Hash) common.Hash {
|
||||||
return GetChtRoot(db, (sectionIdx+1)*(ChtFrequency/ChtV1Frequency)-1, sectionHead)
|
return GetChtRoot(db, (sectionIdx+1)*(CHTFrequencyClient/CHTFrequencyServer)-1, sectionHead)
|
||||||
}
|
}
|
||||||
|
|
||||||
// StoreChtRoot writes the CHT root assoctiated to the given section into the database
|
// StoreChtRoot writes the CHT root assoctiated to the given section into the database
|
||||||
@ -124,10 +129,10 @@ type ChtIndexerBackend struct {
|
|||||||
func NewChtIndexer(db ethdb.Database, clientMode bool) *core.ChainIndexer {
|
func NewChtIndexer(db ethdb.Database, clientMode bool) *core.ChainIndexer {
|
||||||
var sectionSize, confirmReq uint64
|
var sectionSize, confirmReq uint64
|
||||||
if clientMode {
|
if clientMode {
|
||||||
sectionSize = ChtFrequency
|
sectionSize = CHTFrequencyClient
|
||||||
confirmReq = HelperTrieConfirmations
|
confirmReq = HelperTrieConfirmations
|
||||||
} else {
|
} else {
|
||||||
sectionSize = ChtV1Frequency
|
sectionSize = CHTFrequencyServer
|
||||||
confirmReq = HelperTrieProcessConfirmations
|
confirmReq = HelperTrieProcessConfirmations
|
||||||
}
|
}
|
||||||
idb := ethdb.NewTable(db, "chtIndex-")
|
idb := ethdb.NewTable(db, "chtIndex-")
|
||||||
@ -174,8 +179,8 @@ func (c *ChtIndexerBackend) Commit() error {
|
|||||||
}
|
}
|
||||||
c.triedb.Commit(root, false)
|
c.triedb.Commit(root, false)
|
||||||
|
|
||||||
if ((c.section+1)*c.sectionSize)%ChtFrequency == 0 {
|
if ((c.section+1)*c.sectionSize)%CHTFrequencyClient == 0 {
|
||||||
log.Info("Storing CHT", "idx", c.section*c.sectionSize/ChtFrequency, "sectionHead", fmt.Sprintf("%064x", c.lastHash), "root", fmt.Sprintf("%064x", root))
|
log.Info("Storing CHT", "section", c.section*c.sectionSize/CHTFrequencyClient, "head", c.lastHash, "root", root)
|
||||||
}
|
}
|
||||||
StoreChtRoot(c.diskdb, c.section, c.lastHash, root)
|
StoreChtRoot(c.diskdb, c.section, c.lastHash, root)
|
||||||
return nil
|
return nil
|
||||||
@ -294,7 +299,7 @@ func (b *BloomTrieIndexerBackend) Commit() error {
|
|||||||
b.triedb.Commit(root, false)
|
b.triedb.Commit(root, false)
|
||||||
|
|
||||||
sectionHead := b.sectionHeads[b.bloomTrieRatio-1]
|
sectionHead := b.sectionHeads[b.bloomTrieRatio-1]
|
||||||
log.Info("Storing BloomTrie", "section", b.section, "sectionHead", fmt.Sprintf("%064x", sectionHead), "root", fmt.Sprintf("%064x", root), "compression ratio", float64(compSize)/float64(decompSize))
|
log.Info("Storing bloom trie", "section", b.section, "head", sectionHead, "root", root, "compression", float64(compSize)/float64(decompSize))
|
||||||
StoreBloomTrieRoot(b.diskdb, b.section, sectionHead, root)
|
StoreBloomTrieRoot(b.diskdb, b.section, sectionHead, root)
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
Loading…
Reference in New Issue
Block a user