uni3
This commit is contained in:
@@ -63,15 +63,15 @@ AsyncRPCOperation_sendmany::AsyncRPCOperation_sendmany(
|
||||
if (minDepth < 0) {
|
||||
throw JSONRPCError(RPC_INVALID_PARAMETER, "Minconf cannot be negative");
|
||||
}
|
||||
|
||||
|
||||
if (fromAddress.size() == 0) {
|
||||
throw JSONRPCError(RPC_INVALID_PARAMETER, "From address parameter missing");
|
||||
}
|
||||
|
||||
|
||||
if (tOutputs.size() == 0 && zOutputs.size() == 0) {
|
||||
throw JSONRPCError(RPC_INVALID_PARAMETER, "No recipients");
|
||||
}
|
||||
|
||||
|
||||
fromtaddr_ = CBitcoinAddress(fromAddress);
|
||||
isfromtaddr_ = fromtaddr_.IsValid();
|
||||
isfromzaddr_ = false;
|
||||
@@ -86,7 +86,7 @@ AsyncRPCOperation_sendmany::AsyncRPCOperation_sendmany(
|
||||
if (!pwalletMain->GetSpendingKey(addr, key)) {
|
||||
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid from address, no spending key found for zaddr");
|
||||
}
|
||||
|
||||
|
||||
isfromzaddr_ = true;
|
||||
frompaymentaddress_ = addr;
|
||||
spendingkey_ = key;
|
||||
@@ -199,13 +199,13 @@ bool AsyncRPCOperation_sendmany::main_impl() {
|
||||
throw JSONRPCError(RPC_WALLET_INSUFFICIENT_FUNDS, "Could not find any non-coinbase UTXOs to spend.");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (isfromzaddr_ && !find_unspent_notes()) {
|
||||
throw JSONRPCError(RPC_WALLET_INSUFFICIENT_FUNDS, "Insufficient funds, no unspent notes found for zaddr from address.");
|
||||
}
|
||||
|
||||
|
||||
CAmount t_inputs_total = 0;
|
||||
for (SendManyInputUTXO & t : t_inputs_) {
|
||||
t_inputs_total += std::get<2>(t);
|
||||
@@ -237,7 +237,7 @@ bool AsyncRPCOperation_sendmany::main_impl() {
|
||||
strprintf("Insufficient transparent funds, have %s, need %s",
|
||||
FormatMoney(t_inputs_total), FormatMoney(targetAmount)));
|
||||
}
|
||||
|
||||
|
||||
if (isfromzaddr_ && (z_inputs_total < targetAmount)) {
|
||||
throw JSONRPCError(RPC_WALLET_INSUFFICIENT_FUNDS,
|
||||
strprintf("Insufficient protected funds, have %s, need %s",
|
||||
@@ -306,18 +306,18 @@ bool AsyncRPCOperation_sendmany::main_impl() {
|
||||
|
||||
/**
|
||||
* SCENARIO #1
|
||||
*
|
||||
*
|
||||
* taddr -> taddrs
|
||||
*
|
||||
*
|
||||
* There are no zaddrs or joinsplits involved.
|
||||
*/
|
||||
if (isPureTaddrOnlyTx) {
|
||||
add_taddr_outputs_to_tx();
|
||||
|
||||
|
||||
CAmount funds = selectedUTXOAmount;
|
||||
CAmount fundsSpent = t_outputs_total + minersFee;
|
||||
CAmount change = funds - fundsSpent;
|
||||
|
||||
|
||||
if (change > 0) {
|
||||
add_taddr_change_output_to_tx(0,change);
|
||||
|
||||
@@ -326,7 +326,7 @@ bool AsyncRPCOperation_sendmany::main_impl() {
|
||||
FormatMoney(change)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
UniValue obj(UniValue::VOBJ);
|
||||
obj.push_back(Pair("rawtxn", EncodeHexTx(tx_)));
|
||||
sign_send_raw_transaction(obj);
|
||||
@@ -336,7 +336,7 @@ bool AsyncRPCOperation_sendmany::main_impl() {
|
||||
* END SCENARIO #1
|
||||
*/
|
||||
|
||||
|
||||
|
||||
// Prepare raw transaction to handle JoinSplits
|
||||
CMutableTransaction mtx(tx_);
|
||||
mtx.nVersion = 2;
|
||||
@@ -373,10 +373,10 @@ bool AsyncRPCOperation_sendmany::main_impl() {
|
||||
|
||||
/**
|
||||
* SCENARIO #2
|
||||
*
|
||||
*
|
||||
* taddr -> taddrs
|
||||
* -> zaddrs
|
||||
*
|
||||
*
|
||||
* Note: Consensus rule states that coinbase utxos can only be sent to a zaddr.
|
||||
* 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
|
||||
@@ -384,11 +384,11 @@ bool AsyncRPCOperation_sendmany::main_impl() {
|
||||
*/
|
||||
if (isfromtaddr_) {
|
||||
add_taddr_outputs_to_tx();
|
||||
|
||||
|
||||
CAmount funds = selectedUTXOAmount;
|
||||
CAmount fundsSpent = t_outputs_total + minersFee + z_outputs_total;
|
||||
CAmount change = funds - fundsSpent;
|
||||
|
||||
|
||||
if (change > 0) {
|
||||
if (selectedUTXOCoinbase) {
|
||||
assert(isSingleZaddrOutput);
|
||||
@@ -425,7 +425,7 @@ bool AsyncRPCOperation_sendmany::main_impl() {
|
||||
jso.memo = get_memo_from_hex_string(hexMemo);
|
||||
}
|
||||
info.vjsout.push_back(jso);
|
||||
|
||||
|
||||
// Funds are removed from the value pool and enter the private pool
|
||||
info.vpub_old += value;
|
||||
}
|
||||
@@ -436,21 +436,21 @@ bool AsyncRPCOperation_sendmany::main_impl() {
|
||||
}
|
||||
/**
|
||||
* END SCENARIO #2
|
||||
*/
|
||||
|
||||
|
||||
|
||||
*/
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* SCENARIO #3
|
||||
*
|
||||
*
|
||||
* zaddr -> taddrs
|
||||
* -> zaddrs
|
||||
*
|
||||
*
|
||||
* Processing order:
|
||||
* Part 1: taddrs and miners fee
|
||||
* Part 2: zaddrs
|
||||
* Part 2: zaddrs
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* SCENARIO #3
|
||||
* Part 1: Add to the transparent value pool.
|
||||
@@ -498,7 +498,7 @@ bool AsyncRPCOperation_sendmany::main_impl() {
|
||||
wtxDepth
|
||||
);
|
||||
|
||||
|
||||
|
||||
// Put value back into the value pool
|
||||
if (noteFunds >= taddrTargetAmount) {
|
||||
jsChange = noteFunds - taddrTargetAmount;
|
||||
@@ -516,7 +516,7 @@ bool AsyncRPCOperation_sendmany::main_impl() {
|
||||
if (jsChange > 0) {
|
||||
info.vjsout.push_back(JSOutput());
|
||||
info.vjsout.push_back(JSOutput(frompaymentaddress_, jsChange));
|
||||
|
||||
|
||||
LogPrint("zrpcunsafe", "%s: generating note for change (amount=%s)\n",
|
||||
getId(),
|
||||
FormatMoney(jsChange)
|
||||
@@ -535,13 +535,13 @@ bool AsyncRPCOperation_sendmany::main_impl() {
|
||||
/**
|
||||
* SCENARIO #3
|
||||
* Part 2: Send to zaddrs by chaining JoinSplits together and immediately consuming any change
|
||||
*/
|
||||
*/
|
||||
if (z_outputs_total>0) {
|
||||
|
||||
// Keep track of treestate within this transaction
|
||||
// Keep track of treestate within this transaction
|
||||
boost::unordered_map<uint256, ZCIncrementalMerkleTree, CCoinsKeyHasher> intermediates;
|
||||
std::vector<uint256> previousCommitments;
|
||||
|
||||
|
||||
while (zOutputsDeque.size() > 0) {
|
||||
AsyncJoinSplitInfo info;
|
||||
info.vpub_old = 0;
|
||||
@@ -557,20 +557,20 @@ bool AsyncRPCOperation_sendmany::main_impl() {
|
||||
if (tx_.vjoinsplit.size() > 0) {
|
||||
prevJoinSplit = tx_.vjoinsplit.back();
|
||||
}
|
||||
|
||||
|
||||
// If there is no change, the chain has terminated so we can reset the tracked treestate.
|
||||
if (jsChange==0 && tx_.vjoinsplit.size() > 0) {
|
||||
intermediates.clear();
|
||||
previousCommitments.clear();
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Consume change as the first input of the JoinSplit.
|
||||
//
|
||||
if (jsChange > 0) {
|
||||
LOCK2(cs_main, pwalletMain->cs_wallet);
|
||||
|
||||
// Update tree state with previous joinsplit
|
||||
// Update tree state with previous joinsplit
|
||||
ZCIncrementalMerkleTree tree;
|
||||
auto it = intermediates.find(prevJoinSplit.anchor);
|
||||
if (it != intermediates.end()) {
|
||||
@@ -578,7 +578,7 @@ bool AsyncRPCOperation_sendmany::main_impl() {
|
||||
} else if (!pcoinsTip->GetAnchorAt(prevJoinSplit.anchor, tree)) {
|
||||
throw JSONRPCError(RPC_WALLET_ERROR, "Could not find previous JoinSplit anchor");
|
||||
}
|
||||
|
||||
|
||||
assert(changeOutputIndex != -1);
|
||||
boost::optional<ZCIncrementalWitness> changeWitness;
|
||||
int n = 0;
|
||||
@@ -610,9 +610,9 @@ bool AsyncRPCOperation_sendmany::main_impl() {
|
||||
|
||||
Note note = plaintext.note(frompaymentaddress_);
|
||||
info.notes.push_back(note);
|
||||
|
||||
|
||||
jsInputValue += plaintext.value;
|
||||
|
||||
|
||||
LogPrint("zrpcunsafe", "%s: spending change (amount=%s)\n",
|
||||
getId(),
|
||||
FormatMoney(plaintext.value)
|
||||
@@ -623,7 +623,7 @@ bool AsyncRPCOperation_sendmany::main_impl() {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
//
|
||||
// Consume spendable non-change notes
|
||||
//
|
||||
@@ -649,9 +649,9 @@ bool AsyncRPCOperation_sendmany::main_impl() {
|
||||
|
||||
vOutPoints.push_back(jso);
|
||||
vInputNotes.push_back(note);
|
||||
|
||||
|
||||
jsInputValue += noteFunds;
|
||||
|
||||
|
||||
int wtxHeight = -1;
|
||||
int wtxDepth = -1;
|
||||
{
|
||||
@@ -670,14 +670,14 @@ bool AsyncRPCOperation_sendmany::main_impl() {
|
||||
wtxDepth
|
||||
);
|
||||
}
|
||||
|
||||
// Add history of previous commitments to witness
|
||||
|
||||
// Add history of previous commitments to witness
|
||||
if (vInputNotes.size() > 0) {
|
||||
|
||||
if (vInputWitnesses.size()==0) {
|
||||
throw JSONRPCError(RPC_WALLET_ERROR, "Could not find witness for note commitment");
|
||||
}
|
||||
|
||||
|
||||
for (auto & optionalWitness : vInputWitnesses) {
|
||||
if (!optionalWitness) {
|
||||
throw JSONRPCError(RPC_WALLET_ERROR, "Witness for note commitment is null");
|
||||
@@ -695,18 +695,18 @@ bool AsyncRPCOperation_sendmany::main_impl() {
|
||||
}
|
||||
|
||||
// The jsAnchor is null if this JoinSplit is at the start of a new chain
|
||||
if (jsAnchor.IsNull()) {
|
||||
jsAnchor = inputAnchor;
|
||||
if (jsAnchor.IsNull()) {
|
||||
jsAnchor = inputAnchor;
|
||||
}
|
||||
|
||||
// Add spendable notes as inputs
|
||||
std::copy(vInputNotes.begin(), vInputNotes.end(), std::back_inserter(info.notes));
|
||||
}
|
||||
|
||||
|
||||
|
||||
//
|
||||
// Find recipient to transfer funds to
|
||||
//
|
||||
//
|
||||
SendManyRecipient smr = zOutputsDeque.front();
|
||||
std::string address = std::get<0>(smr);
|
||||
CAmount value = std::get<1>(smr);
|
||||
@@ -722,7 +722,7 @@ bool AsyncRPCOperation_sendmany::main_impl() {
|
||||
}
|
||||
outAmount += minersFee;
|
||||
}
|
||||
|
||||
|
||||
if (jsInputValue > outAmount) {
|
||||
jsChange = jsInputValue - outAmount;
|
||||
} else if (outAmount > jsInputValue) {
|
||||
@@ -737,12 +737,12 @@ bool AsyncRPCOperation_sendmany::main_impl() {
|
||||
value -= minersFee;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (!minersFeeProcessed) {
|
||||
minersFeeProcessed = true;
|
||||
info.vpub_new += minersFee; // funds flowing back to public pool
|
||||
}
|
||||
|
||||
|
||||
// create output for recipient
|
||||
PaymentAddress pa = CZCPaymentAddress(address).Get();
|
||||
JSOutput jso = JSOutput(pa, value);
|
||||
@@ -750,7 +750,7 @@ bool AsyncRPCOperation_sendmany::main_impl() {
|
||||
jso.memo = get_memo_from_hex_string(hexMemo);
|
||||
}
|
||||
info.vjsout.push_back(jso);
|
||||
|
||||
|
||||
// create output for any change
|
||||
if (jsChange>0) {
|
||||
info.vjsout.push_back(JSOutput(frompaymentaddress_, jsChange));
|
||||
@@ -779,7 +779,7 @@ bool AsyncRPCOperation_sendmany::main_impl() {
|
||||
* Raw transaction as hex string should be in object field "rawtxn"
|
||||
*/
|
||||
void AsyncRPCOperation_sendmany::sign_send_raw_transaction(UniValue obj)
|
||||
{
|
||||
{
|
||||
// Sign the raw transaction
|
||||
UniValue rawtxnValue = find_value(obj, "rawtxn");
|
||||
if (rawtxnValue.isNull()) {
|
||||
@@ -870,7 +870,7 @@ bool AsyncRPCOperation_sendmany::find_utxos(bool fAcceptCoinbase=false) {
|
||||
if (isCoinbase && fAcceptCoinbase==false) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
CAmount nValue = out.tx->vout[out.i].nValue;
|
||||
SendManyInputUTXO utxo(out.tx->GetHash(), out.i, nValue, isCoinbase);
|
||||
t_inputs_.push_back(utxo);
|
||||
@@ -904,7 +904,7 @@ bool AsyncRPCOperation_sendmany::find_unspent_notes() {
|
||||
HexStr(data).substr(0, 10)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
if (z_inputs_.size() == 0) {
|
||||
return false;
|
||||
}
|
||||
@@ -986,13 +986,13 @@ UniValue AsyncRPCOperation_sendmany::perform_joinsplit(
|
||||
{info.vjsin[0], info.vjsin[1]};
|
||||
boost::array<libzcash::JSOutput, ZC_NUM_JS_OUTPUTS> outputs
|
||||
{info.vjsout[0], info.vjsout[1]};
|
||||
#ifdef __APPLE__
|
||||
#ifdef __LP64__
|
||||
boost::array<uint64_t, ZC_NUM_JS_INPUTS> inputMap;
|
||||
boost::array<uint64_t, ZC_NUM_JS_OUTPUTS> outputMap;
|
||||
#else
|
||||
#else
|
||||
boost::array<size_t, ZC_NUM_JS_INPUTS> inputMap;
|
||||
boost::array<size_t, ZC_NUM_JS_OUTPUTS> outputMap;
|
||||
#endif
|
||||
#endif
|
||||
JSDescription jsdesc = JSDescription::Randomized(
|
||||
*pzcashParams,
|
||||
joinSplitPubKey_,
|
||||
@@ -1132,7 +1132,7 @@ void AsyncRPCOperation_sendmany::add_taddr_change_output_to_tx(CBitcoinAddress *
|
||||
|
||||
boost::array<unsigned char, ZC_MEMO_SIZE> AsyncRPCOperation_sendmany::get_memo_from_hex_string(std::string s) {
|
||||
boost::array<unsigned char, ZC_MEMO_SIZE> memo = {{0x00}};
|
||||
|
||||
|
||||
std::vector<unsigned char> rawMemo = ParseHex(s.c_str());
|
||||
|
||||
// If ParseHex comes across a non-hex char, it will stop but still return results so far.
|
||||
@@ -1140,11 +1140,11 @@ boost::array<unsigned char, ZC_MEMO_SIZE> AsyncRPCOperation_sendmany::get_memo_f
|
||||
if (slen % 2 !=0 || (slen>0 && rawMemo.size()!=slen/2)) {
|
||||
throw JSONRPCError(RPC_INVALID_PARAMETER, "Memo must be in hexadecimal format");
|
||||
}
|
||||
|
||||
|
||||
if (rawMemo.size() > ZC_MEMO_SIZE) {
|
||||
throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("Memo size of %d is too big, maximum allowed is %d", rawMemo.size(), ZC_MEMO_SIZE));
|
||||
}
|
||||
|
||||
|
||||
// copy vector into boost array
|
||||
int lenMemo = rawMemo.size();
|
||||
for (int i = 0; i < ZC_MEMO_SIZE && i < lenMemo; i++) {
|
||||
@@ -1167,4 +1167,3 @@ UniValue AsyncRPCOperation_sendmany::getStatus() const {
|
||||
obj.push_back(Pair("params", contextinfo_ ));
|
||||
return obj;
|
||||
}
|
||||
|
||||
|
||||
110
src/wallet/gtest/test_transaction.cpp
Executable file
110
src/wallet/gtest/test_transaction.cpp
Executable file
@@ -0,0 +1,110 @@
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include "primitives/transaction.h"
|
||||
#include "zcash/Note.hpp"
|
||||
#include "zcash/Address.hpp"
|
||||
|
||||
extern ZCJoinSplit* params;
|
||||
extern int GenZero(int n);
|
||||
extern int GenMax(int n);
|
||||
|
||||
TEST(Transaction, JSDescriptionRandomized) {
|
||||
// construct a merkle tree
|
||||
ZCIncrementalMerkleTree merkleTree;
|
||||
|
||||
libzcash::SpendingKey k = libzcash::SpendingKey::random();
|
||||
libzcash::PaymentAddress addr = k.address();
|
||||
|
||||
libzcash::Note note(addr.a_pk, 100, uint256(), uint256());
|
||||
|
||||
// commitment from coin
|
||||
uint256 commitment = note.cm();
|
||||
|
||||
// insert commitment into the merkle tree
|
||||
merkleTree.append(commitment);
|
||||
|
||||
// compute the merkle root we will be working with
|
||||
uint256 rt = merkleTree.root();
|
||||
|
||||
auto witness = merkleTree.witness();
|
||||
|
||||
// create JSDescription
|
||||
uint256 pubKeyHash;
|
||||
boost::array<libzcash::JSInput, ZC_NUM_JS_INPUTS> inputs = {
|
||||
libzcash::JSInput(witness, note, k),
|
||||
libzcash::JSInput() // dummy input of zero value
|
||||
};
|
||||
boost::array<libzcash::JSOutput, ZC_NUM_JS_OUTPUTS> outputs = {
|
||||
libzcash::JSOutput(addr, 50),
|
||||
libzcash::JSOutput(addr, 50)
|
||||
};
|
||||
#ifdef __LP64__ // required for building on MacOS
|
||||
boost::array<uint64_t, ZC_NUM_JS_INPUTS> inputMap;
|
||||
boost::array<uint64_t, ZC_NUM_JS_OUTPUTS> outputMap;
|
||||
#else
|
||||
boost::array<size_t, ZC_NUM_JS_INPUTS> inputMap;
|
||||
boost::array<size_t, ZC_NUM_JS_OUTPUTS> outputMap;
|
||||
#endif
|
||||
|
||||
{
|
||||
auto jsdesc = JSDescription::Randomized(
|
||||
*params, pubKeyHash, rt,
|
||||
inputs, outputs,
|
||||
inputMap, outputMap,
|
||||
0, 0, false);
|
||||
|
||||
#ifdef __LP64__ // required for building on MacOS
|
||||
std::set<uint64_t> inputSet(inputMap.begin(), inputMap.end());
|
||||
std::set<uint64_t> expectedInputSet {0, 1};
|
||||
#else
|
||||
std::set<size_t> inputSet(inputMap.begin(), inputMap.end());
|
||||
std::set<size_t> expectedInputSet {0, 1};
|
||||
#endif
|
||||
EXPECT_EQ(expectedInputSet, inputSet);
|
||||
|
||||
#ifdef __LP64__ // required for building on MacOS
|
||||
std::set<uint64_t> outputSet(outputMap.begin(), outputMap.end());
|
||||
std::set<uint64_t> expectedOutputSet {0, 1};
|
||||
#else
|
||||
std::set<size_t> outputSet(outputMap.begin(), outputMap.end());
|
||||
std::set<size_t> expectedOutputSet {0, 1};
|
||||
#endif
|
||||
EXPECT_EQ(expectedOutputSet, outputSet);
|
||||
}
|
||||
|
||||
{
|
||||
auto jsdesc = JSDescription::Randomized(
|
||||
*params, pubKeyHash, rt,
|
||||
inputs, outputs,
|
||||
inputMap, outputMap,
|
||||
0, 0, false, GenZero);
|
||||
|
||||
#ifdef __LP64__ // required for building on MacOS
|
||||
boost::array<uint64_t, ZC_NUM_JS_INPUTS> expectedInputMap {1, 0};
|
||||
boost::array<uint64_t, ZC_NUM_JS_OUTPUTS> expectedOutputMap {1, 0};
|
||||
#else
|
||||
boost::array<size_t, ZC_NUM_JS_INPUTS> expectedInputMap {1, 0};
|
||||
boost::array<size_t, ZC_NUM_JS_OUTPUTS> expectedOutputMap {1, 0};
|
||||
#endif
|
||||
EXPECT_EQ(expectedInputMap, inputMap);
|
||||
EXPECT_EQ(expectedOutputMap, outputMap);
|
||||
}
|
||||
|
||||
{
|
||||
auto jsdesc = JSDescription::Randomized(
|
||||
*params, pubKeyHash, rt,
|
||||
inputs, outputs,
|
||||
inputMap, outputMap,
|
||||
0, 0, false, GenMax);
|
||||
|
||||
#ifdef __LP64__ // required for building on MacOS
|
||||
boost::array<uint64_t, ZC_NUM_JS_INPUTS> expectedInputMap {0, 1};
|
||||
boost::array<uint64_t, ZC_NUM_JS_OUTPUTS> expectedOutputMap {0, 1};
|
||||
#else
|
||||
boost::array<size_t, ZC_NUM_JS_INPUTS> expectedInputMap {0, 1};
|
||||
boost::array<size_t, ZC_NUM_JS_OUTPUTS> expectedOutputMap {0, 1};
|
||||
#endif
|
||||
EXPECT_EQ(expectedInputMap, inputMap);
|
||||
EXPECT_EQ(expectedOutputMap, outputMap);
|
||||
}
|
||||
}
|
||||
@@ -114,7 +114,7 @@ UniValue getnewaddress(const UniValue& params, bool fHelp)
|
||||
{
|
||||
if (!EnsureWalletIsAvailable(fHelp))
|
||||
return NullUniValue;
|
||||
|
||||
|
||||
if (fHelp || params.size() > 1)
|
||||
throw runtime_error(
|
||||
"getnewaddress ( \"account\" )\n"
|
||||
@@ -191,7 +191,7 @@ UniValue getaccountaddress(const UniValue& params, bool fHelp)
|
||||
{
|
||||
if (!EnsureWalletIsAvailable(fHelp))
|
||||
return NullUniValue;
|
||||
|
||||
|
||||
if (fHelp || params.size() != 1)
|
||||
throw runtime_error(
|
||||
"getaccountaddress \"account\"\n"
|
||||
@@ -223,7 +223,7 @@ UniValue getrawchangeaddress(const UniValue& params, bool fHelp)
|
||||
{
|
||||
if (!EnsureWalletIsAvailable(fHelp))
|
||||
return NullUniValue;
|
||||
|
||||
|
||||
if (fHelp || params.size() > 1)
|
||||
throw runtime_error(
|
||||
"getrawchangeaddress\n"
|
||||
@@ -258,7 +258,7 @@ UniValue setaccount(const UniValue& params, bool fHelp)
|
||||
{
|
||||
if (!EnsureWalletIsAvailable(fHelp))
|
||||
return NullUniValue;
|
||||
|
||||
|
||||
if (fHelp || params.size() < 1 || params.size() > 2)
|
||||
throw runtime_error(
|
||||
"setaccount \"zcashaddress\" \"account\"\n"
|
||||
@@ -304,7 +304,7 @@ UniValue getaccount(const UniValue& params, bool fHelp)
|
||||
{
|
||||
if (!EnsureWalletIsAvailable(fHelp))
|
||||
return NullUniValue;
|
||||
|
||||
|
||||
if (fHelp || params.size() != 1)
|
||||
throw runtime_error(
|
||||
"getaccount \"zcashaddress\"\n"
|
||||
@@ -336,7 +336,7 @@ UniValue getaddressesbyaccount(const UniValue& params, bool fHelp)
|
||||
{
|
||||
if (!EnsureWalletIsAvailable(fHelp))
|
||||
return NullUniValue;
|
||||
|
||||
|
||||
if (fHelp || params.size() != 1)
|
||||
throw runtime_error(
|
||||
"getaddressesbyaccount \"account\"\n"
|
||||
@@ -418,7 +418,7 @@ UniValue sendtoaddress(const UniValue& params, bool fHelp)
|
||||
{
|
||||
if (!EnsureWalletIsAvailable(fHelp))
|
||||
return NullUniValue;
|
||||
|
||||
|
||||
if (fHelp || params.size() < 2 || params.size() > 5)
|
||||
throw runtime_error(
|
||||
"sendtoaddress \"zcashaddress\" amount ( \"comment\" \"comment-to\" subtractfeefromamount )\n"
|
||||
@@ -689,7 +689,7 @@ UniValue listaddressgroupings(const UniValue& params, bool fHelp)
|
||||
{
|
||||
if (!EnsureWalletIsAvailable(fHelp))
|
||||
return NullUniValue;
|
||||
|
||||
|
||||
if (fHelp)
|
||||
throw runtime_error(
|
||||
"listaddressgroupings\n"
|
||||
@@ -740,7 +740,7 @@ UniValue signmessage(const UniValue& params, bool fHelp)
|
||||
{
|
||||
if (!EnsureWalletIsAvailable(fHelp))
|
||||
return NullUniValue;
|
||||
|
||||
|
||||
if (fHelp || params.size() != 2)
|
||||
throw runtime_error(
|
||||
"signmessage \"zcashaddress\" \"message\"\n"
|
||||
@@ -796,7 +796,7 @@ UniValue getreceivedbyaddress(const UniValue& params, bool fHelp)
|
||||
{
|
||||
if (!EnsureWalletIsAvailable(fHelp))
|
||||
return NullUniValue;
|
||||
|
||||
|
||||
if (fHelp || params.size() < 1 || params.size() > 2)
|
||||
throw runtime_error(
|
||||
"getreceivedbyaddress \"zcashaddress\" ( minconf )\n"
|
||||
@@ -854,7 +854,7 @@ UniValue getreceivedbyaccount(const UniValue& params, bool fHelp)
|
||||
{
|
||||
if (!EnsureWalletIsAvailable(fHelp))
|
||||
return NullUniValue;
|
||||
|
||||
|
||||
if (fHelp || params.size() < 1 || params.size() > 2)
|
||||
throw runtime_error(
|
||||
"getreceivedbyaccount \"account\" ( minconf )\n"
|
||||
@@ -943,7 +943,7 @@ UniValue getbalance(const UniValue& params, bool fHelp)
|
||||
{
|
||||
if (!EnsureWalletIsAvailable(fHelp))
|
||||
return NullUniValue;
|
||||
|
||||
|
||||
if (fHelp || params.size() > 3)
|
||||
throw runtime_error(
|
||||
"getbalance ( \"account\" minconf includeWatchonly )\n"
|
||||
@@ -1015,7 +1015,7 @@ UniValue getunconfirmedbalance(const UniValue ¶ms, bool fHelp)
|
||||
{
|
||||
if (!EnsureWalletIsAvailable(fHelp))
|
||||
return NullUniValue;
|
||||
|
||||
|
||||
if (fHelp || params.size() > 0)
|
||||
throw runtime_error(
|
||||
"getunconfirmedbalance\n"
|
||||
@@ -1031,7 +1031,7 @@ UniValue movecmd(const UniValue& params, bool fHelp)
|
||||
{
|
||||
if (!EnsureWalletIsAvailable(fHelp))
|
||||
return NullUniValue;
|
||||
|
||||
|
||||
if (fHelp || params.size() < 3 || params.size() > 5)
|
||||
throw runtime_error(
|
||||
"move \"fromaccount\" \"toaccount\" amount ( minconf \"comment\" )\n"
|
||||
@@ -1103,7 +1103,7 @@ UniValue sendfrom(const UniValue& params, bool fHelp)
|
||||
{
|
||||
if (!EnsureWalletIsAvailable(fHelp))
|
||||
return NullUniValue;
|
||||
|
||||
|
||||
if (fHelp || params.size() < 3 || params.size() > 6)
|
||||
throw runtime_error(
|
||||
"sendfrom \"fromaccount\" \"tozcashaddress\" amount ( minconf \"comment\" \"comment-to\" )\n"
|
||||
@@ -1168,7 +1168,7 @@ UniValue sendmany(const UniValue& params, bool fHelp)
|
||||
{
|
||||
if (!EnsureWalletIsAvailable(fHelp))
|
||||
return NullUniValue;
|
||||
|
||||
|
||||
if (fHelp || params.size() < 2 || params.size() > 5)
|
||||
throw runtime_error(
|
||||
"sendmany \"fromaccount\" {\"address\":amount,...} ( minconf \"comment\" [\"address\",...] )\n"
|
||||
@@ -1282,7 +1282,7 @@ UniValue addmultisigaddress(const UniValue& params, bool fHelp)
|
||||
{
|
||||
if (!EnsureWalletIsAvailable(fHelp))
|
||||
return NullUniValue;
|
||||
|
||||
|
||||
if (fHelp || params.size() < 2 || params.size() > 3)
|
||||
{
|
||||
string msg = "addmultisigaddress nrequired [\"key\",...] ( \"account\" )\n"
|
||||
@@ -1463,7 +1463,7 @@ UniValue listreceivedbyaddress(const UniValue& params, bool fHelp)
|
||||
{
|
||||
if (!EnsureWalletIsAvailable(fHelp))
|
||||
return NullUniValue;
|
||||
|
||||
|
||||
if (fHelp || params.size() > 3)
|
||||
throw runtime_error(
|
||||
"listreceivedbyaddress ( minconf includeempty includeWatchonly)\n"
|
||||
@@ -1500,7 +1500,7 @@ UniValue listreceivedbyaccount(const UniValue& params, bool fHelp)
|
||||
{
|
||||
if (!EnsureWalletIsAvailable(fHelp))
|
||||
return NullUniValue;
|
||||
|
||||
|
||||
if (fHelp || params.size() > 3)
|
||||
throw runtime_error(
|
||||
"listreceivedbyaccount ( minconf includeempty includeWatchonly)\n"
|
||||
@@ -1567,7 +1567,11 @@ void ListTransactions(const CWalletTx& wtx, const string& strAccount, int nMinDe
|
||||
entry.push_back(Pair("fee", ValueFromAmount(-nFee)));
|
||||
if (fLong)
|
||||
WalletTxToJSON(wtx, entry);
|
||||
#ifdef __APPLE__
|
||||
entry.push_back(Pair("size", (uint64_t)static_cast<CTransaction>(wtx).GetSerializeSize(SER_NETWORK, PROTOCOL_VERSION)));
|
||||
#else
|
||||
entry.push_back(Pair("size", static_cast<CTransaction>(wtx).GetSerializeSize(SER_NETWORK, PROTOCOL_VERSION)));
|
||||
#endif
|
||||
ret.push_back(entry);
|
||||
}
|
||||
}
|
||||
@@ -1604,7 +1608,11 @@ void ListTransactions(const CWalletTx& wtx, const string& strAccount, int nMinDe
|
||||
entry.push_back(Pair("vout", r.vout));
|
||||
if (fLong)
|
||||
WalletTxToJSON(wtx, entry);
|
||||
entry.push_back(Pair("size", static_cast<CTransaction>(wtx).GetSerializeSize(SER_NETWORK, PROTOCOL_VERSION)));
|
||||
#ifdef __APPLE__
|
||||
entry.push_back(Pair("size", (uint64_t)static_cast<CTransaction>(wtx).GetSerializeSize(SER_NETWORK, PROTOCOL_VERSION)));
|
||||
#else
|
||||
entry.push_back(Pair("size", static_cast<CTransaction>(wtx).GetSerializeSize(SER_NETWORK, PROTOCOL_VERSION)));
|
||||
#endif
|
||||
ret.push_back(entry);
|
||||
}
|
||||
}
|
||||
@@ -1632,7 +1640,7 @@ UniValue listtransactions(const UniValue& params, bool fHelp)
|
||||
{
|
||||
if (!EnsureWalletIsAvailable(fHelp))
|
||||
return NullUniValue;
|
||||
|
||||
|
||||
if (fHelp || params.size() > 4)
|
||||
throw runtime_error(
|
||||
"listtransactions ( \"account\" count from includeWatchonly)\n"
|
||||
@@ -1754,7 +1762,7 @@ UniValue listaccounts(const UniValue& params, bool fHelp)
|
||||
{
|
||||
if (!EnsureWalletIsAvailable(fHelp))
|
||||
return NullUniValue;
|
||||
|
||||
|
||||
if (fHelp || params.size() > 2)
|
||||
throw runtime_error(
|
||||
"listaccounts ( minconf includeWatchonly)\n"
|
||||
@@ -1834,7 +1842,7 @@ UniValue listsinceblock(const UniValue& params, bool fHelp)
|
||||
{
|
||||
if (!EnsureWalletIsAvailable(fHelp))
|
||||
return NullUniValue;
|
||||
|
||||
|
||||
if (fHelp)
|
||||
throw runtime_error(
|
||||
"listsinceblock ( \"blockhash\" target-confirmations includeWatchonly)\n"
|
||||
@@ -1925,7 +1933,7 @@ UniValue gettransaction(const UniValue& params, bool fHelp)
|
||||
{
|
||||
if (!EnsureWalletIsAvailable(fHelp))
|
||||
return NullUniValue;
|
||||
|
||||
|
||||
if (fHelp || params.size() < 1 || params.size() > 2)
|
||||
throw runtime_error(
|
||||
"gettransaction \"txid\" ( includeWatchonly )\n"
|
||||
@@ -2014,7 +2022,7 @@ UniValue backupwallet(const UniValue& params, bool fHelp)
|
||||
{
|
||||
if (!EnsureWalletIsAvailable(fHelp))
|
||||
return NullUniValue;
|
||||
|
||||
|
||||
if (fHelp || params.size() != 1)
|
||||
throw runtime_error(
|
||||
"backupwallet \"destination\"\n"
|
||||
@@ -2057,7 +2065,7 @@ UniValue keypoolrefill(const UniValue& params, bool fHelp)
|
||||
{
|
||||
if (!EnsureWalletIsAvailable(fHelp))
|
||||
return NullUniValue;
|
||||
|
||||
|
||||
if (fHelp || params.size() > 1)
|
||||
throw runtime_error(
|
||||
"keypoolrefill ( newsize )\n"
|
||||
@@ -2101,7 +2109,7 @@ UniValue walletpassphrase(const UniValue& params, bool fHelp)
|
||||
{
|
||||
if (!EnsureWalletIsAvailable(fHelp))
|
||||
return NullUniValue;
|
||||
|
||||
|
||||
if (pwalletMain->IsCrypted() && (fHelp || params.size() != 2))
|
||||
throw runtime_error(
|
||||
"walletpassphrase \"passphrase\" timeout\n"
|
||||
@@ -2163,7 +2171,7 @@ UniValue walletpassphrasechange(const UniValue& params, bool fHelp)
|
||||
{
|
||||
if (!EnsureWalletIsAvailable(fHelp))
|
||||
return NullUniValue;
|
||||
|
||||
|
||||
if (pwalletMain->IsCrypted() && (fHelp || params.size() != 2))
|
||||
throw runtime_error(
|
||||
"walletpassphrasechange \"oldpassphrase\" \"newpassphrase\"\n"
|
||||
@@ -2209,7 +2217,7 @@ UniValue walletlock(const UniValue& params, bool fHelp)
|
||||
{
|
||||
if (!EnsureWalletIsAvailable(fHelp))
|
||||
return NullUniValue;
|
||||
|
||||
|
||||
if (pwalletMain->IsCrypted() && (fHelp || params.size() != 0))
|
||||
throw runtime_error(
|
||||
"walletlock\n"
|
||||
@@ -2316,7 +2324,7 @@ UniValue lockunspent(const UniValue& params, bool fHelp)
|
||||
{
|
||||
if (!EnsureWalletIsAvailable(fHelp))
|
||||
return NullUniValue;
|
||||
|
||||
|
||||
if (fHelp || params.size() < 1 || params.size() > 2)
|
||||
throw runtime_error(
|
||||
"lockunspent unlock [{\"txid\":\"txid\",\"vout\":n},...]\n"
|
||||
@@ -2400,7 +2408,7 @@ UniValue listlockunspent(const UniValue& params, bool fHelp)
|
||||
{
|
||||
if (!EnsureWalletIsAvailable(fHelp))
|
||||
return NullUniValue;
|
||||
|
||||
|
||||
if (fHelp || params.size() > 0)
|
||||
throw runtime_error(
|
||||
"listlockunspent\n"
|
||||
@@ -2449,7 +2457,7 @@ UniValue settxfee(const UniValue& params, bool fHelp)
|
||||
{
|
||||
if (!EnsureWalletIsAvailable(fHelp))
|
||||
return NullUniValue;
|
||||
|
||||
|
||||
if (fHelp || params.size() < 1 || params.size() > 1)
|
||||
throw runtime_error(
|
||||
"settxfee amount\n"
|
||||
@@ -2476,7 +2484,7 @@ UniValue getwalletinfo(const UniValue& params, bool fHelp)
|
||||
{
|
||||
if (!EnsureWalletIsAvailable(fHelp))
|
||||
return NullUniValue;
|
||||
|
||||
|
||||
if (fHelp || params.size() != 0)
|
||||
throw runtime_error(
|
||||
"getwalletinfo\n"
|
||||
@@ -2518,7 +2526,7 @@ UniValue resendwallettransactions(const UniValue& params, bool fHelp)
|
||||
{
|
||||
if (!EnsureWalletIsAvailable(fHelp))
|
||||
return NullUniValue;
|
||||
|
||||
|
||||
if (fHelp || params.size() != 0)
|
||||
throw runtime_error(
|
||||
"resendwallettransactions\n"
|
||||
@@ -2545,7 +2553,7 @@ UniValue listunspent(const UniValue& params, bool fHelp)
|
||||
{
|
||||
if (!EnsureWalletIsAvailable(fHelp))
|
||||
return NullUniValue;
|
||||
|
||||
|
||||
if (fHelp || params.size() > 3)
|
||||
throw runtime_error(
|
||||
"listunspent ( minconf maxconf [\"address\",...] )\n"
|
||||
@@ -3241,8 +3249,8 @@ UniValue z_listaddresses(const UniValue& params, bool fHelp)
|
||||
CAmount getBalanceTaddr(std::string transparentAddress, int minDepth=1) {
|
||||
set<CBitcoinAddress> setAddress;
|
||||
vector<COutput> vecOutputs;
|
||||
CAmount balance = 0;
|
||||
|
||||
CAmount balance = 0;
|
||||
|
||||
if (transparentAddress.length() > 0) {
|
||||
CBitcoinAddress taddr = CBitcoinAddress(transparentAddress);
|
||||
if (!taddr.IsValid()) {
|
||||
@@ -3250,7 +3258,7 @@ CAmount getBalanceTaddr(std::string transparentAddress, int minDepth=1) {
|
||||
}
|
||||
setAddress.insert(taddr);
|
||||
}
|
||||
|
||||
|
||||
LOCK2(cs_main, pwalletMain->cs_wallet);
|
||||
|
||||
pwalletMain->AvailableCoins(vecOutputs, false, NULL, true);
|
||||
@@ -3270,7 +3278,7 @@ CAmount getBalanceTaddr(std::string transparentAddress, int minDepth=1) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
CAmount nValue = out.tx->vout[out.i].nValue; // komodo_interest
|
||||
balance += nValue;
|
||||
}
|
||||
@@ -3318,7 +3326,7 @@ UniValue z_listreceivedbyaddress(const UniValue& params, bool fHelp)
|
||||
if (nMinDepth < 0) {
|
||||
throw JSONRPCError(RPC_INVALID_PARAMETER, "Minimum number of confirmations cannot be less than 0");
|
||||
}
|
||||
|
||||
|
||||
// Check that the from address is valid.
|
||||
auto fromaddress = params[0].get_str();
|
||||
|
||||
@@ -3333,8 +3341,8 @@ UniValue z_listreceivedbyaddress(const UniValue& params, bool fHelp)
|
||||
if (!pwalletMain->HaveSpendingKey(zaddr)) {
|
||||
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "From address does not belong to this node, zaddr spending key not found.");
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
UniValue result(UniValue::VARR);
|
||||
std::vector<CNotePlaintextEntry> entries;
|
||||
pwalletMain->GetFilteredNotes(entries, fromaddress, nMinDepth, false);
|
||||
@@ -3382,7 +3390,7 @@ UniValue z_getbalance(const UniValue& params, bool fHelp)
|
||||
if (nMinDepth < 0) {
|
||||
throw JSONRPCError(RPC_INVALID_PARAMETER, "Minimum number of confirmations cannot be less than 0");
|
||||
}
|
||||
|
||||
|
||||
// Check that the from address is valid.
|
||||
auto fromaddress = params[0].get_str();
|
||||
bool fromTaddr = false;
|
||||
@@ -3449,7 +3457,7 @@ UniValue z_gettotalbalance(const UniValue& params, bool fHelp)
|
||||
}
|
||||
|
||||
// getbalance and "getbalance * 1 true" should return the same number
|
||||
// but they don't because wtx.GetAmounts() does not handle tx where there are no outputs
|
||||
// but they don't because wtx.GetAmounts() does not handle tx where there are no outputs
|
||||
// pwalletMain->GetBalance() does not accept min depth parameter
|
||||
// so we use our own method to get balance of utxos.
|
||||
CAmount nBalance = getBalanceTaddr("", nMinDepth);
|
||||
@@ -3479,7 +3487,7 @@ UniValue z_getoperationresult(const UniValue& params, bool fHelp)
|
||||
"\nResult:\n"
|
||||
"\" [object, ...]\" (array) A list of JSON objects\n"
|
||||
);
|
||||
|
||||
|
||||
// This call will remove finished operations
|
||||
return z_getoperationstatus_IMPL(params, true);
|
||||
}
|
||||
@@ -3499,7 +3507,7 @@ UniValue z_getoperationstatus(const UniValue& params, bool fHelp)
|
||||
"\nResult:\n"
|
||||
"\" [object, ...]\" (array) A list of JSON objects\n"
|
||||
);
|
||||
|
||||
|
||||
// This call is idempotent so we don't want to remove finished operations
|
||||
return z_getoperationstatus_IMPL(params, false);
|
||||
}
|
||||
@@ -3524,7 +3532,7 @@ UniValue z_getoperationstatus_IMPL(const UniValue& params, bool fRemoveFinishedO
|
||||
for (auto id : ids) {
|
||||
if (useFilter && !filter.count(id))
|
||||
continue;
|
||||
|
||||
|
||||
std::shared_ptr<AsyncRPCOperation> operation = q->getOperationForId(id);
|
||||
if (!operation) {
|
||||
continue;
|
||||
|
||||
@@ -161,7 +161,7 @@ public:
|
||||
// Transaction hash
|
||||
uint256 hash;
|
||||
// Index into CTransaction.vjoinsplit
|
||||
#ifdef __APPLE__
|
||||
#ifdef __LP64__
|
||||
uint64_t js;
|
||||
#else
|
||||
size_t js;
|
||||
@@ -288,7 +288,7 @@ public:
|
||||
uint256 hashBlock;
|
||||
std::vector<uint256> vMerkleBranch;
|
||||
int nIndex;
|
||||
|
||||
|
||||
// memory only
|
||||
mutable bool fMerkleVerified;
|
||||
|
||||
@@ -337,7 +337,7 @@ public:
|
||||
bool AcceptToMemoryPool(bool fLimitFree=true, bool fRejectAbsurdFee=true);
|
||||
};
|
||||
|
||||
/**
|
||||
/**
|
||||
* A transaction with a bunch of additional info that only the owner cares about.
|
||||
* It includes any unrecorded transactions needed to link it back to the block chain.
|
||||
*/
|
||||
@@ -577,7 +577,7 @@ public:
|
||||
|
||||
|
||||
|
||||
/**
|
||||
/**
|
||||
* A CWallet is an extension of a keystore, which also maintains a set of transactions and balances,
|
||||
* and provides the ability to create new transactions.
|
||||
*/
|
||||
@@ -880,7 +880,7 @@ public:
|
||||
//! Adds an encrypted spending key to the store, and saves it to disk (virtual method, declared in crypter.h)
|
||||
bool AddCryptedSpendingKey(const libzcash::PaymentAddress &address, const libzcash::ViewingKey &vk, const std::vector<unsigned char> &vchCryptedSecret);
|
||||
|
||||
/**
|
||||
/**
|
||||
* Increment the next transaction order id
|
||||
* @return next transaction order id
|
||||
*/
|
||||
@@ -1012,8 +1012,8 @@ public:
|
||||
|
||||
//! Verify the wallet database and perform salvage if required
|
||||
static bool Verify(const std::string& walletFile, std::string& warningString, std::string& errorString);
|
||||
|
||||
/**
|
||||
|
||||
/**
|
||||
* Address book entry changed.
|
||||
* @note called with lock cs_wallet held.
|
||||
*/
|
||||
@@ -1022,7 +1022,7 @@ public:
|
||||
const std::string &purpose,
|
||||
ChangeType status)> NotifyAddressBookChanged;
|
||||
|
||||
/**
|
||||
/**
|
||||
* Wallet transaction added, removed or updated.
|
||||
* @note called with lock cs_wallet held.
|
||||
*/
|
||||
@@ -1039,10 +1039,10 @@ public:
|
||||
bool GetBroadcastTransactions() const { return fBroadcastTransactions; }
|
||||
/** Set whether this wallet broadcasts transactions. */
|
||||
void SetBroadcastTransactions(bool broadcast) { fBroadcastTransactions = broadcast; }
|
||||
|
||||
|
||||
/* Find notes filtered by payment address, min depth, ability to spend */
|
||||
void GetFilteredNotes(std::vector<CNotePlaintextEntry> & outEntries, std::string address, int minDepth=1, bool ignoreSpent=true);
|
||||
|
||||
|
||||
};
|
||||
|
||||
/** A key allocated from the key pool. */
|
||||
@@ -1070,7 +1070,7 @@ public:
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
/**
|
||||
* Account information.
|
||||
* Stored in wallet with key "acc"+string account name.
|
||||
*/
|
||||
@@ -1101,7 +1101,7 @@ public:
|
||||
|
||||
|
||||
|
||||
/**
|
||||
/**
|
||||
* Internal transfers.
|
||||
* Database key is acentry<account><counter>.
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user