-
Notifications
You must be signed in to change notification settings - Fork 21
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
BM-476: Callbacks #335
BM-476: Callbacks #335
Conversation
willpote
commented
Feb 21, 2025
- Callbacks are only ever executed once, the first time a request is fulfilled
- Add a Callback interface and base contract for apps.
- In the non-locked path, callbacks are stored along with the price, when the request is "priced"
…-unaggregated-proofs
…-unaggregated-proofs
…-unaggregated-proofs
…-unaggregated-proofs
…-unaggregated-proofs
…-unaggregated-proofs
…-unaggregated-proofs
Is this not a problem with the image that the callback implementer has chosen to use? If it is possible for the image to generate a journal that leads to tokens being transferred to the wrong person, then the image is the problem? One thing this did make me think of is, would make sense to pass in the Predicate also used for the journal into the callback? Then even for more general purpose images, the callback can verify the journal meets some requirements? [I guess this would require us making the assessor output the predicate] Re: the two mitigations, I don't fully see how they help. Even with a proxy, or fetching the journal from storage, ultimately there is a contract that needs to read the journal and decide what to do as a result of it- and if the journal can be manipulated, that contract will do the wrong thing. |
Another thought, it probably makes sense for the callback template to have some functionality built into it around checking the image id is as expected, as that does feel important. Will add something |
My description of the potential issue is not super clear, but the issue I was thinking of would require an coincidental collision in the value of the 4 byte selector, and sender-based authentication, as well as meeting other constraints on how it interprets the received data. It is unlikely that this will ever be the case. |
…r-delivering-unaggregated-proofs' into willpote/callbacks-2
This reverts commit 749a449.
🚀 Documentation Preview Deployment URL: https://boundless-documentation-4146xiet0-risczero.vercel.app Updated at: 2025-03-05 15:02:08 UTC |
I merged in and changed the base to be the unaggregated proof PR so that I could use the new types there |
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.
Looks good to me!
I was staring at the logic in fulfillBatch
again wondering if we really need 3 branches there. I think I have a nice simplification in that regard by moving the callback before fulfillment is set and using the fact that if anything fails, the whole call will revert anyway.
|
||
/// @inheritdoc IBoundlessMarketCallback | ||
function handleProof(bytes32 imageId, bytes calldata journal, bytes calldata seal) public { | ||
require(msg.sender == BOUNDLESS_MARKET, "Invalid sender"); |
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 this is fine to include, and possibly beneficial, but its not clear to me that this is case. Let's keep this check for now, and clearly folks can always override this function to remove it if they decide it's unnecessary.
Keep in mind that anyone can specify a callback to any contract, and anyone can create a request on the market. So the amount of constraint this applies to the call is limited, beyond the fact that the receipt is already checked, which is rechecked based on our discussion earlier.
Co-authored-by: Victor Snyder-Graf <[email protected]>
… property (#372) This PR is a change I am proposing, but do not have consensus on. Opening it to discuss. With #335, we added support for callbacks on fulfillment and we aimed to have the callback trigger at most once per request. Since that PR, I realized two issues: 1. As implemented, there is a potential re-entrancy attack on this property in that the called contract can call one of the `fulfill` methods and have the callback trigger again for the same request (ID). This is because we use the `fulfilled` flag to indicate whether the callback has run, but that flag is not set until after the callback is complete. 2. Even if a given request ID can only be used to trigger a callback once, any user can create an arbitrary number of unique requests that are fulfilled by the same proof. Using a single receipt, they can fulfill an arbitrary number of requests and trigger an identical callback for each. This is indistinguishable on the called contract from multiple calls associated with the same request. My opinion is that the call-once property does not buy us much. If there is an action which modifies state, the called application will have its own notion of what to do when the callback arrives, and ensuring it behaves reasonably if the same call is repeated is a common requirement for a wide range of applications. As an advantage to dropping this property as a goal, benchmarks show it would save ~800 gas per fulfillment. --------- Co-authored-by: Pote <[email protected]>