示例#1
0
        /// <summary>
        /// Signs the given transaction with the given private key.
        /// The result signature will be assigned to all inputs of the transaction.
        /// </summary>
        private static void signTransation(Transaction tx, EllipticCurve.PrivateKey privateKey)
        {
            var sig    = EllipticCurve.Ecdsa.sign(tx.Id, privateKey);
            var sigStr = AddressUtils.TxInSignatureFromSignatureAndPublicKey(sig, privateKey.publicKey());

            for (int i = 0, c = tx.Inputs.Count; i < c; ++i)
            {
                tx.Inputs[i].Signature = sigStr;
            }
        }
示例#2
0
        /// <summary>
        /// Creates a transaction for sending coins from the given wallet to the given address.
        /// </summary>
        /// <param name="senderAddress">Address of the sender wallet.</param>
        /// <param name="recipientAddress">Address of the recipient wallet.</param>
        /// <param name="amountInNekoshi">Amount of nekoshi to send, not including transaction fee.</param>
        /// <param name="privateKey">Private key of the sender wallet.</param>
        /// <returns>Result of the task.</returns>
        /// <remarks>
        /// If the task succeeds, a pending transaction will be added to the mempool.
        /// The application is responsible for broadcasting the pending transaction
        /// to other nodes.
        /// </remarks>
        public SendResult Send(string senderAddress, string recipientAddress, long amountInNekoshi, EllipticCurve.PrivateKey privateKey)
        {
            var addrFromPrivateKey = AddressUtils.AddressFromPrivateKey(privateKey);

            if (senderAddress != addrFromPrivateKey)
            {
                return new SendResult {
                           Error = SendResult.ErrorType.InvalidKey
                }
            }
            ;

            long amountInNekoshiToSend = amountInNekoshi;

            amountInNekoshi += Config.FeeNekoshiPerTx;

            List <UnspentTxOut> unspentTxOutputs = new List <UnspentTxOut>();
            List <TxOut>        pendingTxOutputs = new List <TxOut>();

            getUnspentTxOutputs(senderAddress, unspentTxOutputs, pendingTxOutputs);

            long accumulatedAmount            = 0;
            List <UnspentTxOut> ouputsToSpend = new List <UnspentTxOut>();
            List <TxOut>        changeOutputs = new List <TxOut>();

            for (int i = 0, c = unspentTxOutputs.Count; i < c; ++i)
            {
                var utxo = unspentTxOutputs[i];

                ouputsToSpend.Add(utxo);

                var refTx = transactionDb.GetTransaction(utxo.TxId);
                var txOut = refTx.Outputs[utxo.TxOutIndex];

                long neededAmount = amountInNekoshi - accumulatedAmount;
                if (txOut.AmountInNekoshi > neededAmount)
                {
                    accumulatedAmount = amountInNekoshi;
                    changeOutputs.Add(new TxOut
                    {
                        Address         = senderAddress,
                        AmountInNekoshi = txOut.AmountInNekoshi - neededAmount,
                    });
                }
                else
                {
                    accumulatedAmount += txOut.AmountInNekoshi;
                }

                if (accumulatedAmount >= amountInNekoshi)
                {
                    break;
                }
            }

            if (accumulatedAmount >= amountInNekoshi)
            {
                if (ouputsToSpend.Count > Config.MaxTransactionInputs)
                {
                    return new SendResult {
                               Error = SendResult.ErrorType.TooManyInputs
                    }
                }
                ;

                var tx = new Transaction();
                for (int i = 0, c = ouputsToSpend.Count; i < c; ++i)
                {
                    var unspentTxOut = ouputsToSpend[i];
                    var txIn         = new TxIn
                    {
                        TxId       = unspentTxOut.TxId,
                        TxOutIndex = unspentTxOut.TxOutIndex,
                    };
                    tx.Inputs.Add(txIn);
                }
                changeOutputs.Add(new TxOut
                {
                    Address         = recipientAddress,
                    AmountInNekoshi = amountInNekoshiToSend,
                });
                tx.Outputs.AddRange(changeOutputs);
                tx.Id = tx.GetId();
                signTransation(tx, privateKey);
                transactionDb.AddPendingTransaction(tx);
                return(new SendResult
                {
                    Error = SendResult.ErrorType.None,
                    TxId = tx.Id,
                });
            }
            else
            {
                return(new SendResult {
                    Error = SendResult.ErrorType.Insufficient
                });
            }
        }