Add CashAddr Address Format
Ported from Bitcoin Unlimited, Bitcoin ABC
This commit is contained in:
@@ -4,6 +4,7 @@
|
||||
|
||||
#include "base58.h"
|
||||
#include "chain.h"
|
||||
#include "dstencode.h"
|
||||
#include "rpc/server.h"
|
||||
#include "init.h"
|
||||
#include "main.h"
|
||||
@@ -152,7 +153,7 @@ UniValue importprivkey(const UniValue& params, bool fHelp)
|
||||
return NullUniValue;
|
||||
}
|
||||
|
||||
void ImportAddress(const CBitcoinAddress& address, const string& strLabel);
|
||||
void ImportAddress(const CTxDestination& dest, const string& strLabel);
|
||||
void ImportScript(const CScript& script, const string& strLabel, bool isRedeemScript)
|
||||
{
|
||||
if (!isRedeemScript && ::IsMine(*pwalletMain, script) == ISMINE_SPENDABLE)
|
||||
@@ -166,7 +167,7 @@ void ImportScript(const CScript& script, const string& strLabel, bool isRedeemSc
|
||||
if (isRedeemScript) {
|
||||
if (!pwalletMain->HaveCScript(script) && !pwalletMain->AddCScript(script))
|
||||
throw JSONRPCError(RPC_WALLET_ERROR, "Error adding p2sh redeemScript to wallet");
|
||||
ImportAddress(CBitcoinAddress(CScriptID(script)), strLabel);
|
||||
ImportAddress(CScriptID(script), strLabel);
|
||||
} else {
|
||||
CTxDestination destination;
|
||||
if (ExtractDestination(script, destination)) {
|
||||
@@ -175,13 +176,12 @@ void ImportScript(const CScript& script, const string& strLabel, bool isRedeemSc
|
||||
}
|
||||
}
|
||||
|
||||
void ImportAddress(const CBitcoinAddress& address, const string& strLabel)
|
||||
{
|
||||
CScript script = GetScriptForDestination(address.Get());
|
||||
void ImportAddress(const CTxDestination &dest, const std::string &strLabel) {
|
||||
CScript script = GetScriptForDestination(dest);
|
||||
ImportScript(script, strLabel, false);
|
||||
// add to address book or update label
|
||||
if (address.IsValid())
|
||||
pwalletMain->SetAddressBook(address.Get(), strLabel, "receive");
|
||||
if (IsValidDestination(dest))
|
||||
pwalletMain->SetAddressBook(dest, strLabel, "receive");
|
||||
}
|
||||
|
||||
UniValue importaddress(const UniValue& params, bool fHelp)
|
||||
@@ -231,13 +231,16 @@ UniValue importaddress(const UniValue& params, bool fHelp)
|
||||
|
||||
LOCK2(cs_main, pwalletMain->cs_wallet);
|
||||
|
||||
CBitcoinAddress address(params[0].get_str());
|
||||
if (address.IsValid()) {
|
||||
if (fP2SH)
|
||||
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Cannot use the p2sh flag with an address - use a script instead");
|
||||
ImportAddress(address, strLabel);
|
||||
CTxDestination dest = DecodeDestination(params[0].get_str());
|
||||
if (IsValidDestination(dest)) {
|
||||
if (fP2SH) {
|
||||
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY,
|
||||
"Cannot use the p2sh flag with an address - use "
|
||||
"a script instead");
|
||||
}
|
||||
ImportAddress(dest, strLabel);
|
||||
} else if (IsHex(params[0].get_str())) {
|
||||
std::vector<unsigned char> data(ParseHex(params[0].get_str()));
|
||||
std::vector<uint8_t> data(ParseHex(params[0].get_str()));
|
||||
ImportScript(CScript(data.begin(), data.end()), strLabel, fP2SH);
|
||||
} else {
|
||||
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid Bitcoin address or script");
|
||||
@@ -393,7 +396,7 @@ UniValue importpubkey(const UniValue& params, bool fHelp)
|
||||
|
||||
LOCK2(cs_main, pwalletMain->cs_wallet);
|
||||
|
||||
ImportAddress(CBitcoinAddress(pubKey.GetID()), strLabel);
|
||||
ImportAddress(pubKey.GetID(), strLabel);
|
||||
ImportScript(GetScriptForRawPubKey(pubKey), strLabel, false);
|
||||
|
||||
if (fRescan)
|
||||
@@ -465,7 +468,8 @@ UniValue importwallet(const UniValue& params, bool fHelp)
|
||||
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]);
|
||||
@@ -483,7 +487,7 @@ UniValue importwallet(const UniValue& params, bool fHelp)
|
||||
fLabel = true;
|
||||
}
|
||||
}
|
||||
LogPrintf("Importing %s...\n", CBitcoinAddress(keyid).ToString());
|
||||
LogPrintf("Importing %s...\n", EncodeDestination(keyid));
|
||||
if (!pwalletMain->AddKeyPubKey(key, pubkey)) {
|
||||
fGood = false;
|
||||
continue;
|
||||
@@ -537,15 +541,18 @@ UniValue dumpprivkey(const UniValue& params, bool fHelp)
|
||||
|
||||
EnsureWalletIsUnlocked();
|
||||
|
||||
string strAddress = params[0].get_str();
|
||||
CBitcoinAddress address;
|
||||
if (!address.SetString(strAddress))
|
||||
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid Bitcoin address");
|
||||
CKeyID keyID;
|
||||
if (!address.GetKeyID(keyID))
|
||||
std::string strAddress = params[0].get_str();
|
||||
CTxDestination dest = DecodeDestination(strAddress);
|
||||
if (!IsValidDestination(dest)) {
|
||||
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY,
|
||||
"Invalid Bitcoin address");
|
||||
}
|
||||
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();
|
||||
}
|
||||
@@ -616,7 +623,7 @@ UniValue dumpwallet(const UniValue& params, bool fHelp)
|
||||
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)) {
|
||||
file << strprintf("%s %s ", CBitcoinSecret(key).ToString(), strTime);
|
||||
|
||||
@@ -4,9 +4,9 @@
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
#include "amount.h"
|
||||
#include "base58.h"
|
||||
#include "chain.h"
|
||||
#include "core_io.h"
|
||||
#include "dstencode.h"
|
||||
#include "init.h"
|
||||
#include "main.h"
|
||||
#include "net.h"
|
||||
@@ -167,18 +167,17 @@ 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(string strAccount, bool bForceNew=false)
|
||||
{
|
||||
CPubKey pubKey;
|
||||
if (!pwalletMain->GetAccountPubkey(pubKey, strAccount, bForceNew)) {
|
||||
throw JSONRPCError(RPC_WALLET_KEYPOOL_RAN_OUT, "Error: Keypool ran out, please call keypoolrefill first");
|
||||
}
|
||||
|
||||
return CBitcoinAddress(pubKey.GetID());
|
||||
return pubKey.GetID();
|
||||
}
|
||||
|
||||
UniValue getaccountaddress(const UniValue& params, bool fHelp)
|
||||
@@ -208,7 +207,7 @@ UniValue getaccountaddress(const UniValue& params, bool fHelp)
|
||||
|
||||
UniValue ret(UniValue::VSTR);
|
||||
|
||||
ret = GetAccountAddress(strAccount).ToString();
|
||||
ret = EncodeDestination(GetAccountAddress(strAccount));
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -244,10 +243,9 @@ UniValue getrawchangeaddress(const UniValue& params, bool fHelp)
|
||||
|
||||
CKeyID keyID = vchPubKey.GetID();
|
||||
|
||||
return CBitcoinAddress(keyID).ToString();
|
||||
return EncodeDestination(keyID);
|
||||
}
|
||||
|
||||
|
||||
UniValue setaccount(const UniValue& params, bool fHelp)
|
||||
{
|
||||
if (!EnsureWalletIsAvailable(fHelp))
|
||||
@@ -267,25 +265,28 @@ UniValue setaccount(const UniValue& params, bool fHelp)
|
||||
|
||||
LOCK2(cs_main, pwalletMain->cs_wallet);
|
||||
|
||||
CBitcoinAddress address(params[0].get_str());
|
||||
if (!address.IsValid())
|
||||
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid Bitcoin address");
|
||||
CTxDestination dest = DecodeDestination(params[0].get_str());
|
||||
if (!IsValidDestination(dest)) {
|
||||
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY,
|
||||
"Invalid Bitcoin 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()))
|
||||
// Detect when changing the account of an address that is the 'unused
|
||||
// current key' of another account:
|
||||
if (pwalletMain->mapAddressBook.count(dest))
|
||||
{
|
||||
string strOldAccount = pwalletMain->mapAddressBook[address.Get()].name;
|
||||
if (address == GetAccountAddress(strOldAccount))
|
||||
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");
|
||||
@@ -293,7 +294,6 @@ UniValue setaccount(const UniValue& params, bool fHelp)
|
||||
return NullUniValue;
|
||||
}
|
||||
|
||||
|
||||
UniValue getaccount(const UniValue& params, bool fHelp)
|
||||
{
|
||||
if (!EnsureWalletIsAvailable(fHelp))
|
||||
@@ -314,18 +314,21 @@ UniValue getaccount(const UniValue& params, bool fHelp)
|
||||
|
||||
LOCK2(cs_main, pwalletMain->cs_wallet);
|
||||
|
||||
CBitcoinAddress address(params[0].get_str());
|
||||
if (!address.IsValid())
|
||||
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid Bitcoin address");
|
||||
CTxDestination dest = DecodeDestination(params[0].get_str());
|
||||
if (!IsValidDestination(dest)) {
|
||||
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY,
|
||||
"Invalid Bitcoin 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;
|
||||
}
|
||||
|
||||
|
||||
UniValue getaddressesbyaccount(const UniValue& params, bool fHelp)
|
||||
{
|
||||
if (!EnsureWalletIsAvailable(fHelp))
|
||||
@@ -353,12 +356,13 @@ 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;
|
||||
}
|
||||
@@ -427,9 +431,10 @@ UniValue sendtoaddress(const UniValue& params, bool fHelp)
|
||||
|
||||
LOCK2(cs_main, pwalletMain->cs_wallet);
|
||||
|
||||
CBitcoinAddress address(params[0].get_str());
|
||||
if (!address.IsValid())
|
||||
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid Bitcoin address");
|
||||
CTxDestination dest = DecodeDestination(params[0].get_str());
|
||||
if (!IsValidDestination(dest)) {
|
||||
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid address");
|
||||
}
|
||||
|
||||
// Amount
|
||||
CAmount nAmount = AmountFromValue(params[1]);
|
||||
@@ -449,7 +454,7 @@ UniValue sendtoaddress(const UniValue& params, bool fHelp)
|
||||
|
||||
EnsureWalletIsUnlocked();
|
||||
|
||||
SendMoney(address.Get(), nAmount, fSubtractFeeFromAmount, wtx);
|
||||
SendMoney(dest, nAmount, fSubtractFeeFromAmount, wtx);
|
||||
|
||||
return wtx.GetHash().GetHex();
|
||||
}
|
||||
@@ -485,18 +490,20 @@ 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);
|
||||
}
|
||||
@@ -538,16 +545,16 @@ 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);
|
||||
@@ -589,10 +596,11 @@ 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 Bitcoin address");
|
||||
CScript scriptPubKey = GetScriptForDestination(address.Get());
|
||||
}
|
||||
CScript scriptPubKey = GetScriptForDestination(dest);
|
||||
if (!IsMine(*pwalletMain, scriptPubKey))
|
||||
return ValueFromAmount(0);
|
||||
|
||||
@@ -609,7 +617,7 @@ UniValue getreceivedbyaddress(const UniValue& params, bool fHelp)
|
||||
if (wtx.IsCoinBase() || !CheckFinalTx(wtx))
|
||||
continue;
|
||||
|
||||
BOOST_FOREACH(const CTxOut& txout, wtx.vout)
|
||||
for (const CTxOut &txout : wtx.vout)
|
||||
if (txout.scriptPubKey == scriptPubKey)
|
||||
if (wtx.GetDepthInMainChain() >= nMinDepth)
|
||||
nAmount += txout.nValue;
|
||||
@@ -618,7 +626,6 @@ UniValue getreceivedbyaddress(const UniValue& params, bool fHelp)
|
||||
return ValueFromAmount(nAmount);
|
||||
}
|
||||
|
||||
|
||||
UniValue getreceivedbyaccount(const UniValue& params, bool fHelp)
|
||||
{
|
||||
if (!EnsureWalletIsAvailable(fHelp))
|
||||
@@ -853,10 +860,12 @@ 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())
|
||||
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid Bitcoin address");
|
||||
std::string strAccount = AccountFromValue(params[0]);
|
||||
CTxDestination dest = DecodeDestination(params[1].get_str());
|
||||
if (!IsValidDestination(dest)) {
|
||||
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY,
|
||||
"Invalid Bitcoin address");
|
||||
}
|
||||
CAmount nAmount = AmountFromValue(params[2]);
|
||||
if (nAmount <= 0)
|
||||
throw JSONRPCError(RPC_TYPE_ERROR, "Invalid amount for send");
|
||||
@@ -878,7 +887,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();
|
||||
}
|
||||
@@ -942,22 +951,27 @@ 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 Bitcoin 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 Bitcoin 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");
|
||||
@@ -1043,7 +1057,7 @@ UniValue addmultisigaddress(const UniValue& params, bool fHelp)
|
||||
pwalletMain->AddCScript(inner);
|
||||
|
||||
pwalletMain->SetAddressBook(innerID, strAccount, "send");
|
||||
return CBitcoinAddress(innerID).ToString();
|
||||
return EncodeDestination(innerID);
|
||||
}
|
||||
|
||||
|
||||
@@ -1079,11 +1093,13 @@ 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)
|
||||
std::map<CTxDestination, tallyitem> mapTally;
|
||||
for (std::map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin();
|
||||
it != pwalletMain->mapWallet.end(); ++it)
|
||||
{
|
||||
const CWalletTx& wtx = (*it).second;
|
||||
const CWalletTx &wtx = (*it).second;
|
||||
|
||||
// CValidationState state;
|
||||
if (wtx.IsCoinBase() || !CheckFinalTx(wtx))
|
||||
continue;
|
||||
|
||||
@@ -1091,7 +1107,7 @@ UniValue ListReceived(const UniValue& params, bool fByAccounts)
|
||||
if (nDepth < nMinDepth)
|
||||
continue;
|
||||
|
||||
BOOST_FOREACH(const CTxOut& txout, wtx.vout)
|
||||
for (const CTxOut &txout : wtx.vout)
|
||||
{
|
||||
CTxDestination address;
|
||||
if (!ExtractDestination(txout.scriptPubKey, address))
|
||||
@@ -1112,12 +1128,12 @@ 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)
|
||||
std::map<std::string, tallyitem> mapAccountTally;
|
||||
for (const std::pair<CTxDestination, CAddressBookData> &item : pwalletMain->mapAddressBook)
|
||||
{
|
||||
const CBitcoinAddress& address = item.first;
|
||||
const string& strAccount = item.second.name;
|
||||
map<CBitcoinAddress, tallyitem>::iterator it = mapTally.find(address);
|
||||
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;
|
||||
|
||||
@@ -1142,17 +1158,23 @@ 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("account", strAccount));
|
||||
obj.push_back(Pair("amount", ValueFromAmount(nAmount)));
|
||||
obj.push_back(Pair("confirmations", (nConf == std::numeric_limits<int>::max() ? 0 : nConf)));
|
||||
}
|
||||
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)));
|
||||
if (!fByAccounts)
|
||||
{
|
||||
obj.push_back(Pair("label", strAccount));
|
||||
}
|
||||
UniValue transactions(UniValue::VARR);
|
||||
if (it != mapTally.end())
|
||||
{
|
||||
BOOST_FOREACH(const uint256& item, (*it).second.txids)
|
||||
for (const uint256 &item : (*it).second.txids)
|
||||
{
|
||||
transactions.push_back(item.GetHex());
|
||||
}
|
||||
@@ -1258,11 +1280,10 @@ UniValue listreceivedbyaccount(const UniValue& params, bool fHelp)
|
||||
return ListReceived(params, true);
|
||||
}
|
||||
|
||||
static void MaybePushAddress(UniValue & entry, const CTxDestination &dest)
|
||||
{
|
||||
CBitcoinAddress addr;
|
||||
if (addr.Set(dest))
|
||||
entry.push_back(Pair("address", addr.ToString()));
|
||||
static void MaybePushAddress(UniValue &entry, const CTxDestination &dest) {
|
||||
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)
|
||||
@@ -2357,17 +2378,17 @@ UniValue listunspent(const UniValue& params, bool fHelp)
|
||||
if (params.size() > 1)
|
||||
nMaxDepth = params[1].get_int();
|
||||
|
||||
set<CBitcoinAddress> setAddress;
|
||||
set<CTxDestination> destinations;
|
||||
if (params.size() > 2) {
|
||||
UniValue inputs = params[2].get_array();
|
||||
for (unsigned int idx = 0; idx < inputs.size(); idx++) {
|
||||
const UniValue& input = inputs[idx];
|
||||
CBitcoinAddress address(input.get_str());
|
||||
if (!address.IsValid())
|
||||
CTxDestination address = DecodeDestination(input.get_str());
|
||||
if (!IsValidDestination(address))
|
||||
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, string("Invalid Bitcoin address: ")+input.get_str());
|
||||
if (setAddress.count(address))
|
||||
if (destinations.count(address))
|
||||
throw JSONRPCError(RPC_INVALID_PARAMETER, string("Invalid parameter, duplicated address: ")+input.get_str());
|
||||
setAddress.insert(address);
|
||||
destinations.insert(address);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2384,7 +2405,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);
|
||||
@@ -2392,7 +2413,7 @@ UniValue listunspent(const UniValue& params, bool fHelp)
|
||||
entry.push_back(Pair("vout", out.i));
|
||||
|
||||
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));
|
||||
@@ -2476,7 +2497,7 @@ UniValue fundrawtransaction(const UniValue& params, bool fHelp)
|
||||
// backward compatibility bool only fallback
|
||||
includeWatching = params[1].get_bool();
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
RPCTypeCheck(params, boost::assign::list_of(UniValue::VSTR)(UniValue::VOBJ));
|
||||
|
||||
UniValue options = params[1];
|
||||
@@ -2492,12 +2513,13 @@ UniValue fundrawtransaction(const UniValue& params, bool fHelp)
|
||||
true, true);
|
||||
|
||||
if (options.exists("changeAddress")) {
|
||||
CBitcoinAddress address(options["changeAddress"].get_str());
|
||||
CTxDestination dest =
|
||||
DecodeDestination(options["changeAddress"].get_str());
|
||||
|
||||
if (!address.IsValid())
|
||||
if (!IsValidDestination(dest)) {
|
||||
throw JSONRPCError(RPC_INVALID_PARAMETER, "changeAddress must be a valid bitcoin address");
|
||||
|
||||
changeAddress = address.Get();
|
||||
changeAddress = dest;
|
||||
}
|
||||
|
||||
if (options.exists("changePosition"))
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
#include "rpc/client.h"
|
||||
|
||||
#include "base58.h"
|
||||
#include "dstencode.h"
|
||||
#include "main.h"
|
||||
#include "wallet/wallet.h"
|
||||
|
||||
@@ -35,18 +36,17 @@ BOOST_AUTO_TEST_CASE(rpc_addmultisig)
|
||||
const char address2Hex[] = "0388c2037017c62240b6b72ac1a2a5f94da790596ebd06177c8572752922165cb4";
|
||||
|
||||
UniValue v;
|
||||
CBitcoinAddress address;
|
||||
BOOST_CHECK_NO_THROW(v = addmultisig(createArgs(1, address1Hex), false));
|
||||
address.SetString(v.get_str());
|
||||
BOOST_CHECK(address.IsValid() && address.IsScript());
|
||||
CTxDestination address = DecodeDestination(v.get_str());
|
||||
BOOST_CHECK(IsValidDestination(address));
|
||||
|
||||
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_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_CHECK_THROW(addmultisig(createArgs(0), false), runtime_error);
|
||||
BOOST_CHECK_THROW(addmultisig(createArgs(1), false), runtime_error);
|
||||
@@ -67,15 +67,15 @@ BOOST_AUTO_TEST_CASE(rpc_wallet)
|
||||
// Test RPC calls for various wallet statistics
|
||||
UniValue r;
|
||||
CPubKey demoPubkey;
|
||||
CBitcoinAddress demoAddress;
|
||||
CTxDestination demoAddress;
|
||||
UniValue retValue;
|
||||
string strAccount = "walletDemoAccount";
|
||||
CBitcoinAddress setaccountDemoAddress;
|
||||
CTxDestination setaccountDemoAddress;
|
||||
{
|
||||
LOCK(pwalletMain->cs_wallet);
|
||||
|
||||
demoPubkey = pwalletMain->GenerateNewKey();
|
||||
demoAddress = CBitcoinAddress(CTxDestination(demoPubkey.GetID()));
|
||||
demoAddress = CTxDestination(demoPubkey.GetID());
|
||||
string strPurpose = "receive";
|
||||
BOOST_CHECK_NO_THROW({ /*Initialize Wallet with an account */
|
||||
CWalletDB walletdb(pwalletMain->strWalletFile);
|
||||
@@ -86,12 +86,12 @@ BOOST_AUTO_TEST_CASE(rpc_wallet)
|
||||
});
|
||||
|
||||
CPubKey setaccountDemoPubkey = pwalletMain->GenerateNewKey();
|
||||
setaccountDemoAddress = CBitcoinAddress(CTxDestination(setaccountDemoPubkey.GetID()));
|
||||
setaccountDemoAddress = CTxDestination(setaccountDemoPubkey.GetID());
|
||||
}
|
||||
/*********************************
|
||||
* setaccount
|
||||
*********************************/
|
||||
BOOST_CHECK_NO_THROW(CallRPC("setaccount " + setaccountDemoAddress.ToString() + " nullaccount"));
|
||||
BOOST_CHECK_NO_THROW(CallRPC("setaccount " + EncodeDestination(setaccountDemoAddress) + " nullaccount"));
|
||||
/* 1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XZ is not owned by the test wallet. */
|
||||
BOOST_CHECK_THROW(CallRPC("setaccount 1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XZ nullaccount"), runtime_error);
|
||||
BOOST_CHECK_THROW(CallRPC("setaccount"), runtime_error);
|
||||
@@ -103,7 +103,7 @@ BOOST_AUTO_TEST_CASE(rpc_wallet)
|
||||
* getbalance
|
||||
*********************************/
|
||||
BOOST_CHECK_NO_THROW(CallRPC("getbalance"));
|
||||
BOOST_CHECK_NO_THROW(CallRPC("getbalance " + demoAddress.ToString()));
|
||||
BOOST_CHECK_NO_THROW(CallRPC("getbalance " + EncodeDestination(demoAddress)));
|
||||
|
||||
/*********************************
|
||||
* listunspent
|
||||
@@ -145,10 +145,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
|
||||
@@ -182,33 +182,33 @@ BOOST_AUTO_TEST_CASE(rpc_wallet)
|
||||
BOOST_CHECK_NO_THROW(CallRPC("getaccountaddress \"\""));
|
||||
BOOST_CHECK_NO_THROW(CallRPC("getaccountaddress accountThatDoesntExists")); // Should generate a new account
|
||||
BOOST_CHECK_NO_THROW(retValue = CallRPC("getaccountaddress " + strAccount));
|
||||
BOOST_CHECK(CBitcoinAddress(retValue.get_str()).Get() == demoAddress.Get());
|
||||
BOOST_CHECK(retValue.get_str() == EncodeDestination(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 1QFqqMUD55ZV3PJEJZtaKCsQmjLT6JkjvJ 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 1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4X " + retValue.get_str() + " mymessage"), runtime_error);
|
||||
/* wrong address */
|
||||
BOOST_CHECK(CallRPC("verifymessage 1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XZ " + 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
|
||||
@@ -217,7 +217,7 @@ BOOST_AUTO_TEST_CASE(rpc_wallet)
|
||||
BOOST_CHECK_NO_THROW(retValue = CallRPC("getaddressesbyaccount " + strAccount));
|
||||
UniValue arr = retValue.get_array();
|
||||
BOOST_CHECK(arr.size() > 0);
|
||||
BOOST_CHECK(CBitcoinAddress(arr[0].get_str()).Get() == demoAddress.Get());
|
||||
BOOST_CHECK(arr[0].get_str() == EncodeDestination(demoAddress));
|
||||
|
||||
/*********************************
|
||||
* fundrawtransaction
|
||||
|
||||
140
src/wallet/test/walletdb_tests.cpp
Normal file
140
src/wallet/test/walletdb_tests.cpp
Normal file
@@ -0,0 +1,140 @@
|
||||
// Copyright (c) 2017 The Bitcoin developers
|
||||
// Distributed under the MIT software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
#include "test/test_bitcoin.h"
|
||||
#include "random.h"
|
||||
#include "fs.h"
|
||||
|
||||
#include "wallet/wallet.h"
|
||||
#include "wallet/walletdb.h"
|
||||
|
||||
#include <boost/test/unit_test.hpp>
|
||||
|
||||
namespace {
|
||||
struct WalletDBTestingSetup : public TestingSetup
|
||||
{
|
||||
WalletDBTestingSetup(const std::string &chainName = CBaseChainParams::MAIN)
|
||||
{
|
||||
bitdb.MakeMock();
|
||||
}
|
||||
|
||||
~WalletDBTestingSetup()
|
||||
{
|
||||
bitdb.Flush(true);
|
||||
bitdb.Reset();
|
||||
}
|
||||
};
|
||||
|
||||
static std::unique_ptr<CWalletDB> TmpDB(const fs::path &pathTemp, const std::string &testname)
|
||||
{
|
||||
fs::path dir = pathTemp / testname;
|
||||
BOOST_CHECK_MESSAGE(fs::create_directory(dir),
|
||||
"Unable to create a directory for test " + testname);
|
||||
fs::path path = dir / strprintf("testwallet%i", static_cast<int>(insecure_rand() % 1000000));
|
||||
return std::unique_ptr<CWalletDB>(new CWalletDB(path.string(), "cr+"));
|
||||
}
|
||||
|
||||
static std::unique_ptr<CWallet> LoadWallet(CWalletDB *db) {
|
||||
std::unique_ptr<CWallet> wallet(new CWallet);
|
||||
DBErrors res = db->LoadWallet(wallet.get());
|
||||
BOOST_CHECK(res == DB_LOAD_OK);
|
||||
return wallet;
|
||||
}
|
||||
}
|
||||
|
||||
BOOST_FIXTURE_TEST_SUITE(walletdb_tests, WalletDBTestingSetup);
|
||||
|
||||
BOOST_AUTO_TEST_CASE(write_erase_name) {
|
||||
auto walletdb = TmpDB(pathTemp, "write_erase_name");
|
||||
|
||||
CTxDestination dst1 = CKeyID(uint160S("c0ffee"));
|
||||
CTxDestination dst2 = CKeyID(uint160S("f00d"));
|
||||
|
||||
BOOST_CHECK(walletdb->WriteName(dst1, "name1"));
|
||||
BOOST_CHECK(walletdb->WriteName(dst2, "name2"));
|
||||
{
|
||||
auto w = LoadWallet(walletdb.get());
|
||||
BOOST_CHECK_EQUAL(1, w->mapAddressBook.count(dst1));
|
||||
BOOST_CHECK_EQUAL("name1", w->mapAddressBook[dst1].name);
|
||||
BOOST_CHECK_EQUAL("name2", w->mapAddressBook[dst2].name);
|
||||
}
|
||||
|
||||
walletdb->EraseName(dst1);
|
||||
|
||||
{
|
||||
auto w = LoadWallet(walletdb.get());
|
||||
BOOST_CHECK_EQUAL(0, w->mapAddressBook.count(dst1));
|
||||
BOOST_CHECK_EQUAL(1, w->mapAddressBook.count(dst2));
|
||||
}
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(write_erase_purpose) {
|
||||
auto walletdb = TmpDB(pathTemp, "write_erase_purpose");
|
||||
|
||||
CTxDestination dst1 = CKeyID(uint160S("c0ffee"));
|
||||
CTxDestination dst2 = CKeyID(uint160S("f00d"));
|
||||
|
||||
BOOST_CHECK(walletdb->WritePurpose(dst1, "purpose1"));
|
||||
BOOST_CHECK(walletdb->WritePurpose(dst2, "purpose2"));
|
||||
{
|
||||
auto w = LoadWallet(walletdb.get());
|
||||
BOOST_CHECK_EQUAL(1, w->mapAddressBook.count(dst1));
|
||||
BOOST_CHECK_EQUAL("purpose1", w->mapAddressBook[dst1].purpose);
|
||||
BOOST_CHECK_EQUAL("purpose2", w->mapAddressBook[dst2].purpose);
|
||||
}
|
||||
|
||||
walletdb->ErasePurpose(dst1);
|
||||
|
||||
{
|
||||
auto w = LoadWallet(walletdb.get());
|
||||
BOOST_CHECK_EQUAL(0, w->mapAddressBook.count(dst1));
|
||||
BOOST_CHECK_EQUAL(1, w->mapAddressBook.count(dst2));
|
||||
}
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(write_erase_destdata) {
|
||||
auto walletdb = TmpDB(pathTemp, "write_erase_destdata");
|
||||
|
||||
CTxDestination dst1 = CKeyID(uint160S("c0ffee"));
|
||||
CTxDestination dst2 = CKeyID(uint160S("f00d"));
|
||||
|
||||
BOOST_CHECK(walletdb->WriteDestData(dst1, "key1", "value1"));
|
||||
BOOST_CHECK(walletdb->WriteDestData(dst1, "key2", "value2"));
|
||||
BOOST_CHECK(walletdb->WriteDestData(dst2, "key1", "value3"));
|
||||
BOOST_CHECK(walletdb->WriteDestData(dst2, "key2", "value4"));
|
||||
{
|
||||
auto w = LoadWallet(walletdb.get());
|
||||
std::string val;
|
||||
BOOST_CHECK(w->GetDestData(dst1, "key1", &val));
|
||||
BOOST_CHECK_EQUAL("value1", val);
|
||||
BOOST_CHECK(w->GetDestData(dst1, "key2", &val));
|
||||
BOOST_CHECK_EQUAL("value2", val);
|
||||
BOOST_CHECK(w->GetDestData(dst2, "key1", &val));
|
||||
BOOST_CHECK_EQUAL("value3", val);
|
||||
BOOST_CHECK(w->GetDestData(dst2, "key2", &val));
|
||||
BOOST_CHECK_EQUAL("value4", val);
|
||||
}
|
||||
|
||||
walletdb->EraseDestData(dst1, "key2");
|
||||
|
||||
{
|
||||
auto w = LoadWallet(walletdb.get());
|
||||
std::string dummy;
|
||||
BOOST_CHECK(w->GetDestData(dst1, "key1", &dummy));
|
||||
BOOST_CHECK(!w->GetDestData(dst1, "key2", &dummy));
|
||||
BOOST_CHECK(w->GetDestData(dst2, "key1", &dummy));
|
||||
BOOST_CHECK(w->GetDestData(dst2, "key2", &dummy));
|
||||
}
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(no_dest_fails) {
|
||||
auto walletdb = TmpDB(pathTemp, "no_dest_fails");
|
||||
|
||||
CTxDestination dst = CNoDestination{};
|
||||
BOOST_CHECK(!walletdb->WriteName(dst, "name"));
|
||||
BOOST_CHECK(!walletdb->WritePurpose(dst, "purpose"));
|
||||
BOOST_CHECK(!walletdb->WriteDestData(dst, "key", "value"));
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_SUITE_END()
|
||||
@@ -5,12 +5,12 @@
|
||||
|
||||
#include "wallet/wallet.h"
|
||||
|
||||
#include "base58.h"
|
||||
#include "checkpoints.h"
|
||||
#include "chain.h"
|
||||
#include "checkpoints.h"
|
||||
#include "coincontrol.h"
|
||||
#include "consensus/consensus.h"
|
||||
#include "consensus/validation.h"
|
||||
#include "dstencode.h"
|
||||
#include "key.h"
|
||||
#include "keystore.h"
|
||||
#include "main.h"
|
||||
@@ -233,16 +233,19 @@ bool CWallet::AddCScript(const CScript& redeemScript)
|
||||
return CWalletDB(strWalletFile).WriteCScript(Hash160(redeemScript), redeemScript);
|
||||
}
|
||||
|
||||
bool CWallet::LoadCScript(const CScript& redeemScript)
|
||||
{
|
||||
/* A sanity check was added in pull #3843 to avoid adding redeemScripts
|
||||
* that never can be redeemed. However, old wallets may still contain
|
||||
* these. Do not add them to the wallet and warn. */
|
||||
if (redeemScript.size() > MAX_SCRIPT_ELEMENT_SIZE)
|
||||
{
|
||||
std::string strAddr = CBitcoinAddress(CScriptID(redeemScript)).ToString();
|
||||
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);
|
||||
bool CWallet::LoadCScript(const CScript &redeemScript) {
|
||||
/**
|
||||
* A sanity check was added in pull #3843 to avoid adding redeemScripts that
|
||||
* never can be redeemed. However, old wallets may still contain these. Do
|
||||
* not add them to the wallet and warn.
|
||||
*/
|
||||
if (redeemScript.size() > MAX_SCRIPT_ELEMENT_SIZE) {
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -1467,6 +1470,11 @@ CAmount CWallet::GetDebit(const CTxIn &txin, const isminefilter& filter) const
|
||||
return 0;
|
||||
}
|
||||
|
||||
isminetype CWallet::IsMine(const CTxDestination &dest) const
|
||||
{
|
||||
return ::IsMine(*this, dest);
|
||||
}
|
||||
|
||||
isminetype CWallet::IsMine(const CTxOut& txout) const
|
||||
{
|
||||
return ::IsMine(*this, txout.scriptPubKey);
|
||||
@@ -3028,9 +3036,13 @@ 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(address, strPurpose))
|
||||
{
|
||||
return false;
|
||||
return CWalletDB(strWalletFile).WriteName(CBitcoinAddress(address).ToString(), strName);
|
||||
}
|
||||
|
||||
return CWalletDB(strWalletFile).WriteName(address, strName);
|
||||
}
|
||||
|
||||
bool CWallet::DelAddressBook(const CTxDestination& address)
|
||||
@@ -3038,13 +3050,11 @@ bool CWallet::DelAddressBook(const CTxDestination& address)
|
||||
{
|
||||
LOCK(cs_wallet); // mapAddressBook
|
||||
|
||||
if(fFileBacked)
|
||||
{
|
||||
// Delete destdata tuples associated with address
|
||||
std::string strAddress = CBitcoinAddress(address).ToString();
|
||||
BOOST_FOREACH(const PAIRTYPE(string, string) &item, mapAddressBook[address].destdata)
|
||||
{
|
||||
CWalletDB(strWalletFile).EraseDestData(strAddress, item.first);
|
||||
if (fFileBacked) {
|
||||
// Delete destdata tuples associated with address.
|
||||
for (const std::pair<std::string, std::string> &item :
|
||||
mapAddressBook[address].destdata) {
|
||||
CWalletDB(strWalletFile).EraseDestData(address, item.first);
|
||||
}
|
||||
}
|
||||
mapAddressBook.erase(address);
|
||||
@@ -3054,8 +3064,9 @@ 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(address);
|
||||
return CWalletDB(strWalletFile).EraseName(address);
|
||||
}
|
||||
|
||||
bool CWallet::SetDefaultKey(const CPubKey &vchPubKey)
|
||||
@@ -3645,7 +3656,8 @@ 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(dest, key, value);
|
||||
}
|
||||
|
||||
bool CWallet::EraseDestData(const CTxDestination &dest, const std::string &key)
|
||||
@@ -3654,7 +3666,8 @@ 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(dest, key);
|
||||
}
|
||||
|
||||
bool CWallet::LoadDestData(const CTxDestination &dest, const std::string &key, const std::string &value)
|
||||
|
||||
@@ -803,6 +803,7 @@ public:
|
||||
CAmount GetAccountBalance(CWalletDB& walletdb, const std::string& strAccount, int nMinDepth, const isminefilter& filter);
|
||||
std::set<CTxDestination> GetAccountAddresses(const std::string& strAccount) const;
|
||||
|
||||
isminetype IsMine(const CTxDestination &dest) const;
|
||||
isminetype IsMine(const CTxIn& txin) const;
|
||||
CAmount GetDebit(const CTxIn& txin, const isminefilter& filter) const;
|
||||
isminetype IsMine(const CTxOut& txout) const;
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
// Copyright (c) 2009-2010 Satoshi Nakamoto
|
||||
// Copyright (c) 2009-2015 The Bitcoin Core developers
|
||||
// Copyright (c) 2015-2017 The Bitcoin Unlimited developers
|
||||
// Copyright (c) 2017 The Bitcoin developers
|
||||
// Distributed under the MIT software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
@@ -8,6 +10,7 @@
|
||||
#include "base58.h"
|
||||
#include "consensus/validation.h"
|
||||
#include "main.h" // For CheckTransaction
|
||||
#include "dstencode.h"
|
||||
#include "protocol.h"
|
||||
#include "serialize.h"
|
||||
#include "sync.h"
|
||||
@@ -29,30 +32,42 @@ static uint64_t nAccountingEntryNumber = 0;
|
||||
// CWalletDB
|
||||
//
|
||||
|
||||
bool CWalletDB::WriteName(const string& strAddress, const string& strName)
|
||||
bool CWalletDB::WriteName(const CTxDestination &address, const std::string &strName)
|
||||
{
|
||||
if (!IsValidDestination(address))
|
||||
return false;
|
||||
|
||||
nWalletDBUpdated++;
|
||||
return Write(make_pair(string("name"), strAddress), strName);
|
||||
return Write(std::make_pair(std::string("name"), EncodeLegacyAddr(address, Params())), strName);
|
||||
}
|
||||
|
||||
bool CWalletDB::EraseName(const string& strAddress)
|
||||
bool CWalletDB::EraseName(const CTxDestination &address)
|
||||
{
|
||||
// This should only be used for sending addresses, never for receiving addresses,
|
||||
// receiving addresses must always have an address book entry if they're not change return.
|
||||
// This should only be used for sending addresses, never for receiving
|
||||
// addresses, receiving addresses must always have an address book entry if
|
||||
// they're not change return.
|
||||
if (!IsValidDestination(address))
|
||||
return false;
|
||||
|
||||
nWalletDBUpdated++;
|
||||
return Erase(make_pair(string("name"), strAddress));
|
||||
return Erase(std::make_pair(std::string("name"), EncodeLegacyAddr(address, Params())));
|
||||
}
|
||||
|
||||
bool CWalletDB::WritePurpose(const string& strAddress, const string& strPurpose)
|
||||
{
|
||||
bool CWalletDB::WritePurpose(const CTxDestination &address, const std::string &strPurpose) {
|
||||
if (!IsValidDestination(address))
|
||||
return false;
|
||||
|
||||
nWalletDBUpdated++;
|
||||
return Write(make_pair(string("purpose"), strAddress), strPurpose);
|
||||
return Write(std::make_pair(std::string("purpose"), EncodeLegacyAddr(address, Params())), strPurpose);
|
||||
}
|
||||
|
||||
bool CWalletDB::ErasePurpose(const string& strPurpose)
|
||||
bool CWalletDB::ErasePurpose(const CTxDestination &address)
|
||||
{
|
||||
if (!IsValidDestination(address))
|
||||
return false;
|
||||
|
||||
nWalletDBUpdated++;
|
||||
return Erase(make_pair(string("purpose"), strPurpose));
|
||||
return Erase(std::make_pair(std::string("purpose"), EncodeLegacyAddr(address, Params())));
|
||||
}
|
||||
|
||||
bool CWalletDB::WriteTx(const CWalletTx& wtx)
|
||||
@@ -359,16 +374,14 @@ ReadKeyValue(CWallet* pwallet, CDataStream& ssKey, CDataStream& ssValue,
|
||||
{
|
||||
string strAddress;
|
||||
ssKey >> strAddress;
|
||||
ssValue >> pwallet->mapAddressBook[CBitcoinAddress(strAddress).Get()].name;
|
||||
}
|
||||
else if (strType == "purpose")
|
||||
{
|
||||
string strAddress;
|
||||
ssValue >>
|
||||
pwallet->mapAddressBook[DecodeDestination(strAddress)].name;
|
||||
} else if (strType == "purpose") {
|
||||
std::string strAddress;
|
||||
ssKey >> strAddress;
|
||||
ssValue >> pwallet->mapAddressBook[CBitcoinAddress(strAddress).Get()].purpose;
|
||||
}
|
||||
else if (strType == "tx")
|
||||
{
|
||||
ssValue >>
|
||||
pwallet->mapAddressBook[DecodeDestination(strAddress)].purpose;
|
||||
} else if (strType == "tx") {
|
||||
uint256 hash;
|
||||
ssKey >> hash;
|
||||
CWalletTx wtx;
|
||||
@@ -593,8 +606,8 @@ 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;
|
||||
}
|
||||
@@ -1002,10 +1015,13 @@ bool CWalletDB::Recover(CDBEnv& dbenv, const std::string& filename)
|
||||
return CWalletDB::Recover(dbenv, filename, false);
|
||||
}
|
||||
|
||||
bool CWalletDB::WriteDestData(const std::string &address, const std::string &key, const std::string &value)
|
||||
bool CWalletDB::WriteDestData(const CTxDestination &address, const std::string &key, const std::string &value)
|
||||
{
|
||||
if (!IsValidDestination(address))
|
||||
return false;
|
||||
|
||||
nWalletDBUpdated++;
|
||||
return Write(std::make_pair(std::string("destdata"), std::make_pair(address, key)), value);
|
||||
return Write(std::make_pair(std::string("destdata"), std::make_pair(EncodeLegacyAddr(address, Params()), key)), value);
|
||||
}
|
||||
|
||||
bool CWalletDB::WriteHDChain(const CHDChain& chain)
|
||||
@@ -1014,8 +1030,11 @@ bool CWalletDB::WriteHDChain(const CHDChain& chain)
|
||||
return Write(std::string("hdchain"), chain);
|
||||
}
|
||||
|
||||
bool CWalletDB::EraseDestData(const std::string &address, const std::string &key)
|
||||
bool CWalletDB::EraseDestData(const CTxDestination &address, const std::string &key)
|
||||
{
|
||||
if (!IsValidDestination(address))
|
||||
return false;
|
||||
|
||||
nWalletDBUpdated++;
|
||||
return Erase(std::make_pair(std::string("destdata"), std::make_pair(address, key)));
|
||||
return Erase(std::make_pair(std::string("destdata"), std::make_pair(EncodeLegacyAddr(address, Params()), key)));
|
||||
}
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
// Copyright (c) 2009-2010 Satoshi Nakamoto
|
||||
// Copyright (c) 2009-2015 The Bitcoin Core developers
|
||||
// Copyright (c) 2015-2017 The Bitcoin Unlimited developers
|
||||
// Copyright (c) 2017 The Bitcoin developers
|
||||
// Distributed under the MIT software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
@@ -7,6 +9,9 @@
|
||||
#define BITCOIN_WALLET_WALLETDB_H
|
||||
|
||||
#include "amount.h"
|
||||
#include "key.h"
|
||||
#include "primitives/transaction.h"
|
||||
#include "script/standard.h" // for CTxDestination
|
||||
#include "wallet/db.h"
|
||||
#include "key.h"
|
||||
|
||||
@@ -121,11 +126,11 @@ public:
|
||||
{
|
||||
}
|
||||
|
||||
bool WriteName(const std::string& strAddress, const std::string& strName);
|
||||
bool EraseName(const std::string& strAddress);
|
||||
bool WriteName(const CTxDestination &address, const std::string &strName);
|
||||
bool EraseName(const CTxDestination &address);
|
||||
|
||||
bool WritePurpose(const std::string& strAddress, const std::string& purpose);
|
||||
bool ErasePurpose(const std::string& strAddress);
|
||||
bool WritePurpose(const CTxDestination &address, const std::string &purpose);
|
||||
bool ErasePurpose(const CTxDestination &address);
|
||||
|
||||
bool WriteTx(const CWalletTx& wtx);
|
||||
bool EraseTx(uint256 hash);
|
||||
@@ -154,15 +159,16 @@ public:
|
||||
|
||||
/// This writes directly to the database, and will not update the CWallet's cached accounting entries!
|
||||
/// Use wallet.AddAccountingEntry instead, to write *and* update its caches.
|
||||
bool WriteAccountingEntry_Backend(const CAccountingEntry& acentry);
|
||||
bool ReadAccount(const std::string& strAccount, CAccount& account);
|
||||
bool WriteAccount(const std::string& strAccount, const CAccount& account);
|
||||
bool WriteAccountingEntry(const uint64_t nAccEntryNum, const CAccountingEntry &acentry);
|
||||
bool WriteAccountingEntry_Backend(const CAccountingEntry &acentry);
|
||||
bool ReadAccount(const std::string &strAccount, CAccount &account);
|
||||
bool WriteAccount(const std::string &strAccount, const CAccount &account);
|
||||
|
||||
/// Write destination data key,value tuple to database
|
||||
bool WriteDestData(const std::string &address, const std::string &key, const std::string &value);
|
||||
bool WriteHDChain(const CHDChain& chain);
|
||||
bool WriteDestData(const CTxDestination &address, const std::string &key, const std::string &value);
|
||||
/// Erase destination data tuple from wallet database
|
||||
bool EraseDestData(const std::string &address, const std::string &key);
|
||||
bool EraseDestData(const CTxDestination &address, const std::string &key);
|
||||
bool WriteHDChain(const CHDChain& chain);
|
||||
CAmount GetAccountCreditDebit(const std::string& strAccount);
|
||||
void ListAccountCreditDebit(const std::string& strAccount, std::list<CAccountingEntry>& acentries);
|
||||
|
||||
@@ -177,8 +183,6 @@ public:
|
||||
private:
|
||||
CWalletDB(const CWalletDB&);
|
||||
void operator=(const CWalletDB&);
|
||||
|
||||
bool WriteAccountingEntry(const uint64_t nAccEntryNum, const CAccountingEntry& acentry);
|
||||
};
|
||||
|
||||
void ThreadFlushWalletDB(const std::string& strFile);
|
||||
|
||||
Reference in New Issue
Block a user