more desprout, ugh
This commit is contained in:
@@ -1,3 +1,4 @@
|
||||
// Copyright (c) 2019-2020 The Hush developers
|
||||
#include "JoinSplit.hpp"
|
||||
#include "prf.h"
|
||||
#include "sodium.h"
|
||||
@@ -28,6 +29,7 @@ public:
|
||||
JoinSplitCircuit() {}
|
||||
~JoinSplitCircuit() {}
|
||||
|
||||
/*
|
||||
SproutProof prove(
|
||||
const std::array<JSInput, NumInputs>& inputs,
|
||||
const std::array<JSOutput, NumOutputs>& outputs,
|
||||
@@ -45,169 +47,13 @@ public:
|
||||
bool computeProof,
|
||||
uint256 *out_esk // Payment disclosure
|
||||
) {
|
||||
if (vpub_old > MAX_MONEY) {
|
||||
throw std::invalid_argument("nonsensical vpub_old value");
|
||||
}
|
||||
|
||||
if (vpub_new > MAX_MONEY) {
|
||||
throw std::invalid_argument("nonsensical vpub_new value");
|
||||
}
|
||||
|
||||
uint64_t lhs_value = vpub_old;
|
||||
uint64_t rhs_value = vpub_new;
|
||||
|
||||
for (size_t i = 0; i < NumInputs; i++) {
|
||||
// Sanity checks of input
|
||||
{
|
||||
// If note has nonzero value
|
||||
if (inputs[i].note.value() != 0) {
|
||||
// The witness root must equal the input root.
|
||||
if (inputs[i].witness.root() != rt) {
|
||||
throw std::invalid_argument("joinsplit not anchored to the correct root");
|
||||
}
|
||||
|
||||
// The tree must witness the correct element
|
||||
if (inputs[i].note.cm() != inputs[i].witness.element()) {
|
||||
throw std::invalid_argument("witness of wrong element for joinsplit input");
|
||||
}
|
||||
}
|
||||
|
||||
// Ensure we have the key to this note.
|
||||
if (inputs[i].note.a_pk != inputs[i].key.address().a_pk) {
|
||||
throw std::invalid_argument("input note not authorized to spend with given key");
|
||||
}
|
||||
|
||||
// Balance must be sensical
|
||||
if (inputs[i].note.value() > MAX_MONEY) {
|
||||
throw std::invalid_argument("nonsensical input note value");
|
||||
}
|
||||
|
||||
lhs_value += inputs[i].note.value();
|
||||
|
||||
if (lhs_value > MAX_MONEY) {
|
||||
throw std::invalid_argument("nonsensical left hand size of joinsplit balance");
|
||||
}
|
||||
}
|
||||
|
||||
// Compute nullifier of input
|
||||
out_nullifiers[i] = inputs[i].nullifier();
|
||||
}
|
||||
|
||||
// Sample randomSeed
|
||||
out_randomSeed = random_uint256();
|
||||
|
||||
// Compute h_sig
|
||||
uint256 h_sig = this->h_sig(out_randomSeed, out_nullifiers, joinSplitPubKey);
|
||||
|
||||
// Sample phi
|
||||
uint252 phi = random_uint252();
|
||||
|
||||
// Compute notes for outputs
|
||||
for (size_t i = 0; i < NumOutputs; i++) {
|
||||
// Sanity checks of output
|
||||
{
|
||||
if (outputs[i].value > MAX_MONEY) {
|
||||
throw std::invalid_argument("nonsensical output value");
|
||||
}
|
||||
|
||||
rhs_value += outputs[i].value;
|
||||
|
||||
if (rhs_value > MAX_MONEY) {
|
||||
throw std::invalid_argument("nonsensical right hand side of joinsplit balance");
|
||||
}
|
||||
}
|
||||
|
||||
// Sample r
|
||||
uint256 r = random_uint256();
|
||||
|
||||
out_notes[i] = outputs[i].note(phi, r, i, h_sig);
|
||||
}
|
||||
|
||||
if (lhs_value != rhs_value) {
|
||||
throw std::invalid_argument("invalid joinsplit balance");
|
||||
}
|
||||
|
||||
// Compute the output commitments
|
||||
for (size_t i = 0; i < NumOutputs; i++) {
|
||||
out_commitments[i] = out_notes[i].cm();
|
||||
}
|
||||
|
||||
// Encrypt the ciphertexts containing the note
|
||||
// plaintexts to the recipients of the value.
|
||||
{
|
||||
ZCNoteEncryption encryptor(h_sig);
|
||||
|
||||
for (size_t i = 0; i < NumOutputs; i++) {
|
||||
SproutNotePlaintext pt(out_notes[i], outputs[i].memo);
|
||||
|
||||
out_ciphertexts[i] = pt.encrypt(encryptor, outputs[i].addr.pk_enc);
|
||||
}
|
||||
|
||||
out_ephemeralKey = encryptor.get_epk();
|
||||
|
||||
// !!! Payment disclosure START
|
||||
if (out_esk != nullptr) {
|
||||
*out_esk = encryptor.get_esk();
|
||||
}
|
||||
// !!! Payment disclosure END
|
||||
}
|
||||
|
||||
// Authenticate h_sig with each of the input
|
||||
// spending keys, producing macs which protect
|
||||
// against malleability.
|
||||
for (size_t i = 0; i < NumInputs; i++) {
|
||||
out_macs[i] = PRF_pk(inputs[i].key, i, h_sig);
|
||||
}
|
||||
|
||||
if (!computeProof) {
|
||||
return GrothProof();
|
||||
}
|
||||
|
||||
GrothProof proof;
|
||||
|
||||
CDataStream ss1(SER_NETWORK, PROTOCOL_VERSION);
|
||||
ss1 << inputs[0].witness.path();
|
||||
std::vector<unsigned char> auth1(ss1.begin(), ss1.end());
|
||||
|
||||
CDataStream ss2(SER_NETWORK, PROTOCOL_VERSION);
|
||||
ss2 << inputs[1].witness.path();
|
||||
std::vector<unsigned char> auth2(ss2.begin(), ss2.end());
|
||||
|
||||
librustzcash_sprout_prove(
|
||||
proof.begin(),
|
||||
|
||||
phi.begin(),
|
||||
rt.begin(),
|
||||
h_sig.begin(),
|
||||
|
||||
inputs[0].key.begin(),
|
||||
inputs[0].note.value(),
|
||||
inputs[0].note.rho.begin(),
|
||||
inputs[0].note.r.begin(),
|
||||
auth1.data(),
|
||||
|
||||
inputs[1].key.begin(),
|
||||
inputs[1].note.value(),
|
||||
inputs[1].note.rho.begin(),
|
||||
inputs[1].note.r.begin(),
|
||||
auth2.data(),
|
||||
|
||||
out_notes[0].a_pk.begin(),
|
||||
out_notes[0].value(),
|
||||
out_notes[0].r.begin(),
|
||||
|
||||
out_notes[1].a_pk.begin(),
|
||||
out_notes[1].value(),
|
||||
out_notes[1].r.begin(),
|
||||
|
||||
vpub_old,
|
||||
vpub_new
|
||||
);
|
||||
|
||||
return proof;
|
||||
}
|
||||
*/
|
||||
};
|
||||
|
||||
/*
|
||||
template<size_t NumInputs, size_t NumOutputs>
|
||||
JoinSplit<NumInputs, NumOutputs>* JoinSplit<NumInputs, NumOutputs>::Prepared()
|
||||
{
|
||||
@@ -250,4 +96,5 @@ uint256 JoinSplit<NumInputs, NumOutputs>::h_sig(
|
||||
template class JoinSplit<ZC_NUM_JS_INPUTS,
|
||||
ZC_NUM_JS_OUTPUTS>;
|
||||
|
||||
*/
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user