Exemple #1
0
        public JObject ValidateAddress(string address)
        {
            if (string.IsNullOrEmpty(address))
            {
                throw new ArgumentNullException("address");
            }

            var res = new JObject();

            res["isvalid"] = false;

            // P2PKH
            if (BitcoinPubKeyAddress.IsValid(address, ref this.Network))
            {
                res["isvalid"] = true;
            }
            // P2SH
            else if (BitcoinScriptAddress.IsValid(address, ref this.Network))
            {
                res["isvalid"] = true;
            }
            // P2WPKH
            else if (BitcoinWitPubKeyAddress.IsValid(address, ref this.Network))
            {
                res ["isvalid"] = true;
            }
            // P2WSH
            else if (BitcoinWitScriptAddress.IsValid(address, ref this.Network))
            {
                res ["isvalid"] = true;
            }
            return(res);
        }
Exemple #2
0
        public ValidatedAddress ValidateAddress(string address)
        {
            if (string.IsNullOrEmpty(address))
            {
                throw new ArgumentNullException("address");
            }

            var res = new ValidatedAddress();

            res.IsValid = false;

            // P2WPKH
            if (BitcoinWitPubKeyAddress.IsValid(address, this.Network, out Exception _))
            {
                res.IsValid = true;
            }
            // P2WSH
            else if (BitcoinWitScriptAddress.IsValid(address, this.Network, out Exception _))
            {
                res.IsValid = true;
            }
            // P2PKH
            else if (BitcoinPubKeyAddress.IsValid(address, this.Network))
            {
                res.IsValid = true;
            }
            // P2SH
            else if (BitcoinScriptAddress.IsValid(address, this.Network))
            {
                res.IsValid = true;
            }

            return(res);
        }
Exemple #3
0
        public IActionResult ValidateAddress([FromQuery] string address)
        {
            Guard.NotEmpty(address, nameof(address));

            var result = new ValidatedAddress
            {
                IsValid = false,
                Address = address,
            };

            try
            {
                // P2WPKH
                if (BitcoinWitPubKeyAddress.IsValid(address, this.network, out Exception _))
                {
                    result.IsValid = true;
                }

                // P2WSH
                else if (BitcoinWitScriptAddress.IsValid(address, this.network, out Exception _))
                {
                    result.IsValid = true;
                }

                // P2PKH
                else if (BitcoinPubKeyAddress.IsValid(address, this.network))
                {
                    result.IsValid = true;
                }

                // P2SH
                else if (BitcoinScriptAddress.IsValid(address, this.network))
                {
                    result.IsValid  = true;
                    result.IsScript = true;
                }
            }
            catch (Exception e)
            {
                this.logger.LogError("Exception occurred: {0}", e.ToString());
                return(ErrorHelpers.BuildErrorResponse(HttpStatusCode.BadRequest, e.Message, e.ToString()));
            }

            if (result.IsValid)
            {
                var scriptPubKey = BitcoinAddress.Create(address, this.network).ScriptPubKey;
                result.ScriptPubKey = scriptPubKey.ToHex();
                result.IsWitness    = scriptPubKey.IsWitness(this.network);
            }

            return(this.Json(result));
        }
        public ValidatedAddress ValidateAddress([FromQuery] string address)
        {
            Guard.NotEmpty(address, nameof(address));

            var result = new ValidatedAddress
            {
                IsValid = false,
                Address = address,
            };

            try
            {
                // P2WPKH
                if (BitcoinWitPubKeyAddress.IsValid(address, this.network, out Exception _))
                {
                    result.IsValid = true;
                }
                // P2WSH
                else if (BitcoinWitScriptAddress.IsValid(address, this.network, out Exception _))
                {
                    result.IsValid = true;
                }
                // P2PKH
                else if (BitcoinPubKeyAddress.IsValid(address, this.network))
                {
                    result.IsValid = true;
                }
                // P2SH
                else if (BitcoinScriptAddress.IsValid(address, this.network))
                {
                    result.IsValid  = true;
                    result.IsScript = true;
                }
            }
            catch (Exception e)
            {
                this.logger.LogDebug("Exception occurred: {0}", e.ToString());

                result.IsValid = false;
                return(result);
            }

            if (result.IsValid)
            {
                var scriptPubKey = BitcoinAddress.Create(address, this.network).ScriptPubKey;
                result.ScriptPubKey = scriptPubKey.ToHex();
                result.IsWitness    = scriptPubKey.IsWitness(this.network);
            }

            return(result);
        }
Exemple #5
0
        public ValidatedAddress ValidateAddress(string address)
        {
            Guard.NotEmpty(address, nameof(address));

            var result = new ValidatedAddress
            {
                IsValid = false,
                Address = address,
            };

            try
            {
                // P2WPKH
                if (BitcoinWitPubKeyAddress.IsValid(address, this.Network, out Exception _))
                {
                    result.IsValid = true;
                }
                // P2WSH
                else if (BitcoinWitScriptAddress.IsValid(address, this.Network, out Exception _))
                {
                    result.IsValid = true;
                }
                // P2PKH
                else if (BitcoinPubKeyAddress.IsValid(address, this.Network))
                {
                    result.IsValid = true;
                }
                // P2SH
                else if (BitcoinScriptAddress.IsValid(address, this.Network))
                {
                    result.IsValid  = true;
                    result.IsScript = true;
                }
            }
            catch (NotImplementedException)
            {
                result.IsValid = false;
            }

            if (result.IsValid)
            {
                var scriptPubKey = BitcoinAddress.Create(address, this.Network).ScriptPubKey;
                result.ScriptPubKey = scriptPubKey.ToHex();
                result.IsWitness    = scriptPubKey.IsWitness(this.Network);
            }

            return(result);
        }
Exemple #6
0
        public IActionResult ValidateAddress([FromQuery] string address)
        {
            try
            {
                Guard.NotEmpty(address, nameof(address));

                var res = new ValidatedAddress
                {
                    IsValid = false
                };
                // P2WPKH
                if (BitcoinWitPubKeyAddress.IsValid(address, this.network, out _))
                {
                    res.IsValid = true;
                }

                // P2WSH
                else if (BitcoinWitScriptAddress.IsValid(address, this.network, out _))
                {
                    res.IsValid = true;
                }

                // P2PKH
                else if (BitcoinPubKeyAddress.IsValid(address, this.network))
                {
                    res.IsValid = true;
                }

                // P2SH
                else if (BitcoinScriptAddress.IsValid(address, this.network))
                {
                    res.IsValid = true;
                }

                return(Json(res));
            }
            catch (Exception e)
            {
                this.logger.LogError("Exception occurred: {0}", e.ToString());
                return(ErrorHelpers.BuildErrorResponse(HttpStatusCode.BadRequest, e.Message, e.ToString()));
            }
        }
Exemple #7
0
        /// <summary>
        /// Creates a cold staking withdrawal <see cref="Transaction"/>.
        /// </summary>
        /// <remarks>
        /// Cold staking withdrawal is performed on the wallet that is in the role of the cold staking cold wallet.
        /// </remarks>
        /// <param name="walletTransactionHandler">The wallet transaction handler used to build the transaction.</param>
        /// <param name="receivingAddress">The address that will receive the withdrawal.</param>
        /// <param name="walletName">The name of the wallet in the role of cold wallet.</param>
        /// <param name="walletPassword">The wallet password.</param>
        /// <param name="amount">The amount to remove from cold staking.</param>
        /// <param name="feeAmount">The fee to pay for cold staking transaction withdrawal.</param>
        /// <returns>The <see cref="Transaction"/> for cold staking withdrawal.</returns>
        /// <exception cref="WalletException">Thrown if the receiving address is in a cold staking account in this wallet.</exception>
        /// <exception cref="ArgumentNullException">Thrown if the receiving address is invalid.</exception>
        internal Transaction GetColdStakingWithdrawalTransaction(IWalletTransactionHandler walletTransactionHandler, string receivingAddress,
                                                                 string walletName, string walletPassword, Money amount, Money feeAmount)
        {
            Guard.NotEmpty(receivingAddress, nameof(receivingAddress));
            Guard.NotEmpty(walletName, nameof(walletName));
            Guard.NotNull(amount, nameof(amount));
            Guard.NotNull(feeAmount, nameof(feeAmount));

            Wallet.Types.Wallet wallet = this.GetWalletByName(walletName);

            // Get the cold staking account.
            HdAccount coldAccount = this.GetColdStakingAccount(wallet, true);

            if (coldAccount == null)
            {
                this.logger.LogTrace("(-)[COLDSTAKE_ACCOUNT_DOES_NOT_EXIST]");
                throw new WalletException("The cold wallet account does not exist.");
            }

            // Prevent reusing cold stake addresses as regular withdrawal addresses.
            if (coldAccount.ExternalAddresses.Concat(coldAccount.InternalAddresses).Any(s => s.Address == receivingAddress || s.Bech32Address == receivingAddress))
            {
                this.logger.LogTrace("(-)[COLDSTAKE_INVALID_COLD_WALLET_ADDRESS_USAGE]");
                throw new WalletException("You can't send the money to a cold staking cold wallet account.");
            }

            HdAccount hotAccount = this.GetColdStakingAccount(wallet, false);

            if (hotAccount != null && hotAccount.ExternalAddresses.Concat(hotAccount.InternalAddresses).Any(s => s.Address == receivingAddress || s.Bech32Address == receivingAddress))
            {
                this.logger.LogTrace("(-)[COLDSTAKE_INVALID_HOT_WALLET_ADDRESS_USAGE]");
                throw new WalletException("You can't send the money to a cold staking hot wallet account.");
            }

            Script destination = null;

            if (BitcoinWitPubKeyAddress.IsValid(receivingAddress, this.network, out Exception _))
            {
                destination = new BitcoinWitPubKeyAddress(receivingAddress, wallet.Network).ScriptPubKey;
            }
            else
            {
                // Send the money to the receiving address.
                destination = BitcoinAddress.Create(receivingAddress, wallet.Network).ScriptPubKey;
            }

            // Create the transaction build context (used in BuildTransaction).
            var accountReference = new WalletAccountReference(walletName, coldAccount.Name);
            var context          = new TransactionBuildContext(wallet.Network)
            {
                AccountReference = accountReference,
                // Specify a dummy change address to prevent a change (internal) address from being created.
                // Will be changed after the transacton is built and before it is signed.
                ChangeAddress    = coldAccount.ExternalAddresses.First(),
                TransactionFee   = feeAmount,
                MinConfirmations = 0,
                Shuffle          = false,
                Sign             = false,
                Recipients       = new[] { new Recipient {
                                               Amount = amount, ScriptPubKey = destination
                                           } }.ToList()
            };

            // Register the cold staking builder extension with the transaction builder.
            context.TransactionBuilder.Extensions.Add(new ColdStakingBuilderExtension(false));

            // Avoid script errors due to missing scriptSig.
            context.TransactionBuilder.StandardTransactionPolicy.ScriptVerify = null;

            // Build the transaction according to the settings recorded in the context.
            Transaction transaction = walletTransactionHandler.BuildTransaction(context);

            // Map OutPoint to UnspentOutputReference.
            Dictionary <OutPoint, UnspentOutputReference> mapOutPointToUnspentOutput = this.GetSpendableTransactionsInAccount(accountReference)
                                                                                       .ToDictionary(unspent => unspent.ToOutPoint(), unspent => unspent);

            // Set the cold staking scriptPubKey on the change output.
            TxOut changeOutput = transaction.Outputs.SingleOrDefault(output => (output.ScriptPubKey != destination) && (output.Value != 0));

            if (changeOutput != null)
            {
                // Find the largest input.
                TxIn largestInput = transaction.Inputs.OrderByDescending(input => mapOutPointToUnspentOutput[input.PrevOut].Transaction.Amount).Take(1).Single();

                // Set the scriptPubKey of the change output to the scriptPubKey of the largest input.
                changeOutput.ScriptPubKey = mapOutPointToUnspentOutput[largestInput.PrevOut].Transaction.ScriptPubKey;
            }

            // Add keys for signing inputs. This takes time so only add keys for distinct addresses.
            foreach (UnspentOutputReference item in transaction.Inputs.Select(i => mapOutPointToUnspentOutput[i.PrevOut]).Distinct())
            {
                Script prevscript = item.Transaction.ScriptPubKey;

                if (prevscript.IsScriptType(ScriptType.P2SH) || prevscript.IsScriptType(ScriptType.P2WSH))
                {
                    if (item.Address.RedeemScript == null)
                    {
                        throw new WalletException("Missing redeem script");
                    }

                    // Provide the redeem script to the builder
                    var scriptCoin = ScriptCoin.Create(this.network, item.ToOutPoint(), new TxOut(item.Transaction.Amount, prevscript), item.Address.RedeemScript);
                    context.TransactionBuilder.AddCoins(scriptCoin);
                }

                context.TransactionBuilder.AddKeys(wallet.GetExtendedPrivateKeyForAddress(walletPassword, item.Address));
            }

            // Sign the transaction.
            context.TransactionBuilder.SignTransactionInPlace(transaction);

            this.logger.LogTrace("(-):'{0}'", transaction.GetHash());
            return(transaction);
        }
Exemple #8
0
        private (TransactionBuildContext, HdAccount, Script) GetWithdrawalTransactionBuildContext(string receivingAddress, string walletName, Money amount, Money feeAmount, bool subtractFeeFromAmount)
        {
            Guard.NotEmpty(receivingAddress, nameof(receivingAddress));
            Guard.NotEmpty(walletName, nameof(walletName));
            Guard.NotNull(amount, nameof(amount));

            Wallet.Wallet wallet = this.GetWallet(walletName);

            // Get the cold staking account.
            HdAccount coldAccount = this.GetColdStakingAccount(wallet, true);

            if (coldAccount == null)
            {
                this.logger.LogTrace("(-)[COLDSTAKE_ACCOUNT_DOES_NOT_EXIST]");
                throw new WalletException("The cold wallet account does not exist.");
            }

            // Prevent reusing cold stake addresses as regular withdrawal addresses.
            if (coldAccount.ExternalAddresses.Concat(coldAccount.InternalAddresses).Any(s => s.Address == receivingAddress || s.Bech32Address == receivingAddress))
            {
                this.logger.LogTrace("(-)[COLDSTAKE_INVALID_COLD_WALLET_ADDRESS_USAGE]");
                throw new WalletException("You can't send the money to a cold staking cold wallet account.");
            }

            HdAccount hotAccount = this.GetColdStakingAccount(wallet, false);

            if (hotAccount != null && hotAccount.ExternalAddresses.Concat(hotAccount.InternalAddresses).Any(s => s.Address == receivingAddress || s.Bech32Address == receivingAddress))
            {
                this.logger.LogTrace("(-)[COLDSTAKE_INVALID_HOT_WALLET_ADDRESS_USAGE]");
                throw new WalletException("You can't send the money to a cold staking hot wallet account.");
            }

            Script destination = null;

            if (BitcoinWitPubKeyAddress.IsValid(receivingAddress, this.network, out Exception _))
            {
                destination = new BitcoinWitPubKeyAddress(receivingAddress, wallet.Network).ScriptPubKey;
            }
            else
            {
                // Send the money to the receiving address.
                destination = BitcoinAddress.Create(receivingAddress, wallet.Network).ScriptPubKey;
            }

            // Create the transaction build context (used in BuildTransaction).
            var accountReference = new WalletAccountReference(walletName, coldAccount.Name);
            var context          = new TransactionBuildContext(wallet.Network)
            {
                AccountReference = accountReference,
                // Specify a dummy change address to prevent a change (internal) address from being created.
                // Will be changed after the transaction is built and before it is signed.
                ChangeAddress    = coldAccount.ExternalAddresses.First(),
                TransactionFee   = feeAmount,
                MinConfirmations = 0,
                Shuffle          = false,
                Sign             = false,
                Recipients       = new[] { new Recipient {
                                               Amount = amount, ScriptPubKey = destination, SubtractFeeFromAmount = subtractFeeFromAmount
                                           } }.ToList()
            };

            // Register the cold staking builder extension with the transaction builder.
            context.TransactionBuilder.Extensions.Add(new ColdStakingBuilderExtension(false));

            // Avoid script errors due to missing scriptSig.
            context.TransactionBuilder.StandardTransactionPolicy.ScriptVerify = null;

            return(context, coldAccount, destination);
        }