如何在Corda中获取交易历史记录?

7
我可以使用Vault来获取状态,但交易信息怎么办?例如,我要通过txHash获取它们,这是否可行?能否通过CordaRPCOps来实现这一点?目前有一个名为internalVerifiedTransactionsSnapshot的方法,但已经被弃用了。
3个回答

8

首先需要注意的是,在 Corda 3 中,任何检索交易或其依赖关系的方法都没有稳定性保证。特别地,我们无法保证所检索到的交易集合不会随着 Corda 版本的变化而改变。

这是因为在 Corda 的未来版本中,节点可能只会以 SGX 加密形式交换交易链。然后,这些交易链将在节点上的 SGX enclave 中进行验证。这将防止节点看到他们正在验证的交易内容(请参见此处的博客文章:https://www.corda.net/2017/06/corda-sgx-privacy-update/)。这甚至可能只允许节点查看他们正在签名的交易的某些部分。

Corda 3 中检索交易的方法

1. 使用 CordaRPCOps.internalVerifiedTransactionsSnapshot

如果您通过 RPC 与节点交互,CordaRPCOps.internalVerifiedTransactionsSnapshot 返回所有已记录的交易列表。

如果您只想获取单个交易并知道它的哈希值,可以编写以下代码:

val transactions = cordaRPCOps.internalVerifiedTransactionsSnapshot()
val signedTransaction = transactions
    .find { it.id == transactionHash }
    ?: throw IllegalArgumentException("Unknown transaction hash.")

请注意返回的交易类型为SignedTransaction。此表单不包含交易的附件或输入(仅包含附件哈希和输入状态引用)。

要通过RPC检索交易的附件,您可以编写以下代码:

val transactions = cordaRPCOps.internalVerifiedTransactionsSnapshot()
val signedTransaction = transactions
        .find { it.id == transactionHash }
        ?: throw IllegalArgumentException("Unknown transaction hash.")

val attachmentHashes = signedTransaction.tx.attachments
val attachmentStreams = attachmentHashes.map { hash -> cordaRPCOps.openAttachment(hash) }

通过RPC检索交易的输入,你可以这样写:

val transactions = cordaRPCOps.internalVerifiedTransactionsSnapshot()
val signedTransaction = transactions
        .find { it.id == transactionHash }
        ?: throw IllegalArgumentException("Unknown transaction hash.")

val inputStateRefs = signedTransaction.inputs
val inputStates = inputStateRefs.map { stateRef ->
    val transaction = transactions.find { it.id == stateRef.txhash }
            ?: throw IllegalArgumentException("Unknown transaction hash.")
    transaction.tx.outputStates[stateRef.index]
}

2. 使用 ServiceHub

如果您处于可以访问节点的 ServiceHub 的情况下(例如在流程或 Corda 服务中),您可以使用 serviceHub.validatedTransactions.track().snapshot 获取所有交易,以及使用 serviceHub.validatedTransactions.getTransaction(transactionHash) 根据哈希获取特定交易。

请注意,返回的交易类型为 SignedTransaction。这种形式不包含交易的附件或输入(仅包含附件哈希和输入状态引用)。

要将 SignedTransaction 转换为 LedgerTransaction(其中解析了附件和输入),您可以编写以下代码:

val signedTransaction = serviceHub.validatedTransactions.getTransaction(transactionHash)
val ledgerTransaction = signedTransaction.toLedgerTransaction(serviceHub)

3. 通过连接节点的数据库

您可以直接连接支持节点的 SQL 数据库,并使用 SQL 查询检索交易。


如果我使用ServiceHub方法,就会出现错误。请将返回类型更改为List<SignedTransaction>。 - Happy Coding

1

没错,需要注意的是,ServiceHub和SQL方法基本上与已弃用的RPC相同,并且将来也可能停止工作(或不停止,这取决于我们如何管理向加密分类帐的转换)。

您可以使用其他方法。例如,您可以将关心的历史位聚合到状态的最新版本中。这还可以让您在SGX到达后限制历史记录的视图。


0
第一种解决方案(使用CordaRPCOps.internalVerifiedTransactionsSnapshot)非常慢。
还有一种获取交易历史记录的方法,它非常有效。
您可以通过使用rpcOps.vaultQueryBy来实现。
fun transaction(transactionId: String): List<Vault.Page<ContractState>> {
    // get jdbc connection (you may simplify it within cordapp) 
    val jt = jt()
    // get all states of transaction
    val output_indexes = jt.queryForList("SELECT OUTPUT_INDEX FROM VAULT_STATES WHERE transaction_id = '$transactionId'", Int::class.java)
    val transactionHash = SecureHash.parse(transactionId)
    // get Rpc connection
    val rpcOps = initialiseNodeRPCConnection()
    val transactionStates = output_indexes.map {
        val constraintTypeCriteria = QueryCriteria.VaultQueryCriteria(status = Vault.StateStatus.ALL, stateRefs = listOf(StateRef(transactionHash, it)))
        rpcOps.vaultQueryBy<ContractState>(constraintTypeCriteria)            
    }
    return transactionStates
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接