Sapling transaction testing
This commit is contained in:
@@ -213,6 +213,7 @@ public:
|
|||||||
CBitcoinAddressVisitor(CBitcoinAddress* addrIn) : addr(addrIn) {}
|
CBitcoinAddressVisitor(CBitcoinAddress* addrIn) : addr(addrIn) {}
|
||||||
|
|
||||||
bool operator()(const CKeyID& id) const { return addr->Set(id); }
|
bool operator()(const CKeyID& id) const { return addr->Set(id); }
|
||||||
|
bool operator()(const CPubKey& key) const { return addr->Set(key); }
|
||||||
bool operator()(const CScriptID& id) const { return addr->Set(id); }
|
bool operator()(const CScriptID& id) const { return addr->Set(id); }
|
||||||
bool operator()(const CNoDestination& no) const { return false; }
|
bool operator()(const CNoDestination& no) const { return false; }
|
||||||
};
|
};
|
||||||
@@ -225,6 +226,13 @@ bool CBitcoinAddress::Set(const CKeyID& id)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool CBitcoinAddress::Set(const CPubKey& key)
|
||||||
|
{
|
||||||
|
CKeyID id = key.GetID();
|
||||||
|
SetData(Params().Base58Prefix(CChainParams::PUBKEY_ADDRESS), &id, 20);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
bool CBitcoinAddress::Set(const CScriptID& id)
|
bool CBitcoinAddress::Set(const CScriptID& id)
|
||||||
{
|
{
|
||||||
SetData(Params().Base58Prefix(CChainParams::SCRIPT_ADDRESS), &id, 20);
|
SetData(Params().Base58Prefix(CChainParams::SCRIPT_ADDRESS), &id, 20);
|
||||||
|
|||||||
@@ -116,6 +116,7 @@ public:
|
|||||||
class CBitcoinAddress : public CBase58Data {
|
class CBitcoinAddress : public CBase58Data {
|
||||||
public:
|
public:
|
||||||
bool Set(const CKeyID &id);
|
bool Set(const CKeyID &id);
|
||||||
|
bool Set(const CPubKey &key);
|
||||||
bool Set(const CScriptID &id);
|
bool Set(const CScriptID &id);
|
||||||
bool Set(const CTxDestination &dest);
|
bool Set(const CTxDestination &dest);
|
||||||
bool IsValid() const;
|
bool IsValid() const;
|
||||||
|
|||||||
@@ -115,9 +115,9 @@ public:
|
|||||||
consensus.vUpgrades[Consensus::UPGRADE_TESTDUMMY].nActivationHeight =
|
consensus.vUpgrades[Consensus::UPGRADE_TESTDUMMY].nActivationHeight =
|
||||||
Consensus::NetworkUpgrade::NO_ACTIVATION_HEIGHT;
|
Consensus::NetworkUpgrade::NO_ACTIVATION_HEIGHT;
|
||||||
consensus.vUpgrades[Consensus::UPGRADE_OVERWINTER].nProtocolVersion = 170005;
|
consensus.vUpgrades[Consensus::UPGRADE_OVERWINTER].nProtocolVersion = 170005;
|
||||||
consensus.vUpgrades[Consensus::UPGRADE_OVERWINTER].nActivationHeight = 227520;
|
consensus.vUpgrades[Consensus::UPGRADE_OVERWINTER].nActivationHeight = 1;
|
||||||
consensus.vUpgrades[Consensus::UPGRADE_SAPLING].nProtocolVersion = 170007;
|
consensus.vUpgrades[Consensus::UPGRADE_SAPLING].nProtocolVersion = 170007;
|
||||||
consensus.vUpgrades[Consensus::UPGRADE_SAPLING].nActivationHeight = 227520;
|
consensus.vUpgrades[Consensus::UPGRADE_SAPLING].nActivationHeight = 1;
|
||||||
|
|
||||||
// The best chain should have at least this much work.
|
// The best chain should have at least this much work.
|
||||||
consensus.nMinimumChainWork = uint256S("0x00000000000000000000000000000000000000000000000000281b32ff3198a1");
|
consensus.nMinimumChainWork = uint256S("0x00000000000000000000000000000000000000000000000000281b32ff3198a1");
|
||||||
|
|||||||
@@ -34,6 +34,14 @@ public:
|
|||||||
return EncodeBase58Check(data);
|
return EncodeBase58Check(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string operator()(const CPubKey& key) const
|
||||||
|
{
|
||||||
|
std::vector<unsigned char> data = m_params.Base58Prefix(CChainParams::PUBKEY_ADDRESS);
|
||||||
|
CKeyID id = key.GetID();
|
||||||
|
data.insert(data.end(), id.begin(), id.end());
|
||||||
|
return EncodeBase58Check(data);
|
||||||
|
}
|
||||||
|
|
||||||
std::string operator()(const CScriptID& id) const
|
std::string operator()(const CScriptID& id) const
|
||||||
{
|
{
|
||||||
std::vector<unsigned char> data = m_params.Base58Prefix(CChainParams::SCRIPT_ADDRESS);
|
std::vector<unsigned char> data = m_params.Base58Prefix(CChainParams::SCRIPT_ADDRESS);
|
||||||
@@ -286,10 +294,7 @@ libzcash::PaymentAddress DecodePaymentAddress(const std::string& str)
|
|||||||
}
|
}
|
||||||
data.clear();
|
data.clear();
|
||||||
auto bech = bech32::Decode(str);
|
auto bech = bech32::Decode(str);
|
||||||
bool allowSapling = Params().NetworkIDString() == "regtest" || (
|
bool allowSapling = true;
|
||||||
Params().NetworkIDString() == "test" &&
|
|
||||||
GetBoolArg("-experimentalfeatures", false) &&
|
|
||||||
GetBoolArg("-developersapling", false));
|
|
||||||
if (allowSapling && bech.first == Params().Bech32HRP(CChainParams::SAPLING_PAYMENT_ADDRESS) &&
|
if (allowSapling && bech.first == Params().Bech32HRP(CChainParams::SAPLING_PAYMENT_ADDRESS) &&
|
||||||
bech.second.size() == ConvertedSaplingPaymentAddressSize) {
|
bech.second.size() == ConvertedSaplingPaymentAddressSize) {
|
||||||
// Bech32 decoding
|
// Bech32 decoding
|
||||||
@@ -356,10 +361,7 @@ libzcash::SpendingKey DecodeSpendingKey(const std::string& str)
|
|||||||
}
|
}
|
||||||
data.clear();
|
data.clear();
|
||||||
auto bech = bech32::Decode(str);
|
auto bech = bech32::Decode(str);
|
||||||
bool allowSapling = Params().NetworkIDString() == "regtest" || (
|
bool allowSapling = true;
|
||||||
Params().NetworkIDString() == "test" &&
|
|
||||||
GetBoolArg("-experimentalfeatures", false) &&
|
|
||||||
GetBoolArg("-developersapling", false));
|
|
||||||
if (allowSapling && bech.first == Params().Bech32HRP(CChainParams::SAPLING_EXTENDED_SPEND_KEY) &&
|
if (allowSapling && bech.first == Params().Bech32HRP(CChainParams::SAPLING_EXTENDED_SPEND_KEY) &&
|
||||||
bech.second.size() == ConvertedSaplingExtendedSpendingKeySize) {
|
bech.second.size() == ConvertedSaplingExtendedSpendingKeySize) {
|
||||||
// Bech32 decoding
|
// Bech32 decoding
|
||||||
|
|||||||
@@ -870,6 +870,8 @@ bool AreInputsStandard(const CTransaction& tx, const CCoinsViewCache& mapInputs,
|
|||||||
txnouttype whichType;
|
txnouttype whichType;
|
||||||
// get the scriptPubKey corresponding to this input:
|
// get the scriptPubKey corresponding to this input:
|
||||||
const CScript& prevScript = prev.scriptPubKey;
|
const CScript& prevScript = prev.scriptPubKey;
|
||||||
|
//printf("Previous script: %s\n", prevScript.ToString().c_str());
|
||||||
|
|
||||||
if (!Solver(prevScript, whichType, vSolutions))
|
if (!Solver(prevScript, whichType, vSolutions))
|
||||||
return false;
|
return false;
|
||||||
int nArgsExpected = ScriptSigArgsExpected(whichType, vSolutions);
|
int nArgsExpected = ScriptSigArgsExpected(whichType, vSolutions);
|
||||||
@@ -883,6 +885,7 @@ bool AreInputsStandard(const CTransaction& tx, const CCoinsViewCache& mapInputs,
|
|||||||
// IsStandardTx() will have already returned false
|
// IsStandardTx() will have already returned false
|
||||||
// and this method isn't called.
|
// and this method isn't called.
|
||||||
vector<vector<unsigned char> > stack;
|
vector<vector<unsigned char> > stack;
|
||||||
|
//printf("Checking script: %s\n", tx.vin[i].scriptSig.ToString().c_str());
|
||||||
if (!EvalScript(stack, tx.vin[i].scriptSig, SCRIPT_VERIFY_NONE, BaseSignatureChecker(), consensusBranchId))
|
if (!EvalScript(stack, tx.vin[i].scriptSig, SCRIPT_VERIFY_NONE, BaseSignatureChecker(), consensusBranchId))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
|||||||
@@ -224,12 +224,26 @@ public:
|
|||||||
CPubKey vchPubKey;
|
CPubKey vchPubKey;
|
||||||
obj.push_back(Pair("isscript", false));
|
obj.push_back(Pair("isscript", false));
|
||||||
if (pwalletMain && pwalletMain->GetPubKey(keyID, vchPubKey)) {
|
if (pwalletMain && pwalletMain->GetPubKey(keyID, vchPubKey)) {
|
||||||
obj.push_back(Pair("pubkey", HexStr(vchPubKey)));
|
obj.push_back(Pair("pubkey", HexStr(vchPubKey))); // should return pubkeyhash, but not sure about compatibility impact
|
||||||
obj.push_back(Pair("iscompressed", vchPubKey.IsCompressed()));
|
obj.push_back(Pair("iscompressed", vchPubKey.IsCompressed()));
|
||||||
}
|
}
|
||||||
return obj;
|
return obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
UniValue operator()(const CPubKey &key) const {
|
||||||
|
UniValue obj(UniValue::VOBJ);
|
||||||
|
obj.push_back(Pair("isscript", false));
|
||||||
|
if (pwalletMain && key.IsValid()) {
|
||||||
|
obj.push_back(Pair("pubkey", HexStr(key)));
|
||||||
|
obj.push_back(Pair("iscompressed", key.IsCompressed()));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
obj.push_back(Pair("pubkey", "invalid"));
|
||||||
|
}
|
||||||
|
return obj;
|
||||||
|
}
|
||||||
|
|
||||||
UniValue operator()(const CScriptID &scriptID) const {
|
UniValue operator()(const CScriptID &scriptID) const {
|
||||||
UniValue obj(UniValue::VOBJ);
|
UniValue obj(UniValue::VOBJ);
|
||||||
CScript subscript;
|
CScript subscript;
|
||||||
|
|||||||
@@ -234,7 +234,7 @@ bool IsStandard(const CScript& scriptPubKey, txnouttype& whichType)
|
|||||||
return whichType != TX_NONSTANDARD;
|
return whichType != TX_NONSTANDARD;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ExtractDestination(const CScript& _scriptPubKey, CTxDestination& addressRet)
|
bool ExtractDestination(const CScript& _scriptPubKey, CTxDestination& addressRet, bool returnPubKey)
|
||||||
{
|
{
|
||||||
vector<valtype> vSolutions;
|
vector<valtype> vSolutions;
|
||||||
txnouttype whichType;
|
txnouttype whichType;
|
||||||
@@ -262,9 +262,13 @@ bool ExtractDestination(const CScript& _scriptPubKey, CTxDestination& addressRet
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
addressRet = pubKey.GetID();
|
if (returnPubKey)
|
||||||
|
addressRet = pubKey;
|
||||||
|
else
|
||||||
|
addressRet = pubKey.GetID();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
else if (whichType == TX_PUBKEYHASH)
|
else if (whichType == TX_PUBKEYHASH)
|
||||||
{
|
{
|
||||||
addressRet = CKeyID(uint160(vSolutions[0]));
|
addressRet = CKeyID(uint160(vSolutions[0]));
|
||||||
@@ -355,6 +359,12 @@ public:
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool operator()(const CPubKey &key) const {
|
||||||
|
script->clear();
|
||||||
|
*script << ToByteVector(key) << OP_CHECKSIG;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
bool operator()(const CKeyID &keyID) const {
|
bool operator()(const CKeyID &keyID) const {
|
||||||
script->clear();
|
script->clear();
|
||||||
*script << OP_DUP << OP_HASH160 << ToByteVector(keyID) << OP_EQUALVERIFY << OP_CHECKSIG;
|
*script << OP_DUP << OP_HASH160 << ToByteVector(keyID) << OP_EQUALVERIFY << OP_CHECKSIG;
|
||||||
|
|||||||
@@ -81,7 +81,7 @@ public:
|
|||||||
* * CScriptID: TX_SCRIPTHASH destination
|
* * CScriptID: TX_SCRIPTHASH destination
|
||||||
* A CTxDestination is the internal data type encoded in a bitcoin address
|
* A CTxDestination is the internal data type encoded in a bitcoin address
|
||||||
*/
|
*/
|
||||||
typedef boost::variant<CNoDestination, CKeyID, CScriptID> CTxDestination;
|
typedef boost::variant<CNoDestination, CPubKey, CKeyID, CScriptID> CTxDestination;
|
||||||
|
|
||||||
/** Check whether a CTxDestination is a CNoDestination. */
|
/** Check whether a CTxDestination is a CNoDestination. */
|
||||||
bool IsValidDestination(const CTxDestination& dest);
|
bool IsValidDestination(const CTxDestination& dest);
|
||||||
@@ -91,7 +91,7 @@ const char* GetTxnOutputType(txnouttype t);
|
|||||||
bool Solver(const CScript& scriptPubKey, txnouttype& typeRet, std::vector<std::vector<unsigned char> >& vSolutionsRet);
|
bool Solver(const CScript& scriptPubKey, txnouttype& typeRet, std::vector<std::vector<unsigned char> >& vSolutionsRet);
|
||||||
int ScriptSigArgsExpected(txnouttype t, const std::vector<std::vector<unsigned char> >& vSolutions);
|
int ScriptSigArgsExpected(txnouttype t, const std::vector<std::vector<unsigned char> >& vSolutions);
|
||||||
bool IsStandard(const CScript& scriptPubKey, txnouttype& whichType);
|
bool IsStandard(const CScript& scriptPubKey, txnouttype& whichType);
|
||||||
bool ExtractDestination(const CScript& scriptPubKey, CTxDestination& addressRet);
|
bool ExtractDestination(const CScript& scriptPubKey, CTxDestination& addressRet, bool returnPubKey=false);
|
||||||
bool ExtractDestinations(const CScript& scriptPubKey, txnouttype& typeRet, std::vector<CTxDestination>& addressRet, int& nRequiredRet);
|
bool ExtractDestinations(const CScript& scriptPubKey, txnouttype& typeRet, std::vector<CTxDestination>& addressRet, int& nRequiredRet);
|
||||||
|
|
||||||
CScript GetScriptForDestination(const CTxDestination& dest);
|
CScript GetScriptForDestination(const CTxDestination& dest);
|
||||||
|
|||||||
@@ -342,8 +342,10 @@ bool AsyncRPCOperation_sendmany::main_impl() {
|
|||||||
|
|
||||||
// update the transaction with these inputs
|
// update the transaction with these inputs
|
||||||
if (isUsingBuilder_) {
|
if (isUsingBuilder_) {
|
||||||
CScript scriptPubKey = GetScriptForDestination(fromtaddr_);
|
CScript scriptPubKey;
|
||||||
for (auto t : t_inputs_) {
|
for (auto t : t_inputs_) {
|
||||||
|
scriptPubKey = GetScriptForDestination(std::get<4>(t));
|
||||||
|
//printf("Checking new script: %s\n", scriptPubKey.ToString().c_str());
|
||||||
uint256 txid = std::get<0>(t);
|
uint256 txid = std::get<0>(t);
|
||||||
int vout = std::get<1>(t);
|
int vout = std::get<1>(t);
|
||||||
CAmount amount = std::get<2>(t);
|
CAmount amount = std::get<2>(t);
|
||||||
@@ -993,17 +995,20 @@ void AsyncRPCOperation_sendmany::sign_send_raw_transaction(UniValue obj)
|
|||||||
tx_ = tx;
|
tx_ = tx;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool AsyncRPCOperation_sendmany::find_utxos(bool fAcceptCoinbase=false) {
|
bool AsyncRPCOperation_sendmany::find_utxos(bool fAcceptCoinbase=false) {
|
||||||
std::set<CTxDestination> destinations;
|
std::set<CTxDestination> destinations;
|
||||||
destinations.insert(fromtaddr_);
|
destinations.insert(fromtaddr_);
|
||||||
|
|
||||||
|
//printf("Looking for %s\n", boost::apply_visitor(AddressVisitorString(), fromtaddr_).c_str());
|
||||||
|
|
||||||
vector<COutput> vecOutputs;
|
vector<COutput> vecOutputs;
|
||||||
|
|
||||||
LOCK2(cs_main, pwalletMain->cs_wallet);
|
LOCK2(cs_main, pwalletMain->cs_wallet);
|
||||||
|
|
||||||
pwalletMain->AvailableCoins(vecOutputs, false, NULL, true, fAcceptCoinbase);
|
pwalletMain->AvailableCoins(vecOutputs, false, NULL, true, fAcceptCoinbase);
|
||||||
|
|
||||||
BOOST_FOREACH(const COutput& out, vecOutputs) {
|
BOOST_FOREACH(const COutput& out, vecOutputs) {
|
||||||
|
CTxDestination dest;
|
||||||
|
|
||||||
if (!out.fSpendable) {
|
if (!out.fSpendable) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -1012,13 +1017,15 @@ bool AsyncRPCOperation_sendmany::find_utxos(bool fAcceptCoinbase=false) {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const CScript &scriptPubKey = out.tx->vout[out.i].scriptPubKey;
|
||||||
|
|
||||||
if (destinations.size()) {
|
if (destinations.size()) {
|
||||||
CTxDestination address;
|
if (!ExtractDestination(scriptPubKey, dest)) {
|
||||||
if (!ExtractDestination(out.tx->vout[out.i].scriptPubKey, address)) {
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!destinations.count(address)) {
|
//printf("%s\n", boost::apply_visitor(AddressVisitorString(), dest).c_str());
|
||||||
|
if (!destinations.count(dest)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1029,8 +1036,12 @@ bool AsyncRPCOperation_sendmany::find_utxos(bool fAcceptCoinbase=false) {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!ExtractDestination(scriptPubKey, dest, true))
|
||||||
|
continue;
|
||||||
|
|
||||||
CAmount nValue = out.tx->vout[out.i].nValue;
|
CAmount nValue = out.tx->vout[out.i].nValue;
|
||||||
SendManyInputUTXO utxo(out.tx->GetHash(), out.i, nValue, isCoinbase);
|
|
||||||
|
SendManyInputUTXO utxo(out.tx->GetHash(), out.i, nValue, isCoinbase, dest);
|
||||||
t_inputs_.push_back(utxo);
|
t_inputs_.push_back(utxo);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ using namespace libzcash;
|
|||||||
typedef std::tuple<std::string, CAmount, std::string> SendManyRecipient;
|
typedef std::tuple<std::string, CAmount, std::string> SendManyRecipient;
|
||||||
|
|
||||||
// Input UTXO is a tuple (quadruple) of txid, vout, amount, coinbase)
|
// Input UTXO is a tuple (quadruple) of txid, vout, amount, coinbase)
|
||||||
typedef std::tuple<uint256, int, CAmount, bool> SendManyInputUTXO;
|
typedef std::tuple<uint256, int, CAmount, bool, CTxDestination> SendManyInputUTXO;
|
||||||
|
|
||||||
// Input JSOP is a tuple of JSOutpoint, note and amount
|
// Input JSOP is a tuple of JSOutpoint, note and amount
|
||||||
typedef std::tuple<JSOutPoint, SproutNote, CAmount> SendManyInputJSOP;
|
typedef std::tuple<JSOutPoint, SproutNote, CAmount> SendManyInputJSOP;
|
||||||
|
|||||||
@@ -77,7 +77,7 @@ AsyncRPCOperation_shieldcoinbase::AsyncRPCOperation_shieldcoinbase(
|
|||||||
auto address = DecodePaymentAddress(toAddress);
|
auto address = DecodePaymentAddress(toAddress);
|
||||||
if (IsValidPaymentAddress(address)) {
|
if (IsValidPaymentAddress(address)) {
|
||||||
// TODO: Add Sapling support. For now, ensure we can freely convert.
|
// TODO: Add Sapling support. For now, ensure we can freely convert.
|
||||||
assert(boost::get<libzcash::SproutPaymentAddress>(&address) != nullptr);
|
// assert(boost::get<libzcash::SproutPaymentAddress>(&address) != nullptr);
|
||||||
tozaddr_ = address;
|
tozaddr_ = address;
|
||||||
} else {
|
} else {
|
||||||
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid to address");
|
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid to address");
|
||||||
|
|||||||
@@ -3451,7 +3451,9 @@ UniValue z_getnewaddress(const UniValue& params, bool fHelp)
|
|||||||
if (!EnsureWalletIsAvailable(fHelp))
|
if (!EnsureWalletIsAvailable(fHelp))
|
||||||
return NullUniValue;
|
return NullUniValue;
|
||||||
|
|
||||||
std::string defaultType = ADDR_TYPE_SPROUT;
|
bool allowSapling = (Params().GetConsensus().vUpgrades[Consensus::UPGRADE_SAPLING].nActivationHeight <= chainActive.LastTip()->nHeight);
|
||||||
|
|
||||||
|
std::string defaultType = allowSapling ? ADDR_TYPE_SAPLING : ADDR_TYPE_SPROUT;
|
||||||
|
|
||||||
if (fHelp || params.size() > 1)
|
if (fHelp || params.size() > 1)
|
||||||
throw runtime_error(
|
throw runtime_error(
|
||||||
@@ -3478,10 +3480,6 @@ UniValue z_getnewaddress(const UniValue& params, bool fHelp)
|
|||||||
addrType = params[0].get_str();
|
addrType = params[0].get_str();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool allowSapling = Params().NetworkIDString() == "regtest" || (
|
|
||||||
Params().NetworkIDString() == "test" &&
|
|
||||||
GetBoolArg("-experimentalfeatures", false) &&
|
|
||||||
GetBoolArg("-developersapling", false));
|
|
||||||
if (addrType == ADDR_TYPE_SPROUT) {
|
if (addrType == ADDR_TYPE_SPROUT) {
|
||||||
return EncodePaymentAddress(pwalletMain->GenerateNewZKey());
|
return EncodePaymentAddress(pwalletMain->GenerateNewZKey());
|
||||||
} else if (addrType == ADDR_TYPE_SAPLING && allowSapling) {
|
} else if (addrType == ADDR_TYPE_SAPLING && allowSapling) {
|
||||||
|
|||||||
@@ -4406,6 +4406,12 @@ public:
|
|||||||
vKeys.push_back(keyId);
|
vKeys.push_back(keyId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void operator()(const CPubKey &key) {
|
||||||
|
CKeyID keyId = key.GetID();
|
||||||
|
if (keystore.HaveKey(keyId))
|
||||||
|
vKeys.push_back(keyId);
|
||||||
|
}
|
||||||
|
|
||||||
void operator()(const CScriptID &scriptId) {
|
void operator()(const CScriptID &scriptId) {
|
||||||
CScript script;
|
CScript script;
|
||||||
if (keystore.GetCScript(scriptId, script))
|
if (keystore.GetCScript(scriptId, script))
|
||||||
|
|||||||
@@ -1387,4 +1387,46 @@ public:
|
|||||||
boost::optional<libzcash::SpendingKey> operator()(const libzcash::InvalidEncoding& no) const;
|
boost::optional<libzcash::SpendingKey> operator()(const libzcash::InvalidEncoding& no) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class GetPubKeyForPubKey : public boost::static_visitor<CPubKey> {
|
||||||
|
private:
|
||||||
|
const CKeyStore &keystore;
|
||||||
|
|
||||||
|
public:
|
||||||
|
GetPubKeyForPubKey(const CKeyStore &keystoreIn) : keystore(keystoreIn) {}
|
||||||
|
|
||||||
|
CPubKey operator()(const CKeyID &id) const {
|
||||||
|
return CPubKey();
|
||||||
|
}
|
||||||
|
|
||||||
|
CPubKey operator()(const CPubKey &key) const {
|
||||||
|
return key;
|
||||||
|
}
|
||||||
|
|
||||||
|
CPubKey operator()(const CScriptID &sid) const {
|
||||||
|
return CPubKey();
|
||||||
|
}
|
||||||
|
|
||||||
|
CPubKey operator()(const CNoDestination &no) const {
|
||||||
|
return CPubKey();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class AddressVisitorString : public boost::static_visitor<std::string>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
std::string operator()(const CNoDestination &dest) const { return ""; }
|
||||||
|
|
||||||
|
std::string operator()(const CKeyID &keyID) const {
|
||||||
|
return "key hash: " + keyID.ToString();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string operator()(const CPubKey &key) const {
|
||||||
|
return "public key: " + HexStr(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string operator()(const CScriptID &scriptID) const {
|
||||||
|
return "script hash: " + scriptID.ToString();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
#endif // BITCOIN_WALLET_WALLET_H
|
#endif // BITCOIN_WALLET_WALLET_H
|
||||||
|
|||||||
Reference in New Issue
Block a user