depolymerization

wire gateway for Bitcoin/Ethereum
Log | Files | Refs | Submodules | README | LICENSE

commit e959a7a45578cd8815461d9a250bd3c0a782cad2
parent 94b9f89b75ff1925948a896476c91be2dbee310a
Author: Antoine A <>
Date:   Fri, 12 Nov 2021 12:39:15 +0100

Optimize decode_segwit_msg

Diffstat:
MCargo.lock | 49-------------------------------------------------
MCargo.toml | 3---
Msrc/lib.rs | 72++++++++++++++++++++++++++++--------------------------------------------
3 files changed, 28 insertions(+), 96 deletions(-)

diff --git a/Cargo.lock b/Cargo.lock @@ -76,15 +76,6 @@ dependencies = [ ] [[package]] -name = "bitcoin-bech32" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "754eb4c7f35c031f33c95cc257b4c4192a5c9d3de637d3ee78ab052a3f35da57" -dependencies = [ - "bech32", -] - -[[package]] name = "bitcoin_hashes" version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -124,12 +115,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693" [[package]] -name = "bs58" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "771fe0050b883fcc3ea2359b1a96bcfbc090b7116eae7c3c512c7a083fdf23d3" - -[[package]] name = "bstr" version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -304,26 +289,14 @@ version = "0.1.0" dependencies = [ "argh", "bech32", - "bitcoin-bech32", "bitcoincore-rpc", - "bs58", "criterion", - "digest", "fastrand", "rand", "rustyline", ] [[package]] -name = "digest" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3dd60d1080a57a05ab032377049e0591415d2b31afd7028356dbf3cc6dcb066" -dependencies = [ - "generic-array", -] - -[[package]] name = "dirs-next" version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -387,16 +360,6 @@ dependencies = [ ] [[package]] -name = "generic-array" -version = "0.14.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "501466ecc8a30d1d3b7fc9229b122b2ce8ed6e9d9223f1138d4babb253e51817" -dependencies = [ - "typenum", - "version_check", -] - -[[package]] name = "getrandom" version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -889,12 +852,6 @@ dependencies = [ ] [[package]] -name = "typenum" -version = "1.14.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b63708a265f51345575b27fe43f9500ad611579e764c79edbc2037b1121959ec" - -[[package]] name = "unicode-segmentation" version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -919,12 +876,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "936e4b492acfd135421d8dca4b1aa80a7bfc26e702ef3af710e0752684df5372" [[package]] -name = "version_check" -version = "0.9.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5fecdca9a5291cc2b8dcf7dc02453fee791a280f3743cb0905f8822ae463b3fe" - -[[package]] name = "walkdir" version = "2.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" diff --git a/Cargo.toml b/Cargo.toml @@ -7,12 +7,9 @@ edition = "2021" [dependencies] bitcoincore-rpc = "0.14.0" -bs58 = "0.4.0" fastrand = "1.5.0" -digest = "0.9.0" argh = "0.1.6" rustyline = "9.0.0" -bitcoin-bech32 = "0.12.1" bech32 = "0.8.1" rand = { version = "0.8.4", features = ["getrandom"] } diff --git a/src/lib.rs b/src/lib.rs @@ -1,7 +1,4 @@ -use std::collections::BTreeMap; - -use bech32::{ToBase32, Variant}; -use bitcoin_bech32::{u5, WitnessProgram}; +use bech32::{u5, FromBase32, ToBase32, Variant}; use bitcoincore_rpc::bitcoin::Amount; use rand::{rngs::OsRng, RngCore}; @@ -70,6 +67,7 @@ pub fn encode_segwit_msg(network: Network, msg: &[u8; 32]) -> [String; 2] { #[derive(Debug, Clone)] pub enum DecodeError { + TooManyAddress, MissingSeqWitAddress, MagicIdCollision, } @@ -79,58 +77,44 @@ pub fn decode_segwit_msg(segwit_addrs: &[impl AsRef<str>]) -> Result<[u8; 32], D return Err(DecodeError::MissingSeqWitAddress); } - let decoded: Vec<[u8; 20]> = segwit_addrs + if segwit_addrs.len() > 4 { + return Err(DecodeError::TooManyAddress); + } + + // Extract parts from every addresses + let decoded: Vec<(bool, [u8; 4], [u8; 16])> = segwit_addrs .into_iter() .filter_map(|addr| { - WitnessProgram::from_address(addr.as_ref()) - .ok() - .and_then(|wp| { - let pg = wp.program(); - if pg.len() == 20 { - let mut buf = [0; 20]; - buf.copy_from_slice(pg); - Some(buf) - } else { - None - } - }) + bech32::decode(addr.as_ref()).ok().and_then(|(_, wp, _)| { + // Skip version + let pg: Vec<u8> = Vec::from_base32(&wp[1..]).unwrap(); + if pg.len() == 20 { + let mut magic_id: [u8; 4] = pg[..4].try_into().unwrap(); + let key_half: [u8; 16] = pg[4..].try_into().unwrap(); + let is_first = !pg[0] & 0b1000_0000 == 0; + // Clear first bit + magic_id[0] &= 0b0111_1111; + Some((is_first, magic_id, key_half)) + } else { + None + } + }) }) .collect(); if decoded.len() < 2 { return Err(DecodeError::MissingSeqWitAddress); } - - let mut parts: Vec<(bool, [u8; 4], &[u8; 16])> = decoded + // Keep only the addresses with duplicated magic id + let matches: Vec<&(bool, [u8; 4], [u8; 16])> = decoded .iter() - .map(|c| { - let mut magic_id: [u8; 4] = c[..4].try_into().unwrap(); - let key_half: &[u8; 16] = c[4..].try_into().unwrap(); - let is_first = !c[0] & 0b1000_0000 == 0; - // Clear first bit - magic_id[0] &= 0b0111_1111; - (is_first, magic_id, key_half) - }) + .filter(|(_, magic, _)| decoded.iter().filter(|(_, other, _)| other == magic).count() > 1) .collect(); - let mut map = BTreeMap::new(); - - for (_, magic, _) in &parts { - match map.get_mut(magic) { - Some(prev) => *prev = true, - None => { - map.insert(*magic, false); - } - } - } - map.retain(|_, many| *many); - assert_eq!(map.len(), 1, "Two possible magic id"); - let magic_id = map.into_keys().next().unwrap(); - parts.retain(|(_, magic, _)| *magic == magic_id); - assert_eq!(parts.len(), 2, "Magic ID collision"); + assert_eq!(matches.len(), 2, "Magic ID collision"); let mut key = [0; 32]; - for (is_first, _, half) in parts { - key[is_first as usize * 16..][..16].copy_from_slice(half); + for (is_first, _, half) in matches { + key[*is_first as usize * 16..][..16].copy_from_slice(half); } Ok(key) }