mirror of
https://github.com/corda/corda.git
synced 2025-02-06 11:09:18 +00:00
CORDA-3200 Use PersistentIdentityMigrationBuilder instead of schema a… (#5449)
* CORDA-3200 Use PersistentIdentityMigrationBuilder instead of schema and correctly name table using node prefix * CORDA-3200 Remove hacky test migration from PersistentIdentityMigrationNewTable into a unit test to fix postgres failure
This commit is contained in:
parent
eece19cce0
commit
4fb1787f1e
@ -44,26 +44,14 @@ class PersistentIdentityMigrationNewTable : CordaMigration() {
|
|||||||
logger.error("Cannot migrate persistent states: Liquibase failed to provide a suitable database connection")
|
logger.error("Cannot migrate persistent states: Liquibase failed to provide a suitable database connection")
|
||||||
throw PersistentIdentitiesMigrationException("Cannot migrate persistent states as liquibase failed to provide a suitable database connection")
|
throw PersistentIdentitiesMigrationException("Cannot migrate persistent states as liquibase failed to provide a suitable database connection")
|
||||||
}
|
}
|
||||||
initialiseNodeServices(database, setOf(PersistentIdentitiesMigrationSchemaV1))
|
initialiseNodeServices(database, setOf(PersistentIdentitiesMigrationSchemaBuilder.getMappedSchema()))
|
||||||
|
|
||||||
val connection = database.connection as JdbcConnection
|
val connection = database.connection as JdbcConnection
|
||||||
|
|
||||||
doAndTestMigration(connection)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun doAndTestMigration(connection: JdbcConnection) {
|
|
||||||
val alice = TestIdentity(CordaX500Name("Alice Corp", "Madrid", "ES"), 70)
|
|
||||||
val pkHash = addTestMapping(connection, alice)
|
|
||||||
|
|
||||||
// Extract data from old table needed to populate the new table
|
|
||||||
val keyPartiesMap = extractKeyParties(connection)
|
val keyPartiesMap = extractKeyParties(connection)
|
||||||
|
|
||||||
keyPartiesMap.forEach {
|
keyPartiesMap.forEach {
|
||||||
insertEntry(connection, it)
|
insertEntry(connection, it)
|
||||||
}
|
}
|
||||||
|
|
||||||
verifyTestMigration(connection, pkHash, alice.name.toString())
|
|
||||||
deleteTestMapping(connection, pkHash)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun extractKeyParties(connection: JdbcConnection): Map<String, CordaX500Name> {
|
private fun extractKeyParties(connection: JdbcConnection): Map<String, CordaX500Name> {
|
||||||
@ -104,41 +92,6 @@ class PersistentIdentityMigrationNewTable : CordaMigration() {
|
|||||||
override fun validate(database: Database?): ValidationErrors? {
|
override fun validate(database: Database?): ValidationErrors? {
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun addTestMapping(connection: JdbcConnection, testIdentity: TestIdentity): String {
|
|
||||||
val pkHash = UUID.randomUUID().toString()
|
|
||||||
val cert = testIdentity.identity.certPath.encoded
|
|
||||||
|
|
||||||
connection.prepareStatement("INSERT INTO node_identities (pk_hash, identity_value) VALUES (?,?)").use {
|
|
||||||
it.setString(1, pkHash)
|
|
||||||
it.setBytes(2, cert)
|
|
||||||
it.executeUpdate()
|
|
||||||
}
|
|
||||||
return pkHash
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun deleteTestMapping(connection: JdbcConnection, pkHash: String) {
|
|
||||||
connection.prepareStatement("DELETE FROM node_identities WHERE pk_hash = ?").use {
|
|
||||||
it.setString(1, pkHash)
|
|
||||||
it.executeUpdate()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun verifyTestMigration(connection: JdbcConnection, pk: String, name: String) {
|
|
||||||
connection.createStatement().use {
|
|
||||||
try {
|
|
||||||
val rs = it.executeQuery("SELECT (pk_hash, name) FROM node_identities_no_cert")
|
|
||||||
while (rs.next()) {
|
|
||||||
val result = rs.getString(1)
|
|
||||||
require(result.contains(pk))
|
|
||||||
require(result.contains(name))
|
|
||||||
}
|
|
||||||
rs.close()
|
|
||||||
} catch (e: Exception) {
|
|
||||||
logger.error(e.localizedMessage)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -150,7 +103,9 @@ class PersistentIdentityMigrationNewTable : CordaMigration() {
|
|||||||
*/
|
*/
|
||||||
object PersistentIdentitiesMigrationSchema
|
object PersistentIdentitiesMigrationSchema
|
||||||
|
|
||||||
object PersistentIdentitiesMigrationSchemaV1 : MappedSchema(schemaFamily = PersistentIdentitiesMigrationSchema.javaClass, version = 1,
|
object PersistentIdentitiesMigrationSchemaBuilder {
|
||||||
|
fun getMappedSchema() =
|
||||||
|
MappedSchema(schemaFamily = PersistentIdentitiesMigrationSchema.javaClass, version = 1,
|
||||||
mappedTypes = listOf(
|
mappedTypes = listOf(
|
||||||
DBTransactionStorage.DBTransaction::class.java,
|
DBTransactionStorage.DBTransaction::class.java,
|
||||||
PersistentIdentityService.PersistentPublicKeyHashToCertificate::class.java,
|
PersistentIdentityService.PersistentPublicKeyHashToCertificate::class.java,
|
||||||
@ -159,40 +114,6 @@ object PersistentIdentitiesMigrationSchemaV1 : MappedSchema(schemaFamily = Persi
|
|||||||
BasicHSMKeyManagementService.PersistentKey::class.java,
|
BasicHSMKeyManagementService.PersistentKey::class.java,
|
||||||
NodeAttachmentService.DBAttachment::class.java,
|
NodeAttachmentService.DBAttachment::class.java,
|
||||||
DBNetworkParametersStorage.PersistentNetworkParameters::class.java
|
DBNetworkParametersStorage.PersistentNetworkParameters::class.java
|
||||||
)
|
))
|
||||||
)
|
|
||||||
|
|
||||||
class PersistentIdentitiesMigrationException(msg: String, cause: Exception? = null) : Exception(msg, cause)
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A class that encapsulates a test identity containing a [CordaX500Name] and a [KeyPair]. Duplicate of [net.corda.testing.core.TestIdentity]
|
|
||||||
* to avoid circular dependencies.
|
|
||||||
*/
|
|
||||||
private class TestIdentity(val name: CordaX500Name, val keyPair: KeyPair) {
|
|
||||||
|
|
||||||
/** Creates an identity with a deterministic [keyPair] i.e. same [entropy] same keyPair. */
|
|
||||||
@JvmOverloads
|
|
||||||
constructor(name: CordaX500Name, entropy: Long, signatureScheme: SignatureScheme = Crypto.DEFAULT_SIGNATURE_SCHEME)
|
|
||||||
: this(name, Crypto.deriveKeyPairFromEntropy(signatureScheme, BigInteger.valueOf(entropy)))
|
|
||||||
|
|
||||||
val publicKey: PublicKey get() = keyPair.public
|
|
||||||
val party: Party = Party(name, publicKey)
|
|
||||||
val identity: PartyAndCertificate by lazy { getTestPartyAndCertificate(party) } // Often not needed.
|
|
||||||
|
|
||||||
fun getTestPartyAndCertificate(party: Party): PartyAndCertificate {
|
|
||||||
val trustRoot: X509Certificate = DEV_ROOT_CA.certificate
|
|
||||||
val intermediate: CertificateAndKeyPair = DEV_INTERMEDIATE_CA
|
|
||||||
|
|
||||||
val (nodeCaCert, nodeCaKeyPair) = createDevNodeCa(intermediate, party.name)
|
|
||||||
|
|
||||||
val identityCert = X509Utilities.createCertificate(
|
|
||||||
CertificateType.LEGAL_IDENTITY,
|
|
||||||
nodeCaCert,
|
|
||||||
nodeCaKeyPair,
|
|
||||||
party.name.x500Principal,
|
|
||||||
party.owningKey)
|
|
||||||
|
|
||||||
val certPath = X509Utilities.buildCertPath(identityCert, nodeCaCert, intermediate.certificate, trustRoot)
|
|
||||||
return PartyAndCertificate(certPath)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
class PersistentIdentitiesMigrationException(msg: String, cause: Exception? = null) : Exception(msg, cause)
|
@ -5,7 +5,7 @@
|
|||||||
logicalFilePath="migration/node-services.changelog-init.xml">
|
logicalFilePath="migration/node-services.changelog-init.xml">
|
||||||
|
|
||||||
<changeSet author="R3.Corda" id="add-new-persistence-table">
|
<changeSet author="R3.Corda" id="add-new-persistence-table">
|
||||||
<createTable tableName="identities_no_cert">
|
<createTable tableName="node_identities_no_cert">
|
||||||
<column name="pk_hash" type="NVARCHAR(130)">
|
<column name="pk_hash" type="NVARCHAR(130)">
|
||||||
<constraints nullable="false"/>
|
<constraints nullable="false"/>
|
||||||
</column>
|
</column>
|
||||||
|
@ -27,8 +27,10 @@ import org.junit.ClassRule
|
|||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
import org.mockito.Mockito
|
import org.mockito.Mockito
|
||||||
import java.security.KeyPair
|
import java.security.KeyPair
|
||||||
|
import java.sql.Connection
|
||||||
import java.time.Clock
|
import java.time.Clock
|
||||||
import java.time.Duration
|
import java.time.Duration
|
||||||
|
import java.util.*
|
||||||
|
|
||||||
class PersistentIdentityMigrationNewTableTest{
|
class PersistentIdentityMigrationNewTableTest{
|
||||||
companion object {
|
companion object {
|
||||||
@ -83,15 +85,9 @@ class PersistentIdentityMigrationNewTableTest{
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `migrate identities to new table`() {
|
fun `migrate identities to new table`() {
|
||||||
/**
|
val pkHash = addTestMapping(cordaDB.dataSource.connection, alice)
|
||||||
* TODO - We have to mock every statement/ result to test this properly.
|
|
||||||
*
|
|
||||||
* The workaround for now is the [PersistentIdentitiesMigration.addTestMapping] and
|
|
||||||
* [PersistentIdentitiesMigration.deleteTestMapping] methods that allow us to see the migration occur properly during debugging.
|
|
||||||
*
|
|
||||||
* Since [PersistentIdentitiesMigration] implements [CordaMigration] the migration will run when the DB is setup.
|
|
||||||
*/
|
|
||||||
PersistentIdentityMigrationNewTable()
|
PersistentIdentityMigrationNewTable()
|
||||||
|
verifyTestMigration(cordaDB.dataSource.connection, pkHash, alice.name.toString())
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun saveAllIdentities(identities: List<PartyAndCertificate>) {
|
private fun saveAllIdentities(identities: List<PartyAndCertificate>) {
|
||||||
@ -137,4 +133,39 @@ class PersistentIdentityMigrationNewTableTest{
|
|||||||
session.save(persistentParams)
|
session.save(persistentParams)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun addTestMapping(connection: Connection, testIdentity: TestIdentity): String {
|
||||||
|
val pkHash = UUID.randomUUID().toString()
|
||||||
|
val cert = testIdentity.identity.certPath.encoded
|
||||||
|
|
||||||
|
connection.prepareStatement("INSERT INTO node_identities (pk_hash, identity_value) VALUES (?,?)").use {
|
||||||
|
it.setString(1, pkHash)
|
||||||
|
it.setBytes(2, cert)
|
||||||
|
it.executeUpdate()
|
||||||
|
}
|
||||||
|
return pkHash
|
||||||
|
}
|
||||||
|
|
||||||
|
// private fun deleteTestMapping(connection: Connection, pkHash: String) {
|
||||||
|
// connection.prepareStatement("DELETE FROM node_identities WHERE pk_hash = ?").use {
|
||||||
|
// it.setString(1, pkHash)
|
||||||
|
// it.executeUpdate()
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
private fun verifyTestMigration(connection: Connection, pk: String, name: String) {
|
||||||
|
connection.createStatement().use {
|
||||||
|
try {
|
||||||
|
val rs = it.executeQuery("SELECT (pk_hash, name) FROM node_identities_no_cert")
|
||||||
|
while (rs.next()) {
|
||||||
|
val result = rs.getString(1)
|
||||||
|
require(result.contains(pk))
|
||||||
|
require(result.contains(name))
|
||||||
|
}
|
||||||
|
rs.close()
|
||||||
|
} catch (e: Exception) {
|
||||||
|
println(e.localizedMessage)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
@ -1,42 +1,25 @@
|
|||||||
package net.corda.node.services.persistence
|
package net.corda.node.services.persistence
|
||||||
|
|
||||||
import co.paralleluniverse.fibers.Suspendable
|
|
||||||
import net.corda.core.contracts.Amount
|
|
||||||
import net.corda.core.identity.CordaX500Name
|
import net.corda.core.identity.CordaX500Name
|
||||||
import net.corda.core.identity.Party
|
import net.corda.core.identity.Party
|
||||||
import net.corda.core.node.services.KeyManagementService
|
|
||||||
import net.corda.core.transactions.SignedTransaction
|
import net.corda.core.transactions.SignedTransaction
|
||||||
import net.corda.core.transactions.TransactionBuilder
|
import net.corda.core.transactions.TransactionBuilder
|
||||||
import net.corda.core.utilities.OpaqueBytes
|
import net.corda.core.utilities.OpaqueBytes
|
||||||
import net.corda.core.utilities.getOrThrow
|
|
||||||
import net.corda.finance.DOLLARS
|
import net.corda.finance.DOLLARS
|
||||||
import net.corda.finance.`issued by`
|
import net.corda.finance.`issued by`
|
||||||
import net.corda.finance.contracts.asset.Cash
|
import net.corda.finance.contracts.asset.Cash
|
||||||
import net.corda.finance.flows.AbstractCashFlow
|
|
||||||
import net.corda.finance.issuedBy
|
import net.corda.finance.issuedBy
|
||||||
import net.corda.node.migration.VaultStateMigrationTest.Companion.bankOfCorda
|
|
||||||
import net.corda.node.services.identity.PersistentIdentityService
|
import net.corda.node.services.identity.PersistentIdentityService
|
||||||
import net.corda.node.services.keys.BasicHSMKeyManagementService
|
|
||||||
import net.corda.node.services.keys.E2ETestKeyManagementService
|
import net.corda.node.services.keys.E2ETestKeyManagementService
|
||||||
import net.corda.nodeapi.internal.persistence.CordaPersistence
|
import net.corda.nodeapi.internal.persistence.CordaPersistence
|
||||||
import net.corda.testing.common.internal.testNetworkParameters
|
import net.corda.testing.common.internal.testNetworkParameters
|
||||||
import net.corda.testing.core.BOC_NAME
|
|
||||||
import net.corda.testing.core.SerializationEnvironmentRule
|
import net.corda.testing.core.SerializationEnvironmentRule
|
||||||
import net.corda.testing.core.TestIdentity
|
import net.corda.testing.core.TestIdentity
|
||||||
import net.corda.testing.internal.TestingNamedCacheFactory
|
import net.corda.testing.internal.TestingNamedCacheFactory
|
||||||
import net.corda.testing.node.InMemoryMessagingNetwork.ServicePeerAllocationStrategy.RoundRobin
|
|
||||||
import net.corda.testing.node.MockNetwork
|
|
||||||
import net.corda.testing.node.MockNetworkParameters
|
|
||||||
import net.corda.testing.node.MockServices
|
import net.corda.testing.node.MockServices
|
||||||
import net.corda.testing.node.StartedMockNode
|
|
||||||
import net.corda.testing.node.internal.FINANCE_CORDAPPS
|
|
||||||
import net.corda.testing.node.internal.InternalMockNetwork
|
|
||||||
import net.corda.testing.node.internal.TestStartedNode
|
|
||||||
import org.junit.After
|
|
||||||
import org.junit.Before
|
import org.junit.Before
|
||||||
import org.junit.Rule
|
import org.junit.Rule
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
import java.util.*
|
|
||||||
import kotlin.test.assertEquals
|
import kotlin.test.assertEquals
|
||||||
|
|
||||||
class HibernateColumnConverterTests {
|
class HibernateColumnConverterTests {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user