Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Release v0.10.4 #93

Merged
merged 16 commits into from
Jul 24, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
216 changes: 120 additions & 96 deletions Cargo.lock

Large diffs are not rendered by default.

14 changes: 7 additions & 7 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -18,16 +18,16 @@ license = "Apache-2.0"

[workspace.dependencies]
amplify = "4.0.0"
baid58 = "0.3.1"
baid58 = "0.4.1"
strict_encoding = "2.5.0"
strict_types = "1.5.0"
commit_verify = { version = "0.10.4", features = ["stl"] }
bp-core = { version = "0.10.5", features = ["stl"] }
rgb-core = { version = "0.10.5", features = ["stl"] }
strict_types = "1.6.0"
commit_verify = { version = "0.10.5", features = ["stl"] }
bp-core = { version = "0.10.6", features = ["stl"] }
rgb-core = { version = "0.10.6", features = ["stl"] }

[package]
name = "rgb-wallet"
version = "0.10.3"
version = "0.10.4"
description = "RGB wallet library for smart contracts on Bitcoin & Lightning network"
keywords = ["bitcoin", "lightning", "rgb", "smart-contracts", "lnp-bp"]
categories = ["cryptography::cryptocurrencies"]
Expand All @@ -52,7 +52,7 @@ strict_encoding = { workspace = true }
# descriptor-wallet = "0.10.0-alpha.1"
bp-core = { workspace = true }
rgb-core = { workspace = true }
rgb-std = { version = "0.10.3", path = "std" }
rgb-std = { version = "0.10.4", path = "std" }
fluent-uri = "0.1.4"
indexmap = "1.9.2"
# TODO: This dependencies should be replaced with psbt package
Expand Down
78 changes: 42 additions & 36 deletions src/invoice.rs
Original file line number Diff line number Diff line change
Expand Up @@ -428,81 +428,84 @@ mod test {
fn parse() {
// all path parameters
let invoice_str = "rgb:EKkb7TMfbPxzn7UhvXqhoCutzdZkSZCNYxVAVjsA67fW/RGB20/\
100+6kzbKKffP6xftkxn9UP8gWqiC41W16wYKE5CYaVhmEve";
100+utxob0egXsFnw5Eud7WKYn7DVQvcPbcrR69YmgmGveacwmUFouMFKFb";
let invoice = RgbInvoice::from_str(invoice_str).unwrap();
assert_eq!(invoice.to_string(), invoice_str);

// no amount
let invoice_str = "rgb:EKkb7TMfbPxzn7UhvXqhoCutzdZkSZCNYxVAVjsA67fW/RGB20/\
6kzbKKffP6xftkxn9UP8gWqiC41W16wYKE5CYaVhmEve";
utxob0egXsFnw5Eud7WKYn7DVQvcPbcrR69YmgmGveacwmUFouMFKFb";
let invoice = RgbInvoice::from_str(invoice_str).unwrap();
assert_eq!(invoice.to_string(), invoice_str);

// no contract ID
let invoice_str = "rgb:~/RGB20/6kzbKKffP6xftkxn9UP8gWqiC41W16wYKE5CYaVhmEve";
let invoice_str = "rgb:~/RGB20/utxob0egXsFnw5Eud7WKYn7DVQvcPbcrR69YmgmGveacwmUFouMFKFb";
let invoice = RgbInvoice::from_str(invoice_str).unwrap();
assert_eq!(invoice.to_string(), invoice_str);

// no contract ID nor iface
let invoice_str = "rgb:~/~/6kzbKKffP6xftkxn9UP8gWqiC41W16wYKE5CYaVhmEve";
let invoice_str = "rgb:~/~/utxob0egXsFnw5Eud7WKYn7DVQvcPbcrR69YmgmGveacwmUFouMFKFb";
let invoice = RgbInvoice::from_str(invoice_str).unwrap();
assert_eq!(invoice.to_string(), invoice_str);

// contract ID provided but no iface
let invoice_str = "rgb:EKkb7TMfbPxzn7UhvXqhoCutzdZkSZCNYxVAVjsA67fW/~/\
6kzbKKffP6xftkxn9UP8gWqiC41W16wYKE5CYaVhmEve";
utxob0egXsFnw5Eud7WKYn7DVQvcPbcrR69YmgmGveacwmUFouMFKFb";
let result = RgbInvoice::from_str(invoice_str);
assert!(matches!(result, Err(InvoiceParseError::ContractIdNoIface)));

// invalid contract ID
let invalid_contract_id = "invalid";
let invoice_str =
format!("rgb:{invalid_contract_id}/RGB20/6kzbKKffP6xftkxn9UP8gWqiC41W16wYKE5CYaVhmEve");
let invoice_str = format!(
"rgb:{invalid_contract_id}/RGB20/\
utxob0egXsFnw5Eud7WKYn7DVQvcPbcrR69YmgmGveacwmUFouMFKFb"
);
let result = RgbInvoice::from_str(&invoice_str);
assert!(matches!(result,
Err(InvoiceParseError::InvalidContractId(c)) if c == invalid_contract_id));

// with expiration
let invoice_str = "rgb:EKkb7TMfbPxzn7UhvXqhoCutzdZkSZCNYxVAVjsA67fW/RGB20/\
100+6kzbKKffP6xftkxn9UP8gWqiC41W16wYKE5CYaVhmEve?expiry=1682086371";
100+utxob0egXsFnw5Eud7WKYn7DVQvcPbcrR69YmgmGveacwmUFouMFKFb?\
expiry=1682086371";
let invoice = RgbInvoice::from_str(invoice_str).unwrap();
assert_eq!(invoice.to_string(), invoice_str);

// bad expiration
let invoice_str = "rgb:EKkb7TMfbPxzn7UhvXqhoCutzdZkSZCNYxVAVjsA67fW/RGB20/\
100+6kzbKKffP6xftkxn9UP8gWqiC41W16wYKE5CYaVhmEve?expiry=six";
100+utxob0egXsFnw5Eud7WKYn7DVQvcPbcrR69YmgmGveacwmUFouMFKFb?expiry=six";
let result = RgbInvoice::from_str(invoice_str);
assert!(matches!(result, Err(InvoiceParseError::InvalidExpiration(_))));

// with bad query parameter
let invoice_str = "rgb:EKkb7TMfbPxzn7UhvXqhoCutzdZkSZCNYxVAVjsA67fW/RGB20/\
100+6kzbKKffP6xftkxn9UP8gWqiC41W16wYKE5CYaVhmEve?expiry";
100+utxob0egXsFnw5Eud7WKYn7DVQvcPbcrR69YmgmGveacwmUFouMFKFb?expiry";
let result = RgbInvoice::from_str(invoice_str);
assert!(matches!(result, Err(InvoiceParseError::InvalidQueryParam(_))));

// with an unknown query parameter
let invoice_str = "rgb:EKkb7TMfbPxzn7UhvXqhoCutzdZkSZCNYxVAVjsA67fW/RGB20/\
100+6kzbKKffP6xftkxn9UP8gWqiC41W16wYKE5CYaVhmEve?unknown=new";
100+utxob0egXsFnw5Eud7WKYn7DVQvcPbcrR69YmgmGveacwmUFouMFKFb?unknown=new";
let invoice = RgbInvoice::from_str(invoice_str).unwrap();
assert_eq!(invoice.to_string(), invoice_str);

// with two unknown query parameters
let invoice_str = "rgb:EKkb7TMfbPxzn7UhvXqhoCutzdZkSZCNYxVAVjsA67fW/RGB20/\
100+6kzbKKffP6xftkxn9UP8gWqiC41W16wYKE5CYaVhmEve?unknown=new&\
another=new";
100+utxob0egXsFnw5Eud7WKYn7DVQvcPbcrR69YmgmGveacwmUFouMFKFb?\
unknown=new&another=new";
let invoice = RgbInvoice::from_str(invoice_str).unwrap();
assert_eq!(invoice.to_string(), invoice_str);

// with expiration and an unknown query parameter
let invoice_str = "rgb:EKkb7TMfbPxzn7UhvXqhoCutzdZkSZCNYxVAVjsA67fW/RGB20/\
100+6kzbKKffP6xftkxn9UP8gWqiC41W16wYKE5CYaVhmEve?expiry=1682086371&\
unknown=new";
100+utxob0egXsFnw5Eud7WKYn7DVQvcPbcrR69YmgmGveacwmUFouMFKFb?\
expiry=1682086371&unknown=new";
let invoice = RgbInvoice::from_str(invoice_str).unwrap();
assert_eq!(invoice.to_string(), invoice_str);

// with an unknown query parameter containing percent-encoded text
let invoice_base = "rgb:EKkb7TMfbPxzn7UhvXqhoCutzdZkSZCNYxVAVjsA67fW/RGB20/\
100+6kzbKKffP6xftkxn9UP8gWqiC41W16wYKE5CYaVhmEve?";
100+utxob0egXsFnw5Eud7WKYn7DVQvcPbcrR69YmgmGveacwmUFouMFKFb?";
let query_key_encoded = ":@-%20%23";
let query_key_decoded = ":@- #";
let query_val_encoded = "?/.%26%3D";
Expand All @@ -519,39 +522,40 @@ mod test {

// no scheme
let invoice_str = "EKkb7TMfbPxzn7UhvXqhoCutzdZkSZCNYxVAVjsA67fW/~/\
6kzbKKffP6xftkxn9UP8gWqiC41W16wYKE5CYaVhmEve";
utxob0egXsFnw5Eud7WKYn7DVQvcPbcrR69YmgmGveacwmUFouMFKFb";
let result = RgbInvoice::from_str(invoice_str);
assert!(matches!(result, Err(InvoiceParseError::Invalid)));

// invalid scheme
let invoice_str = "bad:EKkb7TMfbPxzn7UhvXqhoCutzdZkSZCNYxVAVjsA67fW/~/\
6kzbKKffP6xftkxn9UP8gWqiC41W16wYKE5CYaVhmEve";
utxob0egXsFnw5Eud7WKYn7DVQvcPbcrR69YmgmGveacwmUFouMFKFb";
let result = RgbInvoice::from_str(invoice_str);
assert!(matches!(result, Err(InvoiceParseError::InvalidScheme(_))));

// empty transport endpoint specification
let invoice_str = "rgb:EKkb7TMfbPxzn7UhvXqhoCutzdZkSZCNYxVAVjsA67fW/RGB20/\
100+6kzbKKffP6xftkxn9UP8gWqiC41W16wYKE5CYaVhmEve?endpoints=";
100+utxob0egXsFnw5Eud7WKYn7DVQvcPbcrR69YmgmGveacwmUFouMFKFb?endpoints=";
let result = RgbInvoice::from_str(invoice_str);
assert!(matches!(result, Err(InvoiceParseError::InvalidQueryParam(_))));

// invalid transport endpoint specification
let invoice_str = "rgb:EKkb7TMfbPxzn7UhvXqhoCutzdZkSZCNYxVAVjsA67fW/RGB20/\
100+6kzbKKffP6xftkxn9UP8gWqiC41W16wYKE5CYaVhmEve?endpoints=bad";
100+utxob0egXsFnw5Eud7WKYn7DVQvcPbcrR69YmgmGveacwmUFouMFKFb?\
endpoints=bad";
let result = RgbInvoice::from_str(invoice_str);
assert!(matches!(result, Err(InvoiceParseError::InvalidQueryParam(_))));

// invalid transport variant
let invoice_str = "rgb:EKkb7TMfbPxzn7UhvXqhoCutzdZkSZCNYxVAVjsA67fW/RGB20/\
100+6kzbKKffP6xftkxn9UP8gWqiC41W16wYKE5CYaVhmEve?endpoints=rpca://host.\
example.com";
100+utxob0egXsFnw5Eud7WKYn7DVQvcPbcrR69YmgmGveacwmUFouMFKFb?\
endpoints=rpca://host.example.com";
let result = RgbInvoice::from_str(invoice_str);
assert!(matches!(result, Err(InvoiceParseError::InvalidQueryParam(_))));

// rgb-rpc variant
let invoice_str = "rgb:EKkb7TMfbPxzn7UhvXqhoCutzdZkSZCNYxVAVjsA67fW/RGB20/\
100+6kzbKKffP6xftkxn9UP8gWqiC41W16wYKE5CYaVhmEve?endpoints=rpc://host.\
example.com";
100+utxob0egXsFnw5Eud7WKYn7DVQvcPbcrR69YmgmGveacwmUFouMFKFb?\
endpoints=rpc://host.example.com";
let invoice = RgbInvoice::from_str(invoice_str).unwrap();
assert_eq!(invoice.transports, vec![RgbTransport::JsonRpc {
tls: false,
Expand All @@ -561,8 +565,8 @@ mod test {

// rgb-rpc variant, host containing authentication, "-" characters and port
let invoice_str = "rgb:EKkb7TMfbPxzn7UhvXqhoCutzdZkSZCNYxVAVjsA67fW/RGB20/\
100+6kzbKKffP6xftkxn9UP8gWqiC41W16wYKE5CYaVhmEve?endpoints=rpcs://user:\
[email protected]:1234";
100+utxob0egXsFnw5Eud7WKYn7DVQvcPbcrR69YmgmGveacwmUFouMFKFb?\
endpoints=rpcs://user:[email protected]:1234";
let invoice = RgbInvoice::from_str(invoice_str).unwrap();
assert_eq!(invoice.transports, vec![RgbTransport::JsonRpc {
tls: true,
Expand All @@ -572,8 +576,8 @@ mod test {

// rgb-rpc variant, IPv6 host
let invoice_str = "rgb:EKkb7TMfbPxzn7UhvXqhoCutzdZkSZCNYxVAVjsA67fW/RGB20/\
100+6kzbKKffP6xftkxn9UP8gWqiC41W16wYKE5CYaVhmEve?endpoints=rpcs://%\
5B2001:db8::1%5D:1234";
100+utxob0egXsFnw5Eud7WKYn7DVQvcPbcrR69YmgmGveacwmUFouMFKFb?\
endpoints=rpcs://%5B2001:db8::1%5D:1234";
let invoice = RgbInvoice::from_str(invoice_str).unwrap();
assert_eq!(invoice.transports, vec![RgbTransport::JsonRpc {
tls: true,
Expand All @@ -583,27 +587,29 @@ mod test {

// rgb-rpc variant with missing host
let invoice_str = "rgb:EKkb7TMfbPxzn7UhvXqhoCutzdZkSZCNYxVAVjsA67fW/RGB20/\
100+6kzbKKffP6xftkxn9UP8gWqiC41W16wYKE5CYaVhmEve?endpoints=rpc://";
100+utxob0egXsFnw5Eud7WKYn7DVQvcPbcrR69YmgmGveacwmUFouMFKFb?\
endpoints=rpc://";
let result = RgbInvoice::from_str(invoice_str);
assert!(matches!(result, Err(InvoiceParseError::InvalidQueryParam(_))));

// rgb-rpc variant with invalid separator
let invoice_str = "rgb:EKkb7TMfbPxzn7UhvXqhoCutzdZkSZCNYxVAVjsA67fW/RGB20/\
100+6kzbKKffP6xftkxn9UP8gWqiC41W16wYKE5CYaVhmEve?endpoints=rpc/host.\
example.com";
100+utxob0egXsFnw5Eud7WKYn7DVQvcPbcrR69YmgmGveacwmUFouMFKFb?\
endpoints=rpc/host.example.com";
let result = RgbInvoice::from_str(invoice_str);
assert!(matches!(result, Err(InvoiceParseError::InvalidQueryParam(_))));

// rgb-rpc variant with invalid transport host specification
let invoice_str = "rgb:EKkb7TMfbPxzn7UhvXqhoCutzdZkSZCNYxVAVjsA67fW/RGB20/\
100+6kzbKKffP6xftkxn9UP8gWqiC41W16wYKE5CYaVhmEve?endpoints=rpc://ho]t";
100+utxob0egXsFnw5Eud7WKYn7DVQvcPbcrR69YmgmGveacwmUFouMFKFb?\
endpoints=rpc://ho]t";
let result = RgbInvoice::from_str(invoice_str);
assert!(matches!(result, Err(InvoiceParseError::Uri(_))));

// rgb+http variant
let invoice_str = "rgb:\
EKkb7TMfbPxzn7UhvXqhoCutzdZkSZCNYxVAVjsA67fW/RGB20/\
100+6kzbKKffP6xftkxn9UP8gWqiC41W16wYKE5CYaVhmEve?endpoints=https://\
100+utxob0egXsFnw5Eud7WKYn7DVQvcPbcrR69YmgmGveacwmUFouMFKFb?endpoints=https://\
host.example.com";
let invoice = RgbInvoice::from_str(invoice_str).unwrap();
let transports = vec![RgbTransport::RestHttp {
Expand All @@ -615,8 +621,8 @@ mod test {

// rgb+ws variant
let invoice_str = "rgb:EKkb7TMfbPxzn7UhvXqhoCutzdZkSZCNYxVAVjsA67fW/RGB20/\
100+6kzbKKffP6xftkxn9UP8gWqiC41W16wYKE5CYaVhmEve?endpoints=wss://host.\
example.com";
100+utxob0egXsFnw5Eud7WKYn7DVQvcPbcrR69YmgmGveacwmUFouMFKFb?\
endpoints=wss://host.example.com";
let invoice = RgbInvoice::from_str(invoice_str).unwrap();
let transports = vec![RgbTransport::WebSockets {
tls: true,
Expand All @@ -630,7 +636,7 @@ mod test {
// multiple transports
let invoice_str = "rgb:\
EKkb7TMfbPxzn7UhvXqhoCutzdZkSZCNYxVAVjsA67fW/RGB20/\
100+6kzbKKffP6xftkxn9UP8gWqiC41W16wYKE5CYaVhmEve?endpoints=rpcs://\
100+utxob0egXsFnw5Eud7WKYn7DVQvcPbcrR69YmgmGveacwmUFouMFKFb?endpoints=rpcs://\
host1.example.com,http://host2.example.com,ws://host3.example.com";
let invoice = RgbInvoice::from_str(invoice_str).unwrap();
let transports = vec![
Expand Down
3 changes: 2 additions & 1 deletion std/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "rgb-std"
version = "0.10.3"
version = "0.10.4"
description = "RGB standard library for working with smart contracts on Bitcoin & Lightning"
keywords = ["bitcoin", "lightning", "rgb", "smart-contracts", "lnp-bp"]
categories = ["cryptography::cryptocurrencies"]
Expand Down Expand Up @@ -28,6 +28,7 @@ bp-core = { workspace = true }
rgb-core = { workspace = true }
baid58 = { workspace = true }
base64 = "0.21.0"
chrono = "0.4.26"
serde_crate = { package = "serde", version = "1", features = ["derive"] }

[features]
Expand Down
2 changes: 1 addition & 1 deletion std/src/containers/bindle.rs
Original file line number Diff line number Diff line change
Expand Up @@ -244,7 +244,7 @@ impl<C: BindleContent> FromStr for Bindle<C> {
impl<C: BindleContent> Display for Bindle<C> {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
writeln!(f, "-----BEGIN {}-----", C::PLATE_TITLE)?;
writeln!(f, "Id: {}", self.id)?;
writeln!(f, "Id: {:-}", self.id)?;
for (header, value) in self.bindle_headers() {
writeln!(f, "{header}: {value}")?;
}
Expand Down
8 changes: 5 additions & 3 deletions std/src/containers/transfer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ use crate::LIB_NAME_RGB_STD;
/// Transfer identifier.
#[derive(Wrapper, Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Hash, Debug, Display, From)]
#[wrapper(Deref, BorrowSlice, Hex, Index, RangeOps)]
#[display(Self::to_baid58)]
#[display(Self::to_baid58_string)]
#[derive(StrictType, StrictDumb, StrictEncode, StrictDecode)]
#[strict_type(lib = LIB_NAME_RGB_STD)]
#[cfg_attr(
Expand All @@ -49,15 +49,17 @@ pub struct TransferId(
);

impl ToBaid58<32> for TransferId {
const HRI: &'static str = "tfer";
const HRI: &'static str = "rgb-cons";
fn to_baid58_payload(&self) -> [u8; 32] { self.to_raw_array() }
}
impl FromBaid58<32> for TransferId {}

impl FromStr for TransferId {
type Err = Baid58ParseError;
fn from_str(s: &str) -> Result<Self, Self::Err> { Self::from_baid58_str(s) }
}
impl TransferId {
pub fn to_baid58_string(&self) -> String { format!("{::<#}", self.to_baid58()) }
}

impl CommitEncode for Transfer {
fn commit_encode(&self, e: &mut impl io::Write) {
Expand Down
23 changes: 14 additions & 9 deletions std/src/interface/iface.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
// limitations under the License.

use std::cmp::Ordering;
use std::fmt::{self, Display, Formatter};
use std::str::FromStr;

use amplify::confinement::{TinyOrdMap, TinyOrdSet};
Expand All @@ -39,9 +40,8 @@ use crate::LIB_NAME_RGB_STD;
/// Interface identifier.
///
/// Interface identifier commits to all of the interface data.
#[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_STD)]
#[cfg_attr(
Expand All @@ -56,19 +56,24 @@ pub struct IfaceId(
);

impl ToBaid58<32> for IfaceId {
const HRI: &'static str = "rgb-ifc";
const HRI: &'static str = "if";
fn to_baid58_payload(&self) -> [u8; 32] { self.to_raw_array() }
}
impl FromBaid58<32> for IfaceId {}

impl IfaceId {
#[allow(clippy::wrong_self_convention)]
fn to_baid58_string(&self) -> String { format!("{}", self.to_baid58()) }
impl Display for IfaceId {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
if f.sign_minus() {
write!(f, "urn:lnp-bp:{::<}", self.to_baid58())
} else {
write!(f, "urn:lnp-bp:{::<#}", self.to_baid58())
}
}
}

impl FromStr for IfaceId {
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_str(s.trim_start_matches("urn:lnp-bp:"))
}
}

#[derive(Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Hash, Debug)]
Expand Down
Loading
Loading