diff --git a/.ci/api-current.txt b/.ci/api-current.txt index 73d6272c78..d35e188b7c 100644 --- a/.ci/api-current.txt +++ b/.ci/api-current.txt @@ -4447,21 +4447,19 @@ public class net.corda.core.schemas.PersistentState extends java.lang.Object imp @Embeddable public class net.corda.core.schemas.PersistentStateRef extends java.lang.Object implements java.io.Serializable public () - public (String, Integer) + public (String, int) public (net.corda.core.contracts.StateRef) - @Nullable - public final String component1() - @Nullable - public final Integer component2() @NotNull - public final net.corda.core.schemas.PersistentStateRef copy(String, Integer) + public final String component1() + public final int component2() + @NotNull + public final net.corda.core.schemas.PersistentStateRef copy(String, int) public boolean equals(Object) - @Nullable - public Integer getIndex() - @Nullable + public int getIndex() + @NotNull public String getTxId() public int hashCode() - public void setIndex(Integer) + public void setIndex(int) public void setTxId(String) public String toString() ## diff --git a/core/src/main/kotlin/net/corda/core/schemas/CommonSchema.kt b/core/src/main/kotlin/net/corda/core/schemas/CommonSchema.kt index e7770667d3..1b9a551063 100644 --- a/core/src/main/kotlin/net/corda/core/schemas/CommonSchema.kt +++ b/core/src/main/kotlin/net/corda/core/schemas/CommonSchema.kt @@ -54,7 +54,7 @@ object CommonSchemaV1 : MappedSchema(schemaFamily = CommonSchema.javaClass, vers /** [OwnableState] attributes */ /** X500Name of owner party **/ - @Column(name = "owner_name") + @Column(name = "owner_name", nullable = true) var owner: AbstractParty, /** [FungibleAsset] attributes @@ -64,16 +64,16 @@ object CommonSchemaV1 : MappedSchema(schemaFamily = CommonSchema.javaClass, vers */ /** Amount attributes */ - @Column(name = "quantity") + @Column(name = "quantity", nullable = false) var quantity: Long, /** Issuer attributes */ /** X500Name of issuer party **/ - @Column(name = "issuer_name") + @Column(name = "issuer_name", nullable = true) var issuer: AbstractParty, - @Column(name = "issuer_ref", length = MAX_ISSUER_REF_SIZE) + @Column(name = "issuer_ref", length = MAX_ISSUER_REF_SIZE, nullable = false) @Type(type = "corda-wrapper-binary") var issuerRef: ByteArray ) : PersistentState() diff --git a/core/src/main/kotlin/net/corda/core/schemas/PersistentTypes.kt b/core/src/main/kotlin/net/corda/core/schemas/PersistentTypes.kt index fbf9b3ccf9..986c7b3c26 100644 --- a/core/src/main/kotlin/net/corda/core/schemas/PersistentTypes.kt +++ b/core/src/main/kotlin/net/corda/core/schemas/PersistentTypes.kt @@ -57,11 +57,11 @@ open class MappedSchema(schemaFamily: Class<*>, */ @Embeddable data class PersistentStateRef( - @Column(name = "transaction_id", length = 64) - var txId: String? = null, + @Column(name = "transaction_id", length = 64, nullable = false) + var txId: String, - @Column(name = "output_index") - var index: Int? = null + @Column(name = "output_index", nullable = false) + var index: Int ) : Serializable { constructor(stateRef: StateRef) : this(stateRef.txhash.bytes.toHexString(), stateRef.index) } diff --git a/docs/source/changelog.rst b/docs/source/changelog.rst index 33766cabcf..af05243eb4 100644 --- a/docs/source/changelog.rst +++ b/docs/source/changelog.rst @@ -22,6 +22,12 @@ Unreleased * Fix CORDA-1229. Setter-based serialization was broken with generic types when the property was stored as the raw type, List for example. +* API change: ``net.corda.core.schemas.PersistentStateRef`` fields (index and txId) are now non-nullable. + The fields were always effectively non-nullable - values were set from non-nullable fields of other objects. + The class is used as database Primary Key columns of other entities and databases already impose those columns as non-nullable + (even if JPA annotation nullable=false was absent). + In case your Cordapps use this entity class to persist data in own custom tables as non Primary Key columns refer to :doc:`upgrade-notes` for upgrade instructions. + .. _changelog_v3.1: Version 3.1 @@ -44,6 +50,7 @@ Version 3.1 * Fixed node's behaviour on startup when there is no connectivity to network map. Node continues to work normally if it has all the needed network data, waiting in the background for network map to become available. + .. _changelog_v3: Version 3.0 diff --git a/docs/source/upgrade-notes.rst b/docs/source/upgrade-notes.rst index 7a26afcef8..1658fa99ac 100644 --- a/docs/source/upgrade-notes.rst +++ b/docs/source/upgrade-notes.rst @@ -28,6 +28,45 @@ versions you are currently using are still in force. We also strongly recommend cross referencing with the :doc:`changelog` to confirm changes. +UNRELEASED +---------- + +<<< Fill this in >>> + +* API change: ``net.corda.core.schemas.PersistentStateRef`` fields (``index`` and ``txId``) incorrectly marked as nullable are now non-nullable, + :doc:`changelog` contains the explanation. + + H2 database upgrade action: + + For Cordapps persisting custom entities with ``PersistentStateRef`` used as non Primary Key column, the backing table needs to be updated, + In SQL replace ``your_transaction_id``/``your_output_index`` column names with your custom names, if entity didn't used JPA ``@AttributeOverrides`` + then default names are ``transaction_id`` and ``output_index``. + + .. sourcecode:: sql + + SELECT count(*) FROM [YOUR_PersistentState_TABLE_NAME] WHERE your_transaction_id IS NULL OR your_output_index IS NULL; + + In case your table already contains rows with NULL columns, and the logic doesn't distinguish between NULL and an empty string, + all NULL column occurrences can be changed to an empty string: + + .. sourcecode:: sql + + UPDATE [YOUR_PersistentState_TABLE_NAME] SET your_transaction_id="" WHERE your_transaction_id IS NULL; + UPDATE [YOUR_PersistentState_TABLE_NAME] SET your_output_index="" WHERE your_output_index IS NULL; + + If all rows have NON NULL ``transaction_ids`` and ``output_idx`` or you have assigned empty string values, then it's safe to update the table: + + .. sourcecode:: sql + + ALTER TABLE [YOUR_PersistentState_TABLE_NAME] ALTER COLUMN your_transaction_id SET NOT NULL; + ALTER TABLE [YOUR_PersistentState_TABLE_NAME] ALTER COLUMN your_output_index SET NOT NULL; + + If the table already contains rows with NULL values, and the logic caters differently between NULL and an empty string, + and the logic has to be preserved you would need to create copy of ``PersistentStateRef`` class with different name and use the new class in your entity. + + No action is needed for default node tables as ``PersistentStateRef`` is used as Primary Key only and the backing columns are automatically not nullable + or custom Cordapp entities using ``PersistentStateRef`` as Primary Key. + v3.0 to v3.1 ------------ diff --git a/finance/src/main/kotlin/net/corda/finance/schemas/CashSchemaV1.kt b/finance/src/main/kotlin/net/corda/finance/schemas/CashSchemaV1.kt index 351dcc0c70..dfa936798c 100644 --- a/finance/src/main/kotlin/net/corda/finance/schemas/CashSchemaV1.kt +++ b/finance/src/main/kotlin/net/corda/finance/schemas/CashSchemaV1.kt @@ -26,19 +26,19 @@ object CashSchemaV1 : MappedSchema(schemaFamily = CashSchema.javaClass, version Index(name = "pennies_idx", columnList = "pennies"))) class PersistentCashState( /** X500Name of owner party **/ - @Column(name = "owner_name") + @Column(name = "owner_name", nullable = true) var owner: AbstractParty, - @Column(name = "pennies") + @Column(name = "pennies", nullable = false) var pennies: Long, - @Column(name = "ccy_code", length = 3) + @Column(name = "ccy_code", length = 3, nullable = false) var currency: String, - @Column(name = "issuer_key_hash", length = MAX_HASH_HEX_SIZE) + @Column(name = "issuer_key_hash", length = MAX_HASH_HEX_SIZE, nullable = false) var issuerPartyHash: String, - @Column(name = "issuer_ref", length = MAX_ISSUER_REF_SIZE) + @Column(name = "issuer_ref", length = MAX_ISSUER_REF_SIZE, nullable = false) @Type(type = "corda-wrapper-binary") var issuerRef: ByteArray ) : PersistentState() diff --git a/finance/src/main/kotlin/net/corda/finance/schemas/CommercialPaperSchemaV1.kt b/finance/src/main/kotlin/net/corda/finance/schemas/CommercialPaperSchemaV1.kt index 701630514c..e4b6d638d8 100644 --- a/finance/src/main/kotlin/net/corda/finance/schemas/CommercialPaperSchemaV1.kt +++ b/finance/src/main/kotlin/net/corda/finance/schemas/CommercialPaperSchemaV1.kt @@ -29,29 +29,29 @@ object CommercialPaperSchemaV1 : MappedSchema(schemaFamily = CommercialPaperSche Index(name = "maturity_index", columnList = "maturity_instant"), Index(name = "face_value_index", columnList = "face_value"))) class PersistentCommercialPaperState( - @Column(name = "issuance_key_hash", length = MAX_HASH_HEX_SIZE) + @Column(name = "issuance_key_hash", length = MAX_HASH_HEX_SIZE, nullable = false) var issuancePartyHash: String, - @Column(name = "issuance_ref") + @Column(name = "issuance_ref", nullable = false) @Type(type = "corda-wrapper-binary") var issuanceRef: ByteArray, - @Column(name = "owner_key_hash", length = MAX_HASH_HEX_SIZE) + @Column(name = "owner_key_hash", length = MAX_HASH_HEX_SIZE, nullable = false) var ownerHash: String, - @Column(name = "maturity_instant") + @Column(name = "maturity_instant", nullable = false) var maturity: Instant, - @Column(name = "face_value") + @Column(name = "face_value", nullable = false) var faceValue: Long, - @Column(name = "ccy_code", length = 3) + @Column(name = "ccy_code", length = 3, nullable = false) var currency: String, - @Column(name = "face_value_issuer_key_hash", length = MAX_HASH_HEX_SIZE) + @Column(name = "face_value_issuer_key_hash", length = MAX_HASH_HEX_SIZE, nullable = false) var faceValueIssuerPartyHash: String, - @Column(name = "face_value_issuer_ref", length = MAX_ISSUER_REF_SIZE) + @Column(name = "face_value_issuer_ref", length = MAX_ISSUER_REF_SIZE, nullable = false) @Type(type = "corda-wrapper-binary") var faceValueIssuerRef: ByteArray ) : PersistentState() diff --git a/finance/src/test/kotlin/net/corda/finance/contracts/CommercialPaperTests.kt b/finance/src/test/kotlin/net/corda/finance/contracts/CommercialPaperTests.kt index 93793659df..5c133b9020 100644 --- a/finance/src/test/kotlin/net/corda/finance/contracts/CommercialPaperTests.kt +++ b/finance/src/test/kotlin/net/corda/finance/contracts/CommercialPaperTests.kt @@ -244,7 +244,7 @@ class CommercialPaperTestsGeneric { // MegaCorp will issue some commercial paper and Alice will buy it, using cash issued to her in the name // of the dummy cash issuer. - val allIdentities = arrayOf(megaCorp.identity, miniCorp.identity, dummyCashIssuer.identity, dummyNotary.identity) + val allIdentities = arrayOf(megaCorp.identity, alice.identity, dummyCashIssuer.identity, dummyNotary.identity) val notaryServices = MockServices(dummyNotary) val issuerServices = MockServices(dummyCashIssuer, dummyNotary) val (aliceDatabase, aliceServices) = makeTestDatabaseAndMockServices( diff --git a/finance/src/test/kotlin/net/corda/finance/contracts/asset/CashTests.kt b/finance/src/test/kotlin/net/corda/finance/contracts/asset/CashTests.kt index a2fa76e92c..83faeb168f 100644 --- a/finance/src/test/kotlin/net/corda/finance/contracts/asset/CashTests.kt +++ b/finance/src/test/kotlin/net/corda/finance/contracts/asset/CashTests.kt @@ -82,10 +82,11 @@ class CashTests { LogHelper.setLevel(NodeVaultService::class) megaCorpServices = MockServices(megaCorp) miniCorpServices = MockServices(miniCorp) + val myself = TestIdentity(CordaX500Name("Me", "London", "GB")) val databaseAndServices = makeTestDatabaseAndMockServices( listOf("net.corda.finance.contracts.asset"), - makeTestIdentityService(megaCorp.identity, miniCorp.identity, dummyCashIssuer.identity, dummyNotary.identity), - TestIdentity(CordaX500Name("Me", "London", "GB")) + makeTestIdentityService(megaCorp.identity, miniCorp.identity, dummyCashIssuer.identity, dummyNotary.identity, myself.identity), + myself ) database = databaseAndServices.first ourServices = databaseAndServices.second diff --git a/finance/src/test/kotlin/net/corda/finance/schemas/SampleCashSchemaV1.kt b/finance/src/test/kotlin/net/corda/finance/schemas/SampleCashSchemaV1.kt index 7ac073621e..889ff48b62 100644 --- a/finance/src/test/kotlin/net/corda/finance/schemas/SampleCashSchemaV1.kt +++ b/finance/src/test/kotlin/net/corda/finance/schemas/SampleCashSchemaV1.kt @@ -21,23 +21,23 @@ object CashSchema */ object SampleCashSchemaV1 : MappedSchema(schemaFamily = CashSchema.javaClass, version = 1, mappedTypes = listOf(PersistentCashState::class.java)) { @Entity - @Table(name = "contract_cash_states", + @Table(name = "contract_cash_states_v1", indexes = arrayOf(Index(name = "ccy_code_idx", columnList = "ccy_code"), Index(name = "pennies_idx", columnList = "pennies"))) class PersistentCashState( - @Column(name = "owner_key_hash", length = MAX_HASH_HEX_SIZE) + @Column(name = "owner_key_hash", length = MAX_HASH_HEX_SIZE, nullable = false) var ownerHash: String, - @Column(name = "pennies") + @Column(name = "pennies", nullable = false) var pennies: Long, - @Column(name = "ccy_code", length = 3) + @Column(name = "ccy_code", length = 3, nullable = false) var currency: String, - @Column(name = "issuer_key_hash", length = MAX_HASH_HEX_SIZE) + @Column(name = "issuer_key_hash", length = MAX_HASH_HEX_SIZE, nullable = false) var issuerPartyHash: String, - @Column(name = "issuer_ref", length = MAX_ISSUER_REF_SIZE) + @Column(name = "issuer_ref", length = MAX_ISSUER_REF_SIZE, nullable = false) @Type(type = "corda-wrapper-binary") var issuerRef: ByteArray ) : PersistentState() diff --git a/finance/src/test/kotlin/net/corda/finance/schemas/SampleCashSchemaV2.kt b/finance/src/test/kotlin/net/corda/finance/schemas/SampleCashSchemaV2.kt index 7d893206c6..09cb2dab95 100644 --- a/finance/src/test/kotlin/net/corda/finance/schemas/SampleCashSchemaV2.kt +++ b/finance/src/test/kotlin/net/corda/finance/schemas/SampleCashSchemaV2.kt @@ -16,7 +16,7 @@ object SampleCashSchemaV2 : MappedSchema(schemaFamily = CashSchema.javaClass, ve indexes = arrayOf(Index(name = "ccy_code_idx2", columnList = "ccy_code"))) class PersistentCashState( /** product type */ - @Column(name = "ccy_code", length = 3) + @Column(name = "ccy_code", length = 3, nullable = false) var currency: String, participants: Set, owner: AbstractParty, @@ -26,7 +26,7 @@ object SampleCashSchemaV2 : MappedSchema(schemaFamily = CashSchema.javaClass, ve ) : CommonSchemaV1.FungibleState(participants.toMutableSet(), owner, quantity, issuerParty, issuerRef.bytes) { @ElementCollection - @Column(name = "participants") + @Column(name = "participants", nullable = true) @CollectionTable(name="cash_states_v2_participants", joinColumns = arrayOf( JoinColumn(name = "output_index", referencedColumnName = "output_index"), JoinColumn(name = "transaction_id", referencedColumnName = "transaction_id"))) diff --git a/finance/src/test/kotlin/net/corda/finance/schemas/SampleCashSchemaV3.kt b/finance/src/test/kotlin/net/corda/finance/schemas/SampleCashSchemaV3.kt index 0a6c0cc289..85a6c63de2 100644 --- a/finance/src/test/kotlin/net/corda/finance/schemas/SampleCashSchemaV3.kt +++ b/finance/src/test/kotlin/net/corda/finance/schemas/SampleCashSchemaV3.kt @@ -26,20 +26,20 @@ object SampleCashSchemaV3 : MappedSchema(schemaFamily = CashSchema.javaClass, ve var participants: MutableSet? = null, /** X500Name of owner party **/ - @Column(name = "owner_name") + @Column(name = "owner_name", nullable = true) var owner: AbstractParty, - @Column(name = "pennies") + @Column(name = "pennies", nullable = false) var pennies: Long, - @Column(name = "ccy_code", length = 3) + @Column(name = "ccy_code", length = 3, nullable = false) var currency: String, /** X500Name of issuer party **/ - @Column(name = "issuer_name") + @Column(name = "issuer_name", nullable = true) var issuer: AbstractParty, - @Column(name = "issuer_ref", length = MAX_ISSUER_REF_SIZE) + @Column(name = "issuer_ref", length = MAX_ISSUER_REF_SIZE, nullable = false) @Type(type = "corda-wrapper-binary") var issuerRef: ByteArray ) : PersistentState() diff --git a/finance/src/test/kotlin/net/corda/finance/schemas/SampleCommercialPaperSchemaV1.kt b/finance/src/test/kotlin/net/corda/finance/schemas/SampleCommercialPaperSchemaV1.kt index e3080952f4..16696571eb 100644 --- a/finance/src/test/kotlin/net/corda/finance/schemas/SampleCommercialPaperSchemaV1.kt +++ b/finance/src/test/kotlin/net/corda/finance/schemas/SampleCommercialPaperSchemaV1.kt @@ -27,29 +27,29 @@ object SampleCommercialPaperSchemaV1 : MappedSchema(schemaFamily = CommercialPap Index(name = "maturity_index", columnList = "maturity_instant"), Index(name = "face_value_index", columnList = "face_value"))) class PersistentCommercialPaperState( - @Column(name = "issuance_key_hash", length = MAX_HASH_HEX_SIZE) + @Column(name = "issuance_key_hash", length = MAX_HASH_HEX_SIZE, nullable = false) var issuancePartyHash: String, - @Column(name = "issuance_ref") + @Column(name = "issuance_ref", nullable = false) @Type(type = "corda-wrapper-binary") var issuanceRef: ByteArray, - @Column(name = "owner_key_hash", length = MAX_HASH_HEX_SIZE) + @Column(name = "owner_key_hash", length = MAX_HASH_HEX_SIZE, nullable = false) var ownerHash: String, - @Column(name = "maturity_instant") + @Column(name = "maturity_instant", nullable = false) var maturity: Instant, - @Column(name = "face_value") + @Column(name = "face_value", nullable = false) var faceValue: Long, - @Column(name = "ccy_code", length = 3) + @Column(name = "ccy_code", length = 3, nullable = false) var currency: String, - @Column(name = "face_value_issuer_key_hash", length = MAX_HASH_HEX_SIZE) + @Column(name = "face_value_issuer_key_hash", length = MAX_HASH_HEX_SIZE, nullable = false) var faceValueIssuerPartyHash: String, - @Column(name = "face_value_issuer_ref", length = MAX_ISSUER_REF_SIZE) + @Column(name = "face_value_issuer_ref", length = MAX_ISSUER_REF_SIZE, nullable = false) @Type(type = "corda-wrapper-binary") var faceValueIssuerRef: ByteArray ) : PersistentState() diff --git a/finance/src/test/kotlin/net/corda/finance/schemas/SampleCommercialPaperSchemaV2.kt b/finance/src/test/kotlin/net/corda/finance/schemas/SampleCommercialPaperSchemaV2.kt index 84a2547259..dd1357aa76 100644 --- a/finance/src/test/kotlin/net/corda/finance/schemas/SampleCommercialPaperSchemaV2.kt +++ b/finance/src/test/kotlin/net/corda/finance/schemas/SampleCommercialPaperSchemaV2.kt @@ -21,16 +21,16 @@ object SampleCommercialPaperSchemaV2 : MappedSchema(schemaFamily = CommercialPap indexes = arrayOf(Index(name = "ccy_code_index2", columnList = "ccy_code"), Index(name = "maturity_index2", columnList = "maturity_instant"))) class PersistentCommercialPaperState( - @Column(name = "maturity_instant") + @Column(name = "maturity_instant", nullable = false) var maturity: Instant, - @Column(name = "ccy_code", length = 3) + @Column(name = "ccy_code", length = 3, nullable = false) var currency: String, - @Column(name = "face_value_issuer_key_hash", length = MAX_HASH_HEX_SIZE) + @Column(name = "face_value_issuer_key_hash", length = MAX_HASH_HEX_SIZE, nullable = false) var faceValueIssuerPartyHash: String, - @Column(name = "face_value_issuer_ref", length = MAX_ISSUER_REF_SIZE) + @Column(name = "face_value_issuer_ref", length = MAX_ISSUER_REF_SIZE, nullable = false) @Type(type = "corda-wrapper-binary") var faceValueIssuerRef: ByteArray, diff --git a/node/src/integration-test/kotlin/net/corda/testMessage/MessageState.kt b/node/src/integration-test/kotlin/net/corda/testMessage/MessageState.kt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/node/src/main/kotlin/net/corda/node/internal/schemas/NodeInfoSchema.kt b/node/src/main/kotlin/net/corda/node/internal/schemas/NodeInfoSchema.kt index 3e0386b149..2d2d504d4c 100644 --- a/node/src/main/kotlin/net/corda/node/internal/schemas/NodeInfoSchema.kt +++ b/node/src/main/kotlin/net/corda/node/internal/schemas/NodeInfoSchema.kt @@ -25,25 +25,25 @@ object NodeInfoSchemaV1 : MappedSchema( class PersistentNodeInfo( @Id @GeneratedValue - @Column(name = "node_info_id") + @Column(name = "node_info_id", nullable = false) var id: Int, - @Column(name="node_info_hash", length = 64) + @Column(name = "node_info_hash", length = 64, nullable = false) val hash: String, - @Column(name = "addresses") + @Column(name = "addresses", nullable = false) @OneToMany(cascade = arrayOf(CascadeType.ALL), orphanRemoval = true) @JoinColumn(name = "node_info_id", foreignKey = ForeignKey(name = "FK__info_hosts__infos")) val addresses: List, - @Column(name = "legal_identities_certs") + @Column(name = "legal_identities_certs", nullable = false) @ManyToMany(cascade = arrayOf(CascadeType.ALL)) @JoinTable(name = "node_link_nodeinfo_party", joinColumns = arrayOf(JoinColumn(name = "node_info_id", foreignKey = ForeignKey(name = "FK__link_nodeinfo_party__infos"))), inverseJoinColumns = arrayOf(JoinColumn(name = "party_name", foreignKey = ForeignKey(name = "FK__link_ni_p__info_p_cert")))) val legalIdentitiesAndCerts: List, - @Column(name = "platform_version") + @Column(name = "platform_version", nullable = false) val platformVersion: Int, /** @@ -51,7 +51,7 @@ object NodeInfoSchemaV1 : MappedSchema( * Not expected to be sequential, but later versions of the registration must have higher values * Similar to the serial number on DNS records. */ - @Column(name = "serial") + @Column(name = "serial", nullable = false) val serial: Long ) : Serializable { fun toNodeInfo(): NodeInfo { @@ -69,7 +69,7 @@ object NodeInfoSchemaV1 : MappedSchema( data class DBHostAndPort( @Id @GeneratedValue - @Column(name = "hosts_id") + @Column(name = "hosts_id", nullable = false) var id: Int, val host: String? = null, val port: Int? = null @@ -95,11 +95,11 @@ object NodeInfoSchemaV1 : MappedSchema( @Column(name = "party_name", nullable = false) val name: String, - @Column(name = "owning_key_hash", length = MAX_HASH_HEX_SIZE) + @Column(name = "owning_key_hash", length = MAX_HASH_HEX_SIZE, nullable = false) val owningKeyHash: String, @Lob - @Column(name = "party_cert_binary") + @Column(name = "party_cert_binary", nullable = false) val partyCertBinary: ByteArray, diff --git a/node/src/main/kotlin/net/corda/node/services/events/NodeSchedulerService.kt b/node/src/main/kotlin/net/corda/node/services/events/NodeSchedulerService.kt index be5a44091a..4ca0384cc1 100644 --- a/node/src/main/kotlin/net/corda/node/services/events/NodeSchedulerService.kt +++ b/node/src/main/kotlin/net/corda/node/services/events/NodeSchedulerService.kt @@ -114,14 +114,13 @@ class NodeSchedulerService(private val clock: CordaClock, toPersistentEntityKey = { PersistentStateRef(it.txhash.toString(), it.index) }, fromPersistentEntity = { //TODO null check will become obsolete after making DB/JPA columns not nullable - val txId = it.output.txId ?: throw IllegalStateException("DB returned null SecureHash transactionId") - val index = it.output.index ?: throw IllegalStateException("DB returned null SecureHash index") + val txId = it.output.txId + val index = it.output.index Pair(StateRef(SecureHash.parse(txId), index), ScheduledStateRef(StateRef(SecureHash.parse(txId), index), it.scheduledAt)) }, toPersistentEntity = { key: StateRef, value: ScheduledStateRef -> - PersistentScheduledState().apply { - output = PersistentStateRef(key.txhash.toString(), key.index) + PersistentScheduledState(PersistentStateRef(key.txhash.toString(), key.index)).apply { scheduledAt = value.scheduledAt } }, @@ -152,7 +151,7 @@ class NodeSchedulerService(private val clock: CordaClock, @javax.persistence.Table(name = "${NODE_DATABASE_PREFIX}scheduled_states") class PersistentScheduledState( @EmbeddedId - var output: PersistentStateRef = PersistentStateRef(), + var output: PersistentStateRef, @Column(name = "scheduled_at", nullable = false) var scheduledAt: Instant = Instant.now() diff --git a/node/src/main/kotlin/net/corda/node/services/events/PersistentScheduledFlowRepository.kt b/node/src/main/kotlin/net/corda/node/services/events/PersistentScheduledFlowRepository.kt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/node/src/main/kotlin/net/corda/node/services/identity/PersistentIdentityService.kt b/node/src/main/kotlin/net/corda/node/services/identity/PersistentIdentityService.kt index a6fb506c86..eb525fb792 100644 --- a/node/src/main/kotlin/net/corda/node/services/identity/PersistentIdentityService.kt +++ b/node/src/main/kotlin/net/corda/node/services/identity/PersistentIdentityService.kt @@ -69,11 +69,11 @@ class PersistentIdentityService(override val trustRoot: X509Certificate, @javax.persistence.Table(name = "${NODE_DATABASE_PREFIX}identities") class PersistentIdentity( @Id - @Column(name = "pk_hash", length = MAX_HASH_HEX_SIZE) + @Column(name = "pk_hash", length = MAX_HASH_HEX_SIZE, nullable = false) var publicKeyHash: String = "", @Lob - @Column(name = "identity_value") + @Column(name = "identity_value", nullable = false) var identity: ByteArray = ByteArray(0) ) : Serializable @@ -81,10 +81,10 @@ class PersistentIdentityService(override val trustRoot: X509Certificate, @javax.persistence.Table(name = "${NODE_DATABASE_PREFIX}named_identities") class PersistentIdentityNames( @Id - @Column(name = "name", length = 128) + @Column(name = "name", length = 128, nullable = false) var name: String = "", - @Column(name = "pk_hash", length = MAX_HASH_HEX_SIZE) + @Column(name = "pk_hash", length = MAX_HASH_HEX_SIZE, nullable = false) var publicKeyHash: String = "" ) : Serializable diff --git a/node/src/main/kotlin/net/corda/node/services/keys/PersistentKeyManagementService.kt b/node/src/main/kotlin/net/corda/node/services/keys/PersistentKeyManagementService.kt index 6249a01212..0860e1443c 100644 --- a/node/src/main/kotlin/net/corda/node/services/keys/PersistentKeyManagementService.kt +++ b/node/src/main/kotlin/net/corda/node/services/keys/PersistentKeyManagementService.kt @@ -33,15 +33,15 @@ class PersistentKeyManagementService(val identityService: IdentityService, class PersistentKey( @Id - @Column(name = "public_key_hash", length = MAX_HASH_HEX_SIZE) + @Column(name = "public_key_hash", length = MAX_HASH_HEX_SIZE, nullable = false) var publicKeyHash: String, @Lob - @Column(name = "public_key") + @Column(name = "public_key", nullable = false) var publicKey: ByteArray = ByteArray(0), @Lob - @Column(name = "private_key") + @Column(name = "private_key", nullable = false) var privateKey: ByteArray = ByteArray(0) ) : Serializable { constructor(publicKey: PublicKey, privateKey: PrivateKey) diff --git a/node/src/main/kotlin/net/corda/node/services/messaging/P2PMessageDeduplicator.kt b/node/src/main/kotlin/net/corda/node/services/messaging/P2PMessageDeduplicator.kt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/node/src/main/kotlin/net/corda/node/services/messaging/P2PMessagingClient.kt b/node/src/main/kotlin/net/corda/node/services/messaging/P2PMessagingClient.kt index a2c3c61717..ac960379c2 100644 --- a/node/src/main/kotlin/net/corda/node/services/messaging/P2PMessagingClient.kt +++ b/node/src/main/kotlin/net/corda/node/services/messaging/P2PMessagingClient.kt @@ -202,15 +202,15 @@ class P2PMessagingClient(private val config: NodeConfiguration, @javax.persistence.Table(name = "${NODE_DATABASE_PREFIX}message_retry") class RetryMessage( @Id - @Column(name = "message_id", length = 64) + @Column(name = "message_id", length = 64, nullable = false) var key: Long = 0, @Lob - @Column + @Column(nullable = false) var message: ByteArray = ByteArray(0), @Lob - @Column + @Column(nullable = false) var recipients: ByteArray = ByteArray(0) ) : Serializable diff --git a/node/src/main/kotlin/net/corda/node/services/persistence/DBCheckpointStorage.kt b/node/src/main/kotlin/net/corda/node/services/persistence/DBCheckpointStorage.kt index 5c8b307bc0..15b3edba97 100644 --- a/node/src/main/kotlin/net/corda/node/services/persistence/DBCheckpointStorage.kt +++ b/node/src/main/kotlin/net/corda/node/services/persistence/DBCheckpointStorage.kt @@ -20,11 +20,11 @@ class DBCheckpointStorage : CheckpointStorage { @javax.persistence.Table(name = "${NODE_DATABASE_PREFIX}checkpoints") class DBCheckpoint( @Id - @Column(name = "checkpoint_id", length = 64) + @Column(name = "checkpoint_id", length = 64, nullable = false) var checkpointId: String = "", @Lob - @Column(name = "checkpoint_value") + @Column(name = "checkpoint_value", nullable = false) var checkpoint: ByteArray = ByteArray(0) ) : Serializable diff --git a/node/src/main/kotlin/net/corda/node/services/persistence/DBTransactionMappingStorage.kt b/node/src/main/kotlin/net/corda/node/services/persistence/DBTransactionMappingStorage.kt index 9e9137cf03..2825ada9af 100644 --- a/node/src/main/kotlin/net/corda/node/services/persistence/DBTransactionMappingStorage.kt +++ b/node/src/main/kotlin/net/corda/node/services/persistence/DBTransactionMappingStorage.kt @@ -29,10 +29,10 @@ class DBTransactionMappingStorage : StateMachineRecordedTransactionMappingStorag @javax.persistence.Table(name = "${NODE_DATABASE_PREFIX}transaction_mappings") class DBTransactionMapping( @Id - @Column(name = "tx_id", length = 64) + @Column(name = "tx_id", length = 64, nullable = false) var txId: String = "", - @Column(name = "state_machine_run_id", length = 36) + @Column(name = "state_machine_run_id", length = 36, nullable = false) var stateMachineRunId: String = "" ) : Serializable diff --git a/node/src/main/kotlin/net/corda/node/services/persistence/DBTransactionStorage.kt b/node/src/main/kotlin/net/corda/node/services/persistence/DBTransactionStorage.kt index 880047f765..6b420bf2a4 100644 --- a/node/src/main/kotlin/net/corda/node/services/persistence/DBTransactionStorage.kt +++ b/node/src/main/kotlin/net/corda/node/services/persistence/DBTransactionStorage.kt @@ -30,11 +30,11 @@ class DBTransactionStorage(cacheSizeBytes: Long) : WritableTransactionStorage, S @Table(name = "${NODE_DATABASE_PREFIX}transactions") class DBTransaction( @Id - @Column(name = "tx_id", length = 64) + @Column(name = "tx_id", length = 64, nullable = false) var txId: String = "", @Lob - @Column(name = "transaction_value") + @Column(name = "transaction_value", nullable = false) var transaction: ByteArray = ByteArray(0) ) : Serializable diff --git a/node/src/main/kotlin/net/corda/node/services/persistence/NodeAttachmentService.kt b/node/src/main/kotlin/net/corda/node/services/persistence/NodeAttachmentService.kt index 9593cfc634..86244e5596 100644 --- a/node/src/main/kotlin/net/corda/node/services/persistence/NodeAttachmentService.kt +++ b/node/src/main/kotlin/net/corda/node/services/persistence/NodeAttachmentService.kt @@ -75,24 +75,24 @@ class NodeAttachmentService( indexes = arrayOf(Index(name = "att_id_idx", columnList = "att_id"))) class DBAttachment( @Id - @Column(name = "att_id") + @Column(name = "att_id", nullable = false) var attId: String, - @Column(name = "content") + @Column(name = "content", nullable = false) @Lob var content: ByteArray, @Column(name = "insertion_date", nullable = false, updatable = false) var insertionDate: Instant = Instant.now(), - @Column(name = "uploader", updatable = false) + @Column(name = "uploader", updatable = false, nullable = true) var uploader: String? = null, - @Column(name = "filename", updatable = false) + @Column(name = "filename", updatable = false, nullable = true) var filename: String? = null, @ElementCollection - @Column(name = "contract_class_name") + @Column(name = "contract_class_name", nullable = false) @CollectionTable(name = "node_attchments_contracts", joinColumns = arrayOf( JoinColumn(name = "att_id", referencedColumnName = "att_id")), foreignKey = ForeignKey(name = "FK__ctr_class__attachments")) diff --git a/node/src/main/kotlin/net/corda/node/services/persistence/NodePropertiesPersistentStore.kt b/node/src/main/kotlin/net/corda/node/services/persistence/NodePropertiesPersistentStore.kt index 28a6aaab95..89039b5706 100644 --- a/node/src/main/kotlin/net/corda/node/services/persistence/NodePropertiesPersistentStore.kt +++ b/node/src/main/kotlin/net/corda/node/services/persistence/NodePropertiesPersistentStore.kt @@ -30,10 +30,10 @@ class NodePropertiesPersistentStore(readPhysicalNodeId: () -> String, persistenc @Table(name = "${NODE_DATABASE_PREFIX}properties") class DBNodeProperty( @Id - @Column(name = "property_key") + @Column(name = "property_key", nullable = false) val key: String = "", - @Column(name = "property_value") + @Column(name = "property_value", nullable = true) var value: String? = "" ) : Serializable } diff --git a/node/src/main/kotlin/net/corda/node/services/transactions/BFTNonValidatingNotaryService.kt b/node/src/main/kotlin/net/corda/node/services/transactions/BFTNonValidatingNotaryService.kt index 4602088edd..5aeac561c2 100644 --- a/node/src/main/kotlin/net/corda/node/services/transactions/BFTNonValidatingNotaryService.kt +++ b/node/src/main/kotlin/net/corda/node/services/transactions/BFTNonValidatingNotaryService.kt @@ -107,8 +107,8 @@ class BFTNonValidatingNotaryService( toPersistentEntityKey = { PersistentStateRef(it.txhash.toString(), it.index) }, fromPersistentEntity = { //TODO null check will become obsolete after making DB/JPA columns not nullable - val txId = it.id.txId ?: throw IllegalStateException("DB returned null SecureHash transactionId") - val index = it.id.index ?: throw IllegalStateException("DB returned null SecureHash index") + val txId = it.id.txId + val index = it.id.index Pair(StateRef(txhash = SecureHash.parse(txId), index = index), UniquenessProvider.ConsumingTx( id = SecureHash.parse(it.consumingTxHash), diff --git a/node/src/main/kotlin/net/corda/node/services/transactions/PersistentUniquenessProvider.kt b/node/src/main/kotlin/net/corda/node/services/transactions/PersistentUniquenessProvider.kt index 7fd3bf01a9..5f37b27ce0 100644 --- a/node/src/main/kotlin/net/corda/node/services/transactions/PersistentUniquenessProvider.kt +++ b/node/src/main/kotlin/net/corda/node/services/transactions/PersistentUniquenessProvider.kt @@ -29,12 +29,12 @@ class PersistentUniquenessProvider : UniquenessProvider, SingletonSerializeAsTok @MappedSuperclass open class PersistentUniqueness( @EmbeddedId - var id: PersistentStateRef = PersistentStateRef(), + var id: PersistentStateRef, - @Column(name = "consuming_transaction_id") + @Column(name = "consuming_transaction_id", nullable = false) var consumingTxHash: String = "", - @Column(name = "consuming_input_index", length = 36) + @Column(name = "consuming_input_index", length = 36, nullable = false) var consumingIndex: Int = 0, @Embedded @@ -43,10 +43,10 @@ class PersistentUniquenessProvider : UniquenessProvider, SingletonSerializeAsTok @Embeddable data class PersistentParty( - @Column(name = "requesting_party_name") + @Column(name = "requesting_party_name", nullable = false) var name: String = "", - @Column(name = "requesting_party_key", length = 255) + @Column(name = "requesting_party_key", length = 255, nullable = false) @Type(type = "corda-wrapper-binary") var owningKey: ByteArray = ByteArray(0) ) : Serializable @@ -71,8 +71,7 @@ class PersistentUniquenessProvider : UniquenessProvider, SingletonSerializeAsTok fromPersistentEntity = { //TODO null check will become obsolete after making DB/JPA columns not nullable val txId = it.id.txId - ?: throw IllegalStateException("DB returned null SecureHash transactionId") - val index = it.id.index ?: throw IllegalStateException("DB returned null SecureHash index") + val index = it.id.index Pair(StateRef(txhash = SecureHash.parse(txId), index = index), UniquenessProvider.ConsumingTx( id = SecureHash.parse(it.consumingTxHash), diff --git a/node/src/main/kotlin/net/corda/node/services/transactions/RaftUniquenessProvider.kt b/node/src/main/kotlin/net/corda/node/services/transactions/RaftUniquenessProvider.kt index 8a659e7621..1aa9bdca3b 100644 --- a/node/src/main/kotlin/net/corda/node/services/transactions/RaftUniquenessProvider.kt +++ b/node/src/main/kotlin/net/corda/node/services/transactions/RaftUniquenessProvider.kt @@ -75,14 +75,14 @@ class RaftUniquenessProvider(private val transportConfiguration: NodeSSLConfigur @Table(name = "${NODE_DATABASE_PREFIX}raft_committed_states") class RaftState( @Id - @Column(name = "id") + @Column(name = "id", nullable = false) var key: String = "", @Lob - @Column(name = "state_value") + @Column(name = "state_value", nullable = false) var value: ByteArray = ByteArray(0), - @Column(name = "state_index") + @Column(name = "state_index", nullable = false) var index: Long = 0 ) : Serializable diff --git a/node/src/main/kotlin/net/corda/node/services/upgrade/ContractUpgradeServiceImpl.kt b/node/src/main/kotlin/net/corda/node/services/upgrade/ContractUpgradeServiceImpl.kt index 68f0854770..f5ad410ea2 100644 --- a/node/src/main/kotlin/net/corda/node/services/upgrade/ContractUpgradeServiceImpl.kt +++ b/node/src/main/kotlin/net/corda/node/services/upgrade/ContractUpgradeServiceImpl.kt @@ -18,11 +18,11 @@ class ContractUpgradeServiceImpl : ContractUpgradeService, SingletonSerializeAsT @Table(name = "${NODE_DATABASE_PREFIX}contract_upgrades") class DBContractUpgrade( @Id - @Column(name = "state_ref", length = 96) + @Column(name = "state_ref", length = 96, nullable = false) var stateRef: String = "", /** refers to the UpgradedContract class name*/ - @Column(name = "contract_class_name") + @Column(name = "contract_class_name", nullable = false) var upgradedContractClassName: String = "" ) : Serializable diff --git a/node/src/main/kotlin/net/corda/node/services/vault/VaultSchema.kt b/node/src/main/kotlin/net/corda/node/services/vault/VaultSchema.kt index 5dceb42bab..a76237f4fe 100644 --- a/node/src/main/kotlin/net/corda/node/services/vault/VaultSchema.kt +++ b/node/src/main/kotlin/net/corda/node/services/vault/VaultSchema.kt @@ -36,19 +36,19 @@ object VaultSchemaV1 : MappedSchema(schemaFamily = VaultSchema.javaClass, versio // TODO: create a distinct table to hold serialized state data (once DBTransactionStore is encrypted) /** refers to the X500Name of the notary a state is attached to */ - @Column(name = "notary_name") + @Column(name = "notary_name", nullable = false) var notary: Party, /** references a concrete ContractState that is [QueryableState] and has a [MappedSchema] */ - @Column(name = "contract_state_class_name") + @Column(name = "contract_state_class_name", nullable = false) var contractStateClassName: String, /** state lifecycle: unconsumed, consumed */ - @Column(name = "state_status") + @Column(name = "state_status", nullable = false) var stateStatus: Vault.StateStatus, /** refers to timestamp recorded upon entering UNCONSUMED state */ - @Column(name = "recorded_timestamp") + @Column(name = "recorded_timestamp", nullable = false) var recordedTime: Instant, /** refers to timestamp recorded upon entering CONSUMED state */ @@ -87,7 +87,7 @@ object VaultSchemaV1 : MappedSchema(schemaFamily = VaultSchema.javaClass, versio /** * Represents a [LinearState] [UniqueIdentifier] */ - @Column(name = "external_id") + @Column(name = "external_id", nullable = true) var externalId: String?, @Column(name = "uuid", nullable = false) @@ -112,13 +112,13 @@ object VaultSchemaV1 : MappedSchema(schemaFamily = VaultSchema.javaClass, versio JoinColumn(name = "output_index", referencedColumnName = "output_index"), JoinColumn(name = "transaction_id", referencedColumnName = "transaction_id")), foreignKey = ForeignKey(name = "FK__fung_st_parts__fung_st")) - @Column(name = "participants") + @Column(name = "participants", nullable = true) var participants: MutableSet? = null, /** [OwnableState] attributes */ /** X500Name of owner party **/ - @Column(name = "owner_name") + @Column(name = "owner_name", nullable = true) var owner: AbstractParty, /** [FungibleAsset] attributes @@ -128,16 +128,16 @@ object VaultSchemaV1 : MappedSchema(schemaFamily = VaultSchema.javaClass, versio */ /** Amount attributes */ - @Column(name = "quantity") + @Column(name = "quantity", nullable = false) var quantity: Long, /** Issuer attributes */ /** X500Name of issuer party **/ - @Column(name = "issuer_name") + @Column(name = "issuer_name", nullable = true) var issuer: AbstractParty, - @Column(name = "issuer_ref", length = MAX_ISSUER_REF_SIZE) + @Column(name = "issuer_ref", length = MAX_ISSUER_REF_SIZE, nullable = false) @Type(type = "corda-wrapper-binary") var issuerRef: ByteArray ) : PersistentState() { @@ -156,13 +156,13 @@ object VaultSchemaV1 : MappedSchema(schemaFamily = VaultSchema.javaClass, versio class VaultTxnNote( @Id @GeneratedValue - @Column(name = "seq_no") + @Column(name = "seq_no", nullable = false) var seqNo: Int, - @Column(name = "transaction_id", length = 64) + @Column(name = "transaction_id", length = 64, nullable = false) var txId: String, - @Column(name = "note") + @Column(name = "note", nullable = false) var note: String ) : Serializable { constructor(txId: String, note: String) : this(0, txId, note) diff --git a/testing/test-utils/src/main/kotlin/net/corda/testing/internal/vault/DummyLinearStateSchemaV1.kt b/testing/test-utils/src/main/kotlin/net/corda/testing/internal/vault/DummyLinearStateSchemaV1.kt index d2ff099848..b271e98443 100644 --- a/testing/test-utils/src/main/kotlin/net/corda/testing/internal/vault/DummyLinearStateSchemaV1.kt +++ b/testing/test-utils/src/main/kotlin/net/corda/testing/internal/vault/DummyLinearStateSchemaV1.kt @@ -33,7 +33,7 @@ object DummyLinearStateSchemaV1 : MappedSchema(schemaFamily = DummyLinearStateSc /** * UniqueIdentifier */ - @Column(name = "external_id") + @Column(name = "external_id", nullable = true) var externalId: String?, @Column(name = "uuid", nullable = false) @@ -43,16 +43,16 @@ object DummyLinearStateSchemaV1 : MappedSchema(schemaFamily = DummyLinearStateSc /** * Dummy attributes */ - @Column(name = "linear_string") + @Column(name = "linear_string", nullable = false) var linearString: String, - @Column(name = "linear_number") + @Column(name = "linear_number", nullable = false) var linearNumber: Long, - @Column(name = "linear_timestamp") + @Column(name = "linear_timestamp", nullable = false) var linearTimestamp: Instant, - @Column(name = "linear_boolean") + @Column(name = "linear_boolean", nullable = false) var linearBoolean: Boolean ) : PersistentState() } diff --git a/testing/test-utils/src/main/kotlin/net/corda/testing/internal/vault/DummyLinearStateSchemaV2.kt b/testing/test-utils/src/main/kotlin/net/corda/testing/internal/vault/DummyLinearStateSchemaV2.kt index ea0feb4f63..78ac579e03 100644 --- a/testing/test-utils/src/main/kotlin/net/corda/testing/internal/vault/DummyLinearStateSchemaV2.kt +++ b/testing/test-utils/src/main/kotlin/net/corda/testing/internal/vault/DummyLinearStateSchemaV2.kt @@ -23,13 +23,13 @@ object DummyLinearStateSchemaV2 : MappedSchema(schemaFamily = DummyLinearStateSc JoinColumn(name = "transaction_id", referencedColumnName = "transaction_id"))) override var participants: MutableSet? = null, - @Column(name = "linear_string") var linearString: String, + @Column(name = "linear_string", nullable = false) var linearString: String, - @Column(name = "linear_number") var linearNumber: Long, + @Column(name = "linear_number", nullable = false) var linearNumber: Long, - @Column(name = "linear_timestamp") var linearTimestamp: java.time.Instant, + @Column(name = "linear_timestamp", nullable = false) var linearTimestamp: java.time.Instant, - @Column(name = "linear_boolean") var linearBoolean: Boolean, + @Column(name = "linear_boolean", nullable = false) var linearBoolean: Boolean, @Transient val uid: UniqueIdentifier