public int GetAmount(IEnumerable <UnspentTxOut> unspentTxOuts)
        {
            UnspentTxOut correspondingUnspentTxOut = GetCorrespondingUnspentTxOut(unspentTxOuts);

            if (correspondingUnspentTxOut == null)
            {
                throw new Exception("tried to get amount of a spent or inexisting tx out");
            }

            return(correspondingUnspentTxOut.amount);
        }
Exemple #2
0
        /// <summary>
        /// Adds a new transaction to the database.
        /// </summary>
        /// <param name="tx">The transaction to add.</param>
        /// <param name="blockIndex">Index of the block containing the given transaction.</param>
        /// <param name="positionIndex">Index of the transaction in the block.</param>
        /// <param name="needSave">If true, the database will be saved immediately.</param>
        /// <returns>Index object for the given transaction.</returns>
        /// <remarks>
        /// In scenarios when there are multiple calls to this method,
        /// passing false to <paramref name="needSave"/> and then calling
        /// <see cref="Save"/> in the end would be a more efficient approach.
        /// </remarks>
        public TransactionIndex AddTransaction(Transaction tx, int blockIndex, int positionIndex, bool needSave = true)
        {
            if (_transactions.ContainsKey(tx.Id) || _transactionIndices.ContainsKey(tx.Id))
            {
                throw new InvalidOperationException("Duplicate transaction ID");
            }

            var txIndex = new TransactionIndex
            {
                Id            = tx.Id,
                BlockIndex    = blockIndex,
                PositionIndex = positionIndex,
            };

            _transactionIndices.Add(tx.Id, txIndex);
            _transactions.Add(tx.Id, tx);

            for (int i = 0, c = tx.Inputs.Count; i < c; ++i)
            {
                var txIn = tx.Inputs[i];
                spendTxOut(txIn.TxId, txIn.TxOutIndex);
            }

            for (int i = 0, c = tx.Outputs.Count; i < c; ++i)
            {
                var txOut = tx.Outputs[i];
                var utxo  = new UnspentTxOut
                {
                    TxId       = tx.Id,
                    TxOutIndex = i,
                    Address    = txOut.Address,
                };
                _unspentTxOuts.Add(utxo);
            }

            for (int i = 0, c = _pendingTransactions.Count; i < c; ++i)
            {
                var ptx = _pendingTransactions[i];
                if (ptx.Tx.Id == tx.Id)
                {
                    _pendingTransactions.RemoveAt(i);
                    break;
                }
            }

            if (needSave)
            {
                Save();
            }

            return(txIndex);
        }
        public bool IsValid(string txId, IEnumerable <UnspentTxOut> unspentTxOuts)
        {
            UnspentTxOut referencedUnspentTxOut = unspentTxOuts.FirstOrDefault(uto => uto.txId == txOutTxId & uto.txOutIndex == txOutIndex);

            if (referencedUnspentTxOut == null)
            {
                Debug.LogError("Referenced TxOut not found : " + ToString());
                return(false);
            }

            string address = referencedUnspentTxOut.address;

            return(Cryptography.VerifySignature(signature, txId, address));
        }
Exemple #4
0
        /// <summary>
        /// Removes the given transaction from the database.
        /// </summary>
        /// <param name="tx">The transaction to remove.</param>
        /// <param name="needSave">If true, the database will be saved immediately.</param>
        /// <returns>True if the transaction exists and can be removed.</returns>
        /// <remarks>
        /// In scenarios when there are multiple calls to this method,
        /// passing false to <paramref name="needSave"/> and then calling
        /// <see cref="Save"/> in the end would be a more efficient approach.
        /// </remarks>
        public bool RemoveTransaction(Transaction tx, bool needSave = true)
        {
            if (_transactionIndices.ContainsKey(tx.Id) is false)
            {
                return(false);
            }

            _transactionIndices.Remove(tx.Id);
            _transactions.Remove(tx.Id);

            // Return the TxO's that this Tx has consumed
            for (int i = 0, c = tx.Inputs.Count; i < c; ++i)
            {
                var txIn  = tx.Inputs[i];
                var refTx = GetTransaction(txIn.TxId);
                if (refTx == null)
                {
                    continue;
                }

                var refTxOut = refTx.Outputs[txIn.TxOutIndex];
                var utxo     = new UnspentTxOut
                {
                    TxId       = refTx.Id,
                    TxOutIndex = txIn.TxOutIndex,
                    Address    = refTxOut.Address,
                };
                _unspentTxOuts.Add(utxo);
            }

            // Remove the TxO's that this Tx has produced
            for (int i = 0, c = _unspentTxOuts.Count; i < c; ++i)
            {
                var utxo = _unspentTxOuts[i];
                if (utxo.TxId == tx.Id)
                {
                    _unspentTxOuts.RemoveAt(i);
                    --i;
                    --c;
                }
            }

            if (needSave)
            {
                Save();
            }

            return(true);
        }
        public string ComputeSignature(string txId, CspParameters privateKeyCointainer, IEnumerable <UnspentTxOut> unspentTxOuts)
        {
            UnspentTxOut referencedUnspentTxOut = GetCorrespondingUnspentTxOut(unspentTxOuts);

            if (referencedUnspentTxOut == null)
            {
                Debug.LogError("could not find referenced txOut for txIn");
                return(null);
            }

            string referencedAddress = referencedUnspentTxOut.address;

            if (Cryptography.GetPublicKey(privateKeyCointainer) != referencedAddress)
            {
                Debug.LogError("trying to sign an input with private key that doesn't match the address of txIn's unspent txOut");
                return(null);
            }

            return(Cryptography.SignHashWithPrivateKey(privateKeyCointainer, txId));
        }