formatting code
This commit is contained in:
@@ -11,7 +11,7 @@ use log::{debug, error, info, trace, warn};
|
|||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
use serde_json::json;
|
use serde_json::json;
|
||||||
use sqlite::{Value, Connection};
|
use sqlite::{Connection, Value};
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::env;
|
use std::env;
|
||||||
use std::error::Error as StdError;
|
use std::error::Error as StdError;
|
||||||
@@ -48,14 +48,18 @@ struct MyConfig {
|
|||||||
impl Default for MyConfig {
|
impl Default for MyConfig {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
MyConfig {
|
MyConfig {
|
||||||
zmq_listener: env::var("BAL_PUSHER_ZMQ_LISTENER").unwrap_or("tcp://127.0.0.1:28332".to_string()),
|
zmq_listener: env::var("BAL_PUSHER_ZMQ_LISTENER")
|
||||||
|
.unwrap_or("tcp://127.0.0.1:28332".to_string()),
|
||||||
db_file: env::var("BAL_PUSHER_DB_FILE").unwrap_or("bal.db".to_string()),
|
db_file: env::var("BAL_PUSHER_DB_FILE").unwrap_or("bal.db".to_string()),
|
||||||
bitcoin_dir: env::var("BAL_PUSHER_BITCOIN_DIR").unwrap_or("".to_string()),
|
bitcoin_dir: env::var("BAL_PUSHER_BITCOIN_DIR").unwrap_or("".to_string()),
|
||||||
regtest: get_network_params_default(Network::Regtest),
|
regtest: get_network_params_default(Network::Regtest),
|
||||||
testnet: get_network_params_default(Network::Testnet),
|
testnet: get_network_params_default(Network::Testnet),
|
||||||
signet: get_network_params_default(Network::Signet),
|
signet: get_network_params_default(Network::Signet),
|
||||||
mainnet: get_network_params_default(Network::Bitcoin),
|
mainnet: get_network_params_default(Network::Bitcoin),
|
||||||
send_stats: env::var("BAL_PUSHER_SEND_STATS").unwrap_or("false".to_string()).parse::<bool>().unwrap(),
|
send_stats: env::var("BAL_PUSHER_SEND_STATS")
|
||||||
|
.unwrap_or("false".to_string())
|
||||||
|
.parse::<bool>()
|
||||||
|
.unwrap(),
|
||||||
url: env::var("BAL_SERVER_URL").unwrap_or("http://localhost/".to_string()),
|
url: env::var("BAL_SERVER_URL").unwrap_or("http://localhost/".to_string()),
|
||||||
ssl_key_path: env::var("SSL_KEY_PATH").unwrap_or("privkey.pem".to_string()),
|
ssl_key_path: env::var("SSL_KEY_PATH").unwrap_or("privkey.pem".to_string()),
|
||||||
}
|
}
|
||||||
@@ -308,7 +312,8 @@ async fn calculate_stats(db: &Connection,chain: String) -> Result<(), reqwest::E
|
|||||||
if let Err(err) = db.execute(&sql) {
|
if let Err(err) = db.execute(&sql) {
|
||||||
error!("error deleting from tbl_stats where chain:{chain} error: {err}");
|
error!("error deleting from tbl_stats where chain:{chain} error: {err}");
|
||||||
}
|
}
|
||||||
let sql = format!("INSERT INTO tbl_stats (
|
let sql = format!(
|
||||||
|
"INSERT INTO tbl_stats (
|
||||||
report_date, chain, totals, waiting, sent, failed,
|
report_date, chain, totals, waiting, sent, failed,
|
||||||
waiting_profit, sent_profit, missed_profit, unique_inputs
|
waiting_profit, sent_profit, missed_profit, unique_inputs
|
||||||
)
|
)
|
||||||
@@ -322,7 +327,7 @@ VALUES (
|
|||||||
(SELECT IFNULL(SUM(our_fees),0) FROM tbl_tx WHERE status = 0 AND network = '{chain}'),
|
(SELECT IFNULL(SUM(our_fees),0) FROM tbl_tx WHERE status = 0 AND network = '{chain}'),
|
||||||
(SELECT IFNULL(SUM(our_fees),0) FROM tbl_tx WHERE status = 1 AND network = '{chain}'),
|
(SELECT IFNULL(SUM(our_fees),0) FROM tbl_tx WHERE status = 1 AND network = '{chain}'),
|
||||||
(SELECT IFNULL(SUM(our_fees),0) FROM tbl_tx WHERE status = 2 AND network = '{chain}'),
|
(SELECT IFNULL(SUM(our_fees),0) FROM tbl_tx WHERE status = 2 AND network = '{chain}'),
|
||||||
(SELECT COUNT(DISTINCT tbl_inp.in_txid) -- or appropriate input identifier
|
(SELECT COUNT(DISTINCT tbl_inp.in_txid)
|
||||||
FROM tbl_inp
|
FROM tbl_inp
|
||||||
JOIN tbl_tx ON tbl_inp.txid = tbl_tx.txid
|
JOIN tbl_tx ON tbl_inp.txid = tbl_tx.txid
|
||||||
WHERE tbl_tx.status = 0 AND tbl_tx.network = '{chain}')
|
WHERE tbl_tx.status = 0 AND tbl_tx.network = '{chain}')
|
||||||
@@ -337,7 +342,8 @@ ON CONFLICT(chain) DO UPDATE SET
|
|||||||
sent_profit = excluded.sent_profit,
|
sent_profit = excluded.sent_profit,
|
||||||
missed_profit = excluded.missed_profit,
|
missed_profit = excluded.missed_profit,
|
||||||
unique_inputs = excluded.unique_inputs;
|
unique_inputs = excluded.unique_inputs;
|
||||||
");
|
"
|
||||||
|
);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
let sql = format!("CREATE TABLE tbl_stats AS
|
let sql = format!("CREATE TABLE tbl_stats AS
|
||||||
@@ -366,8 +372,7 @@ ON CONFLICT(chain) DO UPDATE SET
|
|||||||
*/
|
*/
|
||||||
if let Err(err) = db.execute(&sql) {
|
if let Err(err) = db.execute(&sql) {
|
||||||
error!("error inserting creating stats table {err}");
|
error!("error inserting creating stats table {err}");
|
||||||
}
|
} else {
|
||||||
else{
|
|
||||||
info!("tbl_stats creation success");
|
info!("tbl_stats creation success");
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
@@ -495,7 +500,6 @@ fn parse_env_netconfig(cfg_lock: &mut MyConfig, chain: &str) -> NetworkParams {
|
|||||||
cfg.clone()
|
cfg.clone()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
fn check_zmq_connection(endpoint: &str) -> bool {
|
fn check_zmq_connection(endpoint: &str) -> bool {
|
||||||
trace!("check zmq connection");
|
trace!("check zmq connection");
|
||||||
let context = Context::new();
|
let context = Context::new();
|
||||||
|
|||||||
@@ -104,7 +104,10 @@ impl Default for MyConfig {
|
|||||||
db_file: "bal.db".to_string(),
|
db_file: "bal.db".to_string(),
|
||||||
info: "Will Executor Server".to_string(),
|
info: "Will Executor Server".to_string(),
|
||||||
pub_key_path: "public_key.pem".to_string(),
|
pub_key_path: "public_key.pem".to_string(),
|
||||||
expose_stats:env::var("BAL_SERVER_EXPOSE_STATS").unwrap_or("false".to_string()).parse::<bool>().unwrap(),
|
expose_stats: env::var("BAL_SERVER_EXPOSE_STATS")
|
||||||
|
.unwrap_or("false".to_string())
|
||||||
|
.parse::<bool>()
|
||||||
|
.unwrap(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -136,7 +139,6 @@ async fn echo_pub_key(
|
|||||||
async fn echo_stats(
|
async fn echo_stats(
|
||||||
param: &str,
|
param: &str,
|
||||||
cfg: &MyConfig,
|
cfg: &MyConfig,
|
||||||
remote_addr: &String,
|
|
||||||
) -> Result<Response<BoxBody<Bytes, hyper::Error>>, hyper::Error> {
|
) -> Result<Response<BoxBody<Bytes, hyper::Error>>, hyper::Error> {
|
||||||
info!("echo stats!!! {} - {}", param, cfg.expose_stats);
|
info!("echo stats!!! {} - {}", param, cfg.expose_stats);
|
||||||
let netconfig = MyConfig::get_net_config(cfg, param);
|
let netconfig = MyConfig::get_net_config(cfg, param);
|
||||||
@@ -144,7 +146,8 @@ async fn echo_stats(
|
|||||||
debug!("network disabled {}", param);
|
debug!("network disabled {}", param);
|
||||||
return Ok(Response::new(full("network disabled")));
|
return Ok(Response::new(full("network disabled")));
|
||||||
}
|
}
|
||||||
let sql = format!("SELECT
|
let sql = format!(
|
||||||
|
"SELECT
|
||||||
report_date,
|
report_date,
|
||||||
chain,
|
chain,
|
||||||
totals,
|
totals,
|
||||||
@@ -155,11 +158,16 @@ async fn echo_stats(
|
|||||||
sent_profit,
|
sent_profit,
|
||||||
missed_profit,
|
missed_profit,
|
||||||
unique_inputs FROM tbl_stats where chain = '{}'
|
unique_inputs FROM tbl_stats where chain = '{}'
|
||||||
", netconfig.name);
|
",
|
||||||
|
netconfig.name
|
||||||
|
);
|
||||||
let mut stats: Vec<StatsResponse> = vec![];
|
let mut stats: Vec<StatsResponse> = vec![];
|
||||||
let db = sqlite::open(&cfg.db_file).unwrap();
|
let db = sqlite::open(&cfg.db_file).unwrap();
|
||||||
db.iterate(&sql,|pairs|{
|
let _ = db.iterate(&sql, |pairs| {
|
||||||
let row: HashMap<_, _> = pairs.into_iter().map(|(k,v)| (k.to_string(), v.map(|s| s))).collect();
|
let row: HashMap<_, _> = pairs
|
||||||
|
.into_iter()
|
||||||
|
.map(|(k, v)| (k.to_string(), v.map(|s| s)))
|
||||||
|
.collect();
|
||||||
//let row:HashMap<_,_>= pairs.into_iter().collect();
|
//let row:HashMap<_,_>= pairs.into_iter().collect();
|
||||||
println!("row report date {}", row["report_date"].clone().unwrap());
|
println!("row report date {}", row["report_date"].clone().unwrap());
|
||||||
|
|
||||||
@@ -171,10 +179,22 @@ async fn echo_stats(
|
|||||||
waiting: row["waiting"].clone().unwrap().parse::<i64>().unwrap(),
|
waiting: row["waiting"].clone().unwrap().parse::<i64>().unwrap(),
|
||||||
sent: row["sent"].clone().unwrap().parse::<i64>().unwrap(),
|
sent: row["sent"].clone().unwrap().parse::<i64>().unwrap(),
|
||||||
failed: row["failed"].clone().unwrap().parse::<i64>().unwrap(),
|
failed: row["failed"].clone().unwrap().parse::<i64>().unwrap(),
|
||||||
waiting_profit: row["waiting_profit"].clone().unwrap().parse::<i64>().unwrap(),
|
waiting_profit: row["waiting_profit"]
|
||||||
|
.clone()
|
||||||
|
.unwrap()
|
||||||
|
.parse::<i64>()
|
||||||
|
.unwrap(),
|
||||||
sent_profit: row["sent_profit"].clone().unwrap().parse::<i64>().unwrap(),
|
sent_profit: row["sent_profit"].clone().unwrap().parse::<i64>().unwrap(),
|
||||||
missed_profit:row["missed_profit"].clone().unwrap().parse::<i64>().unwrap(),
|
missed_profit: row["missed_profit"]
|
||||||
unique_inputs: row["unique_inputs"].clone().unwrap().parse::<i64>().unwrap(),
|
.clone()
|
||||||
|
.unwrap()
|
||||||
|
.parse::<i64>()
|
||||||
|
.unwrap(),
|
||||||
|
unique_inputs: row["unique_inputs"]
|
||||||
|
.clone()
|
||||||
|
.unwrap()
|
||||||
|
.parse::<i64>()
|
||||||
|
.unwrap(),
|
||||||
});
|
});
|
||||||
true
|
true
|
||||||
});
|
});
|
||||||
@@ -187,7 +207,6 @@ async fn echo_stats(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
async fn echo_info(
|
async fn echo_info(
|
||||||
param: &str,
|
param: &str,
|
||||||
cfg: &MyConfig,
|
cfg: &MyConfig,
|
||||||
@@ -438,7 +457,7 @@ async fn echo_push(
|
|||||||
}
|
}
|
||||||
if address == our_address && amount.to_sat() >= netconfig.fixed_fee {
|
if address == our_address && amount.to_sat() >= netconfig.fixed_fee {
|
||||||
our_fees = amount.to_sat();
|
our_fees = amount.to_sat();
|
||||||
our_address = netconfig.address.to_string();
|
//our_address = netconfig.address.to_string();
|
||||||
found = true;
|
found = true;
|
||||||
trace!("address and fees are correct {}: {}", our_address, our_fees);
|
trace!("address and fees are correct {}: {}", our_address, our_fees);
|
||||||
}
|
}
|
||||||
@@ -541,7 +560,7 @@ async fn echo(
|
|||||||
}
|
}
|
||||||
Method::GET => {
|
Method::GET => {
|
||||||
if let Some(param) = match_uri(r"^?/?(?P<param>[^/]?+)?/stats$", uri.as_str()) {
|
if let Some(param) = match_uri(r"^?/?(?P<param>[^/]?+)?/stats$", uri.as_str()) {
|
||||||
ret = echo_stats(param, cfg, &remote_addr).await;
|
ret = echo_stats(param, cfg).await;
|
||||||
}
|
}
|
||||||
if let Some(param) = match_uri(r"^?/?(?P<param>[^/]?+)?/info$", uri.as_str()) {
|
if let Some(param) = match_uri(r"^?/?(?P<param>[^/]?+)?/info$", uri.as_str()) {
|
||||||
ret = echo_info(param, cfg, &remote_addr).await;
|
ret = echo_info(param, cfg, &remote_addr).await;
|
||||||
|
|||||||
177
src/xpub.rs
177
src/xpub.rs
@@ -1,3 +1,4 @@
|
|||||||
|
//use bs58;
|
||||||
use bitcoin::Address;
|
use bitcoin::Address;
|
||||||
use bitcoin::Network;
|
use bitcoin::Network;
|
||||||
use bitcoin::ScriptBuf;
|
use bitcoin::ScriptBuf;
|
||||||
@@ -12,18 +13,141 @@ use std::str::FromStr;
|
|||||||
// Mainnet (BIP44/BIP49/BIP84)
|
// Mainnet (BIP44/BIP49/BIP84)
|
||||||
enum BS58Prefix {
|
enum BS58Prefix {
|
||||||
Xpub,
|
Xpub,
|
||||||
//Ypub,
|
Ypub,
|
||||||
//Zpub,
|
Zpub,
|
||||||
//Tpub,
|
Tpub,
|
||||||
//Vpub,
|
Vpub,
|
||||||
//Upub
|
Upub,
|
||||||
}
|
}
|
||||||
const XPUB_PREFIX: [u8; 4] = [0x04, 0x88, 0xB2, 0x1E]; // xpub (Legacy P2PKH)
|
const XPUB_PREFIX: [u8; 4] = [0x04, 0x88, 0xB2, 0x1E]; // xpub (Legacy P2PKH)
|
||||||
//const YPUB_PREFIX:[u8; 4] = [0x04, 0x9D, 0x7C, 0xB2]; // ypub (Nested SegWit P2SH-P2WPKH)
|
const YPUB_PREFIX: [u8; 4] = [0x04, 0x9D, 0x7C, 0xB2]; // ypub (Nested SegWit P2SH-P2WPKH)
|
||||||
//const ZPUB_PREFIX:[u8; 4] = [0x04, 0xB2, 0x47, 0x46]; // zpub (Native SegWit P2WPKH)
|
const ZPUB_PREFIX: [u8; 4] = [0x04, 0xB2, 0x47, 0x46]; // zpub (Native SegWit P2WPKH)
|
||||||
//const TPUB_PREFIX:[u8; 4] = [0x04, 0x35, 0x87, 0xCF]; // tpub (Testnet Legacy P2PKH)
|
const TPUB_PREFIX: [u8; 4] = [0x04, 0x35, 0x87, 0xCF]; // tpub (Testnet Legacy P2PKH)
|
||||||
//const VPUB_PREFIX:[u8; 4] = [0x04, 0x5F, 0x1C, 0xF6]; // vpub (Testnet Nested SegWit)
|
const VPUB_PREFIX: [u8; 4] = [0x04, 0x5F, 0x1C, 0xF6]; // vpub (Testnet Nested SegWit)
|
||||||
//const UPUB_PREFIX:[u8; 4] = [0x04, 0x4A, 0x52, 0x62]; // upub (RegTest Nested SegWit)
|
const UPUB_PREFIX: [u8; 4] = [0x04, 0x4A, 0x52, 0x62]; // upub (RegTest Nested SegWit)
|
||||||
|
// Constants from Bitcoin Core's checksum algorithm
|
||||||
|
const INPUT_CHARSET: &[u8] = b"0123456789()[],'/*abcdefgh@:$%{}IJKLMNOPQRSTUVWXYZ&+-.;<=>?!^_|~ijklmnopqrstuvwxyzABCDEFGH`#\"\\ ";
|
||||||
|
const CHECKSUM_CHARSET: &[u8] = b"qpzry9x8gf2tvdw0s3jn54khce6mua7l";
|
||||||
|
|
||||||
|
// Polynomial modulo function used in checksum calculation (same as in Bitcoin Core)
|
||||||
|
fn poly_mod(mut c: u64, val: u64) -> u64 {
|
||||||
|
let c0 = c >> 35;
|
||||||
|
c = ((c & 0x7ffffffff) << 5) ^ val;
|
||||||
|
if c0 & 1 > 0 {
|
||||||
|
c ^= 0xf5dee51989
|
||||||
|
};
|
||||||
|
if c0 & 2 > 0 {
|
||||||
|
c ^= 0xa9fdca3312
|
||||||
|
};
|
||||||
|
if c0 & 4 > 0 {
|
||||||
|
c ^= 0x1bab10e32d
|
||||||
|
};
|
||||||
|
if c0 & 8 > 0 {
|
||||||
|
c ^= 0x3706b1677a
|
||||||
|
};
|
||||||
|
if c0 & 16 > 0 {
|
||||||
|
c ^= 0x644d626ffd
|
||||||
|
};
|
||||||
|
|
||||||
|
c
|
||||||
|
}
|
||||||
|
|
||||||
|
// Calculate checksum for a descriptor string
|
||||||
|
fn calc_checksum(desc: &str) -> Result<String, String> {
|
||||||
|
// Separate descriptor from any existing checksum
|
||||||
|
let desc = match desc.split_once('#') {
|
||||||
|
Some((d, _)) => d,
|
||||||
|
None => desc,
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut c: u64 = 1;
|
||||||
|
let mut cls: u64 = 0;
|
||||||
|
let mut clscount: u64 = 0;
|
||||||
|
|
||||||
|
// Process each character in the descriptor
|
||||||
|
for ch in desc.as_bytes() {
|
||||||
|
let pos = match INPUT_CHARSET.iter().position(|b| b == ch) {
|
||||||
|
Some(p) => p as u64,
|
||||||
|
None => return Err(format!("Invalid character in descriptor: {}", *ch as char)),
|
||||||
|
};
|
||||||
|
|
||||||
|
c = poly_mod(c, pos & 31);
|
||||||
|
cls = cls * 3 + (pos >> 5);
|
||||||
|
clscount += 1;
|
||||||
|
|
||||||
|
if clscount == 3 {
|
||||||
|
c = poly_mod(c, cls);
|
||||||
|
cls = 0;
|
||||||
|
clscount = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if clscount > 0 {
|
||||||
|
c = poly_mod(c, cls);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Final steps in checksum calculation
|
||||||
|
for _ in 0..8 {
|
||||||
|
c = poly_mod(c, 0);
|
||||||
|
}
|
||||||
|
c ^= 1;
|
||||||
|
|
||||||
|
// Convert checksum to characters
|
||||||
|
let mut checksum = String::with_capacity(8);
|
||||||
|
for j in 0..8 {
|
||||||
|
let idx = ((c >> (5 * (7 - j))) & 31) as usize;
|
||||||
|
checksum.push(CHECKSUM_CHARSET[idx] as char);
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(checksum)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_bitcoincore_descriptor(xpub: &String) -> String {
|
||||||
|
let fingerprint = calculate_fingerprint(xpub);
|
||||||
|
let mut bip = 84;
|
||||||
|
let cpub = xpub.to_string();
|
||||||
|
match &xpub[0..4] {
|
||||||
|
"vpub" => {
|
||||||
|
bip = 84;
|
||||||
|
}
|
||||||
|
"zpub" => {
|
||||||
|
bip = 84;
|
||||||
|
}
|
||||||
|
&_ => {
|
||||||
|
bip = 84;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
let descriptor = format!(
|
||||||
|
"wpkh([{}/84h/0h/0h]{}/0/*)",
|
||||||
|
fingerprint,
|
||||||
|
convert_xpub(xpub)
|
||||||
|
);
|
||||||
|
let descriptor = match calc_checksum(&descriptor) {
|
||||||
|
Ok(checksum) => {
|
||||||
|
let clean_descriptor = descriptor.split('#').next().unwrap_or(&descriptor);
|
||||||
|
format!("{}#{}", clean_descriptor, checksum)
|
||||||
|
}
|
||||||
|
Err(err) => {
|
||||||
|
eprintln!("Error: {}", err);
|
||||||
|
"".to_string()
|
||||||
|
}
|
||||||
|
};
|
||||||
|
descriptor
|
||||||
|
//format!("{}#{}",descriptor,checksum)
|
||||||
|
}
|
||||||
|
fn convert_xpub(xpub: &String) -> String {
|
||||||
|
if xpub[0..4] == *"xpub" || xpub[0..4] == *"ypub" || xpub[0..4] == *"zpub" {
|
||||||
|
return convert_to(xpub, BS58Prefix::Xpub).unwrap();
|
||||||
|
} else {
|
||||||
|
return convert_to(xpub, BS58Prefix::Tpub).unwrap();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pub fn calculate_fingerprint(tpub: &str) -> String {
|
||||||
|
let xpub = Xpub::from_str(&convert_to(tpub, BS58Prefix::Xpub).unwrap()).unwrap();
|
||||||
|
let fp = xpub.fingerprint();
|
||||||
|
let pp = xpub.parent_fingerprint;
|
||||||
|
format!("{}", fp)
|
||||||
|
}
|
||||||
|
|
||||||
fn base58check_decode(s: &str) -> Result<Vec<u8>, String> {
|
fn base58check_decode(s: &str) -> Result<Vec<u8>, String> {
|
||||||
let data = bs58::decode(s).into_vec().map_err(|e| e.to_string())?;
|
let data = bs58::decode(s).into_vec().map_err(|e| e.to_string())?;
|
||||||
@@ -31,7 +155,7 @@ fn base58check_decode(s: &str) -> Result<Vec<u8>, String> {
|
|||||||
return Err("Data troppo corta".to_string());
|
return Err("Data troppo corta".to_string());
|
||||||
}
|
}
|
||||||
let (payload, checksum) = data.split_at(data.len() - 4);
|
let (payload, checksum) = data.split_at(data.len() - 4);
|
||||||
let hash = Sha256::digest(Sha256::digest(payload));
|
let hash = Sha256::digest(&Sha256::digest(payload));
|
||||||
if hash[0..4] != checksum[..] {
|
if hash[0..4] != checksum[..] {
|
||||||
return Err("Checksum invalido".to_string());
|
return Err("Checksum invalido".to_string());
|
||||||
}
|
}
|
||||||
@@ -39,7 +163,7 @@ fn base58check_decode(s: &str) -> Result<Vec<u8>, String> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn base58check_encode(data: &[u8]) -> String {
|
fn base58check_encode(data: &[u8]) -> String {
|
||||||
let checksum = &Sha256::digest(Sha256::digest(data))[0..4];
|
let checksum = &Sha256::digest(&Sha256::digest(data))[0..4];
|
||||||
let full = [data, checksum].concat();
|
let full = [data, checksum].concat();
|
||||||
bs58::encode(full).into_string()
|
bs58::encode(full).into_string()
|
||||||
}
|
}
|
||||||
@@ -54,11 +178,11 @@ fn convert_to(zpub: &str, prefix: BS58Prefix) -> Result<String, String> {
|
|||||||
0..4,
|
0..4,
|
||||||
match prefix {
|
match prefix {
|
||||||
BS58Prefix::Xpub => XPUB_PREFIX,
|
BS58Prefix::Xpub => XPUB_PREFIX,
|
||||||
//BS58Prefix::Ypub => YPUB_PREFIX,
|
BS58Prefix::Ypub => YPUB_PREFIX,
|
||||||
//BS58Prefix::Zpub => ZPUB_PREFIX,
|
BS58Prefix::Zpub => ZPUB_PREFIX,
|
||||||
//BS58Prefix::Vpub => VPUB_PREFIX,
|
BS58Prefix::Vpub => VPUB_PREFIX,
|
||||||
//BS58Prefix::Tpub => TPUB_PREFIX,
|
BS58Prefix::Tpub => TPUB_PREFIX,
|
||||||
//BS58Prefix::Upub => UPUB_PREFIX,
|
BS58Prefix::Upub => UPUB_PREFIX,
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -71,7 +195,7 @@ pub fn new_address_from_xpub(
|
|||||||
) -> Result<(String, String), Box<dyn std::error::Error>> {
|
) -> Result<(String, String), Box<dyn std::error::Error>> {
|
||||||
let xpub = Xpub::from_str(&convert_to(zpub, BS58Prefix::Xpub)?)?;
|
let xpub = Xpub::from_str(&convert_to(zpub, BS58Prefix::Xpub)?)?;
|
||||||
let path = format!("m/0/{}", index);
|
let path = format!("m/0/{}", index);
|
||||||
let derivation_path = DerivationPath::from_str(path.as_str())?;
|
let derivation_path = DerivationPath::from_str(&path.as_str())?;
|
||||||
let secp = Secp256k1::new();
|
let secp = Secp256k1::new();
|
||||||
let derived_xpub = xpub.derive_pub(&secp, &derivation_path)?;
|
let derived_xpub = xpub.derive_pub(&secp, &derivation_path)?;
|
||||||
let public_key = derived_xpub.public_key;
|
let public_key = derived_xpub.public_key;
|
||||||
@@ -85,15 +209,17 @@ pub fn new_address_from_xpub(
|
|||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
fn main() -> Result<(), Box<dyn std::error::Error>>{
|
fn main() -> Result<(), Box<dyn std::error::Error>>{
|
||||||
//let zpub = "xpub6C29v8gxCXREHUzoGNfqqFqZWxTVEmYtmZshuzfSwBKNmfYQxoizRziCkkUUA4WwJZkJs2i7nttRiC6MQG7mxZpouXeYkTZe3U52RyPAeo2";
|
match convert_to(zpub,BS58Prefix::Tpub) {
|
||||||
//let zpub = "vpub5Ut36m34VebUUjdhYaxJCjSPqk3ZR8bA2MXLmbHRQCycAxy5Q1GFPJspLkJywJjBgQnvU3rmwPKTPp1ELLWeXrve3zBufpZR4MRCCTNHzsn";
|
Ok(tpub) => println!("XPUB: {}", tpub),
|
||||||
let zpub = "zpub6qdfveGrxBQN3z8paZ88EHpCn5MGXpUoHwQmHhPbj4rPQtUjbWyCHrJFYZGVY7MsmVbDaeu4JYqRqcdLzMx78wZFEWbLrF9FG3gr2MPQC5H";
|
|
||||||
match convert_to(zpub,BS58Prefix::Xpub) {
|
|
||||||
Ok(xpub) => println!("XPUB: {}", xpub),
|
|
||||||
Err(e) => eprintln!("Errore: {}", e),
|
Err(e) => eprintln!("Errore: {}", e),
|
||||||
}
|
}
|
||||||
let xpub = Xpub::from_str(&convert_to(zpub,BS58Prefix::Xpub)?)?;
|
let fingerprint = base58check_encode(&calculate_fingerprint(zpub));
|
||||||
|
println!("ZPUB: {}, FINGERPRINT: {}",zpub,fingerprint);
|
||||||
|
|
||||||
|
let xpub = Xpub::from_str(&convert_to(zpub,BS58Prefix::Xpub)?)?;
|
||||||
|
let tpub = convert_to(zpub,BS58Prefix::Tpub)?;
|
||||||
|
let fingerprint = base58check_encode(&calculate_fingerprint(&tpub));
|
||||||
|
println!("TPUB: {}, FINGERPRINT: {}",tpub,fingerprint);
|
||||||
let derivation_path = DerivationPath::from_str("m/0/0")?;
|
let derivation_path = DerivationPath::from_str("m/0/0")?;
|
||||||
let secp = Secp256k1::new();
|
let secp = Secp256k1::new();
|
||||||
let derived_xpub = xpub.derive_pub(&secp, &derivation_path)?;
|
let derived_xpub = xpub.derive_pub(&secp, &derivation_path)?;
|
||||||
@@ -110,5 +236,4 @@ fn main() -> Result<(), Box<dyn std::error::Error>>{
|
|||||||
let address = Address::from_script(&script_pubkey, network)?;
|
let address = Address::from_script(&script_pubkey, network)?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}*/
|
||||||
*/
|
|
||||||
|
|||||||
Reference in New Issue
Block a user