cargo fix

Bug fixes
This commit is contained in:
Hanh 2023-04-26 10:18:24 +10:00
parent 48f0a2ead4
commit 3d94b41c25
7 changed files with 7696 additions and 6783 deletions

View File

@ -7,7 +7,7 @@ fn main() {
)
.unwrap();
create_c_bindings();
// create_c_bindings();
}
#[allow(dead_code)]

File diff suppressed because it is too large Load Diff

View File

@ -2,18 +2,19 @@ use blake2b_simd::Params;
use blake2b_simd::State;
use byteorder::WriteBytesExt;
use byteorder::LE;
use ff::{Field, PrimeField};
use group::GroupEncoding;
use ff::Field;
use hex_literal::hex;
use jubjub::{Fq, Fr};
use jubjub::Fr;
use orchard::circuit::ProvingKey;
use crate::ledger::builder::orchard_bundle::OrchardBuilder;
use crate::ledger::builder::sapling_bundle::SaplingBuilder;
use crate::ledger::builder::transparent_bundle::TransparentBuilder;
use crate::ledger::transport::*;
use crate::{CompactTxStreamerClient, Destination, RawTransaction, Source, TransactionPlan};
use anyhow::{anyhow, Result};
use rand::{rngs::OsRng, RngCore, SeedableRng};
use rand::{RngCore, SeedableRng};
use rand_chacha::ChaChaRng;
use ripemd::{Digest, Ripemd160};
use secp256k1::PublicKey;
@ -30,24 +31,9 @@ use zcash_primitives::zip32::ExtendedFullViewingKey;
use zcash_primitives::{
consensus::{BlockHeight, BranchId, MainNetwork},
constants::PROOF_GENERATION_KEY_GENERATOR,
merkle_tree::IncrementalWitness,
sapling::{
note_encryption::sapling_note_encryption,
prover::TxProver,
redjubjub::Signature,
value::{NoteValue, ValueCommitment, ValueSum},
Diversifier, Node, Note, Nullifier, PaymentAddress, Rseed,
},
transaction::{
components::{
sapling::{Authorized as SapAuthorized, Bundle},
Amount, OutputDescription, SpendDescription, GROTH_PROOF_SIZE,
},
Authorized, TransactionData, TxVersion,
},
transaction::{Authorized, TransactionData, TxVersion},
};
use zcash_proofs::{prover::LocalTxProver, sapling::SaplingProvingContext};
use zcash_proofs::prover::LocalTxProver;
mod orchard_bundle;
mod sapling_bundle;
@ -95,7 +81,8 @@ pub async fn build_broadcast_tx(
let mut transparent_builder = TransparentBuilder::new(network, &pubkey);
if transparent_builder.taddr != tx_plan.taddr {
anyhow::bail!("This ledger wallet has a different address");
anyhow::bail!("This ledger wallet has a different address {} != {}",
transparent_builder.taddr, tx_plan.taddr);
}
// Compute header digest
@ -116,10 +103,20 @@ pub async fn build_broadcast_tx(
// let dfvk = extsk.to_diversifiable_full_viewing_key();
let dfvk: zcash_primitives::zip32::DiversifiableFullViewingKey = ledger_get_dfvk().await?;
let proofgen_key: zcash_primitives::sapling::ProofGenerationKey = ledger_get_proofgen_key().await?;
let proofgen_key: zcash_primitives::sapling::ProofGenerationKey =
ledger_get_proofgen_key().await?;
let mut sapling_builder = SaplingBuilder::new(prover, dfvk, proofgen_key);
let orchard_fvk: [u8; 96] = hex::decode(&tx_plan.orchard_fvk)
.unwrap()
.try_into()
.unwrap();
let orchard_fvk = orchard::keys::FullViewingKey::from_bytes(&orchard_fvk).unwrap();
let anchor = orchard::Anchor::from_bytes(tx_plan.orchard_anchor).unwrap();
let mut orchard_builder = OrchardBuilder::new(&orchard_fvk, anchor);
let o_fvk: [u8; 96] = ledger_get_o_fvk().await?.try_into().unwrap();
let _o_fvk =
orchard::keys::FullViewingKey::from_bytes(&o_fvk).ok_or(anyhow!("Invalid Orchard FVK"))?;
@ -157,10 +154,14 @@ pub async fn build_broadcast_tx(
} => {
let alpha = Fr::random(&mut alpha_rng);
println!("ALPHA {}", hex::encode(&alpha.to_bytes()));
sapling_builder.add_spend(alpha, diversifier, rseed, witness, sp.amount).await?;
sapling_builder
.add_spend(alpha, diversifier, rseed, witness, sp.amount)
.await?;
}
Source::Orchard { diversifier, rseed, rho, ref witness, .. } => {
orchard_builder.add_spend(diversifier, rseed, rho, &witness, sp.amount)?;
}
Source::Orchard { .. } => {}
}
}
ledger_set_stage(2).await?;
@ -172,25 +173,40 @@ pub async fn build_broadcast_tx(
.await?;
}
}
transparent_builder.set_merkle_proof().await?;
ledger_set_stage(3).await?;
for output in tx_plan.outputs.iter() {
if let Destination::Sapling(raw_address) = output.destination {
let mut rseed = [0u8; 32];
rseed_rng.fill_bytes(&mut rseed);
sapling_builder.add_output(rseed, raw_address, &output.memo, output.amount).await?;
match output.destination {
Destination::Sapling(raw_address) => {
let mut rseed = [0u8; 32];
rseed_rng.fill_bytes(&mut rseed);
sapling_builder
.add_output(rseed, raw_address, &output.memo, output.amount)
.await?;
}
Destination::Orchard(raw_address) => {
orchard_builder.add_output(raw_address, output.amount, &output.memo)?;
}
_ => {}
}
}
sapling_builder.set_merkle_proof(tx_plan.net_chg[0]).await?;
ledger_set_stage(4).await?;
transparent_builder.set_merkle_proof().await?;
let pk = ProvingKey::build();
orchard_builder.prepare(tx_plan.net_chg[1], &pk, &mut alpha_rng, &mut rseed_rng).await?;
ledger_set_stage(5).await?;
ledger_confirm_fee().await?;
transparent_builder.sign().await?;
sapling_builder.sign().await?;
orchard_builder.sign().await?;
let transparent_bundle = transparent_builder.build();
let sapling_bundle = sapling_builder.build(tx_plan.net_chg[0]).await?;
let sapling_bundle = sapling_builder.build().await?;
let orchard_bundle = orchard_builder.build()?;
let authed_tx: TransactionData<Authorized> = TransactionData {
version: TxVersion::Zip225,
@ -200,7 +216,7 @@ pub async fn build_broadcast_tx(
transparent_bundle,
sprout_bundle: None,
sapling_bundle,
orchard_bundle: None,
orchard_bundle,
};
let tx = authed_tx.freeze().unwrap();
@ -216,7 +232,7 @@ pub async fn build_broadcast_tx(
}))
.await?
.into_inner();
log::info!("{}", response.error_message);
println!("{}", response.error_message);
Ok(response.error_message)
}

View File

@ -20,7 +20,8 @@ use orchard::{
value::{NoteValue, ValueCommitTrapdoor, ValueCommitment, ValueSum},
Action, Address, Anchor, Bundle, Note, Proof,
};
use rand::{RngCore, SeedableRng};
use rand::{rngs::OsRng, RngCore, SeedableRng};
use rand_chacha::ChaCha20Rng;
use ripemd::Digest;
@ -35,6 +36,7 @@ use hex_literal::hex;
use nonempty::NonEmpty;
use zcash_primitives::{
consensus::{BlockHeight, BranchId},
memo::MemoBytes,
transaction::{
components::Amount, sighash::SignableInput, sighash_v5, txid::TxIdDigester,
Authorized as TxAuthorized, Transaction, TransactionData, TxVersion, Unauthorized,
@ -43,6 +45,8 @@ use zcash_primitives::{
use crate::{Destination, Source};
use super::create_hasher;
#[derive(Debug)]
pub struct NoAuth;
@ -50,6 +54,279 @@ impl Authorization for NoAuth {
type SpendAuth = ();
}
pub struct OrchardBuilder {
orchard_fvk: FullViewingKey,
anchor: Anchor,
spends: Vec<OrchardSpend>,
outputs: Vec<OrchardOutput>,
padded_inouts: Vec<(OrchardSpend, OrchardOutput)>,
actions: Vec<Action<SigningMetadata>>,
auth_actions: Vec<Action<Signature<SpendAuth>>>,
net_value: ValueSum,
net_rcv: ValueCommitTrapdoor,
proof: Proof,
sig_hash: Vec<u8>
}
impl OrchardBuilder {
pub fn new(orchard_fvk: &FullViewingKey, anchor: Anchor) -> Self {
OrchardBuilder {
orchard_fvk: orchard_fvk.clone(),
anchor,
spends: vec![],
outputs: vec![],
padded_inouts: vec![],
actions: vec![],
auth_actions: vec![],
proof: Proof::new(vec![]),
net_value: ValueSum::default(),
net_rcv: ValueCommitTrapdoor::zero(),
sig_hash: vec![],
}
}
pub fn add_spend(
&mut self,
diversifier: [u8; 11],
rseed: [u8; 32],
rho: [u8; 32],
witness: &[u8],
amount: u64,
) -> Result<()> {
let diversifier = Diversifier::from_bytes(diversifier);
let address = self.orchard_fvk.address(diversifier, Scope::External);
let rho = Nullifier::from_bytes(&rho).unwrap();
let rseed = RandomSeed::from_bytes(rseed, &rho).unwrap();
let note = Note::from_parts(address, NoteValue::from_raw(amount), rho, rseed).unwrap();
let merkle_path = decode_orchard_merkle_path(0, &witness).unwrap();
self.spends.push(OrchardSpend {
ask: None,
fvk: self.orchard_fvk.clone(),
note,
merkle_path,
});
Ok(())
}
pub fn add_output(&mut self, address: [u8; 43], amount: u64, memo: &MemoBytes) -> Result<()> {
let address = Address::from_raw_address_bytes(&address).unwrap();
let output = OrchardOutput {
recipient: address,
amount: NoteValue::from_raw(amount),
memo: memo.as_array().clone(),
};
self.outputs.push(output);
Ok(())
}
pub async fn prepare<R: RngCore>(
&mut self,
netchg: i64,
pk: &ProvingKey,
mut alpha_rng: R,
mut rseed_rng: R,
) -> Result<()> {
let mut orchard_memos_hasher = create_hasher(b"ZTxIdOrcActMHash");
let mut orchard_nc_hasher = create_hasher(b"ZTxIdOrcActNHash");
let num_actions = self.spends.len().max(self.outputs.len());
let mut circuits = vec![];
let mut instances = vec![];
for i in 0..num_actions {
// pad with dummy spends/outputs
let spend = if i < self.spends.len() {
self.spends[i].clone()
} else {
OrchardSpend::dummy(&mut OsRng)
};
let output = if i < self.outputs.len() {
self.outputs[i].clone()
} else {
OrchardOutput::dummy(&mut OsRng)
};
self.padded_inouts.push((spend.clone(), output.clone()));
let rcv = ValueCommitTrapdoor::random(&mut OsRng);
self.net_rcv = self.net_rcv.clone() + &rcv;
let alpha = pasta_curves::Fq::random(&mut alpha_rng);
let ak: SpendValidatingKey = spend.fvk.clone().into();
let rk = ak.randomize(&alpha);
let rho = spend.note.nullifier(&spend.fvk);
let mut rseed = [0u8; 32];
rseed_rng.fill_bytes(&mut rseed);
let rseed = RandomSeed::from_bytes(rseed, &rho).unwrap();
let v_net: ValueSum = spend.note.value() - output.amount;
self.net_value = (self.net_value + v_net).unwrap();
let cv_net = ValueCommitment::derive(v_net, rcv.clone());
let spend_info = SpendInfo::new(
spend.fvk.clone(),
spend.note.clone(),
spend.merkle_path.clone(),
)
.unwrap();
let output_note = Note::from_parts(
output.recipient.clone(),
output.amount.clone(),
rho.clone(),
rseed,
)
.unwrap();
let cmx: ExtractedNoteCommitment = output_note.commitment().into();
let encryptor = OrchardNoteEncryption::new(
Some(self.orchard_fvk.to_ovk(Scope::External)),
output_note.clone(),
output.recipient.clone(),
output.memo.clone(),
);
let epk = encryptor.epk().to_bytes().0;
let enc = encryptor.encrypt_note_plaintext();
let out = encryptor.encrypt_outgoing_plaintext(&cv_net.clone(), &cmx, &mut OsRng);
let encrypted_note = TransmittedNoteCiphertext {
epk_bytes: epk.clone(),
enc_ciphertext: enc.clone(),
out_ciphertext: out.clone(),
};
let rk_bytes: [u8; 32] = rk.clone().0.into();
orchard_memos_hasher.update(&enc[52..564]);
orchard_nc_hasher.update(&cv_net.to_bytes());
orchard_nc_hasher.update(&rk_bytes);
orchard_nc_hasher.update(&enc[564..]);
orchard_nc_hasher.update(&out);
println!(
"d/pkd {}",
hex::encode(&output.recipient.to_raw_address_bytes())
);
println!("rho {}", hex::encode(&rho.to_bytes()));
println!(
"amount {}",
hex::encode(&output.amount.inner().to_le_bytes())
);
println!("rseed {}", hex::encode(&rseed.as_bytes()));
println!("cmx {}", hex::encode(&cmx.to_bytes()));
let action: Action<SigningMetadata> = Action::from_parts(
rho.clone(),
rk.clone(),
cmx.clone(),
encrypted_note,
cv_net.clone(),
SigningMetadata {
dummy_ask: None,
parts: SigningParts { ak, alpha },
},
);
self.actions.push(action);
let circuit =
Circuit::from_action_context(spend_info, output_note, alpha, rcv.clone()).unwrap();
circuits.push(circuit);
let instance = Instance::from_parts(self.anchor, cv_net, rho.clone(), rk, cmx, true, true);
instances.push(instance);
}
self.proof = Proof::create(&pk, &circuits, &instances, &mut OsRng).unwrap();
for (a, (_, ref o)) in self.actions.iter().zip(self.padded_inouts.iter()) {
let nf = a.nullifier().to_bytes();
let epk = a.encrypted_note().epk_bytes;
ledger_add_o_action(
&nf,
o.amount.inner(),
&epk,
&o.recipient.to_raw_address_bytes(),
&a.encrypted_note().enc_ciphertext[0..52],
)
.await
.unwrap();
}
ledger_set_orchard_merkle_proof(
&self.anchor.to_bytes(),
orchard_memos_hasher.finalize().as_bytes(),
orchard_nc_hasher.finalize().as_bytes(),
)
.await
.unwrap();
ledger_set_net_orchard(-netchg).await?;
Ok(())
}
pub async fn sign(&mut self) -> Result<()> {
self.sig_hash = ledger_get_sighash().await?;
for (a, (ref s, _)) in self.actions.iter().zip(self.padded_inouts.iter()) {
println!("alpha {:?}", a.authorization().parts.alpha);
let signature =
match s.ask {
Some(ref ask) => { // dummy spend (we have a dummy key)
println!("DUMMY SPEND");
let rsk = ask.randomize(&a.authorization().parts.alpha);
rsk.sign(&mut OsRng, &self.sig_hash)
}
None => {
let sig_bytes: [u8; 64] = ledger_sign_orchard().await.unwrap().try_into().unwrap();
let signature: Signature<SpendAuth> = sig_bytes.into();
signature
}
};
let auth_action = Action::from_parts(
a.nullifier().clone(),
a.rk().clone(),
a.cmx().clone(),
a.encrypted_note().clone(),
a.cv_net().clone(),
signature,
);
self.auth_actions.push(auth_action);
}
Ok(())
}
pub fn build(self) -> Result<Option<Bundle<Authorized, Amount>>> {
if self.auth_actions.is_empty() { return Ok(None); }
let auth_actions = NonEmpty::from_slice(&self.auth_actions).unwrap();
let nv = i64::try_from(self.net_value).unwrap();
let amount = Amount::from_i64(nv).unwrap();
let bsk = self.net_rcv.into_bsk();
let flags = Flags::from_parts(true, true);
let binding_signature = bsk.sign(&mut OsRng, &self.sig_hash);
let bundle: Bundle<Authorized, Amount> = Bundle::from_parts(
auth_actions,
flags,
amount,
self.anchor.clone(),
Authorized::from_parts(self.proof, binding_signature),
);
Ok(Some(bundle))
}
}
pub async fn build_orchard() -> Result<()> {
dotenv::dotenv()?;
let mut prng = ChaCha20Rng::from_seed([0; 32]);
@ -102,6 +379,7 @@ pub async fn build_orchard() -> Result<()> {
Note::from_parts(address, NoteValue::from_raw(s.amount), rho, rseed).unwrap();
let merkle_path = decode_orchard_merkle_path(0, &witness).unwrap();
Some(OrchardSpend {
ask: None,
fvk: orchard_fvk.clone(),
note,
merkle_path,
@ -143,9 +421,8 @@ pub async fn build_orchard() -> Result<()> {
let mut actions = vec![];
let mut circuits = vec![];
let mut instances = vec![];
let mut net_value = ValueSum::default();
let mut sum_rcv = ValueCommitTrapdoor::zero();
let mut net_value = ValueSum::default();
let mut padded_outputs = vec![];
for i in 0..num_actions {
// pad with dummy spends/outputs
@ -165,7 +442,7 @@ pub async fn build_orchard() -> Result<()> {
let rcv = ValueCommitTrapdoor::random(&mut prng);
sum_rcv = sum_rcv + &rcv;
let alpha = pasta_curves::Fq::random(&mut alpha_rng);
let ak: SpendValidatingKey = orchard_fvk.clone().into();
let ak: SpendValidatingKey = spend.fvk.clone().into();
let rk = ak.randomize(&alpha);
let rho = spend.note.nullifier(&orchard_fvk);
@ -380,6 +657,7 @@ pub async fn build_orchard() -> Result<()> {
#[derive(Clone, Debug)]
struct OrchardSpend {
ask: Option<SpendAuthorizingKey>,
fvk: FullViewingKey,
note: Note,
merkle_path: MerklePath,
@ -387,9 +665,11 @@ struct OrchardSpend {
impl OrchardSpend {
pub fn dummy<R: RngCore>(rng: &mut R) -> Self {
let (_, fvk, dummy_note) = Note::dummy(rng, None);
let (sk, fvk, dummy_note) = Note::dummy(rng, None);
let ask = SpendAuthorizingKey::from(&sk);
let dummy_path = MerklePath::dummy(rng);
OrchardSpend {
ask: Some(ask),
fvk,
note: dummy_note,
merkle_path: dummy_path,

View File

@ -1,38 +1,22 @@
use blake2b_simd::Params;
use blake2b_simd::State;
use byteorder::WriteBytesExt;
use byteorder::LE;
use ff::{Field, PrimeField};
use ff::PrimeField;
use group::GroupEncoding;
use hex_literal::hex;
use jubjub::{Fq, Fr};
use zcash_primitives::memo::MemoBytes;
use zcash_primitives::sapling::ProofGenerationKey;
use zcash_primitives::zip32::DiversifiableFullViewingKey;
use crate::ledger::builder::transparent_bundle::TransparentBuilder;
use crate::ledger::transport::*;
use crate::{CompactTxStreamerClient, Destination, RawTransaction, Source, TransactionPlan};
use anyhow::{anyhow, Result};
use rand::{rngs::OsRng, RngCore, SeedableRng};
use rand_chacha::ChaChaRng;
use ripemd::{Digest, Ripemd160};
use secp256k1::PublicKey;
use sha2::Sha256;
use tonic::{transport::Channel, Request};
use zcash_client_backend::encoding::{
encode_extended_full_viewing_key, encode_transparent_address,
};
use zcash_primitives::consensus::Network;
use zcash_primitives::consensus::Parameters;
use zcash_primitives::legacy::TransparentAddress;
use rand::rngs::OsRng;
use zcash_primitives::zip32::ExtendedFullViewingKey;
use ripemd::Digest;
use zcash_primitives::{
consensus::{BlockHeight, BranchId, MainNetwork},
constants::PROOF_GENERATION_KEY_GENERATOR,
consensus::MainNetwork,
merkle_tree::IncrementalWitness,
sapling::{
note_encryption::sapling_note_encryption,
@ -41,12 +25,9 @@ use zcash_primitives::{
value::{NoteValue, ValueCommitment, ValueSum},
Diversifier, Node, Note, Nullifier, PaymentAddress, Rseed,
},
transaction::{
components::{
sapling::{Authorized as SapAuthorized, Bundle},
Amount, OutputDescription, SpendDescription, GROTH_PROOF_SIZE,
},
Authorized, TransactionData, TxVersion,
transaction::components::{
sapling::{Authorized as SapAuthorized, Bundle},
Amount, OutputDescription, SpendDescription, GROTH_PROOF_SIZE,
},
};
use zcash_proofs::{prover::LocalTxProver, sapling::SaplingProvingContext};
@ -81,15 +62,19 @@ pub struct SaplingBuilder<'a> {
signatures: Vec<Signature>,
}
impl <'a> SaplingBuilder<'a> {
pub fn new(prover: &'a LocalTxProver, dfvk: DiversifiableFullViewingKey, proofgen_key: ProofGenerationKey) -> Self {
impl<'a> SaplingBuilder<'a> {
pub fn new(
prover: &'a LocalTxProver,
dfvk: DiversifiableFullViewingKey,
proofgen_key: ProofGenerationKey,
) -> Self {
let spends_compact_hasher = create_hasher(b"ZTxIdSSpendCHash");
let spends_non_compact_hasher = create_hasher(b"ZTxIdSSpendNHash");
let output_memos_hasher = create_hasher(b"ZTxIdSOutM__Hash");
let output_non_compact_hasher = create_hasher(b"ZTxIdSOutN__Hash");
SaplingBuilder {
SaplingBuilder {
prover,
dfvk,
proofgen_key,
@ -109,9 +94,18 @@ impl <'a> SaplingBuilder<'a> {
}
}
pub async fn add_spend(&mut self, alpha: Fr, diversifier: [u8; 11], rseed: [u8; 32], witness: &[u8], amount: u64) -> Result<()> {
pub async fn add_spend(
&mut self,
alpha: Fr,
diversifier: [u8; 11],
rseed: [u8; 32],
witness: &[u8],
amount: u64,
) -> Result<()> {
let diversifier = Diversifier(diversifier);
let z_address = self.dfvk.fvk
let z_address = self
.dfvk
.fvk
.vk
.to_payment_address(diversifier)
.ok_or(anyhow!("Invalid diversifier"))?;
@ -126,7 +120,8 @@ impl <'a> SaplingBuilder<'a> {
let nf_key = self.proofgen_key.to_viewing_key().nk;
let nullifier = note.nf(&nf_key, merkle_path.position);
let (zkproof, cv, rk) = self.prover
let (zkproof, cv, rk) = self
.prover
.spend_proof(
&mut self.sapling_context,
self.proofgen_key.clone(),
@ -139,7 +134,8 @@ impl <'a> SaplingBuilder<'a> {
OsRng,
)
.map_err(|_| anyhow!("Error generating spend"))?;
self.value_balance = (self.value_balance + note.value()).ok_or(anyhow!("Invalid amount"))?;
self.value_balance =
(self.value_balance + note.value()).ok_or(anyhow!("Invalid amount"))?;
self.spends_compact_hasher.update(nullifier.as_ref());
self.spends_non_compact_hasher.update(&cv.to_bytes());
@ -156,7 +152,13 @@ impl <'a> SaplingBuilder<'a> {
Ok(())
}
pub async fn add_output(&mut self, rseed: [u8; 32], raw_address: [u8; 43], memo: &MemoBytes, amount: u64) -> Result<()> {
pub async fn add_output(
&mut self,
rseed: [u8; 32],
raw_address: [u8; 43],
memo: &MemoBytes,
amount: u64,
) -> Result<()> {
let recipient = PaymentAddress::from_bytes(&raw_address).unwrap();
let rseed = Rseed::AfterZip212(rseed);
@ -201,8 +203,10 @@ impl <'a> SaplingBuilder<'a> {
let memo = &enc_ciphertext[52..564];
self.output_memos_hasher.update(memo);
self.output_non_compact_hasher.update(&cv.as_inner().to_bytes());
self.output_non_compact_hasher.update(&enc_ciphertext[564..]);
self.output_non_compact_hasher
.update(&cv.as_inner().to_bytes());
self.output_non_compact_hasher
.update(&enc_ciphertext[564..]);
self.output_non_compact_hasher.update(&out_ciphertext);
let ephemeral_key = epk.to_bytes();
@ -217,6 +221,36 @@ impl <'a> SaplingBuilder<'a> {
Ok(())
}
pub async fn set_merkle_proof(&mut self, net_chg: i64) -> Result<()> {
let spends_compact_digest = self.spends_compact_hasher.finalize();
log::info!("C SPENDS {}", hex::encode(spends_compact_digest));
let spends_non_compact_digest = self.spends_non_compact_hasher.finalize();
log::info!("NC SPENDS {}", hex::encode(spends_non_compact_digest));
let mut spends_hasher = create_hasher(b"ZTxIdSSpendsHash");
if !self.shielded_spends.is_empty() {
spends_hasher.update(spends_compact_digest.as_bytes());
spends_hasher.update(spends_non_compact_digest.as_bytes());
}
let spends_digest = spends_hasher.finalize();
log::info!("SPENDS {}", hex::encode(spends_digest));
let memos_digest = self.output_memos_hasher.finalize();
log::info!("MEMOS {}", hex::encode(memos_digest));
let outputs_nc_digest = self.output_non_compact_hasher.finalize();
log::info!("NC OUTPUTS {}", hex::encode(outputs_nc_digest));
ledger_set_sapling_merkle_proof(
spends_digest.as_bytes(),
memos_digest.as_bytes(),
outputs_nc_digest.as_bytes(),
)
.await?;
ledger_set_net_sapling(-net_chg).await?;
Ok(())
}
pub async fn sign(&mut self) -> Result<()> {
for _sp in self.shielded_spends.iter() {
let signature = ledger_sign_sapling().await?;
@ -234,29 +268,14 @@ impl <'a> SaplingBuilder<'a> {
Ok(())
}
pub async fn build(self, net_chg: i64) -> Result<Option<Bundle<SapAuthorized>>> {
let spends_compact_digest = self.spends_compact_hasher.finalize();
log::info!("C SPENDS {}", hex::encode(spends_compact_digest));
let spends_non_compact_digest = self.spends_non_compact_hasher.finalize();
log::info!("NC SPENDS {}", hex::encode(spends_non_compact_digest));
let mut spends_hasher = create_hasher(b"ZTxIdSSpendsHash");
if !self.shielded_spends.is_empty() {
spends_hasher.update(spends_compact_digest.as_bytes());
spends_hasher.update(spends_non_compact_digest.as_bytes());
}
let spends_digest = spends_hasher.finalize();
log::info!("SPENDS {}", hex::encode(spends_digest));
let memos_digest = self.output_memos_hasher.finalize();
log::info!("MEMOS {}", hex::encode(memos_digest));
let outputs_nc_digest = self.output_non_compact_hasher.finalize();
log::info!("NC OUTPUTS {}", hex::encode(outputs_nc_digest));
pub async fn build(self) -> Result<Option<Bundle<SapAuthorized>>> {
let has_sapling = !self.shielded_spends.is_empty() || !self.shielded_outputs.is_empty();
if !has_sapling { return Ok(None); }
if !has_sapling {
return Ok(None);
}
let shielded_spends: Vec<_> = self.shielded_spends
let shielded_spends: Vec<_> = self
.shielded_spends
.into_iter()
.zip(self.signatures.into_iter())
.map(|(sp, spend_auth_sig)| SpendDescription::<SapAuthorized> {
@ -274,18 +293,11 @@ impl <'a> SaplingBuilder<'a> {
let sighash = ledger_get_sighash().await?;
log::info!("TXID {}", hex::encode(&sighash));
let binding_sig = self.sapling_context
let binding_sig = self
.sapling_context
.binding_sig(value, &sighash.try_into().unwrap())
.unwrap();
ledger_set_sapling_merkle_proof(
spends_digest.as_bytes(),
memos_digest.as_bytes(),
outputs_nc_digest.as_bytes(),
)
.await?;
ledger_set_net_sapling(-net_chg).await?;
let sapling_bundle = Bundle::<_>::from_parts(
shielded_spends,
self.shielded_outputs,
@ -295,5 +307,4 @@ impl <'a> SaplingBuilder<'a> {
Ok(Some(sapling_bundle))
}
}
}

View File

@ -155,7 +155,7 @@ pub async fn ledger_set_orchard_merkle_proof(
pub async fn ledger_add_t_input(amount: u64) -> Result<()> {
let mut bb: Vec<u8> = vec![];
bb.write_all(&hex!("E015000008"))?;
bb.write_all(&hex!("E015010008"))?;
bb.write_u64::<LE>(amount)?;
apdu(&bb).await?;
Ok(())
@ -222,7 +222,7 @@ pub async fn ledger_set_net_orchard(net: i64) -> Result<()> {
pub async fn ledger_confirm_fee() -> Result<()> {
let mut bb: Vec<u8> = vec![];
bb.write_all(&hex!("E01B000000"))?;
bb.write_all(&hex!("E01B010000"))?;
apdu(&bb).await?;
Ok(())
}

View File

@ -15,7 +15,7 @@ fn main() -> Result<()> {
let mut started = false;
let mut key = String::new();
let mut next_line_is_key = true;
for (i, line) in reader.lines().enumerate() {
for (_i, line) in reader.lines().enumerate() {
let ln = line?.trim_start().to_string();
if ln == "HEADER=END" {
started = true;