chainweb-node icon indicating copy to clipboard operation
chainweb-node copied to clipboard

Suggestion: Give the possibility to install a cap without a signature in a transaction payload

Open CryptoPascal31 opened this issue 2 years ago • 6 comments

Currently: In a transaction payload, a capability is always associated to a signer (pubKey) and a matching signature. It does make a lot of sense because most of the time, a capability code enforces a guard.

But in some cases the capability doesn't enforce any guard, and just need to be installed. One of these particular cases is in gas station triggered by the magic cap GAS_PAYER. Since this usually triggers a public gas station, it is a non-sense to associate GAS_PAYER to a pubKey. However, this is mandatory with the current Chainweb/Pact implementation.

Currently for a client or a Dapp there are 2 possible workarounds to make it work:

  • If the transaction contains already a signer with an already restricted signature, attach GAS_PAYER to the existing signer. From a functional point of view this is completely inconsistent. It just breaks the beauty and the concept of capabilities.
  • Create a fake signer, with a fake key pair just to install a capability that doesn't need a signer. This is stupid and inefficient.

I think that Chainweb should allow and always validate a payload containing a Signer object with an empty pubKey. In this case, I suggest to use a special marker like "NONE" or "NOVERIFY"in the scheme field, to indicate that signature verification must be bypassed.

NB: Not sure if this should be handled directly by Chainweb code or Pact code.

CryptoPascal31 avatar Jul 21 '23 02:07 CryptoPascal31

Thanks for the suggestion to deal with this using a verifier. Here's my thinking, which I think for the most part is a recap of your thinking. My reasoning earlier re: the GAS_PAYER cap is incomplete. Yes, a verifier cannot grant the GAS_PAYER cap, because as mentioned before, verifiers run after gas is bought. But that doesn't mean we can't find the GAS_PAYER cap regardless in a verifier, that is, "trigger a gas station from a verifier"; the only extra piece of machinery we're missing to do that is to make findPayer search for GAS_PAYER in the verifiers and not just in the signers.

The allow verifier is one way we can do that, but what I'd probably prefer is to have a specific verifier just called something like gas-station which has no proof, only grants GAS_PAYER caps, and is the only other place that findPayer looks in aside from signers. Let me know your thoughts.

Frankly I might prefer to not use a verifier for this either, and instead to have a special field in Command.

edmundnoble avatar Feb 16 '24 19:02 edmundnoble

It's never a problem to install a cap, so we could just install GAS_PAYER in chainweb in all cases.

sirlensalot avatar Feb 16 '24 20:02 sirlensalot

It's never a problem to install a cap, so we could just install GAS_PAYER in chainweb in all cases.

But which GAS_PAYER? We need the module + args so that we can call into the cap body to make sure that the module is ok with paying gas.

edmundnoble avatar Feb 16 '24 20:02 edmundnoble

@edmundnoble sorry I forgot that sigs are indeed how a GAS_PAYER cap is specified:

https://github.com/kadena-io/chainweb-node/blob/f13025ba5ca2a374559b9f8e709f636c391a1b95/src/Chainweb/Pact/TransactionExec.hs#L967

Frankly I might prefer to not use a verifier for this either, and instead to have a special field in Command.

Agree, adding something like gasPayer to Payload is probably better so that it's not in scope for the entire tx.

sirlensalot avatar Feb 16 '24 21:02 sirlensalot

Actually, gasPayer could be a way to get away from Ethereum-centered naming (sender really doesn't make sense as a gas payer in the Pact context.) The idea would be, deprecate sender, and have gasPayer replace it with an object { account: "xxx", caps: [{cap: foo.bar.GAS_PAYER, args: [...]}] } . Just a thought

sirlensalot avatar Feb 16 '24 21:02 sirlensalot

Actually, gasPayer could be a way to get away from Ethereum-centered naming (sender really doesn't make sense as a gas payer in the Pact context.) The idea would be, deprecate sender, and have gasPayer replace it with an object { account: "xxx", caps: [{cap: foo.bar.GAS_PAYER, args: [...]}] } . Just a thought

IMO: I agree with you. This makes a lot of sense:

  • Semantic: sender is a bad-chosen name. It confuses a lot of builders, especially people coming from Solidity where sender is used for a more general purpose than just paying gas. gasPayer is definitively better.
  • The GAS_PAYER cap has nothing to do with inside a signer or verifier cap (there is in fact no relation). Attaching it to the gas-paying account makes more sense.

CryptoPascal31 avatar Feb 18 '24 11:02 CryptoPascal31