diff --git a/apps/app/src/main/scala/org/lfdecentralizedtrust/splice/console/LedgerApiExtensions.scala b/apps/app/src/main/scala/org/lfdecentralizedtrust/splice/console/LedgerApiExtensions.scala index a8579efaab..dd617907ba 100644 --- a/apps/app/src/main/scala/org/lfdecentralizedtrust/splice/console/LedgerApiExtensions.scala +++ b/apps/app/src/main/scala/org/lfdecentralizedtrust/splice/console/LedgerApiExtensions.scala @@ -404,7 +404,7 @@ trait LedgerApiExtensions extends AppendedClues with Matchers { predicate: TC => Boolean = (_: TC) => true, ): Seq[TC] = { val filterIdentifier = - PackageQualifiedName.getFromResources(templateCompanion.getTemplateIdWithPackageId) + PackageQualifiedName.fromJavaCodegenCompanion(templateCompanion) val templateId = TemplateId( s"#${filterIdentifier.packageName}", filterIdentifier.qualifiedName.moduleName, @@ -443,8 +443,7 @@ trait LedgerApiExtensions extends AppendedClues with Matchers { ](templateCompanion: javaapi.data.codegen.ContractCompanion[TC, TCid, T])( partyId: PartyId ): Seq[CreatedEvent] = { - val filterIdentifier = - PackageQualifiedName.getFromResources(templateCompanion.getTemplateIdWithPackageId) + val filterIdentifier = PackageQualifiedName.fromJavaCodegenCompanion(templateCompanion) val templateId = TemplateId( s"#${filterIdentifier.packageName}", filterIdentifier.qualifiedName.moduleName, diff --git a/apps/app/src/test/scala/org/lfdecentralizedtrust/splice/integration/tests/DecentralizedSynchronizerMigrationIntegrationTest.scala b/apps/app/src/test/scala/org/lfdecentralizedtrust/splice/integration/tests/DecentralizedSynchronizerMigrationIntegrationTest.scala index 9fe0cdca9a..9adf1b8903 100644 --- a/apps/app/src/test/scala/org/lfdecentralizedtrust/splice/integration/tests/DecentralizedSynchronizerMigrationIntegrationTest.scala +++ b/apps/app/src/test/scala/org/lfdecentralizedtrust/splice/integration/tests/DecentralizedSynchronizerMigrationIntegrationTest.scala @@ -1025,11 +1025,11 @@ class DecentralizedSynchronizerMigrationIntegrationTest pageSize = 1000, templates = Some( Vector( - DsoRules.TEMPLATE_ID_WITH_PACKAGE_ID, - AmuletRules.TEMPLATE_ID_WITH_PACKAGE_ID, - AnsRules.TEMPLATE_ID_WITH_PACKAGE_ID, + DsoRules.COMPANION, + AmuletRules.COMPANION, + AnsRules.COMPANION, ).map( - PackageQualifiedName.getFromResources(_) + PackageQualifiedName.fromJavaCodegenCompanion ) ), ) diff --git a/apps/app/src/test/scala/org/lfdecentralizedtrust/splice/integration/tests/ScanTimeBasedIntegrationTest.scala b/apps/app/src/test/scala/org/lfdecentralizedtrust/splice/integration/tests/ScanTimeBasedIntegrationTest.scala index c9aae37243..b6e1bec57d 100644 --- a/apps/app/src/test/scala/org/lfdecentralizedtrust/splice/integration/tests/ScanTimeBasedIntegrationTest.scala +++ b/apps/app/src/test/scala/org/lfdecentralizedtrust/splice/integration/tests/ScanTimeBasedIntegrationTest.scala @@ -510,8 +510,8 @@ class ScanTimeBasedIntegrationTest migrationId, templates = Some( Vector( - PackageQualifiedName.getFromResources(Amulet.TEMPLATE_ID_WITH_PACKAGE_ID), - PackageQualifiedName.getFromResources(AnsEntry.TEMPLATE_ID_WITH_PACKAGE_ID), + PackageQualifiedName.fromJavaCodegenCompanion(Amulet.COMPANION), + PackageQualifiedName.fromJavaCodegenCompanion(AnsEntry.COMPANION), ) ), partyIds = Some(Vector(aliceUserParty)), diff --git a/apps/common/src/main/resources/db/migration/canton-network/postgres/stable/V047__package_name_acs_stores.sql b/apps/common/src/main/resources/db/migration/canton-network/postgres/stable/V047__package_name_acs_stores.sql new file mode 100644 index 0000000000..9451d9b246 --- /dev/null +++ b/apps/common/src/main/resources/db/migration/canton-network/postgres/stable/V047__package_name_acs_stores.sql @@ -0,0 +1,363 @@ +-- truncates are not strictly necessary, but lets us define the constraint as mandatory afterwards, +-- and also makes index creation faster since there's no data to index +truncate table acs_store_template cascade; +truncate table user_wallet_acs_store cascade; +truncate table external_party_wallet_acs_store cascade; +truncate table validator_acs_store cascade; +truncate table sv_acs_store cascade; +truncate table dso_acs_store cascade; +truncate table scan_acs_store cascade; +truncate table splitwell_acs_store cascade; + +-- we just truncated the tables and there's no concurrent access while migrations are running, +-- so we can make the column not null. +-- All ACS store descriptors should be bumped in all stores to trigger reingestion. +alter table acs_store_template add column package_name text not null; +alter table user_wallet_acs_store add column package_name text not null; +alter table external_party_wallet_acs_store add column package_name text not null; +alter table validator_acs_store add column package_name text not null; +alter table sv_acs_store add column package_name text not null; +alter table dso_acs_store add column package_name text not null; +alter table scan_acs_store add column package_name text not null; +alter table splitwell_acs_store add column package_name text not null; + +-- index creation should be fast since all ACS stores have been truncated + +-- obtained with (unfortunately not all indexes are named consistently, so some require manual intervention) and IJ formatting: +-- select +-- 'DROP INDEX ' || (regexp_matches(indexdef, 'CREATE INDEX (.*) ON'))[1] || ';' || E'\n' +-- 'CREATE INDEX ' || replace((regexp_matches(indexdef, 'CREATE INDEX (.*) ON'))[1], 'tid', 'pn_tid') || ' ON ' || replace(replace(replace((regexp_matches(indexdef, 'CREATE INDEX (.*) ON (.*)'))[2], 'template_id_qualified_name', 'package_name, template_id_qualified_name'), 'public.', ''), 'USING btree', '') || ';' || E'\n' +-- from pg_indexes +-- where tablename like '%acs_store%' +-- and indexdef like '%template_id_qualified_name%'; +DROP INDEX acs_store_template_sid_mid_tid_ce; +CREATE INDEX acs_store_template_sid_mid_pn_tid_ce ON acs_store_template (store_id, migration_id, package_name, + template_id_qualified_name, + contract_expires_at) WHERE (contract_expires_at IS NOT NULL); + +DROP INDEX acs_store_template_sid_mid_tid_sn; +CREATE INDEX acs_store_template_sid_mid_pn_tid_sn ON acs_store_template (store_id, migration_id, package_name, + template_id_qualified_name, state_number); + +DROP INDEX user_wallet_acs_store_store_id_migration_id_template_id_qu_idx2; +CREATE INDEX user_wallet_acs_store_sid_mid_pn_tid_sn ON user_wallet_acs_store (store_id, + migration_id, + package_name, + template_id_qualified_name, + state_number); + +DROP INDEX user_wallet_acs_store_sid_mid_tid_rcr; +CREATE INDEX user_wallet_acs_store_sid_mid_pn_tid_rcr ON user_wallet_acs_store (store_id, migration_id, package_name, + template_id_qualified_name, + reward_coupon_round) WHERE (reward_coupon_round IS NOT NULL); + +DROP INDEX validator_acs_store_store_id_migration_id_template_id_qual_idx1; +CREATE INDEX validator_acs_store_sid_mid_pn_tid_exp ON validator_acs_store (store_id, + migration_id, + package_name, + template_id_qualified_name, + contract_expires_at) WHERE (contract_expires_at IS NOT NULL); + +DROP INDEX validator_acs_store_store_id_migration_id_template_id_qual_idx2; +CREATE INDEX validator_acs_store_sid_mid_pn_tid_sn ON validator_acs_store (store_id, + migration_id, + package_name, + template_id_qualified_name, + state_number); + +DROP INDEX validator_acs_store_sid_mid_tid_up; +CREATE INDEX validator_acs_store_sid_mid_pn_tid_up ON validator_acs_store (store_id, migration_id, package_name, + template_id_qualified_name, + user_party) WHERE (user_party IS NOT NULL); + +DROP INDEX validator_acs_store_sid_mid_tid_un; +CREATE INDEX validator_acs_store_sid_mid_pn_tid_un ON validator_acs_store (store_id, migration_id, package_name, + template_id_qualified_name, + user_name) WHERE (user_name IS NOT NULL); + +DROP INDEX validator_acs_store_sid_mid_tid_pp; +CREATE INDEX validator_acs_store_sid_mid_pn_tid_pp ON validator_acs_store (store_id, migration_id, package_name, + template_id_qualified_name, + provider_party) WHERE (provider_party IS NOT NULL); + +DROP INDEX validator_acs_store_sid_mid_tid_vp; +CREATE INDEX validator_acs_store_sid_mid_pn_tid_vp ON validator_acs_store (store_id, migration_id, package_name, + template_id_qualified_name, + validator_party) WHERE (validator_party IS NOT NULL); + +DROP INDEX validator_acs_store_sid_mid_tid_tdi; +CREATE INDEX validator_acs_store_sid_mid_pn_tid_tdi ON validator_acs_store (store_id, migration_id, package_name, + template_id_qualified_name, + traffic_domain_id) WHERE (traffic_domain_id IS NOT NULL); + +DROP INDEX sv_acs_store_sid_mid_tid_vocs; +CREATE INDEX sv_acs_store_sid_mid_pn_tid_vocs ON sv_acs_store (store_id, migration_id, package_name, + template_id_qualified_name, + onboarding_secret) WHERE (onboarding_secret IS NOT NULL); + +DROP INDEX sv_acs_store_sid_mid_tid_asicn; +CREATE INDEX sv_acs_store_sid_mid_pn_tid_asicn ON sv_acs_store (store_id, migration_id, package_name, + template_id_qualified_name, + sv_candidate_name) WHERE (sv_candidate_name IS NOT NULL); + +DROP INDEX acs_store_template_sid_mid_tid_en; +CREATE INDEX acs_store_template_sid_mid_pn_tid_en ON acs_store_template (store_id, migration_id, package_name, + template_id_qualified_name, event_number); + +DROP INDEX validator_acs_store_store_id_migration_id_template_id_quali_idx; +CREATE INDEX validator_acs_store_sid_mid_pn_tid_en ON validator_acs_store (store_id, + migration_id, + package_name, + template_id_qualified_name, + event_number); + +DROP INDEX user_wallet_acs_store_store_id_migration_id_template_id_qua_idx; +CREATE INDEX user_wallet_acs_store_sid_mid_pn_tid_en ON user_wallet_acs_store (store_id, + migration_id, + package_name, + template_id_qualified_name, + event_number); + +DROP INDEX user_wallet_acs_store_store_id_migration_id_template_id_qu_idx1; +CREATE INDEX user_wallet_acs_store_sid_mid_pn_tid_exp ON user_wallet_acs_store (store_id, + migration_id, + package_name, + template_id_qualified_name, + contract_expires_at) WHERE (contract_expires_at IS NOT NULL); + +DROP INDEX dso_acs_store_store_id_migration_id_template_id_qualified_n_idx; +CREATE INDEX dso_acs_store_sid_mid_pn_tid_en ON dso_acs_store (store_id, migration_id, + package_name, + template_id_qualified_name, + event_number); + +DROP INDEX dso_acs_store_store_id_migration_id_template_id_qualified__idx1; +CREATE INDEX dso_acs_store_sid_mid_pn_tid_exp ON dso_acs_store (store_id, migration_id, + package_name, + template_id_qualified_name, + contract_expires_at) WHERE (contract_expires_at IS NOT NULL); + +DROP INDEX sv_acs_store_store_id_migration_id_template_id_qualified_na_idx; +CREATE INDEX sv_acs_store_sid_mid_pn_tid_en ON sv_acs_store (store_id, migration_id, + package_name, + template_id_qualified_name, + event_number); + +DROP INDEX sv_acs_store_store_id_migration_id_template_id_qualified_n_idx1; +CREATE INDEX sv_acs_store_sid_mid_pn_tid_exp ON sv_acs_store (store_id, migration_id, + package_name, + template_id_qualified_name, + contract_expires_at) WHERE (contract_expires_at IS NOT NULL); + +DROP INDEX sv_acs_store_store_id_migration_id_template_id_qualified_n_idx2; +CREATE INDEX sv_acs_store_sid_mid_pn_tid_sn ON sv_acs_store (store_id, migration_id, + package_name, + template_id_qualified_name, + state_number); + +DROP INDEX dso_acs_store_store_id_migration_id_template_id_qualified__idx2; +CREATE INDEX dso_acs_store_sid_mid_pn_tid_sn ON dso_acs_store (store_id, migration_id, + package_name, + template_id_qualified_name, + state_number); + +DROP INDEX dso_acs_store_sid_tid_mr; +CREATE INDEX dso_acs_store_sid_pn_tid_mr ON dso_acs_store (store_id, migration_id, package_name, + template_id_qualified_name, + mining_round) WHERE (mining_round IS NOT NULL); + +DROP INDEX dso_acs_store_sid_tid_tcid; +CREATE INDEX dso_acs_store_sid_pn_tid_tcid ON dso_acs_store (store_id, migration_id, package_name, + template_id_qualified_name, + vote_request_tracking_cid) WHERE (vote_request_tracking_cid IS NOT NULL); + +DROP INDEX dso_acs_store_sid_tid_croe; +CREATE INDEX dso_acs_store_sid_pn_tid_croe ON dso_acs_store (store_id, migration_id, package_name, + template_id_qualified_name, + amulet_round_of_expiry) WHERE (amulet_round_of_expiry IS NOT NULL); + +DROP INDEX dso_acs_store_sid_tid_ah_c; +CREATE INDEX dso_acs_store_sid_pn_tid_ah_c ON dso_acs_store (store_id, migration_id, package_name, + template_id_qualified_name, action_requiring_confirmation, + confirmer) WHERE (action_requiring_confirmation IS NOT NULL); + +DROP INDEX dso_acs_store_coupons; +CREATE INDEX dso_acs_store_coupons ON dso_acs_store (store_id, migration_id, package_name, template_id_qualified_name, + reward_round, reward_party, + app_reward_is_featured) WHERE ((reward_round IS NOT NULL) AND (reward_party IS NOT NULL)); + +DROP INDEX dso_acs_store_sid_tid_sot; +CREATE INDEX dso_acs_store_sid_pn_tid_sot ON dso_acs_store (store_id, migration_id, package_name, + template_id_qualified_name, + sv_onboarding_token) WHERE (sv_onboarding_token IS NOT NULL); + +DROP INDEX dso_acs_store_sid_mid_tid_scp_scn; +CREATE INDEX dso_acs_store_sid_mid_pn_tid_scp_scn ON dso_acs_store (store_id, migration_id, package_name, + template_id_qualified_name, sv_candidate_party, + sv_candidate_name) WHERE (sv_candidate_party IS NOT NULL); + +DROP INDEX dso_acs_store_sid_mid_tid_scn; +CREATE INDEX dso_acs_store_sid_mid_pn_tid_scn ON dso_acs_store (store_id, migration_id, package_name, + template_id_qualified_name, + sv_candidate_name) WHERE (sv_candidate_name IS NOT NULL); + +DROP INDEX dso_acs_store_sid_mid_tid_v_tp; +CREATE INDEX dso_acs_store_sid_mid_pn_tid_v_tp ON dso_acs_store (store_id, migration_id, package_name, + template_id_qualified_name, validator, + total_traffic_purchased) WHERE (validator IS NOT NULL); + +DROP INDEX dso_acs_store_sid_mid_tid_ah_r; +CREATE INDEX dso_acs_store_sid_mid_pn_tid_ah_r ON dso_acs_store (store_id, migration_id, package_name, + template_id_qualified_name, + action_requiring_confirmation, + requester) WHERE (action_requiring_confirmation IS NOT NULL); + +DROP INDEX dso_acs_store_sid_mid_tid_ere_r; +CREATE INDEX dso_acs_store_sid_mid_pn_tid_ere_r ON dso_acs_store (store_id, migration_id, package_name, + template_id_qualified_name, election_request_epoch, + requester) WHERE ((election_request_epoch IS NOT NULL) AND (requester IS NOT NULL)); + +DROP INDEX dso_acs_store_sid_mid_tid_acecc; +CREATE INDEX dso_acs_store_sid_mid_pn_tid_acecc ON dso_acs_store (store_id, migration_id, package_name, + template_id_qualified_name, + action_ans_entry_context_cid) WHERE (action_ans_entry_context_cid IS NOT NULL); + +DROP INDEX dso_acs_store_sid_mid_tid_sccid; +CREATE INDEX dso_acs_store_sid_mid_pn_tid_sccid ON dso_acs_store (store_id, migration_id, package_name, + template_id_qualified_name, + subscription_reference_contract_id) WHERE (subscription_reference_contract_id IS NOT NULL); + +DROP INDEX dso_acs_store_sid_mid_tid_snpd; +CREATE INDEX dso_acs_store_sid_mid_pn_tid_snpd ON dso_acs_store (store_id, migration_id, package_name, + template_id_qualified_name, + subscription_next_payment_due_at) WHERE (subscription_next_payment_due_at IS NOT NULL); + +DROP INDEX scan_acs_store_store_id_migration_id_template_id_qualified__idx; +CREATE INDEX scan_acs_store_sid_mid_pn_tid_en ON scan_acs_store (store_id, migration_id, + package_name, + template_id_qualified_name, + event_number); + +DROP INDEX scan_acs_store_store_id_migration_id_template_id_qualified_idx1; +CREATE INDEX scan_acs_store_sid_mid_pn_tid_exp ON scan_acs_store (store_id, migration_id, + package_name, + template_id_qualified_name, + contract_expires_at) WHERE (contract_expires_at IS NOT NULL); + +DROP INDEX scan_acs_store_store_id_migration_id_template_id_qualified_idx2; +CREATE INDEX scan_acs_store_sid_mid_pn_tid_sn ON scan_acs_store (store_id, migration_id, + package_name, + template_id_qualified_name, + state_number); + +DROP INDEX scan_acs_store_sid_mid_tid_val; +CREATE INDEX scan_acs_store_sid_mid_pn_tid_val ON scan_acs_store (store_id, migration_id, package_name, + template_id_qualified_name, validator, + event_number) WHERE (validator IS NOT NULL); + +DROP INDEX scan_acs_store_sid_mid_tid_farp; +CREATE INDEX scan_acs_store_sid_mid_pn_tid_farp ON scan_acs_store (store_id, migration_id, package_name, + template_id_qualified_name, + featured_app_right_provider) WHERE (featured_app_right_provider IS NOT NULL); + +DROP INDEX scan_acs_store_sid_mid_tid_vlrc; +CREATE INDEX scan_acs_store_sid_mid_pn_tid_vlrc ON scan_acs_store (store_id, migration_id, package_name, + template_id_qualified_name, + validator_license_rounds_collected) WHERE (validator_license_rounds_collected IS NOT NULL); + +DROP INDEX scan_acs_store_sid_mid_tid_mtm_mtd; +CREATE INDEX scan_acs_store_sid_mid_pn_tid_mtm_mtd ON scan_acs_store (store_id, migration_id, package_name, + template_id_qualified_name, member_traffic_member, + member_traffic_domain) WHERE (member_traffic_member IS NOT NULL); + +DROP INDEX scan_acs_store_wallet_party_idx; +CREATE INDEX scan_acs_store_wallet_party_idx ON scan_acs_store (store_id, migration_id, package_name, + template_id_qualified_name, + wallet_party) WHERE (wallet_party IS NOT NULL); + +DROP INDEX splitwell_acs_store_store_id_migration_id_template_id_quali_idx; +CREATE INDEX splitwell_acs_store_sid_mid_pn_tid_en ON splitwell_acs_store (store_id, + migration_id, + package_name, + template_id_qualified_name, + event_number); + +DROP INDEX splitwell_acs_store_store_id_migration_id_template_id_qual_idx1; +CREATE INDEX splitwell_acs_store_sid_mid_pn_tid_exp ON splitwell_acs_store (store_id, + migration_id, + package_name, + template_id_qualified_name, + contract_expires_at) WHERE (contract_expires_at IS NOT NULL); + +DROP INDEX splitwell_acs_store_store_id_migration_id_template_id_qual_idx2; +CREATE INDEX splitwell_acs_store_sid_mid_pn_tid_sn ON splitwell_acs_store (store_id, + migration_id, + package_name, + template_id_qualified_name, + state_number); + +DROP INDEX dso_acs_store_sid_mid_tid_cen_exp; +CREATE INDEX dso_acs_store_sid_mid_pn_tid_cen_exp ON dso_acs_store (store_id, migration_id, package_name, + template_id_qualified_name, ans_entry_name, + contract_expires_at) WHERE ((ans_entry_name IS NOT NULL) AND (contract_expires_at IS NOT NULL)); + +DROP INDEX scan_acs_store_sid_mid_den_tpo_exp; +CREATE INDEX scan_acs_store_sid_mid_pn_tid_aen_tpo_exp ON scan_acs_store (store_id, migration_id, package_name, + template_id_qualified_name, ans_entry_name + text_pattern_ops, + contract_expires_at) WHERE ((ans_entry_name IS NOT NULL) AND (contract_expires_at IS NOT NULL)); + +DROP INDEX scan_acs_store_sid_mid_deo_den_exp; +CREATE INDEX scan_acs_store_sid_mid_deo_den_exp ON scan_acs_store (store_id, migration_id, package_name, + template_id_qualified_name, ans_entry_owner, + ans_entry_name, contract_expires_at) WHERE ( + (ans_entry_owner IS NOT NULL) AND (ans_entry_name IS NOT NULL) AND (contract_expires_at IS NOT NULL)); + +DROP INDEX scan_acs_store_sid_mid_tidqn_v; +CREATE INDEX scan_acs_store_sid_mid_pn_tid_v ON scan_acs_store (store_id, migration_id, package_name, + template_id_qualified_name, + validator) WHERE (validator IS NOT NULL); + +DROP INDEX user_wallet_acs_store_sid_mid_tid_rcv; +CREATE INDEX user_wallet_acs_store_sid_mid_pn_tid_rcv ON user_wallet_acs_store (store_id, migration_id, package_name, + template_id_qualified_name, + transfer_preapproval_receiver) WHERE (transfer_preapproval_receiver IS NOT NULL); + +DROP INDEX external_party_wallet_acs_sto_store_id_migration_id_templat_idx; +CREATE INDEX external_party_wallet_acs_store_sid_mid_pn_tid_en ON external_party_wallet_acs_store (store_id, + migration_id, + package_name, + template_id_qualified_name, + event_number); + +DROP INDEX external_party_wallet_acs_sto_store_id_migration_id_templa_idx1; +CREATE INDEX external_party_wallet_acs_sid_mid_pn_tid_exp ON external_party_wallet_acs_store (store_id, + migration_id, + package_name, + template_id_qualified_name, + contract_expires_at) WHERE (contract_expires_at IS NOT NULL); + +DROP INDEX external_party_wallet_acs_sto_store_id_migration_id_templa_idx2; +CREATE INDEX external_party_wallet_store_sid_mid_pn_tid_sn ON external_party_wallet_acs_store (store_id, + migration_id, + package_name, + template_id_qualified_name, + state_number); + +DROP INDEX external_party_wallet_acs_store_sid_mid_tid_rcr; +CREATE INDEX external_party_wallet_acs_store_sid_mid_pn_tid_rcr ON external_party_wallet_acs_store (store_id, + migration_id, + package_name, + template_id_qualified_name, + reward_coupon_round) WHERE (reward_coupon_round IS NOT NULL); + +DROP INDEX dso_acs_store_wallet_party_idx; +CREATE INDEX dso_acs_store_wallet_party_idx ON dso_acs_store (store_id, migration_id, package_name, + template_id_qualified_name, + wallet_party) WHERE (wallet_party IS NOT NULL); + +DROP INDEX dso_acs_store_sid_mid_tid_mtm_mtd; +CREATE INDEX dso_acs_store_sid_mid_pn_tid_mtm_mtd ON dso_acs_store (store_id, migration_id, package_name, + template_id_qualified_name, member_traffic_member, + member_traffic_domain) WHERE (member_traffic_member IS NOT NULL); + diff --git a/apps/common/src/main/scala/org/lfdecentralizedtrust/splice/store/DbVotesStoreQueryBuilder.scala b/apps/common/src/main/scala/org/lfdecentralizedtrust/splice/store/DbVotesStoreQueryBuilder.scala index 0adcb616a6..d088861420 100644 --- a/apps/common/src/main/scala/org/lfdecentralizedtrust/splice/store/DbVotesStoreQueryBuilder.scala +++ b/apps/common/src/main/scala/org/lfdecentralizedtrust/splice/store/DbVotesStoreQueryBuilder.scala @@ -11,7 +11,6 @@ import org.lfdecentralizedtrust.splice.codegen.java.splice.dsorules.VoteRequest import org.lfdecentralizedtrust.splice.store.db.AcsQueries.AcsStoreId import org.lfdecentralizedtrust.splice.store.db.TxLogQueries.TxLogStoreId import org.lfdecentralizedtrust.splice.store.db.{AcsQueries, TxLogQueries} -import org.lfdecentralizedtrust.splice.util.QualifiedName import slick.dbio.{Effect, NoStream} import slick.jdbc.canton.ActionBasedSQLInterpolation.Implicits.actionBasedSQLInterpolationCanton import slick.sql.SqlStreamingAction @@ -110,10 +109,8 @@ trait DbVotesAcsStoreQueryBuilder extends AcsQueries with LimitHelpers with Name acsTableName, acsStoreId, domainMigrationId, - where = (sql""" template_id_qualified_name = ${QualifiedName( - VoteRequest.TEMPLATE_ID_WITH_PACKAGE_ID - )} - and #$trackingCidColumnName in """ ++ voteRequestTrackingCidsSql).toActionBuilder, + VoteRequest.COMPANION, + where = (sql""" #$trackingCidColumnName in """ ++ voteRequestTrackingCidsSql).toActionBuilder, orderLimit = sql"""limit ${sqlLimit(limit)}""", ) } @@ -133,10 +130,8 @@ trait DbVotesAcsStoreQueryBuilder extends AcsQueries with LimitHelpers with Name acsTableName, acsStoreId, domainMigrationId, - where = (sql""" template_id_qualified_name = ${QualifiedName( - VoteRequest.TEMPLATE_ID_WITH_PACKAGE_ID - )} - and #$trackingCidColumnName = $voteRequestCid """).toActionBuilder, + VoteRequest.COMPANION, + where = (sql""" #$trackingCidColumnName = $voteRequestCid """).toActionBuilder, ).headOption } diff --git a/apps/common/src/main/scala/org/lfdecentralizedtrust/splice/store/MultiDomainAcsStore.scala b/apps/common/src/main/scala/org/lfdecentralizedtrust/splice/store/MultiDomainAcsStore.scala index 71d5fffd70..8a0776533b 100644 --- a/apps/common/src/main/scala/org/lfdecentralizedtrust/splice/store/MultiDomainAcsStore.scala +++ b/apps/common/src/main/scala/org/lfdecentralizedtrust/splice/store/MultiDomainAcsStore.scala @@ -6,7 +6,10 @@ package org.lfdecentralizedtrust.splice.store import org.apache.pekko.NotUsed import org.apache.pekko.stream.scaladsl.Source import com.daml.ledger.api.v2.transaction_filter.{EventFormat, CumulativeFilter} -import org.lfdecentralizedtrust.splice.util.Contract.Companion.Template as TemplateCompanion +import org.lfdecentralizedtrust.splice.util.Contract.Companion.{ + Interface, + Template as TemplateCompanion, +} import com.daml.ledger.javaapi.data.{CreatedEvent, ExercisedEvent, Identifier, Template} import com.daml.ledger.javaapi.data.codegen.{ContractId, DamlRecord} import com.daml.metrics.api.MetricsContext @@ -26,6 +29,7 @@ import org.lfdecentralizedtrust.splice.util.{ Contract, ContractWithState, PackageQualifiedName, + QualifiedName, TemplateJsonDecoder, } import org.lfdecentralizedtrust.splice.util.PrettyInstances.* @@ -171,22 +175,6 @@ trait MultiDomainAcsStore extends HasIngestionSink with AutoCloseable with Named traceContext: TraceContext, ): Future[Seq[Contract[TCid, T]]] - /** At most 1000 (`notOnDomainsTotalLimit`) contracts sorted by a hash of - * contract ID and participant ID. - * - * The idea is that different apps making the same migration on different - * participants will split the work better, while preserving determinism of a - * specific running app for fault-tolerance. For the former to happen, the - * position of a contract on one list must have no correlation with that on - * another list; that is why the contract ID by itself cannot be used by - * itself as the source of the sort key. - */ - def listAssignedContractsNotOnDomainN( - excludedDomain: SynchronizerId, - companions: Seq[ConstrainedTemplate], - limit: notOnDomainsTotalLimit.type = notOnDomainsTotalLimit, - )(implicit tc: TraceContext): Future[Seq[AssignedContract[?, ?]]] - private[splice] def listExpiredFromPayloadExpiry[C, TCid <: ContractId[T], T <: Template]( companion: C )(implicit @@ -470,7 +458,7 @@ object MultiDomainAcsStore extends StoreErrors { TemplateFilter[TCid, T, R], ) = ( - PackageQualifiedName.getFromResources(templateCompanion.getTemplateIdWithPackageId), + PackageQualifiedName.fromJavaCodegenCompanion(templateCompanion), TemplateFilter( ev => { val c = Contract.fromCreatedEvent(templateCompanion)(ev) @@ -597,6 +585,8 @@ object MultiDomainAcsStore extends StoreErrors { def typeId(companion: C): Identifier + def packageQualifiedName(companion: C): PackageQualifiedName + def toContractId(companion: C, contractId: String): TCid protected def fromJson( @@ -619,6 +609,13 @@ object MultiDomainAcsStore extends StoreErrors { override def typeId(companion: Contract.Companion.Template[TCid, T]): Identifier = companion.getTemplateIdWithPackageId + override def packageQualifiedName( + companion: TemplateCompanion[TCid, T] + ): PackageQualifiedName = PackageQualifiedName( + companion.PACKAGE_NAME, + QualifiedName(companion.getTemplateIdWithPackageId), + ) + override def toContractId(companion: Companion.Template[TCid, T], contractId: String): TCid = companion.toContractId(new ContractId[T](contractId)) @@ -652,6 +649,13 @@ object MultiDomainAcsStore extends StoreErrors { override def typeId(companion: Contract.Companion.Interface[ICid, Marker, View]): Identifier = companion.getTemplateIdWithPackageId + override def packageQualifiedName( + companion: Interface[ICid, Marker, View] + ): PackageQualifiedName = PackageQualifiedName( + companion.PACKAGE_NAME, + QualifiedName(companion.getTemplateIdWithPackageId), + ) + override def toContractId( companion: Companion.Interface[ICid, Marker, View], contractId: String, diff --git a/apps/common/src/main/scala/org/lfdecentralizedtrust/splice/store/db/AcsJdbcTypes.scala b/apps/common/src/main/scala/org/lfdecentralizedtrust/splice/store/db/AcsJdbcTypes.scala index 5b4afe8288..b3ba9f845f 100644 --- a/apps/common/src/main/scala/org/lfdecentralizedtrust/splice/store/db/AcsJdbcTypes.scala +++ b/apps/common/src/main/scala/org/lfdecentralizedtrust/splice/store/db/AcsJdbcTypes.scala @@ -218,6 +218,11 @@ trait AcsJdbcTypes { protected implicit val qualifiedNameGetResult: GetResult[QualifiedName] = GetResult.GetString.andThen { s => QualifiedName.assertFromString(s) } + protected implicit val packageQualifiedNameGetResult: GetResult[PackageQualifiedName] = + implicitly[GetResult[(QualifiedName, String)]].andThen { case (qualifiedName, packageName) => + PackageQualifiedName(packageName, qualifiedName) + } + protected implicit lazy val qualifiedNameJdbcType: JdbcType[QualifiedName] = MappedColumnType.base[QualifiedName, String]( { _.toString }, { diff --git a/apps/common/src/main/scala/org/lfdecentralizedtrust/splice/store/db/AcsQueries.scala b/apps/common/src/main/scala/org/lfdecentralizedtrust/splice/store/db/AcsQueries.scala index 3fba4eb1d7..a58c2b054e 100644 --- a/apps/common/src/main/scala/org/lfdecentralizedtrust/splice/store/db/AcsQueries.scala +++ b/apps/common/src/main/scala/org/lfdecentralizedtrust/splice/store/db/AcsQueries.scala @@ -26,24 +26,33 @@ import scalaz.{@@, Tag} import slick.jdbc.canton.ActionBasedSQLInterpolation.Implicits.actionBasedSQLInterpolationCanton import slick.jdbc.canton.SQLActionBuilder import slick.jdbc.{GetResult, PositionedResult, SetParameter} +import slick.dbio.Effect +import slick.sql.SqlStreamingAction trait AcsQueries extends AcsJdbcTypes { /** @param tableName Must be SQL-safe, as it needs to be interpolated unsafely. * This is fine, as all calls to this method should use static string constants. */ - protected def selectFromAcsTable( + protected def selectFromAcsTable[C, TCid <: ContractId[_], T]( tableName: String, storeId: AcsStoreId, migrationId: Long, - where: SQLActionBuilder, + companion: C, + where: SQLActionBuilder = sql"true", orderLimit: SQLActionBuilder = sql"", - ) = + )(implicit companionClass: ContractCompanion[C, TCid, T]) = { + val packageQualifiedName = companionClass.packageQualifiedName(companion) (sql""" select #${SelectFromAcsTableResult.sqlColumnsCommaSeparated()} from #$tableName acs - where acs.store_id = $storeId and acs.migration_id = $migrationId and """ ++ where ++ sql""" + where acs.store_id = $storeId + and acs.migration_id = $migrationId + and acs.package_name = ${packageQualifiedName.packageName} + and acs.template_id_qualified_name = ${packageQualifiedName.qualifiedName} + and """ ++ where ++ sql""" """ ++ orderLimit).toActionBuilder.as[AcsQueries.SelectFromAcsTableResult] + } implicit val GetResultSelectFromAcsTable: GetResult[AcsQueries.SelectFromAcsTableResult] = GetResult { prs => @@ -55,7 +64,7 @@ trait AcsQueries extends AcsJdbcTypes { <<[Long], <<[ContractId[Any]], <<[String], - <<[QualifiedName], + <<[PackageQualifiedName], <<[Json], <<[Array[Byte]], <<[Timestamp], @@ -65,18 +74,27 @@ trait AcsQueries extends AcsJdbcTypes { } /** Similar to [[selectFromAcsTable]], but also returns the contract state (i.e., the domain to which a contract is currently assigned) */ - protected def selectFromAcsTableWithState( + protected def selectFromAcsTableWithState[C, TCid <: ContractId[_], T]( tableName: String, storeId: AcsStoreId, migrationId: Long, - where: SQLActionBuilder, + companion: C, + additionalWhere: SQLActionBuilder = sql"", orderLimit: SQLActionBuilder = sql"", - ) = + )(implicit companionClass: ContractCompanion[C, TCid, T]): SqlStreamingAction[Vector[ + SelectFromAcsTableWithStateResult + ], SelectFromAcsTableWithStateResult, Effect.Read] = { + val packageQualifiedName = companionClass.packageQualifiedName(companion) (sql""" select #${SelectFromAcsTableWithStateResult.sqlColumnsCommaSeparated()} from #$tableName acs - where acs.store_id = $storeId and acs.migration_id = $migrationId and """ ++ where ++ sql""" + where acs.store_id = $storeId + and acs.migration_id = $migrationId + and acs.package_name = ${packageQualifiedName.packageName} + and acs.template_id_qualified_name = ${packageQualifiedName.qualifiedName} + """ ++ additionalWhere ++ sql""" """ ++ orderLimit).toActionBuilder.as[AcsQueries.SelectFromAcsTableWithStateResult] + } implicit val GetResultSelectFromContractStateResult : GetResult[AcsQueries.SelectFromContractStateResult] = @@ -104,13 +122,15 @@ trait AcsQueries extends AcsJdbcTypes { * This guarantees that the fetched contracts exist in the given offset, * whereas two separate queries (one to fetch the contract and one to fetch the offset) don't guarantee that. */ - protected def selectFromAcsTableWithOffset( + protected def selectFromAcsTableWithOffset[C, TCid <: ContractId[_], T]( tableName: String, storeId: AcsStoreId, migrationId: Long, + companion: C, where: SQLActionBuilder, orderLimit: SQLActionBuilder = sql"", - ) = + )(implicit companionClass: ContractCompanion[C, TCid, T]) = { + val packageQualifiedName = companionClass.packageQualifiedName(companion) (sql""" select acs.store_id, @@ -120,6 +140,7 @@ trait AcsQueries extends AcsJdbcTypes { contract_id, template_id_package_id, template_id_qualified_name, + package_name, create_arguments, created_event_blob, created_at, @@ -130,10 +151,13 @@ trait AcsQueries extends AcsJdbcTypes { left join #$tableName acs on o.store_id = acs.store_id and o.migration_id = acs.migration_id + and acs.package_name = ${packageQualifiedName.packageName} + and acs.template_id_qualified_name = ${packageQualifiedName.qualifiedName} and """ ++ where ++ sql""" where sd.id = $storeId and o.migration_id = $migrationId """ ++ orderLimit).toActionBuilder .as[AcsQueries.SelectFromAcsTableResultWithOffset] + } implicit val GetResultSelectFromAcsTableResultWithOffset : GetResult[AcsQueries.SelectFromAcsTableResultWithOffset] = { (pp: PositionedResult) => @@ -161,13 +185,15 @@ trait AcsQueries extends AcsJdbcTypes { /** Same as [[selectFromAcsTableWithOffset]], but also includes the contract state. */ - protected def selectFromAcsTableWithStateAndOffset( + protected def selectFromAcsTableWithStateAndOffset[C, TCid <: ContractId[_], T]( tableName: String, storeId: AcsStoreId, migrationId: Long, + companion: C, where: SQLActionBuilder = sql"true", orderLimit: SQLActionBuilder = sql"", - ) = + )(implicit companionClass: ContractCompanion[C, TCid, T]) = { + val packageQualifiedName = companionClass.packageQualifiedName(companion) (sql""" select acs.store_id, @@ -177,6 +203,7 @@ trait AcsQueries extends AcsJdbcTypes { acs.contract_id, acs.template_id_package_id, acs.template_id_qualified_name, + acs.package_name, acs.create_arguments, acs.created_event_blob, acs.created_at, @@ -194,10 +221,13 @@ trait AcsQueries extends AcsJdbcTypes { left join #$tableName acs on o.store_id = acs.store_id and o.migration_id = acs.migration_id + and acs.package_name = ${packageQualifiedName.packageName} + and acs.template_id_qualified_name = ${packageQualifiedName.qualifiedName} and """ ++ where ++ sql""" where sd.id = $storeId and o.migration_id = $migrationId """ ++ orderLimit).toActionBuilder .as[AcsQueries.SelectFromAcsTableResultWithStateAndOffset] + } implicit val GetResultSelectFromAcsTableResultWithStateOffset : GetResult[AcsQueries.SelectFromAcsTableResultWithStateAndOffset] = { @@ -311,7 +341,7 @@ object AcsQueries { eventNumber: Long, contractId: ContractId[Any], templateIdPackageId: String, - templateIdQualifiedName: QualifiedName, + packageQualifiedName: PackageQualifiedName, createArguments: Json, createdEventBlob: Array[Byte], createdAt: Timestamp, @@ -321,12 +351,22 @@ object AcsQueries { companionClass: ContractCompanion[C, TCId, T], decoder: TemplateJsonDecoder, ): Contract[TCId, T] = { + // safety check: if the PackageQualifiedNames don't match, + // it means that we would be returning a contract of a different template + // note that the packageId not matching is expected due to upgrades, but the name will be stable + val expectedPackageQualifiedName = companionClass.packageQualifiedName(companion) + if (expectedPackageQualifiedName != packageQualifiedName) { + throw new IllegalStateException( + s"Contract $contractId has a different package qualified name than expected. Expected: $expectedPackageQualifiedName - Got: $packageQualifiedName" + ) + } + companionClass .fromJson(companion)( new Identifier( templateIdPackageId, - templateIdQualifiedName.moduleName, - templateIdQualifiedName.entityName, + packageQualifiedName.qualifiedName.moduleName, + packageQualifiedName.qualifiedName.entityName, ), contractId.contractId, createArguments, @@ -351,6 +391,7 @@ object AcsQueries { ${qualifier}contract_id, ${qualifier}template_id_package_id, ${qualifier}template_id_qualified_name, + ${qualifier}package_name, ${qualifier}create_arguments, ${qualifier}created_event_blob, ${qualifier}created_at, diff --git a/apps/common/src/main/scala/org/lfdecentralizedtrust/splice/store/db/DbAppStore.scala b/apps/common/src/main/scala/org/lfdecentralizedtrust/splice/store/db/DbAppStore.scala index 3a6de14bac..126c1a147f 100644 --- a/apps/common/src/main/scala/org/lfdecentralizedtrust/splice/store/db/DbAppStore.scala +++ b/apps/common/src/main/scala/org/lfdecentralizedtrust/splice/store/db/DbAppStore.scala @@ -58,7 +58,6 @@ abstract class DbTxLogAppStore[TXE]( acsContractFilter, txLogConfig, domainMigrationInfo, - participantId, retryProvider, handleIngestionSummary, ) @@ -98,7 +97,6 @@ abstract class DbAppStore( acsContractFilter, TxLogStore.Config.empty, domainMigrationInfo, - participantId, retryProvider, handleIngestionSummary, ) diff --git a/apps/common/src/main/scala/org/lfdecentralizedtrust/splice/store/db/DbMultiDomainAcsStore.scala b/apps/common/src/main/scala/org/lfdecentralizedtrust/splice/store/db/DbMultiDomainAcsStore.scala index 8576721c44..4182191bf0 100644 --- a/apps/common/src/main/scala/org/lfdecentralizedtrust/splice/store/db/DbMultiDomainAcsStore.scala +++ b/apps/common/src/main/scala/org/lfdecentralizedtrust/splice/store/db/DbMultiDomainAcsStore.scala @@ -88,7 +88,6 @@ final class DbMultiDomainAcsStore[TXE]( ], txLogConfig: TxLogStore.Config[TXE], domainMigrationInfo: DomainMigrationInfo, - participantId: ParticipantId, retryProvider: RetryProvider, /** Allows processing the summary in a store-specific manner, e.g., to produce metrics * on ingestion of certain contracts. @@ -175,7 +174,8 @@ final class DbMultiDomainAcsStore[TXE]( acsTableName, acsStoreId, domainMigrationId, - where = sql"""acs.contract_id = ${lengthLimited(id.contractId)}""", + companion, + additionalWhere = sql"""and acs.contract_id = ${lengthLimited(id.contractId)}""", ).headOption, "lookupContractById", ) @@ -189,7 +189,6 @@ final class DbMultiDomainAcsStore[TXE]( companionClass: ContractCompanion[C, TCid, T], traceContext: TraceContext, ): Future[QueryResult[Option[ContractWithState[TCid, T]]]] = waitUntilAcsIngested { - val templateId = companionClass.typeId(companion) for { resultWithOffset <- storage .querySingle( @@ -197,7 +196,7 @@ final class DbMultiDomainAcsStore[TXE]( acsTableName, acsStoreId, domainMigrationId, - where = sql"""template_id_qualified_name = ${QualifiedName(templateId)}""", + companion, orderLimit = sql"limit 1", ).headOption, "findAnyContractWithOffset", @@ -217,12 +216,14 @@ final class DbMultiDomainAcsStore[TXE]( ): Future[Option[ContractState]] = waitUntilAcsIngested { storage .querySingle( // index: acs_store_template_sid_mid_cid - selectFromAcsTableWithState( - acsTableName, - acsStoreId, - domainMigrationId, - where = sql"""acs.contract_id = ${lengthLimited(id.contractId)}""", - ).headOption, + (sql""" + select #${SelectFromAcsTableWithStateResult.sqlColumnsCommaSeparated()} + from #$acsTableName acs + where acs.store_id = $acsStoreId + and acs.migration_id = $domainMigrationId + and acs.contract_id = ${lengthLimited(id.contractId)}""").toActionBuilder + .as[AcsQueries.SelectFromAcsTableWithStateResult] + .headOption, "lookupContractStateById", ) .map(result => contractStateFromRow(result.stateRow)) @@ -278,15 +279,15 @@ final class DbMultiDomainAcsStore[TXE]( val opName = s"listContracts:${templateId.getEntityName}" val afterCondition = after.fold(sql"")(a => (sql" and " ++ sortOrder.whereEventNumber(a)).toActionBuilder) + for { result <- storage.query( // index: acs_store_template_sid_mid_tid_en selectFromAcsTableWithState( acsTableName, acsStoreId, domainMigrationId, - where = (sql"""template_id_qualified_name = ${QualifiedName( - templateId - )} """ ++ afterCondition).toActionBuilder, + companion, + additionalWhere = afterCondition, orderLimit = (sortOrder.orderByAcsEventNumber ++ sql""" limit ${sqlLimit(limit)}""").toActionBuilder, ), @@ -312,12 +313,11 @@ final class DbMultiDomainAcsStore[TXE]( acsTableName, acsStoreId, domainMigrationId, - where = sql"""template_id_qualified_name = ${QualifiedName( - templateId - )} and assigned_domain is not null""", + companion, + additionalWhere = sql"""and assigned_domain is not null""", orderLimit = sql"""order by event_number limit ${sqlLimit(limit)}""", ), - "listAssignedContracts", + s"listAssignedContracts:$templateId", ) limited = applyLimit("listAssignedContracts", limit, result) assigned = limited.map(assignedContractFromRow(companion)(_)) @@ -329,7 +329,6 @@ final class DbMultiDomainAcsStore[TXE]( ], T <: Template](companion: C)(implicit companionClass: ContractCompanion[C, TCid, T] ): ListExpiredContracts[TCid, T] = { (now, limit) => implicit traceContext => - val templateId = companionClass.typeId(companion) for { _ <- waitUntilAcsIngested() result <- storage @@ -338,9 +337,8 @@ final class DbMultiDomainAcsStore[TXE]( acsTableName, acsStoreId, domainMigrationId, - where = sql"""template_id_qualified_name = ${QualifiedName( - templateId - )} and acs.contract_expires_at < $now""", + companion, + additionalWhere = sql"""and acs.contract_expires_at < $now""", orderLimit = sql"""limit ${sqlLimit(limit)}""", ), "listExpiredFromPayloadExpiry", @@ -358,16 +356,14 @@ final class DbMultiDomainAcsStore[TXE]( companionClass: ContractCompanion[C, TCid, T], traceContext: TraceContext, ): Future[Seq[Contract[TCid, T]]] = waitUntilAcsIngested { - val templateId = companionClass.typeId(companion) for { result <- storage.query( selectFromAcsTableWithState( acsTableName, acsStoreId, domainMigrationId, - where = sql"""template_id_qualified_name = ${QualifiedName( - templateId - )} and assigned_domain = $domain""", + companion, + additionalWhere = sql"""and assigned_domain = $domain""", orderLimit = sql"""limit ${sqlLimit(limit)}""", ), "listContractsOnDomain", @@ -377,50 +373,16 @@ final class DbMultiDomainAcsStore[TXE]( } yield contracts } - override def listAssignedContractsNotOnDomainN( - excludedDomain: SynchronizerId, - companions: Seq[ConstrainedTemplate], - limit: notOnDomainsTotalLimit.type, - )(implicit tc: TraceContext): Future[Seq[AssignedContract[?, ?]]] = waitUntilAcsIngested { - val templateIdMap = companions - .map(c => QualifiedName(c.getTemplateIdWithPackageId) -> c) - .toMap - val templateIds = inClause(templateIdMap.keys) - for { - result <- storage.query( - selectFromAcsTableWithState( - acsTableName, - acsStoreId, - domainMigrationId, - where = - (sql"""template_id_qualified_name IN """ ++ templateIds ++ sql""" and assigned_domain is not null and assigned_domain != $excludedDomain""").toActionBuilder, - // bytea comparison in PG is left-to-right unsigned ascending, shorter - // array is lesser if bytes are otherwise equal; there's an equivalent - // soft implementation in - // InMemoryMultiDomainAcsStore.reassignmentContractOrder - orderLimit = - sql"""order by extensions.digest((contract_id || $participantId)::bytea, 'md5'::text) - limit ${(limit: PageLimit).limit}""", - ), - "listAssignedContractsNotOnDomainN", - ) - } yield result.map { row => - assignedContractFromRow( - templateIdMap(row.acsRow.templateIdQualifiedName) - )(row) - } - } - override def streamAssignedContracts[C, TCid <: ContractId[_], T](companion: C)(implicit companionClass: ContractCompanion[C, TCid, T], traceContext: TraceContext, ): Source[AssignedContract[TCid, T], NotUsed] = { - val templateId = companionClass.typeId(companion) + val packageQualifiedName = companionClass.packageQualifiedName(companion) streamContractsWithState( pageSize = defaultPageSizeForContractStream, - where = sql"""assigned_domain is not null and template_id_qualified_name = ${QualifiedName( - templateId - )}""", + where = sql"""assigned_domain is not null + and package_name = ${packageQualifiedName.packageName} + and template_id_qualified_name = ${packageQualifiedName.qualifiedName}""", ) .map(assignedContractFromRow(companion)(_)) } @@ -695,14 +657,15 @@ final class DbMultiDomainAcsStore[TXE]( val offsetPromise = state.get().offsetChanged storage .query( - selectFromAcsTableWithState( - acsTableName, - acsStoreId, - domainMigrationId, - where = (where ++ sql" and state_number >= $fromNumber").toActionBuilder, - orderLimit = - (sql"order by state_number limit ${sqlLimit(pageSize)}").toActionBuilder, - ), + (sql""" + select #${SelectFromAcsTableWithStateResult.sqlColumnsCommaSeparated()} + from #$acsTableName acs + where acs.store_id = $acsStoreId + and acs.migration_id = $domainMigrationId + and state_number >= $fromNumber + and """ ++ where ++ sql""" + order by state_number limit ${sqlLimit(pageSize)}""").toActionBuilder + .as[AcsQueries.SelectFromAcsTableWithStateResult], "streamContractsWithState", ) .flatMap { rows => @@ -741,12 +704,14 @@ final class DbMultiDomainAcsStore[TXE]( waitUntilAcsIngested { storage .querySingle( - selectFromAcsTableWithState( - acsTableName, - acsStoreId, - domainMigrationId, - where = sql"""acs.contract_id = ${contractId}""", - ).headOption, + (sql""" + select #${SelectFromAcsTableWithStateResult.sqlColumnsCommaSeparated()} + from #$acsTableName acs + where acs.store_id = $acsStoreId + and acs.migration_id = $domainMigrationId + and acs.contract_id = $contractId""").toActionBuilder + .as[AcsQueries.SelectFromAcsTableWithStateResult] + .headOption, "isReadyForAssign", ) .value @@ -1652,6 +1617,7 @@ final class DbMultiDomainAcsStore[TXE]( val templateId = rowData.identifier val templateIdQualifiedName = QualifiedName(templateId) val templateIdPackageId = lengthLimited(rowData.identifier.getPackageId) + val packageName = createdEvent.getPackageName val createArguments = rowData.payload val createdAt = Timestamp.assertFromInstant(rowData.createdAt) val contractExpiresAt = rowData.contractExpiresAt @@ -1670,12 +1636,12 @@ final class DbMultiDomainAcsStore[TXE]( import storage.DbStorageConverters.setParameterByteArray (sql""" - insert into #$acsTableName(store_id, migration_id, contract_id, template_id_package_id, template_id_qualified_name, + insert into #$acsTableName(store_id, migration_id, contract_id, template_id_package_id, template_id_qualified_name, package_name, create_arguments, created_event_blob, created_at, contract_expires_at, assigned_domain, reassignment_counter, reassignment_target_domain, reassignment_source_domain, reassignment_submitter, reassignment_unassign_id #$indexColumnNames) - values ($acsStoreId, $domainMigrationId, $contractId, $templateIdPackageId, $templateIdQualifiedName, + values ($acsStoreId, $domainMigrationId, $contractId, $templateIdPackageId, $templateIdQualifiedName, $packageName, $createArguments, $createdEventBlob, $createdAt, $contractExpiresAt, $assignedDomain, $reassignmentCounter, $reassignmentTargetDomain, $reassignmentSourceDomain, $reassignmentSubmitter, $reassignmentUnassignId diff --git a/apps/common/src/main/scala/org/lfdecentralizedtrust/splice/util/QualifiedName.scala b/apps/common/src/main/scala/org/lfdecentralizedtrust/splice/util/QualifiedName.scala index 72847a4fb5..156d4463f8 100644 --- a/apps/common/src/main/scala/org/lfdecentralizedtrust/splice/util/QualifiedName.scala +++ b/apps/common/src/main/scala/org/lfdecentralizedtrust/splice/util/QualifiedName.scala @@ -37,6 +37,15 @@ object PackageQualifiedName { QualifiedName(event.getTemplateId.getModuleName, event.getTemplateId.getEntityName), ) } + + def fromJavaCodegenCompanion( + companion: com.daml.ledger.javaapi.data.codegen.ContractCompanion[?, ?, ?] + ): PackageQualifiedName = { + PackageQualifiedName( + companion.PACKAGE_NAME, + QualifiedName(companion.TEMPLATE_ID.getModuleName, companion.TEMPLATE_ID.getEntityName), + ) + } } object QualifiedName { diff --git a/apps/common/src/test/scala/org/lfdecentralizedtrust/splice/store/MultiDomainAcsStoreTest.scala b/apps/common/src/test/scala/org/lfdecentralizedtrust/splice/store/MultiDomainAcsStoreTest.scala index 106d40564a..79fbee220a 100644 --- a/apps/common/src/test/scala/org/lfdecentralizedtrust/splice/store/MultiDomainAcsStoreTest.scala +++ b/apps/common/src/test/scala/org/lfdecentralizedtrust/splice/store/MultiDomainAcsStoreTest.scala @@ -837,51 +837,6 @@ abstract class MultiDomainAcsStoreTest[ MultiDomainAcsStoreTest.generatedCoids.value.size should (be >= 900 and be <= 1000) } - "read assignment-mismatched contracts in a stable order" in { - import com.digitalasset.daml.lf.value.Value - import org.lfdecentralizedtrust.splice.codegen.java.splice.amulet.{ - FeaturedAppRight, - AppRewardCoupon, - } - import MultiDomainAcsStore.ConstrainedTemplate - - // the specific templates don't matter, we just need 2 of them - val sampleParticipantId = ParticipantId("foo") - val evenCompanion = FeaturedAppRight.COMPANION - val oddCompanion = AppRewardCoupon.COMPANION - def smallestContract(coid: Value.ContractId, ix: Int) = - if (ix % 2 == 0) featuredAppRight(dsoParty, coid.coid) - else appRewardCoupon(1, dsoParty, contractId = coid.coid) - val coids = MultiDomainAcsStoreTest.generatedCoids.value - val expectedOrder = reassignmentContractOrder( - coids, - sampleParticipantId, - )(_.coid) - - val contractFilter = { - import MultiDomainAcsStore.mkFilter - - MultiDomainAcsStore.SimpleContractFilter[GenericAcsRowData, GenericInterfaceRowData]( - dsoParty, - templateFilters = Map( - mkFilter(evenCompanion)(_ => true)(GenericAcsRowData(_)), - mkFilter(oddCompanion)(_ => true)(GenericAcsRowData(_)), - ), - interfaceFilters = Map.empty, - ) - } - implicit val store: Store = mkStore(0, Some(0), 0L, sampleParticipantId, contractFilter) - for { - _ <- initWithAcs(coids.zipWithIndex.map { case (coid, ix) => - StoreTest.AcsImportEntry(smallestContract(coid, ix), dummyDomain, 0L) - }) - contracts <- store.listAssignedContractsNotOnDomainN( - dummy2Domain, - Seq[ConstrainedTemplate](evenCompanion, oddCompanion), - ) - } yield contracts.map(_.contractId.contractId) shouldBe expectedOrder.map(_.coid) - } - "ingest and return interface views for 1 interface 2 implementors" in { implicit val store = mkStore() val aDifferentIssuer = providerParty(42) @@ -1601,23 +1556,94 @@ abstract class MultiDomainAcsStoreTest[ _ <- assertList() _ <- d1.create( goodContract, - implementedInterfaces = Map( - holdingv1.Holding.INTERFACE_ID_WITH_PACKAGE_ID -> goodView.toValue - ), + implementedInterfaces = goodImplementedInterfaces, ) _ <- d1.create( badContract, - implementedInterfaces = Map( - new Identifier( - maliciousPackageId, - holdingv1.Holding.INTERFACE_ID.getModuleName, - holdingv1.Holding.INTERFACE_ID.getEntityName, - ) -> badView.toValue + implementedInterfaces = badImplementedInterfaces, + ) + resultHolding <- store.listInterfaceViews(holdingv1.Holding.INTERFACE) + resultAmulet <- store.listContracts(Amulet.COMPANION) + } yield { + resultHolding.map(_.contractId.contractId) should contain theSameElementsAs Seq( + goodContract.contractId.contractId + ) + resultAmulet.map(_.contractId.contractId) should contain theSameElementsAs Seq( + goodContract.contractId.contractId + ) + } + } + + "prevent against ingestion of same (moduleName, entityName) with different package name - via interface fallback" in { + val filter = + MultiDomainAcsStore.SimpleContractFilter[GenericAcsRowData, GenericInterfaceRowData]( + dsoParty, + templateFilters = Map.empty, + interfaceFilters = Map( + mkFilterInterface(holdingv1.Holding.INTERFACE)(_ => true) { contract => + GenericInterfaceRowData(contract.identifier, contract.payload) + } ), ) - result <- store.listInterfaceViews(holdingv1.Holding.INTERFACE) + implicit val store = mkStore( + filter = filter + ) + val owner = providerParty(1) + val goodContract = amulet(owner, BigDecimal(10), 1L, BigDecimal(0.00001), dso = dsoParty) + val goodView = holdingView(owner, BigDecimal(10), dsoParty, "AMT") + val goodImplementedInterfaces = Map( + holdingv1.Holding.INTERFACE_ID_WITH_PACKAGE_ID -> goodView.toValue + ) + // like Splice's Amulet, but with different packageid + // that still implements the Holding interface + val fakeAmuletContract = + amulet(owner, BigDecimal(20), 2L, BigDecimal(0.00002), dso = dsoParty).copy(identifier = + new Identifier( + maliciousPackageId, + goodContract.identifier.getModuleName, + goodContract.identifier.getEntityName, + ) + ) + val fakeAmuletView = holdingView(owner, BigDecimal(20), dsoParty, "AMT") + val fakeAmuletImplementedInterfaces = Map( + holdingv1.Holding.INTERFACE_ID_WITH_PACKAGE_ID -> fakeAmuletView.toValue + ) + + filter.contains( + toCreatedEvent( + goodContract, + implementedInterfaces = goodImplementedInterfaces, + ) + ) should be(true) + + filter.contains( + toCreatedEvent( + fakeAmuletContract, + implementedInterfaces = fakeAmuletImplementedInterfaces, + ) + ) should be(true) // as a Holding, it is included. But it should not be included as an Amulet. + + for { + _ <- initWithAcs() + _ <- assertList() + _ <- d1.create( + goodContract, + implementedInterfaces = goodImplementedInterfaces, + ) + _ <- d1.create( + fakeAmuletContract, + implementedInterfaces = fakeAmuletImplementedInterfaces, + ) + resultHolding <- store.listInterfaceViews(holdingv1.Holding.INTERFACE) + resultAmulet <- store.listContracts(Amulet.COMPANION) } yield { - result.map(_.contractId.contractId) should contain theSameElementsAs Seq( + // fakeAmuletContract is a Holding + resultHolding.map(_.contractId.contractId) should contain theSameElementsAs Seq( + goodContract.contractId.contractId, + fakeAmuletContract.contractId.contractId, + ) + // but it is not an Amulet + resultAmulet.map(_.contractId.contractId) should contain theSameElementsAs Seq( goodContract.contractId.contractId ) } diff --git a/apps/common/src/test/scala/org/lfdecentralizedtrust/splice/store/TxLogBackfillingStoreTest.scala b/apps/common/src/test/scala/org/lfdecentralizedtrust/splice/store/TxLogBackfillingStoreTest.scala index 131acbe653..f8bda34843 100644 --- a/apps/common/src/test/scala/org/lfdecentralizedtrust/splice/store/TxLogBackfillingStoreTest.scala +++ b/apps/common/src/test/scala/org/lfdecentralizedtrust/splice/store/TxLogBackfillingStoreTest.scala @@ -590,7 +590,6 @@ class TxLogBackfillingStoreTest migrationId, None, ), - participantId, RetryProvider(loggerFactory, timeouts, FutureSupervisor.Noop, NoOpMetricsFactory), ) } diff --git a/apps/common/src/test/scala/org/lfdecentralizedtrust/splice/store/db/DbMultiDomainAcsStoreTest.scala b/apps/common/src/test/scala/org/lfdecentralizedtrust/splice/store/db/DbMultiDomainAcsStoreTest.scala index 044cbebe17..eb99d8c4a6 100644 --- a/apps/common/src/test/scala/org/lfdecentralizedtrust/splice/store/db/DbMultiDomainAcsStoreTest.scala +++ b/apps/common/src/test/scala/org/lfdecentralizedtrust/splice/store/db/DbMultiDomainAcsStoreTest.scala @@ -651,7 +651,6 @@ class DbMultiDomainAcsStoreTest migrationId, None, ), - participantId, RetryProvider(loggerFactory, timeouts, FutureSupervisor.Noop, NoOpMetricsFactory), ) } diff --git a/apps/scan/src/main/scala/org/lfdecentralizedtrust/splice/scan/store/AcsSnapshotStore.scala b/apps/scan/src/main/scala/org/lfdecentralizedtrust/splice/scan/store/AcsSnapshotStore.scala index 663d113869..9b3255a34d 100644 --- a/apps/scan/src/main/scala/org/lfdecentralizedtrust/splice/scan/store/AcsSnapshotStore.scala +++ b/apps/scan/src/main/scala/org/lfdecentralizedtrust/splice/scan/store/AcsSnapshotStore.scala @@ -398,9 +398,9 @@ object AcsSnapshotStore { ) private val amuletQualifiedName = - PackageQualifiedName.getFromResources(Amulet.TEMPLATE_ID_WITH_PACKAGE_ID) + PackageQualifiedName.fromJavaCodegenCompanion(Amulet.COMPANION) private val lockedAmuletQualifiedName = - PackageQualifiedName.getFromResources(LockedAmulet.TEMPLATE_ID_WITH_PACKAGE_ID) + PackageQualifiedName.fromJavaCodegenCompanion(LockedAmulet.COMPANION) private val holdingsTemplates = Vector(amuletQualifiedName, lockedAmuletQualifiedName) private def decodeHoldingContract(createdEvent: CreatedEvent): Either[ @@ -411,16 +411,14 @@ object AcsSnapshotStore { .withDescription(s"Failed to decode $createdEvent") .asRuntimeException() if ( - PackageQualifiedName.fromEvent(createdEvent) == PackageQualifiedName.getFromResources( - Amulet.TEMPLATE_ID_WITH_PACKAGE_ID - ) + PackageQualifiedName + .fromEvent(createdEvent) == PackageQualifiedName.fromJavaCodegenCompanion(Amulet.COMPANION) ) { Right(Contract.fromCreatedEvent(Amulet.COMPANION)(createdEvent).getOrElse(failedToDecode)) } else { if ( - PackageQualifiedName.fromEvent(createdEvent) != PackageQualifiedName.getFromResources( - LockedAmulet.TEMPLATE_ID_WITH_PACKAGE_ID - ) + PackageQualifiedName.fromEvent(createdEvent) != PackageQualifiedName + .fromJavaCodegenCompanion(LockedAmulet.COMPANION) ) { throw io.grpc.Status.INTERNAL .withDescription( diff --git a/apps/scan/src/main/scala/org/lfdecentralizedtrust/splice/scan/store/db/DbScanStore.scala b/apps/scan/src/main/scala/org/lfdecentralizedtrust/splice/scan/store/db/DbScanStore.scala index 3fb3062dba..c04b2ae4d1 100644 --- a/apps/scan/src/main/scala/org/lfdecentralizedtrust/splice/scan/store/db/DbScanStore.scala +++ b/apps/scan/src/main/scala/org/lfdecentralizedtrust/splice/scan/store/db/DbScanStore.scala @@ -111,7 +111,7 @@ class DbScanStore( // Any change in the store descriptor will lead to previously deployed applications // forgetting all persisted data once they upgrade to the new version. acsStoreDescriptor = StoreDescriptor( - version = 2, // TODO (DACH-NY/canton-network-node#13454): bump when it will backfill. + version = 3, name = "DbScanStore", party = key.dsoParty, participant = participantId, @@ -234,9 +234,7 @@ class DbScanStore( ScanTables.acsTableName, acsStoreId, domainMigrationId, - where = sql"""template_id_qualified_name = ${QualifiedName( - AmuletRules.TEMPLATE_ID_WITH_PACKAGE_ID - )}""", + AmuletRules.COMPANION, orderLimit = sql"""order by event_number desc limit 1""", ).headOption, "lookupAmuletRules", @@ -259,9 +257,7 @@ class DbScanStore( ScanTables.acsTableName, acsStoreId, domainMigrationId, - where = sql"""template_id_qualified_name = ${QualifiedName( - ExternalPartyAmuletRules.TEMPLATE_ID - )}""", + ExternalPartyAmuletRules.COMPANION, orderLimit = sql"""order by event_number desc limit 1""", ).headOption, "lookupExternalPartyAmuletRules", @@ -288,9 +284,7 @@ class DbScanStore( ScanTables.acsTableName, acsStoreId, domainMigrationId, - where = sql"""template_id_qualified_name = ${QualifiedName( - AnsRules.TEMPLATE_ID_WITH_PACKAGE_ID - )}""", + AnsRules.COMPANION, orderLimit = sql"""order by event_number desc limit 1""", ).headOption, "lookupAnsRules", @@ -319,10 +313,9 @@ class DbScanStore( ScanTables.acsTableName, acsStoreId, domainMigrationId, - where = sql""" - template_id_qualified_name = ${QualifiedName( - AnsEntry.TEMPLATE_ID_WITH_PACKAGE_ID - )} and ans_entry_name ^@ $limitedPrefix + AnsEntry.COMPANION, + additionalWhere = sql""" + and ans_entry_name ^@ $limitedPrefix and acs.contract_expires_at >= $now """, orderLimit = sql""" @@ -350,10 +343,8 @@ class DbScanStore( ScanTables.acsTableName, acsStoreId, domainMigrationId, - where = sql""" - template_id_qualified_name = ${QualifiedName( - AnsEntry.TEMPLATE_ID_WITH_PACKAGE_ID - )} + AnsEntry.COMPANION, + additionalWhere = sql""" and ans_entry_owner = $partyId and ans_entry_name >= '' and acs.contract_expires_at >= $now @@ -380,10 +371,8 @@ class DbScanStore( ScanTables.acsTableName, acsStoreId, domainMigrationId, - where = sql""" - template_id_qualified_name = ${QualifiedName( - AnsEntry.TEMPLATE_ID_WITH_PACKAGE_ID - )} + AnsEntry.COMPANION, + additionalWhere = sql""" and ans_entry_name = ${lengthLimited(name)} and acs.contract_expires_at >= $now """, @@ -406,10 +395,8 @@ class DbScanStore( ScanTables.acsTableName, acsStoreId, domainMigrationId, - where = sql""" - template_id_qualified_name = ${QualifiedName( - TransferPreapproval.COMPANION.TEMPLATE_ID - )} + TransferPreapproval.COMPANION, + additionalWhere = sql""" and transfer_preapproval_receiver = $partyId """, orderLimit = sql""" @@ -433,10 +420,8 @@ class DbScanStore( ScanTables.acsTableName, acsStoreId, domainMigrationId, - where = sql""" - template_id_qualified_name = ${QualifiedName( - TransferCommandCounter.COMPANION.TEMPLATE_ID - )} + TransferCommandCounter.COMPANION, + additionalWhere = sql""" and wallet_party = $partyId """, orderLimit = sql"limit 1", @@ -513,10 +498,8 @@ class DbScanStore( ScanTables.acsTableName, acsStoreId, domainMigrationId, - where = sql""" - template_id_qualified_name = ${QualifiedName( - FeaturedAppRight.TEMPLATE_ID_WITH_PACKAGE_ID - )} + FeaturedAppRight.COMPANION, + additionalWhere = sql""" and featured_app_right_provider = $providerPartyId """, orderLimit = sql"limit 1", @@ -810,9 +793,7 @@ class DbScanStore( ScanTables.acsTableName, acsStoreId, domainMigrationId, - where = sql"""template_id_qualified_name = ${QualifiedName( - ValidatorLicense.TEMPLATE_ID_WITH_PACKAGE_ID - )}""", + ValidatorLicense.COMPANION, orderLimit = sql"""order by validator_license_rounds_collected desc limit ${sqlLimit(limit)}""", ), @@ -836,9 +817,8 @@ class DbScanStore( ScanTables.acsTableName, acsStoreId, domainMigrationId, - where = (sql"""template_id_qualified_name = ${QualifiedName( - ValidatorLicense.TEMPLATE_ID - )} and validator in """ ++ validatorPartyIds).toActionBuilder, + ValidatorLicense.COMPANION, + where = (sql"""validator in """ ++ validatorPartyIds).toActionBuilder, ), "getValidatorLicenseByValidator", ) @@ -861,6 +841,7 @@ class DbScanStore( from #${ScanTables.acsTableName} where store_id = $acsStoreId and migration_id = $domainMigrationId + and package_name = ${MemberTraffic.PACKAGE_NAME} and template_id_qualified_name = ${QualifiedName( MemberTraffic.TEMPLATE_ID_WITH_PACKAGE_ID )} @@ -963,9 +944,8 @@ class DbScanStore( ScanTables.acsTableName, acsStoreId, domainMigrationId, - where = sql""" - template_id_qualified_name = ${QualifiedName(templateId)} - and sv_party = $svPartyId""", + companion, + additionalWhere = sql"""and sv_party = $svPartyId""", orderLimit = sql"""limit 1""", ).headOption, s"lookupContractBySvParty[$templateId]", @@ -1088,23 +1068,21 @@ class DbScanStore( companionClass: ContractCompanion[C, TCId, T], tc: TraceContext, ): Future[Option[Contract[TCId, T]]] = { - val templateId = companionClass.typeId(companion) - val packageName = PackageQualifiedName.getFromResources(templateId).packageName + val pqn @ PackageQualifiedName(packageName, QualifiedName(moduleName, entityName)) = + companionClass.packageQualifiedName(companion) for { row <- storage .querySingle( selectFromUpdateCreatesTableResult( updateHistory.historyId, - where = sql"""template_id_module_name = ${lengthLimited( - templateId.getModuleName - )} and template_id_entity_name = ${lengthLimited( - templateId.getEntityName - )} and package_name = ${lengthLimited(packageName)} + where = sql"""template_id_module_name = ${lengthLimited(moduleName)} + and template_id_entity_name = ${lengthLimited(entityName)} + and package_name = ${lengthLimited(packageName)} and record_time > $recordTime""", // TODO(#934): Order by row_id is suspicious orderLimit = sql"""order by row_id asc limit 1""", ).headOption, - s"lookup[$templateId]", + s"lookup[$pqn]", ) .value } yield { diff --git a/apps/splitwell/src/main/scala/org/lfdecentralizedtrust/splice/splitwell/store/db/DbSplitwellStore.scala b/apps/splitwell/src/main/scala/org/lfdecentralizedtrust/splice/splitwell/store/db/DbSplitwellStore.scala index d5c3b800bb..dd246bd255 100644 --- a/apps/splitwell/src/main/scala/org/lfdecentralizedtrust/splice/splitwell/store/db/DbSplitwellStore.scala +++ b/apps/splitwell/src/main/scala/org/lfdecentralizedtrust/splice/splitwell/store/db/DbSplitwellStore.scala @@ -23,7 +23,6 @@ import org.lfdecentralizedtrust.splice.util.{ AssignedContract, Contract, ContractWithState, - QualifiedName, TemplateJsonDecoder, } import com.digitalasset.canton.lifecycle.CloseContext @@ -56,7 +55,7 @@ class DbSplitwellStore( // Any change in the store descriptor will lead to previously deployed applications // forgetting all persisted data once they upgrade to the new version. acsStoreDescriptor = StoreDescriptor( - version = 1, + version = 2, name = "DbSplitwellStore", party = key.providerParty, participant = participantId, @@ -101,10 +100,8 @@ class DbSplitwellStore( SplitwellTables.acsTableName, acsStoreId, domainMigrationId, - where = sql"""template_id_qualified_name = ${QualifiedName( - splitwellCodegen.SplitwellInstall.TEMPLATE_ID_WITH_PACKAGE_ID - )} and assigned_domain = $synchronizerId - and install_user = ${user}""", + splitwellCodegen.SplitwellInstall.COMPANION, + where = sql"""assigned_domain = $synchronizerId and install_user = $user""", orderLimit = sql"limit 1", ).headOption, "lookupInstallWithOffset", @@ -134,9 +131,8 @@ class DbSplitwellStore( SplitwellTables.acsTableName, acsStoreId, domainMigrationId, - where = sql"""template_id_qualified_name = ${QualifiedName( - splitwellCodegen.Group.TEMPLATE_ID_WITH_PACKAGE_ID - )} and group_owner = ${owner} and group_id = ${lengthLimited(id.unpack)}""", + splitwellCodegen.Group.COMPANION, + where = sql"""group_owner = $owner and group_id = ${lengthLimited(id.unpack)}""", orderLimit = sql"limit 1", ).headOption, "lookupInstallWithOffset", @@ -164,11 +160,7 @@ class DbSplitwellStore( SplitwellTables.acsTableName, acsStoreId, domainMigrationId, - where = sql""" - template_id_qualified_name = ${QualifiedName( - splitwellCodegen.Group.TEMPLATE_ID_WITH_PACKAGE_ID - )} - """, + splitwellCodegen.Group.COMPANION, ), "listGroups", ) @@ -192,11 +184,8 @@ class DbSplitwellStore( SplitwellTables.acsTableName, acsStoreId, domainMigrationId, - where = sql""" - template_id_qualified_name = ${QualifiedName( - splitwellCodegen.GroupInvite.TEMPLATE_ID_WITH_PACKAGE_ID - )} and group_owner = ${owner} - """, + splitwellCodegen.GroupInvite.COMPANION, + additionalWhere = sql"""and group_owner = $owner""", ), "listGroupInvites", ) @@ -221,10 +210,9 @@ class DbSplitwellStore( SplitwellTables.acsTableName, acsStoreId, domainMigrationId, - where = sql""" - template_id_qualified_name = ${QualifiedName( - splitwellCodegen.AcceptedGroupInvite.TEMPLATE_ID_WITH_PACKAGE_ID - )} and group_owner = ${owner} + splitwellCodegen.AcceptedGroupInvite.COMPANION, + additionalWhere = sql""" + and group_owner = ${owner} and group_id = ${lengthLimited(groupKey(owner, groupId).id.unpack)} """, ), @@ -250,10 +238,8 @@ class DbSplitwellStore( SplitwellTables.acsTableName, acsStoreId, domainMigrationId, - where = sql""" - template_id_qualified_name = ${QualifiedName( - splitwellCodegen.BalanceUpdate.TEMPLATE_ID_WITH_PACKAGE_ID - )} and group_id = ${lengthLimited(key.id.unpack)} + splitwellCodegen.BalanceUpdate.COMPANION, + additionalWhere = sql""" and group_id = ${lengthLimited(key.id.unpack)} """, orderLimit = sql"""order by event_number desc""", ), @@ -322,10 +308,9 @@ class DbSplitwellStore( SplitwellTables.acsTableName, acsStoreId, domainMigrationId, - where = sql""" - template_id_qualified_name = ${QualifiedName( - splitwellCodegen.SplitwellInstall.TEMPLATE_ID_WITH_PACKAGE_ID - )} and install_user = ${user} + splitwellCodegen.SplitwellInstall.COMPANION, + additionalWhere = sql""" + and install_user = $user and assigned_domain is not null """, ), @@ -352,10 +337,9 @@ class DbSplitwellStore( SplitwellTables.acsTableName, acsStoreId, domainMigrationId, - where = sql""" - template_id_qualified_name = ${QualifiedName( - splitwellCodegen.SplitwellRules.TEMPLATE_ID_WITH_PACKAGE_ID - )} and assigned_domain is not null + splitwellCodegen.SplitwellRules.COMPANION, + additionalWhere = sql""" + and assigned_domain is not null """, ), "listSplitwellRules", @@ -383,11 +367,8 @@ class DbSplitwellStore( SplitwellTables.acsTableName, acsStoreId, domainMigrationId, - where = sql""" - template_id_qualified_name = ${QualifiedName( - splitwellCodegen.SplitwellRules.TEMPLATE_ID_WITH_PACKAGE_ID - )} and assigned_domain = $synchronizerId - """, + splitwellCodegen.SplitwellRules.COMPANION, + where = sql"""assigned_domain = $synchronizerId""", ).headOption, "lookupSplitwellRules", ) @@ -490,10 +471,9 @@ class DbSplitwellStore( SplitwellTables.acsTableName, acsStoreId, domainMigrationId, + splitwellCodegen.TransferInProgress.COMPANION, where = sql""" - template_id_qualified_name = ${QualifiedName( - splitwellCodegen.TransferInProgress.TEMPLATE_ID_WITH_PACKAGE_ID - )} and payment_request_contract_id = ${paymentRequest} + payment_request_contract_id = $paymentRequest and assigned_domain is not null """, ).headOption, diff --git a/apps/sv/src/main/scala/org/lfdecentralizedtrust/splice/sv/store/db/DbSvDsoStore.scala b/apps/sv/src/main/scala/org/lfdecentralizedtrust/splice/sv/store/db/DbSvDsoStore.scala index 908d78ada7..ddfad2489b 100644 --- a/apps/sv/src/main/scala/org/lfdecentralizedtrust/splice/sv/store/db/DbSvDsoStore.scala +++ b/apps/sv/src/main/scala/org/lfdecentralizedtrust/splice/sv/store/db/DbSvDsoStore.scala @@ -6,7 +6,6 @@ package org.lfdecentralizedtrust.splice.sv.store.db import cats.data.OptionT import cats.implicits.* import com.daml.ledger.javaapi.data as javab -import com.daml.ledger.javaapi.data.Identifier import com.daml.ledger.javaapi.data.codegen.ContractId import org.lfdecentralizedtrust.splice.automation.MultiDomainExpiredContractTrigger.ListExpiredContracts import org.lfdecentralizedtrust.splice.codegen.java.splice @@ -87,7 +86,7 @@ class DbSvDsoStore( // Any change in the store descriptor will lead to previously deployed applications // forgetting all persisted data once they upgrade to the new version. acsStoreDescriptor = StoreDescriptor( - version = 1, + version = 2, name = "DbSvDsoStore", party = key.dsoParty, participant = participantId, @@ -143,6 +142,7 @@ class DbSvDsoStore( idle.contract_id, idle.template_id_package_id, idle.template_id_qualified_name, + idle.package_name, idle.create_arguments, idle.created_event_blob, idle.created_at, @@ -153,6 +153,7 @@ class DbSvDsoStore( ctx.contract_id, ctx.template_id_package_id, ctx.template_id_qualified_name, + ctx.package_name, ctx.create_arguments, ctx.created_event_blob, ctx.created_at, @@ -195,9 +196,7 @@ class DbSvDsoStore( DsoTables.acsTableName, acsStoreId, domainMigrationId, - where = sql"""template_id_qualified_name = ${QualifiedName( - SvOnboardingConfirmed.TEMPLATE_ID_WITH_PACKAGE_ID - )}""", + SvOnboardingConfirmed.COMPANION, orderLimit = sql"""limit ${sqlLimit(limit)}""", ), "listSvOnboardingConfirmed", @@ -217,9 +216,8 @@ class DbSvDsoStore( DsoTables.acsTableName, acsStoreId, domainMigrationId, - where = sql"""template_id_qualified_name = ${QualifiedName( - SvOnboardingConfirmed.TEMPLATE_ID_WITH_PACKAGE_ID - )} and sv_candidate_party = $svParty""", + SvOnboardingConfirmed.COMPANION, + where = sql"""sv_candidate_party = $svParty""", orderLimit = sql"limit 1", ).headOption, "lookupSvOnboardingConfirmedByParty", @@ -238,10 +236,8 @@ class DbSvDsoStore( DsoTables.acsTableName, acsStoreId, domainMigrationId, - where = sql"""template_id_qualified_name = ${QualifiedName( - Confirmation.TEMPLATE_ID_WITH_PACKAGE_ID - )} - and action_requiring_confirmation = ${payloadJsonFromDefinedDataType( + Confirmation.COMPANION, + where = sql"""action_requiring_confirmation = ${payloadJsonFromDefinedDataType( action )}""", orderLimit = sql"""limit ${sqlLimit(limit)}""", @@ -266,10 +262,9 @@ class DbSvDsoStore( DsoTables.acsTableName, acsStoreId, domainMigrationId, - where = sql"""template_id_qualified_name = ${QualifiedName( - Confirmation.TEMPLATE_ID_WITH_PACKAGE_ID - )} - and confirmer = $confirmer + Confirmation.COMPANION, + where = sql""" + confirmer = $confirmer and action_requiring_confirmation = ${payloadJsonFromDefinedDataType(action)}""", orderLimit = sql"""limit ${sqlLimit(limit)}""", ), @@ -295,7 +290,7 @@ class DbSvDsoStore( sql"""select sum(case app_reward_is_featured when true then reward_amount else 0 end), sum(case app_reward_is_featured when true then 0 else reward_amount end)""", - AppRewardCoupon.TEMPLATE_ID_WITH_PACKAGE_ID, + PackageQualifiedName.fromJavaCodegenCompanion(AppRewardCoupon.COMPANION), round, synchronizerId, ) @@ -319,7 +314,7 @@ class DbSvDsoStore( ): Future[BigDecimal] = selectFromRewardCouponsOnDomain[Option[BigDecimal]]( sql"select sum(reward_amount)", - ValidatorRewardCoupon.TEMPLATE_ID_WITH_PACKAGE_ID, + PackageQualifiedName.fromJavaCodegenCompanion(ValidatorRewardCoupon.COMPANION), round, synchronizerId, ).map(_.headOption.flatten.getOrElse(BigDecimal(0))) @@ -362,7 +357,7 @@ class DbSvDsoStore( implicit tc: TraceContext ): Future[Long] = selectFromRewardCouponsOnDomain[Option[Long]]( sql"select count(*)", - ValidatorFaucetCoupon.TEMPLATE_ID_WITH_PACKAGE_ID, + PackageQualifiedName.fromJavaCodegenCompanion(ValidatorFaucetCoupon.COMPANION), round, synchronizerId, ).map(_.headOption.flatten.getOrElse(0L)) @@ -374,7 +369,7 @@ class DbSvDsoStore( tc: TraceContext ): Future[Long] = selectFromRewardCouponsOnDomain[Option[Long]]( sql"select count(*)", - ValidatorLivenessActivityRecord.COMPANION.TEMPLATE_ID, + PackageQualifiedName.fromJavaCodegenCompanion(ValidatorLivenessActivityRecord.COMPANION), round, synchronizerId, ).map(_.headOption.flatten.getOrElse(0L)) @@ -383,7 +378,7 @@ class DbSvDsoStore( implicit tc: TraceContext ): Future[Long] = selectFromRewardCouponsOnDomain[Option[Long]]( sql"select sum(reward_weight)", - SvRewardCoupon.TEMPLATE_ID_WITH_PACKAGE_ID, + PackageQualifiedName.fromJavaCodegenCompanion(SvRewardCoupon.COMPANION), round, synchronizerId, ).map(_.headOption.flatten.getOrElse(0L)) @@ -397,10 +392,9 @@ class DbSvDsoStore( companionClass: ContractCompanion[C, TCId, T], tc: TraceContext, ): Future[Seq[Contract[TCId, T]]] = { - val templateId = companionClass.typeId(companion) selectFromRewardCouponsOnDomain[SelectFromAcsTableResult]( sql"select #${SelectFromAcsTableResult.sqlColumnsCommaSeparated()}", - templateId, + companionClass.packageQualifiedName(companion), round, synchronizerId, limit = limit, @@ -409,14 +403,14 @@ class DbSvDsoStore( private def selectFromRewardCouponsOnDomain[R: GetResult]( selectClause: SQLActionBuilder, - templateId: Identifier, + packageQualifiedName: PackageQualifiedName, round: Long, synchronizerId: SynchronizerId, limit: Limit = Limit.DefaultLimit, )(implicit tc: TraceContext ): Future[Seq[R]] = { - val opName = s"selectFrom${templateId.getEntityName}OnDomain" + val opName = s"selectFrom${packageQualifiedName.qualifiedName.entityName}OnDomain" waitUntilAcsIngested { for { result <- storage @@ -426,7 +420,8 @@ class DbSvDsoStore( from #${DsoTables.acsTableName} where store_id = $acsStoreId and migration_id = $domainMigrationId - and template_id_qualified_name = ${QualifiedName(templateId)} + and package_name = ${packageQualifiedName.packageName} + and template_id_qualified_name = ${packageQualifiedName.qualifiedName} and assigned_domain = $synchronizerId and reward_round = $round and reward_party is not null -- otherwise index is not used @@ -516,6 +511,7 @@ class DbSvDsoStore( companionClass: ContractCompanion[C, TCId, T], tc: TraceContext, ): Future[Seq[SvDsoStore.RoundBatch[TCId]]] = { + val packageQualifiedName = companionClass.packageQualifiedName(companion) val templateId = companionClass.typeId(companion) val opName = s"list${templateId.getEntityName}GroupedByRound" val partyFilter = @@ -540,7 +536,8 @@ class DbSvDsoStore( from dso_acs_store where store_id = $acsStoreId and migration_id = $domainMigrationId - and template_id_qualified_name = ${QualifiedName(templateId)} + and package_name = ${packageQualifiedName.packageName} + and template_id_qualified_name = ${packageQualifiedName.qualifiedName} and assigned_domain = $domain and reward_party is not null -- otherwise index is not used and reward_round is not null -- otherwise index is not used @@ -578,11 +575,10 @@ class DbSvDsoStore( DsoTables.acsTableName, acsStoreId, domainMigrationId, - where = sql"""template_id_qualified_name = ${QualifiedName( - ClosedMiningRound.TEMPLATE_ID_WITH_PACKAGE_ID - )} - and assigned_domain = ${dsoRules.domain} - and mining_round is not null""", + ClosedMiningRound.COMPANION, + additionalWhere = sql""" + and assigned_domain = ${dsoRules.domain} + and mining_round is not null""", orderLimit = sql"""order by mining_round limit 1""", ).headOption, "lookupOldestClosedMiningRound", @@ -603,9 +599,7 @@ class DbSvDsoStore( DsoTables.acsTableName, acsStoreId, domainMigrationId, - where = sql"""template_id_qualified_name = ${QualifiedName( - SummarizingMiningRound.TEMPLATE_ID_WITH_PACKAGE_ID - )}""", + SummarizingMiningRound.COMPANION, orderLimit = sql"""order by mining_round limit ${sqlLimit(limit)}""", ), "listOldestSummarizingMiningRounds", @@ -626,11 +620,9 @@ class DbSvDsoStore( DsoTables.acsTableName, acsStoreId, domainMigrationId, + Confirmation.COMPANION, where = sql""" - template_id_qualified_name = ${QualifiedName( - Confirmation.TEMPLATE_ID_WITH_PACKAGE_ID - )} - and confirmer = $confirmer + confirmer = $confirmer and action_requiring_confirmation = ${payloadJsonFromDefinedDataType(action)} """, orderLimit = sql" limit 1", @@ -660,11 +652,9 @@ class DbSvDsoStore( DsoTables.acsTableName, acsStoreId, domainMigrationId, + Confirmation.COMPANION, where = sql""" - template_id_qualified_name = ${QualifiedName( - Confirmation.TEMPLATE_ID_WITH_PACKAGE_ID - )} - and confirmer = $confirmer + confirmer = $confirmer and action_ans_entry_context_payment_id = $paymentId and action_ans_entry_context_arc_type = ${lengthLimited( DsoTables.AnsActionTypeCollectInitialEntryPayment @@ -697,11 +687,9 @@ class DbSvDsoStore( DsoTables.acsTableName, acsStoreId, domainMigrationId, + Confirmation.COMPANION, where = sql""" - template_id_qualified_name = ${QualifiedName( - Confirmation.TEMPLATE_ID_WITH_PACKAGE_ID - )} - and confirmer = $confirmer + confirmer = $confirmer and action_ans_entry_context_payment_id = $paymentId and action_ans_entry_context_arc_type = ${lengthLimited( DsoTables.AnsActionTypeRejectEntryInitialPayment @@ -734,11 +722,9 @@ class DbSvDsoStore( DsoTables.acsTableName, acsStoreId, domainMigrationId, + Confirmation.COMPANION, where = sql""" - template_id_qualified_name = ${QualifiedName( - Confirmation.TEMPLATE_ID_WITH_PACKAGE_ID - )} - and confirmer = $confirmer + confirmer = $confirmer and action_ans_entry_context_payment_id = $paymentId """, orderLimit = sql"limit 1", @@ -764,10 +750,9 @@ class DbSvDsoStore( DsoTables.acsTableName, acsStoreId, domainMigrationId, - where = sql"""template_id_qualified_name = ${QualifiedName( - Confirmation.TEMPLATE_ID_WITH_PACKAGE_ID - )} - and confirmer = $confirmer + Confirmation.COMPANION, + where = sql""" + confirmer = $confirmer and action_ans_entry_context_cid IN ( select contract_id from #${DsoTables.acsTableName} @@ -797,12 +782,8 @@ class DbSvDsoStore( DsoTables.acsTableName, acsStoreId, domainMigrationId, - where = sql""" - template_id_qualified_name = ${QualifiedName( - SvOnboardingRequest.TEMPLATE_ID_WITH_PACKAGE_ID - )} - and sv_onboarding_token = ${lengthLimited(token)} - """, + SvOnboardingRequest.COMPANION, + where = sql"""sv_onboarding_token = ${lengthLimited(token)}""", orderLimit = sql"limit 1", ).headOption, "lookupSvOnboardingRequestByTokenWithOffset", @@ -838,9 +819,9 @@ class DbSvDsoStore( DsoTables.acsTableName, acsStoreId, domainMigrationId, - where = (sql"""template_id_qualified_name = ${QualifiedName( - SvOnboardingRequest.TEMPLATE_ID_WITH_PACKAGE_ID - )} and (sv_candidate_party, sv_candidate_name) in (""" ++ svCandidates ++ sql")").toActionBuilder, + SvOnboardingRequest.COMPANION, + where = + (sql"""(sv_candidate_party, sv_candidate_name) in (""" ++ svCandidates ++ sql")").toActionBuilder, orderLimit = sql"""limit ${sqlLimit(limit)}""", ), "listSvOnboardingRequestsBySvs", @@ -894,14 +875,15 @@ class DbSvDsoStore( DsoTables.acsTableName, acsStoreId, domainMigrationId, - where = (sql""" - template_id_qualified_name = ${QualifiedName(companion.getTemplateIdWithPackageId)} + companion, + additionalWhere = (sql""" and assigned_domain = $synchronizerId and acs.amulet_round_of_expiry <= ( select mining_round - 2 from dso_acs_store where store_id = $acsStoreId and migration_id = $domainMigrationId + and package_name = ${splice.round.OpenMiningRound.PACKAGE_NAME} and template_id_qualified_name = ${QualifiedName( splice.round.OpenMiningRound.TEMPLATE_ID_WITH_PACKAGE_ID )} @@ -930,11 +912,9 @@ class DbSvDsoStore( DsoTables.acsTableName, acsStoreId, domainMigrationId, - where = sql"""template_id_qualified_name = ${QualifiedName( - MemberTraffic.TEMPLATE_ID_WITH_PACKAGE_ID - )} - and member_traffic_member = $memberId - and member_traffic_domain = $synchronizerId""", + MemberTraffic.COMPANION, + where = sql"""member_traffic_member = $memberId + and member_traffic_domain = $synchronizerId""", orderLimit = sql"""limit ${sqlLimit(limit)}""", ), "listMemberTrafficContracts", @@ -962,10 +942,8 @@ class DbSvDsoStore( DsoTables.acsTableName, acsStoreId, domainMigrationId, - where = (sql"""template_id_qualified_name = ${QualifiedName( - AmuletPriceVote.TEMPLATE_ID_WITH_PACKAGE_ID - )} - and voter in """ ++ voterParties).toActionBuilder, + AmuletPriceVote.COMPANION, + where = (sql"""voter in """ ++ voterParties).toActionBuilder, orderLimit = sql"""limit ${sqlLimit(limit)}""", ), "listSvAmuletPriceVotes", @@ -986,12 +964,8 @@ class DbSvDsoStore( DsoTables.acsTableName, acsStoreId, domainMigrationId, - where = sql""" - template_id_qualified_name = ${QualifiedName( - SvOnboardingRequest.TEMPLATE_ID_WITH_PACKAGE_ID - )} - and sv_candidate_party = $candidateParty - """, + SvOnboardingRequest.COMPANION, + where = sql"""sv_candidate_party = $candidateParty""", orderLimit = sql"limit 1", ).headOption, "lookupSvOnboardingRequestByCandidatePartyWithOffset", @@ -1014,12 +988,8 @@ class DbSvDsoStore( DsoTables.acsTableName, acsStoreId, domainMigrationId, - where = sql""" - template_id_qualified_name = ${QualifiedName( - ValidatorLicense.TEMPLATE_ID_WITH_PACKAGE_ID - )} - and validator = $validator - """, + ValidatorLicense.COMPANION, + where = sql"""validator = $validator""", orderLimit = sql"limit 1", ).headOption, "lookupValidatorLicenseWithOffset", @@ -1040,11 +1010,8 @@ class DbSvDsoStore( DsoTables.acsTableName, acsStoreId, domainMigrationId, - where = sql"""template_id_qualified_name = ${QualifiedName( - ValidatorLicense.TEMPLATE_ID_WITH_PACKAGE_ID - )} - AND validator = ${lengthLimited(validator)} - """, + ValidatorLicense.COMPANION, + where = sql"""validator = ${lengthLimited(validator)}""", orderLimit = sql"""limit ${sqlLimit(limit)}""", ), "listValidatorLicensePerValidator", @@ -1062,6 +1029,7 @@ class DbSvDsoStore( from #${DsoTables.acsTableName} where store_id = $acsStoreId and migration_id = $domainMigrationId + and package_name = ${MemberTraffic.PACKAGE_NAME} and template_id_qualified_name = ${QualifiedName( MemberTraffic.TEMPLATE_ID_WITH_PACKAGE_ID )} @@ -1130,12 +1098,8 @@ class DbSvDsoStore( DsoTables.acsTableName, acsStoreId, domainMigrationId, - where = sql""" - template_id_qualified_name = ${QualifiedName( - VoteRequest.TEMPLATE_ID_WITH_PACKAGE_ID - )} - and vote_request_tracking_cid = $voteRequestCid - """, + VoteRequest.COMPANION, + where = sql"""vote_request_tracking_cid = $voteRequestCid""", orderLimit = sql"limit 1", ).headOption, "lookupVoteByThisSvAndVoteRequestWithOffset", @@ -1160,11 +1124,8 @@ class DbSvDsoStore( DsoTables.acsTableName, acsStoreId, domainMigrationId, - where = sql""" - template_id_qualified_name = ${QualifiedName( - VoteRequest.TEMPLATE_ID_WITH_PACKAGE_ID - )} - and action_requiring_confirmation = ${payloadJsonFromDefinedDataType(action)} + VoteRequest.COMPANION, + where = sql"""action_requiring_confirmation = ${payloadJsonFromDefinedDataType(action)} and requester_name = ${key.svParty} """, orderLimit = sql"limit 1", @@ -1187,10 +1148,8 @@ class DbSvDsoStore( DsoTables.acsTableName, acsStoreId, domainMigrationId, - where = sql"""template_id_qualified_name = ${QualifiedName( - AmuletPriceVote.TEMPLATE_ID_WITH_PACKAGE_ID - )} - and voter = ${key.svParty}""", + AmuletPriceVote.COMPANION, + where = sql"""voter = ${key.svParty}""", orderLimit = sql"""limit 1""", ).headOption, "lookupAmuletPriceVoteByThisSv", @@ -1211,12 +1170,8 @@ class DbSvDsoStore( DsoTables.acsTableName, acsStoreId, domainMigrationId, - where = sql""" - template_id_qualified_name = ${QualifiedName( - SvOnboardingRequest.TEMPLATE_ID_WITH_PACKAGE_ID - )} - and sv_candidate_name = ${lengthLimited(candidateName)} - """, + SvOnboardingRequest.COMPANION, + where = sql"""sv_candidate_name = ${lengthLimited(candidateName)}""", orderLimit = sql"limit 1", ).headOption, "lookupSvOnboardingRequestByCandidateNameWithOffset", @@ -1239,12 +1194,8 @@ class DbSvDsoStore( DsoTables.acsTableName, acsStoreId, domainMigrationId, - where = sql""" - template_id_qualified_name = ${QualifiedName( - SvOnboardingConfirmed.TEMPLATE_ID_WITH_PACKAGE_ID - )} - and sv_candidate_name = ${lengthLimited(svName)} - """, + SvOnboardingConfirmed.COMPANION, + where = sql"""sv_candidate_name = ${lengthLimited(svName)}""", orderLimit = sql"limit 1", ).headOption, "lookupSvOnboardingConfirmedByNameWithOffset", @@ -1268,12 +1219,10 @@ class DbSvDsoStore( DsoTables.acsTableName, acsStoreId, domainMigrationId, - where = sql"""template_id_qualified_name = ${QualifiedName( - AnsEntry.TEMPLATE_ID_WITH_PACKAGE_ID - )} - and ans_entry_name = ${lengthLimited(name)} - and assigned_domain is not null - and acs.contract_expires_at >= $now""", + AnsEntry.COMPANION, + where = sql"""ans_entry_name = ${lengthLimited(name)} + and assigned_domain is not null + and acs.contract_expires_at >= $now""", orderLimit = sql"limit 1", ).headOption, "lookupAnsEntryByNameWithOffset", @@ -1300,11 +1249,9 @@ class DbSvDsoStore( DsoTables.acsTableName, acsStoreId, domainMigrationId, - where = sql"""template_id_qualified_name = ${QualifiedName( - SubscriptionInitialPayment.TEMPLATE_ID_WITH_PACKAGE_ID - )} - and contract_id = $paymentCid - and assigned_domain is not null""", + SubscriptionInitialPayment.COMPANION, + where = sql"""contract_id = $paymentCid + and assigned_domain is not null""", orderLimit = sql"limit 1", ).headOption, "lookupSubscriptionInitialPaymentWithOffset", @@ -1331,10 +1278,8 @@ class DbSvDsoStore( DsoTables.acsTableName, acsStoreId, domainMigrationId, - where = sql"""template_id_qualified_name = ${QualifiedName( - FeaturedAppRight.TEMPLATE_ID_WITH_PACKAGE_ID - )} - and featured_app_right_provider = $providerPartyId + FeaturedAppRight.COMPANION, + where = sql"""featured_app_right_provider = $providerPartyId and assigned_domain is not null""", orderLimit = sql"limit 1", ).headOption, @@ -1361,11 +1306,8 @@ class DbSvDsoStore( DsoTables.acsTableName, acsStoreId, domainMigrationId, - where = sql""" - template_id_qualified_name = ${QualifiedName( - AnsEntryContext.TEMPLATE_ID_WITH_PACKAGE_ID - )} - and subscription_reference_contract_id = $reference""", + AnsEntryContext.COMPANION, + additionalWhere = sql"""and subscription_reference_contract_id = $reference""", orderLimit = sql"""limit 1""", ).headOption, "lookupAnsEntryContext", @@ -1393,9 +1335,9 @@ class DbSvDsoStore( DsoTables.acsTableName, acsStoreId, domainMigrationId, - where = (sql"""template_id_qualified_name = ${QualifiedName( - ClosedMiningRound.TEMPLATE_ID_WITH_PACKAGE_ID - )} AND assigned_domain = $synchronizerId AND mining_round IN """ ++ roundNumbersClause).toActionBuilder, + ClosedMiningRound.COMPANION, + where = + (sql"""assigned_domain = $synchronizerId AND mining_round IN """ ++ roundNumbersClause).toActionBuilder, orderLimit = sql"""limit ${sqlLimit(limit)}""", ), "listClosedRounds", @@ -1440,11 +1382,8 @@ class DbSvDsoStore( DsoTables.acsTableName, acsStoreId, domainMigrationId, - where = sql"""template_id_qualified_name = ${QualifiedName( - SvRewardState.TEMPLATE_ID_WITH_PACKAGE_ID - )} - AND sv_name = ${lengthLimited(svName)} - """, + SvRewardState.COMPANION, + where = sql"""sv_name = ${lengthLimited(svName)}""", orderLimit = sql"""limit ${sqlLimit(limit)}""", ), "listSvRewardStates", @@ -1467,9 +1406,8 @@ class DbSvDsoStore( DsoTables.acsTableName, acsStoreId, domainMigrationId, - where = sql""" - template_id_qualified_name = ${QualifiedName(templateId)} - and sv_party = $svPartyId""", + companion, + additionalWhere = sql"""and sv_party = $svPartyId""", orderLimit = sql"""limit 1""", ).headOption, s"lookupContractBySvParty[$templateId]", @@ -1495,9 +1433,8 @@ class DbSvDsoStore( DsoTables.acsTableName, acsStoreId, domainMigrationId, - where = sql""" - template_id_qualified_name = ${QualifiedName(templateId)} - and sv_name = ${lengthLimited(svName)}""", + companion, + additionalWhere = sql"""and sv_name = ${lengthLimited(svName)}""", orderLimit = sql"""limit 1""", ).headOption, s"lookupContractBySvName[$templateId]", @@ -1521,12 +1458,8 @@ class DbSvDsoStore( DsoTables.acsTableName, acsStoreId, domainMigrationId, - where = sql""" - template_id_qualified_name = ${QualifiedName( - splice.externalpartyamuletrules.TransferCommandCounter.TEMPLATE_ID_WITH_PACKAGE_ID - )} - and wallet_party = $partyId - """, + splice.externalpartyamuletrules.TransferCommandCounter.COMPANION, + where = sql"""wallet_party = $partyId""", orderLimit = sql" limit 1", ).headOption, "lookupTransferCommandCounterBySender", @@ -1586,11 +1519,9 @@ class DbSvDsoStore( DsoTables.acsTableName, acsStoreId, domainMigrationId, + splice.ans.amuletconversionratefeed.AmuletConversionRateFeed.COMPANION, where = sql""" - template_id_qualified_name = ${QualifiedName( - splice.ans.amuletconversionratefeed.AmuletConversionRateFeed.TEMPLATE_ID_WITH_PACKAGE_ID - )} - and conversion_rate_feed_publisher = $publisher + conversion_rate_feed_publisher = $publisher """, orderLimit = sql" order by event_number desc limit 1", ).headOption, diff --git a/apps/sv/src/main/scala/org/lfdecentralizedtrust/splice/sv/store/db/DbSvSvStore.scala b/apps/sv/src/main/scala/org/lfdecentralizedtrust/splice/sv/store/db/DbSvSvStore.scala index 95e9ae8616..c392c95d99 100644 --- a/apps/sv/src/main/scala/org/lfdecentralizedtrust/splice/sv/store/db/DbSvSvStore.scala +++ b/apps/sv/src/main/scala/org/lfdecentralizedtrust/splice/sv/store/db/DbSvSvStore.scala @@ -14,7 +14,7 @@ import org.lfdecentralizedtrust.splice.store.db.DbMultiDomainAcsStore.StoreDescr import org.lfdecentralizedtrust.splice.store.db.{AcsQueries, AcsTables, DbAppStore} import org.lfdecentralizedtrust.splice.store.{MultiDomainAcsStore, StoreErrors} import org.lfdecentralizedtrust.splice.sv.store.{SvStore, SvSvStore} -import org.lfdecentralizedtrust.splice.util.{Contract, QualifiedName, TemplateJsonDecoder} +import org.lfdecentralizedtrust.splice.util.{Contract, TemplateJsonDecoder} import com.digitalasset.canton.lifecycle.CloseContext import com.digitalasset.canton.logging.{NamedLoggerFactory, NamedLogging} import com.digitalasset.canton.resource.DbStorage @@ -44,7 +44,7 @@ class DbSvSvStore( // Any change in the store descriptor will lead to previously deployed applications // forgetting all persisted data once they upgrade to the new version. acsStoreDescriptor = StoreDescriptor( - version = 1, + version = 2, name = "DbSvSvStore", party = key.svParty, participant = participantId, @@ -82,12 +82,8 @@ class DbSvSvStore( DbSvSvStore.tableName, acsStoreId, domainMigrationId, - sql""" - template_id_qualified_name = ${QualifiedName( - ValidatorOnboarding.TEMPLATE_ID_WITH_PACKAGE_ID - )} - and onboarding_secret = ${lengthLimited(secret)} - """, + ValidatorOnboarding.COMPANION, + where = sql"""onboarding_secret = ${lengthLimited(secret)}""", ).headOption, "lookupValidatorOnboardingBySecretWithOffset", ) @@ -108,12 +104,8 @@ class DbSvSvStore( DbSvSvStore.tableName, acsStoreId, domainMigrationId, - sql""" - template_id_qualified_name = ${QualifiedName( - UsedSecret.TEMPLATE_ID_WITH_PACKAGE_ID - )} - and onboarding_secret = ${lengthLimited(secret)} - """, + UsedSecret.COMPANION, + where = sql"""onboarding_secret = ${lengthLimited(secret)}""", ).headOption, "lookupUsedSecretWithOffset", ) diff --git a/apps/validator/src/main/scala/org/lfdecentralizedtrust/splice/validator/store/db/DbValidatorStore.scala b/apps/validator/src/main/scala/org/lfdecentralizedtrust/splice/validator/store/db/DbValidatorStore.scala index e2c061f894..94c2e35cdc 100644 --- a/apps/validator/src/main/scala/org/lfdecentralizedtrust/splice/validator/store/db/DbValidatorStore.scala +++ b/apps/validator/src/main/scala/org/lfdecentralizedtrust/splice/validator/store/db/DbValidatorStore.scala @@ -27,12 +27,7 @@ import org.lfdecentralizedtrust.splice.store.db.{ DbAppStore, } import org.lfdecentralizedtrust.splice.store.{LimitHelpers, PageLimit} -import org.lfdecentralizedtrust.splice.util.{ - Contract, - ContractWithState, - QualifiedName, - TemplateJsonDecoder, -} +import org.lfdecentralizedtrust.splice.util.{Contract, ContractWithState, TemplateJsonDecoder} import org.lfdecentralizedtrust.splice.validator.store.ValidatorStore import org.lfdecentralizedtrust.splice.wallet.store.WalletStore import com.digitalasset.canton.data.CantonTimestamp @@ -66,7 +61,7 @@ class DbValidatorStore( // Any change in the store descriptor will lead to previously deployed applications // forgetting all persisted data once they upgrade to the new version. acsStoreDescriptor = StoreDescriptor( - version = 1, + version = 2, name = "DbValidatorStore", party = key.validatorParty, participant = participantId, @@ -114,9 +109,8 @@ class DbValidatorStore( ValidatorTables.acsTableName, acsStoreId, domainMigrationId, - where = sql"""template_id_qualified_name = ${QualifiedName( - walletCodegen.WalletAppInstall.TEMPLATE_ID_WITH_PACKAGE_ID - )} and user_party = $endUserParty""", + walletCodegen.WalletAppInstall.COMPANION, + where = sql"""user_party = $endUserParty""", orderLimit = sql"limit 1", ).headOption, "lookupInstallByParty", @@ -135,9 +129,8 @@ class DbValidatorStore( ValidatorTables.acsTableName, acsStoreId, domainMigrationId, - where = sql"""template_id_qualified_name = ${QualifiedName( - walletCodegen.WalletAppInstall.TEMPLATE_ID_WITH_PACKAGE_ID - )} and user_name = ${lengthLimited(endUserName)}""", + walletCodegen.WalletAppInstall.COMPANION, + where = sql"""user_name = ${lengthLimited(endUserName)}""", orderLimit = sql"limit 1", ).headOption, "lookupInstallByName", @@ -156,9 +149,8 @@ class DbValidatorStore( ValidatorTables.acsTableName, acsStoreId, domainMigrationId, - where = sql"""template_id_qualified_name = ${QualifiedName( - amuletCodegen.FeaturedAppRight.TEMPLATE_ID_WITH_PACKAGE_ID - )} and provider_party = ${walletKey.validatorParty}""", + amuletCodegen.FeaturedAppRight.COMPANION, + where = sql"""provider_party = ${walletKey.validatorParty}""", orderLimit = sql"limit 1", ).headOption, "lookupValidatorFeaturedAppRight", @@ -180,11 +172,8 @@ class DbValidatorStore( ValidatorTables.acsTableName, acsStoreId, domainMigrationId, - sql""" - template_id_qualified_name = ${QualifiedName( - walletCodegen.WalletAppInstall.TEMPLATE_ID_WITH_PACKAGE_ID - )} - and user_name = ${lengthLimited(endUserName)} + walletCodegen.WalletAppInstall.COMPANION, + sql"""user_name = ${lengthLimited(endUserName)} """, sql"limit 1", ).headOption, @@ -211,10 +200,9 @@ class DbValidatorStore( ValidatorTables.acsTableName, acsStoreId, domainMigrationId, - sql""" - template_id_qualified_name = ${QualifiedName( - TransferPreapproval.TEMPLATE_ID_WITH_PACKAGE_ID - )} and contract_expires_at < ${now.plus(renewalDuration.asJava)} + TransferPreapproval.COMPANION, + additionalWhere = + sql"""and contract_expires_at < ${now.plus(renewalDuration.asJava)} """, ), "listExpiringTransferPreapprovals", @@ -238,12 +226,8 @@ class DbValidatorStore( ValidatorTables.acsTableName, acsStoreId, domainMigrationId, - where = sql""" - template_id_qualified_name = ${QualifiedName( - ExternalPartySetupProposal.COMPANION.TEMPLATE_ID - )} - and user_party = $partyId - """, + ExternalPartySetupProposal.COMPANION, + where = sql"""user_party = $partyId""", orderLimit = sql""" limit 1 """, @@ -272,15 +256,9 @@ class DbValidatorStore( ValidatorTables.acsTableName, acsStoreId, domainMigrationId, - where = sql""" - template_id_qualified_name = ${QualifiedName( - TransferPreapproval.COMPANION.TEMPLATE_ID - )} - and user_party = $partyId - """, - orderLimit = sql""" - limit 1 - """, + TransferPreapproval.COMPANION, + where = sql"""user_party = $partyId""", + orderLimit = sql"""limit 1""", ).headOption, "lookupTransferPreapprovalReceiver", ) @@ -307,13 +285,9 @@ class DbValidatorStore( ValidatorTables.acsTableName, acsStoreId, domainMigrationId, - sql""" - template_id_qualified_name = ${QualifiedName( - validatorLicenseCodegen.ValidatorLicense.TEMPLATE_ID_WITH_PACKAGE_ID - )} - and validator_party = ${key.validatorParty} - """, - sql"limit 1", + validatorLicenseCodegen.ValidatorLicense.COMPANION, + where = sql"""validator_party = ${key.validatorParty}""", + orderLimit = sql"limit 1", ).headOption, "lookupValidatorLicenseWithOffset", ) @@ -342,13 +316,9 @@ class DbValidatorStore( ValidatorTables.acsTableName, acsStoreId, domainMigrationId, - sql""" - template_id_qualified_name = ${QualifiedName( - amuletCodegen.ValidatorRight.TEMPLATE_ID_WITH_PACKAGE_ID - )} - and user_party = $party - """, - sql"limit 1", + amuletCodegen.ValidatorRight.COMPANION, + where = sql"""user_party = $party""", + orderLimit = sql"limit 1", ).headOption, "lookupValidatorRightByPartyWithOffset", ) @@ -374,13 +344,9 @@ class DbValidatorStore( ValidatorTables.acsTableName, acsStoreId, domainMigrationId, - sql""" - template_id_qualified_name = ${QualifiedName( - topupCodegen.ValidatorTopUpState.TEMPLATE_ID_WITH_PACKAGE_ID - )} - and traffic_domain_id = $synchronizerId - """, - sql"limit 1", + topupCodegen.ValidatorTopUpState.COMPANION, + where = sql"""traffic_domain_id = $synchronizerId""", + orderLimit = sql"limit 1", ).headOption, "lookupValidatorTopUpStateWithOffset", ) diff --git a/apps/wallet/src/main/scala/org/lfdecentralizedtrust/splice/wallet/store/db/DbExternalPartyWalletStore.scala b/apps/wallet/src/main/scala/org/lfdecentralizedtrust/splice/wallet/store/db/DbExternalPartyWalletStore.scala index acbc993afd..80a07f07a3 100644 --- a/apps/wallet/src/main/scala/org/lfdecentralizedtrust/splice/wallet/store/db/DbExternalPartyWalletStore.scala +++ b/apps/wallet/src/main/scala/org/lfdecentralizedtrust/splice/wallet/store/db/DbExternalPartyWalletStore.scala @@ -40,7 +40,7 @@ class DbExternalPartyWalletStore( acsTableName = WalletTables.externalPartyAcsTableName, interfaceViewsTableNameOpt = None, acsStoreDescriptor = StoreDescriptor( - version = 1, + version = 2, name = "DbExternalPartyWalletStore", party = key.externalParty, participant = participantId, diff --git a/apps/wallet/src/main/scala/org/lfdecentralizedtrust/splice/wallet/store/db/DbUserWalletStore.scala b/apps/wallet/src/main/scala/org/lfdecentralizedtrust/splice/wallet/store/db/DbUserWalletStore.scala index 1b7e086d04..e739c5ba6e 100644 --- a/apps/wallet/src/main/scala/org/lfdecentralizedtrust/splice/wallet/store/db/DbUserWalletStore.scala +++ b/apps/wallet/src/main/scala/org/lfdecentralizedtrust/splice/wallet/store/db/DbUserWalletStore.scala @@ -70,9 +70,7 @@ class DbUserWalletStore( // Any change in the store descriptor will lead to previously deployed applications // forgetting all persisted data once they upgrade to the new version. acsStoreDescriptor = StoreDescriptor( - // Note that the V005__no_end_user_name_in_user_wallet_store.sql DB migration converts from version 1 descriptors - // to version 2 descriptors. - version = 2, + version = 3, name = "DbUserWalletStore", party = key.endUserParty, participant = participantId, @@ -202,7 +200,7 @@ class DbUserWalletStore( companionClass: ContractCompanion[C, TCid, T], traceContext: TraceContext, ): Future[Seq[(Contract[TCid, T], BigDecimal)]] = { - val templateId = companionClass.typeId(companion) + val packageQualifiedName = companionClass.packageQualifiedName(companion) issuingRoundsMap .flatMap { case (round, contract) => roundToIssuance(contract).map(round.number.longValue() -> _) @@ -224,13 +222,14 @@ class DbUserWalletStore( from #${WalletTables.acsTableName} acs join round_to_issuance rti on acs.reward_coupon_round = rti.round where acs.store_id = $acsStoreId and migration_id = $domainMigrationId - and acs.template_id_qualified_name = ${QualifiedName(templateId)} + and acs.package_name = ${packageQualifiedName.packageName} + and acs.template_id_qualified_name = ${packageQualifiedName.qualifiedName} order by (acs.reward_coupon_round, -""" ++ ccValue ++ sql""") limit ${sqlLimit(limit)}""").toActionBuilder .as[(SelectFromAcsTableResult, BigDecimal)], - s"listSorted${templateId.getEntityName}", + s"listSorted:$packageQualifiedName", ) - } yield applyLimit(s"listSorted${templateId.getEntityName}", limit, result).map { + } yield applyLimit(s"listSorted:$packageQualifiedName", limit, result).map { case (row, issuance) => val contract = contractFromRow(companion)(row) contract -> issuance @@ -295,8 +294,10 @@ class DbUserWalletStore( where """ ++ filterAcsStoreMigrationIds("ansEntry.", "ansEntryContext.", "sub.", "st.") ++ sql" and " ++ subscriptionFilter(now) ++ sql""" + and ansEntry.package_name = ${ansCodegen.AnsEntry.PACKAGE_NAME} and ansEntry.template_id_qualified_name = ${QualifiedName(ansCodegen.AnsEntry.TEMPLATE_ID_WITH_PACKAGE_ID)} + and ansEntryContext.package_name = ${ansCodegen.AnsEntryContext.PACKAGE_NAME} and ansEntryContext.template_id_qualified_name = ${QualifiedName(ansCodegen.AnsEntryContext.TEMPLATE_ID_WITH_PACKAGE_ID)} and ansEntry.create_arguments ->> 'name' = ansEntryContext.create_arguments ->> 'name' @@ -388,8 +389,8 @@ class DbUserWalletStore( // provide a grace period for subscription payments. (sql"""select #${SelectFromAcsTableResult.sqlColumnsCommaSeparated("st.")}, #${SelectFromAcsTableResult.sqlColumnsCommaSeparated("sub.")}, - (case when st.template_id_qualified_name = - ${QualifiedName( + (case when st.package_name = ${subsCodegen.SubscriptionIdleState.PACKAGE_NAME} + and st.template_id_qualified_name = ${QualifiedName( subsCodegen.SubscriptionIdleState.TEMPLATE_ID_WITH_PACKAGE_ID )} then $idleStateFlag @@ -420,12 +421,12 @@ class DbUserWalletStore( } private[this] def subscriptionFilter(now: CantonTimestamp) = - sql"""((st.template_id_qualified_name = + sql"""((st.package_name = ${subsCodegen.SubscriptionIdleState.PACKAGE_NAME} and st.template_id_qualified_name = ${QualifiedName(subsCodegen.SubscriptionIdleState.TEMPLATE_ID_WITH_PACKAGE_ID)} and st.contract_expires_at >= $now) - or st.template_id_qualified_name = + or st.package_name = ${subsCodegen.SubscriptionPayment.PACKAGE_NAME} and st.template_id_qualified_name = ${QualifiedName(subsCodegen.SubscriptionPayment.TEMPLATE_ID_WITH_PACKAGE_ID)}) - and sub.template_id_qualified_name = + and sub.package_name = ${subsCodegen.Subscription.PACKAGE_NAME} and sub.template_id_qualified_name = ${QualifiedName(subsCodegen.Subscription.TEMPLATE_ID_WITH_PACKAGE_ID)} and (st.create_arguments ->> 'subscription') = sub.contract_id""" @@ -446,12 +447,8 @@ class DbUserWalletStore( WalletTables.acsTableName, acsStoreId, domainMigrationId, - sql""" - template_id_qualified_name = ${QualifiedName( - TransferPreapproval.TEMPLATE_ID_WITH_PACKAGE_ID - )} - and transfer_preapproval_receiver = ${receiver} - """, + TransferPreapproval.COMPANION, + sql""" transfer_preapproval_receiver = $receiver """, sql"limit 1", ).headOption, "lookupTransferPreapproval", @@ -478,12 +475,8 @@ class DbUserWalletStore( WalletTables.acsTableName, acsStoreId, domainMigrationId, - sql""" - template_id_qualified_name = ${QualifiedName( - TransferPreapprovalProposal.TEMPLATE_ID_WITH_PACKAGE_ID - )} - and transfer_preapproval_receiver = ${receiver} - """, + TransferPreapprovalProposal.COMPANION, + sql"""transfer_preapproval_receiver = $receiver""", sql"limit 1", ).headOption, "lookupTransferPreapprovalProposal",