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
Java specifics
- The field is a nullable
Long, never a long with 0 as a sentinel: zero is a legal instant in $\mathbb{T}$.
- The accessor is
Optional<Long> getExpiresAt(), matching Optional<byte[]> getData() on the same interface.
-
MintTransaction.create had grown to 18 overloads. Replace the set with MintTransaction.builder(networkId, recipient), naming the optional arguments.
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.Java specifics
Long, never alongwith0as a sentinel: zero is a legal instant inOptional<Long> getExpiresAt(), matchingOptional<byte[]> getData()on the same interface.MintTransaction.createhad grown to 18 overloads. Replace the set withMintTransaction.builder(networkId, recipient), naming the optional arguments.Companion issues
aggregator-gorugregatorbft-core(branchl1)state-transition-sdk-jsstate-transition-sdk-javastate-transition-sdk-rust