state_catalog.rs (131375B)
1 //! Immutable RHI schema and migration catalog identity. 2 3 use core::fmt; 4 use std::error::Error; 5 6 use radroots_service_sqlite::{ 7 MigrationCatalog, MigrationChecksum, MigrationDescriptor, SchemaCatalog, SchemaDigest, 8 SchemaObject, SchemaObjectKind, SchemaVersionCatalog, 9 }; 10 11 /// The shared create-new baseline written before RHI migrations run. 12 pub const RHI_STATE_BASE_SCHEMA_VERSION: u32 = 1; 13 14 /// The newest governed RHI state schema understood by this binary. 15 pub const RHI_STATE_SCHEMA_VERSION: u32 = 11; 16 17 /// The shared metadata and migration-ledger objects present at schema v1. 18 pub const RHI_STATE_SCHEMA_VERSION_1_OBJECT_COUNT: u32 = 6; 19 20 /// The shared objects plus the bounded append-only RHI configuration history. 21 pub const RHI_STATE_SCHEMA_VERSION_2_OBJECT_COUNT: u32 = 10; 22 23 /// The shared objects, configuration history, and immutable trade evidence. 24 pub const RHI_STATE_SCHEMA_VERSION_3_OBJECT_COUNT: u32 = 22; 25 26 /// The shared objects, immutable trade evidence, source cursors, and dirty generations. 27 pub const RHI_STATE_SCHEMA_VERSION_4_OBJECT_COUNT: u32 = 28; 28 29 /// The shared objects, canonical evidence, cursors, generations, and durable jobs. 30 pub const RHI_STATE_SCHEMA_VERSION_5_OBJECT_COUNT: u32 = 33; 31 32 /// The shared objects plus immutable reconciliation attempt/source results. 33 pub const RHI_STATE_SCHEMA_VERSION_6_OBJECT_COUNT: u32 = 39; 34 35 /// The shared objects plus immutable report and publication workflow state. 36 pub const RHI_STATE_SCHEMA_VERSION_7_OBJECT_COUNT: u32 = 63; 37 38 /// The shared objects plus fail-closed reconciliation-job shape guards. 39 pub const RHI_STATE_SCHEMA_VERSION_8_OBJECT_COUNT: u32 = 65; 40 41 /// The shared objects plus deterministic durable presence desired state. 42 pub const RHI_STATE_SCHEMA_VERSION_9_OBJECT_COUNT: u32 = 69; 43 44 /// The shared objects plus durable exact-byte presence delivery state. 45 pub const RHI_STATE_SCHEMA_VERSION_10_OBJECT_COUNT: u32 = 80; 46 47 /// The complete v10 state plus the bounded durable admin-operation journal. 48 pub const RHI_STATE_SCHEMA_VERSION_11_OBJECT_COUNT: u32 = 82; 49 50 /// SHA-256 identity of the ordered migration catalog rooted at schema v1. 51 pub const RHI_MIGRATION_CATALOG_SHA256: [u8; 32] = [ 52 0xe6, 0xcb, 0xac, 0xbd, 0x1e, 0xb6, 0x36, 0xc1, 0xa5, 0x60, 0xf8, 0x5e, 0xf8, 0xe5, 0x1e, 0x89, 53 0xc9, 0xff, 0xe3, 0xb3, 0x42, 0xe6, 0x6b, 0xc5, 0xc0, 0xb4, 0x7a, 0xb3, 0x4e, 0x90, 0xc8, 0x18, 54 ]; 55 56 /// SHA-256 identity of the exact schema-v1 object snapshot. 57 pub const RHI_STATE_SCHEMA_VERSION_1_SHA256: [u8; 32] = [ 58 0x94, 0xdc, 0x66, 0xfb, 0xca, 0x60, 0x16, 0x79, 0x61, 0x5c, 0x05, 0x52, 0x29, 0xdc, 0x0d, 0xb6, 59 0x11, 0x9f, 0x5b, 0xd9, 0x2b, 0x04, 0x39, 0x0c, 0x67, 0xf6, 0x98, 0xa0, 0x36, 0xfa, 0x78, 0xae, 60 ]; 61 62 /// SHA-256 identity of the schema-v2 configuration-binding migration. 63 pub const RHI_STATE_SCHEMA_VERSION_2_MIGRATION_SHA256: [u8; 32] = [ 64 0xa2, 0xc1, 0xaa, 0x53, 0xf7, 0xfe, 0xee, 0x03, 0x85, 0xe7, 0x74, 0xde, 0x20, 0xe0, 0x72, 0x52, 65 0x0f, 0x49, 0x26, 0xc5, 0x59, 0xc6, 0x42, 0x1a, 0xab, 0x59, 0x0e, 0x92, 0xba, 0x14, 0x4c, 0x55, 66 ]; 67 68 /// SHA-256 identity of the exact schema-v2 object snapshot. 69 pub const RHI_STATE_SCHEMA_VERSION_2_SHA256: [u8; 32] = [ 70 0xbc, 0xcb, 0xf1, 0xe6, 0x2f, 0xe7, 0x64, 0x4c, 0x9c, 0x37, 0x72, 0x05, 0xb2, 0x5a, 0x92, 0x29, 71 0x8e, 0x08, 0x8b, 0x8c, 0x26, 0xd1, 0x5b, 0xa4, 0x51, 0x33, 0xca, 0x5e, 0x9b, 0x73, 0x15, 0xa9, 72 ]; 73 74 /// SHA-256 identity of the schema-v3 trade-evidence migration. 75 pub const RHI_STATE_SCHEMA_VERSION_3_MIGRATION_SHA256: [u8; 32] = [ 76 0x07, 0xb0, 0x98, 0xc3, 0x93, 0x14, 0x0a, 0xfe, 0xc2, 0x22, 0xfc, 0xe7, 0x6e, 0xc6, 0x68, 0x69, 77 0x8d, 0x50, 0xf1, 0xd2, 0x37, 0x85, 0x85, 0x68, 0x73, 0xe3, 0x04, 0x45, 0xaf, 0x1a, 0x01, 0x3f, 78 ]; 79 80 /// SHA-256 identity of the exact schema-v3 object snapshot. 81 pub const RHI_STATE_SCHEMA_VERSION_3_SHA256: [u8; 32] = [ 82 0xfd, 0x96, 0x22, 0x64, 0x05, 0xab, 0x68, 0x65, 0x5a, 0xee, 0x00, 0xf6, 0x83, 0xf6, 0x02, 0x3c, 83 0x7a, 0xab, 0x2d, 0xbd, 0x23, 0xfe, 0xad, 0xac, 0x16, 0x53, 0x33, 0x49, 0x0d, 0x6f, 0x0a, 0xd5, 84 ]; 85 86 /// SHA-256 identity of the schema-v4 source-checkpoint migration. 87 pub const RHI_STATE_SCHEMA_VERSION_4_MIGRATION_SHA256: [u8; 32] = [ 88 0x24, 0x41, 0xf7, 0xc4, 0xc1, 0x15, 0x94, 0xc6, 0xfd, 0xe7, 0x87, 0xdb, 0xb9, 0x4e, 0x44, 0xba, 89 0x00, 0xb7, 0x2d, 0x2c, 0x97, 0x9b, 0x0e, 0x7f, 0xd3, 0xc7, 0x33, 0xea, 0xe9, 0x14, 0x4d, 0x78, 90 ]; 91 92 /// SHA-256 identity of the exact schema-v4 object snapshot. 93 pub const RHI_STATE_SCHEMA_VERSION_4_SHA256: [u8; 32] = [ 94 0x9c, 0xa7, 0x8a, 0x54, 0xb0, 0xea, 0x20, 0x13, 0xe7, 0xaa, 0x70, 0xd0, 0x9b, 0xea, 0xdc, 0xfb, 95 0x6c, 0xdd, 0xe0, 0x7c, 0x40, 0x42, 0x9d, 0xff, 0xe9, 0x1c, 0xb8, 0x3c, 0x2a, 0x42, 0x5c, 0xea, 96 ]; 97 98 /// SHA-256 identity of the schema-v5 reconciliation-job migration. 99 pub const RHI_STATE_SCHEMA_VERSION_5_MIGRATION_SHA256: [u8; 32] = [ 100 0x82, 0x75, 0xff, 0xb3, 0xd5, 0xc9, 0xfa, 0x0c, 0x76, 0x48, 0xf8, 0x9e, 0x8b, 0xfb, 0x92, 0x87, 101 0x7b, 0x0d, 0xcd, 0x5e, 0xf3, 0xbf, 0x0b, 0x52, 0x54, 0xb7, 0xff, 0xd2, 0x58, 0x0b, 0xd4, 0x5d, 102 ]; 103 104 /// SHA-256 identity of the exact schema-v5 object snapshot. 105 pub const RHI_STATE_SCHEMA_VERSION_5_SHA256: [u8; 32] = [ 106 0xee, 0xf6, 0x7b, 0x48, 0x40, 0x0d, 0xee, 0x23, 0x4f, 0x6c, 0x36, 0xd4, 0x22, 0x55, 0x1c, 0x7e, 107 0x99, 0x83, 0x15, 0x0b, 0x88, 0x7f, 0x26, 0x42, 0x50, 0xf9, 0xc8, 0x7a, 0x1a, 0x31, 0x3e, 0x60, 108 ]; 109 110 /// SHA-256 identity of the schema-v6 reconciliation-result migration. 111 pub const RHI_STATE_SCHEMA_VERSION_6_MIGRATION_SHA256: [u8; 32] = [ 112 0x48, 0xa1, 0x4b, 0x27, 0x44, 0xc4, 0x11, 0x86, 0x49, 0x6d, 0x59, 0x7e, 0xc7, 0x80, 0xad, 0x99, 113 0x8f, 0xa9, 0x30, 0x8a, 0x9c, 0x9d, 0x75, 0x40, 0xd4, 0x75, 0xdb, 0x3f, 0x4d, 0xcf, 0xc4, 0xbb, 114 ]; 115 116 /// SHA-256 identity of the exact schema-v6 object snapshot. 117 pub const RHI_STATE_SCHEMA_VERSION_6_SHA256: [u8; 32] = [ 118 0x5d, 0x1f, 0xa9, 0x50, 0x8b, 0x5b, 0x8a, 0x0c, 0x80, 0x65, 0xfd, 0x37, 0xf1, 0x1c, 0x68, 0x66, 119 0xd5, 0x1f, 0x92, 0x94, 0xc7, 0x52, 0x72, 0x04, 0x1f, 0x34, 0x9e, 0x95, 0xce, 0xd5, 0x0f, 0xb4, 120 ]; 121 122 /// SHA-256 identity of the schema-v7 report/publication migration. 123 pub const RHI_STATE_SCHEMA_VERSION_7_MIGRATION_SHA256: [u8; 32] = [ 124 0x9d, 0xeb, 0xf4, 0xf3, 0xca, 0xad, 0x4d, 0x01, 0x83, 0x11, 0xcb, 0x16, 0x9b, 0xf9, 0x28, 0x22, 125 0x64, 0xd6, 0xab, 0xfc, 0x49, 0xe7, 0x18, 0x84, 0x0b, 0x9c, 0xbf, 0xad, 0x42, 0xed, 0x35, 0x7c, 126 ]; 127 128 /// SHA-256 identity of the exact schema-v7 object snapshot. 129 pub const RHI_STATE_SCHEMA_VERSION_7_SHA256: [u8; 32] = [ 130 0x84, 0x0a, 0xa8, 0x3c, 0x68, 0x9f, 0x9d, 0xf9, 0x9d, 0x26, 0xc5, 0xb4, 0xef, 0x11, 0x71, 0x31, 131 0xc2, 0x70, 0xef, 0x75, 0x22, 0x67, 0x40, 0x37, 0xde, 0xf7, 0x96, 0x28, 0xa2, 0xb0, 0x39, 0x46, 132 ]; 133 134 /// SHA-256 identity of the schema-v8 reconciliation-job shape-guard migration. 135 pub const RHI_STATE_SCHEMA_VERSION_8_MIGRATION_SHA256: [u8; 32] = [ 136 0x6d, 0x3a, 0xa0, 0x6e, 0x69, 0x08, 0xe4, 0x28, 0x1b, 0x50, 0x66, 0xed, 0x4a, 0x13, 0xe2, 0x28, 137 0x7b, 0xda, 0xec, 0x05, 0xb0, 0xe5, 0x39, 0x21, 0x58, 0x91, 0x89, 0x2a, 0x5a, 0xfb, 0x58, 0x3b, 138 ]; 139 140 /// SHA-256 identity of the exact schema-v8 object snapshot. 141 pub const RHI_STATE_SCHEMA_VERSION_8_SHA256: [u8; 32] = [ 142 0x7c, 0xef, 0x55, 0x9a, 0xe1, 0xe6, 0xef, 0xe1, 0x58, 0xc5, 0xd1, 0xde, 0x50, 0x11, 0x4e, 0xba, 143 0xcc, 0xac, 0x90, 0x53, 0x8e, 0x0c, 0xd4, 0x9a, 0x4e, 0xe2, 0x14, 0xcb, 0x0a, 0x39, 0xc6, 0x18, 144 ]; 145 146 /// SHA-256 identity of the schema-v9 presence desired-state migration. 147 pub const RHI_STATE_SCHEMA_VERSION_9_MIGRATION_SHA256: [u8; 32] = [ 148 0x32, 0xda, 0xbe, 0x77, 0x72, 0x89, 0xe0, 0xfb, 0x6e, 0x64, 0xa4, 0xc1, 0xf8, 0x25, 0x78, 0x43, 149 0xfc, 0x08, 0x01, 0x83, 0x21, 0xc3, 0xb7, 0xec, 0x5c, 0xa5, 0x84, 0xfa, 0x18, 0x62, 0xbd, 0xcc, 150 ]; 151 152 /// SHA-256 identity of the exact schema-v9 object snapshot. 153 pub const RHI_STATE_SCHEMA_VERSION_9_SHA256: [u8; 32] = [ 154 0x55, 0x51, 0xe8, 0x79, 0x05, 0x44, 0xa7, 0xc7, 0x8c, 0x83, 0x76, 0xc5, 0xcc, 0xf8, 0x3d, 0xd2, 155 0xa8, 0x48, 0x6d, 0x2d, 0xc0, 0x8b, 0x6a, 0x78, 0x08, 0xbb, 0x20, 0x07, 0xc9, 0x43, 0x35, 0xec, 156 ]; 157 158 /// SHA-256 identity of the schema-v10 presence-publication migration. 159 pub const RHI_STATE_SCHEMA_VERSION_10_MIGRATION_SHA256: [u8; 32] = [ 160 0x54, 0x1a, 0xd1, 0x3b, 0x2c, 0xb0, 0x8d, 0x59, 0x85, 0x72, 0x05, 0xe6, 0xff, 0xae, 0xc1, 0x9b, 161 0x74, 0xde, 0x08, 0x53, 0x24, 0x0f, 0xdf, 0x11, 0xfa, 0x13, 0x40, 0xe4, 0x06, 0xc7, 0x11, 0x4e, 162 ]; 163 164 /// SHA-256 identity of the exact schema-v10 object snapshot. 165 pub const RHI_STATE_SCHEMA_VERSION_10_SHA256: [u8; 32] = [ 166 0xd2, 0xae, 0xd5, 0x1d, 0x0a, 0x6a, 0x2c, 0x01, 0xed, 0xa1, 0x84, 0x46, 0x08, 0x47, 0x2b, 0x2d, 167 0xcd, 0x50, 0x2a, 0xba, 0xa8, 0xa4, 0xca, 0x30, 0xa4, 0x82, 0x35, 0x35, 0xb8, 0xbd, 0x0e, 0x45, 168 ]; 169 170 /// SHA-256 identity of the schema-v11 admin-operation-journal migration. 171 pub const RHI_STATE_SCHEMA_VERSION_11_MIGRATION_SHA256: [u8; 32] = [ 172 0xe3, 0xfb, 0xde, 0x51, 0x1e, 0x84, 0x24, 0xc9, 0x70, 0x80, 0xbe, 0x2c, 0x09, 0xed, 0x81, 0x0a, 173 0xe2, 0x84, 0x63, 0x1d, 0x75, 0xeb, 0x25, 0xc2, 0xe8, 0x8a, 0x60, 0x76, 0xb7, 0x00, 0xaa, 0xef, 174 ]; 175 176 /// SHA-256 identity of the exact schema-v11 object snapshot. 177 pub const RHI_STATE_SCHEMA_VERSION_11_SHA256: [u8; 32] = [ 178 0xc2, 0x5e, 0xc6, 0x3b, 0x33, 0xb4, 0x11, 0x61, 0x80, 0x68, 0xee, 0x06, 0xa0, 0x4c, 0x99, 0xee, 179 0x71, 0x66, 0xe0, 0x01, 0x4d, 0x97, 0x90, 0x39, 0xfa, 0xea, 0xea, 0x4d, 0xc1, 0xac, 0x7e, 0x62, 180 ]; 181 182 /// SHA-256 identity of the schema catalog bound to the migration catalog. 183 pub const RHI_STATE_SCHEMA_CATALOG_SHA256: [u8; 32] = [ 184 0xae, 0xc4, 0x82, 0x81, 0x8b, 0xd9, 0xa6, 0xf3, 0x3f, 0xd9, 0x2b, 0x55, 0xd1, 0x42, 0xc6, 0xb8, 185 0x5a, 0xa6, 0xf0, 0x86, 0x85, 0x57, 0x01, 0xdf, 0xc4, 0xb7, 0x8f, 0x2a, 0x7e, 0xf5, 0xcf, 0x6d, 186 ]; 187 188 macro_rules! rhi_config_bindings_table_sql { 189 () => { 190 r#"CREATE TABLE rhi_config_bindings ( 191 generation INTEGER NOT NULL PRIMARY KEY CHECK (generation BETWEEN 1 AND 1024), 192 normalized_config_sha256 BLOB NOT NULL CHECK (length(normalized_config_sha256) = 32), 193 evidence_policy_sha256 BLOB NOT NULL CHECK (length(evidence_policy_sha256) = 32), 194 service_public_key TEXT NOT NULL 195 CHECK (length(CAST(service_public_key AS BLOB)) = 64) 196 CHECK (service_public_key NOT GLOB '*[^0-9a-f]*'), 197 config_contract_version INTEGER NOT NULL 198 CHECK (config_contract_version BETWEEN 1 AND 4294967295), 199 state_contract_version INTEGER NOT NULL 200 CHECK (state_contract_version BETWEEN 1 AND 4294967295), 201 admin_contract_version INTEGER NOT NULL 202 CHECK (admin_contract_version BETWEEN 1 AND 4294967295), 203 status_contract_version INTEGER NOT NULL 204 CHECK (status_contract_version BETWEEN 1 AND 4294967295), 205 provider_contract_version INTEGER NOT NULL 206 CHECK (provider_contract_version BETWEEN 1 AND 4294967295), 207 applied_at_unix_s INTEGER NOT NULL 208 CHECK (applied_at_unix_s BETWEEN 0 AND 9223372036854775807), 209 service_version TEXT NOT NULL 210 CHECK (length(CAST(service_version AS BLOB)) BETWEEN 1 AND 128), 211 service_commit TEXT NOT NULL 212 CHECK (length(CAST(service_commit AS BLOB)) = 40), 213 lib_revision TEXT NOT NULL 214 CHECK (length(CAST(lib_revision AS BLOB)) = 40), 215 rust_version TEXT NOT NULL 216 CHECK (length(CAST(rust_version AS BLOB)) BETWEEN 1 AND 128), 217 target TEXT NOT NULL CHECK (length(CAST(target AS BLOB)) BETWEEN 1 AND 128), 218 feature_profile TEXT NOT NULL 219 CHECK (length(CAST(feature_profile AS BLOB)) BETWEEN 1 AND 128) 220 ) STRICT"# 221 }; 222 } 223 224 macro_rules! rhi_config_bindings_guard_insert_sql { 225 () => { 226 r#"CREATE TRIGGER rhi_config_bindings_guard_insert 227 BEFORE INSERT ON rhi_config_bindings 228 WHEN NEW.generation != COALESCE( 229 (SELECT MAX(generation) + 1 FROM rhi_config_bindings), 1 230 ) 231 OR (SELECT COUNT(*) FROM rhi_config_bindings) >= 1024 232 OR NEW.applied_at_unix_s < COALESCE( 233 (SELECT MAX(applied_at_unix_s) FROM rhi_config_bindings), 0 234 ) 235 BEGIN 236 SELECT RAISE(ABORT, 'configuration binding sequence is invalid'); 237 END"# 238 }; 239 } 240 241 macro_rules! rhi_config_bindings_no_update_sql { 242 () => { 243 r#"CREATE TRIGGER rhi_config_bindings_no_update 244 BEFORE UPDATE ON rhi_config_bindings 245 BEGIN 246 SELECT RAISE(ABORT, 'configuration binding history is immutable'); 247 END"# 248 }; 249 } 250 251 macro_rules! rhi_config_bindings_no_delete_sql { 252 () => { 253 r#"CREATE TRIGGER rhi_config_bindings_no_delete 254 BEFORE DELETE ON rhi_config_bindings 255 BEGIN 256 SELECT RAISE(ABORT, 'configuration binding history is retained'); 257 END"# 258 }; 259 } 260 261 pub(crate) const CREATE_RHI_CONFIG_BINDINGS_TABLE_SQL: &str = rhi_config_bindings_table_sql!(); 262 const CREATE_RHI_CONFIG_BINDINGS_GUARD_INSERT_SQL: &str = rhi_config_bindings_guard_insert_sql!(); 263 const CREATE_RHI_CONFIG_BINDINGS_NO_UPDATE_SQL: &str = rhi_config_bindings_no_update_sql!(); 264 const CREATE_RHI_CONFIG_BINDINGS_NO_DELETE_SQL: &str = rhi_config_bindings_no_delete_sql!(); 265 const CREATE_RHI_CONFIG_BINDINGS_MIGRATION_SQL: &str = concat!( 266 rhi_config_bindings_table_sql!(), 267 ";\n", 268 rhi_config_bindings_guard_insert_sql!(), 269 ";\n", 270 rhi_config_bindings_no_update_sql!(), 271 ";\n", 272 rhi_config_bindings_no_delete_sql!(), 273 ";", 274 ); 275 276 macro_rules! trade_mutations_table_sql { 277 () => { 278 r#"CREATE TABLE trade_mutations ( 279 mutation_id BLOB NOT NULL PRIMARY KEY CHECK (length(mutation_id) = 32), 280 trade_id BLOB NOT NULL CHECK (length(trade_id) = 16), 281 contract_id TEXT NOT NULL CHECK (contract_id IN ( 282 'radroots.trade.proposal.v1', 283 'radroots.trade.decision.v1', 284 'radroots.trade.revision_proposal.v1', 285 'radroots.trade.revision_decision.v1', 286 'radroots.trade.cancellation.v1' 287 )), 288 schema_version INTEGER NOT NULL CHECK (schema_version = 1), 289 event_kind INTEGER NOT NULL CHECK (event_kind IN (3470, 3471, 3472, 3473, 3474)), 290 author_pubkey BLOB NOT NULL CHECK (length(author_pubkey) = 32), 291 canonical_content BLOB NOT NULL 292 CHECK (length(canonical_content) BETWEEN 1 AND 131072) 293 ) STRICT"# 294 }; 295 } 296 297 macro_rules! trade_mutations_by_trade_sql { 298 () => { 299 r#"CREATE INDEX trade_mutations_by_trade 300 ON trade_mutations (trade_id, mutation_id)"# 301 }; 302 } 303 304 macro_rules! nostr_events_table_sql { 305 () => { 306 r#"CREATE TABLE nostr_events ( 307 event_id BLOB NOT NULL CHECK (length(event_id) = 32), 308 event_signature BLOB NOT NULL CHECK (length(event_signature) = 64), 309 mutation_id BLOB NOT NULL CHECK (length(mutation_id) = 32) 310 REFERENCES trade_mutations (mutation_id), 311 author_pubkey BLOB NOT NULL CHECK (length(author_pubkey) = 32), 312 event_kind INTEGER NOT NULL CHECK (event_kind IN (3470, 3471, 3472, 3473, 3474)), 313 authored_at_unix_s INTEGER NOT NULL 314 CHECK (authored_at_unix_s BETWEEN 0 AND 9223372036854775807), 315 canonical_event_json BLOB NOT NULL 316 CHECK (length(canonical_event_json) BETWEEN 1 AND 524288), 317 PRIMARY KEY (event_id, event_signature) 318 ) STRICT"# 319 }; 320 } 321 322 macro_rules! nostr_events_by_mutation_sql { 323 () => { 324 r#"CREATE INDEX nostr_events_by_mutation 325 ON nostr_events (mutation_id, authored_at_unix_s, event_id)"# 326 }; 327 } 328 329 macro_rules! relay_observations_table_sql { 330 () => { 331 r#"CREATE TABLE relay_observations ( 332 source_id TEXT NOT NULL 333 CHECK (length(CAST(source_id AS BLOB)) BETWEEN 1 AND 64) 334 CHECK (source_id NOT GLOB '*[^a-z0-9_-]*') 335 CHECK (substr(source_id, 1, 1) GLOB '[a-z]'), 336 selector_id TEXT NOT NULL CHECK (selector_id = 'trade_mutation_lineage_v1'), 337 evidence_policy_sha256 BLOB NOT NULL CHECK (length(evidence_policy_sha256) = 32), 338 event_id BLOB NOT NULL CHECK (length(event_id) = 32), 339 event_signature BLOB NOT NULL CHECK (length(event_signature) = 64), 340 observed_at_unix_s INTEGER NOT NULL 341 CHECK (observed_at_unix_s BETWEEN 1 AND 9223372036854775807), 342 FOREIGN KEY (event_id, event_signature) 343 REFERENCES nostr_events (event_id, event_signature), 344 PRIMARY KEY ( 345 source_id, selector_id, evidence_policy_sha256, event_id, event_signature, 346 observed_at_unix_s 347 ) 348 ) STRICT"# 349 }; 350 } 351 352 macro_rules! relay_observations_by_event_sql { 353 () => { 354 r#"CREATE INDEX relay_observations_by_event 355 ON relay_observations (event_id, event_signature, observed_at_unix_s, source_id)"# 356 }; 357 } 358 359 macro_rules! immutable_no_update_sql { 360 ($trigger:literal, $table:literal, $message:literal) => { 361 concat!( 362 "CREATE TRIGGER ", 363 $trigger, 364 "\nBEFORE UPDATE ON ", 365 $table, 366 "\nBEGIN\n SELECT RAISE(ABORT, '", 367 $message, 368 "');\nEND" 369 ) 370 }; 371 } 372 373 macro_rules! immutable_no_delete_sql { 374 ($trigger:literal, $table:literal, $message:literal) => { 375 concat!( 376 "CREATE TRIGGER ", 377 $trigger, 378 "\nBEFORE DELETE ON ", 379 $table, 380 "\nBEGIN\n SELECT RAISE(ABORT, '", 381 $message, 382 "');\nEND" 383 ) 384 }; 385 } 386 387 pub(crate) const CREATE_TRADE_MUTATIONS_TABLE_SQL: &str = trade_mutations_table_sql!(); 388 const CREATE_TRADE_MUTATIONS_BY_TRADE_SQL: &str = trade_mutations_by_trade_sql!(); 389 pub(crate) const CREATE_NOSTR_EVENTS_TABLE_SQL: &str = nostr_events_table_sql!(); 390 const CREATE_NOSTR_EVENTS_BY_MUTATION_SQL: &str = nostr_events_by_mutation_sql!(); 391 pub(crate) const CREATE_RELAY_OBSERVATIONS_TABLE_SQL: &str = relay_observations_table_sql!(); 392 const CREATE_RELAY_OBSERVATIONS_BY_EVENT_SQL: &str = relay_observations_by_event_sql!(); 393 const CREATE_TRADE_MUTATIONS_NO_UPDATE_SQL: &str = immutable_no_update_sql!( 394 "trade_mutations_no_update", 395 "trade_mutations", 396 "trade mutation evidence is immutable" 397 ); 398 const CREATE_TRADE_MUTATIONS_NO_DELETE_SQL: &str = immutable_no_delete_sql!( 399 "trade_mutations_no_delete", 400 "trade_mutations", 401 "trade mutation evidence is retained" 402 ); 403 const CREATE_NOSTR_EVENTS_NO_UPDATE_SQL: &str = immutable_no_update_sql!( 404 "nostr_events_no_update", 405 "nostr_events", 406 "signed event evidence is immutable" 407 ); 408 const CREATE_NOSTR_EVENTS_NO_DELETE_SQL: &str = immutable_no_delete_sql!( 409 "nostr_events_no_delete", 410 "nostr_events", 411 "signed event evidence is retained" 412 ); 413 const CREATE_RELAY_OBSERVATIONS_NO_UPDATE_SQL: &str = immutable_no_update_sql!( 414 "relay_observations_no_update", 415 "relay_observations", 416 "source observation evidence is immutable" 417 ); 418 const CREATE_RELAY_OBSERVATIONS_NO_DELETE_SQL: &str = immutable_no_delete_sql!( 419 "relay_observations_no_delete", 420 "relay_observations", 421 "source observation evidence is retained" 422 ); 423 const CREATE_TRADE_EVIDENCE_MIGRATION_SQL: &str = concat!( 424 trade_mutations_table_sql!(), 425 ";\n", 426 trade_mutations_by_trade_sql!(), 427 ";\n", 428 nostr_events_table_sql!(), 429 ";\n", 430 nostr_events_by_mutation_sql!(), 431 ";\n", 432 relay_observations_table_sql!(), 433 ";\n", 434 relay_observations_by_event_sql!(), 435 ";\n", 436 immutable_no_update_sql!( 437 "trade_mutations_no_update", 438 "trade_mutations", 439 "trade mutation evidence is immutable" 440 ), 441 ";\n", 442 immutable_no_delete_sql!( 443 "trade_mutations_no_delete", 444 "trade_mutations", 445 "trade mutation evidence is retained" 446 ), 447 ";\n", 448 immutable_no_update_sql!( 449 "nostr_events_no_update", 450 "nostr_events", 451 "signed event evidence is immutable" 452 ), 453 ";\n", 454 immutable_no_delete_sql!( 455 "nostr_events_no_delete", 456 "nostr_events", 457 "signed event evidence is retained" 458 ), 459 ";\n", 460 immutable_no_update_sql!( 461 "relay_observations_no_update", 462 "relay_observations", 463 "source observation evidence is immutable" 464 ), 465 ";\n", 466 immutable_no_delete_sql!( 467 "relay_observations_no_delete", 468 "relay_observations", 469 "source observation evidence is retained" 470 ), 471 ";", 472 ); 473 474 macro_rules! relay_checkpoints_table_sql { 475 () => { 476 r#"CREATE TABLE relay_checkpoints ( 477 source_id TEXT NOT NULL 478 CHECK (length(CAST(source_id AS BLOB)) BETWEEN 1 AND 64) 479 CHECK (source_id NOT GLOB '*[^a-z0-9_-]*') 480 CHECK (substr(source_id, 1, 1) GLOB '[a-z]'), 481 selector_id TEXT NOT NULL CHECK (selector_id = 'trade_mutation_lineage_v1'), 482 evidence_policy_sha256 BLOB NOT NULL CHECK (length(evidence_policy_sha256) = 32), 483 trade_id BLOB NOT NULL CHECK (length(trade_id) = 16), 484 cursor_created_at_unix_s INTEGER NOT NULL 485 CHECK (cursor_created_at_unix_s BETWEEN 0 AND 9223372036854775807), 486 cursor_event_id BLOB NOT NULL CHECK (length(cursor_event_id) = 32), 487 revision INTEGER NOT NULL CHECK (revision BETWEEN 1 AND 9223372036854775807), 488 completed_at_unix_s INTEGER NOT NULL 489 CHECK (completed_at_unix_s BETWEEN 1 AND 9223372036854775807), 490 PRIMARY KEY (source_id, selector_id, evidence_policy_sha256, trade_id) 491 ) STRICT"# 492 }; 493 } 494 495 macro_rules! relay_checkpoints_guard_update_sql { 496 () => { 497 r#"CREATE TRIGGER relay_checkpoints_guard_update 498 BEFORE UPDATE ON relay_checkpoints 499 WHEN NEW.source_id != OLD.source_id 500 OR NEW.selector_id != OLD.selector_id 501 OR NEW.evidence_policy_sha256 != OLD.evidence_policy_sha256 502 OR NEW.trade_id != OLD.trade_id 503 OR NEW.revision != OLD.revision + 1 504 OR NEW.completed_at_unix_s < OLD.completed_at_unix_s 505 OR NEW.cursor_created_at_unix_s < OLD.cursor_created_at_unix_s 506 OR ( 507 NEW.cursor_created_at_unix_s = OLD.cursor_created_at_unix_s 508 AND NEW.cursor_event_id <= OLD.cursor_event_id 509 ) 510 BEGIN 511 SELECT RAISE(ABORT, 'relay checkpoint transition is invalid'); 512 END"# 513 }; 514 } 515 516 macro_rules! trade_dirty_generations_table_sql { 517 () => { 518 r#"CREATE TABLE trade_dirty_generations ( 519 trade_id BLOB NOT NULL PRIMARY KEY CHECK (length(trade_id) = 16), 520 generation INTEGER NOT NULL CHECK (generation BETWEEN 1 AND 9223372036854775807), 521 evidence_policy_sha256 BLOB NOT NULL CHECK (length(evidence_policy_sha256) = 32), 522 updated_at_unix_s INTEGER NOT NULL 523 CHECK (updated_at_unix_s BETWEEN 0 AND 9223372036854775807) 524 ) STRICT"# 525 }; 526 } 527 528 macro_rules! trade_dirty_generations_guard_update_sql { 529 () => { 530 r#"CREATE TRIGGER trade_dirty_generations_guard_update 531 BEFORE UPDATE ON trade_dirty_generations 532 WHEN NEW.trade_id != OLD.trade_id 533 OR NEW.generation != OLD.generation + 1 534 OR NEW.updated_at_unix_s < OLD.updated_at_unix_s 535 BEGIN 536 SELECT RAISE(ABORT, 'trade dirty generation transition is invalid'); 537 END"# 538 }; 539 } 540 541 pub(crate) const CREATE_RELAY_CHECKPOINTS_TABLE_SQL: &str = relay_checkpoints_table_sql!(); 542 const CREATE_RELAY_CHECKPOINTS_GUARD_UPDATE_SQL: &str = relay_checkpoints_guard_update_sql!(); 543 const CREATE_RELAY_CHECKPOINTS_NO_DELETE_SQL: &str = immutable_no_delete_sql!( 544 "relay_checkpoints_no_delete", 545 "relay_checkpoints", 546 "relay checkpoints are retained" 547 ); 548 pub(crate) const CREATE_TRADE_DIRTY_GENERATIONS_TABLE_SQL: &str = 549 trade_dirty_generations_table_sql!(); 550 const CREATE_TRADE_DIRTY_GENERATIONS_GUARD_UPDATE_SQL: &str = 551 trade_dirty_generations_guard_update_sql!(); 552 const CREATE_TRADE_DIRTY_GENERATIONS_NO_DELETE_SQL: &str = immutable_no_delete_sql!( 553 "trade_dirty_generations_no_delete", 554 "trade_dirty_generations", 555 "trade dirty generations are retained" 556 ); 557 const CREATE_SOURCE_CHECKPOINT_MIGRATION_SQL: &str = concat!( 558 relay_checkpoints_table_sql!(), 559 ";\n", 560 relay_checkpoints_guard_update_sql!(), 561 ";\n", 562 immutable_no_delete_sql!( 563 "relay_checkpoints_no_delete", 564 "relay_checkpoints", 565 "relay checkpoints are retained" 566 ), 567 ";\n", 568 trade_dirty_generations_table_sql!(), 569 ";\n", 570 trade_dirty_generations_guard_update_sql!(), 571 ";\n", 572 immutable_no_delete_sql!( 573 "trade_dirty_generations_no_delete", 574 "trade_dirty_generations", 575 "trade dirty generations are retained" 576 ), 577 ";", 578 ); 579 580 macro_rules! reconciliation_jobs_table_sql { 581 () => { 582 r#"CREATE TABLE reconciliation_jobs ( 583 job_id BLOB NOT NULL PRIMARY KEY CHECK (length(job_id) = 32), 584 trade_id BLOB NOT NULL CHECK (length(trade_id) = 16), 585 input_generation INTEGER NOT NULL 586 CHECK (input_generation BETWEEN 1 AND 9223372036854775807), 587 evidence_policy_sha256 BLOB NOT NULL CHECK (length(evidence_policy_sha256) = 32), 588 state TEXT NOT NULL 589 CHECK (state IN ('ready', 'leased', 'exhausted', 'superseded', 'completed')), 590 revision INTEGER NOT NULL CHECK (revision BETWEEN 1 AND 9223372036854775807), 591 attempt_count INTEGER NOT NULL CHECK (attempt_count BETWEEN 0 AND 100), 592 failure_count INTEGER NOT NULL CHECK (failure_count BETWEEN 0 AND attempt_count), 593 max_attempts INTEGER NOT NULL CHECK (max_attempts BETWEEN 1 AND 100), 594 lease_duration_ms INTEGER NOT NULL CHECK (lease_duration_ms BETWEEN 1000 AND 300000), 595 lease_renewal_ms INTEGER NOT NULL CHECK (lease_renewal_ms BETWEEN 100 AND 150000), 596 initial_backoff_ms INTEGER NOT NULL CHECK (initial_backoff_ms BETWEEN 1 AND 60000), 597 maximum_backoff_ms INTEGER NOT NULL CHECK (maximum_backoff_ms BETWEEN 1 AND 3600000), 598 next_attempt_unix_ms INTEGER, 599 lease_owner BLOB, 600 lease_expires_unix_ms INTEGER, 601 created_at_unix_ms INTEGER NOT NULL 602 CHECK (created_at_unix_ms BETWEEN 0 AND 9223372036854775807), 603 updated_at_unix_ms INTEGER NOT NULL 604 CHECK (updated_at_unix_ms BETWEEN created_at_unix_ms AND 9223372036854775807), 605 FOREIGN KEY (trade_id) REFERENCES trade_dirty_generations (trade_id), 606 CHECK (lease_renewal_ms < lease_duration_ms), 607 CHECK (initial_backoff_ms <= maximum_backoff_ms), 608 CHECK ( 609 (state = 'ready' 610 AND attempt_count < max_attempts 611 AND next_attempt_unix_ms BETWEEN 0 AND 9223372036854775807 612 AND lease_owner IS NULL 613 AND lease_expires_unix_ms IS NULL) 614 OR (state = 'leased' 615 AND attempt_count BETWEEN 1 AND max_attempts 616 AND next_attempt_unix_ms IS NULL 617 AND length(lease_owner) = 16 618 AND lease_expires_unix_ms BETWEEN 1 AND 9223372036854775807) 619 OR (state IN ('exhausted', 'superseded', 'completed') 620 AND next_attempt_unix_ms IS NULL 621 AND lease_owner IS NULL 622 AND lease_expires_unix_ms IS NULL) 623 ) 624 ) STRICT"# 625 }; 626 } 627 628 macro_rules! reconciliation_jobs_one_active_sql { 629 () => { 630 r#"CREATE UNIQUE INDEX reconciliation_jobs_one_active_per_trade 631 ON reconciliation_jobs (trade_id) 632 WHERE state IN ('ready', 'leased')"# 633 }; 634 } 635 636 macro_rules! reconciliation_jobs_schedule_sql { 637 () => { 638 r#"CREATE INDEX reconciliation_jobs_by_schedule 639 ON reconciliation_jobs ( 640 state, next_attempt_unix_ms, lease_expires_unix_ms, 641 created_at_unix_ms, job_id 642 )"# 643 }; 644 } 645 646 macro_rules! reconciliation_jobs_guard_update_sql { 647 () => { 648 r#"CREATE TRIGGER reconciliation_jobs_guard_update 649 BEFORE UPDATE ON reconciliation_jobs 650 WHEN NEW.job_id != OLD.job_id 651 OR NEW.trade_id != OLD.trade_id 652 OR NEW.input_generation != OLD.input_generation 653 OR NEW.evidence_policy_sha256 != OLD.evidence_policy_sha256 654 OR NEW.max_attempts != OLD.max_attempts 655 OR NEW.lease_duration_ms != OLD.lease_duration_ms 656 OR NEW.lease_renewal_ms != OLD.lease_renewal_ms 657 OR NEW.initial_backoff_ms != OLD.initial_backoff_ms 658 OR NEW.maximum_backoff_ms != OLD.maximum_backoff_ms 659 OR NEW.created_at_unix_ms != OLD.created_at_unix_ms 660 OR NEW.revision != OLD.revision + 1 661 OR NEW.updated_at_unix_ms < OLD.updated_at_unix_ms 662 OR NOT ( 663 (OLD.state = 'ready' AND NEW.state IN ('leased', 'superseded')) 664 OR (OLD.state = 'leased' 665 AND NEW.state IN ('leased', 'ready', 'exhausted', 'superseded', 'completed')) 666 OR (OLD.state = 'exhausted' AND NEW.state = 'superseded') 667 ) 668 BEGIN 669 SELECT RAISE(ABORT, 'reconciliation job transition is invalid'); 670 END"# 671 }; 672 } 673 674 pub(crate) const CREATE_RECONCILIATION_JOBS_TABLE_SQL: &str = reconciliation_jobs_table_sql!(); 675 const CREATE_RECONCILIATION_JOBS_ONE_ACTIVE_SQL: &str = reconciliation_jobs_one_active_sql!(); 676 const CREATE_RECONCILIATION_JOBS_SCHEDULE_SQL: &str = reconciliation_jobs_schedule_sql!(); 677 const CREATE_RECONCILIATION_JOBS_GUARD_UPDATE_SQL: &str = reconciliation_jobs_guard_update_sql!(); 678 const CREATE_RECONCILIATION_JOBS_NO_DELETE_SQL: &str = immutable_no_delete_sql!( 679 "reconciliation_jobs_no_delete", 680 "reconciliation_jobs", 681 "reconciliation jobs are retained" 682 ); 683 const CREATE_RECONCILIATION_JOBS_MIGRATION_SQL: &str = concat!( 684 reconciliation_jobs_table_sql!(), 685 ";\n", 686 reconciliation_jobs_one_active_sql!(), 687 ";\n", 688 reconciliation_jobs_schedule_sql!(), 689 ";\n", 690 reconciliation_jobs_guard_update_sql!(), 691 ";\n", 692 immutable_no_delete_sql!( 693 "reconciliation_jobs_no_delete", 694 "reconciliation_jobs", 695 "reconciliation jobs are retained" 696 ), 697 ";", 698 ); 699 700 macro_rules! reconciliation_jobs_shape_guard_insert_sql { 701 () => { 702 r#"CREATE TRIGGER reconciliation_jobs_shape_guard_insert 703 BEFORE INSERT ON reconciliation_jobs 704 WHEN (NEW.state = 'ready' AND ( 705 NEW.attempt_count >= NEW.max_attempts 706 OR typeof(NEW.next_attempt_unix_ms) != 'integer' 707 OR NEW.next_attempt_unix_ms NOT BETWEEN 0 AND 9223372036854775807 708 OR NEW.lease_owner IS NOT NULL 709 OR NEW.lease_expires_unix_ms IS NOT NULL 710 )) 711 OR (NEW.state = 'leased' AND ( 712 NEW.attempt_count NOT BETWEEN 1 AND NEW.max_attempts 713 OR NEW.next_attempt_unix_ms IS NOT NULL 714 OR typeof(NEW.lease_owner) != 'blob' 715 OR length(NEW.lease_owner) != 16 716 OR typeof(NEW.lease_expires_unix_ms) != 'integer' 717 OR NEW.lease_expires_unix_ms NOT BETWEEN 1 AND 9223372036854775807 718 )) 719 OR (NEW.state IN ('exhausted', 'superseded', 'completed') AND ( 720 NEW.next_attempt_unix_ms IS NOT NULL 721 OR NEW.lease_owner IS NOT NULL 722 OR NEW.lease_expires_unix_ms IS NOT NULL 723 )) 724 BEGIN 725 SELECT RAISE(ABORT, 'reconciliation job state shape is invalid'); 726 END"# 727 }; 728 } 729 730 macro_rules! reconciliation_jobs_shape_guard_update_sql { 731 () => { 732 r#"CREATE TRIGGER reconciliation_jobs_shape_guard_update 733 BEFORE UPDATE ON reconciliation_jobs 734 WHEN (NEW.state = 'ready' AND ( 735 NEW.attempt_count >= NEW.max_attempts 736 OR typeof(NEW.next_attempt_unix_ms) != 'integer' 737 OR NEW.next_attempt_unix_ms NOT BETWEEN 0 AND 9223372036854775807 738 OR NEW.lease_owner IS NOT NULL 739 OR NEW.lease_expires_unix_ms IS NOT NULL 740 )) 741 OR (NEW.state = 'leased' AND ( 742 NEW.attempt_count NOT BETWEEN 1 AND NEW.max_attempts 743 OR NEW.next_attempt_unix_ms IS NOT NULL 744 OR typeof(NEW.lease_owner) != 'blob' 745 OR length(NEW.lease_owner) != 16 746 OR typeof(NEW.lease_expires_unix_ms) != 'integer' 747 OR NEW.lease_expires_unix_ms NOT BETWEEN 1 AND 9223372036854775807 748 )) 749 OR (NEW.state IN ('exhausted', 'superseded', 'completed') AND ( 750 NEW.next_attempt_unix_ms IS NOT NULL 751 OR NEW.lease_owner IS NOT NULL 752 OR NEW.lease_expires_unix_ms IS NOT NULL 753 )) 754 BEGIN 755 SELECT RAISE(ABORT, 'reconciliation job state shape is invalid'); 756 END"# 757 }; 758 } 759 760 const CREATE_RECONCILIATION_JOBS_SHAPE_GUARD_INSERT_SQL: &str = 761 reconciliation_jobs_shape_guard_insert_sql!(); 762 const CREATE_RECONCILIATION_JOBS_SHAPE_GUARD_UPDATE_SQL: &str = 763 reconciliation_jobs_shape_guard_update_sql!(); 764 const CREATE_RECONCILIATION_JOB_SHAPE_GUARDS_MIGRATION_SQL: &str = concat!( 765 "CREATE TABLE reconciliation_jobs_shape_scan_v1 (\n", 766 " invalid INTEGER NOT NULL CHECK (invalid = 0)\n", 767 ") STRICT;\n", 768 "INSERT INTO reconciliation_jobs_shape_scan_v1 (invalid)\n", 769 "SELECT 1 FROM reconciliation_jobs\n", 770 "WHERE (state = 'ready' AND (\n", 771 " attempt_count >= max_attempts\n", 772 " OR typeof(next_attempt_unix_ms) != 'integer'\n", 773 " OR next_attempt_unix_ms NOT BETWEEN 0 AND 9223372036854775807\n", 774 " OR lease_owner IS NOT NULL\n", 775 " OR lease_expires_unix_ms IS NOT NULL\n", 776 " ))\n", 777 " OR (state = 'leased' AND (\n", 778 " attempt_count NOT BETWEEN 1 AND max_attempts\n", 779 " OR next_attempt_unix_ms IS NOT NULL\n", 780 " OR typeof(lease_owner) != 'blob'\n", 781 " OR length(lease_owner) != 16\n", 782 " OR typeof(lease_expires_unix_ms) != 'integer'\n", 783 " OR lease_expires_unix_ms NOT BETWEEN 1 AND 9223372036854775807\n", 784 " ))\n", 785 " OR (state IN ('exhausted', 'superseded', 'completed') AND (\n", 786 " next_attempt_unix_ms IS NOT NULL\n", 787 " OR lease_owner IS NOT NULL\n", 788 " OR lease_expires_unix_ms IS NOT NULL\n", 789 " ))\n", 790 "LIMIT 1;\n", 791 "DROP TABLE reconciliation_jobs_shape_scan_v1;\n", 792 reconciliation_jobs_shape_guard_insert_sql!(), 793 ";\n", 794 reconciliation_jobs_shape_guard_update_sql!(), 795 ";", 796 ); 797 798 macro_rules! presence_desired_state_table_sql { 799 () => { 800 r#"CREATE TABLE presence_desired_state ( 801 singleton INTEGER NOT NULL PRIMARY KEY CHECK (singleton = 1), 802 generation INTEGER NOT NULL 803 CHECK (generation BETWEEN 1 AND 9223372036854775807), 804 enabled INTEGER NOT NULL CHECK (enabled IN (0, 1)), 805 profile INTEGER NOT NULL CHECK (profile IN (0, 1)), 806 application_handler INTEGER NOT NULL CHECK (application_handler IN (0, 1)), 807 target_set_sha256 BLOB NOT NULL CHECK (length(target_set_sha256) = 32), 808 target_count INTEGER NOT NULL CHECK (target_count BETWEEN 0 AND 32), 809 required_target_count INTEGER NOT NULL 810 CHECK (required_target_count BETWEEN 0 AND target_count), 811 queue_capacity INTEGER NOT NULL CHECK (queue_capacity BETWEEN 0 AND 4096), 812 desired_sha256 BLOB NOT NULL UNIQUE CHECK (length(desired_sha256) = 32), 813 CHECK ( 814 (enabled = 0 AND profile = 0 AND application_handler = 0 815 AND target_count = 0 AND required_target_count = 0 816 AND queue_capacity = 0) 817 OR 818 (enabled = 1 AND (profile = 1 OR application_handler = 1) 819 AND target_count BETWEEN 1 AND 32 820 AND queue_capacity BETWEEN 1 AND 4096) 821 ) 822 ) STRICT"# 823 }; 824 } 825 826 macro_rules! presence_desired_state_guard_insert_sql { 827 () => { 828 r#"CREATE TRIGGER presence_desired_state_guard_insert 829 BEFORE INSERT ON presence_desired_state 830 WHEN NEW.generation != 1 831 OR EXISTS (SELECT 1 FROM presence_desired_state) 832 BEGIN 833 SELECT RAISE(ABORT, 'presence desired-state insertion is invalid'); 834 END"# 835 }; 836 } 837 838 macro_rules! presence_desired_state_guard_update_sql { 839 () => { 840 r#"CREATE TRIGGER presence_desired_state_guard_update 841 BEFORE UPDATE ON presence_desired_state 842 WHEN NEW.singleton != OLD.singleton 843 OR OLD.generation >= 9223372036854775807 844 OR NEW.generation != OLD.generation + 1 845 OR NEW.desired_sha256 = OLD.desired_sha256 846 BEGIN 847 SELECT RAISE(ABORT, 'presence desired-state transition is invalid'); 848 END"# 849 }; 850 } 851 852 macro_rules! presence_desired_state_no_delete_sql { 853 () => { 854 r#"CREATE TRIGGER presence_desired_state_no_delete 855 BEFORE DELETE ON presence_desired_state 856 BEGIN 857 SELECT RAISE(ABORT, 'presence desired state is retained'); 858 END"# 859 }; 860 } 861 862 const CREATE_PRESENCE_DESIRED_STATE_TABLE_SQL: &str = presence_desired_state_table_sql!(); 863 const CREATE_PRESENCE_DESIRED_STATE_GUARD_INSERT_SQL: &str = 864 presence_desired_state_guard_insert_sql!(); 865 const CREATE_PRESENCE_DESIRED_STATE_GUARD_UPDATE_SQL: &str = 866 presence_desired_state_guard_update_sql!(); 867 const CREATE_PRESENCE_DESIRED_STATE_NO_DELETE_SQL: &str = presence_desired_state_no_delete_sql!(); 868 const CREATE_PRESENCE_DESIRED_STATE_MIGRATION_SQL: &str = concat!( 869 presence_desired_state_table_sql!(), 870 ";\n", 871 presence_desired_state_guard_insert_sql!(), 872 ";\n", 873 presence_desired_state_guard_update_sql!(), 874 ";\n", 875 presence_desired_state_no_delete_sql!(), 876 ";", 877 ); 878 879 macro_rules! presence_outbox_table_sql { 880 () => { 881 r#"CREATE TABLE presence_outbox ( 882 outbox_id BLOB NOT NULL PRIMARY KEY CHECK (length(outbox_id) = 32), 883 desired_generation INTEGER NOT NULL 884 CHECK (desired_generation BETWEEN 1 AND 9223372036854775807), 885 document_kind TEXT NOT NULL 886 CHECK (document_kind IN ('service_profile', 'application_handler')), 887 desired_sha256 BLOB NOT NULL CHECK (length(desired_sha256) = 32), 888 target_set_sha256 BLOB NOT NULL CHECK (length(target_set_sha256) = 32), 889 event_id BLOB NOT NULL CHECK (length(event_id) = 32), 890 event_sha256 BLOB NOT NULL CHECK (length(event_sha256) = 32), 891 exact_signed_event_bytes BLOB NOT NULL 892 CHECK (length(exact_signed_event_bytes) BETWEEN 1 AND 32768), 893 authored_at_unix_s INTEGER NOT NULL 894 CHECK (authored_at_unix_s BETWEEN 0 AND 9223372036854775807), 895 service_public_key TEXT NOT NULL 896 CHECK (length(CAST(service_public_key AS BLOB)) = 64) 897 CHECK (service_public_key NOT GLOB '*[^0-9a-f]*'), 898 target_count INTEGER NOT NULL CHECK (target_count BETWEEN 1 AND 32), 899 required_target_count INTEGER NOT NULL 900 CHECK (required_target_count BETWEEN 0 AND target_count), 901 max_attempts INTEGER NOT NULL CHECK (max_attempts = 100), 902 initial_backoff_ms INTEGER NOT NULL CHECK (initial_backoff_ms = 250), 903 maximum_backoff_ms INTEGER NOT NULL CHECK (maximum_backoff_ms = 30000), 904 attempt_deadline_ms INTEGER NOT NULL CHECK (attempt_deadline_ms = 15000), 905 state TEXT NOT NULL 906 CHECK (state IN ('pending', 'leased', 'complete', 'blocked', 'superseded')), 907 revision INTEGER NOT NULL CHECK (revision >= 1), 908 next_attempt_unix_ms INTEGER 909 CHECK (next_attempt_unix_ms IS NULL 910 OR next_attempt_unix_ms BETWEEN 0 AND 9223372036854775807), 911 lease_owner BLOB CHECK (lease_owner IS NULL OR length(lease_owner) = 16), 912 lease_expires_unix_ms INTEGER 913 CHECK (lease_expires_unix_ms IS NULL 914 OR lease_expires_unix_ms BETWEEN 1 AND 9223372036854775807), 915 created_at_unix_ms INTEGER NOT NULL 916 CHECK (created_at_unix_ms BETWEEN 0 AND 9223372036854775807), 917 updated_at_unix_ms INTEGER NOT NULL 918 CHECK (updated_at_unix_ms BETWEEN created_at_unix_ms AND 9223372036854775807), 919 UNIQUE (desired_generation, document_kind), 920 CHECK ( 921 (state = 'pending' AND next_attempt_unix_ms IS NOT NULL 922 AND lease_owner IS NULL AND lease_expires_unix_ms IS NULL) 923 OR 924 (state = 'leased' AND next_attempt_unix_ms IS NULL 925 AND lease_owner IS NOT NULL AND lease_expires_unix_ms IS NOT NULL) 926 OR 927 (state IN ('complete', 'blocked', 'superseded') 928 AND next_attempt_unix_ms IS NULL 929 AND lease_owner IS NULL AND lease_expires_unix_ms IS NULL) 930 ) 931 ) STRICT"# 932 }; 933 } 934 935 macro_rules! presence_outbox_schedule_sql { 936 () => { 937 r#"CREATE INDEX presence_outbox_by_schedule 938 ON presence_outbox (state, next_attempt_unix_ms, created_at_unix_ms, document_kind, outbox_id)"# 939 }; 940 } 941 942 macro_rules! presence_outbox_guard_update_sql { 943 () => { 944 r#"CREATE TRIGGER presence_outbox_guard_update 945 BEFORE UPDATE ON presence_outbox 946 WHEN NEW.outbox_id != OLD.outbox_id 947 OR NEW.desired_generation != OLD.desired_generation 948 OR NEW.document_kind != OLD.document_kind 949 OR NEW.desired_sha256 != OLD.desired_sha256 950 OR NEW.target_set_sha256 != OLD.target_set_sha256 951 OR NEW.event_id != OLD.event_id 952 OR NEW.event_sha256 != OLD.event_sha256 953 OR NEW.exact_signed_event_bytes != OLD.exact_signed_event_bytes 954 OR NEW.authored_at_unix_s != OLD.authored_at_unix_s 955 OR NEW.service_public_key != OLD.service_public_key 956 OR NEW.target_count != OLD.target_count 957 OR NEW.required_target_count != OLD.required_target_count 958 OR NEW.max_attempts != OLD.max_attempts 959 OR NEW.initial_backoff_ms != OLD.initial_backoff_ms 960 OR NEW.maximum_backoff_ms != OLD.maximum_backoff_ms 961 OR NEW.attempt_deadline_ms != OLD.attempt_deadline_ms 962 OR NEW.created_at_unix_ms != OLD.created_at_unix_ms 963 OR NEW.revision != OLD.revision + 1 964 OR NEW.updated_at_unix_ms < OLD.updated_at_unix_ms 965 OR NOT ( 966 (OLD.state = 'pending' AND NEW.state IN ('leased', 'superseded')) 967 OR (OLD.state = 'leased' 968 AND NEW.state IN ('pending', 'complete', 'blocked', 'superseded')) 969 OR (OLD.state = 'blocked' AND NEW.state IN ('pending', 'superseded')) 970 ) 971 BEGIN 972 SELECT RAISE(ABORT, 'presence outbox transition is invalid'); 973 END"# 974 }; 975 } 976 977 macro_rules! presence_targets_table_sql { 978 () => { 979 r#"CREATE TABLE presence_targets ( 980 outbox_id BLOB NOT NULL CHECK (length(outbox_id) = 32), 981 target_ordinal INTEGER NOT NULL CHECK (target_ordinal BETWEEN 0 AND 31), 982 relay_id TEXT NOT NULL 983 CHECK (length(CAST(relay_id AS BLOB)) BETWEEN 1 AND 64) 984 CHECK (relay_id NOT GLOB '*[^a-z0-9_-]*') 985 CHECK (substr(relay_id, 1, 1) GLOB '[a-z]'), 986 required INTEGER NOT NULL CHECK (required IN (0, 1)), 987 state TEXT NOT NULL CHECK (state IN ( 988 'pending', 'submitted', 'accepted', 'rejected', 989 'rate_limited', 'auth_required', 'failed', 'unknown' 990 )), 991 revision INTEGER NOT NULL CHECK (revision >= 1), 992 attempt_count INTEGER NOT NULL CHECK (attempt_count BETWEEN 0 AND 100), 993 next_attempt_unix_ms INTEGER 994 CHECK (next_attempt_unix_ms IS NULL 995 OR next_attempt_unix_ms BETWEEN 0 AND 9223372036854775807), 996 last_attempt_id BLOB 997 CHECK (last_attempt_id IS NULL OR length(last_attempt_id) = 32), 998 updated_at_unix_ms INTEGER NOT NULL 999 CHECK (updated_at_unix_ms BETWEEN 0 AND 9223372036854775807), 1000 PRIMARY KEY (outbox_id, target_ordinal), 1001 UNIQUE (outbox_id, relay_id), 1002 FOREIGN KEY (outbox_id) REFERENCES presence_outbox (outbox_id), 1003 CHECK ( 1004 (state = 'pending' AND attempt_count = 0 1005 AND next_attempt_unix_ms IS NOT NULL AND last_attempt_id IS NULL) 1006 OR 1007 (state = 'submitted' AND attempt_count BETWEEN 1 AND 100 1008 AND next_attempt_unix_ms IS NULL AND last_attempt_id IS NOT NULL) 1009 OR 1010 (state IN ('accepted', 'rejected', 'auth_required') 1011 AND attempt_count BETWEEN 1 AND 100 1012 AND next_attempt_unix_ms IS NULL AND last_attempt_id IS NOT NULL) 1013 OR 1014 (state IN ('rate_limited', 'failed', 'unknown') 1015 AND attempt_count BETWEEN 1 AND 99 1016 AND next_attempt_unix_ms IS NOT NULL AND last_attempt_id IS NOT NULL) 1017 OR 1018 (state IN ('rate_limited', 'failed', 'unknown') 1019 AND attempt_count = 100 1020 AND next_attempt_unix_ms IS NULL AND last_attempt_id IS NOT NULL) 1021 ) 1022 ) STRICT"# 1023 }; 1024 } 1025 1026 macro_rules! presence_targets_schedule_sql { 1027 () => { 1028 r#"CREATE INDEX presence_targets_by_schedule 1029 ON presence_targets (state, next_attempt_unix_ms, outbox_id, target_ordinal)"# 1030 }; 1031 } 1032 1033 macro_rules! presence_targets_guard_update_sql { 1034 () => { 1035 r#"CREATE TRIGGER presence_targets_guard_update 1036 BEFORE UPDATE ON presence_targets 1037 WHEN NEW.outbox_id != OLD.outbox_id 1038 OR NEW.target_ordinal != OLD.target_ordinal 1039 OR NEW.relay_id != OLD.relay_id 1040 OR NEW.required != OLD.required 1041 OR NEW.revision != OLD.revision + 1 1042 OR NEW.updated_at_unix_ms < OLD.updated_at_unix_ms 1043 OR NOT ( 1044 (OLD.state IN ('pending', 'rate_limited', 'failed', 'unknown') 1045 AND NEW.state = 'submitted' 1046 AND NEW.attempt_count = OLD.attempt_count + 1 1047 AND NEW.last_attempt_id IS NOT NULL 1048 AND NEW.last_attempt_id IS NOT OLD.last_attempt_id) 1049 OR 1050 (OLD.state = 'submitted' 1051 AND NEW.state IN ( 1052 'accepted', 'rejected', 'rate_limited', 1053 'auth_required', 'failed', 'unknown' 1054 ) 1055 AND NEW.attempt_count = OLD.attempt_count 1056 AND NEW.last_attempt_id = OLD.last_attempt_id) 1057 ) 1058 BEGIN 1059 SELECT RAISE(ABORT, 'presence target transition is invalid'); 1060 END"# 1061 }; 1062 } 1063 1064 macro_rules! presence_attempts_table_sql { 1065 () => { 1066 r#"CREATE TABLE presence_attempts ( 1067 attempt_id BLOB NOT NULL PRIMARY KEY CHECK (length(attempt_id) = 32), 1068 outbox_id BLOB NOT NULL CHECK (length(outbox_id) = 32), 1069 target_ordinal INTEGER NOT NULL CHECK (target_ordinal BETWEEN 0 AND 31), 1070 attempt_number INTEGER NOT NULL CHECK (attempt_number BETWEEN 1 AND 100), 1071 event_sha256 BLOB NOT NULL CHECK (length(event_sha256) = 32), 1072 lease_owner BLOB NOT NULL CHECK (length(lease_owner) = 16), 1073 started_at_unix_ms INTEGER NOT NULL 1074 CHECK (started_at_unix_ms BETWEEN 0 AND 9223372036854775807), 1075 finished_at_unix_ms INTEGER NOT NULL 1076 CHECK (finished_at_unix_ms BETWEEN started_at_unix_ms AND 9223372036854775807), 1077 outcome TEXT NOT NULL CHECK (outcome IN ( 1078 'accepted', 'rejected', 'rate_limited', 1079 'auth_required', 'failed', 'unknown' 1080 )), 1081 result_code TEXT NOT NULL 1082 CHECK (length(CAST(result_code AS BLOB)) BETWEEN 1 AND 64), 1083 UNIQUE (outbox_id, target_ordinal, attempt_number), 1084 FOREIGN KEY (outbox_id, target_ordinal) 1085 REFERENCES presence_targets (outbox_id, target_ordinal) 1086 ) STRICT"# 1087 }; 1088 } 1089 1090 const CREATE_PRESENCE_OUTBOX_TABLE_SQL: &str = presence_outbox_table_sql!(); 1091 const CREATE_PRESENCE_OUTBOX_SCHEDULE_SQL: &str = presence_outbox_schedule_sql!(); 1092 const CREATE_PRESENCE_OUTBOX_GUARD_UPDATE_SQL: &str = presence_outbox_guard_update_sql!(); 1093 const CREATE_PRESENCE_OUTBOX_NO_DELETE_SQL: &str = immutable_no_delete_sql!( 1094 "presence_outbox_no_delete", 1095 "presence_outbox", 1096 "presence outbox rows are retained" 1097 ); 1098 const CREATE_PRESENCE_TARGETS_TABLE_SQL: &str = presence_targets_table_sql!(); 1099 const CREATE_PRESENCE_TARGETS_SCHEDULE_SQL: &str = presence_targets_schedule_sql!(); 1100 const CREATE_PRESENCE_TARGETS_GUARD_UPDATE_SQL: &str = presence_targets_guard_update_sql!(); 1101 const CREATE_PRESENCE_TARGETS_NO_DELETE_SQL: &str = immutable_no_delete_sql!( 1102 "presence_targets_no_delete", 1103 "presence_targets", 1104 "presence targets are retained" 1105 ); 1106 const CREATE_PRESENCE_ATTEMPTS_TABLE_SQL: &str = presence_attempts_table_sql!(); 1107 const CREATE_PRESENCE_ATTEMPTS_NO_UPDATE_SQL: &str = immutable_no_update_sql!( 1108 "presence_attempts_no_update", 1109 "presence_attempts", 1110 "presence attempts are immutable" 1111 ); 1112 const CREATE_PRESENCE_ATTEMPTS_NO_DELETE_SQL: &str = immutable_no_delete_sql!( 1113 "presence_attempts_no_delete", 1114 "presence_attempts", 1115 "presence attempts are retained" 1116 ); 1117 1118 const CREATE_PRESENCE_PUBLICATION_MIGRATION_SQL: &str = concat!( 1119 presence_outbox_table_sql!(), 1120 ";\n", 1121 presence_outbox_schedule_sql!(), 1122 ";\n", 1123 presence_outbox_guard_update_sql!(), 1124 ";\n", 1125 immutable_no_delete_sql!( 1126 "presence_outbox_no_delete", 1127 "presence_outbox", 1128 "presence outbox rows are retained" 1129 ), 1130 ";\n", 1131 presence_targets_table_sql!(), 1132 ";\n", 1133 presence_targets_schedule_sql!(), 1134 ";\n", 1135 presence_targets_guard_update_sql!(), 1136 ";\n", 1137 immutable_no_delete_sql!( 1138 "presence_targets_no_delete", 1139 "presence_targets", 1140 "presence targets are retained" 1141 ), 1142 ";\n", 1143 presence_attempts_table_sql!(), 1144 ";\n", 1145 immutable_no_update_sql!( 1146 "presence_attempts_no_update", 1147 "presence_attempts", 1148 "presence attempts are immutable" 1149 ), 1150 ";\n", 1151 immutable_no_delete_sql!( 1152 "presence_attempts_no_delete", 1153 "presence_attempts", 1154 "presence attempts are retained" 1155 ), 1156 ";" 1157 ); 1158 1159 macro_rules! evidence_reconciliations_table_sql { 1160 () => { 1161 r#"CREATE TABLE evidence_reconciliations ( 1162 attempt_id BLOB NOT NULL PRIMARY KEY CHECK (length(attempt_id) = 32), 1163 job_id BLOB NOT NULL CHECK (length(job_id) = 32), 1164 trade_id BLOB NOT NULL CHECK (length(trade_id) = 16), 1165 input_generation INTEGER NOT NULL 1166 CHECK (input_generation BETWEEN 1 AND 9223372036854775807), 1167 evidence_policy_sha256 BLOB NOT NULL CHECK (length(evidence_policy_sha256) = 32), 1168 attempt_started_unix_ms INTEGER NOT NULL 1169 CHECK (attempt_started_unix_ms BETWEEN 0 AND 9223372036854775807), 1170 deadline_unix_ms INTEGER NOT NULL 1171 CHECK (deadline_unix_ms BETWEEN attempt_started_unix_ms + 1 AND 9223372036854775807), 1172 source_count INTEGER NOT NULL CHECK (source_count BETWEEN 1 AND 16), 1173 FOREIGN KEY (job_id) REFERENCES reconciliation_jobs (job_id) 1174 ) STRICT"# 1175 }; 1176 } 1177 1178 macro_rules! evidence_reconciliation_sources_table_sql { 1179 () => { 1180 r#"CREATE TABLE evidence_reconciliation_sources ( 1181 attempt_id BLOB NOT NULL CHECK (length(attempt_id) = 32), 1182 request_id BLOB NOT NULL CHECK (length(request_id) = 32), 1183 source_ordinal INTEGER NOT NULL CHECK (source_ordinal BETWEEN 0 AND 15), 1184 source_id TEXT NOT NULL 1185 CHECK (length(CAST(source_id AS BLOB)) BETWEEN 1 AND 64) 1186 CHECK (source_id NOT GLOB '*[^a-z0-9_-]*') 1187 CHECK (substr(source_id, 1, 1) GLOB '[a-z]'), 1188 trade_id BLOB NOT NULL CHECK (length(trade_id) = 16), 1189 required INTEGER NOT NULL CHECK (required IN (0, 1)), 1190 selector_sha256 BLOB NOT NULL CHECK (length(selector_sha256) = 32), 1191 replay_id BLOB NOT NULL CHECK (length(replay_id) = 32), 1192 completion TEXT NOT NULL CHECK (completion IN ( 1193 'complete', 'incomplete_timeout', 'incomplete_unavailable', 1194 'incomplete_resource_limit', 'incomplete_unknown', 'unsupported' 1195 )), 1196 started_unix_ms INTEGER NOT NULL 1197 CHECK (started_unix_ms BETWEEN 0 AND 9223372036854775807), 1198 finished_unix_ms INTEGER NOT NULL 1199 CHECK (finished_unix_ms BETWEEN started_unix_ms AND 9223372036854775807), 1200 accepted_event_count INTEGER NOT NULL CHECK (accepted_event_count BETWEEN 0 AND 4096), 1201 accepted_event_bytes INTEGER NOT NULL CHECK (accepted_event_bytes BETWEEN 0 AND 8388608), 1202 accepted_inventory_sha256 BLOB NOT NULL CHECK (length(accepted_inventory_sha256) = 32), 1203 duplicate_observation_count INTEGER NOT NULL 1204 CHECK (duplicate_observation_count BETWEEN 0 AND 4096), 1205 first_observed_unix_s INTEGER 1206 CHECK (first_observed_unix_s BETWEEN 0 AND 9223372036854775807), 1207 prior_cursor_created_at_unix_s INTEGER 1208 CHECK (prior_cursor_created_at_unix_s BETWEEN 0 AND 9223372036854775807), 1209 prior_cursor_event_id BLOB CHECK (length(prior_cursor_event_id) = 32), 1210 overlap_seconds INTEGER NOT NULL CHECK (overlap_seconds BETWEEN 1 AND 86400), 1211 inclusive_since_unix_s INTEGER NOT NULL 1212 CHECK (inclusive_since_unix_s BETWEEN 0 AND 9223372036854775807), 1213 candidate_created_at_unix_s INTEGER 1214 CHECK (candidate_created_at_unix_s BETWEEN 0 AND 9223372036854775807), 1215 candidate_event_id BLOB CHECK (length(candidate_event_id) = 32), 1216 checkpoint_advanced INTEGER NOT NULL CHECK (checkpoint_advanced IN (0, 1)), 1217 PRIMARY KEY (attempt_id, request_id), 1218 UNIQUE (attempt_id, source_ordinal), 1219 FOREIGN KEY (attempt_id) REFERENCES evidence_reconciliations (attempt_id), 1220 CHECK ((accepted_event_count = 0) = (accepted_event_bytes = 0)), 1221 CHECK ((accepted_event_count = 0) = (first_observed_unix_s IS NULL)), 1222 CHECK ((accepted_event_count = 0) = (candidate_created_at_unix_s IS NULL)), 1223 CHECK ((candidate_created_at_unix_s IS NULL) = (candidate_event_id IS NULL)), 1224 CHECK ((prior_cursor_created_at_unix_s IS NULL) = (prior_cursor_event_id IS NULL)), 1225 CHECK (checkpoint_advanced = 0 OR completion = 'complete'), 1226 CHECK (checkpoint_advanced = 0 OR candidate_event_id IS NOT NULL) 1227 ) STRICT"# 1228 }; 1229 } 1230 1231 const CREATE_EVIDENCE_RECONCILIATIONS_TABLE_SQL: &str = evidence_reconciliations_table_sql!(); 1232 const CREATE_EVIDENCE_RECONCILIATIONS_NO_UPDATE_SQL: &str = immutable_no_update_sql!( 1233 "evidence_reconciliations_no_update", 1234 "evidence_reconciliations", 1235 "reconciliation attempts are immutable" 1236 ); 1237 const CREATE_EVIDENCE_RECONCILIATIONS_NO_DELETE_SQL: &str = immutable_no_delete_sql!( 1238 "evidence_reconciliations_no_delete", 1239 "evidence_reconciliations", 1240 "reconciliation attempts are retained" 1241 ); 1242 const CREATE_EVIDENCE_RECONCILIATION_SOURCES_TABLE_SQL: &str = 1243 evidence_reconciliation_sources_table_sql!(); 1244 const CREATE_EVIDENCE_RECONCILIATION_SOURCES_NO_UPDATE_SQL: &str = immutable_no_update_sql!( 1245 "evidence_reconciliation_sources_no_update", 1246 "evidence_reconciliation_sources", 1247 "reconciliation source results are immutable" 1248 ); 1249 const CREATE_EVIDENCE_RECONCILIATION_SOURCES_NO_DELETE_SQL: &str = immutable_no_delete_sql!( 1250 "evidence_reconciliation_sources_no_delete", 1251 "evidence_reconciliation_sources", 1252 "reconciliation source results are retained" 1253 ); 1254 const CREATE_RECONCILIATION_RESULTS_MIGRATION_SQL: &str = concat!( 1255 evidence_reconciliations_table_sql!(), 1256 ";\n", 1257 immutable_no_update_sql!( 1258 "evidence_reconciliations_no_update", 1259 "evidence_reconciliations", 1260 "reconciliation attempts are immutable" 1261 ), 1262 ";\n", 1263 immutable_no_delete_sql!( 1264 "evidence_reconciliations_no_delete", 1265 "evidence_reconciliations", 1266 "reconciliation attempts are retained" 1267 ), 1268 ";\n", 1269 evidence_reconciliation_sources_table_sql!(), 1270 ";\n", 1271 immutable_no_update_sql!( 1272 "evidence_reconciliation_sources_no_update", 1273 "evidence_reconciliation_sources", 1274 "reconciliation source results are immutable" 1275 ), 1276 ";\n", 1277 immutable_no_delete_sql!( 1278 "evidence_reconciliation_sources_no_delete", 1279 "evidence_reconciliation_sources", 1280 "reconciliation source results are retained" 1281 ), 1282 ";", 1283 ); 1284 1285 macro_rules! evidence_manifests_table_sql { 1286 () => { 1287 r#"CREATE TABLE evidence_manifests ( 1288 manifest_sha256 BLOB NOT NULL PRIMARY KEY CHECK (length(manifest_sha256) = 32), 1289 attempt_id BLOB NOT NULL UNIQUE CHECK (length(attempt_id) = 32), 1290 trade_id BLOB NOT NULL CHECK (length(trade_id) = 16), 1291 trade_generation INTEGER NOT NULL 1292 CHECK (trade_generation BETWEEN 1 AND 9223372036854775807), 1293 evidence_policy_sha256 BLOB NOT NULL CHECK (length(evidence_policy_sha256) = 32), 1294 canonical_manifest BLOB NOT NULL 1295 CHECK (length(canonical_manifest) BETWEEN 1 AND 16777216), 1296 observed_at_unix_s INTEGER NOT NULL 1297 CHECK (observed_at_unix_s BETWEEN 0 AND 9223372036854775807), 1298 source_count INTEGER NOT NULL CHECK (source_count BETWEEN 1 AND 16), 1299 observation_count INTEGER NOT NULL CHECK (observation_count BETWEEN 0 AND 65536), 1300 FOREIGN KEY (attempt_id) REFERENCES evidence_reconciliations (attempt_id) 1301 ) STRICT"# 1302 }; 1303 } 1304 1305 macro_rules! trade_projections_table_sql { 1306 () => { 1307 r#"CREATE TABLE trade_projections ( 1308 projection_sha256 BLOB NOT NULL PRIMARY KEY CHECK (length(projection_sha256) = 32), 1309 manifest_sha256 BLOB NOT NULL UNIQUE CHECK (length(manifest_sha256) = 32), 1310 shared_projection_sha256 BLOB NOT NULL CHECK (length(shared_projection_sha256) = 32), 1311 reducer_contract TEXT NOT NULL CHECK (reducer_contract = 'radroots.trade.reducer.v1'), 1312 reducer_contract_version INTEGER NOT NULL CHECK (reducer_contract_version = 1), 1313 issue_count INTEGER NOT NULL CHECK (issue_count BETWEEN 0 AND 65536), 1314 FOREIGN KEY (manifest_sha256) REFERENCES evidence_manifests (manifest_sha256) 1315 ) STRICT"# 1316 }; 1317 } 1318 1319 macro_rules! attestation_reports_table_sql { 1320 () => { 1321 r#"CREATE TABLE attestation_reports ( 1322 statement_sha256 BLOB NOT NULL PRIMARY KEY CHECK (length(statement_sha256) = 32), 1323 manifest_sha256 BLOB NOT NULL CHECK (length(manifest_sha256) = 32), 1324 projection_sha256 BLOB NOT NULL CHECK (length(projection_sha256) = 32), 1325 trade_id BLOB NOT NULL CHECK (length(trade_id) = 16), 1326 claim_mutation_id BLOB NOT NULL CHECK (length(claim_mutation_id) = 32), 1327 issuer_public_key BLOB NOT NULL CHECK (length(issuer_public_key) = 32), 1328 outcome TEXT NOT NULL CHECK (outcome IN ('valid', 'invalid', 'indeterminate')), 1329 canonical_report BLOB NOT NULL CHECK (length(canonical_report) BETWEEN 1 AND 16384), 1330 observed_at_unix_s INTEGER NOT NULL 1331 CHECK (observed_at_unix_s BETWEEN 0 AND 9223372036854775807), 1332 supersedes_statement_sha256 BLOB CHECK (length(supersedes_statement_sha256) = 32), 1333 supersedes_event_id BLOB CHECK (length(supersedes_event_id) = 32), 1334 FOREIGN KEY (manifest_sha256) REFERENCES evidence_manifests (manifest_sha256), 1335 FOREIGN KEY (projection_sha256) REFERENCES trade_projections (projection_sha256), 1336 FOREIGN KEY (supersedes_statement_sha256) 1337 REFERENCES attestation_reports (statement_sha256), 1338 CHECK ((supersedes_statement_sha256 IS NULL) = (supersedes_event_id IS NULL)) 1339 ) STRICT"# 1340 }; 1341 } 1342 1343 macro_rules! attestation_reports_supersession_sql { 1344 () => { 1345 r#"CREATE UNIQUE INDEX attestation_reports_one_successor 1346 ON attestation_reports (supersedes_statement_sha256) 1347 WHERE supersedes_statement_sha256 IS NOT NULL"# 1348 }; 1349 } 1350 1351 macro_rules! signed_attestation_events_table_sql { 1352 () => { 1353 r#"CREATE TABLE signed_attestation_events ( 1354 event_id BLOB NOT NULL PRIMARY KEY CHECK (length(event_id) = 32), 1355 statement_sha256 BLOB NOT NULL UNIQUE CHECK (length(statement_sha256) = 32), 1356 event_sha256 BLOB NOT NULL UNIQUE CHECK (length(event_sha256) = 32), 1357 issuer_public_key BLOB NOT NULL CHECK (length(issuer_public_key) = 32), 1358 authored_at_unix_s INTEGER NOT NULL 1359 CHECK (authored_at_unix_s BETWEEN 0 AND 9223372036854775807), 1360 canonical_event_json BLOB NOT NULL 1361 CHECK (length(canonical_event_json) BETWEEN 1 AND 32768), 1362 FOREIGN KEY (statement_sha256) REFERENCES attestation_reports (statement_sha256) 1363 ) STRICT"# 1364 }; 1365 } 1366 1367 macro_rules! publication_outbox_table_sql { 1368 () => { 1369 r#"CREATE TABLE publication_outbox ( 1370 outbox_id BLOB NOT NULL PRIMARY KEY CHECK (length(outbox_id) = 32), 1371 event_id BLOB NOT NULL UNIQUE CHECK (length(event_id) = 32), 1372 event_sha256 BLOB NOT NULL CHECK (length(event_sha256) = 32), 1373 publication_authority_sha256 BLOB NOT NULL 1374 CHECK (length(publication_authority_sha256) = 32), 1375 target_set_sha256 BLOB NOT NULL CHECK (length(target_set_sha256) = 32), 1376 target_count INTEGER NOT NULL CHECK (target_count BETWEEN 1 AND 32), 1377 required_target_count INTEGER NOT NULL 1378 CHECK (required_target_count BETWEEN 0 AND target_count), 1379 max_attempts INTEGER NOT NULL CHECK (max_attempts BETWEEN 1 AND 100), 1380 initial_backoff_ms INTEGER NOT NULL CHECK (initial_backoff_ms BETWEEN 1 AND 60000), 1381 maximum_backoff_ms INTEGER NOT NULL CHECK (maximum_backoff_ms BETWEEN 1 AND 3600000), 1382 attempt_deadline_ms INTEGER NOT NULL CHECK (attempt_deadline_ms BETWEEN 100 AND 30000), 1383 state TEXT NOT NULL CHECK (state IN ('pending', 'leased', 'complete', 'blocked')), 1384 revision INTEGER NOT NULL CHECK (revision BETWEEN 1 AND 9223372036854775807), 1385 next_attempt_unix_ms INTEGER, 1386 lease_owner BLOB, 1387 lease_expires_unix_ms INTEGER, 1388 created_at_unix_ms INTEGER NOT NULL 1389 CHECK (created_at_unix_ms BETWEEN 0 AND 9223372036854775807), 1390 updated_at_unix_ms INTEGER NOT NULL 1391 CHECK (updated_at_unix_ms BETWEEN created_at_unix_ms AND 9223372036854775807), 1392 FOREIGN KEY (event_id) REFERENCES signed_attestation_events (event_id), 1393 CHECK (initial_backoff_ms <= maximum_backoff_ms), 1394 CHECK ( 1395 (state = 'pending' 1396 AND next_attempt_unix_ms IS NOT NULL 1397 AND next_attempt_unix_ms BETWEEN 0 AND 9223372036854775807 1398 AND lease_owner IS NULL AND lease_expires_unix_ms IS NULL) 1399 OR (state = 'leased' 1400 AND next_attempt_unix_ms IS NULL 1401 AND lease_owner IS NOT NULL 1402 AND length(lease_owner) = 16 1403 AND lease_expires_unix_ms IS NOT NULL 1404 AND lease_expires_unix_ms BETWEEN 1 AND 9223372036854775807) 1405 OR (state IN ('complete', 'blocked') 1406 AND next_attempt_unix_ms IS NULL 1407 AND lease_owner IS NULL AND lease_expires_unix_ms IS NULL) 1408 ) 1409 ) STRICT"# 1410 }; 1411 } 1412 1413 macro_rules! publication_outbox_schedule_sql { 1414 () => { 1415 r#"CREATE INDEX publication_outbox_by_schedule 1416 ON publication_outbox ( 1417 state, next_attempt_unix_ms, lease_expires_unix_ms, 1418 created_at_unix_ms, outbox_id 1419 )"# 1420 }; 1421 } 1422 1423 macro_rules! publication_outbox_guard_update_sql { 1424 () => { 1425 r#"CREATE TRIGGER publication_outbox_guard_update 1426 BEFORE UPDATE ON publication_outbox 1427 WHEN NEW.outbox_id != OLD.outbox_id 1428 OR NEW.event_id != OLD.event_id 1429 OR NEW.event_sha256 != OLD.event_sha256 1430 OR NEW.publication_authority_sha256 != OLD.publication_authority_sha256 1431 OR NEW.target_set_sha256 != OLD.target_set_sha256 1432 OR NEW.target_count != OLD.target_count 1433 OR NEW.required_target_count != OLD.required_target_count 1434 OR NEW.max_attempts != OLD.max_attempts 1435 OR NEW.initial_backoff_ms != OLD.initial_backoff_ms 1436 OR NEW.maximum_backoff_ms != OLD.maximum_backoff_ms 1437 OR NEW.attempt_deadline_ms != OLD.attempt_deadline_ms 1438 OR NEW.created_at_unix_ms != OLD.created_at_unix_ms 1439 OR NEW.revision != OLD.revision + 1 1440 OR NEW.updated_at_unix_ms < OLD.updated_at_unix_ms 1441 OR NOT ( 1442 (OLD.state = 'pending' AND NEW.state IN ('leased', 'blocked')) 1443 OR (OLD.state = 'leased' 1444 AND NEW.state IN ('leased', 'pending', 'complete', 'blocked')) 1445 OR (OLD.state = 'blocked' AND NEW.state = 'pending') 1446 ) 1447 BEGIN 1448 SELECT RAISE(ABORT, 'publication outbox transition is invalid'); 1449 END"# 1450 }; 1451 } 1452 1453 macro_rules! publication_targets_table_sql { 1454 () => { 1455 r#"CREATE TABLE publication_targets ( 1456 outbox_id BLOB NOT NULL CHECK (length(outbox_id) = 32), 1457 target_ordinal INTEGER NOT NULL CHECK (target_ordinal BETWEEN 0 AND 31), 1458 relay_id TEXT NOT NULL 1459 CHECK (length(CAST(relay_id AS BLOB)) BETWEEN 1 AND 64) 1460 CHECK (relay_id NOT GLOB '*[^a-z0-9_-]*') 1461 CHECK (substr(relay_id, 1, 1) GLOB '[a-z]'), 1462 required INTEGER NOT NULL CHECK (required IN (0, 1)), 1463 state TEXT NOT NULL CHECK (state IN ( 1464 'pending', 'submitted', 'accepted', 'rejected', 'rate_limited', 1465 'auth_required', 'failed', 'unknown' 1466 )), 1467 revision INTEGER NOT NULL CHECK (revision BETWEEN 1 AND 9223372036854775807), 1468 attempt_count INTEGER NOT NULL CHECK (attempt_count BETWEEN 0 AND 100), 1469 next_attempt_unix_ms INTEGER 1470 CHECK (next_attempt_unix_ms BETWEEN 0 AND 9223372036854775807), 1471 last_attempt_id BLOB CHECK (length(last_attempt_id) = 32), 1472 updated_at_unix_ms INTEGER NOT NULL 1473 CHECK (updated_at_unix_ms BETWEEN 0 AND 9223372036854775807), 1474 PRIMARY KEY (outbox_id, target_ordinal), 1475 UNIQUE (outbox_id, relay_id), 1476 FOREIGN KEY (outbox_id) REFERENCES publication_outbox (outbox_id), 1477 CHECK ((attempt_count = 0) = (last_attempt_id IS NULL)) 1478 ) STRICT"# 1479 }; 1480 } 1481 1482 macro_rules! publication_targets_schedule_sql { 1483 () => { 1484 r#"CREATE INDEX publication_targets_by_schedule 1485 ON publication_targets (state, next_attempt_unix_ms, updated_at_unix_ms, outbox_id, target_ordinal)"# 1486 }; 1487 } 1488 1489 macro_rules! publication_targets_guard_update_sql { 1490 () => { 1491 r#"CREATE TRIGGER publication_targets_guard_update 1492 BEFORE UPDATE ON publication_targets 1493 WHEN NEW.outbox_id != OLD.outbox_id 1494 OR NEW.target_ordinal != OLD.target_ordinal 1495 OR NEW.relay_id != OLD.relay_id 1496 OR NEW.required != OLD.required 1497 OR NEW.revision != OLD.revision + 1 1498 OR NEW.attempt_count < OLD.attempt_count 1499 OR NEW.attempt_count > OLD.attempt_count + 1 1500 OR NEW.updated_at_unix_ms < OLD.updated_at_unix_ms 1501 OR OLD.state = 'accepted' 1502 BEGIN 1503 SELECT RAISE(ABORT, 'publication target transition is invalid'); 1504 END"# 1505 }; 1506 } 1507 1508 macro_rules! publication_attempts_table_sql { 1509 () => { 1510 r#"CREATE TABLE publication_attempts ( 1511 attempt_id BLOB NOT NULL PRIMARY KEY CHECK (length(attempt_id) = 32), 1512 outbox_id BLOB NOT NULL CHECK (length(outbox_id) = 32), 1513 target_ordinal INTEGER NOT NULL CHECK (target_ordinal BETWEEN 0 AND 31), 1514 attempt_number INTEGER NOT NULL CHECK (attempt_number BETWEEN 1 AND 100), 1515 event_sha256 BLOB NOT NULL CHECK (length(event_sha256) = 32), 1516 lease_owner BLOB NOT NULL CHECK (length(lease_owner) = 16), 1517 started_at_unix_ms INTEGER NOT NULL 1518 CHECK (started_at_unix_ms BETWEEN 0 AND 9223372036854775807), 1519 finished_at_unix_ms INTEGER NOT NULL 1520 CHECK (finished_at_unix_ms BETWEEN started_at_unix_ms AND 9223372036854775807), 1521 outcome TEXT NOT NULL CHECK (outcome IN ( 1522 'submitted', 'accepted', 'rejected', 'rate_limited', 1523 'auth_required', 'failed', 'unknown' 1524 )), 1525 result_code TEXT NOT NULL 1526 CHECK (length(CAST(result_code AS BLOB)) BETWEEN 1 AND 64) 1527 CHECK (result_code NOT GLOB '*[^a-z0-9_]*') 1528 CHECK (substr(result_code, 1, 1) GLOB '[a-z]'), 1529 UNIQUE (outbox_id, target_ordinal, attempt_number), 1530 FOREIGN KEY (outbox_id, target_ordinal) 1531 REFERENCES publication_targets (outbox_id, target_ordinal) 1532 ) STRICT"# 1533 }; 1534 } 1535 1536 const CREATE_EVIDENCE_MANIFESTS_TABLE_SQL: &str = evidence_manifests_table_sql!(); 1537 const CREATE_EVIDENCE_MANIFESTS_NO_UPDATE_SQL: &str = immutable_no_update_sql!( 1538 "evidence_manifests_no_update", 1539 "evidence_manifests", 1540 "evidence manifests are immutable" 1541 ); 1542 const CREATE_EVIDENCE_MANIFESTS_NO_DELETE_SQL: &str = immutable_no_delete_sql!( 1543 "evidence_manifests_no_delete", 1544 "evidence_manifests", 1545 "evidence manifests are retained" 1546 ); 1547 const CREATE_TRADE_PROJECTIONS_TABLE_SQL: &str = trade_projections_table_sql!(); 1548 const CREATE_TRADE_PROJECTIONS_NO_UPDATE_SQL: &str = immutable_no_update_sql!( 1549 "trade_projections_no_update", 1550 "trade_projections", 1551 "trade projections are immutable" 1552 ); 1553 const CREATE_TRADE_PROJECTIONS_NO_DELETE_SQL: &str = immutable_no_delete_sql!( 1554 "trade_projections_no_delete", 1555 "trade_projections", 1556 "trade projections are retained" 1557 ); 1558 const CREATE_ATTESTATION_REPORTS_TABLE_SQL: &str = attestation_reports_table_sql!(); 1559 const CREATE_ATTESTATION_REPORTS_SUPERSESSION_SQL: &str = attestation_reports_supersession_sql!(); 1560 const CREATE_ATTESTATION_REPORTS_NO_UPDATE_SQL: &str = immutable_no_update_sql!( 1561 "attestation_reports_no_update", 1562 "attestation_reports", 1563 "attestation reports are immutable" 1564 ); 1565 const CREATE_ATTESTATION_REPORTS_NO_DELETE_SQL: &str = immutable_no_delete_sql!( 1566 "attestation_reports_no_delete", 1567 "attestation_reports", 1568 "attestation reports are retained" 1569 ); 1570 const CREATE_SIGNED_ATTESTATION_EVENTS_TABLE_SQL: &str = signed_attestation_events_table_sql!(); 1571 const CREATE_SIGNED_ATTESTATION_EVENTS_NO_UPDATE_SQL: &str = immutable_no_update_sql!( 1572 "signed_attestation_events_no_update", 1573 "signed_attestation_events", 1574 "signed attestation events are immutable" 1575 ); 1576 const CREATE_SIGNED_ATTESTATION_EVENTS_NO_DELETE_SQL: &str = immutable_no_delete_sql!( 1577 "signed_attestation_events_no_delete", 1578 "signed_attestation_events", 1579 "signed attestation events are retained" 1580 ); 1581 const CREATE_PUBLICATION_OUTBOX_TABLE_SQL: &str = publication_outbox_table_sql!(); 1582 const CREATE_PUBLICATION_OUTBOX_SCHEDULE_SQL: &str = publication_outbox_schedule_sql!(); 1583 const CREATE_PUBLICATION_OUTBOX_GUARD_UPDATE_SQL: &str = publication_outbox_guard_update_sql!(); 1584 const CREATE_PUBLICATION_OUTBOX_NO_DELETE_SQL: &str = immutable_no_delete_sql!( 1585 "publication_outbox_no_delete", 1586 "publication_outbox", 1587 "publication outbox rows are retained" 1588 ); 1589 const CREATE_PUBLICATION_TARGETS_TABLE_SQL: &str = publication_targets_table_sql!(); 1590 const CREATE_PUBLICATION_TARGETS_SCHEDULE_SQL: &str = publication_targets_schedule_sql!(); 1591 const CREATE_PUBLICATION_TARGETS_GUARD_UPDATE_SQL: &str = publication_targets_guard_update_sql!(); 1592 const CREATE_PUBLICATION_TARGETS_NO_DELETE_SQL: &str = immutable_no_delete_sql!( 1593 "publication_targets_no_delete", 1594 "publication_targets", 1595 "publication targets are retained" 1596 ); 1597 const CREATE_PUBLICATION_ATTEMPTS_TABLE_SQL: &str = publication_attempts_table_sql!(); 1598 const CREATE_PUBLICATION_ATTEMPTS_NO_UPDATE_SQL: &str = immutable_no_update_sql!( 1599 "publication_attempts_no_update", 1600 "publication_attempts", 1601 "publication attempts are immutable" 1602 ); 1603 const CREATE_PUBLICATION_ATTEMPTS_NO_DELETE_SQL: &str = immutable_no_delete_sql!( 1604 "publication_attempts_no_delete", 1605 "publication_attempts", 1606 "publication attempts are retained" 1607 ); 1608 1609 const CREATE_REPORT_PUBLICATION_MIGRATION_SQL: &str = concat!( 1610 evidence_manifests_table_sql!(), 1611 ";\n", 1612 immutable_no_update_sql!( 1613 "evidence_manifests_no_update", 1614 "evidence_manifests", 1615 "evidence manifests are immutable" 1616 ), 1617 ";\n", 1618 immutable_no_delete_sql!( 1619 "evidence_manifests_no_delete", 1620 "evidence_manifests", 1621 "evidence manifests are retained" 1622 ), 1623 ";\n", 1624 trade_projections_table_sql!(), 1625 ";\n", 1626 immutable_no_update_sql!( 1627 "trade_projections_no_update", 1628 "trade_projections", 1629 "trade projections are immutable" 1630 ), 1631 ";\n", 1632 immutable_no_delete_sql!( 1633 "trade_projections_no_delete", 1634 "trade_projections", 1635 "trade projections are retained" 1636 ), 1637 ";\n", 1638 attestation_reports_table_sql!(), 1639 ";\n", 1640 attestation_reports_supersession_sql!(), 1641 ";\n", 1642 immutable_no_update_sql!( 1643 "attestation_reports_no_update", 1644 "attestation_reports", 1645 "attestation reports are immutable" 1646 ), 1647 ";\n", 1648 immutable_no_delete_sql!( 1649 "attestation_reports_no_delete", 1650 "attestation_reports", 1651 "attestation reports are retained" 1652 ), 1653 ";\n", 1654 signed_attestation_events_table_sql!(), 1655 ";\n", 1656 immutable_no_update_sql!( 1657 "signed_attestation_events_no_update", 1658 "signed_attestation_events", 1659 "signed attestation events are immutable" 1660 ), 1661 ";\n", 1662 immutable_no_delete_sql!( 1663 "signed_attestation_events_no_delete", 1664 "signed_attestation_events", 1665 "signed attestation events are retained" 1666 ), 1667 ";\n", 1668 publication_outbox_table_sql!(), 1669 ";\n", 1670 publication_outbox_schedule_sql!(), 1671 ";\n", 1672 publication_outbox_guard_update_sql!(), 1673 ";\n", 1674 immutable_no_delete_sql!( 1675 "publication_outbox_no_delete", 1676 "publication_outbox", 1677 "publication outbox rows are retained" 1678 ), 1679 ";\n", 1680 publication_targets_table_sql!(), 1681 ";\n", 1682 publication_targets_schedule_sql!(), 1683 ";\n", 1684 publication_targets_guard_update_sql!(), 1685 ";\n", 1686 immutable_no_delete_sql!( 1687 "publication_targets_no_delete", 1688 "publication_targets", 1689 "publication targets are retained" 1690 ), 1691 ";\n", 1692 publication_attempts_table_sql!(), 1693 ";\n", 1694 immutable_no_update_sql!( 1695 "publication_attempts_no_update", 1696 "publication_attempts", 1697 "publication attempts are immutable" 1698 ), 1699 ";\n", 1700 immutable_no_delete_sql!( 1701 "publication_attempts_no_delete", 1702 "publication_attempts", 1703 "publication attempts are retained" 1704 ), 1705 ";" 1706 ); 1707 1708 const EVIDENCE_RECONCILIATIONS_TABLE_SHA256: [u8; 32] = [ 1709 0xaf, 0xed, 0xa3, 0xfb, 0xfb, 0x32, 0x6b, 0xd5, 0x27, 0x26, 0x42, 0x1d, 0x6c, 0x41, 0x5e, 0xff, 1710 0xf9, 0x71, 0xf7, 0x47, 0x72, 0x5e, 0xbf, 0x8b, 0x34, 0x26, 0x8f, 0x89, 0x6e, 0xa1, 0x2d, 0x9b, 1711 ]; 1712 const EVIDENCE_RECONCILIATIONS_NO_UPDATE_SHA256: [u8; 32] = [ 1713 0xf4, 0x8f, 0xe6, 0x07, 0x7f, 0x32, 0x9c, 0x96, 0xc7, 0x8a, 0xad, 0xd4, 0x41, 0x53, 0x1a, 0xa3, 1714 0x24, 0x2b, 0x5d, 0x12, 0x63, 0x18, 0xdb, 0x39, 0xe7, 0x73, 0xbb, 0x0c, 0xa5, 0x40, 0xcd, 0xe9, 1715 ]; 1716 const EVIDENCE_RECONCILIATIONS_NO_DELETE_SHA256: [u8; 32] = [ 1717 0x9a, 0x92, 0xf6, 0x89, 0x01, 0x75, 0xff, 0x89, 0x30, 0xee, 0x47, 0x8b, 0x8a, 0x6e, 0x10, 0x4f, 1718 0xc3, 0x88, 0x4f, 0x83, 0xc5, 0x01, 0x95, 0x9b, 0x72, 0x3e, 0xbd, 0xed, 0x87, 0x2b, 0x13, 0xdf, 1719 ]; 1720 const EVIDENCE_RECONCILIATION_SOURCES_TABLE_SHA256: [u8; 32] = [ 1721 0xd1, 0x56, 0x84, 0x76, 0xc7, 0x52, 0xf8, 0x22, 0x5c, 0xa0, 0xce, 0x77, 0xa0, 0x1f, 0xc4, 0xc6, 1722 0x78, 0x22, 0x62, 0x61, 0x02, 0xaa, 0x92, 0x5c, 0xe5, 0x6d, 0x5c, 0x91, 0x4c, 0x8e, 0x1c, 0x5a, 1723 ]; 1724 const EVIDENCE_RECONCILIATION_SOURCES_NO_UPDATE_SHA256: [u8; 32] = [ 1725 0x85, 0x8a, 0x6d, 0x3b, 0x97, 0x35, 0x91, 0x0b, 0x93, 0xe1, 0x9a, 0x73, 0x97, 0x6e, 0x47, 0x0e, 1726 0xe6, 0xb6, 0x38, 0x68, 0x31, 0x35, 0xf2, 0x1d, 0x3a, 0x30, 0xe1, 0xa6, 0x3f, 0xae, 0x07, 0x6b, 1727 ]; 1728 const EVIDENCE_RECONCILIATION_SOURCES_NO_DELETE_SHA256: [u8; 32] = [ 1729 0x55, 0x75, 0xfc, 0xaf, 0xab, 0x07, 0xaf, 0x83, 0x0b, 0x69, 0x8d, 0xfa, 0x86, 0x56, 0xe9, 0xc6, 1730 0x98, 0x0b, 0x4c, 0xdc, 0xa2, 0xde, 0xce, 0xfc, 0x06, 0x41, 0x86, 0x69, 0x2e, 0xac, 0x00, 0x39, 1731 ]; 1732 1733 const EVIDENCE_MANIFESTS_TABLE_SHA256: [u8; 32] = [ 1734 0x95, 0x41, 0x37, 0x66, 0x31, 0x3e, 0x96, 0x83, 0x81, 0xdf, 0x0d, 0x8b, 0xc5, 0xd5, 0x50, 0x8b, 1735 0xde, 0x34, 0x3c, 0x68, 0xd6, 0x56, 0xea, 0xea, 0xab, 0x08, 0x87, 0x10, 0x9b, 0x23, 0xc6, 0xfb, 1736 ]; 1737 const EVIDENCE_MANIFESTS_NO_UPDATE_SHA256: [u8; 32] = [ 1738 0x7f, 0xc1, 0x21, 0xaf, 0x5e, 0x9d, 0xc8, 0x32, 0xae, 0xc9, 0x98, 0x6d, 0x45, 0xc7, 0x68, 0xf3, 1739 0xc1, 0x76, 0x14, 0xbb, 0xf6, 0xbe, 0x41, 0x11, 0x6a, 0x7e, 0xa9, 0x22, 0x90, 0x27, 0x0e, 0xe5, 1740 ]; 1741 const EVIDENCE_MANIFESTS_NO_DELETE_SHA256: [u8; 32] = [ 1742 0xd9, 0x9e, 0x5f, 0x55, 0xf7, 0xf2, 0x48, 0x5e, 0xfc, 0xc3, 0xb9, 0x11, 0x88, 0xf5, 0x8d, 0x3b, 1743 0xa0, 0x0c, 0x3e, 0xf7, 0x82, 0x3d, 0x88, 0xe0, 0x82, 0xc2, 0x60, 0xb8, 0x0f, 0xf4, 0xd6, 0xa4, 1744 ]; 1745 const TRADE_PROJECTIONS_TABLE_SHA256: [u8; 32] = [ 1746 0xac, 0x04, 0x55, 0xd5, 0x1b, 0xed, 0xfb, 0x9b, 0x59, 0xfd, 0xc9, 0xea, 0x63, 0x1b, 0x85, 0x63, 1747 0x7a, 0x16, 0xf1, 0xb1, 0xfe, 0xad, 0x4d, 0x4c, 0xdf, 0xba, 0xad, 0xa3, 0xef, 0x85, 0x65, 0x43, 1748 ]; 1749 const TRADE_PROJECTIONS_NO_UPDATE_SHA256: [u8; 32] = [ 1750 0x8f, 0xba, 0x6b, 0x06, 0x8e, 0xb8, 0x69, 0x84, 0x14, 0x4b, 0x64, 0x14, 0xbf, 0x8c, 0x4e, 0x95, 1751 0x47, 0x58, 0xaf, 0x09, 0x7d, 0xbb, 0x3a, 0xfe, 0x72, 0x06, 0x21, 0x00, 0x6a, 0x43, 0x32, 0xe0, 1752 ]; 1753 const TRADE_PROJECTIONS_NO_DELETE_SHA256: [u8; 32] = [ 1754 0x94, 0x8a, 0x5c, 0xed, 0x5a, 0xaa, 0x0a, 0xb4, 0x90, 0x1c, 0xe4, 0x3a, 0xdb, 0x97, 0x69, 0xbf, 1755 0x5a, 0x19, 0x5d, 0x35, 0x95, 0xc9, 0x39, 0x54, 0x73, 0xe9, 0x6e, 0xea, 0x9c, 0x08, 0x26, 0xb2, 1756 ]; 1757 const ATTESTATION_REPORTS_TABLE_SHA256: [u8; 32] = [ 1758 0x97, 0xc4, 0x83, 0x37, 0x56, 0x92, 0x23, 0x67, 0xb2, 0xb8, 0xd2, 0x00, 0xeb, 0xc9, 0x31, 0x0d, 1759 0xc8, 0xb9, 0x73, 0x38, 0xf6, 0xc5, 0x9c, 0xe5, 0xe5, 0x19, 0x87, 0x64, 0x19, 0x9d, 0x44, 0xd2, 1760 ]; 1761 const ATTESTATION_REPORTS_SUPERSESSION_SHA256: [u8; 32] = [ 1762 0x57, 0xd5, 0x59, 0x2e, 0x2a, 0x7a, 0xd0, 0x03, 0x06, 0x42, 0x28, 0x16, 0x31, 0x8c, 0xe1, 0x25, 1763 0x30, 0x1c, 0xd3, 0x73, 0xff, 0xc3, 0x47, 0xf5, 0xf8, 0x65, 0xc0, 0x63, 0x73, 0x76, 0xad, 0x8e, 1764 ]; 1765 const ATTESTATION_REPORTS_NO_UPDATE_SHA256: [u8; 32] = [ 1766 0x5f, 0x27, 0x19, 0x68, 0xe4, 0xd8, 0x32, 0x84, 0xe1, 0x04, 0x09, 0x37, 0x0b, 0xdc, 0x55, 0x9d, 1767 0xfa, 0x8f, 0xce, 0xa9, 0x0f, 0xd9, 0xd3, 0x47, 0xd4, 0xfa, 0xc8, 0x12, 0x53, 0x77, 0x17, 0x23, 1768 ]; 1769 const ATTESTATION_REPORTS_NO_DELETE_SHA256: [u8; 32] = [ 1770 0xbe, 0xaf, 0xa1, 0x1a, 0xbe, 0x57, 0x27, 0xac, 0x3e, 0x43, 0x26, 0xd0, 0x8b, 0x0d, 0x39, 0x36, 1771 0xb3, 0x04, 0x11, 0x37, 0x48, 0x13, 0xd3, 0x2a, 0xc8, 0x24, 0x1f, 0x56, 0xa9, 0x2c, 0x51, 0xfc, 1772 ]; 1773 const SIGNED_ATTESTATION_EVENTS_TABLE_SHA256: [u8; 32] = [ 1774 0x9b, 0x83, 0x5b, 0x84, 0x97, 0x1f, 0x52, 0xba, 0xc2, 0x8f, 0xf2, 0xba, 0x04, 0x9a, 0x1b, 0x9b, 1775 0xfc, 0xcc, 0x7c, 0xab, 0x39, 0xd0, 0x16, 0x53, 0x06, 0xa3, 0x9b, 0x93, 0x8c, 0x51, 0x72, 0xab, 1776 ]; 1777 const SIGNED_ATTESTATION_EVENTS_NO_UPDATE_SHA256: [u8; 32] = [ 1778 0x36, 0x1d, 0xbe, 0xda, 0xae, 0xd4, 0xfc, 0x4c, 0xf3, 0xe8, 0xa8, 0x60, 0xeb, 0x63, 0xc8, 0xc7, 1779 0x3a, 0x31, 0x79, 0x7c, 0x4f, 0x92, 0x79, 0x8f, 0x7d, 0x3a, 0x9f, 0xec, 0x7f, 0x95, 0xa8, 0x44, 1780 ]; 1781 const SIGNED_ATTESTATION_EVENTS_NO_DELETE_SHA256: [u8; 32] = [ 1782 0x06, 0x4d, 0x71, 0x90, 0x60, 0x9e, 0x6a, 0x8e, 0xac, 0x6d, 0x80, 0x44, 0xe1, 0xef, 0x53, 0x76, 1783 0x6a, 0xea, 0x6a, 0xb3, 0x68, 0xc9, 0x48, 0xb1, 0x64, 0x24, 0x9a, 0xf2, 0xc0, 0xc3, 0xeb, 0x9c, 1784 ]; 1785 const PUBLICATION_OUTBOX_TABLE_SHA256: [u8; 32] = [ 1786 0x26, 0x2a, 0x56, 0x79, 0x77, 0x73, 0xcb, 0x84, 0xb6, 0x55, 0x1c, 0x19, 0x32, 0xe1, 0x0e, 0xb1, 1787 0x98, 0xf2, 0x4b, 0xf2, 0xb3, 0x5f, 0x90, 0x15, 0xac, 0xc1, 0x8f, 0x27, 0xfd, 0x89, 0x4b, 0x2d, 1788 ]; 1789 const PUBLICATION_OUTBOX_SCHEDULE_SHA256: [u8; 32] = [ 1790 0xc0, 0x70, 0xb5, 0xb0, 0xd0, 0x1f, 0x05, 0x34, 0xe9, 0x1e, 0xfa, 0xee, 0x6c, 0xba, 0xdd, 0xf8, 1791 0x5c, 0xf1, 0x85, 0x33, 0xa7, 0x04, 0x5c, 0xfb, 0x65, 0x11, 0xdc, 0x80, 0x28, 0x7b, 0x4f, 0x6e, 1792 ]; 1793 const PUBLICATION_OUTBOX_GUARD_UPDATE_SHA256: [u8; 32] = [ 1794 0x3e, 0xd0, 0x80, 0x98, 0x34, 0xb2, 0x24, 0x51, 0x5b, 0x7b, 0x06, 0x8e, 0x46, 0x8e, 0xbe, 0x8a, 1795 0x52, 0x8b, 0xdb, 0xcf, 0xb4, 0x0e, 0x33, 0xe5, 0x19, 0xc6, 0xfd, 0xef, 0x19, 0x80, 0xcd, 0x62, 1796 ]; 1797 const PUBLICATION_OUTBOX_NO_DELETE_SHA256: [u8; 32] = [ 1798 0xc5, 0x77, 0x63, 0xa0, 0x90, 0xde, 0xe0, 0x11, 0x62, 0x2a, 0xda, 0x9f, 0x32, 0x24, 0x47, 0x59, 1799 0x54, 0xdf, 0x60, 0xd7, 0xe3, 0xf2, 0xf3, 0x42, 0x36, 0x14, 0x8e, 0xba, 0x52, 0x84, 0x3a, 0x6e, 1800 ]; 1801 const PUBLICATION_TARGETS_TABLE_SHA256: [u8; 32] = [ 1802 0x23, 0xa0, 0x78, 0x7f, 0x7d, 0x90, 0x91, 0x8b, 0x41, 0x4a, 0x22, 0x37, 0xcc, 0x70, 0xa0, 0x83, 1803 0x1a, 0xe0, 0xfa, 0x05, 0x2e, 0x1b, 0x9f, 0x25, 0x50, 0xe3, 0x6f, 0xda, 0xd1, 0x53, 0xab, 0x7b, 1804 ]; 1805 const PUBLICATION_TARGETS_SCHEDULE_SHA256: [u8; 32] = [ 1806 0xf8, 0xc4, 0x46, 0x10, 0xcb, 0x2d, 0xe4, 0xa3, 0x54, 0xd7, 0x93, 0x64, 0x9f, 0x8b, 0xa9, 0xf1, 1807 0x95, 0xfd, 0xba, 0x5d, 0xfc, 0xc1, 0xf9, 0x92, 0xe9, 0x08, 0x08, 0x7e, 0x56, 0x6a, 0x14, 0xde, 1808 ]; 1809 const PUBLICATION_TARGETS_GUARD_UPDATE_SHA256: [u8; 32] = [ 1810 0x57, 0x10, 0x3b, 0xa2, 0xc3, 0xd7, 0x88, 0xd3, 0x83, 0x3a, 0xba, 0xed, 0xcd, 0xad, 0x49, 0x5e, 1811 0xce, 0xfe, 0x6e, 0xbd, 0x63, 0x2a, 0x98, 0x14, 0x04, 0x10, 0x86, 0xb9, 0x84, 0x10, 0x72, 0x0c, 1812 ]; 1813 const PUBLICATION_TARGETS_NO_DELETE_SHA256: [u8; 32] = [ 1814 0x53, 0x97, 0x8a, 0xa5, 0xca, 0x4d, 0xef, 0x0e, 0xc4, 0x75, 0xc4, 0x55, 0xf6, 0x10, 0x43, 0xf7, 1815 0x1b, 0x10, 0x15, 0x6b, 0x2b, 0x56, 0xe0, 0x6c, 0x50, 0x4a, 0xc7, 0xee, 0x57, 0x3e, 0x74, 0x4e, 1816 ]; 1817 const PUBLICATION_ATTEMPTS_TABLE_SHA256: [u8; 32] = [ 1818 0x7d, 0xa6, 0xea, 0xbe, 0xfc, 0x07, 0xeb, 0x16, 0xde, 0x5c, 0x47, 0xc9, 0x20, 0xfd, 0x64, 0x76, 1819 0xa9, 0xe9, 0x8d, 0xce, 0xe9, 0x31, 0x84, 0x45, 0x8d, 0xd2, 0x98, 0xb8, 0x53, 0x52, 0x03, 0x28, 1820 ]; 1821 const PUBLICATION_ATTEMPTS_NO_UPDATE_SHA256: [u8; 32] = [ 1822 0xc3, 0xe5, 0x51, 0x35, 0x06, 0xad, 0x45, 0xca, 0xea, 0xe5, 0xaa, 0x7e, 0xa2, 0x40, 0xe7, 0x0a, 1823 0xde, 0x7c, 0xf7, 0x7f, 0x6d, 0x9a, 0x67, 0x76, 0x92, 0x5e, 0x12, 0x06, 0xc4, 0x55, 0xbf, 0x65, 1824 ]; 1825 const PUBLICATION_ATTEMPTS_NO_DELETE_SHA256: [u8; 32] = [ 1826 0x6d, 0x8a, 0x4e, 0x03, 0x67, 0x52, 0x51, 0x1a, 0x4e, 0xe7, 0xaa, 0x41, 0x0c, 0x31, 0xaa, 0xc9, 1827 0xd3, 0x5c, 0x42, 0x48, 0xe3, 0x78, 0xfa, 0x39, 0x7c, 0x9b, 0x90, 0xa0, 0xe3, 0x72, 0x19, 0x29, 1828 ]; 1829 1830 const RECONCILIATION_JOBS_TABLE_SHA256: [u8; 32] = [ 1831 0xe7, 0x0b, 0x5c, 0xb7, 0x26, 0x91, 0x9d, 0x02, 0xef, 0xb3, 0xa6, 0x21, 0x58, 0x48, 0xce, 0x92, 1832 0x30, 0x88, 0x17, 0x2b, 0x3f, 0xe0, 0xc1, 0x40, 0xee, 0x4a, 0xc7, 0x1b, 0xd0, 0x3c, 0x66, 0xa7, 1833 ]; 1834 const RECONCILIATION_JOBS_ONE_ACTIVE_SHA256: [u8; 32] = [ 1835 0xf9, 0xbe, 0x78, 0xc6, 0x46, 0x7a, 0x76, 0x2d, 0x38, 0xf4, 0xe0, 0xb4, 0x80, 0xd4, 0x1b, 0x37, 1836 0x6f, 0x66, 0x8c, 0x21, 0xd2, 0x96, 0xfd, 0x72, 0x12, 0x11, 0x9d, 0x2b, 0x9e, 0x3a, 0x14, 0x3f, 1837 ]; 1838 const RECONCILIATION_JOBS_SCHEDULE_SHA256: [u8; 32] = [ 1839 0x31, 0xd9, 0xf7, 0x38, 0x3b, 0x87, 0x8d, 0xd8, 0x00, 0xda, 0xe6, 0x1f, 0x40, 0x54, 0xd8, 0xd2, 1840 0x99, 0xca, 0x93, 0xef, 0x38, 0xbe, 0x5b, 0x63, 0x63, 0x0e, 0x1c, 0x3f, 0x57, 0x2a, 0x1e, 0x75, 1841 ]; 1842 const RECONCILIATION_JOBS_GUARD_UPDATE_SHA256: [u8; 32] = [ 1843 0xe4, 0x6a, 0x3a, 0xf2, 0x7e, 0xe1, 0xce, 0xe2, 0x4e, 0x29, 0x13, 0x56, 0x51, 0x6c, 0x72, 0x6d, 1844 0xf0, 0xd1, 0x11, 0x29, 0x01, 0x22, 0x97, 0x5e, 0xe1, 0x79, 0x76, 0xe3, 0x6a, 0x74, 0x13, 0x1b, 1845 ]; 1846 const RECONCILIATION_JOBS_NO_DELETE_SHA256: [u8; 32] = [ 1847 0x1a, 0x86, 0xb1, 0x70, 0x05, 0x05, 0x4c, 0x27, 0x1b, 0xa4, 0x9a, 0xf2, 0x1a, 0x44, 0x9c, 0x9d, 1848 0xdc, 0xfb, 0xbc, 0xd9, 0x13, 0xfa, 0x2a, 0x8e, 0x64, 0x6d, 0x5a, 0x6d, 0x22, 0x69, 0x59, 0xa2, 1849 ]; 1850 const RECONCILIATION_JOBS_SHAPE_GUARD_INSERT_SHA256: [u8; 32] = [ 1851 0x77, 0xf6, 0x83, 0x23, 0x27, 0xce, 0xe0, 0x16, 0xc4, 0x0c, 0x22, 0x6a, 0x61, 0xbe, 0x82, 0xe7, 1852 0x5b, 0xf0, 0x0b, 0xee, 0x07, 0xb7, 0x03, 0x6f, 0xf7, 0x0d, 0xd2, 0xc9, 0xe0, 0xdb, 0x26, 0xd5, 1853 ]; 1854 const RECONCILIATION_JOBS_SHAPE_GUARD_UPDATE_SHA256: [u8; 32] = [ 1855 0xf7, 0xbb, 0x8e, 0xb8, 0x1a, 0x6a, 0x1c, 0x19, 0xa9, 0x84, 0x67, 0x51, 0x20, 0x30, 0xe3, 0x9c, 1856 0xb8, 0x0d, 0x51, 0x6c, 0x1e, 0x33, 0xe7, 0x78, 0x8c, 0xfc, 0x37, 0x9e, 0x4e, 0x9e, 0xf4, 0x61, 1857 ]; 1858 1859 const RHI_CONFIG_BINDINGS_TABLE_SHA256: [u8; 32] = [ 1860 0x4d, 0x6e, 0x8f, 0xff, 0xda, 0x43, 0xe6, 0xf5, 0x3e, 0x23, 0x77, 0xd2, 0x77, 0xa4, 0x52, 0x9e, 1861 0x63, 0x3e, 0xaf, 0xb6, 0xea, 0xa2, 0xad, 0xd7, 0x56, 0xde, 0x0d, 0xc9, 0x24, 0xc5, 0x77, 0xeb, 1862 ]; 1863 const RHI_CONFIG_BINDINGS_GUARD_INSERT_SHA256: [u8; 32] = [ 1864 0xe9, 0xc1, 0x7d, 0x5c, 0x2b, 0xbe, 0x59, 0x20, 0x06, 0xe3, 0x7c, 0x5d, 0x93, 0xdc, 0x33, 0x51, 1865 0x42, 0x63, 0xb2, 0xd6, 0x1b, 0x67, 0x57, 0x81, 0x54, 0x63, 0x85, 0x6b, 0x3f, 0x9d, 0x9d, 0x25, 1866 ]; 1867 const RHI_CONFIG_BINDINGS_NO_UPDATE_SHA256: [u8; 32] = [ 1868 0xca, 0xb4, 0xbf, 0x42, 0x05, 0x86, 0x03, 0x78, 0x27, 0x1a, 0xad, 0x5b, 0x57, 0x1f, 0x0e, 0x53, 1869 0x61, 0xe6, 0xb6, 0x62, 0xc1, 0xa9, 0xc1, 0x38, 0x07, 0x5f, 0xab, 0x07, 0xcd, 0xc8, 0x92, 0xe0, 1870 ]; 1871 const RHI_CONFIG_BINDINGS_NO_DELETE_SHA256: [u8; 32] = [ 1872 0x5d, 0x26, 0x82, 0xe9, 0xf2, 0xdc, 0x84, 0x97, 0x61, 0xd1, 0xd7, 0x10, 0xdc, 0xda, 0x75, 0xea, 1873 0x40, 0x6d, 0x10, 0x95, 0xae, 0x1b, 0xc0, 0xad, 0xdf, 0x70, 0x64, 0xec, 0x8b, 0xed, 0x0b, 0x90, 1874 ]; 1875 const TRADE_MUTATIONS_TABLE_SHA256: [u8; 32] = [ 1876 0x86, 0x4f, 0x45, 0xc0, 0x87, 0xe3, 0x87, 0x71, 0x53, 0xb8, 0x6a, 0xa1, 0x88, 0x6c, 0x73, 0x3e, 1877 0x56, 0x9f, 0x1b, 0x8b, 0xad, 0x8e, 0x9c, 0xbf, 0xab, 0xc4, 0x84, 0x7d, 0x33, 0x33, 0xea, 0xb5, 1878 ]; 1879 const TRADE_MUTATIONS_BY_TRADE_SHA256: [u8; 32] = [ 1880 0xcf, 0xd1, 0x79, 0x90, 0xf6, 0x0a, 0x18, 0x94, 0x0a, 0xf9, 0xe6, 0xa8, 0x93, 0xda, 0x9e, 0x9a, 1881 0xc7, 0x5d, 0x2f, 0x69, 0x28, 0xd9, 0xb6, 0x7c, 0x25, 0x06, 0x64, 0x8d, 0x94, 0x9f, 0x97, 0x2e, 1882 ]; 1883 const NOSTR_EVENTS_TABLE_SHA256: [u8; 32] = [ 1884 0xcd, 0x08, 0xad, 0x41, 0xb4, 0xd7, 0x88, 0xde, 0xc1, 0x23, 0xc9, 0x83, 0x27, 0x17, 0xb8, 0xab, 1885 0x26, 0x0d, 0x58, 0x5c, 0x71, 0x56, 0x68, 0x6c, 0xaa, 0xf0, 0x5f, 0x07, 0xba, 0xfc, 0x72, 0x12, 1886 ]; 1887 const NOSTR_EVENTS_BY_MUTATION_SHA256: [u8; 32] = [ 1888 0x57, 0xd2, 0x8a, 0x14, 0xed, 0x74, 0x84, 0xef, 0xa4, 0x1f, 0x78, 0xe8, 0xbf, 0x6e, 0x85, 0x49, 1889 0xfa, 0x50, 0x76, 0x65, 0xc7, 0x95, 0x32, 0x34, 0xe0, 0xc5, 0xb4, 0xcb, 0x03, 0xb7, 0xa4, 0x18, 1890 ]; 1891 const RELAY_OBSERVATIONS_TABLE_SHA256: [u8; 32] = [ 1892 0xb0, 0x4d, 0x44, 0x0b, 0xe0, 0x1b, 0x93, 0x2e, 0xea, 0x53, 0x0b, 0x6a, 0x2e, 0xb2, 0x13, 0xe5, 1893 0x19, 0xab, 0xbf, 0xc2, 0xd2, 0xff, 0xa3, 0xb8, 0x86, 0x98, 0xb1, 0xc7, 0x28, 0x17, 0x86, 0xfc, 1894 ]; 1895 const RELAY_OBSERVATIONS_BY_EVENT_SHA256: [u8; 32] = [ 1896 0xdd, 0x69, 0x9f, 0x49, 0x98, 0x67, 0x0f, 0x78, 0xb4, 0x62, 0xcb, 0x1c, 0xd5, 0x17, 0x2a, 0xdb, 1897 0x8d, 0xa1, 0x68, 0x7c, 0x51, 0x74, 0xb3, 0x34, 0x43, 0xf1, 0xc6, 0x6f, 0x41, 0x03, 0xf7, 0x82, 1898 ]; 1899 const TRADE_MUTATIONS_NO_UPDATE_SHA256: [u8; 32] = [ 1900 0xd7, 0xeb, 0x61, 0x74, 0x43, 0x6a, 0xe3, 0x46, 0xf8, 0x29, 0x31, 0x37, 0x33, 0x93, 0xc0, 0xe9, 1901 0x0c, 0xe7, 0xf3, 0x06, 0xd6, 0xad, 0xc9, 0xe7, 0xc1, 0xe0, 0x19, 0x3e, 0xa2, 0x46, 0x7d, 0xbe, 1902 ]; 1903 const TRADE_MUTATIONS_NO_DELETE_SHA256: [u8; 32] = [ 1904 0xde, 0x61, 0x5b, 0xe4, 0x8f, 0xac, 0xc6, 0xd9, 0xae, 0xb1, 0x11, 0xe7, 0xbb, 0xd3, 0xc7, 0x31, 1905 0x17, 0x6e, 0xc6, 0xe4, 0x82, 0x61, 0x77, 0xba, 0x1c, 0xb7, 0x49, 0x44, 0x02, 0xb1, 0xba, 0xc4, 1906 ]; 1907 const NOSTR_EVENTS_NO_UPDATE_SHA256: [u8; 32] = [ 1908 0x3e, 0x6e, 0xec, 0x38, 0x89, 0xd7, 0xfd, 0x25, 0xde, 0x26, 0xe2, 0x03, 0x6e, 0xa5, 0xa5, 0x2a, 1909 0xd5, 0xa0, 0xeb, 0xd6, 0x04, 0x62, 0x61, 0x08, 0xaa, 0x80, 0x72, 0x56, 0xe9, 0xb6, 0x0a, 0x89, 1910 ]; 1911 const NOSTR_EVENTS_NO_DELETE_SHA256: [u8; 32] = [ 1912 0x17, 0x6b, 0x15, 0x16, 0xce, 0xe2, 0xf1, 0xfc, 0x62, 0xa7, 0x40, 0x90, 0x01, 0x79, 0x51, 0xae, 1913 0x15, 0x2c, 0xbe, 0x79, 0x53, 0xd0, 0x7c, 0x86, 0xa0, 0xae, 0xca, 0xd3, 0x19, 0x1e, 0xf5, 0xf6, 1914 ]; 1915 const RELAY_OBSERVATIONS_NO_UPDATE_SHA256: [u8; 32] = [ 1916 0x6d, 0x20, 0xb3, 0xf0, 0xef, 0x1a, 0x26, 0x55, 0xff, 0xd7, 0x46, 0x5c, 0xce, 0xfa, 0x4c, 0x64, 1917 0x25, 0x26, 0x64, 0xe2, 0x1b, 0xdc, 0xd8, 0x59, 0xdc, 0xb2, 0xde, 0x15, 0xf0, 0x55, 0xf6, 0xaa, 1918 ]; 1919 const RELAY_OBSERVATIONS_NO_DELETE_SHA256: [u8; 32] = [ 1920 0xe9, 0xaa, 0x66, 0xff, 0x29, 0xa0, 0x62, 0xc9, 0xf9, 0x97, 0x27, 0x0f, 0x59, 0xad, 0x63, 0x65, 1921 0xdc, 0x4d, 0x88, 0xc6, 0x59, 0x4b, 0xe5, 0xe5, 0xfe, 0x44, 0xf4, 0x44, 0x6d, 0x00, 0xb7, 0xe0, 1922 ]; 1923 const RELAY_CHECKPOINTS_TABLE_SHA256: [u8; 32] = [ 1924 0x5f, 0xf7, 0xc3, 0x41, 0xa3, 0x48, 0x37, 0x3e, 0x92, 0xf5, 0x46, 0xe1, 0xff, 0xfd, 0x45, 0x4a, 1925 0x86, 0x6e, 0x23, 0x2c, 0xff, 0x60, 0x83, 0xbf, 0x3f, 0xfe, 0xc3, 0xfc, 0x65, 0x53, 0x2c, 0xb6, 1926 ]; 1927 const RELAY_CHECKPOINTS_GUARD_UPDATE_SHA256: [u8; 32] = [ 1928 0x5c, 0xd7, 0x2a, 0xaf, 0x31, 0x2c, 0x17, 0xcf, 0xfa, 0xe4, 0xa8, 0x37, 0x91, 0x3c, 0x5e, 0x92, 1929 0xf2, 0xaa, 0x31, 0xea, 0x71, 0x3e, 0x86, 0x0e, 0x3a, 0xaa, 0x9f, 0xf7, 0x05, 0xd0, 0xc4, 0x92, 1930 ]; 1931 const RELAY_CHECKPOINTS_NO_DELETE_SHA256: [u8; 32] = [ 1932 0x8d, 0xb0, 0x54, 0xf7, 0x75, 0x97, 0xd5, 0xe5, 0x42, 0xd0, 0x0c, 0x2e, 0xdc, 0xf2, 0xd9, 0x26, 1933 0xa9, 0x2b, 0x8e, 0xf5, 0x5a, 0x69, 0x54, 0xb2, 0x01, 0x6b, 0x93, 0x36, 0x48, 0x84, 0xfb, 0x1f, 1934 ]; 1935 const TRADE_DIRTY_GENERATIONS_TABLE_SHA256: [u8; 32] = [ 1936 0xe9, 0x93, 0x53, 0x2c, 0x08, 0x36, 0xa2, 0x99, 0x40, 0xd2, 0xe3, 0x51, 0x5b, 0x11, 0x34, 0xea, 1937 0x68, 0xf7, 0xd3, 0x50, 0xe5, 0xbe, 0xdb, 0x3b, 0xc1, 0xb1, 0xa5, 0x6f, 0x7f, 0xa6, 0xe4, 0xd1, 1938 ]; 1939 const TRADE_DIRTY_GENERATIONS_GUARD_UPDATE_SHA256: [u8; 32] = [ 1940 0x50, 0x31, 0xbc, 0x10, 0x4d, 0x51, 0x66, 0xae, 0xf2, 0xdc, 0x9a, 0x1b, 0xaf, 0x42, 0x0e, 0x47, 1941 0xc1, 0x6b, 0xa9, 0x70, 0x91, 0x6f, 0x5d, 0xc5, 0x6d, 0xb3, 0xc1, 0x70, 0x4e, 0x76, 0x16, 0xcb, 1942 ]; 1943 const TRADE_DIRTY_GENERATIONS_NO_DELETE_SHA256: [u8; 32] = [ 1944 0x36, 0x66, 0x3a, 0x1a, 0xd4, 0x65, 0x41, 0x9f, 0x23, 0x1e, 0xe6, 0xcd, 0x1e, 0xd1, 0x6d, 0xa4, 1945 0x26, 0xac, 0x7d, 0x70, 0xde, 0xc3, 0x67, 0x75, 0x55, 0x62, 0xa8, 0x45, 0x52, 0x86, 0x54, 0x23, 1946 ]; 1947 const PRESENCE_DESIRED_STATE_TABLE_SHA256: [u8; 32] = [ 1948 0x78, 0x4d, 0xfc, 0x23, 0xd5, 0x05, 0xba, 0x09, 0xb3, 0x73, 0x76, 0xf0, 0x18, 0xaa, 0x03, 0xc6, 1949 0x3d, 0x98, 0x77, 0x1e, 0xba, 0xd6, 0x73, 0x25, 0x4a, 0x38, 0x46, 0xe3, 0x72, 0xc0, 0x80, 0x40, 1950 ]; 1951 const PRESENCE_DESIRED_STATE_GUARD_INSERT_SHA256: [u8; 32] = [ 1952 0xe5, 0x55, 0xa5, 0x87, 0xa9, 0x73, 0x2f, 0xae, 0x7c, 0x2d, 0x4e, 0xde, 0xb1, 0x88, 0x93, 0x33, 1953 0x4a, 0xa4, 0x23, 0x12, 0x22, 0x7a, 0x71, 0xca, 0x6c, 0x2b, 0x38, 0x1f, 0x0b, 0x56, 0xad, 0x8b, 1954 ]; 1955 const PRESENCE_DESIRED_STATE_GUARD_UPDATE_SHA256: [u8; 32] = [ 1956 0xb3, 0x2a, 0xc0, 0x44, 0xd6, 0x8c, 0x40, 0xfa, 0x3e, 0xbc, 0x57, 0x8a, 0x2d, 0x59, 0xcb, 0x1b, 1957 0xd6, 0x87, 0xd5, 0x3d, 0xa0, 0xc7, 0xec, 0x99, 0xb5, 0x1e, 0x63, 0xc9, 0x72, 0xeb, 0x27, 0x14, 1958 ]; 1959 const PRESENCE_DESIRED_STATE_NO_DELETE_SHA256: [u8; 32] = [ 1960 0xca, 0xcd, 0xcf, 0x6f, 0x3b, 0x34, 0xc0, 0x7d, 0x6c, 0xf1, 0x1a, 0xab, 0x03, 0xd5, 0x19, 0x7c, 1961 0xca, 0x44, 0xab, 0x2e, 0x4f, 0x77, 0x65, 0x29, 0x75, 0x02, 0x4b, 0xbf, 0x1f, 0x04, 0xdc, 0x3f, 1962 ]; 1963 1964 const PRESENCE_OUTBOX_TABLE_SHA256: [u8; 32] = [ 1965 0x7e, 0x59, 0xa4, 0xb4, 0x54, 0x09, 0x9e, 0x47, 0xf8, 0xad, 0x0d, 0xb8, 0x7f, 0xd2, 0xa0, 0xc5, 1966 0xf6, 0x69, 0x8d, 0x70, 0xda, 0x96, 0x8d, 0xb0, 0x57, 0x6a, 0xa8, 0x54, 0x28, 0xd1, 0x40, 0xdd, 1967 ]; 1968 const PRESENCE_OUTBOX_SCHEDULE_SHA256: [u8; 32] = [ 1969 0xed, 0x0e, 0x52, 0xba, 0xc1, 0xa8, 0xc8, 0xe3, 0x25, 0xf0, 0x28, 0xe4, 0x2c, 0x8d, 0x88, 0x8f, 1970 0x0e, 0x8b, 0x42, 0x63, 0x7c, 0x95, 0x25, 0xf1, 0x02, 0x0c, 0x18, 0x41, 0x3b, 0xf0, 0xf0, 0x41, 1971 ]; 1972 const PRESENCE_OUTBOX_GUARD_UPDATE_SHA256: [u8; 32] = [ 1973 0x1d, 0x80, 0x93, 0xa8, 0xe7, 0x70, 0x82, 0xc4, 0x2f, 0xb3, 0xe4, 0x79, 0xc6, 0x22, 0x6f, 0x39, 1974 0x92, 0x88, 0x80, 0xd4, 0x92, 0xa9, 0x6c, 0x04, 0x29, 0x6b, 0xf2, 0xcc, 0x56, 0x69, 0x6e, 0xce, 1975 ]; 1976 const PRESENCE_OUTBOX_NO_DELETE_SHA256: [u8; 32] = [ 1977 0xc4, 0xe9, 0xb5, 0x5a, 0x02, 0x0b, 0x67, 0x1d, 0x7d, 0x6c, 0x81, 0xf6, 0x99, 0x90, 0x65, 0x52, 1978 0xd9, 0x5e, 0x97, 0xfd, 0xba, 0xac, 0xad, 0x7b, 0x01, 0xb5, 0x02, 0x3f, 0x6b, 0x5f, 0x79, 0xeb, 1979 ]; 1980 const PRESENCE_TARGETS_TABLE_SHA256: [u8; 32] = [ 1981 0x1e, 0xfa, 0xc9, 0xe2, 0x8d, 0x55, 0xcf, 0x90, 0xa5, 0x5d, 0xc4, 0x13, 0x1a, 0x8e, 0xcb, 0xc3, 1982 0x86, 0x2e, 0xff, 0xa9, 0x3d, 0xb3, 0x63, 0xff, 0xed, 0xd4, 0xa1, 0xd6, 0xcd, 0xa4, 0xb7, 0x8c, 1983 ]; 1984 const PRESENCE_TARGETS_SCHEDULE_SHA256: [u8; 32] = [ 1985 0x6d, 0xbc, 0xf6, 0x25, 0x20, 0x1e, 0x11, 0x2e, 0x1a, 0x54, 0xa7, 0xc8, 0x87, 0xaf, 0xbb, 0xb8, 1986 0x21, 0x0a, 0xdc, 0xf6, 0xfa, 0xc1, 0xc5, 0x99, 0xe1, 0xaa, 0x6c, 0xa5, 0xc4, 0x56, 0x74, 0x6a, 1987 ]; 1988 const PRESENCE_TARGETS_GUARD_UPDATE_SHA256: [u8; 32] = [ 1989 0xa0, 0x8f, 0x28, 0x9e, 0x60, 0x32, 0x27, 0xfa, 0x74, 0x34, 0xea, 0x8d, 0x4a, 0xb5, 0x2a, 0x07, 1990 0x60, 0xdc, 0xd2, 0x8f, 0xe1, 0x35, 0x33, 0x51, 0xa3, 0x5c, 0x3e, 0x6c, 0x73, 0x5d, 0x12, 0x44, 1991 ]; 1992 const PRESENCE_TARGETS_NO_DELETE_SHA256: [u8; 32] = [ 1993 0x8f, 0x0a, 0x46, 0x61, 0x55, 0x96, 0xa8, 0x33, 0x6f, 0x5f, 0x56, 0xa0, 0x3e, 0xa9, 0xd3, 0x5c, 1994 0x7d, 0xc3, 0x69, 0xb3, 0xa3, 0x1d, 0x91, 0x0c, 0x23, 0x05, 0xeb, 0xeb, 0xcb, 0x50, 0x71, 0x25, 1995 ]; 1996 const PRESENCE_ATTEMPTS_TABLE_SHA256: [u8; 32] = [ 1997 0xed, 0x26, 0x46, 0x45, 0x6f, 0x96, 0x45, 0xde, 0x57, 0xcb, 0xef, 0x79, 0x62, 0xd6, 0xfe, 0x43, 1998 0x9d, 0xae, 0x10, 0xfd, 0x5e, 0x4c, 0x25, 0x90, 0x91, 0x62, 0x58, 0x8f, 0x58, 0x0d, 0x94, 0x9c, 1999 ]; 2000 const PRESENCE_ATTEMPTS_NO_UPDATE_SHA256: [u8; 32] = [ 2001 0x8b, 0xe2, 0xd1, 0xa5, 0xe6, 0x5d, 0xb9, 0x96, 0xe3, 0x27, 0xb8, 0xee, 0x27, 0x29, 0xa3, 0xe9, 2002 0x1d, 0xa0, 0x68, 0x0e, 0x16, 0x05, 0x90, 0x77, 0x3a, 0x78, 0x1e, 0x80, 0x00, 0x35, 0xac, 0x44, 2003 ]; 2004 const PRESENCE_ATTEMPTS_NO_DELETE_SHA256: [u8; 32] = [ 2005 0x8c, 0x59, 0xe5, 0x11, 0x0e, 0xe5, 0xa7, 0x45, 0x3d, 0xde, 0xca, 0x36, 0xc2, 0x87, 0xc3, 0x6e, 2006 0xbd, 0xf7, 0x74, 0xbb, 0x8d, 0x84, 0xc9, 0xab, 0xd9, 0x76, 0xe2, 0xae, 0x9c, 0xd2, 0x4a, 0x71, 2007 ]; 2008 2009 macro_rules! rhi_admin_operations_table_sql { 2010 () => { 2011 r#"CREATE TABLE rhi_admin_operations ( 2012 operation_id TEXT NOT NULL PRIMARY KEY 2013 CHECK (length(CAST(operation_id AS BLOB)) BETWEEN 1 AND 128) 2014 CHECK (substr(operation_id, 1, 1) GLOB '[A-Za-z0-9]') 2015 CHECK (operation_id NOT GLOB '*[^A-Za-z0-9._:-]*'), 2016 route TEXT NOT NULL CHECK (length(CAST(route AS BLOB)) BETWEEN 1 AND 128), 2017 request_sha256 BLOB NOT NULL CHECK (length(request_sha256) = 32), 2018 state TEXT NOT NULL CHECK (state IN ('prepared', 'completed')), 2019 response_model BLOB CHECK (response_model IS NULL OR 2020 length(response_model) BETWEEN 1 AND 8192), 2021 response_sha256 BLOB CHECK (response_sha256 IS NULL OR 2022 length(response_sha256) = 32), 2023 prepared_at_unix_ms INTEGER NOT NULL 2024 CHECK (prepared_at_unix_ms BETWEEN 0 AND 9223372036854775807), 2025 completed_at_unix_ms INTEGER 2026 CHECK (completed_at_unix_ms IS NULL OR 2027 completed_at_unix_ms BETWEEN prepared_at_unix_ms AND 9223372036854775807), 2028 expires_at_unix_ms INTEGER 2029 CHECK (expires_at_unix_ms IS NULL OR 2030 expires_at_unix_ms BETWEEN completed_at_unix_ms AND 9223372036854775807), 2031 CHECK ((state = 'prepared' AND response_model IS NULL 2032 AND response_sha256 IS NULL AND completed_at_unix_ms IS NULL 2033 AND expires_at_unix_ms IS NULL) 2034 OR (state = 'completed' AND response_model IS NOT NULL 2035 AND response_sha256 IS NOT NULL AND completed_at_unix_ms IS NOT NULL 2036 AND expires_at_unix_ms IS NOT NULL)) 2037 ) STRICT"# 2038 }; 2039 } 2040 2041 macro_rules! rhi_admin_operations_guard_update_sql { 2042 () => { 2043 r#"CREATE TRIGGER rhi_admin_operations_guard_update 2044 BEFORE UPDATE ON rhi_admin_operations 2045 WHEN OLD.state != 'prepared' OR NEW.state != 'completed' 2046 OR NEW.operation_id != OLD.operation_id OR NEW.route != OLD.route 2047 OR NEW.request_sha256 != OLD.request_sha256 2048 OR NEW.prepared_at_unix_ms != OLD.prepared_at_unix_ms 2049 OR NEW.response_model IS NULL OR NEW.response_sha256 IS NULL 2050 OR NEW.completed_at_unix_ms IS NULL OR NEW.expires_at_unix_ms IS NULL 2051 BEGIN 2052 SELECT RAISE(ABORT, 'admin operation transition is invalid'); 2053 END"# 2054 }; 2055 } 2056 2057 const CREATE_RHI_ADMIN_OPERATIONS_TABLE_SQL: &str = rhi_admin_operations_table_sql!(); 2058 const CREATE_RHI_ADMIN_OPERATIONS_GUARD_UPDATE_SQL: &str = rhi_admin_operations_guard_update_sql!(); 2059 const CREATE_RHI_ADMIN_OPERATIONS_MIGRATION_SQL: &str = concat!( 2060 rhi_admin_operations_table_sql!(), 2061 ";\n", 2062 rhi_admin_operations_guard_update_sql!(), 2063 ";", 2064 ); 2065 2066 const RHI_ADMIN_OPERATIONS_TABLE_SHA256: [u8; 32] = [ 2067 0xf7, 0xa6, 0x22, 0x21, 0xc8, 0xec, 0x66, 0x2c, 0x17, 0x14, 0x43, 0x82, 0x2b, 0x11, 0xa9, 0x9b, 2068 0xc4, 0xde, 0x02, 0x13, 0xa1, 0x9e, 0x12, 0xaa, 0x70, 0x54, 0x7b, 0x7f, 0x9d, 0x50, 0x99, 0x21, 2069 ]; 2070 const RHI_ADMIN_OPERATIONS_GUARD_UPDATE_SHA256: [u8; 32] = [ 2071 0xac, 0xe5, 0x7c, 0x97, 0xbc, 0xd5, 0xe9, 0xda, 0x0d, 0xfc, 0xe0, 0x23, 0x65, 0x6d, 0xae, 0xda, 2072 0x96, 0xe5, 0xbf, 0xb6, 0x89, 0x70, 0xa6, 0x06, 0x1b, 0x70, 0x7d, 0x21, 0xec, 0x1f, 0x6b, 0x39, 2073 ]; 2074 2075 /// Stable classes for invalid embedded RHI catalog definitions. 2076 #[derive(Clone, Copy, Debug, PartialEq, Eq)] 2077 pub enum RhiStateCatalogErrorKind { 2078 MigrationCatalog, 2079 SchemaCatalog, 2080 CatalogMismatch, 2081 } 2082 2083 impl RhiStateCatalogErrorKind { 2084 /// Returns the stable machine-readable classification. 2085 #[must_use] 2086 pub const fn code(self) -> &'static str { 2087 match self { 2088 Self::MigrationCatalog => "migration_catalog_invalid", 2089 Self::SchemaCatalog => "schema_catalog_invalid", 2090 Self::CatalogMismatch => "state_catalog_mismatch", 2091 } 2092 } 2093 } 2094 2095 /// Source-free failure to construct or validate the embedded RHI catalogs. 2096 #[derive(Clone, Copy, PartialEq, Eq)] 2097 pub struct RhiStateCatalogError { 2098 kind: RhiStateCatalogErrorKind, 2099 } 2100 2101 impl RhiStateCatalogError { 2102 const fn new(kind: RhiStateCatalogErrorKind) -> Self { 2103 Self { kind } 2104 } 2105 2106 /// Returns the stable failure class. 2107 #[must_use] 2108 pub const fn kind(self) -> RhiStateCatalogErrorKind { 2109 self.kind 2110 } 2111 2112 /// Returns the stable machine-readable code. 2113 #[must_use] 2114 pub const fn code(self) -> &'static str { 2115 self.kind.code() 2116 } 2117 } 2118 2119 impl fmt::Display for RhiStateCatalogError { 2120 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { 2121 formatter.write_str(match self.kind { 2122 RhiStateCatalogErrorKind::MigrationCatalog => { 2123 "RHI migration catalog definition is invalid" 2124 } 2125 RhiStateCatalogErrorKind::SchemaCatalog => "RHI schema catalog definition is invalid", 2126 RhiStateCatalogErrorKind::CatalogMismatch => { 2127 "RHI state catalogs do not match the governed identity" 2128 } 2129 }) 2130 } 2131 } 2132 2133 impl fmt::Debug for RhiStateCatalogError { 2134 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { 2135 formatter 2136 .debug_struct("RhiStateCatalogError") 2137 .field("kind", &self.kind) 2138 .finish() 2139 } 2140 } 2141 2142 impl Error for RhiStateCatalogError {} 2143 2144 fn build_rhi_migration_catalog() -> Result<MigrationCatalog, RhiStateCatalogError> { 2145 let configuration = MigrationDescriptor::sql( 2146 2, 2147 "create_configuration_binding_history", 2148 CREATE_RHI_CONFIG_BINDINGS_MIGRATION_SQL, 2149 MigrationChecksum::from_bytes(RHI_STATE_SCHEMA_VERSION_2_MIGRATION_SHA256), 2150 ) 2151 .map_err(|_| RhiStateCatalogError::new(RhiStateCatalogErrorKind::MigrationCatalog))?; 2152 let trade_evidence = MigrationDescriptor::sql( 2153 3, 2154 "create_immutable_trade_evidence", 2155 CREATE_TRADE_EVIDENCE_MIGRATION_SQL, 2156 MigrationChecksum::from_bytes(RHI_STATE_SCHEMA_VERSION_3_MIGRATION_SHA256), 2157 ) 2158 .map_err(|_| RhiStateCatalogError::new(RhiStateCatalogErrorKind::MigrationCatalog))?; 2159 let source_checkpoints = MigrationDescriptor::sql( 2160 4, 2161 "create_source_checkpoints_and_dirty_generations", 2162 CREATE_SOURCE_CHECKPOINT_MIGRATION_SQL, 2163 MigrationChecksum::from_bytes(RHI_STATE_SCHEMA_VERSION_4_MIGRATION_SHA256), 2164 ) 2165 .map_err(|_| RhiStateCatalogError::new(RhiStateCatalogErrorKind::MigrationCatalog))?; 2166 let reconciliation_jobs = MigrationDescriptor::sql( 2167 5, 2168 "create_reconciliation_jobs", 2169 CREATE_RECONCILIATION_JOBS_MIGRATION_SQL, 2170 MigrationChecksum::from_bytes(RHI_STATE_SCHEMA_VERSION_5_MIGRATION_SHA256), 2171 ) 2172 .map_err(|_| RhiStateCatalogError::new(RhiStateCatalogErrorKind::MigrationCatalog))?; 2173 let reconciliation_results = MigrationDescriptor::sql( 2174 6, 2175 "create_reconciliation_source_results", 2176 CREATE_RECONCILIATION_RESULTS_MIGRATION_SQL, 2177 MigrationChecksum::from_bytes(RHI_STATE_SCHEMA_VERSION_6_MIGRATION_SHA256), 2178 ) 2179 .map_err(|_| RhiStateCatalogError::new(RhiStateCatalogErrorKind::MigrationCatalog))?; 2180 let report_publication = MigrationDescriptor::sql( 2181 7, 2182 "create_reports_and_publication_outbox", 2183 CREATE_REPORT_PUBLICATION_MIGRATION_SQL, 2184 MigrationChecksum::from_bytes(RHI_STATE_SCHEMA_VERSION_7_MIGRATION_SHA256), 2185 ) 2186 .map_err(|_| RhiStateCatalogError::new(RhiStateCatalogErrorKind::MigrationCatalog))?; 2187 let reconciliation_job_shape_guards = MigrationDescriptor::sql( 2188 8, 2189 "guard_reconciliation_job_state_shape", 2190 CREATE_RECONCILIATION_JOB_SHAPE_GUARDS_MIGRATION_SQL, 2191 MigrationChecksum::from_bytes(RHI_STATE_SCHEMA_VERSION_8_MIGRATION_SHA256), 2192 ) 2193 .map_err(|_| RhiStateCatalogError::new(RhiStateCatalogErrorKind::MigrationCatalog))?; 2194 let presence_desired_state = MigrationDescriptor::sql( 2195 9, 2196 "create_presence_desired_state", 2197 CREATE_PRESENCE_DESIRED_STATE_MIGRATION_SQL, 2198 MigrationChecksum::from_bytes(RHI_STATE_SCHEMA_VERSION_9_MIGRATION_SHA256), 2199 ) 2200 .map_err(|_| RhiStateCatalogError::new(RhiStateCatalogErrorKind::MigrationCatalog))?; 2201 let presence_publication = MigrationDescriptor::sql( 2202 10, 2203 "create_presence_publication_workflow", 2204 CREATE_PRESENCE_PUBLICATION_MIGRATION_SQL, 2205 MigrationChecksum::from_bytes(RHI_STATE_SCHEMA_VERSION_10_MIGRATION_SHA256), 2206 ) 2207 .map_err(|_| RhiStateCatalogError::new(RhiStateCatalogErrorKind::MigrationCatalog))?; 2208 let admin_operations = MigrationDescriptor::sql( 2209 11, 2210 "create_admin_operation_journal", 2211 CREATE_RHI_ADMIN_OPERATIONS_MIGRATION_SQL, 2212 MigrationChecksum::from_bytes(RHI_STATE_SCHEMA_VERSION_11_MIGRATION_SHA256), 2213 ) 2214 .map_err(|_| RhiStateCatalogError::new(RhiStateCatalogErrorKind::MigrationCatalog))?; 2215 let catalog = MigrationCatalog::new([ 2216 configuration, 2217 trade_evidence, 2218 source_checkpoints, 2219 reconciliation_jobs, 2220 reconciliation_results, 2221 report_publication, 2222 reconciliation_job_shape_guards, 2223 presence_desired_state, 2224 presence_publication, 2225 admin_operations, 2226 ]) 2227 .map_err(|_| RhiStateCatalogError::new(RhiStateCatalogErrorKind::MigrationCatalog))?; 2228 Ok(catalog) 2229 } 2230 2231 /// Constructs the exact ordered RHI migration catalog. 2232 pub fn rhi_migration_catalog() -> Result<MigrationCatalog, RhiStateCatalogError> { 2233 let catalog = build_rhi_migration_catalog()?; 2234 if catalog.current_version() != RHI_STATE_SCHEMA_VERSION 2235 || catalog.descriptors().len() != 10 2236 || catalog.digest().as_bytes() != &RHI_MIGRATION_CATALOG_SHA256 2237 { 2238 return Err(RhiStateCatalogError::new( 2239 RhiStateCatalogErrorKind::CatalogMismatch, 2240 )); 2241 } 2242 Ok(catalog) 2243 } 2244 2245 /// Constructs the exact RHI schema catalog bound to the migration catalog. 2246 pub fn rhi_schema_catalog() -> Result<SchemaCatalog, RhiStateCatalogError> { 2247 let migrations = rhi_migration_catalog()?; 2248 let catalog = build_rhi_schema_catalog(&migrations)?; 2249 validate_rhi_state_catalogs(&migrations, &catalog)?; 2250 Ok(catalog) 2251 } 2252 2253 fn build_rhi_schema_catalog( 2254 migrations: &MigrationCatalog, 2255 ) -> Result<SchemaCatalog, RhiStateCatalogError> { 2256 let version_one = SchemaVersionCatalog::new( 2257 RHI_STATE_BASE_SCHEMA_VERSION, 2258 [], 2259 SchemaDigest::from_bytes(RHI_STATE_SCHEMA_VERSION_1_SHA256), 2260 ) 2261 .map_err(|_| RhiStateCatalogError::new(RhiStateCatalogErrorKind::SchemaCatalog))?; 2262 let version_two = SchemaVersionCatalog::new( 2263 2, 2264 rhi_config_binding_objects()?, 2265 SchemaDigest::from_bytes(RHI_STATE_SCHEMA_VERSION_2_SHA256), 2266 ) 2267 .map_err(|_| RhiStateCatalogError::new(RhiStateCatalogErrorKind::SchemaCatalog))?; 2268 let version_three = SchemaVersionCatalog::new( 2269 3, 2270 rhi_schema_version_three_objects()?, 2271 SchemaDigest::from_bytes(RHI_STATE_SCHEMA_VERSION_3_SHA256), 2272 ) 2273 .map_err(|_| RhiStateCatalogError::new(RhiStateCatalogErrorKind::SchemaCatalog))?; 2274 let version_four = SchemaVersionCatalog::new( 2275 4, 2276 rhi_schema_version_four_objects()?, 2277 SchemaDigest::from_bytes(RHI_STATE_SCHEMA_VERSION_4_SHA256), 2278 ) 2279 .map_err(|_| RhiStateCatalogError::new(RhiStateCatalogErrorKind::SchemaCatalog))?; 2280 let version_five = SchemaVersionCatalog::new( 2281 5, 2282 rhi_schema_version_five_objects()?, 2283 SchemaDigest::from_bytes(RHI_STATE_SCHEMA_VERSION_5_SHA256), 2284 ) 2285 .map_err(|_| RhiStateCatalogError::new(RhiStateCatalogErrorKind::SchemaCatalog))?; 2286 let version_six = SchemaVersionCatalog::new( 2287 6, 2288 rhi_schema_version_six_objects()?, 2289 SchemaDigest::from_bytes(RHI_STATE_SCHEMA_VERSION_6_SHA256), 2290 ) 2291 .map_err(|_| RhiStateCatalogError::new(RhiStateCatalogErrorKind::SchemaCatalog))?; 2292 let version_seven = SchemaVersionCatalog::new( 2293 7, 2294 rhi_schema_version_seven_objects()?, 2295 SchemaDigest::from_bytes(RHI_STATE_SCHEMA_VERSION_7_SHA256), 2296 ) 2297 .map_err(|_| RhiStateCatalogError::new(RhiStateCatalogErrorKind::SchemaCatalog))?; 2298 let version_eight = SchemaVersionCatalog::new( 2299 8, 2300 rhi_schema_version_eight_objects()?, 2301 SchemaDigest::from_bytes(RHI_STATE_SCHEMA_VERSION_8_SHA256), 2302 ) 2303 .map_err(|_| RhiStateCatalogError::new(RhiStateCatalogErrorKind::SchemaCatalog))?; 2304 let version_nine = SchemaVersionCatalog::new( 2305 9, 2306 rhi_schema_version_nine_objects()?, 2307 SchemaDigest::from_bytes(RHI_STATE_SCHEMA_VERSION_9_SHA256), 2308 ) 2309 .map_err(|_| RhiStateCatalogError::new(RhiStateCatalogErrorKind::SchemaCatalog))?; 2310 let version_ten = SchemaVersionCatalog::new( 2311 10, 2312 rhi_schema_version_ten_objects()?, 2313 SchemaDigest::from_bytes(RHI_STATE_SCHEMA_VERSION_10_SHA256), 2314 ) 2315 .map_err(|_| RhiStateCatalogError::new(RhiStateCatalogErrorKind::SchemaCatalog))?; 2316 let version_eleven = SchemaVersionCatalog::new( 2317 11, 2318 rhi_schema_version_eleven_objects()?, 2319 SchemaDigest::from_bytes(RHI_STATE_SCHEMA_VERSION_11_SHA256), 2320 ) 2321 .map_err(|_| RhiStateCatalogError::new(RhiStateCatalogErrorKind::SchemaCatalog))?; 2322 let catalog = SchemaCatalog::new( 2323 migrations, 2324 [ 2325 version_one, 2326 version_two, 2327 version_three, 2328 version_four, 2329 version_five, 2330 version_six, 2331 version_seven, 2332 version_eight, 2333 version_nine, 2334 version_ten, 2335 version_eleven, 2336 ], 2337 ) 2338 .map_err(|_| RhiStateCatalogError::new(RhiStateCatalogErrorKind::SchemaCatalog))?; 2339 Ok(catalog) 2340 } 2341 2342 /// Independently validates exact catalog versions, counts, and digests. 2343 pub fn validate_rhi_state_catalogs( 2344 migrations: &MigrationCatalog, 2345 schema: &SchemaCatalog, 2346 ) -> Result<(), RhiStateCatalogError> { 2347 let versions = schema.versions(); 2348 let valid = migrations.current_version() == RHI_STATE_SCHEMA_VERSION 2349 && migrations.descriptors().len() == 10 2350 && migrations.digest().as_bytes() == &RHI_MIGRATION_CATALOG_SHA256 2351 && schema.migration_catalog_digest() == migrations.digest() 2352 && versions.len() == 11 2353 && versions[0].version() == RHI_STATE_BASE_SCHEMA_VERSION 2354 && versions[0].object_count() == RHI_STATE_SCHEMA_VERSION_1_OBJECT_COUNT 2355 && versions[0].digest().as_bytes() == &RHI_STATE_SCHEMA_VERSION_1_SHA256 2356 && versions[1].version() == 2 2357 && versions[1].object_count() == RHI_STATE_SCHEMA_VERSION_2_OBJECT_COUNT 2358 && versions[1].digest().as_bytes() == &RHI_STATE_SCHEMA_VERSION_2_SHA256 2359 && versions[2].version() == 3 2360 && versions[2].object_count() == RHI_STATE_SCHEMA_VERSION_3_OBJECT_COUNT 2361 && versions[2].digest().as_bytes() == &RHI_STATE_SCHEMA_VERSION_3_SHA256 2362 && versions[3].version() == 4 2363 && versions[3].object_count() == RHI_STATE_SCHEMA_VERSION_4_OBJECT_COUNT 2364 && versions[3].digest().as_bytes() == &RHI_STATE_SCHEMA_VERSION_4_SHA256 2365 && versions[4].version() == 5 2366 && versions[4].object_count() == RHI_STATE_SCHEMA_VERSION_5_OBJECT_COUNT 2367 && versions[4].digest().as_bytes() == &RHI_STATE_SCHEMA_VERSION_5_SHA256 2368 && versions[5].version() == 6 2369 && versions[5].object_count() == RHI_STATE_SCHEMA_VERSION_6_OBJECT_COUNT 2370 && versions[5].digest().as_bytes() == &RHI_STATE_SCHEMA_VERSION_6_SHA256 2371 && versions[6].version() == 7 2372 && versions[6].object_count() == RHI_STATE_SCHEMA_VERSION_7_OBJECT_COUNT 2373 && versions[6].digest().as_bytes() == &RHI_STATE_SCHEMA_VERSION_7_SHA256 2374 && versions[7].version() == 8 2375 && versions[7].object_count() == RHI_STATE_SCHEMA_VERSION_8_OBJECT_COUNT 2376 && versions[7].digest().as_bytes() == &RHI_STATE_SCHEMA_VERSION_8_SHA256 2377 && versions[8].version() == 9 2378 && versions[8].object_count() == RHI_STATE_SCHEMA_VERSION_9_OBJECT_COUNT 2379 && versions[8].digest().as_bytes() == &RHI_STATE_SCHEMA_VERSION_9_SHA256 2380 && versions[9].version() == 10 2381 && versions[9].object_count() == RHI_STATE_SCHEMA_VERSION_10_OBJECT_COUNT 2382 && versions[9].digest().as_bytes() == &RHI_STATE_SCHEMA_VERSION_10_SHA256 2383 && versions[10].version() == RHI_STATE_SCHEMA_VERSION 2384 && versions[10].object_count() == RHI_STATE_SCHEMA_VERSION_11_OBJECT_COUNT 2385 && versions[10].digest().as_bytes() == &RHI_STATE_SCHEMA_VERSION_11_SHA256 2386 && schema.digest().as_bytes() == &RHI_STATE_SCHEMA_CATALOG_SHA256; 2387 if valid { 2388 Ok(()) 2389 } else { 2390 Err(RhiStateCatalogError::new( 2391 RhiStateCatalogErrorKind::CatalogMismatch, 2392 )) 2393 } 2394 } 2395 2396 fn rhi_config_binding_objects() -> Result<[SchemaObject; 4], RhiStateCatalogError> { 2397 Ok([ 2398 SchemaObject::new( 2399 SchemaObjectKind::Table, 2400 "rhi_config_bindings", 2401 "rhi_config_bindings", 2402 CREATE_RHI_CONFIG_BINDINGS_TABLE_SQL, 2403 SchemaDigest::from_bytes(RHI_CONFIG_BINDINGS_TABLE_SHA256), 2404 ) 2405 .map_err(|_| RhiStateCatalogError::new(RhiStateCatalogErrorKind::SchemaCatalog))?, 2406 SchemaObject::new( 2407 SchemaObjectKind::Trigger, 2408 "rhi_config_bindings_guard_insert", 2409 "rhi_config_bindings", 2410 CREATE_RHI_CONFIG_BINDINGS_GUARD_INSERT_SQL, 2411 SchemaDigest::from_bytes(RHI_CONFIG_BINDINGS_GUARD_INSERT_SHA256), 2412 ) 2413 .map_err(|_| RhiStateCatalogError::new(RhiStateCatalogErrorKind::SchemaCatalog))?, 2414 SchemaObject::new( 2415 SchemaObjectKind::Trigger, 2416 "rhi_config_bindings_no_update", 2417 "rhi_config_bindings", 2418 CREATE_RHI_CONFIG_BINDINGS_NO_UPDATE_SQL, 2419 SchemaDigest::from_bytes(RHI_CONFIG_BINDINGS_NO_UPDATE_SHA256), 2420 ) 2421 .map_err(|_| RhiStateCatalogError::new(RhiStateCatalogErrorKind::SchemaCatalog))?, 2422 SchemaObject::new( 2423 SchemaObjectKind::Trigger, 2424 "rhi_config_bindings_no_delete", 2425 "rhi_config_bindings", 2426 CREATE_RHI_CONFIG_BINDINGS_NO_DELETE_SQL, 2427 SchemaDigest::from_bytes(RHI_CONFIG_BINDINGS_NO_DELETE_SHA256), 2428 ) 2429 .map_err(|_| RhiStateCatalogError::new(RhiStateCatalogErrorKind::SchemaCatalog))?, 2430 ]) 2431 } 2432 2433 fn rhi_schema_version_three_objects() -> Result<Vec<SchemaObject>, RhiStateCatalogError> { 2434 let mut objects = rhi_config_binding_objects()?.to_vec(); 2435 objects.extend(rhi_trade_evidence_objects()?); 2436 Ok(objects) 2437 } 2438 2439 fn rhi_schema_version_four_objects() -> Result<Vec<SchemaObject>, RhiStateCatalogError> { 2440 let mut objects = rhi_schema_version_three_objects()?; 2441 objects.extend(rhi_source_checkpoint_objects()?); 2442 Ok(objects) 2443 } 2444 2445 fn rhi_schema_version_five_objects() -> Result<Vec<SchemaObject>, RhiStateCatalogError> { 2446 let mut objects = rhi_schema_version_four_objects()?; 2447 objects.extend(rhi_reconciliation_job_objects()?); 2448 Ok(objects) 2449 } 2450 2451 fn rhi_schema_version_six_objects() -> Result<Vec<SchemaObject>, RhiStateCatalogError> { 2452 let mut objects = rhi_schema_version_five_objects()?; 2453 objects.extend(rhi_reconciliation_result_objects()?); 2454 Ok(objects) 2455 } 2456 2457 fn rhi_schema_version_seven_objects() -> Result<Vec<SchemaObject>, RhiStateCatalogError> { 2458 let mut objects = rhi_schema_version_six_objects()?; 2459 objects.extend(rhi_report_publication_objects()?); 2460 Ok(objects) 2461 } 2462 2463 fn rhi_schema_version_eight_objects() -> Result<Vec<SchemaObject>, RhiStateCatalogError> { 2464 let mut objects = rhi_schema_version_seven_objects()?; 2465 objects.extend(rhi_reconciliation_job_shape_guard_objects()?); 2466 Ok(objects) 2467 } 2468 2469 fn rhi_schema_version_nine_objects() -> Result<Vec<SchemaObject>, RhiStateCatalogError> { 2470 let mut objects = rhi_schema_version_eight_objects()?; 2471 objects.extend(rhi_presence_desired_state_objects()?); 2472 Ok(objects) 2473 } 2474 2475 fn rhi_schema_version_ten_objects() -> Result<Vec<SchemaObject>, RhiStateCatalogError> { 2476 let mut objects = rhi_schema_version_nine_objects()?; 2477 objects.extend(rhi_presence_publication_objects()?); 2478 Ok(objects) 2479 } 2480 2481 fn rhi_schema_version_eleven_objects() -> Result<Vec<SchemaObject>, RhiStateCatalogError> { 2482 let mut objects = rhi_schema_version_ten_objects()?; 2483 objects.extend(rhi_admin_operation_objects()?); 2484 Ok(objects) 2485 } 2486 2487 fn rhi_admin_operation_objects() -> Result<[SchemaObject; 2], RhiStateCatalogError> { 2488 let object = |kind, name, sql, digest| { 2489 SchemaObject::new( 2490 kind, 2491 name, 2492 "rhi_admin_operations", 2493 sql, 2494 SchemaDigest::from_bytes(digest), 2495 ) 2496 .map_err(|_| RhiStateCatalogError::new(RhiStateCatalogErrorKind::SchemaCatalog)) 2497 }; 2498 Ok([ 2499 object( 2500 SchemaObjectKind::Table, 2501 "rhi_admin_operations", 2502 CREATE_RHI_ADMIN_OPERATIONS_TABLE_SQL, 2503 RHI_ADMIN_OPERATIONS_TABLE_SHA256, 2504 )?, 2505 object( 2506 SchemaObjectKind::Trigger, 2507 "rhi_admin_operations_guard_update", 2508 CREATE_RHI_ADMIN_OPERATIONS_GUARD_UPDATE_SQL, 2509 RHI_ADMIN_OPERATIONS_GUARD_UPDATE_SHA256, 2510 )?, 2511 ]) 2512 } 2513 2514 fn rhi_presence_publication_objects() -> Result<[SchemaObject; 11], RhiStateCatalogError> { 2515 let object = |kind, name, table_name, sql, digest| { 2516 SchemaObject::new( 2517 kind, 2518 name, 2519 table_name, 2520 sql, 2521 SchemaDigest::from_bytes(digest), 2522 ) 2523 .map_err(|_| RhiStateCatalogError::new(RhiStateCatalogErrorKind::SchemaCatalog)) 2524 }; 2525 Ok([ 2526 object( 2527 SchemaObjectKind::Table, 2528 "presence_outbox", 2529 "presence_outbox", 2530 CREATE_PRESENCE_OUTBOX_TABLE_SQL, 2531 PRESENCE_OUTBOX_TABLE_SHA256, 2532 )?, 2533 object( 2534 SchemaObjectKind::Index, 2535 "presence_outbox_by_schedule", 2536 "presence_outbox", 2537 CREATE_PRESENCE_OUTBOX_SCHEDULE_SQL, 2538 PRESENCE_OUTBOX_SCHEDULE_SHA256, 2539 )?, 2540 object( 2541 SchemaObjectKind::Trigger, 2542 "presence_outbox_guard_update", 2543 "presence_outbox", 2544 CREATE_PRESENCE_OUTBOX_GUARD_UPDATE_SQL, 2545 PRESENCE_OUTBOX_GUARD_UPDATE_SHA256, 2546 )?, 2547 object( 2548 SchemaObjectKind::Trigger, 2549 "presence_outbox_no_delete", 2550 "presence_outbox", 2551 CREATE_PRESENCE_OUTBOX_NO_DELETE_SQL, 2552 PRESENCE_OUTBOX_NO_DELETE_SHA256, 2553 )?, 2554 object( 2555 SchemaObjectKind::Table, 2556 "presence_targets", 2557 "presence_targets", 2558 CREATE_PRESENCE_TARGETS_TABLE_SQL, 2559 PRESENCE_TARGETS_TABLE_SHA256, 2560 )?, 2561 object( 2562 SchemaObjectKind::Index, 2563 "presence_targets_by_schedule", 2564 "presence_targets", 2565 CREATE_PRESENCE_TARGETS_SCHEDULE_SQL, 2566 PRESENCE_TARGETS_SCHEDULE_SHA256, 2567 )?, 2568 object( 2569 SchemaObjectKind::Trigger, 2570 "presence_targets_guard_update", 2571 "presence_targets", 2572 CREATE_PRESENCE_TARGETS_GUARD_UPDATE_SQL, 2573 PRESENCE_TARGETS_GUARD_UPDATE_SHA256, 2574 )?, 2575 object( 2576 SchemaObjectKind::Trigger, 2577 "presence_targets_no_delete", 2578 "presence_targets", 2579 CREATE_PRESENCE_TARGETS_NO_DELETE_SQL, 2580 PRESENCE_TARGETS_NO_DELETE_SHA256, 2581 )?, 2582 object( 2583 SchemaObjectKind::Table, 2584 "presence_attempts", 2585 "presence_attempts", 2586 CREATE_PRESENCE_ATTEMPTS_TABLE_SQL, 2587 PRESENCE_ATTEMPTS_TABLE_SHA256, 2588 )?, 2589 object( 2590 SchemaObjectKind::Trigger, 2591 "presence_attempts_no_update", 2592 "presence_attempts", 2593 CREATE_PRESENCE_ATTEMPTS_NO_UPDATE_SQL, 2594 PRESENCE_ATTEMPTS_NO_UPDATE_SHA256, 2595 )?, 2596 object( 2597 SchemaObjectKind::Trigger, 2598 "presence_attempts_no_delete", 2599 "presence_attempts", 2600 CREATE_PRESENCE_ATTEMPTS_NO_DELETE_SQL, 2601 PRESENCE_ATTEMPTS_NO_DELETE_SHA256, 2602 )?, 2603 ]) 2604 } 2605 2606 fn rhi_presence_desired_state_objects() -> Result<[SchemaObject; 4], RhiStateCatalogError> { 2607 let object = |kind, name, sql, digest| { 2608 SchemaObject::new( 2609 kind, 2610 name, 2611 "presence_desired_state", 2612 sql, 2613 SchemaDigest::from_bytes(digest), 2614 ) 2615 .map_err(|_| RhiStateCatalogError::new(RhiStateCatalogErrorKind::SchemaCatalog)) 2616 }; 2617 Ok([ 2618 object( 2619 SchemaObjectKind::Table, 2620 "presence_desired_state", 2621 CREATE_PRESENCE_DESIRED_STATE_TABLE_SQL, 2622 PRESENCE_DESIRED_STATE_TABLE_SHA256, 2623 )?, 2624 object( 2625 SchemaObjectKind::Trigger, 2626 "presence_desired_state_guard_insert", 2627 CREATE_PRESENCE_DESIRED_STATE_GUARD_INSERT_SQL, 2628 PRESENCE_DESIRED_STATE_GUARD_INSERT_SHA256, 2629 )?, 2630 object( 2631 SchemaObjectKind::Trigger, 2632 "presence_desired_state_guard_update", 2633 CREATE_PRESENCE_DESIRED_STATE_GUARD_UPDATE_SQL, 2634 PRESENCE_DESIRED_STATE_GUARD_UPDATE_SHA256, 2635 )?, 2636 object( 2637 SchemaObjectKind::Trigger, 2638 "presence_desired_state_no_delete", 2639 CREATE_PRESENCE_DESIRED_STATE_NO_DELETE_SQL, 2640 PRESENCE_DESIRED_STATE_NO_DELETE_SHA256, 2641 )?, 2642 ]) 2643 } 2644 2645 fn rhi_reconciliation_job_shape_guard_objects() -> Result<[SchemaObject; 2], RhiStateCatalogError> { 2646 let object = |name, sql, digest| { 2647 SchemaObject::new( 2648 SchemaObjectKind::Trigger, 2649 name, 2650 "reconciliation_jobs", 2651 sql, 2652 SchemaDigest::from_bytes(digest), 2653 ) 2654 .map_err(|_| RhiStateCatalogError::new(RhiStateCatalogErrorKind::SchemaCatalog)) 2655 }; 2656 Ok([ 2657 object( 2658 "reconciliation_jobs_shape_guard_insert", 2659 CREATE_RECONCILIATION_JOBS_SHAPE_GUARD_INSERT_SQL, 2660 RECONCILIATION_JOBS_SHAPE_GUARD_INSERT_SHA256, 2661 )?, 2662 object( 2663 "reconciliation_jobs_shape_guard_update", 2664 CREATE_RECONCILIATION_JOBS_SHAPE_GUARD_UPDATE_SQL, 2665 RECONCILIATION_JOBS_SHAPE_GUARD_UPDATE_SHA256, 2666 )?, 2667 ]) 2668 } 2669 2670 fn rhi_report_publication_objects() -> Result<[SchemaObject; 24], RhiStateCatalogError> { 2671 let object = |kind, name, table_name, sql, digest| { 2672 SchemaObject::new( 2673 kind, 2674 name, 2675 table_name, 2676 sql, 2677 SchemaDigest::from_bytes(digest), 2678 ) 2679 .map_err(|_| RhiStateCatalogError::new(RhiStateCatalogErrorKind::SchemaCatalog)) 2680 }; 2681 Ok([ 2682 object( 2683 SchemaObjectKind::Table, 2684 "evidence_manifests", 2685 "evidence_manifests", 2686 CREATE_EVIDENCE_MANIFESTS_TABLE_SQL, 2687 EVIDENCE_MANIFESTS_TABLE_SHA256, 2688 )?, 2689 object( 2690 SchemaObjectKind::Trigger, 2691 "evidence_manifests_no_update", 2692 "evidence_manifests", 2693 CREATE_EVIDENCE_MANIFESTS_NO_UPDATE_SQL, 2694 EVIDENCE_MANIFESTS_NO_UPDATE_SHA256, 2695 )?, 2696 object( 2697 SchemaObjectKind::Trigger, 2698 "evidence_manifests_no_delete", 2699 "evidence_manifests", 2700 CREATE_EVIDENCE_MANIFESTS_NO_DELETE_SQL, 2701 EVIDENCE_MANIFESTS_NO_DELETE_SHA256, 2702 )?, 2703 object( 2704 SchemaObjectKind::Table, 2705 "trade_projections", 2706 "trade_projections", 2707 CREATE_TRADE_PROJECTIONS_TABLE_SQL, 2708 TRADE_PROJECTIONS_TABLE_SHA256, 2709 )?, 2710 object( 2711 SchemaObjectKind::Trigger, 2712 "trade_projections_no_update", 2713 "trade_projections", 2714 CREATE_TRADE_PROJECTIONS_NO_UPDATE_SQL, 2715 TRADE_PROJECTIONS_NO_UPDATE_SHA256, 2716 )?, 2717 object( 2718 SchemaObjectKind::Trigger, 2719 "trade_projections_no_delete", 2720 "trade_projections", 2721 CREATE_TRADE_PROJECTIONS_NO_DELETE_SQL, 2722 TRADE_PROJECTIONS_NO_DELETE_SHA256, 2723 )?, 2724 object( 2725 SchemaObjectKind::Table, 2726 "attestation_reports", 2727 "attestation_reports", 2728 CREATE_ATTESTATION_REPORTS_TABLE_SQL, 2729 ATTESTATION_REPORTS_TABLE_SHA256, 2730 )?, 2731 object( 2732 SchemaObjectKind::Index, 2733 "attestation_reports_one_successor", 2734 "attestation_reports", 2735 CREATE_ATTESTATION_REPORTS_SUPERSESSION_SQL, 2736 ATTESTATION_REPORTS_SUPERSESSION_SHA256, 2737 )?, 2738 object( 2739 SchemaObjectKind::Trigger, 2740 "attestation_reports_no_update", 2741 "attestation_reports", 2742 CREATE_ATTESTATION_REPORTS_NO_UPDATE_SQL, 2743 ATTESTATION_REPORTS_NO_UPDATE_SHA256, 2744 )?, 2745 object( 2746 SchemaObjectKind::Trigger, 2747 "attestation_reports_no_delete", 2748 "attestation_reports", 2749 CREATE_ATTESTATION_REPORTS_NO_DELETE_SQL, 2750 ATTESTATION_REPORTS_NO_DELETE_SHA256, 2751 )?, 2752 object( 2753 SchemaObjectKind::Table, 2754 "signed_attestation_events", 2755 "signed_attestation_events", 2756 CREATE_SIGNED_ATTESTATION_EVENTS_TABLE_SQL, 2757 SIGNED_ATTESTATION_EVENTS_TABLE_SHA256, 2758 )?, 2759 object( 2760 SchemaObjectKind::Trigger, 2761 "signed_attestation_events_no_update", 2762 "signed_attestation_events", 2763 CREATE_SIGNED_ATTESTATION_EVENTS_NO_UPDATE_SQL, 2764 SIGNED_ATTESTATION_EVENTS_NO_UPDATE_SHA256, 2765 )?, 2766 object( 2767 SchemaObjectKind::Trigger, 2768 "signed_attestation_events_no_delete", 2769 "signed_attestation_events", 2770 CREATE_SIGNED_ATTESTATION_EVENTS_NO_DELETE_SQL, 2771 SIGNED_ATTESTATION_EVENTS_NO_DELETE_SHA256, 2772 )?, 2773 object( 2774 SchemaObjectKind::Table, 2775 "publication_outbox", 2776 "publication_outbox", 2777 CREATE_PUBLICATION_OUTBOX_TABLE_SQL, 2778 PUBLICATION_OUTBOX_TABLE_SHA256, 2779 )?, 2780 object( 2781 SchemaObjectKind::Index, 2782 "publication_outbox_by_schedule", 2783 "publication_outbox", 2784 CREATE_PUBLICATION_OUTBOX_SCHEDULE_SQL, 2785 PUBLICATION_OUTBOX_SCHEDULE_SHA256, 2786 )?, 2787 object( 2788 SchemaObjectKind::Trigger, 2789 "publication_outbox_guard_update", 2790 "publication_outbox", 2791 CREATE_PUBLICATION_OUTBOX_GUARD_UPDATE_SQL, 2792 PUBLICATION_OUTBOX_GUARD_UPDATE_SHA256, 2793 )?, 2794 object( 2795 SchemaObjectKind::Trigger, 2796 "publication_outbox_no_delete", 2797 "publication_outbox", 2798 CREATE_PUBLICATION_OUTBOX_NO_DELETE_SQL, 2799 PUBLICATION_OUTBOX_NO_DELETE_SHA256, 2800 )?, 2801 object( 2802 SchemaObjectKind::Table, 2803 "publication_targets", 2804 "publication_targets", 2805 CREATE_PUBLICATION_TARGETS_TABLE_SQL, 2806 PUBLICATION_TARGETS_TABLE_SHA256, 2807 )?, 2808 object( 2809 SchemaObjectKind::Index, 2810 "publication_targets_by_schedule", 2811 "publication_targets", 2812 CREATE_PUBLICATION_TARGETS_SCHEDULE_SQL, 2813 PUBLICATION_TARGETS_SCHEDULE_SHA256, 2814 )?, 2815 object( 2816 SchemaObjectKind::Trigger, 2817 "publication_targets_guard_update", 2818 "publication_targets", 2819 CREATE_PUBLICATION_TARGETS_GUARD_UPDATE_SQL, 2820 PUBLICATION_TARGETS_GUARD_UPDATE_SHA256, 2821 )?, 2822 object( 2823 SchemaObjectKind::Trigger, 2824 "publication_targets_no_delete", 2825 "publication_targets", 2826 CREATE_PUBLICATION_TARGETS_NO_DELETE_SQL, 2827 PUBLICATION_TARGETS_NO_DELETE_SHA256, 2828 )?, 2829 object( 2830 SchemaObjectKind::Table, 2831 "publication_attempts", 2832 "publication_attempts", 2833 CREATE_PUBLICATION_ATTEMPTS_TABLE_SQL, 2834 PUBLICATION_ATTEMPTS_TABLE_SHA256, 2835 )?, 2836 object( 2837 SchemaObjectKind::Trigger, 2838 "publication_attempts_no_update", 2839 "publication_attempts", 2840 CREATE_PUBLICATION_ATTEMPTS_NO_UPDATE_SQL, 2841 PUBLICATION_ATTEMPTS_NO_UPDATE_SHA256, 2842 )?, 2843 object( 2844 SchemaObjectKind::Trigger, 2845 "publication_attempts_no_delete", 2846 "publication_attempts", 2847 CREATE_PUBLICATION_ATTEMPTS_NO_DELETE_SQL, 2848 PUBLICATION_ATTEMPTS_NO_DELETE_SHA256, 2849 )?, 2850 ]) 2851 } 2852 2853 fn rhi_reconciliation_result_objects() -> Result<[SchemaObject; 6], RhiStateCatalogError> { 2854 let object = |kind, name, table_name, sql, digest| { 2855 SchemaObject::new( 2856 kind, 2857 name, 2858 table_name, 2859 sql, 2860 SchemaDigest::from_bytes(digest), 2861 ) 2862 .map_err(|_| RhiStateCatalogError::new(RhiStateCatalogErrorKind::SchemaCatalog)) 2863 }; 2864 Ok([ 2865 object( 2866 SchemaObjectKind::Table, 2867 "evidence_reconciliations", 2868 "evidence_reconciliations", 2869 CREATE_EVIDENCE_RECONCILIATIONS_TABLE_SQL, 2870 EVIDENCE_RECONCILIATIONS_TABLE_SHA256, 2871 )?, 2872 object( 2873 SchemaObjectKind::Trigger, 2874 "evidence_reconciliations_no_update", 2875 "evidence_reconciliations", 2876 CREATE_EVIDENCE_RECONCILIATIONS_NO_UPDATE_SQL, 2877 EVIDENCE_RECONCILIATIONS_NO_UPDATE_SHA256, 2878 )?, 2879 object( 2880 SchemaObjectKind::Trigger, 2881 "evidence_reconciliations_no_delete", 2882 "evidence_reconciliations", 2883 CREATE_EVIDENCE_RECONCILIATIONS_NO_DELETE_SQL, 2884 EVIDENCE_RECONCILIATIONS_NO_DELETE_SHA256, 2885 )?, 2886 object( 2887 SchemaObjectKind::Table, 2888 "evidence_reconciliation_sources", 2889 "evidence_reconciliation_sources", 2890 CREATE_EVIDENCE_RECONCILIATION_SOURCES_TABLE_SQL, 2891 EVIDENCE_RECONCILIATION_SOURCES_TABLE_SHA256, 2892 )?, 2893 object( 2894 SchemaObjectKind::Trigger, 2895 "evidence_reconciliation_sources_no_update", 2896 "evidence_reconciliation_sources", 2897 CREATE_EVIDENCE_RECONCILIATION_SOURCES_NO_UPDATE_SQL, 2898 EVIDENCE_RECONCILIATION_SOURCES_NO_UPDATE_SHA256, 2899 )?, 2900 object( 2901 SchemaObjectKind::Trigger, 2902 "evidence_reconciliation_sources_no_delete", 2903 "evidence_reconciliation_sources", 2904 CREATE_EVIDENCE_RECONCILIATION_SOURCES_NO_DELETE_SQL, 2905 EVIDENCE_RECONCILIATION_SOURCES_NO_DELETE_SHA256, 2906 )?, 2907 ]) 2908 } 2909 2910 fn rhi_reconciliation_job_objects() -> Result<[SchemaObject; 5], RhiStateCatalogError> { 2911 let object = |kind, name, table_name, sql, digest| { 2912 SchemaObject::new( 2913 kind, 2914 name, 2915 table_name, 2916 sql, 2917 SchemaDigest::from_bytes(digest), 2918 ) 2919 .map_err(|_| RhiStateCatalogError::new(RhiStateCatalogErrorKind::SchemaCatalog)) 2920 }; 2921 Ok([ 2922 object( 2923 SchemaObjectKind::Table, 2924 "reconciliation_jobs", 2925 "reconciliation_jobs", 2926 CREATE_RECONCILIATION_JOBS_TABLE_SQL, 2927 RECONCILIATION_JOBS_TABLE_SHA256, 2928 )?, 2929 object( 2930 SchemaObjectKind::Index, 2931 "reconciliation_jobs_one_active_per_trade", 2932 "reconciliation_jobs", 2933 CREATE_RECONCILIATION_JOBS_ONE_ACTIVE_SQL, 2934 RECONCILIATION_JOBS_ONE_ACTIVE_SHA256, 2935 )?, 2936 object( 2937 SchemaObjectKind::Index, 2938 "reconciliation_jobs_by_schedule", 2939 "reconciliation_jobs", 2940 CREATE_RECONCILIATION_JOBS_SCHEDULE_SQL, 2941 RECONCILIATION_JOBS_SCHEDULE_SHA256, 2942 )?, 2943 object( 2944 SchemaObjectKind::Trigger, 2945 "reconciliation_jobs_guard_update", 2946 "reconciliation_jobs", 2947 CREATE_RECONCILIATION_JOBS_GUARD_UPDATE_SQL, 2948 RECONCILIATION_JOBS_GUARD_UPDATE_SHA256, 2949 )?, 2950 object( 2951 SchemaObjectKind::Trigger, 2952 "reconciliation_jobs_no_delete", 2953 "reconciliation_jobs", 2954 CREATE_RECONCILIATION_JOBS_NO_DELETE_SQL, 2955 RECONCILIATION_JOBS_NO_DELETE_SHA256, 2956 )?, 2957 ]) 2958 } 2959 2960 fn rhi_source_checkpoint_objects() -> Result<[SchemaObject; 6], RhiStateCatalogError> { 2961 let object = |kind, name, table_name, sql, digest| { 2962 SchemaObject::new( 2963 kind, 2964 name, 2965 table_name, 2966 sql, 2967 SchemaDigest::from_bytes(digest), 2968 ) 2969 .map_err(|_| RhiStateCatalogError::new(RhiStateCatalogErrorKind::SchemaCatalog)) 2970 }; 2971 Ok([ 2972 object( 2973 SchemaObjectKind::Table, 2974 "relay_checkpoints", 2975 "relay_checkpoints", 2976 CREATE_RELAY_CHECKPOINTS_TABLE_SQL, 2977 RELAY_CHECKPOINTS_TABLE_SHA256, 2978 )?, 2979 object( 2980 SchemaObjectKind::Trigger, 2981 "relay_checkpoints_guard_update", 2982 "relay_checkpoints", 2983 CREATE_RELAY_CHECKPOINTS_GUARD_UPDATE_SQL, 2984 RELAY_CHECKPOINTS_GUARD_UPDATE_SHA256, 2985 )?, 2986 object( 2987 SchemaObjectKind::Trigger, 2988 "relay_checkpoints_no_delete", 2989 "relay_checkpoints", 2990 CREATE_RELAY_CHECKPOINTS_NO_DELETE_SQL, 2991 RELAY_CHECKPOINTS_NO_DELETE_SHA256, 2992 )?, 2993 object( 2994 SchemaObjectKind::Table, 2995 "trade_dirty_generations", 2996 "trade_dirty_generations", 2997 CREATE_TRADE_DIRTY_GENERATIONS_TABLE_SQL, 2998 TRADE_DIRTY_GENERATIONS_TABLE_SHA256, 2999 )?, 3000 object( 3001 SchemaObjectKind::Trigger, 3002 "trade_dirty_generations_guard_update", 3003 "trade_dirty_generations", 3004 CREATE_TRADE_DIRTY_GENERATIONS_GUARD_UPDATE_SQL, 3005 TRADE_DIRTY_GENERATIONS_GUARD_UPDATE_SHA256, 3006 )?, 3007 object( 3008 SchemaObjectKind::Trigger, 3009 "trade_dirty_generations_no_delete", 3010 "trade_dirty_generations", 3011 CREATE_TRADE_DIRTY_GENERATIONS_NO_DELETE_SQL, 3012 TRADE_DIRTY_GENERATIONS_NO_DELETE_SHA256, 3013 )?, 3014 ]) 3015 } 3016 3017 fn rhi_trade_evidence_objects() -> Result<[SchemaObject; 12], RhiStateCatalogError> { 3018 let object = |kind, name, table_name, sql, digest| { 3019 SchemaObject::new( 3020 kind, 3021 name, 3022 table_name, 3023 sql, 3024 SchemaDigest::from_bytes(digest), 3025 ) 3026 .map_err(|_| RhiStateCatalogError::new(RhiStateCatalogErrorKind::SchemaCatalog)) 3027 }; 3028 Ok([ 3029 object( 3030 SchemaObjectKind::Table, 3031 "trade_mutations", 3032 "trade_mutations", 3033 CREATE_TRADE_MUTATIONS_TABLE_SQL, 3034 TRADE_MUTATIONS_TABLE_SHA256, 3035 )?, 3036 object( 3037 SchemaObjectKind::Index, 3038 "trade_mutations_by_trade", 3039 "trade_mutations", 3040 CREATE_TRADE_MUTATIONS_BY_TRADE_SQL, 3041 TRADE_MUTATIONS_BY_TRADE_SHA256, 3042 )?, 3043 object( 3044 SchemaObjectKind::Table, 3045 "nostr_events", 3046 "nostr_events", 3047 CREATE_NOSTR_EVENTS_TABLE_SQL, 3048 NOSTR_EVENTS_TABLE_SHA256, 3049 )?, 3050 object( 3051 SchemaObjectKind::Index, 3052 "nostr_events_by_mutation", 3053 "nostr_events", 3054 CREATE_NOSTR_EVENTS_BY_MUTATION_SQL, 3055 NOSTR_EVENTS_BY_MUTATION_SHA256, 3056 )?, 3057 object( 3058 SchemaObjectKind::Table, 3059 "relay_observations", 3060 "relay_observations", 3061 CREATE_RELAY_OBSERVATIONS_TABLE_SQL, 3062 RELAY_OBSERVATIONS_TABLE_SHA256, 3063 )?, 3064 object( 3065 SchemaObjectKind::Index, 3066 "relay_observations_by_event", 3067 "relay_observations", 3068 CREATE_RELAY_OBSERVATIONS_BY_EVENT_SQL, 3069 RELAY_OBSERVATIONS_BY_EVENT_SHA256, 3070 )?, 3071 object( 3072 SchemaObjectKind::Trigger, 3073 "trade_mutations_no_update", 3074 "trade_mutations", 3075 CREATE_TRADE_MUTATIONS_NO_UPDATE_SQL, 3076 TRADE_MUTATIONS_NO_UPDATE_SHA256, 3077 )?, 3078 object( 3079 SchemaObjectKind::Trigger, 3080 "trade_mutations_no_delete", 3081 "trade_mutations", 3082 CREATE_TRADE_MUTATIONS_NO_DELETE_SQL, 3083 TRADE_MUTATIONS_NO_DELETE_SHA256, 3084 )?, 3085 object( 3086 SchemaObjectKind::Trigger, 3087 "nostr_events_no_update", 3088 "nostr_events", 3089 CREATE_NOSTR_EVENTS_NO_UPDATE_SQL, 3090 NOSTR_EVENTS_NO_UPDATE_SHA256, 3091 )?, 3092 object( 3093 SchemaObjectKind::Trigger, 3094 "nostr_events_no_delete", 3095 "nostr_events", 3096 CREATE_NOSTR_EVENTS_NO_DELETE_SQL, 3097 NOSTR_EVENTS_NO_DELETE_SHA256, 3098 )?, 3099 object( 3100 SchemaObjectKind::Trigger, 3101 "relay_observations_no_update", 3102 "relay_observations", 3103 CREATE_RELAY_OBSERVATIONS_NO_UPDATE_SQL, 3104 RELAY_OBSERVATIONS_NO_UPDATE_SHA256, 3105 )?, 3106 object( 3107 SchemaObjectKind::Trigger, 3108 "relay_observations_no_delete", 3109 "relay_observations", 3110 CREATE_RELAY_OBSERVATIONS_NO_DELETE_SQL, 3111 RELAY_OBSERVATIONS_NO_DELETE_SHA256, 3112 )?, 3113 ]) 3114 }