Skip to content
This repository was archived by the owner on Jan 22, 2025. It is now read-only.

Commit 79d737e

Browse files
mergify[bot]solana-grimes
authored andcommitted
Book: Update durable nonce proposal entry (#7694) (#7770)
automerge
1 parent 8745034 commit 79d737e

File tree

1 file changed

+51
-41
lines changed

1 file changed

+51
-41
lines changed

book/src/implemented-proposals/durable-tx-nonces.md

Lines changed: 51 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -26,10 +26,7 @@ account data. A transaction is now constructed in the normal way, but with the
2626
following additional requirements:
2727

2828
1) The durable nonce value is used in the `recent_blockhash` field
29-
2) A `Nonce` instruction is issued (first?)
30-
3) The appropriate transaction flag is set, signaling that the usual
31-
hash age check should be skipped and the previous requirements enforced. This
32-
may be unnecessary, see [Runtime Support](#runtime-support) below
29+
2) A `NonceAdvance` instruction is the first issued in the transaction
3330

3431
### Contract Mechanics
3532

@@ -66,21 +63,43 @@ WithdrawInstruction(to, lamports)
6663
success
6764
```
6865

69-
A client wishing to use this feature starts by creating a nonce account and
70-
depositing sufficient lamports as to make it rent-exempt. The resultant account
71-
will be in the `Uninitialized` state with no stored hash and thus unusable.
72-
73-
The `Nonce` instruction is used to request that a new nonce be stored for the
74-
calling account. The first `Nonce` instruction run on a newly created account
75-
will drive the account's state to `Initialized`. As such, a `Nonce` instruction
76-
MUST be issued before the account can be used.
77-
78-
To discard a `NonceAccount`, the client should issue a `Withdraw` instruction
79-
which withdraws all lamports, leaving a zero balance and making the account
80-
eligible for deletion.
81-
82-
`Nonce` and `Withdraw` instructions each will only succeed if the stored
83-
blockhash is no longer resident in sysvar.recent_blockhashes.
66+
A client wishing to use this feature starts by creating a nonce account under
67+
the system program. This account will be in the `Uninitialized` state with no
68+
stored hash, and thus unusable.
69+
70+
To initialize a newly created account, a `NonceInitialize` instruction must be
71+
issued. This instruction takes one parameter, the `Pubkey` of the account's
72+
[authority](../offline-signing/durable-nonce.md#nonce-authority). Nonce accounts
73+
must be [rent-exempt](rent.md#two-tiered-rent-regime) to meet the data-persistence
74+
requirements of the feature, and as such, require that sufficient lamports be
75+
deposited before they can be initialized. Upon successful initialization, the
76+
cluster's most recent blockhash is stored along with specified nonce authority
77+
`Pubkey`.
78+
79+
The `NonceAdvance` instruction is used to manage the account's stored nonce
80+
value. It stores the cluster's most recent blockhash in the account's state data,
81+
failing if that matches the value already stored there. This check prevents
82+
replaying transactions within the same block.
83+
84+
Due to nonce accounts' [rent-exempt](rent.md#two-tiered-rent-regime) requirement,
85+
a custom withdraw instruction is used to move funds out of the account.
86+
The `NonceWithdraw` instruction takes a single argument, lamports to withdraw,
87+
and enforces rent-exemption by preventing the account's balance from falling
88+
below the rent-exempt minimum. An exception to this check is if the final balance
89+
would be zero lamports, which makes the account eligible for deletion. This
90+
account closure detail has an additional requirement that the stored nonce value
91+
must not match the cluster's most recent blockhash, as per `NonceAdvance`.
92+
93+
The account's [nonce authority](../offline-signing/durable-nonce.md#nonce-authority)
94+
can be changed using the `NonceAuthorize` instruction. It takes one parameter,
95+
the `Pubkey` of the new authority. Executing this instruction grants full
96+
control over the account and its balance to the new authority.
97+
98+
{% hint style="info" %}
99+
`NonceAdvance`, `NonceWithdraw` and `NonceAuthorize` all require the current
100+
[nonce authority](../offline-signing/durable-nonce.md#nonce-authority) for the
101+
account to sign the transaction.
102+
{% endhint %}
84103

85104
### Runtime Support
86105

@@ -89,25 +108,11 @@ an extant `recent_blockhash` on the transaction and prevent fee theft via
89108
failed transaction replay, runtime modifications are necessary.
90109

91110
Any transaction failing the usual `check_hash_age` validation will be tested
92-
for a Durable Transaction Nonce. This specifics of this test are undecided, some
93-
options:
94-
95-
1) Require that the `Nonce` instruction be the first in the transaction
96-
* + No ABI changes
97-
* + Fast and simple
98-
* - Sets a precedent that may lead to incompatible instruction combinations
99-
2) Blind search for a `Nonce` instruction over all instructions in the
100-
transaction
101-
* + No ABI changes
102-
* - Potentially slow
103-
3) [2], but guarded by a transaction flag
104-
* - ABI changes
105-
* - Wire size increase
106-
* + We'll probably end up with some sort of flags eventually anyway
107-
108-
Current prototyping will use [1]. If it is determined that a Durable Transaction
109-
Nonce is in use, the runtime will take the following actions to validate the
110-
transaction:
111+
for a Durable Transaction Nonce. This is signaled by including a `NonceAdvance`
112+
instruction as the first instruction in the transaction.
113+
114+
If the runtime determines that a Durable Transaction Nonce is in use, it will
115+
take the following additional actions to validate the transaction:
111116

112117
1) The `NonceAccount` specified in the `Nonce` instruction is loaded.
113118
2) The `NonceState` is deserialized from the `NonceAccount`'s data field and
@@ -118,6 +123,11 @@ one specified in the transaction's `recent_blockhash` field.
118123
If all three of the above checks succeed, the transaction is allowed to continue
119124
validation.
120125

121-
### Open Questions
122-
123-
* Should this feature be restricted in the number of uses per transaction?
126+
Since transactions that fail with an `InstructionError` are charged a fee and
127+
changes to their state rolled back, there is an opportunity for fee theft if a
128+
`NonceAdvance` instruction is reverted. A malicious validator could replay the
129+
failed transaction until the stored nonce is successfully advanced. Runtime
130+
changes prevent this behavior. When a durable nonce transaction fails with an
131+
`InstructionError` aside from the `NonceAdvance` instruction, the nonce account
132+
is rolled back to its pre-execution state as usual. Then the runtime advances
133+
its nonce value and the advanced nonce account stored as if it succeeded.

0 commit comments

Comments
 (0)