private HashHeightPair GetTipHash(Types.SessionWrapper session) { if (this.blockHash == null) { Types.StoreInput input = new Types.StoreInput(); Types.StoreOutput output = new Types.StoreOutput(); var lastblockKey = new Types.StoreKey { tableType = "BlockHash", key = blockHashKey }; Types.StoreContext context = new Types.StoreContext(); var blkStatus = session.Session.Read(ref lastblockKey, ref input, ref output, context, 1); // TODO: use height a serial number? if (blkStatus == Status.OK) { this.blockHash = new HashHeightPair(); this.blockHash.FromBytes(output.value.value); } } return(this.blockHash); }
public FetchCoinsResponse FetchCoins(OutPoint[] utxos) { FetchCoinsResponse res = new FetchCoinsResponse(); using (var session = this.db.NewSession()) { using (new StopwatchDisposable(o => this.performanceCounter.AddQueryTime(o))) { this.performanceCounter.AddQueriedEntities(utxos.Length); Types.StoreInput input = new Types.StoreInput(); Types.StoreOutput output = new Types.StoreOutput(); Types.StoreContext context = new Types.StoreContext(); var readKey = new Types.StoreKey { tableType = "Coins" }; foreach (OutPoint outPoint in utxos) { output.value = null; readKey.key = outPoint.ToBytes(); var addStatus = session.Read(ref readKey, ref input, ref output, context, 1); if (addStatus == Status.PENDING) { session.CompletePending(true); context.FinalizeRead(ref addStatus, ref output); } Coins outputs = addStatus == Status.OK ? this.dataStoreSerializer.Deserialize <Coins>(output.value.value) : null; this.logger.LogDebug("Outputs for '{0}' were {1}.", outPoint, outputs == null ? "NOT loaded" : "loaded"); res.UnspentOutputs.Add(outPoint, new UnspentOutput(outPoint, outputs)); } } } return(res); }
public HashHeightPair Rewind() { HashHeightPair res = null; using (var session = this.db.NewSession()) { var wrapper = new Types.SessionWrapper { Session = session }; HashHeightPair current = this.GetTipHash(wrapper); Types.StoreInput input1 = new Types.StoreInput(); Types.StoreOutput output1 = new Types.StoreOutput(); Types.StoreContext context = new Types.StoreContext(); var readKey = new Types.StoreKey { tableType = "Rewind", key = BitConverter.GetBytes(current.Height) }; var addStatus = session.Read(ref readKey, ref input1, ref output1, context, 1); if (addStatus == Status.PENDING) { session.CompletePending(true); context.FinalizeRead(ref addStatus, ref output1); } if (addStatus != Status.OK) { throw new InvalidOperationException($"No rewind data found for block `{current}`"); } var deteletKey = new Types.StoreKey { tableType = "Rewind", key = BitConverter.GetBytes(current.Height) }; Types.StoreContext contextDel = new Types.StoreContext(); var deleteStatus = session.Delete(ref readKey, contextDel, 1); if (deleteStatus != Status.OK) { throw new Exception(); } var rewindData = this.dataStoreSerializer.Deserialize <RewindData>(output1.value.value); this.SetBlockHash(wrapper, rewindData.PreviousBlockHash); foreach (OutPoint outPoint in rewindData.OutputsToRemove) { this.logger.LogDebug("Outputs of outpoint '{0}' will be removed.", outPoint); deteletKey = new Types.StoreKey { tableType = "Coins", key = outPoint.ToBytes() }; contextDel = new Types.StoreContext(); deleteStatus = session.Delete(ref readKey, contextDel, 1); if (deleteStatus != Status.OK) { throw new Exception(); } } foreach (RewindDataOutput rewindDataOutput in rewindData.OutputsToRestore) { this.logger.LogDebug("Outputs of outpoint '{0}' will be restored.", rewindDataOutput.OutPoint); var upsertKey = new Types.StoreKey { tableType = "Coins", key = rewindDataOutput.OutPoint.ToBytes() }; var upsertValue = new Types.StoreValue { value = this.dataStoreSerializer.Serialize(rewindDataOutput.Coins) }; Types.StoreContext context2 = new Types.StoreContext(); addStatus = session.Upsert(ref upsertKey, ref upsertValue, context2, 1); if (addStatus != Status.OK) { throw new Exception(); } } res = rewindData.PreviousBlockHash; } return(res); }