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); }
/// <summary> /// Force a new tip for the chain /// </summary> /// <param name="pindex"></param> /// <returns>forking point</returns> public override ChainedBlock SetTip(ChainedBlock pindex) { AssertInitialized(); if (pindex.HashBlock == Tip.HashBlock) { return(pindex); } var fork = FindFork(pindex.EnumerateToGenesis().Select(g => g.HashBlock)); var backStep = (uint)(Tip.Height - fork.Height); if (backStep != 0) { PushChange(new ChainChange() { ChangeType = ChainChangeType.BackStep, HeightOrBackstep = backStep }, null); } var newBranch = pindex.EnumerateToGenesis().TakeWhile(b => b.Height != fork.Height).ToList(); newBranch.Reverse(); var newTip = newBranch.Count == 0 ? null : newBranch[newBranch.Count - 1]; foreach (var block in newBranch) { var existing = GetBlock(block.HashBlock, true); if (existing == null || block == newTip) { PushChange(new ChainChange() { ChangeType = ChainChangeType.SetTip, BlockHeader = block.Header, HeightOrBackstep = (uint)block.Height }, block.HashBlock); } } return(fork); }
private ChainedBlock SetTipNoLock(ChainedBlock block) { int height = Tip == null ? -1 : Tip.Height; foreach (var orphaned in EnumerateThisToFork(block)) { _BlocksById.Remove(orphaned.HashBlock); _BlocksByHeight.Remove(orphaned.Height); height--; } var fork = GetBlockNoLock(height); foreach (var newBlock in block.EnumerateToGenesis() .TakeWhile(c => c != fork)) { _BlocksById.AddOrReplace(newBlock.HashBlock, newBlock); _BlocksByHeight.AddOrReplace(newBlock.Height, newBlock); } _Tip = block; return(fork); }
private ChainedBlock SetTipLocked(ChainedBlock block) { int height = this.Tip == null ? -1 : this.Tip.Height; foreach (ChainedBlock orphaned in this.EnumerateThisToFork(block)) { this.blocksById.Remove(orphaned.HashBlock); this.blocksByHeight.Remove(orphaned.Height); height--; } ChainedBlock fork = this.GetBlockLocked(height); foreach (ChainedBlock newBlock in block.EnumerateToGenesis().TakeWhile(c => c != fork)) { this.blocksById.AddOrReplace(newBlock.HashBlock, newBlock); this.blocksByHeight.AddOrReplace(newBlock.Height, newBlock); } this.tip = block; return(fork); }
public bool Validate(Network network, bool fullChain = true) { ChainedBlock tip = this.Tip; if (tip == null) { return(false); } if (!fullChain) { return(tip.Validate(network)); } foreach (ChainedBlock block in tip.EnumerateToGenesis()) { if (!block.Validate(network)) { return(false); } } return(true); }
public PersistantChain CreateSubChain(ChainedBlock from, bool fromIncluded, ChainedBlock to, bool toIncluded, ObjectStream <ChainChange> output = null) { if (output == null) { output = new StreamObjectStream <ChainChange>(); } var blocks = to.EnumerateToGenesis() .Skip(toIncluded ? 0 : 1) .TakeWhile(c => c.HashBlock != from.HashBlock); if (fromIncluded) { blocks = blocks.Concat(new ChainedBlock[] { from }); } var array = blocks.ToArray(); Array.Reverse(array); foreach (var b in array) { output.WriteNext(new ChainChange() { ChangeType = ChainChangeType.SetTip, BlockHeader = b.Header, HeightOrBackstep = (uint)b.Height }); } return(new PersistantChain(output)); }
private ChainedBlock SetTipNoLock(ChainedBlock block) { int height = Tip == null ? -1 : Tip.Height; foreach(var orphaned in EnumerateThisToFork(block)) { _BlocksById.Remove(orphaned.HashBlock); _BlocksByHeight.Remove(orphaned.Height); height--; } var fork = GetBlockNoLock(height); foreach(var newBlock in block.EnumerateToGenesis() .TakeWhile(c => c != Tip)) { _BlocksById.AddOrReplace(newBlock.HashBlock, newBlock); _BlocksByHeight.AddOrReplace(newBlock.Height, newBlock); } _Tip = block; return fork; }
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 Chain CreateSubChain(ChainedBlock from, bool fromIncluded, ChainedBlock to, bool toIncluded, ObjectStream<ChainChange> output = null) { if(output == null) output = new StreamObjectStream<ChainChange>(); var blocks = to.EnumerateToGenesis() .Skip(toIncluded ? 0 : 1) .TakeWhile(c => c.HashBlock != from.HashBlock); if(fromIncluded) blocks = blocks.Concat(new ChainedBlock[] { from }); var array = blocks.Reverse().ToArray(); foreach(var b in array) { output.WriteNext(new ChainChange() { Add = true, BlockHeader = b.Header, HeightOrBackstep = (uint)b.Height }); } return new Chain(output); }