Book: Update durable nonce proposal entry (#7694) (#7770)

automerge
This commit is contained in:
mergify[bot]
2020-01-13 13:39:38 -08:00
committed by Grimes
parent 8745034cec
commit 79d737e760

View File

@ -26,10 +26,7 @@ account data. A transaction is now constructed in the normal way, but with the
following additional requirements: following additional requirements:
1) The durable nonce value is used in the `recent_blockhash` field 1) The durable nonce value is used in the `recent_blockhash` field
2) A `Nonce` instruction is issued (first?) 2) A `NonceAdvance` instruction is the first issued in the transaction
3) The appropriate transaction flag is set, signaling that the usual
hash age check should be skipped and the previous requirements enforced. This
may be unnecessary, see [Runtime Support](#runtime-support) below
### Contract Mechanics ### Contract Mechanics
@ -66,21 +63,43 @@ WithdrawInstruction(to, lamports)
success success
``` ```
A client wishing to use this feature starts by creating a nonce account and A client wishing to use this feature starts by creating a nonce account under
depositing sufficient lamports as to make it rent-exempt. The resultant account the system program. This account will be in the `Uninitialized` state with no
will be in the `Uninitialized` state with no stored hash and thus unusable. stored hash, and thus unusable.
The `Nonce` instruction is used to request that a new nonce be stored for the To initialize a newly created account, a `NonceInitialize` instruction must be
calling account. The first `Nonce` instruction run on a newly created account issued. This instruction takes one parameter, the `Pubkey` of the account's
will drive the account's state to `Initialized`. As such, a `Nonce` instruction [authority](../offline-signing/durable-nonce.md#nonce-authority). Nonce accounts
MUST be issued before the account can be used. must be [rent-exempt](rent.md#two-tiered-rent-regime) to meet the data-persistence
requirements of the feature, and as such, require that sufficient lamports be
deposited before they can be initialized. Upon successful initialization, the
cluster's most recent blockhash is stored along with specified nonce authority
`Pubkey`.
To discard a `NonceAccount`, the client should issue a `Withdraw` instruction The `NonceAdvance` instruction is used to manage the account's stored nonce
which withdraws all lamports, leaving a zero balance and making the account value. It stores the cluster's most recent blockhash in the account's state data,
eligible for deletion. failing if that matches the value already stored there. This check prevents
replaying transactions within the same block.
`Nonce` and `Withdraw` instructions each will only succeed if the stored Due to nonce accounts' [rent-exempt](rent.md#two-tiered-rent-regime) requirement,
blockhash is no longer resident in sysvar.recent_blockhashes. a custom withdraw instruction is used to move funds out of the account.
The `NonceWithdraw` instruction takes a single argument, lamports to withdraw,
and enforces rent-exemption by preventing the account's balance from falling
below the rent-exempt minimum. An exception to this check is if the final balance
would be zero lamports, which makes the account eligible for deletion. This
account closure detail has an additional requirement that the stored nonce value
must not match the cluster's most recent blockhash, as per `NonceAdvance`.
The account's [nonce authority](../offline-signing/durable-nonce.md#nonce-authority)
can be changed using the `NonceAuthorize` instruction. It takes one parameter,
the `Pubkey` of the new authority. Executing this instruction grants full
control over the account and its balance to the new authority.
{% hint style="info" %}
`NonceAdvance`, `NonceWithdraw` and `NonceAuthorize` all require the current
[nonce authority](../offline-signing/durable-nonce.md#nonce-authority) for the
account to sign the transaction.
{% endhint %}
### Runtime Support ### Runtime Support
@ -89,25 +108,11 @@ an extant `recent_blockhash` on the transaction and prevent fee theft via
failed transaction replay, runtime modifications are necessary. failed transaction replay, runtime modifications are necessary.
Any transaction failing the usual `check_hash_age` validation will be tested Any transaction failing the usual `check_hash_age` validation will be tested
for a Durable Transaction Nonce. This specifics of this test are undecided, some for a Durable Transaction Nonce. This is signaled by including a `NonceAdvance`
options: instruction as the first instruction in the transaction.
1) Require that the `Nonce` instruction be the first in the transaction If the runtime determines that a Durable Transaction Nonce is in use, it will
* + No ABI changes take the following additional actions to validate the transaction:
* + Fast and simple
* - Sets a precedent that may lead to incompatible instruction combinations
2) Blind search for a `Nonce` instruction over all instructions in the
transaction
* + No ABI changes
* - Potentially slow
3) [2], but guarded by a transaction flag
* - ABI changes
* - Wire size increase
* + We'll probably end up with some sort of flags eventually anyway
Current prototyping will use [1]. If it is determined that a Durable Transaction
Nonce is in use, the runtime will take the following actions to validate the
transaction:
1) The `NonceAccount` specified in the `Nonce` instruction is loaded. 1) The `NonceAccount` specified in the `Nonce` instruction is loaded.
2) The `NonceState` is deserialized from the `NonceAccount`'s data field and 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.
If all three of the above checks succeed, the transaction is allowed to continue If all three of the above checks succeed, the transaction is allowed to continue
validation. validation.
### Open Questions Since transactions that fail with an `InstructionError` are charged a fee and
changes to their state rolled back, there is an opportunity for fee theft if a
* Should this feature be restricted in the number of uses per transaction? `NonceAdvance` instruction is reverted. A malicious validator could replay the
failed transaction until the stored nonce is successfully advanced. Runtime
changes prevent this behavior. When a durable nonce transaction fails with an
`InstructionError` aside from the `NonceAdvance` instruction, the nonce account
is rolled back to its pre-execution state as usual. Then the runtime advances
its nonce value and the advanced nonce account stored as if it succeeded.