Blessed Contracts - A better user experience
Background
Note: I'm not sure if the term "Blessed Contract" is officially defined anywhere, but for this document, the term Blessed Contract implies those contracts which are part of the RChain node software that is required to enforce the consensus protocol and otherwise ensure the proper functioning of the RChain blockchain. I further intend to use this proposal to more formally codify the term Blessed Contract as those Rholang contracts that, like the Scala node software, maintain the correct state of the blockchain based on the protocol rules that have been established through social (off-chain) means.
There are a couple of blessed contracts that implement the core functions of RChain. One that handles the consensus protocol called PoS.rho and one that manages the REV called RevVault.rho.
Currently, these blessed contracts are stored in the registry along with other user contracts using insertSigned. The registry itself is technically a system process, not a blessed contract. To learn more about what a system process is, you can read about it ADDLINK. The inputs into insertSigned are the public key, nonce, channel, and signature over those parameters. This results in a unique URI for the entry in the registry based on the public key used in the insert. The signature guarantees that only the owner of the public key could perform the insert, and updates.
One cumbersome outcome of this approach is that each blessed contract that is added to the registry uses a unique key pair. (I don't believe this is technically necessary in that the same keypair could be used so long as the channel being added were unique for each insert.) Currently the nonce used for system contracts is set to maxLong to prevent it from ever being updated. Thus, using insertSigned for blessed contracts does not currently allow contracts to be updated via Rholang.
With this current approach there are a few ways to update these blessed contracts:
- We can modify the code to use a nonce starting at zero, so we could update the entries with follow-on inserts.
The problem with this approach is that if the private keys for these contracts ever fell into the wrong hands, anyone could deploy code to update these contracts. - We can insert new blessed contracts using new keypairs resulting in a new URI.
I mention this approach for completeness, but in practice, this would be horrible as it would require all Rholang that references these previous URIs to be updated. - Node software manipulates the tuplespace directly to update these special contracts.
Proposal
We add a new system process called insertBlessed("contract name", channel). This call would only be available to the node software via a Scala interface but would add the contract name it the global registry (thus updating the tuple space). A call to insertBlessed with a contract name that is already registered will overwrite the previous name with the new channel.
Users of a blessed contract would use it as follows:
new revVaultCh, registryLookup(`rho:registry:lookup`) in { registryLookup!(`rho:blessed:RevVault`, *revVaultCh) | for (@(_, RevVault) <- revVaultCh) { @RevVault!("findOrCreate", posRevAddress, Nil) // ... } }
With such an approach, updating the blessed contracts would occur in Scala code as follows:
private def bondsQuerySource(name: String = "__SCALA__", blockHeight: Long = 0): String = if (blockHeight == UPGRADE_BLOCK_NUMBER) { insertBlessed("PoS", new_channel) // assume new_channel was result of adding new PoS.rho to tuplespace }
With this change, users of these critical system contracts would always look these contracts up in the registry by name. This makes user code much more readable and eliminates the possibility of malicious actors deploying contracts with URIs similar to the blessed contracts, then publishing example code on the Internet in hopes of fooling a new developer.