예제 #1
0
        private void Unmint(IChainStateCursor chainStateCursor, Transaction tx, ChainedHeader chainedHeader)
        {
            // check that transaction exists
            UnspentTx unspentTx;

            if (!chainStateCursor.TryGetUnspentTx(tx.Hash, out unspentTx))
            {
                // missing transaction output
                logger.Warn($"Missing transaction at block {chainedHeader.Height:N0}, {chainedHeader.Hash}, tx {tx.Hash}");
                throw new ValidationException(chainedHeader.Hash);
            }

            //TODO verify blockheight

            // verify all outputs are unspent before unminting
            if (!unspentTx.OutputStates.All(x => x == OutputState.Unspent))
            {
                throw new ValidationException(chainedHeader.Hash);
            }

            // remove the transaction
            if (!chainStateCursor.TryRemoveUnspentTx(tx.Hash))
            {
                throw new ValidationException(chainedHeader.Hash);
            }

            // remove the tx outputs
            for (var outputIndex = 0; outputIndex < tx.Outputs.Length; outputIndex++)
            {
                if (!chainStateCursor.TryRemoveUnspentTxOutput(new TxOutputKey(tx.Hash, (uint)outputIndex)))
                {
                    throw new ValidationException(chainedHeader.Hash);
                }
            }
        }
예제 #2
0
        public DeferredChainStateCursor(IChainState chainState, IStorageManager storageManager)
        {
            this.chainState     = chainState;
            this.storageManager = storageManager;

            headers = new DeferredDictionary <UInt256, ChainedHeader>(
                blockHash =>
            {
                ChainedHeader header;
                return(Tuple.Create(chainState.TryGetHeader(blockHash, out header), header));
            });

            unspentTxes = new WorkQueueDictionary <UInt256, UnspentTx>(
                txHash =>
            {
                UnspentTx unspentTx;
                return(Tuple.Create(chainState.TryGetUnspentTx(txHash, out unspentTx), unspentTx));
            });

            unspentTxOutputs = new WorkQueueDictionary <TxOutputKey, TxOutput>(
                txOutputKey =>
            {
                TxOutput txOutput;
                return(Tuple.Create(chainState.TryGetUnspentTxOutput(txOutputKey, out txOutput), txOutput));
            });

            blockSpentTxes = new DeferredDictionary <int, BlockSpentTxes>(
                blockHeight =>
            {
                BlockSpentTxes spentTxes;
                return(Tuple.Create(chainState.TryGetBlockSpentTxes(blockHeight, out spentTxes), spentTxes));
            });

            blockUnmintedTxes = new DeferredDictionary <UInt256, IImmutableList <UnmintedTx> >(
                blockHash =>
            {
                IImmutableList <UnmintedTx> unmintedTxes;
                return(Tuple.Create(chainState.TryGetBlockUnmintedTxes(blockHash, out unmintedTxes), unmintedTxes));
            });

            utxoApplier = new ActionBlock <WorkQueueDictionary <UInt256, UnspentTx> .WorkItem>(
                workItem =>
            {
                workItem.Consume(
                    (operation, unspentTxHash, unspentTx) =>
                {
                    lock (parentCursor)
                        switch (operation)
                        {
                        case WorkQueueOperation.Nothing:
                            break;

                        case WorkQueueOperation.Add:
                            if (!parentCursor.TryAddUnspentTx(unspentTx))
                            {
                                throw new InvalidOperationException();
                            }
                            break;

                        case WorkQueueOperation.Update:
                            if (!parentCursor.TryUpdateUnspentTx(unspentTx))
                            {
                                throw new InvalidOperationException();
                            }
                            break;

                        case WorkQueueOperation.Remove:
                            if (!parentCursor.TryRemoveUnspentTx(unspentTxHash))
                            {
                                throw new InvalidOperationException();
                            }
                            break;

                        default:
                            throw new InvalidOperationException();
                        }
                });
            });

            unspentTxes.WorkQueue.LinkTo(utxoApplier, new DataflowLinkOptions {
                PropagateCompletion = true
            });

            utxoApplier2 = new ActionBlock <WorkQueueDictionary <TxOutputKey, TxOutput> .WorkItem>(
                workItem =>
            {
                workItem.Consume(
                    (operation, txOutputKey, txOutput) =>
                {
                    lock (parentCursor)
                        switch (operation)
                        {
                        case WorkQueueOperation.Nothing:
                            break;

                        case WorkQueueOperation.Add:
                            if (!parentCursor.TryAddUnspentTxOutput(txOutputKey, txOutput))
                            {
                                throw new InvalidOperationException();
                            }
                            break;

                        case WorkQueueOperation.Update:
                            throw new InvalidOperationException();

                        case WorkQueueOperation.Remove:
                            if (!parentCursor.TryRemoveUnspentTxOutput(txOutputKey))
                            {
                                throw new InvalidOperationException();
                            }
                            break;

                        default:
                            throw new InvalidOperationException();
                        }
                });
            });

            unspentTxOutputs.WorkQueue.LinkTo(utxoApplier2, new DataflowLinkOptions {
                PropagateCompletion = true
            });
        }
예제 #3
0
        private void Unmint(IChainStateCursor chainStateCursor, Transaction tx, ChainedHeader chainedHeader)
        {
            // check that transaction exists
            UnspentTx unspentTx;
            if (!chainStateCursor.TryGetUnspentTx(tx.Hash, out unspentTx))
            {
                // missing transaction output
                logger.Warn($"Missing transaction at block {chainedHeader.Height:N0}, {chainedHeader.Hash}, tx {tx.Hash}");
                throw new ValidationException(chainedHeader.Hash);
            }

            //TODO verify blockheight

            // verify all outputs are unspent before unminting
            if (!unspentTx.OutputStates.All(x => x == OutputState.Unspent))
            {
                throw new ValidationException(chainedHeader.Hash);
            }

            // remove the transaction
            if (!chainStateCursor.TryRemoveUnspentTx(tx.Hash))
            {
                throw new ValidationException(chainedHeader.Hash);
            }

            // remove the tx outputs
            for (var outputIndex = 0; outputIndex < tx.Outputs.Length; outputIndex++)
            {
                if (!chainStateCursor.TryRemoveUnspentTxOutput(new TxOutputKey(tx.Hash, (uint)outputIndex)))
                    throw new ValidationException(chainedHeader.Hash);
            }
        }