Skip to content

Instantly share code, notes, and snippets.

@dazraf
Created January 24, 2019 18:04
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save dazraf/74a9e9bd93d55a250ed904b27e51b949 to your computer and use it in GitHub Desktop.
Save dazraf/74a9e9bd93d55a250ed904b27e51b949 to your computer and use it in GitHub Desktop.
How to get Corda StateRefs that are locked without corresponding flows (using some Cordite extension methods)
import io.cordite.commons.database.executeCaseInsensitiveQuery
import io.cordite.commons.utils.transaction
import net.corda.core.contracts.StateRef
import net.corda.core.crypto.SecureHash
import net.corda.core.node.AppServiceHub
import net.corda.core.node.services.CordaService
import net.corda.core.serialization.SingletonSerializeAsToken
import net.corda.core.utilities.loggerFor
import net.corda.node.services.statemachine.StateMachineManager
import java.util.*
@CordaService
class DiagnosticsService(private val serviceHub: AppServiceHub) : SingletonSerializeAsToken() {
companion object {
private val log = loggerFor<DiagnosticsService>()
}
private val stateMachineManager = serviceHub
.getFieldValue("flowStarter")!!
.getFieldValue("smm")!! as StateMachineManager
fun dumpLockedStatesWithoutFlow() {
val txt = lockedStatesWithoutFlow().map { "(${it.first.txhash}:${it.first.index}) - ${it.second}" }
log.info("locked states without flows:\n$txt")
}
fun lockedStatesWithoutFlow() : List<Pair<StateRef, UUID>> {
val uuids = stateMachineManager.allStateMachines.map { it.runId.uuid }
return lockedStatesThatDontMatchFlowUUIDs(uuids)
}
fun lockedStatesThatDontMatchFlowUUIDs(uuids: List<UUID>): List<Pair<StateRef, UUID>> {
val concatenated = uuids.joinToString(",") { "'$it'" }
val stmt = """
SELECT TRANSACTION_ID, OUTPUT_INDEX, LOCK_ID
FROM VAULT_STATES
WHERE LOCK_ID IS NOT NULL AND LOCK_ID NOT IN ($concatenated)
"""
return serviceHub.transaction {
serviceHub.jdbcSession().executeCaseInsensitiveQuery(stmt)
.map {
val transactionId = SecureHash.parse(it.getString("TRANSACTION_ID"))
val index = it.getInt("OUTPUT_INDEX")
val lockId = UUID.fromString(it.getString("LOCK_ID"))
StateRef(transactionId, index) to lockId
}.toList().toBlocking().first()
}
}
init {
log.info("started ${DiagnosticsService::class.java.simpleName}")
}
}
private fun <T : Any> T.getFieldValue(name: String) : Any? {
val field = this.javaClass.getDeclaredField(name)
field.isAccessible = true
return field.get(this)
}
@dazraf
Copy link
Author

dazraf commented Jan 24, 2019

The code above is a simple diagnostics services that can be called to locate locked Corda states that do not have a corresponding in-progress flows. Uses extension methods from Cordite project. To invoke this use:

serviceHub.cordaService(DiagnosticsService::class.java).dumpLockedStatesWithoutFlow()

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment