Example #1
0
        /// <summary>
        /// Adds the given pending transactions to the transaction database.
        /// </summary>
        /// <returns>Result of the task.</returns>
        public AddPendingTransactionsResult AddPendingTransactions(IList <PendingTransaction> transactions)
        {
            if (transactions.Count == 0)
            {
                return(AddPendingTransactionsResult.Empty);
            }

            for (int i = 0, c = transactions.Count; i < c; ++i)
            {
                var ptx = transactions[i];
                var tx  = ptx.Tx;

                if (tx.Id != tx.GetId())
                {
                    return(AddPendingTransactionsResult.HardRejected);
                }

                if (transactionDb.HasTransaction(tx.Id))
                {
                    continue;
                }

                if (transactionDb.GetPendingTransaction(tx.Id) != null)
                {
                    continue;
                }

                long totalInAmount  = 0;
                long totalOutAmount = 0;
                bool isIgnored      = false;

                for (int j = 0, n = tx.Inputs.Count; j < n; ++j)
                {
                    var txIn = tx.Inputs[j];

                    if (string.IsNullOrEmpty(txIn.TxId) ||
                        txIn.TxOutIndex < 0 ||
                        string.IsNullOrEmpty(txIn.Signature))
                    {
                        return(AddPendingTransactionsResult.HardRejected);
                    }

                    var refTx = transactionDb.GetTransaction(txIn.TxId);
                    if (refTx is null)
                    {
                        isIgnored = true;
                        break;
                    }

                    if (txIn.TxOutIndex >= refTx.Outputs.Count)
                    {
                        return(AddPendingTransactionsResult.HardRejected);
                    }

                    var refTxOut = refTx.Outputs[txIn.TxOutIndex];

                    var(signature, publicKey) = AddressUtils.SignatureAndPublicKeyFromTxInSignature(txIn.Signature);
                    if (AddressUtils.AddressFromPublicKey(publicKey) != refTxOut.Address)
                    {
                        return(AddPendingTransactionsResult.HardRejected);
                    }

                    if (EllipticCurve.Ecdsa.verify(tx.Id, signature, publicKey) == false)
                    {
                        return(AddPendingTransactionsResult.HardRejected);
                    }

                    totalInAmount += refTxOut.AmountInNekoshi;
                }

                if (isIgnored)
                {
                    continue;
                }

                for (int j = 0, n = tx.Outputs.Count; j < n; ++j)
                {
                    var txOut = tx.Outputs[j];

                    if (string.IsNullOrEmpty(txOut.Address) ||
                        txOut.AmountInNekoshi <= 0)
                    {
                        return(AddPendingTransactionsResult.HardRejected);
                    }

                    totalOutAmount += txOut.AmountInNekoshi;
                }

                if (totalInAmount != totalOutAmount + Config.FeeNekoshiPerTx)
                {
                    return(AddPendingTransactionsResult.HardRejected);
                }
            }

            for (int i = 0, c = transactions.Count; i < c; ++i)
            {
                var ptx = transactions[i];
                transactionDb.AddPendingTransaction(ptx, needSave: false);
            }

            transactionDb.Save();

            return(AddPendingTransactionsResult.Added);
        }