---
id: TIP-1106
title: Expiring Nonce Discriminators
description: Allows the nonce field of an expiring nonce transaction to distinguish otherwise identical transactions.
authors: Alexey Shekhirin (@shekhirin)
status: Draft
related: TIP-1009, TIP-1000, Transactions
protocolVersion: TBD
---

# TIP-1106: Expiring Nonce Discriminators

## Abstract

This TIP allows the `nonce` field of an expiring nonce transaction to contain any `uint64` value,
rather than requiring zero. In expiring nonce mode the field is an opaque discriminator, not a
sequential nonce. Two otherwise identical transactions can therefore choose different values and
produce different signing, transaction, and replay-protection hashes.

## Motivation

[TIP-1009](./tip-1009.md) requires every expiring nonce transaction to set `nonce = 0`. As a result,
two transactions from the same sender with identical calls, validity bounds, fee parameters, and
other signable fields have the same signing payload. This is useful for deduplication, but prevents
an application from intentionally creating distinct instances of the same operation within one
validity window.

Applications can vary another signed field, such as `validBefore`, but doing so changes that
field's actual semantics and may not be possible when transactions are produced concurrently.
Using the existing `nonce` field as an opaque discriminator provides an explicit source of
uniqueness without changing the transaction encoding or adding protocol state.

The alternative is to add a new salt field to the Tempo transaction type. That would require a new
encoding and duplicate functionality already provided by the encoded `nonce` field.

---

# Specification

At the activation protocol version, replace TIP-1009's `nonce == 0` validity requirement with the
following rule:

> When `nonceKey == TEMPO_EXPIRING_NONCE_KEY`, `nonce` MAY be any value in the transaction field's
> existing `uint64` range. The value is an opaque transaction discriminator and has no ordering or
> state-transition semantics.

For an expiring nonce transaction:

1. Validation MUST NOT compare `nonce` with the sender's protocol nonce or a 2D nonce.
2. Execution MUST NOT increment, initialize, read, or write protocol or 2D nonce state as a result
   of the discriminator value.
3. `nonce` MUST remain included in the existing transaction signing payload and transaction
   encoding.
4. The replay-protection identifier MUST continue to commit to the complete signable payload,
   including `nonce`, and to the sender where required by the active protocol version.
5. All other TIP-1009 requirements, including `nonceKey`, validity-window checks, replay checks,
   circular-buffer behavior, and gas charging, remain unchanged.

Consequently, for two valid expiring nonce transactions that differ only in `nonce`, their signing
hashes, signed transaction hashes, and replay-protection identifiers MUST differ. No new state or
storage layout is introduced.

The rule is fork-gated. Before activation, an expiring nonce transaction with `nonce != 0` MUST be
rejected according to TIP-1009. At and after activation, both zero and non-zero values MUST be
accepted.

# Tooling

Transaction builders, RPC helpers, and fillers MUST stop overriding an explicitly supplied
expiring `nonce` with zero after activation. Helpers MAY continue to use zero by default. Helpers
intended to create distinct otherwise identical transactions SHOULD assign distinct `uint64`
values and document whether those values are random, monotonic, or caller-supplied.

RPC estimation and transaction submission MUST apply the fork-gated validation rule. Existing
wire formats and JSON-RPC field types do not change.
