diff --git a/Cargo.toml b/Cargo.toml index 1002012..4965206 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -19,9 +19,9 @@ name = "wallet" path = "src/main/wallet.rs" required-features = ["dotenv"] -[[bin]] -name = "ledger" -path = "src/main/ledger.rs" +#[[bin]] +#name = "ledger" +#path = "src/main/ledger.rs" #[[bin]] #name = "sign" diff --git a/src/ledger/builder/orchard_bundle.rs b/src/ledger/builder/orchard_bundle.rs index fb3cb38..86eb0ff 100644 --- a/src/ledger/builder/orchard_bundle.rs +++ b/src/ledger/builder/orchard_bundle.rs @@ -202,7 +202,7 @@ impl OrchardBuilder { out_ciphertext: out.clone(), }; - let rk_bytes: [u8; 32] = rk.clone().0.into(); + let rk_bytes: [u8; 32] = rk.clone().into(); orchard_memos_hasher.update(&enc[52..564]); orchard_nc_hasher.update(&cv_net.to_bytes()); orchard_nc_hasher.update(&rk_bytes); @@ -275,12 +275,9 @@ impl OrchardBuilder { 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) } @@ -327,334 +324,6 @@ impl OrchardBuilder { } } -pub async fn build_orchard() -> Result<()> { - dotenv::dotenv()?; - let mut prng = ChaCha20Rng::from_seed([0; 32]); - let mut rseed_rng = ChaCha20Rng::from_seed([1; 32]); - let mut alpha_rng = ChaCha20Rng::from_seed([2; 32]); - let _sig_rng = ChaCha20Rng::from_seed([3; 32]); - - let spending_key = hex::decode(dotenv::var("SPENDING_KEY").unwrap()).unwrap(); - let spk = SpendingKey::from_bytes(spending_key.try_into().unwrap()).unwrap(); - let ask = SpendAuthorizingKey::from(&spk); - println!("ASK {:?}", ask); - - let mut file = File::open("/tmp/tx.json").unwrap(); - let mut data = String::new(); - file.read_to_string(&mut data).unwrap(); - let tx_plan: TransactionPlan = serde_json::from_str(&data).unwrap(); - - let mut h = Params::new() - .hash_length(32) - .personal(b"ZTxIdHeadersHash") - .to_state(); - h.update(&hex!("050000800a27a726b4d0d6c200000000")); - h.write_u32::(tx_plan.expiry_height)?; - let header_digest = h.finalize(); - - let orchard_fvk: [u8; 96] = hex::decode(tx_plan.orchard_fvk) - .unwrap() - .try_into() - .unwrap(); - let orchard_fvk = FullViewingKey::from_bytes(&orchard_fvk).unwrap(); - - let anchor = Anchor::from_bytes(tx_plan.orchard_anchor).unwrap(); - - let spends: Vec<_> = tx_plan - .spends - .iter() - .filter_map(|s| match s.source { - Source::Orchard { - id_note: _, - diversifier, - rseed, - rho, - ref witness, - } => { - let diversifier = Diversifier::from_bytes(diversifier); - let address = 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(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, - }) - } - _ => None, - }) - .collect(); - - let outputs: Vec<_> = tx_plan - .outputs - .iter() - .filter_map(|o| match o.destination { - Destination::Orchard(address) => { - let address = Address::from_raw_address_bytes(&address).unwrap(); - let output = OrchardOutput { - recipient: address, - amount: NoteValue::from_raw(o.amount), - memo: o.memo.as_array().clone(), - }; - Some(output) - } - _ => None, - }) - .collect(); - - let _zero_bsk = ValueCommitTrapdoor::zero().into_bsk(); - - let mut orchard_memos_hasher = Params::new() - .hash_length(32) - .personal(b"ZTxIdOrcActMHash") - .to_state(); - let mut orchard_nc_hasher = Params::new() - .hash_length(32) - .personal(b"ZTxIdOrcActNHash") - .to_state(); - - let num_actions = spends.len().max(outputs.len()); - let mut actions = vec![]; - let mut circuits = vec![]; - let mut instances = vec![]; - 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 - let spend = if i < spends.len() { - spends[i].clone() - } else { - OrchardSpend::dummy(&mut prng) - }; - - let output = if i < outputs.len() { - outputs[i].clone() - } else { - OrchardOutput::dummy(&mut prng) - }; - padded_outputs.push(output.clone()); - - let rcv = ValueCommitTrapdoor::random(&mut prng); - sum_rcv = sum_rcv + &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(&orchard_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; - net_value = (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(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 prng); - 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 = Action::from_parts( - rho.clone(), - rk.clone(), - cmx.clone(), - encrypted_note, - cv_net.clone(), - SigningMetadata { - dummy_ask: None, - parts: SigningParts { ak, alpha }, - }, - ); - 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(anchor, cv_net, rho.clone(), rk, cmx, true, true); - instances.push(instance); - } - let actions = NonEmpty::from_slice(&actions).unwrap(); - - let pk = ProvingKey::build(); - let proof = Proof::create(&pk, &circuits, &instances, &mut prng).unwrap(); - let nv = i64::try_from(net_value).unwrap(); - let amount = Amount::from_i64(nv).unwrap(); - - let flags = Flags::from_parts(true, true); - let bsk = sum_rcv.into_bsk(); - let bundle: Bundle<_, Amount> = Bundle::from_parts( - actions, - flags, - amount, - anchor, - InProgress:: { - proof: Unproven { circuits: vec![] }, - sigs: OrchardUnauthorized { bsk: bsk.clone() }, - }, - ); - - let tx_data: TransactionData = TransactionData { - version: TxVersion::Zip225, - consensus_branch_id: BranchId::Nu5, - lock_time: 0, - expiry_height: BlockHeight::from_u32(tx_plan.expiry_height), - transparent_bundle: None, - sprout_bundle: None, - sapling_bundle: None, - orchard_bundle: Some(bundle.clone()), - }; - - let txid_parts = tx_data.digest(TxIdDigester); - let sig_hash = sighash_v5::v5_signature_hash(&tx_data, &SignableInput::Shielded, &txid_parts); - let sig_hash = sig_hash.as_bytes(); - let binding_signature = bsk.sign(&mut prng, &sig_hash); - - ledger_init().await.unwrap(); - ledger_init_tx(header_digest.as_bytes()).await.unwrap(); - ledger_set_orchard_merkle_proof( - &anchor.to_bytes(), - orchard_memos_hasher.finalize().as_bytes(), - orchard_nc_hasher.finalize().as_bytes(), - ) - .await - .unwrap(); - - // no t-in - ledger_set_stage(2).await.unwrap(); - // no t-out - ledger_set_stage(3).await.unwrap(); - // no s-out - ledger_set_stage(4).await.unwrap(); - - for (a, o) in bundle.actions().iter().zip(padded_outputs.iter()) { - let nf = a.nullifier().to_bytes(); - let epk = a.encrypted_note().epk_bytes; - let _address = 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_stage(5).await.unwrap(); - ledger_set_net_orchard(-tx_plan.net_chg[1]).await.unwrap(); - ledger_confirm_fee().await.unwrap(); - - let mut auth_actions = vec![]; - for a in bundle.actions() { - println!("ask {:?}", ask); - println!("alpha {:?}", a.authorization().parts.alpha); - let rsk = ask.randomize(&a.authorization().parts.alpha); - println!("rsk {:?}", rsk); - // let signature: Signature = [0; 64].into(); - // let signature = rsk.sign(&mut sig_rng, sig_hash); - let sig_bytes: [u8; 64] = ledger_sign_orchard().await.unwrap().try_into().unwrap(); - let signature: Signature = sig_bytes.into(); - let auth_action = Action::from_parts( - a.nullifier().clone(), - a.rk().clone(), - a.cmx().clone(), - a.encrypted_note().clone(), - a.cv_net().clone(), - signature, - ); - auth_actions.push(auth_action); - } - let auth_actions = NonEmpty::from_slice(&auth_actions).unwrap(); - - let bundle: Bundle<_, Amount> = Bundle::from_parts( - auth_actions, - Flags::from_parts(true, true), - amount, - anchor.clone(), - Authorized::from_parts(proof, binding_signature), - ); - - let tx_data: TransactionData = TransactionData { - version: TxVersion::Zip225, - consensus_branch_id: BranchId::Nu5, - lock_time: 0, - expiry_height: BlockHeight::from_u32(tx_plan.expiry_height), - transparent_bundle: None, - sprout_bundle: None, - sapling_bundle: None, - orchard_bundle: Some(bundle), - }; - let tx = Transaction::from_data(tx_data).unwrap(); - - let mut tx_bytes = vec![]; - tx.write(&mut tx_bytes).unwrap(); - - let _orchard_memos_hash = orchard_memos_hasher.finalize(); - let _orchard_nc_hash = orchard_nc_hasher.finalize(); - - let mut client = connect_lightwalletd("https://lwdv3.zecwallet.co").await?; - let response = client - .send_transaction(Request::new(RawTransaction { - data: tx_bytes, - height: 0, - })) - .await? - .into_inner(); - - println!("LWD send transaction {:?}", response); - - Ok(()) -} - #[derive(Clone, Debug)] struct OrchardSpend { ask: Option, diff --git a/src/main/ledger.rs b/src/main/ledger.rs index a394e64..c55159a 100644 --- a/src/main/ledger.rs +++ b/src/main/ledger.rs @@ -45,14 +45,6 @@ use hex_literal::hex; #[tokio::main] async fn main() { - // let args = env::args(); - // let device: u32 = args.next().unwrap().parse().unwrap(); - // orchard_bundle::build_orchard().await.unwrap(); - // ledger_init().await.unwrap(); - - // let sk = ledger_test_math(0).await.unwrap(); - // println!("SK {}", hex::encode(&sk)); - let mut rng = ChaCha20Rng::from_seed([4u8; 32]); let (_, _, note) = Note::dummy(&mut rng, None); let cmx: ExtractedNoteCommitment = note.commitment().into(); @@ -76,306 +68,5 @@ async fn main() { let cmu = ledger_cmu(&buffer).await.unwrap(); println!("cmx {:?}", hex::encode(&cmu)); - - // for i in 0..3 { - // let debug_data = ledger_get_debug(i).await.unwrap(); - // println!("debug {}", hex::encode(&debug_data)); - // } - - // for i in 0..10 { - // let sk = ledger_test_math(i).await.unwrap(); - // println!("SK {}", hex::encode(&sk)); - // } - - // let o_fvk = ledger_get_o_fvk().await.unwrap(); - // println!("FVK {}", hex::encode(&o_fvk)); - - // let sk = hex::decode("19778746bfdf33616075940a21c4011263e974ff7b7341a9a8e5713908d39dab").unwrap(); - // let sk = SpendingKey::from_bytes(sk.try_into().unwrap()).unwrap(); - // let ask = SpendAuthorizingKey::from(&sk); - // println!("ask {:?}", ask); - // let fvk = FullViewingKey::from(&sk); - // println!("fvk {}", hex::encode(fvk.to_bytes())); - - } -#[tokio::main] -async fn main1() -> Result<()> { - let params_dir = Path::new(&std::env::var("HOME").unwrap()).join(".zcash-params"); - let prover = LocalTxProver::new( - ¶ms_dir.join("sapling-spend.params"), - ¶ms_dir.join("sapling-output.params"), - ); - let mut file = File::open("/tmp/tx.json").unwrap(); - let mut data = String::new(); - file.read_to_string(&mut data).unwrap(); - let tx_plan: TransactionPlan = serde_json::from_str(&data).unwrap(); - - let mut client = connect_lightwalletd("https://lwdv3.zecwallet.co").await?; - - build_broadcast_tx(&MainNetwork, &mut client, &tx_plan, &prover).await?; - - Ok(()) -} - -const ORCHARD_SPENDAUTHSIG_BASEPOINT_BYTES: [u8; 32] = [ - 99, 201, 117, 184, 132, 114, 26, 141, 12, 161, 112, 123, 227, 12, 127, 12, 95, 68, 95, 62, 124, - 24, 141, 59, 6, 214, 241, 40, 179, 35, 85, 183, -]; - -async fn main3() -> Result<()> { - dotenv::dotenv()?; - let spending_key = hex::decode(dotenv::var("SPENDING_KEY").unwrap()).unwrap(); - - let x = - hex::decode("063b1e0d8b7f64bb2a9465903b46c9019b552951afa5d735817d449d1334c510").unwrap(); - - let expiry_height = 2_500_000; - let mut h = Params::new() - .hash_length(32) - .personal(b"ZTxIdHeadersHash") - .to_state(); - h.update(&hex!("050000800a27a726b4d0d6c200000000")); - h.write_u32::(expiry_height)?; - let header_digest = h.finalize(); - - // let Q: Point = Point::hash_to_curve(Q_PERSONALIZATION)(MERKLE_CRH_PERSONALIZATION.as_bytes()); - // let p = ::from_bytes(&ORCHARD_SPENDAUTHSIG_BASEPOINT_BYTES).unwrap(); - // println!("p {:?}", p); - // let q = Ep::identity() + p; - // println!("q {:?}", q); - // let p = p.double(); - // println!("{:?}", p); - // println!("{}", hex::encode(ORCHARD_SPENDAUTHSIG_BASEPOINT_BYTES)); - let sk = orchard::keys::SpendingKey::from_bytes(spending_key.try_into().unwrap()).unwrap(); - let fvk = orchard::keys::FullViewingKey::from(&sk); - println!("FVK {:?}", fvk); - println!("FVK {}", hex::encode(fvk.to_bytes())); - // let ivk = fvk.to_ivk(Scope::External); - // println!("IVK {:?}", ivk); - // println!("DK {:?}", hex::encode(ivk.dk.to_bytes())); - // let rho = Nullifier::dummy(&mut OsRng); - // println!("rho {}", hex::encode(rho.to_bytes())); - - let rho = Nullifier::from_bytes(&x.clone().try_into().unwrap()).unwrap(); - - let mut prng = ChaCha20Rng::from_seed([0; 32]); - let rcv = ValueCommitTrapdoor::random(&mut prng); - - let mut alpha_rng = ChaCha20Rng::from_seed([1; 32]); - let mut rseed_rng = ChaCha20Rng::from_seed([2; 32]); - - let alpha = pallas::Scalar::random(&mut alpha_rng); - let ak: SpendValidatingKey = fvk.clone().into(); - let rk = ak.randomize(&alpha); - let rk_bytes: [u8; 32] = rk.clone().0.into(); - - let v_net = orchard::value::ValueSum::from_raw(-1000); - let cv_net = orchard::value::ValueCommitment::derive(v_net, rcv.clone()); - - let mut rseed = [0u8; 32]; - rseed_rng.fill_bytes(&mut rseed); - println!("rseed {}", hex::encode(&rseed)); - - let rseed = RandomSeed::from_bytes(rseed, &rho).unwrap(); - println!("esk {:?}", &rseed.esk(&rho)); - println!("psi {:?}", &rseed.psi(&rho)); - println!("rcm {:?}", &rseed.rcm(&rho)); - - let address = fvk.address_at(0u64, Scope::External); - let mut buf = vec![]; - buf.write_all(&rho.to_bytes())?; - buf.write_all(&address.to_raw_address_bytes())?; - buf.write_u64::(400_000)?; - - let note = orchard::Note::from_parts( - address, - orchard::value::NoteValue::from_raw(400_000), - rho, - rseed, - ) - .unwrap(); - println!("note {:?}", note); - let cmx: ExtractedNoteCommitment = note.commitment().into(); - println!("cmx {:?}", cmx); - // ledger_test_math(&buf).await?; - - let mut memo = [0u8; 512]; - memo[0] = 0xF6; - - let encryptor = orchard::note_encryption::OrchardNoteEncryption::new( - None, - note.clone(), - address.clone(), - memo, - ); - - let epk = encryptor.epk().to_bytes().0; - let enc = encryptor.encrypt_note_plaintext(); - let out = encryptor.encrypt_outgoing_plaintext(&cv_net.clone(), &cmx, &mut prng); - let encrypted_note = orchard::note::TransmittedNoteCiphertext { - epk_bytes: epk.clone(), - enc_ciphertext: enc.clone(), - out_ciphertext: out.clone(), - }; - - let merkle_path = MerklePath::dummy(&mut prng); - let anchor = merkle_path.root(cmx); - - let _authorization = zcash_primitives::transaction::components::orchard::Unauthorized {}; - - let action = orchard::Action::from_parts( - rho.clone(), - rk, - cmx, - encrypted_note, - cv_net.clone(), - Signature::::from([0; 64]), - ); - let _actions = NonEmpty::new(action); - let _circuit = Circuit::from_action_context_unchecked( - orchard::builder::SpendInfo::new(fvk.clone(), note.clone(), merkle_path).unwrap(), - note, - alpha, - rcv.clone(), - ); - - let mut orchard_memos_hasher = Params::new() - .hash_length(32) - .personal(b"ZTxIdOrcActMHash") - .to_state(); - orchard_memos_hasher.update(&enc[52..564]); - let orchard_memos_hash = orchard_memos_hasher.finalize(); - - let mut orchard_nc_hasher = Params::new() - .hash_length(32) - .personal(b"ZTxIdOrcActNHash") - .to_state(); - 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); - let orchard_nc_hash = orchard_nc_hasher.finalize(); - - // let mut orchard_builder = orchard::builder::Builder::new(Flags::from_byte(3).unwrap(), - // anchor); - // orchard_builder.add_spend(fvk.clone(), note, merkle_path).unwrap(); - // orchard_builder.add_recipient(None, address.clone(), - // orchard::value::NoteValue::from_raw(399_000), None).unwrap(); - // let bundle: orchard::Bundle, _> = orchard_builder.build(&mut prng).unwrap(); - - let _bsk = rcv.into_bsk(); - - let _pk = ProvingKey::build(); - // let instance = action.to_instance(Flags::from_parts(true, true), anchor.clone()); - // let bundle = orchard::Bundle::from_parts(actions, - // Flags::from_byte(3).unwrap(), - // Amount::from_i64(-1000).unwrap(), - // anchor, - // InProgress:: { - // proof: Unproven { circuits: vec![circuit] }, - // sigs: OrchardUnauthorized { bsk } - // } - // ); - // let proof = bundle.create_proof(&pk, &mut prng).unwrap(); - // let proof = proof.authorization(); - // let proof = &proof.proof; - - // let bundle = orchard::Bundle::from_parts(actions, - // Flags::from_byte(3).unwrap(), - // Amount::from_i64(-1000).unwrap(), - // anchor, - // orchard::bundle::Authorized { - // proof: todo!(), - // binding_signature: todo!(), - // } - // ); - - let tx_data: TransactionData = TransactionData { - version: TxVersion::Zip225, - consensus_branch_id: BranchId::Nu5, - lock_time: 0, - expiry_height: BlockHeight::from_u32(expiry_height), - transparent_bundle: None, - sprout_bundle: None, - sapling_bundle: None, - orchard_bundle: None, - }; - - let txid_parts = tx_data.digest(TxIdDigester); - let sig_hash = sighash_v5::v5_signature_hash(&tx_data, &SignableInput::Shielded, &txid_parts); - - println!("ORCHARD memos {:?}", orchard_memos_hash); - println!("ORCHARD nc {:?}", orchard_nc_hash); - - println!("SIGHASH PARTS {:?}", txid_parts); - println!("SIGHASH {:?}", sig_hash); - - ledger_init().await.unwrap(); - ledger_init_tx(header_digest.as_bytes()).await.unwrap(); - ledger_set_orchard_merkle_proof( - &anchor.to_bytes(), - orchard_memos_hash.as_bytes(), - orchard_nc_hash.as_bytes(), - ) - .await - .unwrap(); - - // no t-in - ledger_set_stage(2).await.unwrap(); - // no t-out - ledger_set_stage(3).await.unwrap(); - // no s-out - ledger_set_stage(4).await.unwrap(); - ledger_add_o_action( - &x, - 400_000, - &epk, - &address.to_raw_address_bytes(), - &enc[0..52], - ) - .await - .unwrap(); - ledger_set_stage(5).await.unwrap(); - - ledger_set_net_orchard(-1000).await.unwrap(); - - ledger_confirm_fee().await.unwrap(); - - // println!("address {}", hex::encode(address.to_raw_address_bytes())); - - // let esk = ExtendedSpendingKey::master(&[1; 32]); - // let (_, pa) = esk.default_address(); - // let ta = TransparentAddress::PublicKey([1; 20]); - - // let ua = UnifiedAddress::from_receivers( - // Some(address), - // Some(pa), - // Some(ta), - // ).unwrap(); - // let ua = ua.encode(&MainNetwork); - // println!("UA {}", ua); - - // let mut message = [1u8; 128]; - // f4jumble::f4jumble_mut(&mut message[..]).unwrap(); - // println!("f4 {}", hex::encode(message)); - - // println!("{}", hex::encode(address.to_raw_address_bytes())); - // let a = zcash_address::ZcashAddress::try_from_encoded("u1hlpt22xwe3sy034cdjhtnlp4l39zwa7xsj6tsxq0d2p9mv0gzsxnzkpc3wxpv6nh9s2kyxe54qnnxujxc8wqjemvlelzsdxlm7feqdjuksgpx45w3we563apmtmxhql6aa584u9569pdaq3q8h9p8gma67z5td3sckhamh99aqkgf3cg76rykn2e2pwxdjm8wdya0w39355rgvhxvpw").unwrap(); - // if let zcash_address::AddressKind::Unified(r) = a.kind { - // let Address(rs) = r; - // let r = &rs[0]; - // if let Receiver::Orchard(address) = r { - // println!("address {}", hex::encode(address)); - // } - // } - // println!("a {:?}", a); - - // ledger_init().await?; - // ledger_test_math().await?; - // let fvk = ledger_get_o_fvk().await?; - // println!("FVK {}", hex::encode(&fvk)); - - Ok(()) -}