-
Notifications
You must be signed in to change notification settings - Fork 39
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Enable out-of-order transaction processing for asset
table
#77
Conversation
39c630c
to
9299d79
Compare
* This allows out-of-order Bubblegum transactions to create and update the asset table. * Upsert leaf schema, owner, delegate, and seq separately since those are updated by all instructions and gated by sequence number to ensure freshest value. * Mint, burn, and decompress happen without regard to sequence number because they operate on unique fields. * Mint and burn have been updated but Decompress still needs to be fixed to handle out of order transactions. * Also remove unused 'filling' variable.
What's the motivation for this PR? Was anyone observing indexing issues due to out of order transactions? |
@NicolasPennie what I heard from @austbot is that both you (Helius) and Triton had observed issues with out of order transactions and as a result, had to essentially stop running the backfiller and use a different method for in-order filling. I also talked to @austbot and @linuskendall about this and it does in fact look like this reference code could not handle out of order transactions in general. The For example, if a However, using this same example but considering the This PR addresses this issue with the |
Great, thanks for the context! That was really helpful. |
6285923
to
1dfdfd0
Compare
330f7b8
to
103a2ae
Compare
103a2ae
to
634030d
Compare
98b5be0
to
07b6712
Compare
asset
table
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
reviewed on a call with md
@@ -116,10 +106,20 @@ pub enum SpecificationAssetClass { | |||
Print, | |||
#[sea_orm(string_value = "PRINTABLE_NFT")] | |||
PrintableNft, | |||
#[sea_orm(string_value = "PROGRAMMABLE_NFT")] | |||
ProgrammableNft, | |||
#[sea_orm(string_value = "TRANSFER_RESTRICTED_NFT")] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
can remove later
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why is that, because we won't ever use it?
this is LGTM @danenbm |
Thank you. Still testing this and working through some issues with upserting parts of an asset row due to NULL constraints on some of the fields. Putting back to draft until I fix them |
) | ||
.await?; | ||
|
||
upsert_asset_with_seq(txn, id_bytes.to_vec(), seq as i64).await |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this necessary? I think we can just update this within one of the earlier methods. We try to reduce to number of DB calls we need to make in favour of performance. (applies for all cNFT indexing methods).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In a previous iteration of this PR I used the existing seq
to protect leaf
updates, and the new owner_delegate_seq
to protect owner
and delegate
fields. Because of this, an effect of my PR changes is that when the leaf was set to None
during decompression, so was the seq
, and then for decompressed assets, a Read API call to getAsset
would return null
for the seq
.
Maybe that was OK because people don't need the seq
when the asset has been removed from the merkle tree. But the merkle tree is still listed and wanted it to match previous behavior.
Maybe I can change it back if we want to remove an extra update that is only for the seq
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
a Read API call to getAsset would return null for the seq.
This would be acceptable if the asset can never be re-compresssed. But I think you plan on adding that, right? If that's the case, then it makes sense to keep the seq value available after a decompression.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah I think long term we plan to add re-compression. Maybe it would insert back into the same tree like cancel_redeem
does but instead of using a voucher it would burn the token-metadata based NFT. But I could also see it just doing a new append to the tree via mint_v1
.
Either way when it got added back into the tree, I think the asset would get a new seq
that is probably a much higher number that what was previously stored there when it was decompressed. I guess what I'm thinking at the moment is that I'm not sure of the use for the seq
after decompression since you cannot use it for re-compression, right?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For reference the previous version of my PR prior to this commit used seq
to protect leaf and owner_delegate_seq
to protect owner
+delegate
and had one less upsert overall. May be worth revisiting that approach to save on an update/upsert.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I guess what I'm thinking at the moment is that I'm not sure of the use for the seq after decompression since you cannot use it for re-compression, right?
If recompressing will add that NFT back into the tree via the same leaf, then we need to keep the seq number around. Otherwise you can have out of order bugs with out of order decompress + recompress transactions. And we need to be able to always handle any order to be safe, even if its unlikely to happen.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think you uncovered something that will be an issue for decompress
> recompress
with the current design both of this PR and with the system in general. The fact that decompress
doesn't have any association with the tree, means there is no change log event and thus no seq
associated with the decompress
.
For this PR, the way I found to deal with decompress
being out of order with others was to add a boolean was_decompressed
flag, which essentially acts like a 1-bit sequence number, which is a one way door assuming no events after the decompression.
If we add recompress
we need to find another way to deal with decompress
being out of order with other instructions that can provide a seq
from the tree.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@NicolasPennie @danenbm we must keep the seq in the db if the asset is recompressed.
there are other things though, since you cant close the mint acccount you cannot fully recompress. so you can use that as a handle some how.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Leaving code as is to make sure seq
stays updated in asset
table.
However, I still don't think recompression can work out of order, because decompression is not sequenced by the tree. Am I missing something?
Co-authored-by: Nicolas Pennie <[email protected]>
…" (metaplex-foundation#78) This reverts commit bb0a5a0.
Notes
leaf
info based onseq
ORwas_decompressed
flag.owner
anddelegate
based onowner_delegate_seq
.compressed
,compressible
,supply
, andsupply_mint
) based onwas_decompressed
flag.Database changes
owner_delegate_seq
andwas_decompressed
columns to asset table, andPROGRAMMABLE_NFT
tospecification_asset_class
type.PROGRAMMABLE_NFT
tospecification_asset_class
since it is needed by the API code but missing from the SQL code.Other misc. changes
Testing
CreateTree
/Mint
,Transfer
, andBurn
in reverse order. While running in reverse order I observed that could not get info for the asset viagetAsset
untilMint
was indexed.cl_items
andasset
table in database. Covered every indexed instruction (noteMintToCollection
indexes asMint
). Did this process on both main branch and this PR branch and compared all results.CreateTree
/Mint
,Transfer
, andBurn
cl_items
OK,asset
incorrect due to only indexingMint
CreateTree
/Mint
,Redeem
,CancelRedeem
, secondRedeem
, andDecompress
cl_items
andasset
incorrect due toRedeem
not indexingcl_items
incorrect due toRedeem
not indexing,asset
incorrect due to only indexingMint
CreateTree
/Mint
,Transfer
, secondTransfer
cl_items
OK,asset
incorrect due to only indexingMint
CreateTree
/Mint
,Delegate
,Transfer
cl_items
OK,asset
incorrect due to only indexingMint
CreateTree
/Mint
,VerifyCreator
cl_items
OK,asset
incorrect due to only indexingMint
,asset_creators
incorrect due to missingVerifyCreator
cl_items
andasset
OK,asset_creators
incorrect due to missingVerifyCreator
CreateTree
/Mint
,VerifyCollection
cl_items
andasset
OK,asset_grouping
incorrect due to missingVerifyCollection
cl_items
OK,asset
incorrect due to only indexingMint
,asset_grouping
incorrect due to missingVerifyCollection
SetAndVerifyCollection
still needs Blockbuster fix to index.cl_items and asset OK, asset_grouping incorrect due to missing VerifyCollectionSetAndVerifyCollection
still needs Blockbuster fix to index.cl_items and asset OK, asset_grouping incorrect due to missing VerifyCollection