public bool TrySetTip(BlockHeader header, out ChainedBlock chainedHeader) { if (header == null) throw new ArgumentNullException("header"); chainedHeader = null; var prev = GetBlock(header.HashPrevBlock); if(prev == null) return false; chainedHeader = new ChainedBlock(header, header.GetHash(), GetBlock(header.HashPrevBlock)); SetTip(chainedHeader); return true; }
public bool TrySetTip(BlockHeader header, out ChainedBlock chainedHeader) { if (header == null) { throw new ArgumentNullException("header"); } chainedHeader = null; var prev = GetBlock(header.HashPrevBlock); if (prev == null) { return(false); } chainedHeader = new ChainedBlock(header, header.GetHash(), GetBlock(header.HashPrevBlock)); SetTip(chainedHeader); return(true); }
public ChainedBlock CreateChainedBlock(BlockHeader header) { AssertInitialized(); var hash = header.GetHash(); var result = GetBlock(hash, true); if (result == null) { var previous = GetBlock(header.HashPrevBlock, true); if (previous == null) { throw new InvalidOperationException("Previous block is missing"); } return(new ChainedBlock(header, hash, previous)); } return(result); }
/// <summary> /// Attempts to set the tip of this chain based upon another block header. /// </summary> /// <param name="header">The block header to set to tip.</param> /// <param name="chainedHeader">The newly chained block header for the tip.</param> /// <returns>Whether the tip was set successfully. The method fails (and returns <c>false</c>) /// if the <paramref name="header"/>'s link to a previous header does not point to any block /// in the current chain.</returns> public bool TrySetTip(BlockHeader header, out ChainedBlock chainedHeader) { if (header == null) { throw new ArgumentNullException("header"); } chainedHeader = null; ChainedBlock prev = this.GetBlock(header.HashPrevBlock); if (prev == null) { return(false); } chainedHeader = new ChainedBlock(header, header.GetHash(this.Network.NetworkOptions), this.GetBlock(header.HashPrevBlock)); this.SetTip(chainedHeader); return(true); }
// (memory only) Sequencial id assigned to distinguish order in which blocks are received. //uint nSequenceId; public ChainedBlock(BlockHeader header,uint256 headerHash, ChainedBlock previous) { if(previous != null) { nHeight = previous.Height + 1; } this.pprev = previous; //this.nDataPos = pos; this.header = header; this.phashBlock = headerHash ?? header.GetHash(); if(previous == null) { if(header.HashPrevBlock != 0) throw new ArgumentException("Only the genesis block can have no previous block"); } else { if(previous.HashBlock != header.HashPrevBlock) throw new ArgumentException("The previous block has not the expected hash"); } }
public void Load(BitcoinStream stream) { stream.ConsensusFactory = this.network.Consensus.ConsensusFactory; using (this.lockObject.LockWrite()) { 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) { this.blocksByHeight.Clear(); this.blocksById.Clear(); this.tip = null; this.SetTipLocked(new ChainedHeader(header, header.GetHash(), 0)); } else if (this.tip.HashBlock == header.HashPrevBlock && !(header.IsNull && header.Nonce == 0)) { this.SetTipLocked(new ChainedHeader(header, id.Value, this.Tip)); } else { break; } height++; } } catch (EndOfStreamException) { } } }
public ChainedBlock(BlockHeader header, int height) { if(header == null) throw new ArgumentNullException("header"); nHeight = height; //this.nDataPos = pos; this.header = header; this.phashBlock = header.GetHash(); }
public ChainedBlock(BlockHeader header, int height) { nHeight = height; //this.nDataPos = pos; this.header = header; this.phashBlock = header.GetHash(); }
public ConcurrentChain(BlockHeader genesisHeader, Network network = null) // TODO: Remove the null default { this.network = network ?? Network.Main; this.SetTip(new ChainedHeader(genesisHeader, genesisHeader.GetHash(), 0)); }
public bool PutHeader(BlockHeader blockHeader) { return(this.headers.TryAdd(blockHeader.GetHash(), blockHeader)); }
public Chain(BlockHeader blockHeader, int height, ObjectStream<ChainChange> changes) { if(changes == null) changes = new StreamObjectStream<ChainChange>(); _Changes = changes; changes.Rewind(); if(changes.EOF) { Initialize(blockHeader, height); } else { var first = changes.ReadNext(); if(first.BlockHeader.GetHash() != blockHeader.GetHash()) { throw new InvalidOperationException("The first block of this stream is different than the expected one at height " + height); } if(first.HeightOrBackstep != height) { throw new InvalidOperationException("The first block of this stream has height " + first.HeightOrBackstep + " but expected is " + height); } changes.Rewind(); Process(); } }
public ConcurrentChain(BlockHeader genesisHeader, Network network = null) // TODO: Remove the null default { this.network = network ?? Network.PurpleMain; this.SetTip(new ChainedBlock(genesisHeader, genesisHeader.GetHash(this.network.NetworkOptions), 0)); }
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; }
public uint256 GetHash() { //Block's hash is his header's hash return(header.GetHash()); }
public Target GetNextWorkRequired(BlockHeader block, Consensus consensus) { return(new ChainedBlock(block, block.GetHash(), this).GetWorkRequired(consensus)); }
private ChainBlockHeader CreateChainChange(int height, BlockHeader block) { return new ChainBlockHeader() { Height = height, Header = block, BlockId = block.GetHash() }; }