Randomize JoinSplits in z_sendmany
This commit is contained in:
@@ -29,6 +29,22 @@
|
|||||||
|
|
||||||
using namespace libzcash;
|
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(
|
AsyncRPCOperation_sendmany::AsyncRPCOperation_sendmany(
|
||||||
std::string fromAddress,
|
std::string fromAddress,
|
||||||
std::vector<SendManyRecipient> tOutputs,
|
std::vector<SendManyRecipient> tOutputs,
|
||||||
@@ -372,6 +388,7 @@ bool AsyncRPCOperation_sendmany::main_impl() {
|
|||||||
*/
|
*/
|
||||||
Object obj;
|
Object obj;
|
||||||
CAmount jsChange = 0; // this is updated after each joinsplit
|
CAmount jsChange = 0; // this is updated after each joinsplit
|
||||||
|
int changeOutputIndex = -1; // this is updated after each joinsplit if jsChange > 0
|
||||||
bool minersFeeProcessed = false;
|
bool minersFeeProcessed = false;
|
||||||
|
|
||||||
if (t_outputs_total > 0) {
|
if (t_outputs_total > 0) {
|
||||||
@@ -429,6 +446,10 @@ bool AsyncRPCOperation_sendmany::main_impl() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
obj = perform_joinsplit(info, outPoints);
|
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;
|
boost::unordered_map<uint256, ZCIncrementalMerkleTree, CCoinsKeyHasher> intermediates;
|
||||||
std::vector<uint256> previousCommitments;
|
std::vector<uint256> previousCommitments;
|
||||||
|
|
||||||
// NOTE: Randomization of input and output order could break this in future
|
|
||||||
const int changeOutputIndex = 1;
|
|
||||||
|
|
||||||
while (zOutputsDeque.size() > 0) {
|
while (zOutputsDeque.size() > 0) {
|
||||||
AsyncJoinSplitInfo info;
|
AsyncJoinSplitInfo info;
|
||||||
info.vpub_old = 0;
|
info.vpub_old = 0;
|
||||||
@@ -645,6 +663,10 @@ bool AsyncRPCOperation_sendmany::main_impl() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
obj = perform_joinsplit(info, witnesses, jsAnchor);
|
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.
|
// 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_,
|
joinSplitPubKey_,
|
||||||
anchor,
|
anchor,
|
||||||
{info.vjsin[0], info.vjsin[1]},
|
inputs,
|
||||||
{info.vjsout[0], info.vjsout[1]},
|
outputs,
|
||||||
|
inputMap,
|
||||||
|
outputMap,
|
||||||
info.vpub_old,
|
info.vpub_old,
|
||||||
info.vpub_new,
|
info.vpub_new,
|
||||||
!this->testmode);
|
!this->testmode);
|
||||||
@@ -910,10 +941,21 @@ Object AsyncRPCOperation_sendmany::perform_joinsplit(
|
|||||||
encryptedNote2 = HexStr(ss2.begin(), ss2.end());
|
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;
|
Object obj;
|
||||||
obj.push_back(Pair("encryptednote1", encryptedNote1));
|
obj.push_back(Pair("encryptednote1", encryptedNote1));
|
||||||
obj.push_back(Pair("encryptednote2", encryptedNote2));
|
obj.push_back(Pair("encryptednote2", encryptedNote2));
|
||||||
obj.push_back(Pair("rawtxn", HexStr(ss.begin(), ss.end())));
|
obj.push_back(Pair("rawtxn", HexStr(ss.begin(), ss.end())));
|
||||||
|
obj.push_back(Pair("inputmap", arrInputMap));
|
||||||
|
obj.push_back(Pair("outputmap", arrOutputMap));
|
||||||
return obj;
|
return obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user