Skip to content

Commit

Permalink
adds feature gate enabling durable nonce
Browse files Browse the repository at this point in the history
Previous commit separates durable nonce and blockhash domains with a
feature gate. A 2nd feature added in this commit enables durable nonce
at least one epoch after the 1st feature.
By the time 2nd feature is activated, some nonce accounts will have an
old blockhash, but no nonce account can have a recent blockhash.
As a result no transaction (durable or normal) can be executed twice.

(cherry picked from commit 9851774)

# Conflicts:
#	runtime/src/bank.rs
  • Loading branch information
behzadnouri authored and mergify[bot] committed Jun 4, 2022
1 parent 1d042d3 commit 304d480
Show file tree
Hide file tree
Showing 2 changed files with 50 additions and 8 deletions.
53 changes: 45 additions & 8 deletions runtime/src/bank.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3672,6 +3672,13 @@ impl Bank {
max_age: usize,
error_counters: &mut TransactionErrorMetrics,
) -> Vec<TransactionCheckResult> {
let separate_nonce_from_blockhash = self
.feature_set
.is_active(&feature_set::separate_nonce_from_blockhash::id());
let enable_durable_nonce = separate_nonce_from_blockhash
&& self
.feature_set
.is_active(&feature_set::enable_durable_nonce::id());
let hash_queue = self.blockhash_queue.read().unwrap();
txs.zip(lock_results)
.map(|(tx, lock_res)| match lock_res {
Expand All @@ -3680,7 +3687,9 @@ impl Bank {
let hash_age = hash_queue.check_hash_age(recent_blockhash, max_age);
if hash_age == Some(true) {
(Ok(()), None)
} else if let Some((address, account)) = self.check_transaction_for_nonce(tx) {
} else if let Some((address, account)) =
self.check_transaction_for_nonce(tx, enable_durable_nonce)
{
(Ok(()), Some(NoncePartial::new(address, account)))
} else if hash_age == Some(false) {
error_counters.blockhash_too_old += 1;
Expand Down Expand Up @@ -3752,9 +3761,10 @@ impl Bank {
})
}

pub fn check_transaction_for_nonce(
fn check_transaction_for_nonce(
&self,
tx: &SanitizedTransaction,
<<<<<<< HEAD
) -> Option<(Pubkey, AccountSharedData)> {
if self.cluster_type() == ClusterType::MainnetBeta {
if self.slot() <= 135986379 {
Expand All @@ -3765,6 +3775,15 @@ impl Bank {
} else {
self.check_message_for_nonce(tx.message())
}
=======
enable_durable_nonce: bool,
) -> Option<TransactionAccount> {
(enable_durable_nonce
|| self.slot() <= 135986379
|| self.cluster_type() != ClusterType::MainnetBeta)
.then(|| self.check_message_for_nonce(tx.message()))
.flatten()
>>>>>>> 985177413 (adds feature gate enabling durable nonce)
}

pub fn check_transactions(
Expand Down Expand Up @@ -11712,7 +11731,10 @@ pub(crate) mod tests {
);
let nonce_account = bank.get_account(&nonce_pubkey).unwrap();
assert_eq!(
bank.check_transaction_for_nonce(&SanitizedTransaction::from_transaction_for_tests(tx)),
bank.check_transaction_for_nonce(
&SanitizedTransaction::from_transaction_for_tests(tx),
true, // enable_durable_nonce
),
Some((nonce_pubkey, nonce_account))
);
}
Expand All @@ -11738,7 +11760,10 @@ pub(crate) mod tests {
nonce_hash,
);
assert!(bank
.check_transaction_for_nonce(&SanitizedTransaction::from_transaction_for_tests(tx,))
.check_transaction_for_nonce(
&SanitizedTransaction::from_transaction_for_tests(tx,),
true, // enable_durable_nonce
)
.is_none());
}

Expand All @@ -11764,7 +11789,10 @@ pub(crate) mod tests {
);
tx.message.instructions[0].accounts.clear();
assert!(bank
.check_transaction_for_nonce(&SanitizedTransaction::from_transaction_for_tests(tx))
.check_transaction_for_nonce(
&SanitizedTransaction::from_transaction_for_tests(tx),
true, // enable_durable_nonce
)
.is_none());
}

Expand All @@ -11791,7 +11819,10 @@ pub(crate) mod tests {
nonce_hash,
);
assert!(bank
.check_transaction_for_nonce(&SanitizedTransaction::from_transaction_for_tests(tx))
.check_transaction_for_nonce(
&SanitizedTransaction::from_transaction_for_tests(tx),
true, // enable_durable_nonce
)
.is_none());
}

Expand All @@ -11815,7 +11846,10 @@ pub(crate) mod tests {
Hash::default(),
);
assert!(bank
.check_transaction_for_nonce(&SanitizedTransaction::from_transaction_for_tests(tx))
.check_transaction_for_nonce(
&SanitizedTransaction::from_transaction_for_tests(tx),
true, // enable_durable_nonce
)
.is_none());
}

Expand Down Expand Up @@ -12487,7 +12521,10 @@ pub(crate) mod tests {
Err(TransactionError::BlockhashNotFound)
);
assert_eq!(
bank.check_transaction_for_nonce(&SanitizedTransaction::from_transaction_for_tests(tx)),
bank.check_transaction_for_nonce(
&SanitizedTransaction::from_transaction_for_tests(tx),
true, // enable_durable_nonce
),
None
);
}
Expand Down
5 changes: 5 additions & 0 deletions sdk/src/feature_set.rs
Original file line number Diff line number Diff line change
Expand Up @@ -327,6 +327,10 @@ pub mod separate_nonce_from_blockhash {
solana_sdk::declare_id!("Gea3ZkK2N4pHuVZVxWcnAtS6UEDdyumdYt4pFcKjA3ar");
}

pub mod enable_durable_nonce {
solana_sdk::declare_id!("4EJQtF2pkRyawwcTVfQutzq4Sa5hRhibF6QAK1QXhtEX");
}

lazy_static! {
/// Map of feature identifiers to user-visible description
pub static ref FEATURE_NAMES: HashMap<Pubkey, &'static str> = [
Expand Down Expand Up @@ -403,6 +407,7 @@ lazy_static! {
(add_shred_type_to_shred_seed::id(), "add shred-type to shred seed #25556"),
(warp_timestamp_with_a_vengeance::id(), "warp timestamp again, adjust bounding to 150% slow #25666"),
(separate_nonce_from_blockhash::id(), "separate durable nonce and blockhash domains #25744"),
(enable_durable_nonce::id(), "enable durable nonce #25744"),
/*************** ADD NEW FEATURES HERE ***************/
]
.iter()
Expand Down

0 comments on commit 304d480

Please sign in to comment.