Initial merge
This commit is contained in:
@@ -21,6 +21,7 @@
|
||||
#include "rpcprotocol.h"
|
||||
#include "zcash/IncrementalMerkleTree.hpp"
|
||||
#include "sodium.h"
|
||||
#include "miner.h"
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
@@ -31,16 +32,16 @@
|
||||
|
||||
using namespace libzcash;
|
||||
|
||||
int find_output(Object obj, int n) {
|
||||
Value outputMapValue = find_value(obj, "outputmap");
|
||||
if (outputMapValue.type() != array_type) {
|
||||
int find_output(UniValue obj, int n) {
|
||||
UniValue outputMapValue = find_value(obj, "outputmap");
|
||||
if (!outputMapValue.isArray()) {
|
||||
throw JSONRPCError(RPC_WALLET_ERROR, "Missing outputmap for JoinSplit operation");
|
||||
}
|
||||
|
||||
Array outputMap = outputMapValue.get_array();
|
||||
UniValue outputMap = outputMapValue.get_array();
|
||||
assert(outputMap.size() == ZC_NUM_JS_OUTPUTS);
|
||||
for (size_t i = 0; i < outputMap.size(); i++) {
|
||||
if (outputMap[i] == n) {
|
||||
if (outputMap[i].get_int() == n) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
@@ -54,10 +55,10 @@ AsyncRPCOperation_sendmany::AsyncRPCOperation_sendmany(
|
||||
std::vector<SendManyRecipient> zOutputs,
|
||||
int minDepth,
|
||||
CAmount fee,
|
||||
Value contextInfo) :
|
||||
UniValue contextInfo) :
|
||||
fromaddress_(fromAddress), t_outputs_(tOutputs), z_outputs_(zOutputs), mindepth_(minDepth), fee_(fee), contextinfo_(contextInfo)
|
||||
{
|
||||
assert(fee_ > 0);
|
||||
assert(fee_ >= 0);
|
||||
|
||||
if (minDepth < 0) {
|
||||
throw JSONRPCError(RPC_INVALID_PARAMETER, "Minconf cannot be negative");
|
||||
@@ -93,6 +94,13 @@ AsyncRPCOperation_sendmany::AsyncRPCOperation_sendmany(
|
||||
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, string("runtime error: ") + e.what());
|
||||
}
|
||||
}
|
||||
|
||||
// Log the context info i.e. the call parameters to z_sendmany
|
||||
if (LogAcceptCategory("zrpcunsafe")) {
|
||||
LogPrint("zrpcunsafe", "%s: z_sendmany initialized (params=%s)\n", getId(), contextInfo.write());
|
||||
} else {
|
||||
LogPrint("zrpc", "%s: z_sendmany initialized\n", getId());
|
||||
}
|
||||
}
|
||||
|
||||
AsyncRPCOperation_sendmany::~AsyncRPCOperation_sendmany() {
|
||||
@@ -107,9 +115,17 @@ void AsyncRPCOperation_sendmany::main() {
|
||||
|
||||
bool success = false;
|
||||
|
||||
#ifdef ENABLE_MINING
|
||||
#ifdef ENABLE_WALLET
|
||||
GenerateBitcoins(false, NULL, 0);
|
||||
#else
|
||||
GenerateBitcoins(false, 0);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
try {
|
||||
success = main_impl();
|
||||
} catch (const Object& objError) {
|
||||
} catch (const UniValue& objError) {
|
||||
int code = find_value(objError, "code").get_int();
|
||||
std::string message = find_value(objError, "message").get_str();
|
||||
set_error_code(code);
|
||||
@@ -128,6 +144,14 @@ void AsyncRPCOperation_sendmany::main() {
|
||||
set_error_message("unknown error");
|
||||
}
|
||||
|
||||
#ifdef ENABLE_MINING
|
||||
#ifdef ENABLE_WALLET
|
||||
GenerateBitcoins(GetBoolArg("-gen",false), pwalletMain, GetArg("-genproclimit", 1));
|
||||
#else
|
||||
GenerateBitcoins(GetBoolArg("-gen",false), GetArg("-genproclimit", 1));
|
||||
#endif
|
||||
#endif
|
||||
|
||||
stop_execution_clock();
|
||||
|
||||
if (success) {
|
||||
@@ -136,9 +160,9 @@ void AsyncRPCOperation_sendmany::main() {
|
||||
set_state(OperationStatus::FAILED);
|
||||
}
|
||||
|
||||
std::string s = strprintf("async rpc %s finished (status=%s", getId(), getStateAsString());
|
||||
std::string s = strprintf("%s: z_sendmany finished (status=%s", getId(), getStateAsString());
|
||||
if (success) {
|
||||
s += strprintf(", tx=%s)\n", tx_.ToString());
|
||||
s += strprintf(", txid=%s)\n", tx_.GetHash().ToString());
|
||||
} else {
|
||||
s += strprintf(", error=%s)\n", getErrorMessage());
|
||||
}
|
||||
@@ -271,13 +295,13 @@ bool AsyncRPCOperation_sendmany::main_impl() {
|
||||
tx_ = CTransaction(rawTx);
|
||||
}
|
||||
|
||||
LogPrint("zrpc", "%s: spending %s to send %s with fee %s\n",
|
||||
getId().substr(0,10), FormatMoney(targetAmount, false), FormatMoney(sendAmount, false), FormatMoney(minersFee, false));
|
||||
LogPrint("zrpc", " - transparent input: %s (to choose from)\n", FormatMoney(t_inputs_total, false));
|
||||
LogPrint("zrpc", " - private input: %s (to choose from)\n", FormatMoney(z_inputs_total, false));
|
||||
LogPrint("zrpc", " - transparent output: %s\n", FormatMoney(t_outputs_total, false));
|
||||
LogPrint("zrpc", " - private output: %s\n", FormatMoney(z_outputs_total, false));
|
||||
LogPrint("zrpc", " - fee: %s\n", FormatMoney(minersFee, false));
|
||||
LogPrint((isfromtaddr_) ? "zrpc" : "zrpcunsafe", "%s: spending %s to send %s with fee %s\n",
|
||||
getId(), FormatMoney(targetAmount), FormatMoney(sendAmount), FormatMoney(minersFee));
|
||||
LogPrint("zrpc", "%s: transparent input: %s (to choose from)\n", getId(), FormatMoney(t_inputs_total));
|
||||
LogPrint("zrpcunsafe", "%s: private input: %s (to choose from)\n", getId(), FormatMoney(z_inputs_total));
|
||||
LogPrint("zrpc", "%s: transparent output: %s\n", getId(), FormatMoney(t_outputs_total));
|
||||
LogPrint("zrpcunsafe", "%s: private output: %s\n", getId(), FormatMoney(z_outputs_total));
|
||||
LogPrint("zrpc", "%s: fee: %s\n", getId(), FormatMoney(minersFee));
|
||||
|
||||
/**
|
||||
* SCENARIO #1
|
||||
@@ -297,12 +321,12 @@ bool AsyncRPCOperation_sendmany::main_impl() {
|
||||
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)
|
||||
getId(),
|
||||
FormatMoney(change)
|
||||
);
|
||||
}
|
||||
|
||||
Object obj;
|
||||
UniValue obj(UniValue::VOBJ);
|
||||
obj.push_back(Pair("rawtxn", EncodeHexTx(tx_)));
|
||||
sign_send_raw_transaction(obj);
|
||||
return true;
|
||||
@@ -373,14 +397,14 @@ bool AsyncRPCOperation_sendmany::main_impl() {
|
||||
} else {
|
||||
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)
|
||||
getId(),
|
||||
FormatMoney(change)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// Create joinsplits, where each output represents a zaddr recipient.
|
||||
Object obj;
|
||||
UniValue obj(UniValue::VOBJ);
|
||||
while (zOutputsDeque.size() > 0) {
|
||||
AsyncJoinSplitInfo info;
|
||||
info.vpub_old = 0;
|
||||
@@ -429,7 +453,7 @@ bool AsyncRPCOperation_sendmany::main_impl() {
|
||||
* SCENARIO #3
|
||||
* Part 1: Add to the transparent value pool.
|
||||
*/
|
||||
Object obj;
|
||||
UniValue obj(UniValue::VOBJ);
|
||||
CAmount jsChange = 0; // this is updated after each joinsplit
|
||||
int changeOutputIndex = -1; // this is updated after each joinsplit if jsChange > 0
|
||||
bool minersFeeProcessed = false;
|
||||
@@ -462,12 +486,12 @@ bool AsyncRPCOperation_sendmany::main_impl() {
|
||||
wtxHeight = mapBlockIndex[wtx.hashBlock]->nHeight;
|
||||
wtxDepth = wtx.GetDepthInMainChain();
|
||||
}
|
||||
LogPrint("zrpc", "%s: spending note (txid=%s, vjoinsplit=%d, ciphertext=%d, amount=%s, height=%d, confirmations=%d)\n",
|
||||
getId().substr(0, 10),
|
||||
LogPrint("zrpcunsafe", "%s: spending note (txid=%s, vjoinsplit=%d, ciphertext=%d, amount=%s, height=%d, confirmations=%d)\n",
|
||||
getId(),
|
||||
outPoint.hash.ToString().substr(0, 10),
|
||||
outPoint.js,
|
||||
int(outPoint.n), // uint8_t
|
||||
FormatMoney(noteFunds, false),
|
||||
FormatMoney(noteFunds),
|
||||
wtxHeight,
|
||||
wtxDepth
|
||||
);
|
||||
@@ -491,9 +515,9 @@ bool AsyncRPCOperation_sendmany::main_impl() {
|
||||
info.vjsout.push_back(JSOutput());
|
||||
info.vjsout.push_back(JSOutput(frompaymentaddress_, jsChange));
|
||||
|
||||
LogPrint("zrpc", "%s: generating note for change (amount=%s)\n",
|
||||
getId().substr(0, 10),
|
||||
FormatMoney(jsChange, false)
|
||||
LogPrint("zrpcunsafe", "%s: generating note for change (amount=%s)\n",
|
||||
getId(),
|
||||
FormatMoney(jsChange)
|
||||
);
|
||||
}
|
||||
|
||||
@@ -587,9 +611,9 @@ bool AsyncRPCOperation_sendmany::main_impl() {
|
||||
|
||||
jsInputValue += plaintext.value;
|
||||
|
||||
LogPrint("zrpc", "%s: spending change (amount=%s)\n",
|
||||
getId().substr(0, 10),
|
||||
FormatMoney(plaintext.value, false)
|
||||
LogPrint("zrpcunsafe", "%s: spending change (amount=%s)\n",
|
||||
getId(),
|
||||
FormatMoney(plaintext.value)
|
||||
);
|
||||
|
||||
} catch (const std::exception& e) {
|
||||
@@ -634,12 +658,12 @@ bool AsyncRPCOperation_sendmany::main_impl() {
|
||||
wtxHeight = mapBlockIndex[wtx.hashBlock]->nHeight;
|
||||
wtxDepth = wtx.GetDepthInMainChain();
|
||||
}
|
||||
LogPrint("zrpc", "%s: spending note (txid=%s, vjoinsplit=%d, ciphertext=%d, amount=%s, height=%d, confirmations=%d)\n",
|
||||
getId().substr(0, 10),
|
||||
LogPrint("zrpcunsafe", "%s: spending note (txid=%s, vjoinsplit=%d, ciphertext=%d, amount=%s, height=%d, confirmations=%d)\n",
|
||||
getId(),
|
||||
jso.hash.ToString().substr(0, 10),
|
||||
jso.js,
|
||||
int(jso.n), // uint8_t
|
||||
FormatMoney(noteFunds, false),
|
||||
FormatMoney(noteFunds),
|
||||
wtxHeight,
|
||||
wtxDepth
|
||||
);
|
||||
@@ -729,9 +753,9 @@ bool AsyncRPCOperation_sendmany::main_impl() {
|
||||
if (jsChange>0) {
|
||||
info.vjsout.push_back(JSOutput(frompaymentaddress_, jsChange));
|
||||
|
||||
LogPrint("zrpc", "%s: generating note for change (amount=%s)\n",
|
||||
getId().substr(0, 10),
|
||||
FormatMoney(jsChange, false)
|
||||
LogPrint("zrpcunsafe", "%s: generating note for change (amount=%s)\n",
|
||||
getId(),
|
||||
FormatMoney(jsChange)
|
||||
);
|
||||
}
|
||||
|
||||
@@ -752,42 +776,47 @@ bool AsyncRPCOperation_sendmany::main_impl() {
|
||||
* Sign and send a raw transaction.
|
||||
* Raw transaction as hex string should be in object field "rawtxn"
|
||||
*/
|
||||
void AsyncRPCOperation_sendmany::sign_send_raw_transaction(Object obj)
|
||||
void AsyncRPCOperation_sendmany::sign_send_raw_transaction(UniValue obj)
|
||||
{
|
||||
// Sign the raw transaction
|
||||
Value rawtxnValue = find_value(obj, "rawtxn");
|
||||
if (rawtxnValue.is_null()) {
|
||||
UniValue rawtxnValue = find_value(obj, "rawtxn");
|
||||
if (rawtxnValue.isNull()) {
|
||||
throw JSONRPCError(RPC_WALLET_ERROR, "Missing hex data for raw transaction");
|
||||
}
|
||||
std::string rawtxn = rawtxnValue.get_str();
|
||||
|
||||
Value signResultValue = signrawtransaction({Value(rawtxn)}, false);
|
||||
Object signResultObject = signResultValue.get_obj();
|
||||
Value completeValue = find_value(signResultObject, "complete");
|
||||
UniValue params = UniValue(UniValue::VARR);
|
||||
params.push_back(rawtxn);
|
||||
UniValue signResultValue = signrawtransaction(params, false);
|
||||
UniValue signResultObject = signResultValue.get_obj();
|
||||
UniValue completeValue = find_value(signResultObject, "complete");
|
||||
bool complete = completeValue.get_bool();
|
||||
if (!complete) {
|
||||
// TODO: #1366 Maybe get "errors" and print array vErrors into a string
|
||||
throw JSONRPCError(RPC_WALLET_ENCRYPTION_FAILED, "Failed to sign transaction");
|
||||
}
|
||||
|
||||
Value hexValue = find_value(signResultObject, "hex");
|
||||
if (hexValue.is_null()) {
|
||||
UniValue hexValue = find_value(signResultObject, "hex");
|
||||
if (hexValue.isNull()) {
|
||||
throw JSONRPCError(RPC_WALLET_ERROR, "Missing hex data for signed transaction");
|
||||
}
|
||||
std::string signedtxn = hexValue.get_str();
|
||||
|
||||
// Send the signed transaction
|
||||
if (!testmode) {
|
||||
Value sendResultValue = sendrawtransaction({Value(signedtxn)}, false);
|
||||
if (sendResultValue.is_null()) {
|
||||
params.clear();
|
||||
params.setArray();
|
||||
params.push_back(signedtxn);
|
||||
UniValue sendResultValue = sendrawtransaction(params, false);
|
||||
if (sendResultValue.isNull()) {
|
||||
throw JSONRPCError(RPC_WALLET_ERROR, "Send raw transaction did not return an error or a txid.");
|
||||
}
|
||||
|
||||
std::string txid = sendResultValue.get_str();
|
||||
|
||||
Object o;
|
||||
UniValue o(UniValue::VOBJ);
|
||||
o.push_back(Pair("txid", txid));
|
||||
set_result(Value(o));
|
||||
set_result(o);
|
||||
} else {
|
||||
// Test mode does not send the transaction to the network.
|
||||
|
||||
@@ -795,11 +824,11 @@ void AsyncRPCOperation_sendmany::sign_send_raw_transaction(Object obj)
|
||||
CTransaction tx;
|
||||
stream >> tx;
|
||||
|
||||
Object o;
|
||||
UniValue o(UniValue::VOBJ);
|
||||
o.push_back(Pair("test", 1));
|
||||
o.push_back(Pair("txid", tx.GetHash().ToString()));
|
||||
o.push_back(Pair("hex", signedtxn));
|
||||
set_result(Value(o));
|
||||
set_result(o);
|
||||
}
|
||||
|
||||
// Keep the signed transaction so we can hash to the same txid
|
||||
@@ -864,24 +893,14 @@ 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());
|
||||
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,
|
||||
int(entry.jsop.n), // uint8_t
|
||||
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)
|
||||
);
|
||||
}
|
||||
LogPrint("zrpcunsafe", "%s: found unspent note (txid=%s, vjoinsplit=%d, ciphertext=%d, amount=%s, memo=%s)\n",
|
||||
getId(),
|
||||
entry.jsop.hash.ToString().substr(0, 10),
|
||||
entry.jsop.js,
|
||||
int(entry.jsop.n), // uint8_t
|
||||
FormatMoney(entry.plaintext.value),
|
||||
HexStr(data).substr(0, 10)
|
||||
);
|
||||
}
|
||||
|
||||
if (z_inputs_.size() == 0) {
|
||||
@@ -896,7 +915,7 @@ bool AsyncRPCOperation_sendmany::find_unspent_notes() {
|
||||
return true;
|
||||
}
|
||||
|
||||
Object AsyncRPCOperation_sendmany::perform_joinsplit(AsyncJoinSplitInfo & info) {
|
||||
UniValue AsyncRPCOperation_sendmany::perform_joinsplit(AsyncJoinSplitInfo & info) {
|
||||
std::vector<boost::optional < ZCIncrementalWitness>> witnesses;
|
||||
uint256 anchor;
|
||||
{
|
||||
@@ -907,7 +926,7 @@ Object AsyncRPCOperation_sendmany::perform_joinsplit(AsyncJoinSplitInfo & info)
|
||||
}
|
||||
|
||||
|
||||
Object AsyncRPCOperation_sendmany::perform_joinsplit(AsyncJoinSplitInfo & info, std::vector<JSOutPoint> & outPoints) {
|
||||
UniValue AsyncRPCOperation_sendmany::perform_joinsplit(AsyncJoinSplitInfo & info, std::vector<JSOutPoint> & outPoints) {
|
||||
std::vector<boost::optional < ZCIncrementalWitness>> witnesses;
|
||||
uint256 anchor;
|
||||
{
|
||||
@@ -917,7 +936,7 @@ Object AsyncRPCOperation_sendmany::perform_joinsplit(AsyncJoinSplitInfo & info,
|
||||
return perform_joinsplit(info, witnesses, anchor);
|
||||
}
|
||||
|
||||
Object AsyncRPCOperation_sendmany::perform_joinsplit(
|
||||
UniValue AsyncRPCOperation_sendmany::perform_joinsplit(
|
||||
AsyncJoinSplitInfo & info,
|
||||
std::vector<boost::optional < ZCIncrementalWitness>> witnesses,
|
||||
uint256 anchor)
|
||||
@@ -952,12 +971,12 @@ Object AsyncRPCOperation_sendmany::perform_joinsplit(
|
||||
|
||||
CMutableTransaction mtx(tx_);
|
||||
|
||||
LogPrint("zrpc", "%s: creating joinsplit at index %d (vpub_old=%s, vpub_new=%s, in[0]=%s, in[1]=%s, out[0]=%s, out[1]=%s)\n",
|
||||
getId().substr(0,10),
|
||||
LogPrint("zrpcunsafe", "%s: creating joinsplit at index %d (vpub_old=%s, vpub_new=%s, in[0]=%s, in[1]=%s, out[0]=%s, out[1]=%s)\n",
|
||||
getId(),
|
||||
tx_.vjoinsplit.size(),
|
||||
FormatMoney(info.vpub_old, false), FormatMoney(info.vpub_new, false),
|
||||
FormatMoney(info.vjsin[0].note.value, false), FormatMoney(info.vjsin[1].note.value, false),
|
||||
FormatMoney(info.vjsout[0].value, false), FormatMoney(info.vjsout[1].value, false)
|
||||
FormatMoney(info.vpub_old), FormatMoney(info.vpub_new),
|
||||
FormatMoney(info.vjsin[0].note.value), FormatMoney(info.vjsin[1].note.value),
|
||||
FormatMoney(info.vjsout[0].value), FormatMoney(info.vjsout[1].value)
|
||||
);
|
||||
|
||||
// Generate the proof, this can take over a minute.
|
||||
@@ -1043,8 +1062,8 @@ Object AsyncRPCOperation_sendmany::perform_joinsplit(
|
||||
encryptedNote2 = HexStr(ss2.begin(), ss2.end());
|
||||
}
|
||||
|
||||
Array arrInputMap;
|
||||
Array arrOutputMap;
|
||||
UniValue arrInputMap(UniValue::VARR);
|
||||
UniValue arrOutputMap(UniValue::VARR);
|
||||
for (size_t i = 0; i < ZC_NUM_JS_INPUTS; i++) {
|
||||
arrInputMap.push_back(inputMap[i]);
|
||||
}
|
||||
@@ -1052,7 +1071,7 @@ Object AsyncRPCOperation_sendmany::perform_joinsplit(
|
||||
arrOutputMap.push_back(outputMap[i]);
|
||||
}
|
||||
|
||||
Object obj;
|
||||
UniValue obj(UniValue::VOBJ);
|
||||
obj.push_back(Pair("encryptednote1", encryptedNote1));
|
||||
obj.push_back(Pair("encryptednote2", encryptedNote2));
|
||||
obj.push_back(Pair("rawtxn", HexStr(ss.begin(), ss.end())));
|
||||
@@ -1128,15 +1147,15 @@ boost::array<unsigned char, ZC_MEMO_SIZE> AsyncRPCOperation_sendmany::get_memo_f
|
||||
/**
|
||||
* Override getStatus() to append the operation's input parameters to the default status object.
|
||||
*/
|
||||
Value AsyncRPCOperation_sendmany::getStatus() const {
|
||||
Value v = AsyncRPCOperation::getStatus();
|
||||
if (contextinfo_.is_null()) {
|
||||
UniValue AsyncRPCOperation_sendmany::getStatus() const {
|
||||
UniValue v = AsyncRPCOperation::getStatus();
|
||||
if (contextinfo_.isNull()) {
|
||||
return v;
|
||||
}
|
||||
|
||||
Object obj = v.get_obj();
|
||||
UniValue obj = v.get_obj();
|
||||
obj.push_back(Pair("method", "z_sendmany"));
|
||||
obj.push_back(Pair("params", contextinfo_ ));
|
||||
return Value(obj);
|
||||
return obj;
|
||||
}
|
||||
|
||||
|
||||
@@ -11,17 +11,17 @@
|
||||
#include "primitives/transaction.h"
|
||||
#include "zcash/JoinSplit.hpp"
|
||||
#include "zcash/Address.hpp"
|
||||
#include "json/json_spirit_value.h"
|
||||
#include "wallet.h"
|
||||
|
||||
#include <unordered_map>
|
||||
#include <tuple>
|
||||
|
||||
#include <univalue.h>
|
||||
|
||||
// Default transaction fee if caller does not specify one.
|
||||
#define ASYNC_RPC_OPERATION_DEFAULT_MINERS_FEE 10000
|
||||
|
||||
using namespace libzcash;
|
||||
using namespace json_spirit;
|
||||
|
||||
// A recipient is a tuple of address, amount, memo (optional if zaddr)
|
||||
typedef std::tuple<std::string, CAmount, std::string> SendManyRecipient;
|
||||
@@ -50,7 +50,7 @@ struct WitnessAnchorData {
|
||||
|
||||
class AsyncRPCOperation_sendmany : public AsyncRPCOperation {
|
||||
public:
|
||||
AsyncRPCOperation_sendmany(std::string fromAddress, std::vector<SendManyRecipient> tOutputs, std::vector<SendManyRecipient> zOutputs, int minDepth, CAmount fee = ASYNC_RPC_OPERATION_DEFAULT_MINERS_FEE, Value contextInfo = Value::null);
|
||||
AsyncRPCOperation_sendmany(std::string fromAddress, std::vector<SendManyRecipient> tOutputs, std::vector<SendManyRecipient> zOutputs, int minDepth, CAmount fee = ASYNC_RPC_OPERATION_DEFAULT_MINERS_FEE, UniValue contextInfo = NullUniValue);
|
||||
virtual ~AsyncRPCOperation_sendmany();
|
||||
|
||||
// We don't want to be copied or moved around
|
||||
@@ -61,14 +61,14 @@ public:
|
||||
|
||||
virtual void main();
|
||||
|
||||
virtual Value getStatus() const;
|
||||
virtual UniValue getStatus() const;
|
||||
|
||||
bool testmode = false; // Set to true to disable sending txs and generating proofs
|
||||
|
||||
private:
|
||||
friend class TEST_FRIEND_AsyncRPCOperation_sendmany; // class for unit testing
|
||||
|
||||
Value contextinfo_; // optional data to include in return value from getStatus()
|
||||
UniValue contextinfo_; // optional data to include in return value from getStatus()
|
||||
|
||||
CAmount fee_;
|
||||
int mindepth_;
|
||||
@@ -100,18 +100,18 @@ private:
|
||||
bool main_impl();
|
||||
|
||||
// JoinSplit without any input notes to spend
|
||||
Object perform_joinsplit(AsyncJoinSplitInfo &);
|
||||
UniValue perform_joinsplit(AsyncJoinSplitInfo &);
|
||||
|
||||
// JoinSplit with input notes to spend (JSOutPoints))
|
||||
Object perform_joinsplit(AsyncJoinSplitInfo &, std::vector<JSOutPoint> & );
|
||||
UniValue perform_joinsplit(AsyncJoinSplitInfo &, std::vector<JSOutPoint> & );
|
||||
|
||||
// JoinSplit where you have the witnesses and anchor
|
||||
Object perform_joinsplit(
|
||||
UniValue perform_joinsplit(
|
||||
AsyncJoinSplitInfo & info,
|
||||
std::vector<boost::optional < ZCIncrementalWitness>> witnesses,
|
||||
uint256 anchor);
|
||||
|
||||
void sign_send_raw_transaction(Object obj); // throws exception if there was an error
|
||||
void sign_send_raw_transaction(UniValue obj); // throws exception if there was an error
|
||||
|
||||
};
|
||||
|
||||
@@ -157,15 +157,15 @@ public:
|
||||
return delegate->main_impl();
|
||||
}
|
||||
|
||||
Object perform_joinsplit(AsyncJoinSplitInfo &info) {
|
||||
UniValue perform_joinsplit(AsyncJoinSplitInfo &info) {
|
||||
return delegate->perform_joinsplit(info);
|
||||
}
|
||||
|
||||
Object perform_joinsplit(AsyncJoinSplitInfo &info, std::vector<JSOutPoint> &v ) {
|
||||
UniValue perform_joinsplit(AsyncJoinSplitInfo &info, std::vector<JSOutPoint> &v ) {
|
||||
return delegate->perform_joinsplit(info, v);
|
||||
}
|
||||
|
||||
Object perform_joinsplit(
|
||||
UniValue perform_joinsplit(
|
||||
AsyncJoinSplitInfo & info,
|
||||
std::vector<boost::optional < ZCIncrementalWitness>> witnesses,
|
||||
uint256 anchor)
|
||||
@@ -173,7 +173,7 @@ public:
|
||||
return delegate->perform_joinsplit(info, witnesses, anchor);
|
||||
}
|
||||
|
||||
void sign_send_raw_transaction(Object obj) {
|
||||
void sign_send_raw_transaction(UniValue obj) {
|
||||
delegate->sign_send_raw_transaction(obj);
|
||||
}
|
||||
|
||||
|
||||
@@ -19,16 +19,15 @@
|
||||
#include <boost/algorithm/string.hpp>
|
||||
#include <boost/date_time/posix_time/posix_time.hpp>
|
||||
|
||||
#include "json/json_spirit_value.h"
|
||||
#include <univalue.h>
|
||||
|
||||
using namespace json_spirit;
|
||||
using namespace std;
|
||||
|
||||
void EnsureWalletIsUnlocked();
|
||||
bool EnsureWalletIsAvailable(bool avoidException);
|
||||
|
||||
Value dumpwallet_impl(const Array& params, bool fHelp, bool fDumpZKeys);
|
||||
Value importwallet_impl(const Array& params, bool fHelp, bool fImportZKeys);
|
||||
UniValue dumpwallet_impl(const UniValue& params, bool fHelp, bool fDumpZKeys);
|
||||
UniValue importwallet_impl(const UniValue& params, bool fHelp, bool fImportZKeys);
|
||||
|
||||
|
||||
std::string static EncodeDumpTime(int64_t nTime) {
|
||||
@@ -74,10 +73,10 @@ std::string DecodeDumpString(const std::string &str) {
|
||||
return ret.str();
|
||||
}
|
||||
|
||||
Value importprivkey(const Array& params, bool fHelp)
|
||||
UniValue importprivkey(const UniValue& params, bool fHelp)
|
||||
{
|
||||
if (!EnsureWalletIsAvailable(fHelp))
|
||||
return Value::null;
|
||||
return NullUniValue;
|
||||
|
||||
if (fHelp || params.size() < 1 || params.size() > 3)
|
||||
throw runtime_error(
|
||||
@@ -130,7 +129,7 @@ Value importprivkey(const Array& params, bool fHelp)
|
||||
|
||||
// Don't throw error in case a key is already there
|
||||
if (pwalletMain->HaveKey(vchAddress))
|
||||
return Value::null;
|
||||
return NullUniValue;
|
||||
|
||||
pwalletMain->mapKeyMetadata[vchAddress].nCreateTime = 1;
|
||||
|
||||
@@ -145,13 +144,13 @@ Value importprivkey(const Array& params, bool fHelp)
|
||||
}
|
||||
}
|
||||
|
||||
return Value::null;
|
||||
return NullUniValue;
|
||||
}
|
||||
|
||||
Value importaddress(const Array& params, bool fHelp)
|
||||
UniValue importaddress(const UniValue& params, bool fHelp)
|
||||
{
|
||||
if (!EnsureWalletIsAvailable(fHelp))
|
||||
return Value::null;
|
||||
return NullUniValue;
|
||||
|
||||
if (fHelp || params.size() < 1 || params.size() > 3)
|
||||
throw runtime_error(
|
||||
@@ -204,7 +203,7 @@ Value importaddress(const Array& params, bool fHelp)
|
||||
|
||||
// Don't throw error in case an address is already there
|
||||
if (pwalletMain->HaveWatchOnly(script))
|
||||
return Value::null;
|
||||
return NullUniValue;
|
||||
|
||||
pwalletMain->MarkDirty();
|
||||
|
||||
@@ -218,13 +217,13 @@ Value importaddress(const Array& params, bool fHelp)
|
||||
}
|
||||
}
|
||||
|
||||
return Value::null;
|
||||
return NullUniValue;
|
||||
}
|
||||
|
||||
Value z_importwallet(const Array& params, bool fHelp)
|
||||
UniValue z_importwallet(const UniValue& params, bool fHelp)
|
||||
{
|
||||
if (!EnsureWalletIsAvailable(fHelp))
|
||||
return Value::null;
|
||||
return NullUniValue;
|
||||
|
||||
if (fHelp || params.size() != 1)
|
||||
throw runtime_error(
|
||||
@@ -244,10 +243,10 @@ Value z_importwallet(const Array& params, bool fHelp)
|
||||
return importwallet_impl(params, fHelp, true);
|
||||
}
|
||||
|
||||
Value importwallet(const Array& params, bool fHelp)
|
||||
UniValue importwallet(const UniValue& params, bool fHelp)
|
||||
{
|
||||
if (!EnsureWalletIsAvailable(fHelp))
|
||||
return Value::null;
|
||||
return NullUniValue;
|
||||
|
||||
if (fHelp || params.size() != 1)
|
||||
throw runtime_error(
|
||||
@@ -267,7 +266,7 @@ Value importwallet(const Array& params, bool fHelp)
|
||||
return importwallet_impl(params, fHelp, false);
|
||||
}
|
||||
|
||||
Value importwallet_impl(const Array& params, bool fHelp, bool fImportZKeys)
|
||||
UniValue importwallet_impl(const UniValue& params, bool fHelp, bool fImportZKeys)
|
||||
{
|
||||
LOCK2(cs_main, pwalletMain->cs_wallet);
|
||||
|
||||
@@ -378,13 +377,13 @@ Value importwallet_impl(const Array& params, bool fHelp, bool fImportZKeys)
|
||||
if (!fGood)
|
||||
throw JSONRPCError(RPC_WALLET_ERROR, "Error adding some keys to wallet");
|
||||
|
||||
return Value::null;
|
||||
return NullUniValue;
|
||||
}
|
||||
|
||||
Value dumpprivkey(const Array& params, bool fHelp)
|
||||
UniValue dumpprivkey(const UniValue& params, bool fHelp)
|
||||
{
|
||||
if (!EnsureWalletIsAvailable(fHelp))
|
||||
return Value::null;
|
||||
return NullUniValue;
|
||||
|
||||
if (fHelp || params.size() != 1)
|
||||
throw runtime_error(
|
||||
@@ -420,10 +419,10 @@ Value dumpprivkey(const Array& params, bool fHelp)
|
||||
|
||||
|
||||
|
||||
Value z_exportwallet(const Array& params, bool fHelp)
|
||||
UniValue z_exportwallet(const UniValue& params, bool fHelp)
|
||||
{
|
||||
if (!EnsureWalletIsAvailable(fHelp))
|
||||
return Value::null;
|
||||
return NullUniValue;
|
||||
|
||||
if (fHelp || params.size() != 1)
|
||||
throw runtime_error(
|
||||
@@ -441,10 +440,10 @@ Value z_exportwallet(const Array& params, bool fHelp)
|
||||
return dumpwallet_impl(params, fHelp, true);
|
||||
}
|
||||
|
||||
Value dumpwallet(const Array& params, bool fHelp)
|
||||
UniValue dumpwallet(const UniValue& params, bool fHelp)
|
||||
{
|
||||
if (!EnsureWalletIsAvailable(fHelp))
|
||||
return Value::null;
|
||||
return NullUniValue;
|
||||
|
||||
if (fHelp || params.size() != 1)
|
||||
throw runtime_error(
|
||||
@@ -462,7 +461,7 @@ Value dumpwallet(const Array& params, bool fHelp)
|
||||
return dumpwallet_impl(params, fHelp, false);
|
||||
}
|
||||
|
||||
Value dumpwallet_impl(const Array& params, bool fHelp, bool fDumpZKeys)
|
||||
UniValue dumpwallet_impl(const UniValue& params, bool fHelp, bool fDumpZKeys)
|
||||
{
|
||||
LOCK2(cs_main, pwalletMain->cs_wallet);
|
||||
|
||||
@@ -548,26 +547,31 @@ Value dumpwallet_impl(const Array& params, bool fHelp, bool fDumpZKeys)
|
||||
}
|
||||
|
||||
|
||||
Value z_importkey(const Array& params, bool fHelp)
|
||||
UniValue z_importkey(const UniValue& params, bool fHelp)
|
||||
{
|
||||
if (!EnsureWalletIsAvailable(fHelp))
|
||||
return Value::null;
|
||||
return NullUniValue;
|
||||
|
||||
if (fHelp || params.size() < 1 || params.size() > 2)
|
||||
if (fHelp || params.size() < 1 || params.size() > 3)
|
||||
throw runtime_error(
|
||||
"z_importkey \"zkey\" ( rescan )\n"
|
||||
"z_importkey \"zkey\" ( rescan startHeight )\n"
|
||||
"\nAdds a zkey (as returned by z_exportkey) to your wallet.\n"
|
||||
"\nArguments:\n"
|
||||
"1. \"zkey\" (string, required) The zkey (see z_exportkey)\n"
|
||||
"2. rescan (boolean, optional, default=true) Rescan the wallet for transactions\n"
|
||||
"2. rescan (string, optional, default=\"whenkeyisnew\") Rescan the wallet for transactions - can be \"yes\", \"no\" or \"whenkeyisnew\"\n"
|
||||
"3. startHeight (numeric, optional, default=0) Block height to start rescan from\n"
|
||||
"\nNote: This call can take minutes to complete if rescan is true.\n"
|
||||
"\nExamples:\n"
|
||||
"\nExport a zkey\n"
|
||||
+ HelpExampleCli("z_exportkey", "\"myaddress\"") +
|
||||
"\nImport the zkey with rescan\n"
|
||||
+ HelpExampleCli("z_importkey", "\"mykey\"") +
|
||||
"\nImport the zkey with partial rescan\n"
|
||||
+ HelpExampleCli("z_importkey", "\"mykey\" whenkeyisnew 30000") +
|
||||
"\nRe-import the zkey with longer partial rescan\n"
|
||||
+ HelpExampleCli("z_importkey", "\"mykey\" yes 20000") +
|
||||
"\nAs a JSON-RPC call\n"
|
||||
+ HelpExampleRpc("z_importkey", "\"mykey\", false")
|
||||
+ HelpExampleRpc("z_importkey", "\"mykey\", \"no\"")
|
||||
);
|
||||
|
||||
LOCK2(cs_main, pwalletMain->cs_wallet);
|
||||
@@ -576,8 +580,36 @@ Value z_importkey(const Array& params, bool fHelp)
|
||||
|
||||
// Whether to perform rescan after import
|
||||
bool fRescan = true;
|
||||
if (params.size() > 1)
|
||||
fRescan = params[1].get_bool();
|
||||
bool fIgnoreExistingKey = true;
|
||||
if (params.size() > 1) {
|
||||
auto rescan = params[1].get_str();
|
||||
if (rescan.compare("whenkeyisnew") != 0) {
|
||||
fIgnoreExistingKey = false;
|
||||
if (rescan.compare("yes") == 0) {
|
||||
fRescan = true;
|
||||
} else if (rescan.compare("no") == 0) {
|
||||
fRescan = false;
|
||||
} else {
|
||||
// Handle older API
|
||||
UniValue jVal;
|
||||
if (!jVal.read(std::string("[")+rescan+std::string("]")) ||
|
||||
!jVal.isArray() || jVal.size()!=1 || !jVal[0].isBool()) {
|
||||
throw JSONRPCError(
|
||||
RPC_INVALID_PARAMETER,
|
||||
"rescan must be \"yes\", \"no\" or \"whenkeyisnew\"");
|
||||
}
|
||||
fRescan = jVal[0].getBool();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Height to rescan from
|
||||
int nRescanHeight = 0;
|
||||
if (params.size() > 2)
|
||||
nRescanHeight = params[2].get_int();
|
||||
if (nRescanHeight < 0 || nRescanHeight > chainActive.Height()) {
|
||||
throw JSONRPCError(RPC_INVALID_PARAMETER, "Block height out of range");
|
||||
}
|
||||
|
||||
string strSecret = params[0].get_str();
|
||||
CZCSpendingKey spendingkey(strSecret);
|
||||
@@ -586,33 +618,36 @@ Value z_importkey(const Array& params, bool fHelp)
|
||||
|
||||
{
|
||||
// Don't throw error in case a key is already there
|
||||
if (pwalletMain->HaveSpendingKey(addr))
|
||||
return Value::null;
|
||||
if (pwalletMain->HaveSpendingKey(addr)) {
|
||||
if (fIgnoreExistingKey) {
|
||||
return NullUniValue;
|
||||
}
|
||||
} else {
|
||||
pwalletMain->MarkDirty();
|
||||
|
||||
pwalletMain->MarkDirty();
|
||||
if (!pwalletMain-> AddZKey(key))
|
||||
throw JSONRPCError(RPC_WALLET_ERROR, "Error adding spending key to wallet");
|
||||
|
||||
if (!pwalletMain-> AddZKey(key))
|
||||
throw JSONRPCError(RPC_WALLET_ERROR, "Error adding spending key to wallet");
|
||||
|
||||
pwalletMain->mapZKeyMetadata[addr].nCreateTime = 1;
|
||||
pwalletMain->mapZKeyMetadata[addr].nCreateTime = 1;
|
||||
}
|
||||
|
||||
// whenever a key is imported, we need to scan the whole chain
|
||||
pwalletMain->nTimeFirstKey = 1; // 0 would be considered 'no value'
|
||||
|
||||
// We want to scan for transactions and notes
|
||||
if (fRescan) {
|
||||
pwalletMain->ScanForWalletTransactions(chainActive.Genesis(), true);
|
||||
pwalletMain->ScanForWalletTransactions(chainActive[nRescanHeight], true);
|
||||
}
|
||||
}
|
||||
|
||||
return Value::null;
|
||||
return NullUniValue;
|
||||
}
|
||||
|
||||
|
||||
Value z_exportkey(const Array& params, bool fHelp)
|
||||
UniValue z_exportkey(const UniValue& params, bool fHelp)
|
||||
{
|
||||
if (!EnsureWalletIsAvailable(fHelp))
|
||||
return Value::null;
|
||||
return NullUniValue;
|
||||
|
||||
if (fHelp || params.size() != 1)
|
||||
throw runtime_error(
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -824,13 +824,11 @@ bool CWallet::EncryptWallet(const SecureString& strWalletPassphrase)
|
||||
return false;
|
||||
|
||||
CKeyingMaterial vMasterKey;
|
||||
RandAddSeedPerfmon();
|
||||
|
||||
vMasterKey.resize(WALLET_CRYPTO_KEY_SIZE);
|
||||
GetRandBytes(&vMasterKey[0], WALLET_CRYPTO_KEY_SIZE);
|
||||
|
||||
CMasterKey kMasterKey;
|
||||
RandAddSeedPerfmon();
|
||||
|
||||
kMasterKey.vchSalt.resize(WALLET_CRYPTO_SALT_SIZE);
|
||||
GetRandBytes(&kMasterKey.vchSalt[0], WALLET_CRYPTO_SALT_SIZE);
|
||||
@@ -1285,12 +1283,7 @@ mapNoteData_t CWallet::FindMyNotes(const CTransaction& tx) const
|
||||
noteData.insert(std::make_pair(jsoutpt, nd));
|
||||
}
|
||||
break;
|
||||
} catch (const std::runtime_error &err) {
|
||||
if (memcmp("Could not decrypt message", err.what(), 25) != 0) {
|
||||
// Unexpected failure
|
||||
LogPrintf("FindMyNotes(): Unexpected runtime error while testing decrypt:\n");
|
||||
LogPrintf("%s\n", err.what());
|
||||
} // else
|
||||
} catch (const note_decryption_failed &err) {
|
||||
// Couldn't decrypt with this decryptor
|
||||
} catch (const std::exception &exc) {
|
||||
// Unexpected failure
|
||||
@@ -2463,7 +2456,7 @@ bool CWallet::SelectCoinsMinConf(const CAmount& nTargetValue, int nConfMine, int
|
||||
bool CWallet::SelectCoins(const CAmount& nTargetValue, set<pair<const CWalletTx*,unsigned int> >& setCoinsRet, CAmount& nValueRet, bool& fOnlyCoinbaseCoinsRet, bool& fNeedCoinbaseCoinsRet, const CCoinControl* coinControl,uint64_t *interestp) const
|
||||
{
|
||||
// Output parameter fOnlyCoinbaseCoinsRet is set to true when the only available coins are coinbase utxos.
|
||||
uint64_t tmp,interest = 0;
|
||||
uint64_t tmp,interest = 0; int32_t retval;
|
||||
if ( interestp == 0 )
|
||||
{
|
||||
interestp = &tmp;
|
||||
@@ -2502,13 +2495,13 @@ bool CWallet::SelectCoins(const CAmount& nTargetValue, set<pair<const CWalletTx*
|
||||
fNeedCoinbaseCoinsRet = (valueWithCoinbase >= nTargetValue);
|
||||
}
|
||||
}
|
||||
// coin control -> return all selected outputs (we want all to go into the transaction for sure)
|
||||
if (coinControl && coinControl->HasSelected())
|
||||
// coin control -> return all selected outputs (we want all selected to go into the transaction for sure)
|
||||
if (coinControl && coinControl->HasSelected() && !coinControl->fAllowOtherInputs)
|
||||
{
|
||||
BOOST_FOREACH(const COutput& out, vCoins)
|
||||
{
|
||||
if(!out.fSpendable)
|
||||
continue;
|
||||
if (!out.fSpendable)
|
||||
continue;
|
||||
nValueRet += out.tx->vout[out.i].nValue;
|
||||
if ( KOMODO_EXCHANGEWALLET == 0 )
|
||||
*interestp += out.tx->vout[out.i].interest;
|
||||
@@ -2516,30 +2509,119 @@ bool CWallet::SelectCoins(const CAmount& nTargetValue, set<pair<const CWalletTx*
|
||||
}
|
||||
return (nValueRet >= nTargetValue);
|
||||
}
|
||||
//fprintf(stderr,"nValueRet %8f vs target %.8f\n",(double)nValueRet/COIN,(double)nTargetValue/COIN);
|
||||
if ( SelectCoinsMinConf(nTargetValue, 1, 6, vCoins, setCoinsRet, nValueRet,&interest) != 0 )
|
||||
// calculate value from preset inputs and store them
|
||||
set<pair<const CWalletTx*, uint32_t> > setPresetCoins;
|
||||
CAmount nValueFromPresetInputs = 0;
|
||||
|
||||
std::vector<COutPoint> vPresetInputs;
|
||||
if (coinControl)
|
||||
coinControl->ListSelected(vPresetInputs);
|
||||
BOOST_FOREACH(const COutPoint& outpoint, vPresetInputs)
|
||||
{
|
||||
map<uint256, CWalletTx>::const_iterator it = mapWallet.find(outpoint.hash);
|
||||
if (it != mapWallet.end())
|
||||
{
|
||||
const CWalletTx* pcoin = &it->second;
|
||||
// Clearly invalid input, fail
|
||||
if (pcoin->vout.size() <= outpoint.n)
|
||||
return false;
|
||||
nValueFromPresetInputs += pcoin->vout[outpoint.n].nValue;
|
||||
if ( KOMODO_EXCHANGEWALLET == 0 )
|
||||
nValueFromPresetInputs += pcoin->vout[outpoint.n].interest;
|
||||
setPresetCoins.insert(make_pair(pcoin, outpoint.n));
|
||||
} else
|
||||
return false; // TODO: Allow non-wallet inputs
|
||||
}
|
||||
|
||||
// remove preset inputs from vCoins
|
||||
for (vector<COutput>::iterator it = vCoins.begin(); it != vCoins.end() && coinControl && coinControl->HasSelected();)
|
||||
{
|
||||
if (setPresetCoins.count(make_pair(it->tx, it->i)))
|
||||
it = vCoins.erase(it);
|
||||
else
|
||||
++it;
|
||||
}
|
||||
retval = false;
|
||||
if ( nTargetValue <= nValueFromPresetInputs )
|
||||
retval = true;
|
||||
else if ( SelectCoinsMinConf(nTargetValue, 1, 6, vCoins, setCoinsRet, nValueRet,&interest) != 0 )
|
||||
{
|
||||
*interestp += interest;
|
||||
return(true);
|
||||
retval = true;
|
||||
}
|
||||
else if ( SelectCoinsMinConf(nTargetValue, 1, 1, vCoins, setCoinsRet, nValueRet,&interest) != 0 )
|
||||
{
|
||||
*interestp += interest;
|
||||
return(true);
|
||||
retval = true;
|
||||
}
|
||||
else if ( bSpendZeroConfChange && SelectCoinsMinConf(nTargetValue, 0, 1, vCoins, setCoinsRet, nValueRet,&interest) != 0 )
|
||||
{
|
||||
*interestp += interest;
|
||||
return(true);
|
||||
retval = true;
|
||||
}
|
||||
return(false);
|
||||
|
||||
//return (SelectCoinsMinConf(nTargetValue, 1, 6, vCoins, setCoinsRet, nValueRet,interestp) ||
|
||||
// SelectCoinsMinConf(nTargetValue, 1, 1, vCoins, setCoinsRet, nValueRet,interestp) ||
|
||||
// (bSpendZeroConfChange && SelectCoinsMinConf(nTargetValue, 0, 1, vCoins, setCoinsRet, nValueRet,interestp)));
|
||||
/*bool res = nTargetValue <= nValueFromPresetInputs ||
|
||||
SelectCoinsMinConf(nTargetValue - nValueFromPresetInputs, 1, 6, vCoins, setCoinsRet, nValueRet) ||
|
||||
SelectCoinsMinConf(nTargetValue - nValueFromPresetInputs, 1, 1, vCoins, setCoinsRet, nValueRet) ||
|
||||
(bSpendZeroConfChange && SelectCoinsMinConf(nTargetValue - nValueFromPresetInputs, 0, 1, vCoins, setCoinsRet, nValueRet));*/
|
||||
|
||||
// because SelectCoinsMinConf clears the setCoinsRet, we now add the possible inputs to the coinset
|
||||
setCoinsRet.insert(setPresetCoins.begin(), setPresetCoins.end());
|
||||
|
||||
// add preset inputs to the total value selected
|
||||
nValueRet += nValueFromPresetInputs;
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
bool CWallet::CreateTransaction(const vector<CRecipient>& vecSend,
|
||||
CWalletTx& wtxNew, CReserveKey& reservekey, CAmount& nFeeRet, int& nChangePosRet, std::string& strFailReason, const CCoinControl* coinControl)
|
||||
bool CWallet::FundTransaction(CMutableTransaction& tx, CAmount &nFeeRet, int& nChangePosRet, std::string& strFailReason)
|
||||
{
|
||||
vector<CRecipient> vecSend;
|
||||
|
||||
// Turn the txout set into a CRecipient vector
|
||||
BOOST_FOREACH(const CTxOut& txOut, tx.vout)
|
||||
{
|
||||
CRecipient recipient = {txOut.scriptPubKey, txOut.nValue, false};
|
||||
vecSend.push_back(recipient);
|
||||
}
|
||||
|
||||
CCoinControl coinControl;
|
||||
coinControl.fAllowOtherInputs = true;
|
||||
BOOST_FOREACH(const CTxIn& txin, tx.vin)
|
||||
coinControl.Select(txin.prevout);
|
||||
|
||||
CReserveKey reservekey(this);
|
||||
CWalletTx wtx;
|
||||
if (!CreateTransaction(vecSend, wtx, reservekey, nFeeRet, nChangePosRet, strFailReason, &coinControl, false))
|
||||
return false;
|
||||
|
||||
if (nChangePosRet != -1)
|
||||
tx.vout.insert(tx.vout.begin() + nChangePosRet, wtx.vout[nChangePosRet]);
|
||||
|
||||
// Add new txins (keeping original txin scriptSig/order)
|
||||
BOOST_FOREACH(const CTxIn& txin, wtx.vin)
|
||||
{
|
||||
bool found = false;
|
||||
BOOST_FOREACH(const CTxIn& origTxIn, tx.vin)
|
||||
{
|
||||
if (txin.prevout.hash == origTxIn.prevout.hash && txin.prevout.n == origTxIn.prevout.n)
|
||||
{
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!found)
|
||||
tx.vin.push_back(txin);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CWallet::CreateTransaction(const vector<CRecipient>& vecSend, CWalletTx& wtxNew, CReserveKey& reservekey, CAmount& nFeeRet,
|
||||
int& nChangePosRet, std::string& strFailReason, const CCoinControl* coinControl, bool sign)
|
||||
{
|
||||
uint64_t interest2,interest = 0; CAmount nValue = 0; unsigned int nSubtractFeeFromAmount = 0;
|
||||
BOOST_FOREACH (const CRecipient& recipient, vecSend)
|
||||
@@ -2774,23 +2856,43 @@ fprintf(stderr,"wallet change %.8f (%.8f - %.8f) interest %.8f interest2 %.8f to
|
||||
|
||||
// Sign
|
||||
int nIn = 0;
|
||||
CTransaction txNewConst(txNew);
|
||||
BOOST_FOREACH(const PAIRTYPE(const CWalletTx*,unsigned int)& coin, setCoins)
|
||||
if (!SignSignature(*this, *coin.first, txNew, nIn++))
|
||||
{
|
||||
bool signSuccess;
|
||||
const CScript& scriptPubKey = coin.first->vout[coin.second].scriptPubKey;
|
||||
CScript& scriptSigRes = txNew.vin[nIn].scriptSig;
|
||||
if (sign)
|
||||
signSuccess = ProduceSignature(TransactionSignatureCreator(this, &txNewConst, nIn, SIGHASH_ALL), scriptPubKey, scriptSigRes);
|
||||
else
|
||||
signSuccess = ProduceSignature(DummySignatureCreator(this), scriptPubKey, scriptSigRes);
|
||||
|
||||
if (!signSuccess)
|
||||
{
|
||||
strFailReason = _("Signing transaction failed");
|
||||
return false;
|
||||
}
|
||||
nIn++;
|
||||
}
|
||||
|
||||
unsigned int nBytes = ::GetSerializeSize(txNew, SER_NETWORK, PROTOCOL_VERSION);
|
||||
|
||||
// Remove scriptSigs if we used dummy signatures for fee calculation
|
||||
if (!sign) {
|
||||
BOOST_FOREACH (CTxIn& vin, txNew.vin)
|
||||
vin.scriptSig = CScript();
|
||||
}
|
||||
|
||||
// Embed the constructed transaction data in wtxNew.
|
||||
*static_cast<CTransaction*>(&wtxNew) = CTransaction(txNew);
|
||||
|
||||
// Limit size
|
||||
unsigned int nBytes = ::GetSerializeSize(*(CTransaction*)&wtxNew, SER_NETWORK, PROTOCOL_VERSION);
|
||||
if (nBytes >= MAX_TX_SIZE)
|
||||
{
|
||||
strFailReason = _("Transaction too large");
|
||||
return false;
|
||||
}
|
||||
|
||||
dPriority = wtxNew.ComputePriority(dPriority, nBytes);
|
||||
|
||||
// Can we complete this as a free transaction?
|
||||
@@ -3289,7 +3391,7 @@ set< set<CTxDestination> > CWallet::GetAddressGroupings()
|
||||
return ret;
|
||||
}
|
||||
|
||||
set<CTxDestination> CWallet::GetAccountAddresses(string strAccount) const
|
||||
std::set<CTxDestination> CWallet::GetAccountAddresses(const std::string& strAccount) const
|
||||
{
|
||||
LOCK(cs_wallet);
|
||||
set<CTxDestination> result;
|
||||
@@ -3699,9 +3801,12 @@ void CWallet::GetFilteredNotes(std::vector<CNotePlaintextEntry> & outEntries, st
|
||||
|
||||
outEntries.push_back(CNotePlaintextEntry{jsop, plaintext});
|
||||
|
||||
} catch (const std::exception &) {
|
||||
} catch (const note_decryption_failed &err) {
|
||||
// Couldn't decrypt with this spending key
|
||||
throw std::runtime_error(strprintf("Could not decrypt note for payment address %s", CZCPaymentAddress(pa).ToString()));
|
||||
} catch (const std::exception &exc) {
|
||||
// Unexpected failure
|
||||
throw std::runtime_error(strprintf("Error while decrypting note for payment address %s: %s", CZCPaymentAddress(pa).ToString(), exc.what()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -713,7 +713,7 @@ public:
|
||||
SetNull();
|
||||
}
|
||||
|
||||
CWallet(std::string strWalletFileIn)
|
||||
CWallet(const std::string& strWalletFileIn)
|
||||
{
|
||||
SetNull();
|
||||
|
||||
@@ -917,8 +917,9 @@ public:
|
||||
CAmount GetWatchOnlyBalance() const;
|
||||
CAmount GetUnconfirmedWatchOnlyBalance() const;
|
||||
CAmount GetImmatureWatchOnlyBalance() const;
|
||||
bool CreateTransaction(const std::vector<CRecipient>& vecSend,
|
||||
CWalletTx& wtxNew, CReserveKey& reservekey, CAmount& nFeeRet, int& nChangePosRet, std::string& strFailReason, const CCoinControl *coinControl = NULL);
|
||||
bool FundTransaction(CMutableTransaction& tx, CAmount& nFeeRet, int& nChangePosRet, std::string& strFailReason);
|
||||
bool CreateTransaction(const std::vector<CRecipient>& vecSend, CWalletTx& wtxNew, CReserveKey& reservekey, CAmount& nFeeRet, int& nChangePosRet,
|
||||
std::string& strFailReason, const CCoinControl *coinControl = NULL, bool sign = true);
|
||||
bool CommitTransaction(CWalletTx& wtxNew, CReserveKey& reservekey);
|
||||
|
||||
static CFeeRate minTxFee;
|
||||
@@ -936,7 +937,7 @@ public:
|
||||
std::set< std::set<CTxDestination> > GetAddressGroupings();
|
||||
std::map<CTxDestination, CAmount> GetAddressBalances();
|
||||
|
||||
std::set<CTxDestination> GetAccountAddresses(std::string strAccount) const;
|
||||
std::set<CTxDestination> GetAccountAddresses(const std::string& strAccount) const;
|
||||
|
||||
boost::optional<uint256> GetNoteNullifier(
|
||||
const JSDescription& jsdesc,
|
||||
@@ -1064,7 +1065,7 @@ public:
|
||||
}
|
||||
|
||||
void ReturnKey();
|
||||
bool GetReservedKey(CPubKey &pubkey);
|
||||
virtual bool GetReservedKey(CPubKey &pubkey);
|
||||
void KeepKey();
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user