adds feature gate enabling durable nonce

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.
This commit is contained in:
behzad nouri 2022-06-03 13:05:55 -04:00
parent 5ee157f43d
commit 9851774133
2 changed files with 46 additions and 17 deletions

View File

@ -4054,6 +4054,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 {
@ -4061,7 +4068,9 @@ impl Bank {
let recent_blockhash = tx.message().recent_blockhash();
if hash_queue.is_hash_valid_for_age(recent_blockhash, max_age) {
(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 {
error_counters.blockhash_not_found += 1;
@ -4131,19 +4140,16 @@ impl Bank {
})
}
pub fn check_transaction_for_nonce(
fn check_transaction_for_nonce(
&self,
tx: &SanitizedTransaction,
enable_durable_nonce: bool,
) -> Option<TransactionAccount> {
if self.cluster_type() == ClusterType::MainnetBeta {
if self.slot() <= 135986379 {
self.check_message_for_nonce(tx.message())
} else {
None
}
} else {
self.check_message_for_nonce(tx.message())
}
(enable_durable_nonce
|| self.slot() <= 135986379
|| self.cluster_type() != ClusterType::MainnetBeta)
.then(|| self.check_message_for_nonce(tx.message()))
.flatten()
}
pub fn check_transactions(
@ -12447,7 +12453,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))
);
}
@ -12473,7 +12482,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());
}
@ -12499,7 +12511,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());
}
@ -12526,7 +12541,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());
}
@ -12550,7 +12568,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());
}
@ -13222,7 +13243,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
);
}

View File

@ -420,6 +420,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> = [
@ -518,6 +522,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()