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
I'm currently writing my research proposal for my PhD, and I am like Primea as it would make some concepts I need for my PhD project a lot easier to implement.
As I investigated how I can use Primea I had to realize that it was not general enough to do most of the things I hoped for but still could provide some of it.
After I thought a little bit, I came to the conclusion that Primea and especially capabilities could be defined more generally in a simple and straightforward more powerful way.
Limitations of Opaque Addresses
Primea Capabilities can only be used for contracts and for no other resources / entities (like a Method)
Only Addresses can be Opaque and no other Datatypes like an int or a byteArray or a Message
Capabilities are incompatible with other datatypes. They cannot be stored on the stack, in local variables, memory or storage
One and Two are primarily a limitation of their power and a reduction of their generality. Three, on the other hand, makes them a very hard compilation target as they need to be handled especially which makes them hard to use in nested data structures (arrays, structs). Capabilities currently have their own storage and the only data structure they can be part of are messages. The need for their own storage regions seems to be unavoidable without changing how memory and storage works.
This idea provides a way to eliminate (or at least reduce) these limitations and introduce a more general concept that can represent capabilities in a more flexible way (and even enable new use cases)
Authenticated Opaque Append-Only Memory
The base idea is to provide a shared global memory that has some unique properties which enable it to store and manage capabilities and despite the fact that it is shared and global still ensures proper isolation between contracts.
There is one dedicated contract/module that manages that memory and enforces most of the needed properties, which are:
Append Only: Whenever somebody stores/creates something in the memory it is added at the end and existing values are never overwritten or changed (At the end of the Transaction the Memory is cleared)
Authenticated: Whenever somebody stores/creates something in the memory, the address of the creator is stored in addition to the value.
Opaque: Whenever somebody stores/creates something in the memory an opaque reference is returned over which the stored value can be read. Such references cannot be faked, and the only way to get one is if its creator delivers it to you directly or indirectly.
Persistable: A reference can be persisted under an index, which stores it in the persisted storage of the current contract and copies its content (recursively) to the contracts persisted storage as well. The ref can later be retrieved or discarded over the index by the same contract. (The used persisted storage is separated and isolated from the normal one and not accessible through other storage operations)
2 kinds of values can be stored in this memory.
Standard data like i64, f32 etc.. (createData)
A reference array (createRefs).
To access a reference array an index has to be provided in addition to the reference pointing to it.
Under this model, the main method of a contract would only receive and return a single reference which points to the received and returned message respectively. If the message had multiple parameters, the reference would point to a reference array.
Data passed in over a transaction are treated as if they were created by the sender (signer) of the transaction.
Building Primea Capabilities on top of it
The Primea System Interface would provide 2 Methods (pseudocode).
That is enough to enforce the capability when only the Primea System Interface can initiate a call to another contract
Some other use cases
Fine grained capabilities
A contract with 3 methods A,B,C could return to its creator createData(0), createData(1), createData(2). When a is called it contains require(getCreator(getRef(msg,0)) == this & getData(getRef(msg,0)) == 0). Same would be done for B & C, and thus the three createData serve as capabilities for the methods, where the Primea capability is used as capability for the contract.
Higher order messages and forwarders
As a message is just a reference(or a pair of references if the receiver is included) it can be passed around, forwarded, etc.. without doing any copies of the content. When it is finally sent the receiver can call getCreator(msg) to find the original sender. A Message could also be stored and sent in a later transaction or multiple times.
Authenticated Facts (virtually Signed data)
A contract could createData that, for example, says: "Address X possessed Y Tokens somewhen during Block Z" everybody receiving a reference to this can check that the expected contract created it and then trust the data, even if it was not directly received from that contract. This can be seen as data which is digitally signed.
Implementation
There is one thing that may be a bit more evolved to implement, and that is the guarantee of opaqueness for references. Here are two variants for doing that:
Variant 1: Using eWASM.
In this variant, a new type named ref is introduced. Only the memory managing contract/module should be able to create values of this type. No operator should exist that can modify or create values of this type (except for the new memory management module).
The values can be stored on the stack or in local variables/parameters and be copied between them, but they can never be loaded from the linear memory. Then the WASM validation process is used to ensure that never a non-ref is provided where a ref is expected. I do not know WASM well enough to be sure that this is enough, but I think that this would guarantee the opaqueness of reference values.
Variant 2: Tracking ownership.
Whenever a contract is called a set is created that contains the input message reference. When another reference is loaded from the opaque memory then it is added to the set as well. If another contract is called the returned reference is added to the set as well and last when a persisted reference is loaded over its index it is added to the set.
Whenever a new data of type reference array is created all the references in the array must be in the set. When a message is sent the message and capability reference must be in the set. when a reference is persisted it must be in the set.
Performance
Especially with variant 1 combined with a wasm jit compiler that inlines calls to other modules, this can be highly performant as access to the new memory is nothing more than a regular memory read.
If we add an unauthenticated variant (where the creator is not stored), getCreator could in that case just return 0, then it may even be on part with the linear memory in such cases concerning its resource usage
The text was updated successfully, but these errors were encountered:
Preamble
I'm currently writing my research proposal for my PhD, and I am like Primea as it would make some concepts I need for my PhD project a lot easier to implement.
As I investigated how I can use Primea I had to realize that it was not general enough to do most of the things I hoped for but still could provide some of it.
After I thought a little bit, I came to the conclusion that Primea and especially capabilities could be defined more generally in a simple and straightforward more powerful way.
Limitations of Opaque Addresses
One and Two are primarily a limitation of their power and a reduction of their generality. Three, on the other hand, makes them a very hard compilation target as they need to be handled especially which makes them hard to use in nested data structures (arrays, structs). Capabilities currently have their own storage and the only data structure they can be part of are messages. The need for their own storage regions seems to be unavoidable without changing how memory and storage works.
This idea provides a way to eliminate (or at least reduce) these limitations and introduce a more general concept that can represent capabilities in a more flexible way (and even enable new use cases)
Authenticated Opaque Append-Only Memory
The base idea is to provide a shared global memory that has some unique properties which enable it to store and manage capabilities and despite the fact that it is shared and global still ensures proper isolation between contracts.
There is one dedicated contract/module that manages that memory and enforces most of the needed properties, which are:
2 kinds of values can be stored in this memory.
To access a reference array an index has to be provided in addition to the reference pointing to it.
Under this model, the main method of a contract would only receive and return a single reference which points to the received and returned message respectively. If the message had multiple parameters, the reference would point to a reference array.
Data passed in over a transaction are treated as if they were created by the sender (signer) of the transaction.
Building Primea Capabilities on top of it
The Primea System Interface would provide 2 Methods (pseudocode).
That is enough to enforce the capability when only the Primea System Interface can initiate a call to another contract
Some other use cases
Fine grained capabilities
A contract with 3 methods A,B,C could return to its creator createData(0), createData(1), createData(2). When a is called it contains require(getCreator(getRef(msg,0)) == this & getData(getRef(msg,0)) == 0). Same would be done for B & C, and thus the three createData serve as capabilities for the methods, where the Primea capability is used as capability for the contract.
Higher order messages and forwarders
As a message is just a reference(or a pair of references if the receiver is included) it can be passed around, forwarded, etc.. without doing any copies of the content. When it is finally sent the receiver can call getCreator(msg) to find the original sender. A Message could also be stored and sent in a later transaction or multiple times.
Authenticated Facts (virtually Signed data)
A contract could createData that, for example, says: "Address X possessed Y Tokens somewhen during Block Z" everybody receiving a reference to this can check that the expected contract created it and then trust the data, even if it was not directly received from that contract. This can be seen as data which is digitally signed.
Implementation
There is one thing that may be a bit more evolved to implement, and that is the guarantee of opaqueness for references. Here are two variants for doing that:
Variant 1: Using eWASM.
In this variant, a new type named ref is introduced. Only the memory managing contract/module should be able to create values of this type. No operator should exist that can modify or create values of this type (except for the new memory management module).
The values can be stored on the stack or in local variables/parameters and be copied between them, but they can never be loaded from the linear memory. Then the WASM validation process is used to ensure that never a non-ref is provided where a ref is expected. I do not know WASM well enough to be sure that this is enough, but I think that this would guarantee the opaqueness of reference values.
Variant 2: Tracking ownership.
Whenever a contract is called a set is created that contains the input message reference. When another reference is loaded from the opaque memory then it is added to the set as well. If another contract is called the returned reference is added to the set as well and last when a persisted reference is loaded over its index it is added to the set.
Whenever a new data of type reference array is created all the references in the array must be in the set. When a message is sent the message and capability reference must be in the set. when a reference is persisted it must be in the set.
Performance
Especially with variant 1 combined with a wasm jit compiler that inlines calls to other modules, this can be highly performant as access to the new memory is nothing more than a regular memory read.
If we add an unauthenticated variant (where the creator is not stored), getCreator could in that case just return 0, then it may even be on part with the linear memory in such cases concerning its resource usage
The text was updated successfully, but these errors were encountered: