Skip to content

Commit

Permalink
feat(rooch-da): enhance BitcoinInscriptionID parsing and serialization (
Browse files Browse the repository at this point in the history
#2488)

## Summary

Improve BitcoinInscriptionID parsing with better string validation and custom serialization: fix parse error :

```
thread 'verify-inscription' panicked at crates/rooch/src/commands/statedb/commands/inscription.rs:52:36:
called `Result::unwrap()` on an `Err` value: Error("invalid type: string \"6fb976ab49dcec017f1e201e84395983204ae1a7c2abf7ced0a85d692e442799i0\", expected struct BitcoinInscriptionID", line: 1, column: 117)
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
thread 'main' panicked at crates/rooch/src/commands/statedb/commands/genesis_verify.rs:255:42:
called `Result::unwrap()` on an `Err` value: Any { .. }
```
  • Loading branch information
popcnt1 authored Aug 22, 2024
1 parent 17c827d commit fa74e1c
Show file tree
Hide file tree
Showing 3 changed files with 65 additions and 18 deletions.
43 changes: 36 additions & 7 deletions crates/rooch-types/src/bitcoin/ord.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ use moveos_types::{
},
};
use serde::de::DeserializeOwned;
use serde::{Deserialize, Serialize};
use serde::{Deserialize, Deserializer, Serialize, Serializer};
use std::fmt::{Debug, Display};
use std::str::FromStr;

Expand Down Expand Up @@ -390,7 +390,7 @@ impl<'a> ModuleBinding<'a> for OrdModule<'a> {
}
}

#[derive(Debug, PartialEq, Clone, Copy, Serialize, Deserialize, Hash, Eq)]
#[derive(Debug, PartialEq, Clone, Copy, Hash, Eq)]
pub struct BitcoinInscriptionID {
pub txid: bitcoin::Txid,
pub index: u32,
Expand Down Expand Up @@ -430,16 +430,45 @@ impl FromStr for BitcoinInscriptionID {
type Err = anyhow::Error;

fn from_str(s: &str) -> Result<Self> {
let parts: Vec<&str> = s.split('i').collect();
if parts.len() != 2 {
bail!("Invalid BitcoinInscriptionID string: {}", s);
const TXID_LEN: usize = 64;
const MIN_LEN: usize = TXID_LEN + 2;
if s.len() < MIN_LEN {
bail!(
"Invalid BitcoinInscriptionID length: {}",
format!("{}, len: {} < {}", s, s.len(), MIN_LEN)
);
}
let txid = bitcoin::Txid::from_str(parts[0])?;
let index = parts[1].parse()?;

let txid = bitcoin::Txid::from_str(&s[..TXID_LEN])?;
let separator = s.chars().nth(TXID_LEN).unwrap();

if separator != 'i' {
bail!("Invalid BitcoinInscriptionID separator: {}", separator);
}
let index = &s[TXID_LEN + 1..];
let index = index.parse()?;
Ok(BitcoinInscriptionID { txid, index })
}
}

impl<'de> Deserialize<'de> for BitcoinInscriptionID {
fn deserialize<D>(deserializer: D) -> std::result::Result<Self, D::Error>
where
D: Deserializer<'de>,
{
Self::from_str(&String::deserialize(deserializer)?).map_err(serde::de::Error::custom)
}
}

impl Serialize for BitcoinInscriptionID {
fn serialize<S>(&self, serializer: S) -> std::result::Result<S::Ok, S::Error>
where
S: Serializer,
{
serializer.collect_str(self)
}
}

#[derive(Debug, PartialEq, Clone)]
pub enum Curse {
DuplicateField,
Expand Down
38 changes: 28 additions & 10 deletions crates/rooch/src/commands/statedb/commands/genesis_verify.rs
Original file line number Diff line number Diff line change
Expand Up @@ -358,15 +358,18 @@ fn verify_utxo(
vout: utxo_raw.vout,
};

let is_case = cases.contains(&raw_output);

let random_picked = if sample_rate == 0 {
let need_verify = if !random_mode {
true
} else {
rand::random::<u32>() % sample_rate == 0
let is_case = cases.contains(&raw_output);
if sample_rate == 0 {
is_case
} else {
rand::random::<u32>() % sample_rate == 0 || is_case
}
};

if (random_mode && random_picked) && !is_case {
if !need_verify {
continue;
}

Expand Down Expand Up @@ -542,14 +545,18 @@ fn verify_inscription(
);
}

let is_case = cases.contains(source.sequence_number);
let random_picked = if sample_rate == 0 {
let need_verify = if !random_mode {
true
} else {
rand::random::<u32>() % sample_rate == 0
let is_case = cases.contains(source.sequence_number);
if sample_rate == 0 {
is_case
} else {
rand::random::<u32>() % sample_rate == 0 || is_case
}
};

if (random_mode && random_picked) && !is_case {
if !need_verify {
continue;
}
// check inscription
Expand Down Expand Up @@ -690,7 +697,18 @@ fn write_mismatched_state_output<T: MoveStructState + std::fmt::Debug, R: std::f
return (false, false);
}

let result = if not_found { "not_found" } else { "mismatched" };
let result = if not_found {
"not_found".to_string()
} else {
let mut mismatched = "mismatched".to_string();
if exp_meta_str != act_meta_str {
mismatched.push_str("_meta");
}
if exp_val_str != act_val_str {
mismatched.push_str("_val");
}
mismatched
};
writeln!(
output_writer,
"{} {}: exp-meta: {:?}, act-meta: {:?}, exp-val: {:?}, act-val: {:?}, src_data: {:?}",
Expand Down
2 changes: 1 addition & 1 deletion frameworks/bitcoin-move/src/natives/ord/inscription_id.rs
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ impl Display for ParseError {
match self {
Self::Character(c) => write!(f, "invalid character: '{c}'"),
Self::Length(len) => write!(f, "invalid length: {len}"),
Self::Separator(c) => write!(f, "invalid seprator: `{c}`"),
Self::Separator(c) => write!(f, "invalid separator: `{c}`"),
Self::Txid(err) => write!(f, "invalid txid: {err}"),
Self::Index(err) => write!(f, "invalid index: {err}"),
}
Expand Down

0 comments on commit fa74e1c

Please sign in to comment.