Randomize JoinSplits in z_sendmany
This commit is contained in:
parent
7f0aa74666
commit
2eeb6bebde
|
@ -29,6 +29,22 @@
|
|||
|
||||
using namespace libzcash;
|
||||
|
||||
int find_output(Object obj, int n) {
|
||||
Value outputMapValue = find_value(obj, "outputmap");
|
||||
if (outputMapValue.type() != array_type) {
|
||||
throw JSONRPCError(RPC_WALLET_ERROR, "Missing outputmap for JoinSplit operation");
|
||||
}
|
||||
|
||||
Array outputMap = outputMapValue.get_array();
|
||||
for (size_t i = 0; i < outputMap.size(); i++) {
|
||||
if (outputMap[i] == n) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
AsyncRPCOperation_sendmany::AsyncRPCOperation_sendmany(
|
||||
std::string fromAddress,
|
||||
std::vector<SendManyRecipient> tOutputs,
|
||||
|
@ -372,6 +388,7 @@ bool AsyncRPCOperation_sendmany::main_impl() {
|
|||
*/
|
||||
Object obj;
|
||||
CAmount jsChange = 0; // this is updated after each joinsplit
|
||||
int changeOutputIndex = -1; // this is updated after each joinsplit if jsChange > 0
|
||||
bool minersFeeProcessed = false;
|
||||
|
||||
if (t_outputs_total > 0) {
|
||||
|
@ -429,6 +446,10 @@ bool AsyncRPCOperation_sendmany::main_impl() {
|
|||
}
|
||||
|
||||
obj = perform_joinsplit(info, outPoints);
|
||||
|
||||
if (jsChange > 0) {
|
||||
changeOutputIndex = find_output(obj, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -443,9 +464,6 @@ bool AsyncRPCOperation_sendmany::main_impl() {
|
|||
boost::unordered_map<uint256, ZCIncrementalMerkleTree, CCoinsKeyHasher> intermediates;
|
||||
std::vector<uint256> previousCommitments;
|
||||
|
||||
// NOTE: Randomization of input and output order could break this in future
|
||||
const int changeOutputIndex = 1;
|
||||
|
||||
while (zOutputsDeque.size() > 0) {
|
||||
AsyncJoinSplitInfo info;
|
||||
info.vpub_old = 0;
|
||||
|
@ -645,6 +663,10 @@ bool AsyncRPCOperation_sendmany::main_impl() {
|
|||
}
|
||||
|
||||
obj = perform_joinsplit(info, witnesses, jsAnchor);
|
||||
|
||||
if (jsChange > 0) {
|
||||
changeOutputIndex = find_output(obj, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -845,11 +867,20 @@ Object AsyncRPCOperation_sendmany::perform_joinsplit(
|
|||
);
|
||||
|
||||
// Generate the proof, this can take over a minute.
|
||||
JSDescription jsdesc(*pzcashParams,
|
||||
boost::array<libzcash::JSInput, ZC_NUM_JS_INPUTS> inputs
|
||||
{info.vjsin[0], info.vjsin[1]};
|
||||
boost::array<libzcash::JSOutput, ZC_NUM_JS_OUTPUTS> outputs
|
||||
{info.vjsout[0], info.vjsout[1]};
|
||||
boost::array<size_t, ZC_NUM_JS_INPUTS> inputMap;
|
||||
boost::array<size_t, ZC_NUM_JS_OUTPUTS> outputMap;
|
||||
JSDescription jsdesc = JSDescription::Randomized(
|
||||
*pzcashParams,
|
||||
joinSplitPubKey_,
|
||||
anchor,
|
||||
{info.vjsin[0], info.vjsin[1]},
|
||||
{info.vjsout[0], info.vjsout[1]},
|
||||
inputs,
|
||||
outputs,
|
||||
inputMap,
|
||||
outputMap,
|
||||
info.vpub_old,
|
||||
info.vpub_new,
|
||||
!this->testmode);
|
||||
|
@ -910,10 +941,21 @@ Object AsyncRPCOperation_sendmany::perform_joinsplit(
|
|||
encryptedNote2 = HexStr(ss2.begin(), ss2.end());
|
||||
}
|
||||
|
||||
Array arrInputMap;
|
||||
Array arrOutputMap;
|
||||
for (size_t i = 0; i < ZC_NUM_JS_INPUTS; i++) {
|
||||
arrInputMap.push_back(inputMap[i]);
|
||||
}
|
||||
for (size_t i = 0; i < ZC_NUM_JS_OUTPUTS; i++) {
|
||||
arrOutputMap.push_back(outputMap[i]);
|
||||
}
|
||||
|
||||
Object obj;
|
||||
obj.push_back(Pair("encryptednote1", encryptedNote1));
|
||||
obj.push_back(Pair("encryptednote2", encryptedNote2));
|
||||
obj.push_back(Pair("rawtxn", HexStr(ss.begin(), ss.end())));
|
||||
obj.push_back(Pair("inputmap", arrInputMap));
|
||||
obj.push_back(Pair("outputmap", arrOutputMap));
|
||||
return obj;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue