Merge pull request #1031 from zcash/sapling-prover-cleanups
Sapling prover cleanups
This commit is contained in:
commit
bf8868ca91
|
@ -105,7 +105,10 @@ where
|
|||
/// Parameters:
|
||||
/// * `wallet_db`: A read/write reference to the wallet database
|
||||
/// * `params`: Consensus parameters
|
||||
/// * `prover`: The [`sapling::TxProver`] to use in constructing the shielded transaction.
|
||||
/// * `spend_prover`: The [`sapling::SpendProver`] to use in constructing the shielded
|
||||
/// transaction.
|
||||
/// * `output_prover`: The [`sapling::OutputProver`] to use in constructing the shielded
|
||||
/// transaction.
|
||||
/// * `usk`: The unified spending key that controls the funds that will be spent
|
||||
/// in the resulting transaction. This procedure will return an error if the
|
||||
/// USK does not correspond to an account known to the wallet.
|
||||
|
@ -182,7 +185,9 @@ where
|
|||
/// # }
|
||||
/// # }
|
||||
/// ```
|
||||
/// [`sapling::TxProver`]: zcash_primitives::sapling::prover::TxProver
|
||||
///
|
||||
/// [`sapling::SpendProver`]: zcash_primitives::sapling::prover::SpendProver
|
||||
/// [`sapling::OutputProver`]: zcash_primitives::sapling::prover::OutputProver
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
#[allow(clippy::type_complexity)]
|
||||
#[deprecated(
|
||||
|
@ -276,7 +281,10 @@ where
|
|||
/// Parameters:
|
||||
/// * `wallet_db`: A read/write reference to the wallet database
|
||||
/// * `params`: Consensus parameters
|
||||
/// * `prover`: The [`sapling::TxProver`] to use in constructing the shielded transaction.
|
||||
/// * `spend_prover`: The [`sapling::SpendProver`] to use in constructing the shielded
|
||||
/// transaction.
|
||||
/// * `output_prover`: The [`sapling::OutputProver`] to use in constructing the shielded
|
||||
/// transaction.
|
||||
/// * `input_selector`: The [`InputSelector`] that will be used to select available
|
||||
/// inputs from the wallet database, choose change amounts and compute required
|
||||
/// transaction fees.
|
||||
|
@ -292,7 +300,8 @@ where
|
|||
/// spent. A value of 10 confirmations is recommended and 0-conf transactions are
|
||||
/// not supported.
|
||||
///
|
||||
/// [`sapling::TxProver`]: zcash_primitives::sapling::prover::TxProver
|
||||
/// [`sapling::SpendProver`]: zcash_primitives::sapling::prover::SpendProver
|
||||
/// [`sapling::OutputProver`]: zcash_primitives::sapling::prover::OutputProver
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
#[allow(clippy::type_complexity)]
|
||||
pub fn spend<DbT, ParamsT, InputsT>(
|
||||
|
@ -764,7 +773,10 @@ where
|
|||
/// Parameters:
|
||||
/// * `wallet_db`: A read/write reference to the wallet database
|
||||
/// * `params`: Consensus parameters
|
||||
/// * `prover`: The [`sapling::TxProver`] to use in constructing the shielded transaction.
|
||||
/// * `spend_prover`: The [`sapling::SpendProver`] to use in constructing the shielded
|
||||
/// transaction.
|
||||
/// * `output_prover`: The [`sapling::OutputProver`] to use in constructing the shielded
|
||||
/// transaction.
|
||||
/// * `input_selector`: The [`InputSelector`] to for note selection and change and fee
|
||||
/// determination
|
||||
/// * `usk`: The unified spending key that will be used to detect and spend transparent UTXOs,
|
||||
|
@ -781,7 +793,8 @@ where
|
|||
/// spent. A value of 10 confirmations is recommended and 0-conf transactions are
|
||||
/// not supported.
|
||||
///
|
||||
/// [`sapling::TxProver`]: zcash_primitives::sapling::prover::TxProver
|
||||
/// [`sapling::SpendProver`]: zcash_primitives::sapling::prover::SpendProver
|
||||
/// [`sapling::OutputProver`]: zcash_primitives::sapling::prover::OutputProver
|
||||
#[cfg(feature = "transparent-inputs")]
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
#[allow(clippy::type_complexity)]
|
||||
|
|
|
@ -42,7 +42,7 @@ and this library adheres to Rust's notion of
|
|||
- `P2PKH_STANDARD_INPUT_SIZE`
|
||||
- `P2PKH_STANDARD_OUTPUT_SIZE`
|
||||
- Test helpers, behind the `test-dependencies` feature flag:
|
||||
- `zcash_primitives::prover::mock::{MockSpendProver, MockOutputProver}`
|
||||
- `zcash_primitives::sapling::prover::mock::{MockSpendProver, MockOutputProver}`
|
||||
- Additions related to `zcash_primitive::components::amount::Amount`
|
||||
and `zcash_primitive::components::amount::NonNegativeAmount`:
|
||||
- `impl TryFrom<Amount> for u64`
|
||||
|
|
|
@ -5,11 +5,10 @@ use rand_core::RngCore;
|
|||
use crate::{
|
||||
sapling::{
|
||||
self,
|
||||
redjubjub::{PublicKey, Signature},
|
||||
value::{NoteValue, ValueCommitTrapdoor, ValueCommitment},
|
||||
value::{NoteValue, ValueCommitTrapdoor},
|
||||
MerklePath,
|
||||
},
|
||||
transaction::components::{sapling::GrothProofBytes, Amount, GROTH_PROOF_SIZE},
|
||||
transaction::components::sapling::GrothProofBytes,
|
||||
};
|
||||
|
||||
use super::{Diversifier, PaymentAddress, ProofGenerationKey, Rseed};
|
||||
|
@ -80,73 +79,19 @@ pub trait OutputProver {
|
|||
fn encode_proof(proof: Self::Proof) -> GrothProofBytes;
|
||||
}
|
||||
|
||||
/// Interface for creating zero-knowledge proofs for shielded transactions.
|
||||
pub trait TxProver {
|
||||
/// Type for persisting any necessary context across multiple Sapling proofs.
|
||||
type SaplingProvingContext;
|
||||
|
||||
/// Instantiate a new Sapling proving context.
|
||||
fn new_sapling_proving_context(&self) -> Self::SaplingProvingContext;
|
||||
|
||||
/// Create the value commitment, re-randomized key, and proof for a Sapling
|
||||
/// [`SpendDescription`], while accumulating its value commitment randomness inside
|
||||
/// the context for later use.
|
||||
///
|
||||
/// [`SpendDescription`]: crate::transaction::components::SpendDescription
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
fn spend_proof(
|
||||
&self,
|
||||
ctx: &mut Self::SaplingProvingContext,
|
||||
proof_generation_key: ProofGenerationKey,
|
||||
diversifier: Diversifier,
|
||||
rseed: Rseed,
|
||||
ar: jubjub::Fr,
|
||||
value: u64,
|
||||
anchor: bls12_381::Scalar,
|
||||
merkle_path: sapling::MerklePath,
|
||||
) -> Result<([u8; GROTH_PROOF_SIZE], ValueCommitment, PublicKey), ()>;
|
||||
|
||||
/// Create the value commitment and proof for a Sapling [`OutputDescription`],
|
||||
/// while accumulating its value commitment randomness inside the context for later
|
||||
/// use.
|
||||
///
|
||||
/// [`OutputDescription`]: crate::transaction::components::OutputDescription
|
||||
fn output_proof(
|
||||
&self,
|
||||
ctx: &mut Self::SaplingProvingContext,
|
||||
esk: jubjub::Fr,
|
||||
payment_address: PaymentAddress,
|
||||
rcm: jubjub::Fr,
|
||||
value: u64,
|
||||
) -> ([u8; GROTH_PROOF_SIZE], ValueCommitment);
|
||||
|
||||
/// Create the `bindingSig` for a Sapling transaction. All calls to
|
||||
/// [`TxProver::spend_proof`] and [`TxProver::output_proof`] must be completed before
|
||||
/// calling this function.
|
||||
fn binding_sig(
|
||||
&self,
|
||||
ctx: &mut Self::SaplingProvingContext,
|
||||
value_balance: Amount,
|
||||
sighash: &[u8; 32],
|
||||
) -> Result<Signature, ()>;
|
||||
}
|
||||
|
||||
#[cfg(any(test, feature = "test-dependencies"))]
|
||||
pub mod mock {
|
||||
use ff::Field;
|
||||
use rand_core::OsRng;
|
||||
|
||||
use super::{OutputProver, SpendProver, TxProver};
|
||||
use super::{OutputProver, SpendProver};
|
||||
use crate::{
|
||||
sapling::{
|
||||
self,
|
||||
circuit::ValueCommitmentOpening,
|
||||
constants::SPENDING_KEY_GENERATOR,
|
||||
redjubjub::{PublicKey, Signature},
|
||||
value::{NoteValue, ValueCommitTrapdoor, ValueCommitment},
|
||||
value::{NoteValue, ValueCommitTrapdoor},
|
||||
Diversifier, PaymentAddress, ProofGenerationKey, Rseed,
|
||||
},
|
||||
transaction::components::{sapling::GrothProofBytes, Amount, GROTH_PROOF_SIZE},
|
||||
transaction::components::{sapling::GrothProofBytes, GROTH_PROOF_SIZE},
|
||||
};
|
||||
|
||||
pub struct MockSpendProver;
|
||||
|
@ -230,61 +175,4 @@ pub mod mock {
|
|||
proof
|
||||
}
|
||||
}
|
||||
|
||||
pub struct MockTxProver;
|
||||
|
||||
impl TxProver for MockTxProver {
|
||||
type SaplingProvingContext = ();
|
||||
|
||||
fn new_sapling_proving_context(&self) -> Self::SaplingProvingContext {}
|
||||
|
||||
fn spend_proof(
|
||||
&self,
|
||||
_ctx: &mut Self::SaplingProvingContext,
|
||||
proof_generation_key: ProofGenerationKey,
|
||||
_diversifier: Diversifier,
|
||||
_rcm: Rseed,
|
||||
ar: jubjub::Fr,
|
||||
value: u64,
|
||||
_anchor: bls12_381::Scalar,
|
||||
_merkle_path: sapling::MerklePath,
|
||||
) -> Result<([u8; GROTH_PROOF_SIZE], ValueCommitment, PublicKey), ()> {
|
||||
let mut rng = OsRng;
|
||||
|
||||
let value = NoteValue::from_raw(value);
|
||||
let rcv = ValueCommitTrapdoor::random(&mut rng);
|
||||
let cv = ValueCommitment::derive(value, rcv);
|
||||
|
||||
let rk =
|
||||
PublicKey(proof_generation_key.ak.into()).randomize(ar, SPENDING_KEY_GENERATOR);
|
||||
|
||||
Ok(([0u8; GROTH_PROOF_SIZE], cv, rk))
|
||||
}
|
||||
|
||||
fn output_proof(
|
||||
&self,
|
||||
_ctx: &mut Self::SaplingProvingContext,
|
||||
_esk: jubjub::Fr,
|
||||
_payment_address: PaymentAddress,
|
||||
_rcm: jubjub::Fr,
|
||||
value: u64,
|
||||
) -> ([u8; GROTH_PROOF_SIZE], ValueCommitment) {
|
||||
let mut rng = OsRng;
|
||||
|
||||
let value = NoteValue::from_raw(value);
|
||||
let rcv = ValueCommitTrapdoor::random(&mut rng);
|
||||
let cv = ValueCommitment::derive(value, rcv);
|
||||
|
||||
([0u8; GROTH_PROOF_SIZE], cv)
|
||||
}
|
||||
|
||||
fn binding_sig(
|
||||
&self,
|
||||
_ctx: &mut Self::SaplingProvingContext,
|
||||
_value_balance: Amount,
|
||||
_sighash: &[u8; 32],
|
||||
) -> Result<Signature, ()> {
|
||||
Err(())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,21 +12,14 @@ and this library adheres to Rust's notion of
|
|||
`zcash_proofs::prover::LocalTxProver`
|
||||
|
||||
### Changed
|
||||
- The new `SpendParameters` and `OutputParameters` types are used in the
|
||||
following places:
|
||||
- `zcash_proofs::ZcashParameters::{spend_params, output_params}` fields.
|
||||
- `zcash_proofs::sapling::prover`:
|
||||
- `SaplingProvingContext::{spend_proof, output_proof}` (the `proving_key`
|
||||
arguments).
|
||||
- `zcash_proofs::sapling::prover`:
|
||||
- The `verifying_key` argument `SaplingProvingContext::spend_proof` has been
|
||||
removed. Callers should instead use `SaplingVerifyingContext` to verify
|
||||
proofs after they have been created.
|
||||
- The `zcash_proofs::ZcashParameters::{spend_params, output_params}` fields
|
||||
now have types `SpendParameters` and `OutputParameters` respectively.
|
||||
|
||||
### Removed
|
||||
- `zcash_proofs::circuit::sapling` (moved to `zcash_primitives::sapling::circuit`).
|
||||
- `zcash_proofs::circuit::{ecc, pedersen_hash}`
|
||||
- `zcash_proofs::constants`
|
||||
- `zcash_proofs::sapling::SaplingProvingContext`
|
||||
|
||||
## [0.13.0] - 2023-09-25
|
||||
### Changed
|
||||
|
|
|
@ -6,18 +6,14 @@ use std::path::Path;
|
|||
use zcash_primitives::{
|
||||
sapling::{
|
||||
self,
|
||||
prover::{OutputProver, SpendProver, TxProver},
|
||||
redjubjub::{PublicKey, Signature},
|
||||
value::{NoteValue, ValueCommitTrapdoor, ValueCommitment},
|
||||
prover::{OutputProver, SpendProver},
|
||||
value::{NoteValue, ValueCommitTrapdoor},
|
||||
Diversifier, MerklePath, PaymentAddress, ProofGenerationKey, Rseed,
|
||||
},
|
||||
transaction::components::{sapling::GrothProofBytes, Amount, GROTH_PROOF_SIZE},
|
||||
transaction::components::{sapling::GrothProofBytes, GROTH_PROOF_SIZE},
|
||||
};
|
||||
|
||||
use crate::{
|
||||
load_parameters, parse_parameters, sapling::SaplingProvingContext, OutputParameters,
|
||||
SpendParameters,
|
||||
};
|
||||
use crate::{load_parameters, parse_parameters, OutputParameters, SpendParameters};
|
||||
|
||||
#[cfg(feature = "local-prover")]
|
||||
use crate::{default_params_folder, SAPLING_OUTPUT_NAME, SAPLING_SPEND_NAME};
|
||||
|
@ -215,68 +211,3 @@ impl OutputProver for LocalTxProver {
|
|||
zkproof
|
||||
}
|
||||
}
|
||||
|
||||
impl TxProver for LocalTxProver {
|
||||
type SaplingProvingContext = SaplingProvingContext;
|
||||
|
||||
fn new_sapling_proving_context(&self) -> Self::SaplingProvingContext {
|
||||
SaplingProvingContext::new()
|
||||
}
|
||||
|
||||
fn spend_proof(
|
||||
&self,
|
||||
ctx: &mut Self::SaplingProvingContext,
|
||||
proof_generation_key: ProofGenerationKey,
|
||||
diversifier: Diversifier,
|
||||
rseed: Rseed,
|
||||
ar: jubjub::Fr,
|
||||
value: u64,
|
||||
anchor: bls12_381::Scalar,
|
||||
merkle_path: MerklePath,
|
||||
) -> Result<([u8; GROTH_PROOF_SIZE], ValueCommitment, PublicKey), ()> {
|
||||
let (proof, cv, rk) = ctx.spend_proof(
|
||||
proof_generation_key,
|
||||
diversifier,
|
||||
rseed,
|
||||
ar,
|
||||
value,
|
||||
anchor,
|
||||
merkle_path,
|
||||
&self.spend_params,
|
||||
)?;
|
||||
|
||||
let mut zkproof = [0u8; GROTH_PROOF_SIZE];
|
||||
proof
|
||||
.write(&mut zkproof[..])
|
||||
.expect("should be able to serialize a proof");
|
||||
|
||||
Ok((zkproof, cv, rk))
|
||||
}
|
||||
|
||||
fn output_proof(
|
||||
&self,
|
||||
ctx: &mut Self::SaplingProvingContext,
|
||||
esk: jubjub::Fr,
|
||||
payment_address: PaymentAddress,
|
||||
rcm: jubjub::Fr,
|
||||
value: u64,
|
||||
) -> ([u8; GROTH_PROOF_SIZE], ValueCommitment) {
|
||||
let (proof, cv) = ctx.output_proof(esk, payment_address, rcm, value, &self.output_params);
|
||||
|
||||
let mut zkproof = [0u8; GROTH_PROOF_SIZE];
|
||||
proof
|
||||
.write(&mut zkproof[..])
|
||||
.expect("should be able to serialize a proof");
|
||||
|
||||
(zkproof, cv)
|
||||
}
|
||||
|
||||
fn binding_sig(
|
||||
&self,
|
||||
ctx: &mut Self::SaplingProvingContext,
|
||||
value_balance: Amount,
|
||||
sighash: &[u8; 32],
|
||||
) -> Result<Signature, ()> {
|
||||
ctx.binding_sig(value_balance, sighash)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,5 +3,4 @@
|
|||
mod prover;
|
||||
mod verifier;
|
||||
|
||||
pub use self::prover::SaplingProvingContext;
|
||||
pub use self::verifier::{BatchValidator, SaplingVerificationContext};
|
||||
|
|
|
@ -1,17 +1,14 @@
|
|||
use bellman::groth16::{create_random_proof, Proof};
|
||||
use bls12_381::Bls12;
|
||||
use group::GroupEncoding;
|
||||
use rand_core::{OsRng, RngCore};
|
||||
use rand_core::RngCore;
|
||||
use zcash_primitives::{
|
||||
sapling::{
|
||||
circuit::{Output, Spend, ValueCommitmentOpening},
|
||||
constants::{SPENDING_KEY_GENERATOR, VALUE_COMMITMENT_RANDOMNESS_GENERATOR},
|
||||
prover::{OutputProver, SpendProver},
|
||||
redjubjub::{PublicKey, Signature},
|
||||
value::{CommitmentSum, NoteValue, TrapdoorSum, ValueCommitTrapdoor, ValueCommitment},
|
||||
value::{NoteValue, ValueCommitTrapdoor},
|
||||
Diversifier, MerklePath, Note, PaymentAddress, ProofGenerationKey, Rseed,
|
||||
},
|
||||
transaction::components::{sapling::GrothProofBytes, Amount, GROTH_PROOF_SIZE},
|
||||
transaction::components::{sapling::GrothProofBytes, GROTH_PROOF_SIZE},
|
||||
};
|
||||
|
||||
use crate::{OutputParameters, SpendParameters};
|
||||
|
@ -111,154 +108,3 @@ impl OutputProver for OutputParameters {
|
|||
zkproof
|
||||
}
|
||||
}
|
||||
|
||||
/// A context object for creating the Sapling components of a Zcash transaction.
|
||||
pub struct SaplingProvingContext {
|
||||
bsk: TrapdoorSum,
|
||||
// (sum of the Spend value commitments) - (sum of the Output value commitments)
|
||||
cv_sum: CommitmentSum,
|
||||
}
|
||||
|
||||
impl Default for SaplingProvingContext {
|
||||
fn default() -> Self {
|
||||
SaplingProvingContext::new()
|
||||
}
|
||||
}
|
||||
|
||||
impl SaplingProvingContext {
|
||||
/// Construct a new context to be used with a single transaction.
|
||||
pub fn new() -> Self {
|
||||
SaplingProvingContext {
|
||||
bsk: TrapdoorSum::zero(),
|
||||
cv_sum: CommitmentSum::zero(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Create the value commitment, re-randomized key, and proof for a Sapling
|
||||
/// SpendDescription, while accumulating its value commitment randomness
|
||||
/// inside the context for later use.
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
pub fn spend_proof(
|
||||
&mut self,
|
||||
proof_generation_key: ProofGenerationKey,
|
||||
diversifier: Diversifier,
|
||||
rseed: Rseed,
|
||||
ar: jubjub::Fr,
|
||||
value: u64,
|
||||
anchor: bls12_381::Scalar,
|
||||
merkle_path: MerklePath,
|
||||
proving_key: &SpendParameters,
|
||||
) -> Result<(Proof<Bls12>, ValueCommitment, PublicKey), ()> {
|
||||
// Initialize secure RNG
|
||||
let mut rng = OsRng;
|
||||
|
||||
// We create the randomness of the value commitment
|
||||
let rcv = ValueCommitTrapdoor::random(&mut rng);
|
||||
|
||||
// Accumulate the value commitment randomness in the context
|
||||
self.bsk += &rcv;
|
||||
|
||||
// Construct the value commitment
|
||||
let value = NoteValue::from_raw(value);
|
||||
let value_commitment = ValueCommitment::derive(value, rcv.clone());
|
||||
|
||||
// This is the result of the re-randomization, we compute it for the caller
|
||||
let rk = PublicKey(proof_generation_key.ak.into()).randomize(ar, SPENDING_KEY_GENERATOR);
|
||||
|
||||
let instance = SpendParameters::prepare_circuit(
|
||||
proof_generation_key,
|
||||
diversifier,
|
||||
rseed,
|
||||
value,
|
||||
ar,
|
||||
rcv,
|
||||
anchor,
|
||||
merkle_path,
|
||||
)
|
||||
.ok_or(())?;
|
||||
|
||||
// Create proof
|
||||
let proof = proving_key.create_proof(instance, &mut rng);
|
||||
|
||||
// Accumulate the value commitment in the context
|
||||
self.cv_sum += &value_commitment;
|
||||
|
||||
Ok((proof, value_commitment, rk))
|
||||
}
|
||||
|
||||
/// Create the value commitment and proof for a Sapling OutputDescription,
|
||||
/// while accumulating its value commitment randomness inside the context
|
||||
/// for later use.
|
||||
pub fn output_proof(
|
||||
&mut self,
|
||||
esk: jubjub::Fr,
|
||||
payment_address: PaymentAddress,
|
||||
rcm: jubjub::Fr,
|
||||
value: u64,
|
||||
proving_key: &OutputParameters,
|
||||
) -> (Proof<Bls12>, ValueCommitment) {
|
||||
// Initialize secure RNG
|
||||
let mut rng = OsRng;
|
||||
|
||||
// We construct ephemeral randomness for the value commitment. This
|
||||
// randomness is not given back to the caller, but the synthetic
|
||||
// blinding factor `bsk` is accumulated in the context.
|
||||
let rcv = ValueCommitTrapdoor::random(&mut rng);
|
||||
|
||||
// Accumulate the value commitment randomness in the context
|
||||
self.bsk -= &rcv; // Outputs subtract from the total.
|
||||
|
||||
// Construct the value commitment for the proof instance
|
||||
let value = NoteValue::from_raw(value);
|
||||
let value_commitment = ValueCommitment::derive(value, rcv.clone());
|
||||
|
||||
// We now have a full witness for the output proof.
|
||||
let instance = OutputParameters::prepare_circuit(esk, payment_address, rcm, value, rcv);
|
||||
|
||||
// Create proof
|
||||
let proof = proving_key.create_proof(instance, &mut rng);
|
||||
|
||||
// Accumulate the value commitment in the context. We do this to check internal consistency.
|
||||
self.cv_sum -= &value_commitment; // Outputs subtract from the total.
|
||||
|
||||
(proof, value_commitment)
|
||||
}
|
||||
|
||||
/// Create the bindingSig for a Sapling transaction. All calls to spend_proof()
|
||||
/// and output_proof() must be completed before calling this function.
|
||||
pub fn binding_sig(&self, value_balance: Amount, sighash: &[u8; 32]) -> Result<Signature, ()> {
|
||||
// Initialize secure RNG
|
||||
let mut rng = OsRng;
|
||||
|
||||
// Grab the current `bsk` from the context
|
||||
let bsk = self.bsk.into_bsk();
|
||||
|
||||
// Grab the `bvk` using DerivePublic.
|
||||
let bvk = PublicKey::from_private(&bsk, VALUE_COMMITMENT_RANDOMNESS_GENERATOR);
|
||||
|
||||
// In order to check internal consistency, let's use the accumulated value
|
||||
// commitments (as the verifier would) and apply value_balance to compare
|
||||
// against our derived bvk.
|
||||
{
|
||||
// Compute the final bvk.
|
||||
let final_bvk = self.cv_sum.into_bvk(value_balance);
|
||||
|
||||
// The result should be the same, unless the provided valueBalance is wrong.
|
||||
if bvk.0 != final_bvk.0 {
|
||||
return Err(());
|
||||
}
|
||||
}
|
||||
|
||||
// Construct signature message
|
||||
let mut data_to_be_signed = [0u8; 64];
|
||||
data_to_be_signed[0..32].copy_from_slice(&bvk.0.to_bytes());
|
||||
data_to_be_signed[32..64].copy_from_slice(&sighash[..]);
|
||||
|
||||
// Sign
|
||||
Ok(bsk.sign(
|
||||
&data_to_be_signed,
|
||||
&mut rng,
|
||||
VALUE_COMMITMENT_RANDOMNESS_GENERATOR,
|
||||
))
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue