fix: correct locktime threshold, PG stats SUM on TEXT, PG locktime width, and translate Italian error strings
- Bug 1: LOCKTIME_THRESHOLD was 5_000_000 instead of BIP-65 value 500_000_000 - Bug 2: PostgreSQL SUM(our_fees) failed on TEXT column; cast to BIGINT - Bug 3: PostgreSQL locktime INTEGER (i32) widened to BIGINT (i64) with idempotent ALTER - Translate 4 Italian error strings in xpub.rs to English
This commit is contained in:
@@ -24,7 +24,8 @@ use reqwest::Client as rClient;
|
|||||||
use std::net::SocketAddr;
|
use std::net::SocketAddr;
|
||||||
use url::Url;
|
use url::Url;
|
||||||
|
|
||||||
const LOCKTIME_THRESHOLD: i64 = 5000000;
|
// BIP-65: locktime values below this are block heights, at or above are UNIX timestamps.
|
||||||
|
const LOCKTIME_THRESHOLD: i64 = 500_000_000;
|
||||||
const VERSION: &str = env!("CARGO_PKG_VERSION");
|
const VERSION: &str = env!("CARGO_PKG_VERSION");
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
struct MyConfig {
|
struct MyConfig {
|
||||||
|
|||||||
@@ -624,9 +624,9 @@ pub async fn get_pending_txs(
|
|||||||
"SELECT txid, tx, locktime, network, status FROM tbl_tx WHERE network = $1 AND status = 0 AND (locktime < $2 OR (locktime > $3 AND locktime < $4))",
|
"SELECT txid, tx, locktime, network, status FROM tbl_tx WHERE network = $1 AND status = 0 AND (locktime < $2 OR (locktime > $3 AND locktime < $4))",
|
||||||
)
|
)
|
||||||
.bind(network)
|
.bind(network)
|
||||||
.bind(bestblock_height as i32)
|
.bind(bestblock_height)
|
||||||
.bind(locktime_threshold as i32)
|
.bind(locktime_threshold)
|
||||||
.bind(bestblock_time as i32)
|
.bind(bestblock_time)
|
||||||
.fetch_all(p)
|
.fetch_all(p)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
@@ -634,7 +634,7 @@ pub async fn get_pending_txs(
|
|||||||
results.push(TxRow {
|
results.push(TxRow {
|
||||||
txid: row.try_get("txid")?,
|
txid: row.try_get("txid")?,
|
||||||
tx: row.try_get("tx")?,
|
tx: row.try_get("tx")?,
|
||||||
locktime: row.try_get::<i32, _>("locktime").unwrap_or(0) as i64,
|
locktime: row.try_get::<i64, _>("locktime").unwrap_or(0),
|
||||||
network: row.try_get("network")?,
|
network: row.try_get("network")?,
|
||||||
status: row.try_get::<i32, _>("status").unwrap_or(0) as i64,
|
status: row.try_get::<i32, _>("status").unwrap_or(0) as i64,
|
||||||
});
|
});
|
||||||
@@ -839,9 +839,9 @@ pub async fn calculate_and_upsert_stats(
|
|||||||
(SELECT COUNT(*) FROM tbl_tx WHERE status = 0 AND network = $1),
|
(SELECT COUNT(*) FROM tbl_tx WHERE status = 0 AND network = $1),
|
||||||
(SELECT COUNT(*) FROM tbl_tx WHERE status = 1 AND network = $1),
|
(SELECT COUNT(*) FROM tbl_tx WHERE status = 1 AND network = $1),
|
||||||
(SELECT COUNT(*) FROM tbl_tx WHERE status = 2 AND network = $1),
|
(SELECT COUNT(*) FROM tbl_tx WHERE status = 2 AND network = $1),
|
||||||
(SELECT COALESCE(SUM(our_fees),0) FROM tbl_tx WHERE status = 0 AND network = $1),
|
(SELECT COALESCE(SUM(CAST(our_fees AS BIGINT)),0) FROM tbl_tx WHERE status = 0 AND network = $1),
|
||||||
(SELECT COALESCE(SUM(our_fees),0) FROM tbl_tx WHERE status = 1 AND network = $1),
|
(SELECT COALESCE(SUM(CAST(our_fees AS BIGINT)),0) FROM tbl_tx WHERE status = 1 AND network = $1),
|
||||||
(SELECT COALESCE(SUM(our_fees),0) FROM tbl_tx WHERE status = 2 AND network = $1),
|
(SELECT COALESCE(SUM(CAST(our_fees AS BIGINT)),0) FROM tbl_tx WHERE status = 2 AND network = $1),
|
||||||
(SELECT COUNT(DISTINCT tbl_inp.in_txid)
|
(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
|
||||||
|
|||||||
@@ -128,7 +128,7 @@ pub async fn create_pg_schema(pool: &PgPool) -> Result<(), sqlx::Error> {
|
|||||||
wtxid TEXT,
|
wtxid TEXT,
|
||||||
ntxid TEXT,
|
ntxid TEXT,
|
||||||
tx TEXT,
|
tx TEXT,
|
||||||
locktime INTEGER,
|
locktime BIGINT,
|
||||||
network TEXT,
|
network TEXT,
|
||||||
network_fees TEXT,
|
network_fees TEXT,
|
||||||
reqid TEXT,
|
reqid TEXT,
|
||||||
@@ -141,6 +141,13 @@ pub async fn create_pg_schema(pool: &PgPool) -> Result<(), sqlx::Error> {
|
|||||||
.execute(pool)
|
.execute(pool)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
|
// Migrate pre-existing deployments where locktime was created as INTEGER.
|
||||||
|
// nLockTime is a u32 (up to 4_294_967_295); INTEGER (i32) cannot hold
|
||||||
|
// timestamp-based locktimes after 2038-01-19.
|
||||||
|
let _ = sqlx::query("ALTER TABLE tbl_tx ALTER COLUMN locktime TYPE BIGINT")
|
||||||
|
.execute(pool)
|
||||||
|
.await;
|
||||||
|
|
||||||
sqlx::query(
|
sqlx::query(
|
||||||
"CREATE TABLE IF NOT EXISTS tbl_inp (
|
"CREATE TABLE IF NOT EXISTS tbl_inp (
|
||||||
id SERIAL PRIMARY KEY,
|
id SERIAL PRIMARY KEY,
|
||||||
|
|||||||
@@ -148,12 +148,12 @@ pub fn calculate_fingerprint(tpub: &str) -> Result<String, String> {
|
|||||||
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())?;
|
||||||
if data.len() < 4 {
|
if data.len() < 4 {
|
||||||
return Err("Data troppo corta".to_string());
|
return Err("Data too short".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("Invalid checksum".to_string());
|
||||||
}
|
}
|
||||||
Ok(payload.to_vec())
|
Ok(payload.to_vec())
|
||||||
}
|
}
|
||||||
@@ -168,7 +168,7 @@ fn convert_to(zpub: &str, prefix: BS58Prefix) -> Result<String, String> {
|
|||||||
let mut data = base58check_decode(zpub)?;
|
let mut data = base58check_decode(zpub)?;
|
||||||
|
|
||||||
if data.len() < 4 {
|
if data.len() < 4 {
|
||||||
return Err("Non è una zpub valida.".to_string());
|
return Err("Not a valid zpub".to_string());
|
||||||
}
|
}
|
||||||
data.splice(
|
data.splice(
|
||||||
0..4,
|
0..4,
|
||||||
@@ -207,7 +207,7 @@ pub fn new_address_from_xpub(
|
|||||||
fn main() -> Result<(), Box<dyn std::error::Error>>{
|
fn main() -> Result<(), Box<dyn std::error::Error>>{
|
||||||
match convert_to(zpub,BS58Prefix::Tpub) {
|
match convert_to(zpub,BS58Prefix::Tpub) {
|
||||||
Ok(tpub) => println!("XPUB: {}", tpub),
|
Ok(tpub) => println!("XPUB: {}", tpub),
|
||||||
Err(e) => eprintln!("Errore: {}", e),
|
Err(e) => eprintln!("Error: {}", e),
|
||||||
}
|
}
|
||||||
let fingerprint = base58check_encode(&calculate_fingerprint(zpub));
|
let fingerprint = base58check_encode(&calculate_fingerprint(zpub));
|
||||||
println!("ZPUB: {}, FINGERPRINT: {}",zpub,fingerprint);
|
println!("ZPUB: {}, FINGERPRINT: {}",zpub,fingerprint);
|
||||||
|
|||||||
Reference in New Issue
Block a user