mirror of
https://github.com/Qortal/piratewallet-light-cli.git
synced 2025-07-30 03:41:28 +00:00
working
This commit is contained in:
@@ -8,6 +8,7 @@ tower-grpc = { git = "https://github.com/tower-rs/tower-grpc" }
|
|||||||
futures = "0.1"
|
futures = "0.1"
|
||||||
bytes = "0.4"
|
bytes = "0.4"
|
||||||
env_logger = { version = "0.5", default-features = false }
|
env_logger = { version = "0.5", default-features = false }
|
||||||
|
base58 = "0.1.0"
|
||||||
log = "0.4"
|
log = "0.4"
|
||||||
http = "0.1"
|
http = "0.1"
|
||||||
prost = "0.5"
|
prost = "0.5"
|
||||||
@@ -25,6 +26,9 @@ rand = "0.5.6"
|
|||||||
json = "0.12.0"
|
json = "0.12.0"
|
||||||
bip39 = "0.6.0-beta.1"
|
bip39 = "0.6.0-beta.1"
|
||||||
clap = "2.33"
|
clap = "2.33"
|
||||||
|
secp256k1 = "=0.15.0"
|
||||||
|
sha2 = "0.8.0"
|
||||||
|
ripemd160 = "0.8.0"
|
||||||
|
|
||||||
[dependencies.bellman]
|
[dependencies.bellman]
|
||||||
path = "../../librustzcash/bellman"
|
path = "../../librustzcash/bellman"
|
||||||
@@ -41,6 +45,7 @@ default-features = false
|
|||||||
[dependencies.zcash_primitives]
|
[dependencies.zcash_primitives]
|
||||||
path = "../../librustzcash/zcash_primitives"
|
path = "../../librustzcash/zcash_primitives"
|
||||||
default-features = false
|
default-features = false
|
||||||
|
features = ["transparent-inputs"]
|
||||||
|
|
||||||
[dependencies.zcash_proofs]
|
[dependencies.zcash_proofs]
|
||||||
path = "../../librustzcash/zcash_proofs"
|
path = "../../librustzcash/zcash_proofs"
|
||||||
|
@@ -89,8 +89,8 @@ impl Command for SendCommand {
|
|||||||
|
|
||||||
fn exec(&self, _args: &[String], lightclient: &mut LightClient) {
|
fn exec(&self, _args: &[String], lightclient: &mut LightClient) {
|
||||||
lightclient.do_send(
|
lightclient.do_send(
|
||||||
"tmHYDCK6PjBMArtDXwPf5bgoFm2Na5fR6Ds".to_string(),
|
"ztestsapling1x65nq4dgp0qfywgxcwk9n0fvm4fysmapgr2q00p85ju252h6l7mmxu2jg9cqqhtvzd69jwhgv8d".to_string(),
|
||||||
150000,
|
50000000 - 10000,
|
||||||
None);
|
None);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -1,5 +1,3 @@
|
|||||||
pub extern crate ff;
|
|
||||||
|
|
||||||
use std::time::SystemTime;
|
use std::time::SystemTime;
|
||||||
use std::io::{self, Read, Write};
|
use std::io::{self, Read, Write};
|
||||||
use std::cmp;
|
use std::cmp;
|
||||||
@@ -29,6 +27,7 @@ use zcash_primitives::{
|
|||||||
components::Amount, components::amount::DEFAULT_FEE,
|
components::Amount, components::amount::DEFAULT_FEE,
|
||||||
TxId, Transaction
|
TxId, Transaction
|
||||||
},
|
},
|
||||||
|
legacy::{TransparentAddress::PublicKey},
|
||||||
note_encryption::{Memo, try_sapling_note_decryption},
|
note_encryption::{Memo, try_sapling_note_decryption},
|
||||||
zip32::{ExtendedFullViewingKey, ExtendedSpendingKey, ChildIndex},
|
zip32::{ExtendedFullViewingKey, ExtendedSpendingKey, ChildIndex},
|
||||||
JUBJUB,
|
JUBJUB,
|
||||||
@@ -42,11 +41,65 @@ use zcash_primitives::{
|
|||||||
use crate::address;
|
use crate::address;
|
||||||
use crate::prover;
|
use crate::prover;
|
||||||
|
|
||||||
|
|
||||||
|
use sha2::{Sha256, Digest};
|
||||||
|
|
||||||
|
/// Sha256(Sha256(value))
|
||||||
|
pub fn double_sha256(payload: &[u8]) -> Vec<u8> {
|
||||||
|
let h1 = Sha256::digest(&payload);
|
||||||
|
let h2 = Sha256::digest(&h1);
|
||||||
|
h2.to_vec()
|
||||||
|
}
|
||||||
|
|
||||||
|
use base58::{ToBase58, FromBase58};
|
||||||
|
|
||||||
const ANCHOR_OFFSET: u32 = 1;
|
const ANCHOR_OFFSET: u32 = 1;
|
||||||
|
|
||||||
const SAPLING_ACTIVATION_HEIGHT: i32 = 280_000;
|
const SAPLING_ACTIVATION_HEIGHT: i32 = 280_000;
|
||||||
|
|
||||||
|
|
||||||
|
/// A trait for converting a [u8] to base58 encoded string.
|
||||||
|
pub trait ToBase58Check {
|
||||||
|
/// Converts a value of `self` to a base58 value, returning the owned string.
|
||||||
|
/// The version is a coin-specific prefix that is added.
|
||||||
|
/// The suffix is any bytes that we want to add at the end (like the "iscompressed" flag for
|
||||||
|
/// Secret key encoding)
|
||||||
|
fn to_base58check(&self, version: &[u8], suffix: &[u8]) -> String;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ToBase58Check for [u8] {
|
||||||
|
fn to_base58check(&self, version: &[u8], suffix: &[u8]) -> String {
|
||||||
|
let mut payload: Vec<u8> = Vec::new();
|
||||||
|
payload.extend_from_slice(version);
|
||||||
|
payload.extend_from_slice(self);
|
||||||
|
payload.extend_from_slice(suffix);
|
||||||
|
|
||||||
|
let mut checksum = double_sha256(&payload);
|
||||||
|
payload.append(&mut checksum[..4].to_vec());
|
||||||
|
payload.to_base58()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub trait FromBase58Check {
|
||||||
|
fn from_base58check(&self, version: &[u8], suffix: &[u8]) -> Vec<u8>;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
impl FromBase58Check for str {
|
||||||
|
fn from_base58check(&self, version: &[u8], suffix: &[u8]) -> Vec<u8> {
|
||||||
|
let mut payload: Vec<u8> = Vec::new();
|
||||||
|
let bytes = self.from_base58().unwrap();
|
||||||
|
|
||||||
|
let start = version.len();
|
||||||
|
let end = bytes.len() - (4 + suffix.len());
|
||||||
|
|
||||||
|
payload.extend(&bytes[start..end]);
|
||||||
|
|
||||||
|
payload
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
fn now() -> f64 {
|
fn now() -> f64 {
|
||||||
// web_sys::window()
|
// web_sys::window()
|
||||||
// .expect("should have a Window")
|
// .expect("should have a Window")
|
||||||
@@ -861,32 +914,73 @@ impl LightWallet {
|
|||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
// Confirm we were able to select sufficient value
|
// Confirm we were able to select sufficient value
|
||||||
let selected_value = notes
|
// let selected_value = notes
|
||||||
.iter()
|
// .iter()
|
||||||
.map(|selected| selected.note.value)
|
// .map(|selected| selected.note.value)
|
||||||
.sum::<u64>();
|
// .sum::<u64>();
|
||||||
if selected_value < u64::from(target_value) {
|
// if selected_value < u64::from(target_value) {
|
||||||
eprintln!(
|
// eprintln!(
|
||||||
"Insufficient funds (have {}, need {:?})",
|
// "Insufficient funds (have {}, need {:?})",
|
||||||
selected_value, target_value
|
// selected_value, target_value
|
||||||
);
|
// );
|
||||||
return None;
|
// return None;
|
||||||
}
|
// }
|
||||||
|
|
||||||
// Create the transaction
|
// Create the transaction
|
||||||
println!("{}: Adding {} inputs", now() - start_time, notes.len());
|
println!("{}: Adding {} inputs", now() - start_time, notes.len());
|
||||||
let mut builder = Builder::new(height);
|
let mut builder = Builder::new(height);
|
||||||
for selected in notes.iter() {
|
// for selected in notes.iter() {
|
||||||
if let Err(e) = builder.add_sapling_spend(
|
// if let Err(e) = builder.add_sapling_spend(
|
||||||
extsk.clone(),
|
// extsk.clone(),
|
||||||
selected.diversifier,
|
// selected.diversifier,
|
||||||
selected.note.clone(),
|
// selected.note.clone(),
|
||||||
selected.witness.clone(),
|
// selected.witness.clone(),
|
||||||
) {
|
// ) {
|
||||||
eprintln!("Error adding note: {:?}", e);
|
// eprintln!("Error adding note: {:?}", e);
|
||||||
return None;
|
// return None;
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
|
|
||||||
|
// TODO: Temp - Add a transparent input manually for testing
|
||||||
|
use zcash_primitives::transaction::components::{TxOut, OutPoint};
|
||||||
|
use zcash_primitives::legacy::Script;
|
||||||
|
let sk_bytes = "cPYbNomCYVh7Sih2LAFg5WEkGT6kMBfdLzWpdSm8qyrgd7viztVq".from_base58check(&[0xEF], &[0x01]);
|
||||||
|
println!("sk bytes {}", sk_bytes.len());
|
||||||
|
|
||||||
|
let sk = secp256k1::SecretKey::from_slice(&sk_bytes).unwrap();
|
||||||
|
let secp = secp256k1::Secp256k1::new();
|
||||||
|
let pk = secp256k1::PublicKey::from_secret_key(&secp, &sk);
|
||||||
|
|
||||||
|
// Address
|
||||||
|
let mut hash160 = ripemd160::Ripemd160::new();
|
||||||
|
hash160.input(sha2::Sha256::digest(&pk.serialize().to_vec()));
|
||||||
|
let addr = hash160.result().to_base58check(&[0x1D, 0x25], &[]);
|
||||||
|
|
||||||
|
println!("Address = {}", addr);
|
||||||
|
|
||||||
|
let mut script_hash = [0u8; 32];
|
||||||
|
script_hash.copy_from_slice(&hex::decode("d8cd8ca083b3f7e1290c51ba5fb3366fbc4e749256446638318022d8672a6862").unwrap()[0..32]);
|
||||||
|
script_hash.reverse();
|
||||||
|
|
||||||
|
let utxo = OutPoint {
|
||||||
|
hash: script_hash,
|
||||||
|
n: 0
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut script_pubkey = hex::decode("76a914433bf369d77494b07f3ebdec0d09a2edfdc4481688ac").unwrap();
|
||||||
|
let script = Script{0: script_pubkey};
|
||||||
|
match script.address().unwrap() {
|
||||||
|
PublicKey(p) => println!("{}", p.to_base58check(&[0x1D, 0x25], &[])),
|
||||||
|
_ => {}
|
||||||
|
};
|
||||||
|
|
||||||
|
let coin = TxOut {
|
||||||
|
value: Amount::from_u64(50000000).unwrap(),
|
||||||
|
script_pubkey: script,
|
||||||
|
};
|
||||||
|
|
||||||
|
builder.add_transparent_input(sk, utxo, coin).unwrap();
|
||||||
|
|
||||||
// Compute memo if it exists
|
// Compute memo if it exists
|
||||||
let encoded_memo = memo.map(|s| Memo::from_str(&s).unwrap() );
|
let encoded_memo = memo.map(|s| Memo::from_str(&s).unwrap() );
|
||||||
|
Reference in New Issue
Block a user