forked from bitcoinafterlife/bal-server
xpub & Some improvement
This commit is contained in:
113
src/xpub.rs
Normal file
113
src/xpub.rs
Normal file
@@ -0,0 +1,113 @@
|
||||
use bs58;
|
||||
use sha2::{Digest, Sha256};
|
||||
use bitcoin::bip32::Xpub;
|
||||
use std::str::FromStr;
|
||||
use bitcoin::bip32::DerivationPath;
|
||||
use bitcoin::key::Secp256k1;
|
||||
use bitcoin::Address;
|
||||
use bitcoin::ScriptBuf;
|
||||
use bitcoin::WPubkeyHash;
|
||||
use bitcoin::Network;
|
||||
use bitcoin::hashes::Hash;
|
||||
|
||||
|
||||
// Mainnet (BIP44/BIP49/BIP84)
|
||||
enum BS58Prefix{
|
||||
Xpub,
|
||||
//Ypub,
|
||||
//Zpub,
|
||||
//Tpub,
|
||||
//Vpub,
|
||||
//Upub
|
||||
}
|
||||
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 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 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)
|
||||
|
||||
|
||||
|
||||
fn base58check_decode(s: &str) -> Result<Vec<u8>, String> {
|
||||
let data = bs58::decode(s).into_vec().map_err(|e| e.to_string())?;
|
||||
if data.len() < 4 {
|
||||
return Err("Data troppo corta".to_string());
|
||||
}
|
||||
let (payload, checksum) = data.split_at(data.len() - 4);
|
||||
let hash = Sha256::digest(&Sha256::digest(payload));
|
||||
if hash[0..4] != checksum[..] {
|
||||
return Err("Checksum invalido".to_string());
|
||||
}
|
||||
Ok(payload.to_vec())
|
||||
}
|
||||
|
||||
fn base58check_encode(data: &[u8]) -> String {
|
||||
let checksum = &Sha256::digest(&Sha256::digest(data))[0..4];
|
||||
let full = [data, checksum].concat();
|
||||
bs58::encode(full).into_string()
|
||||
}
|
||||
|
||||
fn convert_to(zpub: &str,prefix: BS58Prefix) -> Result<String, String> {
|
||||
|
||||
let mut data = base58check_decode(zpub)?;
|
||||
|
||||
if data.len() < 4 {
|
||||
return Err("Non è una zpub valida.".to_string());
|
||||
}
|
||||
data.splice(0..4, match prefix {
|
||||
BS58Prefix::Xpub => XPUB_PREFIX,
|
||||
//BS58Prefix::Ypub => YPUB_PREFIX,
|
||||
//BS58Prefix::Zpub => ZPUB_PREFIX,
|
||||
//BS58Prefix::Vpub => VPUB_PREFIX,
|
||||
//BS58Prefix::Tpub => TPUB_PREFIX,
|
||||
//BS58Prefix::Upub => UPUB_PREFIX,
|
||||
});
|
||||
|
||||
Ok(base58check_encode(&data))
|
||||
}
|
||||
pub fn new_address_from_xpub(zpub: &str, index: i64,network: Network)-> Result<(String,String), Box<dyn std::error::Error>>{
|
||||
let xpub = Xpub::from_str(&convert_to(zpub,BS58Prefix::Xpub)?)?;
|
||||
let path = format!("m/0/{}",index);
|
||||
let derivation_path = DerivationPath::from_str(&path.as_str())?;
|
||||
let secp = Secp256k1::new();
|
||||
let derived_xpub = xpub.derive_pub(&secp, &derivation_path)?;
|
||||
let public_key = derived_xpub.public_key;
|
||||
let pubkey_bytes = public_key.serialize();
|
||||
let witness_program = WPubkeyHash::hash(&pubkey_bytes);
|
||||
let redeem_script = ScriptBuf::new_p2wpkh(&witness_program);
|
||||
//let script_pubkey = ScriptBuf::new_p2sh(&redeem_script.script_hash());
|
||||
let address = Address::from_script(&redeem_script, network)?;
|
||||
//let address = Address::from_script(&script_pubkey, network)?;
|
||||
Ok((address.to_string(),path.to_string()))
|
||||
|
||||
}
|
||||
/*
|
||||
fn main() -> Result<(), Box<dyn std::error::Error>>{
|
||||
//let zpub = "xpub6C29v8gxCXREHUzoGNfqqFqZWxTVEmYtmZshuzfSwBKNmfYQxoizRziCkkUUA4WwJZkJs2i7nttRiC6MQG7mxZpouXeYkTZe3U52RyPAeo2";
|
||||
//let zpub = "vpub5Ut36m34VebUUjdhYaxJCjSPqk3ZR8bA2MXLmbHRQCycAxy5Q1GFPJspLkJywJjBgQnvU3rmwPKTPp1ELLWeXrve3zBufpZR4MRCCTNHzsn";
|
||||
let zpub = "zpub6qdfveGrxBQN3z8paZ88EHpCn5MGXpUoHwQmHhPbj4rPQtUjbWyCHrJFYZGVY7MsmVbDaeu4JYqRqcdLzMx78wZFEWbLrF9FG3gr2MPQC5H";
|
||||
match convert_to(zpub,BS58Prefix::Xpub) {
|
||||
Ok(xpub) => println!("XPUB: {}", xpub),
|
||||
Err(e) => eprintln!("Errore: {}", e),
|
||||
}
|
||||
let xpub = Xpub::from_str(&convert_to(zpub,BS58Prefix::Xpub)?)?;
|
||||
|
||||
let derivation_path = DerivationPath::from_str("m/0/0")?;
|
||||
let secp = Secp256k1::new();
|
||||
let derived_xpub = xpub.derive_pub(&secp, &derivation_path)?;
|
||||
|
||||
let public_key = derived_xpub.public_key;
|
||||
let pubkey_bytes = public_key.serialize();
|
||||
let witness_program = WPubkeyHash::hash(&pubkey_bytes);
|
||||
let redeem_script = ScriptBuf::new_p2wpkh(&witness_program);
|
||||
let script_pubkey = ScriptBuf::new_p2sh(&redeem_script.script_hash());
|
||||
|
||||
// Generate the Bitcoin SegWit (BIP49) address
|
||||
let network = Network::Bitcoin;
|
||||
let address = Address::from_script(&redeem_script, network)?;
|
||||
let address = Address::from_script(&script_pubkey, network)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
*/
|
||||
Reference in New Issue
Block a user