如何在 Corda 中获取交易历史记录?
How to get transaction history in Corda?
要获取状态,我可以使用 Vault,但是事务呢?我怎样才能得到它们,例如,通过 txHash?是否可以通过 CordaRPCOps 做到这一点,有 internalVerifiedTransactionsSnapshot
方法,但现在已弃用。
首先,请注意,从 Corda 3 开始,对于检索事务或其依赖项的任何方法的行为都没有稳定性保证。特别是,我们不能保证检索到的交易集不会在 Corda 版本之间发生变化。
这是因为在 Corda 的未来版本中,节点可能只会以 SGX 加密形式交换交易链。然后,这些交易链将在节点上的 SGX 飞地内进行验证。这将防止节点看到他们正在验证的交易内容(请参阅此处的博文:https://www.corda.net/2017/06/corda-sgx-privacy-update/)。这甚至可能只允许节点看到他们正在签署的交易的某些部分。
从 Corda 3 开始检索交易的方法
1.使用 CordaRPCOps.internalVerifiedTransactionsSnapshot
如果您通过 RPC 与节点交互,CordaRPCOps.internalVerifiedTransactionsSnapshot
returns 所有记录交易的列表。
如果你只想得到一个交易并且你知道它的哈希值,你可以这样写:
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 和 SQL 方法与已弃用的 RPC 基本相同,并且将来也可能停止工作(或不工作,具体取决于我们如何管理过渡到加密账本)。
您还可以使用其他方法。例如,您可以将您关心的历史片段聚合到最新版本的状态中。这也让您可以在 SGX 登陆后限制历史视图。
第一个解决方案(使用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
}
要获取状态,我可以使用 Vault,但是事务呢?我怎样才能得到它们,例如,通过 txHash?是否可以通过 CordaRPCOps 做到这一点,有 internalVerifiedTransactionsSnapshot
方法,但现在已弃用。
首先,请注意,从 Corda 3 开始,对于检索事务或其依赖项的任何方法的行为都没有稳定性保证。特别是,我们不能保证检索到的交易集不会在 Corda 版本之间发生变化。
这是因为在 Corda 的未来版本中,节点可能只会以 SGX 加密形式交换交易链。然后,这些交易链将在节点上的 SGX 飞地内进行验证。这将防止节点看到他们正在验证的交易内容(请参阅此处的博文:https://www.corda.net/2017/06/corda-sgx-privacy-update/)。这甚至可能只允许节点看到他们正在签署的交易的某些部分。
从 Corda 3 开始检索交易的方法
1.使用 CordaRPCOps.internalVerifiedTransactionsSnapshot
如果您通过 RPC 与节点交互,CordaRPCOps.internalVerifiedTransactionsSnapshot
returns 所有记录交易的列表。
如果你只想得到一个交易并且你知道它的哈希值,你可以这样写:
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 和 SQL 方法与已弃用的 RPC 基本相同,并且将来也可能停止工作(或不工作,具体取决于我们如何管理过渡到加密账本)。
您还可以使用其他方法。例如,您可以将您关心的历史片段聚合到最新版本的状态中。这也让您可以在 SGX 登陆后限制历史视图。
第一个解决方案(使用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
}