/// <summary> /// Obtains order number of the last saved rewind state in the database. /// </summary> /// <param name="transaction">Open dBreeze transaction.</param> /// <returns>Order number of the last saved rewind state, or <c>0</c> if no rewind state is found in the database.</returns> /// <remarks> /// TODO: Using <c>0</c> is hacky here, and <see cref="SaveChanges" /> exploits that in a way that if no such rewind /// data exist /// the order number of the first rewind data is 0 + 1 = 1. /// </remarks> int GetRewindIndex(Transaction transaction) { var prevLazySettings = transaction.ValuesLazyLoadingIsOn; transaction.ValuesLazyLoadingIsOn = true; var firstRow = transaction.SelectBackward <int, byte[]>("Rewind").FirstOrDefault(); transaction.ValuesLazyLoadingIsOn = prevLazySettings; return(firstRow != null ? firstRow.Key : 0); }
/// <summary> /// Obtains order number of the last saved rewind state in the database. /// </summary> /// <param name="transaction">Open DBreeze transaction.</param> /// <returns>Order number of the last saved rewind state, or <c>-1</c> if no rewind state is found in the database.</returns> /// <remarks>TODO: Using <c>-1</c> is hacky here, and <see cref="SaveChangesAsync"/> exploits that in a way that if no such rewind data exist /// the order number of the first rewind data is -1 + 1 = 0.</remarks> private int GetRewindIndex(DBreeze.Transactions.Transaction transaction) { bool prevLazySettings = transaction.ValuesLazyLoadingIsOn; transaction.ValuesLazyLoadingIsOn = true; Row <int, RewindData> firstRow = transaction.SelectBackward <int, RewindData>("Rewind").FirstOrDefault(); transaction.ValuesLazyLoadingIsOn = prevLazySettings; return(firstRow != null ? firstRow.Key : -1); }
/// <inheritdoc /> public override Task <uint256> Rewind() { Task <uint256> task = Task.Run(() => { this.logger.LogTrace("()"); uint256 res = null; using (DBreeze.Transactions.Transaction transaction = this.dbreeze.GetTransaction()) { transaction.SynchronizeTables("BlockHash", "Coins", "Rewind"); if (this.GetRewindIndex(transaction) == -1) { transaction.RemoveAllKeys("Coins", true); this.SetBlockHash(transaction, this.network.GenesisHash); res = this.network.GenesisHash; } else { transaction.ValuesLazyLoadingIsOn = false; Row <int, RewindData> firstRow = transaction.SelectBackward <int, RewindData>("Rewind").FirstOrDefault(); transaction.RemoveKey("Rewind", firstRow.Key); this.SetBlockHash(transaction, firstRow.Value.PreviousBlockHash); foreach (uint256 txId in firstRow.Value.TransactionsToRemove) { this.logger.LogTrace("Outputs of transaction ID '{0}' will be removed.", txId); transaction.RemoveKey("Coins", txId.ToBytes(false)); } foreach (UnspentOutputs coin in firstRow.Value.OutputsToRestore) { this.logger.LogTrace("Outputs of transaction ID '{0}' will be restored.", coin.TransactionId); transaction.Insert("Coins", coin.TransactionId.ToBytes(false), coin.ToCoins()); } res = firstRow.Value.PreviousBlockHash; } transaction.Commit(); } this.logger.LogTrace("(-):'{0}'", res); return(res); }); return(task); }
/// <inheritdoc /> public uint256 Rewind() { uint256 res = null; using (DBreeze.Transactions.Transaction transaction = this.CreateTransaction()) { transaction.SynchronizeTables("BlockHash", "Coins", "Rewind"); if (this.GetRewindIndex(transaction) == 0) { transaction.RemoveAllKeys("Coins", true); this.SetBlockHash(transaction, this.network.GenesisHash); res = this.network.GenesisHash; } else { transaction.ValuesLazyLoadingIsOn = false; Row <int, byte[]> firstRow = transaction.SelectBackward <int, byte[]>("Rewind").FirstOrDefault(); transaction.RemoveKey("Rewind", firstRow.Key); var rewindData = this.dBreezeSerializer.Deserialize <RewindData>(firstRow.Value); this.SetBlockHash(transaction, rewindData.PreviousBlockHash); foreach (uint256 txId in rewindData.TransactionsToRemove) { this.logger.LogDebug("Outputs of transaction ID '{0}' will be removed.", txId); transaction.RemoveKey("Coins", txId.ToBytes(false)); } foreach (UnspentOutputs coin in rewindData.OutputsToRestore) { this.logger.LogDebug("Outputs of transaction ID '{0}' will be restored.", coin.TransactionId); transaction.Insert("Coins", coin.TransactionId.ToBytes(false), this.dBreezeSerializer.Serialize(coin.ToCoins())); } res = rewindData.PreviousBlockHash; } transaction.Commit(); } return(res); }
public byte[] GetLast(DBreeze.Transactions.Transaction dbTx) { var record = dbTx.SelectBackward <uint, byte[]>(TABLE).First(); return(record == null ? null : record.Value); }