Beispiel #1
0
 public bool TryGetTransaction(UInt256 txHash, out UnconfirmedTx unconfirmedTx)
 {
     using (var handle = this.cursorCache.TakeItem())
     {
         var cursor = handle.Item.Item;
         return(cursor.TryGetTransaction(txHash, out unconfirmedTx));
     }
 }
Beispiel #2
0
 public bool TryGetTransaction(UInt256 txHash, out UnconfirmedTx unconfirmedTx)
 {
     using (var handle = this.cursorCache.TakeItem())
     {
         var cursor = handle.Item.Item;
         return cursor.TryGetTransaction(txHash, out unconfirmedTx);
     }
 }
        public bool TryAddTransaction(UnconfirmedTx unconfirmedTx)
        {
            CheckWriteTransaction();

            try
            {
                unconfirmedTxes.Modify(x => x.Add(unconfirmedTx.Hash, unconfirmedTx));

                // update index of txes spending each input's prev tx
                for (var inputIndex = 0; inputIndex < unconfirmedTx.Transaction.Inputs.Length; inputIndex++)
                {
                    var input = unconfirmedTx.Transaction.Inputs[inputIndex];

                    unconfirmedTxesByPrevTxOutputKey.Modify(_ => { });
                    ImmutableDictionary<UInt256, UnconfirmedTx>.Builder unconfirmedTxes;
                    if (unconfirmedTxesByPrevTxOutputKey.Value.TryGetValue(input.PrevTxOutputKey, out unconfirmedTxes))
                        // ensure a copy of the builder is modified or underlying storage will see uncomitted state
                        unconfirmedTxes = unconfirmedTxes.ToImmutable().ToBuilder();
                    else
                        unconfirmedTxes = ImmutableDictionary.CreateBuilder<UInt256, UnconfirmedTx>();

                    unconfirmedTxes.Add(unconfirmedTx.Hash, unconfirmedTx);
                    unconfirmedTxesByPrevTxOutputKey.Value[input.PrevTxOutputKey] = unconfirmedTxes;
                }

                return true;
            }
            catch (ArgumentException)
            {
                return false;
            }
        }
 public bool TryGetTransaction(UInt256 txHash, out UnconfirmedTx unconfimedTx)
 {
     CheckTransaction();
     return unconfirmedTxes.Value.TryGetValue(txHash, out unconfimedTx);
 }
 public UnconfirmedTxAddedEventArgs(UnconfirmedTx unconfirmedTx)
 {
     UnconfirmedTx = unconfirmedTx;
 }
        public bool TryAddTransaction(DecodedTx decodedTx)
        {
            if (ContainsTransaction(decodedTx.Hash))
                // unconfirmed tx already exists
                return false;

            var tx = decodedTx.Transaction;
            UnconfirmedTx unconfirmedTx;

            // allow concurrent transaction adds if underlying storage supports it
            // in either case, lock waits for block add/rollback to finish
            if (storageManager.IsUnconfirmedTxesConcurrent)
                updateLock.EnterReadLock();
            else
                updateLock.EnterWriteLock();
            try
            {
                using (var chainState = coreDaemon.GetChainState())
                {
                    // verify each input is available to spend
                    var prevTxOutputKeys = new HashSet<TxOutputKey>();
                    var prevTxOutputs = ImmutableArray.CreateBuilder<PrevTxOutput>(tx.Inputs.Length);
                    var inputValue = 0UL;
                    for (var inputIndex = 0; inputIndex < tx.Inputs.Length; inputIndex++)
                    {
                        var input = tx.Inputs[inputIndex];

                        if (!prevTxOutputKeys.Add(input.PrevTxOutputKey))
                            // tx double spends one of its own inputs
                            return false;

                        UnspentTx unspentTx;
                        if (!chainState.TryGetUnspentTx(input.PrevTxHash, out unspentTx))
                            // input's prev output does not exist
                            return false;

                        if (input.PrevTxOutputIndex >= unspentTx.OutputStates.Length)
                            // input's prev output does not exist
                            return false;

                        if (unspentTx.OutputStates[(int)input.PrevTxOutputIndex] != OutputState.Unspent)
                            // input's prev output has already been spent
                            return false;

                        TxOutput txOutput;
                        if (!chainState.TryGetUnspentTxOutput(input.PrevTxOutputKey, out txOutput))
                            // input's prev output does not exist
                            return false;

                        var prevTxOutput = new PrevTxOutput(txOutput, unspentTx);
                        prevTxOutputs.Add(prevTxOutput);
                        checked { inputValue += prevTxOutput.Value; }
                    }

                    var outputValue = 0UL;
                    for (var outputIndex = 0; outputIndex < tx.Outputs.Length; outputIndex++)
                    {
                        var output = tx.Outputs[outputIndex];
                        checked { outputValue += output.Value; }
                    }

                    if (outputValue > inputValue)
                        // transaction spends more than its inputs
                        return false;

                    // validation passed

                    // create the unconfirmed tx
                    var blockTx = new DecodedBlockTx(-1, decodedTx);
                    var validatableTx = new ValidatableTx(blockTx, null, prevTxOutputs.ToImmutable());
                    unconfirmedTx = new UnconfirmedTx(validatableTx, DateTimeOffset.Now);

                    // add the unconfirmed tx
                    using (var handle = storageManager.OpenUnconfirmedTxesCursor())
                    {
                        var unconfirmedTxesCursor = handle.Item;

                        unconfirmedTxesCursor.BeginTransaction();
                        if (unconfirmedTxesCursor.TryAddTransaction(unconfirmedTx))
                        {
                            unconfirmedTxesCursor.CommitTransaction();
                        }
                        else
                            // unconfirmed tx already exists
                            return false;
                    }
                }
            }
            finally
            {
                if (storageManager.IsUnconfirmedTxesConcurrent)
                    updateLock.ExitReadLock();
                else
                    updateLock.ExitWriteLock();
            }

            UnconfirmedTxAdded?.Invoke(this, new UnconfirmedTxAddedEventArgs(unconfirmedTx));
            return true;
        }
        public bool TryGetTransaction(UInt256 txHash, out UnconfirmedTx unconfirmedTx)
        {
            using (var handle = storageManager.OpenUnconfirmedTxesCursor())
            {
                var unconfirmedTxesCursor = handle.Item;
                unconfirmedTxesCursor.BeginTransaction(readOnly: true);

                return unconfirmedTxesCursor.TryGetTransaction(txHash, out unconfirmedTx);
            }
        }