Yes, that makes sense.
It shouldn’t be – for the full protocol adapter we’d compute the state reads in the transaction function (if we expect them to change) and create the proofs therein (so the proofs would be valid).
Yes, that makes sense.
It shouldn’t be – for the full protocol adapter we’d compute the state reads in the transaction function (if we expect them to change) and create the proofs therein (so the proofs would be valid).
We have accelerated cryptographic primitives in risc0 circuits.
secp256k1 and ECDSA signature seem like a good candidate. We can use ecRecover
to check the binding signature. To build the binding public key, we also need ecAdd
over secp256k1 in Solidity. However, we don’t have the pre-compiled version of ecAdd for secp256k1. Using the non-precompiled version might cost a bit more.
In our last meeting, you, @cwgoes, mentioned that we should add an FFICall
field to Action
and Logic.Instance
. Just thinking about the EVM for now, it could look as follows:
FFICall {
address wrapperContract;
bytes input; // (bytes4 selector, bytes calldata)
bytes ouput;
}
IIRC, you also said that from an action, we could extract a list of kinds and check that for all FFI calls a corresponding wrapper (contract) resource is also included in the action.
Wrapper resources could then enforce certain constraints, e.g., that the FFI call was authorized by someone or that some state-corresponding resources (e.g., ERC20 token resources) are part of the action.
However, I think we lack information allowing the RM to know which kind
s to look for.
IMO, while there could be a predefined wrapper resource label (e.g., matching the wrapperContract
field in FFICall
) but there can’t be a single, general, and predefined wrapper resource logic.
IMO, the logic
of the wrapper contract resources will vary for different EVM state changes:
FFICall
info as shown above.Providing the wrapper resource logic
or kind
as part of the FFICall field could work.
FFICall' {
address wrapperContract;
bytes32 wrapperResourceKind;
bytes input;
bytes ouput;
}
This would mean that the protocol adapter contract has to ensure the correspondence between the wrapper resource kind in the FFICall
field and the wrapper contract (e.g., by requiring the wrapper resource kind to be immutably stored in wrapper contract
). Setting this up will probably require some tricks, i.e., deterministic deployment.
Ultimately, the legitimacy of resources corresponding to EVM state comes from their kind being bound to the wrapper resource, which in turn must be bound to the wrapper contract.
Yes, I think we should do this (/cc @vveiln for context). In the canonical RM types, this would be an opaque bytes
. For the EVM protocol adapter, we can decode it as a specific structure such as the one you propose.
In order to know which kinds to look for, we simply consult the wrapper contract <> resource kind mapping, based on the FFI calls actually performed by the transaction. The binding between a wrapper contract (on the EVM) and a wrapper resource kind must be fixed. I think that this is similar to what you’re proposing, except that I don’t think we need to store the wrapperResourceKind
in the FFI call, since we can simply look it up from the wrapper contract.
Notes from discussion with @vveiln @Michael:
@vveiln to write this up in a forum post response.
We assume that all resources are shielded
Each WR is associated with an FFI call that the PA is supposed to perform. In order to do that,
We store FFI calls in Action.AppData
in a fixed location. Currently, AppData
is partitioned by tags - each partition corresponds to the public inputs of the logic of the resource with the corresponding tag:
tag -> instance
, with instance represented as a list of pairs (bitstring, deletion_criterion)
One option to have a standardised location for the FFI calls is to have them the first argument in the list. Alternatively, we can change the AppData structure to be a map and use a standard FFI key to store the FFI call value.
Q: how to tell the difference between WR putting their FFI calls in appData vs non-WR having FFI calls in their AppData?
A: for that we need to verify that the resource associated with the FFI call is of the WC kind. To do that, we drop function privacy for WR (we don’t lose anything because WC are public anyway) and perform the kind check as described below
A logic of any application must have the self resource tag as a public input and resource object as private input - this is true for any logic. In addition to that, we require WR to have an extra mandatory public input - WR kind, and a new mandatory constraint checking that the input kind is the self resource kind:
Here is why it works:
kind
to the private resource object, proving that this is indeed the kind of the currently checked resourcePA can go through the AppData
, find the FFI calls, verify the logic proofs associated with them, and execute the FFI calls.
TL; DR
appData
TO DO:
appData
. I’ll think if it makes sense to turn this substructure into a map (instead of a list), and if yes, we just need to define the key for FFI calls