/// <inheritdoc /> public Task SaveAsync(ChainIndexer chainIndexer) { Guard.NotNull(chainIndexer, nameof(chainIndexer)); Task task = Task.Run(() => { using (var batch = new WriteBatch()) { ChainedHeader fork = this.locator == null ? null : chainIndexer.FindFork(this.locator); ChainedHeader tip = chainIndexer.Tip; ChainedHeader toSave = tip; var headers = new List <ChainedHeader>(); while (toSave != fork) { headers.Add(toSave); toSave = toSave.Previous; } // DBreeze is faster on ordered insert. IOrderedEnumerable <ChainedHeader> orderedChainedHeaders = headers.OrderBy(b => b.Height); foreach (ChainedHeader block in orderedChainedHeaders) { batch.Put(BitConverter.GetBytes(block.Height), this.dataStoreSerializer.Serialize(block.Header)); } this.locator = tip.GetLocator(); this.leveldb.Write(batch); } }); return(task); }
/// <inheritdoc /> public Task SaveAsync(ChainIndexer chainIndexer) { Guard.NotNull(chainIndexer, nameof(chainIndexer)); Task task = Task.Run(() => { ChainedHeader fork = this.locator == null ? null : chainIndexer.FindFork(this.locator); ChainedHeader tip = chainIndexer.Tip; ChainedHeader toSave = tip; var headers = new List <ChainedHeader>(); while (toSave != fork) { headers.Add(toSave); toSave = toSave.Previous; } var items = headers.OrderBy(b => b.Height).Select(h => new ChainDataItem { Height = h.Height, Data = new ChainData { Hash = h.HashBlock, Work = h.ChainWorkBytes } }); this.chainStore.PutChainData(items); this.locator = tip.GetLocator(); }); return(task); }
/// <summary> /// Returns the first common chained block header between two chains. /// </summary> /// <param name="chainSrc">The source chain.</param> /// <param name="otherChain">The other chain.</param> /// <returns>First common chained block header or <c>null</c>.</returns> private ChainedHeader FindFork(ChainIndexer chainSrc, ChainIndexer otherChain) { if (otherChain == null) { throw new ArgumentNullException("otherChain"); } return(chainSrc.FindFork(otherChain.Tip.EnumerateToGenesis().Select(o => o.HashBlock))); }
/// <inheritdoc /> public Task SaveAsync(ChainIndexer chainIndexer) { Guard.NotNull(chainIndexer, nameof(chainIndexer)); Task task = Task.Run(() => { using (DBreeze.Transactions.Transaction transaction = this.dbreeze.GetTransaction()) { ChainedHeader fork = this.locator == null ? null : chainIndexer.FindFork(this.locator); ChainedHeader tip = chainIndexer.Tip; ChainedHeader toSave = tip; var headers = new List <ChainedHeader>(); while (toSave != fork) { headers.Add(toSave); toSave = toSave.Previous; } // DBreeze is faster on ordered insert. IOrderedEnumerable <ChainedHeader> orderedChainedHeaders = headers.OrderBy(b => b.Height); foreach (ChainedHeader block in orderedChainedHeaders) { BlockHeader header = block.Header; if (header is ProvenBlockHeader) { // copy the header parameters, untill we dont make PH a normal header we store it in its own repo. BlockHeader newHeader = chainIndexer.Network.Consensus.ConsensusFactory.CreateBlockHeader(); newHeader.Bits = header.Bits; newHeader.Time = header.Time; newHeader.Nonce = header.Nonce; newHeader.Version = header.Version; newHeader.HashMerkleRoot = header.HashMerkleRoot; newHeader.HashPrevBlock = header.HashPrevBlock; header = newHeader; } transaction.Insert("Chain", block.Height, this.dBreezeSerializer.Serialize(header)); } this.locator = tip.GetLocator(); transaction.Commit(); } }); return(task); }