Initial merge

This commit is contained in:
jl777
2017-03-30 04:35:16 +03:00
633 changed files with 11230 additions and 184263 deletions

View File

@@ -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;
}