/// <summary> /// Set the tip if header is higher than current tip and previous blocks are present /// </summary> /// <param name="header"></param> /// <param name="chainedBlock">null if header could not be chained with previous blocks</param> /// <returns>True if header is the new Tip</returns> public bool TrySetTip(BlockHeader header, out ChainedBlock chainedBlock) { AssertInitialized(); var headerHash = header.GetHash(); chainedBlock = GetBlock(headerHash, true); if (chainedBlock != null) { return(false); } ChainedBlock previous = GetBlock(header.HashPrevBlock, true); if (previous == null) { return(false); } chainedBlock = new ChainedBlock(header, headerHash, previous); if (chainedBlock.Height > Tip.Height) { SetTip(chainedBlock); } else { var change = new ChainChange() { ChangeType = ChainChangeType.AddBlock, HeightOrBackstep = (uint)chainedBlock.Height, BlockHeader = chainedBlock.Header }; PushChange(change, chainedBlock.HashBlock); } return(true); }
private void Process(ChainChange change, uint256 blockHash) { if (blockHash == null && change.BlockHeader != null) { blockHash = change.BlockHeader.GetHash(); } if (change.Add) { var previous = GetBlock(change.BlockHeader.HashPrevBlock, false); if (Initialized && previous == null && change.HeightOrBackstep != StartHeight) { throw new InvalidOperationException("Previous block missing"); } var block = Initialized ? new ChainedBlock(change.BlockHeader, blockHash, previous) : new ChainedBlock(change.BlockHeader, (int)change.HeightOrBackstep); index.AddOrReplace(blockHash, block); vChain.Add(block); } else { foreach (var removed in vChain.Resize(vChain.Count - (int)change.HeightOrBackstep).Where(r => r != null)) { offchainIndex.AddOrReplace(removed.HashBlock, removed); index.Remove(removed.HashBlock); } } }
public ChainedBlock GetOrAdd(BlockHeader header) { AssertInitialized(); var headerHash = header.GetHash(); ChainedBlock pindex = GetBlock(headerHash, true); if (pindex != null) { return(pindex); } ChainedBlock previous = GetBlock(header.HashPrevBlock, true); if (previous == null) { return(null); } pindex = new ChainedBlock(header, headerHash, previous); if (previous.HashBlock == Tip.HashBlock) { var change = new ChainChange() { Add = true, BlockHeader = pindex.Header, HeightOrBackstep = (uint)pindex.Height }; ProcessAndRecord(change, pindex.HashBlock); } else { if (pindex.Height <= Tip.Height) { offchainIndex.Add(pindex.HashBlock, pindex); } else { var fork = FindFork(pindex.EnumerateToGenesis().Select(c => c.HashBlock)); var change = new ChainChange() { Add = false, HeightOrBackstep = (uint)(Tip.Height - fork.Height) }; ProcessAndRecord(change, null); foreach (var block in pindex.EnumerateToGenesis().TakeWhile(s => s != fork).Reverse()) { change = new ChainChange() { Add = true, BlockHeader = block.Header, HeightOrBackstep = (uint)block.Height }; ProcessAndRecord(change, block.HashBlock); } } } return(pindex); }
public void Initialize(BlockHeader header, int height) { if (Initialized) { throw new InvalidOperationException("Already initialized"); } var change = new ChainChange() { ChangeType = ChainChangeType.SetTip, BlockHeader = header, HeightOrBackstep = (uint)height }; PushChange(change, header.GetHash()); }
public void Initialize(BlockHeader header, int height) { if (Initialized) { throw new InvalidOperationException("Already initialized"); } var change = new ChainChange() { Add = true, BlockHeader = header, HeightOrBackstep = (uint)height }; ProcessAndRecord(change, header.GetHash()); }
void Process(ChainChange change, uint256 blockHash) { if (blockHash == null && change.BlockHeader != null) { blockHash = change.BlockHeader.GetHash(); } if (change.ChangeType == ChainChangeType.SetTip || change.ChangeType == ChainChangeType.AddBlock) { var previous = GetBlock(change.BlockHeader.HashPrevBlock, true); if (Initialized && previous == null && change.HeightOrBackstep != StartHeight) { throw new InvalidOperationException("Previous block missing"); } var block = Initialized ? new ChainedBlock(change.BlockHeader, blockHash, previous) : new ChainedBlock(change.BlockHeader, (int)change.HeightOrBackstep); if (change.ChangeType == ChainChangeType.SetTip) { List <ChainedBlock> newMain = new List <ChainedBlock>(); ChainedBlock previousBlock = block; while (previousBlock != null && previousBlock.Height >= Height + 1) { newMain.Add(previousBlock); previousBlock = previousBlock.Previous; } newMain.Reverse(); foreach (var newBlock in newMain) { vChain.Add(newBlock); index.AddOrReplace(newBlock.HashBlock, newBlock); offchainIndex.Remove(newBlock.HashBlock); } } else { offchainIndex.AddOrReplace(blockHash, block); } } else if (change.ChangeType == ChainChangeType.BackStep) { foreach (var removed in vChain.Resize(vChain.Count - (int)change.HeightOrBackstep).Where(r => r != null)) { offchainIndex.AddOrReplace(removed.HashBlock, removed); index.Remove(removed.HashBlock); } } }
public void PushChange(ChainChange change, uint256 blockHash) { Process(change, blockHash); _Changes.WriteNext(change); _NextToProcess++; }
private void ProcessAndRecord(ChainChange change, uint256 blockHash) { Process(change, blockHash); _Changes.WriteNext(change); _NextToProcess++; }
private void Process(ChainChange change, uint256 blockHash) { if(blockHash == null && change.BlockHeader != null) blockHash = change.BlockHeader.GetHash(); if(change.Add) { var previous = GetBlock(change.BlockHeader.HashPrevBlock, false); if(Initialized && previous == null && change.HeightOrBackstep != StartHeight) throw new InvalidOperationException("Previous block missing"); var block = Initialized ? new ChainedBlock(change.BlockHeader, blockHash, previous) : new ChainedBlock(change.BlockHeader, (int)change.HeightOrBackstep); index.AddOrReplace(blockHash, block); vChain.Add(block); } else { foreach(var removed in vChain.Resize(vChain.Count - (int)change.HeightOrBackstep).Where(r => r != null)) { offchainIndex.AddOrReplace(removed.HashBlock, removed); index.Remove(removed.HashBlock); } } }
public void Initialize(BlockHeader header, int height) { if(Initialized) throw new InvalidOperationException("Already initialized"); var change = new ChainChange() { Add = true, BlockHeader = header, HeightOrBackstep = (uint)height }; ProcessAndRecord(change, header.GetHash()); }
public ChainedBlock GetOrAdd(BlockHeader header) { AssertInitialized(); var headerHash = header.GetHash(); ChainedBlock pindex = GetBlock(headerHash, true); if(pindex != null) return pindex; ChainedBlock previous = GetBlock(header.HashPrevBlock, true); if(previous == null) { return null; } pindex = new ChainedBlock(header, headerHash, previous); if(previous.HashBlock == Tip.HashBlock) { var change = new ChainChange() { Add = true, BlockHeader = pindex.Header, HeightOrBackstep = (uint)pindex.Height }; ProcessAndRecord(change, pindex.HashBlock); } else { if(pindex.Height <= Tip.Height) { offchainIndex.Add(pindex.HashBlock, pindex); } else { var fork = FindFork(pindex.EnumerateToGenesis().Select(c => c.HashBlock)); var change = new ChainChange() { Add = false, HeightOrBackstep = (uint)(Tip.Height - fork.Height) }; ProcessAndRecord(change, null); foreach(var block in pindex.EnumerateToGenesis().TakeWhile(s => s != fork).Reverse()) { change = new ChainChange() { Add = true, BlockHeader = block.Header, HeightOrBackstep = (uint)block.Height }; ProcessAndRecord(change, block.HashBlock); } } } return pindex; }