Make account creation silently skip creating an account that already exists where necessary - #85
Make account creation silently skip creating an account that already exists where necessary#85fedgiac wants to merge 11 commits into
Conversation
| /// Here we assume that we will never create an account for the same seeds | ||
| /// but for a different owner. If the caller does, then the function | ||
| /// still tries to create the account, which then reverts with the system | ||
| /// program's `AccountAlreadyInUse` because the account already exists. |
There was a problem hiding this comment.
this comment sent me into a bit of confusion with how this would work for CreateBuffer accounts, as those accounts are owned by the token program even though they are created by the settlement program. Eventually I realized its because the settlement program sets the owner on creation and at no point is the ownership set to the settlement even though it initialized it.
What I am actually still confused by though is why the strategy for seeing if an account is created or not is by checking the owner, and not by, ex. is_data_empty or even owner, which returns the owner directly so we can see if it is address 0 instead of having to expect it to be the specified owner. I think the reasoning should probably be documented in the code somewhere here.
There was a problem hiding this comment.
Done, does this clarify the motivation? e489ee1
To be fair, it wouldn't be unreasonable to check whether it's initialized or not instead.
Also note that there's no meaningful is_allocated function.
There was a problem hiding this comment.
// ...We confirm the owner is the same, rather than checking that it isn't
// the system owner, to make sure we don't try to reuse the same address
// if the owner is a different parameter (execution continues and
// eventually reverts).
I don't think this explains why not use the straight owner() function to see if it returns address(0) (or the solana equivalent) or not. Seems like that would be a more reliable way to check if the program is initialized or not, right?
…her account was created
kaze-cow
left a comment
There was a problem hiding this comment.
one comment, otherwise looks ok 👍
Closes #37.
Introduce idempotent PDA creation so two parties racing to create the same canonical account don't step on each other's toes, especially when multiple PDAs are created in the same transaction. This happens during an auction when solvers concurrently create the same token buffer, or the same partially-fillable order from a signature.
With these changes, the loser of the race succeeds as a no-op instead of reverting with the system program's
AccountAlreadyInUse.All three creation sites that went through
CanonicalPda::createnow split into two methods over the same allocation:create_idempotent: this is for buffer creation.create_new: this is for order and state PDA creation.(Note: creating orders from a user signature should use
create_idempotent. But right now only a user signature can create an order, and it's better if the user sees an error when trying to recreate a new order again.)How to test
New/updated tests in CI.