A Brief Introduction to the Accounts Library in Corda Blockchain

Published : Dec 16, 2019

Accounts Library Corda Blockchain

  • Accounts Library in Corda Blockchain?

    The accounts library enables a Corda node's vault partition into several subsets. The vault refers to a set of state objects.  Each subset is a representation of an account. In different words, the account's library enables the operator of a Corda node to segment the vault into several "logical" sub-vaults, which benefits in the following ways.

    • Node operators can host multiple entities as accounts on a single node, therefore, lowering the costs.
    • Node operators can do the partition of the vault on a per entity requirement.

    Adding Accounts Dependencies on a CorDapp

    First, add a variable for the accounts release group and the version you wish to use, and add the Corda version that should've installed locally.

    buildscript {
        ext {
            corda_release_version = '4.3-RC01'
            corda_gradle_plugins_version = '4.0.42'
            accounts_release_version = '1.0-RC03'
            quasar_version = '0.7.10'
            kotlin_version = '1.2.71'
            testng_version = '6.14.3'
        repositories {
            maven { url 'https://ci-artifactory.corda.r3cev.com/artifactory/corda' }
        dependencies {
            classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
            classpath "net.corda.plugins:cordapp:$corda_gradle_plugins_version"
            classpath "net.corda.plugins:cordformation:$corda_gradle_plugins_version"

    Second, you must add the accounts artifactory repository,  the list of repositories for your project :

    allprojects {
        repositories {
            maven { url 'https://ci-artifactory.corda.r3cev.com/artifactory/corda' }
            //Corda testing node-driver requires gradle-tooling-api
            maven { url 'https://repo.gradle.org/gradle/libs-releases-local/' }
            //This is needed until the accounts sdk is official
            maven { url "http://ci-artifactory.corda.r3cev.com/artifactory/corda-lib-dev" }
            maven { url 'http://ci-artifactory.corda.r3cev.com/artifactory/corda-lib' }

    You can add the Corda and accounts dependencies to the dependencies block in each module of your CorDapp.

    dependencies {
        cordaCompile "net.corda:corda-node-api:$corda_release_version"
        cordapp "com.r3.corda.lib.accounts:accounts-contracts:$accounts_release_version"
        cordapp "com.r3.corda.lib.accounts:accounts-workflows:$accounts_release_version"

    These should also be added to the deploy nodes task with the following syntax:

    nodeDefaults {
            projectCordapp {
                deploy = false
            rpcUsers = [[user: "user1", "password": "test", "permissions": ["ALL"]]]

    How to share IOUvalue from one node to another is described in Corda's official website IOU example.

    In this blog, we will explain how to share value from one account to another on the same node.

    An Example of IOU using Account Library

    The IOUState 

    The shared facts on the blockchain are represented as states. Our task will define a new state " TransactionState" to represent an IOU.

    Corda state is an instance of a class that implements the ContractState interface.

    In Corda, the ContractState interface has a single field, participants. It represents a list of the entities for which this state is relevant.

    class TransactionState(
        val IOUvalue: Int,
        val lender: PublicKey,
        val borrower: PublicKey
    ) : ContractState {
        override val participants: List<AbstractParty> get() = listOf(lender, borrower).map { AnonymousParty(it)}


    The IOUContract

    In Corda, every contract must implement the Contract interface.

    In Corda, the contract has a single methodverify, which takes a Transaction as input.

    • Verify function, Throws an IllegalArgumentException if it rejects the transaction proposal.
    • Verify function, Returns silently if it accepts the transaction proposal.
    class TransactionContracts : Contract {
        companion object
            val Trans_CONTRACT_ID = TransactionContracts::class.java.name
        interface Commands : CommandData{
            class Create : TypeOnlyCommandData(),Commands
        override fun verify(tx: LedgerTransaction) {


    The IOU Flow

    In Corda, recording a transaction or sending a transaction to a counterparty is very common. Corda developer, instead of forcing to reimplement their logic to handle these tasks, use Corda provided several library's flows to handle these tasks. Using these flows, we invoke in the context of a larger flow to handle a repeatable task sub-flows.

    Corda Flow is instances of classes, made of FlowLogic subclass.

    @InitiatingFlow means that this flow is part of a flow pair and that it triggers the other side to run the counterpart flow (which in our case is the TransactionResponderFlow defined below).

    In Corda @StartableByRPC , RPC interface [startFlowDynamic] Used to initiate any flow [FlowLogic]  and [startTrackedFlowDynamic]) must have this annotation. If it's missing, the flow will not be allowed to start and an exception will be thrown.

    class TransactionFlow (val IouValue : Int,
                           val lenderId : UUID,
                           val borrowerId: UUID
    ) : FlowLogic<SignedTransaction>() {
        override fun call() :SignedTransaction{
            val notary = serviceHub.networkMapCache.notaryIdentities.first();
            val lenderAccountInfo = accountService.accountInfo(lenderId) ?: throw IllegalStateException("Can't find account to move from $lenderId")
            val borrowerAccountInfo = accountService.accountInfo(borrowerId) ?: throw IllegalStateException("Can't find account to move from $borrowerId")
            val lenderKey = subFlow(RequestKeyForAccount(lenderAccountInfo.state.data)).owningKey
            val browerKey = subFlow(RequestKeyForAccount(borrowerAccountInfo.state.data)).owningKey
            val transactionState = TransactionState(IouValue,lenderKey,browerKey)
            val commond = Command(TransactionContracts.Commands.Create(),transactionState.participants.map {it.owningKey})
            val txbuilder = TransactionBuilder(notary).
            var keysToSignWith = mutableListOf(ourIdentity.owningKey, lenderKey)
            //Only add the borrower account if it is hosted on this node (potentially it might be on a different node)
            if (borrowerAccountInfo.state.data.host == serviceHub.myInfo.legalIdentitiesAndCerts.first().party) {
            val locallySignedTx = serviceHub.signInitialTransaction(txbuilder,keysToSignWith)
            //We have to do 2 different flows depending on whether the other account is on our node or a different node
            if (borrowerAccountInfo.state.data.host == serviceHub.myInfo.legalIdentitiesAndCerts.first().party) {
                //Notarise and record the transaction in just our vault.
                return subFlow(FinalityFlow(locallySignedTx, emptyList()))
            } else{
            val borrowerSession = initiateFlow(borrowerAccountInfo.state.data.host)
            val borrowerSignature = subFlow(CollectSignatureFlow(locallySignedTx, borrowerSession, browerKey))
            val fullySignedTx = locallySignedTx.withAdditionalSignatures(borrowerSignature)
            return subFlow(FinalityFlow(fullySignedTx, listOf(borrowerSession)))

    The IOU Responder Flow

    TransactionResponderFlow, in this flow, the borrower has to use ReceiveFinalityFlow to receive and record transactions. It responds to the flow of the lender.

    class TransactionResponderFlow(val counterPartySession : FlowSession) : FlowLogic<SignedTransaction>() {
        override fun call(): SignedTransaction {
            val signTransactionFlow = object : SignTransactionFlow(counterPartySession) {
                override fun checkTransaction(stx: SignedTransaction) = requireThat {
                    val output = stx.tx.outputs.single().data
                    "This must be an lender and borrower  transaction." using (output is TransactionState<*>)
            val txId = subFlow(signTransactionFlow).id
            return subFlow(ReceiveFinalityFlow(counterPartySession, expectedTxId = txId))


    In this post, we implemented the process of an IOU using the account library while inspecting the components that are required to do so. In the Cordapp, States are facts that are shared among parties on the network, contracts are used to validate transactions and flows contain the logic to propose new transactions.

    At Oodles, along with offering Corda blockchain development services, we keep planning to write more on the development aspects of Corda and its complex features.

How useful was this post?

Click on a star to rate it!

  • 0
  • 0

No votes so far! Be the first to rate this post.

Share :

Leave a Comment

Name is required

Comment is required

Recaptcha is required.

No Comments Yet.

More From Oodles

By using this site, you allow our use of cookies. For more information on the cookies we use and how to delete or block them, please read our cookie notice.

Chat with Us Chat with Us
We would love to hear from you!

Oodles | Blockchain Development Company

Name is required

Enter a valid Name

Please enter a valid Phone Number

Please remove URL from text

Recaptcha is required.