Menu

Corda (Labs - Alpha)

A Crux module that allows you to pipe verified Corda transactions into a Crux node, to then query using Crux’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("pro.juxt.crux-labs", "crux-corda", "1.18.0-1")

// Library for inclusion in contract JARs
implementation("pro.juxt.crux-labs", "crux-corda-state", "1.18.0-1")
<dependency>
    <groupId>pro.juxt.crux-labs</groupId>
    <artifactId>crux-corda</artifactId>
    <version>1.18.0-1</version>
</dependency>

<!-- Library for inclusion in contract JARs -->
<dependency>
    <groupId>pro.juxt.crux-labs</groupId>
    <artifactId>crux-corda-state</artifactId>
    <version>1.18.0-1</version>
</dependency>

Corda Service

To set up a Crux node within Corda, create a Corda Service:

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

This is a minimal configuration - see the main Crux configuration documentation for how to further configure the Crux node within the startCruxNode block.

Mapping Corda documents into Crux

By default, any Corda states that implement crux.corda.state.CruxState will be indexed into Crux:

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

    override val cruxId = linearId.id

    override val cruxDoc: 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 CruxState objects:

@CordaService
class CruxService(private val serviceHub: AppServiceHub) : SingletonSerializableAsToken() {
    val node = serviceHub.startCruxNode {
        withCordaTxLog {
            // This replicates the default behaviour.
            withDocumentMapping { state ->
                if (state is CruxState) 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 Crux node will only be able to index the transactions of its associated Corda node.

Querying Crux

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

val cruxNode = serviceHub.cordaService(CruxService::class.java).node

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