public static ChainIndexer Load(this ChainIndexer chainIndexer, BitcoinStream stream) { stream.ConsensusFactory = chainIndexer.Network.Consensus.ConsensusFactory; try { int height = 0; while (true) { uint256.MutableUint256 id = null; stream.ReadWrite <uint256.MutableUint256>(ref id); BlockHeader header = null; stream.ReadWrite(ref header); if (height == 0) { Assert.True(header.GetHash() == chainIndexer.Tip.HashBlock); } else if (chainIndexer.Tip.HashBlock == header.HashPrevBlock && !(header.IsNull && header.Nonce == 0)) { chainIndexer.Add(new ChainedHeader(header, id.Value, chainIndexer.Tip)); } else { break; } height++; } } catch (EndOfStreamException) { } return(chainIndexer); }
public void Query_Range_During_Reorg_Success(int chainLength, int start, int?end) { // Simulate a reorg occuring mid-enumeration and check that the query still returns the full old chain. var chainIndexer = new ChainIndexer(this.network); ChainedHeader[] chainBeforeReorg = this.CreateChain(chainIndexer.Genesis, chainLength); // Create a new reorg that removes 3 blocks and adds another 5. ChainedHeader[] chainAfterReorg = this.CreateChain(chainBeforeReorg[chainLength - 3], 5); chainIndexer.Initialize(chainBeforeReorg.Last()); var query = new ChainIndexerRangeQuery(chainIndexer); IEnumerator <ChainedHeader> enumerator = query.EnumerateRange(start, end).GetEnumerator(); int position = start; while (position < (end ?? chainBeforeReorg.Length)) { enumerator.MoveNext(); ChainedHeader item = enumerator.Current; // Trigger a reorg at position chainLength - 3 if (position == chainLength - 3) { // Remove two headers. chainIndexer.Remove(chainIndexer.Tip); chainIndexer.Remove(chainIndexer.Tip); // Add the reorged chain's headers. // Note: Most likely is that headers are removed only before the enumeration is completed. chainIndexer.Add(chainAfterReorg[1]); chainIndexer.Add(chainAfterReorg[2]); chainIndexer.Add(chainAfterReorg[3]); chainIndexer.Add(chainAfterReorg[4]); } Assert.Equal(chainBeforeReorg[position], item); position++; } enumerator.Dispose(); }
public static ChainedHeaderBlock[] GetBlocks(int count, ChainIndexer chainIndexer, Func <int, ChainedHeaderBlock> block, ChainedHeader previousHeader = null) { ChainedHeader previous = null; if (previousHeader != null) { previous = previousHeader; } return(Enumerable.Range(0, count).Select(i => { ChainedHeaderBlock chainedHeaderBlock = block(i); chainedHeaderBlock.ChainedHeader.SetPrivatePropertyValue("Previous", previous); previous = chainedHeaderBlock.ChainedHeader; chainIndexer.Add(chainedHeaderBlock.ChainedHeader); return chainedHeaderBlock; }).ToArray()); }