private void Mint(IChainStateCursor chainStateCursor, Transaction tx, int txIndex, ChainedHeader chainedHeader) { // add transaction to the utxo var unspentTx = new UnspentTx(tx.Hash, chainedHeader.Height, txIndex, tx.Version, tx.IsCoinbase, tx.Outputs.Length, OutputState.Unspent); if (!chainStateCursor.TryAddUnspentTx(unspentTx)) { // duplicate transaction logger.Warn($"Duplicate transaction at block {chainedHeader.Height:N0}, {chainedHeader.Hash}, coinbase"); throw new ValidationException(chainedHeader.Hash); } // add transaction outputs to the utxo for (var outputIndex = 0; outputIndex < tx.Outputs.Length; outputIndex++) { var output = tx.Outputs[outputIndex]; if (!chainStateCursor.TryAddUnspentTxOutput(new TxOutputKey(tx.Hash, (uint)outputIndex), output)) { throw new ValidationException(chainedHeader.Hash); } } }
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 }); }
private void Mint(IChainStateCursor chainStateCursor, Transaction tx, int txIndex, ChainedHeader chainedHeader) { // add transaction to the utxo var unspentTx = new UnspentTx(tx.Hash, chainedHeader.Height, txIndex, tx.Version, tx.IsCoinbase, tx.Outputs.Length, OutputState.Unspent); if (!chainStateCursor.TryAddUnspentTx(unspentTx)) { // duplicate transaction logger.Warn($"Duplicate transaction at block {chainedHeader.Height:N0}, {chainedHeader.Hash}, coinbase"); throw new ValidationException(chainedHeader.Hash); } // add transaction outputs to the utxo for (var outputIndex = 0; outputIndex < tx.Outputs.Length; outputIndex++) { var output = tx.Outputs[outputIndex]; if (!chainStateCursor.TryAddUnspentTxOutput(new TxOutputKey(tx.Hash, (uint)outputIndex), output)) throw new ValidationException(chainedHeader.Hash); } }