`impl TestFvk for orchard::keys::FullViewingKey`
This commit is contained in:
parent
0a41d65910
commit
6c6080c99c
|
@ -3066,6 +3066,7 @@ dependencies = [
|
||||||
"maybe-rayon",
|
"maybe-rayon",
|
||||||
"nonempty",
|
"nonempty",
|
||||||
"orchard",
|
"orchard",
|
||||||
|
"pasta_curves",
|
||||||
"proptest",
|
"proptest",
|
||||||
"prost",
|
"prost",
|
||||||
"rand_core",
|
"rand_core",
|
||||||
|
|
|
@ -57,6 +57,7 @@ sapling = { package = "sapling-crypto", version = "0.1.1" }
|
||||||
# - Orchard
|
# - Orchard
|
||||||
nonempty = "0.7"
|
nonempty = "0.7"
|
||||||
orchard = { version = "0.7.1", default-features = false }
|
orchard = { version = "0.7.1", default-features = false }
|
||||||
|
pasta_curves = "0.5"
|
||||||
|
|
||||||
# - Transparent
|
# - Transparent
|
||||||
hdwallet = "0.4"
|
hdwallet = "0.4"
|
||||||
|
|
|
@ -70,6 +70,7 @@ maybe-rayon.workspace = true
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
assert_matches.workspace = true
|
assert_matches.workspace = true
|
||||||
incrementalmerkletree = { workspace = true, features = ["test-dependencies"] }
|
incrementalmerkletree = { workspace = true, features = ["test-dependencies"] }
|
||||||
|
pasta_curves.workspace = true
|
||||||
shardtree = { workspace = true, features = ["legacy-api", "test-dependencies"] }
|
shardtree = { workspace = true, features = ["legacy-api", "test-dependencies"] }
|
||||||
nonempty.workspace = true
|
nonempty.workspace = true
|
||||||
proptest.workspace = true
|
proptest.workspace = true
|
||||||
|
|
|
@ -72,6 +72,14 @@ use crate::{
|
||||||
|
|
||||||
use super::BlockDb;
|
use super::BlockDb;
|
||||||
|
|
||||||
|
#[cfg(feature = "orchard")]
|
||||||
|
use {
|
||||||
|
group::ff::{Field, PrimeField},
|
||||||
|
orchard::note_encryption::{OrchardDomain, OrchardNoteEncryption},
|
||||||
|
pasta_curves::pallas,
|
||||||
|
zcash_client_backend::proto::compact_formats::CompactOrchardAction,
|
||||||
|
};
|
||||||
|
|
||||||
#[cfg(feature = "transparent-inputs")]
|
#[cfg(feature = "transparent-inputs")]
|
||||||
use {
|
use {
|
||||||
zcash_client_backend::data_api::wallet::{
|
zcash_client_backend::data_api::wallet::{
|
||||||
|
@ -763,9 +771,18 @@ pub(crate) trait TestFvk {
|
||||||
|
|
||||||
fn sapling_ovk(&self) -> Option<sapling::keys::OutgoingViewingKey>;
|
fn sapling_ovk(&self) -> Option<sapling::keys::OutgoingViewingKey>;
|
||||||
|
|
||||||
fn add_compact_spend(&self, ctx: &mut CompactTx, nf: Self::Nullifier);
|
#[cfg(feature = "orchard")]
|
||||||
|
fn orchard_ovk(&self, scope: zip32::Scope) -> Option<orchard::keys::OutgoingViewingKey>;
|
||||||
|
|
||||||
fn add_compact_output<P: consensus::Parameters, R: RngCore + CryptoRng>(
|
fn add_spend<R: RngCore + CryptoRng>(
|
||||||
|
&self,
|
||||||
|
ctx: &mut CompactTx,
|
||||||
|
nf: Self::Nullifier,
|
||||||
|
rng: &mut R,
|
||||||
|
);
|
||||||
|
|
||||||
|
#[allow(clippy::too_many_arguments)]
|
||||||
|
fn add_output<P: consensus::Parameters, R: RngCore + CryptoRng>(
|
||||||
&self,
|
&self,
|
||||||
ctx: &mut CompactTx,
|
ctx: &mut CompactTx,
|
||||||
params: &P,
|
params: &P,
|
||||||
|
@ -784,12 +801,22 @@ impl TestFvk for DiversifiableFullViewingKey {
|
||||||
Some(self.fvk().ovk)
|
Some(self.fvk().ovk)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn add_compact_spend(&self, ctx: &mut CompactTx, nf: Self::Nullifier) {
|
#[cfg(feature = "orchard")]
|
||||||
|
fn orchard_ovk(&self, _: zip32::Scope) -> Option<orchard::keys::OutgoingViewingKey> {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
|
fn add_spend<R: RngCore + CryptoRng>(
|
||||||
|
&self,
|
||||||
|
ctx: &mut CompactTx,
|
||||||
|
nf: Self::Nullifier,
|
||||||
|
_: &mut R,
|
||||||
|
) {
|
||||||
let cspend = CompactSaplingSpend { nf: nf.to_vec() };
|
let cspend = CompactSaplingSpend { nf: nf.to_vec() };
|
||||||
ctx.spends.push(cspend);
|
ctx.spends.push(cspend);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn add_compact_output<P: consensus::Parameters, R: RngCore + CryptoRng>(
|
fn add_output<P: consensus::Parameters, R: RngCore + CryptoRng>(
|
||||||
&self,
|
&self,
|
||||||
ctx: &mut CompactTx,
|
ctx: &mut CompactTx,
|
||||||
params: &P,
|
params: &P,
|
||||||
|
@ -815,6 +842,79 @@ impl TestFvk for DiversifiableFullViewingKey {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "orchard")]
|
||||||
|
impl TestFvk for orchard::keys::FullViewingKey {
|
||||||
|
type Nullifier = orchard::note::Nullifier;
|
||||||
|
|
||||||
|
fn sapling_ovk(&self) -> Option<sapling::keys::OutgoingViewingKey> {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
|
fn orchard_ovk(&self, scope: zip32::Scope) -> Option<orchard::keys::OutgoingViewingKey> {
|
||||||
|
Some(self.to_ovk(scope))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn add_spend<R: RngCore + CryptoRng>(
|
||||||
|
&self,
|
||||||
|
ctx: &mut CompactTx,
|
||||||
|
nf: Self::Nullifier,
|
||||||
|
rng: &mut R,
|
||||||
|
) {
|
||||||
|
// Generate a dummy recipient.
|
||||||
|
let recipient = loop {
|
||||||
|
let mut bytes = [0; 32];
|
||||||
|
rng.fill_bytes(&mut bytes);
|
||||||
|
let sk = orchard::keys::SpendingKey::from_bytes(bytes);
|
||||||
|
if sk.is_some().into() {
|
||||||
|
break orchard::keys::FullViewingKey::from(&sk.unwrap())
|
||||||
|
.address_at(0u32, zip32::Scope::External);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let (cact, _) = compact_orchard_action(
|
||||||
|
nf,
|
||||||
|
recipient,
|
||||||
|
NonNegativeAmount::ZERO,
|
||||||
|
self.orchard_ovk(zip32::Scope::Internal),
|
||||||
|
rng,
|
||||||
|
);
|
||||||
|
ctx.actions.push(cact);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn add_output<P: consensus::Parameters, R: RngCore + CryptoRng>(
|
||||||
|
&self,
|
||||||
|
ctx: &mut CompactTx,
|
||||||
|
_: &P,
|
||||||
|
_: BlockHeight,
|
||||||
|
req: AddressType,
|
||||||
|
value: NonNegativeAmount,
|
||||||
|
_: u32,
|
||||||
|
mut rng: &mut R,
|
||||||
|
) -> Self::Nullifier {
|
||||||
|
// Generate a dummy nullifier
|
||||||
|
let nullifier =
|
||||||
|
orchard::note::Nullifier::from_bytes(&pallas::Base::random(&mut rng).to_repr())
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
let (j, scope) = match req {
|
||||||
|
AddressType::DefaultExternal => (0u32.into(), zip32::Scope::External),
|
||||||
|
AddressType::DiversifiedExternal(idx) => (idx, zip32::Scope::External),
|
||||||
|
AddressType::Internal => (0u32.into(), zip32::Scope::Internal),
|
||||||
|
};
|
||||||
|
|
||||||
|
let (cact, note) = compact_orchard_action(
|
||||||
|
nullifier,
|
||||||
|
self.address_at(j, scope),
|
||||||
|
value,
|
||||||
|
self.orchard_ovk(scope),
|
||||||
|
rng,
|
||||||
|
);
|
||||||
|
ctx.actions.push(cact);
|
||||||
|
|
||||||
|
note.nullifier(self)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
pub(crate) enum AddressType {
|
pub(crate) enum AddressType {
|
||||||
DefaultExternal,
|
DefaultExternal,
|
||||||
|
@ -854,6 +954,54 @@ fn compact_sapling_output<P: consensus::Parameters, R: RngCore + CryptoRng>(
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Creates a `CompactOrchardAction` at the given height paying the given recipient.
|
||||||
|
///
|
||||||
|
/// Returns the `CompactOrchardAction` and the new note.
|
||||||
|
#[cfg(feature = "orchard")]
|
||||||
|
fn compact_orchard_action<R: RngCore + CryptoRng>(
|
||||||
|
nullifier: orchard::note::Nullifier,
|
||||||
|
recipient: orchard::Address,
|
||||||
|
value: NonNegativeAmount,
|
||||||
|
ovk: Option<orchard::keys::OutgoingViewingKey>,
|
||||||
|
rng: &mut R,
|
||||||
|
) -> (CompactOrchardAction, orchard::Note) {
|
||||||
|
let nf = nullifier.to_bytes().to_vec();
|
||||||
|
|
||||||
|
let rseed = {
|
||||||
|
loop {
|
||||||
|
let mut bytes = [0; 32];
|
||||||
|
rng.fill_bytes(&mut bytes);
|
||||||
|
let rseed = orchard::note::RandomSeed::from_bytes(bytes, &nullifier);
|
||||||
|
if rseed.is_some().into() {
|
||||||
|
break rseed.unwrap();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
let note = orchard::Note::from_parts(
|
||||||
|
recipient,
|
||||||
|
orchard::value::NoteValue::from_raw(value.into_u64()),
|
||||||
|
nullifier,
|
||||||
|
rseed,
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
let encryptor = OrchardNoteEncryption::new(ovk, note, *MemoBytes::empty().as_array());
|
||||||
|
let cmx = orchard::note::ExtractedNoteCommitment::from(note.commitment())
|
||||||
|
.to_bytes()
|
||||||
|
.to_vec();
|
||||||
|
let ephemeral_key = OrchardDomain::epk_bytes(encryptor.epk()).0.to_vec();
|
||||||
|
let enc_ciphertext = encryptor.encrypt_note_plaintext();
|
||||||
|
|
||||||
|
(
|
||||||
|
CompactOrchardAction {
|
||||||
|
nullifier: nf,
|
||||||
|
cmx,
|
||||||
|
ephemeral_key,
|
||||||
|
ciphertext: enc_ciphertext.as_ref()[..52].to_vec(),
|
||||||
|
},
|
||||||
|
note,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
/// Creates a fake `CompactTx` with a random transaction ID and no spends or outputs.
|
/// Creates a fake `CompactTx` with a random transaction ID and no spends or outputs.
|
||||||
fn fake_compact_tx<R: RngCore + CryptoRng>(rng: &mut R) -> CompactTx {
|
fn fake_compact_tx<R: RngCore + CryptoRng>(rng: &mut R) -> CompactTx {
|
||||||
let mut ctx = CompactTx::default();
|
let mut ctx = CompactTx::default();
|
||||||
|
@ -880,7 +1028,7 @@ fn fake_compact_block<P: consensus::Parameters, Fvk: TestFvk>(
|
||||||
|
|
||||||
// Create a fake CompactBlock containing the note
|
// Create a fake CompactBlock containing the note
|
||||||
let mut ctx = fake_compact_tx(&mut rng);
|
let mut ctx = fake_compact_tx(&mut rng);
|
||||||
let nf = fvk.add_compact_output(
|
let nf = fvk.add_output(
|
||||||
&mut ctx,
|
&mut ctx,
|
||||||
params,
|
params,
|
||||||
height,
|
height,
|
||||||
|
@ -953,14 +1101,14 @@ fn fake_compact_block_spending<P: consensus::Parameters, Fvk: TestFvk>(
|
||||||
let mut ctx = fake_compact_tx(&mut rng);
|
let mut ctx = fake_compact_tx(&mut rng);
|
||||||
|
|
||||||
// Create a fake spend
|
// Create a fake spend
|
||||||
fvk.add_compact_spend(&mut ctx, nf);
|
fvk.add_spend(&mut ctx, nf, &mut rng);
|
||||||
|
|
||||||
// Create a fake Note for the payment
|
// Create a fake Note for the payment
|
||||||
ctx.outputs
|
ctx.outputs
|
||||||
.push(compact_sapling_output(params, height, to, value, fvk.sapling_ovk(), &mut rng).0);
|
.push(compact_sapling_output(params, height, to, value, fvk.sapling_ovk(), &mut rng).0);
|
||||||
|
|
||||||
// Create a fake Note for the change
|
// Create a fake Note for the change
|
||||||
fvk.add_compact_output(
|
fvk.add_output(
|
||||||
&mut ctx,
|
&mut ctx,
|
||||||
params,
|
params,
|
||||||
height,
|
height,
|
||||||
|
|
Loading…
Reference in New Issue