vyper
vyper copied to clipboard
VIP: witness storage
Simple Summary
Provide a witness() keyword which only stores the hash of a complex type. To "read" the struct from storage, it must be provided as a calldata "proof" and the hash of the proof must match the stored value.
Motivation
A common pattern is to hash a struct the first time it's seen, then after that, require it to be provided in calldata, and check that its hash matches the stored value. This keyword would abstract the pattern. This is an alternative optimization to struct packing and would generally perform better when "most" of the struct is accessed, but may perform less well when no-more-than-one-word of the packed struct is accessed.
Specification
specification by example:
my_struct: witness(MyStruct) # stored as bytes32 value
some_other_struct: witness(MyStruct)
def foo(proof: self.my_struct.Proof):
# compiler inserts test that keccak256(proof) == self.my_struct
foo: MyStruct = proof # proof has type MyStruct
baz: MyStruct = self.some_other_struct # banned - the proof is not in the calldata
foo.bar = ... # modify foo
self.my_struct = foo # generated code: self.my_struct = keccak256(foo)
Backwards Compatibility
New feature, backwards compatible
Copyright
Copyright and related rights waived via CC0
This proposal is pretty unclear in it's current format. Is it a set of MyStruct objects stored? Just one? What is the size of the type stored in storage? how does foo: MyStruct = proof: witness[MyStruct] work? Can I configure the hash function used? Can I read values from self.my_struct without a proof?
Is it a set of
MyStructobjects stored? Just one?
in this example - just one. witness() is a keyword used like immutable() or public() - so, ex. an array of MyStruct would be witness(MyStruct[10])
What is the size of the type stored in storage?
32 bytes - the output of the keccak256 hash function
how does
foo: MyStruct = proof: witness[MyStruct]work?
proof has physical data in it. so foo: MyStruct = proof would just be a bytes copy.
Can I configure the hash function used?
no
Can I read values from
self.my_structwithout a proof?
no, will clarify
i guess one open question is, do we assign from the proof or the witness?
# only allowed if a proof is allowed in calldata; bytes are copied from calldata
foo: MyStruct = self.my_struct
vs
foo: MyStruct = proof
only one should be allowed.
i guess one open question is, do we assign from the proof or the witness?
# only allowed if a proof is allowed in calldata; bytes are copied from calldata foo: MyStruct = self.my_structvs
foo: MyStruct = proofonly one should be allowed.
Tbh, both of these are pretty confusing. Should probably be something more like:
foo: MyStruct = self.my_struct.validate(proof)
Tbh, both of these are pretty confusing. Should probably be something more like:
foo: MyStruct = self.my_struct.validate(proof)
Whoa, that's pretty slick
meeting notes: should be generic type, punt until module system is more fleshed out