SIMD#83 - Allow conflicting entries in the account locking function#1624
SIMD#83 - Allow conflicting entries in the account locking function#1624Huzaifa696 wants to merge 20 commits intoanza-xyz:masterfrom
Conversation
apfitzge
left a comment
There was a problem hiding this comment.
Some initial comments on code (not tests); Also please remove the "fixes" from the PR description, since this will not close all items in the issue
| loop { | ||
| // try to lock the accounts | ||
| let batch = bank.prepare_sanitized_batch(transactions); | ||
| let (batch, _self_conflicting_batch) = |
There was a problem hiding this comment.
just want to clarify, there will be a follow-up PR with adjustments in this replay scheduler in order to use the fact its' a self-conflicting entry.
As PR currently stands it doesn't seem to satisfy the 2nd item of #1025
There was a problem hiding this comment.
yes, you are right, the PR that handles the conflicting entries on replay side is also in progress.
| writable_keys: Vec<&Pubkey>, | ||
| readonly_keys: Vec<&Pubkey>, | ||
| ) -> Result<()> { | ||
| entry_accts_lookup: &mut EntryAcctLocks, |
There was a problem hiding this comment.
nit: variable name and type isn't consistent. how about entry_account_locks?
There was a problem hiding this comment.
imo, better as batch_account_locks. Entry is a concept at a higher level (PoH) and really shouldn't be making its' way down here.
We have a batch of transactions, they may be from and entry if this is on block-verification, or they may have chance to become an entry if this is block-production.
| pub type PubkeyAccountSlot = (Pubkey, AccountSharedData, Slot); | ||
|
|
||
| #[derive(Debug, Default)] | ||
| struct EntryAcctLocks { |
There was a problem hiding this comment.
nit: i prefer EntryAccountLocks, considering this is a close kin to already existing AccountLocks.
There was a problem hiding this comment.
I think BatchAccountLocks is better, see https://github.com/anza-xyz/agave/pull/1624/files#r1651280535
| debug!("Writable account in use: {:?}", k); | ||
| return (Err(TransactionError::AccountInUse), self_conflicting_tx); | ||
| } else { | ||
| self_conflicting_tx = true; |
There was a problem hiding this comment.
self_conflicting_tx can be set to true if entry_accts_lookup.writables.contains(k) == false and entry_accts_lookup.readables.contains(k) == false for 2nd batch, which is conflicting with the first batch.
is that semantically correct?
There was a problem hiding this comment.
no, you are right, this is not semantically correct.
although, self_conflicting_tx will have no effect if the batch locking fails on the replay side in process_entries (which is part of the next PR).
To be clearer, I will return false for every error condition Err(TransactionError::AccountInUse)
| } | ||
| } | ||
| } | ||
|
|
There was a problem hiding this comment.
below in AccountLocks, I'm considering we may want to have write_locks also track the number of outstanding write-locks, even if all must be in same batch.
It makes it so that the sanity checks we do when unlocking batches not broken by the new functionality.
|
Incorporated the above points except the pre-allocation point in [2f4f969], please review. Note: I also ran |
|
Looking at changes.
Please also run clippy; it's one of the first thing CI is going to do - so not worth blocking the queue up if we know it will fail on clippy. |
| batch_account_locks: &mut BatchAccountLocks, | ||
| allow_self_conflicting_entries: bool, | ||
| ) -> (Result<()>, bool) { | ||
| let mut self_conflicting_tx = false; |
There was a problem hiding this comment.
nit: this indiciates a self-conflicting batch. tx still cannot have duplicate keys so can't conflict with itself.
| ) -> TransactionBatch<'a, 'b> { | ||
| // this lock_results could be: Ok, AccountInUse, WouldExceedBlockMaxLimit or WouldExceedAccountMaxLimit | ||
| let tx_account_lock_limit = self.get_transaction_account_lock_limit(); | ||
| let feature_set: Arc<FeatureSet> = self.feature_set.clone(); |
There was a problem hiding this comment.
do not clone here, see other comment.
|
Incorporated the latest review points [7cfde0b]. Please review. My standard practice is to run these checks before pushing:
|
|
With this sort of change, to something that is critical to Solana's block-verfication, we always need to take some care that we are not making the performance worse. Command: @70089cce5119c9afaeb2986e2ecaa6d4505ec15d (where this branches off): @7cfde0b44fdfa08b18dbc8368a947f9d4285001f (this PR w/ current state): Times not significantly worse, within uncertainty bounds. However, the uncertainty seems to be increased across the board - my instinct is that this is due to use performing additional allocations for the new hashsets. If I make the change to use potentially worth a more targetted bench to benchmark just the locking here. |
557dd6b to
7aeab68
Compare
7aeab68 to
053635a
Compare
|
Rebased again to incorporate the latest API modifications in |
|
added low level tests for |
e29f2bc to
be2ba84
Compare
add conflicting accounts lock test
- changed name of entry level locks lookup table - write locks also track the num of outstanding locks - simplied lock_account function flow - formatted code with cargo fmt - cleared some nits
- added comments for clarity - changed mis-leading variable name
- used thread local var - fixed clippy error
This reverts commit 41fcaa9.
- adapted lock account functions according to new API - fixed unit tests
be2ba84 to
8d42a61
Compare
Problem
Under the old assumption that all entries are disjoint (i.e do not contain conflicting txs), the account lock function do not allow acquiring locks for conflicting txs in the same entry. This assumption is now changed with SIMD#83.
Summary of Changes
Changes to enable account locking of self-conflicting entries:
Related to:
#1025