Store inputs and outputs by reference in JSDescriptionInfo

When creating randomized JoinSplits, the caller passes in references to
arrays in which the mapping from original to randomised position is
stored. However, in the old JSDescription constructors, the caller also
passed the inputs and outputs themselves by reference, and those arrays
were also randomised. The JSDescriptionInfo constructor was instead
taking these by value, meaning that its internal copies were being
randomised, but not the caller's arrays. This caused the Sprout payment
disclosure logic to (with 1/2 probability) store the incorrect output
in a payment disclosure key.

This commit restores the previous behaviour, by storing references to
the input and output arrays in JSDescriptionInfo instead of copying them.
This commit is contained in:
Jack Grigg 2020-12-21 02:18:35 +00:00
parent 6c280abfac
commit 2c17d1e274
4 changed files with 19 additions and 12 deletions

View File

@ -25,8 +25,8 @@ using namespace libzcash;
// Make the Groth proof for a Sprout statement,
// and store the result in a JSDescription object.
JSDescription makeSproutProof(
const std::array<JSInput, 2>& inputs,
const std::array<JSOutput, 2>& outputs,
std::array<JSInput, 2>& inputs,
std::array<JSOutput, 2>& outputs,
const Ed25519VerificationKey& joinSplitPubKey,
uint64_t vpub_old,
uint64_t vpub_new,

View File

@ -53,16 +53,17 @@ struct OutputDescriptionInfo {
struct JSDescriptionInfo {
Ed25519VerificationKey joinSplitPubKey;
uint256 anchor;
std::array<libzcash::JSInput, ZC_NUM_JS_INPUTS> inputs;
std::array<libzcash::JSOutput, ZC_NUM_JS_OUTPUTS> outputs;
// We store references to these so they are correctly randomised for the caller.
std::array<libzcash::JSInput, ZC_NUM_JS_INPUTS>& inputs;
std::array<libzcash::JSOutput, ZC_NUM_JS_OUTPUTS>& outputs;
CAmount vpub_old;
CAmount vpub_new;
JSDescriptionInfo(
Ed25519VerificationKey joinSplitPubKey,
uint256 anchor,
std::array<libzcash::JSInput, ZC_NUM_JS_INPUTS> inputs,
std::array<libzcash::JSOutput, ZC_NUM_JS_OUTPUTS> outputs,
std::array<libzcash::JSInput, ZC_NUM_JS_INPUTS>& inputs,
std::array<libzcash::JSOutput, ZC_NUM_JS_OUTPUTS>& outputs,
CAmount vpub_old,
CAmount vpub_new) : joinSplitPubKey(joinSplitPubKey), anchor(anchor), inputs(inputs), outputs(outputs), vpub_old(vpub_old), vpub_new(vpub_new) {}

View File

@ -2777,10 +2777,12 @@ UniValue zc_sample_joinsplit(const UniValue& params, bool fHelp)
Ed25519VerificationKey joinSplitPubKey;
uint256 anchor = SproutMerkleTree().root();
std::array<libzcash::JSInput, ZC_NUM_JS_INPUTS> inputs({JSInput(), JSInput()});
std::array<libzcash::JSOutput, ZC_NUM_JS_OUTPUTS> outputs({JSOutput(), JSOutput()});
auto samplejoinsplit = JSDescriptionInfo(joinSplitPubKey,
anchor,
{JSInput(), JSInput()},
{JSOutput(), JSOutput()},
inputs,
outputs,
0,
0).BuildDeterministic();
@ -3152,10 +3154,12 @@ UniValue zc_raw_joinsplit(const UniValue& params, bool fHelp)
mtx.nVersionGroupId = SAPLING_VERSION_GROUP_ID;
mtx.joinSplitPubKey = joinSplitPubKey;
std::array<libzcash::JSInput, ZC_NUM_JS_INPUTS> jsInputs({vjsin[0], vjsin[1]});
std::array<libzcash::JSOutput, ZC_NUM_JS_OUTPUTS> jsIutputs({vjsout[0], vjsout[1]});
auto jsdesc = JSDescriptionInfo(joinSplitPubKey,
anchor,
{vjsin[0], vjsin[1]},
{vjsout[0], vjsout[1]},
jsInputs,
jsIutputs,
vpub_old,
vpub_new).BuildDeterministic();

View File

@ -101,13 +101,15 @@ double benchmark_create_joinsplit()
/* Get the anchor of an empty commitment tree. */
uint256 anchor = SproutMerkleTree().root();
std::array<libzcash::JSInput, ZC_NUM_JS_INPUTS> inputs({JSInput(), JSInput()});
std::array<libzcash::JSOutput, ZC_NUM_JS_OUTPUTS> outputs({JSOutput(), JSOutput()});
struct timeval tv_start;
timer_start(tv_start);
auto jsdesc = JSDescriptionInfo(joinSplitPubKey,
anchor,
{JSInput(), JSInput()},
{JSOutput(), JSOutput()},
inputs,
outputs,
0,
0).BuildDeterministic();
double ret = timer_stop(tv_start);