6

If we want those witnessing the chain to know about our apps state without any knowledge of our service layer, what might be the best approach? Since the ledger only records the data given to it in an action, any changes done by the smart contract wouldn’t be known to the ledger unless that data was front-loaded into the action.

An example is a buy/sell auction app like eBay. A user can have an account, items to sell, and other people can bid on items. Imagine all of that data is being stored in on-chain RAM. If you had an action to delete an account, you only need minimal information for the smart contract to do what you need it to:

action: deleteAccount
data: {
            id: 7
}

The smart contract takes that action and performs the following logic:

  1. get account with an ID of 7
  2. get all items that belong to that account
  3. get all bids that belong to each of those items
  4. delete bids
  5. delete items
  6. delete account

The ledger, however, just sees the information passed into the action, which is an id of 7. Those watching the blocks (such as applications running demux to track the state of this particular app) would be unaware of the other entries that were manipulated on RAM (bids 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. It would be much easier if we could transform the action data derived from the smart contract’s methods or inject data into the action that the smart contract modifies, but that doesn't seem possible (unless I'm missing something?).

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.

action: deleteAccount
data: {
            id: 7,
            items: [10, 13, 44, 233, 321],
            bids: [32, 108, 2332, 2433]
}

Then the logic would be as follows:

  1. get account with an ID of 7
  2. get all items that belong to that account
  3. verify items retrieved equal 10, 13, 44, 233, 321
  4. get all bids that belong to each of those items
  5. verify the bids retrieved equal 32, 108, 2332, 2433
  6. delete bids
  7. delete items
  8. delete account

If either of the verification steps fail, the action would be kicked back as invalid. But if all succeeds, then the data that flows through to the ledger would fully instruct a demux implementation of how to update a local database’s state. This method of front-loading the data in the action itself ensures that ledger witnesses know the state of the app.

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 to get the same payload shown in approach one, we would reach out an API node and request all items that belong to account 7. Simultaneously it would request all bids 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.

Few issues with this approach: the calls to an API node could take too long or the querying capability on the API nodes may not be powerful enough to get the necessary information. But it is getting data directly from horse's mouth, so-to-speak, so it's not depending on any local iteration of the data.

Questions

  1. Is this design philosophy the most effective way to make the changes to RAM transparent on the ledger?
    • If so, which approach would be quicker while keeping in mind the necessity for accuracy: using our local database or using an API node?
  2. Is there no way to include additional data with an action as it hits the ledger, such as response{...} or result{...}?
1

Your question is how you can more easily allow external parties to verify your application's state.

If your project is open source, I could mimic your demux setup and query the chain to see what you're seeing. This makes your idea of pulling/adding additional information within the transaction less useful. I could also query the chain for your contract and build the database myself without knowing your demux setup. This takes more work, but you seemed to leave that possibility out, so I want to reiterate that it is there.

In your case, I would use demux in your application to track all transaction metadata as it pertains to a user. For example, you could look up a user on your site and see their bid history. Each bid would have the transaction ID where the bid took place. That transaction ID could hyperlink to a third party browser to prove the transaction took place.

This could provide a better auditing experience and would be open to a wider and less tech savvy audience.


  1. Is this design philosophy the most effective way to make the changes to RAM transparent on the ledger?

    • If so, which approach would be quicker while keeping in mind the necessity for accuracy: using our local database or using an API node?

If you still felt inclined to include all of the users metadata in each transaction then I would pull that from your local chain/local database. It may be worth looking into how that will affect your EOS resource consumption.

  1. Is there no way to include additional data with an action as it hits the ledger, such as response{...} or result{...}?

Not sure.


Feel free to contact block one as well: developers@block.one

Your Answer

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Not the answer you're looking for? Browse other questions tagged or ask your own question.