LedgerGraph

LedgerGraph is a CorDapp you can use to get in-memory access to transaction data. Transaction information is kept in a graph structure on any node where LedgerGraph is installed. As not all transactions are related to all other transactions, there can actually be multiple components in the graph: each a directed acyclic graph (DAG).

LedgerGraph enables other CorDapps, such as the set of Collaborative Recovery CorDapps, to have near real-time access to data concerning all of a node’s transactions and their relationships. Without it, many operations would be unacceptably slow and impractical.

A new configuration option has been added which allows LedgerGraph to initialize and include transactions that have legacy contract states associated with them, that would otherwise fail to deserialize. This configuration option is: ignoreTransactionLoadingFailures = true.

By default, this value is false and the behavior of LedgerGraph is unchanged. However, if you experience a TransactionDeserializationException when initializing LedgerGraph, this configuration option can be added. This allows these transactions to be skipped by substituting in their place an UnknownContractState. The transactions that cause failures will still be included in the graph, however, some of the data contained in these transactions will have unknown values. This may cause issues if filtering the graph by Contract or Participant Data.

To see what’s new in V1.2.3, see the LedgerGraph release notes.

Some improvements have been made to minimize memory footprint. There are no functional changes from V1.2.1.

onDemand: In V1.2.1 you can configure the setting onDemand to true or false. When set to true, your LedgerGraph becomes an on-demand service, active only when triggered by the Archive Service. This saves heap memory usage.

LedgerGraph then deletes a constructed graph when the Archive Service create-snapshot task completes. For example, if a create-snapshot task is followed by a list-items task, the graph will be initialized once more.

  • Corda Enterprise

    Corda nodes must be running Corda Enterprise NOT Corda Open Source.

  • Node Minimum Platform Version (MPV) > 6

    LedgerGraph requires operative Corda nodes to have a Minimum Platform Version (MPV) of 6 or greater, which corresponds with Corda Enterprise 4.4 or newer.

LedgerGraph CorDapps are tested against Corda Enterprise and will work according to the support matrix.

The first step in installation of the LedgerGraph CorDapps is to obtain the Jar files (distributable binaries that the Corda node will run). These should be provided by your Corda representative. Once you have obtained the software in a distributable format, you are ready to install them into your operating Corda node.

You should have access to two individual jar files - one for LedgerGraph itself, and, optionally, another for the LedgerGraph Confidential Identities CorDapp. You should be able to access these files readily on the machine from which you will be performing the installation.

In order to safely install the LedgerGraph software, all pending Corda Flows must finish executing. This can be accomplished by enabling flowDrainingMode - which is a configuration setting that causes the node to no longer accept any incoming instructions to initiate new flows or accept newly initiated incoming flows. Instead, only currently checkpointed flows will continue to execute until the node is drained of any pending activity.

This can be done in one of the following two ways.

  • RPC

    By RPC using the setFlowsDrainingModeEnabled method with the parameter true.

  • CRaSH Shell

    Via the shell by issuing the following command:

    run setFlowsDrainingModeEnabled enabled: true
    

Once the node has been successfully drained of any pending activity you will be able to shut it down safely. Use the checkpoints command, as shown below, to output a JSON representation of remaining checkpoints.

checkpoints dump

If this list is empty, the node has been successfully drained. If the list contains representations of in-flight flows, and continues to do so for an unreasonable amount of time, the flows may have become stuck. At this point you may wish to kill the flows explicitly using the killFlow api. To learn more about this and the associated risks you can review the documentation found here.

If you are upgrading from version 1.0 of Collaborative Recovery, then you should replace ledger-sync-confidential-identities-1.0.jar with ledger-graph-1.2.1.jar.

Using the file transfer protocol of your choice, add the necessary JAR files for ledger-graph and, optionally, ledger-graph-confidential-identities to the cordapps sub-directory of your Corda node.

Before proceeding, check to ensure that your transfer completed successfully and that the files’ sizes don’t differ from the originals that you received.

If you’re installing the ledger-graph-confidential-identities CorDapp, please refer to the Confidential Identities section of this document.

Restart the node in the same manner originally started by the node operator.

Depending on the size of the node’s vault, it might take longer to start than it did previously.

Now that you have successfully installed the LedgerGraph CorDapps, let’s verify that they are available for use. To do so, we will attempt to list out the flows available for initiating via the CRaSH shell.

In the CRaSH shell, run the following command:

flow list

You should now see a list of flows printed to the console, including those listed below. The LedgerGraph CorDapp contains the following flows:

  • GetLedgerGraphMetricsFlow.
  • GetLedgerGraphErrorsFlow.

You can tune LedgerGraph’s behavior through the following configuration parameters:

Default value: 100

Possible values: 10 to 10000000

Description: The number of transactions to include in the result set when querying the database during graph initialization.

Default value: 10

Possible values: 1 to 1000

Description: The number of threads to use when deserializing transaction data during graph initialization.

Default value: true

Possible values: true, false

Description: When set to true, your LedgerGraph becomes an on-demand service, active only when triggered by the Archive Service. This saves heap memory usage.

Default value: false

Possible values: true, false

Description: Specifies if LedgerGraph can initialize even when transactions with associated legacy ContractStates fail to serialize. By default, ignoreTransactionLoadingFailures is false and the behavior of LedgerGraph is unchanged. However, if a TransactionDeserializationException is generated when initializing LedgerGraph, set this config parameter to true to allow transactions to be skipped by substituting an UnknownContractState. The transactions that cause failures will still be included in the graph; however, some of the data contained in these transactions will be altered to Unknown values. This might cause issues if filtering the graph by Contract or by Participant Data. The graph that is built will still be complete.

To use LedgerGraph’s configuration parameters, create a configuration file named after the LedgerGraph JAR file. For example, if the JAR file is called ledger-graph-1.1.jar, the configuration file would be <corda_node_dir>/cordapps/config/ledger-graph-1.1.conf.

If the configuration parameter is not specified, or the configuration file is not present, the default value(s) will be used.

Example configuration file contents:

transactionReaderPageSize = 10000
transactionReaderPoolSize = 32

If you are using Corda Confidential Identities, you need to add further configuration to LedgerGraph in order to properly support your environment. This is due to a limitation in the current implementation of the Confidential Identities CorDapp.

This additional configuration step helps to ensure that confidential identities on your node are properly mapped to known identities (where they have been shared with your node) when new transactions are processed and added to the graph.

In order for LedgerGraph to properly identify transactions belonging to specific confidential identities, the confidential owning keys for those identities must be shared between the involved Corda nodes before to being loaded by LedgerGraph to retrieve data concerning those transactions.

To configure LedgerGraph for use with Confidential Identities:

  1. Deploy the ledger-graph-confidential-identities JAR file to <corda_node_dir>/cordapps.

  2. Edit the node configuration file <corda_node_dir>/node.conf, adding the following flow override:

flowOverrides {
    overrides=[
        {
            initiator="com.r3.corda.lib.ci.workflows.SyncKeyMappingInitiator"
            responder="com.r3.dr.ledgergraph.ci.flows.CustomSyncKeyMappingResponder"
        }
    ]
}

Following is a list of the flows exposed by LedgerGraph:

```
flow start GetLedgerGraphMetricsFlow
```

This flow returns metrics related to LedgerGraph itself. Specifically, the following information is returned:

  • A list of IDs for transactions that could not be resolved (unresolvedTransactions).
  • A list of IDs for attachments that could not be resolved (unresolvedAttachments).
  • A list of IDs for network parameters that could not be resolved (unresolvedNetworkParameters).
  • Metrics for each DAG (dagMetrics).
    • The number of transactions in the DAG (transactionCount).
    • The combined size (in bytes) of all transactions in the DAG (totalSizeOfTransactions).
    • The number of attachments referenced by transactions in the DAG (attachmentCount).
    • The combined size (in bytes) of all attachments referenced by transactions in the DAG (totalSizeOfAttachments).
    • The length of the longest “chain” of transactions in the DAG (lengthOfLongestTransactionChain).
    • Whether all output states of all transactions in this DAG have been spent (consumed) (isFullySpent*).

None.

A LedgerGraphMetrics object.

flow start GetLedgerGraphErrorsFlow

If any errors were encountered by LedgerGraph, this flow can be used to retrieve information regarding those errors.

None.

A list of GraphError objects.

A Corda node running the LedgerGraph CorDapp will expose the following metrics via JMX.

Indicates whether LedgerGraph has finished initialization.

None.

  • true if LedgerGraph has been initialized, false otherwise.

Indicates whether LedgerGraph is in a consistent state. LedgerGraph can be in an inconsistent state for a number of reasons, like missing transaction data, or failure to initialize at node startup. See the log files for more information regarding any consistency issues.

None.

true if the LedgerGraph is in a consistent state. false otherwise.

Indicates whether LedgerGraph has found reference to transactions that it cannot find in the database. When a transaction is inspected and found that it consumes one or more output states of another transaction, but that other transaction can’t be found, that other transaction said to be unresolved.

None.

true if any transactions cannot be found, false otherwise.

Provides the number of transactions that LedgerGraph was unable to resolve.

None.

The number of transactions.

Indicates whether LedgerGraph has found reference to attachments that it cannot find in the database.

None.

true if any attachments cannot be found, false otherwise.

Provides the number of attachments that LedgerGraph was unable to resolve.

None.

The number of attachments.

Indicates whether LedgerGraph has found reference to network parameters that it cannot find in the database.

None.

true if any network parameters cannot be found, false otherwise.

Provides the number of network parameters that LedgerGraph was unable to resolve.

None.

The number of network parameters.

Provides the number of DAGs that exceed the specified length. The length of the DAG is taken from the length of the longest path through the DAG from a transaction that has only issuance states to another that has only exit states or one or more unconsumed states.

maxLength: Integer. DAGs whose lengths exceed this value will be counted in the number of DAGs that exceed the length threshold.

The number of DAGs that exceed the specified length.

Provides the number of DAGs where all of their transactions’ output states have been spent/consumed.

None.

The number of DAGs whose transactions’ states are all spent.

Provides the combined size (in bytes) of all transaction data for all spent DAGs.

None.

The number of bytes used by all transactions of all spent DAGs.

Provides details on any errors LedgerGraph may have encountered during or since initialization.

None.

A list of strings that provide a description of the errors that were encountered.

The LedgerGraph CorDapp requires participating Corda nodes to be:

  • Using Corda Enterprise, not Corda Open Source (OS).
  • Corda Minimum Platform Version (MPV) > 6.
  • Running on top of a supported database technology.

Memory requirements for LedgerGraph are mainly dependent on the the size of a node’s vault. Since LedgerGraph is an in-memory graph of all transactions in the vault, its size is directly related to the number of transactions that exist.

Overall memory usage will be dependent on the number of transactions, number of participants (parties) involved in each transaction, and then number of output states for each transaction.

The following table provides a rough estimation of how much RAM may be required for the number of transactions shown. This is a guideline only. There are many variables in any given Corda network that can affect the amount of heap space used, but this should give you an idea.

Number of TransactionsEstimated RAM Usage (MB)
10 thousand10
100 thousand70
1 million690
10 million6,900
100 million71,680 ‡

1MB = 1,0242 bytes.

Extrapolated. Not tested.

LedgerGraph emits its logs from the com.r3.dr.ledgergraph package, and following is an example of a Log4j2 logger that enables DEBUG-level logging of LedgerGraph logs.

<Loggers>
    <Logger name="com.r3.dr.ledgergraph" level="DEBUG" />
</Loggers>

To specify your own Log4j2 configuration, you can set the following property when starting your Corda node. See the Log4j 2.x docs for more information on configuring Log4j2.

-Dlog4j.configurationFile=path/to/log4j2.xml

To get some metrics from LedgerGraph, you can use the GetLedgerGraphMetricsFlow:

flow start GetLedgerGraphMetricsFlow

This flow will return immediately, and will provide output similar to the following (formatted for readability).

Flow completed with result: LedgerGraphMetrics(
    unresolvedTransactions=[],
    unresolvedAttachments=[
        4C2325D02D1A17078C0CB5B863DFD031E7845FDBF15103BDB119DFE0B6ADD73F
    ],
    unresolvedNetworkParameters=[],
    dagMetrics=[
        DagMetrics(
            transactionCount=1,
            totalSizeOfTransactions=4206,
            attachmentCount=2,
            totalSizeOfAttachments=181504,
            lengthOfLongestTransactionChain=2,
            isFullySpent=false
        )
    ]
)

To check if LedgerGraph ran into any errors you can use the GetLedgerGraphErrorsFlow flow to get any available information regarding those errors:

flow start GetLedgerGraphErrorsFlow

This flow will return immediately, and will provide output similar to the following.

Flow completed with result:
[Attachment with ID '4C2325D02D1A17078C0CB5B863DFD031E7845FDBF15103BDB119DFE0B6ADD73F' could not be found.]

Was this page helpful?

Thanks for your feedback!

Chat with us

Chat with us on our #docs channel on slack. You can also join a lot of other slack channels there and have access to 1-on-1 communication with members of the R3 team and the online community.

Propose documentation improvements directly

Help us to improve the docs by contributing directly. It's simple - just fork this repository and raise a PR of your own - R3's Technical Writers will review it and apply the relevant suggestions.

We're sorry this page wasn't helpful. Let us know how we can make it better!

Chat with us

Chat with us on our #docs channel on slack. You can also join a lot of other slack channels there and have access to 1-on-1 communication with members of the R3 team and the online community.

Create an issue

Create a new GitHub issue in this repository - submit technical feedback, draw attention to a potential documentation bug, or share ideas for improvement and general feedback.

Propose documentation improvements directly

Help us to improve the docs by contributing directly. It's simple - just fork this repository and raise a PR of your own - R3's Technical Writers will review it and apply the relevant suggestions.