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
Along with the contract and enclave binary, devs must also implement the WebSocketListener trait which defines a script which will listen to tendermint events from the configured node_url and call the enclave endpoints based on these events.
Currently, there's no predefined functions or structure to how this is implemented, making it quite unintuitive for a quartz dev. With this issue I'd like to make some architecture decisions around pieces we can provide as part of the framework to help devs.
Issues
Devs must implement their own logic for indexing into the Tendermint event to determine if their WebSocketListener handler should trigger the core logic.
Devs must directly call the tm-prover library's prove function, which requires filling a large configuration parameter struct and blocking execution for the length of 1-2 TM blocks.
Since the websocketlistener handlers are called sequentially on events coming in, if the dev wants to call the enclave on every block, this means an infinitely-growing delay if the handler must wait 1-2 blocks in order to finish executing logic
which we could simplify with a macro quite easily.
There are 3 different objects which effectively represent the same data, which becomes confusing for the dev.
a. There's the protobuf message object, which is a struct containing a "message" field. it's named based on the .proto file
b. There's the object that the protobuf message actually contains in serialized form. One is essentially the wire type and the other the domain type.
c. There's the struct that represents the message sent to the smart contract. It usually contains the exact same info as what is returned by the enclave
So, for example, when getting data returned by the enclave and sending it to the smart contract, the wire type, domain type that you must serialize it into, and the object that you then send to the smart contract are all differently named objects containing the same data.
Discussion
1
For # 1 , I'm trying to think of how I can make the experience more "fill in the blank" in a way which is more helpful than restrictive. In the watchexec library, devs simply pass a filename to the watchexec config, which will then send a 'file update' event over a tokio channel which contains all the metadata about the dev's requested file upon detection of changes. In this case, the dev is starting with the tendermint event. However, this tendermint event needs to be evaluated for whether it matches the dev's query.
Additionally, there is some redundancy in the code now where the dev loops over an event to determine whether to react before looping again to collect desired information from attributes, etc:
which combines these two loops. If the return type is None, the event should be ignored. Otherwise (if there's a match), the return vector contains the specified events & their attributes. The Event obj is this one.
2
The tm-prover is called by both the handshake command in the quartz cli and by devs for WebSocketListener impls. It would be good to get rid of this repetitive logic by moving it into a library somewhere. The issue is that the arguments for the prove function are mostly values that are supplied by the quartz.toml config file. So pulling this prover calling logic into a library (such as quartz-common) would mean that this library would have to be aware of the file structure of a quartz app, or the .config folder more specifically. Alternatively, the quartz-cli would be imported as a library and a function for the prover could be used.
I'm not sure what the optimal solution here is.
3
I'll add some possible implementations here later.
The text was updated successfully, but these errors were encountered:
Summary
Along with the contract and enclave binary, devs must also implement the WebSocketListener trait which defines a script which will listen to tendermint events from the configured
node_url
and call the enclave endpoints based on these events.Currently, there's no predefined functions or structure to how this is implemented, making it quite unintuitive for a quartz dev. With this issue I'd like to make some architecture decisions around pieces we can provide as part of the framework to help devs.
Issues
Devs must implement their own logic for indexing into the Tendermint event to determine if their WebSocketListener handler should trigger the core logic.
Devs must directly call the
tm-prover
library'sprove
function, which requires filling a large configuration parameter struct and blocking execution for the length of 1-2 TM blocks.which we could simplify with a macro quite easily.
a. There's the protobuf message object, which is a struct containing a "message" field. it's named based on the .proto file
b. There's the object that the protobuf message actually contains in serialized form. One is essentially the wire type and the other the domain type.
c. There's the struct that represents the message sent to the smart contract. It usually contains the exact same info as what is returned by the enclave
So, for example, when getting data returned by the enclave and sending it to the smart contract, the wire type, domain type that you must serialize it into, and the object that you then send to the smart contract are all differently named objects containing the same data.
Discussion
1
For # 1 , I'm trying to think of how I can make the experience more "fill in the blank" in a way which is more helpful than restrictive. In the
watchexec
library, devs simply pass a filename to thewatchexec
config, which will then send a 'file update' event over a tokio channel which contains all the metadata about the dev's requested file upon detection of changes. In this case, the dev is starting with the tendermint event. However, this tendermint event needs to be evaluated for whether it matches the dev's query.Additionally, there is some redundancy in the code now where the dev loops over an event to determine whether to react before looping again to collect desired information from attributes, etc:
cycles-quartz/apps/transfers/enclave/src/wslistener.rs
Lines 104 to 113 in c4bd111
cycles-quartz/apps/transfers/enclave/src/wslistener.rs
Lines 46 to 66 in c4bd111
I'm thinking that we should define a trait with a method like
which combines these two loops. If the return type is
None
, the event should be ignored. Otherwise (if there's a match), the return vector contains the specified events & their attributes. TheEvent
obj is this one.2
The tm-prover is called by both the handshake command in the quartz cli and by devs for WebSocketListener impls. It would be good to get rid of this repetitive logic by moving it into a library somewhere. The issue is that the arguments for the prove function are mostly values that are supplied by the
quartz.toml
config file. So pulling this prover calling logic into a library (such as quartz-common) would mean that this library would have to be aware of the file structure of a quartz app, or the.config
folder more specifically. Alternatively, the quartz-cli would be imported as a library and a function for the prover could be used.I'm not sure what the optimal solution here is.
3
I'll add some possible implementations here later.
The text was updated successfully, but these errors were encountered: