Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add block header store #88

Merged
merged 7 commits into from
Apr 12, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -263,4 +263,5 @@ src/.idea/.idea.Stratis.Bitcoin.FullNode/.idea/
.DS_Store

*.iml
/src/.idea
/src/Blockcore.Benchmark/BenchmarkDotNet.Artifacts/results
10 changes: 5 additions & 5 deletions src/Blockcore.Features.BlockStore/BlockStoreBehavior.cs
Original file line number Diff line number Diff line change
Expand Up @@ -357,7 +357,7 @@ public async Task AnnounceBlocksAsync(List<ChainedHeader> blocksToAnnounce)

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");

var headers = new List<BlockHeader>();
var headers = new List<ChainedHeader>();
var inventoryBlockToSend = new List<ChainedHeader>();

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

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

// If we reached here then it means that we've found starting header.
headers.Add(chainedHeader.Header);
headers.Add(chainedHeader);
}
}

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

public override object Clone()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@ public IActionResult GetBlock([FromQuery] SearchByHashRequest query)
var posBlock = block as PosBlock;

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

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,13 +25,13 @@ public ProvenHeadersBlockStoreBehavior(Network network, ChainIndexer chainIndexe

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

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

return provenHeadersPayload;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,13 +44,13 @@ protected override void AddBlockToQueue(ChainedHeaderBlock blockPair, bool isIBD
{
int blockHeight = blockPair.ChainedHeader.Height;

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

// Add to the store, to be sure we actually store it anyway.
// It's ProvenBlockHeaderStore responsibility to prevent us to store it twice.
this.provenBlockHeaderStore.AddToPendingBatch(phHeader, new HashHeightPair(phHeader.GetHash(), blockHeight));
this.provenBlockHeaderStore.AddToPendingBatch(blockPair.ChainedHeader.ProvenBlockHeader, new HashHeightPair(blockPair.ChainedHeader.HashBlock, blockHeight));
}
else
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ public InitialBlockDownloadTest()
public void InIBDIfBehindCheckpoint()
{
BlockHeader blockHeader = this.network.Consensus.ConsensusFactory.CreateBlockHeader();
this.chainState.ConsensusTip = new ChainedHeader(blockHeader, uint256.Zero, 1000);
this.chainState.ConsensusTip = new ChainedHeader(blockHeader, blockHeader.GetHash(), 1000);
var blockDownloadState = new InitialBlockDownloadState(this.chainState, this.network, this.consensusSettings, this.checkpoints, this.loggerFactory.Object, DateTimeProvider.Default);
Assert.True(blockDownloadState.IsInitialBlockDownload());
}
Expand All @@ -43,7 +43,7 @@ public void InIBDIfBehindCheckpoint()
public void InIBDIfChainWorkIsLessThanMinimum()
{
BlockHeader blockHeader = this.network.Consensus.ConsensusFactory.CreateBlockHeader();
this.chainState.ConsensusTip = new ChainedHeader(blockHeader, uint256.Zero, this.checkpoints.GetLastCheckpointHeight() + 1);
this.chainState.ConsensusTip = new ChainedHeader(blockHeader, blockHeader.GetHash(), this.checkpoints.GetLastCheckpointHeight() + 1);
var blockDownloadState = new InitialBlockDownloadState(this.chainState, this.network, this.consensusSettings, this.checkpoints, this.loggerFactory.Object, DateTimeProvider.Default);
Assert.True(blockDownloadState.IsInitialBlockDownload());
}
Expand All @@ -59,7 +59,7 @@ public void InIBDIfTipIsOlderThanMaxAge()
// Block has a time sufficiently in the past that it can't be the tip.
blockHeader.Time = ((uint) DateTimeOffset.Now.ToUnixTimeSeconds()) - (uint) this.network.MaxTipAge - 1;

this.chainState.ConsensusTip = new ChainedHeader(blockHeader, uint256.Zero, this.checkpoints.GetLastCheckpointHeight() + 1);
this.chainState.ConsensusTip = new ChainedHeader(blockHeader, blockHeader.GetHash(), this.checkpoints.GetLastCheckpointHeight() + 1);
var blockDownloadState = new InitialBlockDownloadState(this.chainState, this.network, this.consensusSettings, this.checkpoints, this.loggerFactory.Object, DateTimeProvider.Default);
Assert.True(blockDownloadState.IsInitialBlockDownload());
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ private void AndARuleContext()
this.ruleContext = new PowRuleContext { };
this.ruleContext.ValidationContext = new ValidationContext();
BlockHeader blockHeader = this.network.Consensus.ConsensusFactory.CreateBlockHeader();
this.ruleContext.ValidationContext.ChainedHeaderToValidate = new ChainedHeader(blockHeader, new uint256("bcd7d5de8d3bcc7b15e7c8e5fe77c0227cdfa6c682ca13dcf4910616f10fdd06"), HeightOfBlockchain);
this.ruleContext.ValidationContext.ChainedHeaderToValidate = new ChainedHeader(blockHeader, blockHeader.GetHash(), HeightOfBlockchain);

Block block = this.network.CreateBlock();
block.Transactions = new List<Transaction>();
Expand Down
8 changes: 4 additions & 4 deletions src/Blockcore.Features.Consensus.Tests/StakeValidatorTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1196,7 +1196,7 @@ public void GetTargetDepthRequired_Testnet_HeightBelowMinConfirmationHeight_Uses

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

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

Expand All @@ -1211,7 +1211,7 @@ public void GetTargetDepthRequired_Testnet_HeightAtMinConfirmationHeight_UsesCha

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

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

Expand All @@ -1226,7 +1226,7 @@ public void GetTargetDepthRequired_Mainnet_HeightBelowMinConfirmationHeight_Uses

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

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

Expand All @@ -1241,7 +1241,7 @@ public void GetTargetDepthRequired_Mainnet_HeightAtMinConfirmationHeight_UsesCha

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

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

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,9 @@ protected override Payload ConstructHeadersPayload(GetHeadersPayload getHeadersP

for (int heightIndex = header.Height; heightIndex > fork.Height; heightIndex--)
{
if (!(header.Header is ProvenBlockHeader provenBlockHeader))
ProvenBlockHeader provenBlockHeader = header.ProvenBlockHeader;

if (provenBlockHeader == null)
{
provenBlockHeader = this.provenBlockHeaderStore.GetAsync(header.Height).GetAwaiter().GetResult();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ private UnspentOutput GetAndValidatePreviousUtxo(ProvenBlockHeader header, PosRu

UnspentOutput prevUtxo = null;

FetchCoinsResponse coins = this.PosParent.UtxoSet.FetchCoins(new[] {txIn.PrevOut});
FetchCoinsResponse coins = this.PosParent.UtxoSet.FetchCoins(new[] { txIn.PrevOut });
prevUtxo = coins.UnspentOutputs[txIn.PrevOut];
if (prevUtxo?.Coins == null)
{
Expand Down Expand Up @@ -245,7 +245,7 @@ private uint256 GetPreviousStakeModifier(ChainedHeader chainedHeader)
return this.LastCheckpoint.StakeModifierV2;
}

var previousProvenHeader = chainedHeader.Previous.Header as ProvenBlockHeader;
var previousProvenHeader = chainedHeader.Previous.ProvenBlockHeader;
if (previousProvenHeader != null)
{
if (previousProvenHeader.StakeModifierV2 == null)
Expand Down Expand Up @@ -390,4 +390,4 @@ private OutPoint GetPreviousOut(ProvenBlockHeader header)
return prevOut;
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ public abstract class ProvenHeaderRuleBase : HeaderValidationConsensusRule
{
/// <summary>Allow access to the POS parent.</summary>
protected PosConsensusRuleEngine PosParent;

protected int LastCheckpointHeight;
protected CheckpointInfo LastCheckpoint;

Expand Down Expand Up @@ -43,16 +44,6 @@ public bool IsProvenHeaderActivated(int height)
return height > this.LastCheckpointHeight;
}

/// <summary>
/// Determines whether header is a proven header.
/// </summary>
/// <param name="header">The block header.</param>
/// <returns><c>true</c> if header is a <see cref="ProvenBlockHeader"/>.</returns>
public bool IsProvenHeader(BlockHeader header)
{
return header is ProvenBlockHeader;
}

/// <inheritdoc/>
public override void Run(RuleContext context)
{
Expand All @@ -72,15 +63,15 @@ public override void Run(RuleContext context)
return;
}

if (!this.IsProvenHeader(chainedHeader.Header))
if (chainedHeader.ProvenBlockHeader == null)
{
// We skip validation if the header is a regular header
// This is to allow white-listed peers to sync using regular headers.
this.Logger.LogTrace("(-)[NOT_A_PROVEN_HEADER]");
return;
}

this.ProcessRule((PosRuleContext)context, chainedHeader, (ProvenBlockHeader)chainedHeader.Header);
this.ProcessRule((PosRuleContext)context, chainedHeader, chainedHeader.ProvenBlockHeader);
}

/// <summary>
Expand All @@ -91,4 +82,4 @@ public override void Run(RuleContext context)
/// <param name="header">The Proven Header to be validated.</param>
protected abstract void ProcessRule(PosRuleContext context, ChainedHeader chainedHeader, ProvenBlockHeader header);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,8 @@ public MiningControllerTest()
public void Generate_With_Incorrect_Block_Count_ReturnsInvalidRequest(int? blockCount)
{
var consensusManager = new Mock<IConsensusManager>();
consensusManager.Setup(cm => cm.Tip).Returns(new ChainedHeader(this.network.Consensus.ConsensusFactory.CreateBlockHeader(), new uint256(0), this.network.Consensus.LastPOWBlock - 1));
var header = this.network.Consensus.ConsensusFactory.CreateBlockHeader();
consensusManager.Setup(cm => cm.Tip).Returns(new ChainedHeader(header, header.GetHash(), this.network.Consensus.LastPOWBlock - 1));

var controller = new MiningController(consensusManager.Object, this.fullNode.Object, this.loggerFactory, this.network, new Mock<IPowMining>().Object, new Mock<IWalletManager>().Object);

Expand All @@ -70,7 +71,8 @@ public void Generate_With_Incorrect_Block_Count_ReturnsInvalidRequest(int? block
public void Generate_Blocks_When_Model_Is_Invalid_ReturnsBadRequest()
{
var consensusManager = new Mock<IConsensusManager>();
consensusManager.Setup(cm => cm.Tip).Returns(new ChainedHeader(this.network.Consensus.ConsensusFactory.CreateBlockHeader(), new uint256(0), this.network.Consensus.LastPOWBlock - 1));
var header = this.network.Consensus.ConsensusFactory.CreateBlockHeader();
consensusManager.Setup(cm => cm.Tip).Returns(new ChainedHeader(header, header.GetHash(), this.network.Consensus.LastPOWBlock - 1));

var controller = new MiningController(consensusManager.Object, this.fullNode.Object, this.loggerFactory, this.network, new Mock<IPowMining>().Object, new Mock<IWalletManager>().Object);
controller.ModelState.AddModelError("key", "error message");
Expand Down Expand Up @@ -121,7 +123,8 @@ public void GenerateBlocksOn_PowNetwork_ReturnsSuccess()
public void GenerateBlocksOn_PosNetwork_ConsensusTip_IsBeforeLastPowBlock_ReturnsSuccess()
{
var consensusManager = new Mock<IConsensusManager>();
consensusManager.Setup(cm => cm.Tip).Returns(new ChainedHeader(this.network.Consensus.ConsensusFactory.CreateBlockHeader(), new uint256(0), this.network.Consensus.LastPOWBlock - 1));
var header = this.network.Consensus.ConsensusFactory.CreateBlockHeader();
consensusManager.Setup(cm => cm.Tip).Returns(new ChainedHeader(header, header.GetHash(), this.network.Consensus.LastPOWBlock - 1));

var walletManager = new Mock<IWalletManager>();
walletManager.Setup(f => f.GetWalletsNames()).Returns(new List<string> { wallet });
Expand Down Expand Up @@ -150,7 +153,8 @@ public void GenerateBlocksOn_PosNetwork_ConsensusTip_IsBeforeLastPowBlock_Return
public void GenerateBlocksOn_PosNetwork_ConsensusTip_IsAfterLastPowBlock_ReturnsError()
{
var consensusManager = new Mock<IConsensusManager>();
consensusManager.Setup(cm => cm.Tip).Returns(new ChainedHeader(this.network.Consensus.ConsensusFactory.CreateBlockHeader(), new uint256(0), this.network.Consensus.LastPOWBlock + 1));
var header = this.network.Consensus.ConsensusFactory.CreateBlockHeader();
consensusManager.Setup(cm => cm.Tip).Returns(new ChainedHeader(header, header.GetHash(), this.network.Consensus.LastPOWBlock + 1));
this.fullNode.Setup(i => i.NodeService<IConsensusManager>(false)).Returns(consensusManager.Object);

var controller = new MiningController(consensusManager.Object, this.fullNode.Object, this.loggerFactory, this.network, new Mock<IPowMining>().Object, new Mock<IWalletManager>().Object);
Expand Down
3 changes: 2 additions & 1 deletion src/Blockcore.Features.PoA.Tests/PoATestsBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,8 @@ public PoATestsBase(TestPoANetwork network = null)
this.federationManager = CreateFederationManager(this, this.network, this.loggerFactory, this.signals);

this.chainIndexerMock = new Mock<ChainIndexer>();
this.chainIndexerMock.Setup(x => x.Tip).Returns(new ChainedHeader(new BlockHeader(), 0, 0));
var header = new BlockHeader();
this.chainIndexerMock.Setup(x => x.Tip).Returns(new ChainedHeader(header, header.GetHash(), 0));
this.slotsManager = new SlotsManager(this.network, this.federationManager, this.chainIndexerMock.Object, this.loggerFactory);

this.poaHeaderValidator = new PoABlockHeaderValidator(this.loggerFactory);
Expand Down
8 changes: 5 additions & 3 deletions src/Blockcore.Features.PoA.Tests/SlotsManagerTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,8 @@ public void GetMiningTimestamp()
this.network = new TestPoANetwork(new List<PubKey>() { tool.GeneratePrivateKey().PubKey, key.PubKey, tool.GeneratePrivateKey().PubKey });

IFederationManager fedManager = PoATestsBase.CreateFederationManager(this, this.network, new ExtendedLoggerFactory(), new Signals.Signals(new LoggerFactory(), null));
this.chainIndexer.Setup(x => x.Tip).Returns(new ChainedHeader(new BlockHeader(), 0, 0));
var header = new BlockHeader();
this.chainIndexer.Setup(x => x.Tip).Returns(new ChainedHeader(header, header.GetHash(), 0));
this.slotsManager = new SlotsManager(this.network, fedManager, this.chainIndexer.Object, new LoggerFactory());

List<IFederationMember> federationMembers = fedManager.GetFederationMembers();
Expand Down Expand Up @@ -93,10 +94,11 @@ public void GetMiningTimestamp()
Assert.Equal(thisTurnTimestamp, this.slotsManager.GetMiningTimestamp(thisTurnTimestamp + 1));

// If we are only just past our last timestamp, but we've already mined a block there, then get the NEXT turn's timestamp.
this.chainIndexer.Setup(x => x.Tip).Returns(new ChainedHeader(new BlockHeader
header = new BlockHeader
{
Time = thisTurnTimestamp
}, 0, 0));
};
this.chainIndexer.Setup(x => x.Tip).Returns(new ChainedHeader(header, header.GetHash(), 0));
this.slotsManager = new SlotsManager(this.network, fedManager, this.chainIndexer.Object, new LoggerFactory());
Assert.Equal(nextTurnTimestamp, this.slotsManager.GetMiningTimestamp(thisTurnTimestamp + 1));

Expand Down
Loading