Add methods to persist decrypted states

This commit is contained in:
lemjclarke 2022-04-07 15:11:10 +01:00
parent 5447c23f24
commit 088a6859d5
7 changed files with 64 additions and 5 deletions

View File

@ -244,6 +244,12 @@ interface ServiceHub : ServicesForResolution {
*/
fun recordEncryptedTransactions(txs: List<EncryptedTransaction>)
/**
* Stores decrypted states for which we were a participant in our vault.
* This is expected to be run within a database transaction.
*/
fun recordDecryptedInputsAndRefs(inputs: Set<StateAndRef<ContractState>>, refs: Set<StateAndRef<ContractState>>)
/**
* Converts the given [StateRef] into a [StateAndRef] object.
*

View File

@ -83,10 +83,6 @@ class CashPaymentFlowTests {
val label = labelToStx.first
val stx = labelToStx.second
println("$label (${stx.id})")
println("> FOUND UNENCRYPTED: ${node.services.validatedTransactions.getTransaction(stx.id)}")
println("> FOUND ENCRYPTED: ${node.services.validatedTransactions.getVerifiedEncryptedTransaction(stx.id)?.let { "${shortStringDesc(it.bytes.toHexString())} signature ${it.verifierSignature.toHexString()}"}}")
println()
}
println()
}

View File

@ -184,12 +184,16 @@ class DbTransactionsResolver(private val flow: ResolveTransactionsFlow) : Transa
val encryptSvc = flow.serviceHub.encryptedTransactionService
logger.trace { "Recording ${sortedDependencies.size} dependencies for ${flow.txHashes.size} transactions" }
val transactionStorage = flow.serviceHub.validatedTransactions as WritableTransactionStorage
println("Processing encrypted dependencies for node: ${flow.ourIdentity}")
for (txId in sortedDependencies) {
// Retrieve and delete the transaction from the unverified store.
val (tx, isVerified) = checkNotNull(transactionStorage.getEncryptedTransactionInternal(txId)) {
"Somehow the unverified transaction ($txId) that we stored previously is no longer there."
}
if (!isVerified) {
println("Processing dependency: ${tx.id}")
// get the dependencies
val signedTransactions = tx.dependencies.mapNotNull { transactionStorage.getTransaction(it) }.toSet()
@ -207,7 +211,24 @@ class DbTransactionsResolver(private val flow: ResolveTransactionsFlow) : Transa
// direct to the validatedTransactions service??
// flow.serviceHub.recordTransactions(usedStatesToRecord, listOf(tx))
val transactionStorage = flow.serviceHub.validatedTransactions as WritableTransactionStorage
// encryptedTransactions.forEach {
// println("decrypting inputs and refs for dependency: ${it.id}")
// val statesToRecord = encryptSvc.decryptInputAndRefsForNode(it)
// flow.serviceHub.recordDecryptedInputsAndRefs(statesToRecord.inputs.toSet(), statesToRecord.refs.toSet())
// }
val statesToRecord = encryptSvc.decryptInputAndRefsForNode(tx)
println("Decrypted inputs: ${statesToRecord.inputs}")
println("Decrypted refs: ${statesToRecord.refs}")
if (statesToRecord.inputs.size > 0 || statesToRecord.refs.size > 0) {
println("Break!")
}
flow.serviceHub.recordDecryptedInputsAndRefs(statesToRecord.inputs.toSet(), statesToRecord.refs.toSet())
transactionStorage.addVerifiedEncryptedTransaction(verifiedTransaction)
} else {
logger.debug { "No need to record $txId as it's already been verified" }

View File

@ -2,6 +2,8 @@ package net.corda.node.services.api
import net.corda.core.concurrent.CordaFuture
import net.corda.core.context.InvocationContext
import net.corda.core.contracts.ContractState
import net.corda.core.contracts.StateAndRef
import net.corda.core.crypto.SecureHash
import net.corda.core.flows.FlowLogic
import net.corda.core.flows.StateMachineRunId
@ -77,6 +79,17 @@ interface ServiceHubInternal : ServiceHubCoreInternal {
}
}
fun recordDecryptedInputsAndRefs(
inputs: Set<StateAndRef<ContractState>>,
refs: Set<StateAndRef<ContractState>>,
vaultService: VaultServiceInternal,
database: CordaPersistence) {
database.transaction {
vaultService.notify(inputs, refs)
}
}
fun recordTransactions(statesToRecord: StatesToRecord,
txs: Collection<SignedTransaction>,
validatedTransactions: WritableTransactionStorage,
@ -190,6 +203,10 @@ interface ServiceHubInternal : ServiceHubCoreInternal {
)
}
override fun recordDecryptedInputsAndRefs(inputs: Set<StateAndRef<ContractState>>, refs: Set<StateAndRef<ContractState>>) {
Companion.recordDecryptedInputsAndRefs(inputs, refs, vaultService, database)
}
override fun createTransactionsResolver(flow: ResolveTransactionsFlow): TransactionsResolver = DbTransactionsResolver(flow)
/**

View File

@ -1,5 +1,7 @@
package net.corda.node.services.api
import net.corda.core.contracts.ContractState
import net.corda.core.contracts.StateAndRef
import net.corda.core.node.StatesToRecord
import net.corda.core.node.services.VaultService
import net.corda.core.transactions.CoreTransaction
@ -22,4 +24,9 @@ interface VaultServiceInternal : VaultService {
* This does not allow for passing transactions that have already been seen by the node, as this API is only used in testing.
*/
fun notify(statesToRecord: StatesToRecord, tx: CoreTransaction) = notifyAll(statesToRecord, listOf(tx))
/**
* Persist [inputs] and [refs] for which we were a participant but may not have observed the full transaction.
*/
fun notify(inputs: Set<StateAndRef<ContractState>>, refs: Set<StateAndRef<ContractState>>)
}

View File

@ -261,6 +261,12 @@ class NodeVaultService(
processTransactions(txns, false)
}
override fun notify(inputs: Set<StateAndRef<ContractState>>, refs: Set<StateAndRef<ContractState>>) {
println("NodeVaultService: notified of update: $inputs, $refs")
val updates = Vault.Update(inputs, emptySet(), references = refs)
// processAndNotify(listOf(updates))
}
private fun makeUpdates(batch: Iterable<CoreTransaction>, statesToRecord: StatesToRecord, previouslySeen: Boolean): List<Vault.Update<ContractState>> {
fun <T> withValidDeserialization(list: List<T>, txId: SecureHash): Map<Int, T> = (0 until list.size).mapNotNull { idx ->

View File

@ -4,6 +4,8 @@ import com.google.common.collect.MutableClassToInstanceMap
import net.corda.core.conclave.common.CordaEnclaveClient
import net.corda.core.contracts.Attachment
import net.corda.core.contracts.ContractClassName
import net.corda.core.contracts.ContractState
import net.corda.core.contracts.StateAndRef
import net.corda.core.contracts.StateRef
import net.corda.core.cordapp.CordappProvider
import net.corda.core.crypto.SecureHash
@ -455,6 +457,10 @@ open class MockServices private constructor(
}
}
override fun recordDecryptedInputsAndRefs(inputs: Set<StateAndRef<ContractState>>, refs: Set<StateAndRef<ContractState>>) {
(vaultService as VaultServiceInternal).notify(inputs, refs)
}
override val networkParameters: NetworkParameters
get() = networkParametersService.run { lookup(currentHash)!! }