Auto merge of #3228 - str4d:3058-taddr-encoding-refactor, r=str4d
Refactor t-address encoding Includes code cherry-picked from the following upstream PRs: - bitcoin/bitcoin#11117 - bitcoin/bitcoin#11259 - Only the second commit (first is for QT code) - bitcoin/bitcoin#11167 - Only the first commit (the rest are not part of the t-address encoding refactor). Part of #3058. Precursor to #3202.
This commit is contained in:
commit
d97bfb766b
137
src/base58.cpp
137
src/base58.cpp
|
@ -5,19 +5,20 @@
|
|||
#include "base58.h"
|
||||
|
||||
#include "hash.h"
|
||||
#include "script/script.h"
|
||||
#include "uint256.h"
|
||||
|
||||
#include "version.h"
|
||||
#include "streams.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <boost/variant/apply_visitor.hpp>
|
||||
#include <boost/variant/static_visitor.hpp>
|
||||
|
||||
#include <algorithm>
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
|
||||
|
||||
/** All alphanumeric characters except for "0", "I", "O", and "l" */
|
||||
static const char* pszBase58 = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz";
|
||||
|
||||
|
@ -206,89 +207,55 @@ int CBase58Data::CompareTo(const CBase58Data& b58) const
|
|||
|
||||
namespace
|
||||
{
|
||||
class CBitcoinAddressVisitor : public boost::static_visitor<bool>
|
||||
class DestinationEncoder : public boost::static_visitor<std::string>
|
||||
{
|
||||
private:
|
||||
CBitcoinAddress* addr;
|
||||
const CChainParams& m_params;
|
||||
|
||||
public:
|
||||
CBitcoinAddressVisitor(CBitcoinAddress* addrIn) : addr(addrIn) {}
|
||||
DestinationEncoder(const CChainParams& params) : m_params(params) {}
|
||||
|
||||
bool operator()(const CKeyID& id) const { return addr->Set(id); }
|
||||
bool operator()(const CScriptID& id) const { return addr->Set(id); }
|
||||
bool operator()(const CNoDestination& no) const { return false; }
|
||||
std::string operator()(const CKeyID& id) const
|
||||
{
|
||||
std::vector<unsigned char> data = m_params.Base58Prefix(CChainParams::PUBKEY_ADDRESS);
|
||||
data.insert(data.end(), id.begin(), id.end());
|
||||
return EncodeBase58Check(data);
|
||||
}
|
||||
|
||||
std::string operator()(const CScriptID& id) const
|
||||
{
|
||||
std::vector<unsigned char> data = m_params.Base58Prefix(CChainParams::SCRIPT_ADDRESS);
|
||||
data.insert(data.end(), id.begin(), id.end());
|
||||
return EncodeBase58Check(data);
|
||||
}
|
||||
|
||||
std::string operator()(const CNoDestination& no) const { return ""; }
|
||||
};
|
||||
|
||||
} // anon namespace
|
||||
|
||||
bool CBitcoinAddress::Set(const CKeyID& id)
|
||||
CTxDestination DecodeDestination(const std::string& str, const CChainParams& params)
|
||||
{
|
||||
SetData(Params().Base58Prefix(CChainParams::PUBKEY_ADDRESS), &id, 20);
|
||||
return true;
|
||||
std::vector<unsigned char> data;
|
||||
uint160 hash;
|
||||
if (DecodeBase58Check(str, data)) {
|
||||
// base58-encoded Bitcoin addresses.
|
||||
// Public-key-hash-addresses have version 0 (or 111 testnet).
|
||||
// The data vector contains RIPEMD160(SHA256(pubkey)), where pubkey is the serialized public key.
|
||||
const std::vector<unsigned char>& pubkey_prefix = params.Base58Prefix(CChainParams::PUBKEY_ADDRESS);
|
||||
if (data.size() == hash.size() + pubkey_prefix.size() && std::equal(pubkey_prefix.begin(), pubkey_prefix.end(), data.begin())) {
|
||||
std::copy(data.begin() + pubkey_prefix.size(), data.end(), hash.begin());
|
||||
return CKeyID(hash);
|
||||
}
|
||||
|
||||
bool CBitcoinAddress::Set(const CScriptID& id)
|
||||
{
|
||||
SetData(Params().Base58Prefix(CChainParams::SCRIPT_ADDRESS), &id, 20);
|
||||
return true;
|
||||
// Script-hash-addresses have version 5 (or 196 testnet).
|
||||
// The data vector contains RIPEMD160(SHA256(cscript)), where cscript is the serialized redemption script.
|
||||
const std::vector<unsigned char>& script_prefix = params.Base58Prefix(CChainParams::SCRIPT_ADDRESS);
|
||||
if (data.size() == hash.size() + script_prefix.size() && std::equal(script_prefix.begin(), script_prefix.end(), data.begin())) {
|
||||
std::copy(data.begin() + script_prefix.size(), data.end(), hash.begin());
|
||||
return CScriptID(hash);
|
||||
}
|
||||
|
||||
bool CBitcoinAddress::Set(const CTxDestination& dest)
|
||||
{
|
||||
return boost::apply_visitor(CBitcoinAddressVisitor(this), dest);
|
||||
}
|
||||
|
||||
bool CBitcoinAddress::IsValid() const
|
||||
{
|
||||
return IsValid(Params());
|
||||
}
|
||||
|
||||
bool CBitcoinAddress::IsValid(const CChainParams& params) const
|
||||
{
|
||||
bool fCorrectSize = vchData.size() == 20;
|
||||
bool fKnownVersion = vchVersion == params.Base58Prefix(CChainParams::PUBKEY_ADDRESS) ||
|
||||
vchVersion == params.Base58Prefix(CChainParams::SCRIPT_ADDRESS);
|
||||
return fCorrectSize && fKnownVersion;
|
||||
}
|
||||
|
||||
bool CBitcoinAddress::SetString(const char* pszAddress)
|
||||
{
|
||||
return CBase58Data::SetString(pszAddress, 2);
|
||||
}
|
||||
|
||||
bool CBitcoinAddress::SetString(const std::string& strAddress)
|
||||
{
|
||||
return SetString(strAddress.c_str());
|
||||
}
|
||||
|
||||
CTxDestination CBitcoinAddress::Get() const
|
||||
{
|
||||
if (!IsValid())
|
||||
return CNoDestination();
|
||||
uint160 id;
|
||||
memcpy(&id, vchData.data(), 20);
|
||||
if (vchVersion == Params().Base58Prefix(CChainParams::PUBKEY_ADDRESS))
|
||||
return CKeyID(id);
|
||||
else if (vchVersion == Params().Base58Prefix(CChainParams::SCRIPT_ADDRESS))
|
||||
return CScriptID(id);
|
||||
else
|
||||
return CNoDestination();
|
||||
}
|
||||
|
||||
bool CBitcoinAddress::GetKeyID(CKeyID& keyID) const
|
||||
{
|
||||
if (!IsValid() || vchVersion != Params().Base58Prefix(CChainParams::PUBKEY_ADDRESS))
|
||||
return false;
|
||||
uint160 id;
|
||||
memcpy(&id, vchData.data(), 20);
|
||||
keyID = CKeyID(id);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CBitcoinAddress::IsScript() const
|
||||
{
|
||||
return IsValid() && vchVersion == Params().Base58Prefix(CChainParams::SCRIPT_ADDRESS);
|
||||
}
|
||||
} // namespace
|
||||
|
||||
void CBitcoinSecret::SetKey(const CKey& vchSecret)
|
||||
{
|
||||
|
@ -323,6 +290,26 @@ bool CBitcoinSecret::SetString(const std::string& strSecret)
|
|||
return SetString(strSecret.c_str());
|
||||
}
|
||||
|
||||
std::string EncodeDestination(const CTxDestination& dest)
|
||||
{
|
||||
return boost::apply_visitor(DestinationEncoder(Params()), dest);
|
||||
}
|
||||
|
||||
CTxDestination DecodeDestination(const std::string& str)
|
||||
{
|
||||
return DecodeDestination(str, Params());
|
||||
}
|
||||
|
||||
bool IsValidDestinationString(const std::string& str, const CChainParams& params)
|
||||
{
|
||||
return IsValidDestination(DecodeDestination(str, params));
|
||||
}
|
||||
|
||||
bool IsValidDestinationString(const std::string& str)
|
||||
{
|
||||
return IsValidDestinationString(str, Params());
|
||||
}
|
||||
|
||||
template<class DATA_TYPE, CChainParams::Base58Type PREFIX, size_t SER_SIZE>
|
||||
bool CZCEncoding<DATA_TYPE, PREFIX, SER_SIZE>::Set(const DATA_TYPE& addr)
|
||||
{
|
||||
|
|
32
src/base58.h
32
src/base58.h
|
@ -17,7 +17,6 @@
|
|||
#include "chainparams.h"
|
||||
#include "key.h"
|
||||
#include "pubkey.h"
|
||||
#include "script/script.h"
|
||||
#include "script/standard.h"
|
||||
#include "support/allocators/zeroafterfree.h"
|
||||
#include "zcash/Address.hpp"
|
||||
|
@ -140,32 +139,6 @@ public:
|
|||
CZCSpendingKey(const libzcash::SpendingKey& addr) { Set(addr); }
|
||||
};
|
||||
|
||||
/** base58-encoded Bitcoin addresses.
|
||||
* Public-key-hash-addresses have version 0 (or 111 testnet).
|
||||
* The data vector contains RIPEMD160(SHA256(pubkey)), where pubkey is the serialized public key.
|
||||
* Script-hash-addresses have version 5 (or 196 testnet).
|
||||
* The data vector contains RIPEMD160(SHA256(cscript)), where cscript is the serialized redemption script.
|
||||
*/
|
||||
class CBitcoinAddress : public CBase58Data {
|
||||
public:
|
||||
bool Set(const CKeyID &id);
|
||||
bool Set(const CScriptID &id);
|
||||
bool Set(const CTxDestination &dest);
|
||||
bool IsValid() const;
|
||||
bool IsValid(const CChainParams ¶ms) const;
|
||||
bool SetString(const char* pszSecret);
|
||||
bool SetString(const std::string& strSecret);
|
||||
|
||||
CBitcoinAddress() {}
|
||||
CBitcoinAddress(const CTxDestination &dest) { Set(dest); }
|
||||
CBitcoinAddress(const std::string& strAddress) { SetString(strAddress); }
|
||||
CBitcoinAddress(const char* pszAddress) { SetString(pszAddress); }
|
||||
|
||||
CTxDestination Get() const;
|
||||
bool GetKeyID(CKeyID &keyID) const;
|
||||
bool IsScript() const;
|
||||
};
|
||||
|
||||
/**
|
||||
* A base58-encoded secret key
|
||||
*/
|
||||
|
@ -214,4 +187,9 @@ public:
|
|||
typedef CBitcoinExtKeyBase<CExtKey, BIP32_EXTKEY_SIZE, CChainParams::EXT_SECRET_KEY> CBitcoinExtKey;
|
||||
typedef CBitcoinExtKeyBase<CExtPubKey, BIP32_EXTKEY_SIZE, CChainParams::EXT_PUBLIC_KEY> CBitcoinExtPubKey;
|
||||
|
||||
std::string EncodeDestination(const CTxDestination& dest);
|
||||
CTxDestination DecodeDestination(const std::string& str);
|
||||
bool IsValidDestinationString(const std::string& str);
|
||||
bool IsValidDestinationString(const std::string& str, const CChainParams& params);
|
||||
|
||||
#endif // BITCOIN_BASE58_H
|
||||
|
|
|
@ -240,12 +240,11 @@ static void MutateTxAddOutAddr(CMutableTransaction& tx, const std::string& strIn
|
|||
|
||||
// extract and validate ADDRESS
|
||||
std::string strAddr = strInput.substr(pos + 1, std::string::npos);
|
||||
CBitcoinAddress addr(strAddr);
|
||||
if (!addr.IsValid())
|
||||
CTxDestination destination = DecodeDestination(strAddr);
|
||||
if (!IsValidDestination(destination)) {
|
||||
throw std::runtime_error("invalid TX output address");
|
||||
|
||||
// build standard output script via GetScriptForDestination()
|
||||
CScript scriptPubKey = GetScriptForDestination(addr.Get());
|
||||
}
|
||||
CScript scriptPubKey = GetScriptForDestination(destination);
|
||||
|
||||
// construct TxOut, append to transaction output list
|
||||
CTxOut txout(value, scriptPubKey);
|
||||
|
|
|
@ -502,10 +502,10 @@ std::string CChainParams::GetFoundersRewardAddressAtHeight(int nHeight) const {
|
|||
CScript CChainParams::GetFoundersRewardScriptAtHeight(int nHeight) const {
|
||||
assert(nHeight > 0 && nHeight <= consensus.GetLastFoundersRewardBlockHeight());
|
||||
|
||||
CBitcoinAddress address(GetFoundersRewardAddressAtHeight(nHeight).c_str());
|
||||
assert(address.IsValid());
|
||||
assert(address.IsScript());
|
||||
CScriptID scriptID = boost::get<CScriptID>(address.Get()); // Get() returns a boost variant
|
||||
CTxDestination address = DecodeDestination(GetFoundersRewardAddressAtHeight(nHeight).c_str());
|
||||
assert(IsValidDestination(address));
|
||||
assert(boost::get<CScriptID>(&address) != nullptr);
|
||||
CScriptID scriptID = boost::get<CScriptID>(address); // address is a boost variant
|
||||
CScript script = CScript() << OP_HASH160 << ToByteVector(scriptID) << OP_EQUAL;
|
||||
return script;
|
||||
}
|
||||
|
|
|
@ -143,8 +143,9 @@ void ScriptPubKeyToUniv(const CScript& scriptPubKey,
|
|||
out.pushKV("type", GetTxnOutputType(type));
|
||||
|
||||
UniValue a(UniValue::VARR);
|
||||
BOOST_FOREACH(const CTxDestination& addr, addresses)
|
||||
a.push_back(CBitcoinAddress(addr).ToString());
|
||||
for (const CTxDestination& addr : addresses) {
|
||||
a.push_back(EncodeDestination(addr));
|
||||
}
|
||||
out.pushKV("addresses", a);
|
||||
}
|
||||
|
||||
|
|
|
@ -59,7 +59,7 @@ TEST(founders_reward_test, create_testnet_2of3multisig) {
|
|||
pWallet->AddCScript(result);
|
||||
pWallet->SetAddressBook(innerID, "", "receive");
|
||||
|
||||
std::string address = CBitcoinAddress(innerID).ToString();
|
||||
std::string address = EncodeDestination(innerID);
|
||||
addresses.push_back(address);
|
||||
}
|
||||
|
||||
|
|
|
@ -1079,8 +1079,8 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler)
|
|||
|
||||
#ifdef ENABLE_MINING
|
||||
if (mapArgs.count("-mineraddress")) {
|
||||
CBitcoinAddress addr;
|
||||
if (!addr.SetString(mapArgs["-mineraddress"])) {
|
||||
CTxDestination addr = DecodeDestination(mapArgs["-mineraddress"]);
|
||||
if (!IsValidDestination(addr)) {
|
||||
return InitError(strprintf(
|
||||
_("Invalid address for -mineraddress=<addr>: '%s' (must be a transparent address)"),
|
||||
mapArgs["-mineraddress"]));
|
||||
|
@ -1717,9 +1717,8 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler)
|
|||
bool minerAddressInLocalWallet = false;
|
||||
if (pwalletMain) {
|
||||
// Address has alreday been validated
|
||||
CBitcoinAddress addr(mapArgs["-mineraddress"]);
|
||||
CKeyID keyID;
|
||||
addr.GetKeyID(keyID);
|
||||
CTxDestination addr = DecodeDestination(mapArgs["-mineraddress"]);
|
||||
CKeyID keyID = boost::get<CKeyID>(addr);
|
||||
minerAddressInLocalWallet = pwalletMain->HaveKey(keyID);
|
||||
}
|
||||
if (GetBoolArg("-minetolocalwallet", true) && !minerAddressInLocalWallet) {
|
||||
|
|
|
@ -395,9 +395,9 @@ boost::optional<CScript> GetMinerScriptPubKey()
|
|||
#endif
|
||||
{
|
||||
CKeyID keyID;
|
||||
CBitcoinAddress addr;
|
||||
if (addr.SetString(GetArg("-mineraddress", ""))) {
|
||||
addr.GetKeyID(keyID);
|
||||
CTxDestination addr = DecodeDestination(GetArg("-mineraddress", ""));
|
||||
if (IsValidDestination(addr)) {
|
||||
keyID = boost::get<CKeyID>(addr);
|
||||
} else {
|
||||
#ifdef ENABLE_WALLET
|
||||
CPubKey pubkey;
|
||||
|
|
|
@ -137,8 +137,9 @@ public:
|
|||
obj.push_back(Pair("script", GetTxnOutputType(whichType)));
|
||||
obj.push_back(Pair("hex", HexStr(subscript.begin(), subscript.end())));
|
||||
UniValue a(UniValue::VARR);
|
||||
BOOST_FOREACH(const CTxDestination& addr, addresses)
|
||||
a.push_back(CBitcoinAddress(addr).ToString());
|
||||
for (const CTxDestination& addr : addresses) {
|
||||
a.push_back(EncodeDestination(addr));
|
||||
}
|
||||
obj.push_back(Pair("addresses", a));
|
||||
if (whichType == TX_MULTISIG)
|
||||
obj.push_back(Pair("sigsrequired", nRequired));
|
||||
|
@ -178,15 +179,14 @@ UniValue validateaddress(const UniValue& params, bool fHelp)
|
|||
LOCK(cs_main);
|
||||
#endif
|
||||
|
||||
CBitcoinAddress address(params[0].get_str());
|
||||
bool isValid = address.IsValid();
|
||||
CTxDestination dest = DecodeDestination(params[0].get_str());
|
||||
bool isValid = IsValidDestination(dest);
|
||||
|
||||
UniValue ret(UniValue::VOBJ);
|
||||
ret.push_back(Pair("isvalid", isValid));
|
||||
if (isValid)
|
||||
{
|
||||
CTxDestination dest = address.Get();
|
||||
string currentAddress = address.ToString();
|
||||
std::string currentAddress = EncodeDestination(dest);
|
||||
ret.push_back(Pair("address", currentAddress));
|
||||
|
||||
CScript scriptPubKey = GetScriptForDestination(dest);
|
||||
|
@ -293,17 +293,16 @@ CScript _createmultisig_redeemScript(const UniValue& params)
|
|||
const std::string& ks = keys[i].get_str();
|
||||
#ifdef ENABLE_WALLET
|
||||
// Case 1: Bitcoin address and we have full public key:
|
||||
CBitcoinAddress address(ks);
|
||||
if (pwalletMain && address.IsValid())
|
||||
{
|
||||
CKeyID keyID;
|
||||
if (!address.GetKeyID(keyID))
|
||||
throw runtime_error(
|
||||
strprintf("%s does not refer to a key",ks));
|
||||
CTxDestination dest = DecodeDestination(ks);
|
||||
if (pwalletMain && IsValidDestination(dest)) {
|
||||
const CKeyID *keyID = boost::get<CKeyID>(&dest);
|
||||
if (!keyID) {
|
||||
throw std::runtime_error(strprintf("%s does not refer to a key", ks));
|
||||
}
|
||||
CPubKey vchPubKey;
|
||||
if (!pwalletMain->GetPubKey(keyID, vchPubKey))
|
||||
throw runtime_error(
|
||||
strprintf("no full public key for address %s",ks));
|
||||
if (!pwalletMain->GetPubKey(*keyID, vchPubKey)) {
|
||||
throw std::runtime_error(strprintf("no full public key for address %s", ks));
|
||||
}
|
||||
if (!vchPubKey.IsFullyValid())
|
||||
throw runtime_error(" Invalid public key: "+ks);
|
||||
pubkeys[i] = vchPubKey;
|
||||
|
@ -367,10 +366,9 @@ UniValue createmultisig(const UniValue& params, bool fHelp)
|
|||
// Construct using pay-to-script-hash:
|
||||
CScript inner = _createmultisig_redeemScript(params);
|
||||
CScriptID innerID(inner);
|
||||
CBitcoinAddress address(innerID);
|
||||
|
||||
UniValue result(UniValue::VOBJ);
|
||||
result.push_back(Pair("address", address.ToString()));
|
||||
result.push_back(Pair("address", EncodeDestination(innerID)));
|
||||
result.push_back(Pair("redeemScript", HexStr(inner.begin(), inner.end())));
|
||||
|
||||
return result;
|
||||
|
@ -405,13 +403,15 @@ UniValue verifymessage(const UniValue& params, bool fHelp)
|
|||
string strSign = params[1].get_str();
|
||||
string strMessage = params[2].get_str();
|
||||
|
||||
CBitcoinAddress addr(strAddress);
|
||||
if (!addr.IsValid())
|
||||
CTxDestination destination = DecodeDestination(strAddress);
|
||||
if (!IsValidDestination(destination)) {
|
||||
throw JSONRPCError(RPC_TYPE_ERROR, "Invalid address");
|
||||
}
|
||||
|
||||
CKeyID keyID;
|
||||
if (!addr.GetKeyID(keyID))
|
||||
const CKeyID *keyID = boost::get<CKeyID>(&destination);
|
||||
if (!keyID) {
|
||||
throw JSONRPCError(RPC_TYPE_ERROR, "Address does not refer to key");
|
||||
}
|
||||
|
||||
bool fInvalid = false;
|
||||
vector<unsigned char> vchSig = DecodeBase64(strSign.c_str(), &fInvalid);
|
||||
|
@ -427,7 +427,7 @@ UniValue verifymessage(const UniValue& params, bool fHelp)
|
|||
if (!pubkey.RecoverCompact(ss.GetHash(), vchSig))
|
||||
return false;
|
||||
|
||||
return (pubkey.GetID() == keyID);
|
||||
return (pubkey.GetID() == *keyID);
|
||||
}
|
||||
|
||||
UniValue setmocktime(const UniValue& params, bool fHelp)
|
||||
|
|
|
@ -50,8 +50,9 @@ void ScriptPubKeyToJSON(const CScript& scriptPubKey, UniValue& out, bool fInclud
|
|||
out.push_back(Pair("type", GetTxnOutputType(type)));
|
||||
|
||||
UniValue a(UniValue::VARR);
|
||||
BOOST_FOREACH(const CTxDestination& addr, addresses)
|
||||
a.push_back(CBitcoinAddress(addr).ToString());
|
||||
for (const CTxDestination& addr : addresses) {
|
||||
a.push_back(EncodeDestination(addr));
|
||||
}
|
||||
out.push_back(Pair("addresses", a));
|
||||
}
|
||||
|
||||
|
@ -492,18 +493,19 @@ UniValue createrawtransaction(const UniValue& params, bool fHelp)
|
|||
rawTx.vin.push_back(in);
|
||||
}
|
||||
|
||||
set<CBitcoinAddress> setAddress;
|
||||
std::set<CTxDestination> destinations;
|
||||
vector<string> addrList = sendTo.getKeys();
|
||||
BOOST_FOREACH(const string& name_, addrList) {
|
||||
CBitcoinAddress address(name_);
|
||||
if (!address.IsValid())
|
||||
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, string("Invalid Zcash address: ")+name_);
|
||||
for (const std::string& name_ : addrList) {
|
||||
CTxDestination destination = DecodeDestination(name_);
|
||||
if (!IsValidDestination(destination)) {
|
||||
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, std::string("Invalid Zcash address: ") + name_);
|
||||
}
|
||||
|
||||
if (setAddress.count(address))
|
||||
throw JSONRPCError(RPC_INVALID_PARAMETER, string("Invalid parameter, duplicated address: ")+name_);
|
||||
setAddress.insert(address);
|
||||
if (!destinations.insert(destination).second) {
|
||||
throw JSONRPCError(RPC_INVALID_PARAMETER, std::string("Invalid parameter, duplicated address: ") + name_);
|
||||
}
|
||||
|
||||
CScript scriptPubKey = GetScriptForDestination(address.Get());
|
||||
CScript scriptPubKey = GetScriptForDestination(destination);
|
||||
CAmount nAmount = AmountFromValue(sendTo[name_]);
|
||||
|
||||
CTxOut out(nAmount, scriptPubKey);
|
||||
|
@ -646,7 +648,7 @@ UniValue decodescript(const UniValue& params, bool fHelp)
|
|||
}
|
||||
ScriptPubKeyToJSON(script, r, false);
|
||||
|
||||
r.push_back(Pair("p2sh", CBitcoinAddress(CScriptID(script)).ToString()));
|
||||
r.push_back(Pair("p2sh", EncodeDestination(CScriptID(script))));
|
||||
return r;
|
||||
}
|
||||
|
||||
|
|
|
@ -316,3 +316,7 @@ CScript GetScriptForMultisig(int nRequired, const std::vector<CPubKey>& keys)
|
|||
script << CScript::EncodeOP_N(keys.size()) << OP_CHECKMULTISIG;
|
||||
return script;
|
||||
}
|
||||
|
||||
bool IsValidDestination(const CTxDestination& dest) {
|
||||
return dest.which() != 0;
|
||||
}
|
||||
|
|
|
@ -78,10 +78,13 @@ public:
|
|||
* * CNoDestination: no destination set
|
||||
* * CKeyID: TX_PUBKEYHASH destination
|
||||
* * CScriptID: TX_SCRIPTHASH destination
|
||||
* A CTxDestination is the internal data type encoded in a CBitcoinAddress
|
||||
* A CTxDestination is the internal data type encoded in a bitcoin address
|
||||
*/
|
||||
typedef boost::variant<CNoDestination, CKeyID, CScriptID> CTxDestination;
|
||||
|
||||
/** Check whether a CTxDestination is a CNoDestination. */
|
||||
bool IsValidDestination(const CTxDestination& dest);
|
||||
|
||||
const char* GetTxnOutputType(txnouttype t);
|
||||
|
||||
bool Solver(const CScript& scriptPubKey, txnouttype& typeRet, std::vector<std::vector<unsigned char> >& vSolutionsRet);
|
||||
|
|
|
@ -123,7 +123,7 @@ BOOST_AUTO_TEST_CASE(base58_keys_valid_parse)
|
|||
UniValue tests = read_json(std::string(json_tests::base58_keys_valid, json_tests::base58_keys_valid + sizeof(json_tests::base58_keys_valid)));
|
||||
std::vector<unsigned char> result;
|
||||
CBitcoinSecret secret;
|
||||
CBitcoinAddress addr;
|
||||
CTxDestination destination;
|
||||
SelectParams(CBaseChainParams::MAIN);
|
||||
|
||||
for (size_t idx = 0; idx < tests.size(); idx++) {
|
||||
|
@ -147,7 +147,6 @@ BOOST_AUTO_TEST_CASE(base58_keys_valid_parse)
|
|||
{
|
||||
bool isCompressed = find_value(metadata, "isCompressed").get_bool();
|
||||
// Must be valid private key
|
||||
// Note: CBitcoinSecret::SetString tests isValid, whereas CBitcoinAddress does not!
|
||||
BOOST_CHECK_MESSAGE(secret.SetString(exp_base58string), "!SetString:"+ strTest);
|
||||
BOOST_CHECK_MESSAGE(secret.IsValid(), "!IsValid:" + strTest);
|
||||
CKey privkey = secret.GetKey();
|
||||
|
@ -155,18 +154,17 @@ BOOST_AUTO_TEST_CASE(base58_keys_valid_parse)
|
|||
BOOST_CHECK_MESSAGE(privkey.size() == exp_payload.size() && std::equal(privkey.begin(), privkey.end(), exp_payload.begin()), "key mismatch:" + strTest);
|
||||
|
||||
// Private key must be invalid public key
|
||||
addr.SetString(exp_base58string);
|
||||
BOOST_CHECK_MESSAGE(!addr.IsValid(), "IsValid privkey as pubkey:" + strTest);
|
||||
destination = DecodeDestination(exp_base58string);
|
||||
BOOST_CHECK_MESSAGE(!IsValidDestination(destination), "IsValid privkey as pubkey:" + strTest);
|
||||
}
|
||||
else
|
||||
{
|
||||
std::string exp_addrType = find_value(metadata, "addrType").get_str(); // "script" or "pubkey"
|
||||
// Must be valid public key
|
||||
BOOST_CHECK_MESSAGE(addr.SetString(exp_base58string), "SetString:" + strTest);
|
||||
BOOST_CHECK_MESSAGE(addr.IsValid(), "!IsValid:" + strTest);
|
||||
BOOST_CHECK_MESSAGE(addr.IsScript() == (exp_addrType == "script"), "isScript mismatch" + strTest);
|
||||
CTxDestination dest = addr.Get();
|
||||
BOOST_CHECK_MESSAGE(boost::apply_visitor(TestAddrTypeVisitor(exp_addrType), dest), "addrType mismatch" + strTest);
|
||||
destination = DecodeDestination(exp_base58string);
|
||||
BOOST_CHECK_MESSAGE(IsValidDestination(destination), "!IsValid:" + strTest);
|
||||
BOOST_CHECK_MESSAGE((boost::get<CScriptID>(&destination) != nullptr) == (exp_addrType == "script"), "isScript mismatch" + strTest);
|
||||
BOOST_CHECK_MESSAGE(boost::apply_visitor(TestAddrTypeVisitor(exp_addrType), destination), "addrType mismatch" + strTest);
|
||||
|
||||
// Public key must be invalid private key
|
||||
secret.SetString(exp_base58string);
|
||||
|
@ -229,17 +227,11 @@ BOOST_AUTO_TEST_CASE(base58_keys_valid_gen)
|
|||
BOOST_ERROR("Bad addrtype: " << strTest);
|
||||
continue;
|
||||
}
|
||||
CBitcoinAddress addrOut;
|
||||
BOOST_CHECK_MESSAGE(addrOut.Set(dest), "encode dest: " + strTest);
|
||||
BOOST_CHECK_MESSAGE(addrOut.ToString() == exp_base58string, "mismatch: " + strTest);
|
||||
std::string address = EncodeDestination(dest);
|
||||
BOOST_CHECK_MESSAGE(address == exp_base58string, "mismatch: " + strTest);
|
||||
}
|
||||
}
|
||||
|
||||
// Visiting a CNoDestination must fail
|
||||
CBitcoinAddress dummyAddr;
|
||||
CTxDestination nodest = CNoDestination();
|
||||
BOOST_CHECK(!dummyAddr.Set(nodest));
|
||||
|
||||
SelectParams(CBaseChainParams::MAIN);
|
||||
}
|
||||
|
||||
|
@ -249,7 +241,7 @@ BOOST_AUTO_TEST_CASE(base58_keys_invalid)
|
|||
UniValue tests = read_json(std::string(json_tests::base58_keys_invalid, json_tests::base58_keys_invalid + sizeof(json_tests::base58_keys_invalid))); // Negative testcases
|
||||
std::vector<unsigned char> result;
|
||||
CBitcoinSecret secret;
|
||||
CBitcoinAddress addr;
|
||||
CTxDestination destination;
|
||||
|
||||
for (size_t idx = 0; idx < tests.size(); idx++) {
|
||||
UniValue test = tests[idx];
|
||||
|
@ -262,8 +254,8 @@ BOOST_AUTO_TEST_CASE(base58_keys_invalid)
|
|||
std::string exp_base58string = test[0].get_str();
|
||||
|
||||
// must be invalid as public and as private key
|
||||
addr.SetString(exp_base58string);
|
||||
BOOST_CHECK_MESSAGE(!addr.IsValid(), "IsValid pubkey:" + strTest);
|
||||
destination = DecodeDestination(exp_base58string);
|
||||
BOOST_CHECK_MESSAGE(!IsValidDestination(destination), "IsValid pubkey:" + strTest);
|
||||
secret.SetString(exp_base58string);
|
||||
BOOST_CHECK_MESSAGE(!secret.IsValid(), "IsValid privkey:" + strTest);
|
||||
}
|
||||
|
|
|
@ -21,17 +21,16 @@
|
|||
using namespace std;
|
||||
using namespace libzcash;
|
||||
|
||||
static const string strSecret1 ("5HxWvvfubhXpYYpS3tJkw6fq9jE9j18THftkZjHHfmFiWtmAbrj");
|
||||
static const string strSecret2 ("5KC4ejrDjv152FGwP386VD1i2NYc5KkfSMyv1nGy1VGDxGHqVY3");
|
||||
static const string strSecret1C ("Kwr371tjA9u2rFSMZjTNun2PXXP3WPZu2afRHTcta6KxEUdm1vEw");
|
||||
static const string strSecret2C ("L3Hq7a8FEQwJkW1M2GNKDW28546Vp5miewcCzSqUD9kCAXrJdS3g");
|
||||
static const CBitcoinAddress addr1 ("t1h8SqgtM3QM5e2M8EzhhT1yL2PXXtA6oqe");
|
||||
static const CBitcoinAddress addr2 ("t1Xxa5ZVPKvs9bGMn7aWTiHjyHvR31XkUst");
|
||||
static const CBitcoinAddress addr1C("t1ffus9J1vhxvFqLoExGBRPjE7BcJxiSCTC");
|
||||
static const CBitcoinAddress addr2C("t1VJL2dPUyXK7avDRGqhqQA5bw2eEMdhyg6");
|
||||
static const std::string strSecret1 = "5HxWvvfubhXpYYpS3tJkw6fq9jE9j18THftkZjHHfmFiWtmAbrj";
|
||||
static const std::string strSecret2 = "5KC4ejrDjv152FGwP386VD1i2NYc5KkfSMyv1nGy1VGDxGHqVY3";
|
||||
static const std::string strSecret1C = "Kwr371tjA9u2rFSMZjTNun2PXXP3WPZu2afRHTcta6KxEUdm1vEw";
|
||||
static const std::string strSecret2C = "L3Hq7a8FEQwJkW1M2GNKDW28546Vp5miewcCzSqUD9kCAXrJdS3g";
|
||||
static const std::string addr1 = "t1h8SqgtM3QM5e2M8EzhhT1yL2PXXtA6oqe";
|
||||
static const std::string addr2 = "t1Xxa5ZVPKvs9bGMn7aWTiHjyHvR31XkUst";
|
||||
static const std::string addr1C = "t1ffus9J1vhxvFqLoExGBRPjE7BcJxiSCTC";
|
||||
static const std::string addr2C = "t1VJL2dPUyXK7avDRGqhqQA5bw2eEMdhyg6";
|
||||
|
||||
|
||||
static const string strAddressBad("t1aMkLwU1LcMZYN7TgXUJAwzA1r44dbLkSp");
|
||||
static const std::string strAddressBad = "t1aMkLwU1LcMZYN7TgXUJAwzA1r44dbLkSp";
|
||||
|
||||
|
||||
#ifdef KEY_TESTS_DUMPINFO
|
||||
|
@ -56,7 +55,7 @@ void dumpKeyInfo(uint256 privkey)
|
|||
key.SetSecret(secret, fCompressed);
|
||||
vector<unsigned char> vchPubKey = key.GetPubKey();
|
||||
printf(" * pubkey (hex): %s\n", HexStr(vchPubKey).c_str());
|
||||
printf(" * address (base58): %s\n", CBitcoinAddress(vchPubKey).ToString().c_str());
|
||||
printf(" * address (base58): %s\n", EncodeDestination(vchPubKey).c_str());
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
@ -107,10 +106,10 @@ BOOST_AUTO_TEST_CASE(key_test1)
|
|||
BOOST_CHECK(!key2C.VerifyPubKey(pubkey2));
|
||||
BOOST_CHECK(key2C.VerifyPubKey(pubkey2C));
|
||||
|
||||
BOOST_CHECK(addr1.Get() == CTxDestination(pubkey1.GetID()));
|
||||
BOOST_CHECK(addr2.Get() == CTxDestination(pubkey2.GetID()));
|
||||
BOOST_CHECK(addr1C.Get() == CTxDestination(pubkey1C.GetID()));
|
||||
BOOST_CHECK(addr2C.Get() == CTxDestination(pubkey2C.GetID()));
|
||||
BOOST_CHECK(DecodeDestination(addr1) == CTxDestination(pubkey1.GetID()));
|
||||
BOOST_CHECK(DecodeDestination(addr2) == CTxDestination(pubkey2.GetID()));
|
||||
BOOST_CHECK(DecodeDestination(addr1C) == CTxDestination(pubkey1C.GetID()));
|
||||
BOOST_CHECK(DecodeDestination(addr2C) == CTxDestination(pubkey2C.GetID()));
|
||||
|
||||
for (int n=0; n<16; n++)
|
||||
{
|
||||
|
|
|
@ -68,18 +68,18 @@ BOOST_AUTO_TEST_CASE(rpc_addmultisig)
|
|||
const char address2Hex[] = "0388c2037017c62240b6b72ac1a2a5f94da790596ebd06177c8572752922165cb4";
|
||||
|
||||
UniValue v;
|
||||
CBitcoinAddress address;
|
||||
CTxDestination address;
|
||||
BOOST_CHECK_NO_THROW(v = addmultisig(createArgs(1, address1Hex), false));
|
||||
address.SetString(v.get_str());
|
||||
BOOST_CHECK(address.IsValid() && address.IsScript());
|
||||
address = DecodeDestination(v.get_str());
|
||||
BOOST_CHECK(IsValidDestination(address) && boost::get<CScriptID>(&address) != nullptr);
|
||||
|
||||
BOOST_CHECK_NO_THROW(v = addmultisig(createArgs(1, address1Hex, address2Hex), false));
|
||||
address.SetString(v.get_str());
|
||||
BOOST_CHECK(address.IsValid() && address.IsScript());
|
||||
address = DecodeDestination(v.get_str());
|
||||
BOOST_CHECK(IsValidDestination(address) && boost::get<CScriptID>(&address) != nullptr);
|
||||
|
||||
BOOST_CHECK_NO_THROW(v = addmultisig(createArgs(2, address1Hex, address2Hex), false));
|
||||
address.SetString(v.get_str());
|
||||
BOOST_CHECK(address.IsValid() && address.IsScript());
|
||||
address = DecodeDestination(v.get_str());
|
||||
BOOST_CHECK(IsValidDestination(address) && boost::get<CScriptID>(&address) != nullptr);
|
||||
|
||||
BOOST_CHECK_THROW(addmultisig(createArgs(0), false), runtime_error);
|
||||
BOOST_CHECK_THROW(addmultisig(createArgs(1), false), runtime_error);
|
||||
|
@ -103,7 +103,7 @@ BOOST_AUTO_TEST_CASE(rpc_wallet)
|
|||
LOCK2(cs_main, pwalletMain->cs_wallet);
|
||||
|
||||
CPubKey demoPubkey = pwalletMain->GenerateNewKey();
|
||||
CBitcoinAddress demoAddress = CBitcoinAddress(CTxDestination(demoPubkey.GetID()));
|
||||
CTxDestination demoAddress(CTxDestination(demoPubkey.GetID()));
|
||||
UniValue retValue;
|
||||
string strAccount = "";
|
||||
string strPurpose = "receive";
|
||||
|
@ -116,14 +116,14 @@ BOOST_AUTO_TEST_CASE(rpc_wallet)
|
|||
});
|
||||
|
||||
CPubKey setaccountDemoPubkey = pwalletMain->GenerateNewKey();
|
||||
CBitcoinAddress setaccountDemoAddress = CBitcoinAddress(CTxDestination(setaccountDemoPubkey.GetID()));
|
||||
CTxDestination setaccountDemoAddress(CTxDestination(setaccountDemoPubkey.GetID()));
|
||||
|
||||
/*********************************
|
||||
* setaccount
|
||||
*********************************/
|
||||
BOOST_CHECK_NO_THROW(CallRPC("setaccount " + setaccountDemoAddress.ToString() + " \"\""));
|
||||
BOOST_CHECK_NO_THROW(CallRPC("setaccount " + EncodeDestination(setaccountDemoAddress) + " \"\""));
|
||||
/* Accounts are disabled */
|
||||
BOOST_CHECK_THROW(CallRPC("setaccount " + setaccountDemoAddress.ToString() + " nullaccount"), runtime_error);
|
||||
BOOST_CHECK_THROW(CallRPC("setaccount " + EncodeDestination(setaccountDemoAddress) + " nullaccount"), runtime_error);
|
||||
/* t1VtArtnn1dGPiD2WFfMXYXW5mHM3q1GpgV is not owned by the test wallet. */
|
||||
BOOST_CHECK_THROW(CallRPC("setaccount t1VtArtnn1dGPiD2WFfMXYXW5mHM3q1GpgV nullaccount"), runtime_error);
|
||||
BOOST_CHECK_THROW(CallRPC("setaccount"), runtime_error);
|
||||
|
@ -135,7 +135,7 @@ BOOST_AUTO_TEST_CASE(rpc_wallet)
|
|||
* getbalance
|
||||
*********************************/
|
||||
BOOST_CHECK_NO_THROW(CallRPC("getbalance"));
|
||||
BOOST_CHECK_THROW(CallRPC("getbalance " + demoAddress.ToString()), runtime_error);
|
||||
BOOST_CHECK_THROW(CallRPC("getbalance " + EncodeDestination(demoAddress)), runtime_error);
|
||||
|
||||
/*********************************
|
||||
* listunspent
|
||||
|
@ -177,10 +177,10 @@ BOOST_AUTO_TEST_CASE(rpc_wallet)
|
|||
* listtransactions
|
||||
*********************************/
|
||||
BOOST_CHECK_NO_THROW(CallRPC("listtransactions"));
|
||||
BOOST_CHECK_NO_THROW(CallRPC("listtransactions " + demoAddress.ToString()));
|
||||
BOOST_CHECK_NO_THROW(CallRPC("listtransactions " + demoAddress.ToString() + " 20"));
|
||||
BOOST_CHECK_NO_THROW(CallRPC("listtransactions " + demoAddress.ToString() + " 20 0"));
|
||||
BOOST_CHECK_THROW(CallRPC("listtransactions " + demoAddress.ToString() + " not_int"), runtime_error);
|
||||
BOOST_CHECK_NO_THROW(CallRPC("listtransactions " + EncodeDestination(demoAddress)));
|
||||
BOOST_CHECK_NO_THROW(CallRPC("listtransactions " + EncodeDestination(demoAddress) + " 20"));
|
||||
BOOST_CHECK_NO_THROW(CallRPC("listtransactions " + EncodeDestination(demoAddress) + " 20 0"));
|
||||
BOOST_CHECK_THROW(CallRPC("listtransactions " + EncodeDestination(demoAddress) + " not_int"), runtime_error);
|
||||
|
||||
/*********************************
|
||||
* listlockunspent
|
||||
|
@ -217,33 +217,33 @@ BOOST_AUTO_TEST_CASE(rpc_wallet)
|
|||
/* Accounts are deprecated */
|
||||
BOOST_CHECK_THROW(CallRPC("getaccountaddress accountThatDoesntExists"), runtime_error);
|
||||
BOOST_CHECK_NO_THROW(retValue = CallRPC("getaccountaddress " + strAccount));
|
||||
BOOST_CHECK(CBitcoinAddress(retValue.get_str()).Get() == demoAddress.Get());
|
||||
BOOST_CHECK(DecodeDestination(retValue.get_str()) == demoAddress);
|
||||
|
||||
/*********************************
|
||||
* getaccount
|
||||
*********************************/
|
||||
BOOST_CHECK_THROW(CallRPC("getaccount"), runtime_error);
|
||||
BOOST_CHECK_NO_THROW(CallRPC("getaccount " + demoAddress.ToString()));
|
||||
BOOST_CHECK_NO_THROW(CallRPC("getaccount " + EncodeDestination(demoAddress)));
|
||||
|
||||
/*********************************
|
||||
* signmessage + verifymessage
|
||||
*********************************/
|
||||
BOOST_CHECK_NO_THROW(retValue = CallRPC("signmessage " + demoAddress.ToString() + " mymessage"));
|
||||
BOOST_CHECK_NO_THROW(retValue = CallRPC("signmessage " + EncodeDestination(demoAddress) + " mymessage"));
|
||||
BOOST_CHECK_THROW(CallRPC("signmessage"), runtime_error);
|
||||
/* Should throw error because this address is not loaded in the wallet */
|
||||
BOOST_CHECK_THROW(CallRPC("signmessage t1h8SqgtM3QM5e2M8EzhhT1yL2PXXtA6oqe mymessage"), runtime_error);
|
||||
|
||||
/* missing arguments */
|
||||
BOOST_CHECK_THROW(CallRPC("verifymessage " + demoAddress.ToString()), runtime_error);
|
||||
BOOST_CHECK_THROW(CallRPC("verifymessage " + demoAddress.ToString() + " " + retValue.get_str()), runtime_error);
|
||||
BOOST_CHECK_THROW(CallRPC("verifymessage " + EncodeDestination(demoAddress)), runtime_error);
|
||||
BOOST_CHECK_THROW(CallRPC("verifymessage " + EncodeDestination(demoAddress) + " " + retValue.get_str()), runtime_error);
|
||||
/* Illegal address */
|
||||
BOOST_CHECK_THROW(CallRPC("verifymessage t1VtArtnn1dGPiD2WFfMXYXW5mHM3q1Gpg " + retValue.get_str() + " mymessage"), runtime_error);
|
||||
/* wrong address */
|
||||
BOOST_CHECK(CallRPC("verifymessage t1VtArtnn1dGPiD2WFfMXYXW5mHM3q1GpgV " + retValue.get_str() + " mymessage").get_bool() == false);
|
||||
/* Correct address and signature but wrong message */
|
||||
BOOST_CHECK(CallRPC("verifymessage " + demoAddress.ToString() + " " + retValue.get_str() + " wrongmessage").get_bool() == false);
|
||||
BOOST_CHECK(CallRPC("verifymessage " + EncodeDestination(demoAddress) + " " + retValue.get_str() + " wrongmessage").get_bool() == false);
|
||||
/* Correct address, message and signature*/
|
||||
BOOST_CHECK(CallRPC("verifymessage " + demoAddress.ToString() + " " + retValue.get_str() + " mymessage").get_bool() == true);
|
||||
BOOST_CHECK(CallRPC("verifymessage " + EncodeDestination(demoAddress) + " " + retValue.get_str() + " mymessage").get_bool() == true);
|
||||
|
||||
/*********************************
|
||||
* getaddressesbyaccount
|
||||
|
@ -254,7 +254,7 @@ BOOST_AUTO_TEST_CASE(rpc_wallet)
|
|||
BOOST_CHECK_EQUAL(4, arr.size());
|
||||
bool notFound = true;
|
||||
for (auto a : arr.getValues()) {
|
||||
notFound &= CBitcoinAddress(a.get_str()).Get() != demoAddress.Get();
|
||||
notFound &= DecodeDestination(a.get_str()) != demoAddress;
|
||||
}
|
||||
BOOST_CHECK(!notFound);
|
||||
|
||||
|
|
|
@ -73,8 +73,8 @@ AsyncRPCOperation_mergetoaddress::AsyncRPCOperation_mergetoaddress(
|
|||
throw JSONRPCError(RPC_INVALID_PARAMETER, "Recipient parameter missing");
|
||||
}
|
||||
|
||||
toTaddr_ = CBitcoinAddress(std::get<0>(recipient));
|
||||
isToTaddr_ = toTaddr_.IsValid();
|
||||
toTaddr_ = DecodeDestination(std::get<0>(recipient));
|
||||
isToTaddr_ = IsValidDestination(toTaddr_);
|
||||
isToZaddr_ = false;
|
||||
|
||||
if (!isToTaddr_) {
|
||||
|
@ -246,7 +246,7 @@ bool AsyncRPCOperation_mergetoaddress::main_impl()
|
|||
rawTx.vin.push_back(in);
|
||||
}
|
||||
if (isToTaddr_) {
|
||||
CScript scriptPubKey = GetScriptForDestination(toTaddr_.Get());
|
||||
CScript scriptPubKey = GetScriptForDestination(toTaddr_);
|
||||
CTxOut out(sendAmount, scriptPubKey);
|
||||
rawTx.vout.push_back(out);
|
||||
}
|
||||
|
|
|
@ -86,7 +86,7 @@ private:
|
|||
MergeToAddressRecipient recipient_;
|
||||
bool isToTaddr_;
|
||||
bool isToZaddr_;
|
||||
CBitcoinAddress toTaddr_;
|
||||
CTxDestination toTaddr_;
|
||||
PaymentAddress toPaymentAddress_;
|
||||
|
||||
uint256 joinSplitPubKey_;
|
||||
|
|
|
@ -74,8 +74,8 @@ AsyncRPCOperation_sendmany::AsyncRPCOperation_sendmany(
|
|||
throw JSONRPCError(RPC_INVALID_PARAMETER, "No recipients");
|
||||
}
|
||||
|
||||
fromtaddr_ = CBitcoinAddress(fromAddress);
|
||||
isfromtaddr_ = fromtaddr_.IsValid();
|
||||
fromtaddr_ = DecodeDestination(fromAddress);
|
||||
isfromtaddr_ = IsValidDestination(fromtaddr_);
|
||||
isfromzaddr_ = false;
|
||||
|
||||
if (!isfromtaddr_) {
|
||||
|
@ -829,7 +829,8 @@ void AsyncRPCOperation_sendmany::sign_send_raw_transaction(UniValue obj)
|
|||
|
||||
|
||||
bool AsyncRPCOperation_sendmany::find_utxos(bool fAcceptCoinbase=false) {
|
||||
set<CBitcoinAddress> setAddress = {fromtaddr_};
|
||||
std::set<CTxDestination> destinations;
|
||||
destinations.insert(fromtaddr_);
|
||||
vector<COutput> vecOutputs;
|
||||
|
||||
LOCK2(cs_main, pwalletMain->cs_wallet);
|
||||
|
@ -845,13 +846,13 @@ bool AsyncRPCOperation_sendmany::find_utxos(bool fAcceptCoinbase=false) {
|
|||
continue;
|
||||
}
|
||||
|
||||
if (setAddress.size()) {
|
||||
if (destinations.size()) {
|
||||
CTxDestination address;
|
||||
if (!ExtractDestination(out.tx->vout[out.i].scriptPubKey, address)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!setAddress.count(address)) {
|
||||
if (!destinations.count(address)) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
@ -1101,12 +1102,12 @@ void AsyncRPCOperation_sendmany::add_taddr_outputs_to_tx() {
|
|||
std::string outputAddress = std::get<0>(r);
|
||||
CAmount nAmount = std::get<1>(r);
|
||||
|
||||
CBitcoinAddress address(outputAddress);
|
||||
if (!address.IsValid()) {
|
||||
CTxDestination address = DecodeDestination(outputAddress);
|
||||
if (!IsValidDestination(address)) {
|
||||
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid output address, not a valid taddr.");
|
||||
}
|
||||
|
||||
CScript scriptPubKey = GetScriptForDestination(address.Get());
|
||||
CScript scriptPubKey = GetScriptForDestination(address);
|
||||
|
||||
CTxOut out(nAmount, scriptPubKey);
|
||||
rawTx.vout.push_back(out);
|
||||
|
|
|
@ -79,7 +79,7 @@ private:
|
|||
std::string fromaddress_;
|
||||
bool isfromtaddr_;
|
||||
bool isfromzaddr_;
|
||||
CBitcoinAddress fromtaddr_;
|
||||
CTxDestination fromtaddr_;
|
||||
PaymentAddress frompaymentaddress_;
|
||||
SpendingKey spendingkey_;
|
||||
|
||||
|
|
|
@ -129,7 +129,7 @@ UniValue importprivkey(const UniValue& params, bool fHelp)
|
|||
|
||||
// Don't throw error in case a key is already there
|
||||
if (pwalletMain->HaveKey(vchAddress)) {
|
||||
return CBitcoinAddress(vchAddress).ToString();
|
||||
return EncodeDestination(vchAddress);
|
||||
}
|
||||
|
||||
pwalletMain->mapKeyMetadata[vchAddress].nCreateTime = 1;
|
||||
|
@ -145,7 +145,7 @@ UniValue importprivkey(const UniValue& params, bool fHelp)
|
|||
}
|
||||
}
|
||||
|
||||
return CBitcoinAddress(vchAddress).ToString();
|
||||
return EncodeDestination(vchAddress);
|
||||
}
|
||||
|
||||
UniValue importaddress(const UniValue& params, bool fHelp)
|
||||
|
@ -175,9 +175,9 @@ UniValue importaddress(const UniValue& params, bool fHelp)
|
|||
|
||||
CScript script;
|
||||
|
||||
CBitcoinAddress address(params[0].get_str());
|
||||
if (address.IsValid()) {
|
||||
script = GetScriptForDestination(address.Get());
|
||||
CTxDestination dest = DecodeDestination(params[0].get_str());
|
||||
if (IsValidDestination(dest)) {
|
||||
script = GetScriptForDestination(dest);
|
||||
} else if (IsHex(params[0].get_str())) {
|
||||
std::vector<unsigned char> data(ParseHex(params[0].get_str()));
|
||||
script = CScript(data.begin(), data.end());
|
||||
|
@ -199,8 +199,8 @@ UniValue importaddress(const UniValue& params, bool fHelp)
|
|||
throw JSONRPCError(RPC_WALLET_ERROR, "The wallet already contains the private key for this address or script");
|
||||
|
||||
// add to address book or update label
|
||||
if (address.IsValid())
|
||||
pwalletMain->SetAddressBook(address.Get(), strLabel, "receive");
|
||||
if (IsValidDestination(dest))
|
||||
pwalletMain->SetAddressBook(dest, strLabel, "receive");
|
||||
|
||||
// Don't throw error in case an address is already there
|
||||
if (pwalletMain->HaveWatchOnly(script))
|
||||
|
@ -333,7 +333,7 @@ UniValue importwallet_impl(const UniValue& params, bool fHelp, bool fImportZKeys
|
|||
assert(key.VerifyPubKey(pubkey));
|
||||
CKeyID keyid = pubkey.GetID();
|
||||
if (pwalletMain->HaveKey(keyid)) {
|
||||
LogPrintf("Skipping import of %s (key already present)\n", CBitcoinAddress(keyid).ToString());
|
||||
LogPrintf("Skipping import of %s (key already present)\n", EncodeDestination(keyid));
|
||||
continue;
|
||||
}
|
||||
int64_t nTime = DecodeDumpTime(vstr[1]);
|
||||
|
@ -351,7 +351,7 @@ UniValue importwallet_impl(const UniValue& params, bool fHelp, bool fImportZKeys
|
|||
fLabel = true;
|
||||
}
|
||||
}
|
||||
LogPrintf("Importing %s...\n", CBitcoinAddress(keyid).ToString());
|
||||
LogPrintf("Importing %s...\n", EncodeDestination(keyid));
|
||||
if (!pwalletMain->AddKeyPubKey(key, pubkey)) {
|
||||
fGood = false;
|
||||
continue;
|
||||
|
@ -405,16 +405,19 @@ UniValue dumpprivkey(const UniValue& params, bool fHelp)
|
|||
|
||||
EnsureWalletIsUnlocked();
|
||||
|
||||
string strAddress = params[0].get_str();
|
||||
CBitcoinAddress address;
|
||||
if (!address.SetString(strAddress))
|
||||
std::string strAddress = params[0].get_str();
|
||||
CTxDestination dest = DecodeDestination(strAddress);
|
||||
if (!IsValidDestination(dest)) {
|
||||
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid Zcash address");
|
||||
CKeyID keyID;
|
||||
if (!address.GetKeyID(keyID))
|
||||
}
|
||||
const CKeyID *keyID = boost::get<CKeyID>(&dest);
|
||||
if (!keyID) {
|
||||
throw JSONRPCError(RPC_TYPE_ERROR, "Address does not refer to a key");
|
||||
}
|
||||
CKey vchSecret;
|
||||
if (!pwalletMain->GetKey(keyID, vchSecret))
|
||||
if (!pwalletMain->GetKey(*keyID, vchSecret)) {
|
||||
throw JSONRPCError(RPC_WALLET_ERROR, "Private key for address " + strAddress + " is not known");
|
||||
}
|
||||
return CBitcoinSecret(vchSecret).ToString();
|
||||
}
|
||||
|
||||
|
@ -515,7 +518,7 @@ UniValue dumpwallet_impl(const UniValue& params, bool fHelp, bool fDumpZKeys)
|
|||
for (std::vector<std::pair<int64_t, CKeyID> >::const_iterator it = vKeyBirth.begin(); it != vKeyBirth.end(); it++) {
|
||||
const CKeyID &keyid = it->second;
|
||||
std::string strTime = EncodeDumpTime(it->first);
|
||||
std::string strAddr = CBitcoinAddress(keyid).ToString();
|
||||
std::string strAddr = EncodeDestination(keyid);
|
||||
CKey key;
|
||||
if (pwalletMain->GetKey(keyid, key)) {
|
||||
if (pwalletMain->mapAddressBook.count(keyid)) {
|
||||
|
|
|
@ -146,11 +146,11 @@ UniValue getnewaddress(const UniValue& params, bool fHelp)
|
|||
|
||||
pwalletMain->SetAddressBook(keyID, strAccount, "receive");
|
||||
|
||||
return CBitcoinAddress(keyID).ToString();
|
||||
return EncodeDestination(keyID);
|
||||
}
|
||||
|
||||
|
||||
CBitcoinAddress GetAccountAddress(string strAccount, bool bForceNew=false)
|
||||
CTxDestination GetAccountAddress(std::string strAccount, bool bForceNew=false)
|
||||
{
|
||||
CWalletDB walletdb(pwalletMain->strWalletFile);
|
||||
|
||||
|
@ -184,7 +184,7 @@ CBitcoinAddress GetAccountAddress(string strAccount, bool bForceNew=false)
|
|||
walletdb.WriteAccount(strAccount, account);
|
||||
}
|
||||
|
||||
return CBitcoinAddress(account.vchPubKey.GetID());
|
||||
return account.vchPubKey.GetID();
|
||||
}
|
||||
|
||||
UniValue getaccountaddress(const UniValue& params, bool fHelp)
|
||||
|
@ -214,7 +214,7 @@ UniValue getaccountaddress(const UniValue& params, bool fHelp)
|
|||
|
||||
UniValue ret(UniValue::VSTR);
|
||||
|
||||
ret = GetAccountAddress(strAccount).ToString();
|
||||
ret = EncodeDestination(GetAccountAddress(strAccount));
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -250,7 +250,7 @@ UniValue getrawchangeaddress(const UniValue& params, bool fHelp)
|
|||
|
||||
CKeyID keyID = vchPubKey.GetID();
|
||||
|
||||
return CBitcoinAddress(keyID).ToString();
|
||||
return EncodeDestination(keyID);
|
||||
}
|
||||
|
||||
|
||||
|
@ -273,25 +273,25 @@ UniValue setaccount(const UniValue& params, bool fHelp)
|
|||
|
||||
LOCK2(cs_main, pwalletMain->cs_wallet);
|
||||
|
||||
CBitcoinAddress address(params[0].get_str());
|
||||
if (!address.IsValid())
|
||||
CTxDestination dest = DecodeDestination(params[0].get_str());
|
||||
if (!IsValidDestination(dest)) {
|
||||
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid Zcash address");
|
||||
}
|
||||
|
||||
string strAccount;
|
||||
if (params.size() > 1)
|
||||
strAccount = AccountFromValue(params[1]);
|
||||
|
||||
// Only add the account if the address is yours.
|
||||
if (IsMine(*pwalletMain, address.Get()))
|
||||
{
|
||||
if (IsMine(*pwalletMain, dest)) {
|
||||
// Detect when changing the account of an address that is the 'unused current key' of another account:
|
||||
if (pwalletMain->mapAddressBook.count(address.Get()))
|
||||
{
|
||||
string strOldAccount = pwalletMain->mapAddressBook[address.Get()].name;
|
||||
if (address == GetAccountAddress(strOldAccount))
|
||||
if (pwalletMain->mapAddressBook.count(dest)) {
|
||||
std::string strOldAccount = pwalletMain->mapAddressBook[dest].name;
|
||||
if (dest == GetAccountAddress(strOldAccount)) {
|
||||
GetAccountAddress(strOldAccount, true);
|
||||
}
|
||||
pwalletMain->SetAddressBook(address.Get(), strAccount, "receive");
|
||||
}
|
||||
pwalletMain->SetAddressBook(dest, strAccount, "receive");
|
||||
}
|
||||
else
|
||||
throw JSONRPCError(RPC_MISC_ERROR, "setaccount can only be used with own address");
|
||||
|
@ -320,14 +320,16 @@ UniValue getaccount(const UniValue& params, bool fHelp)
|
|||
|
||||
LOCK2(cs_main, pwalletMain->cs_wallet);
|
||||
|
||||
CBitcoinAddress address(params[0].get_str());
|
||||
if (!address.IsValid())
|
||||
CTxDestination dest = DecodeDestination(params[0].get_str());
|
||||
if (!IsValidDestination(dest)) {
|
||||
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid Zcash address");
|
||||
}
|
||||
|
||||
string strAccount;
|
||||
map<CTxDestination, CAddressBookData>::iterator mi = pwalletMain->mapAddressBook.find(address.Get());
|
||||
if (mi != pwalletMain->mapAddressBook.end() && !(*mi).second.name.empty())
|
||||
std::string strAccount;
|
||||
std::map<CTxDestination, CAddressBookData>::iterator mi = pwalletMain->mapAddressBook.find(dest);
|
||||
if (mi != pwalletMain->mapAddressBook.end() && !(*mi).second.name.empty()) {
|
||||
strAccount = (*mi).second.name;
|
||||
}
|
||||
return strAccount;
|
||||
}
|
||||
|
||||
|
@ -359,12 +361,12 @@ UniValue getaddressesbyaccount(const UniValue& params, bool fHelp)
|
|||
|
||||
// Find all addresses that have the given account
|
||||
UniValue ret(UniValue::VARR);
|
||||
BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, CAddressBookData)& item, pwalletMain->mapAddressBook)
|
||||
{
|
||||
const CBitcoinAddress& address = item.first;
|
||||
const string& strName = item.second.name;
|
||||
if (strName == strAccount)
|
||||
ret.push_back(address.ToString());
|
||||
for (const std::pair<CTxDestination, CAddressBookData>& item : pwalletMain->mapAddressBook) {
|
||||
const CTxDestination& dest = item.first;
|
||||
const std::string& strName = item.second.name;
|
||||
if (strName == strAccount) {
|
||||
ret.push_back(EncodeDestination(dest));
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
@ -431,9 +433,10 @@ UniValue sendtoaddress(const UniValue& params, bool fHelp)
|
|||
|
||||
LOCK2(cs_main, pwalletMain->cs_wallet);
|
||||
|
||||
CBitcoinAddress address(params[0].get_str());
|
||||
if (!address.IsValid())
|
||||
CTxDestination dest = DecodeDestination(params[0].get_str());
|
||||
if (!IsValidDestination(dest)) {
|
||||
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid Zcash address");
|
||||
}
|
||||
|
||||
// Amount
|
||||
CAmount nAmount = AmountFromValue(params[1]);
|
||||
|
@ -453,7 +456,7 @@ UniValue sendtoaddress(const UniValue& params, bool fHelp)
|
|||
|
||||
EnsureWalletIsUnlocked();
|
||||
|
||||
SendMoney(address.Get(), nAmount, fSubtractFeeFromAmount, wtx);
|
||||
SendMoney(dest, nAmount, fSubtractFeeFromAmount, wtx);
|
||||
|
||||
return wtx.GetHash().GetHex();
|
||||
}
|
||||
|
@ -489,18 +492,18 @@ UniValue listaddressgroupings(const UniValue& params, bool fHelp)
|
|||
LOCK2(cs_main, pwalletMain->cs_wallet);
|
||||
|
||||
UniValue jsonGroupings(UniValue::VARR);
|
||||
map<CTxDestination, CAmount> balances = pwalletMain->GetAddressBalances();
|
||||
BOOST_FOREACH(set<CTxDestination> grouping, pwalletMain->GetAddressGroupings())
|
||||
{
|
||||
std::map<CTxDestination, CAmount> balances = pwalletMain->GetAddressBalances();
|
||||
for (const std::set<CTxDestination>& grouping : pwalletMain->GetAddressGroupings()) {
|
||||
UniValue jsonGrouping(UniValue::VARR);
|
||||
BOOST_FOREACH(CTxDestination address, grouping)
|
||||
for (const CTxDestination& address : grouping)
|
||||
{
|
||||
UniValue addressInfo(UniValue::VARR);
|
||||
addressInfo.push_back(CBitcoinAddress(address).ToString());
|
||||
addressInfo.push_back(EncodeDestination(address));
|
||||
addressInfo.push_back(ValueFromAmount(balances[address]));
|
||||
{
|
||||
if (pwalletMain->mapAddressBook.find(CBitcoinAddress(address).Get()) != pwalletMain->mapAddressBook.end())
|
||||
addressInfo.push_back(pwalletMain->mapAddressBook.find(CBitcoinAddress(address).Get())->second.name);
|
||||
if (pwalletMain->mapAddressBook.find(address) != pwalletMain->mapAddressBook.end()) {
|
||||
addressInfo.push_back(pwalletMain->mapAddressBook.find(address)->second.name);
|
||||
}
|
||||
}
|
||||
jsonGrouping.push_back(addressInfo);
|
||||
}
|
||||
|
@ -542,17 +545,20 @@ UniValue signmessage(const UniValue& params, bool fHelp)
|
|||
string strAddress = params[0].get_str();
|
||||
string strMessage = params[1].get_str();
|
||||
|
||||
CBitcoinAddress addr(strAddress);
|
||||
if (!addr.IsValid())
|
||||
CTxDestination dest = DecodeDestination(strAddress);
|
||||
if (!IsValidDestination(dest)) {
|
||||
throw JSONRPCError(RPC_TYPE_ERROR, "Invalid address");
|
||||
}
|
||||
|
||||
CKeyID keyID;
|
||||
if (!addr.GetKeyID(keyID))
|
||||
const CKeyID *keyID = boost::get<CKeyID>(&dest);
|
||||
if (!keyID) {
|
||||
throw JSONRPCError(RPC_TYPE_ERROR, "Address does not refer to key");
|
||||
}
|
||||
|
||||
CKey key;
|
||||
if (!pwalletMain->GetKey(keyID, key))
|
||||
if (!pwalletMain->GetKey(*keyID, key)) {
|
||||
throw JSONRPCError(RPC_WALLET_ERROR, "Private key not available");
|
||||
}
|
||||
|
||||
CHashWriter ss(SER_GETHASH, 0);
|
||||
ss << strMessageMagic;
|
||||
|
@ -593,12 +599,14 @@ UniValue getreceivedbyaddress(const UniValue& params, bool fHelp)
|
|||
LOCK2(cs_main, pwalletMain->cs_wallet);
|
||||
|
||||
// Bitcoin address
|
||||
CBitcoinAddress address = CBitcoinAddress(params[0].get_str());
|
||||
if (!address.IsValid())
|
||||
CTxDestination dest = DecodeDestination(params[0].get_str());
|
||||
if (!IsValidDestination(dest)) {
|
||||
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid Zcash address");
|
||||
CScript scriptPubKey = GetScriptForDestination(address.Get());
|
||||
if (!IsMine(*pwalletMain, scriptPubKey))
|
||||
}
|
||||
CScript scriptPubKey = GetScriptForDestination(dest);
|
||||
if (!IsMine(*pwalletMain, scriptPubKey)) {
|
||||
return ValueFromAmount(0);
|
||||
}
|
||||
|
||||
// Minimum confirmations
|
||||
int nMinDepth = 1;
|
||||
|
@ -907,10 +915,11 @@ UniValue sendfrom(const UniValue& params, bool fHelp)
|
|||
|
||||
LOCK2(cs_main, pwalletMain->cs_wallet);
|
||||
|
||||
string strAccount = AccountFromValue(params[0]);
|
||||
CBitcoinAddress address(params[1].get_str());
|
||||
if (!address.IsValid())
|
||||
std::string strAccount = AccountFromValue(params[0]);
|
||||
CTxDestination dest = DecodeDestination(params[1].get_str());
|
||||
if (!IsValidDestination(dest)) {
|
||||
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid Zcash address");
|
||||
}
|
||||
CAmount nAmount = AmountFromValue(params[2]);
|
||||
if (nAmount <= 0)
|
||||
throw JSONRPCError(RPC_TYPE_ERROR, "Invalid amount for send");
|
||||
|
@ -932,7 +941,7 @@ UniValue sendfrom(const UniValue& params, bool fHelp)
|
|||
if (nAmount > nBalance)
|
||||
throw JSONRPCError(RPC_WALLET_INSUFFICIENT_FUNDS, "Account has insufficient funds");
|
||||
|
||||
SendMoney(address.Get(), nAmount, false, wtx);
|
||||
SendMoney(dest, nAmount, false, wtx);
|
||||
|
||||
return wtx.GetHash().GetHex();
|
||||
}
|
||||
|
@ -996,22 +1005,23 @@ UniValue sendmany(const UniValue& params, bool fHelp)
|
|||
if (params.size() > 4)
|
||||
subtractFeeFromAmount = params[4].get_array();
|
||||
|
||||
set<CBitcoinAddress> setAddress;
|
||||
vector<CRecipient> vecSend;
|
||||
std::set<CTxDestination> destinations;
|
||||
std::vector<CRecipient> vecSend;
|
||||
|
||||
CAmount totalAmount = 0;
|
||||
vector<string> keys = sendTo.getKeys();
|
||||
BOOST_FOREACH(const string& name_, keys)
|
||||
{
|
||||
CBitcoinAddress address(name_);
|
||||
if (!address.IsValid())
|
||||
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, string("Invalid Zcash address: ")+name_);
|
||||
std::vector<std::string> keys = sendTo.getKeys();
|
||||
for (const std::string& name_ : keys) {
|
||||
CTxDestination dest = DecodeDestination(name_);
|
||||
if (!IsValidDestination(dest)) {
|
||||
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, std::string("Invalid Zcash address: ") + name_);
|
||||
}
|
||||
|
||||
if (setAddress.count(address))
|
||||
throw JSONRPCError(RPC_INVALID_PARAMETER, string("Invalid parameter, duplicated address: ")+name_);
|
||||
setAddress.insert(address);
|
||||
if (destinations.count(dest)) {
|
||||
throw JSONRPCError(RPC_INVALID_PARAMETER, std::string("Invalid parameter, duplicated address: ") + name_);
|
||||
}
|
||||
destinations.insert(dest);
|
||||
|
||||
CScript scriptPubKey = GetScriptForDestination(address.Get());
|
||||
CScript scriptPubKey = GetScriptForDestination(dest);
|
||||
CAmount nAmount = AmountFromValue(sendTo[name_]);
|
||||
if (nAmount <= 0)
|
||||
throw JSONRPCError(RPC_TYPE_ERROR, "Invalid amount for send");
|
||||
|
@ -1097,7 +1107,7 @@ UniValue addmultisigaddress(const UniValue& params, bool fHelp)
|
|||
pwalletMain->AddCScript(inner);
|
||||
|
||||
pwalletMain->SetAddressBook(innerID, strAccount, "send");
|
||||
return CBitcoinAddress(innerID).ToString();
|
||||
return EncodeDestination(innerID);
|
||||
}
|
||||
|
||||
|
||||
|
@ -1133,10 +1143,9 @@ UniValue ListReceived(const UniValue& params, bool fByAccounts)
|
|||
filter = filter | ISMINE_WATCH_ONLY;
|
||||
|
||||
// Tally
|
||||
map<CBitcoinAddress, tallyitem> mapTally;
|
||||
for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
|
||||
{
|
||||
const CWalletTx& wtx = (*it).second;
|
||||
std::map<CTxDestination, tallyitem> mapTally;
|
||||
for (const std::pair<uint256, CWalletTx>& pairWtx : pwalletMain->mapWallet) {
|
||||
const CWalletTx& wtx = pairWtx.second;
|
||||
|
||||
if (wtx.IsCoinBase() || !CheckFinalTx(wtx))
|
||||
continue;
|
||||
|
@ -1166,12 +1175,11 @@ UniValue ListReceived(const UniValue& params, bool fByAccounts)
|
|||
|
||||
// Reply
|
||||
UniValue ret(UniValue::VARR);
|
||||
map<string, tallyitem> mapAccountTally;
|
||||
BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, CAddressBookData)& item, pwalletMain->mapAddressBook)
|
||||
{
|
||||
const CBitcoinAddress& address = item.first;
|
||||
const string& strAccount = item.second.name;
|
||||
map<CBitcoinAddress, tallyitem>::iterator it = mapTally.find(address);
|
||||
std::map<std::string, tallyitem> mapAccountTally;
|
||||
for (const std::pair<CTxDestination, CAddressBookData>& item : pwalletMain->mapAddressBook) {
|
||||
const CTxDestination& dest = item.first;
|
||||
const std::string& strAccount = item.second.name;
|
||||
std::map<CTxDestination, tallyitem>::iterator it = mapTally.find(dest);
|
||||
if (it == mapTally.end() && !fIncludeEmpty)
|
||||
continue;
|
||||
|
||||
|
@ -1197,7 +1205,7 @@ UniValue ListReceived(const UniValue& params, bool fByAccounts)
|
|||
UniValue obj(UniValue::VOBJ);
|
||||
if(fIsWatchonly)
|
||||
obj.push_back(Pair("involvesWatchonly", true));
|
||||
obj.push_back(Pair("address", address.ToString()));
|
||||
obj.push_back(Pair("address", EncodeDestination(dest)));
|
||||
obj.push_back(Pair("account", strAccount));
|
||||
obj.push_back(Pair("amount", ValueFromAmount(nAmount)));
|
||||
obj.push_back(Pair("confirmations", (nConf == std::numeric_limits<int>::max() ? 0 : nConf)));
|
||||
|
@ -1308,9 +1316,9 @@ UniValue listreceivedbyaccount(const UniValue& params, bool fHelp)
|
|||
|
||||
static void MaybePushAddress(UniValue & entry, const CTxDestination &dest)
|
||||
{
|
||||
CBitcoinAddress addr;
|
||||
if (addr.Set(dest))
|
||||
entry.push_back(Pair("address", addr.ToString()));
|
||||
if (IsValidDestination(dest)) {
|
||||
entry.push_back(Pair("address", EncodeDestination(dest)));
|
||||
}
|
||||
}
|
||||
|
||||
void ListTransactions(const CWalletTx& wtx, const string& strAccount, int nMinDepth, bool fLong, UniValue& ret, const isminefilter& filter)
|
||||
|
@ -2367,17 +2375,18 @@ UniValue listunspent(const UniValue& params, bool fHelp)
|
|||
if (params.size() > 1)
|
||||
nMaxDepth = params[1].get_int();
|
||||
|
||||
set<CBitcoinAddress> setAddress;
|
||||
std::set<CTxDestination> destinations;
|
||||
if (params.size() > 2) {
|
||||
UniValue inputs = params[2].get_array();
|
||||
for (size_t idx = 0; idx < inputs.size(); idx++) {
|
||||
const UniValue& input = inputs[idx];
|
||||
CBitcoinAddress address(input.get_str());
|
||||
if (!address.IsValid())
|
||||
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, string("Invalid Zcash address: ")+input.get_str());
|
||||
if (setAddress.count(address))
|
||||
throw JSONRPCError(RPC_INVALID_PARAMETER, string("Invalid parameter, duplicated address: ")+input.get_str());
|
||||
setAddress.insert(address);
|
||||
CTxDestination dest = DecodeDestination(input.get_str());
|
||||
if (!IsValidDestination(dest)) {
|
||||
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, std::string("Invalid Zcash address: ") + input.get_str());
|
||||
}
|
||||
if (!destinations.insert(dest).second) {
|
||||
throw JSONRPCError(RPC_INVALID_PARAMETER, std::string("Invalid parameter, duplicated address: ") + input.get_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2394,7 +2403,7 @@ UniValue listunspent(const UniValue& params, bool fHelp)
|
|||
const CScript& scriptPubKey = out.tx->vout[out.i].scriptPubKey;
|
||||
bool fValidAddress = ExtractDestination(scriptPubKey, address);
|
||||
|
||||
if (setAddress.size() && (!fValidAddress || !setAddress.count(address)))
|
||||
if (destinations.size() && (!fValidAddress || !destinations.count(address)))
|
||||
continue;
|
||||
|
||||
UniValue entry(UniValue::VOBJ);
|
||||
|
@ -2403,7 +2412,7 @@ UniValue listunspent(const UniValue& params, bool fHelp)
|
|||
entry.push_back(Pair("generated", out.tx->IsCoinBase()));
|
||||
|
||||
if (fValidAddress) {
|
||||
entry.push_back(Pair("address", CBitcoinAddress(address).ToString()));
|
||||
entry.push_back(Pair("address", EncodeDestination(address)));
|
||||
|
||||
if (pwalletMain->mapAddressBook.count(address))
|
||||
entry.push_back(Pair("account", pwalletMain->mapAddressBook[address].name));
|
||||
|
@ -3129,16 +3138,16 @@ UniValue z_listaddresses(const UniValue& params, bool fHelp)
|
|||
}
|
||||
|
||||
CAmount getBalanceTaddr(std::string transparentAddress, int minDepth=1, bool ignoreUnspendable=true) {
|
||||
set<CBitcoinAddress> setAddress;
|
||||
std::set<CTxDestination> destinations;
|
||||
vector<COutput> vecOutputs;
|
||||
CAmount balance = 0;
|
||||
|
||||
if (transparentAddress.length() > 0) {
|
||||
CBitcoinAddress taddr = CBitcoinAddress(transparentAddress);
|
||||
if (!taddr.IsValid()) {
|
||||
CTxDestination taddr = DecodeDestination(transparentAddress);
|
||||
if (!IsValidDestination(taddr)) {
|
||||
throw std::runtime_error("invalid transparent address");
|
||||
}
|
||||
setAddress.insert(taddr);
|
||||
destinations.insert(taddr);
|
||||
}
|
||||
|
||||
LOCK2(cs_main, pwalletMain->cs_wallet);
|
||||
|
@ -3154,13 +3163,13 @@ CAmount getBalanceTaddr(std::string transparentAddress, int minDepth=1, bool ign
|
|||
continue;
|
||||
}
|
||||
|
||||
if (setAddress.size()) {
|
||||
if (destinations.size()) {
|
||||
CTxDestination address;
|
||||
if (!ExtractDestination(out.tx->vout[out.i].scriptPubKey, address)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!setAddress.count(address)) {
|
||||
if (!destinations.count(address)) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
@ -3288,8 +3297,8 @@ UniValue z_getbalance(const UniValue& params, bool fHelp)
|
|||
// Check that the from address is valid.
|
||||
auto fromaddress = params[0].get_str();
|
||||
bool fromTaddr = false;
|
||||
CBitcoinAddress taddr(fromaddress);
|
||||
fromTaddr = taddr.IsValid();
|
||||
CTxDestination taddr = DecodeDestination(fromaddress);
|
||||
fromTaddr = IsValidDestination(taddr);
|
||||
libzcash::PaymentAddress zaddr;
|
||||
if (!fromTaddr) {
|
||||
CZCPaymentAddress address(fromaddress);
|
||||
|
@ -3522,8 +3531,8 @@ UniValue z_sendmany(const UniValue& params, bool fHelp)
|
|||
// Check that the from address is valid.
|
||||
auto fromaddress = params[0].get_str();
|
||||
bool fromTaddr = false;
|
||||
CBitcoinAddress taddr(fromaddress);
|
||||
fromTaddr = taddr.IsValid();
|
||||
CTxDestination taddr = DecodeDestination(fromaddress);
|
||||
fromTaddr = IsValidDestination(taddr);
|
||||
libzcash::PaymentAddress zaddr;
|
||||
if (!fromTaddr) {
|
||||
CZCPaymentAddress address(fromaddress);
|
||||
|
@ -3568,8 +3577,8 @@ UniValue z_sendmany(const UniValue& params, bool fHelp)
|
|||
|
||||
string address = find_value(o, "address").get_str();
|
||||
bool isZaddr = false;
|
||||
CBitcoinAddress taddr(address);
|
||||
if (!taddr.IsValid()) {
|
||||
CTxDestination taddr = DecodeDestination(address);
|
||||
if (!IsValidDestination(taddr)) {
|
||||
try {
|
||||
CZCPaymentAddress zaddr(address);
|
||||
zaddr.Get();
|
||||
|
@ -3743,10 +3752,10 @@ UniValue z_shieldcoinbase(const UniValue& params, bool fHelp)
|
|||
// Validate the from address
|
||||
auto fromaddress = params[0].get_str();
|
||||
bool isFromWildcard = fromaddress == "*";
|
||||
CBitcoinAddress taddr;
|
||||
CTxDestination taddr;
|
||||
if (!isFromWildcard) {
|
||||
taddr = CBitcoinAddress(fromaddress);
|
||||
if (!taddr.IsValid()) {
|
||||
taddr = DecodeDestination(fromaddress);
|
||||
if (!IsValidDestination(taddr)) {
|
||||
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid from address, should be a taddr or \"*\".");
|
||||
}
|
||||
}
|
||||
|
@ -3791,9 +3800,9 @@ UniValue z_shieldcoinbase(const UniValue& params, bool fHelp)
|
|||
size_t mempoolLimit = (nLimit != 0) ? nLimit : (overwinterActive ? 0 : (size_t)GetArg("-mempooltxinputlimit", 0));
|
||||
|
||||
// Set of addresses to filter utxos by
|
||||
set<CBitcoinAddress> setAddress = {};
|
||||
std::set<CTxDestination> destinations = {};
|
||||
if (!isFromWildcard) {
|
||||
setAddress.insert(taddr);
|
||||
destinations.insert(taddr);
|
||||
}
|
||||
|
||||
// Get available utxos
|
||||
|
@ -3811,7 +3820,7 @@ UniValue z_shieldcoinbase(const UniValue& params, bool fHelp)
|
|||
continue;
|
||||
}
|
||||
// If taddr is not wildcard "*", filter utxos
|
||||
if (setAddress.size()>0 && !setAddress.count(address)) {
|
||||
if (destinations.size() > 0 && !destinations.count(address)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -3823,8 +3832,7 @@ UniValue z_shieldcoinbase(const UniValue& params, bool fHelp)
|
|||
CAmount nValue = out.tx->vout[out.i].nValue;
|
||||
|
||||
if (!maxedOutFlag) {
|
||||
CBitcoinAddress ba(address);
|
||||
size_t increase = (ba.IsScript()) ? CTXIN_SPEND_P2SH_SIZE : CTXIN_SPEND_DUST_SIZE;
|
||||
size_t increase = (boost::get<CScriptID>(&address) != nullptr) ? CTXIN_SPEND_P2SH_SIZE : CTXIN_SPEND_DUST_SIZE;
|
||||
if (estimatedTxSize + increase >= MAX_TX_SIZE ||
|
||||
(mempoolLimit > 0 && utxoCounter > mempoolLimit))
|
||||
{
|
||||
|
@ -3967,7 +3975,7 @@ UniValue z_mergetoaddress(const UniValue& params, bool fHelp)
|
|||
bool useAny = false;
|
||||
bool useAnyUTXO = false;
|
||||
bool useAnyNote = false;
|
||||
std::set<CBitcoinAddress> taddrs = {};
|
||||
std::set<CTxDestination> taddrs = {};
|
||||
std::set<libzcash::PaymentAddress> zaddrs = {};
|
||||
|
||||
UniValue addresses = params[0].get_array();
|
||||
|
@ -3990,8 +3998,8 @@ UniValue z_mergetoaddress(const UniValue& params, bool fHelp)
|
|||
} else if (address == "ANY_ZADDR") {
|
||||
useAnyNote = true;
|
||||
} else {
|
||||
CBitcoinAddress taddr(address);
|
||||
if (taddr.IsValid()) {
|
||||
CTxDestination taddr = DecodeDestination(address);
|
||||
if (IsValidDestination(taddr)) {
|
||||
// Ignore any listed t-addrs if we are using all of them
|
||||
if (!(useAny || useAnyUTXO)) {
|
||||
taddrs.insert(taddr);
|
||||
|
@ -4019,8 +4027,8 @@ UniValue z_mergetoaddress(const UniValue& params, bool fHelp)
|
|||
// Validate the destination address
|
||||
auto destaddress = params[1].get_str();
|
||||
bool isToZaddr = false;
|
||||
CBitcoinAddress taddr(destaddress);
|
||||
if (!taddr.IsValid()) {
|
||||
CTxDestination taddr = DecodeDestination(destaddress);
|
||||
if (!IsValidDestination(taddr)) {
|
||||
try {
|
||||
CZCPaymentAddress zaddr(destaddress);
|
||||
zaddr.Get();
|
||||
|
@ -4116,8 +4124,7 @@ UniValue z_mergetoaddress(const UniValue& params, bool fHelp)
|
|||
CAmount nValue = out.tx->vout[out.i].nValue;
|
||||
|
||||
if (!maxedOutUTXOsFlag) {
|
||||
CBitcoinAddress ba(address);
|
||||
size_t increase = (ba.IsScript()) ? CTXIN_SPEND_P2SH_SIZE : CTXIN_SPEND_DUST_SIZE;
|
||||
size_t increase = (boost::get<CScriptID>(&address) != nullptr) ? CTXIN_SPEND_P2SH_SIZE : CTXIN_SPEND_DUST_SIZE;
|
||||
if (estimatedTxSize + increase >= MAX_TX_SIZE ||
|
||||
(mempoolLimit > 0 && utxoCounter > mempoolLimit))
|
||||
{
|
||||
|
|
|
@ -300,7 +300,7 @@ bool CWallet::LoadCScript(const CScript& redeemScript)
|
|||
* these. Do not add them to the wallet and warn. */
|
||||
if (redeemScript.size() > MAX_SCRIPT_ELEMENT_SIZE)
|
||||
{
|
||||
std::string strAddr = CBitcoinAddress(CScriptID(redeemScript)).ToString();
|
||||
std::string strAddr = EncodeDestination(CScriptID(redeemScript));
|
||||
LogPrintf("%s: Warning: This wallet contains a redeemScript of size %i which exceeds maximum size %i thus can never be redeemed. Do not use address %s.\n",
|
||||
__func__, redeemScript.size(), MAX_SCRIPT_ELEMENT_SIZE, strAddr);
|
||||
return true;
|
||||
|
@ -3018,9 +3018,9 @@ bool CWallet::SetAddressBook(const CTxDestination& address, const string& strNam
|
|||
strPurpose, (fUpdated ? CT_UPDATED : CT_NEW) );
|
||||
if (!fFileBacked)
|
||||
return false;
|
||||
if (!strPurpose.empty() && !CWalletDB(strWalletFile).WritePurpose(CBitcoinAddress(address).ToString(), strPurpose))
|
||||
if (!strPurpose.empty() && !CWalletDB(strWalletFile).WritePurpose(EncodeDestination(address), strPurpose))
|
||||
return false;
|
||||
return CWalletDB(strWalletFile).WriteName(CBitcoinAddress(address).ToString(), strName);
|
||||
return CWalletDB(strWalletFile).WriteName(EncodeDestination(address), strName);
|
||||
}
|
||||
|
||||
bool CWallet::DelAddressBook(const CTxDestination& address)
|
||||
|
@ -3031,7 +3031,7 @@ bool CWallet::DelAddressBook(const CTxDestination& address)
|
|||
if(fFileBacked)
|
||||
{
|
||||
// Delete destdata tuples associated with address
|
||||
std::string strAddress = CBitcoinAddress(address).ToString();
|
||||
std::string strAddress = EncodeDestination(address);
|
||||
BOOST_FOREACH(const PAIRTYPE(string, string) &item, mapAddressBook[address].destdata)
|
||||
{
|
||||
CWalletDB(strWalletFile).EraseDestData(strAddress, item.first);
|
||||
|
@ -3044,8 +3044,8 @@ bool CWallet::DelAddressBook(const CTxDestination& address)
|
|||
|
||||
if (!fFileBacked)
|
||||
return false;
|
||||
CWalletDB(strWalletFile).ErasePurpose(CBitcoinAddress(address).ToString());
|
||||
return CWalletDB(strWalletFile).EraseName(CBitcoinAddress(address).ToString());
|
||||
CWalletDB(strWalletFile).ErasePurpose(EncodeDestination(address));
|
||||
return CWalletDB(strWalletFile).EraseName(EncodeDestination(address));
|
||||
}
|
||||
|
||||
bool CWallet::SetDefaultKey(const CPubKey &vchPubKey)
|
||||
|
@ -3573,7 +3573,7 @@ bool CWallet::AddDestData(const CTxDestination &dest, const std::string &key, co
|
|||
mapAddressBook[dest].destdata.insert(std::make_pair(key, value));
|
||||
if (!fFileBacked)
|
||||
return true;
|
||||
return CWalletDB(strWalletFile).WriteDestData(CBitcoinAddress(dest).ToString(), key, value);
|
||||
return CWalletDB(strWalletFile).WriteDestData(EncodeDestination(dest), key, value);
|
||||
}
|
||||
|
||||
bool CWallet::EraseDestData(const CTxDestination &dest, const std::string &key)
|
||||
|
@ -3582,7 +3582,7 @@ bool CWallet::EraseDestData(const CTxDestination &dest, const std::string &key)
|
|||
return false;
|
||||
if (!fFileBacked)
|
||||
return true;
|
||||
return CWalletDB(strWalletFile).EraseDestData(CBitcoinAddress(dest).ToString(), key);
|
||||
return CWalletDB(strWalletFile).EraseDestData(EncodeDestination(dest), key);
|
||||
}
|
||||
|
||||
bool CWallet::LoadDestData(const CTxDestination &dest, const std::string &key, const std::string &value)
|
||||
|
|
|
@ -409,13 +409,13 @@ ReadKeyValue(CWallet* pwallet, CDataStream& ssKey, CDataStream& ssValue,
|
|||
{
|
||||
string strAddress;
|
||||
ssKey >> strAddress;
|
||||
ssValue >> pwallet->mapAddressBook[CBitcoinAddress(strAddress).Get()].name;
|
||||
ssValue >> pwallet->mapAddressBook[DecodeDestination(strAddress)].name;
|
||||
}
|
||||
else if (strType == "purpose")
|
||||
{
|
||||
string strAddress;
|
||||
ssKey >> strAddress;
|
||||
ssValue >> pwallet->mapAddressBook[CBitcoinAddress(strAddress).Get()].purpose;
|
||||
ssValue >> pwallet->mapAddressBook[DecodeDestination(strAddress)].purpose;
|
||||
}
|
||||
else if (strType == "tx")
|
||||
{
|
||||
|
@ -698,7 +698,7 @@ ReadKeyValue(CWallet* pwallet, CDataStream& ssKey, CDataStream& ssValue,
|
|||
ssKey >> strAddress;
|
||||
ssKey >> strKey;
|
||||
ssValue >> strValue;
|
||||
if (!pwallet->LoadDestData(CBitcoinAddress(strAddress).Get(), strKey, strValue))
|
||||
if (!pwallet->LoadDestData(DecodeDestination(strAddress), strKey, strValue))
|
||||
{
|
||||
strErr = "Error reading wallet database: LoadDestData failed";
|
||||
return false;
|
||||
|
|
Loading…
Reference in New Issue