Skip to content

Commit 7c06cc1

Browse files
authored
Cache the deployment flags to improve startup (#340)
* Cache the deployment flags to improve startup - The deployment flags are cached when calculated as new blocks come in. - The deployment flags are read from cache at startup, as they cannot have changed since shutdown. - This gives a very big improvement on node startup. - #337 * Add empty constructor - Needed for tests. * Add null check for integration tests * Move persisting of flags to BaseFeature - Check the flags every minute and persist if needed. - This only validates ScriptFlags, not BIP30/BIP34/LockTimeFlags.
1 parent 162062d commit 7c06cc1

4 files changed

Lines changed: 42 additions & 4 deletions

File tree

src/Blockcore/Base/BaseFeature.cs

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,10 @@ public sealed class BaseFeature : FullNodeFeature
129129
/// <inheritdoc cref="IPartialValidator"/>
130130
private readonly IPartialValidator partialValidator;
131131

132+
private readonly NodeDeployments nodeDeployments;
133+
134+
private DeploymentFlags deploymentFlags;
135+
132136
public BaseFeature(NodeSettings nodeSettings,
133137
DataFolder dataFolder,
134138
INodeLifetime nodeLifetime,
@@ -151,6 +155,7 @@ public BaseFeature(NodeSettings nodeSettings,
151155
IBlockStore blockStore,
152156
Network network,
153157
ITipsManager tipsManager,
158+
NodeDeployments nodeDeployments,
154159
IKeyValueRepository keyValueRepo,
155160
INodeStats nodeStats,
156161
IBroadcasterManager broadcasterManager,
@@ -176,6 +181,7 @@ public BaseFeature(NodeSettings nodeSettings,
176181
this.peerBanning = Guard.NotNull(peerBanning, nameof(peerBanning));
177182
this.tipsManager = Guard.NotNull(tipsManager, nameof(tipsManager));
178183
this.keyValueRepo = Guard.NotNull(keyValueRepo, nameof(keyValueRepo));
184+
this.nodeDeployments = nodeDeployments;
179185

180186
this.peerAddressManager = Guard.NotNull(peerAddressManager, nameof(peerAddressManager));
181187
this.peerAddressManager.PeerFilePath = this.dataFolder;
@@ -278,7 +284,21 @@ private async Task StartChainAsync()
278284
await this.chainRepository.SaveAsync(this.chainIndexer).ConfigureAwait(false);
279285

280286
if (this.provenBlockHeaderStore != null)
287+
{
281288
await this.provenBlockHeaderStore.SaveAsync().ConfigureAwait(false);
289+
}
290+
291+
// Get latest flags (often cached) and persist.
292+
var flags = this.nodeDeployments.GetFlags(this.consensusManager.Tip);
293+
294+
if (this.deploymentFlags == null || flags.ScriptFlags != this.deploymentFlags.ScriptFlags)
295+
{
296+
// Update the persistent disk cache of Flags when we retrieve it.
297+
this.keyValueRepo.SaveValueJson("deploymentflags", flags);
298+
299+
// Update the local cached copy used to validate against. We don't want to persist to disk unless the flags actually has changed.
300+
this.deploymentFlags = flags;
301+
}
282302
},
283303
this.nodeLifetime.ApplicationStopping,
284304
repeatEvery: TimeSpan.FromMinutes(1.0),

src/Features/Blockcore.Features.Consensus/ConsensusFeature.cs

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
using Blockcore.Networks;
1212
using Blockcore.P2P.Protocol.Payloads;
1313
using Blockcore.Signals;
14+
using Blockcore.Utilities.Store;
1415
using NBitcoin;
1516

1617
[assembly: InternalsVisibleTo("Blockcore.Features.Miner.Tests")]
@@ -30,27 +31,39 @@ public class ConsensusFeature : FullNodeFeature
3031

3132
private readonly NodeDeployments nodeDeployments;
3233

34+
private readonly IKeyValueRepository keyValueRepository;
35+
3336
public ConsensusFeature(
3437
Network network,
3538
IChainState chainState,
3639
IConnectionManager connectionManager,
3740
ISignals signals,
3841
IConsensusManager consensusManager,
39-
NodeDeployments nodeDeployments)
42+
NodeDeployments nodeDeployments,
43+
IKeyValueRepository keyValueRepository)
4044
{
4145
this.chainState = chainState;
4246
this.connectionManager = connectionManager;
4347
this.signals = signals;
4448
this.consensusManager = consensusManager;
4549
this.nodeDeployments = nodeDeployments;
50+
this.keyValueRepository = keyValueRepository;
4651

4752
this.chainState.MaxReorgLength = network.Consensus.MaxReorgLength;
4853
}
4954

5055
/// <inheritdoc />
5156
public override Task InitializeAsync()
5257
{
53-
DeploymentFlags flags = this.nodeDeployments.GetFlags(this.consensusManager.Tip);
58+
DeploymentFlags flags = this.keyValueRepository.LoadValueJson<DeploymentFlags>("deploymentflags");
59+
60+
if (flags == null)
61+
{
62+
flags = this.nodeDeployments.GetFlags(this.consensusManager.Tip);
63+
64+
// Update the cache of Flags when we retrieve it.
65+
this.keyValueRepository.SaveValueJson("deploymentflags", flags);
66+
}
5467

5568
if (flags.ScriptFlags.HasFlag(ScriptVerify.Witness))
5669
{

src/Features/Blockcore.Features.Consensus/PosConsensusFeature.cs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
using Blockcore.Networks;
1616
using Blockcore.P2P.Peer;
1717
using Blockcore.Signals;
18+
using Blockcore.Utilities.Store;
1819
using Microsoft.Extensions.Logging;
1920
using NBitcoin;
2021

@@ -51,7 +52,9 @@ public PosConsensusFeature(
5152
ILoggerFactory loggerFactory,
5253
ICheckpoints checkpoints,
5354
IProvenBlockHeaderStore provenBlockHeaderStore,
54-
ConnectionManagerSettings connectionManagerSettings) : base(network, chainState, connectionManager, signals, consensusManager, nodeDeployments)
55+
ConnectionManagerSettings connectionManagerSettings,
56+
IKeyValueRepository keyValueRepository
57+
) : base(network, chainState, connectionManager, signals, consensusManager, nodeDeployments, keyValueRepository)
5558
{
5659
this.network = network;
5760
this.chainState = chainState;

src/Features/Blockcore.Features.Consensus/PowConsensusFeature.cs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
using Blockcore.Interfaces;
1010
using Blockcore.Networks;
1111
using Blockcore.Signals;
12+
using Blockcore.Utilities.Store;
1213
using Microsoft.Extensions.Logging;
1314
using NBitcoin;
1415

@@ -38,7 +39,8 @@ public PowConsensusFeature(
3839
IInitialBlockDownloadState initialBlockDownloadState,
3940
IPeerBanning peerBanning,
4041
ISignals signals,
41-
ILoggerFactory loggerFactory) : base(network, chainState, connectionManager, signals, consensusManager, nodeDeployments)
42+
ILoggerFactory loggerFactory,
43+
IKeyValueRepository keyValueRepository) : base(network, chainState, connectionManager, signals, consensusManager, nodeDeployments, keyValueRepository)
4244
{
4345
this.chainState = chainState;
4446
this.connectionManager = connectionManager;

0 commit comments

Comments
 (0)