Design doc: Updating genesis block assembly to avoid forgeable names
Mike Stay (stay@)
2018-10-11
Background
Names in Rholang are formed in one of the following two ways (P is a process):
new name in { P }
@P
The first way declares a new name whose scope is constrained to the process in the braces. The second way serializes an existing process. We say a name of form 2 is "forgeable" if the quoted process has no free variables, and "unforgeable" otherwise.
Without the registry, contracts were either inaccessible or insecure. Unforgeable names were inaccessible outside of the scope declaring the free variables, so unsuitable for exposing public contracts. Forgeable names are public, but anyone can deploy competing contracts on those names, so they are insecure. Forgeable names also allow any process to communicate with any other process, so the ocaps requirement that code can be confined is also violated.
The code to assemble the genesis block has used forgeable names as a placeholder until the registry was finished. Now that it is, these forgeable names need to be replaced with unforgeable ones that get added to the registry.
Existing implementation
Each file under casper/src/main/rholang
is currently parsed separately and wrapped in a scala object with two properties, one for the source code and one for the protobuf AST. These are currently assembled sequentially into a list of separate deployments. The contracts refer to each other using forgeable names.
Requirements
We need the contracts to be able to refer to each other while remaining in separate files, without using forgeable names. OPEN QUESTION: do the contracts need to be updateable? For example, what happens if a security flaw is discovered in any of these contracts?
Proposed solutions
Injectable stopgap package manager
Add a name, injectable using the URN syntax, that points to a contract that wraps a map from strings to the casper/src/main/rholang
contracts. Each file would export the names it provides and import the names it needs. Kyle Butt (iteratee@) felt that because the stopgap package manager would always be there even after the real package manager is added to the registry, we should look for another way.
Implementation details
The contract would be implemented in scala that interacts with the rholang interface. We would expose the contract in the same way we expose stdout and the registry. Changing each individual file in casper/src/main/rholang
is basically just adding lines for import and export.
Linking files into a single deployment, then registering them at public keys with LONG_MAX nonces
Create a source template that contains a new
block declaring all the name variables used in the casper/src/main/rholang
contracts, then textually include each of them, generating one large deployment instead of several small ones. To expose these contracts to code deployed after genesis, each one would be registered using a private key and the largest possible nonce, LONG_MAX, so that they could never be replaced. It also allows us to check the key pairs into source control, since they'll never be used for anything other than registering these contracts at an address that's time-independent.
Implementation details
The key generation step would be done once. There would be some substantial changes to Genesis.scala to bundle up the various contracts into the single deployment; as part of that, scala code would need to be added to compute the signatures necessary to register the contracts at the given public keys. The changes to each individual file in casper/src/main/rholang
are mostly just removing quotation marks.
Consensus
From the discussion below in the comments, the consensus is to keep the files separate, but register them at public keys with LONG_MAX nonces. Each file will import the ones it needs explicitly using the public key.