Background
An application may specify an exclusive Unicity Service request deadline. It is optional, because transaction construction must not require access to a reliable system clock.
This is a greenfield protocol with no mainnet, so the deadline does not need a separate compatibility encoding. It occupies a fixed position in one wire shape and is written as the CBOR simple value null when the application does not supply one, which is how the other optional fields in these same arrays are already encoded. appendix-encoding.tex states this as the general rule for optional tuple elements.
This issue concerns request-deadline API and encoding only. Mandatory leaf reference-time commitment is specified separately.
Wire format
One version and one element count per structure:
MintTransaction [2, networkId, recipient, salt, tokenType, justification, data, expiresAt]
TransferTransaction [2, recipient, stateMask, data, expiresAt]
CertificationData [2, lockScript, sourceStateHash, transactionHash, expiresAt, witness]
expiresAt : uint | null
expiresAt is part of the transaction hash preimage in both cases, so
txhash = SHA-256(CBOR([…, expiresAt]))
is total and needs no case split, and changing the value changes txhash and invalidates the witness. A service-assigned deadline is not inserted into the transaction or the certification data.
Naming
The field is named expiresAt (expires_at in Rust, ExpiresAt in Go). The value is an absolute exclusive instant in Unix seconds, not a duration, and these SDKs already use "timeout" for transport and polling deadlines.
Scope in this SDK
- One accepted version and one element count per structure, both checked once.
- Represent an omitted deadline as
null and encode it in its fixed position.
- Include
expiresAt in transaction hashing and certification data unconditionally.
- Enforce
tau < expiresAt during verification only when a deadline is present. When it is absent, the service-assigned deadline is not recorded, not signed, and not re-checked by a verifier; that is inherent to not having a clock, not a regression.
- Default mint, transfer and split flows must read no system clock.
- Replace the positional-overload factories with the language's idiom for optional arguments.
- Keep certified transaction and proof reference-time behavior aligned with the leaf reference-time issue; an omitted deadline must not change that separate protocol invariant.
Acceptance criteria
Rust specifics
- Take
Option<u64> as a plain trailing parameter. Rust has no overloading and no default arguments, and Option is how it spells optional.
- Delete the
*_with_timeout twins (create_with_timeout, new_with_timeout, mint_with_timeout, transfer_with_timeout, split_with_timeout, split_unchecked_with_timeout) and the mint_impl/transfer_impl bodies that existed only to hold the shared code.
Companion issues
Background
An application may specify an exclusive Unicity Service request deadline. It is optional, because transaction construction must not require access to a reliable system clock.
This is a greenfield protocol with no mainnet, so the deadline does not need a separate compatibility encoding. It occupies a fixed position in one wire shape and is written as the CBOR simple value
nullwhen the application does not supply one, which is how the other optional fields in these same arrays are already encoded.appendix-encoding.texstates this as the general rule for optional tuple elements.This issue concerns request-deadline API and encoding only. Mandatory leaf reference-time commitment is specified separately.
Wire format
One version and one element count per structure:
expiresAtis part of the transaction hash preimage in both cases, sois total and needs no case split, and changing the value changes
txhashand invalidates the witness. A service-assigned deadline is not inserted into the transaction or the certification data.Naming
The field is named
expiresAt(expires_atin Rust,ExpiresAtin Go). The value is an absolute exclusive instant in Unix seconds, not a duration, and these SDKs already use "timeout" for transport and polling deadlines.Scope in this SDK
nulland encode it in its fixed position.expiresAtin transaction hashing and certification data unconditionally.tau < expiresAtduring verification only when a deadline is present. When it is absent, the service-assigned deadline is not recorded, not signed, and not re-checked by a verifier; that is inherent to not having a clock, not a regression.Acceptance criteria
expiresAtchangestxhashand invalidates the existing witness.Rust specifics
Option<u64>as a plain trailing parameter. Rust has no overloading and no default arguments, andOptionis how it spells optional.*_with_timeouttwins (create_with_timeout,new_with_timeout,mint_with_timeout,transfer_with_timeout,split_with_timeout,split_unchecked_with_timeout) and themint_impl/transfer_implbodies that existed only to hold the shared code.Companion issues
aggregator-gorugregatorbft-core(branchl1)state-transition-sdk-jsstate-transition-sdk-javastate-transition-sdk-rust