Skip to content

Commit 85a4545

Browse files
committed
all: add global block logs cache (ethereum#25459)
1 parent 022390c commit 85a4545

File tree

19 files changed

+291
-164
lines changed

19 files changed

+291
-164
lines changed

accounts/abi/bind/backends/simulated.go

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,8 @@ type SimulatedBackend struct {
6666
pendingState *state.StateDB // Currently pending state that will be the active on request
6767
pendingReceipts types.Receipts // Currently receipts for the pending block
6868

69-
events *filters.EventSystem // Event system for filtering log events live
69+
events *filters.EventSystem // for filtering log events live
70+
filterSystem *filters.FilterSystem // for filtering database logs
7071

7172
config *params.ChainConfig
7273
}
@@ -95,9 +96,7 @@ func SimulateWalletAddressAndSignFn() (common.Address, func(account accounts.Acc
9596

9697
// XDC simulated backend for testing purpose.
9798
func NewXDCSimulatedBackend(alloc core.GenesisAlloc, gasLimit uint64, chainConfig *params.ChainConfig) *SimulatedBackend {
98-
// database := ethdb.NewMemDatabase()
9999
database := rawdb.NewMemoryDatabase()
100-
101100
genesis := core.Genesis{
102101
GasLimit: gasLimit, // need this big, support initial smart contract
103102
Config: chainConfig,
@@ -128,7 +127,11 @@ func NewXDCSimulatedBackend(alloc core.GenesisAlloc, gasLimit uint64, chainConfi
128127
blockchain: blockchain,
129128
config: genesis.Config,
130129
}
131-
backend.events = filters.NewEventSystem(&filterBackend{database, blockchain, backend}, false)
130+
131+
filterBackend := &filterBackend{database, blockchain, backend}
132+
backend.filterSystem = filters.NewFilterSystem(filterBackend, filters.Config{})
133+
backend.events = filters.NewEventSystem(backend.filterSystem, false)
134+
132135
blockchain.Client = backend
133136
backend.rollback()
134137
return backend
@@ -148,7 +151,11 @@ func NewSimulatedBackend(alloc core.GenesisAlloc) *SimulatedBackend {
148151
blockchain: blockchain,
149152
config: genesis.Config,
150153
}
151-
backend.events = filters.NewEventSystem(&filterBackend{database, blockchain, backend}, false)
154+
155+
filterBackend := &filterBackend{database, blockchain, backend}
156+
backend.filterSystem = filters.NewFilterSystem(filterBackend, filters.Config{})
157+
backend.events = filters.NewEventSystem(backend.filterSystem, false)
158+
152159
backend.rollback()
153160
return backend
154161
}
@@ -423,7 +430,7 @@ func (b *SimulatedBackend) FilterLogs(ctx context.Context, query XDPoSChain.Filt
423430
var filter *filters.Filter
424431
if query.BlockHash != nil {
425432
// Block filter requested, construct a single-shot filter
426-
filter = filters.NewBlockFilter(&filterBackend{b.database, b.blockchain, b}, *query.BlockHash, query.Addresses, query.Topics)
433+
filter = b.filterSystem.NewBlockFilter(*query.BlockHash, query.Addresses, query.Topics)
427434
} else {
428435
// Initialize unset filter boundaried to run from genesis to chain head
429436
from := int64(0)
@@ -435,7 +442,7 @@ func (b *SimulatedBackend) FilterLogs(ctx context.Context, query XDPoSChain.Filt
435442
to = query.ToBlock.Int64()
436443
}
437444
// Construct the range filter
438-
filter = filters.NewRangeFilter(&filterBackend{b.database, b.blockchain, b}, from, to, query.Addresses, query.Topics)
445+
filter = b.filterSystem.NewRangeFilter(from, to, query.Addresses, query.Topics)
439446
}
440447
// Run the filter and return all the logs
441448
logs, err := filter.Logs(ctx)
@@ -552,15 +559,8 @@ func (fb *filterBackend) PendingBlockAndReceipts() (*types.Block, types.Receipts
552559
return fb.backend.pendingBlock, fb.backend.pendingReceipts
553560
}
554561

555-
func (fb *filterBackend) GetLogs(ctx context.Context, hash common.Hash) ([][]*types.Log, error) {
556-
receipts := core.GetBlockReceipts(fb.db, hash, core.GetBlockNumber(fb.db, hash))
557-
if receipts == nil {
558-
return nil, nil
559-
}
560-
logs := make([][]*types.Log, len(receipts))
561-
for i, receipt := range receipts {
562-
logs[i] = receipt.Logs
563-
}
562+
func (fb *filterBackend) GetLogs(ctx context.Context, hash common.Hash, number uint64) ([][]*types.Log, error) {
563+
logs := rawdb.ReadLogs(fb.db, hash, number)
564564
return logs, nil
565565
}
566566

cmd/XDC/main.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,7 @@ var (
9393
utils.CacheDatabaseFlag,
9494
//utils.CacheGCFlag,
9595
//utils.TrieCacheGenFlag,
96+
utils.CacheLogSizeFlag,
9697
utils.FDLimitFlag,
9798
utils.ListenPortFlag,
9899
utils.MaxPeersFlag,

cmd/utils/flags.go

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,8 +42,10 @@ import (
4242
"github.com/XinFinOrg/XDPoSChain/crypto"
4343
"github.com/XinFinOrg/XDPoSChain/eth/downloader"
4444
"github.com/XinFinOrg/XDPoSChain/eth/ethconfig"
45+
"github.com/XinFinOrg/XDPoSChain/eth/filters"
4546
"github.com/XinFinOrg/XDPoSChain/eth/gasprice"
4647
"github.com/XinFinOrg/XDPoSChain/ethdb"
48+
"github.com/XinFinOrg/XDPoSChain/internal/ethapi"
4749
"github.com/XinFinOrg/XDPoSChain/log"
4850
"github.com/XinFinOrg/XDPoSChain/metrics"
4951
"github.com/XinFinOrg/XDPoSChain/metrics/exp"
@@ -54,6 +56,7 @@ import (
5456
"github.com/XinFinOrg/XDPoSChain/p2p/nat"
5557
"github.com/XinFinOrg/XDPoSChain/p2p/netutil"
5658
"github.com/XinFinOrg/XDPoSChain/params"
59+
"github.com/XinFinOrg/XDPoSChain/rpc"
5760
whisper "github.com/XinFinOrg/XDPoSChain/whisper/whisperv6"
5861
gopsutil "github.com/shirou/gopsutil/mem"
5962
"gopkg.in/urfave/cli.v1"
@@ -316,6 +319,11 @@ var (
316319
Usage: "Percentage of cache memory allowance to use for trie pruning",
317320
Value: 25,
318321
}
322+
CacheLogSizeFlag = &cli.IntFlag{
323+
Name: "cache.blocklogs",
324+
Usage: "Size (in number of blocks) of the log cache for filtering",
325+
Value: ethconfig.Defaults.FilterLogCacheSize,
326+
}
319327
FDLimitFlag = cli.IntFlag{
320328
Name: "fdlimit",
321329
Usage: "Raise the open file descriptor resource limit (default = system fd limit)",
@@ -1244,6 +1252,9 @@ func SetEthConfig(ctx *cli.Context, stack *node.Node, cfg *ethconfig.Config) {
12441252
if ctx.GlobalIsSet(GasPriceFlag.Name) {
12451253
cfg.GasPrice = GlobalBig(ctx, GasPriceFlag.Name)
12461254
}
1255+
if ctx.IsSet(CacheLogSizeFlag.Name) {
1256+
cfg.FilterLogCacheSize = ctx.Int(CacheLogSizeFlag.Name)
1257+
}
12471258
if ctx.GlobalIsSet(VMEnableDebugFlag.Name) {
12481259
// TODO(fjl): force-enable this in --dev mode
12491260
cfg.EnablePreimageRecording = ctx.GlobalBool(VMEnableDebugFlag.Name)
@@ -1443,6 +1454,19 @@ func WalkMatch(root, pattern string) ([]string, error) {
14431454
return matches, nil
14441455
}
14451456

1457+
// RegisterFilterAPI adds the eth log filtering RPC API to the node.
1458+
func RegisterFilterAPI(stack *node.Node, backend ethapi.Backend, ethcfg *ethconfig.Config) *filters.FilterSystem {
1459+
isLightClient := ethcfg.SyncMode == downloader.LightSync
1460+
filterSystem := filters.NewFilterSystem(backend, filters.Config{
1461+
LogCacheSize: ethcfg.FilterLogCacheSize,
1462+
})
1463+
stack.RegisterAPIs([]rpc.API{{
1464+
Namespace: "eth",
1465+
Service: filters.NewFilterAPI(filterSystem, isLightClient),
1466+
}})
1467+
return filterSystem
1468+
}
1469+
14461470
func SetupMetrics(ctx *cli.Context) {
14471471
if metrics.Enabled {
14481472
log.Info("Enabling metrics collection")

cmd/utils/utils.go

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,8 +47,7 @@ func RegisterShhService(stack *node.Node, cfg *whisper.Config) {
4747
}
4848
}
4949

50-
// RegisterEthStatsService configures the Ethereum Stats daemon and adds it to
51-
// th egiven node.
50+
// RegisterEthStatsService configures the Ethereum Stats daemon and adds it to the node.
5251
func RegisterEthStatsService(stack *node.Node, url string) {
5352
if err := stack.Register(func(ctx *node.ServiceContext) (node.Service, error) {
5453
// Retrieve both eth and les services

core/chain_makers.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,15 @@ func (b *BlockGen) AddTxWithChain(bc *BlockChain, tx *types.Transaction) {
113113
}
114114
}
115115

116+
// AddUncheckedTx forcefully adds a transaction to the block without any
117+
// validation.
118+
//
119+
// AddUncheckedTx will cause consensus failures when used during real
120+
// chain processing. This is best used in conjunction with raw block insertion.
121+
func (b *BlockGen) AddUncheckedTx(tx *types.Transaction) {
122+
b.txs = append(b.txs, tx)
123+
}
124+
116125
// Number returns the block number of the block being generated.
117126
func (b *BlockGen) Number() *big.Int {
118127
return new(big.Int).Set(b.header.Number)

eth/api_backend.go

Lines changed: 2 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -233,17 +233,8 @@ func (b *EthApiBackend) GetReceipts(ctx context.Context, blockHash common.Hash)
233233
return core.GetBlockReceipts(b.eth.chainDb, blockHash, core.GetBlockNumber(b.eth.chainDb, blockHash)), nil
234234
}
235235

236-
func (b *EthApiBackend) GetLogs(ctx context.Context, blockHash common.Hash) ([][]*types.Log, error) {
237-
db := b.eth.ChainDb()
238-
number := rawdb.ReadHeaderNumber(db, blockHash)
239-
if number == nil {
240-
return nil, errors.New("failed to get block number from hash")
241-
}
242-
logs := rawdb.ReadLogs(db, blockHash, *number)
243-
if logs == nil {
244-
return nil, errors.New("failed to get logs for block")
245-
}
246-
return logs, nil
236+
func (b *EthApiBackend) GetLogs(ctx context.Context, hash common.Hash, number uint64) ([][]*types.Log, error) {
237+
return rawdb.ReadLogs(b.eth.chainDb, hash, number), nil
247238
}
248239

249240
func (b *EthApiBackend) GetTd(blockHash common.Hash) *big.Int {

eth/backend.go

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,6 @@ import (
2424
"runtime"
2525
"sync"
2626
"sync/atomic"
27-
"time"
2827

2928
"github.com/XinFinOrg/XDPoSChain/XDCx"
3029
"github.com/XinFinOrg/XDPoSChain/XDCxlending"
@@ -406,7 +405,7 @@ func (s *Ethereum) APIs() []rpc.API {
406405
}, {
407406
Namespace: "eth",
408407
Version: "1.0",
409-
Service: filters.NewFilterAPI(s.ApiBackend, false, 5*time.Minute),
408+
Service: filters.NewFilterAPI(filters.NewFilterSystem(s.ApiBackend, filters.Config{LogCacheSize: s.config.FilterLogCacheSize}), false),
410409
Public: true,
411410
}, {
412411
Namespace: "admin",

eth/ethconfig/config.go

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -60,12 +60,13 @@ var Defaults = Config{
6060
DatasetsInMem: 1,
6161
DatasetsOnDisk: 2,
6262
},
63-
NetworkId: 88,
64-
LightPeers: 100,
65-
DatabaseCache: 768,
66-
TrieCache: 256,
67-
TrieTimeout: 5 * time.Minute,
68-
GasPrice: big.NewInt(0.25 * params.Shannon),
63+
NetworkId: 88,
64+
LightPeers: 100,
65+
DatabaseCache: 768,
66+
TrieCache: 256,
67+
TrieTimeout: 5 * time.Minute,
68+
FilterLogCacheSize: 32,
69+
GasPrice: big.NewInt(0.25 * params.Shannon),
6970

7071
TxPool: core.DefaultTxPoolConfig,
7172
RPCGasCap: 25000000,
@@ -111,6 +112,9 @@ type Config struct {
111112
TrieCache int
112113
TrieTimeout time.Duration
113114

115+
// This is the number of blocks for which logs will be cached in the filter system.
116+
FilterLogCacheSize int
117+
114118
// Mining-related options
115119
Etherbase common.Address `toml:",omitempty"`
116120
MinerThreads int `toml:",omitempty"`

eth/ethconfig/gen_config.go

Lines changed: 6 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

eth/filters/api.go

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@ import (
3030
"github.com/XinFinOrg/XDPoSChain/common/hexutil"
3131
"github.com/XinFinOrg/XDPoSChain/core/types"
3232
"github.com/XinFinOrg/XDPoSChain/ethdb"
33+
34+
// "github.com/XinFinOrg/XDPoSChain/ethdb"
3335
"github.com/XinFinOrg/XDPoSChain/rpc"
3436
)
3537

@@ -54,7 +56,7 @@ type filter struct {
5456
// FilterAPI offers support to create and manage filters. This will allow external clients to retrieve various
5557
// information related to the Ethereum protocol such als blocks, transactions and logs.
5658
type FilterAPI struct {
57-
backend Backend
59+
sys *FilterSystem
5860
chainDb ethdb.Database
5961
events *EventSystem
6062
filtersMu sync.Mutex
@@ -63,15 +65,15 @@ type FilterAPI struct {
6365
}
6466

6567
// NewFilterAPI returns a new FilterAPI instance.
66-
func NewFilterAPI(backend Backend, lightMode bool, timeout time.Duration) *FilterAPI {
68+
func NewFilterAPI(system *FilterSystem, lightMode bool) *FilterAPI {
6769
api := &FilterAPI{
68-
backend: backend,
69-
chainDb: backend.ChainDb(),
70-
events: NewEventSystem(backend, lightMode),
70+
sys: system,
71+
chainDb: system.backend.ChainDb(),
72+
events: NewEventSystem(system, lightMode),
7173
filters: make(map[rpc.ID]*filter),
72-
timeout: timeout,
74+
timeout: system.cfg.Timeout,
7375
}
74-
go api.timeoutLoop(timeout)
76+
go api.timeoutLoop(system.cfg.Timeout)
7577

7678
return api
7779
}
@@ -341,7 +343,7 @@ func (api *FilterAPI) GetLogs(ctx context.Context, crit FilterCriteria) ([]*type
341343
var filter *Filter
342344
if crit.BlockHash != nil {
343345
// Block filter requested, construct a single-shot filter
344-
filter = NewBlockFilter(api.backend, *crit.BlockHash, crit.Addresses, crit.Topics)
346+
filter = api.sys.NewBlockFilter(*crit.BlockHash, crit.Addresses, crit.Topics)
345347
} else {
346348
// Convert the RPC block numbers into internal representations
347349
begin := rpc.LatestBlockNumber.Int64()
@@ -353,7 +355,7 @@ func (api *FilterAPI) GetLogs(ctx context.Context, crit FilterCriteria) ([]*type
353355
end = crit.ToBlock.Int64()
354356
}
355357
// Construct the range filter
356-
filter = NewRangeFilter(api.backend, begin, end, crit.Addresses, crit.Topics)
358+
filter = api.sys.NewRangeFilter(begin, end, crit.Addresses, crit.Topics)
357359
}
358360
// Run the filter and return all the logs
359361
logs, err := filter.Logs(ctx)
@@ -396,7 +398,7 @@ func (api *FilterAPI) GetFilterLogs(ctx context.Context, id rpc.ID) ([]*types.Lo
396398
var filter *Filter
397399
if f.crit.BlockHash != nil {
398400
// Block filter requested, construct a single-shot filter
399-
filter = NewBlockFilter(api.backend, *f.crit.BlockHash, f.crit.Addresses, f.crit.Topics)
401+
filter = api.sys.NewBlockFilter(*f.crit.BlockHash, f.crit.Addresses, f.crit.Topics)
400402
} else {
401403
// Convert the RPC block numbers into internal representations
402404
begin := rpc.LatestBlockNumber.Int64()
@@ -408,7 +410,7 @@ func (api *FilterAPI) GetFilterLogs(ctx context.Context, id rpc.ID) ([]*types.Lo
408410
end = f.crit.ToBlock.Int64()
409411
}
410412
// Construct the range filter
411-
filter = NewRangeFilter(api.backend, begin, end, f.crit.Addresses, f.crit.Topics)
413+
filter = api.sys.NewRangeFilter(begin, end, f.crit.Addresses, f.crit.Topics)
412414
}
413415
// Run the filter and return all the logs
414416
logs, err := filter.Logs(ctx)

0 commit comments

Comments
 (0)