8 Commits

Author SHA1 Message Date
fa98283df6 version 2026-01-19 20:03:17 -04:00
d5fe22cc14 bal server route / 2025-11-03 09:36:56 -04:00
83749afddd update version 2025-11-03 08:53:58 -04:00
dd075508b7 fix bal-pusher zmq connection stability 2025-11-03 08:46:13 -04:00
4ac492ba79 fix bal-pusher zmq connection stability 2025-11-03 07:42:09 -04:00
ae52b2b4e5 . 2025-11-01 19:02:15 -04:00
7c8ed123aa send times to welist
ED25519 times signing
2025-11-01 18:34:35 -04:00
d937ee9364 send time to welist server 2025-10-31 16:01:15 -04:00
9 changed files with 239 additions and 111 deletions

12
Cargo.lock generated
View File

@@ -124,8 +124,8 @@ dependencies = [
] ]
[[package]] [[package]]
name = "bal-server" name = "bal_server"
version = "0.1.0" version = "0.2.3"
dependencies = [ dependencies = [
"base64 0.22.1", "base64 0.22.1",
"bitcoin", "bitcoin",
@@ -1315,9 +1315,9 @@ dependencies = [
[[package]] [[package]]
name = "proc-macro2" name = "proc-macro2"
version = "1.0.81" version = "1.0.103"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3d1597b0c024618f09a9c3b8655b7e430397a36d23fdafec26d6965e9eec3eba" checksum = "5ee95bc4ef87b8d5ba32e8b7714ccc834865276eab0aed5c9958d00ec45f49e8"
dependencies = [ dependencies = [
"unicode-ident", "unicode-ident",
] ]
@@ -1753,9 +1753,9 @@ checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292"
[[package]] [[package]]
name = "syn" name = "syn"
version = "2.0.60" version = "2.0.108"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "909518bc7b1c9b779f1bbf07f2929d35af9f0f37e47c6e9ef7f9dddc1e1821f3" checksum = "da58917d35242480a05c2897064da0a80589a2a0476c9a3f2fdc83b53502e917"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",

View File

@@ -1,33 +1,33 @@
[package] [package]
name = "bal-server" name = "bal_server"
version = "0.1.0" version = "0.2.3"
edition = "2021" edition = "2024"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies] [dependencies]
base64 = "0.22.1" base64 = { version = "0.22.1" }
bs58 = "0.4.0" bs58 = { version = "0.4.0" }
bytes = "1.2" bytes = { version = "1.2" }
bitcoin = { version = "0.32.5" } bitcoin = { version = "0.32.5" }
bitcoincore-rpc = "0.19.0" bitcoincore-rpc = { version = "0.19.0" }
bitcoincore-rpc-json = "0.19.0" bitcoincore-rpc-json = { version = "0.19.0" }
byteorder = "1.5.0" byteorder = { version = "1.5.0" }
confy = "0.6.1" confy = { version = "0.6.1" }
chrono = "0.4.40" chrono = { version = "0.4.40" }
env_logger = "0.11.5" env_logger = { version = "0.11.5" }
hex = "0.4.3" hex = { version = "0.4.3" }
hex-conservative = "0.1.1" hex-conservative = { version = "0.1.1" }
hyper = { version = "1.3.1", features = ["http1","server"] } hyper = { version = "1.3.1", features = ["http1","server"] }
hyper-util = { version = "0.1.3", features = ["tokio"] } hyper-util = { version = "0.1.3", features = ["tokio"] }
http-body-util = "0.1" http-body-util = { version = "0.1" }
log = "0.4.21" log = { version = "0.4.21" }
openssl = { version = "0.10.74", features = ["vendored"] } openssl = { version = "0.10.74", features = ["vendored"] }
sha2 = "0.10.8" sha2 = { version = "0.10.8" }
serde = { version = "1.0.152", features = ["derive"] } serde = { version = "1.0.152", features = ["derive"] }
serde_json = "1.0.116" serde_json = { version = "1.0.116" }
sqlite = "0.34.0" sqlite = { version = "0.34.0" }
regex = "1.10.4" regex = { version = "1.10.4" }
reqwest = { version = "0.12.24", features = ["json","socks"] } reqwest = { version = "0.12.24", features = ["json","socks"] }
tokio = { version = "1", features = ["rt", "net","macros","rt-multi-thread"] } # Keep only necessary runtime components tokio = { version = "1", features = ["rt", "net","macros","rt-multi-thread"] } # Keep only necessary runtime components
zmq = "0.10.0" zmq = { version = "0.10.0" }

View File

@@ -1,10 +1,11 @@
# bal-server # bal-server
## Installation ## Installation
```bash ```bash
$ git clone .... $ git clone ....
$ cd bal-server $ cd bal-server
$ openssl genpkey -algorithm ED25519 -out private_key.pem
$ openssl pkey -in private_key.pem -pubout -out public_key.pem
$ cargo build --release $ cargo build --release
$ sudo cp target/release/bal-server /usr/local/bin $ sudo cp target/release/bal-server /usr/local/bin
$ bal-server $ bal-server
@@ -20,6 +21,7 @@ The `bal-server` application can be configured using environment variables. The
| `BAL_SERVER_DB_FILE` | Path to the SQLite3 database file. If the file does not exist, a new one will be created. | `bal.db` | | `BAL_SERVER_DB_FILE` | Path to the SQLite3 database file. If the file does not exist, a new one will be created. | `bal.db` |
| `BAL_SERVER_BIND_ADDRESS` | Public address for listening to requests. | `127.0.0.1` | | `BAL_SERVER_BIND_ADDRESS` | Public address for listening to requests. | `127.0.0.1` |
| `BAL_SERVER_BIND_PORT` | Default port for listening to requests. | `9137` | | `BAL_SERVER_BIND_PORT` | Default port for listening to requests. | `9137` |
| `BAL_SERVER_PUB_KEY_PATH` | WillExecutor Ed25519 public key | `public_key.pem` |
| `BAL_SERVER_REGTEST_ADDRESS` | Bitcoin address for the regtest environment. | - | | `BAL_SERVER_REGTEST_ADDRESS` | Bitcoin address for the regtest environment. | - |
| `BAL_SERVER_REGTEST_FIXED_FEE` | Fixed fee for the regtest environment. | 50000 | | `BAL_SERVER_REGTEST_FIXED_FEE` | Fixed fee for the regtest environment. | 50000 |
| `BAL_SERVER_SIGNET_ADDRESS` | Bitcoin address for the signet environment. | - | | `BAL_SERVER_SIGNET_ADDRESS` | Bitcoin address for the signet environment. | - |
@@ -28,6 +30,8 @@ The `bal-server` application can be configured using environment variables. The
| `BAL_SERVER_TESTNET_FIXED_FEE` | Fixed fee for the testnet environment. | 50000 | | `BAL_SERVER_TESTNET_FIXED_FEE` | Fixed fee for the testnet environment. | 50000 |
| `BAL_SERVER_BITCOIN_ADDRESS` | Bitcoin address for the mainnet environment. | - | | `BAL_SERVER_BITCOIN_ADDRESS` | Bitcoin address for the mainnet environment. | - |
| `BAL_SERVER_BITCOIN_FIXED_FEE` | Fixed fee for the mainnet environment. | 50000 | | `BAL_SERVER_BITCOIN_FIXED_FEE` | Fixed fee for the mainnet environment. | 50000 |
# bal-pusher # bal-pusher
`bal-pusher` is a tool that retrieves Bitcoin transactions from a database and pushes them to the Bitcoin network when their **locktime** exceeds the **median time past** (MTP). It listens for Bitcoin block updates via ZMQ. `bal-pusher` is a tool that retrieves Bitcoin transactions from a database and pushes them to the Bitcoin network when their **locktime** exceeds the **median time past** (MTP). It listens for Bitcoin block updates via ZMQ.
@@ -48,27 +52,6 @@ To use `bal-pusher`, you need to compile and install Bitcoin with ZMQ (ZeroMQ) s
2. **Install Rust and Cargo**: 2. **Install Rust and Cargo**:
If you haven't already installed Rust and Cargo, you can follow the official instructions to do so: [Rust Installation](https://www.rust-lang.org/tools/install). If you haven't already installed Rust and Cargo, you can follow the official instructions to do so: [Rust Installation](https://www.rust-lang.org/tools/install).
### Installation Steps
1. Clone the repository:
```bash
git clone <repo-url>
cd bal-pusher
```
2. Build the project:
```bash
cargo build --release
```
3. Install the binary:
```bash
sudo cp target/release/bal-pusher /usr/local/bin
```
## Configuration ## Configuration
`bal-pusher` can be configured using environment variables. If no configuration file is provided, a default configuration file will be created. `bal-pusher` can be configured using environment variables. If no configuration file is provided, a default configuration file will be created.
@@ -85,6 +68,10 @@ To use `bal-pusher`, you need to compile and install Bitcoin with ZMQ (ZeroMQ) s
| `BAL_PUSHER_BITCOIN_COOKIE_FILE` | Path to Bitcoin RPC cookie file. | `$HOME/.bitcoin/.cookie` | | `BAL_PUSHER_BITCOIN_COOKIE_FILE` | Path to Bitcoin RPC cookie file. | `$HOME/.bitcoin/.cookie` |
| `BAL_PUSHER_BITCOIN_RPC_USER` | Bitcoin RPC username. | - | | `BAL_PUSHER_BITCOIN_RPC_USER` | Bitcoin RPC username. | - |
| `BAL_PUSHER_BITCOIN_RPC_PASSWORD` | Bitcoin RPC password. | - | | `BAL_PUSHER_BITCOIN_RPC_PASSWORD` | Bitcoin RPC password. | - |
| `BAL_PUSHER_SEND_STATS` | Contact welist to provide times | false |
| `WELIST_SERVER_URL` | welist server url to provide times | https://welist.bitcoin-afer.life |
| `BAL_SERVER_URL` | WillExecutor server url | - |
| `SSL_KEY_PATH` | Ed25519 private key pem file | `private_key.pem` |
## Running `bal-pusher` ## Running `bal-pusher`
@@ -92,7 +79,7 @@ To use `bal-pusher`, you need to compile and install Bitcoin with ZMQ (ZeroMQ) s
Once the application is installed and configured, you can start `bal-pusher` by running the following command: Once the application is installed and configured, you can start `bal-pusher` by running the following command:
```bash ```bash
$ bal-pusher $ bal-pusher [bitcoin|testnet|regtest|]
``` ```
This will start the service, which will listen for Bitcoin blocks via ZMQ and push transactions from the database when their locktime exceeds the median time past. This will start the service, which will listen for Bitcoin blocks via ZMQ and push transactions from the database when their locktime exceeds the median time past.

View File

@@ -8,4 +8,9 @@ BAL_PUSHER_SIGNET_COOKIE_FILE=/home/bitcoin/.bitcoin/signet/.cookie
BAL_PUSHER_ZMQ_LISTENER=tcp://127.0.0.1:28332 BAL_PUSHER_ZMQ_LISTENER=tcp://127.0.0.1:28332
BAL_PUSHER_SEND_STATS=true
WELIST_SERVER_URL=http://welist.bitcoin-after.life
SSL_KEY_PATH=/home/bal/privkey.pem
#your server domain. do not final / only domain.
BAL_SERVER_URL="https://we.bitcoin-after.life"

14
bal-pusher.sh Normal file
View File

@@ -0,0 +1,14 @@
RUST_LOG=trace
BAL_PUSHER_DB_FILE="$(pwd)/bal.db"
#export BAL_PUSHER_BITCOIN_COOKIE_FILE=/~/.bitcoin/.cookie
#export BAL_PUSHER_REGTEST_COOKIE_FILE=/~/.bitcoin/regtest/.cookie
#export BAL_PUSHER_TESTNET_COOKIE_FILE=/~/.bitcoin/testnet3/.cookie
#export BAL_PUSHER_SIGNET_COOKIE_FILE=/~/.bitcoin/signet/.cookie
BAL_PUSHER_ZMQ_LISTENER=tcp://127.0.0.1:28332
export BAL_PUSHER_SEND_STATS=true
export WELIST_SERVER_URL=http://localhost:8085
export BAL_SERVER_URL="http://127.0.0.1:9133"
export SSL_KEY_PATH="$(pwd)/private_key.pem"
cargo run --bin=bal-pusher regtest

View File

@@ -1,10 +1,11 @@
RUST_LOG=trace RUST_LOG=info
BAL_SERVER_DB_FILE=/home/bal/bal.db BAL_SERVER_DB_FILE="/home/bal/bal.db"
BAL_SERVER_INFO="BAL server test willexecutor" BAL_SERVER_INFO="BAL server test willexecutor"
BAL_SERVER_BIND_ADDRESS=127.0.0.1 BAL_SERVER_BIND_ADDRESS=127.0.0.1
BAL_SERVER_BIND_PORT=9133 BAL_SERVER_BIND_PORT=9133
BAL_SERVER_BITCOIN_ADDRESS="your bitcoin to recive payments here" BAL_SERVER_BITCOIN_ADDRESS="your bitcoin or xpub to recive payments here"
BAL_SERVER_BITCOIN_FIXED_FEE=50000 BAL_SERVER_BITCOIN_FIXED_FEE=50000
BAL_SERVER_PUB_KEY_PATH="/home/bal/public_key.pem"
BAL_SERVER_REGTEST_ADDRESS="vpub5UhLrYG1qQjnJhvJgBdqgpznyH11mxW9hwBYxf3KhfdjiupCFPUVDvgwpeZ9Wj5YUJXjKjXjy7DSbJNBW1sXbKwARiaphm1UjHYy3mKvTG4" BAL_SERVER_REGTEST_ADDRESS="vpub5UhLrYG1qQjnJhvJgBdqgpznyH11mxW9hwBYxf3KhfdjiupCFPUVDvgwpeZ9Wj5YUJXjKjXjy7DSbJNBW1sXbKwARiaphm1UjHYy3mKvTG4"
BAL_SERVER_REGTEST_FEE=5000 BAL_SERVER_REGTEST_FEE=5000

24
bal-server.sh Normal file
View File

@@ -0,0 +1,24 @@
WORKING_DIR=$(pwd)
if [ ! -f "$WORKING_DIR/public_key.pem" ]; then
echo "creating keypairs"
openssl genpkey -algorithm ED25519 -out private_key.pem
openssl pkey -in private_key.pem -pubout -out public_key.pem
fi
export RUST_LOG="trace"
export BAL_SERVER_DB_FILE="$WORKING_DIR/bal.db"
export BAL_SERVER_INFO="BAL devel willexecutor server"
export BAL_SERVER_BIND_ADDRESS="127.0.0.1"
export BAL_SERVER_BIND_PORT=9133
export BAL_SERVER_PUB_KEY_PATH="$WORKING_DIR/public_key.pem"
#export BAL_SERVER_BITCOIN_ADDRESS="your bitcoin address or xpub to recive payments here"
#export BAL_SERVER_BITCOIN_FIXED_FEE=50000
export BAL_SERVER_REGTEST_ADDRESS="vpub5UhLrYG1qQjnJhvJgBdqgpznyH11mxW9hwBYxf3KhfdjiupCFPUVDvgwpeZ9Wj5YUJXjKjXjy7DSbJNBW1sXbKwARiaphm1UjHYy3mKvTG4"
export BAL_SERVER_REGTEST_FEE=5000
#export BAL_SERVER_TESTNET_ADDRESS=
#export BAL_SERVER_TESTNET_FEE=100000
#export BAL_SERVER_SIGNET_ADDRESS=
#export BAL_SERVER_SIGNET_FEE=100000
cargo run --bin=bal-server

View File

@@ -11,12 +11,12 @@ use serde::Deserialize;
use serde_json::json; use serde_json::json;
use std::env; use std::env;
use log::{info,warn,error,trace,debug}; use log::{info,warn,error,trace,debug};
use zmq::{Context, Socket}; use zmq::{Context, Socket, DEALER, DONTWAIT};
use std::str; use std::str;
use std::{thread, time::Duration}; use std::{thread, time::Duration};
use std::collections::HashMap; use std::collections::HashMap;
//use byteorder::{LittleEndian, ReadBytesExt}; use byteorder::{LittleEndian, ReadBytesExt};
//use std::io::Cursor; use std::io::Cursor;
use hex; use hex;
use std::error::Error as StdError; use std::error::Error as StdError;
@@ -24,14 +24,19 @@ use reqwest::Client as rClient;
use openssl::hash::MessageDigest; use openssl::hash::MessageDigest;
use openssl::pkey::{PKey}; use openssl::pkey::{PKey};
use openssl::sign::Signer; use openssl::sign::Signer;
use openssl::sign::Verifier;
use base64::{engine::general_purpose, Engine as _}; use base64::{engine::general_purpose, Engine as _};
use std::fs; use std::fs;
use std::time::Instant;
const LOCKTIME_THRESHOLD:i64 = 5000000; const LOCKTIME_THRESHOLD:i64 = 5000000;
const VERSION:&str = "0.0.1"; const VERSION:&str = "0.0.2";
#[derive(Debug, Clone,Serialize, Deserialize)] #[derive(Debug, Clone,Serialize, Deserialize)]
struct MyConfig { struct MyConfig {
zmq_listener: String, zmq_listener: String,
@@ -311,8 +316,10 @@ async fn send_stats_report(cfg: &MyConfig, bcinfo: GetBlockchainInfoResult) -> R
let client = rClient::new(); let client = rClient::new();
let url = format!("{}/ping",welist_url); let url = format!("{}/ping",welist_url);
debug!("welist url: {}",url);
let chain=bcinfo.chain.to_string().to_lowercase(); let chain=bcinfo.chain.to_string().to_lowercase();
let message = format!("{0}{1}{2}{3}{4}",cfg.url,chain,bcinfo.blocks,bcinfo.median_time,bcinfo.best_block_hash); let message = format!("{0}{1}{2}{3}{4}",cfg.url,chain,bcinfo.blocks,bcinfo.median_time,bcinfo.best_block_hash);
trace!("message to be sent: {}",message);
let sign = sign_message(cfg.ssl_key_path.as_str(),&message.as_str()); let sign = sign_message(cfg.ssl_key_path.as_str(),&message.as_str());
let response = client.post(url) let response = client.post(url)
.header("User-Agent", format!("bal-pusher/{}",VERSION)) .header("User-Agent", format!("bal-pusher/{}",VERSION))
@@ -325,9 +332,13 @@ async fn send_stats_report(cfg: &MyConfig, bcinfo: GetBlockchainInfoResult) -> R
"last_block_hash": bcinfo.best_block_hash, "last_block_hash": bcinfo.best_block_hash,
"signature": sign, "signature": sign,
})) }))
.send().await?; .send().await?;
if !response.status().is_success() {
warn!("Non-success response: {} {}", response.status(), response.status().canonical_reason().unwrap_or(""));
}
let body = &(response.text().await?); let body = &(response.text().await?);
println!("Body: {}", body); info!("Report to welist({})\tSent: {}", welist_url,body);
}else { }else {
debug!("Not sending stats"); debug!("Not sending stats");
} }
@@ -339,16 +350,14 @@ fn sign_message(private_key_path: &str, message: &str) -> String {
let key_data = fs::read(private_key_path).unwrap(); let key_data = fs::read(private_key_path).unwrap();
let private_key = PKey::private_key_from_pem(&key_data).unwrap(); let private_key = PKey::private_key_from_pem(&key_data).unwrap();
let mut signer = Signer::new_without_digest(&private_key).unwrap();
let mut signer = Signer::new(MessageDigest::sha256(), &private_key).unwrap(); let signature = signer.sign_oneshot_to_vec(message.as_bytes()).unwrap();
signer.update(message.as_bytes()).unwrap();
let firma = signer.sign_to_vec().unwrap(); let signature_b64 = general_purpose::STANDARD.encode(&signature);
let firma_b64 = general_purpose::STANDARD.encode(&firma); signature_b64
firma_b64
} }
fn parse_env(cfg: &mut MyConfig){ fn parse_env(cfg: &mut MyConfig){
@@ -449,6 +458,74 @@ fn get_default_config()-> MyConfig {
info!("Default configuration file path is: {:#?}", file); info!("Default configuration file path is: {:#?}", file);
confy::load("bal-pusher",None).expect("cant_load") confy::load("bal-pusher",None).expect("cant_load")
} }
fn check_zmq_connection(endpoint: &str) -> bool {
trace!("check zmq connection");
let context = Context::new();
let socket = match context.socket(DEALER) {
Ok(sock) => sock,
Err(_) => return false,
};
if socket.connect(endpoint).is_err() {
return false;
}
// Try to send an empty message non-blocking
socket.send("", DONTWAIT).is_ok()
}
// Add this struct to monitor connection health
struct ConnectionMonitor {
last_message_time: Instant,
timeout: Duration,
consecutive_timeouts: u32,
max_consecutive_timeouts: u32,
}
impl ConnectionMonitor {
fn new(timeout_secs: u64, max_timeouts: u32) -> Self {
Self {
last_message_time: Instant::now(),
timeout: Duration::from_secs(timeout_secs),
consecutive_timeouts: 0,
max_consecutive_timeouts: max_timeouts,
}
}
fn update(&mut self) {
self.last_message_time = Instant::now();
self.consecutive_timeouts = 0;
}
fn check_connection(&mut self) -> ConnectionStatus {
let elapsed = self.last_message_time.elapsed();
if elapsed > self.timeout {
self.consecutive_timeouts += 1;
if self.consecutive_timeouts >= self.max_consecutive_timeouts {
ConnectionStatus::Lost(elapsed)
} else {
ConnectionStatus::Warning(elapsed)
}
} else {
ConnectionStatus::Healthy
}
}
fn reset(&mut self) {
self.consecutive_timeouts = 0;
self.last_message_time = Instant::now();
}
}
enum ConnectionStatus {
Healthy,
Warning(Duration),
Lost(Duration),
}
#[tokio::main] #[tokio::main]
async fn main()-> std::io::Result<()>{ async fn main()-> std::io::Result<()>{
env_logger::init(); env_logger::init();
@@ -489,7 +566,6 @@ async fn main()-> std::io::Result<()>{
info!("Network: {}",arg_network); info!("Network: {}",arg_network);
let network_params = get_network_params(&cfg,network); let network_params = get_network_params(&cfg,network);
let context = Context::new(); let context = Context::new();
let socket: Socket = context.socket(zmq::SUB).unwrap(); let socket: Socket = context.socket(zmq::SUB).unwrap();
@@ -502,28 +578,28 @@ async fn main()-> std::io::Result<()>{
let _ = main_result(&cfg,network_params).await; let _ = main_result(&cfg,network_params).await;
info!("waiting new blocks.."); info!("waiting new blocks..");
let mut last_seq:Vec<u8>=[0;4].to_vec(); let mut last_seq:Vec<u8>=[0;4].to_vec();
let mut counter=0;
let max=100;
loop { loop {
let message = socket.recv_multipart(0).unwrap(); let message = socket.recv_multipart(0).unwrap();
let topic = message[0].clone(); let topic = message[0].clone();
let body = message[1].clone(); let body = message[1].clone();
let seq = message[2].clone(); let seq = message[2].clone();
if last_seq >= seq {
continue
}
last_seq = seq; last_seq = seq;
//let mut sequence_str = "Unknown".to_string();
/*if seq.len()==4{
let mut rdr = Cursor::new(seq);
let sequence = rdr.read_u32::<LittleEndian>().expect("Failed to read integer");
sequence_str = sequence.to_string();
}*/
debug!("ZMQ:GET TOPIC: {}", String::from_utf8(topic.clone()).expect("invalid topic")); debug!("ZMQ:GET TOPIC: {}", String::from_utf8(topic.clone()).expect("invalid topic"));
trace!("ZMQ:GET BODY: {}", hex::encode(&body)); trace!("ZMQ:GET BODY: {}", hex::encode(&body));
if topic == b"hashblock" { if topic == b"hashblock" {
info!("NEW BLOCK: {}", hex::encode(&body)); info!("NEW BLOCK: {}", hex::encode(&body));
//let cfg = cfg.clone();
let _ = main_result(&cfg,network_params).await; let _ = main_result(&cfg,network_params).await;
} }
thread::sleep(Duration::from_millis(100)); // Sleep for 100ms thread::sleep(Duration::from_millis(100)); // Sleep for 100ms
} }
} }
fn seq_to_str(seq:&Vec<u8>) -> String{
if seq.len()==4{
let mut rdr = Cursor::new(seq);
let sequence = rdr.read_u32::<LittleEndian>().expect("Failed to read integer");
return sequence.to_string();
}
"Unknown".to_string()
}

View File

@@ -11,6 +11,7 @@ use std::net::IpAddr;
use std::env; use std::env;
//use std::time::{SystemTime,UNIX_EPOCH}; //use std::time::{SystemTime,UNIX_EPOCH};
use std::fs;
use std::sync::{ Arc, Mutex, MutexGuard }; use std::sync::{ Arc, Mutex, MutexGuard };
//use std::net::SocketAddr; //use std::net::SocketAddr;
use std::collections::HashMap; use std::collections::HashMap;
@@ -25,15 +26,10 @@ use log::{ info, error, trace, debug};
use serde_json; use serde_json;
use chrono::Utc; use chrono::Utc;
#[path = "../db.rs"] use bal_server::db::{ create_database, get_next_address_index, insert_xpub, save_new_address, get_last_used_address_by_ip, execute_insert };
mod db; use bal_server::xpub::new_address_from_xpub;
use crate::db::{ create_database, get_next_address_index, insert_xpub, save_new_address, get_last_used_address_by_ip, execute_insert };
const VERSION:&str=env!("CARGO_PKG_VERSION");
#[path = "../xpub.rs"]
mod xpub;
use crate::xpub::new_address_from_xpub;
const VERSION:&str="0.2.1";
const NETWORKS : [&str; 4]= ["bitcoin","testnet","signet","regtest"]; const NETWORKS : [&str; 4]= ["bitcoin","testnet","signet","regtest"];
#[derive(Debug, Clone,Serialize, Deserialize)] #[derive(Debug, Clone,Serialize, Deserialize)]
struct NetConfig { struct NetConfig {
@@ -48,26 +44,27 @@ struct NetConfig {
impl NetConfig { impl NetConfig {
fn default_network(name:String, network: Network) -> Self { fn default_network(name:String, network: Network) -> Self {
NetConfig { NetConfig {
address: "".to_string(), address: "".to_string(),
fixed_fee: 50000, fixed_fee: 50000,
xpub: false, xpub: false,
name, name,
network, network,
enabled: false, enabled: false,
} }
} }
} }
#[derive(Debug, Serialize, Deserialize,Clone)] #[derive(Debug, Serialize, Deserialize,Clone)]
struct MyConfig { struct MyConfig {
regtest: NetConfig, regtest: NetConfig,
signet: NetConfig, signet: NetConfig,
testnet: NetConfig, testnet: NetConfig,
mainnet: NetConfig, mainnet: NetConfig,
info: String, info: String,
bind_address: String, bind_address: String,
bind_port: u16, // Changed to u16 for port numbers bind_port: u16, // Changed to u16 for port numbers
db_file: String, db_file: String,
pub_key_path: String,
} }
#[derive(Debug,Serialize, Deserialize)] #[derive(Debug,Serialize, Deserialize)]
@@ -83,14 +80,15 @@ pub struct Info {
impl Default for MyConfig { impl Default for MyConfig {
fn default() -> Self { fn default() -> Self {
MyConfig { MyConfig {
regtest: NetConfig::default_network("regtest".to_string(), Network::Regtest), regtest: NetConfig::default_network("regtest".to_string(), Network::Regtest),
signet: NetConfig::default_network("signet".to_string(), Network::Signet), signet: NetConfig::default_network("signet".to_string(), Network::Signet),
testnet: NetConfig::default_network("testnet".to_string(), Network::Testnet), testnet: NetConfig::default_network("testnet".to_string(), Network::Testnet),
mainnet: NetConfig::default_network("bitcoin".to_string(), Network::Bitcoin), mainnet: NetConfig::default_network("bitcoin".to_string(), Network::Bitcoin),
bind_address: "127.0.0.1".to_string(), bind_address: "127.0.0.1".to_string(),
bind_port: 9137, bind_port: 9137,
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(),
} }
} }
} }
@@ -109,6 +107,18 @@ async fn echo_version(
) -> Result<Response<BoxBody<Bytes, hyper::Error>>, hyper::Error> { ) -> Result<Response<BoxBody<Bytes, hyper::Error>>, hyper::Error> {
Ok(Response::new(full(VERSION))) Ok(Response::new(full(VERSION)))
} }
async fn echo_home(cfg: &MyConfig
) -> Result<Response<BoxBody<Bytes, hyper::Error>>, hyper::Error> {
debug!("echo_home: {}", cfg.info );
Ok(Response::new(full(cfg.info.clone())))
}
async fn echo_pub_key(
cfg: &MyConfig,
) -> Result<Response<BoxBody<Bytes, hyper::Error>>, hyper::Error> {
let pub_key = fs::read_to_string(&cfg.pub_key_path)
.expect(format!("Failed to read public key file {}",cfg.pub_key_path).as_str());
Ok(Response::new(full(pub_key)))
}
async fn echo_info( async fn echo_info(
param: &str, param: &str,
cfg: &MyConfig, cfg: &MyConfig,
@@ -441,6 +451,12 @@ async fn echo(
if uri=="/version"{ if uri=="/version"{
ret= echo_version().await; ret= echo_version().await;
} }
if uri=="/.pub_key.pem" {
ret = echo_pub_key(cfg).await;
}
if uri=="/"{
ret = echo_home(cfg).await;
}
ret ret
} }
@@ -480,6 +496,11 @@ fn parse_env(cfg: &Arc<Mutex<MyConfig>>){
} }
} }
if let Ok(value) = env::var("BAL_SERVER_PUB_KEY_PATH") {
debug!("BAL_SERVER_PUB_KEY_PATH: {}",value);
cfg_lock.pub_key_path = value;
}
if let Ok(value) = env::var("BAL_SERVER_INFO"){ if let Ok(value) = env::var("BAL_SERVER_INFO"){
debug!("BAL_SERVER_INFO: {}",value); debug!("BAL_SERVER_INFO: {}",value);