formatting code

This commit is contained in:
2026-02-06 12:03:10 -04:00
parent 8e322ca441
commit 7604406fdf
3 changed files with 217 additions and 69 deletions

View File

@@ -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()),
} }
@@ -216,7 +220,7 @@ async fn main_result(cfg: &MyConfig, network_params: &NetworkParams) -> Result<(
let average_time = bcinfo.median_time; let average_time = bcinfo.median_time;
let db = sqlite::open(&cfg.db_file).unwrap(); let db = sqlite::open(&cfg.db_file).unwrap();
info!("db open {}",&cfg.db_file); info!("db open {}", &cfg.db_file);
let sqlquery = "SELECT * FROM tbl_tx WHERE network = :network AND status = :status AND ( locktime < :bestblock_height OR locktime > :locktime_threshold AND locktime < :bestblock_time);"; let sqlquery = "SELECT * FROM tbl_tx WHERE network = :network AND status = :status AND ( locktime < :bestblock_height OR locktime > :locktime_threshold AND locktime < :bestblock_time);";
let query_tx = db.prepare(sqlquery).unwrap().into_iter(); let query_tx = db.prepare(sqlquery).unwrap().into_iter();
@@ -294,7 +298,7 @@ async fn main_result(cfg: &MyConfig, network_params: &NetworkParams) -> Result<(
} }
} }
let _ = send_stats_report(cfg, bcinfo).await; let _ = send_stats_report(cfg, bcinfo).await;
let _ = calculate_stats(&db,network_params.db_field.clone()).await; let _ = calculate_stats(&db, network_params.db_field.clone()).await;
} }
Err(erx) => { Err(erx) => {
panic!("impossible to get client {}", erx) panic!("impossible to get client {}", erx)
@@ -302,13 +306,14 @@ async fn main_result(cfg: &MyConfig, network_params: &NetworkParams) -> Result<(
} }
Ok(()) Ok(())
} }
async fn calculate_stats(db: &Connection,chain: String) -> Result<(), reqwest::Error> { async fn calculate_stats(db: &Connection, chain: String) -> Result<(), reqwest::Error> {
//let sql = "drop table if exists tbl_stats;"; //let sql = "drop table if exists tbl_stats;";
let sql = "DELETE FROM tbl_stats WHERE chain = '{chain}';"; let sql = "DELETE FROM tbl_stats WHERE chain = '{chain}';";
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,10 +342,11 @@ 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
SELECT SELECT
CURRENT_TIMESTAMP AS report_date, CURRENT_TIMESTAMP AS report_date,
'{chain}' as chain, '{chain}' as chain,
@@ -364,10 +370,9 @@ ON CONFLICT(chain) DO UPDATE SET
unique_inputs = (SELECT COUNT(*) FROM tbl_inp JOIN tbl_tx ON(tbl_inp.txid = tbl_tx.txid) WHERE tbl_tx.status=0 AND tbl_tx.network ='{chain}') unique_inputs = (SELECT COUNT(*) FROM tbl_inp JOIN tbl_tx ON(tbl_inp.txid = tbl_tx.txid) WHERE tbl_tx.status=0 AND tbl_tx.network ='{chain}')
WHERE chain = '{chain}' WHERE chain = '{chain}'
*/ */
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();

View File

@@ -71,7 +71,7 @@ struct MyConfig {
} }
#[derive(Debug, Serialize, Deserialize)] #[derive(Debug, Serialize, Deserialize)]
pub struct InfoResponse{ pub struct InfoResponse {
pub address: String, pub address: String,
pub base_fee: u64, pub base_fee: u64,
pub chain: String, pub chain: String,
@@ -82,14 +82,14 @@ pub struct InfoResponse{
pub struct StatsResponse { pub struct StatsResponse {
pub report_date: String, pub report_date: String,
pub chain: String, pub chain: String,
pub totals:i64, pub totals: i64,
pub waiting:i64, pub waiting: i64,
pub sent:i64, pub sent: i64,
pub failed:i64, pub failed: i64,
pub waiting_profit:i64, pub waiting_profit: i64,
pub sent_profit:i64, pub sent_profit: i64,
pub missed_profit:i64, pub missed_profit: i64,
pub unique_inputs:i64, pub unique_inputs: i64,
} }
impl Default for MyConfig { impl Default for MyConfig {
@@ -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,15 +139,15 @@ 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);
if !netconfig.enabled { if !netconfig.enabled {
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,26 +158,43 @@ 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); ",
let mut stats:Vec<StatsResponse>=vec![]; netconfig.name
);
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());
dbg!(&row); dbg!(&row);
stats.push(StatsResponse{ stats.push(StatsResponse {
report_date: row["report_date"].clone().unwrap().to_string(), report_date: row["report_date"].clone().unwrap().to_string(),
chain: row["chain"].clone().unwrap().to_string(), chain: row["chain"].clone().unwrap().to_string(),
totals: row["totals"].clone().unwrap().parse::<i64>().unwrap(), totals: row["totals"].clone().unwrap().parse::<i64>().unwrap(),
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
}); });
@@ -185,8 +205,7 @@ async fn echo_stats(
} }
Err(err) => Ok(Response::new(full(format!("error:{}", err)))), Err(err) => Ok(Response::new(full(format!("error:{}", err)))),
} }
} }
async fn echo_info( async fn echo_info(
param: &str, param: &str,
@@ -332,7 +351,7 @@ async fn echo_push(
*response_not_enable.status_mut() = StatusCode::BAD_REQUEST; *response_not_enable.status_mut() = StatusCode::BAD_REQUEST;
let netconfig = MyConfig::get_net_config(cfg, param); let netconfig = MyConfig::get_net_config(cfg, param);
if !netconfig.enabled { if !netconfig.enabled {
trace!("network not enabled {}",&netconfig.name); trace!("network not enabled {}", &netconfig.name);
return Ok(response_not_enable); return Ok(response_not_enable);
} }
let req_time = Utc::now().timestamp_nanos_opt().unwrap(); // Returns i64 let req_time = Utc::now().timestamp_nanos_opt().unwrap(); // Returns i64
@@ -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;

View File

@@ -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(())
} }*/
*/