예제 #1
0
        private static void CheckCoinbaseSignatureScript(Transaction.Input coinbaseInput)
        {
            var scriptLength = coinbaseInput.SignatureScript.Length;

            if (scriptLength < BlockChain.MinCoinbaseScriptLength || scriptLength > BlockChain.MaxCoinbaseScriptLength)
            {
                throw new TransactionRuleException($"Coinbase transaction input signature script length {scriptLength} is outside valid range");
            }
        }
        private async Task RecalculatePendingTransaction()
        {
            if (PendingOutputs.Count == 0 || PendingOutputs.Any(x => !x.IsValid))
            {
                UnsetPendingTransaction();
                return;
            }

            var walletClient = App.Current.Synchronizer?.WalletRpcClient;

            var outputs = PendingOutputs.Select(po =>
            {
                var amount = po.OutputAmount;
                var script = po.BuildOutputScript().Script;
                return new Transaction.Output(amount, Transaction.Output.LatestPkScriptVersion, script);
            }).ToArray();

            TransactionAuthor.InputSource inputSource = async targetAmount =>
            {
                var inputs = new Transaction.Input[0];
                // TODO: don't hardcode confs
                var funding = await walletClient.FundTransactionAsync(SelectedAccount.Account, targetAmount, 1);
                if (funding.Item2 >= targetAmount)
                {
                    inputs = funding.Item1.Select(o =>
                        Transaction.Input.CreateFromPrefix(new Transaction.OutPoint(o.TransactionHash, o.OutputIndex, o.Tree),
                                                           TransactionRules.MaxInputSequence)).ToArray();
                }
                return Tuple.Create(funding.Item2, inputs);
            };
            TransactionAuthor.ChangeSource changeSource = async () =>
            {
                // Use cached change script if one has already been generated for this account.
                var selectedAccount = SelectedAccount.Account;
                OutputScript cachedScript;
                if (_unusedChangeScripts.TryGetValue(selectedAccount, out cachedScript))
                    return cachedScript;

                var changeAddress = await walletClient.NextInternalAddressAsync(SelectedAccount.Account);
                var changeScript = Address.Decode(changeAddress).BuildScript();
                _unusedChangeScripts[selectedAccount] = changeScript;
                return changeScript;
            };

            try
            {
                var r = await TransactionAuthor.BuildUnsignedTransaction(outputs, TransactionFees.DefaultFeePerKb, inputSource, changeSource);
                SetPendingTransaction(r.Item1, r.Item2, outputs.Sum(o => o.Amount));
            }
            catch (Exception ex)
            {
                UnsetPendingTransaction();

                // Insufficient funds will need a nicer error displayed somehow.  For now, hide it
                // while disabling the UI to create the transaction.  All other errors are unexpected.
                if (!(ex is InsufficientFundsException)) throw;
            }
        }