pub struct NsTable {
pub(crate) bytes: Vec<u8>,
}
Expand description
Raw binary data for a namespace table.
Any sequence of bytes is a valid NsTable
.
§Binary format of a namespace table
Byte lengths for the different items that could appear in a namespace table
are specified in local private constants NUM_NSS_BYTE_LEN
,
NS_OFFSET_BYTE_LEN
, NS_ID_BYTE_LEN
.
§Number of entries in the namespace table
The first NUM_NSS_BYTE_LEN
bytes of the namespace table indicate the
number n
of entries in the table as a little-endian unsigned integer. If
the entire table length is smaller than NUM_NSS_BYTE_LEN
then the
missing bytes are zero-padded.
The bytes in the namespace table beyond the first NUM_NSS_BYTE_LEN
bytes
encode table entries. Each entry consumes exactly NS_ID_BYTE_LEN
+
NS_OFFSET_BYTE_LEN
bytes.
The number n
could be anything, including a number much larger than the
number of entries that could fit in the namespace table. As such, the actual
number of entries in the table is defined as the minimum of n
and the
maximum number of whole entries that could fit in the table.
See Self::in_bounds
for clarification.
§Namespace table entry
§Namespace ID
The first NS_ID_BYTE_LEN
bytes of each table entry indicate the
[NamespaceId
] for this namespace. Any table entry whose [NamespaceId
] is
a duplicate of a previous entry is ignored. A correct count of the number of
unique (non-ignored) entries is given by NsTable::iter().count()
.
§Namespace offset
The next NS_OFFSET_BYTE_LEN
bytes of each table entry indicate the
end-index of a namespace in the block payload bytes
Payload
. This end-index is a little-endian
unsigned integer.
§How to deduce a namespace’s byte range
In order to extract the payload bytes of a single namespace N
from the
block payload one needs both the start- and end-indices for N
.
See Self::ns_range
for clarification. What follows is a description of
what’s implemented in Self::ns_range
.
If N
occupies the i
th entry in the namespace table for i>0
then the
start-index for N
is defined as the end-index of the (i-1)
th entry in
the table.
Even if the (i-1)
the entry would otherwise be ignored (due to a duplicate
[NamespaceId
] or any other reason), that entry’s end-index still defines
the start-index of N
. This rule guarantees that both start- and
end-indices for any namespace N
can be read from a constant-size byte
range in the namespace table, and it eliminates the need to traverse an
unbounded number of previous entries of the namespace table looking for a
previous non-ignored entry.
The start-index of the 0th entry in the table is implicitly defined to be
0
.
The start- and end-indices (declared_start, declared_end)
declared in the
namespace table could be anything. As such, the actual start- and
end-indices (start, end)
are defined so as to ensure that the byte range
is well-defined and in-bounds for the block payload:
end = min(declared_end, block_payload_byte_length)
start = min(declared_start, end)
In a “honestly-prepared” namespace table the end-index of the final namespace equals the byte length of the block payload. (Otherwise the block payload might have bytes that are not included in any namespace.)
It is possible that a namespace table could indicate two distinct namespaces whose byte ranges overlap, though no “honestly-prepared” namespace table would do this.
TODO prefer NsTable
to be a newtype like this
#[repr(transparent)]
#[derive(Clone, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)]
#[serde(transparent)]
pub struct NsTable(#[serde(with = "base64_bytes")] Vec<u8>);
but we need to maintain serialization compatibility. https://github.com/EspressoSystems/espresso-sequencer/issues/1575
Fields§
§bytes: Vec<u8>
Implementations§
Source§impl NsTable
impl NsTable
Sourcepub fn find_ns_id(&self, ns_id: &NamespaceId) -> Option<NsIndex>
pub fn find_ns_id(&self, ns_id: &NamespaceId) -> Option<NsIndex>
Search the namespace table for the ns_index belonging to ns_id
.
Sourcepub fn len(&self) -> NumNss
pub fn len(&self) -> NumNss
Number of entries in the namespace table.
Defined as the maximum number of entries that could fit in the namespace table, ignoring what’s declared in the table header.
Sourcepub fn iter(&self) -> impl Iterator<Item = NsIndex> + '_
pub fn iter(&self) -> impl Iterator<Item = NsIndex> + '_
Iterator over all unique namespaces in the namespace table.
Sourcepub fn read_ns_id(&self, index: &NsIndex) -> Option<NamespaceId>
pub fn read_ns_id(&self, index: &NsIndex) -> Option<NamespaceId>
Read the namespace id from the index
th entry from the namespace table.
Returns None
if index
is out of bounds.
TODO I want to restrict visibility to pub(crate)
or lower but this
method is currently used in nasty-client
.
Sourcepub fn read_ns_id_unchecked(&self, index: &NsIndex) -> NamespaceId
pub fn read_ns_id_unchecked(&self, index: &NsIndex) -> NamespaceId
Like Self::read_ns_id
except index
is not checked. Use Self::in_bounds
as needed.
Sourcepub fn in_bounds(&self, index: &NsIndex) -> bool
pub fn in_bounds(&self, index: &NsIndex) -> bool
Does the index
th entry exist in the namespace table?
Sourcepub fn from_bytes_unchecked(bytes: &[u8]) -> NsTable
pub fn from_bytes_unchecked(bytes: &[u8]) -> NsTable
Instantiate an NsTable
from a byte slice.
Sourcepub fn validate(
&self,
payload_byte_len: &PayloadByteLen,
) -> Result<(), NsTableValidationError>
pub fn validate( &self, payload_byte_len: &PayloadByteLen, ) -> Result<(), NsTableValidationError>
Are the bytes of this NsTable
uncorrupted?
§Checks
- Byte length must hold a whole number of entries.
- All offsets must increase monotonically. Offsets must be nonzero. Namespace IDs must be unique.
- Header consistent with byte length. (Obsolete after https://github.com/EspressoSystems/espresso-sequencer/issues/1604.)
- Final offset must equal
payload_byte_len
. (Obsolete after https://github.com/EspressoSystems/espresso-sequencer/issues/1604.) If the namespace table is empty thenpayload_byte_len
must be 0.
Sourcepub fn ns_range(
&self,
index: &NsIndex,
payload_byte_len: &PayloadByteLen,
) -> NsPayloadRange
pub fn ns_range( &self, index: &NsIndex, payload_byte_len: &PayloadByteLen, ) -> NsPayloadRange
Read subslice range for the index
th namespace from the namespace
table.
Sourcefn read_num_nss(&self) -> usize
fn read_num_nss(&self) -> usize
Read the number of namespaces declared in the namespace table. THIS
QUANTITY IS NEVER USED. Instead use NsTable::len
.
TODO Delete this method after https://github.com/EspressoSystems/espresso-sequencer/issues/1604
Sourcefn read_ns_offset_unchecked(&self, index: &NsIndex) -> usize
fn read_ns_offset_unchecked(&self, index: &NsIndex) -> usize
Read the namespace offset from the index
th entry from the namespace table.
Sourcefn validate_deserialization_invariants(
&self,
) -> Result<(), NsTableValidationError>
fn validate_deserialization_invariants( &self, ) -> Result<(), NsTableValidationError>
Helper for NsTable::validate
, used in our custom serde
implementation.
Checks conditions 1-3 of NsTable::validate
. Those conditions can be
checked by looking only at the contents of the NsTable
.
Source§impl<'de> NsTable
impl<'de> NsTable
pub fn deserialize<__D>(__deserializer: __D) -> Result<NsTable, __D::Error>where
__D: Deserializer<'de>,
Trait Implementations§
Source§impl<'de> Deserialize<'de> for NsTable
impl<'de> Deserialize<'de> for NsTable
Source§fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>where
D: Deserializer<'de>,
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>where
D: Deserializer<'de>,
impl Eq for NsTable
impl StructuralPartialEq for NsTable
Auto Trait Implementations§
impl Freeze for NsTable
impl RefUnwindSafe for NsTable
impl Send for NsTable
impl Sync for NsTable
impl Unpin for NsTable
impl UnwindSafe for NsTable
Blanket Implementations§
§impl<T> ArchivePointee for T
impl<T> ArchivePointee for T
§type ArchivedMetadata = ()
type ArchivedMetadata = ()
§fn pointer_metadata(
_: &<T as ArchivePointee>::ArchivedMetadata,
) -> <T as Pointee>::Metadata
fn pointer_metadata( _: &<T as ArchivePointee>::ArchivedMetadata, ) -> <T as Pointee>::Metadata
§impl<'a, T, E> AsTaggedExplicit<'a, E> for Twhere
T: 'a,
impl<'a, T, E> AsTaggedExplicit<'a, E> for Twhere
T: 'a,
§impl<'a, T, E> AsTaggedImplicit<'a, E> for Twhere
T: 'a,
impl<'a, T, E> AsTaggedImplicit<'a, E> for Twhere
T: 'a,
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
§impl<T> CallHasher for T
impl<T> CallHasher for T
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
§impl<T> Conv for T
impl<T> Conv for T
§impl<F, W, T, D> Deserialize<With<T, W>, D> for F
impl<F, W, T, D> Deserialize<With<T, W>, D> for F
§fn deserialize(
&self,
deserializer: &mut D,
) -> Result<With<T, W>, <D as Fallible>::Error>
fn deserialize( &self, deserializer: &mut D, ) -> Result<With<T, W>, <D as Fallible>::Error>
§impl<T> Downcast for Twhere
T: Any,
impl<T> Downcast for Twhere
T: Any,
§fn into_any(self: Box<T>) -> Box<dyn Any>
fn into_any(self: Box<T>) -> Box<dyn Any>
Box<dyn Trait>
(where Trait: Downcast
) to Box<dyn Any>
. Box<dyn Any>
can
then be further downcast
into Box<ConcreteType>
where ConcreteType
implements Trait
.§fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
Rc<Trait>
(where Trait: Downcast
) to Rc<Any>
. Rc<Any>
can then be
further downcast
into Rc<ConcreteType>
where ConcreteType
implements Trait
.§fn as_any(&self) -> &(dyn Any + 'static)
fn as_any(&self) -> &(dyn Any + 'static)
&Trait
(where Trait: Downcast
) to &Any
. This is needed since Rust cannot
generate &Any
’s vtable from &Trait
’s.§fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
&mut Trait
(where Trait: Downcast
) to &Any
. This is needed since Rust cannot
generate &mut Any
’s vtable from &mut Trait
’s.§impl<T> DowncastSync for T
impl<T> DowncastSync for T
§impl<Q, K> Equivalent<K> for Q
impl<Q, K> Equivalent<K> for Q
§fn equivalent(&self, key: &K) -> bool
fn equivalent(&self, key: &K) -> bool
key
and return true
if they are equal.§impl<Q, K> Equivalent<K> for Q
impl<Q, K> Equivalent<K> for Q
§fn equivalent(&self, key: &K) -> bool
fn equivalent(&self, key: &K) -> bool
§impl<Q, K> Equivalent<K> for Q
impl<Q, K> Equivalent<K> for Q
§fn equivalent(&self, key: &K) -> bool
fn equivalent(&self, key: &K) -> bool
§impl<T> FmtForward for T
impl<T> FmtForward for T
§fn fmt_binary(self) -> FmtBinary<Self>where
Self: Binary,
fn fmt_binary(self) -> FmtBinary<Self>where
Self: Binary,
self
to use its Binary
implementation when Debug
-formatted.§fn fmt_display(self) -> FmtDisplay<Self>where
Self: Display,
fn fmt_display(self) -> FmtDisplay<Self>where
Self: Display,
self
to use its Display
implementation when
Debug
-formatted.§fn fmt_lower_exp(self) -> FmtLowerExp<Self>where
Self: LowerExp,
fn fmt_lower_exp(self) -> FmtLowerExp<Self>where
Self: LowerExp,
self
to use its LowerExp
implementation when
Debug
-formatted.§fn fmt_lower_hex(self) -> FmtLowerHex<Self>where
Self: LowerHex,
fn fmt_lower_hex(self) -> FmtLowerHex<Self>where
Self: LowerHex,
self
to use its LowerHex
implementation when
Debug
-formatted.§fn fmt_octal(self) -> FmtOctal<Self>where
Self: Octal,
fn fmt_octal(self) -> FmtOctal<Self>where
Self: Octal,
self
to use its Octal
implementation when Debug
-formatted.§fn fmt_pointer(self) -> FmtPointer<Self>where
Self: Pointer,
fn fmt_pointer(self) -> FmtPointer<Self>where
Self: Pointer,
self
to use its Pointer
implementation when
Debug
-formatted.§fn fmt_upper_exp(self) -> FmtUpperExp<Self>where
Self: UpperExp,
fn fmt_upper_exp(self) -> FmtUpperExp<Self>where
Self: UpperExp,
self
to use its UpperExp
implementation when
Debug
-formatted.§fn fmt_upper_hex(self) -> FmtUpperHex<Self>where
Self: UpperHex,
fn fmt_upper_hex(self) -> FmtUpperHex<Self>where
Self: UpperHex,
self
to use its UpperHex
implementation when
Debug
-formatted.§fn fmt_list(self) -> FmtList<Self>where
&'a Self: for<'a> IntoIterator,
fn fmt_list(self) -> FmtList<Self>where
&'a Self: for<'a> IntoIterator,
§impl<T> Instrument for T
impl<T> Instrument for T
§fn instrument(self, span: Span) -> Instrumented<Self>
fn instrument(self, span: Span) -> Instrumented<Self>
§fn in_current_span(self) -> Instrumented<Self>
fn in_current_span(self) -> Instrumented<Self>
Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self>
fn instrument(self, span: Span) -> Instrumented<Self>
Source§fn in_current_span(self) -> Instrumented<Self>
fn in_current_span(self) -> Instrumented<Self>
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
self
into a Left
variant of Either<Self, Self>
if into_left
is true
.
Converts self
into a Right
variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
self
into a Left
variant of Either<Self, Self>
if into_left(&self)
returns true
.
Converts self
into a Right
variant of Either<Self, Self>
otherwise. Read more§impl<T> LayoutRaw for T
impl<T> LayoutRaw for T
§fn layout_raw(_: <T as Pointee>::Metadata) -> Result<Layout, LayoutError>
fn layout_raw(_: <T as Pointee>::Metadata) -> Result<Layout, LayoutError>
§impl<T> Pipe for Twhere
T: ?Sized,
impl<T> Pipe for Twhere
T: ?Sized,
§fn pipe<R>(self, func: impl FnOnce(Self) -> R) -> Rwhere
Self: Sized,
fn pipe<R>(self, func: impl FnOnce(Self) -> R) -> Rwhere
Self: Sized,
§fn pipe_ref<'a, R>(&'a self, func: impl FnOnce(&'a Self) -> R) -> Rwhere
R: 'a,
fn pipe_ref<'a, R>(&'a self, func: impl FnOnce(&'a Self) -> R) -> Rwhere
R: 'a,
self
and passes that borrow into the pipe function. Read more§fn pipe_ref_mut<'a, R>(&'a mut self, func: impl FnOnce(&'a mut Self) -> R) -> Rwhere
R: 'a,
fn pipe_ref_mut<'a, R>(&'a mut self, func: impl FnOnce(&'a mut Self) -> R) -> Rwhere
R: 'a,
self
and passes that borrow into the pipe function. Read more§fn pipe_borrow<'a, B, R>(&'a self, func: impl FnOnce(&'a B) -> R) -> R
fn pipe_borrow<'a, B, R>(&'a self, func: impl FnOnce(&'a B) -> R) -> R
§fn pipe_borrow_mut<'a, B, R>(
&'a mut self,
func: impl FnOnce(&'a mut B) -> R,
) -> R
fn pipe_borrow_mut<'a, B, R>( &'a mut self, func: impl FnOnce(&'a mut B) -> R, ) -> R
§fn pipe_as_ref<'a, U, R>(&'a self, func: impl FnOnce(&'a U) -> R) -> R
fn pipe_as_ref<'a, U, R>(&'a self, func: impl FnOnce(&'a U) -> R) -> R
self
, then passes self.as_ref()
into the pipe function.§fn pipe_as_mut<'a, U, R>(&'a mut self, func: impl FnOnce(&'a mut U) -> R) -> R
fn pipe_as_mut<'a, U, R>(&'a mut self, func: impl FnOnce(&'a mut U) -> R) -> R
self
, then passes self.as_mut()
into the pipe
function.§fn pipe_deref<'a, T, R>(&'a self, func: impl FnOnce(&'a T) -> R) -> R
fn pipe_deref<'a, T, R>(&'a self, func: impl FnOnce(&'a T) -> R) -> R
self
, then passes self.deref()
into the pipe function.§impl<T> Pointable for T
impl<T> Pointable for T
§impl<T> Resolvable<T> for Twhere
T: Committable,
impl<T> Resolvable<T> for Twhere
T: Committable,
§fn try_resolve(self) -> Result<T, T>
fn try_resolve(self) -> Result<T, T>
§fn commitment(&self) -> Commitment<T>
fn commitment(&self) -> Commitment<T>
§impl<T> Tap for T
impl<T> Tap for T
§fn tap_borrow<B>(self, func: impl FnOnce(&B)) -> Self
fn tap_borrow<B>(self, func: impl FnOnce(&B)) -> Self
Borrow<B>
of a value. Read more§fn tap_borrow_mut<B>(self, func: impl FnOnce(&mut B)) -> Self
fn tap_borrow_mut<B>(self, func: impl FnOnce(&mut B)) -> Self
BorrowMut<B>
of a value. Read more§fn tap_ref<R>(self, func: impl FnOnce(&R)) -> Self
fn tap_ref<R>(self, func: impl FnOnce(&R)) -> Self
AsRef<R>
view of a value. Read more§fn tap_ref_mut<R>(self, func: impl FnOnce(&mut R)) -> Self
fn tap_ref_mut<R>(self, func: impl FnOnce(&mut R)) -> Self
AsMut<R>
view of a value. Read more§fn tap_deref<T>(self, func: impl FnOnce(&T)) -> Self
fn tap_deref<T>(self, func: impl FnOnce(&T)) -> Self
Deref::Target
of a value. Read more§fn tap_deref_mut<T>(self, func: impl FnOnce(&mut T)) -> Self
fn tap_deref_mut<T>(self, func: impl FnOnce(&mut T)) -> Self
Deref::Target
of a value. Read more§fn tap_dbg(self, func: impl FnOnce(&Self)) -> Self
fn tap_dbg(self, func: impl FnOnce(&Self)) -> Self
.tap()
only in debug builds, and is erased in release builds.§fn tap_mut_dbg(self, func: impl FnOnce(&mut Self)) -> Self
fn tap_mut_dbg(self, func: impl FnOnce(&mut Self)) -> Self
.tap_mut()
only in debug builds, and is erased in release
builds.§fn tap_borrow_dbg<B>(self, func: impl FnOnce(&B)) -> Self
fn tap_borrow_dbg<B>(self, func: impl FnOnce(&B)) -> Self
.tap_borrow()
only in debug builds, and is erased in release
builds.§fn tap_borrow_mut_dbg<B>(self, func: impl FnOnce(&mut B)) -> Self
fn tap_borrow_mut_dbg<B>(self, func: impl FnOnce(&mut B)) -> Self
.tap_borrow_mut()
only in debug builds, and is erased in release
builds.§fn tap_ref_dbg<R>(self, func: impl FnOnce(&R)) -> Self
fn tap_ref_dbg<R>(self, func: impl FnOnce(&R)) -> Self
.tap_ref()
only in debug builds, and is erased in release
builds.§fn tap_ref_mut_dbg<R>(self, func: impl FnOnce(&mut R)) -> Self
fn tap_ref_mut_dbg<R>(self, func: impl FnOnce(&mut R)) -> Self
.tap_ref_mut()
only in debug builds, and is erased in release
builds.§fn tap_deref_dbg<T>(self, func: impl FnOnce(&T)) -> Self
fn tap_deref_dbg<T>(self, func: impl FnOnce(&T)) -> Self
.tap_deref()
only in debug builds, and is erased in release
builds.