Corda

Development Status: Alpha

A XTDB module that allows you to pipe verified Corda transactions into an XTDB node, to then query using XTDB’s bitemporal Datalog query engine.

For an introduction to Corda, check out the tutorials on the Corda site.

Setup

  • build.gradle.kts

  • pom.xml

// Main library
implementation("com.xtdb.labs", "xtdb-corda", "1.23.2")

// Library for inclusion in contract JARs
implementation("com.xtdb.labs", "xtdb-corda-state", "1.23.2")
<dependency>
    <groupId>com.xtdb.labs</groupId>
    <artifactId>xtdb-corda</artifactId>
    <version>1.23.2</version>
</dependency>

<!-- Library for inclusion in contract JARs -->
<dependency>
    <groupId>com.xtdb.labs</groupId>
    <artifactId>xtdb-corda-state</artifactId>
    <version>1.23.2</version>
</dependency>

Corda Service

To set up an XTDB node within Corda, create a Corda Service:

@CordaService
class XtdbService(private val serviceHub: AppServiceHub) : SingletonSerializableAsToken() {
    val node = serviceHub.startXtdbNode {
        withCordaTxLog { }
        ...
    }
}

This is a minimal configuration - see the main Configuring XTDB documentation for how to further configure the XTDB node within the startXtdbNode block.

Mapping Corda documents into XTDB

By default, any Corda states that implement xtdb.corda.state.XtdbState will be indexed into XTDB:

@BelongsToContract(IOUContract::class)
data class IOUState(val value: Int,
                    val lender: Party,
                    val borrower: Party,
                    override val linearId: UniqueIdentifier = UniqueIdentifier()) :
    LinearState, XtdbState {

    override val xtdbId = linearId.id

    override val xtdbDoc: Map<String, Any> = mapOf(
        "iou-state/value" to value,
        "iou-state/lender" to lender.name.toString(),
        "iou-state/borrower" to borrower.name.toString())
}

This mapping can be customised further by overriding the document mapping in the tx-log configuration - providing a function taking each Corda state and returning a collection of XtdbState objects:

@CordaService
class XtdbService(private val serviceHub: AppServiceHub) : SingletonSerializableAsToken() {
    val node = serviceHub.startXtdbNode {
        withCordaTxLog {
            // This replicates the default behaviour.
            withDocumentMapping { state ->
                if (state is XtdbState) listOf(state)
                else null
            }
        }
    }
}

In the same way as each Corda node will only see a subset of transactions of the wider Corda network, the XTDB node will only be able to index the transactions of its associated Corda node.

Querying XTDB

To access the standard XTDB query API, you can make the XTDB node available as a field on your Corda service (as above), and then query XTDB as normal.

val xtdbNode = serviceHub.cordaService(XtdbService::class.java).node

xtdbNode.db().query("""
    {:find [?l ?b ?v]
     :where [[?iou :iou-state/lender ?l]
             [?iou :iou-state/borrower ?b]
             [?iou :iou-state/value ?v]]}
    """.trimIndent())