Corda’s pluggable consensus model allows multiple notaries to operate in the same network. Depending on trust relationships, different parties will want to use different notaries, or use multiple notaries at the same time, based on who they transact with.
At present CorDapps can specify what notary to use for which flow, and use the
NotaryChangeFlow to reassign existing states to a different notary. However, the current process of changing notaries is manual and involves writing custom logic.
- Participants can specify what notary to use for a particular flow, state type, and counterparty combination.
- Participants can reassign their contract states to a different notary without having to write a custom flow. This might be required when a notary gets decommissioned, or a new, more preferable notary is introduced.
- Participants that have different notary preferences can negotiate which common notary to use for a particular transaction. Ideally this would be automated by a fair protocol.
Although the compatibility zone (CZ) and business network (BN) design isn’t finalised, for the first iteration of this design proposal the following assumptions are made:
- All nodes in a CZ agree to accept the notaries listed in the global network parameters document.
- Individual BNs (and potentially individual nodes) can express different preferences for notaries to use from the global list.
- All nodes will have at least one common notary they accept to use (e.g. a global BFT notary).
Taking into consideration different notary preferences, here are the generic steps for parties to transact:
1. Parties agree to initiate a transaction (offline).
2. The initiating party runs a “common notary agreement” protocol. It results in a notary identity that all parties accept. The initiator then starts the desired business flow with the common notary identity.
A new method for this should be exposed on the RPC interface, for example:
val notary = rpc.getCommonNotary(otherParty)
rpc.startFlow(::SellerFlow, otherParty, notary, amount)
Ideally it would be auto-invoked as part of
startFlow, but that means we have to enforce a convention for flow constructors, so the notary parameter can be passed on correctly. A potential solution would be introducing a new annotation and a separate
The protocol could operate in two steps:
- Based on counterparties’ notary preferences, find the optimal notary. If there is only one option, return. No message exchange is required, but the tradeoff is that counterparties would each need to verify the chosen notary is correct.
For example, if we have preferences (A, B, G), and (B, G), the result is B.
- If there are multiple possibilities, pick a notary randomly. To ensure this is fair, the choice could depend on nonces from each party.
For example, if we have preferences (A, B, G), and (B, A, G), the best notary to use is either A or B, and will be chosen at random.
The result of the protocol should be cached, with a set expiry time.
3. The flow checks whether states to be used in the transaction are assigned to the correct notary. If not, notary reassignment is performed. Counterparty flows perform the same.
One approach for achieving this would be moving the responsibility of making sure states point to the same notary outside a flow, but that would effectively require writing a “meta-flow” that runs a desired flow. Parties on the receiving end would also have to run some prior special logic.
Another option would be extending the vault query API to perform notary change automatically, when no state with the specified notary is found. However, not all results of a query might get used for a transaction, so it doesn’t make sense to repoint everything in advance.
A third possibility is to have
TransactionBuilder perform notary change for all input states that don’t match the transaction notary, but that doesn’t work when the builder is shared between parties, or when adding a state that was sent by another party.
Seems like the best approach is to leave this up to the flow writers to handle on case-by-case basis.
4. A transaction gets built, signed and finalised.
When a notary gets decommissioned, or a party wants to switch to a different notary and update its preferences, there needs to be a mechanism for bulk state reassignment. The easiest approach is to introduce a new RPC method:
rpc.migrateStates(oldNotary, newNotary, stateType?)
- Expose an RPC method for migrating states to a new notary.
- Add configuration options for specifying notary preference – ideally it would be advertised by each node.
- Expose an RPC method for negotiating a common notary
- Update Finance module to perform automatic notary reassignment (specifically methods like