xpub related update
This commit is contained in:
		
							parent
							
								
									793b6dccf0
								
							
						
					
					
						commit
						713eb8fbaa
					
				| @ -1,12 +1,13 @@ | ||||
| RUST_LOG=info | ||||
| RUST_LOG=trace | ||||
| BAL_SERVER_DB_FILE=/home/bal/bal.db | ||||
| BAL_SERVER_INFO="BAL server test willexecutor" | ||||
| BAL_SERVER_BIND_ADDRESS=127.0.0.1 | ||||
| BAL_SERVER_BIND_PORT=9137 | ||||
| BAL_SERVER_BIND_PORT=9133 | ||||
| BAL_SERVER_BITCOIN_ADDRESS="your bitcoin to recive payments here" | ||||
| BAL_SERVER_BITCOIN_FIXED_FEE=50000 | ||||
| 
 | ||||
| #BAL_SERVER_REGTEST_ADDRESS= | ||||
| #BAL_SERVER_REGTEST_FEE=100000 | ||||
| BAL_SERVER_REGTEST_ADDRESS="vpub5UhLrYG1qQjnJhvJgBdqgpznyH11mxW9hwBYxf3KhfdjiupCFPUVDvgwpeZ9Wj5YUJXjKjXjy7DSbJNBW1sXbKwARiaphm1UjHYy3mKvTG4" | ||||
| BAL_SERVER_REGTEST_FEE=5000 | ||||
| #BAL_SERVER_TESTNET_ADDRESS= | ||||
| #BAL_SERVER_TESTNET_FEE=100000 | ||||
| #BAL_SERVER_SIGNET_ADDRESS= | ||||
|  | ||||
| @ -349,7 +349,7 @@ fn main(){ | ||||
|     env_logger::init(); | ||||
|     let mut cfg: MyConfig = match env::var("BAL_PUSHER_CONFIG_FILE") { | ||||
|         Ok(value) => { | ||||
|                 match confy::load_path(value.to_string()){ | ||||
|                 match confy::load_path(&value){ | ||||
|                     Ok(val) => { | ||||
|                         info!("The configuration file path is: {:#?}", value); | ||||
|                         val | ||||
| @ -393,7 +393,7 @@ fn main(){ | ||||
| 
 | ||||
|     socket.set_subscribe(b"").unwrap(); 
 | ||||
| 
 | ||||
|     let _ = main_result(&cfg,&network_params); | ||||
|     let _ = main_result(&cfg,network_params); | ||||
|     info!("waiting new blocks.."); | ||||
|     let mut last_seq:Vec<u8>=[0;4].to_vec(); | ||||
|     loop { | ||||
| @ -414,7 +414,7 @@ fn main(){ | ||||
|         if topic == b"hashblock" { | ||||
|             info!("NEW BLOCK{}", hex::encode(body));  
 | ||||
|             //let cfg = cfg.clone();
 | ||||
|             let _ = main_result(&cfg,&network_params); | ||||
|             let _ = main_result(&cfg,network_params); | ||||
|         } | ||||
|         thread::sleep(Duration::from_millis(100)); // Sleep for 100ms
 | ||||
|     } | ||||
|  | ||||
| @ -51,8 +51,8 @@ impl NetConfig { | ||||
|             address: "".to_string(), | ||||
|             fixed_fee: 50000, | ||||
|             xpub: false, | ||||
|             name:name, | ||||
|             network:network, | ||||
|             name, | ||||
|             network, | ||||
|             enabled: false, | ||||
|         } | ||||
|     } | ||||
| @ -64,11 +64,22 @@ struct MyConfig { | ||||
|     signet: NetConfig, | ||||
|     testnet: NetConfig, | ||||
|     mainnet: NetConfig, | ||||
|     info:   String, | ||||
|     bind_address: String, | ||||
|     bind_port: u16, // Changed to u16 for port numbers
 | ||||
|     db_file: String, | ||||
| } | ||||
| 
 | ||||
| #[derive(Debug,Serialize, Deserialize)] | ||||
| pub struct Info { | ||||
|     pub address:    String, | ||||
|     pub base_fee:   u64, | ||||
|     pub chain:      String, | ||||
|     pub info:       String, | ||||
|     pub version:    String | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| impl Default for MyConfig { | ||||
|     fn default() -> Self { | ||||
|         MyConfig { | ||||
| @ -79,6 +90,7 @@ impl Default for MyConfig { | ||||
|             bind_address: "127.0.0.1".to_string(), | ||||
|             bind_port: 9137, 
 | ||||
|             db_file: "bal.db".to_string(), | ||||
|             info:"Will Executor Server".to_string() | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @ -129,31 +141,44 @@ async fn echo_info( | ||||
|                 } | ||||
|             } | ||||
|         }; | ||||
|         trace!("address: {}:{}",address,netconfig.fixed_fee); | ||||
|         return Ok(Response::new(full("{\"address\":\"".to_owned()+&address+"\",\"base_fee\":\""+&netconfig.fixed_fee.to_string()+"\"}"))); | ||||
|         let info = Info{ | ||||
|             address, | ||||
|             base_fee:   netconfig.fixed_fee, | ||||
|             chain:      netconfig.network.to_string(), | ||||
|             info:       cfg.info.to_string(), | ||||
|             version:    VERSION.to_string() | ||||
| 
 | ||||
|         }; | ||||
|         trace!("address: {:#?}",info); | ||||
|         match serde_json::to_string(&info){ | ||||
|             Ok(json_data) => Ok(Response::new(full(json_data))), | ||||
|             Err(err) => Ok(Response::new(full(format!("error:{}",err)))) | ||||
|         } | ||||
| 
 | ||||
| 
 | ||||
| } | ||||
| async fn echo_search(whole_body: &Bytes, | ||||
|                      cfg: &MyConfig, 
 | ||||
| ) -> Result<Response<BoxBody<Bytes, hyper::Error>>, hyper::Error> { | ||||
|     info!("echo search!!!"); | ||||
|     let strbody = std::str::from_utf8(&whole_body).unwrap(); | ||||
|     let strbody = std::str::from_utf8(whole_body).unwrap(); | ||||
|     info!("{}",strbody); | ||||
| 
 | ||||
|     let mut response = Response::new(full("Bad data received".to_owned())); | ||||
|     *response.status_mut() = StatusCode::BAD_REQUEST; 
 | ||||
|     if strbody.len() >0 && strbody.len()<=70 { | ||||
|     if !strbody.is_empty() && strbody.len()<=70 { | ||||
|         let db = sqlite::open(&cfg.db_file).unwrap(); | ||||
|         let mut statement = db.prepare("SELECT * FROM tbl_tx WHERE txid = ?").unwrap(); | ||||
|         let mut statement = db.prepare("SELECT * FROM tbl_tx WHERE txid = ? LIMIT 1").unwrap(); | ||||
|         statement.bind((1, strbody)).unwrap(); | ||||
| 
 | ||||
|         while let Ok(State::Row) = statement.next() { | ||||
|         if let Ok(State::Row) = statement.next() { | ||||
|             let mut response_data = HashMap::new(); | ||||
|             match statement.read::<String, _>("status") { | ||||
|                 Ok(value) => response_data.insert("status", value), | ||||
|                 Err(e) => { | ||||
|                     error!("Error reading status: {}", e); | ||||
|                     break; | ||||
|                     //response_data.insert("status", "Error".to_string())
 | ||||
|                     None | ||||
|                 } | ||||
|             }; | ||||
| 
 | ||||
| @ -162,8 +187,8 @@ async fn echo_search(whole_body: &Bytes, | ||||
|                 Ok(value) => response_data.insert("tx", value), | ||||
|                 Err(e) => { | ||||
|                     error!("Error reading tx: {}", e); | ||||
|                     break; | ||||
|                     //response_data.insert("tx", "Error".to_string())
 | ||||
|                     None | ||||
|                 } | ||||
|             }; | ||||
| 
 | ||||
| @ -171,8 +196,8 @@ async fn echo_search(whole_body: &Bytes, | ||||
|                 Ok(value) => response_data.insert("our_address", value), | ||||
|                 Err(e) => { | ||||
|                     error!("Error reading address: {}", e); | ||||
|                     break; | ||||
|                     //response_data.insert("tx", "Error".to_string())
 | ||||
|                     None | ||||
|                 } | ||||
|             }; | ||||
| 
 | ||||
| @ -180,8 +205,8 @@ async fn echo_search(whole_body: &Bytes, | ||||
|                 Ok(value) => response_data.insert("our_fees", value), | ||||
|                 Err(e) => { | ||||
|                     error!("Error reading fees: {}", e); | ||||
|                     break; | ||||
|                     //response_data.insert("tx", "Error".to_string())
 | ||||
|                     None | ||||
|                 } | ||||
|             }; | ||||
| 
 | ||||
| @ -190,13 +215,13 @@ async fn echo_search(whole_body: &Bytes, | ||||
|                 Ok(value) => response_data.insert("time", value), | ||||
|                 Err(e) => { | ||||
|                     error!("Error reading reqid: {}", e); | ||||
|                     break; | ||||
|                     //response_data.insert("time", "Error".to_string())
 | ||||
|                     None | ||||
|                 } | ||||
|             }; | ||||
|             response = match serde_json::to_string(&response_data){ | ||||
|                 Ok(json_data) => Response::new(full(json_data)), | ||||
|                 Err(_) => {break;} | ||||
|                 Err(_) => { response } | ||||
|             }; | ||||
| 
 | ||||
|             return Ok(response); | ||||
| @ -211,19 +236,18 @@ async fn echo_push(whole_body: &Bytes, | ||||
|                    param: &str, | ||||
| ) -> Result<Response<BoxBody<Bytes, hyper::Error>>, hyper::Error> { | ||||
|     //let whole_body = req.collect().await?.to_bytes();
 | ||||
|     let strbody = std::str::from_utf8(&whole_body).unwrap(); | ||||
|     info!("network:{}\n{}",¶m, &strbody); | ||||
| 
 | ||||
|     let strbody = std::str::from_utf8(whole_body).unwrap(); | ||||
|     let mut response = Response::new(full("Bad data received".to_owned())); | ||||
|     let mut response_not_enable = Response::new(full("Network not enabled".to_owned())); | ||||
|     *response.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{ | ||||
|         return Ok(response_not_enable); 
 | ||||
|     } | ||||
|     let req_time = Utc::now().timestamp_nanos_opt().unwrap(); // Returns i64
 | ||||
|     
 | ||||
|     let db = sqlite::open(&cfg.db_file).unwrap(); | ||||
|     
 | ||||
|     let lines = strbody.split("\n"); | ||||
|     let sqltxshead = "INSERT INTO tbl_tx (txid, wtxid, ntxid, tx, locktime, reqid, network, our_address, our_fees)".to_string(); | ||||
| @ -236,8 +260,6 @@ async fn echo_push(whole_body: &Bytes, | ||||
|     let mut union_inps = true; | ||||
|     let mut union_outs = true; | ||||
|     let mut already_present = false; | ||||
|     let db = sqlite::open(&cfg.db_file).unwrap(); | ||||
|     let netconfig = MyConfig::get_net_config(cfg,param); | ||||
|     let mut ptx:Vec<(usize, Value)> = vec![]; | ||||
|     let mut pinps:Vec<(usize, Value)> = vec![]; | ||||
|     let mut pouts:Vec<(usize, Value)> = vec![]; | ||||
| @ -245,7 +267,7 @@ async fn echo_push(whole_body: &Bytes, | ||||
|     let mut lineinp = 1; | ||||
|     let mut lineout = 1; | ||||
|     for line in lines { | ||||
|         if line.len() == 0{ | ||||
|         if line.is_empty(){ | ||||
|             trace!("line len is: {}",line.len()); | ||||
|             continue
 | ||||
|         } | ||||
| @ -258,7 +280,7 @@ async fn echo_push(whole_body: &Bytes, | ||||
|                 continue
 | ||||
|             } | ||||
|         }; | ||||
|         if raw_tx.len() > 0 { | ||||
|         if !raw_tx.is_empty(){ | ||||
|             trace!("len: {}",raw_tx.len()); | ||||
|             let tx: Transaction = match consensus::deserialize(&raw_tx){ | ||||
|                 Ok(tx) => tx, | ||||
| @ -280,13 +302,13 @@ async fn echo_push(whole_body: &Bytes, | ||||
|             let mut our_address:String = "".to_string(); | ||||
|             let mut our_fees:u64 = 0; | ||||
|             for input in tx.input{ | ||||
|                 if union_inps == false { | ||||
|                 if !union_inps { | ||||
|                     sqlinps = format!("{sqlinps} UNION ALL"); | ||||
|                 }else{ | ||||
|                     union_inps = false; | ||||
|                 } | ||||
|                 sqlinps = format!("{sqlinps} SELECT ?, ?, ?"); | ||||
|                 pinps.push((lineinp+0,Value::String(txid.to_string()))); | ||||
|                 pinps.push((lineinp,Value::String(txid.to_string()))); | ||||
|                 pinps.push((lineinp+1,Value::String(input.previous_output.txid.to_string()))); | ||||
|                 pinps.push((lineinp+2,Value::String(input.previous_output.vout.to_string()))); | ||||
|                 lineinp += 3; | ||||
| @ -295,8 +317,7 @@ async fn echo_push(whole_body: &Bytes, | ||||
|             if netconfig.fixed_fee ==0 { | ||||
|                 found = true; | ||||
|             } | ||||
|             let mut idx = 0; | ||||
|             for output in tx.output{ | ||||
|             for (idx,output) in tx.output.into_iter().enumerate(){ | ||||
|                 let script_pubkey = output.script_pubkey; | ||||
|                 let address = match bitcoin::Address::from_script(script_pubkey.as_script(), netconfig.network){ | ||||
|                     Ok(address) => address.to_string(), | ||||
| @ -306,7 +327,7 @@ async fn echo_push(whole_body: &Bytes, | ||||
|                 our_fees = netconfig.fixed_fee;//search wllexecutor output
 | ||||
|                 if netconfig.xpub{ | ||||
|                     let sql="select * from tbl_address where address=?"; | ||||
|                     let mut stmt = db.prepare(&sql).expect("failed to fetch addresses"); | ||||
|                     let mut stmt = db.prepare(sql).expect("failed to fetch addresses"); | ||||
|                     stmt.bind((1,Value::String(address.to_string()))).unwrap(); | ||||
|                     if let Ok(State::Row) = stmt.next() { | ||||
|                         our_address = address.to_string(); | ||||
| @ -320,30 +341,29 @@ async fn echo_push(whole_body: &Bytes, | ||||
|                     found = true; | ||||
|                     trace!("address and fees are correct {}: {}",our_address,our_fees); | ||||
|                 } | ||||
|                 if union_outs == false { | ||||
|                 if !union_outs { | ||||
|                     sqlouts = format!("{sqlouts} UNION ALL"); | ||||
|                 }else{ | ||||
|                     union_outs = false; | ||||
|                 } | ||||
|                 sqlouts = format!("{sqlouts} SELECT ?, ?, ?, ?"); | ||||
|                 pouts.push((lineout+0,Value::String(txid.to_string()))); | ||||
|                 pouts.push((lineout+1,Value::Integer(idx))); | ||||
|                 pouts.push((lineout,Value::String(txid.to_string()))); | ||||
|                 pouts.push((lineout+1,Value::Integer(idx.try_into().unwrap()))); | ||||
|                 pouts.push((lineout+2,Value::String(script_pubkey.to_string()))); | ||||
|                 pouts.push((lineout+3,Value::Integer(amount.to_sat().try_into().unwrap()))); | ||||
|                 idx += 1; | ||||
|                 lineout += 4; | ||||
|             } | ||||
|             if found == false{ | ||||
|             if !found { | ||||
|                 error!("willexecutor output not found "); | ||||
|                 return Ok(response) | ||||
|             } else { | ||||
|                 if union_tx == false { | ||||
|                 if !union_tx { | ||||
|                     sqltxs = format!("{sqltxs} UNION ALL"); | ||||
|                 }else{ | ||||
|                     union_tx = false; | ||||
|                 } | ||||
|                 sqltxs = format!("{sqltxs}  SELECT ?, ?, ?, ?, ?, ?, ?, ?, ?"); | ||||
|                 ptx.push((linenum+0,Value::String(txid))); | ||||
|                 ptx.push((linenum,Value::String(txid))); | ||||
|                 ptx.push((linenum+1,Value::String(wtxid.to_string()))); | ||||
|                 ptx.push((linenum+2,Value::String(ntxid.to_string()))); | ||||
|                 ptx.push((linenum+3,Value::String(line.to_string()))); | ||||
| @ -359,10 +379,8 @@ async fn echo_push(whole_body: &Bytes, | ||||
|             debug!("{}",&sqltxs); | ||||
|         } | ||||
|     }   
 | ||||
|     if sqltxs.len()== 0{ | ||||
|         if already_present == true{ | ||||
|             return Ok(Response::new(full("already present"))) | ||||
|         } | ||||
|     if sqltxs.is_empty() && already_present { | ||||
|         return Ok(Response::new(full("already present"))) | ||||
|     } | ||||
|     let sqltxs = format!("{}{};", sqltxshead, sqltxs); | ||||
|     let sqlinps = format!("{}{};", sqlinpshead, sqlinps); | ||||
| @ -384,8 +402,6 @@ fn match_uri<'a>(path: &str, uri: &'a str) -> Option<&'a str> { | ||||
|     None | ||||
| } | ||||
| 
 | ||||
| /// This is our service handler. It receives a Request, routes on its
 | ||||
| /// path, and returns a Future of a Response.
 | ||||
| 
 | ||||
| async fn echo( | ||||
|     req: Request<hyper::body::Incoming>, | ||||
| @ -401,9 +417,9 @@ async fn echo( | ||||
| 
 | ||||
|     let remote_addr = req.headers().get("X-Real-IP").and_then(|value| value.to_str().ok()).and_then(|xff| xff.split(',').next()).map(|ip| ip.trim().to_string()).unwrap_or_else(|| ip.to_string()); | ||||
|     trace!("{}: {}",remote_addr,uri); | ||||
|     match req.method() { | ||||
|     match *req.method() { | ||||
|         // Serve some instructions at /
 | ||||
|         &Method::POST => { | ||||
|         Method::POST => { | ||||
|             let whole_body = req.collect().await?.to_bytes(); | ||||
|             if let Some(param) = match_uri(r"^?/?(?P<param>[^/]?+)?/pushtxs$",uri.as_str()) { | ||||
|                 //let whole_body = collect_body(req,512_000).await?;
 | ||||
| @ -415,7 +431,7 @@ async fn echo( | ||||
|             } | ||||
|             ret | ||||
|         } | ||||
|         &Method::GET => { | ||||
|         Method::GET => { | ||||
|             if let Some(param) = match_uri(r"^?/?(?P<param>[^/]?+)?/info$",uri.as_str()) { | ||||
|                 ret = echo_info(param,cfg,remote_addr).await; | ||||
|             } | ||||
| @ -443,25 +459,22 @@ fn full<T: Into<Bytes>>(chunk: T) -> BoxBody<Bytes, hyper::Error> { | ||||
| } | ||||
| fn parse_env(cfg: &Arc<Mutex<MyConfig>>){ | ||||
|     let mut cfg_lock = cfg.lock().unwrap(); | ||||
|     match env::var("BAL_SERVER_DB_FILE") { | ||||
|         Ok(value) => { | ||||
|             cfg_lock.db_file = value;}, | ||||
|         Err(_) => {}, | ||||
|     if let Ok(value) = env::var("BAL_SERVER_DB_FILE") { | ||||
|             cfg_lock.db_file = value; | ||||
|     } | ||||
|     match env::var("BAL_SERVER_BIND_ADDRESS") { | ||||
|         Ok(value) => { | ||||
|             cfg_lock.bind_address= value;}, | ||||
|         Err(_) => {}, | ||||
|     if let Ok(value) = env::var("BAL_SERVER_BIND_ADDRESS") { | ||||
|             cfg_lock.bind_address= value; | ||||
|     } | ||||
|     match env::var("BAL_SERVER_BIND_PORT") { | ||||
|         Ok(value) => { | ||||
|             match value.parse::<u16>(){ | ||||
|                 Ok(value) =>{ cfg_lock.bind_port = value; }, | ||||
|                 Err(_) => {}, | ||||
|             } | ||||
|     if let Ok(value) = env::var("BAL_SERVER_BIND_PORT") { | ||||
|         if let Ok(v) = value.parse::<u16>(){ | ||||
|             cfg_lock.bind_port = v; | ||||
|         } | ||||
|         Err(_) => {}, | ||||
|     } | ||||
| 
 | ||||
|     if let Ok(value) = env::var("BAL_SERVER_INFO"){ | ||||
|         cfg_lock.info = value; 
 | ||||
|     } | ||||
| 
 | ||||
|     cfg_lock = parse_env_netconfig(cfg_lock,"regtest");    
 | ||||
|     cfg_lock = parse_env_netconfig(cfg_lock,"signet");    
 | ||||
|     cfg_lock = parse_env_netconfig(cfg_lock,"testnet");    
 | ||||
| @ -475,29 +488,21 @@ fn parse_env_netconfig<'a>(mut cfg_lock: MutexGuard<'a, MyConfig>, chain: &'a st | ||||
|         "testnet" => &mut cfg_lock.testnet, | ||||
|         &_ => &mut cfg_lock.mainnet, | ||||
|     }; | ||||
|     match env::var(format!("BAL_SERVER_{}_ADDRESS",chain.to_uppercase())) { | ||||
|         Ok(value) => { 
 | ||||
|             cfg.address = value; 
 | ||||
|             if cfg.address.len() > 5 { | ||||
|                 if cfg.address[1..4] == *"pub" { | ||||
|                     cfg.xpub=true; | ||||
|                     trace!("is_xpub"); | ||||
|                 } | ||||
|                 cfg.enabled=true; | ||||
|             } | ||||
|         }, | ||||
| 
 | ||||
| 
 | ||||
|         Err(_) => {}, | ||||
|     } | ||||
|     match env::var(format!("BAL_SERVER_{}_FIXE_FEE",chain.to_uppercase())) { | ||||
|         Ok(value) => { | ||||
|             match value.parse::<u64>(){ | ||||
|                 Ok(value) =>{ cfg.fixed_fee = value; }, | ||||
|                 Err(_) => {}, | ||||
|     if let Ok(value) = env::var(format!("BAL_SERVER_{}_ADDRESS",chain.to_uppercase())) { | ||||
|         cfg.address = value; 
 | ||||
|         if cfg.address.len() > 5 { | ||||
|             if cfg.address[1..4] == *"pub" { | ||||
|                 cfg.xpub=true; | ||||
|                 trace!("is_xpub"); | ||||
|             } | ||||
|             cfg.enabled=true; | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     if let Ok(value) = env::var(format!("BAL_SERVER_{}_FIXE_FEE",chain.to_uppercase())) { | ||||
|         if let Ok(v) = value.parse::<u64>(){ | ||||
|             cfg.fixed_fee = v; | ||||
|         } | ||||
|         Err(_) => {}, | ||||
|     } | ||||
|     cfg_lock | ||||
| } | ||||
| @ -505,7 +510,7 @@ fn parse_env_netconfig<'a>(mut cfg_lock: MutexGuard<'a, MyConfig>, chain: &'a st | ||||
| fn init_network(db: &Connection, cfg: &MyConfig){ | ||||
|     for network in NETWORKS{ | ||||
|         let netconfig =  MyConfig::get_net_config(cfg,network); | ||||
|         insert_xpub(&db,&netconfig.name,&netconfig.address); | ||||
|         insert_xpub(db,&netconfig.name,&netconfig.address); | ||||
|     } | ||||
| } | ||||
| #[tokio::main] | ||||
|  | ||||
							
								
								
									
										14
									
								
								src/db.rs
									
									
									
									
									
								
							
							
						
						
									
										14
									
								
								src/db.rs
									
									
									
									
									
								
							| @ -42,7 +42,7 @@ pub fn insert_xpub(db: &Connection, network: &String, xpub: &String){ | ||||
| } | ||||
| 
 | ||||
| pub fn get_last_used_address_by_ip(db: &Connection, network: &String, xpub: &String, address: &String) -> Option<String>{ 
 | ||||
|     let mut stmt = db.prepare("SELECT tbl_address.address FROM tbl_xpub join tbl_address on(tbl_xpub.id = tbl_address.xpub) where tbl_xpub.network = ? and tbl_address.remote_address = ? and tbl_xpub.xpub = ?ORDER BY tbl_address.date_create DESC LIMIT 1;").unwrap(); | ||||
|     let mut stmt = db.prepare("SELECT tbl_address.address FROM tbl_xpub join tbl_address on(tbl_xpub.id = tbl_address.xpub) where tbl_xpub.network = ? and tbl_address.remote_address = ? and tbl_xpub.xpub = ? ORDER BY tbl_address.date_create DESC LIMIT 1;").unwrap(); | ||||
|     let _ = stmt.bind((1,Value::String(network.to_string()))); | ||||
|     let _ = stmt.bind((2,Value::String(address.to_string()))); | ||||
|     let _ = stmt.bind((3,Value::String(xpub.to_string()))); | ||||
| @ -56,8 +56,8 @@ pub fn get_last_used_address_by_ip(db: &Connection, network: &String, xpub: &Str | ||||
| } | ||||
| pub fn get_next_address_index(db: &Connection, network: &String, xpub: &String) -> (i64,i64){ | ||||
|     let mut stmt = db.prepare("UPDATE tbl_xpub SET path_idx = path_idx + 1 WHERE network = ? and xpub= ?  RETURNING path_idx,id;").unwrap(); | ||||
|     let _ = stmt.bind((1,Value::String(network.to_string()))).unwrap(); | ||||
|     let _ = stmt.bind((2,Value::String(xpub.to_string()))).unwrap(); | ||||
|     stmt.bind((1,Value::String(network.to_string()))).unwrap(); | ||||
|     stmt.bind((2,Value::String(xpub.to_string()))).unwrap(); | ||||
|     match stmt.next(){ | ||||
|         Ok(State::Row) =>{ | ||||
|         let next = stmt.read::<i64,_>("path_idx").unwrap(); | ||||
| @ -73,10 +73,10 @@ pub fn get_next_address_index(db: &Connection, network: &String, xpub: &String) | ||||
| pub fn save_new_address(db: &Connection,xpub: i64,address: &String, path: &String,remote_addr: &String){ | ||||
|     let mut stmt = db.prepare("INSERT INTO tbl_address(address,path,xpub,remote_address) VALUES(?,?,?,?);").unwrap(); | ||||
| 
 | ||||
|     let _ = stmt.bind((1,Value::String(address.to_string()))).unwrap(); | ||||
|     let _ = stmt.bind((2,Value::String(path.to_string()))).unwrap(); | ||||
|     let _ = stmt.bind((3,Value::Integer(xpub))).unwrap(); | ||||
|     let _ = stmt.bind((4,Value::String(remote_addr.to_string()))).unwrap(); | ||||
|     stmt.bind((1,Value::String(address.to_string()))).unwrap(); | ||||
|     stmt.bind((2,Value::String(path.to_string()))).unwrap(); | ||||
|     stmt.bind((3,Value::Integer(xpub))).unwrap(); | ||||
|     stmt.bind((4,Value::String(remote_addr.to_string()))).unwrap(); | ||||
| 
 | ||||
|     let _ = stmt.next(); | ||||
| } | ||||
|  | ||||
| @ -1,4 +1,3 @@ | ||||
| use bs58; | ||||
| use sha2::{Digest, Sha256}; | ||||
| use bitcoin::bip32::Xpub; | ||||
| use std::str::FromStr; | ||||
| @ -35,7 +34,7 @@ fn base58check_decode(s: &str) -> Result<Vec<u8>, String> { | ||||
|         return Err("Data troppo corta".to_string()); | ||||
|     } | ||||
|     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[..] { | ||||
|         return Err("Checksum invalido".to_string()); | ||||
|     } | ||||
| @ -43,7 +42,7 @@ fn base58check_decode(s: &str) -> Result<Vec<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(); | ||||
|     bs58::encode(full).into_string() | ||||
| } | ||||
| @ -69,7 +68,7 @@ fn convert_to(zpub: &str,prefix: BS58Prefix) -> Result<String, String> { | ||||
| 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 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; | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 bitcoinafterlife
						bitcoinafterlife