pub struct DownloadReceipt { /* private fields */ }Expand description
One durable record of a served-and-paid blob (issue #248).
The on-disk shape. The paid-delivery path captures a RawReceipt at the
voucher-acceptance point and the background writer renders it into this
value (RawReceipt::render, #1792 item 2), so every receipt still
corresponds to a cumulative payment the node verified and committed — the
rendering just happens off the hot path. All identifier fields are lower-hex
strings (no 0x prefix) so the log is self-describing and greppable without
a schema:
hash— BLAKE3 content hash of the delivered blob (raw 32 bytes, hex).client_node_id— irohNodeId(ed25519 public key) of the paying peer (raw 32 bytes, hex).voucher_amount— the accepted voucher’s cumulative amount (its sole ordering key; there is no nonce), as a decimal string. A decimaluint256(not hex) so an auditor reads the same value the on-chainPaymentPooland operator dashboards show; it is reconstructed from the 32-byte big-endian wire amount.
size is the byte count covered by this payment proof (the newly
delivered, now-paid bytes), and timestamp_secs is the node’s wall-clock
Unix time (seconds) read where the receipt is rendered — the background
writer stamps it as it dequeues, which lags the acceptance point only by the
queue-drain latency (#1792 item 2).
§Invariants
The fields are private and the only public constructor is new, which
renders the hex and decimal-uint256 strings from typed inputs. This makes
the invariants type-owned: a receipt cannot be built field-wise, and serde’s
derived Deserialize cannot synthesize one with a malformed hash /
client_node_id / voucher_amount from outside the crate (the fields stay
private to readers). Accessor methods expose the rendered values read-only.
Field-wise construction from outside the crate does not compile (the fields
are private), so the validating new is the only public path in:
use decdn_node::receipt_log::DownloadReceipt;
// ERROR: fields `hash`, `size`, ... are private — invariant cannot be bypassed.
let _ = DownloadReceipt {
hash: "not-a-hash".to_string(),
size: 1,
client_node_id: "nope".to_string(),
voucher_amount: "0xdeadbeef".to_string(),
timestamp: 0,
};Implementations§
Source§impl DownloadReceipt
impl DownloadReceipt
Sourcepub fn new(
hash: &Hash,
size: u64,
client_node_id_bytes: &[u8; 32],
voucher_amount: U256,
timestamp_secs: u64,
) -> Self
pub fn new( hash: &Hash, size: u64, client_node_id_bytes: &[u8; 32], voucher_amount: U256, timestamp_secs: u64, ) -> Self
Build a receipt from the typed delivery-path values, rendering every invariant inside the constructor:
hashis theiroh_blobs::Hashof the delivered blob — a distinct type fromclient_node_id_bytes, so the two 32-byte identifiers cannot be transposed at a call site. Rendered to lower-hex (no0x).client_node_id_bytesis the raw 32-byte iroh node id, lower-hex.voucher_amountis the accepted voucher’s cumulativeuint256amount; the decimal string is rendered here so the “decimal uint256” invariant is owned by the type, not the caller.
Sourcepub fn hash(&self) -> &str
pub fn hash(&self) -> &str
BLAKE3 content hash of the delivered blob, lower-hex (64 chars, no 0x).
Sourcepub fn client_node_id(&self) -> &str
pub fn client_node_id(&self) -> &str
iroh NodeId of the paying client, lower-hex (64 chars, no 0x).
Sourcepub fn voucher_amount(&self) -> &str
pub fn voucher_amount(&self) -> &str
Accepted voucher cumulative amount, decimal uint256 string.
Sourcepub const fn timestamp_secs(&self) -> u64
pub const fn timestamp_secs(&self) -> u64
Node wall-clock Unix time (seconds) at voucher acceptance.
Trait Implementations§
Source§impl Clone for DownloadReceipt
impl Clone for DownloadReceipt
Source§impl Debug for DownloadReceipt
impl Debug for DownloadReceipt
Source§impl<'de> Deserialize<'de> for DownloadReceipt
impl<'de> Deserialize<'de> for DownloadReceipt
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 DownloadReceipt
Source§impl PartialEq for DownloadReceipt
impl PartialEq for DownloadReceipt
Source§impl Serialize for DownloadReceipt
impl Serialize for DownloadReceipt
impl StructuralPartialEq for DownloadReceipt
Auto Trait Implementations§
impl Freeze for DownloadReceipt
impl RefUnwindSafe for DownloadReceipt
impl Send for DownloadReceipt
impl Sync for DownloadReceipt
impl Unpin for DownloadReceipt
impl UnsafeUnpin for DownloadReceipt
impl UnwindSafe for DownloadReceipt
Blanket Implementations§
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<'de, T> BorrowedRpcObject<'de> for T
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> DeserializeOwned for Twhere
T: for<'de> Deserialize<'de>,
Source§impl<Q, K> Equivalent<K> for Q
impl<Q, K> Equivalent<K> for Q
Source§fn equivalent(&self, key: &K) -> bool
fn equivalent(&self, key: &K) -> bool
key and return true if they are equal.Source§impl<Q, K> Equivalent<K> for Q
impl<Q, K> Equivalent<K> for Q
Source§impl<T> FutureExt for T
impl<T> FutureExt for T
Source§fn with_context(self, otel_cx: Context) -> WithContext<Self> ⓘ
fn with_context(self, otel_cx: Context) -> WithContext<Self> ⓘ
Source§fn with_current_context(self) -> WithContext<Self> ⓘ
fn with_current_context(self) -> WithContext<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 moreSource§impl<T> IntoRequest<T> for T
impl<T> IntoRequest<T> for T
Source§fn into_request(self) -> Request<T>
fn into_request(self) -> Request<T>
T in a tonic::Request