Exemplo n.º 1
0
 private static void CheckHasInputsAndOutputs(Transaction tx)
 {
     if (tx.Inputs.Length == 0)
     {
         throw new TransactionRuleException("Transaction must have at least one input");
     }
     if (tx.Outputs.Length == 0)
     {
         throw new TransactionRuleException("Transaction must have at least one output");
     }
 }
Exemplo n.º 2
0
        public static bool IsCoinbase(Transaction tx)
        {
            if (tx == null)
                throw new ArgumentNullException(nameof(tx));

            if (tx.Inputs.Length != 1)
                return false;

            var previousOutput = tx.Inputs[0].PreviousOutpoint;
            return previousOutput.Index == uint.MaxValue && previousOutput.Hash.Equals(Blake256Hash.Zero);
        }
Exemplo n.º 3
0
 private static void CheckOutputValueSanity(Transaction tx)
 {
     Amount outputSum = 0;
     int outputIndex = 0;
     foreach (var output in tx.Outputs)
     {
         if (!IsSaneOutputValue(output.Amount))
         {
             throw new TransactionRuleException($"Output value {output.Amount} for output {outputIndex} is outside valid range");
         }
         if (outputSum - MaxOutputValue + output.Amount > 0)
         {
             throw new TransactionRuleException("Total output value exceeds maximum");
         }
         outputSum += output.Amount;
         outputIndex++;
     }
 }
Exemplo n.º 4
0
 private static WalletTransaction.Output[] MarshalCombinedOutputs(Transaction transaction,
     Google.Protobuf.Collections.RepeatedField<TransactionDetails.Types.Output> credits)
 {
     var creditIndex = 0;
     return transaction.Outputs.Select((output, outputIndex) =>
     {
         if (creditIndex < credits.Count && credits[creditIndex].Index == outputIndex)
         {
             var controlledOutput = MarshalControlledOutput(credits[creditIndex], output);
             creditIndex++;
             return controlledOutput;
         }
         else
         {
             return new WalletTransaction.Output.UncontrolledOutput(output.Amount, output.PkScript);
         }
     }).ToArray();
 }
Exemplo n.º 5
0
        public static void CheckSanity(Transaction tx)
        {
            if (tx == null)
                throw new ArgumentNullException(nameof(tx));

            CheckHasInputsAndOutputs(tx);

            // TODO: check serialize size

            CheckOutputValueSanity(tx);

            if (BlockChain.IsCoinbase(tx))
            {
                CheckCoinbaseSignatureScript(tx.Inputs[0]);
            }
            else
            {
                CheckNonCoinbaseInputs(tx);
            }
        }
Exemplo n.º 6
0
 public async Task<Tuple<Transaction, bool>> SignTransactionAsync(string passphrase, Transaction tx)
 {
     var client = new WalletService.WalletServiceClient(_channel);
     var request = new SignTransactionRequest
     {
         Passphrase = ByteString.CopyFromUtf8(passphrase),
         SerializedTransaction = ByteString.CopyFrom(tx.Serialize()),
     };
     var response = await client.SignTransactionAsync(request, cancellationToken: _tokenSource.Token);
     var signedTransaction = Transaction.Deserialize(response.Transaction.ToByteArray());
     var complete = response.UnsignedInputIndexes.Count == 0;
     return Tuple.Create(signedTransaction, complete);
 }
        private async Task<bool> SignTransactionWithPassphrase(string passphrase, Transaction tx, bool publishImmediately)
        {
            Tuple<Transaction, bool> signingResponse;
            var walletClient = App.Current.Synchronizer.WalletRpcClient;
            try
            {
                signingResponse = await walletClient.SignTransactionAsync(passphrase, tx);
            }
            catch (RpcException ex) when (ex.Status.StatusCode == StatusCode.InvalidArgument)
            {
                MessageBox.Show(ex.Status.Detail);
                return false;
            }
            var complete = signingResponse.Item2;
            if (!complete)
            {
                MessageBox.Show("Failed to create transaction input signatures.");
                return false;
            }
            var signedTransaction = signingResponse.Item1;

            if (!publishImmediately)
            {
                MessageBox.Show("Reviewing signed transaction before publishing is not implemented yet.");
                return false;
            }

            await walletClient.PublishTransactionAsync(signedTransaction.Serialize());
            MessageBox.Show("Published transaction.");

            _pendingTransaction = null;
            _unusedChangeScripts.Remove(SelectedAccount.Account);
            PendingOutputs.Clear();
            AddPendingOutput();

            return true;
        }
        private void SetPendingTransaction(Transaction unsignedTransaction, Amount inputAmount, Amount targetOutput)
        {
            var wallet = App.Current.Synchronizer.Wallet;
            if (wallet == null)
                return;

            var actualFee = TransactionFees.ActualFee(unsignedTransaction, inputAmount);
            var totalAccountBalance = wallet.LookupAccountProperties(SelectedAccount.Account).TotalBalance;

            _pendingTransaction = unsignedTransaction;

            EstimatedFee = actualFee;
            EstimatedRemainingBalance = totalAccountBalance - targetOutput - actualFee;
            FinishCreateTransaction.Executable = true;
        }
 private void UnsetPendingTransaction()
 {
     _pendingTransaction = null;
     EstimatedFee = null;
     EstimatedRemainingBalance = null;
     FinishCreateTransaction.Executable = false;
 }
Exemplo n.º 10
0
 public static void SerializeSizes(Transaction tx, int expectedSerializeSize)
 {
     var serializeSize = tx.SerializeSize;
     Assert.Equal(expectedSerializeSize, serializeSize);
 }
Exemplo n.º 11
0
        private static void CheckNonCoinbaseInputs(Transaction tx)
        {
            var seenOutPoints = new HashSet<Transaction.OutPoint>();
            foreach (var input in tx.Inputs)
            {
                if (seenOutPoints.Contains(input.PreviousOutpoint))
                {
                    throw new TransactionRuleException($"Transaction input contains duplicate previous output {input.PreviousOutpoint}");
                }
                seenOutPoints.Add(input.PreviousOutpoint);

                if (input.PreviousOutpoint.IsNull())
                {
                    throw new TransactionRuleException("Non-coinbase transaction may not refer to a null previous output");
                }
            }
        }
Exemplo n.º 12
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");
     }
 }
Exemplo n.º 13
0
 private static WalletTransaction.Output MarshalControlledOutput(TransactionDetails.Types.Output o, Transaction.Output txOutput) =>
     new WalletTransaction.Output.ControlledOutput(txOutput.Amount, new Account(o.Account), o.Internal);
Exemplo n.º 14
0
        private void SetPendingTransaction(Amount totalAccountBalance, Transaction unsignedTransaction, Amount inputAmount, Amount targetOutput)
        {
            var actualFee = TransactionFees.ActualFee(unsignedTransaction, inputAmount);

            _pendingTransaction = unsignedTransaction;

            EstimatedFee = actualFee;
            EstimatedRemainingBalance = totalAccountBalance - targetOutput - actualFee;
            FinishCreateTransaction.Executable = true;
        }