Exemplo n.º 1
0
        public void Actual_Fee_Without_OpReturnData_Should_Be_Less_Than_Actual_Fee_With_Costly_OpReturnData()
        {
            (Wallet wallet, (ExtKey ExtKey, string ExtPubKey)accountKeys, (PubKey PubKey, BitcoinPubKeyAddress Address)destinationKeys, TransactionData addressTransaction, WalletTransactionHandler walletTransactionHandler, WalletAccountReference walletReference) = this.SetupWallet();

            // Context with OpReturnData
            TransactionBuildContext contextWithOpReturn = CreateContext(walletReference, "password", destinationKeys.PubKey.ScriptPubKey, new Money(7500), FeeType.Low, 0, this.CostlyOpReturnData);

            walletTransactionHandler.BuildTransaction(contextWithOpReturn);

            // Context without OpReturnData
            TransactionBuildContext contextWithoutOpReturn = CreateContext(walletReference, "password", destinationKeys.PubKey.ScriptPubKey, new Money(7500), FeeType.Low, 0, null);

            walletTransactionHandler.BuildTransaction(contextWithoutOpReturn);

            contextWithoutOpReturn.TransactionFee.Should().NotBe(contextWithOpReturn.TransactionFee);
            contextWithoutOpReturn.TransactionFee.Satoshi.Should().BeLessThan(contextWithOpReturn.TransactionFee.Satoshi);
        }
        /// <summary>
        /// Adjusted to allow smart contract transactions with zero value through.
        /// </summary>
        protected override void AddRecipients(TransactionBuildContext context)
        {
            if (context.Recipients.Any(recipient => recipient.Amount == Money.Zero && !recipient.ScriptPubKey.IsSmartContractExec()))
            {
                throw new WalletException("No amount specified.");
            }

            if (context.Recipients.Any(a => a.SubtractFeeFromAmount))
            {
                throw new NotImplementedException("Substracting the fee from the recipient is not supported yet.");
            }

            foreach (Recipient recipient in context.Recipients)
            {
                context.TransactionBuilder.Send(recipient.ScriptPubKey, recipient.Amount);
            }
        }
Exemplo n.º 3
0
        /// <inheritdoc />
        public Transaction BuildWithdrawalTransaction(uint256 depositId, uint blockTime, Recipient recipient)
        {
            try
            {
                this.logger.LogInformation("BuildDeterministicTransaction depositId(opReturnData)={0} recipient.ScriptPubKey={1} recipient.Amount={2}", depositId, recipient.ScriptPubKey, recipient.Amount);

                // Build the multisig transaction template.
                uint256 opReturnData    = depositId;
                string  walletPassword  = this.federationWalletManager.Secret.WalletPassword;
                bool    sign            = (walletPassword ?? "") != "";
                var     multiSigContext = new TransactionBuildContext(new[] { recipient }.ToList(), opReturnData: opReturnData.ToBytes())
                {
                    OrderCoinsDeterministic = true,
                    TransactionFee          = this.federationGatewaySettings.TransactionFee,
                    MinConfirmations        = this.federationGatewaySettings.MinCoinMaturity,
                    Shuffle        = false,
                    IgnoreVerify   = true,
                    WalletPassword = walletPassword,
                    Sign           = sign,
                };

                Transaction transaction = this.federationWalletTransactionHandler.BuildTransaction(multiSigContext);

                // Build the transaction.
                if (this.network.Consensus.IsProofOfStake)
                {
                    transaction.Time = blockTime;

                    if (sign)
                    {
                        transaction = multiSigContext.TransactionBuilder.SignTransaction(transaction);
                    }
                }

                this.logger.LogInformation("transaction = {0}", transaction.ToString(this.network, RawFormat.BlockExplorer));

                return(transaction);
            }
            catch (Exception error)
            {
                this.logger.LogError("Could not create transaction for deposit {0}: {1}", depositId, error.Message);
            }

            this.logger.LogTrace("(-)[FAIL]");
            return(null);
        }
Exemplo n.º 4
0
        /// <inheritdoc />
        public Transaction BuildTransaction(TransactionBuildContext context)
        {
            this.InitializeTransactionBuilder(context);

            if (context.Shuffle)
            {
                context.TransactionBuilder.Shuffle();
            }

            // build transaction
            context.Transaction = context.TransactionBuilder.BuildTransaction(context.Sign);

            // If this is a multisig transaction, then by definition we only (usually) possess one of the keys
            // and can therefore not immediately construct a transaction that passes verification
            if (!context.IgnoreVerify)
            {
                if (!context.TransactionBuilder.Verify(context.Transaction, out TransactionPolicyError[] errors))
        public void Actual_Fee_Without_OpReturnData_Should_Be_Less_Than_Actual_Fee_With_Costly_OpReturnData()
        {
            WalletTransactionHandlerTestContext testContext = SetupWallet();

            // Context with OpReturnData
            TransactionBuildContext contextWithOpReturn = CreateContext(this.Network, testContext.WalletReference, "password", testContext.DestinationKeys.PubKey.ScriptPubKey, new Money(7500), FeeType.Low, 0, this.CostlyOpReturnData);

            testContext.WalletTransactionHandler.BuildTransaction(contextWithOpReturn);

            // Context without OpReturnData
            TransactionBuildContext contextWithoutOpReturn = CreateContext(this.Network, testContext.WalletReference, "password", testContext.DestinationKeys.PubKey.ScriptPubKey, new Money(7500), FeeType.Low, 0, null);

            testContext.WalletTransactionHandler.BuildTransaction(contextWithoutOpReturn);

            contextWithoutOpReturn.TransactionFee.Should().NotBe(contextWithOpReturn.TransactionFee);
            contextWithoutOpReturn.TransactionFee.Satoshi.Should().BeLessThan(contextWithOpReturn.TransactionFee.Satoshi);
        }
        public Task <CreateTransactionResponse> GetTransferAllTransaction(BitcoinAddress @from, BitcoinAddress to, Guid transactionId)
        {
            return(Retry.Try(async() =>
            {
                var context = new TransactionBuildContext(_connectionParams.Network, _pregeneratedOutputsQueueFactory);

                return await context.Build(async() =>
                {
                    var builder = new TransactionBuilder();
                    var uncoloredCoins = (await _bitcoinOutputsService.GetUncoloredUnspentOutputs(from.ToString())).ToList();
                    var coloredCoins = (await _bitcoinOutputsService.GetColoredUnspentOutputs(from.ToString())).ToList();

                    if (uncoloredCoins.Count == 0 && coloredCoins.Count == 0)
                    {
                        throw new BackendException("Address has no unspent outputs", ErrorCode.NoCoinsFound);
                    }

                    if (uncoloredCoins.Count > 0)
                    {
                        _transactionBuildHelper.SendWithChange(builder, context, uncoloredCoins, to, uncoloredCoins.Sum(o => o.TxOut.Value), from);
                    }
                    foreach (var assetGroup in coloredCoins.GroupBy(o => o.AssetId))
                    {
                        var sum = new AssetMoney(assetGroup.Key);
                        foreach (var coloredCoin in assetGroup)
                        {
                            sum += coloredCoin.Amount;
                        }

                        _transactionBuildHelper.SendAssetWithChange(builder, context, assetGroup.ToList(), to, sum, from);
                    }
                    await _transactionBuildHelper.AddFee(builder, context);

                    var buildedTransaction = builder.BuildTransaction(true);

                    await SaveSpentOutputs(transactionId, buildedTransaction);

                    await _signRequestRepository.InsertTransactionId(transactionId);

                    await SaveNewOutputs(transactionId, buildedTransaction, context);

                    return new CreateTransactionResponse(buildedTransaction.ToHex(), transactionId);
                });
            }, exception => (exception as BackendException)?.Code == ErrorCode.TransactionConcurrentInputsProblem, 3, _log));
        }
        public Task <CreateTransactionResponse> GetIssueTransaction(BitcoinAddress bitcoinAddres, decimal amount, IAsset asset, Guid transactionId)
        {
            return(Retry.Try(async() =>
            {
                var context = new TransactionBuildContext(_connectionParams.Network, _pregeneratedOutputsQueueFactory);

                return await context.Build(async() =>
                {
                    var builder = new TransactionBuilder();
                    var queue = _pregeneratedOutputsQueueFactory.Create(asset.BlockChainAssetId);

                    var coin = await queue.DequeueCoin();

                    try
                    {
                        var issueCoin = new IssuanceCoin(coin)
                        {
                            DefinitionUrl = new Uri(asset.DefinitionUrl)
                        };

                        var assetId = new BitcoinAssetId(asset.BlockChainAssetId, _connectionParams.Network).AssetId;

                        builder.AddCoins(issueCoin)
                        .IssueAsset(bitcoinAddres, new AssetMoney(assetId, amount, asset.MultiplierPower));
                        context.IssueAsset(assetId);

                        await _transactionBuildHelper.AddFee(builder, context);

                        var buildedTransaction = builder.BuildTransaction(true);

                        await SaveSpentOutputs(transactionId, buildedTransaction);

                        await SaveNewOutputs(transactionId, buildedTransaction, context);

                        return new CreateTransactionResponse(buildedTransaction.ToHex(), transactionId);
                    }
                    catch (Exception)
                    {
                        await queue.EnqueueOutputs(coin);
                        throw;
                    }
                });
            }, exception => (exception as BackendException)?.Code == ErrorCode.TransactionConcurrentInputsProblem, 3, _log));
        }
Exemplo n.º 8
0
        public void SendAssetWithChange(TransactionBuilder builder, TransactionBuildContext context, List <ColoredCoin> coins, IDestination destination, AssetMoney amount,
                                        IDestination changeDestination)
        {
            if (amount.Quantity <= 0)
            {
                throw new BackendException("Amount can't be less or equal to zero", ErrorCode.BadInputParameter);
            }

            Action throwError = () =>
            {
                throw new BackendException($"The sum of total applicable outputs is less than the required: {amount.Quantity} {amount.Id}.", ErrorCode.NotEnoughAssetAvailable);
            };

            var selectedCoins = OpenAssetsHelper.CoinSelect(coins, amount);

            if (selectedCoins == null)
            {
                throwError();
            }

            var orderedCounts = selectedCoins.Cast <ColoredCoin>().OrderBy(o => o.Amount).ToList();
            var sendAmount    = new AssetMoney(amount.Id);
            var cnt           = 0;

            while (sendAmount < amount && cnt < orderedCounts.Count)
            {
                sendAmount += orderedCounts[cnt].Amount;
                cnt++;
            }

            if (sendAmount < amount)
            {
                throwError();
            }

            builder.AddCoins(orderedCounts.Take(cnt));
            context.AddCoins(orderedCounts.Take(cnt));
            builder.SendAsset(destination, amount);

            if ((sendAmount - amount).Quantity > 0)
            {
                builder.SendAsset(changeDestination, sendAmount - amount);
            }
        }
Exemplo n.º 9
0
        public async Task <decimal> SendWithChange(TransactionBuilder builder, TransactionBuildContext context, List <ICoin> coins, IDestination destination, Money amount, IDestination changeDestination, bool addDust = true)
        {
            if (amount.Satoshi <= 0)
            {
                throw new BackendException("Amount can't be less or equal to zero", ErrorCode.BadInputParameter);
            }

            Action throwError = () =>
            {
                throw new BackendException($"The sum of total applicable outputs is less than the required: {amount.Satoshi} satoshis.", ErrorCode.NotEnoughBitcoinAvailable);
            };

            var selectedCoins = OpenAssetsHelper.CoinSelect(coins, amount);

            if (selectedCoins == null)
            {
                throwError();
            }

            var orderedCoins = selectedCoins.OrderBy(o => o.Amount).ToList();
            var sendAmount   = Money.Zero;
            var cnt          = 0;

            while (sendAmount < amount && cnt < orderedCoins.Count)
            {
                sendAmount += orderedCoins[cnt].TxOut.Value;
                cnt++;
            }
            if (sendAmount < amount)
            {
                throwError();
            }

            context.AddCoins(orderedCoins.Take(cnt));
            builder.AddCoins(orderedCoins.Take(cnt));

            var sent = await Send(builder, context, destination, amount, addDust);

            if (sendAmount - amount > 0)
            {
                await Send(builder, context, changeDestination, sendAmount - amount, addDust);
            }
            return(sent);
        }
        public IActionResult BuildTransaction([FromBody] BuildTransactionRequest request)
        {
            Guard.NotNull(request, nameof(request));

            // checks the request is valid
            if (!this.ModelState.IsValid)
            {
                var errors = this.ModelState.Values.SelectMany(e => e.Errors.Select(m => m.ErrorMessage));
                return(ErrorHelpers.BuildErrorResponse(HttpStatusCode.BadRequest, "Formatting error", string.Join(Environment.NewLine, errors)));
            }
            var destination = BitcoinAddress.Create(request.DestinationAddress, this.network).ScriptPubKey;

            try
            {
                var context = new TransactionBuildContext(
                    new WalletAccountReference(request.WalletName, request.AccountName),
                    new[] { new Recipient {
                                Amount = request.Amount, ScriptPubKey = destination
                            } }.ToList(),
                    request.Password)
                {
                    FeeType          = FeeParser.Parse(request.FeeType),
                    MinConfirmations = request.AllowUnconfirmed ? 0 : 1,
                    Shuffle          = true
                };

                var transactionResult = this.walletTransactionHandler.BuildTransaction(context);

                var model = new WalletBuildTransactionModel
                {
                    Hex           = transactionResult.ToHex(),
                    Fee           = context.TransactionFee,
                    TransactionId = transactionResult.GetHash()
                };

                return(this.Json(model));
            }
            catch (Exception e)
            {
                this.logger.LogError("Exception occurred: {0}", e.ToString());
                return(ErrorHelpers.BuildErrorResponse(HttpStatusCode.BadRequest, e.Message, e.ToString()));
            }
        }
        public async Task SpendCommitmemtByMultisig(ICommitment commitment, ICoin spendingCoin, string destination)
        {
            TransactionBuildContext context = new TransactionBuildContext(_connectionParams.Network, _pregeneratedOutputsQueueFactory);

            var destinationAddress = BitcoinAddress.Create(destination);

            await context.Build(async() =>
            {
                TransactionBuilder builder = new TransactionBuilder();
                builder.AddCoins(spendingCoin);
                if (OpenAssetsHelper.IsBitcoin(commitment.AssetId))
                {
                    builder.Send(destinationAddress, spendingCoin.Amount);
                }
                else
                {
                    builder.SendAsset(destinationAddress, ((ColoredCoin)spendingCoin).Amount);
                }
                await _transactionBuildHelper.AddFee(builder, context);

                var tr = builder.BuildTransaction(false);

                var scriptParams = new OffchainScriptParams
                {
                    IsMultisig   = true,
                    RedeemScript = commitment.LockedScript.ToScript().ToBytes(),
                    Pushes       = new[] { new byte[0], new byte[0], new byte[0] }
                };

                tr.Inputs[0].ScriptSig = OffchainScriptCommitmentTemplate.GenerateScriptSig(scriptParams);

                var signed = await _signatureApiProvider.SignTransaction(tr.ToHex());

                var signedTr = new Transaction(signed);
                var id       = Guid.NewGuid();
                await _rpcBitcoinClient.BroadcastTransaction(signedTr, id);

                await _lykkeTransactionBuilderService.SaveSpentOutputs(id, signedTr);

                return(Task.CompletedTask);
            });
        }
Exemplo n.º 12
0
        public IActionResult BuildTransaction([FromBody] BuildTransactionRequest request)
        {
            Guard.NotNull(request, nameof(request));

            // checks the request is valid
            if (!this.ModelState.IsValid)
            {
                return(BuildErrorResponse(this.ModelState));
            }

            try
            {
                var destination = BitcoinAddress.Create(request.DestinationAddress, this.network).ScriptPubKey;
                var context     = new TransactionBuildContext(
                    new WalletAccountReference(request.WalletName, request.AccountName),
                    new[] { new Recipient {
                                Amount = request.Amount, ScriptPubKey = destination
                            } }.ToList(),
                    request.Password)
                {
                    FeeType          = FeeParser.Parse(request.FeeType),
                    MinConfirmations = request.AllowUnconfirmed ? 0 : 1,
                    Shuffle          = request.ShuffleOutputs ?? true // We shuffle transaction outputs by default as it's better for anonymity.
                };

                var transactionResult = this.walletTransactionHandler.BuildTransaction(context);

                var model = new WalletBuildTransactionModel
                {
                    Hex           = transactionResult.ToHex(),
                    Fee           = context.TransactionFee,
                    TransactionId = transactionResult.GetHash()
                };

                return(this.Json(model));
            }
            catch (Exception e)
            {
                this.logger.LogError("Exception occurred: {0}", e.ToString());
                return(ErrorHelpers.BuildErrorResponse(HttpStatusCode.BadRequest, e.Message, e.ToString()));
            }
        }
        private async Task TransferOneDirection(TransactionBuilder builder, TransactionBuildContext context,
                                                BitcoinAddress @from, decimal amount, IAsset asset, BitcoinAddress to)
        {
            var fromStr = from.ToString();

            if (OpenAssetsHelper.IsBitcoin(asset.Id))
            {
                var coins = (await _bitcoinOutputsService.GetUncoloredUnspentOutputs(fromStr)).ToList();
                _transactionBuildHelper.SendWithChange(builder, context, coins, to, new Money(amount, MoneyUnit.BTC),
                                                       from);
            }
            else
            {
                var assetIdObj  = new BitcoinAssetId(asset.BlockChainAssetId, _connectionParams.Network).AssetId;
                var assetAmount = new AssetMoney(assetIdObj, amount, asset.MultiplierPower);

                var coins = (await _bitcoinOutputsService.GetColoredUnspentOutputs(fromStr, assetIdObj)).ToList();
                _transactionBuildHelper.SendAssetWithChange(builder, context, coins, to, assetAmount, @from);
            }
        }
        private void a_nulldata_transaction()
        {
            var transactionBuildContext = new TransactionBuildContext(
                this.sendingWalletAccountReference,
                new List <Recipient>()
            {
                new Recipient()
                {
                    Amount = this.transferAmount, ScriptPubKey = this.receiverAddress.ScriptPubKey
                }
            },
                this.password, this.opReturnContent)
            {
                MinConfirmations = 2
            };

            this.transaction = this.senderNode.FullNode.WalletTransactionHandler().BuildTransaction(transactionBuildContext);

            this.transaction.Outputs.Single(t => t.ScriptPubKey.IsUnspendable).Value.Should().Be(Money.Zero);
        }
        /// <summary>
        /// The initialization of the builder is overridden as smart contracts calls allow dust and does not group
        /// inputs by ScriptPubKey.
        /// </summary>
        protected override void InitializeTransactionBuilder(TransactionBuildContext context)
        {
            Guard.NotNull(context, nameof(context));
            Guard.NotNull(context.Recipients, nameof(context.Recipients));
            Guard.NotNull(context.AccountReference, nameof(context.AccountReference));

            context.TransactionBuilder.CoinSelector = new DefaultCoinSelector
            {
                GroupByScriptPubKey = false
            };

            context.TransactionBuilder.DustPrevention            = false;
            context.TransactionBuilder.StandardTransactionPolicy = this.TransactionPolicy;

            this.AddRecipients(context);
            this.AddOpReturnOutput(context);
            this.AddCoins(context);
            this.FindChangeAddress(context);
            this.AddFee(context);
        }
Exemplo n.º 16
0
        /// <summary>
        /// Send a normal transaction.
        /// </summary>
        public WalletSendTransactionModel SendTransaction(Script scriptPubKey, Money amount)
        {
            var txBuildContext = new TransactionBuildContext(this.chain.Network)
            {
                AccountReference = new WalletAccountReference(this.WalletName, this.AccountName),
                MinConfirmations = 1,
                FeeType          = FeeType.Medium,
                WalletPassword   = Password,
                Recipients       = new[] { new Recipient {
                                               Amount = amount, ScriptPubKey = scriptPubKey
                                           } }.ToList()
            };

            Transaction trx = (this.CoreNode.FullNode.NodeService <IWalletTransactionHandler>() as SmartContractWalletTransactionHandler).BuildTransaction(txBuildContext);

            // Broadcast to the other node.
            JsonResult response = (JsonResult)this.smartContractWalletController.SendTransaction(new SendTransactionRequest(trx.ToHex()));

            return((WalletSendTransactionModel)response.Value);
        }
Exemplo n.º 17
0
        private TransactionBuildContext GetOfflineWithdrawalBuildContext(string receivingAddress, string walletName, string accountName, Money amount, Money feeAmount, bool subtractFeeFromAmount)
        {
            // We presume that the amount given by the user is accurate and optimistically pass it to the build context.
            var recipient = new List <Recipient>()
            {
                new Recipient()
                {
                    Amount = amount, ScriptPubKey = BitcoinAddress.Create(receivingAddress, this.network).ScriptPubKey, SubtractFeeFromAmount = subtractFeeFromAmount
                }
            };

            var hotAccountReference = new WalletAccountReference(walletName, accountName);

            // As a simplification, the change address is defaulted to be the same cold staking script the UTXOs originate from.
            UnspentOutputReference coldStakingUtxo = this.GetSpendableTransactionsInAccount(hotAccountReference, 0).FirstOrDefault();

            if (coldStakingUtxo == null)
            {
                throw new WalletException("No unspent transactions found in cold staking hot account.");
            }

            var context = new TransactionBuildContext(this.network)
            {
                AccountReference = hotAccountReference,
                TransactionFee   = feeAmount,
                MinConfirmations = 0,
                Shuffle          = true,                                     // We shuffle transaction outputs by default as it's better for anonymity.
                Recipients       = recipient,
                ChangeScript     = coldStakingUtxo.Transaction.ScriptPubKey, // We specifically use this instead of ChangeAddress.

                Sign = false
            };

            // As we don't actually know when the signed offline transaction will be broadcast, give it the highest chance of success if no fee was specified.
            if (context.TransactionFee == null)
            {
                context.FeeType = FeeType.High;
            }

            return(context);
        }
Exemplo n.º 18
0
        public void a_real_transaction()
        {
            var transactionBuildContext = new TransactionBuildContext(
                this.miningWalletAccountReference,
                new List <Recipient>()
            {
                new Recipient()
                {
                    Amount = this.transferAmount, ScriptPubKey = this.receiverAddress.ScriptPubKey
                }
            },
                this.password)
            {
                MinConfirmations = 2
            };

            this.transaction = this.node.FullNode.WalletTransactionHandler().BuildTransaction(transactionBuildContext);

            this.node.FullNode.NodeService <WalletController>()
            .SendTransaction(new SendTransactionRequest(this.transaction.ToHex()));
        }
        private void node2_sends_funds_to_node1_FROM_fifty_addresses()
        {
            HdAddress sendToNodeOne = this.firstNode.FullNode.WalletManager().GetUnusedAddress(new WalletAccountReference(WalletName, WalletAccountName));

            // Send 49 coins to node1:
            this.transactionBuildContext = new TransactionBuildContext(this.firstNode.FullNode.Network)
            {
                AccountReference = new WalletAccountReference(WalletName, WalletAccountName),
                WalletPassword   = WalletPassword,
                Recipients       = new[] { new Recipient {
                                               Amount = Money.Coins(50) - Money.COIN, ScriptPubKey = sendToNodeOne.ScriptPubKey
                                           } }.ToList()
            };

            Transaction transaction = this.secondNode.FullNode.WalletTransactionHandler().BuildTransaction(this.transactionBuildContext);

            transaction.Inputs.Count.Should().Be(50);

            this.secondNode.FullNode.NodeService <WalletController>().SendTransaction(new SendTransactionRequest(transaction.ToHex()));
            TestHelper.AreNodesSynced(this.firstNode, this.secondNode);
        }
Exemplo n.º 20
0
        public async Task AddFeeWithoutChange(Transaction tr, TransactionBuildContext context, int maxCoins = int.MaxValue)
        {
            Money fee            = Money.Zero;
            var   providedAmount = Money.Zero;
            var   queue          = _pregeneratedOutputsQueueFactory.CreateFeeQueue();
            int   count          = 0;

            do
            {
                var feeInput = await queue.DequeueCoin();

                context.AddCoins(true, feeInput);
                count++;
                tr.Inputs.Add(new TxIn
                {
                    PrevOut = feeInput.Outpoint
                });
                providedAmount += feeInput.Amount;
                fee             = await _feeProvider.CalcFeeForTransaction(tr);
            } while (fee > providedAmount && count < maxCoins);
        }
Exemplo n.º 21
0
        private void a_real_transaction()
        {
            var transactionBuildContext = new TransactionBuildContext(this.node.FullNode.Network)
            {
                AccountReference = this.miningWalletAccountReference,
                MinConfirmations = (int)this.node.FullNode.Network.Consensus.CoinbaseMaturity,
                WalletPassword   = password,
                Recipients       = new List <Recipient>()
                {
                    new Recipient()
                    {
                        Amount = this.transferAmount, ScriptPubKey = this.receiverAddress.ScriptPubKey
                    }
                }
            };

            this.transaction = this.node.FullNode.WalletTransactionHandler().BuildTransaction(transactionBuildContext);

            this.node.FullNode.NodeService <WalletController>()
            .SendTransaction(new SendTransactionRequest(this.transaction.ToHex()));
        }
        public static JoinFederationRequestResult BuildTransaction(IWalletTransactionHandler walletTransactionHandler, Network network, JoinFederationRequest request, JoinFederationRequestEncoder encoder, string walletName, string walletAccount, string walletPassword)
        {
            byte[] encodedVotingRequest = encoder.Encode(request);
            var    votingOutputScript   = new Script(OpcodeType.OP_RETURN, Op.GetPushOp(encodedVotingRequest));

            var context = new TransactionBuildContext(network)
            {
                AccountReference = new WalletAccountReference(walletName, walletAccount),
                MinConfirmations = 0,
                FeeType          = FeeType.High,
                WalletPassword   = walletPassword,
                Recipients       = new[] { new Recipient {
                                               Amount = new Money(VotingRequestTransferAmount, MoneyUnit.BTC), ScriptPubKey = votingOutputScript
                                           } }.ToList()
            };

            Transaction transaction = walletTransactionHandler.BuildTransaction(context);

            Guard.Assert(IsVotingRequestTransaction(transaction, encoder));

            if (context.TransactionBuilder.Verify(transaction, out TransactionPolicyError[] errors))
        private void node2_sends_funds_to_node1_FROM_fifty_addresses()
        {
            HdAddress sendToNodeOne = this.nodes[NodeOne].FullNode.WalletManager().GetUnusedAddress(new WalletAccountReference(WalletName, WalletAccountName));

            this.transactionBuildContext = new TransactionBuildContext(this.nodes[NodeOne].FullNode.Network)
            {
                AccountReference = new WalletAccountReference(WalletName, WalletAccountName),
                WalletPassword   = WalletPassword,
                Recipients       = new[] { new Recipient {
                                               Amount = this.nodeTwoBalance - Money.COIN, ScriptPubKey = sendToNodeOne.ScriptPubKey
                                           } }.ToList()
            };

            Transaction transaction = this.nodes[NodeTwo].FullNode.WalletTransactionHandler().BuildTransaction(this.transactionBuildContext);

            this.transactionFee = this.nodes[NodeTwo].GetFee(this.transactionBuildContext);

            transaction.Inputs.Count.Should().Be(50);

            this.nodes[NodeTwo].FullNode.NodeService <WalletController>().SendTransaction(new SendTransactionRequest(transaction.ToHex()));
        }
Exemplo n.º 24
0
        private void a_nulldata_transaction()
        {
            var maturity = (int)this.senderNode.FullNode.Network.Consensus.CoinbaseMaturity;
            var transactionBuildContext = new TransactionBuildContext(this.senderNode.FullNode.Network)
            {
                AccountReference = this.sendingWalletAccountReference,
                MinConfirmations = maturity,
                OpReturnData     = this.opReturnContent,
                WalletPassword   = this.password,
                Recipients       = new List <Recipient>()
                {
                    new Recipient()
                    {
                        Amount = this.transferAmount, ScriptPubKey = this.receiverAddress.ScriptPubKey
                    }
                }
            };

            this.transaction = this.senderNode.FullNode.WalletTransactionHandler().BuildTransaction(transactionBuildContext);

            this.transaction.Outputs.Single(t => t.ScriptPubKey.IsUnspendable).Value.Should().Be(Money.Zero);
        }
        public void SendOneMillionCoinsFromPowWalletToPosWallet()
        {
            TransactionBuildContext context = SharedSteps.CreateTransactionBuildContext(
                this.PowWallet,
                this.WalletAccount,
                this.PowWalletPassword,
                new List <Recipient>()
            {
                new Recipient {
                    Amount = Money.COIN * 1000000, ScriptPubKey = this.posReceiverAddress.ScriptPubKey
                }
            },
                FeeType.Medium,
                101);

            context.OverrideFeeRate = new FeeRate(Money.Satoshis(20000));

            IEnumerable <UnspentOutputReference> unspent = this.nodes[this.PowMiner].FullNode.WalletManager().GetSpendableTransactionsInWallet(this.PowWallet);
            var coins = new List <Coin>();

            DateTimeOffset blockTimestamp = unspent.OrderBy(u => u.Transaction.CreationTime).Select(ts => ts.Transaction.CreationTime).First();
            Transaction    transaction    = this.nodes[this.PowMiner].FullNode.Network.Consensus.ConsensusFactory.CreateTransaction();

            transaction.Time = (uint)blockTimestamp.ToUnixTimeSeconds();

            foreach (UnspentOutputReference item in unspent.OrderByDescending(a => a.Transaction.Amount))
            {
                coins.Add(new Coin(item.Transaction.Id, (uint)item.Transaction.Index, item.Transaction.Amount, item.Transaction.ScriptPubKey));
            }

            Coin coin = coins.First();
            TxIn txIn = transaction.AddInput(new TxIn(coin.Outpoint, this.powSenderAddress.ScriptPubKey));

            transaction.AddOutput(new TxOut(new Money(9699999999995400), this.powSenderAddress.ScriptPubKey));
            transaction.AddOutput(new TxOut(new Money(100000000000000), this.posReceiverAddress.ScriptPubKey));
            transaction.Sign(this.nodes[this.PowMiner].FullNode.Network, this.powSenderPrivateKey, new[] { coin });

            this.nodes[this.PowMiner].FullNode.NodeService <WalletController>().SendTransaction(new SendTransactionRequest(transaction.ToHex()));
        }
Exemplo n.º 26
0
        public void BuildTransaction_When_OpReturnData_Is_Neither_Null_Nor_Empty_Should_Add_Extra_Output_With_Data()
        {
            WalletTransactionHandlerTestContext testContext = SetupWallet();

            string opReturnData = "some extra transaction info";

            byte[] expectedBytes = Encoding.UTF8.GetBytes(opReturnData);

            TransactionBuildContext context           = CreateContext(this.Network, testContext.WalletReference, "password", testContext.DestinationKeys.PubKey.ScriptPubKey, new Money(7500), FeeType.Low, 0, opReturnData);
            Transaction             transactionResult = testContext.WalletTransactionHandler.BuildTransaction(context);

            IEnumerable <TxOut> unspendableOutputs = transactionResult.Outputs.Where(o => o.ScriptPubKey.IsUnspendable).ToList();

            unspendableOutputs.Count().Should().Be(1);
            unspendableOutputs.Single().Value.Should().Be(Money.Zero);

            IEnumerable <Op> ops = unspendableOutputs.Single().ScriptPubKey.ToOps();

            ops.Count().Should().Be(2);
            ops.First().Code.Should().Be(OpcodeType.OP_RETURN);
            ops.Last().PushData.Should().BeEquivalentTo(expectedBytes);
        }
        private void bob_creates_a_transaction_and_broadcasts()
        {
            HdAddress nodeCReceivingAddress = this.GetSecondUnusedAddressToAvoidClashWithMiningAddress(this.nodes[Charlie]);

            TransactionBuildContext transactionBuildContext = SharedSteps.CreateTransactionBuildContext(
                WalletZero,
                AccountZero,
                WalletPassword,
                new[] {
                new Recipient {
                    Amount       = Money.COIN * 1,
                    ScriptPubKey = nodeCReceivingAddress.ScriptPubKey
                }
            },
                FeeType.Medium
                , 1);

            this.shorterChainTransaction  = this.nodes[Bob].FullNode.WalletTransactionHandler().BuildTransaction(transactionBuildContext);
            this.shortChainTransactionFee = this.nodes[Bob].FullNode.WalletTransactionHandler().EstimateFee(transactionBuildContext);

            this.nodes[Bob].FullNode.NodeService <WalletController>().SendTransaction(new SendTransactionRequest(this.shorterChainTransaction.ToHex()));
        }
Exemplo n.º 28
0
        public void BuildTransactionUsesGivenChangeAddress()
        {
            WalletTransactionHandlerTestContext testContext = SetupWallet();
            TransactionBuildContext             context     = CreateContext(this.Network, testContext.WalletReference, "password", testContext.DestinationKeys.PubKey.ScriptPubKey, new Money(7500), FeeType.Low, 0);

            var key = new Key();
            BitcoinPubKeyAddress address       = key.PubKey.GetAddress(this.Network);
            HdAddress            changeAddress = context.ChangeAddress = new HdAddress
            {
                Index        = 0,
                HdPath       = $"m/44'/0'/0'/0/0",
                Address      = address.ToString(),
                Pubkey       = key.PubKey.ScriptPubKey,
                ScriptPubKey = address.ScriptPubKey,
                //Transactions = new List<TransactionData>()
            };

            Transaction transactionResult = testContext.WalletTransactionHandler.BuildTransaction(context);

            Transaction result = this.Network.CreateTransaction(transactionResult.ToHex());

            Assert.Single(result.Inputs);
            Assert.Equal(testContext.AddressTransaction.Id, result.Inputs[0].PrevOut.Hash);

            Assert.Equal(2, result.Outputs.Count);
            TxOut output = result.Outputs[0];

            Assert.Equal((testContext.AddressTransaction.Amount - context.TransactionFee - 7500), output.Value);
            Assert.Equal(changeAddress.ScriptPubKey, output.ScriptPubKey);

            output = result.Outputs[1];
            Assert.Equal(7500, output.Value);
            Assert.Equal(testContext.DestinationKeys.PubKey.ScriptPubKey, output.ScriptPubKey);

            Assert.Equal(testContext.AddressTransaction.Amount - context.TransactionFee, result.TotalOut);
            Assert.NotNull(transactionResult.GetHash());
            Assert.Equal(result.GetHash(), transactionResult.GetHash());
        }
        private void node1_sends_funds_to_node2_TO_fifty_addresses()
        {
            this.Mine100Coins(this.nodes[NodeOne]);

            IEnumerable <HdAddress> nodeTwoAddresses = this.nodes[NodeTwo].FullNode.WalletManager().GetUnusedAddresses(new WalletAccountReference(WalletName, WalletAccountName), 50);

            List <Recipient> nodeTwoRecipients = nodeTwoAddresses.Select(address => new Recipient
            {
                ScriptPubKey = address.ScriptPubKey,
                Amount       = Money.COIN
            }).ToList();

            this.transactionBuildContext = SharedSteps.CreateTransactionBuildContext(this.nodes[NodeOne].FullNode.Network, WalletName, WalletAccountName, WalletPassword, nodeTwoRecipients, FeeType.Medium, this.CoinBaseMaturity + 1);

            Transaction transaction = this.nodes[NodeOne].FullNode.WalletTransactionHandler().BuildTransaction(this.transactionBuildContext);

            // Returns 50 outputs, including one extra output for change.
            transaction.Outputs.Count.Should().Be(UnspentTransactionOutputs + 1);

            this.transactionFee = this.nodes[NodeOne].GetFee(this.transactionBuildContext);

            this.nodes[NodeOne].FullNode.NodeService <WalletController>().SendTransaction(new SendTransactionRequest(transaction.ToHex()));
        }
Exemplo n.º 30
0
        private void bob_creates_a_transaction_and_broadcasts()
        {
            HdAddress charlieAddress = this.GetSecondUnusedAddressToAvoidClashWithMiningAddress(this.charlieNode);

            TransactionBuildContext transactionBuildContext = TestHelper.CreateTransactionBuildContext(
                this.bobNode.FullNode.Network,
                WalletZero,
                AccountZero,
                WalletPassword,
                new[] {
                new Recipient {
                    Amount       = Money.COIN * 1,
                    ScriptPubKey = charlieAddress.ScriptPubKey
                }
            },
                FeeType.Medium
                , 1);

            this.shorterChainTransaction = this.bobNode.FullNode.WalletTransactionHandler().BuildTransaction(transactionBuildContext);
            Money shortChainTransactionFee = this.bobNode.FullNode.WalletTransactionHandler().EstimateFee(transactionBuildContext);

            this.bobNode.FullNode.NodeController <WalletController>().SendTransactionAsync(new SendTransactionRequest(this.shorterChainTransaction.ToHex()));
        }