public override void SaveChanges(ChainedBlock newTip, IEnumerable <uint256> txIds, IEnumerable <Coins> coins) { int insertedEntities = 0; using (new StopWatch().Start(o => PerformanceCounter.AddInsertTime(o))) { using (var tx = _Engine.GetTransaction()) { var fork = FindFork(newTip, Tip); var currentTip = newTip; var blocks = new ChainedBlock[currentTip.Height - fork.Height]; int i = 0; while (currentTip.Height != fork.Height) { blocks[i++] = currentTip; currentTip = currentTip.Previous; } Array.Reverse(blocks); insertedEntities += blocks.Length; foreach (var block in blocks) { tx.Insert("Chain", block.Height, block.Header); } var txIdsEnum = txIds.GetEnumerator(); var coinsEnum = coins.GetEnumerator(); List <Tuple <uint256, Coins> > all = new List <Tuple <uint256, Coins> >(); while (txIdsEnum.MoveNext()) { coinsEnum.MoveNext(); all.Add(Tuple.Create(txIdsEnum.Current, coinsEnum.Current)); } all.Sort(CoinPairComparer.Instance); foreach (var coin in all) { if (coin.Item2.IsPruned) { tx.RemoveKey("Coins", coin.Item1.ToBytes(false)); } else { tx.Insert("Coins", coin.Item1.ToBytes(false), coin.Item2); } } insertedEntities += all.Count; tx.Commit(); } _Tip = newTip; } PerformanceCounter.AddInsertedEntities(insertedEntities); }
public override void SaveChanges(ChainedBlock newTip, IEnumerable <UnspentOutputs> unspentOutputs) { int insertedEntities = 0; using (new StopWatch().Start(o => PerformanceCounter.AddInsertTime(o))) { using (var tx = _Engine.GetTransaction()) { var fork = FindFork(newTip, Tip); var currentTip = newTip; var blocks = new ChainedBlock[currentTip.Height - fork.Height]; int i = 0; while (currentTip.Height != fork.Height) { blocks[i++] = currentTip; currentTip = currentTip.Previous; } Array.Reverse(blocks); insertedEntities += blocks.Length; foreach (var block in blocks) { tx.Insert("Chain", block.Height, block.Header); } var all = unspentOutputs.ToList(); all.Sort(UnspentOutputsComparer.Instance); foreach (var coin in all) { if (coin.IsPrunable) { tx.RemoveKey("Coins", coin.TransactionId.ToBytes(false)); } else { tx.Insert("Coins", coin.TransactionId.ToBytes(false), coin.ToCoins()); } } insertedEntities += all.Count; tx.Commit(); } _Tip = newTip; } PerformanceCounter.AddInsertedEntities(insertedEntities); }
public override Task SaveChangesAsync(IEnumerable <UnspentOutputs> unspentOutputs, IEnumerable <TxOut[]> originalOutputs, uint256 oldBlockHash, uint256 nextBlockHash) { return(_Session.Do(() => { RewindData rewindData = originalOutputs == null ? null : new RewindData(oldBlockHash); int insertedEntities = 0; using (new StopWatch().Start(o => PerformanceCounter.AddInsertTime(o))) { var current = GetCurrentHash(); if (current != oldBlockHash) { throw new InvalidOperationException("Invalid oldBlockHash"); } SetBlockHash(nextBlockHash); var all = unspentOutputs.ToList(); Dictionary <uint256, TxOut[]> unspentToOriginal = new Dictionary <uint256, TxOut[]>(all.Count); if (originalOutputs != null) { var originalEnumerator = originalOutputs.GetEnumerator(); foreach (var u in all) { originalEnumerator.MoveNext(); unspentToOriginal.Add(u.TransactionId, originalEnumerator.Current); } } all.Sort(UnspentOutputsComparer.Instance); foreach (var coin in all) { if (coin.IsPrunable) { _Session.Transaction.RemoveKey("Coins", coin.TransactionId.ToBytes(false)); } else { _Session.Transaction.Insert("Coins", coin.TransactionId.ToBytes(false), coin.ToCoins()); } if (originalOutputs != null) { TxOut[] original = null; unspentToOriginal.TryGetValue(coin.TransactionId, out original); if (original == null) { //This one did not existed before, if we rewind, delete it rewindData.TransactionsToRemove.Add(coin.TransactionId); } else { //We'll need to restore the original outputs var clone = coin.Clone(); var before = clone.UnspentCount; clone._Outputs = original.ToArray(); rewindData.OutputsToRestore.Add(clone); } } } if (rewindData != null) { int nextRewindIndex = GetRewindIndex() + 1; _Session.Transaction.Insert <int, RewindData>("Rewind", nextRewindIndex, rewindData); } insertedEntities += all.Count; _Session.Transaction.Commit(); } PerformanceCounter.AddInsertedEntities(insertedEntities); })); }