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);
        }