diff --git a/les/backend.go b/les/backend.go index 200fe8c3c1..9bd8c9282a 100644 --- a/les/backend.go +++ b/les/backend.go @@ -223,8 +223,8 @@ func (s *LightEthereum) Protocols() []p2p.Protocol { // Start implements node.Service, starting all internal goroutines needed by the // Ethereum protocol implementation. func (s *LightEthereum) Start(srvr *p2p.Server) error { - s.startBloomHandlers(params.BloomBitsBlocksClient, params.HelperTrieConfirmations) log.Warn("Light client mode is an experimental feature") + s.startBloomHandlers(params.BloomBitsBlocksClient) s.netRPCService = ethapi.NewPublicNetAPI(srvr, s.networkId) // clients are searching for the first advertised protocol in the list protocolVersion := AdvertiseProtocolVersions[0] diff --git a/les/bloombits.go b/les/bloombits.go index 4e6fecbe20..aea0fcd5f4 100644 --- a/les/bloombits.go +++ b/les/bloombits.go @@ -43,7 +43,7 @@ const ( // startBloomHandlers starts a batch of goroutines to accept bloom bit database // retrievals from possibly a range of filters and serving the data to satisfy. -func (eth *LightEthereum) startBloomHandlers(sectionSize, confirms uint64) { +func (eth *LightEthereum) startBloomHandlers(sectionSize uint64) { for i := 0; i < bloomServiceThreads; i++ { go func() { for { @@ -54,7 +54,7 @@ func (eth *LightEthereum) startBloomHandlers(sectionSize, confirms uint64) { case request := <-eth.bloomRequests: task := <-request task.Bitsets = make([][]byte, len(task.Sections)) - compVectors, err := light.GetBloomBits(task.Context, sectionSize, confirms, eth.odr, task.Bit, task.Sections) + compVectors, err := light.GetBloomBits(task.Context, eth.odr, task.Bit, task.Sections) if err == nil { for i := range task.Sections { if blob, err := bitutil.DecompressBytes(compVectors[i], int(sectionSize/8)); err == nil { diff --git a/les/handler.go b/les/handler.go index f0a2f06347..dabeb83cf6 100644 --- a/les/handler.go +++ b/les/handler.go @@ -1149,8 +1149,8 @@ func (pm *ProtocolManager) getAccount(statedb *state.StateDB, root, hash common. func (pm *ProtocolManager) getHelperTrie(id uint, idx uint64) (common.Hash, string) { switch id { case htCanonical: - idxV2 := (idx+1)*(pm.indexerConfig.ChtClientSize/pm.indexerConfig.ChtSize) - 1 - sectionHead := rawdb.ReadCanonicalHash(pm.chainDb, (idx+1)*pm.indexerConfig.ChtClientSize-1) + idxV2 := (idx+1)*(pm.indexerConfig.PairChtSize/pm.indexerConfig.ChtSize) - 1 + sectionHead := rawdb.ReadCanonicalHash(pm.chainDb, (idx+1)*pm.indexerConfig.PairChtSize-1) return light.GetChtRoot(pm.chainDb, idxV2, sectionHead), light.ChtTablePrefix case htBloomBits: sectionHead := rawdb.ReadCanonicalHash(pm.chainDb, (idx+1)*pm.indexerConfig.BloomTrieSize-1) diff --git a/les/odr.go b/les/odr.go index 7a775be8c7..4849cda545 100644 --- a/les/odr.go +++ b/les/odr.go @@ -71,6 +71,11 @@ func (odr *LesOdr) BloomIndexer() *core.ChainIndexer { return odr.bloomIndexer } +// IndexerConfig returns the indexer config. +func (odr *LesOdr) IndexerConfig() *light.IndexerConfig { + return odr.indexerConfig +} + const ( MsgBlockBodies = iota MsgCode diff --git a/les/odr_requests.go b/les/odr_requests.go index b5c9891cd2..f34cac0ae3 100644 --- a/les/odr_requests.go +++ b/les/odr_requests.go @@ -387,7 +387,7 @@ func (r *ChtRequest) Request(reqID uint64, peer *peer, config *light.IndexerConf } blockNum := binary.BigEndian.Uint64(req.Key) // convert HelperTrie request to old CHT request - reqsV1 = ChtReq{ChtNum: (req.TrieIdx+1)*(config.ChtSize/config.ChtClientSize) - 1, BlockNum: blockNum, FromLevel: req.FromLevel} + reqsV1 = ChtReq{ChtNum: (req.TrieIdx+1)*(config.ChtSize/config.PairChtSize) - 1, BlockNum: blockNum, FromLevel: req.FromLevel} return peer.RequestHelperTrieProofs(reqID, r.GetCost(peer), []interface{}{reqsV1}) case lpv2: return peer.RequestHelperTrieProofs(reqID, r.GetCost(peer), []interface{}{req}) diff --git a/light/lightchain.go b/light/lightchain.go index 80c58402cc..bb01e7d310 100644 --- a/light/lightchain.go +++ b/light/lightchain.go @@ -292,7 +292,7 @@ func (self *LightChain) GetBlockByHash(ctx context.Context, hash common.Hash) (* // GetBlockByNumber retrieves a block from the database or ODR service by // number, caching it (associated with its hash) if found. func (self *LightChain) GetBlockByNumber(ctx context.Context, number uint64) (*types.Block, error) { - hash, err := GetCanonicalHash(ctx, self.odr, self.indexerConfig.ChtSize, self.indexerConfig.ChtConfirm, number) + hash, err := GetCanonicalHash(ctx, self.odr, number) if hash == (common.Hash{}) || err != nil { return nil, err } @@ -459,7 +459,7 @@ func (self *LightChain) GetHeaderByNumberOdr(ctx context.Context, number uint64) if header := self.hc.GetHeaderByNumber(number); header != nil { return header, nil } - return GetHeaderByNumber(ctx, self.indexerConfig.ChtSize, self.indexerConfig.ChtConfirm, self.odr, number) + return GetHeaderByNumber(ctx, self.odr, number) } // Config retrieves the header chain's chain configuration. @@ -473,7 +473,7 @@ func (self *LightChain) SyncCht(ctx context.Context) bool { chtCount, _, _ := self.odr.ChtIndexer().Sections() if headNum+1 < chtCount*self.indexerConfig.ChtSize { num := chtCount*self.indexerConfig.ChtSize - 1 - header, err := GetHeaderByNumber(ctx, self.indexerConfig.ChtSize, self.indexerConfig.ChtConfirm, self.odr, num) + header, err := GetHeaderByNumber(ctx, self.odr, num) if header != nil && err == nil { self.mu.Lock() if self.hc.CurrentHeader().Number.Uint64() < header.Number.Uint64() { diff --git a/light/odr.go b/light/odr.go index 15a649889e..aeefbe9395 100644 --- a/light/odr.go +++ b/light/odr.go @@ -40,6 +40,7 @@ type OdrBackend interface { BloomTrieIndexer() *core.ChainIndexer BloomIndexer() *core.ChainIndexer Retrieve(ctx context.Context, req OdrRequest) error + IndexerConfig() *IndexerConfig } // OdrRequest is an interface for retrieval requests diff --git a/light/odr_util.go b/light/odr_util.go index e4d639b908..ee509993c1 100644 --- a/light/odr_util.go +++ b/light/odr_util.go @@ -30,7 +30,7 @@ import ( var sha3_nil = crypto.Keccak256Hash(nil) -func GetHeaderByNumber(ctx context.Context, size uint64, confirms uint64, odr OdrBackend, number uint64) (*types.Header, error) { +func GetHeaderByNumber(ctx context.Context, odr OdrBackend, number uint64) (*types.Header, error) { db := odr.Database() hash := rawdb.ReadCanonicalHash(db, number) if (hash != common.Hash{}) { @@ -53,13 +53,13 @@ func GetHeaderByNumber(ctx context.Context, size uint64, confirms uint64, odr Od for chtCount > 0 && canonicalHash != sectionHead && canonicalHash != (common.Hash{}) { chtCount-- if chtCount > 0 { - sectionHeadNum = chtCount*size - 1 + sectionHeadNum = chtCount*odr.IndexerConfig().ChtSize - 1 sectionHead = odr.ChtIndexer().SectionHead(chtCount - 1) canonicalHash = rawdb.ReadCanonicalHash(db, sectionHeadNum) } } } - if number >= chtCount*size { + if number >= chtCount*odr.IndexerConfig().ChtSize { return nil, ErrNoTrustedCht } r := &ChtRequest{ChtRoot: GetChtRoot(db, chtCount-1, sectionHead), ChtNum: chtCount - 1, BlockNum: number} @@ -69,12 +69,12 @@ func GetHeaderByNumber(ctx context.Context, size uint64, confirms uint64, odr Od return r.Header, nil } -func GetCanonicalHash(ctx context.Context, odr OdrBackend, size uint64, confirm uint64, number uint64) (common.Hash, error) { +func GetCanonicalHash(ctx context.Context, odr OdrBackend, number uint64) (common.Hash, error) { hash := rawdb.ReadCanonicalHash(odr.Database(), number) if (hash != common.Hash{}) { return hash, nil } - header, err := GetHeaderByNumber(ctx, size, confirm, odr, number) + header, err := GetHeaderByNumber(ctx, odr, number) if header != nil { return header.Hash(), nil } @@ -174,10 +174,10 @@ 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 -func GetBloomBits(ctx context.Context, size uint64, confirms uint64, odr OdrBackend, bitIdx uint, sectionIdxList []uint64) ([][]byte, error) { - db := odr.Database() - result := make([][]byte, len(sectionIdxList)) +func GetBloomBits(ctx context.Context, odr OdrBackend, bitIdx uint, sectionIdxList []uint64) ([][]byte, error) { var ( + db = odr.Database() + result = make([][]byte, len(sectionIdxList)) reqList []uint64 reqIdx []int ) @@ -193,7 +193,7 @@ func GetBloomBits(ctx context.Context, size uint64, confirms uint64, odr OdrBack for bloomTrieCount > 0 && canonicalHash != sectionHead && canonicalHash != (common.Hash{}) { bloomTrieCount-- if bloomTrieCount > 0 { - sectionHeadNum = bloomTrieCount*size - 1 + sectionHeadNum = bloomTrieCount*odr.IndexerConfig().BloomTrieSize - 1 sectionHead = odr.BloomTrieIndexer().SectionHead(bloomTrieCount - 1) canonicalHash = rawdb.ReadCanonicalHash(db, sectionHeadNum) } @@ -201,7 +201,7 @@ func GetBloomBits(ctx context.Context, size uint64, confirms uint64, odr OdrBack } for i, sectionIdx := range sectionIdxList { - sectionHead := rawdb.ReadCanonicalHash(db, (sectionIdx+1)*size-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 // 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) @@ -209,6 +209,7 @@ func GetBloomBits(ctx context.Context, size uint64, confirms uint64, odr OdrBack if err == nil { result[i] = bloomBits } else { + // TODO(rjl493456442) Convert sectionIndex to BloomTrie relative index if sectionIdx >= bloomTrieCount { return nil, ErrNoTrustedBloomTrie } diff --git a/light/postprocess.go b/light/postprocess.go index 4e1793564c..07fdb53b1f 100644 --- a/light/postprocess.go +++ b/light/postprocess.go @@ -34,20 +34,35 @@ import ( "github.com/ethereum/go-ethereum/trie" ) -// IndexerConfig specifies a set of configs for chain indexers. +// IndexerConfig includes a set of configs for chain indexers. type IndexerConfig struct { - ChtSize uint64 - ChtClientSize uint64 - ChtConfirm uint64 - BloomSize uint64 - BloomConfirm uint64 - BloomTrieSize uint64 + // The block frequency for creating CHTs. + ChtSize uint64 + + // A special auxiliary field represents client's chtsize for server config, otherwise represents server's chtsize. + PairChtSize uint64 + + // The number of confirmations needed to generate/accept a canonical hash help trie. + ChtConfirm uint64 + + // The block frequency for creating new bloom bits. + BloomSize uint64 + + // The number of confirmation needed before a bloom section is considered probably final and its rotated bits + // are calculated. + BloomConfirm uint64 + + // The block frequency for creating BloomTrie. + BloomTrieSize uint64 + + // The number of confirmations needed to generate/accept a bloom trie. BloomTrieConfirm uint64 } +// DefaultServerIndexerConfig wraps a set of configs as a default indexer config for server side. var DefaultServerIndexerConfig = &IndexerConfig{ ChtSize: params.CHTFrequencyServer, - ChtClientSize: params.CHTFrequencyClient, + PairChtSize: params.CHTFrequencyClient, ChtConfirm: params.HelperTrieProcessConfirmations, BloomSize: params.BloomBitsBlocks, BloomConfirm: params.BloomConfirms, @@ -55,8 +70,10 @@ var DefaultServerIndexerConfig = &IndexerConfig{ BloomTrieConfirm: params.HelperTrieProcessConfirmations, } +// DefaultClientIndexerConfig wraps a set of configs as a default indexer config for client side. var DefaultClientIndexerConfig = &IndexerConfig{ ChtSize: params.CHTFrequencyClient, + PairChtSize: params.CHTFrequencyServer, ChtConfirm: params.HelperTrieConfirmations, BloomSize: params.BloomBitsBlocksClient, BloomConfirm: params.HelperTrieConfirmations, diff --git a/params/network_params.go b/params/network_params.go index 91554b088d..74f8347d68 100644 --- a/params/network_params.go +++ b/params/network_params.go @@ -21,7 +21,7 @@ package params const ( // BloomBitsBlocks is the number of blocks a single bloom bit section vector - // contains. + // contains on the server side. BloomBitsBlocks uint64 = 4096 // BloomBitsBlocksClient is the number of blocks a single bloom bit section vector @@ -44,7 +44,7 @@ const ( // server/client sides. BloomTrieFrequency = 32768 - // HelperTrieConfirmations is the number of confirmations before a server is expected + // HelperTrieConfirmations is the number of confirmations before a client is expected // to have the given HelperTrie available. HelperTrieConfirmations = 2048