diff --git a/.pnp.cjs b/.pnp.cjs index 05207cf96d2..9fbc5f58490 100755 --- a/.pnp.cjs +++ b/.pnp.cjs @@ -6408,7 +6408,7 @@ const RAW_RUNTIME_STATE = ["p-limit", "npm:2.3.0"],\ ["semver", "npm:7.5.3"],\ ["strip-ansi", "npm:6.0.1"],\ - ["tar", "npm:7.5.7"],\ + ["tar", "npm:7.5.9"],\ ["tinylogic", "npm:2.0.0"],\ ["treeify", "npm:1.1.0"],\ ["tslib", "npm:2.6.2"],\ @@ -7754,7 +7754,7 @@ const RAW_RUNTIME_STATE = ["http-errors", "npm:2.0.0"],\ ["iconv-lite", "npm:0.4.24"],\ ["on-finished", "npm:2.4.1"],\ - ["qs", "npm:6.14.1"],\ + ["qs", "npm:6.15.0"],\ ["raw-body", "npm:2.5.2"],\ ["type-is", "npm:1.6.18"],\ ["unpipe", "npm:1.0.0"]\ @@ -7924,7 +7924,7 @@ const RAW_RUNTIME_STATE = "packageDependencies": [\ ["baseline-browser-mapping", "npm:2.9.19"],\ ["browserslist", "npm:4.28.1"],\ - ["caniuse-lite", "npm:1.0.30001769"],\ + ["caniuse-lite", "npm:1.0.30001770"],\ ["electron-to-chromium", "npm:1.5.286"],\ ["node-releases", "npm:2.0.27"],\ ["update-browserslist-db", "virtual:e455c4c2e8dc3f3e2b2f64927f2b0dff7ca09ff7730ccbb69cae3e9342c0b24fae16e40b2aa46a2b677c172a1365ba425382266fccbf1e96179eec79a4a5c294#npm:1.2.3"]\ @@ -8069,7 +8069,7 @@ const RAW_RUNTIME_STATE = ["minipass-pipeline", "npm:1.2.4"],\ ["p-map", "npm:4.0.0"],\ ["ssri", "npm:10.0.5"],\ - ["tar", "npm:7.5.7"],\ + ["tar", "npm:7.5.9"],\ ["unique-filename", "npm:3.0.0"]\ ],\ "linkType": "HARD"\ @@ -8251,10 +8251,10 @@ const RAW_RUNTIME_STATE = ],\ "linkType": "HARD"\ }],\ - ["npm:1.0.30001769", {\ - "packageLocation": "./.yarn/cache/caniuse-lite-npm-1.0.30001769-4fac3a9dca-4b7d087832.zip/node_modules/caniuse-lite/",\ + ["npm:1.0.30001770", {\ + "packageLocation": "./.yarn/cache/caniuse-lite-npm-1.0.30001770-4a95887078-a85fb08958.zip/node_modules/caniuse-lite/",\ "packageDependencies": [\ - ["caniuse-lite", "npm:1.0.30001769"]\ + ["caniuse-lite", "npm:1.0.30001770"]\ ],\ "linkType": "HARD"\ }]\ @@ -9617,14 +9617,14 @@ const RAW_RUNTIME_STATE = ["pretty-bytes", "npm:5.6.0"],\ ["pretty-ms", "npm:7.0.1"],\ ["public-ip", "npm:6.0.1"],\ - ["qs", "npm:6.14.1"],\ + ["qs", "npm:6.15.0"],\ ["rxjs", "npm:6.6.7"],\ ["semver", "npm:7.5.3"],\ ["sinon", "npm:17.0.1"],\ ["sinon-chai", "virtual:e2d057e7cc143d3cb9bec864f4a2d862441b5a09f81f8e6c46e7a098cbc89e4d07017cc6e2e2142d5704bb55da853cbec2d025ebc0b30e8696c31380c00f2c7d#npm:3.7.0"],\ ["systeminformation", "npm:5.27.14"],\ ["table", "npm:6.8.1"],\ - ["tar", "npm:7.5.7"],\ + ["tar", "npm:7.5.9"],\ ["wrap-ansi", "npm:7.0.0"]\ ],\ "linkType": "SOFT"\ @@ -16563,7 +16563,7 @@ const RAW_RUNTIME_STATE = ["nopt", "npm:7.2.0"],\ ["proc-log", "npm:3.0.0"],\ ["semver", "npm:7.5.3"],\ - ["tar", "npm:7.5.7"],\ + ["tar", "npm:7.5.9"],\ ["which", "npm:4.0.0"]\ ],\ "linkType": "HARD"\ @@ -17471,7 +17471,7 @@ const RAW_RUNTIME_STATE = ["read-package-json-fast", "npm:2.0.3"],\ ["rimraf", "npm:3.0.2"],\ ["ssri", "npm:8.0.1"],\ - ["tar", "npm:7.5.7"]\ + ["tar", "npm:7.5.9"]\ ],\ "linkType": "HARD"\ }],\ @@ -17496,7 +17496,7 @@ const RAW_RUNTIME_STATE = ["read-package-json-fast", "npm:3.0.2"],\ ["sigstore", "npm:1.9.0"],\ ["ssri", "npm:10.0.5"],\ - ["tar", "npm:7.5.7"]\ + ["tar", "npm:7.5.9"]\ ],\ "linkType": "HARD"\ }]\ @@ -18285,10 +18285,10 @@ const RAW_RUNTIME_STATE = }]\ ]],\ ["qs", [\ - ["npm:6.14.1", {\ - "packageLocation": "./.yarn/cache/qs-npm-6.14.1-2af4c28250-34b5ab00a9.zip/node_modules/qs/",\ + ["npm:6.15.0", {\ + "packageLocation": "./.yarn/cache/qs-npm-6.15.0-2165244317-a3458f2f38.zip/node_modules/qs/",\ "packageDependencies": [\ - ["qs", "npm:6.14.1"],\ + ["qs", "npm:6.15.0"],\ ["side-channel", "npm:1.1.0"]\ ],\ "linkType": "HARD"\ @@ -20528,14 +20528,14 @@ const RAW_RUNTIME_STATE = }]\ ]],\ ["tar", [\ - ["npm:7.5.7", {\ - "packageLocation": "./.yarn/cache/tar-npm-7.5.7-053aec5a88-0d6938dd32.zip/node_modules/tar/",\ + ["npm:7.5.9", {\ + "packageLocation": "./.yarn/cache/tar-npm-7.5.9-dd42dd386e-1213cdde9c.zip/node_modules/tar/",\ "packageDependencies": [\ ["@isaacs/fs-minipass", "npm:4.0.1"],\ ["chownr", "npm:3.0.0"],\ ["minipass", "npm:7.1.2"],\ ["minizlib", "npm:3.1.0"],\ - ["tar", "npm:7.5.7"],\ + ["tar", "npm:7.5.9"],\ ["yallist", "npm:5.0.0"]\ ],\ "linkType": "HARD"\ @@ -22149,7 +22149,7 @@ const RAW_RUNTIME_STATE = "packageLocation": "./.yarn/cache/url-npm-0.11.3-d3652df78a-a3a5ba64d8.zip/node_modules/url/",\ "packageDependencies": [\ ["punycode", "npm:1.4.1"],\ - ["qs", "npm:6.14.1"],\ + ["qs", "npm:6.15.0"],\ ["url", "npm:0.11.3"]\ ],\ "linkType": "HARD"\ @@ -22427,7 +22427,7 @@ const RAW_RUNTIME_STATE = ["watchpack", "npm:2.5.1"],\ ["webpack", "virtual:01938c2be4835443e5a304e2b117c575220e96e8b7cedeb0f48d79264590b4c4babc6d1fea6367f522b1ca0149d795b42f2ab89c34a6ffe3c20f0a8cbb8b4453#npm:5.105.0"],\ ["webpack-cli", null],\ - ["webpack-sources", "npm:3.3.3"]\ + ["webpack-sources", "npm:3.3.4"]\ ],\ "packagePeers": [\ "@types/webpack-cli",\ @@ -22465,7 +22465,7 @@ const RAW_RUNTIME_STATE = ["watchpack", "npm:2.5.1"],\ ["webpack", "virtual:45f214395bc38640da4dc5e940482d5df0572c5384e0262802601d1973e71077ec8bbd76b77eafa4c0550b706b664abd84d63fd67a5897139f0b2675530fc84f#npm:5.105.0"],\ ["webpack-cli", "virtual:45f214395bc38640da4dc5e940482d5df0572c5384e0262802601d1973e71077ec8bbd76b77eafa4c0550b706b664abd84d63fd67a5897139f0b2675530fc84f#npm:4.9.1"],\ - ["webpack-sources", "npm:3.3.3"]\ + ["webpack-sources", "npm:3.3.4"]\ ],\ "packagePeers": [\ "@types/webpack-cli",\ @@ -22503,7 +22503,7 @@ const RAW_RUNTIME_STATE = ["watchpack", "npm:2.5.1"],\ ["webpack", "virtual:897449be52adaf897095babe74bfcc926f5d083ac9aac6fbc5e260f1f71b7e3ada3f268ac9457d3009b9c6fca51fe685ec21fbed21ec5087df84ab489b719456#npm:5.105.0"],\ ["webpack-cli", "virtual:897449be52adaf897095babe74bfcc926f5d083ac9aac6fbc5e260f1f71b7e3ada3f268ac9457d3009b9c6fca51fe685ec21fbed21ec5087df84ab489b719456#npm:4.9.1"],\ - ["webpack-sources", "npm:3.3.3"]\ + ["webpack-sources", "npm:3.3.4"]\ ],\ "packagePeers": [\ "@types/webpack-cli",\ @@ -22541,7 +22541,7 @@ const RAW_RUNTIME_STATE = ["watchpack", "npm:2.5.1"],\ ["webpack", "virtual:8f25fc90e0fb5fd89843707863857591fa8c52f9f33eadced4bf404b1871d91959f7bb86948ae0e1b53ee94d491ef8fde9c0b58b39c9490c0d0fa6c931945f97#npm:5.105.0"],\ ["webpack-cli", "virtual:8f25fc90e0fb5fd89843707863857591fa8c52f9f33eadced4bf404b1871d91959f7bb86948ae0e1b53ee94d491ef8fde9c0b58b39c9490c0d0fa6c931945f97#npm:4.9.1"],\ - ["webpack-sources", "npm:3.3.3"]\ + ["webpack-sources", "npm:3.3.4"]\ ],\ "packagePeers": [\ "@types/webpack-cli",\ @@ -22579,7 +22579,7 @@ const RAW_RUNTIME_STATE = ["watchpack", "npm:2.5.1"],\ ["webpack", "virtual:98d1afeac78a19485e4cb7428abff692e58b6fc468d8040035b560ed49383fc95857be6b5014af27e53063e6f08b654690c2b945f3443c22dd60c6b083684b3c#npm:5.105.0"],\ ["webpack-cli", "virtual:98d1afeac78a19485e4cb7428abff692e58b6fc468d8040035b560ed49383fc95857be6b5014af27e53063e6f08b654690c2b945f3443c22dd60c6b083684b3c#npm:4.9.1"],\ - ["webpack-sources", "npm:3.3.3"]\ + ["webpack-sources", "npm:3.3.4"]\ ],\ "packagePeers": [\ "@types/webpack-cli",\ @@ -22617,7 +22617,7 @@ const RAW_RUNTIME_STATE = ["watchpack", "npm:2.5.1"],\ ["webpack", "virtual:ad53cff31b1dbd4927a99e71702e3b8b10338636eaff010987c27c9ccea2d52af36900a9e36a4231cbb6e5464248ccc9c1da5d1d24d9b0f4f95660296b1060a6#npm:5.105.0"],\ ["webpack-cli", "virtual:ad53cff31b1dbd4927a99e71702e3b8b10338636eaff010987c27c9ccea2d52af36900a9e36a4231cbb6e5464248ccc9c1da5d1d24d9b0f4f95660296b1060a6#npm:4.9.1"],\ - ["webpack-sources", "npm:3.3.3"]\ + ["webpack-sources", "npm:3.3.4"]\ ],\ "packagePeers": [\ "@types/webpack-cli",\ @@ -22655,7 +22655,7 @@ const RAW_RUNTIME_STATE = ["watchpack", "npm:2.5.1"],\ ["webpack", "virtual:da12f6bb23b671689b7f4f5cfff69cabf980ba04aff1ffd96860c787f7d5d08d32b0db765d9f16463de0d1af2c01fa6987b861cf5df2362e38e0ef415f29b51c#npm:5.105.0"],\ ["webpack-cli", "virtual:da12f6bb23b671689b7f4f5cfff69cabf980ba04aff1ffd96860c787f7d5d08d32b0db765d9f16463de0d1af2c01fa6987b861cf5df2362e38e0ef415f29b51c#npm:4.9.1"],\ - ["webpack-sources", "npm:3.3.3"]\ + ["webpack-sources", "npm:3.3.4"]\ ],\ "packagePeers": [\ "@types/webpack-cli",\ @@ -22693,7 +22693,7 @@ const RAW_RUNTIME_STATE = ["watchpack", "npm:2.5.1"],\ ["webpack", "virtual:e2d057e7cc143d3cb9bec864f4a2d862441b5a09f81f8e6c46e7a098cbc89e4d07017cc6e2e2142d5704bb55da853cbec2d025ebc0b30e8696c31380c00f2c7d#npm:5.105.0"],\ ["webpack-cli", "virtual:e2d057e7cc143d3cb9bec864f4a2d862441b5a09f81f8e6c46e7a098cbc89e4d07017cc6e2e2142d5704bb55da853cbec2d025ebc0b30e8696c31380c00f2c7d#npm:4.9.1"],\ - ["webpack-sources", "npm:3.3.3"]\ + ["webpack-sources", "npm:3.3.4"]\ ],\ "packagePeers": [\ "@types/webpack-cli",\ @@ -23018,10 +23018,10 @@ const RAW_RUNTIME_STATE = }]\ ]],\ ["webpack-sources", [\ - ["npm:3.3.3", {\ - "packageLocation": "./.yarn/cache/webpack-sources-npm-3.3.3-62a2b4959b-ec5d72607e.zip/node_modules/webpack-sources/",\ + ["npm:3.3.4", {\ + "packageLocation": "./.yarn/cache/webpack-sources-npm-3.3.4-91ec02c87c-714427b235.zip/node_modules/webpack-sources/",\ "packageDependencies": [\ - ["webpack-sources", "npm:3.3.3"]\ + ["webpack-sources", "npm:3.3.4"]\ ],\ "linkType": "HARD"\ }]\ diff --git a/.yarn/cache/@unrs-resolver-binding-darwin-arm64-npm-1.11.1-c78d4bd2cb-10.zip b/.yarn/cache/@unrs-resolver-binding-darwin-arm64-npm-1.11.1-c78d4bd2cb-10.zip new file mode 100644 index 00000000000..c25b83d2ad6 Binary files /dev/null and b/.yarn/cache/@unrs-resolver-binding-darwin-arm64-npm-1.11.1-c78d4bd2cb-10.zip differ diff --git a/.yarn/cache/@unrs-resolver-binding-linux-x64-gnu-npm-1.11.1-93a00570de-10.zip b/.yarn/cache/@unrs-resolver-binding-linux-x64-gnu-npm-1.11.1-93a00570de-10.zip deleted file mode 100644 index a5061a1a7eb..00000000000 Binary files a/.yarn/cache/@unrs-resolver-binding-linux-x64-gnu-npm-1.11.1-93a00570de-10.zip and /dev/null differ diff --git a/.yarn/cache/caniuse-lite-npm-1.0.30001769-4fac3a9dca-4b7d087832.zip b/.yarn/cache/caniuse-lite-npm-1.0.30001769-4fac3a9dca-4b7d087832.zip deleted file mode 100644 index 9afe82ece04..00000000000 Binary files a/.yarn/cache/caniuse-lite-npm-1.0.30001769-4fac3a9dca-4b7d087832.zip and /dev/null differ diff --git a/.yarn/cache/caniuse-lite-npm-1.0.30001770-4a95887078-a85fb08958.zip b/.yarn/cache/caniuse-lite-npm-1.0.30001770-4a95887078-a85fb08958.zip new file mode 100644 index 00000000000..2095be9e5f1 Binary files /dev/null and b/.yarn/cache/caniuse-lite-npm-1.0.30001770-4a95887078-a85fb08958.zip differ diff --git a/.yarn/cache/qs-npm-6.14.1-2af4c28250-34b5ab00a9.zip b/.yarn/cache/qs-npm-6.14.1-2af4c28250-34b5ab00a9.zip deleted file mode 100644 index 0ebdd32dd68..00000000000 Binary files a/.yarn/cache/qs-npm-6.14.1-2af4c28250-34b5ab00a9.zip and /dev/null differ diff --git a/.yarn/cache/qs-npm-6.15.0-2165244317-a3458f2f38.zip b/.yarn/cache/qs-npm-6.15.0-2165244317-a3458f2f38.zip new file mode 100644 index 00000000000..bd815cedcfc Binary files /dev/null and b/.yarn/cache/qs-npm-6.15.0-2165244317-a3458f2f38.zip differ diff --git a/.yarn/cache/tar-npm-7.5.7-053aec5a88-0d6938dd32.zip b/.yarn/cache/tar-npm-7.5.7-053aec5a88-0d6938dd32.zip deleted file mode 100644 index 4e183c1f29e..00000000000 Binary files a/.yarn/cache/tar-npm-7.5.7-053aec5a88-0d6938dd32.zip and /dev/null differ diff --git a/.yarn/cache/tar-npm-7.5.9-dd42dd386e-1213cdde9c.zip b/.yarn/cache/tar-npm-7.5.9-dd42dd386e-1213cdde9c.zip new file mode 100644 index 00000000000..11ecff8d7f6 Binary files /dev/null and b/.yarn/cache/tar-npm-7.5.9-dd42dd386e-1213cdde9c.zip differ diff --git a/.yarn/cache/webpack-sources-npm-3.3.3-62a2b4959b-ec5d72607e.zip b/.yarn/cache/webpack-sources-npm-3.3.3-62a2b4959b-ec5d72607e.zip deleted file mode 100644 index a3cfef318c3..00000000000 Binary files a/.yarn/cache/webpack-sources-npm-3.3.3-62a2b4959b-ec5d72607e.zip and /dev/null differ diff --git a/.yarn/cache/webpack-sources-npm-3.3.4-91ec02c87c-714427b235.zip b/.yarn/cache/webpack-sources-npm-3.3.4-91ec02c87c-714427b235.zip new file mode 100644 index 00000000000..29028a785aa Binary files /dev/null and b/.yarn/cache/webpack-sources-npm-3.3.4-91ec02c87c-714427b235.zip differ diff --git a/package.json b/package.json index 14babb1c238..a67167fc2c5 100644 --- a/package.json +++ b/package.json @@ -81,7 +81,7 @@ "packages/js-evo-sdk" ], "resolutions": { - "tar": "7.5.7", + "tar": "7.5.9", "pbkdf2": "^3.1.3", "elliptic": "6.6.1", "bn.js": "4.12.0", diff --git a/packages/dashmate/package.json b/packages/dashmate/package.json index bd572633e14..b58a83ce8f1 100644 --- a/packages/dashmate/package.json +++ b/packages/dashmate/package.json @@ -88,12 +88,12 @@ "pretty-bytes": "^5.3.0", "pretty-ms": "^7.0.0", "public-ip": "^6.0.1", - "qs": "^6.14.1", + "qs": "^6.14.2", "rxjs": "^6.6.7", "semver": "^7.5.3", "systeminformation": "^5.27.14", "table": "^6.8.1", - "tar": "7.5.7", + "tar": "7.5.9", "wrap-ansi": "^7.0.0" }, "devDependencies": { diff --git a/packages/rs-dpp/src/data_contract/config/methods/validate_update/mod.rs b/packages/rs-dpp/src/data_contract/config/methods/validate_update/mod.rs index 1df2ee3d726..85a7fdb1ae1 100644 --- a/packages/rs-dpp/src/data_contract/config/methods/validate_update/mod.rs +++ b/packages/rs-dpp/src/data_contract/config/methods/validate_update/mod.rs @@ -5,6 +5,7 @@ use platform_value::Identifier; use platform_version::version::PlatformVersion; mod v0; +mod v1; impl DataContractConfig { pub fn validate_update( @@ -20,9 +21,10 @@ impl DataContractConfig { .validate_config_update { 0 => Ok(self.validate_update_v0(new_config, contract_id)), + 1 => Ok(self.validate_update_v1(new_config, contract_id, platform_version)), version => Err(ProtocolError::UnknownVersionMismatch { method: "validate_update".to_string(), - known_versions: vec![0], + known_versions: vec![0, 1], received: version, }), } diff --git a/packages/rs-dpp/src/data_contract/config/methods/validate_update/v1/mod.rs b/packages/rs-dpp/src/data_contract/config/methods/validate_update/v1/mod.rs new file mode 100644 index 00000000000..08e809d36d9 --- /dev/null +++ b/packages/rs-dpp/src/data_contract/config/methods/validate_update/v1/mod.rs @@ -0,0 +1,206 @@ +use crate::consensus::state::data_contract::data_contract_config_update_error::DataContractConfigUpdateError; +use crate::data_contract::config::v1::DataContractConfigGettersV1; +use crate::data_contract::config::DataContractConfig; +use crate::validation::SimpleConsensusValidationResult; +use platform_value::Identifier; +use platform_version::version::FeatureVersion; +use platform_version::version::PlatformVersion; + +impl DataContractConfig { + #[inline(always)] + pub(super) fn validate_update_v1( + &self, + new_config: &DataContractConfig, + contract_id: Identifier, + platform_version: &PlatformVersion, + ) -> SimpleConsensusValidationResult { + // Run all v0 checks first + let v0_result = self.validate_update_v0(new_config, contract_id); + if !v0_result.is_valid() { + return v0_result; + } + + // Validate: new config version meets minimum version requirement. + // Since protocol version 12, V0 config is no longer accepted because it lacks + // sized_integer_types support. + let min_version = platform_version.dpp.contract_versions.config.min_version; + if (new_config.version() as FeatureVersion) < min_version { + return SimpleConsensusValidationResult::new_with_error( + DataContractConfigUpdateError::new( + contract_id, + format!( + "config version {} is not supported, minimum version is {}", + new_config.version(), + min_version + ), + ) + .into(), + ); + } + + // Validate: sized_integer_types cannot change from true to false. + // V1→V0 (true→false) is DANGEROUS: documents serialized with sized types (version byte 1/2) + // would break when deserialized with I64 types. + // V0→V1 (false→true) is SAFE: version byte 0 docs use from_bytes_v0 which forces I64 + // regardless of current config. + if self.sized_integer_types() && !new_config.sized_integer_types() { + return SimpleConsensusValidationResult::new_with_error( + DataContractConfigUpdateError::new( + contract_id, + "contract can not disable sized integer types once enabled, as this would break deserialization of existing documents", + ) + .into(), + ); + } + + SimpleConsensusValidationResult::new() + } +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::data_contract::config::v0::DataContractConfigV0; + use crate::data_contract::config::v1::DataContractConfigV1; + + #[test] + fn test_v1_to_v0_rejected() { + let platform_version = PlatformVersion::latest(); + let contract_id = Identifier::new([1u8; 32]); + let config_v1 = DataContractConfig::V1(DataContractConfigV1::default()); + let config_v0 = DataContractConfig::V0(DataContractConfigV0::default()); + + // ConfigV1 has sized_integer_types=true, ConfigV0 has sized_integer_types=false + assert!(config_v1.sized_integer_types()); + assert!(!config_v0.sized_integer_types()); + + let result = config_v1.validate_update_v1(&config_v0, contract_id, platform_version); + assert!( + !result.is_valid(), + "V1→V0 config change should be rejected. Errors: {:?}", + result.errors + ); + } + + #[test] + fn test_v1_sized_true_to_v1_sized_false_rejected() { + let platform_version = PlatformVersion::latest(); + let contract_id = Identifier::new([1u8; 32]); + let config_v1_true = DataContractConfig::V1(DataContractConfigV1::default()); + let mut v1_false = DataContractConfigV1::default(); + v1_false.sized_integer_types = false; + let config_v1_false = DataContractConfig::V1(v1_false); + + assert!(config_v1_true.sized_integer_types()); + assert!(!config_v1_false.sized_integer_types()); + + let result = + config_v1_true.validate_update_v1(&config_v1_false, contract_id, platform_version); + assert!( + !result.is_valid(), + "V1(sized=true)→V1(sized=false) should be rejected. Errors: {:?}", + result.errors + ); + } + + #[test] + fn test_v0_to_v1_allowed() { + let platform_version = PlatformVersion::latest(); + let contract_id = Identifier::new([1u8; 32]); + let config_v0 = DataContractConfig::V0(DataContractConfigV0::default()); + let config_v1 = DataContractConfig::V1(DataContractConfigV1::default()); + + // V0→V1 (false→true) is safe because version byte 0 docs use from_bytes_v0 + let result = config_v0.validate_update_v1(&config_v1, contract_id, platform_version); + assert!( + result.is_valid(), + "V0→V1 config change should be allowed (safe direction). Errors: {:?}", + result.errors + ); + } + + #[test] + fn test_v0_to_v0_rejected_on_latest_version() { + let platform_version = PlatformVersion::latest(); + let contract_id = Identifier::new([1u8; 32]); + let config_v0 = DataContractConfig::V0(DataContractConfigV0::default()); + let config_v0_2 = DataContractConfig::V0(DataContractConfigV0::default()); + + // On latest platform version (v12+), V0 config is below min_version=1 + let result = config_v0.validate_update_v1(&config_v0_2, contract_id, platform_version); + assert!( + !result.is_valid(), + "V0→V0 should be rejected on latest platform version where min config version is 1. Errors: {:?}", + result.errors + ); + } + + #[test] + fn test_v1_to_v1_same_allowed() { + let platform_version = PlatformVersion::latest(); + let contract_id = Identifier::new([1u8; 32]); + let config_v1 = DataContractConfig::V1(DataContractConfigV1::default()); + let config_v1_2 = DataContractConfig::V1(DataContractConfigV1::default()); + + let result = config_v1.validate_update_v1(&config_v1_2, contract_id, platform_version); + assert!( + result.is_valid(), + "V1→V1 (same config) should be allowed. Errors: {:?}", + result.errors + ); + } + + #[test] + fn test_all_v0_checks_still_work() { + let platform_version = PlatformVersion::latest(); + let contract_id = Identifier::new([1u8; 32]); + let config_v1 = DataContractConfig::V1(DataContractConfigV1::default()); + + // Changing keeps_history should be rejected + let mut modified = DataContractConfigV1::default(); + modified.keeps_history = !modified.keeps_history; + let config_modified = DataContractConfig::V1(modified); + + let result = config_v1.validate_update_v1(&config_modified, contract_id, platform_version); + assert!( + !result.is_valid(), + "Changing keeps_history should be rejected by validate_update_v1" + ); + + // Changing readonly (to true) should be rejected + let mut modified2 = DataContractConfigV1::default(); + modified2.readonly = true; + let config_readonly = DataContractConfig::V1(modified2); + + let result2 = config_v1.validate_update_v1(&config_readonly, contract_id, platform_version); + assert!( + !result2.is_valid(), + "Changing readonly to true should be rejected by validate_update_v1" + ); + + // Changing can_be_deleted should be rejected + let mut modified3 = DataContractConfigV1::default(); + modified3.can_be_deleted = !modified3.can_be_deleted; + let config_can_be_deleted = DataContractConfig::V1(modified3); + + let result3 = + config_v1.validate_update_v1(&config_can_be_deleted, contract_id, platform_version); + assert!( + !result3.is_valid(), + "Changing can_be_deleted should be rejected by validate_update_v1" + ); + + // Changing documents_mutable_contract_default should be rejected + let mut modified4 = DataContractConfigV1::default(); + modified4.documents_mutable_contract_default = + !modified4.documents_mutable_contract_default; + let config_docs_mutable = DataContractConfig::V1(modified4); + + let result4 = + config_v1.validate_update_v1(&config_docs_mutable, contract_id, platform_version); + assert!( + !result4.is_valid(), + "Changing documents_mutable_contract_default should be rejected by validate_update_v1" + ); + } +} diff --git a/packages/rs-dpp/src/data_contract/methods/validate_update/v0/mod.rs b/packages/rs-dpp/src/data_contract/methods/validate_update/v0/mod.rs index 45aeef36e7b..9657db4afa3 100644 --- a/packages/rs-dpp/src/data_contract/methods/validate_update/v0/mod.rs +++ b/packages/rs-dpp/src/data_contract/methods/validate_update/v0/mod.rs @@ -368,12 +368,16 @@ mod tests { fn should_return_invalid_result_if_owner_id_is_not_the_same() { let platform_version = PlatformVersion::latest(); - let old_data_contract = - get_data_contract_fixture(None, IdentityNonce::default(), 1).data_contract_owned(); + let old_data_contract = get_data_contract_fixture( + None, + IdentityNonce::default(), + platform_version.protocol_version, + ) + .data_contract_owned(); let mut new_data_contract = old_data_contract.clone(); - new_data_contract.as_v0_mut().unwrap().owner_id = Identifier::random(); + new_data_contract.set_owner_id(Identifier::random()); let result = old_data_contract .validate_update(&new_data_contract, &BlockInfo::default(), platform_version) @@ -391,8 +395,12 @@ mod tests { fn should_return_invalid_result_if_contract_version_is_not_greater_for_one() { let platform_version = PlatformVersion::latest(); - let old_data_contract = - get_data_contract_fixture(None, IdentityNonce::default(), 1).data_contract_owned(); + let old_data_contract = get_data_contract_fixture( + None, + IdentityNonce::default(), + platform_version.protocol_version, + ) + .data_contract_owned(); let new_data_contract = old_data_contract.clone(); @@ -412,8 +420,12 @@ mod tests { fn should_return_invalid_result_if_config_was_updated() { let platform_version = PlatformVersion::latest(); - let old_data_contract = - get_data_contract_fixture(None, IdentityNonce::default(), 1).data_contract_owned(); + let old_data_contract = get_data_contract_fixture( + None, + IdentityNonce::default(), + platform_version.protocol_version, + ) + .data_contract_owned(); let mut new_data_contract = old_data_contract.clone(); @@ -436,8 +448,12 @@ mod tests { fn should_return_invalid_result_when_document_type_is_removed() { let platform_version = PlatformVersion::latest(); - let old_data_contract = - get_data_contract_fixture(None, IdentityNonce::default(), 1).data_contract_owned(); + let old_data_contract = get_data_contract_fixture( + None, + IdentityNonce::default(), + platform_version.protocol_version, + ) + .data_contract_owned(); let mut new_data_contract = old_data_contract.clone(); @@ -462,22 +478,26 @@ mod tests { fn should_return_invalid_result_when_document_type_has_incompatible_change() { let platform_version = PlatformVersion::latest(); - let old_data_contract = - get_data_contract_fixture(None, IdentityNonce::default(), 1).data_contract_owned(); + let old_data_contract = get_data_contract_fixture( + None, + IdentityNonce::default(), + platform_version.protocol_version, + ) + .data_contract_owned(); let mut new_data_contract = old_data_contract.clone(); new_data_contract.set_version(old_data_contract.version() + 1); - let DocumentTypeMutRef::V0(new_document_type) = new_data_contract + match new_data_contract .document_types_mut() .get_mut("niceDocument") .unwrap() .as_mut_ref() - else { - panic!("expected v0") - }; - new_document_type.documents_mutable = false; + { + DocumentTypeMutRef::V0(dt) => dt.documents_mutable = false, + DocumentTypeMutRef::V1(dt) => dt.documents_mutable = false, + } let result = old_data_contract .validate_update_v0(&new_data_contract, &BlockInfo::default(), platform_version) @@ -495,8 +515,12 @@ mod tests { fn should_return_invalid_result_when_defs_is_removed() { let platform_version = PlatformVersion::latest(); - let mut old_data_contract = - get_data_contract_fixture(None, IdentityNonce::default(), 1).data_contract_owned(); + let mut old_data_contract = get_data_contract_fixture( + None, + IdentityNonce::default(), + platform_version.protocol_version, + ) + .data_contract_owned(); // Remove document that uses $defs, so we can safely remove it for testing old_data_contract @@ -526,8 +550,12 @@ mod tests { fn should_return_invalid_result_when_updated_defs_is_incompatible() { let platform_version = PlatformVersion::latest(); - let old_data_contract = - get_data_contract_fixture(None, IdentityNonce::default(), 1).data_contract_owned(); + let old_data_contract = get_data_contract_fixture( + None, + IdentityNonce::default(), + platform_version.protocol_version, + ) + .data_contract_owned(); let mut new_data_contract = old_data_contract.clone(); @@ -566,8 +594,12 @@ mod tests { fn should_pass_when_all_changes_are_compatible() { let platform_version = PlatformVersion::latest(); - let old_data_contract = - get_data_contract_fixture(None, IdentityNonce::default(), 1).data_contract_owned(); + let old_data_contract = get_data_contract_fixture( + None, + IdentityNonce::default(), + platform_version.protocol_version, + ) + .data_contract_owned(); let mut new_data_contract = old_data_contract.clone(); diff --git a/packages/rs-dpp/src/tests/json_document.rs b/packages/rs-dpp/src/tests/json_document.rs index a76be4dd5a2..526aa093552 100644 --- a/packages/rs-dpp/src/tests/json_document.rs +++ b/packages/rs-dpp/src/tests/json_document.rs @@ -1,5 +1,7 @@ use crate::data_contract::accessors::v0::DataContractV0Setters; #[cfg(feature = "data-contract-json-conversion")] +use crate::data_contract::config::DataContractConfig; +#[cfg(feature = "data-contract-json-conversion")] use crate::data_contract::conversion::json::DataContractJsonConversionMethodsV0; #[cfg(any(feature = "state-transitions", feature = "factories"))] use crate::data_contract::created_data_contract::v0::CreatedDataContractV0; @@ -84,7 +86,12 @@ pub fn json_document_to_created_contract( full_validation: bool, platform_version: &PlatformVersion, ) -> Result { - let data_contract = json_document_to_contract(path, full_validation, platform_version)?; + let mut data_contract = json_document_to_contract(path, full_validation, platform_version)?; + + // JSON fixtures typically lack a config field, so they deserialize with V0 config default. + // Set config to the platform version default to match what the factory would produce, + // ensuring the contract passes config min_version validation during state transition processing. + data_contract.set_config(DataContractConfig::default_for_version(platform_version)?); Ok(CreatedDataContractV0 { data_contract, diff --git a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/data_contract_create/basic_structure/mod.rs b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/data_contract_create/basic_structure/mod.rs index 9a1925de7fc..008be12cc67 100644 --- a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/data_contract_create/basic_structure/mod.rs +++ b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/data_contract_create/basic_structure/mod.rs @@ -1 +1,2 @@ pub(crate) mod v0; +pub(crate) mod v1; diff --git a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/data_contract_create/basic_structure/v1/mod.rs b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/data_contract_create/basic_structure/v1/mod.rs new file mode 100644 index 00000000000..2babde9ba25 --- /dev/null +++ b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/data_contract_create/basic_structure/v1/mod.rs @@ -0,0 +1,52 @@ +use crate::error::Error; +use dpp::consensus::state::data_contract::data_contract_config_update_error::DataContractConfigUpdateError; +use dpp::dashcore::Network; +use dpp::state_transition::data_contract_create_transition::accessors::DataContractCreateTransitionAccessorsV0; +use dpp::state_transition::data_contract_create_transition::DataContractCreateTransition; +use dpp::validation::SimpleConsensusValidationResult; +use dpp::version::{FeatureVersion, PlatformVersion}; + +use super::v0::DataContractCreateStateTransitionBasicStructureValidationV0; + +pub(in crate::execution::validation::state_transition::state_transitions::data_contract_create) trait DataContractCreateStateTransitionBasicStructureValidationV1 +{ + fn validate_basic_structure_v1( + &self, + network_type: Network, + platform_version: &PlatformVersion, + ) -> Result; +} + +impl DataContractCreateStateTransitionBasicStructureValidationV1 for DataContractCreateTransition { + fn validate_basic_structure_v1( + &self, + network_type: Network, + platform_version: &PlatformVersion, + ) -> Result { + // First run all v0 validations + let v0_result = self.validate_basic_structure_v0(network_type, platform_version)?; + if !v0_result.is_valid() { + return Ok(v0_result); + } + + // Validate config version meets minimum requirement for the current protocol version. + // Since protocol version 12, V0 config is no longer accepted because it lacks + // sized_integer_types support. + let config_min_version = platform_version.dpp.contract_versions.config.min_version; + if (self.data_contract().config().version() as FeatureVersion) < config_min_version { + return Ok(SimpleConsensusValidationResult::new_with_error( + DataContractConfigUpdateError::new( + self.data_contract().id(), + format!( + "config version {} is not supported, minimum version is {}", + self.data_contract().config().version(), + config_min_version + ), + ) + .into(), + )); + } + + Ok(SimpleConsensusValidationResult::new()) + } +} diff --git a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/data_contract_create/mod.rs b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/data_contract_create/mod.rs index ec152365b82..67e1c6838bb 100644 --- a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/data_contract_create/mod.rs +++ b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/data_contract_create/mod.rs @@ -5,6 +5,7 @@ mod state; use advanced_structure::v1::DataContractCreatedStateTransitionAdvancedStructureValidationV1; use basic_structure::v0::DataContractCreateStateTransitionBasicStructureValidationV0; +use basic_structure::v1::DataContractCreateStateTransitionBasicStructureValidationV1; use dpp::address_funds::PlatformAddress; use dpp::block::block_info::BlockInfo; use dpp::dashcore::Network; @@ -96,14 +97,15 @@ impl StateTransitionBasicStructureValidationV0 for DataContractCreateTransition .basic_structure { Some(0) => self.validate_basic_structure_v0(network_type, platform_version), + Some(1) => self.validate_basic_structure_v1(network_type, platform_version), Some(version) => Err(Error::Execution(ExecutionError::UnknownVersionMismatch { method: "data contract create transition: validate_basic_structure".to_string(), - known_versions: vec![0], + known_versions: vec![0, 1], received: version, })), None => Err(Error::Execution(ExecutionError::VersionNotActive { method: "data contract create transition: validate_basic_structure".to_string(), - known_versions: vec![0], + known_versions: vec![0, 1], })), } } @@ -190,12 +192,13 @@ mod tests { use dpp::consensus::basic::BasicError; use dpp::consensus::ConsensusError; use dpp::dash_to_credits; - use dpp::data_contract::accessors::v0::DataContractV0Getters; + use dpp::data_contract::accessors::v0::{DataContractV0Getters, DataContractV0Setters}; use dpp::data_contract::accessors::v1::DataContractV1Getters; use dpp::data_contract::associated_token::token_configuration::accessors::v0::TokenConfigurationV0Setters; use dpp::data_contract::change_control_rules::authorized_action_takers::AuthorizedActionTakers; use dpp::data_contract::change_control_rules::v0::ChangeControlRulesV0; use dpp::data_contract::change_control_rules::ChangeControlRules; + use dpp::data_contract::config::DataContractConfig; use dpp::data_contract::document_type::accessors::{ DocumentTypeV0MutGetters, DocumentTypeV1Setters, }; @@ -231,7 +234,7 @@ mod tests { let (identity, signer, key) = setup_identity(&mut platform, 958, dash_to_credits!(2.0)); - let data_contract = json_document_to_contract_with_ids( + let mut data_contract = json_document_to_contract_with_ids( "tests/supporting_files/contract/dpns/dpns-contract-contested-unique-index.json", None, None, @@ -240,6 +243,10 @@ mod tests { ) .expect("expected to get json based contract"); + // Upgrade config to V1 (required since protocol version 12) + data_contract + .set_config(DataContractConfig::default_for_version(platform_version).unwrap()); + let data_contract_create_transition = DataContractCreateTransition::new_from_data_contract( data_contract, 1, @@ -295,7 +302,7 @@ mod tests { let (identity, signer, key) = setup_identity(&mut platform, 958, dash_to_credits!(0.1)); - let data_contract = json_document_to_contract_with_ids( + let mut data_contract = json_document_to_contract_with_ids( "tests/supporting_files/contract/dpns/dpns-contract-contested-unique-index.json", None, None, @@ -304,6 +311,10 @@ mod tests { ) .expect("expected to get json based contract"); + // Upgrade config to V1 (required since protocol version 12) + data_contract + .set_config(DataContractConfig::default_for_version(platform_version).unwrap()); + let data_contract_create_transition = DataContractCreateTransition::new_from_data_contract( data_contract, 1, @@ -358,7 +369,7 @@ mod tests { let (identity, signer, key) = setup_identity(&mut platform, 958, dash_to_credits!(2.0)); - let data_contract = json_document_to_contract_with_ids( + let mut data_contract = json_document_to_contract_with_ids( "tests/supporting_files/contract/dpns/dpns-contract-contested-unique-index-with-contract-id.json", None, None, @@ -367,6 +378,10 @@ mod tests { ) .expect("expected to get json based contract"); + // Upgrade config to V1 (required since protocol version 12) + data_contract + .set_config(DataContractConfig::default_for_version(platform_version).unwrap()); + let data_contract_create_transition = DataContractCreateTransition::new_from_data_contract( data_contract, 1, @@ -421,7 +436,7 @@ mod tests { let (identity, signer, key) = setup_identity(&mut platform, 958, dash_to_credits!(2.0)); - let data_contract = json_document_to_contract_with_ids( + let mut data_contract = json_document_to_contract_with_ids( "tests/supporting_files/contract/dpns/dpns-contract-contested-unique-index-and-other-unique-index.json", None, None, @@ -430,6 +445,10 @@ mod tests { ) .expect("expected to get json based contract"); + // Upgrade config to V1 (required since protocol version 12) + data_contract + .set_config(DataContractConfig::default_for_version(platform_version).unwrap()); + let data_contract_create_transition = DataContractCreateTransition::new_from_data_contract( data_contract, 1, diff --git a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/data_contract_update/basic_structure/mod.rs b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/data_contract_update/basic_structure/mod.rs index 9a1925de7fc..008be12cc67 100644 --- a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/data_contract_update/basic_structure/mod.rs +++ b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/data_contract_update/basic_structure/mod.rs @@ -1 +1,2 @@ pub(crate) mod v0; +pub(crate) mod v1; diff --git a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/data_contract_update/basic_structure/v1/mod.rs b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/data_contract_update/basic_structure/v1/mod.rs new file mode 100644 index 00000000000..4d416a5ebf0 --- /dev/null +++ b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/data_contract_update/basic_structure/v1/mod.rs @@ -0,0 +1,52 @@ +use crate::error::Error; +use dpp::consensus::state::data_contract::data_contract_config_update_error::DataContractConfigUpdateError; +use dpp::dashcore::Network; +use dpp::state_transition::data_contract_update_transition::accessors::DataContractUpdateTransitionAccessorsV0; +use dpp::state_transition::data_contract_update_transition::DataContractUpdateTransition; +use dpp::validation::SimpleConsensusValidationResult; +use dpp::version::{FeatureVersion, PlatformVersion}; + +use super::v0::DataContractUpdateStateTransitionBasicStructureValidationV0; + +pub(in crate::execution::validation::state_transition::state_transitions::data_contract_update) trait DataContractUpdateStateTransitionBasicStructureValidationV1 +{ + fn validate_basic_structure_v1( + &self, + network_type: Network, + platform_version: &PlatformVersion, + ) -> Result; +} + +impl DataContractUpdateStateTransitionBasicStructureValidationV1 for DataContractUpdateTransition { + fn validate_basic_structure_v1( + &self, + network_type: Network, + platform_version: &PlatformVersion, + ) -> Result { + // First run all v0 validations + let v0_result = self.validate_basic_structure_v0(network_type, platform_version)?; + if !v0_result.is_valid() { + return Ok(v0_result); + } + + // Validate config version meets minimum requirement for the current protocol version. + // Since protocol version 12, V0 config is no longer accepted because it lacks + // sized_integer_types support. + let config_min_version = platform_version.dpp.contract_versions.config.min_version; + if (self.data_contract().config().version() as FeatureVersion) < config_min_version { + return Ok(SimpleConsensusValidationResult::new_with_error( + DataContractConfigUpdateError::new( + self.data_contract().id(), + format!( + "config version {} is not supported, minimum version is {}", + self.data_contract().config().version(), + config_min_version + ), + ) + .into(), + )); + } + + Ok(SimpleConsensusValidationResult::new()) + } +} diff --git a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/data_contract_update/mod.rs b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/data_contract_update/mod.rs index 5de155b0617..4c67a5c1858 100644 --- a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/data_contract_update/mod.rs +++ b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/data_contract_update/mod.rs @@ -3,6 +3,7 @@ mod identity_contract_nonce; mod state; use basic_structure::v0::DataContractUpdateStateTransitionBasicStructureValidationV0; +use basic_structure::v1::DataContractUpdateStateTransitionBasicStructureValidationV1; use dpp::address_funds::PlatformAddress; use dpp::block::block_info::BlockInfo; use dpp::dashcore::Network; @@ -44,9 +45,10 @@ impl StateTransitionBasicStructureValidationV0 for DataContractUpdateTransition .basic_structure { Some(0) => self.validate_basic_structure_v0(network_type, platform_version), + Some(1) => self.validate_basic_structure_v1(network_type, platform_version), Some(version) => Err(Error::Execution(ExecutionError::UnknownVersionMismatch { method: "data contract update transition: validate_basic_structure".to_string(), - known_versions: vec![0], + known_versions: vec![0, 1], received: version, })), None => Err(Error::Execution(ExecutionError::VersionNotActive { @@ -104,6 +106,7 @@ mod tests { use dpp::consensus::ConsensusError; use dpp::dash_to_credits; use dpp::data_contract::accessors::v0::{DataContractV0Getters, DataContractV0Setters}; + use dpp::data_contract::config::DataContractConfig; use rand::prelude::StdRng; use rand::SeedableRng; use std::collections::BTreeMap; @@ -632,6 +635,8 @@ mod tests { .expect("expected to get data contract"); contract.set_owner_id(identity.id()); + // Upgrade config to V1 (required since protocol version 12) + contract.set_config(DataContractConfig::default_for_version(platform_version).unwrap()); platform .drive @@ -653,6 +658,9 @@ mod tests { .expect("expected to get data contract"); contract_not_restricted_to_owner.set_owner_id(identity.id()); + // Upgrade config to V1 (required since protocol version 12) + contract_not_restricted_to_owner + .set_config(DataContractConfig::default_for_version(platform_version).unwrap()); contract_not_restricted_to_owner.set_version(2); diff --git a/packages/rs-platform-version/src/version/dpp_versions/dpp_contract_versions/v3.rs b/packages/rs-platform-version/src/version/dpp_versions/dpp_contract_versions/v3.rs index 1f20fd2793a..af22004dc52 100644 --- a/packages/rs-platform-version/src/version/dpp_versions/dpp_contract_versions/v3.rs +++ b/packages/rs-platform-version/src/version/dpp_versions/dpp_contract_versions/v3.rs @@ -16,7 +16,8 @@ pub const CONTRACT_VERSIONS_V3: DPPContractVersions = DPPContractVersions { contract_structure_version: 1, created_data_contract_structure: 0, config: FeatureVersionBounds { - min_version: 0, + min_version: 1, // changed: V0 config no longer accepted for registration or update. + // V0 config lacks sized_integer_types; require V1 for all new and updated contracts. max_version: 1, default_current_version: 1, }, diff --git a/packages/rs-platform-version/src/version/dpp_versions/dpp_validation_versions/mod.rs b/packages/rs-platform-version/src/version/dpp_versions/dpp_validation_versions/mod.rs index ebd9adc8180..d77c94722e3 100644 --- a/packages/rs-platform-version/src/version/dpp_versions/dpp_validation_versions/mod.rs +++ b/packages/rs-platform-version/src/version/dpp_versions/dpp_validation_versions/mod.rs @@ -2,6 +2,7 @@ use versioned_feature_core::FeatureVersion; pub mod v1; pub mod v2; +pub mod v3; #[derive(Clone, Debug, Default)] pub struct DPPValidationVersions { diff --git a/packages/rs-platform-version/src/version/dpp_versions/dpp_validation_versions/v3.rs b/packages/rs-platform-version/src/version/dpp_versions/dpp_validation_versions/v3.rs new file mode 100644 index 00000000000..e5621fd5851 --- /dev/null +++ b/packages/rs-platform-version/src/version/dpp_versions/dpp_validation_versions/v3.rs @@ -0,0 +1,35 @@ +use crate::version::dpp_versions::dpp_validation_versions::{ + DPPValidationVersions, DataContractValidationVersions, DocumentTypeValidationVersions, + JsonSchemaValidatorVersions, VotingValidationVersions, +}; + +pub const DPP_VALIDATION_VERSIONS_V3: DPPValidationVersions = DPPValidationVersions { + json_schema_validator: JsonSchemaValidatorVersions { + new: 0, + validate: 0, + compile: 0, + compile_and_validate: 0, + }, + data_contract: DataContractValidationVersions { + validate: 0, + // prevent sized_integer_types config downgrade on contract update + validate_config_update: 1, + validate_token_config_update: 0, + validate_index_definitions: 0, + validate_index_naming_duplicates: 0, + validate_not_defined_properties: 0, + validate_property_definition: 0, + validate_token_config_groups_exist: 0, + validate_localizations: 0, + }, + document_type: DocumentTypeValidationVersions { + validate_update: 0, + contested_index_limit: 1, + unique_index_limit: 10, + }, + voting: VotingValidationVersions { + allow_other_contenders_time_mainnet_ms: 604_800_000, // 1 week in ms + allow_other_contenders_time_testing_ms: 2_700_000, //45 minutes + votes_allowed_per_masternode: 5, + }, +}; diff --git a/packages/rs-platform-version/src/version/drive_abci_versions/drive_abci_validation_versions/mod.rs b/packages/rs-platform-version/src/version/drive_abci_versions/drive_abci_validation_versions/mod.rs index 23163606246..fc8364f8201 100644 --- a/packages/rs-platform-version/src/version/drive_abci_versions/drive_abci_validation_versions/mod.rs +++ b/packages/rs-platform-version/src/version/drive_abci_versions/drive_abci_validation_versions/mod.rs @@ -5,6 +5,7 @@ pub mod v4; pub mod v5; pub mod v6; pub mod v7; +pub mod v8; use versioned_feature_core::{FeatureVersion, OptionalFeatureVersion}; diff --git a/packages/rs-platform-version/src/version/drive_abci_versions/drive_abci_validation_versions/v8.rs b/packages/rs-platform-version/src/version/drive_abci_versions/drive_abci_validation_versions/v8.rs new file mode 100644 index 00000000000..421541526c8 --- /dev/null +++ b/packages/rs-platform-version/src/version/drive_abci_versions/drive_abci_validation_versions/v8.rs @@ -0,0 +1,225 @@ +use crate::version::drive_abci_versions::drive_abci_validation_versions::{ + DriveAbciAssetLockValidationVersions, DriveAbciDocumentsStateTransitionValidationVersions, + DriveAbciStateTransitionCommonValidationVersions, DriveAbciStateTransitionValidationVersion, + DriveAbciStateTransitionValidationVersions, DriveAbciValidationConstants, + DriveAbciValidationDataTriggerAndBindingVersions, DriveAbciValidationDataTriggerVersions, + DriveAbciValidationVersions, PenaltyAmounts, +}; + +// Bump basic_structure to v1 for contract create and update state transitions. +// v1 adds config min_version enforcement: since protocol version 12, V0 config is no longer +// accepted because it lacks sized_integer_types support. +pub const DRIVE_ABCI_VALIDATION_VERSIONS_V8: DriveAbciValidationVersions = + DriveAbciValidationVersions { + state_transitions: DriveAbciStateTransitionValidationVersions { + common_validation_methods: DriveAbciStateTransitionCommonValidationVersions { + asset_locks: DriveAbciAssetLockValidationVersions { + fetch_asset_lock_transaction_output_sync: 0, + verify_asset_lock_is_not_spent_and_has_enough_balance: 0, + }, + validate_identity_public_key_contract_bounds: 0, + validate_identity_public_key_ids_dont_exist_in_state: 0, + validate_identity_public_key_ids_exist_in_state: 0, + validate_state_transition_identity_signed: 0, + validate_unique_identity_public_key_hashes_in_state: 1, + validate_master_key_uniqueness: 0, + validate_non_masternode_identity_exists: 0, + validate_identity_exists: 0, + }, + max_asset_lock_usage_attempts: 16, + identity_create_state_transition: DriveAbciStateTransitionValidationVersion { + basic_structure: Some(0), + advanced_structure: Some(0), + identity_signatures: Some(0), + nonce: None, + state: 0, + transform_into_action: 0, + }, + identity_update_state_transition: DriveAbciStateTransitionValidationVersion { + basic_structure: Some(0), + advanced_structure: Some(0), + identity_signatures: Some(0), + nonce: Some(0), + state: 0, + transform_into_action: 0, + }, + identity_top_up_state_transition: DriveAbciStateTransitionValidationVersion { + basic_structure: Some(0), + advanced_structure: None, + identity_signatures: None, + nonce: None, + state: 0, + transform_into_action: 0, + }, + identity_credit_withdrawal_state_transition: + DriveAbciStateTransitionValidationVersion { + // v1 adds config min_version enforcement: since protocol version 12, V0 config is no longer + // accepted because it lacks sized_integer_types support. + basic_structure: Some(1), + advanced_structure: None, + identity_signatures: None, + nonce: Some(0), + state: 0, + transform_into_action: 0, + }, + identity_credit_withdrawal_state_transition_purpose_matches_requirements: 0, + identity_credit_transfer_state_transition: DriveAbciStateTransitionValidationVersion { + basic_structure: Some(0), + advanced_structure: None, + identity_signatures: None, + nonce: Some(0), + state: 0, + transform_into_action: 0, + }, + identity_credit_transfer_to_addresses_state_transition: + DriveAbciStateTransitionValidationVersion { + basic_structure: Some(0), + advanced_structure: None, + identity_signatures: None, + nonce: Some(0), + state: 0, + transform_into_action: 0, + }, + masternode_vote_state_transition: DriveAbciStateTransitionValidationVersion { + basic_structure: None, + advanced_structure: Some(0), + identity_signatures: None, + nonce: Some(1), + state: 0, + transform_into_action: 0, + }, + masternode_vote_state_transition_balance_pre_check: 0, + contract_create_state_transition: DriveAbciStateTransitionValidationVersion { + basic_structure: Some(1), + advanced_structure: Some(1), + identity_signatures: None, + nonce: Some(0), + state: 0, + transform_into_action: 0, + }, + contract_update_state_transition: DriveAbciStateTransitionValidationVersion { + basic_structure: Some(1), + advanced_structure: None, + identity_signatures: None, + nonce: Some(0), + state: 0, + transform_into_action: 0, + }, + batch_state_transition: DriveAbciDocumentsStateTransitionValidationVersions { + basic_structure: 0, + advanced_structure: 0, + state: 0, + revision: 0, + transform_into_action: 0, + data_triggers: DriveAbciValidationDataTriggerAndBindingVersions { + bindings: 0, + triggers: DriveAbciValidationDataTriggerVersions { + create_contact_request_data_trigger: 0, + create_domain_data_trigger: 0, + create_identity_data_trigger: 0, + create_feature_flag_data_trigger: 0, + create_masternode_reward_shares_data_trigger: 0, + delete_withdrawal_data_trigger: 0, + reject_data_trigger: 0, + }, + }, + is_allowed: 0, + document_create_transition_structure_validation: 0, + document_delete_transition_structure_validation: 0, + document_replace_transition_structure_validation: 0, + document_transfer_transition_structure_validation: 0, + document_purchase_transition_structure_validation: 0, + document_update_price_transition_structure_validation: 0, + document_base_transition_state_validation: 0, + document_create_transition_state_validation: 1, + document_delete_transition_state_validation: 0, + document_replace_transition_state_validation: 0, + document_transfer_transition_state_validation: 0, + document_purchase_transition_state_validation: 0, + document_update_price_transition_state_validation: 0, + token_mint_transition_structure_validation: 0, + token_burn_transition_structure_validation: 0, + token_transfer_transition_structure_validation: 0, + token_mint_transition_state_validation: 0, + token_burn_transition_state_validation: 0, + token_transfer_transition_state_validation: 0, + token_base_transition_structure_validation: 0, + token_base_transition_state_validation: 0, + token_freeze_transition_structure_validation: 0, + token_unfreeze_transition_structure_validation: 0, + token_freeze_transition_state_validation: 0, + token_unfreeze_transition_state_validation: 0, + token_destroy_frozen_funds_transition_structure_validation: 0, + token_destroy_frozen_funds_transition_state_validation: 0, + token_emergency_action_transition_structure_validation: 0, + token_emergency_action_transition_state_validation: 0, + token_config_update_transition_structure_validation: 0, + token_config_update_transition_state_validation: 0, + token_base_transition_group_action_validation: 0, + token_claim_transition_structure_validation: 0, + token_claim_transition_state_validation: 0, + token_direct_purchase_transition_structure_validation: 0, + token_direct_purchase_transition_state_validation: 0, + token_set_price_for_direct_purchase_transition_structure_validation: 0, + token_set_price_for_direct_purchase_transition_state_validation: 0, + }, + identity_create_from_addresses_state_transition: + DriveAbciStateTransitionValidationVersion { + basic_structure: Some(0), + advanced_structure: Some(0), + identity_signatures: Some(0), + nonce: Some(0), + state: 0, + transform_into_action: 0, + }, + identity_top_up_from_addresses_state_transition: + DriveAbciStateTransitionValidationVersion { + basic_structure: Some(0), + advanced_structure: None, + identity_signatures: None, + nonce: Some(0), + state: 0, + transform_into_action: 0, + }, + address_credit_withdrawal: DriveAbciStateTransitionValidationVersion { + basic_structure: Some(0), + advanced_structure: None, + identity_signatures: None, + nonce: Some(0), + state: 0, + transform_into_action: 0, + }, + address_funds_from_asset_lock: DriveAbciStateTransitionValidationVersion { + basic_structure: Some(0), + advanced_structure: Some(0), + identity_signatures: None, + nonce: Some(0), + state: 0, + transform_into_action: 0, + }, + address_funds_transfer: DriveAbciStateTransitionValidationVersion { + basic_structure: Some(0), + advanced_structure: None, + identity_signatures: None, + nonce: Some(0), + state: 0, + transform_into_action: 0, + }, + }, + has_nonce_validation: 1, + has_address_witness_validation: 0, + validate_address_witnesses: 0, + process_state_transition: 0, + state_transition_to_execution_event_for_check_tx: 0, + penalties: PenaltyAmounts { + identity_id_not_correct: 50000000, + unique_key_already_present: 10000000, + validation_of_added_keys_structure_failure: 10000000, + validation_of_added_keys_proof_of_possession_failure: 50000000, + address_funds_insufficient_balance: 10000000, + }, + event_constants: DriveAbciValidationConstants { + maximum_vote_polls_to_process: 2, + maximum_contenders_to_consider: 100, + }, + }; diff --git a/packages/rs-platform-version/src/version/v12.rs b/packages/rs-platform-version/src/version/v12.rs index 486f4be1fb5..eacb417eca5 100644 --- a/packages/rs-platform-version/src/version/v12.rs +++ b/packages/rs-platform-version/src/version/v12.rs @@ -11,14 +11,14 @@ use crate::version::dpp_versions::dpp_state_transition_method_versions::v1::STAT use crate::version::dpp_versions::dpp_state_transition_serialization_versions::v2::STATE_TRANSITION_SERIALIZATION_VERSIONS_V2; use crate::version::dpp_versions::dpp_state_transition_versions::v3::STATE_TRANSITION_VERSIONS_V3; use crate::version::dpp_versions::dpp_token_versions::v1::TOKEN_VERSIONS_V1; -use crate::version::dpp_versions::dpp_validation_versions::v2::DPP_VALIDATION_VERSIONS_V2; +use crate::version::dpp_versions::dpp_validation_versions::v3::DPP_VALIDATION_VERSIONS_V3; use crate::version::dpp_versions::dpp_voting_versions::v2::VOTING_VERSION_V2; use crate::version::dpp_versions::DPPVersion; use crate::version::drive_abci_versions::drive_abci_checkpoint_parameters::v1::DRIVE_ABCI_CHECKPOINT_PARAMETERS_V1; use crate::version::drive_abci_versions::drive_abci_method_versions::v7::DRIVE_ABCI_METHOD_VERSIONS_V7; use crate::version::drive_abci_versions::drive_abci_query_versions::v1::DRIVE_ABCI_QUERY_VERSIONS_V1; use crate::version::drive_abci_versions::drive_abci_structure_versions::v1::DRIVE_ABCI_STRUCTURE_VERSIONS_V1; -use crate::version::drive_abci_versions::drive_abci_validation_versions::v7::DRIVE_ABCI_VALIDATION_VERSIONS_V7; +use crate::version::drive_abci_versions::drive_abci_validation_versions::v8::DRIVE_ABCI_VALIDATION_VERSIONS_V8; use crate::version::drive_abci_versions::drive_abci_withdrawal_constants::v2::DRIVE_ABCI_WITHDRAWAL_CONSTANTS_V2; use crate::version::drive_abci_versions::DriveAbciVersion; use crate::version::drive_versions::v6::DRIVE_VERSION_V6; @@ -30,21 +30,23 @@ use crate::version::ProtocolVersion; pub const PROTOCOL_VERSION_12: ProtocolVersion = 12; -/// This version was for Platform release 3.1.0 +/// This version is for Platform release 3.1.0 pub const PLATFORM_V12: PlatformVersion = PlatformVersion { protocol_version: PROTOCOL_VERSION_12, drive: DRIVE_VERSION_V6, drive_abci: DriveAbciVersion { structs: DRIVE_ABCI_STRUCTURE_VERSIONS_V1, methods: DRIVE_ABCI_METHOD_VERSIONS_V7, - validation_and_processing: DRIVE_ABCI_VALIDATION_VERSIONS_V7, + // enforce minimum config version check for contract create/update transitions + validation_and_processing: DRIVE_ABCI_VALIDATION_VERSIONS_V8, withdrawal_constants: DRIVE_ABCI_WITHDRAWAL_CONSTANTS_V2, query: DRIVE_ABCI_QUERY_VERSIONS_V1, checkpoints: DRIVE_ABCI_CHECKPOINT_PARAMETERS_V1, }, dpp: DPPVersion { costs: DPP_COSTS_VERSIONS_V1, - validation: DPP_VALIDATION_VERSIONS_V2, + // prevent sized_integer_types config downgrade on contract update + validation: DPP_VALIDATION_VERSIONS_V3, state_transition_serialization_versions: STATE_TRANSITION_SERIALIZATION_VERSIONS_V2, state_transition_conversion_versions: STATE_TRANSITION_CONVERSION_VERSIONS_V2, state_transition_method_versions: STATE_TRANSITION_METHOD_VERSIONS_V1, diff --git a/packages/wasm-dpp/src/data_contract/data_contract.rs b/packages/wasm-dpp/src/data_contract/data_contract.rs index a78eab156a1..682a050869a 100644 --- a/packages/wasm-dpp/src/data_contract/data_contract.rs +++ b/packages/wasm-dpp/src/data_contract/data_contract.rs @@ -358,7 +358,7 @@ impl DataContractWasm { pub fn set_config(&mut self, config: JsValue) -> Result<(), JsValue> { let value = config.with_serde_to_platform_value()?; - let platform_version = &PlatformVersion::first(); + let platform_version = PlatformVersion::latest(); let data_contract_config = DataContractConfig::from_value(value, platform_version).with_js_error()?; diff --git a/yarn.lock b/yarn.lock index 3f148ada2a6..1206cab979b 100644 --- a/yarn.lock +++ b/yarn.lock @@ -6066,9 +6066,9 @@ __metadata: linkType: hard "caniuse-lite@npm:^1.0.30001759": - version: 1.0.30001769 - resolution: "caniuse-lite@npm:1.0.30001769" - checksum: 10/4b7d087832d4330a8b1fa02cd9455bdb068ea67f1735f2aa6324d5b64b24f5079cf6349b13d209f268ffa59644b9f4f784266b780bafd877ceb83c9797ca80ba + version: 1.0.30001770 + resolution: "caniuse-lite@npm:1.0.30001770" + checksum: 10/a85fb0895881d31f0b7ae246725a8b67ab8590601a08027439be1d53418352b58896418145b4da2eaae7130d59877b487eeef9e4434fa1069225b9e50d00f79b languageName: node linkType: hard @@ -7273,14 +7273,14 @@ __metadata: pretty-bytes: "npm:^5.3.0" pretty-ms: "npm:^7.0.0" public-ip: "npm:^6.0.1" - qs: "npm:^6.14.1" + qs: "npm:^6.14.2" rxjs: "npm:^6.6.7" semver: "npm:^7.5.3" sinon: "npm:^17.0.1" sinon-chai: "npm:^3.7.0" systeminformation: "npm:^5.27.14" table: "npm:^6.8.1" - tar: "npm:7.5.7" + tar: "npm:7.5.9" wrap-ansi: "npm:^7.0.0" bin: dashmate: ./bin/run.js @@ -14755,11 +14755,11 @@ __metadata: linkType: hard "qs@npm:^6.14.1": - version: 6.14.1 - resolution: "qs@npm:6.14.1" + version: 6.15.0 + resolution: "qs@npm:6.15.0" dependencies: side-channel: "npm:^1.1.0" - checksum: 10/34b5ab00a910df432d55180ef39c1d1375e550f098b5ec153b41787f1a6a6d7e5f9495593c3b112b77dbc6709d0ae18e55b82847a4c2bbbb0de1e8ccbb1794c5 + checksum: 10/a3458f2f389285c3512e0ebc55522ee370ac7cb720ba9f0eff3e30fb2bb07631caf556c08e2a3d4481a371ac14faa9ceb7442a0610c5a7e55b23a5bdee7b701c languageName: node linkType: hard @@ -16879,16 +16879,16 @@ __metadata: languageName: node linkType: hard -"tar@npm:7.5.7": - version: 7.5.7 - resolution: "tar@npm:7.5.7" +"tar@npm:7.5.9": + version: 7.5.9 + resolution: "tar@npm:7.5.9" dependencies: "@isaacs/fs-minipass": "npm:^4.0.0" chownr: "npm:^3.0.0" minipass: "npm:^7.1.2" minizlib: "npm:^3.1.0" yallist: "npm:^5.0.0" - checksum: 10/0d6938dd32fe5c0f17c8098d92bd9889ee0ed9d11f12381b8146b6e8c87bb5aa49feec7abc42463f0597503d8e89e4c4c0b42bff1a5a38444e918b4878b7fd21 + checksum: 10/1213cdde9c22d6acf8809ba5d2a025212ce3517bc99c4a4c6981b7dc0489bf3b164db9c826c9517680889194c9ba57448c8ff0da35eca9a60bb7689bf0b3897d languageName: node linkType: hard @@ -18222,9 +18222,9 @@ __metadata: linkType: hard "webpack-sources@npm:^3.3.3": - version: 3.3.3 - resolution: "webpack-sources@npm:3.3.3" - checksum: 10/ec5d72607e8068467370abccbfff855c596c098baedbe9d198a557ccf198e8546a322836a6f74241492576adba06100286592993a62b63196832cdb53c8bae91 + version: 3.3.4 + resolution: "webpack-sources@npm:3.3.4" + checksum: 10/714427b235b04c2d7cf229f204b9e65145ea3643da3c7b139ebfa8a51056238d1e3a2a47c3cc3fc8eab71ed4300f66405cdc7cff29cd2f7f6b71086252f81cf1 languageName: node linkType: hard