From 750cb893c4a819b582593dfa5ec7ec20b0d9e4f7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zoe=20Faltib=C3=A0?= Date: Fri, 3 May 2024 16:20:56 +0200 Subject: [PATCH 1/4] electrum: add safety margins for tx height check --- src/resolvers/electrum_blocking.rs | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/resolvers/electrum_blocking.rs b/src/resolvers/electrum_blocking.rs index 6cbd187..b7c0566 100644 --- a/src/resolvers/electrum_blocking.rs +++ b/src/resolvers/electrum_blocking.rs @@ -72,9 +72,16 @@ impl RgbResolver for Client { let tip_height = u32::try_from(header.height).map_err(|_| s!("impossible height value"))?; let height: usize = (tip_height + 1 - confirmations) as usize; - let get_merkle_res = (0..=forward) + // first check from expected min to max height then max + 1 and finally min - 1 + let get_merkle_res = if let Some(res) = (0..=forward + 1) .find_map(|offset| self.transaction_get_merkle(&txid, height + offset).ok()) - .ok_or_else(|| s!("transaction can't be located in the blockchain"))?; + { + res + } else { + self.transaction_get_merkle(&txid, height - 1) + .or_else(|_| Err(s!("transaction can't be located in the blockchain")))? + }; + let tx_height = u32::try_from(get_merkle_res.block_height) .map_err(|_| s!("impossible height value"))?; From f69200e36f1fa7ea2b9ebc34f6b8f061b1b5be1f Mon Sep 17 00:00:00 2001 From: Dr Maxim Orlovsky Date: Fri, 3 May 2024 17:24:55 +0200 Subject: [PATCH 2/4] resolver: make electrum checks rusty --- src/resolvers/electrum_blocking.rs | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/src/resolvers/electrum_blocking.rs b/src/resolvers/electrum_blocking.rs index b7c0566..044df1a 100644 --- a/src/resolvers/electrum_blocking.rs +++ b/src/resolvers/electrum_blocking.rs @@ -71,16 +71,12 @@ impl RgbResolver for Client { ); let tip_height = u32::try_from(header.height).map_err(|_| s!("impossible height value"))?; - let height: usize = (tip_height + 1 - confirmations) as usize; + let height: usize = (tip_height - confirmations) as usize; // first check from expected min to max height then max + 1 and finally min - 1 - let get_merkle_res = if let Some(res) = (0..=forward + 1) + let get_merkle_res = (1..=forward + 1) + .chain([0]) .find_map(|offset| self.transaction_get_merkle(&txid, height + offset).ok()) - { - res - } else { - self.transaction_get_merkle(&txid, height - 1) - .or_else(|_| Err(s!("transaction can't be located in the blockchain")))? - }; + .ok_or_else(|| s!("transaction can't be located in the blockchain"))?; let tx_height = u32::try_from(get_merkle_res.block_height) .map_err(|_| s!("impossible height value"))?; From ce75db2c62673d70f79bb739d1196b1d8b75d25d Mon Sep 17 00:00:00 2001 From: Dr Maxim Orlovsky Date: Sat, 4 May 2024 11:44:16 +0200 Subject: [PATCH 3/4] resolver: add safety margins to electrum resolver --- src/resolvers/electrum_blocking.rs | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/src/resolvers/electrum_blocking.rs b/src/resolvers/electrum_blocking.rs index 044df1a..96d23be 100644 --- a/src/resolvers/electrum_blocking.rs +++ b/src/resolvers/electrum_blocking.rs @@ -52,7 +52,7 @@ impl RgbResolver for Client { Param::String(txid.to_string()), Param::Bool(true), ])); - let forward = iter::from_fn(|| self.block_headers_pop().ok().flatten()).count(); + let forward = iter::from_fn(|| self.block_headers_pop().ok().flatten()).count() as isize; let Some(confirmations) = tx_details.get("confirmations") else { return Ok(witness_anchor); @@ -71,11 +71,14 @@ impl RgbResolver for Client { ); let tip_height = u32::try_from(header.height).map_err(|_| s!("impossible height value"))?; - let height: usize = (tip_height - confirmations) as usize; - // first check from expected min to max height then max + 1 and finally min - 1 + let height: isize = (tip_height - confirmations) as isize; + const SAFETY_MARGIN: isize = 1; + // first check from expected min to max height, then max + 1 and finally min - 1 let get_merkle_res = (1..=forward + 1) - .chain([0]) - .find_map(|offset| self.transaction_get_merkle(&txid, height + offset).ok()) + // we need this under assumption that electrum was lying due to "DB desynchronization" + // since this have a very low probability we do that after everything else + .chain((1..=SAFETY_MARGIN).flat_map(|i| [i + forward + 1, 1 - i])) + .find_map(|offset| self.transaction_get_merkle(&txid, (height + offset) as usize).ok()) .ok_or_else(|| s!("transaction can't be located in the blockchain"))?; let tx_height = u32::try_from(get_merkle_res.block_height) From c58e58da9259d1c2feb7aec5d13db13a8228db63 Mon Sep 17 00:00:00 2001 From: Dr Maxim Orlovsky Date: Mon, 6 May 2024 10:12:03 +0200 Subject: [PATCH 4/4] whatever --- src/resolvers/electrum_blocking.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/resolvers/electrum_blocking.rs b/src/resolvers/electrum_blocking.rs index 96d23be..90f2d47 100644 --- a/src/resolvers/electrum_blocking.rs +++ b/src/resolvers/electrum_blocking.rs @@ -73,7 +73,7 @@ impl RgbResolver for Client { let tip_height = u32::try_from(header.height).map_err(|_| s!("impossible height value"))?; let height: isize = (tip_height - confirmations) as isize; const SAFETY_MARGIN: isize = 1; - // first check from expected min to max height, then max + 1 and finally min - 1 + // first check from expected min to max height let get_merkle_res = (1..=forward + 1) // we need this under assumption that electrum was lying due to "DB desynchronization" // since this have a very low probability we do that after everything else