CORDA-1392 Make Hibernate entities non-Serializable (#3458)

* CORDA-1392 Make Hibernate entities non-Serializable

* CORDA-1392 Make Hibernate entities non-Serializable - fix api

* CORDA-1392 Fix determinise

* CORDA-1392 Add changelog entry

* CORDA-1392 Address code review changes
This commit is contained in:
Tudor Malene 2018-07-05 09:37:30 +01:00 committed by GitHub
parent d72caf59f0
commit 2ab5a4cf12
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
20 changed files with 43 additions and 84 deletions

View File

@ -4359,7 +4359,7 @@ public interface net.corda.core.schemas.QueryableState extends net.corda.core.co
@NotNull
public abstract Iterable<net.corda.core.schemas.MappedSchema> supportedSchemas()
##
public interface net.corda.core.schemas.StatePersistable extends java.io.Serializable
public interface net.corda.core.schemas.StatePersistable
##
public interface net.corda.core.serialization.ClassWhitelist
public abstract boolean hasListed(Class<?>)

View File

@ -74,7 +74,7 @@ task predeterminise(type: ProGuardTask) {
keepattributes '*'
keepdirectories
dontwarn '**$1$1'
dontwarn '**$1$1,org.hibernate.annotations.*'
dontpreverify
dontobfuscate
dontoptimize
@ -100,7 +100,8 @@ task jarFilter(type: JarFilterTask) {
"net.corda.core.StubOutForDJVM"
]
forRemove = [
"co.paralleluniverse.fibers.Suspendable"
"co.paralleluniverse.fibers.Suspendable",
"org.hibernate.annotations.Immutable"
]
}
}

View File

@ -5,6 +5,7 @@ import net.corda.core.contracts.ContractState
import net.corda.core.contracts.StateRef
import net.corda.core.serialization.CordaSerializable
import net.corda.core.utilities.toHexString
import org.hibernate.annotations.Immutable
import java.io.Serializable
import javax.persistence.Column
import javax.persistence.Embeddable
@ -82,6 +83,7 @@ class PersistentState(@EmbeddedId var stateRef: PersistentStateRef? = null) : St
*/
@KeepForDJVM
@Embeddable
@Immutable
data class PersistentStateRef(
@Column(name = "transaction_id", length = 64, nullable = false)
var txId: String,
@ -96,7 +98,8 @@ data class PersistentStateRef(
* Marker interface to denote a persistable Corda state entity that will always have a transaction id and index
*/
@KeepForDJVM
interface StatePersistable : Serializable
interface StatePersistable
object MappedSchemaValidator {
fun fieldsFromOtherMappedSchema(schema: MappedSchema) : List<SchemaCrossReferenceReport> =
schema.mappedTypes.map { entity ->

View File

@ -6,6 +6,9 @@ release, see :doc:`upgrade-notes`.
Unreleased
----------
* The Corda JPA entities no longer implement java.io.Serializable, as this was causing persistence errors in obscure cases.
Java serialization is disabled globally in the node, but in the unlikely event you were relying on these types being Java serializable please contact us.
* Remove all references to the out-of-process transaction verification.
* The class carpenter has a "lenient" mode where it will, during deserialisation, happily synthesis classes that implement

View File

@ -10,7 +10,6 @@ import net.corda.core.serialization.serialize
import net.corda.core.utilities.MAX_HASH_HEX_SIZE
import net.corda.core.utilities.NetworkHostAndPort
import net.corda.node.services.persistence.NodePropertiesPersistentStore
import java.io.Serializable
import javax.persistence.*
object NodeInfoSchema
@ -53,7 +52,7 @@ object NodeInfoSchemaV1 : MappedSchema(
*/
@Column(name = "serial", nullable = false)
val serial: Long
) : Serializable {
) {
fun toNodeInfo(): NodeInfo {
return NodeInfo(
this.addresses.map { it.toHostAndPort() },
@ -73,7 +72,7 @@ object NodeInfoSchemaV1 : MappedSchema(
var id: Int,
val host: String? = null,
val port: Int? = null
) : Serializable {
) {
companion object {
fun fromHostAndPort(hostAndPort: NetworkHostAndPort) = DBHostAndPort(
0, hostAndPort.host, hostAndPort.port
@ -106,7 +105,7 @@ object NodeInfoSchemaV1 : MappedSchema(
@ManyToMany(mappedBy = "legalIdentitiesAndCerts", cascade = [(CascadeType.ALL)]) // ManyToMany because of distributed services.
private val persistentNodeInfos: Set<PersistentNodeInfo> = emptySet()
) : Serializable {
) {
constructor(partyAndCert: PartyAndCertificate, isMain: Boolean = false)
: this(partyAndCert.name.toString(),
partyAndCert.party.owningKey.toStringShort(),

View File

@ -11,13 +11,9 @@ import net.corda.core.contracts.ScheduledStateRef
import net.corda.core.contracts.StateRef
import net.corda.core.flows.FlowLogic
import net.corda.core.flows.FlowLogicRefFactory
import net.corda.core.internal.FlowStateMachine
import net.corda.core.internal.ThreadBox
import net.corda.core.internal.VisibleForTesting
import net.corda.core.internal.*
import net.corda.core.internal.concurrent.flatMap
import net.corda.core.internal.concurrent.openFuture
import net.corda.core.internal.join
import net.corda.core.internal.until
import net.corda.core.node.ServicesForResolution
import net.corda.core.schemas.PersistentStateRef
import net.corda.core.serialization.SingletonSerializeAsToken
@ -37,18 +33,9 @@ import net.corda.nodeapi.internal.persistence.contextTransaction
import org.apache.activemq.artemis.utils.ReusableLatch
import org.apache.mina.util.ConcurrentHashSet
import org.slf4j.Logger
import java.io.Serializable
import java.time.Duration
import java.time.Instant
import java.util.concurrent.CancellationException
import java.util.concurrent.CompletableFuture
import java.util.concurrent.CompletionStage
import java.util.concurrent.ExecutionException
import java.util.concurrent.Executor
import java.util.concurrent.Executors
import java.util.concurrent.Future
import java.util.concurrent.TimeUnit
import java.util.concurrent.TimeoutException
import java.util.concurrent.*
import javax.annotation.concurrent.ThreadSafe
import javax.persistence.Column
import javax.persistence.EmbeddedId
@ -149,7 +136,7 @@ class NodeSchedulerService(private val clock: CordaClock,
@Column(name = "scheduled_at", nullable = false)
var scheduledAt: Instant = Instant.now()
) : Serializable
)
private class InnerState {
var rescheduled: GuavaSettableFuture<Boolean>? = null

View File

@ -19,7 +19,6 @@ import net.corda.nodeapi.internal.crypto.x509Certificates
import net.corda.nodeapi.internal.persistence.CordaPersistence
import net.corda.nodeapi.internal.persistence.NODE_DATABASE_PREFIX
import org.apache.commons.lang.ArrayUtils.EMPTY_BYTE_ARRAY
import java.io.Serializable
import java.security.InvalidAlgorithmParameterException
import java.security.PublicKey
import java.security.cert.*
@ -86,7 +85,7 @@ class PersistentIdentityService(override val trustRoot: X509Certificate,
@Lob
@Column(name = "identity_value", nullable = false)
var identity: ByteArray = EMPTY_BYTE_ARRAY
) : Serializable
)
@Entity
@javax.persistence.Table(name = "${NODE_DATABASE_PREFIX}named_identities")
@ -97,7 +96,7 @@ class PersistentIdentityService(override val trustRoot: X509Certificate,
@Column(name = "pk_hash", length = MAX_HASH_HEX_SIZE, nullable = true)
var publicKeyHash: String? = ""
) : Serializable
)
override val caCertStore: CertStore
override val trustAnchor: TrustAnchor = TrustAnchor(trustRoot, null)

View File

@ -11,7 +11,6 @@ import net.corda.nodeapi.internal.persistence.CordaPersistence
import net.corda.nodeapi.internal.persistence.NODE_DATABASE_PREFIX
import org.apache.commons.lang.ArrayUtils.EMPTY_BYTE_ARRAY
import org.bouncycastle.operator.ContentSigner
import java.io.Serializable
import java.security.KeyPair
import java.security.PrivateKey
import java.security.PublicKey
@ -45,7 +44,7 @@ class PersistentKeyManagementService(val identityService: IdentityService,
@Lob
@Column(name = "private_key", nullable = false)
var privateKey: ByteArray = EMPTY_BYTE_ARRAY
) : Serializable {
) {
constructor(publicKey: PublicKey, privateKey: PrivateKey)
: this(publicKey.toStringShort(), publicKey.encoded, privateKey.encoded)
}

View File

@ -6,7 +6,6 @@ import net.corda.node.services.statemachine.DeduplicationId
import net.corda.node.utilities.AppendOnlyPersistentMap
import net.corda.nodeapi.internal.persistence.CordaPersistence
import net.corda.nodeapi.internal.persistence.NODE_DATABASE_PREFIX
import java.io.Serializable
import java.time.Instant
import java.util.concurrent.ConcurrentHashMap
import javax.persistence.Column
@ -97,7 +96,7 @@ class P2PMessageDeduplicator(private val database: CordaPersistence) {
@Column(name = "sequence_number", nullable = true)
var seqNo: Long? = null
) : Serializable
)
private data class MessageMeta(val insertionTime: Instant, val senderHash: String?, val senderSeqNo: Long?)

View File

@ -10,7 +10,6 @@ import net.corda.nodeapi.internal.persistence.currentDBSession
import org.apache.commons.lang.ArrayUtils.EMPTY_BYTE_ARRAY
import org.slf4j.Logger
import org.slf4j.LoggerFactory
import java.io.Serializable
import java.util.*
import java.util.stream.Stream
import javax.persistence.Column
@ -34,7 +33,7 @@ class DBCheckpointStorage : CheckpointStorage {
@Lob
@Column(name = "checkpoint_value", nullable = false)
var checkpoint: ByteArray = EMPTY_BYTE_ARRAY
) : Serializable
)
override fun addCheckpoint(id: StateMachineRunId, checkpoint: SerializedBytes<Checkpoint>) {
currentDBSession().saveOrUpdate(DBCheckpoint().apply {

View File

@ -1,21 +1,22 @@
package net.corda.node.services.persistence
import net.corda.core.internal.bufferUntilSubscribed
import net.corda.core.crypto.SecureHash
import net.corda.core.flows.StateMachineRunId
import net.corda.core.internal.bufferUntilSubscribed
import net.corda.core.messaging.DataFeed
import net.corda.core.messaging.StateMachineTransactionMapping
import net.corda.node.services.api.StateMachineRecordedTransactionMappingStorage
import net.corda.node.utilities.*
import net.corda.node.utilities.AppendOnlyPersistentMap
import net.corda.nodeapi.internal.persistence.CordaPersistence
import net.corda.nodeapi.internal.persistence.NODE_DATABASE_PREFIX
import net.corda.nodeapi.internal.persistence.bufferUntilDatabaseCommit
import net.corda.nodeapi.internal.persistence.wrapWithDatabaseTransaction
import rx.subjects.PublishSubject
import java.io.Serializable
import java.util.*
import javax.annotation.concurrent.ThreadSafe
import javax.persistence.*
import javax.persistence.Column
import javax.persistence.Entity
import javax.persistence.Id
/**
* Database storage of a txhash -> state machine id mapping.
@ -35,7 +36,7 @@ class DBTransactionMappingStorage(private val database: CordaPersistence) : Stat
@Column(name = "state_machine_run_id", length = 36, nullable = true)
var stateMachineRunId: String? = ""
) : Serializable
)
private companion object {
fun createMap(): AppendOnlyPersistentMap<SecureHash, StateMachineRunId, DBTransactionMapping, String> {

View File

@ -8,11 +8,7 @@ import net.corda.core.internal.VisibleForTesting
import net.corda.core.internal.bufferUntilSubscribed
import net.corda.core.internal.concurrent.doneFuture
import net.corda.core.messaging.DataFeed
import net.corda.core.serialization.SerializationDefaults
import net.corda.core.serialization.SerializedBytes
import net.corda.core.serialization.SingletonSerializeAsToken
import net.corda.core.serialization.deserialize
import net.corda.core.serialization.serialize
import net.corda.core.serialization.*
import net.corda.core.toFuture
import net.corda.core.transactions.CoreTransaction
import net.corda.core.transactions.SignedTransaction
@ -26,12 +22,7 @@ import net.corda.nodeapi.internal.persistence.wrapWithDatabaseTransaction
import org.apache.commons.lang.ArrayUtils.EMPTY_BYTE_ARRAY
import rx.Observable
import rx.subjects.PublishSubject
import java.io.Serializable
import javax.persistence.Column
import javax.persistence.Entity
import javax.persistence.Id
import javax.persistence.Lob
import javax.persistence.Table
import javax.persistence.*
// cache value type to just store the immutable bits of a signed transaction plus conversion helpers
typealias TxCacheValue = Pair<SerializedBytes<CoreTransaction>, List<TransactionSignature>>
@ -51,7 +42,7 @@ class DBTransactionStorage(cacheSizeBytes: Long, private val database: CordaPers
@Lob
@Column(name = "transaction_value", nullable = false)
var transaction: ByteArray = EMPTY_BYTE_ARRAY
) : Serializable
)
private companion object {
fun createTransactionsMap(maxSizeInBytes: Long)

View File

@ -20,11 +20,7 @@ import net.corda.core.node.services.AttachmentId
import net.corda.core.node.services.AttachmentStorage
import net.corda.core.node.services.vault.AttachmentQueryCriteria
import net.corda.core.node.services.vault.AttachmentSort
import net.corda.core.serialization.CordaSerializable
import net.corda.core.serialization.SerializationToken
import net.corda.core.serialization.SerializeAsToken
import net.corda.core.serialization.SerializeAsTokenContext
import net.corda.core.serialization.SingletonSerializeAsToken
import net.corda.core.serialization.*
import net.corda.core.utilities.contextLogger
import net.corda.node.services.config.NodeConfiguration
import net.corda.node.services.vault.HibernateAttachmentQueryCriteriaParser
@ -38,22 +34,12 @@ import net.corda.nodeapi.internal.withContractsInJar
import java.io.FilterInputStream
import java.io.IOException
import java.io.InputStream
import java.io.Serializable
import java.nio.file.Paths
import java.time.Instant
import java.util.*
import java.util.jar.JarInputStream
import javax.annotation.concurrent.ThreadSafe
import javax.persistence.CollectionTable
import javax.persistence.Column
import javax.persistence.ElementCollection
import javax.persistence.Entity
import javax.persistence.ForeignKey
import javax.persistence.Id
import javax.persistence.Index
import javax.persistence.JoinColumn
import javax.persistence.Lob
import javax.persistence.Table
import javax.persistence.*
/**
* Stores attachments using Hibernate to database.
@ -115,7 +101,7 @@ class NodeAttachmentService(
@CollectionTable(name = "${NODE_DATABASE_PREFIX}attachments_contracts", joinColumns = [(JoinColumn(name = "att_id", referencedColumnName = "att_id"))],
foreignKey = ForeignKey(name = "FK__ctr_class__attachments"))
var contractClassNames: List<ContractClassName>? = null
) : Serializable
)
@VisibleForTesting
var checkAttachmentsOnLoad = true

View File

@ -9,7 +9,6 @@ import net.corda.nodeapi.internal.persistence.CordaPersistence
import net.corda.nodeapi.internal.persistence.NODE_DATABASE_PREFIX
import org.slf4j.Logger
import rx.subjects.PublishSubject
import java.io.Serializable
import javax.persistence.Column
import javax.persistence.Entity
import javax.persistence.Id
@ -35,7 +34,7 @@ class NodePropertiesPersistentStore(readPhysicalNodeId: () -> String, persistenc
@Column(name = "property_value", nullable = true)
var value: String? = ""
) : Serializable
)
}
private class FlowsDrainingModeOperationsImpl(readPhysicalNodeId: () -> String, private val persistence: CordaPersistence, logger: Logger) : FlowsDrainingModeOperations {

View File

@ -22,7 +22,6 @@ import net.corda.core.utilities.debug
import net.corda.node.utilities.AppendOnlyPersistentMap
import net.corda.nodeapi.internal.persistence.NODE_DATABASE_PREFIX
import net.corda.nodeapi.internal.persistence.currentDBSession
import java.io.Serializable
import java.time.Clock
import java.time.Instant
import java.util.*
@ -39,7 +38,7 @@ class PersistentUniquenessProvider(val clock: Clock) : UniquenessProvider, Singl
@Column(name = "consuming_transaction_id", nullable = true)
val consumingTxHash: String?
) : Serializable
)
@Entity
@javax.persistence.Table(name = "${NODE_DATABASE_PREFIX}notary_request_log")
@ -62,7 +61,7 @@ class PersistentUniquenessProvider(val clock: Clock) : UniquenessProvider, Singl
@Column(name = "request_timestamp", nullable = false)
var requestDate: Instant
) : Serializable
)
@Entity
@javax.persistence.Table(name = "${NODE_DATABASE_PREFIX}notary_committed_states")

View File

@ -32,7 +32,6 @@ import net.corda.nodeapi.internal.config.NodeSSLConfiguration
import net.corda.nodeapi.internal.config.SSLConfiguration
import net.corda.nodeapi.internal.persistence.CordaPersistence
import net.corda.nodeapi.internal.persistence.NODE_DATABASE_PREFIX
import java.io.Serializable
import java.nio.file.Path
import java.time.Clock
import java.util.concurrent.CompletableFuture
@ -94,7 +93,7 @@ class RaftUniquenessProvider(
var value: String? = "",
@Column(name = "raft_log_index", nullable = false)
var index: Long = 0
) : Serializable
)
/** Directory storing the Raft log and state machine snapshots */
private val storagePath: Path = transportConfiguration.baseDirectory

View File

@ -4,9 +4,8 @@ import net.corda.core.contracts.StateRef
import net.corda.core.contracts.UpgradedContract
import net.corda.core.node.services.ContractUpgradeService
import net.corda.core.serialization.SingletonSerializeAsToken
import net.corda.nodeapi.internal.persistence.NODE_DATABASE_PREFIX
import net.corda.node.utilities.PersistentMap
import java.io.Serializable
import net.corda.nodeapi.internal.persistence.NODE_DATABASE_PREFIX
import javax.persistence.Column
import javax.persistence.Entity
import javax.persistence.Id
@ -24,7 +23,7 @@ class ContractUpgradeServiceImpl : ContractUpgradeService, SingletonSerializeAsT
/** refers to the UpgradedContract class name*/
@Column(name = "contract_class_name", nullable = true)
var upgradedContractClassName: String? = ""
) : Serializable
)
private companion object {
fun createContractUpgradesMap(): PersistentMap<String, String, DBContractUpgrade, String> {

View File

@ -11,7 +11,6 @@ import net.corda.core.schemas.PersistentState
import net.corda.core.serialization.CordaSerializable
import net.corda.core.utilities.OpaqueBytes
import org.hibernate.annotations.Type
import java.io.Serializable
import java.time.Instant
import java.util.*
import javax.persistence.*
@ -154,7 +153,7 @@ object VaultSchemaV1 : MappedSchema(schemaFamily = VaultSchema.javaClass, versio
@Column(name = "note", nullable = true)
var note: String?
) : Serializable {
) {
constructor(txId: String, note: String) : this(0, txId, note)
}
}

View File

@ -6,14 +6,12 @@ import net.corda.node.internal.configureDatabase
import net.corda.node.services.schema.NodeSchemaService
import net.corda.node.utilities.AppendOnlyPersistentMap
import net.corda.nodeapi.internal.persistence.DatabaseConfig
import net.corda.testing.node.MockServices.Companion.makeTestDataSourceProperties
import org.junit.After
import org.junit.Assert.*
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.runners.Parameterized
import java.io.Serializable
import java.util.concurrent.CountDownLatch
import javax.persistence.Column
import javax.persistence.Entity
@ -270,7 +268,7 @@ class AppendOnlyPersistentMapTest(var scenario: Scenario) {
@Column(name = "value", length = 16)
var value: String = ""
) : Serializable
)
class TestMap : AppendOnlyPersistentMap<Long, String, PersistentMapEntry, Long>(
toPersistentEntityKey = { it },

View File

@ -20,7 +20,6 @@ import org.hibernate.annotations.Cascade
import org.hibernate.annotations.CascadeType
import org.junit.Ignore
import org.junit.Test
import java.io.Serializable
import javax.persistence.*
import kotlin.test.assertEquals
import kotlin.test.assertFalse
@ -142,7 +141,7 @@ object TestSchema : MappedSchema(SchemaFamily::class.java, 1, setOf(Parent::clas
@Suppress("unused")
@Entity
@Table(name = "Children")
class Child : Serializable {
class Child {
@Id
@GeneratedValue
@Column(name = "child_id", unique = true, nullable = false)