Merge remote-tracking branch 'zcash/master' into dPoW
This commit is contained in:
@@ -29,6 +29,23 @@
|
||||
|
||||
using namespace libzcash;
|
||||
|
||||
int find_output(Object obj, int n) {
|
||||
Value outputMapValue = find_value(obj, "outputmap");
|
||||
if (outputMapValue.type() != array_type) {
|
||||
throw JSONRPCError(RPC_WALLET_ERROR, "Missing outputmap for JoinSplit operation");
|
||||
}
|
||||
|
||||
Array outputMap = outputMapValue.get_array();
|
||||
assert(outputMap.size() == ZC_NUM_JS_OUTPUTS);
|
||||
for (size_t i = 0; i < outputMap.size(); i++) {
|
||||
if (outputMap[i] == n) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
throw std::logic_error("n is not present in outputmap");
|
||||
}
|
||||
|
||||
AsyncRPCOperation_sendmany::AsyncRPCOperation_sendmany(
|
||||
std::string fromAddress,
|
||||
std::vector<SendManyRecipient> tOutputs,
|
||||
@@ -179,12 +196,15 @@ bool AsyncRPCOperation_sendmany::main_impl() {
|
||||
CAmount sendAmount = z_outputs_total + t_outputs_total;
|
||||
CAmount targetAmount = sendAmount + minersFee;
|
||||
|
||||
assert(!isfromtaddr_ || z_inputs_total == 0);
|
||||
assert(!isfromzaddr_ || t_inputs_total == 0);
|
||||
|
||||
if (isfromtaddr_ && (t_inputs_total < targetAmount)) {
|
||||
throw JSONRPCError(RPC_WALLET_INSUFFICIENT_FUNDS, strprintf("Insufficient transparent funds, have %ld, need %ld plus fee %ld", t_inputs_total, t_outputs_total, minersFee));
|
||||
throw JSONRPCError(RPC_WALLET_INSUFFICIENT_FUNDS, strprintf("Insufficient transparent funds, have %ld, need %ld", t_inputs_total, targetAmount));
|
||||
}
|
||||
|
||||
if (isfromzaddr_ && (z_inputs_total < targetAmount)) {
|
||||
throw JSONRPCError(RPC_WALLET_INSUFFICIENT_FUNDS, strprintf("Insufficient protected funds, have %ld, need %ld plus fee %ld", z_inputs_total, z_outputs_total, minersFee));
|
||||
throw JSONRPCError(RPC_WALLET_INSUFFICIENT_FUNDS, strprintf("Insufficient protected funds, have %ld, need %ld", z_inputs_total, targetAmount));
|
||||
}
|
||||
|
||||
// If from address is a taddr, select UTXOs to spend
|
||||
@@ -284,8 +304,9 @@ bool AsyncRPCOperation_sendmany::main_impl() {
|
||||
* -> zaddrs
|
||||
*
|
||||
* Note: Consensus rule states that coinbase utxos can only be sent to a zaddr.
|
||||
* Any change over and above the amount specified by the user will be sent
|
||||
* to the same zaddr the user is sending funds to.
|
||||
* Local wallet rule does not allow any change when sending coinbase utxos
|
||||
* since there is currently no way to specify a change address and we don't
|
||||
* want users accidentally sending excess funds to a recipient.
|
||||
*/
|
||||
if (isfromtaddr_) {
|
||||
add_taddr_outputs_to_tx();
|
||||
@@ -294,25 +315,13 @@ bool AsyncRPCOperation_sendmany::main_impl() {
|
||||
CAmount fundsSpent = t_outputs_total + minersFee + z_outputs_total;
|
||||
CAmount change = funds - fundsSpent;
|
||||
|
||||
// If there is a single zaddr and there are coinbase utxos, change goes to the zaddr.
|
||||
if (change > 0) {
|
||||
if (isSingleZaddrOutput && selectedUTXOCoinbase) {
|
||||
std::string address = std::get<0>(zOutputsDeque.front());
|
||||
SendManyRecipient smr(address, change, std::string());
|
||||
zOutputsDeque.push_back(smr);
|
||||
|
||||
LogPrint("zrpc", "%s: change from coinbase utxo is also sent to the recipient (amount=%s)\n",
|
||||
getId().substr(0, 10),
|
||||
FormatMoney(change, false)
|
||||
);
|
||||
|
||||
} else if (!isSingleZaddrOutput && selectedUTXOCoinbase) {
|
||||
// This should not happen and is not allowed
|
||||
assert(false);
|
||||
if (selectedUTXOCoinbase) {
|
||||
assert(isSingleZaddrOutput);
|
||||
throw JSONRPCError(RPC_WALLET_ERROR, strprintf(
|
||||
"Change %ld not allowed. When protecting coinbase funds, the wallet does not allow any change as there is currently no way to specify a change address in z_sendmany.", change));
|
||||
} else {
|
||||
// If there is a single zaddr and no coinbase utxos, just use a regular output for change.
|
||||
add_taddr_change_output_to_tx(change);
|
||||
|
||||
LogPrint("zrpc", "%s: transparent change in transaction output (amount=%s)\n",
|
||||
getId().substr(0, 10),
|
||||
FormatMoney(change, false)
|
||||
@@ -372,6 +381,7 @@ bool AsyncRPCOperation_sendmany::main_impl() {
|
||||
*/
|
||||
Object obj;
|
||||
CAmount jsChange = 0; // this is updated after each joinsplit
|
||||
int changeOutputIndex = -1; // this is updated after each joinsplit if jsChange > 0
|
||||
bool minersFeeProcessed = false;
|
||||
|
||||
if (t_outputs_total > 0) {
|
||||
@@ -429,6 +439,10 @@ bool AsyncRPCOperation_sendmany::main_impl() {
|
||||
}
|
||||
|
||||
obj = perform_joinsplit(info, outPoints);
|
||||
|
||||
if (jsChange > 0) {
|
||||
changeOutputIndex = find_output(obj, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -442,9 +456,6 @@ bool AsyncRPCOperation_sendmany::main_impl() {
|
||||
// Keep track of treestate within this transaction
|
||||
boost::unordered_map<uint256, ZCIncrementalMerkleTree, CCoinsKeyHasher> intermediates;
|
||||
std::vector<uint256> previousCommitments;
|
||||
|
||||
// NOTE: Randomization of input and output order could break this in future
|
||||
const int changeOutputIndex = 1;
|
||||
|
||||
while (zOutputsDeque.size() > 0) {
|
||||
AsyncJoinSplitInfo info;
|
||||
@@ -483,7 +494,6 @@ bool AsyncRPCOperation_sendmany::main_impl() {
|
||||
throw JSONRPCError(RPC_WALLET_ERROR, "Could not find previous JoinSplit anchor");
|
||||
}
|
||||
|
||||
// NOTE: We assume the last commitment, output 1, is the change we want
|
||||
for (const uint256& commitment : prevJoinSplit.commitments) {
|
||||
tree.append(commitment);
|
||||
previousCommitments.push_back(commitment);
|
||||
@@ -645,6 +655,10 @@ bool AsyncRPCOperation_sendmany::main_impl() {
|
||||
}
|
||||
|
||||
obj = perform_joinsplit(info, witnesses, jsAnchor);
|
||||
|
||||
if (jsChange > 0) {
|
||||
changeOutputIndex = find_output(obj, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -758,7 +772,8 @@ bool AsyncRPCOperation_sendmany::find_unspent_notes() {
|
||||
for (CNotePlaintextEntry & entry : entries) {
|
||||
z_inputs_.push_back(SendManyInputJSOP(entry.jsop, entry.plaintext.note(frompaymentaddress_), CAmount(entry.plaintext.value)));
|
||||
std::string data(entry.plaintext.memo.begin(), entry.plaintext.memo.end());
|
||||
LogPrint("zrpc", "%s: found unspent note (txid=%s, vjoinsplit=%d, ciphertext=%d, amount=%s, memo=%s)\n",
|
||||
if (LogAcceptCategory("zrpcunsafe")) {
|
||||
LogPrint("zrpcunsafe", "%s: found unspent note (txid=%s, vjoinsplit=%d, ciphertext=%d, amount=%s, memo=%s)\n",
|
||||
getId().substr(0, 10),
|
||||
entry.jsop.hash.ToString().substr(0, 10),
|
||||
entry.jsop.js,
|
||||
@@ -766,6 +781,15 @@ bool AsyncRPCOperation_sendmany::find_unspent_notes() {
|
||||
FormatMoney(entry.plaintext.value, false),
|
||||
HexStr(data).substr(0, 10)
|
||||
);
|
||||
} else {
|
||||
LogPrint("zrpc", "%s: found unspent note (txid=%s, vjoinsplit=%d, ciphertext=%d, amount=%s)\n",
|
||||
getId().substr(0, 10),
|
||||
entry.jsop.hash.ToString().substr(0, 10),
|
||||
entry.jsop.js,
|
||||
int(entry.jsop.n), // uint8_t
|
||||
FormatMoney(entry.plaintext.value, false)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if (z_inputs_.size() == 0) {
|
||||
@@ -845,11 +869,20 @@ Object AsyncRPCOperation_sendmany::perform_joinsplit(
|
||||
);
|
||||
|
||||
// Generate the proof, this can take over a minute.
|
||||
JSDescription jsdesc(*pzcashParams,
|
||||
boost::array<libzcash::JSInput, ZC_NUM_JS_INPUTS> inputs
|
||||
{info.vjsin[0], info.vjsin[1]};
|
||||
boost::array<libzcash::JSOutput, ZC_NUM_JS_OUTPUTS> outputs
|
||||
{info.vjsout[0], info.vjsout[1]};
|
||||
boost::array<size_t, ZC_NUM_JS_INPUTS> inputMap;
|
||||
boost::array<size_t, ZC_NUM_JS_OUTPUTS> outputMap;
|
||||
JSDescription jsdesc = JSDescription::Randomized(
|
||||
*pzcashParams,
|
||||
joinSplitPubKey_,
|
||||
anchor,
|
||||
{info.vjsin[0], info.vjsin[1]},
|
||||
{info.vjsout[0], info.vjsout[1]},
|
||||
inputs,
|
||||
outputs,
|
||||
inputMap,
|
||||
outputMap,
|
||||
info.vpub_old,
|
||||
info.vpub_new,
|
||||
!this->testmode);
|
||||
@@ -910,10 +943,21 @@ Object AsyncRPCOperation_sendmany::perform_joinsplit(
|
||||
encryptedNote2 = HexStr(ss2.begin(), ss2.end());
|
||||
}
|
||||
|
||||
Array arrInputMap;
|
||||
Array arrOutputMap;
|
||||
for (size_t i = 0; i < ZC_NUM_JS_INPUTS; i++) {
|
||||
arrInputMap.push_back(inputMap[i]);
|
||||
}
|
||||
for (size_t i = 0; i < ZC_NUM_JS_OUTPUTS; i++) {
|
||||
arrOutputMap.push_back(outputMap[i]);
|
||||
}
|
||||
|
||||
Object obj;
|
||||
obj.push_back(Pair("encryptednote1", encryptedNote1));
|
||||
obj.push_back(Pair("encryptednote2", encryptedNote2));
|
||||
obj.push_back(Pair("rawtxn", HexStr(ss.begin(), ss.end())));
|
||||
obj.push_back(Pair("inputmap", arrInputMap));
|
||||
obj.push_back(Pair("outputmap", arrOutputMap));
|
||||
return obj;
|
||||
}
|
||||
|
||||
|
||||
@@ -11,9 +11,11 @@
|
||||
#include "zcash/Note.hpp"
|
||||
#include "zcash/NoteEncryption.hpp"
|
||||
|
||||
#include <boost/filesystem.hpp>
|
||||
|
||||
using ::testing::Return;
|
||||
|
||||
ZCJoinSplit* params = ZCJoinSplit::Unopened();
|
||||
extern ZCJoinSplit* params;
|
||||
|
||||
ACTION(ThrowLogicError) {
|
||||
throw std::logic_error("Boom");
|
||||
@@ -178,6 +180,13 @@ CWalletTx GetValidSpend(const libzcash::SpendingKey& sk,
|
||||
return wtx;
|
||||
}
|
||||
|
||||
TEST(wallet_tests, setup_datadir_location_run_as_first_test) {
|
||||
// Get temporary and unique path for file.
|
||||
boost::filesystem::path pathTemp = boost::filesystem::temp_directory_path() / boost::filesystem::unique_path();
|
||||
boost::filesystem::create_directories(pathTemp);
|
||||
mapArgs["-datadir"] = pathTemp.string();
|
||||
}
|
||||
|
||||
TEST(wallet_tests, note_data_serialisation) {
|
||||
auto sk = libzcash::SpendingKey::random();
|
||||
auto wtx = GetValidReceive(sk, 10, true);
|
||||
@@ -734,6 +743,14 @@ TEST(wallet_tests, cached_witnesses_chain_tip) {
|
||||
wallet.GetNoteWitnesses(notes, witnesses, anchor4);
|
||||
EXPECT_TRUE((bool) witnesses[0]);
|
||||
EXPECT_EQ(anchor2, anchor4);
|
||||
|
||||
// Incrementing with the same block again should not change the cache
|
||||
uint256 anchor5;
|
||||
wallet.IncrementNoteWitnesses(&index2, &block2, tree);
|
||||
std::vector<boost::optional<ZCIncrementalWitness>> witnesses5;
|
||||
wallet.GetNoteWitnesses(notes, witnesses5, anchor5);
|
||||
EXPECT_EQ(witnesses, witnesses5);
|
||||
EXPECT_EQ(anchor4, anchor5);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -81,10 +81,10 @@ Value importprivkey(const Array& params, bool fHelp)
|
||||
|
||||
if (fHelp || params.size() < 1 || params.size() > 3)
|
||||
throw runtime_error(
|
||||
"importprivkey \"bitcoinprivkey\" ( \"label\" rescan )\n"
|
||||
"importprivkey \"zcashprivkey\" ( \"label\" rescan )\n"
|
||||
"\nAdds a private key (as returned by dumpprivkey) to your wallet.\n"
|
||||
"\nArguments:\n"
|
||||
"1. \"bitcoinprivkey\" (string, required) The private key (see dumpprivkey)\n"
|
||||
"1. \"zcashprivkey\" (string, required) The private key (see dumpprivkey)\n"
|
||||
"2. \"label\" (string, optional, default=\"\") An optional label\n"
|
||||
"3. rescan (boolean, optional, default=true) Rescan the wallet for transactions\n"
|
||||
"\nNote: This call can take minutes to complete if rescan is true.\n"
|
||||
@@ -182,7 +182,7 @@ Value importaddress(const Array& params, bool fHelp)
|
||||
std::vector<unsigned char> data(ParseHex(params[0].get_str()));
|
||||
script = CScript(data.begin(), data.end());
|
||||
} else {
|
||||
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid Bitcoin address or script");
|
||||
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid Zcash address or script");
|
||||
}
|
||||
|
||||
string strLabel = "";
|
||||
@@ -321,7 +321,7 @@ Value importwallet_impl(const Array& params, bool fHelp, bool fImportZKeys)
|
||||
}
|
||||
catch (const std::runtime_error &e) {
|
||||
LogPrint("zrpc","Importing detected an error: %s\n", e.what());
|
||||
// Not a valid spending key, so carry on and see if it's a Bitcoin style address.
|
||||
// Not a valid spending key, so carry on and see if it's a Zcash style address.
|
||||
}
|
||||
}
|
||||
|
||||
@@ -388,11 +388,11 @@ Value dumpprivkey(const Array& params, bool fHelp)
|
||||
|
||||
if (fHelp || params.size() != 1)
|
||||
throw runtime_error(
|
||||
"dumpprivkey \"bitcoinaddress\"\n"
|
||||
"\nReveals the private key corresponding to 'bitcoinaddress'.\n"
|
||||
"dumpprivkey \"zcashaddress\"\n"
|
||||
"\nReveals the private key corresponding to 'zcashaddress'.\n"
|
||||
"Then the importprivkey can be used with this output\n"
|
||||
"\nArguments:\n"
|
||||
"1. \"bitcoinaddress\" (string, required) The bitcoin address for the private key\n"
|
||||
"1. \"zcashaddress\" (string, required) The zcash address for the private key\n"
|
||||
"\nResult:\n"
|
||||
"\"key\" (string) The private key\n"
|
||||
"\nExamples:\n"
|
||||
@@ -408,7 +408,7 @@ Value dumpprivkey(const Array& params, bool fHelp)
|
||||
string strAddress = params[0].get_str();
|
||||
CBitcoinAddress address;
|
||||
if (!address.SetString(strAddress))
|
||||
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid Bitcoin address");
|
||||
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid Zcash address");
|
||||
CKeyID keyID;
|
||||
if (!address.GetKeyID(keyID))
|
||||
throw JSONRPCError(RPC_TYPE_ERROR, "Address does not refer to a key");
|
||||
|
||||
@@ -114,11 +114,11 @@ Value getnewaddress(const Array& params, bool fHelp)
|
||||
if (fHelp || params.size() > 1)
|
||||
throw runtime_error(
|
||||
"getnewaddress ( \"account\" )\n"
|
||||
"\nReturns a new Bitcoin address for receiving payments.\n"
|
||||
"\nReturns a new Zcash address for receiving payments.\n"
|
||||
"\nArguments:\n"
|
||||
"1. \"account\" (string, optional) DEPRECATED. If provided, it MUST be set to the empty string \"\" to represent the default account. Passing any other string will result in an error.\n"
|
||||
"\nResult:\n"
|
||||
"\"bitcoinaddress\" (string) The new bitcoin address\n"
|
||||
"\"zcashaddress\" (string) The new zcash address\n"
|
||||
"\nExamples:\n"
|
||||
+ HelpExampleCli("getnewaddress", "")
|
||||
+ HelpExampleRpc("getnewaddress", "")
|
||||
@@ -191,11 +191,11 @@ Value getaccountaddress(const Array& params, bool fHelp)
|
||||
if (fHelp || params.size() != 1)
|
||||
throw runtime_error(
|
||||
"getaccountaddress \"account\"\n"
|
||||
"\nDEPRECATED. Returns the current Bitcoin address for receiving payments to this account.\n"
|
||||
"\nDEPRECATED. Returns the current Zcash address for receiving payments to this account.\n"
|
||||
"\nArguments:\n"
|
||||
"1. \"account\" (string, required) MUST be set to the empty string \"\" to represent the default account. Passing any other string will result in an error.\n"
|
||||
"\nResult:\n"
|
||||
"\"bitcoinaddress\" (string) The account bitcoin address\n"
|
||||
"\"zcashaddress\" (string) The account zcash address\n"
|
||||
"\nExamples:\n"
|
||||
+ HelpExampleCli("getaccountaddress", "")
|
||||
+ HelpExampleCli("getaccountaddress", "\"\"")
|
||||
@@ -223,7 +223,7 @@ Value getrawchangeaddress(const Array& params, bool fHelp)
|
||||
if (fHelp || params.size() > 1)
|
||||
throw runtime_error(
|
||||
"getrawchangeaddress\n"
|
||||
"\nReturns a new Bitcoin address, for receiving change.\n"
|
||||
"\nReturns a new Zcash address, for receiving change.\n"
|
||||
"This is for use with raw transactions, NOT normal use.\n"
|
||||
"\nResult:\n"
|
||||
"\"address\" (string) The address\n"
|
||||
@@ -257,10 +257,10 @@ Value setaccount(const Array& params, bool fHelp)
|
||||
|
||||
if (fHelp || params.size() < 1 || params.size() > 2)
|
||||
throw runtime_error(
|
||||
"setaccount \"bitcoinaddress\" \"account\"\n"
|
||||
"setaccount \"zcashaddress\" \"account\"\n"
|
||||
"\nDEPRECATED. Sets the account associated with the given address.\n"
|
||||
"\nArguments:\n"
|
||||
"1. \"bitcoinaddress\" (string, required) The bitcoin address to be associated with an account.\n"
|
||||
"1. \"zcashaddress\" (string, required) The zcash address to be associated with an account.\n"
|
||||
"2. \"account\" (string, required) MUST be set to the empty string \"\" to represent the default account. Passing any other string will result in an error.\n"
|
||||
"\nExamples:\n"
|
||||
+ HelpExampleCli("setaccount", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XZ\" \"tabby\"")
|
||||
@@ -271,7 +271,7 @@ Value setaccount(const Array& params, bool fHelp)
|
||||
|
||||
CBitcoinAddress address(params[0].get_str());
|
||||
if (!address.IsValid())
|
||||
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid Bitcoin address");
|
||||
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid Zcash address");
|
||||
|
||||
string strAccount;
|
||||
if (params.size() > 1)
|
||||
@@ -303,10 +303,10 @@ Value getaccount(const Array& params, bool fHelp)
|
||||
|
||||
if (fHelp || params.size() != 1)
|
||||
throw runtime_error(
|
||||
"getaccount \"bitcoinaddress\"\n"
|
||||
"getaccount \"zcashaddress\"\n"
|
||||
"\nDEPRECATED. Returns the account associated with the given address.\n"
|
||||
"\nArguments:\n"
|
||||
"1. \"bitcoinaddress\" (string, required) The bitcoin address for account lookup.\n"
|
||||
"1. \"zcashaddress\" (string, required) The zcash address for account lookup.\n"
|
||||
"\nResult:\n"
|
||||
"\"accountname\" (string) the account address\n"
|
||||
"\nExamples:\n"
|
||||
@@ -318,7 +318,7 @@ Value getaccount(const Array& params, bool fHelp)
|
||||
|
||||
CBitcoinAddress address(params[0].get_str());
|
||||
if (!address.IsValid())
|
||||
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid Bitcoin address");
|
||||
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid Zcash address");
|
||||
|
||||
string strAccount;
|
||||
map<CTxDestination, CAddressBookData>::iterator mi = pwalletMain->mapAddressBook.find(address.Get());
|
||||
@@ -341,7 +341,7 @@ Value getaddressesbyaccount(const Array& params, bool fHelp)
|
||||
"1. \"account\" (string, required) MUST be set to the empty string \"\" to represent the default account. Passing any other string will result in an error.\n"
|
||||
"\nResult:\n"
|
||||
"[ (json array of string)\n"
|
||||
" \"bitcoinaddress\" (string) a bitcoin address associated with the given account\n"
|
||||
" \"zcashaddress\" (string) a zcash address associated with the given account\n"
|
||||
" ,...\n"
|
||||
"]\n"
|
||||
"\nExamples:\n"
|
||||
@@ -376,7 +376,7 @@ static void SendMoney(const CTxDestination &address, CAmount nValue, bool fSubtr
|
||||
if (nValue > curBalance)
|
||||
throw JSONRPCError(RPC_WALLET_INSUFFICIENT_FUNDS, "Insufficient funds");
|
||||
|
||||
// Parse Bitcoin address
|
||||
// Parse Zcash address
|
||||
CScript scriptPubKey = GetScriptForDestination(address);
|
||||
|
||||
// Create and send the transaction
|
||||
@@ -417,11 +417,11 @@ Value sendtoaddress(const Array& params, bool fHelp)
|
||||
|
||||
if (fHelp || params.size() < 2 || params.size() > 5)
|
||||
throw runtime_error(
|
||||
"sendtoaddress \"bitcoinaddress\" amount ( \"comment\" \"comment-to\" subtractfeefromamount )\n"
|
||||
"sendtoaddress \"zcashaddress\" amount ( \"comment\" \"comment-to\" subtractfeefromamount )\n"
|
||||
"\nSend an amount to a given address. The amount is a real and is rounded to the nearest 0.00000001\n"
|
||||
+ HelpRequiringPassphrase() +
|
||||
"\nArguments:\n"
|
||||
"1. \"bitcoinaddress\" (string, required) The bitcoin address to send to.\n"
|
||||
"1. \"zcashaddress\" (string, required) The zcash address to send to.\n"
|
||||
"2. \"amount\" (numeric, required) The amount in btc to send. eg 0.1\n"
|
||||
"3. \"comment\" (string, optional) A comment used to store what the transaction is for. \n"
|
||||
" This is not part of the transaction, just kept in your wallet.\n"
|
||||
@@ -429,7 +429,7 @@ Value sendtoaddress(const Array& params, bool fHelp)
|
||||
" to which you're sending the transaction. This is not part of the \n"
|
||||
" transaction, just kept in your wallet.\n"
|
||||
"5. subtractfeefromamount (boolean, optional, default=false) The fee will be deducted from the amount being sent.\n"
|
||||
" The recipient will receive less bitcoins than you enter in the amount field.\n"
|
||||
" The recipient will receive less zcash than you enter in the amount field.\n"
|
||||
"\nResult:\n"
|
||||
"\"transactionid\" (string) The transaction id.\n"
|
||||
"\nExamples:\n"
|
||||
@@ -443,7 +443,7 @@ Value sendtoaddress(const Array& params, bool fHelp)
|
||||
|
||||
CBitcoinAddress address(params[0].get_str());
|
||||
if (!address.IsValid())
|
||||
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid Bitcoin address");
|
||||
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid Zcash address");
|
||||
|
||||
// Amount
|
||||
CAmount nAmount = AmountFromValue(params[1]);
|
||||
@@ -519,7 +519,7 @@ Value listaddressgroupings(const Array& params, bool fHelp)
|
||||
"[\n"
|
||||
" [\n"
|
||||
" [\n"
|
||||
" \"bitcoinaddress\", (string) The bitcoin address\n"
|
||||
" \"zcashaddress\", (string) The zcash address\n"
|
||||
" amount, (numeric) The amount in btc\n"
|
||||
" \"account\" (string, optional) The account (DEPRECATED)\n"
|
||||
" ]\n"
|
||||
@@ -562,11 +562,11 @@ Value signmessage(const Array& params, bool fHelp)
|
||||
|
||||
if (fHelp || params.size() != 2)
|
||||
throw runtime_error(
|
||||
"signmessage \"bitcoinaddress\" \"message\"\n"
|
||||
"signmessage \"zcashaddress\" \"message\"\n"
|
||||
"\nSign a message with the private key of an address"
|
||||
+ HelpRequiringPassphrase() + "\n"
|
||||
"\nArguments:\n"
|
||||
"1. \"bitcoinaddress\" (string, required) The bitcoin address to use for the private key.\n"
|
||||
"1. \"zcashaddress\" (string, required) The zcash address to use for the private key.\n"
|
||||
"2. \"message\" (string, required) The message to create a signature of.\n"
|
||||
"\nResult:\n"
|
||||
"\"signature\" (string) The signature of the message encoded in base 64\n"
|
||||
@@ -618,10 +618,10 @@ Value getreceivedbyaddress(const Array& params, bool fHelp)
|
||||
|
||||
if (fHelp || params.size() < 1 || params.size() > 2)
|
||||
throw runtime_error(
|
||||
"getreceivedbyaddress \"bitcoinaddress\" ( minconf )\n"
|
||||
"\nReturns the total amount received by the given bitcoinaddress in transactions with at least minconf confirmations.\n"
|
||||
"getreceivedbyaddress \"zcashaddress\" ( minconf )\n"
|
||||
"\nReturns the total amount received by the given zcashaddress in transactions with at least minconf confirmations.\n"
|
||||
"\nArguments:\n"
|
||||
"1. \"bitcoinaddress\" (string, required) The bitcoin address for transactions.\n"
|
||||
"1. \"zcashaddress\" (string, required) The zcash address for transactions.\n"
|
||||
"2. minconf (numeric, optional, default=1) Only include transactions confirmed at least this many times.\n"
|
||||
"\nResult:\n"
|
||||
"amount (numeric) The total amount in btc received at this address.\n"
|
||||
@@ -641,7 +641,7 @@ Value getreceivedbyaddress(const Array& params, bool fHelp)
|
||||
// Bitcoin address
|
||||
CBitcoinAddress address = CBitcoinAddress(params[0].get_str());
|
||||
if (!address.IsValid())
|
||||
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid Bitcoin address");
|
||||
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid Zcash address");
|
||||
CScript scriptPubKey = GetScriptForDestination(address.Get());
|
||||
if (!IsMine(*pwalletMain,scriptPubKey))
|
||||
return (double)0.0;
|
||||
@@ -923,13 +923,13 @@ Value sendfrom(const Array& params, bool fHelp)
|
||||
|
||||
if (fHelp || params.size() < 3 || params.size() > 6)
|
||||
throw runtime_error(
|
||||
"sendfrom \"fromaccount\" \"tobitcoinaddress\" amount ( minconf \"comment\" \"comment-to\" )\n"
|
||||
"\nDEPRECATED (use sendtoaddress). Sent an amount from an account to a bitcoin address.\n"
|
||||
"sendfrom \"fromaccount\" \"tozcashaddress\" amount ( minconf \"comment\" \"comment-to\" )\n"
|
||||
"\nDEPRECATED (use sendtoaddress). Sent an amount from an account to a zcash address.\n"
|
||||
"The amount is a real and is rounded to the nearest 0.00000001."
|
||||
+ HelpRequiringPassphrase() + "\n"
|
||||
"\nArguments:\n"
|
||||
"1. \"fromaccount\" (string, required) MUST be set to the empty string \"\" to represent the default account. Passing any other string will result in an error.\n"
|
||||
"2. \"tobitcoinaddress\" (string, required) The bitcoin address to send funds to.\n"
|
||||
"2. \"tozcashaddress\" (string, required) The zcash address to send funds to.\n"
|
||||
"3. amount (numeric, required) The amount in btc. (transaction fee is added on top).\n"
|
||||
"4. minconf (numeric, optional, default=1) Only use funds with at least this many confirmations.\n"
|
||||
"5. \"comment\" (string, optional) A comment used to store what the transaction is for. \n"
|
||||
@@ -953,7 +953,7 @@ Value sendfrom(const Array& params, bool fHelp)
|
||||
string strAccount = AccountFromValue(params[0]);
|
||||
CBitcoinAddress address(params[1].get_str());
|
||||
if (!address.IsValid())
|
||||
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid Bitcoin address");
|
||||
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid Zcash address");
|
||||
CAmount nAmount = AmountFromValue(params[2]);
|
||||
int nMinDepth = 1;
|
||||
if (params.size() > 3)
|
||||
@@ -993,14 +993,14 @@ Value sendmany(const Array& params, bool fHelp)
|
||||
"1. \"fromaccount\" (string, required) MUST be set to the empty string \"\" to represent the default account. Passing any other string will result in an error.\n"
|
||||
"2. \"amounts\" (string, required) A json object with addresses and amounts\n"
|
||||
" {\n"
|
||||
" \"address\":amount (numeric) The bitcoin address is the key, the numeric amount in btc is the value\n"
|
||||
" \"address\":amount (numeric) The zcash address is the key, the numeric amount in btc is the value\n"
|
||||
" ,...\n"
|
||||
" }\n"
|
||||
"3. minconf (numeric, optional, default=1) Only use the balance confirmed at least this many times.\n"
|
||||
"4. \"comment\" (string, optional) A comment\n"
|
||||
"5. subtractfeefromamount (string, optional) A json array with addresses.\n"
|
||||
" The fee will be equally deducted from the amount of each selected address.\n"
|
||||
" Those recipients will receive less bitcoins than you enter in their corresponding amount field.\n"
|
||||
" Those recipients will receive less zcashs than you enter in their corresponding amount field.\n"
|
||||
" If no addresses are specified here, the sender pays the fee.\n"
|
||||
" [\n"
|
||||
" \"address\" (string) Subtract fee from this address\n"
|
||||
@@ -1045,7 +1045,7 @@ Value sendmany(const Array& params, bool fHelp)
|
||||
{
|
||||
CBitcoinAddress address(s.name_);
|
||||
if (!address.IsValid())
|
||||
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, string("Invalid Bitcoin address: ")+s.name_);
|
||||
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, string("Invalid Zcash address: ")+s.name_);
|
||||
|
||||
if (setAddress.count(address))
|
||||
throw JSONRPCError(RPC_INVALID_PARAMETER, string("Invalid parameter, duplicated address: ")+s.name_);
|
||||
@@ -1097,20 +1097,20 @@ Value addmultisigaddress(const Array& params, bool fHelp)
|
||||
{
|
||||
string msg = "addmultisigaddress nrequired [\"key\",...] ( \"account\" )\n"
|
||||
"\nAdd a nrequired-to-sign multisignature address to the wallet.\n"
|
||||
"Each key is a Bitcoin address or hex-encoded public key.\n"
|
||||
"Each key is a Zcash address or hex-encoded public key.\n"
|
||||
"If 'account' is specified (DEPRECATED), assign address to that account.\n"
|
||||
|
||||
"\nArguments:\n"
|
||||
"1. nrequired (numeric, required) The number of required signatures out of the n keys or addresses.\n"
|
||||
"2. \"keysobject\" (string, required) A json array of bitcoin addresses or hex-encoded public keys\n"
|
||||
"2. \"keysobject\" (string, required) A json array of zcash addresses or hex-encoded public keys\n"
|
||||
" [\n"
|
||||
" \"address\" (string) bitcoin address or hex-encoded public key\n"
|
||||
" \"address\" (string) zcash address or hex-encoded public key\n"
|
||||
" ...,\n"
|
||||
" ]\n"
|
||||
"3. \"account\" (string, optional) DEPRECATED. If provided, MUST be set to the empty string \"\" to represent the default account. Passing any other string will result in an error.\n"
|
||||
|
||||
"\nResult:\n"
|
||||
"\"bitcoinaddress\" (string) A bitcoin address associated with the keys.\n"
|
||||
"\"zcashaddress\" (string) A zcash address associated with the keys.\n"
|
||||
|
||||
"\nExamples:\n"
|
||||
"\nAdd a multisig address from 2 addresses\n"
|
||||
@@ -1455,7 +1455,7 @@ Value listtransactions(const Array& params, bool fHelp)
|
||||
" {\n"
|
||||
" \"account\":\"accountname\", (string) DEPRECATED. The account name associated with the transaction. \n"
|
||||
" It will be \"\" for the default account.\n"
|
||||
" \"address\":\"bitcoinaddress\", (string) The bitcoin address of the transaction. Not present for \n"
|
||||
" \"address\":\"zcashaddress\", (string) The zcash address of the transaction. Not present for \n"
|
||||
" move transactions (category = move).\n"
|
||||
" \"category\":\"send|receive|move\", (string) The transaction category. 'move' is a local (off blockchain)\n"
|
||||
" transaction between accounts, and not associated with an address,\n"
|
||||
@@ -1647,7 +1647,7 @@ Value listsinceblock(const Array& params, bool fHelp)
|
||||
"{\n"
|
||||
" \"transactions\": [\n"
|
||||
" \"account\":\"accountname\", (string) DEPRECATED. The account name associated with the transaction. Will be \"\" for the default account.\n"
|
||||
" \"address\":\"bitcoinaddress\", (string) The bitcoin address of the transaction. Not present for move transactions (category = move).\n"
|
||||
" \"address\":\"zcashaddress\", (string) The zcash address of the transaction. Not present for move transactions (category = move).\n"
|
||||
" \"category\":\"send|receive\", (string) The transaction category. 'send' has negative amounts, 'receive' has positive amounts.\n"
|
||||
" \"amount\": x.xxx, (numeric) The amount in btc. This is negative for the 'send' category, and for the 'move' category for moves \n"
|
||||
" outbound. It is positive for the 'receive' category, and for the 'move' category for inbound funds.\n"
|
||||
@@ -1746,7 +1746,7 @@ Value gettransaction(const Array& params, bool fHelp)
|
||||
" \"details\" : [\n"
|
||||
" {\n"
|
||||
" \"account\" : \"accountname\", (string) DEPRECATED. The account name involved in the transaction, can be \"\" for the default account.\n"
|
||||
" \"address\" : \"bitcoinaddress\", (string) The bitcoin address involved in the transaction\n"
|
||||
" \"address\" : \"zcashaddress\", (string) The zcash address involved in the transaction\n"
|
||||
" \"category\" : \"send|receive\", (string) The category, either 'send' or 'receive'\n"
|
||||
" \"amount\" : x.xxx (numeric) The amount in btc\n"
|
||||
" \"vout\" : n, (numeric) the vout value\n"
|
||||
@@ -1889,7 +1889,7 @@ Value walletpassphrase(const Array& params, bool fHelp)
|
||||
throw runtime_error(
|
||||
"walletpassphrase \"passphrase\" timeout\n"
|
||||
"\nStores the wallet decryption key in memory for 'timeout' seconds.\n"
|
||||
"This is needed prior to performing transactions related to private keys such as sending bitcoins\n"
|
||||
"This is needed prior to performing transactions related to private keys such as sending zcash\n"
|
||||
"\nArguments:\n"
|
||||
"1. \"passphrase\" (string, required) The wallet passphrase\n"
|
||||
"2. timeout (numeric, required) The time to keep the decryption key in seconds.\n"
|
||||
@@ -2031,10 +2031,18 @@ Value encryptwallet(const Array& params, bool fHelp)
|
||||
{
|
||||
if (!EnsureWalletIsAvailable(fHelp))
|
||||
return Value::null;
|
||||
|
||||
|
||||
auto fEnableWalletEncryption = GetBoolArg("-developerencryptwallet", false);
|
||||
|
||||
std::string strWalletEncryptionDisabledMsg = "";
|
||||
if (!fEnableWalletEncryption) {
|
||||
strWalletEncryptionDisabledMsg = "\nWARNING: Wallet encryption is DISABLED. This call always fails.\n";
|
||||
}
|
||||
|
||||
if (!pwalletMain->IsCrypted() && (fHelp || params.size() != 1))
|
||||
throw runtime_error(
|
||||
"encryptwallet \"passphrase\"\n"
|
||||
+ strWalletEncryptionDisabledMsg +
|
||||
"\nEncrypts the wallet with 'passphrase'. This is for first time encryption.\n"
|
||||
"After this, any calls that interact with private keys such as sending or signing \n"
|
||||
"will require the passphrase to be set prior the making these calls.\n"
|
||||
@@ -2046,10 +2054,10 @@ Value encryptwallet(const Array& params, bool fHelp)
|
||||
"\nExamples:\n"
|
||||
"\nEncrypt you wallet\n"
|
||||
+ HelpExampleCli("encryptwallet", "\"my pass phrase\"") +
|
||||
"\nNow set the passphrase to use the wallet, such as for signing or sending bitcoin\n"
|
||||
"\nNow set the passphrase to use the wallet, such as for signing or sending zcash\n"
|
||||
+ HelpExampleCli("walletpassphrase", "\"my pass phrase\"") +
|
||||
"\nNow we can so something like sign\n"
|
||||
+ HelpExampleCli("signmessage", "\"bitcoinaddress\" \"test message\"") +
|
||||
+ HelpExampleCli("signmessage", "\"zcashaddress\" \"test message\"") +
|
||||
"\nNow lock the wallet again by removing the passphrase\n"
|
||||
+ HelpExampleCli("walletlock", "") +
|
||||
"\nAs a json rpc call\n"
|
||||
@@ -2060,6 +2068,9 @@ Value encryptwallet(const Array& params, bool fHelp)
|
||||
|
||||
if (fHelp)
|
||||
return true;
|
||||
if (!fEnableWalletEncryption) {
|
||||
throw JSONRPCError(RPC_WALLET_ENCRYPTION_FAILED, "Error: wallet encryption is disabled.");
|
||||
}
|
||||
if (pwalletMain->IsCrypted())
|
||||
throw JSONRPCError(RPC_WALLET_WRONG_ENC_STATE, "Error: running with an encrypted wallet, but encryptwallet was called.");
|
||||
|
||||
@@ -2081,7 +2092,7 @@ Value encryptwallet(const Array& params, bool fHelp)
|
||||
// slack space in .dat files; that is bad if the old data is
|
||||
// unencrypted private keys. So:
|
||||
StartShutdown();
|
||||
return "wallet encrypted; Bitcoin server stopping, restart to run with encrypted wallet. The keypool has been flushed, you need to make a new backup.";
|
||||
return "wallet encrypted; Zcash server stopping, restart to run with encrypted wallet. The keypool has been flushed, you need to make a new backup.";
|
||||
}
|
||||
|
||||
Value lockunspent(const Array& params, bool fHelp)
|
||||
@@ -2094,7 +2105,7 @@ Value lockunspent(const Array& params, bool fHelp)
|
||||
"lockunspent unlock [{\"txid\":\"txid\",\"vout\":n},...]\n"
|
||||
"\nUpdates list of temporarily unspendable outputs.\n"
|
||||
"Temporarily lock (unlock=false) or unlock (unlock=true) specified transaction outputs.\n"
|
||||
"A locked transaction output will not be chosen by automatic coin selection, when spending bitcoins.\n"
|
||||
"A locked transaction output will not be chosen by automatic coin selection, when spending zcash.\n"
|
||||
"Locks are stored in memory only. Nodes start with zero locked outputs, and the locked output list\n"
|
||||
"is always cleared (by virtue of process exit) when a node stops or fails.\n"
|
||||
"Also see the listunspent call\n"
|
||||
@@ -2258,8 +2269,8 @@ Value getwalletinfo(const Array& params, bool fHelp)
|
||||
"\nResult:\n"
|
||||
"{\n"
|
||||
" \"walletversion\": xxxxx, (numeric) the wallet version\n"
|
||||
" \"balance\": xxxxxxx, (numeric) the total confirmed bitcoin balance of the wallet\n"
|
||||
" \"unconfirmed_balance\": xxx, (numeric) the total unconfirmed bitcoin balance of the wallet\n"
|
||||
" \"balance\": xxxxxxx, (numeric) the total confirmed zcash balance of the wallet\n"
|
||||
" \"unconfirmed_balance\": xxx, (numeric) the total unconfirmed zcash balance of the wallet\n"
|
||||
" \"immature_balance\": xxxxxx, (numeric) the total immature balance of the wallet\n"
|
||||
" \"txcount\": xxxxxxx, (numeric) the total number of transactions in the wallet\n"
|
||||
" \"keypoololdest\": xxxxxx, (numeric) the timestamp (seconds since GMT epoch) of the oldest pre-generated key in the key pool\n"
|
||||
@@ -2329,9 +2340,9 @@ Value listunspent(const Array& params, bool fHelp)
|
||||
"\nArguments:\n"
|
||||
"1. minconf (numeric, optional, default=1) The minimum confirmations to filter\n"
|
||||
"2. maxconf (numeric, optional, default=9999999) The maximum confirmations to filter\n"
|
||||
"3. \"addresses\" (string) A json array of bitcoin addresses to filter\n"
|
||||
"3. \"addresses\" (string) A json array of zcash addresses to filter\n"
|
||||
" [\n"
|
||||
" \"address\" (string) bitcoin address\n"
|
||||
" \"address\" (string) zcash address\n"
|
||||
" ,...\n"
|
||||
" ]\n"
|
||||
"\nResult\n"
|
||||
@@ -2339,7 +2350,7 @@ Value listunspent(const Array& params, bool fHelp)
|
||||
" {\n"
|
||||
" \"txid\" : \"txid\", (string) the transaction id \n"
|
||||
" \"vout\" : n, (numeric) the vout value\n"
|
||||
" \"address\" : \"address\", (string) the bitcoin address\n"
|
||||
" \"address\" : \"address\", (string) the zcash address\n"
|
||||
" \"account\" : \"account\", (string) DEPRECATED. The associated account, or \"\" for the default account\n"
|
||||
" \"scriptPubKey\" : \"key\", (string) the script key\n"
|
||||
" \"amount\" : x.xxx, (numeric) the transaction amount in btc\n"
|
||||
@@ -2370,7 +2381,7 @@ Value listunspent(const Array& params, bool fHelp)
|
||||
BOOST_FOREACH(Value& input, inputs) {
|
||||
CBitcoinAddress address(input.get_str());
|
||||
if (!address.IsValid())
|
||||
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, string("Invalid Bitcoin address: ")+input.get_str());
|
||||
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, string("Invalid Zcash address: ")+input.get_str());
|
||||
if (setAddress.count(address))
|
||||
throw JSONRPCError(RPC_INVALID_PARAMETER, string("Invalid parameter, duplicated address: ")+input.get_str());
|
||||
setAddress.insert(address);
|
||||
@@ -3230,6 +3241,7 @@ Value z_sendmany(const Array& params, bool fHelp)
|
||||
"z_sendmany \"fromaddress\" [{\"address\":... ,\"amount\":...},...] ( minconf )\n"
|
||||
"\nSend multiple times. Amounts are double-precision floating point numbers."
|
||||
"\nChange from a taddr flows to a new taddr address, while change from zaddr returns to itself."
|
||||
"\nWhen sending coinbase UTXOs to a zaddr, change is not alllowed. The entire value of the UTXO(s) must be consumed."
|
||||
+ HelpRequiringPassphrase() + "\n"
|
||||
"\nArguments:\n"
|
||||
"1. \"fromaddress\" (string, required) The taddr or zaddr to send the funds from.\n"
|
||||
@@ -3287,8 +3299,6 @@ Value z_sendmany(const Array& params, bool fHelp)
|
||||
throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, expected object");
|
||||
const Object& o = output.get_obj();
|
||||
|
||||
RPCTypeCheck(o, boost::assign::map_list_of("address", str_type)("amount", real_type));
|
||||
|
||||
// sanity check, report error if unknown key-value pairs
|
||||
for (const Pair& p : o) {
|
||||
std::string s = p.name_;
|
||||
|
||||
@@ -699,7 +699,23 @@ void CWallet::IncrementNoteWitnesses(const CBlockIndex* pindex,
|
||||
JSOutPoint jsoutpt {hash, i, j};
|
||||
if (mapWallet[hash].mapNoteData.count(jsoutpt)) {
|
||||
CNoteData* nd = &(mapWallet[hash].mapNoteData[jsoutpt]);
|
||||
assert(nd->witnesses.size() == 0);
|
||||
if (nd->witnesses.size() > 0) {
|
||||
// We think this can happen because we write out the
|
||||
// witness cache state after every block increment or
|
||||
// decrement, but the block index itself is written in
|
||||
// batches. So if the node crashes in between these two
|
||||
// operations, it is possible for IncrementNoteWitnesses
|
||||
// to be called again on previously-cached blocks. This
|
||||
// doesn't affect existing cached notes because of the
|
||||
// CNoteData::witnessHeight checks. See #1378 for details.
|
||||
LogPrintf("Inconsistent witness cache state found for %s\n- Cache size: %d\n- Top (height %d): %s\n- New (height %d): %s\n",
|
||||
jsoutpt.ToString(), nd->witnesses.size(),
|
||||
nd->witnessHeight,
|
||||
nd->witnesses.front().root().GetHex(),
|
||||
pindex->nHeight,
|
||||
tree.witness().root().GetHex());
|
||||
nd->witnesses.clear();
|
||||
}
|
||||
nd->witnesses.push_front(tree.witness());
|
||||
// Set height to one less than pindex so it gets incremented
|
||||
nd->witnessHeight = pindex->nHeight - 1;
|
||||
|
||||
@@ -885,7 +885,7 @@ DBErrors CWalletDB::ZapWalletTx(CWallet* pwallet, vector<CWalletTx>& vWtx)
|
||||
void ThreadFlushWalletDB(const string& strFile)
|
||||
{
|
||||
// Make this thread recognisable as the wallet flushing thread
|
||||
RenameThread("bitcoin-wallet");
|
||||
RenameThread("zcash-wallet");
|
||||
|
||||
static bool fOneThread;
|
||||
if (fOneThread)
|
||||
|
||||
Reference in New Issue
Block a user