Skip to content

Commit

Permalink
fix: handling of the namespaces in v255
Browse files Browse the repository at this point in the history
  • Loading branch information
zvolin committed Dec 13, 2023
1 parent 0ab21ab commit 7670ed2
Show file tree
Hide file tree
Showing 2 changed files with 86 additions and 8 deletions.
3 changes: 3 additions & 0 deletions types/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,9 @@ pub enum Error {
#[error("Invalid namespace v0")]
InvalidNamespaceV0,

#[error("Invalid namespace v255")]
InvalidNamespaceV255,

#[error(transparent)]
InvalidNamespacedHash(#[from] nmt_rs::InvalidNamespacedHash),

Expand Down
91 changes: 83 additions & 8 deletions types/src/nmt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,14 @@ pub type Nmt = nmt_rs::NamespaceMerkleTree<MemDb<NamespacedHash>, NamespacedSha2
pub struct Namespace(nmt_rs::NamespaceId<NS_SIZE>);

impl Namespace {
pub const MAX: Namespace = Namespace(nmt_rs::NamespaceId::MAX_ID);
pub const TRANSACTION: Namespace = Namespace::const_v0([0, 0, 0, 0, 0, 0, 0, 0, 0, 1]);
pub const PAY_FOR_BLOB: Namespace = Namespace::const_v0([0, 0, 0, 0, 0, 0, 0, 0, 0, 1]);
pub const PRIMARY_RESERVED_PADDING: Namespace = Namespace::MAX_PRIMARY_RESERVED;
pub const MAX_PRIMARY_RESERVED: Namespace =
Namespace::const_v0([0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff]);
pub const MIN_SECONDARY_RESERVED: Namespace = Namespace::const_v255(0);
pub const TAIL_PADDING: Namespace = Namespace::const_v255(0xfe);
pub const PARITY_SHARE: Namespace = Namespace::const_v255(0xff);

pub fn from_raw(bytes: &[u8]) -> Result<Self> {
if bytes.len() != NS_SIZE {
Expand All @@ -47,7 +54,7 @@ impl Namespace {
pub fn new(version: u8, id: &[u8]) -> Result<Self> {
match version {
0 => Self::new_v0(id),
255 => Self::try_max(id),
255 => Self::new_v255(id),
n => Err(Error::UnsupportedNamespaceVersion(n)),
}
}
Expand Down Expand Up @@ -98,11 +105,21 @@ impl Namespace {
Namespace(nmt_rs::NamespaceId(bytes))
}

fn try_max(id: &[u8]) -> Result<Self> {
if id.iter().all(|&x| x == 0xff) {
Ok(Namespace::MAX)
pub const fn const_v255(id: u8) -> Self {
let mut bytes = [255u8; NS_SIZE];
bytes[NS_ID_SIZE] = id;
Namespace(nmt_rs::NamespaceId(bytes))
}

pub fn new_v255(id: &[u8]) -> Result<Self> {
if id.len() != NS_ID_SIZE {
return Err(Error::InvalidNamespaceSize);
}

if id.iter().take(NS_ID_SIZE - 1).all(|&x| x == 0xff) {
Ok(Namespace::const_v255(id[NS_ID_SIZE - 1]))
} else {
Err(Error::UnsupportedNamespaceVersion(255))
Err(Error::InvalidNamespaceV255)
}
}

Expand Down Expand Up @@ -267,6 +284,14 @@ mod tests {
assert_eq!(nid, expected_nid);
}

#[test]
fn namespace_id_max() {
let nid = Namespace::new(0xff, &[0xff; 28]).unwrap();
let expected_nid = Namespace::PARITY_SHARE;

assert_eq!(nid, expected_nid);
}

#[test]
fn namespace_id_const_v0() {
let nid = Namespace::const_v0([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);
Expand All @@ -279,6 +304,20 @@ mod tests {
assert_eq!(nid, expected_nid);
}

#[test]
fn namespace_id_const_v255() {
let nid = Namespace::const_v255(0xab);
let expected_nid = Namespace(nmt_rs::NamespaceId([
0xff, // version
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, // prefix
0xab, // id
]));

assert_eq!(nid, expected_nid);
}

#[test]
fn namespace_id_10_bytes_with_prefix() {
let nid = Namespace::new_v0(&[
Expand Down Expand Up @@ -314,6 +353,32 @@ mod tests {
assert!(matches!(e, Error::InvalidNamespaceSize));
}

#[test]
fn namespace_id_v255_too_long() {
let e = Namespace::new_v255(&[0xff; 29]).unwrap_err();

assert!(matches!(e, Error::InvalidNamespaceSize));
}

#[test]
fn namespace_id_v255_too_short() {
let e = Namespace::new_v255(&[0xff; 27]).unwrap_err();

assert!(matches!(e, Error::InvalidNamespaceSize));
}

#[test]
fn namespace_id_max_invalid_prefix() {
let namespace = &[
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xfe, 0xff,
];
let e = Namespace::new_v255(namespace).unwrap_err();

assert!(matches!(e, Error::InvalidNamespaceV255));
}

#[test]
fn namespace_id_from_raw_bytes() {
let nid = Namespace::from_raw(&[
Expand Down Expand Up @@ -365,7 +430,7 @@ mod tests {
])
.unwrap();

let expected_nid = Namespace::MAX;
let expected_nid = Namespace::PARITY_SHARE;

assert_eq!(nid, expected_nid);
}
Expand All @@ -378,9 +443,19 @@ mod tests {
])
.unwrap_err();

assert!(matches!(e, Error::UnsupportedNamespaceVersion(255)));
assert!(matches!(e, Error::InvalidNamespaceV255));

let e = Namespace::from_raw(&[
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xfe, 0xff,
])
.unwrap_err();

assert!(matches!(e, Error::InvalidNamespaceV255));
}


#[test]
fn invalid_version() {
let e = Namespace::from_raw(&[
Expand Down

0 comments on commit 7670ed2

Please sign in to comment.