diff --git a/.github/actions/rust/action.yaml b/.github/actions/rust/action.yaml index a6aa86446e0..4965f7721a9 100644 --- a/.github/actions/rust/action.yaml +++ b/.github/actions/rust/action.yaml @@ -5,7 +5,7 @@ inputs: toolchain: description: Rust toolchain to use, stable / nightly / beta, or exact version # The same as in /README.md - default: "stable" + default: "1.76" target: description: Target Rust platform required: false diff --git a/.github/workflows/tests-rs-package.yml b/.github/workflows/tests-rs-package.yml index 77e28b2232f..2cf0b636d12 100644 --- a/.github/workflows/tests-rs-package.yml +++ b/.github/workflows/tests-rs-package.yml @@ -73,7 +73,7 @@ jobs: cache: false - name: Check formatting - run: exit `cargo fmt --check --package=${{ inputs.package }} | wc -l` + run: cargo fmt --check --package=${{ inputs.package }} unused_deps: name: Unused dependencies diff --git a/.pnp.cjs b/.pnp.cjs index e1544666999..57d12a7b7d4 100755 --- a/.pnp.cjs +++ b/.pnp.cjs @@ -2621,7 +2621,7 @@ const RAW_RUNTIME_STATE = ["sinon", "npm:17.0.1"],\ ["sinon-chai", "virtual:e2d057e7cc143d3cb9bec864f4a2d862441b5a09f81f8e6c46e7a098cbc89e4d07017cc6e2e2142d5704bb55da853cbec2d025ebc0b30e8696c31380c00f2c7d#npm:3.7.0"],\ ["swagger-jsdoc", "npm:3.7.0"],\ - ["ws", "virtual:7469c013e9c5baa67d67122340123f2260ba4f66d6748855fb7f2ab67ea3fe52b2c8821a105003266d54faf99a9564056fb1b532d9ae8b6985087ab5f8394bf0#npm:7.5.5"]\ + ["ws", "virtual:b375dcefccef90d9158d5f197a75395cffedb61772e66f2efcf31c6c8e30c82a6423e0d52b091b15b4fa72cda43a09256ed00b6ce89b9cfb14074f087b9c8496#npm:8.17.1"]\ ],\ "linkType": "SOFT"\ }]\ @@ -2655,7 +2655,7 @@ const RAW_RUNTIME_STATE = ["eslint-plugin-jsdoc", "virtual:8f25fc90e0fb5fd89843707863857591fa8c52f9f33eadced4bf404b1871d91959f7bb86948ae0e1b53ee94d491ef8fde9c0b58b39c9490c0d0fa6c931945f97#npm:46.9.0"],\ ["events", "npm:3.3.0"],\ ["google-protobuf", "npm:3.19.1"],\ - ["karma", "npm:6.4.1"],\ + ["karma", "npm:6.4.3"],\ ["karma-chai", "virtual:e2d057e7cc143d3cb9bec864f4a2d862441b5a09f81f8e6c46e7a098cbc89e4d07017cc6e2e2142d5704bb55da853cbec2d025ebc0b30e8696c31380c00f2c7d#npm:0.1.0"],\ ["karma-chrome-launcher", "npm:3.1.0"],\ ["karma-firefox-launcher", "npm:2.1.2"],\ @@ -2965,7 +2965,7 @@ const RAW_RUNTIME_STATE = ["glob", "npm:10.4.1"],\ ["https-browserify", "npm:1.0.0"],\ ["js-merkle", "npm:0.1.5"],\ - ["karma", "npm:6.4.1"],\ + ["karma", "npm:6.4.3"],\ ["karma-chai", "virtual:e2d057e7cc143d3cb9bec864f4a2d862441b5a09f81f8e6c46e7a098cbc89e4d07017cc6e2e2142d5704bb55da853cbec2d025ebc0b30e8696c31380c00f2c7d#npm:0.1.0"],\ ["karma-chrome-launcher", "npm:3.1.0"],\ ["karma-firefox-launcher", "npm:2.1.2"],\ @@ -2992,7 +2992,7 @@ const RAW_RUNTIME_STATE = ["utf-8-validate", "npm:5.0.9"],\ ["util", "npm:0.12.4"],\ ["webpack", "virtual:01938c2be4835443e5a304e2b117c575220e96e8b7cedeb0f48d79264590b4c4babc6d1fea6367f522b1ca0149d795b42f2ab89c34a6ffe3c20f0a8cbb8b4453#npm:5.76.1"],\ - ["ws", "virtual:01938c2be4835443e5a304e2b117c575220e96e8b7cedeb0f48d79264590b4c4babc6d1fea6367f522b1ca0149d795b42f2ab89c34a6ffe3c20f0a8cbb8b4453#npm:7.5.5"]\ + ["ws", "virtual:01938c2be4835443e5a304e2b117c575220e96e8b7cedeb0f48d79264590b4c4babc6d1fea6367f522b1ca0149d795b42f2ab89c34a6ffe3c20f0a8cbb8b4453#npm:8.17.1"]\ ],\ "linkType": "SOFT"\ }]\ @@ -3053,7 +3053,7 @@ const RAW_RUNTIME_STATE = ["eslint-plugin-import", "virtual:e2d057e7cc143d3cb9bec864f4a2d862441b5a09f81f8e6c46e7a098cbc89e4d07017cc6e2e2142d5704bb55da853cbec2d025ebc0b30e8696c31380c00f2c7d#npm:2.29.0"],\ ["events", "npm:3.3.0"],\ ["https-browserify", "npm:1.0.0"],\ - ["karma", "npm:6.4.1"],\ + ["karma", "npm:6.4.3"],\ ["karma-chai", "virtual:e2d057e7cc143d3cb9bec864f4a2d862441b5a09f81f8e6c46e7a098cbc89e4d07017cc6e2e2142d5704bb55da853cbec2d025ebc0b30e8696c31380c00f2c7d#npm:0.1.0"],\ ["karma-chrome-launcher", "npm:3.1.0"],\ ["karma-firefox-launcher", "npm:2.1.2"],\ @@ -3118,7 +3118,7 @@ const RAW_RUNTIME_STATE = ["fast-json-patch", "npm:3.1.1"],\ ["https-browserify", "npm:1.0.0"],\ ["json-schema-diff-validator", "npm:0.4.1"],\ - ["karma", "npm:6.4.1"],\ + ["karma", "npm:6.4.3"],\ ["karma-chai", "virtual:e2d057e7cc143d3cb9bec864f4a2d862441b5a09f81f8e6c46e7a098cbc89e4d07017cc6e2e2142d5704bb55da853cbec2d025ebc0b30e8696c31380c00f2c7d#npm:0.1.0"],\ ["karma-chrome-launcher", "npm:3.1.0"],\ ["karma-firefox-launcher", "npm:2.1.2"],\ @@ -8411,7 +8411,7 @@ const RAW_RUNTIME_STATE = ["eslint-plugin-import", "virtual:ad53cff31b1dbd4927a99e71702e3b8b10338636eaff010987c27c9ccea2d52af36900a9e36a4231cbb6e5464248ccc9c1da5d1d24d9b0f4f95660296b1060a6#npm:2.29.0"],\ ["events", "npm:3.3.0"],\ ["https-browserify", "npm:1.0.0"],\ - ["karma", "npm:6.4.1"],\ + ["karma", "npm:6.4.3"],\ ["karma-chai", "virtual:ad53cff31b1dbd4927a99e71702e3b8b10338636eaff010987c27c9ccea2d52af36900a9e36a4231cbb6e5464248ccc9c1da5d1d24d9b0f4f95660296b1060a6#npm:0.1.0"],\ ["karma-chrome-launcher", "npm:3.1.0"],\ ["karma-firefox-launcher", "npm:2.1.2"],\ @@ -8567,6 +8567,13 @@ const RAW_RUNTIME_STATE = ],\ "linkType": "SOFT"\ }],\ + ["npm:4.3.5", {\ + "packageLocation": "./.yarn/cache/debug-npm-4.3.5-b5001f59b7-cb6eab424c.zip/node_modules/debug/",\ + "packageDependencies": [\ + ["debug", "npm:4.3.5"]\ + ],\ + "linkType": "SOFT"\ + }],\ ["virtual:2a426afc4b2eef43db12a540d29c2b5476640459bfcd5c24f86bb401cf8cce97e63bd81794d206a5643057e7f662643afd5ce3dfc4d4bfd8e706006c6309c5fa#npm:3.2.7", {\ "packageLocation": "./.yarn/__virtual__/debug-virtual-d2345003b7/0/cache/debug-npm-3.2.7-754e818c7a-d86fd7be2b.zip/node_modules/debug/",\ "packageDependencies": [\ @@ -8623,6 +8630,20 @@ const RAW_RUNTIME_STATE = ],\ "linkType": "HARD"\ }],\ + ["virtual:7a0505537f63825f62aaaf982168c2b7c1e816756656d44af98202b8d07990e163024e7dadf5587aa11d691887401ca8792ff06467da4d479c747705c9e87544#npm:4.3.5", {\ + "packageLocation": "./.yarn/__virtual__/debug-virtual-e443f3d004/0/cache/debug-npm-4.3.5-b5001f59b7-cb6eab424c.zip/node_modules/debug/",\ + "packageDependencies": [\ + ["debug", "virtual:7a0505537f63825f62aaaf982168c2b7c1e816756656d44af98202b8d07990e163024e7dadf5587aa11d691887401ca8792ff06467da4d479c747705c9e87544#npm:4.3.5"],\ + ["@types/supports-color", null],\ + ["ms", "npm:2.1.2"],\ + ["supports-color", null]\ + ],\ + "packagePeers": [\ + "@types/supports-color",\ + "supports-color"\ + ],\ + "linkType": "HARD"\ + }],\ ["virtual:87db25c7c5e6b25bbc12571091cdabc648b79d427ab445d1714ccfdcdfb3265c9de6561ca760cc3de470037cbedf3af4be56ba3b684b3a1c01d4c9c2fd55a741#npm:4.3.4", {\ "packageLocation": "./.yarn/__virtual__/debug-virtual-762d08cbe9/0/cache/debug-npm-4.3.4-4513954577-0073c3bcbd.zip/node_modules/debug/",\ "packageDependencies": [\ @@ -9233,7 +9254,7 @@ const RAW_RUNTIME_STATE = ["cors", "npm:2.8.5"],\ ["debug", "virtual:4b12ba5111caf7e8338099bdbc7cb046a9f8e079a44e74d0c03dca469876e3071ebbe671c5e90ae6b78ae33e22c205fa5ed32169a4aabd1404b13c56d09986e1#npm:4.3.4"],\ ["engine.io-parser", "npm:5.0.4"],\ - ["ws", "virtual:b375dcefccef90d9158d5f197a75395cffedb61772e66f2efcf31c6c8e30c82a6423e0d52b091b15b4fa72cda43a09256ed00b6ce89b9cfb14074f087b9c8496#npm:8.11.0"]\ + ["ws", "virtual:b375dcefccef90d9158d5f197a75395cffedb61772e66f2efcf31c6c8e30c82a6423e0d52b091b15b4fa72cda43a09256ed00b6ce89b9cfb14074f087b9c8496#npm:8.17.1"]\ ],\ "linkType": "HARD"\ }]\ @@ -12205,7 +12226,7 @@ const RAW_RUNTIME_STATE = "packageDependencies": [\ ["isomorphic-ws", "virtual:7469c013e9c5baa67d67122340123f2260ba4f66d6748855fb7f2ab67ea3fe52b2c8821a105003266d54faf99a9564056fb1b532d9ae8b6985087ab5f8394bf0#npm:4.0.1"],\ ["@types/ws", "npm:7.4.7"],\ - ["ws", "virtual:7469c013e9c5baa67d67122340123f2260ba4f66d6748855fb7f2ab67ea3fe52b2c8821a105003266d54faf99a9564056fb1b532d9ae8b6985087ab5f8394bf0#npm:7.5.5"]\ + ["ws", "virtual:b375dcefccef90d9158d5f197a75395cffedb61772e66f2efcf31c6c8e30c82a6423e0d52b091b15b4fa72cda43a09256ed00b6ce89b9cfb14074f087b9c8496#npm:8.17.1"]\ ],\ "packagePeers": [\ "@types/ws",\ @@ -12360,7 +12381,7 @@ const RAW_RUNTIME_STATE = ["isomorphic-ws", "virtual:7469c013e9c5baa67d67122340123f2260ba4f66d6748855fb7f2ab67ea3fe52b2c8821a105003266d54faf99a9564056fb1b532d9ae8b6985087ab5f8394bf0#npm:4.0.1"],\ ["json-stringify-safe", "npm:5.0.1"],\ ["uuid", "npm:8.3.2"],\ - ["ws", "virtual:7469c013e9c5baa67d67122340123f2260ba4f66d6748855fb7f2ab67ea3fe52b2c8821a105003266d54faf99a9564056fb1b532d9ae8b6985087ab5f8394bf0#npm:7.5.5"]\ + ["ws", "virtual:b375dcefccef90d9158d5f197a75395cffedb61772e66f2efcf31c6c8e30c82a6423e0d52b091b15b4fa72cda43a09256ed00b6ce89b9cfb14074f087b9c8496#npm:8.17.1"]\ ],\ "linkType": "HARD"\ }]\ @@ -12663,10 +12684,10 @@ const RAW_RUNTIME_STATE = }]\ ]],\ ["karma", [\ - ["npm:6.4.1", {\ - "packageLocation": "./.yarn/cache/karma-npm-6.4.1-5443d36ee9-24faabfaf0.zip/node_modules/karma/",\ + ["npm:6.4.3", {\ + "packageLocation": "./.yarn/cache/karma-npm-6.4.3-c1db2b322c-7fc194f5d4.zip/node_modules/karma/",\ "packageDependencies": [\ - ["karma", "npm:6.4.1"],\ + ["karma", "npm:6.4.3"],\ ["@colors/colors", "npm:1.5.0"],\ ["body-parser", "npm:1.19.0"],\ ["braces", "npm:3.0.2"],\ @@ -12686,7 +12707,7 @@ const RAW_RUNTIME_STATE = ["qjobs", "npm:1.2.0"],\ ["range-parser", "npm:1.2.1"],\ ["rimraf", "npm:3.0.2"],\ - ["socket.io", "npm:4.5.2"],\ + ["socket.io", "npm:4.7.5"],\ ["source-map", "npm:0.6.1"],\ ["tmp", "npm:0.2.1"],\ ["ua-parser-js", "npm:1.0.33"],\ @@ -12710,7 +12731,7 @@ const RAW_RUNTIME_STATE = ["@types/chai", "npm:4.2.22"],\ ["@types/karma", null],\ ["chai", "npm:4.3.10"],\ - ["karma", "npm:6.4.1"]\ + ["karma", "npm:6.4.3"]\ ],\ "packagePeers": [\ "@types/chai",\ @@ -12727,7 +12748,7 @@ const RAW_RUNTIME_STATE = ["@types/chai", null],\ ["@types/karma", null],\ ["chai", "npm:4.3.10"],\ - ["karma", "npm:6.4.1"]\ + ["karma", "npm:6.4.3"]\ ],\ "packagePeers": [\ "@types/chai",\ @@ -12784,7 +12805,7 @@ const RAW_RUNTIME_STATE = ["karma-mocha-reporter", "virtual:e2d057e7cc143d3cb9bec864f4a2d862441b5a09f81f8e6c46e7a098cbc89e4d07017cc6e2e2142d5704bb55da853cbec2d025ebc0b30e8696c31380c00f2c7d#npm:2.2.5"],\ ["@types/karma", null],\ ["chalk", "npm:2.4.2"],\ - ["karma", "npm:6.4.1"],\ + ["karma", "npm:6.4.3"],\ ["log-symbols", "npm:2.2.0"],\ ["strip-ansi", "npm:4.0.0"]\ ],\ @@ -17273,25 +17294,28 @@ const RAW_RUNTIME_STATE = }]\ ]],\ ["socket.io", [\ - ["npm:4.5.2", {\ - "packageLocation": "./.yarn/cache/socket.io-npm-4.5.2-11f9913f37-872605db0f.zip/node_modules/socket.io/",\ + ["npm:4.7.5", {\ + "packageLocation": "./.yarn/cache/socket.io-npm-4.7.5-7db6120b90-911528f5bf.zip/node_modules/socket.io/",\ "packageDependencies": [\ - ["socket.io", "npm:4.5.2"],\ + ["socket.io", "npm:4.7.5"],\ ["accepts", "npm:1.3.7"],\ ["base64id", "npm:2.0.0"],\ + ["cors", "npm:2.8.5"],\ ["debug", "virtual:4b12ba5111caf7e8338099bdbc7cb046a9f8e079a44e74d0c03dca469876e3071ebbe671c5e90ae6b78ae33e22c205fa5ed32169a4aabd1404b13c56d09986e1#npm:4.3.4"],\ ["engine.io", "npm:6.4.2"],\ - ["socket.io-adapter", "npm:2.4.0"],\ + ["socket.io-adapter", "npm:2.5.5"],\ ["socket.io-parser", "npm:4.2.3"]\ ],\ "linkType": "HARD"\ }]\ ]],\ ["socket.io-adapter", [\ - ["npm:2.4.0", {\ - "packageLocation": "./.yarn/cache/socket.io-adapter-npm-2.4.0-36a74a6ea1-e10c8c36a1.zip/node_modules/socket.io-adapter/",\ + ["npm:2.5.5", {\ + "packageLocation": "./.yarn/cache/socket.io-adapter-npm-2.5.5-7a0505537f-e364733a4c.zip/node_modules/socket.io-adapter/",\ "packageDependencies": [\ - ["socket.io-adapter", "npm:2.4.0"]\ + ["socket.io-adapter", "npm:2.5.5"],\ + ["debug", "virtual:7a0505537f63825f62aaaf982168c2b7c1e816756656d44af98202b8d07990e163024e7dadf5587aa11d691887401ca8792ff06467da4d479c747705c9e87544#npm:4.3.5"],\ + ["ws", "virtual:b375dcefccef90d9158d5f197a75395cffedb61772e66f2efcf31c6c8e30c82a6423e0d52b091b15b4fa72cda43a09256ed00b6ce89b9cfb14074f087b9c8496#npm:8.17.1"]\ ],\ "linkType": "HARD"\ }]\ @@ -19989,24 +20013,17 @@ const RAW_RUNTIME_STATE = }]\ ]],\ ["ws", [\ - ["npm:7.5.5", {\ - "packageLocation": "./.yarn/cache/ws-npm-7.5.5-8f4a2a84a8-2e91fd634b.zip/node_modules/ws/",\ + ["npm:8.17.1", {\ + "packageLocation": "./.yarn/cache/ws-npm-8.17.1-f57fb24a2c-4264ae92c0.zip/node_modules/ws/",\ "packageDependencies": [\ - ["ws", "npm:7.5.5"]\ + ["ws", "npm:8.17.1"]\ ],\ "linkType": "SOFT"\ }],\ - ["npm:8.11.0", {\ - "packageLocation": "./.yarn/cache/ws-npm-8.11.0-ab72116a01-f759ea19e4.zip/node_modules/ws/",\ + ["virtual:01938c2be4835443e5a304e2b117c575220e96e8b7cedeb0f48d79264590b4c4babc6d1fea6367f522b1ca0149d795b42f2ab89c34a6ffe3c20f0a8cbb8b4453#npm:8.17.1", {\ + "packageLocation": "./.yarn/__virtual__/ws-virtual-9c0ceafc6c/0/cache/ws-npm-8.17.1-f57fb24a2c-4264ae92c0.zip/node_modules/ws/",\ "packageDependencies": [\ - ["ws", "npm:8.11.0"]\ - ],\ - "linkType": "SOFT"\ - }],\ - ["virtual:01938c2be4835443e5a304e2b117c575220e96e8b7cedeb0f48d79264590b4c4babc6d1fea6367f522b1ca0149d795b42f2ab89c34a6ffe3c20f0a8cbb8b4453#npm:7.5.5", {\ - "packageLocation": "./.yarn/__virtual__/ws-virtual-49f0813c39/0/cache/ws-npm-7.5.5-8f4a2a84a8-2e91fd634b.zip/node_modules/ws/",\ - "packageDependencies": [\ - ["ws", "virtual:01938c2be4835443e5a304e2b117c575220e96e8b7cedeb0f48d79264590b4c4babc6d1fea6367f522b1ca0149d795b42f2ab89c34a6ffe3c20f0a8cbb8b4453#npm:7.5.5"],\ + ["ws", "virtual:01938c2be4835443e5a304e2b117c575220e96e8b7cedeb0f48d79264590b4c4babc6d1fea6367f522b1ca0149d795b42f2ab89c34a6ffe3c20f0a8cbb8b4453#npm:8.17.1"],\ ["@types/bufferutil", null],\ ["@types/utf-8-validate", null],\ ["bufferutil", "npm:4.0.6"],\ @@ -20020,27 +20037,10 @@ const RAW_RUNTIME_STATE = ],\ "linkType": "HARD"\ }],\ - ["virtual:7469c013e9c5baa67d67122340123f2260ba4f66d6748855fb7f2ab67ea3fe52b2c8821a105003266d54faf99a9564056fb1b532d9ae8b6985087ab5f8394bf0#npm:7.5.5", {\ - "packageLocation": "./.yarn/__virtual__/ws-virtual-90d8bcd261/0/cache/ws-npm-7.5.5-8f4a2a84a8-2e91fd634b.zip/node_modules/ws/",\ - "packageDependencies": [\ - ["ws", "virtual:7469c013e9c5baa67d67122340123f2260ba4f66d6748855fb7f2ab67ea3fe52b2c8821a105003266d54faf99a9564056fb1b532d9ae8b6985087ab5f8394bf0#npm:7.5.5"],\ - ["@types/bufferutil", null],\ - ["@types/utf-8-validate", null],\ - ["bufferutil", null],\ - ["utf-8-validate", null]\ - ],\ - "packagePeers": [\ - "@types/bufferutil",\ - "@types/utf-8-validate",\ - "bufferutil",\ - "utf-8-validate"\ - ],\ - "linkType": "HARD"\ - }],\ - ["virtual:b375dcefccef90d9158d5f197a75395cffedb61772e66f2efcf31c6c8e30c82a6423e0d52b091b15b4fa72cda43a09256ed00b6ce89b9cfb14074f087b9c8496#npm:8.11.0", {\ - "packageLocation": "./.yarn/__virtual__/ws-virtual-110db35f33/0/cache/ws-npm-8.11.0-ab72116a01-f759ea19e4.zip/node_modules/ws/",\ + ["virtual:b375dcefccef90d9158d5f197a75395cffedb61772e66f2efcf31c6c8e30c82a6423e0d52b091b15b4fa72cda43a09256ed00b6ce89b9cfb14074f087b9c8496#npm:8.17.1", {\ + "packageLocation": "./.yarn/__virtual__/ws-virtual-59f3d5fa16/0/cache/ws-npm-8.17.1-f57fb24a2c-4264ae92c0.zip/node_modules/ws/",\ "packageDependencies": [\ - ["ws", "virtual:b375dcefccef90d9158d5f197a75395cffedb61772e66f2efcf31c6c8e30c82a6423e0d52b091b15b4fa72cda43a09256ed00b6ce89b9cfb14074f087b9c8496#npm:8.11.0"],\ + ["ws", "virtual:b375dcefccef90d9158d5f197a75395cffedb61772e66f2efcf31c6c8e30c82a6423e0d52b091b15b4fa72cda43a09256ed00b6ce89b9cfb14074f087b9c8496#npm:8.17.1"],\ ["@types/bufferutil", null],\ ["@types/utf-8-validate", null],\ ["bufferutil", null],\ diff --git a/.yarn/cache/debug-npm-4.3.5-b5001f59b7-cb6eab424c.zip b/.yarn/cache/debug-npm-4.3.5-b5001f59b7-cb6eab424c.zip new file mode 100644 index 00000000000..c621a4c78dd Binary files /dev/null and b/.yarn/cache/debug-npm-4.3.5-b5001f59b7-cb6eab424c.zip differ diff --git a/.yarn/cache/karma-npm-6.4.1-5443d36ee9-24faabfaf0.zip b/.yarn/cache/karma-npm-6.4.3-c1db2b322c-7fc194f5d4.zip similarity index 59% rename from .yarn/cache/karma-npm-6.4.1-5443d36ee9-24faabfaf0.zip rename to .yarn/cache/karma-npm-6.4.3-c1db2b322c-7fc194f5d4.zip index 755877b272e..601d8fc02b8 100644 Binary files a/.yarn/cache/karma-npm-6.4.1-5443d36ee9-24faabfaf0.zip and b/.yarn/cache/karma-npm-6.4.3-c1db2b322c-7fc194f5d4.zip differ diff --git a/.yarn/cache/socket.io-adapter-npm-2.4.0-36a74a6ea1-e10c8c36a1.zip b/.yarn/cache/socket.io-adapter-npm-2.4.0-36a74a6ea1-e10c8c36a1.zip deleted file mode 100644 index 898ffcf179c..00000000000 Binary files a/.yarn/cache/socket.io-adapter-npm-2.4.0-36a74a6ea1-e10c8c36a1.zip and /dev/null differ diff --git a/.yarn/cache/socket.io-adapter-npm-2.5.5-7a0505537f-e364733a4c.zip b/.yarn/cache/socket.io-adapter-npm-2.5.5-7a0505537f-e364733a4c.zip new file mode 100644 index 00000000000..8645bbec5e0 Binary files /dev/null and b/.yarn/cache/socket.io-adapter-npm-2.5.5-7a0505537f-e364733a4c.zip differ diff --git a/.yarn/cache/socket.io-npm-4.5.2-11f9913f37-872605db0f.zip b/.yarn/cache/socket.io-npm-4.5.2-11f9913f37-872605db0f.zip deleted file mode 100644 index d53d3f6ddd7..00000000000 Binary files a/.yarn/cache/socket.io-npm-4.5.2-11f9913f37-872605db0f.zip and /dev/null differ diff --git a/.yarn/cache/socket.io-npm-4.7.5-7db6120b90-911528f5bf.zip b/.yarn/cache/socket.io-npm-4.7.5-7db6120b90-911528f5bf.zip new file mode 100644 index 00000000000..7fad0bb2ff8 Binary files /dev/null and b/.yarn/cache/socket.io-npm-4.7.5-7db6120b90-911528f5bf.zip differ diff --git a/.yarn/cache/ws-npm-7.5.5-8f4a2a84a8-2e91fd634b.zip b/.yarn/cache/ws-npm-7.5.5-8f4a2a84a8-2e91fd634b.zip deleted file mode 100644 index ce54109cc3a..00000000000 Binary files a/.yarn/cache/ws-npm-7.5.5-8f4a2a84a8-2e91fd634b.zip and /dev/null differ diff --git a/.yarn/cache/ws-npm-8.11.0-ab72116a01-f759ea19e4.zip b/.yarn/cache/ws-npm-8.11.0-ab72116a01-f759ea19e4.zip deleted file mode 100644 index 337545a406a..00000000000 Binary files a/.yarn/cache/ws-npm-8.11.0-ab72116a01-f759ea19e4.zip and /dev/null differ diff --git a/.yarn/cache/ws-npm-8.17.1-f57fb24a2c-4264ae92c0.zip b/.yarn/cache/ws-npm-8.17.1-f57fb24a2c-4264ae92c0.zip new file mode 100644 index 00000000000..cd6b6f229ef Binary files /dev/null and b/.yarn/cache/ws-npm-8.17.1-f57fb24a2c-4264ae92c0.zip differ diff --git a/Cargo.lock b/Cargo.lock index 19c63f23809..f5e046b964f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1653,6 +1653,7 @@ dependencies = [ "dotenvy", "dpp", "drive", + "drive-abci", "envy", "file-rotate", "hex", diff --git a/package.json b/package.json index b37fc18a9dc..041d54ec125 100644 --- a/package.json +++ b/package.json @@ -90,7 +90,8 @@ "cacache": "18.0.0", "node-gyp": "10.0.1", "follow-redirects": "^1.15.5", - "socks": "^2.8.1" + "socks": "^2.8.1", + "ws": "^8.17.1" }, "dependencies": { "node-gyp": "^10.0.1" diff --git a/packages/dapi/package.json b/packages/dapi/package.json index daa6a436c18..513f8f41dc4 100644 --- a/packages/dapi/package.json +++ b/packages/dapi/package.json @@ -53,7 +53,7 @@ "lru-cache": "^5.1.1", "pino": "^8.16.2", "pino-pretty": "^10.2.3", - "ws": "^7.5.3" + "ws": "^8.17.1" }, "devDependencies": { "@babel/core": "^7.23.3", diff --git a/packages/dashmate/configs/defaults/getBaseConfigFactory.js b/packages/dashmate/configs/defaults/getBaseConfigFactory.js index 94268b2e7a3..171a843d87a 100644 --- a/packages/dashmate/configs/defaults/getBaseConfigFactory.js +++ b/packages/dashmate/configs/defaults/getBaseConfigFactory.js @@ -15,7 +15,8 @@ import semver from 'semver'; import fs from 'fs'; import { - NETWORK_TESTNET, PACKAGE_ROOT_DIR, + NETWORK_MAINNET, + PACKAGE_ROOT_DIR, } from '../../src/constants.js'; import Config from '../../src/config/Config.js'; @@ -282,12 +283,28 @@ export default function getBaseConfigFactory(homeDir) { retention: 60 * 3, }, validatorSet: { - llmqType: 4, + quorum: { + llmqType: 4, + dkgInterval: 24, + activeSigners: 24, + rotation: false, + }, }, chainLock: { - llmqType: 2, - dkgInterval: 288, - llmqSize: 400, + quorum: { + llmqType: 2, + dkgInterval: 288, + activeSigners: 4, + rotation: false, + }, + }, + instantLock: { + quorum: { + llmqType: 5, + dkgInterval: 288, + activeSigners: 32, + rotation: true, + }, }, metrics: { enabled: false, @@ -462,7 +479,7 @@ export default function getBaseConfigFactory(homeDir) { }, }, externalIp: null, - network: NETWORK_TESTNET, + network: NETWORK_MAINNET, environment: 'production', }; diff --git a/packages/dashmate/configs/defaults/getLocalConfigFactory.js b/packages/dashmate/configs/defaults/getLocalConfigFactory.js index c2fde1eef83..7b1805db5db 100644 --- a/packages/dashmate/configs/defaults/getLocalConfigFactory.js +++ b/packages/dashmate/configs/defaults/getLocalConfigFactory.js @@ -70,12 +70,28 @@ export default function getLocalConfigFactory(getBaseConfig) { }, abci: { validatorSet: { - llmqType: 106, + quorum: { + llmqType: 106, + dkgInterval: 24, + activeSigners: 2, + rotation: false, + }, }, chainLock: { - llmqType: 100, - dkgInterval: 24, - llmqSize: 3, + quorum: { + llmqType: 100, + dkgInterval: 24, + activeSigners: 2, + rotation: false, + }, + }, + instantLock: { + quorum: { + llmqType: 104, + dkgInterval: 24, + activeSigners: 2, + rotation: false, + }, }, }, }, diff --git a/packages/dashmate/configs/defaults/getTestnetConfigFactory.js b/packages/dashmate/configs/defaults/getTestnetConfigFactory.js index 323d63314bb..59210678ce1 100644 --- a/packages/dashmate/configs/defaults/getTestnetConfigFactory.js +++ b/packages/dashmate/configs/defaults/getTestnetConfigFactory.js @@ -55,12 +55,28 @@ export default function getTestnetConfigFactory(homeDir, getBaseConfig) { abci: { epochTime: 3600, validatorSet: { - llmqType: 6, + quorum: { + llmqType: 6, + dkgInterval: 24, + activeSigners: 24, + rotation: false, + }, }, chainLock: { - llmqType: 1, - dkgInterval: 24, - llmqSize: 50, + quorum: { + llmqType: 1, + dkgInterval: 24, + activeSigners: 24, + rotation: false, + }, + }, + instantLock: { + quorum: { + llmqType: 5, + dkgInterval: 288, + activeSigners: 32, + rotation: true, + }, }, }, tenderdash: { diff --git a/packages/dashmate/configs/getConfigFileMigrationsFactory.js b/packages/dashmate/configs/getConfigFileMigrationsFactory.js index 2a8f1d61546..a2ebba9a273 100644 --- a/packages/dashmate/configs/getConfigFileMigrationsFactory.js +++ b/packages/dashmate/configs/getConfigFileMigrationsFactory.js @@ -40,6 +40,20 @@ export default function getConfigFileMigrationsFactory(homeDir, defaultConfigs) return defaultConfigs.get(baseConfigName); } + function getDefaultConfigByNetwork(network) { + if (network === NETWORK_MAINNET) { + return defaultConfigs.get('mainnet'); + } + if (network === NETWORK_TESTNET) { + return defaultConfigs.get('testnet'); + } + if (network === NETWORK_LOCAL) { + return defaultConfigs.get('local'); + } + + return defaultConfigs.get('base'); + } + return { '0.24.0': (configFile) => { Object.entries(configFile.configs) @@ -615,7 +629,44 @@ export default function getConfigFileMigrationsFactory(homeDir, defaultConfigs) }, '1.0.0-dev.16': (configFile) => { Object.entries(configFile.configs) - .forEach(([, options]) => { + .forEach(([name, options]) => { + // Update Drive's quorum configuration + if (name === 'base') { + options.network = NETWORK_MAINNET; + } + + const networkConfig = getDefaultConfigByNetwork(options.network); + + options.platform.drive.abci.chainLock.quorum = { + llmqType: networkConfig.get('platform.drive.abci.chainLock.quorum.llmqType'), + dkgInterval: networkConfig.get('platform.drive.abci.chainLock.quorum.dkgInterval'), + activeSigners: networkConfig.get('platform.drive.abci.chainLock.quorum.activeSigners'), + rotation: networkConfig.get('platform.drive.abci.chainLock.quorum.rotation'), + }; + + delete options.platform.drive.abci.chainLock.llmqType; + delete options.platform.drive.abci.chainLock.llmqSize; + delete options.platform.drive.abci.chainLock.dkgInterval; + + options.platform.drive.abci.validatorSet.quorum = { + llmqType: networkConfig.get('platform.drive.abci.validatorSet.quorum.llmqType'), + dkgInterval: networkConfig.get('platform.drive.abci.validatorSet.quorum.dkgInterval'), + activeSigners: networkConfig.get('platform.drive.abci.validatorSet.quorum.activeSigners'), + rotation: networkConfig.get('platform.drive.abci.validatorSet.quorum.rotation'), + }; + + delete options.platform.drive.abci.validatorSet.llmqType; + + options.platform.drive.abci.instantLock = { + quorum: { + llmqType: networkConfig.get('platform.drive.abci.instantLock.quorum.llmqType'), + dkgInterval: networkConfig.get('platform.drive.abci.instantLock.quorum.dkgInterval'), + activeSigners: networkConfig.get('platform.drive.abci.instantLock.quorum.activeSigners'), + rotation: networkConfig.get('platform.drive.abci.instantLock.quorum.rotation'), + }, + }; + + // Update Core RPC auth configuration options.core.rpc.users = base.get('core.rpc.users'); options.core.rpc.users.dashmate = options.core.rpc.password; diff --git a/packages/dashmate/docker-compose.yml b/packages/dashmate/docker-compose.yml index 17e07639973..7081174bba7 100644 --- a/packages/dashmate/docker-compose.yml +++ b/packages/dashmate/docker-compose.yml @@ -69,10 +69,18 @@ services: - MASTERNODE_REWARD_SHARES_SECOND_PUBLIC_KEY=${PLATFORM_MASTERNODE_REWARD_SHARES_SECOND_PUBLIC_KEY} - WITHDRAWALS_MASTER_PUBLIC_KEY=${PLATFORM_WITHDRAWALS_MASTER_PUBLIC_KEY} - WITHDRAWALS_SECOND_PUBLIC_KEY=${PLATFORM_WITHDRAWALS_SECOND_PUBLIC_KEY} - - VALIDATOR_SET_QUORUM_TYPE=${PLATFORM_DRIVE_ABCI_VALIDATOR_SET_LLMQ_TYPE:?err} - - CHAIN_LOCK_QUORUM_TYPE=${PLATFORM_DRIVE_ABCI_CHAIN_LOCK_LLMQ_TYPE:?err} - - CHAIN_LOCK_QUORUM_WINDOW=${PLATFORM_DRIVE_ABCI_CHAIN_LOCK_DKG_INTERVAL:?err} - - CHAIN_LOCK_QUORUM_SIZE=${PLATFORM_DRIVE_ABCI_CHAIN_LOCK_LLMQ_SIZE:?err} + - VALIDATOR_SET_QUORUM_TYPE=${PLATFORM_DRIVE_ABCI_VALIDATOR_SET_QUORUM_LLMQ_TYPE:?err} + - VALIDATOR_SET_QUORUM_WINDOW=${PLATFORM_DRIVE_ABCI_VALIDATOR_SET_QUORUM_DKG_INTERVAL:?err} + - VALIDATOR_SET_QUORUM_ACTIVE_SIGNERS=${PLATFORM_DRIVE_ABCI_VALIDATOR_SET_QUORUM_ACTIVE_SIGNERS:?err} + - VALIDATOR_SET_QUORUM_ROTATION=${PLATFORM_DRIVE_ABCI_VALIDATOR_SET_QUORUM_ROTATION:?err} + - CHAIN_LOCK_QUORUM_TYPE=${PLATFORM_DRIVE_ABCI_CHAIN_LOCK_QUORUM_LLMQ_TYPE:?err} + - CHAIN_LOCK_QUORUM_WINDOW=${PLATFORM_DRIVE_ABCI_CHAIN_LOCK_QUORUM_DKG_INTERVAL:?err} + - CHAIN_LOCK_QUORUM_ACTIVE_SIGNERS=${PLATFORM_DRIVE_ABCI_CHAIN_LOCK_QUORUM_ACTIVE_SIGNERS:?err} + - CHAIN_LOCK_QUORUM_ROTATION=${PLATFORM_DRIVE_ABCI_CHAIN_LOCK_QUORUM_ROTATION:?err} + - INSTANT_LOCK_QUORUM_TYPE=${PLATFORM_DRIVE_ABCI_INSTANT_LOCK_QUORUM_LLMQ_TYPE:?err} + - INSTANT_LOCK_QUORUM_WINDOW=${PLATFORM_DRIVE_ABCI_INSTANT_LOCK_QUORUM_DKG_INTERVAL:?err} + - INSTANT_LOCK_QUORUM_ACTIVE_SIGNERS=${PLATFORM_DRIVE_ABCI_INSTANT_LOCK_QUORUM_ACTIVE_SIGNERS:?err} + - INSTANT_LOCK_QUORUM_ROTATION=${PLATFORM_DRIVE_ABCI_INSTANT_LOCK_QUORUM_ROTATION:?err} - DB_PATH=/var/lib/dash/rs-drive-abci/db - ABCI_CONSENSUS_BIND_ADDRESS=tcp://0.0.0.0:26658 - GRPC_BIND_ADDRESS=0.0.0.0:26670 diff --git a/packages/dashmate/src/config/configJsonSchema.js b/packages/dashmate/src/config/configJsonSchema.js index 2af2391fdc0..e80dfd27caa 100644 --- a/packages/dashmate/src/config/configJsonSchema.js +++ b/packages/dashmate/src/config/configJsonSchema.js @@ -105,6 +105,28 @@ export default { additionalProperties: false, required: ['enabled', 'host', 'port'], }, + quorum: { + type: 'object', + properties: { + llmqType: { + type: 'integer', + enum: [1, 2, 3, 4, 5, 6, 100, 101, 102, 103, 104, 105, 106, 107], + }, + dkgInterval: { + type: 'integer', + minimum: 1, + }, + activeSigners: { + type: 'integer', + minimum: 1, + }, + rotation: { + type: 'boolean', + }, + }, + required: ['llmqType', 'dkgInterval', 'activeSigners', 'rotation'], + additionalProperties: false, + }, }, properties: { description: { @@ -788,34 +810,32 @@ export default { validatorSet: { type: 'object', properties: { - llmqType: { - type: 'number', - // https://github.com/dashpay/dashcore-lib/blob/843176fed9fc81feae43ccf319d99e2dd942fe1f/lib/constants/index.js#L50-L99 - enum: [1, 2, 3, 4, 5, 6, 100, 101, 102, 103, 104, 105, 106, 107], + quorum: { + $ref: '#/definitions/quorum', }, }, additionalProperties: false, - required: ['llmqType'], + required: ['quorum'], }, chainLock: { type: 'object', properties: { - llmqType: { - type: 'number', - // https://github.com/dashpay/dashcore-lib/blob/843176fed9fc81feae43ccf319d99e2dd942fe1f/lib/constants/index.js#L50-L99 - enum: [1, 2, 3, 4, 5, 6, 100, 101, 102, 103, 104, 105, 106, 107], - }, - llmqSize: { - type: 'integer', - minimum: 0, + quorum: { + $ref: '#/definitions/quorum', }, - dkgInterval: { - type: 'integer', - minimum: 0, + }, + additionalProperties: false, + required: ['quorum'], + }, + instantLock: { + type: 'object', + properties: { + quorum: { + $ref: '#/definitions/quorum', }, }, additionalProperties: false, - required: ['llmqType', 'llmqSize', 'dkgInterval'], + required: ['quorum'], }, epochTime: { type: 'integer', diff --git a/packages/dashmate/src/helper/scheduleRenewZeroSslCertificateFactory.js b/packages/dashmate/src/helper/scheduleRenewZeroSslCertificateFactory.js index 8b490c6b3e9..c403c2bef39 100644 --- a/packages/dashmate/src/helper/scheduleRenewZeroSslCertificateFactory.js +++ b/packages/dashmate/src/helper/scheduleRenewZeroSslCertificateFactory.js @@ -55,6 +55,7 @@ export default function scheduleRenewZeroSslCertificateFactory( await tasks.run({ expirationDays: Certificate.EXPIRATION_LIMIT_DAYS, + noRetry: true, }); // Write config files diff --git a/packages/dashmate/src/listr/tasks/setup/local/configureTenderdashTaskFactory.js b/packages/dashmate/src/listr/tasks/setup/local/configureTenderdashTaskFactory.js index af533570888..da5e7e66fc0 100644 --- a/packages/dashmate/src/listr/tasks/setup/local/configureTenderdashTaskFactory.js +++ b/packages/dashmate/src/listr/tasks/setup/local/configureTenderdashTaskFactory.js @@ -50,7 +50,7 @@ export default function configureTenderdashTaskFactory() { config.set( 'platform.drive.tenderdash.genesis.validator_quorum_type', - config.get('platform.drive.abci.validatorSet.llmqType'), + config.get('platform.drive.abci.validatorSet.quorum.llmqType'), ); }); }, diff --git a/packages/dashmate/src/listr/tasks/setup/local/enableCoreQuorumsTaskFactory.js b/packages/dashmate/src/listr/tasks/setup/local/enableCoreQuorumsTaskFactory.js index 9dd3f68699a..49fbbd47379 100644 --- a/packages/dashmate/src/listr/tasks/setup/local/enableCoreQuorumsTaskFactory.js +++ b/packages/dashmate/src/listr/tasks/setup/local/enableCoreQuorumsTaskFactory.js @@ -268,7 +268,7 @@ export default function enableCoreQuorumsTaskFactory(generateBlocks) { // eslint-disable-next-line prefer-destructuring ctx.quorumHash = quorumList[LLMQ_TYPE_TEST_PLATFORM][0]; - const llmqType = ctx.masternodeCoreServices[0].getConfig().get('platform.drive.abci.validatorSet.llmqType'); + const llmqType = ctx.masternodeCoreServices[0].getConfig().get('platform.drive.abci.validatorSet.quorum.llmqType'); const { result: quorumInfo } = await ctx.seedRpcClient.quorum('info', llmqType, ctx.quorumHash); diff --git a/packages/dashmate/test/unit/commands/config/set.spec.js b/packages/dashmate/test/unit/commands/config/set.spec.js index 94089cb9a77..67b8bef75a3 100644 --- a/packages/dashmate/test/unit/commands/config/set.spec.js +++ b/packages/dashmate/test/unit/commands/config/set.spec.js @@ -42,18 +42,18 @@ describe('Config set command', () => { const command = new ConfigSetCommand(); await command.runWithDependencies({ - option: 'platform.drive.abci.validatorSet.llmqType', + option: 'platform.drive.abci.validatorSet.quorum.llmqType', value: 107, }, flags, config); - expect(config.get('platform.drive.abci.validatorSet.llmqType')).to.equal(107); + expect(config.get('platform.drive.abci.validatorSet.quorum.llmqType')).to.equal(107); await command.runWithDependencies({ - option: 'platform.drive.abci.validatorSet.llmqType', + option: 'platform.drive.abci.validatorSet.quorum.llmqType', value: '107', }, flags, config); - expect(config.get('platform.drive.abci.validatorSet.llmqType')).to.equal(107); + expect(config.get('platform.drive.abci.validatorSet.quorum.llmqType')).to.equal(107); }); it('should allow setting booleans', async () => { diff --git a/packages/js-dapi-client/package.json b/packages/js-dapi-client/package.json index 8f13a34a86b..a9793033f16 100644 --- a/packages/js-dapi-client/package.json +++ b/packages/js-dapi-client/package.json @@ -57,7 +57,7 @@ "eslint-plugin-import": "^2.29.0", "eslint-plugin-jsdoc": "^46.9.0", "events": "^3.3.0", - "karma": "^6.4.1", + "karma": "^6.4.3", "karma-chai": "^0.1.0", "karma-chrome-launcher": "^3.1.0", "karma-firefox-launcher": "^2.1.2", diff --git a/packages/js-dash-sdk/package.json b/packages/js-dash-sdk/package.json index 662bc45dd04..36675334e9d 100644 --- a/packages/js-dash-sdk/package.json +++ b/packages/js-dash-sdk/package.json @@ -78,7 +78,7 @@ "eslint-plugin-import": "^2.29.0", "events": "^3.3.0", "https-browserify": "^1.0.0", - "karma": "^6.4.1", + "karma": "^6.4.3", "karma-chai": "^0.1.0", "karma-chrome-launcher": "^3.1.0", "karma-firefox-launcher": "^2.1.2", diff --git a/packages/platform-test-suite/package.json b/packages/platform-test-suite/package.json index 9f97dc81441..f55c7ded77f 100644 --- a/packages/platform-test-suite/package.json +++ b/packages/platform-test-suite/package.json @@ -47,7 +47,7 @@ "glob": "^10.3.4", "https-browserify": "^1.0.0", "js-merkle": "^0.1.5", - "karma": "^6.4.1", + "karma": "^6.4.3", "karma-chai": "^0.1.0", "karma-chrome-launcher": "^3.1.0", "karma-firefox-launcher": "^2.1.2", @@ -74,7 +74,7 @@ "utf-8-validate": "^5.0.9", "util": "^0.12.4", "webpack": "^5.76.1", - "ws": "^7.5.3" + "ws": "^8.17.1" }, "devDependencies": { "eslint": "^8.53.0", diff --git a/packages/rs-dpp/src/data_contract/document_type/class_methods/try_from_schema/v0/mod.rs b/packages/rs-dpp/src/data_contract/document_type/class_methods/try_from_schema/v0/mod.rs index 97534fe049e..9c79f5c2812 100644 --- a/packages/rs-dpp/src/data_contract/document_type/class_methods/try_from_schema/v0/mod.rs +++ b/packages/rs-dpp/src/data_contract/document_type/class_methods/try_from_schema/v0/mod.rs @@ -39,7 +39,9 @@ use crate::data_contract::document_type::property_names::{ CAN_BE_DELETED, CREATION_RESTRICTION_MODE, DOCUMENTS_KEEP_HISTORY, DOCUMENTS_MUTABLE, TRADE_MODE, TRANSFERABLE, }; -use crate::data_contract::document_type::{property_names, DocumentType}; +use crate::data_contract::document_type::{ + property_names, ByteArrayPropertySizes, DocumentType, StringPropertySizes, +}; use crate::data_contract::errors::DataContractError; use crate::data_contract::storage_requirements::keys_for_document_type::StorageKeyRequirements; use crate::identity::SecurityLevel; @@ -383,7 +385,7 @@ impl DocumentTypeV0 { })?; // Validate indexed property type - match property_definition.property_type { + match &property_definition.property_type { // Array and objects aren't supported for indexing yet DocumentPropertyType::Array(_) | DocumentPropertyType::Object(_) @@ -399,9 +401,9 @@ impl DocumentTypeV0 { ))) } // Indexed byte array size must be limited - DocumentPropertyType::ByteArray(_, maybe_max_size) - if maybe_max_size.is_none() - || maybe_max_size.unwrap() + DocumentPropertyType::ByteArray(sizes) + if sizes.max_size.is_none() + || sizes.max_size.unwrap() > MAX_INDEXED_BYTE_ARRAY_PROPERTY_LENGTH => { Err(ProtocolError::ConsensusError(Box::new( @@ -419,9 +421,9 @@ impl DocumentTypeV0 { ))) } // Indexed string length must be limited - DocumentPropertyType::String(_, maybe_max_length) - if maybe_max_length.is_none() - || maybe_max_length.unwrap() + DocumentPropertyType::String(sizes) + if sizes.max_length.is_none() + || sizes.max_length.unwrap() > MAX_INDEXED_STRING_PROPERTY_LENGTH => { Err(ProtocolError::ConsensusError(Box::new( @@ -567,12 +569,14 @@ fn insert_values( Some("application/x.dash.dpp.identifier") => { DocumentPropertyType::Identifier } - Some(_) | None => DocumentPropertyType::ByteArray( - inner_properties - .get_optional_integer(property_names::MIN_ITEMS)?, - inner_properties - .get_optional_integer(property_names::MAX_ITEMS)?, - ), + Some(_) | None => { + DocumentPropertyType::ByteArray(ByteArrayPropertySizes { + min_size: inner_properties + .get_optional_integer(property_names::MIN_ITEMS)?, + max_size: inner_properties + .get_optional_integer(property_names::MAX_ITEMS)?, + }) + } } } else { return Err(DataContractError::InvalidContractStructure( @@ -622,10 +626,12 @@ fn insert_values( } "string" => { - field_type = DocumentPropertyType::String( - inner_properties.get_optional_integer(property_names::MIN_LENGTH)?, - inner_properties.get_optional_integer(property_names::MAX_LENGTH)?, - ); + field_type = DocumentPropertyType::String(StringPropertySizes { + min_length: inner_properties + .get_optional_integer(property_names::MIN_LENGTH)?, + max_length: inner_properties + .get_optional_integer(property_names::MAX_LENGTH)?, + }); document_properties.insert( prefixed_property_key, DocumentProperty { @@ -673,10 +679,10 @@ fn insert_values_nested( let field_type = match type_value { "integer" => DocumentPropertyType::Integer, "number" => DocumentPropertyType::Number, - "string" => DocumentPropertyType::String( - inner_properties.get_optional_integer(property_names::MIN_LENGTH)?, - inner_properties.get_optional_integer(property_names::MAX_LENGTH)?, - ), + "string" => DocumentPropertyType::String(StringPropertySizes { + min_length: inner_properties.get_optional_integer(property_names::MIN_LENGTH)?, + max_length: inner_properties.get_optional_integer(property_names::MAX_LENGTH)?, + }), "array" => { // Only handling bytearrays for v1 // Return an error if it is not a byte array @@ -689,10 +695,14 @@ fn insert_values_nested( Some("application/x.dash.dpp.identifier") => { DocumentPropertyType::Identifier } - Some(_) | None => DocumentPropertyType::ByteArray( - inner_properties.get_optional_integer(property_names::MIN_ITEMS)?, - inner_properties.get_optional_integer(property_names::MAX_ITEMS)?, - ), + Some(_) | None => { + DocumentPropertyType::ByteArray(ByteArrayPropertySizes { + min_size: inner_properties + .get_optional_integer(property_names::MIN_ITEMS)?, + max_size: inner_properties + .get_optional_integer(property_names::MAX_ITEMS)?, + }) + } } } else { return Err(DataContractError::InvalidContractStructure( diff --git a/packages/rs-dpp/src/data_contract/document_type/property/mod.rs b/packages/rs-dpp/src/data_contract/document_type/property/mod.rs index e3a4003239b..b4d69b8e071 100644 --- a/packages/rs-dpp/src/data_contract/document_type/property/mod.rs +++ b/packages/rs-dpp/src/data_contract/document_type/property/mod.rs @@ -28,14 +28,26 @@ pub struct DocumentProperty { pub required: bool, } +#[derive(Debug, PartialEq, Clone, Serialize)] +pub struct StringPropertySizes { + pub min_length: Option, + pub max_length: Option, +} + +#[derive(Debug, PartialEq, Clone, Serialize)] +pub struct ByteArrayPropertySizes { + pub min_size: Option, + pub max_size: Option, +} + // @append_only #[derive(Debug, PartialEq, Clone, Serialize)] pub enum DocumentPropertyType { ///Todo decompose integer Integer, Number, - String(Option, Option), // TODO use structure - ByteArray(Option, Option), // TODO user structure + String(StringPropertySizes), + ByteArray(ByteArrayPropertySizes), Identifier, Boolean, Date, @@ -62,8 +74,8 @@ impl DocumentPropertyType { match self { DocumentPropertyType::Integer => "integer".to_string(), DocumentPropertyType::Number => "number".to_string(), - DocumentPropertyType::String(_, _) => "string".to_string(), - DocumentPropertyType::ByteArray(_, _) => "byteArray".to_string(), + DocumentPropertyType::String(_) => "string".to_string(), + DocumentPropertyType::ByteArray(_) => "byteArray".to_string(), DocumentPropertyType::Identifier => "identifier".to_string(), DocumentPropertyType::Boolean => "boolean".to_string(), DocumentPropertyType::Date => "date".to_string(), @@ -77,13 +89,13 @@ impl DocumentPropertyType { match self { DocumentPropertyType::Integer => Some(8), DocumentPropertyType::Number => Some(8), - DocumentPropertyType::String(min_length, _) => match min_length { + DocumentPropertyType::String(sizes) => match sizes.min_length { None => Some(0), - Some(size) => Some(*size), + Some(size) => Some(size), }, - DocumentPropertyType::ByteArray(min_size, _) => match min_size { + DocumentPropertyType::ByteArray(sizes) => match sizes.min_size { None => Some(0), - Some(size) => Some(*size), + Some(size) => Some(size), }, DocumentPropertyType::Boolean => Some(1), DocumentPropertyType::Date => Some(8), @@ -101,13 +113,13 @@ impl DocumentPropertyType { match self { DocumentPropertyType::Integer => Some(8), DocumentPropertyType::Number => Some(8), - DocumentPropertyType::String(min_length, _) => match min_length { + DocumentPropertyType::String(sizes) => match sizes.min_length { None => Some(0), - Some(size) => Some(*size * 4), + Some(size) => Some(size * 4), }, - DocumentPropertyType::ByteArray(min_size, _) => match min_size { + DocumentPropertyType::ByteArray(sizes) => match sizes.min_size { None => Some(0), - Some(size) => Some(*size), + Some(size) => Some(size), }, DocumentPropertyType::Boolean => Some(1), DocumentPropertyType::Date => Some(8), @@ -125,13 +137,13 @@ impl DocumentPropertyType { match self { DocumentPropertyType::Integer => Some(8), DocumentPropertyType::Number => Some(8), - DocumentPropertyType::String(_, max_length) => match max_length { + DocumentPropertyType::String(sizes) => match sizes.max_length { None => Some(u16::MAX), - Some(size) => Some(*size * 4), + Some(size) => Some(size * 4), }, - DocumentPropertyType::ByteArray(_, max_size) => match max_size { + DocumentPropertyType::ByteArray(sizes) => match sizes.max_size { None => Some(u16::MAX), - Some(size) => Some(*size), + Some(size) => Some(size), }, DocumentPropertyType::Boolean => Some(1), DocumentPropertyType::Date => Some(8), @@ -149,13 +161,13 @@ impl DocumentPropertyType { match self { DocumentPropertyType::Integer => Some(8), DocumentPropertyType::Number => Some(8), - DocumentPropertyType::String(_, max_length) => match max_length { + DocumentPropertyType::String(sizes) => match sizes.max_length { None => Some(16383), - Some(size) => Some(*size), + Some(size) => Some(size), }, - DocumentPropertyType::ByteArray(_, max_size) => match max_size { + DocumentPropertyType::ByteArray(sizes) => match sizes.max_size { None => Some(u16::MAX), - Some(size) => Some(*size), + Some(size) => Some(size), }, DocumentPropertyType::Boolean => Some(1), DocumentPropertyType::Date => Some(8), @@ -231,7 +243,7 @@ impl DocumentPropertyType { match self { DocumentPropertyType::Integer => Value::I64(rng.gen::()), DocumentPropertyType::Number => Value::Float(rng.gen::()), - DocumentPropertyType::String(_, _) => { + DocumentPropertyType::String(_) => { let size = self.random_size(rng); Value::Text( rng.sample_iter(Alphanumeric) @@ -240,7 +252,7 @@ impl DocumentPropertyType { .collect(), ) } - DocumentPropertyType::ByteArray(_, _) => { + DocumentPropertyType::ByteArray(_) => { let size = self.random_size(rng); if self.min_size() == self.max_size() { match size { @@ -290,7 +302,7 @@ impl DocumentPropertyType { match self { DocumentPropertyType::Integer => Value::I64(rng.gen::()), DocumentPropertyType::Number => Value::Float(rng.gen::()), - DocumentPropertyType::String(_, _) => { + DocumentPropertyType::String(_) => { let size = self.min_size().unwrap(); Value::Text( rng.sample_iter(Alphanumeric) @@ -299,7 +311,7 @@ impl DocumentPropertyType { .collect(), ) } - DocumentPropertyType::ByteArray(_, _) => { + DocumentPropertyType::ByteArray(_) => { let size = self.min_size().unwrap(); Value::Bytes(rng.sample_iter(Standard).take(size as usize).collect()) } @@ -330,7 +342,7 @@ impl DocumentPropertyType { match self { DocumentPropertyType::Integer => Value::I64(rng.gen::()), DocumentPropertyType::Number => Value::Float(rng.gen::()), - DocumentPropertyType::String(_, _) => { + DocumentPropertyType::String(_) => { let size = self.max_size().unwrap(); Value::Text( rng.sample_iter(Alphanumeric) @@ -339,7 +351,7 @@ impl DocumentPropertyType { .collect(), ) } - DocumentPropertyType::ByteArray(_, _) => { + DocumentPropertyType::ByteArray(_) => { let size = self.max_size().unwrap(); Value::Bytes(rng.sample_iter(Standard).take(size as usize).collect()) } @@ -401,7 +413,7 @@ impl DocumentPropertyType { } } match self { - DocumentPropertyType::String(_, _) => { + DocumentPropertyType::String(_) => { let bytes = Self::read_varint_value(buf)?; let string = String::from_utf8(bytes).map_err(|_| { DataContractError::CorruptedSerialization( @@ -437,11 +449,11 @@ impl DocumentPropertyType { _ => Ok((Some(Value::Bool(true)), false)), } } - DocumentPropertyType::ByteArray(min, max) => { - match (min, max) { + DocumentPropertyType::ByteArray(sizes) => { + match (sizes.min_size, sizes.max_size) { (Some(min), Some(max)) if min == max => { // if min == max, then we don't need a varint for the length - let len = *min as usize; + let len = min as usize; let mut bytes = vec![0; len]; buf.read_exact(&mut bytes).map_err(|_| { DataContractError::DecodingContractError(DecodingError::new(format!( @@ -543,7 +555,7 @@ impl DocumentPropertyType { return Ok(vec![]); } match self { - DocumentPropertyType::String(_, _) => { + DocumentPropertyType::String(_) => { if let Value::Text(value) = value { let vec = value.into_bytes(); let mut r_vec = vec.len().encode_var_vec(); @@ -589,7 +601,7 @@ impl DocumentPropertyType { Ok(r_vec) } } - DocumentPropertyType::ByteArray(_, _) => { + DocumentPropertyType::ByteArray(_) => { let mut bytes = value.into_binary_bytes()?; let mut r_vec = bytes.len().encode_var_vec(); @@ -675,7 +687,7 @@ impl DocumentPropertyType { return Ok(vec![]); } return match self { - DocumentPropertyType::String(_, _) => { + DocumentPropertyType::String(_) => { let value_as_text = value.as_text().ok_or_else(get_field_type_matching_error)?; let vec = value_as_text.as_bytes().to_vec(); let mut r_vec = vec.len().encode_var_vec(); @@ -704,7 +716,7 @@ impl DocumentPropertyType { let value_as_f64 = value.to_float().map_err(ProtocolError::ValueError)?; Ok(value_as_f64.to_be_bytes().to_vec()) } - DocumentPropertyType::ByteArray(min, max) => match (min, max) { + DocumentPropertyType::ByteArray(sizes) => match (sizes.min_size, sizes.max_size) { (Some(min), Some(max)) if min == max => Ok(value.to_binary_bytes()?), _ => { let mut bytes = value.to_binary_bytes()?; @@ -786,7 +798,7 @@ impl DocumentPropertyType { return Ok(vec![]); } match self { - DocumentPropertyType::String(_, _) => { + DocumentPropertyType::String(_) => { let value_as_text = value.as_text().ok_or_else(get_field_type_matching_error)?; let vec = value_as_text.as_bytes().to_vec(); if vec.is_empty() { @@ -807,7 +819,7 @@ impl DocumentPropertyType { DocumentPropertyType::Number => Ok(Self::encode_float( value.to_float().map_err(ProtocolError::ValueError)?, )), - DocumentPropertyType::ByteArray(_, _) => { + DocumentPropertyType::ByteArray(_) => { value.to_binary_bytes().map_err(ProtocolError::ValueError) } DocumentPropertyType::Identifier => value @@ -839,16 +851,16 @@ impl DocumentPropertyType { // Given a field type and a value this function chooses and executes the right encoding method pub fn value_from_string(&self, str: &str) -> Result { match self { - DocumentPropertyType::String(min, max) => { - if let Some(min) = min { - if str.len() < *min as usize { + DocumentPropertyType::String(sizes) => { + if let Some(min) = sizes.min_length { + if str.len() < min as usize { return Err(DataContractError::FieldRequirementUnmet( "string is too small".to_string(), )); } } - if let Some(max) = max { - if str.len() > *max as usize { + if let Some(max) = sizes.max_length { + if str.len() > max as usize { return Err(DataContractError::FieldRequirementUnmet( "string is too big".to_string(), )); @@ -866,16 +878,16 @@ impl DocumentPropertyType { ) }) } - DocumentPropertyType::ByteArray(min, max) => { - if let Some(min) = min { - if str.len() / 2 < *min as usize { + DocumentPropertyType::ByteArray(sizes) => { + if let Some(min) = sizes.min_size { + if str.len() / 2 < min as usize { return Err(DataContractError::FieldRequirementUnmet( "byte array is too small".to_string(), )); } } - if let Some(max) = max { - if str.len() / 2 > *max as usize { + if let Some(max) = sizes.max_size { + if str.len() / 2 > max as usize { return Err(DataContractError::FieldRequirementUnmet( "byte array is too big".to_string(), )); diff --git a/packages/rs-dpp/src/data_contract/document_type/schema/find_identifier_and_binary_paths/v0/mod.rs b/packages/rs-dpp/src/data_contract/document_type/schema/find_identifier_and_binary_paths/v0/mod.rs index 35fb76650d1..3fc2259f7ef 100644 --- a/packages/rs-dpp/src/data_contract/document_type/schema/find_identifier_and_binary_paths/v0/mod.rs +++ b/packages/rs-dpp/src/data_contract/document_type/schema/find_identifier_and_binary_paths/v0/mod.rs @@ -32,7 +32,7 @@ impl DocumentTypeV0 { DocumentPropertyType::Identifier => { identifier_paths.insert(new_path); } - DocumentPropertyType::ByteArray(_, _) => { + DocumentPropertyType::ByteArray(_) => { binary_paths.insert(new_path); } DocumentPropertyType::Object(inner_properties) => { diff --git a/packages/rs-dpp/src/data_contract/document_type/v0/random_document_type.rs b/packages/rs-dpp/src/data_contract/document_type/v0/random_document_type.rs index 3e46c291ea1..35649093130 100644 --- a/packages/rs-dpp/src/data_contract/document_type/v0/random_document_type.rs +++ b/packages/rs-dpp/src/data_contract/document_type/v0/random_document_type.rs @@ -106,6 +106,7 @@ use crate::data_contract::document_type::v0::StatelessJsonSchemaLazyValidator; use crate::data_contract::document_type::{ v0::DocumentTypeV0, DocumentProperty, DocumentPropertyType, DocumentType, Index, }; +use crate::data_contract::document_type::{ByteArrayPropertySizes, StringPropertySizes}; use crate::document::transfer::Transferable; use crate::identity::SecurityLevel; use crate::nft::TradeMode; @@ -145,14 +146,17 @@ impl DocumentTypeV0 { let random_weight = rng.gen_range(0..total_weight); let document_type = if random_weight < field_weights.string_weight { let has_min_len = rng.gen_bool(parameters.field_bounds.string_has_min_len_chance); - let min_len = if has_min_len { + let min_length = if has_min_len { Some(rng.gen_range(parameters.field_bounds.string_min_len.clone())) } else { None }; // If a string property is used in an index it must have maxLength 63 or less (v1.0-dev) - let max_len = Some(63); - DocumentPropertyType::String(min_len, max_len) + let max_length = Some(63); + DocumentPropertyType::String(StringPropertySizes { + min_length, + max_length, + }) } else if random_weight < field_weights.string_weight + field_weights.integer_weight { DocumentPropertyType::Integer } else if random_weight @@ -179,14 +183,14 @@ impl DocumentTypeV0 { } else { let has_min_len = rng.gen_bool(parameters.field_bounds.byte_array_has_min_len_chance); - let min_len = if has_min_len { + let min_size = if has_min_len { Some(rng.gen_range(parameters.field_bounds.byte_array_min_len.clone())) } else { None }; // Indexed arrays must have maxItems 255 or less (v1.0-dev) - let max_len = Some(255); - DocumentPropertyType::ByteArray(min_len, max_len) + let max_size = Some(255); + DocumentPropertyType::ByteArray(ByteArrayPropertySizes { min_size, max_size }) }; DocumentProperty { @@ -263,14 +267,14 @@ impl DocumentTypeV0 { let mut position_counter = 0; let properties_json_schema = properties.iter().map(|(key, prop)| { let mut schema_part = match &prop.property_type { - DocumentPropertyType::String(min, max) => { + DocumentPropertyType::String(sizes) => { let mut schema = serde_json::Map::new(); schema.insert("type".to_string(), serde_json::Value::String("string".to_owned())); - if let Some(min_len) = min { - schema.insert("minLength".to_string(), serde_json::Value::Number(serde_json::Number::from(*min_len))); + if let Some(min_len) = sizes.min_length { + schema.insert("minLength".to_string(), serde_json::Value::Number(serde_json::Number::from(min_len))); } - if let Some(max_len) = max { - schema.insert("maxLength".to_string(), serde_json::Value::Number(serde_json::Number::from(*max_len))); + if let Some(max_len) = sizes.max_length { + schema.insert("maxLength".to_string(), serde_json::Value::Number(serde_json::Number::from(max_len))); } serde_json::Value::Object(schema) }, @@ -305,14 +309,14 @@ impl DocumentTypeV0 { DocumentPropertyType::Boolean => { serde_json::json!({"type": "boolean"}) }, - DocumentPropertyType::ByteArray(min, max) => { + DocumentPropertyType::ByteArray(sizes) => { let mut schema = serde_json::Map::new(); schema.insert("type".to_string(), serde_json::Value::String("array".to_owned())); - if let Some(min_len) = min { - schema.insert("minItems".to_string(), serde_json::Value::Number(serde_json::Number::from(*min_len))); + if let Some(min_len) = sizes.min_size { + schema.insert("minItems".to_string(), serde_json::Value::Number(serde_json::Number::from(min_len))); } - if let Some(max_len) = max { - schema.insert("maxItems".to_string(), serde_json::Value::Number(serde_json::Number::from(*max_len))); + if let Some(max_len) = sizes.max_size { + schema.insert("maxItems".to_string(), serde_json::Value::Number(serde_json::Number::from(max_len))); } schema.insert("byteArray".to_string(), serde_json::Value::Bool(true)); serde_json::Value::Object(schema) @@ -463,14 +467,17 @@ impl DocumentTypeV0 { let random_weight = rng.gen_range(0..total_weight); let document_type = if random_weight < field_weights.string_weight { let has_min_len = rng.gen_bool(parameters.field_bounds.string_has_min_len_chance); - let min_len = if has_min_len { + let min_length = if has_min_len { Some(rng.gen_range(parameters.field_bounds.string_min_len.clone())) } else { None }; // If a string property is used in an index it must have maxLength 63 or less (v1.0-dev) - let max_len = Some(63); - DocumentPropertyType::String(min_len, max_len) + let max_length = Some(63); + DocumentPropertyType::String(StringPropertySizes { + min_length, + max_length, + }) } else if random_weight < field_weights.string_weight + field_weights.integer_weight { DocumentPropertyType::Integer } else if random_weight @@ -497,14 +504,14 @@ impl DocumentTypeV0 { } else { let has_min_len = rng.gen_bool(parameters.field_bounds.byte_array_has_min_len_chance); - let min_len = if has_min_len { + let min_size = if has_min_len { Some(rng.gen_range(parameters.field_bounds.byte_array_min_len.clone())) } else { None }; // Indexed arrays must have maxItems 255 or less (v1.0-dev) - let max_len = Some(255); - DocumentPropertyType::ByteArray(min_len, max_len) + let max_size = Some(255); + DocumentPropertyType::ByteArray(ByteArrayPropertySizes { min_size, max_size }) }; DocumentProperty { diff --git a/packages/rs-dpp/src/data_contract/errors/contract.rs b/packages/rs-dpp/src/data_contract/errors/contract.rs index 5b152a0a6b1..32989597a00 100644 --- a/packages/rs-dpp/src/data_contract/errors/contract.rs +++ b/packages/rs-dpp/src/data_contract/errors/contract.rs @@ -3,7 +3,6 @@ use crate::consensus::basic::decode::DecodingError; use crate::consensus::basic::BasicError; use bincode::{Decode, Encode}; use platform_serialization_derive::{PlatformDeserialize, PlatformSerialize}; -use platform_value::Identifier; use thiserror::Error; use crate::consensus::basic::document::InvalidDocumentTypeError; diff --git a/packages/rs-dpp/src/errors/consensus/basic/identity/invalid_instant_asset_lock_proof_signature_error.rs b/packages/rs-dpp/src/errors/consensus/basic/identity/invalid_instant_asset_lock_proof_signature_error.rs index 130349d16a8..8d72de7772b 100644 --- a/packages/rs-dpp/src/errors/consensus/basic/identity/invalid_instant_asset_lock_proof_signature_error.rs +++ b/packages/rs-dpp/src/errors/consensus/basic/identity/invalid_instant_asset_lock_proof_signature_error.rs @@ -18,7 +18,7 @@ use bincode::{Decode, Encode}; PlatformSerialize, PlatformDeserialize, )] -#[error("Invalid instant lock proof signature")] +#[error("Instant lock proof signature is invalid or wasn't created recently. Pleases try chain asset lock proof instead.")] #[platform_serialize(unversioned)] pub struct InvalidInstantAssetLockProofSignatureError; diff --git a/packages/rs-dpp/src/tests/fixtures/identity_fixture.rs b/packages/rs-dpp/src/tests/fixtures/identity_fixture.rs index b0e92a5850d..b8ff26652ab 100644 --- a/packages/rs-dpp/src/tests/fixtures/identity_fixture.rs +++ b/packages/rs-dpp/src/tests/fixtures/identity_fixture.rs @@ -1,10 +1,9 @@ use crate::identity::identity_public_key::v0::IdentityPublicKeyV0; -use crate::identity::{IdentityPublicKey, IdentityV0, KeyType, Purpose, SecurityLevel}; +use crate::identity::{IdentityV0, KeyType, Purpose, SecurityLevel}; use platform_value::platform_value; use platform_value::string_encoding::Encoding; use platform_value::BinaryData; use serde_json::json; -use std::collections::BTreeMap; use crate::prelude::{Identifier, Identity}; diff --git a/packages/rs-drive-abci/.env.local b/packages/rs-drive-abci/.env.local index 5b1026eb48e..c1b8a3647e0 100644 --- a/packages/rs-drive-abci/.env.local +++ b/packages/rs-drive-abci/.env.local @@ -33,13 +33,24 @@ CORE_CHECK_TX_JSON_RPC_PASSWORD=password INITIAL_CORE_CHAINLOCKED_HEIGHT=1243 # https://github.com/dashevo/dashcore-lib/blob/286c33a9d29d33f05d874c47a9b33764a0be0cf1/lib/constants/index.js#L42-L57 -VALIDATOR_SET_QUORUM_TYPE=llmq_test +VALIDATOR_SET_QUORUM_TYPE=llmq_test_platform VALIDATOR_SET_QUORUM_SIZE=3 +VALIDATOR_SET_QUORUM_WINDOW=24 +VALIDATOR_SET_QUORUM_ACTIVE_SIGNERS=2 +VALIDATOR_SET_QUORUM_ROTATION=false VALIDATOR_SET_ROTATION_BLOCK_COUNT=64 CHAIN_LOCK_QUORUM_TYPE=llmq_test -CHAIN_LOCK_QUORUM_WINDOW=24 CHAIN_LOCK_QUORUM_SIZE=3 +CHAIN_LOCK_QUORUM_WINDOW=24 +CHAIN_LOCK_QUORUM_ACTIVE_SIGNERS=2 +CHAIN_LOCK_QUORUM_ROTATION=false + +INSTANT_LOCK_QUORUM_TYPE=llmq_test_instantsend +INSTANT_LOCK_QUORUM_SIZE=3 +INSTANT_LOCK_QUORUM_WINDOW=24 +INSTANT_LOCK_QUORUM_ACTIVE_SIGNERS=2 +INSTANT_LOCK_QUORUM_ROTATION=false # DPNS Contract diff --git a/packages/rs-drive-abci/.env.mainnet b/packages/rs-drive-abci/.env.mainnet index 527b55709c6..1b4bab0298b 100644 --- a/packages/rs-drive-abci/.env.mainnet +++ b/packages/rs-drive-abci/.env.mainnet @@ -35,10 +35,22 @@ INITIAL_CORE_CHAINLOCKED_HEIGHT=1243 # https://github.com/dashevo/dashcore-lib/blob/286c33a9d29d33f05d874c47a9b33764a0be0cf1/lib/constants/index.js#L42-L57 VALIDATOR_SET_QUORUM_TYPE=llmq_100_67 VALIDATOR_SET_QUORUM_SIZE=100 +VALIDATOR_SET_QUORUM_WINDOW=24 +VALIDATOR_SET_QUORUM_ACTIVE_SIGNERS=24 +VALIDATOR_SET_QUORUM_ROTATION=false VALIDATOR_SET_ROTATION_BLOCK_COUNT=64 CHAIN_LOCK_QUORUM_TYPE=llmq_400_60 +CHAIN_LOCK_QUORUM_SIZE=400 CHAIN_LOCK_QUORUM_WINDOW=288 +CHAIN_LOCK_QUORUM_ACTIVE_SIGNERS=4 +CHAIN_LOCK_QUORUM_ROTATION=false + +INSTANT_LOCK_QUORUM_TYPE=llmq_60_75 +INSTANT_LOCK_QUORUM_SIZE=60 +INSTANT_LOCK_QUORUM_WINDOW=288 +INSTANT_LOCK_QUORUM_ACTIVE_SIGNERS=32 +INSTANT_LOCK_QUORUM_ROTATION=true # DPNS Contract diff --git a/packages/rs-drive-abci/.env.testnet b/packages/rs-drive-abci/.env.testnet index 0179d1c2aca..0a278952efb 100644 --- a/packages/rs-drive-abci/.env.testnet +++ b/packages/rs-drive-abci/.env.testnet @@ -35,10 +35,22 @@ INITIAL_CORE_CHAINLOCKED_HEIGHT=1243 # https://github.com/dashevo/dashcore-lib/blob/286c33a9d29d33f05d874c47a9b33764a0be0cf1/lib/constants/index.js#L42-L57 VALIDATOR_SET_QUORUM_TYPE=llmq_25_67 VALIDATOR_SET_QUORUM_SIZE=25 +VALIDATOR_SET_QUORUM_WINDOW=24 +VALIDATOR_SET_QUORUM_ACTIVE_SIGNERS=24 +VALIDATOR_SET_QUORUM_ROTATION=false VALIDATOR_SET_ROTATION_BLOCK_COUNT=64 CHAIN_LOCK_QUORUM_TYPE=llmq_50_60 +CHAIN_LOCK_QUORUM_SIZE=50 CHAIN_LOCK_QUORUM_WINDOW=24 +CHAIN_LOCK_QUORUM_ACTIVE_SIGNERS=24 +CHAIN_LOCK_QUORUM_ROTATION=false + +INSTANT_LOCK_QUORUM_TYPE=llmq_60_75 +INSTANT_LOCK_QUORUM_SIZE=50 +INSTANT_LOCK_QUORUM_WINDOW=288 +INSTANT_LOCK_QUORUM_ACTIVE_SIGNERS=32 +INSTANT_LOCK_QUORUM_ROTATION=true # DPNS Contract diff --git a/packages/rs-drive-abci/Cargo.toml b/packages/rs-drive-abci/Cargo.toml index 8b1281b271e..eb01bfd39d8 100644 --- a/packages/rs-drive-abci/Cargo.toml +++ b/packages/rs-drive-abci/Cargo.toml @@ -99,6 +99,7 @@ dpp = { path = "../rs-dpp", features = [ drive = { path = "../rs-drive" } strategy-tests = { path = "../strategy-tests" } assert_matches = "1.5.0" +drive-abci = { path = ".", features = ["testing-config"]} # For tests of grovedb verify rocksdb = { version = "0.22.0" } @@ -109,7 +110,7 @@ integer-encoding = { version = "4.0.0" } default = ["mocks", "console"] mocks = ["mockall", "drive/fixtures-and-mocks"] console = ["console-subscriber", "tokio/tracing"] - +testing-config = [] [[bin]] name = "drive-abci" diff --git a/packages/rs-drive-abci/src/config.rs b/packages/rs-drive-abci/src/config.rs index d9ab80e9975..e9d2913b001 100644 --- a/packages/rs-drive-abci/src/config.rs +++ b/packages/rs-drive-abci/src/config.rs @@ -26,6 +26,7 @@ // IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER // DEALINGS IN THE SOFTWARE. +use bincode::{Decode, Encode}; use dashcore_rpc::json::QuorumType; use std::path::PathBuf; @@ -122,6 +123,7 @@ pub struct ExecutionConfig { #[serde(default = "ExecutionConfig::default_verify_sum_trees")] pub verify_sum_trees: bool, + // TODO: Move to ValidatorSetConfig /// How often should quorums change? #[serde( default = "ExecutionConfig::default_validator_set_rotation_block_count", @@ -199,21 +201,16 @@ pub struct PlatformConfig { pub execution: ExecutionConfig, /// The default quorum type - pub validator_set_quorum_type: String, - - /// The quorum type used for verifying chain locks - pub chain_lock_quorum_type: String, - - /// The validator set quorum size - pub validator_set_quorum_size: u16, + #[serde(flatten)] + pub validator_set: ValidatorSetConfig, - /// The chain lock quorum size - pub chain_lock_quorum_size: u16, + /// Chain lock configuration + #[serde(flatten)] + pub chain_lock: ChainLockConfig, - /// The window for chain locks - /// On Mainnet Chain Locks are signed using 400_60: One quorum in every 288 blocks and activeQuorumCount is 4. - /// On Testnet Chain Locks are signed using 50_60: One quorum in every 24 blocks and activeQuorumCount is 24. - pub chain_lock_quorum_window: u32, + /// Instant lock configuration + #[serde(flatten)] + pub instant_lock: InstantLockConfig, // todo: this should probably be coming from Tenderdash config. It's a test only param /// Approximately how often are blocks produced @@ -233,7 +230,7 @@ pub struct PlatformConfig { #[serde(default)] pub rejections_path: Option, - // todo: put this in tests like #[cfg(test)] + #[cfg(feature = "testing-config")] /// This should be None, except in the case of Testing platform #[serde(skip)] pub testing_configs: PlatformTestConfig, @@ -250,6 +247,317 @@ pub struct PlatformConfig { pub tokio_console_retention_secs: u64, } +/// A config suitable for a quorum configuration +pub trait QuorumLikeConfig: Sized { + /// Quorum type + fn quorum_type(&self) -> QuorumType; + + /// Quorum size + fn quorum_size(&self) -> u16; + + /// Quorum DKG interval + fn quorum_window(&self) -> u32; + + /// Quorum active signers count + fn quorum_active_signers(&self) -> u16; + + /// Quorum rotation (dip24) or classic + fn quorum_rotation(&self) -> bool; +} + +/// Chain Lock quorum configuration +#[derive(Clone, Debug, Serialize, Deserialize, Encode, Decode)] +pub struct ValidatorSetConfig { + /// The quorum type used for verifying chain locks + #[serde( + rename = "validator_set_quorum_type", + serialize_with = "serialize_quorum_type", + deserialize_with = "deserialize_quorum_type" + )] + pub quorum_type: QuorumType, + + /// The quorum size + #[serde( + rename = "validator_set_quorum_size", + deserialize_with = "from_str_or_number" + )] + pub quorum_size: u16, + + /// The quorum window (DKG interval) + /// On Mainnet Chain Locks are signed using 400_60: One quorum in every 288 blocks and activeQuorumCount is 4. + /// On Testnet Chain Locks are signed using 50_60: One quorum in every 24 blocks and activeQuorumCount is 24. + #[serde( + rename = "validator_set_quorum_window", + deserialize_with = "from_str_or_number" + )] + pub quorum_window: u32, + + /// The number of active signers + #[serde( + rename = "validator_set_quorum_active_signers", + deserialize_with = "from_str_or_number" + )] + pub quorum_active_signers: u16, + + /// Whether the quorum is rotated DIP24 or classic + #[serde( + rename = "validator_set_quorum_rotation", + deserialize_with = "from_str_or_number" + )] + pub quorum_rotation: bool, +} + +impl Default for ValidatorSetConfig { + fn default() -> Self { + // Mainnet + Self::default_100_67() + } +} + +impl ValidatorSetConfig { + /// Creates a default config for LLMQ 100 67 + pub fn default_100_67() -> Self { + Self { + quorum_type: QuorumType::Llmq100_67, + quorum_size: 100, + quorum_window: 24, + quorum_active_signers: 24, + quorum_rotation: false, + } + } +} + +impl QuorumLikeConfig for ValidatorSetConfig { + fn quorum_type(&self) -> QuorumType { + self.quorum_type + } + + fn quorum_size(&self) -> u16 { + self.quorum_size + } + + fn quorum_window(&self) -> u32 { + self.quorum_window + } + + fn quorum_active_signers(&self) -> u16 { + self.quorum_active_signers + } + + fn quorum_rotation(&self) -> bool { + self.quorum_rotation + } +} + +/// Chain Lock quorum configuration +#[derive(Clone, Debug, Serialize, Deserialize, Encode, Decode)] +pub struct ChainLockConfig { + /// The quorum type used for verifying chain locks + #[serde( + rename = "chain_lock_quorum_type", + serialize_with = "serialize_quorum_type", + deserialize_with = "deserialize_quorum_type" + )] + pub quorum_type: QuorumType, + + /// The quorum size + #[serde( + rename = "chain_lock_quorum_size", + deserialize_with = "from_str_or_number" + )] + pub quorum_size: u16, + + /// The quorum window (DKG interval) + /// On Mainnet Chain Locks are signed using 400_60: One quorum in every 288 blocks and activeQuorumCount is 4. + /// On Testnet Chain Locks are signed using 50_60: One quorum in every 24 blocks and activeQuorumCount is 24. + #[serde( + rename = "chain_lock_quorum_window", + deserialize_with = "from_str_or_number" + )] + pub quorum_window: u32, + + /// The number of active signers + #[serde( + rename = "chain_lock_quorum_active_signers", + deserialize_with = "from_str_or_number" + )] + pub quorum_active_signers: u16, + + /// Whether the quorum is rotated DIP24 or classic + #[serde( + rename = "chain_lock_quorum_rotation", + deserialize_with = "from_str_or_number" + )] + pub quorum_rotation: bool, +} + +impl Default for ChainLockConfig { + fn default() -> Self { + // Mainnet + Self { + quorum_type: QuorumType::Llmq400_60, + quorum_size: 400, + quorum_window: 24 * 12, + quorum_active_signers: 4, + quorum_rotation: false, + } + } +} + +impl QuorumLikeConfig for ChainLockConfig { + fn quorum_type(&self) -> QuorumType { + self.quorum_type + } + + fn quorum_size(&self) -> u16 { + self.quorum_size + } + + fn quorum_window(&self) -> u32 { + self.quorum_window + } + + fn quorum_active_signers(&self) -> u16 { + self.quorum_active_signers + } + + fn quorum_rotation(&self) -> bool { + self.quorum_rotation + } +} + +impl ChainLockConfig { + /// Creates a default config for LLMQ 100 67 + pub fn default_100_67() -> Self { + Self { + quorum_type: QuorumType::Llmq100_67, + quorum_size: 100, + quorum_window: 24, + quorum_active_signers: 24, + quorum_rotation: false, + } + } +} + +/// Chain Lock quorum configuration +#[derive(Clone, Debug, Serialize, Deserialize, Encode, Decode)] +pub struct InstantLockConfig { + /// The quorum type used for verifying chain locks + #[serde( + rename = "instant_lock_quorum_type", + serialize_with = "serialize_quorum_type", + deserialize_with = "deserialize_quorum_type" + )] + pub quorum_type: QuorumType, + + /// The quorum size + #[serde( + rename = "instant_lock_quorum_size", + deserialize_with = "from_str_or_number" + )] + pub quorum_size: u16, + + /// The quorum window (DKG interval) + /// On Mainnet Chain Locks are signed using 400_60: One quorum in every 288 blocks and activeQuorumCount is 4. + /// On Testnet Chain Locks are signed using 50_60: One quorum in every 24 blocks and activeQuorumCount is 24. + #[serde( + rename = "instant_lock_quorum_window", + deserialize_with = "from_str_or_number" + )] + pub quorum_window: u32, + + /// The number of active signers + #[serde( + rename = "instant_lock_quorum_active_signers", + deserialize_with = "from_str_or_number" + )] + pub quorum_active_signers: u16, + + /// Whether the quorum is rotated DIP24 or classic + #[serde( + rename = "instant_lock_quorum_rotation", + deserialize_with = "from_str_or_number" + )] + pub quorum_rotation: bool, +} + +impl Default for InstantLockConfig { + fn default() -> Self { + // Mainnet + Self { + quorum_type: QuorumType::Llmq60_75, + quorum_active_signers: 32, + quorum_size: 60, + quorum_window: 24 * 12, + quorum_rotation: true, + } + } +} + +impl InstantLockConfig { + /// Creates a default config for LLMQ 100 67 + pub fn default_100_67() -> Self { + Self { + quorum_type: QuorumType::Llmq100_67, + quorum_size: 100, + quorum_window: 24, + quorum_active_signers: 24, + quorum_rotation: false, + } + } +} + +impl QuorumLikeConfig for InstantLockConfig { + fn quorum_type(&self) -> QuorumType { + self.quorum_type + } + + fn quorum_size(&self) -> u16 { + self.quorum_size + } + + fn quorum_window(&self) -> u32 { + self.quorum_window + } + + fn quorum_active_signers(&self) -> u16 { + self.quorum_active_signers + } + + fn quorum_rotation(&self) -> bool { + self.quorum_rotation + } +} + +fn serialize_quorum_type(quorum_type: &QuorumType, serializer: S) -> Result +where + S: serde::Serializer, +{ + serializer.serialize_str(quorum_type.to_string().as_str()) +} + +fn deserialize_quorum_type<'de, D>(deserializer: D) -> Result +where + D: serde::Deserializer<'de>, +{ + let quorum_type_name = String::deserialize(deserializer)?; + + let quorum_type = if let Ok(t) = quorum_type_name.trim().parse::() { + QuorumType::from(t) + } else { + QuorumType::from(quorum_type_name.as_str()) + }; + + if quorum_type == QuorumType::UNKNOWN { + return Err(serde::de::Error::custom(format!( + "unsupported QUORUM_TYPE: {}", + quorum_type_name + ))); + }; + + Ok(quorum_type) +} + impl ExecutionConfig { fn default_verify_sum_trees() -> bool { true @@ -280,43 +588,8 @@ impl PlatformConfig { fn default_tokio_console_retention_secs() -> u64 { 60 * 3 } - - /// Return type of quorum - pub fn validator_set_quorum_type(&self) -> QuorumType { - let found = if let Ok(t) = self.validator_set_quorum_type.trim().parse::() { - QuorumType::from(t) - } else { - QuorumType::from(self.validator_set_quorum_type.as_str()) - }; - - if found == QuorumType::UNKNOWN { - panic!( - "config: unsupported QUORUM_TYPE: {}", - self.validator_set_quorum_type - ); - } - - found - } - - /// Return type of quorum for validating chain locks - pub fn chain_lock_quorum_type(&self) -> QuorumType { - let found = if let Ok(t) = self.chain_lock_quorum_type.trim().parse::() { - QuorumType::from(t) - } else { - QuorumType::from(self.chain_lock_quorum_type.as_str()) - }; - - if found == QuorumType::UNKNOWN { - panic!( - "config: unsupported QUORUM_TYPE: {}", - self.chain_lock_quorum_type - ); - } - - found - } } + /// create new object using values from environment variables pub trait FromEnv { /// create new object using values from environment variables @@ -362,11 +635,27 @@ impl Default for PlatformConfig { impl PlatformConfig { pub fn default_local() -> Self { Self { - validator_set_quorum_type: "llmq_test_platform".to_string(), - chain_lock_quorum_type: "llmq_test".to_string(), - validator_set_quorum_size: 3, - chain_lock_quorum_size: 3, - chain_lock_quorum_window: 24, + validator_set: ValidatorSetConfig { + quorum_type: QuorumType::LlmqTestPlatform, + quorum_size: 3, + quorum_window: 24, + quorum_active_signers: 2, + quorum_rotation: false, + }, + chain_lock: ChainLockConfig { + quorum_type: QuorumType::LlmqTest, + quorum_active_signers: 2, + quorum_size: 3, + quorum_window: 24, + quorum_rotation: false, + }, + instant_lock: InstantLockConfig { + quorum_type: QuorumType::LlmqTest, + quorum_active_signers: 2, + quorum_size: 3, + quorum_window: 24, + quorum_rotation: false, + }, block_spacing_ms: 5000, drive: Default::default(), abci: Default::default(), @@ -374,6 +663,7 @@ impl PlatformConfig { execution: Default::default(), db_path: PathBuf::from("/var/lib/dash-platform/data"), rejections_path: Some(PathBuf::from("/var/log/dash/rejected")), + #[cfg(feature = "testing-config")] testing_configs: PlatformTestConfig::default(), tokio_console_enabled: false, tokio_console_address: PlatformConfig::default_tokio_console_address(), @@ -386,11 +676,27 @@ impl PlatformConfig { pub fn default_testnet() -> Self { Self { - validator_set_quorum_type: "llmq_25_67".to_string(), - chain_lock_quorum_type: "llmq_50_60".to_string(), - validator_set_quorum_size: 25, - chain_lock_quorum_size: 50, - chain_lock_quorum_window: 24, + validator_set: ValidatorSetConfig { + quorum_type: QuorumType::Llmq25_67, + quorum_size: 25, + quorum_window: 24, + quorum_active_signers: 24, + quorum_rotation: false, + }, + chain_lock: ChainLockConfig { + quorum_type: QuorumType::Llmq50_60, + quorum_active_signers: 24, + quorum_size: 50, + quorum_window: 24, + quorum_rotation: false, + }, + instant_lock: InstantLockConfig { + quorum_type: QuorumType::Llmq60_75, + quorum_active_signers: 32, + quorum_size: 60, + quorum_window: 24 * 12, + quorum_rotation: true, + }, block_spacing_ms: 5000, drive: Default::default(), abci: Default::default(), @@ -398,6 +704,7 @@ impl PlatformConfig { execution: Default::default(), db_path: PathBuf::from("/var/lib/dash-platform/data"), rejections_path: Some(PathBuf::from("/var/log/dash/rejected")), + #[cfg(feature = "testing-config")] testing_configs: PlatformTestConfig::default(), initial_protocol_version: Self::default_initial_protocol_version(), prometheus_bind_address: None, @@ -410,11 +717,27 @@ impl PlatformConfig { pub fn default_mainnet() -> Self { Self { - validator_set_quorum_type: "llmq_100_67".to_string(), - chain_lock_quorum_type: "llmq_400_60".to_string(), - validator_set_quorum_size: 100, - chain_lock_quorum_size: 400, - chain_lock_quorum_window: 288, + validator_set: ValidatorSetConfig { + quorum_type: QuorumType::Llmq100_67, + quorum_size: 100, + quorum_window: 24, + quorum_active_signers: 24, + quorum_rotation: false, + }, + chain_lock: ChainLockConfig { + quorum_type: QuorumType::Llmq400_60, + quorum_active_signers: 4, + quorum_size: 400, + quorum_window: 24 * 12, + quorum_rotation: false, + }, + instant_lock: InstantLockConfig { + quorum_type: QuorumType::Llmq60_75, + quorum_active_signers: 32, + quorum_size: 60, + quorum_window: 24 * 12, + quorum_rotation: true, + }, block_spacing_ms: 5000, drive: Default::default(), abci: Default::default(), @@ -422,6 +745,7 @@ impl PlatformConfig { execution: Default::default(), db_path: PathBuf::from("/var/lib/dash-platform/data"), rejections_path: Some(PathBuf::from("/var/log/dash/rejected")), + #[cfg(feature = "testing-config")] testing_configs: PlatformTestConfig::default(), initial_protocol_version: Self::default_initial_protocol_version(), prometheus_bind_address: None, @@ -433,30 +757,37 @@ impl PlatformConfig { } } +#[cfg(feature = "testing-config")] /// Configs that should only happen during testing -#[derive(Clone, Debug, Serialize, Deserialize)] +#[derive(Clone, Debug)] pub struct PlatformTestConfig { /// Block signing pub block_signing: bool, /// Block signature verification pub block_commit_signature_verification: bool, + /// Disable instant lock signature verification + pub disable_instant_lock_signature_verification: bool, } +#[cfg(feature = "testing-config")] impl PlatformTestConfig { /// Much faster config for tests pub fn default_with_no_block_signing() -> Self { Self { block_signing: false, block_commit_signature_verification: false, + disable_instant_lock_signature_verification: false, } } } +#[cfg(feature = "testing-config")] impl Default for PlatformTestConfig { fn default() -> Self { Self { block_signing: true, block_commit_signature_verification: true, + disable_instant_lock_signature_verification: false, } } } @@ -492,7 +823,7 @@ mod tests { let config = super::PlatformConfig::from_env().expect("expected config from env"); assert!(config.execution.verify_sum_trees); - assert_ne!(config.validator_set_quorum_type(), QuorumType::UNKNOWN); + assert_ne!(config.validator_set.quorum_type, QuorumType::UNKNOWN); for id in vectors { matches!(config.abci.log[id.0].destination, LogDestination::Bytes); } diff --git a/packages/rs-drive-abci/src/execution/check_tx/v0/mod.rs b/packages/rs-drive-abci/src/execution/check_tx/v0/mod.rs index 1b3d1999622..1eec9fb8bd4 100644 --- a/packages/rs-drive-abci/src/execution/check_tx/v0/mod.rs +++ b/packages/rs-drive-abci/src/execution/check_tx/v0/mod.rs @@ -197,7 +197,7 @@ where #[cfg(test)] mod tests { - use crate::config::PlatformConfig; + use crate::config::{PlatformConfig, PlatformTestConfig}; use crate::platform_types::event_execution_result::EventExecutionResult::{ SuccessfulPaidExecution, UnpaidConsensusExecutionError, UnsuccessfulPaidExecution, }; @@ -269,14 +269,17 @@ mod tests { #[test] #[ignore] fn verify_check_tx_on_data_contract_create() { - let mut platform = TestPlatformBuilder::new() - .with_config(PlatformConfig::default()) - .build_with_mock_rpc(); + let platform_config = PlatformConfig { + testing_configs: PlatformTestConfig { + disable_instant_lock_signature_verification: true, + ..Default::default() + }, + ..Default::default() + }; - platform - .core_rpc - .expect_verify_instant_lock() - .returning(|_, _| Ok(true)); + let platform = TestPlatformBuilder::new() + .with_config(platform_config) + .build_with_mock_rpc(); let platform_state = platform.state.load(); let protocol_version = platform_state.current_protocol_version_in_consensus(); @@ -370,14 +373,17 @@ mod tests { #[test] fn data_contract_create_check_tx() { - let mut platform = TestPlatformBuilder::new() - .with_config(PlatformConfig::default()) - .build_with_mock_rpc(); + let platform_config = PlatformConfig { + testing_configs: PlatformTestConfig { + disable_instant_lock_signature_verification: true, + ..Default::default() + }, + ..Default::default() + }; - platform - .core_rpc - .expect_verify_instant_lock() - .returning(|_, _| Ok(true)); + let platform = TestPlatformBuilder::new() + .with_config(platform_config) + .build_with_mock_rpc(); let platform_state = platform.state.load(); let protocol_version = platform_state.current_protocol_version_in_consensus(); @@ -515,14 +521,17 @@ mod tests { #[test] fn data_contract_create_check_tx_for_invalid_contract() { - let mut platform = TestPlatformBuilder::new() - .with_config(PlatformConfig::default()) - .build_with_mock_rpc(); + let platform_config = PlatformConfig { + testing_configs: PlatformTestConfig { + disable_instant_lock_signature_verification: true, + ..Default::default() + }, + ..Default::default() + }; - platform - .core_rpc - .expect_verify_instant_lock() - .returning(|_, _| Ok(true)); + let platform = TestPlatformBuilder::new() + .with_config(platform_config) + .build_with_mock_rpc(); let platform_state = platform.state.load(); let protocol_version = platform_state.current_protocol_version_in_consensus(); @@ -721,14 +730,17 @@ mod tests { #[test] fn data_contract_create_check_tx_priority() { - let mut platform = TestPlatformBuilder::new() - .with_config(PlatformConfig::default()) - .build_with_mock_rpc(); + let platform_config = PlatformConfig { + testing_configs: PlatformTestConfig { + disable_instant_lock_signature_verification: true, + ..Default::default() + }, + ..Default::default() + }; - platform - .core_rpc - .expect_verify_instant_lock() - .returning(|_, _| Ok(true)); + let platform = TestPlatformBuilder::new() + .with_config(platform_config) + .build_with_mock_rpc(); let platform_state = platform.state.load(); let protocol_version = platform_state.current_protocol_version_in_consensus(); @@ -873,14 +885,17 @@ mod tests { #[test] fn data_contract_create_check_tx_after_identity_balance_used_up() { - let mut platform = TestPlatformBuilder::new() - .with_config(PlatformConfig::default()) - .build_with_mock_rpc(); + let platform_config = PlatformConfig { + testing_configs: PlatformTestConfig { + disable_instant_lock_signature_verification: true, + ..Default::default() + }, + ..Default::default() + }; - platform - .core_rpc - .expect_verify_instant_lock() - .returning(|_, _| Ok(true)); + let platform = TestPlatformBuilder::new() + .with_config(platform_config) + .build_with_mock_rpc(); let platform_state = platform.state.load(); let protocol_version = platform_state.current_protocol_version_in_consensus(); @@ -1004,14 +1019,17 @@ mod tests { #[test] fn data_contract_update_check_tx() { - let mut platform = TestPlatformBuilder::new() - .with_config(PlatformConfig::default()) - .build_with_mock_rpc(); + let platform_config = PlatformConfig { + testing_configs: PlatformTestConfig { + disable_instant_lock_signature_verification: true, + ..Default::default() + }, + ..Default::default() + }; - platform - .core_rpc - .expect_verify_instant_lock() - .returning(|_, _| Ok(true)); + let platform = TestPlatformBuilder::new() + .with_config(platform_config) + .build_with_mock_rpc(); let platform_state = platform.state.load(); let protocol_version = platform_state.current_protocol_version_in_consensus(); @@ -1207,14 +1225,17 @@ mod tests { #[test] fn data_contract_update_check_tx_for_invalid_update() { - let mut platform = TestPlatformBuilder::new() - .with_config(PlatformConfig::default()) - .build_with_mock_rpc(); + let platform_config = PlatformConfig { + testing_configs: PlatformTestConfig { + disable_instant_lock_signature_verification: true, + ..Default::default() + }, + ..Default::default() + }; - platform - .core_rpc - .expect_verify_instant_lock() - .returning(|_, _| Ok(true)); + let platform = TestPlatformBuilder::new() + .with_config(platform_config) + .build_with_mock_rpc(); let platform_state = platform.state.load(); let protocol_version = platform_state.current_protocol_version_in_consensus(); @@ -1445,16 +1466,19 @@ mod tests { #[test] fn document_update_check_tx() { - let mut platform = TestPlatformBuilder::new() - .with_config(PlatformConfig::default()) + let platform_config = PlatformConfig { + testing_configs: PlatformTestConfig { + disable_instant_lock_signature_verification: true, + ..Default::default() + }, + ..Default::default() + }; + + let platform = TestPlatformBuilder::new() + .with_config(platform_config) .build_with_mock_rpc() .set_genesis_state(); - platform - .core_rpc - .expect_verify_instant_lock() - .returning(|_, _| Ok(true)); - let platform_state = platform.state.load(); let platform_version = platform_state.current_platform_version().unwrap(); @@ -1640,14 +1664,17 @@ mod tests { #[test] fn identity_top_up_check_tx() { - let mut platform = TestPlatformBuilder::new() - .with_config(PlatformConfig::default()) - .build_with_mock_rpc(); + let platform_config = PlatformConfig { + testing_configs: PlatformTestConfig { + disable_instant_lock_signature_verification: true, + ..Default::default() + }, + ..Default::default() + }; - platform - .core_rpc - .expect_verify_instant_lock() - .returning(|_, _| Ok(true)); + let platform = TestPlatformBuilder::new() + .with_config(platform_config) + .build_with_mock_rpc(); let platform_state = platform.state.load(); let platform_version = platform_state.current_platform_version().unwrap(); @@ -1786,14 +1813,17 @@ mod tests { #[test] fn identity_cant_double_top_up() { - let mut platform = TestPlatformBuilder::new() - .with_config(PlatformConfig::default()) - .build_with_mock_rpc(); + let platform_config = PlatformConfig { + testing_configs: PlatformTestConfig { + disable_instant_lock_signature_verification: true, + ..Default::default() + }, + ..Default::default() + }; - platform - .core_rpc - .expect_verify_instant_lock() - .returning(|_, _| Ok(true)); + let platform = TestPlatformBuilder::new() + .with_config(platform_config) + .build_with_mock_rpc(); let platform_state = platform.state.load(); let platform_version = platform_state.current_platform_version().unwrap(); @@ -1964,14 +1994,17 @@ mod tests { #[test] fn identity_top_up_with_unknown_identity_doesnt_panic() { - let mut platform = TestPlatformBuilder::new() - .with_config(PlatformConfig::default()) - .build_with_mock_rpc(); + let platform_config = PlatformConfig { + testing_configs: PlatformTestConfig { + disable_instant_lock_signature_verification: true, + ..Default::default() + }, + ..Default::default() + }; - platform - .core_rpc - .expect_verify_instant_lock() - .returning(|_, _| Ok(true)); + let platform = TestPlatformBuilder::new() + .with_config(platform_config) + .build_with_mock_rpc(); let platform_state = platform.state.load(); let platform_version = platform_state.current_platform_version().unwrap(); @@ -2065,14 +2098,17 @@ mod tests { #[test] fn identity_cant_create_with_used_outpoint() { - let mut platform = TestPlatformBuilder::new() - .with_config(PlatformConfig::default()) - .build_with_mock_rpc(); + let platform_config = PlatformConfig { + testing_configs: PlatformTestConfig { + disable_instant_lock_signature_verification: true, + ..Default::default() + }, + ..Default::default() + }; - platform - .core_rpc - .expect_verify_instant_lock() - .returning(|_, _| Ok(true)); + let platform = TestPlatformBuilder::new() + .with_config(platform_config) + .build_with_mock_rpc(); let platform_state = platform.state.load(); let platform_version = platform_state.current_platform_version().unwrap(); @@ -2290,14 +2326,17 @@ mod tests { #[test] fn identity_can_create_with_semi_used_outpoint() { - let mut platform = TestPlatformBuilder::new() - .with_config(PlatformConfig::default()) - .build_with_mock_rpc(); + let platform_config = PlatformConfig { + testing_configs: PlatformTestConfig { + disable_instant_lock_signature_verification: true, + ..Default::default() + }, + ..Default::default() + }; - platform - .core_rpc - .expect_verify_instant_lock() - .returning(|_, _| Ok(true)); + let platform = TestPlatformBuilder::new() + .with_config(platform_config) + .build_with_mock_rpc(); let platform_state = platform.state.load(); let platform_version = platform_state.current_platform_version().unwrap(); @@ -2611,14 +2650,17 @@ mod tests { config.abci.keys.dpns_second_public_key = high_public_key.serialize().to_vec(); - let mut platform = TestPlatformBuilder::new() - .with_config(config) - .build_with_mock_rpc(); + let platform_config = PlatformConfig { + testing_configs: PlatformTestConfig { + disable_instant_lock_signature_verification: true, + ..Default::default() + }, + ..Default::default() + }; - platform - .core_rpc - .expect_verify_instant_lock() - .returning(|_, _| Ok(true)); + let platform = TestPlatformBuilder::new() + .with_config(platform_config) + .build_with_mock_rpc(); let platform_state = platform.state.load(); let platform_version = platform_state.current_platform_version().unwrap(); @@ -2732,14 +2774,17 @@ mod tests { config.abci.keys.dashpay_second_public_key = high_public_key.serialize().to_vec(); - let mut platform = TestPlatformBuilder::new() - .with_config(config) - .build_with_mock_rpc(); + let platform_config = PlatformConfig { + testing_configs: PlatformTestConfig { + disable_instant_lock_signature_verification: true, + ..Default::default() + }, + ..Default::default() + }; - platform - .core_rpc - .expect_verify_instant_lock() - .returning(|_, _| Ok(true)); + let platform = TestPlatformBuilder::new() + .with_config(platform_config) + .build_with_mock_rpc(); let platform_state = platform.state.load(); let platform_version = platform_state.current_platform_version().unwrap(); diff --git a/packages/rs-drive-abci/src/execution/engine/finalize_block_proposal/v0/mod.rs b/packages/rs-drive-abci/src/execution/engine/finalize_block_proposal/v0/mod.rs index ae78f603616..68b226873b1 100644 --- a/packages/rs-drive-abci/src/execution/engine/finalize_block_proposal/v0/mod.rs +++ b/packages/rs-drive-abci/src/execution/engine/finalize_block_proposal/v0/mod.rs @@ -154,18 +154,23 @@ where return Ok(validation_result.into()); } + // Verify commit + // In production this will always be true - if self + #[cfg(not(feature = "testing-config"))] + let verify_commit_signature = true; + + #[cfg(feature = "testing-config")] + let verify_commit_signature = self .config .testing_configs - .block_commit_signature_verification - { - // Verify commit + .block_commit_signature_verification; + if verify_commit_signature { let quorum_public_key = last_committed_state .current_validator_set()? .threshold_public_key(); - let quorum_type = self.config.validator_set_quorum_type(); + let quorum_type = self.config.validator_set.quorum_type; // TODO: We already had commit in the function above, why do we need to create it again with clone? let commit = Commit::new_from_cleaned( commit_info.clone(), diff --git a/packages/rs-drive-abci/src/execution/engine/initialization/init_chain/v0/mod.rs b/packages/rs-drive-abci/src/execution/engine/initialization/init_chain/v0/mod.rs index 29fba3c5148..75bd88a55cf 100644 --- a/packages/rs-drive-abci/src/execution/engine/initialization/init_chain/v0/mod.rs +++ b/packages/rs-drive-abci/src/execution/engine/initialization/init_chain/v0/mod.rs @@ -52,7 +52,8 @@ where let mut initial_platform_state = PlatformState::default_with_protocol_versions( request.initial_protocol_version, request.initial_protocol_version, - ); + &self.config, + )?; let genesis_block_info = BlockInfo { height: request.initial_height, diff --git a/packages/rs-drive-abci/src/execution/platform_events/block_fee_processing/add_process_epoch_change_operations/v0/mod.rs b/packages/rs-drive-abci/src/execution/platform_events/block_fee_processing/add_process_epoch_change_operations/v0/mod.rs index e705b047ba0..3e34b5c5822 100644 --- a/packages/rs-drive-abci/src/execution/platform_events/block_fee_processing/add_process_epoch_change_operations/v0/mod.rs +++ b/packages/rs-drive-abci/src/execution/platform_events/block_fee_processing/add_process_epoch_change_operations/v0/mod.rs @@ -252,7 +252,9 @@ mod tests { let block_platform_state = PlatformState::default_with_protocol_versions( INITIAL_PROTOCOL_VERSION, INITIAL_PROTOCOL_VERSION, - ); + &platform.config, + ) + .expect("failed to create platform state"); let block_execution_context = BlockExecutionContextV0 { block_state_info: block_info.clone().into(), diff --git a/packages/rs-drive-abci/src/execution/platform_events/block_fee_processing/process_block_fees/v0/mod.rs b/packages/rs-drive-abci/src/execution/platform_events/block_fee_processing/process_block_fees/v0/mod.rs index 0b92b87f241..d6df6c83012 100644 --- a/packages/rs-drive-abci/src/execution/platform_events/block_fee_processing/process_block_fees/v0/mod.rs +++ b/packages/rs-drive-abci/src/execution/platform_events/block_fee_processing/process_block_fees/v0/mod.rs @@ -283,7 +283,9 @@ mod tests { let block_platform_state = PlatformState::default_with_protocol_versions( INITIAL_PROTOCOL_VERSION, INITIAL_PROTOCOL_VERSION, - ); + &platform.config, + ) + .expect("failed to create default platform state"); let block_execution_context = BlockExecutionContextV0 { block_state_info: block_info.clone().into(), diff --git a/packages/rs-drive-abci/src/execution/platform_events/core_based_updates/update_quorum_info/v0/mod.rs b/packages/rs-drive-abci/src/execution/platform_events/core_based_updates/update_quorum_info/v0/mod.rs index 50ad933c426..55c4b053321 100644 --- a/packages/rs-drive-abci/src/execution/platform_events/core_based_updates/update_quorum_info/v0/mod.rs +++ b/packages/rs-drive-abci/src/execution/platform_events/core_based_updates/update_quorum_info/v0/mod.rs @@ -3,17 +3,45 @@ use crate::error::Error; use crate::platform_types::platform::Platform; use crate::platform_types::platform_state::v0::PlatformStateV0Methods; use crate::platform_types::platform_state::PlatformState; -use crate::platform_types::signature_verification_quorums::SignatureVerificationQuorumsV0Methods; +use dashcore_rpc::json::{ExtendedQuorumListResult, QuorumType}; use std::collections::BTreeMap; +use std::fmt::Display; use crate::platform_types::validator_set::v0::{ValidatorSetV0, ValidatorSetV0Getters}; use crate::platform_types::validator_set::ValidatorSet; use crate::rpc::core::CoreRPCLike; +use crate::platform_types::signature_verification_quorum_set::{ + SignatureVerificationQuorumSet, SignatureVerificationQuorumSetV0Methods, VerificationQuorum, +}; use dpp::bls_signatures::PublicKey as BlsPublicKey; use dpp::dashcore::QuorumHash; use tracing::Level; +#[derive(Copy, Clone)] +enum QuorumSetType { + ChainLock(QuorumType), + InstantLock(QuorumType), +} + +impl QuorumSetType { + fn quorum_type(&self) -> QuorumType { + match self { + QuorumSetType::ChainLock(quorum_type) => *quorum_type, + QuorumSetType::InstantLock(quorum_type) => *quorum_type, + } + } +} + +impl Display for QuorumSetType { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + QuorumSetType::ChainLock(quorum_type) => write!(f, "chain lock ({quorum_type})"), + QuorumSetType::InstantLock(quorum_type) => write!(f, "instant lock ({quorum_type})"), + } + } +} + impl Platform where C: CoreRPCLike, @@ -63,8 +91,9 @@ where .core_rpc .get_quorum_listextended(Some(core_block_height))?; - let validator_set_quorum_type = self.config.validator_set_quorum_type(); - let chain_lock_quorum_type = self.config.chain_lock_quorum_type(); + let validator_set_quorum_type = self.config.validator_set.quorum_type; + let chain_lock_quorum_type = self.config.chain_lock.quorum_type; + let instant_lock_quorum_type = self.config.instant_lock.quorum_type; let validator_quorums_list: BTreeMap<_, _> = extended_quorum_list .quorums_by_type @@ -72,7 +101,7 @@ where .ok_or(Error::Execution(ExecutionError::DashCoreBadResponseError( format!( "expected quorums of type {}, but did not receive any from Dash Core", - self.config.validator_set_quorum_type + self.config.validator_set.quorum_type ), )))? .into_iter() @@ -90,10 +119,10 @@ where if !retain { tracing::trace!( ?quorum_hash, - quorum_type = ?self.config.validator_set_quorum_type(), + quorum_type = ?self.config.validator_set.quorum_type, "removed validator set {} with quorum type {}", quorum_hash, - self.config.validator_set_quorum_type() + self.config.validator_set.quorum_type ) } @@ -102,7 +131,7 @@ where // Fetch quorum info and their keys from the RPC for new quorums let mut quorum_infos = validator_quorums_list - .iter() + .into_iter() .filter(|(key, _)| { !block_platform_state .validator_sets() @@ -110,12 +139,12 @@ where }) .map(|(key, _)| { let quorum_info_result = self.core_rpc.get_quorum_info( - self.config.validator_set_quorum_type(), - key, + self.config.validator_set.quorum_type, + &key, None, )?; - Ok((*key, quorum_info_result)) + Ok((key, quorum_info_result)) }) .collect::, Error>>()?; @@ -141,17 +170,17 @@ where tracing::trace!( ?validator_set, ?quorum_hash, - quorum_type = ?self.config.validator_set_quorum_type(), + quorum_type = ?self.config.validator_set.quorum_type, "add new validator set {} with quorum type {}", quorum_hash, - self.config.validator_set_quorum_type() + self.config.validator_set.quorum_type ); Ok((quorum_hash, validator_set)) }) .collect::, Error>>()?; - let added_a_validator_set = !new_validator_sets.is_empty(); + let is_validator_set_updated = !new_validator_sets.is_empty() || removed_a_validator_set; // Add new validator_sets entries block_platform_state @@ -173,139 +202,227 @@ where } }); - if validator_set_quorum_type == chain_lock_quorum_type { - // Remove validator_sets entries that are no longer valid for the core block height - if removed_a_validator_set || added_a_validator_set { - let quorums = block_platform_state - .validator_sets() - .iter() - .map(|(quorum_hash, validator_set)| { - (*quorum_hash, validator_set.threshold_public_key().clone()) - }) - .collect(); - - tracing::trace!("updated chain lock validating quorums to current validator set"); - - if platform_state.is_some() { - // we already have state, so we update last and previous quorums - block_platform_state - .chain_lock_validating_quorums_mut() - .rotate_quorums(quorums, last_committed_core_height, core_block_height); - } else { - // the only case where there will be no platform_state is init chain, - // so there is no previous quorums to update - block_platform_state - .chain_lock_validating_quorums_mut() - .set_current_quorums(quorums) - } + // Update Chain Lock quorums + + // Use already updated validator sets if we use the same quorums + let quorum_set_type = QuorumSetType::ChainLock(chain_lock_quorum_type); + let are_chainlock_quorum_updated = if chain_lock_quorum_type == validator_set_quorum_type { + // Update only in case if there are any changes + if is_validator_set_updated { + Self::update_quorums_from_validator_set( + quorum_set_type, + platform_state, + block_platform_state, + core_block_height, + ); } + + is_validator_set_updated } else { - let chain_lock_quorums_list: BTreeMap<_, _> = extended_quorum_list - .quorums_by_type - .remove(&chain_lock_quorum_type) - .ok_or(Error::Execution(ExecutionError::DashCoreBadResponseError( - format!( - "expected quorums of type {}, but did not receive any from Dash Core", - self.config.chain_lock_quorum_type - ), - )))? - .into_iter() - .map(|(quorum_hash, extended_quorum_details)| { - (quorum_hash, extended_quorum_details.quorum_index) - }) - .collect(); - - let mut removed_a_chain_lock_validating_quorum = false; - - // Remove chain_lock_validating_quorums entries that are no longer valid for the core block height - block_platform_state - .chain_lock_validating_quorums_mut() - .current_quorums_mut() - .retain(|quorum_hash, _| { - let retain = chain_lock_quorums_list.contains_key::(quorum_hash); - if !retain { - tracing::trace!( - ?quorum_hash, - quorum_type = ?chain_lock_quorum_type, - "removed old chain lock quorum {} with quorum type {}", - quorum_hash, - chain_lock_quorum_type - ); - } - removed_a_chain_lock_validating_quorum |= !retain; - retain - }); - - // Fetch quorum info and their keys from the RPC for new quorums - let quorum_infos = chain_lock_quorums_list - .iter() - .filter(|(key, _)| { - !block_platform_state - .chain_lock_validating_quorums() - .current_quorums() - .contains_key::(key) - }) - .map(|(key, _)| { - let quorum_info_result = - self.core_rpc - .get_quorum_info(chain_lock_quorum_type, key, None)?; - - Ok((*key, quorum_info_result)) - }) - .collect::, Error>>()?; - - let added_a_chain_lock_validating_quorum = !quorum_infos.is_empty(); - - if added_a_chain_lock_validating_quorum { - // Map to chain lock validating quorums - let new_chain_lock_quorums = quorum_infos - .into_iter() - .map(|(quorum_hash, info_result)| { - let public_key = match BlsPublicKey::from_bytes( - info_result.quorum_public_key.as_slice(), - ) - .map_err(ExecutionError::BlsErrorFromDashCoreResponse) - { - Ok(public_key) => public_key, - Err(e) => return Err(e.into()), - }; - - tracing::trace!( - ?public_key, - ?quorum_hash, - quorum_type = ?chain_lock_quorum_type, - "add new chain lock quorum {} with quorum type {}", - quorum_hash, - chain_lock_quorum_type - ); - - Ok((quorum_hash, public_key)) - }) - .collect::, Error>>()?; - - // Add new validator_sets entries - block_platform_state - .chain_lock_validating_quorums_mut() - .current_quorums_mut() - .extend(new_chain_lock_quorums); + self.update_quorums_from_quorum_list( + quorum_set_type, + block_platform_state.chain_lock_validating_quorums_mut(), + platform_state, + &extended_quorum_list, + last_committed_core_height, + core_block_height, + )? + }; + + // Update Instant Lock quorums + + // Use already updated chainlock quorums if we use the same quorum type + let quorum_set_type = QuorumSetType::InstantLock(instant_lock_quorum_type); + if instant_lock_quorum_type == chain_lock_quorum_type { + if are_chainlock_quorum_updated { + tracing::trace!( + "updated instant lock validating quorums to chain lock validating quorums", + ); + + block_platform_state.set_instant_lock_validating_quorums( + block_platform_state.chain_lock_validating_quorums().clone(), + ); + } + // The same for validator set quorum type + } else if instant_lock_quorum_type == validator_set_quorum_type { + if is_validator_set_updated { + Self::update_quorums_from_validator_set( + quorum_set_type, + platform_state, + block_platform_state, + core_block_height, + ); } + } else { + self.update_quorums_from_quorum_list( + quorum_set_type, + block_platform_state.instant_lock_validating_quorums_mut(), + platform_state, + &extended_quorum_list, + last_committed_core_height, + core_block_height, + )?; + } + + Ok(()) + } - if added_a_chain_lock_validating_quorum || removed_a_chain_lock_validating_quorum { - if let Some(old_state) = platform_state { - let previous_chain_lock_validating_quorums = - old_state.chain_lock_validating_quorums().current_quorums(); - - block_platform_state - .chain_lock_validating_quorums_mut() - .set_previous_past_quorums( - previous_chain_lock_validating_quorums.clone(), - last_committed_core_height, - core_block_height, - ); + fn update_quorums_from_validator_set( + quorum_set_type: QuorumSetType, + platform_state: Option<&PlatformState>, + block_platform_state: &mut PlatformState, + core_block_height: u32, + ) { + let quorums = block_platform_state + .validator_sets() + .iter() + .map(|(quorum_hash, validator_set)| { + ( + *quorum_hash, + VerificationQuorum { + public_key: validator_set.threshold_public_key().clone(), + index: validator_set.quorum_index(), + }, + ) + }) + .collect(); + + tracing::trace!( + "updated {} validating quorums to current validator set", + quorum_set_type + ); + + let last_committed_core_height = block_platform_state.last_committed_core_height(); + + let quorum_set = quorum_set_by_type_mut(block_platform_state, &quorum_set_type); + + if platform_state.is_some() { + // we already have state, so we update last and previous quorums + quorum_set.replace_quorums(quorums, last_committed_core_height, core_block_height); + } else { + // the only case where there will be no platform_state is init chain, + // so there is no previous quorums to update + quorum_set.set_current_quorums(quorums) + } + } + + fn update_quorums_from_quorum_list( + &self, + quorum_set_type: QuorumSetType, + quorum_set: &mut SignatureVerificationQuorumSet, + platform_state: Option<&PlatformState>, + full_quorum_list: &ExtendedQuorumListResult, + last_committed_core_height: u32, + next_core_height: u32, + ) -> Result { + let quorums_list: BTreeMap<_, _> = full_quorum_list + .quorums_by_type + .get(&quorum_set_type.quorum_type()) + .ok_or(Error::Execution(ExecutionError::DashCoreBadResponseError( + format!( + "expected quorums {}, but did not receive any from Dash Core", + quorum_set_type + ), + )))? + .iter() + .map(|(quorum_hash, extended_quorum_details)| { + (quorum_hash, extended_quorum_details.quorum_index) + }) + .collect(); + + let mut removed_a_validating_quorum = false; + + // Remove validating_quorums entries that are no longer valid for the core block height + // and update quorum index for existing validator sets + quorum_set + .current_quorums_mut() + .retain(|quorum_hash, quorum| { + let retain = match quorums_list.get(quorum_hash) { + Some(index) => { + quorum.index = *index; + true + } + None => false, + }; + + if !retain { + tracing::trace!( + ?quorum_hash, + quorum_type = ?quorum_set_type.quorum_type(), + "removed old {} quorum {}", + quorum_set_type, + quorum_hash, + ); } + removed_a_validating_quorum |= !retain; + retain + }); + + // Fetch quorum info and their keys from the RPC for new quorums + // and then create VerificationQuorum instances + let new_quorums = quorums_list + .into_iter() + .filter(|(quorum_hash, _)| { + !quorum_set + .current_quorums() + .contains_key::(quorum_hash) + }) + .map(|(quorum_hash, index)| { + let quorum_info = self.core_rpc.get_quorum_info( + quorum_set_type.quorum_type(), + quorum_hash, + None, + )?; + + let public_key = + match BlsPublicKey::from_bytes(quorum_info.quorum_public_key.as_slice()) + .map_err(ExecutionError::BlsErrorFromDashCoreResponse) + { + Ok(public_key) => public_key, + Err(e) => return Err(e.into()), + }; + + tracing::trace!( + ?public_key, + ?quorum_hash, + index, + quorum_type = ?quorum_set_type.quorum_type(), + "add new {} quorum {}", + quorum_set_type, + quorum_hash, + ); + + Ok((*quorum_hash, VerificationQuorum { public_key, index })) + }) + .collect::, Error>>()?; + + let are_quorums_updated = !new_quorums.is_empty() || removed_a_validating_quorum; + + quorum_set.current_quorums_mut().extend(new_quorums); + + if are_quorums_updated { + if let Some(old_state) = platform_state { + let previous_validating_quorums = + old_state.chain_lock_validating_quorums().current_quorums(); + + quorum_set.set_previous_past_quorums( + previous_validating_quorums.clone(), + last_committed_core_height, + next_core_height, + ); } } - Ok(()) + Ok(are_quorums_updated) + } +} + +fn quorum_set_by_type_mut<'p>( + block_platform_state: &'p mut PlatformState, + quorum_set_type: &QuorumSetType, +) -> &'p mut SignatureVerificationQuorumSet { + match quorum_set_type { + QuorumSetType::ChainLock(_) => block_platform_state.chain_lock_validating_quorums_mut(), + QuorumSetType::InstantLock(_) => block_platform_state.instant_lock_validating_quorums_mut(), } } diff --git a/packages/rs-drive-abci/src/execution/platform_events/core_chain_lock/choose_quorum/mod.rs b/packages/rs-drive-abci/src/execution/platform_events/core_chain_lock/choose_quorum/mod.rs index 11d1b02f782..3af3b3fbd2d 100644 --- a/packages/rs-drive-abci/src/execution/platform_events/core_chain_lock/choose_quorum/mod.rs +++ b/packages/rs-drive-abci/src/execution/platform_events/core_chain_lock/choose_quorum/mod.rs @@ -21,7 +21,7 @@ where C: CoreRPCLike, { /// Based on DIP8 deterministically chooses a pseudorandom quorum from the list of quorums - /// + // TODO: use CoreQuorumSet.select_quorums instead pub fn choose_quorum<'a>( llmq_quorum_type: QuorumType, quorums: &'a BTreeMap, diff --git a/packages/rs-drive-abci/src/execution/platform_events/core_chain_lock/make_sure_core_is_synced_to_chain_lock/v0/mod.rs b/packages/rs-drive-abci/src/execution/platform_events/core_chain_lock/make_sure_core_is_synced_to_chain_lock/v0/mod.rs index 4ca9f9705cb..f92183277b4 100644 --- a/packages/rs-drive-abci/src/execution/platform_events/core_chain_lock/make_sure_core_is_synced_to_chain_lock/v0/mod.rs +++ b/packages/rs-drive-abci/src/execution/platform_events/core_chain_lock/make_sure_core_is_synced_to_chain_lock/v0/mod.rs @@ -18,6 +18,8 @@ where ) -> Result { let given_chain_lock_height = chain_lock.block_height; // We need to make sure core is synced to the core height we see as valid for the state transitions + + // TODO: submit_chain_lock responds with invalid signature. We should handle it properly and return CoreSyncStatus let best_chain_locked_height = self.core_rpc.submit_chain_lock(chain_lock)?; Ok(if best_chain_locked_height >= given_chain_lock_height { CoreSyncStatus::Done diff --git a/packages/rs-drive-abci/src/execution/platform_events/core_chain_lock/verify_chain_lock_locally/v0/mod.rs b/packages/rs-drive-abci/src/execution/platform_events/core_chain_lock/verify_chain_lock_locally/v0/mod.rs index d0f7b60af84..a48fc30c670 100644 --- a/packages/rs-drive-abci/src/execution/platform_events/core_chain_lock/verify_chain_lock_locally/v0/mod.rs +++ b/packages/rs-drive-abci/src/execution/platform_events/core_chain_lock/verify_chain_lock_locally/v0/mod.rs @@ -12,7 +12,7 @@ use crate::rpc::core::CoreRPCLike; use crate::error::execution::ExecutionError; use crate::platform_types::platform_state::v0::PlatformStateV0Methods; use crate::platform_types::platform_state::PlatformState; -use crate::platform_types::signature_verification_quorums::SignatureVerificationQuorumsV0Methods; +use crate::platform_types::signature_verification_quorum_set::SignatureVerificationQuorumSetV0Methods; use dpp::version::PlatformVersion; const CHAIN_LOCK_REQUEST_ID_PREFIX: &str = "clsig"; @@ -31,15 +31,20 @@ where round: u32, platform_state: &PlatformState, chain_lock: &ChainLock, - platform_version: &PlatformVersion, + _platform_version: &PlatformVersion, ) -> Result, Error> { + let quorum_set = platform_state.chain_lock_validating_quorums(); + let quorum_config = quorum_set.config(); + // First verify that the signature conforms to a signature - let signature = G2Element::from_bytes(chain_lock.signature.as_bytes())?; + let Ok(signature) = G2Element::from_bytes(chain_lock.signature.as_bytes()) else { + return Ok(Some(false)); + }; // we attempt to verify the chain lock locally let chain_lock_height = chain_lock.block_height; - let window_width = self.config.chain_lock_quorum_window; + let window_width = quorum_config.window; // The last block in the window where the quorums would be the same let last_block_in_window = platform_state.last_committed_core_height() @@ -63,10 +68,12 @@ where return Ok(None); // the chain lock is too far in the future or the past to verify locally } - let mut selected_quorum_sets = platform_state + let mut selected_quorums = platform_state .chain_lock_validating_quorums() .select_quorums(chain_lock_height, verification_height); + // TODO: We can use chain_lock.request_id() + // From DIP 8: https://github.com/dashpay/dips/blob/master/dip-0008.md#finalization-of-signed-blocks // The request id is SHA256("clsig", blockHeight) and the message hash is the block hash of the previously successful attempt. @@ -86,20 +93,15 @@ where ); // Based on the deterministic masternode list at the given height, a quorum must be selected that was active at the time this block was mined - let probable_quorums = selected_quorum_sets.next().ok_or_else(|| { + + let probable_quorums = selected_quorums.next().ok_or_else(|| { Error::Execution(ExecutionError::CorruptedCodeExecution( - "at lest one set of quorums must be selected", + "No quorums selected for chain lock signature verification for specified height", )) })?; - let quorum = Platform::::choose_quorum( - self.config.chain_lock_quorum_type(), - probable_quorums, - request_id.as_ref(), - platform_version, - )?; - - let Some((quorum_hash, public_key)) = quorum else { + let Some((quorum_hash, quorum)) = probable_quorums.choose_quorum(request_id.as_ref()) + else { return Ok(None); }; @@ -107,14 +109,19 @@ where let mut engine = sha256d::Hash::engine(); - engine.input(&[self.config.chain_lock_quorum_type() as u8]); - engine.input(quorum_hash.as_slice()); + let mut reversed_quorum_hash = quorum_hash.to_byte_array().to_vec(); + reversed_quorum_hash.reverse(); + + engine.input(&[quorum_config.quorum_type as u8]); + engine.input(reversed_quorum_hash.as_slice()); engine.input(request_id.as_byte_array()); engine.input(chain_lock.block_hash.as_byte_array()); let message_digest = sha256d::Hash::from_engine(engine); - let mut chain_lock_verified = public_key.verify(&signature, message_digest.as_ref()); + let mut chain_lock_verified = quorum + .public_key + .verify(&signature, message_digest.as_ref()); tracing::debug!( ?chain_lock, @@ -123,7 +130,7 @@ where round, chain_lock.block_height, hex::encode(message_digest.as_byte_array()), - hex::encode(quorum_hash.as_slice()), + hex::encode(reversed_quorum_hash.as_slice()), hex::encode(chain_lock.block_hash.as_byte_array()), if chain_lock_verified { "verified"} else {"not verified"}, platform_state.last_committed_core_height(), @@ -133,15 +140,10 @@ where if !chain_lock_verified { // We should also check the other quorum, as there could be the situation where the core height wasn't updated every block. - if let Some(second_to_check_quorums) = selected_quorum_sets.next() { - let quorum = Platform::::choose_quorum( - self.config.chain_lock_quorum_type(), - second_to_check_quorums, - request_id.as_ref(), - platform_version, - )?; - - let Some((quorum_hash, public_key)) = quorum else { + if let Some(second_to_check_quorums) = selected_quorums.next() { + let Some((quorum_hash, quorum)) = + second_to_check_quorums.choose_quorum(request_id.as_ref()) + else { // we return that we are not able to verify return Ok(None); }; @@ -150,14 +152,19 @@ where let mut engine = sha256d::Hash::engine(); - engine.input(&[self.config.chain_lock_quorum_type() as u8]); - engine.input(quorum_hash.as_slice()); + let mut reversed_quorum_hash = quorum_hash.to_byte_array().to_vec(); + reversed_quorum_hash.reverse(); + + engine.input(&[quorum_config.quorum_type as u8]); + engine.input(reversed_quorum_hash.as_slice()); engine.input(request_id.as_byte_array()); engine.input(chain_lock.block_hash.as_byte_array()); let message_digest = sha256d::Hash::from_engine(engine); - chain_lock_verified = public_key.verify(&signature, message_digest.as_ref()); + chain_lock_verified = quorum + .public_key + .verify(&signature, message_digest.as_ref()); tracing::debug!( ?chain_lock, @@ -166,7 +173,7 @@ where round, chain_lock.block_height, hex::encode(message_digest.as_byte_array()), - hex::encode(quorum_hash.as_slice()), + hex::encode(reversed_quorum_hash.as_slice()), hex::encode(chain_lock.block_hash.as_byte_array()), if chain_lock_verified { "verified"} else {"not verified"} ); @@ -175,17 +182,16 @@ where "chain lock was invalid for both recent and old chain lock quorums" ); } - } else if platform_state + } else if !platform_state .chain_lock_validating_quorums() - .previous_past_quorums() - .is_none() + .has_previous_past_quorums() { // we don't have old quorums, this means our node is very new. tracing::debug!( "we had no previous quorums locally, we should validate through core", ); return Ok(None); - } else if !selected_quorum_sets.should_be_verifiable { + } else if !selected_quorums.should_be_verifiable() { tracing::debug!( "we were in a situation where it would be possible we didn't have all quorums and we couldn't verify locally, we should validate through core", ); diff --git a/packages/rs-drive-abci/src/execution/platform_events/core_instant_send_lock/mod.rs b/packages/rs-drive-abci/src/execution/platform_events/core_instant_send_lock/mod.rs new file mode 100644 index 00000000000..87db2f8862d --- /dev/null +++ b/packages/rs-drive-abci/src/execution/platform_events/core_instant_send_lock/mod.rs @@ -0,0 +1,2 @@ +/// Instant Lock recent signature verification +pub mod verify_recent_signature_locally; diff --git a/packages/rs-drive-abci/src/execution/platform_events/core_instant_send_lock/verify_recent_signature_locally/mod.rs b/packages/rs-drive-abci/src/execution/platform_events/core_instant_send_lock/verify_recent_signature_locally/mod.rs new file mode 100644 index 00000000000..e804ad228ef --- /dev/null +++ b/packages/rs-drive-abci/src/execution/platform_events/core_instant_send_lock/verify_recent_signature_locally/mod.rs @@ -0,0 +1,47 @@ +mod v0; + +use crate::error::execution::ExecutionError; +use crate::error::Error; +use dpp::dashcore::InstantLock; + +use crate::platform_types::platform_state::PlatformState; +use dpp::version::PlatformVersion; + +/// Traits implements a method for signature verification using platform execution state +pub trait VerifyInstantLockSignature { + fn verify_recent_signature_locally( + &self, + platform_state: &PlatformState, + platform_version: &PlatformVersion, + ) -> Result; +} + +impl VerifyInstantLockSignature for InstantLock { + /// Verify instant lock signature with limited quorum set what we store in Platform state + /// + /// This is a limited verification and will work properly only for recently signed instant locks. + /// Even valid instant locks that was signed some time ago will be considered invalid due to limited + /// quorum information in the platform state. In turn, this verification doesn't use Core RPC or any other + /// IO. This is done to prevent DoS attacks on slow verify instant lock signature Core RPC method. + /// In case of failed signature verification (or any knowing the fact that signing quorum is old), + /// we expect clients to use ChainAssetLockProof. + fn verify_recent_signature_locally( + &self, + platform_state: &PlatformState, + platform_version: &PlatformVersion, + ) -> Result { + match platform_version + .drive_abci + .methods + .core_instant_send_lock + .verify_recent_signature_locally + { + 0 => v0::verify_recent_instant_lock_signature_locally_v0(self, platform_state), + version => Err(Error::Execution(ExecutionError::UnknownVersionMismatch { + method: "InstantLock.verify_recent_signature_locally".to_string(), + known_versions: vec![0], + received: version, + })), + } + } +} diff --git a/packages/rs-drive-abci/src/execution/platform_events/core_instant_send_lock/verify_recent_signature_locally/v0/mod.rs b/packages/rs-drive-abci/src/execution/platform_events/core_instant_send_lock/verify_recent_signature_locally/v0/mod.rs new file mode 100644 index 00000000000..b7fb76a10c0 --- /dev/null +++ b/packages/rs-drive-abci/src/execution/platform_events/core_instant_send_lock/verify_recent_signature_locally/v0/mod.rs @@ -0,0 +1,144 @@ +use dpp::bls_signatures::G2Element; +use std::fmt::{Debug, Formatter}; + +use dpp::dashcore::hashes::{sha256d, Hash, HashEngine}; +use dpp::dashcore::InstantLock; + +use crate::error::execution::ExecutionError; +use crate::error::Error; + +use crate::error::serialization::SerializationError; +use crate::platform_types::platform_state::v0::PlatformStateV0Methods; +use crate::platform_types::platform_state::PlatformState; +use crate::platform_types::signature_verification_quorum_set::{ + SignatureVerificationQuorumSetV0Methods, SIGN_OFFSET, +}; + +#[inline(always)] +pub(super) fn verify_recent_instant_lock_signature_locally_v0( + instant_lock: &InstantLock, + platform_state: &PlatformState, +) -> Result { + // First verify that the signature conforms to a signature + let signature = match G2Element::from_bytes(instant_lock.signature.as_bytes()) { + Ok(signature) => signature, + Err(e) => { + tracing::trace!( + instant_lock = ?InstantLockDebug(instant_lock), + "Invalid instant Lock {} signature format: {}", + instant_lock.txid, + e, + ); + + return Ok(false); + } + }; + + let signing_height = platform_state.last_committed_core_height(); + let verification_height = signing_height.saturating_sub(SIGN_OFFSET); + + let quorum_set = platform_state.instant_lock_validating_quorums(); + + // Based on the deterministic masternode list at the given height, a quorum must be selected + // that was active at the time this block was mined + let selected_quorums = quorum_set.select_quorums(signing_height, verification_height); + + if selected_quorums.is_empty() { + return Err(Error::Execution(ExecutionError::CorruptedCodeExecution( + "No quorums selected for instant lock signature verification for specified height", + ))); + }; + + let request_id = instant_lock.request_id().map_err(|e| { + Error::Serialization(SerializationError::CorruptedSerialization(format!( + "can't hash instant lock request ID for signature verification: {e}" + ))) + })?; + + for (i, quorums) in selected_quorums.enumerate() { + let Some((quorum_hash, quorum)) = quorums.choose_quorum(request_id.as_ref()) else { + if tracing::enabled!(tracing::Level::TRACE) { + tracing::trace!( + quorums_iteration = i + 1, + instant_lock = ?InstantLockDebug(instant_lock), + request_id = request_id.to_string(), + quorums = ?quorums.quorums, + request_id = request_id.to_string(), + signing_height, + verification_height, + "No chosen for instant Lock {} request ID {}", + instant_lock.txid, + request_id, + ); + }; + + continue; + }; + + // The signature must verify against the quorum public key and SHA256(llmqType, quorumHash, SHA256(height), txId). + // llmqType and quorumHash must be taken from the quorum selected in 1. + let mut engine = sha256d::Hash::engine(); + + let mut reversed_quorum_hash = quorum_hash.to_byte_array().to_vec(); + reversed_quorum_hash.reverse(); + + engine.input(&[quorum_set.config().quorum_type as u8]); + engine.input(reversed_quorum_hash.as_slice()); + engine.input(request_id.as_byte_array()); + engine.input(instant_lock.txid.as_byte_array()); + + let message_digest = sha256d::Hash::from_engine(engine); + + if quorum + .public_key + .verify(&signature, message_digest.as_ref()) + { + return Ok(true); + } + + if tracing::enabled!(tracing::Level::TRACE) { + tracing::trace!( + quorums_iteration = i + 1, + instant_lock = ?InstantLockDebug(instant_lock), + quorum_hash = quorum_hash.to_string(), + quorum_config = ?quorum_set.config(), + quorum = ?quorum, + request_id = request_id.to_string(), + message_digest = message_digest.to_string(), + signing_height, + verification_height, + "Instant Lock {} signature verification failed", + instant_lock.txid, + ); + }; + } + + Ok(false) +} + +// TODO: The best way is to implement Value trait for InstantLock and hashes +// in dashcore + +/// An additional struct to implement Debug for InstantLock with hex strings +/// instead of byte arrays +struct InstantLockDebug<'a>(&'a InstantLock); + +impl<'a> Debug for InstantLockDebug<'a> { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + let instant_lock = &self.0; + f.debug_struct("InstantLock") + .field("version", &instant_lock.version) + .field( + "inputs", + &instant_lock + .inputs + .iter() + .map(|input| input.to_string()) + .collect::>(), + ) + .field("txid", &instant_lock.txid.to_string()) + .field("cyclehash", &instant_lock.cyclehash.to_string()) + .field("signature", &instant_lock.signature.to_string()) + .finish() + } +} diff --git a/packages/rs-drive-abci/src/execution/platform_events/mod.rs b/packages/rs-drive-abci/src/execution/platform_events/mod.rs index 79821827bea..d63103d880d 100644 --- a/packages/rs-drive-abci/src/execution/platform_events/mod.rs +++ b/packages/rs-drive-abci/src/execution/platform_events/mod.rs @@ -26,3 +26,6 @@ pub(in crate::execution) mod block_start; /// Verify the chain lock pub(in crate::execution) mod core_chain_lock; + +/// Instant lock methods +pub(in crate::execution) mod core_instant_send_lock; diff --git a/packages/rs-drive-abci/src/execution/platform_events/state_transition_processing/process_raw_state_transitions/v0/mod.rs b/packages/rs-drive-abci/src/execution/platform_events/state_transition_processing/process_raw_state_transitions/v0/mod.rs index 29827900d00..a9ba48da712 100644 --- a/packages/rs-drive-abci/src/execution/platform_events/state_transition_processing/process_raw_state_transitions/v0/mod.rs +++ b/packages/rs-drive-abci/src/execution/platform_events/state_transition_processing/process_raw_state_transitions/v0/mod.rs @@ -214,6 +214,19 @@ where // the first error must be present for an invalid result .remove(0); + if tracing::enabled!(tracing::Level::DEBUG) { + let st_hash = hex::encode(hash_single(raw_state_transition)); + + tracing::debug!( + error = ?first_consensus_error, + st_hash, + "Invalid {} state transition without identity ({}): {}", + state_transition_name, + st_hash, + &first_consensus_error + ); + } + // We don't have execution event, so we can't pay for processing return Ok(StateTransitionExecutionResult::UnpaidConsensusError( first_consensus_error, diff --git a/packages/rs-drive-abci/src/execution/validation/state_transition/common/asset_lock/proof/validate/instant/mod.rs b/packages/rs-drive-abci/src/execution/validation/state_transition/common/asset_lock/proof/validate/instant/mod.rs index e9fb84b8f8d..a2500b06636 100644 --- a/packages/rs-drive-abci/src/execution/validation/state_transition/common/asset_lock/proof/validate/instant/mod.rs +++ b/packages/rs-drive-abci/src/execution/validation/state_transition/common/asset_lock/proof/validate/instant/mod.rs @@ -1,7 +1,6 @@ use crate::error::Error; use crate::platform_types::platform::PlatformRef; use crate::rpc::core::CoreRPCLike; -use crate::rpc::signature::CoreSignatureVerification; use dpp::asset_lock::reduced_asset_lock_value::AssetLockValue; use dpp::consensus::basic::identity::InvalidInstantAssetLockProofSignatureError; use dpp::fee::Credits; @@ -11,10 +10,10 @@ use dpp::state_transition::signable_bytes_hasher::SignableBytesHasher; use dpp::validation::ConsensusValidationResult; use dpp::version::PlatformVersion; use drive::grovedb::TransactionArg; +use crate::execution::platform_events::core_instant_send_lock::verify_recent_signature_locally::VerifyInstantLockSignature; use crate::execution::validation::state_transition::common::asset_lock::proof::validate::AssetLockProofValidation; use crate::execution::validation::state_transition::common::asset_lock::proof::verify_is_not_spent::AssetLockProofVerifyIsNotSpent; use crate::execution::validation::state_transition::ValidationMode; -use crate::platform_types::platform_state::v0::PlatformStateV0Methods; // TODO: Versioning impl AssetLockProofValidation for InstantAssetLockProof { @@ -45,12 +44,29 @@ impl AssetLockProofValidation for InstantAssetLockProof { // As we know this outpoint was already considered final and locked. if validation_mode != ValidationMode::RecheckTx && !validation_result.has_data() { - let is_instant_lock_signature_valid = self.instant_lock().verify_signature( - platform_ref.core_rpc, - platform_ref.state.last_committed_core_height(), - )?; + // We should be able to disable instant lock versification for integration tests + #[cfg(feature = "testing-config")] + if platform_ref + .config + .testing_configs + .disable_instant_lock_signature_verification + { + return Ok(validation_result); + } + + // TODO: Shouldn't we add an operation for fees? + + // This is a limited verification and will work properly only for recently signed instant locks. + // Even valid instant locks that was signed some time ago will be considered invalid due to limited + // quorum information in the platform state. In turn, this verification doesn't use Core RPC or any other + // IO. This is done to prevent DoS attacks on slow verify instant lock signature Core RPC method. + // In case of failed signature verification (or any knowing the fact that signing quorum is old), + // we expect clients to use ChainAssetLockProof. + let is_valid = self + .instant_lock() + .verify_recent_signature_locally(platform_ref.state, platform_version)?; - if !is_instant_lock_signature_valid { + if !is_valid { return Ok(ConsensusValidationResult::new_with_error( InvalidInstantAssetLockProofSignatureError::new().into(), )); 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 dffa542954d..ae6e797a544 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 @@ -52,12 +52,11 @@ impl StateTransitionActionTransformerV0 for DataContractUpdateTransition { #[cfg(test)] mod tests { - use crate::config::{ExecutionConfig, PlatformConfig, PlatformTestConfig}; + use crate::config::{ExecutionConfig, PlatformConfig, PlatformTestConfig, ValidatorSetConfig}; use crate::platform_types::platform::PlatformRef; use crate::rpc::core::MockCoreRPCLike; use crate::test::helpers::setup::{TempPlatform, TestPlatformBuilder}; use dpp::block::block_info::BlockInfo; - use dpp::consensus::basic::BasicError; use dpp::consensus::state::state_error::StateError; use dpp::consensus::ConsensusError; use dpp::dash_to_credits; @@ -174,7 +173,10 @@ mod tests { .data_contract_owned(); let config = PlatformConfig { - validator_set_quorum_size: 10, + validator_set: ValidatorSetConfig { + quorum_size: 10, + ..Default::default() + }, execution: ExecutionConfig { verify_sum_trees: true, validator_set_rotation_block_count: 25, diff --git a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/identity_create/mod.rs b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/identity_create/mod.rs index f68781b6b13..a7db42dc744 100644 --- a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/identity_create/mod.rs +++ b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/identity_create/mod.rs @@ -193,6 +193,7 @@ impl StateTransitionStateValidationForIdentityCreateTransitionV0 for IdentityCre #[cfg(test)] mod tests { + use crate::config::{PlatformConfig, PlatformTestConfig}; use crate::test::helpers::setup::TestPlatformBuilder; use dpp::block::block_info::BlockInfo; use dpp::dashcore::{Network, PrivateKey}; @@ -215,15 +216,19 @@ mod tests { #[test] fn test_identity_create_validation() { let platform_version = PlatformVersion::latest(); - let mut platform = TestPlatformBuilder::new() + let platform_config = PlatformConfig { + testing_configs: PlatformTestConfig { + disable_instant_lock_signature_verification: true, + ..Default::default() + }, + ..Default::default() + }; + + let platform = TestPlatformBuilder::new() + .with_config(platform_config) .build_with_mock_rpc() .set_initial_state_structure(); - platform - .core_rpc - .expect_verify_instant_lock() - .returning(|_, _| Ok(true)); - let platform_state = platform.state.load(); let mut signer = SimpleSigner::default(); @@ -322,15 +327,19 @@ mod tests { #[test] fn test_identity_create_asset_lock_reuse_after_issue() { let platform_version = PlatformVersion::latest(); - let mut platform = TestPlatformBuilder::new() + let platform_config = PlatformConfig { + testing_configs: PlatformTestConfig { + disable_instant_lock_signature_verification: true, + ..Default::default() + }, + ..Default::default() + }; + + let platform = TestPlatformBuilder::new() + .with_config(platform_config) .build_with_mock_rpc() .set_initial_state_structure(); - platform - .core_rpc - .expect_verify_instant_lock() - .returning(|_, _| Ok(true)); - let platform_state = platform.state.load(); let mut signer = SimpleSigner::default(); @@ -536,15 +545,19 @@ mod tests { #[test] fn test_identity_create_asset_lock_reuse_after_max_issues() { let platform_version = PlatformVersion::latest(); - let mut platform = TestPlatformBuilder::new() + let platform_config = PlatformConfig { + testing_configs: PlatformTestConfig { + disable_instant_lock_signature_verification: true, + ..Default::default() + }, + ..Default::default() + }; + + let platform = TestPlatformBuilder::new() + .with_config(platform_config) .build_with_mock_rpc() .set_initial_state_structure(); - platform - .core_rpc - .expect_verify_instant_lock() - .returning(|_, _| Ok(true)); - let platform_state = platform.state.load(); let mut signer = SimpleSigner::default(); @@ -756,15 +769,19 @@ mod tests { #[test] fn test_identity_create_asset_lock_use_all_funds() { let platform_version = PlatformVersion::latest(); - let mut platform = TestPlatformBuilder::new() + let platform_config = PlatformConfig { + testing_configs: PlatformTestConfig { + disable_instant_lock_signature_verification: true, + ..Default::default() + }, + ..Default::default() + }; + + let platform = TestPlatformBuilder::new() + .with_config(platform_config) .build_with_mock_rpc() .set_initial_state_structure(); - platform - .core_rpc - .expect_verify_instant_lock() - .returning(|_, _| Ok(true)); - let platform_state = platform.state.load(); let mut signer = SimpleSigner::default(); @@ -977,15 +994,19 @@ mod tests { #[test] fn test_identity_create_asset_lock_replay_attack() { let platform_version = PlatformVersion::latest(); - let mut platform = TestPlatformBuilder::new() + let platform_config = PlatformConfig { + testing_configs: PlatformTestConfig { + disable_instant_lock_signature_verification: true, + ..Default::default() + }, + ..Default::default() + }; + + let platform = TestPlatformBuilder::new() + .with_config(platform_config) .build_with_mock_rpc() .set_initial_state_structure(); - platform - .core_rpc - .expect_verify_instant_lock() - .returning(|_, _| Ok(true)); - let platform_state = platform.state.load(); let mut signer = SimpleSigner::default(); diff --git a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/identity_top_up/mod.rs b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/identity_top_up/mod.rs index 670a1ac80cb..7bfa108e724 100644 --- a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/identity_top_up/mod.rs +++ b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/identity_top_up/mod.rs @@ -100,6 +100,7 @@ impl StateTransitionBasicStructureValidationV0 for IdentityTopUpTransition { #[cfg(test)] mod tests { + use crate::config::{PlatformConfig, PlatformTestConfig}; use crate::test::helpers::setup::TestPlatformBuilder; use dpp::block::block_info::BlockInfo; use dpp::dashcore::{Network, PrivateKey}; @@ -121,15 +122,19 @@ mod tests { #[test] fn test_identity_top_up_validation() { let platform_version = PlatformVersion::latest(); - let mut platform = TestPlatformBuilder::new() + let platform_config = PlatformConfig { + testing_configs: PlatformTestConfig { + disable_instant_lock_signature_verification: true, + ..Default::default() + }, + ..Default::default() + }; + + let platform = TestPlatformBuilder::new() + .with_config(platform_config) .build_with_mock_rpc() .set_initial_state_structure(); - platform - .core_rpc - .expect_verify_instant_lock() - .returning(|_, _| Ok(true)); - let platform_state = platform.state.load(); let mut signer = SimpleSigner::default(); diff --git a/packages/rs-drive-abci/src/mimic/mod.rs b/packages/rs-drive-abci/src/mimic/mod.rs index d548590106a..a691cd47724 100644 --- a/packages/rs-drive-abci/src/mimic/mod.rs +++ b/packages/rs-drive-abci/src/mimic/mod.rs @@ -457,7 +457,7 @@ impl<'a, C: CoreRPCLike> FullAbciApplication<'a, C> { // We need to sign the block - let quorum_type = self.platform.config.validator_set_quorum_type(); + let quorum_type = self.platform.config.validator_set.quorum_type; let state_id_hash = state_id .calculate_msg_hash(CHAIN_ID, height as i64, round as i32) .expect("cannot calculate state id hash"); @@ -480,7 +480,13 @@ impl<'a, C: CoreRPCLike> FullAbciApplication<'a, C> { threshold_vote_extensions: extensions, }; //if not in testing this will default to true - if self.platform.config.testing_configs.block_signing { + #[cfg(not(feature = "testing-config"))] + let sign_block = true; + + #[cfg(feature = "testing-config")] + let sign_block = self.platform.config.testing_configs.block_signing; + + if sign_block { let quorum_hash: [u8; 32] = quorum_hash.try_into().expect("wrong quorum hash len"); let digest = commit .calculate_sign_hash( diff --git a/packages/rs-drive-abci/src/mimic/test_quorum.rs b/packages/rs-drive-abci/src/mimic/test_quorum.rs index e32888457bc..c1653183c6d 100644 --- a/packages/rs-drive-abci/src/mimic/test_quorum.rs +++ b/packages/rs-drive-abci/src/mimic/test_quorum.rs @@ -95,6 +95,8 @@ pub struct TestQuorumInfo { pub core_height: u32, /// The hash of the quorum. pub quorum_hash: QuorumHash, + /// The quorum index. Available only for DIP24 rotated quorums. + pub quorum_index: Option, /// The set of validators that belong to the quorum. pub validator_set: Vec, /// A map of validators indexed by their `ProTxHash` identifiers. @@ -129,6 +131,7 @@ impl TestQuorumInfo { pub fn from_quorum_hash_and_pro_tx_hashes( core_height: u32, quorum_hash: QuorumHash, + quorum_index: Option, pro_tx_hashes: Vec, rng: &mut StdRng, ) -> Self { @@ -172,6 +175,7 @@ impl TestQuorumInfo { TestQuorumInfo { core_height, quorum_hash, + quorum_index, validator_set, validator_map: map, private_key: recovered_private_key, @@ -185,6 +189,7 @@ impl From<&TestQuorumInfo> for ValidatorSetV0 { let TestQuorumInfo { core_height, quorum_hash, + quorum_index, validator_set, private_key: _, public_key, @@ -199,6 +204,7 @@ impl From<&TestQuorumInfo> for ValidatorSetV0 { .map(|v| (v.pro_tx_hash, v.into())) .collect(), threshold_public_key: public_key.clone(), + quorum_index: *quorum_index, } } } @@ -208,6 +214,7 @@ impl From for ValidatorSetV0 { let TestQuorumInfo { core_height, quorum_hash, + quorum_index, validator_set, private_key: _, public_key, @@ -216,6 +223,7 @@ impl From for ValidatorSetV0 { ValidatorSetV0 { quorum_hash, + quorum_index, core_height, members: validator_set .iter() diff --git a/packages/rs-drive-abci/src/platform_types/mod.rs b/packages/rs-drive-abci/src/platform_types/mod.rs index 66a86cbbee2..f6e9b3f838e 100644 --- a/packages/rs-drive-abci/src/platform_types/mod.rs +++ b/packages/rs-drive-abci/src/platform_types/mod.rs @@ -47,8 +47,8 @@ pub mod platform; pub mod platform_state; /// Required identity public key set for system identities pub mod required_identity_public_key_set; -/// Signature verification quorums -pub mod signature_verification_quorums; +/// Signature verification quorums for Core +pub mod signature_verification_quorum_set; /// The state transition execution result as part of the block execution outcome pub mod state_transitions_processing_result; /// System identity public keys diff --git a/packages/rs-drive-abci/src/platform_types/platform/mod.rs b/packages/rs-drive-abci/src/platform_types/platform/mod.rs index 08c51c21b31..e413f3e9fc0 100644 --- a/packages/rs-drive-abci/src/platform_types/platform/mod.rs +++ b/packages/rs-drive-abci/src/platform_types/platform/mod.rs @@ -249,7 +249,8 @@ impl Platform { let platform_state = PlatformState::default_with_protocol_versions( current_protocol_version_in_consensus, next_epoch_protocol_version, - ); + &config, + )?; let height = platform_state.last_committed_block_height(); diff --git a/packages/rs-drive-abci/src/platform_types/platform_state/mod.rs b/packages/rs-drive-abci/src/platform_types/platform_state/mod.rs index be67bdb11e4..d92a5a00c88 100644 --- a/packages/rs-drive-abci/src/platform_types/platform_state/mod.rs +++ b/packages/rs-drive-abci/src/platform_types/platform_state/mod.rs @@ -20,8 +20,9 @@ use dpp::version::{PlatformVersion, TryFromPlatformVersioned, TryIntoPlatformVer use dpp::ProtocolError; use indexmap::IndexMap; +use crate::config::PlatformConfig; use crate::error::execution::ExecutionError; -use crate::platform_types::signature_verification_quorums::SignatureVerificationQuorums; +use crate::platform_types::signature_verification_quorum_set::SignatureVerificationQuorumSet; use dpp::block::block_info::BlockInfo; use dpp::util::hash::hash_double; use std::collections::BTreeMap; @@ -119,13 +120,17 @@ impl PlatformState { pub fn default_with_protocol_versions( current_protocol_version_in_consensus: ProtocolVersion, next_epoch_protocol_version: ProtocolVersion, - ) -> PlatformState { + config: &PlatformConfig, + ) -> Result { //todo find the current Platform state for the protocol version - PlatformStateV0::default_with_protocol_versions( + let state = PlatformStateV0::default_with_protocol_versions( current_protocol_version_in_consensus, next_epoch_protocol_version, - ) - .into() + config, + )? + .into(); + + Ok(state) } /// Retrieve version 0, or an error if not currently on version 0 @@ -316,7 +321,7 @@ impl PlatformStateV0Methods for PlatformState { } } - fn chain_lock_validating_quorums(&self) -> &SignatureVerificationQuorums { + fn chain_lock_validating_quorums(&self) -> &SignatureVerificationQuorumSet { match self { PlatformState::V0(v0) => &v0.chain_lock_validating_quorums, } @@ -382,12 +387,18 @@ impl PlatformStateV0Methods for PlatformState { } } - fn set_chain_lock_validating_quorums(&mut self, quorums: SignatureVerificationQuorums) { + fn set_chain_lock_validating_quorums(&mut self, quorums: SignatureVerificationQuorumSet) { match self { PlatformState::V0(v0) => v0.set_chain_lock_validating_quorums(quorums), } } + fn set_instant_lock_validating_quorums(&mut self, quorums: SignatureVerificationQuorumSet) { + match self { + PlatformState::V0(v0) => v0.set_instant_lock_validating_quorums(quorums), + } + } + fn set_full_masternode_list(&mut self, list: BTreeMap) { match self { PlatformState::V0(v0) => v0.set_full_masternode_list(list), @@ -442,7 +453,7 @@ impl PlatformStateV0Methods for PlatformState { } } - fn chain_lock_validating_quorums_mut(&mut self) -> &mut SignatureVerificationQuorums { + fn chain_lock_validating_quorums_mut(&mut self) -> &mut SignatureVerificationQuorumSet { match self { PlatformState::V0(v0) => v0.chain_lock_validating_quorums_mut(), } @@ -471,4 +482,16 @@ impl PlatformStateV0Methods for PlatformState { PlatformState::V0(v0) => v0.last_committed_block_id_hash(), } } + + fn instant_lock_validating_quorums(&self) -> &SignatureVerificationQuorumSet { + match self { + PlatformState::V0(v0) => v0.instant_lock_validating_quorums(), + } + } + + fn instant_lock_validating_quorums_mut(&mut self) -> &mut SignatureVerificationQuorumSet { + match self { + PlatformState::V0(v0) => v0.instant_lock_validating_quorums_mut(), + } + } } diff --git a/packages/rs-drive-abci/src/platform_types/platform_state/v0/mod.rs b/packages/rs-drive-abci/src/platform_types/platform_state/v0/mod.rs index 4a9da76867f..2c22025628b 100644 --- a/packages/rs-drive-abci/src/platform_types/platform_state/v0/mod.rs +++ b/packages/rs-drive-abci/src/platform_types/platform_state/v0/mod.rs @@ -19,7 +19,10 @@ use dpp::block::block_info::{BlockInfo, DEFAULT_BLOCK_INFO}; use dpp::block::extended_block_info::v0::ExtendedBlockInfoV0Getters; use dpp::version::{PlatformVersion, TryIntoPlatformVersioned}; -use crate::platform_types::signature_verification_quorums::SignatureVerificationQuorums; +use crate::config::PlatformConfig; +use crate::platform_types::signature_verification_quorum_set::{ + SignatureVerificationQuorumSet, SignatureVerificationQuorumSetForSaving, +}; use itertools::Itertools; use std::collections::BTreeMap; use std::fmt::{Debug, Formatter}; @@ -44,8 +47,11 @@ pub struct PlatformStateV0 { /// all members pub validator_sets: IndexMap, - /// The current quorums used for validating chain locks (400 60 for mainnet) - pub chain_lock_validating_quorums: SignatureVerificationQuorums, + /// Quorums used for validating chain locks (400 60 for mainnet) + pub chain_lock_validating_quorums: SignatureVerificationQuorumSet, + + /// Quorums used for validating instant locks + pub instant_lock_validating_quorums: SignatureVerificationQuorumSet, /// current full masternode list pub full_masternode_list: BTreeMap, @@ -89,6 +95,10 @@ impl Debug for PlatformStateV0 { "chain_lock_validating_quorums", &self.chain_lock_validating_quorums, ) + .field( + "instant_lock_validating_quorums", + &self.instant_lock_validating_quorums, + ) .finish() } } @@ -122,8 +132,11 @@ pub struct PlatformStateForSavingV0 { #[bincode(with_serde)] pub validator_sets: Vec<(Bytes32, ValidatorSet)>, - /// The 400 60 quorums used for validating chain locks - pub chain_lock_validating_quorums: SignatureVerificationQuorums, + /// The quorums used for validating chain locks + pub chain_lock_validating_quorums: SignatureVerificationQuorumSetForSaving, + + /// The quorums used for validating instant locks + pub instant_lock_validating_quorums: SignatureVerificationQuorumSetForSaving, /// current full masternode list pub full_masternode_list: BTreeMap, @@ -154,7 +167,8 @@ impl TryFrom for PlatformStateForSavingV0 { .into_iter() .map(|(k, v)| (k.to_byte_array().into(), v)) .collect(), - chain_lock_validating_quorums: value.chain_lock_validating_quorums, + chain_lock_validating_quorums: value.chain_lock_validating_quorums.into(), + instant_lock_validating_quorums: value.instant_lock_validating_quorums.into(), full_masternode_list: value .full_masternode_list .into_iter() @@ -197,7 +211,8 @@ impl From for PlatformStateV0 { .into_iter() .map(|(k, v)| (QuorumHash::from_byte_array(k.to_buffer()), v)) .collect(), - chain_lock_validating_quorums: value.chain_lock_validating_quorums, + chain_lock_validating_quorums: value.chain_lock_validating_quorums.into(), + instant_lock_validating_quorums: value.instant_lock_validating_quorums.into(), full_masternode_list: value .full_masternode_list .into_iter() @@ -217,23 +232,31 @@ impl PlatformStateV0 { pub(super) fn default_with_protocol_versions( current_protocol_version_in_consensus: ProtocolVersion, next_epoch_protocol_version: ProtocolVersion, - ) -> PlatformStateV0 { - let platform_version = PlatformVersion::get(current_protocol_version_in_consensus) - .expect("invalid protocol version"); + config: &PlatformConfig, + ) -> Result { + let platform_version = PlatformVersion::get(current_protocol_version_in_consensus)?; - PlatformStateV0 { + let state = PlatformStateV0 { last_committed_block_info: None, current_protocol_version_in_consensus, next_epoch_protocol_version, current_validator_set_quorum_hash: QuorumHash::all_zeros(), next_validator_set_quorum_hash: None, validator_sets: Default::default(), - chain_lock_validating_quorums: - SignatureVerificationQuorums::default_for_platform_version(platform_version), + chain_lock_validating_quorums: SignatureVerificationQuorumSet::new( + &config.chain_lock, + platform_version, + )?, + instant_lock_validating_quorums: SignatureVerificationQuorumSet::new( + &config.instant_lock, + platform_version, + )?, full_masternode_list: Default::default(), hpmn_masternode_list: Default::default(), genesis_block_info: None, - } + }; + + Ok(state) } } @@ -283,8 +306,11 @@ pub trait PlatformStateV0Methods { /// Returns the current validator sets. fn validator_sets(&self) -> &IndexMap; - /// Returns the current 400 60 quorums used to validate chain locks. - fn chain_lock_validating_quorums(&self) -> &SignatureVerificationQuorums; + /// Returns the quorums used to validate chain locks. + fn chain_lock_validating_quorums(&self) -> &SignatureVerificationQuorumSet; + + /// Returns quorums used to validate instant locks. + fn instant_lock_validating_quorums(&self) -> &SignatureVerificationQuorumSet; /// Returns the full list of masternodes. fn full_masternode_list(&self) -> &BTreeMap; @@ -317,7 +343,10 @@ pub trait PlatformStateV0Methods { fn set_validator_sets(&mut self, sets: IndexMap); /// Sets the current chain lock validating quorums. - fn set_chain_lock_validating_quorums(&mut self, quorums: SignatureVerificationQuorums); + fn set_chain_lock_validating_quorums(&mut self, quorums: SignatureVerificationQuorumSet); + + /// Sets the current instant lock validating quorums. + fn set_instant_lock_validating_quorums(&mut self, quorums: SignatureVerificationQuorumSet); /// Sets the full masternode list. fn set_full_masternode_list(&mut self, list: BTreeMap); @@ -345,8 +374,11 @@ pub trait PlatformStateV0Methods { /// Returns a mutable reference to the current validator sets. fn validator_sets_mut(&mut self) -> &mut IndexMap; - /// Returns a mutable reference to the current chain lock validating quorums. - fn chain_lock_validating_quorums_mut(&mut self) -> &mut SignatureVerificationQuorums; + /// Returns a mutable reference to the chain lock validating quorums. + fn chain_lock_validating_quorums_mut(&mut self) -> &mut SignatureVerificationQuorumSet; + + /// Returns a mutable reference to the instant lock validating quorums. + fn instant_lock_validating_quorums_mut(&mut self) -> &mut SignatureVerificationQuorumSet; /// Returns a mutable reference to the full masternode list. fn full_masternode_list_mut(&mut self) -> &mut BTreeMap; @@ -499,11 +531,16 @@ impl PlatformStateV0Methods for PlatformStateV0 { &self.validator_sets } - /// Returns the current 400 60 quorums used to validate chain locks. - fn chain_lock_validating_quorums(&self) -> &SignatureVerificationQuorums { + /// Returns the quorums used to validate chain locks. + fn chain_lock_validating_quorums(&self) -> &SignatureVerificationQuorumSet { &self.chain_lock_validating_quorums } + /// Returns the quorums used to validate instant locks. + fn instant_lock_validating_quorums(&self) -> &SignatureVerificationQuorumSet { + &self.instant_lock_validating_quorums + } + /// Returns the full list of masternodes. fn full_masternode_list(&self) -> &BTreeMap { &self.full_masternode_list @@ -561,10 +598,15 @@ impl PlatformStateV0Methods for PlatformStateV0 { } /// Sets the current chain lock validating quorums. - fn set_chain_lock_validating_quorums(&mut self, quorums: SignatureVerificationQuorums) { + fn set_chain_lock_validating_quorums(&mut self, quorums: SignatureVerificationQuorumSet) { self.chain_lock_validating_quorums = quorums; } + /// Sets the current instant lock validating quorums. + fn set_instant_lock_validating_quorums(&mut self, quorums: SignatureVerificationQuorumSet) { + self.instant_lock_validating_quorums = quorums; + } + /// Sets the full masternode list. fn set_full_masternode_list(&mut self, list: BTreeMap) { self.full_masternode_list = list; @@ -604,10 +646,14 @@ impl PlatformStateV0Methods for PlatformStateV0 { &mut self.validator_sets } - fn chain_lock_validating_quorums_mut(&mut self) -> &mut SignatureVerificationQuorums { + fn chain_lock_validating_quorums_mut(&mut self) -> &mut SignatureVerificationQuorumSet { &mut self.chain_lock_validating_quorums } + fn instant_lock_validating_quorums_mut(&mut self) -> &mut SignatureVerificationQuorumSet { + &mut self.instant_lock_validating_quorums + } + fn full_masternode_list_mut(&mut self) -> &mut BTreeMap { &mut self.full_masternode_list } diff --git a/packages/rs-drive-abci/src/platform_types/signature_verification_quorum_set/mod.rs b/packages/rs-drive-abci/src/platform_types/signature_verification_quorum_set/mod.rs new file mode 100644 index 00000000000..8d0eac3c0a3 --- /dev/null +++ b/packages/rs-drive-abci/src/platform_types/signature_verification_quorum_set/mod.rs @@ -0,0 +1,141 @@ +mod v0; + +use crate::config::QuorumLikeConfig; +use crate::error::execution::ExecutionError; +use crate::error::Error; +use crate::platform_types::signature_verification_quorum_set::v0::for_saving::SignatureVerificationQuorumSetForSavingV0; +pub use crate::platform_types::signature_verification_quorum_set::v0::quorum_set::{ + QuorumConfig, QuorumsWithConfig, SelectedQuorumSetIterator, SignatureVerificationQuorumSetV0, + SignatureVerificationQuorumSetV0Methods, SIGN_OFFSET, +}; +pub use crate::platform_types::signature_verification_quorum_set::v0::quorums::{ + Quorum, Quorums, SigningQuorum, ThresholdBlsPublicKey, VerificationQuorum, +}; +use bincode::{Decode, Encode}; +use derive_more::From; +use dpp::version::PlatformVersion; + +/// Quorums with keys for signature verification +#[derive(Debug, Clone, From)] +pub enum SignatureVerificationQuorumSet { + /// Version 0 of the signature verification quorums + V0(SignatureVerificationQuorumSetV0), +} + +impl SignatureVerificationQuorumSet { + /// Create a default SignatureVerificationQuorums + pub fn new( + config: &impl QuorumLikeConfig, + platform_version: &PlatformVersion, + ) -> Result { + match platform_version + .drive_abci + .structs + .signature_verification_quorum_set + { + 0 => Ok(SignatureVerificationQuorumSetV0::new(config).into()), + version => Err(Error::Execution(ExecutionError::UnknownVersionMismatch { + method: "SignatureVerificationQuorumSet.new".to_string(), + known_versions: vec![0], + received: version, + })), + } + } +} + +impl SignatureVerificationQuorumSetV0Methods for SignatureVerificationQuorumSet { + fn config(&self) -> &QuorumConfig { + match self { + Self::V0(v0) => v0.config(), + } + } + + fn set_current_quorums(&mut self, quorums: Quorums) { + match self { + Self::V0(v0) => v0.set_current_quorums(quorums), + } + } + + fn current_quorums(&self) -> &Quorums { + match self { + Self::V0(v0) => v0.current_quorums(), + } + } + + fn current_quorums_mut(&mut self) -> &mut Quorums { + match self { + Self::V0(v0) => v0.current_quorums_mut(), + } + } + + fn has_previous_past_quorums(&self) -> bool { + match self { + Self::V0(v0) => v0.has_previous_past_quorums(), + } + } + + fn replace_quorums( + &mut self, + quorums: Quorums, + last_active_core_height: u32, + updated_at_core_height: u32, + ) { + match self { + Self::V0(v0) => { + v0.replace_quorums(quorums, last_active_core_height, updated_at_core_height) + } + } + } + + fn set_previous_past_quorums( + &mut self, + previous_quorums: Quorums, + last_active_core_height: u32, + updated_at_core_height: u32, + ) { + match self { + Self::V0(v0) => v0.set_previous_past_quorums( + previous_quorums, + last_active_core_height, + updated_at_core_height, + ), + } + } + + fn select_quorums( + &self, + signing_height: u32, + verification_height: u32, + ) -> SelectedQuorumSetIterator { + match self { + Self::V0(v0) => v0.select_quorums(signing_height, verification_height), + } + } +} + +/// Core Quorum Set structure for saving to the database +#[derive(Debug, Clone, Encode, Decode)] +pub enum SignatureVerificationQuorumSetForSaving { + /// Version 0 of the signature verification quorums + V0(SignatureVerificationQuorumSetForSavingV0), +} + +impl From for SignatureVerificationQuorumSetForSaving { + fn from(value: SignatureVerificationQuorumSet) -> Self { + match value { + SignatureVerificationQuorumSet::V0(v0) => { + SignatureVerificationQuorumSetForSaving::V0(v0.into()) + } + } + } +} + +impl From for SignatureVerificationQuorumSet { + fn from(value: SignatureVerificationQuorumSetForSaving) -> Self { + match value { + SignatureVerificationQuorumSetForSaving::V0(v0) => { + SignatureVerificationQuorumSet::V0(v0.into()) + } + } + } +} diff --git a/packages/rs-drive-abci/src/platform_types/signature_verification_quorum_set/v0/for_saving.rs b/packages/rs-drive-abci/src/platform_types/signature_verification_quorum_set/v0/for_saving.rs new file mode 100644 index 00000000000..5e254e62023 --- /dev/null +++ b/packages/rs-drive-abci/src/platform_types/signature_verification_quorum_set/v0/for_saving.rs @@ -0,0 +1,167 @@ +use crate::platform_types::signature_verification_quorum_set::v0::quorum_set::{ + PreviousPastQuorumsV0, QuorumConfig, +}; +use crate::platform_types::signature_verification_quorum_set::{ + Quorums, SignatureVerificationQuorumSetForSaving, SignatureVerificationQuorumSetV0, + ThresholdBlsPublicKey, VerificationQuorum, +}; +use dashcore_rpc::dashcore::hashes::Hash; +use dashcore_rpc::dashcore::QuorumHash; +use dashcore_rpc::json::QuorumType; +use dpp::identity::state_transition::asset_lock_proof::Encode; +use dpp::platform_serialization::de::Decode; +use dpp::platform_value::Bytes32; + +#[derive(Debug, Clone, Encode, Decode)] +pub struct SignatureVerificationQuorumSetForSavingV0 { + config: QuorumConfigForSavingV0, + current_quorums: Vec, + previous_quorums: Option, +} + +impl From for SignatureVerificationQuorumSetForSaving { + fn from(value: SignatureVerificationQuorumSetForSavingV0) -> Self { + SignatureVerificationQuorumSetForSaving::V0(value) + } +} + +impl From for SignatureVerificationQuorumSetForSavingV0 { + fn from(value: SignatureVerificationQuorumSetV0) -> Self { + let SignatureVerificationQuorumSetV0 { + config, + current_quorums, + previous, + } = value; + + Self { + config: config.into(), + current_quorums: current_quorums.into(), + previous_quorums: previous.map(|previous| previous.into()), + } + } +} + +impl From for SignatureVerificationQuorumSetV0 { + fn from(value: SignatureVerificationQuorumSetForSavingV0) -> Self { + let SignatureVerificationQuorumSetForSavingV0 { + config, + current_quorums, + previous_quorums, + } = value; + + Self { + config: config.into(), + current_quorums: current_quorums.into(), + previous: previous_quorums.map(|previous| previous.into()), + } + } +} + +#[derive(Debug, Clone, Encode, Decode)] +pub struct QuorumConfigForSavingV0 { + quorum_type: QuorumType, + active_signers: u16, + rotation: bool, + window: u32, +} + +impl From for QuorumConfigForSavingV0 { + fn from(config: QuorumConfig) -> Self { + Self { + quorum_type: config.quorum_type, + active_signers: config.active_signers, + rotation: config.rotation, + window: config.window, + } + } +} + +impl From for QuorumConfig { + fn from(config: QuorumConfigForSavingV0) -> Self { + Self { + quorum_type: config.quorum_type, + active_signers: config.active_signers, + rotation: config.rotation, + window: config.window, + } + } +} + +#[derive(Debug, Clone, Encode, Decode)] +pub struct PreviousPastQuorumsForSavingV0 { + quorums: Vec, + active_core_height: u32, + updated_at_core_height: u32, + previous_change_height: Option, +} + +impl From for PreviousPastQuorumsForSavingV0 { + fn from(value: PreviousPastQuorumsV0) -> Self { + let PreviousPastQuorumsV0 { + quorums, + active_core_height, + updated_at_core_height, + previous_change_height, + } = value; + + Self { + quorums: quorums.into(), + active_core_height, + updated_at_core_height, + previous_change_height, + } + } +} + +impl From for PreviousPastQuorumsV0 { + fn from(value: PreviousPastQuorumsForSavingV0) -> Self { + let PreviousPastQuorumsForSavingV0 { + quorums, + active_core_height, + updated_at_core_height, + previous_change_height, + } = value; + + Self { + quorums: quorums.into(), + active_core_height, + updated_at_core_height, + previous_change_height, + } + } +} + +#[derive(Debug, Clone, Encode, Decode)] +pub struct QuorumForSavingV0 { + hash: Bytes32, + #[bincode(with_serde)] + public_key: ThresholdBlsPublicKey, + index: Option, +} + +impl From> for Quorums { + fn from(value: Vec) -> Self { + Quorums::from_iter(value.into_iter().map(|quorum| { + ( + QuorumHash::from_byte_array(quorum.hash.to_buffer()), + VerificationQuorum { + public_key: quorum.public_key, + index: quorum.index, + }, + ) + })) + } +} + +#[allow(clippy::from_over_into)] +impl Into> for Quorums { + fn into(self) -> Vec { + self.into_iter() + .map(|(hash, quorum)| QuorumForSavingV0 { + hash: Bytes32::from(hash.as_byte_array()), + public_key: quorum.public_key, + index: quorum.index, + }) + .collect() + } +} diff --git a/packages/rs-drive-abci/src/platform_types/signature_verification_quorum_set/v0/mod.rs b/packages/rs-drive-abci/src/platform_types/signature_verification_quorum_set/v0/mod.rs new file mode 100644 index 00000000000..e78d6c1c7f4 --- /dev/null +++ b/packages/rs-drive-abci/src/platform_types/signature_verification_quorum_set/v0/mod.rs @@ -0,0 +1,3 @@ +pub mod for_saving; +pub mod quorum_set; +pub mod quorums; diff --git a/packages/rs-drive-abci/src/platform_types/signature_verification_quorum_set/v0/quorum_set.rs b/packages/rs-drive-abci/src/platform_types/signature_verification_quorum_set/v0/quorum_set.rs new file mode 100644 index 00000000000..9225ced3164 --- /dev/null +++ b/packages/rs-drive-abci/src/platform_types/signature_verification_quorum_set/v0/quorum_set.rs @@ -0,0 +1,296 @@ +use crate::config::{ChainLockConfig, QuorumLikeConfig}; +use crate::platform_types::signature_verification_quorum_set::v0::quorums::Quorums; +use crate::platform_types::signature_verification_quorum_set::VerificationQuorum; +use dashcore_rpc::json::QuorumType; +use dpp::dashcore::QuorumHash; +use std::vec::IntoIter; + +/// Offset for signature verification +pub const SIGN_OFFSET: u32 = 8; + +/// Previously obtained quorums and heights. Required for signature verification +#[derive(Debug, Clone)] +pub(super) struct PreviousPastQuorumsV0 { + pub(super) quorums: Quorums, + + /// The core height at which these quorums were last active + pub(super) active_core_height: u32, + + /// The core height when the quorums were changed + pub(super) updated_at_core_height: u32, + + /// The core height the previous chain lock validating quorums became active + pub(super) previous_change_height: Option, +} + +/// Quorums with keys for signature verification +#[derive(Debug, Clone)] +pub struct SignatureVerificationQuorumSetV0 { + /// Quorum configuration + pub(super) config: QuorumConfig, + + /// Current quorums + pub(super) current_quorums: Quorums, + + /// The slightly old quorums used for validating ch ain locks (or instant locks), it's important to keep + /// these because validation of signatures happens for the quorums that are 8 blocks before the + /// height written in the chain lock. The same for instant locks + pub(super) previous: Option, +} + +/// The trait defines methods for the signature verification quorums structure v0 +pub trait SignatureVerificationQuorumSetV0Methods { + /// Config + fn config(&self) -> &QuorumConfig; + + /// Set current quorum keys + fn set_current_quorums(&mut self, quorums: Quorums); + + /// Current quorum + fn current_quorums(&self) -> &Quorums; + + /// Last quorum keys mutable + fn current_quorums_mut(&mut self) -> &mut Quorums; + + /// Has previous quorums? + fn has_previous_past_quorums(&self) -> bool; + + /// Set last quorums keys and update previous quorums + fn replace_quorums( + &mut self, + quorums: Quorums, + last_active_core_height: u32, + updated_at_core_height: u32, + ); + + /// Update previous quorums + fn set_previous_past_quorums( + &mut self, + previous_quorums: Quorums, + last_active_core_height: u32, + updated_at_core_height: u32, + ); + + /// Select quorums for signature verification based on sign and verification heights + fn select_quorums( + &self, + signing_height: u32, + verification_height: u32, + ) -> SelectedQuorumSetIterator; +} + +/// Iterator over selected quorum sets and specific quorums based on request_id and quorum configuration +pub struct SelectedQuorumSetIterator<'q> { + /// Quorum configuration + config: &'q QuorumConfig, + /// Appropriate quorum sets + quorum_set: IntoIter<&'q Quorums>, + /// Should we expect signature verification to be successful + should_be_verifiable: bool, +} + +impl<'q> Iterator for SelectedQuorumSetIterator<'q> { + type Item = QuorumsWithConfig<'q>; + + fn next(&mut self) -> Option { + self.quorum_set.next().map(|quorums| QuorumsWithConfig { + quorums, + config: self.config, + }) + } +} + +/// Quorums with configuration +pub struct QuorumsWithConfig<'q> { + /// Quorums + pub quorums: &'q Quorums, + /// Config + pub config: &'q QuorumConfig, +} + +impl<'q> QuorumsWithConfig<'q> { + /// Choose pseudorandom DIP8 or DIP24 quorum based on quorum config + /// and request_id + pub fn choose_quorum( + &self, + request_id: &[u8; 32], + ) -> Option<(QuorumHash, &VerificationQuorum)> { + self.quorums.choose_quorum(self.config, request_id) + } +} + +impl<'q> SelectedQuorumSetIterator<'q> { + /// Number of quorum sets + pub fn len(&self) -> usize { + self.quorum_set.len() + } + + /// Does the iterator have any quorum sets + pub fn is_empty(&self) -> bool { + self.quorum_set.len() == 0 + } + + /// Should we expect signature verification to be successful + pub fn should_be_verifiable(&self) -> bool { + self.should_be_verifiable + } +} + +/// Quorum configuration +#[derive(Debug, Clone)] +pub struct QuorumConfig { + /// Type + pub quorum_type: QuorumType, + /// Active quorum signers count + pub active_signers: u16, + /// Is it a DIP24 rotating quorum or classic + pub rotation: bool, + /// DKG interval + pub window: u32, +} + +impl SignatureVerificationQuorumSetV0Methods for SignatureVerificationQuorumSetV0 { + fn config(&self) -> &QuorumConfig { + &self.config + } + + fn set_current_quorums(&mut self, quorums: Quorums) { + self.current_quorums = quorums; + } + + fn current_quorums(&self) -> &Quorums { + &self.current_quorums + } + + fn current_quorums_mut(&mut self) -> &mut Quorums { + &mut self.current_quorums + } + + fn has_previous_past_quorums(&self) -> bool { + self.previous.is_some() + } + + fn replace_quorums( + &mut self, + quorums: Quorums, + last_active_height: u32, + updated_at_core_height: u32, + ) { + let previous_quorums = std::mem::replace(&mut self.current_quorums, quorums); + + self.set_previous_past_quorums( + previous_quorums, + last_active_height, + updated_at_core_height, + ); + } + + fn set_previous_past_quorums( + &mut self, + previous_quorums: Quorums, + last_active_core_height: u32, + updated_at_core_height: u32, + ) { + self.previous = Some(PreviousPastQuorumsV0 { + quorums: previous_quorums, + active_core_height: last_active_core_height, + updated_at_core_height, + previous_change_height: self + .previous + .as_ref() + .map(|previous| previous.updated_at_core_height), + }); + } + + fn select_quorums( + &self, + signing_height: u32, + verification_height: u32, + ) -> SelectedQuorumSetIterator { + let mut quorums = Vec::new(); + let mut should_be_verifiable = false; + + if let Some(previous) = &self.previous { + let previous_quorum_height = previous.active_core_height; + let change_quorum_height = previous.updated_at_core_height; + let previous_quorums_change_height = previous.previous_change_height; + + if signing_height > SIGN_OFFSET && verification_height >= change_quorum_height { + // in this case we are sure that we should be targeting the current quorum + // We updated core chain lock height from 100 to 105, new chain lock comes in for block 114 + // ------- 100 (previous_quorum_height) ------ 105 (change_quorum_height) ------ 106 (new chain lock verification height 114 - 8) + // We are sure that we should use current quorums + // If we have + // ------- 100 (previous_quorum_height) ------ 105 (change_quorum_height) ------ 105 (new chain lock verification height 113 - 8) + // We should also use current quorums, this is because at 105 we are sure new chain lock validating quorums are active + quorums.push(&self.current_quorums); + should_be_verifiable = true; + } else if signing_height > SIGN_OFFSET && verification_height <= previous_quorum_height + { + should_be_verifiable = previous_quorums_change_height + .map(|previous_quorums_change_height| { + verification_height > previous_quorums_change_height + }) + .unwrap_or(false); + // In this case the quorums were changed recently meaning that we should use the previous quorums to verify the chain lock + // We updated core chain lock height from 100 to 105, new chain lock comes in for block 106 + // -------- 98 (new chain lock verification height 106 - 8) ------- 100 (previous_quorum_height) ------ 105 (change_quorum_height) + // We are sure that we should use previous quorums + // If we have + // -------- 100 (new chain lock verification height 108 - 8) ------- 100 (previous_quorum_height) ------ 105 (change_quorum_height) + // We should also use previous quorums, this is because at 100 we are sure the old quorum set was active + quorums.push(&previous.quorums); + } else { + should_be_verifiable = previous_quorums_change_height + .map(|previous_quorums_change_height| { + verification_height > previous_quorums_change_height + }) + .unwrap_or(false); + // we are in between, so we don't actually know if it was the old one or the new one to be used. + // ------- 100 (previous_quorum_height) ------ 104 (new chain lock verification height 112 - 8) -------105 (change_quorum_height) + // we should just try both, starting with the current quorums + quorums.push(&self.current_quorums); + quorums.push(&previous.quorums); + } + } else { + quorums.push(&self.current_quorums); + } + + SelectedQuorumSetIterator { + config: &self.config, + quorum_set: quorums.into_iter(), + should_be_verifiable, + } + } +} + +impl SignatureVerificationQuorumSetV0 { + /// New empty quorum set based on quorum configuration + pub fn new(config: &impl QuorumLikeConfig) -> Self { + SignatureVerificationQuorumSetV0 { + config: QuorumConfig { + quorum_type: config.quorum_type(), + active_signers: config.quorum_active_signers(), + rotation: config.quorum_rotation(), + window: config.quorum_window(), + }, + current_quorums: Quorums::default(), + previous: None, + } + } +} + +impl From for SignatureVerificationQuorumSetV0 { + fn from(value: ChainLockConfig) -> Self { + SignatureVerificationQuorumSetV0 { + config: QuorumConfig { + quorum_type: value.quorum_type, + active_signers: value.quorum_active_signers, + rotation: value.quorum_rotation, + window: value.quorum_window, + }, + current_quorums: Quorums::default(), + previous: None, + } + } +} diff --git a/packages/rs-drive-abci/src/platform_types/signature_verification_quorum_set/v0/quorums.rs b/packages/rs-drive-abci/src/platform_types/signature_verification_quorum_set/v0/quorums.rs new file mode 100644 index 00000000000..112b877a9b8 --- /dev/null +++ b/packages/rs-drive-abci/src/platform_types/signature_verification_quorum_set/v0/quorums.rs @@ -0,0 +1,220 @@ +use derive_more::{Deref, DerefMut, From}; +use dpp::bls_signatures::PrivateKey; +use dpp::dashcore::bls_sig_utils::BLSSignature; +use dpp::dashcore::{QuorumHash, Txid}; +use std::collections::BTreeMap; +use std::convert::TryInto; +use std::fmt::Debug; + +pub use dpp::bls_signatures::PublicKey as ThresholdBlsPublicKey; + +use crate::error::Error; +use crate::platform_types::signature_verification_quorum_set::QuorumConfig; +use dpp::dashcore::hashes::{sha256d, Hash, HashEngine}; + +/// Quorum per hash +#[derive(Clone, Deref, DerefMut, From)] +pub struct Quorums(BTreeMap); + +impl Default for Quorums { + fn default() -> Self { + Quorums::(BTreeMap::new()) + } +} + +impl FromIterator<(QuorumHash, Q)> for Quorums { + fn from_iter>(iter: T) -> Self { + Quorums::(BTreeMap::from_iter(iter)) + } +} + +impl IntoIterator for Quorums { + type Item = (QuorumHash, Q); + type IntoIter = std::collections::btree_map::IntoIter; + + fn into_iter(self) -> Self::IntoIter { + self.0.into_iter() + } +} + +impl Quorums { + /// Choose pseudorandom DIP8 or DIP24 quorum based on quorum config + /// and request_id + pub fn choose_quorum( + &self, + quorum_config: &QuorumConfig, + request_id: &[u8; 32], + ) -> Option<(QuorumHash, &Q)> { + if quorum_config.rotation { + self.choose_rotating_quorum(quorum_config, request_id) + } else { + self.choose_classic_quorum(quorum_config, request_id) + } + } + + /// Based on DIP8 deterministically chooses a pseudorandom quorum from the list of quorums + fn choose_classic_quorum( + &self, + quorum_config: &QuorumConfig, + request_id: &[u8; 32], + ) -> Option<(QuorumHash, &Q)> { + // Scoring system logic + let mut scores: Vec<(&QuorumHash, &Q, [u8; 32])> = Vec::new(); + + for (quorum_hash, quorum) in self.0.iter() { + let mut quorum_hash_bytes = quorum_hash.to_byte_array().to_vec(); + + // Only the quorum hash needs reversal. + quorum_hash_bytes.reverse(); + + let mut hasher = sha256d::Hash::engine(); + + // Serialize and hash the LLMQ type + hasher.input(&[quorum_config.quorum_type as u8]); + + // Serialize and add the quorum hash + hasher.input(quorum_hash_bytes.as_slice()); + + // Serialize and add the selection hash from the chain lock + hasher.input(request_id.as_slice()); + + // Finalize the hash + let hash_result = sha256d::Hash::from_engine(hasher); + scores.push((quorum_hash, quorum, hash_result.into())); + } + + if scores.is_empty() { + return None; + } + + scores.sort_by_key(|k| k.2); + + let (quorum_hash, quorum, _) = scores.remove(0); + + Some((*quorum_hash, quorum)) + } + + /// Based on DIP24 deterministically chooses a pseudorandom quorum from the list of quorums + fn choose_rotating_quorum( + &self, + quorum_config: &QuorumConfig, + request_id: &[u8; 32], + ) -> Option<(QuorumHash, &Q)> { + let active_signers = quorum_config.active_signers as u32; + + // binary (base-2) logarithm from active_signers + let n = 31 - active_signers.leading_zeros(); + + // Extract last 64 bits of request_id + let b = u64::from_le_bytes( + request_id[24..32] + .try_into() + .expect("request_id is [u8; 32]"), + ); + + // Take last n bits of b + let mask = (1u64 << n) - 1; + let signer = (mask & (b >> (64 - n - 1))) as u32; + + self.0 + .iter() + .find(|(_, quorum)| quorum.index() == Some(signer)) + .map(|(quorum_hash, quorum)| (*quorum_hash, quorum)) + } +} + +impl Debug for Quorums { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.debug_map() + .entries( + self.0 + .iter() + .map(|(quorum_hash, quorum)| (quorum_hash.to_string(), quorum)), + ) + .finish() + } +} + +/// Quorum trait for Quorums collection +pub trait Quorum { + /// Index is present only for rotated quorums (DIP24) + fn index(&self) -> Option; +} + +/// Quorum for signature verification +#[derive(Clone)] +pub struct VerificationQuorum { + /// Index is present only for rotated quorums (DIP24) + pub index: Option, + + /// Quorum threshold public key is used to verify + /// signatures produced by corresponding quorum + pub public_key: ThresholdBlsPublicKey, +} + +impl Debug for VerificationQuorum { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.debug_struct("VerificationQuorum") + .field("index", &self.index) + .field( + "public_key", + &hex::encode(*self.public_key.to_bytes()).to_string(), + ) + .finish() + } +} + +impl Quorum for VerificationQuorum { + fn index(&self) -> Option { + self.index + } +} + +/// Quorum for signature verification +#[derive(Debug, Clone)] +pub struct SigningQuorum { + /// Index is present only for rotated quorums (DIP24) + pub index: Option, + + /// Quorum private key for signing + pub private_key: [u8; 32], +} + +impl Quorum for SigningQuorum { + fn index(&self) -> Option { + self.index + } +} + +impl SigningQuorum { + /// Signs a transition for instant lock + pub fn sign_for_instant_lock( + &self, + quorum_config: &QuorumConfig, + quorum_hash: &QuorumHash, + request_id: &[u8; 32], + transaction_id: &Txid, + ) -> Result { + // The signature must verify against the quorum public key and SHA256(llmqType, quorumHash, SHA256(height), txId). + // llmqType and quorumHash must be taken from the quorum selected in 1. + let mut engine = sha256d::Hash::engine(); + + let mut reversed_quorum_hash = quorum_hash.to_byte_array().to_vec(); + reversed_quorum_hash.reverse(); + + engine.input(&[quorum_config.quorum_type as u8]); + engine.input(reversed_quorum_hash.as_slice()); + engine.input(request_id); + engine.input(transaction_id.as_byte_array()); + + let message_digest = sha256d::Hash::from_engine(engine); + + let private_key = + PrivateKey::from_bytes(&self.private_key, false).map_err(Error::BLSError)?; + + let g2element = private_key.sign(message_digest.as_ref()); + let g2element_bytes = *g2element.to_bytes(); + + Ok(BLSSignature::from(g2element_bytes)) + } +} diff --git a/packages/rs-drive-abci/src/platform_types/signature_verification_quorums/mod.rs b/packages/rs-drive-abci/src/platform_types/signature_verification_quorums/mod.rs deleted file mode 100644 index 4ad03aebc33..00000000000 --- a/packages/rs-drive-abci/src/platform_types/signature_verification_quorums/mod.rs +++ /dev/null @@ -1,91 +0,0 @@ -mod v0; - -use crate::platform_types::signature_verification_quorums::v0::{ - PreviousPastQuorums, SelectedVerificationQuorumSets, -}; -use bincode::{Decode, Encode}; -use derive_more::From; -use dpp::version::PlatformVersion; -pub use v0::{ - QuorumKeysByQuorumHash, SignatureVerificationQuorumsV0, SignatureVerificationQuorumsV0Methods, -}; - -/// Quorums with keys for signature verification -#[derive(Debug, Clone, Encode, Decode, From)] -pub enum SignatureVerificationQuorums { - /// Version 0 of the signature verification quorums - V0(SignatureVerificationQuorumsV0), -} - -impl SignatureVerificationQuorums { - /// Create a default SignatureVerificationQuorums - pub fn default_for_platform_version(platform_version: &PlatformVersion) -> Self { - // TODO: default for platform version - - SignatureVerificationQuorumsV0::default().into() - } -} - -impl SignatureVerificationQuorumsV0Methods for SignatureVerificationQuorums { - fn set_current_quorums(&mut self, quorums: QuorumKeysByQuorumHash) { - match self { - Self::V0(v0) => v0.set_current_quorums(quorums), - } - } - - fn current_quorums(&self) -> &QuorumKeysByQuorumHash { - match self { - Self::V0(v0) => v0.current_quorums(), - } - } - - fn current_quorums_mut(&mut self) -> &mut QuorumKeysByQuorumHash { - match self { - Self::V0(v0) => v0.current_quorums_mut(), - } - } - - fn previous_past_quorums(&self) -> Option<&PreviousPastQuorums> { - match self { - Self::V0(v0) => v0.previous_past_quorums(), - } - } - - fn rotate_quorums( - &mut self, - quorums: QuorumKeysByQuorumHash, - last_active_core_height: u32, - updated_at_core_height: u32, - ) { - match self { - Self::V0(v0) => { - v0.rotate_quorums(quorums, last_active_core_height, updated_at_core_height) - } - } - } - - fn set_previous_past_quorums( - &mut self, - previous_quorums: QuorumKeysByQuorumHash, - last_active_core_height: u32, - updated_at_core_height: u32, - ) { - match self { - Self::V0(v0) => v0.set_previous_past_quorums( - previous_quorums, - last_active_core_height, - updated_at_core_height, - ), - } - } - - fn select_quorums( - &self, - signing_height: u32, - verification_height: u32, - ) -> SelectedVerificationQuorumSets { - match self { - Self::V0(v0) => v0.select_quorums(signing_height, verification_height), - } - } -} diff --git a/packages/rs-drive-abci/src/platform_types/signature_verification_quorums/v0/mod.rs b/packages/rs-drive-abci/src/platform_types/signature_verification_quorums/v0/mod.rs deleted file mode 100644 index 6ab87f6f6b0..00000000000 --- a/packages/rs-drive-abci/src/platform_types/signature_verification_quorums/v0/mod.rs +++ /dev/null @@ -1,198 +0,0 @@ -use bincode::{Decode, Encode}; -use dpp::dashcore::QuorumHash; -use std::collections::{BTreeMap, VecDeque}; - -pub use dpp::bls_signatures::PublicKey as ThresholdBlsPublicKey; - -/// Quorum key per hash -pub type QuorumKeysByQuorumHash = BTreeMap; - -/// Previously obtained quorums and heights. Required for signature verification -#[derive(Debug, Clone, Encode, Decode, Default)] -pub struct PreviousPastQuorums { - /// The quorum keys by quorum hash - #[bincode(with_serde)] - quorums: QuorumKeysByQuorumHash, - - /// The core height at which these quorums were last active - active_core_height: u32, - - /// The core height when the quorums were changed - updated_at_core_height: u32, - - /// The core height the previous chain lock validating quorums became active - previous_change_height: Option, -} - -/// Quorums with keys for signature verification -#[derive(Debug, Clone, Encode, Decode, Default)] -pub struct SignatureVerificationQuorumsV0 { - /// Current quorums - #[bincode(with_serde)] - current_quorums: QuorumKeysByQuorumHash, - - /// The slightly old quorums used for validating chain locks (or instant locks), it's important to keep - /// these because validation of signatures happens for the quorums that are 8 blocks before the - /// height written in the chain lock. The same for instant locks - previous: Option, -} - -/// The trait defines methods for the signature verification quorums structure v0 -pub trait SignatureVerificationQuorumsV0Methods { - /// Set last quorum keys - fn set_current_quorums(&mut self, quorums: QuorumKeysByQuorumHash); - - /// Current quorum keys by quorum hash - fn current_quorums(&self) -> &QuorumKeysByQuorumHash; - - /// The current quorums keys mutable - fn current_quorums_mut(&mut self) -> &mut QuorumKeysByQuorumHash; - - /// Previous quorums - fn previous_past_quorums(&self) -> Option<&PreviousPastQuorums>; - - /// Set last quorums keys and update previous quorums - fn rotate_quorums( - &mut self, - quorums: QuorumKeysByQuorumHash, - last_active_core_height: u32, - updated_at_core_height: u32, - ); - - /// Set previous quorums - fn set_previous_past_quorums( - &mut self, - previous_quorums: QuorumKeysByQuorumHash, - last_active_core_height: u32, - updated_at_core_height: u32, - ); - - /// Select quorum sets for signature verification - fn select_quorums( - &self, - signing_height: u32, - verification_height: u32, - ) -> SelectedVerificationQuorumSets; -} - -pub struct SelectedVerificationQuorumSets<'q> { - pub quorum_sets: VecDeque<&'q QuorumKeysByQuorumHash>, - pub should_be_verifiable: bool, -} - -impl<'q> Iterator for SelectedVerificationQuorumSets<'q> { - type Item = &'q QuorumKeysByQuorumHash; - - fn next(&mut self) -> Option { - self.quorum_sets.pop_front() - } -} - -impl SignatureVerificationQuorumsV0Methods for SignatureVerificationQuorumsV0 { - fn set_current_quorums(&mut self, quorums: QuorumKeysByQuorumHash) { - self.current_quorums = quorums; - } - - fn current_quorums(&self) -> &QuorumKeysByQuorumHash { - &self.current_quorums - } - - fn current_quorums_mut(&mut self) -> &mut QuorumKeysByQuorumHash { - &mut self.current_quorums - } - - fn previous_past_quorums(&self) -> Option<&PreviousPastQuorums> { - self.previous.as_ref() - } - - fn rotate_quorums( - &mut self, - quorums: QuorumKeysByQuorumHash, - last_active_height: u32, - updated_at_core_height: u32, - ) { - let previous_quorums = std::mem::replace(&mut self.current_quorums, quorums); - - self.set_previous_past_quorums( - previous_quorums, - last_active_height, - updated_at_core_height, - ); - } - - fn set_previous_past_quorums( - &mut self, - previous_quorums: QuorumKeysByQuorumHash, - last_active_core_height: u32, - updated_at_core_height: u32, - ) { - self.previous = Some(PreviousPastQuorums { - quorums: previous_quorums, - active_core_height: last_active_core_height, - updated_at_core_height, - previous_change_height: self - .previous - .as_ref() - .map(|previous| previous.updated_at_core_height), - }); - } - - fn select_quorums( - &self, - signing_height: u32, - verification_height: u32, - ) -> SelectedVerificationQuorumSets { - let mut quorums = VecDeque::new(); - let mut should_be_verifiable = false; - - if let Some(previous) = &self.previous { - let previous_quorum_height = previous.active_core_height; - let change_quorum_height = previous.updated_at_core_height; - let previous_quorums_change_height = previous.previous_change_height; - - if signing_height > 8 && verification_height >= change_quorum_height { - // in this case we are sure that we should be targeting the current quorum - // We updated core chain lock height from 100 to 105, new chain lock comes in for block 114 - // ------- 100 (previous_quorum_height) ------ 105 (change_quorum_height) ------ 106 (new chain lock verification height 114 - 8) - // We are sure that we should use current quorums - // If we have - // ------- 100 (previous_quorum_height) ------ 105 (change_quorum_height) ------ 105 (new chain lock verification height 113 - 8) - // We should also use current quorums, this is because at 105 we are sure new chain lock validating quorums are active - quorums.push_back(&self.current_quorums); - should_be_verifiable = true; - } else if signing_height > 8 && verification_height <= previous_quorum_height { - should_be_verifiable = previous_quorums_change_height - .map(|previous_quorums_change_height| { - verification_height > previous_quorums_change_height - }) - .unwrap_or(false); - // In this case the quorums were changed recently meaning that we should use the previous quorums to verify the chain lock - // We updated core chain lock height from 100 to 105, new chain lock comes in for block 106 - // -------- 98 (new chain lock verification height 106 - 8) ------- 100 (previous_quorum_height) ------ 105 (change_quorum_height) - // We are sure that we should use previous quorums - // If we have - // -------- 100 (new chain lock verification height 108 - 8) ------- 100 (previous_quorum_height) ------ 105 (change_quorum_height) - // We should also use previous quorums, this is because at 100 we are sure the old quorum set was active - quorums.push_back(&previous.quorums); - } else { - should_be_verifiable = previous_quorums_change_height - .map(|previous_quorums_change_height| { - verification_height > previous_quorums_change_height - }) - .unwrap_or(false); - // we are in between, so we don't actually know if it was the old one or the new one to be used. - // ------- 100 (previous_quorum_height) ------ 104 (new chain lock verification height 112 - 8) -------105 (change_quorum_height) - // we should just try both, starting with the current quorums - quorums.push_back(&self.current_quorums); - quorums.push_back(&previous.quorums); - } - } else { - quorums.push_back(&self.current_quorums); - } - - SelectedVerificationQuorumSets { - quorum_sets: quorums, - should_be_verifiable, - } - } -} diff --git a/packages/rs-drive-abci/src/platform_types/validator_set/mod.rs b/packages/rs-drive-abci/src/platform_types/validator_set/mod.rs index 70fd7fe1067..5dd9adb1f83 100644 --- a/packages/rs-drive-abci/src/platform_types/validator_set/mod.rs +++ b/packages/rs-drive-abci/src/platform_types/validator_set/mod.rs @@ -26,6 +26,12 @@ impl ValidatorSetV0Getters for ValidatorSet { } } + fn quorum_index(&self) -> Option { + match self { + ValidatorSet::V0(v0) => v0.quorum_index(), + } + } + fn core_height(&self) -> u32 { match self { ValidatorSet::V0(v0) => v0.core_height(), @@ -64,6 +70,12 @@ impl ValidatorSetV0Setters for ValidatorSet { } } + fn set_quorum_index(&mut self, index: Option) { + match self { + ValidatorSet::V0(v0) => v0.set_quorum_index(index), + } + } + fn set_core_height(&mut self, core_height: u32) { match self { ValidatorSet::V0(v0) => v0.set_core_height(core_height), diff --git a/packages/rs-drive-abci/src/platform_types/validator_set/v0/mod.rs b/packages/rs-drive-abci/src/platform_types/validator_set/v0/mod.rs index 3adf9559b02..7574a5d31db 100644 --- a/packages/rs-drive-abci/src/platform_types/validator_set/v0/mod.rs +++ b/packages/rs-drive-abci/src/platform_types/validator_set/v0/mod.rs @@ -21,6 +21,8 @@ use tenderdash_abci::proto::{abci, crypto}; pub struct ValidatorSetV0 { /// The quorum hash pub quorum_hash: QuorumHash, + /// Rotation quorum index is available only for DIP24 quorums + pub quorum_index: Option, /// Active height pub core_height: u32, /// The list of masternodes @@ -297,6 +299,7 @@ impl ValidatorSetV0 { let QuorumInfoResult { height, quorum_hash, + quorum_index, quorum_public_key, members, .. @@ -332,8 +335,15 @@ impl ValidatorSetV0 { let threshold_public_key = BlsPublicKey::from_bytes(quorum_public_key.as_slice()) .map_err(ExecutionError::BlsErrorFromDashCoreResponse)?; + let optional_quorum_index = if quorum_index == 0 { + None + } else { + Some(quorum_index) + }; + Ok(ValidatorSetV0 { quorum_hash, + quorum_index: optional_quorum_index, core_height: height, members: validator_set, threshold_public_key, @@ -345,6 +355,8 @@ impl ValidatorSetV0 { pub trait ValidatorSetV0Getters { /// Returns the quorum hash of the validator set. fn quorum_hash(&self) -> &QuorumHash; + /// Returns rotation quorum index. It's available only for DIP24 quorums + fn quorum_index(&self) -> Option; /// Returns the active height of the validator set. fn core_height(&self) -> u32; /// Returns the members of the validator set. @@ -361,6 +373,8 @@ pub trait ValidatorSetV0Getters { pub trait ValidatorSetV0Setters { /// Sets the quorum hash of the validator set. fn set_quorum_hash(&mut self, quorum_hash: QuorumHash); + /// Sets the quorum index of the validator set. + fn set_quorum_index(&mut self, index: Option); /// Sets the active height of the validator set. fn set_core_height(&mut self, core_height: u32); /// Sets the members of the validator set. @@ -374,6 +388,10 @@ impl ValidatorSetV0Getters for ValidatorSetV0 { &self.quorum_hash } + fn quorum_index(&self) -> Option { + self.quorum_index + } + fn core_height(&self) -> u32 { self.core_height } @@ -400,6 +418,10 @@ impl ValidatorSetV0Setters for ValidatorSetV0 { self.quorum_hash = quorum_hash; } + fn set_quorum_index(&mut self, index: Option) { + self.quorum_index = index; + } + fn set_core_height(&mut self, core_height: u32) { self.core_height = core_height; } diff --git a/packages/rs-drive-abci/src/query/response_metadata/v0/mod.rs b/packages/rs-drive-abci/src/query/response_metadata/v0/mod.rs index 12286271562..edd234ab2d4 100644 --- a/packages/rs-drive-abci/src/query/response_metadata/v0/mod.rs +++ b/packages/rs-drive-abci/src/query/response_metadata/v0/mod.rs @@ -28,7 +28,7 @@ impl Platform { Proof { grovedb_proof: proof, quorum_hash: platform_state.last_committed_quorum_hash().to_vec(), - quorum_type: self.config.validator_set_quorum_type() as u32, + quorum_type: self.config.validator_set.quorum_type as u32, block_id_hash: platform_state.last_committed_block_id_hash().to_vec(), signature: platform_state.last_committed_block_signature().to_vec(), round: platform_state.last_committed_block_round(), diff --git a/packages/rs-drive-abci/tests/strategy_tests/chain_lock_update.rs b/packages/rs-drive-abci/tests/strategy_tests/chain_lock_update.rs index f80ec3645de..c406e2159d8 100644 --- a/packages/rs-drive-abci/tests/strategy_tests/chain_lock_update.rs +++ b/packages/rs-drive-abci/tests/strategy_tests/chain_lock_update.rs @@ -4,7 +4,10 @@ mod tests { use crate::execution::run_chain_for_strategy; use crate::strategy::CoreHeightIncrease::RandomCoreHeightIncrease; use crate::strategy::{MasternodeListChangesStrategy, NetworkStrategy}; - use drive_abci::config::{ExecutionConfig, PlatformConfig, PlatformTestConfig}; + use drive_abci::config::{ + ChainLockConfig, ExecutionConfig, InstantLockConfig, PlatformConfig, PlatformTestConfig, + ValidatorSetConfig, + }; use drive_abci::test::helpers::setup::TestPlatformBuilder; use strategy_tests::frequency::Frequency; @@ -58,19 +61,19 @@ mod tests { ..Default::default() }; - let quorum_size = 100; - let config = PlatformConfig { - validator_set_quorum_size: quorum_size, - validator_set_quorum_type: "llmq_100_67".to_string(), - chain_lock_quorum_type: "llmq_400_60".to_string(), + instant_lock: InstantLockConfig::default_100_67(), execution: ExecutionConfig { verify_sum_trees: true, validator_set_rotation_block_count: 25, ..Default::default() }, block_spacing_ms: 3000, - testing_configs: PlatformTestConfig::default_with_no_block_signing(), + testing_configs: PlatformTestConfig { + block_signing: false, + block_commit_signature_verification: false, + disable_instant_lock_signature_verification: true, + }, ..Default::default() }; let mut platform = TestPlatformBuilder::new() diff --git a/packages/rs-drive-abci/tests/strategy_tests/core_update_tests.rs b/packages/rs-drive-abci/tests/strategy_tests/core_update_tests.rs index 4c892673123..5ec8b6b9d29 100644 --- a/packages/rs-drive-abci/tests/strategy_tests/core_update_tests.rs +++ b/packages/rs-drive-abci/tests/strategy_tests/core_update_tests.rs @@ -4,7 +4,10 @@ mod tests { use crate::execution::run_chain_for_strategy; use crate::strategy::CoreHeightIncrease::RandomCoreHeightIncrease; use crate::strategy::{MasternodeListChangesStrategy, NetworkStrategy}; - use drive_abci::config::{ExecutionConfig, PlatformConfig, PlatformTestConfig}; + use drive_abci::config::{ + ChainLockConfig, ExecutionConfig, InstantLockConfig, PlatformConfig, PlatformTestConfig, + ValidatorSetConfig, + }; use drive_abci::platform_types::platform_state::v0::PlatformStateV0Methods; use drive_abci::platform_types::validator_set::v0::ValidatorSetV0Getters; use drive_abci::test::helpers::setup::TestPlatformBuilder; @@ -61,9 +64,12 @@ mod tests { let quorum_size = 100; let config = PlatformConfig { - validator_set_quorum_size: quorum_size, - validator_set_quorum_type: "llmq_100_67".to_string(), - chain_lock_quorum_type: "llmq_100_67".to_string(), + validator_set: ValidatorSetConfig { + quorum_size, + ..Default::default() + }, + + instant_lock: InstantLockConfig::default_100_67(), execution: ExecutionConfig { verify_sum_trees: true, validator_set_rotation_block_count: 25, @@ -159,9 +165,12 @@ mod tests { let quorum_size = 100; let config = PlatformConfig { - validator_set_quorum_size: quorum_size, - validator_set_quorum_type: "llmq_100_67".to_string(), - chain_lock_quorum_type: "llmq_100_67".to_string(), + validator_set: ValidatorSetConfig { + quorum_size, + ..Default::default() + }, + chain_lock: ChainLockConfig::default_100_67(), + instant_lock: InstantLockConfig::default_100_67(), execution: ExecutionConfig { verify_sum_trees: true, validator_set_rotation_block_count: 25, @@ -246,9 +255,12 @@ mod tests { let quorum_size = 100; let config = PlatformConfig { - validator_set_quorum_size: quorum_size, - validator_set_quorum_type: "llmq_100_67".to_string(), - chain_lock_quorum_type: "llmq_100_67".to_string(), + validator_set: ValidatorSetConfig { + quorum_size, + ..Default::default() + }, + chain_lock: ChainLockConfig::default_100_67(), + instant_lock: InstantLockConfig::default_100_67(), execution: ExecutionConfig { verify_sum_trees: true, validator_set_rotation_block_count: 25, diff --git a/packages/rs-drive-abci/tests/strategy_tests/execution.rs b/packages/rs-drive-abci/tests/strategy_tests/execution.rs index 3db5a245faa..08728958757 100644 --- a/packages/rs-drive-abci/tests/strategy_tests/execution.rs +++ b/packages/rs-drive-abci/tests/strategy_tests/execution.rs @@ -31,6 +31,7 @@ use drive_abci::mimic::{MimicExecuteBlockOptions, MimicExecuteBlockOutcome}; use drive_abci::platform_types::epoch_info::v0::EpochInfoV0; use drive_abci::platform_types::platform::Platform; use drive_abci::platform_types::platform_state::v0::PlatformStateV0Methods; +use drive_abci::platform_types::signature_verification_quorum_set::{Quorums, SigningQuorum}; use drive_abci::platform_types::withdrawal::unsigned_withdrawal_txs::v0::UnsignedWithdrawalTxs; use drive_abci::rpc::core::MockCoreRPCLike; use drive_abci::test::fixture::abci::static_init_chain_request; @@ -50,13 +51,16 @@ pub(crate) fn run_chain_for_strategy( platform: &mut Platform, block_count: u64, strategy: NetworkStrategy, - config: PlatformConfig, + mut config: PlatformConfig, seed: u64, ) -> ChainExecutionOutcome { + // TODO: Do we want to sign instant locks or just disable verification? + let validator_quorum_count = strategy.validator_quorum_count; // In most tests 24 quorums let chain_lock_quorum_count = strategy.chain_lock_quorum_count; // In most tests 4 quorums when not the same as validator - let validator_set_quorum_size = config.validator_set_quorum_size; - let chain_lock_quorum_size = config.chain_lock_quorum_size; + let instant_lock_quorum_count = strategy.instant_lock_quorum_count; // In most tests 24 quorums when not the same as validator + let validator_set_quorum_size = config.validator_set.quorum_size; + let chain_lock_quorum_size = config.chain_lock.quorum_size; let mut rng = StdRng::seed_from_u64(seed); @@ -68,7 +72,7 @@ pub(crate) fn run_chain_for_strategy( let max_core_height = core_height_increase.max_core_height(block_count, strategy.initial_core_height); - let chain_lock_quorum_type = config.chain_lock_quorum_type(); + let chain_lock_quorum_type = config.chain_lock.quorum_type; let sign_chain_locks = strategy.sign_chain_locks; @@ -242,7 +246,7 @@ pub(crate) fn run_chain_for_strategy( &mut rng, ); - let mut quorums_details: Vec<(QuorumHash, ExtendedQuorumDetails)> = validator_quorums + let mut validator_quorums_details: Vec<(QuorumHash, ExtendedQuorumDetails)> = validator_quorums .keys() .map(|quorum_hash| { ( @@ -258,10 +262,10 @@ pub(crate) fn run_chain_for_strategy( }) .collect(); - quorums_details.shuffle(&mut rng); + validator_quorums_details.shuffle(&mut rng); let (chain_lock_quorums, chain_lock_quorums_details) = - if config.validator_set_quorum_type != config.chain_lock_quorum_type { + if config.validator_set.quorum_type != config.chain_lock.quorum_type { let total_chain_lock_quorums = if strategy.rotate_quorums { chain_lock_quorum_count * 10 } else { @@ -301,6 +305,95 @@ pub(crate) fn run_chain_for_strategy( (BTreeMap::new(), vec![]) }; + let (instant_lock_quorum_infos, instant_lock_quorums_details, instant_lock_signing_quorums) = + if config.validator_set.quorum_type != config.instant_lock.quorum_type { + // TODO: Implement instant lock quorums rotation? + let total_instant_lock_quorums = if strategy.rotate_quorums { + instant_lock_quorum_count * 10 + } else { + instant_lock_quorum_count + }; + + let instant_lock_quorums_infos = masternodes::generate_test_quorums( + total_instant_lock_quorums as usize, + initial_all_masternodes + .iter() + .map(|masternode| &masternode.masternode), + config.instant_lock.quorum_size as usize, + &mut rng, + ); + + let mut instant_lock_quorums_details: Vec<(QuorumHash, ExtendedQuorumDetails)> = + instant_lock_quorums_infos + .iter() + .map(|(hash, quorum)| { + ( + *hash, + ExtendedQuorumDetails { + creation_height: 0, + quorum_index: quorum.quorum_index, + mined_block_hash: BlockHash::all_zeros(), + num_valid_members: 0, + health_ratio: 0.0, + }, + ) + }) + .collect(); + + instant_lock_quorums_details.shuffle(&mut rng); + + let instant_lock_signing_quorums: Quorums = + if strategy.sign_instant_locks { + instant_lock_quorums_infos + .iter() + .map(|(quorum_hash, info)| { + let bytes = info.private_key.to_bytes(); + let fixed_bytes: [u8; 32] = bytes + .as_slice() + .try_into() + .expect("Expected a byte array of length 32"); + ( + *quorum_hash, + SigningQuorum { + index: info.quorum_index, + private_key: fixed_bytes, + }, + ) + }) + .collect() + } else { + Default::default() + }; + + ( + instant_lock_quorums_infos, + instant_lock_quorums_details, + instant_lock_signing_quorums, + ) + } else if strategy.sign_instant_locks { + let signing_quorums = validator_quorums + .iter() + .map(|(quorum_hash, info)| { + let bytes = info.private_key.to_bytes(); + let fixed_bytes: [u8; 32] = bytes + .as_slice() + .try_into() + .expect("Expected a byte array of length 32"); + ( + *quorum_hash, + SigningQuorum { + index: info.quorum_index, + private_key: fixed_bytes, + }, + ) + }) + .collect(); + + (Default::default(), Default::default(), signing_quorums) + } else { + Default::default() + }; + let start_core_height = platform.config.abci.genesis_core_height; platform @@ -330,17 +423,12 @@ pub(crate) fn run_chain_for_strategy( })) }); - platform - .core_rpc - .expect_verify_instant_lock() - .returning(|_, _| Ok(true)); - platform .core_rpc .expect_get_quorum_listextended() .returning(move |core_height: Option| { let validator_set_extended_info = if !strategy.rotate_quorums { - quorums_details.clone().into_iter().collect() + validator_quorums_details.clone().into_iter().collect() } else { let core_height = core_height.expect("expected a core height"); // if we rotate quorums we shouldn't give back the same ones every time @@ -350,18 +438,18 @@ pub(crate) fn run_chain_for_strategy( let end_range = end_range % total_validator_quorums as u32; if end_range > start_range { - quorums_details + validator_quorums_details .iter() .skip(start_range as usize) .take((end_range - start_range) as usize) .map(|(quorum_hash, quorum)| (*quorum_hash, quorum.clone())) .collect() } else { - let first_range = quorums_details + let first_range = validator_quorums_details .iter() .skip(start_range as usize) .take((total_validator_quorums as u32 - start_range) as usize); - let second_range = quorums_details.iter().take(end_range as usize); + let second_range = validator_quorums_details.iter().take(end_range as usize); first_range .chain(second_range) .map(|(quorum_hash, quorum)| (*quorum_hash, quorum.clone())) @@ -379,6 +467,13 @@ pub(crate) fn run_chain_for_strategy( ); } + if !instant_lock_quorums_details.is_empty() { + quorums_by_type.insert( + QuorumType::Llmq60_75, + instant_lock_quorums_details.clone().into_iter().collect(), + ); + } + let result = ExtendedQuorumListResult { quorums_by_type }; Ok(result) @@ -387,6 +482,7 @@ pub(crate) fn run_chain_for_strategy( let all_quorums_info: HashMap = validator_quorums .iter() .chain(chain_lock_quorums.iter()) + .chain(instant_lock_quorum_infos.iter()) .map(|(quorum_hash, test_quorum_info)| (*quorum_hash, test_quorum_info.into())) .collect(); @@ -661,6 +757,7 @@ pub(crate) fn run_chain_for_strategy( block_count, all_hpmns_with_updates, validator_quorums, + instant_lock_signing_quorums, strategy, config, rng, @@ -671,7 +768,8 @@ pub(crate) fn create_chain_for_strategy( platform: &Platform, block_count: u64, proposers_with_updates: Vec, - quorums: BTreeMap, + validator_quorums: BTreeMap, + instant_lock_quorums: Quorums, strategy: NetworkStrategy, config: PlatformConfig, rng: StdRng, @@ -688,7 +786,8 @@ pub(crate) fn create_chain_for_strategy( abci_application, block_count, proposers_with_updates, - quorums, + validator_quorums, + instant_lock_quorums, strategy, config, seed, @@ -699,7 +798,8 @@ pub(crate) fn start_chain_for_strategy( abci_application: FullAbciApplication, block_count: u64, proposers_with_updates: Vec, - quorums: BTreeMap, + validator_quorums: BTreeMap, + instant_lock_quorums: Quorums, strategy: NetworkStrategy, config: PlatformConfig, seed: StrategyRandomness, @@ -709,14 +809,14 @@ pub(crate) fn start_chain_for_strategy( StrategyRandomness::RNGEntropy(rng) => rng, }; - let quorum_hashes: Vec<&QuorumHash> = quorums.keys().collect(); + let quorum_hashes: Vec<&QuorumHash> = validator_quorums.keys().collect(); - let mut current_quorum_hash = **quorum_hashes + let mut current_validator_quorum_hash = **quorum_hashes .choose(&mut rng) .expect("expected quorums to be initialized"); - let current_quorum_with_test_info = quorums - .get::(¤t_quorum_hash) + let current_quorum_with_test_info = validator_quorums + .get::(¤t_validator_quorum_hash) .expect("expected a quorum to be found"); // init chain @@ -743,7 +843,7 @@ pub(crate) fn start_chain_for_strategy( current_quorum_with_test_info.public_key.to_bytes().to_vec(), )), }), - quorum_hash: current_quorum_hash.to_byte_array().to_vec(), + quorum_hash: current_validator_quorum_hash.to_byte_array().to_vec(), }); let ResponseInitChain { @@ -754,7 +854,7 @@ pub(crate) fn start_chain_for_strategy( .expect("should init chain"); // initialization will change the current quorum hash - current_quorum_hash = abci_application + current_validator_quorum_hash = abci_application .platform .state .load() @@ -767,8 +867,9 @@ pub(crate) fn start_chain_for_strategy( core_height_start: initial_core_height, block_count, proposers: proposers_with_updates, - quorums, - current_quorum_hash, + validator_quorums, + current_validator_quorum_hash, + instant_lock_quorums, current_proposer_versions: None, current_identity_nonce_counter: Default::default(), current_identity_contract_nonce_counter: Default::default(), @@ -794,19 +895,20 @@ pub(crate) fn continue_chain_for_strategy( core_height_start: _, block_count, proposers: proposers_with_updates, - quorums, - mut current_quorum_hash, + validator_quorums: quorums, + current_validator_quorum_hash: mut current_quorum_hash, current_proposer_versions, mut current_identity_nonce_counter, mut current_identity_contract_nonce_counter, start_time_ms, mut current_time_ms, + instant_lock_quorums, } = chain_execution_parameters; let mut rng = match seed { StrategyRandomness::SeedEntropy(seed) => StdRng::seed_from_u64(seed), StrategyRandomness::RNGEntropy(rng) => rng, }; - let quorum_size = config.validator_set_quorum_size; + let quorum_size = config.validator_set.quorum_size; let first_block_time = start_time_ms; let mut current_identities = vec![]; let mut signer = strategy.strategy.signer.clone().unwrap_or_default(); @@ -877,6 +979,7 @@ pub(crate) fn continue_chain_for_strategy( &mut current_identity_contract_nonce_counter, &mut signer, &mut rng, + &instant_lock_quorums, ); state_transitions_per_block.insert(block_height, state_transitions.clone()); @@ -1013,7 +1116,7 @@ pub(crate) fn continue_chain_for_strategy( query_strategy.query_chain_for_strategy( &ProofVerification { quorum_hash: ¤t_quorum_with_test_info.quorum_hash.into(), - quorum_type: config.validator_set_quorum_type(), + quorum_type: config.validator_set.quorum_type, app_version, chain_id: drive_abci::mimic::CHAIN_ID.to_string(), core_chain_locked_height: state_id.core_chain_locked_height, @@ -1076,8 +1179,8 @@ pub(crate) fn continue_chain_for_strategy( masternode_identity_balances, identities: current_identities, proposers: proposers_with_updates, - quorums, - current_quorum_hash, + validator_quorums: quorums, + current_validator_quorum_hash: current_quorum_hash, current_proposer_versions: proposer_versions, identity_nonce_counter: current_identity_nonce_counter, identity_contract_nonce_counter: current_identity_contract_nonce_counter, @@ -1087,5 +1190,6 @@ pub(crate) fn continue_chain_for_strategy( withdrawals: total_withdrawals, validator_set_updates, state_transition_results_per_block, + instant_lock_quorums, } } diff --git a/packages/rs-drive-abci/tests/strategy_tests/failures.rs b/packages/rs-drive-abci/tests/strategy_tests/failures.rs index c1fe8150951..addb94cdbf7 100644 --- a/packages/rs-drive-abci/tests/strategy_tests/failures.rs +++ b/packages/rs-drive-abci/tests/strategy_tests/failures.rs @@ -7,7 +7,10 @@ mod tests { use crate::strategy::{FailureStrategy, NetworkStrategy}; use strategy_tests::{IdentityInsertInfo, StartIdentities, Strategy}; - use drive_abci::config::{ExecutionConfig, PlatformConfig, PlatformTestConfig}; + use drive_abci::config::{ + ChainLockConfig, ExecutionConfig, InstantLockConfig, PlatformConfig, PlatformTestConfig, + ValidatorSetConfig, + }; use dpp::dashcore::hashes::Hash; use dpp::dashcore::{BlockHash, ChainLock}; @@ -75,16 +78,20 @@ mod tests { ..Default::default() }; let config = PlatformConfig { - validator_set_quorum_size: 100, - validator_set_quorum_type: "llmq_100_67".to_string(), - chain_lock_quorum_type: "llmq_100_67".to_string(), + validator_set: ValidatorSetConfig::default_100_67(), + chain_lock: ChainLockConfig::default_100_67(), + instant_lock: InstantLockConfig::default_100_67(), execution: ExecutionConfig { verify_sum_trees: true, validator_set_rotation_block_count: 25, ..Default::default() }, block_spacing_ms: 3000, - testing_configs: PlatformTestConfig::default_with_no_block_signing(), + testing_configs: PlatformTestConfig { + block_signing: false, + block_commit_signature_verification: false, + disable_instant_lock_signature_verification: true, + }, ..Default::default() }; let mut platform = TestPlatformBuilder::new() @@ -150,9 +157,9 @@ mod tests { ..Default::default() }; let config = PlatformConfig { - validator_set_quorum_size: 100, - validator_set_quorum_type: "llmq_100_67".to_string(), - chain_lock_quorum_type: "llmq_100_67".to_string(), + validator_set: ValidatorSetConfig::default_100_67(), + chain_lock: ChainLockConfig::default_100_67(), + instant_lock: InstantLockConfig::default_100_67(), execution: ExecutionConfig { verify_sum_trees: true, validator_set_rotation_block_count: 25, @@ -198,9 +205,9 @@ mod tests { // // We use the dpns contract and we insert two documents both with the same "name" // // This is a common scenario we should see quite often // let config = PlatformConfig { - // validator_set_quorum_size: 100, - // validator_set_quorum_type: "llmq_100_67".to_string(), - // chain_lock_quorum_type: "llmq_100_67".to_string(), + // validator_set_quorum_quorum_size: 100, + // validator_set_quorum_type: QuorumType::Llmq100_67, + // chain_lock_quorum_type: QuorumType::Llmq100_67, // execution: ExecutionConfig { // //we disable document triggers because we are using dpns and dpns needs a preorder // use_document_triggers: false, diff --git a/packages/rs-drive-abci/tests/strategy_tests/main.rs b/packages/rs-drive-abci/tests/strategy_tests/main.rs index 43ea171e360..bef89ceca8c 100644 --- a/packages/rs-drive-abci/tests/strategy_tests/main.rs +++ b/packages/rs-drive-abci/tests/strategy_tests/main.rs @@ -47,7 +47,7 @@ mod tests { use dashcore_rpc::dashcore::hashes::Hash; use dashcore_rpc::dashcore::BlockHash; use dashcore_rpc::dashcore_rpc_json::AssetUnlockStatus; - use dashcore_rpc::json::AssetUnlockStatusResult; + use dashcore_rpc::json::{AssetUnlockStatusResult, QuorumType}; use dpp::block::extended_block_info::v0::ExtendedBlockInfoV0Getters; use std::sync::{Arc, Mutex}; use strategy_tests::operations::DocumentAction::{ @@ -74,7 +74,9 @@ mod tests { use dpp::version::PlatformVersion; use drive::drive::config::DEFAULT_QUERY_LIMIT; use drive::drive::identity::withdrawals::WithdrawalTransactionIndex; - use drive_abci::config::{ExecutionConfig, PlatformTestConfig}; + use drive_abci::config::{ + ChainLockConfig, ExecutionConfig, InstantLockConfig, PlatformTestConfig, ValidatorSetConfig, + }; use drive_abci::logging::LogLevel; use drive_abci::platform_types::platform_state::v0::PlatformStateV0Methods; @@ -113,9 +115,9 @@ mod tests { ..Default::default() }; let config = PlatformConfig { - validator_set_quorum_size: 100, - validator_set_quorum_type: "llmq_100_67".to_string(), - chain_lock_quorum_type: "llmq_100_67".to_string(), + validator_set: ValidatorSetConfig::default_100_67(), + chain_lock: ChainLockConfig::default_100_67(), + instant_lock: InstantLockConfig::default_100_67(), execution: ExecutionConfig { verify_sum_trees: true, validator_set_rotation_block_count: 25, @@ -158,9 +160,9 @@ mod tests { ..Default::default() }; let config = PlatformConfig { - validator_set_quorum_size: 100, - validator_set_quorum_type: "llmq_100_67".to_string(), - chain_lock_quorum_type: "llmq_100_67".to_string(), + validator_set: ValidatorSetConfig::default_100_67(), + chain_lock: ChainLockConfig::default_100_67(), + instant_lock: InstantLockConfig::default_100_67(), execution: ExecutionConfig { verify_sum_trees: true, validator_set_rotation_block_count: 25, @@ -203,9 +205,9 @@ mod tests { ..Default::default() }; let config = PlatformConfig { - validator_set_quorum_size: 100, - validator_set_quorum_type: "llmq_100_67".to_string(), - chain_lock_quorum_type: "llmq_100_67".to_string(), + validator_set: ValidatorSetConfig::default_100_67(), + chain_lock: ChainLockConfig::default_100_67(), + instant_lock: InstantLockConfig::default_100_67(), execution: ExecutionConfig { verify_sum_trees: true, validator_set_rotation_block_count: 25, @@ -225,12 +227,13 @@ mod tests { let ChainExecutionOutcome { abci_app, proposers, - quorums, - current_quorum_hash, + validator_quorums: quorums, + current_validator_quorum_hash: current_quorum_hash, current_proposer_versions, end_time_ms, identity_nonce_counter, identity_contract_nonce_counter, + instant_lock_quorums, .. } = run_chain_for_strategy(&mut platform, 15, strategy.clone(), config.clone(), 40); @@ -289,13 +292,14 @@ mod tests { core_height_start: 1, block_count: 30, proposers, - quorums, - current_quorum_hash, + validator_quorums: quorums, + current_validator_quorum_hash: current_quorum_hash, current_proposer_versions: Some(current_proposer_versions), current_identity_nonce_counter: identity_nonce_counter, current_identity_contract_nonce_counter: identity_contract_nonce_counter, start_time_ms: 1681094380000, current_time_ms: end_time_ms, + instant_lock_quorums, }, strategy, config, @@ -335,9 +339,9 @@ mod tests { ..Default::default() }; let config = PlatformConfig { - validator_set_quorum_size: 100, - validator_set_quorum_type: "llmq_100_67".to_string(), - chain_lock_quorum_type: "llmq_100_67".to_string(), + validator_set: ValidatorSetConfig::default_100_67(), + chain_lock: ChainLockConfig::default_100_67(), + instant_lock: InstantLockConfig::default_100_67(), execution: ExecutionConfig { verify_sum_trees: true, validator_set_rotation_block_count: 25, @@ -357,12 +361,13 @@ mod tests { let ChainExecutionOutcome { abci_app, proposers, - quorums, - current_quorum_hash, + validator_quorums: quorums, + current_validator_quorum_hash: current_quorum_hash, current_proposer_versions, end_time_ms, identity_nonce_counter, identity_contract_nonce_counter, + instant_lock_quorums, .. } = run_chain_for_strategy(&mut platform, 15, strategy.clone(), config.clone(), 40); @@ -421,13 +426,14 @@ mod tests { core_height_start: 1, block_count: 30, proposers, - quorums, - current_quorum_hash, + validator_quorums: quorums, + current_validator_quorum_hash: current_quorum_hash, current_proposer_versions: Some(current_proposer_versions), current_identity_nonce_counter: identity_nonce_counter, current_identity_contract_nonce_counter: identity_contract_nonce_counter, start_time_ms: 1681094380000, current_time_ms: end_time_ms, + instant_lock_quorums, }, strategy, config, @@ -468,16 +474,20 @@ mod tests { ..Default::default() }; let config = PlatformConfig { - validator_set_quorum_size: 100, - validator_set_quorum_type: "llmq_100_67".to_string(), - chain_lock_quorum_type: "llmq_100_67".to_string(), + validator_set: ValidatorSetConfig::default_100_67(), + chain_lock: ChainLockConfig::default_100_67(), + instant_lock: InstantLockConfig::default_100_67(), execution: ExecutionConfig { verify_sum_trees: true, validator_set_rotation_block_count: 25, ..Default::default() }, block_spacing_ms: 3000, - testing_configs: PlatformTestConfig::default_with_no_block_signing(), + testing_configs: PlatformTestConfig { + block_signing: false, + block_commit_signature_verification: false, + disable_instant_lock_signature_verification: true, + }, ..Default::default() }; let mut platform = TestPlatformBuilder::new() @@ -530,9 +540,9 @@ mod tests { ..Default::default() }; let config = PlatformConfig { - validator_set_quorum_size: 100, - validator_set_quorum_type: "llmq_100_67".to_string(), - chain_lock_quorum_type: "llmq_100_67".to_string(), + validator_set: ValidatorSetConfig::default_100_67(), + chain_lock: ChainLockConfig::default_100_67(), + instant_lock: InstantLockConfig::default_100_67(), execution: ExecutionConfig { verify_sum_trees: true, validator_set_rotation_block_count: 25, @@ -579,9 +589,9 @@ mod tests { }; let hour_in_ms = 1000 * 60 * 60; let config = PlatformConfig { - validator_set_quorum_size: 100, - validator_set_quorum_type: "llmq_100_67".to_string(), - chain_lock_quorum_type: "llmq_100_67".to_string(), + validator_set: ValidatorSetConfig::default_100_67(), + chain_lock: ChainLockConfig::default_100_67(), + instant_lock: InstantLockConfig::default_100_67(), execution: ExecutionConfig { verify_sum_trees: true, validator_set_rotation_block_count: 100, @@ -636,9 +646,9 @@ mod tests { let hour_in_s = 60 * 60; let three_mins_in_ms = 1000 * 60 * 3; let config = PlatformConfig { - validator_set_quorum_size: 100, - validator_set_quorum_type: "llmq_100_67".to_string(), - chain_lock_quorum_type: "llmq_100_67".to_string(), + validator_set: ValidatorSetConfig::default_100_67(), + chain_lock: ChainLockConfig::default_100_67(), + instant_lock: InstantLockConfig::default_100_67(), execution: ExecutionConfig { verify_sum_trees: true, validator_set_rotation_block_count: 100, @@ -694,9 +704,25 @@ mod tests { ..Default::default() }; let config = PlatformConfig { - validator_set_quorum_size: 10, - validator_set_quorum_type: "llmq_100_67".to_string(), - chain_lock_quorum_type: "llmq_100_67".to_string(), + validator_set: ValidatorSetConfig { + quorum_type: QuorumType::Llmq100_67, + quorum_size: 10, + ..Default::default() + }, + chain_lock: ChainLockConfig { + quorum_type: QuorumType::Llmq100_67, + quorum_size: 10, + quorum_window: 24, + quorum_active_signers: 24, + quorum_rotation: false, + }, + instant_lock: InstantLockConfig { + quorum_type: QuorumType::Llmq100_67, + quorum_size: 10, + quorum_window: 24, + quorum_active_signers: 24, + quorum_rotation: false, + }, execution: ExecutionConfig { verify_sum_trees: true, validator_set_rotation_block_count: 25, @@ -774,9 +800,25 @@ mod tests { ..Default::default() }; let config = PlatformConfig { - validator_set_quorum_size: 10, - validator_set_quorum_type: "llmq_100_67".to_string(), - chain_lock_quorum_type: "llmq_100_67".to_string(), + validator_set: ValidatorSetConfig { + quorum_type: QuorumType::Llmq100_67, + quorum_size: 10, + ..Default::default() + }, + chain_lock: ChainLockConfig { + quorum_type: QuorumType::Llmq100_67, + quorum_size: 10, + quorum_window: 24, + quorum_active_signers: 24, + quorum_rotation: false, + }, + instant_lock: InstantLockConfig { + quorum_type: QuorumType::Llmq100_67, + quorum_size: 10, + quorum_window: 24, + quorum_active_signers: 24, + quorum_rotation: false, + }, execution: ExecutionConfig { verify_sum_trees: true, validator_set_rotation_block_count: 25, @@ -841,9 +883,25 @@ mod tests { ..Default::default() }; let config = PlatformConfig { - validator_set_quorum_size: 10, - validator_set_quorum_type: "llmq_100_67".to_string(), - chain_lock_quorum_type: "llmq_100_67".to_string(), + validator_set: ValidatorSetConfig { + quorum_type: QuorumType::Llmq100_67, + quorum_size: 10, + ..Default::default() + }, + chain_lock: ChainLockConfig { + quorum_type: QuorumType::Llmq100_67, + quorum_size: 10, + quorum_window: 24, + quorum_active_signers: 24, + quorum_rotation: false, + }, + instant_lock: InstantLockConfig { + quorum_type: QuorumType::Llmq100_67, + quorum_size: 10, + quorum_window: 24, + quorum_active_signers: 24, + quorum_rotation: false, + }, execution: ExecutionConfig { verify_sum_trees: true, validator_set_rotation_block_count: 25, @@ -903,9 +961,25 @@ mod tests { ..Default::default() }; let config = PlatformConfig { - validator_set_quorum_size: 10, - validator_set_quorum_type: "llmq_100_67".to_string(), - chain_lock_quorum_type: "llmq_100_67".to_string(), + validator_set: ValidatorSetConfig { + quorum_type: QuorumType::Llmq100_67, + quorum_size: 10, + ..Default::default() + }, + chain_lock: ChainLockConfig { + quorum_type: QuorumType::Llmq100_67, + quorum_size: 10, + quorum_window: 24, + quorum_active_signers: 24, + quorum_rotation: false, + }, + instant_lock: InstantLockConfig { + quorum_type: QuorumType::Llmq100_67, + quorum_size: 10, + quorum_window: 24, + quorum_active_signers: 24, + quorum_rotation: false, + }, execution: ExecutionConfig { verify_sum_trees: true, validator_set_rotation_block_count: 25, @@ -962,7 +1036,8 @@ mod tests { #[test] fn run_chain_insert_one_new_identity_per_block_with_block_signing() { - // drive_abci::logging::Loggers::default().try_install().ok(); + drive_abci::logging::init_for_tests(LogLevel::Silent); + let strategy = NetworkStrategy { strategy: Strategy { start_contracts: vec![], @@ -995,12 +1070,13 @@ mod tests { }, }), verify_state_transition_results: true, + sign_instant_locks: true, ..Default::default() }; let config = PlatformConfig { - validator_set_quorum_size: 100, - validator_set_quorum_type: "llmq_100_67".to_string(), - chain_lock_quorum_type: "llmq_100_67".to_string(), + validator_set: ValidatorSetConfig::default_100_67(), + chain_lock: ChainLockConfig::default_100_67(), + instant_lock: InstantLockConfig::default(), execution: ExecutionConfig { verify_sum_trees: true, validator_set_rotation_block_count: 25, @@ -1052,16 +1128,20 @@ mod tests { }; let day_in_ms = 1000 * 60 * 60 * 24; let config = PlatformConfig { - validator_set_quorum_size: 100, - validator_set_quorum_type: "llmq_100_67".to_string(), - chain_lock_quorum_type: "llmq_100_67".to_string(), + validator_set: ValidatorSetConfig::default_100_67(), + chain_lock: ChainLockConfig::default_100_67(), + instant_lock: InstantLockConfig::default_100_67(), execution: ExecutionConfig { verify_sum_trees: true, validator_set_rotation_block_count: 100, ..Default::default() }, block_spacing_ms: day_in_ms, - testing_configs: PlatformTestConfig::default_with_no_block_signing(), + testing_configs: PlatformTestConfig { + block_signing: false, + block_commit_signature_verification: false, + disable_instant_lock_signature_verification: true, + }, ..Default::default() }; @@ -1133,16 +1213,20 @@ mod tests { ..Default::default() }; let config = PlatformConfig { - validator_set_quorum_size: 100, - validator_set_quorum_type: "llmq_100_67".to_string(), - chain_lock_quorum_type: "llmq_100_67".to_string(), + validator_set: ValidatorSetConfig::default_100_67(), + chain_lock: ChainLockConfig::default_100_67(), + instant_lock: InstantLockConfig::default_100_67(), execution: ExecutionConfig { verify_sum_trees: true, validator_set_rotation_block_count: 25, ..Default::default() }, block_spacing_ms: 3000, - testing_configs: PlatformTestConfig::default_with_no_block_signing(), + testing_configs: PlatformTestConfig { + block_signing: false, + block_commit_signature_verification: false, + disable_instant_lock_signature_verification: true, + }, ..Default::default() }; let mut platform = TestPlatformBuilder::new() @@ -1252,9 +1336,9 @@ mod tests { ..Default::default() }; let config = PlatformConfig { - validator_set_quorum_size: 100, - validator_set_quorum_type: "llmq_100_67".to_string(), - chain_lock_quorum_type: "llmq_100_67".to_string(), + validator_set: ValidatorSetConfig::default_100_67(), + chain_lock: ChainLockConfig::default_100_67(), + instant_lock: InstantLockConfig::default_100_67(), execution: ExecutionConfig { verify_sum_trees: true, validator_set_rotation_block_count: 25, @@ -1339,16 +1423,20 @@ mod tests { ..Default::default() }; let config = PlatformConfig { - validator_set_quorum_size: 100, - validator_set_quorum_type: "llmq_100_67".to_string(), - chain_lock_quorum_type: "llmq_100_67".to_string(), + validator_set: ValidatorSetConfig::default_100_67(), + chain_lock: ChainLockConfig::default_100_67(), + instant_lock: InstantLockConfig::default_100_67(), execution: ExecutionConfig { verify_sum_trees: true, validator_set_rotation_block_count: 25, ..Default::default() }, block_spacing_ms: 3000, - testing_configs: PlatformTestConfig::default_with_no_block_signing(), + testing_configs: PlatformTestConfig { + block_signing: false, + block_commit_signature_verification: false, + disable_instant_lock_signature_verification: true, + }, ..Default::default() }; let mut platform = TestPlatformBuilder::new() @@ -1443,9 +1531,9 @@ mod tests { ..Default::default() }; let config = PlatformConfig { - validator_set_quorum_size: 100, - validator_set_quorum_type: "llmq_100_67".to_string(), - chain_lock_quorum_type: "llmq_100_67".to_string(), + validator_set: ValidatorSetConfig::default_100_67(), + chain_lock: ChainLockConfig::default_100_67(), + instant_lock: InstantLockConfig::default_100_67(), execution: ExecutionConfig { verify_sum_trees: true, validator_set_rotation_block_count: 25, @@ -1524,16 +1612,20 @@ mod tests { }; let day_in_ms = 1000 * 60 * 60 * 24; let config = PlatformConfig { - validator_set_quorum_size: 100, - validator_set_quorum_type: "llmq_100_67".to_string(), - chain_lock_quorum_type: "llmq_100_67".to_string(), + validator_set: ValidatorSetConfig::default_100_67(), + chain_lock: ChainLockConfig::default_100_67(), + instant_lock: InstantLockConfig::default_100_67(), execution: ExecutionConfig { verify_sum_trees: true, validator_set_rotation_block_count: 100, ..Default::default() }, block_spacing_ms: day_in_ms, - testing_configs: PlatformTestConfig::default_with_no_block_signing(), + testing_configs: PlatformTestConfig { + block_signing: false, + block_commit_signature_verification: false, + disable_instant_lock_signature_verification: true, + }, ..Default::default() }; let block_count = 120; @@ -1632,16 +1724,20 @@ mod tests { }; let day_in_ms = 1000 * 60 * 60 * 24; let config = PlatformConfig { - validator_set_quorum_size: 100, - validator_set_quorum_type: "llmq_100_67".to_string(), - chain_lock_quorum_type: "llmq_100_67".to_string(), + validator_set: ValidatorSetConfig::default_100_67(), + chain_lock: ChainLockConfig::default_100_67(), + instant_lock: InstantLockConfig::default_100_67(), execution: ExecutionConfig { verify_sum_trees: true, validator_set_rotation_block_count: 100, ..Default::default() }, block_spacing_ms: day_in_ms, - testing_configs: PlatformTestConfig::default_with_no_block_signing(), + testing_configs: PlatformTestConfig { + block_signing: false, + block_commit_signature_verification: false, + disable_instant_lock_signature_verification: true, + }, ..Default::default() }; let block_count = 120; @@ -1740,16 +1836,20 @@ mod tests { }; let day_in_ms = 1000 * 60 * 60 * 24; let config = PlatformConfig { - validator_set_quorum_size: 100, - validator_set_quorum_type: "llmq_100_67".to_string(), - chain_lock_quorum_type: "llmq_100_67".to_string(), + validator_set: ValidatorSetConfig::default_100_67(), + chain_lock: ChainLockConfig::default_100_67(), + instant_lock: InstantLockConfig::default_100_67(), execution: ExecutionConfig { verify_sum_trees: true, validator_set_rotation_block_count: 100, ..Default::default() }, block_spacing_ms: day_in_ms, - testing_configs: PlatformTestConfig::default_with_no_block_signing(), + testing_configs: PlatformTestConfig { + block_signing: false, + block_commit_signature_verification: false, + disable_instant_lock_signature_verification: true, + }, ..Default::default() }; @@ -1866,16 +1966,20 @@ mod tests { }; let day_in_ms = 1000 * 60 * 60 * 24; let config = PlatformConfig { - validator_set_quorum_size: 100, - validator_set_quorum_type: "llmq_100_67".to_string(), - chain_lock_quorum_type: "llmq_100_67".to_string(), + validator_set: ValidatorSetConfig::default_100_67(), + chain_lock: ChainLockConfig::default_100_67(), + instant_lock: InstantLockConfig::default_100_67(), execution: ExecutionConfig { verify_sum_trees: true, validator_set_rotation_block_count: 100, ..Default::default() }, block_spacing_ms: day_in_ms, - testing_configs: PlatformTestConfig::default_with_no_block_signing(), + testing_configs: PlatformTestConfig { + block_signing: false, + block_commit_signature_verification: false, + disable_instant_lock_signature_verification: true, + }, ..Default::default() }; @@ -1991,9 +2095,9 @@ mod tests { }; let day_in_ms = 1000 * 60 * 60 * 24; let config = PlatformConfig { - validator_set_quorum_size: 100, - validator_set_quorum_type: "llmq_100_67".to_string(), - chain_lock_quorum_type: "llmq_100_67".to_string(), + validator_set: ValidatorSetConfig::default_100_67(), + chain_lock: ChainLockConfig::default_100_67(), + instant_lock: InstantLockConfig::default_100_67(), execution: ExecutionConfig { verify_sum_trees: true, validator_set_rotation_block_count: 100, @@ -2105,9 +2209,9 @@ mod tests { }; let day_in_ms = 1000 * 60 * 60 * 24; let config = PlatformConfig { - validator_set_quorum_size: 100, - validator_set_quorum_type: "llmq_100_67".to_string(), - chain_lock_quorum_type: "llmq_100_67".to_string(), + validator_set: ValidatorSetConfig::default_100_67(), + chain_lock: ChainLockConfig::default_100_67(), + instant_lock: InstantLockConfig::default_100_67(), execution: ExecutionConfig { verify_sum_trees: true, validator_set_rotation_block_count: 100, @@ -2219,9 +2323,9 @@ mod tests { let day_in_ms = 1000 * 60 * 60 * 24; let config = PlatformConfig { - validator_set_quorum_size: 100, - validator_set_quorum_type: "llmq_100_67".to_string(), - chain_lock_quorum_type: "llmq_100_67".to_string(), + validator_set: ValidatorSetConfig::default_100_67(), + chain_lock: ChainLockConfig::default_100_67(), + instant_lock: InstantLockConfig::default_100_67(), execution: ExecutionConfig { verify_sum_trees: true, validator_set_rotation_block_count: 100, @@ -2229,7 +2333,11 @@ mod tests { ..Default::default() }, block_spacing_ms: day_in_ms, - testing_configs: PlatformTestConfig::default_with_no_block_signing(), + testing_configs: PlatformTestConfig { + block_signing: false, + block_commit_signature_verification: false, + disable_instant_lock_signature_verification: true, + }, ..Default::default() }; let block_count = 30; @@ -2348,9 +2456,9 @@ mod tests { let day_in_ms = 1000 * 60 * 60 * 24; let config = PlatformConfig { - validator_set_quorum_size: 100, - validator_set_quorum_type: "llmq_100_67".to_string(), - chain_lock_quorum_type: "llmq_100_67".to_string(), + validator_set: ValidatorSetConfig::default_100_67(), + chain_lock: ChainLockConfig::default_100_67(), + instant_lock: InstantLockConfig::default_100_67(), execution: ExecutionConfig { verify_sum_trees: true, validator_set_rotation_block_count: 100, @@ -2358,7 +2466,11 @@ mod tests { ..Default::default() }, block_spacing_ms: day_in_ms, - testing_configs: PlatformTestConfig::default_with_no_block_signing(), + testing_configs: PlatformTestConfig { + block_signing: false, + block_commit_signature_verification: false, + disable_instant_lock_signature_verification: true, + }, ..Default::default() }; let block_count = 30; @@ -2493,9 +2605,9 @@ mod tests { let day_in_ms = 1000 * 60 * 60 * 24; let config = PlatformConfig { - validator_set_quorum_size: 100, - validator_set_quorum_type: "llmq_100_67".to_string(), - chain_lock_quorum_type: "llmq_100_67".to_string(), + validator_set: ValidatorSetConfig::default_100_67(), + chain_lock: ChainLockConfig::default_100_67(), + instant_lock: InstantLockConfig::default_100_67(), execution: ExecutionConfig { verify_sum_trees: true, validator_set_rotation_block_count: 100, @@ -2503,7 +2615,11 @@ mod tests { ..Default::default() }, block_spacing_ms: day_in_ms, - testing_configs: PlatformTestConfig::default_with_no_block_signing(), + testing_configs: PlatformTestConfig { + block_signing: false, + block_commit_signature_verification: false, + disable_instant_lock_signature_verification: true, + }, ..Default::default() }; let block_count = 30; @@ -2559,12 +2675,13 @@ mod tests { failure_testing: None, query_testing: None, verify_state_transition_results: true, + sign_instant_locks: true, ..Default::default() }; let config = PlatformConfig { - validator_set_quorum_size: 100, - validator_set_quorum_type: "llmq_100_67".to_string(), - chain_lock_quorum_type: "llmq_100_67".to_string(), + validator_set: ValidatorSetConfig::default_100_67(), + chain_lock: ChainLockConfig::default_100_67(), + instant_lock: InstantLockConfig::default_100_67(), execution: ExecutionConfig { verify_sum_trees: true, validator_set_rotation_block_count: 25, @@ -2642,16 +2759,20 @@ mod tests { ..Default::default() }; let config = PlatformConfig { - validator_set_quorum_size: 100, - validator_set_quorum_type: "llmq_100_67".to_string(), - chain_lock_quorum_type: "llmq_100_67".to_string(), + validator_set: ValidatorSetConfig::default_100_67(), + chain_lock: ChainLockConfig::default_100_67(), + instant_lock: InstantLockConfig::default_100_67(), execution: ExecutionConfig { verify_sum_trees: true, validator_set_rotation_block_count: 25, ..Default::default() }, block_spacing_ms: 3000, - testing_configs: PlatformTestConfig::default_with_no_block_signing(), + testing_configs: PlatformTestConfig { + block_signing: false, + block_commit_signature_verification: false, + disable_instant_lock_signature_verification: true, + }, ..Default::default() }; let mut platform = TestPlatformBuilder::new() @@ -2727,16 +2848,20 @@ mod tests { ..Default::default() }; let config = PlatformConfig { - validator_set_quorum_size: 100, - validator_set_quorum_type: "llmq_100_67".to_string(), - chain_lock_quorum_type: "llmq_100_67".to_string(), + validator_set: ValidatorSetConfig::default_100_67(), + chain_lock: ChainLockConfig::default_100_67(), + instant_lock: InstantLockConfig::default_100_67(), execution: ExecutionConfig { verify_sum_trees: true, validator_set_rotation_block_count: 25, ..Default::default() }, block_spacing_ms: 3000, - testing_configs: PlatformTestConfig::default_with_no_block_signing(), + testing_configs: PlatformTestConfig { + block_signing: false, + block_commit_signature_verification: false, + disable_instant_lock_signature_verification: true, + }, ..Default::default() }; let mut platform = TestPlatformBuilder::new() @@ -2824,16 +2949,20 @@ mod tests { ..Default::default() }; let config = PlatformConfig { - validator_set_quorum_size: 100, - validator_set_quorum_type: "llmq_100_67".to_string(), - chain_lock_quorum_type: "llmq_100_67".to_string(), + validator_set: ValidatorSetConfig::default_100_67(), + chain_lock: ChainLockConfig::default_100_67(), + instant_lock: InstantLockConfig::default_100_67(), execution: ExecutionConfig { verify_sum_trees: true, validator_set_rotation_block_count: 25, ..Default::default() }, block_spacing_ms: 3000, - testing_configs: PlatformTestConfig::default_with_no_block_signing(), + testing_configs: PlatformTestConfig { + block_signing: false, + block_commit_signature_verification: false, + disable_instant_lock_signature_verification: true, + }, ..Default::default() }; @@ -2901,12 +3030,13 @@ mod tests { ChainExecutionOutcome { abci_app, proposers, - quorums, - current_quorum_hash, + validator_quorums: quorums, + current_validator_quorum_hash: current_quorum_hash, current_proposer_versions, end_time_ms, identity_nonce_counter, identity_contract_nonce_counter, + instant_lock_quorums, .. }, last_block_pooled_withdrawals_amount, @@ -2940,13 +3070,14 @@ mod tests { let ChainExecutionOutcome { abci_app, proposers, - quorums, - current_quorum_hash, + validator_quorums: quorums, + current_validator_quorum_hash: current_quorum_hash, current_proposer_versions, end_time_ms, withdrawals: last_block_withdrawals, identity_nonce_counter, identity_contract_nonce_counter, + instant_lock_quorums, .. } = { let outcome = continue_chain_for_strategy( @@ -2956,13 +3087,14 @@ mod tests { core_height_start: 1, block_count: 1, proposers, - quorums, - current_quorum_hash, + validator_quorums: quorums, + current_validator_quorum_hash: current_quorum_hash, current_proposer_versions: Some(current_proposer_versions), current_identity_nonce_counter: identity_nonce_counter, current_identity_contract_nonce_counter: identity_contract_nonce_counter, start_time_ms: GENESIS_TIME_MS, current_time_ms: end_time_ms, + instant_lock_quorums, }, strategy.clone(), config.clone(), @@ -3019,13 +3151,14 @@ mod tests { ChainExecutionOutcome { abci_app, proposers, - quorums, - current_quorum_hash, + validator_quorums: quorums, + current_validator_quorum_hash: current_quorum_hash, current_proposer_versions, end_time_ms, withdrawals: last_block_withdrawals, identity_nonce_counter, identity_contract_nonce_counter, + instant_lock_quorums, .. }, last_block_broadcased_withdrawals_amount, @@ -3037,13 +3170,14 @@ mod tests { core_height_start: 1, block_count: 1, proposers, - quorums, - current_quorum_hash, + validator_quorums: quorums, + current_validator_quorum_hash: current_quorum_hash, current_proposer_versions: Some(current_proposer_versions), current_identity_nonce_counter: identity_nonce_counter, current_identity_contract_nonce_counter: identity_contract_nonce_counter, start_time_ms: GENESIS_TIME_MS, current_time_ms: end_time_ms + 1000, + instant_lock_quorums, }, strategy.clone(), config.clone(), @@ -3131,13 +3265,14 @@ mod tests { ChainExecutionOutcome { abci_app, proposers, - quorums, - current_quorum_hash, + validator_quorums: quorums, + current_validator_quorum_hash: current_quorum_hash, current_proposer_versions, end_time_ms, withdrawals: last_block_withdrawals, identity_nonce_counter, identity_contract_nonce_counter, + instant_lock_quorums, .. }, last_block_withdrawals_completed_amount, @@ -3149,13 +3284,14 @@ mod tests { core_height_start: 1, block_count: 1, proposers, - quorums, - current_quorum_hash, + validator_quorums: quorums, + current_validator_quorum_hash: current_quorum_hash, current_proposer_versions: Some(current_proposer_versions), current_identity_nonce_counter: identity_nonce_counter, current_identity_contract_nonce_counter: identity_contract_nonce_counter, start_time_ms: GENESIS_TIME_MS, current_time_ms: end_time_ms + 1000, + instant_lock_quorums, }, strategy.clone(), config.clone(), @@ -3256,13 +3392,14 @@ mod tests { core_height_start: 1, block_count: 1, proposers, - quorums, - current_quorum_hash, + validator_quorums: quorums, + current_validator_quorum_hash: current_quorum_hash, current_proposer_versions: Some(current_proposer_versions), current_identity_nonce_counter: identity_nonce_counter, current_identity_contract_nonce_counter: identity_contract_nonce_counter, start_time_ms: GENESIS_TIME_MS, current_time_ms: end_time_ms + 1000, + instant_lock_quorums, }, strategy.clone(), config.clone(), @@ -3387,9 +3524,25 @@ mod tests { }; let day_in_ms = 1000 * 60 * 60 * 24; let config = PlatformConfig { - validator_set_quorum_size: 3, - validator_set_quorum_type: "llmq_100_67".to_string(), - chain_lock_quorum_type: "llmq_100_67".to_string(), + validator_set: ValidatorSetConfig { + quorum_type: QuorumType::Llmq100_67, + quorum_size: 3, + ..Default::default() + }, + chain_lock: ChainLockConfig { + quorum_type: QuorumType::Llmq100_67, + quorum_size: 3, + quorum_window: 24, + quorum_active_signers: 24, + quorum_rotation: false, + }, + instant_lock: InstantLockConfig { + quorum_type: QuorumType::Llmq100_67, + quorum_size: 3, + quorum_window: 24, + quorum_active_signers: 24, + quorum_rotation: false, + }, execution: ExecutionConfig { verify_sum_trees: true, validator_set_rotation_block_count: 1, @@ -3552,9 +3705,25 @@ mod tests { }; let day_in_ms = 1000 * 60 * 60 * 24; let config = PlatformConfig { - validator_set_quorum_size: 3, - validator_set_quorum_type: "llmq_100_67".to_string(), - chain_lock_quorum_type: "llmq_100_67".to_string(), + validator_set: ValidatorSetConfig { + quorum_type: QuorumType::Llmq100_67, + quorum_size: 3, + ..Default::default() + }, + chain_lock: ChainLockConfig { + quorum_type: QuorumType::Llmq100_67, + quorum_size: 3, + quorum_window: 24, + quorum_active_signers: 24, + quorum_rotation: false, + }, + instant_lock: InstantLockConfig { + quorum_type: QuorumType::Llmq100_67, + quorum_size: 3, + quorum_window: 24, + quorum_active_signers: 24, + quorum_rotation: false, + }, execution: ExecutionConfig { verify_sum_trees: true, validator_set_rotation_block_count: 1, @@ -3688,16 +3857,36 @@ mod tests { }; let day_in_ms = 1000 * 60 * 60 * 24; let config = PlatformConfig { - validator_set_quorum_size: 3, - validator_set_quorum_type: "llmq_100_67".to_string(), - chain_lock_quorum_type: "llmq_100_67".to_string(), + validator_set: ValidatorSetConfig { + quorum_type: QuorumType::Llmq100_67, + quorum_size: 3, + ..Default::default() + }, + chain_lock: ChainLockConfig { + quorum_type: QuorumType::Llmq100_67, + quorum_size: 3, + quorum_window: 24, + quorum_active_signers: 24, + quorum_rotation: false, + }, + instant_lock: InstantLockConfig { + quorum_type: QuorumType::Llmq100_67, + quorum_size: 3, + quorum_window: 24, + quorum_active_signers: 24, + quorum_rotation: false, + }, execution: ExecutionConfig { verify_sum_trees: true, validator_set_rotation_block_count: 1, ..Default::default() }, block_spacing_ms: day_in_ms, - testing_configs: PlatformTestConfig::default_with_no_block_signing(), + testing_configs: PlatformTestConfig { + block_signing: false, + block_commit_signature_verification: false, + disable_instant_lock_signature_verification: true, + }, ..Default::default() }; let mut platform_a = TestPlatformBuilder::new() @@ -3814,9 +4003,25 @@ mod tests { }; let day_in_ms = 1000 * 60 * 60 * 24; let config = PlatformConfig { - validator_set_quorum_size: 3, - validator_set_quorum_type: "llmq_100_67".to_string(), - chain_lock_quorum_type: "llmq_100_67".to_string(), + validator_set: ValidatorSetConfig { + quorum_type: QuorumType::Llmq100_67, + quorum_size: 3, + ..Default::default() + }, + chain_lock: ChainLockConfig { + quorum_type: QuorumType::Llmq100_67, + quorum_size: 3, + quorum_window: 24, + quorum_active_signers: 24, + quorum_rotation: false, + }, + instant_lock: InstantLockConfig { + quorum_type: QuorumType::Llmq100_67, + quorum_size: 3, + quorum_window: 24, + quorum_active_signers: 24, + quorum_rotation: false, + }, execution: ExecutionConfig { verify_sum_trees: true, validator_set_rotation_block_count: 1, @@ -3837,8 +4042,8 @@ mod tests { let ChainExecutionOutcome { abci_app, proposers, - quorums, - current_quorum_hash, + validator_quorums: quorums, + current_validator_quorum_hash: current_quorum_hash, current_proposer_versions, end_time_ms, identity_nonce_counter, @@ -3899,8 +4104,9 @@ mod tests { core_height_start: 10, block_count: 30, proposers, - quorums, - current_quorum_hash, + validator_quorums: quorums, + current_validator_quorum_hash: current_quorum_hash, + instant_lock_quorums: Default::default(), current_proposer_versions: Some(current_proposer_versions), current_identity_nonce_counter: identity_nonce_counter, current_identity_contract_nonce_counter: identity_contract_nonce_counter, @@ -3958,16 +4164,20 @@ mod tests { }; let config = PlatformConfig { - validator_set_quorum_size: 100, - validator_set_quorum_type: "llmq_100_67".to_string(), - chain_lock_quorum_type: "llmq_100_67".to_string(), + validator_set: ValidatorSetConfig::default_100_67(), + chain_lock: ChainLockConfig::default_100_67(), + instant_lock: InstantLockConfig::default_100_67(), execution: ExecutionConfig { verify_sum_trees: true, validator_set_rotation_block_count: 25, ..Default::default() }, block_spacing_ms: 3000, - testing_configs: PlatformTestConfig::default_with_no_block_signing(), + testing_configs: PlatformTestConfig { + block_signing: false, + block_commit_signature_verification: false, + disable_instant_lock_signature_verification: true, + }, ..Default::default() }; @@ -4014,16 +4224,20 @@ mod tests { ..Default::default() }; let config = PlatformConfig { - validator_set_quorum_size: 100, - validator_set_quorum_type: "llmq_100_67".to_string(), - chain_lock_quorum_type: "llmq_100_67".to_string(), + validator_set: ValidatorSetConfig::default_100_67(), + chain_lock: ChainLockConfig::default_100_67(), + instant_lock: InstantLockConfig::default_100_67(), execution: ExecutionConfig { verify_sum_trees: true, validator_set_rotation_block_count: 25, ..Default::default() }, block_spacing_ms: 3000, - testing_configs: PlatformTestConfig::default_with_no_block_signing(), + testing_configs: PlatformTestConfig { + block_signing: false, + block_commit_signature_verification: false, + disable_instant_lock_signature_verification: true, + }, ..Default::default() }; let mut platform = TestPlatformBuilder::new() diff --git a/packages/rs-drive-abci/tests/strategy_tests/masternodes.rs b/packages/rs-drive-abci/tests/strategy_tests/masternodes.rs index d240752a265..7dcde2d97af 100644 --- a/packages/rs-drive-abci/tests/strategy_tests/masternodes.rs +++ b/packages/rs-drive-abci/tests/strategy_tests/masternodes.rs @@ -537,6 +537,7 @@ where TestQuorumInfo::from_quorum_hash_and_pro_tx_hashes( index as u32 * 24, quorum_hash, + Some(index as u32 + 1), validator_pro_tx_hashes, rng, ), diff --git a/packages/rs-drive-abci/tests/strategy_tests/query.rs b/packages/rs-drive-abci/tests/strategy_tests/query.rs index c8825c7dfef..e7e4fd7ca9e 100644 --- a/packages/rs-drive-abci/tests/strategy_tests/query.rs +++ b/packages/rs-drive-abci/tests/strategy_tests/query.rs @@ -306,7 +306,10 @@ mod tests { use dpp::block::extended_epoch_info::v0::ExtendedEpochInfoV0Getters; use dpp::version::PlatformVersion; - use drive_abci::config::{ExecutionConfig, PlatformConfig, PlatformTestConfig}; + use drive_abci::config::{ + ChainLockConfig, ExecutionConfig, InstantLockConfig, PlatformConfig, PlatformTestConfig, + ValidatorSetConfig, + }; use drive_abci::platform_types::platform_state::v0::PlatformStateV0Methods; use drive_abci::test::helpers::setup::TestPlatformBuilder; @@ -369,9 +372,9 @@ mod tests { }; let hour_in_ms = 1000 * 60 * 60; let config = PlatformConfig { - validator_set_quorum_size: 100, - validator_set_quorum_type: "llmq_100_67".to_string(), - chain_lock_quorum_type: "llmq_100_67".to_string(), + validator_set: ValidatorSetConfig::default_100_67(), + chain_lock: ChainLockConfig::default_100_67(), + instant_lock: InstantLockConfig::default_100_67(), execution: ExecutionConfig { verify_sum_trees: true, validator_set_rotation_block_count: 100, @@ -467,9 +470,9 @@ mod tests { }; let hour_in_ms = 1000 * 60 * 60; let config = PlatformConfig { - validator_set_quorum_size: 100, - validator_set_quorum_type: "llmq_100_67".to_string(), - chain_lock_quorum_type: "llmq_100_67".to_string(), + validator_set: ValidatorSetConfig::default_100_67(), + chain_lock: ChainLockConfig::default_100_67(), + instant_lock: InstantLockConfig::default_100_67(), execution: ExecutionConfig { verify_sum_trees: true, validator_set_rotation_block_count: 100, @@ -566,9 +569,9 @@ mod tests { }; let hour_in_ms = 1000 * 60 * 60; let config = PlatformConfig { - validator_set_quorum_size: 100, - validator_set_quorum_type: "llmq_100_67".to_string(), - chain_lock_quorum_type: "llmq_100_67".to_string(), + validator_set: ValidatorSetConfig::default_100_67(), + chain_lock: ChainLockConfig::default_100_67(), + instant_lock: InstantLockConfig::default_100_67(), execution: ExecutionConfig { verify_sum_trees: true, validator_set_rotation_block_count: 100, diff --git a/packages/rs-drive-abci/tests/strategy_tests/strategy.rs b/packages/rs-drive-abci/tests/strategy_tests/strategy.rs index dae0d7acc8f..43fba42224d 100644 --- a/packages/rs-drive-abci/tests/strategy_tests/strategy.rs +++ b/packages/rs-drive-abci/tests/strategy_tests/strategy.rs @@ -40,7 +40,7 @@ use drive_abci::rpc::core::MockCoreRPCLike; use rand::prelude::{IteratorRandom, SliceRandom, StdRng}; use rand::Rng; use strategy_tests::{KeyMaps, Strategy}; -use strategy_tests::transitions::{create_state_transitions_for_identities, instant_asset_lock_proof_fixture}; +use strategy_tests::transitions::{create_state_transitions_for_identities, create_state_transitions_for_identities_and_proofs, instant_asset_lock_proof_fixture}; use std::borrow::Cow; use std::collections::{BTreeMap, HashMap, HashSet}; use std::str::FromStr; @@ -48,8 +48,9 @@ use tenderdash_abci::proto::abci::{ExecTxResult, ValidatorSetUpdate}; use dpp::data_contract::document_type::accessors::DocumentTypeV0Getters; use dpp::data_contract::document_type::v0::DocumentTypeV0; use dpp::identity::accessors::IdentityGettersV0; +use dpp::identity::state_transition::asset_lock_proof::InstantAssetLockProof; use dpp::platform_value::{BinaryData, Value}; -use dpp::prelude::{Identifier, IdentityNonce}; +use dpp::prelude::{AssetLockProof, Identifier, IdentityNonce}; use dpp::state_transition::documents_batch_transition::document_base_transition::v0::DocumentBaseTransitionV0; use dpp::state_transition::documents_batch_transition::document_create_transition::{DocumentCreateTransition, DocumentCreateTransitionV0}; use dpp::state_transition::documents_batch_transition::document_transition::document_delete_transition::DocumentDeleteTransitionV0; @@ -59,7 +60,10 @@ use dpp::state_transition::documents_batch_transition::document_transition::{Doc use drive::drive::document::query::QueryDocumentsOutcomeV0Methods; use dpp::state_transition::data_contract_create_transition::methods::v0::DataContractCreateTransitionMethodsV0; use dpp::state_transition::documents_batch_transition::document_transition::document_transfer_transition::DocumentTransferTransitionV0; +use dpp::state_transition::identity_topup_transition::v0::IdentityTopUpTransitionV0; use drive_abci::abci::app::FullAbciApplication; +use drive_abci::config::PlatformConfig; +use drive_abci::platform_types::signature_verification_quorum_set::{QuorumConfig, Quorums, SigningQuorum}; use drive_abci::platform_types::withdrawal::unsigned_withdrawal_txs::v0::UnsignedWithdrawalTxs; use crate::strategy::CoreHeightIncrease::NoCoreHeightIncrease; @@ -240,6 +244,7 @@ pub struct NetworkStrategy { pub extra_normal_mns: u16, pub validator_quorum_count: u16, pub chain_lock_quorum_count: u16, + pub instant_lock_quorum_count: u16, pub initial_core_height: u32, pub upgrading_info: Option, pub core_height_increase: CoreHeightIncrease, @@ -251,6 +256,7 @@ pub struct NetworkStrategy { pub max_tx_bytes_per_block: u64, pub independent_process_proposal_verification: bool, pub sign_chain_locks: bool, + pub sign_instant_locks: bool, } impl Default for NetworkStrategy { @@ -261,6 +267,7 @@ impl Default for NetworkStrategy { extra_normal_mns: 0, validator_quorum_count: 24, chain_lock_quorum_count: 24, + instant_lock_quorum_count: 24, initial_core_height: 1, upgrading_info: None, core_height_increase: NoCoreHeightIncrease, @@ -272,6 +279,7 @@ impl Default for NetworkStrategy { max_tx_bytes_per_block: 44800, independent_process_proposal_verification: false, sign_chain_locks: false, + sign_instant_locks: false, } } } @@ -365,16 +373,18 @@ impl NetworkStrategy { block_info: &BlockInfo, signer: &mut SimpleSigner, rng: &mut StdRng, + instant_lock_quorums: &Quorums, + platform_config: &PlatformConfig, platform_version: &PlatformVersion, ) -> Result, ProtocolError> { let mut state_transitions = vec![]; if block_info.height == 1 && self.strategy.start_identities.number_of_identities > 0 { - let mut new_transitions = NetworkStrategy::create_identities_state_transitions( + let mut new_transitions = self.create_identities_state_transitions( self.strategy.start_identities.number_of_identities.into(), - self.strategy.identity_inserts.start_keys as KeyID, - &self.strategy.identity_inserts.extra_keys, signer, rng, + instant_lock_quorums, + platform_config, platform_version, ); state_transitions.append(&mut new_transitions); @@ -382,12 +392,12 @@ impl NetworkStrategy { let frequency = &self.strategy.identity_inserts.frequency; if frequency.check_hit(rng) { let count = frequency.events(rng); - let mut new_transitions = NetworkStrategy::create_identities_state_transitions( + let mut new_transitions = self.create_identities_state_transitions( count, - self.strategy.identity_inserts.start_keys as KeyID, - &self.strategy.identity_inserts.extra_keys, signer, rng, + instant_lock_quorums, + platform_config, platform_version, ); state_transitions.append(&mut new_transitions); @@ -522,6 +532,7 @@ impl NetworkStrategy { signer: &mut SimpleSigner, identity_nonce_counter: &mut BTreeMap, contract_nonce_counter: &mut BTreeMap<(Identifier, Identifier), u64>, + instant_lock_quorums: &Quorums, rng: &mut StdRng, platform_version: &PlatformVersion, ) -> (Vec, Vec) { @@ -1046,9 +1057,11 @@ impl NetworkStrategy { .collect(); for random_identity in random_identities { - operations.push(NetworkStrategy::create_identity_top_up_transition( + operations.push(self.create_identity_top_up_transition( rng, random_identity, + instant_lock_quorums, + &platform.config, platform_version, )); } @@ -1252,6 +1265,7 @@ impl NetworkStrategy { contract_nonce_counter: &mut BTreeMap<(Identifier, Identifier), u64>, signer: &mut SimpleSigner, rng: &mut StdRng, + instant_lock_quorums: &Quorums, ) -> (Vec, Vec) { let mut finalize_block_operations = vec![]; let platform_state = platform.state.load(); @@ -1259,8 +1273,14 @@ impl NetworkStrategy { .current_platform_version() .expect("expected platform version"); - let identity_state_transitions_result = - self.identity_state_transitions_for_block(block_info, signer, rng, platform_version); + let identity_state_transitions_result = self.identity_state_transitions_for_block( + block_info, + signer, + rng, + instant_lock_quorums, + &platform.config, + platform_version, + ); // Handle the Result returned by identity_state_transitions_for_block let (mut identities, mut state_transitions) = match identity_state_transitions_result { @@ -1293,6 +1313,7 @@ impl NetworkStrategy { signer, identity_nonce_counter, contract_nonce_counter, + instant_lock_quorums, rng, platform_version, ); @@ -1317,13 +1338,17 @@ impl NetworkStrategy { // add this because strategy tests library now requires a callback and uses the actual chain. fn create_identities_state_transitions( + &self, count: u16, - key_count: KeyID, - extra_keys: &KeyMaps, signer: &mut SimpleSigner, rng: &mut StdRng, + instant_lock_quorums: &Quorums, + platform_config: &PlatformConfig, platform_version: &PlatformVersion, ) -> Vec<(Identity, StateTransition)> { + let key_count = self.strategy.identity_inserts.start_keys as KeyID; + let extra_keys = &self.strategy.identity_inserts.extra_keys; + let (mut identities, mut keys) = Identity::random_identities_with_private_keys_with_rng::< Vec<_>, >(count, key_count, rng, platform_version) @@ -1352,13 +1377,33 @@ impl NetworkStrategy { } signer.add_keys(keys); - create_state_transitions_for_identities(identities, signer, rng, platform_version) + + if self.sign_instant_locks { + let identities_with_proofs = create_signed_instant_asset_lock_proofs_for_identities( + identities, + rng, + instant_lock_quorums, + platform_config, + platform_version, + ); + + create_state_transitions_for_identities_and_proofs( + identities_with_proofs, + signer, + platform_version, + ) + } else { + create_state_transitions_for_identities(identities, signer, rng, platform_version) + } } // add this because strategy tests library now requires a callback and uses the actual chain. fn create_identity_top_up_transition( + &self, rng: &mut StdRng, identity: &Identity, + instant_lock_quorums: &Quorums, + platform_config: &PlatformConfig, platform_version: &PlatformVersion, ) -> StateTransition { let (_, pk) = ECDSA_SECP256K1 @@ -1366,9 +1411,43 @@ impl NetworkStrategy { .unwrap(); let sk: [u8; 32] = pk.try_into().unwrap(); let secret_key = SecretKey::from_str(hex::encode(sk).as_str()).unwrap(); - let asset_lock_proof = + let mut asset_lock_proof = instant_asset_lock_proof_fixture(PrivateKey::new(secret_key, Network::Dash)); + // Sign transaction and update signature in instant lock proof + if self.sign_instant_locks { + let quorum_config = QuorumConfig { + quorum_type: platform_config.instant_lock.quorum_type, + active_signers: platform_config.instant_lock.quorum_active_signers, + rotation: platform_config.instant_lock.quorum_rotation, + window: platform_config.instant_lock.quorum_window, + }; + + // Sign transaction and update instant lock + let AssetLockProof::Instant(InstantAssetLockProof { instant_lock, .. }) = + &mut asset_lock_proof + else { + panic!("must be instant lock proof"); + }; + + let request_id = instant_lock + .request_id() + .expect("failed to build request id"); + + let (quorum_hash, quorum) = instant_lock_quorums + .choose_quorum(&quorum_config, request_id.as_ref()) + .expect("failed to choose quorum for instant lock transaction signing"); + + instant_lock.signature = quorum + .sign_for_instant_lock( + &quorum_config, + &quorum_hash, + request_id.as_ref(), + &instant_lock.txid, + ) + .expect("failed to sign transaction for instant lock"); + } + IdentityTopUpTransition::try_from_identity( identity, asset_lock_proof, @@ -1399,9 +1478,10 @@ pub struct ChainExecutionOutcome<'a> { pub masternode_identity_balances: BTreeMap<[u8; 32], Credits>, pub identities: Vec, pub proposers: Vec, - pub quorums: BTreeMap, - pub current_quorum_hash: QuorumHash, + pub validator_quorums: BTreeMap, + pub current_validator_quorum_hash: QuorumHash, pub current_proposer_versions: Option>, + pub instant_lock_quorums: Quorums, /// Identity nonce counters pub identity_nonce_counter: BTreeMap, /// Identity Contract nonce counters @@ -1417,8 +1497,8 @@ pub struct ChainExecutionOutcome<'a> { impl<'a> ChainExecutionOutcome<'a> { pub fn current_quorum(&self) -> &TestQuorumInfo { - self.quorums - .get::(&self.current_quorum_hash) + self.validator_quorums + .get::(&self.current_validator_quorum_hash) .unwrap() } } @@ -1428,8 +1508,9 @@ pub struct ChainExecutionParameters { pub core_height_start: u32, pub block_count: u64, pub proposers: Vec, - pub quorums: BTreeMap, - pub current_quorum_hash: QuorumHash, + pub validator_quorums: BTreeMap, + pub current_validator_quorum_hash: QuorumHash, + pub instant_lock_quorums: Quorums, // the first option is if it is set // the second option is if we are even upgrading pub current_proposer_versions: Option>>, @@ -1438,3 +1519,60 @@ pub struct ChainExecutionParameters { pub start_time_ms: u64, pub current_time_ms: u64, } + +fn create_signed_instant_asset_lock_proofs_for_identities( + identities: Vec, + rng: &mut StdRng, + instant_lock_quorums: &Quorums, + platform_config: &PlatformConfig, + platform_version: &PlatformVersion, +) -> Vec<(Identity, [u8; 32], AssetLockProof)> { + let quorum_config = QuorumConfig { + quorum_type: platform_config.instant_lock.quorum_type, + active_signers: platform_config.instant_lock.quorum_active_signers, + rotation: platform_config.instant_lock.quorum_rotation, + window: platform_config.instant_lock.quorum_window, + }; + + identities + .into_iter() + .map(|identity| { + // Create instant asset lock proof + let (_, pk) = ECDSA_SECP256K1 + .random_public_and_private_key_data(rng, platform_version) + .unwrap(); + + let pk_fixed: [u8; 32] = pk.try_into().unwrap(); + let secret_key = SecretKey::from_str(hex::encode(pk_fixed).as_str()).unwrap(); + let private_key = PrivateKey::new(secret_key, Network::Dash); + + let mut asset_lock_proof = instant_asset_lock_proof_fixture(private_key); + + // Sign transaction and update instant lock + let AssetLockProof::Instant(InstantAssetLockProof { instant_lock, .. }) = + &mut asset_lock_proof + else { + panic!("must be instant lock proof"); + }; + + let request_id = instant_lock + .request_id() + .expect("failed to build request id"); + + let (quorum_hash, quorum) = instant_lock_quorums + .choose_quorum(&quorum_config, request_id.as_ref()) + .expect("failed to choose quorum for instant lock transaction signing"); + + instant_lock.signature = quorum + .sign_for_instant_lock( + &quorum_config, + &quorum_hash, + request_id.as_ref(), + &instant_lock.txid, + ) + .expect("failed to sign transaction for instant lock"); + + (identity, pk_fixed, asset_lock_proof) + }) + .collect() +} diff --git a/packages/rs-drive-abci/tests/strategy_tests/upgrade_fork_tests.rs b/packages/rs-drive-abci/tests/strategy_tests/upgrade_fork_tests.rs index 7b588734515..0146fc16f7d 100644 --- a/packages/rs-drive-abci/tests/strategy_tests/upgrade_fork_tests.rs +++ b/packages/rs-drive-abci/tests/strategy_tests/upgrade_fork_tests.rs @@ -13,7 +13,10 @@ mod tests { ChainExecutionOutcome, ChainExecutionParameters, CoreHeightIncrease, MasternodeListChangesStrategy, NetworkStrategy, StrategyRandomness, UpgradingInfo, }; - use drive_abci::config::{ExecutionConfig, PlatformConfig, PlatformTestConfig}; + use drive_abci::config::{ + ChainLockConfig, ExecutionConfig, InstantLockConfig, PlatformConfig, PlatformTestConfig, + ValidatorSetConfig, + }; use drive_abci::mimic::MimicExecuteBlockOptions; use drive_abci::platform_types::platform_state::v0::PlatformStateV0Methods; use drive_abci::test::helpers::setup::TestPlatformBuilder; @@ -64,9 +67,9 @@ mod tests { }; let twenty_minutes_in_ms = 1000 * 60 * 20; let mut config = PlatformConfig { - validator_set_quorum_size: 100, - validator_set_quorum_type: "llmq_100_67".to_string(), - chain_lock_quorum_type: "llmq_100_67".to_string(), + validator_set: ValidatorSetConfig::default_100_67(), + chain_lock: ChainLockConfig::default_100_67(), + instant_lock: InstantLockConfig::default_100_67(), execution: ExecutionConfig { verify_sum_trees: true, validator_set_rotation_block_count: 125, @@ -98,12 +101,13 @@ mod tests { let ChainExecutionOutcome { abci_app, proposers, - quorums, - current_quorum_hash, + validator_quorums: quorums, + current_validator_quorum_hash: current_quorum_hash, current_proposer_versions, end_time_ms, identity_nonce_counter, identity_contract_nonce_counter, + instant_lock_quorums, .. } = run_chain_for_strategy( &mut platform, @@ -162,11 +166,12 @@ mod tests { let ChainExecutionOutcome { abci_app, proposers, - quorums, - current_quorum_hash, + validator_quorums: quorums, + current_validator_quorum_hash: current_quorum_hash, end_time_ms, identity_nonce_counter, identity_contract_nonce_counter, + instant_lock_quorums, .. } = continue_chain_for_strategy( abci_app, @@ -175,13 +180,14 @@ mod tests { core_height_start: 1, block_count: 200, proposers, - quorums, - current_quorum_hash, + validator_quorums: quorums, + current_validator_quorum_hash: current_quorum_hash, current_proposer_versions: Some(current_proposer_versions.clone()), current_identity_nonce_counter: identity_nonce_counter, current_identity_contract_nonce_counter: identity_contract_nonce_counter, start_time_ms: 1681094380000, current_time_ms: end_time_ms, + instant_lock_quorums, }, strategy.clone(), config.clone(), @@ -225,13 +231,14 @@ mod tests { core_height_start: 1, block_count: 400, proposers, - quorums, - current_quorum_hash, + validator_quorums: quorums, + current_validator_quorum_hash: current_quorum_hash, current_proposer_versions: Some(current_proposer_versions), current_identity_nonce_counter: identity_nonce_counter, current_identity_contract_nonce_counter: identity_contract_nonce_counter, start_time_ms: 1681094380000, current_time_ms: end_time_ms, + instant_lock_quorums, }, strategy, config, @@ -307,9 +314,12 @@ mod tests { let one_hour_in_s = 60 * 60; let thirty_seconds_in_ms = 1000 * 30; let config = PlatformConfig { - validator_set_quorum_size: 30, - validator_set_quorum_type: "llmq_100_67".to_string(), - chain_lock_quorum_type: "llmq_100_67".to_string(), + validator_set: ValidatorSetConfig { + quorum_size: 30, + ..Default::default() + }, + chain_lock: ChainLockConfig::default_100_67(), + instant_lock: InstantLockConfig::default_100_67(), execution: ExecutionConfig { verify_sum_trees: true, validator_set_rotation_block_count: 30, @@ -337,12 +347,13 @@ mod tests { let ChainExecutionOutcome { abci_app, proposers, - quorums, - current_quorum_hash, + validator_quorums: quorums, + current_validator_quorum_hash: current_quorum_hash, current_proposer_versions, end_time_ms, identity_nonce_counter, identity_contract_nonce_counter, + instant_lock_quorums, .. } = run_chain_for_strategy( &mut platform, @@ -398,11 +409,12 @@ mod tests { let ChainExecutionOutcome { abci_app, proposers, - quorums, - current_quorum_hash, + validator_quorums: quorums, + current_validator_quorum_hash: current_quorum_hash, end_time_ms, identity_nonce_counter, identity_contract_nonce_counter, + instant_lock_quorums, .. } = continue_chain_for_strategy( abci_app, @@ -411,13 +423,14 @@ mod tests { core_height_start: 1, block_count: 1, proposers, - quorums, - current_quorum_hash, + validator_quorums: quorums, + current_validator_quorum_hash: current_quorum_hash, current_proposer_versions: Some(current_proposer_versions.clone()), current_identity_nonce_counter: identity_nonce_counter, current_identity_contract_nonce_counter: identity_contract_nonce_counter, start_time_ms: 1681094380000, current_time_ms: end_time_ms, + instant_lock_quorums, }, strategy.clone(), config.clone(), @@ -461,13 +474,14 @@ mod tests { core_height_start: 1, block_count: 120, proposers, - quorums, - current_quorum_hash, + validator_quorums: quorums, + current_validator_quorum_hash: current_quorum_hash, current_proposer_versions: Some(current_proposer_versions), current_identity_nonce_counter: identity_nonce_counter, current_identity_contract_nonce_counter: identity_contract_nonce_counter, start_time_ms: 1681094380000, current_time_ms: end_time_ms, + instant_lock_quorums, }, strategy, config, @@ -544,14 +558,23 @@ mod tests { let epoch_time_length_s = 60; let config = PlatformConfig { - validator_set_quorum_size: 30, + validator_set: ValidatorSetConfig { + quorum_size: 30, + ..Default::default() + }, + chain_lock: ChainLockConfig::default_100_67(), + instant_lock: InstantLockConfig::default_100_67(), execution: ExecutionConfig { epoch_time_length_s, ..Default::default() }, initial_protocol_version: TEST_PROTOCOL_VERSION_4_WITH_1_HPMN_UPGRADE, block_spacing_ms: epoch_time_length_s * 1000, - testing_configs: PlatformTestConfig::default_with_no_block_signing(), + testing_configs: PlatformTestConfig { + block_signing: false, + block_commit_signature_verification: false, + disable_instant_lock_signature_verification: true, + }, ..Default::default() }; @@ -562,8 +585,8 @@ mod tests { let ChainExecutionOutcome { abci_app, proposers, - quorums, - current_quorum_hash, + validator_quorums: quorums, + current_validator_quorum_hash: current_quorum_hash, end_time_ms, .. } = run_chain_for_strategy(&mut platform, 1, strategy.clone(), config.clone(), 13); @@ -701,9 +724,12 @@ mod tests { }; let hour_in_ms = 1000 * 60 * 60; let config = PlatformConfig { - validator_set_quorum_size: 40, - validator_set_quorum_type: "llmq_100_67".to_string(), - chain_lock_quorum_type: "llmq_100_67".to_string(), + validator_set: ValidatorSetConfig { + quorum_size: 40, + ..Default::default() + }, + chain_lock: ChainLockConfig::default_100_67(), + instant_lock: InstantLockConfig::default_100_67(), execution: ExecutionConfig { verify_sum_trees: true, validator_set_rotation_block_count: 80, @@ -736,12 +762,13 @@ mod tests { let ChainExecutionOutcome { abci_app, proposers, - quorums, - current_quorum_hash, + validator_quorums: quorums, + current_validator_quorum_hash: current_quorum_hash, current_proposer_versions, end_time_ms, identity_nonce_counter, identity_contract_nonce_counter, + instant_lock_quorums, .. } = run_chain_for_strategy( &mut platform, @@ -789,12 +816,13 @@ mod tests { let ChainExecutionOutcome { abci_app, proposers, - quorums, - current_quorum_hash, + validator_quorums: quorums, + current_validator_quorum_hash: current_quorum_hash, end_time_ms, identity_nonce_counter, identity_contract_nonce_counter, + instant_lock_quorums, .. } = continue_chain_for_strategy( abci_app, @@ -803,13 +831,14 @@ mod tests { core_height_start: 1, block_count: 2500, proposers, - quorums, - current_quorum_hash, + validator_quorums: quorums, + current_validator_quorum_hash: current_quorum_hash, current_proposer_versions: Some(current_proposer_versions.clone()), current_identity_nonce_counter: identity_nonce_counter, current_identity_contract_nonce_counter: identity_contract_nonce_counter, start_time_ms: 1681094380000, current_time_ms: end_time_ms, + instant_lock_quorums, }, strategy.clone(), config.clone(), @@ -856,13 +885,14 @@ mod tests { core_height_start: 1, block_count: 400, proposers, - quorums, - current_quorum_hash, + validator_quorums: quorums, + current_validator_quorum_hash: current_quorum_hash, current_proposer_versions: Some(current_proposer_versions), current_identity_nonce_counter: identity_nonce_counter, current_identity_contract_nonce_counter: identity_contract_nonce_counter, start_time_ms: 1681094380000, current_time_ms: end_time_ms, + instant_lock_quorums, }, strategy, config, @@ -934,9 +964,12 @@ mod tests { }; let hour_in_ms = 1000 * 60 * 60; let mut config = PlatformConfig { - validator_set_quorum_size: 50, - validator_set_quorum_type: "llmq_100_67".to_string(), - chain_lock_quorum_type: "llmq_100_67".to_string(), + validator_set: ValidatorSetConfig { + quorum_size: 50, + ..Default::default() + }, + chain_lock: ChainLockConfig::default_100_67(), + instant_lock: InstantLockConfig::default_100_67(), execution: ExecutionConfig { verify_sum_trees: true, validator_set_rotation_block_count: 50, @@ -968,12 +1001,13 @@ mod tests { let ChainExecutionOutcome { abci_app, proposers, - quorums, - current_quorum_hash, + validator_quorums: quorums, + current_validator_quorum_hash: current_quorum_hash, current_proposer_versions, end_time_ms, identity_nonce_counter, identity_contract_nonce_counter, + instant_lock_quorums, .. } = run_chain_for_strategy( &mut platform, @@ -1013,12 +1047,13 @@ mod tests { let ChainExecutionOutcome { abci_app, proposers, - quorums, - current_quorum_hash, + validator_quorums: quorums, + current_validator_quorum_hash: current_quorum_hash, end_time_ms, identity_nonce_counter, identity_contract_nonce_counter, + instant_lock_quorums, .. } = continue_chain_for_strategy( abci_app, @@ -1027,13 +1062,14 @@ mod tests { core_height_start: 1, block_count: 3000, proposers, - quorums, - current_quorum_hash, + validator_quorums: quorums, + current_validator_quorum_hash: current_quorum_hash, current_proposer_versions: Some(current_proposer_versions), current_identity_nonce_counter: identity_nonce_counter, current_identity_contract_nonce_counter: identity_contract_nonce_counter, start_time_ms: 1681094380000, current_time_ms: end_time_ms, + instant_lock_quorums, }, strategy, config.clone(), @@ -1108,13 +1144,14 @@ mod tests { let ChainExecutionOutcome { abci_app, proposers, - quorums, - current_quorum_hash, + validator_quorums: quorums, + current_validator_quorum_hash: current_quorum_hash, current_proposer_versions, end_time_ms, identity_nonce_counter, identity_contract_nonce_counter, + instant_lock_quorums, .. } = continue_chain_for_strategy( abci_app, @@ -1123,13 +1160,14 @@ mod tests { core_height_start: 1, block_count: 2000, proposers, - quorums, - current_quorum_hash, + validator_quorums: quorums, + current_validator_quorum_hash: current_quorum_hash, current_proposer_versions: None, //restart the proposer versions current_identity_nonce_counter: identity_nonce_counter, current_identity_contract_nonce_counter: identity_contract_nonce_counter, start_time_ms: 1681094380000, current_time_ms: end_time_ms, + instant_lock_quorums, }, strategy.clone(), config.clone(), @@ -1178,13 +1216,14 @@ mod tests { core_height_start: 1, block_count: 100, proposers, - quorums, - current_quorum_hash, + validator_quorums: quorums, + current_validator_quorum_hash: current_quorum_hash, current_proposer_versions: Some(current_proposer_versions), current_identity_nonce_counter: identity_nonce_counter, current_identity_contract_nonce_counter: identity_contract_nonce_counter, start_time_ms: 1681094380000, current_time_ms: end_time_ms, + instant_lock_quorums, }, strategy, config, @@ -1263,9 +1302,12 @@ mod tests { }; let hour_in_ms = 1000 * 60 * 60; let config = PlatformConfig { - validator_set_quorum_size: 50, - validator_set_quorum_type: "llmq_100_67".to_string(), - chain_lock_quorum_type: "llmq_100_67".to_string(), + validator_set: ValidatorSetConfig { + quorum_size: 50, + ..Default::default() + }, + chain_lock: ChainLockConfig::default_100_67(), + instant_lock: InstantLockConfig::default_100_67(), execution: ExecutionConfig { verify_sum_trees: true, validator_set_rotation_block_count: 30, @@ -1297,11 +1339,12 @@ mod tests { let ChainExecutionOutcome { abci_app, proposers, - quorums, - current_quorum_hash, + validator_quorums: quorums, + current_validator_quorum_hash: current_quorum_hash, end_time_ms, identity_nonce_counter, identity_contract_nonce_counter, + instant_lock_quorums, .. } = run_chain_for_strategy(&mut platform, 1400, strategy, config.clone(), 15); let state = abci_app.platform.state.load(); @@ -1395,13 +1438,14 @@ mod tests { core_height_start: 1, block_count: 1100, proposers, - quorums, - current_quorum_hash, + validator_quorums: quorums, + current_validator_quorum_hash: current_quorum_hash, current_proposer_versions: None, current_identity_nonce_counter: identity_nonce_counter, current_identity_contract_nonce_counter: identity_contract_nonce_counter, start_time_ms: 1681094380000, current_time_ms: end_time_ms, + instant_lock_quorums, }, strategy, config, diff --git a/packages/rs-platform-version/src/version/drive_abci_versions.rs b/packages/rs-platform-version/src/version/drive_abci_versions.rs index 2439f050b17..5953f56e91c 100644 --- a/packages/rs-platform-version/src/version/drive_abci_versions.rs +++ b/packages/rs-platform-version/src/version/drive_abci_versions.rs @@ -53,6 +53,7 @@ pub struct DriveAbciStructureVersions { pub state_transition_execution_context: FeatureVersion, pub commit: FeatureVersion, pub masternode: FeatureVersion, + pub signature_verification_quorum_set: FeatureVersion, } #[derive(Clone, Debug, Default)] @@ -64,6 +65,7 @@ pub struct DriveAbciMethodVersions { pub block_fee_processing: DriveAbciBlockFeeProcessingMethodVersions, pub core_subsidy: DriveAbciCoreSubsidyMethodVersions, pub core_chain_lock: DriveAbciCoreChainLockMethodVersionsAndConstants, + pub core_instant_send_lock: DriveAbciCoreInstantSendLockMethodVersions, pub fee_pool_inwards_distribution: DriveAbciFeePoolInwardsDistributionMethodVersions, pub fee_pool_outwards_distribution: DriveAbciFeePoolOutwardsDistributionMethodVersions, pub withdrawals: DriveAbciIdentityCreditWithdrawalMethodVersions, @@ -231,6 +233,11 @@ pub struct DriveAbciCoreSubsidyMethodVersions { pub epoch_core_reward_credits_for_distribution: FeatureVersion, } +#[derive(Clone, Debug, Default)] +pub struct DriveAbciCoreInstantSendLockMethodVersions { + pub verify_recent_signature_locally: FeatureVersion, +} + #[derive(Clone, Debug, Default)] pub struct DriveAbciCoreChainLockMethodVersionsAndConstants { pub choose_quorum: FeatureVersion, diff --git a/packages/rs-platform-version/src/version/mocks/v2_test.rs b/packages/rs-platform-version/src/version/mocks/v2_test.rs index d47370d65b7..41e1a4f381b 100644 --- a/packages/rs-platform-version/src/version/mocks/v2_test.rs +++ b/packages/rs-platform-version/src/version/mocks/v2_test.rs @@ -15,9 +15,9 @@ use crate::version::drive_abci_versions::{ DriveAbciAssetLockValidationVersions, DriveAbciBlockEndMethodVersions, DriveAbciBlockFeeProcessingMethodVersions, DriveAbciBlockStartMethodVersions, DriveAbciCoreBasedUpdatesMethodVersions, DriveAbciCoreChainLockMethodVersionsAndConstants, - DriveAbciCoreSubsidyMethodVersions, DriveAbciDocumentsStateTransitionValidationVersions, - DriveAbciEngineMethodVersions, DriveAbciEpochMethodVersions, - DriveAbciFeePoolInwardsDistributionMethodVersions, + DriveAbciCoreInstantSendLockMethodVersions, DriveAbciCoreSubsidyMethodVersions, + DriveAbciDocumentsStateTransitionValidationVersions, DriveAbciEngineMethodVersions, + DriveAbciEpochMethodVersions, DriveAbciFeePoolInwardsDistributionMethodVersions, DriveAbciFeePoolOutwardsDistributionMethodVersions, DriveAbciIdentityCreditWithdrawalMethodVersions, DriveAbciInitializationMethodVersions, DriveAbciMasternodeIdentitiesUpdatesMethodVersions, DriveAbciMethodVersions, @@ -502,6 +502,7 @@ pub const TEST_PLATFORM_V2: PlatformVersion = PlatformVersion { state_transition_execution_context: 0, commit: 0, masternode: 0, + signature_verification_quorum_set: 0, }, methods: DriveAbciMethodVersions { engine: DriveAbciEngineMethodVersions { @@ -555,6 +556,9 @@ pub const TEST_PLATFORM_V2: PlatformVersion = PlatformVersion { make_sure_core_is_synced_to_chain_lock: 0, recent_block_count_amount: 2, }, + core_instant_send_lock: DriveAbciCoreInstantSendLockMethodVersions { + verify_recent_signature_locally: 0, + }, fee_pool_inwards_distribution: DriveAbciFeePoolInwardsDistributionMethodVersions { add_distribute_block_fees_into_pools_operations: 0, add_distribute_storage_fee_to_epochs_operations: 0, diff --git a/packages/rs-platform-version/src/version/mocks/v3_test.rs b/packages/rs-platform-version/src/version/mocks/v3_test.rs index d603bf780e8..c027f7886fc 100644 --- a/packages/rs-platform-version/src/version/mocks/v3_test.rs +++ b/packages/rs-platform-version/src/version/mocks/v3_test.rs @@ -15,9 +15,9 @@ use crate::version::drive_abci_versions::{ DriveAbciAssetLockValidationVersions, DriveAbciBlockEndMethodVersions, DriveAbciBlockFeeProcessingMethodVersions, DriveAbciBlockStartMethodVersions, DriveAbciCoreBasedUpdatesMethodVersions, DriveAbciCoreChainLockMethodVersionsAndConstants, - DriveAbciCoreSubsidyMethodVersions, DriveAbciDocumentsStateTransitionValidationVersions, - DriveAbciEngineMethodVersions, DriveAbciEpochMethodVersions, - DriveAbciFeePoolInwardsDistributionMethodVersions, + DriveAbciCoreInstantSendLockMethodVersions, DriveAbciCoreSubsidyMethodVersions, + DriveAbciDocumentsStateTransitionValidationVersions, DriveAbciEngineMethodVersions, + DriveAbciEpochMethodVersions, DriveAbciFeePoolInwardsDistributionMethodVersions, DriveAbciFeePoolOutwardsDistributionMethodVersions, DriveAbciIdentityCreditWithdrawalMethodVersions, DriveAbciInitializationMethodVersions, DriveAbciMasternodeIdentitiesUpdatesMethodVersions, DriveAbciMethodVersions, @@ -502,6 +502,7 @@ pub const TEST_PLATFORM_V3: PlatformVersion = PlatformVersion { state_transition_execution_context: 0, commit: 0, masternode: 0, + signature_verification_quorum_set: 0, }, methods: DriveAbciMethodVersions { engine: DriveAbciEngineMethodVersions { @@ -555,6 +556,9 @@ pub const TEST_PLATFORM_V3: PlatformVersion = PlatformVersion { make_sure_core_is_synced_to_chain_lock: 0, recent_block_count_amount: 2, }, + core_instant_send_lock: DriveAbciCoreInstantSendLockMethodVersions { + verify_recent_signature_locally: 0, + }, fee_pool_inwards_distribution: DriveAbciFeePoolInwardsDistributionMethodVersions { add_distribute_block_fees_into_pools_operations: 0, add_distribute_storage_fee_to_epochs_operations: 0, diff --git a/packages/rs-platform-version/src/version/v1.rs b/packages/rs-platform-version/src/version/v1.rs index 268ae2a7c57..a539e8bc29e 100644 --- a/packages/rs-platform-version/src/version/v1.rs +++ b/packages/rs-platform-version/src/version/v1.rs @@ -15,9 +15,9 @@ use crate::version::drive_abci_versions::{ DriveAbciAssetLockValidationVersions, DriveAbciBlockEndMethodVersions, DriveAbciBlockFeeProcessingMethodVersions, DriveAbciBlockStartMethodVersions, DriveAbciCoreBasedUpdatesMethodVersions, DriveAbciCoreChainLockMethodVersionsAndConstants, - DriveAbciCoreSubsidyMethodVersions, DriveAbciDocumentsStateTransitionValidationVersions, - DriveAbciEngineMethodVersions, DriveAbciEpochMethodVersions, - DriveAbciFeePoolInwardsDistributionMethodVersions, + DriveAbciCoreInstantSendLockMethodVersions, DriveAbciCoreSubsidyMethodVersions, + DriveAbciDocumentsStateTransitionValidationVersions, DriveAbciEngineMethodVersions, + DriveAbciEpochMethodVersions, DriveAbciFeePoolInwardsDistributionMethodVersions, DriveAbciFeePoolOutwardsDistributionMethodVersions, DriveAbciIdentityCreditWithdrawalMethodVersions, DriveAbciInitializationMethodVersions, DriveAbciMasternodeIdentitiesUpdatesMethodVersions, DriveAbciMethodVersions, @@ -501,6 +501,7 @@ pub const PLATFORM_V1: PlatformVersion = PlatformVersion { state_transition_execution_context: 0, commit: 0, masternode: 0, + signature_verification_quorum_set: 0, }, methods: DriveAbciMethodVersions { engine: DriveAbciEngineMethodVersions { @@ -554,6 +555,9 @@ pub const PLATFORM_V1: PlatformVersion = PlatformVersion { make_sure_core_is_synced_to_chain_lock: 0, recent_block_count_amount: 2, }, + core_instant_send_lock: DriveAbciCoreInstantSendLockMethodVersions { + verify_recent_signature_locally: 0, + }, fee_pool_inwards_distribution: DriveAbciFeePoolInwardsDistributionMethodVersions { add_distribute_block_fees_into_pools_operations: 0, add_distribute_storage_fee_to_epochs_operations: 0, diff --git a/packages/strategy-tests/src/transitions.rs b/packages/strategy-tests/src/transitions.rs index 0ef26db956b..0a9ef44be30 100644 --- a/packages/strategy-tests/src/transitions.rs +++ b/packages/strategy-tests/src/transitions.rs @@ -779,7 +779,7 @@ pub fn create_state_transitions_for_identities( let (_, pk) = ECDSA_SECP256K1 .random_public_and_private_key_data(rng, platform_version) .unwrap(); - let sk: [u8; 32] = pk.clone().try_into().unwrap(); + let sk: [u8; 32] = pk.try_into().unwrap(); let secret_key = SecretKey::from_str(hex::encode(sk).as_str()).unwrap(); let asset_lock_proof = instant_asset_lock_proof_fixture(PrivateKey::new(secret_key, Network::Dash)); @@ -787,7 +787,33 @@ pub fn create_state_transitions_for_identities( IdentityCreateTransition::try_from_identity_with_signer( &identity.clone(), asset_lock_proof, - pk.as_slice(), + &sk, + signer, + &NativeBlsModule, + 0, + platform_version, + ) + .expect("expected to transform identity into identity create transition"); + identity.set_id(identity_create_transition.owner_id()); + + (identity, identity_create_transition) + }) + .collect() +} + +pub fn create_state_transitions_for_identities_and_proofs( + identities_with_proofs: Vec<(Identity, [u8; 32], AssetLockProof)>, + signer: &mut SimpleSigner, + platform_version: &PlatformVersion, +) -> Vec<(Identity, StateTransition)> { + identities_with_proofs + .into_iter() + .map(|(mut identity, private_key, asset_lock_proof)| { + let identity_create_transition = + IdentityCreateTransition::try_from_identity_with_signer( + &identity.clone(), + asset_lock_proof, + &private_key, signer, &NativeBlsModule, 0, diff --git a/packages/wallet-lib/package.json b/packages/wallet-lib/package.json index 263c42579f0..9aa0faeccc7 100644 --- a/packages/wallet-lib/package.json +++ b/packages/wallet-lib/package.json @@ -72,7 +72,7 @@ "eslint-plugin-import": "^2.29.0", "events": "^3.3.0", "https-browserify": "^1.0.0", - "karma": "^6.4.1", + "karma": "^6.4.3", "karma-chai": "^0.1.0", "karma-chrome-launcher": "^3.1.0", "karma-firefox-launcher": "^2.1.2", diff --git a/packages/wasm-dpp/package.json b/packages/wasm-dpp/package.json index ef9f8f09b3a..6617b1e6ac3 100644 --- a/packages/wasm-dpp/package.json +++ b/packages/wasm-dpp/package.json @@ -64,7 +64,7 @@ "fast-json-patch": "^3.1.1", "https-browserify": "^1.0.0", "json-schema-diff-validator": "^0.4.1", - "karma": "^6.4.1", + "karma": "^6.4.3", "karma-chai": "^0.1.0", "karma-chrome-launcher": "^3.1.0", "karma-firefox-launcher": "^2.1.2", diff --git a/yarn.lock b/yarn.lock index 35315db6461..83176e15518 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1490,7 +1490,7 @@ __metadata: eslint-plugin-jsdoc: "npm:^46.9.0" events: "npm:^3.3.0" google-protobuf: "npm:^3.12.2" - karma: "npm:^6.4.1" + karma: "npm:^6.4.3" karma-chai: "npm:^0.1.0" karma-chrome-launcher: "npm:^3.1.0" karma-firefox-launcher: "npm:^2.1.2" @@ -1583,7 +1583,7 @@ __metadata: sinon: "npm:^17.0.1" sinon-chai: "npm:^3.7.0" swagger-jsdoc: "npm:^3.5.0" - ws: "npm:^7.5.3" + ws: "npm:^8.17.1" languageName: unknown linkType: soft @@ -1806,7 +1806,7 @@ __metadata: glob: "npm:^10.3.4" https-browserify: "npm:^1.0.0" js-merkle: "npm:^0.1.5" - karma: "npm:^6.4.1" + karma: "npm:^6.4.3" karma-chai: "npm:^0.1.0" karma-chrome-launcher: "npm:^3.1.0" karma-firefox-launcher: "npm:^2.1.2" @@ -1833,7 +1833,7 @@ __metadata: utf-8-validate: "npm:^5.0.9" util: "npm:^0.12.4" webpack: "npm:^5.76.1" - ws: "npm:^7.5.3" + ws: "npm:^8.17.1" bin: test: bin/test.sh languageName: unknown @@ -1903,7 +1903,7 @@ __metadata: eslint-plugin-import: "npm:^2.29.0" events: "npm:^3.3.0" https-browserify: "npm:^1.0.0" - karma: "npm:^6.4.1" + karma: "npm:^6.4.3" karma-chai: "npm:^0.1.0" karma-chrome-launcher: "npm:^3.1.0" karma-firefox-launcher: "npm:^2.1.2" @@ -1966,7 +1966,7 @@ __metadata: fast-json-patch: "npm:^3.1.1" https-browserify: "npm:^1.0.0" json-schema-diff-validator: "npm:^0.4.1" - karma: "npm:^6.4.1" + karma: "npm:^6.4.3" karma-chai: "npm:^0.1.0" karma-chrome-launcher: "npm:^3.1.0" karma-firefox-launcher: "npm:^2.1.2" @@ -6274,7 +6274,7 @@ __metadata: eslint-plugin-import: "npm:^2.29.0" events: "npm:^3.3.0" https-browserify: "npm:^1.0.0" - karma: "npm:^6.4.1" + karma: "npm:^6.4.3" karma-chai: "npm:^0.1.0" karma-chrome-launcher: "npm:^3.1.0" karma-firefox-launcher: "npm:^2.1.2" @@ -6438,6 +6438,18 @@ __metadata: languageName: node linkType: hard +"debug@npm:~4.3.4": + version: 4.3.5 + resolution: "debug@npm:4.3.5" + dependencies: + ms: "npm:2.1.2" + peerDependenciesMeta: + supports-color: + optional: true + checksum: cb6eab424c410e07813ca1392888589972ce9a32b8829c6508f5e1f25f3c3e70a76731610ae55b4bbe58d1a2fffa1424b30e97fa8d394e49cd2656a9643aedd2 + languageName: node + linkType: hard + "debuglog@npm:^1.0.1": version: 1.0.1 resolution: "debuglog@npm:1.0.1" @@ -9924,9 +9936,9 @@ __metadata: languageName: node linkType: hard -"karma@npm:^6.4.1": - version: 6.4.1 - resolution: "karma@npm:6.4.1" +"karma@npm:^6.4.3": + version: 6.4.3 + resolution: "karma@npm:6.4.3" dependencies: "@colors/colors": "npm:1.5.0" body-parser: "npm:^1.19.0" @@ -9947,14 +9959,14 @@ __metadata: qjobs: "npm:^1.2.0" range-parser: "npm:^1.2.1" rimraf: "npm:^3.0.2" - socket.io: "npm:^4.4.1" + socket.io: "npm:^4.7.2" source-map: "npm:^0.6.1" tmp: "npm:^0.2.1" ua-parser-js: "npm:^0.7.30" yargs: "npm:^16.1.1" bin: karma: bin/karma - checksum: 24faabfaf05fbef1bb3a7b218549ace55566c59f64e3602c55e5fc221c3fcec69f80ec43901f64225d0020fd3f9d756e947df609530ef0a5565020096bf6a056 + checksum: 7fc194f5d4b0dae27e97375d0e005a7b74a6bee3c6ad676c3e21ec7c6309f32202d62cf0f0645ea99aa5adea455d79afe1d32e8aa28ac3c09609f16d0e2120ca languageName: node linkType: hard @@ -13896,10 +13908,13 @@ __metadata: languageName: node linkType: hard -"socket.io-adapter@npm:~2.4.0": - version: 2.4.0 - resolution: "socket.io-adapter@npm:2.4.0" - checksum: e10c8c36a1b0744432d9fb7266c69268fb11cacb548e95f5feb7708c1438c4c1e034abf3eee56dc3fd4d5524aba4e5a306a402f0c15efb1334be364a05bfad04 +"socket.io-adapter@npm:~2.5.2": + version: 2.5.5 + resolution: "socket.io-adapter@npm:2.5.5" + dependencies: + debug: "npm:~4.3.4" + ws: "npm:~8.17.1" + checksum: e364733a4c34ff1d4a02219e409bd48074fd614b7f5b0568ccfa30dd553252a5b9a41056931306a276891d13ea76a19e2c6f2128a4675c37323f642896874d80 languageName: node linkType: hard @@ -13913,17 +13928,18 @@ __metadata: languageName: node linkType: hard -"socket.io@npm:^4.4.1": - version: 4.5.2 - resolution: "socket.io@npm:4.5.2" +"socket.io@npm:^4.7.2": + version: 4.7.5 + resolution: "socket.io@npm:4.7.5" dependencies: accepts: "npm:~1.3.4" base64id: "npm:~2.0.0" + cors: "npm:~2.8.5" debug: "npm:~4.3.2" - engine.io: "npm:~6.2.0" - socket.io-adapter: "npm:~2.4.0" - socket.io-parser: "npm:~4.2.0" - checksum: 872605db0f8bb3fa78c54ba13b22dced2270a7a52967ef215c3121b93312606ec5e0862a6cde058a63ba23c404733e52d560c3ca73dc3d0c8cbed35bbae65731 + engine.io: "npm:~6.5.2" + socket.io-adapter: "npm:~2.5.2" + socket.io-parser: "npm:~4.2.4" + checksum: 911528f5bfdf83dbe2b154866884b736a7498f112f294a6f8420418fa11baadf08578869dab3e220c943094ff0d17b7f4587de3b1ad39679d9c12ed4cb226900 languageName: node linkType: hard @@ -15868,33 +15884,18 @@ __metadata: languageName: node linkType: hard -"ws@npm:^7.4.5, ws@npm:^7.5.3": - version: 7.5.5 - resolution: "ws@npm:7.5.5" - peerDependencies: - bufferutil: ^4.0.1 - utf-8-validate: ^5.0.2 - peerDependenciesMeta: - bufferutil: - optional: true - utf-8-validate: - optional: true - checksum: 2e91fd634b470f3a39bd6a9ada5e398a411bd9a32bd10d11c4ceabb2e4fd28835aeb5187fd2fc489c3e65bfdab4c29187f083d6672d7aeba014ab8a3f5f1ece2 - languageName: node - linkType: hard - -"ws@npm:~8.11.0": - version: 8.11.0 - resolution: "ws@npm:8.11.0" +"ws@npm:^8.17.1": + version: 8.17.1 + resolution: "ws@npm:8.17.1" peerDependencies: bufferutil: ^4.0.1 - utf-8-validate: ^5.0.2 + utf-8-validate: ">=5.0.2" peerDependenciesMeta: bufferutil: optional: true utf-8-validate: optional: true - checksum: f759ea19e42f6d94727b3d8590693f2d92521a78ec2de5c6064c3356f50d4815d427b7ddb10bf39596cc67d3b18232a1b2dfbc3b6361d4772bdfec69d4c130f4 + checksum: 4264ae92c0b3e59c7e309001e93079b26937aab181835fb7af79f906b22cd33b6196d96556dafb4e985742dd401e99139572242e9847661fdbc96556b9e6902d languageName: node linkType: hard