Skip to content

Commit

Permalink
Merge pull request #173 from RGB-WG/baid58
Browse files Browse the repository at this point in the history
Add chunking to Baid58-based identifiers
  • Loading branch information
dr-orlovsky authored Jul 25, 2023
2 parents d567426 + ad4179d commit eec46ed
Show file tree
Hide file tree
Showing 5 changed files with 90 additions and 39 deletions.
24 changes: 15 additions & 9 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,9 @@ strict_types = "~1.6.0"
aluvm = { version = "~0.10.5", features = ["std"] }
commit_verify = { version = "~0.10.5", features = ["rand", "derive"] }
single_use_seals = "~0.10.0"
bp-core = { version = "~0.10.6" }
bp-core = { version = "~0.10.7" }
secp256k1-zkp = { version = "0.8.0", features = ["use-rand", "rand-std", "global-context"] }
baid58 = "~0.4.1"
baid58 = "~0.4.4"
mime = "~0.3.16"
serde_crate = { package = "serde", version = "1", features = ["derive"], optional = true }

Expand Down
22 changes: 13 additions & 9 deletions src/contract/attachment.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
use std::str::FromStr;

use amplify::{Bytes32, RawArray};
use baid58::{Baid58ParseError, FromBaid58, ToBaid58};
use baid58::{Baid58ParseError, Chunking, FromBaid58, ToBaid58, CHUNKING_32};
use bp::secp256k1::rand::{thread_rng, RngCore};
use commit_verify::{CommitVerify, Conceal, StrictEncodedProtocol};
use strict_encoding::StrictEncode;
Expand All @@ -49,18 +49,21 @@ pub struct AttachId(
);

impl ToBaid58<32> for AttachId {
const HRI: &'static str = "rgb-file";
const HRI: &'static str = "stashfs";
const CHUNKING: Option<Chunking> = CHUNKING_32;
fn to_baid58_payload(&self) -> [u8; 32] { self.to_raw_array() }
fn to_baid58_string(&self) -> String { self.to_string() }
}
impl FromBaid58<32> for AttachId {}
impl AttachId {
pub fn to_baid58_string(&self) -> String { format!("{::<#}", self.to_baid58()) }
pub fn to_baid58_string(&self) -> String { format!("{::<#.2}", self.to_baid58()) }
}
impl FromStr for AttachId {
type Err = Baid58ParseError;
fn from_str(s: &str) -> Result<Self, Self::Err> {
Self::from_baid58_str(s.trim_start_matches("rgb-file:"))
}
fn from_str(s: &str) -> Result<Self, Self::Err> { Self::from_baid58_chunked_str(s, ':', '#') }
}
impl AttachId {
pub fn to_mnemonic(&self) -> String { self.to_baid58().mnemonic() }
}

#[derive(Clone, PartialOrd, Ord, PartialEq, Eq, Hash, Debug)]
Expand Down Expand Up @@ -141,10 +144,11 @@ mod test {
#[test]
fn attach_id_display() {
const ID: &str =
"rgb-file:8JEvTXJ6sD5U4n1p7GEERYMPN9ijjs9ZM4ysJ3qhgyqM#flash-plasma-sinatra";
"stashfs:8JEvTX-J6sD5U4n-1p7GEERY-MPN9ijjs-9ZM4ysJ3-qhgyqM#juice-empty-joker";
let id = AttachId::from_raw_array([0x6c; 32]);
assert_eq!(ID, id.to_string());
assert_eq!(ID, id.to_baid58_string());
assert_eq!("juice-empty-joker", id.to_mnemonic());
}

#[test]
Expand All @@ -153,12 +157,12 @@ mod test {
assert_eq!(
Ok(id),
AttachId::from_str(
"rgb-file:8JEvTXJ6sD5U4n1p7GEERYMPN9ijjs9ZM4ysJ3qhgyqM#flash-plasma-sinatra"
"stashfs:8JEvTX-J6sD5U4n-1p7GEERY-MPN9ijjs-9ZM4ysJ3-qhgyqM#juice-empty-joker"
)
);
assert_eq!(
Ok(id),
AttachId::from_str("rgb-file:8JEvTXJ6sD5U4n1p7GEERYMPN9ijjs9ZM4ysJ3qhgyqM")
AttachId::from_str("stashfs:8JEvTX-J6sD5U4n-1p7GEERY-MPN9ijjs-9ZM4ysJ3-qhgyqM")
);
}
}
48 changes: 38 additions & 10 deletions src/contract/operations.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,14 @@

use std::cmp::Ordering;
use std::collections::{btree_map, btree_set};
use std::fmt::{self, Display, Formatter};
use std::iter;
use std::str::FromStr;

use amplify::confinement::{SmallBlob, TinyOrdMap, TinyOrdSet};
use amplify::hex::{FromHex, ToHex};
use amplify::{hex, Bytes32, RawArray, Wrapper};
use baid58::{Baid58ParseError, FromBaid58, ToBaid58};
use baid58::{Baid58ParseError, Chunking, FromBaid58, ToBaid58, CHUNKING_32CHECKSUM};
use bp::Chain;
use commit_verify::{mpc, CommitmentId, Conceal};
use strict_encoding::{StrictDeserialize, StrictEncode, StrictSerialize};
Expand Down Expand Up @@ -155,9 +156,8 @@ impl OpId {
}

/// Unique contract identifier equivalent to the contract genesis commitment
#[derive(Wrapper, Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Hash, Debug, Display, From)]
#[derive(Wrapper, Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Hash, Debug, From)]
#[wrapper(Deref, BorrowSlice, Hex, Index, RangeOps)]
#[display(Self::to_baid58_string)]
#[derive(StrictType, StrictDumb, StrictEncode, StrictDecode)]
#[strict_type(lib = LIB_NAME_RGB)]
#[cfg_attr(
Expand Down Expand Up @@ -186,17 +186,25 @@ impl ContractId {

impl ToBaid58<32> for ContractId {
const HRI: &'static str = "rgb";
const CHUNKING: Option<Chunking> = CHUNKING_32CHECKSUM;
fn to_baid58_payload(&self) -> [u8; 32] { self.to_raw_array() }
fn to_baid58_string(&self) -> String { self.to_string() }
}
impl FromBaid58<32> for ContractId {}

impl ContractId {
fn to_baid58_string(&self) -> String { format!("{::^}", self.to_baid58()) }
impl Display for ContractId {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
if f.alternate() {
write!(f, "{::^}", self.to_baid58())
} else {
write!(f, "{::^.3}", self.to_baid58())
}
}
}

impl FromStr for ContractId {
type Err = Baid58ParseError;
fn from_str(s: &str) -> Result<Self, Self::Err> { Self::from_baid58_str(s) }
fn from_str(s: &str) -> Result<Self, Self::Err> {
Self::from_baid58_maybe_chunked_str(s, ':', '#')
}
}

impl From<mpc::ProtocolId> for ContractId {
Expand Down Expand Up @@ -637,16 +645,25 @@ mod test {

#[test]
fn contract_id_display() {
const ID: &str = "rgb:pkXwpsbaemTWhtSgVDGF25hEijtTAnPjzhB63ZwSehEWvfhF9";
const ID: &str = "rgb:pkXwpsb-aemTWhtSg-VDGF25hEi-jtTAnPjzh-B63ZwSehE-WvfhF9";
let id = ContractId::from_raw_array([0x6c; 32]);
assert_eq!(ID.len(), 53);
assert_eq!(ID.len(), 58);
assert_eq!(ID.replace('-', ""), format!("{id:#}"));
assert_eq!(ID, id.to_string());
assert_eq!(ID, id.to_baid58_string());
}

#[test]
fn contract_id_from_str() {
let id = ContractId::from_raw_array([0x6c; 32]);
assert_eq!(
Ok(id),
ContractId::from_str("rgb:pkXwpsb-aemTWhtSg-VDGF25hEi-jtTAnPjzh-B63ZwSehE-WvfhF9")
);
assert_eq!(
Ok(id),
ContractId::from_str("pkXwpsb-aemTWhtSg-VDGF25hEi-jtTAnPjzh-B63ZwSehE-WvfhF9")
);
assert_eq!(
Ok(id),
ContractId::from_str("rgb:pkXwpsbaemTWhtSgVDGF25hEijtTAnPjzhB63ZwSehEWvfhF9")
Expand All @@ -655,5 +672,16 @@ mod test {
Ok(id),
ContractId::from_str("pkXwpsbaemTWhtSgVDGF25hEijtTAnPjzhB63ZwSehEWvfhF9")
);

// Wrong separator placement
assert!(
ContractId::from_str("rgb:pkXwpsb-aemTWhtSg-VDGF25hEi-jtTAnPjzh-B63ZwSeh-EWvfhF9")
.is_err()
);
// Wrong separator number
assert!(
ContractId::from_str("rgb:pkXwpsb-aemTWhtSg-VDGF25hEi-jtTAnPjzh-B63ZwSehEWvfhF9")
.is_err()
);
}
}
31 changes: 22 additions & 9 deletions src/schema/schema.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ use std::str::FromStr;

use amplify::confinement::{TinyOrdMap, TinyOrdSet};
use amplify::{Bytes32, RawArray};
use baid58::{Baid58ParseError, FromBaid58, ToBaid58};
use baid58::{Baid58ParseError, Chunking, FromBaid58, ToBaid58, CHUNKING_32};
use commit_verify::{CommitStrategy, CommitmentId};
use strict_encoding::{StrictDecode, StrictDeserialize, StrictEncode, StrictSerialize, StrictType};
use strict_types::TypeSystem;
Expand Down Expand Up @@ -68,25 +68,32 @@ pub struct SchemaId(

impl ToBaid58<32> for SchemaId {
const HRI: &'static str = "sc";
const CHUNKING: Option<Chunking> = CHUNKING_32;
fn to_baid58_payload(&self) -> [u8; 32] { self.to_raw_array() }
fn to_baid58_string(&self) -> String { self.to_string() }
}
impl FromBaid58<32> for SchemaId {}
impl Display for SchemaId {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
if !f.alternate() {
f.write_str("urn:lnp-bp:sc:")?;
}
if f.sign_minus() {
write!(f, "urn:lnp-bp:{::<}", self.to_baid58())
write!(f, "{:.2}", self.to_baid58())
} else {
write!(f, "urn:lnp-bp:{::<#}", self.to_baid58())
write!(f, "{:#.2}", self.to_baid58())
}
}
}

impl FromStr for SchemaId {
type Err = Baid58ParseError;
fn from_str(s: &str) -> Result<Self, Self::Err> {
Self::from_baid58_str(s.trim_start_matches("urn:lnp-bp:"))
Self::from_baid58_maybe_chunked_str(s.trim_start_matches("urn:lnp-bp:"), ':', '#')
}
}
impl SchemaId {
pub fn to_mnemonic(&self) -> String { self.to_baid58().mnemonic() }
}

pub trait SchemaRoot: Clone + Eq + StrictType + StrictEncode + StrictDecode + Default {}
impl SchemaRoot for () {}
Expand Down Expand Up @@ -168,18 +175,24 @@ mod test {
let dumb = SchemaId::strict_dumb();
assert_eq!(
dumb.to_string(),
"urn:lnp-bp:sc:11111111111111111111111111111111#comedy-vega-mary"
"urn:lnp-bp:sc:111111-11111111-11111111-11111111-11#comedy-vega-mary"
);
assert_eq!(&format!("{dumb:-}"), "urn:lnp-bp:sc:11111111111111111111111111111111");
assert_eq!(&format!("{dumb:-}"), "urn:lnp-bp:sc:111111-11111111-11111111-11111111-11");

let less_dumb = SchemaId::from_raw_array(*b"EV4350-'4vwj'4;v-w94w'e'vFVVDhpq");
assert_eq!(
less_dumb.to_string(),
"urn:lnp-bp:sc:5ffNUkMTVSnWquPLT6xKb7VmAxUbw8CUNqCkUWsZfkwz#distant-thermos-arctic"
"urn:lnp-bp:sc:5ffNUk-MTVSnWqu-PLT6xKb7-VmAxUbw8-CUNqCkUW-sZfkwz#\
distant-thermos-arctic"
);
assert_eq!(
&format!("{less_dumb:-}"),
"urn:lnp-bp:sc:5ffNUkMTVSnWquPLT6xKb7VmAxUbw8CUNqCkUWsZfkwz"
"urn:lnp-bp:sc:5ffNUk-MTVSnWqu-PLT6xKb7-VmAxUbw8-CUNqCkUW-sZfkwz"
);
assert_eq!(
&format!("{less_dumb:#}"),
"5ffNUk-MTVSnWqu-PLT6xKb7-VmAxUbw8-CUNqCkUW-sZfkwz#distant-thermos-arctic"
);
assert_eq!(&format!("{less_dumb:-#}"), "5ffNUk-MTVSnWqu-PLT6xKb7-VmAxUbw8-CUNqCkUW-sZfkwz");
}
}

0 comments on commit eec46ed

Please sign in to comment.