You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
What is the best practice when it comes to tracking RAM changes on the ledger? Consider the following situation: we have a smart contract with a series of actions that are manipulating various tables on the on-chain RAM. When a smart contract action manipulates multiple entries on the RAM tables, how do we get that information on the ledger?
Example: A user can have an account, items to trade, and can send and receive trade offers. Consider the following action:
deleteAccount
data: {
id: 7
}
The smart contract takes that action and performs the following logic:
get account with an ID of 7
get all items that belong to that account
get all offers that belong to each of those items
delete offers
delete items
delete account
The ledger, to our understanding, just sees the information passed into the account, which is:
deleteAccount
data: {
id: 7
}
Those watching the blocks (such as applications running demux to track the state of this particular dApp) would be unaware of the other entries that were manipulated on RAM (offers and items).
We are looking for a way to expose any change done to RAM on the ledger so that anybody or anything watching the blocks can derive a state locally if they replay the chain.
We have come up with a few approaches, and were wondering if there’s a best practice and/or a more appropriate way of doing this than presented below.
Approach one
Make an assumption of what will be affected by the smart contract action by looking at your local state and passing that information in the action. The local state would be derived from a demux implementation that’s watching all blocks from the chain and mapping relevant data to our local database.
So by following the example above, before we pass the deleteAccount action to the smart contract, we would first look to our database and gather all of the other entities that will be affected and include them in the payload to the smart contract.
deleteAccount
data: {
id: 7,
items: [10, 13, 44, 233, 321],
offers: [32, 108, 2332, 2433]
}
Then the logic would be as follows:
get account with an ID of 7
get all items that belong to that account
verify items retrieved equal 10, 13, 44, 233, 321
get all offers that belong to each of those items
verify the offers retrieved equal 32, 108, 2332, 2433
delete offers
delete items
delete account
If either of the verification steps fail, the action would be kicked back as invalid. But if all succeeds, then data that flows through to the ledger would fully instruct a demux implementation of how to update a local database’s state.
Approach two
The seconds approach would follow the same philosophy of packaging all information in action’s payload that will be affected by the smart contract, but instead of retrieving the information from the local database, it retrieves that information from the chain's database through an API node.
So the payload below would reach out the API node and request all items that belong to account 7. Simultaneously it would request all offers that belong to each item retrieved. Then it would include that freshly-retrieved information in the payload and pass it to the smart contract, which would follow the same logic of verifying the state is in-sync before processing.
deleteAccount
data: {
id: 7,
items: [10, 13, 44, 233, 321],
offers: [32, 108, 2332, 2433]
}
Questions
The only difference between these two approaches is the way they each get the ancillary data before passing it into the smart contract. Our questions are:
Is this design philosophy the most effective way to make the changes to RAM transparent on the ledger?
Which approach would be quicker while keeping in mind the necessity for accuracy: using our local database or using an API node?
Is there no way to include additional data with an action as it hits the ledger, such as response{...} or result{...}?
The text was updated successfully, but these errors were encountered:
There are some changes coming that will make this process obsolete, but as of right now, you need to re-implement contract state-changing logic in your Updaters so that your database can track the values in parallel. In other words, you need to track all actions that may affect the RAM state value of terms, offers, accounts, etcetera, so that when you get your deleteAccount action, you can properly update these values, too.
The only thing different from your second option and what I would recommend is, instead of modifying the payload of the deleteAccount action with the additional fields, simply retrieve the database values you need in the deleteAccount Updater function.
Soon, we'll be able to track state within Demux natively, which means that the state updates will simply come in as "virtual" actions (an action that may be processed by its corresponding updater).
I'm going to close this and re-open an issue related to capturing blockchain state, but feel free to continue the conversation here / ask any followup questions.
Summarizing the Problem
What is the best practice when it comes to tracking RAM changes on the ledger? Consider the following situation: we have a smart contract with a series of actions that are manipulating various tables on the on-chain RAM. When a smart contract action manipulates multiple entries on the RAM tables, how do we get that information on the ledger?
Example: A user can have an account, items to trade, and can send and receive trade offers. Consider the following action:
deleteAccount
data: {
id: 7
}
The smart contract takes that action and performs the following logic:
get account with an ID of 7
get all items that belong to that account
get all offers that belong to each of those items
delete offers
delete items
delete account
The ledger, to our understanding, just sees the information passed into the account, which is:
deleteAccount
data: {
id: 7
}
Those watching the blocks (such as applications running demux to track the state of this particular dApp) would be unaware of the other entries that were manipulated on RAM (offers and items).
We are looking for a way to expose any change done to RAM on the ledger so that anybody or anything watching the blocks can derive a state locally if they replay the chain.
We have come up with a few approaches, and were wondering if there’s a best practice and/or a more appropriate way of doing this than presented below.
Approach one
Make an assumption of what will be affected by the smart contract action by looking at your local state and passing that information in the action. The local state would be derived from a demux implementation that’s watching all blocks from the chain and mapping relevant data to our local database.
So by following the example above, before we pass the deleteAccount action to the smart contract, we would first look to our database and gather all of the other entities that will be affected and include them in the payload to the smart contract.
deleteAccount
data: {
id: 7,
items: [10, 13, 44, 233, 321],
offers: [32, 108, 2332, 2433]
}
Then the logic would be as follows:
get account with an ID of 7
get all items that belong to that account
verify items retrieved equal 10, 13, 44, 233, 321
get all offers that belong to each of those items
verify the offers retrieved equal 32, 108, 2332, 2433
delete offers
delete items
delete account
If either of the verification steps fail, the action would be kicked back as invalid. But if all succeeds, then data that flows through to the ledger would fully instruct a demux implementation of how to update a local database’s state.
Approach two
The seconds approach would follow the same philosophy of packaging all information in action’s payload that will be affected by the smart contract, but instead of retrieving the information from the local database, it retrieves that information from the chain's database through an API node.
So the payload below would reach out the API node and request all items that belong to account 7. Simultaneously it would request all offers that belong to each item retrieved. Then it would include that freshly-retrieved information in the payload and pass it to the smart contract, which would follow the same logic of verifying the state is in-sync before processing.
deleteAccount
data: {
id: 7,
items: [10, 13, 44, 233, 321],
offers: [32, 108, 2332, 2433]
}
Questions
The only difference between these two approaches is the way they each get the ancillary data before passing it into the smart contract. Our questions are:
Is this design philosophy the most effective way to make the changes to RAM transparent on the ledger?
Which approach would be quicker while keeping in mind the necessity for accuracy: using our local database or using an API node?
Is there no way to include additional data with an action as it hits the ledger, such as response{...} or result{...}?
The text was updated successfully, but these errors were encountered: