How to get transaction history in Corda?

前端 未结 3 568
别跟我提以往
别跟我提以往 2020-12-10 07:01

To get state I can use Vault, but what about transactions? How I can get them, for example, by txHash? Is it possible to do this by CordaRPCOps, there is internalVerif

相关标签:
3条回答
  • 2020-12-10 07:42

    The first solution (Using CordaRPCOps.internalVerifiedTransactionsSnapshot) is really slow.

    It is exist one more way to get transaction history and it is pretty effective.

    You can do it by using 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
    }
    
    0 讨论(0)
  • 2020-12-10 07:48

    First, note that as of Corda 3, there are no stability guarantees regarding the behaviour of any method to retrieve a transaction or its dependencies. In particular, we cannot guarantee that the set of transactions retrieved will not change across Corda versions.

    This is because in future versions of Corda, nodes will likely only exchange transaction chains in SGX-encrypted form. These transaction chains will then be verified inside an SGX enclave on the node. This will prevent nodes from seeing the contents of the transactions they are verifying (see the blogpost here: https://www.corda.net/2017/06/corda-sgx-privacy-update/). This may even go so far as to only allow nodes to see certain parts of the transactions they are signing.

    Ways to retrieve transactions as of Corda 3

    1. Using CordaRPCOps.internalVerifiedTransactionsSnapshot

    If you are interacting with the node via RPC, CordaRPCOps.internalVerifiedTransactionsSnapshot returns a list of all recorded transactions.

    If you only wanted to get a single transaction and you knew its hash, you could write:

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

    Note that the transactions returned are of type SignedTransaction. This form does not contain the transaction's attachments or inputs (only the attachment hashes and input state references).

    To retrieve a transaction's attachments via RPC, you could write:

    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) }
    

    And to retrieve a transaction's inputs via RPC, you could write:

    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. Using the ServiceHub

    If you are in a situation where you have access to the node's ServiceHub (e.g. within a flow or a Corda service), you can use serviceHub.validatedTransactions.track().snapshot to get all transactions, and serviceHub.validatedTransactions.getTransaction(transactionHash) to get a specific transaction by hash.

    Note that the transactions returned are of type SignedTransaction. This form does not contain the transaction's attachments or inputs (only the attachment hashes and input state references).

    To convert the SignedTransaction to a LedgerTransaction (where the attachments and inputs are resolved), you could write:

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

    3. By connecting to the node's database

    You can connect directly to the SQL database backing the node, and retrieve the transactions using an SQL query.

    0 讨论(0)
  • 2020-12-10 07:54

    That's right, although please note that the ServiceHub and SQL approaches are basically the same thing as the deprecated RPC and may also stop working in future (or not, depending on how we manage the transition to an encrypted ledger).

    There are other approaches you can use. For instance you could aggregate the bits of history you care about up into the latest version of the state. This also lets you restrict the view of the history once SGX lands.

    0 讨论(0)
提交回复
热议问题