Skip to content

Commit

Permalink
R3SOL-367 Extract ledger persistence to library (#6346)
Browse files Browse the repository at this point in the history
Move `UtxoPersistenceServiceImpl` and its related classes as part of 
ledger persistence to `ledger-lib-persistence`.

The library itself does not have any OSGi services and only includes 
OSGi package annotations to keep everything working.

The library is then called from `ledger-persistence` to keep existing 
functionality the same.

The JSON validator module was also split to remove OSGi references.

Changes include:

- `UtxoPersistenceServiceImpl` -> `ledger-lib-persistence`.
- `DefaultContractStateVaultJsonFactory` -> `ledger-lib-persistence`.
- `ContractStateVaultJsonFactoryRegistry` -> `ledger-lib-persistence`.
- `PostgresUtxoQueryProvider` -> `ledger-lib-persistence`.
- `UtxoRepositoryImpl` -> `ledger-lib-persistence`.
- Copies of `SignatureSpec`, `SignatureWithKey` and 
 `SignedGroupParameters` added to remove Avro dependency.
 - `JsonValidator` -> `json-validator-lib`.
 - `JsonValidatorImpl` -> `json-validator-lib-impl` with an OSGi version
   remaining in existing module.

---------

Co-authored-by: nkovacsx <[email protected]>
Co-authored-by: Dan Newton <[email protected]>
  • Loading branch information
3 people authored Sep 27, 2024
1 parent 1979410 commit b1de83d
Show file tree
Hide file tree
Showing 95 changed files with 501 additions and 239 deletions.
1 change: 1 addition & 0 deletions components/ledger/ledger-consensual-flow/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ dependencies {
implementation project(':libs:ledger:ledger-consensual-data')
implementation project(':libs:ledger:ledger-common-data')
implementation project(":libs:serialization:json-validator")
implementation project(":libs:serialization:json-validator-lib")
implementation project(':libs:serialization:serialization-checkpoint-api')
implementation project(':libs:serialization:serialization-internal')
implementation project(':libs:utilities')
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package net.corda.ledger.consensual.flow.impl.transaction.factory

import net.corda.common.json.validation.JsonValidator
import net.corda.ledger.common.data.transaction.TransactionMetadataImpl
import net.corda.ledger.common.data.transaction.WireTransaction
import net.corda.ledger.common.data.transaction.factory.WireTransactionFactory
Expand All @@ -14,6 +13,7 @@ import net.corda.ledger.consensual.data.transaction.consensualComponentGroupStru
import net.corda.ledger.consensual.data.transaction.verifier.verifyMetadata
import net.corda.ledger.consensual.flow.impl.transaction.ConsensualSignedTransactionImpl
import net.corda.ledger.consensual.flow.impl.transaction.verifier.ConsensualLedgerTransactionVerifier
import net.corda.libs.json.validator.JsonValidator
import net.corda.sandbox.type.UsedByFlow
import net.corda.sandboxgroupcontext.CurrentSandboxGroupContext
import net.corda.v5.application.crypto.DigitalSignatureAndMetadata
Expand Down
2 changes: 2 additions & 0 deletions components/ledger/ledger-persistence/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -39,10 +39,12 @@ dependencies {
implementation project(':libs:messaging:messaging')
implementation project(':libs:metrics')
implementation project(':libs:serialization:json-validator')
implementation project(':libs:serialization:json-validator-lib')
implementation project(':libs:utilities')
implementation project(":libs:serialization:serialization-avro")
implementation project(":libs:tracing")
implementation project(':libs:virtual-node:sandbox-group-context')
implementation project(':libs:ledger-lib-persistence')

// TODO This might not be needed if code is refactored so that WireTransactionSerializer is not used and
// WireTransaction's ID is sent over wire (doesn't need to be calculated using MerkleTreeFactory)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package net.corda.ledger.persistence.consensual.tests

import net.corda.common.json.validation.JsonValidator
import net.corda.cpiinfo.read.CpiInfoReadService
import net.corda.crypto.core.SecureHashImpl
import net.corda.db.persistence.testkit.components.VirtualNodeService
Expand All @@ -18,6 +17,7 @@ import net.corda.ledger.persistence.consensual.ConsensualTransactionReader
import net.corda.ledger.persistence.consensual.impl.ConsensualPersistenceServiceImpl
import net.corda.ledger.persistence.consensual.tests.datamodel.ConsensualEntityFactory
import net.corda.ledger.persistence.consensual.tests.datamodel.field
import net.corda.libs.json.validator.JsonValidator
import net.corda.orm.utils.transaction
import net.corda.persistence.common.getEntityManagerFactory
import net.corda.persistence.common.getSerializationService
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,7 @@
package net.corda.ledger.persistence.utxo.tests

import net.corda.common.json.validation.JsonValidator
import net.corda.cpiinfo.read.CpiInfoReadService
import net.corda.crypto.core.SecureHashImpl
import net.corda.data.crypto.wire.CryptoSignatureSpec
import net.corda.data.crypto.wire.CryptoSignatureWithKey
import net.corda.data.membership.SignedGroupParameters
import net.corda.db.persistence.testkit.components.VirtualNodeService
import net.corda.db.testkit.DbUtils
import net.corda.ledger.common.data.transaction.PrivacySalt
Expand All @@ -26,14 +22,17 @@ import net.corda.ledger.common.testkit.cpiPackageSummaryExample
import net.corda.ledger.common.testkit.cpkPackageSummaryListExample
import net.corda.ledger.common.testkit.getPrivacySalt
import net.corda.ledger.common.testkit.getSignatureWithMetadataExample
import net.corda.ledger.libs.persistence.json.ContractStateVaultJsonFactoryRegistry
import net.corda.ledger.libs.persistence.utxo.CustomRepresentation
import net.corda.ledger.libs.persistence.utxo.SignatureSpec
import net.corda.ledger.libs.persistence.utxo.SignatureWithKey
import net.corda.ledger.libs.persistence.utxo.SignedGroupParameters
import net.corda.ledger.libs.persistence.utxo.UtxoPersistenceService
import net.corda.ledger.libs.persistence.utxo.UtxoRepository
import net.corda.ledger.libs.persistence.utxo.UtxoTransactionReader
import net.corda.ledger.libs.persistence.utxo.impl.UtxoPersistenceServiceImpl
import net.corda.ledger.persistence.consensual.tests.datamodel.field
import net.corda.ledger.persistence.json.ContractStateVaultJsonFactoryRegistry
import net.corda.ledger.persistence.json.impl.DefaultContractStateVaultJsonFactoryImpl
import net.corda.ledger.persistence.utxo.CustomRepresentation
import net.corda.ledger.persistence.utxo.UtxoPersistenceService
import net.corda.ledger.persistence.utxo.UtxoRepository
import net.corda.ledger.persistence.utxo.UtxoTransactionReader
import net.corda.ledger.persistence.utxo.impl.UtxoPersistenceServiceImpl
import net.corda.ledger.persistence.utxo.tests.datamodel.UtxoEntityFactory
import net.corda.ledger.utxo.data.state.StateAndRefImpl
import net.corda.ledger.utxo.data.transaction.SignedLedgerTransactionContainer
Expand All @@ -45,6 +44,7 @@ import net.corda.ledger.utxo.data.transaction.UtxoOutputInfoComponent
import net.corda.ledger.utxo.data.transaction.UtxoTransactionMetadata
import net.corda.ledger.utxo.data.transaction.UtxoVisibleTransactionOutputDto
import net.corda.ledger.utxo.data.transaction.utxoComponentGroupStructure
import net.corda.libs.json.validator.JsonValidator
import net.corda.libs.packaging.hash
import net.corda.orm.utils.transaction
import net.corda.persistence.common.getEntityManagerFactory
Expand Down Expand Up @@ -93,7 +93,6 @@ import org.osgi.test.common.annotation.InjectService
import org.osgi.test.junit5.context.BundleContextExtension
import org.osgi.test.junit5.service.ServiceExtension
import java.math.BigDecimal
import java.nio.ByteBuffer
import java.nio.file.Path
import java.security.KeyPairGenerator
import java.security.MessageDigest
Expand Down Expand Up @@ -590,28 +589,25 @@ class UtxoPersistenceServiceImplTest {
@Test
fun `persist and find signed group parameter`() {
val signedGroupParameters = SignedGroupParameters(
ByteBuffer.wrap(ByteArray(1)),
CryptoSignatureWithKey(
ByteBuffer.wrap(ByteArray(1)),
ByteBuffer.wrap(ByteArray(1))
),
CryptoSignatureSpec("", null, null)
ByteArray(1),
SignatureWithKey(ByteArray(1), ByteArray(1)),
SignatureSpec("", null, null)
)

val hash = signedGroupParameters.groupParameters.array().hash(DigestAlgorithmName.SHA2_256).toString()
val hash = signedGroupParameters.groupParameters.hash(DigestAlgorithmName.SHA2_256).toString()

persistenceService.persistSignedGroupParametersIfDoNotExist(signedGroupParameters)

val persistedSignedGroupParameters = persistenceService.findSignedGroupParameters(hash)

// Compare byte arrays using contentEquals instead of toString()
assertThat(
persistedSignedGroupParameters?.mgmSignature?.publicKey.toString()
)
.isEqualTo(signedGroupParameters.mgmSignature?.publicKey.toString())
persistedSignedGroupParameters?.mgmSignature?.publicKey?.contentEquals(signedGroupParameters.mgmSignature.publicKey)
).isTrue() // this will check if the byte arrays have the same content

// Compare signature spec directly (you can use toString() if it's a standard POJO)
assertThat(
persistedSignedGroupParameters?.mgmSignatureSpec.toString()
)
.isEqualTo(signedGroupParameters.mgmSignatureSpec.toString())
).isEqualTo(signedGroupParameters.mgmSignatureSpec.toString())
}

@Test
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package net.corda.ledger.persistence.consensual.impl

import net.corda.ledger.persistence.common.ComponentGroupMapper
import net.corda.ledger.libs.persistence.common.ComponentGroupMapper
import javax.persistence.Tuple

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import net.corda.ledger.common.data.transaction.PrivacySaltImpl
import net.corda.ledger.common.data.transaction.SignedTransactionContainer
import net.corda.ledger.common.data.transaction.TransactionStatus
import net.corda.ledger.common.data.transaction.factory.WireTransactionFactory
import net.corda.ledger.persistence.common.mapToComponentGroups
import net.corda.ledger.libs.persistence.common.mapToComponentGroups
import net.corda.ledger.persistence.consensual.ConsensualRepository
import net.corda.sandbox.type.SandboxConstants.CORDA_MARKER_ONLY_SERVICE
import net.corda.sandbox.type.UsedByPersistence
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package net.corda.ledger.persistence.json.impl

import net.corda.ledger.persistence.json.ContractStateVaultJsonFactoryRegistry
import net.corda.ledger.libs.persistence.json.ContractStateVaultJsonFactoryRegistry
import net.corda.sandbox.type.SandboxConstants
import net.corda.sandbox.type.UsedByPersistence
import net.corda.sandboxgroupcontext.CustomMetadataConsumer
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package net.corda.ledger.persistence.json.impl

import net.corda.ledger.persistence.json.ContractStateVaultJsonFactoryRegistry
import net.corda.ledger.libs.persistence.json.ContractStateVaultJsonFactoryRegistry
import net.corda.sandbox.type.UsedByPersistence
import net.corda.v5.ledger.utxo.ContractState
import net.corda.v5.ledger.utxo.query.json.ContractStateVaultJsonFactory
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package net.corda.ledger.persistence.json.impl

import net.corda.ledger.persistence.json.DefaultContractStateVaultJsonFactory
import net.corda.ledger.libs.persistence.json.DefaultContractStateVaultJsonFactory
import net.corda.v5.application.marshalling.JsonMarshallingService
import net.corda.v5.ledger.utxo.StateAndRef

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import net.corda.crypto.core.parseSecureHash
import net.corda.data.flow.event.FlowEvent
import net.corda.data.ledger.persistence.LedgerPersistenceRequest
import net.corda.flow.utils.toMap
import net.corda.ledger.persistence.common.InconsistentLedgerStateException
import net.corda.ledger.libs.persistence.common.InconsistentLedgerStateException
import net.corda.ledger.persistence.common.UnsupportedLedgerTypeException
import net.corda.ledger.persistence.common.UnsupportedRequestTypeException
import net.corda.messaging.api.processor.SyncRPCProcessor
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package net.corda.ledger.persistence.utxo.impl

import net.corda.ledger.libs.persistence.utxo.impl.PostgresUtxoQueryProvider
import net.corda.ledger.libs.persistence.utxo.impl.UtxoQueryProvider
import net.corda.orm.DatabaseTypeProvider
import net.corda.orm.DatabaseTypeProvider.Companion.POSTGRES_TYPE_FILTER
import net.corda.utilities.debug
import org.osgi.service.component.annotations.Activate
import org.osgi.service.component.annotations.Component
import org.osgi.service.component.annotations.Reference
import org.slf4j.LoggerFactory

@Suppress("unused")
@Component(service = [ UtxoQueryProvider::class ])
class PostgresUtxoOsgiQueryProvider(
databaseTypeProvider: DatabaseTypeProvider,
delegate: UtxoQueryProvider
) : UtxoQueryProvider by delegate {
init {
LoggerFactory.getLogger(this::class.java).debug { "Activated for ${databaseTypeProvider.databaseType}" }
}

@Activate constructor(
@Reference(target = POSTGRES_TYPE_FILTER)
databaseTypeProvider: DatabaseTypeProvider
) : this(databaseTypeProvider, PostgresUtxoQueryProvider())
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package net.corda.ledger.persistence.utxo.impl

import net.corda.db.core.utils.BatchPersistenceServiceImpl
import net.corda.ledger.common.data.transaction.factory.WireTransactionFactory
import net.corda.ledger.libs.persistence.utxo.UtxoRepository
import net.corda.ledger.libs.persistence.utxo.impl.UtxoQueryProvider
import net.corda.ledger.libs.persistence.utxo.impl.UtxoRepositoryImpl
import net.corda.sandbox.type.SandboxConstants.CORDA_MARKER_ONLY_SERVICE
import net.corda.sandbox.type.UsedByPersistence
import net.corda.v5.application.serialization.SerializationService
import org.osgi.service.component.annotations.Activate
import org.osgi.service.component.annotations.Component
import org.osgi.service.component.annotations.Reference
import org.osgi.service.component.annotations.ServiceScope.PROTOTYPE

/**
* Reads and writes ledger transaction data to and from the virtual node vault database.
* The component only exists to be created inside a PERSISTENCE sandbox. We denote it
* as "corda.marker.only" to force the sandbox to create it, despite it implementing
* only the [UsedByPersistence] marker interface.
*/
@Component(
service = [ UtxoRepository::class, UsedByPersistence::class ],
property = [ CORDA_MARKER_ONLY_SERVICE ],
scope = PROTOTYPE
)
class UtxoRepositoryOsgiImpl(delegate: UtxoRepository) : UtxoRepository by delegate, UsedByPersistence {
@Suppress("Unused")
@Activate
constructor(
@Reference(service = SerializationService::class)
serializationService: SerializationService,
@Reference(service = WireTransactionFactory::class)
wireTransactionFactory: WireTransactionFactory,
@Reference(service = UtxoQueryProvider::class)
queryProvider: UtxoQueryProvider
) : this(UtxoRepositoryImpl(BatchPersistenceServiceImpl(), serializationService, wireTransactionFactory, queryProvider))
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import net.corda.data.ledger.persistence.ResolveStateRefs
import net.corda.data.ledger.persistence.UpdateTransactionStatus
import net.corda.data.persistence.FindWithNamedQuery
import net.corda.flow.external.events.responses.factory.ExternalEventResponseFactory
import net.corda.ledger.libs.persistence.utxo.impl.UtxoPersistenceServiceImpl
import net.corda.ledger.persistence.common.RequestHandler
import net.corda.ledger.persistence.common.UnsupportedRequestTypeException
import net.corda.ledger.persistence.json.impl.DefaultContractStateVaultJsonFactoryImpl
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,9 @@ import net.corda.ledger.common.data.transaction.SignedTransactionContainer
import net.corda.ledger.common.data.transaction.TransactionMetadataInternal
import net.corda.ledger.common.data.transaction.TransactionStatus
import net.corda.ledger.common.data.transaction.TransactionStatus.Companion.toTransactionStatus
import net.corda.ledger.libs.persistence.utxo.UtxoPersistenceService
import net.corda.ledger.libs.persistence.utxo.UtxoTransactionReader
import net.corda.ledger.persistence.common.LedgerPersistenceUtils.findAccount
import net.corda.ledger.persistence.utxo.UtxoPersistenceService
import net.corda.ledger.persistence.utxo.UtxoTransactionReader
import net.corda.ledger.utxo.data.state.cast
import net.corda.ledger.utxo.data.transaction.UtxoComponentGroup
import net.corda.ledger.utxo.data.transaction.UtxoVisibleTransactionOutputDto
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@ package net.corda.ledger.persistence.utxo.impl.request.handlers
import net.corda.crypto.core.SecureHashImpl
import net.corda.data.flow.event.external.ExternalEventContext
import net.corda.data.ledger.persistence.FindFilteredTransactionsAndSignatures
import net.corda.ledger.libs.persistence.utxo.UtxoPersistenceService
import net.corda.ledger.persistence.common.RequestHandler
import net.corda.ledger.persistence.utxo.UtxoOutputRecordFactory
import net.corda.ledger.persistence.utxo.UtxoPersistenceService
import net.corda.messaging.api.records.Record
import net.corda.v5.ledger.utxo.StateRef

Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,19 @@
package net.corda.ledger.persistence.utxo.impl.request.handlers

import net.corda.data.crypto.wire.CryptoSignatureParameterSpec
import net.corda.data.crypto.wire.CryptoSignatureSpec
import net.corda.data.crypto.wire.CryptoSignatureWithKey
import net.corda.data.flow.event.FlowEvent
import net.corda.data.flow.event.external.ExternalEventContext
import net.corda.data.ledger.persistence.FindSignedGroupParameters
import net.corda.data.ledger.persistence.FindSignedGroupParametersResponse
import net.corda.ledger.libs.persistence.utxo.SignedGroupParameters
import net.corda.ledger.libs.persistence.utxo.UtxoPersistenceService
import net.corda.ledger.persistence.common.RequestHandler
import net.corda.ledger.persistence.utxo.UtxoPersistenceService
import net.corda.messaging.api.records.Record
import net.corda.persistence.common.ResponseFactory
import java.nio.ByteBuffer
import net.corda.data.membership.SignedGroupParameters as SignedGroupParametersAvro

class UtxoFindSignedGroupParametersRequestHandler(
private val findSignedGroupParameters: FindSignedGroupParameters,
Expand All @@ -19,13 +25,29 @@ class UtxoFindSignedGroupParametersRequestHandler(
val signedGroupParameters = persistenceService.findSignedGroupParameters(
findSignedGroupParameters.hash,
)

return listOf(
responseFactory.successResponse(
externalEventContext,
FindSignedGroupParametersResponse(
listOfNotNull(signedGroupParameters)
listOfNotNull(signedGroupParameters?.toAvro())
)
)
)
}
}

private fun SignedGroupParameters.toAvro(): SignedGroupParametersAvro {
return SignedGroupParametersAvro(
ByteBuffer.wrap(groupParameters),
CryptoSignatureWithKey(ByteBuffer.wrap(mgmSignature.publicKey), ByteBuffer.wrap(mgmSignature.bytes)),
CryptoSignatureSpec(
mgmSignatureSpec.signatureName,
mgmSignatureSpec.customDigestName,
CryptoSignatureParameterSpec(
mgmSignatureSpec.params?.javaClass?.name,
ByteBuffer.wrap(mgmSignatureSpec.params)
)
)
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@ package net.corda.ledger.persistence.utxo.impl.request.handlers
import net.corda.data.flow.event.external.ExternalEventContext
import net.corda.data.ledger.persistence.FindSignedLedgerTransaction
import net.corda.ledger.common.data.transaction.TransactionStatus.Companion.toTransactionStatus
import net.corda.ledger.libs.persistence.utxo.UtxoPersistenceService
import net.corda.ledger.persistence.common.RequestHandler
import net.corda.ledger.persistence.utxo.UtxoOutputRecordFactory
import net.corda.ledger.persistence.utxo.UtxoPersistenceService
import net.corda.messaging.api.records.Record

class UtxoFindSignedLedgerTransactionRequestHandler(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ import net.corda.data.flow.event.external.ExternalEventContext
import net.corda.data.ledger.persistence.FindTransactionIdsAndStatuses
import net.corda.data.persistence.EntityResponse
import net.corda.flow.external.events.responses.factory.ExternalEventResponseFactory
import net.corda.ledger.libs.persistence.utxo.UtxoPersistenceService
import net.corda.ledger.persistence.common.RequestHandler
import net.corda.ledger.persistence.utxo.UtxoPersistenceService
import net.corda.messaging.api.records.Record
import net.corda.v5.application.serialization.SerializationService
import java.nio.ByteBuffer
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@ package net.corda.ledger.persistence.utxo.impl.request.handlers
import net.corda.data.flow.event.external.ExternalEventContext
import net.corda.data.ledger.persistence.FindTransaction
import net.corda.ledger.common.data.transaction.TransactionStatus.Companion.toTransactionStatus
import net.corda.ledger.libs.persistence.utxo.UtxoPersistenceService
import net.corda.ledger.persistence.common.RequestHandler
import net.corda.ledger.persistence.utxo.UtxoOutputRecordFactory
import net.corda.ledger.persistence.utxo.UtxoPersistenceService
import net.corda.messaging.api.records.Record

class UtxoFindTransactionRequestHandler(
Expand Down
Loading

0 comments on commit b1de83d

Please sign in to comment.