By Sneha Damle, Developer Evangelist at R3
An application underpinned by blockchain technology can be complex to deploy and operate. Blockchain applications — and their networks — need a way to represent their customers, be it a brokerage firm, a bank or a custodial account. The Accounts SDK is designed to satisfy these customer needs.
What are Accounts
The accounts library allows a Corda node operator to split the vault into multiple “logical” sub-partitions. That’s it.
An account is NOT a true identity. There is no physical vault isolation between accounts, and all accounts share the same vault. Accounts do not have a Doorman provisioned identity; instead, they only have an identity in the context of a host node.
Let’s take a look at a typical account flow.
Step 1 : Import accounts
The very first step after making the decision to use accounts in your CorDapp is to import the needed dependencies. The Accounts SDK operates on the application layer and so the following entries in your build.gradle (as shown below) will make Accounts accessible within your project. The entries include versioning info, addition of the corda-lib repository, and accounts and confidential identity. You can utilize accounts with new applications, or migrate an existing application from a node based model to accounts based (in the latter scenario, you will also need to adjust your state definitions to handle AnonymousParty as described in step 4).
Before you move to Step 2….. a bit on AccountInfo
An account is represented using an AccountInfo state which is a Linear State.
Each account has a name, host and unique id (linear id of linear state) associated with it. Account id can be assumed to be unique at a network level. AccountInfo is similar to NodeInfo but is not auto discoverable via Network Map Service. It is expected that the node which creates the account will share this account info with the peers as stated below.
Step 2: Create Accounts
To use accounts, the node needs to create accounts. The node vault is logically subdivided into multiple sub vaults each corresponding to an account. To create an account, you can use the inbuilt flow CreateAccount as below.
This flow creates an AccountInfo object and specifies the node name as the hostname on the node which runs this flow. Note: hostname is a Party object; hence an account is always associated with a particular node. This party object is the single participant of AccountInfo Linear state and will get notified of any state changes.
Step 3 : Share Account
If account on NodeB wants to interact with this account created on NodeA, NodeA should either share this account with NodeB by calling ShareAccountInfo…
or, NodeB can request this account from NodeA by calling RequestAccountInfo.
Once both the nodes are aware of the account info, they can transact with each other.
Step 4: State Share with accounts
We use Corda to make sure “What you see is what I see”, where you and I were nodes until now. With accounts, we aim to achieve “What you see is what I see” where you and I are accounts hosted on individual nodes.
As we know, states have a participant field which is of type AbstractParty.
Instead of adding Party class which implements AbstractParty, we will add AnonymousParty (which takes in a Public Key as a parameter) representing an account to participants. Hence each account must be associated with a Public Key. Just as a node is associated with a CordaX500 name and a public key, an account is not associated with any legal CordaX500 and is not a true identity, but is only associated with a public key (We rely on Confidential Identities to generate these public keys). To create a public key and associate it with an account, you can use the below flow.
This creates a public key saves the public key to account id mapping in the database and returns an AnonymousParty object.
Note: One account has more than 1 public keys associated with it. 1 public key belongs to only 1 account.
Generate a new key pair, map it to an account and use this public key to participate in a state. These public keys are based on confidential identities.
This state is now mapped to account using the above generated public keys.
An account is a collection of Public Keys. These PublicKeys are used to participate in (or own) ContractStates. Then we’d say ContractState is owned by the account that the Public Key is allocated to.
Step 5 : Signing the transaction
These bunch of public-private key pairs created for accounts are actually owned by the host node, and when it comes to account signing, it’s actually the host node who signs the transaction using these keys on behalf of the account.
Buyer first signs the transaction by passing in its key to signInitialTransaction. Here the node actually signs using this key on behalf of the buyer. We then call CollectSignaturesFlow to get the seller’s signature on the transaction by specifying the buyer’s key as the last parameter which tells CollectSignaturesFlow that buyer has already signed the transaction.
Some important flows to know
We usually use SendStateAndRefFlow for sharing states between nodes. For accounts, you can use, ShareStateWithAccountFlow flow which wraps SendStateAndRefFlow and makes sure that the shared state is visible only to the specified account and not to other accounts hosted on the node. This is how states are shared to accounts only on a need to know basis.
As we know there can be multiple keys mapped to a single account. Also in each transaction we could potentially request for new keys and use new keys each time. The counterparty must be aware about the keys used for signing the transaction. So it makes sense to share account<->public key mappings to the counterparty. This can be done by calling SyncKeyMappingFlow.
This flow is a combination of above two which can be used to sync states as well as sync keys.It shares a StateRef with another node, sends all the confidential identities participating in the state and also sends all the AccountInfos associated with the participation keys.
To query states which belong to this account make sure you specify the account id. Not specifying this account id will return you states not belonging to this account but other accounts as well.
Migrating from One Host to other
Can we in any way change the host “ownership” of the account from one node to another?
There will be work done on this in the future, but as of now, there are two options which could help you resolve your issue.
- Set up a new account on the new node. Generate new key(s) for the new account. Spend all the states from the old account to this new account. (This is the recommended one)
- If you control the all the keys used to participate in your states and can migrate them to the new node, then you need to import the key pairs somehow and then copy all the states across from the old node to the new node.
Holistic Account View
Looking at accounts from a holistic view, we can see that the above diagram is divided into 3 parts — the nodes which are first-class identities and have their certificates signed by the Doorman.
The second part shows how a node hosts accounts. 1 account belongs(hosted on) to only 1 node but can be shared with other nodes as well.
The third layer talks about identities. These are not true identities like node but are identifiable only in the context of the node. They do not have certificates signed by Doorman but instead have self-signed certificates. These identities represent application-level identities which can be mapped to accounts. Hence off ledger identities can be easily mapped to accounts on Corda. Account-level / ACL should be handled by the Cordapp developer at the application level. Identities can be used to handle permissioning at the application level.
Points to Note:
- By default, an account is not created for the node.
- Do not mix accounts with non-accounts, its highly recommended that if you wish to use accounts, then use accounts in all your flows.
- Accounts can be thought of as the very first step towards handling key pairs outside the node.
- Use cases like building custody accounts/brokerage accounts/bank accounts/company employee account etc. can make good use of accounts-sdk.
- All nodes need not support accounts. The accounts sdk is a JAR which can be dropped into the CorDapps folder. Use of it is optional.
- Accounts-sdk was introduced in Corda 4.3, available to CE and OS. It integrates well with tokens-sdk.
Sample code showing how to use Accounts can be found here.
Accounts blog explaining a sample on Accounts can be found here.
Thanks to Roger, Will, Kasia, Stefano and The Corda Team
Thanks for reading — Sneha Damle, Developer Evangelist (R3)
Want to learn more about building awesome blockchain applications on Corda? Be sure to visit corda.net, check out our community page to learn how to connect with other Corda developers, and sign up for one of our newsletters for the latest updates.
— Sneha Damle is a Developer Evangelist at R3, an enterprise blockchain software firm working with a global ecosystem of more than 350 participants across multiple industries from both the private and public sectors to develop on Corda, its open-source blockchain platform, and Corda Enterprise, a commercial version of Corda for enterprise usage.
Follow Sneha on Linkedin.