Open dete opened 1 month ago
For clarity: This is merely a feature suggestion, and should not be considered until after C1.0…
Great idea!
I guess access on fields would return references, so that e.g. containers (arrays, dictionaries, nested composites, etc.) would be immutable?
If we add hash()
method to struct we can make a Signed
struct, then we don't need to worry about mutability.
It would be nice to be able to generate signed stuff from Cadence side too. ( if there are multiple signers for example )
access(all) struct Signed{
access(all) var payload : AnyStruct
access(all) var signatureSet: [Crypto.KeyListSignature]
access(all) fun verify(keyList: Crypto.KeyList): Bool {
keyList.isValid(
signatureSet: signatureSet,
signedData: self.payload.hash()
)
}
}
Issue to be solved
A frequent use-case in blockchains is to have a user sign some data structure, similarly to how we asks users to sign transactions. Depending on the application, the data structures could be very different. They could be as simple as a few integers, or it could be a complicated structure with nested arrays and dictionaries.
Ideally, there would be a way in Cadence to easily handle such data structures: make it easy for client software to generate signed structures, and make it easy for smart contracts (or off-chain code) to verify those structures.
Suggested Solution
I'm imagining a wrapper mechanism similar to Capabilities. If I had a structure called
Foo
, Cadence code could refer toSigned<Foo>
datatypes.Signed<Foo>
instances would look and act just like the base type with a few caveats:let
declarations, so they couldn't be written directly.signatureSet
would be available, which is a list of KeyListSignature objects.verify(keyList: Crypto.KeyList): Bool
would check if the current contents of the structure (including the signatureSet) are consistent with the keys in the given KeyList.The resulting code could look sort of like this:
As a rule,
Signed<>
structures would be constructed off-chain and serialized to be used as arguments to scripts and transactions, so we'd also need to make sure that any client libraries had convenience methods for constructing signed objects. I don't think it would typically make much sense for Cadence code to constructSigned<>
instances directly. I don't believe signed resource objects are useful (or perhaps even possible).The type of the wrapped object could be used as a domain tag to prevent cross-domain attacks.
Open Question: What (if any) protection against replay attacks can/should we provide here?