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));
        }
Esempio n. 2
0
        public void ValidateAddress_ValidP2WSHAddress_ReturnsTrue()
        {
            // P2WSH
            var    scriptaddress = new Key().PubKey.ScriptPubKey.WitHash.ScriptPubKey.GetWitScriptAddress(this.network);
            string address       = scriptaddress.ToString();

            var json = (JsonResult)this.controller.ValidateAddress(address);
            ValidatedAddress resultModel = (ValidatedAddress)json.Value;

            var isValid = resultModel.IsValid;

            Assert.True(isValid);
        }
Esempio n. 3
0
        public void ValidateAddress_ValidP2PKHAddress_ReturnsTrue()
        {
            // P2PKH
            var    pubkeyaddress = new Key().PubKey.GetAddress(this.network);
            string address       = pubkeyaddress.ToString();

            var json = (JsonResult)this.controller.ValidateAddress(address);
            ValidatedAddress resultModel = (ValidatedAddress)json.Value;

            var isValid = resultModel.IsValid;

            Assert.True(isValid);
        }
Esempio n. 4
0
        public void ValidateAddress_ValidAddressOfDifferentNetwork_ReturnsFalse()
        {
            // P2PKH
            var    pubkeyaddress = new Key().PubKey.GetAddress(Network.Main);
            string address       = pubkeyaddress.ToString();

            var json = (JsonResult)this.controller.ValidateAddress(address);
            ValidatedAddress resultModel = (ValidatedAddress)json.Value;

            var isValid = resultModel.IsValid;

            Assert.False(isValid);
        }
        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);
        }
Esempio n. 6
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);
        }
Esempio n. 7
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()));
            }
        }
        /// <summary>
        /// Get the current address
        /// </summary>
        ValidatedAddress GetAddress(bool isValid)
        {
            var toReturn = new ValidatedAddress
            {
                IsValid      = isValid,
                Address1     = AddressObj.GetAddress(),
                Address2     = AddressObj.GetAddress2(),
                Suite        = AddressObj.GetSuite(),
                City         = AddressObj.GetCity(),
                State        = AddressObj.GetState(),
                PostalCode   = AddressObj.GetZip(),
                Plus4        = AddressObj.GetPlus4(),
                CountryCode  = AddressObj.GetCountryCode(),
                Urbanization = AddressObj.GetUrbanization(),
                Company      = AddressObj.GetCompany()
            };

            // populate the last line
            toReturn.LastLine = $"{toReturn.City} {toReturn.State} {toReturn.PostalCode}-{toReturn.Plus4}";

            return(toReturn);
        }
Esempio n. 9
0
        private async Task ProcessBlockForSwapVoteTransactionsAsync(BlockTransactionDetailsModel block, int blockHeight)
        {
            // Inspect each transaction
            foreach (TransactionVerboseModel transaction in block.Transactions)
            {
                // Find the first the OP_RETURN output.
                Vout opReturnOutput = transaction.VOut.FirstOrDefault(v => v.ScriptPubKey.Type == "nulldata");
                if (opReturnOutput == null)
                {
                    continue;
                }

                IList <Op> ops           = new NBitcoin.Script(opReturnOutput.ScriptPubKey.Asm).ToOps();
                var        potentialVote = Encoding.ASCII.GetString(ops.Last().PushData);
                try
                {
                    var isVote = potentialVote.Substring(0, 1);
                    if (isVote != "V")
                    {
                        continue;
                    }

                    var isVoteValue = potentialVote.Substring(1, 1);
                    if (isVoteValue == "1" || isVoteValue == "0")
                    {
                        // Verify the sender address is a valid Strat address
                        var potentialStratAddress       = potentialVote.Substring(2);
                        ValidatedAddress validateResult = await $"http://localhost:{this.StratisNetworkApiPort}/api"
                                                          .AppendPathSegment("node/validateaddress")
                                                          .SetQueryParams(new { address = potentialStratAddress })
                                                          .GetJsonAsync <ValidatedAddress>();

                        if (!validateResult.IsValid)
                        {
                            Console.WriteLine($"Invalid STRAT address: '{potentialStratAddress}'");
                            continue;
                        }

                        AddressBalancesResult balance = await $"http://localhost:{this.StratisNetworkApiPort}/api"
                                                        .AppendPathSegment($"blockstore/{BlockStoreRouteEndPoint.GetAddressesBalances}")
                                                        .SetQueryParams(new { addresses = potentialStratAddress, minConfirmations = 0 })
                                                        .GetJsonAsync <AddressBalancesResult>();

                        if (isVoteValue == "0")
                        {
                            this.castVotes.Add(new CastVote()
                            {
                                Address = potentialStratAddress, Balance = balance.Balances[0].Balance, InFavour = false, BlockHeight = blockHeight
                            });
                            Console.WriteLine($"'No' vote found at height {blockHeight}.");
                        }

                        if (isVoteValue == "1")
                        {
                            this.castVotes.Add(new CastVote()
                            {
                                Address = potentialStratAddress, Balance = balance.Balances[0].Balance, InFavour = true, BlockHeight = blockHeight
                            });
                            Console.WriteLine($"'Yes' vote found at height {blockHeight}.");
                        }
                    }
                }
                catch (Exception)
                {
                }
            }
        }
Esempio n. 10
0
        private async Task ProcessBlockForCollateralVoteTransactionsAsync(BlockTransactionDetailsModel block, int blockHeight)
        {
            // Inspect each transaction
            foreach (TransactionVerboseModel transaction in block.Transactions)
            {
                // Find the first the OP_RETURN output.
                Vout opReturnOutput = transaction.VOut.FirstOrDefault(v => v.ScriptPubKey.Type == "nulldata");
                if (opReturnOutput == null)
                {
                    continue;
                }

                // Before checking if it's a vote, check if it's a swap transaction as we now know it has an OP_RETURN.
                // Ignore any transactions that have inconsequential OP_RETURN values.
                if (opReturnOutput.Value >= 1.0m)
                {
                    // For the purposes of speeding up this search, it doesn't matter per se whether the burn transaction has a valid destination address in it.

                    TransactionModel tx = this.blockExplorerClient.GetTransaction(transaction.TxId);

                    // Check the inputs of the transaction to see if it was funded by one of the vote addresses.
                    string address = null;
                    foreach (In input in tx._in)
                    {
                        if (input.hash == null)
                        {
                            continue;
                        }

                        // The block explorer calls this 'hash' but it is in fact the address that funded the input.
                        // It is possible that several voting addresses consolidated together in one swap transaction, so just take the first one.
                        if (this.collateralVotes.ContainsKey(input.hash))
                        {
                            if (address == null)
                            {
                                // We will assign the entire burn amount to the first found voting address.
                                address = input.hash;
                            }
                            else
                            {
                                // However, we have to recompute the balance of all the vote addresses present in the inputs that we are not going to assign the burn to.
                                // This is because they will not necessarily be revisited later if there are no further transactions affecting them.
                                // We presume that since they are participating in a burn subsequent to their initial vote, their balance will drop.
                                if (!address.Equals(input.hash))
                                {
                                    AddressBalancesResult balance = await $"http://localhost:{this.StratisNetworkApiPort}/api"
                                                                    .AppendPathSegment($"blockstore/{BlockStoreRouteEndPoint.GetAddressesBalances}")
                                                                    .SetQueryParams(new { addresses = input.hash, minConfirmations = 0 })
                                                                    .GetJsonAsync <AddressBalancesResult>();

                                    Console.WriteLine($"Reset balance for '{input.hash}' to {balance.Balances[0].Balance} due to burn transaction {transaction.TxId} at height {blockHeight}");

                                    this.collateralVotes[input.hash].Balance = balance.Balances[0].Balance;
                                }
                            }
                        }
                    }

                    if (address != null)
                    {
                        this.collateralVotes[address].BlockHeight = blockHeight;
                        this.collateralVotes[address].Balance     = Money.Coins(opReturnOutput.Value);

                        Console.WriteLine($"Detected that address '{address}' burnt {opReturnOutput.Value} via transaction {transaction.TxId} at height {blockHeight}");

                        // We can now skip checking if this output was a vote.
                        continue;
                    }
                }

                IList <Op> ops           = new NBitcoin.Script(opReturnOutput.ScriptPubKey.Asm).ToOps();
                var        potentialVote = Encoding.ASCII.GetString(ops.Last().PushData);
                try
                {
                    var isVote = potentialVote.Substring(0, 1);
                    if (isVote != "V")
                    {
                        continue;
                    }

                    var isCollateralVote = potentialVote.Substring(1, 1);
                    if (isCollateralVote != "C")
                    {
                        continue;
                    }

                    var collateralVote = potentialVote.Substring(2, 1);
                    if (!new[] { "A", "B", "C", "D", "E" }.Contains(collateralVote))
                    {
                        Console.WriteLine($"Invalid vote found '{collateralVote}'; height {blockHeight}.");
                        continue;
                    }

                    // Verify the sender address is a valid Strat address
                    var potentialStratAddress       = potentialVote.Substring(3);
                    ValidatedAddress validateResult = await $"http://localhost:{this.StratisNetworkApiPort}/api"
                                                      .AppendPathSegment("node/validateaddress")
                                                      .SetQueryParams(new { address = potentialStratAddress })
                                                      .GetJsonAsync <ValidatedAddress>();

                    if (!validateResult.IsValid)
                    {
                        Console.WriteLine($"Invalid STRAT address: '{potentialStratAddress}'");
                        continue;
                    }

                    AddressBalancesResult balance = await $"http://localhost:{this.StratisNetworkApiPort}/api"
                                                    .AppendPathSegment($"blockstore/{BlockStoreRouteEndPoint.GetAddressesBalances}")
                                                    .SetQueryParams(new { addresses = potentialStratAddress, minConfirmations = 0 })
                                                    .GetJsonAsync <AddressBalancesResult>();

                    Money determinedBalance = balance.Balances[0].Balance;

                    if (!this.collateralVotes.ContainsKey(potentialStratAddress))
                    {
                        Console.WriteLine($"Collateral vote found for {potentialStratAddress} at height {blockHeight}; Selection '{collateralVote}'; Balance {determinedBalance}");

                        this.collateralVotes.Add(potentialStratAddress, new CollateralVote()
                        {
                            Address = potentialStratAddress, Balance = determinedBalance, Selection = collateralVote, BlockHeight = blockHeight
                        });
                    }
                    else
                    {
                        Console.WriteLine($"Updating existing vote for {potentialStratAddress} at height {blockHeight}; Selection '{collateralVote}'; Balance {determinedBalance}");

                        this.collateralVotes[potentialStratAddress] = new CollateralVote()
                        {
                            Address = potentialStratAddress, Balance = determinedBalance, Selection = collateralVote, BlockHeight = blockHeight
                        };
                    }
                }
                catch (Exception)
                {
                }
            }
        }