kadena-io / pact

The Pact Smart Contract Language
https://pact-language.readthedocs.io/en/stable/
BSD 3-Clause "New" or "Revised" License
580 stars 100 forks source link

Verifier plugin interface #1324

Closed edmundnoble closed 6 months ago

edmundnoble commented 8 months ago

This PR provides a prototype of an interface designed to provide generalized verification of Pact transactions using proofs included in the transaction. A KIP will be forthcoming with more details and a higher level view.

The idea is to make it easy to integrate new types of proofs of a transaction's validity, whether they're some new type of signatures, ZK proofs, SPV proofs, or anything else similar. Pact can effectively treat them all the same, as an opaque piece of data and a set of capabilities that it purports to provide. The Pact container layer, usually chainweb, is responsible for actually verifying that the contents of these proofs provide the capabilities they purport to; Pact code only knows that they are scoped to the capabilities they provide.

PR checklist:

Additionally, please justify why you should or should not do the following:

edmundnoble commented 7 months ago

I think I understand the change better, so my main concern is not with how this is implemented but future semantic consistency with keysets, where we can't put the cat back in the bag -- keyset enforces will be allowed outside of defcaps, so should we be similarly lenient for this enforce?

It's arguably worse to allow verifier enforces outside of defcaps because while a signer has presumably at least seen the code of the transaction, a verifier has no way to do so. Regardless, to me, a keyset enforce outside of a defcap is a definite, unambiguous bug. I would support looking at a possible migration in the future so that newly deployed modules make it illegal. There exist historical examples and I think that's because capabilities are newer than keysets and guards, but that's not something any new code should do.

edmundnoble commented 7 months ago

I'm re-requesting review from @sirlensalot specifically for the last two commits in here; @jmcardon spotted an issue where managed caps that are being composed don't actually show up as CapComposed on the cap stack, so we really do need a separate stack of caps that are currently being evaluated in EvalState.

Specifically I chose to push and pop from this stack in the with-capability and compose-capability native functions and not in the cap runtime (specifically evalCap) because evalCap is sort of recursive and it just confused me, whereas I think I know from the natives' definitions exactly where the cap is being evaluated and where it's done evaluating. If there was a better place to put this, especially close to evalCap, I want to know.