|
|
@ -140,58 +140,22 @@ Value listusernames(const Array& params, bool fHelp) |
|
|
|
return ret; |
|
|
|
return ret; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
Value sendtoaddress(const Array& params, bool fHelp) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
if (fHelp || params.size() < 2 || params.size() > 4) |
|
|
|
|
|
|
|
throw runtime_error( |
|
|
|
|
|
|
|
"sendtoaddress <bitcoinaddress> <amount> [comment] [comment-to]\n" |
|
|
|
|
|
|
|
"<amount> is a real and is rounded to the nearest 0.00000001" |
|
|
|
|
|
|
|
+ HelpRequiringPassphrase()); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
CBitcoinAddress address(params[0].get_str()); |
|
|
|
|
|
|
|
if (!address.IsValid()) |
|
|
|
|
|
|
|
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid Bitcoin address"); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Amount
|
|
|
|
|
|
|
|
int64 nAmount = AmountFromValue(params[1]); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Wallet comments
|
|
|
|
|
|
|
|
CWalletTx wtx; |
|
|
|
|
|
|
|
if (params.size() > 2 && params[2].type() != null_type && !params[2].get_str().empty()) |
|
|
|
|
|
|
|
wtx.mapValue["comment"] = params[2].get_str(); |
|
|
|
|
|
|
|
if (params.size() > 3 && params[3].type() != null_type && !params[3].get_str().empty()) |
|
|
|
|
|
|
|
wtx.mapValue["to"] = params[3].get_str(); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (pwalletMain->IsLocked()) |
|
|
|
|
|
|
|
throw JSONRPCError(RPC_WALLET_UNLOCK_NEEDED, "Error: Please enter the wallet passphrase with walletpassphrase first."); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
string strError;// = pwalletMain->SendMoneyToDestination(address.Get(), nAmount, wtx);
|
|
|
|
|
|
|
|
if (strError != "") |
|
|
|
|
|
|
|
throw JSONRPCError(RPC_WALLET_ERROR, strError); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return wtx.GetHash().GetHex(); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Value signmessage(const Array& params, bool fHelp) |
|
|
|
Value signmessage(const Array& params, bool fHelp) |
|
|
|
{ |
|
|
|
{ |
|
|
|
if (fHelp || params.size() != 2) |
|
|
|
if (fHelp || params.size() != 2) |
|
|
|
throw runtime_error( |
|
|
|
throw runtime_error( |
|
|
|
"signmessage <bitcoinaddress> <message>\n" |
|
|
|
"signmessage <username> <message>\n" |
|
|
|
"Sign a message with the private key of an address"); |
|
|
|
"Sign a message with the private key of an address"); |
|
|
|
|
|
|
|
|
|
|
|
EnsureWalletIsUnlocked(); |
|
|
|
EnsureWalletIsUnlocked(); |
|
|
|
|
|
|
|
|
|
|
|
string strAddress = params[0].get_str(); |
|
|
|
string strUsername = params[0].get_str(); |
|
|
|
string strMessage = params[1].get_str(); |
|
|
|
string strMessage = params[1].get_str(); |
|
|
|
|
|
|
|
|
|
|
|
CBitcoinAddress addr(strAddress); |
|
|
|
|
|
|
|
if (!addr.IsValid()) |
|
|
|
|
|
|
|
throw JSONRPCError(RPC_TYPE_ERROR, "Invalid address"); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
CKeyID keyID; |
|
|
|
CKeyID keyID; |
|
|
|
if (!addr.GetKeyID(keyID)) |
|
|
|
if( !pwalletMain->GetKeyIdFromUsername(strUsername, keyID) ) |
|
|
|
throw JSONRPCError(RPC_TYPE_ERROR, "Address does not refer to key"); |
|
|
|
throw JSONRPCError(RPC_WALLET_INVALID_ACCOUNT_NAME, "Error: no such user in wallet"); |
|
|
|
|
|
|
|
|
|
|
|
CKey key; |
|
|
|
CKey key; |
|
|
|
if (!pwalletMain->GetKey(keyID, key)) |
|
|
|
if (!pwalletMain->GetKey(keyID, key)) |
|
|
@ -212,20 +176,36 @@ Value verifymessage(const Array& params, bool fHelp) |
|
|
|
{ |
|
|
|
{ |
|
|
|
if (fHelp || params.size() != 3) |
|
|
|
if (fHelp || params.size() != 3) |
|
|
|
throw runtime_error( |
|
|
|
throw runtime_error( |
|
|
|
"verifymessage <bitcoinaddress> <signature> <message>\n" |
|
|
|
"verifymessage <username> <signature> <message>\n" |
|
|
|
"Verify a signed message"); |
|
|
|
"Verify a signed message"); |
|
|
|
|
|
|
|
|
|
|
|
string strAddress = params[0].get_str(); |
|
|
|
string strUsername = params[0].get_str(); |
|
|
|
string strSign = params[1].get_str(); |
|
|
|
string strSign = params[1].get_str(); |
|
|
|
string strMessage = params[2].get_str(); |
|
|
|
string strMessage = params[2].get_str(); |
|
|
|
|
|
|
|
|
|
|
|
CBitcoinAddress addr(strAddress); |
|
|
|
CPubKey pubkey; |
|
|
|
if (!addr.IsValid()) |
|
|
|
{ |
|
|
|
throw JSONRPCError(RPC_TYPE_ERROR, "Invalid address"); |
|
|
|
CKeyID keyID; |
|
|
|
|
|
|
|
if( pwalletMain->GetKeyIdFromUsername(strUsername, keyID) ) { |
|
|
|
|
|
|
|
if( !pwalletMain->GetPubKey(keyID, pubkey) ) |
|
|
|
|
|
|
|
throw JSONRPCError(RPC_WALLET_INVALID_ACCOUNT_NAME, "Error: failed to read pubkey from wallet"); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
CKeyID keyID; |
|
|
|
if( !pubkey.IsValid() ) { |
|
|
|
if (!addr.GetKeyID(keyID)) |
|
|
|
CTransaction txOut; |
|
|
|
throw JSONRPCError(RPC_TYPE_ERROR, "Address does not refer to key"); |
|
|
|
uint256 hashBlock; |
|
|
|
|
|
|
|
uint256 userhash = SerializeHash(strUsername); |
|
|
|
|
|
|
|
if( !GetTransaction(userhash, txOut, hashBlock) ) |
|
|
|
|
|
|
|
throw JSONRPCError(RPC_WALLET_INVALID_ACCOUNT_NAME, "Error: this username does not exist in tx database"); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
std::vector< std::vector<unsigned char> > vData; |
|
|
|
|
|
|
|
if( !txOut.pubKey.ExtractPushData(vData) || vData.size() < 1 ) |
|
|
|
|
|
|
|
throw JSONRPCError(RPC_INTERNAL_ERROR, "Error: error extracting pubkey from tx"); |
|
|
|
|
|
|
|
pubkey = CPubKey(vData[0]); |
|
|
|
|
|
|
|
if( !pubkey.IsValid() ) |
|
|
|
|
|
|
|
throw JSONRPCError(RPC_INTERNAL_ERROR, "Error: invalid pubkey data from tx"); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
bool fInvalid = false; |
|
|
|
bool fInvalid = false; |
|
|
|
vector<unsigned char> vchSig = DecodeBase64(strSign.c_str(), &fInvalid); |
|
|
|
vector<unsigned char> vchSig = DecodeBase64(strSign.c_str(), &fInvalid); |
|
|
@ -237,410 +217,14 @@ Value verifymessage(const Array& params, bool fHelp) |
|
|
|
ss << strMessageMagic; |
|
|
|
ss << strMessageMagic; |
|
|
|
ss << strMessage; |
|
|
|
ss << strMessage; |
|
|
|
|
|
|
|
|
|
|
|
CPubKey pubkey; |
|
|
|
CPubKey pubkeyRec; |
|
|
|
if (!pubkey.RecoverCompact(ss.GetHash(), vchSig)) |
|
|
|
if (!pubkeyRec.RecoverCompact(ss.GetHash(), vchSig)) |
|
|
|
return false; |
|
|
|
return false; |
|
|
|
|
|
|
|
|
|
|
|
return (pubkey.GetID() == keyID); |
|
|
|
return (pubkeyRec.GetID() == pubkey.GetID()); |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Value getreceivedbyaddress(const Array& params, bool fHelp) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
if (fHelp || params.size() < 1 || params.size() > 2) |
|
|
|
|
|
|
|
throw runtime_error( |
|
|
|
|
|
|
|
"getreceivedbyaddress <bitcoinaddress> [minconf=1]\n" |
|
|
|
|
|
|
|
"Returns the total amount received by <bitcoinaddress> in transactions with at least [minconf] confirmations."); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Bitcoin address
|
|
|
|
|
|
|
|
CBitcoinAddress address = CBitcoinAddress(params[0].get_str()); |
|
|
|
|
|
|
|
CScript scriptPubKey; |
|
|
|
|
|
|
|
if (!address.IsValid()) |
|
|
|
|
|
|
|
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid Bitcoin address"); |
|
|
|
|
|
|
|
scriptPubKey.SetDestination(address.Get()); |
|
|
|
|
|
|
|
if (!IsMine(*pwalletMain,scriptPubKey)) |
|
|
|
|
|
|
|
return (double)0.0; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Minimum confirmations
|
|
|
|
|
|
|
|
int nMinDepth = 1; |
|
|
|
|
|
|
|
if (params.size() > 1) |
|
|
|
|
|
|
|
nMinDepth = params[1].get_int(); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Tally
|
|
|
|
|
|
|
|
int64 nAmount = 0; |
|
|
|
|
|
|
|
for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
const CWalletTx& wtx = (*it).second; |
|
|
|
|
|
|
|
if (wtx.IsSpamMessage()) |
|
|
|
|
|
|
|
continue; |
|
|
|
|
|
|
|
/*
|
|
|
|
|
|
|
|
BOOST_FOREACH(const CTxOut& txout, wtx.vout) |
|
|
|
|
|
|
|
if (txout.scriptPubKey == scriptPubKey) |
|
|
|
|
|
|
|
if (wtx.GetDepthInMainChain() >= nMinDepth) |
|
|
|
|
|
|
|
nAmount += txout.nValue; |
|
|
|
|
|
|
|
*/ |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return ValueFromAmount(nAmount); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void GetAccountAddresses(string strAccount, set<CTxDestination>& setAddress) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
BOOST_FOREACH(const PAIRTYPE(CTxDestination, string)& item, pwalletMain->mapAddressBook) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
const CTxDestination& address = item.first; |
|
|
|
|
|
|
|
const string& strName = item.second; |
|
|
|
|
|
|
|
if (strName == strAccount) |
|
|
|
|
|
|
|
setAddress.insert(address); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Value getreceivedbyaccount(const Array& params, bool fHelp) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
if (fHelp || params.size() < 1 || params.size() > 2) |
|
|
|
|
|
|
|
throw runtime_error( |
|
|
|
|
|
|
|
"getreceivedbyaccount <account> [minconf=1]\n" |
|
|
|
|
|
|
|
"Returns the total amount received by addresses with <account> in transactions with at least [minconf] confirmations."); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Minimum confirmations
|
|
|
|
|
|
|
|
int nMinDepth = 1; |
|
|
|
|
|
|
|
if (params.size() > 1) |
|
|
|
|
|
|
|
nMinDepth = params[1].get_int(); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Get the set of pub keys assigned to account
|
|
|
|
|
|
|
|
string strAccount = AccountFromValue(params[0]); |
|
|
|
|
|
|
|
set<CTxDestination> setAddress; |
|
|
|
|
|
|
|
GetAccountAddresses(strAccount, setAddress); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Tally
|
|
|
|
|
|
|
|
int64 nAmount = 0; |
|
|
|
|
|
|
|
for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
const CWalletTx& wtx = (*it).second; |
|
|
|
|
|
|
|
if (wtx.IsSpamMessage()) |
|
|
|
|
|
|
|
continue; |
|
|
|
|
|
|
|
/*
|
|
|
|
|
|
|
|
BOOST_FOREACH(const CTxOut& txout, wtx.vout) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
CTxDestination address; |
|
|
|
|
|
|
|
if (ExtractDestination(txout.scriptPubKey, address) && IsMine(*pwalletMain, address) && setAddress.count(address)) |
|
|
|
|
|
|
|
if (wtx.GetDepthInMainChain() >= nMinDepth) |
|
|
|
|
|
|
|
nAmount += txout.nValue; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
*/ |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return (double)nAmount / (double)COIN; |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Value sendmany(const Array& params, bool fHelp) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
if (fHelp || params.size() < 2 || params.size() > 4) |
|
|
|
|
|
|
|
throw runtime_error( |
|
|
|
|
|
|
|
"sendmany <fromaccount> {address:amount,...} [minconf=1] [comment]\n" |
|
|
|
|
|
|
|
"amounts are double-precision floating point numbers" |
|
|
|
|
|
|
|
+ HelpRequiringPassphrase()); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
string strAccount = AccountFromValue(params[0]); |
|
|
|
|
|
|
|
Object sendTo = params[1].get_obj(); |
|
|
|
|
|
|
|
int nMinDepth = 1; |
|
|
|
|
|
|
|
if (params.size() > 2) |
|
|
|
|
|
|
|
nMinDepth = params[2].get_int(); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
CWalletTx wtx; |
|
|
|
|
|
|
|
wtx.strFromAccount = strAccount; |
|
|
|
|
|
|
|
if (params.size() > 3 && params[3].type() != null_type && !params[3].get_str().empty()) |
|
|
|
|
|
|
|
wtx.mapValue["comment"] = params[3].get_str(); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
set<CBitcoinAddress> setAddress; |
|
|
|
|
|
|
|
vector<pair<CScript, int64> > vecSend; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int64 totalAmount = 0; |
|
|
|
|
|
|
|
BOOST_FOREACH(const Pair& s, sendTo) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
CBitcoinAddress address(s.name_); |
|
|
|
|
|
|
|
if (!address.IsValid()) |
|
|
|
|
|
|
|
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, string("Invalid Bitcoin address: ")+s.name_); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (setAddress.count(address)) |
|
|
|
|
|
|
|
throw JSONRPCError(RPC_INVALID_PARAMETER, string("Invalid parameter, duplicated address: ")+s.name_); |
|
|
|
|
|
|
|
setAddress.insert(address); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
CScript scriptPubKey; |
|
|
|
|
|
|
|
scriptPubKey.SetDestination(address.Get()); |
|
|
|
|
|
|
|
int64 nAmount = AmountFromValue(s.value_); |
|
|
|
|
|
|
|
totalAmount += nAmount; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
vecSend.push_back(make_pair(scriptPubKey, nAmount)); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
EnsureWalletIsUnlocked(); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Send
|
|
|
|
|
|
|
|
CReserveKey keyChange(pwalletMain); |
|
|
|
|
|
|
|
int64 nFeeRequired = 0; |
|
|
|
|
|
|
|
string strFailReason; |
|
|
|
|
|
|
|
bool fCreated = pwalletMain->CreateTransaction(vecSend, wtx, keyChange, nFeeRequired, strFailReason); |
|
|
|
|
|
|
|
if (!fCreated) |
|
|
|
|
|
|
|
throw JSONRPCError(RPC_WALLET_INSUFFICIENT_FUNDS, strFailReason); |
|
|
|
|
|
|
|
if (!pwalletMain->CommitTransaction(wtx, keyChange)) |
|
|
|
|
|
|
|
throw JSONRPCError(RPC_WALLET_ERROR, "Transaction commit failed"); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return wtx.GetHash().GetHex(); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
|
|
|
|
// Used by addmultisigaddress / createmultisig:
|
|
|
|
|
|
|
|
//
|
|
|
|
|
|
|
|
static CScript _createmultisig(const Array& params) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
int nRequired = params[0].get_int(); |
|
|
|
|
|
|
|
const Array& keys = params[1].get_array(); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Gather public keys
|
|
|
|
|
|
|
|
if (nRequired < 1) |
|
|
|
|
|
|
|
throw runtime_error("a multisignature address must require at least one key to redeem"); |
|
|
|
|
|
|
|
if ((int)keys.size() < nRequired) |
|
|
|
|
|
|
|
throw runtime_error( |
|
|
|
|
|
|
|
strprintf("not enough keys supplied " |
|
|
|
|
|
|
|
"(got %"PRIszu" keys, but need at least %d to redeem)", keys.size(), nRequired)); |
|
|
|
|
|
|
|
std::vector<CPubKey> pubkeys; |
|
|
|
|
|
|
|
pubkeys.resize(keys.size()); |
|
|
|
|
|
|
|
for (unsigned int i = 0; i < keys.size(); i++) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
const std::string& ks = keys[i].get_str(); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Case 1: Bitcoin address and we have full public key:
|
|
|
|
|
|
|
|
CBitcoinAddress address(ks); |
|
|
|
|
|
|
|
if (address.IsValid()) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
CKeyID keyID; |
|
|
|
|
|
|
|
if (!address.GetKeyID(keyID)) |
|
|
|
|
|
|
|
throw runtime_error( |
|
|
|
|
|
|
|
strprintf("%s does not refer to a key",ks.c_str())); |
|
|
|
|
|
|
|
CPubKey vchPubKey; |
|
|
|
|
|
|
|
if (!pwalletMain->GetPubKey(keyID, vchPubKey)) |
|
|
|
|
|
|
|
throw runtime_error( |
|
|
|
|
|
|
|
strprintf("no full public key for address %s",ks.c_str())); |
|
|
|
|
|
|
|
if (!vchPubKey.IsFullyValid()) |
|
|
|
|
|
|
|
throw runtime_error(" Invalid public key: "+ks); |
|
|
|
|
|
|
|
pubkeys[i] = vchPubKey; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Case 2: hex public key
|
|
|
|
|
|
|
|
else if (IsHex(ks)) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
CPubKey vchPubKey(ParseHex(ks)); |
|
|
|
|
|
|
|
if (!vchPubKey.IsFullyValid()) |
|
|
|
|
|
|
|
throw runtime_error(" Invalid public key: "+ks); |
|
|
|
|
|
|
|
pubkeys[i] = vchPubKey; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
else |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
throw runtime_error(" Invalid public key: "+ks); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
CScript result; |
|
|
|
|
|
|
|
result.SetMultisig(nRequired, pubkeys); |
|
|
|
|
|
|
|
return result; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Value addmultisigaddress(const Array& params, bool fHelp) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
if (fHelp || params.size() < 2 || params.size() > 3) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
string msg = "addmultisigaddress <nrequired> <'[\"key\",\"key\"]'> [account]\n" |
|
|
|
|
|
|
|
"Add a nrequired-to-sign multisignature address to the wallet\"\n" |
|
|
|
|
|
|
|
"each key is a Bitcoin address or hex-encoded public key\n" |
|
|
|
|
|
|
|
"If [account] is specified, assign address to [account]."; |
|
|
|
|
|
|
|
throw runtime_error(msg); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
string strAccount; |
|
|
|
|
|
|
|
if (params.size() > 2) |
|
|
|
|
|
|
|
strAccount = AccountFromValue(params[2]); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Construct using pay-to-script-hash:
|
|
|
|
|
|
|
|
CScript inner = _createmultisig(params); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//pwalletMain->SetAddressBookName(innerID, strAccount);
|
|
|
|
|
|
|
|
//return CBitcoinAddress(innerID).ToString();
|
|
|
|
|
|
|
|
return CBitcoinAddress().ToString(); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Value createmultisig(const Array& params, bool fHelp) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
if (fHelp || params.size() < 2 || params.size() > 2) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
string msg = "createmultisig <nrequired> <'[\"key\",\"key\"]'>\n" |
|
|
|
|
|
|
|
"Creates a multi-signature address and returns a json object\n" |
|
|
|
|
|
|
|
"with keys:\n" |
|
|
|
|
|
|
|
"address : bitcoin address\n" |
|
|
|
|
|
|
|
"redeemScript : hex-encoded redemption script"; |
|
|
|
|
|
|
|
throw runtime_error(msg); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Construct using pay-to-script-hash:
|
|
|
|
|
|
|
|
CScript inner = _createmultisig(params); |
|
|
|
|
|
|
|
CScriptID innerID = inner.GetID(); |
|
|
|
|
|
|
|
CBitcoinAddress address(innerID); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Object result; |
|
|
|
|
|
|
|
result.push_back(Pair("address", address.ToString())); |
|
|
|
|
|
|
|
result.push_back(Pair("redeemScript", HexStr(inner.begin(), inner.end()))); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return result; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
struct tallyitem |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
int64 nAmount; |
|
|
|
|
|
|
|
int nConf; |
|
|
|
|
|
|
|
vector<uint256> txids; |
|
|
|
|
|
|
|
tallyitem() |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
nAmount = 0; |
|
|
|
|
|
|
|
nConf = std::numeric_limits<int>::max(); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Value ListReceived(const Array& params, bool fByAccounts) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
// Minimum confirmations
|
|
|
|
|
|
|
|
int nMinDepth = 1; |
|
|
|
|
|
|
|
if (params.size() > 0) |
|
|
|
|
|
|
|
nMinDepth = params[0].get_int(); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Whether to include empty accounts
|
|
|
|
|
|
|
|
bool fIncludeEmpty = false; |
|
|
|
|
|
|
|
if (params.size() > 1) |
|
|
|
|
|
|
|
fIncludeEmpty = params[1].get_bool(); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Tally
|
|
|
|
|
|
|
|
map<CBitcoinAddress, tallyitem> mapTally; |
|
|
|
|
|
|
|
for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
const CWalletTx& wtx = (*it).second; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (wtx.IsSpamMessage()) |
|
|
|
|
|
|
|
continue; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int nDepth = wtx.GetDepthInMainChain(); |
|
|
|
|
|
|
|
if (nDepth < nMinDepth) |
|
|
|
|
|
|
|
continue; |
|
|
|
|
|
|
|
/*
|
|
|
|
|
|
|
|
BOOST_FOREACH(const CTxOut& txout, wtx.vout) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
CTxDestination address; |
|
|
|
|
|
|
|
if (!ExtractDestination(txout.scriptPubKey, address) || !IsMine(*pwalletMain, address)) |
|
|
|
|
|
|
|
continue; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
tallyitem& item = mapTally[address]; |
|
|
|
|
|
|
|
item.nAmount += txout.nValue; |
|
|
|
|
|
|
|
item.nConf = min(item.nConf, nDepth); |
|
|
|
|
|
|
|
item.txids.push_back(wtx.GetHash()); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
*/ |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Reply
|
|
|
|
|
|
|
|
Array ret; |
|
|
|
|
|
|
|
map<string, tallyitem> mapAccountTally; |
|
|
|
|
|
|
|
BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, string)& item, pwalletMain->mapAddressBook) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
const CBitcoinAddress& address = item.first; |
|
|
|
|
|
|
|
const string& strAccount = item.second; |
|
|
|
|
|
|
|
map<CBitcoinAddress, tallyitem>::iterator it = mapTally.find(address); |
|
|
|
|
|
|
|
if (it == mapTally.end() && !fIncludeEmpty) |
|
|
|
|
|
|
|
continue; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int64 nAmount = 0; |
|
|
|
|
|
|
|
int nConf = std::numeric_limits<int>::max(); |
|
|
|
|
|
|
|
if (it != mapTally.end()) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
nAmount = (*it).second.nAmount; |
|
|
|
|
|
|
|
nConf = (*it).second.nConf; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (fByAccounts) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
tallyitem& item = mapAccountTally[strAccount]; |
|
|
|
|
|
|
|
item.nAmount += nAmount; |
|
|
|
|
|
|
|
item.nConf = min(item.nConf, nConf); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
else |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
Object obj; |
|
|
|
|
|
|
|
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))); |
|
|
|
|
|
|
|
Array transactions; |
|
|
|
|
|
|
|
if (it != mapTally.end()) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
BOOST_FOREACH(const uint256& item, (*it).second.txids) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
transactions.push_back(item.GetHex()); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
obj.push_back(Pair("txids", transactions)); |
|
|
|
|
|
|
|
ret.push_back(obj); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (fByAccounts) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
for (map<string, tallyitem>::iterator it = mapAccountTally.begin(); it != mapAccountTally.end(); ++it) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
int64 nAmount = (*it).second.nAmount; |
|
|
|
|
|
|
|
int nConf = (*it).second.nConf; |
|
|
|
|
|
|
|
Object obj; |
|
|
|
|
|
|
|
obj.push_back(Pair("account", (*it).first)); |
|
|
|
|
|
|
|
obj.push_back(Pair("amount", ValueFromAmount(nAmount))); |
|
|
|
|
|
|
|
obj.push_back(Pair("confirmations", (nConf == std::numeric_limits<int>::max() ? 0 : nConf))); |
|
|
|
|
|
|
|
ret.push_back(obj); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return ret; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Value listreceivedbyaddress(const Array& params, bool fHelp) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
if (fHelp || params.size() > 2) |
|
|
|
|
|
|
|
throw runtime_error( |
|
|
|
|
|
|
|
"listreceivedbyaddress [minconf=1] [includeempty=false]\n" |
|
|
|
|
|
|
|
"[minconf] is the minimum number of confirmations before payments are included.\n" |
|
|
|
|
|
|
|
"[includeempty] whether to include addresses that haven't received any payments.\n" |
|
|
|
|
|
|
|
"Returns an array of objects containing:\n" |
|
|
|
|
|
|
|
" \"address\" : receiving address\n" |
|
|
|
|
|
|
|
" \"account\" : the account of the receiving address\n" |
|
|
|
|
|
|
|
" \"amount\" : total amount received by the address\n" |
|
|
|
|
|
|
|
" \"confirmations\" : number of confirmations of the most recent transaction included\n" |
|
|
|
|
|
|
|
" \"txids\" : list of transactions with outputs to the address\n"); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return ListReceived(params, false); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Value listreceivedbyaccount(const Array& params, bool fHelp) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
if (fHelp || params.size() > 2) |
|
|
|
|
|
|
|
throw runtime_error( |
|
|
|
|
|
|
|
"listreceivedbyaccount [minconf=1] [includeempty=false]\n" |
|
|
|
|
|
|
|
"[minconf] is the minimum number of confirmations before payments are included.\n" |
|
|
|
|
|
|
|
"[includeempty] whether to include accounts that haven't received any payments.\n" |
|
|
|
|
|
|
|
"Returns an array of objects containing:\n" |
|
|
|
|
|
|
|
" \"account\" : the account of the receiving addresses\n" |
|
|
|
|
|
|
|
" \"amount\" : total amount received by addresses with this account\n" |
|
|
|
|
|
|
|
" \"confirmations\" : number of confirmations of the most recent transaction included"); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return ListReceived(params, true); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void ListTransactions(const CWalletTx& wtx, const string& strAccount, int nMinDepth, bool fLong, Array& ret) |
|
|
|
void ListTransactions(const CWalletTx& wtx, const string& strAccount, int nMinDepth, bool fLong, Array& ret) |
|
|
|
{ |
|
|
|
{ |
|
|
|
bool fAllAccounts = (strAccount == string("*")); |
|
|
|
bool fAllAccounts = (strAccount == string("*")); |
|
|
@ -710,35 +294,6 @@ Value listtransactions(const Array& params, bool fHelp) |
|
|
|
return ret; |
|
|
|
return ret; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
Value listaccounts(const Array& params, bool fHelp) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
if (fHelp || params.size() > 1) |
|
|
|
|
|
|
|
throw runtime_error( |
|
|
|
|
|
|
|
"listaccounts [minconf=1]\n" |
|
|
|
|
|
|
|
"Returns Object that has account names as keys, account balances as values."); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int nMinDepth = 1; |
|
|
|
|
|
|
|
if (params.size() > 0) |
|
|
|
|
|
|
|
nMinDepth = params[0].get_int(); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
map<string, int64> mapAccountBalances; |
|
|
|
|
|
|
|
BOOST_FOREACH(const PAIRTYPE(CTxDestination, string)& entry, pwalletMain->mapAddressBook) { |
|
|
|
|
|
|
|
if (IsMine(*pwalletMain, entry.first)) // This address belongs to me
|
|
|
|
|
|
|
|
mapAccountBalances[entry.second] = 0; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
const CWalletTx& wtx = (*it).second; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (wtx.GetDepthInMainChain() >= nMinDepth) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
Array ret; |
|
|
|
|
|
|
|
return ret; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Value listsinceblock(const Array& params, bool fHelp) |
|
|
|
Value listsinceblock(const Array& params, bool fHelp) |
|
|
|
{ |
|
|
|
{ |
|
|
|
if (fHelp) |
|
|
|
if (fHelp) |
|
|
@ -992,32 +547,4 @@ public: |
|
|
|
} |
|
|
|
} |
|
|
|
}; |
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
Value validateaddress(const Array& params, bool fHelp) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
if (fHelp || params.size() != 1) |
|
|
|
|
|
|
|
throw runtime_error( |
|
|
|
|
|
|
|
"validateaddress <bitcoinaddress>\n" |
|
|
|
|
|
|
|
"Return information about <bitcoinaddress>."); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
CBitcoinAddress address(params[0].get_str()); |
|
|
|
|
|
|
|
bool isValid = address.IsValid(); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Object ret; |
|
|
|
|
|
|
|
ret.push_back(Pair("isvalid", isValid)); |
|
|
|
|
|
|
|
if (isValid) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
CTxDestination dest = address.Get(); |
|
|
|
|
|
|
|
string currentAddress = address.ToString(); |
|
|
|
|
|
|
|
ret.push_back(Pair("address", currentAddress)); |
|
|
|
|
|
|
|
bool fMine = IsMine(*pwalletMain, dest); |
|
|
|
|
|
|
|
ret.push_back(Pair("ismine", fMine)); |
|
|
|
|
|
|
|
if (fMine) { |
|
|
|
|
|
|
|
Object detail = boost::apply_visitor(DescribeAddressVisitor(), dest); |
|
|
|
|
|
|
|
ret.insert(ret.end(), detail.begin(), detail.end()); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
if (pwalletMain->mapAddressBook.count(dest)) |
|
|
|
|
|
|
|
ret.push_back(Pair("account", pwalletMain->mapAddressBook[dest])); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
return ret; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|