Skip to content

Commit c0c8422

Browse files
authored
Add block header store (#88)
* Add block header store * Fix consensus puller bug assertion * Optimize chain work field as byte array insted of BigInteger * Store proven header in a new field * Fixing tests * Better for POS increse cache count ahead
1 parent 72aa513 commit c0c8422

29 files changed

Lines changed: 351 additions & 135 deletions

File tree

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -263,4 +263,5 @@ src/.idea/.idea.Stratis.Bitcoin.FullNode/.idea/
263263
.DS_Store
264264

265265
*.iml
266+
/src/.idea
266267
/src/Blockcore.Benchmark/BenchmarkDotNet.Artifacts/results

src/Blockcore.Features.BlockStore/BlockStoreBehavior.cs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -357,7 +357,7 @@ public async Task AnnounceBlocksAsync(List<ChainedHeader> blocksToAnnounce)
357357

358358
this.logger.LogDebug("Block propagation preferences of the peer '{0}': prefer headers - {1}, prefer headers and IDs - {2}, will{3} revert to 'inv' now.", peer.RemoteSocketEndpoint, this.PreferHeaders, this.preferHeaderAndIDs, revertToInv ? "" : " NOT");
359359

360-
var headers = new List<BlockHeader>();
360+
var headers = new List<ChainedHeader>();
361361
var inventoryBlockToSend = new List<ChainedHeader>();
362362

363363
try
@@ -373,7 +373,7 @@ public async Task AnnounceBlocksAsync(List<ChainedHeader> blocksToAnnounce)
373373
// We expect peer to answer with getheaders message.
374374
if (bestSentHeader == null)
375375
{
376-
await peer.SendMessageAsync(this.BuildHeadersAnnouncePayload(new[] { blocksToAnnounce.Last().Header })).ConfigureAwait(false);
376+
await peer.SendMessageAsync(this.BuildHeadersAnnouncePayload(new[] { blocksToAnnounce.Last() })).ConfigureAwait(false);
377377

378378
this.logger.LogTrace("(-)[SENT_SINGLE_HEADER]");
379379
return;
@@ -409,7 +409,7 @@ public async Task AnnounceBlocksAsync(List<ChainedHeader> blocksToAnnounce)
409409
}
410410

411411
// If we reached here then it means that we've found starting header.
412-
headers.Add(chainedHeader.Header);
412+
headers.Add(chainedHeader);
413413
}
414414
}
415415

@@ -480,9 +480,9 @@ public async Task AnnounceBlocksAsync(List<ChainedHeader> blocksToAnnounce)
480480
/// <returns>
481481
/// The <see cref="HeadersPayload" /> instance to announce to the peer.
482482
/// </returns>
483-
protected virtual Payload BuildHeadersAnnouncePayload(IEnumerable<BlockHeader> headers)
483+
protected virtual Payload BuildHeadersAnnouncePayload(IEnumerable<ChainedHeader> headers)
484484
{
485-
return new HeadersPayload(headers);
485+
return new HeadersPayload(headers.Select(b => b.Header));
486486
}
487487

488488
public override object Clone()

src/Blockcore.Features.BlockStore/Controllers/BlockStoreController.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,7 @@ public IActionResult GetBlock([FromQuery] SearchByHashRequest query)
129129
var posBlock = block as PosBlock;
130130

131131
blockModel.PosBlockSignature = posBlock.BlockSignature.ToHex(this.network);
132-
blockModel.PosBlockTrust = new Target(chainedHeader.GetBlockProof()).ToUInt256().ToString();
132+
blockModel.PosBlockTrust = new Target(chainedHeader.GetBlockTarget()).ToUInt256().ToString();
133133
blockModel.PosChainTrust = chainedHeader.ChainWork.ToString(); // this should be similar to ChainWork
134134
}
135135

src/Blockcore.Features.BlockStore/ProvenHeadersBlockStoreBehavior.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,13 +25,13 @@ public ProvenHeadersBlockStoreBehavior(Network network, ChainIndexer chainIndexe
2525

2626
/// <inheritdoc />
2727
/// <returns>The <see cref="HeadersPayload"/> instance to announce to the peer, or <see cref="ProvenHeadersPayload"/> if the peers requires it.</returns>
28-
protected override Payload BuildHeadersAnnouncePayload(IEnumerable<BlockHeader> headers)
28+
protected override Payload BuildHeadersAnnouncePayload(IEnumerable<ChainedHeader> headers)
2929
{
3030
// Sanity check. That should never happen.
31-
if (!headers.All(x => x is ProvenBlockHeader))
31+
if (!headers.All(x => x.ProvenBlockHeader != null))
3232
throw new BlockStoreException("UnexpectedError: BlockHeader is expected to be a ProvenBlockHeader");
3333

34-
var provenHeadersPayload = new ProvenHeadersPayload(headers.Cast<ProvenBlockHeader>().ToArray());
34+
var provenHeadersPayload = new ProvenHeadersPayload(headers.Select(s => s.ProvenBlockHeader).ToArray());
3535

3636
return provenHeadersPayload;
3737
}

src/Blockcore.Features.BlockStore/ProvenHeadersBlockStoreSignaled.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,13 +44,13 @@ protected override void AddBlockToQueue(ChainedHeaderBlock blockPair, bool isIBD
4444
{
4545
int blockHeight = blockPair.ChainedHeader.Height;
4646

47-
if (blockPair.ChainedHeader.Header is ProvenBlockHeader phHeader)
47+
if (blockPair.ChainedHeader.ProvenBlockHeader != null)
4848
{
4949
this.logger.LogDebug("Current header is already a Proven Header.");
5050

5151
// Add to the store, to be sure we actually store it anyway.
5252
// It's ProvenBlockHeaderStore responsibility to prevent us to store it twice.
53-
this.provenBlockHeaderStore.AddToPendingBatch(phHeader, new HashHeightPair(phHeader.GetHash(), blockHeight));
53+
this.provenBlockHeaderStore.AddToPendingBatch(blockPair.ChainedHeader.ProvenBlockHeader, new HashHeightPair(blockPair.ChainedHeader.HashBlock, blockHeight));
5454
}
5555
else
5656
{

src/Blockcore.Features.Consensus.Tests/InitialBlockDownloadTest.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ public InitialBlockDownloadTest()
3434
public void InIBDIfBehindCheckpoint()
3535
{
3636
BlockHeader blockHeader = this.network.Consensus.ConsensusFactory.CreateBlockHeader();
37-
this.chainState.ConsensusTip = new ChainedHeader(blockHeader, uint256.Zero, 1000);
37+
this.chainState.ConsensusTip = new ChainedHeader(blockHeader, blockHeader.GetHash(), 1000);
3838
var blockDownloadState = new InitialBlockDownloadState(this.chainState, this.network, this.consensusSettings, this.checkpoints, this.loggerFactory.Object, DateTimeProvider.Default);
3939
Assert.True(blockDownloadState.IsInitialBlockDownload());
4040
}
@@ -43,7 +43,7 @@ public void InIBDIfBehindCheckpoint()
4343
public void InIBDIfChainWorkIsLessThanMinimum()
4444
{
4545
BlockHeader blockHeader = this.network.Consensus.ConsensusFactory.CreateBlockHeader();
46-
this.chainState.ConsensusTip = new ChainedHeader(blockHeader, uint256.Zero, this.checkpoints.GetLastCheckpointHeight() + 1);
46+
this.chainState.ConsensusTip = new ChainedHeader(blockHeader, blockHeader.GetHash(), this.checkpoints.GetLastCheckpointHeight() + 1);
4747
var blockDownloadState = new InitialBlockDownloadState(this.chainState, this.network, this.consensusSettings, this.checkpoints, this.loggerFactory.Object, DateTimeProvider.Default);
4848
Assert.True(blockDownloadState.IsInitialBlockDownload());
4949
}
@@ -59,7 +59,7 @@ public void InIBDIfTipIsOlderThanMaxAge()
5959
// Block has a time sufficiently in the past that it can't be the tip.
6060
blockHeader.Time = ((uint) DateTimeOffset.Now.ToUnixTimeSeconds()) - (uint) this.network.MaxTipAge - 1;
6161

62-
this.chainState.ConsensusTip = new ChainedHeader(blockHeader, uint256.Zero, this.checkpoints.GetLastCheckpointHeight() + 1);
62+
this.chainState.ConsensusTip = new ChainedHeader(blockHeader, blockHeader.GetHash(), this.checkpoints.GetLastCheckpointHeight() + 1);
6363
var blockDownloadState = new InitialBlockDownloadState(this.chainState, this.network, this.consensusSettings, this.checkpoints, this.loggerFactory.Object, DateTimeProvider.Default);
6464
Assert.True(blockDownloadState.IsInitialBlockDownload());
6565
}

src/Blockcore.Features.Consensus.Tests/Rules/CommonRules/PowCoinViewRuleTests.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ private void AndARuleContext()
7979
this.ruleContext = new PowRuleContext { };
8080
this.ruleContext.ValidationContext = new ValidationContext();
8181
BlockHeader blockHeader = this.network.Consensus.ConsensusFactory.CreateBlockHeader();
82-
this.ruleContext.ValidationContext.ChainedHeaderToValidate = new ChainedHeader(blockHeader, new uint256("bcd7d5de8d3bcc7b15e7c8e5fe77c0227cdfa6c682ca13dcf4910616f10fdd06"), HeightOfBlockchain);
82+
this.ruleContext.ValidationContext.ChainedHeaderToValidate = new ChainedHeader(blockHeader, blockHeader.GetHash(), HeightOfBlockchain);
8383

8484
Block block = this.network.CreateBlock();
8585
block.Transactions = new List<Transaction>();

src/Blockcore.Features.Consensus.Tests/StakeValidatorTests.cs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1196,7 +1196,7 @@ public void GetTargetDepthRequired_Testnet_HeightBelowMinConfirmationHeight_Uses
11961196

11971197
var height = PosConsensusOptions.CoinstakeMinConfirmationActivationHeightTestnet - 2;
11981198
BlockHeader blockHeader = this.Network.Consensus.ConsensusFactory.CreateBlockHeader();
1199-
ChainedHeader header = new ChainedHeader(blockHeader, uint256.One, height);
1199+
ChainedHeader header = new ChainedHeader(blockHeader, blockHeader.GetHash(), height);
12001200

12011201
var depth = this.stakeValidator.GetTargetDepthRequired(header);
12021202

@@ -1211,7 +1211,7 @@ public void GetTargetDepthRequired_Testnet_HeightAtMinConfirmationHeight_UsesCha
12111211

12121212
var height = PosConsensusOptions.CoinstakeMinConfirmationActivationHeightTestnet - 1;
12131213
BlockHeader blockHeader = this.Network.Consensus.ConsensusFactory.CreateBlockHeader();
1214-
ChainedHeader header = new ChainedHeader(blockHeader, uint256.One, height);
1214+
ChainedHeader header = new ChainedHeader(blockHeader, blockHeader.GetHash(), height);
12151215

12161216
var depth = this.stakeValidator.GetTargetDepthRequired(header);
12171217

@@ -1226,7 +1226,7 @@ public void GetTargetDepthRequired_Mainnet_HeightBelowMinConfirmationHeight_Uses
12261226

12271227
var height = PosConsensusOptions.CoinstakeMinConfirmationActivationHeightMainnet - 2;
12281228
BlockHeader blockHeader = this.Network.Consensus.ConsensusFactory.CreateBlockHeader();
1229-
ChainedHeader header = new ChainedHeader(blockHeader, uint256.One, height);
1229+
ChainedHeader header = new ChainedHeader(blockHeader, blockHeader.GetHash(), height);
12301230

12311231
var depth = this.stakeValidator.GetTargetDepthRequired(header);
12321232

@@ -1241,7 +1241,7 @@ public void GetTargetDepthRequired_Mainnet_HeightAtMinConfirmationHeight_UsesCha
12411241

12421242
var height = PosConsensusOptions.CoinstakeMinConfirmationActivationHeightMainnet - 1;
12431243
BlockHeader blockHeader = this.Network.Consensus.ConsensusFactory.CreateBlockHeader();
1244-
ChainedHeader header = new ChainedHeader(blockHeader, uint256.One, height);
1244+
ChainedHeader header = new ChainedHeader(blockHeader, blockHeader.GetHash(), height);
12451245

12461246
var depth = this.stakeValidator.GetTargetDepthRequired(header);
12471247

src/Blockcore.Features.Consensus/Behaviors/ProvenHeadersConsensusManagerBehavior.cs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -167,7 +167,9 @@ protected override Payload ConstructHeadersPayload(GetHeadersPayload getHeadersP
167167

168168
for (int heightIndex = header.Height; heightIndex > fork.Height; heightIndex--)
169169
{
170-
if (!(header.Header is ProvenBlockHeader provenBlockHeader))
170+
ProvenBlockHeader provenBlockHeader = header.ProvenBlockHeader;
171+
172+
if (provenBlockHeader == null)
171173
{
172174
provenBlockHeader = this.provenBlockHeaderStore.GetAsync(header.Height).GetAwaiter().GetResult();
173175

src/Blockcore.Features.Consensus/Rules/ProvenHeaderRules/ProvenHeaderCoinstakeRule.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,7 @@ private UnspentOutput GetAndValidatePreviousUtxo(ProvenBlockHeader header, PosRu
121121

122122
UnspentOutput prevUtxo = null;
123123

124-
FetchCoinsResponse coins = this.PosParent.UtxoSet.FetchCoins(new[] {txIn.PrevOut});
124+
FetchCoinsResponse coins = this.PosParent.UtxoSet.FetchCoins(new[] { txIn.PrevOut });
125125
prevUtxo = coins.UnspentOutputs[txIn.PrevOut];
126126
if (prevUtxo?.Coins == null)
127127
{
@@ -245,7 +245,7 @@ private uint256 GetPreviousStakeModifier(ChainedHeader chainedHeader)
245245
return this.LastCheckpoint.StakeModifierV2;
246246
}
247247

248-
var previousProvenHeader = chainedHeader.Previous.Header as ProvenBlockHeader;
248+
var previousProvenHeader = chainedHeader.Previous.ProvenBlockHeader;
249249
if (previousProvenHeader != null)
250250
{
251251
if (previousProvenHeader.StakeModifierV2 == null)
@@ -390,4 +390,4 @@ private OutPoint GetPreviousOut(ProvenBlockHeader header)
390390
return prevOut;
391391
}
392392
}
393-
}
393+
}

0 commit comments

Comments
 (0)