-
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
Output Unification #42
Comments
Can you add more context on why do we need more output types? Can you give examples? |
Of course. Take @fvbizzo's effort in implementing Complex Vouchers as an example. One cannot currently encode a timed voucher, or a voucher dependency, or a permissioned voucher. This is why we'd need to create new output types for these kinds of use cases. In reality, most—if not all—of these complex vouchers could be implemented with only one new output type: a voucher that could do a |
Could you give practical use case examples for these suggested complex vouchers? For instance, I'm not sure in which application we would need a timed voucher, or if we have had any real demand for these. I also don't even understand what a permissioned voucher is ;) |
@miltonjonat Sorry, I meant to say targeted vouchers! Let me try to give some examples of use cases for each of the vouchers proposed in the Complex Vouchers RFP.
Footnotes |
Time based vouchers also have a bunch off applications in finance. For example, we could have a forward operation that allows me to buy X amount of a token in a future date for a certain price x. The dapp can generate two vouchers at the moment of the deal that can only be executed at the forward contract expiration date: one transfer of x eth from the buyer to the seller and a transfer of X tokens to the buyer. Complex vouchers are being developed in response to RFP#003. |
An alternative encoding for outputsCurrently, notices and vouchers are encoded with abi.encode(notice)
abi.encode(destination, payload) In order to unify the outputs in the same tree, we need to make their encodings disjoint (to avoid ambiguity and make it easier to detect the type of outputs). In this issue, I've proposed to prepend the output with a header like bytes1 constant NOTICE = bytes1(0x00);
bytes1 constant VOUCHER = bytes1(0x01);
// [...]
abi.encodePacked(NOTICE, notice)
abi.encodePacked(VOUCHER, destination, payload) The problem with this solution is that if we create output types that have more than one arbitrary-length field, we'll have to use To solve these issues, I've come up with a better solution: to use Solidity's function call encoding. This is how the encoding of notices and vouchers would look: abi.encodeWithSignature("Notice(bytes)", notice)
abi.encodeWithSignature("Voucher(address,bytes)", destination, payload) With this encoding, we can use the output name as the function name, and the output fields as the function arguments. This removes the burden of having to come up with arbitrary numbers for output types, and uses the strict encoding of arguments out-of-the-box (like we do now). Besides, Solidiy already supports a nicer syntax for this encoding. |
Very nice idea. |
Now, from the perspective of the machine, outputs can be thought of as arbitrary blobs. You will be able to tell them apart by the first 4 bytes, which correspond to the function selector of the function call. How this will be reflected on the HTTP API is still under discussion, but some options are:
|
Given that this changes the public API that devs use, maybe it would be nice to consider inputs from the Prototyping and DevAd units. @cf-cartesi @gbarros would you like to comment? |
Encoding and decoding outputs in SoliditySo, recently I discovered a nice idiomatic, type-safe way to encode function calls (which we'll be doing a lot). Here's the step-by-step process. I'll link to files from the output unification branch for reference.
|
|
I created an issue in rollups-node repository to track the changes on our side: cartesi/rollups-node#103 |
The machine-sdk side changes are being tracked here: cartesi/machine-emulator#137 |
OpenZeppelin v5 also migrated from |
📚 Context
Currently, the off-chain machine is able to generate two types of outputs: vouchers and notices. On-chain, these outputs can be validated by anyone with the help of validity proofs.
The proof consists on reconstructing the epoch hash and comparing it with the epoch hash that was claimed by the DApp's consensus. If they are equal, then we can be sure the output is valid.
Currently, this epoch hash is composed by the following components.
As you can see, vouchers and notices each have their own separate Merkle tree. This helps to avoid misinterpreting notices as vouchers and vice versa.
There are, however, two main issues with this design. First, it unnecessarily complicates the on-chain and off-chain code. Second, it hinders the implementation of new output types, since we would have to add a new Merkle tree, which would result in a breaking change in the validation procedure.
✔️ Solution
And so, we noticed that things would be much simpler if we had a single tree for all verifiable outputs. To differentiate between output types, we could add a prefix to each output. For example,
0x00
for vouchers and0x01
for notices. As a result, the epoch hash would only be composed of two components:The text was updated successfully, but these errors were encountered: