From 738ee9ccd14d8ab925c8b778590372dc59f8e8d8 Mon Sep 17 00:00:00 2001 From: Djavid Gabibyan Date: Fri, 16 Dec 2022 16:29:40 +0500 Subject: [PATCH 001/170] chore: deps update --- .pnp.cjs | 2054 ++++++----------- .pnp.loader.mjs | 1809 +-------------- .yarn/cache/fsevents-patch-2882183fbf-8.zip | Bin 23675 -> 0 bytes ...> resolve-patch-bad885c6ea-c79ecaea36.zip} | Bin ...ypescript-patch-1236c99922-dc7141ab55.zip} | Bin yarn.lock | 6 +- 6 files changed, 705 insertions(+), 3164 deletions(-) delete mode 100644 .yarn/cache/fsevents-patch-2882183fbf-8.zip rename .yarn/cache/{resolve-patch-b984c6fd86-c79ecaea36.zip => resolve-patch-bad885c6ea-c79ecaea36.zip} (100%) rename .yarn/cache/{typescript-patch-7ad1c7f5d0-dc7141ab55.zip => typescript-patch-1236c99922-dc7141ab55.zip} (100%) diff --git a/.pnp.cjs b/.pnp.cjs index 62f3b1a2657..b4e291c7a9c 100755 --- a/.pnp.cjs +++ b/.pnp.cjs @@ -1,6 +1,11 @@ #!/usr/bin/env node /* eslint-disable */ -"use strict"; + +try { + Object.freeze({}).detectStrictMode = true; +} catch (error) { + throw new Error(`The whole PnP file got strict-mode-ified, which is known to break (Emscripten libraries aren't strict mode). This usually happens when the file goes through Babel.`); +} function $$SETUP_STATE(hydrateRuntimeState, basePath) { return hydrateRuntimeState(JSON.parse('{\ @@ -327,7 +332,7 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { ["@types/babel__core", null],\ ["debug", "virtual:c2bff3e67180802999655a22d390062982690e911b9d9225c258f3b25e7409f3867b2682c16232b77415f560a09d05a95042dc512a5b8c566c42bbbed88b0bbc#npm:4.3.4"],\ ["lodash.debounce", "npm:4.0.8"],\ - ["resolve", "patch:resolve@npm%3A1.22.0#~builtin::version=1.22.0&hash=c3c19d"],\ + ["resolve", "patch:resolve@npm%3A1.22.0#~builtin::version=1.22.0&hash=07638b"],\ ["semver", "npm:6.3.0"]\ ],\ "packagePeers": [\ @@ -2996,7 +3001,7 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { ["stream-http", "npm:3.2.0"],\ ["string_decoder", "npm:1.3.0"],\ ["ts-loader", "virtual:e2d057e7cc143d3cb9bec864f4a2d862441b5a09f81f8e6c46e7a098cbc89e4d07017cc6e2e2142d5704bb55da853cbec2d025ebc0b30e8696c31380c00f2c7d#npm:8.3.0"],\ - ["typescript", "patch:typescript@npm%3A3.9.10#~builtin::version=3.9.10&hash=3bd3d3"],\ + ["typescript", "patch:typescript@npm%3A3.9.10#~builtin::version=3.9.10&hash=f456af"],\ ["url", "npm:0.11.0"],\ ["util", "npm:0.12.4"],\ ["webpack", "virtual:e2d057e7cc143d3cb9bec864f4a2d862441b5a09f81f8e6c46e7a098cbc89e4d07017cc6e2e2142d5704bb55da853cbec2d025ebc0b30e8696c31380c00f2c7d#npm:5.64.1"],\ @@ -5662,7 +5667,7 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { ["@types/eslint", null],\ ["eslint", "npm:7.32.0"],\ ["eslint-visitor-keys", "npm:1.3.0"],\ - ["resolve", "patch:resolve@npm%3A1.22.0#~builtin::version=1.22.0&hash=c3c19d"]\ + ["resolve", "patch:resolve@npm%3A1.22.0#~builtin::version=1.22.0&hash=07638b"]\ ],\ "packagePeers": [\ "@types/eslint",\ @@ -6606,7 +6611,7 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { ["chokidar", "npm:3.5.3"],\ ["anymatch", "npm:3.1.2"],\ ["braces", "npm:3.0.2"],\ - ["fsevents", "patch:fsevents@npm%3A2.3.2#~builtin::version=2.3.2&hash=df0bf1"],\ + ["fsevents", "patch:fsevents@npm%3A2.3.2#~builtin::version=2.3.2&hash=18f3a7"],\ ["glob-parent", "npm:5.1.2"],\ ["is-binary-path", "npm:2.1.0"],\ ["is-glob", "npm:4.0.3"],\ @@ -7604,7 +7609,7 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { ["ts-mocha", "virtual:ad53cff31b1dbd4927a99e71702e3b8b10338636eaff010987c27c9ccea2d52af36900a9e36a4231cbb6e5464248ccc9c1da5d1d24d9b0f4f95660296b1060a6#npm:9.0.2"],\ ["ts-mock-imports", "virtual:ad53cff31b1dbd4927a99e71702e3b8b10338636eaff010987c27c9ccea2d52af36900a9e36a4231cbb6e5464248ccc9c1da5d1d24d9b0f4f95660296b1060a6#npm:1.3.8"],\ ["ts-node", "virtual:ad53cff31b1dbd4927a99e71702e3b8b10338636eaff010987c27c9ccea2d52af36900a9e36a4231cbb6e5464248ccc9c1da5d1d24d9b0f4f95660296b1060a6#npm:10.4.0"],\ - ["typescript", "patch:typescript@npm%3A3.9.10#~builtin::version=3.9.10&hash=3bd3d3"],\ + ["typescript", "patch:typescript@npm%3A3.9.10#~builtin::version=3.9.10&hash=f456af"],\ ["url", "npm:0.11.0"],\ ["util", "npm:0.12.4"],\ ["webpack", "virtual:ad53cff31b1dbd4927a99e71702e3b8b10338636eaff010987c27c9ccea2d52af36900a9e36a4231cbb6e5464248ccc9c1da5d1d24d9b0f4f95660296b1060a6#npm:5.64.1"],\ @@ -8729,7 +8734,7 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { "packageDependencies": [\ ["eslint-import-resolver-node", "npm:0.3.6"],\ ["debug", "virtual:d9426786c635bc4b52511d6cc4b56156f50d780a698c0e20fc6caf10d3be51cbf176e79cff882f4d42a23ff4d0f89fe94222849578214e7fbae0f2754c82af02#npm:3.2.7"],\ - ["resolve", "patch:resolve@npm%3A1.22.0#~builtin::version=1.22.0&hash=c3c19d"]\ + ["resolve", "patch:resolve@npm%3A1.22.0#~builtin::version=1.22.0&hash=07638b"]\ ],\ "linkType": "HARD"\ }]\ @@ -8798,7 +8803,7 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { ["is-glob", "npm:4.0.3"],\ ["minimatch", "npm:3.1.2"],\ ["object.values", "npm:1.1.5"],\ - ["resolve", "patch:resolve@npm%3A1.22.0#~builtin::version=1.22.0&hash=c3c19d"],\ + ["resolve", "patch:resolve@npm%3A1.22.0#~builtin::version=1.22.0&hash=07638b"],\ ["tsconfig-paths", "npm:3.12.0"]\ ],\ "packagePeers": [\ @@ -9565,10 +9570,10 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { }]\ ]],\ ["fsevents", [\ - ["patch:fsevents@npm%3A2.3.2#~builtin::version=2.3.2&hash=df0bf1", {\ - "packageLocation": "./.yarn/unplugged/fsevents-patch-2882183fbf/node_modules/fsevents/",\ + ["patch:fsevents@npm%3A2.3.2#~builtin::version=2.3.2&hash=18f3a7", {\ + "packageLocation": "./.yarn/unplugged/fsevents-patch-3340e2eb10/node_modules/fsevents/",\ "packageDependencies": [\ - ["fsevents", "patch:fsevents@npm%3A2.3.2#~builtin::version=2.3.2&hash=df0bf1"],\ + ["fsevents", "patch:fsevents@npm%3A2.3.2#~builtin::version=2.3.2&hash=18f3a7"],\ ["node-gyp", "npm:8.4.0"]\ ],\ "linkType": "HARD"\ @@ -13385,7 +13390,7 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { "packageDependencies": [\ ["normalize-package-data", "npm:2.5.0"],\ ["hosted-git-info", "npm:2.8.9"],\ - ["resolve", "patch:resolve@npm%3A1.22.0#~builtin::version=1.22.0&hash=c3c19d"],\ + ["resolve", "patch:resolve@npm%3A1.22.0#~builtin::version=1.22.0&hash=07638b"],\ ["semver", "npm:5.7.1"],\ ["validate-npm-package-license", "npm:3.0.4"]\ ],\ @@ -14940,7 +14945,7 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { "packageLocation": "./.yarn/cache/rechoir-npm-0.6.2-0df5f171ec-fe76bf9c21.zip/node_modules/rechoir/",\ "packageDependencies": [\ ["rechoir", "npm:0.6.2"],\ - ["resolve", "patch:resolve@npm%3A1.22.0#~builtin::version=1.22.0&hash=c3c19d"]\ + ["resolve", "patch:resolve@npm%3A1.22.0#~builtin::version=1.22.0&hash=07638b"]\ ],\ "linkType": "HARD"\ }],\ @@ -14948,7 +14953,7 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { "packageLocation": "./.yarn/cache/rechoir-npm-0.7.1-0c7e5c1201-2a04aab4e2.zip/node_modules/rechoir/",\ "packageDependencies": [\ ["rechoir", "npm:0.7.1"],\ - ["resolve", "patch:resolve@npm%3A1.22.0#~builtin::version=1.22.0&hash=c3c19d"]\ + ["resolve", "patch:resolve@npm%3A1.22.0#~builtin::version=1.22.0&hash=07638b"]\ ],\ "linkType": "HARD"\ }]\ @@ -15147,10 +15152,10 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { }]\ ]],\ ["resolve", [\ - ["patch:resolve@npm%3A1.22.0#~builtin::version=1.22.0&hash=c3c19d", {\ - "packageLocation": "./.yarn/cache/resolve-patch-b984c6fd86-c79ecaea36.zip/node_modules/resolve/",\ + ["patch:resolve@npm%3A1.22.0#~builtin::version=1.22.0&hash=07638b", {\ + "packageLocation": "./.yarn/cache/resolve-patch-bad885c6ea-c79ecaea36.zip/node_modules/resolve/",\ "packageDependencies": [\ - ["resolve", "patch:resolve@npm%3A1.22.0#~builtin::version=1.22.0&hash=c3c19d"],\ + ["resolve", "patch:resolve@npm%3A1.22.0#~builtin::version=1.22.0&hash=07638b"],\ ["is-core-module", "npm:2.8.1"],\ ["path-parse", "npm:1.0.7"],\ ["supports-preserve-symlinks-flag", "npm:1.0.0"]\ @@ -17012,7 +17017,7 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { ["loader-utils", "npm:2.0.2"],\ ["micromatch", "npm:4.0.4"],\ ["semver", "npm:7.3.7"],\ - ["typescript", "patch:typescript@npm%3A3.9.10#~builtin::version=3.9.10&hash=3bd3d3"],\ + ["typescript", "patch:typescript@npm%3A3.9.10#~builtin::version=3.9.10&hash=f456af"],\ ["webpack", "virtual:ad53cff31b1dbd4927a99e71702e3b8b10338636eaff010987c27c9ccea2d52af36900a9e36a4231cbb6e5464248ccc9c1da5d1d24d9b0f4f95660296b1060a6#npm:5.64.1"]\ ],\ "packagePeers": [\ @@ -17034,7 +17039,7 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { ["loader-utils", "npm:2.0.2"],\ ["micromatch", "npm:4.0.4"],\ ["semver", "npm:7.3.7"],\ - ["typescript", "patch:typescript@npm%3A3.9.10#~builtin::version=3.9.10&hash=3bd3d3"],\ + ["typescript", "patch:typescript@npm%3A3.9.10#~builtin::version=3.9.10&hash=f456af"],\ ["webpack", "virtual:e2d057e7cc143d3cb9bec864f4a2d862441b5a09f81f8e6c46e7a098cbc89e4d07017cc6e2e2142d5704bb55da853cbec2d025ebc0b30e8696c31380c00f2c7d#npm:5.64.1"]\ ],\ "packagePeers": [\ @@ -17085,7 +17090,7 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { ["@types/sinon", "npm:9.0.11"],\ ["@types/typescript", null],\ ["sinon", "npm:11.1.2"],\ - ["typescript", "patch:typescript@npm%3A3.9.10#~builtin::version=3.9.10&hash=3bd3d3"]\ + ["typescript", "patch:typescript@npm%3A3.9.10#~builtin::version=3.9.10&hash=f456af"]\ ],\ "packagePeers": [\ "@types/sinon",\ @@ -17115,7 +17120,7 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { ["minimist", "npm:1.2.6"],\ ["mkdirp", "npm:0.5.6"],\ ["source-map-support", "npm:0.5.21"],\ - ["typescript", "patch:typescript@npm%3A3.9.10#~builtin::version=3.9.10&hash=3bd3d3"],\ + ["typescript", "patch:typescript@npm%3A3.9.10#~builtin::version=3.9.10&hash=f456af"],\ ["yn", "npm:2.0.0"]\ ],\ "linkType": "HARD"\ @@ -17141,7 +17146,7 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { ["create-require", "npm:1.1.1"],\ ["diff", "npm:4.0.2"],\ ["make-error", "npm:1.3.6"],\ - ["typescript", "patch:typescript@npm%3A3.9.10#~builtin::version=3.9.10&hash=3bd3d3"],\ + ["typescript", "patch:typescript@npm%3A3.9.10#~builtin::version=3.9.10&hash=f456af"],\ ["yn", "npm:3.1.1"]\ ],\ "packagePeers": [\ @@ -17315,10 +17320,10 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { }]\ ]],\ ["typescript", [\ - ["patch:typescript@npm%3A3.9.10#~builtin::version=3.9.10&hash=3bd3d3", {\ - "packageLocation": "./.yarn/cache/typescript-patch-7ad1c7f5d0-dc7141ab55.zip/node_modules/typescript/",\ + ["patch:typescript@npm%3A3.9.10#~builtin::version=3.9.10&hash=f456af", {\ + "packageLocation": "./.yarn/cache/typescript-patch-1236c99922-dc7141ab55.zip/node_modules/typescript/",\ "packageDependencies": [\ - ["typescript", "patch:typescript@npm%3A3.9.10#~builtin::version=3.9.10&hash=3bd3d3"]\ + ["typescript", "patch:typescript@npm%3A3.9.10#~builtin::version=3.9.10&hash=f456af"]\ ],\ "linkType": "HARD"\ }]\ @@ -18891,7 +18896,6 @@ const StringDecoder = require('string_decoder'); const url = require('url'); const os = require('os'); const nodeUtils = require('util'); -const assert = require('assert'); const stream = require('stream'); const zlib = require('zlib'); const events = require('events'); @@ -18921,7 +18925,6 @@ const path__default = /*#__PURE__*/_interopDefaultLegacy(path); const require$$0__default = /*#__PURE__*/_interopDefaultLegacy(require$$0); const StringDecoder__default = /*#__PURE__*/_interopDefaultLegacy(StringDecoder); const nodeUtils__namespace = /*#__PURE__*/_interopNamespace(nodeUtils); -const assert__default = /*#__PURE__*/_interopDefaultLegacy(assert); const zlib__default = /*#__PURE__*/_interopDefaultLegacy(zlib); const S_IFMT = 61440; @@ -19113,10 +19116,15 @@ function areStatsEqual(a, b) { return true; } +var PathType; +(function(PathType2) { + PathType2[PathType2["File"] = 0] = "File"; + PathType2[PathType2["Portable"] = 1] = "Portable"; + PathType2[PathType2["Native"] = 2] = "Native"; +})(PathType || (PathType = {})); const PortablePath = { root: `/`, - dot: `.`, - parent: `..` + dot: `.` }; const Filename = { nodeModules: `node_modules`, @@ -19186,16 +19194,40 @@ function convertPath(targetPathUtils, sourcePath) { return targetPathUtils === npath ? fromPortablePath(sourcePath) : toPortablePath(sourcePath); } +var __defProp$5 = Object.defineProperty; +var __defProps$3 = Object.defineProperties; +var __getOwnPropDescs$3 = Object.getOwnPropertyDescriptors; +var __getOwnPropSymbols$6 = Object.getOwnPropertySymbols; +var __hasOwnProp$6 = Object.prototype.hasOwnProperty; +var __propIsEnum$6 = Object.prototype.propertyIsEnumerable; +var __defNormalProp$5 = (obj, key, value) => key in obj ? __defProp$5(obj, key, {enumerable: true, configurable: true, writable: true, value}) : obj[key] = value; +var __spreadValues$5 = (a, b) => { + for (var prop in b || (b = {})) + if (__hasOwnProp$6.call(b, prop)) + __defNormalProp$5(a, prop, b[prop]); + if (__getOwnPropSymbols$6) + for (var prop of __getOwnPropSymbols$6(b)) { + if (__propIsEnum$6.call(b, prop)) + __defNormalProp$5(a, prop, b[prop]); + } + return a; +}; +var __spreadProps$3 = (a, b) => __defProps$3(a, __getOwnPropDescs$3(b)); const defaultTime = new Date(SAFE_TIME * 1e3); +var LinkStrategy; +(function(LinkStrategy2) { + LinkStrategy2["Allow"] = `allow`; + LinkStrategy2["ReadOnly"] = `readOnly`; +})(LinkStrategy || (LinkStrategy = {})); async function copyPromise(destinationFs, destination, sourceFs, source, opts) { const normalizedDestination = destinationFs.pathUtils.normalize(destination); const normalizedSource = sourceFs.pathUtils.normalize(source); const prelayout = []; const postlayout = []; - const { atime, mtime } = opts.stableTime ? { atime: defaultTime, mtime: defaultTime } : await sourceFs.lstatPromise(normalizedSource); - await destinationFs.mkdirpPromise(destinationFs.pathUtils.dirname(destination), { utimes: [atime, mtime] }); + const {atime, mtime} = opts.stableTime ? {atime: defaultTime, mtime: defaultTime} : await sourceFs.lstatPromise(normalizedSource); + await destinationFs.mkdirpPromise(destinationFs.pathUtils.dirname(destination), {utimes: [atime, mtime]}); const updateTime = typeof destinationFs.lutimesPromise === `function` ? destinationFs.lutimesPromise.bind(destinationFs) : destinationFs.utimesPromise.bind(destinationFs); - await copyImpl(prelayout, postlayout, updateTime, destinationFs, normalizedDestination, sourceFs, normalizedSource, { ...opts, didParentExist: true }); + await copyImpl(prelayout, postlayout, updateTime, destinationFs, normalizedDestination, sourceFs, normalizedSource, __spreadProps$3(__spreadValues$5({}, opts), {didParentExist: true})); for (const operation of prelayout) await operation(); await Promise.all(postlayout.map((operation) => { @@ -19206,7 +19238,7 @@ async function copyImpl(prelayout, postlayout, updateTime, destinationFs, destin var _a, _b; const destinationStat = opts.didParentExist ? await maybeLStat(destinationFs, destination) : null; const sourceStat = await sourceFs.lstatPromise(source); - const { atime, mtime } = opts.stableTime ? { atime: defaultTime, mtime: defaultTime } : sourceStat; + const {atime, mtime} = opts.stableTime ? {atime: defaultTime, mtime: defaultTime} : sourceStat; let updated; switch (true) { case sourceStat.isDirectory(): @@ -19259,7 +19291,7 @@ async function copyFolder(prelayout, postlayout, updateTime, destinationFs, dest if (destinationStat === null) { prelayout.push(async () => { try { - await destinationFs.mkdirPromise(destination, { mode: sourceStat.mode }); + await destinationFs.mkdirPromise(destination, {mode: sourceStat.mode}); } catch (err) { if (err.code !== `EEXIST`) { throw err; @@ -19269,7 +19301,7 @@ async function copyFolder(prelayout, postlayout, updateTime, destinationFs, dest updated = true; } const entries = await sourceFs.readdirPromise(source); - const nextOpts = opts.didParentExist && !destinationStat ? { ...opts, didParentExist: false } : opts; + const nextOpts = opts.didParentExist && !destinationStat ? __spreadProps$3(__spreadValues$5({}, opts), {didParentExist: false}) : opts; if (opts.stableSort) { for (const entry of entries.sort()) { if (await copyImpl(prelayout, postlayout, updateTime, destinationFs, destinationFs.pathUtils.join(destination, entry), sourceFs, sourceFs.pathUtils.join(source, entry), nextOpts)) { @@ -19286,11 +19318,11 @@ async function copyFolder(prelayout, postlayout, updateTime, destinationFs, dest } return updated; } -const isCloneSupportedCache = /* @__PURE__ */ new WeakMap(); +const isCloneSupportedCache = new WeakMap(); function makeLinkOperation(opFs, destination, source, sourceStat, linkStrategy) { return async () => { await opFs.linkPromise(source, destination); - if (linkStrategy === "readOnly" /* ReadOnly */) { + if (linkStrategy === LinkStrategy.ReadOnly) { sourceStat.mode &= ~146; await opFs.chmodPromise(destination, sourceStat.mode); } @@ -19351,7 +19383,7 @@ async function copySymlink(prelayout, postlayout, updateTime, destinationFs, des } function makeError$1(code, message) { - return Object.assign(new Error(`${code}: ${message}`), { code }); + return Object.assign(new Error(`${code}: ${message}`), {code}); } function EBUSY(message) { return makeError$1(`EBUSY`, message); @@ -19458,7 +19490,7 @@ class FakeFS { constructor(pathUtils) { this.pathUtils = pathUtils; } - async *genTraversePromise(init, { stableSort = false } = {}) { + async *genTraversePromise(init, {stableSort = false} = {}) { const stack = [init]; while (stack.length > 0) { const p = stack.shift(); @@ -19477,7 +19509,7 @@ class FakeFS { } } } - async removePromise(p, { recursive = true, maxRetries = 5 } = {}) { + async removePromise(p, {recursive = true, maxRetries = 5} = {}) { let stat; try { stat = await this.lstatPromise(p); @@ -19511,7 +19543,7 @@ class FakeFS { await this.unlinkPromise(p); } } - removeSync(p, { recursive = true } = {}) { + removeSync(p, {recursive = true} = {}) { let stat; try { stat = this.lstatSync(p); @@ -19531,7 +19563,7 @@ class FakeFS { this.unlinkSync(p); } } - async mkdirpPromise(p, { chmod, utimes } = {}) { + async mkdirpPromise(p, {chmod, utimes} = {}) { p = this.resolve(p); if (p === this.pathUtils.dirname(p)) return void 0; @@ -19562,7 +19594,7 @@ class FakeFS { } return createdDirectory; } - mkdirpSync(p, { chmod, utimes } = {}) { + mkdirpSync(p, {chmod, utimes} = {}) { p = this.resolve(p); if (p === this.pathUtils.dirname(p)) return void 0; @@ -19593,17 +19625,17 @@ class FakeFS { } return createdDirectory; } - async copyPromise(destination, source, { baseFs = this, overwrite = true, stableSort = false, stableTime = false, linkStrategy = null } = {}) { - return await copyPromise(this, destination, baseFs, source, { overwrite, stableSort, stableTime, linkStrategy }); + async copyPromise(destination, source, {baseFs = this, overwrite = true, stableSort = false, stableTime = false, linkStrategy = null} = {}) { + return await copyPromise(this, destination, baseFs, source, {overwrite, stableSort, stableTime, linkStrategy}); } - copySync(destination, source, { baseFs = this, overwrite = true } = {}) { + copySync(destination, source, {baseFs = this, overwrite = true} = {}) { const stat = baseFs.lstatSync(source); const exists = this.existsSync(destination); if (stat.isDirectory()) { this.mkdirpSync(destination); const directoryListing = baseFs.readdirSync(source); for (const entry of directoryListing) { - this.copySync(this.pathUtils.join(destination, entry), baseFs.pathUtils.join(source, entry), { baseFs, overwrite }); + this.copySync(this.pathUtils.join(destination, entry), baseFs.pathUtils.join(source, entry), {baseFs, overwrite}); } } else if (stat.isFile()) { if (!exists || overwrite) { @@ -19632,7 +19664,7 @@ class FakeFS { return this.changeFileTextPromise(p, content, opts); } } - async changeFileBufferPromise(p, content, { mode } = {}) { + async changeFileBufferPromise(p, content, {mode} = {}) { let current = Buffer.alloc(0); try { current = await this.readFilePromise(p); @@ -19640,9 +19672,9 @@ class FakeFS { } if (Buffer.compare(current, content) === 0) return; - await this.writeFilePromise(p, content, { mode }); + await this.writeFilePromise(p, content, {mode}); } - async changeFileTextPromise(p, content, { automaticNewlines, mode } = {}) { + async changeFileTextPromise(p, content, {automaticNewlines, mode} = {}) { let current = ``; try { current = await this.readFilePromise(p, `utf8`); @@ -19651,7 +19683,7 @@ class FakeFS { const normalizedContent = automaticNewlines ? normalizeLineEndings(current, content) : content; if (current === normalizedContent) return; - await this.writeFilePromise(p, normalizedContent, { mode }); + await this.writeFilePromise(p, normalizedContent, {mode}); } changeFileSync(p, content, opts = {}) { if (Buffer.isBuffer(content)) { @@ -19660,7 +19692,7 @@ class FakeFS { return this.changeFileTextSync(p, content, opts); } } - changeFileBufferSync(p, content, { mode } = {}) { + changeFileBufferSync(p, content, {mode} = {}) { let current = Buffer.alloc(0); try { current = this.readFileSync(p); @@ -19668,9 +19700,9 @@ class FakeFS { } if (Buffer.compare(current, content) === 0) return; - this.writeFileSync(p, content, { mode }); + this.writeFileSync(p, content, {mode}); } - changeFileTextSync(p, content, { automaticNewlines = false, mode } = {}) { + changeFileTextSync(p, content, {automaticNewlines = false, mode} = {}) { let current = ``; try { current = this.readFileSync(p, `utf8`); @@ -19679,7 +19711,7 @@ class FakeFS { const normalizedContent = automaticNewlines ? normalizeLineEndings(current, content) : content; if (current === normalizedContent) return; - this.writeFileSync(p, normalizedContent, { mode }); + this.writeFileSync(p, normalizedContent, {mode}); } async movePromise(fromP, toP) { try { @@ -19860,12 +19892,12 @@ class NodeFS extends BasePortableFakeFS { this.realFs.opendir(npath.fromPortablePath(p), this.makeCallback(resolve, reject)); } }).then((dir) => { - return Object.defineProperty(dir, `path`, { value: p, configurable: true, writable: true }); + return Object.defineProperty(dir, `path`, {value: p, configurable: true, writable: true}); }); } opendirSync(p, opts) { const dir = typeof opts !== `undefined` ? this.realFs.opendirSync(npath.fromPortablePath(p), opts) : this.realFs.opendirSync(npath.fromPortablePath(p)); - return Object.defineProperty(dir, `path`, { value: p, configurable: true, writable: true }); + return Object.defineProperty(dir, `path`, {value: p, configurable: true, writable: true}); } async readPromise(fd, buffer, offset = 0, length = 0, position = -1) { return await new Promise((resolve, reject) => { @@ -20003,14 +20035,6 @@ class NodeFS extends BasePortableFakeFS { chmodSync(p, mask) { return this.realFs.chmodSync(npath.fromPortablePath(p), mask); } - async fchownPromise(fd, uid, gid) { - return await new Promise((resolve, reject) => { - this.realFs.fchown(fd, uid, gid, this.makeCallback(resolve, reject)); - }); - } - fchownSync(fd, uid, gid) { - return this.realFs.fchownSync(fd, uid, gid); - } async chownPromise(p, uid, gid) { return await new Promise((resolve, reject) => { this.realFs.chown(npath.fromPortablePath(p), uid, gid, this.makeCallback(resolve, reject)); @@ -20150,7 +20174,7 @@ class NodeFS extends BasePortableFakeFS { async readdirPromise(p, opts) { return await new Promise((resolve, reject) => { if (opts == null ? void 0 : opts.withFileTypes) { - this.realFs.readdir(npath.fromPortablePath(p), { withFileTypes: true }, this.makeCallback(resolve, reject)); + this.realFs.readdir(npath.fromPortablePath(p), {withFileTypes: true}, this.makeCallback(resolve, reject)); } else { this.realFs.readdir(npath.fromPortablePath(p), this.makeCallback((value) => resolve(value), reject)); } @@ -20158,7 +20182,7 @@ class NodeFS extends BasePortableFakeFS { } readdirSync(p, opts) { if (opts == null ? void 0 : opts.withFileTypes) { - return this.realFs.readdirSync(npath.fromPortablePath(p), { withFileTypes: true }); + return this.realFs.readdirSync(npath.fromPortablePath(p), {withFileTypes: true}); } else { return this.realFs.readdirSync(npath.fromPortablePath(p)); } @@ -20190,18 +20214,10 @@ class NodeFS extends BasePortableFakeFS { return this.realFs.ftruncateSync(fd, len); } watch(p, a, b) { - return this.realFs.watch( - npath.fromPortablePath(p), - a, - b - ); + return this.realFs.watch(npath.fromPortablePath(p), a, b); } watchFile(p, a, b) { - return this.realFs.watchFile( - npath.fromPortablePath(p), - a, - b - ); + return this.realFs.watchFile(npath.fromPortablePath(p), a, b); } unwatchFile(p, cb) { return this.realFs.unwatchFile(npath.fromPortablePath(p), cb); @@ -20217,16 +20233,27 @@ class NodeFS extends BasePortableFakeFS { } } +var Event; +(function(Event2) { + Event2["Change"] = `change`; + Event2["Stop"] = `stop`; +})(Event || (Event = {})); +var Status; +(function(Status2) { + Status2["Ready"] = `ready`; + Status2["Running"] = `running`; + Status2["Stopped"] = `stopped`; +})(Status || (Status = {})); function assertStatus(current, expected) { if (current !== expected) { throw new Error(`Invalid StatWatcher status: expected '${expected}', got '${current}'`); } } class CustomStatWatcher extends events.EventEmitter { - constructor(fakeFs, path, { bigint = false } = {}) { + constructor(fakeFs, path, {bigint = false} = {}) { super(); - this.status = "ready" /* Ready */; - this.changeListeners = /* @__PURE__ */ new Map(); + this.status = Status.Ready; + this.changeListeners = new Map(); this.startTimeout = null; this.fakeFs = fakeFs; this.path = path; @@ -20239,27 +20266,27 @@ class CustomStatWatcher extends events.EventEmitter { return statWatcher; } start() { - assertStatus(this.status, "ready" /* Ready */); - this.status = "running" /* Running */; + assertStatus(this.status, Status.Ready); + this.status = Status.Running; this.startTimeout = setTimeout(() => { this.startTimeout = null; if (!this.fakeFs.existsSync(this.path)) { - this.emit("change" /* Change */, this.lastStats, this.lastStats); + this.emit(Event.Change, this.lastStats, this.lastStats); } }, 3); } stop() { - assertStatus(this.status, "running" /* Running */); - this.status = "stopped" /* Stopped */; + assertStatus(this.status, Status.Running); + this.status = Status.Stopped; if (this.startTimeout !== null) { clearTimeout(this.startTimeout); this.startTimeout = null; } - this.emit("stop" /* Stop */); + this.emit(Event.Stop); } stat() { try { - return this.fakeFs.statSync(this.path, { bigint: this.bigint }); + return this.fakeFs.statSync(this.path, {bigint: this.bigint}); } catch (error) { const statInstance = this.bigint ? new BigIntStatsEntry() : new StatEntry(); return clearStats(statInstance); @@ -20272,16 +20299,16 @@ class CustomStatWatcher extends events.EventEmitter { if (areStatsEqual(currentStats, previousStats)) return; this.lastStats = currentStats; - this.emit("change" /* Change */, currentStats, previousStats); + this.emit(Event.Change, currentStats, previousStats); }, opts.interval); return opts.persistent ? interval : interval.unref(); } registerChangeListener(listener, opts) { - this.addListener("change" /* Change */, listener); + this.addListener(Event.Change, listener); this.changeListeners.set(listener, this.makeInterval(opts)); } unregisterChangeListener(listener) { - this.removeListener("change" /* Change */, listener); + this.removeListener(Event.Change, listener); const interval = this.changeListeners.get(listener); if (typeof interval !== `undefined`) clearInterval(interval); @@ -20307,7 +20334,7 @@ class CustomStatWatcher extends events.EventEmitter { } } -const statWatchersByFakeFS = /* @__PURE__ */ new WeakMap(); +const statWatchersByFakeFS = new WeakMap(); function watchFile(fakeFs, path, a, b) { let bigint; let persistent; @@ -20335,13 +20362,13 @@ function watchFile(fakeFs, path, a, b) { } let statWatchers = statWatchersByFakeFS.get(fakeFs); if (typeof statWatchers === `undefined`) - statWatchersByFakeFS.set(fakeFs, statWatchers = /* @__PURE__ */ new Map()); + statWatchersByFakeFS.set(fakeFs, statWatchers = new Map()); let statWatcher = statWatchers.get(path); if (typeof statWatcher === `undefined`) { - statWatcher = CustomStatWatcher.create(fakeFs, path, { bigint }); + statWatcher = CustomStatWatcher.create(fakeFs, path, {bigint}); statWatchers.set(path, statWatcher); } - statWatcher.registerChangeListener(listener, { persistent, interval }); + statWatcher.registerChangeListener(listener, {persistent, interval}); return statWatcher; } function unwatchFile(fakeFs, path, cb) { @@ -20369,6 +20396,22 @@ function unwatchAllFiles(fakeFs) { } } +var __defProp$4 = Object.defineProperty; +var __getOwnPropSymbols$5 = Object.getOwnPropertySymbols; +var __hasOwnProp$5 = Object.prototype.hasOwnProperty; +var __propIsEnum$5 = Object.prototype.propertyIsEnumerable; +var __defNormalProp$4 = (obj, key, value) => key in obj ? __defProp$4(obj, key, {enumerable: true, configurable: true, writable: true, value}) : obj[key] = value; +var __spreadValues$4 = (a, b) => { + for (var prop in b || (b = {})) + if (__hasOwnProp$5.call(b, prop)) + __defNormalProp$4(a, prop, b[prop]); + if (__getOwnPropSymbols$5) + for (var prop of __getOwnPropSymbols$5(b)) { + if (__propIsEnum$5.call(b, prop)) + __defNormalProp$4(a, prop, b[prop]); + } + return a; +}; const DEFAULT_COMPRESSION_LEVEL = `mixed`; function toUnixTimestamp(time) { if (typeof time === `string` && String(+time) === time) @@ -20414,10 +20457,10 @@ class ZipFS extends BasePortableFakeFS { constructor(source, opts) { super(); this.lzSource = null; - this.listings = /* @__PURE__ */ new Map(); - this.entries = /* @__PURE__ */ new Map(); - this.fileSources = /* @__PURE__ */ new Map(); - this.fds = /* @__PURE__ */ new Map(); + this.listings = new Map(); + this.entries = new Map(); + this.fileSources = new Map(); + this.fds = new Map(); this.nextFd = 0; this.ready = false; this.readOnly = false; @@ -20426,7 +20469,7 @@ class ZipFS extends BasePortableFakeFS { this.level = typeof pathOptions.level !== `undefined` ? pathOptions.level : DEFAULT_COMPRESSION_LEVEL; source != null ? source : source = makeEmptyArchive(); if (typeof source === `string`) { - const { baseFs = new NodeFS() } = pathOptions; + const {baseFs = new NodeFS()} = pathOptions; this.baseFs = baseFs; this.path = source; } else { @@ -20479,7 +20522,7 @@ class ZipFS extends BasePortableFakeFS { } finally { this.libzip.free(errPtr); } - this.listings.set(PortablePath.root, /* @__PURE__ */ new Set()); + this.listings.set(PortablePath.root, new Set()); const entryCount = this.libzip.getNumEntries(this.zip, 0); for (let t = 0; t < entryCount; ++t) { const raw = this.libzip.getName(this.zip, t, 0); @@ -20576,7 +20619,7 @@ class ZipFS extends BasePortableFakeFS { const newMode = this.baseFs.existsSync(this.path) || this.stats.mode === DEFAULT_MODE ? void 0 : this.stats.mode; if (this.entries.size === 0) { this.discardAndClose(); - this.baseFs.writeFileSync(this.path, makeEmptyArchive(), { mode: newMode }); + this.baseFs.writeFileSync(this.path, makeEmptyArchive(), {mode: newMode}); } else { const rc = this.libzip.close(this.zip); if (rc === -1) @@ -20600,7 +20643,7 @@ class ZipFS extends BasePortableFakeFS { } openSync(p, flags, mode) { const fd = this.nextFd++; - this.fds.set(fd, { cursor: 0, p }); + this.fds.set(fd, {cursor: 0, p}); return fd; } hasOpenFileHandles() { @@ -20621,7 +20664,7 @@ class ZipFS extends BasePortableFakeFS { const onClose = () => { this.closeSync(fd); }; - return opendir(this, resolvedP, entries, { onClose }); + return opendir(this, resolvedP, entries, {onClose}); } async readPromise(fd, buffer, offset, length, position) { return this.readSync(fd, buffer, offset, length, position); @@ -20660,28 +20703,25 @@ class ZipFS extends BasePortableFakeFS { throw EBADF(`read`); this.fds.delete(fd); } - createReadStream(p, { encoding } = {}) { + createReadStream(p, {encoding} = {}) { if (p === null) throw new Error(`Unimplemented`); const fd = this.openSync(p, `r`); - const stream$1 = Object.assign( - new stream.PassThrough({ - emitClose: true, - autoDestroy: true, - destroy: (error, callback) => { - clearImmediate(immediate); - this.closeSync(fd); - callback(error); - } - }), - { - close() { - stream$1.destroy(); - }, - bytesRead: 0, - path: p + const stream$1 = Object.assign(new stream.PassThrough({ + emitClose: true, + autoDestroy: true, + destroy: (error, callback) => { + clearImmediate(immediate); + this.closeSync(fd); + callback(error); } - ); + }), { + close() { + stream$1.destroy(); + }, + bytesRead: 0, + path: p + }); const immediate = setImmediate(async () => { try { const data = await this.readFilePromise(p, encoding); @@ -20693,40 +20733,37 @@ class ZipFS extends BasePortableFakeFS { }); return stream$1; } - createWriteStream(p, { encoding } = {}) { + createWriteStream(p, {encoding} = {}) { if (this.readOnly) throw EROFS(`open '${p}'`); if (p === null) throw new Error(`Unimplemented`); const chunks = []; const fd = this.openSync(p, `w`); - const stream$1 = Object.assign( - new stream.PassThrough({ - autoDestroy: true, - emitClose: true, - destroy: (error, callback) => { - try { - if (error) { - callback(error); - } else { - this.writeFileSync(p, Buffer.concat(chunks), encoding); - callback(null); - } - } catch (err) { - callback(err); - } finally { - this.closeSync(fd); + const stream$1 = Object.assign(new stream.PassThrough({ + autoDestroy: true, + emitClose: true, + destroy: (error, callback) => { + try { + if (error) { + callback(error); + } else { + this.writeFileSync(p, Buffer.concat(chunks), encoding); + callback(null); } + } catch (err) { + callback(err); + } finally { + this.closeSync(fd); } - }), - { - bytesWritten: 0, - path: p, - close() { - stream$1.destroy(); - } } - ); + }), { + bytesWritten: 0, + path: p, + close() { + stream$1.destroy(); + } + }); stream$1.on(`data`, (chunk) => { const chunkBuffer = Buffer.from(chunk); stream$1.bytesWritten += chunkBuffer.length; @@ -20774,12 +20811,12 @@ class ZipFS extends BasePortableFakeFS { throw EROFS(`access '${p}'`); } } - async statPromise(p, opts = { bigint: false }) { + async statPromise(p, opts = {bigint: false}) { if (opts.bigint) - return this.statSync(p, { bigint: true }); + return this.statSync(p, {bigint: true}); return this.statSync(p); } - statSync(p, opts = { bigint: false, throwIfNoEntry: true }) { + statSync(p, opts = {bigint: false, throwIfNoEntry: true}) { const resolvedP = this.resolveFilename(`stat '${p}'`, p, void 0, opts.throwIfNoEntry); if (resolvedP === void 0) return void 0; @@ -20799,7 +20836,7 @@ class ZipFS extends BasePortableFakeFS { const entry = this.fds.get(fd); if (typeof entry === `undefined`) throw EBADF(`fstatSync`); - const { p } = entry; + const {p} = entry; const resolvedP = this.resolveFilename(`stat '${p}'`, p); if (!this.entries.has(resolvedP) && !this.listings.has(resolvedP)) throw ENOENT(`stat '${p}'`); @@ -20807,12 +20844,12 @@ class ZipFS extends BasePortableFakeFS { throw ENOTDIR(`stat '${p}'`); return this.statImpl(`fstat '${p}'`, resolvedP, opts); } - async lstatPromise(p, opts = { bigint: false }) { + async lstatPromise(p, opts = {bigint: false}) { if (opts.bigint) - return this.lstatSync(p, { bigint: true }); + return this.lstatSync(p, {bigint: true}); return this.lstatSync(p); } - lstatSync(p, opts = { bigint: false, throwIfNoEntry: true }) { + lstatSync(p, opts = {bigint: false, throwIfNoEntry: true}) { const resolvedP = this.resolveFilename(`lstat '${p}'`, p, false, opts.throwIfNoEntry); if (resolvedP === void 0) return void 0; @@ -20849,7 +20886,7 @@ class ZipFS extends BasePortableFakeFS { const defaultMode = type === S_IFDIR ? 493 : 420; const mode = type | this.getUnixMode(entry, defaultMode) & 511; const crc = this.libzip.struct.statCrc(stat); - const statInstance = Object.assign(new StatEntry(), { uid, gid, size, blksize, blocks, atime, birthtime, ctime, mtime, atimeMs, birthtimeMs, ctimeMs, mtimeMs, mode, crc }); + const statInstance = Object.assign(new StatEntry(), {uid, gid, size, blksize, blocks, atime, birthtime, ctime, mtime, atimeMs, birthtimeMs, ctimeMs, mtimeMs, mode, crc}); return opts.bigint === true ? convertToBigIntStats(statInstance) : statInstance; } if (this.listings.has(p)) { @@ -20868,7 +20905,7 @@ class ZipFS extends BasePortableFakeFS { const mtime = new Date(mtimeMs); const mode = S_IFDIR | 493; const crc = 0; - const statInstance = Object.assign(new StatEntry(), { uid, gid, size, blksize, blocks, atime, birthtime, ctime, mtime, atimeMs, birthtimeMs, ctimeMs, mtimeMs, mode, crc }); + const statInstance = Object.assign(new StatEntry(), {uid, gid, size, blksize, blocks, atime, birthtime, ctime, mtime, atimeMs, birthtimeMs, ctimeMs, mtimeMs, mode, crc}); return opts.bigint === true ? convertToBigIntStats(statInstance) : statInstance; } throw new Error(`Unreachable`); @@ -20888,7 +20925,7 @@ class ZipFS extends BasePortableFakeFS { return existingListing; const parentListing = this.registerListing(ppath.dirname(p)); parentListing.add(ppath.basename(p)); - const newListing = /* @__PURE__ */ new Set(); + const newListing = new Set(); this.listings.set(p, newListing); return newListing; } @@ -20971,11 +21008,11 @@ class ZipFS extends BasePortableFakeFS { throw new Error(`Couldn't allocate enough memory`); const heap = new Uint8Array(this.libzip.HEAPU8.buffer, buffer, content.byteLength); heap.set(content); - return { buffer, byteLength: content.byteLength }; + return {buffer, byteLength: content.byteLength}; } allocateUnattachedSource(content) { const error = this.libzip.struct.errorS(); - const { buffer, byteLength } = this.allocateBuffer(content); + const {buffer, byteLength} = this.allocateBuffer(content); const source = this.libzip.source.fromUnattachedBuffer(buffer, byteLength, 0, true, error); if (source === 0) { this.libzip.free(error); @@ -20984,7 +21021,7 @@ class ZipFS extends BasePortableFakeFS { return source; } allocateSource(content) { - const { buffer, byteLength } = this.allocateBuffer(content); + const {buffer, byteLength} = this.allocateBuffer(content); const source = this.libzip.source.fromBuffer(this.zip, buffer, byteLength, 0, true); if (source === 0) { this.libzip.free(buffer); @@ -21026,7 +21063,7 @@ class ZipFS extends BasePortableFakeFS { const attributes = this.libzip.getValue(this.libzip.uint32S, `i32`) >>> 16; return (attributes & S_IFMT) === S_IFLNK; } - getFileSource(index, opts = { asyncDecompress: false }) { + getFileSource(index, opts = {asyncDecompress: false}) { const cachedFileSource = this.fileSources.get(index); if (typeof cachedFileSource !== `undefined`) return cachedFileSource; @@ -21101,12 +21138,6 @@ class ZipFS extends BasePortableFakeFS { throw this.makeLibzipError(this.libzip.getError(this.zip)); } } - async fchownPromise(fd, uid, gid) { - return this.chownPromise(this.fdToPath(fd, `fchown`), uid, gid); - } - fchownSync(fd, uid, gid) { - return this.chownSync(this.fdToPath(fd, `fchownSync`), uid, gid); - } async chownPromise(p, uid, gid) { return this.chownSync(p, uid, gid); } @@ -21120,15 +21151,15 @@ class ZipFS extends BasePortableFakeFS { throw new Error(`Unimplemented`); } async copyFilePromise(sourceP, destP, flags) { - const { indexSource, indexDest, resolvedDestP } = this.prepareCopyFile(sourceP, destP, flags); - const source = await this.getFileSource(indexSource, { asyncDecompress: true }); + const {indexSource, indexDest, resolvedDestP} = this.prepareCopyFile(sourceP, destP, flags); + const source = await this.getFileSource(indexSource, {asyncDecompress: true}); const newIndex = this.setFileSource(resolvedDestP, source); if (newIndex !== indexDest) { this.registerEntry(resolvedDestP, newIndex); } } copyFileSync(sourceP, destP, flags = 0) { - const { indexSource, indexDest, resolvedDestP } = this.prepareCopyFile(sourceP, destP, flags); + const {indexSource, indexDest, resolvedDestP} = this.prepareCopyFile(sourceP, destP, flags); const source = this.getFileSource(indexSource); const newIndex = this.setFileSource(resolvedDestP, source); if (newIndex !== indexDest) { @@ -21158,22 +21189,22 @@ class ZipFS extends BasePortableFakeFS { if (this.readOnly) throw EROFS(`open '${p}'`); if (typeof opts === `undefined`) - opts = { flag: `a` }; + opts = {flag: `a`}; else if (typeof opts === `string`) - opts = { flag: `a`, encoding: opts }; + opts = {flag: `a`, encoding: opts}; else if (typeof opts.flag === `undefined`) - opts = { flag: `a`, ...opts }; + opts = __spreadValues$4({flag: `a`}, opts); return this.writeFilePromise(p, content, opts); } appendFileSync(p, content, opts = {}) { if (this.readOnly) throw EROFS(`open '${p}'`); if (typeof opts === `undefined`) - opts = { flag: `a` }; + opts = {flag: `a`}; else if (typeof opts === `string`) - opts = { flag: `a`, encoding: opts }; + opts = {flag: `a`, encoding: opts}; else if (typeof opts.flag === `undefined`) - opts = { flag: `a`, ...opts }; + opts = __spreadValues$4({flag: `a`}, opts); return this.writeFileSync(p, content, opts); } fdToPath(fd, reason) { @@ -21184,9 +21215,9 @@ class ZipFS extends BasePortableFakeFS { return path; } async writeFilePromise(p, content, opts) { - const { encoding, mode, index, resolvedP } = this.prepareWriteFile(p, opts); + const {encoding, mode, index, resolvedP} = this.prepareWriteFile(p, opts); if (index !== void 0 && typeof opts === `object` && opts.flag && opts.flag.includes(`a`)) - content = Buffer.concat([await this.getFileSource(index, { asyncDecompress: true }), Buffer.from(content)]); + content = Buffer.concat([await this.getFileSource(index, {asyncDecompress: true}), Buffer.from(content)]); if (encoding !== null) content = content.toString(encoding); const newIndex = this.setFileSource(resolvedP, content); @@ -21197,7 +21228,7 @@ class ZipFS extends BasePortableFakeFS { } } writeFileSync(p, content, opts) { - const { encoding, mode, index, resolvedP } = this.prepareWriteFile(p, opts); + const {encoding, mode, index, resolvedP} = this.prepareWriteFile(p, opts); if (index !== void 0 && typeof opts === `object` && opts.flag && opts.flag.includes(`a`)) content = Buffer.concat([this.getFileSource(index), Buffer.from(content)]); if (encoding !== null) @@ -21282,9 +21313,9 @@ class ZipFS extends BasePortableFakeFS { async mkdirPromise(p, opts) { return this.mkdirSync(p, opts); } - mkdirSync(p, { mode = 493, recursive = false } = {}) { + mkdirSync(p, {mode = 493, recursive = false} = {}) { if (recursive) - return this.mkdirpSync(p, { chmod: mode }); + return this.mkdirpSync(p, {chmod: mode}); if (this.readOnly) throw EROFS(`mkdir '${p}'`); const resolvedP = this.resolveFilename(`mkdir '${p}'`, p); @@ -21297,7 +21328,7 @@ class ZipFS extends BasePortableFakeFS { async rmdirPromise(p, opts) { return this.rmdirSync(p, opts); } - rmdirSync(p, { recursive = false } = {}) { + rmdirSync(p, {recursive = false} = {}) { if (this.readOnly) throw EROFS(`rmdir '${p}'`); if (recursive) { @@ -21350,7 +21381,7 @@ class ZipFS extends BasePortableFakeFS { async readFilePromise(p, encoding) { if (typeof encoding === `object`) encoding = encoding ? encoding.encoding : void 0; - const data = await this.readFileBuffer(p, { asyncDecompress: true }); + const data = await this.readFileBuffer(p, {asyncDecompress: true}); return encoding ? data.toString(encoding) : data; } readFileSync(p, encoding) { @@ -21359,7 +21390,7 @@ class ZipFS extends BasePortableFakeFS { const data = this.readFileBuffer(p); return encoding ? data.toString(encoding) : data; } - readFileBuffer(p, opts = { asyncDecompress: false }) { + readFileBuffer(p, opts = {asyncDecompress: false}) { if (typeof p === `number`) p = this.fdToPath(p, `read`); const resolvedP = this.resolveFilename(`open '${p}'`, p); @@ -21395,7 +21426,7 @@ class ZipFS extends BasePortableFakeFS { } async readlinkPromise(p) { const entry = this.prepareReadlink(p); - return (await this.getFileSource(entry, { asyncDecompress: true })).toString(); + return (await this.getFileSource(entry, {asyncDecompress: true})).toString(); } readlinkSync(p) { const entry = this.prepareReadlink(p); @@ -21421,7 +21452,7 @@ class ZipFS extends BasePortableFakeFS { const index = this.entries.get(resolvedP); if (typeof index === `undefined`) throw EINVAL(`open '${p}'`); - const source = await this.getFileSource(index, { asyncDecompress: true }); + const source = await this.getFileSource(index, {asyncDecompress: true}); const truncated = Buffer.alloc(len, 0); source.copy(truncated); return await this.writeFilePromise(p, truncated); @@ -21454,20 +21485,20 @@ class ZipFS extends BasePortableFakeFS { break; default: { - ({ persistent = true } = a); + ({persistent = true} = a); } break; } if (!persistent) - return { on: () => { + return {on: () => { }, close: () => { - } }; + }}; const interval = setInterval(() => { }, 24 * 60 * 60 * 1e3); - return { on: () => { + return {on: () => { }, close: () => { clearInterval(interval); - } }; + }}; } watchFile(p, a, b) { const resolvedP = ppath.resolve(PortablePath.root, p); @@ -21496,10 +21527,10 @@ class ProxiedFS extends FakeFS { return this.baseFs.openSync(this.mapToBase(p), flags, mode); } async opendirPromise(p, opts) { - return Object.assign(await this.baseFs.opendirPromise(this.mapToBase(p), opts), { path: p }); + return Object.assign(await this.baseFs.opendirPromise(this.mapToBase(p), opts), {path: p}); } opendirSync(p, opts) { - return Object.assign(this.baseFs.opendirSync(this.mapToBase(p), opts), { path: p }); + return Object.assign(this.baseFs.opendirSync(this.mapToBase(p), opts), {path: p}); } async readPromise(fd, buffer, offset, length, position) { return await this.baseFs.readPromise(fd, buffer, offset, length, position); @@ -21581,12 +21612,6 @@ class ProxiedFS extends FakeFS { chmodSync(p, mask) { return this.baseFs.chmodSync(this.mapToBase(p), mask); } - async fchownPromise(fd, uid, gid) { - return this.baseFs.fchownPromise(fd, uid, gid); - } - fchownSync(fd, uid, gid) { - return this.baseFs.fchownSync(fd, uid, gid); - } async chownPromise(p, uid, gid) { return this.baseFs.chownPromise(this.mapToBase(p), uid, gid); } @@ -21702,18 +21727,10 @@ class ProxiedFS extends FakeFS { return this.baseFs.ftruncateSync(fd, len); } watch(p, a, b) { - return this.baseFs.watch( - this.mapToBase(p), - a, - b - ); + return this.baseFs.watch(this.mapToBase(p), a, b); } watchFile(p, a, b) { - return this.baseFs.watchFile( - this.mapToBase(p), - a, - b - ); + return this.baseFs.watchFile(this.mapToBase(p), a, b); } unwatchFile(p, cb) { return this.baseFs.unwatchFile(this.mapToBase(p), cb); @@ -21744,10 +21761,6 @@ const NUMBER_REGEXP = /^[0-9]+$/; const VIRTUAL_REGEXP = /^(\/(?:[^/]+\/)*?(?:\$\$virtual|__virtual__))((?:\/((?:[^/]+-)?[a-f0-9]+)(?:\/([^/]+))?)?((?:\/.*)?))$/; const VALID_COMPONENT = /^([^/]+-)?[a-f0-9]+$/; class VirtualFS extends ProxiedFS { - constructor({ baseFs = new NodeFS() } = {}) { - super(ppath); - this.baseFs = baseFs; - } static makeVirtualPath(base, component, to) { if (ppath.basename(base) !== `__virtual__`) throw new Error(`Assertion failed: Virtual folders must be named "__virtual__"`); @@ -21777,6 +21790,10 @@ class VirtualFS extends ProxiedFS { const subpath = match[5] || `.`; return VirtualFS.resolveVirtual(ppath.join(target, backstep, subpath)); } + constructor({baseFs = new NodeFS()} = {}) { + super(ppath); + this.baseFs = baseFs; + } getExtractHint(hints) { return this.baseFs.getExtractHint(hints); } @@ -21815,8 +21832,7 @@ class VirtualFS extends ProxiedFS { } } -const ZIP_MASK = 4278190080; -const ZIP_MAGIC = 704643072; +const ZIP_FD = 2147483648; const getArchivePart = (path, extension) => { let idx = path.indexOf(extension); if (idx <= 0) @@ -21835,17 +21851,17 @@ const getArchivePart = (path, extension) => { return path.slice(0, nextCharIdx); }; class ZipOpenFS extends BasePortableFakeFS { - constructor({ libzip, baseFs = new NodeFS(), filter = null, maxOpenFiles = Infinity, readOnlyArchives = false, useCache = true, maxAge = 5e3, fileExtensions = null }) { + constructor({libzip, baseFs = new NodeFS(), filter = null, maxOpenFiles = Infinity, readOnlyArchives = false, useCache = true, maxAge = 5e3, fileExtensions = null}) { super(); - this.fdMap = /* @__PURE__ */ new Map(); + this.fdMap = new Map(); this.nextFd = 3; - this.isZip = /* @__PURE__ */ new Set(); - this.notZip = /* @__PURE__ */ new Set(); - this.realPaths = /* @__PURE__ */ new Map(); + this.isZip = new Set(); + this.notZip = new Set(); + this.realPaths = new Map(); this.limitOpenFilesTimeout = null; this.libzipFactory = typeof libzip !== `function` ? () => libzip : libzip; this.baseFs = baseFs; - this.zipInstances = useCache ? /* @__PURE__ */ new Map() : null; + this.zipInstances = useCache ? new Map() : null; this.filter = filter; this.maxOpenFiles = maxOpenFiles; this.readOnlyArchives = readOnlyArchives; @@ -21874,7 +21890,7 @@ class ZipOpenFS extends BasePortableFakeFS { saveAndClose() { unwatchAllFiles(this); if (this.zipInstances) { - for (const [path, { zipFs }] of this.zipInstances.entries()) { + for (const [path, {zipFs}] of this.zipInstances.entries()) { zipFs.saveAndClose(); this.zipInstances.delete(path); } @@ -21883,7 +21899,7 @@ class ZipOpenFS extends BasePortableFakeFS { discardAndClose() { unwatchAllFiles(this); if (this.zipInstances) { - for (const [path, { zipFs }] of this.zipInstances.entries()) { + for (const [path, {zipFs}] of this.zipInstances.entries()) { zipFs.discardAndClose(); this.zipInstances.delete(path); } @@ -21893,28 +21909,28 @@ class ZipOpenFS extends BasePortableFakeFS { return this.baseFs.resolve(p); } remapFd(zipFs, fd) { - const remappedFd = this.nextFd++ | ZIP_MAGIC; + const remappedFd = this.nextFd++ | ZIP_FD; this.fdMap.set(remappedFd, [zipFs, fd]); return remappedFd; } async openPromise(p, flags, mode) { return await this.makeCallPromise(p, async () => { return await this.baseFs.openPromise(p, flags, mode); - }, async (zipFs, { subPath }) => { + }, async (zipFs, {subPath}) => { return this.remapFd(zipFs, await zipFs.openPromise(subPath, flags, mode)); }); } openSync(p, flags, mode) { return this.makeCallSync(p, () => { return this.baseFs.openSync(p, flags, mode); - }, (zipFs, { subPath }) => { + }, (zipFs, {subPath}) => { return this.remapFd(zipFs, zipFs.openSync(subPath, flags, mode)); }); } async opendirPromise(p, opts) { return await this.makeCallPromise(p, async () => { return await this.baseFs.opendirPromise(p, opts); - }, async (zipFs, { subPath }) => { + }, async (zipFs, {subPath}) => { return await zipFs.opendirPromise(subPath, opts); }, { requireSubpath: false @@ -21923,14 +21939,14 @@ class ZipOpenFS extends BasePortableFakeFS { opendirSync(p, opts) { return this.makeCallSync(p, () => { return this.baseFs.opendirSync(p, opts); - }, (zipFs, { subPath }) => { + }, (zipFs, {subPath}) => { return zipFs.opendirSync(subPath, opts); }, { requireSubpath: false }); } async readPromise(fd, buffer, offset, length, position) { - if ((fd & ZIP_MASK) !== ZIP_MAGIC) + if ((fd & ZIP_FD) === 0) return await this.baseFs.readPromise(fd, buffer, offset, length, position); const entry = this.fdMap.get(fd); if (typeof entry === `undefined`) @@ -21939,7 +21955,7 @@ class ZipOpenFS extends BasePortableFakeFS { return await zipFs.readPromise(realFd, buffer, offset, length, position); } readSync(fd, buffer, offset, length, position) { - if ((fd & ZIP_MASK) !== ZIP_MAGIC) + if ((fd & ZIP_FD) === 0) return this.baseFs.readSync(fd, buffer, offset, length, position); const entry = this.fdMap.get(fd); if (typeof entry === `undefined`) @@ -21948,7 +21964,7 @@ class ZipOpenFS extends BasePortableFakeFS { return zipFs.readSync(realFd, buffer, offset, length, position); } async writePromise(fd, buffer, offset, length, position) { - if ((fd & ZIP_MASK) !== ZIP_MAGIC) { + if ((fd & ZIP_FD) === 0) { if (typeof buffer === `string`) { return await this.baseFs.writePromise(fd, buffer, offset); } else { @@ -21966,7 +21982,7 @@ class ZipOpenFS extends BasePortableFakeFS { } } writeSync(fd, buffer, offset, length, position) { - if ((fd & ZIP_MASK) !== ZIP_MAGIC) { + if ((fd & ZIP_FD) === 0) { if (typeof buffer === `string`) { return this.baseFs.writeSync(fd, buffer, offset); } else { @@ -21984,7 +22000,7 @@ class ZipOpenFS extends BasePortableFakeFS { } } async closePromise(fd) { - if ((fd & ZIP_MASK) !== ZIP_MAGIC) + if ((fd & ZIP_FD) === 0) return await this.baseFs.closePromise(fd); const entry = this.fdMap.get(fd); if (typeof entry === `undefined`) @@ -21994,7 +22010,7 @@ class ZipOpenFS extends BasePortableFakeFS { return await zipFs.closePromise(realFd); } closeSync(fd) { - if ((fd & ZIP_MASK) !== ZIP_MAGIC) + if ((fd & ZIP_FD) === 0) return this.baseFs.closeSync(fd); const entry = this.fdMap.get(fd); if (typeof entry === `undefined`) @@ -22008,7 +22024,7 @@ class ZipOpenFS extends BasePortableFakeFS { return this.baseFs.createReadStream(p, opts); return this.makeCallSync(p, () => { return this.baseFs.createReadStream(p, opts); - }, (zipFs, { archivePath, subPath }) => { + }, (zipFs, {archivePath, subPath}) => { const stream = zipFs.createReadStream(subPath, opts); stream.path = npath.fromPortablePath(this.pathUtils.join(archivePath, subPath)); return stream; @@ -22019,14 +22035,14 @@ class ZipOpenFS extends BasePortableFakeFS { return this.baseFs.createWriteStream(p, opts); return this.makeCallSync(p, () => { return this.baseFs.createWriteStream(p, opts); - }, (zipFs, { subPath }) => { + }, (zipFs, {subPath}) => { return zipFs.createWriteStream(subPath, opts); }); } async realpathPromise(p) { return await this.makeCallPromise(p, async () => { return await this.baseFs.realpathPromise(p); - }, async (zipFs, { archivePath, subPath }) => { + }, async (zipFs, {archivePath, subPath}) => { let realArchivePath = this.realPaths.get(archivePath); if (typeof realArchivePath === `undefined`) { realArchivePath = await this.baseFs.realpathPromise(archivePath); @@ -22038,7 +22054,7 @@ class ZipOpenFS extends BasePortableFakeFS { realpathSync(p) { return this.makeCallSync(p, () => { return this.baseFs.realpathSync(p); - }, (zipFs, { archivePath, subPath }) => { + }, (zipFs, {archivePath, subPath}) => { let realArchivePath = this.realPaths.get(archivePath); if (typeof realArchivePath === `undefined`) { realArchivePath = this.baseFs.realpathSync(archivePath); @@ -22050,47 +22066,47 @@ class ZipOpenFS extends BasePortableFakeFS { async existsPromise(p) { return await this.makeCallPromise(p, async () => { return await this.baseFs.existsPromise(p); - }, async (zipFs, { subPath }) => { + }, async (zipFs, {subPath}) => { return await zipFs.existsPromise(subPath); }); } existsSync(p) { return this.makeCallSync(p, () => { return this.baseFs.existsSync(p); - }, (zipFs, { subPath }) => { + }, (zipFs, {subPath}) => { return zipFs.existsSync(subPath); }); } async accessPromise(p, mode) { return await this.makeCallPromise(p, async () => { return await this.baseFs.accessPromise(p, mode); - }, async (zipFs, { subPath }) => { + }, async (zipFs, {subPath}) => { return await zipFs.accessPromise(subPath, mode); }); } accessSync(p, mode) { return this.makeCallSync(p, () => { return this.baseFs.accessSync(p, mode); - }, (zipFs, { subPath }) => { + }, (zipFs, {subPath}) => { return zipFs.accessSync(subPath, mode); }); } async statPromise(p, opts) { return await this.makeCallPromise(p, async () => { return await this.baseFs.statPromise(p, opts); - }, async (zipFs, { subPath }) => { + }, async (zipFs, {subPath}) => { return await zipFs.statPromise(subPath, opts); }); } statSync(p, opts) { return this.makeCallSync(p, () => { return this.baseFs.statSync(p, opts); - }, (zipFs, { subPath }) => { + }, (zipFs, {subPath}) => { return zipFs.statSync(subPath, opts); }); } async fstatPromise(fd, opts) { - if ((fd & ZIP_MASK) !== ZIP_MAGIC) + if ((fd & ZIP_FD) === 0) return this.baseFs.fstatPromise(fd, opts); const entry = this.fdMap.get(fd); if (typeof entry === `undefined`) @@ -22099,7 +22115,7 @@ class ZipOpenFS extends BasePortableFakeFS { return zipFs.fstatPromise(realFd, opts); } fstatSync(fd, opts) { - if ((fd & ZIP_MASK) !== ZIP_MAGIC) + if ((fd & ZIP_FD) === 0) return this.baseFs.fstatSync(fd, opts); const entry = this.fdMap.get(fd); if (typeof entry === `undefined`) @@ -22110,19 +22126,19 @@ class ZipOpenFS extends BasePortableFakeFS { async lstatPromise(p, opts) { return await this.makeCallPromise(p, async () => { return await this.baseFs.lstatPromise(p, opts); - }, async (zipFs, { subPath }) => { + }, async (zipFs, {subPath}) => { return await zipFs.lstatPromise(subPath, opts); }); } lstatSync(p, opts) { return this.makeCallSync(p, () => { return this.baseFs.lstatSync(p, opts); - }, (zipFs, { subPath }) => { + }, (zipFs, {subPath}) => { return zipFs.lstatSync(subPath, opts); }); } async fchmodPromise(fd, mask) { - if ((fd & ZIP_MASK) !== ZIP_MAGIC) + if ((fd & ZIP_FD) === 0) return this.baseFs.fchmodPromise(fd, mask); const entry = this.fdMap.get(fd); if (typeof entry === `undefined`) @@ -22131,7 +22147,7 @@ class ZipOpenFS extends BasePortableFakeFS { return zipFs.fchmodPromise(realFd, mask); } fchmodSync(fd, mask) { - if ((fd & ZIP_MASK) !== ZIP_MAGIC) + if ((fd & ZIP_FD) === 0) return this.baseFs.fchmodSync(fd, mask); const entry = this.fdMap.get(fd); if (typeof entry === `undefined`) @@ -22142,46 +22158,28 @@ class ZipOpenFS extends BasePortableFakeFS { async chmodPromise(p, mask) { return await this.makeCallPromise(p, async () => { return await this.baseFs.chmodPromise(p, mask); - }, async (zipFs, { subPath }) => { + }, async (zipFs, {subPath}) => { return await zipFs.chmodPromise(subPath, mask); }); } chmodSync(p, mask) { return this.makeCallSync(p, () => { return this.baseFs.chmodSync(p, mask); - }, (zipFs, { subPath }) => { + }, (zipFs, {subPath}) => { return zipFs.chmodSync(subPath, mask); }); } - async fchownPromise(fd, uid, gid) { - if ((fd & ZIP_MASK) !== ZIP_MAGIC) - return this.baseFs.fchownPromise(fd, uid, gid); - const entry = this.fdMap.get(fd); - if (typeof entry === `undefined`) - throw EBADF(`fchown`); - const [zipFs, realFd] = entry; - return zipFs.fchownPromise(realFd, uid, gid); - } - fchownSync(fd, uid, gid) { - if ((fd & ZIP_MASK) !== ZIP_MAGIC) - return this.baseFs.fchownSync(fd, uid, gid); - const entry = this.fdMap.get(fd); - if (typeof entry === `undefined`) - throw EBADF(`fchownSync`); - const [zipFs, realFd] = entry; - return zipFs.fchownSync(realFd, uid, gid); - } async chownPromise(p, uid, gid) { return await this.makeCallPromise(p, async () => { return await this.baseFs.chownPromise(p, uid, gid); - }, async (zipFs, { subPath }) => { + }, async (zipFs, {subPath}) => { return await zipFs.chownPromise(subPath, uid, gid); }); } chownSync(p, uid, gid) { return this.makeCallSync(p, () => { return this.baseFs.chownSync(p, uid, gid); - }, (zipFs, { subPath }) => { + }, (zipFs, {subPath}) => { return zipFs.chownSync(subPath, uid, gid); }); } @@ -22190,14 +22188,14 @@ class ZipOpenFS extends BasePortableFakeFS { return await this.makeCallPromise(newP, async () => { return await this.baseFs.renamePromise(oldP, newP); }, async () => { - throw Object.assign(new Error(`EEXDEV: cross-device link not permitted`), { code: `EEXDEV` }); + throw Object.assign(new Error(`EEXDEV: cross-device link not permitted`), {code: `EEXDEV`}); }); - }, async (zipFsO, { subPath: subPathO }) => { + }, async (zipFsO, {subPath: subPathO}) => { return await this.makeCallPromise(newP, async () => { - throw Object.assign(new Error(`EEXDEV: cross-device link not permitted`), { code: `EEXDEV` }); - }, async (zipFsN, { subPath: subPathN }) => { + throw Object.assign(new Error(`EEXDEV: cross-device link not permitted`), {code: `EEXDEV`}); + }, async (zipFsN, {subPath: subPathN}) => { if (zipFsO !== zipFsN) { - throw Object.assign(new Error(`EEXDEV: cross-device link not permitted`), { code: `EEXDEV` }); + throw Object.assign(new Error(`EEXDEV: cross-device link not permitted`), {code: `EEXDEV`}); } else { return await zipFsO.renamePromise(subPathO, subPathN); } @@ -22209,14 +22207,14 @@ class ZipOpenFS extends BasePortableFakeFS { return this.makeCallSync(newP, () => { return this.baseFs.renameSync(oldP, newP); }, () => { - throw Object.assign(new Error(`EEXDEV: cross-device link not permitted`), { code: `EEXDEV` }); + throw Object.assign(new Error(`EEXDEV: cross-device link not permitted`), {code: `EEXDEV`}); }); - }, (zipFsO, { subPath: subPathO }) => { + }, (zipFsO, {subPath: subPathO}) => { return this.makeCallSync(newP, () => { - throw Object.assign(new Error(`EEXDEV: cross-device link not permitted`), { code: `EEXDEV` }); - }, (zipFsN, { subPath: subPathN }) => { + throw Object.assign(new Error(`EEXDEV: cross-device link not permitted`), {code: `EEXDEV`}); + }, (zipFsN, {subPath: subPathN}) => { if (zipFsO !== zipFsN) { - throw Object.assign(new Error(`EEXDEV: cross-device link not permitted`), { code: `EEXDEV` }); + throw Object.assign(new Error(`EEXDEV: cross-device link not permitted`), {code: `EEXDEV`}); } else { return zipFsO.renameSync(subPathO, subPathN); } @@ -22226,27 +22224,27 @@ class ZipOpenFS extends BasePortableFakeFS { async copyFilePromise(sourceP, destP, flags = 0) { const fallback = async (sourceFs, sourceP2, destFs, destP2) => { if ((flags & fs.constants.COPYFILE_FICLONE_FORCE) !== 0) - throw Object.assign(new Error(`EXDEV: cross-device clone not permitted, copyfile '${sourceP2}' -> ${destP2}'`), { code: `EXDEV` }); + throw Object.assign(new Error(`EXDEV: cross-device clone not permitted, copyfile '${sourceP2}' -> ${destP2}'`), {code: `EXDEV`}); if (flags & fs.constants.COPYFILE_EXCL && await this.existsPromise(sourceP2)) - throw Object.assign(new Error(`EEXIST: file already exists, copyfile '${sourceP2}' -> '${destP2}'`), { code: `EEXIST` }); + throw Object.assign(new Error(`EEXIST: file already exists, copyfile '${sourceP2}' -> '${destP2}'`), {code: `EEXIST`}); let content; try { content = await sourceFs.readFilePromise(sourceP2); } catch (error) { - throw Object.assign(new Error(`EINVAL: invalid argument, copyfile '${sourceP2}' -> '${destP2}'`), { code: `EINVAL` }); + throw Object.assign(new Error(`EINVAL: invalid argument, copyfile '${sourceP2}' -> '${destP2}'`), {code: `EINVAL`}); } await destFs.writeFilePromise(destP2, content); }; return await this.makeCallPromise(sourceP, async () => { return await this.makeCallPromise(destP, async () => { return await this.baseFs.copyFilePromise(sourceP, destP, flags); - }, async (zipFsD, { subPath: subPathD }) => { + }, async (zipFsD, {subPath: subPathD}) => { return await fallback(this.baseFs, sourceP, zipFsD, subPathD); }); - }, async (zipFsS, { subPath: subPathS }) => { + }, async (zipFsS, {subPath: subPathS}) => { return await this.makeCallPromise(destP, async () => { return await fallback(zipFsS, subPathS, this.baseFs, destP); - }, async (zipFsD, { subPath: subPathD }) => { + }, async (zipFsD, {subPath: subPathD}) => { if (zipFsS !== zipFsD) { return await fallback(zipFsS, subPathS, zipFsD, subPathD); } else { @@ -22258,27 +22256,27 @@ class ZipOpenFS extends BasePortableFakeFS { copyFileSync(sourceP, destP, flags = 0) { const fallback = (sourceFs, sourceP2, destFs, destP2) => { if ((flags & fs.constants.COPYFILE_FICLONE_FORCE) !== 0) - throw Object.assign(new Error(`EXDEV: cross-device clone not permitted, copyfile '${sourceP2}' -> ${destP2}'`), { code: `EXDEV` }); + throw Object.assign(new Error(`EXDEV: cross-device clone not permitted, copyfile '${sourceP2}' -> ${destP2}'`), {code: `EXDEV`}); if (flags & fs.constants.COPYFILE_EXCL && this.existsSync(sourceP2)) - throw Object.assign(new Error(`EEXIST: file already exists, copyfile '${sourceP2}' -> '${destP2}'`), { code: `EEXIST` }); + throw Object.assign(new Error(`EEXIST: file already exists, copyfile '${sourceP2}' -> '${destP2}'`), {code: `EEXIST`}); let content; try { content = sourceFs.readFileSync(sourceP2); } catch (error) { - throw Object.assign(new Error(`EINVAL: invalid argument, copyfile '${sourceP2}' -> '${destP2}'`), { code: `EINVAL` }); + throw Object.assign(new Error(`EINVAL: invalid argument, copyfile '${sourceP2}' -> '${destP2}'`), {code: `EINVAL`}); } destFs.writeFileSync(destP2, content); }; return this.makeCallSync(sourceP, () => { return this.makeCallSync(destP, () => { return this.baseFs.copyFileSync(sourceP, destP, flags); - }, (zipFsD, { subPath: subPathD }) => { + }, (zipFsD, {subPath: subPathD}) => { return fallback(this.baseFs, sourceP, zipFsD, subPathD); }); - }, (zipFsS, { subPath: subPathS }) => { + }, (zipFsS, {subPath: subPathS}) => { return this.makeCallSync(destP, () => { return fallback(zipFsS, subPathS, this.baseFs, destP); - }, (zipFsD, { subPath: subPathD }) => { + }, (zipFsD, {subPath: subPathD}) => { if (zipFsS !== zipFsD) { return fallback(zipFsS, subPathS, zipFsD, subPathD); } else { @@ -22290,112 +22288,112 @@ class ZipOpenFS extends BasePortableFakeFS { async appendFilePromise(p, content, opts) { return await this.makeCallPromise(p, async () => { return await this.baseFs.appendFilePromise(p, content, opts); - }, async (zipFs, { subPath }) => { + }, async (zipFs, {subPath}) => { return await zipFs.appendFilePromise(subPath, content, opts); }); } appendFileSync(p, content, opts) { return this.makeCallSync(p, () => { return this.baseFs.appendFileSync(p, content, opts); - }, (zipFs, { subPath }) => { + }, (zipFs, {subPath}) => { return zipFs.appendFileSync(subPath, content, opts); }); } async writeFilePromise(p, content, opts) { return await this.makeCallPromise(p, async () => { return await this.baseFs.writeFilePromise(p, content, opts); - }, async (zipFs, { subPath }) => { + }, async (zipFs, {subPath}) => { return await zipFs.writeFilePromise(subPath, content, opts); }); } writeFileSync(p, content, opts) { return this.makeCallSync(p, () => { return this.baseFs.writeFileSync(p, content, opts); - }, (zipFs, { subPath }) => { + }, (zipFs, {subPath}) => { return zipFs.writeFileSync(subPath, content, opts); }); } async unlinkPromise(p) { return await this.makeCallPromise(p, async () => { return await this.baseFs.unlinkPromise(p); - }, async (zipFs, { subPath }) => { + }, async (zipFs, {subPath}) => { return await zipFs.unlinkPromise(subPath); }); } unlinkSync(p) { return this.makeCallSync(p, () => { return this.baseFs.unlinkSync(p); - }, (zipFs, { subPath }) => { + }, (zipFs, {subPath}) => { return zipFs.unlinkSync(subPath); }); } async utimesPromise(p, atime, mtime) { return await this.makeCallPromise(p, async () => { return await this.baseFs.utimesPromise(p, atime, mtime); - }, async (zipFs, { subPath }) => { + }, async (zipFs, {subPath}) => { return await zipFs.utimesPromise(subPath, atime, mtime); }); } utimesSync(p, atime, mtime) { return this.makeCallSync(p, () => { return this.baseFs.utimesSync(p, atime, mtime); - }, (zipFs, { subPath }) => { + }, (zipFs, {subPath}) => { return zipFs.utimesSync(subPath, atime, mtime); }); } async mkdirPromise(p, opts) { return await this.makeCallPromise(p, async () => { return await this.baseFs.mkdirPromise(p, opts); - }, async (zipFs, { subPath }) => { + }, async (zipFs, {subPath}) => { return await zipFs.mkdirPromise(subPath, opts); }); } mkdirSync(p, opts) { return this.makeCallSync(p, () => { return this.baseFs.mkdirSync(p, opts); - }, (zipFs, { subPath }) => { + }, (zipFs, {subPath}) => { return zipFs.mkdirSync(subPath, opts); }); } async rmdirPromise(p, opts) { return await this.makeCallPromise(p, async () => { return await this.baseFs.rmdirPromise(p, opts); - }, async (zipFs, { subPath }) => { + }, async (zipFs, {subPath}) => { return await zipFs.rmdirPromise(subPath, opts); }); } rmdirSync(p, opts) { return this.makeCallSync(p, () => { return this.baseFs.rmdirSync(p, opts); - }, (zipFs, { subPath }) => { + }, (zipFs, {subPath}) => { return zipFs.rmdirSync(subPath, opts); }); } async linkPromise(existingP, newP) { return await this.makeCallPromise(newP, async () => { return await this.baseFs.linkPromise(existingP, newP); - }, async (zipFs, { subPath }) => { + }, async (zipFs, {subPath}) => { return await zipFs.linkPromise(existingP, subPath); }); } linkSync(existingP, newP) { return this.makeCallSync(newP, () => { return this.baseFs.linkSync(existingP, newP); - }, (zipFs, { subPath }) => { + }, (zipFs, {subPath}) => { return zipFs.linkSync(existingP, subPath); }); } async symlinkPromise(target, p, type) { return await this.makeCallPromise(p, async () => { return await this.baseFs.symlinkPromise(target, p, type); - }, async (zipFs, { subPath }) => { + }, async (zipFs, {subPath}) => { return await zipFs.symlinkPromise(target, subPath); }); } symlinkSync(target, p, type) { return this.makeCallSync(p, () => { return this.baseFs.symlinkSync(target, p, type); - }, (zipFs, { subPath }) => { + }, (zipFs, {subPath}) => { return zipFs.symlinkSync(target, subPath); }); } @@ -22407,7 +22405,7 @@ class ZipOpenFS extends BasePortableFakeFS { default: return await this.baseFs.readFilePromise(p, encoding); } - }, async (zipFs, { subPath }) => { + }, async (zipFs, {subPath}) => { return await zipFs.readFilePromise(subPath, encoding); }); } @@ -22419,14 +22417,14 @@ class ZipOpenFS extends BasePortableFakeFS { default: return this.baseFs.readFileSync(p, encoding); } - }, (zipFs, { subPath }) => { + }, (zipFs, {subPath}) => { return zipFs.readFileSync(subPath, encoding); }); } async readdirPromise(p, opts) { return await this.makeCallPromise(p, async () => { return await this.baseFs.readdirPromise(p, opts); - }, async (zipFs, { subPath }) => { + }, async (zipFs, {subPath}) => { return await zipFs.readdirPromise(subPath, opts); }, { requireSubpath: false @@ -22435,7 +22433,7 @@ class ZipOpenFS extends BasePortableFakeFS { readdirSync(p, opts) { return this.makeCallSync(p, () => { return this.baseFs.readdirSync(p, opts); - }, (zipFs, { subPath }) => { + }, (zipFs, {subPath}) => { return zipFs.readdirSync(subPath, opts); }, { requireSubpath: false @@ -22444,33 +22442,33 @@ class ZipOpenFS extends BasePortableFakeFS { async readlinkPromise(p) { return await this.makeCallPromise(p, async () => { return await this.baseFs.readlinkPromise(p); - }, async (zipFs, { subPath }) => { + }, async (zipFs, {subPath}) => { return await zipFs.readlinkPromise(subPath); }); } readlinkSync(p) { return this.makeCallSync(p, () => { return this.baseFs.readlinkSync(p); - }, (zipFs, { subPath }) => { + }, (zipFs, {subPath}) => { return zipFs.readlinkSync(subPath); }); } async truncatePromise(p, len) { return await this.makeCallPromise(p, async () => { return await this.baseFs.truncatePromise(p, len); - }, async (zipFs, { subPath }) => { + }, async (zipFs, {subPath}) => { return await zipFs.truncatePromise(subPath, len); }); } truncateSync(p, len) { return this.makeCallSync(p, () => { return this.baseFs.truncateSync(p, len); - }, (zipFs, { subPath }) => { + }, (zipFs, {subPath}) => { return zipFs.truncateSync(subPath, len); }); } async ftruncatePromise(fd, len) { - if ((fd & ZIP_MASK) !== ZIP_MAGIC) + if ((fd & ZIP_FD) === 0) return this.baseFs.ftruncatePromise(fd, len); const entry = this.fdMap.get(fd); if (typeof entry === `undefined`) @@ -22479,7 +22477,7 @@ class ZipOpenFS extends BasePortableFakeFS { return zipFs.ftruncatePromise(realFd, len); } ftruncateSync(fd, len) { - if ((fd & ZIP_MASK) !== ZIP_MAGIC) + if ((fd & ZIP_FD) === 0) return this.baseFs.ftruncateSync(fd, len); const entry = this.fdMap.get(fd); if (typeof entry === `undefined`) @@ -22489,26 +22487,14 @@ class ZipOpenFS extends BasePortableFakeFS { } watch(p, a, b) { return this.makeCallSync(p, () => { - return this.baseFs.watch( - p, - a, - b - ); - }, (zipFs, { subPath }) => { - return zipFs.watch( - subPath, - a, - b - ); + return this.baseFs.watch(p, a, b); + }, (zipFs, {subPath}) => { + return zipFs.watch(subPath, a, b); }); } watchFile(p, a, b) { return this.makeCallSync(p, () => { - return this.baseFs.watchFile( - p, - a, - b - ); + return this.baseFs.watchFile(p, a, b); }, () => { return watchFile(this, p, a, b); }); @@ -22520,7 +22506,7 @@ class ZipOpenFS extends BasePortableFakeFS { return unwatchFile(this, p, cb); }); } - async makeCallPromise(p, discard, accept, { requireSubpath = true } = {}) { + async makeCallPromise(p, discard, accept, {requireSubpath = true} = {}) { if (typeof p !== `string`) return await discard(); const normalizedP = this.resolve(p); @@ -22531,7 +22517,7 @@ class ZipOpenFS extends BasePortableFakeFS { return await discard(); return await this.getZipPromise(zipInfo.archivePath, async (zipFs) => await accept(zipFs, zipInfo)); } - makeCallSync(p, discard, accept, { requireSubpath = true } = {}) { + makeCallSync(p, discard, accept, {requireSubpath = true} = {}) { if (typeof p !== `string`) return discard(); const normalizedP = this.resolve(p); @@ -22587,7 +22573,7 @@ class ZipOpenFS extends BasePortableFakeFS { const now = Date.now(); let nextExpiresAt = now + this.maxAge; let closeCount = max === null ? 0 : this.zipInstances.size - max; - for (const [path, { zipFs, expiresAt, refCount }] of this.zipInstances.entries()) { + for (const [path, {zipFs, expiresAt, refCount}] of this.zipInstances.entries()) { if (refCount !== 0 || zipFs.hasOpenFileHandles()) { continue; } else if (now >= expiresAt) { @@ -22681,7 +22667,7 @@ class ZipOpenFS extends BasePortableFakeFS { } } -class NodePathFS extends ProxiedFS { +class URLFS extends ProxiedFS { constructor(baseFs) { super(npath); this.baseFs = baseFs; @@ -22690,20 +22676,31 @@ class NodePathFS extends ProxiedFS { return path; } mapToBase(path) { - if (typeof path === `string`) - return path; if (path instanceof url.URL) return url.fileURLToPath(path); - if (Buffer.isBuffer(path)) { - const str = path.toString(); - if (Buffer.byteLength(str) !== path.byteLength) - throw new Error(`Non-utf8 buffers are not supported at the moment. Please upvote the following issue if you encounter this error: https://github.com/yarnpkg/berry/issues/4942`); - return str; - } - throw new Error(`Unsupported path type: ${nodeUtils.inspect(path)}`); + return path; } } +var __defProp$3 = Object.defineProperty; +var __defProps$2 = Object.defineProperties; +var __getOwnPropDescs$2 = Object.getOwnPropertyDescriptors; +var __getOwnPropSymbols$4 = Object.getOwnPropertySymbols; +var __hasOwnProp$4 = Object.prototype.hasOwnProperty; +var __propIsEnum$4 = Object.prototype.propertyIsEnumerable; +var __defNormalProp$3 = (obj, key, value) => key in obj ? __defProp$3(obj, key, {enumerable: true, configurable: true, writable: true, value}) : obj[key] = value; +var __spreadValues$3 = (a, b) => { + for (var prop in b || (b = {})) + if (__hasOwnProp$4.call(b, prop)) + __defNormalProp$3(a, prop, b[prop]); + if (__getOwnPropSymbols$4) + for (var prop of __getOwnPropSymbols$4(b)) { + if (__propIsEnum$4.call(b, prop)) + __defNormalProp$3(a, prop, b[prop]); + } + return a; +}; +var __spreadProps$2 = (a, b) => __defProps$2(a, __getOwnPropDescs$2(b)); var _a, _b, _c, _d; const kBaseFs = Symbol(`kBaseFs`); const kFd = Symbol(`kFd`); @@ -22730,18 +22727,13 @@ class FileHandle { try { this[kRef](this.appendFile); const encoding = (_a2 = typeof options === `string` ? options : options == null ? void 0 : options.encoding) != null ? _a2 : void 0; - return await this[kBaseFs].appendFilePromise(this.fd, data, encoding ? { encoding } : void 0); + return await this[kBaseFs].appendFilePromise(this.fd, data, encoding ? {encoding} : void 0); } finally { this[kUnref](); } } - async chown(uid, gid) { - try { - this[kRef](this.chown); - return await this[kBaseFs].fchownPromise(this.fd, uid, gid); - } finally { - this[kUnref](); - } + chown(uid, gid) { + throw new Error(`Method not implemented.`); } async chmod(mode) { try { @@ -22752,10 +22744,10 @@ class FileHandle { } } createReadStream(options) { - return this[kBaseFs].createReadStream(null, { ...options, fd: this.fd }); + return this[kBaseFs].createReadStream(null, __spreadProps$2(__spreadValues$3({}, options), {fd: this.fd})); } createWriteStream(options) { - return this[kBaseFs].createWriteStream(null, { ...options, fd: this.fd }); + return this[kBaseFs].createWriteStream(null, __spreadProps$2(__spreadValues$3({}, options), {fd: this.fd})); } datasync() { throw new Error(`Method not implemented.`); @@ -22839,11 +22831,11 @@ class FileHandle { if (ArrayBuffer.isView(args[0])) { const [buffer, offset, length, position] = args; const bytesWritten = await this[kBaseFs].writePromise(this.fd, buffer, offset != null ? offset : void 0, length != null ? length : void 0, position != null ? position : void 0); - return { bytesWritten, buffer }; + return {bytesWritten, buffer}; } else { const [data, position, encoding] = args; const bytesWritten = await this[kBaseFs].writePromise(this.fd, data, position, encoding); - return { bytesWritten, buffer: data }; + return {bytesWritten, buffer: data}; } } finally { this[kUnref](); @@ -22919,7 +22911,7 @@ class FileHandle { } } -const SYNC_IMPLEMENTATIONS = /* @__PURE__ */ new Set([ +const SYNC_IMPLEMENTATIONS = new Set([ `accessSync`, `appendFileSync`, `createReadStream`, @@ -22927,7 +22919,6 @@ const SYNC_IMPLEMENTATIONS = /* @__PURE__ */ new Set([ `chmodSync`, `fchmodSync`, `chownSync`, - `fchownSync`, `closeSync`, `copyFileSync`, `linkSync`, @@ -22956,12 +22947,11 @@ const SYNC_IMPLEMENTATIONS = /* @__PURE__ */ new Set([ `writeFileSync`, `writeSync` ]); -const ASYNC_IMPLEMENTATIONS = /* @__PURE__ */ new Set([ +const ASYNC_IMPLEMENTATIONS = new Set([ `accessPromise`, `appendFilePromise`, `fchmodPromise`, `chmodPromise`, - `fchownPromise`, `chownPromise`, `closePromise`, `copyFilePromise`, @@ -22989,7 +22979,7 @@ const ASYNC_IMPLEMENTATIONS = /* @__PURE__ */ new Set([ `writeSync` ]); function patchFs(patchedFs, fakeFs) { - fakeFs = new NodePathFS(fakeFs); + fakeFs = new URLFS(fakeFs); const setupFn = (target, name, replacement) => { const orig = target[name]; target[name] = replacement; @@ -23081,7 +23071,7 @@ function patchFs(patchedFs, fakeFs) { let [fd, buffer, offset, length, position] = args; if (args.length <= 3) { const options = args[2] || {}; - ({ offset = 0, length = buffer.byteLength, position } = options); + ({offset = 0, length = buffer.byteLength, position} = options); } if (offset == null) offset = 0; @@ -23140,11 +23130,11 @@ function patchFs(patchedFs, fakeFs) { { patchedFs.read[nodeUtils.promisify.custom] = async (fd, buffer, ...args) => { const res = fakeFs.readPromise(fd, buffer, ...args); - return { bytesRead: await res, buffer }; + return {bytesRead: await res, buffer}; }; patchedFs.write[nodeUtils.promisify.custom] = async (fd, buffer, ...args) => { const res = fakeFs.writePromise(fd, buffer, ...args); - return { bytesWritten: await res, buffer }; + return {bytesWritten: await res, buffer}; }; } } @@ -23274,10 +23264,7 @@ var createModule = function() { } function getCFunc(ident) { var func = Module["_" + ident]; - assert( - func, - "Cannot call unknown function " + ident + ", make sure it is exported" - ); + assert(func, "Cannot call unknown function " + ident + ", make sure it is exported"); return func; } function ccall(ident, returnType, argTypes, args, opts) { @@ -23576,16 +23563,14 @@ var createModule = function() { var str = e.toString(); err("failed to compile wasm module: " + str); if (str.includes("imported Memory") || str.includes("memory import")) { - err( - "Memory size incompatibility issues may be due to changing INITIAL_MEMORY at runtime to something too large. Use ALLOW_MEMORY_GROWTH to allow any size memory (and also make sure not to set INITIAL_MEMORY at runtime to something smaller than it was at compile time)." - ); + err("Memory size incompatibility issues may be due to changing INITIAL_MEMORY at runtime to something too large. Use ALLOW_MEMORY_GROWTH to allow any size memory (and also make sure not to set INITIAL_MEMORY at runtime to something smaller than it was at compile time)."); } throw e; } return [instance, module2]; } function createWasm() { - var info = { a: asmLibraryArg }; + var info = {a: asmLibraryArg}; function receiveInstance(instance, module2) { var exports3 = instance.exports; Module["asm"] = exports3; @@ -23680,12 +23665,9 @@ var createModule = function() { }, normalize: function(path) { var isAbsolute = path.charAt(0) === "/", trailingSlash = path.substr(-1) === "/"; - path = PATH.normalizeArray( - path.split("/").filter(function(p) { - return !!p; - }), - !isAbsolute - ).join("/"); + path = PATH.normalizeArray(path.split("/").filter(function(p) { + return !!p; + }), !isAbsolute).join("/"); if (!path && !isAbsolute) { path = "."; } @@ -23752,12 +23734,9 @@ var createModule = function() { resolvedPath = path + "/" + resolvedPath; resolvedAbsolute = path.charAt(0) === "/"; } - resolvedPath = PATH.normalizeArray( - resolvedPath.split("/").filter(function(p) { - return !!p; - }), - !resolvedAbsolute - ).join("/"); + resolvedPath = PATH.normalizeArray(resolvedPath.split("/").filter(function(p) { + return !!p; + }), !resolvedAbsolute).join("/"); return (resolvedAbsolute ? "/" : "") + resolvedPath || "."; }, relative: function(from, to) { @@ -23803,7 +23782,7 @@ var createModule = function() { shutdown: function() { }, register: function(dev, ops) { - TTY.ttys[dev] = { input: [], output: [], ops }; + TTY.ttys[dev] = {input: [], output: [], ops}; FS.registerDevice(dev, TTY.stream_ops); }, stream_ops: { @@ -23872,13 +23851,7 @@ var createModule = function() { var buf = Buffer.alloc ? Buffer.alloc(BUFSIZE) : new Buffer(BUFSIZE); var bytesRead = 0; try { - bytesRead = nodeFS.readSync( - process.stdin.fd, - buf, - 0, - BUFSIZE, - null - ); + bytesRead = nodeFS.readSync(process.stdin.fd, buf, 0, BUFSIZE, null); } catch (e) { if (e.toString().includes("EOF")) bytesRead = 0; @@ -23962,7 +23935,7 @@ var createModule = function() { readdir: MEMFS.node_ops.readdir, symlink: MEMFS.node_ops.symlink }, - stream: { llseek: MEMFS.stream_ops.llseek } + stream: {llseek: MEMFS.stream_ops.llseek} }, file: { node: { @@ -24031,10 +24004,7 @@ var createModule = function() { if (prevCapacity >= newCapacity) return; var CAPACITY_DOUBLING_MAX = 1024 * 1024; - newCapacity = Math.max( - newCapacity, - prevCapacity * (prevCapacity < CAPACITY_DOUBLING_MAX ? 2 : 1.125) >>> 0 - ); + newCapacity = Math.max(newCapacity, prevCapacity * (prevCapacity < CAPACITY_DOUBLING_MAX ? 2 : 1.125) >>> 0); if (prevCapacity != 0) newCapacity = Math.max(newCapacity, 256); var oldContents = node.contents; @@ -24052,9 +24022,7 @@ var createModule = function() { var oldContents = node.contents; node.contents = new Uint8Array(newSize); if (oldContents) { - node.contents.set( - oldContents.subarray(0, Math.min(newSize, node.usedBytes)) - ); + node.contents.set(oldContents.subarray(0, Math.min(newSize, node.usedBytes))); } node.usedBytes = newSize; } @@ -24188,19 +24156,13 @@ var createModule = function() { node.usedBytes = length; return length; } else if (position + length <= node.usedBytes) { - node.contents.set( - buffer2.subarray(offset, offset + length), - position - ); + node.contents.set(buffer2.subarray(offset, offset + length), position); return length; } } MEMFS.expandFileStorage(node, position + length); if (node.contents.subarray && buffer2.subarray) { - node.contents.set( - buffer2.subarray(offset, offset + length), - position - ); + node.contents.set(buffer2.subarray(offset, offset + length), position); } else { for (var i = 0; i < length; i++) { node.contents[position + i] = buffer2[offset + i]; @@ -24225,10 +24187,7 @@ var createModule = function() { }, allocate: function(stream, offset, length) { MEMFS.expandFileStorage(stream.node, offset + length); - stream.node.usedBytes = Math.max( - stream.node.usedBytes, - offset + length - ); + stream.node.usedBytes = Math.max(stream.node.usedBytes, offset + length); }, mmap: function(stream, address, length, position, prot, flags) { if (address !== 0) { @@ -24248,11 +24207,7 @@ var createModule = function() { if (contents.subarray) { contents = contents.subarray(position, position + length); } else { - contents = Array.prototype.slice.call( - contents, - position, - position + length - ); + contents = Array.prototype.slice.call(contents, position, position + length); } } allocated = true; @@ -24262,7 +24217,7 @@ var createModule = function() { } HEAP8.set(contents, ptr); } - return { ptr, allocated }; + return {ptr, allocated}; }, msync: function(stream, buffer2, offset, length, mmapFlags) { if (!FS.isFile(stream.node.mode)) { @@ -24271,14 +24226,7 @@ var createModule = function() { if (mmapFlags & 2) { return 0; } - MEMFS.stream_ops.write( - stream, - buffer2, - 0, - length, - offset, - false - ); + MEMFS.stream_ops.write(stream, buffer2, 0, length, offset, false); return 0; } } @@ -24410,7 +24358,7 @@ var createModule = function() { isWindows: false, staticInit: function() { NODEFS.isWindows = !!process.platform.match(/^win/); - var flags = { fs: fs.constants }; + var flags = {fs: fs.constants}; if (flags["fs"]) { flags = flags["fs"]; } @@ -24552,7 +24500,7 @@ var createModule = function() { if (FS.isDir(node.mode)) { fs.mkdirSync(path, node.mode); } else { - fs.writeFileSync(path, "", { mode: node.mode }); + fs.writeFileSync(path, "", {mode: node.mode}); } } catch (e) { if (!e.code) @@ -24617,10 +24565,7 @@ var createModule = function() { var path = NODEFS.realPath(node); try { path = fs.readlinkSync(path); - path = NODEJS_PATH.relative( - NODEJS_PATH.resolve(node.mount.opts.root), - path - ); + path = NODEJS_PATH.relative(NODEJS_PATH.resolve(node.mount.opts.root), path); return path; } catch (e) { if (!e.code) @@ -24657,26 +24602,14 @@ var createModule = function() { if (length === 0) return 0; try { - return fs.readSync( - stream.nfd, - NODEFS.bufferFrom(buffer2.buffer), - offset, - length, - position - ); + return fs.readSync(stream.nfd, NODEFS.bufferFrom(buffer2.buffer), offset, length, position); } catch (e) { throw new FS.ErrnoError(NODEFS.convertNodeCode(e)); } }, write: function(stream, buffer2, offset, length, position) { try { - return fs.writeSync( - stream.nfd, - NODEFS.bufferFrom(buffer2.buffer), - offset, - length, - position - ); + return fs.writeSync(stream.nfd, NODEFS.bufferFrom(buffer2.buffer), offset, length, position); } catch (e) { throw new FS.ErrnoError(NODEFS.convertNodeCode(e)); } @@ -24709,7 +24642,7 @@ var createModule = function() { } var ptr = mmapAlloc(length); NODEFS.stream_ops.read(stream, HEAP8, ptr, length, position); - return { ptr, allocated: true }; + return {ptr, allocated: true}; }, msync: function(stream, buffer2, offset, length, mmapFlags) { if (!FS.isFile(stream.node.mode)) { @@ -24718,21 +24651,14 @@ var createModule = function() { if (mmapFlags & 2) { return 0; } - NODEFS.stream_ops.write( - stream, - buffer2, - 0, - length, - offset, - false - ); + NODEFS.stream_ops.write(stream, buffer2, 0, length, offset, false); return 0; } } }; var NODERAWFS = { lookupPath: function(path) { - return { path, node: { mode: NODEFS.getMode(path) } }; + return {path, node: {mode: NODEFS.getMode(path)}}; }, createStandardStreams: function() { FS.streams[0] = { @@ -24766,7 +24692,7 @@ var createModule = function() { if (FS.isDir(path)) { fs.mkdirSync(path, mode); } else { - fs.writeFileSync(path, "", { mode }); + fs.writeFileSync(path, "", {mode}); } }, mkdir: function() { @@ -24868,13 +24794,7 @@ var createModule = function() { var seeking = typeof position !== "undefined"; if (!seeking && stream.seekable) position = stream.position; - var bytesRead = fs.readSync( - stream.nfd, - NODEFS.bufferFrom(buffer2.buffer), - offset, - length, - position - ); + var bytesRead = fs.readSync(stream.nfd, NODEFS.bufferFrom(buffer2.buffer), offset, length, position); if (!seeking) stream.position += bytesRead; return bytesRead; @@ -24889,13 +24809,7 @@ var createModule = function() { var seeking = typeof position !== "undefined"; if (!seeking && stream.seekable) position = stream.position; - var bytesWritten = fs.writeSync( - stream.nfd, - NODEFS.bufferFrom(buffer2.buffer), - offset, - length, - position - ); + var bytesWritten = fs.writeSync(stream.nfd, NODEFS.bufferFrom(buffer2.buffer), offset, length, position); if (!seeking) stream.position += bytesWritten; return bytesWritten; @@ -24912,7 +24826,7 @@ var createModule = function() { } var ptr = mmapAlloc(length); FS.read(stream, HEAP8, ptr, length, position); - return { ptr, allocated: true }; + return {ptr, allocated: true}; }, msync: function(stream, buffer2, offset, length, mmapFlags) { if (stream.stream_ops) { @@ -24942,7 +24856,7 @@ var createModule = function() { initialized: false, ignorePermissions: true, trackingDelegate: {}, - tracking: { openFlags: { READ: 1, WRITE: 2 } }, + tracking: {openFlags: {READ: 1, WRITE: 2}}, ErrnoError: null, genericErrors: {}, filesystems: null, @@ -24951,8 +24865,8 @@ var createModule = function() { path = PATH_FS.resolve(FS.cwd(), path); opts = opts || {}; if (!path) - return { path: "", node: null }; - var defaults = { follow_mount: true, recurse_count: 0 }; + return {path: "", node: null}; + var defaults = {follow_mount: true, recurse_count: 0}; for (var key2 in defaults) { if (opts[key2] === void 0) { opts[key2] = defaults[key2]; @@ -24961,12 +24875,9 @@ var createModule = function() { if (opts.recurse_count > 8) { throw new FS.ErrnoError(32); } - var parts = PATH.normalizeArray( - path.split("/").filter(function(p) { - return !!p; - }), - false - ); + var parts = PATH.normalizeArray(path.split("/").filter(function(p) { + return !!p; + }), false); var current = FS.root; var current_path = "/"; for (var i = 0; i < parts.length; i++) { @@ -24996,7 +24907,7 @@ var createModule = function() { } } } - return { path: current_path, node: current }; + return {path: current_path, node: current}; }, getPath: function(node) { var path; @@ -25087,7 +24998,7 @@ var createModule = function() { isSocket: function(mode) { return (mode & 49152) === 49152; }, - flagModes: { r: 0, "r+": 2, w: 577, "w+": 578, a: 1089, "a+": 1090 }, + flagModes: {r: 0, "r+": 2, w: 577, "w+": 578, a: 1089, "a+": 1090}, modeStringToFlags: function(str) { var flags = FS.flagModes[str]; if (typeof flags === "undefined") { @@ -25248,7 +25159,7 @@ var createModule = function() { return ma << 8 | mi; }, registerDevice: function(dev, ops) { - FS.devices[dev] = { stream_ops: ops }; + FS.devices[dev] = {stream_ops: ops}; }, getDevice: function(dev) { return FS.devices[dev]; @@ -25270,9 +25181,7 @@ var createModule = function() { } FS.syncFSRequests++; if (FS.syncFSRequests > 1) { - err( - "warning: " + FS.syncFSRequests + " FS.syncfs operations in flight at once, probably just doing extra work" - ); + err("warning: " + FS.syncFSRequests + " FS.syncfs operations in flight at once, probably just doing extra work"); } var mounts = FS.getMounts(FS.root.mount); var completed = 0; @@ -25306,7 +25215,7 @@ var createModule = function() { if (root && FS.root) { throw new FS.ErrnoError(10); } else if (!root && !pseudo) { - var lookup = FS.lookupPath(mountpoint, { follow_mount: false }); + var lookup = FS.lookupPath(mountpoint, {follow_mount: false}); mountpoint = lookup.path; node = lookup.node; if (FS.isMountpoint(node)) { @@ -25336,7 +25245,7 @@ var createModule = function() { return mountRoot; }, unmount: function(mountpoint) { - var lookup = FS.lookupPath(mountpoint, { follow_mount: false }); + var lookup = FS.lookupPath(mountpoint, {follow_mount: false}); if (!FS.isMountpoint(lookup.node)) { throw new FS.ErrnoError(28); } @@ -25361,7 +25270,7 @@ var createModule = function() { return parent.node_ops.lookup(parent, name); }, mknod: function(path, mode, dev) { - var lookup = FS.lookupPath(path, { parent: true }); + var lookup = FS.lookupPath(path, {parent: true}); var parent = lookup.node; var name = PATH.basename(path); if (!name || name === "." || name === "..") { @@ -25415,7 +25324,7 @@ var createModule = function() { if (!PATH_FS.resolve(oldpath)) { throw new FS.ErrnoError(44); } - var lookup = FS.lookupPath(newpath, { parent: true }); + var lookup = FS.lookupPath(newpath, {parent: true}); var parent = lookup.node; if (!parent) { throw new FS.ErrnoError(44); @@ -25436,9 +25345,9 @@ var createModule = function() { var old_name = PATH.basename(old_path); var new_name = PATH.basename(new_path); var lookup, old_dir, new_dir; - lookup = FS.lookupPath(old_path, { parent: true }); + lookup = FS.lookupPath(old_path, {parent: true}); old_dir = lookup.node; - lookup = FS.lookupPath(new_path, { parent: true }); + lookup = FS.lookupPath(new_path, {parent: true}); new_dir = lookup.node; if (!old_dir || !new_dir) throw new FS.ErrnoError(44); @@ -25488,9 +25397,7 @@ var createModule = function() { FS.trackingDelegate["willMovePath"](old_path, new_path); } } catch (e) { - err( - "FS.trackingDelegate['willMovePath']('" + old_path + "', '" + new_path + "') threw an exception: " + e.message - ); + err("FS.trackingDelegate['willMovePath']('" + old_path + "', '" + new_path + "') threw an exception: " + e.message); } FS.hashRemoveNode(old_node); try { @@ -25504,13 +25411,11 @@ var createModule = function() { if (FS.trackingDelegate["onMovePath"]) FS.trackingDelegate["onMovePath"](old_path, new_path); } catch (e) { - err( - "FS.trackingDelegate['onMovePath']('" + old_path + "', '" + new_path + "') threw an exception: " + e.message - ); + err("FS.trackingDelegate['onMovePath']('" + old_path + "', '" + new_path + "') threw an exception: " + e.message); } }, rmdir: function(path) { - var lookup = FS.lookupPath(path, { parent: true }); + var lookup = FS.lookupPath(path, {parent: true}); var parent = lookup.node; var name = PATH.basename(path); var node = FS.lookupNode(parent, name); @@ -25529,9 +25434,7 @@ var createModule = function() { FS.trackingDelegate["willDeletePath"](path); } } catch (e) { - err( - "FS.trackingDelegate['willDeletePath']('" + path + "') threw an exception: " + e.message - ); + err("FS.trackingDelegate['willDeletePath']('" + path + "') threw an exception: " + e.message); } parent.node_ops.rmdir(parent, name); FS.destroyNode(node); @@ -25539,13 +25442,11 @@ var createModule = function() { if (FS.trackingDelegate["onDeletePath"]) FS.trackingDelegate["onDeletePath"](path); } catch (e) { - err( - "FS.trackingDelegate['onDeletePath']('" + path + "') threw an exception: " + e.message - ); + err("FS.trackingDelegate['onDeletePath']('" + path + "') threw an exception: " + e.message); } }, readdir: function(path) { - var lookup = FS.lookupPath(path, { follow: true }); + var lookup = FS.lookupPath(path, {follow: true}); var node = lookup.node; if (!node.node_ops.readdir) { throw new FS.ErrnoError(54); @@ -25553,7 +25454,7 @@ var createModule = function() { return node.node_ops.readdir(node); }, unlink: function(path) { - var lookup = FS.lookupPath(path, { parent: true }); + var lookup = FS.lookupPath(path, {parent: true}); var parent = lookup.node; var name = PATH.basename(path); var node = FS.lookupNode(parent, name); @@ -25572,9 +25473,7 @@ var createModule = function() { FS.trackingDelegate["willDeletePath"](path); } } catch (e) { - err( - "FS.trackingDelegate['willDeletePath']('" + path + "') threw an exception: " + e.message - ); + err("FS.trackingDelegate['willDeletePath']('" + path + "') threw an exception: " + e.message); } parent.node_ops.unlink(parent, name); FS.destroyNode(node); @@ -25582,9 +25481,7 @@ var createModule = function() { if (FS.trackingDelegate["onDeletePath"]) FS.trackingDelegate["onDeletePath"](path); } catch (e) { - err( - "FS.trackingDelegate['onDeletePath']('" + path + "') threw an exception: " + e.message - ); + err("FS.trackingDelegate['onDeletePath']('" + path + "') threw an exception: " + e.message); } }, readlink: function(path) { @@ -25596,13 +25493,10 @@ var createModule = function() { if (!link.node_ops.readlink) { throw new FS.ErrnoError(28); } - return PATH_FS.resolve( - FS.getPath(link.parent), - link.node_ops.readlink(link) - ); + return PATH_FS.resolve(FS.getPath(link.parent), link.node_ops.readlink(link)); }, stat: function(path, dontFollow) { - var lookup = FS.lookupPath(path, { follow: !dontFollow }); + var lookup = FS.lookupPath(path, {follow: !dontFollow}); var node = lookup.node; if (!node) { throw new FS.ErrnoError(44); @@ -25618,7 +25512,7 @@ var createModule = function() { chmod: function(path, mode, dontFollow) { var node; if (typeof path === "string") { - var lookup = FS.lookupPath(path, { follow: !dontFollow }); + var lookup = FS.lookupPath(path, {follow: !dontFollow}); node = lookup.node; } else { node = path; @@ -25644,7 +25538,7 @@ var createModule = function() { chown: function(path, uid, gid, dontFollow) { var node; if (typeof path === "string") { - var lookup = FS.lookupPath(path, { follow: !dontFollow }); + var lookup = FS.lookupPath(path, {follow: !dontFollow}); node = lookup.node; } else { node = path; @@ -25652,7 +25546,7 @@ var createModule = function() { if (!node.node_ops.setattr) { throw new FS.ErrnoError(63); } - node.node_ops.setattr(node, { timestamp: Date.now() }); + node.node_ops.setattr(node, {timestamp: Date.now()}); }, lchown: function(path, uid, gid) { FS.chown(path, uid, gid, true); @@ -25670,7 +25564,7 @@ var createModule = function() { } var node; if (typeof path === "string") { - var lookup = FS.lookupPath(path, { follow: true }); + var lookup = FS.lookupPath(path, {follow: true}); node = lookup.node; } else { node = path; @@ -25688,7 +25582,7 @@ var createModule = function() { if (errCode) { throw new FS.ErrnoError(errCode); } - node.node_ops.setattr(node, { size: len, timestamp: Date.now() }); + node.node_ops.setattr(node, {size: len, timestamp: Date.now()}); }, ftruncate: function(fd, len) { var stream = FS.getStream(fd); @@ -25701,9 +25595,9 @@ var createModule = function() { FS.truncate(stream.node, len); }, utime: function(path, atime, mtime) { - var lookup = FS.lookupPath(path, { follow: true }); + var lookup = FS.lookupPath(path, {follow: true}); var node = lookup.node; - node.node_ops.setattr(node, { timestamp: Math.max(atime, mtime) }); + node.node_ops.setattr(node, {timestamp: Math.max(atime, mtime)}); }, open: function(path, flags, mode, fd_start, fd_end) { if (path === "") { @@ -25722,7 +25616,7 @@ var createModule = function() { } else { path = PATH.normalize(path); try { - var lookup = FS.lookupPath(path, { follow: !(flags & 131072) }); + var lookup = FS.lookupPath(path, {follow: !(flags & 131072)}); node = lookup.node; } catch (e) { } @@ -25757,20 +25651,16 @@ var createModule = function() { FS.truncate(node, 0); } flags &= ~(128 | 512 | 131072); - var stream = FS.createStream( - { - node, - path: FS.getPath(node), - flags, - seekable: true, - position: 0, - stream_ops: node.stream_ops, - ungotten: [], - error: false - }, - fd_start, - fd_end - ); + var stream = FS.createStream({ + node, + path: FS.getPath(node), + flags, + seekable: true, + position: 0, + stream_ops: node.stream_ops, + ungotten: [], + error: false + }, fd_start, fd_end); if (stream.stream_ops.open) { stream.stream_ops.open(stream); } @@ -25794,9 +25684,7 @@ var createModule = function() { FS.trackingDelegate["onOpenFile"](path, trackingFlags); } } catch (e) { - err( - "FS.trackingDelegate['onOpenFile']('" + path + "', flags) threw an exception: " + e.message - ); + err("FS.trackingDelegate['onOpenFile']('" + path + "', flags) threw an exception: " + e.message); } return stream; }, @@ -25856,13 +25744,7 @@ var createModule = function() { } else if (!stream.seekable) { throw new FS.ErrnoError(70); } - var bytesRead = stream.stream_ops.read( - stream, - buffer2, - offset, - length, - position - ); + var bytesRead = stream.stream_ops.read(stream, buffer2, offset, length, position); if (!seeking) stream.position += bytesRead; return bytesRead; @@ -25892,23 +25774,14 @@ var createModule = function() { } else if (!stream.seekable) { throw new FS.ErrnoError(70); } - var bytesWritten = stream.stream_ops.write( - stream, - buffer2, - offset, - length, - position, - canOwn - ); + var bytesWritten = stream.stream_ops.write(stream, buffer2, offset, length, position, canOwn); if (!seeking) stream.position += bytesWritten; try { if (stream.path && FS.trackingDelegate["onWriteToFile"]) FS.trackingDelegate["onWriteToFile"](stream.path); } catch (e) { - err( - "FS.trackingDelegate['onWriteToFile']('" + stream.path + "') threw an exception: " + e.message - ); + err("FS.trackingDelegate['onWriteToFile']('" + stream.path + "') threw an exception: " + e.message); } return bytesWritten; }, @@ -25940,26 +25813,13 @@ var createModule = function() { if (!stream.stream_ops.mmap) { throw new FS.ErrnoError(43); } - return stream.stream_ops.mmap( - stream, - address, - length, - position, - prot, - flags - ); + return stream.stream_ops.mmap(stream, address, length, position, prot, flags); }, msync: function(stream, buffer2, offset, length, mmapFlags) { if (!stream || !stream.stream_ops.msync) { return 0; } - return stream.stream_ops.msync( - stream, - buffer2, - offset, - length, - mmapFlags - ); + return stream.stream_ops.msync(stream, buffer2, offset, length, mmapFlags); }, munmap: function(stream) { return 0; @@ -26010,7 +25870,7 @@ var createModule = function() { return FS.currentPath; }, chdir: function(path) { - var lookup = FS.lookupPath(path, { follow: true }); + var lookup = FS.lookupPath(path, {follow: true}); if (lookup.node === null) { throw new FS.ErrnoError(44); } @@ -26053,35 +25913,31 @@ var createModule = function() { FS.mkdir("/proc"); var proc_self = FS.mkdir("/proc/self"); FS.mkdir("/proc/self/fd"); - FS.mount( - { - mount: function() { - var node = FS.createNode(proc_self, "fd", 16384 | 511, 73); - node.node_ops = { - lookup: function(parent, name) { - var fd = +name; - var stream = FS.getStream(fd); - if (!stream) - throw new FS.ErrnoError(8); - var ret = { - parent: null, - mount: { mountpoint: "fake" }, - node_ops: { - readlink: function() { - return stream.path; - } + FS.mount({ + mount: function() { + var node = FS.createNode(proc_self, "fd", 16384 | 511, 73); + node.node_ops = { + lookup: function(parent, name) { + var fd = +name; + var stream = FS.getStream(fd); + if (!stream) + throw new FS.ErrnoError(8); + var ret = { + parent: null, + mount: {mountpoint: "fake"}, + node_ops: { + readlink: function() { + return stream.path; } - }; - ret.parent = ret; - return ret; - } - }; - return node; - } - }, - {}, - "/proc/self/fd" - ); + } + }; + ret.parent = ret; + return ret; + } + }; + return node; + } + }, {}, "/proc/self/fd"); }, createStandardStreams: function() { if (Module["stdin"]) { @@ -26128,7 +25984,7 @@ var createModule = function() { FS.createDefaultDirectories(); FS.createDefaultDevices(); FS.createSpecialDirectories(); - FS.filesystems = { MEMFS, NODEFS }; + FS.filesystems = {MEMFS, NODEFS}; }, init: function(input, output, error) { FS.init.initialized = true; @@ -26169,7 +26025,7 @@ var createModule = function() { }, analyzePath: function(path, dontResolveLastLink) { try { - var lookup = FS.lookupPath(path, { follow: !dontResolveLastLink }); + var lookup = FS.lookupPath(path, {follow: !dontResolveLastLink}); path = lookup.path; } catch (e) { } @@ -26185,12 +26041,12 @@ var createModule = function() { parentObject: null }; try { - var lookup = FS.lookupPath(path, { parent: true }); + var lookup = FS.lookupPath(path, {parent: true}); ret.parentExists = true; ret.parentPath = lookup.path; ret.parentObject = lookup.node; ret.name = PATH.basename(path); - lookup = FS.lookupPath(path, { follow: !dontResolveLastLink }); + lookup = FS.lookupPath(path, {follow: !dontResolveLastLink}); ret.exists = true; ret.path = lookup.path; ret.object = lookup.node; @@ -26218,18 +26074,12 @@ var createModule = function() { return current; }, createFile: function(parent, name, properties, canRead, canWrite) { - var path = PATH.join2( - typeof parent === "string" ? parent : FS.getPath(parent), - name - ); + var path = PATH.join2(typeof parent === "string" ? parent : FS.getPath(parent), name); var mode = FS.getMode(canRead, canWrite); return FS.create(path, mode); }, createDataFile: function(parent, name, data, canRead, canWrite, canOwn) { - var path = name ? PATH.join2( - typeof parent === "string" ? parent : FS.getPath(parent), - name - ) : parent; + var path = name ? PATH.join2(typeof parent === "string" ? parent : FS.getPath(parent), name) : parent; var mode = FS.getMode(canRead, canWrite); var node = FS.create(path, mode); if (data) { @@ -26248,10 +26098,7 @@ var createModule = function() { return node; }, createDevice: function(parent, name, input, output) { - var path = PATH.join2( - typeof parent === "string" ? parent : FS.getPath(parent), - name - ); + var path = PATH.join2(typeof parent === "string" ? parent : FS.getPath(parent), name); var mode = FS.getMode(!!input, !!output); if (!FS.createDevice.major) FS.createDevice.major = 64; @@ -26319,7 +26166,7 @@ var createModule = function() { }, createLazyFile: function(parent, name, url, canRead, canWrite) { var properties; { - var properties = { isDevice: false, url }; + var properties = {isDevice: false, url}; } var node = FS.createFile(parent, name, properties, canRead, canWrite); if (properties.contents) { @@ -26372,14 +26219,7 @@ var createModule = function() { if (preFinish) preFinish(); if (!dontCreateFile) { - FS.createDataFile( - parent, - name, - byteArray2, - canRead, - canWrite, - canOwn - ); + FS.createDataFile(parent, name, byteArray2, canRead, canWrite, canOwn); } if (onload) onload(); @@ -26403,13 +26243,9 @@ var createModule = function() { } addRunDependency(); if (typeof url == "string") { - Browser.asyncLoad( - url, - function(byteArray) { - processData(byteArray); - }, - onerror - ); + Browser.asyncLoad(url, function(byteArray) { + processData(byteArray); + }, onerror); } else { processData(url); } @@ -26450,10 +26286,7 @@ var createModule = function() { onerror(); } paths.forEach(function(path) { - var putRequest = files.put( - FS.analyzePath(path).object.contents, - path - ); + var putRequest = files.put(FS.analyzePath(path).object.contents, path); putRequest.onsuccess = function putRequest_onsuccess() { ok++; if (ok + fail == total) @@ -26503,14 +26336,7 @@ var createModule = function() { if (FS.analyzePath(path).exists) { FS.unlink(path); } - FS.createDataFile( - PATH.dirname(path), - PATH.basename(path), - getRequest.result, - true, - true, - true - ); + FS.createDataFile(PATH.dirname(path), PATH.basename(path), getRequest.result, true, true, true); ok++; if (ok + fail == total) finish(); @@ -26571,9 +26397,7 @@ var createModule = function() { HEAP32[buf + 32 >> 2] = 0; tempI64 = [ stat.size >>> 0, - (tempDouble = stat.size, +Math.abs(tempDouble) >= 1 ? tempDouble > 0 ? (Math.min(+Math.floor(tempDouble / 4294967296), 4294967295) | 0) >>> 0 : ~~+Math.ceil( - (tempDouble - +(~~tempDouble >>> 0)) / 4294967296 - ) >>> 0 : 0) + (tempDouble = stat.size, +Math.abs(tempDouble) >= 1 ? tempDouble > 0 ? (Math.min(+Math.floor(tempDouble / 4294967296), 4294967295) | 0) >>> 0 : ~~+Math.ceil((tempDouble - +(~~tempDouble >>> 0)) / 4294967296) >>> 0 : 0) ], HEAP32[buf + 40 >> 2] = tempI64[0], HEAP32[buf + 44 >> 2] = tempI64[1]; HEAP32[buf + 48 >> 2] = 4096; HEAP32[buf + 52 >> 2] = stat.blocks; @@ -26585,9 +26409,7 @@ var createModule = function() { HEAP32[buf + 76 >> 2] = 0; tempI64 = [ stat.ino >>> 0, - (tempDouble = stat.ino, +Math.abs(tempDouble) >= 1 ? tempDouble > 0 ? (Math.min(+Math.floor(tempDouble / 4294967296), 4294967295) | 0) >>> 0 : ~~+Math.ceil( - (tempDouble - +(~~tempDouble >>> 0)) / 4294967296 - ) >>> 0 : 0) + (tempDouble = stat.ino, +Math.abs(tempDouble) >= 1 ? tempDouble > 0 ? (Math.min(+Math.floor(tempDouble / 4294967296), 4294967295) | 0) >>> 0 : ~~+Math.ceil((tempDouble - +(~~tempDouble >>> 0)) / 4294967296) >>> 0 : 0) ], HEAP32[buf + 80 >> 2] = tempI64[0], HEAP32[buf + 84 >> 2] = tempI64[1]; return 0; }, @@ -26631,7 +26453,7 @@ var createModule = function() { return -28; } var node; - var lookup = FS.lookupPath(path, { follow: true }); + var lookup = FS.lookupPath(path, {follow: true}); node = lookup.node; if (!node) { return -44; @@ -26907,14 +26729,8 @@ var createModule = function() { } for (var cutDown = 1; cutDown <= 4; cutDown *= 2) { var overGrownHeapSize = oldSize * (1 + 0.2 / cutDown); - overGrownHeapSize = Math.min( - overGrownHeapSize, - requestedSize + 100663296 - ); - var newSize = Math.min( - maxHeapSize, - alignUp(Math.max(requestedSize, overGrownHeapSize), 65536) - ); + overGrownHeapSize = Math.min(overGrownHeapSize, requestedSize + 100663296); + var newSize = Math.min(maxHeapSize, alignUp(Math.max(requestedSize, overGrownHeapSize), 65536)); var replacement = emscripten_realloc_buffer(newSize); if (replacement) { return true; @@ -26969,9 +26785,7 @@ var createModule = function() { FS.llseek(stream, offset, whence); tempI64 = [ stream.position >>> 0, - (tempDouble = stream.position, +Math.abs(tempDouble) >= 1 ? tempDouble > 0 ? (Math.min(+Math.floor(tempDouble / 4294967296), 4294967295) | 0) >>> 0 : ~~+Math.ceil( - (tempDouble - +(~~tempDouble >>> 0)) / 4294967296 - ) >>> 0 : 0) + (tempDouble = stream.position, +Math.abs(tempDouble) >= 1 ? tempDouble > 0 ? (Math.min(+Math.floor(tempDouble / 4294967296), 4294967295) | 0) >>> 0 : ~~+Math.ceil((tempDouble - +(~~tempDouble >>> 0)) / 4294967296) >>> 0 : 0) ], HEAP32[newOffset >> 2] = tempI64[0], HEAP32[newOffset + 4 >> 2] = tempI64[1]; if (stream.getdents && offset === 0 && whence === 0) stream.getdents = null; @@ -27033,15 +26847,7 @@ var createModule = function() { } function _timegm(tmPtr) { _tzset(); - var time = Date.UTC( - HEAP32[tmPtr + 20 >> 2] + 1900, - HEAP32[tmPtr + 16 >> 2], - HEAP32[tmPtr + 12 >> 2], - HEAP32[tmPtr + 8 >> 2], - HEAP32[tmPtr + 4 >> 2], - HEAP32[tmPtr >> 2], - 0 - ); + var time = Date.UTC(HEAP32[tmPtr + 20 >> 2] + 1900, HEAP32[tmPtr + 16 >> 2], HEAP32[tmPtr + 12 >> 2], HEAP32[tmPtr + 8 >> 2], HEAP32[tmPtr + 4 >> 2], HEAP32[tmPtr >> 2], 0); var date = new Date(time); HEAP32[tmPtr + 24 >> 2] = date.getUTCDay(); var start = Date.UTC(date.getUTCFullYear(), 0, 1, 0, 0, 0, 0); @@ -27119,12 +26925,7 @@ var createModule = function() { function intArrayFromString(stringy, dontAddNull, length) { var len = length > 0 ? length : lengthBytesUTF8(stringy) + 1; var u8array = new Array(len); - var numBytesWritten = stringToUTF8Array( - stringy, - u8array, - 0, - u8array.length - ); + var numBytesWritten = stringToUTF8Array(stringy, u8array, 0, u8array.length); if (dontAddNull) u8array.length = numBytesWritten; return u8array; @@ -27137,11 +26938,7 @@ var createModule = function() { } catch (_) { buf = new Buffer(s, "base64"); } - return new Uint8Array( - buf["buffer"], - buf["byteOffset"], - buf["byteLength"] - ); + return new Uint8Array(buf["buffer"], buf["byteOffset"], buf["byteLength"]); } } function tryParseAsDataURI(filename) { @@ -27294,7 +27091,8 @@ const number64 = [ `number`, `number` ]; -var Errors = /* @__PURE__ */ ((Errors2) => { +var Errors; +(function(Errors2) { Errors2[Errors2["ZIP_ER_OK"] = 0] = "ZIP_ER_OK"; Errors2[Errors2["ZIP_ER_MULTIDISK"] = 1] = "ZIP_ER_MULTIDISK"; Errors2[Errors2["ZIP_ER_RENAME"] = 2] = "ZIP_ER_RENAME"; @@ -27327,8 +27125,7 @@ var Errors = /* @__PURE__ */ ((Errors2) => { Errors2[Errors2["ZIP_ER_INUSE"] = 29] = "ZIP_ER_INUSE"; Errors2[Errors2["ZIP_ER_TELL"] = 30] = "ZIP_ER_TELL"; Errors2[Errors2["ZIP_ER_COMPRESSED_DATA"] = 31] = "ZIP_ER_COMPRESSED_DATA"; - return Errors2; -})(Errors || {}); +})(Errors || (Errors = {})); const makeInterface = (libzip) => ({ get HEAP8() { return libzip.HEAP8; @@ -27448,7 +27245,27 @@ function getLibzipSync() { return mod; } -var ErrorCode = /* @__PURE__ */ ((ErrorCode2) => { +var __defProp$2 = Object.defineProperty; +var __defProps$1 = Object.defineProperties; +var __getOwnPropDescs$1 = Object.getOwnPropertyDescriptors; +var __getOwnPropSymbols$3 = Object.getOwnPropertySymbols; +var __hasOwnProp$3 = Object.prototype.hasOwnProperty; +var __propIsEnum$3 = Object.prototype.propertyIsEnumerable; +var __defNormalProp$2 = (obj, key, value) => key in obj ? __defProp$2(obj, key, {enumerable: true, configurable: true, writable: true, value}) : obj[key] = value; +var __spreadValues$2 = (a, b) => { + for (var prop in b || (b = {})) + if (__hasOwnProp$3.call(b, prop)) + __defNormalProp$2(a, prop, b[prop]); + if (__getOwnPropSymbols$3) + for (var prop of __getOwnPropSymbols$3(b)) { + if (__propIsEnum$3.call(b, prop)) + __defNormalProp$2(a, prop, b[prop]); + } + return a; +}; +var __spreadProps$1 = (a, b) => __defProps$1(a, __getOwnPropDescs$1(b)); +var ErrorCode; +(function(ErrorCode2) { ErrorCode2["API_ERROR"] = `API_ERROR`; ErrorCode2["BUILTIN_NODE_RESOLUTION_FAILED"] = `BUILTIN_NODE_RESOLUTION_FAILED`; ErrorCode2["EXPORTS_RESOLUTION_FAILED"] = `EXPORTS_RESOLUTION_FAILED`; @@ -27458,14 +27275,13 @@ var ErrorCode = /* @__PURE__ */ ((ErrorCode2) => { ErrorCode2["INTERNAL"] = `INTERNAL`; ErrorCode2["UNDECLARED_DEPENDENCY"] = `UNDECLARED_DEPENDENCY`; ErrorCode2["UNSUPPORTED"] = `UNSUPPORTED`; - return ErrorCode2; -})(ErrorCode || {}); -const MODULE_NOT_FOUND_ERRORS = /* @__PURE__ */ new Set([ - "BUILTIN_NODE_RESOLUTION_FAILED" /* BUILTIN_NODE_RESOLUTION_FAILED */, - "MISSING_DEPENDENCY" /* MISSING_DEPENDENCY */, - "MISSING_PEER_DEPENDENCY" /* MISSING_PEER_DEPENDENCY */, - "QUALIFIED_PATH_RESOLUTION_FAILED" /* QUALIFIED_PATH_RESOLUTION_FAILED */, - "UNDECLARED_DEPENDENCY" /* UNDECLARED_DEPENDENCY */ +})(ErrorCode || (ErrorCode = {})); +const MODULE_NOT_FOUND_ERRORS = new Set([ + ErrorCode.BUILTIN_NODE_RESOLUTION_FAILED, + ErrorCode.MISSING_DEPENDENCY, + ErrorCode.MISSING_PEER_DEPENDENCY, + ErrorCode.QUALIFIED_PATH_RESOLUTION_FAILED, + ErrorCode.UNDECLARED_DEPENDENCY ]); function makeError(pnpCode, message, data = {}, code) { code != null ? code : code = MODULE_NOT_FOUND_ERRORS.has(pnpCode) ? `MODULE_NOT_FOUND` : pnpCode; @@ -27475,18 +27291,15 @@ function makeError(pnpCode, message, data = {}, code) { enumerable: false }; return Object.defineProperties(new Error(message), { - code: { - ...propertySpec, + code: __spreadProps$1(__spreadValues$2({}, propertySpec), { value: code - }, - pnpCode: { - ...propertySpec, + }), + pnpCode: __spreadProps$1(__spreadValues$2({}, propertySpec), { value: pnpCode - }, - data: { - ...propertySpec, + }), + data: __spreadProps$1(__spreadValues$2({}, propertySpec), { value: data - } + }) }); } function getIssuerModule(parent) { @@ -27534,12 +27347,21 @@ Instead change the require of ${basename} in ${parentPath} to a dynamic import() return err; } -const shouldReportRequiredModules = process.env.WATCH_REPORT_DEPENDENCIES; -function reportModuleToWatchMode(filename) { - if (shouldReportRequiredModules && process.send) { - process.send({ "watch:require": npath.fromPortablePath(VirtualFS.resolveVirtual(npath.toPortablePath(filename))) }); - } -} +var __getOwnPropSymbols$2 = Object.getOwnPropertySymbols; +var __hasOwnProp$2 = Object.prototype.hasOwnProperty; +var __propIsEnum$2 = Object.prototype.propertyIsEnumerable; +var __objRest$1 = (source, exclude) => { + var target = {}; + for (var prop in source) + if (__hasOwnProp$2.call(source, prop) && exclude.indexOf(prop) < 0) + target[prop] = source[prop]; + if (source != null && __getOwnPropSymbols$2) + for (var prop of __getOwnPropSymbols$2(source)) { + if (exclude.indexOf(prop) < 0 && __propIsEnum$2.call(source, prop)) + target[prop] = source[prop]; + } + return target; +}; function applyPatch(pnpapi, opts) { const defaultCache = {}; let enableNativeHooks = true; @@ -27580,7 +27402,7 @@ function applyPatch(pnpapi, opts) { const modulePath = require$$0.Module._resolveFilename(request, parent, isMain); const isOwnedByRuntime = parentApi !== null ? parentApi.findPackageLocator(modulePath) !== null : false; const moduleApiPath = isOwnedByRuntime ? parentApiPath : opts.manager.findApiPathFor(npath.dirname(modulePath)); - const entry = moduleApiPath !== null ? opts.manager.getApiEntry(moduleApiPath) : { instance: null, cache: defaultCache }; + const entry = moduleApiPath !== null ? opts.manager.getApiEntry(moduleApiPath) : {instance: null, cache: defaultCache}; const cacheEntry = entry.cache[modulePath]; if (cacheEntry) { if (cacheEntry.loaded === false && cacheEntry.isLoading !== true) { @@ -27599,7 +27421,6 @@ function applyPatch(pnpapi, opts) { } const module = new require$$0.Module(modulePath, parent != null ? parent : void 0); module.pnpApiPath = moduleApiPath; - reportModuleToWatchMode(modulePath); entry.cache[modulePath] = module; if (isMain) { process.mainModule = module; @@ -27638,11 +27459,11 @@ function applyPatch(pnpapi, opts) { if (issuer !== null) { const path = npath.dirname(issuer.filename); const apiPath = opts.manager.getApiPathFromParent(issuer); - return [{ apiPath, path, module }]; + return [{apiPath, path, module}]; } else { const path = process.cwd(); const apiPath = (_a = opts.manager.findApiPathFor(npath.join(path, `[file]`))) != null ? _a : opts.manager.getApiPathFromParent(null); - return [{ apiPath, path, module }]; + return [{apiPath, path, module}]; } } function makeFakeParent(path) { @@ -27659,7 +27480,7 @@ function applyPatch(pnpapi, opts) { if (!enableNativeHooks) return originalModuleResolveFilename.call(require$$0.Module, request, parent, isMain, options); if (options && options.plugnplay === false) { - const { plugnplay, ...rest } = options; + const _a = options, rest = __objRest$1(_a, ["plugnplay"]); const forwardedOptions = Object.keys(rest).length > 0 ? rest : void 0; try { enableNativeHooks = false; @@ -27673,10 +27494,7 @@ function applyPatch(pnpapi, opts) { optionNames.delete(`paths`); optionNames.delete(`plugnplay`); if (optionNames.size > 0) { - throw makeError( - ErrorCode.UNSUPPORTED, - `Some options passed to require() aren't supported by PnP yet (${Array.from(optionNames).join(`, `)})` - ); + throw makeError(ErrorCode.UNSUPPORTED, `Some options passed to require() aren't supported by PnP yet (${Array.from(optionNames).join(`, `)})`); } } const issuerSpecs = options && options.paths ? getIssuerSpecsFromPaths(options.paths) : getIssuerSpecsFromModule(parent); @@ -27695,7 +27513,7 @@ function applyPatch(pnpapi, opts) { } } let firstError; - for (const { apiPath, path, module } of issuerSpecs) { + for (const {apiPath, path, module} of issuerSpecs) { let resolution; const issuerApi = apiPath !== null ? opts.manager.getApiEntry(apiPath, true).instance : null; try { @@ -27776,12 +27594,7 @@ Require stack: const originalDlopen = process.dlopen; process.dlopen = function(...args) { const [module, filename, ...rest] = args; - return originalDlopen.call( - this, - module, - npath.fromPortablePath(VirtualFS.resolveVirtual(npath.toPortablePath(filename))), - ...rest - ); + return originalDlopen.call(this, module, npath.fromPortablePath(VirtualFS.resolveVirtual(npath.toPortablePath(filename))), ...rest); }; const originalEmit = process.emit; process.emit = function(name, data, ...args) { @@ -27792,21 +27605,21 @@ Require stack: patchFs(fs__default.default, new PosixFS(opts.fakeFs)); } -function hydrateRuntimeState(data, { basePath }) { +function hydrateRuntimeState(data, {basePath}) { const portablePath = npath.toPortablePath(basePath); const absolutePortablePath = ppath.resolve(portablePath); const ignorePattern = data.ignorePatternData !== null ? new RegExp(data.ignorePatternData) : null; - const packageLocatorsByLocations = /* @__PURE__ */ new Map(); + const packageLocatorsByLocations = new Map(); const packageRegistry = new Map(data.packageRegistryData.map(([packageName, packageStoreData]) => { return [packageName, new Map(packageStoreData.map(([packageReference, packageInformationData]) => { var _a; if (packageName === null !== (packageReference === null)) throw new Error(`Assertion failed: The name and reference should be null, or neither should`); const discardFromLookup = (_a = packageInformationData.discardFromLookup) != null ? _a : false; - const packageLocator = { name: packageName, reference: packageReference }; + const packageLocator = {name: packageName, reference: packageReference}; const entry = packageLocatorsByLocations.get(packageInformationData.packageLocation); if (!entry) { - packageLocatorsByLocations.set(packageInformationData.packageLocation, { locator: packageLocator, discardFromLookup }); + packageLocatorsByLocations.set(packageInformationData.packageLocation, {locator: packageLocator, discardFromLookup}); } else { entry.discardFromLookup = entry.discardFromLookup && discardFromLookup; if (!discardFromLookup) { @@ -27955,459 +27768,25 @@ function resolve(pkg, entry='.', options={}) { } } -const ArrayIsArray = Array.isArray; -const JSONStringify = JSON.stringify; -const ObjectGetOwnPropertyNames = Object.getOwnPropertyNames; -const ObjectPrototypeHasOwnProperty = (obj, prop) => Object.prototype.hasOwnProperty.call(obj, prop); -const RegExpPrototypeExec = (obj, string) => RegExp.prototype.exec.call(obj, string); -const RegExpPrototypeSymbolReplace = (obj, ...rest) => RegExp.prototype[Symbol.replace].apply(obj, rest); -const StringPrototypeEndsWith = (str, ...rest) => String.prototype.endsWith.apply(str, rest); -const StringPrototypeIncludes = (str, ...rest) => String.prototype.includes.apply(str, rest); -const StringPrototypeLastIndexOf = (str, ...rest) => String.prototype.lastIndexOf.apply(str, rest); -const StringPrototypeIndexOf = (str, ...rest) => String.prototype.indexOf.apply(str, rest); -const StringPrototypeReplace = (str, ...rest) => String.prototype.replace.apply(str, rest); -const StringPrototypeSlice = (str, ...rest) => String.prototype.slice.apply(str, rest); -const StringPrototypeStartsWith = (str, ...rest) => String.prototype.startsWith.apply(str, rest); -const SafeMap = Map; -const JSONParse = JSON.parse; - -function createErrorType(code, messageCreator, errorType) { - return class extends errorType { - constructor(...args) { - super(messageCreator(...args)); - this.code = code; - this.name = `${errorType.name} [${code}]`; - } - }; -} -const ERR_PACKAGE_IMPORT_NOT_DEFINED = createErrorType( - `ERR_PACKAGE_IMPORT_NOT_DEFINED`, - (specifier, packagePath, base) => { - return `Package import specifier "${specifier}" is not defined${packagePath ? ` in package ${packagePath}package.json` : ``} imported from ${base}`; - }, - TypeError -); -const ERR_INVALID_MODULE_SPECIFIER = createErrorType( - `ERR_INVALID_MODULE_SPECIFIER`, - (request, reason, base = void 0) => { - return `Invalid module "${request}" ${reason}${base ? ` imported from ${base}` : ``}`; - }, - TypeError -); -const ERR_INVALID_PACKAGE_TARGET = createErrorType( - `ERR_INVALID_PACKAGE_TARGET`, - (pkgPath, key, target, isImport = false, base = void 0) => { - const relError = typeof target === `string` && !isImport && target.length && !StringPrototypeStartsWith(target, `./`); - if (key === `.`) { - assert__default.default(isImport === false); - return `Invalid "exports" main target ${JSONStringify(target)} defined in the package config ${pkgPath}package.json${base ? ` imported from ${base}` : ``}${relError ? `; targets must start with "./"` : ``}`; - } - return `Invalid "${isImport ? `imports` : `exports`}" target ${JSONStringify( - target - )} defined for '${key}' in the package config ${pkgPath}package.json${base ? ` imported from ${base}` : ``}${relError ? `; targets must start with "./"` : ``}`; - }, - Error -); -const ERR_INVALID_PACKAGE_CONFIG = createErrorType( - `ERR_INVALID_PACKAGE_CONFIG`, - (path, base, message) => { - return `Invalid package config ${path}${base ? ` while importing ${base}` : ``}${message ? `. ${message}` : ``}`; - }, - Error -); - -function filterOwnProperties(source, keys) { - const filtered = /* @__PURE__ */ Object.create(null); - for (let i = 0; i < keys.length; i++) { - const key = keys[i]; - if (ObjectPrototypeHasOwnProperty(source, key)) { - filtered[key] = source[key]; - } - } - return filtered; -} - -const packageJSONCache = new SafeMap(); -function getPackageConfig(path, specifier, base, readFileSyncFn) { - const existing = packageJSONCache.get(path); - if (existing !== void 0) { - return existing; - } - const source = readFileSyncFn(path); - if (source === void 0) { - const packageConfig2 = { - pjsonPath: path, - exists: false, - main: void 0, - name: void 0, - type: "none", - exports: void 0, - imports: void 0 - }; - packageJSONCache.set(path, packageConfig2); - return packageConfig2; - } - let packageJSON; - try { - packageJSON = JSONParse(source); - } catch (error) { - throw new ERR_INVALID_PACKAGE_CONFIG( - path, - (base ? `"${specifier}" from ` : "") + url.fileURLToPath(base || specifier), - error.message - ); - } - let { imports, main, name, type } = filterOwnProperties(packageJSON, [ - "imports", - "main", - "name", - "type" - ]); - const exports = ObjectPrototypeHasOwnProperty(packageJSON, "exports") ? packageJSON.exports : void 0; - if (typeof imports !== "object" || imports === null) { - imports = void 0; - } - if (typeof main !== "string") { - main = void 0; - } - if (typeof name !== "string") { - name = void 0; - } - if (type !== "module" && type !== "commonjs") { - type = "none"; - } - const packageConfig = { - pjsonPath: path, - exists: true, - main, - name, - type, - exports, - imports - }; - packageJSONCache.set(path, packageConfig); - return packageConfig; -} -function getPackageScopeConfig(resolved, readFileSyncFn) { - let packageJSONUrl = new URL("./package.json", resolved); - while (true) { - const packageJSONPath2 = packageJSONUrl.pathname; - if (StringPrototypeEndsWith(packageJSONPath2, "node_modules/package.json")) { - break; - } - const packageConfig2 = getPackageConfig( - url.fileURLToPath(packageJSONUrl), - resolved, - void 0, - readFileSyncFn - ); - if (packageConfig2.exists) { - return packageConfig2; - } - const lastPackageJSONUrl = packageJSONUrl; - packageJSONUrl = new URL("../package.json", packageJSONUrl); - if (packageJSONUrl.pathname === lastPackageJSONUrl.pathname) { - break; - } - } - const packageJSONPath = url.fileURLToPath(packageJSONUrl); - const packageConfig = { - pjsonPath: packageJSONPath, - exists: false, - main: void 0, - name: void 0, - type: "none", - exports: void 0, - imports: void 0 - }; - packageJSONCache.set(packageJSONPath, packageConfig); - return packageConfig; -} - -/** - @license - Copyright Node.js contributors. All rights reserved. - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to - deal in the Software without restriction, including without limitation the - rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - sell copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - IN THE SOFTWARE. -*/ -function throwImportNotDefined(specifier, packageJSONUrl, base) { - throw new ERR_PACKAGE_IMPORT_NOT_DEFINED( - specifier, - packageJSONUrl && url.fileURLToPath(new URL(".", packageJSONUrl)), - url.fileURLToPath(base) - ); -} -function throwInvalidSubpath(subpath, packageJSONUrl, internal, base) { - const reason = `request is not a valid subpath for the "${internal ? "imports" : "exports"}" resolution of ${url.fileURLToPath(packageJSONUrl)}`; - throw new ERR_INVALID_MODULE_SPECIFIER( - subpath, - reason, - base && url.fileURLToPath(base) - ); -} -function throwInvalidPackageTarget(subpath, target, packageJSONUrl, internal, base) { - if (typeof target === "object" && target !== null) { - target = JSONStringify(target, null, ""); - } else { - target = `${target}`; - } - throw new ERR_INVALID_PACKAGE_TARGET( - url.fileURLToPath(new URL(".", packageJSONUrl)), - subpath, - target, - internal, - base && url.fileURLToPath(base) - ); -} -const invalidSegmentRegEx = /(^|\\|\/)((\.|%2e)(\.|%2e)?|(n|%6e|%4e)(o|%6f|%4f)(d|%64|%44)(e|%65|%45)(_|%5f)(m|%6d|%4d)(o|%6f|%4f)(d|%64|%44)(u|%75|%55)(l|%6c|%4c)(e|%65|%45)(s|%73|%53))(\\|\/|$)/i; -const patternRegEx = /\*/g; -function resolvePackageTargetString(target, subpath, match, packageJSONUrl, base, pattern, internal, conditions) { - if (subpath !== "" && !pattern && target[target.length - 1] !== "/") - throwInvalidPackageTarget(match, target, packageJSONUrl, internal, base); - if (!StringPrototypeStartsWith(target, "./")) { - if (internal && !StringPrototypeStartsWith(target, "../") && !StringPrototypeStartsWith(target, "/")) { - let isURL = false; - try { - new URL(target); - isURL = true; - } catch { - } - if (!isURL) { - const exportTarget = pattern ? RegExpPrototypeSymbolReplace(patternRegEx, target, () => subpath) : target + subpath; - return exportTarget; - } - } - throwInvalidPackageTarget(match, target, packageJSONUrl, internal, base); - } - if (RegExpPrototypeExec( - invalidSegmentRegEx, - StringPrototypeSlice(target, 2) - ) !== null) - throwInvalidPackageTarget(match, target, packageJSONUrl, internal, base); - const resolved = new URL(target, packageJSONUrl); - const resolvedPath = resolved.pathname; - const packagePath = new URL(".", packageJSONUrl).pathname; - if (!StringPrototypeStartsWith(resolvedPath, packagePath)) - throwInvalidPackageTarget(match, target, packageJSONUrl, internal, base); - if (subpath === "") - return resolved; - if (RegExpPrototypeExec(invalidSegmentRegEx, subpath) !== null) { - const request = pattern ? StringPrototypeReplace(match, "*", () => subpath) : match + subpath; - throwInvalidSubpath(request, packageJSONUrl, internal, base); - } - if (pattern) { - return new URL( - RegExpPrototypeSymbolReplace(patternRegEx, resolved.href, () => subpath) - ); - } - return new URL(subpath, resolved); -} -function isArrayIndex(key) { - const keyNum = +key; - if (`${keyNum}` !== key) - return false; - return keyNum >= 0 && keyNum < 4294967295; -} -function resolvePackageTarget(packageJSONUrl, target, subpath, packageSubpath, base, pattern, internal, conditions) { - if (typeof target === "string") { - return resolvePackageTargetString( - target, - subpath, - packageSubpath, - packageJSONUrl, - base, - pattern, - internal); - } else if (ArrayIsArray(target)) { - if (target.length === 0) { - return null; - } - let lastException; - for (let i = 0; i < target.length; i++) { - const targetItem = target[i]; - let resolveResult; - try { - resolveResult = resolvePackageTarget( - packageJSONUrl, - targetItem, - subpath, - packageSubpath, - base, - pattern, - internal, - conditions - ); - } catch (e) { - lastException = e; - if (e.code === "ERR_INVALID_PACKAGE_TARGET") { - continue; - } - throw e; - } - if (resolveResult === void 0) { - continue; - } - if (resolveResult === null) { - lastException = null; - continue; - } - return resolveResult; - } - if (lastException === void 0 || lastException === null) - return lastException; - throw lastException; - } else if (typeof target === "object" && target !== null) { - const keys = ObjectGetOwnPropertyNames(target); - for (let i = 0; i < keys.length; i++) { - const key = keys[i]; - if (isArrayIndex(key)) { - throw new ERR_INVALID_PACKAGE_CONFIG( - url.fileURLToPath(packageJSONUrl), - base, - '"exports" cannot contain numeric property keys.' - ); - } - } - for (let i = 0; i < keys.length; i++) { - const key = keys[i]; - if (key === "default" || conditions.has(key)) { - const conditionalTarget = target[key]; - const resolveResult = resolvePackageTarget( - packageJSONUrl, - conditionalTarget, - subpath, - packageSubpath, - base, - pattern, - internal, - conditions - ); - if (resolveResult === void 0) - continue; - return resolveResult; - } +var __defProp$1 = Object.defineProperty; +var __defProps = Object.defineProperties; +var __getOwnPropDescs = Object.getOwnPropertyDescriptors; +var __getOwnPropSymbols$1 = Object.getOwnPropertySymbols; +var __hasOwnProp$1 = Object.prototype.hasOwnProperty; +var __propIsEnum$1 = Object.prototype.propertyIsEnumerable; +var __defNormalProp$1 = (obj, key, value) => key in obj ? __defProp$1(obj, key, {enumerable: true, configurable: true, writable: true, value}) : obj[key] = value; +var __spreadValues$1 = (a, b) => { + for (var prop in b || (b = {})) + if (__hasOwnProp$1.call(b, prop)) + __defNormalProp$1(a, prop, b[prop]); + if (__getOwnPropSymbols$1) + for (var prop of __getOwnPropSymbols$1(b)) { + if (__propIsEnum$1.call(b, prop)) + __defNormalProp$1(a, prop, b[prop]); } - return void 0; - } else if (target === null) { - return null; - } - throwInvalidPackageTarget( - packageSubpath, - target, - packageJSONUrl, - internal, - base - ); -} -function patternKeyCompare(a, b) { - const aPatternIndex = StringPrototypeIndexOf(a, "*"); - const bPatternIndex = StringPrototypeIndexOf(b, "*"); - const baseLenA = aPatternIndex === -1 ? a.length : aPatternIndex + 1; - const baseLenB = bPatternIndex === -1 ? b.length : bPatternIndex + 1; - if (baseLenA > baseLenB) - return -1; - if (baseLenB > baseLenA) - return 1; - if (aPatternIndex === -1) - return 1; - if (bPatternIndex === -1) - return -1; - if (a.length > b.length) - return -1; - if (b.length > a.length) - return 1; - return 0; -} -function packageImportsResolve({ - name, - base, - conditions, - readFileSyncFn -}) { - if (name === "#" || StringPrototypeStartsWith(name, "#/") || StringPrototypeEndsWith(name, "/")) { - const reason = "is not a valid internal imports specifier name"; - throw new ERR_INVALID_MODULE_SPECIFIER(name, reason, url.fileURLToPath(base)); - } - let packageJSONUrl; - const packageConfig = getPackageScopeConfig(base, readFileSyncFn); - if (packageConfig.exists) { - packageJSONUrl = url.pathToFileURL(packageConfig.pjsonPath); - const imports = packageConfig.imports; - if (imports) { - if (ObjectPrototypeHasOwnProperty(imports, name) && !StringPrototypeIncludes(name, "*")) { - const resolveResult = resolvePackageTarget( - packageJSONUrl, - imports[name], - "", - name, - base, - false, - true, - conditions - ); - if (resolveResult != null) { - return resolveResult; - } - } else { - let bestMatch = ""; - let bestMatchSubpath; - const keys = ObjectGetOwnPropertyNames(imports); - for (let i = 0; i < keys.length; i++) { - const key = keys[i]; - const patternIndex = StringPrototypeIndexOf(key, "*"); - if (patternIndex !== -1 && StringPrototypeStartsWith( - name, - StringPrototypeSlice(key, 0, patternIndex) - )) { - const patternTrailer = StringPrototypeSlice(key, patternIndex + 1); - if (name.length >= key.length && StringPrototypeEndsWith(name, patternTrailer) && patternKeyCompare(bestMatch, key) === 1 && StringPrototypeLastIndexOf(key, "*") === patternIndex) { - bestMatch = key; - bestMatchSubpath = StringPrototypeSlice( - name, - patternIndex, - name.length - patternTrailer.length - ); - } - } - } - if (bestMatch) { - const target = imports[bestMatch]; - const resolveResult = resolvePackageTarget( - packageJSONUrl, - target, - bestMatchSubpath, - bestMatch, - base, - true, - true, - conditions - ); - if (resolveResult != null) { - return resolveResult; - } - } - } - } - } - throwImportNotDefined(name, packageJSONUrl, base); -} - + return a; +}; +var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b)); function makeApi(runtimeState, opts) { const alwaysWarnOnFallback = Number(process.env.PNP_ALWAYS_WARN_ON_FALLBACK) > 0; const debugLevel = Number(process.env.PNP_DEBUG_LEVEL); @@ -28415,9 +27794,9 @@ function makeApi(runtimeState, opts) { const isStrictRegExp = /^(\/|\.{1,2}(\/|$))/; const isDirRegExp = /\/$/; const isRelativeRegexp = /^\.{0,2}\//; - const topLevelLocator = { name: null, reference: null }; + const topLevelLocator = {name: null, reference: null}; const fallbackLocators = []; - const emittedWarnings = /* @__PURE__ */ new Set(); + const emittedWarnings = new Set(); if (runtimeState.enableTopLevelFallback === true) fallbackLocators.push(topLevelLocator); if (opts.compatibilityMode !== false) { @@ -28428,7 +27807,7 @@ function makeApi(runtimeState, opts) { if (reference === null) { throw new Error(`Assertion failed: This reference shouldn't be null`); } else { - fallbackLocators.push({ name, reference }); + fallbackLocators.push({name, reference}); } } } @@ -28450,7 +27829,7 @@ function makeApi(runtimeState, opts) { function trace(entry) { var _a, _b, _c, _d, _e, _f; const colors = (_c = (_b = (_a = process.stderr) == null ? void 0 : _a.hasColors) == null ? void 0 : _b.call(_a)) != null ? _c : process.stdout.isTTY; - const c = (n, str) => `\x1B[${n}m${str}\x1B[0m`; + const c = (n, str) => `[${n}m${str}`; const error = entry.error; if (error) console.error(c(`31;1`, `\u2716 ${(_d = entry.error) == null ? void 0 : _d.message.replace(/\n.*/s, ``)}`)); @@ -28459,10 +27838,10 @@ function makeApi(runtimeState, opts) { if (entry.args.length > 0) console.error(); for (const arg of entry.args) - console.error(` ${c(`37;1`, `In \u2190`)} ${nodeUtils.inspect(arg, { colors, compact: true })}`); + console.error(` ${c(`37;1`, `In \u2190`)} ${nodeUtils.inspect(arg, {colors, compact: true})}`); if (entry.result) { console.error(); - console.error(` ${c(`37;1`, `Out \u2192`)} ${nodeUtils.inspect(entry.result, { colors, compact: true })}`); + console.error(` ${c(`37;1`, `Out \u2192`)} ${nodeUtils.inspect(entry.result, {colors, compact: true})}`); } const stack = (_f = (_e = new Error().stack.match(/(?<=^ +)at.*/gm)) == null ? void 0 : _e.slice(2)) != null ? _f : []; if (stack.length > 0) { @@ -28506,10 +27885,7 @@ function makeApi(runtimeState, opts) { function getPackageInformationSafe(packageLocator) { const packageInformation = getPackageInformation(packageLocator); if (!packageInformation) { - throw makeError( - ErrorCode.INTERNAL, - `Couldn't find a matching entry in the dependency tree for the specified parent (this is probably an internal error)` - ); + throw makeError(ErrorCode.INTERNAL, `Couldn't find a matching entry in the dependency tree for the specified parent (this is probably an internal error)`); } return packageInformation; } @@ -28521,29 +27897,23 @@ function makeApi(runtimeState, opts) { return true; return false; } - const defaultExportsConditions = /* @__PURE__ */ new Set([`default`, `node`, `require`]); + const defaultExportsConditions = new Set([`default`, `node`, `require`]); function applyNodeExportsResolution(unqualifiedPath, conditions = defaultExportsConditions) { const locator = findPackageLocator(ppath.join(unqualifiedPath, `internal.js`), { resolveIgnored: true, includeDiscardFromLookup: true }); if (locator === null) { - throw makeError( - ErrorCode.INTERNAL, - `The locator that owns the "${unqualifiedPath}" path can't be found inside the dependency tree (this is probably an internal error)` - ); + throw makeError(ErrorCode.INTERNAL, `The locator that owns the "${unqualifiedPath}" path can't be found inside the dependency tree (this is probably an internal error)`); } - const { packageLocation } = getPackageInformationSafe(locator); + const {packageLocation} = getPackageInformationSafe(locator); const manifestPath = ppath.join(packageLocation, Filename.manifest); if (!opts.fakeFs.existsSync(manifestPath)) return null; const pkgJson = JSON.parse(opts.fakeFs.readFileSync(manifestPath, `utf8`)); let subpath = ppath.contains(packageLocation, unqualifiedPath); if (subpath === null) { - throw makeError( - ErrorCode.INTERNAL, - `unqualifiedPath doesn't contain the packageLocation (this is probably an internal error)` - ); + throw makeError(ErrorCode.INTERNAL, `unqualifiedPath doesn't contain the packageLocation (this is probably an internal error)`); } if (!isRelativeRegexp.test(subpath)) subpath = `./${subpath}`; @@ -28554,18 +27924,13 @@ function makeApi(runtimeState, opts) { unsafe: true }); } catch (error) { - throw makeError( - ErrorCode.EXPORTS_RESOLUTION_FAILED, - error.message, - { unqualifiedPath: getPathForDisplay(unqualifiedPath), locator, pkgJson, subpath: getPathForDisplay(subpath), conditions }, - `ERR_PACKAGE_PATH_NOT_EXPORTED` - ); + throw makeError(ErrorCode.EXPORTS_RESOLUTION_FAILED, error.message, {unqualifiedPath: getPathForDisplay(unqualifiedPath), locator, pkgJson, subpath: getPathForDisplay(subpath), conditions}, `ERR_PACKAGE_PATH_NOT_EXPORTED`); } if (typeof resolvedExport === `string`) return ppath.join(packageLocation, resolvedExport); return null; } - function applyNodeExtensionResolution(unqualifiedPath, candidates, { extensions }) { + function applyNodeExtensionResolution(unqualifiedPath, candidates, {extensions}) { let stat; try { candidates.push(unqualifiedPath); @@ -28584,7 +27949,7 @@ function makeApi(runtimeState, opts) { if (pkgJson && pkgJson.main) nextUnqualifiedPath = ppath.resolve(unqualifiedPath, pkgJson.main); if (nextUnqualifiedPath && nextUnqualifiedPath !== unqualifiedPath) { - const resolution = applyNodeExtensionResolution(nextUnqualifiedPath, candidates, { extensions }); + const resolution = applyNodeExtensionResolution(nextUnqualifiedPath, candidates, {extensions}); if (resolution !== null) { return resolution; } @@ -28599,7 +27964,7 @@ function makeApi(runtimeState, opts) { } if (stat && stat.isDirectory()) { for (let i = 0, length = extensions.length; i < length; i++) { - const candidateFile = ppath.format({ dir: unqualifiedPath, name: `index`, ext: extensions[i] }); + const candidateFile = ppath.format({dir: unqualifiedPath, name: `index`, ext: extensions[i]}); candidates.push(candidateFile); if (opts.fakeFs.existsSync(candidateFile)) { return candidateFile; @@ -28617,7 +27982,7 @@ function makeApi(runtimeState, opts) { function callNativeResolution(request, issuer) { if (issuer.endsWith(`/`)) issuer = ppath.join(issuer, `internal.js`); - return require$$0.Module._resolveFilename(npath.fromPortablePath(request), makeFakeModule(npath.fromPortablePath(issuer)), false, { plugnplay: false }); + return require$$0.Module._resolveFilename(npath.fromPortablePath(request), makeFakeModule(npath.fromPortablePath(issuer)), false, {plugnplay: false}); } function isPathIgnored(path) { if (ignorePattern === null) @@ -28631,9 +27996,9 @@ function makeApi(runtimeState, opts) { return false; } } - const VERSIONS = { std: 3, resolveVirtual: 1, getAllLocators: 1 }; + const VERSIONS = {std: 3, resolveVirtual: 1, getAllLocators: 1}; const topLevel = topLevelLocator; - function getPackageInformation({ name, reference }) { + function getPackageInformation({name, reference}) { const packageInformationStore = packageRegistry.get(name); if (!packageInformationStore) return null; @@ -28642,7 +28007,7 @@ function makeApi(runtimeState, opts) { return null; return packageInformation; } - function findPackageDependents({ name, reference }) { + function findPackageDependents({name, reference}) { const dependents = []; for (const [dependentName, packageInformationStore] of packageRegistry) { if (dependentName === null) @@ -28664,8 +28029,8 @@ function makeApi(runtimeState, opts) { return dependents; } function findBrokenPeerDependencies(dependency, initialPackage) { - const brokenPackages = /* @__PURE__ */ new Map(); - const alreadyVisited = /* @__PURE__ */ new Set(); + const brokenPackages = new Map(); + const alreadyVisited = new Set(); const traversal = (currentPackage) => { const identifier = JSON.stringify(currentPackage.name); if (alreadyVisited.has(identifier)) @@ -28679,7 +28044,7 @@ function makeApi(runtimeState, opts) { } else { let brokenSet = brokenPackages.get(dependent.name); if (typeof brokenSet === `undefined`) - brokenPackages.set(dependent.name, brokenSet = /* @__PURE__ */ new Set()); + brokenPackages.set(dependent.name, brokenSet = new Set()); brokenSet.add(dependent.reference); } } @@ -28688,10 +28053,10 @@ function makeApi(runtimeState, opts) { const brokenList = []; for (const name of [...brokenPackages.keys()].sort()) for (const reference of [...brokenPackages.get(name)].sort()) - brokenList.push({ name, reference }); + brokenList.push({name, reference}); return brokenList; } - function findPackageLocator(location, { resolveIgnored = false, includeDiscardFromLookup = false } = {}) { + function findPackageLocator(location, {resolveIgnored = false, includeDiscardFromLookup = false} = {}) { if (isPathIgnored(location) && !resolveIgnored) return null; let relativeLocation = ppath.relative(runtimeState.basePath, location); @@ -28709,18 +28074,7 @@ function makeApi(runtimeState, opts) { } while (relativeLocation !== ``); return null; } - function tryReadFile(filePath) { - try { - return opts.fakeFs.readFileSync(npath.toPortablePath(filePath), `utf8`); - } catch (err) { - if (err.code === `ENOENT`) - return void 0; - throw err; - } - } - function resolveToUnqualified(request, issuer, { considerBuiltins = true } = {}) { - if (request.startsWith(`#`)) - throw new Error(`resolveToUnqualified can not handle private import mappings`); + function resolveToUnqualified(request, issuer, {considerBuiltins = true} = {}) { if (request === `pnpapi`) return npath.toPortablePath(opts.pnpapiResolution); if (considerBuiltins && isBuiltinModule(request)) @@ -28731,15 +28085,11 @@ function makeApi(runtimeState, opts) { if (!ppath.isAbsolute(request) || findPackageLocator(request) === null) { const result = callNativeResolution(request, issuer); if (result === false) { - throw makeError( - ErrorCode.BUILTIN_NODE_RESOLUTION_FAILED, - `The builtin node resolution algorithm was unable to resolve the requested module (it didn't go through the pnp resolver because the issuer was explicitely ignored by the regexp) + throw makeError(ErrorCode.BUILTIN_NODE_RESOLUTION_FAILED, `The builtin node resolution algorithm was unable to resolve the requested module (it didn't go through the pnp resolver because the issuer was explicitely ignored by the regexp) Require request: "${requestForDisplay}" Required by: ${issuerForDisplay} -`, - { request: requestForDisplay, issuer: issuerForDisplay } - ); +`, {request: requestForDisplay, issuer: issuerForDisplay}); } return npath.toPortablePath(result); } @@ -28751,11 +28101,7 @@ Required by: ${issuerForDisplay} unqualifiedPath = ppath.normalize(request); } else { if (!issuer) { - throw makeError( - ErrorCode.API_ERROR, - `The resolveToUnqualified function must be called with a valid issuer when the path isn't a builtin nor absolute`, - { request: requestForDisplay, issuer: issuerForDisplay } - ); + throw makeError(ErrorCode.API_ERROR, `The resolveToUnqualified function must be called with a valid issuer when the path isn't a builtin nor absolute`, {request: requestForDisplay, issuer: issuerForDisplay}); } const absoluteIssuer = ppath.resolve(issuer); if (issuer.match(isDirRegExp)) { @@ -28766,26 +28112,18 @@ Required by: ${issuerForDisplay} } } else { if (!issuer) { - throw makeError( - ErrorCode.API_ERROR, - `The resolveToUnqualified function must be called with a valid issuer when the path isn't a builtin nor absolute`, - { request: requestForDisplay, issuer: issuerForDisplay } - ); + throw makeError(ErrorCode.API_ERROR, `The resolveToUnqualified function must be called with a valid issuer when the path isn't a builtin nor absolute`, {request: requestForDisplay, issuer: issuerForDisplay}); } const [, dependencyName, subPath] = dependencyNameMatch; const issuerLocator = findPackageLocator(issuer); if (!issuerLocator) { const result = callNativeResolution(request, issuer); if (result === false) { - throw makeError( - ErrorCode.BUILTIN_NODE_RESOLUTION_FAILED, - `The builtin node resolution algorithm was unable to resolve the requested module (it didn't go through the pnp resolver because the issuer doesn't seem to be part of the Yarn-managed dependency tree). + throw makeError(ErrorCode.BUILTIN_NODE_RESOLUTION_FAILED, `The builtin node resolution algorithm was unable to resolve the requested module (it didn't go through the pnp resolver because the issuer doesn't seem to be part of the Yarn-managed dependency tree). Require path: "${requestForDisplay}" Required by: ${issuerForDisplay} -`, - { request: requestForDisplay, issuer: issuerForDisplay } - ); +`, {request: requestForDisplay, issuer: issuerForDisplay}); } return npath.toPortablePath(result); } @@ -28822,88 +28160,60 @@ Required by: ${issuerForDisplay} let error = null; if (dependencyReference === null) { if (isDependencyTreeRoot(issuerLocator)) { - error = makeError( - ErrorCode.MISSING_PEER_DEPENDENCY, - `Your application tried to access ${dependencyName} (a peer dependency); this isn't allowed as there is no ancestor to satisfy the requirement. Use a devDependency if needed. + error = makeError(ErrorCode.MISSING_PEER_DEPENDENCY, `Your application tried to access ${dependencyName} (a peer dependency); this isn't allowed as there is no ancestor to satisfy the requirement. Use a devDependency if needed. Required package: ${dependencyName}${dependencyName !== requestForDisplay ? ` (via "${requestForDisplay}")` : ``} Required by: ${issuerForDisplay} -`, - { request: requestForDisplay, issuer: issuerForDisplay, dependencyName } - ); +`, {request: requestForDisplay, issuer: issuerForDisplay, dependencyName}); } else { const brokenAncestors = findBrokenPeerDependencies(dependencyName, issuerLocator); if (brokenAncestors.every((ancestor) => isDependencyTreeRoot(ancestor))) { - error = makeError( - ErrorCode.MISSING_PEER_DEPENDENCY, - `${issuerLocator.name} tried to access ${dependencyName} (a peer dependency) but it isn't provided by your application; this makes the require call ambiguous and unsound. + error = makeError(ErrorCode.MISSING_PEER_DEPENDENCY, `${issuerLocator.name} tried to access ${dependencyName} (a peer dependency) but it isn't provided by your application; this makes the require call ambiguous and unsound. Required package: ${dependencyName}${dependencyName !== requestForDisplay ? ` (via "${requestForDisplay}")` : ``} Required by: ${issuerLocator.name}@${issuerLocator.reference} (via ${issuerForDisplay}) ${brokenAncestors.map((ancestorLocator) => `Ancestor breaking the chain: ${ancestorLocator.name}@${ancestorLocator.reference} `).join(``)} -`, - { request: requestForDisplay, issuer: issuerForDisplay, issuerLocator: Object.assign({}, issuerLocator), dependencyName, brokenAncestors } - ); +`, {request: requestForDisplay, issuer: issuerForDisplay, issuerLocator: Object.assign({}, issuerLocator), dependencyName, brokenAncestors}); } else { - error = makeError( - ErrorCode.MISSING_PEER_DEPENDENCY, - `${issuerLocator.name} tried to access ${dependencyName} (a peer dependency) but it isn't provided by its ancestors; this makes the require call ambiguous and unsound. + error = makeError(ErrorCode.MISSING_PEER_DEPENDENCY, `${issuerLocator.name} tried to access ${dependencyName} (a peer dependency) but it isn't provided by its ancestors; this makes the require call ambiguous and unsound. Required package: ${dependencyName}${dependencyName !== requestForDisplay ? ` (via "${requestForDisplay}")` : ``} Required by: ${issuerLocator.name}@${issuerLocator.reference} (via ${issuerForDisplay}) ${brokenAncestors.map((ancestorLocator) => `Ancestor breaking the chain: ${ancestorLocator.name}@${ancestorLocator.reference} `).join(``)} -`, - { request: requestForDisplay, issuer: issuerForDisplay, issuerLocator: Object.assign({}, issuerLocator), dependencyName, brokenAncestors } - ); +`, {request: requestForDisplay, issuer: issuerForDisplay, issuerLocator: Object.assign({}, issuerLocator), dependencyName, brokenAncestors}); } } } else if (dependencyReference === void 0) { if (!considerBuiltins && isBuiltinModule(request)) { if (isDependencyTreeRoot(issuerLocator)) { - error = makeError( - ErrorCode.UNDECLARED_DEPENDENCY, - `Your application tried to access ${dependencyName}. While this module is usually interpreted as a Node builtin, your resolver is running inside a non-Node resolution context where such builtins are ignored. Since ${dependencyName} isn't otherwise declared in your dependencies, this makes the require call ambiguous and unsound. + error = makeError(ErrorCode.UNDECLARED_DEPENDENCY, `Your application tried to access ${dependencyName}. While this module is usually interpreted as a Node builtin, your resolver is running inside a non-Node resolution context where such builtins are ignored. Since ${dependencyName} isn't otherwise declared in your dependencies, this makes the require call ambiguous and unsound. Required package: ${dependencyName}${dependencyName !== requestForDisplay ? ` (via "${requestForDisplay}")` : ``} Required by: ${issuerForDisplay} -`, - { request: requestForDisplay, issuer: issuerForDisplay, dependencyName } - ); +`, {request: requestForDisplay, issuer: issuerForDisplay, dependencyName}); } else { - error = makeError( - ErrorCode.UNDECLARED_DEPENDENCY, - `${issuerLocator.name} tried to access ${dependencyName}. While this module is usually interpreted as a Node builtin, your resolver is running inside a non-Node resolution context where such builtins are ignored. Since ${dependencyName} isn't otherwise declared in ${issuerLocator.name}'s dependencies, this makes the require call ambiguous and unsound. + error = makeError(ErrorCode.UNDECLARED_DEPENDENCY, `${issuerLocator.name} tried to access ${dependencyName}. While this module is usually interpreted as a Node builtin, your resolver is running inside a non-Node resolution context where such builtins are ignored. Since ${dependencyName} isn't otherwise declared in ${issuerLocator.name}'s dependencies, this makes the require call ambiguous and unsound. Required package: ${dependencyName}${dependencyName !== requestForDisplay ? ` (via "${requestForDisplay}")` : ``} Required by: ${issuerForDisplay} -`, - { request: requestForDisplay, issuer: issuerForDisplay, issuerLocator: Object.assign({}, issuerLocator), dependencyName } - ); +`, {request: requestForDisplay, issuer: issuerForDisplay, issuerLocator: Object.assign({}, issuerLocator), dependencyName}); } } else { if (isDependencyTreeRoot(issuerLocator)) { - error = makeError( - ErrorCode.UNDECLARED_DEPENDENCY, - `Your application tried to access ${dependencyName}, but it isn't declared in your dependencies; this makes the require call ambiguous and unsound. + error = makeError(ErrorCode.UNDECLARED_DEPENDENCY, `Your application tried to access ${dependencyName}, but it isn't declared in your dependencies; this makes the require call ambiguous and unsound. Required package: ${dependencyName}${dependencyName !== requestForDisplay ? ` (via "${requestForDisplay}")` : ``} Required by: ${issuerForDisplay} -`, - { request: requestForDisplay, issuer: issuerForDisplay, dependencyName } - ); +`, {request: requestForDisplay, issuer: issuerForDisplay, dependencyName}); } else { - error = makeError( - ErrorCode.UNDECLARED_DEPENDENCY, - `${issuerLocator.name} tried to access ${dependencyName}, but it isn't declared in its dependencies; this makes the require call ambiguous and unsound. + error = makeError(ErrorCode.UNDECLARED_DEPENDENCY, `${issuerLocator.name} tried to access ${dependencyName}, but it isn't declared in its dependencies; this makes the require call ambiguous and unsound. Required package: ${dependencyName}${dependencyName !== requestForDisplay ? ` (via "${requestForDisplay}")` : ``} Required by: ${issuerLocator.name}@${issuerLocator.reference} (via ${issuerForDisplay}) -`, - { request: requestForDisplay, issuer: issuerForDisplay, issuerLocator: Object.assign({}, issuerLocator), dependencyName } - ); +`, {request: requestForDisplay, issuer: issuerForDisplay, issuerLocator: Object.assign({}, issuerLocator), dependencyName}); } } } @@ -28918,18 +28228,14 @@ Required by: ${issuerLocator.name}@${issuerLocator.reference} (via ${issuerForDi process.emitWarning(error); } } - const dependencyLocator = Array.isArray(dependencyReference) ? { name: dependencyReference[0], reference: dependencyReference[1] } : { name: dependencyName, reference: dependencyReference }; + const dependencyLocator = Array.isArray(dependencyReference) ? {name: dependencyReference[0], reference: dependencyReference[1]} : {name: dependencyName, reference: dependencyReference}; const dependencyInformation = getPackageInformationSafe(dependencyLocator); if (!dependencyInformation.packageLocation) { - throw makeError( - ErrorCode.MISSING_DEPENDENCY, - `A dependency seems valid but didn't get installed for some reason. This might be caused by a partial install, such as dev vs prod. + throw makeError(ErrorCode.MISSING_DEPENDENCY, `A dependency seems valid but didn't get installed for some reason. This might be caused by a partial install, such as dev vs prod. Required package: ${dependencyLocator.name}@${dependencyLocator.reference}${dependencyLocator.name !== requestForDisplay ? ` (via "${requestForDisplay}")` : ``} Required by: ${issuerLocator.name}@${issuerLocator.reference} (via ${issuerForDisplay}) -`, - { request: requestForDisplay, issuer: issuerForDisplay, dependencyLocator: Object.assign({}, dependencyLocator) } - ); +`, {request: requestForDisplay, issuer: issuerForDisplay, dependencyLocator: Object.assign({}, dependencyLocator)}); } const dependencyLocation = dependencyInformation.packageLocation; if (subPath) { @@ -28950,17 +28256,17 @@ Required by: ${issuerLocator.name}@${issuerLocator.reference} (via ${issuerForDi return unqualifiedPath; } } - function resolveUnqualified(unqualifiedPath, { extensions = Object.keys(require$$0.Module._extensions) } = {}) { + function resolveUnqualified(unqualifiedPath, {extensions = Object.keys(require$$0.Module._extensions)} = {}) { var _a, _b; const candidates = []; - const qualifiedPath = applyNodeExtensionResolution(unqualifiedPath, candidates, { extensions }); + const qualifiedPath = applyNodeExtensionResolution(unqualifiedPath, candidates, {extensions}); if (qualifiedPath) { return ppath.normalize(qualifiedPath); } else { const unqualifiedPathForDisplay = getPathForDisplay(unqualifiedPath); const containingPackage = findPackageLocator(unqualifiedPath); if (containingPackage) { - const { packageLocation } = getPackageInformationSafe(containingPackage); + const {packageLocation} = getPackageInformationSafe(containingPackage); let exists = true; try { opts.fakeFs.accessSync(packageLocation); @@ -28973,67 +28279,38 @@ Required by: ${issuerLocator.name}@${issuerLocator.reference} (via ${issuerForDi Missing package: ${containingPackage.name}@${containingPackage.reference} Expected package location: ${getPathForDisplay(packageLocation)} -`, { unqualifiedPath: unqualifiedPathForDisplay, extensions }); +`, {unqualifiedPath: unqualifiedPathForDisplay, extensions}); } } if (!exists) { const errorMessage = packageLocation.includes(`/unplugged/`) ? `Required unplugged package missing from disk. This may happen when switching branches without running installs (unplugged packages must be fully materialized on disk to work).` : `Required package missing from disk. If you keep your packages inside your repository then restarting the Node process may be enough. Otherwise, try to run an install first.`; - throw makeError( - ErrorCode.QUALIFIED_PATH_RESOLUTION_FAILED, - `${errorMessage} + throw makeError(ErrorCode.QUALIFIED_PATH_RESOLUTION_FAILED, `${errorMessage} Missing package: ${containingPackage.name}@${containingPackage.reference} Expected package location: ${getPathForDisplay(packageLocation)} -`, - { unqualifiedPath: unqualifiedPathForDisplay, extensions } - ); +`, {unqualifiedPath: unqualifiedPathForDisplay, extensions}); } } - throw makeError( - ErrorCode.QUALIFIED_PATH_RESOLUTION_FAILED, - `Qualified path resolution failed: we looked for the following paths, but none could be accessed. + throw makeError(ErrorCode.QUALIFIED_PATH_RESOLUTION_FAILED, `Qualified path resolution failed: we looked for the following paths, but none could be accessed. Source path: ${unqualifiedPathForDisplay} ${candidates.map((candidate) => `Not found: ${getPathForDisplay(candidate)} -`).join(``)}`, - { unqualifiedPath: unqualifiedPathForDisplay, extensions } - ); - } - } - function resolvePrivateRequest(request, issuer, opts2) { - var _a; - if (!issuer) - throw new Error(`Assertion failed: An issuer is required to resolve private import mappings`); - const resolved = packageImportsResolve({ - name: request, - base: url.pathToFileURL(npath.fromPortablePath(issuer)), - conditions: (_a = opts2.conditions) != null ? _a : defaultExportsConditions, - readFileSyncFn: tryReadFile - }); - if (resolved instanceof URL) { - return resolveUnqualified(npath.toPortablePath(url.fileURLToPath(resolved)), { extensions: opts2.extensions }); - } else { - if (resolved.startsWith(`#`)) - throw new Error(`Mapping from one private import to another isn't allowed`); - return resolveRequest(resolved, issuer, opts2); +`).join(``)}`, {unqualifiedPath: unqualifiedPathForDisplay, extensions}); } } - function resolveRequest(request, issuer, opts2 = {}) { + function resolveRequest(request, issuer, {considerBuiltins, extensions, conditions} = {}) { try { - if (request.startsWith(`#`)) - return resolvePrivateRequest(request, issuer, opts2); - const { considerBuiltins, extensions, conditions } = opts2; - const unqualifiedPath = resolveToUnqualified(request, issuer, { considerBuiltins }); + const unqualifiedPath = resolveToUnqualified(request, issuer, {considerBuiltins}); if (request === `pnpapi`) return unqualifiedPath; if (unqualifiedPath === null) return null; const isIssuerIgnored = () => issuer !== null ? isPathIgnored(issuer) : false; const remappedPath = (!considerBuiltins || !isBuiltinModule(request)) && !isIssuerIgnored() ? resolveUnqualifiedExport(request, unqualifiedPath, conditions) : unqualifiedPath; - return resolveUnqualified(remappedPath, { extensions }); + return resolveUnqualified(remappedPath, {extensions}); } catch (error) { if (Object.prototype.hasOwnProperty.call(error, `pnpCode`)) - Object.assign(error.data, { request: getPathForDisplay(request), issuer: issuer && getPathForDisplay(issuer) }); + Object.assign(error.data, {request: getPathForDisplay(request), issuer: issuer && getPathForDisplay(issuer)}); throw error; } } @@ -29047,9 +28324,9 @@ ${candidates.map((candidate) => `Not found: ${getPathForDisplay(candidate)} topLevel, getLocator: (name, referencish) => { if (Array.isArray(referencish)) { - return { name: referencish[0], reference: referencish[1] }; + return {name: referencish[0], reference: referencish[1]}; } else { - return { name, reference: referencish }; + return {name, reference: referencish}; } }, getDependencyTreeRoots: () => { @@ -29060,7 +28337,7 @@ ${candidates.map((candidate) => `Not found: ${getPathForDisplay(candidate)} for (const [name, entry] of packageRegistry) for (const reference of entry.keys()) if (name !== null && reference !== null) - locators.push({ name, reference }); + locators.push({name, reference}); return locators; }, getPackageInformation: (locator) => { @@ -29068,7 +28345,7 @@ ${candidates.map((candidate) => `Not found: ${getPathForDisplay(candidate)} if (info === null) return null; const packageLocation = npath.fromPortablePath(info.packageLocation); - const nativeInfo = { ...info, packageLocation }; + const nativeInfo = __spreadProps(__spreadValues$1({}, info), {packageLocation}); return nativeInfo; }, findPackageLocator: (path) => { @@ -29105,7 +28382,7 @@ ${candidates.map((candidate) => `Not found: ${getPathForDisplay(candidate)} function makeManager(pnpapi, opts) { const initialApiPath = npath.toPortablePath(pnpapi.resolveToUnqualified(`pnpapi`, null)); const initialApiStats = opts.fakeFs.statSync(npath.toPortablePath(initialApiPath)); - const apiMetadata = /* @__PURE__ */ new Map([ + const apiMetadata = new Map([ [initialApiPath, { cache: require$$0.Module._cache, instance: pnpapi, @@ -29147,7 +28424,7 @@ function makeManager(pnpapi, opts) { } return apiEntry; } - const findApiPathCache = /* @__PURE__ */ new Map(); + const findApiPathCache = new Map(); function addToCacheAndReturn(start, end, target) { if (target !== null) target = VirtualFS.resolveVirtual(target); @@ -29172,11 +28449,11 @@ function makeManager(pnpapi, opts) { if (!packageInformation) throw new Error(`Assertion failed: Couldn't get package information for '${modulePath}'`); if (!bestCandidate) - bestCandidate = { packageLocation: packageInformation.packageLocation, apiPaths: [] }; + bestCandidate = {packageLocation: packageInformation.packageLocation, apiPaths: []}; if (packageInformation.packageLocation === bestCandidate.packageLocation) { bestCandidate.apiPaths.push(apiPath); } else if (packageInformation.packageLocation.length > bestCandidate.packageLocation.length) { - bestCandidate = { packageLocation: packageInformation.packageLocation, apiPaths: [apiPath] }; + bestCandidate = {packageLocation: packageInformation.packageLocation, apiPaths: [apiPath]}; } } if (bestCandidate) { @@ -29230,7 +28507,35 @@ ${controlSegment} }; } -const localFs = { ...fs__default.default }; +var __defProp = Object.defineProperty; +var __getOwnPropSymbols = Object.getOwnPropertySymbols; +var __hasOwnProp = Object.prototype.hasOwnProperty; +var __propIsEnum = Object.prototype.propertyIsEnumerable; +var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, {enumerable: true, configurable: true, writable: true, value}) : obj[key] = value; +var __spreadValues = (a, b) => { + for (var prop in b || (b = {})) + if (__hasOwnProp.call(b, prop)) + __defNormalProp(a, prop, b[prop]); + if (__getOwnPropSymbols) + for (var prop of __getOwnPropSymbols(b)) { + if (__propIsEnum.call(b, prop)) + __defNormalProp(a, prop, b[prop]); + } + return a; +}; +var __objRest = (source, exclude) => { + var target = {}; + for (var prop in source) + if (__hasOwnProp.call(source, prop) && exclude.indexOf(prop) < 0) + target[prop] = source[prop]; + if (source != null && __getOwnPropSymbols) + for (var prop of __getOwnPropSymbols(source)) { + if (exclude.indexOf(prop) < 0 && __propIsEnum.call(source, prop)) + target[prop] = source[prop]; + } + return target; +}; +const localFs = __spreadValues({}, fs__default.default); const nodeFs = new NodeFS(localFs); const defaultRuntimeState = $$SETUP_STATE(hydrateRuntimeState); const defaultPnpapiResolution = __filename; @@ -29260,18 +28565,21 @@ const defaultApi = Object.assign(makeApi(defaultRuntimeState, { fakeFs: dynamicFsLayer, pnpapiResolution: defaultPnpapiResolution }), { - makeApi: ({ - basePath = void 0, - fakeFs = dynamicFsLayer, - pnpapiResolution = defaultPnpapiResolution, - ...rest - }) => { + makeApi: (_a) => { + var _b = _a, { + basePath = void 0, + fakeFs = dynamicFsLayer, + pnpapiResolution = defaultPnpapiResolution + } = _b, rest = __objRest(_b, [ + "basePath", + "fakeFs", + "pnpapiResolution" + ]); const apiRuntimeState = typeof basePath !== `undefined` ? $$SETUP_STATE(hydrateRuntimeState, basePath) : defaultRuntimeState; - return makeApi(apiRuntimeState, { + return makeApi(apiRuntimeState, __spreadValues({ fakeFs, - pnpapiResolution, - ...rest - }); + pnpapiResolution + }, rest)); }, setup: (api) => { applyPatch(api || defaultApi, { @@ -29292,7 +28600,7 @@ if (module.parent && module.parent.id === `internal/preload`) { } if (process.mainModule === module) { const reportError = (code, message, data) => { - process.stdout.write(`${JSON.stringify([{ code, message, data }, null])} + process.stdout.write(`${JSON.stringify([{code, message, data}, null])} `); }; const reportSuccess = (resolution) => { diff --git a/.pnp.loader.mjs b/.pnp.loader.mjs index dbd09ddd327..26efb974622 100644 --- a/.pnp.loader.mjs +++ b/.pnp.loader.mjs @@ -1,17 +1,14 @@ -import { URL as URL$1, fileURLToPath, pathToFileURL } from 'url'; +import { URL, fileURLToPath, pathToFileURL } from 'url'; import fs from 'fs'; import path from 'path'; import moduleExports, { Module } from 'module'; -import { EOL } from 'os'; -import assert from 'assert'; -const SAFE_TIME = 456789e3; - -const PortablePath = { - root: `/`, - dot: `.`, - parent: `..` -}; +var PathType; +(function(PathType2) { + PathType2[PathType2["File"] = 0] = "File"; + PathType2[PathType2["Portable"] = 1] = "Portable"; + PathType2[PathType2["Native"] = 2] = "Native"; +})(PathType || (PathType = {})); const npath = Object.create(path); const ppath = Object.create(path.posix); npath.cwd = () => process.cwd(); @@ -67,1266 +64,6 @@ function toPortablePath(p) { p = `/unc/${uncWindowsPathMatch[1] ? `.dot/` : ``}${uncWindowsPathMatch[2]}`; return p; } -function convertPath(targetPathUtils, sourcePath) { - return targetPathUtils === npath ? fromPortablePath(sourcePath) : toPortablePath(sourcePath); -} - -const defaultTime = new Date(SAFE_TIME * 1e3); -async function copyPromise(destinationFs, destination, sourceFs, source, opts) { - const normalizedDestination = destinationFs.pathUtils.normalize(destination); - const normalizedSource = sourceFs.pathUtils.normalize(source); - const prelayout = []; - const postlayout = []; - const { atime, mtime } = opts.stableTime ? { atime: defaultTime, mtime: defaultTime } : await sourceFs.lstatPromise(normalizedSource); - await destinationFs.mkdirpPromise(destinationFs.pathUtils.dirname(destination), { utimes: [atime, mtime] }); - const updateTime = typeof destinationFs.lutimesPromise === `function` ? destinationFs.lutimesPromise.bind(destinationFs) : destinationFs.utimesPromise.bind(destinationFs); - await copyImpl(prelayout, postlayout, updateTime, destinationFs, normalizedDestination, sourceFs, normalizedSource, { ...opts, didParentExist: true }); - for (const operation of prelayout) - await operation(); - await Promise.all(postlayout.map((operation) => { - return operation(); - })); -} -async function copyImpl(prelayout, postlayout, updateTime, destinationFs, destination, sourceFs, source, opts) { - var _a, _b; - const destinationStat = opts.didParentExist ? await maybeLStat(destinationFs, destination) : null; - const sourceStat = await sourceFs.lstatPromise(source); - const { atime, mtime } = opts.stableTime ? { atime: defaultTime, mtime: defaultTime } : sourceStat; - let updated; - switch (true) { - case sourceStat.isDirectory(): - { - updated = await copyFolder(prelayout, postlayout, updateTime, destinationFs, destination, destinationStat, sourceFs, source, sourceStat, opts); - } - break; - case sourceStat.isFile(): - { - updated = await copyFile(prelayout, postlayout, updateTime, destinationFs, destination, destinationStat, sourceFs, source, sourceStat, opts); - } - break; - case sourceStat.isSymbolicLink(): - { - updated = await copySymlink(prelayout, postlayout, updateTime, destinationFs, destination, destinationStat, sourceFs, source, sourceStat, opts); - } - break; - default: - { - throw new Error(`Unsupported file type (${sourceStat.mode})`); - } - } - if (updated || ((_a = destinationStat == null ? void 0 : destinationStat.mtime) == null ? void 0 : _a.getTime()) !== mtime.getTime() || ((_b = destinationStat == null ? void 0 : destinationStat.atime) == null ? void 0 : _b.getTime()) !== atime.getTime()) { - postlayout.push(() => updateTime(destination, atime, mtime)); - updated = true; - } - if (destinationStat === null || (destinationStat.mode & 511) !== (sourceStat.mode & 511)) { - postlayout.push(() => destinationFs.chmodPromise(destination, sourceStat.mode & 511)); - updated = true; - } - return updated; -} -async function maybeLStat(baseFs, p) { - try { - return await baseFs.lstatPromise(p); - } catch (e) { - return null; - } -} -async function copyFolder(prelayout, postlayout, updateTime, destinationFs, destination, destinationStat, sourceFs, source, sourceStat, opts) { - if (destinationStat !== null && !destinationStat.isDirectory()) { - if (opts.overwrite) { - prelayout.push(async () => destinationFs.removePromise(destination)); - destinationStat = null; - } else { - return false; - } - } - let updated = false; - if (destinationStat === null) { - prelayout.push(async () => { - try { - await destinationFs.mkdirPromise(destination, { mode: sourceStat.mode }); - } catch (err) { - if (err.code !== `EEXIST`) { - throw err; - } - } - }); - updated = true; - } - const entries = await sourceFs.readdirPromise(source); - const nextOpts = opts.didParentExist && !destinationStat ? { ...opts, didParentExist: false } : opts; - if (opts.stableSort) { - for (const entry of entries.sort()) { - if (await copyImpl(prelayout, postlayout, updateTime, destinationFs, destinationFs.pathUtils.join(destination, entry), sourceFs, sourceFs.pathUtils.join(source, entry), nextOpts)) { - updated = true; - } - } - } else { - const entriesUpdateStatus = await Promise.all(entries.map(async (entry) => { - await copyImpl(prelayout, postlayout, updateTime, destinationFs, destinationFs.pathUtils.join(destination, entry), sourceFs, sourceFs.pathUtils.join(source, entry), nextOpts); - })); - if (entriesUpdateStatus.some((status) => status)) { - updated = true; - } - } - return updated; -} -const isCloneSupportedCache = /* @__PURE__ */ new WeakMap(); -function makeLinkOperation(opFs, destination, source, sourceStat, linkStrategy) { - return async () => { - await opFs.linkPromise(source, destination); - if (linkStrategy === "readOnly" /* ReadOnly */) { - sourceStat.mode &= ~146; - await opFs.chmodPromise(destination, sourceStat.mode); - } - }; -} -function makeCloneLinkOperation(opFs, destination, source, sourceStat, linkStrategy) { - const isCloneSupported = isCloneSupportedCache.get(opFs); - if (typeof isCloneSupported === `undefined`) { - return async () => { - try { - await opFs.copyFilePromise(source, destination, fs.constants.COPYFILE_FICLONE_FORCE); - isCloneSupportedCache.set(opFs, true); - } catch (err) { - if (err.code === `ENOSYS` || err.code === `ENOTSUP`) { - isCloneSupportedCache.set(opFs, false); - await makeLinkOperation(opFs, destination, source, sourceStat, linkStrategy)(); - } else { - throw err; - } - } - }; - } else { - if (isCloneSupported) { - return async () => opFs.copyFilePromise(source, destination, fs.constants.COPYFILE_FICLONE_FORCE); - } else { - return makeLinkOperation(opFs, destination, source, sourceStat, linkStrategy); - } - } -} -async function copyFile(prelayout, postlayout, updateTime, destinationFs, destination, destinationStat, sourceFs, source, sourceStat, opts) { - var _a; - if (destinationStat !== null) { - if (opts.overwrite) { - prelayout.push(async () => destinationFs.removePromise(destination)); - destinationStat = null; - } else { - return false; - } - } - const linkStrategy = (_a = opts.linkStrategy) != null ? _a : null; - const op = destinationFs === sourceFs ? linkStrategy !== null ? makeCloneLinkOperation(destinationFs, destination, source, sourceStat, linkStrategy) : async () => destinationFs.copyFilePromise(source, destination, fs.constants.COPYFILE_FICLONE) : linkStrategy !== null ? makeLinkOperation(destinationFs, destination, source, sourceStat, linkStrategy) : async () => destinationFs.writeFilePromise(destination, await sourceFs.readFilePromise(source)); - prelayout.push(async () => op()); - return true; -} -async function copySymlink(prelayout, postlayout, updateTime, destinationFs, destination, destinationStat, sourceFs, source, sourceStat, opts) { - if (destinationStat !== null) { - if (opts.overwrite) { - prelayout.push(async () => destinationFs.removePromise(destination)); - destinationStat = null; - } else { - return false; - } - } - prelayout.push(async () => { - await destinationFs.symlinkPromise(convertPath(destinationFs.pathUtils, await sourceFs.readlinkPromise(source)), destination); - }); - return true; -} - -function makeError(code, message) { - return Object.assign(new Error(`${code}: ${message}`), { code }); -} -function ENOSYS(message, reason) { - return makeError(`ENOSYS`, `${message}, ${reason}`); -} - -class FakeFS { - constructor(pathUtils) { - this.pathUtils = pathUtils; - } - async *genTraversePromise(init, { stableSort = false } = {}) { - const stack = [init]; - while (stack.length > 0) { - const p = stack.shift(); - const entry = await this.lstatPromise(p); - if (entry.isDirectory()) { - const entries = await this.readdirPromise(p); - if (stableSort) { - for (const entry2 of entries.sort()) { - stack.push(this.pathUtils.join(p, entry2)); - } - } else { - throw new Error(`Not supported`); - } - } else { - yield p; - } - } - } - async removePromise(p, { recursive = true, maxRetries = 5 } = {}) { - let stat; - try { - stat = await this.lstatPromise(p); - } catch (error) { - if (error.code === `ENOENT`) { - return; - } else { - throw error; - } - } - if (stat.isDirectory()) { - if (recursive) { - const entries = await this.readdirPromise(p); - await Promise.all(entries.map((entry) => { - return this.removePromise(this.pathUtils.resolve(p, entry)); - })); - } - for (let t = 0; t <= maxRetries; t++) { - try { - await this.rmdirPromise(p); - break; - } catch (error) { - if (error.code !== `EBUSY` && error.code !== `ENOTEMPTY`) { - throw error; - } else if (t < maxRetries) { - await new Promise((resolve) => setTimeout(resolve, t * 100)); - } - } - } - } else { - await this.unlinkPromise(p); - } - } - removeSync(p, { recursive = true } = {}) { - let stat; - try { - stat = this.lstatSync(p); - } catch (error) { - if (error.code === `ENOENT`) { - return; - } else { - throw error; - } - } - if (stat.isDirectory()) { - if (recursive) - for (const entry of this.readdirSync(p)) - this.removeSync(this.pathUtils.resolve(p, entry)); - this.rmdirSync(p); - } else { - this.unlinkSync(p); - } - } - async mkdirpPromise(p, { chmod, utimes } = {}) { - p = this.resolve(p); - if (p === this.pathUtils.dirname(p)) - return void 0; - const parts = p.split(this.pathUtils.sep); - let createdDirectory; - for (let u = 2; u <= parts.length; ++u) { - const subPath = parts.slice(0, u).join(this.pathUtils.sep); - if (!this.existsSync(subPath)) { - try { - await this.mkdirPromise(subPath); - } catch (error) { - if (error.code === `EEXIST`) { - continue; - } else { - throw error; - } - } - createdDirectory != null ? createdDirectory : createdDirectory = subPath; - if (chmod != null) - await this.chmodPromise(subPath, chmod); - if (utimes != null) { - await this.utimesPromise(subPath, utimes[0], utimes[1]); - } else { - const parentStat = await this.statPromise(this.pathUtils.dirname(subPath)); - await this.utimesPromise(subPath, parentStat.atime, parentStat.mtime); - } - } - } - return createdDirectory; - } - mkdirpSync(p, { chmod, utimes } = {}) { - p = this.resolve(p); - if (p === this.pathUtils.dirname(p)) - return void 0; - const parts = p.split(this.pathUtils.sep); - let createdDirectory; - for (let u = 2; u <= parts.length; ++u) { - const subPath = parts.slice(0, u).join(this.pathUtils.sep); - if (!this.existsSync(subPath)) { - try { - this.mkdirSync(subPath); - } catch (error) { - if (error.code === `EEXIST`) { - continue; - } else { - throw error; - } - } - createdDirectory != null ? createdDirectory : createdDirectory = subPath; - if (chmod != null) - this.chmodSync(subPath, chmod); - if (utimes != null) { - this.utimesSync(subPath, utimes[0], utimes[1]); - } else { - const parentStat = this.statSync(this.pathUtils.dirname(subPath)); - this.utimesSync(subPath, parentStat.atime, parentStat.mtime); - } - } - } - return createdDirectory; - } - async copyPromise(destination, source, { baseFs = this, overwrite = true, stableSort = false, stableTime = false, linkStrategy = null } = {}) { - return await copyPromise(this, destination, baseFs, source, { overwrite, stableSort, stableTime, linkStrategy }); - } - copySync(destination, source, { baseFs = this, overwrite = true } = {}) { - const stat = baseFs.lstatSync(source); - const exists = this.existsSync(destination); - if (stat.isDirectory()) { - this.mkdirpSync(destination); - const directoryListing = baseFs.readdirSync(source); - for (const entry of directoryListing) { - this.copySync(this.pathUtils.join(destination, entry), baseFs.pathUtils.join(source, entry), { baseFs, overwrite }); - } - } else if (stat.isFile()) { - if (!exists || overwrite) { - if (exists) - this.removeSync(destination); - const content = baseFs.readFileSync(source); - this.writeFileSync(destination, content); - } - } else if (stat.isSymbolicLink()) { - if (!exists || overwrite) { - if (exists) - this.removeSync(destination); - const target = baseFs.readlinkSync(source); - this.symlinkSync(convertPath(this.pathUtils, target), destination); - } - } else { - throw new Error(`Unsupported file type (file: ${source}, mode: 0o${stat.mode.toString(8).padStart(6, `0`)})`); - } - const mode = stat.mode & 511; - this.chmodSync(destination, mode); - } - async changeFilePromise(p, content, opts = {}) { - if (Buffer.isBuffer(content)) { - return this.changeFileBufferPromise(p, content, opts); - } else { - return this.changeFileTextPromise(p, content, opts); - } - } - async changeFileBufferPromise(p, content, { mode } = {}) { - let current = Buffer.alloc(0); - try { - current = await this.readFilePromise(p); - } catch (error) { - } - if (Buffer.compare(current, content) === 0) - return; - await this.writeFilePromise(p, content, { mode }); - } - async changeFileTextPromise(p, content, { automaticNewlines, mode } = {}) { - let current = ``; - try { - current = await this.readFilePromise(p, `utf8`); - } catch (error) { - } - const normalizedContent = automaticNewlines ? normalizeLineEndings(current, content) : content; - if (current === normalizedContent) - return; - await this.writeFilePromise(p, normalizedContent, { mode }); - } - changeFileSync(p, content, opts = {}) { - if (Buffer.isBuffer(content)) { - return this.changeFileBufferSync(p, content, opts); - } else { - return this.changeFileTextSync(p, content, opts); - } - } - changeFileBufferSync(p, content, { mode } = {}) { - let current = Buffer.alloc(0); - try { - current = this.readFileSync(p); - } catch (error) { - } - if (Buffer.compare(current, content) === 0) - return; - this.writeFileSync(p, content, { mode }); - } - changeFileTextSync(p, content, { automaticNewlines = false, mode } = {}) { - let current = ``; - try { - current = this.readFileSync(p, `utf8`); - } catch (error) { - } - const normalizedContent = automaticNewlines ? normalizeLineEndings(current, content) : content; - if (current === normalizedContent) - return; - this.writeFileSync(p, normalizedContent, { mode }); - } - async movePromise(fromP, toP) { - try { - await this.renamePromise(fromP, toP); - } catch (error) { - if (error.code === `EXDEV`) { - await this.copyPromise(toP, fromP); - await this.removePromise(fromP); - } else { - throw error; - } - } - } - moveSync(fromP, toP) { - try { - this.renameSync(fromP, toP); - } catch (error) { - if (error.code === `EXDEV`) { - this.copySync(toP, fromP); - this.removeSync(fromP); - } else { - throw error; - } - } - } - async lockPromise(affectedPath, callback) { - const lockPath = `${affectedPath}.flock`; - const interval = 1e3 / 60; - const startTime = Date.now(); - let fd = null; - const isAlive = async () => { - let pid; - try { - [pid] = await this.readJsonPromise(lockPath); - } catch (error) { - return Date.now() - startTime < 500; - } - try { - process.kill(pid, 0); - return true; - } catch (error) { - return false; - } - }; - while (fd === null) { - try { - fd = await this.openPromise(lockPath, `wx`); - } catch (error) { - if (error.code === `EEXIST`) { - if (!await isAlive()) { - try { - await this.unlinkPromise(lockPath); - continue; - } catch (error2) { - } - } - if (Date.now() - startTime < 60 * 1e3) { - await new Promise((resolve) => setTimeout(resolve, interval)); - } else { - throw new Error(`Couldn't acquire a lock in a reasonable time (via ${lockPath})`); - } - } else { - throw error; - } - } - } - await this.writePromise(fd, JSON.stringify([process.pid])); - try { - return await callback(); - } finally { - try { - await this.closePromise(fd); - await this.unlinkPromise(lockPath); - } catch (error) { - } - } - } - async readJsonPromise(p) { - const content = await this.readFilePromise(p, `utf8`); - try { - return JSON.parse(content); - } catch (error) { - error.message += ` (in ${p})`; - throw error; - } - } - readJsonSync(p) { - const content = this.readFileSync(p, `utf8`); - try { - return JSON.parse(content); - } catch (error) { - error.message += ` (in ${p})`; - throw error; - } - } - async writeJsonPromise(p, data) { - return await this.writeFilePromise(p, `${JSON.stringify(data, null, 2)} -`); - } - writeJsonSync(p, data) { - return this.writeFileSync(p, `${JSON.stringify(data, null, 2)} -`); - } - async preserveTimePromise(p, cb) { - const stat = await this.lstatPromise(p); - const result = await cb(); - if (typeof result !== `undefined`) - p = result; - if (this.lutimesPromise) { - await this.lutimesPromise(p, stat.atime, stat.mtime); - } else if (!stat.isSymbolicLink()) { - await this.utimesPromise(p, stat.atime, stat.mtime); - } - } - async preserveTimeSync(p, cb) { - const stat = this.lstatSync(p); - const result = cb(); - if (typeof result !== `undefined`) - p = result; - if (this.lutimesSync) { - this.lutimesSync(p, stat.atime, stat.mtime); - } else if (!stat.isSymbolicLink()) { - this.utimesSync(p, stat.atime, stat.mtime); - } - } -} -class BasePortableFakeFS extends FakeFS { - constructor() { - super(ppath); - } -} -function getEndOfLine(content) { - const matches = content.match(/\r?\n/g); - if (matches === null) - return EOL; - const crlf = matches.filter((nl) => nl === `\r -`).length; - const lf = matches.length - crlf; - return crlf > lf ? `\r -` : ` -`; -} -function normalizeLineEndings(originalContent, newContent) { - return newContent.replace(/\r?\n/g, getEndOfLine(originalContent)); -} - -class NodeFS extends BasePortableFakeFS { - constructor(realFs = fs) { - super(); - this.realFs = realFs; - if (typeof this.realFs.lutimes !== `undefined`) { - this.lutimesPromise = this.lutimesPromiseImpl; - this.lutimesSync = this.lutimesSyncImpl; - } - } - getExtractHint() { - return false; - } - getRealPath() { - return PortablePath.root; - } - resolve(p) { - return ppath.resolve(p); - } - async openPromise(p, flags, mode) { - return await new Promise((resolve, reject) => { - this.realFs.open(npath.fromPortablePath(p), flags, mode, this.makeCallback(resolve, reject)); - }); - } - openSync(p, flags, mode) { - return this.realFs.openSync(npath.fromPortablePath(p), flags, mode); - } - async opendirPromise(p, opts) { - return await new Promise((resolve, reject) => { - if (typeof opts !== `undefined`) { - this.realFs.opendir(npath.fromPortablePath(p), opts, this.makeCallback(resolve, reject)); - } else { - this.realFs.opendir(npath.fromPortablePath(p), this.makeCallback(resolve, reject)); - } - }).then((dir) => { - return Object.defineProperty(dir, `path`, { value: p, configurable: true, writable: true }); - }); - } - opendirSync(p, opts) { - const dir = typeof opts !== `undefined` ? this.realFs.opendirSync(npath.fromPortablePath(p), opts) : this.realFs.opendirSync(npath.fromPortablePath(p)); - return Object.defineProperty(dir, `path`, { value: p, configurable: true, writable: true }); - } - async readPromise(fd, buffer, offset = 0, length = 0, position = -1) { - return await new Promise((resolve, reject) => { - this.realFs.read(fd, buffer, offset, length, position, (error, bytesRead) => { - if (error) { - reject(error); - } else { - resolve(bytesRead); - } - }); - }); - } - readSync(fd, buffer, offset, length, position) { - return this.realFs.readSync(fd, buffer, offset, length, position); - } - async writePromise(fd, buffer, offset, length, position) { - return await new Promise((resolve, reject) => { - if (typeof buffer === `string`) { - return this.realFs.write(fd, buffer, offset, this.makeCallback(resolve, reject)); - } else { - return this.realFs.write(fd, buffer, offset, length, position, this.makeCallback(resolve, reject)); - } - }); - } - writeSync(fd, buffer, offset, length, position) { - if (typeof buffer === `string`) { - return this.realFs.writeSync(fd, buffer, offset); - } else { - return this.realFs.writeSync(fd, buffer, offset, length, position); - } - } - async closePromise(fd) { - await new Promise((resolve, reject) => { - this.realFs.close(fd, this.makeCallback(resolve, reject)); - }); - } - closeSync(fd) { - this.realFs.closeSync(fd); - } - createReadStream(p, opts) { - const realPath = p !== null ? npath.fromPortablePath(p) : p; - return this.realFs.createReadStream(realPath, opts); - } - createWriteStream(p, opts) { - const realPath = p !== null ? npath.fromPortablePath(p) : p; - return this.realFs.createWriteStream(realPath, opts); - } - async realpathPromise(p) { - return await new Promise((resolve, reject) => { - this.realFs.realpath(npath.fromPortablePath(p), {}, this.makeCallback(resolve, reject)); - }).then((path) => { - return npath.toPortablePath(path); - }); - } - realpathSync(p) { - return npath.toPortablePath(this.realFs.realpathSync(npath.fromPortablePath(p), {})); - } - async existsPromise(p) { - return await new Promise((resolve) => { - this.realFs.exists(npath.fromPortablePath(p), resolve); - }); - } - accessSync(p, mode) { - return this.realFs.accessSync(npath.fromPortablePath(p), mode); - } - async accessPromise(p, mode) { - return await new Promise((resolve, reject) => { - this.realFs.access(npath.fromPortablePath(p), mode, this.makeCallback(resolve, reject)); - }); - } - existsSync(p) { - return this.realFs.existsSync(npath.fromPortablePath(p)); - } - async statPromise(p, opts) { - return await new Promise((resolve, reject) => { - if (opts) { - this.realFs.stat(npath.fromPortablePath(p), opts, this.makeCallback(resolve, reject)); - } else { - this.realFs.stat(npath.fromPortablePath(p), this.makeCallback(resolve, reject)); - } - }); - } - statSync(p, opts) { - if (opts) { - return this.realFs.statSync(npath.fromPortablePath(p), opts); - } else { - return this.realFs.statSync(npath.fromPortablePath(p)); - } - } - async fstatPromise(fd, opts) { - return await new Promise((resolve, reject) => { - if (opts) { - this.realFs.fstat(fd, opts, this.makeCallback(resolve, reject)); - } else { - this.realFs.fstat(fd, this.makeCallback(resolve, reject)); - } - }); - } - fstatSync(fd, opts) { - if (opts) { - return this.realFs.fstatSync(fd, opts); - } else { - return this.realFs.fstatSync(fd); - } - } - async lstatPromise(p, opts) { - return await new Promise((resolve, reject) => { - if (opts) { - this.realFs.lstat(npath.fromPortablePath(p), opts, this.makeCallback(resolve, reject)); - } else { - this.realFs.lstat(npath.fromPortablePath(p), this.makeCallback(resolve, reject)); - } - }); - } - lstatSync(p, opts) { - if (opts) { - return this.realFs.lstatSync(npath.fromPortablePath(p), opts); - } else { - return this.realFs.lstatSync(npath.fromPortablePath(p)); - } - } - async fchmodPromise(fd, mask) { - return await new Promise((resolve, reject) => { - this.realFs.fchmod(fd, mask, this.makeCallback(resolve, reject)); - }); - } - fchmodSync(fd, mask) { - return this.realFs.fchmodSync(fd, mask); - } - async chmodPromise(p, mask) { - return await new Promise((resolve, reject) => { - this.realFs.chmod(npath.fromPortablePath(p), mask, this.makeCallback(resolve, reject)); - }); - } - chmodSync(p, mask) { - return this.realFs.chmodSync(npath.fromPortablePath(p), mask); - } - async fchownPromise(fd, uid, gid) { - return await new Promise((resolve, reject) => { - this.realFs.fchown(fd, uid, gid, this.makeCallback(resolve, reject)); - }); - } - fchownSync(fd, uid, gid) { - return this.realFs.fchownSync(fd, uid, gid); - } - async chownPromise(p, uid, gid) { - return await new Promise((resolve, reject) => { - this.realFs.chown(npath.fromPortablePath(p), uid, gid, this.makeCallback(resolve, reject)); - }); - } - chownSync(p, uid, gid) { - return this.realFs.chownSync(npath.fromPortablePath(p), uid, gid); - } - async renamePromise(oldP, newP) { - return await new Promise((resolve, reject) => { - this.realFs.rename(npath.fromPortablePath(oldP), npath.fromPortablePath(newP), this.makeCallback(resolve, reject)); - }); - } - renameSync(oldP, newP) { - return this.realFs.renameSync(npath.fromPortablePath(oldP), npath.fromPortablePath(newP)); - } - async copyFilePromise(sourceP, destP, flags = 0) { - return await new Promise((resolve, reject) => { - this.realFs.copyFile(npath.fromPortablePath(sourceP), npath.fromPortablePath(destP), flags, this.makeCallback(resolve, reject)); - }); - } - copyFileSync(sourceP, destP, flags = 0) { - return this.realFs.copyFileSync(npath.fromPortablePath(sourceP), npath.fromPortablePath(destP), flags); - } - async appendFilePromise(p, content, opts) { - return await new Promise((resolve, reject) => { - const fsNativePath = typeof p === `string` ? npath.fromPortablePath(p) : p; - if (opts) { - this.realFs.appendFile(fsNativePath, content, opts, this.makeCallback(resolve, reject)); - } else { - this.realFs.appendFile(fsNativePath, content, this.makeCallback(resolve, reject)); - } - }); - } - appendFileSync(p, content, opts) { - const fsNativePath = typeof p === `string` ? npath.fromPortablePath(p) : p; - if (opts) { - this.realFs.appendFileSync(fsNativePath, content, opts); - } else { - this.realFs.appendFileSync(fsNativePath, content); - } - } - async writeFilePromise(p, content, opts) { - return await new Promise((resolve, reject) => { - const fsNativePath = typeof p === `string` ? npath.fromPortablePath(p) : p; - if (opts) { - this.realFs.writeFile(fsNativePath, content, opts, this.makeCallback(resolve, reject)); - } else { - this.realFs.writeFile(fsNativePath, content, this.makeCallback(resolve, reject)); - } - }); - } - writeFileSync(p, content, opts) { - const fsNativePath = typeof p === `string` ? npath.fromPortablePath(p) : p; - if (opts) { - this.realFs.writeFileSync(fsNativePath, content, opts); - } else { - this.realFs.writeFileSync(fsNativePath, content); - } - } - async unlinkPromise(p) { - return await new Promise((resolve, reject) => { - this.realFs.unlink(npath.fromPortablePath(p), this.makeCallback(resolve, reject)); - }); - } - unlinkSync(p) { - return this.realFs.unlinkSync(npath.fromPortablePath(p)); - } - async utimesPromise(p, atime, mtime) { - return await new Promise((resolve, reject) => { - this.realFs.utimes(npath.fromPortablePath(p), atime, mtime, this.makeCallback(resolve, reject)); - }); - } - utimesSync(p, atime, mtime) { - this.realFs.utimesSync(npath.fromPortablePath(p), atime, mtime); - } - async lutimesPromiseImpl(p, atime, mtime) { - const lutimes = this.realFs.lutimes; - if (typeof lutimes === `undefined`) - throw ENOSYS(`unavailable Node binding`, `lutimes '${p}'`); - return await new Promise((resolve, reject) => { - lutimes.call(this.realFs, npath.fromPortablePath(p), atime, mtime, this.makeCallback(resolve, reject)); - }); - } - lutimesSyncImpl(p, atime, mtime) { - const lutimesSync = this.realFs.lutimesSync; - if (typeof lutimesSync === `undefined`) - throw ENOSYS(`unavailable Node binding`, `lutimes '${p}'`); - lutimesSync.call(this.realFs, npath.fromPortablePath(p), atime, mtime); - } - async mkdirPromise(p, opts) { - return await new Promise((resolve, reject) => { - this.realFs.mkdir(npath.fromPortablePath(p), opts, this.makeCallback(resolve, reject)); - }); - } - mkdirSync(p, opts) { - return this.realFs.mkdirSync(npath.fromPortablePath(p), opts); - } - async rmdirPromise(p, opts) { - return await new Promise((resolve, reject) => { - if (opts) { - this.realFs.rmdir(npath.fromPortablePath(p), opts, this.makeCallback(resolve, reject)); - } else { - this.realFs.rmdir(npath.fromPortablePath(p), this.makeCallback(resolve, reject)); - } - }); - } - rmdirSync(p, opts) { - return this.realFs.rmdirSync(npath.fromPortablePath(p), opts); - } - async linkPromise(existingP, newP) { - return await new Promise((resolve, reject) => { - this.realFs.link(npath.fromPortablePath(existingP), npath.fromPortablePath(newP), this.makeCallback(resolve, reject)); - }); - } - linkSync(existingP, newP) { - return this.realFs.linkSync(npath.fromPortablePath(existingP), npath.fromPortablePath(newP)); - } - async symlinkPromise(target, p, type) { - return await new Promise((resolve, reject) => { - this.realFs.symlink(npath.fromPortablePath(target.replace(/\/+$/, ``)), npath.fromPortablePath(p), type, this.makeCallback(resolve, reject)); - }); - } - symlinkSync(target, p, type) { - return this.realFs.symlinkSync(npath.fromPortablePath(target.replace(/\/+$/, ``)), npath.fromPortablePath(p), type); - } - async readFilePromise(p, encoding) { - return await new Promise((resolve, reject) => { - const fsNativePath = typeof p === `string` ? npath.fromPortablePath(p) : p; - this.realFs.readFile(fsNativePath, encoding, this.makeCallback(resolve, reject)); - }); - } - readFileSync(p, encoding) { - const fsNativePath = typeof p === `string` ? npath.fromPortablePath(p) : p; - return this.realFs.readFileSync(fsNativePath, encoding); - } - async readdirPromise(p, opts) { - return await new Promise((resolve, reject) => { - if (opts == null ? void 0 : opts.withFileTypes) { - this.realFs.readdir(npath.fromPortablePath(p), { withFileTypes: true }, this.makeCallback(resolve, reject)); - } else { - this.realFs.readdir(npath.fromPortablePath(p), this.makeCallback((value) => resolve(value), reject)); - } - }); - } - readdirSync(p, opts) { - if (opts == null ? void 0 : opts.withFileTypes) { - return this.realFs.readdirSync(npath.fromPortablePath(p), { withFileTypes: true }); - } else { - return this.realFs.readdirSync(npath.fromPortablePath(p)); - } - } - async readlinkPromise(p) { - return await new Promise((resolve, reject) => { - this.realFs.readlink(npath.fromPortablePath(p), this.makeCallback(resolve, reject)); - }).then((path) => { - return npath.toPortablePath(path); - }); - } - readlinkSync(p) { - return npath.toPortablePath(this.realFs.readlinkSync(npath.fromPortablePath(p))); - } - async truncatePromise(p, len) { - return await new Promise((resolve, reject) => { - this.realFs.truncate(npath.fromPortablePath(p), len, this.makeCallback(resolve, reject)); - }); - } - truncateSync(p, len) { - return this.realFs.truncateSync(npath.fromPortablePath(p), len); - } - async ftruncatePromise(fd, len) { - return await new Promise((resolve, reject) => { - this.realFs.ftruncate(fd, len, this.makeCallback(resolve, reject)); - }); - } - ftruncateSync(fd, len) { - return this.realFs.ftruncateSync(fd, len); - } - watch(p, a, b) { - return this.realFs.watch( - npath.fromPortablePath(p), - a, - b - ); - } - watchFile(p, a, b) { - return this.realFs.watchFile( - npath.fromPortablePath(p), - a, - b - ); - } - unwatchFile(p, cb) { - return this.realFs.unwatchFile(npath.fromPortablePath(p), cb); - } - makeCallback(resolve, reject) { - return (err, result) => { - if (err) { - reject(err); - } else { - resolve(result); - } - }; - } -} - -class ProxiedFS extends FakeFS { - getExtractHint(hints) { - return this.baseFs.getExtractHint(hints); - } - resolve(path) { - return this.mapFromBase(this.baseFs.resolve(this.mapToBase(path))); - } - getRealPath() { - return this.mapFromBase(this.baseFs.getRealPath()); - } - async openPromise(p, flags, mode) { - return this.baseFs.openPromise(this.mapToBase(p), flags, mode); - } - openSync(p, flags, mode) { - return this.baseFs.openSync(this.mapToBase(p), flags, mode); - } - async opendirPromise(p, opts) { - return Object.assign(await this.baseFs.opendirPromise(this.mapToBase(p), opts), { path: p }); - } - opendirSync(p, opts) { - return Object.assign(this.baseFs.opendirSync(this.mapToBase(p), opts), { path: p }); - } - async readPromise(fd, buffer, offset, length, position) { - return await this.baseFs.readPromise(fd, buffer, offset, length, position); - } - readSync(fd, buffer, offset, length, position) { - return this.baseFs.readSync(fd, buffer, offset, length, position); - } - async writePromise(fd, buffer, offset, length, position) { - if (typeof buffer === `string`) { - return await this.baseFs.writePromise(fd, buffer, offset); - } else { - return await this.baseFs.writePromise(fd, buffer, offset, length, position); - } - } - writeSync(fd, buffer, offset, length, position) { - if (typeof buffer === `string`) { - return this.baseFs.writeSync(fd, buffer, offset); - } else { - return this.baseFs.writeSync(fd, buffer, offset, length, position); - } - } - async closePromise(fd) { - return this.baseFs.closePromise(fd); - } - closeSync(fd) { - this.baseFs.closeSync(fd); - } - createReadStream(p, opts) { - return this.baseFs.createReadStream(p !== null ? this.mapToBase(p) : p, opts); - } - createWriteStream(p, opts) { - return this.baseFs.createWriteStream(p !== null ? this.mapToBase(p) : p, opts); - } - async realpathPromise(p) { - return this.mapFromBase(await this.baseFs.realpathPromise(this.mapToBase(p))); - } - realpathSync(p) { - return this.mapFromBase(this.baseFs.realpathSync(this.mapToBase(p))); - } - async existsPromise(p) { - return this.baseFs.existsPromise(this.mapToBase(p)); - } - existsSync(p) { - return this.baseFs.existsSync(this.mapToBase(p)); - } - accessSync(p, mode) { - return this.baseFs.accessSync(this.mapToBase(p), mode); - } - async accessPromise(p, mode) { - return this.baseFs.accessPromise(this.mapToBase(p), mode); - } - async statPromise(p, opts) { - return this.baseFs.statPromise(this.mapToBase(p), opts); - } - statSync(p, opts) { - return this.baseFs.statSync(this.mapToBase(p), opts); - } - async fstatPromise(fd, opts) { - return this.baseFs.fstatPromise(fd, opts); - } - fstatSync(fd, opts) { - return this.baseFs.fstatSync(fd, opts); - } - lstatPromise(p, opts) { - return this.baseFs.lstatPromise(this.mapToBase(p), opts); - } - lstatSync(p, opts) { - return this.baseFs.lstatSync(this.mapToBase(p), opts); - } - async fchmodPromise(fd, mask) { - return this.baseFs.fchmodPromise(fd, mask); - } - fchmodSync(fd, mask) { - return this.baseFs.fchmodSync(fd, mask); - } - async chmodPromise(p, mask) { - return this.baseFs.chmodPromise(this.mapToBase(p), mask); - } - chmodSync(p, mask) { - return this.baseFs.chmodSync(this.mapToBase(p), mask); - } - async fchownPromise(fd, uid, gid) { - return this.baseFs.fchownPromise(fd, uid, gid); - } - fchownSync(fd, uid, gid) { - return this.baseFs.fchownSync(fd, uid, gid); - } - async chownPromise(p, uid, gid) { - return this.baseFs.chownPromise(this.mapToBase(p), uid, gid); - } - chownSync(p, uid, gid) { - return this.baseFs.chownSync(this.mapToBase(p), uid, gid); - } - async renamePromise(oldP, newP) { - return this.baseFs.renamePromise(this.mapToBase(oldP), this.mapToBase(newP)); - } - renameSync(oldP, newP) { - return this.baseFs.renameSync(this.mapToBase(oldP), this.mapToBase(newP)); - } - async copyFilePromise(sourceP, destP, flags = 0) { - return this.baseFs.copyFilePromise(this.mapToBase(sourceP), this.mapToBase(destP), flags); - } - copyFileSync(sourceP, destP, flags = 0) { - return this.baseFs.copyFileSync(this.mapToBase(sourceP), this.mapToBase(destP), flags); - } - async appendFilePromise(p, content, opts) { - return this.baseFs.appendFilePromise(this.fsMapToBase(p), content, opts); - } - appendFileSync(p, content, opts) { - return this.baseFs.appendFileSync(this.fsMapToBase(p), content, opts); - } - async writeFilePromise(p, content, opts) { - return this.baseFs.writeFilePromise(this.fsMapToBase(p), content, opts); - } - writeFileSync(p, content, opts) { - return this.baseFs.writeFileSync(this.fsMapToBase(p), content, opts); - } - async unlinkPromise(p) { - return this.baseFs.unlinkPromise(this.mapToBase(p)); - } - unlinkSync(p) { - return this.baseFs.unlinkSync(this.mapToBase(p)); - } - async utimesPromise(p, atime, mtime) { - return this.baseFs.utimesPromise(this.mapToBase(p), atime, mtime); - } - utimesSync(p, atime, mtime) { - return this.baseFs.utimesSync(this.mapToBase(p), atime, mtime); - } - async mkdirPromise(p, opts) { - return this.baseFs.mkdirPromise(this.mapToBase(p), opts); - } - mkdirSync(p, opts) { - return this.baseFs.mkdirSync(this.mapToBase(p), opts); - } - async rmdirPromise(p, opts) { - return this.baseFs.rmdirPromise(this.mapToBase(p), opts); - } - rmdirSync(p, opts) { - return this.baseFs.rmdirSync(this.mapToBase(p), opts); - } - async linkPromise(existingP, newP) { - return this.baseFs.linkPromise(this.mapToBase(existingP), this.mapToBase(newP)); - } - linkSync(existingP, newP) { - return this.baseFs.linkSync(this.mapToBase(existingP), this.mapToBase(newP)); - } - async symlinkPromise(target, p, type) { - const mappedP = this.mapToBase(p); - if (this.pathUtils.isAbsolute(target)) - return this.baseFs.symlinkPromise(this.mapToBase(target), mappedP, type); - const mappedAbsoluteTarget = this.mapToBase(this.pathUtils.join(this.pathUtils.dirname(p), target)); - const mappedTarget = this.baseFs.pathUtils.relative(this.baseFs.pathUtils.dirname(mappedP), mappedAbsoluteTarget); - return this.baseFs.symlinkPromise(mappedTarget, mappedP, type); - } - symlinkSync(target, p, type) { - const mappedP = this.mapToBase(p); - if (this.pathUtils.isAbsolute(target)) - return this.baseFs.symlinkSync(this.mapToBase(target), mappedP, type); - const mappedAbsoluteTarget = this.mapToBase(this.pathUtils.join(this.pathUtils.dirname(p), target)); - const mappedTarget = this.baseFs.pathUtils.relative(this.baseFs.pathUtils.dirname(mappedP), mappedAbsoluteTarget); - return this.baseFs.symlinkSync(mappedTarget, mappedP, type); - } - async readFilePromise(p, encoding) { - if (encoding === `utf8`) { - return this.baseFs.readFilePromise(this.fsMapToBase(p), encoding); - } else { - return this.baseFs.readFilePromise(this.fsMapToBase(p), encoding); - } - } - readFileSync(p, encoding) { - if (encoding === `utf8`) { - return this.baseFs.readFileSync(this.fsMapToBase(p), encoding); - } else { - return this.baseFs.readFileSync(this.fsMapToBase(p), encoding); - } - } - async readdirPromise(p, opts) { - return this.baseFs.readdirPromise(this.mapToBase(p), opts); - } - readdirSync(p, opts) { - return this.baseFs.readdirSync(this.mapToBase(p), opts); - } - async readlinkPromise(p) { - return this.mapFromBase(await this.baseFs.readlinkPromise(this.mapToBase(p))); - } - readlinkSync(p) { - return this.mapFromBase(this.baseFs.readlinkSync(this.mapToBase(p))); - } - async truncatePromise(p, len) { - return this.baseFs.truncatePromise(this.mapToBase(p), len); - } - truncateSync(p, len) { - return this.baseFs.truncateSync(this.mapToBase(p), len); - } - async ftruncatePromise(fd, len) { - return this.baseFs.ftruncatePromise(fd, len); - } - ftruncateSync(fd, len) { - return this.baseFs.ftruncateSync(fd, len); - } - watch(p, a, b) { - return this.baseFs.watch( - this.mapToBase(p), - a, - b - ); - } - watchFile(p, a, b) { - return this.baseFs.watchFile( - this.mapToBase(p), - a, - b - ); - } - unwatchFile(p, cb) { - return this.baseFs.unwatchFile(this.mapToBase(p), cb); - } - fsMapToBase(p) { - if (typeof p === `number`) { - return p; - } else { - return this.mapToBase(p); - } - } -} - -const NUMBER_REGEXP = /^[0-9]+$/; -const VIRTUAL_REGEXP = /^(\/(?:[^/]+\/)*?(?:\$\$virtual|__virtual__))((?:\/((?:[^/]+-)?[a-f0-9]+)(?:\/([^/]+))?)?((?:\/.*)?))$/; -const VALID_COMPONENT = /^([^/]+-)?[a-f0-9]+$/; -class VirtualFS extends ProxiedFS { - constructor({ baseFs = new NodeFS() } = {}) { - super(ppath); - this.baseFs = baseFs; - } - static makeVirtualPath(base, component, to) { - if (ppath.basename(base) !== `__virtual__`) - throw new Error(`Assertion failed: Virtual folders must be named "__virtual__"`); - if (!ppath.basename(component).match(VALID_COMPONENT)) - throw new Error(`Assertion failed: Virtual components must be ended by an hexadecimal hash`); - const target = ppath.relative(ppath.dirname(base), to); - const segments = target.split(`/`); - let depth = 0; - while (depth < segments.length && segments[depth] === `..`) - depth += 1; - const finalSegments = segments.slice(depth); - const fullVirtualPath = ppath.join(base, component, String(depth), ...finalSegments); - return fullVirtualPath; - } - static resolveVirtual(p) { - const match = p.match(VIRTUAL_REGEXP); - if (!match || !match[3] && match[5]) - return p; - const target = ppath.dirname(match[1]); - if (!match[3] || !match[4]) - return target; - const isnum = NUMBER_REGEXP.test(match[4]); - if (!isnum) - return p; - const depth = Number(match[4]); - const backstep = `../`.repeat(depth); - const subpath = match[5] || `.`; - return VirtualFS.resolveVirtual(ppath.join(target, backstep, subpath)); - } - getExtractHint(hints) { - return this.baseFs.getExtractHint(hints); - } - getRealPath() { - return this.baseFs.getRealPath(); - } - realpathSync(p) { - const match = p.match(VIRTUAL_REGEXP); - if (!match) - return this.baseFs.realpathSync(p); - if (!match[5]) - return p; - const realpath = this.baseFs.realpathSync(this.mapToBase(p)); - return VirtualFS.makeVirtualPath(match[1], match[3], realpath); - } - async realpathPromise(p) { - const match = p.match(VIRTUAL_REGEXP); - if (!match) - return await this.baseFs.realpathPromise(p); - if (!match[5]) - return p; - const realpath = await this.baseFs.realpathPromise(this.mapToBase(p)); - return VirtualFS.makeVirtualPath(match[1], match[3], realpath); - } - mapToBase(p) { - if (p === ``) - return p; - if (this.pathUtils.isAbsolute(p)) - return VirtualFS.resolveVirtual(p); - const resolvedRoot = VirtualFS.resolveVirtual(this.baseFs.resolve(PortablePath.dot)); - const resolvedP = VirtualFS.resolveVirtual(this.baseFs.resolve(p)); - return ppath.relative(resolvedRoot, resolvedP) || PortablePath.dot; - } - mapFromBase(p) { - return p; - } -} const builtinModules = new Set(Module.builtinModules || Object.keys(process.binding(`natives`))); const isBuiltinModule = (request) => request.startsWith(`node:`) || builtinModules.has(request); @@ -1355,12 +92,7 @@ function readPackage(requestPath) { return JSON.parse(fs.readFileSync(jsonPath, `utf8`)); } -const [major, minor] = process.versions.node.split(`.`).map((value) => parseInt(value, 10)); -const HAS_CONSOLIDATED_HOOKS = major > 16 || major === 16 && minor >= 12; -const HAS_UNFLAGGED_JSON_MODULES = major > 17 || major === 17 && minor >= 5 || major === 16 && minor >= 15; -const HAS_JSON_IMPORT_ASSERTION_REQUIREMENT = major > 17 || major === 17 && minor >= 1 || major === 16 && minor > 14; - -async function tryReadFile$1(path2) { +async function tryReadFile(path2) { try { return await fs.promises.readFile(path2, `utf8`); } catch (error) { @@ -1371,7 +103,7 @@ async function tryReadFile$1(path2) { } function tryParseURL(str, base) { try { - return new URL$1(str, base); + return new URL(str, base); } catch { return null; } @@ -1391,16 +123,10 @@ function getFileFormat(filepath) { return `commonjs`; } case `.wasm`: { - throw new Error( - `Unknown file extension ".wasm" for ${filepath}` - ); + throw new Error(`Unknown file extension ".wasm" for ${filepath}`); } case `.json`: { - if (HAS_UNFLAGGED_JSON_MODULES) - return `json`; - throw new Error( - `Unknown file extension ".json" for ${filepath}` - ); + throw new Error(`Unknown file extension ".json" for ${filepath}`); } case `.js`: { const pkg = readPackageScope(filepath); @@ -1444,7 +170,6 @@ async function getSource$1(urlString, context, defaultGetSource) { } async function load$1(urlString, context, nextLoad) { - var _a; const url = tryParseURL(urlString); if ((url == null ? void 0 : url.protocol) !== `file:`) return nextLoad(urlString, context, nextLoad); @@ -1452,20 +177,6 @@ async function load$1(urlString, context, nextLoad) { const format = getFileFormat(filePath); if (!format) return nextLoad(urlString, context, nextLoad); - if (HAS_JSON_IMPORT_ASSERTION_REQUIREMENT && format === `json` && ((_a = context.importAssertions) == null ? void 0 : _a.type) !== `json`) { - const err = new TypeError(`[ERR_IMPORT_ASSERTION_TYPE_MISSING]: Module "${urlString}" needs an import assertion of type "json"`); - err.code = `ERR_IMPORT_ASSERTION_TYPE_MISSING`; - throw err; - } - if (process.env.WATCH_REPORT_DEPENDENCIES && process.send) { - process.send({ - "watch:import": pathToFileURL( - npath.fromPortablePath( - VirtualFS.resolveVirtual(npath.toPortablePath(filePath)) - ) - ).href - }); - } return { format, source: await fs.promises.readFile(filePath, `utf8`), @@ -1473,488 +184,11 @@ async function load$1(urlString, context, nextLoad) { }; } -const ArrayIsArray = Array.isArray; -const JSONStringify = JSON.stringify; -const ObjectGetOwnPropertyNames = Object.getOwnPropertyNames; -const ObjectPrototypeHasOwnProperty = (obj, prop) => Object.prototype.hasOwnProperty.call(obj, prop); -const RegExpPrototypeExec = (obj, string) => RegExp.prototype.exec.call(obj, string); -const RegExpPrototypeSymbolReplace = (obj, ...rest) => RegExp.prototype[Symbol.replace].apply(obj, rest); -const StringPrototypeEndsWith = (str, ...rest) => String.prototype.endsWith.apply(str, rest); -const StringPrototypeIncludes = (str, ...rest) => String.prototype.includes.apply(str, rest); -const StringPrototypeLastIndexOf = (str, ...rest) => String.prototype.lastIndexOf.apply(str, rest); -const StringPrototypeIndexOf = (str, ...rest) => String.prototype.indexOf.apply(str, rest); -const StringPrototypeReplace = (str, ...rest) => String.prototype.replace.apply(str, rest); -const StringPrototypeSlice = (str, ...rest) => String.prototype.slice.apply(str, rest); -const StringPrototypeStartsWith = (str, ...rest) => String.prototype.startsWith.apply(str, rest); -const SafeMap = Map; -const JSONParse = JSON.parse; - -function createErrorType(code, messageCreator, errorType) { - return class extends errorType { - constructor(...args) { - super(messageCreator(...args)); - this.code = code; - this.name = `${errorType.name} [${code}]`; - } - }; -} -const ERR_PACKAGE_IMPORT_NOT_DEFINED = createErrorType( - `ERR_PACKAGE_IMPORT_NOT_DEFINED`, - (specifier, packagePath, base) => { - return `Package import specifier "${specifier}" is not defined${packagePath ? ` in package ${packagePath}package.json` : ``} imported from ${base}`; - }, - TypeError -); -const ERR_INVALID_MODULE_SPECIFIER = createErrorType( - `ERR_INVALID_MODULE_SPECIFIER`, - (request, reason, base = void 0) => { - return `Invalid module "${request}" ${reason}${base ? ` imported from ${base}` : ``}`; - }, - TypeError -); -const ERR_INVALID_PACKAGE_TARGET = createErrorType( - `ERR_INVALID_PACKAGE_TARGET`, - (pkgPath, key, target, isImport = false, base = void 0) => { - const relError = typeof target === `string` && !isImport && target.length && !StringPrototypeStartsWith(target, `./`); - if (key === `.`) { - assert(isImport === false); - return `Invalid "exports" main target ${JSONStringify(target)} defined in the package config ${pkgPath}package.json${base ? ` imported from ${base}` : ``}${relError ? `; targets must start with "./"` : ``}`; - } - return `Invalid "${isImport ? `imports` : `exports`}" target ${JSONStringify( - target - )} defined for '${key}' in the package config ${pkgPath}package.json${base ? ` imported from ${base}` : ``}${relError ? `; targets must start with "./"` : ``}`; - }, - Error -); -const ERR_INVALID_PACKAGE_CONFIG = createErrorType( - `ERR_INVALID_PACKAGE_CONFIG`, - (path, base, message) => { - return `Invalid package config ${path}${base ? ` while importing ${base}` : ``}${message ? `. ${message}` : ``}`; - }, - Error -); - -function filterOwnProperties(source, keys) { - const filtered = /* @__PURE__ */ Object.create(null); - for (let i = 0; i < keys.length; i++) { - const key = keys[i]; - if (ObjectPrototypeHasOwnProperty(source, key)) { - filtered[key] = source[key]; - } - } - return filtered; -} - -const packageJSONCache = new SafeMap(); -function getPackageConfig(path, specifier, base, readFileSyncFn) { - const existing = packageJSONCache.get(path); - if (existing !== void 0) { - return existing; - } - const source = readFileSyncFn(path); - if (source === void 0) { - const packageConfig2 = { - pjsonPath: path, - exists: false, - main: void 0, - name: void 0, - type: "none", - exports: void 0, - imports: void 0 - }; - packageJSONCache.set(path, packageConfig2); - return packageConfig2; - } - let packageJSON; - try { - packageJSON = JSONParse(source); - } catch (error) { - throw new ERR_INVALID_PACKAGE_CONFIG( - path, - (base ? `"${specifier}" from ` : "") + fileURLToPath(base || specifier), - error.message - ); - } - let { imports, main, name, type } = filterOwnProperties(packageJSON, [ - "imports", - "main", - "name", - "type" - ]); - const exports = ObjectPrototypeHasOwnProperty(packageJSON, "exports") ? packageJSON.exports : void 0; - if (typeof imports !== "object" || imports === null) { - imports = void 0; - } - if (typeof main !== "string") { - main = void 0; - } - if (typeof name !== "string") { - name = void 0; - } - if (type !== "module" && type !== "commonjs") { - type = "none"; - } - const packageConfig = { - pjsonPath: path, - exists: true, - main, - name, - type, - exports, - imports - }; - packageJSONCache.set(path, packageConfig); - return packageConfig; -} -function getPackageScopeConfig(resolved, readFileSyncFn) { - let packageJSONUrl = new URL("./package.json", resolved); - while (true) { - const packageJSONPath2 = packageJSONUrl.pathname; - if (StringPrototypeEndsWith(packageJSONPath2, "node_modules/package.json")) { - break; - } - const packageConfig2 = getPackageConfig( - fileURLToPath(packageJSONUrl), - resolved, - void 0, - readFileSyncFn - ); - if (packageConfig2.exists) { - return packageConfig2; - } - const lastPackageJSONUrl = packageJSONUrl; - packageJSONUrl = new URL("../package.json", packageJSONUrl); - if (packageJSONUrl.pathname === lastPackageJSONUrl.pathname) { - break; - } - } - const packageJSONPath = fileURLToPath(packageJSONUrl); - const packageConfig = { - pjsonPath: packageJSONPath, - exists: false, - main: void 0, - name: void 0, - type: "none", - exports: void 0, - imports: void 0 - }; - packageJSONCache.set(packageJSONPath, packageConfig); - return packageConfig; -} - -/** - @license - Copyright Node.js contributors. All rights reserved. - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to - deal in the Software without restriction, including without limitation the - rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - sell copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - IN THE SOFTWARE. -*/ -function throwImportNotDefined(specifier, packageJSONUrl, base) { - throw new ERR_PACKAGE_IMPORT_NOT_DEFINED( - specifier, - packageJSONUrl && fileURLToPath(new URL(".", packageJSONUrl)), - fileURLToPath(base) - ); -} -function throwInvalidSubpath(subpath, packageJSONUrl, internal, base) { - const reason = `request is not a valid subpath for the "${internal ? "imports" : "exports"}" resolution of ${fileURLToPath(packageJSONUrl)}`; - throw new ERR_INVALID_MODULE_SPECIFIER( - subpath, - reason, - base && fileURLToPath(base) - ); -} -function throwInvalidPackageTarget(subpath, target, packageJSONUrl, internal, base) { - if (typeof target === "object" && target !== null) { - target = JSONStringify(target, null, ""); - } else { - target = `${target}`; - } - throw new ERR_INVALID_PACKAGE_TARGET( - fileURLToPath(new URL(".", packageJSONUrl)), - subpath, - target, - internal, - base && fileURLToPath(base) - ); -} -const invalidSegmentRegEx = /(^|\\|\/)((\.|%2e)(\.|%2e)?|(n|%6e|%4e)(o|%6f|%4f)(d|%64|%44)(e|%65|%45)(_|%5f)(m|%6d|%4d)(o|%6f|%4f)(d|%64|%44)(u|%75|%55)(l|%6c|%4c)(e|%65|%45)(s|%73|%53))(\\|\/|$)/i; -const patternRegEx = /\*/g; -function resolvePackageTargetString(target, subpath, match, packageJSONUrl, base, pattern, internal, conditions) { - if (subpath !== "" && !pattern && target[target.length - 1] !== "/") - throwInvalidPackageTarget(match, target, packageJSONUrl, internal, base); - if (!StringPrototypeStartsWith(target, "./")) { - if (internal && !StringPrototypeStartsWith(target, "../") && !StringPrototypeStartsWith(target, "/")) { - let isURL = false; - try { - new URL(target); - isURL = true; - } catch { - } - if (!isURL) { - const exportTarget = pattern ? RegExpPrototypeSymbolReplace(patternRegEx, target, () => subpath) : target + subpath; - return exportTarget; - } - } - throwInvalidPackageTarget(match, target, packageJSONUrl, internal, base); - } - if (RegExpPrototypeExec( - invalidSegmentRegEx, - StringPrototypeSlice(target, 2) - ) !== null) - throwInvalidPackageTarget(match, target, packageJSONUrl, internal, base); - const resolved = new URL(target, packageJSONUrl); - const resolvedPath = resolved.pathname; - const packagePath = new URL(".", packageJSONUrl).pathname; - if (!StringPrototypeStartsWith(resolvedPath, packagePath)) - throwInvalidPackageTarget(match, target, packageJSONUrl, internal, base); - if (subpath === "") - return resolved; - if (RegExpPrototypeExec(invalidSegmentRegEx, subpath) !== null) { - const request = pattern ? StringPrototypeReplace(match, "*", () => subpath) : match + subpath; - throwInvalidSubpath(request, packageJSONUrl, internal, base); - } - if (pattern) { - return new URL( - RegExpPrototypeSymbolReplace(patternRegEx, resolved.href, () => subpath) - ); - } - return new URL(subpath, resolved); -} -function isArrayIndex(key) { - const keyNum = +key; - if (`${keyNum}` !== key) - return false; - return keyNum >= 0 && keyNum < 4294967295; -} -function resolvePackageTarget(packageJSONUrl, target, subpath, packageSubpath, base, pattern, internal, conditions) { - if (typeof target === "string") { - return resolvePackageTargetString( - target, - subpath, - packageSubpath, - packageJSONUrl, - base, - pattern, - internal); - } else if (ArrayIsArray(target)) { - if (target.length === 0) { - return null; - } - let lastException; - for (let i = 0; i < target.length; i++) { - const targetItem = target[i]; - let resolveResult; - try { - resolveResult = resolvePackageTarget( - packageJSONUrl, - targetItem, - subpath, - packageSubpath, - base, - pattern, - internal, - conditions - ); - } catch (e) { - lastException = e; - if (e.code === "ERR_INVALID_PACKAGE_TARGET") { - continue; - } - throw e; - } - if (resolveResult === void 0) { - continue; - } - if (resolveResult === null) { - lastException = null; - continue; - } - return resolveResult; - } - if (lastException === void 0 || lastException === null) - return lastException; - throw lastException; - } else if (typeof target === "object" && target !== null) { - const keys = ObjectGetOwnPropertyNames(target); - for (let i = 0; i < keys.length; i++) { - const key = keys[i]; - if (isArrayIndex(key)) { - throw new ERR_INVALID_PACKAGE_CONFIG( - fileURLToPath(packageJSONUrl), - base, - '"exports" cannot contain numeric property keys.' - ); - } - } - for (let i = 0; i < keys.length; i++) { - const key = keys[i]; - if (key === "default" || conditions.has(key)) { - const conditionalTarget = target[key]; - const resolveResult = resolvePackageTarget( - packageJSONUrl, - conditionalTarget, - subpath, - packageSubpath, - base, - pattern, - internal, - conditions - ); - if (resolveResult === void 0) - continue; - return resolveResult; - } - } - return void 0; - } else if (target === null) { - return null; - } - throwInvalidPackageTarget( - packageSubpath, - target, - packageJSONUrl, - internal, - base - ); -} -function patternKeyCompare(a, b) { - const aPatternIndex = StringPrototypeIndexOf(a, "*"); - const bPatternIndex = StringPrototypeIndexOf(b, "*"); - const baseLenA = aPatternIndex === -1 ? a.length : aPatternIndex + 1; - const baseLenB = bPatternIndex === -1 ? b.length : bPatternIndex + 1; - if (baseLenA > baseLenB) - return -1; - if (baseLenB > baseLenA) - return 1; - if (aPatternIndex === -1) - return 1; - if (bPatternIndex === -1) - return -1; - if (a.length > b.length) - return -1; - if (b.length > a.length) - return 1; - return 0; -} -function packageImportsResolve({ - name, - base, - conditions, - readFileSyncFn -}) { - if (name === "#" || StringPrototypeStartsWith(name, "#/") || StringPrototypeEndsWith(name, "/")) { - const reason = "is not a valid internal imports specifier name"; - throw new ERR_INVALID_MODULE_SPECIFIER(name, reason, fileURLToPath(base)); - } - let packageJSONUrl; - const packageConfig = getPackageScopeConfig(base, readFileSyncFn); - if (packageConfig.exists) { - packageJSONUrl = pathToFileURL(packageConfig.pjsonPath); - const imports = packageConfig.imports; - if (imports) { - if (ObjectPrototypeHasOwnProperty(imports, name) && !StringPrototypeIncludes(name, "*")) { - const resolveResult = resolvePackageTarget( - packageJSONUrl, - imports[name], - "", - name, - base, - false, - true, - conditions - ); - if (resolveResult != null) { - return resolveResult; - } - } else { - let bestMatch = ""; - let bestMatchSubpath; - const keys = ObjectGetOwnPropertyNames(imports); - for (let i = 0; i < keys.length; i++) { - const key = keys[i]; - const patternIndex = StringPrototypeIndexOf(key, "*"); - if (patternIndex !== -1 && StringPrototypeStartsWith( - name, - StringPrototypeSlice(key, 0, patternIndex) - )) { - const patternTrailer = StringPrototypeSlice(key, patternIndex + 1); - if (name.length >= key.length && StringPrototypeEndsWith(name, patternTrailer) && patternKeyCompare(bestMatch, key) === 1 && StringPrototypeLastIndexOf(key, "*") === patternIndex) { - bestMatch = key; - bestMatchSubpath = StringPrototypeSlice( - name, - patternIndex, - name.length - patternTrailer.length - ); - } - } - } - if (bestMatch) { - const target = imports[bestMatch]; - const resolveResult = resolvePackageTarget( - packageJSONUrl, - target, - bestMatchSubpath, - bestMatch, - base, - true, - true, - conditions - ); - if (resolveResult != null) { - return resolveResult; - } - } - } - } - } - throwImportNotDefined(name, packageJSONUrl, base); -} - const pathRegExp = /^(?![a-zA-Z]:[\\/]|\\\\|\.{0,2}(?:\/|$))((?:node:)?(?:@[^/]+\/)?[^/]+)\/*(.*|)$/; const isRelativeRegexp = /^\.{0,2}\//; -function tryReadFile(filePath) { - try { - return fs.readFileSync(filePath, `utf8`); - } catch (err) { - if (err.code === `ENOENT`) - return void 0; - throw err; - } -} -async function resolvePrivateRequest(specifier, issuer, context, nextResolve) { - const resolved = packageImportsResolve({ - name: specifier, - base: pathToFileURL(issuer), - conditions: new Set(context.conditions), - readFileSyncFn: tryReadFile - }); - if (resolved instanceof URL) { - return { url: resolved.href, shortCircuit: true }; - } else { - if (resolved.startsWith(`#`)) - throw new Error(`Mapping from one private import to another isn't allowed`); - return resolve$1(resolved, context, nextResolve); - } -} async function resolve$1(originalSpecifier, context, nextResolve) { var _a; - const { findPnpApi } = moduleExports; + const {findPnpApi} = moduleExports; if (!findPnpApi || isBuiltinModule(originalSpecifier)) return nextResolve(originalSpecifier, context, nextResolve); let specifier = originalSpecifier; @@ -1964,13 +198,11 @@ async function resolve$1(originalSpecifier, context, nextResolve) { return nextResolve(originalSpecifier, context, nextResolve); specifier = fileURLToPath(url); } - const { parentURL, conditions = [] } = context; + const {parentURL, conditions = []} = context; const issuer = parentURL ? fileURLToPath(parentURL) : process.cwd(); const pnpapi = (_a = findPnpApi(issuer)) != null ? _a : url ? findPnpApi(specifier) : null; if (!pnpapi) return nextResolve(originalSpecifier, context, nextResolve); - if (specifier.startsWith(`#`)) - return resolvePrivateRequest(specifier, issuer, context, nextResolve); const dependencyNameMatch = specifier.match(pathRegExp); let allowLegacyResolve = false; if (dependencyNameMatch) { @@ -1978,7 +210,7 @@ async function resolve$1(originalSpecifier, context, nextResolve) { if (subPath === ``) { const resolved = pnpapi.resolveToUnqualified(`${dependencyName}/package.json`, issuer); if (resolved) { - const content = await tryReadFile$1(resolved); + const content = await tryReadFile(resolved); if (content) { const pkg = JSON.parse(content); allowLegacyResolve = pkg.exports == null; @@ -2007,11 +239,10 @@ async function resolve$1(originalSpecifier, context, nextResolve) { const binding = process.binding(`fs`); const originalfstat = binding.fstat; -const ZIP_MASK = 4278190080; -const ZIP_MAGIC = 704643072; +const ZIP_FD = 2147483648; binding.fstat = function(...args) { const [fd, useBigint, req] = args; - if ((fd & ZIP_MASK) === ZIP_MAGIC && useBigint === false && req === void 0) { + if ((fd & ZIP_FD) !== 0 && useBigint === false && req === void 0) { try { const stats = fs.fstatSync(fd); return new Float64Array([ @@ -2032,9 +263,11 @@ binding.fstat = function(...args) { return originalfstat.apply(this, args); }; +const [major, minor] = process.versions.node.split(`.`).map((value) => parseInt(value, 10)); +const hasConsolidatedHooks = major > 16 || major === 16 && minor >= 12; const resolve = resolve$1; -const getFormat = HAS_CONSOLIDATED_HOOKS ? void 0 : getFormat$1; -const getSource = HAS_CONSOLIDATED_HOOKS ? void 0 : getSource$1; -const load = HAS_CONSOLIDATED_HOOKS ? load$1 : void 0; +const getFormat = hasConsolidatedHooks ? void 0 : getFormat$1; +const getSource = hasConsolidatedHooks ? void 0 : getSource$1; +const load = hasConsolidatedHooks ? load$1 : void 0; export { getFormat, getSource, load, resolve }; diff --git a/.yarn/cache/fsevents-patch-2882183fbf-8.zip b/.yarn/cache/fsevents-patch-2882183fbf-8.zip deleted file mode 100644 index c4511f19bda176f6c1a39da1fbf5c56a981f61c2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 23675 zcmbrl1ymc(_AUygK!M`!#kELrFD^xjyA>C!&wYWp%rN48| zdhfn<&$@T5e^xTO_c!0(Gs#RQJ0CwFy(B>R`*>fw@amt!zY|P&?&xG`W$NH$>0xi> z#`*ETiW2?*MXlYeJgpqv|D*E);nhFzAZMAh{1*ra4lfZ9DF3UDvZA!Cs-~>5<_EPM zE}ZUX-B`ikR4e^>KR5gggY1kPf@XOEmnh=JT6-H@Sm1~)VuO0=XA_VGV~saQs1J&{qDUSfEXln}Z1ql$1>>h%V2(BAJ2N?h zLq=QE5@11EW3Uo=u_#T=l{{sLCy{%QqEEOp&}5}z_%)UZi!&+-<59jg%5-p(le32S zX3(m9Wlb~ijrn_*mm)i1Tz!<=)i>zb@`*I9k{<>`r!lY9mzgcLMLrk5Fd9+p)Aq`2 zZP!TuMm0B< zskA{mLMR7Tn<$wl5BHiF6Ge2cB&Yhe?BEA{_4a;?nUiDs0B!M!0h6N`H=gBJnDvT$ zmc9Okq0>uv%GLdQGwMFudKJm@mBGEp=Y{ttl;CZTVCtQ7o%-5PIUJLp3^w0(JWL!h zOeA{I4~|h_h@IPFA$OSc{TKu`#xJVB{SqLVA>{Pw8T*xW@6m50@PfHX>qZomuJyiy z&|#LlgcGNE|JL9QMz!8Lh?Z?XNbD2BdPKTa5v_a7vFr@0&+OStz|u{N?w^f-n1RiV7*ia?}<4bThcilo0xqo{4foO6~BzP zdXIcQBehUe`7U`O3V-57h#Q|saf$XoMvU2q=oZRngs_llyoL+W+l=e=WWc}P4gXo$ z%Y6HA){vEyQIX|vu#D4LbzGIh2{_PI&PCOamsxg9LQ%q>^Y|n8 z{trpREOGHG-Cd=%uWMGG8Oif=?%grWLZ4s|5MzjMIu$S!-`PVbt%60||`L>(Y~DvXl;fk+eQUF}BYXV#w8r=9@QpRe)qw`@NWNbyude*9vso`oTnA^CBNV$$|^YFed$r^<#B>Fi)ih`xam#YEUOy}Mj^)|3V1V)LX=OB?sx?-($G3&?Q8u_)RKZ+wW8XYwbhr@SE6sXmQt8_ zrzepbf@BDc7qzX}aroNxX8ROt;Eicm;(sqMS5m0(d+kW0tF#Xl>^%=oJN~W-F1}4>?A?SXG%tME% zbmI5`L4z9d)km}gOSu=K{S7G>3FDhW9&O)btl(fx9={EG`rPPj9HoexpX9?=!?R8Rq-rD<}r6KgFS;HfwX<%I!gh~1FhaGpJxwD~*mIzIg z%ex*H;?J)&qn_-fCPLCs^Xf_afHPI8=|vR`T&|VcnsN?9)=Ta&^GdB|7AJvR1(gfv zgu+^+v`DO9nyo#6L&vO{uAv1%#I!z~0S?owGyOpbtFd*iY5Oz)V-5#47GY)QZRG}g zqZE}nM8HzzceJ-$s8&)_9P%tS)}=d6mJS(%Fs2U{!d`{aKXk_COZbwfzAvy`dk>H; zTe6Whc{3Gm1{?lh&=h=8BdG%vesA%?*>SBfcpEB={Q7ff&T9nLa7`6tOZ0$+NTvlA z$#kbucE@!GI_Ef`kD&q2fQtB>0tc(mnZfwsW{?}C(Nq^tri8O=PHD?(;khxABRVx= zM49M^h*1P=fkeWdG*Y)jKQhvQllRAT$9aK0RJ=V*aooBiD%hrl1EZ8!Bw7F`a)WuB z<0r93yFgjjLSGl6S0*R6W1EenD%#j3Wkb)kACmZ9M~7y`c1!hyF7lq|cgbYVq2O(n zXkB^*EV3Gb7s$PFc^oCg(kLtGg#!*B61CMAGMlDyqxwfB%YCWh$=4VAVWX!=^HVv8o&9yR`1z(gS6!(18$4!=xPgx1fji=LCzNU1M2>OM=!hoK z_#URkxORMY^yFH?X5=vcD`<#nop|e;X2MTPUn4hXKO*W_^U)&Q<5X2;D}O;H^^^ z_vkgAsryq%07_tgZ149*V24)Ia#fBMJ%zcJ||*-fPY_R2NtH3+SnPb6MeYm!8Z!-w7&Rq)iY$ z`5s7Td~qm#di%+^0)23#H*$a0Hj-^tXRBY=>w+3fvOde;adhG|gUb@jFB%x|EB{_Dri+`6=S~ zp{7RZ=HG{+|7-&UxDKWi@B>Z;d@G>)uiL2w|Q3vIxOK zxD2U9XQV74MvKR&k`Z;PVRy@&*>mia(PsEdlwDQ|;LJ;=vEGM?^6f%h^{$=GP`g1$ z_vHO=hlWg70*22S_l&BpiL^`aNej43Vt6?%e zOs5W$j-4CWHLSLqJV)Z-?D{0VUY|l31CWe;eHau!sF*yKCRaGMbaC)GS7iM_KzB;$ z1D4|T^y#>r1u^o7Y*&r~Yb+7=s~(am{F-J%99$)|0K~YDCIhhrb(xu5by=pHG+ULt zT30EPAt-^8z}h6KTN!m*z3Qq;Dz)Kpa?|?btjG<~#*cB*0xh2tn+{3+Pnwyd4Ss=ceM$GMT>o|Rdbf!2sJW+^4#^49La>jQ~)5lG?iZcFo61wT;agiiPyJA z(kP0Nt%eToSCC^a=6JbI`dJpYl~ENl0{4bJ#by=;95%T-$xXaSO+QS;VIowz#@?eKeh zlTlPYz9vCQO;;r%kD60pt;O9%I<@gi(CT(4_MIS zNO@_cky}9;z@nUcbuRN>j%)@LBu((t$utr8Ay3Pg;X5vuI(g-I6h* zDx`4&WjnSKiTIMjgcd=Q*#{vQwN*!{YIm$=JPXe}-OgXm{N{CQ*?SZX{rT|=%3xGS z^jE4jP9_n-CN`$~Cx?8|8Z1r0B0v1(mV)|w$ZNTxGO8zGGmN+?&APWz8n^r(n5^iF zQm^DnB0eCZTF=nZ@DIJ)PH4$$EDa{I2nZ#qEaEFnFQQ$zUz=^T+cneA1m0B09-9lur3B7fjoL!7zvmZ9tj(Ik+jxjfq~co{7) z8O7a@HIm0jr0^b>H8sP&E(2S~n+ZDror&8RQ%3XjBjhtChacYsRoR!#{@2mYS!oA2 z$5)~38@GC4s^2!JQ81Jb%Vm)Aov3^<1r2NS+{D~iiApgG(~*waCed-cFqi5CPtz1v zCc0BacFH?V! zEMy;OTYWeZNy1x7Qx$w$=UitwbaeN5nSthbhJZOaG4=a_Gv5qWfbjkLBAa}W=uGkz zfzjzYA*^=iOw8JBKUKyKox(P_BBBA+Q zM)A1dX)-*8rIq-6Qy`1NT@N^6A@8eVAwT%?d%H`@x{O@|TX}iPCjP)*I95JFC%=TZ z+l?`nAXws2JiAO!iF~H*E&9lEw-7G&l@056cA0cA@=@e2JesFvF<|F1!54Xjf0t}mtQuzKl8uX=7VPZYe zow^O?fzxu2iFkS}LSRDp@=5RHP~v}mcLzS;qwmQeAhe3V_`lgY{(dt*?Lza{l5OV? zY;VN5t5=knvQ9$#YDtVU7>4ubbMLpHH_^GO?a~IxXJy1MU7Bz&lgW!ET__L8a@Em_ zE!;^^ony#1jVMFeIEoRC3}l&D->AO<8EQLuED9aryLOMl?qO&5^VJ?zc~u9M*E+ev z9z<1Y&_LG%jOe0oD$z5j+k&#A;fLPu>`^2)5W>Gj?dGnjUJ=;NlqjY!s$}v0j|v8L ztA;)PUOy6wzHPtBeQC}WmM$Z^9JE(1t-!|?J<(imHrh`@81`xB;9MPm@%Y!)xQl#~AH(9&MET867kD z#ohA)RoI+;`;Oq4_>?vujO$Oa32RG&SkgCwtf5{NzjMm=t~|Zddivt$1=X+bPGpH5dio{L|3mwB-usuNGqQb}q?c^Q6WLW6wgQ&8=W4A0rztwY~aH1Zmx)olsM69N^9xYb9d@QQZ%RC-H5$kAG2=14>B_BP8U zM9_yQMkV?QOo?io6W?jsA1X)z@&JsOghMiymKa97$2epkNiWjt2ui=S7Tpj(ZIj|- z?9wsSN#)F|h-h?c5y;1ad7LFMl{QjH&nKY|Wz;+e1njJSULpNpt*6`2h#Or-w^%vx zCXH|d-#qyBiuAc7Lydc!#O8NJHrKT0Kizz`*Zy~82S2Gm=m3N6k%OEAwDv88Hqo=n zv`+d{*K#1X5VT1YlW8IFDPtrhPi!bqDYsj@7QNgQz?nnS#ALjt1|Ak{&o2OF=$x`L z6>jIam02r$d=IAIQzL#T(?`N<^55T{6Jjpp$9?AZBDPzkAKVrE@IPO3@Ffe=v`_kZ z7h_eYrAq0)Fd;TvI<&Bo|J_4CZ=gK4lzE{&lT>~nKSc|&QgRWPTmczxht8L)pEumgXHCr_jCNvJZ{ z^VqGwUw!?fgJxmHcq?1c5i+k>U+w(L6R-PHxgF$;8PvaieR$9Osum$<`o$T6X{Oih z58Xp3aVVosKqVz)4jO6o4G^z&$I9n?+Q<8n*uKI8OaRt$!LqqcMsqUSeWxhMGESktc-O| zg3p2m;wZ6G^u2$g2g^nLJmVZ~nkf!u8N4Le-=ru=0Tcgf;qRA7D9p?(_#kII9h?6` z`th>DqWz)W7JtPjShdcI=~rX!-4Q?8tUP$1{$@CeNAWqVqr zt+#eHjY9?)#&a_$vVPxx*45@0zV1GK>&pfBxiA5;r~!tCnoPZRc{jL<@h+ao(qDJ9 zqrU#Es3hhD>B!Pd&#Pxm5sRpzKR}5p72kmX@`Vpewr?UXSa^tbh-07 z$4q26j|sW|$)}5|`m^DZi_GHXdLakiBh1gf#vw4#1#TV;1M}87k$dAzFYS$Ye^xF? zr+!j~nq9Lluc`8X7~TIPS<-R9YWyTpTHzV^0oUD1eVxY=b}c|b>3=O!lJwKbzz)Rn z9r8G2=~{6v5o+0Gkp0O6lBGO?G4V}=X0&~4r%zxpMcVXvbs;2H_3*;UM*fK$#eHnZ zm*+;s|(mPA@Q{AcA0JjI6HJkOWzGpid8&R==b6Q2afB-rf zWYV|D&QIN3(Q!e@*0Mg_;qE}b;?IC!XTGVWqlZN~R{M|N09()Me8b8gTBc??3;+yn zNNJ~=<0nZz<1(2Ov81%h%*G+5`AKe;_Y?TE2hI>vMJo~gx2EAvB(m51MSoUjGykAz z*al3}5#h}X)N6%to6yw^OhS|3j@z3Z}EKfJg7{ugm69`f$PdDmcy1mgSQqeJg zSDZreMVK9$DmDBoLaZqiszfXNa#QNkcL~i()`MKCiT$8_rwMzsJCGtL$C>c;0r4{5 zR%s_C-LHE6Bq=PKlga*eL#F!B)?}m4@z&en)?VJ+=JR6m`dixs!d;xuaH@VkecceZ zdM^#~*Zo7XKSydjnqD3Iq%O=Z3cEqO&3<^SS6hOUaDNXUFeipRV~0&VBbi;}ENi7q z@c!UVnaGBiyKydS-7FeOyyc=HS_rgVH=g=Z6l$(s{WCC-JbnprJoiI^H?@dbsKfhZ zd5$P+opj6;!oG!-`vG!c1t&!0XqZqkQ37j~SZoFxMwffUYLq-MdE#w-W$d_sdmhcK zTL2dYR=nlNO4j>;FXb7(omuu(KNQr4nX5WR#;@6%6CX|Ji88W&(k0IHe=GWAHcyS7E9i=Ddv?QvxO&D1YYg_Kf(1xeJ1x5j&G9Be1c-DPov7Ml z3^3q6;L{Q%EEu!}Ds)UXxW_sc@7wNU%_X&FV}F=0naR!n?G6~+hA^rV*M$N5LImd9 zB?@ZEVqirx3~XEZ5kEpu=i6~pzHyLykZTEJj9XV2RxZpJp9vCi>KrAfUih;A(mmN` zwERnQRvulXxnr-SNq$>bno~xGpQZhs5Q~@4NZ2-sKed)Xj!!V zk6-)rZN&b$_WUVvarTTU6S%HvwlvwoKiYEahm$90-sQsL>>X*dA1za)_)$k?4}g}9 z5%&AZ6J|diU*!S&6B6Sx?5&ekXqW$-Vq~NKvKCslOrAhoY78%|D@*`7*Kk~VE zU-rkN+7Ephexe_b{J8u;`eP&0l>xelsp?tesTyW+ZghB-ziW#H^HrP^#~f*nsy`hjU2N_Cf_!?Yljx-sU4u&A_E6A` zuG9Ol_^eb=KfGRd2^diHb#gl&{e`Jw!P~}=WiL+JM!AADx=wCTWaa1mBXHAI$BwPq z!?bDhhHf{wsXLC4-a~G1>$BMD^e(sZ*+zl8+_8dn8k5(IutpJb3sjk{rT&E-)8f9I z7mrw$ass1fv4?%RjZ*-3wS{7;Cj3)EHf2L~gBn;Dv3nMR!^XVy_4e^|z%}`s6BG6? zgWed!6MuB-%%0Ceh{jh2=5Ff$DEG<>d80pC;!sjmI)?#N_kbqPAp_B0R=48gVuKDT z4GD!Z#3>X|ZEga-{)C1wnc1^HKP^ihmp`^8U2!HKi9O(wVQQJlm^6CZdVk}PuzR)F zGyKrQ00wbjQd3lnBv^nuNP4KZOnZ32#KzFu*mFxT$~RBX4e8qJ6O>_ZYD6&YFwh*F z83qv8GA$dRo_Iiu?IE9`cf-YgdA5axxu+WS9yM&24YcOUk;O$nA;sf^4g$*~9c9>e~Vb>q6 zZf*)Z_wLjBNzT5*UeB0Tg{=T1W;8=1Ye$qtv=>P?FM>( z$C6081d+dggwTPhpN98)fMB1n%kz+tlw7nhSTYt&eHi;4H1QQ61q(nJ4;Ti$Z22y- z^Vih;kq0`Go*ni{;M7+B@Pp}%%{BSf2yVAxB#Z$r2s=}r1Z5Ls!(PKH_qgId10;b8 zkpPUpUH-2R;0Bt;@8n&U~4gzX0#f9$Q^FTLNw%B z_xOU-=I?~zZFx;SnnuFCns8GHMvZiX;!r}TgYCgQP?>%SxdWK@UkJEONCSc}7E0*) z-vtW7fdbvZCl_p_5|NkGq`x0CjxK-};FrTddT{aI4t!ErmyD->q%#!TMR*5*04F4o za*;3vcLN~xGBg&Z_3prFW~=TK_{DI(>O*g#=;Kza`FoYB;qc63eKNVtZ|@f zfAM<$0O89;Lh$SLeU=Bj45%rlSu+v1)U%fJ`iy=&+g@ z*ftC%_IDu4^2SRw&=}@8?P84N4OBjAqRt8|PXc3k2g5G8mkQts(rF3=FT_oJGe8xd|-Fn7>e?3pWW%lUKzdcvBrSXVA!|`D1bd6`p>mjWUR(qlK zf&NyR{??oR)|uYJiQdDI-ouUF!ZRC;zWGO54y_Hq*R7v;kU_T zIEoEDz8YE*)|_j|yJ?)n5eDR>)i!Y%_nwwFm5=_n_R-A|~c}G_{r*J&3@Wq>co-vu5eL=|0%2KxFEL2k6r@jWEY+~7l(1}r&edXWbwr5RPcQ8B;*!<}6zJ_q!i}rB_b0#w5+4oBy)sb7 z4%+>p-{Nfr#qQPV{vdl1KjwC~)l1aP;?8Opb{;sQ7nwL;;*orxJU+|O;`Ti&Q(C}? zpOGmX=vlH^^w1tSYHK7j=WMm}ctoNCWwrU1Cw$y+6F^qyY}MPoe0jCC-D6ZP5Pp@{ z!Ti;C$N&E2(JjrezN*seoYk-ma+{_OxkUzc9%n`#NzPVn66b|oP1irtEUEWvVv=(o zIMM~}M626faL3}>z80CdHcXwm2p)(a-91tTNXRC0+sIngd9bd#2;?e_#d)$?-6qFO z>FJhMlT!=zeM>Q#|6nrd*4LF$hm$AWE^^13&JEC>*$_TCGV(k6=~%7?8&7b3od;1j z=WOd3q)NMYEAZT*N+r9+qVL)_I?BrW zlHn&SfJHk{k-~h!Ctu^4zeAAc8m+F|R=eo`_Qx}l*oAHh>8<|UT?mNFiD2_OV6n>E z92l@0y^$qYy~WX<-N9gB@7!LJ^$j{L@A>1zk!tZsWGJswF?PC2N}k21uBq3}VVvl) z|79n z>{#VJ{Rdb57IE!I=+A}=#e{bPXXTqt+={UPi*?Ho*a)ljY$EiM(JHTKTw8Awu$Wge z>NJVM3`w=uDh-{)&~9Q=lFHPNa*EO2&U$9vU!xyN71fIxqby?f%b@@Er%X^&4L~hS z3EKoy#Kv%SQ|!Ept?LsEy2K=L8hpTtrS5%DkIm-Zh`OvMfg$Y#kiZ*ohUK|U^hUR< zxoi8EA}?=AKp`$j!}k_o`B+%&rDv?^@B?NnXrvW$$B9ck_EIr6WvZ@_Bw_d)#3H%q zX24r;*ydACv(QTkz_IJcKXyyzf*Q(sQ;BDM&qo_z0lE;^h1y5E+ zD=pC+C7T+k@6n@XwnjU;?@a-d-6!HCjd$-X!ms`FvJ}Dx+#L9`*Uuvd?5~kO=dYLz zF0<(@u~xxfr?p=kHm(ZR4?armo=?bPIh6v@CLHNU$-ZHV63XmaA%z1jMVf}_ElqY@ z+GI6UxZpnrJW6?GydZx3t(0MOwY68BcJJAjP^n?XJzqs9*<^^8H^Ltmr*QlBS&yIBuW zK%N{MGXoY5NDG=p-;>YE*scHWp?-m>qN+NHnMtNnQ|9Rw+QwJdH^<+*O5vn<{+8~! zjb2jymuc80NVcpyrP81h>A+7oDTy#R5*8fkp4L$k%m+8HEO04MWT2dmLoVkpDI6D` zPa@m=gLXJf89be6E*#s8a3D?^I47EaabmrAxF7l7b0R{e0>C|$FGV2*X5F?Pq<-Tl z4aVHI1dA^MUt)huwK#Du3Tu*XJ)fN3G`fnU-cgSBI3n>4Q zVn0-zei;sayUT21reUE$4TH{7eOCihX{p_SMKnwcHa>mKpL|5h6gMsg&L6t*`Ep*# z7j9HfNAf-;%7Nm+T5~OSH*sVE#d08LTq@2vxAEH=vVdwiQ){aS*S|HB6a&srMNV%A zPcV*!;%|E7^1n~F7>{2#sRLaG0gc0eMgx#&{ub=L*oYCRz!nf%25G|}ar|2~O|Mvp z`F2Q7{BG^5Z#*5Oe7Q$g1bQiAlTe&zQLDDtBw;)o7zn%My$3WHI8FZn6^TKAfrb*` zW7JNU+l^3P^=$3{3-UnNnW)?WF_L0E0AY;VQ}m75pzr5I+1;9WJq0Uf4YjhXNU@gUmhx^HFQx|K$J(bS~^(FUXT{`YtIpA|?(? zGL8950V+EC^(hhF4}By*&c-}`yq=Nx2(pGN)^)?3@mCN)aoYwb|LCCiE)NDT_&B{g zCjTpGPIYYfH{ZpBTeWjd{b({*PCj>iFdtXJ$y0FvY>BII;)3S`tLmUnaKwB#B{;?W zmVt_c){z6)JeZo}0xSTRxMr!qCWULl+~)+~2=~Z3b1m@tJ%-gkk`hi~pO#X@wdb@Z2srV*AnQBM@}1_wlbAK&UG6|F{95 z75n4~*X*uDzooc;0Luryx*ht9u+a4ng?rP93MYOz!q{Cw_XK<>Q#C;~?w|SFul=pP=H; z{Dbh(2fjW&FXzIOZ7;ZNzA5egxkUoq{(0nc=I3m>x8la3JiM*%Lo>cOr=fr<`dVzA zQ&1#;L76)(d=G}0{F(FKohWLvn=yP#6V9R|i*^?dWZ*;;32U8aSV);a@c@$$R3TJ^ z*V{RVEMaz&0+VBI(-qUCuJ8WyMG6@>8KvdR#Q~YWRA}T-wM!NX@n`376sM_8*vuyJ z_B`Yn8xtxM3YggxNBiO*fnxLd;*ku@8npQ4Pe?s^Kh>)`=?9T8Si}WNm;enJso!u{ zG^~DcaQIRLXCwTADh&IL|En#!SJcuEFZ(5E{L!~~-htjPVQ(RXh2n@uULc2Y()c6O zyxxM}t$bS&a(UJ7h0`5*!TC<&{R3iu0#0CvGf6)#zmgj$(wjQ0xD57q+Q8iW3q;a# z*)wTh%%)|ZC6Q^552Z>`=`vILsVr+;rax1}F~_*J@n*6+$}E&(rnOx zJ*64F6NOuyBu``MDt$>ZJ4nUZ@${0Ne21YBncw>7`)WD0E^95Xp~K3Bm@mYrRg1{S z-_c`#GIA|M_b#0v(p4jNd`E7Q6%JEo?;o7?xXLovs`ONz_$tPETfoJ$pjG+iG=Li$8BVIn~@)}a%xQQuS zhX_?S9`}{(%GnL&uAM4)ntNw`+$5k`-jykQIx%PKRHo|3fS?{F^oj zd?@eIhYQTuI>CSIYlI`z%x>7jyH1(}49~~sZJnCo&2YVcHv@6b`{y;264RFXFv#(e zHu;Pc4PUlcK%2H%b$^bXs5Ba%T-GS;WYm2w5VG;HF63#8Q;a1l7 zc2?_K@)i-@?>B_<$G17#LWq>OV6Ka)LLY;pJ8s%1_o;PFg+EL&dO+^15xiV^&aOy~ zJ3U4xo?VBC&WXep(kp)H4QsGk+e9Lx$_h;SZh;e&OA!RC%@|CdXL-gWv_gV;Y5dR` z_}=@v;a}kpyTik1Bo_zd1=xbRs71UE0e(;0?Lo7}OY95e)Q>FK$D?dwJ&pkr57?l# zeP*JQ5B*Ol6~~R*Le*WWrm;^ez+n%%ede=`9`tv*Cr>sivJx*T7AIUno|c}CbDyFc zx*O%I8XnG{kDo%$?2H{z{e;$kcFz-U3lkz{cU&e=G#@c)0M|OheVV}^h*LSV;;?fC zRbP$HCG6z|{RS@G>W5u2-We9vM}!=0{gwk!&bCY&A2;q+C4|aq!UG*fB;AbWZ%aP~ z4C&=%twLNFAVl$VbOd3%5W?tnr~R+g^PbrN6_vK~m3_@a(65z4zD zV?TfNDz8YA;c9_-tis zUGvvl7#;F}COh<;E@0b7s(iORro#xN{j1h;ovY-gv0QP9-G|vL-WBU4pfoSaV* zrK%uS-SFAE9^y%yl@yLMra(Gl#U!Ge=b0+wJ$kJix5>HK%6PuS67bOr5U<_)kaVC? zjxZ|2pL@Zjgvt)R4n`Wrk=!Mc!L|`|4xX`-?j~5rcZSJ3aqLLWfWo6e1I^hef2&zF zm$I64v^GisCf4k+@is2xhz)3b$p}k!cVz2Z$E5{)yX!10)2FL+RQ$B9+`4afRNcIY zH&H4~3)%1M>}wdoQA+X;ikesY>8R0?pw;#C5KvnD24-;K*7f7aImd@h2ur?K;sZD*o+#yqgYePppb(|@ zz7SUMVjV2jx_&;@~Z+~w9 z$A6cxGI)*Xqy7F(i1xc*eJaxC{R6^qZ@19L^lz(4mSoyCWMlD}`e^GeTxU%+1GcMa zISM|YHW7u#;MOF=NJ)K*7i>IjwIah;n$20iT7$un3)y$corPh<*n*Bn4f0&)2oxje zhjl=6YE!27`9my1cF#f7`&03ykE7X+u^*m1hw5@M#tP07@RuGhX$FaD^6h(XC-%s?=)Nt`Oj|P+hG&{_oYC4($tf|-Q#w`XUnqB-o%I4*=ZA|(hmgv zA~<*NAFLi5d-;NgUmK7B?FxbB6cY+rvo5lh~7H9DY19tP5^$el;>gfu1&~|Ara+QAb*TIck!^Byd5` zYFIZnmrlftqB+=8;^tED5Y&OU z`iDu|&mcx&r@2dRfu|+83IS1-Bf$&Q*|JbBre3Yan2&>eko(h)*Sz{h4-(OP_{hgO14v(8LZX=AstcRQEAG$f`QEE+8pEbwy7$S{`6?2`tSbVUrTxrhD^4H2Tuvv!w z81UNLG3^Q%6dAoMhf!X!6Ae=?P7V{Z(2elA>!fC*t`XCy31PHF7T*S9K3dtxwVecY zU|y{ZbDag}!`qbn$>|>K(9?L6_+#bH>ZW}`G~IDTty~e%n5M1QyPm8^IUSJ?o)Nv_ zCxf{qn8hUbTY{SJ4#d^`MT|EY!Bo?k}#58;i3p2 z!QI=C@+aqrkMv;3NaBAjeRiZyy?_Ubh+4~5+J`p`1(M+J`9?WO%braz@FS?vZl`4gg3o6r(GyDY==hRc;NlEA+-ybKm8Aq zqdxU8A27~!q6C2d*hSyL8QK;$$%!GU`O2I>jQv$5&hUE@^g`@5(@>uS)K{ib4`o=!Q86)f`PA5(dPP$YpLBCN7w9^|v(cwk7KO}PYCcvq` z8yIs3!TJ?B0{a%gi}rgmjO(?OP2l#1MKi9miV&tCoq0ZsGiRDYKHwLm7r3(w8Kkni z3EZB#ob>w@K+skT!g7PDEBCA~`vB81mWA-okQP^fglen4dr@@G>ndG|ls%J~zvCw_ zFIBcEy~U{W5f=9c%T!wr6mloP=SCj{6;-qW2RYp;xdL}~$NoCY=3PN?my>L1a22Gi z700UldCysR*i9`mxcZ014tq0f@^VyV%jGhgK=UxfStw>T5H%;Wj4~JSQ5Y-U2B`5| zSVtAn2GKZ-;XkbVbt}N>3*pOr;OWCVEFPND%@`0{E@C|FPyy=)t>yEZ;K>Jcu*ZvX zcD{mC*#9;zpX!WUXgHBwQ?U<}KmeLRBu9Lv)aIQ0zFrQ4`Y#4Tr5PB57rpVvsQu`6 zx?J&NoL+1It%JQV#y~Jbq61L;GbI`8qv~dwgV`Roal*ZM%R7K6%7$dHOf#UY zfVVsAFFUc3O~{{k?u6~n-^S`Lu>#hCRPqoMs_)F3Olt-hqC`-bV@#^CY}Z z6J@(Pp6=0Z1x4zKp2dC~)%@h=Bnt~^1%WIAilrD5qE2h1Vc;dsd#;V(S!sqI;#I>K z$icu)GwCz7w^uaOK?bH%1jr^iH{YC(hC)!E4rDhR4yi932_QQoixbdJXW-5 z=$4CL1Xw#tw>N*6W|H*hJJ?}mIIQprf+iyyO_$jiL z!uxvYZX*t=T?i2P@idIcX}ZaB-*C5_u@e~C;InDfN}Wk_VQ^;N*^u^&oMNvOt#fKU zwgnUn#WcGf9_SS@+}zt3^2XLS>!FwRvH1#hkc0hhpuCLr!oP_43SAF|E?;(P6?KZk z4VaQ3kAL2=r$|LQ4^zCTLxgmYt-7%PepcLM@rJHu6apgkMNz#?F*?(IZ_ZiQoJ0n~ z?lXHa)}x_shg@KktLK87T})59kx=8{QwUiC=LOX8279C~0PX1>c_-?EgD)Q3qx<91a3YcnG_y^ z$Zmkq2dlH{8{tKO>ggVzC7{|iyeIw;^z+aZ@d_HYgYA9r6$iuFjd*TGu@<>@pnV$}%VXiJY;z4jVmm&b$bPtBh+Kwpr-Gwkg zp9J=k0Qt$lW6TAV;X=ys#)*hZAW-bZ2Js8d78FQ!)JQSa2=#?Hk+%}xlb3iiG4LQe zs73eYob1L4B_630_NH^a2*7dUL>8~vdCr2maa{z^J_Px+g2*odk-P!85W{%r-lj_j z)&bupUldemy2t*HL}&h+PE=VK#i1$VT|PD({|paO{T}u%@nHB8wNrSy$MuGj@_CPp z0?=y+pUwzqsd+$}AT-FU<}e=DmdX0DUEaUy;4!n(VD z*C~OpLHMHXk94|(=es+QM3Ml}Sp#yO74;Y>KN=eFbqC!W`9u%U-f7fqzUqGa=P3so)px-jJwDJTofQ4$=JI ziNaXsI7_m_-9r=a(Es1Dn4}<5@c;D-n6>MvYgo_Ll~3Jbv+#u9z~Sjic*5PY67y(F zn9z=*q-K1G&dtbt#+#I<-S_m=}QU{|;6ddFliH zw>Sm7YkBc?7=PwzO3Y-gO5j(Mf1(lYwR&PzPpk6#2N40KtJa+N5ADKLkLyX3=QEjr z@2iu!6WeUY@$+M4A+6}bbaky$=`EkPN}G#9kcrstTyJR~ndhoYt{V@baxV{`k>4^Q=<&&*p?XF$ zc%+T&)hp+T+J2g|@mz7&)z46uJsAsnTKY)4`lXzlVo1v?4GlG4Ck1U@`KF_naQ(8s zyEh1R?aXwimf7X$NDa~ysUm71Y%?gRN>2Pt@n)X0e(}(+ScG_L-%`>|i-VS4TeYD? zt-&%nGSR6cZ(&mjxStMibBz{Caiwun7UA|3NV>`wf}UfIEYUGtRbu=TSMX!sE3JK} zJVdiSJMV$LMe23}KZ{->LVwdm8l+s}ps6j5PVoPfa_7-d{f!^Mi|hu;I*};E$i9tj zNGMa5Y$;12L|@q_OqK*L!M+^opicQP8VCk3GBu_uze>)hx|1 zy4B}AEPYQ2-YL-u#kAj)Jq?()A4kN0xaDE&IsYbnz+KL$%;J8W04+DMRRvjG0M_YC z8K(AaG%x7pS;vli99HxX0;qscs83@nbBy3KM)rem3iTuoprJN&avmvosf1CY*X^3s z*9n2GDfz5PnOf1?iGfmyG(L?*O^;5X5?S~4Nb~A40TzJ27u=WcY}VptEt>f@-c00y zFIVqg?<4;PEwpZ|%|}!HamN&G&xxzKpWL!iv`y=0`J_jT78cvI00nT?Wczvi=J%=+ z+G*$;q;-iE=cWn&N>O=g@B4U*rH8n!KK!}%uj4$dJI|5u<-kWJ$klJhtfSqGT&|K4 zy^9@ki3_?Bpj52kpd+yn+yOFliLd`MV7IYJ{zKTX3)3=7)SJgS2BEDC4enb0c!UKCaiUd=?-+{|pH%!TKN zEu^h4oSAI*!0D6Q%gjsceZFO@bY>Ij zOZuQLdtG8XRJcV}YgYm?ep+&<)$jlM(@3m=z9GxGSVB?G{&CHQ^o`PrLkG zzK9U(dyQVSZG#f25v~$#Cb!L=x*owWwN+X9iM1hGsyQ+9;!{sHkQ`OF{Wu6l*G#34 zU|1prZzV@>6dG>3ennvXpmS@`s8&y%SZl-IyYs(Xf=0A_$7_9lY9SjFSGEPsJ_Z1U zniY%qB7kE#70}m0$V6jq)_febcVL2(8L8w>PFI;IWWAw28cwG32ZFud6ZJd|k@}?* zboXR>!yn0x{=BNpsZsUYgWpbJ?Y?pCgwE^H`3(jCqw#}0LZ++qW5QjHrP?vVecXk` z#&?cQ7BYtjd%mn!;K*Xk)L3NG+O(D_X~R$(D>|vnyT$VeN6zjiznrWbpD%p)nJ~E< zkyg=ZfqAg5bNz%6ZLNo=_}S4{FtNV*@{-P6LVi$X+IJgGO4?WEv-D;<;Fs*@f^=>a z^*?`}j_kl}%t5)bQ`1YD^13KA0{Z9OYsvHPg&HOZxsK*Pe$?JAseKnF*#)3|;j}xU zPi^c5CRk&&=M*3-jf)@rVw&>`uQ+ogIleZz@s8GytZdNY33A)?q%_4-XZaveD%=}k z;oDl7@PNA-FJExooZ(%qhX~%Y( zWq3X-@dNGa=2hg#H)G?nD~JykrH@(0Nw%T2YT!+$#i@#YuCA`L9mQMF40bSe7UkSA zU5dP>?qIr9XKnk4%N=!X7`KQwNw+@KfP2+AHdAHH>CBu>(j7&Y?KMUx(qGT3-&v&< z%j+%8`FvFTx--PH5xXe_F#xmt#toOCxy(Au+2GnT>2!Rz;iVnl2-7f(R&L7)`VXAN zB9MnTVdVyJbob`UDy^LiK$_!}o8#oafy(Z3=bWSYtp@|iZ46SS_8vRm=ZWsv7l=QJ zV`+&UsY>J$MU9?%`?d_)dDN&u+-Q7~L4HMO3xZBykrG^!xqT3DFWg{?AL+=!@VZ^= z!`$THt#Szp*>)|V@WjXzjKJ8ug4Aqe@bX;gGbaOQIf!l&t9wI;51FD@i&DwwhKZ7U z6f*^wN7zo5v1Mqyh2Rc-L`+QD_M^KIcV92OgW627p~fG$pcdsml3(-f{vJ@Qtrw>z zpuw5iRIF>!!q!rCrjjp!tCW3XDRfN(51nCaNeOKZ)#8^-_ETtvhLXI1Suhsda`JeI z#zZ96xMiQ|;8dw(_%!T{js~7@#tN_yCTFH%s*i8Pgzlb>UTVItICDGHp!b%S(u`S) zX=nkHWn}eH;9rb~Ed?Y`!R`9VKA1-%IU4KT0%t-+$OmC>w%lZT{er_;Ly2}nq9rl( zymh~2i*d`h(E894bw9BgMW(9LQ{nQF*gGwqc9MXZSO`U2Gz+e_v{WL7w(~k``l-zL zhr*d4cGFn3cAU=fQvZb-Z<4l#Z+~MNZ}g(bUK5ujy;naSxvja1?Y%) zzNzT3kZRBdf=>tBz1|GSiM5M$$2Pu%s)wS~>L^NUV1RVUV&YLx4jYqXh=Ex_X50WL zG0NM(zQG-OlgUMcOA{|SGrK{L3h`2y5ucH4LGew6%HKV5tAnn{+Ux90ROtCf+)acX zK9DH6SzZFm(kF>K$6jPezT`qT6#6N~=`x86r5)k52%Di0kP*PiJv&fYgc51idzy&8 zH!LBGCn(EsH$b>e(I4%ZMDwVCSDG+*mhNiEJo_Sa4o4+Ty0yo;Xb>=90$Wr-geK}8 z>=%XjB8_tbD{~6A7-s-tfiYpo=lBW2Hu(k~SjsjlvEK?ehEbPjnZYg<^~n}&^9kVQ zY=U`6&!J2Qi9Ja>ecVm=rAU*+9eZ!lauLBAz*t1F&E@X@-u7TPiLkkrS09K|2K&e6 z9E3{~+SjzEG=Ys_s^teqfoJ#Q#q?bUz8lEk45L!fYiH@LdYC|EwdOE?Jd=a{u2e1hu&GsPa0gUKSJfHyfdt`@Pq=A9Cu=Jlw zqA!U`il728i33G?U=iQ2Z!KOhU1b-k4P(H4OrJWzfi$3jV>=31dJjO+Zu`;$ zRG|?(R7D~RVK;t43-OL7uCzIuJGF(n5bF6#dIz!WGq`d_Ny$`8FdB1u%p<-H{x z!!=(weN;OT!E@vBPY0pW83FhaKY|ufb7-EV8H}RdmPi5vt17b^8i9d~jv53Km>`No zl4uIC;VNhF=s_tZFqy8Je=RUsT6{E)AJ`j08tYHJ(D06a`zCN;_FI1)h_y2(^$-9_ zL7^r{ss)%UfNqhbHVEHUhI~nqV(8%z8qh6hlmMuG2?a!2I;!~te@7HLCHnW?@xLYM z7Br7#)K62<;LX1%x1)z3Ul*iZ%eq|C%;J9lx7Y-+O;ItZenhWD0bk-%0uxXuMJfpd zj~qw>0W%9vKp}R1;F!?C2`EN?4&Wi=2?>NHo?(|AjR*)!K*cCWC!ly%?J}LBE3gkh zz5QRwKog7uX6C@!Md8CvlS=dsOI0j$lZj1g$hu6B%a!E``D4?H)M#}qdri#Kb@Ct{Ui`6X@t`wI(HF3sP5ZN^ z6ir&QNlv&l^r;A|tZu`OGKN<_yjV|~mtLr<{O-dLJf6hx+Gje>VLZI{N_mTh`CD@) z>oatA(o4qnsnzQg@%axr=Oaw*1AU6YrqtwFiVxv>;jp#DNc6VNw*;T@>+u@a=IoKJ*CA~qVGAN9 z7)ZO-c?IQGx52T9tJWeiQKkLTBa#M_8acUUR$#}#ys00biX-4MaJcn(kzsRVu&@4I zPq?<>3q0R(#a9uc@UxeO&sArtQXA4&Sg_Hi5U|zXeua3VD{O znGjanYij^e8jjB6EEUW@#bVo*q+nEgU1RcX*;Yi^c7&VNm4@SDSPxCXGX}3?vwJ#5 zY-jDIdIxQ<0Jl-wkD+EeLjkVId5xx@m#i+bK@_DPR_gGNmzKL**`={7`rcSxUMMZM z`z|eLE@+vX!l?l2>0c5}$+7)j0q}@YPK6?XM>q%n(hqr_W`JcNA&LLMBS`vz#3Skh z3x6Yt!#v_22eFh=1E`6Sf8`O&oHI@}KEljpl1SUz>U_*6>;1g_i;cEw!{Q(CI~|`W z-Wv=rFdG&vk?VO_)Lz9GW!aM%_9MOEbF8d~LlW8~HfMb~kF{;fOE-zqQ_tXbaIj+Z zxhIBPd86+6^P#J!)cWC#oz7{twf-MNRg@p>#xd`Ao*8kEo-5UuAGorX5vg3+iDd8| zZI8cu=hYUA~V56%On}n%-cur&CtrFOXPoyzjtCF7QOUFT z`#mmYIz+933`cm|9T9^YImuq_n;+;Hiw@@M*p2x=ds>Y8dG%+xj4E$!Mv(i#M8!Dv zuZ&M4oc0HQ3|kX@h)vd1C(>Z+xq>70Tf^irQRk5heC?~b0x4G-c8a?lbXF}Kq!5HD zJ4=|?H~1jq!CZ@=u0RUxozF@oS~mgwIni>4MyYaV^ZrDuXH*$#8Mo1gn3CT481*Gb z*%gD)728c^3f=kBQGlIUKlp=2VsWbv{<+nOy54dTjUOHcq5XxmHhm)*Nh4n8&Ay z_U2o!Ab{j~$>{%vc=+je(E9o$`8foUciY<-%67PRA0&J6XpbS%;TR`9za)?1L;>5=`=l4cGN$ z`DeZ1QG5~?baXt4*a-tB;)eDih z;bqCr44oiM9oz&Q2Ztv8&{@B_^+q@|<#beMgGZVm=tiC#a<$n|{c>O>2HK|RECq`Ha7mng{>O%7L5`tyC;X8Z<`j`C-QS1_-eylDyhhz##E?SssNqcge zo*+lniK}`}`?lw2K6@0e4YLm%?Sh-K_SVJ1C=#P{MY3zyc-O8ttS&NOdNl@oj1&hT zZbx?2Ip%BdpLexNcv!EV79ksn4G**vXKQff7H*C#&r$exiG4S(&|=uyhZVPZjO!e;d_v>{i&nT!nVv3 z+00+IEo5yNgJABwdlpTi`l+=SD(vj}P|qZvcglH-XXquu=}Qx1?P=z!h2tznsX9CZ!U3{tOtY&}azxhJYyl}8jAo$4?L-I1Kc8#%Zj8IcO?S*u!Jbo6p} zOnZUa#;(fj75!sfCN_N?IQLg0k2W=9{e{%H`#+>n_aV+aymp#uLFl|?X>-KuX}dJ8CFEYe7|XJ!FeRdkmN(NuJC zSjUtMnlmr#hU<`Yo!8DnbgNliTMR6%wG~i|8q7mb5R&!_N5cGYefN~_P|GMYdx+8vuWLRk4>67t68YmD;~q_~gbSaupfbF*#q_-%1rLAt z?r=&;-i5lpMoaEi7Sbhoo|E4@dAe(Hswvspa6f-*(nkgLl&mVLHf^?{>4tEO4fQ3u z(P|(11or?5`(WczI8VQLD{Eua%-pT<389E~7DKPWfiAh>m~;20&I%L^HA@$THs)9j zbNHV+$LOx3ldOQZ+%&^w;Nr(C94_Z#>Ga@7$zbGvFL4G==${`eYNWeEmCk?PlvL{c z=VL_;0(|>#oBk;=1R4;3W&G(tJY4epC*w_^cJ@}Nuz0i&rINTw%L^Q)BgeB C+4lDU diff --git a/.yarn/cache/resolve-patch-b984c6fd86-c79ecaea36.zip b/.yarn/cache/resolve-patch-bad885c6ea-c79ecaea36.zip similarity index 100% rename from .yarn/cache/resolve-patch-b984c6fd86-c79ecaea36.zip rename to .yarn/cache/resolve-patch-bad885c6ea-c79ecaea36.zip diff --git a/.yarn/cache/typescript-patch-7ad1c7f5d0-dc7141ab55.zip b/.yarn/cache/typescript-patch-1236c99922-dc7141ab55.zip similarity index 100% rename from .yarn/cache/typescript-patch-7ad1c7f5d0-dc7141ab55.zip rename to .yarn/cache/typescript-patch-1236c99922-dc7141ab55.zip diff --git a/yarn.lock b/yarn.lock index 98c3c53fbcc..5918512c385 100644 --- a/yarn.lock +++ b/yarn.lock @@ -7271,7 +7271,7 @@ __metadata: "fsevents@patch:fsevents@~2.3.2#~builtin": version: 2.3.2 - resolution: "fsevents@patch:fsevents@npm%3A2.3.2#~builtin::version=2.3.2&hash=df0bf1" + resolution: "fsevents@patch:fsevents@npm%3A2.3.2#~builtin::version=2.3.2&hash=18f3a7" dependencies: node-gyp: latest conditions: os=darwin @@ -12196,7 +12196,7 @@ fsevents@~2.3.2: "resolve@patch:resolve@^1.1.6#~builtin, resolve@patch:resolve@^1.10.0#~builtin, resolve@patch:resolve@^1.12.0#~builtin, resolve@patch:resolve@^1.14.2#~builtin, resolve@patch:resolve@^1.20.0#~builtin, resolve@patch:resolve@^1.9.0#~builtin": version: 1.22.0 - resolution: "resolve@patch:resolve@npm%3A1.22.0#~builtin::version=1.22.0&hash=c3c19d" + resolution: "resolve@patch:resolve@npm%3A1.22.0#~builtin::version=1.22.0&hash=07638b" dependencies: is-core-module: ^2.8.1 path-parse: ^1.0.7 @@ -13937,7 +13937,7 @@ typescript@^3.9.5: "typescript@patch:typescript@^3.9.5#~builtin": version: 3.9.10 - resolution: "typescript@patch:typescript@npm%3A3.9.10#~builtin::version=3.9.10&hash=3bd3d3" + resolution: "typescript@patch:typescript@npm%3A3.9.10#~builtin::version=3.9.10&hash=f456af" bin: tsc: bin/tsc tsserver: bin/tsserver From 3c6ceb433b877792ad5fcffd95d43ce93a9c74ea Mon Sep 17 00:00:00 2001 From: Djavid Gabibyan Date: Fri, 16 Dec 2022 16:45:48 +0500 Subject: [PATCH 002/170] chore: withdrawals contract updates --- .../withdrawals-contract-documents.json | 110 ++++++++++++++++++ packages/rs-dpp/src/contracts/mod.rs | 1 + .../src/contracts/withdrawals_contract.rs | 20 ++++ .../tests/fixtures/get_documents_fixture.rs | 24 +++- .../fixtures/get_withdrawals_data_contract.rs | 44 +++++++ packages/rs-dpp/src/tests/fixtures/mod.rs | 2 + .../schema/withdrawals-documents.json | 6 + .../test/unit/withdrawalsContract.spec.js | 41 +++++++ 8 files changed, 245 insertions(+), 3 deletions(-) create mode 100644 packages/rs-dpp/contracts/withdrawals/withdrawals-contract-documents.json create mode 100644 packages/rs-dpp/src/contracts/withdrawals_contract.rs create mode 100644 packages/rs-dpp/src/tests/fixtures/get_withdrawals_data_contract.rs diff --git a/packages/rs-dpp/contracts/withdrawals/withdrawals-contract-documents.json b/packages/rs-dpp/contracts/withdrawals/withdrawals-contract-documents.json new file mode 100644 index 00000000000..4a4f27dc40d --- /dev/null +++ b/packages/rs-dpp/contracts/withdrawals/withdrawals-contract-documents.json @@ -0,0 +1,110 @@ +{ + "withdrawal": { + "description": "Withdrawal document to track underlying transaction", + "type": "object", + "indices": [ + { + "name": "pooling", + "properties": [ + { + "status": "asc" + }, + { + "pooling": "asc" + }, + { + "coreFeePerByte": "asc" + }, + { + "$updatedAt": "asc" + } + ], + "unique": false + }, + { + "name": "transaction", + "properties": [ + { + "status": "asc" + }, + { + "transactionId": "asc" + } + ], + "unique": false + }, + { + "name": "ownerId", + "properties": [ + { + "$ownerId": "asc" + } + ], + "unique": false + } + ], + "properties": { + "transactionId": { + "description": "Hash of asset unlock transaction. Populated with untied transaction hash on “pooled” stage and with signed transaction on “broatcasted” stage", + "type": "array", + "byteArray": true, + "minItems": 32, + "maxItems": 32 + }, + "transactionSignHeight": { + "type": "integer", + "description": "The Core height on which transaction was signed", + "minimum": 1 + }, + "transactionIndex": { + "type": "integer", + "description": "Sequential index used to create withdrawal transaction", + "minimum": 1 + }, + "amount": { + "type": "integer", + "description": "The amount to be withdrawn", + "minimum": 1000 + }, + "coreFeePerByte": { + "type": "integer", + "description": "This is the fee that you are willing to spend for this transaction in Duffs/Byte", + "minimum": 1 + }, + "pooling": { + "type": "integer", + "description": "This indicated the level at which Platform should try to pool this transaction", + "enum": [ + 0 + ] + }, + "outputScript": { + "type": "array", + "byteArray": true, + "minItems": 23, + "maxItems": 25 + }, + "status": { + "type": "integer", + "enum": [ + 0, + 1, + 2, + 3, + 4 + ] + } + }, + "additionalProperties": false, + "required": [ + "$createdAt", + "$updatedAt", + "amount", + "coreFeePerByte", + "pooling", + "outputScript", + "transactionIndex", + "status" + ] + } +} diff --git a/packages/rs-dpp/src/contracts/mod.rs b/packages/rs-dpp/src/contracts/mod.rs index b8de2e21572..b426ef7239c 100644 --- a/packages/rs-dpp/src/contracts/mod.rs +++ b/packages/rs-dpp/src/contracts/mod.rs @@ -5,6 +5,7 @@ pub mod dashpay_contract; pub mod dpns_contract; pub mod feature_flags_contract; pub mod masternode_reward_shares_contract; +pub mod withdrawals_contract; /// Contains the system IDs. //? The structure contains the heap-allocated String, which is not memory efficient. diff --git a/packages/rs-dpp/src/contracts/withdrawals_contract.rs b/packages/rs-dpp/src/contracts/withdrawals_contract.rs new file mode 100644 index 00000000000..2f8b322c3f9 --- /dev/null +++ b/packages/rs-dpp/src/contracts/withdrawals_contract.rs @@ -0,0 +1,20 @@ +use super::SystemIDs; + +pub mod types { + pub const WITHDRAWAL: &str = "withdrawal"; +} + +pub mod statuses { + pub const QUEUED: u8 = 0; + pub const POOLED: u8 = 1; + pub const BROADCASTED: u8 = 2; + pub const COMPLETE: u8 = 3; + pub const EXPIRED: u8 = 4; +} + +pub fn system_ids() -> SystemIDs { + SystemIDs { + contract_id: "4fJLR2GYTPFdomuTVvNy3VRrvWgvkKPzqehEBpNf2nk6".to_string(), + owner_id: "CUjAw7eD64wmaznNrfC5sKdn4Lpr1wBvWKMjGLrmEs5h".to_string(), + } +} diff --git a/packages/rs-dpp/src/tests/fixtures/get_documents_fixture.rs b/packages/rs-dpp/src/tests/fixtures/get_documents_fixture.rs index 0f62c96d246..d03ef7e9293 100644 --- a/packages/rs-dpp/src/tests/fixtures/get_documents_fixture.rs +++ b/packages/rs-dpp/src/tests/fixtures/get_documents_fixture.rs @@ -1,8 +1,9 @@ -use serde_json::json; +use serde_json::{json, Value}; use crate::{ - document::document_factory::DocumentFactory, mocks, prelude::*, - tests::utils::generate_random_identifier_struct as gen_owner_id, version::LATEST_VERSION, + contracts::withdrawals_contract, document::document_factory::DocumentFactory, mocks, + prelude::*, tests::utils::generate_random_identifier_struct as gen_owner_id, + version::LATEST_VERSION, }; use super::get_document_validator_fixture; @@ -97,6 +98,23 @@ fn get_documents( Ok(documents) } +pub fn get_withdrawal_document_fixture(data_contract: &DataContract, data: Value) -> Document { + let factory = DocumentFactory::new( + LATEST_VERSION, + get_document_validator_fixture(), + mocks::FetchAndValidateDataContract {}, + ); + + factory + .create( + data_contract.clone(), + data_contract.owner_id.clone(), + withdrawals_contract::types::WITHDRAWAL.to_string(), + data, + ) + .unwrap() +} + fn get_random_10_bytes() -> Vec { let mut buffer = [0u8; 10]; let _ = getrandom::getrandom(&mut buffer); diff --git a/packages/rs-dpp/src/tests/fixtures/get_withdrawals_data_contract.rs b/packages/rs-dpp/src/tests/fixtures/get_withdrawals_data_contract.rs new file mode 100644 index 00000000000..e7254534069 --- /dev/null +++ b/packages/rs-dpp/src/tests/fixtures/get_withdrawals_data_contract.rs @@ -0,0 +1,44 @@ +use std::sync::Arc; + +use lazy_static::lazy_static; +use serde_json::Value; + +use crate::contracts::withdrawals_contract; +use crate::prelude::*; +use crate::util::string_encoding::Encoding; +use crate::{ + data_contract::validation::data_contract_validator::DataContractValidator, + data_contract::DataContractFactory, + tests::utils::generate_random_identifier_struct, + version::{ProtocolVersionValidator, COMPATIBILITY_MAP, LATEST_VERSION}, +}; + +lazy_static! { + static ref WITHDRAWALS_SCHEMA: Value = serde_json::from_str(include_str!( + "./../../../contracts/withdrawals/withdrawals-contract-documents.json" + )) + .expect("withdrawals contract should be valid json"); +} + +pub fn get_withdrawals_data_contract_fixture(owner_id: Option) -> DataContract { + let protocol_version_validator = + ProtocolVersionValidator::new(LATEST_VERSION, LATEST_VERSION, COMPATIBILITY_MAP.clone()); + let data_contract_validator = DataContractValidator::new(Arc::new(protocol_version_validator)); + let factory = DataContractFactory::new(1, data_contract_validator); + + let owner_id = owner_id.unwrap_or_else(generate_random_identifier_struct); + + let withdrawals_schema = WITHDRAWALS_SCHEMA.clone(); + + let mut data_contract = factory + .create(owner_id, withdrawals_schema) + .expect("data in fixture should be correct"); + + data_contract.id = Identifier::from_string( + &withdrawals_contract::system_ids().contract_id, + Encoding::Base58, + ) + .unwrap(); + + data_contract +} diff --git a/packages/rs-dpp/src/tests/fixtures/mod.rs b/packages/rs-dpp/src/tests/fixtures/mod.rs index 77340e7c734..d26e3e70830 100644 --- a/packages/rs-dpp/src/tests/fixtures/mod.rs +++ b/packages/rs-dpp/src/tests/fixtures/mod.rs @@ -26,6 +26,8 @@ mod get_dashpay_document_fixture; mod get_document_transitions_fixture; mod get_document_validator_fixture; pub use get_document_validator_fixture::*; +mod get_withdrawals_data_contract; +pub use get_withdrawals_data_contract::*; mod get_masternode_reward_shares_documents_fixture; pub use get_masternode_reward_shares_documents_fixture::*; diff --git a/packages/withdrawals-contract/schema/withdrawals-documents.json b/packages/withdrawals-contract/schema/withdrawals-documents.json index 9b08af74d5e..4a4f27dc40d 100644 --- a/packages/withdrawals-contract/schema/withdrawals-documents.json +++ b/packages/withdrawals-contract/schema/withdrawals-documents.json @@ -56,6 +56,11 @@ "description": "The Core height on which transaction was signed", "minimum": 1 }, + "transactionIndex": { + "type": "integer", + "description": "Sequential index used to create withdrawal transaction", + "minimum": 1 + }, "amount": { "type": "integer", "description": "The amount to be withdrawn", @@ -98,6 +103,7 @@ "coreFeePerByte", "pooling", "outputScript", + "transactionIndex", "status" ] } diff --git a/packages/withdrawals-contract/test/unit/withdrawalsContract.spec.js b/packages/withdrawals-contract/test/unit/withdrawalsContract.spec.js index b8809615677..a2a1bbdd7ea 100644 --- a/packages/withdrawals-contract/test/unit/withdrawalsContract.spec.js +++ b/packages/withdrawals-contract/test/unit/withdrawalsContract.spec.js @@ -42,6 +42,7 @@ describe('Withdrawals contract', () => { beforeEach(() => { rawWithdrawalDocument = { transactionId: Buffer.alloc(32, 1), + transactionIndex: 42, amount: 1000, coreFeePerByte: 1, pooling: 0, @@ -249,6 +250,46 @@ describe('Withdrawals contract', () => { }); }); + describe('transactionIndex', () => { + it('should be integer', () => { + rawWithdrawalDocument.transactionIndex = 'string'; + + try { + dpp.document.create(dataContract, identityId, 'withdrawal', rawWithdrawalDocument); + + expect.fail('should throw error'); + } catch (e) { + expect(e.name).to.equal('InvalidDocumentError'); + expect(e.getErrors()).to.have.a.lengthOf(1); + + const [error] = e.getErrors(); + + expect(error.name).to.equal('JsonSchemaError'); + expect(error.keyword).to.equal('type'); + expect(error.params.type).to.equal('integer'); + } + }); + + it('should be at least 1', () => { + rawWithdrawalDocument.transactionIndex = 0; + + try { + dpp.document.create(dataContract, identityId, 'withdrawal', rawWithdrawalDocument); + + expect.fail('should throw error'); + } catch (e) { + expect(e.name).to.equal('InvalidDocumentError'); + expect(e.getErrors()).to.have.a.lengthOf(1); + + const [error] = e.getErrors(); + + expect(error.name).to.equal('JsonSchemaError'); + expect(error.keyword).to.equal('minimum'); + expect(error.params.limit).to.equal(1); + } + }); + }); + describe('coreFeePerByte', () => { it('should be present', async () => { delete rawWithdrawalDocument.coreFeePerByte; From 3bf85dfe2bb727d52cdaae5be0ccdb5f004ed267 Mon Sep 17 00:00:00 2001 From: Djavid Gabibyan Date: Fri, 16 Dec 2022 17:14:17 +0500 Subject: [PATCH 003/170] chore: update `verifyVoteExtensionHandler` --- .../verifyVoteExtensionHandlerFactory.js | 45 +++++++++++++++++-- .../verifyVoteExtensionHandlerFactory.spec.js | 45 ++++++++++++++++++- 2 files changed, 86 insertions(+), 4 deletions(-) diff --git a/packages/js-drive/lib/abci/handlers/verifyVoteExtensionHandlerFactory.js b/packages/js-drive/lib/abci/handlers/verifyVoteExtensionHandlerFactory.js index 1c5a56479b9..7e8c3c3d907 100644 --- a/packages/js-drive/lib/abci/handlers/verifyVoteExtensionHandlerFactory.js +++ b/packages/js-drive/lib/abci/handlers/verifyVoteExtensionHandlerFactory.js @@ -3,6 +3,9 @@ const { abci: { ResponseVerifyVoteExtension, }, + types: { + VoteExtensionType, + }, }, } = require('@dashevo/abci/types'); @@ -19,9 +22,12 @@ const verifyStatus = { function verifyVoteExtensionHandlerFactory(proposalBlockExecutionContext) { /** * @typedef verifyVoteExtensionHandler + * + * @param {abci.RequestVerifyVoteExtension} request + * * @return {Promise} */ - async function verifyVoteExtensionHandler() { + async function verifyVoteExtensionHandler({ voteExtensions }) { const consensusLogger = proposalBlockExecutionContext.getConsensusLogger() .child({ abciMethod: 'verifyVoteExtension', @@ -29,10 +35,43 @@ function verifyVoteExtensionHandlerFactory(proposalBlockExecutionContext) { consensusLogger.debug('VerifyVote ABCI method requested'); - // TODO Verify withdrawal vote extensions and add logs + const unsignedWithdrawalTransactionsMap = proposalBlockExecutionContext + .getWithdrawalTransactionsMap(); + + const voteExtensionsToCheck = Object.keys(unsignedWithdrawalTransactionsMap || {}) + .sort() + .map((txHashHex) => ({ + type: VoteExtensionType.THRESHOLD_RECOVER, + extension: Buffer.from(txHashHex, 'hex'), + })); + + const allVoteExtensionsPresent = voteExtensionsToCheck.reduce((result, nextExtension) => { + const searchedVoteExtension = (voteExtensions || []).find((voteExtension) => ( + voteExtension.type == nextExtension.type + && Buffer.compare(voteExtension.extension, nextExtension.extension) + )); + + if (!searchedVoteExtension) { + const extensionString = nextExtension.extension.toString('hex'); + + const extensionTruncatedString = extensionString.substring( + 0, + Math.min(30, extensionString.length), + ); + + consensusLogger.debug({ + type: nextExtension.type, + extension: extensionString, + }, `${nextExtension.type} vote extension ${extensionTruncatedString}... was not found in verify request`); + } + + return result && (searchedVoteExtension != undefined); + }, true); + + let status = allVoteExtensionsPresent ? verifyStatus.ACCEPT : verifyStatus.REJECT; return new ResponseVerifyVoteExtension({ - status: verifyStatus.ACCEPT, + status, }); } diff --git a/packages/js-drive/test/unit/abci/handlers/verifyVoteExtensionHandlerFactory.spec.js b/packages/js-drive/test/unit/abci/handlers/verifyVoteExtensionHandlerFactory.spec.js index d1821dc96de..6f5c1a4e2d6 100644 --- a/packages/js-drive/test/unit/abci/handlers/verifyVoteExtensionHandlerFactory.spec.js +++ b/packages/js-drive/test/unit/abci/handlers/verifyVoteExtensionHandlerFactory.spec.js @@ -3,6 +3,9 @@ const { abci: { ResponseVerifyVoteExtension, }, + types: { + VoteExtensionType, + }, }, } = require('@dashevo/abci/types'); const verifyVoteExtensionHandlerFactory = require('../../../../lib/abci/handlers/verifyVoteExtensionHandlerFactory'); @@ -12,6 +15,7 @@ const LoggerMock = require('../../../../lib/test/mock/LoggerMock'); describe('verifyVoteExtensionHandlerFactory', () => { let verifyVoteExtensionHandler; let proposalBlockExecutionContextMock; + let unsignedWithdrawalTransactionsMapMock; beforeEach(function beforeEach() { proposalBlockExecutionContextMock = new BlockExecutionContextMock(this.sinon); @@ -19,13 +23,52 @@ describe('verifyVoteExtensionHandlerFactory', () => { const loggerMock = new LoggerMock(this.sinon); proposalBlockExecutionContextMock.getConsensusLogger.returns(loggerMock); + unsignedWithdrawalTransactionsMapMock = {}; + proposalBlockExecutionContextMock.getWithdrawalTransactionsMap.returns( + unsignedWithdrawalTransactionsMapMock, + ); + verifyVoteExtensionHandler = verifyVoteExtensionHandlerFactory( proposalBlockExecutionContextMock, ); }); + it('should return ResponseVerifyVoteExtension with REJECT status if vote extension is missing', async () => { + const voteExtensions = [ + { type: VoteExtensionType.THRESHOLD_RECOVER, extension: Buffer.alloc(32, 1) }, + ]; + + const unsignedWithdrawalTransactionsMap = { + [Buffer.alloc(32, 1).toString('hex')]: undefined, + [Buffer.alloc(32, 2).toString('hex')]: undefined, + }; + + proposalBlockExecutionContextMock.getWithdrawalTransactionsMap.returns( + unsignedWithdrawalTransactionsMap, + ); + + const result = await verifyVoteExtensionHandler({ voteExtensions }); + + expect(result).to.be.an.instanceOf(ResponseVerifyVoteExtension); + expect(result.status).to.equal(2); + }); + it('should return ResponseVerifyVoteExtension', async () => { - const result = await verifyVoteExtensionHandler(); + const voteExtensions = [ + { type: VoteExtensionType.THRESHOLD_RECOVER, extension: Buffer.alloc(32, 1) }, + { type: VoteExtensionType.THRESHOLD_RECOVER, extension: Buffer.alloc(32, 2) }, + ]; + + const unsignedWithdrawalTransactionsMap = { + [Buffer.alloc(32, 1).toString('hex')]: undefined, + [Buffer.alloc(32, 2).toString('hex')]: undefined, + }; + + proposalBlockExecutionContextMock.getWithdrawalTransactionsMap.returns( + unsignedWithdrawalTransactionsMap, + ); + + const result = await verifyVoteExtensionHandler({ voteExtensions }); expect(result).to.be.an.instanceOf(ResponseVerifyVoteExtension); expect(result.status).to.equal(1); From a1c69a54a6168e9a7a2e08900dd0ee57e2cefba6 Mon Sep 17 00:00:00 2001 From: Djavid Gabibyan Date: Fri, 16 Dec 2022 17:19:51 +0500 Subject: [PATCH 004/170] chore: use Revision --- .../state/validate_documents_batch_transition_state.rs | 2 +- packages/rs-dpp/src/errors/abstract_state_error.rs | 9 ++++++--- .../validate_identity_update_transition_state.rs | 2 +- .../state/document/invalid_document_revision_error.rs | 8 ++++---- .../state/identity/invalid_identity_revision_error.rs | 8 ++++---- 5 files changed, 16 insertions(+), 13 deletions(-) diff --git a/packages/rs-dpp/src/document/state_transition/documents_batch_transition/validation/state/validate_documents_batch_transition_state.rs b/packages/rs-dpp/src/document/state_transition/documents_batch_transition/validation/state/validate_documents_batch_transition_state.rs index c62eccf20cf..c89a238a01e 100644 --- a/packages/rs-dpp/src/document/state_transition/documents_batch_transition/validation/state/validate_documents_batch_transition_state.rs +++ b/packages/rs-dpp/src/document/state_transition/documents_batch_transition/validation/state/validate_documents_batch_transition_state.rs @@ -250,7 +250,7 @@ fn check_revision( result.add_error(ConsensusError::StateError(Box::new( StateError::InvalidDocumentRevisionError { document_id: document_transition.base().id.clone(), - current_revision: fetched_document.revision, + current_revision: fetched_document.revision as u64, }, ))) } diff --git a/packages/rs-dpp/src/errors/abstract_state_error.rs b/packages/rs-dpp/src/errors/abstract_state_error.rs index 7ebad01077d..7e853b8221b 100644 --- a/packages/rs-dpp/src/errors/abstract_state_error.rs +++ b/packages/rs-dpp/src/errors/abstract_state_error.rs @@ -1,6 +1,9 @@ use thiserror::Error; -use crate::{identity::KeyID, prelude::Identifier}; +use crate::{ + identity::KeyID, + prelude::{Identifier, Revision}, +}; use super::DataTriggerError; @@ -43,7 +46,7 @@ pub enum StateError { )] InvalidDocumentRevisionError { document_id: Identifier, - current_revision: u32, + current_revision: Revision, }, #[error("Data Contract {data_contract_id} is already present")] @@ -57,7 +60,7 @@ pub enum StateError { )] InvalidIdentityRevisionError { identity_id: Identifier, - current_revision: u32, + current_revision: Revision, }, #[error("Duplicated public keys {duplicated_public_key_ids:?} found")] diff --git a/packages/rs-dpp/src/identity/state_transition/identity_update_transition/validate_identity_update_transition_state.rs b/packages/rs-dpp/src/identity/state_transition/identity_update_transition/validate_identity_update_transition_state.rs index 7d40e69a0fe..52ac7791ca2 100644 --- a/packages/rs-dpp/src/identity/state_transition/identity_update_transition/validate_identity_update_transition_state.rs +++ b/packages/rs-dpp/src/identity/state_transition/identity_update_transition/validate_identity_update_transition_state.rs @@ -68,7 +68,7 @@ where if identity.get_revision() != (state_transition.get_revision() - 1) { validation_result.add_error(StateError::InvalidIdentityRevisionError { identity_id: state_transition.get_identity_id().to_owned(), - current_revision: identity.get_revision() as u32, + current_revision: identity.get_revision(), }); return Ok(validation_result); } diff --git a/packages/wasm-dpp/src/errors/consensus/state/document/invalid_document_revision_error.rs b/packages/wasm-dpp/src/errors/consensus/state/document/invalid_document_revision_error.rs index 307171e75ef..775af49d543 100644 --- a/packages/wasm-dpp/src/errors/consensus/state/document/invalid_document_revision_error.rs +++ b/packages/wasm-dpp/src/errors/consensus/state/document/invalid_document_revision_error.rs @@ -1,11 +1,11 @@ use crate::buffer::Buffer; -use dpp::identifier::Identifier; +use dpp::{identifier::Identifier, prelude::Revision}; use wasm_bindgen::prelude::*; #[wasm_bindgen(js_name=InvalidDocumentRevisionError)] pub struct InvalidDocumentRevisionErrorWasm { document_id: Identifier, - current_revision: u32, + current_revision: Revision, code: u32, } @@ -17,7 +17,7 @@ impl InvalidDocumentRevisionErrorWasm { } #[wasm_bindgen(js_name=getCurrentRevision)] - pub fn current_revision(&self) -> u32 { + pub fn current_revision(&self) -> u64 { self.current_revision } @@ -28,7 +28,7 @@ impl InvalidDocumentRevisionErrorWasm { } impl InvalidDocumentRevisionErrorWasm { - pub fn new(document_id: Identifier, current_revision: u32, code: u32) -> Self { + pub fn new(document_id: Identifier, current_revision: Revision, code: u32) -> Self { Self { document_id, current_revision, diff --git a/packages/wasm-dpp/src/errors/consensus/state/identity/invalid_identity_revision_error.rs b/packages/wasm-dpp/src/errors/consensus/state/identity/invalid_identity_revision_error.rs index 949c6346cf7..e7003ab7c4e 100644 --- a/packages/wasm-dpp/src/errors/consensus/state/identity/invalid_identity_revision_error.rs +++ b/packages/wasm-dpp/src/errors/consensus/state/identity/invalid_identity_revision_error.rs @@ -1,11 +1,11 @@ use crate::buffer::Buffer; -use dpp::identifier::Identifier; +use dpp::{identifier::Identifier, prelude::Revision}; use wasm_bindgen::prelude::*; #[wasm_bindgen(js_name=InvalidIdentityRevisionError)] pub struct InvalidIdentityRevisionErrorWasm { identity_id: Identifier, - current_revision: u32, + current_revision: Revision, code: u32, } @@ -17,7 +17,7 @@ impl InvalidIdentityRevisionErrorWasm { } #[wasm_bindgen(js_name=getCurrentRevision)] - pub fn current_revision(&self) -> u32 { + pub fn current_revision(&self) -> u64 { self.current_revision } @@ -28,7 +28,7 @@ impl InvalidIdentityRevisionErrorWasm { } impl InvalidIdentityRevisionErrorWasm { - pub fn new(identity_id: Identifier, current_revision: u32, code: u32) -> Self { + pub fn new(identity_id: Identifier, current_revision: Revision, code: u32) -> Self { Self { identity_id, current_revision, From 85bd2d36b62475f7051ef92d68189971cd8e43ae Mon Sep 17 00:00:00 2001 From: Djavid Gabibyan Date: Fri, 16 Dec 2022 17:49:23 +0500 Subject: [PATCH 005/170] chore: state transition updates --- ...it_withdrawal_transition_core_fee_error.rs | 12 +- ...ty_credit_withdrawal_transition_factory.rs | 104 ++++++++++++------ .../mod.rs | 16 ++- ...tity_credit_withdrawal_transition_basic.rs | 8 +- ...tity_credit_withdrawal_transition_state.rs | 12 +- .../identityCreditWithdrawal.json | 12 +- ...ty_credit_withdrawal_transition_fixture.rs | 6 +- ...edit_withdrawal_transition_factory_spec.rs | 75 +++++++++++-- ...credit_withdrawal_transition_basic_spec.rs | 18 +-- ...e_identity_credit_withdrawal_state_spec.rs | 4 +- 10 files changed, 199 insertions(+), 68 deletions(-) diff --git a/packages/rs-dpp/src/errors/consensus/basic/identity/invalid_credit_withdrawal_transition_core_fee_error.rs b/packages/rs-dpp/src/errors/consensus/basic/identity/invalid_credit_withdrawal_transition_core_fee_error.rs index 9e206b3ca38..2255397688d 100644 --- a/packages/rs-dpp/src/errors/consensus/basic/identity/invalid_credit_withdrawal_transition_core_fee_error.rs +++ b/packages/rs-dpp/src/errors/consensus/basic/identity/invalid_credit_withdrawal_transition_core_fee_error.rs @@ -3,18 +3,18 @@ use thiserror::Error; use crate::consensus::ConsensusError; #[derive(Error, Debug, Clone, PartialEq, Eq)] -#[error("Core fee {core_fee:?} must be part of fibonacci sequence")] +#[error("Core fee per byte {core_fee_per_byte:?} must be part of fibonacci sequence")] pub struct InvalidIdentityCreditWithdrawalTransitionCoreFeeError { - core_fee: u32, + core_fee_per_byte: u32, } impl InvalidIdentityCreditWithdrawalTransitionCoreFeeError { - pub fn new(core_fee: u32) -> Self { - Self { core_fee } + pub fn new(core_fee_per_byte: u32) -> Self { + Self { core_fee_per_byte } } - pub fn core_fee(&self) -> u32 { - self.core_fee + pub fn core_fee_per_byte(&self) -> u32 { + self.core_fee_per_byte } } diff --git a/packages/rs-dpp/src/identity/state_transition/identity_credit_withdrawal_transition/apply_identity_credit_withdrawal_transition_factory.rs b/packages/rs-dpp/src/identity/state_transition/identity_credit_withdrawal_transition/apply_identity_credit_withdrawal_transition_factory.rs index 36a11505bf0..e82821e4400 100644 --- a/packages/rs-dpp/src/identity/state_transition/identity_credit_withdrawal_transition/apply_identity_credit_withdrawal_transition_factory.rs +++ b/packages/rs-dpp/src/identity/state_transition/identity_credit_withdrawal_transition/apply_identity_credit_withdrawal_transition_factory.rs @@ -1,20 +1,25 @@ +use std::convert::TryInto; + use anyhow::{anyhow, Result}; -use dashcore::{ - blockdata::transaction::special_transaction::asset_unlock::unqualified_asset_unlock::{ - AssetUnlockBasePayload, AssetUnlockBaseTransactionInfo, - }, - consensus::Encodable, - Script, TxOut, -}; -use lazy_static::__Deref; +use serde_json::{json, Value as JsonValue}; use crate::{ - identity::convert_credits_to_satoshi, prelude::Identity, state_repository::StateRepositoryLike, + contracts::withdrawals_contract, + data_contract::DataContract, + document::Document, + prelude::Identifier, + prelude::Identity, + state_repository::StateRepositoryLike, + state_transition::StateTransitionConvert, state_transition::StateTransitionLike, + util::{entropy_generator::generate, json_value::JsonValueExt, string_encoding::Encoding}, }; use super::IdentityCreditWithdrawalTransition; +const PLATFORM_BLOCK_HEADER_TIME_PROPERTY: &str = "time"; +const PLATFORM_BLOCK_HEADER_TIME_SECONDS_PROPERTY: &str = "seconds"; + pub struct ApplyIdentityCreditWithdrawalTransition where SR: StateRepositoryLike, @@ -34,37 +39,70 @@ where &self, state_transition: &IdentityCreditWithdrawalTransition, ) -> Result<()> { - let latest_withdrawal_index = self + let data_contract_id = Identifier::from_string( + &withdrawals_contract::system_ids().contract_id, + Encoding::Base58, + )?; + let data_contract_owner_id = Identifier::from_string( + &withdrawals_contract::system_ids().owner_id, + Encoding::Base58, + )?; + + let maybe_withdrawals_data_contract: Option = self .state_repository - .fetch_latest_withdrawal_transaction_index() + .fetch_data_contract(&data_contract_id, state_transition.get_execution_context()) .await?; - let output_script: Script = state_transition.output_script.deref().clone(); + let withdrawals_data_contract = maybe_withdrawals_data_contract + .ok_or_else(|| anyhow!("Withdrawals data contract not found"))?; - let tx_out = TxOut { - value: convert_credits_to_satoshi(state_transition.amount), - script_pubkey: output_script, - }; + let latest_platform_block_header: JsonValue = self + .state_repository + .fetch_latest_platform_block_header() + .await?; - let withdrawal_transaction = AssetUnlockBaseTransactionInfo { - version: 1, - lock_time: 0, - output: vec![tx_out], - base_payload: AssetUnlockBasePayload { - version: 1, - index: latest_withdrawal_index + 1, - fee: state_transition.core_fee, - }, - }; + let document_type = String::from(withdrawals_contract::types::WITHDRAWAL); + let document_entropy = generate(); + let document_created_at_millis = latest_platform_block_header + .get(PLATFORM_BLOCK_HEADER_TIME_PROPERTY) + .ok_or_else(|| anyhow!("time property is not set in block header"))? + .get_i64(PLATFORM_BLOCK_HEADER_TIME_SECONDS_PROPERTY)? + * 1000; + + let document_data = json!({ + "amount": state_transition.amount, + "coreFeePerByte": state_transition.core_fee_per_byte, + "pooling": 0, + "outputScript": state_transition.output_script.as_bytes(), + "status": withdrawals_contract::statuses::QUEUED, + }); - let mut transaction_buffer: Vec = vec![]; + let document_id_bytes: [u8; 32] = state_transition + .hash(true)? + .try_into() + .map_err(|_| anyhow!("Can't convert state transition hash to a document id"))?; - withdrawal_transaction - .consensus_encode(&mut transaction_buffer) - .map_err(|e| anyhow!(e))?; + // TODO: use DocumentFactory once it is complete + let withdrawal_document = Document { + protocol_version: state_transition.protocol_version, + id: Identifier::new(document_id_bytes), + document_type, + revision: 0, + data_contract_id, + owner_id: data_contract_owner_id.clone(), + created_at: Some(document_created_at_millis), + updated_at: Some(document_created_at_millis), + data: document_data, + data_contract: withdrawals_data_contract, + metadata: None, + entropy: document_entropy, + }; self.state_repository - .enqueue_withdrawal_transaction(latest_withdrawal_index, transaction_buffer) + .create_document( + &withdrawal_document, + state_transition.get_execution_context(), + ) .await?; let maybe_existing_identity: Option = self @@ -80,6 +118,10 @@ where existing_identity.reduce_balance(state_transition.amount); + let updated_identity_revision = existing_identity.get_revision() + 1; + + existing_identity.set_revision(updated_identity_revision); + // TODO: we need to be able to batch state repository operations self.state_repository .update_identity(&existing_identity, state_transition.get_execution_context()) diff --git a/packages/rs-dpp/src/identity/state_transition/identity_credit_withdrawal_transition/mod.rs b/packages/rs-dpp/src/identity/state_transition/identity_credit_withdrawal_transition/mod.rs index 3154baf6541..4da32ca01db 100644 --- a/packages/rs-dpp/src/identity/state_transition/identity_credit_withdrawal_transition/mod.rs +++ b/packages/rs-dpp/src/identity/state_transition/identity_credit_withdrawal_transition/mod.rs @@ -5,7 +5,7 @@ use serde_repr::{Deserialize_repr, Serialize_repr}; use crate::{ identity::{core_script::CoreScript, KeyID}, - prelude::Identifier, + prelude::{Identifier, Revision}, state_transition::{ state_transition_execution_context::StateTransitionExecutionContext, StateTransitionConvert, StateTransitionIdentitySigned, StateTransitionLike, @@ -48,9 +48,10 @@ pub struct IdentityCreditWithdrawalTransition { pub transition_type: StateTransitionType, pub identity_id: Identifier, pub amount: u64, - pub core_fee: u32, + pub core_fee_per_byte: u32, pub pooling: Pooling, pub output_script: CoreScript, + pub revision: Revision, pub signature_public_key_id: KeyID, pub signature: Vec, #[serde(skip)] @@ -64,9 +65,10 @@ impl std::default::Default for IdentityCreditWithdrawalTransition { transition_type: StateTransitionType::IdentityCreditWithdrawal, identity_id: Default::default(), amount: Default::default(), - core_fee: Default::default(), + core_fee_per_byte: Default::default(), pooling: Default::default(), output_script: Default::default(), + revision: Default::default(), signature_public_key_id: Default::default(), signature: Default::default(), execution_context: Default::default(), @@ -112,6 +114,14 @@ impl IdentityCreditWithdrawalTransition { pub fn get_modified_data_ids(&self) -> Vec<&Identifier> { vec![&self.identity_id] } + + pub fn set_revision(&mut self, revision: Revision) { + self.revision = revision; + } + + pub fn get_revision(&self) -> Revision { + self.revision + } } impl StateTransitionIdentitySigned for IdentityCreditWithdrawalTransition { diff --git a/packages/rs-dpp/src/identity/state_transition/identity_credit_withdrawal_transition/validation/basic/validate_identity_credit_withdrawal_transition_basic.rs b/packages/rs-dpp/src/identity/state_transition/identity_credit_withdrawal_transition/validation/basic/validate_identity_credit_withdrawal_transition_basic.rs index a5d77c043c6..e0ff1fdc1fd 100644 --- a/packages/rs-dpp/src/identity/state_transition/identity_credit_withdrawal_transition/validation/basic/validate_identity_credit_withdrawal_transition_basic.rs +++ b/packages/rs-dpp/src/identity/state_transition/identity_credit_withdrawal_transition/validation/basic/validate_identity_credit_withdrawal_transition_basic.rs @@ -73,12 +73,14 @@ impl IdentityCreditWithdrawalTransitionBasicValidator { // validate core_fee is in fibonacci sequence let core_fee = transition_json - .get("coreFee") + .get("coreFeePerByte") .ok_or_else(|| { - SerdeParsingError::new("Expected credit withdrawal transition to have coreFee") + SerdeParsingError::new( + "Expected credit withdrawal transition to have coreFeePerByte", + ) })? .as_u64() - .ok_or_else(|| SerdeParsingError::new("Expected coreFee to be a uint"))?; + .ok_or_else(|| SerdeParsingError::new("Expected coreFeePerByte to be a uint"))?; if !is_fibonacci_number(core_fee) { result.add_error(InvalidIdentityCreditWithdrawalTransitionCoreFeeError::new( diff --git a/packages/rs-dpp/src/identity/state_transition/identity_credit_withdrawal_transition/validation/state/validate_identity_credit_withdrawal_transition_state.rs b/packages/rs-dpp/src/identity/state_transition/identity_credit_withdrawal_transition/validation/state/validate_identity_credit_withdrawal_transition_state.rs index bd4c98a892f..e06756ae447 100644 --- a/packages/rs-dpp/src/identity/state_transition/identity_credit_withdrawal_transition/validation/state/validate_identity_credit_withdrawal_transition_state.rs +++ b/packages/rs-dpp/src/identity/state_transition/identity_credit_withdrawal_transition/validation/state/validate_identity_credit_withdrawal_transition_state.rs @@ -9,7 +9,7 @@ use crate::{ state_repository::StateRepositoryLike, state_transition::StateTransitionLike, validation::ValidationResult, - NonConsensusError, + NonConsensusError, StateError, }; pub struct IdentityCreditWithdrawalTransitionValidator @@ -66,6 +66,16 @@ where return Ok(result); } + // Check revision + if existing_identity.get_revision() != (state_transition.get_revision() - 1) { + result.add_error(StateError::InvalidIdentityRevisionError { + identity_id: existing_identity.get_id().to_owned(), + current_revision: existing_identity.get_revision(), + }); + + return Ok(result); + } + Ok(result) } } diff --git a/packages/rs-dpp/src/schema/identity/stateTransition/identityCreditWithdrawal.json b/packages/rs-dpp/src/schema/identity/stateTransition/identityCreditWithdrawal.json index 69692a8a69e..848eca2db42 100644 --- a/packages/rs-dpp/src/schema/identity/stateTransition/identityCreditWithdrawal.json +++ b/packages/rs-dpp/src/schema/identity/stateTransition/identityCreditWithdrawal.json @@ -21,7 +21,7 @@ "type": "integer", "minimum": 1000 }, - "coreFee": { + "coreFeePerByte": { "type": "integer", "minimum": 1 }, @@ -46,6 +46,11 @@ "signaturePublicKeyId": { "type": "integer", "minimum": 0 + }, + "revision": { + "type": "integer", + "minimum": 0, + "description": "State transition revision" } }, "additionalProperties": false, @@ -54,10 +59,11 @@ "type", "identityId", "amount", - "coreFee", + "coreFeePerByte", "pooling", "outputScript", "signature", - "signaturePublicKeyId" + "signaturePublicKeyId", + "revision" ] } diff --git a/packages/rs-dpp/src/tests/fixtures/identity_credit_withdrawal_transition_fixture.rs b/packages/rs-dpp/src/tests/fixtures/identity_credit_withdrawal_transition_fixture.rs index f215f208af8..2f2cc0eaa64 100644 --- a/packages/rs-dpp/src/tests/fixtures/identity_credit_withdrawal_transition_fixture.rs +++ b/packages/rs-dpp/src/tests/fixtures/identity_credit_withdrawal_transition_fixture.rs @@ -14,11 +14,12 @@ pub fn identity_credit_withdrawal_transition_fixture_raw_object() -> Value { "type": StateTransitionType::IdentityCreditWithdrawal, "identityId": vec![1_u8; 32], "amount": 1042, - "coreFee": 2, + "coreFeePerByte": 3, "pooling": Pooling::Never, "outputScript": Script::new_p2pkh(&PubkeyHash::from_hex("0000000000000000000000000000000000000000").unwrap()).to_bytes(), "signature": vec![0_u8; 65], "signaturePublicKeyId": 0, + "revision": 1, }) } @@ -28,10 +29,11 @@ pub fn identity_credit_withdrawal_transition_fixture_json() -> Value { "type": StateTransitionType::IdentityCreditWithdrawal, "identityId": encode(&vec![1_u8; 32], Encoding::Base58), "amount": 1042, - "coreFee": 2, + "coreFeePerByte": 3, "pooling": Pooling::Never, "outputScript": encode(&Script::new_p2pkh(&PubkeyHash::from_hex("0000000000000000000000000000000000000000").unwrap()).to_bytes(), Encoding::Base64), "signature": encode(&vec![0_u8; 65], Encoding::Base64), "signaturePublicKeyId": 0, + "revision": 1, }) } diff --git a/packages/rs-dpp/src/tests/identity/state_transition/identity_credit_withdrawal_transition/apply_identity_credit_withdrawal_transition_factory_spec.rs b/packages/rs-dpp/src/tests/identity/state_transition/identity_credit_withdrawal_transition/apply_identity_credit_withdrawal_transition_factory_spec.rs index 49e9fbd5395..5d0795ff1b7 100644 --- a/packages/rs-dpp/src/tests/identity/state_transition/identity_credit_withdrawal_transition/apply_identity_credit_withdrawal_transition_factory_spec.rs +++ b/packages/rs-dpp/src/tests/identity/state_transition/identity_credit_withdrawal_transition/apply_identity_credit_withdrawal_transition_factory_spec.rs @@ -1,27 +1,88 @@ #[cfg(test)] mod apply_identity_credit_withdrawal_transition_factory { + use std::convert::TryInto; + + use serde_json::json; + use crate::{ + contracts::withdrawals_contract, + data_contract::DataContract, identity::state_transition::identity_credit_withdrawal_transition::{ apply_identity_credit_withdrawal_transition_factory::ApplyIdentityCreditWithdrawalTransition, IdentityCreditWithdrawalTransition, }, prelude::{Identifier, Identity}, state_repository::MockStateRepositoryLike, + state_transition::StateTransitionConvert, + tests::fixtures::get_data_contract_fixture, }; + #[tokio::test] + async fn should_fail_if_data_contract_was_not_found() { + let state_transition = IdentityCreditWithdrawalTransition::default(); + + let mut state_repository = MockStateRepositoryLike::default(); + + state_repository + .expect_fetch_data_contract::>() + .times(1) + .returning(|_, _| anyhow::Ok(None)); + + let applier = ApplyIdentityCreditWithdrawalTransition::new(state_repository); + + match applier + .apply_identity_credit_withdrawal_transition(&state_transition) + .await + { + Ok(_) => assert!(false, "should not be able to apply state transition"), + Err(e) => { + assert_eq!(e.to_string(), "Withdrawals data contract not found"); + } + }; + } + #[tokio::test] async fn should_call_state_repository_methods() { + let block_time_seconds = 1669260925; + + let mut state_transition = IdentityCreditWithdrawalTransition::default(); + + state_transition.amount = 10; + + let st_hash: [u8; 32] = state_transition.hash(true).unwrap().try_into().unwrap(); + let mut state_repository = MockStateRepositoryLike::default(); state_repository - .expect_fetch_latest_withdrawal_transaction_index() + .expect_fetch_data_contract::>() + .times(1) + .returning(|_, _| anyhow::Ok(Some(get_data_contract_fixture(None)))); + + state_repository + .expect_fetch_latest_platform_block_header() .times(1) - // trying to use values other than default to check they are actually set - .returning(|| anyhow::Ok(42)); + .returning(move || anyhow::Ok(json!({"time": {"seconds": block_time_seconds}}))); state_repository - .expect_enqueue_withdrawal_transaction() - .withf(|index, _| *index == 42) + .expect_create_document() + .times(1) + .withf(move |doc, _| { + let id_match = doc.id == Identifier::from_bytes(&st_hash).unwrap(); + + let created_at_match = doc.created_at == Some(block_time_seconds * 1000); + let updated_at_match = doc.created_at == Some(block_time_seconds * 1000); + + let document_data_match = doc.data + == json!({ + "amount": 10, + "coreFeePerByte": 0, + "pooling": 0, + "outputScript": [], + "status": withdrawals_contract::statuses::QUEUED, + }); + + id_match && created_at_match && updated_at_match && document_data_match + }) .returning(|_, _| anyhow::Ok(())); state_repository @@ -49,10 +110,6 @@ mod apply_identity_credit_withdrawal_transition_factory { let applier = ApplyIdentityCreditWithdrawalTransition::new(state_repository); - let mut state_transition = IdentityCreditWithdrawalTransition::default(); - - state_transition.amount = 10; - match applier .apply_identity_credit_withdrawal_transition(&state_transition) .await diff --git a/packages/rs-dpp/src/tests/identity/state_transition/identity_credit_withdrawal_transition/validation/basic/validate_identity_credit_withdrawal_transition_basic_spec.rs b/packages/rs-dpp/src/tests/identity/state_transition/identity_credit_withdrawal_transition/validation/basic/validate_identity_credit_withdrawal_transition_basic_spec.rs index 8882179de60..e5bca9ca153 100644 --- a/packages/rs-dpp/src/tests/identity/state_transition/identity_credit_withdrawal_transition/validation/basic/validate_identity_credit_withdrawal_transition_basic_spec.rs +++ b/packages/rs-dpp/src/tests/identity/state_transition/identity_credit_withdrawal_transition/validation/basic/validate_identity_credit_withdrawal_transition_basic_spec.rs @@ -282,14 +282,14 @@ mod validate_identity_credit_withdrawal_transition_basic_factory { } } - mod core_fee { + mod core_fee_per_byte { use super::*; #[tokio::test] async fn should_be_present() { let (mut raw_state_transition, validator) = setup_test(); - raw_state_transition.remove_key("coreFee"); + raw_state_transition.remove_key("coreFeePerByte"); let result = validator.validate(&raw_state_transition).await.unwrap(); @@ -302,7 +302,7 @@ mod validate_identity_credit_withdrawal_transition_basic_factory { match error.kind() { ValidationErrorKind::Required { property } => { - assert_eq!(property.to_string(), "\"coreFee\""); + assert_eq!(property.to_string(), "\"coreFeePerByte\""); } _ => panic!("Expected to be missing property"), } @@ -312,7 +312,7 @@ mod validate_identity_credit_withdrawal_transition_basic_factory { async fn should_be_integer() { let (mut raw_state_transition, validator) = setup_test(); - raw_state_transition.set_key_value("coreFee", "1"); + raw_state_transition.set_key_value("coreFeePerByte", "1"); let result = validator.validate(&raw_state_transition).await.unwrap(); @@ -320,7 +320,7 @@ mod validate_identity_credit_withdrawal_transition_basic_factory { let error = errors.first().unwrap(); - assert_eq!(error.instance_path().to_string(), "/coreFee"); + assert_eq!(error.instance_path().to_string(), "/coreFeePerByte"); assert_eq!(error.keyword().unwrap(), "type"); } @@ -328,7 +328,7 @@ mod validate_identity_credit_withdrawal_transition_basic_factory { pub async fn should_be_not_less_than_1() { let (mut raw_state_transition, validator) = setup_test(); - raw_state_transition.set_key_value("coreFee", -1); + raw_state_transition.set_key_value("coreFeePerByte", -1); let result = validator.validate(&raw_state_transition).await.unwrap(); @@ -336,7 +336,7 @@ mod validate_identity_credit_withdrawal_transition_basic_factory { let error = errors.first().unwrap(); - assert_eq!(error.instance_path().to_string(), "/coreFee"); + assert_eq!(error.instance_path().to_string(), "/coreFeePerByte"); assert_eq!(error.keyword().unwrap(), "minimum"); } @@ -344,7 +344,7 @@ mod validate_identity_credit_withdrawal_transition_basic_factory { pub async fn should_be_in_a_fibonacci_sequence() { let (mut raw_state_transition, validator) = setup_test(); - raw_state_transition.set_key_value("coreFee", 6); + raw_state_transition.set_key_value("coreFeePerByte", 6); let result = validator.validate(&raw_state_transition).await.unwrap(); @@ -356,7 +356,7 @@ mod validate_identity_credit_withdrawal_transition_basic_factory { let error = errors.first().unwrap(); - assert_eq!(error.core_fee(), 6); + assert_eq!(error.core_fee_per_byte(), 6); } } diff --git a/packages/rs-dpp/src/tests/identity/state_transition/identity_credit_withdrawal_transition/validation/state/validate_identity_credit_withdrawal_state_spec.rs b/packages/rs-dpp/src/tests/identity/state_transition/identity_credit_withdrawal_transition/validation/state/validate_identity_credit_withdrawal_state_spec.rs index 9bfdff46f49..2934749bfff 100644 --- a/packages/rs-dpp/src/tests/identity/state_transition/identity_credit_withdrawal_transition/validation/state/validate_identity_credit_withdrawal_state_spec.rs +++ b/packages/rs-dpp/src/tests/identity/state_transition/identity_credit_withdrawal_transition/validation/state/validate_identity_credit_withdrawal_state_spec.rs @@ -130,7 +130,9 @@ mod validate_identity_credit_withdrawal_transition_state_factory { anyhow::Ok(Some(identity)) }); - let (state_transition, validator) = setup_test(state_repository, Some(5)); + let (mut state_transition, validator) = setup_test(state_repository, Some(5)); + + state_transition.revision = 1; let result = validator .validate_identity_credit_withdrawal_transition_state(&state_transition) From 0db4008e5fc9214a8d47b151195fa625a472bf89 Mon Sep 17 00:00:00 2001 From: Djavid Gabibyan Date: Sun, 18 Dec 2022 23:58:54 +0500 Subject: [PATCH 006/170] chore: pools --- packages/rs-dpp/src/lib.rs | 2 +- packages/rs-drive-abci/src/abci/handlers.rs | 20 ++ packages/rs-drive-abci/src/abci/messages.rs | 4 + packages/rs-drive/src/drive/identity/mod.rs | 2 + .../src/drive/identity/withdrawal_queue.rs | 170 +---------- .../src/drive/identity/withdrawals/mod.rs | 10 + .../src/drive/identity/withdrawals/paths.rs | 66 +++++ .../src/drive/identity/withdrawals/queue.rs | 203 +++++++++++++ .../withdrawals/transaction_index_counter.rs | 61 ++++ .../identity/withdrawals/withdrawal_status.rs | 271 ++++++++++++++++++ .../withdrawals/withdrawal_transactions.rs | 105 +++++++ packages/rs-drive/src/drive/initialization.rs | 2 +- ...it_withdrawal_transition_core_fee_error.rs | 4 +- 13 files changed, 753 insertions(+), 167 deletions(-) create mode 100644 packages/rs-drive/src/drive/identity/withdrawals/mod.rs create mode 100644 packages/rs-drive/src/drive/identity/withdrawals/paths.rs create mode 100644 packages/rs-drive/src/drive/identity/withdrawals/queue.rs create mode 100644 packages/rs-drive/src/drive/identity/withdrawals/transaction_index_counter.rs create mode 100644 packages/rs-drive/src/drive/identity/withdrawals/withdrawal_status.rs create mode 100644 packages/rs-drive/src/drive/identity/withdrawals/withdrawal_transactions.rs diff --git a/packages/rs-dpp/src/lib.rs b/packages/rs-dpp/src/lib.rs index 89ce59effb6..7524290ae79 100644 --- a/packages/rs-dpp/src/lib.rs +++ b/packages/rs-dpp/src/lib.rs @@ -12,7 +12,7 @@ pub use convertible::Convertible; pub use dash_platform_protocol::DashPlatformProtocol; pub use errors::*; -mod contracts; +pub mod contracts; pub mod data_contract; mod convertible; diff --git a/packages/rs-drive-abci/src/abci/handlers.rs b/packages/rs-drive-abci/src/abci/handlers.rs index 9f33c75c839..015cd668912 100644 --- a/packages/rs-drive-abci/src/abci/handlers.rs +++ b/packages/rs-drive-abci/src/abci/handlers.rs @@ -123,6 +123,15 @@ impl TenderdashAbci for Platform { self.block_execution_context .replace(Some(block_execution_context)); + self.drive.update_withdrawal_statuses( + request.last_synced_core_height, + request.core_chain_locked_height, + request.block_time_ms, + request.block_height, + epoch_info.current_epoch_index, + transaction, + )?; + let unsigned_withdrawal_transaction_bytes = self .fetch_and_prepare_unsigned_withdrawal_transactions( request.block_height as u32, @@ -152,6 +161,13 @@ impl TenderdashAbci for Platform { ), ))?; + self.drive.pool_withdrawals_into_transactions( + block_execution_context.block_info.block_time_ms, + block_execution_context.block_info.block_height, + block_execution_context.epoch_info.current_epoch_index, + transaction, + )?; + // Process fees let process_block_fees_result = self.process_block_fees( &block_execution_context.block_info, @@ -283,6 +299,8 @@ mod tests { proposer_pro_tx_hash: proposers [block_height as usize % (proposers_count as usize)], validator_set_quorum_hash: Default::default(), + last_synced_core_height: 1, + core_chain_locked_height: 1, }; let block_begin_response = platform @@ -471,6 +489,8 @@ mod tests { proposer_pro_tx_hash: proposers [block_height as usize % (proposers_count as usize)], validator_set_quorum_hash: Default::default(), + last_synced_core_height: 1, + core_chain_locked_height: 1, }; let block_begin_response = platform diff --git a/packages/rs-drive-abci/src/abci/messages.rs b/packages/rs-drive-abci/src/abci/messages.rs index 9149a083b4c..9c7b403badb 100644 --- a/packages/rs-drive-abci/src/abci/messages.rs +++ b/packages/rs-drive-abci/src/abci/messages.rs @@ -64,6 +64,10 @@ pub struct BlockBeginRequest { pub proposer_pro_tx_hash: [u8; 32], /// Validator set quorum hash pub validator_set_quorum_hash: [u8; 32], + /// Last synced core height + pub last_synced_core_height: u64, + /// Core chain locked height + pub core_chain_locked_height: u64, } /// A struct for handling block begin responses diff --git a/packages/rs-drive/src/drive/identity/mod.rs b/packages/rs-drive/src/drive/identity/mod.rs index 8c28b9ee53b..28028b304cc 100644 --- a/packages/rs-drive/src/drive/identity/mod.rs +++ b/packages/rs-drive/src/drive/identity/mod.rs @@ -51,6 +51,8 @@ use crate::fee::op::DriveOperation; use crate::fee::{calculate_fee, FeeResult}; pub mod withdrawal_queue; +/// Everything related to withdrawals +pub mod withdrawals; const IDENTITY_KEY: [u8; 1] = [0]; diff --git a/packages/rs-drive/src/drive/identity/withdrawal_queue.rs b/packages/rs-drive/src/drive/identity/withdrawal_queue.rs index 779e0ec95eb..e756aa11e3f 100644 --- a/packages/rs-drive/src/drive/identity/withdrawal_queue.rs +++ b/packages/rs-drive/src/drive/identity/withdrawal_queue.rs @@ -43,171 +43,15 @@ use crate::error::Error; use crate::fee::op::DriveOperation; /// constant id for transaction counter -pub const WITHDRAWAL_TRANSACTIONS_COUNTER_ID: [u8; 1] = [0]; -/// constant id for subtree containing transactions queue -pub const WITHDRAWAL_TRANSACTIONS_QUEUE_ID: [u8; 1] = [1]; - -type WithdrawalTransaction = (Vec, Vec); - -/// Add operations for creating initial withdrawal state structure -pub fn add_initial_withdrawal_state_structure_operations(batch: &mut GroveDbOpBatch) { - batch.add_insert_empty_tree(vec![], vec![RootTree::WithdrawalTransactions as u8]); - - batch.add_insert( - vec![vec![RootTree::WithdrawalTransactions as u8]], - WITHDRAWAL_TRANSACTIONS_COUNTER_ID.to_vec(), - Element::Item(0u64.to_be_bytes().to_vec(), None), - ); - - batch.add_insert_empty_tree( - vec![vec![RootTree::WithdrawalTransactions as u8]], - WITHDRAWAL_TRANSACTIONS_QUEUE_ID.to_vec(), - ); -} - -impl Drive { - /// Get latest withdrawal index in a queue - pub fn fetch_latest_withdrawal_transaction_index( - &self, - transaction: TransactionArg, - ) -> Result { - let result = self - .grove - .get( - [Into::<&[u8; 1]>::into(RootTree::WithdrawalTransactions).as_slice()], - &WITHDRAWAL_TRANSACTIONS_COUNTER_ID, - transaction, - ) - .unwrap() - .map_err(Error::GroveDB); - - if let Err(Error::GroveDB(grovedb::Error::PathKeyNotFound(_))) = &result { - return Ok(0); - } - - let element = result?; - - if let Element::Item(counter_bytes, _) = element { - let counter = u64::from_be_bytes(counter_bytes.try_into().map_err(|_| { - DriveError::CorruptedWithdrawalTransactionsCounterInvalidLength( - "withdrawal transactions counter must be an u64", - ) - })?); - - Ok(counter) - } else { - Err(Error::Drive( - DriveError::CorruptedWithdrawalTransactionsCounterNotItem( - "withdrawal transactions counter must be an item", - ), - )) - } - } +// pub const WITHDRAWAL_TRANSACTIONS_COUNTER_ID: [u8; 1] = [0]; +// /// constant id for subtree containing transactions queue +// pub const WITHDRAWAL_TRANSACTIONS_QUEUE_ID: [u8; 1] = [1]; +// /// constant id for subtree containing expired transaction ids +// pub const WITHDRAWAL_TRANSACTIONS_EXPIRED_IDS: [u8; 1] = [2]; - /// Add counter update operations to the batch - pub fn add_update_withdrawal_index_counter_operation( - &self, - batch: &mut GroveDbOpBatch, - value: Vec, - ) { - batch.add_insert( - vec![vec![RootTree::WithdrawalTransactions as u8]], - WITHDRAWAL_TRANSACTIONS_COUNTER_ID.to_vec(), - Element::Item(value, None), - ); - } +// type WithdrawalTransaction = (Vec, Vec); - /// Add insert operations for withdrawal transactions to the batch - pub fn add_enqueue_withdrawal_transaction_operations( - &self, - batch: &mut GroveDbOpBatch, - withdrawals: Vec<(Vec, Vec)>, - ) { - for (id, bytes) in withdrawals { - batch.add_insert( - vec![ - vec![RootTree::WithdrawalTransactions as u8], - WITHDRAWAL_TRANSACTIONS_QUEUE_ID.to_vec(), - ], - id, - Element::Item(bytes, None), - ); - } - } - - /// Get specified amount of withdrawal transactions from the DB - pub fn dequeue_withdrawal_transactions( - &self, - num_of_transactions: u16, - transaction: TransactionArg, - ) -> Result, Error> { - let mut query = Query::new(); - - query.insert_item(QueryItem::RangeFull(RangeFull)); - - let path_query = PathQuery { - path: vec![ - vec![RootTree::WithdrawalTransactions as u8], - WITHDRAWAL_TRANSACTIONS_QUEUE_ID.to_vec(), - ], - query: SizedQuery { - query, - limit: Some(num_of_transactions), - offset: None, - }, - }; - - let result_items = self - .grove - .query_raw(&path_query, QueryKeyElementPairResultType, transaction) - .unwrap() - .map_err(Error::GroveDB)? - .0 - .to_key_elements(); - - let withdrawals = result_items - .into_iter() - .map(|(id, element)| match element { - Element::Item(bytes, _) => Ok((id, bytes)), - _ => Err(Error::Drive(DriveError::CorruptedWithdrawalNotItem( - "withdrawal is not an item", - ))), - }) - .collect::, Vec)>, Error>>()?; - - if !withdrawals.is_empty() { - let mut batch_operations: Vec = vec![]; - let mut drive_operations: Vec = vec![]; - - let withdrawals_path: [&[u8]; 2] = [ - Into::<&[u8; 1]>::into(RootTree::WithdrawalTransactions), - &WITHDRAWAL_TRANSACTIONS_QUEUE_ID, - ]; - - for (id, _) in withdrawals.iter() { - self.batch_delete( - withdrawals_path, - id, - // we know that we are not deleting a subtree - BatchDeleteApplyType::StatefulBatchDelete { - is_known_to_be_subtree_with_sum: Some((false, false)), - }, - transaction, - &mut batch_operations, - )?; - } - - self.apply_batch_drive_operations( - None, - transaction, - batch_operations, - &mut drive_operations, - )?; - } - - Ok(withdrawals) - } -} +impl Drive {} #[cfg(test)] mod tests { diff --git a/packages/rs-drive/src/drive/identity/withdrawals/mod.rs b/packages/rs-drive/src/drive/identity/withdrawals/mod.rs new file mode 100644 index 00000000000..06232d183bf --- /dev/null +++ b/packages/rs-drive/src/drive/identity/withdrawals/mod.rs @@ -0,0 +1,10 @@ +/// Functions and constants related to GroveDB paths +pub mod paths; +/// Functions related to withdrawal queue +pub mod queue; +/// Functions related to transaction index counter +pub mod transaction_index_counter; +/// Functions related to updating of a withdrawal status +pub mod withdrawal_status; +/// Functions reated to withdrawal transactions +pub mod withdrawal_transactions; diff --git a/packages/rs-drive/src/drive/identity/withdrawals/paths.rs b/packages/rs-drive/src/drive/identity/withdrawals/paths.rs new file mode 100644 index 00000000000..fd2a6156ba1 --- /dev/null +++ b/packages/rs-drive/src/drive/identity/withdrawals/paths.rs @@ -0,0 +1,66 @@ +use grovedb::Element; + +use crate::drive::{batch::GroveDbOpBatch, RootTree}; + +/// constant id for transaction counter +pub const WITHDRAWAL_TRANSACTIONS_COUNTER_ID: [u8; 1] = [0]; +/// constant id for subtree containing transactions queue +pub const WITHDRAWAL_TRANSACTIONS_QUEUE_ID: [u8; 1] = [1]; +/// constant id for subtree containing expired transaction ids +pub const WITHDRAWAL_TRANSACTIONS_EXPIRED_IDS: [u8; 1] = [2]; + +/// Simple type alias for withdrawal transaction with it's id +pub type WithdrawalTransaction = (Vec, Vec); + +/// Add operations for creating initial withdrawal state structure +pub fn add_initial_withdrawal_state_structure_operations(batch: &mut GroveDbOpBatch) { + batch.add_insert_empty_tree(vec![], vec![RootTree::WithdrawalTransactions as u8]); + + batch.add_insert( + vec![vec![RootTree::WithdrawalTransactions as u8]], + WITHDRAWAL_TRANSACTIONS_COUNTER_ID.to_vec(), + Element::Item(0u64.to_be_bytes().to_vec(), None), + ); + + batch.add_insert_empty_tree( + vec![vec![RootTree::WithdrawalTransactions as u8]], + WITHDRAWAL_TRANSACTIONS_QUEUE_ID.to_vec(), + ); + + batch.add_insert_empty_tree( + vec![vec![RootTree::WithdrawalTransactions as u8]], + WITHDRAWAL_TRANSACTIONS_EXPIRED_IDS.to_vec(), + ); +} + +/// Helper function to get queue path as Vec +pub fn get_withdrawal_transactions_queue_path() -> Vec> { + vec![ + vec![RootTree::WithdrawalTransactions as u8], + WITHDRAWAL_TRANSACTIONS_QUEUE_ID.to_vec(), + ] +} + +/// Helper function to get queue path as [u8] +pub fn get_withdrawal_transactions_queue_path_as_u8() -> [&'static [u8]; 2] { + [ + Into::<&[u8; 1]>::into(RootTree::WithdrawalTransactions), + &WITHDRAWAL_TRANSACTIONS_QUEUE_ID, + ] +} + +/// Helper function to get expired ids path as Vec +pub fn get_withdrawal_transactions_expired_ids_path() -> Vec> { + vec![ + vec![RootTree::WithdrawalTransactions as u8], + WITHDRAWAL_TRANSACTIONS_EXPIRED_IDS.to_vec(), + ] +} + +/// Helper function to get expired ids path as [u8] +pub fn get_withdrawal_transactions_expired_ids_path_as_u8() -> [&'static [u8]; 2] { + [ + Into::<&[u8; 1]>::into(RootTree::WithdrawalTransactions), + &WITHDRAWAL_TRANSACTIONS_EXPIRED_IDS, + ] +} diff --git a/packages/rs-drive/src/drive/identity/withdrawals/queue.rs b/packages/rs-drive/src/drive/identity/withdrawals/queue.rs new file mode 100644 index 00000000000..d170a7b6ac9 --- /dev/null +++ b/packages/rs-drive/src/drive/identity/withdrawals/queue.rs @@ -0,0 +1,203 @@ +use std::collections::HashMap; + +use dashcore::{ + blockdata::transaction::special_transaction::asset_unlock::unqualified_asset_unlock::{ + AssetUnlockBasePayload, AssetUnlockBaseTransactionInfo, + }, + consensus::Encodable, + Script, TxOut, +}; +use dpp::{ + contracts::withdrawals_contract, + identity::convert_credits_to_satoshi, + prelude::{Document, Identifier}, + util::{hash, json_value::JsonValueExt, string_encoding::Encoding}, +}; +use grovedb::TransactionArg; +use serde_json::{Number, Value as JsonValue}; + +use crate::{ + drive::{batch::GroveDbOpBatch, Drive}, + error::{drive::DriveError, Error}, +}; + +use super::{ + paths::WithdrawalTransaction, + withdrawal_status::{fetch_withdrawal_documents_by_status, update_document_data}, +}; + +fn build_withdrawal_transactions_from_documents( + drive: &Drive, + documents: &[Document], + transaction: TransactionArg, +) -> Result, Error> { + let mut withdrawals: HashMap = HashMap::new(); + + let latest_withdrawal_index = drive.fetch_latest_withdrawal_transaction_index(transaction)?; + + for (i, document) in documents.iter().enumerate() { + let output_script = document.data.get_bytes("outputScript").map_err(|_| { + Error::Drive(DriveError::CorruptedCodeExecution( + "Can't get outputScript from withdrawal document", + )) + })?; + + let amount = document.data.get_u64("amount").map_err(|_| { + Error::Drive(DriveError::CorruptedCodeExecution( + "Can't get amount from withdrawal document", + )) + })?; + + let core_fee_per_byte = document.data.get_u64("coreFeePerByte").map_err(|_| { + Error::Drive(DriveError::CorruptedCodeExecution( + "Can't get coreFeePerByte from withdrawal document", + )) + })?; + + let state_transition_size = 184; + + let output_script: Script = Script::from(output_script); + + let tx_out = TxOut { + value: convert_credits_to_satoshi(amount), + script_pubkey: output_script, + }; + + let transaction_index = latest_withdrawal_index + i as u64; + + let withdrawal_transaction = AssetUnlockBaseTransactionInfo { + version: 1, + lock_time: 0, + output: vec![tx_out], + base_payload: AssetUnlockBasePayload { + version: 1, + index: transaction_index, + fee: (state_transition_size * core_fee_per_byte * 1000) as u32, + }, + }; + + let mut transaction_buffer: Vec = vec![]; + + withdrawal_transaction + .consensus_encode(&mut transaction_buffer) + .map_err(|_| { + Error::Drive(DriveError::CorruptedCodeExecution( + "Can't consensus encode a withdrawal transaction", + )) + })?; + + withdrawals.insert( + document.id.clone(), + ( + transaction_index.to_be_bytes().to_vec(), + transaction_buffer.clone(), + ), + ); + } + + Ok(withdrawals) +} + +impl Drive { + /// Pool withdrawal documents into transactions + pub fn pool_withdrawals_into_transactions( + &self, + block_time_ms: u64, + block_height: u64, + current_epoch_index: u16, + transaction: TransactionArg, + ) -> Result<(), Error> { + let maybe_data_contract = self.get_cached_contract_with_fetch_info( + Identifier::from_string( + &withdrawals_contract::system_ids().contract_id, + Encoding::Base58, + ) + .map_err(|_| { + Error::Drive(DriveError::CorruptedCodeExecution( + "Can't create withdrawals id identifier from string", + )) + })? + .to_buffer(), + transaction, + ); + + let contract_fetch_info = maybe_data_contract.ok_or(Error::Drive( + DriveError::CorruptedCodeExecution("Can't fetch withdrawal data contract"), + ))?; + + let mut documents = fetch_withdrawal_documents_by_status( + self, + withdrawals_contract::statuses::QUEUED, + transaction, + )?; + + let withdrawal_transactions = + build_withdrawal_transactions_from_documents(self, &documents, transaction)?; + + for document in documents.iter_mut() { + let transaction_id = + hash::hash(withdrawal_transactions.get(&document.id).unwrap().1.clone()); + + update_document_data( + self, + &contract_fetch_info.contract, + document, + block_time_ms, + block_height, + current_epoch_index, + transaction, + |document: &mut Document| -> Result<&mut Document, Error> { + document + .data + .insert( + "transactionId".to_string(), + JsonValue::Array( + transaction_id + .clone() + .into_iter() + .map(|byte| JsonValue::Number(Number::from(byte))) + .collect(), + ), + ) + .map_err(|_| { + Error::Drive(DriveError::CorruptedCodeExecution( + "Can't update document field: transactionId", + )) + })?; + + document + .data + .insert( + "status".to_string(), + JsonValue::Number(Number::from(withdrawals_contract::statuses::POOLED)), + ) + .map_err(|_| { + Error::Drive(DriveError::CorruptedCodeExecution( + "Can't update document field: status", + )) + })?; + + document.revision += 1; + + Ok(document) + }, + )?; + } + + let mut batch = GroveDbOpBatch::new(); + + let withdrawal_transactions = withdrawal_transactions + .values() + .into_iter() + .cloned() + .collect(); + + self.add_enqueue_withdrawal_transaction_operations(&mut batch, withdrawal_transactions); + + if !batch.is_empty() { + self.grove_apply_batch(batch, true, transaction)?; + } + + Ok(()) + } +} diff --git a/packages/rs-drive/src/drive/identity/withdrawals/transaction_index_counter.rs b/packages/rs-drive/src/drive/identity/withdrawals/transaction_index_counter.rs new file mode 100644 index 00000000000..b7863048996 --- /dev/null +++ b/packages/rs-drive/src/drive/identity/withdrawals/transaction_index_counter.rs @@ -0,0 +1,61 @@ +use grovedb::{Element, TransactionArg}; + +use crate::{ + drive::{batch::GroveDbOpBatch, Drive, RootTree}, + error::{drive::DriveError, Error}, +}; + +use super::paths::WITHDRAWAL_TRANSACTIONS_COUNTER_ID; + +impl Drive { + /// Get latest withdrawal index in a queue + pub fn fetch_latest_withdrawal_transaction_index( + &self, + transaction: TransactionArg, + ) -> Result { + let result = self + .grove + .get( + [Into::<&[u8; 1]>::into(RootTree::WithdrawalTransactions).as_slice()], + &WITHDRAWAL_TRANSACTIONS_COUNTER_ID, + transaction, + ) + .unwrap() + .map_err(Error::GroveDB); + + if let Err(Error::GroveDB(grovedb::Error::PathKeyNotFound(_))) = &result { + return Ok(0); + } + + let element = result?; + + if let Element::Item(counter_bytes, _) = element { + let counter = u64::from_be_bytes(counter_bytes.try_into().map_err(|_| { + DriveError::CorruptedWithdrawalTransactionsCounterInvalidLength( + "withdrawal transactions counter must be an u64", + ) + })?); + + Ok(counter) + } else { + Err(Error::Drive( + DriveError::CorruptedWithdrawalTransactionsCounterNotItem( + "withdrawal transactions counter must be an item", + ), + )) + } + } + + /// Add counter update operations to the batch + pub fn add_update_withdrawal_index_counter_operation( + &self, + batch: &mut GroveDbOpBatch, + value: Vec, + ) { + batch.add_insert( + vec![vec![RootTree::WithdrawalTransactions as u8]], + WITHDRAWAL_TRANSACTIONS_COUNTER_ID.to_vec(), + Element::Item(value, None), + ); + } +} diff --git a/packages/rs-drive/src/drive/identity/withdrawals/withdrawal_status.rs b/packages/rs-drive/src/drive/identity/withdrawals/withdrawal_status.rs new file mode 100644 index 00000000000..4761ea678a2 --- /dev/null +++ b/packages/rs-drive/src/drive/identity/withdrawals/withdrawal_status.rs @@ -0,0 +1,271 @@ +use dpp::{ + contracts::withdrawals_contract, + data_contract::extra::common, + prelude::{DataContract, Document, Identifier}, + util::{json_value::JsonValueExt, string_encoding::Encoding}, +}; +use grovedb::{Element, TransactionArg}; +use serde_json::{json, Number, Value as JsonValue}; + +use crate::{ + drive::{block_info::BlockInfo, Drive}, + error::{drive::DriveError, Error}, + fee_pools::epochs::Epoch, +}; + +use super::paths::get_withdrawal_transactions_expired_ids_path_as_u8; + +pub(crate) fn fetch_withdrawal_documents_by_status( + drive: &Drive, + status: u8, + transaction: TransactionArg, +) -> Result, Error> { + let query_value = json!({ + "where": [ + ["status", "==", status], + ], + "orderBy": [ + ["$createdAt", "desc"], + ] + }); + + let query_cbor = common::value_to_cbor(query_value, None); + + let (documents, _, _) = drive.query_documents( + &query_cbor, + Identifier::from_string( + &withdrawals_contract::system_ids().contract_id, + Encoding::Base58, + ) + .map_err(|_| { + Error::Drive(DriveError::CorruptedCodeExecution( + "Can't create withdrawals id identifier from string", + )) + })? + .to_buffer(), + withdrawals_contract::types::WITHDRAWAL, + None, + transaction, + )?; + + let documents = documents + .into_iter() + .map(|document_cbor| { + Document::from_cbor(document_cbor).map_err(|_| { + Error::Drive(DriveError::CorruptedCodeExecution( + "Can't create a document from cbor", + )) + }) + }) + .collect::, Error>>()?; + + Ok(documents) +} + +pub(crate) fn update_document_data( + drive: &Drive, + contract: &DataContract, + document: &mut Document, + block_time_ms: u64, + block_height: u64, + current_epoch_index: u16, + transaction: TransactionArg, + update_fn: F, +) -> Result<(), Error> +where + F: Fn(&mut Document) -> Result<&mut Document, Error>, +{ + let document = update_fn(document)?; + + drive.update_document_for_contract_cbor( + &document.to_cbor().map_err(|_| { + Error::Drive(DriveError::CorruptedCodeExecution( + "Can't cbor withdrawal document", + )) + })?, + &contract.to_cbor().map_err(|_| { + Error::Drive(DriveError::CorruptedCodeExecution( + "Can't cbor withdrawal data contract", + )) + })?, + withdrawals_contract::types::WITHDRAWAL, + Some(document.owner_id.to_buffer()), + BlockInfo { + time_ms: block_time_ms, + height: block_height, + epoch: Epoch::new(current_epoch_index), + }, + true, + None, + transaction, + )?; + + Ok(()) +} + +fn fetch_core_block_transactions( + drive: &Drive, + last_synced_core_height: u64, + core_chain_locked_height: u64, +) -> Result, Error> { + // let core_rpc = + // drive + // .core_rpc + // .as_ref() + // .ok_or(Error::Drive(DriveError::CorruptedCodeExecution( + // "Core RPC client has not been set up", + // )))?; + + let mut tx_hashes: Vec = vec![]; + + for height in last_synced_core_height..=core_chain_locked_height { + // let block_hash = core_rpc.get_block_hash(height).map_err(|_| { + // Error::Drive(DriveError::CorruptedCodeExecution( + // "could not get block by height", + // )) + // })?; + + let block_json: JsonValue = JsonValue::Bool(true); + // core_rpc.get_block_json(&block_hash).map_err(|_| { + // Error::Drive(DriveError::CorruptedCodeExecution( + // "could not get block by hash", + // )) + // })?; + + if let Some(transactions) = block_json.get("tx") { + if let Some(transactions) = transactions.as_array() { + for transaction_hash in transactions { + tx_hashes.push( + transaction_hash + .as_str() + .ok_or(Error::Drive(DriveError::CorruptedCodeExecution( + "could not get transaction hash as string", + )))? + .to_string(), + ); + } + } + } + } + + Ok(tx_hashes) +} + +impl Drive { + /// Update statuses for pending withdrawals + pub fn update_withdrawal_statuses( + &self, + last_synced_core_height: u64, + core_chain_locked_height: u64, + block_time_ms: u64, + block_height: u64, + current_epoch_index: u16, + transaction: TransactionArg, + ) -> Result<(), Error> { + let maybe_data_contract = self.get_cached_contract_with_fetch_info( + Identifier::from_string( + &withdrawals_contract::system_ids().contract_id, + Encoding::Base58, + ) + .map_err(|_| { + Error::Drive(DriveError::CorruptedCodeExecution( + "Can't create withdrawals id identifier from string", + )) + })? + .to_buffer(), + transaction, + ); + + let contract_fetch_info = maybe_data_contract.ok_or(Error::Drive( + DriveError::CorruptedCodeExecution("Can't fetch withdrawal data contract"), + ))?; + + let core_transactions = + fetch_core_block_transactions(self, last_synced_core_height, core_chain_locked_height)?; + + let broadcasted_documents = fetch_withdrawal_documents_by_status( + self, + withdrawals_contract::statuses::BROADCASTED, + transaction, + )?; + + for mut document in broadcasted_documents { + let transaction_sign_height = + document + .data + .get_u64("transactionSignHeight") + .map_err(|_| { + Error::Drive(DriveError::CorruptedCodeExecution( + "Can't get transactionSignHeight from withdrawal document", + )) + })?; + + let transaction_id_bytes = document.data.get_bytes("transactionId").map_err(|_| { + Error::Drive(DriveError::CorruptedCodeExecution( + "Can't get transactionId from withdrawal document", + )) + })?; + + let transaction_id = hex::encode(transaction_id_bytes); + + let transaction_index = document.data.get_u64("transactionIdex").map_err(|_| { + Error::Drive(DriveError::CorruptedCodeExecution( + "Can't get transactionIdex from withdrawal document", + )) + })?; + + if core_transactions.contains(&transaction_id) + || core_chain_locked_height - transaction_sign_height > 48 + { + let status = if core_transactions.contains(&transaction_id) { + withdrawals_contract::statuses::COMPLETE + } else { + let bytes = transaction_index.to_be_bytes(); + + let path = get_withdrawal_transactions_expired_ids_path_as_u8(); + + self.grove + .insert( + path, + &bytes, + Element::Item(bytes.to_vec(), None), + None, + transaction, + ) + .unwrap()?; + + withdrawals_contract::statuses::EXPIRED + }; + + update_document_data( + self, + &contract_fetch_info.contract, + &mut document, + block_time_ms, + block_height, + current_epoch_index, + transaction, + |document: &mut Document| -> Result<&mut Document, Error> { + document + .data + .insert( + "status".to_string(), + JsonValue::Number(Number::from(status)), + ) + .map_err(|_| { + Error::Drive(DriveError::CorruptedCodeExecution( + "Can't update document field: status", + )) + })?; + + document.revision += 1; + + Ok(document) + }, + )?; + } + } + + Ok(()) + } +} diff --git a/packages/rs-drive/src/drive/identity/withdrawals/withdrawal_transactions.rs b/packages/rs-drive/src/drive/identity/withdrawals/withdrawal_transactions.rs new file mode 100644 index 00000000000..cbe173cf318 --- /dev/null +++ b/packages/rs-drive/src/drive/identity/withdrawals/withdrawal_transactions.rs @@ -0,0 +1,105 @@ +use std::ops::RangeFull; + +use grovedb::{ + query_result_type::QueryResultType, Element, PathQuery, Query, QueryItem, SizedQuery, + TransactionArg, +}; + +use crate::{ + drive::{batch::GroveDbOpBatch, grove_operations::BatchDeleteApplyType, Drive}, + error::{drive::DriveError, Error}, + fee::op::DriveOperation, +}; + +use super::paths::{ + get_withdrawal_transactions_queue_path, get_withdrawal_transactions_queue_path_as_u8, + WithdrawalTransaction, +}; + +impl Drive { + /// Add insert operations for withdrawal transactions to the batch + pub fn add_enqueue_withdrawal_transaction_operations( + &self, + batch: &mut GroveDbOpBatch, + withdrawals: Vec, + ) { + for (id, bytes) in withdrawals { + batch.add_insert( + get_withdrawal_transactions_queue_path(), + id, + Element::Item(bytes, None), + ); + } + } + + /// Get specified amount of withdrawal transactions from the DB + pub fn dequeue_withdrawal_transactions( + &self, + num_of_transactions: u16, + transaction: TransactionArg, + ) -> Result, Error> { + let mut query = Query::new(); + + query.insert_item(QueryItem::RangeFull(RangeFull)); + + let path_query = PathQuery { + path: get_withdrawal_transactions_queue_path(), + query: SizedQuery { + query, + limit: Some(num_of_transactions), + offset: None, + }, + }; + + let result_items = self + .grove + .query_raw( + &path_query, + QueryResultType::QueryKeyElementPairResultType, + transaction, + ) + .unwrap() + .map_err(Error::GroveDB)? + .0 + .to_key_elements(); + + let withdrawals = result_items + .into_iter() + .map(|(id, element)| match element { + Element::Item(bytes, _) => Ok((id, bytes)), + _ => Err(Error::Drive(DriveError::CorruptedWithdrawalNotItem( + "withdrawal is not an item", + ))), + }) + .collect::, Vec)>, Error>>()?; + + if !withdrawals.is_empty() { + let mut batch_operations: Vec = vec![]; + let mut drive_operations: Vec = vec![]; + + let withdrawals_path: [&[u8]; 2] = get_withdrawal_transactions_queue_path_as_u8(); + + for (id, _) in withdrawals.iter() { + self.batch_delete( + withdrawals_path, + id, + // we know that we are not deleting a subtree + BatchDeleteApplyType::StatefulBatchDelete { + is_known_to_be_subtree_with_sum: Some((false, false)), + }, + transaction, + &mut batch_operations, + )?; + } + + self.apply_batch_drive_operations( + None, + transaction, + batch_operations, + &mut drive_operations, + )?; + } + + Ok(withdrawals) + } +} diff --git a/packages/rs-drive/src/drive/initialization.rs b/packages/rs-drive/src/drive/initialization.rs index d3a27f24e0a..04f6fbe2ba1 100644 --- a/packages/rs-drive/src/drive/initialization.rs +++ b/packages/rs-drive/src/drive/initialization.rs @@ -37,7 +37,7 @@ use crate::error::Error; use crate::fee_pools::add_create_fee_pool_trees_operations; use grovedb::TransactionArg; -use super::identity::withdrawal_queue::add_initial_withdrawal_state_structure_operations; +use super::identity::withdrawals::paths::add_initial_withdrawal_state_structure_operations; impl Drive { /// Creates the initial state structure. diff --git a/packages/wasm-dpp/src/errors/consensus/basic/identity/invalid_identity_credit_withdrawal_transition_core_fee_error.rs b/packages/wasm-dpp/src/errors/consensus/basic/identity/invalid_identity_credit_withdrawal_transition_core_fee_error.rs index edbe4a7d012..bb2cfa55528 100644 --- a/packages/wasm-dpp/src/errors/consensus/basic/identity/invalid_identity_credit_withdrawal_transition_core_fee_error.rs +++ b/packages/wasm-dpp/src/errors/consensus/basic/identity/invalid_identity_credit_withdrawal_transition_core_fee_error.rs @@ -18,8 +18,8 @@ impl From<&InvalidIdentityCreditWithdrawalTransitionCoreFeeError> #[wasm_bindgen(js_class=InvalidIdentityCreditWithdrawalTransitionCoreFeeError)] impl InvalidIdentityCreditWithdrawalTransitionCoreFeeErrorWasm { #[wasm_bindgen(js_name=getCoreFee)] - pub fn core_fee(&self) -> u32 { - self.inner.core_fee() + pub fn core_fee_per_byte(&self) -> u32 { + self.inner.core_fee_per_byte() } #[wasm_bindgen(js_name=getCode)] From 22e3146e9a1df5fc5f2526e4061aa88ec8eb8826 Mon Sep 17 00:00:00 2001 From: Djavid Gabibyan Date: Mon, 19 Dec 2022 00:12:40 +0500 Subject: [PATCH 007/170] chore: CoreRPC --- Cargo.lock | 169 +++++++++++++++++++------- packages/rs-dpp/Cargo.toml | 2 +- packages/rs-drive-abci/Cargo.toml | 2 +- packages/rs-drive/Cargo.toml | 7 +- packages/rs-drive/src/drive/config.rs | 12 ++ packages/rs-drive/src/drive/mod.rs | 23 ++++ packages/rs-drive/src/lib.rs | 3 + packages/rs-drive/src/rpc/core.rs | 46 +++++++ packages/rs-drive/src/rpc/mod.rs | 2 + 9 files changed, 217 insertions(+), 49 deletions(-) create mode 100644 packages/rs-drive/src/rpc/core.rs create mode 100644 packages/rs-drive/src/rpc/mod.rs diff --git a/Cargo.lock b/Cargo.lock index 98bbaec1c41..69ec71ba1a9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -17,12 +17,6 @@ version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" -[[package]] -name = "ahash" -version = "0.3.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8fd72866655d1904d6b0997d0b07ba561047d070fbe29de039031c641b61217" - [[package]] name = "ahash" version = "0.7.6" @@ -196,7 +190,6 @@ version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "006cc91e1a1d99819bc5b8214be3555c1f0611b169f527a1fdc54ed1f2b745b0" dependencies = [ - "core2", "serde", ] @@ -478,6 +471,7 @@ dependencies = [ "js-sys", "num-integer", "num-traits", + "serde", "time 0.1.45", "wasm-bindgen", "winapi", @@ -574,15 +568,6 @@ version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5827cebf4670468b8772dd191856768aedcb1b0278a04f989f7766351917b9dc" -[[package]] -name = "core2" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "239fa3ae9b63c2dc74bd3fa852d4792b8b305ae64eeede946265b6af62f1fff3" -dependencies = [ - "memchr", -] - [[package]] name = "costs" version = "0.0.0" @@ -793,16 +778,49 @@ dependencies = [ "syn", ] +[[package]] +name = "darling" +version = "0.14.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0dd3cd20dc6b5a876612a6e5accfe7f3dd883db6d07acfbf14c128f61550dfa" +dependencies = [ + "darling_core", + "darling_macro", +] + +[[package]] +name = "darling_core" +version = "0.14.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a784d2ccaf7c98501746bf0be29b2022ba41fd62a2e622af997a03e9f972859f" +dependencies = [ + "fnv", + "ident_case", + "proc-macro2", + "quote", + "strsim", + "syn", +] + +[[package]] +name = "darling_macro" +version = "0.14.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7618812407e9402654622dd402b0a89dff9ba93badd6540781526117b92aab7e" +dependencies = [ + "darling_core", + "quote", + "syn", +] + [[package]] name = "dashcore" version = "0.29.1" -source = "git+https://github.com/dashevo/rust-dashcore?branch=master#6092d584487918c5330fec93152e4df06a714067" +source = "git+https://github.com/dashevo/rust-dashcore?rev=6092d584487918c5330fec93152e4df06a714067#6092d584487918c5330fec93152e4df06a714067" dependencies = [ "anyhow", "bech32", "bitcoin_hashes", - "core2", - "hashbrown 0.8.2", "hex", "rustversion", "secp256k1", @@ -810,18 +828,26 @@ dependencies = [ ] [[package]] -name = "dashcore" -version = "0.29.1" -source = "git+https://github.com/dashpay/rust-dashcore?branch=master#6092d584487918c5330fec93152e4df06a714067" +name = "dashcore-rpc" +version = "0.15.0" +source = "git+https://github.com/jawid-h/rust-dashcore-rpc?branch=fix/attempt-to-fix#2b4156aac527eb91ee9882f6575766b59a226ef9" dependencies = [ - "anyhow", - "bech32", - "bitcoin_hashes", - "core2", - "hashbrown 0.8.2", - "hex", - "rustversion", - "secp256k1", + "dashcore-rpc-json", + "jsonrpc", + "log", + "serde", + "serde_json", +] + +[[package]] +name = "dashcore-rpc-json" +version = "0.15.0" +source = "git+https://github.com/jawid-h/rust-dashcore-rpc?branch=fix/attempt-to-fix#2b4156aac527eb91ee9882f6575766b59a226ef9" +dependencies = [ + "dashcore", + "serde", + "serde_json", + "serde_with", ] [[package]] @@ -868,7 +894,7 @@ dependencies = [ "byteorder", "chrono", "ciborium", - "dashcore 0.29.1 (git+https://github.com/dashevo/rust-dashcore?branch=master)", + "dashcore", "env_logger", "futures", "getrandom", @@ -908,7 +934,8 @@ dependencies = [ "ciborium", "costs", "criterion", - "dashcore 0.29.1 (git+https://github.com/dashpay/rust-dashcore?branch=master)", + "dashcore", + "dashcore-rpc", "dpp", "enum-map", "grovedb", @@ -917,6 +944,7 @@ dependencies = [ "integer-encoding", "intmap", "itertools", + "mockall", "moka", "rand 0.8.5", "rand_distr", @@ -936,7 +964,7 @@ dependencies = [ "bs58", "chrono", "ciborium", - "dashcore 0.29.1 (git+https://github.com/dashpay/rust-dashcore?branch=master)", + "dashcore", "drive", "hex", "rand 0.8.5", @@ -1088,6 +1116,12 @@ dependencies = [ "num-traits", ] +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + [[package]] name = "form_urlencoded" version = "1.1.0" @@ -1294,23 +1328,13 @@ version = "1.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "eabb4a44450da02c90444cf74558da904edde8fb4e9035a9a6a4e15445af0bd7" -[[package]] -name = "hashbrown" -version = "0.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e91b62f79061a0bc2e046024cb7ba44b08419ed238ecbd9adbd787434b9e8c25" -dependencies = [ - "ahash 0.3.8", - "autocfg 1.1.0", -] - [[package]] name = "hashbrown" version = "0.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ab5ef0d4909ef3724cc8cce6ccc8572c5c817592e9285f5464f8e86f8bd3726e" dependencies = [ - "ahash 0.7.6", + "ahash", ] [[package]] @@ -1319,7 +1343,7 @@ version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" dependencies = [ - "ahash 0.7.6", + "ahash", ] [[package]] @@ -1393,6 +1417,12 @@ dependencies = [ "cxx-build", ] +[[package]] +name = "ident_case" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" + [[package]] name = "idna" version = "0.3.0" @@ -1411,6 +1441,7 @@ checksum = "1885e79c1fc4b10f0e172c475f458b7f7b93061064d98c3293e98c5ba0c8b399" dependencies = [ "autocfg 1.1.0", "hashbrown 0.12.3", + "serde", ] [[package]] @@ -1529,12 +1560,23 @@ dependencies = [ "url", ] +[[package]] +name = "jsonrpc" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "248ea3eab5d9a37ee324b1f576f19d274ff7e56cd5206ea4755a7ef918e94fa4" +dependencies = [ + "base64 0.13.1", + "serde", + "serde_json", +] + [[package]] name = "jsonschema" version = "0.15.0" source = "git+https://github.com/qrayven/jsonschema-rs?branch=feat-unknown-format-cutsom-keywords#7a1657bc8acce1b4270a26bce72423b4ba3b7c23" dependencies = [ - "ahash 0.7.6", + "ahash", "anyhow", "base64 0.20.0", "bytecount", @@ -2773,6 +2815,34 @@ dependencies = [ "syn", ] +[[package]] +name = "serde_with" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "25bf4a5a814902cd1014dbccfa4d4560fb8432c779471e96e035602519f82eef" +dependencies = [ + "base64 0.13.1", + "chrono", + "hex", + "indexmap", + "serde", + "serde_json", + "serde_with_macros", + "time 0.3.17", +] + +[[package]] +name = "serde_with_macros" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3452b4c0f6c1e357f73fdb87cd1efabaa12acf328c7a528e252893baeb3f4aa" +dependencies = [ + "darling", + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "sha2" version = "0.9.9" @@ -2879,6 +2949,12 @@ dependencies = [ "visualize", ] +[[package]] +name = "strsim" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" + [[package]] name = "strum" version = "0.24.1" @@ -3050,6 +3126,7 @@ version = "0.3.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a561bf4617eebd33bca6434b988f39ed798e527f51a1e797d0ee4f61c0a38376" dependencies = [ + "itoa 1.0.4", "serde", "time-core", "time-macros", diff --git a/packages/rs-dpp/Cargo.toml b/packages/rs-dpp/Cargo.toml index c0190817844..7bfd08a2162 100644 --- a/packages/rs-dpp/Cargo.toml +++ b/packages/rs-dpp/Cargo.toml @@ -13,7 +13,7 @@ bs58 = "0.4.0" byteorder = { version="1.4"} chrono = { version="0.4.20", default-features=false, features=["wasmbind", "clock"]} ciborium = { version="0.2"} -dashcore = { git="https://github.com/dashevo/rust-dashcore", features=["no-std", "secp-recovery", "rand", "signer", "use-serde"], default-features = false, branch="master" } +dashcore = { git="https://github.com/dashevo/rust-dashcore", features=["std", "secp-recovery", "rand", "signer"], default-features = false, rev = "6092d584487918c5330fec93152e4df06a714067" } env_logger = { version="0.9"} futures = { version ="0.3"} getrandom= { version="0.2", features=["js"]} diff --git a/packages/rs-drive-abci/Cargo.toml b/packages/rs-drive-abci/Cargo.toml index b3678fb8d37..de97b8197c9 100644 --- a/packages/rs-drive-abci/Cargo.toml +++ b/packages/rs-drive-abci/Cargo.toml @@ -20,5 +20,5 @@ tempfile = "3" bs58 = "0.4.0" base64 = "0.13.0" hex = "0.4.3" -dashcore = { git="https://github.com/dashpay/rust-dashcore", features=["no-std", "secp-recovery", "rand", "signer"], default-features = false, branch="master" } +dashcore = { git="https://github.com/dashevo/rust-dashcore", features=["std", "secp-recovery", "rand", "signer"], default-features = false, rev = "6092d584487918c5330fec93152e4df06a714067" } diff --git a/packages/rs-drive/Cargo.toml b/packages/rs-drive/Cargo.toml index 92d40e4002b..ec2ba039c29 100644 --- a/packages/rs-drive/Cargo.toml +++ b/packages/rs-drive/Cargo.toml @@ -29,7 +29,9 @@ chrono = "0.4.20" bincode = "1.3.3" dpp = { path = "../rs-dpp" } itertools = { version = "0.10.5" } -dashcore = { git="https://github.com/dashpay/rust-dashcore", features=["no-std", "secp-recovery", "rand", "signer"], default-features = false, branch="master" } +dashcore = { git="https://github.com/dashevo/rust-dashcore", features=["std", "secp-recovery", "rand", "signer"], default-features = false, rev = "6092d584487918c5330fec93152e4df06a714067" } +dashcore-rpc = { git="https://github.com/jawid-h/rust-dashcore-rpc", branch="fix/attempt-to-fix" } +mockall= { version ="0.11", optional = true} [dependencies.grovedb] git = "https://github.com/dashpay/grovedb" @@ -49,3 +51,6 @@ criterion = "0.3.5" [[bench]] name = "benchmarks" harness = false + +[features] +core-rpc-mock = ["mockall"] diff --git a/packages/rs-drive/src/drive/config.rs b/packages/rs-drive/src/drive/config.rs index a40b157fe67..f60b8d38d2e 100644 --- a/packages/rs-drive/src/drive/config.rs +++ b/packages/rs-drive/src/drive/config.rs @@ -71,6 +71,15 @@ pub struct DriveConfig { /// Maximum number of contracts in block candidate cache pub data_contracts_block_cache_size: u64, + + /// Core RPC client url + pub core_rpc_url: Option, + + /// Core RPC client username + pub core_rpc_username: Option, + + /// Core RPC client password + pub core_rpc_password: Option, } impl Default for DriveConfig { @@ -84,6 +93,9 @@ impl Default for DriveConfig { encoding: DriveCbor, data_contracts_global_cache_size: DEFAULT_DATA_CONTRACTS_CACHE_SIZE, data_contracts_block_cache_size: DEFAULT_DATA_CONTRACTS_CACHE_SIZE, + core_rpc_url: None, + core_rpc_password: None, + core_rpc_username: None, } } } diff --git a/packages/rs-drive/src/drive/mod.rs b/packages/rs-drive/src/drive/mod.rs index 56bb09e1b22..ce249987aee 100644 --- a/packages/rs-drive/src/drive/mod.rs +++ b/packages/rs-drive/src/drive/mod.rs @@ -40,6 +40,7 @@ use object_size_info::DocumentInfo::DocumentEstimatedAverageSize; use crate::contract::Contract; use crate::drive::batch::GroveDbOpBatch; use crate::drive::config::DriveConfig; +use crate::error::drive::DriveError; use crate::error::Error; use crate::fee::op::DriveOperation; use crate::fee::op::DriveOperation::GroveOperation; @@ -75,6 +76,7 @@ use crate::drive::block_info::BlockInfo; use crate::drive::cache::{DataContractCache, DriveCache}; use crate::fee::FeeResult; use crate::fee_pools::epochs::Epoch; +use crate::rpc::core::{CoreRPCLike, DefaultCoreRPC}; use dpp::data_contract::extra::DriveContractExt; type TransactionPointerAddress = usize; @@ -87,6 +89,8 @@ pub struct Drive { pub config: DriveConfig, /// Drive Cache pub cache: RefCell, + /// Core RPC Client + pub core_rpc: Option>, } /// Keys for the root tree. @@ -157,6 +161,24 @@ impl Drive { let data_contracts_global_cache_size = config.data_contracts_global_cache_size; let data_contracts_block_cache_size = config.data_contracts_block_cache_size; + let core_rpc: Option> = + if let (Some(url), Some(username), Some(password)) = ( + &config.core_rpc_url, + &config.core_rpc_username, + &config.core_rpc_password, + ) { + Some(Box::new( + DefaultCoreRPC::open(url.clone(), username.clone(), password.clone()) + .map_err(|_| { + Error::Drive(DriveError::CorruptedCodeExecution( + "Could not setup Dash Core RPC client", + )) + })?, + )) + } else { + None + }; + Ok(Drive { grove, config, @@ -167,6 +189,7 @@ impl Drive { ), genesis_time_ms, }), + core_rpc, }) } Err(e) => Err(Error::GroveDB(e)), diff --git a/packages/rs-drive/src/lib.rs b/packages/rs-drive/src/lib.rs index c91d5c6cced..1e571c4a510 100644 --- a/packages/rs-drive/src/lib.rs +++ b/packages/rs-drive/src/lib.rs @@ -28,3 +28,6 @@ pub mod query; pub use dpp; /// GroveDB module pub use grovedb; + +/// Everything related to RPC +pub mod rpc; diff --git a/packages/rs-drive/src/rpc/core.rs b/packages/rs-drive/src/rpc/core.rs new file mode 100644 index 00000000000..faa8ac1d6f2 --- /dev/null +++ b/packages/rs-drive/src/rpc/core.rs @@ -0,0 +1,46 @@ +use dashcore::{Block, BlockHash}; +use dashcore_rpc::{Auth, Client, Error, RpcApi}; +#[cfg(feature = "core-rpc-mock")] +use mockall::{automock, predicate::*}; +use serde_json::Value; + +/// Core RPC interface +#[cfg_attr(feature = "core-rpc-mock", automock)] +pub trait CoreRPCLike { + /// Get block hash by height + fn get_block_hash(&self, height: u64) -> Result; + + /// Get block by hash + fn get_block(&self, block_hash: &BlockHash) -> Result; + + /// Get block by hash in JSON format + fn get_block_json(&self, block_hash: &BlockHash) -> Result; +} + +/// Default implementation of Dash Core RPC using DashCoreRPC client +pub struct DefaultCoreRPC { + inner: Client, +} + +impl DefaultCoreRPC { + /// Create new instance + pub fn open(url: String, username: String, password: String) -> Result { + Ok(DefaultCoreRPC { + inner: Client::new(url.as_str(), Auth::UserPass(username, password))?, + }) + } +} + +impl CoreRPCLike for DefaultCoreRPC { + fn get_block_hash(&self, height: u64) -> Result { + self.inner.get_block_hash(height) + } + + fn get_block(&self, block_hash: &BlockHash) -> Result { + self.inner.get_block(block_hash) + } + + fn get_block_json(&self, block_hash: &BlockHash) -> Result { + self.inner.get_block_json(block_hash) + } +} diff --git a/packages/rs-drive/src/rpc/mod.rs b/packages/rs-drive/src/rpc/mod.rs new file mode 100644 index 00000000000..6575232295f --- /dev/null +++ b/packages/rs-drive/src/rpc/mod.rs @@ -0,0 +1,2 @@ +/// Dash Core RPC +pub mod core; From e838660e2bd79c41baadd9130fa4b672781c9e82 Mon Sep 17 00:00:00 2001 From: Djavid Gabibyan Date: Mon, 19 Dec 2022 00:13:19 +0500 Subject: [PATCH 008/170] chore: CoreRPC --- .../identity/withdrawals/withdrawal_status.rs | 37 +++++++++---------- 1 file changed, 18 insertions(+), 19 deletions(-) diff --git a/packages/rs-drive/src/drive/identity/withdrawals/withdrawal_status.rs b/packages/rs-drive/src/drive/identity/withdrawals/withdrawal_status.rs index 4761ea678a2..6a271b4032a 100644 --- a/packages/rs-drive/src/drive/identity/withdrawals/withdrawal_status.rs +++ b/packages/rs-drive/src/drive/identity/withdrawals/withdrawal_status.rs @@ -108,29 +108,28 @@ fn fetch_core_block_transactions( last_synced_core_height: u64, core_chain_locked_height: u64, ) -> Result, Error> { - // let core_rpc = - // drive - // .core_rpc - // .as_ref() - // .ok_or(Error::Drive(DriveError::CorruptedCodeExecution( - // "Core RPC client has not been set up", - // )))?; + let core_rpc = + drive + .core_rpc + .as_ref() + .ok_or(Error::Drive(DriveError::CorruptedCodeExecution( + "Core RPC client has not been set up", + )))?; let mut tx_hashes: Vec = vec![]; for height in last_synced_core_height..=core_chain_locked_height { - // let block_hash = core_rpc.get_block_hash(height).map_err(|_| { - // Error::Drive(DriveError::CorruptedCodeExecution( - // "could not get block by height", - // )) - // })?; - - let block_json: JsonValue = JsonValue::Bool(true); - // core_rpc.get_block_json(&block_hash).map_err(|_| { - // Error::Drive(DriveError::CorruptedCodeExecution( - // "could not get block by hash", - // )) - // })?; + let block_hash = core_rpc.get_block_hash(height).map_err(|_| { + Error::Drive(DriveError::CorruptedCodeExecution( + "could not get block by height", + )) + })?; + + let block_json: JsonValue = core_rpc.get_block_json(&block_hash).map_err(|_| { + Error::Drive(DriveError::CorruptedCodeExecution( + "could not get block by hash", + )) + })?; if let Some(transactions) = block_json.get("tx") { if let Some(transactions) = transactions.as_array() { From 67c54bfa007c6c3b121ff57c84a05da7383c2648 Mon Sep 17 00:00:00 2001 From: Djavid Gabibyan Date: Mon, 19 Dec 2022 00:30:31 +0500 Subject: [PATCH 009/170] chore: wip --- Cargo.lock | 1 + packages/rs-drive-abci/Cargo.toml | 2 + .../rs-drive-abci/src/common/helpers/setup.rs | 31 ++++++++++++ .../withdrawals/transaction_index_counter.rs | 48 ++++++++++++++++++- 4 files changed, 80 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 69ec71ba1a9..5c09f60f67b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -965,6 +965,7 @@ dependencies = [ "chrono", "ciborium", "dashcore", + "dpp", "drive", "hex", "rand 0.8.5", diff --git a/packages/rs-drive-abci/Cargo.toml b/packages/rs-drive-abci/Cargo.toml index de97b8197c9..91d0b202c2b 100644 --- a/packages/rs-drive-abci/Cargo.toml +++ b/packages/rs-drive-abci/Cargo.toml @@ -22,3 +22,5 @@ base64 = "0.13.0" hex = "0.4.3" dashcore = { git="https://github.com/dashevo/rust-dashcore", features=["std", "secp-recovery", "rand", "signer"], default-features = false, rev = "6092d584487918c5330fec93152e4df06a714067" } +[dev-dependencies] +dpp = { path = "../rs-dpp"} diff --git a/packages/rs-drive-abci/src/common/helpers/setup.rs b/packages/rs-drive-abci/src/common/helpers/setup.rs index 8252755ea27..00cc9afe133 100644 --- a/packages/rs-drive-abci/src/common/helpers/setup.rs +++ b/packages/rs-drive-abci/src/common/helpers/setup.rs @@ -33,6 +33,14 @@ //! use crate::platform::Platform; +#[cfg(test)] +use dpp::prelude::DataContract; +#[cfg(test)] +use drive::{ + drive::{block_info::BlockInfo, Drive}, + fee_pools::epochs::Epoch, + query::TransactionArg, +}; use tempfile::TempDir; /// A function which sets up Platform. @@ -53,3 +61,26 @@ pub fn setup_platform_with_initial_state_structure() -> Platform { platform } + +#[cfg(test)] +/// A function to setup system data contract +pub fn setup_system_data_contract( + drive: &Drive, + data_contract: DataContract, + transaction: TransactionArg, +) { + drive + .apply_contract_cbor( + data_contract.to_cbor().unwrap(), + Some(data_contract.id.to_buffer()), + BlockInfo { + time_ms: 1, + height: 1, + epoch: Epoch::new(1), + }, + true, + None, + transaction, + ) + .unwrap(); +} diff --git a/packages/rs-drive/src/drive/identity/withdrawals/transaction_index_counter.rs b/packages/rs-drive/src/drive/identity/withdrawals/transaction_index_counter.rs index b7863048996..4bf05459ee1 100644 --- a/packages/rs-drive/src/drive/identity/withdrawals/transaction_index_counter.rs +++ b/packages/rs-drive/src/drive/identity/withdrawals/transaction_index_counter.rs @@ -1,11 +1,17 @@ -use grovedb::{Element, TransactionArg}; +use grovedb::{ + query_result_type::{QueryResultElement, QueryResultType}, + Element, PathQuery, Query, SizedQuery, TransactionArg, +}; use crate::{ drive::{batch::GroveDbOpBatch, Drive, RootTree}, error::{drive::DriveError, Error}, }; -use super::paths::WITHDRAWAL_TRANSACTIONS_COUNTER_ID; +use super::paths::{ + get_withdrawal_transactions_expired_ids_path, + get_withdrawal_transactions_expired_ids_path_as_u8, WITHDRAWAL_TRANSACTIONS_COUNTER_ID, +}; impl Drive { /// Get latest withdrawal index in a queue @@ -13,6 +19,44 @@ impl Drive { &self, transaction: TransactionArg, ) -> Result { + let mut inner_query = Query::new(); + + inner_query.insert_all(); + + let expired_index_query = PathQuery::new( + get_withdrawal_transactions_expired_ids_path(), + SizedQuery::new(inner_query, Some(1), None), + ); + + let (expired_index_elements, _) = self + .grove + .query_raw( + &expired_index_query, + QueryResultType::QueryKeyElementPairResultType, + transaction, + ) + .unwrap()?; + + if expired_index_elements.len() > 0 { + let expired_index_element_pair = expired_index_elements.into_iter().next().unwrap(); + + if let QueryResultElement::KeyElementPairResultItem((key, Element::Item(bytes, _))) = + expired_index_element_pair + { + let index = u64::from_be_bytes(bytes.try_into().map_err(|_| { + Error::Drive(DriveError::CorruptedCodeExecution( + "Transaction index has wrong length", + )) + })?); + + let path: [&[u8]; 2] = get_withdrawal_transactions_expired_ids_path_as_u8(); + + self.grove.delete(path, &key, None, transaction).unwrap()?; + + return Ok(index); + } + } + let result = self .grove .get( From a97bbef2bc0d248c4e6dcbaec776de591c8b581a Mon Sep 17 00:00:00 2001 From: Djavid Gabibyan Date: Mon, 19 Dec 2022 11:11:27 +0500 Subject: [PATCH 010/170] chore: initial testing setup --- packages/rs-dpp/Cargo.toml | 5 +- .../withdrawals-contract-documents.json | 12 +++ packages/rs-dpp/src/lib.rs | 4 +- packages/rs-dpp/src/state_repository.rs | 4 +- .../fixtures/public_keys_validator_mock.rs | 2 +- packages/rs-dpp/src/tests/mod.rs | 6 ++ packages/rs-drive/Cargo.toml | 2 +- packages/rs-drive/src/common/helpers/setup.rs | 55 ++++++++++++ .../identity/withdrawals/withdrawal_status.rs | 83 +++++++++++++++++++ .../schema/withdrawals-documents.json | 12 +++ 10 files changed, 178 insertions(+), 7 deletions(-) diff --git a/packages/rs-dpp/Cargo.toml b/packages/rs-dpp/Cargo.toml index 7bfd08a2162..309324965fe 100644 --- a/packages/rs-dpp/Cargo.toml +++ b/packages/rs-dpp/Cargo.toml @@ -35,8 +35,11 @@ serde_json = { version="1.0", features=["preserve_order"]} serde_repr = { version = "0.1.7" } sha2 = { version="0.10"} thiserror = { version = "1.0"} +mockall= { version ="0.11", optional = true } [dev-dependencies] -mockall= { version ="0.11"} test-case = { version ="2.0"} tokio = { version ="1.17", features=["full"]} + +[features] +fixtures-and-mocks = ["mockall"] \ No newline at end of file diff --git a/packages/rs-dpp/contracts/withdrawals/withdrawals-contract-documents.json b/packages/rs-dpp/contracts/withdrawals/withdrawals-contract-documents.json index 4a4f27dc40d..003929aacf9 100644 --- a/packages/rs-dpp/contracts/withdrawals/withdrawals-contract-documents.json +++ b/packages/rs-dpp/contracts/withdrawals/withdrawals-contract-documents.json @@ -41,6 +41,18 @@ } ], "unique": false + }, + { + "name": "status", + "properties": [ + { + "status": "asc" + }, + { + "$createdAt": "asc" + } + ], + "unique": false } ], "properties": { diff --git a/packages/rs-dpp/src/lib.rs b/packages/rs-dpp/src/lib.rs index 7524290ae79..2c2e9ed862a 100644 --- a/packages/rs-dpp/src/lib.rs +++ b/packages/rs-dpp/src/lib.rs @@ -38,8 +38,8 @@ pub mod block_time_window; pub mod mocks; mod bls; -#[cfg(test)] -mod tests; +#[cfg(feature = "fixtures-and-mocks")] +pub mod tests; pub use bls::*; pub mod prelude { diff --git a/packages/rs-dpp/src/state_repository.rs b/packages/rs-dpp/src/state_repository.rs index 407203b44c3..c87d16b978e 100644 --- a/packages/rs-dpp/src/state_repository.rs +++ b/packages/rs-dpp/src/state_repository.rs @@ -1,7 +1,7 @@ use anyhow::Result as AnyResult; use async_trait::async_trait; use dashcore::InstantLock; -#[cfg(test)] +#[cfg(feature = "fixtures-and-mocks")] use mockall::{automock, predicate::*}; use serde_json::Value as JsonValue; @@ -10,7 +10,7 @@ use crate::{ state_transition::state_transition_execution_context::StateTransitionExecutionContext, }; -#[cfg_attr(test, automock)] +#[cfg_attr(feature = "fixtures-and-mocks", automock)] #[async_trait] pub trait StateRepositoryLike: Send + Sync { /// Fetch the Data Contract by ID diff --git a/packages/rs-dpp/src/tests/fixtures/public_keys_validator_mock.rs b/packages/rs-dpp/src/tests/fixtures/public_keys_validator_mock.rs index 4b0c0bc6d51..b45e8e88a93 100644 --- a/packages/rs-dpp/src/tests/fixtures/public_keys_validator_mock.rs +++ b/packages/rs-dpp/src/tests/fixtures/public_keys_validator_mock.rs @@ -6,7 +6,7 @@ use crate::identity::validation::TPublicKeysValidator; use crate::validation::ValidationResult; use crate::NonConsensusError; -#[cfg(test)] +#[cfg(feature = "fixtures-and-mocks")] pub struct PublicKeysValidatorMock { returns: Mutex, NonConsensusError>>, returns_fn: diff --git a/packages/rs-dpp/src/tests/mod.rs b/packages/rs-dpp/src/tests/mod.rs index 9811d845083..1089b693b75 100644 --- a/packages/rs-dpp/src/tests/mod.rs +++ b/packages/rs-dpp/src/tests/mod.rs @@ -1,9 +1,15 @@ pub mod fixtures; + +#[cfg(test)] mod identifier_spec; pub mod utils; +#[cfg(test)] mod data_contract; +#[cfg(test)] mod document; +#[cfg(test)] mod identity; +#[cfg(test)] mod version; diff --git a/packages/rs-drive/Cargo.toml b/packages/rs-drive/Cargo.toml index ec2ba039c29..038544a35af 100644 --- a/packages/rs-drive/Cargo.toml +++ b/packages/rs-drive/Cargo.toml @@ -27,7 +27,7 @@ moka = "0.8.1" intmap = { version="2.0.0", features=["serde"] } chrono = "0.4.20" bincode = "1.3.3" -dpp = { path = "../rs-dpp" } +dpp = { path = "../rs-dpp", features = ["fixtures-and-mocks"]} itertools = { version = "0.10.5" } dashcore = { git="https://github.com/dashevo/rust-dashcore", features=["std", "secp-recovery", "rand", "signer"], default-features = false, rev = "6092d584487918c5330fec93152e4df06a714067" } dashcore-rpc = { git="https://github.com/jawid-h/rust-dashcore-rpc", branch="fix/attempt-to-fix" } diff --git a/packages/rs-drive/src/common/helpers/setup.rs b/packages/rs-drive/src/common/helpers/setup.rs index a1cb48e2e9f..64d3efb235c 100644 --- a/packages/rs-drive/src/common/helpers/setup.rs +++ b/packages/rs-drive/src/common/helpers/setup.rs @@ -32,8 +32,15 @@ //! Defines helper functions pertinent to setting up Drive. //! +use crate::drive::block_info::BlockInfo; use crate::drive::config::DriveConfig; use crate::drive::Drive; +use crate::fee_pools::epochs::Epoch; +use dpp::{ + contracts::withdrawals_contract, + prelude::{DataContract, Document}, +}; +use grovedb::TransactionArg; use tempfile::TempDir; /// Struct with options regarding setting up fee pools. @@ -68,3 +75,51 @@ pub fn setup_drive_with_initial_state_structure() -> Drive { drive } + +/// A function to setup system data contract +pub fn setup_system_data_contract( + drive: &Drive, + data_contract: &DataContract, + transaction: TransactionArg, +) { + drive + .apply_contract_cbor( + data_contract.to_cbor().unwrap(), + Some(data_contract.id.to_buffer()), + BlockInfo { + time_ms: 1, + height: 1, + epoch: Epoch::new(1), + }, + true, + None, + transaction, + ) + .unwrap(); +} + +/// Setup document for a contract +pub fn setup_document( + drive: &Drive, + document: &Document, + data_contract: &DataContract, + transaction: TransactionArg, +) { + drive + .add_serialized_document_for_serialized_contract( + &document.to_cbor().unwrap(), + &data_contract.to_cbor().unwrap(), + withdrawals_contract::types::WITHDRAWAL, + Some(data_contract.owner_id.to_buffer()), + false, + BlockInfo { + time_ms: 1, + height: 1, + epoch: Epoch::new(1), + }, + true, + None, + transaction, + ) + .unwrap(); +} diff --git a/packages/rs-drive/src/drive/identity/withdrawals/withdrawal_status.rs b/packages/rs-drive/src/drive/identity/withdrawals/withdrawal_status.rs index 6a271b4032a..1b9d1771524 100644 --- a/packages/rs-drive/src/drive/identity/withdrawals/withdrawal_status.rs +++ b/packages/rs-drive/src/drive/identity/withdrawals/withdrawal_status.rs @@ -268,3 +268,86 @@ impl Drive { Ok(()) } } + +#[cfg(test)] +mod tests { + use crate::drive::identity::withdrawals::withdrawal_status::fetch_withdrawal_documents_by_status; + use dpp::contracts::withdrawals_contract; + use dpp::tests::fixtures::get_withdrawal_document_fixture; + use dpp::tests::fixtures::get_withdrawals_data_contract_fixture; + use serde_json::json; + + use crate::common::helpers::setup::setup_drive_with_initial_state_structure; + use crate::common::helpers::setup::{setup_document, setup_system_data_contract}; + + mod fetch_withdrawal_documents_by_status { + + use super::*; + + #[test] + fn test_return_list_of_documents() { + let drive = setup_drive_with_initial_state_structure(); + + let transaction = drive.grove.start_transaction(); + + let data_contract = get_withdrawals_data_contract_fixture(None); + + setup_system_data_contract(&drive, &data_contract, Some(&transaction)); + + let documents = fetch_withdrawal_documents_by_status( + &drive, + withdrawals_contract::statuses::QUEUED, + Some(&transaction), + ) + .expect("to fetch documents by status"); + + assert_eq!(documents.len(), 0); + + let document = get_withdrawal_document_fixture( + &data_contract, + json!({ + "amount": 1000, + "coreFeePerByte": 1, + "pooling": 0, + "outputScript": (0..23).collect::>(), + "status": withdrawals_contract::statuses::QUEUED, + "transactionIndex": 1, + }), + ); + + setup_document(&drive, &document, &data_contract, Some(&transaction)); + + let document = get_withdrawal_document_fixture( + &data_contract, + json!({ + "amount": 1000, + "coreFeePerByte": 1, + "pooling": 0, + "outputScript": (0..23).collect::>(), + "status": withdrawals_contract::statuses::POOLED, + "transactionIndex": 2, + }), + ); + + setup_document(&drive, &document, &data_contract, Some(&transaction)); + + let documents = fetch_withdrawal_documents_by_status( + &drive, + withdrawals_contract::statuses::QUEUED, + Some(&transaction), + ) + .expect("to fetch documents by status"); + + assert_eq!(documents.len(), 1); + + let documents = fetch_withdrawal_documents_by_status( + &drive, + withdrawals_contract::statuses::POOLED, + Some(&transaction), + ) + .expect("to fetch documents by status"); + + assert_eq!(documents.len(), 1); + } + } +} diff --git a/packages/withdrawals-contract/schema/withdrawals-documents.json b/packages/withdrawals-contract/schema/withdrawals-documents.json index 4a4f27dc40d..003929aacf9 100644 --- a/packages/withdrawals-contract/schema/withdrawals-documents.json +++ b/packages/withdrawals-contract/schema/withdrawals-documents.json @@ -41,6 +41,18 @@ } ], "unique": false + }, + { + "name": "status", + "properties": [ + { + "status": "asc" + }, + { + "$createdAt": "asc" + } + ], + "unique": false } ], "properties": { From 4cb8d3c4efffcc581c39b84ed15c86f472000e5c Mon Sep 17 00:00:00 2001 From: Djavid Gabibyan Date: Mon, 19 Dec 2022 19:23:25 +0500 Subject: [PATCH 011/170] chore: more tests --- packages/rs-drive-abci/Cargo.toml | 4 +- packages/rs-drive/Cargo.toml | 2 +- packages/rs-drive/src/common/helpers/setup.rs | 5 +- packages/rs-drive/src/drive/identity/mod.rs | 1 - .../src/drive/identity/withdrawal_queue.rs | 144 ------------- .../src/drive/identity/withdrawals/queue.rs | 181 +++++++++++++++- .../withdrawals/transaction_index_counter.rs | 81 +++++++ .../identity/withdrawals/withdrawal_status.rs | 197 +++++++++++++++++- .../withdrawals/withdrawal_transactions.rs | 45 ++++ packages/rs-drive/src/lib.rs | 5 +- 10 files changed, 508 insertions(+), 157 deletions(-) delete mode 100644 packages/rs-drive/src/drive/identity/withdrawal_queue.rs diff --git a/packages/rs-drive-abci/Cargo.toml b/packages/rs-drive-abci/Cargo.toml index 91d0b202c2b..c5fe4f44448 100644 --- a/packages/rs-drive-abci/Cargo.toml +++ b/packages/rs-drive-abci/Cargo.toml @@ -13,7 +13,7 @@ rust_decimal_macros = "1.25.0" chrono = "0.4.20" serde = { version = "1.0.132", features = ["derive"] } serde_json = { version="1.0", features=["preserve_order"] } -drive = { path = "../rs-drive" } +drive = { path = "../rs-drive", features = ["core-rpc-mock"]} thiserror = "1.0.30" rand = "0.8.4" tempfile = "3" @@ -23,4 +23,4 @@ hex = "0.4.3" dashcore = { git="https://github.com/dashevo/rust-dashcore", features=["std", "secp-recovery", "rand", "signer"], default-features = false, rev = "6092d584487918c5330fec93152e4df06a714067" } [dev-dependencies] -dpp = { path = "../rs-dpp"} +dpp = { path = "../rs-dpp", features = ["fixtures-and-mocks"]} diff --git a/packages/rs-drive/Cargo.toml b/packages/rs-drive/Cargo.toml index 038544a35af..22927708201 100644 --- a/packages/rs-drive/Cargo.toml +++ b/packages/rs-drive/Cargo.toml @@ -31,7 +31,7 @@ dpp = { path = "../rs-dpp", features = ["fixtures-and-mocks"]} itertools = { version = "0.10.5" } dashcore = { git="https://github.com/dashevo/rust-dashcore", features=["std", "secp-recovery", "rand", "signer"], default-features = false, rev = "6092d584487918c5330fec93152e4df06a714067" } dashcore-rpc = { git="https://github.com/jawid-h/rust-dashcore-rpc", branch="fix/attempt-to-fix" } -mockall= { version ="0.11", optional = true} +mockall= { version ="0.11", optional = true } [dependencies.grovedb] git = "https://github.com/dashpay/grovedb" diff --git a/packages/rs-drive/src/common/helpers/setup.rs b/packages/rs-drive/src/common/helpers/setup.rs index 64d3efb235c..807b0307389 100644 --- a/packages/rs-drive/src/common/helpers/setup.rs +++ b/packages/rs-drive/src/common/helpers/setup.rs @@ -32,10 +32,13 @@ //! Defines helper functions pertinent to setting up Drive. //! -use crate::drive::block_info::BlockInfo; +use std::sync::Arc; + use crate::drive::config::DriveConfig; use crate::drive::Drive; +use crate::drive::{block_info::BlockInfo, contract::ContractFetchInfo}; use crate::fee_pools::epochs::Epoch; +use costs::OperationCost; use dpp::{ contracts::withdrawals_contract, prelude::{DataContract, Document}, diff --git a/packages/rs-drive/src/drive/identity/mod.rs b/packages/rs-drive/src/drive/identity/mod.rs index 28028b304cc..4f32418c1bf 100644 --- a/packages/rs-drive/src/drive/identity/mod.rs +++ b/packages/rs-drive/src/drive/identity/mod.rs @@ -50,7 +50,6 @@ use crate::error::Error; use crate::fee::op::DriveOperation; use crate::fee::{calculate_fee, FeeResult}; -pub mod withdrawal_queue; /// Everything related to withdrawals pub mod withdrawals; diff --git a/packages/rs-drive/src/drive/identity/withdrawal_queue.rs b/packages/rs-drive/src/drive/identity/withdrawal_queue.rs deleted file mode 100644 index e756aa11e3f..00000000000 --- a/packages/rs-drive/src/drive/identity/withdrawal_queue.rs +++ /dev/null @@ -1,144 +0,0 @@ -// MIT LICENSE -// -// Copyright (c) 2021 Dash Core Group -// -// Permission is hereby granted, free of charge, to any -// person obtaining a copy of this software and associated -// documentation files (the "Software"), to deal in the -// Software without restriction, including without -// limitation the rights to use, copy, modify, merge, -// publish, distribute, sublicense, and/or sell copies of -// the Software, and to permit persons to whom the Software -// is furnished to do so, subject to the following -// conditions: -// -// The above copyright notice and this permission notice -// shall be included in all copies or substantial portions -// of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF -// ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED -// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A -// PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -// SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY -// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR -// IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -// DEALINGS IN THE SOFTWARE. -// - -//! This module defines functions within the Drive struct related to withdrawal transaction (AssetUnlock) -//! - -use std::ops::RangeFull; - -use grovedb::query_result_type::QueryResultType::QueryKeyElementPairResultType; -use grovedb::{Element, PathQuery, Query, QueryItem, SizedQuery, TransactionArg}; - -use crate::drive::batch::GroveDbOpBatch; -use crate::drive::grove_operations::BatchDeleteApplyType; -use crate::drive::{Drive, RootTree}; -use crate::error::drive::DriveError; -use crate::error::Error; -use crate::fee::op::DriveOperation; - -/// constant id for transaction counter -// pub const WITHDRAWAL_TRANSACTIONS_COUNTER_ID: [u8; 1] = [0]; -// /// constant id for subtree containing transactions queue -// pub const WITHDRAWAL_TRANSACTIONS_QUEUE_ID: [u8; 1] = [1]; -// /// constant id for subtree containing expired transaction ids -// pub const WITHDRAWAL_TRANSACTIONS_EXPIRED_IDS: [u8; 1] = [2]; - -// type WithdrawalTransaction = (Vec, Vec); - -impl Drive {} - -#[cfg(test)] -mod tests { - use crate::common::helpers::setup::setup_drive_with_initial_state_structure; - use crate::drive::batch::GroveDbOpBatch; - - mod queue { - use super::*; - - #[test] - fn test_enqueue_and_dequeue() { - let drive = setup_drive_with_initial_state_structure(); - - let transaction = drive.grove.start_transaction(); - - let withdrawals: Vec<(Vec, Vec)> = (0..17) - .map(|i: u8| (i.to_be_bytes().to_vec(), vec![i; 32])) - .collect(); - - let mut batch = GroveDbOpBatch::new(); - - drive.add_enqueue_withdrawal_transaction_operations(&mut batch, withdrawals); - - drive - .grove_apply_batch(batch, true, Some(&transaction)) - .expect("to apply ops"); - - let withdrawals = drive - .dequeue_withdrawal_transactions(16, Some(&transaction)) - .expect("to dequeue withdrawals"); - - assert_eq!(withdrawals.len(), 16); - - let withdrawals = drive - .dequeue_withdrawal_transactions(16, Some(&transaction)) - .expect("to dequeue withdrawals"); - - assert_eq!(withdrawals.len(), 1); - - let withdrawals = drive - .dequeue_withdrawal_transactions(16, Some(&transaction)) - .expect("to dequeue withdrawals"); - - assert_eq!(withdrawals.len(), 0); - } - } - - mod index { - use super::*; - - #[test] - fn test_withdrawal_transaction_counter() { - let drive = setup_drive_with_initial_state_structure(); - - let transaction = drive.grove.start_transaction(); - - let mut batch = GroveDbOpBatch::new(); - - let counter: u64 = 42; - - drive.add_update_withdrawal_index_counter_operation( - &mut batch, - counter.to_be_bytes().to_vec(), - ); - - drive - .grove_apply_batch(batch, false, Some(&transaction)) - .expect("to apply ops"); - - let stored_counter = drive - .fetch_latest_withdrawal_transaction_index(Some(&transaction)) - .expect("to withdraw counter"); - - assert_eq!(stored_counter, counter); - } - - #[test] - fn test_returns_0_if_empty() { - let drive = setup_drive_with_initial_state_structure(); - - let transaction = drive.grove.start_transaction(); - - let stored_counter = drive - .fetch_latest_withdrawal_transaction_index(Some(&transaction)) - .expect("to withdraw counter"); - - assert_eq!(stored_counter, 0); - } - } -} diff --git a/packages/rs-drive/src/drive/identity/withdrawals/queue.rs b/packages/rs-drive/src/drive/identity/withdrawals/queue.rs index d170a7b6ac9..e3cf6aa5ce6 100644 --- a/packages/rs-drive/src/drive/identity/withdrawals/queue.rs +++ b/packages/rs-drive/src/drive/identity/withdrawals/queue.rs @@ -19,6 +19,7 @@ use serde_json::{Number, Value as JsonValue}; use crate::{ drive::{batch::GroveDbOpBatch, Drive}, error::{drive::DriveError, Error}, + fee_pools::epochs::Epoch, }; use super::{ @@ -107,7 +108,7 @@ impl Drive { current_epoch_index: u16, transaction: TransactionArg, ) -> Result<(), Error> { - let maybe_data_contract = self.get_cached_contract_with_fetch_info( + let (_, maybe_data_contract) = self.get_contract_with_fetch_info( Identifier::from_string( &withdrawals_contract::system_ids().contract_id, Encoding::Base58, @@ -118,8 +119,9 @@ impl Drive { )) })? .to_buffer(), + Some(&Epoch::new(current_epoch_index)), transaction, - ); + )?; let contract_fetch_info = maybe_data_contract.ok_or(Error::Drive( DriveError::CorruptedCodeExecution("Can't fetch withdrawal data contract"), @@ -201,3 +203,178 @@ impl Drive { Ok(()) } } + +#[cfg(test)] +mod tests { + use dpp::{ + contracts::withdrawals_contract, + tests::fixtures::{get_withdrawal_document_fixture, get_withdrawals_data_contract_fixture}, + }; + use serde_json::json; + + use crate::common::helpers::setup::{ + setup_document, setup_drive_with_initial_state_structure, setup_system_data_contract, + }; + + use crate::drive::identity::withdrawals::withdrawal_status::fetch_withdrawal_documents_by_status; + + mod build_withdrawal_transactions_from_documents { + + use crate::drive::identity::withdrawals::{ + paths::WithdrawalTransaction, queue::build_withdrawal_transactions_from_documents, + }; + + use super::*; + + #[test] + fn test_build() { + let drive = setup_drive_with_initial_state_structure(); + + let transaction = drive.grove.start_transaction(); + + let data_contract = get_withdrawals_data_contract_fixture(None); + + setup_system_data_contract(&drive, &data_contract, Some(&transaction)); + + let document_1 = get_withdrawal_document_fixture( + &data_contract, + json!({ + "amount": 1000, + "coreFeePerByte": 1, + "pooling": 0, + "outputScript": (0..23).collect::>(), + "status": withdrawals_contract::statuses::POOLED, + "transactionIndex": 1, + }), + ); + + setup_document(&drive, &document_1, &data_contract, Some(&transaction)); + + let document_2 = get_withdrawal_document_fixture( + &data_contract, + json!({ + "amount": 1000, + "coreFeePerByte": 1, + "pooling": 0, + "outputScript": (0..23).collect::>(), + "status": withdrawals_contract::statuses::POOLED, + "transactionIndex": 2, + }), + ); + + setup_document(&drive, &document_2, &data_contract, Some(&transaction)); + + let documents = vec![document_1, document_2]; + + let transactions = build_withdrawal_transactions_from_documents( + &drive, + &documents, + Some(&transaction), + ) + .expect("to build transactions from documents"); + + assert_eq!( + transactions + .values() + .cloned() + .collect::>(), + vec![ + ( + vec![0, 0, 0, 0, 0, 0, 0, 0], + vec![ + 1, 0, 9, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 23, 0, 1, 2, 3, 4, 5, 6, 7, + 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, 0, 0, 0, 192, 206, 2, 0, + ], + ), + ( + vec![0, 0, 0, 0, 0, 0, 0, 1], + vec![ + 1, 0, 9, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 23, 0, 1, 2, 3, 4, 5, 6, 7, + 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, 192, 206, 2, 0, + ], + ), + ], + ); + } + } + + mod pool_withdrawals_into_transactions { + + use super::*; + + #[test] + fn test_pooling() { + let drive = setup_drive_with_initial_state_structure(); + + let transaction = drive.grove.start_transaction(); + + let data_contract = get_withdrawals_data_contract_fixture(None); + + setup_system_data_contract(&drive, &data_contract, Some(&transaction)); + + let document_1 = get_withdrawal_document_fixture( + &data_contract, + json!({ + "amount": 1000, + "coreFeePerByte": 1, + "pooling": 0, + "outputScript": (0..23).collect::>(), + "status": withdrawals_contract::statuses::QUEUED, + "transactionIndex": 1, + }), + ); + + setup_document(&drive, &document_1, &data_contract, Some(&transaction)); + + let document_2 = get_withdrawal_document_fixture( + &data_contract, + json!({ + "amount": 1000, + "coreFeePerByte": 1, + "pooling": 0, + "outputScript": (0..23).collect::>(), + "status": withdrawals_contract::statuses::QUEUED, + "transactionIndex": 2, + }), + ); + + setup_document(&drive, &document_2, &data_contract, Some(&transaction)); + + drive + .pool_withdrawals_into_transactions(1, 1, 1, Some(&transaction)) + .expect("to pool withdrawal documents into transactions"); + + let updated_documents = fetch_withdrawal_documents_by_status( + &drive, + withdrawals_contract::statuses::POOLED, + Some(&transaction), + ) + .expect("to fetch withdrawal documents"); + + let tx_ids = [ + "73050b2f1cdc267ecd9ccd10038e4c957fc108a404704e83077a593787b5f122", + "de7889314e9dcfc6f7b142c18acc3bd1ccbee5f37d525651cdb3d5ce7fe66700", + ]; + + for document in updated_documents { + assert_eq!(document.revision, 2); + + let tx_id: Vec = document + .data + .get("transactionId") + .unwrap() + .as_array() + .unwrap() + .iter() + .map(|byte| byte.as_u64().unwrap() as u8) + .collect(); + + let tx_id_hex = hex::encode(tx_id); + + assert!(tx_ids.contains(&tx_id_hex.as_str())); + } + } + } +} diff --git a/packages/rs-drive/src/drive/identity/withdrawals/transaction_index_counter.rs b/packages/rs-drive/src/drive/identity/withdrawals/transaction_index_counter.rs index 4bf05459ee1..0dbc6b83be7 100644 --- a/packages/rs-drive/src/drive/identity/withdrawals/transaction_index_counter.rs +++ b/packages/rs-drive/src/drive/identity/withdrawals/transaction_index_counter.rs @@ -103,3 +103,84 @@ impl Drive { ); } } + +#[cfg(test)] +mod tests { + use grovedb::Element; + + use crate::{ + common::helpers::setup::setup_drive_with_initial_state_structure, + drive::{ + batch::GroveDbOpBatch, + identity::withdrawals::paths::get_withdrawal_transactions_expired_ids_path_as_u8, + }, + }; + + #[test] + fn test_withdrawal_transaction_counter() { + let drive = setup_drive_with_initial_state_structure(); + + let transaction = drive.grove.start_transaction(); + + let mut batch = GroveDbOpBatch::new(); + + let counter: u64 = 42; + + drive.add_update_withdrawal_index_counter_operation( + &mut batch, + counter.to_be_bytes().to_vec(), + ); + + drive + .grove_apply_batch(batch, false, Some(&transaction)) + .expect("to apply ops"); + + let stored_counter = drive + .fetch_latest_withdrawal_transaction_index(Some(&transaction)) + .expect("to withdraw counter"); + + assert_eq!(stored_counter, counter); + } + + #[test] + fn test_returns_0_if_empty() { + let drive = setup_drive_with_initial_state_structure(); + + let transaction = drive.grove.start_transaction(); + + let stored_counter = drive + .fetch_latest_withdrawal_transaction_index(Some(&transaction)) + .expect("to withdraw counter"); + + assert_eq!(stored_counter, 0); + } + + #[test] + fn test_should_return_expired_index_if_any() { + let drive = setup_drive_with_initial_state_structure(); + + let transaction = drive.grove.start_transaction(); + + let bytes = 42u64.to_be_bytes(); + + let path = get_withdrawal_transactions_expired_ids_path_as_u8(); + + drive + .grove + .insert( + path, + &bytes, + Element::Item(bytes.to_vec(), None), + None, + Some(&transaction), + ) + .unwrap() + .expect("to update index counter"); + + let stored_counter = drive + .fetch_latest_withdrawal_transaction_index(Some(&transaction)) + .expect("to withdraw counter"); + + assert_eq!(stored_counter, 42); + } +} diff --git a/packages/rs-drive/src/drive/identity/withdrawals/withdrawal_status.rs b/packages/rs-drive/src/drive/identity/withdrawals/withdrawal_status.rs index 1b9d1771524..fbe165c1c4e 100644 --- a/packages/rs-drive/src/drive/identity/withdrawals/withdrawal_status.rs +++ b/packages/rs-drive/src/drive/identity/withdrawals/withdrawal_status.rs @@ -161,7 +161,7 @@ impl Drive { current_epoch_index: u16, transaction: TransactionArg, ) -> Result<(), Error> { - let maybe_data_contract = self.get_cached_contract_with_fetch_info( + let (_, maybe_data_contract) = self.get_contract_with_fetch_info( Identifier::from_string( &withdrawals_contract::system_ids().contract_id, Encoding::Base58, @@ -172,8 +172,9 @@ impl Drive { )) })? .to_buffer(), + Some(&Epoch::new(current_epoch_index)), transaction, - ); + )?; let contract_fetch_info = maybe_data_contract.ok_or(Error::Drive( DriveError::CorruptedCodeExecution("Can't fetch withdrawal data contract"), @@ -207,7 +208,7 @@ impl Drive { let transaction_id = hex::encode(transaction_id_bytes); - let transaction_index = document.data.get_u64("transactionIdex").map_err(|_| { + let transaction_index = document.data.get_u64("transactionIndex").map_err(|_| { Error::Drive(DriveError::CorruptedCodeExecution( "Can't get transactionIdex from withdrawal document", )) @@ -280,6 +281,12 @@ mod tests { use crate::common::helpers::setup::setup_drive_with_initial_state_structure; use crate::common::helpers::setup::{setup_document, setup_system_data_contract}; + use dashcore::hashes::hex::ToHex; + + use crate::rpc::core::MockCoreRPCLike; + + use dashcore::{hashes::hex::FromHex, BlockHash}; + mod fetch_withdrawal_documents_by_status { use super::*; @@ -350,4 +357,188 @@ mod tests { assert_eq!(documents.len(), 1); } } + + mod fetch_core_block_transactions { + use crate::drive::identity::withdrawals::withdrawal_status::fetch_core_block_transactions; + + use super::*; + + #[test] + fn test_fetches_core_transactions() { + let mut drive = setup_drive_with_initial_state_structure(); + + let mut mock_rpc_client = MockCoreRPCLike::new(); + + mock_rpc_client + .expect_get_block_hash() + .withf(|height| *height == 1) + .returning(|_| { + Ok(BlockHash::from_hex( + "0000000000000000000000000000000000000000000000000000000000000000", + ) + .unwrap()) + }); + + mock_rpc_client + .expect_get_block_hash() + .withf(|height| *height == 2) + .returning(|_| { + Ok(BlockHash::from_hex( + "1111111111111111111111111111111111111111111111111111111111111111", + ) + .unwrap()) + }); + + mock_rpc_client + .expect_get_block_json() + .withf(|bh| { + bh.to_hex() + == "0000000000000000000000000000000000000000000000000000000000000000" + }) + .returning(|_| { + Ok(json!({ + "tx": ["1"] + })) + }); + + mock_rpc_client + .expect_get_block_json() + .withf(|bh| { + bh.to_hex() + == "1111111111111111111111111111111111111111111111111111111111111111" + }) + .returning(|_| { + Ok(json!({ + "tx": ["2"] + })) + }); + + drive.core_rpc = Some(Box::new(mock_rpc_client)); + + let transactions = + fetch_core_block_transactions(&drive, 1, 2).expect("to fetch core transactions"); + + assert_eq!(transactions.len(), 2); + assert_eq!(transactions, ["1", "2"]); + } + } + + mod update_withdrawal_statuses { + use super::*; + + #[test] + fn test_statuses_are_updated() { + let mut drive = setup_drive_with_initial_state_structure(); + + let mut mock_rpc_client = MockCoreRPCLike::new(); + + mock_rpc_client + .expect_get_block_hash() + .withf(|height| *height == 95) + .returning(|_| { + Ok(BlockHash::from_hex( + "0000000000000000000000000000000000000000000000000000000000000000", + ) + .unwrap()) + }); + + mock_rpc_client + .expect_get_block_hash() + .withf(|height| *height == 96) + .returning(|_| { + Ok(BlockHash::from_hex( + "1111111111111111111111111111111111111111111111111111111111111111", + ) + .unwrap()) + }); + + mock_rpc_client + .expect_get_block_json() + .withf(|bh| { + bh.to_hex() + == "0000000000000000000000000000000000000000000000000000000000000000" + }) + .returning(|_| { + Ok(json!({ + "tx": ["0101010101010101010101010101010101010101010101010101010101010101"] + })) + }); + + mock_rpc_client + .expect_get_block_json() + .withf(|bh| { + bh.to_hex() + == "1111111111111111111111111111111111111111111111111111111111111111" + }) + .returning(|_| { + Ok(json!({ + "tx": ["0202020202020202020202020202020202020202020202020202020202020202"] + })) + }); + + drive.core_rpc = Some(Box::new(mock_rpc_client)); + + let transaction = drive.grove.start_transaction(); + + let data_contract = get_withdrawals_data_contract_fixture(None); + + setup_system_data_contract(&drive, &data_contract, Some(&transaction)); + + let document_1 = get_withdrawal_document_fixture( + &data_contract, + json!({ + "amount": 1000, + "coreFeePerByte": 1, + "pooling": 0, + "outputScript": (0..23).collect::>(), + "status": withdrawals_contract::statuses::BROADCASTED, + "transactionIndex": 1, + "transactionSignHeight": 93, + "transactionId": vec![1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], + }), + ); + + setup_document(&drive, &document_1, &data_contract, Some(&transaction)); + + let document_2 = get_withdrawal_document_fixture( + &data_contract, + json!({ + "amount": 1000, + "coreFeePerByte": 1, + "pooling": 0, + "outputScript": (0..23).collect::>(), + "status": withdrawals_contract::statuses::BROADCASTED, + "transactionIndex": 2, + "transactionSignHeight": 10, + "transactionId": vec![3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], + }), + ); + + setup_document(&drive, &document_2, &data_contract, Some(&transaction)); + + drive + .update_withdrawal_statuses(95, 96, 1, 1, 1, Some(&transaction)) + .expect("to update withdrawal statuses"); + + let documents = fetch_withdrawal_documents_by_status( + &drive, + withdrawals_contract::statuses::EXPIRED, + Some(&transaction), + ) + .expect("to fetch documents by status"); + + assert_eq!(documents.len(), 1); + assert_eq!(documents.get(0).unwrap().id, document_2.id); + + let documents = fetch_withdrawal_documents_by_status( + &drive, + withdrawals_contract::statuses::COMPLETE, + Some(&transaction), + ) + .expect("to fetch documents by status"); + + assert_eq!(documents.len(), 1); + assert_eq!(documents.get(0).unwrap().id, document_1.id); + } + } } diff --git a/packages/rs-drive/src/drive/identity/withdrawals/withdrawal_transactions.rs b/packages/rs-drive/src/drive/identity/withdrawals/withdrawal_transactions.rs index cbe173cf318..2847dc9bc24 100644 --- a/packages/rs-drive/src/drive/identity/withdrawals/withdrawal_transactions.rs +++ b/packages/rs-drive/src/drive/identity/withdrawals/withdrawal_transactions.rs @@ -103,3 +103,48 @@ impl Drive { Ok(withdrawals) } } + +#[cfg(test)] +mod tests { + use crate::{ + common::helpers::setup::setup_drive_with_initial_state_structure, + drive::batch::GroveDbOpBatch, + }; + + #[test] + fn test_enqueue_and_dequeue() { + let drive = setup_drive_with_initial_state_structure(); + + let transaction = drive.grove.start_transaction(); + + let withdrawals: Vec<(Vec, Vec)> = (0..17) + .map(|i: u8| (i.to_be_bytes().to_vec(), vec![i; 32])) + .collect(); + + let mut batch = GroveDbOpBatch::new(); + + drive.add_enqueue_withdrawal_transaction_operations(&mut batch, withdrawals); + + drive + .grove_apply_batch(batch, true, Some(&transaction)) + .expect("to apply ops"); + + let withdrawals = drive + .dequeue_withdrawal_transactions(16, Some(&transaction)) + .expect("to dequeue withdrawals"); + + assert_eq!(withdrawals.len(), 16); + + let withdrawals = drive + .dequeue_withdrawal_transactions(16, Some(&transaction)) + .expect("to dequeue withdrawals"); + + assert_eq!(withdrawals.len(), 1); + + let withdrawals = drive + .dequeue_withdrawal_transactions(16, Some(&transaction)) + .expect("to dequeue withdrawals"); + + assert_eq!(withdrawals.len(), 0); + } +} diff --git a/packages/rs-drive/src/lib.rs b/packages/rs-drive/src/lib.rs index 1e571c4a510..b09e4e44e65 100644 --- a/packages/rs-drive/src/lib.rs +++ b/packages/rs-drive/src/lib.rs @@ -23,11 +23,10 @@ pub mod fee; pub mod fee_pools; /// Query module pub mod query; +/// Everything related to RPC +pub mod rpc; /// DPP module pub use dpp; /// GroveDB module pub use grovedb; - -/// Everything related to RPC -pub mod rpc; From ee43234ea56ed6100e0fe013836fec0aecbb7a46 Mon Sep 17 00:00:00 2001 From: Djavid Gabibyan Date: Mon, 19 Dec 2022 19:34:14 +0500 Subject: [PATCH 012/170] chore: more testing --- packages/rs-drive-abci/src/abci/handlers.rs | 63 ++++++++++++++++++++- 1 file changed, 60 insertions(+), 3 deletions(-) diff --git a/packages/rs-drive-abci/src/abci/handlers.rs b/packages/rs-drive-abci/src/abci/handlers.rs index 015cd668912..a3e4d8e1e16 100644 --- a/packages/rs-drive-abci/src/abci/handlers.rs +++ b/packages/rs-drive-abci/src/abci/handlers.rs @@ -199,20 +199,28 @@ mod tests { use crate::abci::handlers::TenderdashAbci; use crate::common::helpers::fee_pools::create_test_masternode_share_identities_and_documents; use chrono::{Duration, Utc}; + use dashcore::hashes::hex::FromHex; + use dashcore::BlockHash; + use dpp::tests::fixtures::get_withdrawals_data_contract_fixture; use drive::common::helpers::identities::create_test_masternode_identities; use drive::drive::batch::GroveDbOpBatch; use drive::fee::FeeResult; + use drive::rpc::core::MockCoreRPCLike; use rust_decimal::prelude::ToPrimitive; + use serde_json::json; use std::ops::Div; use crate::abci::messages::{ AfterFinalizeBlockRequest, BlockBeginRequest, BlockEndRequest, InitChainRequest, }; - use crate::common::helpers::setup::setup_platform; + use crate::common::helpers::setup::{setup_platform, setup_system_data_contract}; #[test] fn test_abci_flow() { - let platform = setup_platform(); + let mut platform = setup_platform(); + + let mut core_rpc_mock = MockCoreRPCLike::new(); + let transaction = platform.drive.grove.start_transaction(); // init chain @@ -222,6 +230,12 @@ mod tests { .init_chain(init_chain_request, Some(&transaction)) .expect("should init chain"); + setup_system_data_contract( + &platform.drive, + get_withdrawals_data_contract_fixture(None), + Some(&transaction), + ); + // Init withdrawal requests let withdrawals = (0..16) .map(|index: u64| (index.to_be_bytes().to_vec(), vec![index as u8; 32])) @@ -273,6 +287,23 @@ mod tests { let mut previous_block_time_ms: Option = None; + core_rpc_mock + .expect_get_block_hash() + // .times(total_days) + .returning(|_| { + Ok(BlockHash::from_hex( + "0000000000000000000000000000000000000000000000000000000000000000", + ) + .unwrap()) + }); + + core_rpc_mock + .expect_get_block_json() + // .times(total_days) + .returning(|_| Ok(json!({}))); + + platform.drive.core_rpc = Some(Box::new(core_rpc_mock)); + // process blocks for day in 0..total_days { for block_num in 0..blocks_per_day { @@ -422,7 +453,27 @@ mod tests { fn test_chain_halt_for_36_days() { // TODO refactor to remove code duplication - let platform = setup_platform(); + let mut platform = setup_platform(); + + let mut core_rpc_mock = MockCoreRPCLike::new(); + + core_rpc_mock + .expect_get_block_hash() + // .times(1) // TODO: investigate why it always n + 1 + .returning(|_| { + Ok(BlockHash::from_hex( + "0000000000000000000000000000000000000000000000000000000000000000", + ) + .unwrap()) + }); + + core_rpc_mock + .expect_get_block_json() + // .times(1) // TODO: investigate why it always n + 1 + .returning(|_| Ok(json!({}))); + + platform.drive.core_rpc = Some(Box::new(core_rpc_mock)); + let transaction = platform.drive.grove.start_transaction(); // init chain @@ -432,6 +483,12 @@ mod tests { .init_chain(init_chain_request, Some(&transaction)) .expect("should init chain"); + setup_system_data_contract( + &platform.drive, + get_withdrawals_data_contract_fixture(None), + Some(&transaction), + ); + // setup the contract let contract = platform.create_mn_shares_contract(Some(&transaction)); From 41c5ddb6decfd50ce3ce73d6a3c25badfd3d54e8 Mon Sep 17 00:00:00 2001 From: Djavid Gabibiyan Date: Mon, 19 Dec 2022 22:12:25 +0500 Subject: [PATCH 013/170] chore: linter fixes --- .../abci/handlers/verifyVoteExtensionHandlerFactory.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/js-drive/lib/abci/handlers/verifyVoteExtensionHandlerFactory.js b/packages/js-drive/lib/abci/handlers/verifyVoteExtensionHandlerFactory.js index 7e8c3c3d907..315151c0426 100644 --- a/packages/js-drive/lib/abci/handlers/verifyVoteExtensionHandlerFactory.js +++ b/packages/js-drive/lib/abci/handlers/verifyVoteExtensionHandlerFactory.js @@ -47,8 +47,8 @@ function verifyVoteExtensionHandlerFactory(proposalBlockExecutionContext) { const allVoteExtensionsPresent = voteExtensionsToCheck.reduce((result, nextExtension) => { const searchedVoteExtension = (voteExtensions || []).find((voteExtension) => ( - voteExtension.type == nextExtension.type - && Buffer.compare(voteExtension.extension, nextExtension.extension) + voteExtension.type === nextExtension.type + && Buffer.compare(voteExtension.extension, nextExtension.extension) )); if (!searchedVoteExtension) { @@ -65,10 +65,10 @@ function verifyVoteExtensionHandlerFactory(proposalBlockExecutionContext) { }, `${nextExtension.type} vote extension ${extensionTruncatedString}... was not found in verify request`); } - return result && (searchedVoteExtension != undefined); + return result && (searchedVoteExtension !== undefined); }, true); - let status = allVoteExtensionsPresent ? verifyStatus.ACCEPT : verifyStatus.REJECT; + const status = allVoteExtensionsPresent ? verifyStatus.ACCEPT : verifyStatus.REJECT; return new ResponseVerifyVoteExtension({ status, From 11c9c1991ac955c31dfbfc8a609dcd1c38f901e4 Mon Sep 17 00:00:00 2001 From: Konstantin Shuplenkov Date: Tue, 20 Dec 2022 13:30:07 +0300 Subject: [PATCH 014/170] WIP --- .pnp.cjs | 2054 +++++++++++------ .pnp.loader.mjs | 1809 ++++++++++++++- .yarn/cache/fsevents-patch-2882183fbf-8.zip | Bin 0 -> 23675 bytes ...> resolve-patch-b984c6fd86-c79ecaea36.zip} | Bin ...ypescript-patch-7ad1c7f5d0-dc7141ab55.zip} | Bin yarn.lock | 6 +- 6 files changed, 3164 insertions(+), 705 deletions(-) create mode 100644 .yarn/cache/fsevents-patch-2882183fbf-8.zip rename .yarn/cache/{resolve-patch-bad885c6ea-c79ecaea36.zip => resolve-patch-b984c6fd86-c79ecaea36.zip} (100%) rename .yarn/cache/{typescript-patch-1236c99922-dc7141ab55.zip => typescript-patch-7ad1c7f5d0-dc7141ab55.zip} (100%) diff --git a/.pnp.cjs b/.pnp.cjs index b4e291c7a9c..62f3b1a2657 100755 --- a/.pnp.cjs +++ b/.pnp.cjs @@ -1,11 +1,6 @@ #!/usr/bin/env node /* eslint-disable */ - -try { - Object.freeze({}).detectStrictMode = true; -} catch (error) { - throw new Error(`The whole PnP file got strict-mode-ified, which is known to break (Emscripten libraries aren't strict mode). This usually happens when the file goes through Babel.`); -} +"use strict"; function $$SETUP_STATE(hydrateRuntimeState, basePath) { return hydrateRuntimeState(JSON.parse('{\ @@ -332,7 +327,7 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { ["@types/babel__core", null],\ ["debug", "virtual:c2bff3e67180802999655a22d390062982690e911b9d9225c258f3b25e7409f3867b2682c16232b77415f560a09d05a95042dc512a5b8c566c42bbbed88b0bbc#npm:4.3.4"],\ ["lodash.debounce", "npm:4.0.8"],\ - ["resolve", "patch:resolve@npm%3A1.22.0#~builtin::version=1.22.0&hash=07638b"],\ + ["resolve", "patch:resolve@npm%3A1.22.0#~builtin::version=1.22.0&hash=c3c19d"],\ ["semver", "npm:6.3.0"]\ ],\ "packagePeers": [\ @@ -3001,7 +2996,7 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { ["stream-http", "npm:3.2.0"],\ ["string_decoder", "npm:1.3.0"],\ ["ts-loader", "virtual:e2d057e7cc143d3cb9bec864f4a2d862441b5a09f81f8e6c46e7a098cbc89e4d07017cc6e2e2142d5704bb55da853cbec2d025ebc0b30e8696c31380c00f2c7d#npm:8.3.0"],\ - ["typescript", "patch:typescript@npm%3A3.9.10#~builtin::version=3.9.10&hash=f456af"],\ + ["typescript", "patch:typescript@npm%3A3.9.10#~builtin::version=3.9.10&hash=3bd3d3"],\ ["url", "npm:0.11.0"],\ ["util", "npm:0.12.4"],\ ["webpack", "virtual:e2d057e7cc143d3cb9bec864f4a2d862441b5a09f81f8e6c46e7a098cbc89e4d07017cc6e2e2142d5704bb55da853cbec2d025ebc0b30e8696c31380c00f2c7d#npm:5.64.1"],\ @@ -5667,7 +5662,7 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { ["@types/eslint", null],\ ["eslint", "npm:7.32.0"],\ ["eslint-visitor-keys", "npm:1.3.0"],\ - ["resolve", "patch:resolve@npm%3A1.22.0#~builtin::version=1.22.0&hash=07638b"]\ + ["resolve", "patch:resolve@npm%3A1.22.0#~builtin::version=1.22.0&hash=c3c19d"]\ ],\ "packagePeers": [\ "@types/eslint",\ @@ -6611,7 +6606,7 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { ["chokidar", "npm:3.5.3"],\ ["anymatch", "npm:3.1.2"],\ ["braces", "npm:3.0.2"],\ - ["fsevents", "patch:fsevents@npm%3A2.3.2#~builtin::version=2.3.2&hash=18f3a7"],\ + ["fsevents", "patch:fsevents@npm%3A2.3.2#~builtin::version=2.3.2&hash=df0bf1"],\ ["glob-parent", "npm:5.1.2"],\ ["is-binary-path", "npm:2.1.0"],\ ["is-glob", "npm:4.0.3"],\ @@ -7609,7 +7604,7 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { ["ts-mocha", "virtual:ad53cff31b1dbd4927a99e71702e3b8b10338636eaff010987c27c9ccea2d52af36900a9e36a4231cbb6e5464248ccc9c1da5d1d24d9b0f4f95660296b1060a6#npm:9.0.2"],\ ["ts-mock-imports", "virtual:ad53cff31b1dbd4927a99e71702e3b8b10338636eaff010987c27c9ccea2d52af36900a9e36a4231cbb6e5464248ccc9c1da5d1d24d9b0f4f95660296b1060a6#npm:1.3.8"],\ ["ts-node", "virtual:ad53cff31b1dbd4927a99e71702e3b8b10338636eaff010987c27c9ccea2d52af36900a9e36a4231cbb6e5464248ccc9c1da5d1d24d9b0f4f95660296b1060a6#npm:10.4.0"],\ - ["typescript", "patch:typescript@npm%3A3.9.10#~builtin::version=3.9.10&hash=f456af"],\ + ["typescript", "patch:typescript@npm%3A3.9.10#~builtin::version=3.9.10&hash=3bd3d3"],\ ["url", "npm:0.11.0"],\ ["util", "npm:0.12.4"],\ ["webpack", "virtual:ad53cff31b1dbd4927a99e71702e3b8b10338636eaff010987c27c9ccea2d52af36900a9e36a4231cbb6e5464248ccc9c1da5d1d24d9b0f4f95660296b1060a6#npm:5.64.1"],\ @@ -8734,7 +8729,7 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { "packageDependencies": [\ ["eslint-import-resolver-node", "npm:0.3.6"],\ ["debug", "virtual:d9426786c635bc4b52511d6cc4b56156f50d780a698c0e20fc6caf10d3be51cbf176e79cff882f4d42a23ff4d0f89fe94222849578214e7fbae0f2754c82af02#npm:3.2.7"],\ - ["resolve", "patch:resolve@npm%3A1.22.0#~builtin::version=1.22.0&hash=07638b"]\ + ["resolve", "patch:resolve@npm%3A1.22.0#~builtin::version=1.22.0&hash=c3c19d"]\ ],\ "linkType": "HARD"\ }]\ @@ -8803,7 +8798,7 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { ["is-glob", "npm:4.0.3"],\ ["minimatch", "npm:3.1.2"],\ ["object.values", "npm:1.1.5"],\ - ["resolve", "patch:resolve@npm%3A1.22.0#~builtin::version=1.22.0&hash=07638b"],\ + ["resolve", "patch:resolve@npm%3A1.22.0#~builtin::version=1.22.0&hash=c3c19d"],\ ["tsconfig-paths", "npm:3.12.0"]\ ],\ "packagePeers": [\ @@ -9570,10 +9565,10 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { }]\ ]],\ ["fsevents", [\ - ["patch:fsevents@npm%3A2.3.2#~builtin::version=2.3.2&hash=18f3a7", {\ - "packageLocation": "./.yarn/unplugged/fsevents-patch-3340e2eb10/node_modules/fsevents/",\ + ["patch:fsevents@npm%3A2.3.2#~builtin::version=2.3.2&hash=df0bf1", {\ + "packageLocation": "./.yarn/unplugged/fsevents-patch-2882183fbf/node_modules/fsevents/",\ "packageDependencies": [\ - ["fsevents", "patch:fsevents@npm%3A2.3.2#~builtin::version=2.3.2&hash=18f3a7"],\ + ["fsevents", "patch:fsevents@npm%3A2.3.2#~builtin::version=2.3.2&hash=df0bf1"],\ ["node-gyp", "npm:8.4.0"]\ ],\ "linkType": "HARD"\ @@ -13390,7 +13385,7 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { "packageDependencies": [\ ["normalize-package-data", "npm:2.5.0"],\ ["hosted-git-info", "npm:2.8.9"],\ - ["resolve", "patch:resolve@npm%3A1.22.0#~builtin::version=1.22.0&hash=07638b"],\ + ["resolve", "patch:resolve@npm%3A1.22.0#~builtin::version=1.22.0&hash=c3c19d"],\ ["semver", "npm:5.7.1"],\ ["validate-npm-package-license", "npm:3.0.4"]\ ],\ @@ -14945,7 +14940,7 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { "packageLocation": "./.yarn/cache/rechoir-npm-0.6.2-0df5f171ec-fe76bf9c21.zip/node_modules/rechoir/",\ "packageDependencies": [\ ["rechoir", "npm:0.6.2"],\ - ["resolve", "patch:resolve@npm%3A1.22.0#~builtin::version=1.22.0&hash=07638b"]\ + ["resolve", "patch:resolve@npm%3A1.22.0#~builtin::version=1.22.0&hash=c3c19d"]\ ],\ "linkType": "HARD"\ }],\ @@ -14953,7 +14948,7 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { "packageLocation": "./.yarn/cache/rechoir-npm-0.7.1-0c7e5c1201-2a04aab4e2.zip/node_modules/rechoir/",\ "packageDependencies": [\ ["rechoir", "npm:0.7.1"],\ - ["resolve", "patch:resolve@npm%3A1.22.0#~builtin::version=1.22.0&hash=07638b"]\ + ["resolve", "patch:resolve@npm%3A1.22.0#~builtin::version=1.22.0&hash=c3c19d"]\ ],\ "linkType": "HARD"\ }]\ @@ -15152,10 +15147,10 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { }]\ ]],\ ["resolve", [\ - ["patch:resolve@npm%3A1.22.0#~builtin::version=1.22.0&hash=07638b", {\ - "packageLocation": "./.yarn/cache/resolve-patch-bad885c6ea-c79ecaea36.zip/node_modules/resolve/",\ + ["patch:resolve@npm%3A1.22.0#~builtin::version=1.22.0&hash=c3c19d", {\ + "packageLocation": "./.yarn/cache/resolve-patch-b984c6fd86-c79ecaea36.zip/node_modules/resolve/",\ "packageDependencies": [\ - ["resolve", "patch:resolve@npm%3A1.22.0#~builtin::version=1.22.0&hash=07638b"],\ + ["resolve", "patch:resolve@npm%3A1.22.0#~builtin::version=1.22.0&hash=c3c19d"],\ ["is-core-module", "npm:2.8.1"],\ ["path-parse", "npm:1.0.7"],\ ["supports-preserve-symlinks-flag", "npm:1.0.0"]\ @@ -17017,7 +17012,7 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { ["loader-utils", "npm:2.0.2"],\ ["micromatch", "npm:4.0.4"],\ ["semver", "npm:7.3.7"],\ - ["typescript", "patch:typescript@npm%3A3.9.10#~builtin::version=3.9.10&hash=f456af"],\ + ["typescript", "patch:typescript@npm%3A3.9.10#~builtin::version=3.9.10&hash=3bd3d3"],\ ["webpack", "virtual:ad53cff31b1dbd4927a99e71702e3b8b10338636eaff010987c27c9ccea2d52af36900a9e36a4231cbb6e5464248ccc9c1da5d1d24d9b0f4f95660296b1060a6#npm:5.64.1"]\ ],\ "packagePeers": [\ @@ -17039,7 +17034,7 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { ["loader-utils", "npm:2.0.2"],\ ["micromatch", "npm:4.0.4"],\ ["semver", "npm:7.3.7"],\ - ["typescript", "patch:typescript@npm%3A3.9.10#~builtin::version=3.9.10&hash=f456af"],\ + ["typescript", "patch:typescript@npm%3A3.9.10#~builtin::version=3.9.10&hash=3bd3d3"],\ ["webpack", "virtual:e2d057e7cc143d3cb9bec864f4a2d862441b5a09f81f8e6c46e7a098cbc89e4d07017cc6e2e2142d5704bb55da853cbec2d025ebc0b30e8696c31380c00f2c7d#npm:5.64.1"]\ ],\ "packagePeers": [\ @@ -17090,7 +17085,7 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { ["@types/sinon", "npm:9.0.11"],\ ["@types/typescript", null],\ ["sinon", "npm:11.1.2"],\ - ["typescript", "patch:typescript@npm%3A3.9.10#~builtin::version=3.9.10&hash=f456af"]\ + ["typescript", "patch:typescript@npm%3A3.9.10#~builtin::version=3.9.10&hash=3bd3d3"]\ ],\ "packagePeers": [\ "@types/sinon",\ @@ -17120,7 +17115,7 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { ["minimist", "npm:1.2.6"],\ ["mkdirp", "npm:0.5.6"],\ ["source-map-support", "npm:0.5.21"],\ - ["typescript", "patch:typescript@npm%3A3.9.10#~builtin::version=3.9.10&hash=f456af"],\ + ["typescript", "patch:typescript@npm%3A3.9.10#~builtin::version=3.9.10&hash=3bd3d3"],\ ["yn", "npm:2.0.0"]\ ],\ "linkType": "HARD"\ @@ -17146,7 +17141,7 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { ["create-require", "npm:1.1.1"],\ ["diff", "npm:4.0.2"],\ ["make-error", "npm:1.3.6"],\ - ["typescript", "patch:typescript@npm%3A3.9.10#~builtin::version=3.9.10&hash=f456af"],\ + ["typescript", "patch:typescript@npm%3A3.9.10#~builtin::version=3.9.10&hash=3bd3d3"],\ ["yn", "npm:3.1.1"]\ ],\ "packagePeers": [\ @@ -17320,10 +17315,10 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { }]\ ]],\ ["typescript", [\ - ["patch:typescript@npm%3A3.9.10#~builtin::version=3.9.10&hash=f456af", {\ - "packageLocation": "./.yarn/cache/typescript-patch-1236c99922-dc7141ab55.zip/node_modules/typescript/",\ + ["patch:typescript@npm%3A3.9.10#~builtin::version=3.9.10&hash=3bd3d3", {\ + "packageLocation": "./.yarn/cache/typescript-patch-7ad1c7f5d0-dc7141ab55.zip/node_modules/typescript/",\ "packageDependencies": [\ - ["typescript", "patch:typescript@npm%3A3.9.10#~builtin::version=3.9.10&hash=f456af"]\ + ["typescript", "patch:typescript@npm%3A3.9.10#~builtin::version=3.9.10&hash=3bd3d3"]\ ],\ "linkType": "HARD"\ }]\ @@ -18896,6 +18891,7 @@ const StringDecoder = require('string_decoder'); const url = require('url'); const os = require('os'); const nodeUtils = require('util'); +const assert = require('assert'); const stream = require('stream'); const zlib = require('zlib'); const events = require('events'); @@ -18925,6 +18921,7 @@ const path__default = /*#__PURE__*/_interopDefaultLegacy(path); const require$$0__default = /*#__PURE__*/_interopDefaultLegacy(require$$0); const StringDecoder__default = /*#__PURE__*/_interopDefaultLegacy(StringDecoder); const nodeUtils__namespace = /*#__PURE__*/_interopNamespace(nodeUtils); +const assert__default = /*#__PURE__*/_interopDefaultLegacy(assert); const zlib__default = /*#__PURE__*/_interopDefaultLegacy(zlib); const S_IFMT = 61440; @@ -19116,15 +19113,10 @@ function areStatsEqual(a, b) { return true; } -var PathType; -(function(PathType2) { - PathType2[PathType2["File"] = 0] = "File"; - PathType2[PathType2["Portable"] = 1] = "Portable"; - PathType2[PathType2["Native"] = 2] = "Native"; -})(PathType || (PathType = {})); const PortablePath = { root: `/`, - dot: `.` + dot: `.`, + parent: `..` }; const Filename = { nodeModules: `node_modules`, @@ -19194,40 +19186,16 @@ function convertPath(targetPathUtils, sourcePath) { return targetPathUtils === npath ? fromPortablePath(sourcePath) : toPortablePath(sourcePath); } -var __defProp$5 = Object.defineProperty; -var __defProps$3 = Object.defineProperties; -var __getOwnPropDescs$3 = Object.getOwnPropertyDescriptors; -var __getOwnPropSymbols$6 = Object.getOwnPropertySymbols; -var __hasOwnProp$6 = Object.prototype.hasOwnProperty; -var __propIsEnum$6 = Object.prototype.propertyIsEnumerable; -var __defNormalProp$5 = (obj, key, value) => key in obj ? __defProp$5(obj, key, {enumerable: true, configurable: true, writable: true, value}) : obj[key] = value; -var __spreadValues$5 = (a, b) => { - for (var prop in b || (b = {})) - if (__hasOwnProp$6.call(b, prop)) - __defNormalProp$5(a, prop, b[prop]); - if (__getOwnPropSymbols$6) - for (var prop of __getOwnPropSymbols$6(b)) { - if (__propIsEnum$6.call(b, prop)) - __defNormalProp$5(a, prop, b[prop]); - } - return a; -}; -var __spreadProps$3 = (a, b) => __defProps$3(a, __getOwnPropDescs$3(b)); const defaultTime = new Date(SAFE_TIME * 1e3); -var LinkStrategy; -(function(LinkStrategy2) { - LinkStrategy2["Allow"] = `allow`; - LinkStrategy2["ReadOnly"] = `readOnly`; -})(LinkStrategy || (LinkStrategy = {})); async function copyPromise(destinationFs, destination, sourceFs, source, opts) { const normalizedDestination = destinationFs.pathUtils.normalize(destination); const normalizedSource = sourceFs.pathUtils.normalize(source); const prelayout = []; const postlayout = []; - const {atime, mtime} = opts.stableTime ? {atime: defaultTime, mtime: defaultTime} : await sourceFs.lstatPromise(normalizedSource); - await destinationFs.mkdirpPromise(destinationFs.pathUtils.dirname(destination), {utimes: [atime, mtime]}); + const { atime, mtime } = opts.stableTime ? { atime: defaultTime, mtime: defaultTime } : await sourceFs.lstatPromise(normalizedSource); + await destinationFs.mkdirpPromise(destinationFs.pathUtils.dirname(destination), { utimes: [atime, mtime] }); const updateTime = typeof destinationFs.lutimesPromise === `function` ? destinationFs.lutimesPromise.bind(destinationFs) : destinationFs.utimesPromise.bind(destinationFs); - await copyImpl(prelayout, postlayout, updateTime, destinationFs, normalizedDestination, sourceFs, normalizedSource, __spreadProps$3(__spreadValues$5({}, opts), {didParentExist: true})); + await copyImpl(prelayout, postlayout, updateTime, destinationFs, normalizedDestination, sourceFs, normalizedSource, { ...opts, didParentExist: true }); for (const operation of prelayout) await operation(); await Promise.all(postlayout.map((operation) => { @@ -19238,7 +19206,7 @@ async function copyImpl(prelayout, postlayout, updateTime, destinationFs, destin var _a, _b; const destinationStat = opts.didParentExist ? await maybeLStat(destinationFs, destination) : null; const sourceStat = await sourceFs.lstatPromise(source); - const {atime, mtime} = opts.stableTime ? {atime: defaultTime, mtime: defaultTime} : sourceStat; + const { atime, mtime } = opts.stableTime ? { atime: defaultTime, mtime: defaultTime } : sourceStat; let updated; switch (true) { case sourceStat.isDirectory(): @@ -19291,7 +19259,7 @@ async function copyFolder(prelayout, postlayout, updateTime, destinationFs, dest if (destinationStat === null) { prelayout.push(async () => { try { - await destinationFs.mkdirPromise(destination, {mode: sourceStat.mode}); + await destinationFs.mkdirPromise(destination, { mode: sourceStat.mode }); } catch (err) { if (err.code !== `EEXIST`) { throw err; @@ -19301,7 +19269,7 @@ async function copyFolder(prelayout, postlayout, updateTime, destinationFs, dest updated = true; } const entries = await sourceFs.readdirPromise(source); - const nextOpts = opts.didParentExist && !destinationStat ? __spreadProps$3(__spreadValues$5({}, opts), {didParentExist: false}) : opts; + const nextOpts = opts.didParentExist && !destinationStat ? { ...opts, didParentExist: false } : opts; if (opts.stableSort) { for (const entry of entries.sort()) { if (await copyImpl(prelayout, postlayout, updateTime, destinationFs, destinationFs.pathUtils.join(destination, entry), sourceFs, sourceFs.pathUtils.join(source, entry), nextOpts)) { @@ -19318,11 +19286,11 @@ async function copyFolder(prelayout, postlayout, updateTime, destinationFs, dest } return updated; } -const isCloneSupportedCache = new WeakMap(); +const isCloneSupportedCache = /* @__PURE__ */ new WeakMap(); function makeLinkOperation(opFs, destination, source, sourceStat, linkStrategy) { return async () => { await opFs.linkPromise(source, destination); - if (linkStrategy === LinkStrategy.ReadOnly) { + if (linkStrategy === "readOnly" /* ReadOnly */) { sourceStat.mode &= ~146; await opFs.chmodPromise(destination, sourceStat.mode); } @@ -19383,7 +19351,7 @@ async function copySymlink(prelayout, postlayout, updateTime, destinationFs, des } function makeError$1(code, message) { - return Object.assign(new Error(`${code}: ${message}`), {code}); + return Object.assign(new Error(`${code}: ${message}`), { code }); } function EBUSY(message) { return makeError$1(`EBUSY`, message); @@ -19490,7 +19458,7 @@ class FakeFS { constructor(pathUtils) { this.pathUtils = pathUtils; } - async *genTraversePromise(init, {stableSort = false} = {}) { + async *genTraversePromise(init, { stableSort = false } = {}) { const stack = [init]; while (stack.length > 0) { const p = stack.shift(); @@ -19509,7 +19477,7 @@ class FakeFS { } } } - async removePromise(p, {recursive = true, maxRetries = 5} = {}) { + async removePromise(p, { recursive = true, maxRetries = 5 } = {}) { let stat; try { stat = await this.lstatPromise(p); @@ -19543,7 +19511,7 @@ class FakeFS { await this.unlinkPromise(p); } } - removeSync(p, {recursive = true} = {}) { + removeSync(p, { recursive = true } = {}) { let stat; try { stat = this.lstatSync(p); @@ -19563,7 +19531,7 @@ class FakeFS { this.unlinkSync(p); } } - async mkdirpPromise(p, {chmod, utimes} = {}) { + async mkdirpPromise(p, { chmod, utimes } = {}) { p = this.resolve(p); if (p === this.pathUtils.dirname(p)) return void 0; @@ -19594,7 +19562,7 @@ class FakeFS { } return createdDirectory; } - mkdirpSync(p, {chmod, utimes} = {}) { + mkdirpSync(p, { chmod, utimes } = {}) { p = this.resolve(p); if (p === this.pathUtils.dirname(p)) return void 0; @@ -19625,17 +19593,17 @@ class FakeFS { } return createdDirectory; } - async copyPromise(destination, source, {baseFs = this, overwrite = true, stableSort = false, stableTime = false, linkStrategy = null} = {}) { - return await copyPromise(this, destination, baseFs, source, {overwrite, stableSort, stableTime, linkStrategy}); + async copyPromise(destination, source, { baseFs = this, overwrite = true, stableSort = false, stableTime = false, linkStrategy = null } = {}) { + return await copyPromise(this, destination, baseFs, source, { overwrite, stableSort, stableTime, linkStrategy }); } - copySync(destination, source, {baseFs = this, overwrite = true} = {}) { + copySync(destination, source, { baseFs = this, overwrite = true } = {}) { const stat = baseFs.lstatSync(source); const exists = this.existsSync(destination); if (stat.isDirectory()) { this.mkdirpSync(destination); const directoryListing = baseFs.readdirSync(source); for (const entry of directoryListing) { - this.copySync(this.pathUtils.join(destination, entry), baseFs.pathUtils.join(source, entry), {baseFs, overwrite}); + this.copySync(this.pathUtils.join(destination, entry), baseFs.pathUtils.join(source, entry), { baseFs, overwrite }); } } else if (stat.isFile()) { if (!exists || overwrite) { @@ -19664,7 +19632,7 @@ class FakeFS { return this.changeFileTextPromise(p, content, opts); } } - async changeFileBufferPromise(p, content, {mode} = {}) { + async changeFileBufferPromise(p, content, { mode } = {}) { let current = Buffer.alloc(0); try { current = await this.readFilePromise(p); @@ -19672,9 +19640,9 @@ class FakeFS { } if (Buffer.compare(current, content) === 0) return; - await this.writeFilePromise(p, content, {mode}); + await this.writeFilePromise(p, content, { mode }); } - async changeFileTextPromise(p, content, {automaticNewlines, mode} = {}) { + async changeFileTextPromise(p, content, { automaticNewlines, mode } = {}) { let current = ``; try { current = await this.readFilePromise(p, `utf8`); @@ -19683,7 +19651,7 @@ class FakeFS { const normalizedContent = automaticNewlines ? normalizeLineEndings(current, content) : content; if (current === normalizedContent) return; - await this.writeFilePromise(p, normalizedContent, {mode}); + await this.writeFilePromise(p, normalizedContent, { mode }); } changeFileSync(p, content, opts = {}) { if (Buffer.isBuffer(content)) { @@ -19692,7 +19660,7 @@ class FakeFS { return this.changeFileTextSync(p, content, opts); } } - changeFileBufferSync(p, content, {mode} = {}) { + changeFileBufferSync(p, content, { mode } = {}) { let current = Buffer.alloc(0); try { current = this.readFileSync(p); @@ -19700,9 +19668,9 @@ class FakeFS { } if (Buffer.compare(current, content) === 0) return; - this.writeFileSync(p, content, {mode}); + this.writeFileSync(p, content, { mode }); } - changeFileTextSync(p, content, {automaticNewlines = false, mode} = {}) { + changeFileTextSync(p, content, { automaticNewlines = false, mode } = {}) { let current = ``; try { current = this.readFileSync(p, `utf8`); @@ -19711,7 +19679,7 @@ class FakeFS { const normalizedContent = automaticNewlines ? normalizeLineEndings(current, content) : content; if (current === normalizedContent) return; - this.writeFileSync(p, normalizedContent, {mode}); + this.writeFileSync(p, normalizedContent, { mode }); } async movePromise(fromP, toP) { try { @@ -19892,12 +19860,12 @@ class NodeFS extends BasePortableFakeFS { this.realFs.opendir(npath.fromPortablePath(p), this.makeCallback(resolve, reject)); } }).then((dir) => { - return Object.defineProperty(dir, `path`, {value: p, configurable: true, writable: true}); + return Object.defineProperty(dir, `path`, { value: p, configurable: true, writable: true }); }); } opendirSync(p, opts) { const dir = typeof opts !== `undefined` ? this.realFs.opendirSync(npath.fromPortablePath(p), opts) : this.realFs.opendirSync(npath.fromPortablePath(p)); - return Object.defineProperty(dir, `path`, {value: p, configurable: true, writable: true}); + return Object.defineProperty(dir, `path`, { value: p, configurable: true, writable: true }); } async readPromise(fd, buffer, offset = 0, length = 0, position = -1) { return await new Promise((resolve, reject) => { @@ -20035,6 +20003,14 @@ class NodeFS extends BasePortableFakeFS { chmodSync(p, mask) { return this.realFs.chmodSync(npath.fromPortablePath(p), mask); } + async fchownPromise(fd, uid, gid) { + return await new Promise((resolve, reject) => { + this.realFs.fchown(fd, uid, gid, this.makeCallback(resolve, reject)); + }); + } + fchownSync(fd, uid, gid) { + return this.realFs.fchownSync(fd, uid, gid); + } async chownPromise(p, uid, gid) { return await new Promise((resolve, reject) => { this.realFs.chown(npath.fromPortablePath(p), uid, gid, this.makeCallback(resolve, reject)); @@ -20174,7 +20150,7 @@ class NodeFS extends BasePortableFakeFS { async readdirPromise(p, opts) { return await new Promise((resolve, reject) => { if (opts == null ? void 0 : opts.withFileTypes) { - this.realFs.readdir(npath.fromPortablePath(p), {withFileTypes: true}, this.makeCallback(resolve, reject)); + this.realFs.readdir(npath.fromPortablePath(p), { withFileTypes: true }, this.makeCallback(resolve, reject)); } else { this.realFs.readdir(npath.fromPortablePath(p), this.makeCallback((value) => resolve(value), reject)); } @@ -20182,7 +20158,7 @@ class NodeFS extends BasePortableFakeFS { } readdirSync(p, opts) { if (opts == null ? void 0 : opts.withFileTypes) { - return this.realFs.readdirSync(npath.fromPortablePath(p), {withFileTypes: true}); + return this.realFs.readdirSync(npath.fromPortablePath(p), { withFileTypes: true }); } else { return this.realFs.readdirSync(npath.fromPortablePath(p)); } @@ -20214,10 +20190,18 @@ class NodeFS extends BasePortableFakeFS { return this.realFs.ftruncateSync(fd, len); } watch(p, a, b) { - return this.realFs.watch(npath.fromPortablePath(p), a, b); + return this.realFs.watch( + npath.fromPortablePath(p), + a, + b + ); } watchFile(p, a, b) { - return this.realFs.watchFile(npath.fromPortablePath(p), a, b); + return this.realFs.watchFile( + npath.fromPortablePath(p), + a, + b + ); } unwatchFile(p, cb) { return this.realFs.unwatchFile(npath.fromPortablePath(p), cb); @@ -20233,27 +20217,16 @@ class NodeFS extends BasePortableFakeFS { } } -var Event; -(function(Event2) { - Event2["Change"] = `change`; - Event2["Stop"] = `stop`; -})(Event || (Event = {})); -var Status; -(function(Status2) { - Status2["Ready"] = `ready`; - Status2["Running"] = `running`; - Status2["Stopped"] = `stopped`; -})(Status || (Status = {})); function assertStatus(current, expected) { if (current !== expected) { throw new Error(`Invalid StatWatcher status: expected '${expected}', got '${current}'`); } } class CustomStatWatcher extends events.EventEmitter { - constructor(fakeFs, path, {bigint = false} = {}) { + constructor(fakeFs, path, { bigint = false } = {}) { super(); - this.status = Status.Ready; - this.changeListeners = new Map(); + this.status = "ready" /* Ready */; + this.changeListeners = /* @__PURE__ */ new Map(); this.startTimeout = null; this.fakeFs = fakeFs; this.path = path; @@ -20266,27 +20239,27 @@ class CustomStatWatcher extends events.EventEmitter { return statWatcher; } start() { - assertStatus(this.status, Status.Ready); - this.status = Status.Running; + assertStatus(this.status, "ready" /* Ready */); + this.status = "running" /* Running */; this.startTimeout = setTimeout(() => { this.startTimeout = null; if (!this.fakeFs.existsSync(this.path)) { - this.emit(Event.Change, this.lastStats, this.lastStats); + this.emit("change" /* Change */, this.lastStats, this.lastStats); } }, 3); } stop() { - assertStatus(this.status, Status.Running); - this.status = Status.Stopped; + assertStatus(this.status, "running" /* Running */); + this.status = "stopped" /* Stopped */; if (this.startTimeout !== null) { clearTimeout(this.startTimeout); this.startTimeout = null; } - this.emit(Event.Stop); + this.emit("stop" /* Stop */); } stat() { try { - return this.fakeFs.statSync(this.path, {bigint: this.bigint}); + return this.fakeFs.statSync(this.path, { bigint: this.bigint }); } catch (error) { const statInstance = this.bigint ? new BigIntStatsEntry() : new StatEntry(); return clearStats(statInstance); @@ -20299,16 +20272,16 @@ class CustomStatWatcher extends events.EventEmitter { if (areStatsEqual(currentStats, previousStats)) return; this.lastStats = currentStats; - this.emit(Event.Change, currentStats, previousStats); + this.emit("change" /* Change */, currentStats, previousStats); }, opts.interval); return opts.persistent ? interval : interval.unref(); } registerChangeListener(listener, opts) { - this.addListener(Event.Change, listener); + this.addListener("change" /* Change */, listener); this.changeListeners.set(listener, this.makeInterval(opts)); } unregisterChangeListener(listener) { - this.removeListener(Event.Change, listener); + this.removeListener("change" /* Change */, listener); const interval = this.changeListeners.get(listener); if (typeof interval !== `undefined`) clearInterval(interval); @@ -20334,7 +20307,7 @@ class CustomStatWatcher extends events.EventEmitter { } } -const statWatchersByFakeFS = new WeakMap(); +const statWatchersByFakeFS = /* @__PURE__ */ new WeakMap(); function watchFile(fakeFs, path, a, b) { let bigint; let persistent; @@ -20362,13 +20335,13 @@ function watchFile(fakeFs, path, a, b) { } let statWatchers = statWatchersByFakeFS.get(fakeFs); if (typeof statWatchers === `undefined`) - statWatchersByFakeFS.set(fakeFs, statWatchers = new Map()); + statWatchersByFakeFS.set(fakeFs, statWatchers = /* @__PURE__ */ new Map()); let statWatcher = statWatchers.get(path); if (typeof statWatcher === `undefined`) { - statWatcher = CustomStatWatcher.create(fakeFs, path, {bigint}); + statWatcher = CustomStatWatcher.create(fakeFs, path, { bigint }); statWatchers.set(path, statWatcher); } - statWatcher.registerChangeListener(listener, {persistent, interval}); + statWatcher.registerChangeListener(listener, { persistent, interval }); return statWatcher; } function unwatchFile(fakeFs, path, cb) { @@ -20396,22 +20369,6 @@ function unwatchAllFiles(fakeFs) { } } -var __defProp$4 = Object.defineProperty; -var __getOwnPropSymbols$5 = Object.getOwnPropertySymbols; -var __hasOwnProp$5 = Object.prototype.hasOwnProperty; -var __propIsEnum$5 = Object.prototype.propertyIsEnumerable; -var __defNormalProp$4 = (obj, key, value) => key in obj ? __defProp$4(obj, key, {enumerable: true, configurable: true, writable: true, value}) : obj[key] = value; -var __spreadValues$4 = (a, b) => { - for (var prop in b || (b = {})) - if (__hasOwnProp$5.call(b, prop)) - __defNormalProp$4(a, prop, b[prop]); - if (__getOwnPropSymbols$5) - for (var prop of __getOwnPropSymbols$5(b)) { - if (__propIsEnum$5.call(b, prop)) - __defNormalProp$4(a, prop, b[prop]); - } - return a; -}; const DEFAULT_COMPRESSION_LEVEL = `mixed`; function toUnixTimestamp(time) { if (typeof time === `string` && String(+time) === time) @@ -20457,10 +20414,10 @@ class ZipFS extends BasePortableFakeFS { constructor(source, opts) { super(); this.lzSource = null; - this.listings = new Map(); - this.entries = new Map(); - this.fileSources = new Map(); - this.fds = new Map(); + this.listings = /* @__PURE__ */ new Map(); + this.entries = /* @__PURE__ */ new Map(); + this.fileSources = /* @__PURE__ */ new Map(); + this.fds = /* @__PURE__ */ new Map(); this.nextFd = 0; this.ready = false; this.readOnly = false; @@ -20469,7 +20426,7 @@ class ZipFS extends BasePortableFakeFS { this.level = typeof pathOptions.level !== `undefined` ? pathOptions.level : DEFAULT_COMPRESSION_LEVEL; source != null ? source : source = makeEmptyArchive(); if (typeof source === `string`) { - const {baseFs = new NodeFS()} = pathOptions; + const { baseFs = new NodeFS() } = pathOptions; this.baseFs = baseFs; this.path = source; } else { @@ -20522,7 +20479,7 @@ class ZipFS extends BasePortableFakeFS { } finally { this.libzip.free(errPtr); } - this.listings.set(PortablePath.root, new Set()); + this.listings.set(PortablePath.root, /* @__PURE__ */ new Set()); const entryCount = this.libzip.getNumEntries(this.zip, 0); for (let t = 0; t < entryCount; ++t) { const raw = this.libzip.getName(this.zip, t, 0); @@ -20619,7 +20576,7 @@ class ZipFS extends BasePortableFakeFS { const newMode = this.baseFs.existsSync(this.path) || this.stats.mode === DEFAULT_MODE ? void 0 : this.stats.mode; if (this.entries.size === 0) { this.discardAndClose(); - this.baseFs.writeFileSync(this.path, makeEmptyArchive(), {mode: newMode}); + this.baseFs.writeFileSync(this.path, makeEmptyArchive(), { mode: newMode }); } else { const rc = this.libzip.close(this.zip); if (rc === -1) @@ -20643,7 +20600,7 @@ class ZipFS extends BasePortableFakeFS { } openSync(p, flags, mode) { const fd = this.nextFd++; - this.fds.set(fd, {cursor: 0, p}); + this.fds.set(fd, { cursor: 0, p }); return fd; } hasOpenFileHandles() { @@ -20664,7 +20621,7 @@ class ZipFS extends BasePortableFakeFS { const onClose = () => { this.closeSync(fd); }; - return opendir(this, resolvedP, entries, {onClose}); + return opendir(this, resolvedP, entries, { onClose }); } async readPromise(fd, buffer, offset, length, position) { return this.readSync(fd, buffer, offset, length, position); @@ -20703,25 +20660,28 @@ class ZipFS extends BasePortableFakeFS { throw EBADF(`read`); this.fds.delete(fd); } - createReadStream(p, {encoding} = {}) { + createReadStream(p, { encoding } = {}) { if (p === null) throw new Error(`Unimplemented`); const fd = this.openSync(p, `r`); - const stream$1 = Object.assign(new stream.PassThrough({ - emitClose: true, - autoDestroy: true, - destroy: (error, callback) => { - clearImmediate(immediate); - this.closeSync(fd); - callback(error); + const stream$1 = Object.assign( + new stream.PassThrough({ + emitClose: true, + autoDestroy: true, + destroy: (error, callback) => { + clearImmediate(immediate); + this.closeSync(fd); + callback(error); + } + }), + { + close() { + stream$1.destroy(); + }, + bytesRead: 0, + path: p } - }), { - close() { - stream$1.destroy(); - }, - bytesRead: 0, - path: p - }); + ); const immediate = setImmediate(async () => { try { const data = await this.readFilePromise(p, encoding); @@ -20733,37 +20693,40 @@ class ZipFS extends BasePortableFakeFS { }); return stream$1; } - createWriteStream(p, {encoding} = {}) { + createWriteStream(p, { encoding } = {}) { if (this.readOnly) throw EROFS(`open '${p}'`); if (p === null) throw new Error(`Unimplemented`); const chunks = []; const fd = this.openSync(p, `w`); - const stream$1 = Object.assign(new stream.PassThrough({ - autoDestroy: true, - emitClose: true, - destroy: (error, callback) => { - try { - if (error) { - callback(error); - } else { - this.writeFileSync(p, Buffer.concat(chunks), encoding); - callback(null); + const stream$1 = Object.assign( + new stream.PassThrough({ + autoDestroy: true, + emitClose: true, + destroy: (error, callback) => { + try { + if (error) { + callback(error); + } else { + this.writeFileSync(p, Buffer.concat(chunks), encoding); + callback(null); + } + } catch (err) { + callback(err); + } finally { + this.closeSync(fd); } - } catch (err) { - callback(err); - } finally { - this.closeSync(fd); + } + }), + { + bytesWritten: 0, + path: p, + close() { + stream$1.destroy(); } } - }), { - bytesWritten: 0, - path: p, - close() { - stream$1.destroy(); - } - }); + ); stream$1.on(`data`, (chunk) => { const chunkBuffer = Buffer.from(chunk); stream$1.bytesWritten += chunkBuffer.length; @@ -20811,12 +20774,12 @@ class ZipFS extends BasePortableFakeFS { throw EROFS(`access '${p}'`); } } - async statPromise(p, opts = {bigint: false}) { + async statPromise(p, opts = { bigint: false }) { if (opts.bigint) - return this.statSync(p, {bigint: true}); + return this.statSync(p, { bigint: true }); return this.statSync(p); } - statSync(p, opts = {bigint: false, throwIfNoEntry: true}) { + statSync(p, opts = { bigint: false, throwIfNoEntry: true }) { const resolvedP = this.resolveFilename(`stat '${p}'`, p, void 0, opts.throwIfNoEntry); if (resolvedP === void 0) return void 0; @@ -20836,7 +20799,7 @@ class ZipFS extends BasePortableFakeFS { const entry = this.fds.get(fd); if (typeof entry === `undefined`) throw EBADF(`fstatSync`); - const {p} = entry; + const { p } = entry; const resolvedP = this.resolveFilename(`stat '${p}'`, p); if (!this.entries.has(resolvedP) && !this.listings.has(resolvedP)) throw ENOENT(`stat '${p}'`); @@ -20844,12 +20807,12 @@ class ZipFS extends BasePortableFakeFS { throw ENOTDIR(`stat '${p}'`); return this.statImpl(`fstat '${p}'`, resolvedP, opts); } - async lstatPromise(p, opts = {bigint: false}) { + async lstatPromise(p, opts = { bigint: false }) { if (opts.bigint) - return this.lstatSync(p, {bigint: true}); + return this.lstatSync(p, { bigint: true }); return this.lstatSync(p); } - lstatSync(p, opts = {bigint: false, throwIfNoEntry: true}) { + lstatSync(p, opts = { bigint: false, throwIfNoEntry: true }) { const resolvedP = this.resolveFilename(`lstat '${p}'`, p, false, opts.throwIfNoEntry); if (resolvedP === void 0) return void 0; @@ -20886,7 +20849,7 @@ class ZipFS extends BasePortableFakeFS { const defaultMode = type === S_IFDIR ? 493 : 420; const mode = type | this.getUnixMode(entry, defaultMode) & 511; const crc = this.libzip.struct.statCrc(stat); - const statInstance = Object.assign(new StatEntry(), {uid, gid, size, blksize, blocks, atime, birthtime, ctime, mtime, atimeMs, birthtimeMs, ctimeMs, mtimeMs, mode, crc}); + const statInstance = Object.assign(new StatEntry(), { uid, gid, size, blksize, blocks, atime, birthtime, ctime, mtime, atimeMs, birthtimeMs, ctimeMs, mtimeMs, mode, crc }); return opts.bigint === true ? convertToBigIntStats(statInstance) : statInstance; } if (this.listings.has(p)) { @@ -20905,7 +20868,7 @@ class ZipFS extends BasePortableFakeFS { const mtime = new Date(mtimeMs); const mode = S_IFDIR | 493; const crc = 0; - const statInstance = Object.assign(new StatEntry(), {uid, gid, size, blksize, blocks, atime, birthtime, ctime, mtime, atimeMs, birthtimeMs, ctimeMs, mtimeMs, mode, crc}); + const statInstance = Object.assign(new StatEntry(), { uid, gid, size, blksize, blocks, atime, birthtime, ctime, mtime, atimeMs, birthtimeMs, ctimeMs, mtimeMs, mode, crc }); return opts.bigint === true ? convertToBigIntStats(statInstance) : statInstance; } throw new Error(`Unreachable`); @@ -20925,7 +20888,7 @@ class ZipFS extends BasePortableFakeFS { return existingListing; const parentListing = this.registerListing(ppath.dirname(p)); parentListing.add(ppath.basename(p)); - const newListing = new Set(); + const newListing = /* @__PURE__ */ new Set(); this.listings.set(p, newListing); return newListing; } @@ -21008,11 +20971,11 @@ class ZipFS extends BasePortableFakeFS { throw new Error(`Couldn't allocate enough memory`); const heap = new Uint8Array(this.libzip.HEAPU8.buffer, buffer, content.byteLength); heap.set(content); - return {buffer, byteLength: content.byteLength}; + return { buffer, byteLength: content.byteLength }; } allocateUnattachedSource(content) { const error = this.libzip.struct.errorS(); - const {buffer, byteLength} = this.allocateBuffer(content); + const { buffer, byteLength } = this.allocateBuffer(content); const source = this.libzip.source.fromUnattachedBuffer(buffer, byteLength, 0, true, error); if (source === 0) { this.libzip.free(error); @@ -21021,7 +20984,7 @@ class ZipFS extends BasePortableFakeFS { return source; } allocateSource(content) { - const {buffer, byteLength} = this.allocateBuffer(content); + const { buffer, byteLength } = this.allocateBuffer(content); const source = this.libzip.source.fromBuffer(this.zip, buffer, byteLength, 0, true); if (source === 0) { this.libzip.free(buffer); @@ -21063,7 +21026,7 @@ class ZipFS extends BasePortableFakeFS { const attributes = this.libzip.getValue(this.libzip.uint32S, `i32`) >>> 16; return (attributes & S_IFMT) === S_IFLNK; } - getFileSource(index, opts = {asyncDecompress: false}) { + getFileSource(index, opts = { asyncDecompress: false }) { const cachedFileSource = this.fileSources.get(index); if (typeof cachedFileSource !== `undefined`) return cachedFileSource; @@ -21138,6 +21101,12 @@ class ZipFS extends BasePortableFakeFS { throw this.makeLibzipError(this.libzip.getError(this.zip)); } } + async fchownPromise(fd, uid, gid) { + return this.chownPromise(this.fdToPath(fd, `fchown`), uid, gid); + } + fchownSync(fd, uid, gid) { + return this.chownSync(this.fdToPath(fd, `fchownSync`), uid, gid); + } async chownPromise(p, uid, gid) { return this.chownSync(p, uid, gid); } @@ -21151,15 +21120,15 @@ class ZipFS extends BasePortableFakeFS { throw new Error(`Unimplemented`); } async copyFilePromise(sourceP, destP, flags) { - const {indexSource, indexDest, resolvedDestP} = this.prepareCopyFile(sourceP, destP, flags); - const source = await this.getFileSource(indexSource, {asyncDecompress: true}); + const { indexSource, indexDest, resolvedDestP } = this.prepareCopyFile(sourceP, destP, flags); + const source = await this.getFileSource(indexSource, { asyncDecompress: true }); const newIndex = this.setFileSource(resolvedDestP, source); if (newIndex !== indexDest) { this.registerEntry(resolvedDestP, newIndex); } } copyFileSync(sourceP, destP, flags = 0) { - const {indexSource, indexDest, resolvedDestP} = this.prepareCopyFile(sourceP, destP, flags); + const { indexSource, indexDest, resolvedDestP } = this.prepareCopyFile(sourceP, destP, flags); const source = this.getFileSource(indexSource); const newIndex = this.setFileSource(resolvedDestP, source); if (newIndex !== indexDest) { @@ -21189,22 +21158,22 @@ class ZipFS extends BasePortableFakeFS { if (this.readOnly) throw EROFS(`open '${p}'`); if (typeof opts === `undefined`) - opts = {flag: `a`}; + opts = { flag: `a` }; else if (typeof opts === `string`) - opts = {flag: `a`, encoding: opts}; + opts = { flag: `a`, encoding: opts }; else if (typeof opts.flag === `undefined`) - opts = __spreadValues$4({flag: `a`}, opts); + opts = { flag: `a`, ...opts }; return this.writeFilePromise(p, content, opts); } appendFileSync(p, content, opts = {}) { if (this.readOnly) throw EROFS(`open '${p}'`); if (typeof opts === `undefined`) - opts = {flag: `a`}; + opts = { flag: `a` }; else if (typeof opts === `string`) - opts = {flag: `a`, encoding: opts}; + opts = { flag: `a`, encoding: opts }; else if (typeof opts.flag === `undefined`) - opts = __spreadValues$4({flag: `a`}, opts); + opts = { flag: `a`, ...opts }; return this.writeFileSync(p, content, opts); } fdToPath(fd, reason) { @@ -21215,9 +21184,9 @@ class ZipFS extends BasePortableFakeFS { return path; } async writeFilePromise(p, content, opts) { - const {encoding, mode, index, resolvedP} = this.prepareWriteFile(p, opts); + const { encoding, mode, index, resolvedP } = this.prepareWriteFile(p, opts); if (index !== void 0 && typeof opts === `object` && opts.flag && opts.flag.includes(`a`)) - content = Buffer.concat([await this.getFileSource(index, {asyncDecompress: true}), Buffer.from(content)]); + content = Buffer.concat([await this.getFileSource(index, { asyncDecompress: true }), Buffer.from(content)]); if (encoding !== null) content = content.toString(encoding); const newIndex = this.setFileSource(resolvedP, content); @@ -21228,7 +21197,7 @@ class ZipFS extends BasePortableFakeFS { } } writeFileSync(p, content, opts) { - const {encoding, mode, index, resolvedP} = this.prepareWriteFile(p, opts); + const { encoding, mode, index, resolvedP } = this.prepareWriteFile(p, opts); if (index !== void 0 && typeof opts === `object` && opts.flag && opts.flag.includes(`a`)) content = Buffer.concat([this.getFileSource(index), Buffer.from(content)]); if (encoding !== null) @@ -21313,9 +21282,9 @@ class ZipFS extends BasePortableFakeFS { async mkdirPromise(p, opts) { return this.mkdirSync(p, opts); } - mkdirSync(p, {mode = 493, recursive = false} = {}) { + mkdirSync(p, { mode = 493, recursive = false } = {}) { if (recursive) - return this.mkdirpSync(p, {chmod: mode}); + return this.mkdirpSync(p, { chmod: mode }); if (this.readOnly) throw EROFS(`mkdir '${p}'`); const resolvedP = this.resolveFilename(`mkdir '${p}'`, p); @@ -21328,7 +21297,7 @@ class ZipFS extends BasePortableFakeFS { async rmdirPromise(p, opts) { return this.rmdirSync(p, opts); } - rmdirSync(p, {recursive = false} = {}) { + rmdirSync(p, { recursive = false } = {}) { if (this.readOnly) throw EROFS(`rmdir '${p}'`); if (recursive) { @@ -21381,7 +21350,7 @@ class ZipFS extends BasePortableFakeFS { async readFilePromise(p, encoding) { if (typeof encoding === `object`) encoding = encoding ? encoding.encoding : void 0; - const data = await this.readFileBuffer(p, {asyncDecompress: true}); + const data = await this.readFileBuffer(p, { asyncDecompress: true }); return encoding ? data.toString(encoding) : data; } readFileSync(p, encoding) { @@ -21390,7 +21359,7 @@ class ZipFS extends BasePortableFakeFS { const data = this.readFileBuffer(p); return encoding ? data.toString(encoding) : data; } - readFileBuffer(p, opts = {asyncDecompress: false}) { + readFileBuffer(p, opts = { asyncDecompress: false }) { if (typeof p === `number`) p = this.fdToPath(p, `read`); const resolvedP = this.resolveFilename(`open '${p}'`, p); @@ -21426,7 +21395,7 @@ class ZipFS extends BasePortableFakeFS { } async readlinkPromise(p) { const entry = this.prepareReadlink(p); - return (await this.getFileSource(entry, {asyncDecompress: true})).toString(); + return (await this.getFileSource(entry, { asyncDecompress: true })).toString(); } readlinkSync(p) { const entry = this.prepareReadlink(p); @@ -21452,7 +21421,7 @@ class ZipFS extends BasePortableFakeFS { const index = this.entries.get(resolvedP); if (typeof index === `undefined`) throw EINVAL(`open '${p}'`); - const source = await this.getFileSource(index, {asyncDecompress: true}); + const source = await this.getFileSource(index, { asyncDecompress: true }); const truncated = Buffer.alloc(len, 0); source.copy(truncated); return await this.writeFilePromise(p, truncated); @@ -21485,20 +21454,20 @@ class ZipFS extends BasePortableFakeFS { break; default: { - ({persistent = true} = a); + ({ persistent = true } = a); } break; } if (!persistent) - return {on: () => { + return { on: () => { }, close: () => { - }}; + } }; const interval = setInterval(() => { }, 24 * 60 * 60 * 1e3); - return {on: () => { + return { on: () => { }, close: () => { clearInterval(interval); - }}; + } }; } watchFile(p, a, b) { const resolvedP = ppath.resolve(PortablePath.root, p); @@ -21527,10 +21496,10 @@ class ProxiedFS extends FakeFS { return this.baseFs.openSync(this.mapToBase(p), flags, mode); } async opendirPromise(p, opts) { - return Object.assign(await this.baseFs.opendirPromise(this.mapToBase(p), opts), {path: p}); + return Object.assign(await this.baseFs.opendirPromise(this.mapToBase(p), opts), { path: p }); } opendirSync(p, opts) { - return Object.assign(this.baseFs.opendirSync(this.mapToBase(p), opts), {path: p}); + return Object.assign(this.baseFs.opendirSync(this.mapToBase(p), opts), { path: p }); } async readPromise(fd, buffer, offset, length, position) { return await this.baseFs.readPromise(fd, buffer, offset, length, position); @@ -21612,6 +21581,12 @@ class ProxiedFS extends FakeFS { chmodSync(p, mask) { return this.baseFs.chmodSync(this.mapToBase(p), mask); } + async fchownPromise(fd, uid, gid) { + return this.baseFs.fchownPromise(fd, uid, gid); + } + fchownSync(fd, uid, gid) { + return this.baseFs.fchownSync(fd, uid, gid); + } async chownPromise(p, uid, gid) { return this.baseFs.chownPromise(this.mapToBase(p), uid, gid); } @@ -21727,10 +21702,18 @@ class ProxiedFS extends FakeFS { return this.baseFs.ftruncateSync(fd, len); } watch(p, a, b) { - return this.baseFs.watch(this.mapToBase(p), a, b); + return this.baseFs.watch( + this.mapToBase(p), + a, + b + ); } watchFile(p, a, b) { - return this.baseFs.watchFile(this.mapToBase(p), a, b); + return this.baseFs.watchFile( + this.mapToBase(p), + a, + b + ); } unwatchFile(p, cb) { return this.baseFs.unwatchFile(this.mapToBase(p), cb); @@ -21761,6 +21744,10 @@ const NUMBER_REGEXP = /^[0-9]+$/; const VIRTUAL_REGEXP = /^(\/(?:[^/]+\/)*?(?:\$\$virtual|__virtual__))((?:\/((?:[^/]+-)?[a-f0-9]+)(?:\/([^/]+))?)?((?:\/.*)?))$/; const VALID_COMPONENT = /^([^/]+-)?[a-f0-9]+$/; class VirtualFS extends ProxiedFS { + constructor({ baseFs = new NodeFS() } = {}) { + super(ppath); + this.baseFs = baseFs; + } static makeVirtualPath(base, component, to) { if (ppath.basename(base) !== `__virtual__`) throw new Error(`Assertion failed: Virtual folders must be named "__virtual__"`); @@ -21790,10 +21777,6 @@ class VirtualFS extends ProxiedFS { const subpath = match[5] || `.`; return VirtualFS.resolveVirtual(ppath.join(target, backstep, subpath)); } - constructor({baseFs = new NodeFS()} = {}) { - super(ppath); - this.baseFs = baseFs; - } getExtractHint(hints) { return this.baseFs.getExtractHint(hints); } @@ -21832,7 +21815,8 @@ class VirtualFS extends ProxiedFS { } } -const ZIP_FD = 2147483648; +const ZIP_MASK = 4278190080; +const ZIP_MAGIC = 704643072; const getArchivePart = (path, extension) => { let idx = path.indexOf(extension); if (idx <= 0) @@ -21851,17 +21835,17 @@ const getArchivePart = (path, extension) => { return path.slice(0, nextCharIdx); }; class ZipOpenFS extends BasePortableFakeFS { - constructor({libzip, baseFs = new NodeFS(), filter = null, maxOpenFiles = Infinity, readOnlyArchives = false, useCache = true, maxAge = 5e3, fileExtensions = null}) { + constructor({ libzip, baseFs = new NodeFS(), filter = null, maxOpenFiles = Infinity, readOnlyArchives = false, useCache = true, maxAge = 5e3, fileExtensions = null }) { super(); - this.fdMap = new Map(); + this.fdMap = /* @__PURE__ */ new Map(); this.nextFd = 3; - this.isZip = new Set(); - this.notZip = new Set(); - this.realPaths = new Map(); + this.isZip = /* @__PURE__ */ new Set(); + this.notZip = /* @__PURE__ */ new Set(); + this.realPaths = /* @__PURE__ */ new Map(); this.limitOpenFilesTimeout = null; this.libzipFactory = typeof libzip !== `function` ? () => libzip : libzip; this.baseFs = baseFs; - this.zipInstances = useCache ? new Map() : null; + this.zipInstances = useCache ? /* @__PURE__ */ new Map() : null; this.filter = filter; this.maxOpenFiles = maxOpenFiles; this.readOnlyArchives = readOnlyArchives; @@ -21890,7 +21874,7 @@ class ZipOpenFS extends BasePortableFakeFS { saveAndClose() { unwatchAllFiles(this); if (this.zipInstances) { - for (const [path, {zipFs}] of this.zipInstances.entries()) { + for (const [path, { zipFs }] of this.zipInstances.entries()) { zipFs.saveAndClose(); this.zipInstances.delete(path); } @@ -21899,7 +21883,7 @@ class ZipOpenFS extends BasePortableFakeFS { discardAndClose() { unwatchAllFiles(this); if (this.zipInstances) { - for (const [path, {zipFs}] of this.zipInstances.entries()) { + for (const [path, { zipFs }] of this.zipInstances.entries()) { zipFs.discardAndClose(); this.zipInstances.delete(path); } @@ -21909,28 +21893,28 @@ class ZipOpenFS extends BasePortableFakeFS { return this.baseFs.resolve(p); } remapFd(zipFs, fd) { - const remappedFd = this.nextFd++ | ZIP_FD; + const remappedFd = this.nextFd++ | ZIP_MAGIC; this.fdMap.set(remappedFd, [zipFs, fd]); return remappedFd; } async openPromise(p, flags, mode) { return await this.makeCallPromise(p, async () => { return await this.baseFs.openPromise(p, flags, mode); - }, async (zipFs, {subPath}) => { + }, async (zipFs, { subPath }) => { return this.remapFd(zipFs, await zipFs.openPromise(subPath, flags, mode)); }); } openSync(p, flags, mode) { return this.makeCallSync(p, () => { return this.baseFs.openSync(p, flags, mode); - }, (zipFs, {subPath}) => { + }, (zipFs, { subPath }) => { return this.remapFd(zipFs, zipFs.openSync(subPath, flags, mode)); }); } async opendirPromise(p, opts) { return await this.makeCallPromise(p, async () => { return await this.baseFs.opendirPromise(p, opts); - }, async (zipFs, {subPath}) => { + }, async (zipFs, { subPath }) => { return await zipFs.opendirPromise(subPath, opts); }, { requireSubpath: false @@ -21939,14 +21923,14 @@ class ZipOpenFS extends BasePortableFakeFS { opendirSync(p, opts) { return this.makeCallSync(p, () => { return this.baseFs.opendirSync(p, opts); - }, (zipFs, {subPath}) => { + }, (zipFs, { subPath }) => { return zipFs.opendirSync(subPath, opts); }, { requireSubpath: false }); } async readPromise(fd, buffer, offset, length, position) { - if ((fd & ZIP_FD) === 0) + if ((fd & ZIP_MASK) !== ZIP_MAGIC) return await this.baseFs.readPromise(fd, buffer, offset, length, position); const entry = this.fdMap.get(fd); if (typeof entry === `undefined`) @@ -21955,7 +21939,7 @@ class ZipOpenFS extends BasePortableFakeFS { return await zipFs.readPromise(realFd, buffer, offset, length, position); } readSync(fd, buffer, offset, length, position) { - if ((fd & ZIP_FD) === 0) + if ((fd & ZIP_MASK) !== ZIP_MAGIC) return this.baseFs.readSync(fd, buffer, offset, length, position); const entry = this.fdMap.get(fd); if (typeof entry === `undefined`) @@ -21964,7 +21948,7 @@ class ZipOpenFS extends BasePortableFakeFS { return zipFs.readSync(realFd, buffer, offset, length, position); } async writePromise(fd, buffer, offset, length, position) { - if ((fd & ZIP_FD) === 0) { + if ((fd & ZIP_MASK) !== ZIP_MAGIC) { if (typeof buffer === `string`) { return await this.baseFs.writePromise(fd, buffer, offset); } else { @@ -21982,7 +21966,7 @@ class ZipOpenFS extends BasePortableFakeFS { } } writeSync(fd, buffer, offset, length, position) { - if ((fd & ZIP_FD) === 0) { + if ((fd & ZIP_MASK) !== ZIP_MAGIC) { if (typeof buffer === `string`) { return this.baseFs.writeSync(fd, buffer, offset); } else { @@ -22000,7 +21984,7 @@ class ZipOpenFS extends BasePortableFakeFS { } } async closePromise(fd) { - if ((fd & ZIP_FD) === 0) + if ((fd & ZIP_MASK) !== ZIP_MAGIC) return await this.baseFs.closePromise(fd); const entry = this.fdMap.get(fd); if (typeof entry === `undefined`) @@ -22010,7 +21994,7 @@ class ZipOpenFS extends BasePortableFakeFS { return await zipFs.closePromise(realFd); } closeSync(fd) { - if ((fd & ZIP_FD) === 0) + if ((fd & ZIP_MASK) !== ZIP_MAGIC) return this.baseFs.closeSync(fd); const entry = this.fdMap.get(fd); if (typeof entry === `undefined`) @@ -22024,7 +22008,7 @@ class ZipOpenFS extends BasePortableFakeFS { return this.baseFs.createReadStream(p, opts); return this.makeCallSync(p, () => { return this.baseFs.createReadStream(p, opts); - }, (zipFs, {archivePath, subPath}) => { + }, (zipFs, { archivePath, subPath }) => { const stream = zipFs.createReadStream(subPath, opts); stream.path = npath.fromPortablePath(this.pathUtils.join(archivePath, subPath)); return stream; @@ -22035,14 +22019,14 @@ class ZipOpenFS extends BasePortableFakeFS { return this.baseFs.createWriteStream(p, opts); return this.makeCallSync(p, () => { return this.baseFs.createWriteStream(p, opts); - }, (zipFs, {subPath}) => { + }, (zipFs, { subPath }) => { return zipFs.createWriteStream(subPath, opts); }); } async realpathPromise(p) { return await this.makeCallPromise(p, async () => { return await this.baseFs.realpathPromise(p); - }, async (zipFs, {archivePath, subPath}) => { + }, async (zipFs, { archivePath, subPath }) => { let realArchivePath = this.realPaths.get(archivePath); if (typeof realArchivePath === `undefined`) { realArchivePath = await this.baseFs.realpathPromise(archivePath); @@ -22054,7 +22038,7 @@ class ZipOpenFS extends BasePortableFakeFS { realpathSync(p) { return this.makeCallSync(p, () => { return this.baseFs.realpathSync(p); - }, (zipFs, {archivePath, subPath}) => { + }, (zipFs, { archivePath, subPath }) => { let realArchivePath = this.realPaths.get(archivePath); if (typeof realArchivePath === `undefined`) { realArchivePath = this.baseFs.realpathSync(archivePath); @@ -22066,47 +22050,47 @@ class ZipOpenFS extends BasePortableFakeFS { async existsPromise(p) { return await this.makeCallPromise(p, async () => { return await this.baseFs.existsPromise(p); - }, async (zipFs, {subPath}) => { + }, async (zipFs, { subPath }) => { return await zipFs.existsPromise(subPath); }); } existsSync(p) { return this.makeCallSync(p, () => { return this.baseFs.existsSync(p); - }, (zipFs, {subPath}) => { + }, (zipFs, { subPath }) => { return zipFs.existsSync(subPath); }); } async accessPromise(p, mode) { return await this.makeCallPromise(p, async () => { return await this.baseFs.accessPromise(p, mode); - }, async (zipFs, {subPath}) => { + }, async (zipFs, { subPath }) => { return await zipFs.accessPromise(subPath, mode); }); } accessSync(p, mode) { return this.makeCallSync(p, () => { return this.baseFs.accessSync(p, mode); - }, (zipFs, {subPath}) => { + }, (zipFs, { subPath }) => { return zipFs.accessSync(subPath, mode); }); } async statPromise(p, opts) { return await this.makeCallPromise(p, async () => { return await this.baseFs.statPromise(p, opts); - }, async (zipFs, {subPath}) => { + }, async (zipFs, { subPath }) => { return await zipFs.statPromise(subPath, opts); }); } statSync(p, opts) { return this.makeCallSync(p, () => { return this.baseFs.statSync(p, opts); - }, (zipFs, {subPath}) => { + }, (zipFs, { subPath }) => { return zipFs.statSync(subPath, opts); }); } async fstatPromise(fd, opts) { - if ((fd & ZIP_FD) === 0) + if ((fd & ZIP_MASK) !== ZIP_MAGIC) return this.baseFs.fstatPromise(fd, opts); const entry = this.fdMap.get(fd); if (typeof entry === `undefined`) @@ -22115,7 +22099,7 @@ class ZipOpenFS extends BasePortableFakeFS { return zipFs.fstatPromise(realFd, opts); } fstatSync(fd, opts) { - if ((fd & ZIP_FD) === 0) + if ((fd & ZIP_MASK) !== ZIP_MAGIC) return this.baseFs.fstatSync(fd, opts); const entry = this.fdMap.get(fd); if (typeof entry === `undefined`) @@ -22126,19 +22110,19 @@ class ZipOpenFS extends BasePortableFakeFS { async lstatPromise(p, opts) { return await this.makeCallPromise(p, async () => { return await this.baseFs.lstatPromise(p, opts); - }, async (zipFs, {subPath}) => { + }, async (zipFs, { subPath }) => { return await zipFs.lstatPromise(subPath, opts); }); } lstatSync(p, opts) { return this.makeCallSync(p, () => { return this.baseFs.lstatSync(p, opts); - }, (zipFs, {subPath}) => { + }, (zipFs, { subPath }) => { return zipFs.lstatSync(subPath, opts); }); } async fchmodPromise(fd, mask) { - if ((fd & ZIP_FD) === 0) + if ((fd & ZIP_MASK) !== ZIP_MAGIC) return this.baseFs.fchmodPromise(fd, mask); const entry = this.fdMap.get(fd); if (typeof entry === `undefined`) @@ -22147,7 +22131,7 @@ class ZipOpenFS extends BasePortableFakeFS { return zipFs.fchmodPromise(realFd, mask); } fchmodSync(fd, mask) { - if ((fd & ZIP_FD) === 0) + if ((fd & ZIP_MASK) !== ZIP_MAGIC) return this.baseFs.fchmodSync(fd, mask); const entry = this.fdMap.get(fd); if (typeof entry === `undefined`) @@ -22158,28 +22142,46 @@ class ZipOpenFS extends BasePortableFakeFS { async chmodPromise(p, mask) { return await this.makeCallPromise(p, async () => { return await this.baseFs.chmodPromise(p, mask); - }, async (zipFs, {subPath}) => { + }, async (zipFs, { subPath }) => { return await zipFs.chmodPromise(subPath, mask); }); } chmodSync(p, mask) { return this.makeCallSync(p, () => { return this.baseFs.chmodSync(p, mask); - }, (zipFs, {subPath}) => { + }, (zipFs, { subPath }) => { return zipFs.chmodSync(subPath, mask); }); } + async fchownPromise(fd, uid, gid) { + if ((fd & ZIP_MASK) !== ZIP_MAGIC) + return this.baseFs.fchownPromise(fd, uid, gid); + const entry = this.fdMap.get(fd); + if (typeof entry === `undefined`) + throw EBADF(`fchown`); + const [zipFs, realFd] = entry; + return zipFs.fchownPromise(realFd, uid, gid); + } + fchownSync(fd, uid, gid) { + if ((fd & ZIP_MASK) !== ZIP_MAGIC) + return this.baseFs.fchownSync(fd, uid, gid); + const entry = this.fdMap.get(fd); + if (typeof entry === `undefined`) + throw EBADF(`fchownSync`); + const [zipFs, realFd] = entry; + return zipFs.fchownSync(realFd, uid, gid); + } async chownPromise(p, uid, gid) { return await this.makeCallPromise(p, async () => { return await this.baseFs.chownPromise(p, uid, gid); - }, async (zipFs, {subPath}) => { + }, async (zipFs, { subPath }) => { return await zipFs.chownPromise(subPath, uid, gid); }); } chownSync(p, uid, gid) { return this.makeCallSync(p, () => { return this.baseFs.chownSync(p, uid, gid); - }, (zipFs, {subPath}) => { + }, (zipFs, { subPath }) => { return zipFs.chownSync(subPath, uid, gid); }); } @@ -22188,14 +22190,14 @@ class ZipOpenFS extends BasePortableFakeFS { return await this.makeCallPromise(newP, async () => { return await this.baseFs.renamePromise(oldP, newP); }, async () => { - throw Object.assign(new Error(`EEXDEV: cross-device link not permitted`), {code: `EEXDEV`}); + throw Object.assign(new Error(`EEXDEV: cross-device link not permitted`), { code: `EEXDEV` }); }); - }, async (zipFsO, {subPath: subPathO}) => { + }, async (zipFsO, { subPath: subPathO }) => { return await this.makeCallPromise(newP, async () => { - throw Object.assign(new Error(`EEXDEV: cross-device link not permitted`), {code: `EEXDEV`}); - }, async (zipFsN, {subPath: subPathN}) => { + throw Object.assign(new Error(`EEXDEV: cross-device link not permitted`), { code: `EEXDEV` }); + }, async (zipFsN, { subPath: subPathN }) => { if (zipFsO !== zipFsN) { - throw Object.assign(new Error(`EEXDEV: cross-device link not permitted`), {code: `EEXDEV`}); + throw Object.assign(new Error(`EEXDEV: cross-device link not permitted`), { code: `EEXDEV` }); } else { return await zipFsO.renamePromise(subPathO, subPathN); } @@ -22207,14 +22209,14 @@ class ZipOpenFS extends BasePortableFakeFS { return this.makeCallSync(newP, () => { return this.baseFs.renameSync(oldP, newP); }, () => { - throw Object.assign(new Error(`EEXDEV: cross-device link not permitted`), {code: `EEXDEV`}); + throw Object.assign(new Error(`EEXDEV: cross-device link not permitted`), { code: `EEXDEV` }); }); - }, (zipFsO, {subPath: subPathO}) => { + }, (zipFsO, { subPath: subPathO }) => { return this.makeCallSync(newP, () => { - throw Object.assign(new Error(`EEXDEV: cross-device link not permitted`), {code: `EEXDEV`}); - }, (zipFsN, {subPath: subPathN}) => { + throw Object.assign(new Error(`EEXDEV: cross-device link not permitted`), { code: `EEXDEV` }); + }, (zipFsN, { subPath: subPathN }) => { if (zipFsO !== zipFsN) { - throw Object.assign(new Error(`EEXDEV: cross-device link not permitted`), {code: `EEXDEV`}); + throw Object.assign(new Error(`EEXDEV: cross-device link not permitted`), { code: `EEXDEV` }); } else { return zipFsO.renameSync(subPathO, subPathN); } @@ -22224,27 +22226,27 @@ class ZipOpenFS extends BasePortableFakeFS { async copyFilePromise(sourceP, destP, flags = 0) { const fallback = async (sourceFs, sourceP2, destFs, destP2) => { if ((flags & fs.constants.COPYFILE_FICLONE_FORCE) !== 0) - throw Object.assign(new Error(`EXDEV: cross-device clone not permitted, copyfile '${sourceP2}' -> ${destP2}'`), {code: `EXDEV`}); + throw Object.assign(new Error(`EXDEV: cross-device clone not permitted, copyfile '${sourceP2}' -> ${destP2}'`), { code: `EXDEV` }); if (flags & fs.constants.COPYFILE_EXCL && await this.existsPromise(sourceP2)) - throw Object.assign(new Error(`EEXIST: file already exists, copyfile '${sourceP2}' -> '${destP2}'`), {code: `EEXIST`}); + throw Object.assign(new Error(`EEXIST: file already exists, copyfile '${sourceP2}' -> '${destP2}'`), { code: `EEXIST` }); let content; try { content = await sourceFs.readFilePromise(sourceP2); } catch (error) { - throw Object.assign(new Error(`EINVAL: invalid argument, copyfile '${sourceP2}' -> '${destP2}'`), {code: `EINVAL`}); + throw Object.assign(new Error(`EINVAL: invalid argument, copyfile '${sourceP2}' -> '${destP2}'`), { code: `EINVAL` }); } await destFs.writeFilePromise(destP2, content); }; return await this.makeCallPromise(sourceP, async () => { return await this.makeCallPromise(destP, async () => { return await this.baseFs.copyFilePromise(sourceP, destP, flags); - }, async (zipFsD, {subPath: subPathD}) => { + }, async (zipFsD, { subPath: subPathD }) => { return await fallback(this.baseFs, sourceP, zipFsD, subPathD); }); - }, async (zipFsS, {subPath: subPathS}) => { + }, async (zipFsS, { subPath: subPathS }) => { return await this.makeCallPromise(destP, async () => { return await fallback(zipFsS, subPathS, this.baseFs, destP); - }, async (zipFsD, {subPath: subPathD}) => { + }, async (zipFsD, { subPath: subPathD }) => { if (zipFsS !== zipFsD) { return await fallback(zipFsS, subPathS, zipFsD, subPathD); } else { @@ -22256,27 +22258,27 @@ class ZipOpenFS extends BasePortableFakeFS { copyFileSync(sourceP, destP, flags = 0) { const fallback = (sourceFs, sourceP2, destFs, destP2) => { if ((flags & fs.constants.COPYFILE_FICLONE_FORCE) !== 0) - throw Object.assign(new Error(`EXDEV: cross-device clone not permitted, copyfile '${sourceP2}' -> ${destP2}'`), {code: `EXDEV`}); + throw Object.assign(new Error(`EXDEV: cross-device clone not permitted, copyfile '${sourceP2}' -> ${destP2}'`), { code: `EXDEV` }); if (flags & fs.constants.COPYFILE_EXCL && this.existsSync(sourceP2)) - throw Object.assign(new Error(`EEXIST: file already exists, copyfile '${sourceP2}' -> '${destP2}'`), {code: `EEXIST`}); + throw Object.assign(new Error(`EEXIST: file already exists, copyfile '${sourceP2}' -> '${destP2}'`), { code: `EEXIST` }); let content; try { content = sourceFs.readFileSync(sourceP2); } catch (error) { - throw Object.assign(new Error(`EINVAL: invalid argument, copyfile '${sourceP2}' -> '${destP2}'`), {code: `EINVAL`}); + throw Object.assign(new Error(`EINVAL: invalid argument, copyfile '${sourceP2}' -> '${destP2}'`), { code: `EINVAL` }); } destFs.writeFileSync(destP2, content); }; return this.makeCallSync(sourceP, () => { return this.makeCallSync(destP, () => { return this.baseFs.copyFileSync(sourceP, destP, flags); - }, (zipFsD, {subPath: subPathD}) => { + }, (zipFsD, { subPath: subPathD }) => { return fallback(this.baseFs, sourceP, zipFsD, subPathD); }); - }, (zipFsS, {subPath: subPathS}) => { + }, (zipFsS, { subPath: subPathS }) => { return this.makeCallSync(destP, () => { return fallback(zipFsS, subPathS, this.baseFs, destP); - }, (zipFsD, {subPath: subPathD}) => { + }, (zipFsD, { subPath: subPathD }) => { if (zipFsS !== zipFsD) { return fallback(zipFsS, subPathS, zipFsD, subPathD); } else { @@ -22288,112 +22290,112 @@ class ZipOpenFS extends BasePortableFakeFS { async appendFilePromise(p, content, opts) { return await this.makeCallPromise(p, async () => { return await this.baseFs.appendFilePromise(p, content, opts); - }, async (zipFs, {subPath}) => { + }, async (zipFs, { subPath }) => { return await zipFs.appendFilePromise(subPath, content, opts); }); } appendFileSync(p, content, opts) { return this.makeCallSync(p, () => { return this.baseFs.appendFileSync(p, content, opts); - }, (zipFs, {subPath}) => { + }, (zipFs, { subPath }) => { return zipFs.appendFileSync(subPath, content, opts); }); } async writeFilePromise(p, content, opts) { return await this.makeCallPromise(p, async () => { return await this.baseFs.writeFilePromise(p, content, opts); - }, async (zipFs, {subPath}) => { + }, async (zipFs, { subPath }) => { return await zipFs.writeFilePromise(subPath, content, opts); }); } writeFileSync(p, content, opts) { return this.makeCallSync(p, () => { return this.baseFs.writeFileSync(p, content, opts); - }, (zipFs, {subPath}) => { + }, (zipFs, { subPath }) => { return zipFs.writeFileSync(subPath, content, opts); }); } async unlinkPromise(p) { return await this.makeCallPromise(p, async () => { return await this.baseFs.unlinkPromise(p); - }, async (zipFs, {subPath}) => { + }, async (zipFs, { subPath }) => { return await zipFs.unlinkPromise(subPath); }); } unlinkSync(p) { return this.makeCallSync(p, () => { return this.baseFs.unlinkSync(p); - }, (zipFs, {subPath}) => { + }, (zipFs, { subPath }) => { return zipFs.unlinkSync(subPath); }); } async utimesPromise(p, atime, mtime) { return await this.makeCallPromise(p, async () => { return await this.baseFs.utimesPromise(p, atime, mtime); - }, async (zipFs, {subPath}) => { + }, async (zipFs, { subPath }) => { return await zipFs.utimesPromise(subPath, atime, mtime); }); } utimesSync(p, atime, mtime) { return this.makeCallSync(p, () => { return this.baseFs.utimesSync(p, atime, mtime); - }, (zipFs, {subPath}) => { + }, (zipFs, { subPath }) => { return zipFs.utimesSync(subPath, atime, mtime); }); } async mkdirPromise(p, opts) { return await this.makeCallPromise(p, async () => { return await this.baseFs.mkdirPromise(p, opts); - }, async (zipFs, {subPath}) => { + }, async (zipFs, { subPath }) => { return await zipFs.mkdirPromise(subPath, opts); }); } mkdirSync(p, opts) { return this.makeCallSync(p, () => { return this.baseFs.mkdirSync(p, opts); - }, (zipFs, {subPath}) => { + }, (zipFs, { subPath }) => { return zipFs.mkdirSync(subPath, opts); }); } async rmdirPromise(p, opts) { return await this.makeCallPromise(p, async () => { return await this.baseFs.rmdirPromise(p, opts); - }, async (zipFs, {subPath}) => { + }, async (zipFs, { subPath }) => { return await zipFs.rmdirPromise(subPath, opts); }); } rmdirSync(p, opts) { return this.makeCallSync(p, () => { return this.baseFs.rmdirSync(p, opts); - }, (zipFs, {subPath}) => { + }, (zipFs, { subPath }) => { return zipFs.rmdirSync(subPath, opts); }); } async linkPromise(existingP, newP) { return await this.makeCallPromise(newP, async () => { return await this.baseFs.linkPromise(existingP, newP); - }, async (zipFs, {subPath}) => { + }, async (zipFs, { subPath }) => { return await zipFs.linkPromise(existingP, subPath); }); } linkSync(existingP, newP) { return this.makeCallSync(newP, () => { return this.baseFs.linkSync(existingP, newP); - }, (zipFs, {subPath}) => { + }, (zipFs, { subPath }) => { return zipFs.linkSync(existingP, subPath); }); } async symlinkPromise(target, p, type) { return await this.makeCallPromise(p, async () => { return await this.baseFs.symlinkPromise(target, p, type); - }, async (zipFs, {subPath}) => { + }, async (zipFs, { subPath }) => { return await zipFs.symlinkPromise(target, subPath); }); } symlinkSync(target, p, type) { return this.makeCallSync(p, () => { return this.baseFs.symlinkSync(target, p, type); - }, (zipFs, {subPath}) => { + }, (zipFs, { subPath }) => { return zipFs.symlinkSync(target, subPath); }); } @@ -22405,7 +22407,7 @@ class ZipOpenFS extends BasePortableFakeFS { default: return await this.baseFs.readFilePromise(p, encoding); } - }, async (zipFs, {subPath}) => { + }, async (zipFs, { subPath }) => { return await zipFs.readFilePromise(subPath, encoding); }); } @@ -22417,14 +22419,14 @@ class ZipOpenFS extends BasePortableFakeFS { default: return this.baseFs.readFileSync(p, encoding); } - }, (zipFs, {subPath}) => { + }, (zipFs, { subPath }) => { return zipFs.readFileSync(subPath, encoding); }); } async readdirPromise(p, opts) { return await this.makeCallPromise(p, async () => { return await this.baseFs.readdirPromise(p, opts); - }, async (zipFs, {subPath}) => { + }, async (zipFs, { subPath }) => { return await zipFs.readdirPromise(subPath, opts); }, { requireSubpath: false @@ -22433,7 +22435,7 @@ class ZipOpenFS extends BasePortableFakeFS { readdirSync(p, opts) { return this.makeCallSync(p, () => { return this.baseFs.readdirSync(p, opts); - }, (zipFs, {subPath}) => { + }, (zipFs, { subPath }) => { return zipFs.readdirSync(subPath, opts); }, { requireSubpath: false @@ -22442,33 +22444,33 @@ class ZipOpenFS extends BasePortableFakeFS { async readlinkPromise(p) { return await this.makeCallPromise(p, async () => { return await this.baseFs.readlinkPromise(p); - }, async (zipFs, {subPath}) => { + }, async (zipFs, { subPath }) => { return await zipFs.readlinkPromise(subPath); }); } readlinkSync(p) { return this.makeCallSync(p, () => { return this.baseFs.readlinkSync(p); - }, (zipFs, {subPath}) => { + }, (zipFs, { subPath }) => { return zipFs.readlinkSync(subPath); }); } async truncatePromise(p, len) { return await this.makeCallPromise(p, async () => { return await this.baseFs.truncatePromise(p, len); - }, async (zipFs, {subPath}) => { + }, async (zipFs, { subPath }) => { return await zipFs.truncatePromise(subPath, len); }); } truncateSync(p, len) { return this.makeCallSync(p, () => { return this.baseFs.truncateSync(p, len); - }, (zipFs, {subPath}) => { + }, (zipFs, { subPath }) => { return zipFs.truncateSync(subPath, len); }); } async ftruncatePromise(fd, len) { - if ((fd & ZIP_FD) === 0) + if ((fd & ZIP_MASK) !== ZIP_MAGIC) return this.baseFs.ftruncatePromise(fd, len); const entry = this.fdMap.get(fd); if (typeof entry === `undefined`) @@ -22477,7 +22479,7 @@ class ZipOpenFS extends BasePortableFakeFS { return zipFs.ftruncatePromise(realFd, len); } ftruncateSync(fd, len) { - if ((fd & ZIP_FD) === 0) + if ((fd & ZIP_MASK) !== ZIP_MAGIC) return this.baseFs.ftruncateSync(fd, len); const entry = this.fdMap.get(fd); if (typeof entry === `undefined`) @@ -22487,14 +22489,26 @@ class ZipOpenFS extends BasePortableFakeFS { } watch(p, a, b) { return this.makeCallSync(p, () => { - return this.baseFs.watch(p, a, b); - }, (zipFs, {subPath}) => { - return zipFs.watch(subPath, a, b); + return this.baseFs.watch( + p, + a, + b + ); + }, (zipFs, { subPath }) => { + return zipFs.watch( + subPath, + a, + b + ); }); } watchFile(p, a, b) { return this.makeCallSync(p, () => { - return this.baseFs.watchFile(p, a, b); + return this.baseFs.watchFile( + p, + a, + b + ); }, () => { return watchFile(this, p, a, b); }); @@ -22506,7 +22520,7 @@ class ZipOpenFS extends BasePortableFakeFS { return unwatchFile(this, p, cb); }); } - async makeCallPromise(p, discard, accept, {requireSubpath = true} = {}) { + async makeCallPromise(p, discard, accept, { requireSubpath = true } = {}) { if (typeof p !== `string`) return await discard(); const normalizedP = this.resolve(p); @@ -22517,7 +22531,7 @@ class ZipOpenFS extends BasePortableFakeFS { return await discard(); return await this.getZipPromise(zipInfo.archivePath, async (zipFs) => await accept(zipFs, zipInfo)); } - makeCallSync(p, discard, accept, {requireSubpath = true} = {}) { + makeCallSync(p, discard, accept, { requireSubpath = true } = {}) { if (typeof p !== `string`) return discard(); const normalizedP = this.resolve(p); @@ -22573,7 +22587,7 @@ class ZipOpenFS extends BasePortableFakeFS { const now = Date.now(); let nextExpiresAt = now + this.maxAge; let closeCount = max === null ? 0 : this.zipInstances.size - max; - for (const [path, {zipFs, expiresAt, refCount}] of this.zipInstances.entries()) { + for (const [path, { zipFs, expiresAt, refCount }] of this.zipInstances.entries()) { if (refCount !== 0 || zipFs.hasOpenFileHandles()) { continue; } else if (now >= expiresAt) { @@ -22667,7 +22681,7 @@ class ZipOpenFS extends BasePortableFakeFS { } } -class URLFS extends ProxiedFS { +class NodePathFS extends ProxiedFS { constructor(baseFs) { super(npath); this.baseFs = baseFs; @@ -22676,31 +22690,20 @@ class URLFS extends ProxiedFS { return path; } mapToBase(path) { + if (typeof path === `string`) + return path; if (path instanceof url.URL) return url.fileURLToPath(path); - return path; + if (Buffer.isBuffer(path)) { + const str = path.toString(); + if (Buffer.byteLength(str) !== path.byteLength) + throw new Error(`Non-utf8 buffers are not supported at the moment. Please upvote the following issue if you encounter this error: https://github.com/yarnpkg/berry/issues/4942`); + return str; + } + throw new Error(`Unsupported path type: ${nodeUtils.inspect(path)}`); } } -var __defProp$3 = Object.defineProperty; -var __defProps$2 = Object.defineProperties; -var __getOwnPropDescs$2 = Object.getOwnPropertyDescriptors; -var __getOwnPropSymbols$4 = Object.getOwnPropertySymbols; -var __hasOwnProp$4 = Object.prototype.hasOwnProperty; -var __propIsEnum$4 = Object.prototype.propertyIsEnumerable; -var __defNormalProp$3 = (obj, key, value) => key in obj ? __defProp$3(obj, key, {enumerable: true, configurable: true, writable: true, value}) : obj[key] = value; -var __spreadValues$3 = (a, b) => { - for (var prop in b || (b = {})) - if (__hasOwnProp$4.call(b, prop)) - __defNormalProp$3(a, prop, b[prop]); - if (__getOwnPropSymbols$4) - for (var prop of __getOwnPropSymbols$4(b)) { - if (__propIsEnum$4.call(b, prop)) - __defNormalProp$3(a, prop, b[prop]); - } - return a; -}; -var __spreadProps$2 = (a, b) => __defProps$2(a, __getOwnPropDescs$2(b)); var _a, _b, _c, _d; const kBaseFs = Symbol(`kBaseFs`); const kFd = Symbol(`kFd`); @@ -22727,13 +22730,18 @@ class FileHandle { try { this[kRef](this.appendFile); const encoding = (_a2 = typeof options === `string` ? options : options == null ? void 0 : options.encoding) != null ? _a2 : void 0; - return await this[kBaseFs].appendFilePromise(this.fd, data, encoding ? {encoding} : void 0); + return await this[kBaseFs].appendFilePromise(this.fd, data, encoding ? { encoding } : void 0); } finally { this[kUnref](); } } - chown(uid, gid) { - throw new Error(`Method not implemented.`); + async chown(uid, gid) { + try { + this[kRef](this.chown); + return await this[kBaseFs].fchownPromise(this.fd, uid, gid); + } finally { + this[kUnref](); + } } async chmod(mode) { try { @@ -22744,10 +22752,10 @@ class FileHandle { } } createReadStream(options) { - return this[kBaseFs].createReadStream(null, __spreadProps$2(__spreadValues$3({}, options), {fd: this.fd})); + return this[kBaseFs].createReadStream(null, { ...options, fd: this.fd }); } createWriteStream(options) { - return this[kBaseFs].createWriteStream(null, __spreadProps$2(__spreadValues$3({}, options), {fd: this.fd})); + return this[kBaseFs].createWriteStream(null, { ...options, fd: this.fd }); } datasync() { throw new Error(`Method not implemented.`); @@ -22831,11 +22839,11 @@ class FileHandle { if (ArrayBuffer.isView(args[0])) { const [buffer, offset, length, position] = args; const bytesWritten = await this[kBaseFs].writePromise(this.fd, buffer, offset != null ? offset : void 0, length != null ? length : void 0, position != null ? position : void 0); - return {bytesWritten, buffer}; + return { bytesWritten, buffer }; } else { const [data, position, encoding] = args; const bytesWritten = await this[kBaseFs].writePromise(this.fd, data, position, encoding); - return {bytesWritten, buffer: data}; + return { bytesWritten, buffer: data }; } } finally { this[kUnref](); @@ -22911,7 +22919,7 @@ class FileHandle { } } -const SYNC_IMPLEMENTATIONS = new Set([ +const SYNC_IMPLEMENTATIONS = /* @__PURE__ */ new Set([ `accessSync`, `appendFileSync`, `createReadStream`, @@ -22919,6 +22927,7 @@ const SYNC_IMPLEMENTATIONS = new Set([ `chmodSync`, `fchmodSync`, `chownSync`, + `fchownSync`, `closeSync`, `copyFileSync`, `linkSync`, @@ -22947,11 +22956,12 @@ const SYNC_IMPLEMENTATIONS = new Set([ `writeFileSync`, `writeSync` ]); -const ASYNC_IMPLEMENTATIONS = new Set([ +const ASYNC_IMPLEMENTATIONS = /* @__PURE__ */ new Set([ `accessPromise`, `appendFilePromise`, `fchmodPromise`, `chmodPromise`, + `fchownPromise`, `chownPromise`, `closePromise`, `copyFilePromise`, @@ -22979,7 +22989,7 @@ const ASYNC_IMPLEMENTATIONS = new Set([ `writeSync` ]); function patchFs(patchedFs, fakeFs) { - fakeFs = new URLFS(fakeFs); + fakeFs = new NodePathFS(fakeFs); const setupFn = (target, name, replacement) => { const orig = target[name]; target[name] = replacement; @@ -23071,7 +23081,7 @@ function patchFs(patchedFs, fakeFs) { let [fd, buffer, offset, length, position] = args; if (args.length <= 3) { const options = args[2] || {}; - ({offset = 0, length = buffer.byteLength, position} = options); + ({ offset = 0, length = buffer.byteLength, position } = options); } if (offset == null) offset = 0; @@ -23130,11 +23140,11 @@ function patchFs(patchedFs, fakeFs) { { patchedFs.read[nodeUtils.promisify.custom] = async (fd, buffer, ...args) => { const res = fakeFs.readPromise(fd, buffer, ...args); - return {bytesRead: await res, buffer}; + return { bytesRead: await res, buffer }; }; patchedFs.write[nodeUtils.promisify.custom] = async (fd, buffer, ...args) => { const res = fakeFs.writePromise(fd, buffer, ...args); - return {bytesWritten: await res, buffer}; + return { bytesWritten: await res, buffer }; }; } } @@ -23264,7 +23274,10 @@ var createModule = function() { } function getCFunc(ident) { var func = Module["_" + ident]; - assert(func, "Cannot call unknown function " + ident + ", make sure it is exported"); + assert( + func, + "Cannot call unknown function " + ident + ", make sure it is exported" + ); return func; } function ccall(ident, returnType, argTypes, args, opts) { @@ -23563,14 +23576,16 @@ var createModule = function() { var str = e.toString(); err("failed to compile wasm module: " + str); if (str.includes("imported Memory") || str.includes("memory import")) { - err("Memory size incompatibility issues may be due to changing INITIAL_MEMORY at runtime to something too large. Use ALLOW_MEMORY_GROWTH to allow any size memory (and also make sure not to set INITIAL_MEMORY at runtime to something smaller than it was at compile time)."); + err( + "Memory size incompatibility issues may be due to changing INITIAL_MEMORY at runtime to something too large. Use ALLOW_MEMORY_GROWTH to allow any size memory (and also make sure not to set INITIAL_MEMORY at runtime to something smaller than it was at compile time)." + ); } throw e; } return [instance, module2]; } function createWasm() { - var info = {a: asmLibraryArg}; + var info = { a: asmLibraryArg }; function receiveInstance(instance, module2) { var exports3 = instance.exports; Module["asm"] = exports3; @@ -23665,9 +23680,12 @@ var createModule = function() { }, normalize: function(path) { var isAbsolute = path.charAt(0) === "/", trailingSlash = path.substr(-1) === "/"; - path = PATH.normalizeArray(path.split("/").filter(function(p) { - return !!p; - }), !isAbsolute).join("/"); + path = PATH.normalizeArray( + path.split("/").filter(function(p) { + return !!p; + }), + !isAbsolute + ).join("/"); if (!path && !isAbsolute) { path = "."; } @@ -23734,9 +23752,12 @@ var createModule = function() { resolvedPath = path + "/" + resolvedPath; resolvedAbsolute = path.charAt(0) === "/"; } - resolvedPath = PATH.normalizeArray(resolvedPath.split("/").filter(function(p) { - return !!p; - }), !resolvedAbsolute).join("/"); + resolvedPath = PATH.normalizeArray( + resolvedPath.split("/").filter(function(p) { + return !!p; + }), + !resolvedAbsolute + ).join("/"); return (resolvedAbsolute ? "/" : "") + resolvedPath || "."; }, relative: function(from, to) { @@ -23782,7 +23803,7 @@ var createModule = function() { shutdown: function() { }, register: function(dev, ops) { - TTY.ttys[dev] = {input: [], output: [], ops}; + TTY.ttys[dev] = { input: [], output: [], ops }; FS.registerDevice(dev, TTY.stream_ops); }, stream_ops: { @@ -23851,7 +23872,13 @@ var createModule = function() { var buf = Buffer.alloc ? Buffer.alloc(BUFSIZE) : new Buffer(BUFSIZE); var bytesRead = 0; try { - bytesRead = nodeFS.readSync(process.stdin.fd, buf, 0, BUFSIZE, null); + bytesRead = nodeFS.readSync( + process.stdin.fd, + buf, + 0, + BUFSIZE, + null + ); } catch (e) { if (e.toString().includes("EOF")) bytesRead = 0; @@ -23935,7 +23962,7 @@ var createModule = function() { readdir: MEMFS.node_ops.readdir, symlink: MEMFS.node_ops.symlink }, - stream: {llseek: MEMFS.stream_ops.llseek} + stream: { llseek: MEMFS.stream_ops.llseek } }, file: { node: { @@ -24004,7 +24031,10 @@ var createModule = function() { if (prevCapacity >= newCapacity) return; var CAPACITY_DOUBLING_MAX = 1024 * 1024; - newCapacity = Math.max(newCapacity, prevCapacity * (prevCapacity < CAPACITY_DOUBLING_MAX ? 2 : 1.125) >>> 0); + newCapacity = Math.max( + newCapacity, + prevCapacity * (prevCapacity < CAPACITY_DOUBLING_MAX ? 2 : 1.125) >>> 0 + ); if (prevCapacity != 0) newCapacity = Math.max(newCapacity, 256); var oldContents = node.contents; @@ -24022,7 +24052,9 @@ var createModule = function() { var oldContents = node.contents; node.contents = new Uint8Array(newSize); if (oldContents) { - node.contents.set(oldContents.subarray(0, Math.min(newSize, node.usedBytes))); + node.contents.set( + oldContents.subarray(0, Math.min(newSize, node.usedBytes)) + ); } node.usedBytes = newSize; } @@ -24156,13 +24188,19 @@ var createModule = function() { node.usedBytes = length; return length; } else if (position + length <= node.usedBytes) { - node.contents.set(buffer2.subarray(offset, offset + length), position); + node.contents.set( + buffer2.subarray(offset, offset + length), + position + ); return length; } } MEMFS.expandFileStorage(node, position + length); if (node.contents.subarray && buffer2.subarray) { - node.contents.set(buffer2.subarray(offset, offset + length), position); + node.contents.set( + buffer2.subarray(offset, offset + length), + position + ); } else { for (var i = 0; i < length; i++) { node.contents[position + i] = buffer2[offset + i]; @@ -24187,7 +24225,10 @@ var createModule = function() { }, allocate: function(stream, offset, length) { MEMFS.expandFileStorage(stream.node, offset + length); - stream.node.usedBytes = Math.max(stream.node.usedBytes, offset + length); + stream.node.usedBytes = Math.max( + stream.node.usedBytes, + offset + length + ); }, mmap: function(stream, address, length, position, prot, flags) { if (address !== 0) { @@ -24207,7 +24248,11 @@ var createModule = function() { if (contents.subarray) { contents = contents.subarray(position, position + length); } else { - contents = Array.prototype.slice.call(contents, position, position + length); + contents = Array.prototype.slice.call( + contents, + position, + position + length + ); } } allocated = true; @@ -24217,7 +24262,7 @@ var createModule = function() { } HEAP8.set(contents, ptr); } - return {ptr, allocated}; + return { ptr, allocated }; }, msync: function(stream, buffer2, offset, length, mmapFlags) { if (!FS.isFile(stream.node.mode)) { @@ -24226,7 +24271,14 @@ var createModule = function() { if (mmapFlags & 2) { return 0; } - MEMFS.stream_ops.write(stream, buffer2, 0, length, offset, false); + MEMFS.stream_ops.write( + stream, + buffer2, + 0, + length, + offset, + false + ); return 0; } } @@ -24358,7 +24410,7 @@ var createModule = function() { isWindows: false, staticInit: function() { NODEFS.isWindows = !!process.platform.match(/^win/); - var flags = {fs: fs.constants}; + var flags = { fs: fs.constants }; if (flags["fs"]) { flags = flags["fs"]; } @@ -24500,7 +24552,7 @@ var createModule = function() { if (FS.isDir(node.mode)) { fs.mkdirSync(path, node.mode); } else { - fs.writeFileSync(path, "", {mode: node.mode}); + fs.writeFileSync(path, "", { mode: node.mode }); } } catch (e) { if (!e.code) @@ -24565,7 +24617,10 @@ var createModule = function() { var path = NODEFS.realPath(node); try { path = fs.readlinkSync(path); - path = NODEJS_PATH.relative(NODEJS_PATH.resolve(node.mount.opts.root), path); + path = NODEJS_PATH.relative( + NODEJS_PATH.resolve(node.mount.opts.root), + path + ); return path; } catch (e) { if (!e.code) @@ -24602,14 +24657,26 @@ var createModule = function() { if (length === 0) return 0; try { - return fs.readSync(stream.nfd, NODEFS.bufferFrom(buffer2.buffer), offset, length, position); + return fs.readSync( + stream.nfd, + NODEFS.bufferFrom(buffer2.buffer), + offset, + length, + position + ); } catch (e) { throw new FS.ErrnoError(NODEFS.convertNodeCode(e)); } }, write: function(stream, buffer2, offset, length, position) { try { - return fs.writeSync(stream.nfd, NODEFS.bufferFrom(buffer2.buffer), offset, length, position); + return fs.writeSync( + stream.nfd, + NODEFS.bufferFrom(buffer2.buffer), + offset, + length, + position + ); } catch (e) { throw new FS.ErrnoError(NODEFS.convertNodeCode(e)); } @@ -24642,7 +24709,7 @@ var createModule = function() { } var ptr = mmapAlloc(length); NODEFS.stream_ops.read(stream, HEAP8, ptr, length, position); - return {ptr, allocated: true}; + return { ptr, allocated: true }; }, msync: function(stream, buffer2, offset, length, mmapFlags) { if (!FS.isFile(stream.node.mode)) { @@ -24651,14 +24718,21 @@ var createModule = function() { if (mmapFlags & 2) { return 0; } - NODEFS.stream_ops.write(stream, buffer2, 0, length, offset, false); + NODEFS.stream_ops.write( + stream, + buffer2, + 0, + length, + offset, + false + ); return 0; } } }; var NODERAWFS = { lookupPath: function(path) { - return {path, node: {mode: NODEFS.getMode(path)}}; + return { path, node: { mode: NODEFS.getMode(path) } }; }, createStandardStreams: function() { FS.streams[0] = { @@ -24692,7 +24766,7 @@ var createModule = function() { if (FS.isDir(path)) { fs.mkdirSync(path, mode); } else { - fs.writeFileSync(path, "", {mode}); + fs.writeFileSync(path, "", { mode }); } }, mkdir: function() { @@ -24794,7 +24868,13 @@ var createModule = function() { var seeking = typeof position !== "undefined"; if (!seeking && stream.seekable) position = stream.position; - var bytesRead = fs.readSync(stream.nfd, NODEFS.bufferFrom(buffer2.buffer), offset, length, position); + var bytesRead = fs.readSync( + stream.nfd, + NODEFS.bufferFrom(buffer2.buffer), + offset, + length, + position + ); if (!seeking) stream.position += bytesRead; return bytesRead; @@ -24809,7 +24889,13 @@ var createModule = function() { var seeking = typeof position !== "undefined"; if (!seeking && stream.seekable) position = stream.position; - var bytesWritten = fs.writeSync(stream.nfd, NODEFS.bufferFrom(buffer2.buffer), offset, length, position); + var bytesWritten = fs.writeSync( + stream.nfd, + NODEFS.bufferFrom(buffer2.buffer), + offset, + length, + position + ); if (!seeking) stream.position += bytesWritten; return bytesWritten; @@ -24826,7 +24912,7 @@ var createModule = function() { } var ptr = mmapAlloc(length); FS.read(stream, HEAP8, ptr, length, position); - return {ptr, allocated: true}; + return { ptr, allocated: true }; }, msync: function(stream, buffer2, offset, length, mmapFlags) { if (stream.stream_ops) { @@ -24856,7 +24942,7 @@ var createModule = function() { initialized: false, ignorePermissions: true, trackingDelegate: {}, - tracking: {openFlags: {READ: 1, WRITE: 2}}, + tracking: { openFlags: { READ: 1, WRITE: 2 } }, ErrnoError: null, genericErrors: {}, filesystems: null, @@ -24865,8 +24951,8 @@ var createModule = function() { path = PATH_FS.resolve(FS.cwd(), path); opts = opts || {}; if (!path) - return {path: "", node: null}; - var defaults = {follow_mount: true, recurse_count: 0}; + return { path: "", node: null }; + var defaults = { follow_mount: true, recurse_count: 0 }; for (var key2 in defaults) { if (opts[key2] === void 0) { opts[key2] = defaults[key2]; @@ -24875,9 +24961,12 @@ var createModule = function() { if (opts.recurse_count > 8) { throw new FS.ErrnoError(32); } - var parts = PATH.normalizeArray(path.split("/").filter(function(p) { - return !!p; - }), false); + var parts = PATH.normalizeArray( + path.split("/").filter(function(p) { + return !!p; + }), + false + ); var current = FS.root; var current_path = "/"; for (var i = 0; i < parts.length; i++) { @@ -24907,7 +24996,7 @@ var createModule = function() { } } } - return {path: current_path, node: current}; + return { path: current_path, node: current }; }, getPath: function(node) { var path; @@ -24998,7 +25087,7 @@ var createModule = function() { isSocket: function(mode) { return (mode & 49152) === 49152; }, - flagModes: {r: 0, "r+": 2, w: 577, "w+": 578, a: 1089, "a+": 1090}, + flagModes: { r: 0, "r+": 2, w: 577, "w+": 578, a: 1089, "a+": 1090 }, modeStringToFlags: function(str) { var flags = FS.flagModes[str]; if (typeof flags === "undefined") { @@ -25159,7 +25248,7 @@ var createModule = function() { return ma << 8 | mi; }, registerDevice: function(dev, ops) { - FS.devices[dev] = {stream_ops: ops}; + FS.devices[dev] = { stream_ops: ops }; }, getDevice: function(dev) { return FS.devices[dev]; @@ -25181,7 +25270,9 @@ var createModule = function() { } FS.syncFSRequests++; if (FS.syncFSRequests > 1) { - err("warning: " + FS.syncFSRequests + " FS.syncfs operations in flight at once, probably just doing extra work"); + err( + "warning: " + FS.syncFSRequests + " FS.syncfs operations in flight at once, probably just doing extra work" + ); } var mounts = FS.getMounts(FS.root.mount); var completed = 0; @@ -25215,7 +25306,7 @@ var createModule = function() { if (root && FS.root) { throw new FS.ErrnoError(10); } else if (!root && !pseudo) { - var lookup = FS.lookupPath(mountpoint, {follow_mount: false}); + var lookup = FS.lookupPath(mountpoint, { follow_mount: false }); mountpoint = lookup.path; node = lookup.node; if (FS.isMountpoint(node)) { @@ -25245,7 +25336,7 @@ var createModule = function() { return mountRoot; }, unmount: function(mountpoint) { - var lookup = FS.lookupPath(mountpoint, {follow_mount: false}); + var lookup = FS.lookupPath(mountpoint, { follow_mount: false }); if (!FS.isMountpoint(lookup.node)) { throw new FS.ErrnoError(28); } @@ -25270,7 +25361,7 @@ var createModule = function() { return parent.node_ops.lookup(parent, name); }, mknod: function(path, mode, dev) { - var lookup = FS.lookupPath(path, {parent: true}); + var lookup = FS.lookupPath(path, { parent: true }); var parent = lookup.node; var name = PATH.basename(path); if (!name || name === "." || name === "..") { @@ -25324,7 +25415,7 @@ var createModule = function() { if (!PATH_FS.resolve(oldpath)) { throw new FS.ErrnoError(44); } - var lookup = FS.lookupPath(newpath, {parent: true}); + var lookup = FS.lookupPath(newpath, { parent: true }); var parent = lookup.node; if (!parent) { throw new FS.ErrnoError(44); @@ -25345,9 +25436,9 @@ var createModule = function() { var old_name = PATH.basename(old_path); var new_name = PATH.basename(new_path); var lookup, old_dir, new_dir; - lookup = FS.lookupPath(old_path, {parent: true}); + lookup = FS.lookupPath(old_path, { parent: true }); old_dir = lookup.node; - lookup = FS.lookupPath(new_path, {parent: true}); + lookup = FS.lookupPath(new_path, { parent: true }); new_dir = lookup.node; if (!old_dir || !new_dir) throw new FS.ErrnoError(44); @@ -25397,7 +25488,9 @@ var createModule = function() { FS.trackingDelegate["willMovePath"](old_path, new_path); } } catch (e) { - err("FS.trackingDelegate['willMovePath']('" + old_path + "', '" + new_path + "') threw an exception: " + e.message); + err( + "FS.trackingDelegate['willMovePath']('" + old_path + "', '" + new_path + "') threw an exception: " + e.message + ); } FS.hashRemoveNode(old_node); try { @@ -25411,11 +25504,13 @@ var createModule = function() { if (FS.trackingDelegate["onMovePath"]) FS.trackingDelegate["onMovePath"](old_path, new_path); } catch (e) { - err("FS.trackingDelegate['onMovePath']('" + old_path + "', '" + new_path + "') threw an exception: " + e.message); + err( + "FS.trackingDelegate['onMovePath']('" + old_path + "', '" + new_path + "') threw an exception: " + e.message + ); } }, rmdir: function(path) { - var lookup = FS.lookupPath(path, {parent: true}); + var lookup = FS.lookupPath(path, { parent: true }); var parent = lookup.node; var name = PATH.basename(path); var node = FS.lookupNode(parent, name); @@ -25434,7 +25529,9 @@ var createModule = function() { FS.trackingDelegate["willDeletePath"](path); } } catch (e) { - err("FS.trackingDelegate['willDeletePath']('" + path + "') threw an exception: " + e.message); + err( + "FS.trackingDelegate['willDeletePath']('" + path + "') threw an exception: " + e.message + ); } parent.node_ops.rmdir(parent, name); FS.destroyNode(node); @@ -25442,11 +25539,13 @@ var createModule = function() { if (FS.trackingDelegate["onDeletePath"]) FS.trackingDelegate["onDeletePath"](path); } catch (e) { - err("FS.trackingDelegate['onDeletePath']('" + path + "') threw an exception: " + e.message); + err( + "FS.trackingDelegate['onDeletePath']('" + path + "') threw an exception: " + e.message + ); } }, readdir: function(path) { - var lookup = FS.lookupPath(path, {follow: true}); + var lookup = FS.lookupPath(path, { follow: true }); var node = lookup.node; if (!node.node_ops.readdir) { throw new FS.ErrnoError(54); @@ -25454,7 +25553,7 @@ var createModule = function() { return node.node_ops.readdir(node); }, unlink: function(path) { - var lookup = FS.lookupPath(path, {parent: true}); + var lookup = FS.lookupPath(path, { parent: true }); var parent = lookup.node; var name = PATH.basename(path); var node = FS.lookupNode(parent, name); @@ -25473,7 +25572,9 @@ var createModule = function() { FS.trackingDelegate["willDeletePath"](path); } } catch (e) { - err("FS.trackingDelegate['willDeletePath']('" + path + "') threw an exception: " + e.message); + err( + "FS.trackingDelegate['willDeletePath']('" + path + "') threw an exception: " + e.message + ); } parent.node_ops.unlink(parent, name); FS.destroyNode(node); @@ -25481,7 +25582,9 @@ var createModule = function() { if (FS.trackingDelegate["onDeletePath"]) FS.trackingDelegate["onDeletePath"](path); } catch (e) { - err("FS.trackingDelegate['onDeletePath']('" + path + "') threw an exception: " + e.message); + err( + "FS.trackingDelegate['onDeletePath']('" + path + "') threw an exception: " + e.message + ); } }, readlink: function(path) { @@ -25493,10 +25596,13 @@ var createModule = function() { if (!link.node_ops.readlink) { throw new FS.ErrnoError(28); } - return PATH_FS.resolve(FS.getPath(link.parent), link.node_ops.readlink(link)); + return PATH_FS.resolve( + FS.getPath(link.parent), + link.node_ops.readlink(link) + ); }, stat: function(path, dontFollow) { - var lookup = FS.lookupPath(path, {follow: !dontFollow}); + var lookup = FS.lookupPath(path, { follow: !dontFollow }); var node = lookup.node; if (!node) { throw new FS.ErrnoError(44); @@ -25512,7 +25618,7 @@ var createModule = function() { chmod: function(path, mode, dontFollow) { var node; if (typeof path === "string") { - var lookup = FS.lookupPath(path, {follow: !dontFollow}); + var lookup = FS.lookupPath(path, { follow: !dontFollow }); node = lookup.node; } else { node = path; @@ -25538,7 +25644,7 @@ var createModule = function() { chown: function(path, uid, gid, dontFollow) { var node; if (typeof path === "string") { - var lookup = FS.lookupPath(path, {follow: !dontFollow}); + var lookup = FS.lookupPath(path, { follow: !dontFollow }); node = lookup.node; } else { node = path; @@ -25546,7 +25652,7 @@ var createModule = function() { if (!node.node_ops.setattr) { throw new FS.ErrnoError(63); } - node.node_ops.setattr(node, {timestamp: Date.now()}); + node.node_ops.setattr(node, { timestamp: Date.now() }); }, lchown: function(path, uid, gid) { FS.chown(path, uid, gid, true); @@ -25564,7 +25670,7 @@ var createModule = function() { } var node; if (typeof path === "string") { - var lookup = FS.lookupPath(path, {follow: true}); + var lookup = FS.lookupPath(path, { follow: true }); node = lookup.node; } else { node = path; @@ -25582,7 +25688,7 @@ var createModule = function() { if (errCode) { throw new FS.ErrnoError(errCode); } - node.node_ops.setattr(node, {size: len, timestamp: Date.now()}); + node.node_ops.setattr(node, { size: len, timestamp: Date.now() }); }, ftruncate: function(fd, len) { var stream = FS.getStream(fd); @@ -25595,9 +25701,9 @@ var createModule = function() { FS.truncate(stream.node, len); }, utime: function(path, atime, mtime) { - var lookup = FS.lookupPath(path, {follow: true}); + var lookup = FS.lookupPath(path, { follow: true }); var node = lookup.node; - node.node_ops.setattr(node, {timestamp: Math.max(atime, mtime)}); + node.node_ops.setattr(node, { timestamp: Math.max(atime, mtime) }); }, open: function(path, flags, mode, fd_start, fd_end) { if (path === "") { @@ -25616,7 +25722,7 @@ var createModule = function() { } else { path = PATH.normalize(path); try { - var lookup = FS.lookupPath(path, {follow: !(flags & 131072)}); + var lookup = FS.lookupPath(path, { follow: !(flags & 131072) }); node = lookup.node; } catch (e) { } @@ -25651,16 +25757,20 @@ var createModule = function() { FS.truncate(node, 0); } flags &= ~(128 | 512 | 131072); - var stream = FS.createStream({ - node, - path: FS.getPath(node), - flags, - seekable: true, - position: 0, - stream_ops: node.stream_ops, - ungotten: [], - error: false - }, fd_start, fd_end); + var stream = FS.createStream( + { + node, + path: FS.getPath(node), + flags, + seekable: true, + position: 0, + stream_ops: node.stream_ops, + ungotten: [], + error: false + }, + fd_start, + fd_end + ); if (stream.stream_ops.open) { stream.stream_ops.open(stream); } @@ -25684,7 +25794,9 @@ var createModule = function() { FS.trackingDelegate["onOpenFile"](path, trackingFlags); } } catch (e) { - err("FS.trackingDelegate['onOpenFile']('" + path + "', flags) threw an exception: " + e.message); + err( + "FS.trackingDelegate['onOpenFile']('" + path + "', flags) threw an exception: " + e.message + ); } return stream; }, @@ -25744,7 +25856,13 @@ var createModule = function() { } else if (!stream.seekable) { throw new FS.ErrnoError(70); } - var bytesRead = stream.stream_ops.read(stream, buffer2, offset, length, position); + var bytesRead = stream.stream_ops.read( + stream, + buffer2, + offset, + length, + position + ); if (!seeking) stream.position += bytesRead; return bytesRead; @@ -25774,14 +25892,23 @@ var createModule = function() { } else if (!stream.seekable) { throw new FS.ErrnoError(70); } - var bytesWritten = stream.stream_ops.write(stream, buffer2, offset, length, position, canOwn); + var bytesWritten = stream.stream_ops.write( + stream, + buffer2, + offset, + length, + position, + canOwn + ); if (!seeking) stream.position += bytesWritten; try { if (stream.path && FS.trackingDelegate["onWriteToFile"]) FS.trackingDelegate["onWriteToFile"](stream.path); } catch (e) { - err("FS.trackingDelegate['onWriteToFile']('" + stream.path + "') threw an exception: " + e.message); + err( + "FS.trackingDelegate['onWriteToFile']('" + stream.path + "') threw an exception: " + e.message + ); } return bytesWritten; }, @@ -25813,13 +25940,26 @@ var createModule = function() { if (!stream.stream_ops.mmap) { throw new FS.ErrnoError(43); } - return stream.stream_ops.mmap(stream, address, length, position, prot, flags); + return stream.stream_ops.mmap( + stream, + address, + length, + position, + prot, + flags + ); }, msync: function(stream, buffer2, offset, length, mmapFlags) { if (!stream || !stream.stream_ops.msync) { return 0; } - return stream.stream_ops.msync(stream, buffer2, offset, length, mmapFlags); + return stream.stream_ops.msync( + stream, + buffer2, + offset, + length, + mmapFlags + ); }, munmap: function(stream) { return 0; @@ -25870,7 +26010,7 @@ var createModule = function() { return FS.currentPath; }, chdir: function(path) { - var lookup = FS.lookupPath(path, {follow: true}); + var lookup = FS.lookupPath(path, { follow: true }); if (lookup.node === null) { throw new FS.ErrnoError(44); } @@ -25913,31 +26053,35 @@ var createModule = function() { FS.mkdir("/proc"); var proc_self = FS.mkdir("/proc/self"); FS.mkdir("/proc/self/fd"); - FS.mount({ - mount: function() { - var node = FS.createNode(proc_self, "fd", 16384 | 511, 73); - node.node_ops = { - lookup: function(parent, name) { - var fd = +name; - var stream = FS.getStream(fd); - if (!stream) - throw new FS.ErrnoError(8); - var ret = { - parent: null, - mount: {mountpoint: "fake"}, - node_ops: { - readlink: function() { - return stream.path; + FS.mount( + { + mount: function() { + var node = FS.createNode(proc_self, "fd", 16384 | 511, 73); + node.node_ops = { + lookup: function(parent, name) { + var fd = +name; + var stream = FS.getStream(fd); + if (!stream) + throw new FS.ErrnoError(8); + var ret = { + parent: null, + mount: { mountpoint: "fake" }, + node_ops: { + readlink: function() { + return stream.path; + } } - } - }; - ret.parent = ret; - return ret; - } - }; - return node; - } - }, {}, "/proc/self/fd"); + }; + ret.parent = ret; + return ret; + } + }; + return node; + } + }, + {}, + "/proc/self/fd" + ); }, createStandardStreams: function() { if (Module["stdin"]) { @@ -25984,7 +26128,7 @@ var createModule = function() { FS.createDefaultDirectories(); FS.createDefaultDevices(); FS.createSpecialDirectories(); - FS.filesystems = {MEMFS, NODEFS}; + FS.filesystems = { MEMFS, NODEFS }; }, init: function(input, output, error) { FS.init.initialized = true; @@ -26025,7 +26169,7 @@ var createModule = function() { }, analyzePath: function(path, dontResolveLastLink) { try { - var lookup = FS.lookupPath(path, {follow: !dontResolveLastLink}); + var lookup = FS.lookupPath(path, { follow: !dontResolveLastLink }); path = lookup.path; } catch (e) { } @@ -26041,12 +26185,12 @@ var createModule = function() { parentObject: null }; try { - var lookup = FS.lookupPath(path, {parent: true}); + var lookup = FS.lookupPath(path, { parent: true }); ret.parentExists = true; ret.parentPath = lookup.path; ret.parentObject = lookup.node; ret.name = PATH.basename(path); - lookup = FS.lookupPath(path, {follow: !dontResolveLastLink}); + lookup = FS.lookupPath(path, { follow: !dontResolveLastLink }); ret.exists = true; ret.path = lookup.path; ret.object = lookup.node; @@ -26074,12 +26218,18 @@ var createModule = function() { return current; }, createFile: function(parent, name, properties, canRead, canWrite) { - var path = PATH.join2(typeof parent === "string" ? parent : FS.getPath(parent), name); + var path = PATH.join2( + typeof parent === "string" ? parent : FS.getPath(parent), + name + ); var mode = FS.getMode(canRead, canWrite); return FS.create(path, mode); }, createDataFile: function(parent, name, data, canRead, canWrite, canOwn) { - var path = name ? PATH.join2(typeof parent === "string" ? parent : FS.getPath(parent), name) : parent; + var path = name ? PATH.join2( + typeof parent === "string" ? parent : FS.getPath(parent), + name + ) : parent; var mode = FS.getMode(canRead, canWrite); var node = FS.create(path, mode); if (data) { @@ -26098,7 +26248,10 @@ var createModule = function() { return node; }, createDevice: function(parent, name, input, output) { - var path = PATH.join2(typeof parent === "string" ? parent : FS.getPath(parent), name); + var path = PATH.join2( + typeof parent === "string" ? parent : FS.getPath(parent), + name + ); var mode = FS.getMode(!!input, !!output); if (!FS.createDevice.major) FS.createDevice.major = 64; @@ -26166,7 +26319,7 @@ var createModule = function() { }, createLazyFile: function(parent, name, url, canRead, canWrite) { var properties; { - var properties = {isDevice: false, url}; + var properties = { isDevice: false, url }; } var node = FS.createFile(parent, name, properties, canRead, canWrite); if (properties.contents) { @@ -26219,7 +26372,14 @@ var createModule = function() { if (preFinish) preFinish(); if (!dontCreateFile) { - FS.createDataFile(parent, name, byteArray2, canRead, canWrite, canOwn); + FS.createDataFile( + parent, + name, + byteArray2, + canRead, + canWrite, + canOwn + ); } if (onload) onload(); @@ -26243,9 +26403,13 @@ var createModule = function() { } addRunDependency(); if (typeof url == "string") { - Browser.asyncLoad(url, function(byteArray) { - processData(byteArray); - }, onerror); + Browser.asyncLoad( + url, + function(byteArray) { + processData(byteArray); + }, + onerror + ); } else { processData(url); } @@ -26286,7 +26450,10 @@ var createModule = function() { onerror(); } paths.forEach(function(path) { - var putRequest = files.put(FS.analyzePath(path).object.contents, path); + var putRequest = files.put( + FS.analyzePath(path).object.contents, + path + ); putRequest.onsuccess = function putRequest_onsuccess() { ok++; if (ok + fail == total) @@ -26336,7 +26503,14 @@ var createModule = function() { if (FS.analyzePath(path).exists) { FS.unlink(path); } - FS.createDataFile(PATH.dirname(path), PATH.basename(path), getRequest.result, true, true, true); + FS.createDataFile( + PATH.dirname(path), + PATH.basename(path), + getRequest.result, + true, + true, + true + ); ok++; if (ok + fail == total) finish(); @@ -26397,7 +26571,9 @@ var createModule = function() { HEAP32[buf + 32 >> 2] = 0; tempI64 = [ stat.size >>> 0, - (tempDouble = stat.size, +Math.abs(tempDouble) >= 1 ? tempDouble > 0 ? (Math.min(+Math.floor(tempDouble / 4294967296), 4294967295) | 0) >>> 0 : ~~+Math.ceil((tempDouble - +(~~tempDouble >>> 0)) / 4294967296) >>> 0 : 0) + (tempDouble = stat.size, +Math.abs(tempDouble) >= 1 ? tempDouble > 0 ? (Math.min(+Math.floor(tempDouble / 4294967296), 4294967295) | 0) >>> 0 : ~~+Math.ceil( + (tempDouble - +(~~tempDouble >>> 0)) / 4294967296 + ) >>> 0 : 0) ], HEAP32[buf + 40 >> 2] = tempI64[0], HEAP32[buf + 44 >> 2] = tempI64[1]; HEAP32[buf + 48 >> 2] = 4096; HEAP32[buf + 52 >> 2] = stat.blocks; @@ -26409,7 +26585,9 @@ var createModule = function() { HEAP32[buf + 76 >> 2] = 0; tempI64 = [ stat.ino >>> 0, - (tempDouble = stat.ino, +Math.abs(tempDouble) >= 1 ? tempDouble > 0 ? (Math.min(+Math.floor(tempDouble / 4294967296), 4294967295) | 0) >>> 0 : ~~+Math.ceil((tempDouble - +(~~tempDouble >>> 0)) / 4294967296) >>> 0 : 0) + (tempDouble = stat.ino, +Math.abs(tempDouble) >= 1 ? tempDouble > 0 ? (Math.min(+Math.floor(tempDouble / 4294967296), 4294967295) | 0) >>> 0 : ~~+Math.ceil( + (tempDouble - +(~~tempDouble >>> 0)) / 4294967296 + ) >>> 0 : 0) ], HEAP32[buf + 80 >> 2] = tempI64[0], HEAP32[buf + 84 >> 2] = tempI64[1]; return 0; }, @@ -26453,7 +26631,7 @@ var createModule = function() { return -28; } var node; - var lookup = FS.lookupPath(path, {follow: true}); + var lookup = FS.lookupPath(path, { follow: true }); node = lookup.node; if (!node) { return -44; @@ -26729,8 +26907,14 @@ var createModule = function() { } for (var cutDown = 1; cutDown <= 4; cutDown *= 2) { var overGrownHeapSize = oldSize * (1 + 0.2 / cutDown); - overGrownHeapSize = Math.min(overGrownHeapSize, requestedSize + 100663296); - var newSize = Math.min(maxHeapSize, alignUp(Math.max(requestedSize, overGrownHeapSize), 65536)); + overGrownHeapSize = Math.min( + overGrownHeapSize, + requestedSize + 100663296 + ); + var newSize = Math.min( + maxHeapSize, + alignUp(Math.max(requestedSize, overGrownHeapSize), 65536) + ); var replacement = emscripten_realloc_buffer(newSize); if (replacement) { return true; @@ -26785,7 +26969,9 @@ var createModule = function() { FS.llseek(stream, offset, whence); tempI64 = [ stream.position >>> 0, - (tempDouble = stream.position, +Math.abs(tempDouble) >= 1 ? tempDouble > 0 ? (Math.min(+Math.floor(tempDouble / 4294967296), 4294967295) | 0) >>> 0 : ~~+Math.ceil((tempDouble - +(~~tempDouble >>> 0)) / 4294967296) >>> 0 : 0) + (tempDouble = stream.position, +Math.abs(tempDouble) >= 1 ? tempDouble > 0 ? (Math.min(+Math.floor(tempDouble / 4294967296), 4294967295) | 0) >>> 0 : ~~+Math.ceil( + (tempDouble - +(~~tempDouble >>> 0)) / 4294967296 + ) >>> 0 : 0) ], HEAP32[newOffset >> 2] = tempI64[0], HEAP32[newOffset + 4 >> 2] = tempI64[1]; if (stream.getdents && offset === 0 && whence === 0) stream.getdents = null; @@ -26847,7 +27033,15 @@ var createModule = function() { } function _timegm(tmPtr) { _tzset(); - var time = Date.UTC(HEAP32[tmPtr + 20 >> 2] + 1900, HEAP32[tmPtr + 16 >> 2], HEAP32[tmPtr + 12 >> 2], HEAP32[tmPtr + 8 >> 2], HEAP32[tmPtr + 4 >> 2], HEAP32[tmPtr >> 2], 0); + var time = Date.UTC( + HEAP32[tmPtr + 20 >> 2] + 1900, + HEAP32[tmPtr + 16 >> 2], + HEAP32[tmPtr + 12 >> 2], + HEAP32[tmPtr + 8 >> 2], + HEAP32[tmPtr + 4 >> 2], + HEAP32[tmPtr >> 2], + 0 + ); var date = new Date(time); HEAP32[tmPtr + 24 >> 2] = date.getUTCDay(); var start = Date.UTC(date.getUTCFullYear(), 0, 1, 0, 0, 0, 0); @@ -26925,7 +27119,12 @@ var createModule = function() { function intArrayFromString(stringy, dontAddNull, length) { var len = length > 0 ? length : lengthBytesUTF8(stringy) + 1; var u8array = new Array(len); - var numBytesWritten = stringToUTF8Array(stringy, u8array, 0, u8array.length); + var numBytesWritten = stringToUTF8Array( + stringy, + u8array, + 0, + u8array.length + ); if (dontAddNull) u8array.length = numBytesWritten; return u8array; @@ -26938,7 +27137,11 @@ var createModule = function() { } catch (_) { buf = new Buffer(s, "base64"); } - return new Uint8Array(buf["buffer"], buf["byteOffset"], buf["byteLength"]); + return new Uint8Array( + buf["buffer"], + buf["byteOffset"], + buf["byteLength"] + ); } } function tryParseAsDataURI(filename) { @@ -27091,8 +27294,7 @@ const number64 = [ `number`, `number` ]; -var Errors; -(function(Errors2) { +var Errors = /* @__PURE__ */ ((Errors2) => { Errors2[Errors2["ZIP_ER_OK"] = 0] = "ZIP_ER_OK"; Errors2[Errors2["ZIP_ER_MULTIDISK"] = 1] = "ZIP_ER_MULTIDISK"; Errors2[Errors2["ZIP_ER_RENAME"] = 2] = "ZIP_ER_RENAME"; @@ -27125,7 +27327,8 @@ var Errors; Errors2[Errors2["ZIP_ER_INUSE"] = 29] = "ZIP_ER_INUSE"; Errors2[Errors2["ZIP_ER_TELL"] = 30] = "ZIP_ER_TELL"; Errors2[Errors2["ZIP_ER_COMPRESSED_DATA"] = 31] = "ZIP_ER_COMPRESSED_DATA"; -})(Errors || (Errors = {})); + return Errors2; +})(Errors || {}); const makeInterface = (libzip) => ({ get HEAP8() { return libzip.HEAP8; @@ -27245,27 +27448,7 @@ function getLibzipSync() { return mod; } -var __defProp$2 = Object.defineProperty; -var __defProps$1 = Object.defineProperties; -var __getOwnPropDescs$1 = Object.getOwnPropertyDescriptors; -var __getOwnPropSymbols$3 = Object.getOwnPropertySymbols; -var __hasOwnProp$3 = Object.prototype.hasOwnProperty; -var __propIsEnum$3 = Object.prototype.propertyIsEnumerable; -var __defNormalProp$2 = (obj, key, value) => key in obj ? __defProp$2(obj, key, {enumerable: true, configurable: true, writable: true, value}) : obj[key] = value; -var __spreadValues$2 = (a, b) => { - for (var prop in b || (b = {})) - if (__hasOwnProp$3.call(b, prop)) - __defNormalProp$2(a, prop, b[prop]); - if (__getOwnPropSymbols$3) - for (var prop of __getOwnPropSymbols$3(b)) { - if (__propIsEnum$3.call(b, prop)) - __defNormalProp$2(a, prop, b[prop]); - } - return a; -}; -var __spreadProps$1 = (a, b) => __defProps$1(a, __getOwnPropDescs$1(b)); -var ErrorCode; -(function(ErrorCode2) { +var ErrorCode = /* @__PURE__ */ ((ErrorCode2) => { ErrorCode2["API_ERROR"] = `API_ERROR`; ErrorCode2["BUILTIN_NODE_RESOLUTION_FAILED"] = `BUILTIN_NODE_RESOLUTION_FAILED`; ErrorCode2["EXPORTS_RESOLUTION_FAILED"] = `EXPORTS_RESOLUTION_FAILED`; @@ -27275,13 +27458,14 @@ var ErrorCode; ErrorCode2["INTERNAL"] = `INTERNAL`; ErrorCode2["UNDECLARED_DEPENDENCY"] = `UNDECLARED_DEPENDENCY`; ErrorCode2["UNSUPPORTED"] = `UNSUPPORTED`; -})(ErrorCode || (ErrorCode = {})); -const MODULE_NOT_FOUND_ERRORS = new Set([ - ErrorCode.BUILTIN_NODE_RESOLUTION_FAILED, - ErrorCode.MISSING_DEPENDENCY, - ErrorCode.MISSING_PEER_DEPENDENCY, - ErrorCode.QUALIFIED_PATH_RESOLUTION_FAILED, - ErrorCode.UNDECLARED_DEPENDENCY + return ErrorCode2; +})(ErrorCode || {}); +const MODULE_NOT_FOUND_ERRORS = /* @__PURE__ */ new Set([ + "BUILTIN_NODE_RESOLUTION_FAILED" /* BUILTIN_NODE_RESOLUTION_FAILED */, + "MISSING_DEPENDENCY" /* MISSING_DEPENDENCY */, + "MISSING_PEER_DEPENDENCY" /* MISSING_PEER_DEPENDENCY */, + "QUALIFIED_PATH_RESOLUTION_FAILED" /* QUALIFIED_PATH_RESOLUTION_FAILED */, + "UNDECLARED_DEPENDENCY" /* UNDECLARED_DEPENDENCY */ ]); function makeError(pnpCode, message, data = {}, code) { code != null ? code : code = MODULE_NOT_FOUND_ERRORS.has(pnpCode) ? `MODULE_NOT_FOUND` : pnpCode; @@ -27291,15 +27475,18 @@ function makeError(pnpCode, message, data = {}, code) { enumerable: false }; return Object.defineProperties(new Error(message), { - code: __spreadProps$1(__spreadValues$2({}, propertySpec), { + code: { + ...propertySpec, value: code - }), - pnpCode: __spreadProps$1(__spreadValues$2({}, propertySpec), { + }, + pnpCode: { + ...propertySpec, value: pnpCode - }), - data: __spreadProps$1(__spreadValues$2({}, propertySpec), { + }, + data: { + ...propertySpec, value: data - }) + } }); } function getIssuerModule(parent) { @@ -27347,21 +27534,12 @@ Instead change the require of ${basename} in ${parentPath} to a dynamic import() return err; } -var __getOwnPropSymbols$2 = Object.getOwnPropertySymbols; -var __hasOwnProp$2 = Object.prototype.hasOwnProperty; -var __propIsEnum$2 = Object.prototype.propertyIsEnumerable; -var __objRest$1 = (source, exclude) => { - var target = {}; - for (var prop in source) - if (__hasOwnProp$2.call(source, prop) && exclude.indexOf(prop) < 0) - target[prop] = source[prop]; - if (source != null && __getOwnPropSymbols$2) - for (var prop of __getOwnPropSymbols$2(source)) { - if (exclude.indexOf(prop) < 0 && __propIsEnum$2.call(source, prop)) - target[prop] = source[prop]; - } - return target; -}; +const shouldReportRequiredModules = process.env.WATCH_REPORT_DEPENDENCIES; +function reportModuleToWatchMode(filename) { + if (shouldReportRequiredModules && process.send) { + process.send({ "watch:require": npath.fromPortablePath(VirtualFS.resolveVirtual(npath.toPortablePath(filename))) }); + } +} function applyPatch(pnpapi, opts) { const defaultCache = {}; let enableNativeHooks = true; @@ -27402,7 +27580,7 @@ function applyPatch(pnpapi, opts) { const modulePath = require$$0.Module._resolveFilename(request, parent, isMain); const isOwnedByRuntime = parentApi !== null ? parentApi.findPackageLocator(modulePath) !== null : false; const moduleApiPath = isOwnedByRuntime ? parentApiPath : opts.manager.findApiPathFor(npath.dirname(modulePath)); - const entry = moduleApiPath !== null ? opts.manager.getApiEntry(moduleApiPath) : {instance: null, cache: defaultCache}; + const entry = moduleApiPath !== null ? opts.manager.getApiEntry(moduleApiPath) : { instance: null, cache: defaultCache }; const cacheEntry = entry.cache[modulePath]; if (cacheEntry) { if (cacheEntry.loaded === false && cacheEntry.isLoading !== true) { @@ -27421,6 +27599,7 @@ function applyPatch(pnpapi, opts) { } const module = new require$$0.Module(modulePath, parent != null ? parent : void 0); module.pnpApiPath = moduleApiPath; + reportModuleToWatchMode(modulePath); entry.cache[modulePath] = module; if (isMain) { process.mainModule = module; @@ -27459,11 +27638,11 @@ function applyPatch(pnpapi, opts) { if (issuer !== null) { const path = npath.dirname(issuer.filename); const apiPath = opts.manager.getApiPathFromParent(issuer); - return [{apiPath, path, module}]; + return [{ apiPath, path, module }]; } else { const path = process.cwd(); const apiPath = (_a = opts.manager.findApiPathFor(npath.join(path, `[file]`))) != null ? _a : opts.manager.getApiPathFromParent(null); - return [{apiPath, path, module}]; + return [{ apiPath, path, module }]; } } function makeFakeParent(path) { @@ -27480,7 +27659,7 @@ function applyPatch(pnpapi, opts) { if (!enableNativeHooks) return originalModuleResolveFilename.call(require$$0.Module, request, parent, isMain, options); if (options && options.plugnplay === false) { - const _a = options, rest = __objRest$1(_a, ["plugnplay"]); + const { plugnplay, ...rest } = options; const forwardedOptions = Object.keys(rest).length > 0 ? rest : void 0; try { enableNativeHooks = false; @@ -27494,7 +27673,10 @@ function applyPatch(pnpapi, opts) { optionNames.delete(`paths`); optionNames.delete(`plugnplay`); if (optionNames.size > 0) { - throw makeError(ErrorCode.UNSUPPORTED, `Some options passed to require() aren't supported by PnP yet (${Array.from(optionNames).join(`, `)})`); + throw makeError( + ErrorCode.UNSUPPORTED, + `Some options passed to require() aren't supported by PnP yet (${Array.from(optionNames).join(`, `)})` + ); } } const issuerSpecs = options && options.paths ? getIssuerSpecsFromPaths(options.paths) : getIssuerSpecsFromModule(parent); @@ -27513,7 +27695,7 @@ function applyPatch(pnpapi, opts) { } } let firstError; - for (const {apiPath, path, module} of issuerSpecs) { + for (const { apiPath, path, module } of issuerSpecs) { let resolution; const issuerApi = apiPath !== null ? opts.manager.getApiEntry(apiPath, true).instance : null; try { @@ -27594,7 +27776,12 @@ Require stack: const originalDlopen = process.dlopen; process.dlopen = function(...args) { const [module, filename, ...rest] = args; - return originalDlopen.call(this, module, npath.fromPortablePath(VirtualFS.resolveVirtual(npath.toPortablePath(filename))), ...rest); + return originalDlopen.call( + this, + module, + npath.fromPortablePath(VirtualFS.resolveVirtual(npath.toPortablePath(filename))), + ...rest + ); }; const originalEmit = process.emit; process.emit = function(name, data, ...args) { @@ -27605,21 +27792,21 @@ Require stack: patchFs(fs__default.default, new PosixFS(opts.fakeFs)); } -function hydrateRuntimeState(data, {basePath}) { +function hydrateRuntimeState(data, { basePath }) { const portablePath = npath.toPortablePath(basePath); const absolutePortablePath = ppath.resolve(portablePath); const ignorePattern = data.ignorePatternData !== null ? new RegExp(data.ignorePatternData) : null; - const packageLocatorsByLocations = new Map(); + const packageLocatorsByLocations = /* @__PURE__ */ new Map(); const packageRegistry = new Map(data.packageRegistryData.map(([packageName, packageStoreData]) => { return [packageName, new Map(packageStoreData.map(([packageReference, packageInformationData]) => { var _a; if (packageName === null !== (packageReference === null)) throw new Error(`Assertion failed: The name and reference should be null, or neither should`); const discardFromLookup = (_a = packageInformationData.discardFromLookup) != null ? _a : false; - const packageLocator = {name: packageName, reference: packageReference}; + const packageLocator = { name: packageName, reference: packageReference }; const entry = packageLocatorsByLocations.get(packageInformationData.packageLocation); if (!entry) { - packageLocatorsByLocations.set(packageInformationData.packageLocation, {locator: packageLocator, discardFromLookup}); + packageLocatorsByLocations.set(packageInformationData.packageLocation, { locator: packageLocator, discardFromLookup }); } else { entry.discardFromLookup = entry.discardFromLookup && discardFromLookup; if (!discardFromLookup) { @@ -27768,25 +27955,459 @@ function resolve(pkg, entry='.', options={}) { } } -var __defProp$1 = Object.defineProperty; -var __defProps = Object.defineProperties; -var __getOwnPropDescs = Object.getOwnPropertyDescriptors; -var __getOwnPropSymbols$1 = Object.getOwnPropertySymbols; -var __hasOwnProp$1 = Object.prototype.hasOwnProperty; -var __propIsEnum$1 = Object.prototype.propertyIsEnumerable; -var __defNormalProp$1 = (obj, key, value) => key in obj ? __defProp$1(obj, key, {enumerable: true, configurable: true, writable: true, value}) : obj[key] = value; -var __spreadValues$1 = (a, b) => { - for (var prop in b || (b = {})) - if (__hasOwnProp$1.call(b, prop)) - __defNormalProp$1(a, prop, b[prop]); - if (__getOwnPropSymbols$1) - for (var prop of __getOwnPropSymbols$1(b)) { - if (__propIsEnum$1.call(b, prop)) - __defNormalProp$1(a, prop, b[prop]); +const ArrayIsArray = Array.isArray; +const JSONStringify = JSON.stringify; +const ObjectGetOwnPropertyNames = Object.getOwnPropertyNames; +const ObjectPrototypeHasOwnProperty = (obj, prop) => Object.prototype.hasOwnProperty.call(obj, prop); +const RegExpPrototypeExec = (obj, string) => RegExp.prototype.exec.call(obj, string); +const RegExpPrototypeSymbolReplace = (obj, ...rest) => RegExp.prototype[Symbol.replace].apply(obj, rest); +const StringPrototypeEndsWith = (str, ...rest) => String.prototype.endsWith.apply(str, rest); +const StringPrototypeIncludes = (str, ...rest) => String.prototype.includes.apply(str, rest); +const StringPrototypeLastIndexOf = (str, ...rest) => String.prototype.lastIndexOf.apply(str, rest); +const StringPrototypeIndexOf = (str, ...rest) => String.prototype.indexOf.apply(str, rest); +const StringPrototypeReplace = (str, ...rest) => String.prototype.replace.apply(str, rest); +const StringPrototypeSlice = (str, ...rest) => String.prototype.slice.apply(str, rest); +const StringPrototypeStartsWith = (str, ...rest) => String.prototype.startsWith.apply(str, rest); +const SafeMap = Map; +const JSONParse = JSON.parse; + +function createErrorType(code, messageCreator, errorType) { + return class extends errorType { + constructor(...args) { + super(messageCreator(...args)); + this.code = code; + this.name = `${errorType.name} [${code}]`; } - return a; -}; -var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b)); + }; +} +const ERR_PACKAGE_IMPORT_NOT_DEFINED = createErrorType( + `ERR_PACKAGE_IMPORT_NOT_DEFINED`, + (specifier, packagePath, base) => { + return `Package import specifier "${specifier}" is not defined${packagePath ? ` in package ${packagePath}package.json` : ``} imported from ${base}`; + }, + TypeError +); +const ERR_INVALID_MODULE_SPECIFIER = createErrorType( + `ERR_INVALID_MODULE_SPECIFIER`, + (request, reason, base = void 0) => { + return `Invalid module "${request}" ${reason}${base ? ` imported from ${base}` : ``}`; + }, + TypeError +); +const ERR_INVALID_PACKAGE_TARGET = createErrorType( + `ERR_INVALID_PACKAGE_TARGET`, + (pkgPath, key, target, isImport = false, base = void 0) => { + const relError = typeof target === `string` && !isImport && target.length && !StringPrototypeStartsWith(target, `./`); + if (key === `.`) { + assert__default.default(isImport === false); + return `Invalid "exports" main target ${JSONStringify(target)} defined in the package config ${pkgPath}package.json${base ? ` imported from ${base}` : ``}${relError ? `; targets must start with "./"` : ``}`; + } + return `Invalid "${isImport ? `imports` : `exports`}" target ${JSONStringify( + target + )} defined for '${key}' in the package config ${pkgPath}package.json${base ? ` imported from ${base}` : ``}${relError ? `; targets must start with "./"` : ``}`; + }, + Error +); +const ERR_INVALID_PACKAGE_CONFIG = createErrorType( + `ERR_INVALID_PACKAGE_CONFIG`, + (path, base, message) => { + return `Invalid package config ${path}${base ? ` while importing ${base}` : ``}${message ? `. ${message}` : ``}`; + }, + Error +); + +function filterOwnProperties(source, keys) { + const filtered = /* @__PURE__ */ Object.create(null); + for (let i = 0; i < keys.length; i++) { + const key = keys[i]; + if (ObjectPrototypeHasOwnProperty(source, key)) { + filtered[key] = source[key]; + } + } + return filtered; +} + +const packageJSONCache = new SafeMap(); +function getPackageConfig(path, specifier, base, readFileSyncFn) { + const existing = packageJSONCache.get(path); + if (existing !== void 0) { + return existing; + } + const source = readFileSyncFn(path); + if (source === void 0) { + const packageConfig2 = { + pjsonPath: path, + exists: false, + main: void 0, + name: void 0, + type: "none", + exports: void 0, + imports: void 0 + }; + packageJSONCache.set(path, packageConfig2); + return packageConfig2; + } + let packageJSON; + try { + packageJSON = JSONParse(source); + } catch (error) { + throw new ERR_INVALID_PACKAGE_CONFIG( + path, + (base ? `"${specifier}" from ` : "") + url.fileURLToPath(base || specifier), + error.message + ); + } + let { imports, main, name, type } = filterOwnProperties(packageJSON, [ + "imports", + "main", + "name", + "type" + ]); + const exports = ObjectPrototypeHasOwnProperty(packageJSON, "exports") ? packageJSON.exports : void 0; + if (typeof imports !== "object" || imports === null) { + imports = void 0; + } + if (typeof main !== "string") { + main = void 0; + } + if (typeof name !== "string") { + name = void 0; + } + if (type !== "module" && type !== "commonjs") { + type = "none"; + } + const packageConfig = { + pjsonPath: path, + exists: true, + main, + name, + type, + exports, + imports + }; + packageJSONCache.set(path, packageConfig); + return packageConfig; +} +function getPackageScopeConfig(resolved, readFileSyncFn) { + let packageJSONUrl = new URL("./package.json", resolved); + while (true) { + const packageJSONPath2 = packageJSONUrl.pathname; + if (StringPrototypeEndsWith(packageJSONPath2, "node_modules/package.json")) { + break; + } + const packageConfig2 = getPackageConfig( + url.fileURLToPath(packageJSONUrl), + resolved, + void 0, + readFileSyncFn + ); + if (packageConfig2.exists) { + return packageConfig2; + } + const lastPackageJSONUrl = packageJSONUrl; + packageJSONUrl = new URL("../package.json", packageJSONUrl); + if (packageJSONUrl.pathname === lastPackageJSONUrl.pathname) { + break; + } + } + const packageJSONPath = url.fileURLToPath(packageJSONUrl); + const packageConfig = { + pjsonPath: packageJSONPath, + exists: false, + main: void 0, + name: void 0, + type: "none", + exports: void 0, + imports: void 0 + }; + packageJSONCache.set(packageJSONPath, packageConfig); + return packageConfig; +} + +/** + @license + Copyright Node.js contributors. All rights reserved. + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to + deal in the Software without restriction, including without limitation the + rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + sell copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + IN THE SOFTWARE. +*/ +function throwImportNotDefined(specifier, packageJSONUrl, base) { + throw new ERR_PACKAGE_IMPORT_NOT_DEFINED( + specifier, + packageJSONUrl && url.fileURLToPath(new URL(".", packageJSONUrl)), + url.fileURLToPath(base) + ); +} +function throwInvalidSubpath(subpath, packageJSONUrl, internal, base) { + const reason = `request is not a valid subpath for the "${internal ? "imports" : "exports"}" resolution of ${url.fileURLToPath(packageJSONUrl)}`; + throw new ERR_INVALID_MODULE_SPECIFIER( + subpath, + reason, + base && url.fileURLToPath(base) + ); +} +function throwInvalidPackageTarget(subpath, target, packageJSONUrl, internal, base) { + if (typeof target === "object" && target !== null) { + target = JSONStringify(target, null, ""); + } else { + target = `${target}`; + } + throw new ERR_INVALID_PACKAGE_TARGET( + url.fileURLToPath(new URL(".", packageJSONUrl)), + subpath, + target, + internal, + base && url.fileURLToPath(base) + ); +} +const invalidSegmentRegEx = /(^|\\|\/)((\.|%2e)(\.|%2e)?|(n|%6e|%4e)(o|%6f|%4f)(d|%64|%44)(e|%65|%45)(_|%5f)(m|%6d|%4d)(o|%6f|%4f)(d|%64|%44)(u|%75|%55)(l|%6c|%4c)(e|%65|%45)(s|%73|%53))(\\|\/|$)/i; +const patternRegEx = /\*/g; +function resolvePackageTargetString(target, subpath, match, packageJSONUrl, base, pattern, internal, conditions) { + if (subpath !== "" && !pattern && target[target.length - 1] !== "/") + throwInvalidPackageTarget(match, target, packageJSONUrl, internal, base); + if (!StringPrototypeStartsWith(target, "./")) { + if (internal && !StringPrototypeStartsWith(target, "../") && !StringPrototypeStartsWith(target, "/")) { + let isURL = false; + try { + new URL(target); + isURL = true; + } catch { + } + if (!isURL) { + const exportTarget = pattern ? RegExpPrototypeSymbolReplace(patternRegEx, target, () => subpath) : target + subpath; + return exportTarget; + } + } + throwInvalidPackageTarget(match, target, packageJSONUrl, internal, base); + } + if (RegExpPrototypeExec( + invalidSegmentRegEx, + StringPrototypeSlice(target, 2) + ) !== null) + throwInvalidPackageTarget(match, target, packageJSONUrl, internal, base); + const resolved = new URL(target, packageJSONUrl); + const resolvedPath = resolved.pathname; + const packagePath = new URL(".", packageJSONUrl).pathname; + if (!StringPrototypeStartsWith(resolvedPath, packagePath)) + throwInvalidPackageTarget(match, target, packageJSONUrl, internal, base); + if (subpath === "") + return resolved; + if (RegExpPrototypeExec(invalidSegmentRegEx, subpath) !== null) { + const request = pattern ? StringPrototypeReplace(match, "*", () => subpath) : match + subpath; + throwInvalidSubpath(request, packageJSONUrl, internal, base); + } + if (pattern) { + return new URL( + RegExpPrototypeSymbolReplace(patternRegEx, resolved.href, () => subpath) + ); + } + return new URL(subpath, resolved); +} +function isArrayIndex(key) { + const keyNum = +key; + if (`${keyNum}` !== key) + return false; + return keyNum >= 0 && keyNum < 4294967295; +} +function resolvePackageTarget(packageJSONUrl, target, subpath, packageSubpath, base, pattern, internal, conditions) { + if (typeof target === "string") { + return resolvePackageTargetString( + target, + subpath, + packageSubpath, + packageJSONUrl, + base, + pattern, + internal); + } else if (ArrayIsArray(target)) { + if (target.length === 0) { + return null; + } + let lastException; + for (let i = 0; i < target.length; i++) { + const targetItem = target[i]; + let resolveResult; + try { + resolveResult = resolvePackageTarget( + packageJSONUrl, + targetItem, + subpath, + packageSubpath, + base, + pattern, + internal, + conditions + ); + } catch (e) { + lastException = e; + if (e.code === "ERR_INVALID_PACKAGE_TARGET") { + continue; + } + throw e; + } + if (resolveResult === void 0) { + continue; + } + if (resolveResult === null) { + lastException = null; + continue; + } + return resolveResult; + } + if (lastException === void 0 || lastException === null) + return lastException; + throw lastException; + } else if (typeof target === "object" && target !== null) { + const keys = ObjectGetOwnPropertyNames(target); + for (let i = 0; i < keys.length; i++) { + const key = keys[i]; + if (isArrayIndex(key)) { + throw new ERR_INVALID_PACKAGE_CONFIG( + url.fileURLToPath(packageJSONUrl), + base, + '"exports" cannot contain numeric property keys.' + ); + } + } + for (let i = 0; i < keys.length; i++) { + const key = keys[i]; + if (key === "default" || conditions.has(key)) { + const conditionalTarget = target[key]; + const resolveResult = resolvePackageTarget( + packageJSONUrl, + conditionalTarget, + subpath, + packageSubpath, + base, + pattern, + internal, + conditions + ); + if (resolveResult === void 0) + continue; + return resolveResult; + } + } + return void 0; + } else if (target === null) { + return null; + } + throwInvalidPackageTarget( + packageSubpath, + target, + packageJSONUrl, + internal, + base + ); +} +function patternKeyCompare(a, b) { + const aPatternIndex = StringPrototypeIndexOf(a, "*"); + const bPatternIndex = StringPrototypeIndexOf(b, "*"); + const baseLenA = aPatternIndex === -1 ? a.length : aPatternIndex + 1; + const baseLenB = bPatternIndex === -1 ? b.length : bPatternIndex + 1; + if (baseLenA > baseLenB) + return -1; + if (baseLenB > baseLenA) + return 1; + if (aPatternIndex === -1) + return 1; + if (bPatternIndex === -1) + return -1; + if (a.length > b.length) + return -1; + if (b.length > a.length) + return 1; + return 0; +} +function packageImportsResolve({ + name, + base, + conditions, + readFileSyncFn +}) { + if (name === "#" || StringPrototypeStartsWith(name, "#/") || StringPrototypeEndsWith(name, "/")) { + const reason = "is not a valid internal imports specifier name"; + throw new ERR_INVALID_MODULE_SPECIFIER(name, reason, url.fileURLToPath(base)); + } + let packageJSONUrl; + const packageConfig = getPackageScopeConfig(base, readFileSyncFn); + if (packageConfig.exists) { + packageJSONUrl = url.pathToFileURL(packageConfig.pjsonPath); + const imports = packageConfig.imports; + if (imports) { + if (ObjectPrototypeHasOwnProperty(imports, name) && !StringPrototypeIncludes(name, "*")) { + const resolveResult = resolvePackageTarget( + packageJSONUrl, + imports[name], + "", + name, + base, + false, + true, + conditions + ); + if (resolveResult != null) { + return resolveResult; + } + } else { + let bestMatch = ""; + let bestMatchSubpath; + const keys = ObjectGetOwnPropertyNames(imports); + for (let i = 0; i < keys.length; i++) { + const key = keys[i]; + const patternIndex = StringPrototypeIndexOf(key, "*"); + if (patternIndex !== -1 && StringPrototypeStartsWith( + name, + StringPrototypeSlice(key, 0, patternIndex) + )) { + const patternTrailer = StringPrototypeSlice(key, patternIndex + 1); + if (name.length >= key.length && StringPrototypeEndsWith(name, patternTrailer) && patternKeyCompare(bestMatch, key) === 1 && StringPrototypeLastIndexOf(key, "*") === patternIndex) { + bestMatch = key; + bestMatchSubpath = StringPrototypeSlice( + name, + patternIndex, + name.length - patternTrailer.length + ); + } + } + } + if (bestMatch) { + const target = imports[bestMatch]; + const resolveResult = resolvePackageTarget( + packageJSONUrl, + target, + bestMatchSubpath, + bestMatch, + base, + true, + true, + conditions + ); + if (resolveResult != null) { + return resolveResult; + } + } + } + } + } + throwImportNotDefined(name, packageJSONUrl, base); +} + function makeApi(runtimeState, opts) { const alwaysWarnOnFallback = Number(process.env.PNP_ALWAYS_WARN_ON_FALLBACK) > 0; const debugLevel = Number(process.env.PNP_DEBUG_LEVEL); @@ -27794,9 +28415,9 @@ function makeApi(runtimeState, opts) { const isStrictRegExp = /^(\/|\.{1,2}(\/|$))/; const isDirRegExp = /\/$/; const isRelativeRegexp = /^\.{0,2}\//; - const topLevelLocator = {name: null, reference: null}; + const topLevelLocator = { name: null, reference: null }; const fallbackLocators = []; - const emittedWarnings = new Set(); + const emittedWarnings = /* @__PURE__ */ new Set(); if (runtimeState.enableTopLevelFallback === true) fallbackLocators.push(topLevelLocator); if (opts.compatibilityMode !== false) { @@ -27807,7 +28428,7 @@ function makeApi(runtimeState, opts) { if (reference === null) { throw new Error(`Assertion failed: This reference shouldn't be null`); } else { - fallbackLocators.push({name, reference}); + fallbackLocators.push({ name, reference }); } } } @@ -27829,7 +28450,7 @@ function makeApi(runtimeState, opts) { function trace(entry) { var _a, _b, _c, _d, _e, _f; const colors = (_c = (_b = (_a = process.stderr) == null ? void 0 : _a.hasColors) == null ? void 0 : _b.call(_a)) != null ? _c : process.stdout.isTTY; - const c = (n, str) => `[${n}m${str}`; + const c = (n, str) => `\x1B[${n}m${str}\x1B[0m`; const error = entry.error; if (error) console.error(c(`31;1`, `\u2716 ${(_d = entry.error) == null ? void 0 : _d.message.replace(/\n.*/s, ``)}`)); @@ -27838,10 +28459,10 @@ function makeApi(runtimeState, opts) { if (entry.args.length > 0) console.error(); for (const arg of entry.args) - console.error(` ${c(`37;1`, `In \u2190`)} ${nodeUtils.inspect(arg, {colors, compact: true})}`); + console.error(` ${c(`37;1`, `In \u2190`)} ${nodeUtils.inspect(arg, { colors, compact: true })}`); if (entry.result) { console.error(); - console.error(` ${c(`37;1`, `Out \u2192`)} ${nodeUtils.inspect(entry.result, {colors, compact: true})}`); + console.error(` ${c(`37;1`, `Out \u2192`)} ${nodeUtils.inspect(entry.result, { colors, compact: true })}`); } const stack = (_f = (_e = new Error().stack.match(/(?<=^ +)at.*/gm)) == null ? void 0 : _e.slice(2)) != null ? _f : []; if (stack.length > 0) { @@ -27885,7 +28506,10 @@ function makeApi(runtimeState, opts) { function getPackageInformationSafe(packageLocator) { const packageInformation = getPackageInformation(packageLocator); if (!packageInformation) { - throw makeError(ErrorCode.INTERNAL, `Couldn't find a matching entry in the dependency tree for the specified parent (this is probably an internal error)`); + throw makeError( + ErrorCode.INTERNAL, + `Couldn't find a matching entry in the dependency tree for the specified parent (this is probably an internal error)` + ); } return packageInformation; } @@ -27897,23 +28521,29 @@ function makeApi(runtimeState, opts) { return true; return false; } - const defaultExportsConditions = new Set([`default`, `node`, `require`]); + const defaultExportsConditions = /* @__PURE__ */ new Set([`default`, `node`, `require`]); function applyNodeExportsResolution(unqualifiedPath, conditions = defaultExportsConditions) { const locator = findPackageLocator(ppath.join(unqualifiedPath, `internal.js`), { resolveIgnored: true, includeDiscardFromLookup: true }); if (locator === null) { - throw makeError(ErrorCode.INTERNAL, `The locator that owns the "${unqualifiedPath}" path can't be found inside the dependency tree (this is probably an internal error)`); + throw makeError( + ErrorCode.INTERNAL, + `The locator that owns the "${unqualifiedPath}" path can't be found inside the dependency tree (this is probably an internal error)` + ); } - const {packageLocation} = getPackageInformationSafe(locator); + const { packageLocation } = getPackageInformationSafe(locator); const manifestPath = ppath.join(packageLocation, Filename.manifest); if (!opts.fakeFs.existsSync(manifestPath)) return null; const pkgJson = JSON.parse(opts.fakeFs.readFileSync(manifestPath, `utf8`)); let subpath = ppath.contains(packageLocation, unqualifiedPath); if (subpath === null) { - throw makeError(ErrorCode.INTERNAL, `unqualifiedPath doesn't contain the packageLocation (this is probably an internal error)`); + throw makeError( + ErrorCode.INTERNAL, + `unqualifiedPath doesn't contain the packageLocation (this is probably an internal error)` + ); } if (!isRelativeRegexp.test(subpath)) subpath = `./${subpath}`; @@ -27924,13 +28554,18 @@ function makeApi(runtimeState, opts) { unsafe: true }); } catch (error) { - throw makeError(ErrorCode.EXPORTS_RESOLUTION_FAILED, error.message, {unqualifiedPath: getPathForDisplay(unqualifiedPath), locator, pkgJson, subpath: getPathForDisplay(subpath), conditions}, `ERR_PACKAGE_PATH_NOT_EXPORTED`); + throw makeError( + ErrorCode.EXPORTS_RESOLUTION_FAILED, + error.message, + { unqualifiedPath: getPathForDisplay(unqualifiedPath), locator, pkgJson, subpath: getPathForDisplay(subpath), conditions }, + `ERR_PACKAGE_PATH_NOT_EXPORTED` + ); } if (typeof resolvedExport === `string`) return ppath.join(packageLocation, resolvedExport); return null; } - function applyNodeExtensionResolution(unqualifiedPath, candidates, {extensions}) { + function applyNodeExtensionResolution(unqualifiedPath, candidates, { extensions }) { let stat; try { candidates.push(unqualifiedPath); @@ -27949,7 +28584,7 @@ function makeApi(runtimeState, opts) { if (pkgJson && pkgJson.main) nextUnqualifiedPath = ppath.resolve(unqualifiedPath, pkgJson.main); if (nextUnqualifiedPath && nextUnqualifiedPath !== unqualifiedPath) { - const resolution = applyNodeExtensionResolution(nextUnqualifiedPath, candidates, {extensions}); + const resolution = applyNodeExtensionResolution(nextUnqualifiedPath, candidates, { extensions }); if (resolution !== null) { return resolution; } @@ -27964,7 +28599,7 @@ function makeApi(runtimeState, opts) { } if (stat && stat.isDirectory()) { for (let i = 0, length = extensions.length; i < length; i++) { - const candidateFile = ppath.format({dir: unqualifiedPath, name: `index`, ext: extensions[i]}); + const candidateFile = ppath.format({ dir: unqualifiedPath, name: `index`, ext: extensions[i] }); candidates.push(candidateFile); if (opts.fakeFs.existsSync(candidateFile)) { return candidateFile; @@ -27982,7 +28617,7 @@ function makeApi(runtimeState, opts) { function callNativeResolution(request, issuer) { if (issuer.endsWith(`/`)) issuer = ppath.join(issuer, `internal.js`); - return require$$0.Module._resolveFilename(npath.fromPortablePath(request), makeFakeModule(npath.fromPortablePath(issuer)), false, {plugnplay: false}); + return require$$0.Module._resolveFilename(npath.fromPortablePath(request), makeFakeModule(npath.fromPortablePath(issuer)), false, { plugnplay: false }); } function isPathIgnored(path) { if (ignorePattern === null) @@ -27996,9 +28631,9 @@ function makeApi(runtimeState, opts) { return false; } } - const VERSIONS = {std: 3, resolveVirtual: 1, getAllLocators: 1}; + const VERSIONS = { std: 3, resolveVirtual: 1, getAllLocators: 1 }; const topLevel = topLevelLocator; - function getPackageInformation({name, reference}) { + function getPackageInformation({ name, reference }) { const packageInformationStore = packageRegistry.get(name); if (!packageInformationStore) return null; @@ -28007,7 +28642,7 @@ function makeApi(runtimeState, opts) { return null; return packageInformation; } - function findPackageDependents({name, reference}) { + function findPackageDependents({ name, reference }) { const dependents = []; for (const [dependentName, packageInformationStore] of packageRegistry) { if (dependentName === null) @@ -28029,8 +28664,8 @@ function makeApi(runtimeState, opts) { return dependents; } function findBrokenPeerDependencies(dependency, initialPackage) { - const brokenPackages = new Map(); - const alreadyVisited = new Set(); + const brokenPackages = /* @__PURE__ */ new Map(); + const alreadyVisited = /* @__PURE__ */ new Set(); const traversal = (currentPackage) => { const identifier = JSON.stringify(currentPackage.name); if (alreadyVisited.has(identifier)) @@ -28044,7 +28679,7 @@ function makeApi(runtimeState, opts) { } else { let brokenSet = brokenPackages.get(dependent.name); if (typeof brokenSet === `undefined`) - brokenPackages.set(dependent.name, brokenSet = new Set()); + brokenPackages.set(dependent.name, brokenSet = /* @__PURE__ */ new Set()); brokenSet.add(dependent.reference); } } @@ -28053,10 +28688,10 @@ function makeApi(runtimeState, opts) { const brokenList = []; for (const name of [...brokenPackages.keys()].sort()) for (const reference of [...brokenPackages.get(name)].sort()) - brokenList.push({name, reference}); + brokenList.push({ name, reference }); return brokenList; } - function findPackageLocator(location, {resolveIgnored = false, includeDiscardFromLookup = false} = {}) { + function findPackageLocator(location, { resolveIgnored = false, includeDiscardFromLookup = false } = {}) { if (isPathIgnored(location) && !resolveIgnored) return null; let relativeLocation = ppath.relative(runtimeState.basePath, location); @@ -28074,7 +28709,18 @@ function makeApi(runtimeState, opts) { } while (relativeLocation !== ``); return null; } - function resolveToUnqualified(request, issuer, {considerBuiltins = true} = {}) { + function tryReadFile(filePath) { + try { + return opts.fakeFs.readFileSync(npath.toPortablePath(filePath), `utf8`); + } catch (err) { + if (err.code === `ENOENT`) + return void 0; + throw err; + } + } + function resolveToUnqualified(request, issuer, { considerBuiltins = true } = {}) { + if (request.startsWith(`#`)) + throw new Error(`resolveToUnqualified can not handle private import mappings`); if (request === `pnpapi`) return npath.toPortablePath(opts.pnpapiResolution); if (considerBuiltins && isBuiltinModule(request)) @@ -28085,11 +28731,15 @@ function makeApi(runtimeState, opts) { if (!ppath.isAbsolute(request) || findPackageLocator(request) === null) { const result = callNativeResolution(request, issuer); if (result === false) { - throw makeError(ErrorCode.BUILTIN_NODE_RESOLUTION_FAILED, `The builtin node resolution algorithm was unable to resolve the requested module (it didn't go through the pnp resolver because the issuer was explicitely ignored by the regexp) + throw makeError( + ErrorCode.BUILTIN_NODE_RESOLUTION_FAILED, + `The builtin node resolution algorithm was unable to resolve the requested module (it didn't go through the pnp resolver because the issuer was explicitely ignored by the regexp) Require request: "${requestForDisplay}" Required by: ${issuerForDisplay} -`, {request: requestForDisplay, issuer: issuerForDisplay}); +`, + { request: requestForDisplay, issuer: issuerForDisplay } + ); } return npath.toPortablePath(result); } @@ -28101,7 +28751,11 @@ Required by: ${issuerForDisplay} unqualifiedPath = ppath.normalize(request); } else { if (!issuer) { - throw makeError(ErrorCode.API_ERROR, `The resolveToUnqualified function must be called with a valid issuer when the path isn't a builtin nor absolute`, {request: requestForDisplay, issuer: issuerForDisplay}); + throw makeError( + ErrorCode.API_ERROR, + `The resolveToUnqualified function must be called with a valid issuer when the path isn't a builtin nor absolute`, + { request: requestForDisplay, issuer: issuerForDisplay } + ); } const absoluteIssuer = ppath.resolve(issuer); if (issuer.match(isDirRegExp)) { @@ -28112,18 +28766,26 @@ Required by: ${issuerForDisplay} } } else { if (!issuer) { - throw makeError(ErrorCode.API_ERROR, `The resolveToUnqualified function must be called with a valid issuer when the path isn't a builtin nor absolute`, {request: requestForDisplay, issuer: issuerForDisplay}); + throw makeError( + ErrorCode.API_ERROR, + `The resolveToUnqualified function must be called with a valid issuer when the path isn't a builtin nor absolute`, + { request: requestForDisplay, issuer: issuerForDisplay } + ); } const [, dependencyName, subPath] = dependencyNameMatch; const issuerLocator = findPackageLocator(issuer); if (!issuerLocator) { const result = callNativeResolution(request, issuer); if (result === false) { - throw makeError(ErrorCode.BUILTIN_NODE_RESOLUTION_FAILED, `The builtin node resolution algorithm was unable to resolve the requested module (it didn't go through the pnp resolver because the issuer doesn't seem to be part of the Yarn-managed dependency tree). + throw makeError( + ErrorCode.BUILTIN_NODE_RESOLUTION_FAILED, + `The builtin node resolution algorithm was unable to resolve the requested module (it didn't go through the pnp resolver because the issuer doesn't seem to be part of the Yarn-managed dependency tree). Require path: "${requestForDisplay}" Required by: ${issuerForDisplay} -`, {request: requestForDisplay, issuer: issuerForDisplay}); +`, + { request: requestForDisplay, issuer: issuerForDisplay } + ); } return npath.toPortablePath(result); } @@ -28160,60 +28822,88 @@ Required by: ${issuerForDisplay} let error = null; if (dependencyReference === null) { if (isDependencyTreeRoot(issuerLocator)) { - error = makeError(ErrorCode.MISSING_PEER_DEPENDENCY, `Your application tried to access ${dependencyName} (a peer dependency); this isn't allowed as there is no ancestor to satisfy the requirement. Use a devDependency if needed. + error = makeError( + ErrorCode.MISSING_PEER_DEPENDENCY, + `Your application tried to access ${dependencyName} (a peer dependency); this isn't allowed as there is no ancestor to satisfy the requirement. Use a devDependency if needed. Required package: ${dependencyName}${dependencyName !== requestForDisplay ? ` (via "${requestForDisplay}")` : ``} Required by: ${issuerForDisplay} -`, {request: requestForDisplay, issuer: issuerForDisplay, dependencyName}); +`, + { request: requestForDisplay, issuer: issuerForDisplay, dependencyName } + ); } else { const brokenAncestors = findBrokenPeerDependencies(dependencyName, issuerLocator); if (brokenAncestors.every((ancestor) => isDependencyTreeRoot(ancestor))) { - error = makeError(ErrorCode.MISSING_PEER_DEPENDENCY, `${issuerLocator.name} tried to access ${dependencyName} (a peer dependency) but it isn't provided by your application; this makes the require call ambiguous and unsound. + error = makeError( + ErrorCode.MISSING_PEER_DEPENDENCY, + `${issuerLocator.name} tried to access ${dependencyName} (a peer dependency) but it isn't provided by your application; this makes the require call ambiguous and unsound. Required package: ${dependencyName}${dependencyName !== requestForDisplay ? ` (via "${requestForDisplay}")` : ``} Required by: ${issuerLocator.name}@${issuerLocator.reference} (via ${issuerForDisplay}) ${brokenAncestors.map((ancestorLocator) => `Ancestor breaking the chain: ${ancestorLocator.name}@${ancestorLocator.reference} `).join(``)} -`, {request: requestForDisplay, issuer: issuerForDisplay, issuerLocator: Object.assign({}, issuerLocator), dependencyName, brokenAncestors}); +`, + { request: requestForDisplay, issuer: issuerForDisplay, issuerLocator: Object.assign({}, issuerLocator), dependencyName, brokenAncestors } + ); } else { - error = makeError(ErrorCode.MISSING_PEER_DEPENDENCY, `${issuerLocator.name} tried to access ${dependencyName} (a peer dependency) but it isn't provided by its ancestors; this makes the require call ambiguous and unsound. + error = makeError( + ErrorCode.MISSING_PEER_DEPENDENCY, + `${issuerLocator.name} tried to access ${dependencyName} (a peer dependency) but it isn't provided by its ancestors; this makes the require call ambiguous and unsound. Required package: ${dependencyName}${dependencyName !== requestForDisplay ? ` (via "${requestForDisplay}")` : ``} Required by: ${issuerLocator.name}@${issuerLocator.reference} (via ${issuerForDisplay}) ${brokenAncestors.map((ancestorLocator) => `Ancestor breaking the chain: ${ancestorLocator.name}@${ancestorLocator.reference} `).join(``)} -`, {request: requestForDisplay, issuer: issuerForDisplay, issuerLocator: Object.assign({}, issuerLocator), dependencyName, brokenAncestors}); +`, + { request: requestForDisplay, issuer: issuerForDisplay, issuerLocator: Object.assign({}, issuerLocator), dependencyName, brokenAncestors } + ); } } } else if (dependencyReference === void 0) { if (!considerBuiltins && isBuiltinModule(request)) { if (isDependencyTreeRoot(issuerLocator)) { - error = makeError(ErrorCode.UNDECLARED_DEPENDENCY, `Your application tried to access ${dependencyName}. While this module is usually interpreted as a Node builtin, your resolver is running inside a non-Node resolution context where such builtins are ignored. Since ${dependencyName} isn't otherwise declared in your dependencies, this makes the require call ambiguous and unsound. + error = makeError( + ErrorCode.UNDECLARED_DEPENDENCY, + `Your application tried to access ${dependencyName}. While this module is usually interpreted as a Node builtin, your resolver is running inside a non-Node resolution context where such builtins are ignored. Since ${dependencyName} isn't otherwise declared in your dependencies, this makes the require call ambiguous and unsound. Required package: ${dependencyName}${dependencyName !== requestForDisplay ? ` (via "${requestForDisplay}")` : ``} Required by: ${issuerForDisplay} -`, {request: requestForDisplay, issuer: issuerForDisplay, dependencyName}); +`, + { request: requestForDisplay, issuer: issuerForDisplay, dependencyName } + ); } else { - error = makeError(ErrorCode.UNDECLARED_DEPENDENCY, `${issuerLocator.name} tried to access ${dependencyName}. While this module is usually interpreted as a Node builtin, your resolver is running inside a non-Node resolution context where such builtins are ignored. Since ${dependencyName} isn't otherwise declared in ${issuerLocator.name}'s dependencies, this makes the require call ambiguous and unsound. + error = makeError( + ErrorCode.UNDECLARED_DEPENDENCY, + `${issuerLocator.name} tried to access ${dependencyName}. While this module is usually interpreted as a Node builtin, your resolver is running inside a non-Node resolution context where such builtins are ignored. Since ${dependencyName} isn't otherwise declared in ${issuerLocator.name}'s dependencies, this makes the require call ambiguous and unsound. Required package: ${dependencyName}${dependencyName !== requestForDisplay ? ` (via "${requestForDisplay}")` : ``} Required by: ${issuerForDisplay} -`, {request: requestForDisplay, issuer: issuerForDisplay, issuerLocator: Object.assign({}, issuerLocator), dependencyName}); +`, + { request: requestForDisplay, issuer: issuerForDisplay, issuerLocator: Object.assign({}, issuerLocator), dependencyName } + ); } } else { if (isDependencyTreeRoot(issuerLocator)) { - error = makeError(ErrorCode.UNDECLARED_DEPENDENCY, `Your application tried to access ${dependencyName}, but it isn't declared in your dependencies; this makes the require call ambiguous and unsound. + error = makeError( + ErrorCode.UNDECLARED_DEPENDENCY, + `Your application tried to access ${dependencyName}, but it isn't declared in your dependencies; this makes the require call ambiguous and unsound. Required package: ${dependencyName}${dependencyName !== requestForDisplay ? ` (via "${requestForDisplay}")` : ``} Required by: ${issuerForDisplay} -`, {request: requestForDisplay, issuer: issuerForDisplay, dependencyName}); +`, + { request: requestForDisplay, issuer: issuerForDisplay, dependencyName } + ); } else { - error = makeError(ErrorCode.UNDECLARED_DEPENDENCY, `${issuerLocator.name} tried to access ${dependencyName}, but it isn't declared in its dependencies; this makes the require call ambiguous and unsound. + error = makeError( + ErrorCode.UNDECLARED_DEPENDENCY, + `${issuerLocator.name} tried to access ${dependencyName}, but it isn't declared in its dependencies; this makes the require call ambiguous and unsound. Required package: ${dependencyName}${dependencyName !== requestForDisplay ? ` (via "${requestForDisplay}")` : ``} Required by: ${issuerLocator.name}@${issuerLocator.reference} (via ${issuerForDisplay}) -`, {request: requestForDisplay, issuer: issuerForDisplay, issuerLocator: Object.assign({}, issuerLocator), dependencyName}); +`, + { request: requestForDisplay, issuer: issuerForDisplay, issuerLocator: Object.assign({}, issuerLocator), dependencyName } + ); } } } @@ -28228,14 +28918,18 @@ Required by: ${issuerLocator.name}@${issuerLocator.reference} (via ${issuerForDi process.emitWarning(error); } } - const dependencyLocator = Array.isArray(dependencyReference) ? {name: dependencyReference[0], reference: dependencyReference[1]} : {name: dependencyName, reference: dependencyReference}; + const dependencyLocator = Array.isArray(dependencyReference) ? { name: dependencyReference[0], reference: dependencyReference[1] } : { name: dependencyName, reference: dependencyReference }; const dependencyInformation = getPackageInformationSafe(dependencyLocator); if (!dependencyInformation.packageLocation) { - throw makeError(ErrorCode.MISSING_DEPENDENCY, `A dependency seems valid but didn't get installed for some reason. This might be caused by a partial install, such as dev vs prod. + throw makeError( + ErrorCode.MISSING_DEPENDENCY, + `A dependency seems valid but didn't get installed for some reason. This might be caused by a partial install, such as dev vs prod. Required package: ${dependencyLocator.name}@${dependencyLocator.reference}${dependencyLocator.name !== requestForDisplay ? ` (via "${requestForDisplay}")` : ``} Required by: ${issuerLocator.name}@${issuerLocator.reference} (via ${issuerForDisplay}) -`, {request: requestForDisplay, issuer: issuerForDisplay, dependencyLocator: Object.assign({}, dependencyLocator)}); +`, + { request: requestForDisplay, issuer: issuerForDisplay, dependencyLocator: Object.assign({}, dependencyLocator) } + ); } const dependencyLocation = dependencyInformation.packageLocation; if (subPath) { @@ -28256,17 +28950,17 @@ Required by: ${issuerLocator.name}@${issuerLocator.reference} (via ${issuerForDi return unqualifiedPath; } } - function resolveUnqualified(unqualifiedPath, {extensions = Object.keys(require$$0.Module._extensions)} = {}) { + function resolveUnqualified(unqualifiedPath, { extensions = Object.keys(require$$0.Module._extensions) } = {}) { var _a, _b; const candidates = []; - const qualifiedPath = applyNodeExtensionResolution(unqualifiedPath, candidates, {extensions}); + const qualifiedPath = applyNodeExtensionResolution(unqualifiedPath, candidates, { extensions }); if (qualifiedPath) { return ppath.normalize(qualifiedPath); } else { const unqualifiedPathForDisplay = getPathForDisplay(unqualifiedPath); const containingPackage = findPackageLocator(unqualifiedPath); if (containingPackage) { - const {packageLocation} = getPackageInformationSafe(containingPackage); + const { packageLocation } = getPackageInformationSafe(containingPackage); let exists = true; try { opts.fakeFs.accessSync(packageLocation); @@ -28279,38 +28973,67 @@ Required by: ${issuerLocator.name}@${issuerLocator.reference} (via ${issuerForDi Missing package: ${containingPackage.name}@${containingPackage.reference} Expected package location: ${getPathForDisplay(packageLocation)} -`, {unqualifiedPath: unqualifiedPathForDisplay, extensions}); +`, { unqualifiedPath: unqualifiedPathForDisplay, extensions }); } } if (!exists) { const errorMessage = packageLocation.includes(`/unplugged/`) ? `Required unplugged package missing from disk. This may happen when switching branches without running installs (unplugged packages must be fully materialized on disk to work).` : `Required package missing from disk. If you keep your packages inside your repository then restarting the Node process may be enough. Otherwise, try to run an install first.`; - throw makeError(ErrorCode.QUALIFIED_PATH_RESOLUTION_FAILED, `${errorMessage} + throw makeError( + ErrorCode.QUALIFIED_PATH_RESOLUTION_FAILED, + `${errorMessage} Missing package: ${containingPackage.name}@${containingPackage.reference} Expected package location: ${getPathForDisplay(packageLocation)} -`, {unqualifiedPath: unqualifiedPathForDisplay, extensions}); +`, + { unqualifiedPath: unqualifiedPathForDisplay, extensions } + ); } } - throw makeError(ErrorCode.QUALIFIED_PATH_RESOLUTION_FAILED, `Qualified path resolution failed: we looked for the following paths, but none could be accessed. + throw makeError( + ErrorCode.QUALIFIED_PATH_RESOLUTION_FAILED, + `Qualified path resolution failed: we looked for the following paths, but none could be accessed. Source path: ${unqualifiedPathForDisplay} ${candidates.map((candidate) => `Not found: ${getPathForDisplay(candidate)} -`).join(``)}`, {unqualifiedPath: unqualifiedPathForDisplay, extensions}); +`).join(``)}`, + { unqualifiedPath: unqualifiedPathForDisplay, extensions } + ); + } + } + function resolvePrivateRequest(request, issuer, opts2) { + var _a; + if (!issuer) + throw new Error(`Assertion failed: An issuer is required to resolve private import mappings`); + const resolved = packageImportsResolve({ + name: request, + base: url.pathToFileURL(npath.fromPortablePath(issuer)), + conditions: (_a = opts2.conditions) != null ? _a : defaultExportsConditions, + readFileSyncFn: tryReadFile + }); + if (resolved instanceof URL) { + return resolveUnqualified(npath.toPortablePath(url.fileURLToPath(resolved)), { extensions: opts2.extensions }); + } else { + if (resolved.startsWith(`#`)) + throw new Error(`Mapping from one private import to another isn't allowed`); + return resolveRequest(resolved, issuer, opts2); } } - function resolveRequest(request, issuer, {considerBuiltins, extensions, conditions} = {}) { + function resolveRequest(request, issuer, opts2 = {}) { try { - const unqualifiedPath = resolveToUnqualified(request, issuer, {considerBuiltins}); + if (request.startsWith(`#`)) + return resolvePrivateRequest(request, issuer, opts2); + const { considerBuiltins, extensions, conditions } = opts2; + const unqualifiedPath = resolveToUnqualified(request, issuer, { considerBuiltins }); if (request === `pnpapi`) return unqualifiedPath; if (unqualifiedPath === null) return null; const isIssuerIgnored = () => issuer !== null ? isPathIgnored(issuer) : false; const remappedPath = (!considerBuiltins || !isBuiltinModule(request)) && !isIssuerIgnored() ? resolveUnqualifiedExport(request, unqualifiedPath, conditions) : unqualifiedPath; - return resolveUnqualified(remappedPath, {extensions}); + return resolveUnqualified(remappedPath, { extensions }); } catch (error) { if (Object.prototype.hasOwnProperty.call(error, `pnpCode`)) - Object.assign(error.data, {request: getPathForDisplay(request), issuer: issuer && getPathForDisplay(issuer)}); + Object.assign(error.data, { request: getPathForDisplay(request), issuer: issuer && getPathForDisplay(issuer) }); throw error; } } @@ -28324,9 +29047,9 @@ ${candidates.map((candidate) => `Not found: ${getPathForDisplay(candidate)} topLevel, getLocator: (name, referencish) => { if (Array.isArray(referencish)) { - return {name: referencish[0], reference: referencish[1]}; + return { name: referencish[0], reference: referencish[1] }; } else { - return {name, reference: referencish}; + return { name, reference: referencish }; } }, getDependencyTreeRoots: () => { @@ -28337,7 +29060,7 @@ ${candidates.map((candidate) => `Not found: ${getPathForDisplay(candidate)} for (const [name, entry] of packageRegistry) for (const reference of entry.keys()) if (name !== null && reference !== null) - locators.push({name, reference}); + locators.push({ name, reference }); return locators; }, getPackageInformation: (locator) => { @@ -28345,7 +29068,7 @@ ${candidates.map((candidate) => `Not found: ${getPathForDisplay(candidate)} if (info === null) return null; const packageLocation = npath.fromPortablePath(info.packageLocation); - const nativeInfo = __spreadProps(__spreadValues$1({}, info), {packageLocation}); + const nativeInfo = { ...info, packageLocation }; return nativeInfo; }, findPackageLocator: (path) => { @@ -28382,7 +29105,7 @@ ${candidates.map((candidate) => `Not found: ${getPathForDisplay(candidate)} function makeManager(pnpapi, opts) { const initialApiPath = npath.toPortablePath(pnpapi.resolveToUnqualified(`pnpapi`, null)); const initialApiStats = opts.fakeFs.statSync(npath.toPortablePath(initialApiPath)); - const apiMetadata = new Map([ + const apiMetadata = /* @__PURE__ */ new Map([ [initialApiPath, { cache: require$$0.Module._cache, instance: pnpapi, @@ -28424,7 +29147,7 @@ function makeManager(pnpapi, opts) { } return apiEntry; } - const findApiPathCache = new Map(); + const findApiPathCache = /* @__PURE__ */ new Map(); function addToCacheAndReturn(start, end, target) { if (target !== null) target = VirtualFS.resolveVirtual(target); @@ -28449,11 +29172,11 @@ function makeManager(pnpapi, opts) { if (!packageInformation) throw new Error(`Assertion failed: Couldn't get package information for '${modulePath}'`); if (!bestCandidate) - bestCandidate = {packageLocation: packageInformation.packageLocation, apiPaths: []}; + bestCandidate = { packageLocation: packageInformation.packageLocation, apiPaths: [] }; if (packageInformation.packageLocation === bestCandidate.packageLocation) { bestCandidate.apiPaths.push(apiPath); } else if (packageInformation.packageLocation.length > bestCandidate.packageLocation.length) { - bestCandidate = {packageLocation: packageInformation.packageLocation, apiPaths: [apiPath]}; + bestCandidate = { packageLocation: packageInformation.packageLocation, apiPaths: [apiPath] }; } } if (bestCandidate) { @@ -28507,35 +29230,7 @@ ${controlSegment} }; } -var __defProp = Object.defineProperty; -var __getOwnPropSymbols = Object.getOwnPropertySymbols; -var __hasOwnProp = Object.prototype.hasOwnProperty; -var __propIsEnum = Object.prototype.propertyIsEnumerable; -var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, {enumerable: true, configurable: true, writable: true, value}) : obj[key] = value; -var __spreadValues = (a, b) => { - for (var prop in b || (b = {})) - if (__hasOwnProp.call(b, prop)) - __defNormalProp(a, prop, b[prop]); - if (__getOwnPropSymbols) - for (var prop of __getOwnPropSymbols(b)) { - if (__propIsEnum.call(b, prop)) - __defNormalProp(a, prop, b[prop]); - } - return a; -}; -var __objRest = (source, exclude) => { - var target = {}; - for (var prop in source) - if (__hasOwnProp.call(source, prop) && exclude.indexOf(prop) < 0) - target[prop] = source[prop]; - if (source != null && __getOwnPropSymbols) - for (var prop of __getOwnPropSymbols(source)) { - if (exclude.indexOf(prop) < 0 && __propIsEnum.call(source, prop)) - target[prop] = source[prop]; - } - return target; -}; -const localFs = __spreadValues({}, fs__default.default); +const localFs = { ...fs__default.default }; const nodeFs = new NodeFS(localFs); const defaultRuntimeState = $$SETUP_STATE(hydrateRuntimeState); const defaultPnpapiResolution = __filename; @@ -28565,21 +29260,18 @@ const defaultApi = Object.assign(makeApi(defaultRuntimeState, { fakeFs: dynamicFsLayer, pnpapiResolution: defaultPnpapiResolution }), { - makeApi: (_a) => { - var _b = _a, { - basePath = void 0, - fakeFs = dynamicFsLayer, - pnpapiResolution = defaultPnpapiResolution - } = _b, rest = __objRest(_b, [ - "basePath", - "fakeFs", - "pnpapiResolution" - ]); + makeApi: ({ + basePath = void 0, + fakeFs = dynamicFsLayer, + pnpapiResolution = defaultPnpapiResolution, + ...rest + }) => { const apiRuntimeState = typeof basePath !== `undefined` ? $$SETUP_STATE(hydrateRuntimeState, basePath) : defaultRuntimeState; - return makeApi(apiRuntimeState, __spreadValues({ + return makeApi(apiRuntimeState, { fakeFs, - pnpapiResolution - }, rest)); + pnpapiResolution, + ...rest + }); }, setup: (api) => { applyPatch(api || defaultApi, { @@ -28600,7 +29292,7 @@ if (module.parent && module.parent.id === `internal/preload`) { } if (process.mainModule === module) { const reportError = (code, message, data) => { - process.stdout.write(`${JSON.stringify([{code, message, data}, null])} + process.stdout.write(`${JSON.stringify([{ code, message, data }, null])} `); }; const reportSuccess = (resolution) => { diff --git a/.pnp.loader.mjs b/.pnp.loader.mjs index 26efb974622..dbd09ddd327 100644 --- a/.pnp.loader.mjs +++ b/.pnp.loader.mjs @@ -1,14 +1,17 @@ -import { URL, fileURLToPath, pathToFileURL } from 'url'; +import { URL as URL$1, fileURLToPath, pathToFileURL } from 'url'; import fs from 'fs'; import path from 'path'; import moduleExports, { Module } from 'module'; +import { EOL } from 'os'; +import assert from 'assert'; -var PathType; -(function(PathType2) { - PathType2[PathType2["File"] = 0] = "File"; - PathType2[PathType2["Portable"] = 1] = "Portable"; - PathType2[PathType2["Native"] = 2] = "Native"; -})(PathType || (PathType = {})); +const SAFE_TIME = 456789e3; + +const PortablePath = { + root: `/`, + dot: `.`, + parent: `..` +}; const npath = Object.create(path); const ppath = Object.create(path.posix); npath.cwd = () => process.cwd(); @@ -64,6 +67,1266 @@ function toPortablePath(p) { p = `/unc/${uncWindowsPathMatch[1] ? `.dot/` : ``}${uncWindowsPathMatch[2]}`; return p; } +function convertPath(targetPathUtils, sourcePath) { + return targetPathUtils === npath ? fromPortablePath(sourcePath) : toPortablePath(sourcePath); +} + +const defaultTime = new Date(SAFE_TIME * 1e3); +async function copyPromise(destinationFs, destination, sourceFs, source, opts) { + const normalizedDestination = destinationFs.pathUtils.normalize(destination); + const normalizedSource = sourceFs.pathUtils.normalize(source); + const prelayout = []; + const postlayout = []; + const { atime, mtime } = opts.stableTime ? { atime: defaultTime, mtime: defaultTime } : await sourceFs.lstatPromise(normalizedSource); + await destinationFs.mkdirpPromise(destinationFs.pathUtils.dirname(destination), { utimes: [atime, mtime] }); + const updateTime = typeof destinationFs.lutimesPromise === `function` ? destinationFs.lutimesPromise.bind(destinationFs) : destinationFs.utimesPromise.bind(destinationFs); + await copyImpl(prelayout, postlayout, updateTime, destinationFs, normalizedDestination, sourceFs, normalizedSource, { ...opts, didParentExist: true }); + for (const operation of prelayout) + await operation(); + await Promise.all(postlayout.map((operation) => { + return operation(); + })); +} +async function copyImpl(prelayout, postlayout, updateTime, destinationFs, destination, sourceFs, source, opts) { + var _a, _b; + const destinationStat = opts.didParentExist ? await maybeLStat(destinationFs, destination) : null; + const sourceStat = await sourceFs.lstatPromise(source); + const { atime, mtime } = opts.stableTime ? { atime: defaultTime, mtime: defaultTime } : sourceStat; + let updated; + switch (true) { + case sourceStat.isDirectory(): + { + updated = await copyFolder(prelayout, postlayout, updateTime, destinationFs, destination, destinationStat, sourceFs, source, sourceStat, opts); + } + break; + case sourceStat.isFile(): + { + updated = await copyFile(prelayout, postlayout, updateTime, destinationFs, destination, destinationStat, sourceFs, source, sourceStat, opts); + } + break; + case sourceStat.isSymbolicLink(): + { + updated = await copySymlink(prelayout, postlayout, updateTime, destinationFs, destination, destinationStat, sourceFs, source, sourceStat, opts); + } + break; + default: + { + throw new Error(`Unsupported file type (${sourceStat.mode})`); + } + } + if (updated || ((_a = destinationStat == null ? void 0 : destinationStat.mtime) == null ? void 0 : _a.getTime()) !== mtime.getTime() || ((_b = destinationStat == null ? void 0 : destinationStat.atime) == null ? void 0 : _b.getTime()) !== atime.getTime()) { + postlayout.push(() => updateTime(destination, atime, mtime)); + updated = true; + } + if (destinationStat === null || (destinationStat.mode & 511) !== (sourceStat.mode & 511)) { + postlayout.push(() => destinationFs.chmodPromise(destination, sourceStat.mode & 511)); + updated = true; + } + return updated; +} +async function maybeLStat(baseFs, p) { + try { + return await baseFs.lstatPromise(p); + } catch (e) { + return null; + } +} +async function copyFolder(prelayout, postlayout, updateTime, destinationFs, destination, destinationStat, sourceFs, source, sourceStat, opts) { + if (destinationStat !== null && !destinationStat.isDirectory()) { + if (opts.overwrite) { + prelayout.push(async () => destinationFs.removePromise(destination)); + destinationStat = null; + } else { + return false; + } + } + let updated = false; + if (destinationStat === null) { + prelayout.push(async () => { + try { + await destinationFs.mkdirPromise(destination, { mode: sourceStat.mode }); + } catch (err) { + if (err.code !== `EEXIST`) { + throw err; + } + } + }); + updated = true; + } + const entries = await sourceFs.readdirPromise(source); + const nextOpts = opts.didParentExist && !destinationStat ? { ...opts, didParentExist: false } : opts; + if (opts.stableSort) { + for (const entry of entries.sort()) { + if (await copyImpl(prelayout, postlayout, updateTime, destinationFs, destinationFs.pathUtils.join(destination, entry), sourceFs, sourceFs.pathUtils.join(source, entry), nextOpts)) { + updated = true; + } + } + } else { + const entriesUpdateStatus = await Promise.all(entries.map(async (entry) => { + await copyImpl(prelayout, postlayout, updateTime, destinationFs, destinationFs.pathUtils.join(destination, entry), sourceFs, sourceFs.pathUtils.join(source, entry), nextOpts); + })); + if (entriesUpdateStatus.some((status) => status)) { + updated = true; + } + } + return updated; +} +const isCloneSupportedCache = /* @__PURE__ */ new WeakMap(); +function makeLinkOperation(opFs, destination, source, sourceStat, linkStrategy) { + return async () => { + await opFs.linkPromise(source, destination); + if (linkStrategy === "readOnly" /* ReadOnly */) { + sourceStat.mode &= ~146; + await opFs.chmodPromise(destination, sourceStat.mode); + } + }; +} +function makeCloneLinkOperation(opFs, destination, source, sourceStat, linkStrategy) { + const isCloneSupported = isCloneSupportedCache.get(opFs); + if (typeof isCloneSupported === `undefined`) { + return async () => { + try { + await opFs.copyFilePromise(source, destination, fs.constants.COPYFILE_FICLONE_FORCE); + isCloneSupportedCache.set(opFs, true); + } catch (err) { + if (err.code === `ENOSYS` || err.code === `ENOTSUP`) { + isCloneSupportedCache.set(opFs, false); + await makeLinkOperation(opFs, destination, source, sourceStat, linkStrategy)(); + } else { + throw err; + } + } + }; + } else { + if (isCloneSupported) { + return async () => opFs.copyFilePromise(source, destination, fs.constants.COPYFILE_FICLONE_FORCE); + } else { + return makeLinkOperation(opFs, destination, source, sourceStat, linkStrategy); + } + } +} +async function copyFile(prelayout, postlayout, updateTime, destinationFs, destination, destinationStat, sourceFs, source, sourceStat, opts) { + var _a; + if (destinationStat !== null) { + if (opts.overwrite) { + prelayout.push(async () => destinationFs.removePromise(destination)); + destinationStat = null; + } else { + return false; + } + } + const linkStrategy = (_a = opts.linkStrategy) != null ? _a : null; + const op = destinationFs === sourceFs ? linkStrategy !== null ? makeCloneLinkOperation(destinationFs, destination, source, sourceStat, linkStrategy) : async () => destinationFs.copyFilePromise(source, destination, fs.constants.COPYFILE_FICLONE) : linkStrategy !== null ? makeLinkOperation(destinationFs, destination, source, sourceStat, linkStrategy) : async () => destinationFs.writeFilePromise(destination, await sourceFs.readFilePromise(source)); + prelayout.push(async () => op()); + return true; +} +async function copySymlink(prelayout, postlayout, updateTime, destinationFs, destination, destinationStat, sourceFs, source, sourceStat, opts) { + if (destinationStat !== null) { + if (opts.overwrite) { + prelayout.push(async () => destinationFs.removePromise(destination)); + destinationStat = null; + } else { + return false; + } + } + prelayout.push(async () => { + await destinationFs.symlinkPromise(convertPath(destinationFs.pathUtils, await sourceFs.readlinkPromise(source)), destination); + }); + return true; +} + +function makeError(code, message) { + return Object.assign(new Error(`${code}: ${message}`), { code }); +} +function ENOSYS(message, reason) { + return makeError(`ENOSYS`, `${message}, ${reason}`); +} + +class FakeFS { + constructor(pathUtils) { + this.pathUtils = pathUtils; + } + async *genTraversePromise(init, { stableSort = false } = {}) { + const stack = [init]; + while (stack.length > 0) { + const p = stack.shift(); + const entry = await this.lstatPromise(p); + if (entry.isDirectory()) { + const entries = await this.readdirPromise(p); + if (stableSort) { + for (const entry2 of entries.sort()) { + stack.push(this.pathUtils.join(p, entry2)); + } + } else { + throw new Error(`Not supported`); + } + } else { + yield p; + } + } + } + async removePromise(p, { recursive = true, maxRetries = 5 } = {}) { + let stat; + try { + stat = await this.lstatPromise(p); + } catch (error) { + if (error.code === `ENOENT`) { + return; + } else { + throw error; + } + } + if (stat.isDirectory()) { + if (recursive) { + const entries = await this.readdirPromise(p); + await Promise.all(entries.map((entry) => { + return this.removePromise(this.pathUtils.resolve(p, entry)); + })); + } + for (let t = 0; t <= maxRetries; t++) { + try { + await this.rmdirPromise(p); + break; + } catch (error) { + if (error.code !== `EBUSY` && error.code !== `ENOTEMPTY`) { + throw error; + } else if (t < maxRetries) { + await new Promise((resolve) => setTimeout(resolve, t * 100)); + } + } + } + } else { + await this.unlinkPromise(p); + } + } + removeSync(p, { recursive = true } = {}) { + let stat; + try { + stat = this.lstatSync(p); + } catch (error) { + if (error.code === `ENOENT`) { + return; + } else { + throw error; + } + } + if (stat.isDirectory()) { + if (recursive) + for (const entry of this.readdirSync(p)) + this.removeSync(this.pathUtils.resolve(p, entry)); + this.rmdirSync(p); + } else { + this.unlinkSync(p); + } + } + async mkdirpPromise(p, { chmod, utimes } = {}) { + p = this.resolve(p); + if (p === this.pathUtils.dirname(p)) + return void 0; + const parts = p.split(this.pathUtils.sep); + let createdDirectory; + for (let u = 2; u <= parts.length; ++u) { + const subPath = parts.slice(0, u).join(this.pathUtils.sep); + if (!this.existsSync(subPath)) { + try { + await this.mkdirPromise(subPath); + } catch (error) { + if (error.code === `EEXIST`) { + continue; + } else { + throw error; + } + } + createdDirectory != null ? createdDirectory : createdDirectory = subPath; + if (chmod != null) + await this.chmodPromise(subPath, chmod); + if (utimes != null) { + await this.utimesPromise(subPath, utimes[0], utimes[1]); + } else { + const parentStat = await this.statPromise(this.pathUtils.dirname(subPath)); + await this.utimesPromise(subPath, parentStat.atime, parentStat.mtime); + } + } + } + return createdDirectory; + } + mkdirpSync(p, { chmod, utimes } = {}) { + p = this.resolve(p); + if (p === this.pathUtils.dirname(p)) + return void 0; + const parts = p.split(this.pathUtils.sep); + let createdDirectory; + for (let u = 2; u <= parts.length; ++u) { + const subPath = parts.slice(0, u).join(this.pathUtils.sep); + if (!this.existsSync(subPath)) { + try { + this.mkdirSync(subPath); + } catch (error) { + if (error.code === `EEXIST`) { + continue; + } else { + throw error; + } + } + createdDirectory != null ? createdDirectory : createdDirectory = subPath; + if (chmod != null) + this.chmodSync(subPath, chmod); + if (utimes != null) { + this.utimesSync(subPath, utimes[0], utimes[1]); + } else { + const parentStat = this.statSync(this.pathUtils.dirname(subPath)); + this.utimesSync(subPath, parentStat.atime, parentStat.mtime); + } + } + } + return createdDirectory; + } + async copyPromise(destination, source, { baseFs = this, overwrite = true, stableSort = false, stableTime = false, linkStrategy = null } = {}) { + return await copyPromise(this, destination, baseFs, source, { overwrite, stableSort, stableTime, linkStrategy }); + } + copySync(destination, source, { baseFs = this, overwrite = true } = {}) { + const stat = baseFs.lstatSync(source); + const exists = this.existsSync(destination); + if (stat.isDirectory()) { + this.mkdirpSync(destination); + const directoryListing = baseFs.readdirSync(source); + for (const entry of directoryListing) { + this.copySync(this.pathUtils.join(destination, entry), baseFs.pathUtils.join(source, entry), { baseFs, overwrite }); + } + } else if (stat.isFile()) { + if (!exists || overwrite) { + if (exists) + this.removeSync(destination); + const content = baseFs.readFileSync(source); + this.writeFileSync(destination, content); + } + } else if (stat.isSymbolicLink()) { + if (!exists || overwrite) { + if (exists) + this.removeSync(destination); + const target = baseFs.readlinkSync(source); + this.symlinkSync(convertPath(this.pathUtils, target), destination); + } + } else { + throw new Error(`Unsupported file type (file: ${source}, mode: 0o${stat.mode.toString(8).padStart(6, `0`)})`); + } + const mode = stat.mode & 511; + this.chmodSync(destination, mode); + } + async changeFilePromise(p, content, opts = {}) { + if (Buffer.isBuffer(content)) { + return this.changeFileBufferPromise(p, content, opts); + } else { + return this.changeFileTextPromise(p, content, opts); + } + } + async changeFileBufferPromise(p, content, { mode } = {}) { + let current = Buffer.alloc(0); + try { + current = await this.readFilePromise(p); + } catch (error) { + } + if (Buffer.compare(current, content) === 0) + return; + await this.writeFilePromise(p, content, { mode }); + } + async changeFileTextPromise(p, content, { automaticNewlines, mode } = {}) { + let current = ``; + try { + current = await this.readFilePromise(p, `utf8`); + } catch (error) { + } + const normalizedContent = automaticNewlines ? normalizeLineEndings(current, content) : content; + if (current === normalizedContent) + return; + await this.writeFilePromise(p, normalizedContent, { mode }); + } + changeFileSync(p, content, opts = {}) { + if (Buffer.isBuffer(content)) { + return this.changeFileBufferSync(p, content, opts); + } else { + return this.changeFileTextSync(p, content, opts); + } + } + changeFileBufferSync(p, content, { mode } = {}) { + let current = Buffer.alloc(0); + try { + current = this.readFileSync(p); + } catch (error) { + } + if (Buffer.compare(current, content) === 0) + return; + this.writeFileSync(p, content, { mode }); + } + changeFileTextSync(p, content, { automaticNewlines = false, mode } = {}) { + let current = ``; + try { + current = this.readFileSync(p, `utf8`); + } catch (error) { + } + const normalizedContent = automaticNewlines ? normalizeLineEndings(current, content) : content; + if (current === normalizedContent) + return; + this.writeFileSync(p, normalizedContent, { mode }); + } + async movePromise(fromP, toP) { + try { + await this.renamePromise(fromP, toP); + } catch (error) { + if (error.code === `EXDEV`) { + await this.copyPromise(toP, fromP); + await this.removePromise(fromP); + } else { + throw error; + } + } + } + moveSync(fromP, toP) { + try { + this.renameSync(fromP, toP); + } catch (error) { + if (error.code === `EXDEV`) { + this.copySync(toP, fromP); + this.removeSync(fromP); + } else { + throw error; + } + } + } + async lockPromise(affectedPath, callback) { + const lockPath = `${affectedPath}.flock`; + const interval = 1e3 / 60; + const startTime = Date.now(); + let fd = null; + const isAlive = async () => { + let pid; + try { + [pid] = await this.readJsonPromise(lockPath); + } catch (error) { + return Date.now() - startTime < 500; + } + try { + process.kill(pid, 0); + return true; + } catch (error) { + return false; + } + }; + while (fd === null) { + try { + fd = await this.openPromise(lockPath, `wx`); + } catch (error) { + if (error.code === `EEXIST`) { + if (!await isAlive()) { + try { + await this.unlinkPromise(lockPath); + continue; + } catch (error2) { + } + } + if (Date.now() - startTime < 60 * 1e3) { + await new Promise((resolve) => setTimeout(resolve, interval)); + } else { + throw new Error(`Couldn't acquire a lock in a reasonable time (via ${lockPath})`); + } + } else { + throw error; + } + } + } + await this.writePromise(fd, JSON.stringify([process.pid])); + try { + return await callback(); + } finally { + try { + await this.closePromise(fd); + await this.unlinkPromise(lockPath); + } catch (error) { + } + } + } + async readJsonPromise(p) { + const content = await this.readFilePromise(p, `utf8`); + try { + return JSON.parse(content); + } catch (error) { + error.message += ` (in ${p})`; + throw error; + } + } + readJsonSync(p) { + const content = this.readFileSync(p, `utf8`); + try { + return JSON.parse(content); + } catch (error) { + error.message += ` (in ${p})`; + throw error; + } + } + async writeJsonPromise(p, data) { + return await this.writeFilePromise(p, `${JSON.stringify(data, null, 2)} +`); + } + writeJsonSync(p, data) { + return this.writeFileSync(p, `${JSON.stringify(data, null, 2)} +`); + } + async preserveTimePromise(p, cb) { + const stat = await this.lstatPromise(p); + const result = await cb(); + if (typeof result !== `undefined`) + p = result; + if (this.lutimesPromise) { + await this.lutimesPromise(p, stat.atime, stat.mtime); + } else if (!stat.isSymbolicLink()) { + await this.utimesPromise(p, stat.atime, stat.mtime); + } + } + async preserveTimeSync(p, cb) { + const stat = this.lstatSync(p); + const result = cb(); + if (typeof result !== `undefined`) + p = result; + if (this.lutimesSync) { + this.lutimesSync(p, stat.atime, stat.mtime); + } else if (!stat.isSymbolicLink()) { + this.utimesSync(p, stat.atime, stat.mtime); + } + } +} +class BasePortableFakeFS extends FakeFS { + constructor() { + super(ppath); + } +} +function getEndOfLine(content) { + const matches = content.match(/\r?\n/g); + if (matches === null) + return EOL; + const crlf = matches.filter((nl) => nl === `\r +`).length; + const lf = matches.length - crlf; + return crlf > lf ? `\r +` : ` +`; +} +function normalizeLineEndings(originalContent, newContent) { + return newContent.replace(/\r?\n/g, getEndOfLine(originalContent)); +} + +class NodeFS extends BasePortableFakeFS { + constructor(realFs = fs) { + super(); + this.realFs = realFs; + if (typeof this.realFs.lutimes !== `undefined`) { + this.lutimesPromise = this.lutimesPromiseImpl; + this.lutimesSync = this.lutimesSyncImpl; + } + } + getExtractHint() { + return false; + } + getRealPath() { + return PortablePath.root; + } + resolve(p) { + return ppath.resolve(p); + } + async openPromise(p, flags, mode) { + return await new Promise((resolve, reject) => { + this.realFs.open(npath.fromPortablePath(p), flags, mode, this.makeCallback(resolve, reject)); + }); + } + openSync(p, flags, mode) { + return this.realFs.openSync(npath.fromPortablePath(p), flags, mode); + } + async opendirPromise(p, opts) { + return await new Promise((resolve, reject) => { + if (typeof opts !== `undefined`) { + this.realFs.opendir(npath.fromPortablePath(p), opts, this.makeCallback(resolve, reject)); + } else { + this.realFs.opendir(npath.fromPortablePath(p), this.makeCallback(resolve, reject)); + } + }).then((dir) => { + return Object.defineProperty(dir, `path`, { value: p, configurable: true, writable: true }); + }); + } + opendirSync(p, opts) { + const dir = typeof opts !== `undefined` ? this.realFs.opendirSync(npath.fromPortablePath(p), opts) : this.realFs.opendirSync(npath.fromPortablePath(p)); + return Object.defineProperty(dir, `path`, { value: p, configurable: true, writable: true }); + } + async readPromise(fd, buffer, offset = 0, length = 0, position = -1) { + return await new Promise((resolve, reject) => { + this.realFs.read(fd, buffer, offset, length, position, (error, bytesRead) => { + if (error) { + reject(error); + } else { + resolve(bytesRead); + } + }); + }); + } + readSync(fd, buffer, offset, length, position) { + return this.realFs.readSync(fd, buffer, offset, length, position); + } + async writePromise(fd, buffer, offset, length, position) { + return await new Promise((resolve, reject) => { + if (typeof buffer === `string`) { + return this.realFs.write(fd, buffer, offset, this.makeCallback(resolve, reject)); + } else { + return this.realFs.write(fd, buffer, offset, length, position, this.makeCallback(resolve, reject)); + } + }); + } + writeSync(fd, buffer, offset, length, position) { + if (typeof buffer === `string`) { + return this.realFs.writeSync(fd, buffer, offset); + } else { + return this.realFs.writeSync(fd, buffer, offset, length, position); + } + } + async closePromise(fd) { + await new Promise((resolve, reject) => { + this.realFs.close(fd, this.makeCallback(resolve, reject)); + }); + } + closeSync(fd) { + this.realFs.closeSync(fd); + } + createReadStream(p, opts) { + const realPath = p !== null ? npath.fromPortablePath(p) : p; + return this.realFs.createReadStream(realPath, opts); + } + createWriteStream(p, opts) { + const realPath = p !== null ? npath.fromPortablePath(p) : p; + return this.realFs.createWriteStream(realPath, opts); + } + async realpathPromise(p) { + return await new Promise((resolve, reject) => { + this.realFs.realpath(npath.fromPortablePath(p), {}, this.makeCallback(resolve, reject)); + }).then((path) => { + return npath.toPortablePath(path); + }); + } + realpathSync(p) { + return npath.toPortablePath(this.realFs.realpathSync(npath.fromPortablePath(p), {})); + } + async existsPromise(p) { + return await new Promise((resolve) => { + this.realFs.exists(npath.fromPortablePath(p), resolve); + }); + } + accessSync(p, mode) { + return this.realFs.accessSync(npath.fromPortablePath(p), mode); + } + async accessPromise(p, mode) { + return await new Promise((resolve, reject) => { + this.realFs.access(npath.fromPortablePath(p), mode, this.makeCallback(resolve, reject)); + }); + } + existsSync(p) { + return this.realFs.existsSync(npath.fromPortablePath(p)); + } + async statPromise(p, opts) { + return await new Promise((resolve, reject) => { + if (opts) { + this.realFs.stat(npath.fromPortablePath(p), opts, this.makeCallback(resolve, reject)); + } else { + this.realFs.stat(npath.fromPortablePath(p), this.makeCallback(resolve, reject)); + } + }); + } + statSync(p, opts) { + if (opts) { + return this.realFs.statSync(npath.fromPortablePath(p), opts); + } else { + return this.realFs.statSync(npath.fromPortablePath(p)); + } + } + async fstatPromise(fd, opts) { + return await new Promise((resolve, reject) => { + if (opts) { + this.realFs.fstat(fd, opts, this.makeCallback(resolve, reject)); + } else { + this.realFs.fstat(fd, this.makeCallback(resolve, reject)); + } + }); + } + fstatSync(fd, opts) { + if (opts) { + return this.realFs.fstatSync(fd, opts); + } else { + return this.realFs.fstatSync(fd); + } + } + async lstatPromise(p, opts) { + return await new Promise((resolve, reject) => { + if (opts) { + this.realFs.lstat(npath.fromPortablePath(p), opts, this.makeCallback(resolve, reject)); + } else { + this.realFs.lstat(npath.fromPortablePath(p), this.makeCallback(resolve, reject)); + } + }); + } + lstatSync(p, opts) { + if (opts) { + return this.realFs.lstatSync(npath.fromPortablePath(p), opts); + } else { + return this.realFs.lstatSync(npath.fromPortablePath(p)); + } + } + async fchmodPromise(fd, mask) { + return await new Promise((resolve, reject) => { + this.realFs.fchmod(fd, mask, this.makeCallback(resolve, reject)); + }); + } + fchmodSync(fd, mask) { + return this.realFs.fchmodSync(fd, mask); + } + async chmodPromise(p, mask) { + return await new Promise((resolve, reject) => { + this.realFs.chmod(npath.fromPortablePath(p), mask, this.makeCallback(resolve, reject)); + }); + } + chmodSync(p, mask) { + return this.realFs.chmodSync(npath.fromPortablePath(p), mask); + } + async fchownPromise(fd, uid, gid) { + return await new Promise((resolve, reject) => { + this.realFs.fchown(fd, uid, gid, this.makeCallback(resolve, reject)); + }); + } + fchownSync(fd, uid, gid) { + return this.realFs.fchownSync(fd, uid, gid); + } + async chownPromise(p, uid, gid) { + return await new Promise((resolve, reject) => { + this.realFs.chown(npath.fromPortablePath(p), uid, gid, this.makeCallback(resolve, reject)); + }); + } + chownSync(p, uid, gid) { + return this.realFs.chownSync(npath.fromPortablePath(p), uid, gid); + } + async renamePromise(oldP, newP) { + return await new Promise((resolve, reject) => { + this.realFs.rename(npath.fromPortablePath(oldP), npath.fromPortablePath(newP), this.makeCallback(resolve, reject)); + }); + } + renameSync(oldP, newP) { + return this.realFs.renameSync(npath.fromPortablePath(oldP), npath.fromPortablePath(newP)); + } + async copyFilePromise(sourceP, destP, flags = 0) { + return await new Promise((resolve, reject) => { + this.realFs.copyFile(npath.fromPortablePath(sourceP), npath.fromPortablePath(destP), flags, this.makeCallback(resolve, reject)); + }); + } + copyFileSync(sourceP, destP, flags = 0) { + return this.realFs.copyFileSync(npath.fromPortablePath(sourceP), npath.fromPortablePath(destP), flags); + } + async appendFilePromise(p, content, opts) { + return await new Promise((resolve, reject) => { + const fsNativePath = typeof p === `string` ? npath.fromPortablePath(p) : p; + if (opts) { + this.realFs.appendFile(fsNativePath, content, opts, this.makeCallback(resolve, reject)); + } else { + this.realFs.appendFile(fsNativePath, content, this.makeCallback(resolve, reject)); + } + }); + } + appendFileSync(p, content, opts) { + const fsNativePath = typeof p === `string` ? npath.fromPortablePath(p) : p; + if (opts) { + this.realFs.appendFileSync(fsNativePath, content, opts); + } else { + this.realFs.appendFileSync(fsNativePath, content); + } + } + async writeFilePromise(p, content, opts) { + return await new Promise((resolve, reject) => { + const fsNativePath = typeof p === `string` ? npath.fromPortablePath(p) : p; + if (opts) { + this.realFs.writeFile(fsNativePath, content, opts, this.makeCallback(resolve, reject)); + } else { + this.realFs.writeFile(fsNativePath, content, this.makeCallback(resolve, reject)); + } + }); + } + writeFileSync(p, content, opts) { + const fsNativePath = typeof p === `string` ? npath.fromPortablePath(p) : p; + if (opts) { + this.realFs.writeFileSync(fsNativePath, content, opts); + } else { + this.realFs.writeFileSync(fsNativePath, content); + } + } + async unlinkPromise(p) { + return await new Promise((resolve, reject) => { + this.realFs.unlink(npath.fromPortablePath(p), this.makeCallback(resolve, reject)); + }); + } + unlinkSync(p) { + return this.realFs.unlinkSync(npath.fromPortablePath(p)); + } + async utimesPromise(p, atime, mtime) { + return await new Promise((resolve, reject) => { + this.realFs.utimes(npath.fromPortablePath(p), atime, mtime, this.makeCallback(resolve, reject)); + }); + } + utimesSync(p, atime, mtime) { + this.realFs.utimesSync(npath.fromPortablePath(p), atime, mtime); + } + async lutimesPromiseImpl(p, atime, mtime) { + const lutimes = this.realFs.lutimes; + if (typeof lutimes === `undefined`) + throw ENOSYS(`unavailable Node binding`, `lutimes '${p}'`); + return await new Promise((resolve, reject) => { + lutimes.call(this.realFs, npath.fromPortablePath(p), atime, mtime, this.makeCallback(resolve, reject)); + }); + } + lutimesSyncImpl(p, atime, mtime) { + const lutimesSync = this.realFs.lutimesSync; + if (typeof lutimesSync === `undefined`) + throw ENOSYS(`unavailable Node binding`, `lutimes '${p}'`); + lutimesSync.call(this.realFs, npath.fromPortablePath(p), atime, mtime); + } + async mkdirPromise(p, opts) { + return await new Promise((resolve, reject) => { + this.realFs.mkdir(npath.fromPortablePath(p), opts, this.makeCallback(resolve, reject)); + }); + } + mkdirSync(p, opts) { + return this.realFs.mkdirSync(npath.fromPortablePath(p), opts); + } + async rmdirPromise(p, opts) { + return await new Promise((resolve, reject) => { + if (opts) { + this.realFs.rmdir(npath.fromPortablePath(p), opts, this.makeCallback(resolve, reject)); + } else { + this.realFs.rmdir(npath.fromPortablePath(p), this.makeCallback(resolve, reject)); + } + }); + } + rmdirSync(p, opts) { + return this.realFs.rmdirSync(npath.fromPortablePath(p), opts); + } + async linkPromise(existingP, newP) { + return await new Promise((resolve, reject) => { + this.realFs.link(npath.fromPortablePath(existingP), npath.fromPortablePath(newP), this.makeCallback(resolve, reject)); + }); + } + linkSync(existingP, newP) { + return this.realFs.linkSync(npath.fromPortablePath(existingP), npath.fromPortablePath(newP)); + } + async symlinkPromise(target, p, type) { + return await new Promise((resolve, reject) => { + this.realFs.symlink(npath.fromPortablePath(target.replace(/\/+$/, ``)), npath.fromPortablePath(p), type, this.makeCallback(resolve, reject)); + }); + } + symlinkSync(target, p, type) { + return this.realFs.symlinkSync(npath.fromPortablePath(target.replace(/\/+$/, ``)), npath.fromPortablePath(p), type); + } + async readFilePromise(p, encoding) { + return await new Promise((resolve, reject) => { + const fsNativePath = typeof p === `string` ? npath.fromPortablePath(p) : p; + this.realFs.readFile(fsNativePath, encoding, this.makeCallback(resolve, reject)); + }); + } + readFileSync(p, encoding) { + const fsNativePath = typeof p === `string` ? npath.fromPortablePath(p) : p; + return this.realFs.readFileSync(fsNativePath, encoding); + } + async readdirPromise(p, opts) { + return await new Promise((resolve, reject) => { + if (opts == null ? void 0 : opts.withFileTypes) { + this.realFs.readdir(npath.fromPortablePath(p), { withFileTypes: true }, this.makeCallback(resolve, reject)); + } else { + this.realFs.readdir(npath.fromPortablePath(p), this.makeCallback((value) => resolve(value), reject)); + } + }); + } + readdirSync(p, opts) { + if (opts == null ? void 0 : opts.withFileTypes) { + return this.realFs.readdirSync(npath.fromPortablePath(p), { withFileTypes: true }); + } else { + return this.realFs.readdirSync(npath.fromPortablePath(p)); + } + } + async readlinkPromise(p) { + return await new Promise((resolve, reject) => { + this.realFs.readlink(npath.fromPortablePath(p), this.makeCallback(resolve, reject)); + }).then((path) => { + return npath.toPortablePath(path); + }); + } + readlinkSync(p) { + return npath.toPortablePath(this.realFs.readlinkSync(npath.fromPortablePath(p))); + } + async truncatePromise(p, len) { + return await new Promise((resolve, reject) => { + this.realFs.truncate(npath.fromPortablePath(p), len, this.makeCallback(resolve, reject)); + }); + } + truncateSync(p, len) { + return this.realFs.truncateSync(npath.fromPortablePath(p), len); + } + async ftruncatePromise(fd, len) { + return await new Promise((resolve, reject) => { + this.realFs.ftruncate(fd, len, this.makeCallback(resolve, reject)); + }); + } + ftruncateSync(fd, len) { + return this.realFs.ftruncateSync(fd, len); + } + watch(p, a, b) { + return this.realFs.watch( + npath.fromPortablePath(p), + a, + b + ); + } + watchFile(p, a, b) { + return this.realFs.watchFile( + npath.fromPortablePath(p), + a, + b + ); + } + unwatchFile(p, cb) { + return this.realFs.unwatchFile(npath.fromPortablePath(p), cb); + } + makeCallback(resolve, reject) { + return (err, result) => { + if (err) { + reject(err); + } else { + resolve(result); + } + }; + } +} + +class ProxiedFS extends FakeFS { + getExtractHint(hints) { + return this.baseFs.getExtractHint(hints); + } + resolve(path) { + return this.mapFromBase(this.baseFs.resolve(this.mapToBase(path))); + } + getRealPath() { + return this.mapFromBase(this.baseFs.getRealPath()); + } + async openPromise(p, flags, mode) { + return this.baseFs.openPromise(this.mapToBase(p), flags, mode); + } + openSync(p, flags, mode) { + return this.baseFs.openSync(this.mapToBase(p), flags, mode); + } + async opendirPromise(p, opts) { + return Object.assign(await this.baseFs.opendirPromise(this.mapToBase(p), opts), { path: p }); + } + opendirSync(p, opts) { + return Object.assign(this.baseFs.opendirSync(this.mapToBase(p), opts), { path: p }); + } + async readPromise(fd, buffer, offset, length, position) { + return await this.baseFs.readPromise(fd, buffer, offset, length, position); + } + readSync(fd, buffer, offset, length, position) { + return this.baseFs.readSync(fd, buffer, offset, length, position); + } + async writePromise(fd, buffer, offset, length, position) { + if (typeof buffer === `string`) { + return await this.baseFs.writePromise(fd, buffer, offset); + } else { + return await this.baseFs.writePromise(fd, buffer, offset, length, position); + } + } + writeSync(fd, buffer, offset, length, position) { + if (typeof buffer === `string`) { + return this.baseFs.writeSync(fd, buffer, offset); + } else { + return this.baseFs.writeSync(fd, buffer, offset, length, position); + } + } + async closePromise(fd) { + return this.baseFs.closePromise(fd); + } + closeSync(fd) { + this.baseFs.closeSync(fd); + } + createReadStream(p, opts) { + return this.baseFs.createReadStream(p !== null ? this.mapToBase(p) : p, opts); + } + createWriteStream(p, opts) { + return this.baseFs.createWriteStream(p !== null ? this.mapToBase(p) : p, opts); + } + async realpathPromise(p) { + return this.mapFromBase(await this.baseFs.realpathPromise(this.mapToBase(p))); + } + realpathSync(p) { + return this.mapFromBase(this.baseFs.realpathSync(this.mapToBase(p))); + } + async existsPromise(p) { + return this.baseFs.existsPromise(this.mapToBase(p)); + } + existsSync(p) { + return this.baseFs.existsSync(this.mapToBase(p)); + } + accessSync(p, mode) { + return this.baseFs.accessSync(this.mapToBase(p), mode); + } + async accessPromise(p, mode) { + return this.baseFs.accessPromise(this.mapToBase(p), mode); + } + async statPromise(p, opts) { + return this.baseFs.statPromise(this.mapToBase(p), opts); + } + statSync(p, opts) { + return this.baseFs.statSync(this.mapToBase(p), opts); + } + async fstatPromise(fd, opts) { + return this.baseFs.fstatPromise(fd, opts); + } + fstatSync(fd, opts) { + return this.baseFs.fstatSync(fd, opts); + } + lstatPromise(p, opts) { + return this.baseFs.lstatPromise(this.mapToBase(p), opts); + } + lstatSync(p, opts) { + return this.baseFs.lstatSync(this.mapToBase(p), opts); + } + async fchmodPromise(fd, mask) { + return this.baseFs.fchmodPromise(fd, mask); + } + fchmodSync(fd, mask) { + return this.baseFs.fchmodSync(fd, mask); + } + async chmodPromise(p, mask) { + return this.baseFs.chmodPromise(this.mapToBase(p), mask); + } + chmodSync(p, mask) { + return this.baseFs.chmodSync(this.mapToBase(p), mask); + } + async fchownPromise(fd, uid, gid) { + return this.baseFs.fchownPromise(fd, uid, gid); + } + fchownSync(fd, uid, gid) { + return this.baseFs.fchownSync(fd, uid, gid); + } + async chownPromise(p, uid, gid) { + return this.baseFs.chownPromise(this.mapToBase(p), uid, gid); + } + chownSync(p, uid, gid) { + return this.baseFs.chownSync(this.mapToBase(p), uid, gid); + } + async renamePromise(oldP, newP) { + return this.baseFs.renamePromise(this.mapToBase(oldP), this.mapToBase(newP)); + } + renameSync(oldP, newP) { + return this.baseFs.renameSync(this.mapToBase(oldP), this.mapToBase(newP)); + } + async copyFilePromise(sourceP, destP, flags = 0) { + return this.baseFs.copyFilePromise(this.mapToBase(sourceP), this.mapToBase(destP), flags); + } + copyFileSync(sourceP, destP, flags = 0) { + return this.baseFs.copyFileSync(this.mapToBase(sourceP), this.mapToBase(destP), flags); + } + async appendFilePromise(p, content, opts) { + return this.baseFs.appendFilePromise(this.fsMapToBase(p), content, opts); + } + appendFileSync(p, content, opts) { + return this.baseFs.appendFileSync(this.fsMapToBase(p), content, opts); + } + async writeFilePromise(p, content, opts) { + return this.baseFs.writeFilePromise(this.fsMapToBase(p), content, opts); + } + writeFileSync(p, content, opts) { + return this.baseFs.writeFileSync(this.fsMapToBase(p), content, opts); + } + async unlinkPromise(p) { + return this.baseFs.unlinkPromise(this.mapToBase(p)); + } + unlinkSync(p) { + return this.baseFs.unlinkSync(this.mapToBase(p)); + } + async utimesPromise(p, atime, mtime) { + return this.baseFs.utimesPromise(this.mapToBase(p), atime, mtime); + } + utimesSync(p, atime, mtime) { + return this.baseFs.utimesSync(this.mapToBase(p), atime, mtime); + } + async mkdirPromise(p, opts) { + return this.baseFs.mkdirPromise(this.mapToBase(p), opts); + } + mkdirSync(p, opts) { + return this.baseFs.mkdirSync(this.mapToBase(p), opts); + } + async rmdirPromise(p, opts) { + return this.baseFs.rmdirPromise(this.mapToBase(p), opts); + } + rmdirSync(p, opts) { + return this.baseFs.rmdirSync(this.mapToBase(p), opts); + } + async linkPromise(existingP, newP) { + return this.baseFs.linkPromise(this.mapToBase(existingP), this.mapToBase(newP)); + } + linkSync(existingP, newP) { + return this.baseFs.linkSync(this.mapToBase(existingP), this.mapToBase(newP)); + } + async symlinkPromise(target, p, type) { + const mappedP = this.mapToBase(p); + if (this.pathUtils.isAbsolute(target)) + return this.baseFs.symlinkPromise(this.mapToBase(target), mappedP, type); + const mappedAbsoluteTarget = this.mapToBase(this.pathUtils.join(this.pathUtils.dirname(p), target)); + const mappedTarget = this.baseFs.pathUtils.relative(this.baseFs.pathUtils.dirname(mappedP), mappedAbsoluteTarget); + return this.baseFs.symlinkPromise(mappedTarget, mappedP, type); + } + symlinkSync(target, p, type) { + const mappedP = this.mapToBase(p); + if (this.pathUtils.isAbsolute(target)) + return this.baseFs.symlinkSync(this.mapToBase(target), mappedP, type); + const mappedAbsoluteTarget = this.mapToBase(this.pathUtils.join(this.pathUtils.dirname(p), target)); + const mappedTarget = this.baseFs.pathUtils.relative(this.baseFs.pathUtils.dirname(mappedP), mappedAbsoluteTarget); + return this.baseFs.symlinkSync(mappedTarget, mappedP, type); + } + async readFilePromise(p, encoding) { + if (encoding === `utf8`) { + return this.baseFs.readFilePromise(this.fsMapToBase(p), encoding); + } else { + return this.baseFs.readFilePromise(this.fsMapToBase(p), encoding); + } + } + readFileSync(p, encoding) { + if (encoding === `utf8`) { + return this.baseFs.readFileSync(this.fsMapToBase(p), encoding); + } else { + return this.baseFs.readFileSync(this.fsMapToBase(p), encoding); + } + } + async readdirPromise(p, opts) { + return this.baseFs.readdirPromise(this.mapToBase(p), opts); + } + readdirSync(p, opts) { + return this.baseFs.readdirSync(this.mapToBase(p), opts); + } + async readlinkPromise(p) { + return this.mapFromBase(await this.baseFs.readlinkPromise(this.mapToBase(p))); + } + readlinkSync(p) { + return this.mapFromBase(this.baseFs.readlinkSync(this.mapToBase(p))); + } + async truncatePromise(p, len) { + return this.baseFs.truncatePromise(this.mapToBase(p), len); + } + truncateSync(p, len) { + return this.baseFs.truncateSync(this.mapToBase(p), len); + } + async ftruncatePromise(fd, len) { + return this.baseFs.ftruncatePromise(fd, len); + } + ftruncateSync(fd, len) { + return this.baseFs.ftruncateSync(fd, len); + } + watch(p, a, b) { + return this.baseFs.watch( + this.mapToBase(p), + a, + b + ); + } + watchFile(p, a, b) { + return this.baseFs.watchFile( + this.mapToBase(p), + a, + b + ); + } + unwatchFile(p, cb) { + return this.baseFs.unwatchFile(this.mapToBase(p), cb); + } + fsMapToBase(p) { + if (typeof p === `number`) { + return p; + } else { + return this.mapToBase(p); + } + } +} + +const NUMBER_REGEXP = /^[0-9]+$/; +const VIRTUAL_REGEXP = /^(\/(?:[^/]+\/)*?(?:\$\$virtual|__virtual__))((?:\/((?:[^/]+-)?[a-f0-9]+)(?:\/([^/]+))?)?((?:\/.*)?))$/; +const VALID_COMPONENT = /^([^/]+-)?[a-f0-9]+$/; +class VirtualFS extends ProxiedFS { + constructor({ baseFs = new NodeFS() } = {}) { + super(ppath); + this.baseFs = baseFs; + } + static makeVirtualPath(base, component, to) { + if (ppath.basename(base) !== `__virtual__`) + throw new Error(`Assertion failed: Virtual folders must be named "__virtual__"`); + if (!ppath.basename(component).match(VALID_COMPONENT)) + throw new Error(`Assertion failed: Virtual components must be ended by an hexadecimal hash`); + const target = ppath.relative(ppath.dirname(base), to); + const segments = target.split(`/`); + let depth = 0; + while (depth < segments.length && segments[depth] === `..`) + depth += 1; + const finalSegments = segments.slice(depth); + const fullVirtualPath = ppath.join(base, component, String(depth), ...finalSegments); + return fullVirtualPath; + } + static resolveVirtual(p) { + const match = p.match(VIRTUAL_REGEXP); + if (!match || !match[3] && match[5]) + return p; + const target = ppath.dirname(match[1]); + if (!match[3] || !match[4]) + return target; + const isnum = NUMBER_REGEXP.test(match[4]); + if (!isnum) + return p; + const depth = Number(match[4]); + const backstep = `../`.repeat(depth); + const subpath = match[5] || `.`; + return VirtualFS.resolveVirtual(ppath.join(target, backstep, subpath)); + } + getExtractHint(hints) { + return this.baseFs.getExtractHint(hints); + } + getRealPath() { + return this.baseFs.getRealPath(); + } + realpathSync(p) { + const match = p.match(VIRTUAL_REGEXP); + if (!match) + return this.baseFs.realpathSync(p); + if (!match[5]) + return p; + const realpath = this.baseFs.realpathSync(this.mapToBase(p)); + return VirtualFS.makeVirtualPath(match[1], match[3], realpath); + } + async realpathPromise(p) { + const match = p.match(VIRTUAL_REGEXP); + if (!match) + return await this.baseFs.realpathPromise(p); + if (!match[5]) + return p; + const realpath = await this.baseFs.realpathPromise(this.mapToBase(p)); + return VirtualFS.makeVirtualPath(match[1], match[3], realpath); + } + mapToBase(p) { + if (p === ``) + return p; + if (this.pathUtils.isAbsolute(p)) + return VirtualFS.resolveVirtual(p); + const resolvedRoot = VirtualFS.resolveVirtual(this.baseFs.resolve(PortablePath.dot)); + const resolvedP = VirtualFS.resolveVirtual(this.baseFs.resolve(p)); + return ppath.relative(resolvedRoot, resolvedP) || PortablePath.dot; + } + mapFromBase(p) { + return p; + } +} const builtinModules = new Set(Module.builtinModules || Object.keys(process.binding(`natives`))); const isBuiltinModule = (request) => request.startsWith(`node:`) || builtinModules.has(request); @@ -92,7 +1355,12 @@ function readPackage(requestPath) { return JSON.parse(fs.readFileSync(jsonPath, `utf8`)); } -async function tryReadFile(path2) { +const [major, minor] = process.versions.node.split(`.`).map((value) => parseInt(value, 10)); +const HAS_CONSOLIDATED_HOOKS = major > 16 || major === 16 && minor >= 12; +const HAS_UNFLAGGED_JSON_MODULES = major > 17 || major === 17 && minor >= 5 || major === 16 && minor >= 15; +const HAS_JSON_IMPORT_ASSERTION_REQUIREMENT = major > 17 || major === 17 && minor >= 1 || major === 16 && minor > 14; + +async function tryReadFile$1(path2) { try { return await fs.promises.readFile(path2, `utf8`); } catch (error) { @@ -103,7 +1371,7 @@ async function tryReadFile(path2) { } function tryParseURL(str, base) { try { - return new URL(str, base); + return new URL$1(str, base); } catch { return null; } @@ -123,10 +1391,16 @@ function getFileFormat(filepath) { return `commonjs`; } case `.wasm`: { - throw new Error(`Unknown file extension ".wasm" for ${filepath}`); + throw new Error( + `Unknown file extension ".wasm" for ${filepath}` + ); } case `.json`: { - throw new Error(`Unknown file extension ".json" for ${filepath}`); + if (HAS_UNFLAGGED_JSON_MODULES) + return `json`; + throw new Error( + `Unknown file extension ".json" for ${filepath}` + ); } case `.js`: { const pkg = readPackageScope(filepath); @@ -170,6 +1444,7 @@ async function getSource$1(urlString, context, defaultGetSource) { } async function load$1(urlString, context, nextLoad) { + var _a; const url = tryParseURL(urlString); if ((url == null ? void 0 : url.protocol) !== `file:`) return nextLoad(urlString, context, nextLoad); @@ -177,6 +1452,20 @@ async function load$1(urlString, context, nextLoad) { const format = getFileFormat(filePath); if (!format) return nextLoad(urlString, context, nextLoad); + if (HAS_JSON_IMPORT_ASSERTION_REQUIREMENT && format === `json` && ((_a = context.importAssertions) == null ? void 0 : _a.type) !== `json`) { + const err = new TypeError(`[ERR_IMPORT_ASSERTION_TYPE_MISSING]: Module "${urlString}" needs an import assertion of type "json"`); + err.code = `ERR_IMPORT_ASSERTION_TYPE_MISSING`; + throw err; + } + if (process.env.WATCH_REPORT_DEPENDENCIES && process.send) { + process.send({ + "watch:import": pathToFileURL( + npath.fromPortablePath( + VirtualFS.resolveVirtual(npath.toPortablePath(filePath)) + ) + ).href + }); + } return { format, source: await fs.promises.readFile(filePath, `utf8`), @@ -184,11 +1473,488 @@ async function load$1(urlString, context, nextLoad) { }; } +const ArrayIsArray = Array.isArray; +const JSONStringify = JSON.stringify; +const ObjectGetOwnPropertyNames = Object.getOwnPropertyNames; +const ObjectPrototypeHasOwnProperty = (obj, prop) => Object.prototype.hasOwnProperty.call(obj, prop); +const RegExpPrototypeExec = (obj, string) => RegExp.prototype.exec.call(obj, string); +const RegExpPrototypeSymbolReplace = (obj, ...rest) => RegExp.prototype[Symbol.replace].apply(obj, rest); +const StringPrototypeEndsWith = (str, ...rest) => String.prototype.endsWith.apply(str, rest); +const StringPrototypeIncludes = (str, ...rest) => String.prototype.includes.apply(str, rest); +const StringPrototypeLastIndexOf = (str, ...rest) => String.prototype.lastIndexOf.apply(str, rest); +const StringPrototypeIndexOf = (str, ...rest) => String.prototype.indexOf.apply(str, rest); +const StringPrototypeReplace = (str, ...rest) => String.prototype.replace.apply(str, rest); +const StringPrototypeSlice = (str, ...rest) => String.prototype.slice.apply(str, rest); +const StringPrototypeStartsWith = (str, ...rest) => String.prototype.startsWith.apply(str, rest); +const SafeMap = Map; +const JSONParse = JSON.parse; + +function createErrorType(code, messageCreator, errorType) { + return class extends errorType { + constructor(...args) { + super(messageCreator(...args)); + this.code = code; + this.name = `${errorType.name} [${code}]`; + } + }; +} +const ERR_PACKAGE_IMPORT_NOT_DEFINED = createErrorType( + `ERR_PACKAGE_IMPORT_NOT_DEFINED`, + (specifier, packagePath, base) => { + return `Package import specifier "${specifier}" is not defined${packagePath ? ` in package ${packagePath}package.json` : ``} imported from ${base}`; + }, + TypeError +); +const ERR_INVALID_MODULE_SPECIFIER = createErrorType( + `ERR_INVALID_MODULE_SPECIFIER`, + (request, reason, base = void 0) => { + return `Invalid module "${request}" ${reason}${base ? ` imported from ${base}` : ``}`; + }, + TypeError +); +const ERR_INVALID_PACKAGE_TARGET = createErrorType( + `ERR_INVALID_PACKAGE_TARGET`, + (pkgPath, key, target, isImport = false, base = void 0) => { + const relError = typeof target === `string` && !isImport && target.length && !StringPrototypeStartsWith(target, `./`); + if (key === `.`) { + assert(isImport === false); + return `Invalid "exports" main target ${JSONStringify(target)} defined in the package config ${pkgPath}package.json${base ? ` imported from ${base}` : ``}${relError ? `; targets must start with "./"` : ``}`; + } + return `Invalid "${isImport ? `imports` : `exports`}" target ${JSONStringify( + target + )} defined for '${key}' in the package config ${pkgPath}package.json${base ? ` imported from ${base}` : ``}${relError ? `; targets must start with "./"` : ``}`; + }, + Error +); +const ERR_INVALID_PACKAGE_CONFIG = createErrorType( + `ERR_INVALID_PACKAGE_CONFIG`, + (path, base, message) => { + return `Invalid package config ${path}${base ? ` while importing ${base}` : ``}${message ? `. ${message}` : ``}`; + }, + Error +); + +function filterOwnProperties(source, keys) { + const filtered = /* @__PURE__ */ Object.create(null); + for (let i = 0; i < keys.length; i++) { + const key = keys[i]; + if (ObjectPrototypeHasOwnProperty(source, key)) { + filtered[key] = source[key]; + } + } + return filtered; +} + +const packageJSONCache = new SafeMap(); +function getPackageConfig(path, specifier, base, readFileSyncFn) { + const existing = packageJSONCache.get(path); + if (existing !== void 0) { + return existing; + } + const source = readFileSyncFn(path); + if (source === void 0) { + const packageConfig2 = { + pjsonPath: path, + exists: false, + main: void 0, + name: void 0, + type: "none", + exports: void 0, + imports: void 0 + }; + packageJSONCache.set(path, packageConfig2); + return packageConfig2; + } + let packageJSON; + try { + packageJSON = JSONParse(source); + } catch (error) { + throw new ERR_INVALID_PACKAGE_CONFIG( + path, + (base ? `"${specifier}" from ` : "") + fileURLToPath(base || specifier), + error.message + ); + } + let { imports, main, name, type } = filterOwnProperties(packageJSON, [ + "imports", + "main", + "name", + "type" + ]); + const exports = ObjectPrototypeHasOwnProperty(packageJSON, "exports") ? packageJSON.exports : void 0; + if (typeof imports !== "object" || imports === null) { + imports = void 0; + } + if (typeof main !== "string") { + main = void 0; + } + if (typeof name !== "string") { + name = void 0; + } + if (type !== "module" && type !== "commonjs") { + type = "none"; + } + const packageConfig = { + pjsonPath: path, + exists: true, + main, + name, + type, + exports, + imports + }; + packageJSONCache.set(path, packageConfig); + return packageConfig; +} +function getPackageScopeConfig(resolved, readFileSyncFn) { + let packageJSONUrl = new URL("./package.json", resolved); + while (true) { + const packageJSONPath2 = packageJSONUrl.pathname; + if (StringPrototypeEndsWith(packageJSONPath2, "node_modules/package.json")) { + break; + } + const packageConfig2 = getPackageConfig( + fileURLToPath(packageJSONUrl), + resolved, + void 0, + readFileSyncFn + ); + if (packageConfig2.exists) { + return packageConfig2; + } + const lastPackageJSONUrl = packageJSONUrl; + packageJSONUrl = new URL("../package.json", packageJSONUrl); + if (packageJSONUrl.pathname === lastPackageJSONUrl.pathname) { + break; + } + } + const packageJSONPath = fileURLToPath(packageJSONUrl); + const packageConfig = { + pjsonPath: packageJSONPath, + exists: false, + main: void 0, + name: void 0, + type: "none", + exports: void 0, + imports: void 0 + }; + packageJSONCache.set(packageJSONPath, packageConfig); + return packageConfig; +} + +/** + @license + Copyright Node.js contributors. All rights reserved. + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to + deal in the Software without restriction, including without limitation the + rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + sell copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + IN THE SOFTWARE. +*/ +function throwImportNotDefined(specifier, packageJSONUrl, base) { + throw new ERR_PACKAGE_IMPORT_NOT_DEFINED( + specifier, + packageJSONUrl && fileURLToPath(new URL(".", packageJSONUrl)), + fileURLToPath(base) + ); +} +function throwInvalidSubpath(subpath, packageJSONUrl, internal, base) { + const reason = `request is not a valid subpath for the "${internal ? "imports" : "exports"}" resolution of ${fileURLToPath(packageJSONUrl)}`; + throw new ERR_INVALID_MODULE_SPECIFIER( + subpath, + reason, + base && fileURLToPath(base) + ); +} +function throwInvalidPackageTarget(subpath, target, packageJSONUrl, internal, base) { + if (typeof target === "object" && target !== null) { + target = JSONStringify(target, null, ""); + } else { + target = `${target}`; + } + throw new ERR_INVALID_PACKAGE_TARGET( + fileURLToPath(new URL(".", packageJSONUrl)), + subpath, + target, + internal, + base && fileURLToPath(base) + ); +} +const invalidSegmentRegEx = /(^|\\|\/)((\.|%2e)(\.|%2e)?|(n|%6e|%4e)(o|%6f|%4f)(d|%64|%44)(e|%65|%45)(_|%5f)(m|%6d|%4d)(o|%6f|%4f)(d|%64|%44)(u|%75|%55)(l|%6c|%4c)(e|%65|%45)(s|%73|%53))(\\|\/|$)/i; +const patternRegEx = /\*/g; +function resolvePackageTargetString(target, subpath, match, packageJSONUrl, base, pattern, internal, conditions) { + if (subpath !== "" && !pattern && target[target.length - 1] !== "/") + throwInvalidPackageTarget(match, target, packageJSONUrl, internal, base); + if (!StringPrototypeStartsWith(target, "./")) { + if (internal && !StringPrototypeStartsWith(target, "../") && !StringPrototypeStartsWith(target, "/")) { + let isURL = false; + try { + new URL(target); + isURL = true; + } catch { + } + if (!isURL) { + const exportTarget = pattern ? RegExpPrototypeSymbolReplace(patternRegEx, target, () => subpath) : target + subpath; + return exportTarget; + } + } + throwInvalidPackageTarget(match, target, packageJSONUrl, internal, base); + } + if (RegExpPrototypeExec( + invalidSegmentRegEx, + StringPrototypeSlice(target, 2) + ) !== null) + throwInvalidPackageTarget(match, target, packageJSONUrl, internal, base); + const resolved = new URL(target, packageJSONUrl); + const resolvedPath = resolved.pathname; + const packagePath = new URL(".", packageJSONUrl).pathname; + if (!StringPrototypeStartsWith(resolvedPath, packagePath)) + throwInvalidPackageTarget(match, target, packageJSONUrl, internal, base); + if (subpath === "") + return resolved; + if (RegExpPrototypeExec(invalidSegmentRegEx, subpath) !== null) { + const request = pattern ? StringPrototypeReplace(match, "*", () => subpath) : match + subpath; + throwInvalidSubpath(request, packageJSONUrl, internal, base); + } + if (pattern) { + return new URL( + RegExpPrototypeSymbolReplace(patternRegEx, resolved.href, () => subpath) + ); + } + return new URL(subpath, resolved); +} +function isArrayIndex(key) { + const keyNum = +key; + if (`${keyNum}` !== key) + return false; + return keyNum >= 0 && keyNum < 4294967295; +} +function resolvePackageTarget(packageJSONUrl, target, subpath, packageSubpath, base, pattern, internal, conditions) { + if (typeof target === "string") { + return resolvePackageTargetString( + target, + subpath, + packageSubpath, + packageJSONUrl, + base, + pattern, + internal); + } else if (ArrayIsArray(target)) { + if (target.length === 0) { + return null; + } + let lastException; + for (let i = 0; i < target.length; i++) { + const targetItem = target[i]; + let resolveResult; + try { + resolveResult = resolvePackageTarget( + packageJSONUrl, + targetItem, + subpath, + packageSubpath, + base, + pattern, + internal, + conditions + ); + } catch (e) { + lastException = e; + if (e.code === "ERR_INVALID_PACKAGE_TARGET") { + continue; + } + throw e; + } + if (resolveResult === void 0) { + continue; + } + if (resolveResult === null) { + lastException = null; + continue; + } + return resolveResult; + } + if (lastException === void 0 || lastException === null) + return lastException; + throw lastException; + } else if (typeof target === "object" && target !== null) { + const keys = ObjectGetOwnPropertyNames(target); + for (let i = 0; i < keys.length; i++) { + const key = keys[i]; + if (isArrayIndex(key)) { + throw new ERR_INVALID_PACKAGE_CONFIG( + fileURLToPath(packageJSONUrl), + base, + '"exports" cannot contain numeric property keys.' + ); + } + } + for (let i = 0; i < keys.length; i++) { + const key = keys[i]; + if (key === "default" || conditions.has(key)) { + const conditionalTarget = target[key]; + const resolveResult = resolvePackageTarget( + packageJSONUrl, + conditionalTarget, + subpath, + packageSubpath, + base, + pattern, + internal, + conditions + ); + if (resolveResult === void 0) + continue; + return resolveResult; + } + } + return void 0; + } else if (target === null) { + return null; + } + throwInvalidPackageTarget( + packageSubpath, + target, + packageJSONUrl, + internal, + base + ); +} +function patternKeyCompare(a, b) { + const aPatternIndex = StringPrototypeIndexOf(a, "*"); + const bPatternIndex = StringPrototypeIndexOf(b, "*"); + const baseLenA = aPatternIndex === -1 ? a.length : aPatternIndex + 1; + const baseLenB = bPatternIndex === -1 ? b.length : bPatternIndex + 1; + if (baseLenA > baseLenB) + return -1; + if (baseLenB > baseLenA) + return 1; + if (aPatternIndex === -1) + return 1; + if (bPatternIndex === -1) + return -1; + if (a.length > b.length) + return -1; + if (b.length > a.length) + return 1; + return 0; +} +function packageImportsResolve({ + name, + base, + conditions, + readFileSyncFn +}) { + if (name === "#" || StringPrototypeStartsWith(name, "#/") || StringPrototypeEndsWith(name, "/")) { + const reason = "is not a valid internal imports specifier name"; + throw new ERR_INVALID_MODULE_SPECIFIER(name, reason, fileURLToPath(base)); + } + let packageJSONUrl; + const packageConfig = getPackageScopeConfig(base, readFileSyncFn); + if (packageConfig.exists) { + packageJSONUrl = pathToFileURL(packageConfig.pjsonPath); + const imports = packageConfig.imports; + if (imports) { + if (ObjectPrototypeHasOwnProperty(imports, name) && !StringPrototypeIncludes(name, "*")) { + const resolveResult = resolvePackageTarget( + packageJSONUrl, + imports[name], + "", + name, + base, + false, + true, + conditions + ); + if (resolveResult != null) { + return resolveResult; + } + } else { + let bestMatch = ""; + let bestMatchSubpath; + const keys = ObjectGetOwnPropertyNames(imports); + for (let i = 0; i < keys.length; i++) { + const key = keys[i]; + const patternIndex = StringPrototypeIndexOf(key, "*"); + if (patternIndex !== -1 && StringPrototypeStartsWith( + name, + StringPrototypeSlice(key, 0, patternIndex) + )) { + const patternTrailer = StringPrototypeSlice(key, patternIndex + 1); + if (name.length >= key.length && StringPrototypeEndsWith(name, patternTrailer) && patternKeyCompare(bestMatch, key) === 1 && StringPrototypeLastIndexOf(key, "*") === patternIndex) { + bestMatch = key; + bestMatchSubpath = StringPrototypeSlice( + name, + patternIndex, + name.length - patternTrailer.length + ); + } + } + } + if (bestMatch) { + const target = imports[bestMatch]; + const resolveResult = resolvePackageTarget( + packageJSONUrl, + target, + bestMatchSubpath, + bestMatch, + base, + true, + true, + conditions + ); + if (resolveResult != null) { + return resolveResult; + } + } + } + } + } + throwImportNotDefined(name, packageJSONUrl, base); +} + const pathRegExp = /^(?![a-zA-Z]:[\\/]|\\\\|\.{0,2}(?:\/|$))((?:node:)?(?:@[^/]+\/)?[^/]+)\/*(.*|)$/; const isRelativeRegexp = /^\.{0,2}\//; +function tryReadFile(filePath) { + try { + return fs.readFileSync(filePath, `utf8`); + } catch (err) { + if (err.code === `ENOENT`) + return void 0; + throw err; + } +} +async function resolvePrivateRequest(specifier, issuer, context, nextResolve) { + const resolved = packageImportsResolve({ + name: specifier, + base: pathToFileURL(issuer), + conditions: new Set(context.conditions), + readFileSyncFn: tryReadFile + }); + if (resolved instanceof URL) { + return { url: resolved.href, shortCircuit: true }; + } else { + if (resolved.startsWith(`#`)) + throw new Error(`Mapping from one private import to another isn't allowed`); + return resolve$1(resolved, context, nextResolve); + } +} async function resolve$1(originalSpecifier, context, nextResolve) { var _a; - const {findPnpApi} = moduleExports; + const { findPnpApi } = moduleExports; if (!findPnpApi || isBuiltinModule(originalSpecifier)) return nextResolve(originalSpecifier, context, nextResolve); let specifier = originalSpecifier; @@ -198,11 +1964,13 @@ async function resolve$1(originalSpecifier, context, nextResolve) { return nextResolve(originalSpecifier, context, nextResolve); specifier = fileURLToPath(url); } - const {parentURL, conditions = []} = context; + const { parentURL, conditions = [] } = context; const issuer = parentURL ? fileURLToPath(parentURL) : process.cwd(); const pnpapi = (_a = findPnpApi(issuer)) != null ? _a : url ? findPnpApi(specifier) : null; if (!pnpapi) return nextResolve(originalSpecifier, context, nextResolve); + if (specifier.startsWith(`#`)) + return resolvePrivateRequest(specifier, issuer, context, nextResolve); const dependencyNameMatch = specifier.match(pathRegExp); let allowLegacyResolve = false; if (dependencyNameMatch) { @@ -210,7 +1978,7 @@ async function resolve$1(originalSpecifier, context, nextResolve) { if (subPath === ``) { const resolved = pnpapi.resolveToUnqualified(`${dependencyName}/package.json`, issuer); if (resolved) { - const content = await tryReadFile(resolved); + const content = await tryReadFile$1(resolved); if (content) { const pkg = JSON.parse(content); allowLegacyResolve = pkg.exports == null; @@ -239,10 +2007,11 @@ async function resolve$1(originalSpecifier, context, nextResolve) { const binding = process.binding(`fs`); const originalfstat = binding.fstat; -const ZIP_FD = 2147483648; +const ZIP_MASK = 4278190080; +const ZIP_MAGIC = 704643072; binding.fstat = function(...args) { const [fd, useBigint, req] = args; - if ((fd & ZIP_FD) !== 0 && useBigint === false && req === void 0) { + if ((fd & ZIP_MASK) === ZIP_MAGIC && useBigint === false && req === void 0) { try { const stats = fs.fstatSync(fd); return new Float64Array([ @@ -263,11 +2032,9 @@ binding.fstat = function(...args) { return originalfstat.apply(this, args); }; -const [major, minor] = process.versions.node.split(`.`).map((value) => parseInt(value, 10)); -const hasConsolidatedHooks = major > 16 || major === 16 && minor >= 12; const resolve = resolve$1; -const getFormat = hasConsolidatedHooks ? void 0 : getFormat$1; -const getSource = hasConsolidatedHooks ? void 0 : getSource$1; -const load = hasConsolidatedHooks ? load$1 : void 0; +const getFormat = HAS_CONSOLIDATED_HOOKS ? void 0 : getFormat$1; +const getSource = HAS_CONSOLIDATED_HOOKS ? void 0 : getSource$1; +const load = HAS_CONSOLIDATED_HOOKS ? load$1 : void 0; export { getFormat, getSource, load, resolve }; diff --git a/.yarn/cache/fsevents-patch-2882183fbf-8.zip b/.yarn/cache/fsevents-patch-2882183fbf-8.zip new file mode 100644 index 0000000000000000000000000000000000000000..c4511f19bda176f6c1a39da1fbf5c56a981f61c2 GIT binary patch literal 23675 zcmbrl1ymc(_AUygK!M`!#kELrFD^xjyA>C!&wYWp%rN48| zdhfn<&$@T5e^xTO_c!0(Gs#RQJ0CwFy(B>R`*>fw@amt!zY|P&?&xG`W$NH$>0xi> z#`*ETiW2?*MXlYeJgpqv|D*E);nhFzAZMAh{1*ra4lfZ9DF3UDvZA!Cs-~>5<_EPM zE}ZUX-B`ikR4e^>KR5gggY1kPf@XOEmnh=JT6-H@Sm1~)VuO0=XA_VGV~saQs1J&{qDUSfEXln}Z1ql$1>>h%V2(BAJ2N?h zLq=QE5@11EW3Uo=u_#T=l{{sLCy{%QqEEOp&}5}z_%)UZi!&+-<59jg%5-p(le32S zX3(m9Wlb~ijrn_*mm)i1Tz!<=)i>zb@`*I9k{<>`r!lY9mzgcLMLrk5Fd9+p)Aq`2 zZP!TuMm0B< zskA{mLMR7Tn<$wl5BHiF6Ge2cB&Yhe?BEA{_4a;?nUiDs0B!M!0h6N`H=gBJnDvT$ zmc9Okq0>uv%GLdQGwMFudKJm@mBGEp=Y{ttl;CZTVCtQ7o%-5PIUJLp3^w0(JWL!h zOeA{I4~|h_h@IPFA$OSc{TKu`#xJVB{SqLVA>{Pw8T*xW@6m50@PfHX>qZomuJyiy z&|#LlgcGNE|JL9QMz!8Lh?Z?XNbD2BdPKTa5v_a7vFr@0&+OStz|u{N?w^f-n1RiV7*ia?}<4bThcilo0xqo{4foO6~BzP zdXIcQBehUe`7U`O3V-57h#Q|saf$XoMvU2q=oZRngs_llyoL+W+l=e=WWc}P4gXo$ z%Y6HA){vEyQIX|vu#D4LbzGIh2{_PI&PCOamsxg9LQ%q>^Y|n8 z{trpREOGHG-Cd=%uWMGG8Oif=?%grWLZ4s|5MzjMIu$S!-`PVbt%60||`L>(Y~DvXl;fk+eQUF}BYXV#w8r=9@QpRe)qw`@NWNbyude*9vso`oTnA^CBNV$$|^YFed$r^<#B>Fi)ih`xam#YEUOy}Mj^)|3V1V)LX=OB?sx?-($G3&?Q8u_)RKZ+wW8XYwbhr@SE6sXmQt8_ zrzepbf@BDc7qzX}aroNxX8ROt;Eicm;(sqMS5m0(d+kW0tF#Xl>^%=oJN~W-F1}4>?A?SXG%tME% zbmI5`L4z9d)km}gOSu=K{S7G>3FDhW9&O)btl(fx9={EG`rPPj9HoexpX9?=!?R8Rq-rD<}r6KgFS;HfwX<%I!gh~1FhaGpJxwD~*mIzIg z%ex*H;?J)&qn_-fCPLCs^Xf_afHPI8=|vR`T&|VcnsN?9)=Ta&^GdB|7AJvR1(gfv zgu+^+v`DO9nyo#6L&vO{uAv1%#I!z~0S?owGyOpbtFd*iY5Oz)V-5#47GY)QZRG}g zqZE}nM8HzzceJ-$s8&)_9P%tS)}=d6mJS(%Fs2U{!d`{aKXk_COZbwfzAvy`dk>H; zTe6Whc{3Gm1{?lh&=h=8BdG%vesA%?*>SBfcpEB={Q7ff&T9nLa7`6tOZ0$+NTvlA z$#kbucE@!GI_Ef`kD&q2fQtB>0tc(mnZfwsW{?}C(Nq^tri8O=PHD?(;khxABRVx= zM49M^h*1P=fkeWdG*Y)jKQhvQllRAT$9aK0RJ=V*aooBiD%hrl1EZ8!Bw7F`a)WuB z<0r93yFgjjLSGl6S0*R6W1EenD%#j3Wkb)kACmZ9M~7y`c1!hyF7lq|cgbYVq2O(n zXkB^*EV3Gb7s$PFc^oCg(kLtGg#!*B61CMAGMlDyqxwfB%YCWh$=4VAVWX!=^HVv8o&9yR`1z(gS6!(18$4!=xPgx1fji=LCzNU1M2>OM=!hoK z_#URkxORMY^yFH?X5=vcD`<#nop|e;X2MTPUn4hXKO*W_^U)&Q<5X2;D}O;H^^^ z_vkgAsryq%07_tgZ149*V24)Ia#fBMJ%zcJ||*-fPY_R2NtH3+SnPb6MeYm!8Z!-w7&Rq)iY$ z`5s7Td~qm#di%+^0)23#H*$a0Hj-^tXRBY=>w+3fvOde;adhG|gUb@jFB%x|EB{_Dri+`6=S~ zp{7RZ=HG{+|7-&UxDKWi@B>Z;d@G>)uiL2w|Q3vIxOK zxD2U9XQV74MvKR&k`Z;PVRy@&*>mia(PsEdlwDQ|;LJ;=vEGM?^6f%h^{$=GP`g1$ z_vHO=hlWg70*22S_l&BpiL^`aNej43Vt6?%e zOs5W$j-4CWHLSLqJV)Z-?D{0VUY|l31CWe;eHau!sF*yKCRaGMbaC)GS7iM_KzB;$ z1D4|T^y#>r1u^o7Y*&r~Yb+7=s~(am{F-J%99$)|0K~YDCIhhrb(xu5by=pHG+ULt zT30EPAt-^8z}h6KTN!m*z3Qq;Dz)Kpa?|?btjG<~#*cB*0xh2tn+{3+Pnwyd4Ss=ceM$GMT>o|Rdbf!2sJW+^4#^49La>jQ~)5lG?iZcFo61wT;agiiPyJA z(kP0Nt%eToSCC^a=6JbI`dJpYl~ENl0{4bJ#by=;95%T-$xXaSO+QS;VIowz#@?eKeh zlTlPYz9vCQO;;r%kD60pt;O9%I<@gi(CT(4_MIS zNO@_cky}9;z@nUcbuRN>j%)@LBu((t$utr8Ay3Pg;X5vuI(g-I6h* zDx`4&WjnSKiTIMjgcd=Q*#{vQwN*!{YIm$=JPXe}-OgXm{N{CQ*?SZX{rT|=%3xGS z^jE4jP9_n-CN`$~Cx?8|8Z1r0B0v1(mV)|w$ZNTxGO8zGGmN+?&APWz8n^r(n5^iF zQm^DnB0eCZTF=nZ@DIJ)PH4$$EDa{I2nZ#qEaEFnFQQ$zUz=^T+cneA1m0B09-9lur3B7fjoL!7zvmZ9tj(Ik+jxjfq~co{7) z8O7a@HIm0jr0^b>H8sP&E(2S~n+ZDror&8RQ%3XjBjhtChacYsRoR!#{@2mYS!oA2 z$5)~38@GC4s^2!JQ81Jb%Vm)Aov3^<1r2NS+{D~iiApgG(~*waCed-cFqi5CPtz1v zCc0BacFH?V! zEMy;OTYWeZNy1x7Qx$w$=UitwbaeN5nSthbhJZOaG4=a_Gv5qWfbjkLBAa}W=uGkz zfzjzYA*^=iOw8JBKUKyKox(P_BBBA+Q zM)A1dX)-*8rIq-6Qy`1NT@N^6A@8eVAwT%?d%H`@x{O@|TX}iPCjP)*I95JFC%=TZ z+l?`nAXws2JiAO!iF~H*E&9lEw-7G&l@056cA0cA@=@e2JesFvF<|F1!54Xjf0t}mtQuzKl8uX=7VPZYe zow^O?fzxu2iFkS}LSRDp@=5RHP~v}mcLzS;qwmQeAhe3V_`lgY{(dt*?Lza{l5OV? zY;VN5t5=knvQ9$#YDtVU7>4ubbMLpHH_^GO?a~IxXJy1MU7Bz&lgW!ET__L8a@Em_ zE!;^^ony#1jVMFeIEoRC3}l&D->AO<8EQLuED9aryLOMl?qO&5^VJ?zc~u9M*E+ev z9z<1Y&_LG%jOe0oD$z5j+k&#A;fLPu>`^2)5W>Gj?dGnjUJ=;NlqjY!s$}v0j|v8L ztA;)PUOy6wzHPtBeQC}WmM$Z^9JE(1t-!|?J<(imHrh`@81`xB;9MPm@%Y!)xQl#~AH(9&MET867kD z#ohA)RoI+;`;Oq4_>?vujO$Oa32RG&SkgCwtf5{NzjMm=t~|Zddivt$1=X+bPGpH5dio{L|3mwB-usuNGqQb}q?c^Q6WLW6wgQ&8=W4A0rztwY~aH1Zmx)olsM69N^9xYb9d@QQZ%RC-H5$kAG2=14>B_BP8U zM9_yQMkV?QOo?io6W?jsA1X)z@&JsOghMiymKa97$2epkNiWjt2ui=S7Tpj(ZIj|- z?9wsSN#)F|h-h?c5y;1ad7LFMl{QjH&nKY|Wz;+e1njJSULpNpt*6`2h#Or-w^%vx zCXH|d-#qyBiuAc7Lydc!#O8NJHrKT0Kizz`*Zy~82S2Gm=m3N6k%OEAwDv88Hqo=n zv`+d{*K#1X5VT1YlW8IFDPtrhPi!bqDYsj@7QNgQz?nnS#ALjt1|Ak{&o2OF=$x`L z6>jIam02r$d=IAIQzL#T(?`N<^55T{6Jjpp$9?AZBDPzkAKVrE@IPO3@Ffe=v`_kZ z7h_eYrAq0)Fd;TvI<&Bo|J_4CZ=gK4lzE{&lT>~nKSc|&QgRWPTmczxht8L)pEumgXHCr_jCNvJZ{ z^VqGwUw!?fgJxmHcq?1c5i+k>U+w(L6R-PHxgF$;8PvaieR$9Osum$<`o$T6X{Oih z58Xp3aVVosKqVz)4jO6o4G^z&$I9n?+Q<8n*uKI8OaRt$!LqqcMsqUSeWxhMGESktc-O| zg3p2m;wZ6G^u2$g2g^nLJmVZ~nkf!u8N4Le-=ru=0Tcgf;qRA7D9p?(_#kII9h?6` z`th>DqWz)W7JtPjShdcI=~rX!-4Q?8tUP$1{$@CeNAWqVqr zt+#eHjY9?)#&a_$vVPxx*45@0zV1GK>&pfBxiA5;r~!tCnoPZRc{jL<@h+ao(qDJ9 zqrU#Es3hhD>B!Pd&#Pxm5sRpzKR}5p72kmX@`Vpewr?UXSa^tbh-07 z$4q26j|sW|$)}5|`m^DZi_GHXdLakiBh1gf#vw4#1#TV;1M}87k$dAzFYS$Ye^xF? zr+!j~nq9Lluc`8X7~TIPS<-R9YWyTpTHzV^0oUD1eVxY=b}c|b>3=O!lJwKbzz)Rn z9r8G2=~{6v5o+0Gkp0O6lBGO?G4V}=X0&~4r%zxpMcVXvbs;2H_3*;UM*fK$#eHnZ zm*+;s|(mPA@Q{AcA0JjI6HJkOWzGpid8&R==b6Q2afB-rf zWYV|D&QIN3(Q!e@*0Mg_;qE}b;?IC!XTGVWqlZN~R{M|N09()Me8b8gTBc??3;+yn zNNJ~=<0nZz<1(2Ov81%h%*G+5`AKe;_Y?TE2hI>vMJo~gx2EAvB(m51MSoUjGykAz z*al3}5#h}X)N6%to6yw^OhS|3j@z3Z}EKfJg7{ugm69`f$PdDmcy1mgSQqeJg zSDZreMVK9$DmDBoLaZqiszfXNa#QNkcL~i()`MKCiT$8_rwMzsJCGtL$C>c;0r4{5 zR%s_C-LHE6Bq=PKlga*eL#F!B)?}m4@z&en)?VJ+=JR6m`dixs!d;xuaH@VkecceZ zdM^#~*Zo7XKSydjnqD3Iq%O=Z3cEqO&3<^SS6hOUaDNXUFeipRV~0&VBbi;}ENi7q z@c!UVnaGBiyKydS-7FeOyyc=HS_rgVH=g=Z6l$(s{WCC-JbnprJoiI^H?@dbsKfhZ zd5$P+opj6;!oG!-`vG!c1t&!0XqZqkQ37j~SZoFxMwffUYLq-MdE#w-W$d_sdmhcK zTL2dYR=nlNO4j>;FXb7(omuu(KNQr4nX5WR#;@6%6CX|Ji88W&(k0IHe=GWAHcyS7E9i=Ddv?QvxO&D1YYg_Kf(1xeJ1x5j&G9Be1c-DPov7Ml z3^3q6;L{Q%EEu!}Ds)UXxW_sc@7wNU%_X&FV}F=0naR!n?G6~+hA^rV*M$N5LImd9 zB?@ZEVqirx3~XEZ5kEpu=i6~pzHyLykZTEJj9XV2RxZpJp9vCi>KrAfUih;A(mmN` zwERnQRvulXxnr-SNq$>bno~xGpQZhs5Q~@4NZ2-sKed)Xj!!V zk6-)rZN&b$_WUVvarTTU6S%HvwlvwoKiYEahm$90-sQsL>>X*dA1za)_)$k?4}g}9 z5%&AZ6J|diU*!S&6B6Sx?5&ekXqW$-Vq~NKvKCslOrAhoY78%|D@*`7*Kk~VE zU-rkN+7Ephexe_b{J8u;`eP&0l>xelsp?tesTyW+ZghB-ziW#H^HrP^#~f*nsy`hjU2N_Cf_!?Yljx-sU4u&A_E6A` zuG9Ol_^eb=KfGRd2^diHb#gl&{e`Jw!P~}=WiL+JM!AADx=wCTWaa1mBXHAI$BwPq z!?bDhhHf{wsXLC4-a~G1>$BMD^e(sZ*+zl8+_8dn8k5(IutpJb3sjk{rT&E-)8f9I z7mrw$ass1fv4?%RjZ*-3wS{7;Cj3)EHf2L~gBn;Dv3nMR!^XVy_4e^|z%}`s6BG6? zgWed!6MuB-%%0Ceh{jh2=5Ff$DEG<>d80pC;!sjmI)?#N_kbqPAp_B0R=48gVuKDT z4GD!Z#3>X|ZEga-{)C1wnc1^HKP^ihmp`^8U2!HKi9O(wVQQJlm^6CZdVk}PuzR)F zGyKrQ00wbjQd3lnBv^nuNP4KZOnZ32#KzFu*mFxT$~RBX4e8qJ6O>_ZYD6&YFwh*F z83qv8GA$dRo_Iiu?IE9`cf-YgdA5axxu+WS9yM&24YcOUk;O$nA;sf^4g$*~9c9>e~Vb>q6 zZf*)Z_wLjBNzT5*UeB0Tg{=T1W;8=1Ye$qtv=>P?FM>( z$C6081d+dggwTPhpN98)fMB1n%kz+tlw7nhSTYt&eHi;4H1QQ61q(nJ4;Ti$Z22y- z^Vih;kq0`Go*ni{;M7+B@Pp}%%{BSf2yVAxB#Z$r2s=}r1Z5Ls!(PKH_qgId10;b8 zkpPUpUH-2R;0Bt;@8n&U~4gzX0#f9$Q^FTLNw%B z_xOU-=I?~zZFx;SnnuFCns8GHMvZiX;!r}TgYCgQP?>%SxdWK@UkJEONCSc}7E0*) z-vtW7fdbvZCl_p_5|NkGq`x0CjxK-};FrTddT{aI4t!ErmyD->q%#!TMR*5*04F4o za*;3vcLN~xGBg&Z_3prFW~=TK_{DI(>O*g#=;Kza`FoYB;qc63eKNVtZ|@f zfAM<$0O89;Lh$SLeU=Bj45%rlSu+v1)U%fJ`iy=&+g@ z*ftC%_IDu4^2SRw&=}@8?P84N4OBjAqRt8|PXc3k2g5G8mkQts(rF3=FT_oJGe8xd|-Fn7>e?3pWW%lUKzdcvBrSXVA!|`D1bd6`p>mjWUR(qlK zf&NyR{??oR)|uYJiQdDI-ouUF!ZRC;zWGO54y_Hq*R7v;kU_T zIEoEDz8YE*)|_j|yJ?)n5eDR>)i!Y%_nwwFm5=_n_R-A|~c}G_{r*J&3@Wq>co-vu5eL=|0%2KxFEL2k6r@jWEY+~7l(1}r&edXWbwr5RPcQ8B;*!<}6zJ_q!i}rB_b0#w5+4oBy)sb7 z4%+>p-{Nfr#qQPV{vdl1KjwC~)l1aP;?8Opb{;sQ7nwL;;*orxJU+|O;`Ti&Q(C}? zpOGmX=vlH^^w1tSYHK7j=WMm}ctoNCWwrU1Cw$y+6F^qyY}MPoe0jCC-D6ZP5Pp@{ z!Ti;C$N&E2(JjrezN*seoYk-ma+{_OxkUzc9%n`#NzPVn66b|oP1irtEUEWvVv=(o zIMM~}M626faL3}>z80CdHcXwm2p)(a-91tTNXRC0+sIngd9bd#2;?e_#d)$?-6qFO z>FJhMlT!=zeM>Q#|6nrd*4LF$hm$AWE^^13&JEC>*$_TCGV(k6=~%7?8&7b3od;1j z=WOd3q)NMYEAZT*N+r9+qVL)_I?BrW zlHn&SfJHk{k-~h!Ctu^4zeAAc8m+F|R=eo`_Qx}l*oAHh>8<|UT?mNFiD2_OV6n>E z92l@0y^$qYy~WX<-N9gB@7!LJ^$j{L@A>1zk!tZsWGJswF?PC2N}k21uBq3}VVvl) z|79n z>{#VJ{Rdb57IE!I=+A}=#e{bPXXTqt+={UPi*?Ho*a)ljY$EiM(JHTKTw8Awu$Wge z>NJVM3`w=uDh-{)&~9Q=lFHPNa*EO2&U$9vU!xyN71fIxqby?f%b@@Er%X^&4L~hS z3EKoy#Kv%SQ|!Ept?LsEy2K=L8hpTtrS5%DkIm-Zh`OvMfg$Y#kiZ*ohUK|U^hUR< zxoi8EA}?=AKp`$j!}k_o`B+%&rDv?^@B?NnXrvW$$B9ck_EIr6WvZ@_Bw_d)#3H%q zX24r;*ydACv(QTkz_IJcKXyyzf*Q(sQ;BDM&qo_z0lE;^h1y5E+ zD=pC+C7T+k@6n@XwnjU;?@a-d-6!HCjd$-X!ms`FvJ}Dx+#L9`*Uuvd?5~kO=dYLz zF0<(@u~xxfr?p=kHm(ZR4?armo=?bPIh6v@CLHNU$-ZHV63XmaA%z1jMVf}_ElqY@ z+GI6UxZpnrJW6?GydZx3t(0MOwY68BcJJAjP^n?XJzqs9*<^^8H^Ltmr*QlBS&yIBuW zK%N{MGXoY5NDG=p-;>YE*scHWp?-m>qN+NHnMtNnQ|9Rw+QwJdH^<+*O5vn<{+8~! zjb2jymuc80NVcpyrP81h>A+7oDTy#R5*8fkp4L$k%m+8HEO04MWT2dmLoVkpDI6D` zPa@m=gLXJf89be6E*#s8a3D?^I47EaabmrAxF7l7b0R{e0>C|$FGV2*X5F?Pq<-Tl z4aVHI1dA^MUt)huwK#Du3Tu*XJ)fN3G`fnU-cgSBI3n>4Q zVn0-zei;sayUT21reUE$4TH{7eOCihX{p_SMKnwcHa>mKpL|5h6gMsg&L6t*`Ep*# z7j9HfNAf-;%7Nm+T5~OSH*sVE#d08LTq@2vxAEH=vVdwiQ){aS*S|HB6a&srMNV%A zPcV*!;%|E7^1n~F7>{2#sRLaG0gc0eMgx#&{ub=L*oYCRz!nf%25G|}ar|2~O|Mvp z`F2Q7{BG^5Z#*5Oe7Q$g1bQiAlTe&zQLDDtBw;)o7zn%My$3WHI8FZn6^TKAfrb*` zW7JNU+l^3P^=$3{3-UnNnW)?WF_L0E0AY;VQ}m75pzr5I+1;9WJq0Uf4YjhXNU@gUmhx^HFQx|K$J(bS~^(FUXT{`YtIpA|?(? zGL8950V+EC^(hhF4}By*&c-}`yq=Nx2(pGN)^)?3@mCN)aoYwb|LCCiE)NDT_&B{g zCjTpGPIYYfH{ZpBTeWjd{b({*PCj>iFdtXJ$y0FvY>BII;)3S`tLmUnaKwB#B{;?W zmVt_c){z6)JeZo}0xSTRxMr!qCWULl+~)+~2=~Z3b1m@tJ%-gkk`hi~pO#X@wdb@Z2srV*AnQBM@}1_wlbAK&UG6|F{95 z75n4~*X*uDzooc;0Luryx*ht9u+a4ng?rP93MYOz!q{Cw_XK<>Q#C;~?w|SFul=pP=H; z{Dbh(2fjW&FXzIOZ7;ZNzA5egxkUoq{(0nc=I3m>x8la3JiM*%Lo>cOr=fr<`dVzA zQ&1#;L76)(d=G}0{F(FKohWLvn=yP#6V9R|i*^?dWZ*;;32U8aSV);a@c@$$R3TJ^ z*V{RVEMaz&0+VBI(-qUCuJ8WyMG6@>8KvdR#Q~YWRA}T-wM!NX@n`376sM_8*vuyJ z_B`Yn8xtxM3YggxNBiO*fnxLd;*ku@8npQ4Pe?s^Kh>)`=?9T8Si}WNm;enJso!u{ zG^~DcaQIRLXCwTADh&IL|En#!SJcuEFZ(5E{L!~~-htjPVQ(RXh2n@uULc2Y()c6O zyxxM}t$bS&a(UJ7h0`5*!TC<&{R3iu0#0CvGf6)#zmgj$(wjQ0xD57q+Q8iW3q;a# z*)wTh%%)|ZC6Q^552Z>`=`vILsVr+;rax1}F~_*J@n*6+$}E&(rnOx zJ*64F6NOuyBu``MDt$>ZJ4nUZ@${0Ne21YBncw>7`)WD0E^95Xp~K3Bm@mYrRg1{S z-_c`#GIA|M_b#0v(p4jNd`E7Q6%JEo?;o7?xXLovs`ONz_$tPETfoJ$pjG+iG=Li$8BVIn~@)}a%xQQuS zhX_?S9`}{(%GnL&uAM4)ntNw`+$5k`-jykQIx%PKRHo|3fS?{F^oj zd?@eIhYQTuI>CSIYlI`z%x>7jyH1(}49~~sZJnCo&2YVcHv@6b`{y;264RFXFv#(e zHu;Pc4PUlcK%2H%b$^bXs5Ba%T-GS;WYm2w5VG;HF63#8Q;a1l7 zc2?_K@)i-@?>B_<$G17#LWq>OV6Ka)LLY;pJ8s%1_o;PFg+EL&dO+^15xiV^&aOy~ zJ3U4xo?VBC&WXep(kp)H4QsGk+e9Lx$_h;SZh;e&OA!RC%@|CdXL-gWv_gV;Y5dR` z_}=@v;a}kpyTik1Bo_zd1=xbRs71UE0e(;0?Lo7}OY95e)Q>FK$D?dwJ&pkr57?l# zeP*JQ5B*Ol6~~R*Le*WWrm;^ez+n%%ede=`9`tv*Cr>sivJx*T7AIUno|c}CbDyFc zx*O%I8XnG{kDo%$?2H{z{e;$kcFz-U3lkz{cU&e=G#@c)0M|OheVV}^h*LSV;;?fC zRbP$HCG6z|{RS@G>W5u2-We9vM}!=0{gwk!&bCY&A2;q+C4|aq!UG*fB;AbWZ%aP~ z4C&=%twLNFAVl$VbOd3%5W?tnr~R+g^PbrN6_vK~m3_@a(65z4zD zV?TfNDz8YA;c9_-tis zUGvvl7#;F}COh<;E@0b7s(iORro#xN{j1h;ovY-gv0QP9-G|vL-WBU4pfoSaV* zrK%uS-SFAE9^y%yl@yLMra(Gl#U!Ge=b0+wJ$kJix5>HK%6PuS67bOr5U<_)kaVC? zjxZ|2pL@Zjgvt)R4n`Wrk=!Mc!L|`|4xX`-?j~5rcZSJ3aqLLWfWo6e1I^hef2&zF zm$I64v^GisCf4k+@is2xhz)3b$p}k!cVz2Z$E5{)yX!10)2FL+RQ$B9+`4afRNcIY zH&H4~3)%1M>}wdoQA+X;ikesY>8R0?pw;#C5KvnD24-;K*7f7aImd@h2ur?K;sZD*o+#yqgYePppb(|@ zz7SUMVjV2jx_&;@~Z+~w9 z$A6cxGI)*Xqy7F(i1xc*eJaxC{R6^qZ@19L^lz(4mSoyCWMlD}`e^GeTxU%+1GcMa zISM|YHW7u#;MOF=NJ)K*7i>IjwIah;n$20iT7$un3)y$corPh<*n*Bn4f0&)2oxje zhjl=6YE!27`9my1cF#f7`&03ykE7X+u^*m1hw5@M#tP07@RuGhX$FaD^6h(XC-%s?=)Nt`Oj|P+hG&{_oYC4($tf|-Q#w`XUnqB-o%I4*=ZA|(hmgv zA~<*NAFLi5d-;NgUmK7B?FxbB6cY+rvo5lh~7H9DY19tP5^$el;>gfu1&~|Ara+QAb*TIck!^Byd5` zYFIZnmrlftqB+=8;^tED5Y&OU z`iDu|&mcx&r@2dRfu|+83IS1-Bf$&Q*|JbBre3Yan2&>eko(h)*Sz{h4-(OP_{hgO14v(8LZX=AstcRQEAG$f`QEE+8pEbwy7$S{`6?2`tSbVUrTxrhD^4H2Tuvv!w z81UNLG3^Q%6dAoMhf!X!6Ae=?P7V{Z(2elA>!fC*t`XCy31PHF7T*S9K3dtxwVecY zU|y{ZbDag}!`qbn$>|>K(9?L6_+#bH>ZW}`G~IDTty~e%n5M1QyPm8^IUSJ?o)Nv_ zCxf{qn8hUbTY{SJ4#d^`MT|EY!Bo?k}#58;i3p2 z!QI=C@+aqrkMv;3NaBAjeRiZyy?_Ubh+4~5+J`p`1(M+J`9?WO%braz@FS?vZl`4gg3o6r(GyDY==hRc;NlEA+-ybKm8Aq zqdxU8A27~!q6C2d*hSyL8QK;$$%!GU`O2I>jQv$5&hUE@^g`@5(@>uS)K{ib4`o=!Q86)f`PA5(dPP$YpLBCN7w9^|v(cwk7KO}PYCcvq` z8yIs3!TJ?B0{a%gi}rgmjO(?OP2l#1MKi9miV&tCoq0ZsGiRDYKHwLm7r3(w8Kkni z3EZB#ob>w@K+skT!g7PDEBCA~`vB81mWA-okQP^fglen4dr@@G>ndG|ls%J~zvCw_ zFIBcEy~U{W5f=9c%T!wr6mloP=SCj{6;-qW2RYp;xdL}~$NoCY=3PN?my>L1a22Gi z700UldCysR*i9`mxcZ014tq0f@^VyV%jGhgK=UxfStw>T5H%;Wj4~JSQ5Y-U2B`5| zSVtAn2GKZ-;XkbVbt}N>3*pOr;OWCVEFPND%@`0{E@C|FPyy=)t>yEZ;K>Jcu*ZvX zcD{mC*#9;zpX!WUXgHBwQ?U<}KmeLRBu9Lv)aIQ0zFrQ4`Y#4Tr5PB57rpVvsQu`6 zx?J&NoL+1It%JQV#y~Jbq61L;GbI`8qv~dwgV`Roal*ZM%R7K6%7$dHOf#UY zfVVsAFFUc3O~{{k?u6~n-^S`Lu>#hCRPqoMs_)F3Olt-hqC`-bV@#^CY}Z z6J@(Pp6=0Z1x4zKp2dC~)%@h=Bnt~^1%WIAilrD5qE2h1Vc;dsd#;V(S!sqI;#I>K z$icu)GwCz7w^uaOK?bH%1jr^iH{YC(hC)!E4rDhR4yi932_QQoixbdJXW-5 z=$4CL1Xw#tw>N*6W|H*hJJ?}mIIQprf+iyyO_$jiL z!uxvYZX*t=T?i2P@idIcX}ZaB-*C5_u@e~C;InDfN}Wk_VQ^;N*^u^&oMNvOt#fKU zwgnUn#WcGf9_SS@+}zt3^2XLS>!FwRvH1#hkc0hhpuCLr!oP_43SAF|E?;(P6?KZk z4VaQ3kAL2=r$|LQ4^zCTLxgmYt-7%PepcLM@rJHu6apgkMNz#?F*?(IZ_ZiQoJ0n~ z?lXHa)}x_shg@KktLK87T})59kx=8{QwUiC=LOX8279C~0PX1>c_-?EgD)Q3qx<91a3YcnG_y^ z$Zmkq2dlH{8{tKO>ggVzC7{|iyeIw;^z+aZ@d_HYgYA9r6$iuFjd*TGu@<>@pnV$}%VXiJY;z4jVmm&b$bPtBh+Kwpr-Gwkg zp9J=k0Qt$lW6TAV;X=ys#)*hZAW-bZ2Js8d78FQ!)JQSa2=#?Hk+%}xlb3iiG4LQe zs73eYob1L4B_630_NH^a2*7dUL>8~vdCr2maa{z^J_Px+g2*odk-P!85W{%r-lj_j z)&bupUldemy2t*HL}&h+PE=VK#i1$VT|PD({|paO{T}u%@nHB8wNrSy$MuGj@_CPp z0?=y+pUwzqsd+$}AT-FU<}e=DmdX0DUEaUy;4!n(VD z*C~OpLHMHXk94|(=es+QM3Ml}Sp#yO74;Y>KN=eFbqC!W`9u%U-f7fqzUqGa=P3so)px-jJwDJTofQ4$=JI ziNaXsI7_m_-9r=a(Es1Dn4}<5@c;D-n6>MvYgo_Ll~3Jbv+#u9z~Sjic*5PY67y(F zn9z=*q-K1G&dtbt#+#I<-S_m=}QU{|;6ddFliH zw>Sm7YkBc?7=PwzO3Y-gO5j(Mf1(lYwR&PzPpk6#2N40KtJa+N5ADKLkLyX3=QEjr z@2iu!6WeUY@$+M4A+6}bbaky$=`EkPN}G#9kcrstTyJR~ndhoYt{V@baxV{`k>4^Q=<&&*p?XF$ zc%+T&)hp+T+J2g|@mz7&)z46uJsAsnTKY)4`lXzlVo1v?4GlG4Ck1U@`KF_naQ(8s zyEh1R?aXwimf7X$NDa~ysUm71Y%?gRN>2Pt@n)X0e(}(+ScG_L-%`>|i-VS4TeYD? zt-&%nGSR6cZ(&mjxStMibBz{Caiwun7UA|3NV>`wf}UfIEYUGtRbu=TSMX!sE3JK} zJVdiSJMV$LMe23}KZ{->LVwdm8l+s}ps6j5PVoPfa_7-d{f!^Mi|hu;I*};E$i9tj zNGMa5Y$;12L|@q_OqK*L!M+^opicQP8VCk3GBu_uze>)hx|1 zy4B}AEPYQ2-YL-u#kAj)Jq?()A4kN0xaDE&IsYbnz+KL$%;J8W04+DMRRvjG0M_YC z8K(AaG%x7pS;vli99HxX0;qscs83@nbBy3KM)rem3iTuoprJN&avmvosf1CY*X^3s z*9n2GDfz5PnOf1?iGfmyG(L?*O^;5X5?S~4Nb~A40TzJ27u=WcY}VptEt>f@-c00y zFIVqg?<4;PEwpZ|%|}!HamN&G&xxzKpWL!iv`y=0`J_jT78cvI00nT?Wczvi=J%=+ z+G*$;q;-iE=cWn&N>O=g@B4U*rH8n!KK!}%uj4$dJI|5u<-kWJ$klJhtfSqGT&|K4 zy^9@ki3_?Bpj52kpd+yn+yOFliLd`MV7IYJ{zKTX3)3=7)SJgS2BEDC4enb0c!UKCaiUd=?-+{|pH%!TKN zEu^h4oSAI*!0D6Q%gjsceZFO@bY>Ij zOZuQLdtG8XRJcV}YgYm?ep+&<)$jlM(@3m=z9GxGSVB?G{&CHQ^o`PrLkG zzK9U(dyQVSZG#f25v~$#Cb!L=x*owWwN+X9iM1hGsyQ+9;!{sHkQ`OF{Wu6l*G#34 zU|1prZzV@>6dG>3ennvXpmS@`s8&y%SZl-IyYs(Xf=0A_$7_9lY9SjFSGEPsJ_Z1U zniY%qB7kE#70}m0$V6jq)_febcVL2(8L8w>PFI;IWWAw28cwG32ZFud6ZJd|k@}?* zboXR>!yn0x{=BNpsZsUYgWpbJ?Y?pCgwE^H`3(jCqw#}0LZ++qW5QjHrP?vVecXk` z#&?cQ7BYtjd%mn!;K*Xk)L3NG+O(D_X~R$(D>|vnyT$VeN6zjiznrWbpD%p)nJ~E< zkyg=ZfqAg5bNz%6ZLNo=_}S4{FtNV*@{-P6LVi$X+IJgGO4?WEv-D;<;Fs*@f^=>a z^*?`}j_kl}%t5)bQ`1YD^13KA0{Z9OYsvHPg&HOZxsK*Pe$?JAseKnF*#)3|;j}xU zPi^c5CRk&&=M*3-jf)@rVw&>`uQ+ogIleZz@s8GytZdNY33A)?q%_4-XZaveD%=}k z;oDl7@PNA-FJExooZ(%qhX~%Y( zWq3X-@dNGa=2hg#H)G?nD~JykrH@(0Nw%T2YT!+$#i@#YuCA`L9mQMF40bSe7UkSA zU5dP>?qIr9XKnk4%N=!X7`KQwNw+@KfP2+AHdAHH>CBu>(j7&Y?KMUx(qGT3-&v&< z%j+%8`FvFTx--PH5xXe_F#xmt#toOCxy(Au+2GnT>2!Rz;iVnl2-7f(R&L7)`VXAN zB9MnTVdVyJbob`UDy^LiK$_!}o8#oafy(Z3=bWSYtp@|iZ46SS_8vRm=ZWsv7l=QJ zV`+&UsY>J$MU9?%`?d_)dDN&u+-Q7~L4HMO3xZBykrG^!xqT3DFWg{?AL+=!@VZ^= z!`$THt#Szp*>)|V@WjXzjKJ8ug4Aqe@bX;gGbaOQIf!l&t9wI;51FD@i&DwwhKZ7U z6f*^wN7zo5v1Mqyh2Rc-L`+QD_M^KIcV92OgW627p~fG$pcdsml3(-f{vJ@Qtrw>z zpuw5iRIF>!!q!rCrjjp!tCW3XDRfN(51nCaNeOKZ)#8^-_ETtvhLXI1Suhsda`JeI z#zZ96xMiQ|;8dw(_%!T{js~7@#tN_yCTFH%s*i8Pgzlb>UTVItICDGHp!b%S(u`S) zX=nkHWn}eH;9rb~Ed?Y`!R`9VKA1-%IU4KT0%t-+$OmC>w%lZT{er_;Ly2}nq9rl( zymh~2i*d`h(E894bw9BgMW(9LQ{nQF*gGwqc9MXZSO`U2Gz+e_v{WL7w(~k``l-zL zhr*d4cGFn3cAU=fQvZb-Z<4l#Z+~MNZ}g(bUK5ujy;naSxvja1?Y%) zzNzT3kZRBdf=>tBz1|GSiM5M$$2Pu%s)wS~>L^NUV1RVUV&YLx4jYqXh=Ex_X50WL zG0NM(zQG-OlgUMcOA{|SGrK{L3h`2y5ucH4LGew6%HKV5tAnn{+Ux90ROtCf+)acX zK9DH6SzZFm(kF>K$6jPezT`qT6#6N~=`x86r5)k52%Di0kP*PiJv&fYgc51idzy&8 zH!LBGCn(EsH$b>e(I4%ZMDwVCSDG+*mhNiEJo_Sa4o4+Ty0yo;Xb>=90$Wr-geK}8 z>=%XjB8_tbD{~6A7-s-tfiYpo=lBW2Hu(k~SjsjlvEK?ehEbPjnZYg<^~n}&^9kVQ zY=U`6&!J2Qi9Ja>ecVm=rAU*+9eZ!lauLBAz*t1F&E@X@-u7TPiLkkrS09K|2K&e6 z9E3{~+SjzEG=Ys_s^teqfoJ#Q#q?bUz8lEk45L!fYiH@LdYC|EwdOE?Jd=a{u2e1hu&GsPa0gUKSJfHyfdt`@Pq=A9Cu=Jlw zqA!U`il728i33G?U=iQ2Z!KOhU1b-k4P(H4OrJWzfi$3jV>=31dJjO+Zu`;$ zRG|?(R7D~RVK;t43-OL7uCzIuJGF(n5bF6#dIz!WGq`d_Ny$`8FdB1u%p<-H{x z!!=(weN;OT!E@vBPY0pW83FhaKY|ufb7-EV8H}RdmPi5vt17b^8i9d~jv53Km>`No zl4uIC;VNhF=s_tZFqy8Je=RUsT6{E)AJ`j08tYHJ(D06a`zCN;_FI1)h_y2(^$-9_ zL7^r{ss)%UfNqhbHVEHUhI~nqV(8%z8qh6hlmMuG2?a!2I;!~te@7HLCHnW?@xLYM z7Br7#)K62<;LX1%x1)z3Ul*iZ%eq|C%;J9lx7Y-+O;ItZenhWD0bk-%0uxXuMJfpd zj~qw>0W%9vKp}R1;F!?C2`EN?4&Wi=2?>NHo?(|AjR*)!K*cCWC!ly%?J}LBE3gkh zz5QRwKog7uX6C@!Md8CvlS=dsOI0j$lZj1g$hu6B%a!E``D4?H)M#}qdri#Kb@Ct{Ui`6X@t`wI(HF3sP5ZN^ z6ir&QNlv&l^r;A|tZu`OGKN<_yjV|~mtLr<{O-dLJf6hx+Gje>VLZI{N_mTh`CD@) z>oatA(o4qnsnzQg@%axr=Oaw*1AU6YrqtwFiVxv>;jp#DNc6VNw*;T@>+u@a=IoKJ*CA~qVGAN9 z7)ZO-c?IQGx52T9tJWeiQKkLTBa#M_8acUUR$#}#ys00biX-4MaJcn(kzsRVu&@4I zPq?<>3q0R(#a9uc@UxeO&sArtQXA4&Sg_Hi5U|zXeua3VD{O znGjanYij^e8jjB6EEUW@#bVo*q+nEgU1RcX*;Yi^c7&VNm4@SDSPxCXGX}3?vwJ#5 zY-jDIdIxQ<0Jl-wkD+EeLjkVId5xx@m#i+bK@_DPR_gGNmzKL**`={7`rcSxUMMZM z`z|eLE@+vX!l?l2>0c5}$+7)j0q}@YPK6?XM>q%n(hqr_W`JcNA&LLMBS`vz#3Skh z3x6Yt!#v_22eFh=1E`6Sf8`O&oHI@}KEljpl1SUz>U_*6>;1g_i;cEw!{Q(CI~|`W z-Wv=rFdG&vk?VO_)Lz9GW!aM%_9MOEbF8d~LlW8~HfMb~kF{;fOE-zqQ_tXbaIj+Z zxhIBPd86+6^P#J!)cWC#oz7{twf-MNRg@p>#xd`Ao*8kEo-5UuAGorX5vg3+iDd8| zZI8cu=hYUA~V56%On}n%-cur&CtrFOXPoyzjtCF7QOUFT z`#mmYIz+933`cm|9T9^YImuq_n;+;Hiw@@M*p2x=ds>Y8dG%+xj4E$!Mv(i#M8!Dv zuZ&M4oc0HQ3|kX@h)vd1C(>Z+xq>70Tf^irQRk5heC?~b0x4G-c8a?lbXF}Kq!5HD zJ4=|?H~1jq!CZ@=u0RUxozF@oS~mgwIni>4MyYaV^ZrDuXH*$#8Mo1gn3CT481*Gb z*%gD)728c^3f=kBQGlIUKlp=2VsWbv{<+nOy54dTjUOHcq5XxmHhm)*Nh4n8&Ay z_U2o!Ab{j~$>{%vc=+je(E9o$`8foUciY<-%67PRA0&J6XpbS%;TR`9za)?1L;>5=`=l4cGN$ z`DeZ1QG5~?baXt4*a-tB;)eDih z;bqCr44oiM9oz&Q2Ztv8&{@B_^+q@|<#beMgGZVm=tiC#a<$n|{c>O>2HK|RECq`Ha7mng{>O%7L5`tyC;X8Z<`j`C-QS1_-eylDyhhz##E?SssNqcge zo*+lniK}`}`?lw2K6@0e4YLm%?Sh-K_SVJ1C=#P{MY3zyc-O8ttS&NOdNl@oj1&hT zZbx?2Ip%BdpLexNcv!EV79ksn4G**vXKQff7H*C#&r$exiG4S(&|=uyhZVPZjO!e;d_v>{i&nT!nVv3 z+00+IEo5yNgJABwdlpTi`l+=SD(vj}P|qZvcglH-XXquu=}Qx1?P=z!h2tznsX9CZ!U3{tOtY&}azxhJYyl}8jAo$4?L-I1Kc8#%Zj8IcO?S*u!Jbo6p} zOnZUa#;(fj75!sfCN_N?IQLg0k2W=9{e{%H`#+>n_aV+aymp#uLFl|?X>-KuX}dJ8CFEYe7|XJ!FeRdkmN(NuJC zSjUtMnlmr#hU<`Yo!8DnbgNliTMR6%wG~i|8q7mb5R&!_N5cGYefN~_P|GMYdx+8vuWLRk4>67t68YmD;~q_~gbSaupfbF*#q_-%1rLAt z?r=&;-i5lpMoaEi7Sbhoo|E4@dAe(Hswvspa6f-*(nkgLl&mVLHf^?{>4tEO4fQ3u z(P|(11or?5`(WczI8VQLD{Eua%-pT<389E~7DKPWfiAh>m~;20&I%L^HA@$THs)9j zbNHV+$LOx3ldOQZ+%&^w;Nr(C94_Z#>Ga@7$zbGvFL4G==${`eYNWeEmCk?PlvL{c z=VL_;0(|>#oBk;=1R4;3W&G(tJY4epC*w_^cJ@}Nuz0i&rINTw%L^Q)BgeB C+4lDU literal 0 HcmV?d00001 diff --git a/.yarn/cache/resolve-patch-bad885c6ea-c79ecaea36.zip b/.yarn/cache/resolve-patch-b984c6fd86-c79ecaea36.zip similarity index 100% rename from .yarn/cache/resolve-patch-bad885c6ea-c79ecaea36.zip rename to .yarn/cache/resolve-patch-b984c6fd86-c79ecaea36.zip diff --git a/.yarn/cache/typescript-patch-1236c99922-dc7141ab55.zip b/.yarn/cache/typescript-patch-7ad1c7f5d0-dc7141ab55.zip similarity index 100% rename from .yarn/cache/typescript-patch-1236c99922-dc7141ab55.zip rename to .yarn/cache/typescript-patch-7ad1c7f5d0-dc7141ab55.zip diff --git a/yarn.lock b/yarn.lock index 5918512c385..98c3c53fbcc 100644 --- a/yarn.lock +++ b/yarn.lock @@ -7271,7 +7271,7 @@ __metadata: "fsevents@patch:fsevents@~2.3.2#~builtin": version: 2.3.2 - resolution: "fsevents@patch:fsevents@npm%3A2.3.2#~builtin::version=2.3.2&hash=18f3a7" + resolution: "fsevents@patch:fsevents@npm%3A2.3.2#~builtin::version=2.3.2&hash=df0bf1" dependencies: node-gyp: latest conditions: os=darwin @@ -12196,7 +12196,7 @@ fsevents@~2.3.2: "resolve@patch:resolve@^1.1.6#~builtin, resolve@patch:resolve@^1.10.0#~builtin, resolve@patch:resolve@^1.12.0#~builtin, resolve@patch:resolve@^1.14.2#~builtin, resolve@patch:resolve@^1.20.0#~builtin, resolve@patch:resolve@^1.9.0#~builtin": version: 1.22.0 - resolution: "resolve@patch:resolve@npm%3A1.22.0#~builtin::version=1.22.0&hash=07638b" + resolution: "resolve@patch:resolve@npm%3A1.22.0#~builtin::version=1.22.0&hash=c3c19d" dependencies: is-core-module: ^2.8.1 path-parse: ^1.0.7 @@ -13937,7 +13937,7 @@ typescript@^3.9.5: "typescript@patch:typescript@^3.9.5#~builtin": version: 3.9.10 - resolution: "typescript@patch:typescript@npm%3A3.9.10#~builtin::version=3.9.10&hash=f456af" + resolution: "typescript@patch:typescript@npm%3A3.9.10#~builtin::version=3.9.10&hash=3bd3d3" bin: tsc: bin/tsc tsserver: bin/tsserver From 5c0ad949a4cd7c93213eb96dab02fab5be0aa692 Mon Sep 17 00:00:00 2001 From: Djavid Gabibyan Date: Tue, 20 Dec 2022 15:47:07 +0500 Subject: [PATCH 015/170] chore: updates --- packages/rs-dpp/Cargo.toml | 2 +- .../apply_identity_credit_withdrawal_transition_factory.rs | 5 ++++- ...ply_identity_credit_withdrawal_transition_factory_spec.rs | 4 ++-- packages/rs-drive-abci/Cargo.toml | 2 +- packages/rs-drive/Cargo.toml | 2 +- 5 files changed, 9 insertions(+), 6 deletions(-) diff --git a/packages/rs-dpp/Cargo.toml b/packages/rs-dpp/Cargo.toml index 309324965fe..a2400cef4e6 100644 --- a/packages/rs-dpp/Cargo.toml +++ b/packages/rs-dpp/Cargo.toml @@ -13,7 +13,7 @@ bs58 = "0.4.0" byteorder = { version="1.4"} chrono = { version="0.4.20", default-features=false, features=["wasmbind", "clock"]} ciborium = { version="0.2"} -dashcore = { git="https://github.com/dashevo/rust-dashcore", features=["std", "secp-recovery", "rand", "signer"], default-features = false, rev = "6092d584487918c5330fec93152e4df06a714067" } +dashcore = { git="https://github.com/dashevo/rust-dashcore", features=["std", "secp-recovery", "rand", "signer", "use-serde"], default-features = false, rev = "6092d584487918c5330fec93152e4df06a714067" } env_logger = { version="0.9"} futures = { version ="0.3"} getrandom= { version="0.2", features=["js"]} diff --git a/packages/rs-dpp/src/identity/state_transition/identity_credit_withdrawal_transition/apply_identity_credit_withdrawal_transition_factory.rs b/packages/rs-dpp/src/identity/state_transition/identity_credit_withdrawal_transition/apply_identity_credit_withdrawal_transition_factory.rs index e82821e4400..b3c287a8cf0 100644 --- a/packages/rs-dpp/src/identity/state_transition/identity_credit_withdrawal_transition/apply_identity_credit_withdrawal_transition_factory.rs +++ b/packages/rs-dpp/src/identity/state_transition/identity_credit_withdrawal_transition/apply_identity_credit_withdrawal_transition_factory.rs @@ -51,7 +51,10 @@ where let maybe_withdrawals_data_contract: Option = self .state_repository .fetch_data_contract(&data_contract_id, state_transition.get_execution_context()) - .await?; + .await? + .map(TryInto::try_into) + .transpose() + .map_err(Into::into)?; let withdrawals_data_contract = maybe_withdrawals_data_contract .ok_or_else(|| anyhow!("Withdrawals data contract not found"))?; diff --git a/packages/rs-dpp/src/tests/identity/state_transition/identity_credit_withdrawal_transition/apply_identity_credit_withdrawal_transition_factory_spec.rs b/packages/rs-dpp/src/tests/identity/state_transition/identity_credit_withdrawal_transition/apply_identity_credit_withdrawal_transition_factory_spec.rs index 5d0795ff1b7..f86f7553e59 100644 --- a/packages/rs-dpp/src/tests/identity/state_transition/identity_credit_withdrawal_transition/apply_identity_credit_withdrawal_transition_factory_spec.rs +++ b/packages/rs-dpp/src/tests/identity/state_transition/identity_credit_withdrawal_transition/apply_identity_credit_withdrawal_transition_factory_spec.rs @@ -24,7 +24,7 @@ mod apply_identity_credit_withdrawal_transition_factory { let mut state_repository = MockStateRepositoryLike::default(); state_repository - .expect_fetch_data_contract::>() + .expect_fetch_data_contract() .times(1) .returning(|_, _| anyhow::Ok(None)); @@ -54,7 +54,7 @@ mod apply_identity_credit_withdrawal_transition_factory { let mut state_repository = MockStateRepositoryLike::default(); state_repository - .expect_fetch_data_contract::>() + .expect_fetch_data_contract() .times(1) .returning(|_, _| anyhow::Ok(Some(get_data_contract_fixture(None)))); diff --git a/packages/rs-drive-abci/Cargo.toml b/packages/rs-drive-abci/Cargo.toml index c5fe4f44448..e4aa7d56aa3 100644 --- a/packages/rs-drive-abci/Cargo.toml +++ b/packages/rs-drive-abci/Cargo.toml @@ -20,7 +20,7 @@ tempfile = "3" bs58 = "0.4.0" base64 = "0.13.0" hex = "0.4.3" -dashcore = { git="https://github.com/dashevo/rust-dashcore", features=["std", "secp-recovery", "rand", "signer"], default-features = false, rev = "6092d584487918c5330fec93152e4df06a714067" } +dashcore = { git="https://github.com/dashevo/rust-dashcore", features=["std", "secp-recovery", "rand", "signer", "use-serde"], default-features = false, rev = "6092d584487918c5330fec93152e4df06a714067" } [dev-dependencies] dpp = { path = "../rs-dpp", features = ["fixtures-and-mocks"]} diff --git a/packages/rs-drive/Cargo.toml b/packages/rs-drive/Cargo.toml index 22927708201..6b07ff2fd14 100644 --- a/packages/rs-drive/Cargo.toml +++ b/packages/rs-drive/Cargo.toml @@ -29,7 +29,7 @@ chrono = "0.4.20" bincode = "1.3.3" dpp = { path = "../rs-dpp", features = ["fixtures-and-mocks"]} itertools = { version = "0.10.5" } -dashcore = { git="https://github.com/dashevo/rust-dashcore", features=["std", "secp-recovery", "rand", "signer"], default-features = false, rev = "6092d584487918c5330fec93152e4df06a714067" } +dashcore = { git="https://github.com/dashevo/rust-dashcore", features=["std", "secp-recovery", "rand", "signer", "use-serde"], default-features = false, rev = "6092d584487918c5330fec93152e4df06a714067" } dashcore-rpc = { git="https://github.com/jawid-h/rust-dashcore-rpc", branch="fix/attempt-to-fix" } mockall= { version ="0.11", optional = true } From 20a841cbf809a38c59b9e7a9a4c8c684e59cdf6e Mon Sep 17 00:00:00 2001 From: Djavid Gabibyan Date: Tue, 20 Dec 2022 23:57:58 +0500 Subject: [PATCH 016/170] chore: mock CoreRPC for tests of nodejs bindings --- .pnp.cjs | 1 + Cargo.lock | 1 + packages/rs-drive-nodejs/Cargo.toml | 6 +++- packages/rs-drive-nodejs/Drive.js | 2 ++ packages/rs-drive-nodejs/package.json | 1 + packages/rs-drive-nodejs/scripts/build.sh | 4 ++- packages/rs-drive-nodejs/src/lib.rs | 26 ++++++++++++-- packages/rs-drive-nodejs/test/Drive.spec.js | 40 +++++++++++++++++++++ packages/rs-drive/src/drive/mod.rs | 2 +- yarn.lock | 3 +- 10 files changed, 80 insertions(+), 6 deletions(-) diff --git a/.pnp.cjs b/.pnp.cjs index 62f3b1a2657..72f52d380a4 100755 --- a/.pnp.cjs +++ b/.pnp.cjs @@ -2877,6 +2877,7 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { "packageDependencies": [\ ["@dashevo/rs-drive", "workspace:packages/rs-drive-nodejs"],\ ["@dashevo/dpp", "workspace:packages/js-dpp"],\ + ["@dashevo/withdrawals-contract", "workspace:packages/withdrawals-contract"],\ ["cargo-cp-artifact", "npm:0.1.6"],\ ["cbor", "npm:8.1.0"],\ ["chai", "npm:4.3.4"],\ diff --git a/Cargo.lock b/Cargo.lock index 4588035b2e5..933dfefbf8f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -985,6 +985,7 @@ dependencies = [ "drive-abci", "neon", "num 0.4.0", + "serde_json", ] [[package]] diff --git a/packages/rs-drive-nodejs/Cargo.toml b/packages/rs-drive-nodejs/Cargo.toml index b9a3a70ae5b..f894514bd69 100644 --- a/packages/rs-drive-nodejs/Cargo.toml +++ b/packages/rs-drive-nodejs/Cargo.toml @@ -10,11 +10,15 @@ private = true crate-type = ["cdylib"] [dependencies] -drive = { path = "../rs-drive" } +drive = { path = "../rs-drive", features = ["core-rpc-mock"]} drive-abci = { path = "../rs-drive-abci" } num = "0.4.0" +serde_json = { version="1.0", features=["preserve_order"] } [dependencies.neon] version = "0.10.1" default-features = false features = ["napi-6", "event-queue-api", "try-catch-api"] + +[features] +enable-core-rpc-mocking = [] diff --git a/packages/rs-drive-nodejs/Drive.js b/packages/rs-drive-nodejs/Drive.js index 5a1041ee21c..065f4aa55c0 100644 --- a/packages/rs-drive-nodejs/Drive.js +++ b/packages/rs-drive-nodejs/Drive.js @@ -495,6 +495,8 @@ class Drive { * @property {number} [previousBlockTimeMs] - timestamp in milliseconds * @property {Buffer} proposerProTxHash * @property {Buffer} validatorSetQuorumHash + * @property {number} lastSyncedCoreHeight + * @property {number} coreChainLockedHeight, */ /** diff --git a/packages/rs-drive-nodejs/package.json b/packages/rs-drive-nodejs/package.json index 40f1f0b464b..943f372fff3 100644 --- a/packages/rs-drive-nodejs/package.json +++ b/packages/rs-drive-nodejs/package.json @@ -17,6 +17,7 @@ ], "license": "MIT", "devDependencies": { + "@dashevo/withdrawals-contract": "workspace:*", "chai": "^4.3.4", "dirty-chai": "^2.0.1", "eslint": "^7.32.0", diff --git a/packages/rs-drive-nodejs/scripts/build.sh b/packages/rs-drive-nodejs/scripts/build.sh index dc316035f0e..a405e3aff26 100755 --- a/packages/rs-drive-nodejs/scripts/build.sh +++ b/packages/rs-drive-nodejs/scripts/build.sh @@ -1,16 +1,18 @@ #!/usr/bin/env bash PROFILE_ARG="" +FEATURES_ARG="" if [ -n "$CARGO_BUILD_PROFILE" ]; then if [ "$CARGO_BUILD_PROFILE" == "release" ]; then PROFILE_ARG="--release" elif [ "$CARGO_BUILD_PROFILE" != "debug" ]; then PROFILE_ARG="--profile $CARGO_BUILD_PROFILE" + FEATURES_ARG="--features enable-core-rpc-mocking" fi fi cargo-cp-artifact -ac drive-nodejs native/index.node -- \ - cargo build --message-format=json-render-diagnostics $PROFILE_ARG \ + cargo build --message-format=json-render-diagnostics $PROFILE_ARG $FEATURES_ARG --features enable-core-rpc-mocking \ && neon-tag-prebuild \ && rm -rf native diff --git a/packages/rs-drive-nodejs/src/lib.rs b/packages/rs-drive-nodejs/src/lib.rs index fd9942d4e7e..0724a09afdb 100644 --- a/packages/rs-drive-nodejs/src/lib.rs +++ b/packages/rs-drive-nodejs/src/lib.rs @@ -1,7 +1,9 @@ mod converter; mod fee_result; -use neon::object::PropertyKey; +use drive::dpp::dashcore::hashes::hex::FromHex; +use drive::dpp::dashcore::BlockHash; +use drive::rpc::core::MockCoreRPCLike; use std::ops::Deref; use std::{option::Option::None, path::Path, sync::mpsc, thread}; @@ -20,6 +22,7 @@ use drive_abci::abci::messages::{ }; use drive_abci::platform::Platform; use neon::prelude::*; +use serde_json::json; type PlatformCallback = Box FnOnce(&'a Platform, TransactionArg, &Channel) + Send>; type UnitCallback = Box; @@ -98,7 +101,26 @@ impl PlatformWrapper { }; // TODO: think how to pass this error to JS - let platform: Platform = Platform::open(path, Some(drive_config)).unwrap(); + let mut platform: Platform = Platform::open(path, Some(drive_config)).unwrap(); + + if cfg!(feature = "enable-core-rpc-mocking") { + let mut core_rpc_mock = MockCoreRPCLike::new(); + + core_rpc_mock.expect_get_block_hash().returning(|_| { + Ok(BlockHash::from_hex( + "0000000000000000000000000000000000000000000000000000000000000000", + ) + .unwrap()) + }); + + core_rpc_mock.expect_get_block_json().returning(|_| { + Ok(json!({ + "tx": [], + })) + }); + + platform.drive.core_rpc = Some(Box::new(core_rpc_mock)); + } let mut maybe_transaction: Option = None; diff --git a/packages/rs-drive-nodejs/test/Drive.spec.js b/packages/rs-drive-nodejs/test/Drive.spec.js index f00a4f58775..00377e31463 100644 --- a/packages/rs-drive-nodejs/test/Drive.spec.js +++ b/packages/rs-drive-nodejs/test/Drive.spec.js @@ -3,11 +3,18 @@ const fs = require('fs'); const { expect, use } = require('chai'); use(require('dirty-chai')); +const DashPlatformProtocol = require('@dashevo/dpp'); + const Document = require('@dashevo/dpp/lib/document/Document'); +const Identifier = require('@dashevo/dpp/lib/Identifier'); const getDataContractFixture = require('@dashevo/dpp/lib/test/fixtures/getDataContractFixture'); const getDocumentsFixture = require('@dashevo/dpp/lib/test/fixtures/getDocumentsFixture'); const getIdentityFixture = require('@dashevo/dpp/lib/test/fixtures/getIdentityFixture'); +const generateRandomIdentifier = require('@dashevo/dpp/lib/test/utils/generateRandomIdentifier'); + +const withdrawalContractDocumentsSchema = require('@dashevo/withdrawals-contract/schema/withdrawals-documents.json'); +const withdrawalContractIds = require('@dashevo/withdrawals-contract/lib/systemIds'); const { expectFeeResult, @@ -26,6 +33,7 @@ describe('Drive', () => { let blockInfo; let documents; let initialRootHash; + let withdrawalsDataContract; beforeEach(async () => { drive = new Drive(TEST_DATA_PATH, { @@ -33,6 +41,21 @@ describe('Drive', () => { dataContractsBlockCacheSize: 500, }); + const dpp = new DashPlatformProtocol({ + stateRepository: { + fetchDataContract: () => {}, + }, + }); + + await dpp.initialize(); + + withdrawalsDataContract = dpp.dataContract.create( + generateRandomIdentifier(), + withdrawalContractDocumentsSchema, + ); + + withdrawalsDataContract.id = Identifier.from(withdrawalContractIds.contractId); + dataContract = getDataContractFixture(); identity = getIdentityFixture(); @@ -504,6 +527,9 @@ describe('Drive', () => { describe('BlockBegin', () => { beforeEach(async () => { + await drive.createInitialStateStructure(); + await drive.createContract(withdrawalsDataContract, blockInfo); + await drive.getAbci().initChain({}); }); @@ -513,6 +539,8 @@ describe('Drive', () => { blockTimeMs: (new Date()).getTime(), proposerProTxHash: Buffer.alloc(32, 1), validatorSetQuorumHash: Buffer.alloc(32, 2), + lastSyncedCoreHeight: 1, + coreChainLockedHeight: 1, }; const response = await drive.getAbci().blockBegin(request); @@ -533,6 +561,8 @@ describe('Drive', () => { blockTimeMs, proposerProTxHash: Buffer.alloc(32, 1), validatorSetQuorumHash: Buffer.alloc(32, 2), + lastSyncedCoreHeight: 1, + coreChainLockedHeight: 1, }); const response = await drive.getAbci().blockBegin({ @@ -541,6 +571,8 @@ describe('Drive', () => { proposerProTxHash: Buffer.alloc(32, 1), previousBlockTimeMs: blockTimeMs, validatorSetQuorumHash: Buffer.alloc(32, 2), + lastSyncedCoreHeight: 1, + coreChainLockedHeight: 1, }); expect(response.unsignedWithdrawalTransactions).to.be.empty(); @@ -554,12 +586,17 @@ describe('Drive', () => { describe('BlockEnd', () => { beforeEach(async () => { + await drive.createInitialStateStructure(); + await drive.createContract(withdrawalsDataContract, blockInfo); + await drive.getAbci().initChain({}); await drive.getAbci().blockBegin({ blockHeight: 1, blockTimeMs: (new Date()).getTime(), proposerProTxHash: Buffer.alloc(32, 1), validatorSetQuorumHash: Buffer.alloc(32, 2), + lastSyncedCoreHeight: 1, + coreChainLockedHeight: 1, }); }); @@ -581,6 +618,7 @@ describe('Drive', () => { await drive.createInitialStateStructure(); await drive.createContract(dataContract, blockInfo); + await drive.createContract(withdrawalsDataContract, blockInfo); await drive.getAbci().initChain({}); await drive.getAbci().blockBegin({ @@ -588,6 +626,8 @@ describe('Drive', () => { blockTimeMs: (new Date()).getTime(), proposerProTxHash: Buffer.alloc(32, 1), validatorSetQuorumHash: Buffer.alloc(32, 2), + lastSyncedCoreHeight: 1, + coreChainLockedHeight: 1, }); await drive.getAbci().blockEnd({ fees: FeeResult.create(100, 10), diff --git a/packages/rs-drive/src/drive/mod.rs b/packages/rs-drive/src/drive/mod.rs index ce249987aee..bfa45197f93 100644 --- a/packages/rs-drive/src/drive/mod.rs +++ b/packages/rs-drive/src/drive/mod.rs @@ -76,7 +76,7 @@ use crate::drive::block_info::BlockInfo; use crate::drive::cache::{DataContractCache, DriveCache}; use crate::fee::FeeResult; use crate::fee_pools::epochs::Epoch; -use crate::rpc::core::{CoreRPCLike, DefaultCoreRPC}; +use crate::rpc::core::{CoreRPCLike, DefaultCoreRPC, MockCoreRPCLike}; use dpp::data_contract::extra::DriveContractExt; type TransactionPointerAddress = usize; diff --git a/yarn.lock b/yarn.lock index 98c3c53fbcc..1f27cacea4a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1838,6 +1838,7 @@ __metadata: resolution: "@dashevo/rs-drive@workspace:packages/rs-drive-nodejs" dependencies: "@dashevo/dpp": "workspace:*" + "@dashevo/withdrawals-contract": "workspace:*" cargo-cp-artifact: ^0.1.6 cbor: ^8.0.0 chai: ^4.3.4 @@ -1968,7 +1969,7 @@ __metadata: languageName: node linkType: hard -"@dashevo/withdrawals-contract@workspace:packages/withdrawals-contract": +"@dashevo/withdrawals-contract@workspace:*, @dashevo/withdrawals-contract@workspace:packages/withdrawals-contract": version: 0.0.0-use.local resolution: "@dashevo/withdrawals-contract@workspace:packages/withdrawals-contract" dependencies: From 365828be6c37c90b0ede7a88b5386195d15b5838 Mon Sep 17 00:00:00 2001 From: Djavid Gabibyan Date: Wed, 21 Dec 2022 10:14:24 +0500 Subject: [PATCH 017/170] chore: wip --- .pnp.cjs | 1 + .../handlers/proposal/beginBlockFactory.js | 10 ++++++++ packages/js-drive/package.json | 1 + .../test/integration/fee/pools.spec.js | 24 +++++++++++++++++++ yarn.lock | 1 + 5 files changed, 37 insertions(+) diff --git a/.pnp.cjs b/.pnp.cjs index 72f52d380a4..9b3c96912f0 100755 --- a/.pnp.cjs +++ b/.pnp.cjs @@ -2659,6 +2659,7 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { ["@dashevo/grpc-common", "workspace:packages/js-grpc-common"],\ ["@dashevo/masternode-reward-shares-contract", "workspace:packages/masternode-reward-shares-contract"],\ ["@dashevo/rs-drive", "workspace:packages/rs-drive-nodejs"],\ + ["@dashevo/withdrawals-contract", "workspace:packages/withdrawals-contract"],\ ["@types/pino", "npm:6.3.12"],\ ["ajv", "npm:8.8.1"],\ ["ajv-keywords", "virtual:34fbe5a7dba3086dcbcce8a7faed986b10f7a208f11db70499feb2c1afd76e24089e5b95f9e3b937e89512de1cf4937177cc2000303a1e908baefc73362a7d48#npm:5.0.0"],\ diff --git a/packages/js-drive/lib/abci/handlers/proposal/beginBlockFactory.js b/packages/js-drive/lib/abci/handlers/proposal/beginBlockFactory.js index d5fc50c9a58..4a859cc23c4 100644 --- a/packages/js-drive/lib/abci/handlers/proposal/beginBlockFactory.js +++ b/packages/js-drive/lib/abci/handlers/proposal/beginBlockFactory.js @@ -20,6 +20,7 @@ const protoTimestampToMillis = require('../../../util/protoTimestampToMillis'); * @param {synchronizeMasternodeIdentities} synchronizeMasternodeIdentities * @param {RSAbci} rsAbci * @param {ExecutionTimer} executionTimer + * @param {LastSyncedCoreHeightRepository} lastSyncedCoreHeightRepository * * @return {beginBlock} */ @@ -35,6 +36,7 @@ function beginBlockFactory( synchronizeMasternodeIdentities, rsAbci, executionTimer, + lastSyncedCoreHeightRepository, ) { /** * @typedef beginBlock @@ -107,6 +109,12 @@ function beginBlockFactory( await groveDBStore.startTransaction(); + const lastSyncedHeightResult = await lastSyncedCoreHeightRepository.fetch({ + useTransaction: true, + }); + + const lastSyncedCoreHeight = lastSyncedHeightResult.getValue() || coreChainLockedHeight; + // Call RS ABCI /** @@ -118,6 +126,8 @@ function beginBlockFactory( proposerProTxHash, // TODO replace with real value validatorSetQuorumHash: Buffer.alloc(32), + coreChainLockedHeight, + lastSyncedCoreHeight, }; if (!latestBlockExecutionContext.isEmpty()) { diff --git a/packages/js-drive/package.json b/packages/js-drive/package.json index 11190a32b2f..32979ccbeff 100644 --- a/packages/js-drive/package.json +++ b/packages/js-drive/package.json @@ -77,6 +77,7 @@ "@dashevo/grpc-common": "workspace:*", "@dashevo/masternode-reward-shares-contract": "workspace:*", "@dashevo/rs-drive": "workspace:*", + "@dashevo/withdrawals-contract": "workspace:*", "ajv": "^8.6.0", "ajv-keywords": "^5.0.0", "awilix": "^4.2.6", diff --git a/packages/js-drive/test/integration/fee/pools.spec.js b/packages/js-drive/test/integration/fee/pools.spec.js index 11e2e060272..73dce7fb0ad 100644 --- a/packages/js-drive/test/integration/fee/pools.spec.js +++ b/packages/js-drive/test/integration/fee/pools.spec.js @@ -1,10 +1,15 @@ const moment = require('moment'); +const DashPlatformProtocol = require('@dashevo/dpp'); + const masternodeRewardSharesSystemIds = require('@dashevo/masternode-reward-shares-contract/lib/systemIds'); const getMasternodeRewardSharesContractFixture = require('@dashevo/dpp/lib/test/fixtures/getMasternodeRewardSharesContractFixture'); const getMasternodeRewardShareDocumentsFixture = require('@dashevo/dpp/lib/test/fixtures/getMasternodeRewardShareDocumentsFixture'); +const withdrawalContractDocumentsSchema = require('@dashevo/withdrawals-contract/schema/withdrawals-documents.json'); +const withdrawalContractIds = require('@dashevo/withdrawals-contract/lib/systemIds'); + const getIdentityFixture = require('@dashevo/dpp/lib/test/fixtures/getIdentityFixture'); const Identifier = require('@dashevo/dpp/lib/identifier/Identifier'); @@ -35,6 +40,23 @@ describe('Fee Pools', () => { rsDrive = container.resolve('rsDrive'); await rsDrive.getAbci().initChain({}); + const dpp = new DashPlatformProtocol({ + stateRepository: { + fetchDataContract: () => {}, + }, + }); + + await dpp.initialize(); + + const withdrawalsDataContract = dpp.dataContract.create( + generateRandomIdentifier(), + withdrawalContractDocumentsSchema, + ); + + withdrawalsDataContract.id = Identifier.from(withdrawalContractIds.contractId); + + await dataContractRepository.create(withdrawalsDataContract, blockInfo); + // setup mn reward shares contract const mnSharesContract = getMasternodeRewardSharesContractFixture(); mnSharesContract.id = Identifier.from(masternodeRewardSharesSystemIds.contractId); @@ -93,6 +115,8 @@ describe('Fee Pools', () => { blockTimeMs, proposerProTxHash: mnIdentity.getId(), validatorSetQuorumHash: Buffer.alloc(32), + coreChainLockedHeight: 1, + lastSyncedCoreHeight: 1, }; if (previousBlockTimeMs) { diff --git a/yarn.lock b/yarn.lock index 1f27cacea4a..69cc5773722 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1636,6 +1636,7 @@ __metadata: "@dashevo/grpc-common": "workspace:*" "@dashevo/masternode-reward-shares-contract": "workspace:*" "@dashevo/rs-drive": "workspace:*" + "@dashevo/withdrawals-contract": "workspace:*" "@types/pino": ^6.3.0 ajv: ^8.6.0 ajv-keywords: ^5.0.0 From c2d422f4636e56b71b9c9dccbbe9e2cb117f7cbe Mon Sep 17 00:00:00 2001 From: Djavid Gabibyan Date: Wed, 21 Dec 2022 10:24:37 +0500 Subject: [PATCH 018/170] chore: fix app hash tests --- ...ynchronizeMasternodeIdentitiesFactory.spec.js | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/packages/js-drive/test/integration/identity/masternode/synchronizeMasternodeIdentitiesFactory.spec.js b/packages/js-drive/test/integration/identity/masternode/synchronizeMasternodeIdentitiesFactory.spec.js index fadf5e51574..9045178122a 100644 --- a/packages/js-drive/test/integration/identity/masternode/synchronizeMasternodeIdentitiesFactory.spec.js +++ b/packages/js-drive/test/integration/identity/masternode/synchronizeMasternodeIdentitiesFactory.spec.js @@ -367,7 +367,7 @@ describe('synchronizeMasternodeIdentitiesFactory', () => { beforeEach(async function beforeEach() { coreHeight = 3; - firstSyncAppHash = '20a1b452ad2b98fb8c6250d501c636e1b6a3bf95af1dc952fc7cf21904f226a7'; + firstSyncAppHash = '6dc2a81f029eff542d9f40ead09e929615b10744809d26259173b0f9f44a5144'; blockInfo = new BlockInfo(10, 0, 1668702100799); container = await createTestDIContainer(); @@ -695,7 +695,7 @@ describe('synchronizeMasternodeIdentitiesFactory', () => { // Nothing happened - await expectDeterministicAppHash('34cfbd49f7d8b3b18791c51966821fd5343efb67d3bd41805585ce21dad6fe91'); + await expectDeterministicAppHash('ca14fde445978315558fd4d1ce77b52003daa2f9e0da7e769c27f7950ef4304b'); // Core RPC should be called @@ -750,7 +750,7 @@ describe('synchronizeMasternodeIdentitiesFactory', () => { expect(result.updatedEntities).to.have.lengthOf(0); expect(result.removedEntities).to.have.lengthOf(0); - await expectDeterministicAppHash('c5bfc7b21f420b4dac0201c6a941aa0801ff0aa55d0f0ff70ca5d369ec31bd65'); + await expectDeterministicAppHash('984a2868aa1cba0b8606fface2fdb1b99a75e1dc5456a449a4b9488699fff6f7'); // New masternode identity should be created @@ -834,7 +834,7 @@ describe('synchronizeMasternodeIdentitiesFactory', () => { expect(result.updatedEntities).to.have.lengthOf(0); expect(result.removedEntities).to.have.lengthOf(1); - await expectDeterministicAppHash('25bd044189691f61a872ab485c70554fa86136d8aa34b3d0b30cf5e75f15670a'); + await expectDeterministicAppHash('553d688a16811ba92d9ede063ffbf6985f78f6ee4065fbadfbea3c96a88cfd59'); // Masternode identity should stay @@ -902,7 +902,7 @@ describe('synchronizeMasternodeIdentitiesFactory', () => { expect(result.updatedEntities).to.have.lengthOf(0); expect(result.removedEntities).to.have.lengthOf(1); - await expectDeterministicAppHash('25bd044189691f61a872ab485c70554fa86136d8aa34b3d0b30cf5e75f15670a'); + await expectDeterministicAppHash('553d688a16811ba92d9ede063ffbf6985f78f6ee4065fbadfbea3c96a88cfd59'); const invalidMasternodeIdentifier = Identifier.from( Buffer.from(invalidSmlEntry.proRegTxHash, 'hex'), @@ -952,7 +952,7 @@ describe('synchronizeMasternodeIdentitiesFactory', () => { expect(result.updatedEntities).to.have.lengthOf(3); expect(result.removedEntities).to.have.lengthOf(0); - await expectDeterministicAppHash('955896708aa0372060544d21311e2fc8f21205fe3c52e53e6777787f443f08bc'); + await expectDeterministicAppHash('ba35e7bc3c3e347c7724da0e9ff3fcf7798abf8b32735bde8f9e5e534483f593'); // Masternode identity should stay @@ -1027,7 +1027,7 @@ describe('synchronizeMasternodeIdentitiesFactory', () => { await synchronizeMasternodeIdentities(coreHeight + 1, blockInfo); - await expectDeterministicAppHash('1910be205225620460d2205149138ef3c0ef8fcef883e6894280a37edf0dee65'); + await expectDeterministicAppHash('058a528131c4eba0e3f766d934a004cdc72f71f29ccc96c95507d0f450e5a262'); // Masternode identity should contain new public key @@ -1110,7 +1110,7 @@ describe('synchronizeMasternodeIdentitiesFactory', () => { await synchronizeMasternodeIdentities(coreHeight, blockInfo); - await expectDeterministicAppHash('5b0ff77efd9d3a4894263c284ebb9be416bfb15ba64b59e584405cfa0fd5ab24'); + await expectDeterministicAppHash('3fbb1f504303d8ddc4334ad1501ba62acca77213f87b3b2665368362b9628883'); const votingIdentifier = createVotingIdentifier(smlFixture[0]); From d067e86de52d0ae3a8ae6a9d12d582f1e12c0135 Mon Sep 17 00:00:00 2001 From: Djavid Gabibyan Date: Wed, 21 Dec 2022 10:57:25 +0500 Subject: [PATCH 019/170] chore: register withdrawls contract --- .pnp.cjs | 1 + packages/dashmate/configs/system/base.js | 11 ++++++++ packages/dashmate/docker-compose.platform.yml | 2 ++ packages/dashmate/package.json | 1 + .../setup/setupLocalPresetTaskFactory.js | 14 ++++++++++ packages/js-drive/.env.example | 5 ++++ .../registerSystemDataContractsFactory.js | 28 +++++++++++++++++++ packages/js-drive/lib/createDIContainer.js | 18 ++++++++++++ yarn.lock | 1 + 9 files changed, 81 insertions(+) diff --git a/.pnp.cjs b/.pnp.cjs index 9b3c96912f0..b42f4865c1b 100755 --- a/.pnp.cjs +++ b/.pnp.cjs @@ -7630,6 +7630,7 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { ["@dashevo/feature-flags-contract", "workspace:packages/feature-flags-contract"],\ ["@dashevo/masternode-reward-shares-contract", "workspace:packages/masternode-reward-shares-contract"],\ ["@dashevo/wallet-lib", "workspace:packages/wallet-lib"],\ + ["@dashevo/withdrawals-contract", "workspace:packages/withdrawals-contract"],\ ["@oclif/core", "npm:1.16.3"],\ ["@oclif/plugin-help", "npm:5.1.12"],\ ["ajv", "npm:8.8.1"],\ diff --git a/packages/dashmate/configs/system/base.js b/packages/dashmate/configs/system/base.js index aeaa97117bf..ac90803f013 100644 --- a/packages/dashmate/configs/system/base.js +++ b/packages/dashmate/configs/system/base.js @@ -18,6 +18,10 @@ const { contractId: masternodeRewardSharesContractId, } = require('@dashevo/masternode-reward-shares-contract/lib/systemIds'); +const { + contractId: withdrawalsContractId, +} = require('@dashevo/withdrawals-contract/lib/systemIds'); + const { NETWORK_TESTNET, HOME_DIR_PATH, @@ -194,6 +198,13 @@ module.exports = { masterPublicKey: null, secondPublicKey: null, }, + withdrawals: { + contract: { + id: withdrawalsContractId, + }, + masterPublicKey: null, + secondPublicKey: null, + }, }, dashmate: { helper: { diff --git a/packages/dashmate/docker-compose.platform.yml b/packages/dashmate/docker-compose.platform.yml index 7ee7157be02..447668b869c 100644 --- a/packages/dashmate/docker-compose.platform.yml +++ b/packages/dashmate/docker-compose.platform.yml @@ -25,6 +25,8 @@ services: - FEATURE_FLAGS_SECOND_PUBLIC_KEY=${PLATFORM_FEATURE_FLAGS_SECOND_PUBLIC_KEY} - MASTERNODE_REWARD_SHARES_MASTER_PUBLIC_KEY=${PLATFORM_MASTERNODE_REWARD_SHARES_MASTER_PUBLIC_KEY} - 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} - NODE_ENV=${ENVIRONMENT:?err} - LOG_STDOUT_LEVEL=${PLATFORM_DRIVE_ABCI_LOG_STDOUT_LEVEL:?err} - LOG_PRETTY_FILE_LEVEL=${PLATFORM_DRIVE_ABCI_LOG_PRETTY_FILE_LEVEL:?err} diff --git a/packages/dashmate/package.json b/packages/dashmate/package.json index b10cdafeeaa..0a6beec1775 100644 --- a/packages/dashmate/package.json +++ b/packages/dashmate/package.json @@ -56,6 +56,7 @@ "@dashevo/feature-flags-contract": "workspace:*", "@dashevo/masternode-reward-shares-contract": "workspace:*", "@dashevo/wallet-lib": "workspace:*", + "@dashevo/withdrawals-contract": "workspace:*", "@oclif/core": "^1.16.3", "@oclif/plugin-help": "^5.1.12", "ajv": "^8.6.0", diff --git a/packages/dashmate/src/listr/tasks/setup/setupLocalPresetTaskFactory.js b/packages/dashmate/src/listr/tasks/setup/setupLocalPresetTaskFactory.js index 4f459e2e241..1928c66b6b2 100644 --- a/packages/dashmate/src/listr/tasks/setup/setupLocalPresetTaskFactory.js +++ b/packages/dashmate/src/listr/tasks/setup/setupLocalPresetTaskFactory.js @@ -124,6 +124,14 @@ function setupLocalPresetTaskFactory( ], } = await generateHDPrivateKeys(network, [0, 1]); + const { + hdPrivateKey: withdrawalsPrivateKey, + derivedPrivateKeys: [ + withdrawalsDerivedMasterPrivateKey, + withdrawalsDerivedSecondPrivateKey, + ], + } = await generateHDPrivateKeys(network, [0, 1]); + const { hdPrivateKey: masternodeRewardSharesPrivateKey, derivedPrivateKeys: [ @@ -144,6 +152,9 @@ function setupLocalPresetTaskFactory( // eslint-disable-next-line no-param-reassign task.output = `Masternode Reward Shares Private Key: ${masternodeRewardSharesPrivateKey.toString()}`; + // eslint-disable-next-line no-param-reassign + task.output = `Withdrawals Private Key: ${withdrawalsPrivateKey.toString()}`; + const subTasks = ctx.configGroup.map((config, i) => ( { title: `Create ${config.getName()} config`, @@ -214,6 +225,9 @@ function setupLocalPresetTaskFactory( config.set('platform.dashpay.masterPublicKey', dashpayDerivedMasterPrivateKey.privateKey.toPublicKey().toString()); config.set('platform.dashpay.secondPublicKey', dashpayDerivedSecondPrivateKey.privateKey.toPublicKey().toString()); + config.set('platform.withdrawals.masterPublicKey', withdrawalsDerivedMasterPrivateKey.privateKey.toPublicKey().toString()); + config.set('platform.withdrawals.secondPublicKey', withdrawalsDerivedSecondPrivateKey.privateKey.toPublicKey().toString()); + config.set( 'platform.masternodeRewardShares.masterPublicKey', masternodeRewardSharesDerivedMasterPrivateKey.privateKey diff --git a/packages/js-drive/.env.example b/packages/js-drive/.env.example index bf25bde0756..c0afd31ff42 100644 --- a/packages/js-drive/.env.example +++ b/packages/js-drive/.env.example @@ -50,6 +50,11 @@ FEATURE_FLAGS_SECOND_PUBLIC_KEY= MASTERNODE_REWARD_SHARES_MASTER_PUBLIC_KEY= MASTERNODE_REWARD_SHARES_SECOND_PUBLIC_KEY= +# Withdrawals contract + +WITHDRAWALS_MASTER_PUBLIC_KEY= +WITHDRAWALS_SECOND_PUBLIC_KEY= + # logging LOG_STDOUT_LEVEL=info diff --git a/packages/js-drive/lib/abci/handlers/state/registerSystemDataContractsFactory.js b/packages/js-drive/lib/abci/handlers/state/registerSystemDataContractsFactory.js index ee56f683a5e..948981fd09d 100644 --- a/packages/js-drive/lib/abci/handlers/state/registerSystemDataContractsFactory.js +++ b/packages/js-drive/lib/abci/handlers/state/registerSystemDataContractsFactory.js @@ -22,6 +22,11 @@ * @param {PublicKey} dashpayOwnerMasterPublicKey * @param {PublicKey} dashpayOwnerSecondPublicKey * @param {Object} dashpayDocuments + * @param {Identifier} withdrawalsContractId + * @param {Identifier} withdrawalsOwnerId + * @param {PublicKey} withdrawalsOwnerMasterPublicKey + * @param {PublicKey} withdrawalsOwnerSecondPublicKey + * @param {Object} withdrawalsDocuments * * @return {registerSystemDataContracts} */ @@ -48,6 +53,11 @@ function registerSystemDataContractsFactory( dashpayOwnerMasterPublicKey, dashpayOwnerSecondPublicKey, dashpayDocuments, + withdrawalsContractId, + withdrawalsOwnerId, + withdrawalsOwnerMasterPublicKey, + withdrawalsOwnerSecondPublicKey, + withdrawalsDocuments, ) { /** * @typedef {registerSystemDataContracts} @@ -131,6 +141,24 @@ function registerSystemDataContractsFactory( dashpayDocuments, blockInfo, ); + + contextLogger.debug('Registering withdrawals data contract'); + contextLogger.trace({ + ownerId: withdrawalsOwnerId, + contractId: withdrawalsContractId, + masterPublicKey: withdrawalsOwnerMasterPublicKey, + secondPublicKey: withdrawalsOwnerSecondPublicKey, + }); + + // Registering withdrawals data contract + await registerSystemDataContract( + withdrawalsOwnerId, + withdrawalsContractId, + withdrawalsOwnerMasterPublicKey, + withdrawalsOwnerSecondPublicKey, + withdrawalsDocuments, + blockInfo, + ); } return registerSystemDataContracts; diff --git a/packages/js-drive/lib/createDIContainer.js b/packages/js-drive/lib/createDIContainer.js index 5e30e59a235..db59dfda946 100644 --- a/packages/js-drive/lib/createDIContainer.js +++ b/packages/js-drive/lib/createDIContainer.js @@ -43,6 +43,9 @@ const masternodeRewardsDocuments = require('@dashevo/masternode-reward-shares-co const dashpaySystemIds = require('@dashevo/dashpay-contract/lib/systemIds'); const dashpayDocuments = require('@dashevo/dashpay-contract/schema/dashpay.schema.json'); +const withdrawalsSystemIds = require('@dashevo/withdrawals-contract/lib/systemIds'); +const withdrawalsDocuments = require('@dashevo/withdrawals-contract/schema/withdrawals-documents.json'); + const packageJSON = require('../package.json'); const ZMQClient = require('./core/ZmqClient'); @@ -164,6 +167,8 @@ const processProposalFactory = require('./abci/handlers/proposal/processProposal * @param {string} options.FEATURE_FLAGS_SECOND_PUBLIC_KEY * @param {string} options.MASTERNODE_REWARD_SHARES_MASTER_PUBLIC_KEY * @param {string} options.MASTERNODE_REWARD_SHARES_SECOND_PUBLIC_KEY + * @param {string} options.WITHDRAWALS_MASTER_PUBLIC_KEY + * @param {string} options.WITHDRAWALS_SECOND_PUBLIC_KEY * @param {string} options.INITIAL_CORE_CHAINLOCKED_HEIGHT * @param {string} options.VALIDATOR_SET_LLMQ_TYPE * @param {string} options.TENDERDASH_P2P_PORT @@ -333,6 +338,19 @@ function createDIContainer(options) { ), ), dashpayDocuments: asValue(dashpayDocuments), + withdrawalsContractId: asValue(Identifier.from(withdrawalsSystemIds.contractId)), + withdrawalsOwnerId: asValue(Identifier.from(withdrawalsSystemIds.ownerId)), + withdrawalsOwnerMasterPublicKey: asValue( + PublicKey.fromString( + options.WITHDRAWALS_MASTER_PUBLIC_KEY, + ), + ), + withdrawalsOwnerSecondPublicKey: asValue( + PublicKey.fromString( + options.WITHDRAWALS_SECOND_PUBLIC_KEY, + ), + ), + withdrawalsDocuments: asValue(withdrawalsDocuments), tenderdashP2pPort: asValue(options.TENDERDASH_P2P_PORT), }); diff --git a/yarn.lock b/yarn.lock index 69cc5773722..15612cf6fcd 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5685,6 +5685,7 @@ __metadata: "@dashevo/feature-flags-contract": "workspace:*" "@dashevo/masternode-reward-shares-contract": "workspace:*" "@dashevo/wallet-lib": "workspace:*" + "@dashevo/withdrawals-contract": "workspace:*" "@oclif/core": ^1.16.3 "@oclif/plugin-help": ^5.1.12 ajv: ^8.6.0 From 8f61710b9d7bc63b36ad1c06284cd6f2fd08561e Mon Sep 17 00:00:00 2001 From: Djavid Gabibyan Date: Wed, 21 Dec 2022 10:59:42 +0500 Subject: [PATCH 020/170] chore: fix --- packages/dashmate/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/dashmate/package.json b/packages/dashmate/package.json index 83fe8f17f6e..a552a8e5ea5 100644 --- a/packages/dashmate/package.json +++ b/packages/dashmate/package.json @@ -55,8 +55,8 @@ "@dashevo/dpp": "workspace:*", "@dashevo/feature-flags-contract": "workspace:*", "@dashevo/masternode-reward-shares-contract": "workspace:*", - "@dashevo/withdrawals-contract": "workspace:*", "@dashevo/wallet-lib": "workspace:*", + "@dashevo/withdrawals-contract": "workspace:*", "@oclif/core": "^1.21.0", "@oclif/plugin-help": "^5.1.20", "ajv": "^8.6.0", From 52c3bcb5c42413081e9d933b83eb884027c3a597 Mon Sep 17 00:00:00 2001 From: Djavid Gabibyan Date: Wed, 21 Dec 2022 11:20:20 +0500 Subject: [PATCH 021/170] chore: fixes --- packages/js-drive/lib/createDIContainer.js | 8 ++++++++ packages/js-drive/lib/test/bootstrap.js | 6 ++++++ 2 files changed, 14 insertions(+) diff --git a/packages/js-drive/lib/createDIContainer.js b/packages/js-drive/lib/createDIContainer.js index db59dfda946..0ce07292eff 100644 --- a/packages/js-drive/lib/createDIContainer.js +++ b/packages/js-drive/lib/createDIContainer.js @@ -214,6 +214,14 @@ function createDIContainer(options) { throw new Error('MASTERNODE_REWARD_SHARES_SECOND_PUBLIC_KEY must be set'); } + if (!options.WITHDRAWALS_MASTER_PUBLIC_KEY) { + throw new Error('WITHDRAWALS_MASTER_PUBLIC_KEY must be set'); + } + + if (!options.WITHDRAWALS_SECOND_PUBLIC_KEY) { + throw new Error('WITHDRAWALS_SECOND_PUBLIC_KEY must be set'); + } + const container = createAwilixContainer({ injectionMode: InjectionMode.CLASSIC, }); diff --git a/packages/js-drive/lib/test/bootstrap.js b/packages/js-drive/lib/test/bootstrap.js index b0c2a9c8190..542cd754c19 100644 --- a/packages/js-drive/lib/test/bootstrap.js +++ b/packages/js-drive/lib/test/bootstrap.js @@ -46,6 +46,12 @@ if (process.env.MASTERNODE_REWARD_SHARES_MASTER_PUBLIC_KEY === undefined) { if (process.env.MASTERNODE_REWARD_SHARES_SECOND_PUBLIC_KEY === undefined) { process.env.MASTERNODE_REWARD_SHARES_SECOND_PUBLIC_KEY = testPublicKey; } +if (process.env.WITHDRAWALS_MASTER_PUBLIC_KEY === undefined) { + process.env.WITHDRAWALS_MASTER_PUBLIC_KEY = testPublicKey; +} +if (process.env.WITHDRAWALS_SECOND_PUBLIC_KEY === undefined) { + process.env.WITHDRAWALS_SECOND_PUBLIC_KEY = testPublicKey; +} const dotenvConfig = dotenvSafe.config({ path: path.resolve(__dirname, '..', '..', '.env'), From 17a0482b6563d66f7c364cc6825fc33c726865b7 Mon Sep 17 00:00:00 2001 From: Djavid Gabibyan Date: Wed, 21 Dec 2022 11:47:33 +0500 Subject: [PATCH 022/170] chore: tests fixes --- .../unit/abci/handlers/proposal/beginBlockFactory.spec.js | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/packages/js-drive/test/unit/abci/handlers/proposal/beginBlockFactory.spec.js b/packages/js-drive/test/unit/abci/handlers/proposal/beginBlockFactory.spec.js index 51d7d9dface..837ee9e0c8f 100644 --- a/packages/js-drive/test/unit/abci/handlers/proposal/beginBlockFactory.spec.js +++ b/packages/js-drive/test/unit/abci/handlers/proposal/beginBlockFactory.spec.js @@ -46,6 +46,7 @@ describe('beginBlockFactory', () => { let timeMs; let epochInfo; let time; + let lastSyncedCoreHeightRepositoryMock; beforeEach(function beforeEach() { round = 0; @@ -106,6 +107,12 @@ describe('beginBlockFactory', () => { blockBegin: this.sinon.stub().resolves(rsResponseMock), }; + lastSyncedCoreHeightRepositoryMock = { + fetch: this.sinon.stub().resolves({ + getValue: () => undefined, + }), + }; + beginBlock = beginBlockFactory( groveDBStoreMock, latestBlockExecutionContextMock, @@ -118,6 +125,7 @@ describe('beginBlockFactory', () => { synchronizeMasternodeIdentitiesMock, rsAbciMock, executionTimerMock, + lastSyncedCoreHeightRepositoryMock, ); lastCommitInfo = {}; From 083fed982cbef9e79eb80deee57bc7fdc406facb Mon Sep 17 00:00:00 2001 From: Djavid Gabibyan Date: Wed, 21 Dec 2022 11:48:08 +0500 Subject: [PATCH 023/170] chore: tests fixes --- packages/rs-drive-nodejs/test/Drive.spec.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/packages/rs-drive-nodejs/test/Drive.spec.js b/packages/rs-drive-nodejs/test/Drive.spec.js index 00377e31463..6f79492514e 100644 --- a/packages/rs-drive-nodejs/test/Drive.spec.js +++ b/packages/rs-drive-nodejs/test/Drive.spec.js @@ -26,7 +26,9 @@ const FeeResult = require('../FeeResult'); const TEST_DATA_PATH = './test_data'; -describe('Drive', () => { +describe('Drive', function describe() { + this.timeout(10000); + let drive; let dataContract; let identity; From 260a32baf08a994dd18347b69befae972c026000 Mon Sep 17 00:00:00 2001 From: Djavid Gabibyan Date: Wed, 21 Dec 2022 11:52:51 +0500 Subject: [PATCH 024/170] chore: schema fix --- .../configs/schema/configJsonSchema.js | 28 ++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/packages/dashmate/configs/schema/configJsonSchema.js b/packages/dashmate/configs/schema/configJsonSchema.js index 211534ad487..5142b8c430d 100644 --- a/packages/dashmate/configs/schema/configJsonSchema.js +++ b/packages/dashmate/configs/schema/configJsonSchema.js @@ -632,8 +632,34 @@ module.exports = { required: ['contract', 'masterPublicKey', 'secondPublicKey'], additionalProperties: false, }, + withdrawals: { + type: 'object', + properties: { + contract: { + type: 'object', + properties: { + id: { + type: ['string', 'null'], + minLength: 1, + }, + }, + required: ['id'], + additionalProperties: false, + }, + masterPublicKey: { + type: ['string', 'null'], + minLength: 1, + }, + secondPublicKey: { + type: ['string', 'null'], + minLength: 1, + }, + }, + required: ['contract', 'masterPublicKey', 'secondPublicKey'], + additionalProperties: false, + }, }, - required: ['dapi', 'drive', 'dpns', 'dashpay', 'featureFlags', 'sourcePath', 'masternodeRewardShares'], + required: ['dapi', 'drive', 'dpns', 'dashpay', 'featureFlags', 'sourcePath', 'masternodeRewardShares', 'withdrawals'], additionalProperties: false, }, dashmate: { From 061f9b8560d5e180e4e35dd5e8e37b15d25f09c3 Mon Sep 17 00:00:00 2001 From: Djavid Gabibyan Date: Wed, 21 Dec 2022 12:04:07 +0500 Subject: [PATCH 025/170] chore: missing workspace --- packages/js-drive/Dockerfile | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/js-drive/Dockerfile b/packages/js-drive/Dockerfile index 49a871063a1..9697a49505b 100644 --- a/packages/js-drive/Dockerfile +++ b/packages/js-drive/Dockerfile @@ -74,6 +74,7 @@ COPY packages/js-grpc-common packages/js-grpc-common COPY packages/masternode-reward-shares-contract packages/masternode-reward-shares-contract COPY packages/dpns-contract packages/dpns-contract COPY packages/dashpay-contract packages/dashpay-contract +COPY packages/withdrawals-contract packages/withdrawals-contract # Build RS Drive Node.JS binding RUN --mount=type=cache,target=target \ From 3af6b70cd50f0e0bb678b6301966857a8194895c Mon Sep 17 00:00:00 2001 From: Djavid Gabibyan Date: Wed, 21 Dec 2022 12:53:37 +0500 Subject: [PATCH 026/170] chore: missing transactionId update --- packages/rs-drive-abci/Cargo.toml | 2 - packages/rs-drive-abci/src/abci/handlers.rs | 4 +- .../src/identity_credit_withdrawal/mod.rs | 26 ++- .../src/drive/identity/withdrawals/queue.rs | 175 +++++++++++++++++- 4 files changed, 199 insertions(+), 8 deletions(-) diff --git a/packages/rs-drive-abci/Cargo.toml b/packages/rs-drive-abci/Cargo.toml index e4aa7d56aa3..ef7bce0888a 100644 --- a/packages/rs-drive-abci/Cargo.toml +++ b/packages/rs-drive-abci/Cargo.toml @@ -21,6 +21,4 @@ bs58 = "0.4.0" base64 = "0.13.0" hex = "0.4.3" dashcore = { git="https://github.com/dashevo/rust-dashcore", features=["std", "secp-recovery", "rand", "signer", "use-serde"], default-features = false, rev = "6092d584487918c5330fec93152e4df06a714067" } - -[dev-dependencies] dpp = { path = "../rs-dpp", features = ["fixtures-and-mocks"]} diff --git a/packages/rs-drive-abci/src/abci/handlers.rs b/packages/rs-drive-abci/src/abci/handlers.rs index a3e4d8e1e16..a6820b02cee 100644 --- a/packages/rs-drive-abci/src/abci/handlers.rs +++ b/packages/rs-drive-abci/src/abci/handlers.rs @@ -134,7 +134,9 @@ impl TenderdashAbci for Platform { let unsigned_withdrawal_transaction_bytes = self .fetch_and_prepare_unsigned_withdrawal_transactions( - request.block_height as u32, + request.block_time_ms, + request.block_height, + epoch_info.current_epoch_index, request.validator_set_quorum_hash, transaction, )?; diff --git a/packages/rs-drive-abci/src/identity_credit_withdrawal/mod.rs b/packages/rs-drive-abci/src/identity_credit_withdrawal/mod.rs index 0cd3ca43228..a2ed62bce23 100644 --- a/packages/rs-drive-abci/src/identity_credit_withdrawal/mod.rs +++ b/packages/rs-drive-abci/src/identity_credit_withdrawal/mod.rs @@ -2,7 +2,10 @@ use dashcore::{ blockdata::transaction::special_transaction::asset_unlock::request_info::AssetUnlockRequestInfo, hashes::Hash, QuorumHash, }; -use drive::query::TransactionArg; +use dpp::util::hash; +use drive::{ + drive::identity::withdrawals::queue::update_document_transaction_id, query::TransactionArg, +}; use crate::{ error::{execution::ExecutionError, Error}, @@ -15,7 +18,9 @@ impl Platform { /// Prepares a list of an unsigned withdrawal transaction bytes pub fn fetch_and_prepare_unsigned_withdrawal_transactions( &self, - block_height: u32, + block_time_ms: u64, + block_height: u64, + current_epoch_index: u16, validator_set_quorum_hash: [u8; 32], transaction: TransactionArg, ) -> Result>, Error> { @@ -30,20 +35,33 @@ impl Platform { .into_iter() .map(|(_, bytes)| { let request_info = AssetUnlockRequestInfo { - request_height: block_height, + request_height: block_height as u32, quorum_hash: QuorumHash::hash(&validator_set_quorum_hash), }; let mut bytes_buffer = vec![]; request_info - .consensus_append_to_base_encode(bytes, &mut bytes_buffer) + .consensus_append_to_base_encode(bytes.clone(), &mut bytes_buffer) .map_err(|_| { Error::Execution(ExecutionError::CorruptedCodeExecution( "could not add aditional request info to asset unlock transaction", )) })?; + let original_transaction_id = hash::hash(bytes); + let update_transaction_id = hash::hash(bytes_buffer.clone()); + + update_document_transaction_id( + &self.drive, + &original_transaction_id, + &update_transaction_id, + block_time_ms, + block_height, + current_epoch_index, + transaction, + )?; + Ok(bytes_buffer) }) .collect::>, Error>>() diff --git a/packages/rs-drive/src/drive/identity/withdrawals/queue.rs b/packages/rs-drive/src/drive/identity/withdrawals/queue.rs index e3cf6aa5ce6..5364ecd9979 100644 --- a/packages/rs-drive/src/drive/identity/withdrawals/queue.rs +++ b/packages/rs-drive/src/drive/identity/withdrawals/queue.rs @@ -9,12 +9,13 @@ use dashcore::{ }; use dpp::{ contracts::withdrawals_contract, + data_contract::extra::common, identity::convert_credits_to_satoshi, prelude::{Document, Identifier}, util::{hash, json_value::JsonValueExt, string_encoding::Encoding}, }; use grovedb::TransactionArg; -use serde_json::{Number, Value as JsonValue}; +use serde_json::{json, Number, Value as JsonValue}; use crate::{ drive::{batch::GroveDbOpBatch, Drive}, @@ -99,6 +100,102 @@ fn build_withdrawal_transactions_from_documents( Ok(withdrawals) } +/// Helper function to find document by original transactionId +/// and update document transactionId to new one +pub fn update_document_transaction_id( + drive: &Drive, + original_transaction_id: &[u8], + update_transaction_id: &[u8], + block_time_ms: u64, + block_height: u64, + current_epoch_index: u16, + transaction: TransactionArg, +) -> Result<(), Error> { + let data_contract_id = Identifier::from_string( + &withdrawals_contract::system_ids().contract_id, + Encoding::Base58, + ) + .map_err(|_| { + Error::Drive(DriveError::CorruptedCodeExecution( + "Can't create withdrawals id identifier from string", + )) + })?; + + let (_, maybe_data_contract) = drive.get_contract_with_fetch_info( + data_contract_id.to_buffer(), + Some(&Epoch::new(current_epoch_index)), + transaction, + )?; + + let contract_fetch_info = maybe_data_contract.ok_or(Error::Drive( + DriveError::CorruptedCodeExecution("Can't fetch withdrawal data contract"), + ))?; + + let query_value = json!({ + "where": [ + ["transactionId", "==", original_transaction_id], + ["status", "==", withdrawals_contract::statuses::POOLED], + ], + }); + + let query_cbor = common::value_to_cbor(query_value, None); + + let (documents, _, _) = drive.query_documents( + &query_cbor, + data_contract_id.to_buffer(), + withdrawals_contract::types::WITHDRAWAL, + None, + transaction, + )?; + + let documents = documents + .into_iter() + .map(|document_cbor| { + Document::from_cbor(document_cbor).map_err(|_| { + Error::Drive(DriveError::CorruptedCodeExecution( + "Can't create a document from cbor", + )) + }) + }) + .collect::, Error>>()?; + + for mut document in documents { + update_document_data( + drive, + &contract_fetch_info.contract, + &mut document, + block_time_ms, + block_height, + current_epoch_index, + transaction, + |document: &mut Document| -> Result<&mut Document, Error> { + document + .data + .insert( + "transactionId".to_string(), + JsonValue::Array( + update_transaction_id + .iter() + .map(|byte| JsonValue::Number(Number::from(*byte))) + .collect(), + ), + ) + .map_err(|_| { + Error::Drive(DriveError::CorruptedCodeExecution( + "Can't update document field: transactionId", + )) + })?; + + document.revision += 1; + + Ok(document) + }, + )?; + } + + Ok(()) +} + impl Drive { /// Pool withdrawal documents into transactions pub fn pool_withdrawals_into_transactions( @@ -377,4 +474,80 @@ mod tests { } } } + + mod update_document_transaction_id { + use crate::drive::identity::withdrawals::queue::update_document_transaction_id; + + use super::*; + + #[test] + fn test_transaction_id_updated() { + let drive = setup_drive_with_initial_state_structure(); + + let transaction = drive.grove.start_transaction(); + + let data_contract = get_withdrawals_data_contract_fixture(None); + + setup_system_data_contract(&drive, &data_contract, Some(&transaction)); + + let original_transaction_id: Vec = vec![ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, + ]; + + let updated_transaction_id: Vec = vec![ + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, + ]; + + let document = get_withdrawal_document_fixture( + &data_contract, + json!({ + "amount": 1000, + "coreFeePerByte": 1, + "pooling": 0, + "outputScript": (0..23).collect::>(), + "status": withdrawals_contract::statuses::POOLED, + "transactionIndex": 1, + "transactionId": original_transaction_id, + }), + ); + + setup_document(&drive, &document, &data_contract, Some(&transaction)); + + update_document_transaction_id( + &drive, + &original_transaction_id, + &updated_transaction_id, + 1, + 1, + 1, + Some(&transaction), + ) + .expect("to update transactionId"); + + let updated_documents = fetch_withdrawal_documents_by_status( + &drive, + withdrawals_contract::statuses::POOLED, + Some(&transaction), + ) + .expect("to fetch withdrawal documents"); + + assert_eq!(updated_documents.len(), 1); + + let stored_transaction_id: Vec = updated_documents + .get(0) + .unwrap() + .data + .get("transactionId") + .unwrap() + .as_array() + .unwrap() + .iter() + .map(|byte| byte.as_u64().unwrap() as u8) + .collect(); + + assert_eq!(stored_transaction_id, updated_transaction_id); + } + } } From c2894bcc9f7acdd167110d7908de8cfd20fa1bb4 Mon Sep 17 00:00:00 2001 From: Djavid Gabibyan Date: Wed, 21 Dec 2022 13:21:51 +0500 Subject: [PATCH 027/170] chore: update status to BROADCASTED --- .../handlers/finalizeBlockHandlerFactory.js | 14 +++++ packages/js-drive/lib/createDIContainer.js | 10 +++ ...WithdrawalTransactionIdAndStatusFactory.js | 62 +++++++++++++++++++ 3 files changed, 86 insertions(+) create mode 100644 packages/js-drive/lib/identity/withdrawals/updateWithdrawalTransactionIdAndStatusFactory.js diff --git a/packages/js-drive/lib/abci/handlers/finalizeBlockHandlerFactory.js b/packages/js-drive/lib/abci/handlers/finalizeBlockHandlerFactory.js index b09282b9af7..9f600c0ea8f 100644 --- a/packages/js-drive/lib/abci/handlers/finalizeBlockHandlerFactory.js +++ b/packages/js-drive/lib/abci/handlers/finalizeBlockHandlerFactory.js @@ -8,6 +8,8 @@ const { } = require('@dashevo/abci/types'); const lodashCloneDeep = require('lodash/cloneDeep'); +const BlockInfo = require('../../blockExecution/BlockInfo'); + /** * * @return {finalizeBlockHandler} @@ -29,6 +31,7 @@ function finalizeBlockHandlerFactory( latestBlockExecutionContext, proposalBlockExecutionContext, processProposal, + updateWithdrawalTransactionIdAndStatus, ) { /** * @typedef finalizeBlockHandler @@ -116,6 +119,8 @@ function finalizeBlockHandlerFactory( const { thresholdVoteExtensions } = commitInfo; + const blockInfo = BlockInfo.createFromBlockExecutionContext(proposalBlockExecutionContext); + for (const { extension, signature } of (thresholdVoteExtensions || [])) { const withdrawalTransactionHash = extension.toString('hex'); @@ -131,6 +136,15 @@ function finalizeBlockHandlerFactory( // TODO: think about Core error handling await coreRpcClient.sendRawTransaction(transactionBytes.toString('hex')); + + await updateWithdrawalTransactionIdAndStatus( + blockInfo, + unsignedWithdrawalTransactionBytes, + transactionBytes, + { + useTransaction: true, + }, + ); } } diff --git a/packages/js-drive/lib/createDIContainer.js b/packages/js-drive/lib/createDIContainer.js index 0ce07292eff..459eebc5b86 100644 --- a/packages/js-drive/lib/createDIContainer.js +++ b/packages/js-drive/lib/createDIContainer.js @@ -133,6 +133,7 @@ const handleRemovedMasternodeFactory = require('./identity/masternode/handleRemo const handleUpdatedScriptPayoutFactory = require('./identity/masternode/handleUpdatedScriptPayoutFactory'); const getWithdrawPubKeyTypeFromPayoutScriptFactory = require('./identity/masternode/getWithdrawPubKeyTypeFromPayoutScriptFactory'); const getPublicKeyFromPayoutScript = require('./identity/masternode/getPublicKeyFromPayoutScript'); +const updateWithdrawalTransactionIdAndStatusFactory = require('./identity/withdrawals/updateWithdrawalTransactionIdAndStatusFactory'); const DocumentRepository = require('./document/DocumentRepository'); const ExecutionTimer = require('./util/ExecutionTimer'); @@ -677,6 +678,15 @@ function createDIContainer(options) { validatorSet: asClass(ValidatorSet), }); + /** + * Register withrawals stuff + */ + container.register({ + updateWithdrawalTransactionIdAndStatus: asFunction( + updateWithdrawalTransactionIdAndStatusFactory, + ), + }); + /** * Register feature flags stuff */ diff --git a/packages/js-drive/lib/identity/withdrawals/updateWithdrawalTransactionIdAndStatusFactory.js b/packages/js-drive/lib/identity/withdrawals/updateWithdrawalTransactionIdAndStatusFactory.js new file mode 100644 index 00000000000..3b601effc20 --- /dev/null +++ b/packages/js-drive/lib/identity/withdrawals/updateWithdrawalTransactionIdAndStatusFactory.js @@ -0,0 +1,62 @@ +const WITHDRAWALS_DOCUMENT_TYPE = 'withdrawals'; + +const WITHDRAWALS_STATUS_POOLED = 1; +const WITHDRAWALS_STATUS_BROADCASTED = 1; + +/** + * @param {DocumentRepository} documentRepository + * @param {fetchDocuments} fetchDocuments + * @param {Identifier} withdrawalsContractId + * + * @returns {updateWithdrawalTransactionIdAndStatus} + */ +function updateWithdrawalTransactionIdAndStatusFactory( + documentRepository, + fetchDocuments, + withdrawalsContractId, +) { + /** + * Update withdrawal transactionId and set status to BROADCASTED + * + * @typedef updateWithdrawalTransactionIdAndStatus + * + * @param {BlockInfo} blockInfo + * @param {Buffer} originalTransactionId + * @param {Buffer} updatedTransactionId + * @param {Object} options + * + * @returns {Promise} + */ + async function updateWithdrawalTransactionIdAndStatus( + blockInfo, + originalTransactionId, + updatedTransactionId, + options, + ) { + const fetchOptions = { + where: [ + ['status', '==', WITHDRAWALS_STATUS_POOLED], + ['transactionId', '==', originalTransactionId], + ], + ...options, + }; + + const documents = await fetchDocuments( + withdrawalsContractId, + WITHDRAWALS_DOCUMENT_TYPE, + fetchOptions, + ); + + for (const document of documents) { + document.set('transactionId', updatedTransactionId); + document.set('status', WITHDRAWALS_STATUS_BROADCASTED); + document.setRevision(document.getRevision() + 1); + + await documentRepository.update(document, blockInfo, options); + } + } + + return updateWithdrawalTransactionIdAndStatus; +} + +module.exports = updateWithdrawalTransactionIdAndStatusFactory; From 65975af7c22aa80f0c1852364393e45fafe11e52 Mon Sep 17 00:00:00 2001 From: Djavid Gabibyan Date: Wed, 21 Dec 2022 13:25:24 +0500 Subject: [PATCH 028/170] chore: test fix --- .../abci/handlers/finalizeBlockHandlerFactory.spec.js | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/packages/js-drive/test/unit/abci/handlers/finalizeBlockHandlerFactory.spec.js b/packages/js-drive/test/unit/abci/handlers/finalizeBlockHandlerFactory.spec.js index 919fe252f06..3a9de26b864 100644 --- a/packages/js-drive/test/unit/abci/handlers/finalizeBlockHandlerFactory.spec.js +++ b/packages/js-drive/test/unit/abci/handlers/finalizeBlockHandlerFactory.spec.js @@ -32,6 +32,7 @@ describe('finalizeBlockHandlerFactory', () => { let round; let block; let processProposalMock; + let updateWithdrawalTransactionIdAndStatusMock; beforeEach(function beforeEach() { round = 0; @@ -84,6 +85,10 @@ describe('finalizeBlockHandlerFactory', () => { proposalBlockExecutionContextMock.getHeight.returns(new Long(42)); proposalBlockExecutionContextMock.getRound.returns(round); proposalBlockExecutionContextMock.getDataContracts.returns([dataContract]); + proposalBlockExecutionContextMock.getEpochInfo.returns({ + currentEpochIndex: 1, + }) + proposalBlockExecutionContextMock.getTimeMs.returns((new Date()).getTime()); groveDBStoreMock = new GroveDBStoreMock(this.sinon); groveDBStoreMock.getRootHash.resolves(appHash); @@ -98,6 +103,8 @@ describe('finalizeBlockHandlerFactory', () => { processProposalMock = this.sinon.stub(); + updateWithdrawalTransactionIdAndStatusMock = this.sinon.stub(); + finalizeBlockHandler = finalizeBlockHandlerFactory( groveDBStoreMock, blockExecutionContextRepositoryMock, @@ -107,6 +114,7 @@ describe('finalizeBlockHandlerFactory', () => { latestBlockExecutionContextMock, proposalBlockExecutionContextMock, processProposalMock, + updateWithdrawalTransactionIdAndStatusMock, ); }); From 38483ff130fcf628f0ccb6aa125ffbab000bf4f9 Mon Sep 17 00:00:00 2001 From: Djavid Gabibyan Date: Wed, 21 Dec 2022 14:07:45 +0500 Subject: [PATCH 029/170] chore: fixes --- packages/dashmate/Dockerfile | 1 + .../test/unit/abci/handlers/finalizeBlockHandlerFactory.spec.js | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/dashmate/Dockerfile b/packages/dashmate/Dockerfile index dfe9b6da646..aec5143a3fb 100644 --- a/packages/dashmate/Dockerfile +++ b/packages/dashmate/Dockerfile @@ -35,6 +35,7 @@ COPY packages/js-dapi-client packages/js-dapi-client COPY packages/js-grpc-common packages/js-grpc-common COPY packages/dapi-grpc packages/dapi-grpc COPY packages/dash-spv packages/dash-spv +COPY packages/withdrawals-contract packages/withdrawals-contract # Print build output RUN yarn config set enableInlineBuilds true diff --git a/packages/js-drive/test/unit/abci/handlers/finalizeBlockHandlerFactory.spec.js b/packages/js-drive/test/unit/abci/handlers/finalizeBlockHandlerFactory.spec.js index 3a9de26b864..ab6a966442b 100644 --- a/packages/js-drive/test/unit/abci/handlers/finalizeBlockHandlerFactory.spec.js +++ b/packages/js-drive/test/unit/abci/handlers/finalizeBlockHandlerFactory.spec.js @@ -87,7 +87,7 @@ describe('finalizeBlockHandlerFactory', () => { proposalBlockExecutionContextMock.getDataContracts.returns([dataContract]); proposalBlockExecutionContextMock.getEpochInfo.returns({ currentEpochIndex: 1, - }) + }); proposalBlockExecutionContextMock.getTimeMs.returns((new Date()).getTime()); groveDBStoreMock = new GroveDBStoreMock(this.sinon); From 081b505f12a7ef6685f43e616085ba64629fc520 Mon Sep 17 00:00:00 2001 From: Djavid Gabibyan Date: Wed, 21 Dec 2022 14:35:37 +0500 Subject: [PATCH 030/170] chore: final testing --- ...WithdrawalTransactionIdAndStatusFactory.js | 2 +- ...rawalTransactionIdAndStatusFactory.spec.js | 62 +++++++++++++++++++ 2 files changed, 63 insertions(+), 1 deletion(-) create mode 100644 packages/js-drive/test/unit/identity/withdrawals/updateWithdrawalTransactionIdAndStatusFactory.spec.js diff --git a/packages/js-drive/lib/identity/withdrawals/updateWithdrawalTransactionIdAndStatusFactory.js b/packages/js-drive/lib/identity/withdrawals/updateWithdrawalTransactionIdAndStatusFactory.js index 3b601effc20..92a7fe61b53 100644 --- a/packages/js-drive/lib/identity/withdrawals/updateWithdrawalTransactionIdAndStatusFactory.js +++ b/packages/js-drive/lib/identity/withdrawals/updateWithdrawalTransactionIdAndStatusFactory.js @@ -1,7 +1,7 @@ const WITHDRAWALS_DOCUMENT_TYPE = 'withdrawals'; const WITHDRAWALS_STATUS_POOLED = 1; -const WITHDRAWALS_STATUS_BROADCASTED = 1; +const WITHDRAWALS_STATUS_BROADCASTED = 2; /** * @param {DocumentRepository} documentRepository diff --git a/packages/js-drive/test/unit/identity/withdrawals/updateWithdrawalTransactionIdAndStatusFactory.spec.js b/packages/js-drive/test/unit/identity/withdrawals/updateWithdrawalTransactionIdAndStatusFactory.spec.js new file mode 100644 index 00000000000..2afe42b2954 --- /dev/null +++ b/packages/js-drive/test/unit/identity/withdrawals/updateWithdrawalTransactionIdAndStatusFactory.spec.js @@ -0,0 +1,62 @@ +const getDocumentFixture = require('@dashevo/dpp/lib/test/fixtures/getDocumentsFixture'); +const Identifier = require('@dashevo/dpp/lib/identifier/Identifier'); + +const updateWithdrawalTransactionIdAndStatusFactory = require('../../../../lib/identity/withdrawals/updateWithdrawalTransactionIdAndStatusFactory'); +const BlockInfo = require('../../../../lib/blockExecution/BlockInfo'); + +describe('updateWithdrawalTransactionIdAndStatusFactory', () => { + let updateWithdrawalTransactionIdAndStatus; + let withdrawalsContractId; + let documentRepositoryMock; + let fetchDocumentsMock; + let documentFixture; + + beforeEach(function beforeEach() { + documentFixture = getDocumentFixture(); + + withdrawalsContractId = Identifier.from(Buffer.alloc(32)); + + documentRepositoryMock = { + update: this.sinon.stub(), + }; + + fetchDocumentsMock = this.sinon.stub(); + fetchDocumentsMock.resolves([documentFixture[0]]); + + updateWithdrawalTransactionIdAndStatus = updateWithdrawalTransactionIdAndStatusFactory( + documentRepositoryMock, + fetchDocumentsMock, + withdrawalsContractId, + ); + }); + + it('should update documents transactionId, status and revision', async () => { + const blockInfo = new BlockInfo(1, 1, 1); + + const updatedTxId = Buffer.alloc(32, 2); + + await updateWithdrawalTransactionIdAndStatus(blockInfo, Buffer.alloc(0), updatedTxId, { + useTransaction: true, + }); + + expect(fetchDocumentsMock).to.have.been.calledOnceWithExactly( + withdrawalsContractId, + 'withdrawals', + { + where: [ + ['status', '==', 1], + ['transactionId', '==', Buffer.alloc(0)], + ], + useTransaction: true, + }, + ); + + expect(documentRepositoryMock.update).to.have.been.calledOnceWithExactly( + documentFixture[0], blockInfo, { useTransaction: true }, + ); + + expect(documentFixture[0].get('transactionId')).to.deep.equal(updatedTxId); + expect(documentFixture[0].get('status')).to.deep.equal(2); + expect(documentFixture[0].getRevision()).to.deep.equal(2); + }); +}); From 8f28e92470d9ddece0c2c31b8a3c640e7a075e29 Mon Sep 17 00:00:00 2001 From: Djavid Gabibyan Date: Wed, 21 Dec 2022 15:10:59 +0500 Subject: [PATCH 031/170] chore: fixes --- packages/rs-drive-nodejs/test/Drive.spec.js | 2 +- packages/rs-drive/src/drive/mod.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/rs-drive-nodejs/test/Drive.spec.js b/packages/rs-drive-nodejs/test/Drive.spec.js index 6f79492514e..6ef7ad512e3 100644 --- a/packages/rs-drive-nodejs/test/Drive.spec.js +++ b/packages/rs-drive-nodejs/test/Drive.spec.js @@ -26,7 +26,7 @@ const FeeResult = require('../FeeResult'); const TEST_DATA_PATH = './test_data'; -describe('Drive', function describe() { +describe('Drive', function main() { this.timeout(10000); let drive; diff --git a/packages/rs-drive/src/drive/mod.rs b/packages/rs-drive/src/drive/mod.rs index bfa45197f93..ce249987aee 100644 --- a/packages/rs-drive/src/drive/mod.rs +++ b/packages/rs-drive/src/drive/mod.rs @@ -76,7 +76,7 @@ use crate::drive::block_info::BlockInfo; use crate::drive::cache::{DataContractCache, DriveCache}; use crate::fee::FeeResult; use crate::fee_pools::epochs::Epoch; -use crate::rpc::core::{CoreRPCLike, DefaultCoreRPC, MockCoreRPCLike}; +use crate::rpc::core::{CoreRPCLike, DefaultCoreRPC}; use dpp::data_contract::extra::DriveContractExt; type TransactionPointerAddress = usize; From f162762abd6e36240a779a288df05349d22380fa Mon Sep 17 00:00:00 2001 From: Djavid Gabibyan Date: Wed, 21 Dec 2022 20:59:56 +0500 Subject: [PATCH 032/170] chore: use real validator set quorum hash --- .../js-drive/lib/abci/handlers/proposal/beginBlockFactory.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/packages/js-drive/lib/abci/handlers/proposal/beginBlockFactory.js b/packages/js-drive/lib/abci/handlers/proposal/beginBlockFactory.js index 4a859cc23c4..1d730cf002d 100644 --- a/packages/js-drive/lib/abci/handlers/proposal/beginBlockFactory.js +++ b/packages/js-drive/lib/abci/handlers/proposal/beginBlockFactory.js @@ -124,8 +124,7 @@ function beginBlockFactory( blockHeight: height.toNumber(), blockTimeMs: proposalBlockExecutionContext.getTimeMs(), proposerProTxHash, - // TODO replace with real value - validatorSetQuorumHash: Buffer.alloc(32), + validatorSetQuorumHash: lastCommitInfo.quorumHash, coreChainLockedHeight, lastSyncedCoreHeight, }; From 7e272cdfef8d19a1a4dfd59793850d96ed1d7b4c Mon Sep 17 00:00:00 2001 From: Djavid Gabibiyan Date: Wed, 21 Dec 2022 22:40:17 +0500 Subject: [PATCH 033/170] chore: PR fixes --- .../js-drive/lib/abci/handlers/proposal/beginBlockFactory.js | 3 +-- .../lib/abci/handlers/verifyVoteExtensionHandlerFactory.js | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/packages/js-drive/lib/abci/handlers/proposal/beginBlockFactory.js b/packages/js-drive/lib/abci/handlers/proposal/beginBlockFactory.js index 4a859cc23c4..1d730cf002d 100644 --- a/packages/js-drive/lib/abci/handlers/proposal/beginBlockFactory.js +++ b/packages/js-drive/lib/abci/handlers/proposal/beginBlockFactory.js @@ -124,8 +124,7 @@ function beginBlockFactory( blockHeight: height.toNumber(), blockTimeMs: proposalBlockExecutionContext.getTimeMs(), proposerProTxHash, - // TODO replace with real value - validatorSetQuorumHash: Buffer.alloc(32), + validatorSetQuorumHash: lastCommitInfo.quorumHash, coreChainLockedHeight, lastSyncedCoreHeight, }; diff --git a/packages/js-drive/lib/abci/handlers/verifyVoteExtensionHandlerFactory.js b/packages/js-drive/lib/abci/handlers/verifyVoteExtensionHandlerFactory.js index 315151c0426..22d3f645f9f 100644 --- a/packages/js-drive/lib/abci/handlers/verifyVoteExtensionHandlerFactory.js +++ b/packages/js-drive/lib/abci/handlers/verifyVoteExtensionHandlerFactory.js @@ -59,7 +59,7 @@ function verifyVoteExtensionHandlerFactory(proposalBlockExecutionContext) { Math.min(30, extensionString.length), ); - consensusLogger.debug({ + consensusLogger.warn({ type: nextExtension.type, extension: extensionString, }, `${nextExtension.type} vote extension ${extensionTruncatedString}... was not found in verify request`); From aa4b8bbe048da0242ef628b096284c0fafa2a209 Mon Sep 17 00:00:00 2001 From: Djavid Gabibiyan Date: Wed, 21 Dec 2022 23:05:41 +0500 Subject: [PATCH 034/170] chore: PR comments --- .../verifyVoteExtensionHandlerFactory.js | 8 ++++++- .../verifyVoteExtensionHandlerFactory.spec.js | 24 ++++++++++++++++++- 2 files changed, 30 insertions(+), 2 deletions(-) diff --git a/packages/js-drive/lib/abci/handlers/verifyVoteExtensionHandlerFactory.js b/packages/js-drive/lib/abci/handlers/verifyVoteExtensionHandlerFactory.js index 22d3f645f9f..2b87e15e871 100644 --- a/packages/js-drive/lib/abci/handlers/verifyVoteExtensionHandlerFactory.js +++ b/packages/js-drive/lib/abci/handlers/verifyVoteExtensionHandlerFactory.js @@ -45,6 +45,10 @@ function verifyVoteExtensionHandlerFactory(proposalBlockExecutionContext) { extension: Buffer.from(txHashHex, 'hex'), })); + const numberOfVoteExtensionsMatch = ( + voteExtensionsToCheck.length === (voteExtensions || []).length + ); + const allVoteExtensionsPresent = voteExtensionsToCheck.reduce((result, nextExtension) => { const searchedVoteExtension = (voteExtensions || []).find((voteExtension) => ( voteExtension.type === nextExtension.type @@ -68,7 +72,9 @@ function verifyVoteExtensionHandlerFactory(proposalBlockExecutionContext) { return result && (searchedVoteExtension !== undefined); }, true); - const status = allVoteExtensionsPresent ? verifyStatus.ACCEPT : verifyStatus.REJECT; + const status = (numberOfVoteExtensionsMatch && allVoteExtensionsPresent) + ? verifyStatus.ACCEPT + : verifyStatus.REJECT; return new ResponseVerifyVoteExtension({ status, diff --git a/packages/js-drive/test/unit/abci/handlers/verifyVoteExtensionHandlerFactory.spec.js b/packages/js-drive/test/unit/abci/handlers/verifyVoteExtensionHandlerFactory.spec.js index 6f5c1a4e2d6..986c2ac90b1 100644 --- a/packages/js-drive/test/unit/abci/handlers/verifyVoteExtensionHandlerFactory.spec.js +++ b/packages/js-drive/test/unit/abci/handlers/verifyVoteExtensionHandlerFactory.spec.js @@ -33,6 +33,28 @@ describe('verifyVoteExtensionHandlerFactory', () => { ); }); + it('should return ResponseVerifyVoteExtension with REJECT status if vote extensions length not match', async () => { + const voteExtensions = [ + { type: VoteExtensionType.THRESHOLD_RECOVER, extension: Buffer.alloc(32, 1) }, + { type: VoteExtensionType.THRESHOLD_RECOVER, extension: Buffer.alloc(32, 2) }, + { type: VoteExtensionType.THRESHOLD_RECOVER, extension: Buffer.alloc(32, 3) }, + ]; + + const unsignedWithdrawalTransactionsMap = { + [Buffer.alloc(32, 1).toString('hex')]: undefined, + [Buffer.alloc(32, 2).toString('hex')]: undefined, + }; + + proposalBlockExecutionContextMock.getWithdrawalTransactionsMap.returns( + unsignedWithdrawalTransactionsMap, + ); + + const result = await verifyVoteExtensionHandler({ voteExtensions }); + + expect(result).to.be.an.instanceOf(ResponseVerifyVoteExtension); + expect(result.status).to.equal(2); + }); + it('should return ResponseVerifyVoteExtension with REJECT status if vote extension is missing', async () => { const voteExtensions = [ { type: VoteExtensionType.THRESHOLD_RECOVER, extension: Buffer.alloc(32, 1) }, @@ -53,7 +75,7 @@ describe('verifyVoteExtensionHandlerFactory', () => { expect(result.status).to.equal(2); }); - it('should return ResponseVerifyVoteExtension', async () => { + it('should return ACCEPT if everything is fine', async () => { const voteExtensions = [ { type: VoteExtensionType.THRESHOLD_RECOVER, extension: Buffer.alloc(32, 1) }, { type: VoteExtensionType.THRESHOLD_RECOVER, extension: Buffer.alloc(32, 2) }, From c48b4aae86b85169bf9c1213c8fcb310ec7e247b Mon Sep 17 00:00:00 2001 From: Djavid Gabibiyan Date: Wed, 21 Dec 2022 23:08:45 +0500 Subject: [PATCH 035/170] chore: PR comments --- .../lib/abci/handlers/verifyVoteExtensionHandlerFactory.js | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/packages/js-drive/lib/abci/handlers/verifyVoteExtensionHandlerFactory.js b/packages/js-drive/lib/abci/handlers/verifyVoteExtensionHandlerFactory.js index 2b87e15e871..e775a3d962f 100644 --- a/packages/js-drive/lib/abci/handlers/verifyVoteExtensionHandlerFactory.js +++ b/packages/js-drive/lib/abci/handlers/verifyVoteExtensionHandlerFactory.js @@ -27,13 +27,18 @@ function verifyVoteExtensionHandlerFactory(proposalBlockExecutionContext) { * * @return {Promise} */ - async function verifyVoteExtensionHandler({ voteExtensions }) { + async function verifyVoteExtensionHandler(request) { + const { + voteExtensions, + } = request; + const consensusLogger = proposalBlockExecutionContext.getConsensusLogger() .child({ abciMethod: 'verifyVoteExtension', }); consensusLogger.debug('VerifyVote ABCI method requested'); + consensusLogger.trace({ request }); const unsignedWithdrawalTransactionsMap = proposalBlockExecutionContext .getWithdrawalTransactionsMap(); From d7cc213d1f4a890cbdcf3e0a5cca47ac30f67fed Mon Sep 17 00:00:00 2001 From: Djavid Gabibyan Date: Thu, 22 Dec 2022 16:50:31 +0500 Subject: [PATCH 036/170] chore: PR fixes --- packages/rs-drive-abci/Cargo.toml | 2 +- packages/rs-drive-abci/src/abci/handlers.rs | 17 +++++++++-------- packages/rs-drive-nodejs/Cargo.toml | 2 +- packages/rs-drive/Cargo.toml | 2 +- .../identity/withdrawals/withdrawal_status.rs | 13 ++++++++++--- packages/rs-drive/src/rpc/core.rs | 4 ++-- .../document/invalid_document_revision_error.rs | 2 +- .../identity/invalid_identity_revision_error.rs | 2 +- 8 files changed, 26 insertions(+), 18 deletions(-) diff --git a/packages/rs-drive-abci/Cargo.toml b/packages/rs-drive-abci/Cargo.toml index ef7bce0888a..19a1b2bf67e 100644 --- a/packages/rs-drive-abci/Cargo.toml +++ b/packages/rs-drive-abci/Cargo.toml @@ -13,7 +13,7 @@ rust_decimal_macros = "1.25.0" chrono = "0.4.20" serde = { version = "1.0.132", features = ["derive"] } serde_json = { version="1.0", features=["preserve_order"] } -drive = { path = "../rs-drive", features = ["core-rpc-mock"]} +drive = { path = "../rs-drive", features = ["fixtures-and-mocks"]} thiserror = "1.0.30" rand = "0.8.4" tempfile = "3" diff --git a/packages/rs-drive-abci/src/abci/handlers.rs b/packages/rs-drive-abci/src/abci/handlers.rs index a6820b02cee..2cb98bca10e 100644 --- a/packages/rs-drive-abci/src/abci/handlers.rs +++ b/packages/rs-drive-abci/src/abci/handlers.rs @@ -123,14 +123,15 @@ impl TenderdashAbci for Platform { self.block_execution_context .replace(Some(block_execution_context)); - self.drive.update_withdrawal_statuses( - request.last_synced_core_height, - request.core_chain_locked_height, - request.block_time_ms, - request.block_height, - epoch_info.current_epoch_index, - transaction, - )?; + self.drive + .update_broadcasted_withdrawal_transaction_statuses( + request.last_synced_core_height, + request.core_chain_locked_height, + request.block_time_ms, + request.block_height, + epoch_info.current_epoch_index, + transaction, + )?; let unsigned_withdrawal_transaction_bytes = self .fetch_and_prepare_unsigned_withdrawal_transactions( diff --git a/packages/rs-drive-nodejs/Cargo.toml b/packages/rs-drive-nodejs/Cargo.toml index f894514bd69..c832b14481d 100644 --- a/packages/rs-drive-nodejs/Cargo.toml +++ b/packages/rs-drive-nodejs/Cargo.toml @@ -10,7 +10,7 @@ private = true crate-type = ["cdylib"] [dependencies] -drive = { path = "../rs-drive", features = ["core-rpc-mock"]} +drive = { path = "../rs-drive", features = ["fixtures-and-mocks"]} drive-abci = { path = "../rs-drive-abci" } num = "0.4.0" serde_json = { version="1.0", features=["preserve_order"] } diff --git a/packages/rs-drive/Cargo.toml b/packages/rs-drive/Cargo.toml index 6b07ff2fd14..4aeeb324a5c 100644 --- a/packages/rs-drive/Cargo.toml +++ b/packages/rs-drive/Cargo.toml @@ -53,4 +53,4 @@ name = "benchmarks" harness = false [features] -core-rpc-mock = ["mockall"] +fixtures-and-mocks = ["mockall"] diff --git a/packages/rs-drive/src/drive/identity/withdrawals/withdrawal_status.rs b/packages/rs-drive/src/drive/identity/withdrawals/withdrawal_status.rs index fbe165c1c4e..a5926ac61f4 100644 --- a/packages/rs-drive/src/drive/identity/withdrawals/withdrawal_status.rs +++ b/packages/rs-drive/src/drive/identity/withdrawals/withdrawal_status.rs @@ -151,8 +151,8 @@ fn fetch_core_block_transactions( } impl Drive { - /// Update statuses for pending withdrawals - pub fn update_withdrawal_statuses( + /// Update statuses for broadcasted withdrawals + pub fn update_broadcasted_withdrawal_transaction_statuses( &self, last_synced_core_height: u64, core_chain_locked_height: u64, @@ -517,7 +517,14 @@ mod tests { setup_document(&drive, &document_2, &data_contract, Some(&transaction)); drive - .update_withdrawal_statuses(95, 96, 1, 1, 1, Some(&transaction)) + .update_broadcasted_withdrawal_transaction_statuses( + 95, + 96, + 1, + 1, + 1, + Some(&transaction), + ) .expect("to update withdrawal statuses"); let documents = fetch_withdrawal_documents_by_status( diff --git a/packages/rs-drive/src/rpc/core.rs b/packages/rs-drive/src/rpc/core.rs index faa8ac1d6f2..6be8bf436c0 100644 --- a/packages/rs-drive/src/rpc/core.rs +++ b/packages/rs-drive/src/rpc/core.rs @@ -1,11 +1,11 @@ use dashcore::{Block, BlockHash}; use dashcore_rpc::{Auth, Client, Error, RpcApi}; -#[cfg(feature = "core-rpc-mock")] +#[cfg(feature = "fixtures-and-mocks")] use mockall::{automock, predicate::*}; use serde_json::Value; /// Core RPC interface -#[cfg_attr(feature = "core-rpc-mock", automock)] +#[cfg_attr(feature = "fixtures-and-mocks", automock)] pub trait CoreRPCLike { /// Get block hash by height fn get_block_hash(&self, height: u64) -> Result; diff --git a/packages/wasm-dpp/src/errors/consensus/state/document/invalid_document_revision_error.rs b/packages/wasm-dpp/src/errors/consensus/state/document/invalid_document_revision_error.rs index 775af49d543..43af8cd40de 100644 --- a/packages/wasm-dpp/src/errors/consensus/state/document/invalid_document_revision_error.rs +++ b/packages/wasm-dpp/src/errors/consensus/state/document/invalid_document_revision_error.rs @@ -17,7 +17,7 @@ impl InvalidDocumentRevisionErrorWasm { } #[wasm_bindgen(js_name=getCurrentRevision)] - pub fn current_revision(&self) -> u64 { + pub fn current_revision(&self) -> Revision { self.current_revision } diff --git a/packages/wasm-dpp/src/errors/consensus/state/identity/invalid_identity_revision_error.rs b/packages/wasm-dpp/src/errors/consensus/state/identity/invalid_identity_revision_error.rs index e7003ab7c4e..e9882a06f55 100644 --- a/packages/wasm-dpp/src/errors/consensus/state/identity/invalid_identity_revision_error.rs +++ b/packages/wasm-dpp/src/errors/consensus/state/identity/invalid_identity_revision_error.rs @@ -17,7 +17,7 @@ impl InvalidIdentityRevisionErrorWasm { } #[wasm_bindgen(js_name=getCurrentRevision)] - pub fn current_revision(&self) -> u64 { + pub fn current_revision(&self) -> Revision { self.current_revision } From 2597f5daad8c6e24db823514efd466fcad5cfec5 Mon Sep 17 00:00:00 2001 From: Djavid Gabibyan Date: Fri, 23 Dec 2022 12:35:46 +0500 Subject: [PATCH 037/170] chore: moving code around --- packages/rs-drive-abci/src/abci/handlers.rs | 23 +- .../rs-drive-abci/src/common/helpers/setup.rs | 2 +- .../src/identity_credit_withdrawal/mod.rs | 495 +++++++++++++- .../rs-drive/src/drive/document/helpers.rs | 240 +++++++ packages/rs-drive/src/drive/document/mod.rs | 1 + .../src/drive/identity/withdrawals/queue.rs | 619 +++--------------- .../identity/withdrawals/withdrawal_status.rs | 508 ++------------ .../withdrawals/withdrawal_transactions.rs | 377 +++++++---- 8 files changed, 1169 insertions(+), 1096 deletions(-) create mode 100644 packages/rs-drive/src/drive/document/helpers.rs diff --git a/packages/rs-drive-abci/src/abci/handlers.rs b/packages/rs-drive-abci/src/abci/handlers.rs index 2cb98bca10e..cb4518f110f 100644 --- a/packages/rs-drive-abci/src/abci/handlers.rs +++ b/packages/rs-drive-abci/src/abci/handlers.rs @@ -123,15 +123,14 @@ impl TenderdashAbci for Platform { self.block_execution_context .replace(Some(block_execution_context)); - self.drive - .update_broadcasted_withdrawal_transaction_statuses( - request.last_synced_core_height, - request.core_chain_locked_height, - request.block_time_ms, - request.block_height, - epoch_info.current_epoch_index, - transaction, - )?; + self.update_broadcasted_withdrawal_transaction_statuses( + request.last_synced_core_height, + request.core_chain_locked_height, + request.block_time_ms, + request.block_height, + epoch_info.current_epoch_index, + transaction, + )?; let unsigned_withdrawal_transaction_bytes = self .fetch_and_prepare_unsigned_withdrawal_transactions( @@ -164,7 +163,7 @@ impl TenderdashAbci for Platform { ), ))?; - self.drive.pool_withdrawals_into_transactions( + self.pool_withdrawals_into_transactions( block_execution_context.block_info.block_time_ms, block_execution_context.block_info.block_height, block_execution_context.epoch_info.current_epoch_index, @@ -235,7 +234,7 @@ mod tests { setup_system_data_contract( &platform.drive, - get_withdrawals_data_contract_fixture(None), + &get_withdrawals_data_contract_fixture(None), Some(&transaction), ); @@ -488,7 +487,7 @@ mod tests { setup_system_data_contract( &platform.drive, - get_withdrawals_data_contract_fixture(None), + &get_withdrawals_data_contract_fixture(None), Some(&transaction), ); diff --git a/packages/rs-drive-abci/src/common/helpers/setup.rs b/packages/rs-drive-abci/src/common/helpers/setup.rs index 00cc9afe133..16573da7670 100644 --- a/packages/rs-drive-abci/src/common/helpers/setup.rs +++ b/packages/rs-drive-abci/src/common/helpers/setup.rs @@ -66,7 +66,7 @@ pub fn setup_platform_with_initial_state_structure() -> Platform { /// A function to setup system data contract pub fn setup_system_data_contract( drive: &Drive, - data_contract: DataContract, + data_contract: &DataContract, transaction: TransactionArg, ) { drive diff --git a/packages/rs-drive-abci/src/identity_credit_withdrawal/mod.rs b/packages/rs-drive-abci/src/identity_credit_withdrawal/mod.rs index a2ed62bce23..88fbd0776a1 100644 --- a/packages/rs-drive-abci/src/identity_credit_withdrawal/mod.rs +++ b/packages/rs-drive-abci/src/identity_credit_withdrawal/mod.rs @@ -2,10 +2,20 @@ use dashcore::{ blockdata::transaction::special_transaction::asset_unlock::request_info::AssetUnlockRequestInfo, hashes::Hash, QuorumHash, }; -use dpp::util::hash; +use dpp::{ + contracts::withdrawals_contract, + prelude::{Document, Identifier}, + util::{hash, json_value::JsonValueExt, string_encoding::Encoding}, +}; use drive::{ - drive::identity::withdrawals::queue::update_document_transaction_id, query::TransactionArg, + drive::{ + batch::GroveDbOpBatch, + identity::withdrawals::paths::get_withdrawal_transactions_expired_ids_path_as_u8, + }, + fee_pools::epochs::Epoch, + query::{Element, TransactionArg}, }; +use serde_json::{Number, Value as JsonValue}; use crate::{ error::{execution::ExecutionError, Error}, @@ -15,6 +25,131 @@ use crate::{ const WITHDRAWAL_TRANSACTIONS_QUERY_LIMIT: u16 = 16; impl Platform { + /// Update statuses for broadcasted withdrawals + pub fn update_broadcasted_withdrawal_transaction_statuses( + &self, + last_synced_core_height: u64, + core_chain_locked_height: u64, + block_time_ms: u64, + block_height: u64, + current_epoch_index: u16, + transaction: TransactionArg, + ) -> Result<(), Error> { + let (_, maybe_data_contract) = self.drive.get_contract_with_fetch_info( + Identifier::from_string( + &withdrawals_contract::system_ids().contract_id, + Encoding::Base58, + ) + .map_err(|_| { + Error::Execution(ExecutionError::CorruptedCodeExecution( + "Can't create withdrawals id identifier from string", + )) + })? + .to_buffer(), + Some(&Epoch::new(current_epoch_index)), + transaction, + )?; + + let contract_fetch_info = maybe_data_contract.ok_or(Error::Execution( + ExecutionError::CorruptedCodeExecution("Can't fetch withdrawal data contract"), + ))?; + + let core_transactions = self + .drive + .fetch_core_block_transactions(last_synced_core_height, core_chain_locked_height)?; + + let broadcasted_documents = self.drive.fetch_withdrawal_documents_by_status( + withdrawals_contract::statuses::BROADCASTED, + transaction, + )?; + + for mut document in broadcasted_documents { + let transaction_sign_height = + document + .data + .get_u64("transactionSignHeight") + .map_err(|_| { + Error::Execution(ExecutionError::CorruptedCodeExecution( + "Can't get transactionSignHeight from withdrawal document", + )) + })?; + + let transaction_id_bytes = document.data.get_bytes("transactionId").map_err(|_| { + Error::Execution(ExecutionError::CorruptedCodeExecution( + "Can't get transactionId from withdrawal document", + )) + })?; + + let transaction_id = hex::encode(transaction_id_bytes); + + let transaction_index = document.data.get_u64("transactionIndex").map_err(|_| { + Error::Execution(ExecutionError::CorruptedCodeExecution( + "Can't get transactionIdex from withdrawal document", + )) + })?; + + if core_transactions.contains(&transaction_id) + || core_chain_locked_height - transaction_sign_height > 48 + { + let status = if core_transactions.contains(&transaction_id) { + withdrawals_contract::statuses::COMPLETE + } else { + let bytes = transaction_index.to_be_bytes(); + + let path = get_withdrawal_transactions_expired_ids_path_as_u8(); + + self.drive + .grove + .insert( + path, + &bytes, + Element::Item(bytes.to_vec(), None), + None, + transaction, + ) + .unwrap() + .map_err(|_| { + Error::Execution(ExecutionError::CorruptedCodeExecution( + "Can't update transaction_index in GroveDB", + )) + })?; + + withdrawals_contract::statuses::EXPIRED + }; + + self.drive.update_document_data( + &contract_fetch_info.contract, + &mut document, + block_time_ms, + block_height, + current_epoch_index, + transaction, + |document: &mut Document| -> Result<&mut Document, drive::error::Error> { + document + .data + .insert( + "status".to_string(), + JsonValue::Number(Number::from(status)), + ) + .map_err(|_| { + drive::error::Error::Drive( + drive::error::drive::DriveError::CorruptedCodeExecution( + "Can't update document field: status", + ), + ) + })?; + + document.revision += 1; + + Ok(document) + }, + )?; + } + } + + Ok(()) + } + /// Prepares a list of an unsigned withdrawal transaction bytes pub fn fetch_and_prepare_unsigned_withdrawal_transactions( &self, @@ -52,8 +187,7 @@ impl Platform { let original_transaction_id = hash::hash(bytes); let update_transaction_id = hash::hash(bytes_buffer.clone()); - update_document_transaction_id( - &self.drive, + self.drive.update_document_transaction_id( &original_transaction_id, &update_transaction_id, block_time_ms, @@ -66,4 +200,357 @@ impl Platform { }) .collect::>, Error>>() } + + /// Pool withdrawal documents into transactions + pub fn pool_withdrawals_into_transactions( + &self, + block_time_ms: u64, + block_height: u64, + current_epoch_index: u16, + transaction: TransactionArg, + ) -> Result<(), Error> { + let (_, maybe_data_contract) = self.drive.get_contract_with_fetch_info( + Identifier::from_string( + &withdrawals_contract::system_ids().contract_id, + Encoding::Base58, + ) + .map_err(|_| { + Error::Execution(ExecutionError::CorruptedCodeExecution( + "Can't create withdrawals id identifier from string", + )) + })? + .to_buffer(), + Some(&Epoch::new(current_epoch_index)), + transaction, + )?; + + let contract_fetch_info = maybe_data_contract.ok_or(Error::Execution( + ExecutionError::CorruptedCodeExecution("Can't fetch withdrawal data contract"), + ))?; + + let mut documents = self.drive.fetch_withdrawal_documents_by_status( + withdrawals_contract::statuses::QUEUED, + transaction, + )?; + + let withdrawal_transactions = self + .drive + .build_withdrawal_transactions_from_documents(&documents, transaction)?; + + for document in documents.iter_mut() { + let transaction_id = + hash::hash(withdrawal_transactions.get(&document.id).unwrap().1.clone()); + + self.drive.update_document_data( + &contract_fetch_info.contract, + document, + block_time_ms, + block_height, + current_epoch_index, + transaction, + |document: &mut Document| -> Result<&mut Document, drive::error::Error> { + document + .data + .insert( + "transactionId".to_string(), + JsonValue::Array( + transaction_id + .clone() + .into_iter() + .map(|byte| JsonValue::Number(Number::from(byte))) + .collect(), + ), + ) + .map_err(|_| { + drive::error::Error::Drive( + drive::error::drive::DriveError::CorruptedCodeExecution( + "Can't update document field: transactionId", + ), + ) + })?; + + document + .data + .insert( + "status".to_string(), + JsonValue::Number(Number::from(withdrawals_contract::statuses::POOLED)), + ) + .map_err(|_| { + drive::error::Error::Drive( + drive::error::drive::DriveError::CorruptedCodeExecution( + "Can't update document field: status", + ), + ) + })?; + + document.revision += 1; + + Ok(document) + }, + )?; + } + + let mut batch = GroveDbOpBatch::new(); + + let withdrawal_transactions = withdrawal_transactions + .values() + .into_iter() + .cloned() + .collect(); + + self.drive + .add_enqueue_withdrawal_transaction_operations(&mut batch, withdrawal_transactions); + + if !batch.is_empty() { + self.drive.grove_apply_batch(batch, true, transaction)?; + } + + Ok(()) + } +} + +#[cfg(test)] +mod tests { + use dashcore::{ + hashes::hex::{FromHex, ToHex}, + BlockHash, + }; + use dpp::{ + contracts::withdrawals_contract, + tests::fixtures::{get_withdrawal_document_fixture, get_withdrawals_data_contract_fixture}, + }; + use drive::{common::helpers::setup::setup_document, rpc::core::MockCoreRPCLike}; + use serde_json::json; + + use crate::common::helpers::setup::setup_system_data_contract; + + use crate::common::helpers::setup::setup_platform_with_initial_state_structure; + + mod update_withdrawal_statuses { + + use super::*; + + #[test] + fn test_statuses_are_updated() { + let mut platform = setup_platform_with_initial_state_structure(); + + let mut mock_rpc_client = MockCoreRPCLike::new(); + + mock_rpc_client + .expect_get_block_hash() + .withf(|height| *height == 95) + .returning(|_| { + Ok(BlockHash::from_hex( + "0000000000000000000000000000000000000000000000000000000000000000", + ) + .unwrap()) + }); + + mock_rpc_client + .expect_get_block_hash() + .withf(|height| *height == 96) + .returning(|_| { + Ok(BlockHash::from_hex( + "1111111111111111111111111111111111111111111111111111111111111111", + ) + .unwrap()) + }); + + mock_rpc_client + .expect_get_block_json() + .withf(|bh| { + bh.to_hex() + == "0000000000000000000000000000000000000000000000000000000000000000" + }) + .returning(|_| { + Ok(json!({ + "tx": ["0101010101010101010101010101010101010101010101010101010101010101"] + })) + }); + + mock_rpc_client + .expect_get_block_json() + .withf(|bh| { + bh.to_hex() + == "1111111111111111111111111111111111111111111111111111111111111111" + }) + .returning(|_| { + Ok(json!({ + "tx": ["0202020202020202020202020202020202020202020202020202020202020202"] + })) + }); + + platform.drive.core_rpc = Some(Box::new(mock_rpc_client)); + + let transaction = platform.drive.grove.start_transaction(); + + let data_contract = get_withdrawals_data_contract_fixture(None); + + setup_system_data_contract(&platform.drive, &data_contract, Some(&transaction)); + + let document_1 = get_withdrawal_document_fixture( + &data_contract, + json!({ + "amount": 1000, + "coreFeePerByte": 1, + "pooling": 0, // TODO: use constant + "outputScript": (0..23).collect::>(), + "status": withdrawals_contract::statuses::BROADCASTED, + "transactionIndex": 1, + "transactionSignHeight": 93, + "transactionId": vec![1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], + }), + ); + + setup_document( + &platform.drive, + &document_1, + &data_contract, + Some(&transaction), + ); + + let document_2 = get_withdrawal_document_fixture( + &data_contract, + json!({ + "amount": 1000, + "coreFeePerByte": 1, + "pooling": 0, + "outputScript": (0..23).collect::>(), + "status": withdrawals_contract::statuses::BROADCASTED, + "transactionIndex": 2, + "transactionSignHeight": 10, + "transactionId": vec![3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], + }), + ); + + setup_document( + &platform.drive, + &document_2, + &data_contract, + Some(&transaction), + ); + + platform + .update_broadcasted_withdrawal_transaction_statuses( + 95, + 96, + 1, + 1, + 1, + Some(&transaction), + ) + .expect("to update withdrawal statuses"); + + let documents = platform + .drive + .fetch_withdrawal_documents_by_status( + withdrawals_contract::statuses::EXPIRED, + Some(&transaction), + ) + .expect("to fetch documents by status"); + + assert_eq!(documents.len(), 1); + assert_eq!(documents.get(0).unwrap().id, document_2.id); + + let documents = platform + .drive + .fetch_withdrawal_documents_by_status( + withdrawals_contract::statuses::COMPLETE, + Some(&transaction), + ) + .expect("to fetch documents by status"); + + assert_eq!(documents.len(), 1); + assert_eq!(documents.get(0).unwrap().id, document_1.id); + } + } + + mod pool_withdrawals_into_transactions { + + use super::*; + + #[test] + fn test_pooling() { + let mut platform = setup_platform_with_initial_state_structure(); + + let transaction = platform.drive.grove.start_transaction(); + + let data_contract = get_withdrawals_data_contract_fixture(None); + + setup_system_data_contract(&platform.drive, &data_contract, Some(&transaction)); + + let document_1 = get_withdrawal_document_fixture( + &data_contract, + json!({ + "amount": 1000, + "coreFeePerByte": 1, + "pooling": 0, + "outputScript": (0..23).collect::>(), + "status": withdrawals_contract::statuses::QUEUED, + "transactionIndex": 1, + }), + ); + + setup_document( + &platform.drive, + &document_1, + &data_contract, + Some(&transaction), + ); + + let document_2 = get_withdrawal_document_fixture( + &data_contract, + json!({ + "amount": 1000, + "coreFeePerByte": 1, + "pooling": 0, + "outputScript": (0..23).collect::>(), + "status": withdrawals_contract::statuses::QUEUED, + "transactionIndex": 2, + }), + ); + + setup_document( + &platform.drive, + &document_2, + &data_contract, + Some(&transaction), + ); + + platform + .pool_withdrawals_into_transactions(1, 1, 1, Some(&transaction)) + .expect("to pool withdrawal documents into transactions"); + + let updated_documents = platform + .drive + .fetch_withdrawal_documents_by_status( + withdrawals_contract::statuses::POOLED, + Some(&transaction), + ) + .expect("to fetch withdrawal documents"); + + let tx_ids = [ + "73050b2f1cdc267ecd9ccd10038e4c957fc108a404704e83077a593787b5f122", + "de7889314e9dcfc6f7b142c18acc3bd1ccbee5f37d525651cdb3d5ce7fe66700", + ]; + + for document in updated_documents { + assert_eq!(document.revision, 2); + + let tx_id: Vec = document + .data + .get("transactionId") + .unwrap() + .as_array() + .unwrap() + .iter() + .map(|byte| byte.as_u64().unwrap() as u8) + .collect(); + + let tx_id_hex = hex::encode(tx_id); + + assert!(tx_ids.contains(&tx_id_hex.as_str())); + } + } + } } diff --git a/packages/rs-drive/src/drive/document/helpers.rs b/packages/rs-drive/src/drive/document/helpers.rs new file mode 100644 index 00000000000..a721e0ab900 --- /dev/null +++ b/packages/rs-drive/src/drive/document/helpers.rs @@ -0,0 +1,240 @@ +use dpp::{ + contracts::withdrawals_contract, + data_contract::extra::common, + prelude::{DataContract, Document, Identifier}, + util::{json_value::JsonValueExt, string_encoding::Encoding}, +}; +use grovedb::TransactionArg; +use serde_json::{json, Number, Value as JsonValue}; + +use crate::{ + drive::{block_info::BlockInfo, Drive}, + error::{drive::DriveError, Error}, + fee_pools::epochs::Epoch, +}; + +impl Drive { + /// Helper function to avoid boilerplate of calling an update + pub fn update_document_data( + &self, + contract: &DataContract, + document: &mut Document, + block_time_ms: u64, + block_height: u64, + current_epoch_index: u16, + transaction: TransactionArg, + update_fn: F, + ) -> Result<(), Error> + where + F: Fn(&mut Document) -> Result<&mut Document, Error>, + { + let document = update_fn(document)?; + + self.update_document_for_contract_cbor( + &document.to_cbor().map_err(|_| { + Error::Drive(DriveError::CorruptedCodeExecution( + "Can't cbor withdrawal document", + )) + })?, + &contract.to_cbor().map_err(|_| { + Error::Drive(DriveError::CorruptedCodeExecution( + "Can't cbor withdrawal data contract", + )) + })?, + withdrawals_contract::types::WITHDRAWAL, + Some(document.owner_id.to_buffer()), + BlockInfo { + time_ms: block_time_ms, + height: block_height, + epoch: Epoch::new(current_epoch_index), + }, + true, + None, + transaction, + )?; + + Ok(()) + } + + /// Helper function to find document by original transactionId + /// and update document transactionId to new one + pub fn update_document_transaction_id( + &self, + original_transaction_id: &[u8], + update_transaction_id: &[u8], + block_time_ms: u64, + block_height: u64, + current_epoch_index: u16, + transaction: TransactionArg, + ) -> Result<(), Error> { + let data_contract_id = Identifier::from_string( + &withdrawals_contract::system_ids().contract_id, + Encoding::Base58, + ) + .map_err(|_| { + Error::Drive(DriveError::CorruptedCodeExecution( + "Can't create withdrawals id identifier from string", + )) + })?; + + let (_, maybe_data_contract) = self.get_contract_with_fetch_info( + data_contract_id.to_buffer(), + Some(&Epoch::new(current_epoch_index)), + transaction, + )?; + + let contract_fetch_info = maybe_data_contract.ok_or(Error::Drive( + DriveError::CorruptedCodeExecution("Can't fetch withdrawal data contract"), + ))?; + + let query_value = json!({ + "where": [ + ["transactionId", "==", original_transaction_id], + ["status", "==", withdrawals_contract::statuses::POOLED], + ], + }); + + let query_cbor = common::value_to_cbor(query_value, None); + + let (documents, _, _) = self.query_documents( + &query_cbor, + data_contract_id.to_buffer(), + withdrawals_contract::types::WITHDRAWAL, + None, + transaction, + )?; + + let documents = documents + .into_iter() + .map(|document_cbor| { + Document::from_cbor(document_cbor).map_err(|_| { + Error::Drive(DriveError::CorruptedCodeExecution( + "Can't create a document from cbor", + )) + }) + }) + .collect::, Error>>()?; + + for mut document in documents { + self.update_document_data( + &contract_fetch_info.contract, + &mut document, + block_time_ms, + block_height, + current_epoch_index, + transaction, + |document: &mut Document| -> Result<&mut Document, Error> { + document + .data + .insert( + "transactionId".to_string(), + JsonValue::Array( + update_transaction_id + .iter() + .map(|byte| JsonValue::Number(Number::from(*byte))) + .collect(), + ), + ) + .map_err(|_| { + Error::Drive(DriveError::CorruptedCodeExecution( + "Can't update document field: transactionId", + )) + })?; + + document.revision += 1; + + Ok(document) + }, + )?; + } + + Ok(()) + } +} + +#[cfg(test)] +mod tests { + use dpp::{ + contracts::withdrawals_contract, + tests::fixtures::{get_withdrawal_document_fixture, get_withdrawals_data_contract_fixture}, + }; + use serde_json::json; + + use crate::common::helpers::setup::{ + setup_document, setup_drive_with_initial_state_structure, setup_system_data_contract, + }; + + mod update_document_transaction_id { + use super::*; + + #[test] + fn test_transaction_id_updated() { + let drive = setup_drive_with_initial_state_structure(); + + let transaction = drive.grove.start_transaction(); + + let data_contract = get_withdrawals_data_contract_fixture(None); + + setup_system_data_contract(&drive, &data_contract, Some(&transaction)); + + let original_transaction_id: Vec = vec![ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, + ]; + + let updated_transaction_id: Vec = vec![ + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, + ]; + + let document = get_withdrawal_document_fixture( + &data_contract, + json!({ + "amount": 1000, + "coreFeePerByte": 1, + "pooling": 0, + "outputScript": (0..23).collect::>(), + "status": withdrawals_contract::statuses::POOLED, + "transactionIndex": 1, + "transactionId": original_transaction_id, + }), + ); + + setup_document(&drive, &document, &data_contract, Some(&transaction)); + + drive + .update_document_transaction_id( + &original_transaction_id, + &updated_transaction_id, + 1, + 1, + 1, + Some(&transaction), + ) + .expect("to update transactionId"); + + let updated_documents = drive + .fetch_withdrawal_documents_by_status( + withdrawals_contract::statuses::POOLED, + Some(&transaction), + ) + .expect("to fetch withdrawal documents"); + + assert_eq!(updated_documents.len(), 1); + + let stored_transaction_id: Vec = updated_documents + .get(0) + .unwrap() + .data + .get("transactionId") + .unwrap() + .as_array() + .unwrap() + .iter() + .map(|byte| byte.as_u64().unwrap() as u8) + .collect(); + + assert_eq!(stored_transaction_id, updated_transaction_id); + } + } +} diff --git a/packages/rs-drive/src/drive/document/mod.rs b/packages/rs-drive/src/drive/document/mod.rs index 87f51e4d1fc..675a51781f7 100644 --- a/packages/rs-drive/src/drive/document/mod.rs +++ b/packages/rs-drive/src/drive/document/mod.rs @@ -45,6 +45,7 @@ use grovedb::Element; mod delete; mod estimation_costs; +mod helpers; mod insert; mod update; diff --git a/packages/rs-drive/src/drive/identity/withdrawals/queue.rs b/packages/rs-drive/src/drive/identity/withdrawals/queue.rs index 5364ecd9979..2847dc9bc24 100644 --- a/packages/rs-drive/src/drive/identity/withdrawals/queue.rs +++ b/packages/rs-drive/src/drive/identity/withdrawals/queue.rs @@ -1,553 +1,150 @@ -use std::collections::HashMap; +use std::ops::RangeFull; -use dashcore::{ - blockdata::transaction::special_transaction::asset_unlock::unqualified_asset_unlock::{ - AssetUnlockBasePayload, AssetUnlockBaseTransactionInfo, - }, - consensus::Encodable, - Script, TxOut, +use grovedb::{ + query_result_type::QueryResultType, Element, PathQuery, Query, QueryItem, SizedQuery, + TransactionArg, }; -use dpp::{ - contracts::withdrawals_contract, - data_contract::extra::common, - identity::convert_credits_to_satoshi, - prelude::{Document, Identifier}, - util::{hash, json_value::JsonValueExt, string_encoding::Encoding}, -}; -use grovedb::TransactionArg; -use serde_json::{json, Number, Value as JsonValue}; use crate::{ - drive::{batch::GroveDbOpBatch, Drive}, + drive::{batch::GroveDbOpBatch, grove_operations::BatchDeleteApplyType, Drive}, error::{drive::DriveError, Error}, - fee_pools::epochs::Epoch, + fee::op::DriveOperation, }; -use super::{ - paths::WithdrawalTransaction, - withdrawal_status::{fetch_withdrawal_documents_by_status, update_document_data}, +use super::paths::{ + get_withdrawal_transactions_queue_path, get_withdrawal_transactions_queue_path_as_u8, + WithdrawalTransaction, }; -fn build_withdrawal_transactions_from_documents( - drive: &Drive, - documents: &[Document], - transaction: TransactionArg, -) -> Result, Error> { - let mut withdrawals: HashMap = HashMap::new(); - - let latest_withdrawal_index = drive.fetch_latest_withdrawal_transaction_index(transaction)?; - - for (i, document) in documents.iter().enumerate() { - let output_script = document.data.get_bytes("outputScript").map_err(|_| { - Error::Drive(DriveError::CorruptedCodeExecution( - "Can't get outputScript from withdrawal document", - )) - })?; - - let amount = document.data.get_u64("amount").map_err(|_| { - Error::Drive(DriveError::CorruptedCodeExecution( - "Can't get amount from withdrawal document", - )) - })?; - - let core_fee_per_byte = document.data.get_u64("coreFeePerByte").map_err(|_| { - Error::Drive(DriveError::CorruptedCodeExecution( - "Can't get coreFeePerByte from withdrawal document", - )) - })?; - - let state_transition_size = 184; - - let output_script: Script = Script::from(output_script); - - let tx_out = TxOut { - value: convert_credits_to_satoshi(amount), - script_pubkey: output_script, - }; - - let transaction_index = latest_withdrawal_index + i as u64; - - let withdrawal_transaction = AssetUnlockBaseTransactionInfo { - version: 1, - lock_time: 0, - output: vec![tx_out], - base_payload: AssetUnlockBasePayload { - version: 1, - index: transaction_index, - fee: (state_transition_size * core_fee_per_byte * 1000) as u32, - }, - }; - - let mut transaction_buffer: Vec = vec![]; - - withdrawal_transaction - .consensus_encode(&mut transaction_buffer) - .map_err(|_| { - Error::Drive(DriveError::CorruptedCodeExecution( - "Can't consensus encode a withdrawal transaction", - )) - })?; - - withdrawals.insert( - document.id.clone(), - ( - transaction_index.to_be_bytes().to_vec(), - transaction_buffer.clone(), - ), - ); - } - - Ok(withdrawals) -} - -/// Helper function to find document by original transactionId -/// and update document transactionId to new one -pub fn update_document_transaction_id( - drive: &Drive, - original_transaction_id: &[u8], - update_transaction_id: &[u8], - block_time_ms: u64, - block_height: u64, - current_epoch_index: u16, - transaction: TransactionArg, -) -> Result<(), Error> { - let data_contract_id = Identifier::from_string( - &withdrawals_contract::system_ids().contract_id, - Encoding::Base58, - ) - .map_err(|_| { - Error::Drive(DriveError::CorruptedCodeExecution( - "Can't create withdrawals id identifier from string", - )) - })?; - - let (_, maybe_data_contract) = drive.get_contract_with_fetch_info( - data_contract_id.to_buffer(), - Some(&Epoch::new(current_epoch_index)), - transaction, - )?; - - let contract_fetch_info = maybe_data_contract.ok_or(Error::Drive( - DriveError::CorruptedCodeExecution("Can't fetch withdrawal data contract"), - ))?; - - let query_value = json!({ - "where": [ - ["transactionId", "==", original_transaction_id], - ["status", "==", withdrawals_contract::statuses::POOLED], - ], - }); - - let query_cbor = common::value_to_cbor(query_value, None); - - let (documents, _, _) = drive.query_documents( - &query_cbor, - data_contract_id.to_buffer(), - withdrawals_contract::types::WITHDRAWAL, - None, - transaction, - )?; - - let documents = documents - .into_iter() - .map(|document_cbor| { - Document::from_cbor(document_cbor).map_err(|_| { - Error::Drive(DriveError::CorruptedCodeExecution( - "Can't create a document from cbor", - )) - }) - }) - .collect::, Error>>()?; - - for mut document in documents { - update_document_data( - drive, - &contract_fetch_info.contract, - &mut document, - block_time_ms, - block_height, - current_epoch_index, - transaction, - |document: &mut Document| -> Result<&mut Document, Error> { - document - .data - .insert( - "transactionId".to_string(), - JsonValue::Array( - update_transaction_id - .iter() - .map(|byte| JsonValue::Number(Number::from(*byte))) - .collect(), - ), - ) - .map_err(|_| { - Error::Drive(DriveError::CorruptedCodeExecution( - "Can't update document field: transactionId", - )) - })?; - - document.revision += 1; - - Ok(document) - }, - )?; +impl Drive { + /// Add insert operations for withdrawal transactions to the batch + pub fn add_enqueue_withdrawal_transaction_operations( + &self, + batch: &mut GroveDbOpBatch, + withdrawals: Vec, + ) { + for (id, bytes) in withdrawals { + batch.add_insert( + get_withdrawal_transactions_queue_path(), + id, + Element::Item(bytes, None), + ); + } } - Ok(()) -} - -impl Drive { - /// Pool withdrawal documents into transactions - pub fn pool_withdrawals_into_transactions( + /// Get specified amount of withdrawal transactions from the DB + pub fn dequeue_withdrawal_transactions( &self, - block_time_ms: u64, - block_height: u64, - current_epoch_index: u16, + num_of_transactions: u16, transaction: TransactionArg, - ) -> Result<(), Error> { - let (_, maybe_data_contract) = self.get_contract_with_fetch_info( - Identifier::from_string( - &withdrawals_contract::system_ids().contract_id, - Encoding::Base58, - ) - .map_err(|_| { - Error::Drive(DriveError::CorruptedCodeExecution( - "Can't create withdrawals id identifier from string", - )) - })? - .to_buffer(), - Some(&Epoch::new(current_epoch_index)), - transaction, - )?; - - let contract_fetch_info = maybe_data_contract.ok_or(Error::Drive( - DriveError::CorruptedCodeExecution("Can't fetch withdrawal data contract"), - ))?; + ) -> Result, Error> { + let mut query = Query::new(); - let mut documents = fetch_withdrawal_documents_by_status( - self, - withdrawals_contract::statuses::QUEUED, - transaction, - )?; + query.insert_item(QueryItem::RangeFull(RangeFull)); - let withdrawal_transactions = - build_withdrawal_transactions_from_documents(self, &documents, transaction)?; - - for document in documents.iter_mut() { - let transaction_id = - hash::hash(withdrawal_transactions.get(&document.id).unwrap().1.clone()); + let path_query = PathQuery { + path: get_withdrawal_transactions_queue_path(), + query: SizedQuery { + query, + limit: Some(num_of_transactions), + offset: None, + }, + }; - update_document_data( - self, - &contract_fetch_info.contract, - document, - block_time_ms, - block_height, - current_epoch_index, + let result_items = self + .grove + .query_raw( + &path_query, + QueryResultType::QueryKeyElementPairResultType, transaction, - |document: &mut Document| -> Result<&mut Document, Error> { - document - .data - .insert( - "transactionId".to_string(), - JsonValue::Array( - transaction_id - .clone() - .into_iter() - .map(|byte| JsonValue::Number(Number::from(byte))) - .collect(), - ), - ) - .map_err(|_| { - Error::Drive(DriveError::CorruptedCodeExecution( - "Can't update document field: transactionId", - )) - })?; - - document - .data - .insert( - "status".to_string(), - JsonValue::Number(Number::from(withdrawals_contract::statuses::POOLED)), - ) - .map_err(|_| { - Error::Drive(DriveError::CorruptedCodeExecution( - "Can't update document field: status", - )) - })?; - - document.revision += 1; - - Ok(document) - }, - )?; - } - - let mut batch = GroveDbOpBatch::new(); + ) + .unwrap() + .map_err(Error::GroveDB)? + .0 + .to_key_elements(); - let withdrawal_transactions = withdrawal_transactions - .values() + let withdrawals = result_items .into_iter() - .cloned() - .collect(); - - self.add_enqueue_withdrawal_transaction_operations(&mut batch, withdrawal_transactions); + .map(|(id, element)| match element { + Element::Item(bytes, _) => Ok((id, bytes)), + _ => Err(Error::Drive(DriveError::CorruptedWithdrawalNotItem( + "withdrawal is not an item", + ))), + }) + .collect::, Vec)>, Error>>()?; + + if !withdrawals.is_empty() { + let mut batch_operations: Vec = vec![]; + let mut drive_operations: Vec = vec![]; + + let withdrawals_path: [&[u8]; 2] = get_withdrawal_transactions_queue_path_as_u8(); + + for (id, _) in withdrawals.iter() { + self.batch_delete( + withdrawals_path, + id, + // we know that we are not deleting a subtree + BatchDeleteApplyType::StatefulBatchDelete { + is_known_to_be_subtree_with_sum: Some((false, false)), + }, + transaction, + &mut batch_operations, + )?; + } - if !batch.is_empty() { - self.grove_apply_batch(batch, true, transaction)?; + self.apply_batch_drive_operations( + None, + transaction, + batch_operations, + &mut drive_operations, + )?; } - Ok(()) + Ok(withdrawals) } } #[cfg(test)] mod tests { - use dpp::{ - contracts::withdrawals_contract, - tests::fixtures::{get_withdrawal_document_fixture, get_withdrawals_data_contract_fixture}, + use crate::{ + common::helpers::setup::setup_drive_with_initial_state_structure, + drive::batch::GroveDbOpBatch, }; - use serde_json::json; - use crate::common::helpers::setup::{ - setup_document, setup_drive_with_initial_state_structure, setup_system_data_contract, - }; - - use crate::drive::identity::withdrawals::withdrawal_status::fetch_withdrawal_documents_by_status; - - mod build_withdrawal_transactions_from_documents { - - use crate::drive::identity::withdrawals::{ - paths::WithdrawalTransaction, queue::build_withdrawal_transactions_from_documents, - }; - - use super::*; - - #[test] - fn test_build() { - let drive = setup_drive_with_initial_state_structure(); - - let transaction = drive.grove.start_transaction(); - - let data_contract = get_withdrawals_data_contract_fixture(None); - - setup_system_data_contract(&drive, &data_contract, Some(&transaction)); - - let document_1 = get_withdrawal_document_fixture( - &data_contract, - json!({ - "amount": 1000, - "coreFeePerByte": 1, - "pooling": 0, - "outputScript": (0..23).collect::>(), - "status": withdrawals_contract::statuses::POOLED, - "transactionIndex": 1, - }), - ); - - setup_document(&drive, &document_1, &data_contract, Some(&transaction)); - - let document_2 = get_withdrawal_document_fixture( - &data_contract, - json!({ - "amount": 1000, - "coreFeePerByte": 1, - "pooling": 0, - "outputScript": (0..23).collect::>(), - "status": withdrawals_contract::statuses::POOLED, - "transactionIndex": 2, - }), - ); - - setup_document(&drive, &document_2, &data_contract, Some(&transaction)); - - let documents = vec![document_1, document_2]; - - let transactions = build_withdrawal_transactions_from_documents( - &drive, - &documents, - Some(&transaction), - ) - .expect("to build transactions from documents"); - - assert_eq!( - transactions - .values() - .cloned() - .collect::>(), - vec![ - ( - vec![0, 0, 0, 0, 0, 0, 0, 0], - vec![ - 1, 0, 9, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 23, 0, 1, 2, 3, 4, 5, 6, 7, - 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 0, 0, 0, 0, - 1, 0, 0, 0, 0, 0, 0, 0, 0, 192, 206, 2, 0, - ], - ), - ( - vec![0, 0, 0, 0, 0, 0, 0, 1], - vec![ - 1, 0, 9, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 23, 0, 1, 2, 3, 4, 5, 6, 7, - 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 0, 0, 0, 0, - 1, 1, 0, 0, 0, 0, 0, 0, 0, 192, 206, 2, 0, - ], - ), - ], - ); - } - } - - mod pool_withdrawals_into_transactions { - - use super::*; - - #[test] - fn test_pooling() { - let drive = setup_drive_with_initial_state_structure(); - - let transaction = drive.grove.start_transaction(); - - let data_contract = get_withdrawals_data_contract_fixture(None); + #[test] + fn test_enqueue_and_dequeue() { + let drive = setup_drive_with_initial_state_structure(); - setup_system_data_contract(&drive, &data_contract, Some(&transaction)); + let transaction = drive.grove.start_transaction(); - let document_1 = get_withdrawal_document_fixture( - &data_contract, - json!({ - "amount": 1000, - "coreFeePerByte": 1, - "pooling": 0, - "outputScript": (0..23).collect::>(), - "status": withdrawals_contract::statuses::QUEUED, - "transactionIndex": 1, - }), - ); - - setup_document(&drive, &document_1, &data_contract, Some(&transaction)); - - let document_2 = get_withdrawal_document_fixture( - &data_contract, - json!({ - "amount": 1000, - "coreFeePerByte": 1, - "pooling": 0, - "outputScript": (0..23).collect::>(), - "status": withdrawals_contract::statuses::QUEUED, - "transactionIndex": 2, - }), - ); - - setup_document(&drive, &document_2, &data_contract, Some(&transaction)); - - drive - .pool_withdrawals_into_transactions(1, 1, 1, Some(&transaction)) - .expect("to pool withdrawal documents into transactions"); - - let updated_documents = fetch_withdrawal_documents_by_status( - &drive, - withdrawals_contract::statuses::POOLED, - Some(&transaction), - ) - .expect("to fetch withdrawal documents"); - - let tx_ids = [ - "73050b2f1cdc267ecd9ccd10038e4c957fc108a404704e83077a593787b5f122", - "de7889314e9dcfc6f7b142c18acc3bd1ccbee5f37d525651cdb3d5ce7fe66700", - ]; - - for document in updated_documents { - assert_eq!(document.revision, 2); - - let tx_id: Vec = document - .data - .get("transactionId") - .unwrap() - .as_array() - .unwrap() - .iter() - .map(|byte| byte.as_u64().unwrap() as u8) - .collect(); - - let tx_id_hex = hex::encode(tx_id); - - assert!(tx_ids.contains(&tx_id_hex.as_str())); - } - } - } - - mod update_document_transaction_id { - use crate::drive::identity::withdrawals::queue::update_document_transaction_id; - - use super::*; - - #[test] - fn test_transaction_id_updated() { - let drive = setup_drive_with_initial_state_structure(); - - let transaction = drive.grove.start_transaction(); - - let data_contract = get_withdrawals_data_contract_fixture(None); + let withdrawals: Vec<(Vec, Vec)> = (0..17) + .map(|i: u8| (i.to_be_bytes().to_vec(), vec![i; 32])) + .collect(); - setup_system_data_contract(&drive, &data_contract, Some(&transaction)); + let mut batch = GroveDbOpBatch::new(); - let original_transaction_id: Vec = vec![ - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, - ]; + drive.add_enqueue_withdrawal_transaction_operations(&mut batch, withdrawals); - let updated_transaction_id: Vec = vec![ - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, - ]; + drive + .grove_apply_batch(batch, true, Some(&transaction)) + .expect("to apply ops"); - let document = get_withdrawal_document_fixture( - &data_contract, - json!({ - "amount": 1000, - "coreFeePerByte": 1, - "pooling": 0, - "outputScript": (0..23).collect::>(), - "status": withdrawals_contract::statuses::POOLED, - "transactionIndex": 1, - "transactionId": original_transaction_id, - }), - ); + let withdrawals = drive + .dequeue_withdrawal_transactions(16, Some(&transaction)) + .expect("to dequeue withdrawals"); - setup_document(&drive, &document, &data_contract, Some(&transaction)); + assert_eq!(withdrawals.len(), 16); - update_document_transaction_id( - &drive, - &original_transaction_id, - &updated_transaction_id, - 1, - 1, - 1, - Some(&transaction), - ) - .expect("to update transactionId"); + let withdrawals = drive + .dequeue_withdrawal_transactions(16, Some(&transaction)) + .expect("to dequeue withdrawals"); - let updated_documents = fetch_withdrawal_documents_by_status( - &drive, - withdrawals_contract::statuses::POOLED, - Some(&transaction), - ) - .expect("to fetch withdrawal documents"); - - assert_eq!(updated_documents.len(), 1); + assert_eq!(withdrawals.len(), 1); - let stored_transaction_id: Vec = updated_documents - .get(0) - .unwrap() - .data - .get("transactionId") - .unwrap() - .as_array() - .unwrap() - .iter() - .map(|byte| byte.as_u64().unwrap() as u8) - .collect(); + let withdrawals = drive + .dequeue_withdrawal_transactions(16, Some(&transaction)) + .expect("to dequeue withdrawals"); - assert_eq!(stored_transaction_id, updated_transaction_id); - } + assert_eq!(withdrawals.len(), 0); } } diff --git a/packages/rs-drive/src/drive/identity/withdrawals/withdrawal_status.rs b/packages/rs-drive/src/drive/identity/withdrawals/withdrawal_status.rs index a5926ac61f4..b2258ec3bf8 100644 --- a/packages/rs-drive/src/drive/identity/withdrawals/withdrawal_status.rs +++ b/packages/rs-drive/src/drive/identity/withdrawals/withdrawal_status.rs @@ -1,167 +1,37 @@ use dpp::{ contracts::withdrawals_contract, data_contract::extra::common, - prelude::{DataContract, Document, Identifier}, - util::{json_value::JsonValueExt, string_encoding::Encoding}, + prelude::{Document, Identifier}, + util::string_encoding::Encoding, }; -use grovedb::{Element, TransactionArg}; -use serde_json::{json, Number, Value as JsonValue}; +use grovedb::TransactionArg; +use serde_json::json; use crate::{ - drive::{block_info::BlockInfo, Drive}, + drive::Drive, error::{drive::DriveError, Error}, - fee_pools::epochs::Epoch, }; -use super::paths::get_withdrawal_transactions_expired_ids_path_as_u8; - -pub(crate) fn fetch_withdrawal_documents_by_status( - drive: &Drive, - status: u8, - transaction: TransactionArg, -) -> Result, Error> { - let query_value = json!({ - "where": [ - ["status", "==", status], - ], - "orderBy": [ - ["$createdAt", "desc"], - ] - }); - - let query_cbor = common::value_to_cbor(query_value, None); - - let (documents, _, _) = drive.query_documents( - &query_cbor, - Identifier::from_string( - &withdrawals_contract::system_ids().contract_id, - Encoding::Base58, - ) - .map_err(|_| { - Error::Drive(DriveError::CorruptedCodeExecution( - "Can't create withdrawals id identifier from string", - )) - })? - .to_buffer(), - withdrawals_contract::types::WITHDRAWAL, - None, - transaction, - )?; - - let documents = documents - .into_iter() - .map(|document_cbor| { - Document::from_cbor(document_cbor).map_err(|_| { - Error::Drive(DriveError::CorruptedCodeExecution( - "Can't create a document from cbor", - )) - }) - }) - .collect::, Error>>()?; - - Ok(documents) -} - -pub(crate) fn update_document_data( - drive: &Drive, - contract: &DataContract, - document: &mut Document, - block_time_ms: u64, - block_height: u64, - current_epoch_index: u16, - transaction: TransactionArg, - update_fn: F, -) -> Result<(), Error> -where - F: Fn(&mut Document) -> Result<&mut Document, Error>, -{ - let document = update_fn(document)?; - - drive.update_document_for_contract_cbor( - &document.to_cbor().map_err(|_| { - Error::Drive(DriveError::CorruptedCodeExecution( - "Can't cbor withdrawal document", - )) - })?, - &contract.to_cbor().map_err(|_| { - Error::Drive(DriveError::CorruptedCodeExecution( - "Can't cbor withdrawal data contract", - )) - })?, - withdrawals_contract::types::WITHDRAWAL, - Some(document.owner_id.to_buffer()), - BlockInfo { - time_ms: block_time_ms, - height: block_height, - epoch: Epoch::new(current_epoch_index), - }, - true, - None, - transaction, - )?; - - Ok(()) -} - -fn fetch_core_block_transactions( - drive: &Drive, - last_synced_core_height: u64, - core_chain_locked_height: u64, -) -> Result, Error> { - let core_rpc = - drive - .core_rpc - .as_ref() - .ok_or(Error::Drive(DriveError::CorruptedCodeExecution( - "Core RPC client has not been set up", - )))?; - - let mut tx_hashes: Vec = vec![]; - - for height in last_synced_core_height..=core_chain_locked_height { - let block_hash = core_rpc.get_block_hash(height).map_err(|_| { - Error::Drive(DriveError::CorruptedCodeExecution( - "could not get block by height", - )) - })?; - - let block_json: JsonValue = core_rpc.get_block_json(&block_hash).map_err(|_| { - Error::Drive(DriveError::CorruptedCodeExecution( - "could not get block by hash", - )) - })?; - - if let Some(transactions) = block_json.get("tx") { - if let Some(transactions) = transactions.as_array() { - for transaction_hash in transactions { - tx_hashes.push( - transaction_hash - .as_str() - .ok_or(Error::Drive(DriveError::CorruptedCodeExecution( - "could not get transaction hash as string", - )))? - .to_string(), - ); - } - } - } - } - - Ok(tx_hashes) -} - impl Drive { - /// Update statuses for broadcasted withdrawals - pub fn update_broadcasted_withdrawal_transaction_statuses( + /// Fetch withdrawal documents by it's status + pub fn fetch_withdrawal_documents_by_status( &self, - last_synced_core_height: u64, - core_chain_locked_height: u64, - block_time_ms: u64, - block_height: u64, - current_epoch_index: u16, + status: u8, transaction: TransactionArg, - ) -> Result<(), Error> { - let (_, maybe_data_contract) = self.get_contract_with_fetch_info( + ) -> Result, Error> { + let query_value = json!({ + "where": [ + ["status", "==", status], + ], + "orderBy": [ + ["$createdAt", "desc"], + ] + }); + + let query_cbor = common::value_to_cbor(query_value, None); + + let (documents, _, _) = self.query_documents( + &query_cbor, Identifier::from_string( &withdrawals_contract::system_ids().contract_id, Encoding::Base58, @@ -172,107 +42,28 @@ impl Drive { )) })? .to_buffer(), - Some(&Epoch::new(current_epoch_index)), + withdrawals_contract::types::WITHDRAWAL, + None, transaction, )?; - let contract_fetch_info = maybe_data_contract.ok_or(Error::Drive( - DriveError::CorruptedCodeExecution("Can't fetch withdrawal data contract"), - ))?; - - let core_transactions = - fetch_core_block_transactions(self, last_synced_core_height, core_chain_locked_height)?; - - let broadcasted_documents = fetch_withdrawal_documents_by_status( - self, - withdrawals_contract::statuses::BROADCASTED, - transaction, - )?; - - for mut document in broadcasted_documents { - let transaction_sign_height = - document - .data - .get_u64("transactionSignHeight") - .map_err(|_| { - Error::Drive(DriveError::CorruptedCodeExecution( - "Can't get transactionSignHeight from withdrawal document", - )) - })?; - - let transaction_id_bytes = document.data.get_bytes("transactionId").map_err(|_| { - Error::Drive(DriveError::CorruptedCodeExecution( - "Can't get transactionId from withdrawal document", - )) - })?; - - let transaction_id = hex::encode(transaction_id_bytes); - - let transaction_index = document.data.get_u64("transactionIndex").map_err(|_| { - Error::Drive(DriveError::CorruptedCodeExecution( - "Can't get transactionIdex from withdrawal document", - )) - })?; - - if core_transactions.contains(&transaction_id) - || core_chain_locked_height - transaction_sign_height > 48 - { - let status = if core_transactions.contains(&transaction_id) { - withdrawals_contract::statuses::COMPLETE - } else { - let bytes = transaction_index.to_be_bytes(); - - let path = get_withdrawal_transactions_expired_ids_path_as_u8(); - - self.grove - .insert( - path, - &bytes, - Element::Item(bytes.to_vec(), None), - None, - transaction, - ) - .unwrap()?; - - withdrawals_contract::statuses::EXPIRED - }; - - update_document_data( - self, - &contract_fetch_info.contract, - &mut document, - block_time_ms, - block_height, - current_epoch_index, - transaction, - |document: &mut Document| -> Result<&mut Document, Error> { - document - .data - .insert( - "status".to_string(), - JsonValue::Number(Number::from(status)), - ) - .map_err(|_| { - Error::Drive(DriveError::CorruptedCodeExecution( - "Can't update document field: status", - )) - })?; - - document.revision += 1; - - Ok(document) - }, - )?; - } - } + let documents = documents + .into_iter() + .map(|document_cbor| { + Document::from_cbor(document_cbor).map_err(|_| { + Error::Drive(DriveError::CorruptedCodeExecution( + "Can't create a document from cbor", + )) + }) + }) + .collect::, Error>>()?; - Ok(()) + Ok(documents) } } #[cfg(test)] mod tests { - use crate::drive::identity::withdrawals::withdrawal_status::fetch_withdrawal_documents_by_status; use dpp::contracts::withdrawals_contract; use dpp::tests::fixtures::get_withdrawal_document_fixture; use dpp::tests::fixtures::get_withdrawals_data_contract_fixture; @@ -281,12 +72,6 @@ mod tests { use crate::common::helpers::setup::setup_drive_with_initial_state_structure; use crate::common::helpers::setup::{setup_document, setup_system_data_contract}; - use dashcore::hashes::hex::ToHex; - - use crate::rpc::core::MockCoreRPCLike; - - use dashcore::{hashes::hex::FromHex, BlockHash}; - mod fetch_withdrawal_documents_by_status { use super::*; @@ -301,12 +86,12 @@ mod tests { setup_system_data_contract(&drive, &data_contract, Some(&transaction)); - let documents = fetch_withdrawal_documents_by_status( - &drive, - withdrawals_contract::statuses::QUEUED, - Some(&transaction), - ) - .expect("to fetch documents by status"); + let documents = drive + .fetch_withdrawal_documents_by_status( + withdrawals_contract::statuses::QUEUED, + Some(&transaction), + ) + .expect("to fetch documents by status"); assert_eq!(documents.len(), 0); @@ -338,214 +123,23 @@ mod tests { setup_document(&drive, &document, &data_contract, Some(&transaction)); - let documents = fetch_withdrawal_documents_by_status( - &drive, - withdrawals_contract::statuses::QUEUED, - Some(&transaction), - ) - .expect("to fetch documents by status"); - - assert_eq!(documents.len(), 1); - - let documents = fetch_withdrawal_documents_by_status( - &drive, - withdrawals_contract::statuses::POOLED, - Some(&transaction), - ) - .expect("to fetch documents by status"); - - assert_eq!(documents.len(), 1); - } - } - - mod fetch_core_block_transactions { - use crate::drive::identity::withdrawals::withdrawal_status::fetch_core_block_transactions; - - use super::*; - - #[test] - fn test_fetches_core_transactions() { - let mut drive = setup_drive_with_initial_state_structure(); - - let mut mock_rpc_client = MockCoreRPCLike::new(); - - mock_rpc_client - .expect_get_block_hash() - .withf(|height| *height == 1) - .returning(|_| { - Ok(BlockHash::from_hex( - "0000000000000000000000000000000000000000000000000000000000000000", - ) - .unwrap()) - }); - - mock_rpc_client - .expect_get_block_hash() - .withf(|height| *height == 2) - .returning(|_| { - Ok(BlockHash::from_hex( - "1111111111111111111111111111111111111111111111111111111111111111", - ) - .unwrap()) - }); - - mock_rpc_client - .expect_get_block_json() - .withf(|bh| { - bh.to_hex() - == "0000000000000000000000000000000000000000000000000000000000000000" - }) - .returning(|_| { - Ok(json!({ - "tx": ["1"] - })) - }); - - mock_rpc_client - .expect_get_block_json() - .withf(|bh| { - bh.to_hex() - == "1111111111111111111111111111111111111111111111111111111111111111" - }) - .returning(|_| { - Ok(json!({ - "tx": ["2"] - })) - }); - - drive.core_rpc = Some(Box::new(mock_rpc_client)); - - let transactions = - fetch_core_block_transactions(&drive, 1, 2).expect("to fetch core transactions"); - - assert_eq!(transactions.len(), 2); - assert_eq!(transactions, ["1", "2"]); - } - } - - mod update_withdrawal_statuses { - use super::*; - - #[test] - fn test_statuses_are_updated() { - let mut drive = setup_drive_with_initial_state_structure(); - - let mut mock_rpc_client = MockCoreRPCLike::new(); - - mock_rpc_client - .expect_get_block_hash() - .withf(|height| *height == 95) - .returning(|_| { - Ok(BlockHash::from_hex( - "0000000000000000000000000000000000000000000000000000000000000000", - ) - .unwrap()) - }); - - mock_rpc_client - .expect_get_block_hash() - .withf(|height| *height == 96) - .returning(|_| { - Ok(BlockHash::from_hex( - "1111111111111111111111111111111111111111111111111111111111111111", - ) - .unwrap()) - }); - - mock_rpc_client - .expect_get_block_json() - .withf(|bh| { - bh.to_hex() - == "0000000000000000000000000000000000000000000000000000000000000000" - }) - .returning(|_| { - Ok(json!({ - "tx": ["0101010101010101010101010101010101010101010101010101010101010101"] - })) - }); - - mock_rpc_client - .expect_get_block_json() - .withf(|bh| { - bh.to_hex() - == "1111111111111111111111111111111111111111111111111111111111111111" - }) - .returning(|_| { - Ok(json!({ - "tx": ["0202020202020202020202020202020202020202020202020202020202020202"] - })) - }); - - drive.core_rpc = Some(Box::new(mock_rpc_client)); - - let transaction = drive.grove.start_transaction(); - - let data_contract = get_withdrawals_data_contract_fixture(None); - - setup_system_data_contract(&drive, &data_contract, Some(&transaction)); - - let document_1 = get_withdrawal_document_fixture( - &data_contract, - json!({ - "amount": 1000, - "coreFeePerByte": 1, - "pooling": 0, - "outputScript": (0..23).collect::>(), - "status": withdrawals_contract::statuses::BROADCASTED, - "transactionIndex": 1, - "transactionSignHeight": 93, - "transactionId": vec![1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], - }), - ); - - setup_document(&drive, &document_1, &data_contract, Some(&transaction)); - - let document_2 = get_withdrawal_document_fixture( - &data_contract, - json!({ - "amount": 1000, - "coreFeePerByte": 1, - "pooling": 0, - "outputScript": (0..23).collect::>(), - "status": withdrawals_contract::statuses::BROADCASTED, - "transactionIndex": 2, - "transactionSignHeight": 10, - "transactionId": vec![3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], - }), - ); - - setup_document(&drive, &document_2, &data_contract, Some(&transaction)); - - drive - .update_broadcasted_withdrawal_transaction_statuses( - 95, - 96, - 1, - 1, - 1, + let documents = drive + .fetch_withdrawal_documents_by_status( + withdrawals_contract::statuses::QUEUED, Some(&transaction), ) - .expect("to update withdrawal statuses"); - - let documents = fetch_withdrawal_documents_by_status( - &drive, - withdrawals_contract::statuses::EXPIRED, - Some(&transaction), - ) - .expect("to fetch documents by status"); + .expect("to fetch documents by status"); assert_eq!(documents.len(), 1); - assert_eq!(documents.get(0).unwrap().id, document_2.id); - let documents = fetch_withdrawal_documents_by_status( - &drive, - withdrawals_contract::statuses::COMPLETE, - Some(&transaction), - ) - .expect("to fetch documents by status"); + let documents = drive + .fetch_withdrawal_documents_by_status( + withdrawals_contract::statuses::POOLED, + Some(&transaction), + ) + .expect("to fetch documents by status"); assert_eq!(documents.len(), 1); - assert_eq!(documents.get(0).unwrap().id, document_1.id); } } } diff --git a/packages/rs-drive/src/drive/identity/withdrawals/withdrawal_transactions.rs b/packages/rs-drive/src/drive/identity/withdrawals/withdrawal_transactions.rs index 2847dc9bc24..7e641a5eb82 100644 --- a/packages/rs-drive/src/drive/identity/withdrawals/withdrawal_transactions.rs +++ b/packages/rs-drive/src/drive/identity/withdrawals/withdrawal_transactions.rs @@ -1,150 +1,305 @@ -use std::ops::RangeFull; +use std::{collections::HashMap, ops::RangeFull}; -use grovedb::{ - query_result_type::QueryResultType, Element, PathQuery, Query, QueryItem, SizedQuery, - TransactionArg, +use dashcore::{ + blockdata::transaction::special_transaction::asset_unlock::unqualified_asset_unlock::{ + AssetUnlockBasePayload, AssetUnlockBaseTransactionInfo, + }, + consensus::Encodable, + Script, TxOut, }; +use dpp::{ + identity::convert_credits_to_satoshi, + prelude::{Document, Identifier}, + util::json_value::JsonValueExt, +}; +use grovedb::TransactionArg; +use serde_json::Value as JsonValue; use crate::{ - drive::{batch::GroveDbOpBatch, grove_operations::BatchDeleteApplyType, Drive}, + drive::Drive, error::{drive::DriveError, Error}, - fee::op::DriveOperation, }; -use super::paths::{ - get_withdrawal_transactions_queue_path, get_withdrawal_transactions_queue_path_as_u8, - WithdrawalTransaction, -}; +use super::paths::WithdrawalTransaction; impl Drive { - /// Add insert operations for withdrawal transactions to the batch - pub fn add_enqueue_withdrawal_transaction_operations( + /// Build list of Core transactions from withdrawal documents + pub fn build_withdrawal_transactions_from_documents( &self, - batch: &mut GroveDbOpBatch, - withdrawals: Vec, - ) { - for (id, bytes) in withdrawals { - batch.add_insert( - get_withdrawal_transactions_queue_path(), - id, - Element::Item(bytes, None), + documents: &[Document], + transaction: TransactionArg, + ) -> Result, Error> { + let mut withdrawals: HashMap = HashMap::new(); + + let latest_withdrawal_index = + self.fetch_latest_withdrawal_transaction_index(transaction)?; + + for (i, document) in documents.iter().enumerate() { + let output_script = document.data.get_bytes("outputScript").map_err(|_| { + Error::Drive(DriveError::CorruptedCodeExecution( + "Can't get outputScript from withdrawal document", + )) + })?; + + let amount = document.data.get_u64("amount").map_err(|_| { + Error::Drive(DriveError::CorruptedCodeExecution( + "Can't get amount from withdrawal document", + )) + })?; + + let core_fee_per_byte = document.data.get_u64("coreFeePerByte").map_err(|_| { + Error::Drive(DriveError::CorruptedCodeExecution( + "Can't get coreFeePerByte from withdrawal document", + )) + })?; + + let state_transition_size = 184; + + let output_script: Script = Script::from(output_script); + + let tx_out = TxOut { + value: convert_credits_to_satoshi(amount), + script_pubkey: output_script, + }; + + let transaction_index = latest_withdrawal_index + i as u64; + + let withdrawal_transaction = AssetUnlockBaseTransactionInfo { + version: 1, + lock_time: 0, + output: vec![tx_out], + base_payload: AssetUnlockBasePayload { + version: 1, + index: transaction_index, + fee: (state_transition_size * core_fee_per_byte * 1000) as u32, + }, + }; + + let mut transaction_buffer: Vec = vec![]; + + withdrawal_transaction + .consensus_encode(&mut transaction_buffer) + .map_err(|_| { + Error::Drive(DriveError::CorruptedCodeExecution( + "Can't consensus encode a withdrawal transaction", + )) + })?; + + withdrawals.insert( + document.id.clone(), + ( + transaction_index.to_be_bytes().to_vec(), + transaction_buffer.clone(), + ), ); } + + Ok(withdrawals) } - /// Get specified amount of withdrawal transactions from the DB - pub fn dequeue_withdrawal_transactions( + /// Fetch Core transactions by range of Core heights + pub fn fetch_core_block_transactions( &self, - num_of_transactions: u16, - transaction: TransactionArg, - ) -> Result, Error> { - let mut query = Query::new(); - - query.insert_item(QueryItem::RangeFull(RangeFull)); - - let path_query = PathQuery { - path: get_withdrawal_transactions_queue_path(), - query: SizedQuery { - query, - limit: Some(num_of_transactions), - offset: None, - }, - }; - - let result_items = self - .grove - .query_raw( - &path_query, - QueryResultType::QueryKeyElementPairResultType, - transaction, - ) - .unwrap() - .map_err(Error::GroveDB)? - .0 - .to_key_elements(); - - let withdrawals = result_items - .into_iter() - .map(|(id, element)| match element { - Element::Item(bytes, _) => Ok((id, bytes)), - _ => Err(Error::Drive(DriveError::CorruptedWithdrawalNotItem( - "withdrawal is not an item", - ))), - }) - .collect::, Vec)>, Error>>()?; - - if !withdrawals.is_empty() { - let mut batch_operations: Vec = vec![]; - let mut drive_operations: Vec = vec![]; - - let withdrawals_path: [&[u8]; 2] = get_withdrawal_transactions_queue_path_as_u8(); - - for (id, _) in withdrawals.iter() { - self.batch_delete( - withdrawals_path, - id, - // we know that we are not deleting a subtree - BatchDeleteApplyType::StatefulBatchDelete { - is_known_to_be_subtree_with_sum: Some((false, false)), - }, - transaction, - &mut batch_operations, - )?; - } + last_synced_core_height: u64, + core_chain_locked_height: u64, + ) -> Result, Error> { + let core_rpc = + self.core_rpc + .as_ref() + .ok_or(Error::Drive(DriveError::CorruptedCodeExecution( + "Core RPC client has not been set up", + )))?; + + let mut tx_hashes: Vec = vec![]; + + for height in last_synced_core_height..=core_chain_locked_height { + let block_hash = core_rpc.get_block_hash(height).map_err(|_| { + Error::Drive(DriveError::CorruptedCodeExecution( + "could not get block by height", + )) + })?; - self.apply_batch_drive_operations( - None, - transaction, - batch_operations, - &mut drive_operations, - )?; + let block_json: JsonValue = core_rpc.get_block_json(&block_hash).map_err(|_| { + Error::Drive(DriveError::CorruptedCodeExecution( + "could not get block by hash", + )) + })?; + + if let Some(transactions) = block_json.get("tx") { + if let Some(transactions) = transactions.as_array() { + for transaction_hash in transactions { + tx_hashes.push( + transaction_hash + .as_str() + .ok_or(Error::Drive(DriveError::CorruptedCodeExecution( + "could not get transaction hash as string", + )))? + .to_string(), + ); + } + } + } } - Ok(withdrawals) + Ok(tx_hashes) } } #[cfg(test)] mod tests { + use crate::common::helpers::setup::setup_drive_with_initial_state_structure; + + use dashcore::{hashes::hex::FromHex, hashes::hex::ToHex, BlockHash}; + use serde_json::json; + + use crate::rpc::core::MockCoreRPCLike; + + use dpp::{ + contracts::withdrawals_contract, + tests::fixtures::{get_withdrawal_document_fixture, get_withdrawals_data_contract_fixture}, + }; + use crate::{ - common::helpers::setup::setup_drive_with_initial_state_structure, - drive::batch::GroveDbOpBatch, + common::helpers::setup::{setup_document, setup_system_data_contract}, + drive::identity::withdrawals::paths::WithdrawalTransaction, }; - #[test] - fn test_enqueue_and_dequeue() { - let drive = setup_drive_with_initial_state_structure(); + mod fetch_core_block_transactions { - let transaction = drive.grove.start_transaction(); + use super::*; - let withdrawals: Vec<(Vec, Vec)> = (0..17) - .map(|i: u8| (i.to_be_bytes().to_vec(), vec![i; 32])) - .collect(); + #[test] + fn test_fetches_core_transactions() { + let mut drive = setup_drive_with_initial_state_structure(); - let mut batch = GroveDbOpBatch::new(); + let mut mock_rpc_client = MockCoreRPCLike::new(); - drive.add_enqueue_withdrawal_transaction_operations(&mut batch, withdrawals); + mock_rpc_client + .expect_get_block_hash() + .withf(|height| *height == 1) + .returning(|_| { + Ok(BlockHash::from_hex( + "0000000000000000000000000000000000000000000000000000000000000000", + ) + .unwrap()) + }); - drive - .grove_apply_batch(batch, true, Some(&transaction)) - .expect("to apply ops"); + mock_rpc_client + .expect_get_block_hash() + .withf(|height| *height == 2) + .returning(|_| { + Ok(BlockHash::from_hex( + "1111111111111111111111111111111111111111111111111111111111111111", + ) + .unwrap()) + }); - let withdrawals = drive - .dequeue_withdrawal_transactions(16, Some(&transaction)) - .expect("to dequeue withdrawals"); + mock_rpc_client + .expect_get_block_json() + .withf(|bh| { + bh.to_hex() + == "0000000000000000000000000000000000000000000000000000000000000000" + }) + .returning(|_| { + Ok(json!({ + "tx": ["1"] + })) + }); + + mock_rpc_client + .expect_get_block_json() + .withf(|bh| { + bh.to_hex() + == "1111111111111111111111111111111111111111111111111111111111111111" + }) + .returning(|_| { + Ok(json!({ + "tx": ["2"] + })) + }); + + drive.core_rpc = Some(Box::new(mock_rpc_client)); + + let transactions = drive + .fetch_core_block_transactions(1, 2) + .expect("to fetch core transactions"); + + assert_eq!(transactions.len(), 2); + assert_eq!(transactions, ["1", "2"]); + } + } - assert_eq!(withdrawals.len(), 16); + mod build_withdrawal_transactions_from_documents { + use super::*; - let withdrawals = drive - .dequeue_withdrawal_transactions(16, Some(&transaction)) - .expect("to dequeue withdrawals"); + #[test] + fn test_build() { + let drive = setup_drive_with_initial_state_structure(); - assert_eq!(withdrawals.len(), 1); + let transaction = drive.grove.start_transaction(); - let withdrawals = drive - .dequeue_withdrawal_transactions(16, Some(&transaction)) - .expect("to dequeue withdrawals"); + let data_contract = get_withdrawals_data_contract_fixture(None); - assert_eq!(withdrawals.len(), 0); + setup_system_data_contract(&drive, &data_contract, Some(&transaction)); + + let document_1 = get_withdrawal_document_fixture( + &data_contract, + json!({ + "amount": 1000, + "coreFeePerByte": 1, + "pooling": 0, + "outputScript": (0..23).collect::>(), + "status": withdrawals_contract::statuses::POOLED, + "transactionIndex": 1, + }), + ); + + setup_document(&drive, &document_1, &data_contract, Some(&transaction)); + + let document_2 = get_withdrawal_document_fixture( + &data_contract, + json!({ + "amount": 1000, + "coreFeePerByte": 1, + "pooling": 0, + "outputScript": (0..23).collect::>(), + "status": withdrawals_contract::statuses::POOLED, + "transactionIndex": 2, + }), + ); + + setup_document(&drive, &document_2, &data_contract, Some(&transaction)); + + let documents = vec![document_1, document_2]; + + let transactions = drive + .build_withdrawal_transactions_from_documents(&documents, Some(&transaction)) + .expect("to build transactions from documents"); + + assert_eq!( + transactions + .values() + .cloned() + .collect::>(), + vec![ + ( + vec![0, 0, 0, 0, 0, 0, 0, 0], + vec![ + 1, 0, 9, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 23, 0, 1, 2, 3, 4, 5, 6, 7, + 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, 0, 0, 0, 192, 206, 2, 0, + ], + ), + ( + vec![0, 0, 0, 0, 0, 0, 0, 1], + vec![ + 1, 0, 9, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 23, 0, 1, 2, 3, 4, 5, 6, 7, + 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, 192, 206, 2, 0, + ], + ), + ], + ); + } } } From 563f91a2a627f84cb3496845c78de03c47fc18d6 Mon Sep 17 00:00:00 2001 From: Djavid Gabibyan Date: Fri, 23 Dec 2022 17:21:23 +0500 Subject: [PATCH 038/170] chore: PR fixes --- ..._identity_credit_withdrawal_transition_factory.rs | 4 ++-- ...tity_credit_withdrawal_transition_factory_spec.rs | 4 ++-- .../src/identity_credit_withdrawal/mod.rs | 12 ++++++++---- packages/rs-drive/src/drive/document/helpers.rs | 4 +++- .../drive/identity/withdrawals/withdrawal_status.rs | 6 ++++-- .../identity/withdrawals/withdrawal_transactions.rs | 6 ++++-- 6 files changed, 23 insertions(+), 13 deletions(-) diff --git a/packages/rs-dpp/src/identity/state_transition/identity_credit_withdrawal_transition/apply_identity_credit_withdrawal_transition_factory.rs b/packages/rs-dpp/src/identity/state_transition/identity_credit_withdrawal_transition/apply_identity_credit_withdrawal_transition_factory.rs index b3c287a8cf0..9e9ac405781 100644 --- a/packages/rs-dpp/src/identity/state_transition/identity_credit_withdrawal_transition/apply_identity_credit_withdrawal_transition_factory.rs +++ b/packages/rs-dpp/src/identity/state_transition/identity_credit_withdrawal_transition/apply_identity_credit_withdrawal_transition_factory.rs @@ -12,7 +12,7 @@ use crate::{ state_repository::StateRepositoryLike, state_transition::StateTransitionConvert, state_transition::StateTransitionLike, - util::{entropy_generator::generate, json_value::JsonValueExt, string_encoding::Encoding}, + util::{entropy_generator::generate, json_value::JsonValueExt, string_encoding::Encoding}, identity::state_transition::identity_credit_withdrawal_transition::Pooling, }; use super::IdentityCreditWithdrawalTransition; @@ -75,7 +75,7 @@ where let document_data = json!({ "amount": state_transition.amount, "coreFeePerByte": state_transition.core_fee_per_byte, - "pooling": 0, + "pooling": Pooling::Never, "outputScript": state_transition.output_script.as_bytes(), "status": withdrawals_contract::statuses::QUEUED, }); diff --git a/packages/rs-dpp/src/tests/identity/state_transition/identity_credit_withdrawal_transition/apply_identity_credit_withdrawal_transition_factory_spec.rs b/packages/rs-dpp/src/tests/identity/state_transition/identity_credit_withdrawal_transition/apply_identity_credit_withdrawal_transition_factory_spec.rs index f86f7553e59..e672f3ba027 100644 --- a/packages/rs-dpp/src/tests/identity/state_transition/identity_credit_withdrawal_transition/apply_identity_credit_withdrawal_transition_factory_spec.rs +++ b/packages/rs-dpp/src/tests/identity/state_transition/identity_credit_withdrawal_transition/apply_identity_credit_withdrawal_transition_factory_spec.rs @@ -9,7 +9,7 @@ mod apply_identity_credit_withdrawal_transition_factory { data_contract::DataContract, identity::state_transition::identity_credit_withdrawal_transition::{ apply_identity_credit_withdrawal_transition_factory::ApplyIdentityCreditWithdrawalTransition, - IdentityCreditWithdrawalTransition, + IdentityCreditWithdrawalTransition, Pooling, }, prelude::{Identifier, Identity}, state_repository::MockStateRepositoryLike, @@ -76,7 +76,7 @@ mod apply_identity_credit_withdrawal_transition_factory { == json!({ "amount": 10, "coreFeePerByte": 0, - "pooling": 0, + "pooling": Pooling::Never, "outputScript": [], "status": withdrawals_contract::statuses::QUEUED, }); diff --git a/packages/rs-drive-abci/src/identity_credit_withdrawal/mod.rs b/packages/rs-drive-abci/src/identity_credit_withdrawal/mod.rs index 88fbd0776a1..a27096a38a5 100644 --- a/packages/rs-drive-abci/src/identity_credit_withdrawal/mod.rs +++ b/packages/rs-drive-abci/src/identity_credit_withdrawal/mod.rs @@ -328,6 +328,8 @@ mod tests { mod update_withdrawal_statuses { + use dpp::identity::state_transition::identity_credit_withdrawal_transition::Pooling; + use super::*; #[test] @@ -393,7 +395,7 @@ mod tests { json!({ "amount": 1000, "coreFeePerByte": 1, - "pooling": 0, // TODO: use constant + "pooling": Pooling::Never, "outputScript": (0..23).collect::>(), "status": withdrawals_contract::statuses::BROADCASTED, "transactionIndex": 1, @@ -414,7 +416,7 @@ mod tests { json!({ "amount": 1000, "coreFeePerByte": 1, - "pooling": 0, + "pooling": Pooling::Never, "outputScript": (0..23).collect::>(), "status": withdrawals_contract::statuses::BROADCASTED, "transactionIndex": 2, @@ -467,6 +469,8 @@ mod tests { mod pool_withdrawals_into_transactions { + use dpp::identity::state_transition::identity_credit_withdrawal_transition::Pooling; + use super::*; #[test] @@ -484,7 +488,7 @@ mod tests { json!({ "amount": 1000, "coreFeePerByte": 1, - "pooling": 0, + "pooling": Pooling::Never, "outputScript": (0..23).collect::>(), "status": withdrawals_contract::statuses::QUEUED, "transactionIndex": 1, @@ -503,7 +507,7 @@ mod tests { json!({ "amount": 1000, "coreFeePerByte": 1, - "pooling": 0, + "pooling": Pooling::Never, "outputScript": (0..23).collect::>(), "status": withdrawals_contract::statuses::QUEUED, "transactionIndex": 2, diff --git a/packages/rs-drive/src/drive/document/helpers.rs b/packages/rs-drive/src/drive/document/helpers.rs index a721e0ab900..19842974d43 100644 --- a/packages/rs-drive/src/drive/document/helpers.rs +++ b/packages/rs-drive/src/drive/document/helpers.rs @@ -165,6 +165,8 @@ mod tests { }; mod update_document_transaction_id { + use dpp::identity::state_transition::identity_credit_withdrawal_transition::Pooling; + use super::*; #[test] @@ -192,7 +194,7 @@ mod tests { json!({ "amount": 1000, "coreFeePerByte": 1, - "pooling": 0, + "pooling": Pooling::Never, "outputScript": (0..23).collect::>(), "status": withdrawals_contract::statuses::POOLED, "transactionIndex": 1, diff --git a/packages/rs-drive/src/drive/identity/withdrawals/withdrawal_status.rs b/packages/rs-drive/src/drive/identity/withdrawals/withdrawal_status.rs index b2258ec3bf8..23d7e25b141 100644 --- a/packages/rs-drive/src/drive/identity/withdrawals/withdrawal_status.rs +++ b/packages/rs-drive/src/drive/identity/withdrawals/withdrawal_status.rs @@ -74,6 +74,8 @@ mod tests { mod fetch_withdrawal_documents_by_status { + use dpp::identity::state_transition::identity_credit_withdrawal_transition::Pooling; + use super::*; #[test] @@ -100,7 +102,7 @@ mod tests { json!({ "amount": 1000, "coreFeePerByte": 1, - "pooling": 0, + "pooling": Pooling::Never, "outputScript": (0..23).collect::>(), "status": withdrawals_contract::statuses::QUEUED, "transactionIndex": 1, @@ -114,7 +116,7 @@ mod tests { json!({ "amount": 1000, "coreFeePerByte": 1, - "pooling": 0, + "pooling": Pooling::Never, "outputScript": (0..23).collect::>(), "status": withdrawals_contract::statuses::POOLED, "transactionIndex": 2, diff --git a/packages/rs-drive/src/drive/identity/withdrawals/withdrawal_transactions.rs b/packages/rs-drive/src/drive/identity/withdrawals/withdrawal_transactions.rs index 7e641a5eb82..00d1f09b5b4 100644 --- a/packages/rs-drive/src/drive/identity/withdrawals/withdrawal_transactions.rs +++ b/packages/rs-drive/src/drive/identity/withdrawals/withdrawal_transactions.rs @@ -230,6 +230,8 @@ mod tests { } mod build_withdrawal_transactions_from_documents { + use dpp::identity::state_transition::identity_credit_withdrawal_transition::Pooling; + use super::*; #[test] @@ -247,7 +249,7 @@ mod tests { json!({ "amount": 1000, "coreFeePerByte": 1, - "pooling": 0, + "pooling": Pooling::Never, "outputScript": (0..23).collect::>(), "status": withdrawals_contract::statuses::POOLED, "transactionIndex": 1, @@ -261,7 +263,7 @@ mod tests { json!({ "amount": 1000, "coreFeePerByte": 1, - "pooling": 0, + "pooling": Pooling::Never, "outputScript": (0..23).collect::>(), "status": withdrawals_contract::statuses::POOLED, "transactionIndex": 2, From b3dd9027daebfde1c664876263eaa3ee2b39edb0 Mon Sep 17 00:00:00 2001 From: Djavid Gabibyan Date: Fri, 23 Dec 2022 17:49:19 +0500 Subject: [PATCH 039/170] chore: PR fixes --- packages/rs-dpp/src/document/mod.rs | 5 +++++ .../src/identity_credit_withdrawal/mod.rs | 20 +++++-------------- .../rs-drive/src/drive/document/helpers.rs | 16 +++++++++------ 3 files changed, 20 insertions(+), 21 deletions(-) diff --git a/packages/rs-dpp/src/document/mod.rs b/packages/rs-dpp/src/document/mod.rs index fc06448ccab..c3cce3e66b6 100644 --- a/packages/rs-dpp/src/document/mod.rs +++ b/packages/rs-dpp/src/document/mod.rs @@ -205,6 +205,11 @@ impl Document { pub fn set_data(&mut self, data: JsonValue) { self.data = data; } + + /// Increment document's revision + pub fn increment_revision(&mut self) { + self.revision += 1; + } } #[cfg(test)] diff --git a/packages/rs-drive-abci/src/identity_credit_withdrawal/mod.rs b/packages/rs-drive-abci/src/identity_credit_withdrawal/mod.rs index a27096a38a5..23892a2204b 100644 --- a/packages/rs-drive-abci/src/identity_credit_withdrawal/mod.rs +++ b/packages/rs-drive-abci/src/identity_credit_withdrawal/mod.rs @@ -126,11 +126,7 @@ impl Platform { transaction, |document: &mut Document| -> Result<&mut Document, drive::error::Error> { document - .data - .insert( - "status".to_string(), - JsonValue::Number(Number::from(status)), - ) + .set("status", JsonValue::Number(Number::from(status))) .map_err(|_| { drive::error::Error::Drive( drive::error::drive::DriveError::CorruptedCodeExecution( @@ -139,8 +135,6 @@ impl Platform { ) })?; - document.revision += 1; - Ok(document) }, )?; @@ -250,9 +244,8 @@ impl Platform { transaction, |document: &mut Document| -> Result<&mut Document, drive::error::Error> { document - .data - .insert( - "transactionId".to_string(), + .set( + "transactionId", JsonValue::Array( transaction_id .clone() @@ -270,9 +263,8 @@ impl Platform { })?; document - .data - .insert( - "status".to_string(), + .set( + "status", JsonValue::Number(Number::from(withdrawals_contract::statuses::POOLED)), ) .map_err(|_| { @@ -283,8 +275,6 @@ impl Platform { ) })?; - document.revision += 1; - Ok(document) }, )?; diff --git a/packages/rs-drive/src/drive/document/helpers.rs b/packages/rs-drive/src/drive/document/helpers.rs index 19842974d43..fcd931cf14f 100644 --- a/packages/rs-drive/src/drive/document/helpers.rs +++ b/packages/rs-drive/src/drive/document/helpers.rs @@ -30,6 +30,13 @@ impl Drive { { let document = update_fn(document)?; + document.updated_at = Some(block_time_ms.try_into().map_err(|_| { + Error::Drive(DriveError::CorruptedCodeExecution( + "Can't convert u64 block time to i64 updated_at", + )) + })?); + document.increment_revision(); + self.update_document_for_contract_cbor( &document.to_cbor().map_err(|_| { Error::Drive(DriveError::CorruptedCodeExecution( @@ -125,9 +132,8 @@ impl Drive { transaction, |document: &mut Document| -> Result<&mut Document, Error> { document - .data - .insert( - "transactionId".to_string(), + .set( + "transactionId", JsonValue::Array( update_transaction_id .iter() @@ -137,12 +143,10 @@ impl Drive { ) .map_err(|_| { Error::Drive(DriveError::CorruptedCodeExecution( - "Can't update document field: transactionId", + "Can't set document field: transactionId", )) })?; - document.revision += 1; - Ok(document) }, )?; From 2a85eb0e2ae11b04115e72d7a94abc0a9968ce0d Mon Sep 17 00:00:00 2001 From: Djavid Gabibyan Date: Fri, 23 Dec 2022 18:24:03 +0500 Subject: [PATCH 040/170] chore: PR fixes --- packages/rs-drive-abci/src/abci/handlers.rs | 22 +--- packages/rs-drive-abci/src/block.rs | 3 + .../execution/fee_pools/process_block_fees.rs | 2 + .../src/identity_credit_withdrawal/mod.rs | 113 ++++++++++++------ .../rs-drive/src/drive/document/helpers.rs | 38 +++--- 5 files changed, 105 insertions(+), 73 deletions(-) diff --git a/packages/rs-drive-abci/src/abci/handlers.rs b/packages/rs-drive-abci/src/abci/handlers.rs index cb4518f110f..8d9855275fa 100644 --- a/packages/rs-drive-abci/src/abci/handlers.rs +++ b/packages/rs-drive-abci/src/abci/handlers.rs @@ -120,27 +120,22 @@ impl TenderdashAbci for Platform { epoch_info: epoch_info.clone(), }; - self.block_execution_context - .replace(Some(block_execution_context)); - self.update_broadcasted_withdrawal_transaction_statuses( request.last_synced_core_height, - request.core_chain_locked_height, - request.block_time_ms, - request.block_height, - epoch_info.current_epoch_index, + &block_execution_context, transaction, )?; let unsigned_withdrawal_transaction_bytes = self .fetch_and_prepare_unsigned_withdrawal_transactions( - request.block_time_ms, - request.block_height, - epoch_info.current_epoch_index, + &block_execution_context, request.validator_set_quorum_hash, transaction, )?; + self.block_execution_context + .replace(Some(block_execution_context)); + let response = BlockBeginResponse { epoch_info, unsigned_withdrawal_transactions: unsigned_withdrawal_transaction_bytes, @@ -163,12 +158,7 @@ impl TenderdashAbci for Platform { ), ))?; - self.pool_withdrawals_into_transactions( - block_execution_context.block_info.block_time_ms, - block_execution_context.block_info.block_height, - block_execution_context.epoch_info.current_epoch_index, - transaction, - )?; + self.pool_withdrawals_into_transactions(&block_execution_context, transaction)?; // Process fees let process_block_fees_result = self.process_block_fees( diff --git a/packages/rs-drive-abci/src/block.rs b/packages/rs-drive-abci/src/block.rs index 8c5acd5c1e1..3f0839cdb58 100644 --- a/packages/rs-drive-abci/src/block.rs +++ b/packages/rs-drive-abci/src/block.rs @@ -40,6 +40,8 @@ pub struct BlockInfo { pub previous_block_time_ms: Option, /// Block proposer's proTxHash pub proposer_pro_tx_hash: [u8; 32], + /// Core chain locked height + pub core_chain_locked_height: u64, } impl BlockInfo { @@ -50,6 +52,7 @@ impl BlockInfo { block_time_ms: block_begin_request.block_time_ms, previous_block_time_ms: block_begin_request.previous_block_time_ms, proposer_pro_tx_hash: block_begin_request.proposer_pro_tx_hash, + core_chain_locked_height: block_begin_request.core_chain_locked_height, } } } diff --git a/packages/rs-drive-abci/src/execution/fee_pools/process_block_fees.rs b/packages/rs-drive-abci/src/execution/fee_pools/process_block_fees.rs index 1caed2510e9..f7b73d0ff92 100644 --- a/packages/rs-drive-abci/src/execution/fee_pools/process_block_fees.rs +++ b/packages/rs-drive-abci/src/execution/fee_pools/process_block_fees.rs @@ -258,6 +258,7 @@ mod tests { block_time_ms, previous_block_time_ms, proposer_pro_tx_hash, + core_chain_locked_height: 1, }; let epoch_info = @@ -423,6 +424,7 @@ mod tests { block_time_ms, previous_block_time_ms, proposer_pro_tx_hash, + core_chain_locked_height: 1, }; let epoch_info = diff --git a/packages/rs-drive-abci/src/identity_credit_withdrawal/mod.rs b/packages/rs-drive-abci/src/identity_credit_withdrawal/mod.rs index 23892a2204b..6f89d4f9ae4 100644 --- a/packages/rs-drive-abci/src/identity_credit_withdrawal/mod.rs +++ b/packages/rs-drive-abci/src/identity_credit_withdrawal/mod.rs @@ -9,7 +9,7 @@ use dpp::{ }; use drive::{ drive::{ - batch::GroveDbOpBatch, + batch::GroveDbOpBatch, block_info::BlockInfo, identity::withdrawals::paths::get_withdrawal_transactions_expired_ids_path_as_u8, }, fee_pools::epochs::Epoch, @@ -18,6 +18,7 @@ use drive::{ use serde_json::{Number, Value as JsonValue}; use crate::{ + block::BlockExecutionContext, error::{execution::ExecutionError, Error}, platform::Platform, }; @@ -29,10 +30,7 @@ impl Platform { pub fn update_broadcasted_withdrawal_transaction_statuses( &self, last_synced_core_height: u64, - core_chain_locked_height: u64, - block_time_ms: u64, - block_height: u64, - current_epoch_index: u16, + block_execution_context: &BlockExecutionContext, transaction: TransactionArg, ) -> Result<(), Error> { let (_, maybe_data_contract) = self.drive.get_contract_with_fetch_info( @@ -46,7 +44,9 @@ impl Platform { )) })? .to_buffer(), - Some(&Epoch::new(current_epoch_index)), + Some(&Epoch::new( + block_execution_context.epoch_info.current_epoch_index, + )), transaction, )?; @@ -54,9 +54,10 @@ impl Platform { ExecutionError::CorruptedCodeExecution("Can't fetch withdrawal data contract"), ))?; - let core_transactions = self - .drive - .fetch_core_block_transactions(last_synced_core_height, core_chain_locked_height)?; + let core_transactions = self.drive.fetch_core_block_transactions( + last_synced_core_height, + block_execution_context.block_info.core_chain_locked_height, + )?; let broadcasted_documents = self.drive.fetch_withdrawal_documents_by_status( withdrawals_contract::statuses::BROADCASTED, @@ -89,7 +90,9 @@ impl Platform { })?; if core_transactions.contains(&transaction_id) - || core_chain_locked_height - transaction_sign_height > 48 + || block_execution_context.block_info.core_chain_locked_height + - transaction_sign_height + > 48 { let status = if core_transactions.contains(&transaction_id) { withdrawals_contract::statuses::COMPLETE @@ -120,9 +123,11 @@ impl Platform { self.drive.update_document_data( &contract_fetch_info.contract, &mut document, - block_time_ms, - block_height, - current_epoch_index, + BlockInfo { + time_ms: block_execution_context.block_info.block_time_ms, + height: block_execution_context.block_info.block_height, + epoch: Epoch::new(block_execution_context.epoch_info.current_epoch_index), + }, transaction, |document: &mut Document| -> Result<&mut Document, drive::error::Error> { document @@ -147,9 +152,7 @@ impl Platform { /// Prepares a list of an unsigned withdrawal transaction bytes pub fn fetch_and_prepare_unsigned_withdrawal_transactions( &self, - block_time_ms: u64, - block_height: u64, - current_epoch_index: u16, + block_execution_context: &BlockExecutionContext, validator_set_quorum_hash: [u8; 32], transaction: TransactionArg, ) -> Result>, Error> { @@ -164,7 +167,8 @@ impl Platform { .into_iter() .map(|(_, bytes)| { let request_info = AssetUnlockRequestInfo { - request_height: block_height as u32, + request_height: block_execution_context.block_info.core_chain_locked_height + as u32, quorum_hash: QuorumHash::hash(&validator_set_quorum_hash), }; @@ -184,9 +188,11 @@ impl Platform { self.drive.update_document_transaction_id( &original_transaction_id, &update_transaction_id, - block_time_ms, - block_height, - current_epoch_index, + BlockInfo { + time_ms: block_execution_context.block_info.block_time_ms, + height: block_execution_context.block_info.block_height, + epoch: Epoch::new(block_execution_context.epoch_info.current_epoch_index), + }, transaction, )?; @@ -198,9 +204,7 @@ impl Platform { /// Pool withdrawal documents into transactions pub fn pool_withdrawals_into_transactions( &self, - block_time_ms: u64, - block_height: u64, - current_epoch_index: u16, + block_execution_context: &BlockExecutionContext, transaction: TransactionArg, ) -> Result<(), Error> { let (_, maybe_data_contract) = self.drive.get_contract_with_fetch_info( @@ -214,7 +218,9 @@ impl Platform { )) })? .to_buffer(), - Some(&Epoch::new(current_epoch_index)), + Some(&Epoch::new( + block_execution_context.epoch_info.current_epoch_index, + )), transaction, )?; @@ -238,9 +244,11 @@ impl Platform { self.drive.update_document_data( &contract_fetch_info.contract, document, - block_time_ms, - block_height, - current_epoch_index, + BlockInfo { + time_ms: block_execution_context.block_info.block_time_ms, + height: block_execution_context.block_info.block_height, + epoch: Epoch::new(block_execution_context.epoch_info.current_epoch_index), + }, transaction, |document: &mut Document| -> Result<&mut Document, drive::error::Error> { document @@ -315,11 +323,14 @@ mod tests { use crate::common::helpers::setup::setup_system_data_contract; use crate::common::helpers::setup::setup_platform_with_initial_state_structure; + use dpp::identity::state_transition::identity_credit_withdrawal_transition::Pooling; - mod update_withdrawal_statuses { - - use dpp::identity::state_transition::identity_credit_withdrawal_transition::Pooling; + use crate::{ + block::{BlockExecutionContext, BlockInfo}, + execution::fee_pools::epoch::EpochInfo, + }; + mod update_withdrawal_statuses { use super::*; #[test] @@ -425,10 +436,23 @@ mod tests { platform .update_broadcasted_withdrawal_transaction_statuses( 95, - 96, - 1, - 1, - 1, + &BlockExecutionContext { + block_info: BlockInfo { + block_height: 1, + block_time_ms: 1, + previous_block_time_ms: Some(1), + proposer_pro_tx_hash: [ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + ], + core_chain_locked_height: 96, + }, + epoch_info: EpochInfo { + current_epoch_index: 1, + previous_epoch_index: None, + is_epoch_change: false, + }, + }, Some(&transaction), ) .expect("to update withdrawal statuses"); @@ -512,7 +536,26 @@ mod tests { ); platform - .pool_withdrawals_into_transactions(1, 1, 1, Some(&transaction)) + .pool_withdrawals_into_transactions( + &BlockExecutionContext { + block_info: BlockInfo { + block_height: 1, + block_time_ms: 1, + previous_block_time_ms: Some(1), + proposer_pro_tx_hash: [ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + ], + core_chain_locked_height: 96, + }, + epoch_info: EpochInfo { + current_epoch_index: 1, + previous_epoch_index: None, + is_epoch_change: false, + }, + }, + Some(&transaction), + ) .expect("to pool withdrawal documents into transactions"); let updated_documents = platform diff --git a/packages/rs-drive/src/drive/document/helpers.rs b/packages/rs-drive/src/drive/document/helpers.rs index fcd931cf14f..b1aa5ae3ef8 100644 --- a/packages/rs-drive/src/drive/document/helpers.rs +++ b/packages/rs-drive/src/drive/document/helpers.rs @@ -2,7 +2,7 @@ use dpp::{ contracts::withdrawals_contract, data_contract::extra::common, prelude::{DataContract, Document, Identifier}, - util::{json_value::JsonValueExt, string_encoding::Encoding}, + util::string_encoding::Encoding, }; use grovedb::TransactionArg; use serde_json::{json, Number, Value as JsonValue}; @@ -10,7 +10,6 @@ use serde_json::{json, Number, Value as JsonValue}; use crate::{ drive::{block_info::BlockInfo, Drive}, error::{drive::DriveError, Error}, - fee_pools::epochs::Epoch, }; impl Drive { @@ -19,9 +18,7 @@ impl Drive { &self, contract: &DataContract, document: &mut Document, - block_time_ms: u64, - block_height: u64, - current_epoch_index: u16, + block_info: BlockInfo, transaction: TransactionArg, update_fn: F, ) -> Result<(), Error> @@ -30,7 +27,7 @@ impl Drive { { let document = update_fn(document)?; - document.updated_at = Some(block_time_ms.try_into().map_err(|_| { + document.updated_at = Some(block_info.time_ms.try_into().map_err(|_| { Error::Drive(DriveError::CorruptedCodeExecution( "Can't convert u64 block time to i64 updated_at", )) @@ -50,11 +47,7 @@ impl Drive { })?, withdrawals_contract::types::WITHDRAWAL, Some(document.owner_id.to_buffer()), - BlockInfo { - time_ms: block_time_ms, - height: block_height, - epoch: Epoch::new(current_epoch_index), - }, + block_info, true, None, transaction, @@ -69,9 +62,7 @@ impl Drive { &self, original_transaction_id: &[u8], update_transaction_id: &[u8], - block_time_ms: u64, - block_height: u64, - current_epoch_index: u16, + block_info: BlockInfo, transaction: TransactionArg, ) -> Result<(), Error> { let data_contract_id = Identifier::from_string( @@ -86,7 +77,7 @@ impl Drive { let (_, maybe_data_contract) = self.get_contract_with_fetch_info( data_contract_id.to_buffer(), - Some(&Epoch::new(current_epoch_index)), + Some(&block_info.epoch), transaction, )?; @@ -126,9 +117,7 @@ impl Drive { self.update_document_data( &contract_fetch_info.contract, &mut document, - block_time_ms, - block_height, - current_epoch_index, + block_info.clone(), transaction, |document: &mut Document| -> Result<&mut Document, Error> { document @@ -168,8 +157,11 @@ mod tests { setup_document, setup_drive_with_initial_state_structure, setup_system_data_contract, }; + use dpp::identity::state_transition::identity_credit_withdrawal_transition::Pooling; + + use crate::{drive::block_info::BlockInfo, fee_pools::epochs::Epoch}; + mod update_document_transaction_id { - use dpp::identity::state_transition::identity_credit_withdrawal_transition::Pooling; use super::*; @@ -212,9 +204,11 @@ mod tests { .update_document_transaction_id( &original_transaction_id, &updated_transaction_id, - 1, - 1, - 1, + BlockInfo { + time_ms: 1, + height: 1, + epoch: Epoch::new(1), + }, Some(&transaction), ) .expect("to update transactionId"); From 7aedcba56c7fa45b4fb765a3fedec3f7fd67c2b7 Mon Sep 17 00:00:00 2001 From: Djavid Gabibyan Date: Fri, 23 Dec 2022 20:49:47 +0500 Subject: [PATCH 041/170] chore: PR fixes --- .../rs-drive-abci/src/common/helpers/setup.rs | 5 +- packages/rs-drive-abci/src/config.rs | 35 +++++ .../src/identity_credit_withdrawal/mod.rs | 118 +++++++++++++++-- packages/rs-drive-abci/src/lib.rs | 5 +- packages/rs-drive-abci/src/platform.rs | 25 +++- packages/rs-drive-nodejs/src/lib.rs | 48 +++---- packages/rs-drive/src/drive/config.rs | 12 -- .../withdrawals/transaction_index_counter.rs | 4 +- .../withdrawals/withdrawal_transactions.rs | 125 +----------------- packages/rs-drive/src/drive/mod.rs | 25 ---- 10 files changed, 206 insertions(+), 196 deletions(-) create mode 100644 packages/rs-drive-abci/src/config.rs diff --git a/packages/rs-drive-abci/src/common/helpers/setup.rs b/packages/rs-drive-abci/src/common/helpers/setup.rs index 16573da7670..f2493370772 100644 --- a/packages/rs-drive-abci/src/common/helpers/setup.rs +++ b/packages/rs-drive-abci/src/common/helpers/setup.rs @@ -32,7 +32,7 @@ //! This module defines helper functions related to setting up Platform. //! -use crate::platform::Platform; +use crate::{config::PlatformConfig, platform::Platform}; #[cfg(test)] use dpp::prelude::DataContract; #[cfg(test)] @@ -46,7 +46,8 @@ use tempfile::TempDir; /// A function which sets up Platform. pub fn setup_platform() -> Platform { let tmp_dir = TempDir::new().unwrap(); - let drive: Platform = Platform::open(tmp_dir, None).expect("should open Platform successfully"); + let drive: Platform = Platform::open(tmp_dir, PlatformConfig::default()) + .expect("should open Platform successfully"); drive } diff --git a/packages/rs-drive-abci/src/config.rs b/packages/rs-drive-abci/src/config.rs new file mode 100644 index 00000000000..a39cc7b4b05 --- /dev/null +++ b/packages/rs-drive-abci/src/config.rs @@ -0,0 +1,35 @@ +use drive::drive::config::DriveConfig; + +/// Configuration for Dash Core related things +pub struct CoreConfig { + /// Core RPC client url + pub rpc_url: String, + + /// Core RPC client username + pub rpc_username: String, + + /// Core RPC client password + pub rpc_password: String, +} + +/// Platform configuration +pub struct PlatformConfig { + /// Drive configuration + pub drive: Option, + + /// Dash Core config + pub core: CoreConfig, +} + +impl Default for PlatformConfig { + fn default() -> Self { + Self { + drive: None, + core: CoreConfig { + rpc_url: "".to_owned(), + rpc_username: "".to_owned(), + rpc_password: "".to_owned(), + }, + } + } +} diff --git a/packages/rs-drive-abci/src/identity_credit_withdrawal/mod.rs b/packages/rs-drive-abci/src/identity_credit_withdrawal/mod.rs index 6f89d4f9ae4..522d9ee9138 100644 --- a/packages/rs-drive-abci/src/identity_credit_withdrawal/mod.rs +++ b/packages/rs-drive-abci/src/identity_credit_withdrawal/mod.rs @@ -54,7 +54,7 @@ impl Platform { ExecutionError::CorruptedCodeExecution("Can't fetch withdrawal data contract"), ))?; - let core_transactions = self.drive.fetch_core_block_transactions( + let core_transactions = self.fetch_core_block_transactions( last_synced_core_height, block_execution_context.block_info.core_chain_locked_height, )?; @@ -103,13 +103,7 @@ impl Platform { self.drive .grove - .insert( - path, - &bytes, - Element::Item(bytes.to_vec(), None), - None, - transaction, - ) + .insert(path, &bytes, Element::Item(vec![], None), None, transaction) .unwrap() .map_err(|_| { Error::Execution(ExecutionError::CorruptedCodeExecution( @@ -305,6 +299,47 @@ impl Platform { Ok(()) } + + /// Fetch Core transactions by range of Core heights + pub fn fetch_core_block_transactions( + &self, + last_synced_core_height: u64, + core_chain_locked_height: u64, + ) -> Result, Error> { + let mut tx_hashes: Vec = vec![]; + + for height in last_synced_core_height..=core_chain_locked_height { + let block_hash = self.core_rpc.get_block_hash(height).map_err(|_| { + Error::Execution(ExecutionError::CorruptedCodeExecution( + "could not get block by height", + )) + })?; + + let block_json: JsonValue = + self.core_rpc.get_block_json(&block_hash).map_err(|_| { + Error::Execution(ExecutionError::CorruptedCodeExecution( + "could not get block by hash", + )) + })?; + + if let Some(transactions) = block_json.get("tx") { + if let Some(transactions) = transactions.as_array() { + for transaction_hash in transactions { + tx_hashes.push( + transaction_hash + .as_str() + .ok_or(Error::Execution(ExecutionError::CorruptedCodeExecution( + "could not get transaction hash as string", + )))? + .to_string(), + ); + } + } + } + } + + Ok(tx_hashes) + } } #[cfg(test)] @@ -383,7 +418,7 @@ mod tests { })) }); - platform.drive.core_rpc = Some(Box::new(mock_rpc_client)); + platform.core_rpc = Box::new(mock_rpc_client); let transaction = platform.drive.grove.start_transaction(); @@ -590,4 +625,69 @@ mod tests { } } } + + mod fetch_core_block_transactions { + + use super::*; + + #[test] + fn test_fetches_core_transactions() { + let mut platform = setup_platform_with_initial_state_structure(); + + let mut mock_rpc_client = MockCoreRPCLike::new(); + + mock_rpc_client + .expect_get_block_hash() + .withf(|height| *height == 1) + .returning(|_| { + Ok(BlockHash::from_hex( + "0000000000000000000000000000000000000000000000000000000000000000", + ) + .unwrap()) + }); + + mock_rpc_client + .expect_get_block_hash() + .withf(|height| *height == 2) + .returning(|_| { + Ok(BlockHash::from_hex( + "1111111111111111111111111111111111111111111111111111111111111111", + ) + .unwrap()) + }); + + mock_rpc_client + .expect_get_block_json() + .withf(|bh| { + bh.to_hex() + == "0000000000000000000000000000000000000000000000000000000000000000" + }) + .returning(|_| { + Ok(json!({ + "tx": ["1"] + })) + }); + + mock_rpc_client + .expect_get_block_json() + .withf(|bh| { + bh.to_hex() + == "1111111111111111111111111111111111111111111111111111111111111111" + }) + .returning(|_| { + Ok(json!({ + "tx": ["2"] + })) + }); + + platform.core_rpc = Box::new(mock_rpc_client); + + let transactions = platform + .fetch_core_block_transactions(1, 2) + .expect("to fetch core transactions"); + + assert_eq!(transactions.len(), 2); + assert_eq!(transactions, ["1", "2"]); + } + } } diff --git a/packages/rs-drive-abci/src/lib.rs b/packages/rs-drive-abci/src/lib.rs index 685c17f3ab1..9a4dc7cfaa8 100644 --- a/packages/rs-drive-abci/src/lib.rs +++ b/packages/rs-drive-abci/src/lib.rs @@ -30,5 +30,8 @@ pub mod execution; pub mod platform; -/// Functions related to IdentityCreditWithdrawalTransaction +/// Functions related to IdentityCreditWithdrawalTransaction pub mod identity_credit_withdrawal; + +/// Platform configuration +pub mod config; diff --git a/packages/rs-drive-abci/src/platform.rs b/packages/rs-drive-abci/src/platform.rs index eb4fd47f589..b1d44b88ec0 100644 --- a/packages/rs-drive-abci/src/platform.rs +++ b/packages/rs-drive-abci/src/platform.rs @@ -31,9 +31,11 @@ //! use crate::block::BlockExecutionContext; +use crate::config::PlatformConfig; +use crate::error::execution::ExecutionError; use crate::error::Error; -use drive::drive::config::DriveConfig; use drive::drive::Drive; +use drive::rpc::core::{CoreRPCLike, DefaultCoreRPC}; use std::cell::RefCell; use std::path::Path; @@ -43,15 +45,32 @@ pub struct Platform { pub drive: Drive, /// Block execution context pub block_execution_context: RefCell>, + /// Core RPC Client + pub core_rpc: Box, } impl Platform { /// Open Platform with Drive and block execution context. - pub fn open>(path: P, config: Option) -> Result { - let drive = Drive::open(path, config).map_err(Error::Drive)?; + pub fn open>(path: P, config: PlatformConfig) -> Result { + let drive = Drive::open(path, config.drive).map_err(Error::Drive)?; + + let core_rpc: Box = Box::new( + DefaultCoreRPC::open( + config.core.rpc_url, + config.core.rpc_username, + config.core.rpc_password, + ) + .map_err(|_| { + Error::Execution(ExecutionError::CorruptedCodeExecution( + "Could not setup Dash Core RPC client", + )) + })?, + ); + Ok(Platform { drive, block_execution_context: RefCell::new(None), + core_rpc, }) } } diff --git a/packages/rs-drive-nodejs/src/lib.rs b/packages/rs-drive-nodejs/src/lib.rs index 0724a09afdb..4beb57d7367 100644 --- a/packages/rs-drive-nodejs/src/lib.rs +++ b/packages/rs-drive-nodejs/src/lib.rs @@ -1,9 +1,7 @@ mod converter; mod fee_result; -use drive::dpp::dashcore::hashes::hex::FromHex; -use drive::dpp::dashcore::BlockHash; -use drive::rpc::core::MockCoreRPCLike; +use drive_abci::config::{CoreConfig, PlatformConfig}; use std::ops::Deref; use std::{option::Option::None, path::Path, sync::mpsc, thread}; @@ -22,7 +20,6 @@ use drive_abci::abci::messages::{ }; use drive_abci::platform::Platform; use neon::prelude::*; -use serde_json::json; type PlatformCallback = Box FnOnce(&'a Platform, TransactionArg, &Channel) + Send>; type UnitCallback = Box; @@ -60,7 +57,18 @@ impl PlatformWrapper { fn new(cx: &mut FunctionContext) -> NeonResult { // Drive's configuration let path_string = cx.argument::(0)?.value(cx); - let drive_config = cx.argument::(1)?; + let platform_config = cx.argument::(1)?; + + let drive_config: Handle = platform_config.get(cx, "drive")?; + let core_config: Handle = platform_config.get(cx, "core")?; + + let js_core_rpc_url: Handle = core_config.get(cx, "rpc_url")?; + let js_core_rpc_username: Handle = core_config.get(cx, "rpc_username")?; + let js_core_rpc_password: Handle = core_config.get(cx, "rpc_password")?; + + let core_rpc_url = js_core_rpc_url.value(cx); + let core_rpc_username = js_core_rpc_username.value(cx); + let core_rpc_password = js_core_rpc_password.value(cx); let js_data_contracts_cache_size: Handle = drive_config.get(cx, "dataContractsGlobalCacheSize")?; @@ -100,27 +108,19 @@ impl PlatformWrapper { ..Default::default() }; - // TODO: think how to pass this error to JS - let mut platform: Platform = Platform::open(path, Some(drive_config)).unwrap(); - - if cfg!(feature = "enable-core-rpc-mocking") { - let mut core_rpc_mock = MockCoreRPCLike::new(); - - core_rpc_mock.expect_get_block_hash().returning(|_| { - Ok(BlockHash::from_hex( - "0000000000000000000000000000000000000000000000000000000000000000", - ) - .unwrap()) - }); + let core_config = CoreConfig { + rpc_url: core_rpc_url, + rpc_username: core_rpc_username, + rpc_password: core_rpc_password, + }; - core_rpc_mock.expect_get_block_json().returning(|_| { - Ok(json!({ - "tx": [], - })) - }); + let platform_config = PlatformConfig { + drive: Some(drive_config), + core: core_config, + }; - platform.drive.core_rpc = Some(Box::new(core_rpc_mock)); - } + // TODO: think how to pass this error to JS + let platform: Platform = Platform::open(path, platform_config).unwrap(); let mut maybe_transaction: Option = None; diff --git a/packages/rs-drive/src/drive/config.rs b/packages/rs-drive/src/drive/config.rs index f60b8d38d2e..a40b157fe67 100644 --- a/packages/rs-drive/src/drive/config.rs +++ b/packages/rs-drive/src/drive/config.rs @@ -71,15 +71,6 @@ pub struct DriveConfig { /// Maximum number of contracts in block candidate cache pub data_contracts_block_cache_size: u64, - - /// Core RPC client url - pub core_rpc_url: Option, - - /// Core RPC client username - pub core_rpc_username: Option, - - /// Core RPC client password - pub core_rpc_password: Option, } impl Default for DriveConfig { @@ -93,9 +84,6 @@ impl Default for DriveConfig { encoding: DriveCbor, data_contracts_global_cache_size: DEFAULT_DATA_CONTRACTS_CACHE_SIZE, data_contracts_block_cache_size: DEFAULT_DATA_CONTRACTS_CACHE_SIZE, - core_rpc_url: None, - core_rpc_password: None, - core_rpc_username: None, } } } diff --git a/packages/rs-drive/src/drive/identity/withdrawals/transaction_index_counter.rs b/packages/rs-drive/src/drive/identity/withdrawals/transaction_index_counter.rs index 0dbc6b83be7..a609f41c03f 100644 --- a/packages/rs-drive/src/drive/identity/withdrawals/transaction_index_counter.rs +++ b/packages/rs-drive/src/drive/identity/withdrawals/transaction_index_counter.rs @@ -40,10 +40,10 @@ impl Drive { if expired_index_elements.len() > 0 { let expired_index_element_pair = expired_index_elements.into_iter().next().unwrap(); - if let QueryResultElement::KeyElementPairResultItem((key, Element::Item(bytes, _))) = + if let QueryResultElement::KeyElementPairResultItem((key, _)) = expired_index_element_pair { - let index = u64::from_be_bytes(bytes.try_into().map_err(|_| { + let index = u64::from_be_bytes(key.clone().try_into().map_err(|_| { Error::Drive(DriveError::CorruptedCodeExecution( "Transaction index has wrong length", )) diff --git a/packages/rs-drive/src/drive/identity/withdrawals/withdrawal_transactions.rs b/packages/rs-drive/src/drive/identity/withdrawals/withdrawal_transactions.rs index 00d1f09b5b4..ad32ac44a73 100644 --- a/packages/rs-drive/src/drive/identity/withdrawals/withdrawal_transactions.rs +++ b/packages/rs-drive/src/drive/identity/withdrawals/withdrawal_transactions.rs @@ -1,4 +1,4 @@ -use std::{collections::HashMap, ops::RangeFull}; +use std::collections::HashMap; use dashcore::{ blockdata::transaction::special_transaction::asset_unlock::unqualified_asset_unlock::{ @@ -13,7 +13,6 @@ use dpp::{ util::json_value::JsonValueExt, }; use grovedb::TransactionArg; -use serde_json::Value as JsonValue; use crate::{ drive::Drive, @@ -96,64 +95,14 @@ impl Drive { Ok(withdrawals) } - - /// Fetch Core transactions by range of Core heights - pub fn fetch_core_block_transactions( - &self, - last_synced_core_height: u64, - core_chain_locked_height: u64, - ) -> Result, Error> { - let core_rpc = - self.core_rpc - .as_ref() - .ok_or(Error::Drive(DriveError::CorruptedCodeExecution( - "Core RPC client has not been set up", - )))?; - - let mut tx_hashes: Vec = vec![]; - - for height in last_synced_core_height..=core_chain_locked_height { - let block_hash = core_rpc.get_block_hash(height).map_err(|_| { - Error::Drive(DriveError::CorruptedCodeExecution( - "could not get block by height", - )) - })?; - - let block_json: JsonValue = core_rpc.get_block_json(&block_hash).map_err(|_| { - Error::Drive(DriveError::CorruptedCodeExecution( - "could not get block by hash", - )) - })?; - - if let Some(transactions) = block_json.get("tx") { - if let Some(transactions) = transactions.as_array() { - for transaction_hash in transactions { - tx_hashes.push( - transaction_hash - .as_str() - .ok_or(Error::Drive(DriveError::CorruptedCodeExecution( - "could not get transaction hash as string", - )))? - .to_string(), - ); - } - } - } - } - - Ok(tx_hashes) - } } #[cfg(test)] mod tests { use crate::common::helpers::setup::setup_drive_with_initial_state_structure; - use dashcore::{hashes::hex::FromHex, hashes::hex::ToHex, BlockHash}; use serde_json::json; - use crate::rpc::core::MockCoreRPCLike; - use dpp::{ contracts::withdrawals_contract, tests::fixtures::{get_withdrawal_document_fixture, get_withdrawals_data_contract_fixture}, @@ -164,73 +113,9 @@ mod tests { drive::identity::withdrawals::paths::WithdrawalTransaction, }; - mod fetch_core_block_transactions { - - use super::*; - - #[test] - fn test_fetches_core_transactions() { - let mut drive = setup_drive_with_initial_state_structure(); - - let mut mock_rpc_client = MockCoreRPCLike::new(); - - mock_rpc_client - .expect_get_block_hash() - .withf(|height| *height == 1) - .returning(|_| { - Ok(BlockHash::from_hex( - "0000000000000000000000000000000000000000000000000000000000000000", - ) - .unwrap()) - }); - - mock_rpc_client - .expect_get_block_hash() - .withf(|height| *height == 2) - .returning(|_| { - Ok(BlockHash::from_hex( - "1111111111111111111111111111111111111111111111111111111111111111", - ) - .unwrap()) - }); - - mock_rpc_client - .expect_get_block_json() - .withf(|bh| { - bh.to_hex() - == "0000000000000000000000000000000000000000000000000000000000000000" - }) - .returning(|_| { - Ok(json!({ - "tx": ["1"] - })) - }); - - mock_rpc_client - .expect_get_block_json() - .withf(|bh| { - bh.to_hex() - == "1111111111111111111111111111111111111111111111111111111111111111" - }) - .returning(|_| { - Ok(json!({ - "tx": ["2"] - })) - }); - - drive.core_rpc = Some(Box::new(mock_rpc_client)); - - let transactions = drive - .fetch_core_block_transactions(1, 2) - .expect("to fetch core transactions"); - - assert_eq!(transactions.len(), 2); - assert_eq!(transactions, ["1", "2"]); - } - } - mod build_withdrawal_transactions_from_documents { use dpp::identity::state_transition::identity_credit_withdrawal_transition::Pooling; + use itertools::Itertools; use super::*; @@ -282,6 +167,7 @@ mod tests { transactions .values() .cloned() + .sorted() .collect::>(), vec![ ( @@ -300,7 +186,10 @@ mod tests { 1, 1, 0, 0, 0, 0, 0, 0, 0, 192, 206, 2, 0, ], ), - ], + ] + .into_iter() + .sorted() + .collect::>(), ); } } diff --git a/packages/rs-drive/src/drive/mod.rs b/packages/rs-drive/src/drive/mod.rs index ce249987aee..3f14c0970c9 100644 --- a/packages/rs-drive/src/drive/mod.rs +++ b/packages/rs-drive/src/drive/mod.rs @@ -40,7 +40,6 @@ use object_size_info::DocumentInfo::DocumentEstimatedAverageSize; use crate::contract::Contract; use crate::drive::batch::GroveDbOpBatch; use crate::drive::config::DriveConfig; -use crate::error::drive::DriveError; use crate::error::Error; use crate::fee::op::DriveOperation; use crate::fee::op::DriveOperation::GroveOperation; @@ -76,11 +75,8 @@ use crate::drive::block_info::BlockInfo; use crate::drive::cache::{DataContractCache, DriveCache}; use crate::fee::FeeResult; use crate::fee_pools::epochs::Epoch; -use crate::rpc::core::{CoreRPCLike, DefaultCoreRPC}; use dpp::data_contract::extra::DriveContractExt; -type TransactionPointerAddress = usize; - /// Drive struct pub struct Drive { /// GroveDB @@ -89,8 +85,6 @@ pub struct Drive { pub config: DriveConfig, /// Drive Cache pub cache: RefCell, - /// Core RPC Client - pub core_rpc: Option>, } /// Keys for the root tree. @@ -161,24 +155,6 @@ impl Drive { let data_contracts_global_cache_size = config.data_contracts_global_cache_size; let data_contracts_block_cache_size = config.data_contracts_block_cache_size; - let core_rpc: Option> = - if let (Some(url), Some(username), Some(password)) = ( - &config.core_rpc_url, - &config.core_rpc_username, - &config.core_rpc_password, - ) { - Some(Box::new( - DefaultCoreRPC::open(url.clone(), username.clone(), password.clone()) - .map_err(|_| { - Error::Drive(DriveError::CorruptedCodeExecution( - "Could not setup Dash Core RPC client", - )) - })?, - )) - } else { - None - }; - Ok(Drive { grove, config, @@ -189,7 +165,6 @@ impl Drive { ), genesis_time_ms, }), - core_rpc, }) } Err(e) => Err(Error::GroveDB(e)), From 3c1036d27ec27350d08e0875a87ca641cf6975ad Mon Sep 17 00:00:00 2001 From: Djavid Gabibyan Date: Fri, 23 Dec 2022 22:10:48 +0500 Subject: [PATCH 042/170] chore: PR fixes --- Cargo.lock | 1 - packages/rs-drive-abci/Cargo.toml | 3 ++ packages/rs-drive-abci/src/abci/handlers.rs | 6 ++-- .../src/identity_credit_withdrawal/mod.rs | 2 +- packages/rs-drive-abci/src/platform.rs | 31 +++++++++++++++++++ packages/rs-drive-nodejs/Cargo.toml | 5 ++- packages/rs-drive-nodejs/package.json | 2 +- packages/rs-drive-nodejs/scripts/build.sh | 4 +-- packages/rs-drive-nodejs/src/lib.rs | 6 +++- packages/rs-drive-nodejs/test/Drive.spec.js | 11 +++++-- 10 files changed, 56 insertions(+), 15 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 933dfefbf8f..4588035b2e5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -985,7 +985,6 @@ dependencies = [ "drive-abci", "neon", "num 0.4.0", - "serde_json", ] [[package]] diff --git a/packages/rs-drive-abci/Cargo.toml b/packages/rs-drive-abci/Cargo.toml index 19a1b2bf67e..fcada6d575e 100644 --- a/packages/rs-drive-abci/Cargo.toml +++ b/packages/rs-drive-abci/Cargo.toml @@ -22,3 +22,6 @@ base64 = "0.13.0" hex = "0.4.3" dashcore = { git="https://github.com/dashevo/rust-dashcore", features=["std", "secp-recovery", "rand", "signer", "use-serde"], default-features = false, rev = "6092d584487918c5330fec93152e4df06a714067" } dpp = { path = "../rs-dpp", features = ["fixtures-and-mocks"]} + +[features] +fixtures-and-mocks = [] diff --git a/packages/rs-drive-abci/src/abci/handlers.rs b/packages/rs-drive-abci/src/abci/handlers.rs index 8d9855275fa..0193fe4c702 100644 --- a/packages/rs-drive-abci/src/abci/handlers.rs +++ b/packages/rs-drive-abci/src/abci/handlers.rs @@ -158,7 +158,7 @@ impl TenderdashAbci for Platform { ), ))?; - self.pool_withdrawals_into_transactions(&block_execution_context, transaction)?; + self.pool_withdrawals_into_transactions(block_execution_context, transaction)?; // Process fees let process_block_fees_result = self.process_block_fees( @@ -294,7 +294,7 @@ mod tests { // .times(total_days) .returning(|_| Ok(json!({}))); - platform.drive.core_rpc = Some(Box::new(core_rpc_mock)); + platform.core_rpc = Box::new(core_rpc_mock); // process blocks for day in 0..total_days { @@ -464,7 +464,7 @@ mod tests { // .times(1) // TODO: investigate why it always n + 1 .returning(|_| Ok(json!({}))); - platform.drive.core_rpc = Some(Box::new(core_rpc_mock)); + platform.core_rpc = Box::new(core_rpc_mock); let transaction = platform.drive.grove.start_transaction(); diff --git a/packages/rs-drive-abci/src/identity_credit_withdrawal/mod.rs b/packages/rs-drive-abci/src/identity_credit_withdrawal/mod.rs index 522d9ee9138..f0b016fba83 100644 --- a/packages/rs-drive-abci/src/identity_credit_withdrawal/mod.rs +++ b/packages/rs-drive-abci/src/identity_credit_withdrawal/mod.rs @@ -524,7 +524,7 @@ mod tests { #[test] fn test_pooling() { - let mut platform = setup_platform_with_initial_state_structure(); + let platform = setup_platform_with_initial_state_structure(); let transaction = platform.drive.grove.start_transaction(); diff --git a/packages/rs-drive-abci/src/platform.rs b/packages/rs-drive-abci/src/platform.rs index b1d44b88ec0..ea044396aa2 100644 --- a/packages/rs-drive-abci/src/platform.rs +++ b/packages/rs-drive-abci/src/platform.rs @@ -39,6 +39,15 @@ use drive::rpc::core::{CoreRPCLike, DefaultCoreRPC}; use std::cell::RefCell; use std::path::Path; +#[cfg(feature = "fixtures-and-mocks")] +use dashcore::hashes::hex::FromHex; +#[cfg(feature = "fixtures-and-mocks")] +use dashcore::BlockHash; +#[cfg(feature = "fixtures-and-mocks")] +use drive::rpc::core::MockCoreRPCLike; +#[cfg(feature = "fixtures-and-mocks")] +use serde_json::json; + /// Platform pub struct Platform { /// Drive @@ -73,4 +82,26 @@ impl Platform { core_rpc, }) } + + /// Helper function to be able + /// to quickly mock core rpc for tests + #[cfg(feature = "fixtures-and-mocks")] + pub fn mock_core_rpc_client(&mut self) { + let mut core_rpc_mock = MockCoreRPCLike::new(); + + core_rpc_mock.expect_get_block_hash().returning(|_| { + Ok(BlockHash::from_hex( + "0000000000000000000000000000000000000000000000000000000000000000", + ) + .unwrap()) + }); + + core_rpc_mock.expect_get_block_json().returning(|_| { + Ok(json!({ + "tx": [], + })) + }); + + self.core_rpc = Box::new(core_rpc_mock); + } } diff --git a/packages/rs-drive-nodejs/Cargo.toml b/packages/rs-drive-nodejs/Cargo.toml index c832b14481d..3e80db4ea1e 100644 --- a/packages/rs-drive-nodejs/Cargo.toml +++ b/packages/rs-drive-nodejs/Cargo.toml @@ -10,10 +10,9 @@ private = true crate-type = ["cdylib"] [dependencies] -drive = { path = "../rs-drive", features = ["fixtures-and-mocks"]} -drive-abci = { path = "../rs-drive-abci" } +drive = { path = "../rs-drive", features = ["fixtures-and-mocks"] } +drive-abci = { path = "../rs-drive-abci", features = ["fixtures-and-mocks"] } num = "0.4.0" -serde_json = { version="1.0", features=["preserve_order"] } [dependencies.neon] version = "0.10.1" diff --git a/packages/rs-drive-nodejs/package.json b/packages/rs-drive-nodejs/package.json index 6eacda69e04..28cff402975 100644 --- a/packages/rs-drive-nodejs/package.json +++ b/packages/rs-drive-nodejs/package.json @@ -5,7 +5,7 @@ "main": "Drive.js", "scripts": { "build": "yarn exec scripts/build.sh", - "test": "ultra --build && mocha test", + "test": "CARGO_BUILD_PROFILE=test ultra --build && mocha test", "lint": "eslint ." }, "files": [ diff --git a/packages/rs-drive-nodejs/scripts/build.sh b/packages/rs-drive-nodejs/scripts/build.sh index a405e3aff26..dc316035f0e 100755 --- a/packages/rs-drive-nodejs/scripts/build.sh +++ b/packages/rs-drive-nodejs/scripts/build.sh @@ -1,18 +1,16 @@ #!/usr/bin/env bash PROFILE_ARG="" -FEATURES_ARG="" if [ -n "$CARGO_BUILD_PROFILE" ]; then if [ "$CARGO_BUILD_PROFILE" == "release" ]; then PROFILE_ARG="--release" elif [ "$CARGO_BUILD_PROFILE" != "debug" ]; then PROFILE_ARG="--profile $CARGO_BUILD_PROFILE" - FEATURES_ARG="--features enable-core-rpc-mocking" fi fi cargo-cp-artifact -ac drive-nodejs native/index.node -- \ - cargo build --message-format=json-render-diagnostics $PROFILE_ARG $FEATURES_ARG --features enable-core-rpc-mocking \ + cargo build --message-format=json-render-diagnostics $PROFILE_ARG \ && neon-tag-prebuild \ && rm -rf native diff --git a/packages/rs-drive-nodejs/src/lib.rs b/packages/rs-drive-nodejs/src/lib.rs index 4beb57d7367..8760fc772a1 100644 --- a/packages/rs-drive-nodejs/src/lib.rs +++ b/packages/rs-drive-nodejs/src/lib.rs @@ -120,7 +120,11 @@ impl PlatformWrapper { }; // TODO: think how to pass this error to JS - let platform: Platform = Platform::open(path, platform_config).unwrap(); + let mut platform: Platform = Platform::open(path, platform_config).unwrap(); + + if cfg!(test) { + platform.mock_core_rpc_client(); + } let mut maybe_transaction: Option = None; diff --git a/packages/rs-drive-nodejs/test/Drive.spec.js b/packages/rs-drive-nodejs/test/Drive.spec.js index 6ef7ad512e3..93983d3c0f1 100644 --- a/packages/rs-drive-nodejs/test/Drive.spec.js +++ b/packages/rs-drive-nodejs/test/Drive.spec.js @@ -39,8 +39,15 @@ describe('Drive', function main() { beforeEach(async () => { drive = new Drive(TEST_DATA_PATH, { - dataContractsGlobalCacheSize: 500, - dataContractsBlockCacheSize: 500, + drive: { + dataContractsGlobalCacheSize: 500, + dataContractsBlockCacheSize: 500, + }, + core: { + rpcUrl: '', + rpcUsername: '', + rpcPassword: '', + }, }); const dpp = new DashPlatformProtocol({ From ec99d5e3e7b7afeeaad70f19107695bdbc324244 Mon Sep 17 00:00:00 2001 From: Djavid Gabibyan Date: Fri, 23 Dec 2022 22:41:37 +0500 Subject: [PATCH 043/170] chore: PR fixes --- .../lib/abci/handlers/proposal/beginBlockFactory.js | 2 +- packages/rs-drive-abci/src/abci/handlers.rs | 8 +++++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/packages/js-drive/lib/abci/handlers/proposal/beginBlockFactory.js b/packages/js-drive/lib/abci/handlers/proposal/beginBlockFactory.js index 1d730cf002d..3e217276da7 100644 --- a/packages/js-drive/lib/abci/handlers/proposal/beginBlockFactory.js +++ b/packages/js-drive/lib/abci/handlers/proposal/beginBlockFactory.js @@ -113,7 +113,7 @@ function beginBlockFactory( useTransaction: true, }); - const lastSyncedCoreHeight = lastSyncedHeightResult.getValue() || coreChainLockedHeight; + const lastSyncedCoreHeight = lastSyncedHeightResult.getValue() || 0; // Call RS ABCI diff --git a/packages/rs-drive-abci/src/abci/handlers.rs b/packages/rs-drive-abci/src/abci/handlers.rs index 0193fe4c702..7558fbafefe 100644 --- a/packages/rs-drive-abci/src/abci/handlers.rs +++ b/packages/rs-drive-abci/src/abci/handlers.rs @@ -120,8 +120,14 @@ impl TenderdashAbci for Platform { epoch_info: epoch_info.clone(), }; + let last_synced_core_height = if request.last_synced_core_height == 0 { + block_execution_context.block_info.core_chain_locked_height + } else { + request.last_synced_core_height + }; + self.update_broadcasted_withdrawal_transaction_statuses( - request.last_synced_core_height, + last_synced_core_height, &block_execution_context, transaction, )?; From 70ddde3c71a8be7d123cdfd2284b24c33fa00129 Mon Sep 17 00:00:00 2001 From: Djavid Gabibyan Date: Fri, 23 Dec 2022 23:32:56 +0500 Subject: [PATCH 044/170] chore: PR fixes --- .../handlers/finalizeBlockHandlerFactory.js | 41 +++--------- .../broadcastWithdrawalTransactionsFactory.js | 60 +++++++++++++++++ .../finalizeBlockHandlerFactory.spec.js | 19 +++--- ...dcastWithdrawalTransactionsFactory.spec.js | 66 +++++++++++++++++++ 4 files changed, 143 insertions(+), 43 deletions(-) create mode 100644 packages/js-drive/lib/abci/handlers/proposal/broadcastWithdrawalTransactionsFactory.js create mode 100644 packages/js-drive/test/unit/abci/handlers/proposal/broadcastWithdrawalTransactionsFactory.spec.js diff --git a/packages/js-drive/lib/abci/handlers/finalizeBlockHandlerFactory.js b/packages/js-drive/lib/abci/handlers/finalizeBlockHandlerFactory.js index 9f600c0ea8f..fc281ece7e9 100644 --- a/packages/js-drive/lib/abci/handlers/finalizeBlockHandlerFactory.js +++ b/packages/js-drive/lib/abci/handlers/finalizeBlockHandlerFactory.js @@ -6,32 +6,30 @@ const { }, }, } = require('@dashevo/abci/types'); -const lodashCloneDeep = require('lodash/cloneDeep'); -const BlockInfo = require('../../blockExecution/BlockInfo'); +const lodashCloneDeep = require('lodash/cloneDeep'); /** * * @return {finalizeBlockHandler} * @param {GroveDBStore} groveDBStore * @param {BlockExecutionContextRepository} blockExecutionContextRepository - * @param {CoreRpcClient} coreRpcClient * @param {BaseLogger} logger * @param {ExecutionTimer} executionTimer * @param {BlockExecutionContext} latestBlockExecutionContext * @param {BlockExecutionContext} proposalBlockExecutionContext * @param {processProposal} processProposal + * @param {broadcastWithdrawalTransactions} broadcastWithdrawalTransactions */ function finalizeBlockHandlerFactory( groveDBStore, blockExecutionContextRepository, - coreRpcClient, logger, executionTimer, latestBlockExecutionContext, proposalBlockExecutionContext, processProposal, - updateWithdrawalTransactionIdAndStatus, + broadcastWithdrawalTransactions, ) { /** * @typedef finalizeBlockHandler @@ -119,34 +117,11 @@ function finalizeBlockHandlerFactory( const { thresholdVoteExtensions } = commitInfo; - const blockInfo = BlockInfo.createFromBlockExecutionContext(proposalBlockExecutionContext); - - for (const { extension, signature } of (thresholdVoteExtensions || [])) { - const withdrawalTransactionHash = extension.toString('hex'); - - const unsignedWithdrawalTransactionBytes = unsignedWithdrawalTransactionsMap[ - withdrawalTransactionHash - ]; - - if (unsignedWithdrawalTransactionBytes) { - const transactionBytes = Buffer.concat([ - unsignedWithdrawalTransactionBytes, - signature, - ]); - - // TODO: think about Core error handling - await coreRpcClient.sendRawTransaction(transactionBytes.toString('hex')); - - await updateWithdrawalTransactionIdAndStatus( - blockInfo, - unsignedWithdrawalTransactionBytes, - transactionBytes, - { - useTransaction: true, - }, - ); - } - } + await broadcastWithdrawalTransactions( + proposalBlockExecutionContext, + thresholdVoteExtensions, + unsignedWithdrawalTransactionsMap, + ); proposalBlockExecutionContext.reset(); diff --git a/packages/js-drive/lib/abci/handlers/proposal/broadcastWithdrawalTransactionsFactory.js b/packages/js-drive/lib/abci/handlers/proposal/broadcastWithdrawalTransactionsFactory.js new file mode 100644 index 00000000000..15c8898ef61 --- /dev/null +++ b/packages/js-drive/lib/abci/handlers/proposal/broadcastWithdrawalTransactionsFactory.js @@ -0,0 +1,60 @@ +const BlockInfo = require('../../../blockExecution/BlockInfo'); + +/** + * @param {CoreRpcClient} coreRpcClient + * @param {updateWithdrawalTransactionIdAndStatus} updateWithdrawalTransactionIdAndStatus + * + * @return {broadcastWithdrawalTransactions} + */ +function broadcastWithdrawalTransactionsFactory( + coreRpcClient, + updateWithdrawalTransactionIdAndStatus, +) { + /** + * @typedef broadcastWithdrawalTransactions + * + * @param {BlockExecutionContext} proposalBlockExecutionContext + * @param {{{ extension: Buffer, signature: Buffer }}[]} thresholdVoteExtensions + * @param {Object} unsignedWithdrawalTransactionsMap + * + * @return {Promise} + */ + async function broadcastWithdrawalTransactions( + proposalBlockExecutionContext, + thresholdVoteExtensions, + unsignedWithdrawalTransactionsMap, + ) { + const blockInfo = BlockInfo.createFromBlockExecutionContext(proposalBlockExecutionContext); + + for (const { extension, signature } of (thresholdVoteExtensions || [])) { + const withdrawalTransactionHash = extension.toString('hex'); + + const unsignedWithdrawalTransactionBytes = unsignedWithdrawalTransactionsMap[ + withdrawalTransactionHash + ]; + + if (unsignedWithdrawalTransactionBytes) { + const transactionBytes = Buffer.concat([ + unsignedWithdrawalTransactionBytes, + signature, + ]); + + // TODO: think about Core error handling + await coreRpcClient.sendRawTransaction(transactionBytes.toString('hex')); + + await updateWithdrawalTransactionIdAndStatus( + blockInfo, + unsignedWithdrawalTransactionBytes, + transactionBytes, + { + useTransaction: true, + }, + ); + } + } + } + + return broadcastWithdrawalTransactions; +} + +module.exports = broadcastWithdrawalTransactionsFactory; diff --git a/packages/js-drive/test/unit/abci/handlers/finalizeBlockHandlerFactory.spec.js b/packages/js-drive/test/unit/abci/handlers/finalizeBlockHandlerFactory.spec.js index ab6a966442b..620cd1786b9 100644 --- a/packages/js-drive/test/unit/abci/handlers/finalizeBlockHandlerFactory.spec.js +++ b/packages/js-drive/test/unit/abci/handlers/finalizeBlockHandlerFactory.spec.js @@ -25,14 +25,13 @@ describe('finalizeBlockHandlerFactory', () => { let requestMock; let appHash; let groveDBStoreMock; - let coreRpcClientMock; let blockExecutionContextRepositoryMock; let dataContract; let proposalBlockExecutionContextMock; let round; let block; let processProposalMock; - let updateWithdrawalTransactionIdAndStatusMock; + let broadcastWithdrawalTransactions; beforeEach(function beforeEach() { round = 0; @@ -93,28 +92,23 @@ describe('finalizeBlockHandlerFactory', () => { groveDBStoreMock = new GroveDBStoreMock(this.sinon); groveDBStoreMock.getRootHash.resolves(appHash); - coreRpcClientMock = { - sendRawTransaction: this.sinon.stub(), - }; - blockExecutionContextRepositoryMock = new BlockExecutionContextRepositoryMock( this.sinon, ); processProposalMock = this.sinon.stub(); - updateWithdrawalTransactionIdAndStatusMock = this.sinon.stub(); + broadcastWithdrawalTransactions = this.sinon.stub(); finalizeBlockHandler = finalizeBlockHandlerFactory( groveDBStoreMock, blockExecutionContextRepositoryMock, - coreRpcClientMock, loggerMock, executionTimerMock, latestBlockExecutionContextMock, proposalBlockExecutionContextMock, processProposalMock, - updateWithdrawalTransactionIdAndStatusMock, + broadcastWithdrawalTransactions, ); }); @@ -138,6 +132,12 @@ describe('finalizeBlockHandlerFactory', () => { expect(latestBlockExecutionContextMock.populate).to.be.calledOnce(); expect(processProposalMock).to.be.not.called(); + + expect(broadcastWithdrawalTransactions).to.have.been.calledOnceWith( + proposalBlockExecutionContextMock, + undefined, + undefined, + ); }); it('should send withdrawal transaction if vote extensions are present', async () => { @@ -166,7 +166,6 @@ describe('finalizeBlockHandlerFactory', () => { await finalizeBlockHandler(requestMock); - expect(coreRpcClientMock.sendRawTransaction).to.have.been.calledTwice(); expect(processProposalMock).to.be.not.called(); }); diff --git a/packages/js-drive/test/unit/abci/handlers/proposal/broadcastWithdrawalTransactionsFactory.spec.js b/packages/js-drive/test/unit/abci/handlers/proposal/broadcastWithdrawalTransactionsFactory.spec.js new file mode 100644 index 00000000000..7e3ad2a6001 --- /dev/null +++ b/packages/js-drive/test/unit/abci/handlers/proposal/broadcastWithdrawalTransactionsFactory.spec.js @@ -0,0 +1,66 @@ +const Long = require('long'); + +const BlockExecutionContextMock = require('../../../../../lib/test/mock/BlockExecutionContextMock'); + +const broadcastWithdrawalTransactionsFactory = require('../../../../../lib/abci/handlers/proposal/broadcastWithdrawalTransactionsFactory'); +const BlockInfo = require('../../../../../lib/blockExecution/BlockInfo'); + +describe('broadcastWithdrawalTransactionsFactory', () => { + let broadcastWithdrawalTransactions; + let proposalBlockExecutionContextMock; + let coreRpcMock; + let updateWithdrawalTransactionIdAndStatusMock; + + beforeEach(function beforeEach() { + proposalBlockExecutionContextMock = new BlockExecutionContextMock(this.sinon); + + proposalBlockExecutionContextMock.getEpochInfo.returns({ + currentEpochIndex: 1, + }); + proposalBlockExecutionContextMock.getHeight.returns(new Long(1)); + proposalBlockExecutionContextMock.getTimeMs.returns(1); + + coreRpcMock = { + sendRawTransaction: this.sinon.stub(), + }; + + updateWithdrawalTransactionIdAndStatusMock = this.sinon.stub(); + + broadcastWithdrawalTransactions = broadcastWithdrawalTransactionsFactory( + coreRpcMock, + updateWithdrawalTransactionIdAndStatusMock, + ); + }); + + it('should call Core RPC and call document update function', async () => { + const extension = Buffer.alloc(32, 2); + const signature = Buffer.alloc(32, 3); + + const txBytes = Buffer.alloc(32, 1); + + const thresholdVoteExtensions = [ + { extension, signature }, + ]; + const unsignedWithdrawalTransactionsMap = { + [extension.toString('hex')]: txBytes, + }; + + await broadcastWithdrawalTransactions( + proposalBlockExecutionContextMock, + thresholdVoteExtensions, + unsignedWithdrawalTransactionsMap, + ); + + expect(coreRpcMock.sendRawTransaction).to.have.been.calledOnceWithExactly( + Buffer.concat([txBytes, signature]).toString('hex'), + ); + expect(updateWithdrawalTransactionIdAndStatusMock).to.have.been.calledOnceWithExactly( + BlockInfo.createFromBlockExecutionContext(proposalBlockExecutionContextMock), + txBytes, + Buffer.concat([txBytes, signature]), + { + useTransaction: true, + }, + ); + }); +}); From c339f72fa15bcb71558068952dafa1f30f411f9f Mon Sep 17 00:00:00 2001 From: Djavid Gabibyan Date: Fri, 23 Dec 2022 23:46:03 +0500 Subject: [PATCH 045/170] chore: PR fixes --- packages/rs-drive-abci/src/abci/handlers.rs | 1 - .../drive/identity/withdrawals/transaction_index_counter.rs | 6 +++--- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/packages/rs-drive-abci/src/abci/handlers.rs b/packages/rs-drive-abci/src/abci/handlers.rs index a451d777045..e69e7cd4cb3 100644 --- a/packages/rs-drive-abci/src/abci/handlers.rs +++ b/packages/rs-drive-abci/src/abci/handlers.rs @@ -203,7 +203,6 @@ mod tests { use drive::common::helpers::identities::create_test_masternode_identities; use drive::drive::batch::GroveDbOpBatch; use drive::fee::epoch::CreditsPerEpoch; - use drive::fee::FeeResult; use drive::rpc::core::MockCoreRPCLike; use rust_decimal::prelude::ToPrimitive; use serde_json::json; diff --git a/packages/rs-drive/src/drive/identity/withdrawals/transaction_index_counter.rs b/packages/rs-drive/src/drive/identity/withdrawals/transaction_index_counter.rs index a609f41c03f..586c0b21559 100644 --- a/packages/rs-drive/src/drive/identity/withdrawals/transaction_index_counter.rs +++ b/packages/rs-drive/src/drive/identity/withdrawals/transaction_index_counter.rs @@ -37,8 +37,8 @@ impl Drive { ) .unwrap()?; - if expired_index_elements.len() > 0 { - let expired_index_element_pair = expired_index_elements.into_iter().next().unwrap(); + if !expired_index_elements.is_empty() { + let expired_index_element_pair = expired_index_elements.elements.get(0).unwrap(); if let QueryResultElement::KeyElementPairResultItem((key, _)) = expired_index_element_pair @@ -51,7 +51,7 @@ impl Drive { let path: [&[u8]; 2] = get_withdrawal_transactions_expired_ids_path_as_u8(); - self.grove.delete(path, &key, None, transaction).unwrap()?; + self.grove.delete(path, key, None, transaction).unwrap()?; return Ok(index); } From 05c99fcd6a84016597a8570ebc534ade596bca15 Mon Sep 17 00:00:00 2001 From: Djavid Gabibiyan Date: Tue, 27 Dec 2022 11:50:15 +0500 Subject: [PATCH 046/170] chore: more ops --- .../src/drive/batch/drive_op_batch.rs | 124 +++++++++++++++++- .../src/drive/identity/withdrawals/paths.rs | 10 ++ 2 files changed, 133 insertions(+), 1 deletion(-) diff --git a/packages/rs-drive/src/drive/batch/drive_op_batch.rs b/packages/rs-drive/src/drive/batch/drive_op_batch.rs index e7d5a46817a..119fd7b8261 100644 --- a/packages/rs-drive/src/drive/batch/drive_op_batch.rs +++ b/packages/rs-drive/src/drive/batch/drive_op_batch.rs @@ -31,6 +31,12 @@ use crate::contract::document::Document; use crate::contract::Contract; use crate::drive::block_info::BlockInfo; use crate::drive::flags::StorageFlags; +use crate::drive::grove_operations::BatchDeleteApplyType; +use crate::drive::identity::withdrawals::paths::{ + get_withdrawal_root_path, get_withdrawal_transactions_expired_ids_path, + get_withdrawal_transactions_expired_ids_path_as_u8, get_withdrawal_transactions_queue_path, + WithdrawalTransaction, WITHDRAWAL_TRANSACTIONS_COUNTER_ID, +}; use crate::drive::object_size_info::DocumentAndContractInfo; use crate::drive::object_size_info::DocumentInfo::DocumentRefAndSerialization; use crate::drive::Drive; @@ -40,7 +46,7 @@ use crate::fee::op::DriveOperation; use crate::fee::result::FeeResult; use dpp::data_contract::extra::DriveContractExt; use grovedb::batch::KeyInfoPath; -use grovedb::{EstimatedLayerInformation, TransactionArg}; +use grovedb::{Element, EstimatedLayerInformation, TransactionArg}; use std::collections::HashMap; /// A converter that will get Drive Operations from High Level Operations @@ -457,6 +463,112 @@ impl DriveOperationConverter for DocumentOperationType<'_> { // } // } +/// Operations for Withdrawals +pub enum WithdrawalOperationType<'a> { + /// Inserts expired index into it's tree + InsertExpiredIndex { + /// index value + index: u64, + }, + /// Removes expired index from the tree + DeleteExpiredIndex { + /// index value + key: &'a [u8], + }, + /// Update index counter + UpdateIndexCounter { + /// index counter value + index: u64, + }, + /// Insert Core Transaction into queue + InsertTransactions { + /// transaction id bytes + transactions: Vec, + }, +} + +impl DriveOperationConverter for WithdrawalOperationType<'_> { + fn to_drive_operations( + self, + drive: &Drive, + _estimated_costs_only_with_layer_info: &mut Option< + HashMap, + >, + _block_info: &BlockInfo, + transaction: TransactionArg, + ) -> Result, Error> { + match self { + WithdrawalOperationType::InsertExpiredIndex { index } => { + let mut drive_operations = vec![]; + + let index_bytes = index.to_be_bytes(); + + let path = get_withdrawal_transactions_expired_ids_path(); + + drive.batch_insert( + crate::drive::object_size_info::PathKeyElementInfo::PathKeyElement::<'_, 1>(( + path, + &index_bytes, + Element::Item(vec![], None), + )), + &mut drive_operations, + )?; + + Ok(drive_operations) + } + WithdrawalOperationType::DeleteExpiredIndex { key } => { + let mut drive_operations = vec![]; + + let path: [&[u8]; 2] = get_withdrawal_transactions_expired_ids_path_as_u8(); + + drive.batch_delete( + path, + key, + BatchDeleteApplyType::StatefulBatchDelete { + is_known_to_be_subtree_with_sum: Some((false, false)), + }, + transaction, + &mut drive_operations, + )?; + + Ok(drive_operations) + } + WithdrawalOperationType::UpdateIndexCounter { index } => { + let mut drive_operations = vec![]; + + let path = get_withdrawal_root_path(); + + drive.batch_insert( + crate::drive::object_size_info::PathKeyElementInfo::PathKeyElement::<'_, 1>(( + path, + &WITHDRAWAL_TRANSACTIONS_COUNTER_ID, + Element::Item(index.to_be_bytes().to_vec(), None), + )), + &mut drive_operations, + )?; + + Ok(drive_operations) + } + WithdrawalOperationType::InsertTransactions { transactions } => { + let mut drive_operations = vec![]; + + let path = get_withdrawal_transactions_queue_path(); + + for (id, bytes) in transactions { + drive.batch_insert( + crate::drive::object_size_info::PathKeyElementInfo::PathKeyElement::<'_, 1>( + (path.clone(), &id, Element::Item(bytes, None)), + ), + &mut drive_operations, + )?; + } + + Ok(drive_operations) + } + } + } +} + /// All types of Drive Operations pub enum DriveOperationType<'a> { /// A contract operation @@ -465,6 +577,8 @@ pub enum DriveOperationType<'a> { DocumentOperation(DocumentOperationType<'a>), // /// An identity operation // IdentityOperation(IdentityOperationType<'a>), + /// Withdrawal operation + WithdrawalOperation(WithdrawalOperationType<'a>), } impl DriveOperationConverter for DriveOperationType<'_> { @@ -493,6 +607,14 @@ impl DriveOperationConverter for DriveOperationType<'_> { block_info, transaction, ) + } + DriveOperationType::WithdrawalOperation(withdrawal_operation_type) => { + withdrawal_operation_type.to_drive_operations( + drive, + estimated_costs_only_with_layer_info, + block_info, + transaction, + ) } // DriveOperationType::IdentityOperation(identity_operation_type) => { // identity_operation_type.to_grove_db_operations( // drive, diff --git a/packages/rs-drive/src/drive/identity/withdrawals/paths.rs b/packages/rs-drive/src/drive/identity/withdrawals/paths.rs index fd2a6156ba1..b6a1dcaf426 100644 --- a/packages/rs-drive/src/drive/identity/withdrawals/paths.rs +++ b/packages/rs-drive/src/drive/identity/withdrawals/paths.rs @@ -33,6 +33,16 @@ pub fn add_initial_withdrawal_state_structure_operations(batch: &mut GroveDbOpBa ); } +/// Helper function to get root path +pub fn get_withdrawal_root_path() -> Vec> { + vec![vec![RootTree::WithdrawalTransactions as u8]] +} + +/// Helper function to get root path as u8 +pub fn get_withdrawal_root_path_as_u8() -> [&'static [u8]; 1] { + [Into::<&[u8; 1]>::into(RootTree::WithdrawalTransactions)] +} + /// Helper function to get queue path as Vec pub fn get_withdrawal_transactions_queue_path() -> Vec> { vec![ From aa83870d9fd6b1669718644877da456e53e9423c Mon Sep 17 00:00:00 2001 From: Djavid Gabibiyan Date: Tue, 27 Dec 2022 17:44:45 +0500 Subject: [PATCH 047/170] chore: wip --- .../src/identity_credit_withdrawal/mod.rs | 39 +++++++++------ .../rs-drive/src/drive/document/helpers.rs | 50 ++++++++++++------- .../withdrawals/transaction_index_counter.rs | 28 ++++++++++- 3 files changed, 82 insertions(+), 35 deletions(-) diff --git a/packages/rs-drive-abci/src/identity_credit_withdrawal/mod.rs b/packages/rs-drive-abci/src/identity_credit_withdrawal/mod.rs index f0b016fba83..de0356f89e7 100644 --- a/packages/rs-drive-abci/src/identity_credit_withdrawal/mod.rs +++ b/packages/rs-drive-abci/src/identity_credit_withdrawal/mod.rs @@ -12,6 +12,7 @@ use drive::{ batch::GroveDbOpBatch, block_info::BlockInfo, identity::withdrawals::paths::get_withdrawal_transactions_expired_ids_path_as_u8, }, + fee::op::DriveOperation, fee_pools::epochs::Epoch, query::{Element, TransactionArg}, }; @@ -64,6 +65,8 @@ impl Platform { transaction, )?; + let mut drive_operations: Vec = vec![]; + for mut document in broadcasted_documents { let transaction_sign_height = document @@ -97,24 +100,23 @@ impl Platform { let status = if core_transactions.contains(&transaction_id) { withdrawals_contract::statuses::COMPLETE } else { - let bytes = transaction_index.to_be_bytes(); - - let path = get_withdrawal_transactions_expired_ids_path_as_u8(); - - self.drive - .grove - .insert(path, &bytes, Element::Item(vec![], None), None, transaction) - .unwrap() - .map_err(|_| { - Error::Execution(ExecutionError::CorruptedCodeExecution( - "Can't update transaction_index in GroveDB", - )) - })?; + self.drive.add_insert_expired_index_operation( + transaction_index, + BlockInfo { + time_ms: block_execution_context.block_info.block_time_ms, + height: block_execution_context.block_info.block_height, + epoch: Epoch::new( + block_execution_context.epoch_info.current_epoch_index, + ), + }, + &mut drive_operations, + transaction, + )?; withdrawals_contract::statuses::EXPIRED }; - self.drive.update_document_data( + self.drive.add_update_document_data_operations( &contract_fetch_info.contract, &mut document, BlockInfo { @@ -123,6 +125,7 @@ impl Platform { epoch: Epoch::new(block_execution_context.epoch_info.current_epoch_index), }, transaction, + &mut drive_operations, |document: &mut Document| -> Result<&mut Document, drive::error::Error> { document .set("status", JsonValue::Number(Number::from(status))) @@ -140,6 +143,9 @@ impl Platform { } } + self.drive + .apply_drive_operations(drive_operations, true, block_info, transaction)?; + Ok(()) } @@ -231,11 +237,13 @@ impl Platform { .drive .build_withdrawal_transactions_from_documents(&documents, transaction)?; + let mut drive_operations = vec![]; + for document in documents.iter_mut() { let transaction_id = hash::hash(withdrawal_transactions.get(&document.id).unwrap().1.clone()); - self.drive.update_document_data( + self.drive.add_update_document_data_operations( &contract_fetch_info.contract, document, BlockInfo { @@ -244,6 +252,7 @@ impl Platform { epoch: Epoch::new(block_execution_context.epoch_info.current_epoch_index), }, transaction, + &mut drive_operations, |document: &mut Document| -> Result<&mut Document, drive::error::Error> { document .set( diff --git a/packages/rs-drive/src/drive/document/helpers.rs b/packages/rs-drive/src/drive/document/helpers.rs index b1aa5ae3ef8..3e53727202f 100644 --- a/packages/rs-drive/src/drive/document/helpers.rs +++ b/packages/rs-drive/src/drive/document/helpers.rs @@ -1,6 +1,6 @@ use dpp::{ contracts::withdrawals_contract, - data_contract::extra::common, + data_contract::extra::{common, DocumentType, DriveContractExt}, prelude::{DataContract, Document, Identifier}, util::string_encoding::Encoding, }; @@ -8,18 +8,24 @@ use grovedb::TransactionArg; use serde_json::{json, Number, Value as JsonValue}; use crate::{ - drive::{block_info::BlockInfo, Drive}, + drive::{ + block_info::BlockInfo, + object_size_info::{DocumentAndContractInfo, DocumentInfo}, + Drive, + }, error::{drive::DriveError, Error}, + fee::op::DriveOperation, }; impl Drive { /// Helper function to avoid boilerplate of calling an update - pub fn update_document_data( + pub fn add_update_document_data_operations( &self, contract: &DataContract, document: &mut Document, block_info: BlockInfo, transaction: TransactionArg, + drive_operations: &mut Vec, update_fn: F, ) -> Result<(), Error> where @@ -34,25 +40,31 @@ impl Drive { })?); document.increment_revision(); - self.update_document_for_contract_cbor( - &document.to_cbor().map_err(|_| { - Error::Drive(DriveError::CorruptedCodeExecution( - "Can't cbor withdrawal document", - )) - })?, - &contract.to_cbor().map_err(|_| { - Error::Drive(DriveError::CorruptedCodeExecution( - "Can't cbor withdrawal data contract", - )) - })?, - withdrawals_contract::types::WITHDRAWAL, - Some(document.owner_id.to_buffer()), - block_info, + let document_cbor = document.to_cbor().map_err(|_| { + Error::Drive(DriveError::CorruptedCodeExecution( + "Can't cbor withdrawal document", + )) + })?; + + let operations = self.add_document_for_contract_operations( + DocumentAndContractInfo { + document_info: DocumentInfo::DocumentWithoutSerialization(( + crate::drive::document::Document::from_cbor(&document_cbor, None, None)?, + None, + )), + contract: &contract, + document_type: contract + .document_type_for_name(withdrawals_contract::types::WITHDRAWAL)?, + owner_id: Some(document.owner_id.to_buffer()), + }, true, - None, + &block_info, + &mut None, transaction, )?; + drive_operations.extend(operations); + Ok(()) } @@ -114,7 +126,7 @@ impl Drive { .collect::, Error>>()?; for mut document in documents { - self.update_document_data( + self.add_update_document_data_operations( &contract_fetch_info.contract, &mut document, block_info.clone(), diff --git a/packages/rs-drive/src/drive/identity/withdrawals/transaction_index_counter.rs b/packages/rs-drive/src/drive/identity/withdrawals/transaction_index_counter.rs index 586c0b21559..16bd8220b39 100644 --- a/packages/rs-drive/src/drive/identity/withdrawals/transaction_index_counter.rs +++ b/packages/rs-drive/src/drive/identity/withdrawals/transaction_index_counter.rs @@ -4,8 +4,16 @@ use grovedb::{ }; use crate::{ - drive::{batch::GroveDbOpBatch, Drive, RootTree}, + drive::{ + batch::{ + drive_op_batch::{DriveOperationConverter, WithdrawalOperationType}, + GroveDbOpBatch, + }, + block_info::BlockInfo, + Drive, RootTree, + }, error::{drive::DriveError, Error}, + fee::op::DriveOperation, }; use super::paths::{ @@ -102,6 +110,24 @@ impl Drive { Element::Item(value, None), ); } + + /// Add insert expired counter operations + pub fn add_insert_expired_index_operation( + &self, + transaction_index: u64, + block_info: BlockInfo, + drive_operations: &mut Vec, + transaction: TransactionArg, + ) -> Result<(), Error> { + let operations = WithdrawalOperationType::InsertExpiredIndex { + index: transaction_index, + } + .to_drive_operations(self, &mut None, &block_info, transaction)?; + + drive_operations.extend(operations); + + Ok(()) + } } #[cfg(test)] From f6fe64baa2c8f921c6fcaa4dcf54a7901305aaf3 Mon Sep 17 00:00:00 2001 From: Djavid Gabibyan Date: Tue, 27 Dec 2022 19:38:50 +0500 Subject: [PATCH 048/170] chore: wip --- packages/rs-drive-abci/src/abci/handlers.rs | 18 +++- .../src/identity_credit_withdrawal/mod.rs | 97 +++++++++++++------ .../src/drive/batch/drive_op_batch.rs | 4 +- .../rs-drive/src/drive/document/helpers.rs | 35 +++++-- .../src/drive/identity/withdrawals/queue.rs | 65 ++++++++++--- packages/rs-drive/src/drive/mod.rs | 2 +- 6 files changed, 158 insertions(+), 63 deletions(-) diff --git a/packages/rs-drive-abci/src/abci/handlers.rs b/packages/rs-drive-abci/src/abci/handlers.rs index e69e7cd4cb3..e0c12ec9087 100644 --- a/packages/rs-drive-abci/src/abci/handlers.rs +++ b/packages/rs-drive-abci/src/abci/handlers.rs @@ -240,15 +240,27 @@ mod tests { .map(|index: u64| (index.to_be_bytes().to_vec(), vec![index as u8; 32])) .collect(); - let mut batch = GroveDbOpBatch::new(); + let mut batch = vec![]; + let mut result_operations = vec![]; platform .drive - .add_enqueue_withdrawal_transaction_operations(&mut batch, withdrawals); + .add_enqueue_withdrawal_transaction_operations( + &withdrawals, + &block_info, + &mut batch, + Some(&transaction), + ) + .expect("to add enqueue operations"); platform .drive - .grove_apply_batch(batch, true, Some(&transaction)) + .apply_batch_drive_operations( + None, + Some(&transaction), + batch, + &mut result_operations, + ) .expect("to apply batch"); // setup the contract diff --git a/packages/rs-drive-abci/src/identity_credit_withdrawal/mod.rs b/packages/rs-drive-abci/src/identity_credit_withdrawal/mod.rs index de0356f89e7..319d4e6ed92 100644 --- a/packages/rs-drive-abci/src/identity_credit_withdrawal/mod.rs +++ b/packages/rs-drive-abci/src/identity_credit_withdrawal/mod.rs @@ -65,6 +65,12 @@ impl Platform { transaction, )?; + let block_info = BlockInfo { + time_ms: block_execution_context.block_info.block_time_ms, + height: block_execution_context.block_info.block_height, + epoch: Epoch::new(block_execution_context.epoch_info.current_epoch_index), + }; + let mut drive_operations: Vec = vec![]; for mut document in broadcasted_documents { @@ -102,13 +108,7 @@ impl Platform { } else { self.drive.add_insert_expired_index_operation( transaction_index, - BlockInfo { - time_ms: block_execution_context.block_info.block_time_ms, - height: block_execution_context.block_info.block_height, - epoch: Epoch::new( - block_execution_context.epoch_info.current_epoch_index, - ), - }, + &block_info, &mut drive_operations, transaction, )?; @@ -119,11 +119,7 @@ impl Platform { self.drive.add_update_document_data_operations( &contract_fetch_info.contract, &mut document, - BlockInfo { - time_ms: block_execution_context.block_info.block_time_ms, - height: block_execution_context.block_info.block_height, - epoch: Epoch::new(block_execution_context.epoch_info.current_epoch_index), - }, + &block_info, transaction, &mut drive_operations, |document: &mut Document| -> Result<&mut Document, drive::error::Error> { @@ -143,8 +139,16 @@ impl Platform { } } - self.drive - .apply_drive_operations(drive_operations, true, block_info, transaction)?; + if !drive_operations.is_empty() { + let mut result_operations = vec![]; + + self.drive.apply_batch_drive_operations( + None, + transaction, + drive_operations, + &mut result_operations, + )?; + } Ok(()) } @@ -156,6 +160,14 @@ impl Platform { validator_set_quorum_hash: [u8; 32], transaction: TransactionArg, ) -> Result>, Error> { + let block_info = BlockInfo { + time_ms: block_execution_context.block_info.block_time_ms, + height: block_execution_context.block_info.block_height, + epoch: Epoch::new(block_execution_context.epoch_info.current_epoch_index), + }; + + let mut drive_operations = vec![]; + // Get 16 latest withdrawal transactions from the queue let withdrawal_transactions = self .drive @@ -163,7 +175,7 @@ impl Platform { // Appending request_height and quorum_hash to withdrwal transaction // and pass it to JS Drive for singing and broadcasting - withdrawal_transactions + let result = withdrawal_transactions .into_iter() .map(|(_, bytes)| { let request_info = AssetUnlockRequestInfo { @@ -188,17 +200,27 @@ impl Platform { self.drive.update_document_transaction_id( &original_transaction_id, &update_transaction_id, - BlockInfo { - time_ms: block_execution_context.block_info.block_time_ms, - height: block_execution_context.block_info.block_height, - epoch: Epoch::new(block_execution_context.epoch_info.current_epoch_index), - }, + &block_info, + &mut drive_operations, transaction, )?; Ok(bytes_buffer) }) - .collect::>, Error>>() + .collect::>, Error>>(); + + if !drive_operations.is_empty() { + let mut result_operations = vec![]; + + self.drive.apply_batch_drive_operations( + None, + transaction, + &mut drive_operations, + &mut result_operations, + )?; + } + + Ok(result) } /// Pool withdrawal documents into transactions @@ -237,6 +259,12 @@ impl Platform { .drive .build_withdrawal_transactions_from_documents(&documents, transaction)?; + let block_info = BlockInfo { + time_ms: block_execution_context.block_info.block_time_ms, + height: block_execution_context.block_info.block_height, + epoch: Epoch::new(block_execution_context.epoch_info.current_epoch_index), + }; + let mut drive_operations = vec![]; for document in documents.iter_mut() { @@ -246,11 +274,7 @@ impl Platform { self.drive.add_update_document_data_operations( &contract_fetch_info.contract, document, - BlockInfo { - time_ms: block_execution_context.block_info.block_time_ms, - height: block_execution_context.block_info.block_height, - epoch: Epoch::new(block_execution_context.epoch_info.current_epoch_index), - }, + &block_info, transaction, &mut drive_operations, |document: &mut Document| -> Result<&mut Document, drive::error::Error> { @@ -291,19 +315,28 @@ impl Platform { )?; } - let mut batch = GroveDbOpBatch::new(); - let withdrawal_transactions = withdrawal_transactions .values() .into_iter() .cloned() .collect(); - self.drive - .add_enqueue_withdrawal_transaction_operations(&mut batch, withdrawal_transactions); + self.drive.add_enqueue_withdrawal_transaction_operations( + &withdrawal_transactions, + &block_info, + &mut drive_operations, + transaction, + )?; - if !batch.is_empty() { - self.drive.grove_apply_batch(batch, true, transaction)?; + if !drive_operations.is_empty() { + let mut result_operations = vec![]; + + self.drive.apply_batch_drive_operations( + None, + transaction, + drive_operations, + &mut result_operations, + )?; } Ok(()) diff --git a/packages/rs-drive/src/drive/batch/drive_op_batch.rs b/packages/rs-drive/src/drive/batch/drive_op_batch.rs index 119fd7b8261..880bbbd07f4 100644 --- a/packages/rs-drive/src/drive/batch/drive_op_batch.rs +++ b/packages/rs-drive/src/drive/batch/drive_op_batch.rs @@ -483,7 +483,7 @@ pub enum WithdrawalOperationType<'a> { /// Insert Core Transaction into queue InsertTransactions { /// transaction id bytes - transactions: Vec, + transactions: &'a [WithdrawalTransaction], }, } @@ -557,7 +557,7 @@ impl DriveOperationConverter for WithdrawalOperationType<'_> { for (id, bytes) in transactions { drive.batch_insert( crate::drive::object_size_info::PathKeyElementInfo::PathKeyElement::<'_, 1>( - (path.clone(), &id, Element::Item(bytes, None)), + (path.clone(), &id, Element::Item(bytes.clone(), None)), ), &mut drive_operations, )?; diff --git a/packages/rs-drive/src/drive/document/helpers.rs b/packages/rs-drive/src/drive/document/helpers.rs index 3e53727202f..7898a199b80 100644 --- a/packages/rs-drive/src/drive/document/helpers.rs +++ b/packages/rs-drive/src/drive/document/helpers.rs @@ -23,7 +23,7 @@ impl Drive { &self, contract: &DataContract, document: &mut Document, - block_info: BlockInfo, + block_info: &BlockInfo, transaction: TransactionArg, drive_operations: &mut Vec, update_fn: F, @@ -58,7 +58,7 @@ impl Drive { owner_id: Some(document.owner_id.to_buffer()), }, true, - &block_info, + block_info, &mut None, transaction, )?; @@ -74,7 +74,8 @@ impl Drive { &self, original_transaction_id: &[u8], update_transaction_id: &[u8], - block_info: BlockInfo, + block_info: &BlockInfo, + drive_operations: &mut Vec, transaction: TransactionArg, ) -> Result<(), Error> { let data_contract_id = Identifier::from_string( @@ -129,8 +130,9 @@ impl Drive { self.add_update_document_data_operations( &contract_fetch_info.contract, &mut document, - block_info.clone(), + block_info, transaction, + drive_operations, |document: &mut Document| -> Result<&mut Document, Error> { document .set( @@ -212,19 +214,34 @@ mod tests { setup_document(&drive, &document, &data_contract, Some(&transaction)); + let block_info = BlockInfo { + time_ms: 1, + height: 1, + epoch: Epoch::new(1), + }; + + let mut drive_operations = vec![]; + let mut result_operations = vec![]; + drive .update_document_transaction_id( &original_transaction_id, &updated_transaction_id, - BlockInfo { - time_ms: 1, - height: 1, - epoch: Epoch::new(1), - }, + &block_info, + &mut drive_operations, Some(&transaction), ) .expect("to update transactionId"); + drive + .apply_batch_drive_operations( + None, + Some(&transaction), + drive_operations, + &mut result_operations, + ) + .expect("to apply batch drive operations"); + let updated_documents = drive .fetch_withdrawal_documents_by_status( withdrawals_contract::statuses::POOLED, diff --git a/packages/rs-drive/src/drive/identity/withdrawals/queue.rs b/packages/rs-drive/src/drive/identity/withdrawals/queue.rs index 2847dc9bc24..b2a8ab5752b 100644 --- a/packages/rs-drive/src/drive/identity/withdrawals/queue.rs +++ b/packages/rs-drive/src/drive/identity/withdrawals/queue.rs @@ -6,7 +6,15 @@ use grovedb::{ }; use crate::{ - drive::{batch::GroveDbOpBatch, grove_operations::BatchDeleteApplyType, Drive}, + drive::{ + batch::{ + drive_op_batch::{DriveOperationConverter, WithdrawalOperationType}, + GroveDbOpBatch, + }, + block_info::BlockInfo, + grove_operations::BatchDeleteApplyType, + Drive, + }, error::{drive::DriveError, Error}, fee::op::DriveOperation, }; @@ -20,16 +28,26 @@ impl Drive { /// Add insert operations for withdrawal transactions to the batch pub fn add_enqueue_withdrawal_transaction_operations( &self, - batch: &mut GroveDbOpBatch, - withdrawals: Vec, - ) { - for (id, bytes) in withdrawals { - batch.add_insert( - get_withdrawal_transactions_queue_path(), - id, - Element::Item(bytes, None), - ); - } + withdrawals: &Vec, + block_info: &BlockInfo, + drive_operations: &mut Vec, + transaction: TransactionArg, + ) -> Result<(), Error> { + drive_operations.extend( + WithdrawalOperationType::InsertTransactions { + transactions: withdrawals, + } + .to_drive_operations(self, &mut None, block_info, transaction)?, + ); + + Ok(()) + // for (id, bytes) in withdrawals { + // batch.add_insert( + // get_withdrawal_transactions_queue_path(), + // id, + // Element::Item(bytes, None), + // ); + // } } /// Get specified amount of withdrawal transactions from the DB @@ -108,7 +126,9 @@ impl Drive { mod tests { use crate::{ common::helpers::setup::setup_drive_with_initial_state_structure, - drive::batch::GroveDbOpBatch, + drive::{batch::GroveDbOpBatch, block_info::BlockInfo}, + fee::op::DriveOperation, + fee_pools::epochs::Epoch, }; #[test] @@ -121,13 +141,26 @@ mod tests { .map(|i: u8| (i.to_be_bytes().to_vec(), vec![i; 32])) .collect(); - let mut batch = GroveDbOpBatch::new(); + let block_info = BlockInfo { + time_ms: 1, + height: 1, + epoch: Epoch::new(1), + }; - drive.add_enqueue_withdrawal_transaction_operations(&mut batch, withdrawals); + let mut batch: Vec = vec![]; drive - .grove_apply_batch(batch, true, Some(&transaction)) - .expect("to apply ops"); + .add_enqueue_withdrawal_transaction_operations( + &withdrawals, + &block_info, + &mut batch, + Some(&transaction), + ) + .expect("to add operations"); + + // drive + // .apply_drive_operations(batch, true, &block_info, Some(&transaction)) + // .expect("to apply batch"); let withdrawals = drive .dequeue_withdrawal_transactions(16, Some(&transaction)) diff --git a/packages/rs-drive/src/drive/mod.rs b/packages/rs-drive/src/drive/mod.rs index 386c260d84a..aa931ef79d9 100644 --- a/packages/rs-drive/src/drive/mod.rs +++ b/packages/rs-drive/src/drive/mod.rs @@ -207,7 +207,7 @@ impl Drive { } /// Applies a batch of Drive operations to groveDB. - fn apply_batch_drive_operations( + pub fn apply_batch_drive_operations( &self, estimated_costs_only_with_layer_info: Option< HashMap, From 7a5b8c19c2e615be4c76a45970590b1cb2867a02 Mon Sep 17 00:00:00 2001 From: Djavid Gabibiyan Date: Tue, 27 Dec 2022 20:27:11 +0500 Subject: [PATCH 049/170] chore: wip --- packages/rs-drive-abci/src/abci/handlers.rs | 9 ++- .../src/identity_credit_withdrawal/mod.rs | 13 ++-- packages/rs-drive-nodejs/src/lib.rs | 44 +++++++++---- .../src/drive/batch/drive_op_batch.rs | 2 +- .../rs-drive/src/drive/document/helpers.rs | 4 +- .../src/drive/identity/withdrawals/queue.rs | 16 +---- .../withdrawals/transaction_index_counter.rs | 62 +++++++++++++------ 7 files changed, 92 insertions(+), 58 deletions(-) diff --git a/packages/rs-drive-abci/src/abci/handlers.rs b/packages/rs-drive-abci/src/abci/handlers.rs index e0c12ec9087..408ddef5da5 100644 --- a/packages/rs-drive-abci/src/abci/handlers.rs +++ b/packages/rs-drive-abci/src/abci/handlers.rs @@ -201,8 +201,9 @@ mod tests { use dashcore::BlockHash; use dpp::tests::fixtures::get_withdrawals_data_contract_fixture; use drive::common::helpers::identities::create_test_masternode_identities; - use drive::drive::batch::GroveDbOpBatch; + use drive::drive::block_info::BlockInfo; use drive::fee::epoch::CreditsPerEpoch; + use drive::fee_pools::epochs::Epoch; use drive::rpc::core::MockCoreRPCLike; use rust_decimal::prelude::ToPrimitive; use serde_json::json; @@ -240,6 +241,12 @@ mod tests { .map(|index: u64| (index.to_be_bytes().to_vec(), vec![index as u8; 32])) .collect(); + let block_info = BlockInfo { + time_ms: 1, + height: 1, + epoch: Epoch::new(1), + }; + let mut batch = vec![]; let mut result_operations = vec![]; diff --git a/packages/rs-drive-abci/src/identity_credit_withdrawal/mod.rs b/packages/rs-drive-abci/src/identity_credit_withdrawal/mod.rs index 319d4e6ed92..0d8d95ec11a 100644 --- a/packages/rs-drive-abci/src/identity_credit_withdrawal/mod.rs +++ b/packages/rs-drive-abci/src/identity_credit_withdrawal/mod.rs @@ -8,13 +8,8 @@ use dpp::{ util::{hash, json_value::JsonValueExt, string_encoding::Encoding}, }; use drive::{ - drive::{ - batch::GroveDbOpBatch, block_info::BlockInfo, - identity::withdrawals::paths::get_withdrawal_transactions_expired_ids_path_as_u8, - }, - fee::op::DriveOperation, - fee_pools::epochs::Epoch, - query::{Element, TransactionArg}, + drive::block_info::BlockInfo, fee::op::DriveOperation, fee_pools::epochs::Epoch, + query::TransactionArg, }; use serde_json::{Number, Value as JsonValue}; @@ -207,7 +202,7 @@ impl Platform { Ok(bytes_buffer) }) - .collect::>, Error>>(); + .collect::>, Error>>()?; if !drive_operations.is_empty() { let mut result_operations = vec![]; @@ -215,7 +210,7 @@ impl Platform { self.drive.apply_batch_drive_operations( None, transaction, - &mut drive_operations, + drive_operations, &mut result_operations, )?; } diff --git a/packages/rs-drive-nodejs/src/lib.rs b/packages/rs-drive-nodejs/src/lib.rs index b203565c3de..e1e9884de77 100644 --- a/packages/rs-drive-nodejs/src/lib.rs +++ b/packages/rs-drive-nodejs/src/lib.rs @@ -2268,26 +2268,48 @@ impl PlatformWrapper { Ok(None) }; - let mut batch = GroveDbOpBatch::new(); + let block_info = drive::drive::block_info::BlockInfo { + time_ms: 1, + height: 1, + epoch: Epoch::new(1), + }; + + let mut batch = vec![]; let index_bytes = (index as u64).to_be_bytes().to_vec(); - let withdrawals = vec![(index_bytes.clone(), transaction_bytes)]; + let withdrawals = vec![(index_bytes, transaction_bytes)]; - platform - .drive - .add_enqueue_withdrawal_transaction_operations(&mut batch, withdrawals); + let execution_function = |transaction: TransactionArg| -> Result<(), String> { + platform + .drive + .add_enqueue_withdrawal_transaction_operations( + &withdrawals, + &block_info, + &mut batch, + transaction, + ) + .map_err(|err| err.to_string())?; - platform - .drive - .add_update_withdrawal_index_counter_operation(&mut batch, index_bytes); + platform + .drive + .add_update_withdrawal_index_counter_operation( + index as u64, + &block_info, + &mut batch, + transaction, + ) + .map_err(|err| err.to_string())?; + + let mut result_operations = vec![]; - let result = transaction_result.and_then(|transaction_arg| { platform .drive - .grove_apply_batch(batch, false, transaction_arg) + .apply_batch_drive_operations(None, transaction, batch, &mut result_operations) .map_err(|err| err.to_string()) - }); + }; + + let result = transaction_result.and_then(execution_function); channel.send(move |mut task_context| { let callback = js_callback.into_inner(&mut task_context); diff --git a/packages/rs-drive/src/drive/batch/drive_op_batch.rs b/packages/rs-drive/src/drive/batch/drive_op_batch.rs index 880bbbd07f4..8a15152b6b3 100644 --- a/packages/rs-drive/src/drive/batch/drive_op_batch.rs +++ b/packages/rs-drive/src/drive/batch/drive_op_batch.rs @@ -557,7 +557,7 @@ impl DriveOperationConverter for WithdrawalOperationType<'_> { for (id, bytes) in transactions { drive.batch_insert( crate::drive::object_size_info::PathKeyElementInfo::PathKeyElement::<'_, 1>( - (path.clone(), &id, Element::Item(bytes.clone(), None)), + (path.clone(), id, Element::Item(bytes.clone(), None)), ), &mut drive_operations, )?; diff --git a/packages/rs-drive/src/drive/document/helpers.rs b/packages/rs-drive/src/drive/document/helpers.rs index 7898a199b80..1d44189d6e0 100644 --- a/packages/rs-drive/src/drive/document/helpers.rs +++ b/packages/rs-drive/src/drive/document/helpers.rs @@ -1,6 +1,6 @@ use dpp::{ contracts::withdrawals_contract, - data_contract::extra::{common, DocumentType, DriveContractExt}, + data_contract::extra::{common, DriveContractExt}, prelude::{DataContract, Document, Identifier}, util::string_encoding::Encoding, }; @@ -52,7 +52,7 @@ impl Drive { crate::drive::document::Document::from_cbor(&document_cbor, None, None)?, None, )), - contract: &contract, + contract, document_type: contract .document_type_for_name(withdrawals_contract::types::WITHDRAWAL)?, owner_id: Some(document.owner_id.to_buffer()), diff --git a/packages/rs-drive/src/drive/identity/withdrawals/queue.rs b/packages/rs-drive/src/drive/identity/withdrawals/queue.rs index b2a8ab5752b..e3cc6fc9975 100644 --- a/packages/rs-drive/src/drive/identity/withdrawals/queue.rs +++ b/packages/rs-drive/src/drive/identity/withdrawals/queue.rs @@ -7,10 +7,7 @@ use grovedb::{ use crate::{ drive::{ - batch::{ - drive_op_batch::{DriveOperationConverter, WithdrawalOperationType}, - GroveDbOpBatch, - }, + batch::drive_op_batch::{DriveOperationConverter, WithdrawalOperationType}, block_info::BlockInfo, grove_operations::BatchDeleteApplyType, Drive, @@ -41,13 +38,6 @@ impl Drive { ); Ok(()) - // for (id, bytes) in withdrawals { - // batch.add_insert( - // get_withdrawal_transactions_queue_path(), - // id, - // Element::Item(bytes, None), - // ); - // } } /// Get specified amount of withdrawal transactions from the DB @@ -126,9 +116,7 @@ impl Drive { mod tests { use crate::{ common::helpers::setup::setup_drive_with_initial_state_structure, - drive::{batch::GroveDbOpBatch, block_info::BlockInfo}, - fee::op::DriveOperation, - fee_pools::epochs::Epoch, + drive::block_info::BlockInfo, fee::op::DriveOperation, fee_pools::epochs::Epoch, }; #[test] diff --git a/packages/rs-drive/src/drive/identity/withdrawals/transaction_index_counter.rs b/packages/rs-drive/src/drive/identity/withdrawals/transaction_index_counter.rs index 16bd8220b39..49a12985af5 100644 --- a/packages/rs-drive/src/drive/identity/withdrawals/transaction_index_counter.rs +++ b/packages/rs-drive/src/drive/identity/withdrawals/transaction_index_counter.rs @@ -5,10 +5,7 @@ use grovedb::{ use crate::{ drive::{ - batch::{ - drive_op_batch::{DriveOperationConverter, WithdrawalOperationType}, - GroveDbOpBatch, - }, + batch::drive_op_batch::{DriveOperationConverter, WithdrawalOperationType}, block_info::BlockInfo, Drive, RootTree, }, @@ -101,28 +98,41 @@ impl Drive { /// Add counter update operations to the batch pub fn add_update_withdrawal_index_counter_operation( &self, - batch: &mut GroveDbOpBatch, - value: Vec, - ) { - batch.add_insert( - vec![vec![RootTree::WithdrawalTransactions as u8]], - WITHDRAWAL_TRANSACTIONS_COUNTER_ID.to_vec(), - Element::Item(value, None), + value: u64, + block_info: &BlockInfo, + drive_operations: &mut Vec, + transaction: TransactionArg, + ) -> Result<(), Error> { + drive_operations.extend( + WithdrawalOperationType::UpdateIndexCounter { index: value }.to_drive_operations( + self, + &mut None, + block_info, + transaction, + )?, ); + + Ok(()) + + // batch.add_insert( + // vec![vec![RootTree::WithdrawalTransactions as u8]], + // WITHDRAWAL_TRANSACTIONS_COUNTER_ID.to_vec(), + // Element::Item(value, None), + // ); } /// Add insert expired counter operations pub fn add_insert_expired_index_operation( &self, transaction_index: u64, - block_info: BlockInfo, + block_info: &BlockInfo, drive_operations: &mut Vec, transaction: TransactionArg, ) -> Result<(), Error> { let operations = WithdrawalOperationType::InsertExpiredIndex { index: transaction_index, } - .to_drive_operations(self, &mut None, &block_info, transaction)?; + .to_drive_operations(self, &mut None, block_info, transaction)?; drive_operations.extend(operations); @@ -137,9 +147,10 @@ mod tests { use crate::{ common::helpers::setup::setup_drive_with_initial_state_structure, drive::{ - batch::GroveDbOpBatch, + block_info::BlockInfo, identity::withdrawals::paths::get_withdrawal_transactions_expired_ids_path_as_u8, }, + fee_pools::epochs::Epoch, }; #[test] @@ -148,17 +159,28 @@ mod tests { let transaction = drive.grove.start_transaction(); - let mut batch = GroveDbOpBatch::new(); + let block_info = BlockInfo { + time_ms: 1, + height: 1, + epoch: Epoch::new(1), + }; + + let mut batch = vec![]; + let mut result_operations = vec![]; let counter: u64 = 42; - drive.add_update_withdrawal_index_counter_operation( - &mut batch, - counter.to_be_bytes().to_vec(), - ); + drive + .add_update_withdrawal_index_counter_operation( + counter, + &block_info, + &mut batch, + Some(&transaction), + ) + .expect("to add update operations"); drive - .grove_apply_batch(batch, false, Some(&transaction)) + .apply_batch_drive_operations(None, Some(&transaction), batch, &mut result_operations) .expect("to apply ops"); let stored_counter = drive From b5743fac50d1a369bc8f464029b4e54b293654fd Mon Sep 17 00:00:00 2001 From: Djavid Gabibyan Date: Wed, 28 Dec 2022 21:56:43 +0500 Subject: [PATCH 050/170] chore: wip --- .../identity/validation/public_keys_validator_spec.rs | 2 +- packages/rs-drive-abci/src/common/helpers/setup.rs | 10 +++++++--- packages/rs-drive-abci/src/config.rs | 2 +- packages/rs-drive-abci/src/platform.rs | 9 ++++++++- packages/rs-drive-nodejs/scripts/build.sh | 5 ++++- packages/rs-drive-nodejs/src/lib.rs | 8 ++++---- packages/rs-drive-nodejs/test/Drive.spec.js | 2 +- packages/rs-drive-nodejs/test/GroveDB.spec.js | 11 +++++++++-- packages/rs-drive/src/drive/document/helpers.rs | 7 +++++-- .../rs-drive/src/drive/identity/withdrawals/queue.rs | 7 ++++--- 10 files changed, 44 insertions(+), 19 deletions(-) diff --git a/packages/rs-dpp/src/tests/identity/validation/public_keys_validator_spec.rs b/packages/rs-dpp/src/tests/identity/validation/public_keys_validator_spec.rs index 3f1a9c8aea1..0ca453a1028 100644 --- a/packages/rs-dpp/src/tests/identity/validation/public_keys_validator_spec.rs +++ b/packages/rs-dpp/src/tests/identity/validation/public_keys_validator_spec.rs @@ -414,7 +414,7 @@ pub fn should_return_invalid_result_if_key_data_is_not_a_valid_der() { ); assert_eq!( error.validation_error().as_ref().unwrap().message(), - "Key secp256k1 error: malformed public key" + "Key secp256k1 error: secp: malformed public key" ); } diff --git a/packages/rs-drive-abci/src/common/helpers/setup.rs b/packages/rs-drive-abci/src/common/helpers/setup.rs index f2493370772..b88455b0979 100644 --- a/packages/rs-drive-abci/src/common/helpers/setup.rs +++ b/packages/rs-drive-abci/src/common/helpers/setup.rs @@ -46,20 +46,24 @@ use tempfile::TempDir; /// A function which sets up Platform. pub fn setup_platform() -> Platform { let tmp_dir = TempDir::new().unwrap(); - let drive: Platform = Platform::open(tmp_dir, PlatformConfig::default()) + let mut platform: Platform = Platform::open(tmp_dir, PlatformConfig::default()) .expect("should open Platform successfully"); - drive + platform.mock_core_rpc_client(); + + platform } /// A function which sets up Platform with its initial state structure. pub fn setup_platform_with_initial_state_structure() -> Platform { - let platform = setup_platform(); + let mut platform = setup_platform(); platform .drive .create_initial_state_structure(None) .expect("should create root tree successfully"); + platform.mock_core_rpc_client(); + platform } diff --git a/packages/rs-drive-abci/src/config.rs b/packages/rs-drive-abci/src/config.rs index a39cc7b4b05..1e6d51dd4a1 100644 --- a/packages/rs-drive-abci/src/config.rs +++ b/packages/rs-drive-abci/src/config.rs @@ -26,7 +26,7 @@ impl Default for PlatformConfig { Self { drive: None, core: CoreConfig { - rpc_url: "".to_owned(), + rpc_url: "127.0.0.1".to_owned(), rpc_username: "".to_owned(), rpc_password: "".to_owned(), }, diff --git a/packages/rs-drive-abci/src/platform.rs b/packages/rs-drive-abci/src/platform.rs index ea044396aa2..e40ce21f5c1 100644 --- a/packages/rs-drive-abci/src/platform.rs +++ b/packages/rs-drive-abci/src/platform.rs @@ -58,6 +58,12 @@ pub struct Platform { pub core_rpc: Box, } +impl std::fmt::Debug for Platform { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.debug_struct("Platform").finish() + } +} + impl Platform { /// Open Platform with Drive and block execution context. pub fn open>(path: P, config: PlatformConfig) -> Result { @@ -69,7 +75,8 @@ impl Platform { config.core.rpc_username, config.core.rpc_password, ) - .map_err(|_| { + .map_err(|e| { + dbg!(e); Error::Execution(ExecutionError::CorruptedCodeExecution( "Could not setup Dash Core RPC client", )) diff --git a/packages/rs-drive-nodejs/scripts/build.sh b/packages/rs-drive-nodejs/scripts/build.sh index dc316035f0e..a770212933e 100755 --- a/packages/rs-drive-nodejs/scripts/build.sh +++ b/packages/rs-drive-nodejs/scripts/build.sh @@ -1,16 +1,19 @@ #!/usr/bin/env bash PROFILE_ARG="" +FEATURE_FLAG="" if [ -n "$CARGO_BUILD_PROFILE" ]; then if [ "$CARGO_BUILD_PROFILE" == "release" ]; then PROFILE_ARG="--release" + elif [ "$CARGO_BUILD_PROFILE" == "test" ]; then + FEATURE_FLAG="--features enable-core-rpc-mocking" elif [ "$CARGO_BUILD_PROFILE" != "debug" ]; then PROFILE_ARG="--profile $CARGO_BUILD_PROFILE" fi fi cargo-cp-artifact -ac drive-nodejs native/index.node -- \ - cargo build --message-format=json-render-diagnostics $PROFILE_ARG \ + cargo build --message-format=json-render-diagnostics $PROFILE_ARG $FEATURE_FLAG \ && neon-tag-prebuild \ && rm -rf native diff --git a/packages/rs-drive-nodejs/src/lib.rs b/packages/rs-drive-nodejs/src/lib.rs index e1e9884de77..d7224333fc2 100644 --- a/packages/rs-drive-nodejs/src/lib.rs +++ b/packages/rs-drive-nodejs/src/lib.rs @@ -67,9 +67,9 @@ impl PlatformWrapper { let drive_config: Handle = platform_config.get(cx, "drive")?; let core_config: Handle = platform_config.get(cx, "core")?; - let js_core_rpc_url: Handle = core_config.get(cx, "rpc_url")?; - let js_core_rpc_username: Handle = core_config.get(cx, "rpc_username")?; - let js_core_rpc_password: Handle = core_config.get(cx, "rpc_password")?; + let js_core_rpc_url: Handle = core_config.get(cx, "rpcUrl")?; + let js_core_rpc_username: Handle = core_config.get(cx, "rpcUsername")?; + let js_core_rpc_password: Handle = core_config.get(cx, "rpcPassword")?; let core_rpc_url = js_core_rpc_url.value(cx); let core_rpc_username = js_core_rpc_username.value(cx); @@ -127,7 +127,7 @@ impl PlatformWrapper { // TODO: think how to pass this error to JS let mut platform: Platform = Platform::open(path, platform_config).unwrap(); - if cfg!(test) { + if cfg!(feature = "enable-core-rpc-mocking") { platform.mock_core_rpc_client(); } diff --git a/packages/rs-drive-nodejs/test/Drive.spec.js b/packages/rs-drive-nodejs/test/Drive.spec.js index e18214b7688..8a04ea7d0ad 100644 --- a/packages/rs-drive-nodejs/test/Drive.spec.js +++ b/packages/rs-drive-nodejs/test/Drive.spec.js @@ -44,7 +44,7 @@ describe('Drive', function main() { dataContractsBlockCacheSize: 500, }, core: { - rpcUrl: '', + rpcUrl: '127.0.0.1', rpcUsername: '', rpcPassword: '', }, diff --git a/packages/rs-drive-nodejs/test/GroveDB.spec.js b/packages/rs-drive-nodejs/test/GroveDB.spec.js index 9e1bcfb2df3..1b285897eaf 100644 --- a/packages/rs-drive-nodejs/test/GroveDB.spec.js +++ b/packages/rs-drive-nodejs/test/GroveDB.spec.js @@ -19,8 +19,15 @@ describe('GroveDB', () => { beforeEach(() => { drive = new Drive(TEST_DATA_PATH, { - dataContractsGlobalCacheSize: 500, - dataContractsBlockCacheSize: 500, + drive: { + dataContractsGlobalCacheSize: 500, + dataContractsBlockCacheSize: 500, + }, + core: { + rpcUrl: '127.0.0.1', + rpcUsername: '', + rpcPassword: '', + }, }); groveDb = drive.getGroveDB(); diff --git a/packages/rs-drive/src/drive/document/helpers.rs b/packages/rs-drive/src/drive/document/helpers.rs index 1d44189d6e0..58c665e1b5c 100644 --- a/packages/rs-drive/src/drive/document/helpers.rs +++ b/packages/rs-drive/src/drive/document/helpers.rs @@ -48,8 +48,9 @@ impl Drive { let operations = self.add_document_for_contract_operations( DocumentAndContractInfo { - document_info: DocumentInfo::DocumentWithoutSerialization(( - crate::drive::document::Document::from_cbor(&document_cbor, None, None)?, + document_info: DocumentInfo::DocumentRefAndSerialization(( + &crate::drive::document::Document::from_cbor(&document_cbor, None, None)?, + &document_cbor, None, )), contract, @@ -233,6 +234,8 @@ mod tests { ) .expect("to update transactionId"); + dbg!(&drive_operations); + drive .apply_batch_drive_operations( None, diff --git a/packages/rs-drive/src/drive/identity/withdrawals/queue.rs b/packages/rs-drive/src/drive/identity/withdrawals/queue.rs index e3cc6fc9975..d9b7de933d6 100644 --- a/packages/rs-drive/src/drive/identity/withdrawals/queue.rs +++ b/packages/rs-drive/src/drive/identity/withdrawals/queue.rs @@ -136,6 +136,7 @@ mod tests { }; let mut batch: Vec = vec![]; + let mut result_operations = vec![]; drive .add_enqueue_withdrawal_transaction_operations( @@ -146,9 +147,9 @@ mod tests { ) .expect("to add operations"); - // drive - // .apply_drive_operations(batch, true, &block_info, Some(&transaction)) - // .expect("to apply batch"); + drive + .apply_batch_drive_operations(None, Some(&transaction), batch, &mut result_operations) + .expect("to apply batch"); let withdrawals = drive .dequeue_withdrawal_transactions(16, Some(&transaction)) From bbf3136840db2222b36fe88bad071af8232463b6 Mon Sep 17 00:00:00 2001 From: Djavid Gabibyan Date: Thu, 29 Dec 2022 10:16:02 +0500 Subject: [PATCH 051/170] chore: tests fixes --- packages/js-drive/lib/createDIContainer.js | 15 +++++++++++-- .../BlockExecutionContextRepository.spec.js | 11 ++++++++-- .../DataContractStoreRepository.spec.js | 11 ++++++++-- .../integration/groveDB/GroveDBStore.spec.js | 22 +++++++++++++++---- .../identity/IdentityStoreRepository.spec.js | 11 ++++++++-- ...blicKeyToIdentitiesStoreRepository.spec.js | 11 ++++++++-- ...entAssetLockTransactionsRepository.spec.js | 11 ++++++++-- .../LastSyncedCoreHeightRepository.spec.js | 11 ++++++++-- 8 files changed, 85 insertions(+), 18 deletions(-) diff --git a/packages/js-drive/lib/createDIContainer.js b/packages/js-drive/lib/createDIContainer.js index 459eebc5b86..15895e438ac 100644 --- a/packages/js-drive/lib/createDIContainer.js +++ b/packages/js-drive/lib/createDIContainer.js @@ -473,9 +473,20 @@ function createDIContainer(options) { groveDBLatestFile, dataContractsGlobalCacheSize, dataContractsBlockCacheSize, + coreJsonRpcHost, + coreJsonRpcPort, + coreJsonRpcUsername, + coreJsonRpcPassword, ) => new RSDrive(groveDBLatestFile, { - dataContractsGlobalCacheSize, - dataContractsBlockCacheSize, + drive: { + dataContractsGlobalCacheSize, + dataContractsBlockCacheSize, + }, + core: { + rpcUrl: `${coreJsonRpcHost}:${coreJsonRpcPort}`, + rpcUsername: coreJsonRpcUsername, + rpcPassword: coreJsonRpcPassword, + }, })) // TODO: With signed state rotation we need to dispose each groveDB store. .disposer(async (rsDrive) => { diff --git a/packages/js-drive/test/integration/blockExecution/BlockExecutionContextRepository.spec.js b/packages/js-drive/test/integration/blockExecution/BlockExecutionContextRepository.spec.js index 6895d6e4359..afbdcca2c89 100644 --- a/packages/js-drive/test/integration/blockExecution/BlockExecutionContextRepository.spec.js +++ b/packages/js-drive/test/integration/blockExecution/BlockExecutionContextRepository.spec.js @@ -26,8 +26,15 @@ describe('BlockExecutionContextRepository', () => { blockExecutionContext.fromObject(plainObject); rsDrive = new Drive('./db/grovedb_test', { - dataContractsGlobalCacheSize: 500, - dataContractsBlockCacheSize: 500, + drive: { + dataContractsGlobalCacheSize: 500, + dataContractsBlockCacheSize: 500, + }, + core: { + rpcUrl: '127.0.0.1', + rpcUsername: '', + rpcPassword: '', + }, }); store = new GroveDBStore(rsDrive, noopLogger); diff --git a/packages/js-drive/test/integration/dataContract/DataContractStoreRepository.spec.js b/packages/js-drive/test/integration/dataContract/DataContractStoreRepository.spec.js index b104584e459..842410e0f04 100644 --- a/packages/js-drive/test/integration/dataContract/DataContractStoreRepository.spec.js +++ b/packages/js-drive/test/integration/dataContract/DataContractStoreRepository.spec.js @@ -20,8 +20,15 @@ describe('DataContractStoreRepository', () => { beforeEach(async () => { rsDrive = new Drive('./db/grovedb_test', { - dataContractsGlobalCacheSize: 500, - dataContractsBlockCacheSize: 500, + drive: { + dataContractsGlobalCacheSize: 500, + dataContractsBlockCacheSize: 500, + }, + core: { + rpcUrl: '127.0.0.1', + rpcUsername: '', + rpcPassword: '', + }, }); store = new GroveDBStore(rsDrive, noopLogger); diff --git a/packages/js-drive/test/integration/groveDB/GroveDBStore.spec.js b/packages/js-drive/test/integration/groveDB/GroveDBStore.spec.js index d37d5bde52d..88f54c48d00 100644 --- a/packages/js-drive/test/integration/groveDB/GroveDBStore.spec.js +++ b/packages/js-drive/test/integration/groveDB/GroveDBStore.spec.js @@ -15,8 +15,15 @@ describe('GroveDBStore', () => { beforeEach(async () => { rsDrive = new Drive('./db/grovedb_test', { - dataContractsGlobalCacheSize: 500, - dataContractsBlockCacheSize: 500, + drive: { + dataContractsGlobalCacheSize: 500, + dataContractsBlockCacheSize: 500, + }, + core: { + rpcUrl: '127.0.0.1', + rpcUsername: '', + rpcPassword: '', + }, }); store = new GroveDBStore(rsDrive, logger); @@ -381,8 +388,15 @@ describe('GroveDBStore', () => { rimraf.sync('./db/grovedb_test'); rsDrive = new Drive('./db/grovedb_test', { - dataContractsGlobalCacheSize: 500, - dataContractsBlockCacheSize: 500, + drive: { + dataContractsGlobalCacheSize: 500, + dataContractsBlockCacheSize: 500, + }, + core: { + rpcUrl: '127.0.0.1', + rpcUsername: '', + rpcPassword: '', + }, }); store = new GroveDBStore(rsDrive, logger); diff --git a/packages/js-drive/test/integration/identity/IdentityStoreRepository.spec.js b/packages/js-drive/test/integration/identity/IdentityStoreRepository.spec.js index 14328e9bbda..9704c0dd741 100644 --- a/packages/js-drive/test/integration/identity/IdentityStoreRepository.spec.js +++ b/packages/js-drive/test/integration/identity/IdentityStoreRepository.spec.js @@ -19,8 +19,15 @@ describe('IdentityStoreRepository', () => { beforeEach(async () => { rsDrive = new Drive('./db/grovedb_test', { - dataContractsGlobalCacheSize: 500, - dataContractsBlockCacheSize: 500, + drive: { + dataContractsGlobalCacheSize: 500, + dataContractsBlockCacheSize: 500, + }, + core: { + rpcUrl: '127.0.0.1', + rpcUsername: '', + rpcPassword: '', + }, }); store = new GroveDBStore(rsDrive, logger); diff --git a/packages/js-drive/test/integration/identity/PublicKeyToIdentitiesStoreRepository.spec.js b/packages/js-drive/test/integration/identity/PublicKeyToIdentitiesStoreRepository.spec.js index ab6bb6608e3..cb3e36539a1 100644 --- a/packages/js-drive/test/integration/identity/PublicKeyToIdentitiesStoreRepository.spec.js +++ b/packages/js-drive/test/integration/identity/PublicKeyToIdentitiesStoreRepository.spec.js @@ -19,8 +19,15 @@ describe('PublicKeyToIdentitiesStoreRepository', () => { beforeEach(async () => { rsDrive = new Drive('./db/grovedb_test', { - dataContractsGlobalCacheSize: 500, - dataContractsBlockCacheSize: 500, + drive: { + dataContractsGlobalCacheSize: 500, + dataContractsBlockCacheSize: 500, + }, + core: { + rpcUrl: '127.0.0.1', + rpcUsername: '', + rpcPassword: '', + }, }); store = new GroveDBStore(rsDrive, logger, { diff --git a/packages/js-drive/test/integration/identity/SpentAssetLockTransactionsRepository.spec.js b/packages/js-drive/test/integration/identity/SpentAssetLockTransactionsRepository.spec.js index b34d899a43c..97a9e78a57e 100644 --- a/packages/js-drive/test/integration/identity/SpentAssetLockTransactionsRepository.spec.js +++ b/packages/js-drive/test/integration/identity/SpentAssetLockTransactionsRepository.spec.js @@ -16,8 +16,15 @@ describe('SpentAssetLockTransactionsRepository', () => { outPointBuffer = Buffer.from([42]); rsDrive = new Drive('./db/grovedb_test', { - dataContractsGlobalCacheSize: 500, - dataContractsBlockCacheSize: 500, + drive: { + dataContractsGlobalCacheSize: 500, + dataContractsBlockCacheSize: 500, + }, + core: { + rpcUrl: '127.0.0.1', + rpcUsername: '', + rpcPassword: '', + }, }); store = new GroveDBStore(rsDrive, logger); diff --git a/packages/js-drive/test/integration/identity/masternode/LastSyncedCoreHeightRepository.spec.js b/packages/js-drive/test/integration/identity/masternode/LastSyncedCoreHeightRepository.spec.js index 9578f29bf5f..7e6039ebbce 100644 --- a/packages/js-drive/test/integration/identity/masternode/LastSyncedCoreHeightRepository.spec.js +++ b/packages/js-drive/test/integration/identity/masternode/LastSyncedCoreHeightRepository.spec.js @@ -13,8 +13,15 @@ describe('LastSyncedSmlHeightRepository', () => { beforeEach(async () => { rsDrive = new Drive('./db/grovedb_test', { - dataContractsGlobalCacheSize: 500, - dataContractsBlockCacheSize: 500, + drive: { + dataContractsGlobalCacheSize: 500, + dataContractsBlockCacheSize: 500, + }, + core: { + rpcUrl: '127.0.0.1', + rpcUsername: '', + rpcPassword: '', + }, }); store = new GroveDBStore(rsDrive, logger); From e1ab8c70e772500300d3a900724f56eb5c898bf0 Mon Sep 17 00:00:00 2001 From: Djavid Gabibyan Date: Thu, 29 Dec 2022 21:56:26 +0500 Subject: [PATCH 052/170] chore: wip --- packages/js-drive/lib/createDIContainer.js | 2 ++ ...ynchronizeMasternodeIdentitiesFactory.spec.js | 16 ++++++++-------- packages/rs-drive/src/drive/document/helpers.rs | 3 +-- 3 files changed, 11 insertions(+), 10 deletions(-) diff --git a/packages/js-drive/lib/createDIContainer.js b/packages/js-drive/lib/createDIContainer.js index 15895e438ac..2cec0160449 100644 --- a/packages/js-drive/lib/createDIContainer.js +++ b/packages/js-drive/lib/createDIContainer.js @@ -134,6 +134,7 @@ const handleUpdatedScriptPayoutFactory = require('./identity/masternode/handleUp const getWithdrawPubKeyTypeFromPayoutScriptFactory = require('./identity/masternode/getWithdrawPubKeyTypeFromPayoutScriptFactory'); const getPublicKeyFromPayoutScript = require('./identity/masternode/getPublicKeyFromPayoutScript'); const updateWithdrawalTransactionIdAndStatusFactory = require('./identity/withdrawals/updateWithdrawalTransactionIdAndStatusFactory'); +const broadcastWithdrawalTransactionsFactory = require('./abci/handlers/proposal/broadcastWithdrawalTransactionsFactory'); const DocumentRepository = require('./document/DocumentRepository'); const ExecutionTimer = require('./util/ExecutionTimer'); @@ -696,6 +697,7 @@ function createDIContainer(options) { updateWithdrawalTransactionIdAndStatus: asFunction( updateWithdrawalTransactionIdAndStatusFactory, ), + broadcastWithdrawalTransactions: asFunction(broadcastWithdrawalTransactionsFactory), }); /** diff --git a/packages/js-drive/test/integration/identity/masternode/synchronizeMasternodeIdentitiesFactory.spec.js b/packages/js-drive/test/integration/identity/masternode/synchronizeMasternodeIdentitiesFactory.spec.js index 19446cb2680..7b2dc9eb127 100644 --- a/packages/js-drive/test/integration/identity/masternode/synchronizeMasternodeIdentitiesFactory.spec.js +++ b/packages/js-drive/test/integration/identity/masternode/synchronizeMasternodeIdentitiesFactory.spec.js @@ -367,7 +367,7 @@ describe('synchronizeMasternodeIdentitiesFactory', () => { beforeEach(async function beforeEach() { coreHeight = 3; - firstSyncAppHash = '6dc2a81f029eff542d9f40ead09e929615b10744809d26259173b0f9f44a5144'; + firstSyncAppHash = '48002d90813b6536f11b1927760311d978c514aac5940a90a897f713950b2464'; blockInfo = new BlockInfo(10, 0, 1668702100799); container = await createTestDIContainer(); @@ -695,7 +695,7 @@ describe('synchronizeMasternodeIdentitiesFactory', () => { // Nothing happened - await expectDeterministicAppHash('ca14fde445978315558fd4d1ce77b52003daa2f9e0da7e769c27f7950ef4304b'); + await expectDeterministicAppHash('0cc76cc02c67b21d6b60289f9e68fae070fa7e2ae77a72c00f61b860647d5810'); // Core RPC should be called @@ -750,7 +750,7 @@ describe('synchronizeMasternodeIdentitiesFactory', () => { expect(result.updatedEntities).to.have.lengthOf(0); expect(result.removedEntities).to.have.lengthOf(0); - await expectDeterministicAppHash('984a2868aa1cba0b8606fface2fdb1b99a75e1dc5456a449a4b9488699fff6f7'); + await expectDeterministicAppHash('af64cbf6303f7a9977385d622113c96f3704a1000d4ff48a6961d986499b2347'); // New masternode identity should be created @@ -834,7 +834,7 @@ describe('synchronizeMasternodeIdentitiesFactory', () => { expect(result.updatedEntities).to.have.lengthOf(0); expect(result.removedEntities).to.have.lengthOf(1); - await expectDeterministicAppHash('553d688a16811ba92d9ede063ffbf6985f78f6ee4065fbadfbea3c96a88cfd59'); + await expectDeterministicAppHash('7c68e136e95c2f8e638c0bf3eecb67a2cf32f35eaf9b782b75134cc6ae4a6b85'); // Masternode identity should stay @@ -902,7 +902,7 @@ describe('synchronizeMasternodeIdentitiesFactory', () => { expect(result.updatedEntities).to.have.lengthOf(0); expect(result.removedEntities).to.have.lengthOf(1); - await expectDeterministicAppHash('553d688a16811ba92d9ede063ffbf6985f78f6ee4065fbadfbea3c96a88cfd59'); + await expectDeterministicAppHash('7c68e136e95c2f8e638c0bf3eecb67a2cf32f35eaf9b782b75134cc6ae4a6b85'); const invalidMasternodeIdentifier = Identifier.from( Buffer.from(invalidSmlEntry.proRegTxHash, 'hex'), @@ -952,7 +952,7 @@ describe('synchronizeMasternodeIdentitiesFactory', () => { expect(result.updatedEntities).to.have.lengthOf(1); expect(result.removedEntities).to.have.lengthOf(1); - await expectDeterministicAppHash('ba35e7bc3c3e347c7724da0e9ff3fcf7798abf8b32735bde8f9e5e534483f593'); + await expectDeterministicAppHash('fcb68d208398ec82404510f0a5ebe64d127ba0610bdab697f2017820d2857df8'); // Masternode identity should stay @@ -1027,7 +1027,7 @@ describe('synchronizeMasternodeIdentitiesFactory', () => { await synchronizeMasternodeIdentities(coreHeight + 1, blockInfo); - await expectDeterministicAppHash('058a528131c4eba0e3f766d934a004cdc72f71f29ccc96c95507d0f450e5a262'); + await expectDeterministicAppHash('4a640e22f8740d5f8fbb6723ef1caef958e2832264cf3dabe3222a5f30a4fb5f'); // Masternode identity should contain new public key @@ -1110,7 +1110,7 @@ describe('synchronizeMasternodeIdentitiesFactory', () => { await synchronizeMasternodeIdentities(coreHeight, blockInfo); - await expectDeterministicAppHash('3fbb1f504303d8ddc4334ad1501ba62acca77213f87b3b2665368362b9628883'); + await expectDeterministicAppHash('d71afa23ed2f58e7e83d14ffdd6e31ab413b5063159759622b5860ae53f64e03'); const votingIdentifier = createVotingIdentifier(smlFixture[0]); diff --git a/packages/rs-drive/src/drive/document/helpers.rs b/packages/rs-drive/src/drive/document/helpers.rs index 58c665e1b5c..ddcccc47a96 100644 --- a/packages/rs-drive/src/drive/document/helpers.rs +++ b/packages/rs-drive/src/drive/document/helpers.rs @@ -46,7 +46,7 @@ impl Drive { )) })?; - let operations = self.add_document_for_contract_operations( + let operations = self.update_document_for_contract_operations( DocumentAndContractInfo { document_info: DocumentInfo::DocumentRefAndSerialization(( &crate::drive::document::Document::from_cbor(&document_cbor, None, None)?, @@ -58,7 +58,6 @@ impl Drive { .document_type_for_name(withdrawals_contract::types::WITHDRAWAL)?, owner_id: Some(document.owner_id.to_buffer()), }, - true, block_info, &mut None, transaction, From f1ae6f245ea930f65a5564fac1760e632bda9fb9 Mon Sep 17 00:00:00 2001 From: Djavid Gabibyan Date: Fri, 30 Dec 2022 18:09:16 +0500 Subject: [PATCH 053/170] Merge branch 'v0.24-dev' into feat/withdrawal-sync --- packages/rs-drive/src/drive/batch/drive_op_batch.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/packages/rs-drive/src/drive/batch/drive_op_batch.rs b/packages/rs-drive/src/drive/batch/drive_op_batch.rs index 2fcea066b36..477e4b39a15 100644 --- a/packages/rs-drive/src/drive/batch/drive_op_batch.rs +++ b/packages/rs-drive/src/drive/batch/drive_op_batch.rs @@ -37,8 +37,6 @@ use crate::drive::identity::withdrawals::paths::{ get_withdrawal_transactions_expired_ids_path_as_u8, get_withdrawal_transactions_queue_path, WithdrawalTransaction, WITHDRAWAL_TRANSACTIONS_COUNTER_ID, }; -use crate::drive::object_size_info::DocumentAndContractInfo; -use crate::drive::object_size_info::DocumentInfo::DocumentRefAndSerialization; use crate::drive::object_size_info::DocumentInfo::{ DocumentRefAndSerialization, DocumentRefWithoutSerialization, }; From 22ae54bea08b0ba6ec348ca733a836820fe50c25 Mon Sep 17 00:00:00 2001 From: Djavid Gabibyan Date: Sat, 31 Dec 2022 20:38:42 +0500 Subject: [PATCH 054/170] chore: wip --- packages/rs-drive-abci/src/abci/handlers.rs | 70 ++-- .../src/identity_credit_withdrawal/mod.rs | 213 +++++++--- packages/rs-drive-nodejs/src/lib.rs | 24 +- .../src/drive/batch/drive_op_batch.rs | 14 +- .../rs-drive/src/drive/document/helpers.rs | 383 +++++++++--------- .../src/drive/identity/withdrawals/queue.rs | 120 +++--- .../withdrawals/transaction_index_counter.rs | 62 +-- .../identity/withdrawals/withdrawal_status.rs | 56 ++- packages/rs-drive/src/drive/mod.rs | 2 +- 9 files changed, 556 insertions(+), 388 deletions(-) diff --git a/packages/rs-drive-abci/src/abci/handlers.rs b/packages/rs-drive-abci/src/abci/handlers.rs index 408ddef5da5..de7aeb0db34 100644 --- a/packages/rs-drive-abci/src/abci/handlers.rs +++ b/packages/rs-drive-abci/src/abci/handlers.rs @@ -137,7 +137,11 @@ impl TenderdashAbci for Platform { &block_execution_context, request.validator_set_quorum_hash, transaction, - )?; + ); + + dbg!(&unsigned_withdrawal_transaction_bytes); + + let unsigned_withdrawal_transaction_bytes = unsigned_withdrawal_transaction_bytes?; self.block_execution_context .replace(Some(block_execution_context)); @@ -199,9 +203,16 @@ mod tests { use chrono::{Duration, Utc}; use dashcore::hashes::hex::FromHex; use dashcore::BlockHash; - use dpp::tests::fixtures::get_withdrawals_data_contract_fixture; + use dpp::contracts::withdrawals_contract; + use dpp::identity::state_transition::identity_credit_withdrawal_transition::Pooling; + use dpp::tests::fixtures::{ + get_withdrawal_document_fixture, get_withdrawals_data_contract_fixture, + }; + use dpp::util::hash; use drive::common::helpers::identities::create_test_masternode_identities; + use drive::common::helpers::setup::setup_document; use drive::drive::block_info::BlockInfo; + use drive::drive::identity::withdrawals::paths::WithdrawalTransaction; use drive::fee::epoch::CreditsPerEpoch; use drive::fee_pools::epochs::Epoch; use drive::rpc::core::MockCoreRPCLike; @@ -230,45 +241,56 @@ mod tests { .init_chain(init_chain_request, Some(&transaction)) .expect("should init chain"); - setup_system_data_contract( - &platform.drive, - &get_withdrawals_data_contract_fixture(None), - Some(&transaction), - ); + let data_contract = get_withdrawals_data_contract_fixture(None); + + setup_system_data_contract(&platform.drive, &data_contract, Some(&transaction)); // Init withdrawal requests - let withdrawals = (0..16) + let withdrawals: Vec = (0..16) .map(|index: u64| (index.to_be_bytes().to_vec(), vec![index as u8; 32])) .collect(); + for (_, tx_bytes) in withdrawals.iter() { + let tx_id = hash::hash(tx_bytes); + + let document = get_withdrawal_document_fixture( + &data_contract, + json!({ + "amount": 1000, + "coreFeePerByte": 1, + "pooling": Pooling::Never, + "outputScript": (0..23).collect::>(), + "status": withdrawals_contract::statuses::POOLED, + "transactionIndex": 1, + "transactionSignHeight": 93, + "transactionId": tx_id, + }), + ); + + setup_document( + &platform.drive, + &document, + &data_contract, + Some(&transaction), + ); + } + let block_info = BlockInfo { time_ms: 1, height: 1, epoch: Epoch::new(1), }; - let mut batch = vec![]; - let mut result_operations = vec![]; + let mut drive_operations = vec![]; platform .drive - .add_enqueue_withdrawal_transaction_operations( - &withdrawals, - &block_info, - &mut batch, - Some(&transaction), - ) - .expect("to add enqueue operations"); + .add_enqueue_withdrawal_transaction_operations(&withdrawals, &mut drive_operations); platform .drive - .apply_batch_drive_operations( - None, - Some(&transaction), - batch, - &mut result_operations, - ) - .expect("to apply batch"); + .apply_drive_operations(drive_operations, true, &block_info, Some(&transaction)) + .expect("to apply drive operations"); // setup the contract let contract = platform.create_mn_shares_contract(Some(&transaction)); diff --git a/packages/rs-drive-abci/src/identity_credit_withdrawal/mod.rs b/packages/rs-drive-abci/src/identity_credit_withdrawal/mod.rs index 0d8d95ec11a..03f30e1e8be 100644 --- a/packages/rs-drive-abci/src/identity_credit_withdrawal/mod.rs +++ b/packages/rs-drive-abci/src/identity_credit_withdrawal/mod.rs @@ -4,11 +4,16 @@ use dashcore::{ }; use dpp::{ contracts::withdrawals_contract, + data_contract::extra::DriveContractExt, prelude::{Document, Identifier}, util::{hash, json_value::JsonValueExt, string_encoding::Encoding}, }; use drive::{ - drive::block_info::BlockInfo, fee::op::DriveOperation, fee_pools::epochs::Epoch, + drive::{ + batch::DriveOperationType, block_info::BlockInfo, + identity::withdrawals::paths::WithdrawalTransaction, + }, + fee_pools::epochs::Epoch, query::TransactionArg, }; use serde_json::{Number, Value as JsonValue}; @@ -55,7 +60,7 @@ impl Platform { block_execution_context.block_info.core_chain_locked_height, )?; - let broadcasted_documents = self.drive.fetch_withdrawal_documents_by_status( + let mut broadcasted_documents = self.drive.fetch_withdrawal_documents_by_status( withdrawals_contract::statuses::BROADCASTED, transaction, )?; @@ -66,9 +71,9 @@ impl Platform { epoch: Epoch::new(block_execution_context.epoch_info.current_epoch_index), }; - let mut drive_operations: Vec = vec![]; + let mut drive_operations: Vec = vec![]; - for mut document in broadcasted_documents { + for document in broadcasted_documents.iter_mut() { let transaction_sign_height = document .data @@ -103,20 +108,15 @@ impl Platform { } else { self.drive.add_insert_expired_index_operation( transaction_index, - &block_info, &mut drive_operations, - transaction, - )?; + ); withdrawals_contract::statuses::EXPIRED }; - self.drive.add_update_document_data_operations( - &contract_fetch_info.contract, - &mut document, + self.drive.update_document_data( + document, &block_info, - transaction, - &mut drive_operations, |document: &mut Document| -> Result<&mut Document, drive::error::Error> { document .set("status", JsonValue::Number(Number::from(status))) @@ -134,15 +134,27 @@ impl Platform { } } - if !drive_operations.is_empty() { - let mut result_operations = vec![]; + let drive_documents = self + .drive + .convert_dpp_documents_to_drive_documents(broadcasted_documents.iter())?; + + self.drive.add_update_multiple_documents_operations( + &drive_documents, + &contract_fetch_info.contract, + contract_fetch_info + .contract + .document_type_for_name("withdrawal") + .map_err(|_| { + Error::Execution(ExecutionError::CorruptedCodeExecution( + "Can't fetch withdrawal data contract", + )) + })?, + &mut drive_operations, + ); - self.drive.apply_batch_drive_operations( - None, - transaction, - drive_operations, - &mut result_operations, - )?; + if !drive_operations.is_empty() { + self.drive + .apply_drive_operations(drive_operations, true, &block_info, transaction)?; } Ok(()) @@ -155,13 +167,34 @@ impl Platform { validator_set_quorum_hash: [u8; 32], transaction: TransactionArg, ) -> Result>, Error> { + let (_, maybe_data_contract) = self.drive.get_contract_with_fetch_info( + Identifier::from_string( + &withdrawals_contract::system_ids().contract_id, + Encoding::Base58, + ) + .map_err(|_| { + Error::Execution(ExecutionError::CorruptedCodeExecution( + "Can't create withdrawals id identifier from string", + )) + })? + .to_buffer(), + Some(&Epoch::new( + block_execution_context.epoch_info.current_epoch_index, + )), + transaction, + )?; + + let contract_fetch_info = maybe_data_contract.ok_or(Error::Execution( + ExecutionError::CorruptedCodeExecution("Can't fetch withdrawal data contract"), + ))?; + let block_info = BlockInfo { time_ms: block_execution_context.block_info.block_time_ms, height: block_execution_context.block_info.block_height, epoch: Epoch::new(block_execution_context.epoch_info.current_epoch_index), }; - let mut drive_operations = vec![]; + let mut drive_operations: Vec = vec![]; // Get 16 latest withdrawal transactions from the queue let withdrawal_transactions = self @@ -170,7 +203,7 @@ impl Platform { // Appending request_height and quorum_hash to withdrwal transaction // and pass it to JS Drive for singing and broadcasting - let result = withdrawal_transactions + let transactions_and_documents = withdrawal_transactions .into_iter() .map(|(_, bytes)| { let request_info = AssetUnlockRequestInfo { @@ -192,30 +225,65 @@ impl Platform { let original_transaction_id = hash::hash(bytes); let update_transaction_id = hash::hash(bytes_buffer.clone()); - self.drive.update_document_transaction_id( - &original_transaction_id, - &update_transaction_id, - &block_info, - &mut drive_operations, - transaction, - )?; + let mut document = self + .drive + .find_document_by_transaction_id(&original_transaction_id, transaction)?; - Ok(bytes_buffer) + self.drive + .update_document_data(&mut document, &block_info, |doc| { + doc.set( + "transactionId", + JsonValue::Array( + update_transaction_id + .iter() + .map(|byte| JsonValue::Number(Number::from(*byte))) + .collect(), + ), + ) + .map_err(|_| { + drive::error::Error::Drive( + drive::error::drive::DriveError::CorruptedCodeExecution( + "Can't set document field: transactionId", + ), + ) + })?; + + Ok(doc) + })?; + + Ok((bytes_buffer, document)) }) - .collect::>, Error>>()?; + .collect::, Document)>, Error>>()?; - if !drive_operations.is_empty() { - let mut result_operations = vec![]; + let drive_documents = self.drive.convert_dpp_documents_to_drive_documents( + transactions_and_documents + .iter() + .map(|(_, document)| document), + )?; - self.drive.apply_batch_drive_operations( - None, - transaction, - drive_operations, - &mut result_operations, - )?; + self.drive.add_update_multiple_documents_operations( + &drive_documents, + &contract_fetch_info.contract, + contract_fetch_info + .contract + .document_type_for_name("withdrawal") + .map_err(|_| { + Error::Execution(ExecutionError::CorruptedCodeExecution( + "could not get document type", + )) + })?, + &mut drive_operations, + ); + + if !drive_operations.is_empty() { + self.drive + .apply_drive_operations(drive_operations, true, &block_info, transaction)?; } - Ok(result) + Ok(transactions_and_documents + .iter() + .map(|(bytes, _)| bytes.clone()) + .collect()) } /// Pool withdrawal documents into transactions @@ -266,12 +334,9 @@ impl Platform { let transaction_id = hash::hash(withdrawal_transactions.get(&document.id).unwrap().1.clone()); - self.drive.add_update_document_data_operations( - &contract_fetch_info.contract, + self.drive.update_document_data( document, &block_info, - transaction, - &mut drive_operations, |document: &mut Document| -> Result<&mut Document, drive::error::Error> { document .set( @@ -310,7 +375,41 @@ impl Platform { )?; } - let withdrawal_transactions = withdrawal_transactions + let drive_documents = documents + .iter() + .map(|document| { + drive::contract::document::Document::from_cbor( + &document.to_cbor().map_err(|_| { + Error::Execution(ExecutionError::CorruptedCodeExecution( + "Can't fetch withdrawal data contract", + )) + })?, + None, + None, + ) + .map_err(|_| { + Error::Execution(ExecutionError::CorruptedCodeExecution( + "Can't fetch withdrawal data contract", + )) + }) + }) + .collect::, Error>>()?; + + self.drive.add_update_multiple_documents_operations( + &drive_documents, + &contract_fetch_info.contract, + contract_fetch_info + .contract + .document_type_for_name("withdrawal") + .map_err(|_| { + Error::Execution(ExecutionError::CorruptedCodeExecution( + "Can't fetch withdrawal data contract", + )) + })?, + &mut drive_operations, + ); + + let withdrawal_transactions: Vec = withdrawal_transactions .values() .into_iter() .cloned() @@ -318,20 +417,12 @@ impl Platform { self.drive.add_enqueue_withdrawal_transaction_operations( &withdrawal_transactions, - &block_info, &mut drive_operations, - transaction, - )?; + ); if !drive_operations.is_empty() { - let mut result_operations = vec![]; - - self.drive.apply_batch_drive_operations( - None, - transaction, - drive_operations, - &mut result_operations, - )?; + self.drive + .apply_drive_operations(drive_operations, true, &block_info, transaction)?; } Ok(()) @@ -403,6 +494,8 @@ mod tests { }; mod update_withdrawal_statuses { + use dpp::prelude::DataContract; + use super::*; #[test] @@ -461,6 +554,14 @@ mod tests { let data_contract = get_withdrawals_data_contract_fixture(None); + // TODO: figure out the bug in data contract factory + let data_contract = DataContract::from_cbor( + data_contract + .to_cbor() + .expect("to convert contract to CBOR"), + ) + .expect("to create data contract from CBOR"); + setup_system_data_contract(&platform.drive, &data_contract, Some(&transaction)); let document_1 = get_withdrawal_document_fixture( diff --git a/packages/rs-drive-nodejs/src/lib.rs b/packages/rs-drive-nodejs/src/lib.rs index b94cf03a395..c52f9635f4d 100644 --- a/packages/rs-drive-nodejs/src/lib.rs +++ b/packages/rs-drive-nodejs/src/lib.rs @@ -2274,7 +2274,7 @@ impl PlatformWrapper { epoch: Epoch::new(1), }; - let mut batch = vec![]; + let mut drive_operations = vec![]; let index_bytes = (index as u64).to_be_bytes().to_vec(); @@ -2285,28 +2285,22 @@ impl PlatformWrapper { .drive .add_enqueue_withdrawal_transaction_operations( &withdrawals, - &block_info, - &mut batch, - transaction, - ) - .map_err(|err| err.to_string())?; + &mut drive_operations, + ); platform .drive .add_update_withdrawal_index_counter_operation( index as u64, - &block_info, - &mut batch, - transaction, - ) - .map_err(|err| err.to_string())?; - - let mut result_operations = vec![]; + &mut drive_operations, + ); platform .drive - .apply_batch_drive_operations(None, transaction, batch, &mut result_operations) - .map_err(|err| err.to_string()) + .apply_drive_operations(drive_operations, true, &block_info, transaction) + .map_err(|err| err.to_string())?; + + Ok(()) }; let result = transaction_result.and_then(execution_function); diff --git a/packages/rs-drive/src/drive/batch/drive_op_batch.rs b/packages/rs-drive/src/drive/batch/drive_op_batch.rs index 477e4b39a15..947b8c2652e 100644 --- a/packages/rs-drive/src/drive/batch/drive_op_batch.rs +++ b/packages/rs-drive/src/drive/batch/drive_op_batch.rs @@ -136,13 +136,13 @@ impl DriveOperationConverter for ContractOperationType<'_> { /// A wrapper for an update operation pub struct UpdateOperationInfo<'a> { /// The document to update - document: &'a Document, + pub document: &'a Document, /// The document in pre-serialized form - serialized_document: Option<&'a [u8]>, + pub serialized_document: Option<&'a [u8]>, /// The owner id, if none is specified will try to recover from serialized document - owner_id: Option<[u8; 32]>, + pub owner_id: Option<[u8; 32]>, /// Add storage flags (like epoch, owner id, etc) - storage_flags: Option<&'a StorageFlags>, + pub storage_flags: Option<&'a StorageFlags>, } /// A wrapper for a document operation @@ -528,6 +528,12 @@ impl DriveOperationConverter for DocumentOperationType<'_> { storage_flags, } = update_operation; + let document_cbor = document.to_cbor(); + + // If serialized document not submitted updates are not performed + // TODO: figure that out + let serialized_document = serialized_document.or(Some(&document_cbor)); + let document_info = if let Some(serialized_document) = serialized_document { DocumentRefAndSerialization(( diff --git a/packages/rs-drive/src/drive/document/helpers.rs b/packages/rs-drive/src/drive/document/helpers.rs index ddcccc47a96..294a11d84e0 100644 --- a/packages/rs-drive/src/drive/document/helpers.rs +++ b/packages/rs-drive/src/drive/document/helpers.rs @@ -1,6 +1,6 @@ use dpp::{ contracts::withdrawals_contract, - data_contract::extra::{common, DriveContractExt}, + data_contract::extra::{common, DocumentType, DriveContractExt}, prelude::{DataContract, Document, Identifier}, util::string_encoding::Encoding, }; @@ -9,23 +9,24 @@ use serde_json::{json, Number, Value as JsonValue}; use crate::{ drive::{ + batch::{ + drive_op_batch::{ + DocumentOperation, DocumentOperationsForContractDocumentType, UpdateOperationInfo, + }, + DocumentOperationType, DriveOperationType, + }, block_info::BlockInfo, - object_size_info::{DocumentAndContractInfo, DocumentInfo}, Drive, }, error::{drive::DriveError, Error}, - fee::op::DriveOperation, }; impl Drive { /// Helper function to avoid boilerplate of calling an update - pub fn add_update_document_data_operations( - &self, - contract: &DataContract, + pub fn update_document_data<'a, F>( + &'a self, document: &mut Document, block_info: &BlockInfo, - transaction: TransactionArg, - drive_operations: &mut Vec, update_fn: F, ) -> Result<(), Error> where @@ -40,42 +41,16 @@ impl Drive { })?); document.increment_revision(); - let document_cbor = document.to_cbor().map_err(|_| { - Error::Drive(DriveError::CorruptedCodeExecution( - "Can't cbor withdrawal document", - )) - })?; - - let operations = self.update_document_for_contract_operations( - DocumentAndContractInfo { - document_info: DocumentInfo::DocumentRefAndSerialization(( - &crate::drive::document::Document::from_cbor(&document_cbor, None, None)?, - &document_cbor, - None, - )), - contract, - document_type: contract - .document_type_for_name(withdrawals_contract::types::WITHDRAWAL)?, - owner_id: Some(document.owner_id.to_buffer()), - }, - block_info, - &mut None, - transaction, - )?; - - drive_operations.extend(operations); - Ok(()) } /// Helper function to find document by original transactionId /// and update document transactionId to new one - pub fn update_document_transaction_id( + pub fn find_and_update_document_by_transaction_id( &self, original_transaction_id: &[u8], update_transaction_id: &[u8], block_info: &BlockInfo, - drive_operations: &mut Vec, transaction: TransactionArg, ) -> Result<(), Error> { let data_contract_id = Identifier::from_string( @@ -88,16 +63,6 @@ impl Drive { )) })?; - let (_, maybe_data_contract) = self.get_contract_with_fetch_info( - data_contract_id.to_buffer(), - Some(&block_info.epoch), - transaction, - )?; - - let contract_fetch_info = maybe_data_contract.ok_or(Error::Drive( - DriveError::CorruptedCodeExecution("Can't fetch withdrawal data contract"), - ))?; - let query_value = json!({ "where": [ ["transactionId", "==", original_transaction_id], @@ -115,7 +80,7 @@ impl Drive { transaction, )?; - let documents = documents + let mut documents = documents .into_iter() .map(|document_cbor| { Document::from_cbor(document_cbor).map_err(|_| { @@ -126,146 +91,202 @@ impl Drive { }) .collect::, Error>>()?; - for mut document in documents { - self.add_update_document_data_operations( - &contract_fetch_info.contract, - &mut document, - block_info, - transaction, - drive_operations, - |document: &mut Document| -> Result<&mut Document, Error> { - document - .set( - "transactionId", - JsonValue::Array( - update_transaction_id - .iter() - .map(|byte| JsonValue::Number(Number::from(*byte))) - .collect(), - ), - ) - .map_err(|_| { - Error::Drive(DriveError::CorruptedCodeExecution( - "Can't set document field: transactionId", - )) - })?; - - Ok(document) - }, - )?; - } + let document = + documents + .get_mut(0) + .ok_or(Error::Drive(DriveError::CorruptedCodeExecution( + "Document was not found by transactionId", + )))?; - Ok(()) + self.update_document_data( + document, + block_info, + |document: &mut Document| -> Result<&mut Document, Error> { + document + .set( + "transactionId", + JsonValue::Array( + update_transaction_id + .iter() + .map(|byte| JsonValue::Number(Number::from(*byte))) + .collect(), + ), + ) + .map_err(|_| { + Error::Drive(DriveError::CorruptedCodeExecution( + "Can't set document field: transactionId", + )) + })?; + + Ok(document) + }, + ) } -} - -#[cfg(test)] -mod tests { - use dpp::{ - contracts::withdrawals_contract, - tests::fixtures::{get_withdrawal_document_fixture, get_withdrawals_data_contract_fixture}, - }; - use serde_json::json; - - use crate::common::helpers::setup::{ - setup_document, setup_drive_with_initial_state_structure, setup_system_data_contract, - }; - - use dpp::identity::state_transition::identity_credit_withdrawal_transition::Pooling; - - use crate::{drive::block_info::BlockInfo, fee_pools::epochs::Epoch}; - - mod update_document_transaction_id { - - use super::*; - - #[test] - fn test_transaction_id_updated() { - let drive = setup_drive_with_initial_state_structure(); - - let transaction = drive.grove.start_transaction(); - - let data_contract = get_withdrawals_data_contract_fixture(None); - - setup_system_data_contract(&drive, &data_contract, Some(&transaction)); - - let original_transaction_id: Vec = vec![ - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, - ]; - - let updated_transaction_id: Vec = vec![ - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, - ]; - - let document = get_withdrawal_document_fixture( - &data_contract, - json!({ - "amount": 1000, - "coreFeePerByte": 1, - "pooling": Pooling::Never, - "outputScript": (0..23).collect::>(), - "status": withdrawals_contract::statuses::POOLED, - "transactionIndex": 1, - "transactionId": original_transaction_id, - }), - ); - - setup_document(&drive, &document, &data_contract, Some(&transaction)); - - let block_info = BlockInfo { - time_ms: 1, - height: 1, - epoch: Epoch::new(1), - }; - - let mut drive_operations = vec![]; - let mut result_operations = vec![]; - - drive - .update_document_transaction_id( - &original_transaction_id, - &updated_transaction_id, - &block_info, - &mut drive_operations, - Some(&transaction), - ) - .expect("to update transactionId"); - dbg!(&drive_operations); + /// Add update multiple documents operations + pub fn add_update_multiple_documents_operations<'a>( + &self, + documents: &'a [crate::contract::document::Document], + data_contract: &'a DataContract, + document_type: &'a DocumentType, + drive_operations: &mut Vec>, + ) { + let operations: Vec = documents + .iter() + .map(|document| { + DocumentOperation::UpdateOperation(UpdateOperationInfo { + document, + serialized_document: None, + owner_id: None, + storage_flags: None, + }) + }) + .collect(); + + if !operations.is_empty() { + drive_operations.push(DriveOperationType::DocumentOperation( + DocumentOperationType::MultipleDocumentOperationsForSameContractDocumentType { + document_operations: DocumentOperationsForContractDocumentType { + operations, + contract: data_contract, + document_type, + }, + }, + )); + } + } - drive - .apply_batch_drive_operations( + /// Helper function to convert DPP documents to Drive documents + pub fn convert_dpp_documents_to_drive_documents<'a, I>( + &self, + dpp_documents: I, + ) -> Result, Error> + where + I: Iterator, + { + dpp_documents + .map(|document| { + crate::contract::document::Document::from_cbor( + &document.to_cbor().map_err(|_| { + Error::Drive(DriveError::CorruptedCodeExecution( + "Can't convert dpp document to cbor", + )) + })?, + None, None, - Some(&transaction), - drive_operations, - &mut result_operations, - ) - .expect("to apply batch drive operations"); - - let updated_documents = drive - .fetch_withdrawal_documents_by_status( - withdrawals_contract::statuses::POOLED, - Some(&transaction), ) - .expect("to fetch withdrawal documents"); - - assert_eq!(updated_documents.len(), 1); - - let stored_transaction_id: Vec = updated_documents - .get(0) - .unwrap() - .data - .get("transactionId") - .unwrap() - .as_array() - .unwrap() - .iter() - .map(|byte| byte.as_u64().unwrap() as u8) - .collect(); - - assert_eq!(stored_transaction_id, updated_transaction_id); - } + }) + .collect::, Error>>() } } + +// #[cfg(test)] +// mod tests { +// use dpp::{ +// contracts::withdrawals_contract, +// tests::fixtures::{get_withdrawal_document_fixture, get_withdrawals_data_contract_fixture}, +// }; +// use serde_json::json; + +// use crate::common::helpers::setup::{ +// setup_document, setup_drive_with_initial_state_structure, setup_system_data_contract, +// }; + +// use dpp::identity::state_transition::identity_credit_withdrawal_transition::Pooling; + +// use crate::{drive::block_info::BlockInfo, fee_pools::epochs::Epoch}; + +// mod update_document_transaction_id { + +// use super::*; + +// #[test] +// fn test_transaction_id_updated() { +// let drive = setup_drive_with_initial_state_structure(); + +// let transaction = drive.grove.start_transaction(); + +// let data_contract = get_withdrawals_data_contract_fixture(None); + +// setup_system_data_contract(&drive, &data_contract, Some(&transaction)); + +// let original_transaction_id: Vec = vec![ +// 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, +// 1, 1, 1, 1, +// ]; + +// let updated_transaction_id: Vec = vec![ +// 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, +// 2, 2, 2, 2, +// ]; + +// let document = get_withdrawal_document_fixture( +// &data_contract, +// json!({ +// "amount": 1000, +// "coreFeePerByte": 1, +// "pooling": Pooling::Never, +// "outputScript": (0..23).collect::>(), +// "status": withdrawals_contract::statuses::POOLED, +// "transactionIndex": 1, +// "transactionId": original_transaction_id, +// }), +// ); + +// setup_document(&drive, &document, &data_contract, Some(&transaction)); + +// let block_info = BlockInfo { +// time_ms: 1, +// height: 1, +// epoch: Epoch::new(1), +// }; + +// let mut drive_operations = vec![]; +// let mut result_operations = vec![]; + +// drive +// .find_and_update_document_by_transaction_id( +// &original_transaction_id, +// &updated_transaction_id, +// &block_info, +// &mut drive_operations, +// Some(&transaction), +// ) +// .expect("to update transactionId"); + +// dbg!(&drive_operations); + +// drive +// .apply_batch_drive_operations( +// None, +// Some(&transaction), +// drive_operations, +// &mut result_operations, +// ) +// .expect("to apply batch drive operations"); + +// let updated_documents = drive +// .fetch_withdrawal_documents_by_status( +// withdrawals_contract::statuses::POOLED, +// Some(&transaction), +// ) +// .expect("to fetch withdrawal documents"); + +// assert_eq!(updated_documents.len(), 1); + +// let stored_transaction_id: Vec = updated_documents +// .get(0) +// .unwrap() +// .data +// .get("transactionId") +// .unwrap() +// .as_array() +// .unwrap() +// .iter() +// .map(|byte| byte.as_u64().unwrap() as u8) +// .collect(); + +// assert_eq!(stored_transaction_id, updated_transaction_id); +// } +// } +// } diff --git a/packages/rs-drive/src/drive/identity/withdrawals/queue.rs b/packages/rs-drive/src/drive/identity/withdrawals/queue.rs index d9b7de933d6..1257504e68a 100644 --- a/packages/rs-drive/src/drive/identity/withdrawals/queue.rs +++ b/packages/rs-drive/src/drive/identity/withdrawals/queue.rs @@ -7,7 +7,10 @@ use grovedb::{ use crate::{ drive::{ - batch::drive_op_batch::{DriveOperationConverter, WithdrawalOperationType}, + batch::{ + drive_op_batch::{DriveOperationConverter, WithdrawalOperationType}, + DriveOperationType, + }, block_info::BlockInfo, grove_operations::BatchDeleteApplyType, Drive, @@ -23,21 +26,18 @@ use super::paths::{ impl Drive { /// Add insert operations for withdrawal transactions to the batch - pub fn add_enqueue_withdrawal_transaction_operations( + pub fn add_enqueue_withdrawal_transaction_operations<'a>( &self, - withdrawals: &Vec, - block_info: &BlockInfo, - drive_operations: &mut Vec, - transaction: TransactionArg, - ) -> Result<(), Error> { - drive_operations.extend( - WithdrawalOperationType::InsertTransactions { - transactions: withdrawals, - } - .to_drive_operations(self, &mut None, block_info, transaction)?, - ); - - Ok(()) + withdrawals: &'a [WithdrawalTransaction], + drive_operations: &mut Vec>, + ) { + if !withdrawals.is_empty() { + drive_operations.push(DriveOperationType::WithdrawalOperation( + WithdrawalOperationType::InsertTransactions { + transactions: withdrawals, + }, + )); + } } /// Get specified amount of withdrawal transactions from the DB @@ -112,61 +112,61 @@ impl Drive { } } -#[cfg(test)] -mod tests { - use crate::{ - common::helpers::setup::setup_drive_with_initial_state_structure, - drive::block_info::BlockInfo, fee::op::DriveOperation, fee_pools::epochs::Epoch, - }; +// #[cfg(test)] +// mod tests { +// use crate::{ +// common::helpers::setup::setup_drive_with_initial_state_structure, +// drive::block_info::BlockInfo, fee::op::DriveOperation, fee_pools::epochs::Epoch, +// }; - #[test] - fn test_enqueue_and_dequeue() { - let drive = setup_drive_with_initial_state_structure(); +// #[test] +// fn test_enqueue_and_dequeue() { +// let drive = setup_drive_with_initial_state_structure(); - let transaction = drive.grove.start_transaction(); +// let transaction = drive.grove.start_transaction(); - let withdrawals: Vec<(Vec, Vec)> = (0..17) - .map(|i: u8| (i.to_be_bytes().to_vec(), vec![i; 32])) - .collect(); +// let withdrawals: Vec<(Vec, Vec)> = (0..17) +// .map(|i: u8| (i.to_be_bytes().to_vec(), vec![i; 32])) +// .collect(); - let block_info = BlockInfo { - time_ms: 1, - height: 1, - epoch: Epoch::new(1), - }; +// let block_info = BlockInfo { +// time_ms: 1, +// height: 1, +// epoch: Epoch::new(1), +// }; - let mut batch: Vec = vec![]; - let mut result_operations = vec![]; +// let mut batch: Vec = vec![]; +// let mut result_operations = vec![]; - drive - .add_enqueue_withdrawal_transaction_operations( - &withdrawals, - &block_info, - &mut batch, - Some(&transaction), - ) - .expect("to add operations"); +// drive +// .add_enqueue_withdrawal_transaction_operations( +// &withdrawals, +// &block_info, +// &mut batch, +// Some(&transaction), +// ) +// .expect("to add operations"); - drive - .apply_batch_drive_operations(None, Some(&transaction), batch, &mut result_operations) - .expect("to apply batch"); +// drive +// .apply_batch_drive_operations(None, Some(&transaction), batch, &mut result_operations) +// .expect("to apply batch"); - let withdrawals = drive - .dequeue_withdrawal_transactions(16, Some(&transaction)) - .expect("to dequeue withdrawals"); +// let withdrawals = drive +// .dequeue_withdrawal_transactions(16, Some(&transaction)) +// .expect("to dequeue withdrawals"); - assert_eq!(withdrawals.len(), 16); +// assert_eq!(withdrawals.len(), 16); - let withdrawals = drive - .dequeue_withdrawal_transactions(16, Some(&transaction)) - .expect("to dequeue withdrawals"); +// let withdrawals = drive +// .dequeue_withdrawal_transactions(16, Some(&transaction)) +// .expect("to dequeue withdrawals"); - assert_eq!(withdrawals.len(), 1); +// assert_eq!(withdrawals.len(), 1); - let withdrawals = drive - .dequeue_withdrawal_transactions(16, Some(&transaction)) - .expect("to dequeue withdrawals"); +// let withdrawals = drive +// .dequeue_withdrawal_transactions(16, Some(&transaction)) +// .expect("to dequeue withdrawals"); - assert_eq!(withdrawals.len(), 0); - } -} +// assert_eq!(withdrawals.len(), 0); +// } +// } diff --git a/packages/rs-drive/src/drive/identity/withdrawals/transaction_index_counter.rs b/packages/rs-drive/src/drive/identity/withdrawals/transaction_index_counter.rs index 49a12985af5..e27335c269b 100644 --- a/packages/rs-drive/src/drive/identity/withdrawals/transaction_index_counter.rs +++ b/packages/rs-drive/src/drive/identity/withdrawals/transaction_index_counter.rs @@ -5,12 +5,10 @@ use grovedb::{ use crate::{ drive::{ - batch::drive_op_batch::{DriveOperationConverter, WithdrawalOperationType}, - block_info::BlockInfo, + batch::{drive_op_batch::WithdrawalOperationType, DriveOperationType}, Drive, RootTree, }, error::{drive::DriveError, Error}, - fee::op::DriveOperation, }; use super::paths::{ @@ -99,44 +97,24 @@ impl Drive { pub fn add_update_withdrawal_index_counter_operation( &self, value: u64, - block_info: &BlockInfo, - drive_operations: &mut Vec, - transaction: TransactionArg, - ) -> Result<(), Error> { - drive_operations.extend( - WithdrawalOperationType::UpdateIndexCounter { index: value }.to_drive_operations( - self, - &mut None, - block_info, - transaction, - )?, - ); - - Ok(()) - - // batch.add_insert( - // vec![vec![RootTree::WithdrawalTransactions as u8]], - // WITHDRAWAL_TRANSACTIONS_COUNTER_ID.to_vec(), - // Element::Item(value, None), - // ); + drive_operations: &mut Vec, + ) { + drive_operations.push(DriveOperationType::WithdrawalOperation( + WithdrawalOperationType::UpdateIndexCounter { index: value }, + )); } /// Add insert expired counter operations pub fn add_insert_expired_index_operation( &self, transaction_index: u64, - block_info: &BlockInfo, - drive_operations: &mut Vec, - transaction: TransactionArg, - ) -> Result<(), Error> { - let operations = WithdrawalOperationType::InsertExpiredIndex { - index: transaction_index, - } - .to_drive_operations(self, &mut None, block_info, transaction)?; - - drive_operations.extend(operations); - - Ok(()) + drive_operations: &mut Vec, + ) { + drive_operations.push(DriveOperationType::WithdrawalOperation( + WithdrawalOperationType::InsertExpiredIndex { + index: transaction_index, + }, + )); } } @@ -166,22 +144,14 @@ mod tests { }; let mut batch = vec![]; - let mut result_operations = vec![]; let counter: u64 = 42; - drive - .add_update_withdrawal_index_counter_operation( - counter, - &block_info, - &mut batch, - Some(&transaction), - ) - .expect("to add update operations"); + drive.add_update_withdrawal_index_counter_operation(counter, &mut batch); drive - .apply_batch_drive_operations(None, Some(&transaction), batch, &mut result_operations) - .expect("to apply ops"); + .apply_drive_operations(batch, true, &block_info, Some(&transaction)) + .expect("to apply drive ops"); let stored_counter = drive .fetch_latest_withdrawal_transaction_index(Some(&transaction)) diff --git a/packages/rs-drive/src/drive/identity/withdrawals/withdrawal_status.rs b/packages/rs-drive/src/drive/identity/withdrawals/withdrawal_status.rs index 23d7e25b141..54bc5f798ea 100644 --- a/packages/rs-drive/src/drive/identity/withdrawals/withdrawal_status.rs +++ b/packages/rs-drive/src/drive/identity/withdrawals/withdrawal_status.rs @@ -8,7 +8,7 @@ use grovedb::TransactionArg; use serde_json::json; use crate::{ - drive::Drive, + drive::{block_info::BlockInfo, Drive}, error::{drive::DriveError, Error}, }; @@ -60,6 +60,60 @@ impl Drive { Ok(documents) } + + /// Find one document by it's transactionId field + pub fn find_document_by_transaction_id( + &self, + original_transaction_id: &[u8], + transaction: TransactionArg, + ) -> Result { + let data_contract_id = Identifier::from_string( + &withdrawals_contract::system_ids().contract_id, + Encoding::Base58, + ) + .map_err(|_| { + Error::Drive(DriveError::CorruptedCodeExecution( + "Can't create withdrawals id identifier from string", + )) + })?; + + let query_value = json!({ + "where": [ + ["transactionId", "==", original_transaction_id], + ["status", "==", withdrawals_contract::statuses::POOLED], + ], + }); + + let query_cbor = common::value_to_cbor(query_value, None); + + let (documents, _, _) = self.query_documents( + &query_cbor, + data_contract_id.to_buffer(), + withdrawals_contract::types::WITHDRAWAL, + None, + transaction, + )?; + + let documents = documents + .into_iter() + .map(|document_cbor| { + Document::from_cbor(document_cbor).map_err(|_| { + Error::Drive(DriveError::CorruptedCodeExecution( + "Can't create a document from cbor", + )) + }) + }) + .collect::, Error>>()?; + + let document = documents + .get(0) + .ok_or(Error::Drive(DriveError::CorruptedCodeExecution( + "Document was not found by transactionId", + )))? + .clone(); + + Ok(document) + } } #[cfg(test)] diff --git a/packages/rs-drive/src/drive/mod.rs b/packages/rs-drive/src/drive/mod.rs index 08fdbad0828..6c5b9fc316b 100644 --- a/packages/rs-drive/src/drive/mod.rs +++ b/packages/rs-drive/src/drive/mod.rs @@ -208,7 +208,7 @@ impl Drive { } /// Applies a batch of Drive operations to groveDB. - pub fn apply_batch_drive_operations( + fn apply_batch_drive_operations( &self, estimated_costs_only_with_layer_info: Option< HashMap, From bd3cdb6e3fe0273385706ae06783a645bb57b264 Mon Sep 17 00:00:00 2001 From: Djavid Gabibyan Date: Thu, 5 Jan 2023 16:22:12 +0500 Subject: [PATCH 055/170] chore: st size --- .../src/drive/identity/withdrawals/withdrawal_transactions.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/rs-drive/src/drive/identity/withdrawals/withdrawal_transactions.rs b/packages/rs-drive/src/drive/identity/withdrawals/withdrawal_transactions.rs index ad32ac44a73..ce11b700e7c 100644 --- a/packages/rs-drive/src/drive/identity/withdrawals/withdrawal_transactions.rs +++ b/packages/rs-drive/src/drive/identity/withdrawals/withdrawal_transactions.rs @@ -52,7 +52,7 @@ impl Drive { )) })?; - let state_transition_size = 184; + let state_transition_size = 190; let output_script: Script = Script::from(output_script); From 23542d78dbf106479770001980d595d5386396f4 Mon Sep 17 00:00:00 2001 From: Djavid Gabibyan Date: Fri, 6 Jan 2023 11:48:12 +0500 Subject: [PATCH 056/170] chore: wip --- packages/js-drive/lib/createDIContainer.js | 8 ++++--- .../BlockExecutionContextRepository.spec.js | 8 ++++--- .../DataContractStoreRepository.spec.js | 8 ++++--- .../integration/groveDB/GroveDBStore.spec.js | 16 ++++++++----- .../identity/IdentityStoreRepository.spec.js | 8 ++++--- ...blicKeyToIdentitiesStoreRepository.spec.js | 8 ++++--- ...entAssetLockTransactionsRepository.spec.js | 8 ++++--- .../LastSyncedCoreHeightRepository.spec.js | 8 ++++--- packages/rs-drive-abci/src/abci/handlers.rs | 8 ++----- packages/rs-drive-abci/src/config.rs | 23 ++++++++++++------- .../src/identity_credit_withdrawal/mod.rs | 4 ++-- packages/rs-drive-abci/src/platform.rs | 6 ++--- packages/rs-drive-nodejs/src/lib.rs | 17 ++++++++------ packages/rs-drive-nodejs/test/Drive.spec.js | 8 ++++--- packages/rs-drive-nodejs/test/GroveDB.spec.js | 8 ++++--- 15 files changed, 87 insertions(+), 59 deletions(-) diff --git a/packages/js-drive/lib/createDIContainer.js b/packages/js-drive/lib/createDIContainer.js index 2cec0160449..ef7e6b9362d 100644 --- a/packages/js-drive/lib/createDIContainer.js +++ b/packages/js-drive/lib/createDIContainer.js @@ -484,9 +484,11 @@ function createDIContainer(options) { dataContractsBlockCacheSize, }, core: { - rpcUrl: `${coreJsonRpcHost}:${coreJsonRpcPort}`, - rpcUsername: coreJsonRpcUsername, - rpcPassword: coreJsonRpcPassword, + rpc: { + url: `${coreJsonRpcHost}:${coreJsonRpcPort}`, + username: coreJsonRpcUsername, + password: coreJsonRpcPassword, + }, }, })) // TODO: With signed state rotation we need to dispose each groveDB store. diff --git a/packages/js-drive/test/integration/blockExecution/BlockExecutionContextRepository.spec.js b/packages/js-drive/test/integration/blockExecution/BlockExecutionContextRepository.spec.js index afbdcca2c89..a0a466ea8fc 100644 --- a/packages/js-drive/test/integration/blockExecution/BlockExecutionContextRepository.spec.js +++ b/packages/js-drive/test/integration/blockExecution/BlockExecutionContextRepository.spec.js @@ -31,9 +31,11 @@ describe('BlockExecutionContextRepository', () => { dataContractsBlockCacheSize: 500, }, core: { - rpcUrl: '127.0.0.1', - rpcUsername: '', - rpcPassword: '', + rpc: { + url: '127.0.0.1', + username: '', + password: '', + }, }, }); diff --git a/packages/js-drive/test/integration/dataContract/DataContractStoreRepository.spec.js b/packages/js-drive/test/integration/dataContract/DataContractStoreRepository.spec.js index 842410e0f04..a8be383ef27 100644 --- a/packages/js-drive/test/integration/dataContract/DataContractStoreRepository.spec.js +++ b/packages/js-drive/test/integration/dataContract/DataContractStoreRepository.spec.js @@ -25,9 +25,11 @@ describe('DataContractStoreRepository', () => { dataContractsBlockCacheSize: 500, }, core: { - rpcUrl: '127.0.0.1', - rpcUsername: '', - rpcPassword: '', + rpc: { + url: '127.0.0.1', + username: '', + password: '', + }, }, }); diff --git a/packages/js-drive/test/integration/groveDB/GroveDBStore.spec.js b/packages/js-drive/test/integration/groveDB/GroveDBStore.spec.js index 88f54c48d00..162c155e7fd 100644 --- a/packages/js-drive/test/integration/groveDB/GroveDBStore.spec.js +++ b/packages/js-drive/test/integration/groveDB/GroveDBStore.spec.js @@ -20,9 +20,11 @@ describe('GroveDBStore', () => { dataContractsBlockCacheSize: 500, }, core: { - rpcUrl: '127.0.0.1', - rpcUsername: '', - rpcPassword: '', + rpc: { + url: '127.0.0.1', + username: '', + password: '', + }, }, }); @@ -393,9 +395,11 @@ describe('GroveDBStore', () => { dataContractsBlockCacheSize: 500, }, core: { - rpcUrl: '127.0.0.1', - rpcUsername: '', - rpcPassword: '', + rpc: { + url: '127.0.0.1', + username: '', + password: '', + }, }, }); diff --git a/packages/js-drive/test/integration/identity/IdentityStoreRepository.spec.js b/packages/js-drive/test/integration/identity/IdentityStoreRepository.spec.js index 9704c0dd741..5577c7ea7e0 100644 --- a/packages/js-drive/test/integration/identity/IdentityStoreRepository.spec.js +++ b/packages/js-drive/test/integration/identity/IdentityStoreRepository.spec.js @@ -24,9 +24,11 @@ describe('IdentityStoreRepository', () => { dataContractsBlockCacheSize: 500, }, core: { - rpcUrl: '127.0.0.1', - rpcUsername: '', - rpcPassword: '', + rpc: { + url: '127.0.0.1', + username: '', + password: '', + }, }, }); diff --git a/packages/js-drive/test/integration/identity/PublicKeyToIdentitiesStoreRepository.spec.js b/packages/js-drive/test/integration/identity/PublicKeyToIdentitiesStoreRepository.spec.js index cb3e36539a1..0372c8267d1 100644 --- a/packages/js-drive/test/integration/identity/PublicKeyToIdentitiesStoreRepository.spec.js +++ b/packages/js-drive/test/integration/identity/PublicKeyToIdentitiesStoreRepository.spec.js @@ -24,9 +24,11 @@ describe('PublicKeyToIdentitiesStoreRepository', () => { dataContractsBlockCacheSize: 500, }, core: { - rpcUrl: '127.0.0.1', - rpcUsername: '', - rpcPassword: '', + rpc: { + url: '127.0.0.1', + username: '', + password: '', + }, }, }); diff --git a/packages/js-drive/test/integration/identity/SpentAssetLockTransactionsRepository.spec.js b/packages/js-drive/test/integration/identity/SpentAssetLockTransactionsRepository.spec.js index 97a9e78a57e..b21ab1687fc 100644 --- a/packages/js-drive/test/integration/identity/SpentAssetLockTransactionsRepository.spec.js +++ b/packages/js-drive/test/integration/identity/SpentAssetLockTransactionsRepository.spec.js @@ -21,9 +21,11 @@ describe('SpentAssetLockTransactionsRepository', () => { dataContractsBlockCacheSize: 500, }, core: { - rpcUrl: '127.0.0.1', - rpcUsername: '', - rpcPassword: '', + rpc: { + url: '127.0.0.1', + username: '', + password: '', + }, }, }); diff --git a/packages/js-drive/test/integration/identity/masternode/LastSyncedCoreHeightRepository.spec.js b/packages/js-drive/test/integration/identity/masternode/LastSyncedCoreHeightRepository.spec.js index 7e6039ebbce..d9c75f95503 100644 --- a/packages/js-drive/test/integration/identity/masternode/LastSyncedCoreHeightRepository.spec.js +++ b/packages/js-drive/test/integration/identity/masternode/LastSyncedCoreHeightRepository.spec.js @@ -18,9 +18,11 @@ describe('LastSyncedSmlHeightRepository', () => { dataContractsBlockCacheSize: 500, }, core: { - rpcUrl: '127.0.0.1', - rpcUsername: '', - rpcPassword: '', + rpc: { + url: '127.0.0.1', + username: '', + password: '', + }, }, }); diff --git a/packages/rs-drive-abci/src/abci/handlers.rs b/packages/rs-drive-abci/src/abci/handlers.rs index de7aeb0db34..23101d9b838 100644 --- a/packages/rs-drive-abci/src/abci/handlers.rs +++ b/packages/rs-drive-abci/src/abci/handlers.rs @@ -137,11 +137,7 @@ impl TenderdashAbci for Platform { &block_execution_context, request.validator_set_quorum_hash, transaction, - ); - - dbg!(&unsigned_withdrawal_transaction_bytes); - - let unsigned_withdrawal_transaction_bytes = unsigned_withdrawal_transaction_bytes?; + )?; self.block_execution_context .replace(Some(block_execution_context)); @@ -168,7 +164,7 @@ impl TenderdashAbci for Platform { ), ))?; - self.pool_withdrawals_into_transactions(block_execution_context, transaction)?; + self.pool_withdrawals_into_transactions_queue(block_execution_context, transaction)?; // Process fees let process_block_fees_result = self.process_block_fees( diff --git a/packages/rs-drive-abci/src/config.rs b/packages/rs-drive-abci/src/config.rs index 1e6d51dd4a1..ca4c008f3e3 100644 --- a/packages/rs-drive-abci/src/config.rs +++ b/packages/rs-drive-abci/src/config.rs @@ -1,15 +1,20 @@ use drive::drive::config::DriveConfig; -/// Configuration for Dash Core related things -pub struct CoreConfig { +pub struct CoreRpcConfig { /// Core RPC client url - pub rpc_url: String, + pub url: String, /// Core RPC client username - pub rpc_username: String, + pub username: String, /// Core RPC client password - pub rpc_password: String, + pub password: String, +} + +/// Configuration for Dash Core related things +pub struct CoreConfig { + /// Core RPC config + pub rpc: CoreRpcConfig, } /// Platform configuration @@ -26,9 +31,11 @@ impl Default for PlatformConfig { Self { drive: None, core: CoreConfig { - rpc_url: "127.0.0.1".to_owned(), - rpc_username: "".to_owned(), - rpc_password: "".to_owned(), + rpc: CoreRpcConfig { + url: "127.0.0.1".to_owned(), + username: "".to_owned(), + password: "".to_owned(), + }, }, } } diff --git a/packages/rs-drive-abci/src/identity_credit_withdrawal/mod.rs b/packages/rs-drive-abci/src/identity_credit_withdrawal/mod.rs index 03f30e1e8be..596e15f5b81 100644 --- a/packages/rs-drive-abci/src/identity_credit_withdrawal/mod.rs +++ b/packages/rs-drive-abci/src/identity_credit_withdrawal/mod.rs @@ -287,7 +287,7 @@ impl Platform { } /// Pool withdrawal documents into transactions - pub fn pool_withdrawals_into_transactions( + pub fn pool_withdrawals_into_transactions_queue( &self, block_execution_context: &BlockExecutionContext, transaction: TransactionArg, @@ -709,7 +709,7 @@ mod tests { ); platform - .pool_withdrawals_into_transactions( + .pool_withdrawals_into_transactions_queue( &BlockExecutionContext { block_info: BlockInfo { block_height: 1, diff --git a/packages/rs-drive-abci/src/platform.rs b/packages/rs-drive-abci/src/platform.rs index e40ce21f5c1..97f7646ead4 100644 --- a/packages/rs-drive-abci/src/platform.rs +++ b/packages/rs-drive-abci/src/platform.rs @@ -71,9 +71,9 @@ impl Platform { let core_rpc: Box = Box::new( DefaultCoreRPC::open( - config.core.rpc_url, - config.core.rpc_username, - config.core.rpc_password, + config.core.rpc.url, + config.core.rpc.username, + config.core.rpc.password, ) .map_err(|e| { dbg!(e); diff --git a/packages/rs-drive-nodejs/src/lib.rs b/packages/rs-drive-nodejs/src/lib.rs index c52f9635f4d..c91152b1ac3 100644 --- a/packages/rs-drive-nodejs/src/lib.rs +++ b/packages/rs-drive-nodejs/src/lib.rs @@ -1,7 +1,7 @@ mod converter; mod fee; -use drive_abci::config::{CoreConfig, PlatformConfig}; +use drive_abci::config::{CoreConfig, CoreRpcConfig, PlatformConfig}; use std::num::ParseIntError; use std::ops::Deref; use std::{option::Option::None, path::Path, sync::mpsc, thread}; @@ -66,10 +66,11 @@ impl PlatformWrapper { let drive_config: Handle = platform_config.get(cx, "drive")?; let core_config: Handle = platform_config.get(cx, "core")?; + let core_rpc_config: Handle = core_config.get(cx, "rpc")?; - let js_core_rpc_url: Handle = core_config.get(cx, "rpcUrl")?; - let js_core_rpc_username: Handle = core_config.get(cx, "rpcUsername")?; - let js_core_rpc_password: Handle = core_config.get(cx, "rpcPassword")?; + let js_core_rpc_url: Handle = core_rpc_config.get(cx, "url")?; + let js_core_rpc_username: Handle = core_rpc_config.get(cx, "username")?; + let js_core_rpc_password: Handle = core_rpc_config.get(cx, "password")?; let core_rpc_url = js_core_rpc_url.value(cx); let core_rpc_username = js_core_rpc_username.value(cx); @@ -114,9 +115,11 @@ impl PlatformWrapper { }; let core_config = CoreConfig { - rpc_url: core_rpc_url, - rpc_username: core_rpc_username, - rpc_password: core_rpc_password, + rpc: CoreRpcConfig { + url: core_rpc_url, + username: core_rpc_username, + password: core_rpc_password, + }, }; let platform_config = PlatformConfig { diff --git a/packages/rs-drive-nodejs/test/Drive.spec.js b/packages/rs-drive-nodejs/test/Drive.spec.js index 8a04ea7d0ad..eb526dad207 100644 --- a/packages/rs-drive-nodejs/test/Drive.spec.js +++ b/packages/rs-drive-nodejs/test/Drive.spec.js @@ -44,9 +44,11 @@ describe('Drive', function main() { dataContractsBlockCacheSize: 500, }, core: { - rpcUrl: '127.0.0.1', - rpcUsername: '', - rpcPassword: '', + rpc: { + url: '127.0.0.1', + username: '', + password: '', + }, }, }); diff --git a/packages/rs-drive-nodejs/test/GroveDB.spec.js b/packages/rs-drive-nodejs/test/GroveDB.spec.js index 1b285897eaf..fb7810f69d5 100644 --- a/packages/rs-drive-nodejs/test/GroveDB.spec.js +++ b/packages/rs-drive-nodejs/test/GroveDB.spec.js @@ -24,9 +24,11 @@ describe('GroveDB', () => { dataContractsBlockCacheSize: 500, }, core: { - rpcUrl: '127.0.0.1', - rpcUsername: '', - rpcPassword: '', + rpc: { + url: '127.0.0.1', + username: '', + password: '', + }, }, }); From 821545f46839e3dc174f225d1f3dd2b5a3ab4636 Mon Sep 17 00:00:00 2001 From: Djavid Gabibyan Date: Fri, 6 Jan 2023 12:15:46 +0500 Subject: [PATCH 057/170] chore: wip --- .../src/identity_credit_withdrawal/mod.rs | 40 +++++++++++-------- .../withdrawals/withdrawal_transactions.rs | 15 +++---- 2 files changed, 32 insertions(+), 23 deletions(-) diff --git a/packages/rs-drive-abci/src/identity_credit_withdrawal/mod.rs b/packages/rs-drive-abci/src/identity_credit_withdrawal/mod.rs index 596e15f5b81..886e82645fd 100644 --- a/packages/rs-drive-abci/src/identity_credit_withdrawal/mod.rs +++ b/packages/rs-drive-abci/src/identity_credit_withdrawal/mod.rs @@ -25,6 +25,7 @@ use crate::{ }; const WITHDRAWAL_TRANSACTIONS_QUERY_LIMIT: u16 = 16; +const NUMBER_OF_BLOCKS_BEFORE_EXPIRED: u64 = 48; impl Platform { /// Update statuses for broadcasted withdrawals @@ -74,34 +75,41 @@ impl Platform { let mut drive_operations: Vec = vec![]; for document in broadcasted_documents.iter_mut() { - let transaction_sign_height = + let transaction_sign_height = document + .get_data() + .get_u64("transactionSignHeight") + .map_err(|_| { + Error::Execution(ExecutionError::CorruptedCodeExecution( + "Can't get transactionSignHeight from withdrawal document", + )) + })?; + + let transaction_id_bytes = document - .data - .get_u64("transactionSignHeight") + .get_data() + .get_bytes("transactionId") .map_err(|_| { Error::Execution(ExecutionError::CorruptedCodeExecution( - "Can't get transactionSignHeight from withdrawal document", + "Can't get transactionId from withdrawal document", )) })?; - let transaction_id_bytes = document.data.get_bytes("transactionId").map_err(|_| { - Error::Execution(ExecutionError::CorruptedCodeExecution( - "Can't get transactionId from withdrawal document", - )) - })?; - let transaction_id = hex::encode(transaction_id_bytes); - let transaction_index = document.data.get_u64("transactionIndex").map_err(|_| { - Error::Execution(ExecutionError::CorruptedCodeExecution( - "Can't get transactionIdex from withdrawal document", - )) - })?; + let transaction_index = + document + .get_data() + .get_u64("transactionIndex") + .map_err(|_| { + Error::Execution(ExecutionError::CorruptedCodeExecution( + "Can't get transactionIdex from withdrawal document", + )) + })?; if core_transactions.contains(&transaction_id) || block_execution_context.block_info.core_chain_locked_height - transaction_sign_height - > 48 + > NUMBER_OF_BLOCKS_BEFORE_EXPIRED { let status = if core_transactions.contains(&transaction_id) { withdrawals_contract::statuses::COMPLETE diff --git a/packages/rs-drive/src/drive/identity/withdrawals/withdrawal_transactions.rs b/packages/rs-drive/src/drive/identity/withdrawals/withdrawal_transactions.rs index ce11b700e7c..08b919329d2 100644 --- a/packages/rs-drive/src/drive/identity/withdrawals/withdrawal_transactions.rs +++ b/packages/rs-drive/src/drive/identity/withdrawals/withdrawal_transactions.rs @@ -34,23 +34,24 @@ impl Drive { self.fetch_latest_withdrawal_transaction_index(transaction)?; for (i, document) in documents.iter().enumerate() { - let output_script = document.data.get_bytes("outputScript").map_err(|_| { + let output_script = document.get_data().get_bytes("outputScript").map_err(|_| { Error::Drive(DriveError::CorruptedCodeExecution( "Can't get outputScript from withdrawal document", )) })?; - let amount = document.data.get_u64("amount").map_err(|_| { + let amount = document.get_data().get_u64("amount").map_err(|_| { Error::Drive(DriveError::CorruptedCodeExecution( "Can't get amount from withdrawal document", )) })?; - let core_fee_per_byte = document.data.get_u64("coreFeePerByte").map_err(|_| { - Error::Drive(DriveError::CorruptedCodeExecution( - "Can't get coreFeePerByte from withdrawal document", - )) - })?; + let core_fee_per_byte = + document.get_data().get_u64("coreFeePerByte").map_err(|_| { + Error::Drive(DriveError::CorruptedCodeExecution( + "Can't get coreFeePerByte from withdrawal document", + )) + })?; let state_transition_size = 190; From 2010642892a4994dfef9c9133dd78df216a7f618 Mon Sep 17 00:00:00 2001 From: Djavid Gabibyan Date: Fri, 6 Jan 2023 16:48:07 +0500 Subject: [PATCH 058/170] chore: wip --- Cargo.lock | 1 + packages/rs-drive-abci/Cargo.toml | 3 + packages/rs-drive-abci/src/config.rs | 1 + .../src/identity_credit_withdrawal/mod.rs | 415 ++++++++++++------ .../rs-drive/src/drive/document/convert.rs | 25 ++ .../rs-drive/src/drive/document/helpers.rs | 292 ------------ packages/rs-drive/src/drive/document/mod.rs | 4 +- .../rs-drive/src/drive/document/update.rs | 40 +- .../src/drive/identity/withdrawals/queue.rs | 6 +- .../identity/withdrawals/withdrawal_status.rs | 4 +- .../withdrawals/withdrawal_transactions.rs | 239 ++-------- 11 files changed, 402 insertions(+), 628 deletions(-) create mode 100644 packages/rs-drive/src/drive/document/convert.rs delete mode 100644 packages/rs-drive/src/drive/document/helpers.rs diff --git a/Cargo.lock b/Cargo.lock index 0de286b81b3..cbffa793492 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -971,6 +971,7 @@ dependencies = [ "dpp", "drive", "hex", + "itertools", "rand 0.8.5", "rust_decimal", "rust_decimal_macros", diff --git a/packages/rs-drive-abci/Cargo.toml b/packages/rs-drive-abci/Cargo.toml index cc2bf2a0f46..b764381e143 100644 --- a/packages/rs-drive-abci/Cargo.toml +++ b/packages/rs-drive-abci/Cargo.toml @@ -23,5 +23,8 @@ dpp = { path = "../rs-dpp", features = ["fixtures-and-mocks"]} rust_decimal = "1.2.5" rust_decimal_macros = "1.25.0" +[dev-dependencies] +itertools = { version = "0.10.5" } + [features] fixtures-and-mocks = [] diff --git a/packages/rs-drive-abci/src/config.rs b/packages/rs-drive-abci/src/config.rs index ca4c008f3e3..8da2e027bd7 100644 --- a/packages/rs-drive-abci/src/config.rs +++ b/packages/rs-drive-abci/src/config.rs @@ -1,5 +1,6 @@ use drive::drive::config::DriveConfig; +/// Configuration for Dash Core RPC client pub struct CoreRpcConfig { /// Core RPC client url pub url: String, diff --git a/packages/rs-drive-abci/src/identity_credit_withdrawal/mod.rs b/packages/rs-drive-abci/src/identity_credit_withdrawal/mod.rs index 886e82645fd..90011848292 100644 --- a/packages/rs-drive-abci/src/identity_credit_withdrawal/mod.rs +++ b/packages/rs-drive-abci/src/identity_credit_withdrawal/mod.rs @@ -1,16 +1,25 @@ +use std::collections::HashMap; + use dashcore::{ - blockdata::transaction::special_transaction::asset_unlock::request_info::AssetUnlockRequestInfo, - hashes::Hash, QuorumHash, + blockdata::transaction::special_transaction::asset_unlock::{ + request_info::AssetUnlockRequestInfo, + unqualified_asset_unlock::{AssetUnlockBasePayload, AssetUnlockBaseTransactionInfo}, + }, + consensus::Encodable, + hashes::Hash, + QuorumHash, Script, TxOut, }; use dpp::{ contracts::withdrawals_contract, data_contract::extra::DriveContractExt, + identity::convert_credits_to_satoshi, prelude::{Document, Identifier}, util::{hash, json_value::JsonValueExt, string_encoding::Encoding}, }; use drive::{ drive::{ batch::DriveOperationType, block_info::BlockInfo, + document::convert_dpp_documents_to_drive_documents, identity::withdrawals::paths::WithdrawalTransaction, }, fee_pools::epochs::Epoch, @@ -35,17 +44,18 @@ impl Platform { block_execution_context: &BlockExecutionContext, transaction: TransactionArg, ) -> Result<(), Error> { + let data_contract_id = Identifier::from_string( + &withdrawals_contract::system_ids().contract_id, + Encoding::Base58, + ) + .map_err(|_| { + Error::Execution(ExecutionError::CorruptedCodeExecution( + "Can't create withdrawals id identifier from string", + )) + })?; + let (_, maybe_data_contract) = self.drive.get_contract_with_fetch_info( - Identifier::from_string( - &withdrawals_contract::system_ids().contract_id, - Encoding::Base58, - ) - .map_err(|_| { - Error::Execution(ExecutionError::CorruptedCodeExecution( - "Can't create withdrawals id identifier from string", - )) - })? - .to_buffer(), + data_contract_id.to_buffer(), Some(&Epoch::new( block_execution_context.epoch_info.current_epoch_index, )), @@ -122,29 +132,25 @@ impl Platform { withdrawals_contract::statuses::EXPIRED }; - self.drive.update_document_data( - document, - &block_info, - |document: &mut Document| -> Result<&mut Document, drive::error::Error> { - document - .set("status", JsonValue::Number(Number::from(status))) - .map_err(|_| { - drive::error::Error::Drive( - drive::error::drive::DriveError::CorruptedCodeExecution( - "Can't update document field: status", - ), - ) - })?; - - Ok(document) - }, - )?; + document + .set("status", JsonValue::Number(Number::from(status))) + .map_err(|_| { + Error::Execution(ExecutionError::CorruptedCodeExecution( + "Can't update document field: status", + )) + })?; + + document.updated_at = Some(block_info.time_ms.try_into().map_err(|_| { + Error::Execution(ExecutionError::CorruptedCodeExecution( + "Can't convert u64 block time to i64 updated_at", + )) + })?); + document.increment_revision(); } } - let drive_documents = self - .drive - .convert_dpp_documents_to_drive_documents(broadcasted_documents.iter())?; + let drive_documents = + convert_dpp_documents_to_drive_documents(broadcasted_documents.iter())?; self.drive.add_update_multiple_documents_operations( &drive_documents, @@ -175,17 +181,18 @@ impl Platform { validator_set_quorum_hash: [u8; 32], transaction: TransactionArg, ) -> Result>, Error> { + let data_contract_id = Identifier::from_string( + &withdrawals_contract::system_ids().contract_id, + Encoding::Base58, + ) + .map_err(|_| { + Error::Execution(ExecutionError::CorruptedCodeExecution( + "Can't create withdrawals id identifier from string", + )) + })?; + let (_, maybe_data_contract) = self.drive.get_contract_with_fetch_info( - Identifier::from_string( - &withdrawals_contract::system_ids().contract_id, - Encoding::Base58, - ) - .map_err(|_| { - Error::Execution(ExecutionError::CorruptedCodeExecution( - "Can't create withdrawals id identifier from string", - )) - })? - .to_buffer(), + data_contract_id.to_buffer(), Some(&Epoch::new( block_execution_context.epoch_info.current_epoch_index, )), @@ -237,33 +244,34 @@ impl Platform { .drive .find_document_by_transaction_id(&original_transaction_id, transaction)?; - self.drive - .update_document_data(&mut document, &block_info, |doc| { - doc.set( - "transactionId", - JsonValue::Array( - update_transaction_id - .iter() - .map(|byte| JsonValue::Number(Number::from(*byte))) - .collect(), - ), - ) - .map_err(|_| { - drive::error::Error::Drive( - drive::error::drive::DriveError::CorruptedCodeExecution( - "Can't set document field: transactionId", - ), - ) - })?; - - Ok(doc) + document + .set( + "transactionId", + JsonValue::Array( + update_transaction_id + .iter() + .map(|byte| JsonValue::Number(Number::from(*byte))) + .collect(), + ), + ) + .map_err(|_| { + Error::Execution(ExecutionError::CorruptedCodeExecution( + "Can't set document field: transactionId", + )) })?; + document.updated_at = Some(block_info.time_ms.try_into().map_err(|_| { + Error::Execution(ExecutionError::CorruptedCodeExecution( + "Can't convert u64 block time to i64 updated_at", + )) + })?); + document.increment_revision(); + Ok((bytes_buffer, document)) }) .collect::, Document)>, Error>>()?; - let drive_documents = self.drive.convert_dpp_documents_to_drive_documents( + let drive_documents = convert_dpp_documents_to_drive_documents( transactions_and_documents .iter() .map(|(_, document)| document), @@ -300,17 +308,18 @@ impl Platform { block_execution_context: &BlockExecutionContext, transaction: TransactionArg, ) -> Result<(), Error> { + let data_contract_id = Identifier::from_string( + &withdrawals_contract::system_ids().contract_id, + Encoding::Base58, + ) + .map_err(|_| { + Error::Execution(ExecutionError::CorruptedCodeExecution( + "Can't create withdrawals id identifier from string", + )) + })?; + let (_, maybe_data_contract) = self.drive.get_contract_with_fetch_info( - Identifier::from_string( - &withdrawals_contract::system_ids().contract_id, - Encoding::Base58, - ) - .map_err(|_| { - Error::Execution(ExecutionError::CorruptedCodeExecution( - "Can't create withdrawals id identifier from string", - )) - })? - .to_buffer(), + data_contract_id.to_buffer(), Some(&Epoch::new( block_execution_context.epoch_info.current_epoch_index, )), @@ -326,9 +335,8 @@ impl Platform { transaction, )?; - let withdrawal_transactions = self - .drive - .build_withdrawal_transactions_from_documents(&documents, transaction)?; + let withdrawal_transactions = + self.build_withdrawal_transactions_from_documents(&documents, transaction)?; let block_info = BlockInfo { time_ms: block_execution_context.block_info.block_time_ms, @@ -342,66 +350,43 @@ impl Platform { let transaction_id = hash::hash(withdrawal_transactions.get(&document.id).unwrap().1.clone()); - self.drive.update_document_data( - document, - &block_info, - |document: &mut Document| -> Result<&mut Document, drive::error::Error> { - document - .set( - "transactionId", - JsonValue::Array( - transaction_id - .clone() - .into_iter() - .map(|byte| JsonValue::Number(Number::from(byte))) - .collect(), - ), - ) - .map_err(|_| { - drive::error::Error::Drive( - drive::error::drive::DriveError::CorruptedCodeExecution( - "Can't update document field: transactionId", - ), - ) - })?; - - document - .set( - "status", - JsonValue::Number(Number::from(withdrawals_contract::statuses::POOLED)), - ) - .map_err(|_| { - drive::error::Error::Drive( - drive::error::drive::DriveError::CorruptedCodeExecution( - "Can't update document field: status", - ), - ) - })?; - - Ok(document) - }, - )?; - } + document + .set( + "transactionId", + JsonValue::Array( + transaction_id + .clone() + .into_iter() + .map(|byte| JsonValue::Number(Number::from(byte))) + .collect(), + ), + ) + .map_err(|_| { + Error::Execution(ExecutionError::CorruptedCodeExecution( + "Can't update document field: transactionId", + )) + })?; - let drive_documents = documents - .iter() - .map(|document| { - drive::contract::document::Document::from_cbor( - &document.to_cbor().map_err(|_| { - Error::Execution(ExecutionError::CorruptedCodeExecution( - "Can't fetch withdrawal data contract", - )) - })?, - None, - None, + document + .set( + "status", + JsonValue::Number(Number::from(withdrawals_contract::statuses::POOLED)), ) .map_err(|_| { Error::Execution(ExecutionError::CorruptedCodeExecution( - "Can't fetch withdrawal data contract", + "Can't update document field: status", )) - }) - }) - .collect::, Error>>()?; + })?; + + document.updated_at = Some(block_info.time_ms.try_into().map_err(|_| { + Error::Execution(ExecutionError::CorruptedCodeExecution( + "Can't convert u64 block time to i64 updated_at", + )) + })?); + document.increment_revision(); + } + + let drive_documents = convert_dpp_documents_to_drive_documents(documents.iter())?; self.drive.add_update_multiple_documents_operations( &drive_documents, @@ -476,6 +461,82 @@ impl Platform { Ok(tx_hashes) } + + /// Build list of Core transactions from withdrawal documents + pub fn build_withdrawal_transactions_from_documents( + &self, + documents: &[Document], + transaction: TransactionArg, + ) -> Result, Error> { + let mut withdrawals: HashMap = HashMap::new(); + + let latest_withdrawal_index = self + .drive + .fetch_latest_withdrawal_transaction_index(transaction)?; + + for (i, document) in documents.iter().enumerate() { + let output_script = document.get_data().get_bytes("outputScript").map_err(|_| { + Error::Execution(ExecutionError::CorruptedCodeExecution( + "Can't get outputScript from withdrawal document", + )) + })?; + + let amount = document.get_data().get_u64("amount").map_err(|_| { + Error::Execution(ExecutionError::CorruptedCodeExecution( + "Can't get amount from withdrawal document", + )) + })?; + + let core_fee_per_byte = + document.get_data().get_u64("coreFeePerByte").map_err(|_| { + Error::Execution(ExecutionError::CorruptedCodeExecution( + "Can't get coreFeePerByte from withdrawal document", + )) + })?; + + let state_transition_size = 190; + + let output_script: Script = Script::from(output_script); + + let tx_out = TxOut { + value: convert_credits_to_satoshi(amount), + script_pubkey: output_script, + }; + + let transaction_index = latest_withdrawal_index + i as u64; + + let withdrawal_transaction = AssetUnlockBaseTransactionInfo { + version: 1, + lock_time: 0, + output: vec![tx_out], + base_payload: AssetUnlockBasePayload { + version: 1, + index: transaction_index, + fee: (state_transition_size * core_fee_per_byte * 1000) as u32, + }, + }; + + let mut transaction_buffer: Vec = vec![]; + + withdrawal_transaction + .consensus_encode(&mut transaction_buffer) + .map_err(|_| { + Error::Execution(ExecutionError::CorruptedCodeExecution( + "Can't consensus encode a withdrawal transaction", + )) + })?; + + withdrawals.insert( + document.id.clone(), + ( + transaction_index.to_be_bytes().to_vec(), + transaction_buffer.clone(), + ), + ); + } + + Ok(withdrawals) + } } #[cfg(test)] @@ -836,4 +897,96 @@ mod tests { assert_eq!(transactions, ["1", "2"]); } } + + mod build_withdrawal_transactions_from_documents { + use dpp::identity::state_transition::identity_credit_withdrawal_transition::Pooling; + use drive::drive::identity::withdrawals::paths::WithdrawalTransaction; + use itertools::Itertools; + + use super::*; + + #[test] + fn test_build() { + let platform = setup_platform_with_initial_state_structure(); + + let transaction = platform.drive.grove.start_transaction(); + + let data_contract = get_withdrawals_data_contract_fixture(None); + + setup_system_data_contract(&platform.drive, &data_contract, Some(&transaction)); + + let document_1 = get_withdrawal_document_fixture( + &data_contract, + json!({ + "amount": 1000, + "coreFeePerByte": 1, + "pooling": Pooling::Never, + "outputScript": (0..23).collect::>(), + "status": withdrawals_contract::statuses::POOLED, + "transactionIndex": 1, + }), + ); + + setup_document( + &platform.drive, + &document_1, + &data_contract, + Some(&transaction), + ); + + let document_2 = get_withdrawal_document_fixture( + &data_contract, + json!({ + "amount": 1000, + "coreFeePerByte": 1, + "pooling": Pooling::Never, + "outputScript": (0..23).collect::>(), + "status": withdrawals_contract::statuses::POOLED, + "transactionIndex": 2, + }), + ); + + setup_document( + &platform.drive, + &document_2, + &data_contract, + Some(&transaction), + ); + + let documents = vec![document_1, document_2]; + + let transactions = platform + .build_withdrawal_transactions_from_documents(&documents, Some(&transaction)) + .expect("to build transactions from documents"); + + assert_eq!( + transactions + .values() + .cloned() + .sorted() + .collect::>(), + vec![ + ( + vec![0, 0, 0, 0, 0, 0, 0, 0], + vec![ + 1, 0, 9, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 23, 0, 1, 2, 3, 4, 5, 6, 7, + 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, 0, 0, 0, 192, 206, 2, 0, + ], + ), + ( + vec![0, 0, 0, 0, 0, 0, 0, 1], + vec![ + 1, 0, 9, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 23, 0, 1, 2, 3, 4, 5, 6, 7, + 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, 192, 206, 2, 0, + ], + ), + ] + .into_iter() + .sorted() + .collect::>(), + ); + } + } } diff --git a/packages/rs-drive/src/drive/document/convert.rs b/packages/rs-drive/src/drive/document/convert.rs new file mode 100644 index 00000000000..566b4c1b91e --- /dev/null +++ b/packages/rs-drive/src/drive/document/convert.rs @@ -0,0 +1,25 @@ +use dpp::prelude::Document; + +use crate::error::{drive::DriveError, Error}; + +/// Helper function to convert DPP documents to Drive documents +pub fn convert_dpp_documents_to_drive_documents<'a, I>( + dpp_documents: I, +) -> Result, Error> +where + I: Iterator, +{ + dpp_documents + .map(|document| { + crate::contract::document::Document::from_cbor( + &document.to_cbor().map_err(|_| { + Error::Drive(DriveError::CorruptedCodeExecution( + "Can't convert dpp document to cbor", + )) + })?, + None, + None, + ) + }) + .collect::, Error>>() +} diff --git a/packages/rs-drive/src/drive/document/helpers.rs b/packages/rs-drive/src/drive/document/helpers.rs deleted file mode 100644 index 294a11d84e0..00000000000 --- a/packages/rs-drive/src/drive/document/helpers.rs +++ /dev/null @@ -1,292 +0,0 @@ -use dpp::{ - contracts::withdrawals_contract, - data_contract::extra::{common, DocumentType, DriveContractExt}, - prelude::{DataContract, Document, Identifier}, - util::string_encoding::Encoding, -}; -use grovedb::TransactionArg; -use serde_json::{json, Number, Value as JsonValue}; - -use crate::{ - drive::{ - batch::{ - drive_op_batch::{ - DocumentOperation, DocumentOperationsForContractDocumentType, UpdateOperationInfo, - }, - DocumentOperationType, DriveOperationType, - }, - block_info::BlockInfo, - Drive, - }, - error::{drive::DriveError, Error}, -}; - -impl Drive { - /// Helper function to avoid boilerplate of calling an update - pub fn update_document_data<'a, F>( - &'a self, - document: &mut Document, - block_info: &BlockInfo, - update_fn: F, - ) -> Result<(), Error> - where - F: Fn(&mut Document) -> Result<&mut Document, Error>, - { - let document = update_fn(document)?; - - document.updated_at = Some(block_info.time_ms.try_into().map_err(|_| { - Error::Drive(DriveError::CorruptedCodeExecution( - "Can't convert u64 block time to i64 updated_at", - )) - })?); - document.increment_revision(); - - Ok(()) - } - - /// Helper function to find document by original transactionId - /// and update document transactionId to new one - pub fn find_and_update_document_by_transaction_id( - &self, - original_transaction_id: &[u8], - update_transaction_id: &[u8], - block_info: &BlockInfo, - transaction: TransactionArg, - ) -> Result<(), Error> { - let data_contract_id = Identifier::from_string( - &withdrawals_contract::system_ids().contract_id, - Encoding::Base58, - ) - .map_err(|_| { - Error::Drive(DriveError::CorruptedCodeExecution( - "Can't create withdrawals id identifier from string", - )) - })?; - - let query_value = json!({ - "where": [ - ["transactionId", "==", original_transaction_id], - ["status", "==", withdrawals_contract::statuses::POOLED], - ], - }); - - let query_cbor = common::value_to_cbor(query_value, None); - - let (documents, _, _) = self.query_documents( - &query_cbor, - data_contract_id.to_buffer(), - withdrawals_contract::types::WITHDRAWAL, - None, - transaction, - )?; - - let mut documents = documents - .into_iter() - .map(|document_cbor| { - Document::from_cbor(document_cbor).map_err(|_| { - Error::Drive(DriveError::CorruptedCodeExecution( - "Can't create a document from cbor", - )) - }) - }) - .collect::, Error>>()?; - - let document = - documents - .get_mut(0) - .ok_or(Error::Drive(DriveError::CorruptedCodeExecution( - "Document was not found by transactionId", - )))?; - - self.update_document_data( - document, - block_info, - |document: &mut Document| -> Result<&mut Document, Error> { - document - .set( - "transactionId", - JsonValue::Array( - update_transaction_id - .iter() - .map(|byte| JsonValue::Number(Number::from(*byte))) - .collect(), - ), - ) - .map_err(|_| { - Error::Drive(DriveError::CorruptedCodeExecution( - "Can't set document field: transactionId", - )) - })?; - - Ok(document) - }, - ) - } - - /// Add update multiple documents operations - pub fn add_update_multiple_documents_operations<'a>( - &self, - documents: &'a [crate::contract::document::Document], - data_contract: &'a DataContract, - document_type: &'a DocumentType, - drive_operations: &mut Vec>, - ) { - let operations: Vec = documents - .iter() - .map(|document| { - DocumentOperation::UpdateOperation(UpdateOperationInfo { - document, - serialized_document: None, - owner_id: None, - storage_flags: None, - }) - }) - .collect(); - - if !operations.is_empty() { - drive_operations.push(DriveOperationType::DocumentOperation( - DocumentOperationType::MultipleDocumentOperationsForSameContractDocumentType { - document_operations: DocumentOperationsForContractDocumentType { - operations, - contract: data_contract, - document_type, - }, - }, - )); - } - } - - /// Helper function to convert DPP documents to Drive documents - pub fn convert_dpp_documents_to_drive_documents<'a, I>( - &self, - dpp_documents: I, - ) -> Result, Error> - where - I: Iterator, - { - dpp_documents - .map(|document| { - crate::contract::document::Document::from_cbor( - &document.to_cbor().map_err(|_| { - Error::Drive(DriveError::CorruptedCodeExecution( - "Can't convert dpp document to cbor", - )) - })?, - None, - None, - ) - }) - .collect::, Error>>() - } -} - -// #[cfg(test)] -// mod tests { -// use dpp::{ -// contracts::withdrawals_contract, -// tests::fixtures::{get_withdrawal_document_fixture, get_withdrawals_data_contract_fixture}, -// }; -// use serde_json::json; - -// use crate::common::helpers::setup::{ -// setup_document, setup_drive_with_initial_state_structure, setup_system_data_contract, -// }; - -// use dpp::identity::state_transition::identity_credit_withdrawal_transition::Pooling; - -// use crate::{drive::block_info::BlockInfo, fee_pools::epochs::Epoch}; - -// mod update_document_transaction_id { - -// use super::*; - -// #[test] -// fn test_transaction_id_updated() { -// let drive = setup_drive_with_initial_state_structure(); - -// let transaction = drive.grove.start_transaction(); - -// let data_contract = get_withdrawals_data_contract_fixture(None); - -// setup_system_data_contract(&drive, &data_contract, Some(&transaction)); - -// let original_transaction_id: Vec = vec![ -// 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, -// 1, 1, 1, 1, -// ]; - -// let updated_transaction_id: Vec = vec![ -// 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, -// 2, 2, 2, 2, -// ]; - -// let document = get_withdrawal_document_fixture( -// &data_contract, -// json!({ -// "amount": 1000, -// "coreFeePerByte": 1, -// "pooling": Pooling::Never, -// "outputScript": (0..23).collect::>(), -// "status": withdrawals_contract::statuses::POOLED, -// "transactionIndex": 1, -// "transactionId": original_transaction_id, -// }), -// ); - -// setup_document(&drive, &document, &data_contract, Some(&transaction)); - -// let block_info = BlockInfo { -// time_ms: 1, -// height: 1, -// epoch: Epoch::new(1), -// }; - -// let mut drive_operations = vec![]; -// let mut result_operations = vec![]; - -// drive -// .find_and_update_document_by_transaction_id( -// &original_transaction_id, -// &updated_transaction_id, -// &block_info, -// &mut drive_operations, -// Some(&transaction), -// ) -// .expect("to update transactionId"); - -// dbg!(&drive_operations); - -// drive -// .apply_batch_drive_operations( -// None, -// Some(&transaction), -// drive_operations, -// &mut result_operations, -// ) -// .expect("to apply batch drive operations"); - -// let updated_documents = drive -// .fetch_withdrawal_documents_by_status( -// withdrawals_contract::statuses::POOLED, -// Some(&transaction), -// ) -// .expect("to fetch withdrawal documents"); - -// assert_eq!(updated_documents.len(), 1); - -// let stored_transaction_id: Vec = updated_documents -// .get(0) -// .unwrap() -// .data -// .get("transactionId") -// .unwrap() -// .as_array() -// .unwrap() -// .iter() -// .map(|byte| byte.as_u64().unwrap() as u8) -// .collect(); - -// assert_eq!(stored_transaction_id, updated_transaction_id); -// } -// } -// } diff --git a/packages/rs-drive/src/drive/document/mod.rs b/packages/rs-drive/src/drive/document/mod.rs index 675a51781f7..66e722e14d8 100644 --- a/packages/rs-drive/src/drive/document/mod.rs +++ b/packages/rs-drive/src/drive/document/mod.rs @@ -43,12 +43,14 @@ use grovedb::batch::KeyInfoPath; use grovedb::reference_path::ReferencePathType::UpstreamRootHeightReference; use grovedb::Element; +mod convert; mod delete; mod estimation_costs; -mod helpers; mod insert; mod update; +pub use convert::*; + /// Returns the path to a contract document type. pub(crate) fn contract_document_type_path<'a>( contract_id: &'a [u8], diff --git a/packages/rs-drive/src/drive/document/update.rs b/packages/rs-drive/src/drive/document/update.rs index 7dbbe69e697..c716592c49a 100644 --- a/packages/rs-drive/src/drive/document/update.rs +++ b/packages/rs-drive/src/drive/document/update.rs @@ -41,6 +41,10 @@ use grovedb::{Element, EstimatedLayerInformation, TransactionArg}; use crate::contract::document::Document; use crate::contract::Contract; +use crate::drive::batch::drive_op_batch::{ + DocumentOperation, DocumentOperationsForContractDocumentType, UpdateOperationInfo, +}; +use crate::drive::batch::{DocumentOperationType, DriveOperationType}; use crate::drive::defaults::CONTRACT_DOCUMENTS_PATH_HEIGHT; use crate::drive::document::{ contract_document_type_path, @@ -71,7 +75,8 @@ use crate::drive::grove_operations::{ QueryType, }; use crate::fee::result::FeeResult; -use dpp::data_contract::extra::DriveContractExt; +use dpp::data_contract::extra::{DocumentType, DriveContractExt}; +use dpp::prelude::DataContract; impl Drive { /// Updates a serialized document given a contract CBOR and returns the associated fee. @@ -633,6 +638,39 @@ impl Drive { } Ok(batch_operations) } + + /// Add update multiple documents operations + pub fn add_update_multiple_documents_operations<'a>( + &self, + documents: &'a [crate::contract::document::Document], + data_contract: &'a DataContract, + document_type: &'a DocumentType, + drive_operations: &mut Vec>, + ) { + let operations: Vec = documents + .iter() + .map(|document| { + DocumentOperation::UpdateOperation(UpdateOperationInfo { + document, + serialized_document: None, + owner_id: None, + storage_flags: None, + }) + }) + .collect(); + + if !operations.is_empty() { + drive_operations.push(DriveOperationType::DocumentOperation( + DocumentOperationType::MultipleDocumentOperationsForSameContractDocumentType { + document_operations: DocumentOperationsForContractDocumentType { + operations, + contract: data_contract, + document_type, + }, + }, + )); + } + } } #[cfg(test)] diff --git a/packages/rs-drive/src/drive/identity/withdrawals/queue.rs b/packages/rs-drive/src/drive/identity/withdrawals/queue.rs index 1257504e68a..543c6ad960a 100644 --- a/packages/rs-drive/src/drive/identity/withdrawals/queue.rs +++ b/packages/rs-drive/src/drive/identity/withdrawals/queue.rs @@ -7,11 +7,7 @@ use grovedb::{ use crate::{ drive::{ - batch::{ - drive_op_batch::{DriveOperationConverter, WithdrawalOperationType}, - DriveOperationType, - }, - block_info::BlockInfo, + batch::{drive_op_batch::WithdrawalOperationType, DriveOperationType}, grove_operations::BatchDeleteApplyType, Drive, }, diff --git a/packages/rs-drive/src/drive/identity/withdrawals/withdrawal_status.rs b/packages/rs-drive/src/drive/identity/withdrawals/withdrawal_status.rs index 54bc5f798ea..6c49819d832 100644 --- a/packages/rs-drive/src/drive/identity/withdrawals/withdrawal_status.rs +++ b/packages/rs-drive/src/drive/identity/withdrawals/withdrawal_status.rs @@ -8,7 +8,7 @@ use grovedb::TransactionArg; use serde_json::json; use crate::{ - drive::{block_info::BlockInfo, Drive}, + drive::Drive, error::{drive::DriveError, Error}, }; @@ -198,4 +198,6 @@ mod tests { assert_eq!(documents.len(), 1); } } + + mod find_document_by_transaction_id {} } diff --git a/packages/rs-drive/src/drive/identity/withdrawals/withdrawal_transactions.rs b/packages/rs-drive/src/drive/identity/withdrawals/withdrawal_transactions.rs index 08b919329d2..e2ce9ea8e60 100644 --- a/packages/rs-drive/src/drive/identity/withdrawals/withdrawal_transactions.rs +++ b/packages/rs-drive/src/drive/identity/withdrawals/withdrawal_transactions.rs @@ -1,197 +1,42 @@ -use std::collections::HashMap; - -use dashcore::{ - blockdata::transaction::special_transaction::asset_unlock::unqualified_asset_unlock::{ - AssetUnlockBasePayload, AssetUnlockBaseTransactionInfo, - }, - consensus::Encodable, - Script, TxOut, -}; -use dpp::{ - identity::convert_credits_to_satoshi, - prelude::{Document, Identifier}, - util::json_value::JsonValueExt, -}; -use grovedb::TransactionArg; - -use crate::{ - drive::Drive, - error::{drive::DriveError, Error}, -}; - -use super::paths::WithdrawalTransaction; - -impl Drive { - /// Build list of Core transactions from withdrawal documents - pub fn build_withdrawal_transactions_from_documents( - &self, - documents: &[Document], - transaction: TransactionArg, - ) -> Result, Error> { - let mut withdrawals: HashMap = HashMap::new(); - - let latest_withdrawal_index = - self.fetch_latest_withdrawal_transaction_index(transaction)?; - - for (i, document) in documents.iter().enumerate() { - let output_script = document.get_data().get_bytes("outputScript").map_err(|_| { - Error::Drive(DriveError::CorruptedCodeExecution( - "Can't get outputScript from withdrawal document", - )) - })?; - - let amount = document.get_data().get_u64("amount").map_err(|_| { - Error::Drive(DriveError::CorruptedCodeExecution( - "Can't get amount from withdrawal document", - )) - })?; - - let core_fee_per_byte = - document.get_data().get_u64("coreFeePerByte").map_err(|_| { - Error::Drive(DriveError::CorruptedCodeExecution( - "Can't get coreFeePerByte from withdrawal document", - )) - })?; - - let state_transition_size = 190; - - let output_script: Script = Script::from(output_script); - - let tx_out = TxOut { - value: convert_credits_to_satoshi(amount), - script_pubkey: output_script, - }; - - let transaction_index = latest_withdrawal_index + i as u64; - - let withdrawal_transaction = AssetUnlockBaseTransactionInfo { - version: 1, - lock_time: 0, - output: vec![tx_out], - base_payload: AssetUnlockBasePayload { - version: 1, - index: transaction_index, - fee: (state_transition_size * core_fee_per_byte * 1000) as u32, - }, - }; - - let mut transaction_buffer: Vec = vec![]; - - withdrawal_transaction - .consensus_encode(&mut transaction_buffer) - .map_err(|_| { - Error::Drive(DriveError::CorruptedCodeExecution( - "Can't consensus encode a withdrawal transaction", - )) - })?; - - withdrawals.insert( - document.id.clone(), - ( - transaction_index.to_be_bytes().to_vec(), - transaction_buffer.clone(), - ), - ); - } - - Ok(withdrawals) - } -} - -#[cfg(test)] -mod tests { - use crate::common::helpers::setup::setup_drive_with_initial_state_structure; - - use serde_json::json; - - use dpp::{ - contracts::withdrawals_contract, - tests::fixtures::{get_withdrawal_document_fixture, get_withdrawals_data_contract_fixture}, - }; - - use crate::{ - common::helpers::setup::{setup_document, setup_system_data_contract}, - drive::identity::withdrawals::paths::WithdrawalTransaction, - }; - - mod build_withdrawal_transactions_from_documents { - use dpp::identity::state_transition::identity_credit_withdrawal_transition::Pooling; - use itertools::Itertools; - - use super::*; - - #[test] - fn test_build() { - let drive = setup_drive_with_initial_state_structure(); - - let transaction = drive.grove.start_transaction(); - - let data_contract = get_withdrawals_data_contract_fixture(None); - - setup_system_data_contract(&drive, &data_contract, Some(&transaction)); - - let document_1 = get_withdrawal_document_fixture( - &data_contract, - json!({ - "amount": 1000, - "coreFeePerByte": 1, - "pooling": Pooling::Never, - "outputScript": (0..23).collect::>(), - "status": withdrawals_contract::statuses::POOLED, - "transactionIndex": 1, - }), - ); - - setup_document(&drive, &document_1, &data_contract, Some(&transaction)); - - let document_2 = get_withdrawal_document_fixture( - &data_contract, - json!({ - "amount": 1000, - "coreFeePerByte": 1, - "pooling": Pooling::Never, - "outputScript": (0..23).collect::>(), - "status": withdrawals_contract::statuses::POOLED, - "transactionIndex": 2, - }), - ); - - setup_document(&drive, &document_2, &data_contract, Some(&transaction)); - - let documents = vec![document_1, document_2]; - - let transactions = drive - .build_withdrawal_transactions_from_documents(&documents, Some(&transaction)) - .expect("to build transactions from documents"); - - assert_eq!( - transactions - .values() - .cloned() - .sorted() - .collect::>(), - vec![ - ( - vec![0, 0, 0, 0, 0, 0, 0, 0], - vec![ - 1, 0, 9, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 23, 0, 1, 2, 3, 4, 5, 6, 7, - 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 0, 0, 0, 0, - 1, 0, 0, 0, 0, 0, 0, 0, 0, 192, 206, 2, 0, - ], - ), - ( - vec![0, 0, 0, 0, 0, 0, 0, 1], - vec![ - 1, 0, 9, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 23, 0, 1, 2, 3, 4, 5, 6, 7, - 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 0, 0, 0, 0, - 1, 1, 0, 0, 0, 0, 0, 0, 0, 192, 206, 2, 0, - ], - ), - ] - .into_iter() - .sorted() - .collect::>(), - ); - } - } -} +// use std::collections::HashMap; + +// use dashcore::{ +// blockdata::transaction::special_transaction::asset_unlock::unqualified_asset_unlock::{ +// AssetUnlockBasePayload, AssetUnlockBaseTransactionInfo, +// }, +// consensus::Encodable, +// Script, TxOut, +// }; +// use dpp::{ +// identity::convert_credits_to_satoshi, +// prelude::{Document, Identifier}, +// util::json_value::JsonValueExt, +// }; +// use grovedb::TransactionArg; + +// use crate::{ +// drive::Drive, +// error::{drive::DriveError, Error}, +// }; + +// use super::paths::WithdrawalTransaction; + +// impl Drive {} + +// #[cfg(test)] +// mod tests { +// use crate::common::helpers::setup::setup_drive_with_initial_state_structure; + +// use serde_json::json; + +// use dpp::{ +// contracts::withdrawals_contract, +// tests::fixtures::{get_withdrawal_document_fixture, get_withdrawals_data_contract_fixture}, +// }; + +// use crate::{ +// common::helpers::setup::{setup_document, setup_system_data_contract}, +// drive::identity::withdrawals::paths::WithdrawalTransaction, +// }; + +// } From 21270b2b32d30df7f14179d650f942f1a919584f Mon Sep 17 00:00:00 2001 From: Djavid Gabibyan Date: Fri, 6 Jan 2023 17:03:20 +0500 Subject: [PATCH 059/170] chore: wip --- .../src/drive/identity/withdrawals/mod.rs | 2 - .../src/drive/identity/withdrawals/queue.rs | 109 ++++++++---------- .../identity/withdrawals/withdrawal_status.rs | 38 +++++- .../withdrawals/withdrawal_transactions.rs | 42 ------- 4 files changed, 88 insertions(+), 103 deletions(-) delete mode 100644 packages/rs-drive/src/drive/identity/withdrawals/withdrawal_transactions.rs diff --git a/packages/rs-drive/src/drive/identity/withdrawals/mod.rs b/packages/rs-drive/src/drive/identity/withdrawals/mod.rs index 06232d183bf..0ffd527b2cf 100644 --- a/packages/rs-drive/src/drive/identity/withdrawals/mod.rs +++ b/packages/rs-drive/src/drive/identity/withdrawals/mod.rs @@ -6,5 +6,3 @@ pub mod queue; pub mod transaction_index_counter; /// Functions related to updating of a withdrawal status pub mod withdrawal_status; -/// Functions reated to withdrawal transactions -pub mod withdrawal_transactions; diff --git a/packages/rs-drive/src/drive/identity/withdrawals/queue.rs b/packages/rs-drive/src/drive/identity/withdrawals/queue.rs index 543c6ad960a..8b52e952d29 100644 --- a/packages/rs-drive/src/drive/identity/withdrawals/queue.rs +++ b/packages/rs-drive/src/drive/identity/withdrawals/queue.rs @@ -108,61 +108,54 @@ impl Drive { } } -// #[cfg(test)] -// mod tests { -// use crate::{ -// common::helpers::setup::setup_drive_with_initial_state_structure, -// drive::block_info::BlockInfo, fee::op::DriveOperation, fee_pools::epochs::Epoch, -// }; - -// #[test] -// fn test_enqueue_and_dequeue() { -// let drive = setup_drive_with_initial_state_structure(); - -// let transaction = drive.grove.start_transaction(); - -// let withdrawals: Vec<(Vec, Vec)> = (0..17) -// .map(|i: u8| (i.to_be_bytes().to_vec(), vec![i; 32])) -// .collect(); - -// let block_info = BlockInfo { -// time_ms: 1, -// height: 1, -// epoch: Epoch::new(1), -// }; - -// let mut batch: Vec = vec![]; -// let mut result_operations = vec![]; - -// drive -// .add_enqueue_withdrawal_transaction_operations( -// &withdrawals, -// &block_info, -// &mut batch, -// Some(&transaction), -// ) -// .expect("to add operations"); - -// drive -// .apply_batch_drive_operations(None, Some(&transaction), batch, &mut result_operations) -// .expect("to apply batch"); - -// let withdrawals = drive -// .dequeue_withdrawal_transactions(16, Some(&transaction)) -// .expect("to dequeue withdrawals"); - -// assert_eq!(withdrawals.len(), 16); - -// let withdrawals = drive -// .dequeue_withdrawal_transactions(16, Some(&transaction)) -// .expect("to dequeue withdrawals"); - -// assert_eq!(withdrawals.len(), 1); - -// let withdrawals = drive -// .dequeue_withdrawal_transactions(16, Some(&transaction)) -// .expect("to dequeue withdrawals"); - -// assert_eq!(withdrawals.len(), 0); -// } -// } +#[cfg(test)] +mod tests { + use crate::{ + common::helpers::setup::setup_drive_with_initial_state_structure, + drive::{batch::DriveOperationType, block_info::BlockInfo}, + fee_pools::epochs::Epoch, + }; + + #[test] + fn test_enqueue_and_dequeue() { + let drive = setup_drive_with_initial_state_structure(); + + let transaction = drive.grove.start_transaction(); + + let withdrawals: Vec<(Vec, Vec)> = (0..17) + .map(|i: u8| (i.to_be_bytes().to_vec(), vec![i; 32])) + .collect(); + + let block_info = BlockInfo { + time_ms: 1, + height: 1, + epoch: Epoch::new(1), + }; + + let mut drive_operations: Vec = vec![]; + + drive.add_enqueue_withdrawal_transaction_operations(&withdrawals, &mut drive_operations); + + drive + .apply_drive_operations(drive_operations, true, &block_info, Some(&transaction)) + .expect("to apply batch"); + + let withdrawals = drive + .dequeue_withdrawal_transactions(16, Some(&transaction)) + .expect("to dequeue withdrawals"); + + assert_eq!(withdrawals.len(), 16); + + let withdrawals = drive + .dequeue_withdrawal_transactions(16, Some(&transaction)) + .expect("to dequeue withdrawals"); + + assert_eq!(withdrawals.len(), 1); + + let withdrawals = drive + .dequeue_withdrawal_transactions(16, Some(&transaction)) + .expect("to dequeue withdrawals"); + + assert_eq!(withdrawals.len(), 0); + } +} diff --git a/packages/rs-drive/src/drive/identity/withdrawals/withdrawal_status.rs b/packages/rs-drive/src/drive/identity/withdrawals/withdrawal_status.rs index 6c49819d832..c9207b9f1a7 100644 --- a/packages/rs-drive/src/drive/identity/withdrawals/withdrawal_status.rs +++ b/packages/rs-drive/src/drive/identity/withdrawals/withdrawal_status.rs @@ -199,5 +199,41 @@ mod tests { } } - mod find_document_by_transaction_id {} + mod find_document_by_transaction_id { + use dpp::identity::state_transition::identity_credit_withdrawal_transition::Pooling; + + use super::*; + + #[test] + fn test_find_document_by_transaction_id() { + let drive = setup_drive_with_initial_state_structure(); + + let transaction = drive.grove.start_transaction(); + + let data_contract = get_withdrawals_data_contract_fixture(None); + + setup_system_data_contract(&drive, &data_contract, Some(&transaction)); + + let document = get_withdrawal_document_fixture( + &data_contract, + json!({ + "amount": 1000, + "coreFeePerByte": 1, + "pooling": Pooling::Never, + "outputScript": (0..23).collect::>(), + "status": withdrawals_contract::statuses::POOLED, + "transactionIndex": 1, + "transactionId": (0..32).collect::>(), + }), + ); + + setup_document(&drive, &document, &data_contract, Some(&transaction)); + + let found_document = drive + .find_document_by_transaction_id(&(0..32).collect::>(), Some(&transaction)) + .expect("to find document by it's transaction id"); + + assert_eq!(found_document.id, document.id); + } + } } diff --git a/packages/rs-drive/src/drive/identity/withdrawals/withdrawal_transactions.rs b/packages/rs-drive/src/drive/identity/withdrawals/withdrawal_transactions.rs deleted file mode 100644 index e2ce9ea8e60..00000000000 --- a/packages/rs-drive/src/drive/identity/withdrawals/withdrawal_transactions.rs +++ /dev/null @@ -1,42 +0,0 @@ -// use std::collections::HashMap; - -// use dashcore::{ -// blockdata::transaction::special_transaction::asset_unlock::unqualified_asset_unlock::{ -// AssetUnlockBasePayload, AssetUnlockBaseTransactionInfo, -// }, -// consensus::Encodable, -// Script, TxOut, -// }; -// use dpp::{ -// identity::convert_credits_to_satoshi, -// prelude::{Document, Identifier}, -// util::json_value::JsonValueExt, -// }; -// use grovedb::TransactionArg; - -// use crate::{ -// drive::Drive, -// error::{drive::DriveError, Error}, -// }; - -// use super::paths::WithdrawalTransaction; - -// impl Drive {} - -// #[cfg(test)] -// mod tests { -// use crate::common::helpers::setup::setup_drive_with_initial_state_structure; - -// use serde_json::json; - -// use dpp::{ -// contracts::withdrawals_contract, -// tests::fixtures::{get_withdrawal_document_fixture, get_withdrawals_data_contract_fixture}, -// }; - -// use crate::{ -// common::helpers::setup::{setup_document, setup_system_data_contract}, -// drive::identity::withdrawals::paths::WithdrawalTransaction, -// }; - -// } From 9dbf47c207dd2a3ede30faf89fb33af57a60c7bf Mon Sep 17 00:00:00 2001 From: Djavid Gabibyan Date: Fri, 6 Jan 2023 17:30:30 +0500 Subject: [PATCH 060/170] chore: wip --- .../validation/basic/find_duplicates_by_id.rs | 4 ++-- .../validate_indices_are_backward_compatible_spec.rs | 2 +- .../rs-drive-abci/src/identity_credit_withdrawal/mod.rs | 8 ++++---- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/packages/rs-dpp/src/document/state_transition/documents_batch_transition/validation/basic/find_duplicates_by_id.rs b/packages/rs-dpp/src/document/state_transition/documents_batch_transition/validation/basic/find_duplicates_by_id.rs index da190ef2082..f5919d83867 100644 --- a/packages/rs-dpp/src/document/state_transition/documents_batch_transition/validation/basic/find_duplicates_by_id.rs +++ b/packages/rs-dpp/src/document/state_transition/documents_batch_transition/validation/basic/find_duplicates_by_id.rs @@ -35,12 +35,13 @@ fn create_fingerprint(document_transition: &JsonValue) -> Option { Some(format!( "{}:{}", document_transition.as_object()?.get("$type")?, - document_transition.as_object()?.get("id")?, + document_transition.as_object()?.get("$id")?, )) } #[cfg(test)] mod test { + use crate::document::document_transition::{DocumentTransitionObjectLike, JsonValue}; use crate::{ document::document_transition::{ DocumentCreateTransition, DocumentDeleteTransition, DocumentReplaceTransition, @@ -48,7 +49,6 @@ mod test { }, tests::utils::generate_random_identifier_struct, }; - use crate::document::document_transition::{DocumentTransitionObjectLike, JsonValue}; use super::find_duplicates_by_id; diff --git a/packages/rs-dpp/src/tests/data_contract/state_transition/data_contract_update_transition/validation/basic/validate_indices_are_backward_compatible_spec.rs b/packages/rs-dpp/src/tests/data_contract/state_transition/data_contract_update_transition/validation/basic/validate_indices_are_backward_compatible_spec.rs index 67a5ee22475..65e7beff1f0 100644 --- a/packages/rs-dpp/src/tests/data_contract/state_transition/data_contract_update_transition/validation/basic/validate_indices_are_backward_compatible_spec.rs +++ b/packages/rs-dpp/src/tests/data_contract/state_transition/data_contract_update_transition/validation/basic/validate_indices_are_backward_compatible_spec.rs @@ -93,7 +93,7 @@ fn should_return_invalid_result_if_some_of_unique_indices_have_changed() { .expect("validation result should be returned"); assert_eq!(1, result.errors().len()); - assert_eq!(4016, result.errors()[0].code()); + assert_eq!(1053, result.errors()[0].code()); let basic_error = get_basic_error(&result, 0); matches!(basic_error, BasicError::DataContractUniqueIndicesChangedError { document_type, index_name }if { diff --git a/packages/rs-drive-abci/src/identity_credit_withdrawal/mod.rs b/packages/rs-drive-abci/src/identity_credit_withdrawal/mod.rs index 90011848292..fea2cbffcff 100644 --- a/packages/rs-drive-abci/src/identity_credit_withdrawal/mod.rs +++ b/packages/rs-drive-abci/src/identity_credit_withdrawal/mod.rs @@ -809,8 +809,8 @@ mod tests { .expect("to fetch withdrawal documents"); let tx_ids = [ - "73050b2f1cdc267ecd9ccd10038e4c957fc108a404704e83077a593787b5f122", - "de7889314e9dcfc6f7b142c18acc3bd1ccbee5f37d525651cdb3d5ce7fe66700", + "4b74f91644215904ff1aa4122b204ba674aea74d99a17c03fbda483692bf735b", + "897ec16cb13d802ee6acdaf55274c59f3509a4929d726bab919a962ed4a8703c", ]; for document in updated_documents { @@ -971,7 +971,7 @@ mod tests { vec![ 1, 0, 9, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 23, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 0, 0, 0, 0, - 1, 0, 0, 0, 0, 0, 0, 0, 0, 192, 206, 2, 0, + 1, 0, 0, 0, 0, 0, 0, 0, 0, 48, 230, 2, 0 ], ), ( @@ -979,7 +979,7 @@ mod tests { vec![ 1, 0, 9, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 23, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 0, 0, 0, 0, - 1, 1, 0, 0, 0, 0, 0, 0, 0, 192, 206, 2, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, 48, 230, 2, 0 ], ), ] From 187d7aed4aa07b74b30de9493207282c8a8db924 Mon Sep 17 00:00:00 2001 From: Djavid Gabibyan Date: Tue, 10 Jan 2023 15:29:31 +0500 Subject: [PATCH 061/170] chore: fix query_raw --- packages/rs-drive/src/drive/identity/withdrawals/queue.rs | 1 + .../src/drive/identity/withdrawals/transaction_index_counter.rs | 1 + 2 files changed, 2 insertions(+) diff --git a/packages/rs-drive/src/drive/identity/withdrawals/queue.rs b/packages/rs-drive/src/drive/identity/withdrawals/queue.rs index 8b52e952d29..f5973c9b66e 100644 --- a/packages/rs-drive/src/drive/identity/withdrawals/queue.rs +++ b/packages/rs-drive/src/drive/identity/withdrawals/queue.rs @@ -59,6 +59,7 @@ impl Drive { .grove .query_raw( &path_query, + transaction.is_some(), QueryResultType::QueryKeyElementPairResultType, transaction, ) diff --git a/packages/rs-drive/src/drive/identity/withdrawals/transaction_index_counter.rs b/packages/rs-drive/src/drive/identity/withdrawals/transaction_index_counter.rs index e27335c269b..b3e90934343 100644 --- a/packages/rs-drive/src/drive/identity/withdrawals/transaction_index_counter.rs +++ b/packages/rs-drive/src/drive/identity/withdrawals/transaction_index_counter.rs @@ -35,6 +35,7 @@ impl Drive { .grove .query_raw( &expired_index_query, + transaction.is_some(), QueryResultType::QueryKeyElementPairResultType, transaction, ) From f6847705f45e5889de15f4eefca8f067025e30e7 Mon Sep 17 00:00:00 2001 From: Djavid Gabibyan Date: Tue, 10 Jan 2023 15:35:00 +0500 Subject: [PATCH 062/170] chore: run `clippy --fix` --- .../execution/fee_pools/fee_distribution.rs | 2 +- packages/rs-drive-nodejs/src/lib.rs | 4 +- packages/rs-drive/src/common/helpers/setup.rs | 6 +-- .../src/drive/batch/drive_op_batch.rs | 50 +++++++------------ .../rs-drive/src/drive/document/update.rs | 4 +- packages/rs-drive/src/query/mod.rs | 2 +- 6 files changed, 26 insertions(+), 42 deletions(-) diff --git a/packages/rs-drive-abci/src/execution/fee_pools/fee_distribution.rs b/packages/rs-drive-abci/src/execution/fee_pools/fee_distribution.rs index 91e35932247..d2b29c6e2f5 100644 --- a/packages/rs-drive-abci/src/execution/fee_pools/fee_distribution.rs +++ b/packages/rs-drive-abci/src/execution/fee_pools/fee_distribution.rs @@ -874,7 +874,7 @@ mod tests { assert!(matches!( proposer_payouts, Some(ProposersPayouts { - proposers_paid_count: proposers_count, + proposers_paid_count: _proposers_count, paid_epoch_index: 0 }) )); diff --git a/packages/rs-drive-nodejs/src/lib.rs b/packages/rs-drive-nodejs/src/lib.rs index 39ebf7cadd1..d10adafe70b 100644 --- a/packages/rs-drive-nodejs/src/lib.rs +++ b/packages/rs-drive-nodejs/src/lib.rs @@ -3,12 +3,12 @@ mod fee; use drive_abci::config::{CoreConfig, CoreRpcConfig, PlatformConfig}; use std::num::ParseIntError; -use std::ops::Deref; + use std::{option::Option::None, path::Path, sync::mpsc, thread}; use crate::fee::result::FeeResultWrapper; use drive::dpp::identity::Identity; -use drive::drive::batch::GroveDbOpBatch; + use drive::drive::config::DriveConfig; use drive::drive::flags::StorageFlags; use drive::error::Error; diff --git a/packages/rs-drive/src/common/helpers/setup.rs b/packages/rs-drive/src/common/helpers/setup.rs index 5304304c46f..504d1d2aeb7 100644 --- a/packages/rs-drive/src/common/helpers/setup.rs +++ b/packages/rs-drive/src/common/helpers/setup.rs @@ -32,13 +32,13 @@ //! Defines helper functions pertinent to setting up Drive. //! -use std::sync::Arc; + use crate::drive::config::DriveConfig; use crate::drive::Drive; -use crate::drive::{block_info::BlockInfo, contract::ContractFetchInfo}; +use crate::drive::{block_info::BlockInfo}; use crate::fee_pools::epochs::Epoch; -use costs::OperationCost; + use dpp::{ contracts::withdrawals_contract, prelude::{DataContract, Document}, diff --git a/packages/rs-drive/src/drive/batch/drive_op_batch.rs b/packages/rs-drive/src/drive/batch/drive_op_batch.rs index 947b8c2652e..bf997e7fe97 100644 --- a/packages/rs-drive/src/drive/batch/drive_op_batch.rs +++ b/packages/rs-drive/src/drive/batch/drive_op_batch.rs @@ -937,7 +937,7 @@ mod tests { drive_operations.push(ContractOperation(ApplyContractWithSerialization { contract: &contract, - serialized_contract: serialized_contract.clone(), + serialized_contract: serialized_contract, storage_flags: None, })); @@ -1042,13 +1042,11 @@ mod tests { operations.push(AddOperation { owned_document_info: OwnedDocumentInfo { - document_info: DocumentRefAndSerialization { - 0: ( + document_info: DocumentRefAndSerialization(( &document0, dashpay_cr_serialized_document0.as_slice(), StorageFlags::optional_default_as_ref(), - ), - }, + )), owner_id: Some(random_owner_id), }, override_document: false, @@ -1063,13 +1061,11 @@ mod tests { operations.push(AddOperation { owned_document_info: OwnedDocumentInfo { - document_info: DocumentRefAndSerialization { - 0: ( + document_info: DocumentRefAndSerialization(( &document1, dashpay_cr_serialized_document1.as_slice(), StorageFlags::optional_default_as_ref(), - ), - }, + )), owner_id: Some(random_owner_id), }, override_document: false, @@ -1181,13 +1177,11 @@ mod tests { operations.push(AddOperation { owned_document_info: OwnedDocumentInfo { - document_info: DocumentRefAndSerialization { - 0: ( + document_info: DocumentRefAndSerialization(( &document0, person_serialized_document0.as_slice(), StorageFlags::optional_default_as_ref(), - ), - }, + )), owner_id: Some(random_owner_id0), }, override_document: false, @@ -1204,13 +1198,11 @@ mod tests { operations.push(AddOperation { owned_document_info: OwnedDocumentInfo { - document_info: DocumentRefAndSerialization { - 0: ( + document_info: DocumentRefAndSerialization(( &document1, person_serialized_document0.as_slice(), StorageFlags::optional_default_as_ref(), - ), - }, + )), owner_id: Some(random_owner_id1), }, override_document: false, @@ -1310,13 +1302,11 @@ mod tests { operations.push(AddOperation { owned_document_info: OwnedDocumentInfo { - document_info: DocumentRefAndSerialization { - 0: ( + document_info: DocumentRefAndSerialization(( &document0, person_serialized_document0.as_slice(), StorageFlags::optional_default_as_ref(), - ), - }, + )), owner_id: Some(random_owner_id0), }, override_document: false, @@ -1333,13 +1323,11 @@ mod tests { operations.push(AddOperation { owned_document_info: OwnedDocumentInfo { - document_info: DocumentRefAndSerialization { - 0: ( + document_info: DocumentRefAndSerialization(( &document1, person_serialized_document1.as_slice(), StorageFlags::optional_default_as_ref(), - ), - }, + )), owner_id: Some(random_owner_id1), }, override_document: false, @@ -1546,13 +1534,11 @@ mod tests { operations.push(AddOperation { owned_document_info: OwnedDocumentInfo { - document_info: DocumentRefAndSerialization { - 0: ( + document_info: DocumentRefAndSerialization(( &document0, person_serialized_document0.as_slice(), StorageFlags::optional_default_as_ref(), - ), - }, + )), owner_id: Some(random_owner_id0), }, override_document: false, @@ -1569,13 +1555,11 @@ mod tests { operations.push(AddOperation { owned_document_info: OwnedDocumentInfo { - document_info: DocumentRefAndSerialization { - 0: ( + document_info: DocumentRefAndSerialization(( &document1, person_serialized_document1.as_slice(), StorageFlags::optional_default_as_ref(), - ), - }, + )), owner_id: Some(random_owner_id1), }, override_document: false, diff --git a/packages/rs-drive/src/drive/document/update.rs b/packages/rs-drive/src/drive/document/update.rs index c716592c49a..01694586025 100644 --- a/packages/rs-drive/src/drive/document/update.rs +++ b/packages/rs-drive/src/drive/document/update.rs @@ -577,7 +577,7 @@ impl Drive { is_known_to_be_subtree_with_sum: Some((false, false)), }, transaction, - &previous_batch_operations, + previous_batch_operations, &mut batch_operations, )?; } else { @@ -590,7 +590,7 @@ impl Drive { is_known_to_be_subtree_with_sum: Some((false, false)), }, transaction, - &previous_batch_operations, + previous_batch_operations, &mut batch_operations, )?; } diff --git a/packages/rs-drive/src/query/mod.rs b/packages/rs-drive/src/query/mod.rs index 6000b315976..022a7c066c8 100644 --- a/packages/rs-drive/src/query/mod.rs +++ b/packages/rs-drive/src/query/mod.rs @@ -1249,7 +1249,7 @@ impl<'a> DriveQuery<'a> { let proof = drive.grove_get_proved_path_query(&path_query, transaction, drive_operations)?; - let (root_hash, mut key_value_elements) = + let (root_hash, key_value_elements) = GroveDb::verify_query(proof.as_slice(), &path_query).map_err(Error::GroveDB)?; let mut values = vec![]; From e713139ccd6eac955f4aa9039aa25664abc9156b Mon Sep 17 00:00:00 2001 From: Djavid Gabibyan Date: Tue, 10 Jan 2023 17:28:03 +0500 Subject: [PATCH 063/170] chore: PR fixes --- packages/rs-drive-nodejs/src/lib.rs | 39 +++++-------------- .../src/drive/identity/withdrawals/queue.rs | 24 ++++++++++++ 2 files changed, 34 insertions(+), 29 deletions(-) diff --git a/packages/rs-drive-nodejs/src/lib.rs b/packages/rs-drive-nodejs/src/lib.rs index d10adafe70b..bd261e8e3e6 100644 --- a/packages/rs-drive-nodejs/src/lib.rs +++ b/packages/rs-drive-nodejs/src/lib.rs @@ -2252,8 +2252,9 @@ impl PlatformWrapper { fn js_enqueue_withdrawal_transaction(mut cx: FunctionContext) -> JsResult { let js_index = cx.argument::(0)?; let js_core_transaction = cx.argument::(1)?; - let js_using_transaction = cx.argument::(2)?; - let js_callback = cx.argument::(3)?.root(&mut cx); + let js_block_info = cx.argument::(2)?; + let js_using_transaction = cx.argument::(3)?; + let js_callback = cx.argument::(4)?.root(&mut cx); let db = cx .this() @@ -2262,6 +2263,7 @@ impl PlatformWrapper { let index = js_index.value(&mut cx); let transaction_bytes = converter::js_buffer_to_vec_u8(js_core_transaction, &mut cx); let using_transaction = js_using_transaction.value(&mut cx); + let block_info = converter::js_object_to_block_info(js_block_info, &mut cx)?; db.send_to_drive_thread(move |platform: &Platform, transaction, channel| { let transaction_result = if using_transaction { @@ -2274,37 +2276,16 @@ impl PlatformWrapper { Ok(None) }; - let block_info = drive::drive::block_info::BlockInfo { - time_ms: 1, - height: 1, - epoch: Epoch::new(1), - }; - - let mut drive_operations = vec![]; - - let index_bytes = (index as u64).to_be_bytes().to_vec(); - - let withdrawals = vec![(index_bytes, transaction_bytes)]; - let execution_function = |transaction: TransactionArg| -> Result<(), String> { platform .drive - .add_enqueue_withdrawal_transaction_operations( - &withdrawals, - &mut drive_operations, - ); - - platform - .drive - .add_update_withdrawal_index_counter_operation( + .enqueue_withdrawal_transaction( index as u64, - &mut drive_operations, - ); - - platform - .drive - .apply_drive_operations(drive_operations, true, &block_info, transaction) - .map_err(|err| err.to_string())?; + transaction_bytes, + &block_info, + transaction, + ) + .map_err(|e| e.to_string())?; Ok(()) }; diff --git a/packages/rs-drive/src/drive/identity/withdrawals/queue.rs b/packages/rs-drive/src/drive/identity/withdrawals/queue.rs index f5973c9b66e..7305ea8f261 100644 --- a/packages/rs-drive/src/drive/identity/withdrawals/queue.rs +++ b/packages/rs-drive/src/drive/identity/withdrawals/queue.rs @@ -8,6 +8,7 @@ use grovedb::{ use crate::{ drive::{ batch::{drive_op_batch::WithdrawalOperationType, DriveOperationType}, + block_info::BlockInfo, grove_operations::BatchDeleteApplyType, Drive, }, @@ -107,6 +108,29 @@ impl Drive { Ok(withdrawals) } + + /// Enqueue single withdrawal transaction + pub fn enqueue_withdrawal_transaction( + &self, + index: u64, + transaction_bytes: Vec, + block_info: &BlockInfo, + transaction: TransactionArg, + ) -> Result<(), Error> { + let mut drive_operations = vec![]; + + let index_bytes = (index as u64).to_be_bytes().to_vec(); + + let withdrawals = vec![(index_bytes, transaction_bytes)]; + + self.add_enqueue_withdrawal_transaction_operations(&withdrawals, &mut drive_operations); + + self.add_update_withdrawal_index_counter_operation(index, &mut drive_operations); + + self.apply_drive_operations(drive_operations, true, &block_info, transaction)?; + + Ok(()) + } } #[cfg(test)] From 340ddf4f7ddf8f9bb3a47d72fa10c5c4d6a3cc53 Mon Sep 17 00:00:00 2001 From: Djavid Gabibyan Date: Tue, 10 Jan 2023 17:42:49 +0500 Subject: [PATCH 064/170] chore: PR fixes --- packages/js-drive/lib/dpp/DriveStateRepository.js | 3 +++ packages/rs-drive-nodejs/Drive.js | 3 ++- packages/rs-drive-nodejs/test/Drive.spec.js | 2 +- 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/packages/js-drive/lib/dpp/DriveStateRepository.js b/packages/js-drive/lib/dpp/DriveStateRepository.js index 0816509c321..1baf2dc4677 100644 --- a/packages/js-drive/lib/dpp/DriveStateRepository.js +++ b/packages/js-drive/lib/dpp/DriveStateRepository.js @@ -535,10 +535,13 @@ class DriveStateRepository { * @returns {Promise} */ async enqueueWithdrawalTransaction(index, transactionBytes) { + const blockInfo = BlockInfo.createFromBlockExecutionContext(this.blockExecutionContext); + // TODO: handle dry run via passing state transition execution context return this.rsDrive.enqueueWithdrawalTransaction( index, transactionBytes, + blockInfo, this.#options.useTransaction, ); } diff --git a/packages/rs-drive-nodejs/Drive.js b/packages/rs-drive-nodejs/Drive.js index 229be27ad96..292c357559b 100644 --- a/packages/rs-drive-nodejs/Drive.js +++ b/packages/rs-drive-nodejs/Drive.js @@ -361,11 +361,12 @@ class Drive { * * @returns {Promise} */ - async enqueueWithdrawalTransaction(index, transactionBytes, useTransaction = false) { + async enqueueWithdrawalTransaction(index, transactionBytes, blockInfo, useTransaction = false) { return driveEnqueueWithdrawalTransactionAsync.call( this.drive, index, transactionBytes, + blockInfo, useTransaction, ); } diff --git a/packages/rs-drive-nodejs/test/Drive.spec.js b/packages/rs-drive-nodejs/test/Drive.spec.js index eb526dad207..d5f20503440 100644 --- a/packages/rs-drive-nodejs/test/Drive.spec.js +++ b/packages/rs-drive-nodejs/test/Drive.spec.js @@ -517,7 +517,7 @@ describe('Drive', function main() { }); it('should enqueue withdrawal transaction into the queue', async () => { - await drive.enqueueWithdrawalTransaction(1, Buffer.alloc(32, 1)); + await drive.enqueueWithdrawalTransaction(1, Buffer.alloc(32, 1), blockInfo); const result = await drive.fetchLatestWithdrawalTransactionIndex(); From 9b56224b1ba58caf93b9608fcf9592ea4aa54827 Mon Sep 17 00:00:00 2001 From: Djavid Gabibyan Date: Tue, 10 Jan 2023 18:14:55 +0500 Subject: [PATCH 065/170] chore: PR fixes --- .github/workflows/rs-checks.yml | 2 +- packages/js-drive/test/unit/dpp/DriveStateRepository.spec.js | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/rs-checks.yml b/.github/workflows/rs-checks.yml index 50e379f7729..c2d8226d912 100644 --- a/.github/workflows/rs-checks.yml +++ b/.github/workflows/rs-checks.yml @@ -64,7 +64,7 @@ jobs: - name: Enable Rust cache uses: Swatinem/rust-cache@v2 - - run: cargo check --package=${{ inputs.package }} + - run: cargo check --package=${{ inputs.package }} --all-features test: name: Tests diff --git a/packages/js-drive/test/unit/dpp/DriveStateRepository.spec.js b/packages/js-drive/test/unit/dpp/DriveStateRepository.spec.js index 9466b7efb32..70445771422 100644 --- a/packages/js-drive/test/unit/dpp/DriveStateRepository.spec.js +++ b/packages/js-drive/test/unit/dpp/DriveStateRepository.spec.js @@ -681,6 +681,7 @@ describe('DriveStateRepository', () => { ).to.have.been.calledOnceWithExactly( index, transactionBytes, + blockInfo, repositoryOptions.useTransaction, ); }); From ec1d986cea0576e8e8e3c2b3be2f6a2366bde3c2 Mon Sep 17 00:00:00 2001 From: Djavid Gabibyan Date: Tue, 10 Jan 2023 18:27:21 +0500 Subject: [PATCH 066/170] chore: fmt fixes --- ...ty_credit_withdrawal_transition_factory.rs | 3 +- packages/rs-drive/src/common/helpers/setup.rs | 4 +- .../src/drive/batch/drive_op_batch.rs | 64 +++++++++---------- 3 files changed, 35 insertions(+), 36 deletions(-) diff --git a/packages/rs-dpp/src/identity/state_transition/identity_credit_withdrawal_transition/apply_identity_credit_withdrawal_transition_factory.rs b/packages/rs-dpp/src/identity/state_transition/identity_credit_withdrawal_transition/apply_identity_credit_withdrawal_transition_factory.rs index 9e9ac405781..bd1cfc6724c 100644 --- a/packages/rs-dpp/src/identity/state_transition/identity_credit_withdrawal_transition/apply_identity_credit_withdrawal_transition_factory.rs +++ b/packages/rs-dpp/src/identity/state_transition/identity_credit_withdrawal_transition/apply_identity_credit_withdrawal_transition_factory.rs @@ -7,12 +7,13 @@ use crate::{ contracts::withdrawals_contract, data_contract::DataContract, document::Document, + identity::state_transition::identity_credit_withdrawal_transition::Pooling, prelude::Identifier, prelude::Identity, state_repository::StateRepositoryLike, state_transition::StateTransitionConvert, state_transition::StateTransitionLike, - util::{entropy_generator::generate, json_value::JsonValueExt, string_encoding::Encoding}, identity::state_transition::identity_credit_withdrawal_transition::Pooling, + util::{entropy_generator::generate, json_value::JsonValueExt, string_encoding::Encoding}, }; use super::IdentityCreditWithdrawalTransition; diff --git a/packages/rs-drive/src/common/helpers/setup.rs b/packages/rs-drive/src/common/helpers/setup.rs index 504d1d2aeb7..dda3765c415 100644 --- a/packages/rs-drive/src/common/helpers/setup.rs +++ b/packages/rs-drive/src/common/helpers/setup.rs @@ -32,11 +32,9 @@ //! Defines helper functions pertinent to setting up Drive. //! - - +use crate::drive::block_info::BlockInfo; use crate::drive::config::DriveConfig; use crate::drive::Drive; -use crate::drive::{block_info::BlockInfo}; use crate::fee_pools::epochs::Epoch; use dpp::{ diff --git a/packages/rs-drive/src/drive/batch/drive_op_batch.rs b/packages/rs-drive/src/drive/batch/drive_op_batch.rs index bf997e7fe97..2e993cd362d 100644 --- a/packages/rs-drive/src/drive/batch/drive_op_batch.rs +++ b/packages/rs-drive/src/drive/batch/drive_op_batch.rs @@ -1043,10 +1043,10 @@ mod tests { operations.push(AddOperation { owned_document_info: OwnedDocumentInfo { document_info: DocumentRefAndSerialization(( - &document0, - dashpay_cr_serialized_document0.as_slice(), - StorageFlags::optional_default_as_ref(), - )), + &document0, + dashpay_cr_serialized_document0.as_slice(), + StorageFlags::optional_default_as_ref(), + )), owner_id: Some(random_owner_id), }, override_document: false, @@ -1062,10 +1062,10 @@ mod tests { operations.push(AddOperation { owned_document_info: OwnedDocumentInfo { document_info: DocumentRefAndSerialization(( - &document1, - dashpay_cr_serialized_document1.as_slice(), - StorageFlags::optional_default_as_ref(), - )), + &document1, + dashpay_cr_serialized_document1.as_slice(), + StorageFlags::optional_default_as_ref(), + )), owner_id: Some(random_owner_id), }, override_document: false, @@ -1178,10 +1178,10 @@ mod tests { operations.push(AddOperation { owned_document_info: OwnedDocumentInfo { document_info: DocumentRefAndSerialization(( - &document0, - person_serialized_document0.as_slice(), - StorageFlags::optional_default_as_ref(), - )), + &document0, + person_serialized_document0.as_slice(), + StorageFlags::optional_default_as_ref(), + )), owner_id: Some(random_owner_id0), }, override_document: false, @@ -1199,10 +1199,10 @@ mod tests { operations.push(AddOperation { owned_document_info: OwnedDocumentInfo { document_info: DocumentRefAndSerialization(( - &document1, - person_serialized_document0.as_slice(), - StorageFlags::optional_default_as_ref(), - )), + &document1, + person_serialized_document0.as_slice(), + StorageFlags::optional_default_as_ref(), + )), owner_id: Some(random_owner_id1), }, override_document: false, @@ -1303,10 +1303,10 @@ mod tests { operations.push(AddOperation { owned_document_info: OwnedDocumentInfo { document_info: DocumentRefAndSerialization(( - &document0, - person_serialized_document0.as_slice(), - StorageFlags::optional_default_as_ref(), - )), + &document0, + person_serialized_document0.as_slice(), + StorageFlags::optional_default_as_ref(), + )), owner_id: Some(random_owner_id0), }, override_document: false, @@ -1324,10 +1324,10 @@ mod tests { operations.push(AddOperation { owned_document_info: OwnedDocumentInfo { document_info: DocumentRefAndSerialization(( - &document1, - person_serialized_document1.as_slice(), - StorageFlags::optional_default_as_ref(), - )), + &document1, + person_serialized_document1.as_slice(), + StorageFlags::optional_default_as_ref(), + )), owner_id: Some(random_owner_id1), }, override_document: false, @@ -1535,10 +1535,10 @@ mod tests { operations.push(AddOperation { owned_document_info: OwnedDocumentInfo { document_info: DocumentRefAndSerialization(( - &document0, - person_serialized_document0.as_slice(), - StorageFlags::optional_default_as_ref(), - )), + &document0, + person_serialized_document0.as_slice(), + StorageFlags::optional_default_as_ref(), + )), owner_id: Some(random_owner_id0), }, override_document: false, @@ -1556,10 +1556,10 @@ mod tests { operations.push(AddOperation { owned_document_info: OwnedDocumentInfo { document_info: DocumentRefAndSerialization(( - &document1, - person_serialized_document1.as_slice(), - StorageFlags::optional_default_as_ref(), - )), + &document1, + person_serialized_document1.as_slice(), + StorageFlags::optional_default_as_ref(), + )), owner_id: Some(random_owner_id1), }, override_document: false, From 8f7ab700f3fc97e00449d21c34e7e675ab9ac7f5 Mon Sep 17 00:00:00 2001 From: Djavid Gabibiyan Date: Tue, 10 Jan 2023 19:32:41 +0500 Subject: [PATCH 067/170] chore: CI --- .github/workflows/js-checks.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/js-checks.yml b/.github/workflows/js-checks.yml index 8ec9579c847..85346b75a7e 100644 --- a/.github/workflows/js-checks.yml +++ b/.github/workflows/js-checks.yml @@ -121,6 +121,8 @@ jobs: - name: Build SDK run: yarn build --filter "+dash" if: ${{ inputs.start-local-network }} + env: + CARGO_BUILD_PROFILE: test - name: Create necessary dotenv files run: | From 42834dce982603c94ba3983b88eed27a0f2fd919 Mon Sep 17 00:00:00 2001 From: Djavid Gabibiyan Date: Tue, 10 Jan 2023 20:09:07 +0500 Subject: [PATCH 068/170] chore: CI --- .github/workflows/js-checks.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/js-checks.yml b/.github/workflows/js-checks.yml index 85346b75a7e..f73bc0fcf4b 100644 --- a/.github/workflows/js-checks.yml +++ b/.github/workflows/js-checks.yml @@ -117,12 +117,12 @@ jobs: - name: Build package and dependencies run: yarn build --filter "+${{ inputs.package }}" + env: + CARGO_BUILD_PROFILE: test - name: Build SDK run: yarn build --filter "+dash" if: ${{ inputs.start-local-network }} - env: - CARGO_BUILD_PROFILE: test - name: Create necessary dotenv files run: | From 2f620a72149f6136e1c3fb629d1cd351159e686f Mon Sep 17 00:00:00 2001 From: Djavid Gabibiyan Date: Tue, 10 Jan 2023 20:27:18 +0500 Subject: [PATCH 069/170] empty commit From 19e4c3d8a220849c0d5569b7dcd1e325db5f94ec Mon Sep 17 00:00:00 2001 From: Djavid Gabibiyan Date: Thu, 12 Jan 2023 18:45:36 +0500 Subject: [PATCH 070/170] chore: after merge update --- Cargo.lock | 57 ++++++++++++++++--- packages/rs-dpp/Cargo.toml | 2 +- ...ty_credit_withdrawal_transition_factory.rs | 2 +- .../tests/fixtures/get_documents_fixture.rs | 4 +- packages/rs-drive-abci/Cargo.toml | 2 +- packages/rs-drive/Cargo.toml | 3 +- 6 files changed, 55 insertions(+), 15 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 512ea7ad8cc..47487bd5e9d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -193,6 +193,12 @@ dependencies = [ "serde", ] +[[package]] +name = "bitcoin_hashes" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90064b8dee6815a6470d60bad07bbbaee885c0e12d04177138fa3291a01b7bc4" + [[package]] name = "bitflags" version = "1.3.2" @@ -830,6 +836,20 @@ dependencies = [ "syn", ] +[[package]] +name = "dashcore" +version = "0.29.1" +source = "git+https://github.com/dashevo/rust-dashcore?rev=51548a4a1b9eca7430f5f3caf94d9784886ff2e9#51548a4a1b9eca7430f5f3caf94d9784886ff2e9" +dependencies = [ + "anyhow", + "bech32", + "bitcoin_hashes 0.10.0", + "hex", + "rustversion", + "secp256k1 0.24.2", + "serde", +] + [[package]] name = "dashcore" version = "0.29.1" @@ -837,10 +857,10 @@ source = "git+https://github.com/dashevo/rust-dashcore?rev=6092d584487918c5330fe dependencies = [ "anyhow", "bech32", - "bitcoin_hashes", + "bitcoin_hashes 0.10.0", "hex", "rustversion", - "secp256k1", + "secp256k1 0.22.1", "serde", ] @@ -861,7 +881,7 @@ name = "dashcore-rpc-json" version = "0.15.0" source = "git+https://github.com/jawid-h/rust-dashcore-rpc?branch=fix/attempt-to-fix#2b4156aac527eb91ee9882f6575766b59a226ef9" dependencies = [ - "dashcore", + "dashcore 0.29.1 (git+https://github.com/dashevo/rust-dashcore?rev=6092d584487918c5330fec93152e4df06a714067)", "serde", "serde_json", "serde_with", @@ -917,7 +937,7 @@ dependencies = [ "byteorder", "chrono", "ciborium", - "dashcore", + "dashcore 0.29.1 (git+https://github.com/dashevo/rust-dashcore?rev=51548a4a1b9eca7430f5f3caf94d9784886ff2e9)", "env_logger", "futures", "getrandom", @@ -932,7 +952,7 @@ dependencies = [ "mockall", "num_enum", "pretty_assertions", - "rand", + "rand 0.8.5", "regex", "serde", "serde-big-array", @@ -958,7 +978,7 @@ dependencies = [ "ciborium", "costs", "criterion", - "dashcore", + "dashcore 0.29.1 (git+https://github.com/dashevo/rust-dashcore?rev=51548a4a1b9eca7430f5f3caf94d9784886ff2e9)", "dashcore-rpc", "dpp", "enum-map", @@ -991,7 +1011,7 @@ dependencies = [ "bs58", "chrono", "ciborium", - "dashcore", + "dashcore 0.29.1 (git+https://github.com/dashevo/rust-dashcore?rev=51548a4a1b9eca7430f5f3caf94d9784886ff2e9)", "dpp", "drive", "hex", @@ -2748,7 +2768,19 @@ version = "0.22.1" source = "git+https://github.com/rust-bitcoin/rust-secp256k1?rev=f7cae46fc7733522cb84ef1b1ee1d1ed0cec2fd3#f7cae46fc7733522cb84ef1b1ee1d1ed0cec2fd3" dependencies = [ "rand 0.6.5", - "secp256k1-sys", + "secp256k1-sys 0.5.0", + "serde", +] + +[[package]] +name = "secp256k1" +version = "0.24.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9512ffd81e3a3503ed401f79c33168b9148c75038956039166cd750eaa037c3" +dependencies = [ + "bitcoin_hashes 0.11.0", + "rand 0.8.5", + "secp256k1-sys 0.6.1", "serde", ] @@ -2760,6 +2792,15 @@ dependencies = [ "cc", ] +[[package]] +name = "secp256k1-sys" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "83080e2c2fc1006e625be82e5d1eb6a43b7fd9578b617fcc55814daf286bba4b" +dependencies = [ + "cc", +] + [[package]] name = "semver" version = "0.9.0" diff --git a/packages/rs-dpp/Cargo.toml b/packages/rs-dpp/Cargo.toml index cb9e5f90c3c..ae49c35fcfc 100644 --- a/packages/rs-dpp/Cargo.toml +++ b/packages/rs-dpp/Cargo.toml @@ -13,7 +13,7 @@ bs58 = "0.4.0" byteorder = { version="1.4"} chrono = { version="0.4.20", default-features=false, features=["wasmbind", "clock"]} ciborium = { git="https://github.com/qrayven/ciborium", branch="feat-ser-null-as-undefined"} -dashcore = { git="https://github.com/dashevo/rust-dashcore", features=["std", "secp-recovery", "rand", "signer", "use-serde"], default-features = false, branch="master" } +dashcore = { git="https://github.com/dashevo/rust-dashcore", features=["std", "secp-recovery", "rand", "signer", "use-serde"], default-features = false, rev = "51548a4a1b9eca7430f5f3caf94d9784886ff2e9" } env_logger = { version="0.9"} futures = { version ="0.3"} getrandom= { version="0.2", features=["js"]} diff --git a/packages/rs-dpp/src/identity/state_transition/identity_credit_withdrawal_transition/apply_identity_credit_withdrawal_transition_factory.rs b/packages/rs-dpp/src/identity/state_transition/identity_credit_withdrawal_transition/apply_identity_credit_withdrawal_transition_factory.rs index bd1cfc6724c..8590f6cbe0a 100644 --- a/packages/rs-dpp/src/identity/state_transition/identity_credit_withdrawal_transition/apply_identity_credit_withdrawal_transition_factory.rs +++ b/packages/rs-dpp/src/identity/state_transition/identity_credit_withdrawal_transition/apply_identity_credit_withdrawal_transition_factory.rs @@ -66,7 +66,7 @@ where .await?; let document_type = String::from(withdrawals_contract::types::WITHDRAWAL); - let document_entropy = generate(); + let document_entropy = generate()?; let document_created_at_millis = latest_platform_block_header .get(PLATFORM_BLOCK_HEADER_TIME_PROPERTY) .ok_or_else(|| anyhow!("time property is not set in block header"))? diff --git a/packages/rs-dpp/src/tests/fixtures/get_documents_fixture.rs b/packages/rs-dpp/src/tests/fixtures/get_documents_fixture.rs index 7087efb8e5c..25056bdc86e 100644 --- a/packages/rs-dpp/src/tests/fixtures/get_documents_fixture.rs +++ b/packages/rs-dpp/src/tests/fixtures/get_documents_fixture.rs @@ -3,11 +3,11 @@ use std::sync::Arc; use serde_json::{json, Value}; use crate::{ + contracts::withdrawals_contract, document::{ document_factory::DocumentFactory, fetch_and_validate_data_contract::DataContractFetcherAndValidator, }, - mocks, prelude::*, state_repository::{MockStateRepositoryLike, StateRepositoryLike}, tests::utils::generate_random_identifier_struct as gen_owner_id, @@ -114,7 +114,7 @@ pub fn get_withdrawal_document_fixture(data_contract: &DataContract, data: Value let factory = DocumentFactory::new( LATEST_VERSION, get_document_validator_fixture(), - mocks::FetchAndValidateDataContract {}, + DataContractFetcherAndValidator::new(Arc::new(MockStateRepositoryLike::new())), ); factory diff --git a/packages/rs-drive-abci/Cargo.toml b/packages/rs-drive-abci/Cargo.toml index 8b1be817ee9..59a0b43d154 100644 --- a/packages/rs-drive-abci/Cargo.toml +++ b/packages/rs-drive-abci/Cargo.toml @@ -18,7 +18,7 @@ tempfile = "3" bs58 = "0.4.0" base64 = "0.13.0" hex = "0.4.3" -dashcore = { git="https://github.com/dashevo/rust-dashcore", features=["std", "secp-recovery", "rand", "signer", "use-serde"], default-features = false, rev = "6092d584487918c5330fec93152e4df06a714067" } +dashcore = { git="https://github.com/dashevo/rust-dashcore", features=["std", "secp-recovery", "rand", "signer", "use-serde"], default-features = false, rev = "51548a4a1b9eca7430f5f3caf94d9784886ff2e9" } dpp = { path = "../rs-dpp", features = ["fixtures-and-mocks"]} rust_decimal = "1.2.5" rust_decimal_macros = "1.25.0" diff --git a/packages/rs-drive/Cargo.toml b/packages/rs-drive/Cargo.toml index 00d3d5d709e..8f9be802b94 100644 --- a/packages/rs-drive/Cargo.toml +++ b/packages/rs-drive/Cargo.toml @@ -30,7 +30,7 @@ chrono = "0.4.20" bincode = "1.3.3" dpp = { path = "../rs-dpp", features = ["fixtures-and-mocks"]} itertools = { version = "0.10.5" } -dashcore = { git="https://github.com/dashevo/rust-dashcore", features=["std", "secp-recovery", "rand", "signer", "use-serde"], default-features = false, rev = "6092d584487918c5330fec93152e4df06a714067" } +dashcore = { git="https://github.com/dashevo/rust-dashcore", features=["std", "secp-recovery", "rand", "signer", "use-serde"], default-features = false, rev = "51548a4a1b9eca7430f5f3caf94d9784886ff2e9" } dashcore-rpc = { git="https://github.com/jawid-h/rust-dashcore-rpc", branch="fix/attempt-to-fix" } mockall= { version ="0.11", optional = true } rust_decimal = "1.2.5" @@ -50,7 +50,6 @@ rev = "a9e168767c318b94b6edd119c51542c43e8772b2" [dev-dependencies] criterion = "0.3.5" -dpp = { path = "../rs-dpp", features=["mocks"]} [[bench]] name = "benchmarks" From 8565f07e45c5e5d6d802dcf1ef621d5a4cf239ef Mon Sep 17 00:00:00 2001 From: Djavid Gabibiyan Date: Thu, 12 Jan 2023 19:06:59 +0500 Subject: [PATCH 071/170] chore: after merge update --- Cargo.lock | 249 +++++++++-------------------------------------------- 1 file changed, 39 insertions(+), 210 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 47487bd5e9d..29a4e4486c8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -93,15 +93,6 @@ dependencies = [ "winapi", ] -[[package]] -name = "autocfg" -version = "0.1.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0dde43e75fd43e8a1bf86103336bc699aa8d17ad1be60c76c0bdfd4828e19b78" -dependencies = [ - "autocfg 1.1.0", -] - [[package]] name = "autocfg" version = "1.1.0" @@ -260,7 +251,7 @@ dependencies = [ "group", "hkdf", "pairing", - "rand_core 0.6.4", + "rand_core", "rayon", "sha2 0.9.9", "subtle", @@ -277,7 +268,7 @@ dependencies = [ "ff", "group", "pairing", - "rand_core 0.6.4", + "rand_core", "subtle", ] @@ -529,15 +520,6 @@ dependencies = [ "unicode-width", ] -[[package]] -name = "cloudabi" -version = "0.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f" -dependencies = [ - "bitflags", -] - [[package]] name = "codespan-reporting" version = "0.11.1" @@ -663,7 +645,7 @@ version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "058ed274caafc1f60c4997b5fc07bf7dc7cca454af7c6e81edffe5f33f70dace" dependencies = [ - "autocfg 1.1.0", + "autocfg", "cfg-if 0.1.10", "crossbeam-utils 0.7.2", "lazy_static", @@ -678,7 +660,7 @@ version = "0.9.13" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "01a9af1f4c2ef74bb8aa1f7e19706bc72d03598c8a570bb5de72243c7a9d9d5a" dependencies = [ - "autocfg 1.1.0", + "autocfg", "cfg-if 1.0.0", "crossbeam-utils 0.8.14", "memoffset 0.7.1", @@ -691,7 +673,7 @@ version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c3c7c73a2d1e9fc0886a08b93e98eb643461230d5f1925e4036204d5f2e261a8" dependencies = [ - "autocfg 1.1.0", + "autocfg", "cfg-if 0.1.10", "lazy_static", ] @@ -846,28 +828,14 @@ dependencies = [ "bitcoin_hashes 0.10.0", "hex", "rustversion", - "secp256k1 0.24.2", - "serde", -] - -[[package]] -name = "dashcore" -version = "0.29.1" -source = "git+https://github.com/dashevo/rust-dashcore?rev=6092d584487918c5330fec93152e4df06a714067#6092d584487918c5330fec93152e4df06a714067" -dependencies = [ - "anyhow", - "bech32", - "bitcoin_hashes 0.10.0", - "hex", - "rustversion", - "secp256k1 0.22.1", + "secp256k1", "serde", ] [[package]] name = "dashcore-rpc" version = "0.15.0" -source = "git+https://github.com/jawid-h/rust-dashcore-rpc?branch=fix/attempt-to-fix#2b4156aac527eb91ee9882f6575766b59a226ef9" +source = "git+https://github.com/jawid-h/rust-dashcore-rpc?branch=fix/attempt-to-fix#5dbc28583ef77d0b6eca3b3519448569bc41ce8d" dependencies = [ "dashcore-rpc-json", "jsonrpc", @@ -879,9 +847,9 @@ dependencies = [ [[package]] name = "dashcore-rpc-json" version = "0.15.0" -source = "git+https://github.com/jawid-h/rust-dashcore-rpc?branch=fix/attempt-to-fix#2b4156aac527eb91ee9882f6575766b59a226ef9" +source = "git+https://github.com/jawid-h/rust-dashcore-rpc?branch=fix/attempt-to-fix#5dbc28583ef77d0b6eca3b3519448569bc41ce8d" dependencies = [ - "dashcore 0.29.1 (git+https://github.com/dashevo/rust-dashcore?rev=6092d584487918c5330fec93152e4df06a714067)", + "dashcore", "serde", "serde_json", "serde_with", @@ -937,7 +905,7 @@ dependencies = [ "byteorder", "chrono", "ciborium", - "dashcore 0.29.1 (git+https://github.com/dashevo/rust-dashcore?rev=51548a4a1b9eca7430f5f3caf94d9784886ff2e9)", + "dashcore", "env_logger", "futures", "getrandom", @@ -952,7 +920,7 @@ dependencies = [ "mockall", "num_enum", "pretty_assertions", - "rand 0.8.5", + "rand", "regex", "serde", "serde-big-array", @@ -978,7 +946,7 @@ dependencies = [ "ciborium", "costs", "criterion", - "dashcore 0.29.1 (git+https://github.com/dashevo/rust-dashcore?rev=51548a4a1b9eca7430f5f3caf94d9784886ff2e9)", + "dashcore", "dashcore-rpc", "dpp", "enum-map", @@ -991,7 +959,7 @@ dependencies = [ "mockall", "moka", "nohash-hasher", - "rand 0.8.5", + "rand", "rand_distr", "rust_decimal", "rust_decimal_macros", @@ -1011,12 +979,12 @@ dependencies = [ "bs58", "chrono", "ciborium", - "dashcore 0.29.1 (git+https://github.com/dashevo/rust-dashcore?rev=51548a4a1b9eca7430f5f3caf94d9784886ff2e9)", + "dashcore", "dpp", "drive", "hex", "itertools", - "rand 0.8.5", + "rand", "rust_decimal", "rust_decimal_macros", "serde", @@ -1152,7 +1120,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d013fc25338cc558c5c2cfbad646908fb23591e2404481826742b651c9af7160" dependencies = [ "bitvec", - "rand_core 0.6.4", + "rand_core", "subtle", ] @@ -1202,12 +1170,6 @@ version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2022715d62ab30faffd124d40b76f4134a550a87792276512b18d63272333394" -[[package]] -name = "fuchsia-cprng" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba" - [[package]] name = "funty" version = "2.0.0" @@ -1345,7 +1307,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5dfbfb3a6cfbd390d5c9564ab283a0349b9b9fcd46a706c1eb10e0db70bfbac7" dependencies = [ "ff", - "rand_core 0.6.4", + "rand_core", "subtle", ] @@ -1496,7 +1458,7 @@ version = "1.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1885e79c1fc4b10f0e172c475f458b7f7b93061064d98c3293e98c5ba0c8b399" dependencies = [ - "autocfg 1.1.0", + "autocfg", "hashbrown 0.12.3", "serde", ] @@ -1739,7 +1701,7 @@ version = "0.4.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "435011366fe56583b16cf956f9df0095b405b82d76425bc8981c0e22e60ec4df" dependencies = [ - "autocfg 1.1.0", + "autocfg", "scopeguard", ] @@ -1779,7 +1741,7 @@ version = "0.5.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "043175f069eda7b85febe4a74abbaeff828d9f8b448515d3151a14a3542811aa" dependencies = [ - "autocfg 1.1.0", + "autocfg", ] [[package]] @@ -1788,7 +1750,7 @@ version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5de893c32cde5f383baa4c04c5d6dbdd735cfd4a794b0debdb2bb1b421da5ff4" dependencies = [ - "autocfg 1.1.0", + "autocfg", ] [[package]] @@ -1807,7 +1769,7 @@ dependencies = [ "integer-encoding", "jemallocator", "num_cpus", - "rand 0.8.5", + "rand", "storage", "thiserror", "time 0.3.17", @@ -1987,7 +1949,7 @@ version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "090c7f9998ee0ff65aa5b723e4009f7b217707f1fb5ea551329cc4d6231fb304" dependencies = [ - "autocfg 1.1.0", + "autocfg", "num-integer", "num-traits", ] @@ -1998,7 +1960,7 @@ version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f93ab6289c7b344a8a9f60f88d80aa20032336fe78da341afc91c8a2341fc75f" dependencies = [ - "autocfg 1.1.0", + "autocfg", "num-integer", "num-traits", ] @@ -2015,7 +1977,7 @@ version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b6b19411a9719e753aff12e5187b74d60d3dc449ec3f4dc21e3989c3f554bc95" dependencies = [ - "autocfg 1.1.0", + "autocfg", "num-traits", ] @@ -2034,7 +1996,7 @@ version = "0.1.45" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9" dependencies = [ - "autocfg 1.1.0", + "autocfg", "num-traits", ] @@ -2044,7 +2006,7 @@ version = "0.1.43" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7d03e6c028c5dc5cac6e2dec0efda81fc887605bb3d884578bb6d6bf7514e252" dependencies = [ - "autocfg 1.1.0", + "autocfg", "num-integer", "num-traits", ] @@ -2055,7 +2017,7 @@ version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5c000134b5dbf44adc5cb772486d335293351644b801551abe8f75c84cfa4aef" dependencies = [ - "autocfg 1.1.0", + "autocfg", "num-bigint 0.2.6", "num-integer", "num-traits", @@ -2067,7 +2029,7 @@ version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0638a1c9d0a3c0914158145bc76cff373a75a627e6ecbfb71cbe6f453a5a19b0" dependencies = [ - "autocfg 1.1.0", + "autocfg", "num-bigint 0.4.3", "num-integer", "num-traits", @@ -2079,7 +2041,7 @@ version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd" dependencies = [ - "autocfg 1.1.0", + "autocfg", "libm", ] @@ -2403,25 +2365,6 @@ version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dc33ff2d4973d518d823d61aa239014831e521c75da58e3df4840d3f47749d09" -[[package]] -name = "rand" -version = "0.6.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d71dacdc3c88c1fde3885a3be3fbab9f35724e6ce99467f7d9c5026132184ca" -dependencies = [ - "autocfg 0.1.8", - "libc", - "rand_chacha 0.1.1", - "rand_core 0.4.2", - "rand_hc", - "rand_isaac", - "rand_jitter", - "rand_os", - "rand_pcg", - "rand_xorshift", - "winapi", -] - [[package]] name = "rand" version = "0.8.5" @@ -2429,18 +2372,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" dependencies = [ "libc", - "rand_chacha 0.3.1", - "rand_core 0.6.4", -] - -[[package]] -name = "rand_chacha" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "556d3a1ca6600bfcbab7c7c91ccb085ac7fbbcd70e008a98742e7847f4f7bcef" -dependencies = [ - "autocfg 0.1.8", - "rand_core 0.3.1", + "rand_chacha", + "rand_core", ] [[package]] @@ -2450,24 +2383,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" dependencies = [ "ppv-lite86", - "rand_core 0.6.4", -] - -[[package]] -name = "rand_core" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a6fdeb83b075e8266dcc8762c22776f6877a63111121f5f8c7411e5be7eed4b" -dependencies = [ - "rand_core 0.4.2", + "rand_core", ] -[[package]] -name = "rand_core" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c33a3c44ca05fa6f1807d8e6743f3824e8509beca625669633be0acbdf509dc" - [[package]] name = "rand_core" version = "0.6.4" @@ -2484,69 +2402,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32cb0b9bc82b0a0876c2dd994a7e7a2683d3e7390ca40e6886785ef0c7e3ee31" dependencies = [ "num-traits", - "rand 0.8.5", -] - -[[package]] -name = "rand_hc" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b40677c7be09ae76218dc623efbf7b18e34bced3f38883af07bb75630a21bc4" -dependencies = [ - "rand_core 0.3.1", -] - -[[package]] -name = "rand_isaac" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ded997c9d5f13925be2a6fd7e66bf1872597f759fd9dd93513dd7e92e5a5ee08" -dependencies = [ - "rand_core 0.3.1", -] - -[[package]] -name = "rand_jitter" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1166d5c91dc97b88d1decc3285bb0a99ed84b05cfd0bc2341bdf2d43fc41e39b" -dependencies = [ - "libc", - "rand_core 0.4.2", - "winapi", -] - -[[package]] -name = "rand_os" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b75f676a1e053fc562eafbb47838d67c84801e38fc1ba459e8f180deabd5071" -dependencies = [ - "cloudabi", - "fuchsia-cprng", - "libc", - "rand_core 0.4.2", - "rdrand", - "winapi", -] - -[[package]] -name = "rand_pcg" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "abf9b09b01790cfe0364f52bf32995ea3c39f4d2dd011eac241d2914146d0b44" -dependencies = [ - "autocfg 0.1.8", - "rand_core 0.4.2", -] - -[[package]] -name = "rand_xorshift" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cbf7e9e623549b0e21f6e97cf8ecf247c1a8fd2e8a992ae265314300b2455d5c" -dependencies = [ - "rand_core 0.3.1", + "rand", ] [[package]] @@ -2580,15 +2436,6 @@ dependencies = [ "num_cpus", ] -[[package]] -name = "rdrand" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2" -dependencies = [ - "rand_core 0.3.1", -] - [[package]] name = "redox_syscall" version = "0.2.16" @@ -2686,7 +2533,7 @@ dependencies = [ "byteorder", "bytes", "num-traits", - "rand 0.8.5", + "rand", "rkyv", "serde", "serde_json", @@ -2762,16 +2609,6 @@ version = "4.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1c107b6f4780854c8b126e228ea8869f4d7b71260f962fefb57b996b8959ba6b" -[[package]] -name = "secp256k1" -version = "0.22.1" -source = "git+https://github.com/rust-bitcoin/rust-secp256k1?rev=f7cae46fc7733522cb84ef1b1ee1d1ed0cec2fd3#f7cae46fc7733522cb84ef1b1ee1d1ed0cec2fd3" -dependencies = [ - "rand 0.6.5", - "secp256k1-sys 0.5.0", - "serde", -] - [[package]] name = "secp256k1" version = "0.24.2" @@ -2779,19 +2616,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d9512ffd81e3a3503ed401f79c33168b9148c75038956039166cd750eaa037c3" dependencies = [ "bitcoin_hashes 0.11.0", - "rand 0.8.5", - "secp256k1-sys 0.6.1", + "rand", + "secp256k1-sys", "serde", ] -[[package]] -name = "secp256k1-sys" -version = "0.5.0" -source = "git+https://github.com/rust-bitcoin/rust-secp256k1?rev=f7cae46fc7733522cb84ef1b1ee1d1ed0cec2fd3#f7cae46fc7733522cb84ef1b1ee1d1ed0cec2fd3" -dependencies = [ - "cc", -] - [[package]] name = "secp256k1-sys" version = "0.6.1" @@ -2986,7 +2815,7 @@ version = "0.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4614a76b2a8be0058caa9dbbaf66d988527d86d003c11a94fbd335d7661edcef" dependencies = [ - "autocfg 1.1.0", + "autocfg", ] [[package]] @@ -3261,7 +3090,7 @@ version = "1.23.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "38a54aca0c15d014013256222ba0ebed095673f89345dd79119d912eb561b7a8" dependencies = [ - "autocfg 1.1.0", + "autocfg", "bytes", "libc", "memchr", From 618001cf5b57f940c095aa5dded818128f333f95 Mon Sep 17 00:00:00 2001 From: Djavid Gabibiyan Date: Thu, 12 Jan 2023 19:23:46 +0500 Subject: [PATCH 072/170] chore: after merge update --- packages/rs-drive/src/common/helpers/setup.rs | 2 +- packages/rs-drive/src/drive/document/convert.rs | 2 +- .../src/drive/identity/withdrawals/withdrawal_status.rs | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/rs-drive/src/common/helpers/setup.rs b/packages/rs-drive/src/common/helpers/setup.rs index dda3765c415..89e503ad453 100644 --- a/packages/rs-drive/src/common/helpers/setup.rs +++ b/packages/rs-drive/src/common/helpers/setup.rs @@ -111,7 +111,7 @@ pub fn setup_document( ) { drive .add_serialized_document_for_serialized_contract( - &document.to_cbor().unwrap(), + &document.to_buffer().unwrap(), &data_contract.to_cbor().unwrap(), withdrawals_contract::types::WITHDRAWAL, Some(data_contract.owner_id.to_buffer()), diff --git a/packages/rs-drive/src/drive/document/convert.rs b/packages/rs-drive/src/drive/document/convert.rs index 566b4c1b91e..fbee844f6bc 100644 --- a/packages/rs-drive/src/drive/document/convert.rs +++ b/packages/rs-drive/src/drive/document/convert.rs @@ -12,7 +12,7 @@ where dpp_documents .map(|document| { crate::contract::document::Document::from_cbor( - &document.to_cbor().map_err(|_| { + &document.to_buffer().map_err(|_| { Error::Drive(DriveError::CorruptedCodeExecution( "Can't convert dpp document to cbor", )) diff --git a/packages/rs-drive/src/drive/identity/withdrawals/withdrawal_status.rs b/packages/rs-drive/src/drive/identity/withdrawals/withdrawal_status.rs index c9207b9f1a7..62b43a9226e 100644 --- a/packages/rs-drive/src/drive/identity/withdrawals/withdrawal_status.rs +++ b/packages/rs-drive/src/drive/identity/withdrawals/withdrawal_status.rs @@ -50,7 +50,7 @@ impl Drive { let documents = documents .into_iter() .map(|document_cbor| { - Document::from_cbor(document_cbor).map_err(|_| { + Document::from_buffer(document_cbor).map_err(|_| { Error::Drive(DriveError::CorruptedCodeExecution( "Can't create a document from cbor", )) @@ -97,7 +97,7 @@ impl Drive { let documents = documents .into_iter() .map(|document_cbor| { - Document::from_cbor(document_cbor).map_err(|_| { + Document::from_buffer(document_cbor).map_err(|_| { Error::Drive(DriveError::CorruptedCodeExecution( "Can't create a document from cbor", )) From 316c6b31505714430cd12714296bebf76bc20f9d Mon Sep 17 00:00:00 2001 From: Djavid Gabibiyan Date: Thu, 12 Jan 2023 19:38:52 +0500 Subject: [PATCH 073/170] chore: after merge update --- .../src/tests/identity/validation/public_keys_validator_spec.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/rs-dpp/src/tests/identity/validation/public_keys_validator_spec.rs b/packages/rs-dpp/src/tests/identity/validation/public_keys_validator_spec.rs index 099f8628874..d17d11fdfa1 100644 --- a/packages/rs-dpp/src/tests/identity/validation/public_keys_validator_spec.rs +++ b/packages/rs-dpp/src/tests/identity/validation/public_keys_validator_spec.rs @@ -417,7 +417,7 @@ pub fn should_return_invalid_result_if_key_data_is_not_a_valid_der() { ); assert_eq!( error.validation_error().as_ref().unwrap().message(), - "Key secp256k1 error: secp: malformed public key" + "Key secp256k1 error: malformed public key" ); } From 6c6f2cff5746df819683f34319ff1c0f9c3ff146 Mon Sep 17 00:00:00 2001 From: Djavid Gabibiyan Date: Fri, 13 Jan 2023 10:44:04 +0500 Subject: [PATCH 074/170] chore: trying to use empty quorum hash --- .../js-drive/lib/abci/handlers/proposal/beginBlockFactory.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/js-drive/lib/abci/handlers/proposal/beginBlockFactory.js b/packages/js-drive/lib/abci/handlers/proposal/beginBlockFactory.js index 3e217276da7..2a7fda88f4d 100644 --- a/packages/js-drive/lib/abci/handlers/proposal/beginBlockFactory.js +++ b/packages/js-drive/lib/abci/handlers/proposal/beginBlockFactory.js @@ -124,7 +124,7 @@ function beginBlockFactory( blockHeight: height.toNumber(), blockTimeMs: proposalBlockExecutionContext.getTimeMs(), proposerProTxHash, - validatorSetQuorumHash: lastCommitInfo.quorumHash, + validatorSetQuorumHash: Buffer.alloc(32, 0), coreChainLockedHeight, lastSyncedCoreHeight, }; From 9b067864392425042f81f66ff8322b715432ef09 Mon Sep 17 00:00:00 2001 From: Djavid Gabibiyan Date: Mon, 16 Jan 2023 20:39:28 +0500 Subject: [PATCH 075/170] chore: fixes for CI --- .github/workflows/js-checks.yml | 2 +- packages/dashmate/configs/system/base.js | 2 +- packages/rs-drive-nodejs/package.json | 2 +- packages/rs-drive-nodejs/scripts/build.sh | 6 ++++-- 4 files changed, 7 insertions(+), 5 deletions(-) diff --git a/.github/workflows/js-checks.yml b/.github/workflows/js-checks.yml index f73bc0fcf4b..d187e0f3958 100644 --- a/.github/workflows/js-checks.yml +++ b/.github/workflows/js-checks.yml @@ -118,7 +118,7 @@ jobs: - name: Build package and dependencies run: yarn build --filter "+${{ inputs.package }}" env: - CARGO_BUILD_PROFILE: test + ENABLE_CORE_RPC_MOCKING: true - name: Build SDK run: yarn build --filter "+dash" diff --git a/packages/dashmate/configs/system/base.js b/packages/dashmate/configs/system/base.js index e3813a78c67..b84e8c76feb 100644 --- a/packages/dashmate/configs/system/base.js +++ b/packages/dashmate/configs/system/base.js @@ -37,7 +37,7 @@ module.exports = { }, core: { docker: { - image: 'dashpay/dashd:18.1.1', + image: 'dashpay/dashd:18.2', }, p2p: { port: 20001, diff --git a/packages/rs-drive-nodejs/package.json b/packages/rs-drive-nodejs/package.json index eae48a40090..bd204f72166 100644 --- a/packages/rs-drive-nodejs/package.json +++ b/packages/rs-drive-nodejs/package.json @@ -5,7 +5,7 @@ "main": "Drive.js", "scripts": { "build": "yarn exec scripts/build.sh", - "test": "CARGO_BUILD_PROFILE=test ultra --build && mocha test", + "test": "ENABLE_CORE_RPC_MOCKING=true ultra --build && mocha test", "lint": "eslint ." }, "files": [ diff --git a/packages/rs-drive-nodejs/scripts/build.sh b/packages/rs-drive-nodejs/scripts/build.sh index a770212933e..343c87c6d78 100755 --- a/packages/rs-drive-nodejs/scripts/build.sh +++ b/packages/rs-drive-nodejs/scripts/build.sh @@ -6,13 +6,15 @@ FEATURE_FLAG="" if [ -n "$CARGO_BUILD_PROFILE" ]; then if [ "$CARGO_BUILD_PROFILE" == "release" ]; then PROFILE_ARG="--release" - elif [ "$CARGO_BUILD_PROFILE" == "test" ]; then - FEATURE_FLAG="--features enable-core-rpc-mocking" elif [ "$CARGO_BUILD_PROFILE" != "debug" ]; then PROFILE_ARG="--profile $CARGO_BUILD_PROFILE" fi fi +if [ -n "$ENABLE_CORE_RPC_MOCKING" ]; then + FEATURE_FLAG="--features enable-core-rpc-mocking" +fi + cargo-cp-artifact -ac drive-nodejs native/index.node -- \ cargo build --message-format=json-render-diagnostics $PROFILE_ARG $FEATURE_FLAG \ && neon-tag-prebuild \ From f70fdddfca8be68a556b4aa2eb79ec9736899546 Mon Sep 17 00:00:00 2001 From: Djavid Gabibiyan Date: Mon, 16 Jan 2023 20:48:55 +0500 Subject: [PATCH 076/170] empty commit From 8752dd17d6ca44cfc894966e6662973a8494161c Mon Sep 17 00:00:00 2001 From: Djavid Gabibiyan Date: Wed, 18 Jan 2023 11:13:16 +0500 Subject: [PATCH 077/170] chore: missing rename --- .../abci/handlers/verifyVoteExtensionHandlerFactory.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/js-drive/lib/abci/handlers/verifyVoteExtensionHandlerFactory.js b/packages/js-drive/lib/abci/handlers/verifyVoteExtensionHandlerFactory.js index e775a3d962f..c414ef3e4a7 100644 --- a/packages/js-drive/lib/abci/handlers/verifyVoteExtensionHandlerFactory.js +++ b/packages/js-drive/lib/abci/handlers/verifyVoteExtensionHandlerFactory.js @@ -32,13 +32,13 @@ function verifyVoteExtensionHandlerFactory(proposalBlockExecutionContext) { voteExtensions, } = request; - const consensusLogger = proposalBlockExecutionContext.getConsensusLogger() + const contextLogger = proposalBlockExecutionContext.getContextLogger() .child({ abciMethod: 'verifyVoteExtension', }); - consensusLogger.debug('VerifyVote ABCI method requested'); - consensusLogger.trace({ request }); + contextLogger.debug('VerifyVote ABCI method requested'); + contextLogger.trace({ request }); const unsignedWithdrawalTransactionsMap = proposalBlockExecutionContext .getWithdrawalTransactionsMap(); @@ -68,7 +68,7 @@ function verifyVoteExtensionHandlerFactory(proposalBlockExecutionContext) { Math.min(30, extensionString.length), ); - consensusLogger.warn({ + contextLogger.warn({ type: nextExtension.type, extension: extensionString, }, `${nextExtension.type} vote extension ${extensionTruncatedString}... was not found in verify request`); From 44a59191ab1bef8666f0c021721d237faf68ac0a Mon Sep 17 00:00:00 2001 From: Djavid Gabibiyan Date: Wed, 18 Jan 2023 15:12:19 +0500 Subject: [PATCH 078/170] chore: updated to Tenderdash dev.8 --- packages/dashmate/configs/system/base.js | 2 +- .../js-drive/lib/abci/handlers/proposal/beginBlockFactory.js | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/packages/dashmate/configs/system/base.js b/packages/dashmate/configs/system/base.js index e50fbab1164..bb1df846e69 100644 --- a/packages/dashmate/configs/system/base.js +++ b/packages/dashmate/configs/system/base.js @@ -144,7 +144,7 @@ module.exports = { }, tenderdash: { docker: { - image: 'dashpay/tenderdash:0.10.0-dev.6', + image: 'dashpay/tenderdash:0.10.0-dev.8', }, p2p: { port: 26656, diff --git a/packages/js-drive/lib/abci/handlers/proposal/beginBlockFactory.js b/packages/js-drive/lib/abci/handlers/proposal/beginBlockFactory.js index 171f097e6da..52eb8ce7e0d 100644 --- a/packages/js-drive/lib/abci/handlers/proposal/beginBlockFactory.js +++ b/packages/js-drive/lib/abci/handlers/proposal/beginBlockFactory.js @@ -60,6 +60,7 @@ function beginBlockFactory( time, proposerProTxHash, round, + quorumHash, } = request; if (proposalBlockExecutionContext.isEmpty()) { @@ -124,7 +125,7 @@ function beginBlockFactory( blockHeight: height.toNumber(), blockTimeMs: proposalBlockExecutionContext.getTimeMs(), proposerProTxHash, - validatorSetQuorumHash: Buffer.alloc(32, 0), + validatorSetQuorumHash: quorumHash, coreChainLockedHeight, lastSyncedCoreHeight, }; From 21fa9dd523512a3de77e045a1d8bb5add4e550ed Mon Sep 17 00:00:00 2001 From: Djavid Gabibiyan Date: Fri, 20 Jan 2023 16:40:07 +0500 Subject: [PATCH 079/170] chore: missing fraction of the request --- .../js-drive/lib/abci/handlers/prepareProposalHandlerFactory.js | 2 ++ .../lib/abci/handlers/proposal/processProposalFactory.js | 2 ++ 2 files changed, 4 insertions(+) diff --git a/packages/js-drive/lib/abci/handlers/prepareProposalHandlerFactory.js b/packages/js-drive/lib/abci/handlers/prepareProposalHandlerFactory.js index 0c0b84d915d..7eac78b5b14 100644 --- a/packages/js-drive/lib/abci/handlers/prepareProposalHandlerFactory.js +++ b/packages/js-drive/lib/abci/handlers/prepareProposalHandlerFactory.js @@ -53,6 +53,7 @@ function prepareProposalHandlerFactory( time, proposerProTxHash, round, + quorumHash, } = request; const contextLogger = createContextLogger(logger, { @@ -78,6 +79,7 @@ function prepareProposalHandlerFactory( time, proposerProTxHash: Buffer.from(proposerProTxHash), round, + quorumHash, }, contextLogger, ); diff --git a/packages/js-drive/lib/abci/handlers/proposal/processProposalFactory.js b/packages/js-drive/lib/abci/handlers/proposal/processProposalFactory.js index 506c1fc9b57..162259982fa 100644 --- a/packages/js-drive/lib/abci/handlers/proposal/processProposalFactory.js +++ b/packages/js-drive/lib/abci/handlers/proposal/processProposalFactory.js @@ -43,6 +43,7 @@ function processProposalFactory( time, proposerProTxHash, round, + quorumHash, } = request; contextLogger.info(`Processing a block proposal for height #${height} round #${round}`); @@ -56,6 +57,7 @@ function processProposalFactory( time, proposerProTxHash: Buffer.from(proposerProTxHash), round, + quorumHash, }, contextLogger, ); From dec761802fa1823064bb5bbfb0a322846c681759 Mon Sep 17 00:00:00 2001 From: Djavid Gabibiyan Date: Fri, 20 Jan 2023 17:20:54 +0500 Subject: [PATCH 080/170] chore: test fix --- .../unit/abci/handlers/prepareProposalHandlerFactory.spec.js | 5 +++++ .../abci/handlers/proposal/processProposalFactory.spec.js | 5 +++++ 2 files changed, 10 insertions(+) diff --git a/packages/js-drive/test/unit/abci/handlers/prepareProposalHandlerFactory.spec.js b/packages/js-drive/test/unit/abci/handlers/prepareProposalHandlerFactory.spec.js index 2bb3e3f5640..a925e8965b0 100644 --- a/packages/js-drive/test/unit/abci/handlers/prepareProposalHandlerFactory.spec.js +++ b/packages/js-drive/test/unit/abci/handlers/prepareProposalHandlerFactory.spec.js @@ -34,6 +34,7 @@ describe('prepareProposalHandlerFactory', () => { let round; let executionTimerMock; let createContextLoggerMock; + let quorumHash; beforeEach(function beforeEach() { round = 1; @@ -126,6 +127,8 @@ describe('prepareProposalHandlerFactory', () => { const localLastCommit = {}; + quorumHash = Buffer.alloc(32, 0); + request = { height, maxTxBytes, @@ -136,6 +139,7 @@ describe('prepareProposalHandlerFactory', () => { time, proposerProTxHash, round, + quorumHash, }; }); @@ -166,6 +170,7 @@ describe('prepareProposalHandlerFactory', () => { time: request.time, proposerProTxHash: Buffer.from(request.proposerProTxHash), round, + quorumHash, }, loggerMock, ); diff --git a/packages/js-drive/test/unit/abci/handlers/proposal/processProposalFactory.spec.js b/packages/js-drive/test/unit/abci/handlers/proposal/processProposalFactory.spec.js index cda64a71068..4e0f2996206 100644 --- a/packages/js-drive/test/unit/abci/handlers/proposal/processProposalFactory.spec.js +++ b/packages/js-drive/test/unit/abci/handlers/proposal/processProposalFactory.spec.js @@ -30,6 +30,7 @@ describe('processProposalFactory', () => { let proposalBlockExecutionContextMock; let round; let executionTimerMock; + let quorumHash; beforeEach(function beforeEach() { round = 0; @@ -110,6 +111,8 @@ describe('processProposalFactory', () => { signature: '1897ce8f54d2070f44ca5c29983b68b391e8137c25e44f67416e579f3e3bdfef7b4fd22db7818399147e52907998857b0fbc8edfdc40a64f2c7df0e88544d31d12ca8c15e73d50dda25ca23f754ed3f789ed4bcb392161995f464017c10df404', }; + quorumHash = Buffer.alloc(32, 0); + request = { round, height, @@ -120,6 +123,7 @@ describe('processProposalFactory', () => { time, proposerProTxHash, coreChainLockUpdate, + quorumHash, }; }); @@ -142,6 +146,7 @@ describe('processProposalFactory', () => { time: request.time, proposerProTxHash: Buffer.from(request.proposerProTxHash), round, + quorumHash, }, loggerMock, ); From ff4710718e6f30fd79e14cecca33ae25059a596e Mon Sep 17 00:00:00 2001 From: Djavid Gabibiyan Date: Tue, 24 Jan 2023 18:58:53 +0500 Subject: [PATCH 081/170] chore: add data triggers --- .../data_trigger/get_data_triggers_factory.rs | 23 ++++ packages/rs-dpp/src/data_trigger/mod.rs | 1 + .../withdrawals_data_triggers/mod.rs | 129 ++++++++++++++++++ 3 files changed, 153 insertions(+) create mode 100644 packages/rs-dpp/src/data_trigger/withdrawals_data_triggers/mod.rs diff --git a/packages/rs-dpp/src/data_trigger/get_data_triggers_factory.rs b/packages/rs-dpp/src/data_trigger/get_data_triggers_factory.rs index eeed6b9b0ba..5ce20f13f54 100644 --- a/packages/rs-dpp/src/data_trigger/get_data_triggers_factory.rs +++ b/packages/rs-dpp/src/data_trigger/get_data_triggers_factory.rs @@ -3,6 +3,7 @@ use std::vec; use crate::{ contracts::{ dashpay_contract, dpns_contract, feature_flags_contract, masternode_reward_shares_contract, + withdrawals_contract, }, document::document_transition::Action, errors::ProtocolError, @@ -53,6 +54,14 @@ fn data_triggers() -> Result, ProtocolError> { &masternode_reward_shares_contract::system_ids().contract_id, Encoding::Base58, )?; + let withdrawals_owner_id = Identifier::from_string( + &withdrawals_contract::system_ids().owner_id, + Encoding::Base58, + )?; + let withdrawals_contract_id = Identifier::from_string( + &withdrawals_contract::system_ids().contract_id, + Encoding::Base58, + )?; let data_triggers = vec![ DataTrigger { @@ -146,6 +155,20 @@ fn data_triggers() -> Result, ProtocolError> { data_trigger_kind: DataTriggerKind::CreateDataContractRequest, top_level_identity: None, }, + DataTrigger { + data_contract_id: withdrawals_contract_id.clone(), + document_type: withdrawals_contract::types::WITHDRAWAL.to_string(), + transition_action: Action::Create, + data_trigger_kind: DataTriggerKind::DataTriggerReject, + top_level_identity: None, + }, + DataTrigger { + data_contract_id: withdrawals_contract_id, + document_type: withdrawals_contract::types::WITHDRAWAL.to_string(), + transition_action: Action::Replace, + data_trigger_kind: DataTriggerKind::DataTriggerReject, + top_level_identity: None, + }, ]; Ok(data_triggers) } diff --git a/packages/rs-dpp/src/data_trigger/mod.rs b/packages/rs-dpp/src/data_trigger/mod.rs index 6041b1f6f69..ceef397ebb4 100644 --- a/packages/rs-dpp/src/data_trigger/mod.rs +++ b/packages/rs-dpp/src/data_trigger/mod.rs @@ -22,6 +22,7 @@ pub mod dpns_triggers; pub mod feature_flags_data_triggers; pub mod get_data_triggers_factory; pub mod reward_share_data_triggers; +pub mod withdrawals_data_triggers; mod data_trigger_execution_result; mod reject_data_trigger; diff --git a/packages/rs-dpp/src/data_trigger/withdrawals_data_triggers/mod.rs b/packages/rs-dpp/src/data_trigger/withdrawals_data_triggers/mod.rs new file mode 100644 index 00000000000..1072810eabc --- /dev/null +++ b/packages/rs-dpp/src/data_trigger/withdrawals_data_triggers/mod.rs @@ -0,0 +1,129 @@ +use anyhow::{anyhow, bail}; +use serde_json::json; + +use crate::contracts::withdrawals_contract; +use crate::data_trigger::DataTriggerError; +use crate::data_trigger::DataTriggerExecutionContext; +use crate::data_trigger::DataTriggerExecutionResult; +use crate::document::Document; +use crate::get_from_transition; +use crate::prelude::DocumentTransition; +use crate::prelude::Identifier; +use crate::state_repository::StateRepositoryLike; + +pub async fn delete_withdrawal_data_trigger<'a, SR>( + document_transition: &DocumentTransition, + context: &DataTriggerExecutionContext<'a, SR>, + _top_level_identity: Option<&Identifier>, +) -> Result +where + SR: StateRepositoryLike, +{ + let mut result = DataTriggerExecutionResult::default(); + + if context.state_transition_execution_context.is_dry_run() { + return Ok(result); + } + + let dt_delete = match document_transition { + DocumentTransition::Delete(d) => d, + _ => bail!( + "the Document Transition {} isn't 'DELETE'", + get_from_transition!(document_transition, id) + ), + }; + + let withdrawals: Vec = context + .state_repository + .fetch_documents( + &context.data_contract.id, + withdrawals_contract::types::WITHDRAWAL, + json!({ + "where" : [ + ["$id", "==", dt_delete.base.id], + ] + }), + context.state_transition_execution_context, + ) + .await?; + + if withdrawals.is_empty() { + let err = DataTriggerError::DataTriggerConditionError { + data_contract_id: context.data_contract.id.clone(), + document_transition_id: dt_delete.base.id.clone(), + message: "Withdrawal document was not found".to_string(), + owner_id: Some(context.owner_id.clone()), + document_transition: Some(DocumentTransition::Delete(dt_delete.clone())), + }; + + result.add_error(err.into()); + + return Ok(result); + } + + let withdrawal = withdrawals.get(0).unwrap(); + + let status = withdrawal + .get("status") + .ok_or(anyhow!( + "can't get withdrawal status property from the document" + ))? + .as_u64() + .ok_or(anyhow!("can't convert withdrawal status to u64"))? as u8; + + if status != withdrawals_contract::statuses::COMPLETE + || status != withdrawals_contract::statuses::EXPIRED + { + let err = DataTriggerError::DataTriggerConditionError { + data_contract_id: context.data_contract.id.clone(), + document_transition_id: dt_delete.base.id.clone(), + message: "withdrawal deletion is allowed only for COMPLETE and EXPIRED statuses" + .to_string(), + owner_id: Some(context.owner_id.clone()), + document_transition: Some(DocumentTransition::Delete(dt_delete.clone())), + }; + + result.add_error(err.into()); + + return Ok(result); + } + + Ok(result) +} + +#[cfg(test)] +mod test { + use super::delete_withdrawal_data_trigger; + use crate::{ + data_trigger::DataTriggerExecutionContext, + document::document_transition::DocumentTransition, + state_repository::MockStateRepositoryLike, + state_transition::state_transition_execution_context::StateTransitionExecutionContext, + tests::fixtures::get_data_contract_fixture, + }; + + #[tokio::test] + async fn should_successfully_execute_on_dry_run() { + let transition_execution_context = StateTransitionExecutionContext::default(); + let state_repository = MockStateRepositoryLike::new(); + let data_contract = get_data_contract_fixture(None); + let owner_id = data_contract.owner_id().to_owned(); + + let document_transition = DocumentTransition::Create(Default::default()); + let data_trigger_context = DataTriggerExecutionContext { + data_contract: &data_contract, + owner_id: &owner_id, + state_repository: &state_repository, + state_transition_execution_context: &transition_execution_context, + }; + + transition_execution_context.enable_dry_run(); + + let result = + delete_withdrawal_data_trigger(&document_transition, &data_trigger_context, None) + .await + .expect("the execution result should be returned"); + + assert!(result.is_ok()); + } +} From acc04b88c183f247199dc430507c17f84db4dbdf Mon Sep 17 00:00:00 2001 From: Djavid Gabibiyan Date: Tue, 24 Jan 2023 20:02:55 +0500 Subject: [PATCH 082/170] chore: linter fix --- packages/dashmate/configs/migrations.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/dashmate/configs/migrations.js b/packages/dashmate/configs/migrations.js index c90165756dd..183aacd22c1 100644 --- a/packages/dashmate/configs/migrations.js +++ b/packages/dashmate/configs/migrations.js @@ -4,7 +4,7 @@ const lodashGet = require('lodash/get'); const systemConfigs = require('./system'); -const {NETWORK_TESTNET} = require('../src/constants'); +const { NETWORK_TESTNET } = require('../src/constants'); module.exports = { '0.17.2': (configFile) => { From 6a36a81b171771243564b37dcc3af84db536459c Mon Sep 17 00:00:00 2001 From: Djavid Gabibiyan Date: Tue, 24 Jan 2023 20:27:52 +0500 Subject: [PATCH 083/170] chore: cargo fmt --- .../apply_identity_credit_withdrawal_transition_factory.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/rs-dpp/src/identity/state_transition/identity_credit_withdrawal_transition/apply_identity_credit_withdrawal_transition_factory.rs b/packages/rs-dpp/src/identity/state_transition/identity_credit_withdrawal_transition/apply_identity_credit_withdrawal_transition_factory.rs index 3d34fdad7b7..ffd6736e981 100644 --- a/packages/rs-dpp/src/identity/state_transition/identity_credit_withdrawal_transition/apply_identity_credit_withdrawal_transition_factory.rs +++ b/packages/rs-dpp/src/identity/state_transition/identity_credit_withdrawal_transition/apply_identity_credit_withdrawal_transition_factory.rs @@ -8,8 +8,8 @@ use crate::{ data_contract::DataContract, document::Document, identity::state_transition::identity_credit_withdrawal_transition::Pooling, - state_repository::StateRepositoryLike, prelude::Identifier, + state_repository::StateRepositoryLike, state_transition::StateTransitionConvert, state_transition::StateTransitionLike, util::{entropy_generator::generate, json_value::JsonValueExt, string_encoding::Encoding}, From 58c64d42103308146ce4e32ab690ecf4e4e080f7 Mon Sep 17 00:00:00 2001 From: Djavid Gabibiyan Date: Thu, 26 Jan 2023 23:15:09 +0500 Subject: [PATCH 084/170] chore: PR comments --- .github/workflows/js-checks.yml | 2 +- .../src/contracts/withdrawals_contract.rs | 56 +++++-- .../data_trigger/get_data_triggers_factory.rs | 19 +-- packages/rs-dpp/src/data_trigger/mod.rs | 5 + .../withdrawals_data_triggers/mod.rs | 8 +- packages/rs-dpp/src/identity/identity.rs | 11 ++ ...ty_credit_withdrawal_transition_factory.rs | 44 +++--- ...tity_credit_withdrawal_transition_basic.rs | 28 +++- .../fixtures/get_withdrawals_data_contract.rs | 6 +- ...edit_withdrawal_transition_factory_spec.rs | 3 +- packages/rs-drive-abci/src/abci/handlers.rs | 2 +- .../src/identity_credit_withdrawal/mod.rs | 145 ++++++++---------- packages/rs-drive-nodejs/Cargo.toml | 2 +- packages/rs-drive-nodejs/package.json | 2 +- packages/rs-drive-nodejs/scripts/build.sh | 6 +- packages/rs-drive-nodejs/src/lib.rs | 2 +- .../identity/withdrawals/withdrawal_status.rs | 48 ++---- 17 files changed, 199 insertions(+), 190 deletions(-) diff --git a/.github/workflows/js-checks.yml b/.github/workflows/js-checks.yml index d187e0f3958..76c685fe8fb 100644 --- a/.github/workflows/js-checks.yml +++ b/.github/workflows/js-checks.yml @@ -118,7 +118,7 @@ jobs: - name: Build package and dependencies run: yarn build --filter "+${{ inputs.package }}" env: - ENABLE_CORE_RPC_MOCKING: true + NODE_ENV: test - name: Build SDK run: yarn build --filter "+dash" diff --git a/packages/rs-dpp/src/contracts/withdrawals_contract.rs b/packages/rs-dpp/src/contracts/withdrawals_contract.rs index 2f8b322c3f9..4d0c4474924 100644 --- a/packages/rs-dpp/src/contracts/withdrawals_contract.rs +++ b/packages/rs-dpp/src/contracts/withdrawals_contract.rs @@ -1,20 +1,52 @@ -use super::SystemIDs; +use lazy_static::lazy_static; +use num_enum::{IntoPrimitive, TryFromPrimitive}; +use serde_repr::{Deserialize_repr, Serialize_repr}; + +use crate::prelude::Identifier; pub mod types { pub const WITHDRAWAL: &str = "withdrawal"; } -pub mod statuses { - pub const QUEUED: u8 = 0; - pub const POOLED: u8 = 1; - pub const BROADCASTED: u8 = 2; - pub const COMPLETE: u8 = 3; - pub const EXPIRED: u8 = 4; +pub mod property_names { + pub const TRANSACTION_ID: &str = "transactionId"; + pub const TRANSACTION_SIGN_HEIGHT: &str = "transactionSignHeight"; + pub const TRANSACTION_INDEX: &str = "transactionIndex"; + pub const AMOUNT: &str = "amount"; + pub const CORE_FEE_PER_BYTE: &str = "coreFeePerByte"; + pub const POOLING: &str = "pooling"; + pub const OUTPUT_SCRIPT: &str = "outputScript"; + pub const STATUS: &str = "status"; + pub const CREATE_AT: &str = "$createdAt"; +} + +#[repr(u8)] +#[derive( + Serialize_repr, + Deserialize_repr, + PartialEq, + Eq, + Clone, + Copy, + Debug, + TryFromPrimitive, + IntoPrimitive, +)] +pub enum Status { + QUEUED = 0, + POOLED = 1, + BROADCASTED = 2, + COMPLETE = 3, + EXPIRED = 4, } -pub fn system_ids() -> SystemIDs { - SystemIDs { - contract_id: "4fJLR2GYTPFdomuTVvNy3VRrvWgvkKPzqehEBpNf2nk6".to_string(), - owner_id: "CUjAw7eD64wmaznNrfC5sKdn4Lpr1wBvWKMjGLrmEs5h".to_string(), - } +lazy_static! { + pub static ref CONTRACT_ID: Identifier = Identifier::new([ + 54, 98, 187, 97, 225, 127, 174, 62, 162, 148, 207, 96, 49, 151, 251, 10, 171, 109, 81, 24, + 11, 216, 182, 16, 76, 73, 68, 166, 47, 226, 217, 127 + ]); + pub static ref OWNER_ID: Identifier = Identifier::new([ + 170, 138, 235, 213, 173, 122, 202, 36, 243, 48, 61, 185, 146, 50, 146, 255, 194, 133, 221, + 176, 188, 82, 144, 69, 234, 198, 106, 35, 245, 167, 46, 192 + ]); } diff --git a/packages/rs-dpp/src/data_trigger/get_data_triggers_factory.rs b/packages/rs-dpp/src/data_trigger/get_data_triggers_factory.rs index 5ce20f13f54..1c71d982327 100644 --- a/packages/rs-dpp/src/data_trigger/get_data_triggers_factory.rs +++ b/packages/rs-dpp/src/data_trigger/get_data_triggers_factory.rs @@ -54,14 +54,8 @@ fn data_triggers() -> Result, ProtocolError> { &masternode_reward_shares_contract::system_ids().contract_id, Encoding::Base58, )?; - let withdrawals_owner_id = Identifier::from_string( - &withdrawals_contract::system_ids().owner_id, - Encoding::Base58, - )?; - let withdrawals_contract_id = Identifier::from_string( - &withdrawals_contract::system_ids().contract_id, - Encoding::Base58, - )?; + let withdrawals_owner_id = withdrawals_contract::OWNER_ID.clone(); + let withdrawals_contract_id = withdrawals_contract::CONTRACT_ID.clone(); let data_triggers = vec![ DataTrigger { @@ -163,12 +157,19 @@ fn data_triggers() -> Result, ProtocolError> { top_level_identity: None, }, DataTrigger { - data_contract_id: withdrawals_contract_id, + data_contract_id: withdrawals_contract_id.clone(), document_type: withdrawals_contract::types::WITHDRAWAL.to_string(), transition_action: Action::Replace, data_trigger_kind: DataTriggerKind::DataTriggerReject, top_level_identity: None, }, + DataTrigger { + data_contract_id: withdrawals_contract_id, + document_type: withdrawals_contract::types::WITHDRAWAL.to_string(), + transition_action: Action::Delete, + data_trigger_kind: DataTriggerKind::DeleteWithdrawal, + top_level_identity: Some(withdrawals_owner_id), + }, ]; Ok(data_triggers) } diff --git a/packages/rs-dpp/src/data_trigger/mod.rs b/packages/rs-dpp/src/data_trigger/mod.rs index ceef397ebb4..b640f71b689 100644 --- a/packages/rs-dpp/src/data_trigger/mod.rs +++ b/packages/rs-dpp/src/data_trigger/mod.rs @@ -14,6 +14,7 @@ use self::dashpay_data_triggers::create_contact_request_data_trigger; use self::dpns_triggers::create_domain_data_trigger; use self::feature_flags_data_triggers::create_feature_flag_data_trigger; use self::reward_share_data_triggers::create_masternode_reward_shares_data_trigger; +use self::withdrawals_data_triggers::delete_withdrawal_data_trigger; mod data_trigger_execution_context; @@ -42,6 +43,7 @@ pub enum DataTriggerKind { DataTriggerRewardShare, DataTriggerReject, CrateFeatureFlag, + DeleteWithdrawal, } pub struct DataTrigger { @@ -127,6 +129,9 @@ where create_masternode_reward_shares_data_trigger(document_transition, context, identifier) .await } + DataTriggerKind::DeleteWithdrawal => { + delete_withdrawal_data_trigger(document_transition, context, identifier).await + } } } diff --git a/packages/rs-dpp/src/data_trigger/withdrawals_data_triggers/mod.rs b/packages/rs-dpp/src/data_trigger/withdrawals_data_triggers/mod.rs index 1072810eabc..b0fe51627f5 100644 --- a/packages/rs-dpp/src/data_trigger/withdrawals_data_triggers/mod.rs +++ b/packages/rs-dpp/src/data_trigger/withdrawals_data_triggers/mod.rs @@ -21,10 +21,6 @@ where { let mut result = DataTriggerExecutionResult::default(); - if context.state_transition_execution_context.is_dry_run() { - return Ok(result); - } - let dt_delete = match document_transition { DocumentTransition::Delete(d) => d, _ => bail!( @@ -71,8 +67,8 @@ where .as_u64() .ok_or(anyhow!("can't convert withdrawal status to u64"))? as u8; - if status != withdrawals_contract::statuses::COMPLETE - || status != withdrawals_contract::statuses::EXPIRED + if status != withdrawals_contract::Status::COMPLETE as u8 + || status != withdrawals_contract::Status::EXPIRED as u8 { let err = DataTriggerError::DataTriggerConditionError { data_contract_id: context.data_contract.id.clone(), diff --git a/packages/rs-dpp/src/identity/identity.rs b/packages/rs-dpp/src/identity/identity.rs index 405bd35b0ef..71119cb9ccd 100644 --- a/packages/rs-dpp/src/identity/identity.rs +++ b/packages/rs-dpp/src/identity/identity.rs @@ -116,6 +116,17 @@ impl Identity { self.revision } + /// Increment revision + pub fn increment_revision(&mut self) -> Result<(), ProtocolError> { + let result = self.revision.checked_add(1).ok_or(ProtocolError::Generic( + "identity revision is at max level".to_string(), + ))?; + + self.revision = result; + + Ok(()) + } + /// Get metadata pub fn get_metadata(&self) -> Option<&Metadata> { self.metadata.as_ref() diff --git a/packages/rs-dpp/src/identity/state_transition/identity_credit_withdrawal_transition/apply_identity_credit_withdrawal_transition_factory.rs b/packages/rs-dpp/src/identity/state_transition/identity_credit_withdrawal_transition/apply_identity_credit_withdrawal_transition_factory.rs index ffd6736e981..6c1a564a54a 100644 --- a/packages/rs-dpp/src/identity/state_transition/identity_credit_withdrawal_transition/apply_identity_credit_withdrawal_transition_factory.rs +++ b/packages/rs-dpp/src/identity/state_transition/identity_credit_withdrawal_transition/apply_identity_credit_withdrawal_transition_factory.rs @@ -6,13 +6,12 @@ use serde_json::{json, Value as JsonValue}; use crate::{ contracts::withdrawals_contract, data_contract::DataContract, + document::generate_document_id, document::Document, identity::state_transition::identity_credit_withdrawal_transition::Pooling, - prelude::Identifier, state_repository::StateRepositoryLike, - state_transition::StateTransitionConvert, state_transition::StateTransitionLike, - util::{entropy_generator::generate, json_value::JsonValueExt, string_encoding::Encoding}, + util::{entropy_generator::generate, json_value::JsonValueExt}, }; use super::IdentityCreditWithdrawalTransition; @@ -39,14 +38,8 @@ where &self, state_transition: &IdentityCreditWithdrawalTransition, ) -> Result<()> { - let data_contract_id = Identifier::from_string( - &withdrawals_contract::system_ids().contract_id, - Encoding::Base58, - )?; - let data_contract_owner_id = Identifier::from_string( - &withdrawals_contract::system_ids().owner_id, - Encoding::Base58, - )?; + let data_contract_id = withdrawals_contract::CONTRACT_ID.clone(); + let data_contract_owner_id = withdrawals_contract::OWNER_ID.clone(); let maybe_withdrawals_data_contract: Option = self .state_repository @@ -73,22 +66,24 @@ where * 1000; let document_data = json!({ - "amount": state_transition.amount, - "coreFeePerByte": state_transition.core_fee_per_byte, - "pooling": Pooling::Never, - "outputScript": state_transition.output_script.as_bytes(), - "status": withdrawals_contract::statuses::QUEUED, + withdrawals_contract::property_names::AMOUNT: state_transition.amount, + withdrawals_contract::property_names::CORE_FEE_PER_BYTE: state_transition.core_fee_per_byte, + withdrawals_contract::property_names::POOLING: Pooling::Never, + withdrawals_contract::property_names::OUTPUT_SCRIPT: state_transition.output_script.as_bytes(), + withdrawals_contract::property_names::STATUS: withdrawals_contract::Status::QUEUED, }); - let document_id_bytes: [u8; 32] = state_transition - .hash(true)? - .try_into() - .map_err(|_| anyhow!("Can't convert state transition hash to a document id"))?; + let document_id = generate_document_id::generate_document_id( + &data_contract_id, + &data_contract_owner_id, + &document_type, + &document_entropy, + ); // TODO: use DocumentFactory once it is complete let withdrawal_document = Document { protocol_version: state_transition.protocol_version, - id: Identifier::new(document_id_bytes), + id: document_id, document_type, revision: 0, data_contract_id, @@ -98,7 +93,7 @@ where data: document_data, data_contract: withdrawals_data_contract, metadata: None, - entropy: document_entropy, + entropy: [0; 32], }; self.state_repository @@ -123,10 +118,7 @@ where maybe_existing_identity.ok_or_else(|| anyhow!("Identity not found"))?; existing_identity.reduce_balance(state_transition.amount); - - let updated_identity_revision = existing_identity.get_revision() + 1; - - existing_identity.set_revision(updated_identity_revision); + existing_identity.increment_revision()?; // TODO: we need to be able to batch state repository operations self.state_repository diff --git a/packages/rs-dpp/src/identity/state_transition/identity_credit_withdrawal_transition/validation/basic/validate_identity_credit_withdrawal_transition_basic.rs b/packages/rs-dpp/src/identity/state_transition/identity_credit_withdrawal_transition/validation/basic/validate_identity_credit_withdrawal_transition_basic.rs index e0ff1fdc1fd..696d8a7ab46 100644 --- a/packages/rs-dpp/src/identity/state_transition/identity_credit_withdrawal_transition/validation/basic/validate_identity_credit_withdrawal_transition_basic.rs +++ b/packages/rs-dpp/src/identity/state_transition/identity_credit_withdrawal_transition/validation/basic/validate_identity_credit_withdrawal_transition_basic.rs @@ -8,6 +8,7 @@ use crate::{ InvalidIdentityCreditWithdrawalTransitionCoreFeeError, InvalidIdentityCreditWithdrawalTransitionOutputScriptError, }, + contracts::withdrawals_contract, identity::core_script::CoreScript, util::{is_fibonacci_number::is_fibonacci_number, protocol_data::get_protocol_version}, validation::{JsonSchemaValidator, ValidationResult}, @@ -73,14 +74,20 @@ impl IdentityCreditWithdrawalTransitionBasicValidator { // validate core_fee is in fibonacci sequence let core_fee = transition_json - .get("coreFeePerByte") + .get(withdrawals_contract::property_names::CORE_FEE_PER_BYTE) .ok_or_else(|| { - SerdeParsingError::new( - "Expected credit withdrawal transition to have coreFeePerByte", - ) + SerdeParsingError::new(format!( + "Expected credit withdrawal transition to have {} property", + withdrawals_contract::property_names::CORE_FEE_PER_BYTE + )) })? .as_u64() - .ok_or_else(|| SerdeParsingError::new("Expected coreFeePerByte to be a uint"))?; + .ok_or_else(|| { + SerdeParsingError::new(format!( + "Expected {} property to be a uint", + withdrawals_contract::property_names::CORE_FEE_PER_BYTE + )) + })?; if !is_fibonacci_number(core_fee) { result.add_error(InvalidIdentityCreditWithdrawalTransitionCoreFeeError::new( @@ -93,9 +100,14 @@ impl IdentityCreditWithdrawalTransitionBasicValidator { } // validate output_script types - let output_script_value = transition_json.get("outputScript").ok_or_else(|| { - SerdeParsingError::new("Expected credit withdrawal transition to have outputScript") - })?; + let output_script_value = transition_json + .get(withdrawals_contract::property_names::OUTPUT_SCRIPT) + .ok_or_else(|| { + SerdeParsingError::new(format!( + "Expected credit withdrawal transition to have {} property", + withdrawals_contract::property_names::OUTPUT_SCRIPT + )) + })?; let output_script_bytes: Vec = serde_json::from_value(output_script_value.clone())?; diff --git a/packages/rs-dpp/src/tests/fixtures/get_withdrawals_data_contract.rs b/packages/rs-dpp/src/tests/fixtures/get_withdrawals_data_contract.rs index e7254534069..0f2e68f622a 100644 --- a/packages/rs-dpp/src/tests/fixtures/get_withdrawals_data_contract.rs +++ b/packages/rs-dpp/src/tests/fixtures/get_withdrawals_data_contract.rs @@ -34,11 +34,7 @@ pub fn get_withdrawals_data_contract_fixture(owner_id: Option) -> Da .create(owner_id, withdrawals_schema) .expect("data in fixture should be correct"); - data_contract.id = Identifier::from_string( - &withdrawals_contract::system_ids().contract_id, - Encoding::Base58, - ) - .unwrap(); + data_contract.id = withdrawals_contract::CONTRACT_ID.clone(); data_contract } diff --git a/packages/rs-dpp/src/tests/identity/state_transition/identity_credit_withdrawal_transition/apply_identity_credit_withdrawal_transition_factory_spec.rs b/packages/rs-dpp/src/tests/identity/state_transition/identity_credit_withdrawal_transition/apply_identity_credit_withdrawal_transition_factory_spec.rs index 0f6ef2e80d3..8b4a99bd088 100644 --- a/packages/rs-dpp/src/tests/identity/state_transition/identity_credit_withdrawal_transition/apply_identity_credit_withdrawal_transition_factory_spec.rs +++ b/packages/rs-dpp/src/tests/identity/state_transition/identity_credit_withdrawal_transition/apply_identity_credit_withdrawal_transition_factory_spec.rs @@ -6,7 +6,6 @@ mod apply_identity_credit_withdrawal_transition_factory { use crate::{ contracts::withdrawals_contract, - data_contract::DataContract, identity::state_transition::identity_credit_withdrawal_transition::{ apply_identity_credit_withdrawal_transition_factory::ApplyIdentityCreditWithdrawalTransition, IdentityCreditWithdrawalTransition, Pooling, @@ -78,7 +77,7 @@ mod apply_identity_credit_withdrawal_transition_factory { "coreFeePerByte": 0, "pooling": Pooling::Never, "outputScript": [], - "status": withdrawals_contract::statuses::QUEUED, + "status": withdrawals_contract::Status::QUEUED, }); id_match && created_at_match && updated_at_match && document_data_match diff --git a/packages/rs-drive-abci/src/abci/handlers.rs b/packages/rs-drive-abci/src/abci/handlers.rs index 158bf26560c..78e037fc364 100644 --- a/packages/rs-drive-abci/src/abci/handlers.rs +++ b/packages/rs-drive-abci/src/abci/handlers.rs @@ -256,7 +256,7 @@ mod tests { "coreFeePerByte": 1, "pooling": Pooling::Never, "outputScript": (0..23).collect::>(), - "status": withdrawals_contract::statuses::POOLED, + "status": withdrawals_contract::Status::POOLED, "transactionIndex": 1, "transactionSignHeight": 93, "transactionId": tx_id, diff --git a/packages/rs-drive-abci/src/identity_credit_withdrawal/mod.rs b/packages/rs-drive-abci/src/identity_credit_withdrawal/mod.rs index fea2cbffcff..e0c6d530219 100644 --- a/packages/rs-drive-abci/src/identity_credit_withdrawal/mod.rs +++ b/packages/rs-drive-abci/src/identity_credit_withdrawal/mod.rs @@ -14,7 +14,7 @@ use dpp::{ data_contract::extra::DriveContractExt, identity::convert_credits_to_satoshi, prelude::{Document, Identifier}, - util::{hash, json_value::JsonValueExt, string_encoding::Encoding}, + util::{hash, json_value::JsonValueExt}, }; use drive::{ drive::{ @@ -44,15 +44,7 @@ impl Platform { block_execution_context: &BlockExecutionContext, transaction: TransactionArg, ) -> Result<(), Error> { - let data_contract_id = Identifier::from_string( - &withdrawals_contract::system_ids().contract_id, - Encoding::Base58, - ) - .map_err(|_| { - Error::Execution(ExecutionError::CorruptedCodeExecution( - "Can't create withdrawals id identifier from string", - )) - })?; + let data_contract_id = withdrawals_contract::CONTRACT_ID.clone(); let (_, maybe_data_contract) = self.drive.get_contract_with_fetch_info( data_contract_id.to_buffer(), @@ -72,7 +64,7 @@ impl Platform { )?; let mut broadcasted_documents = self.drive.fetch_withdrawal_documents_by_status( - withdrawals_contract::statuses::BROADCASTED, + withdrawals_contract::Status::BROADCASTED.into(), transaction, )?; @@ -87,34 +79,32 @@ impl Platform { for document in broadcasted_documents.iter_mut() { let transaction_sign_height = document .get_data() - .get_u64("transactionSignHeight") + .get_u64(withdrawals_contract::property_names::TRANSACTION_SIGN_HEIGHT) .map_err(|_| { Error::Execution(ExecutionError::CorruptedCodeExecution( "Can't get transactionSignHeight from withdrawal document", )) })?; - let transaction_id_bytes = - document - .get_data() - .get_bytes("transactionId") - .map_err(|_| { - Error::Execution(ExecutionError::CorruptedCodeExecution( - "Can't get transactionId from withdrawal document", - )) - })?; + let transaction_id_bytes = document + .get_data() + .get_bytes(withdrawals_contract::property_names::TRANSACTION_ID) + .map_err(|_| { + Error::Execution(ExecutionError::CorruptedCodeExecution( + "Can't get transactionId from withdrawal document", + )) + })?; let transaction_id = hex::encode(transaction_id_bytes); - let transaction_index = - document - .get_data() - .get_u64("transactionIndex") - .map_err(|_| { - Error::Execution(ExecutionError::CorruptedCodeExecution( - "Can't get transactionIdex from withdrawal document", - )) - })?; + let transaction_index = document + .get_data() + .get_u64(withdrawals_contract::property_names::TRANSACTION_INDEX) + .map_err(|_| { + Error::Execution(ExecutionError::CorruptedCodeExecution( + "Can't get transactionIdex from withdrawal document", + )) + })?; if core_transactions.contains(&transaction_id) || block_execution_context.block_info.core_chain_locked_height @@ -122,18 +112,21 @@ impl Platform { > NUMBER_OF_BLOCKS_BEFORE_EXPIRED { let status = if core_transactions.contains(&transaction_id) { - withdrawals_contract::statuses::COMPLETE + withdrawals_contract::Status::COMPLETE } else { self.drive.add_insert_expired_index_operation( transaction_index, &mut drive_operations, ); - withdrawals_contract::statuses::EXPIRED + withdrawals_contract::Status::EXPIRED }; document - .set("status", JsonValue::Number(Number::from(status))) + .set( + withdrawals_contract::property_names::STATUS, + JsonValue::Number(Number::from(status as u8)), + ) .map_err(|_| { Error::Execution(ExecutionError::CorruptedCodeExecution( "Can't update document field: status", @@ -157,7 +150,7 @@ impl Platform { &contract_fetch_info.contract, contract_fetch_info .contract - .document_type_for_name("withdrawal") + .document_type_for_name(withdrawals_contract::types::WITHDRAWAL) .map_err(|_| { Error::Execution(ExecutionError::CorruptedCodeExecution( "Can't fetch withdrawal data contract", @@ -181,15 +174,7 @@ impl Platform { validator_set_quorum_hash: [u8; 32], transaction: TransactionArg, ) -> Result>, Error> { - let data_contract_id = Identifier::from_string( - &withdrawals_contract::system_ids().contract_id, - Encoding::Base58, - ) - .map_err(|_| { - Error::Execution(ExecutionError::CorruptedCodeExecution( - "Can't create withdrawals id identifier from string", - )) - })?; + let data_contract_id = withdrawals_contract::CONTRACT_ID.clone(); let (_, maybe_data_contract) = self.drive.get_contract_with_fetch_info( data_contract_id.to_buffer(), @@ -246,7 +231,7 @@ impl Platform { document .set( - "transactionId", + withdrawals_contract::property_names::TRANSACTION_ID, JsonValue::Array( update_transaction_id .iter() @@ -282,7 +267,7 @@ impl Platform { &contract_fetch_info.contract, contract_fetch_info .contract - .document_type_for_name("withdrawal") + .document_type_for_name(withdrawals_contract::types::WITHDRAWAL) .map_err(|_| { Error::Execution(ExecutionError::CorruptedCodeExecution( "could not get document type", @@ -308,15 +293,7 @@ impl Platform { block_execution_context: &BlockExecutionContext, transaction: TransactionArg, ) -> Result<(), Error> { - let data_contract_id = Identifier::from_string( - &withdrawals_contract::system_ids().contract_id, - Encoding::Base58, - ) - .map_err(|_| { - Error::Execution(ExecutionError::CorruptedCodeExecution( - "Can't create withdrawals id identifier from string", - )) - })?; + let data_contract_id = withdrawals_contract::CONTRACT_ID.clone(); let (_, maybe_data_contract) = self.drive.get_contract_with_fetch_info( data_contract_id.to_buffer(), @@ -331,7 +308,7 @@ impl Platform { ))?; let mut documents = self.drive.fetch_withdrawal_documents_by_status( - withdrawals_contract::statuses::QUEUED, + withdrawals_contract::Status::QUEUED.into(), transaction, )?; @@ -352,7 +329,7 @@ impl Platform { document .set( - "transactionId", + withdrawals_contract::property_names::TRANSACTION_ID, JsonValue::Array( transaction_id .clone() @@ -369,8 +346,8 @@ impl Platform { document .set( - "status", - JsonValue::Number(Number::from(withdrawals_contract::statuses::POOLED)), + withdrawals_contract::property_names::STATUS, + JsonValue::Number(Number::from(withdrawals_contract::Status::POOLED as u8)), ) .map_err(|_| { Error::Execution(ExecutionError::CorruptedCodeExecution( @@ -393,7 +370,7 @@ impl Platform { &contract_fetch_info.contract, contract_fetch_info .contract - .document_type_for_name("withdrawal") + .document_type_for_name(withdrawals_contract::types::WITHDRAWAL) .map_err(|_| { Error::Execution(ExecutionError::CorruptedCodeExecution( "Can't fetch withdrawal data contract", @@ -475,20 +452,28 @@ impl Platform { .fetch_latest_withdrawal_transaction_index(transaction)?; for (i, document) in documents.iter().enumerate() { - let output_script = document.get_data().get_bytes("outputScript").map_err(|_| { - Error::Execution(ExecutionError::CorruptedCodeExecution( - "Can't get outputScript from withdrawal document", - )) - })?; + let output_script = document + .get_data() + .get_bytes(withdrawals_contract::property_names::OUTPUT_SCRIPT) + .map_err(|_| { + Error::Execution(ExecutionError::CorruptedCodeExecution( + "Can't get outputScript from withdrawal document", + )) + })?; - let amount = document.get_data().get_u64("amount").map_err(|_| { - Error::Execution(ExecutionError::CorruptedCodeExecution( - "Can't get amount from withdrawal document", - )) - })?; + let amount = document + .get_data() + .get_u64(withdrawals_contract::property_names::AMOUNT) + .map_err(|_| { + Error::Execution(ExecutionError::CorruptedCodeExecution( + "Can't get amount from withdrawal document", + )) + })?; - let core_fee_per_byte = - document.get_data().get_u64("coreFeePerByte").map_err(|_| { + let core_fee_per_byte = document + .get_data() + .get_u64(withdrawals_contract::property_names::CORE_FEE_PER_BYTE) + .map_err(|_| { Error::Execution(ExecutionError::CorruptedCodeExecution( "Can't get coreFeePerByte from withdrawal document", )) @@ -640,7 +625,7 @@ mod tests { "coreFeePerByte": 1, "pooling": Pooling::Never, "outputScript": (0..23).collect::>(), - "status": withdrawals_contract::statuses::BROADCASTED, + "status": withdrawals_contract::Status::BROADCASTED, "transactionIndex": 1, "transactionSignHeight": 93, "transactionId": vec![1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], @@ -661,7 +646,7 @@ mod tests { "coreFeePerByte": 1, "pooling": Pooling::Never, "outputScript": (0..23).collect::>(), - "status": withdrawals_contract::statuses::BROADCASTED, + "status": withdrawals_contract::Status::BROADCASTED, "transactionIndex": 2, "transactionSignHeight": 10, "transactionId": vec![3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], @@ -702,7 +687,7 @@ mod tests { let documents = platform .drive .fetch_withdrawal_documents_by_status( - withdrawals_contract::statuses::EXPIRED, + withdrawals_contract::Status::EXPIRED.into(), Some(&transaction), ) .expect("to fetch documents by status"); @@ -713,7 +698,7 @@ mod tests { let documents = platform .drive .fetch_withdrawal_documents_by_status( - withdrawals_contract::statuses::COMPLETE, + withdrawals_contract::Status::COMPLETE.into(), Some(&transaction), ) .expect("to fetch documents by status"); @@ -746,7 +731,7 @@ mod tests { "coreFeePerByte": 1, "pooling": Pooling::Never, "outputScript": (0..23).collect::>(), - "status": withdrawals_contract::statuses::QUEUED, + "status": withdrawals_contract::Status::QUEUED, "transactionIndex": 1, }), ); @@ -765,7 +750,7 @@ mod tests { "coreFeePerByte": 1, "pooling": Pooling::Never, "outputScript": (0..23).collect::>(), - "status": withdrawals_contract::statuses::QUEUED, + "status": withdrawals_contract::Status::QUEUED, "transactionIndex": 2, }), ); @@ -803,7 +788,7 @@ mod tests { let updated_documents = platform .drive .fetch_withdrawal_documents_by_status( - withdrawals_contract::statuses::POOLED, + withdrawals_contract::Status::POOLED.into(), Some(&transaction), ) .expect("to fetch withdrawal documents"); @@ -922,7 +907,7 @@ mod tests { "coreFeePerByte": 1, "pooling": Pooling::Never, "outputScript": (0..23).collect::>(), - "status": withdrawals_contract::statuses::POOLED, + "status": withdrawals_contract::Status::POOLED, "transactionIndex": 1, }), ); @@ -941,7 +926,7 @@ mod tests { "coreFeePerByte": 1, "pooling": Pooling::Never, "outputScript": (0..23).collect::>(), - "status": withdrawals_contract::statuses::POOLED, + "status": withdrawals_contract::Status::POOLED, "transactionIndex": 2, }), ); diff --git a/packages/rs-drive-nodejs/Cargo.toml b/packages/rs-drive-nodejs/Cargo.toml index 3e80db4ea1e..4b1bd9d9079 100644 --- a/packages/rs-drive-nodejs/Cargo.toml +++ b/packages/rs-drive-nodejs/Cargo.toml @@ -20,4 +20,4 @@ default-features = false features = ["napi-6", "event-queue-api", "try-catch-api"] [features] -enable-core-rpc-mocking = [] +enable-mocking = [] diff --git a/packages/rs-drive-nodejs/package.json b/packages/rs-drive-nodejs/package.json index bd204f72166..992b8305372 100644 --- a/packages/rs-drive-nodejs/package.json +++ b/packages/rs-drive-nodejs/package.json @@ -5,7 +5,7 @@ "main": "Drive.js", "scripts": { "build": "yarn exec scripts/build.sh", - "test": "ENABLE_CORE_RPC_MOCKING=true ultra --build && mocha test", + "test": "NODE_ENV=test ultra --build && mocha test", "lint": "eslint ." }, "files": [ diff --git a/packages/rs-drive-nodejs/scripts/build.sh b/packages/rs-drive-nodejs/scripts/build.sh index 343c87c6d78..6e169fdf681 100755 --- a/packages/rs-drive-nodejs/scripts/build.sh +++ b/packages/rs-drive-nodejs/scripts/build.sh @@ -11,8 +11,10 @@ if [ -n "$CARGO_BUILD_PROFILE" ]; then fi fi -if [ -n "$ENABLE_CORE_RPC_MOCKING" ]; then - FEATURE_FLAG="--features enable-core-rpc-mocking" +if [ -n "$NODE_ENV" ]; then + if [ "$NODE_ENV" == "test" ]; then + FEATURE_FLAG="--features enable-mocking" + fi fi cargo-cp-artifact -ac drive-nodejs native/index.node -- \ diff --git a/packages/rs-drive-nodejs/src/lib.rs b/packages/rs-drive-nodejs/src/lib.rs index bd261e8e3e6..66c9d892e3f 100644 --- a/packages/rs-drive-nodejs/src/lib.rs +++ b/packages/rs-drive-nodejs/src/lib.rs @@ -130,7 +130,7 @@ impl PlatformWrapper { // TODO: think how to pass this error to JS let mut platform: Platform = Platform::open(path, platform_config).unwrap(); - if cfg!(feature = "enable-core-rpc-mocking") { + if cfg!(feature = "enable-mocking") { platform.mock_core_rpc_client(); } diff --git a/packages/rs-drive/src/drive/identity/withdrawals/withdrawal_status.rs b/packages/rs-drive/src/drive/identity/withdrawals/withdrawal_status.rs index 62b43a9226e..f768a9e268a 100644 --- a/packages/rs-drive/src/drive/identity/withdrawals/withdrawal_status.rs +++ b/packages/rs-drive/src/drive/identity/withdrawals/withdrawal_status.rs @@ -1,9 +1,4 @@ -use dpp::{ - contracts::withdrawals_contract, - data_contract::extra::common, - prelude::{Document, Identifier}, - util::string_encoding::Encoding, -}; +use dpp::{contracts::withdrawals_contract, data_contract::extra::common, prelude::Document}; use grovedb::TransactionArg; use serde_json::json; @@ -21,10 +16,10 @@ impl Drive { ) -> Result, Error> { let query_value = json!({ "where": [ - ["status", "==", status], + [withdrawals_contract::property_names::STATUS, "==", status], ], "orderBy": [ - ["$createdAt", "desc"], + [withdrawals_contract::property_names::CREATE_AT, "desc"], ] }); @@ -32,16 +27,7 @@ impl Drive { let (documents, _, _) = self.query_documents( &query_cbor, - Identifier::from_string( - &withdrawals_contract::system_ids().contract_id, - Encoding::Base58, - ) - .map_err(|_| { - Error::Drive(DriveError::CorruptedCodeExecution( - "Can't create withdrawals id identifier from string", - )) - })? - .to_buffer(), + withdrawals_contract::CONTRACT_ID.clone().to_buffer(), withdrawals_contract::types::WITHDRAWAL, None, transaction, @@ -67,20 +53,12 @@ impl Drive { original_transaction_id: &[u8], transaction: TransactionArg, ) -> Result { - let data_contract_id = Identifier::from_string( - &withdrawals_contract::system_ids().contract_id, - Encoding::Base58, - ) - .map_err(|_| { - Error::Drive(DriveError::CorruptedCodeExecution( - "Can't create withdrawals id identifier from string", - )) - })?; + let data_contract_id = withdrawals_contract::CONTRACT_ID.clone(); let query_value = json!({ "where": [ - ["transactionId", "==", original_transaction_id], - ["status", "==", withdrawals_contract::statuses::POOLED], + [withdrawals_contract::property_names::TRANSACTION_ID, "==", original_transaction_id], + [withdrawals_contract::property_names::STATUS, "==", withdrawals_contract::Status::POOLED], ], }); @@ -144,7 +122,7 @@ mod tests { let documents = drive .fetch_withdrawal_documents_by_status( - withdrawals_contract::statuses::QUEUED, + withdrawals_contract::Status::QUEUED.into(), Some(&transaction), ) .expect("to fetch documents by status"); @@ -158,7 +136,7 @@ mod tests { "coreFeePerByte": 1, "pooling": Pooling::Never, "outputScript": (0..23).collect::>(), - "status": withdrawals_contract::statuses::QUEUED, + "status": withdrawals_contract::Status::QUEUED, "transactionIndex": 1, }), ); @@ -172,7 +150,7 @@ mod tests { "coreFeePerByte": 1, "pooling": Pooling::Never, "outputScript": (0..23).collect::>(), - "status": withdrawals_contract::statuses::POOLED, + "status": withdrawals_contract::Status::POOLED, "transactionIndex": 2, }), ); @@ -181,7 +159,7 @@ mod tests { let documents = drive .fetch_withdrawal_documents_by_status( - withdrawals_contract::statuses::QUEUED, + withdrawals_contract::Status::QUEUED.into(), Some(&transaction), ) .expect("to fetch documents by status"); @@ -190,7 +168,7 @@ mod tests { let documents = drive .fetch_withdrawal_documents_by_status( - withdrawals_contract::statuses::POOLED, + withdrawals_contract::Status::POOLED.into(), Some(&transaction), ) .expect("to fetch documents by status"); @@ -221,7 +199,7 @@ mod tests { "coreFeePerByte": 1, "pooling": Pooling::Never, "outputScript": (0..23).collect::>(), - "status": withdrawals_contract::statuses::POOLED, + "status": withdrawals_contract::Status::POOLED, "transactionIndex": 1, "transactionId": (0..32).collect::>(), }), From a65dfbdb8d61c3e2e2f6e2f1f48f991c92cded75 Mon Sep 17 00:00:00 2001 From: Djavid Gabibiyan Date: Fri, 27 Jan 2023 14:19:14 +0500 Subject: [PATCH 085/170] chore: merge updates --- .../src/identity_credit_withdrawal/mod.rs | 3 +-- packages/rs-drive/src/drive/document/convert.rs | 16 ++++++++++------ packages/rs-drive/src/drive/document/update.rs | 4 ++-- .../identity/withdrawals/withdrawal_status.rs | 6 +++--- 4 files changed, 16 insertions(+), 13 deletions(-) diff --git a/packages/rs-drive-abci/src/identity_credit_withdrawal/mod.rs b/packages/rs-drive-abci/src/identity_credit_withdrawal/mod.rs index e0c6d530219..8eb2a7fd9ef 100644 --- a/packages/rs-drive-abci/src/identity_credit_withdrawal/mod.rs +++ b/packages/rs-drive-abci/src/identity_credit_withdrawal/mod.rs @@ -11,10 +11,9 @@ use dashcore::{ }; use dpp::{ contracts::withdrawals_contract, - data_contract::extra::DriveContractExt, identity::convert_credits_to_satoshi, prelude::{Document, Identifier}, - util::{hash, json_value::JsonValueExt}, + util::{hash, json_value::JsonValueExt}, data_contract::DriveContractExt, }; use drive::{ drive::{ diff --git a/packages/rs-drive/src/drive/document/convert.rs b/packages/rs-drive/src/drive/document/convert.rs index fbee844f6bc..a1a56d80fd7 100644 --- a/packages/rs-drive/src/drive/document/convert.rs +++ b/packages/rs-drive/src/drive/document/convert.rs @@ -1,25 +1,29 @@ -use dpp::prelude::Document; +use dpp::{prelude::Document, document::document_stub::DocumentStub}; use crate::error::{drive::DriveError, Error}; /// Helper function to convert DPP documents to Drive documents pub fn convert_dpp_documents_to_drive_documents<'a, I>( dpp_documents: I, -) -> Result, Error> +) -> Result, Error> where I: Iterator, { dpp_documents .map(|document| { - crate::contract::document::Document::from_cbor( + DocumentStub::from_cbor( &document.to_buffer().map_err(|_| { Error::Drive(DriveError::CorruptedCodeExecution( - "Can't convert dpp document to cbor", + "Can't convert dpp document to CBOR", )) })?, None, None, - ) + ).map_err(|_| { + Error::Drive(DriveError::CorruptedCodeExecution( + "Can't create drive document from CBOR", + )) + }) }) - .collect::, Error>>() + .collect::, Error>>() } diff --git a/packages/rs-drive/src/drive/document/update.rs b/packages/rs-drive/src/drive/document/update.rs index 6831943609d..fad7d153df2 100644 --- a/packages/rs-drive/src/drive/document/update.rs +++ b/packages/rs-drive/src/drive/document/update.rs @@ -35,6 +35,7 @@ use std::collections::{HashMap, HashSet}; use dpp::data_contract::DriveContractExt; +use dpp::data_contract::document_type::DocumentType; use grovedb::batch::key_info::KeyInfo; use grovedb::batch::key_info::KeyInfo::KnownKey; use grovedb::batch::KeyInfoPath; @@ -76,7 +77,6 @@ use crate::drive::grove_operations::{ QueryType, }; use crate::fee::result::FeeResult; -use dpp::data_contract::extra::{DocumentType, DriveContractExt}; use dpp::prelude::DataContract; impl Drive { @@ -646,7 +646,7 @@ impl Drive { /// Add update multiple documents operations pub fn add_update_multiple_documents_operations<'a>( &self, - documents: &'a [crate::contract::document::Document], + documents: &'a [DocumentStub], data_contract: &'a DataContract, document_type: &'a DocumentType, drive_operations: &mut Vec>, diff --git a/packages/rs-drive/src/drive/identity/withdrawals/withdrawal_status.rs b/packages/rs-drive/src/drive/identity/withdrawals/withdrawal_status.rs index f768a9e268a..9ade0ccdfd1 100644 --- a/packages/rs-drive/src/drive/identity/withdrawals/withdrawal_status.rs +++ b/packages/rs-drive/src/drive/identity/withdrawals/withdrawal_status.rs @@ -1,4 +1,4 @@ -use dpp::{contracts::withdrawals_contract, data_contract::extra::common, prelude::Document}; +use dpp::{contracts::withdrawals_contract, prelude::Document, util::serializer}; use grovedb::TransactionArg; use serde_json::json; @@ -23,7 +23,7 @@ impl Drive { ] }); - let query_cbor = common::value_to_cbor(query_value, None); + let query_cbor = serializer::value_to_cbor(query_value, None)?; let (documents, _, _) = self.query_documents( &query_cbor, @@ -62,7 +62,7 @@ impl Drive { ], }); - let query_cbor = common::value_to_cbor(query_value, None); + let query_cbor = serializer::value_to_cbor(query_value, None)?; let (documents, _, _) = self.query_documents( &query_cbor, From 9c98c9463bb2119461570ccb8bfab9fb9427d97e Mon Sep 17 00:00:00 2001 From: Djavid Gabibiyan Date: Fri, 27 Jan 2023 14:19:49 +0500 Subject: [PATCH 086/170] chore: fmt --- packages/rs-drive-abci/src/identity_credit_withdrawal/mod.rs | 3 ++- packages/rs-drive/src/drive/document/convert.rs | 5 +++-- packages/rs-drive/src/drive/document/update.rs | 2 +- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/packages/rs-drive-abci/src/identity_credit_withdrawal/mod.rs b/packages/rs-drive-abci/src/identity_credit_withdrawal/mod.rs index 8eb2a7fd9ef..dce83f6d149 100644 --- a/packages/rs-drive-abci/src/identity_credit_withdrawal/mod.rs +++ b/packages/rs-drive-abci/src/identity_credit_withdrawal/mod.rs @@ -11,9 +11,10 @@ use dashcore::{ }; use dpp::{ contracts::withdrawals_contract, + data_contract::DriveContractExt, identity::convert_credits_to_satoshi, prelude::{Document, Identifier}, - util::{hash, json_value::JsonValueExt}, data_contract::DriveContractExt, + util::{hash, json_value::JsonValueExt}, }; use drive::{ drive::{ diff --git a/packages/rs-drive/src/drive/document/convert.rs b/packages/rs-drive/src/drive/document/convert.rs index a1a56d80fd7..e28d7c9c53c 100644 --- a/packages/rs-drive/src/drive/document/convert.rs +++ b/packages/rs-drive/src/drive/document/convert.rs @@ -1,4 +1,4 @@ -use dpp::{prelude::Document, document::document_stub::DocumentStub}; +use dpp::{document::document_stub::DocumentStub, prelude::Document}; use crate::error::{drive::DriveError, Error}; @@ -19,7 +19,8 @@ where })?, None, None, - ).map_err(|_| { + ) + .map_err(|_| { Error::Drive(DriveError::CorruptedCodeExecution( "Can't create drive document from CBOR", )) diff --git a/packages/rs-drive/src/drive/document/update.rs b/packages/rs-drive/src/drive/document/update.rs index fad7d153df2..17004a1b300 100644 --- a/packages/rs-drive/src/drive/document/update.rs +++ b/packages/rs-drive/src/drive/document/update.rs @@ -34,8 +34,8 @@ use std::collections::{HashMap, HashSet}; -use dpp::data_contract::DriveContractExt; use dpp::data_contract::document_type::DocumentType; +use dpp::data_contract::DriveContractExt; use grovedb::batch::key_info::KeyInfo; use grovedb::batch::key_info::KeyInfo::KnownKey; use grovedb::batch::KeyInfoPath; From 37249f69e5354520b44e9fa54aaa548832ab5c13 Mon Sep 17 00:00:00 2001 From: Djavid Gabibiyan Date: Fri, 27 Jan 2023 16:10:56 +0500 Subject: [PATCH 087/170] chore: validate existing id --- .../rs-dpp/src/errors/non_consensus_error.rs | 6 ++- ...ty_credit_withdrawal_transition_factory.rs | 28 ++++++++++++-- .../validation/state/mod.rs | 1 + .../state/validate_existing_withdrawal_id.rs | 38 +++++++++++++++++++ 4 files changed, 69 insertions(+), 4 deletions(-) create mode 100644 packages/rs-dpp/src/identity/state_transition/identity_credit_withdrawal_transition/validation/state/validate_existing_withdrawal_id.rs diff --git a/packages/rs-dpp/src/errors/non_consensus_error.rs b/packages/rs-dpp/src/errors/non_consensus_error.rs index 44ad0a627d1..ab2160fdb29 100644 --- a/packages/rs-dpp/src/errors/non_consensus_error.rs +++ b/packages/rs-dpp/src/errors/non_consensus_error.rs @@ -1,7 +1,8 @@ use thiserror::Error; use crate::{ - CompatibleProtocolVersionIsNotDefinedError, InvalidVectorSizeError, SerdeParsingError, + prelude::Identifier, CompatibleProtocolVersionIsNotDefinedError, InvalidVectorSizeError, + SerdeParsingError, }; #[derive(Debug, Error)] @@ -35,6 +36,9 @@ pub enum NonConsensusError { details: String, }, + #[error("Withdrawal with id {id_string} already exists")] + WithdrawalIdAlreadyExists { id_string: String }, + #[error(transparent)] Error(#[from] anyhow::Error), } diff --git a/packages/rs-dpp/src/identity/state_transition/identity_credit_withdrawal_transition/apply_identity_credit_withdrawal_transition_factory.rs b/packages/rs-dpp/src/identity/state_transition/identity_credit_withdrawal_transition/apply_identity_credit_withdrawal_transition_factory.rs index 6c1a564a54a..670ecdb0102 100644 --- a/packages/rs-dpp/src/identity/state_transition/identity_credit_withdrawal_transition/apply_identity_credit_withdrawal_transition_factory.rs +++ b/packages/rs-dpp/src/identity/state_transition/identity_credit_withdrawal_transition/apply_identity_credit_withdrawal_transition_factory.rs @@ -14,7 +14,10 @@ use crate::{ util::{entropy_generator::generate, json_value::JsonValueExt}, }; -use super::IdentityCreditWithdrawalTransition; +use super::{ + validation::state::validate_existing_withdrawal_id::validate_existing_withdrawal_id, + IdentityCreditWithdrawalTransition, +}; const PLATFORM_BLOCK_HEADER_TIME_PROPERTY: &str = "time"; const PLATFORM_BLOCK_HEADER_TIME_SECONDS_PROPERTY: &str = "seconds"; @@ -58,7 +61,6 @@ where .await?; let document_type = String::from(withdrawals_contract::types::WITHDRAWAL); - let document_entropy = generate()?; let document_created_at_millis = latest_platform_block_header .get(PLATFORM_BLOCK_HEADER_TIME_PROPERTY) .ok_or_else(|| anyhow!("time property is not set in block header"))? @@ -73,13 +75,33 @@ where withdrawals_contract::property_names::STATUS: withdrawals_contract::Status::QUEUED, }); - let document_id = generate_document_id::generate_document_id( + let document_entropy = generate()?; + + let mut document_id = generate_document_id::generate_document_id( &data_contract_id, &data_contract_owner_id, &document_type, &document_entropy, ); + while validate_existing_withdrawal_id( + &self.state_repository, + &document_id, + state_transition, + ) + .await + .is_err() + { + let document_entropy = generate()?; + + document_id = generate_document_id::generate_document_id( + &data_contract_id, + &data_contract_owner_id, + &document_type, + &document_entropy, + ) + } + // TODO: use DocumentFactory once it is complete let withdrawal_document = Document { protocol_version: state_transition.protocol_version, diff --git a/packages/rs-dpp/src/identity/state_transition/identity_credit_withdrawal_transition/validation/state/mod.rs b/packages/rs-dpp/src/identity/state_transition/identity_credit_withdrawal_transition/validation/state/mod.rs index cdad34d2bce..4c6fc2fc426 100644 --- a/packages/rs-dpp/src/identity/state_transition/identity_credit_withdrawal_transition/validation/state/mod.rs +++ b/packages/rs-dpp/src/identity/state_transition/identity_credit_withdrawal_transition/validation/state/mod.rs @@ -1 +1,2 @@ +pub mod validate_existing_withdrawal_id; pub mod validate_identity_credit_withdrawal_transition_state; diff --git a/packages/rs-dpp/src/identity/state_transition/identity_credit_withdrawal_transition/validation/state/validate_existing_withdrawal_id.rs b/packages/rs-dpp/src/identity/state_transition/identity_credit_withdrawal_transition/validation/state/validate_existing_withdrawal_id.rs new file mode 100644 index 00000000000..efec17bb539 --- /dev/null +++ b/packages/rs-dpp/src/identity/state_transition/identity_credit_withdrawal_transition/validation/state/validate_existing_withdrawal_id.rs @@ -0,0 +1,38 @@ +use serde_json::json; + +use crate::{ + contracts::withdrawals_contract, document::Document, + identity::state_transition::identity_credit_withdrawal_transition::IdentityCreditWithdrawalTransition, + prelude::Identifier, state_repository::StateRepositoryLike, util::string_encoding::Encoding, + NonConsensusError, +}; + +pub async fn validate_existing_withdrawal_id( + state_repository: &SR, + document_id: &Identifier, + state_transition: &IdentityCreditWithdrawalTransition, +) -> Result<(), NonConsensusError> +where + SR: StateRepositoryLike, +{ + let documents: Vec = state_repository + .fetch_documents( + &withdrawals_contract::CONTRACT_ID.clone(), + withdrawals_contract::types::WITHDRAWAL, + json!({ + "where": [ + ["$id", "==", document_id], + ], + }), + &state_transition.execution_context, + ) + .await?; + + if !documents.is_empty() { + return Err(NonConsensusError::WithdrawalIdAlreadyExists { + id_string: document_id.to_string(Encoding::Base58), + }); + } + + Ok(()) +} From 112c50407a4374023aa4b8483116af6306cfe03e Mon Sep 17 00:00:00 2001 From: Djavid Gabibiyan Date: Fri, 27 Jan 2023 16:26:32 +0500 Subject: [PATCH 088/170] chore: indices update --- .../withdrawals-contract-documents.json | 24 ++++++++++++------- .../schema/withdrawals-documents.json | 24 ++++++++++++------- 2 files changed, 30 insertions(+), 18 deletions(-) diff --git a/packages/rs-dpp/contracts/withdrawals/withdrawals-contract-documents.json b/packages/rs-dpp/contracts/withdrawals/withdrawals-contract-documents.json index 003929aacf9..8b899ff5117 100644 --- a/packages/rs-dpp/contracts/withdrawals/withdrawals-contract-documents.json +++ b/packages/rs-dpp/contracts/withdrawals/withdrawals-contract-documents.json @@ -3,6 +3,21 @@ "description": "Withdrawal document to track underlying transaction", "type": "object", "indices": [ + { + "name": "identityRecent", + "properties": [ + { + "$ownerId": "asc" + }, + { + "$updatedAt": "asc" + }, + { + "status": "asc" + } + ], + "unique": false + }, { "name": "pooling", "properties": [ @@ -33,15 +48,6 @@ ], "unique": false }, - { - "name": "ownerId", - "properties": [ - { - "$ownerId": "asc" - } - ], - "unique": false - }, { "name": "status", "properties": [ diff --git a/packages/withdrawals-contract/schema/withdrawals-documents.json b/packages/withdrawals-contract/schema/withdrawals-documents.json index 003929aacf9..8b899ff5117 100644 --- a/packages/withdrawals-contract/schema/withdrawals-documents.json +++ b/packages/withdrawals-contract/schema/withdrawals-documents.json @@ -3,6 +3,21 @@ "description": "Withdrawal document to track underlying transaction", "type": "object", "indices": [ + { + "name": "identityRecent", + "properties": [ + { + "$ownerId": "asc" + }, + { + "$updatedAt": "asc" + }, + { + "status": "asc" + } + ], + "unique": false + }, { "name": "pooling", "properties": [ @@ -33,15 +48,6 @@ ], "unique": false }, - { - "name": "ownerId", - "properties": [ - { - "$ownerId": "asc" - } - ], - "unique": false - }, { "name": "status", "properties": [ From 7f7ef86c697bd62606140d44bfa18f79e381a69a Mon Sep 17 00:00:00 2001 From: Djavid Gabibiyan Date: Mon, 30 Jan 2023 13:16:34 +0500 Subject: [PATCH 089/170] chore: update tests for data trigger --- .../withdrawals_data_triggers/mod.rs | 68 +++++++++++++++++-- 1 file changed, 61 insertions(+), 7 deletions(-) diff --git a/packages/rs-dpp/src/data_trigger/withdrawals_data_triggers/mod.rs b/packages/rs-dpp/src/data_trigger/withdrawals_data_triggers/mod.rs index b0fe51627f5..f9f71c6fca8 100644 --- a/packages/rs-dpp/src/data_trigger/withdrawals_data_triggers/mod.rs +++ b/packages/rs-dpp/src/data_trigger/withdrawals_data_triggers/mod.rs @@ -91,21 +91,28 @@ where mod test { use super::delete_withdrawal_data_trigger; use crate::{ + contracts::withdrawals_contract, data_trigger::DataTriggerExecutionContext, - document::document_transition::DocumentTransition, + document::{document_transition::DocumentTransition, Document}, + identity::state_transition::identity_credit_withdrawal_transition::Pooling, state_repository::MockStateRepositoryLike, state_transition::state_transition_execution_context::StateTransitionExecutionContext, - tests::fixtures::get_data_contract_fixture, + tests::fixtures::{get_data_contract_fixture, get_withdrawal_document_fixture, get_withdrawals_data_contract_fixture}, }; + use serde_json::json; #[tokio::test] - async fn should_successfully_execute_on_dry_run() { + async fn should_throw_error_if_withdrawal_not_found() { let transition_execution_context = StateTransitionExecutionContext::default(); - let state_repository = MockStateRepositoryLike::new(); + let mut state_repository = MockStateRepositoryLike::new(); let data_contract = get_data_contract_fixture(None); let owner_id = data_contract.owner_id().to_owned(); - let document_transition = DocumentTransition::Create(Default::default()); + state_repository + .expect_fetch_documents::() + .returning(|_, _, _, _| Ok(vec![])); + + let document_transition = DocumentTransition::Delete(Default::default()); let data_trigger_context = DataTriggerExecutionContext { data_contract: &data_contract, owner_id: &owner_id, @@ -113,13 +120,60 @@ mod test { state_transition_execution_context: &transition_execution_context, }; - transition_execution_context.enable_dry_run(); + let result = + delete_withdrawal_data_trigger(&document_transition, &data_trigger_context, None) + .await + .expect("the execution result should be returned"); + + assert!(!result.is_ok()); + + let error = result.get_errors().get(0).unwrap(); + + assert_eq!(error.to_string(), "Withdrawal document was not found"); + } + + #[tokio::test] + async fn should_throw_error_if_withdrawal_has_wrong_status() { + let transition_execution_context = StateTransitionExecutionContext::default(); + let mut state_repository = MockStateRepositoryLike::new(); + let data_contract = get_withdrawals_data_contract_fixture(None); + let owner_id = data_contract.owner_id().to_owned(); + + let document = get_withdrawal_document_fixture( + &data_contract, + json!({ + "amount": 1000, + "coreFeePerByte": 1, + "pooling": Pooling::Never, + "outputScript": (0..23).collect::>(), + "status": withdrawals_contract::Status::BROADCASTED, + "transactionIndex": 1, + "transactionSignHeight": 93, + "transactionId": vec![1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], + }), + ); + + state_repository + .expect_fetch_documents::() + .return_once(move |_, _, _, _| Ok(vec![document])); + + let document_transition = DocumentTransition::Delete(Default::default()); + let data_trigger_context = DataTriggerExecutionContext { + data_contract: &data_contract, + owner_id: &owner_id, + state_repository: &state_repository, + state_transition_execution_context: &transition_execution_context, + }; let result = delete_withdrawal_data_trigger(&document_transition, &data_trigger_context, None) .await .expect("the execution result should be returned"); - assert!(result.is_ok()); + assert!(!result.is_ok()); + + let error = result.get_errors().get(0).unwrap(); + + assert_eq!(error.to_string(), "withdrawal deletion is allowed only for COMPLETE and EXPIRED statuses"); } } From 41894e64a07ad817a556f94e5f499693de9e2b44 Mon Sep 17 00:00:00 2001 From: Djavid Gabibiyan Date: Mon, 30 Jan 2023 13:17:45 +0500 Subject: [PATCH 090/170] chore: fmt --- .../src/data_trigger/withdrawals_data_triggers/mod.rs | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/packages/rs-dpp/src/data_trigger/withdrawals_data_triggers/mod.rs b/packages/rs-dpp/src/data_trigger/withdrawals_data_triggers/mod.rs index f9f71c6fca8..8e41266e6c7 100644 --- a/packages/rs-dpp/src/data_trigger/withdrawals_data_triggers/mod.rs +++ b/packages/rs-dpp/src/data_trigger/withdrawals_data_triggers/mod.rs @@ -97,7 +97,10 @@ mod test { identity::state_transition::identity_credit_withdrawal_transition::Pooling, state_repository::MockStateRepositoryLike, state_transition::state_transition_execution_context::StateTransitionExecutionContext, - tests::fixtures::{get_data_contract_fixture, get_withdrawal_document_fixture, get_withdrawals_data_contract_fixture}, + tests::fixtures::{ + get_data_contract_fixture, get_withdrawal_document_fixture, + get_withdrawals_data_contract_fixture, + }, }; use serde_json::json; @@ -174,6 +177,9 @@ mod test { let error = result.get_errors().get(0).unwrap(); - assert_eq!(error.to_string(), "withdrawal deletion is allowed only for COMPLETE and EXPIRED statuses"); + assert_eq!( + error.to_string(), + "withdrawal deletion is allowed only for COMPLETE and EXPIRED statuses" + ); } } From ca09296fed3d254c1116591266c738a941ac22ad Mon Sep 17 00:00:00 2001 From: Djavid Gabibiyan Date: Mon, 30 Jan 2023 13:29:53 +0500 Subject: [PATCH 091/170] chore: PR comments --- .../withdrawals-contract-documents.json | 27 ++++++++++--------- ...edit_withdrawal_transition_factory_spec.rs | 11 ++++---- .../schema/withdrawals-documents.json | 27 ++++++++++--------- 3 files changed, 36 insertions(+), 29 deletions(-) diff --git a/packages/rs-dpp/contracts/withdrawals/withdrawals-contract-documents.json b/packages/rs-dpp/contracts/withdrawals/withdrawals-contract-documents.json index 8b899ff5117..3319bb81983 100644 --- a/packages/rs-dpp/contracts/withdrawals/withdrawals-contract-documents.json +++ b/packages/rs-dpp/contracts/withdrawals/withdrawals-contract-documents.json @@ -3,6 +3,21 @@ "description": "Withdrawal document to track underlying transaction", "type": "object", "indices": [ + { + "name": "identityStatus", + "properties": [ + { + "$ownerId": "asc" + }, + { + "status": "asc" + }, + { + "$createdAt": "asc" + } + ], + "unique": false + }, { "name": "identityRecent", "properties": [ @@ -47,18 +62,6 @@ } ], "unique": false - }, - { - "name": "status", - "properties": [ - { - "status": "asc" - }, - { - "$createdAt": "asc" - } - ], - "unique": false } ], "properties": { diff --git a/packages/rs-dpp/src/tests/identity/state_transition/identity_credit_withdrawal_transition/apply_identity_credit_withdrawal_transition_factory_spec.rs b/packages/rs-dpp/src/tests/identity/state_transition/identity_credit_withdrawal_transition/apply_identity_credit_withdrawal_transition_factory_spec.rs index 8b4a99bd088..accdb6cc9eb 100644 --- a/packages/rs-dpp/src/tests/identity/state_transition/identity_credit_withdrawal_transition/apply_identity_credit_withdrawal_transition_factory_spec.rs +++ b/packages/rs-dpp/src/tests/identity/state_transition/identity_credit_withdrawal_transition/apply_identity_credit_withdrawal_transition_factory_spec.rs @@ -6,6 +6,7 @@ mod apply_identity_credit_withdrawal_transition_factory { use crate::{ contracts::withdrawals_contract, + document::{generate_document_id, Document}, identity::state_transition::identity_credit_withdrawal_transition::{ apply_identity_credit_withdrawal_transition_factory::ApplyIdentityCreditWithdrawalTransition, IdentityCreditWithdrawalTransition, Pooling, @@ -48,10 +49,12 @@ mod apply_identity_credit_withdrawal_transition_factory { state_transition.amount = 10; - let st_hash: [u8; 32] = state_transition.hash(true).unwrap().try_into().unwrap(); - let mut state_repository = MockStateRepositoryLike::default(); + state_repository + .expect_fetch_documents::() + .returning(|_, _, _, _| anyhow::Ok(vec![])); + state_repository .expect_fetch_data_contract() .times(1) @@ -66,8 +69,6 @@ mod apply_identity_credit_withdrawal_transition_factory { .expect_create_document() .times(1) .withf(move |doc, _| { - let id_match = doc.id == Identifier::from_bytes(&st_hash).unwrap(); - let created_at_match = doc.created_at == Some(block_time_seconds * 1000); let updated_at_match = doc.created_at == Some(block_time_seconds * 1000); @@ -80,7 +81,7 @@ mod apply_identity_credit_withdrawal_transition_factory { "status": withdrawals_contract::Status::QUEUED, }); - id_match && created_at_match && updated_at_match && document_data_match + created_at_match && updated_at_match && document_data_match }) .returning(|_, _| anyhow::Ok(())); diff --git a/packages/withdrawals-contract/schema/withdrawals-documents.json b/packages/withdrawals-contract/schema/withdrawals-documents.json index 8b899ff5117..3319bb81983 100644 --- a/packages/withdrawals-contract/schema/withdrawals-documents.json +++ b/packages/withdrawals-contract/schema/withdrawals-documents.json @@ -3,6 +3,21 @@ "description": "Withdrawal document to track underlying transaction", "type": "object", "indices": [ + { + "name": "identityStatus", + "properties": [ + { + "$ownerId": "asc" + }, + { + "status": "asc" + }, + { + "$createdAt": "asc" + } + ], + "unique": false + }, { "name": "identityRecent", "properties": [ @@ -47,18 +62,6 @@ } ], "unique": false - }, - { - "name": "status", - "properties": [ - { - "status": "asc" - }, - { - "$createdAt": "asc" - } - ], - "unique": false } ], "properties": { From 55e76d895648158946a7e0592697d8818330b7f8 Mon Sep 17 00:00:00 2001 From: Djavid Gabibiyan Date: Mon, 30 Jan 2023 13:59:47 +0500 Subject: [PATCH 092/170] chore: fixing tests --- packages/rs-dpp/src/contracts/withdrawals_contract.rs | 1 + packages/rs-drive-abci/src/identity_credit_withdrawal/mod.rs | 3 ++- .../src/drive/identity/withdrawals/withdrawal_status.rs | 4 +++- 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/packages/rs-dpp/src/contracts/withdrawals_contract.rs b/packages/rs-dpp/src/contracts/withdrawals_contract.rs index 4d0c4474924..12e5d93ec8f 100644 --- a/packages/rs-dpp/src/contracts/withdrawals_contract.rs +++ b/packages/rs-dpp/src/contracts/withdrawals_contract.rs @@ -18,6 +18,7 @@ pub mod property_names { pub const OUTPUT_SCRIPT: &str = "outputScript"; pub const STATUS: &str = "status"; pub const CREATE_AT: &str = "$createdAt"; + pub const OWNER_ID: &str = "$ownerId"; } #[repr(u8)] diff --git a/packages/rs-drive-abci/src/identity_credit_withdrawal/mod.rs b/packages/rs-drive-abci/src/identity_credit_withdrawal/mod.rs index dce83f6d149..a8370e83c26 100644 --- a/packages/rs-drive-abci/src/identity_credit_withdrawal/mod.rs +++ b/packages/rs-drive-abci/src/identity_credit_withdrawal/mod.rs @@ -606,7 +606,8 @@ mod tests { let transaction = platform.drive.grove.start_transaction(); - let data_contract = get_withdrawals_data_contract_fixture(None); + let data_contract = + get_withdrawals_data_contract_fixture(Some(withdrawals_contract::OWNER_ID.clone())); // TODO: figure out the bug in data contract factory let data_contract = DataContract::from_cbor( diff --git a/packages/rs-drive/src/drive/identity/withdrawals/withdrawal_status.rs b/packages/rs-drive/src/drive/identity/withdrawals/withdrawal_status.rs index 9ade0ccdfd1..76c09276d9d 100644 --- a/packages/rs-drive/src/drive/identity/withdrawals/withdrawal_status.rs +++ b/packages/rs-drive/src/drive/identity/withdrawals/withdrawal_status.rs @@ -16,6 +16,7 @@ impl Drive { ) -> Result, Error> { let query_value = json!({ "where": [ + [withdrawals_contract::property_names::OWNER_ID, "==", withdrawals_contract::OWNER_ID.clone()], [withdrawals_contract::property_names::STATUS, "==", status], ], "orderBy": [ @@ -116,7 +117,8 @@ mod tests { let transaction = drive.grove.start_transaction(); - let data_contract = get_withdrawals_data_contract_fixture(None); + let data_contract = + get_withdrawals_data_contract_fixture(Some(withdrawals_contract::OWNER_ID.clone())); setup_system_data_contract(&drive, &data_contract, Some(&transaction)); From 46fa08577bb68eacb82cf108b362c95ae40e2134 Mon Sep 17 00:00:00 2001 From: Djavid Gabibiyan Date: Mon, 30 Jan 2023 14:33:56 +0500 Subject: [PATCH 093/170] chore: fix hashes --- ...ynchronizeMasternodeIdentitiesFactory.spec.js | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/packages/js-drive/test/integration/identity/masternode/synchronizeMasternodeIdentitiesFactory.spec.js b/packages/js-drive/test/integration/identity/masternode/synchronizeMasternodeIdentitiesFactory.spec.js index 66690388565..0bfeb6edf5c 100644 --- a/packages/js-drive/test/integration/identity/masternode/synchronizeMasternodeIdentitiesFactory.spec.js +++ b/packages/js-drive/test/integration/identity/masternode/synchronizeMasternodeIdentitiesFactory.spec.js @@ -367,7 +367,7 @@ describe('synchronizeMasternodeIdentitiesFactory', () => { beforeEach(async function beforeEach() { coreHeight = 3; - firstSyncAppHash = '56964579e1cd1814f0a7ee7c8340881b208b7253d3b574d15007ff585d6d9be6'; + firstSyncAppHash = '419f4fd8095bcfb9f4f349d1f09b6f713002be429305ff65df88c18724cd81a9'; blockInfo = new BlockInfo(10, 0, 1668702100799); container = await createTestDIContainer(); @@ -695,7 +695,7 @@ describe('synchronizeMasternodeIdentitiesFactory', () => { // Nothing happened - await expectDeterministicAppHash('72a6582fa713e6a0188c5037beb6a5c3f3c68bf4f62f9a083b0f848d98b4e394'); + await expectDeterministicAppHash('66cdaf71e956daebb3f7978f5adac91526ab6d610b0f649196c1de868de2a7a2'); // Core RPC should be called @@ -750,7 +750,7 @@ describe('synchronizeMasternodeIdentitiesFactory', () => { expect(result.updatedEntities).to.have.lengthOf(0); expect(result.removedEntities).to.have.lengthOf(0); - await expectDeterministicAppHash('de31529588ed3545988367dfbeccc29704f3de95da0b8f1dc59d734dcfe20542'); + await expectDeterministicAppHash('bab239def5796ff31d1749b086326439ea937eca80ab02609c9c4a80204fd023'); // New masternode identity should be created @@ -834,7 +834,7 @@ describe('synchronizeMasternodeIdentitiesFactory', () => { expect(result.updatedEntities).to.have.lengthOf(0); expect(result.removedEntities).to.have.lengthOf(1); - await expectDeterministicAppHash('4055b1fd4ddfe79a43a90cb7fe8102bdf4eba2fcc565dc5f3f27d0552961c8d0'); + await expectDeterministicAppHash('a55ed533379c6b3a4b4cbddc72b3c3052840ee6d462eb1b7b1270460fa09262f'); // Masternode identity should stay @@ -902,7 +902,7 @@ describe('synchronizeMasternodeIdentitiesFactory', () => { expect(result.updatedEntities).to.have.lengthOf(0); expect(result.removedEntities).to.have.lengthOf(1); - await expectDeterministicAppHash('4055b1fd4ddfe79a43a90cb7fe8102bdf4eba2fcc565dc5f3f27d0552961c8d0'); + await expectDeterministicAppHash('a55ed533379c6b3a4b4cbddc72b3c3052840ee6d462eb1b7b1270460fa09262f'); const invalidMasternodeIdentifier = Identifier.from( Buffer.from(invalidSmlEntry.proRegTxHash, 'hex'), @@ -952,7 +952,7 @@ describe('synchronizeMasternodeIdentitiesFactory', () => { expect(result.updatedEntities).to.have.lengthOf(1); expect(result.removedEntities).to.have.lengthOf(1); - await expectDeterministicAppHash('5cb5a8dc96548735498e532a0a24749efa4e945fa396c2cf03cf58e54ae5c6ab'); + await expectDeterministicAppHash('4881d021f980d7b4879886aadb495ab807f6629c495dfae1ffea3e227ae01100'); // Masternode identity should stay @@ -1027,7 +1027,7 @@ describe('synchronizeMasternodeIdentitiesFactory', () => { await synchronizeMasternodeIdentities(coreHeight + 1, blockInfo); - await expectDeterministicAppHash('09aa8c14efcd1b1d1e0aa025c54a9bd4510dd6bc5eb63fa5fea1bf047d9ae9a7'); + await expectDeterministicAppHash('09bdd2d52c4006cbcb405699020da89c8b0edc69849bfca9092febfacda9ac75'); // Masternode identity should contain new public key @@ -1110,7 +1110,7 @@ describe('synchronizeMasternodeIdentitiesFactory', () => { await synchronizeMasternodeIdentities(coreHeight, blockInfo); - await expectDeterministicAppHash('ca2f5dde68e9d8bc3ad4cfab2919880a1018c807e22b726c5d59f3e021d2fe95'); + await expectDeterministicAppHash('e66038a956d6d32560e36e2990d1d02d4354cbc9b7070d89db011121a38caf95'); const votingIdentifier = createVotingIdentifier(smlFixture[0]); From ff607b5944bcde3e3391b4d2b69b53d1758733bb Mon Sep 17 00:00:00 2001 From: QuantumExplorer Date: Wed, 1 Feb 2023 12:22:55 +0700 Subject: [PATCH 094/170] =?UTF-8?q?refactor:=20renamed=20a=20few=20query?= =?UTF-8?q?=20methods=20and=20added=20a=20few=20to=20query=20Drive=20?= =?UTF-8?q?=E2=80=A6=20(#764)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/contracts/reward_shares.rs | 16 +- packages/rs-drive-nodejs/src/lib.rs | 4 +- .../src/drive/batch/drive_op_batch.rs | 18 +-- .../rs-drive/src/drive/document/delete.rs | 4 +- .../identity/withdrawals/withdrawal_status.rs | 4 +- packages/rs-drive/src/drive/query.rs | 146 ++++++++++++------ packages/rs-drive/tests/query_tests.rs | 58 +++---- .../rs-drive/tests/query_tests_history.rs | 38 ++--- 8 files changed, 172 insertions(+), 116 deletions(-) diff --git a/packages/rs-drive-abci/src/contracts/reward_shares.rs b/packages/rs-drive-abci/src/contracts/reward_shares.rs index 0a8ef0806f4..9e05474940b 100644 --- a/packages/rs-drive-abci/src/contracts/reward_shares.rs +++ b/packages/rs-drive-abci/src/contracts/reward_shares.rs @@ -73,13 +73,15 @@ impl Platform { let query_cbor = serializer::value_to_cbor(query_json, None).expect("expected to serialize to cbor"); - let (document_cbors, _, _) = self.drive.query_documents( - &query_cbor, - MN_REWARD_SHARES_CONTRACT_ID, - MN_REWARD_SHARES_DOCUMENT_TYPE, - None, - transaction, - )?; + let (document_cbors, _, _) = self + .drive + .query_raw_documents_using_cbor_encoded_query_with_cost( + &query_cbor, + MN_REWARD_SHARES_CONTRACT_ID, + MN_REWARD_SHARES_DOCUMENT_TYPE, + None, + transaction, + )?; document_cbors .iter() diff --git a/packages/rs-drive-nodejs/src/lib.rs b/packages/rs-drive-nodejs/src/lib.rs index 66c9d892e3f..200de99291a 100644 --- a/packages/rs-drive-nodejs/src/lib.rs +++ b/packages/rs-drive-nodejs/src/lib.rs @@ -985,7 +985,7 @@ impl PlatformWrapper { let result = transaction_result.and_then(|transaction_arg| { platform .drive - .query_documents( + .query_raw_documents_using_cbor_encoded_query_with_cost( &query_cbor, contract_id, document_type_name.as_str(), @@ -1058,7 +1058,7 @@ impl PlatformWrapper { let result = transaction_result.and_then(|transaction_arg| { platform .drive - .query_documents_as_grove_proof( + .query_proof_of_documents_using_contract_id_using_cbor_encoded_query_with_cost( &query_cbor, contract_id, document_type_name.as_str(), diff --git a/packages/rs-drive/src/drive/batch/drive_op_batch.rs b/packages/rs-drive/src/drive/batch/drive_op_batch.rs index d59026074e3..4e79a7cba67 100644 --- a/packages/rs-drive/src/drive/batch/drive_op_batch.rs +++ b/packages/rs-drive/src/drive/batch/drive_op_batch.rs @@ -905,7 +905,7 @@ mod tests { serializer::value_to_cbor(query_value, None).expect("expected to serialize to cbor"); let (docs, _, _) = drive - .query_documents_from_contract( + .query_raw_documents_from_contract_using_cbor_encoded_query_with_cost( &contract, document_type, where_cbor.as_slice(), @@ -1126,7 +1126,7 @@ mod tests { serializer::value_to_cbor(query_value, None).expect("expected to serialize to cbor"); let (docs, _, _) = drive - .query_documents_from_contract( + .query_raw_documents_from_contract_using_cbor_encoded_query_with_cost( &contract, document_type, where_cbor.as_slice(), @@ -1254,7 +1254,7 @@ mod tests { serializer::value_to_cbor(query_value, None).expect("expected to serialize to cbor"); let (docs, _, _) = drive - .query_documents_from_contract( + .query_raw_documents_from_contract_using_cbor_encoded_query_with_cost( &contract, document_type, where_cbor.as_slice(), @@ -1447,7 +1447,7 @@ mod tests { serializer::value_to_cbor(query_value, None).expect("expected to serialize to cbor"); let (docs, _, _) = drive - .query_documents_from_contract( + .query_raw_documents_from_contract_using_cbor_encoded_query_with_cost( &contract, document_type, where_cbor.as_slice(), @@ -1470,7 +1470,7 @@ mod tests { serializer::value_to_cbor(query_value, None).expect("expected to serialize to cbor"); let (docs, _, _) = drive - .query_documents_from_contract( + .query_raw_documents_from_contract_using_cbor_encoded_query_with_cost( &contract, document_type, where_cbor.as_slice(), @@ -1493,7 +1493,7 @@ mod tests { serializer::value_to_cbor(query_value, None).expect("expected to serialize to cbor"); let (docs, _, _) = drive - .query_documents_from_contract( + .query_raw_documents_from_contract_using_cbor_encoded_query_with_cost( &contract, document_type, where_cbor.as_slice(), @@ -1687,7 +1687,7 @@ mod tests { serializer::value_to_cbor(query_value, None).expect("expected to serialize to cbor"); let (docs, _, _) = drive - .query_documents_from_contract( + .query_raw_documents_from_contract_using_cbor_encoded_query_with_cost( &contract, document_type, where_cbor.as_slice(), @@ -1710,7 +1710,7 @@ mod tests { serializer::value_to_cbor(query_value, None).expect("expected to serialize to cbor"); let (docs, _, _) = drive - .query_documents_from_contract( + .query_raw_documents_from_contract_using_cbor_encoded_query_with_cost( &contract, document_type, where_cbor.as_slice(), @@ -1733,7 +1733,7 @@ mod tests { serializer::value_to_cbor(query_value, None).expect("expected to serialize to cbor"); let (docs, _, _) = drive - .query_documents_from_contract( + .query_raw_documents_from_contract_using_cbor_encoded_query_with_cost( &contract, document_type, where_cbor.as_slice(), diff --git a/packages/rs-drive/src/drive/document/delete.rs b/packages/rs-drive/src/drive/document/delete.rs index 25b9fcfddb3..83bf25867ce 100644 --- a/packages/rs-drive/src/drive/document/delete.rs +++ b/packages/rs-drive/src/drive/document/delete.rs @@ -1657,7 +1657,7 @@ mod tests { .expect("unable to commit transaction"); let (results, _, _) = drive - .query_documents_from_contract( + .query_raw_documents_from_contract_using_cbor_encoded_query_with_cost( &contract, contract.document_types().get("niceDocument").unwrap(), query_cbor.as_slice(), @@ -1692,7 +1692,7 @@ mod tests { serializer::value_to_cbor(query_json, None).expect("expected to serialize to cbor"); let (results, _, _) = drive - .query_documents_from_contract( + .query_raw_documents_from_contract_using_cbor_encoded_query_with_cost( &contract, contract.document_types().get("niceDocument").unwrap(), query_cbor.as_slice(), diff --git a/packages/rs-drive/src/drive/identity/withdrawals/withdrawal_status.rs b/packages/rs-drive/src/drive/identity/withdrawals/withdrawal_status.rs index 76c09276d9d..49bbb20aab5 100644 --- a/packages/rs-drive/src/drive/identity/withdrawals/withdrawal_status.rs +++ b/packages/rs-drive/src/drive/identity/withdrawals/withdrawal_status.rs @@ -26,7 +26,7 @@ impl Drive { let query_cbor = serializer::value_to_cbor(query_value, None)?; - let (documents, _, _) = self.query_documents( + let (documents, _, _) = self.query_raw_documents_using_cbor_encoded_query_with_cost( &query_cbor, withdrawals_contract::CONTRACT_ID.clone().to_buffer(), withdrawals_contract::types::WITHDRAWAL, @@ -65,7 +65,7 @@ impl Drive { let query_cbor = serializer::value_to_cbor(query_value, None)?; - let (documents, _, _) = self.query_documents( + let (documents, _, _) = self.query_raw_documents_using_cbor_encoded_query_with_cost( &query_cbor, data_contract_id.to_buffer(), withdrawals_contract::types::WITHDRAWAL, diff --git a/packages/rs-drive/src/drive/query.rs b/packages/rs-drive/src/drive/query.rs index 57fe7e61014..dc165f4c2ba 100644 --- a/packages/rs-drive/src/drive/query.rs +++ b/packages/rs-drive/src/drive/query.rs @@ -43,13 +43,98 @@ use crate::fee::op::DriveOperation; use crate::query::DriveQuery; use dpp::data_contract::document_type::DocumentType; use dpp::data_contract::DriveContractExt; +use dpp::document::document_stub::DocumentStub; use crate::drive::block_info::BlockInfo; use crate::fee_pools::epochs::Epoch; impl Drive { + /// Performs and returns the result of the specified query along with skipped items. + /// Documents are returned as raw bytes and must later be decoded + /// Use query_documents instead if you would prefer the result be documents directly + pub fn query_raw_documents( + &self, + drive_query: DriveQuery, + transaction: TransactionArg, + drive_operations: &mut Vec, + ) -> Result<(Vec>, u16), Error> { + drive_query.execute_no_proof_internal(self, transaction, drive_operations) + } + + /// Performs and returns the result of the specified query along with skipped items and the cost. + /// Documents are returned as raw bytes and must later be decoded + /// Use query_raw_documents_with_cost instead if you would prefer the result be documents directly + pub fn query_raw_documents_with_cost( + &self, + drive_query: DriveQuery, + transaction: TransactionArg, + epoch: Option<&Epoch>, + ) -> Result<(Vec>, u16, u64), Error> { + let mut drive_operations: Vec = vec![]; + let (items, skipped) = + drive_query.execute_no_proof_internal(self, transaction, &mut drive_operations)?; + let cost = if let Some(epoch) = epoch { + let fee_result = calculate_fee(None, Some(drive_operations), epoch)?; + fee_result.processing_fee + } else { + 0 + }; + + Ok((items, skipped, cost)) + } + /// Performs and returns the result of the specified query along with skipped items and the cost. pub fn query_documents( + &self, + drive_query: DriveQuery, + transaction: TransactionArg, + drive_operations: &mut Vec, + ) -> Result<(Vec, u16), Error> { + let (items, skipped) = + drive_query.execute_no_proof_internal(self, transaction, drive_operations)?; + + let documents = items + .into_iter() + .map(|document_bytes| { + DocumentStub::from_cbor(document_bytes.as_slice(), None, None) + .map_err(Error::Protocol) + }) + .collect::, Error>>()?; + + Ok((documents, skipped)) + } + + /// Performs and returns the result of the specified query along with skipped items and the cost. + pub fn query_documents_with_cost( + &self, + drive_query: DriveQuery, + transaction: TransactionArg, + epoch: Option<&Epoch>, + ) -> Result<(Vec, u16, u64), Error> { + let mut drive_operations: Vec = vec![]; + let (items, skipped) = + drive_query.execute_no_proof_internal(self, transaction, &mut drive_operations)?; + let cost = if let Some(epoch) = epoch { + let fee_result = calculate_fee(None, Some(drive_operations), epoch)?; + fee_result.processing_fee + } else { + 0 + }; + + let documents = items + .into_iter() + .map(|document_bytes| { + DocumentStub::from_cbor(document_bytes.as_slice(), None, None) + .map_err(Error::Protocol) + }) + .collect::, Error>>()?; + + Ok((documents, skipped, cost)) + } + + /// Performs and returns the result of the specified query along with skipped items and the cost. + /// The query must be cbor encoded + pub fn query_raw_documents_using_cbor_encoded_query_with_cost( &self, query_cbor: &[u8], contract_id: [u8; 32], @@ -71,7 +156,7 @@ impl Drive { let document_type = contract .contract .document_type_for_name(document_type_name)?; - let (items, skipped) = self.query_documents_from_contract_internal( + let (items, skipped) = self.query_raw_documents_using_cbor_encoded_query( &contract.contract, document_type, query_cbor, @@ -89,7 +174,7 @@ impl Drive { } /// Performs and returns the result of the specified query along with skipped items and the cost. - pub fn query_documents_from_contract_cbor( + pub fn query_raw_documents_from_contract_cbor_using_cbor_encoded_query_with_cost( &self, contract_cbor: &[u8], document_type_name: String, @@ -102,7 +187,7 @@ impl Drive { //todo cbor cost let document_type = contract.document_type_for_name(document_type_name.as_str())?; - let (items, skipped) = self.query_documents_from_contract_internal( + let (items, skipped) = self.query_raw_documents_using_cbor_encoded_query( &contract, document_type, query_cbor, @@ -119,7 +204,7 @@ impl Drive { } /// Performs and returns the result of the specified query along with skipped items and the cost. - pub fn query_documents_from_contract( + pub fn query_raw_documents_from_contract_using_cbor_encoded_query_with_cost( &self, contract: &Contract, document_type: &DocumentType, @@ -128,7 +213,7 @@ impl Drive { transaction: TransactionArg, ) -> Result<(Vec>, u16, u64), Error> { let mut drive_operations: Vec = vec![]; - let (items, skipped) = self.query_documents_from_contract_internal( + let (items, skipped) = self.query_raw_documents_using_cbor_encoded_query( contract, document_type, query_cbor, @@ -145,7 +230,7 @@ impl Drive { } /// Performs and returns the result of the specified query along with skipped items. - pub(crate) fn query_documents_from_contract_internal( + pub(crate) fn query_raw_documents_using_cbor_encoded_query( &self, contract: &Contract, document_type: &DocumentType, @@ -155,12 +240,12 @@ impl Drive { ) -> Result<(Vec>, u16), Error> { let query = DriveQuery::from_cbor(query_cbor, contract, document_type)?; - query.execute_no_proof_internal(self, transaction, drive_operations) + self.query_raw_documents(query, transaction, drive_operations) } /// Performs and returns the result of the specified query along with the fee. /// Proof is generated. - pub fn query_documents_as_grove_proof( + pub fn query_proof_of_documents_using_contract_id_using_cbor_encoded_query_with_cost( &self, query_cbor: &[u8], contract_id: [u8; 32], @@ -183,7 +268,7 @@ impl Drive { let document_type = contract .contract .document_type_for_name(document_type_name)?; - let items = self.query_documents_from_contract_as_grove_proof_internal( + let items = self.query_proof_of_documents_using_cbor_encoded_query( &contract.contract, document_type, query_cbor, @@ -201,38 +286,7 @@ impl Drive { /// Performs and returns the result of the specified query along with the fee. /// Proof is generated. - pub fn query_documents_from_contract_cbor_as_grove_proof( - &self, - contract_cbor: &[u8], - document_type_name: String, - query_cbor: &[u8], - block_info: Option, - transaction: TransactionArg, - ) -> Result<(Vec, u64), Error> { - let mut drive_operations: Vec = vec![]; - let contract = ::from_cbor(contract_cbor, None)?; - - let document_type = contract.document_type_for_name(document_type_name.as_str())?; - - let items = self.query_documents_from_contract_as_grove_proof_internal( - &contract, - document_type, - query_cbor, - transaction, - &mut drive_operations, - )?; - let cost = if let Some(block_info) = block_info { - let fee_result = calculate_fee(None, Some(drive_operations), &block_info.epoch)?; - fee_result.processing_fee - } else { - 0 - }; - Ok((items, cost)) - } - - /// Performs and returns the result of the specified query along with the fee. - /// Proof is generated. - pub fn query_documents_from_contract_as_grove_proof( + pub fn query_proof_of_documents_using_cbor_encoded_query_with_cost( &self, contract: &Contract, document_type: &DocumentType, @@ -242,7 +296,7 @@ impl Drive { ) -> Result<(Vec, u64), Error> { let mut drive_operations: Vec = vec![]; - let items = self.query_documents_from_contract_as_grove_proof_internal( + let items = self.query_proof_of_documents_using_cbor_encoded_query( contract, document_type, query_cbor, @@ -260,7 +314,7 @@ impl Drive { /// Performs and returns the result of the specified internal query. /// Proof is generated. - pub(crate) fn query_documents_from_contract_as_grove_proof_internal( + pub(crate) fn query_proof_of_documents_using_cbor_encoded_query( &self, contract: &Contract, document_type: &DocumentType, @@ -274,7 +328,7 @@ impl Drive { } /// Performs the specified internal query and returns the root hash, values, and fee. - pub fn query_documents_from_contract_as_grove_proof_only_get_elements( + pub fn query_proof_of_documents_using_cbor_encoded_query_only_get_elements( &self, contract: &Contract, document_type: &DocumentType, @@ -285,7 +339,7 @@ impl Drive { let mut drive_operations: Vec = vec![]; let (root_hash, items) = self - .query_documents_from_contract_as_grove_proof_only_get_elements_internal( + .query_proof_of_documents_using_cbor_encoded_query_only_get_elements_internal( contract, document_type, query_cbor, @@ -302,7 +356,7 @@ impl Drive { } /// Performs the specified internal query and returns the root hash and values. - pub(crate) fn query_documents_from_contract_as_grove_proof_only_get_elements_internal( + pub(crate) fn query_proof_of_documents_using_cbor_encoded_query_only_get_elements_internal( &self, contract: &Contract, document_type: &DocumentType, diff --git a/packages/rs-drive/tests/query_tests.rs b/packages/rs-drive/tests/query_tests.rs index c8302bf839b..93dd78086e2 100644 --- a/packages/rs-drive/tests/query_tests.rs +++ b/packages/rs-drive/tests/query_tests.rs @@ -818,7 +818,7 @@ fn test_family_basic_queries() { .expect("contract should have a person document type"); let (results, _, _) = drive - .query_documents_from_contract( + .query_raw_documents_from_contract_using_cbor_encoded_query_with_cost( &contract, person_document_type, query_cbor.as_slice(), @@ -829,7 +829,7 @@ fn test_family_basic_queries() { assert_eq!(results.len(), 1); let (proof_root_hash, proof_results, _) = drive - .query_documents_from_contract_as_grove_proof_only_get_elements( + .query_proof_of_documents_using_cbor_encoded_query_only_get_elements( &contract, person_document_type, query_cbor.as_slice(), @@ -858,7 +858,7 @@ fn test_family_basic_queries() { .expect("contract should have a person document type"); let (results, _, _) = drive - .query_documents_from_contract( + .query_raw_documents_from_contract_using_cbor_encoded_query_with_cost( &contract, person_document_type, query_cbor.as_slice(), @@ -870,7 +870,7 @@ fn test_family_basic_queries() { assert_eq!(results.len(), 1); let (proof_root_hash, proof_results, _) = drive - .query_documents_from_contract_as_grove_proof_only_get_elements( + .query_proof_of_documents_using_cbor_encoded_query_only_get_elements( &contract, person_document_type, query_cbor.as_slice(), @@ -914,7 +914,7 @@ fn test_family_basic_queries() { .expect("contract should have a person document type"); let (results, _, _) = drive - .query_documents_from_contract( + .query_raw_documents_from_contract_using_cbor_encoded_query_with_cost( &contract, person_document_type, query_cbor.as_slice(), @@ -926,7 +926,7 @@ fn test_family_basic_queries() { assert_eq!(results.len(), 1); let (proof_root_hash, proof_results, _) = drive - .query_documents_from_contract_as_grove_proof_only_get_elements( + .query_proof_of_documents_using_cbor_encoded_query_only_get_elements( &contract, person_document_type, query_cbor.as_slice(), @@ -957,7 +957,7 @@ fn test_family_basic_queries() { .expect("contract should have a person document type"); let (results, _, _) = drive - .query_documents_from_contract( + .query_raw_documents_from_contract_using_cbor_encoded_query_with_cost( &contract, person_document_type, query_cbor.as_slice(), @@ -969,7 +969,7 @@ fn test_family_basic_queries() { assert_eq!(results.len(), 1); let (proof_root_hash, proof_results, _) = drive - .query_documents_from_contract_as_grove_proof_only_get_elements( + .query_proof_of_documents_using_cbor_encoded_query_only_get_elements( &contract, person_document_type, query_cbor.as_slice(), @@ -1008,7 +1008,7 @@ fn test_family_basic_queries() { .expect("contract should have a person document type"); let (results, _, _) = drive - .query_documents_from_contract( + .query_raw_documents_from_contract_using_cbor_encoded_query_with_cost( &contract, person_document_type, query_cbor.as_slice(), @@ -1020,7 +1020,7 @@ fn test_family_basic_queries() { assert_eq!(results.len(), 0); let (proof_root_hash, proof_results, _) = drive - .query_documents_from_contract_as_grove_proof_only_get_elements( + .query_proof_of_documents_using_cbor_encoded_query_only_get_elements( &contract, person_document_type, query_cbor.as_slice(), @@ -1048,7 +1048,7 @@ fn test_family_basic_queries() { .expect("contract should have a person document type"); let (results, _, _) = drive - .query_documents_from_contract( + .query_raw_documents_from_contract_using_cbor_encoded_query_with_cost( &contract, person_document_type, query_cbor.as_slice(), @@ -1060,7 +1060,7 @@ fn test_family_basic_queries() { assert_eq!(results.len(), 1); let (proof_root_hash, proof_results, _) = drive - .query_documents_from_contract_as_grove_proof_only_get_elements( + .query_proof_of_documents_using_cbor_encoded_query_only_get_elements( &contract, person_document_type, query_cbor.as_slice(), @@ -1631,7 +1631,7 @@ fn test_family_basic_queries() { .expect("contract should have a person document type"); let (results, _, _) = drive - .query_documents_from_contract( + .query_raw_documents_from_contract_using_cbor_encoded_query_with_cost( &contract, person_document_type, query_cbor.as_slice(), @@ -1674,7 +1674,7 @@ fn test_family_basic_queries() { .expect("contract should have a person document type"); let (results, _, _) = drive - .query_documents_from_contract( + .query_raw_documents_from_contract_using_cbor_encoded_query_with_cost( &contract, person_document_type, query_cbor.as_slice(), @@ -1715,7 +1715,7 @@ fn test_family_basic_queries() { .expect("contract should have a person document type"); let (results, _, _) = drive - .query_documents_from_contract( + .query_raw_documents_from_contract_using_cbor_encoded_query_with_cost( &contract, person_document_type, query_cbor.as_slice(), @@ -1752,7 +1752,7 @@ fn test_family_basic_queries() { .expect("contract should have a person document type"); let (results, _, _) = drive - .query_documents_from_contract( + .query_raw_documents_from_contract_using_cbor_encoded_query_with_cost( &contract, person_document_type, query_cbor.as_slice(), @@ -1779,7 +1779,7 @@ fn test_family_basic_queries() { .expect("contract should have a person document type"); let (results, _, _) = drive - .query_documents_from_contract( + .query_raw_documents_from_contract_using_cbor_encoded_query_with_cost( &contract, person_document_type, query_cbor.as_slice(), @@ -1821,7 +1821,7 @@ fn test_family_basic_queries() { .expect("contract should have a person document type"); let (results, _, _) = drive - .query_documents_from_contract( + .query_raw_documents_from_contract_using_cbor_encoded_query_with_cost( &contract, person_document_type, query_cbor.as_slice(), @@ -1851,7 +1851,7 @@ fn test_family_basic_queries() { .expect("contract should have a person document type"); let (results, _, _) = drive - .query_documents_from_contract( + .query_raw_documents_from_contract_using_cbor_encoded_query_with_cost( &contract, person_document_type, query_cbor.as_slice(), @@ -1888,7 +1888,7 @@ fn test_family_basic_queries() { serializer::value_to_cbor(query_value, None).expect("expected to serialize to cbor"); let (results, _, _) = drive - .query_documents_from_contract_cbor( + .query_raw_documents_from_contract_cbor_using_cbor_encoded_query_with_cost( contract_cbor.as_slice(), String::from("contact"), query_cbor.as_slice(), @@ -1917,7 +1917,7 @@ fn test_family_basic_queries() { .expect("contract should have a person document type"); let (results, _, _) = drive - .query_documents_from_contract( + .query_raw_documents_from_contract_using_cbor_encoded_query_with_cost( &contract, person_document_type, query_cbor.as_slice(), @@ -1946,7 +1946,7 @@ fn test_family_basic_queries() { .get("person") .expect("contract should have a person document type"); - let result = drive.query_documents_from_contract( + let result = drive.query_raw_documents_from_contract_using_cbor_encoded_query_with_cost( &contract, person_document_type, query_cbor.as_slice(), @@ -1976,7 +1976,7 @@ fn test_family_basic_queries() { .get("person") .expect("contract should have a person document type"); - let result = drive.query_documents_from_contract( + let result = drive.query_raw_documents_from_contract_using_cbor_encoded_query_with_cost( &contract, person_document_type, query_cbor.as_slice(), @@ -2547,7 +2547,7 @@ fn test_query_with_cached_contract() { serializer::value_to_cbor(query_value, None).expect("expected to serialize to cbor"); let (results, _, _) = drive - .query_documents( + .query_raw_documents_using_cbor_encoded_query_with_cost( where_cbor.as_slice(), *contract.id.as_bytes(), "person", @@ -2994,7 +2994,7 @@ fn test_dpns_insertion_no_aliases() { .expect("contract should have a domain document type"); let result = drive - .query_documents_from_contract( + .query_raw_documents_from_contract_using_cbor_encoded_query_with_cost( &contract, domain_document_type, query_cbor.as_slice(), @@ -3006,7 +3006,7 @@ fn test_dpns_insertion_no_aliases() { assert_eq!(result.0.len(), 15); let (proof_root_hash, proof_results, _) = drive - .query_documents_from_contract_as_grove_proof_only_get_elements( + .query_proof_of_documents_using_cbor_encoded_query_only_get_elements( &contract, domain_document_type, query_cbor.as_slice(), @@ -3046,7 +3046,7 @@ fn test_dpns_insertion_with_aliases() { .expect("contract should have a domain document type"); let result = drive - .query_documents_from_contract( + .query_raw_documents_from_contract_using_cbor_encoded_query_with_cost( &contract, domain_document_type, query_cbor.as_slice(), @@ -3058,7 +3058,7 @@ fn test_dpns_insertion_with_aliases() { assert_eq!(result.0.len(), 24); let (proof_root_hash, proof_results, _) = drive - .query_documents_from_contract_as_grove_proof_only_get_elements( + .query_proof_of_documents_using_cbor_encoded_query_only_get_elements( &contract, domain_document_type, query_cbor.as_slice(), @@ -4237,7 +4237,7 @@ fn test_query_a_b_c_d_e_contract() { serializer::value_to_cbor(query_json, None).expect("expected to serialize to cbor"); drive - .query_documents_from_contract( + .query_raw_documents_from_contract_using_cbor_encoded_query_with_cost( &contract, contract .document_types() diff --git a/packages/rs-drive/tests/query_tests_history.rs b/packages/rs-drive/tests/query_tests_history.rs index 5276ae06aee..047ebc6fdd2 100644 --- a/packages/rs-drive/tests/query_tests_history.rs +++ b/packages/rs-drive/tests/query_tests_history.rs @@ -335,7 +335,7 @@ fn test_query_historical() { .expect("contract should have a person document type"); let (results, _, _) = drive - .query_documents_from_contract( + .query_raw_documents_from_contract_using_cbor_encoded_query_with_cost( &contract, person_document_type, query_cbor.as_slice(), @@ -364,7 +364,7 @@ fn test_query_historical() { .expect("contract should have a person document type"); let (results, _, _) = drive - .query_documents_from_contract( + .query_raw_documents_from_contract_using_cbor_encoded_query_with_cost( &contract, person_document_type, query_cbor.as_slice(), @@ -408,7 +408,7 @@ fn test_query_historical() { .expect("contract should have a person document type"); let (results, _, _) = drive - .query_documents_from_contract( + .query_raw_documents_from_contract_using_cbor_encoded_query_with_cost( &contract, person_document_type, query_cbor.as_slice(), @@ -439,7 +439,7 @@ fn test_query_historical() { .expect("contract should have a person document type"); let (results, _, _) = drive - .query_documents_from_contract( + .query_raw_documents_from_contract_using_cbor_encoded_query_with_cost( &contract, person_document_type, query_cbor.as_slice(), @@ -478,7 +478,7 @@ fn test_query_historical() { .expect("contract should have a person document type"); let (results, _, _) = drive - .query_documents_from_contract( + .query_raw_documents_from_contract_using_cbor_encoded_query_with_cost( &contract, person_document_type, query_cbor.as_slice(), @@ -506,7 +506,7 @@ fn test_query_historical() { .expect("contract should have a person document type"); let (results, _, _) = drive - .query_documents_from_contract( + .query_raw_documents_from_contract_using_cbor_encoded_query_with_cost( &contract, person_document_type, query_cbor.as_slice(), @@ -1134,7 +1134,7 @@ fn test_query_historical() { .expect("contract should have a person document type"); let (results, _, _) = drive - .query_documents_from_contract( + .query_raw_documents_from_contract_using_cbor_encoded_query_with_cost( &contract, person_document_type, query_cbor.as_slice(), @@ -1160,7 +1160,7 @@ fn test_query_historical() { .expect("contract should have a person document type"); let (results, _, _) = drive - .query_documents_from_contract( + .query_raw_documents_from_contract_using_cbor_encoded_query_with_cost( &contract, person_document_type, query_cbor.as_slice(), @@ -1187,7 +1187,7 @@ fn test_query_historical() { .expect("contract should have a person document type"); let (results, _, _) = drive - .query_documents_from_contract( + .query_raw_documents_from_contract_using_cbor_encoded_query_with_cost( &contract, person_document_type, query_cbor.as_slice(), @@ -1216,7 +1216,7 @@ fn test_query_historical() { .expect("contract should have a person document type"); let (results, _, _) = drive - .query_documents_from_contract( + .query_raw_documents_from_contract_using_cbor_encoded_query_with_cost( &contract, person_document_type, query_cbor.as_slice(), @@ -1257,7 +1257,7 @@ fn test_query_historical() { .expect("contract should have a person document type"); let (results, _, _) = drive - .query_documents_from_contract( + .query_raw_documents_from_contract_using_cbor_encoded_query_with_cost( &contract, person_document_type, query_cbor.as_slice(), @@ -1294,7 +1294,7 @@ fn test_query_historical() { .expect("contract should have a person document type"); let (results, _, _) = drive - .query_documents_from_contract( + .query_raw_documents_from_contract_using_cbor_encoded_query_with_cost( &contract, person_document_type, query_cbor.as_slice(), @@ -1321,7 +1321,7 @@ fn test_query_historical() { .expect("contract should have a person document type"); let (results, _, _) = drive - .query_documents_from_contract( + .query_raw_documents_from_contract_using_cbor_encoded_query_with_cost( &contract, person_document_type, query_cbor.as_slice(), @@ -1373,7 +1373,7 @@ fn test_query_historical() { .expect("contract should have a person document type"); drive - .query_documents_from_contract( + .query_raw_documents_from_contract_using_cbor_encoded_query_with_cost( &contract, person_document_type, query_cbor.as_slice(), @@ -1427,7 +1427,7 @@ fn test_query_historical() { .expect("contract should have a person document type"); let (results, _, _) = drive - .query_documents_from_contract( + .query_raw_documents_from_contract_using_cbor_encoded_query_with_cost( &contract, person_document_type, query_cbor.as_slice(), @@ -1457,7 +1457,7 @@ fn test_query_historical() { .expect("contract should have a person document type"); let (results, _, _) = drive - .query_documents_from_contract( + .query_raw_documents_from_contract_using_cbor_encoded_query_with_cost( &contract, person_document_type, query_cbor.as_slice(), @@ -1494,7 +1494,7 @@ fn test_query_historical() { serializer::value_to_cbor(query_value, None).expect("expected to serialize to cbor"); let (results, _, _) = drive - .query_documents_from_contract_cbor( + .query_raw_documents_from_contract_cbor_using_cbor_encoded_query_with_cost( contract_cbor.as_slice(), String::from("contact"), query_cbor.as_slice(), @@ -1523,7 +1523,7 @@ fn test_query_historical() { .get("person") .expect("contract should have a person document type"); - let result = drive.query_documents_from_contract( + let result = drive.query_raw_documents_from_contract_using_cbor_encoded_query_with_cost( &contract, person_document_type, query_cbor.as_slice(), @@ -1553,7 +1553,7 @@ fn test_query_historical() { .get("person") .expect("contract should have a person document type"); - let result = drive.query_documents_from_contract( + let result = drive.query_raw_documents_from_contract_using_cbor_encoded_query_with_cost( &contract, person_document_type, query_cbor.as_slice(), From d6cb41f94942042585e9d971b83ff19405ac72b5 Mon Sep 17 00:00:00 2001 From: Djavid Gabibiyan Date: Thu, 2 Feb 2023 22:06:01 +0500 Subject: [PATCH 095/170] chore: PR comments --- packages/rs-drive-abci/src/abci/handlers.rs | 3 + .../src/identity_credit_withdrawal/mod.rs | 12 +-- packages/rs-drive-nodejs/src/lib.rs | 2 +- packages/rs-drive/src/common/helpers/mod.rs | 1 - .../src/drive/batch/drive_op_batch.rs | 44 +++++++--- packages/rs-drive/src/drive/contract/mod.rs | 2 +- .../rs-drive/src/drive/document/update.rs | 4 +- .../epochs/credit_distribution_pools.rs | 2 +- .../src/drive/fee_pools/epochs/mod.rs | 2 +- .../src/drive/fee_pools/epochs/proposers.rs | 2 +- .../src/drive/fee_pools/epochs/start_block.rs | 2 +- .../src/drive/fee_pools/epochs/start_time.rs | 2 +- packages/rs-drive/src/drive/fee_pools/mod.rs | 2 +- .../drive/fee_pools/pending_epoch_updates.rs | 2 +- .../storage_fee_distribution_pool.rs | 2 +- .../src/drive/fee_pools/unpaid_epoch.rs | 2 +- packages/rs-drive/src/drive/genesis_time.rs | 2 +- packages/rs-drive/src/drive/identity/mod.rs | 2 +- .../src/drive/identity/withdrawals/paths.rs | 12 +-- .../src/drive/identity/withdrawals/queue.rs | 82 +++++++++---------- .../withdrawals/transaction_index_counter.rs | 30 +++---- .../identity/withdrawals/withdrawal_status.rs | 8 +- .../fee_pools/epochs/operations_factory.rs | 2 +- packages/rs-drive/src/fee_pools/mod.rs | 2 +- packages/rs-drive/src/lib.rs | 4 + packages/rs-drive/src/tests/helpers/mod.rs | 1 + .../src/{common => tests}/helpers/setup.rs | 0 packages/rs-drive/src/tests/mod.rs | 1 + packages/rs-drive/tests/query_tests.rs | 3 +- .../rs-drive/tests/query_tests_history.rs | 4 +- 30 files changed, 135 insertions(+), 104 deletions(-) create mode 100644 packages/rs-drive/src/tests/helpers/mod.rs rename packages/rs-drive/src/{common => tests}/helpers/setup.rs (100%) create mode 100644 packages/rs-drive/src/tests/mod.rs diff --git a/packages/rs-drive-abci/src/abci/handlers.rs b/packages/rs-drive-abci/src/abci/handlers.rs index 78e037fc364..aba13ff66cf 100644 --- a/packages/rs-drive-abci/src/abci/handlers.rs +++ b/packages/rs-drive-abci/src/abci/handlers.rs @@ -120,6 +120,9 @@ impl TenderdashAbci for Platform { epoch_info: epoch_info.clone(), }; + // If last synced Core block height is not set instead of scanning + // number of blocks for asset unlock transactions scan only one + // on Core chain locked height by setting last_synced_core_height to the same value let last_synced_core_height = if request.last_synced_core_height == 0 { block_execution_context.block_info.core_chain_locked_height } else { diff --git a/packages/rs-drive-abci/src/identity_credit_withdrawal/mod.rs b/packages/rs-drive-abci/src/identity_credit_withdrawal/mod.rs index a8370e83c26..7052d23e4ce 100644 --- a/packages/rs-drive-abci/src/identity_credit_withdrawal/mod.rs +++ b/packages/rs-drive-abci/src/identity_credit_withdrawal/mod.rs @@ -197,9 +197,11 @@ impl Platform { let mut drive_operations: Vec = vec![]; // Get 16 latest withdrawal transactions from the queue - let withdrawal_transactions = self - .drive - .dequeue_withdrawal_transactions(WITHDRAWAL_TRANSACTIONS_QUERY_LIMIT, transaction)?; + let withdrawal_transactions = self.drive.dequeue_withdrawal_transactions( + WITHDRAWAL_TRANSACTIONS_QUERY_LIMIT, + transaction, + &mut drive_operations, + )?; // Appending request_height and quorum_hash to withdrwal transaction // and pass it to JS Drive for singing and broadcasting @@ -449,7 +451,7 @@ impl Platform { let latest_withdrawal_index = self .drive - .fetch_latest_withdrawal_transaction_index(transaction)?; + .remove_latest_withdrawal_transaction_index(transaction)?; for (i, document) in documents.iter().enumerate() { let output_script = document @@ -534,7 +536,7 @@ mod tests { contracts::withdrawals_contract, tests::fixtures::{get_withdrawal_document_fixture, get_withdrawals_data_contract_fixture}, }; - use drive::{common::helpers::setup::setup_document, rpc::core::MockCoreRPCLike}; + use drive::{rpc::core::MockCoreRPCLike, tests::helpers::setup::setup_document}; use serde_json::json; use crate::common::helpers::setup::setup_system_data_contract; diff --git a/packages/rs-drive-nodejs/src/lib.rs b/packages/rs-drive-nodejs/src/lib.rs index 200de99291a..3c6d2175b80 100644 --- a/packages/rs-drive-nodejs/src/lib.rs +++ b/packages/rs-drive-nodejs/src/lib.rs @@ -2212,7 +2212,7 @@ impl PlatformWrapper { let result = transaction_result.and_then(|transaction_arg| { platform .drive - .fetch_latest_withdrawal_transaction_index(transaction_arg) + .remove_latest_withdrawal_transaction_index(transaction_arg) .map_err(|err| err.to_string()) }); diff --git a/packages/rs-drive/src/common/helpers/mod.rs b/packages/rs-drive/src/common/helpers/mod.rs index ece28e30146..990fed2c0e5 100644 --- a/packages/rs-drive/src/common/helpers/mod.rs +++ b/packages/rs-drive/src/common/helpers/mod.rs @@ -1,3 +1,2 @@ pub mod epoch; pub mod identities; -pub mod setup; diff --git a/packages/rs-drive/src/drive/batch/drive_op_batch.rs b/packages/rs-drive/src/drive/batch/drive_op_batch.rs index 4e79a7cba67..0c37f7428cd 100644 --- a/packages/rs-drive/src/drive/batch/drive_op_batch.rs +++ b/packages/rs-drive/src/drive/batch/drive_op_batch.rs @@ -32,9 +32,10 @@ use crate::drive::block_info::BlockInfo; use crate::drive::flags::StorageFlags; use crate::drive::grove_operations::BatchDeleteApplyType; use crate::drive::identity::withdrawals::paths::{ - get_withdrawal_root_path, get_withdrawal_transactions_expired_ids_path, - get_withdrawal_transactions_expired_ids_path_as_u8, get_withdrawal_transactions_queue_path, - WithdrawalTransaction, WITHDRAWAL_TRANSACTIONS_COUNTER_ID, + get_withdrawal_root_path_vec, get_withdrawal_transactions_expired_ids_path, + get_withdrawal_transactions_expired_ids_path_vec, get_withdrawal_transactions_queue_path, + get_withdrawal_transactions_queue_path_vec, WithdrawalTransaction, + WITHDRAWAL_TRANSACTIONS_COUNTER_ID, }; use crate::drive::object_size_info::DocumentInfo::{ DocumentRefAndSerialization, DocumentRefWithoutSerialization, @@ -529,12 +530,6 @@ impl DriveOperationConverter for DocumentOperationType<'_> { storage_flags, } = update_operation; - let document_cbor = document.to_cbor(); - - // If serialized document not submitted updates are not performed - // TODO: figure that out - let serialized_document = serialized_document.or(Some(&document_cbor)); - let document_info = if let Some(serialized_document) = serialized_document { DocumentRefAndSerialization(( @@ -622,6 +617,11 @@ pub enum WithdrawalOperationType<'a> { /// transaction id bytes transactions: &'a [WithdrawalTransaction], }, + /// Delete withdrawal + DeleteWithdrawalTransaction { + /// withdrawal transaction tuple with id and bytes + id: Vec, + }, } impl DriveOperationConverter for WithdrawalOperationType<'_> { @@ -640,7 +640,7 @@ impl DriveOperationConverter for WithdrawalOperationType<'_> { let index_bytes = index.to_be_bytes(); - let path = get_withdrawal_transactions_expired_ids_path(); + let path = get_withdrawal_transactions_expired_ids_path_vec(); drive.batch_insert( crate::drive::object_size_info::PathKeyElementInfo::PathKeyElement::<'_, 1>(( @@ -656,7 +656,7 @@ impl DriveOperationConverter for WithdrawalOperationType<'_> { WithdrawalOperationType::DeleteExpiredIndex { key } => { let mut drive_operations = vec![]; - let path: [&[u8]; 2] = get_withdrawal_transactions_expired_ids_path_as_u8(); + let path: [&[u8]; 2] = get_withdrawal_transactions_expired_ids_path(); drive.batch_delete( path, @@ -673,7 +673,7 @@ impl DriveOperationConverter for WithdrawalOperationType<'_> { WithdrawalOperationType::UpdateIndexCounter { index } => { let mut drive_operations = vec![]; - let path = get_withdrawal_root_path(); + let path = get_withdrawal_root_path_vec(); drive.batch_insert( crate::drive::object_size_info::PathKeyElementInfo::PathKeyElement::<'_, 1>(( @@ -689,7 +689,7 @@ impl DriveOperationConverter for WithdrawalOperationType<'_> { WithdrawalOperationType::InsertTransactions { transactions } => { let mut drive_operations = vec![]; - let path = get_withdrawal_transactions_queue_path(); + let path = get_withdrawal_transactions_queue_path_vec(); for (id, bytes) in transactions { drive.batch_insert( @@ -700,6 +700,24 @@ impl DriveOperationConverter for WithdrawalOperationType<'_> { )?; } + Ok(drive_operations) + } + WithdrawalOperationType::DeleteWithdrawalTransaction { id } => { + let mut drive_operations = vec![]; + + let path = get_withdrawal_transactions_queue_path(); + + drive.batch_delete( + path, + &id, + // we know that we are not deleting a subtree + BatchDeleteApplyType::StatefulBatchDelete { + is_known_to_be_subtree_with_sum: Some((false, false)), + }, + transaction, + &mut drive_operations, + )?; + Ok(drive_operations) } } diff --git a/packages/rs-drive/src/drive/contract/mod.rs b/packages/rs-drive/src/drive/contract/mod.rs index 7c1d5a52ee9..bfb762c3b31 100644 --- a/packages/rs-drive/src/drive/contract/mod.rs +++ b/packages/rs-drive/src/drive/contract/mod.rs @@ -1011,7 +1011,7 @@ mod tests { use crate::drive::Drive; use dpp::data_contract::extra::common::json_document_to_cbor; - use crate::common::helpers::setup::setup_drive_with_initial_state_structure; + use crate::tests::helpers::setup::setup_drive_with_initial_state_structure; fn setup_deep_nested_50_contract() -> (Drive, Contract, Vec) { // Todo: make TempDir based on _prefix diff --git a/packages/rs-drive/src/drive/document/update.rs b/packages/rs-drive/src/drive/document/update.rs index 17004a1b300..ab7f1e92064 100644 --- a/packages/rs-drive/src/drive/document/update.rs +++ b/packages/rs-drive/src/drive/document/update.rs @@ -649,7 +649,7 @@ impl Drive { documents: &'a [DocumentStub], data_contract: &'a DataContract, document_type: &'a DocumentType, - drive_operations: &mut Vec>, + drive_operation_types: &mut Vec>, ) { let operations: Vec = documents .iter() @@ -664,7 +664,7 @@ impl Drive { .collect(); if !operations.is_empty() { - drive_operations.push(DriveOperationType::DocumentOperation( + drive_operation_types.push(DriveOperationType::DocumentOperation( DocumentOperationType::MultipleDocumentOperationsForSameContractDocumentType { document_operations: DocumentOperationsForContractDocumentType { operations, diff --git a/packages/rs-drive/src/drive/fee_pools/epochs/credit_distribution_pools.rs b/packages/rs-drive/src/drive/fee_pools/epochs/credit_distribution_pools.rs index daa8be714ab..be00cbbee8a 100644 --- a/packages/rs-drive/src/drive/fee_pools/epochs/credit_distribution_pools.rs +++ b/packages/rs-drive/src/drive/fee_pools/epochs/credit_distribution_pools.rs @@ -147,9 +147,9 @@ impl Drive { mod tests { use super::*; - use crate::common::helpers::setup::setup_drive_with_initial_state_structure; use crate::drive::batch::GroveDbOpBatch; use crate::fee_pools::epochs_root_tree_key_constants::KEY_STORAGE_FEE_POOL; + use crate::tests::helpers::setup::setup_drive_with_initial_state_structure; mod get_epoch_storage_credits_for_distribution { use super::*; diff --git a/packages/rs-drive/src/drive/fee_pools/epochs/mod.rs b/packages/rs-drive/src/drive/fee_pools/epochs/mod.rs index ff07c475330..4e49e71c0f2 100644 --- a/packages/rs-drive/src/drive/fee_pools/epochs/mod.rs +++ b/packages/rs-drive/src/drive/fee_pools/epochs/mod.rs @@ -59,7 +59,7 @@ impl Drive { mod tests { use super::*; - use crate::common::helpers::setup::setup_drive_with_initial_state_structure; + use crate::tests::helpers::setup::setup_drive_with_initial_state_structure; mod is_epoch_tree_exists { use super::*; diff --git a/packages/rs-drive/src/drive/fee_pools/epochs/proposers.rs b/packages/rs-drive/src/drive/fee_pools/epochs/proposers.rs index dd549a4bab5..48b3b5ae711 100644 --- a/packages/rs-drive/src/drive/fee_pools/epochs/proposers.rs +++ b/packages/rs-drive/src/drive/fee_pools/epochs/proposers.rs @@ -152,8 +152,8 @@ impl Drive { #[cfg(test)] mod tests { use super::*; - use crate::common::helpers::setup::setup_drive_with_initial_state_structure; use crate::drive::batch::GroveDbOpBatch; + use crate::tests::helpers::setup::setup_drive_with_initial_state_structure; mod get_epochs_proposer_block_count { use super::*; diff --git a/packages/rs-drive/src/drive/fee_pools/epochs/start_block.rs b/packages/rs-drive/src/drive/fee_pools/epochs/start_block.rs index 626baa4dc46..591661c32a3 100644 --- a/packages/rs-drive/src/drive/fee_pools/epochs/start_block.rs +++ b/packages/rs-drive/src/drive/fee_pools/epochs/start_block.rs @@ -144,7 +144,7 @@ impl Drive { #[cfg(test)] mod tests { use super::*; - use crate::common::helpers::setup::setup_drive_with_initial_state_structure; + use crate::tests::helpers::setup::setup_drive_with_initial_state_structure; mod get_epoch_start_block_height { use super::*; diff --git a/packages/rs-drive/src/drive/fee_pools/epochs/start_time.rs b/packages/rs-drive/src/drive/fee_pools/epochs/start_time.rs index 5db343933c0..4e0cbe1cd17 100644 --- a/packages/rs-drive/src/drive/fee_pools/epochs/start_time.rs +++ b/packages/rs-drive/src/drive/fee_pools/epochs/start_time.rs @@ -72,7 +72,7 @@ impl Drive { #[cfg(test)] mod tests { - use crate::common::helpers::setup::setup_drive_with_initial_state_structure; + use crate::tests::helpers::setup::setup_drive_with_initial_state_structure; use super::*; diff --git a/packages/rs-drive/src/drive/fee_pools/mod.rs b/packages/rs-drive/src/drive/fee_pools/mod.rs index a5fabeca0b7..2afd7295c2b 100644 --- a/packages/rs-drive/src/drive/fee_pools/mod.rs +++ b/packages/rs-drive/src/drive/fee_pools/mod.rs @@ -172,7 +172,7 @@ impl Drive { mod tests { use super::*; - use crate::common::helpers::setup::setup_drive_with_initial_state_structure; + use crate::tests::helpers::setup::setup_drive_with_initial_state_structure; mod add_update_epoch_storage_fee_pools_operations { use super::*; diff --git a/packages/rs-drive/src/drive/fee_pools/pending_epoch_updates.rs b/packages/rs-drive/src/drive/fee_pools/pending_epoch_updates.rs index 630ece00ab5..51728ebf483 100644 --- a/packages/rs-drive/src/drive/fee_pools/pending_epoch_updates.rs +++ b/packages/rs-drive/src/drive/fee_pools/pending_epoch_updates.rs @@ -210,7 +210,7 @@ pub fn add_update_pending_epoch_storage_pool_update_operations( #[cfg(test)] mod tests { use super::*; - use crate::common::helpers::setup::setup_drive_with_initial_state_structure; + use crate::tests::helpers::setup::setup_drive_with_initial_state_structure; mod fetch_and_merge_with_existing_pending_epoch_storage_pool_updates { use super::*; diff --git a/packages/rs-drive/src/drive/fee_pools/storage_fee_distribution_pool.rs b/packages/rs-drive/src/drive/fee_pools/storage_fee_distribution_pool.rs index d5610f36b34..2d8395f5dd0 100644 --- a/packages/rs-drive/src/drive/fee_pools/storage_fee_distribution_pool.rs +++ b/packages/rs-drive/src/drive/fee_pools/storage_fee_distribution_pool.rs @@ -64,7 +64,7 @@ impl Drive { mod tests { use super::*; - use crate::common::helpers::setup::{setup_drive, setup_drive_with_initial_state_structure}; + use crate::tests::helpers::setup::{setup_drive, setup_drive_with_initial_state_structure}; mod get_aggregate_storage_fees_from_distribution_pool { use super::*; diff --git a/packages/rs-drive/src/drive/fee_pools/unpaid_epoch.rs b/packages/rs-drive/src/drive/fee_pools/unpaid_epoch.rs index c298ea7b448..edd867df892 100644 --- a/packages/rs-drive/src/drive/fee_pools/unpaid_epoch.rs +++ b/packages/rs-drive/src/drive/fee_pools/unpaid_epoch.rs @@ -68,7 +68,7 @@ impl Drive { mod tests { use super::*; - use crate::common::helpers::setup::{setup_drive, setup_drive_with_initial_state_structure}; + use crate::tests::helpers::setup::{setup_drive, setup_drive_with_initial_state_structure}; mod get_unpaid_epoch_index { use super::*; diff --git a/packages/rs-drive/src/drive/genesis_time.rs b/packages/rs-drive/src/drive/genesis_time.rs index 8dc0488bbca..ca9f41ba713 100644 --- a/packages/rs-drive/src/drive/genesis_time.rs +++ b/packages/rs-drive/src/drive/genesis_time.rs @@ -77,7 +77,7 @@ impl Drive { mod tests { use super::*; - use crate::common::helpers::setup::{setup_drive, setup_drive_with_initial_state_structure}; + use crate::tests::helpers::setup::{setup_drive, setup_drive_with_initial_state_structure}; mod get_genesis_time { use super::*; diff --git a/packages/rs-drive/src/drive/identity/mod.rs b/packages/rs-drive/src/drive/identity/mod.rs index 07386aed9d4..949bda62688 100644 --- a/packages/rs-drive/src/drive/identity/mod.rs +++ b/packages/rs-drive/src/drive/identity/mod.rs @@ -234,9 +234,9 @@ impl Drive { #[cfg(test)] mod tests { - use crate::common::helpers::setup::setup_drive; use crate::drive::block_info::BlockInfo; use crate::drive::flags::StorageFlags; + use crate::tests::helpers::setup::setup_drive; use dpp::identity::Identity; #[test] diff --git a/packages/rs-drive/src/drive/identity/withdrawals/paths.rs b/packages/rs-drive/src/drive/identity/withdrawals/paths.rs index b6a1dcaf426..ac6ee715add 100644 --- a/packages/rs-drive/src/drive/identity/withdrawals/paths.rs +++ b/packages/rs-drive/src/drive/identity/withdrawals/paths.rs @@ -34,17 +34,17 @@ pub fn add_initial_withdrawal_state_structure_operations(batch: &mut GroveDbOpBa } /// Helper function to get root path -pub fn get_withdrawal_root_path() -> Vec> { +pub fn get_withdrawal_root_path_vec() -> Vec> { vec![vec![RootTree::WithdrawalTransactions as u8]] } /// Helper function to get root path as u8 -pub fn get_withdrawal_root_path_as_u8() -> [&'static [u8]; 1] { +pub fn get_withdrawal_root_path() -> [&'static [u8]; 1] { [Into::<&[u8; 1]>::into(RootTree::WithdrawalTransactions)] } /// Helper function to get queue path as Vec -pub fn get_withdrawal_transactions_queue_path() -> Vec> { +pub fn get_withdrawal_transactions_queue_path_vec() -> Vec> { vec![ vec![RootTree::WithdrawalTransactions as u8], WITHDRAWAL_TRANSACTIONS_QUEUE_ID.to_vec(), @@ -52,7 +52,7 @@ pub fn get_withdrawal_transactions_queue_path() -> Vec> { } /// Helper function to get queue path as [u8] -pub fn get_withdrawal_transactions_queue_path_as_u8() -> [&'static [u8]; 2] { +pub fn get_withdrawal_transactions_queue_path() -> [&'static [u8]; 2] { [ Into::<&[u8; 1]>::into(RootTree::WithdrawalTransactions), &WITHDRAWAL_TRANSACTIONS_QUEUE_ID, @@ -60,7 +60,7 @@ pub fn get_withdrawal_transactions_queue_path_as_u8() -> [&'static [u8]; 2] { } /// Helper function to get expired ids path as Vec -pub fn get_withdrawal_transactions_expired_ids_path() -> Vec> { +pub fn get_withdrawal_transactions_expired_ids_path_vec() -> Vec> { vec![ vec![RootTree::WithdrawalTransactions as u8], WITHDRAWAL_TRANSACTIONS_EXPIRED_IDS.to_vec(), @@ -68,7 +68,7 @@ pub fn get_withdrawal_transactions_expired_ids_path() -> Vec> { } /// Helper function to get expired ids path as [u8] -pub fn get_withdrawal_transactions_expired_ids_path_as_u8() -> [&'static [u8]; 2] { +pub fn get_withdrawal_transactions_expired_ids_path() -> [&'static [u8]; 2] { [ Into::<&[u8; 1]>::into(RootTree::WithdrawalTransactions), &WITHDRAWAL_TRANSACTIONS_EXPIRED_IDS, diff --git a/packages/rs-drive/src/drive/identity/withdrawals/queue.rs b/packages/rs-drive/src/drive/identity/withdrawals/queue.rs index 7305ea8f261..aaea60695ca 100644 --- a/packages/rs-drive/src/drive/identity/withdrawals/queue.rs +++ b/packages/rs-drive/src/drive/identity/withdrawals/queue.rs @@ -9,27 +9,22 @@ use crate::{ drive::{ batch::{drive_op_batch::WithdrawalOperationType, DriveOperationType}, block_info::BlockInfo, - grove_operations::BatchDeleteApplyType, Drive, }, error::{drive::DriveError, Error}, - fee::op::DriveOperation, }; -use super::paths::{ - get_withdrawal_transactions_queue_path, get_withdrawal_transactions_queue_path_as_u8, - WithdrawalTransaction, -}; +use super::paths::{get_withdrawal_transactions_queue_path_vec, WithdrawalTransaction}; impl Drive { /// Add insert operations for withdrawal transactions to the batch pub fn add_enqueue_withdrawal_transaction_operations<'a>( &self, withdrawals: &'a [WithdrawalTransaction], - drive_operations: &mut Vec>, + drive_operation_types: &mut Vec>, ) { if !withdrawals.is_empty() { - drive_operations.push(DriveOperationType::WithdrawalOperation( + drive_operation_types.push(DriveOperationType::WithdrawalOperation( WithdrawalOperationType::InsertTransactions { transactions: withdrawals, }, @@ -38,20 +33,21 @@ impl Drive { } /// Get specified amount of withdrawal transactions from the DB - pub fn dequeue_withdrawal_transactions( + pub fn dequeue_withdrawal_transactions<'a>( &self, - num_of_transactions: u16, + max_amount: u16, transaction: TransactionArg, + drive_operation_types: &mut Vec>, ) -> Result, Error> { let mut query = Query::new(); query.insert_item(QueryItem::RangeFull(RangeFull)); let path_query = PathQuery { - path: get_withdrawal_transactions_queue_path(), + path: get_withdrawal_transactions_queue_path_vec(), query: SizedQuery { query, - limit: Some(num_of_transactions), + limit: Some(max_amount), offset: None, }, }; @@ -80,30 +76,11 @@ impl Drive { .collect::, Vec)>, Error>>()?; if !withdrawals.is_empty() { - let mut batch_operations: Vec = vec![]; - let mut drive_operations: Vec = vec![]; - - let withdrawals_path: [&[u8]; 2] = get_withdrawal_transactions_queue_path_as_u8(); - for (id, _) in withdrawals.iter() { - self.batch_delete( - withdrawals_path, - id, - // we know that we are not deleting a subtree - BatchDeleteApplyType::StatefulBatchDelete { - is_known_to_be_subtree_with_sum: Some((false, false)), - }, - transaction, - &mut batch_operations, - )?; + drive_operation_types.push(DriveOperationType::WithdrawalOperation( + WithdrawalOperationType::DeleteWithdrawalTransaction { id: id.clone() }, + )); } - - self.apply_batch_drive_operations( - None, - transaction, - batch_operations, - &mut drive_operations, - )?; } Ok(withdrawals) @@ -117,17 +94,20 @@ impl Drive { block_info: &BlockInfo, transaction: TransactionArg, ) -> Result<(), Error> { - let mut drive_operations = vec![]; + let mut drive_operation_types = vec![]; let index_bytes = (index as u64).to_be_bytes().to_vec(); let withdrawals = vec![(index_bytes, transaction_bytes)]; - self.add_enqueue_withdrawal_transaction_operations(&withdrawals, &mut drive_operations); + self.add_enqueue_withdrawal_transaction_operations( + &withdrawals, + &mut drive_operation_types, + ); - self.add_update_withdrawal_index_counter_operation(index, &mut drive_operations); + self.add_update_withdrawal_index_counter_operation(index, &mut drive_operation_types); - self.apply_drive_operations(drive_operations, true, &block_info, transaction)?; + self.apply_drive_operations(drive_operation_types, true, &block_info, transaction)?; Ok(()) } @@ -136,9 +116,9 @@ impl Drive { #[cfg(test)] mod tests { use crate::{ - common::helpers::setup::setup_drive_with_initial_state_structure, drive::{batch::DriveOperationType, block_info::BlockInfo}, fee_pools::epochs::Epoch, + tests::helpers::setup::setup_drive_with_initial_state_structure, }; #[test] @@ -165,22 +145,40 @@ mod tests { .apply_drive_operations(drive_operations, true, &block_info, Some(&transaction)) .expect("to apply batch"); + let mut drive_operations: Vec = vec![]; + let withdrawals = drive - .dequeue_withdrawal_transactions(16, Some(&transaction)) + .dequeue_withdrawal_transactions(16, Some(&transaction), &mut drive_operations) .expect("to dequeue withdrawals"); + drive + .apply_drive_operations(drive_operations, true, &block_info, Some(&transaction)) + .expect("to apply batch"); + assert_eq!(withdrawals.len(), 16); + let mut drive_operations: Vec = vec![]; + let withdrawals = drive - .dequeue_withdrawal_transactions(16, Some(&transaction)) + .dequeue_withdrawal_transactions(16, Some(&transaction), &mut drive_operations) .expect("to dequeue withdrawals"); + drive + .apply_drive_operations(drive_operations, true, &block_info, Some(&transaction)) + .expect("to apply batch"); + assert_eq!(withdrawals.len(), 1); + let mut drive_operations: Vec = vec![]; + let withdrawals = drive - .dequeue_withdrawal_transactions(16, Some(&transaction)) + .dequeue_withdrawal_transactions(16, Some(&transaction), &mut drive_operations) .expect("to dequeue withdrawals"); + drive + .apply_drive_operations(drive_operations, true, &block_info, Some(&transaction)) + .expect("to apply batch"); + assert_eq!(withdrawals.len(), 0); } } diff --git a/packages/rs-drive/src/drive/identity/withdrawals/transaction_index_counter.rs b/packages/rs-drive/src/drive/identity/withdrawals/transaction_index_counter.rs index b3e90934343..8accd4adeb4 100644 --- a/packages/rs-drive/src/drive/identity/withdrawals/transaction_index_counter.rs +++ b/packages/rs-drive/src/drive/identity/withdrawals/transaction_index_counter.rs @@ -12,13 +12,13 @@ use crate::{ }; use super::paths::{ - get_withdrawal_transactions_expired_ids_path, - get_withdrawal_transactions_expired_ids_path_as_u8, WITHDRAWAL_TRANSACTIONS_COUNTER_ID, + get_withdrawal_transactions_expired_ids_path, get_withdrawal_transactions_expired_ids_path_vec, + WITHDRAWAL_TRANSACTIONS_COUNTER_ID, }; impl Drive { /// Get latest withdrawal index in a queue - pub fn fetch_latest_withdrawal_transaction_index( + pub fn remove_latest_withdrawal_transaction_index( &self, transaction: TransactionArg, ) -> Result { @@ -27,7 +27,7 @@ impl Drive { inner_query.insert_all(); let expired_index_query = PathQuery::new( - get_withdrawal_transactions_expired_ids_path(), + get_withdrawal_transactions_expired_ids_path_vec(), SizedQuery::new(inner_query, Some(1), None), ); @@ -53,7 +53,7 @@ impl Drive { )) })?); - let path: [&[u8]; 2] = get_withdrawal_transactions_expired_ids_path_as_u8(); + let path: [&[u8]; 2] = get_withdrawal_transactions_expired_ids_path(); self.grove.delete(path, key, None, transaction).unwrap()?; @@ -98,9 +98,9 @@ impl Drive { pub fn add_update_withdrawal_index_counter_operation( &self, value: u64, - drive_operations: &mut Vec, + drive_operation_types: &mut Vec, ) { - drive_operations.push(DriveOperationType::WithdrawalOperation( + drive_operation_types.push(DriveOperationType::WithdrawalOperation( WithdrawalOperationType::UpdateIndexCounter { index: value }, )); } @@ -109,9 +109,9 @@ impl Drive { pub fn add_insert_expired_index_operation( &self, transaction_index: u64, - drive_operations: &mut Vec, + drive_operation_types: &mut Vec, ) { - drive_operations.push(DriveOperationType::WithdrawalOperation( + drive_operation_types.push(DriveOperationType::WithdrawalOperation( WithdrawalOperationType::InsertExpiredIndex { index: transaction_index, }, @@ -124,12 +124,12 @@ mod tests { use grovedb::Element; use crate::{ - common::helpers::setup::setup_drive_with_initial_state_structure, drive::{ block_info::BlockInfo, - identity::withdrawals::paths::get_withdrawal_transactions_expired_ids_path_as_u8, + identity::withdrawals::paths::get_withdrawal_transactions_expired_ids_path, }, fee_pools::epochs::Epoch, + tests::helpers::setup::setup_drive_with_initial_state_structure, }; #[test] @@ -155,7 +155,7 @@ mod tests { .expect("to apply drive ops"); let stored_counter = drive - .fetch_latest_withdrawal_transaction_index(Some(&transaction)) + .remove_latest_withdrawal_transaction_index(Some(&transaction)) .expect("to withdraw counter"); assert_eq!(stored_counter, counter); @@ -168,7 +168,7 @@ mod tests { let transaction = drive.grove.start_transaction(); let stored_counter = drive - .fetch_latest_withdrawal_transaction_index(Some(&transaction)) + .remove_latest_withdrawal_transaction_index(Some(&transaction)) .expect("to withdraw counter"); assert_eq!(stored_counter, 0); @@ -182,7 +182,7 @@ mod tests { let bytes = 42u64.to_be_bytes(); - let path = get_withdrawal_transactions_expired_ids_path_as_u8(); + let path = get_withdrawal_transactions_expired_ids_path(); drive .grove @@ -197,7 +197,7 @@ mod tests { .expect("to update index counter"); let stored_counter = drive - .fetch_latest_withdrawal_transaction_index(Some(&transaction)) + .remove_latest_withdrawal_transaction_index(Some(&transaction)) .expect("to withdraw counter"); assert_eq!(stored_counter, 42); diff --git a/packages/rs-drive/src/drive/identity/withdrawals/withdrawal_status.rs b/packages/rs-drive/src/drive/identity/withdrawals/withdrawal_status.rs index 49bbb20aab5..1e2bd52b1de 100644 --- a/packages/rs-drive/src/drive/identity/withdrawals/withdrawal_status.rs +++ b/packages/rs-drive/src/drive/identity/withdrawals/withdrawal_status.rs @@ -4,7 +4,7 @@ use serde_json::json; use crate::{ drive::Drive, - error::{drive::DriveError, Error}, + error::{drive::DriveError, Error}, query::DriveQuery, }; impl Drive { @@ -24,6 +24,8 @@ impl Drive { ] }); + let dq = DriveQuery { contract: todo!(), document_type: todo!(), internal_clauses: todo!(), offset: todo!(), limit: todo!(), order_by: todo!(), start_at: todo!(), start_at_included: todo!(), block_time: todo!() }; + let query_cbor = serializer::value_to_cbor(query_value, None)?; let (documents, _, _) = self.query_raw_documents_using_cbor_encoded_query_with_cost( @@ -102,8 +104,8 @@ mod tests { use dpp::tests::fixtures::get_withdrawals_data_contract_fixture; use serde_json::json; - use crate::common::helpers::setup::setup_drive_with_initial_state_structure; - use crate::common::helpers::setup::{setup_document, setup_system_data_contract}; + use crate::tests::helpers::setup::setup_drive_with_initial_state_structure; + use crate::tests::helpers::setup::{setup_document, setup_system_data_contract}; mod fetch_withdrawal_documents_by_status { diff --git a/packages/rs-drive/src/fee_pools/epochs/operations_factory.rs b/packages/rs-drive/src/fee_pools/epochs/operations_factory.rs index 0874681b6e5..f8d5cf12557 100644 --- a/packages/rs-drive/src/fee_pools/epochs/operations_factory.rs +++ b/packages/rs-drive/src/fee_pools/epochs/operations_factory.rs @@ -217,7 +217,7 @@ impl Epoch { #[cfg(test)] mod tests { use super::*; - use crate::common::helpers::setup::{setup_drive, setup_drive_with_initial_state_structure}; + use crate::tests::helpers::setup::{setup_drive, setup_drive_with_initial_state_structure}; use chrono::Utc; mod increment_proposer_block_count_operation { diff --git a/packages/rs-drive/src/fee_pools/mod.rs b/packages/rs-drive/src/fee_pools/mod.rs index 0556f5fe3fe..68f343bcdcf 100644 --- a/packages/rs-drive/src/fee_pools/mod.rs +++ b/packages/rs-drive/src/fee_pools/mod.rs @@ -94,7 +94,7 @@ pub fn update_unpaid_epoch_index_operation(epoch_index: EpochIndex) -> GroveDbOp #[cfg(test)] mod tests { use super::*; - use crate::common::helpers::setup::setup_drive_with_initial_state_structure; + use crate::tests::helpers::setup::setup_drive_with_initial_state_structure; mod add_create_fee_pool_trees_operations { use super::*; diff --git a/packages/rs-drive/src/lib.rs b/packages/rs-drive/src/lib.rs index b09e4e44e65..d767ef67240 100644 --- a/packages/rs-drive/src/lib.rs +++ b/packages/rs-drive/src/lib.rs @@ -30,3 +30,7 @@ pub mod rpc; pub use dpp; /// GroveDB module pub use grovedb; + +/// Test helpers +#[cfg(test)] +pub mod tests; diff --git a/packages/rs-drive/src/tests/helpers/mod.rs b/packages/rs-drive/src/tests/helpers/mod.rs new file mode 100644 index 00000000000..138906d09f7 --- /dev/null +++ b/packages/rs-drive/src/tests/helpers/mod.rs @@ -0,0 +1 @@ +pub mod setup; diff --git a/packages/rs-drive/src/common/helpers/setup.rs b/packages/rs-drive/src/tests/helpers/setup.rs similarity index 100% rename from packages/rs-drive/src/common/helpers/setup.rs rename to packages/rs-drive/src/tests/helpers/setup.rs diff --git a/packages/rs-drive/src/tests/mod.rs b/packages/rs-drive/src/tests/mod.rs new file mode 100644 index 00000000000..1630fabcd1b --- /dev/null +++ b/packages/rs-drive/src/tests/mod.rs @@ -0,0 +1 @@ +pub mod helpers; diff --git a/packages/rs-drive/tests/query_tests.rs b/packages/rs-drive/tests/query_tests.rs index 93dd78086e2..14ba76e1e8a 100644 --- a/packages/rs-drive/tests/query_tests.rs +++ b/packages/rs-drive/tests/query_tests.rs @@ -46,7 +46,6 @@ use serde_json::json; use tempfile::TempDir; use drive::common; -use drive::common::helpers::setup::setup_drive; use drive::common::setup_contract; use drive::drive::batch::GroveDbOpBatch; use drive::drive::config::DriveConfig; @@ -57,6 +56,8 @@ use drive::drive::object_size_info::{DocumentAndContractInfo, OwnedDocumentInfo} use drive::drive::Drive; use drive::error::{query::QueryError, Error}; use drive::query::DriveQuery; +#[cfg(test)] +use drive::tests::helpers::setup::setup_drive; use dpp::data_contract::validation::data_contract_validator::DataContractValidator; use dpp::document::document_stub::DocumentStub; diff --git a/packages/rs-drive/tests/query_tests_history.rs b/packages/rs-drive/tests/query_tests_history.rs index 047ebc6fdd2..b4ba95fe59b 100644 --- a/packages/rs-drive/tests/query_tests_history.rs +++ b/packages/rs-drive/tests/query_tests_history.rs @@ -43,7 +43,9 @@ use serde::{Deserialize, Serialize}; use serde_json::json; use drive::common; -use drive::common::helpers::setup::setup_drive; + +use drive::tests::helpers::setup::setup_drive; + use drive::contract::Contract; use drive::drive::batch::GroveDbOpBatch; use drive::drive::config::DriveConfig; From 0234d7696aa13ebf036cf78a430d318f4df0610c Mon Sep 17 00:00:00 2001 From: Djavid Gabibiyan Date: Mon, 6 Feb 2023 17:21:09 +0500 Subject: [PATCH 096/170] chore: use `DocumentStub` --- .../src/contracts/withdrawals_contract.rs | 1 + packages/rs-dpp/src/document/document_stub.rs | 114 +++++++++- packages/rs-drive-abci/Cargo.toml | 2 +- packages/rs-drive-abci/src/abci/handlers.rs | 2 +- .../src/identity_credit_withdrawal/mod.rs | 199 +++++++++--------- packages/rs-drive/Cargo.toml | 1 + .../rs-drive/src/drive/document/convert.rs | 30 --- packages/rs-drive/src/drive/document/mod.rs | 3 - .../src/drive/identity/withdrawals/queue.rs | 5 +- .../identity/withdrawals/withdrawal_status.rs | 23 +- packages/rs-drive/src/lib.rs | 2 +- packages/rs-drive/src/tests/mod.rs | 1 + 12 files changed, 225 insertions(+), 158 deletions(-) delete mode 100644 packages/rs-drive/src/drive/document/convert.rs diff --git a/packages/rs-dpp/src/contracts/withdrawals_contract.rs b/packages/rs-dpp/src/contracts/withdrawals_contract.rs index 12e5d93ec8f..c29f3673c70 100644 --- a/packages/rs-dpp/src/contracts/withdrawals_contract.rs +++ b/packages/rs-dpp/src/contracts/withdrawals_contract.rs @@ -18,6 +18,7 @@ pub mod property_names { pub const OUTPUT_SCRIPT: &str = "outputScript"; pub const STATUS: &str = "status"; pub const CREATE_AT: &str = "$createdAt"; + pub const UPDATED_AT: &str = "$updatedAt"; pub const OWNER_ID: &str = "$ownerId"; } diff --git a/packages/rs-dpp/src/document/document_stub.rs b/packages/rs-dpp/src/document/document_stub.rs index 12d263c7b15..595d68d2e12 100644 --- a/packages/rs-dpp/src/document/document_stub.rs +++ b/packages/rs-dpp/src/document/document_stub.rs @@ -37,9 +37,8 @@ use std::convert::{TryFrom, TryInto}; use std::fmt; use std::io::{BufReader, Read}; -use byteorder::{BigEndian, WriteBytesExt}; -use ciborium::value::Value; -use integer_encoding::{VarInt, VarIntWriter}; +use ciborium::value::{Integer, Value}; +use integer_encoding::VarIntWriter; use crate::data_contract::{DataContract, DriveContractExt}; use serde::{Deserialize, Serialize}; @@ -48,13 +47,15 @@ use crate::data_contract::document_type::document_type::PROTOCOL_VERSION; use crate::data_contract::document_type::DocumentType; use crate::data_contract::errors::{DataContractError, StructureError}; use crate::data_contract::extra::common::{ - bytes_for_system_value_from_tree_map, check_protocol_version, check_protocol_version_bytes, - get_key_from_cbor_map, reduced_value_string_representation, + bytes_for_system_value_from_tree_map, get_key_from_cbor_map, + reduced_value_string_representation, }; use crate::util::deserializer; use crate::util::deserializer::SplitProtocolVersionOutcome; use crate::ProtocolError; +use anyhow::{anyhow, bail}; + //todo: rename /// Documents contain the data that goes into data contracts. #[derive(Serialize, Deserialize, Clone, Debug, PartialEq)] @@ -384,6 +385,109 @@ impl DocumentStub { })?; self.get_raw_for_document_type(key, document_type, owner_id) } + + /// Temporary helper method to get property in u64 format + /// Imitating JsonValueExt trait + pub fn get_u64(&self, property_name: &str) -> Result { + let property_value = self.properties.get(property_name).ok_or_else(|| { + anyhow!( + "the property '{}' doesn't exist in '{:?}'", + property_name, + self + ) + })?; + + if let Value::Integer(s) = property_value { + return (*s) + .try_into() + .map_err(|_| anyhow!("unable convert {} to u64", property_name)); + } + bail!( + "getting property '{}' failed: {:?} isn't a number", + property_name, + property_value + ); + } + + /// Temporary helper method to get property in u32 format + /// Imitating JsonValueExt trait + pub fn get_u32(&self, property_name: &str) -> Result { + let property_value = self.properties.get(property_name).ok_or_else(|| { + anyhow!( + "the property '{}' doesn't exist in '{:?}'", + property_name, + self + ) + })?; + + if let Value::Integer(s) = property_value { + return (*s) + .try_into() + .map_err(|_| anyhow!("unable convert {} to u32", property_name)); + } + bail!( + "getting property '{}' failed: {:?} isn't a number", + property_name, + property_value + ); + } + + /// Temporary helper method to get property in bytes format + /// Imitating JsonValueExt trait + pub fn get_bytes(&self, property_name: &str) -> Result, anyhow::Error> { + let property_value = self.properties.get(property_name).ok_or_else(|| { + anyhow!( + "the property '{}' doesn't exist in '{:?}'", + property_name, + self + ) + })?; + + if let Value::Bytes(s) = property_value { + return Ok(s.clone()); + } + bail!( + "getting property '{}' failed: {:?} isn't an array of bytes", + property_name, + property_value + ); + } + + pub fn set_u8(&mut self, property_name: &str, value: u8) { + self.properties.insert( + property_name.to_string(), + Value::Integer(Integer::from(value)), + ); + } + + pub fn set_i64(&mut self, property_name: &str, value: i64) { + self.properties.insert( + property_name.to_string(), + Value::Integer(Integer::from(value)), + ); + } + + pub fn set_bytes(&mut self, property_name: &str, value: Vec) { + self.properties + .insert(property_name.to_string(), Value::Bytes(value)); + } + + pub fn increment_revision(&mut self) -> Result<(), anyhow::Error> { + let property_name = "$revision"; + + let revision = self.get_u32(property_name)?; + + let new_revision = revision + .checked_add(1) + .ok_or_else(|| anyhow!("could not increment revision: overflow occured"))?; + + self.properties.insert( + property_name.to_string(), + Value::Integer(Integer::from(new_revision)), + ); + + Ok(()) + } } impl fmt::Display for DocumentStub { diff --git a/packages/rs-drive-abci/Cargo.toml b/packages/rs-drive-abci/Cargo.toml index 59a0b43d154..0c1bdbce26f 100644 --- a/packages/rs-drive-abci/Cargo.toml +++ b/packages/rs-drive-abci/Cargo.toml @@ -11,7 +11,7 @@ ciborium = { git="https://github.com/qrayven/ciborium", branch="feat-ser-null-as chrono = "0.4.20" serde = { version = "1.0.132", features = ["derive"] } serde_json = { version="1.0", features=["preserve_order"] } -drive = { path = "../rs-drive", features = ["fixtures-and-mocks"]} +drive = { path = "../rs-drive", features = ["fixtures-and-mocks", "test-helpers"]} thiserror = "1.0.30" rand = "0.8.4" tempfile = "3" diff --git a/packages/rs-drive-abci/src/abci/handlers.rs b/packages/rs-drive-abci/src/abci/handlers.rs index aba13ff66cf..2fa0eace56e 100644 --- a/packages/rs-drive-abci/src/abci/handlers.rs +++ b/packages/rs-drive-abci/src/abci/handlers.rs @@ -209,7 +209,7 @@ mod tests { }; use dpp::util::hash; use drive::common::helpers::identities::create_test_masternode_identities; - use drive::common::helpers::setup::setup_document; + use drive::tests::helpers::setup::setup_document; use drive::drive::block_info::BlockInfo; use drive::drive::identity::withdrawals::paths::WithdrawalTransaction; use drive::fee::epoch::CreditsPerEpoch; diff --git a/packages/rs-drive-abci/src/identity_credit_withdrawal/mod.rs b/packages/rs-drive-abci/src/identity_credit_withdrawal/mod.rs index 7052d23e4ce..ad6a2b7dd1a 100644 --- a/packages/rs-drive-abci/src/identity_credit_withdrawal/mod.rs +++ b/packages/rs-drive-abci/src/identity_credit_withdrawal/mod.rs @@ -10,22 +10,19 @@ use dashcore::{ QuorumHash, Script, TxOut, }; use dpp::{ - contracts::withdrawals_contract, - data_contract::DriveContractExt, - identity::convert_credits_to_satoshi, - prelude::{Document, Identifier}, - util::{hash, json_value::JsonValueExt}, + contracts::withdrawals_contract, data_contract::DriveContractExt, + document::document_stub::DocumentStub, identity::convert_credits_to_satoshi, + prelude::Identifier, util::hash, }; use drive::{ drive::{ batch::DriveOperationType, block_info::BlockInfo, - document::convert_dpp_documents_to_drive_documents, identity::withdrawals::paths::WithdrawalTransaction, }, fee_pools::epochs::Epoch, query::TransactionArg, }; -use serde_json::{Number, Value as JsonValue}; +use serde_json::Value as JsonValue; use crate::{ block::BlockExecutionContext, @@ -78,7 +75,6 @@ impl Platform { for document in broadcasted_documents.iter_mut() { let transaction_sign_height = document - .get_data() .get_u64(withdrawals_contract::property_names::TRANSACTION_SIGN_HEIGHT) .map_err(|_| { Error::Execution(ExecutionError::CorruptedCodeExecution( @@ -87,7 +83,6 @@ impl Platform { })?; let transaction_id_bytes = document - .get_data() .get_bytes(withdrawals_contract::property_names::TRANSACTION_ID) .map_err(|_| { Error::Execution(ExecutionError::CorruptedCodeExecution( @@ -98,7 +93,6 @@ impl Platform { let transaction_id = hex::encode(transaction_id_bytes); let transaction_index = document - .get_data() .get_u64(withdrawals_contract::property_names::TRANSACTION_INDEX) .map_err(|_| { Error::Execution(ExecutionError::CorruptedCodeExecution( @@ -122,31 +116,27 @@ impl Platform { withdrawals_contract::Status::EXPIRED }; - document - .set( - withdrawals_contract::property_names::STATUS, - JsonValue::Number(Number::from(status as u8)), - ) - .map_err(|_| { + document.set_u8(withdrawals_contract::property_names::STATUS, status.into()); + + document.set_i64( + withdrawals_contract::property_names::UPDATED_AT, + block_info.time_ms.try_into().map_err(|_| { Error::Execution(ExecutionError::CorruptedCodeExecution( - "Can't update document field: status", + "Can't convert u64 block time to i64 updated_at", )) - })?; + })?, + ); - document.updated_at = Some(block_info.time_ms.try_into().map_err(|_| { + document.increment_revision().map_err(|_| { Error::Execution(ExecutionError::CorruptedCodeExecution( - "Can't convert u64 block time to i64 updated_at", + "Could not increment document revision", )) - })?); - document.increment_revision(); + })?; } } - let drive_documents = - convert_dpp_documents_to_drive_documents(broadcasted_documents.iter())?; - self.drive.add_update_multiple_documents_operations( - &drive_documents, + &broadcasted_documents, &contract_fetch_info.contract, contract_fetch_info .contract @@ -231,41 +221,42 @@ impl Platform { .drive .find_document_by_transaction_id(&original_transaction_id, transaction)?; - document - .set( - withdrawals_contract::property_names::TRANSACTION_ID, - JsonValue::Array( - update_transaction_id - .iter() - .map(|byte| JsonValue::Number(Number::from(*byte))) - .collect(), - ), - ) - .map_err(|_| { + document.set_bytes( + withdrawals_contract::property_names::TRANSACTION_ID, + update_transaction_id.clone(), + ); + + document.set_i64( + withdrawals_contract::property_names::UPDATED_AT, + block_info.time_ms.try_into().map_err(|_| { Error::Execution(ExecutionError::CorruptedCodeExecution( - "Can't set document field: transactionId", + "Can't convert u64 block time to i64 updated_at", )) - })?; + })?, + ); - document.updated_at = Some(block_info.time_ms.try_into().map_err(|_| { + document.increment_revision().map_err(|_| { Error::Execution(ExecutionError::CorruptedCodeExecution( - "Can't convert u64 block time to i64 updated_at", + "Could not increment document revision", )) - })?); - document.increment_revision(); + })?; Ok((bytes_buffer, document)) }) - .collect::, Document)>, Error>>()?; + .collect::, DocumentStub)>, Error>>()?; - let drive_documents = convert_dpp_documents_to_drive_documents( - transactions_and_documents - .iter() - .map(|(_, document)| document), - )?; + let withdrawals = transactions_and_documents + .iter() + .map(|(bytes, _)| bytes.clone()) + .collect(); + + let documents: Vec = transactions_and_documents + .into_iter() + .map(|(_, document)| document) + .collect(); self.drive.add_update_multiple_documents_operations( - &drive_documents, + &documents, &contract_fetch_info.contract, contract_fetch_info .contract @@ -283,10 +274,7 @@ impl Platform { .apply_drive_operations(drive_operations, true, &block_info, transaction)?; } - Ok(transactions_and_documents - .iter() - .map(|(bytes, _)| bytes.clone()) - .collect()) + Ok(withdrawals) } /// Pool withdrawal documents into transactions @@ -326,49 +314,39 @@ impl Platform { let mut drive_operations = vec![]; for document in documents.iter_mut() { + let document_id = Identifier::from_bytes(&document.id)?; + let transaction_id = - hash::hash(withdrawal_transactions.get(&document.id).unwrap().1.clone()); + hash::hash(withdrawal_transactions.get(&document_id).unwrap().1.clone()); - document - .set( - withdrawals_contract::property_names::TRANSACTION_ID, - JsonValue::Array( - transaction_id - .clone() - .into_iter() - .map(|byte| JsonValue::Number(Number::from(byte))) - .collect(), - ), - ) - .map_err(|_| { - Error::Execution(ExecutionError::CorruptedCodeExecution( - "Can't update document field: transactionId", - )) - })?; + document.set_bytes( + withdrawals_contract::property_names::TRANSACTION_ID, + transaction_id.clone(), + ); - document - .set( - withdrawals_contract::property_names::STATUS, - JsonValue::Number(Number::from(withdrawals_contract::Status::POOLED as u8)), - ) - .map_err(|_| { + document.set_u8( + withdrawals_contract::property_names::STATUS, + withdrawals_contract::Status::POOLED as u8, + ); + + document.set_i64( + withdrawals_contract::property_names::UPDATED_AT, + block_info.time_ms.try_into().map_err(|_| { Error::Execution(ExecutionError::CorruptedCodeExecution( - "Can't update document field: status", + "Can't convert u64 block time to i64 updated_at", )) - })?; + })?, + ); - document.updated_at = Some(block_info.time_ms.try_into().map_err(|_| { + document.increment_revision().map_err(|_| { Error::Execution(ExecutionError::CorruptedCodeExecution( - "Can't convert u64 block time to i64 updated_at", + "Could not increment document revision", )) - })?); - document.increment_revision(); + })?; } - let drive_documents = convert_dpp_documents_to_drive_documents(documents.iter())?; - self.drive.add_update_multiple_documents_operations( - &drive_documents, + &documents, &contract_fetch_info.contract, contract_fetch_info .contract @@ -444,7 +422,7 @@ impl Platform { /// Build list of Core transactions from withdrawal documents pub fn build_withdrawal_transactions_from_documents( &self, - documents: &[Document], + documents: &[DocumentStub], transaction: TransactionArg, ) -> Result, Error> { let mut withdrawals: HashMap = HashMap::new(); @@ -455,7 +433,6 @@ impl Platform { for (i, document) in documents.iter().enumerate() { let output_script = document - .get_data() .get_bytes(withdrawals_contract::property_names::OUTPUT_SCRIPT) .map_err(|_| { Error::Execution(ExecutionError::CorruptedCodeExecution( @@ -464,7 +441,6 @@ impl Platform { })?; let amount = document - .get_data() .get_u64(withdrawals_contract::property_names::AMOUNT) .map_err(|_| { Error::Execution(ExecutionError::CorruptedCodeExecution( @@ -473,7 +449,6 @@ impl Platform { })?; let core_fee_per_byte = document - .get_data() .get_u64(withdrawals_contract::property_names::CORE_FEE_PER_BYTE) .map_err(|_| { Error::Execution(ExecutionError::CorruptedCodeExecution( @@ -514,7 +489,7 @@ impl Platform { })?; withdrawals.insert( - document.id.clone(), + Identifier::from_bytes(&document.id)?, ( transaction_index.to_be_bytes().to_vec(), transaction_buffer.clone(), @@ -696,7 +671,10 @@ mod tests { .expect("to fetch documents by status"); assert_eq!(documents.len(), 1); - assert_eq!(documents.get(0).unwrap().id, document_2.id); + assert_eq!( + documents.get(0).unwrap().id.to_vec(), + document_2.id.to_vec() + ); let documents = platform .drive @@ -707,7 +685,10 @@ mod tests { .expect("to fetch documents by status"); assert_eq!(documents.len(), 1); - assert_eq!(documents.get(0).unwrap().id, document_1.id); + assert_eq!( + documents.get(0).unwrap().id.to_vec(), + document_1.id.to_vec() + ); } } @@ -802,17 +783,11 @@ mod tests { ]; for document in updated_documents { - assert_eq!(document.revision, 2); + assert_eq!(document.get_u32("$revision").expect("to get $revision"), 2); let tx_id: Vec = document - .data - .get("transactionId") - .unwrap() - .as_array() - .unwrap() - .iter() - .map(|byte| byte.as_u64().unwrap() as u8) - .collect(); + .get_bytes("transactionId") + .expect("to get transactionId"); let tx_id_hex = hex::encode(tx_id); @@ -887,7 +862,10 @@ mod tests { } mod build_withdrawal_transactions_from_documents { - use dpp::identity::state_transition::identity_credit_withdrawal_transition::Pooling; + use dpp::{ + document::document_stub::DocumentStub, + identity::state_transition::identity_credit_withdrawal_transition::Pooling, + }; use drive::drive::identity::withdrawals::paths::WithdrawalTransaction; use itertools::Itertools; @@ -941,7 +919,20 @@ mod tests { Some(&transaction), ); - let documents = vec![document_1, document_2]; + let documents = vec![ + DocumentStub::from_cbor( + &document_1.to_buffer().expect("to convert document to cbor"), + None, + None, + ) + .expect("to create document from cbor"), + DocumentStub::from_cbor( + &document_2.to_buffer().expect("to convert document to cbor"), + None, + None, + ) + .expect("to create document from cbor"), + ]; let transactions = platform .build_withdrawal_transactions_from_documents(&documents, Some(&transaction)) diff --git a/packages/rs-drive/Cargo.toml b/packages/rs-drive/Cargo.toml index 8f9be802b94..dd167783213 100644 --- a/packages/rs-drive/Cargo.toml +++ b/packages/rs-drive/Cargo.toml @@ -57,3 +57,4 @@ harness = false [features] fixtures-and-mocks = ["mockall"] +test-helpers = [] diff --git a/packages/rs-drive/src/drive/document/convert.rs b/packages/rs-drive/src/drive/document/convert.rs deleted file mode 100644 index e28d7c9c53c..00000000000 --- a/packages/rs-drive/src/drive/document/convert.rs +++ /dev/null @@ -1,30 +0,0 @@ -use dpp::{document::document_stub::DocumentStub, prelude::Document}; - -use crate::error::{drive::DriveError, Error}; - -/// Helper function to convert DPP documents to Drive documents -pub fn convert_dpp_documents_to_drive_documents<'a, I>( - dpp_documents: I, -) -> Result, Error> -where - I: Iterator, -{ - dpp_documents - .map(|document| { - DocumentStub::from_cbor( - &document.to_buffer().map_err(|_| { - Error::Drive(DriveError::CorruptedCodeExecution( - "Can't convert dpp document to CBOR", - )) - })?, - None, - None, - ) - .map_err(|_| { - Error::Drive(DriveError::CorruptedCodeExecution( - "Can't create drive document from CBOR", - )) - }) - }) - .collect::, Error>>() -} diff --git a/packages/rs-drive/src/drive/document/mod.rs b/packages/rs-drive/src/drive/document/mod.rs index 8b40aabcdda..41b795bd5c0 100644 --- a/packages/rs-drive/src/drive/document/mod.rs +++ b/packages/rs-drive/src/drive/document/mod.rs @@ -43,14 +43,11 @@ use grovedb::batch::KeyInfoPath; use grovedb::reference_path::ReferencePathType::UpstreamRootHeightReference; use grovedb::Element; -mod convert; mod delete; mod estimation_costs; mod insert; mod update; -pub use convert::*; - /// Returns the path to a contract document type. pub(crate) fn contract_document_type_path<'a>( contract_id: &'a [u8], diff --git a/packages/rs-drive/src/drive/identity/withdrawals/queue.rs b/packages/rs-drive/src/drive/identity/withdrawals/queue.rs index aaea60695ca..eb44031ddf7 100644 --- a/packages/rs-drive/src/drive/identity/withdrawals/queue.rs +++ b/packages/rs-drive/src/drive/identity/withdrawals/queue.rs @@ -86,7 +86,7 @@ impl Drive { Ok(withdrawals) } - /// Enqueue single withdrawal transaction + /// pub fn enqueue_withdrawal_transaction( &self, index: u64, @@ -94,7 +94,8 @@ impl Drive { block_info: &BlockInfo, transaction: TransactionArg, ) -> Result<(), Error> { - let mut drive_operation_types = vec![]; + let vec = vec![]; + let mut drive_operation_types = vec; let index_bytes = (index as u64).to_be_bytes().to_vec(); diff --git a/packages/rs-drive/src/drive/identity/withdrawals/withdrawal_status.rs b/packages/rs-drive/src/drive/identity/withdrawals/withdrawal_status.rs index 1e2bd52b1de..cf14dde7670 100644 --- a/packages/rs-drive/src/drive/identity/withdrawals/withdrawal_status.rs +++ b/packages/rs-drive/src/drive/identity/withdrawals/withdrawal_status.rs @@ -1,10 +1,13 @@ -use dpp::{contracts::withdrawals_contract, prelude::Document, util::serializer}; +use dpp::{ + contracts::withdrawals_contract, document::document_stub::DocumentStub, prelude::Document, + util::serializer, +}; use grovedb::TransactionArg; use serde_json::json; use crate::{ drive::Drive, - error::{drive::DriveError, Error}, query::DriveQuery, + error::{drive::DriveError, Error}, }; impl Drive { @@ -13,7 +16,7 @@ impl Drive { &self, status: u8, transaction: TransactionArg, - ) -> Result, Error> { + ) -> Result, Error> { let query_value = json!({ "where": [ [withdrawals_contract::property_names::OWNER_ID, "==", withdrawals_contract::OWNER_ID.clone()], @@ -24,8 +27,6 @@ impl Drive { ] }); - let dq = DriveQuery { contract: todo!(), document_type: todo!(), internal_clauses: todo!(), offset: todo!(), limit: todo!(), order_by: todo!(), start_at: todo!(), start_at_included: todo!(), block_time: todo!() }; - let query_cbor = serializer::value_to_cbor(query_value, None)?; let (documents, _, _) = self.query_raw_documents_using_cbor_encoded_query_with_cost( @@ -39,13 +40,13 @@ impl Drive { let documents = documents .into_iter() .map(|document_cbor| { - Document::from_buffer(document_cbor).map_err(|_| { + DocumentStub::from_cbor(&document_cbor, None, None).map_err(|_| { Error::Drive(DriveError::CorruptedCodeExecution( "Can't create a document from cbor", )) }) }) - .collect::, Error>>()?; + .collect::, Error>>()?; Ok(documents) } @@ -55,7 +56,7 @@ impl Drive { &self, original_transaction_id: &[u8], transaction: TransactionArg, - ) -> Result { + ) -> Result { let data_contract_id = withdrawals_contract::CONTRACT_ID.clone(); let query_value = json!({ @@ -78,13 +79,13 @@ impl Drive { let documents = documents .into_iter() .map(|document_cbor| { - Document::from_buffer(document_cbor).map_err(|_| { + DocumentStub::from_cbor(&document_cbor, None, None).map_err(|_| { Error::Drive(DriveError::CorruptedCodeExecution( "Can't create a document from cbor", )) }) }) - .collect::, Error>>()?; + .collect::, Error>>()?; let document = documents .get(0) @@ -215,7 +216,7 @@ mod tests { .find_document_by_transaction_id(&(0..32).collect::>(), Some(&transaction)) .expect("to find document by it's transaction id"); - assert_eq!(found_document.id, document.id); + // assert_eq!(found_document.id, document.id); } } } diff --git a/packages/rs-drive/src/lib.rs b/packages/rs-drive/src/lib.rs index d767ef67240..c3ff17eed83 100644 --- a/packages/rs-drive/src/lib.rs +++ b/packages/rs-drive/src/lib.rs @@ -32,5 +32,5 @@ pub use dpp; pub use grovedb; /// Test helpers -#[cfg(test)] +#[cfg(feature = "test-helpers")] pub mod tests; diff --git a/packages/rs-drive/src/tests/mod.rs b/packages/rs-drive/src/tests/mod.rs index 1630fabcd1b..99a2445f20b 100644 --- a/packages/rs-drive/src/tests/mod.rs +++ b/packages/rs-drive/src/tests/mod.rs @@ -1 +1,2 @@ +/// Everything related to test helpers pub mod helpers; From 74fa26b7119b565195eccb91a6aa775ba9dffd6e Mon Sep 17 00:00:00 2001 From: Djavid Gabibiyan Date: Mon, 6 Feb 2023 17:27:06 +0500 Subject: [PATCH 097/170] chore: remove unused method --- packages/rs-dpp/src/state_repository.rs | 7 -- packages/rs-drive-nodejs/src/lib.rs | 71 ------------------- .../src/drive/identity/withdrawals/queue.rs | 27 ------- packages/wasm-dpp/src/state_repository.rs | 8 --- 4 files changed, 113 deletions(-) diff --git a/packages/rs-dpp/src/state_repository.rs b/packages/rs-dpp/src/state_repository.rs index 9c7b531c29f..5850302f45c 100644 --- a/packages/rs-dpp/src/state_repository.rs +++ b/packages/rs-dpp/src/state_repository.rs @@ -171,11 +171,4 @@ pub trait StateRepositoryLike: Send + Sync { // Get latest (in a queue) withdrawal transaction index async fn fetch_latest_platform_core_chain_locked_height(&self) -> AnyResult>; - - // Enqueue withdrawal transaction - async fn enqueue_withdrawal_transaction( - &self, - index: u64, - transaction_bytes: Vec, - ) -> AnyResult<()>; } diff --git a/packages/rs-drive-nodejs/src/lib.rs b/packages/rs-drive-nodejs/src/lib.rs index 3c6d2175b80..c280ae23b91 100644 --- a/packages/rs-drive-nodejs/src/lib.rs +++ b/packages/rs-drive-nodejs/src/lib.rs @@ -2248,73 +2248,6 @@ impl PlatformWrapper { // The result is returned through the callback, not through direct return Ok(cx.undefined()) } - - fn js_enqueue_withdrawal_transaction(mut cx: FunctionContext) -> JsResult { - let js_index = cx.argument::(0)?; - let js_core_transaction = cx.argument::(1)?; - let js_block_info = cx.argument::(2)?; - let js_using_transaction = cx.argument::(3)?; - let js_callback = cx.argument::(4)?.root(&mut cx); - - let db = cx - .this() - .downcast_or_throw::, _>(&mut cx)?; - - let index = js_index.value(&mut cx); - let transaction_bytes = converter::js_buffer_to_vec_u8(js_core_transaction, &mut cx); - let using_transaction = js_using_transaction.value(&mut cx); - let block_info = converter::js_object_to_block_info(js_block_info, &mut cx)?; - - db.send_to_drive_thread(move |platform: &Platform, transaction, channel| { - let transaction_result = if using_transaction { - if transaction.is_none() { - Err("transaction is not started".to_string()) - } else { - Ok(transaction) - } - } else { - Ok(None) - }; - - let execution_function = |transaction: TransactionArg| -> Result<(), String> { - platform - .drive - .enqueue_withdrawal_transaction( - index as u64, - transaction_bytes, - &block_info, - transaction, - ) - .map_err(|e| e.to_string())?; - - Ok(()) - }; - - let result = transaction_result.and_then(execution_function); - - channel.send(move |mut task_context| { - let callback = js_callback.into_inner(&mut task_context); - let this = task_context.undefined(); - - let callback_arguments: Vec> = match result { - Ok(_) => { - vec![task_context.null().upcast(), task_context.null().upcast()] - } - - // Convert the error to a JavaScript exception on failure - Err(err) => vec![task_context.error(err)?.upcast()], - }; - - callback.call(&mut task_context, this, callback_arguments)?; - - Ok(()) - }); - }) - .or_else(|err| cx.throw_error(err.to_string()))?; - - // The result is returned through the callback, not through direct return - Ok(cx.undefined()) - } } #[neon::main] @@ -2346,10 +2279,6 @@ fn main(mut cx: ModuleContext) -> NeonResult<()> { "driveFetchLatestWithdrawalTransactionIndex", PlatformWrapper::js_fetch_latest_withdrawal_transaction_index, )?; - cx.export_function( - "driveEnqueueWithdrawalTransaction", - PlatformWrapper::js_enqueue_withdrawal_transaction, - )?; cx.export_function("groveDbInsert", PlatformWrapper::js_grove_db_insert)?; cx.export_function( diff --git a/packages/rs-drive/src/drive/identity/withdrawals/queue.rs b/packages/rs-drive/src/drive/identity/withdrawals/queue.rs index eb44031ddf7..1869aefe069 100644 --- a/packages/rs-drive/src/drive/identity/withdrawals/queue.rs +++ b/packages/rs-drive/src/drive/identity/withdrawals/queue.rs @@ -85,33 +85,6 @@ impl Drive { Ok(withdrawals) } - - /// - pub fn enqueue_withdrawal_transaction( - &self, - index: u64, - transaction_bytes: Vec, - block_info: &BlockInfo, - transaction: TransactionArg, - ) -> Result<(), Error> { - let vec = vec![]; - let mut drive_operation_types = vec; - - let index_bytes = (index as u64).to_be_bytes().to_vec(); - - let withdrawals = vec![(index_bytes, transaction_bytes)]; - - self.add_enqueue_withdrawal_transaction_operations( - &withdrawals, - &mut drive_operation_types, - ); - - self.add_update_withdrawal_index_counter_operation(index, &mut drive_operation_types); - - self.apply_drive_operations(drive_operation_types, true, &block_info, transaction)?; - - Ok(()) - } } #[cfg(test)] diff --git a/packages/wasm-dpp/src/state_repository.rs b/packages/wasm-dpp/src/state_repository.rs index 8381ff272e4..f1b96ce5b5a 100644 --- a/packages/wasm-dpp/src/state_repository.rs +++ b/packages/wasm-dpp/src/state_repository.rs @@ -359,12 +359,4 @@ impl StateRepositoryLike for ExternalStateRepositoryLikeWrapper { async fn fetch_latest_withdrawal_transaction_index(&self) -> anyhow::Result { todo!() } - - async fn enqueue_withdrawal_transaction( - &self, - _index: u64, - _transaction_bytes: Vec, - ) -> anyhow::Result<()> { - todo!() - } } From 84f0124a3071f836d417eeb296a44814454ecea3 Mon Sep 17 00:00:00 2001 From: Djavid Gabibiyan Date: Mon, 6 Feb 2023 17:27:32 +0500 Subject: [PATCH 098/170] chore: imports --- packages/rs-drive/src/drive/identity/withdrawals/queue.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/rs-drive/src/drive/identity/withdrawals/queue.rs b/packages/rs-drive/src/drive/identity/withdrawals/queue.rs index 1869aefe069..678047a412d 100644 --- a/packages/rs-drive/src/drive/identity/withdrawals/queue.rs +++ b/packages/rs-drive/src/drive/identity/withdrawals/queue.rs @@ -8,7 +8,6 @@ use grovedb::{ use crate::{ drive::{ batch::{drive_op_batch::WithdrawalOperationType, DriveOperationType}, - block_info::BlockInfo, Drive, }, error::{drive::DriveError, Error}, From 060764e81e990ca8bfe05eedc59986ca09bdbe32 Mon Sep 17 00:00:00 2001 From: Djavid Gabibiyan Date: Mon, 6 Feb 2023 17:38:18 +0500 Subject: [PATCH 099/170] chore: test fix --- packages/rs-drive/src/drive/identity/withdrawals/queue.rs | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/packages/rs-drive/src/drive/identity/withdrawals/queue.rs b/packages/rs-drive/src/drive/identity/withdrawals/queue.rs index 678047a412d..d186ff47e8b 100644 --- a/packages/rs-drive/src/drive/identity/withdrawals/queue.rs +++ b/packages/rs-drive/src/drive/identity/withdrawals/queue.rs @@ -144,14 +144,10 @@ mod tests { let mut drive_operations: Vec = vec![]; - let withdrawals = drive + drive .dequeue_withdrawal_transactions(16, Some(&transaction), &mut drive_operations) .expect("to dequeue withdrawals"); - drive - .apply_drive_operations(drive_operations, true, &block_info, Some(&transaction)) - .expect("to apply batch"); - - assert_eq!(withdrawals.len(), 0); + assert_eq!(drive_operations.len(), 0); } } From b5b81e6f8f45597439d6d29043e31f6b91800b79 Mon Sep 17 00:00:00 2001 From: Djavid Gabibiyan Date: Mon, 6 Feb 2023 17:39:23 +0500 Subject: [PATCH 100/170] chore: fmt --- packages/rs-drive-abci/src/abci/handlers.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/rs-drive-abci/src/abci/handlers.rs b/packages/rs-drive-abci/src/abci/handlers.rs index 2fa0eace56e..5a29c5f2ac9 100644 --- a/packages/rs-drive-abci/src/abci/handlers.rs +++ b/packages/rs-drive-abci/src/abci/handlers.rs @@ -209,12 +209,12 @@ mod tests { }; use dpp::util::hash; use drive::common::helpers::identities::create_test_masternode_identities; - use drive::tests::helpers::setup::setup_document; use drive::drive::block_info::BlockInfo; use drive::drive::identity::withdrawals::paths::WithdrawalTransaction; use drive::fee::epoch::CreditsPerEpoch; use drive::fee_pools::epochs::Epoch; use drive::rpc::core::MockCoreRPCLike; + use drive::tests::helpers::setup::setup_document; use rust_decimal::prelude::ToPrimitive; use serde_json::json; use std::ops::Div; From 568b3bdb76e84868eaec6889eb3ed4f93e6b1d62 Mon Sep 17 00:00:00 2001 From: Djavid Gabibiyan Date: Mon, 6 Feb 2023 17:56:48 +0500 Subject: [PATCH 101/170] chore: tests fixes --- packages/rs-drive-nodejs/Drive.js | 23 ------------------- packages/rs-drive-nodejs/test/Drive.spec.js | 14 ----------- .../identity/withdrawals/withdrawal_status.rs | 4 ++-- 3 files changed, 2 insertions(+), 39 deletions(-) diff --git a/packages/rs-drive-nodejs/Drive.js b/packages/rs-drive-nodejs/Drive.js index c9ee35938a2..06533bff506 100644 --- a/packages/rs-drive-nodejs/Drive.js +++ b/packages/rs-drive-nodejs/Drive.js @@ -20,7 +20,6 @@ const { driveProveDocumentsQuery, driveInsertIdentity, driveFetchLatestWithdrawalTransactionIndex, - driveEnqueueWithdrawalTransaction, abciInitChain, abciBlockBegin, abciBlockEnd, @@ -53,9 +52,6 @@ const driveProveDocumentsQueryAsync = appendStackAsync(promisify(driveProveDocum const driveFetchLatestWithdrawalTransactionIndexAsync = appendStackAsync( promisify(driveFetchLatestWithdrawalTransactionIndex), ); -const driveEnqueueWithdrawalTransactionAsync = appendStackAsync( - promisify(driveEnqueueWithdrawalTransaction), -); const driveInsertIdentityAsync = appendStackAsync(promisify(driveInsertIdentity)); const abciInitChainAsync = appendStackAsync(promisify(abciInitChain)); const abciBlockBeginAsync = appendStackAsync(promisify(abciBlockBegin)); @@ -352,25 +348,6 @@ class Drive { ); } - /** - * Enqueue withdrawal transaction into the queue - * - * @param {number} index - * @param {Buffer} transactionBytes - * @param {boolean} [useTransaction=false] - * - * @returns {Promise} - */ - async enqueueWithdrawalTransaction(index, transactionBytes, blockInfo, useTransaction = false) { - return driveEnqueueWithdrawalTransactionAsync.call( - this.drive, - index, - transactionBytes, - blockInfo, - useTransaction, - ); - } - /** * Get the ABCI interface * @returns {RSAbci} diff --git a/packages/rs-drive-nodejs/test/Drive.spec.js b/packages/rs-drive-nodejs/test/Drive.spec.js index 61cae04273d..b331f44354b 100644 --- a/packages/rs-drive-nodejs/test/Drive.spec.js +++ b/packages/rs-drive-nodejs/test/Drive.spec.js @@ -511,20 +511,6 @@ describe('Drive', function main() { }); }); - describe('#enqueueWithdrawalTransaction', () => { - beforeEach(async () => { - await drive.createInitialStateStructure(); - }); - - it('should enqueue withdrawal transaction into the queue', async () => { - await drive.enqueueWithdrawalTransaction(1, Buffer.alloc(32, 1), blockInfo); - - const result = await drive.fetchLatestWithdrawalTransactionIndex(); - - expect(result).to.equal(1); - }); - }); - describe('ABCI', () => { describe('InitChain', () => { it('should successfully init chain', async () => { diff --git a/packages/rs-drive/src/drive/identity/withdrawals/withdrawal_status.rs b/packages/rs-drive/src/drive/identity/withdrawals/withdrawal_status.rs index cf14dde7670..bae727509c1 100644 --- a/packages/rs-drive/src/drive/identity/withdrawals/withdrawal_status.rs +++ b/packages/rs-drive/src/drive/identity/withdrawals/withdrawal_status.rs @@ -1,5 +1,5 @@ use dpp::{ - contracts::withdrawals_contract, document::document_stub::DocumentStub, prelude::Document, + contracts::withdrawals_contract, document::document_stub::DocumentStub, util::serializer, }; use grovedb::TransactionArg; @@ -216,7 +216,7 @@ mod tests { .find_document_by_transaction_id(&(0..32).collect::>(), Some(&transaction)) .expect("to find document by it's transaction id"); - // assert_eq!(found_document.id, document.id); + assert_eq!(found_document.id.to_vec(), document.id.to_vec()); } } } From 9fd0e7d93ac3abdeb1f42bc1cc406e59ccbda523 Mon Sep 17 00:00:00 2001 From: Djavid Gabibiyan Date: Mon, 6 Feb 2023 18:51:21 +0500 Subject: [PATCH 102/170] chore: use `DriveQuery` --- .../identity/withdrawals/withdrawal_status.rs | 186 ++++++++++++------ 1 file changed, 126 insertions(+), 60 deletions(-) diff --git a/packages/rs-drive/src/drive/identity/withdrawals/withdrawal_status.rs b/packages/rs-drive/src/drive/identity/withdrawals/withdrawal_status.rs index bae727509c1..0a2e2464343 100644 --- a/packages/rs-drive/src/drive/identity/withdrawals/withdrawal_status.rs +++ b/packages/rs-drive/src/drive/identity/withdrawals/withdrawal_status.rs @@ -1,13 +1,16 @@ +use std::collections::BTreeMap; + use dpp::{ - contracts::withdrawals_contract, document::document_stub::DocumentStub, - util::serializer, + contracts::withdrawals_contract, data_contract::DriveContractExt, + document::document_stub::DocumentStub, }; use grovedb::TransactionArg; -use serde_json::json; +use indexmap::IndexMap; use crate::{ drive::Drive, error::{drive::DriveError, Error}, + query::{DriveQuery, InternalClauses, OrderClause, WhereClause}, }; impl Drive { @@ -17,36 +20,72 @@ impl Drive { status: u8, transaction: TransactionArg, ) -> Result, Error> { - let query_value = json!({ - "where": [ - [withdrawals_contract::property_names::OWNER_ID, "==", withdrawals_contract::OWNER_ID.clone()], - [withdrawals_contract::property_names::STATUS, "==", status], - ], - "orderBy": [ - [withdrawals_contract::property_names::CREATE_AT, "desc"], - ] - }); - - let query_cbor = serializer::value_to_cbor(query_value, None)?; - - let (documents, _, _) = self.query_raw_documents_using_cbor_encoded_query_with_cost( - &query_cbor, - withdrawals_contract::CONTRACT_ID.clone().to_buffer(), - withdrawals_contract::types::WITHDRAWAL, - None, - transaction, - )?; - - let documents = documents - .into_iter() - .map(|document_cbor| { - DocumentStub::from_cbor(&document_cbor, None, None).map_err(|_| { - Error::Drive(DriveError::CorruptedCodeExecution( - "Can't create a document from cbor", - )) - }) - }) - .collect::, Error>>()?; + let data_contract_id = withdrawals_contract::CONTRACT_ID.clone(); + + let contract_fetch_info = self + .fetch_contract(data_contract_id.to_buffer(), None, transaction) + .unwrap()? + .ok_or_else(|| { + Error::Drive(DriveError::CorruptedCodeExecution( + "Can't fetch data contract", + )) + })?; + + let document_type = contract_fetch_info + .contract + .document_type_for_name(withdrawals_contract::types::WITHDRAWAL)?; + + let mut where_clauses = BTreeMap::new(); + + where_clauses.insert( + withdrawals_contract::property_names::OWNER_ID.to_string(), + WhereClause { + field: withdrawals_contract::property_names::OWNER_ID.to_string(), + operator: crate::query::WhereOperator::Equal, + value: ciborium::Value::Bytes( + withdrawals_contract::OWNER_ID.clone().to_buffer().to_vec(), + ), + }, + ); + + where_clauses.insert( + withdrawals_contract::property_names::STATUS.to_string(), + WhereClause { + field: withdrawals_contract::property_names::STATUS.to_string(), + operator: crate::query::WhereOperator::Equal, + value: ciborium::Value::Integer(status.into()), + }, + ); + + let mut order_by = IndexMap::new(); + + order_by.insert( + withdrawals_contract::property_names::CREATE_AT.to_string(), + OrderClause { + field: withdrawals_contract::property_names::CREATE_AT.to_string(), + ascending: false, + }, + ); + + let drive_query = DriveQuery { + contract: &contract_fetch_info.contract, + document_type: document_type, + internal_clauses: InternalClauses { + primary_key_in_clause: None, + primary_key_equal_clause: None, + in_clause: None, + range_clause: None, + equal_clauses: where_clauses, + }, + offset: 0, + limit: 100, + order_by, + start_at: None, + start_at_included: false, + block_time: None, + }; + + let (documents, _) = self.query_documents(drive_query, transaction, &mut vec![])?; Ok(documents) } @@ -59,33 +98,60 @@ impl Drive { ) -> Result { let data_contract_id = withdrawals_contract::CONTRACT_ID.clone(); - let query_value = json!({ - "where": [ - [withdrawals_contract::property_names::TRANSACTION_ID, "==", original_transaction_id], - [withdrawals_contract::property_names::STATUS, "==", withdrawals_contract::Status::POOLED], - ], - }); - - let query_cbor = serializer::value_to_cbor(query_value, None)?; - - let (documents, _, _) = self.query_raw_documents_using_cbor_encoded_query_with_cost( - &query_cbor, - data_contract_id.to_buffer(), - withdrawals_contract::types::WITHDRAWAL, - None, - transaction, - )?; - - let documents = documents - .into_iter() - .map(|document_cbor| { - DocumentStub::from_cbor(&document_cbor, None, None).map_err(|_| { - Error::Drive(DriveError::CorruptedCodeExecution( - "Can't create a document from cbor", - )) - }) - }) - .collect::, Error>>()?; + let contract_fetch_info = self + .fetch_contract(data_contract_id.to_buffer(), None, transaction) + .unwrap()? + .ok_or_else(|| { + Error::Drive(DriveError::CorruptedCodeExecution( + "Can't fetch data contract", + )) + })?; + + let document_type = contract_fetch_info + .contract + .document_type_for_name(withdrawals_contract::types::WITHDRAWAL)?; + + let mut where_clauses = BTreeMap::new(); + + where_clauses.insert( + withdrawals_contract::property_names::TRANSACTION_ID.to_string(), + WhereClause { + field: withdrawals_contract::property_names::TRANSACTION_ID.to_string(), + operator: crate::query::WhereOperator::Equal, + value: ciborium::Value::Bytes(original_transaction_id.to_vec()), + }, + ); + + where_clauses.insert( + withdrawals_contract::property_names::STATUS.to_string(), + WhereClause { + field: withdrawals_contract::property_names::STATUS.to_string(), + operator: crate::query::WhereOperator::Equal, + value: ciborium::Value::Integer( + (withdrawals_contract::Status::POOLED as u8).into(), + ), + }, + ); + + let drive_query = DriveQuery { + contract: &contract_fetch_info.contract, + document_type: document_type, + internal_clauses: InternalClauses { + primary_key_in_clause: None, + primary_key_equal_clause: None, + in_clause: None, + range_clause: None, + equal_clauses: where_clauses, + }, + offset: 0, + limit: 100, + order_by: IndexMap::new(), + start_at: None, + start_at_included: false, + block_time: None, + }; + + let (documents, _) = self.query_documents(drive_query, transaction, &mut vec![])?; let document = documents .get(0) From 2f4e8e0c41cd4180b310774dee26555784ce9889 Mon Sep 17 00:00:00 2001 From: Djavid Gabibiyan Date: Mon, 6 Feb 2023 22:34:50 +0500 Subject: [PATCH 103/170] chore: merge fixes --- ...lidate_documents_batch_transition_state.rs | 4 +-- ...ty_credit_withdrawal_transition_factory.rs | 28 +++++++++---------- packages/rs-drive/src/rpc/core.rs | 4 +-- 3 files changed, 17 insertions(+), 19 deletions(-) diff --git a/packages/rs-dpp/src/document/state_transition/documents_batch_transition/validation/state/validate_documents_batch_transition_state.rs b/packages/rs-dpp/src/document/state_transition/documents_batch_transition/validation/state/validate_documents_batch_transition_state.rs index 989f479e4af..baf2ae669e7 100644 --- a/packages/rs-dpp/src/document/state_transition/documents_batch_transition/validation/state/validate_documents_batch_transition_state.rs +++ b/packages/rs-dpp/src/document/state_transition/documents_batch_transition/validation/state/validate_documents_batch_transition_state.rs @@ -13,7 +13,7 @@ use crate::{ document_transition::{Action, DocumentTransition, DocumentTransitionExt}, Document, DocumentsBatchTransition, }, - prelude::{Identifier, TimestampMillis}, + prelude::{Identifier, Revision, TimestampMillis}, state_repository::StateRepositoryLike, state_transition::{ state_transition_execution_context::StateTransitionExecutionContext, @@ -258,7 +258,7 @@ fn check_revision( result.add_error(ConsensusError::StateError(Box::new( StateError::InvalidDocumentRevisionError { document_id: document_transition.base().id, - current_revision: fetched_document.revision, + current_revision: fetched_document.revision as Revision, }, ))) } diff --git a/packages/rs-dpp/src/identity/state_transition/identity_credit_withdrawal_transition/apply_identity_credit_withdrawal_transition_factory.rs b/packages/rs-dpp/src/identity/state_transition/identity_credit_withdrawal_transition/apply_identity_credit_withdrawal_transition_factory.rs index 0341b33cc8d..6c7d3921fd9 100644 --- a/packages/rs-dpp/src/identity/state_transition/identity_credit_withdrawal_transition/apply_identity_credit_withdrawal_transition_factory.rs +++ b/packages/rs-dpp/src/identity/state_transition/identity_credit_withdrawal_transition/apply_identity_credit_withdrawal_transition_factory.rs @@ -1,17 +1,14 @@ use anyhow::{anyhow, Result}; +use dashcore::{consensus, BlockHeader}; use std::convert::TryInto; -use serde_json::{json, Value as JsonValue}; +use serde_json::json; use crate::{ - contracts::withdrawals_contract, - data_contract::DataContract, - document::generate_document_id, - document::Document, - identity::state_transition::identity_credit_withdrawal_transition::Pooling, - state_repository::StateRepositoryLike, - state_transition::StateTransitionLike, - util::{entropy_generator::generate, json_value::JsonValueExt}, + contracts::withdrawals_contract, data_contract::DataContract, document::generate_document_id, + document::Document, identity::state_transition::identity_credit_withdrawal_transition::Pooling, + state_repository::StateRepositoryLike, state_transition::StateTransitionLike, + util::entropy_generator::generate, }; use super::{ @@ -55,17 +52,18 @@ where let withdrawals_data_contract = maybe_withdrawals_data_contract .ok_or_else(|| anyhow!("Withdrawals data contract not found"))?; - let latest_platform_block_header: JsonValue = self + let latest_platform_block_header_bytes: Vec = self .state_repository .fetch_latest_platform_block_header() .await?; + let latest_platform_block_header: BlockHeader = + consensus::deserialize(&latest_platform_block_header_bytes)?; + let document_type = String::from(withdrawals_contract::types::WITHDRAWAL); - let document_created_at_millis = latest_platform_block_header - .get(PLATFORM_BLOCK_HEADER_TIME_PROPERTY) - .ok_or_else(|| anyhow!("time property is not set in block header"))? - .get_i64(PLATFORM_BLOCK_HEADER_TIME_SECONDS_PROPERTY)? - * 1000; + let document_created_at_millis: i64 = (latest_platform_block_header.time * 1000) + .try_into() + .map_err(|_| anyhow!("Can't convert block header time from u32 to i64"))?; let document_data = json!({ withdrawals_contract::property_names::AMOUNT: state_transition.amount, diff --git a/packages/rs-drive/src/rpc/core.rs b/packages/rs-drive/src/rpc/core.rs index 6be8bf436c0..0b0d7f20e3e 100644 --- a/packages/rs-drive/src/rpc/core.rs +++ b/packages/rs-drive/src/rpc/core.rs @@ -24,9 +24,9 @@ pub struct DefaultCoreRPC { impl DefaultCoreRPC { /// Create new instance - pub fn open(url: String, username: String, password: String) -> Result { + pub fn open(url: &str, username: String, password: String) -> Result { Ok(DefaultCoreRPC { - inner: Client::new(url.as_str(), Auth::UserPass(username, password))?, + inner: Client::new(url, Auth::UserPass(username, password))?, }) } } From 1061a18992b78e22dfa8026e016feb77604ad68c Mon Sep 17 00:00:00 2001 From: Djavid Gabibiyan Date: Mon, 6 Feb 2023 23:19:46 +0500 Subject: [PATCH 104/170] chore(wip): fixing merge --- packages/rs-drive-abci/src/abci/handlers.rs | 9 +- packages/rs-drive-abci/src/config.rs | 2 + .../execution/fee_pools/process_block_fees.rs | 2 +- .../src/identity_credit_withdrawal/mod.rs | 23 +- packages/rs-drive-abci/src/platform.rs | 5 +- .../src/drive/batch/drive_op_batch/mod.rs | 685 +----------------- .../drive/batch/drive_op_batch/withdrawals.rs | 151 ++++ .../src/drive/identity/balance/prove.rs | 3 +- .../src/drive/identity/balance/update.rs | 8 +- .../fetch/fetch_by_public_key_hashes.rs | 2 +- .../src/drive/identity/fetch/full_identity.rs | 2 +- .../full_identities_by_public_key_hashes.rs | 2 +- .../identity/fetch/prove/full_identity.rs | 2 +- .../identity_ids_by_public_key_hashes.rs | 2 +- .../rs-drive/src/drive/identity/insert.rs | 3 +- packages/rs-drive/src/drive/identity/mod.rs | 2 +- .../rs-drive/src/drive/identity/update.rs | 2 +- .../identity/withdrawals/withdrawal_status.rs | 36 +- 18 files changed, 230 insertions(+), 711 deletions(-) create mode 100644 packages/rs-drive/src/drive/batch/drive_op_batch/withdrawals.rs diff --git a/packages/rs-drive-abci/src/abci/handlers.rs b/packages/rs-drive-abci/src/abci/handlers.rs index 71298b17a88..1b5298b1aa8 100644 --- a/packages/rs-drive-abci/src/abci/handlers.rs +++ b/packages/rs-drive-abci/src/abci/handlers.rs @@ -199,6 +199,7 @@ mod tests { mod handlers { use crate::abci::handlers::TenderdashAbci; use crate::common::helpers::fee_pools::create_test_masternode_share_identities_and_documents; + use crate::config::PlatformConfig; use chrono::{Duration, Utc}; use dashcore::hashes::hex::FromHex; use dashcore::BlockHash; @@ -224,15 +225,13 @@ mod tests { AfterFinalizeBlockRequest, BlockBeginRequest, BlockEndRequest, BlockFees, InitChainRequest, }; - use crate::common::helpers::setup::{ - setup_platform, setup_platform_raw, setup_system_data_contract, - }; + use crate::common::helpers::setup::{setup_platform_raw, setup_system_data_contract}; #[test] fn test_abci_flow() { let mut platform = setup_platform_raw(Some(PlatformConfig { - drive_config: Default::default(), verify_sum_trees: false, + ..Default::default() })); let mut core_rpc_mock = MockCoreRPCLike::new(); @@ -503,8 +502,8 @@ mod tests { // TODO refactor to remove code duplication let mut platform = setup_platform_raw(Some(PlatformConfig { - drive_config: Default::default(), verify_sum_trees: false, + ..Default::default() })); let mut core_rpc_mock = MockCoreRPCLike::new(); diff --git a/packages/rs-drive-abci/src/config.rs b/packages/rs-drive-abci/src/config.rs index 98f54c3a8ac..bd4111af9a9 100644 --- a/packages/rs-drive-abci/src/config.rs +++ b/packages/rs-drive-abci/src/config.rs @@ -1,6 +1,7 @@ use drive::drive::config::DriveConfig; /// Configuration for Dash Core RPC client +#[derive(Clone, Debug)] pub struct CoreRpcConfig { /// Core RPC client url pub url: String, @@ -13,6 +14,7 @@ pub struct CoreRpcConfig { } /// Configuration for Dash Core related things +#[derive(Clone, Debug)] pub struct CoreConfig { /// Core RPC config pub rpc: CoreRpcConfig, diff --git a/packages/rs-drive-abci/src/execution/fee_pools/process_block_fees.rs b/packages/rs-drive-abci/src/execution/fee_pools/process_block_fees.rs index 6922bc38517..a6476d194ad 100644 --- a/packages/rs-drive-abci/src/execution/fee_pools/process_block_fees.rs +++ b/packages/rs-drive-abci/src/execution/fee_pools/process_block_fees.rs @@ -558,8 +558,8 @@ mod tests { // We are not adding to the overall platform credits so we can't verify // the sum trees let platform = setup_platform_with_initial_state_structure(Some(PlatformConfig { - drive_config: Default::default(), verify_sum_trees: false, + ..Default::default() })); let transaction = platform.drive.grove.start_transaction(); diff --git a/packages/rs-drive-abci/src/identity_credit_withdrawal/mod.rs b/packages/rs-drive-abci/src/identity_credit_withdrawal/mod.rs index ad6a2b7dd1a..79ddc8341c2 100644 --- a/packages/rs-drive-abci/src/identity_credit_withdrawal/mod.rs +++ b/packages/rs-drive-abci/src/identity_credit_withdrawal/mod.rs @@ -514,24 +514,23 @@ mod tests { use drive::{rpc::core::MockCoreRPCLike, tests::helpers::setup::setup_document}; use serde_json::json; + use crate::common::helpers::setup::setup_platform_with_initial_state_structure; use crate::common::helpers::setup::setup_system_data_contract; - use crate::common::helpers::setup::setup_platform_with_initial_state_structure; use dpp::identity::state_transition::identity_credit_withdrawal_transition::Pooling; - use crate::{ - block::{BlockExecutionContext, BlockInfo}, - execution::fee_pools::epoch::EpochInfo, - }; + use crate::{block::BlockExecutionContext, execution::fee_pools::epoch::EpochInfo}; mod update_withdrawal_statuses { use dpp::prelude::DataContract; + use crate::block::BlockStateInfo; + use super::*; #[test] fn test_statuses_are_updated() { - let mut platform = setup_platform_with_initial_state_structure(); + let mut platform = setup_platform_with_initial_state_structure(None); let mut mock_rpc_client = MockCoreRPCLike::new(); @@ -642,7 +641,7 @@ mod tests { .update_broadcasted_withdrawal_transaction_statuses( 95, &BlockExecutionContext { - block_info: BlockInfo { + block_info: BlockStateInfo { block_height: 1, block_time_ms: 1, previous_block_time_ms: Some(1), @@ -696,11 +695,13 @@ mod tests { use dpp::identity::state_transition::identity_credit_withdrawal_transition::Pooling; + use crate::block::BlockStateInfo; + use super::*; #[test] fn test_pooling() { - let platform = setup_platform_with_initial_state_structure(); + let platform = setup_platform_with_initial_state_structure(None); let transaction = platform.drive.grove.start_transaction(); @@ -749,7 +750,7 @@ mod tests { platform .pool_withdrawals_into_transactions_queue( &BlockExecutionContext { - block_info: BlockInfo { + block_info: BlockStateInfo { block_height: 1, block_time_ms: 1, previous_block_time_ms: Some(1), @@ -802,7 +803,7 @@ mod tests { #[test] fn test_fetches_core_transactions() { - let mut platform = setup_platform_with_initial_state_structure(); + let mut platform = setup_platform_with_initial_state_structure(None); let mut mock_rpc_client = MockCoreRPCLike::new(); @@ -873,7 +874,7 @@ mod tests { #[test] fn test_build() { - let platform = setup_platform_with_initial_state_structure(); + let platform = setup_platform_with_initial_state_structure(None); let transaction = platform.drive.grove.start_transaction(); diff --git a/packages/rs-drive-abci/src/platform.rs b/packages/rs-drive-abci/src/platform.rs index db162180de8..4e95f9268fb 100644 --- a/packages/rs-drive-abci/src/platform.rs +++ b/packages/rs-drive-abci/src/platform.rs @@ -38,8 +38,6 @@ use crate::state::PlatformState; use drive::drive::Drive; use drive::rpc::core::{CoreRPCLike, DefaultCoreRPC}; -use drive::drive::Drive; - use std::cell::RefCell; use std::path::Path; @@ -76,7 +74,8 @@ impl Platform { /// Open Platform with Drive and block execution context. pub fn open>(path: P, config: Option) -> Result { let config = config.unwrap_or_default(); - let drive = Drive::open(path, Some(config.drive_config.clone())).map_err(Error::Drive)?; + + let drive = Drive::open(path, config.drive).map_err(Error::Drive)?; let core_rpc: Box = Box::new( DefaultCoreRPC::open( diff --git a/packages/rs-drive/src/drive/batch/drive_op_batch/mod.rs b/packages/rs-drive/src/drive/batch/drive_op_batch/mod.rs index 7457c1ebf73..52b36b41007 100644 --- a/packages/rs-drive/src/drive/batch/drive_op_batch/mod.rs +++ b/packages/rs-drive/src/drive/batch/drive_op_batch/mod.rs @@ -31,40 +31,30 @@ mod contract; mod document; mod identity; mod system; +mod withdrawals; use crate::drive::batch::GroveDbOpBatch; use crate::drive::block_info::BlockInfo; -use crate::drive::flags::StorageFlags; -use crate::drive::grove_operations::BatchDeleteApplyType; -use crate::drive::identity::withdrawals::paths::{ - get_withdrawal_root_path_vec, get_withdrawal_transactions_expired_ids_path, - get_withdrawal_transactions_expired_ids_path_vec, get_withdrawal_transactions_queue_path, - get_withdrawal_transactions_queue_path_vec, WithdrawalTransaction, - WITHDRAWAL_TRANSACTIONS_COUNTER_ID, -}; -use crate::drive::object_size_info::DocumentInfo::{ - DocumentRefAndSerialization, DocumentRefWithoutSerialization, -}; -use crate::drive::object_size_info::{DocumentAndContractInfo, OwnedDocumentInfo}; use crate::drive::Drive; use crate::error::Error; use crate::fee::calculate_fee; use crate::fee::op::DriveOperation; use crate::fee::result::FeeResult; + pub use contract::ContractOperationType; +pub use document::DocumentOperation; pub use document::DocumentOperationType; -use dpp::data_contract::document_type::DocumentType; -use dpp::data_contract::DriveContractExt; -use dpp::document::document_stub::DocumentStub; -use grovedb::batch::KeyInfoPath; -use grovedb::{Element, EstimatedLayerInformation, TransactionArg}; +pub use document::DocumentOperationsForContractDocumentType; +pub use document::UpdateOperationInfo; +pub use identity::IdentityOperationType; +pub use system::SystemOperationType; +pub use withdrawals::WithdrawalOperationType; -use grovedb::batch::{GroveDbOp, KeyInfoPath}; use grovedb::{EstimatedLayerInformation, TransactionArg}; -pub use identity::IdentityOperationType; + +use grovedb::batch::{GroveDbOp, KeyInfoPath}; use itertools::Itertools; use std::collections::HashMap; -pub use system::SystemOperationType; /// A converter that will get Drive Operations from High Level Operations pub trait DriveOperationConverter { @@ -80,661 +70,6 @@ pub trait DriveOperationConverter { ) -> Result, Error>; } -/// Operations on Contracts -pub enum ContractOperationType<'a> { - /// Deserializes a contract from CBOR and applies it. - ApplyContractCbor { - /// The cbor serialized contract - contract_cbor: Vec, - /// The contract id, if it is not present will try to recover it from the contract - contract_id: Option<[u8; 32]>, - /// Storage flags for the contract - storage_flags: Option<&'a StorageFlags>, - }, - /// Applies a contract and returns the fee for applying. - /// If the contract already exists, an update is applied, otherwise an insert. - ApplyContractWithSerialization { - /// The contract - contract: &'a Contract, - /// The serialized contract - serialized_contract: Vec, - /// Storage flags for the contract - storage_flags: Option<&'a StorageFlags>, - }, -} - -impl DriveOperationConverter for ContractOperationType<'_> { - fn to_drive_operations( - self, - drive: &Drive, - estimated_costs_only_with_layer_info: &mut Option< - HashMap, - >, - block_info: &BlockInfo, - transaction: TransactionArg, - ) -> Result, Error> { - match self { - ContractOperationType::ApplyContractCbor { - contract_cbor, - contract_id, - storage_flags, - } => { - // first we need to deserialize the contract - let contract = - ::from_cbor(&contract_cbor, contract_id)?; - - drive.apply_contract_operations( - &contract, - block_info, - estimated_costs_only_with_layer_info, - storage_flags, - transaction, - ) - } - ContractOperationType::ApplyContractWithSerialization { - contract, - serialized_contract: contract_serialization, - storage_flags, - } => drive.apply_contract_operations( - contract, - block_info, - estimated_costs_only_with_layer_info, - storage_flags, - transaction, - ), - } - } -} - -/// A wrapper for an update operation -pub struct UpdateOperationInfo<'a> { - /// The document to update - pub document: &'a DocumentStub, - /// The document in pre-serialized form - pub serialized_document: Option<&'a [u8]>, - /// The owner id, if none is specified will try to recover from serialized document - pub owner_id: Option<[u8; 32]>, - /// Add storage flags (like epoch, owner id, etc) - pub storage_flags: Option<&'a StorageFlags>, -} - -/// A wrapper for a document operation -pub enum DocumentOperation<'a> { - /// An add operation - AddOperation { - /// Document info with maybe the owner id - owned_document_info: OwnedDocumentInfo<'a>, - /// Should we override the document if one already exists? - override_document: bool, - }, - /// An update operation - UpdateOperation(UpdateOperationInfo<'a>), -} - -/// Document and contract info -pub struct DocumentOperationsForContractDocumentType<'a> { - /// Document info - pub operations: Vec>, - /// Contract - pub contract: &'a Contract, - /// Document type - pub document_type: &'a DocumentType, -} - -/// Operations on Documents -pub enum DocumentOperationType<'a> { - /// Deserializes a document and a contract and adds the document to the contract. - AddSerializedDocumentForSerializedContract { - /// The serialized document - serialized_document: &'a [u8], - /// The serialized contract - serialized_contract: &'a [u8], - /// The name of the document type - document_type_name: &'a str, - /// The owner id, if none is specified will try to recover from serialized document - owner_id: Option<[u8; 32]>, - /// Should we override the document if one already exists? - override_document: bool, - /// Add storage flags (like epoch, owner id, etc) - storage_flags: Option<&'a StorageFlags>, - }, - /// Deserializes a document and adds it to a contract. - AddSerializedDocumentForContract { - /// The serialized document - serialized_document: &'a [u8], - /// The contract - contract: &'a Contract, - /// The name of the document type - document_type_name: &'a str, - /// The owner id, if none is specified will try to recover from serialized document - owner_id: Option<[u8; 32]>, - /// Should we override the document if one already exists? - override_document: bool, - /// Add storage flags (like epoch, owner id, etc) - storage_flags: Option<&'a StorageFlags>, - }, - /// Adds a document to a contract. - AddDocumentForContract { - /// The document and contract info, also may contain the owner_id - document_and_contract_info: DocumentAndContractInfo<'a>, - /// Should we override the document if one already exists? - override_document: bool, - }, - /// Adds a document to a contract. - MultipleDocumentOperationsForSameContractDocumentType { - /// The document operations - document_operations: DocumentOperationsForContractDocumentType<'a>, - }, - /// Deletes a document and returns the associated fee. - DeleteDocumentForContract { - /// The document id - document_id: [u8; 32], - /// The contract - contract: &'a Contract, - /// The name of the document type - document_type_name: &'a str, - /// The owner id, if none is specified will try to recover from serialized document - owner_id: Option<[u8; 32]>, - }, - /// Deletes a document and returns the associated fee. - /// The contract CBOR is given instead of the contract itself. - DeleteDocumentForContractCbor { - /// The document id - document_id: [u8; 32], - /// The serialized contract - contract_cbor: &'a [u8], - /// The name of the document type - document_type_name: &'a str, - /// The owner id, if none is specified will try to recover from serialized document - owner_id: Option<[u8; 32]>, - }, - /// Updates a serialized document given a contract CBOR and returns the associated fee. - UpdateDocumentForContractCbor { - /// The serialized document - serialized_document: &'a [u8], - /// The serialized contract - contract_cbor: &'a [u8], - /// The name of the document type - document_type_name: &'a str, - /// The owner id, if none is specified will try to recover from serialized document - owner_id: Option<[u8; 32]>, - /// Add storage flags (like epoch, owner id, etc) - storage_flags: Option<&'a StorageFlags>, - }, - /// Updates a serialized document and returns the associated fee. - UpdateSerializedDocumentForContract { - /// The serialized document - serialized_document: &'a [u8], - /// The contract - contract: &'a Contract, - /// The name of the document type - document_type_name: &'a str, - /// The owner id, if none is specified will try to recover from serialized document - owner_id: Option<[u8; 32]>, - /// Add storage flags (like epoch, owner id, etc) - storage_flags: Option<&'a StorageFlags>, - }, - /// Updates a document and returns the associated fee. - UpdateDocumentForContract { - /// The document to update - document: &'a DocumentStub, - /// The document in pre-serialized form - serialized_document: &'a [u8], - /// The contract - contract: &'a Contract, - /// The name of the document type - document_type_name: &'a str, - /// The owner id, if none is specified will try to recover from serialized document - owner_id: Option<[u8; 32]>, - /// Add storage flags (like epoch, owner id, etc) - storage_flags: Option<&'a StorageFlags>, - }, -} - -impl DriveOperationConverter for DocumentOperationType<'_> { - fn to_drive_operations( - self, - drive: &Drive, - estimated_costs_only_with_layer_info: &mut Option< - HashMap, - >, - block_info: &BlockInfo, - transaction: TransactionArg, - ) -> Result, Error> { - match self { - DocumentOperationType::AddSerializedDocumentForSerializedContract { - serialized_document, - serialized_contract, - document_type_name, - owner_id, - override_document, - storage_flags, - } => { - let contract = - ::from_cbor(serialized_contract, None)?; - - let document = DocumentStub::from_cbor(serialized_document, None, owner_id)?; - - let document_info = - DocumentRefAndSerialization((&document, serialized_document, storage_flags)); - - let document_type = contract.document_type_for_name(document_type_name)?; - - let document_and_contract_info = DocumentAndContractInfo { - owned_document_info: OwnedDocumentInfo { - document_info, - owner_id, - }, - contract: &contract, - document_type, - }; - drive.add_document_for_contract_operations( - document_and_contract_info, - override_document, - block_info, - &mut None, - estimated_costs_only_with_layer_info, - transaction, - ) - } - DocumentOperationType::AddSerializedDocumentForContract { - serialized_document, - contract, - document_type_name, - owner_id, - override_document, - storage_flags, - } => { - let document = DocumentStub::from_cbor(serialized_document, None, owner_id)?; - - let document_info = - DocumentRefAndSerialization((&document, serialized_document, storage_flags)); - - let document_type = contract.document_type_for_name(document_type_name)?; - - let document_and_contract_info = DocumentAndContractInfo { - owned_document_info: OwnedDocumentInfo { - document_info, - owner_id, - }, - contract, - document_type, - }; - drive.add_document_for_contract_operations( - document_and_contract_info, - override_document, - block_info, - &mut None, - estimated_costs_only_with_layer_info, - transaction, - ) - } - DocumentOperationType::AddDocumentForContract { - document_and_contract_info, - override_document, - } => drive.add_document_for_contract_operations( - document_and_contract_info, - override_document, - block_info, - &mut None, - estimated_costs_only_with_layer_info, - transaction, - ), - DocumentOperationType::DeleteDocumentForContract { - document_id, - contract, - document_type_name, - owner_id, - } => drive.delete_document_for_contract_operations( - document_id, - contract, - document_type_name, - owner_id, - None, - estimated_costs_only_with_layer_info, - transaction, - ), - DocumentOperationType::DeleteDocumentForContractCbor { - document_id, - contract_cbor, - document_type_name, - owner_id, - } => { - let contract = ::from_cbor(contract_cbor, None)?; - drive.delete_document_for_contract_operations( - document_id, - &contract, - document_type_name, - owner_id, - None, - estimated_costs_only_with_layer_info, - transaction, - ) - } - DocumentOperationType::UpdateDocumentForContractCbor { - serialized_document, - contract_cbor, - document_type_name, - owner_id, - storage_flags, - } => { - let contract = ::from_cbor(contract_cbor, None)?; - - let document = DocumentStub::from_cbor(serialized_document, None, owner_id)?; - - let document_info = - DocumentRefAndSerialization((&document, serialized_document, storage_flags)); - - let document_type = contract.document_type_for_name(document_type_name)?; - - let document_and_contract_info = DocumentAndContractInfo { - owned_document_info: OwnedDocumentInfo { - document_info, - owner_id, - }, - contract: &contract, - document_type, - }; - drive.update_document_for_contract_operations( - document_and_contract_info, - block_info, - &mut None, - estimated_costs_only_with_layer_info, - transaction, - ) - } - DocumentOperationType::UpdateSerializedDocumentForContract { - serialized_document, - contract, - document_type_name, - owner_id, - storage_flags, - } => { - let document = DocumentStub::from_cbor(serialized_document, None, owner_id)?; - - let document_info = - DocumentRefAndSerialization((&document, serialized_document, storage_flags)); - - let document_type = contract.document_type_for_name(document_type_name)?; - - let document_and_contract_info = DocumentAndContractInfo { - owned_document_info: OwnedDocumentInfo { - document_info, - owner_id, - }, - contract, - document_type, - }; - drive.update_document_for_contract_operations( - document_and_contract_info, - block_info, - &mut None, - estimated_costs_only_with_layer_info, - transaction, - ) - } - DocumentOperationType::UpdateDocumentForContract { - document, - serialized_document, - contract, - document_type_name, - owner_id, - storage_flags, - } => { - let document_info = - DocumentRefAndSerialization((document, serialized_document, storage_flags)); - - let document_type = contract.document_type_for_name(document_type_name)?; - - let document_and_contract_info = DocumentAndContractInfo { - owned_document_info: OwnedDocumentInfo { - document_info, - owner_id, - }, - contract, - document_type, - }; - drive.update_document_for_contract_operations( - document_and_contract_info, - block_info, - &mut None, - estimated_costs_only_with_layer_info, - transaction, - ) - } - DocumentOperationType::MultipleDocumentOperationsForSameContractDocumentType { - document_operations, - } => { - let DocumentOperationsForContractDocumentType { - operations, - contract, - document_type, - } = document_operations; - - let mut drive_operations = vec![]; - for document_operation in operations { - match document_operation { - DocumentOperation::AddOperation { - owned_document_info, - override_document, - } => { - let document_and_contract_info = DocumentAndContractInfo { - owned_document_info, - contract, - document_type, - }; - let mut operations = drive.add_document_for_contract_operations( - document_and_contract_info, - override_document, - block_info, - &mut Some(&mut drive_operations), - estimated_costs_only_with_layer_info, - transaction, - )?; - drive_operations.append(&mut operations); - } - DocumentOperation::UpdateOperation(update_operation) => { - let UpdateOperationInfo { - document, - serialized_document, - owner_id, - storage_flags, - } = update_operation; - - let document_info = - if let Some(serialized_document) = serialized_document { - DocumentRefAndSerialization(( - document, - serialized_document, - storage_flags, - )) - } else { - DocumentRefWithoutSerialization((document, storage_flags)) - }; - let document_and_contract_info = DocumentAndContractInfo { - owned_document_info: OwnedDocumentInfo { - document_info, - owner_id, - }, - contract, - document_type, - }; - let mut operations = drive.update_document_for_contract_operations( - document_and_contract_info, - block_info, - &mut Some(&mut drive_operations), - estimated_costs_only_with_layer_info, - transaction, - )?; - drive_operations.append(&mut operations); - } - } - } - Ok(drive_operations) - } - } - } -} -// -// /// Operations on Identities -// pub enum IdentityOperationType<'a> { -// /// Inserts a new identity to the `Identities` subtree. -// InsertIdentity { -// /// The identity we wish to insert -// identity: Identity, -// /// Add storage flags (like epoch, owner id, etc) -// storage_flags: Option<&'a StorageFlags>, -// }, -// } -// -// impl DriveOperationConverter for IdentityOperationType<'_> { -// fn to_grove_db_operations( -// self, -// drive: &Drive, -// apply: bool, -// block_info: &BlockInfo, -// transaction: TransactionArg, -// ) -> Result, Error> { -// match self { -// IdentityOperationType::InsertIdentity { -// identity, -// storage_flags, -// } => { -// drive.insert_identity(identity, block_info, apply, storage_flags, transaction) -// } -// } -// } -// } - -/// Operations for Withdrawals -pub enum WithdrawalOperationType<'a> { - /// Inserts expired index into it's tree - InsertExpiredIndex { - /// index value - index: u64, - }, - /// Removes expired index from the tree - DeleteExpiredIndex { - /// index value - key: &'a [u8], - }, - /// Update index counter - UpdateIndexCounter { - /// index counter value - index: u64, - }, - /// Insert Core Transaction into queue - InsertTransactions { - /// transaction id bytes - transactions: &'a [WithdrawalTransaction], - }, - /// Delete withdrawal - DeleteWithdrawalTransaction { - /// withdrawal transaction tuple with id and bytes - id: Vec, - }, -} - -impl DriveOperationConverter for WithdrawalOperationType<'_> { - fn to_drive_operations( - self, - drive: &Drive, - _estimated_costs_only_with_layer_info: &mut Option< - HashMap, - >, - _block_info: &BlockInfo, - transaction: TransactionArg, - ) -> Result, Error> { - match self { - WithdrawalOperationType::InsertExpiredIndex { index } => { - let mut drive_operations = vec![]; - - let index_bytes = index.to_be_bytes(); - - let path = get_withdrawal_transactions_expired_ids_path_vec(); - - drive.batch_insert( - crate::drive::object_size_info::PathKeyElementInfo::PathKeyElement::<'_, 1>(( - path, - &index_bytes, - Element::Item(vec![], None), - )), - &mut drive_operations, - )?; - - Ok(drive_operations) - } - WithdrawalOperationType::DeleteExpiredIndex { key } => { - let mut drive_operations = vec![]; - - let path: [&[u8]; 2] = get_withdrawal_transactions_expired_ids_path(); - - drive.batch_delete( - path, - key, - BatchDeleteApplyType::StatefulBatchDelete { - is_known_to_be_subtree_with_sum: Some((false, false)), - }, - transaction, - &mut drive_operations, - )?; - - Ok(drive_operations) - } - WithdrawalOperationType::UpdateIndexCounter { index } => { - let mut drive_operations = vec![]; - - let path = get_withdrawal_root_path_vec(); - - drive.batch_insert( - crate::drive::object_size_info::PathKeyElementInfo::PathKeyElement::<'_, 1>(( - path, - &WITHDRAWAL_TRANSACTIONS_COUNTER_ID, - Element::Item(index.to_be_bytes().to_vec(), None), - )), - &mut drive_operations, - )?; - - Ok(drive_operations) - } - WithdrawalOperationType::InsertTransactions { transactions } => { - let mut drive_operations = vec![]; - - let path = get_withdrawal_transactions_queue_path_vec(); - - for (id, bytes) in transactions { - drive.batch_insert( - crate::drive::object_size_info::PathKeyElementInfo::PathKeyElement::<'_, 1>( - (path.clone(), id, Element::Item(bytes.clone(), None)), - ), - &mut drive_operations, - )?; - } - - Ok(drive_operations) - } - WithdrawalOperationType::DeleteWithdrawalTransaction { id } => { - let mut drive_operations = vec![]; - - let path = get_withdrawal_transactions_queue_path(); - - drive.batch_delete( - path, - &id, - // we know that we are not deleting a subtree - BatchDeleteApplyType::StatefulBatchDelete { - is_known_to_be_subtree_with_sum: Some((false, false)), - }, - transaction, - &mut drive_operations, - )?; - - Ok(drive_operations) - } - } - } -} - /// All types of Drive Operations #[derive(Clone, Debug)] pub enum DriveOperationType<'a> { diff --git a/packages/rs-drive/src/drive/batch/drive_op_batch/withdrawals.rs b/packages/rs-drive/src/drive/batch/drive_op_batch/withdrawals.rs new file mode 100644 index 00000000000..d6c95b11902 --- /dev/null +++ b/packages/rs-drive/src/drive/batch/drive_op_batch/withdrawals.rs @@ -0,0 +1,151 @@ +use std::collections::HashMap; + +use grovedb::{batch::KeyInfoPath, Element, EstimatedLayerInformation, TransactionArg}; + +use crate::{ + drive::{ + block_info::BlockInfo, + grove_operations::BatchDeleteApplyType, + identity::withdrawals::paths::{ + get_withdrawal_root_path_vec, get_withdrawal_transactions_expired_ids_path, + get_withdrawal_transactions_expired_ids_path_vec, + get_withdrawal_transactions_queue_path, get_withdrawal_transactions_queue_path_vec, + WithdrawalTransaction, WITHDRAWAL_TRANSACTIONS_COUNTER_ID, + }, + Drive, + }, + error::Error, + fee::op::DriveOperation, +}; + +use super::DriveOperationConverter; + +/// Operations for Withdrawals +#[derive(Clone, Debug)] +pub enum WithdrawalOperationType<'a> { + /// Inserts expired index into it's tree + InsertExpiredIndex { + /// index value + index: u64, + }, + /// Removes expired index from the tree + DeleteExpiredIndex { + /// index value + key: &'a [u8], + }, + /// Update index counter + UpdateIndexCounter { + /// index counter value + index: u64, + }, + /// Insert Core Transaction into queue + InsertTransactions { + /// transaction id bytes + transactions: &'a [WithdrawalTransaction], + }, + /// Delete withdrawal + DeleteWithdrawalTransaction { + /// withdrawal transaction tuple with id and bytes + id: Vec, + }, +} + +impl DriveOperationConverter for WithdrawalOperationType<'_> { + fn to_drive_operations( + self, + drive: &Drive, + _estimated_costs_only_with_layer_info: &mut Option< + HashMap, + >, + _block_info: &BlockInfo, + transaction: TransactionArg, + ) -> Result, Error> { + match self { + WithdrawalOperationType::InsertExpiredIndex { index } => { + let mut drive_operations = vec![]; + + let index_bytes = index.to_be_bytes(); + + let path = get_withdrawal_transactions_expired_ids_path_vec(); + + drive.batch_insert( + crate::drive::object_size_info::PathKeyElementInfo::PathKeyElement::<'_, 1>(( + path, + index_bytes.to_vec(), + Element::Item(vec![], None), + )), + &mut drive_operations, + )?; + + Ok(drive_operations) + } + WithdrawalOperationType::DeleteExpiredIndex { key } => { + let mut drive_operations = vec![]; + + let path: [&[u8]; 2] = get_withdrawal_transactions_expired_ids_path(); + + drive.batch_delete( + path, + key, + BatchDeleteApplyType::StatefulBatchDelete { + is_known_to_be_subtree_with_sum: Some((false, false)), + }, + transaction, + &mut drive_operations, + )?; + + Ok(drive_operations) + } + WithdrawalOperationType::UpdateIndexCounter { index } => { + let mut drive_operations = vec![]; + + let path = get_withdrawal_root_path_vec(); + + drive.batch_insert( + crate::drive::object_size_info::PathKeyElementInfo::PathKeyElement::<'_, 1>(( + path, + WITHDRAWAL_TRANSACTIONS_COUNTER_ID.to_vec(), + Element::Item(index.to_be_bytes().to_vec(), None), + )), + &mut drive_operations, + )?; + + Ok(drive_operations) + } + WithdrawalOperationType::InsertTransactions { transactions } => { + let mut drive_operations = vec![]; + + let path = get_withdrawal_transactions_queue_path_vec(); + + for (id, bytes) in transactions { + drive.batch_insert( + crate::drive::object_size_info::PathKeyElementInfo::PathKeyElement::<'_, 1>( + (path.clone(), id.clone(), Element::Item(bytes.clone(), None)), + ), + &mut drive_operations, + )?; + } + + Ok(drive_operations) + } + WithdrawalOperationType::DeleteWithdrawalTransaction { id } => { + let mut drive_operations = vec![]; + + let path = get_withdrawal_transactions_queue_path(); + + drive.batch_delete( + path, + &id, + // we know that we are not deleting a subtree + BatchDeleteApplyType::StatefulBatchDelete { + is_known_to_be_subtree_with_sum: Some((false, false)), + }, + transaction, + &mut drive_operations, + )?; + + Ok(drive_operations) + } + } + } +} diff --git a/packages/rs-drive/src/drive/identity/balance/prove.rs b/packages/rs-drive/src/drive/identity/balance/prove.rs index 9450a5b1900..abc394d7206 100644 --- a/packages/rs-drive/src/drive/identity/balance/prove.rs +++ b/packages/rs-drive/src/drive/identity/balance/prove.rs @@ -28,11 +28,12 @@ impl Drive { #[cfg(test)] mod tests { use super::*; - use crate::common::helpers::setup::setup_drive_with_initial_state_structure; use crate::drive::block_info::BlockInfo; + use crate::tests::helpers::setup::setup_drive_with_initial_state_structure; use dpp::identity::Identity; mod prove_identity_balance { + use super::*; #[test] diff --git a/packages/rs-drive/src/drive/identity/balance/update.rs b/packages/rs-drive/src/drive/identity/balance/update.rs index fab2b9794f8..b1f98fd5e9a 100644 --- a/packages/rs-drive/src/drive/identity/balance/update.rs +++ b/packages/rs-drive/src/drive/identity/balance/update.rs @@ -471,13 +471,15 @@ mod tests { use super::*; use dpp::prelude::*; - use crate::common::helpers::setup::setup_drive_with_initial_state_structure; - use crate::fee_pools::epochs::Epoch; + use crate::{ + common::helpers::identities::create_test_identity, + tests::helpers::setup::setup_drive_with_initial_state_structure, + }; + mod add_to_identity_balance { use super::*; - use crate::common::helpers::identities::create_test_identity; #[test] fn should_add_to_balance() { diff --git a/packages/rs-drive/src/drive/identity/fetch/fetch_by_public_key_hashes.rs b/packages/rs-drive/src/drive/identity/fetch/fetch_by_public_key_hashes.rs index f4c2b720825..33560d152a3 100644 --- a/packages/rs-drive/src/drive/identity/fetch/fetch_by_public_key_hashes.rs +++ b/packages/rs-drive/src/drive/identity/fetch/fetch_by_public_key_hashes.rs @@ -278,8 +278,8 @@ impl Drive { #[cfg(test)] mod tests { - use crate::common::helpers::setup::setup_drive; use crate::drive::block_info::BlockInfo; + use crate::tests::helpers::setup::setup_drive; use super::*; diff --git a/packages/rs-drive/src/drive/identity/fetch/full_identity.rs b/packages/rs-drive/src/drive/identity/fetch/full_identity.rs index 249ae620099..a6c42ddc93a 100644 --- a/packages/rs-drive/src/drive/identity/fetch/full_identity.rs +++ b/packages/rs-drive/src/drive/identity/fetch/full_identity.rs @@ -152,7 +152,7 @@ impl Drive { #[cfg(test)] mod tests { use super::*; - use crate::common::helpers::setup::setup_drive_with_initial_state_structure; + use crate::tests::helpers::setup::setup_drive_with_initial_state_structure; mod fetch_full_identities { use super::*; diff --git a/packages/rs-drive/src/drive/identity/fetch/prove/full_identities_by_public_key_hashes.rs b/packages/rs-drive/src/drive/identity/fetch/prove/full_identities_by_public_key_hashes.rs index c6d54d02c0a..1db2ee31859 100644 --- a/packages/rs-drive/src/drive/identity/fetch/prove/full_identities_by_public_key_hashes.rs +++ b/packages/rs-drive/src/drive/identity/fetch/prove/full_identities_by_public_key_hashes.rs @@ -56,8 +56,8 @@ impl Drive { #[cfg(test)] mod tests { use super::*; - use crate::common::helpers::setup::setup_drive_with_initial_state_structure; use crate::drive::block_info::BlockInfo; + use crate::tests::helpers::setup::setup_drive_with_initial_state_structure; use dpp::identity::Identity; use std::collections::BTreeMap; diff --git a/packages/rs-drive/src/drive/identity/fetch/prove/full_identity.rs b/packages/rs-drive/src/drive/identity/fetch/prove/full_identity.rs index fd3443bd357..48a386aa7be 100644 --- a/packages/rs-drive/src/drive/identity/fetch/prove/full_identity.rs +++ b/packages/rs-drive/src/drive/identity/fetch/prove/full_identity.rs @@ -30,8 +30,8 @@ impl Drive { #[cfg(test)] mod tests { use super::*; - use crate::common::helpers::setup::setup_drive_with_initial_state_structure; use crate::drive::block_info::BlockInfo; + use crate::tests::helpers::setup::setup_drive_with_initial_state_structure; use dpp::identity::Identity; use grovedb::query_result_type::QueryResultType; diff --git a/packages/rs-drive/src/drive/identity/fetch/prove/identity_ids_by_public_key_hashes.rs b/packages/rs-drive/src/drive/identity/fetch/prove/identity_ids_by_public_key_hashes.rs index d38600ec9be..83dbed107ca 100644 --- a/packages/rs-drive/src/drive/identity/fetch/prove/identity_ids_by_public_key_hashes.rs +++ b/packages/rs-drive/src/drive/identity/fetch/prove/identity_ids_by_public_key_hashes.rs @@ -29,8 +29,8 @@ impl Drive { #[cfg(test)] mod tests { use super::*; - use crate::common::helpers::setup::setup_drive_with_initial_state_structure; use crate::drive::block_info::BlockInfo; + use crate::tests::helpers::setup::setup_drive_with_initial_state_structure; use dpp::identity::Identity; use std::collections::BTreeMap; diff --git a/packages/rs-drive/src/drive/identity/insert.rs b/packages/rs-drive/src/drive/identity/insert.rs index 2bdd23db0d0..4162b1be9b2 100644 --- a/packages/rs-drive/src/drive/identity/insert.rs +++ b/packages/rs-drive/src/drive/identity/insert.rs @@ -161,8 +161,7 @@ impl Drive { #[cfg(test)] mod tests { - use crate::common::helpers::setup::setup_drive; - use crate::drive::block_info::BlockInfo; + use crate::{drive::block_info::BlockInfo, tests::helpers::setup::setup_drive}; use dpp::identity::Identity; use tempfile::TempDir; diff --git a/packages/rs-drive/src/drive/identity/mod.rs b/packages/rs-drive/src/drive/identity/mod.rs index c42ae5d3421..664a0f32f7a 100644 --- a/packages/rs-drive/src/drive/identity/mod.rs +++ b/packages/rs-drive/src/drive/identity/mod.rs @@ -51,7 +51,7 @@ mod insert; mod key; mod update; -pub use withdrawal_queue::add_initial_withdrawal_state_structure_operations; +pub use withdrawals::paths::add_initial_withdrawal_state_structure_operations; pub(crate) const IDENTITY_KEY: [u8; 1] = [0]; diff --git a/packages/rs-drive/src/drive/identity/update.rs b/packages/rs-drive/src/drive/identity/update.rs index 5ef95937c8c..b24fd9995f6 100644 --- a/packages/rs-drive/src/drive/identity/update.rs +++ b/packages/rs-drive/src/drive/identity/update.rs @@ -270,7 +270,7 @@ mod tests { use super::*; use dpp::prelude::*; - use crate::common::helpers::setup::setup_drive_with_initial_state_structure; + use crate::tests::helpers::setup::setup_drive_with_initial_state_structure; mod add_new_keys_to_identity { use super::*; diff --git a/packages/rs-drive/src/drive/identity/withdrawals/withdrawal_status.rs b/packages/rs-drive/src/drive/identity/withdrawals/withdrawal_status.rs index 0a2e2464343..46c89f3bd9c 100644 --- a/packages/rs-drive/src/drive/identity/withdrawals/withdrawal_status.rs +++ b/packages/rs-drive/src/drive/identity/withdrawals/withdrawal_status.rs @@ -8,7 +8,7 @@ use grovedb::TransactionArg; use indexmap::IndexMap; use crate::{ - drive::Drive, + drive::{query::QueryDocumentsOutcome, Drive}, error::{drive::DriveError, Error}, query::{DriveQuery, InternalClauses, OrderClause, WhereClause}, }; @@ -85,7 +85,22 @@ impl Drive { block_time: None, }; - let (documents, _) = self.query_documents(drive_query, transaction, &mut vec![])?; + let QueryDocumentsOutcome { + items, + skipped, + cost, + } = self.query_documents(drive_query, None, transaction)?; + + let documents = items + .iter() + .map(|document_cbor| { + DocumentStub::from_cbor(document_cbor, None, None).map_err(|_| { + Error::Drive(DriveError::CorruptedCodeExecution( + "Can't create document from CBOR", + )) + }) + }) + .collect::, Error>>()?; Ok(documents) } @@ -151,7 +166,22 @@ impl Drive { block_time: None, }; - let (documents, _) = self.query_documents(drive_query, transaction, &mut vec![])?; + let QueryDocumentsOutcome { + items, + skipped, + cost, + } = self.query_documents(drive_query, None, transaction)?; + + let documents = items + .iter() + .map(|document_cbor| { + DocumentStub::from_cbor(document_cbor, None, None).map_err(|_| { + Error::Drive(DriveError::CorruptedCodeExecution( + "Can't create document from CBOR", + )) + }) + }) + .collect::, Error>>()?; let document = documents .get(0) From 97383c815b7d07f0cf1b75cedb24a22dabfa5ca1 Mon Sep 17 00:00:00 2001 From: Djavid Gabibiyan Date: Tue, 7 Feb 2023 00:00:12 +0500 Subject: [PATCH 105/170] chore(wip): fixing merge --- ...edit_withdrawal_transition_factory_spec.rs | 36 ++++++++++------ .../rs-drive-abci/src/common/helpers/setup.rs | 5 ++- .../rs-drive-abci/src/execution/engine.rs | 2 + packages/rs-drive-abci/src/platform.rs | 2 +- .../rs-drive-abci/tests/strategy_tests.rs | 18 ++++---- packages/rs-drive-nodejs/src/lib.rs | 6 +-- .../rs-drive/src/drive/identity/key/fetch.rs | 2 +- packages/rs-drive/src/drive/identity/mod.rs | 43 ------------------- packages/rs-drive/src/drive/query/mod.rs | 2 +- packages/rs-drive/tests/query_tests.rs | 20 ++++----- .../rs-drive/tests/query_tests_history.rs | 22 +++++----- 11 files changed, 61 insertions(+), 97 deletions(-) diff --git a/packages/rs-dpp/src/tests/identity/state_transition/identity_credit_withdrawal_transition/apply_identity_credit_withdrawal_transition_factory_spec.rs b/packages/rs-dpp/src/tests/identity/state_transition/identity_credit_withdrawal_transition/apply_identity_credit_withdrawal_transition_factory_spec.rs index 9a666726227..f09746c0829 100644 --- a/packages/rs-dpp/src/tests/identity/state_transition/identity_credit_withdrawal_transition/apply_identity_credit_withdrawal_transition_factory_spec.rs +++ b/packages/rs-dpp/src/tests/identity/state_transition/identity_credit_withdrawal_transition/apply_identity_credit_withdrawal_transition_factory_spec.rs @@ -1,5 +1,6 @@ #[cfg(test)] mod apply_identity_credit_withdrawal_transition_factory { + use dashcore::{consensus, BlockHeader}; use serde_json::json; use crate::{ @@ -17,8 +18,6 @@ mod apply_identity_credit_withdrawal_transition_factory { #[tokio::test] async fn should_fail_if_data_contract_was_not_found() { - let state_transition = IdentityCreditWithdrawalTransition::default(); - let mut state_repository = MockStateRepositoryLike::default(); let state_transition = IdentityCreditWithdrawalTransition { @@ -26,12 +25,6 @@ mod apply_identity_credit_withdrawal_transition_factory { ..Default::default() }; - let IdentityCreditWithdrawalTransition { - identity_id, - amount, - .. - } = state_transition.clone(); - state_repository .expect_fetch_data_contract() .times(1) @@ -52,7 +45,7 @@ mod apply_identity_credit_withdrawal_transition_factory { #[tokio::test] async fn should_call_state_repository_methods() { - let block_time_seconds = 1669260925; + let block_time_seconds = 1675709306; let mut state_transition = IdentityCreditWithdrawalTransition::default(); @@ -72,14 +65,25 @@ mod apply_identity_credit_withdrawal_transition_factory { state_repository .expect_fetch_latest_platform_block_header() .times(1) - .returning(move || anyhow::Ok(json!({"time": {"seconds": block_time_seconds}}))); + .returning(move || { + let header = BlockHeader { + time: block_time_seconds, + version: 1, + prev_blockhash: Default::default(), + merkle_root: Default::default(), + bits: Default::default(), + nonce: Default::default(), + }; + + anyhow::Ok(consensus::serialize(&header)) + }); state_repository .expect_create_document() .times(1) .withf(move |doc, _| { - let created_at_match = doc.created_at == Some(block_time_seconds * 1000); - let updated_at_match = doc.created_at == Some(block_time_seconds * 1000); + let created_at_match = doc.created_at == Some((block_time_seconds * 1000) as i64); + let updated_at_match = doc.created_at == Some((block_time_seconds * 1000) as i64); let document_data_match = doc.data == json!({ @@ -98,13 +102,17 @@ mod apply_identity_credit_withdrawal_transition_factory { .expect_remove_from_identity_balance() .times(1) // TODO: we need to assert execution context as well - .with(eq(identity_id), eq(amount), always()) + .with( + eq(state_transition.identity_id), + eq(state_transition.amount), + always(), + ) .returning(|_, _, _| anyhow::Ok(())); state_repository .expect_remove_from_system_credits() .times(1) - .with(eq(amount), always()) + .with(eq(state_transition.amount), always()) .returning(|_, _| anyhow::Ok(())); let applier = ApplyIdentityCreditWithdrawalTransition::new(state_repository); diff --git a/packages/rs-drive-abci/src/common/helpers/setup.rs b/packages/rs-drive-abci/src/common/helpers/setup.rs index aea2306c744..82dd8872936 100644 --- a/packages/rs-drive-abci/src/common/helpers/setup.rs +++ b/packages/rs-drive-abci/src/common/helpers/setup.rs @@ -47,7 +47,7 @@ use tempfile::TempDir; pub fn setup_platform_raw(config: Option) -> Platform { let tmp_dir = TempDir::new().unwrap(); - let platform: Platform = + let mut platform: Platform = Platform::open(tmp_dir, config).expect("should open Platform successfully"); platform.mock_core_rpc_client(); @@ -57,7 +57,8 @@ pub fn setup_platform_raw(config: Option) -> Platform { /// A function which sets up Platform with its initial state structure. pub fn setup_platform_with_initial_state_structure(config: Option) -> Platform { - let platform = setup_platform_raw(config); + let mut platform = setup_platform_raw(config); + platform .drive .create_initial_state_structure(None) diff --git a/packages/rs-drive-abci/src/execution/engine.rs b/packages/rs-drive-abci/src/execution/engine.rs index c46e59518b5..e82e0a62a3b 100644 --- a/packages/rs-drive-abci/src/execution/engine.rs +++ b/packages/rs-drive-abci/src/execution/engine.rs @@ -159,6 +159,8 @@ impl Platform { .map(|block_info| block_info.time_ms), proposer_pro_tx_hash: proposer, validator_set_quorum_hash: Default::default(), + last_synced_core_height: 1, + core_chain_locked_height: 1, }; // println!("Block #{}", block_info.height); diff --git a/packages/rs-drive-abci/src/platform.rs b/packages/rs-drive-abci/src/platform.rs index 4e95f9268fb..1846ad95af6 100644 --- a/packages/rs-drive-abci/src/platform.rs +++ b/packages/rs-drive-abci/src/platform.rs @@ -75,7 +75,7 @@ impl Platform { pub fn open>(path: P, config: Option) -> Result { let config = config.unwrap_or_default(); - let drive = Drive::open(path, config.drive).map_err(Error::Drive)?; + let drive = Drive::open(path, config.drive.clone()).map_err(Error::Drive)?; let core_rpc: Box = Box::new( DefaultCoreRPC::open( diff --git a/packages/rs-drive-abci/tests/strategy_tests.rs b/packages/rs-drive-abci/tests/strategy_tests.rs index 62b9e6b82b9..439ef9af9c3 100644 --- a/packages/rs-drive-abci/tests/strategy_tests.rs +++ b/packages/rs-drive-abci/tests/strategy_tests.rs @@ -413,8 +413,8 @@ mod tests { }, }; let config = PlatformConfig { - drive_config: Default::default(), verify_sum_trees: true, + ..Default::default() }; run_chain_for_strategy(1000, 3000, strategy, config, 15); } @@ -430,8 +430,8 @@ mod tests { }, }; let config = PlatformConfig { - drive_config: Default::default(), verify_sum_trees: true, + ..Default::default() }; let outcome = run_chain_for_strategy(100, 3000, strategy, config, 15); @@ -449,8 +449,8 @@ mod tests { }, }; let config = PlatformConfig { - drive_config: Default::default(), verify_sum_trees: true, + ..Default::default() }; let day_in_ms = 1000 * 60 * 60 * 24; let outcome = run_chain_for_strategy(150, day_in_ms, strategy, config, 15); @@ -482,8 +482,8 @@ mod tests { }, }; let config = PlatformConfig { - drive_config: Default::default(), verify_sum_trees: true, + ..Default::default() }; run_chain_for_strategy(1, 3000, strategy, config, 15); } @@ -522,8 +522,8 @@ mod tests { }, }; let config = PlatformConfig { - drive_config: Default::default(), verify_sum_trees: true, + ..Default::default() }; run_chain_for_strategy(100, 3000, strategy, config, 15); } @@ -562,8 +562,8 @@ mod tests { }, }; let config = PlatformConfig { - drive_config: Default::default(), verify_sum_trees: true, + ..Default::default() }; let day_in_ms = 1000 * 60 * 60 * 24; let block_count = 120; @@ -630,8 +630,8 @@ mod tests { }, }; let config = PlatformConfig { - drive_config: Default::default(), verify_sum_trees: true, + ..Default::default() }; let day_in_ms = 1000 * 60 * 60 * 24; let block_count = 120; @@ -698,8 +698,8 @@ mod tests { }, }; let config = PlatformConfig { - drive_config: Default::default(), verify_sum_trees: true, + ..Default::default() }; let day_in_ms = 1000 * 60 * 60 * 24; let block_count = 120; @@ -766,8 +766,8 @@ mod tests { }, }; let config = PlatformConfig { - drive_config: Default::default(), verify_sum_trees: true, + ..Default::default() }; let day_in_ms = 1000 * 60 * 60 * 24; let block_count = 30; diff --git a/packages/rs-drive-nodejs/src/lib.rs b/packages/rs-drive-nodejs/src/lib.rs index 7a4697fe167..202da27d097 100644 --- a/packages/rs-drive-nodejs/src/lib.rs +++ b/packages/rs-drive-nodejs/src/lib.rs @@ -1,20 +1,17 @@ mod converter; mod fee; +use drive::drive::config::DriveConfig; use drive_abci::config::{CoreConfig, CoreRpcConfig, PlatformConfig}; -use std::num::ParseIntError; use std::ops::Deref; use std::{option::Option::None, path::Path, sync::mpsc, thread}; use crate::converter::js_object_to_fee_refunds; use crate::fee::result::FeeResultWrapper; -use drive::dpp::identity::Identity; use drive::dpp::identity::{KeyID, TimestampMillis}; use drive::dpp::prelude::Revision; -use drive::drive::batch::GroveDbOpBatch; -use drive::drive::config::DriveConfig; use drive::drive::flags::StorageFlags; use drive::drive::query::QueryDocumentsOutcome; use drive::error::Error; @@ -27,7 +24,6 @@ use drive_abci::abci::messages::{ AfterFinalizeBlockRequest, BlockBeginRequest, BlockEndRequest, BlockFees, InitChainRequest, Serializable, }; -use drive_abci::config::PlatformConfig; use drive_abci::platform::Platform; use fee::js_calculate_storage_fee_distribution_amount_and_leftovers; use neon::prelude::*; diff --git a/packages/rs-drive/src/drive/identity/key/fetch.rs b/packages/rs-drive/src/drive/identity/key/fetch.rs index 96fbfa5a905..c2b07b5d425 100644 --- a/packages/rs-drive/src/drive/identity/key/fetch.rs +++ b/packages/rs-drive/src/drive/identity/key/fetch.rs @@ -504,8 +504,8 @@ impl Drive { #[cfg(test)] mod tests { - use crate::common::helpers::setup::setup_drive; use crate::drive::block_info::BlockInfo; + use crate::tests::helpers::setup::setup_drive; use dpp::identity::Identity; use super::*; diff --git a/packages/rs-drive/src/drive/identity/mod.rs b/packages/rs-drive/src/drive/identity/mod.rs index 664a0f32f7a..06f11a3389c 100644 --- a/packages/rs-drive/src/drive/identity/mod.rs +++ b/packages/rs-drive/src/drive/identity/mod.rs @@ -250,46 +250,3 @@ impl From for &'static [u8; 1] { } } } - -#[cfg(test)] -mod tests { - use crate::drive::block_info::BlockInfo; - use crate::drive::flags::StorageFlags; - use crate::tests::helpers::setup::setup_drive; - use dpp::identity::Identity; - - #[test] - fn test_insert_and_fetch_identity() { - let drive = setup_drive(None); - - let transaction = drive.grove.start_transaction(); - - drive - .create_initial_state_structure(Some(&transaction)) - .expect("expected to create root tree successfully"); - - let identity_bytes = hex::decode("01a462696458203012c19b98ec0033addb36cd64b7f510670f2a351a4304b5f6994144286efdac6762616c616e636500687265766973696f6e006a7075626c69634b65797381a6626964006464617461582102abb64674c5df796559eb3cf92a84525cc1a6068e7ad9d4ff48a1f0b179ae29e164747970650067707572706f73650068726561644f6e6c79f46d73656375726974794c6576656c00").expect("expected to decode identity hex"); - - let identity = Identity::from_buffer(identity_bytes.as_slice()) - .expect("expected to deserialize an identity"); - - drive - .insert_identity( - identity.clone(), - BlockInfo::default(), - true, - StorageFlags::optional_default_as_ref(), - Some(&transaction), - ) - .expect("expected to insert identity"); - - let (fetched_identity, _) = drive - .fetch_identity(&identity.id.buffer, Some(&transaction)) - .expect("should fetch an identity"); - - assert_eq!( - fetched_identity.to_buffer().expect("should serialize"), - identity.to_buffer().expect("should serialize") - ); - } -} diff --git a/packages/rs-drive/src/drive/query/mod.rs b/packages/rs-drive/src/drive/query/mod.rs index 0ba98ec525c..0667231fc12 100644 --- a/packages/rs-drive/src/drive/query/mod.rs +++ b/packages/rs-drive/src/drive/query/mod.rs @@ -215,7 +215,7 @@ impl Drive { } /// Performs and returns the result of the specified query along with skipped items and the cost. - pub fn query_documentss_from_contract( + pub fn query_documents_from_contract( &self, contract: &Contract, document_type: &DocumentType, diff --git a/packages/rs-drive/tests/query_tests.rs b/packages/rs-drive/tests/query_tests.rs index f8e89e89d0d..b2617c0da2f 100644 --- a/packages/rs-drive/tests/query_tests.rs +++ b/packages/rs-drive/tests/query_tests.rs @@ -1890,17 +1890,17 @@ fn test_family_basic_queries() { let query_cbor = serializer::value_to_cbor(query_value, None).expect("expected to serialize to cbor"); - let (results, _, _) = drive - .query_documents_from_contract_cbor( - query_cbor.as_slice(), - contract_cbor.as_slice(), - String::from("contact"), - None, - Some(&db_transaction), - ) - .expect("query should be executed"); + // let (results, _, _) = drive + // .query_documents_from_contract_cbor( + // query_cbor.as_slice(), + // contract_cbor.as_slice(), + // String::from("contact"), + // None, + // Some(&db_transaction), + // ) + // .expect("query should be executed"); - assert_eq!(results.len(), 0); + // assert_eq!(results.len(), 0); // using non existing document in startAt diff --git a/packages/rs-drive/tests/query_tests_history.rs b/packages/rs-drive/tests/query_tests_history.rs index e4a09b92841..f3ada8e75f4 100644 --- a/packages/rs-drive/tests/query_tests_history.rs +++ b/packages/rs-drive/tests/query_tests_history.rs @@ -1496,17 +1496,17 @@ fn test_query_historical() { let query_cbor = serializer::value_to_cbor(query_value, None).expect("expected to serialize to cbor"); - let (results, _, _) = drive - .query_documents_from_contract_cbor( - query_cbor.as_slice(), - contract_cbor.as_slice(), - String::from("contact"), - None, - Some(&db_transaction), - ) - .expect("query should be executed"); - - assert_eq!(results.len(), 0); + // let (results, _, _) = drive + // .query_documents_from_contract( + // query_cbor.as_slice(), + // contract_cbor.as_slice(), + // String::from("contact"), + // None, + // Some(&db_transaction), + // ) + // .expect("query should be executed"); + + // assert_eq!(results.len(), 0); // using non existing document in startAt From 874f1347118e98636294fd2abbed1268e9cc78d9 Mon Sep 17 00:00:00 2001 From: Djavid Gabibiyan Date: Tue, 7 Feb 2023 00:09:38 +0500 Subject: [PATCH 106/170] chore(wip): merge fixes --- packages/rs-drive/tests/query_tests.rs | 20 ++++++++--------- .../rs-drive/tests/query_tests_history.rs | 22 +++++++++---------- 2 files changed, 21 insertions(+), 21 deletions(-) diff --git a/packages/rs-drive/tests/query_tests.rs b/packages/rs-drive/tests/query_tests.rs index b2617c0da2f..8cf42bad1a9 100644 --- a/packages/rs-drive/tests/query_tests.rs +++ b/packages/rs-drive/tests/query_tests.rs @@ -1890,17 +1890,17 @@ fn test_family_basic_queries() { let query_cbor = serializer::value_to_cbor(query_value, None).expect("expected to serialize to cbor"); - // let (results, _, _) = drive - // .query_documents_from_contract_cbor( - // query_cbor.as_slice(), - // contract_cbor.as_slice(), - // String::from("contact"), - // None, - // Some(&db_transaction), - // ) - // .expect("query should be executed"); + let (results, _, _) = drive + .query_raw_documents_from_contract_cbor_using_cbor_encoded_query_with_cost( + query_cbor.as_slice(), + contract_cbor.as_slice(), + String::from("contact"), + None, + Some(&db_transaction), + ) + .expect("query should be executed"); - // assert_eq!(results.len(), 0); + assert_eq!(results.len(), 0); // using non existing document in startAt diff --git a/packages/rs-drive/tests/query_tests_history.rs b/packages/rs-drive/tests/query_tests_history.rs index f3ada8e75f4..c09247c0894 100644 --- a/packages/rs-drive/tests/query_tests_history.rs +++ b/packages/rs-drive/tests/query_tests_history.rs @@ -1496,17 +1496,17 @@ fn test_query_historical() { let query_cbor = serializer::value_to_cbor(query_value, None).expect("expected to serialize to cbor"); - // let (results, _, _) = drive - // .query_documents_from_contract( - // query_cbor.as_slice(), - // contract_cbor.as_slice(), - // String::from("contact"), - // None, - // Some(&db_transaction), - // ) - // .expect("query should be executed"); - - // assert_eq!(results.len(), 0); + let (results, _, _) = drive + .query_raw_documents_from_contract_cbor_using_cbor_encoded_query_with_cost( + query_cbor.as_slice(), + contract_cbor.as_slice(), + String::from("contact"), + None, + Some(&db_transaction), + ) + .expect("query should be executed"); + + assert_eq!(results.len(), 0); // using non existing document in startAt From 28332ea53705478123cbe628553ea172c5b8e953 Mon Sep 17 00:00:00 2001 From: Djavid Gabibiyan Date: Tue, 7 Feb 2023 00:34:08 +0500 Subject: [PATCH 107/170] chore: fix time conversion --- .../apply_identity_credit_withdrawal_transition_factory.rs | 4 +--- ...pply_identity_credit_withdrawal_transition_factory_spec.rs | 4 ++-- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/packages/rs-dpp/src/identity/state_transition/identity_credit_withdrawal_transition/apply_identity_credit_withdrawal_transition_factory.rs b/packages/rs-dpp/src/identity/state_transition/identity_credit_withdrawal_transition/apply_identity_credit_withdrawal_transition_factory.rs index 6c7d3921fd9..b12305b0ba8 100644 --- a/packages/rs-dpp/src/identity/state_transition/identity_credit_withdrawal_transition/apply_identity_credit_withdrawal_transition_factory.rs +++ b/packages/rs-dpp/src/identity/state_transition/identity_credit_withdrawal_transition/apply_identity_credit_withdrawal_transition_factory.rs @@ -61,9 +61,7 @@ where consensus::deserialize(&latest_platform_block_header_bytes)?; let document_type = String::from(withdrawals_contract::types::WITHDRAWAL); - let document_created_at_millis: i64 = (latest_platform_block_header.time * 1000) - .try_into() - .map_err(|_| anyhow!("Can't convert block header time from u32 to i64"))?; + let document_created_at_millis: i64 = latest_platform_block_header.time as i64 * 1000i64; let document_data = json!({ withdrawals_contract::property_names::AMOUNT: state_transition.amount, diff --git a/packages/rs-dpp/src/tests/identity/state_transition/identity_credit_withdrawal_transition/apply_identity_credit_withdrawal_transition_factory_spec.rs b/packages/rs-dpp/src/tests/identity/state_transition/identity_credit_withdrawal_transition/apply_identity_credit_withdrawal_transition_factory_spec.rs index f09746c0829..c8ea7dc0312 100644 --- a/packages/rs-dpp/src/tests/identity/state_transition/identity_credit_withdrawal_transition/apply_identity_credit_withdrawal_transition_factory_spec.rs +++ b/packages/rs-dpp/src/tests/identity/state_transition/identity_credit_withdrawal_transition/apply_identity_credit_withdrawal_transition_factory_spec.rs @@ -82,8 +82,8 @@ mod apply_identity_credit_withdrawal_transition_factory { .expect_create_document() .times(1) .withf(move |doc, _| { - let created_at_match = doc.created_at == Some((block_time_seconds * 1000) as i64); - let updated_at_match = doc.created_at == Some((block_time_seconds * 1000) as i64); + let created_at_match = doc.created_at == Some((block_time_seconds as i64 * 1000) as i64); + let updated_at_match = doc.created_at == Some((block_time_seconds as i64 * 1000) as i64); let document_data_match = doc.data == json!({ From 835b499a4b1e100fb742afb6da372e428cd202b2 Mon Sep 17 00:00:00 2001 From: Djavid Gabibiyan Date: Tue, 7 Feb 2023 00:34:35 +0500 Subject: [PATCH 108/170] chore: fmt --- ...ly_identity_credit_withdrawal_transition_factory_spec.rs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/packages/rs-dpp/src/tests/identity/state_transition/identity_credit_withdrawal_transition/apply_identity_credit_withdrawal_transition_factory_spec.rs b/packages/rs-dpp/src/tests/identity/state_transition/identity_credit_withdrawal_transition/apply_identity_credit_withdrawal_transition_factory_spec.rs index c8ea7dc0312..ccb690add7a 100644 --- a/packages/rs-dpp/src/tests/identity/state_transition/identity_credit_withdrawal_transition/apply_identity_credit_withdrawal_transition_factory_spec.rs +++ b/packages/rs-dpp/src/tests/identity/state_transition/identity_credit_withdrawal_transition/apply_identity_credit_withdrawal_transition_factory_spec.rs @@ -82,8 +82,10 @@ mod apply_identity_credit_withdrawal_transition_factory { .expect_create_document() .times(1) .withf(move |doc, _| { - let created_at_match = doc.created_at == Some((block_time_seconds as i64 * 1000) as i64); - let updated_at_match = doc.created_at == Some((block_time_seconds as i64 * 1000) as i64); + let created_at_match = + doc.created_at == Some((block_time_seconds as i64 * 1000) as i64); + let updated_at_match = + doc.created_at == Some((block_time_seconds as i64 * 1000) as i64); let document_data_match = doc.data == json!({ From c944f7b357fad7b7919f7d12b5e4f9e4139175a5 Mon Sep 17 00:00:00 2001 From: Djavid Gabibiyan Date: Tue, 7 Feb 2023 00:40:05 +0500 Subject: [PATCH 109/170] chore: linter fix --- packages/js-drive/lib/createDIContainer.js | 26 +++++++++++----------- packages/js-drive/lib/test/bootstrap.js | 4 ++-- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/packages/js-drive/lib/createDIContainer.js b/packages/js-drive/lib/createDIContainer.js index e693ef35885..b130ced4e33 100644 --- a/packages/js-drive/lib/createDIContainer.js +++ b/packages/js-drive/lib/createDIContainer.js @@ -444,19 +444,19 @@ function createDIContainer(options) { logJsonFileLevel, logJsonFileStream, ) => [ - { - level: logStdoutLevel, - stream: logStdoutStream, - }, - { - level: logPrettyFileLevel, - stream: logPrettyFileStream, - }, - { - level: logJsonFileLevel, - stream: logJsonFileStream, - }, - ]), + { + level: logStdoutLevel, + stream: logStdoutStream, + }, + { + level: logPrettyFileLevel, + stream: logPrettyFileStream, + }, + { + level: logJsonFileLevel, + stream: logJsonFileStream, + }, + ]), logger: asFunction( (loggerStreams) => pino({ diff --git a/packages/js-drive/lib/test/bootstrap.js b/packages/js-drive/lib/test/bootstrap.js index b736297d77f..47953174343 100644 --- a/packages/js-drive/lib/test/bootstrap.js +++ b/packages/js-drive/lib/test/bootstrap.js @@ -45,10 +45,10 @@ if (process.env.MASTERNODE_REWARD_SHARES_SECOND_PUBLIC_KEY === undefined) { process.env.MASTERNODE_REWARD_SHARES_SECOND_PUBLIC_KEY = '03a3002856ad91662dc34b6650a2c7f8b2726c947a419e0b880fb3acc38763a271'; } if (process.env.WITHDRAWALS_MASTER_PUBLIC_KEY === undefined) { - process.env.WITHDRAWALS_MASTER_PUBLIC_KEY = testPublicKey; + process.env.WITHDRAWALS_MASTER_PUBLIC_KEY = '02c571ff0cdb72634de4fd23f40c4ed530b3d31defc987a55479d65e7e8c1e249b'; } if (process.env.WITHDRAWALS_SECOND_PUBLIC_KEY === undefined) { - process.env.WITHDRAWALS_SECOND_PUBLIC_KEY = testPublicKey; + process.env.WITHDRAWALS_SECOND_PUBLIC_KEY = '03b3002856ad91662dc34b6650a2c7f8b2726c947a419e0b880fb3acc38763a271'; } const dotenvConfig = dotenvSafe.config({ From 26a4099f263490a2aee63b118fa0a285e222a19f Mon Sep 17 00:00:00 2001 From: Quantum Explorer Date: Tue, 7 Feb 2023 15:59:35 +0700 Subject: [PATCH 110/170] many fixes --- .../document_type/document_field.rs | 4 +- packages/rs-dpp/src/document/document_stub.rs | 39 +- packages/rs-dpp/src/errors/errors.rs | 8 + .../rs-dpp/src/errors/non_consensus_error.rs | 3 +- .../fixtures/get_withdrawals_data_contract.rs | 2 +- packages/rs-drive-abci/src/abci/handlers.rs | 9 +- .../rs-drive-abci/src/common/helpers/setup.rs | 2 + .../src/identity_credit_withdrawal/mod.rs | 46 +- packages/rs-drive/src/common/helpers/mod.rs | 1 + .../src/{tests => common}/helpers/setup.rs | 28 +- .../src/drive/batch/drive_op_batch/mod.rs | 3 + .../drive/batch/drive_op_batch/withdrawals.rs | 86 +-- packages/rs-drive/src/drive/contract/mod.rs | 2 +- .../rs-drive/src/drive/document/insert.rs | 1 + .../rs-drive/src/drive/document/update.rs | 583 +++++++++--------- .../epochs/credit_distribution_pools.rs | 2 +- .../src/drive/fee_pools/epochs/mod.rs | 2 +- .../src/drive/fee_pools/epochs/proposers.rs | 2 +- .../src/drive/fee_pools/epochs/start_block.rs | 2 +- .../src/drive/fee_pools/epochs/start_time.rs | 2 +- packages/rs-drive/src/drive/fee_pools/mod.rs | 2 +- .../drive/fee_pools/pending_epoch_refunds.rs | 2 +- .../storage_fee_distribution_pool.rs | 2 +- .../src/drive/fee_pools/unpaid_epoch.rs | 2 +- packages/rs-drive/src/drive/genesis_time.rs | 2 +- .../src/drive/identity/balance/prove.rs | 2 +- .../src/drive/identity/balance/update.rs | 2 +- .../fetch/fetch_by_public_key_hashes.rs | 2 +- .../src/drive/identity/fetch/full_identity.rs | 2 +- .../full_identities_by_public_key_hashes.rs | 2 +- .../identity/fetch/prove/full_identity.rs | 2 +- .../identity_ids_by_public_key_hashes.rs | 2 +- .../rs-drive/src/drive/identity/insert.rs | 2 +- .../rs-drive/src/drive/identity/key/fetch.rs | 2 +- .../rs-drive/src/drive/identity/update.rs | 2 +- .../src/drive/identity/withdrawals/delete.rs | 33 + .../identity/withdrawals/expired_index.rs | 54 ++ .../src/drive/identity/withdrawals/insert.rs | 33 + .../src/drive/identity/withdrawals/mod.rs | 6 + .../src/drive/identity/withdrawals/paths.rs | 2 - .../src/drive/identity/withdrawals/queue.rs | 4 +- .../withdrawals/transaction_index_counter.rs | 24 +- .../identity/withdrawals/withdrawal_status.rs | 60 +- packages/rs-drive/src/drive/query/mod.rs | 1 - .../fee_pools/epochs/operations_factory.rs | 2 +- packages/rs-drive/src/fee_pools/mod.rs | 2 +- packages/rs-drive/src/lib.rs | 4 - packages/rs-drive/src/tests/helpers/mod.rs | 1 - packages/rs-drive/src/tests/mod.rs | 2 - packages/rs-drive/tests/query_tests.rs | 4 +- .../rs-drive/tests/query_tests_history.rs | 2 +- 51 files changed, 631 insertions(+), 460 deletions(-) rename packages/rs-drive/src/{tests => common}/helpers/setup.rs (78%) create mode 100644 packages/rs-drive/src/drive/identity/withdrawals/delete.rs create mode 100644 packages/rs-drive/src/drive/identity/withdrawals/expired_index.rs create mode 100644 packages/rs-drive/src/drive/identity/withdrawals/insert.rs delete mode 100644 packages/rs-drive/src/tests/helpers/mod.rs delete mode 100644 packages/rs-drive/src/tests/mod.rs diff --git a/packages/rs-dpp/src/data_contract/document_type/document_field.rs b/packages/rs-dpp/src/data_contract/document_type/document_field.rs index 839053287c3..c1768d0c650 100644 --- a/packages/rs-dpp/src/data_contract/document_type/document_field.rs +++ b/packages/rs-dpp/src/data_contract/document_type/document_field.rs @@ -263,7 +263,7 @@ impl DocumentFieldType { fn read_varint_value(buf: &mut BufReader<&[u8]>) -> Result>, ProtocolError> { let bytes: usize = buf.read_varint().map_err(|_| { ProtocolError::DataContractError(DataContractError::CorruptedSerialization( - "error reading from serialized document", + "error reading varint length from serialized document", )) })?; if bytes == 0 { @@ -272,7 +272,7 @@ impl DocumentFieldType { let mut value: Vec = vec![0u8; bytes]; buf.read_exact(&mut value).map_err(|_| { ProtocolError::DataContractError(DataContractError::CorruptedSerialization( - "error reading from serialized document", + "error reading varint from serialized document", )) })?; Ok(Some(value)) diff --git a/packages/rs-dpp/src/document/document_stub.rs b/packages/rs-dpp/src/document/document_stub.rs index fa0160c4435..b86567eaf10 100644 --- a/packages/rs-dpp/src/document/document_stub.rs +++ b/packages/rs-dpp/src/document/document_stub.rs @@ -151,12 +151,14 @@ impl DocumentStub { } let mut id = [0; 32]; buf.read_exact(&mut id).map_err(|_| { - ProtocolError::DecodingError("error reading from serialized document".to_string()) + ProtocolError::DecodingError("error reading id from serialized document".to_string()) })?; let mut owner_id = [0; 32]; buf.read_exact(&mut owner_id).map_err(|_| { - ProtocolError::DecodingError("error reading from serialized document".to_string()) + ProtocolError::DecodingError( + "error reading owner id from serialized document".to_string(), + ) })?; let properties = document_type @@ -194,7 +196,7 @@ impl DocumentStub { let mut document: BTreeMap = ciborium::de::from_reader(read_document_cbor) .map_err(|_| { ProtocolError::StructureError(StructureError::InvalidCBOR( - "unable to decode contract for document call", + "unable to decode document for document call", )) })?; @@ -411,25 +413,24 @@ impl DocumentStub { /// Temporary helper method to get property in u32 format /// Imitating JsonValueExt trait - pub fn get_u32(&self, property_name: &str) -> Result { - let property_value = self.properties.get(property_name).ok_or_else(|| { - anyhow!( - "the property '{}' doesn't exist in '{:?}'", - property_name, - self - ) - })?; + pub fn get_u32(&self, property_name: &str) -> Result { + let property_value = + self.properties + .get(property_name) + .ok_or(ProtocolError::DocumentKeyMissing(format!( + "the property '{}' doesn't exist in '{:?}'", + property_name, self + )))?; if let Value::Integer(s) = property_value { return (*s) .try_into() - .map_err(|_| anyhow!("unable convert {} to u32", property_name)); + .map_err(|_| ProtocolError::DecodingError("expected a u32 integer".to_string())); + } else { + Err(ProtocolError::DecodingError( + "expected an integer".to_string(), + )) } - bail!( - "getting property '{}' failed: {:?} isn't a number", - property_name, - property_value - ); } /// Temporary helper method to get property in bytes format @@ -472,14 +473,14 @@ impl DocumentStub { .insert(property_name.to_string(), Value::Bytes(value)); } - pub fn increment_revision(&mut self) -> Result<(), anyhow::Error> { + pub fn increment_revision(&mut self) -> Result<(), ProtocolError> { let property_name = "$revision"; let revision = self.get_u32(property_name)?; let new_revision = revision .checked_add(1) - .ok_or_else(|| anyhow!("could not increment revision: overflow occured"))?; + .ok_or(ProtocolError::Overflow("overflow when adding 1"))?; self.properties.insert( property_name.to_string(), diff --git a/packages/rs-dpp/src/errors/errors.rs b/packages/rs-dpp/src/errors/errors.rs index fdb7ecf2df5..f206d8731b9 100644 --- a/packages/rs-dpp/src/errors/errors.rs +++ b/packages/rs-dpp/src/errors/errors.rs @@ -115,6 +115,14 @@ pub enum ProtocolError { #[error("Identity is not present")] IdentityNotPresentError { id: Identifier }, + + /// Error + #[error("overflow error: {0}")] + Overflow(&'static str), + + /// Error + #[error("missing key: {0}")] + DocumentKeyMissing(String), } impl From for ProtocolError { diff --git a/packages/rs-dpp/src/errors/non_consensus_error.rs b/packages/rs-dpp/src/errors/non_consensus_error.rs index ab2160fdb29..bb68b9084e8 100644 --- a/packages/rs-dpp/src/errors/non_consensus_error.rs +++ b/packages/rs-dpp/src/errors/non_consensus_error.rs @@ -1,8 +1,7 @@ use thiserror::Error; use crate::{ - prelude::Identifier, CompatibleProtocolVersionIsNotDefinedError, InvalidVectorSizeError, - SerdeParsingError, + CompatibleProtocolVersionIsNotDefinedError, InvalidVectorSizeError, SerdeParsingError, }; #[derive(Debug, Error)] diff --git a/packages/rs-dpp/src/tests/fixtures/get_withdrawals_data_contract.rs b/packages/rs-dpp/src/tests/fixtures/get_withdrawals_data_contract.rs index 0f2e68f622a..1939d5b5adf 100644 --- a/packages/rs-dpp/src/tests/fixtures/get_withdrawals_data_contract.rs +++ b/packages/rs-dpp/src/tests/fixtures/get_withdrawals_data_contract.rs @@ -5,7 +5,7 @@ use serde_json::Value; use crate::contracts::withdrawals_contract; use crate::prelude::*; -use crate::util::string_encoding::Encoding; + use crate::{ data_contract::validation::data_contract_validator::DataContractValidator, data_contract::DataContractFactory, diff --git a/packages/rs-drive-abci/src/abci/handlers.rs b/packages/rs-drive-abci/src/abci/handlers.rs index 1b5298b1aa8..9fe256be0f3 100644 --- a/packages/rs-drive-abci/src/abci/handlers.rs +++ b/packages/rs-drive-abci/src/abci/handlers.rs @@ -204,18 +204,20 @@ mod tests { use dashcore::hashes::hex::FromHex; use dashcore::BlockHash; use dpp::contracts::withdrawals_contract; + use dpp::data_contract::DriveContractExt; + use dpp::document::document_stub::DocumentStub; use dpp::identity::state_transition::identity_credit_withdrawal_transition::Pooling; use dpp::tests::fixtures::{ get_withdrawal_document_fixture, get_withdrawals_data_contract_fixture, }; use dpp::util::hash; use drive::common::helpers::identities::create_test_masternode_identities; + use drive::common::helpers::setup::setup_document; use drive::drive::block_info::BlockInfo; use drive::drive::identity::withdrawals::paths::WithdrawalTransaction; use drive::fee::epoch::CreditsPerEpoch; use drive::fee_pools::epochs::Epoch; use drive::rpc::core::MockCoreRPCLike; - use drive::tests::helpers::setup::setup_document; use rust_decimal::prelude::ToPrimitive; use serde_json::json; use std::cmp::Ordering; @@ -271,10 +273,15 @@ mod tests { }), ); + let document_type = data_contract + .document_type_for_name(withdrawals_contract::types::WITHDRAWAL) + .expect("expected to get document type"); + setup_document( &platform.drive, &document, &data_contract, + document_type, Some(&transaction), ); } diff --git a/packages/rs-drive-abci/src/common/helpers/setup.rs b/packages/rs-drive-abci/src/common/helpers/setup.rs index 82dd8872936..1304c00d283 100644 --- a/packages/rs-drive-abci/src/common/helpers/setup.rs +++ b/packages/rs-drive-abci/src/common/helpers/setup.rs @@ -50,6 +50,7 @@ pub fn setup_platform_raw(config: Option) -> Platform { let mut platform: Platform = Platform::open(tmp_dir, config).expect("should open Platform successfully"); + #[cfg(feature = "fixtures-and-mocks")] platform.mock_core_rpc_client(); platform @@ -64,6 +65,7 @@ pub fn setup_platform_with_initial_state_structure(config: Option Result<(), Error> { - let data_contract_id = withdrawals_contract::CONTRACT_ID.clone(); + let data_contract_id = &withdrawals_contract::CONTRACT_ID; let (_, maybe_data_contract) = self.drive.get_contract_with_fetch_info( data_contract_id.to_buffer(), @@ -52,7 +52,7 @@ impl Platform { )?; let contract_fetch_info = maybe_data_contract.ok_or(Error::Execution( - ExecutionError::CorruptedCodeExecution("Can't fetch withdrawal data contract"), + ExecutionError::CorruptedCodeExecution("can't fetch withdrawal data contract"), ))?; let core_transactions = self.fetch_core_block_transactions( @@ -127,11 +127,7 @@ impl Platform { })?, ); - document.increment_revision().map_err(|_| { - Error::Execution(ExecutionError::CorruptedCodeExecution( - "Could not increment document revision", - )) - })?; + document.increment_revision().map_err(Error::Protocol)?; } } @@ -149,10 +145,8 @@ impl Platform { &mut drive_operations, ); - if !drive_operations.is_empty() { - self.drive - .apply_drive_operations(drive_operations, true, &block_info, transaction)?; - } + self.drive + .apply_drive_operations(drive_operations, true, &block_info, transaction)?; Ok(()) } @@ -432,7 +426,7 @@ impl Platform { .remove_latest_withdrawal_transaction_index(transaction)?; for (i, document) in documents.iter().enumerate() { - let output_script = document + let output_script_bytes = document .get_bytes(withdrawals_contract::property_names::OUTPUT_SCRIPT) .map_err(|_| { Error::Execution(ExecutionError::CorruptedCodeExecution( @@ -458,7 +452,7 @@ impl Platform { let state_transition_size = 190; - let output_script: Script = Script::from(output_script); + let output_script: Script = Script::from(output_script_bytes); let tx_out = TxOut { value: convert_credits_to_satoshi(amount), @@ -511,7 +505,7 @@ mod tests { contracts::withdrawals_contract, tests::fixtures::{get_withdrawal_document_fixture, get_withdrawals_data_contract_fixture}, }; - use drive::{rpc::core::MockCoreRPCLike, tests::helpers::setup::setup_document}; + use drive::{common::helpers::setup::setup_document, rpc::core::MockCoreRPCLike}; use serde_json::json; use crate::common::helpers::setup::setup_platform_with_initial_state_structure; @@ -522,9 +516,8 @@ mod tests { use crate::{block::BlockExecutionContext, execution::fee_pools::epoch::EpochInfo}; mod update_withdrawal_statuses { - use dpp::prelude::DataContract; - use crate::block::BlockStateInfo; + use dpp::data_contract::{DataContract, DriveContractExt}; use super::*; @@ -609,10 +602,15 @@ mod tests { }), ); + let document_type = data_contract + .document_type_for_name(withdrawals_contract::types::WITHDRAWAL) + .expect("expected to get document type"); + setup_document( &platform.drive, &document_1, &data_contract, + document_type, Some(&transaction), ); @@ -634,6 +632,7 @@ mod tests { &platform.drive, &document_2, &data_contract, + document_type, Some(&transaction), ); @@ -692,7 +691,7 @@ mod tests { } mod pool_withdrawals_into_transactions { - + use dpp::data_contract::DriveContractExt; use dpp::identity::state_transition::identity_credit_withdrawal_transition::Pooling; use crate::block::BlockStateInfo; @@ -721,10 +720,15 @@ mod tests { }), ); + let document_type = data_contract + .document_type_for_name(withdrawals_contract::types::WITHDRAWAL) + .expect("expected to get document type"); + setup_document( &platform.drive, &document_1, &data_contract, + document_type, Some(&transaction), ); @@ -744,6 +748,7 @@ mod tests { &platform.drive, &document_2, &data_contract, + document_type, Some(&transaction), ); @@ -863,6 +868,7 @@ mod tests { } mod build_withdrawal_transactions_from_documents { + use dpp::data_contract::DriveContractExt; use dpp::{ document::document_stub::DocumentStub, identity::state_transition::identity_credit_withdrawal_transition::Pooling, @@ -894,10 +900,15 @@ mod tests { }), ); + let document_type = data_contract + .document_type_for_name(withdrawals_contract::types::WITHDRAWAL) + .expect("expected to get document type"); + setup_document( &platform.drive, &document_1, &data_contract, + document_type, Some(&transaction), ); @@ -917,6 +928,7 @@ mod tests { &platform.drive, &document_2, &data_contract, + document_type, Some(&transaction), ); diff --git a/packages/rs-drive/src/common/helpers/mod.rs b/packages/rs-drive/src/common/helpers/mod.rs index 990fed2c0e5..ece28e30146 100644 --- a/packages/rs-drive/src/common/helpers/mod.rs +++ b/packages/rs-drive/src/common/helpers/mod.rs @@ -1,2 +1,3 @@ pub mod epoch; pub mod identities; +pub mod setup; diff --git a/packages/rs-drive/src/tests/helpers/setup.rs b/packages/rs-drive/src/common/helpers/setup.rs similarity index 78% rename from packages/rs-drive/src/tests/helpers/setup.rs rename to packages/rs-drive/src/common/helpers/setup.rs index 89e503ad453..a062379b4f6 100644 --- a/packages/rs-drive/src/tests/helpers/setup.rs +++ b/packages/rs-drive/src/common/helpers/setup.rs @@ -37,6 +37,12 @@ use crate::drive::config::DriveConfig; use crate::drive::Drive; use crate::fee_pools::epochs::Epoch; +use crate::drive::object_size_info::DocumentInfo::{ + DocumentRefAndSerialization, DocumentRefWithoutSerialization, +}; +use crate::drive::object_size_info::{DocumentAndContractInfo, OwnedDocumentInfo}; +use dpp::data_contract::document_type::DocumentType; +use dpp::document::document_stub::DocumentStub; use dpp::{ contracts::withdrawals_contract, prelude::{DataContract, Document}, @@ -107,14 +113,25 @@ pub fn setup_document( drive: &Drive, document: &Document, data_contract: &DataContract, + document_type: &DocumentType, transaction: TransactionArg, ) { + //todo: remove this hack + let serialized_document = document + .to_buffer() + .expect("expected to serialize to buffer"); + let document_stub = DocumentStub::from_cbor(&serialized_document, None, None) + .expect("expected to convert to document stub"); drive - .add_serialized_document_for_serialized_contract( - &document.to_buffer().unwrap(), - &data_contract.to_cbor().unwrap(), - withdrawals_contract::types::WITHDRAWAL, - Some(data_contract.owner_id.to_buffer()), + .add_document_for_contract( + DocumentAndContractInfo { + owned_document_info: OwnedDocumentInfo { + document_info: DocumentRefWithoutSerialization((&document_stub, None)), + owner_id: None, + }, + contract: data_contract, + document_type, + }, false, BlockInfo { time_ms: 1, @@ -122,7 +139,6 @@ pub fn setup_document( epoch: Epoch::new(1), }, true, - None, transaction, ) .unwrap(); diff --git a/packages/rs-drive/src/drive/batch/drive_op_batch/mod.rs b/packages/rs-drive/src/drive/batch/drive_op_batch/mod.rs index 52b36b41007..1046c58366a 100644 --- a/packages/rs-drive/src/drive/batch/drive_op_batch/mod.rs +++ b/packages/rs-drive/src/drive/batch/drive_op_batch/mod.rs @@ -168,6 +168,9 @@ impl Drive { block_info: &BlockInfo, transaction: TransactionArg, ) -> Result { + if operations.is_empty() { + return Ok(FeeResult::default()); + } let mut drive_operations = vec![]; let mut estimated_costs_only_with_layer_info = if apply { None::> diff --git a/packages/rs-drive/src/drive/batch/drive_op_batch/withdrawals.rs b/packages/rs-drive/src/drive/batch/drive_op_batch/withdrawals.rs index d6c95b11902..9ea9f7ae59c 100644 --- a/packages/rs-drive/src/drive/batch/drive_op_batch/withdrawals.rs +++ b/packages/rs-drive/src/drive/batch/drive_op_batch/withdrawals.rs @@ -41,7 +41,7 @@ pub enum WithdrawalOperationType<'a> { /// Insert Core Transaction into queue InsertTransactions { /// transaction id bytes - transactions: &'a [WithdrawalTransaction], + withdrawal_transactions: &'a [WithdrawalTransaction], }, /// Delete withdrawal DeleteWithdrawalTransaction { @@ -62,89 +62,19 @@ impl DriveOperationConverter for WithdrawalOperationType<'_> { ) -> Result, Error> { match self { WithdrawalOperationType::InsertExpiredIndex { index } => { - let mut drive_operations = vec![]; - - let index_bytes = index.to_be_bytes(); - - let path = get_withdrawal_transactions_expired_ids_path_vec(); - - drive.batch_insert( - crate::drive::object_size_info::PathKeyElementInfo::PathKeyElement::<'_, 1>(( - path, - index_bytes.to_vec(), - Element::Item(vec![], None), - )), - &mut drive_operations, - )?; - - Ok(drive_operations) + drive.insert_withdrawal_expired_index(index) } WithdrawalOperationType::DeleteExpiredIndex { key } => { - let mut drive_operations = vec![]; - - let path: [&[u8]; 2] = get_withdrawal_transactions_expired_ids_path(); - - drive.batch_delete( - path, - key, - BatchDeleteApplyType::StatefulBatchDelete { - is_known_to_be_subtree_with_sum: Some((false, false)), - }, - transaction, - &mut drive_operations, - )?; - - Ok(drive_operations) + drive.delete_withdrawal_expired_index(key, transaction) } WithdrawalOperationType::UpdateIndexCounter { index } => { - let mut drive_operations = vec![]; - - let path = get_withdrawal_root_path_vec(); - - drive.batch_insert( - crate::drive::object_size_info::PathKeyElementInfo::PathKeyElement::<'_, 1>(( - path, - WITHDRAWAL_TRANSACTIONS_COUNTER_ID.to_vec(), - Element::Item(index.to_be_bytes().to_vec(), None), - )), - &mut drive_operations, - )?; - - Ok(drive_operations) - } - WithdrawalOperationType::InsertTransactions { transactions } => { - let mut drive_operations = vec![]; - - let path = get_withdrawal_transactions_queue_path_vec(); - - for (id, bytes) in transactions { - drive.batch_insert( - crate::drive::object_size_info::PathKeyElementInfo::PathKeyElement::<'_, 1>( - (path.clone(), id.clone(), Element::Item(bytes.clone(), None)), - ), - &mut drive_operations, - )?; - } - - Ok(drive_operations) + drive.update_transaction_index_counter(index) } + WithdrawalOperationType::InsertTransactions { + withdrawal_transactions, + } => drive.insert_withdrawal_transactions(withdrawal_transactions), WithdrawalOperationType::DeleteWithdrawalTransaction { id } => { - let mut drive_operations = vec![]; - - let path = get_withdrawal_transactions_queue_path(); - - drive.batch_delete( - path, - &id, - // we know that we are not deleting a subtree - BatchDeleteApplyType::StatefulBatchDelete { - is_known_to_be_subtree_with_sum: Some((false, false)), - }, - transaction, - &mut drive_operations, - )?; - - Ok(drive_operations) + drive.delete_withdrawal_transaction(id.as_slice(), transaction) } } } diff --git a/packages/rs-drive/src/drive/contract/mod.rs b/packages/rs-drive/src/drive/contract/mod.rs index b4dd0adbdc3..b79470dc7ea 100644 --- a/packages/rs-drive/src/drive/contract/mod.rs +++ b/packages/rs-drive/src/drive/contract/mod.rs @@ -1037,7 +1037,7 @@ mod tests { use crate::drive::Drive; use dpp::data_contract::extra::common::json_document_to_cbor; - use crate::tests::helpers::setup::setup_drive_with_initial_state_structure; + use crate::common::helpers::setup::setup_drive_with_initial_state_structure; fn setup_deep_nested_50_contract() -> (Drive, Contract, Vec) { // Todo: make TempDir based on _prefix diff --git a/packages/rs-drive/src/drive/document/insert.rs b/packages/rs-drive/src/drive/document/insert.rs index a8d69af1edb..8ca59979505 100644 --- a/packages/rs-drive/src/drive/document/insert.rs +++ b/packages/rs-drive/src/drive/document/insert.rs @@ -32,6 +32,7 @@ //! This module implements functions in Drive relevant to inserting documents. //! +use dpp::data_contract::document_type::random_document::CreateRandomDocument; use dpp::data_contract::document_type::{encode_unsigned_integer, IndexLevel}; use dpp::data_contract::DriveContractExt; use grovedb::batch::key_info::KeyInfo; diff --git a/packages/rs-drive/src/drive/document/update.rs b/packages/rs-drive/src/drive/document/update.rs index b20b2d657c5..2d1d81a5212 100644 --- a/packages/rs-drive/src/drive/document/update.rs +++ b/packages/rs-drive/src/drive/document/update.rs @@ -55,13 +55,14 @@ use crate::drive::document::{ }; use crate::drive::flags::StorageFlags; use crate::drive::object_size_info::DocumentInfo::{ - DocumentRefAndSerialization, DocumentWithoutSerialization, + DocumentEstimatedAverageSize, DocumentRefAndSerialization, DocumentRefWithoutSerialization, + DocumentWithoutSerialization, }; use dpp::document::document_stub::DocumentStub; use crate::drive::object_size_info::PathKeyElementInfo::PathKeyRefElement; use crate::drive::object_size_info::{ - DocumentAndContractInfo, DriveKeyInfo, OwnedDocumentInfo, PathKeyInfo, + DocumentAndContractInfo, DocumentInfo, DriveKeyInfo, OwnedDocumentInfo, PathKeyInfo, }; use crate::drive::Drive; use crate::error::drive::DriveError; @@ -301,179 +302,122 @@ impl Drive { let contract = document_and_contract_info.contract; let document_type = document_and_contract_info.document_type; let owner_id = document_and_contract_info.owned_document_info.owner_id; - - if let DocumentRefAndSerialization((document, _serialized_document, ref storage_flags)) = - document_and_contract_info.owned_document_info.document_info - { - // we need to construct the path for documents on the contract - // the path is - // * Document and Contract root tree - // * Contract ID recovered from document - // * 0 to signify Documents and not Contract - let contract_document_type_path = - contract_document_type_path(contract.id.as_bytes(), document_type.name.as_str()); - - let contract_documents_primary_key_path = contract_documents_primary_key_path( - contract.id.as_bytes(), - document_type.name.as_str(), - ); - - let document_reference = make_document_reference( - document, - document_and_contract_info.document_type, - storage_flags.as_ref().map(|flags| flags.as_ref()), - ); - - // next we need to get the old document from storage - let old_document_element = if document_type.documents_keep_history { - let contract_documents_keeping_history_primary_key_path_for_document_id = - contract_documents_keeping_history_primary_key_path_for_document_id( - contract.id.as_bytes(), - document_type.name.as_str(), - document.id.as_slice(), - ); - // When keeping document history the 0 is a reference that points to the current value - // O is just on one byte, so we have at most one hop of size 1 (1 byte) - self.grove_get( - contract_documents_keeping_history_primary_key_path_for_document_id, - &[0], - QueryType::StatefulQuery, - transaction, - &mut batch_operations, - )? - } else { - self.grove_get_raw( - contract_documents_primary_key_path, - document.id.as_slice(), - DirectQueryType::StatefulDirectQuery, - transaction, - &mut batch_operations, - )? - }; - - // we need to store the document for it's primary key - // we should be overriding if the document_type does not have history enabled - self.add_document_to_primary_storage( - &document_and_contract_info, - block_info, - true, - estimated_costs_only_with_layer_info, - transaction, - &mut batch_operations, - )?; - - let old_document_info = if let Some(old_document_element) = old_document_element { - if let Element::Item(old_serialized_document, element_flags) = old_document_element - { - let document = DocumentStub::from_cbor( - old_serialized_document.as_slice(), - None, - owner_id, - )?; - let storage_flags = StorageFlags::map_some_element_flags_ref(&element_flags)?; - Ok(DocumentWithoutSerialization(( - document, - storage_flags.map(Cow::Owned), - ))) + match document_and_contract_info.owned_document_info.document_info { + DocumentRefAndSerialization((document, _, ref storage_flags)) + | DocumentRefWithoutSerialization((document, ref storage_flags)) => { + // we need to construct the path for documents on the contract + // the path is + // * Document and Contract root tree + // * Contract ID recovered from document + // * 0 to signify Documents and not Contract + let contract_document_type_path = contract_document_type_path( + contract.id.as_bytes(), + document_type.name.as_str(), + ); + + let contract_documents_primary_key_path = contract_documents_primary_key_path( + contract.id.as_bytes(), + document_type.name.as_str(), + ); + + let document_reference = make_document_reference( + document, + document_and_contract_info.document_type, + storage_flags.as_ref().map(|flags| flags.as_ref()), + ); + + // next we need to get the old document from storage + let old_document_element = if document_type.documents_keep_history { + let contract_documents_keeping_history_primary_key_path_for_document_id = + contract_documents_keeping_history_primary_key_path_for_document_id( + contract.id.as_bytes(), + document_type.name.as_str(), + document.id.as_slice(), + ); + // When keeping document history the 0 is a reference that points to the current value + // O is just on one byte, so we have at most one hop of size 1 (1 byte) + self.grove_get( + contract_documents_keeping_history_primary_key_path_for_document_id, + &[0], + QueryType::StatefulQuery, + transaction, + &mut batch_operations, + )? } else { - Err(Error::Drive(DriveError::CorruptedDocumentNotItem( - "old document is not an item", - ))) - }? - } else { - return Err(Error::Drive(DriveError::UpdatingDocumentThatDoesNotExist( - "document being updated does not exist", - ))); - }; - - let mut batch_insertion_cache: HashSet>> = HashSet::new(); - // fourth we need to store a reference to the document for each index - for index in &document_type.indices { - // at this point the contract path is to the contract documents - // for each index the top index component will already have been added - // when the contract itself was created - let mut index_path: Vec> = contract_document_type_path - .iter() - .map(|&x| Vec::from(x)) - .collect(); - let top_index_property = index.properties.get(0).ok_or(Error::Drive( - DriveError::CorruptedContractIndexes("invalid contract indices"), - ))?; - index_path.push(Vec::from(top_index_property.name.as_bytes())); - - // with the example of the dashpay contract's first index - // the index path is now something like Contracts/ContractID/Documents(1)/$ownerId - let document_top_field = document - .get_raw_for_document_type(&top_index_property.name, document_type, owner_id)? - .unwrap_or_default(); - - let old_document_top_field = old_document_info - .get_raw_for_document_type( - &top_index_property.name, - document_type, - owner_id, - None, + self.grove_get_raw( + contract_documents_primary_key_path, + document.id.as_slice(), + DirectQueryType::StatefulDirectQuery, + transaction, + &mut batch_operations, )? - .unwrap_or_default(); - - // if we are not applying that means we are trying to get worst case costs - // which would entail a change on every index - let mut change_occurred_on_index = match &old_document_top_field { - DriveKeyInfo::Key(k) => &document_top_field != k, - DriveKeyInfo::KeyRef(k) => document_top_field.as_slice() != *k, - DriveKeyInfo::KeySize(_) => { - // we should assume true in this worst case cost scenario - true - } }; - if change_occurred_on_index { - // here we are inserting an empty tree that will have a subtree of all other index properties - let mut qualified_path = index_path.clone(); - qualified_path.push(document_top_field.clone()); - - if !batch_insertion_cache.contains(&qualified_path) { - let inserted = self.batch_insert_empty_tree_if_not_exists( - PathKeyInfo::PathKeyRef::<0>(( - index_path.clone(), - document_top_field.as_slice(), - )), - storage_flags.as_ref().map(|flags| flags.as_ref()), - BatchInsertTreeApplyType::StatefulBatchInsertTree, - transaction, - previous_batch_operations, - &mut batch_operations, + // we need to store the document for it's primary key + // we should be overriding if the document_type does not have history enabled + self.add_document_to_primary_storage( + &document_and_contract_info, + block_info, + true, + estimated_costs_only_with_layer_info, + transaction, + &mut batch_operations, + )?; + + let old_document_info = if let Some(old_document_element) = old_document_element { + if let Element::Item(old_serialized_document, element_flags) = + old_document_element + { + let document = DocumentStub::from_cbor( + old_serialized_document.as_slice(), + None, + owner_id, )?; - if inserted { - batch_insertion_cache.insert(qualified_path); - } - } - } - - let mut all_fields_null = document_top_field.is_empty(); - - let mut old_index_path: Vec = index_path - .iter() - .map(|path_item| DriveKeyInfo::Key(path_item.clone())) - .collect(); - // we push the actual value of the index path - index_path.push(document_top_field); - // the index path is now something like Contracts/ContractID/Documents(1)/$ownerId/ - - old_index_path.push(old_document_top_field); + let storage_flags = + StorageFlags::map_some_element_flags_ref(&element_flags)?; + Ok(DocumentWithoutSerialization(( + document, + storage_flags.map(Cow::Owned), + ))) + } else { + Err(Error::Drive(DriveError::CorruptedDocumentNotItem( + "old document is not an item", + ))) + }? + } else { + return Err(Error::Drive(DriveError::UpdatingDocumentThatDoesNotExist( + "document being updated does not exist", + ))); + }; - for i in 1..index.properties.len() { - let index_property = index.properties.get(i).ok_or(Error::Drive( + let mut batch_insertion_cache: HashSet>> = HashSet::new(); + // fourth we need to store a reference to the document for each index + for index in &document_type.indices { + // at this point the contract path is to the contract documents + // for each index the top index component will already have been added + // when the contract itself was created + let mut index_path: Vec> = contract_document_type_path + .iter() + .map(|&x| Vec::from(x)) + .collect(); + let top_index_property = index.properties.get(0).ok_or(Error::Drive( DriveError::CorruptedContractIndexes("invalid contract indices"), ))?; + index_path.push(Vec::from(top_index_property.name.as_bytes())); - let document_index_field = document - .get_raw_for_document_type(&index_property.name, document_type, owner_id)? + // with the example of the dashpay contract's first index + // the index path is now something like Contracts/ContractID/Documents(1)/$ownerId + let document_top_field = document + .get_raw_for_document_type( + &top_index_property.name, + document_type, + owner_id, + )? .unwrap_or_default(); - let old_document_index_field = old_document_info + let old_document_top_field = old_document_info .get_raw_for_document_type( - &index_property.name, + &top_index_property.name, document_type, owner_id, None, @@ -482,9 +426,9 @@ impl Drive { // if we are not applying that means we are trying to get worst case costs // which would entail a change on every index - change_occurred_on_index |= match &old_document_index_field { - DriveKeyInfo::Key(k) => &document_index_field != k, - DriveKeyInfo::KeyRef(k) => document_index_field != *k, + let mut change_occurred_on_index = match &old_document_top_field { + DriveKeyInfo::Key(k) => &document_top_field != k, + DriveKeyInfo::KeyRef(k) => document_top_field.as_slice() != *k, DriveKeyInfo::KeySize(_) => { // we should assume true in this worst case cost scenario true @@ -493,15 +437,14 @@ impl Drive { if change_occurred_on_index { // here we are inserting an empty tree that will have a subtree of all other index properties - let mut qualified_path = index_path.clone(); - qualified_path.push(index_property.name.as_bytes().to_vec()); + qualified_path.push(document_top_field.clone()); if !batch_insertion_cache.contains(&qualified_path) { let inserted = self.batch_insert_empty_tree_if_not_exists( PathKeyInfo::PathKeyRef::<0>(( index_path.clone(), - index_property.name.as_bytes(), + document_top_field.as_slice(), )), storage_flags.as_ref().map(|flags| flags.as_ref()), BatchInsertTreeApplyType::StatefulBatchInsertTree, @@ -515,132 +458,212 @@ impl Drive { } } - index_path.push(Vec::from(index_property.name.as_bytes())); - old_index_path - .push(DriveKeyInfo::Key(Vec::from(index_property.name.as_bytes()))); + let mut all_fields_null = document_top_field.is_empty(); + + let mut old_index_path: Vec = index_path + .iter() + .map(|path_item| DriveKeyInfo::Key(path_item.clone())) + .collect(); + // we push the actual value of the index path + index_path.push(document_top_field); + // the index path is now something like Contracts/ContractID/Documents(1)/$ownerId/ + + old_index_path.push(old_document_top_field); + + for i in 1..index.properties.len() { + let index_property = index.properties.get(i).ok_or(Error::Drive( + DriveError::CorruptedContractIndexes("invalid contract indices"), + ))?; + + let document_index_field = document + .get_raw_for_document_type( + &index_property.name, + document_type, + owner_id, + )? + .unwrap_or_default(); + + let old_document_index_field = old_document_info + .get_raw_for_document_type( + &index_property.name, + document_type, + owner_id, + None, + )? + .unwrap_or_default(); + + // if we are not applying that means we are trying to get worst case costs + // which would entail a change on every index + change_occurred_on_index |= match &old_document_index_field { + DriveKeyInfo::Key(k) => &document_index_field != k, + DriveKeyInfo::KeyRef(k) => document_index_field != *k, + DriveKeyInfo::KeySize(_) => { + // we should assume true in this worst case cost scenario + true + } + }; + + if change_occurred_on_index { + // here we are inserting an empty tree that will have a subtree of all other index properties + + let mut qualified_path = index_path.clone(); + qualified_path.push(index_property.name.as_bytes().to_vec()); + + if !batch_insertion_cache.contains(&qualified_path) { + let inserted = self.batch_insert_empty_tree_if_not_exists( + PathKeyInfo::PathKeyRef::<0>(( + index_path.clone(), + index_property.name.as_bytes(), + )), + storage_flags.as_ref().map(|flags| flags.as_ref()), + BatchInsertTreeApplyType::StatefulBatchInsertTree, + transaction, + previous_batch_operations, + &mut batch_operations, + )?; + if inserted { + batch_insertion_cache.insert(qualified_path); + } + } + } - // Iteration 1. the index path is now something like Contracts/ContractID/Documents(1)/$ownerId//toUserId - // Iteration 2. the index path is now something like Contracts/ContractID/Documents(1)/$ownerId//toUserId//accountReference + index_path.push(Vec::from(index_property.name.as_bytes())); + old_index_path + .push(DriveKeyInfo::Key(Vec::from(index_property.name.as_bytes()))); + + // Iteration 1. the index path is now something like Contracts/ContractID/Documents(1)/$ownerId//toUserId + // Iteration 2. the index path is now something like Contracts/ContractID/Documents(1)/$ownerId//toUserId//accountReference + + if change_occurred_on_index { + // here we are inserting an empty tree that will have a subtree of all other index properties + + let mut qualified_path = index_path.clone(); + qualified_path.push(document_index_field.clone()); + + if !batch_insertion_cache.contains(&qualified_path) { + let inserted = self.batch_insert_empty_tree_if_not_exists( + PathKeyInfo::PathKeyRef::<0>(( + index_path.clone(), + document_index_field.as_slice(), + )), + storage_flags.as_ref().map(|flags| flags.as_ref()), + BatchInsertTreeApplyType::StatefulBatchInsertTree, + transaction, + previous_batch_operations, + &mut batch_operations, + )?; + if inserted { + batch_insertion_cache.insert(qualified_path); + } + } + } - if change_occurred_on_index { - // here we are inserting an empty tree that will have a subtree of all other index properties + all_fields_null &= document_index_field.is_empty(); - let mut qualified_path = index_path.clone(); - qualified_path.push(document_index_field.clone()); + // we push the actual value of the index path, both for the new and the old + index_path.push(document_index_field); + old_index_path.push(old_document_index_field); + // Iteration 1. the index path is now something like Contracts/ContractID/Documents(1)/$ownerId//toUserId// + // Iteration 2. the index path is now something like Contracts/ContractID/Documents(1)/$ownerId//toUserId//accountReference/ + } - if !batch_insertion_cache.contains(&qualified_path) { - let inserted = self.batch_insert_empty_tree_if_not_exists( - PathKeyInfo::PathKeyRef::<0>(( - index_path.clone(), - document_index_field.as_slice(), - )), + if change_occurred_on_index { + // we first need to delete the old values + // unique indexes will be stored under key "0" + // non unique indices should have a tree at key "0" that has all elements based off of primary key + + let mut key_info_path = KeyInfoPath::from_vec( + old_index_path + .into_iter() + .map(|key_info| match key_info { + Key(key) => KnownKey(key), + KeyRef(key_ref) => KnownKey(key_ref.to_vec()), + KeySize(key_info) => key_info, + }) + .collect::>(), + ); + + if !index.unique { + key_info_path.push(KnownKey(vec![0])); + + // here we should return an error if the element already exists + self.batch_delete_up_tree_while_empty( + key_info_path, + document.id.as_slice(), + Some(CONTRACT_DOCUMENTS_PATH_HEIGHT), + BatchDeleteUpTreeApplyType::StatefulBatchDelete { + is_known_to_be_subtree_with_sum: Some((false, false)), + }, + transaction, + previous_batch_operations, + &mut batch_operations, + )?; + } else { + // here we should return an error if the element already exists + self.batch_delete_up_tree_while_empty( + key_info_path, + &[0], + Some(CONTRACT_DOCUMENTS_PATH_HEIGHT), + BatchDeleteUpTreeApplyType::StatefulBatchDelete { + is_known_to_be_subtree_with_sum: Some((false, false)), + }, + transaction, + previous_batch_operations, + &mut batch_operations, + )?; + } + + // unique indexes will be stored under key "0" + // non unique indices should have a tree at key "0" that has all elements based off of primary key + if !index.unique || all_fields_null { + // here we are inserting an empty tree that will have a subtree of all other index properties + self.batch_insert_empty_tree_if_not_exists( + PathKeyInfo::PathKeyRef::<0>((index_path.clone(), &[0])), storage_flags.as_ref().map(|flags| flags.as_ref()), BatchInsertTreeApplyType::StatefulBatchInsertTree, transaction, previous_batch_operations, &mut batch_operations, )?; - if inserted { - batch_insertion_cache.insert(qualified_path); + index_path.push(vec![0]); + + // here we should return an error if the element already exists + self.batch_insert( + PathKeyRefElement::<0>(( + index_path, + document.id.as_slice(), + document_reference.clone(), + )), + &mut batch_operations, + )?; + } else { + // in one update you can't insert an element twice, so need to check the cache + // here we should return an error if the element already exists + let inserted = self.batch_insert_if_not_exists( + PathKeyRefElement::<0>(( + index_path, + &[0], + document_reference.clone(), + )), + BatchInsertApplyType::StatefulBatchInsert, + transaction, + &mut batch_operations, + )?; + if !inserted { + return Err(Error::Drive(DriveError::CorruptedContractIndexes( + "index already exists", + ))); } } } - - all_fields_null &= document_index_field.is_empty(); - - // we push the actual value of the index path, both for the new and the old - index_path.push(document_index_field); - old_index_path.push(old_document_index_field); - // Iteration 1. the index path is now something like Contracts/ContractID/Documents(1)/$ownerId//toUserId// - // Iteration 2. the index path is now something like Contracts/ContractID/Documents(1)/$ownerId//toUserId//accountReference/ - } - - if change_occurred_on_index { - // we first need to delete the old values - // unique indexes will be stored under key "0" - // non unique indices should have a tree at key "0" that has all elements based off of primary key - - let mut key_info_path = KeyInfoPath::from_vec( - old_index_path - .into_iter() - .map(|key_info| match key_info { - Key(key) => KnownKey(key), - KeyRef(key_ref) => KnownKey(key_ref.to_vec()), - KeySize(key_info) => key_info, - }) - .collect::>(), - ); - - if !index.unique { - key_info_path.push(KnownKey(vec![0])); - - // here we should return an error if the element already exists - self.batch_delete_up_tree_while_empty( - key_info_path, - document.id.as_slice(), - Some(CONTRACT_DOCUMENTS_PATH_HEIGHT), - BatchDeleteUpTreeApplyType::StatefulBatchDelete { - is_known_to_be_subtree_with_sum: Some((false, false)), - }, - transaction, - previous_batch_operations, - &mut batch_operations, - )?; - } else { - // here we should return an error if the element already exists - self.batch_delete_up_tree_while_empty( - key_info_path, - &[0], - Some(CONTRACT_DOCUMENTS_PATH_HEIGHT), - BatchDeleteUpTreeApplyType::StatefulBatchDelete { - is_known_to_be_subtree_with_sum: Some((false, false)), - }, - transaction, - previous_batch_operations, - &mut batch_operations, - )?; - } - - // unique indexes will be stored under key "0" - // non unique indices should have a tree at key "0" that has all elements based off of primary key - if !index.unique || all_fields_null { - // here we are inserting an empty tree that will have a subtree of all other index properties - self.batch_insert_empty_tree_if_not_exists( - PathKeyInfo::PathKeyRef::<0>((index_path.clone(), &[0])), - storage_flags.as_ref().map(|flags| flags.as_ref()), - BatchInsertTreeApplyType::StatefulBatchInsertTree, - transaction, - previous_batch_operations, - &mut batch_operations, - )?; - index_path.push(vec![0]); - - // here we should return an error if the element already exists - self.batch_insert( - PathKeyRefElement::<0>(( - index_path, - document.id.as_slice(), - document_reference.clone(), - )), - &mut batch_operations, - )?; - } else { - // in one update you can't insert an element twice, so need to check the cache - // here we should return an error if the element already exists - let inserted = self.batch_insert_if_not_exists( - PathKeyRefElement::<0>((index_path, &[0], document_reference.clone())), - BatchInsertApplyType::StatefulBatchInsert, - transaction, - &mut batch_operations, - )?; - if !inserted { - return Err(Error::Drive(DriveError::CorruptedContractIndexes( - "index already exists", - ))); - } - } } } + DocumentWithoutSerialization(_) => { + todo!() + } + DocumentEstimatedAverageSize(_) => { + unreachable!() + } } Ok(batch_operations) } diff --git a/packages/rs-drive/src/drive/fee_pools/epochs/credit_distribution_pools.rs b/packages/rs-drive/src/drive/fee_pools/epochs/credit_distribution_pools.rs index be00cbbee8a..daa8be714ab 100644 --- a/packages/rs-drive/src/drive/fee_pools/epochs/credit_distribution_pools.rs +++ b/packages/rs-drive/src/drive/fee_pools/epochs/credit_distribution_pools.rs @@ -147,9 +147,9 @@ impl Drive { mod tests { use super::*; + use crate::common::helpers::setup::setup_drive_with_initial_state_structure; use crate::drive::batch::GroveDbOpBatch; use crate::fee_pools::epochs_root_tree_key_constants::KEY_STORAGE_FEE_POOL; - use crate::tests::helpers::setup::setup_drive_with_initial_state_structure; mod get_epoch_storage_credits_for_distribution { use super::*; diff --git a/packages/rs-drive/src/drive/fee_pools/epochs/mod.rs b/packages/rs-drive/src/drive/fee_pools/epochs/mod.rs index 4e49e71c0f2..ff07c475330 100644 --- a/packages/rs-drive/src/drive/fee_pools/epochs/mod.rs +++ b/packages/rs-drive/src/drive/fee_pools/epochs/mod.rs @@ -59,7 +59,7 @@ impl Drive { mod tests { use super::*; - use crate::tests::helpers::setup::setup_drive_with_initial_state_structure; + use crate::common::helpers::setup::setup_drive_with_initial_state_structure; mod is_epoch_tree_exists { use super::*; diff --git a/packages/rs-drive/src/drive/fee_pools/epochs/proposers.rs b/packages/rs-drive/src/drive/fee_pools/epochs/proposers.rs index 68678520826..7f4067ba385 100644 --- a/packages/rs-drive/src/drive/fee_pools/epochs/proposers.rs +++ b/packages/rs-drive/src/drive/fee_pools/epochs/proposers.rs @@ -148,8 +148,8 @@ impl Drive { #[cfg(test)] mod tests { use super::*; + use crate::common::helpers::setup::setup_drive_with_initial_state_structure; use crate::drive::batch::GroveDbOpBatch; - use crate::tests::helpers::setup::setup_drive_with_initial_state_structure; mod get_epochs_proposer_block_count { use super::*; diff --git a/packages/rs-drive/src/drive/fee_pools/epochs/start_block.rs b/packages/rs-drive/src/drive/fee_pools/epochs/start_block.rs index 591661c32a3..626baa4dc46 100644 --- a/packages/rs-drive/src/drive/fee_pools/epochs/start_block.rs +++ b/packages/rs-drive/src/drive/fee_pools/epochs/start_block.rs @@ -144,7 +144,7 @@ impl Drive { #[cfg(test)] mod tests { use super::*; - use crate::tests::helpers::setup::setup_drive_with_initial_state_structure; + use crate::common::helpers::setup::setup_drive_with_initial_state_structure; mod get_epoch_start_block_height { use super::*; diff --git a/packages/rs-drive/src/drive/fee_pools/epochs/start_time.rs b/packages/rs-drive/src/drive/fee_pools/epochs/start_time.rs index 4e0cbe1cd17..5db343933c0 100644 --- a/packages/rs-drive/src/drive/fee_pools/epochs/start_time.rs +++ b/packages/rs-drive/src/drive/fee_pools/epochs/start_time.rs @@ -72,7 +72,7 @@ impl Drive { #[cfg(test)] mod tests { - use crate::tests::helpers::setup::setup_drive_with_initial_state_structure; + use crate::common::helpers::setup::setup_drive_with_initial_state_structure; use super::*; diff --git a/packages/rs-drive/src/drive/fee_pools/mod.rs b/packages/rs-drive/src/drive/fee_pools/mod.rs index 8a154790ce0..92924a8dc32 100644 --- a/packages/rs-drive/src/drive/fee_pools/mod.rs +++ b/packages/rs-drive/src/drive/fee_pools/mod.rs @@ -181,7 +181,7 @@ impl Drive { mod tests { use super::*; - use crate::tests::helpers::setup::setup_drive_with_initial_state_structure; + use crate::common::helpers::setup::setup_drive_with_initial_state_structure; mod add_update_epoch_storage_fee_pools_operations { use super::*; diff --git a/packages/rs-drive/src/drive/fee_pools/pending_epoch_refunds.rs b/packages/rs-drive/src/drive/fee_pools/pending_epoch_refunds.rs index 5376da02281..f2b90110c30 100644 --- a/packages/rs-drive/src/drive/fee_pools/pending_epoch_refunds.rs +++ b/packages/rs-drive/src/drive/fee_pools/pending_epoch_refunds.rs @@ -219,7 +219,7 @@ pub fn add_update_pending_epoch_refunds_operations( #[cfg(test)] mod tests { use super::*; - use crate::tests::helpers::setup::setup_drive_with_initial_state_structure; + use crate::common::helpers::setup::setup_drive_with_initial_state_structure; mod fetch_and_add_pending_epoch_refunds_to_collection { use super::*; diff --git a/packages/rs-drive/src/drive/fee_pools/storage_fee_distribution_pool.rs b/packages/rs-drive/src/drive/fee_pools/storage_fee_distribution_pool.rs index 59639002632..de98f680bb5 100644 --- a/packages/rs-drive/src/drive/fee_pools/storage_fee_distribution_pool.rs +++ b/packages/rs-drive/src/drive/fee_pools/storage_fee_distribution_pool.rs @@ -64,7 +64,7 @@ impl Drive { mod tests { use super::*; - use crate::tests::helpers::setup::{setup_drive, setup_drive_with_initial_state_structure}; + use crate::common::helpers::setup::{setup_drive, setup_drive_with_initial_state_structure}; mod get_storage_fees_from_distribution_pool { use super::*; diff --git a/packages/rs-drive/src/drive/fee_pools/unpaid_epoch.rs b/packages/rs-drive/src/drive/fee_pools/unpaid_epoch.rs index edd867df892..c298ea7b448 100644 --- a/packages/rs-drive/src/drive/fee_pools/unpaid_epoch.rs +++ b/packages/rs-drive/src/drive/fee_pools/unpaid_epoch.rs @@ -68,7 +68,7 @@ impl Drive { mod tests { use super::*; - use crate::tests::helpers::setup::{setup_drive, setup_drive_with_initial_state_structure}; + use crate::common::helpers::setup::{setup_drive, setup_drive_with_initial_state_structure}; mod get_unpaid_epoch_index { use super::*; diff --git a/packages/rs-drive/src/drive/genesis_time.rs b/packages/rs-drive/src/drive/genesis_time.rs index ca9f41ba713..8dc0488bbca 100644 --- a/packages/rs-drive/src/drive/genesis_time.rs +++ b/packages/rs-drive/src/drive/genesis_time.rs @@ -77,7 +77,7 @@ impl Drive { mod tests { use super::*; - use crate::tests::helpers::setup::{setup_drive, setup_drive_with_initial_state_structure}; + use crate::common::helpers::setup::{setup_drive, setup_drive_with_initial_state_structure}; mod get_genesis_time { use super::*; diff --git a/packages/rs-drive/src/drive/identity/balance/prove.rs b/packages/rs-drive/src/drive/identity/balance/prove.rs index abc394d7206..9df7feb2999 100644 --- a/packages/rs-drive/src/drive/identity/balance/prove.rs +++ b/packages/rs-drive/src/drive/identity/balance/prove.rs @@ -28,8 +28,8 @@ impl Drive { #[cfg(test)] mod tests { use super::*; + use crate::common::helpers::setup::setup_drive_with_initial_state_structure; use crate::drive::block_info::BlockInfo; - use crate::tests::helpers::setup::setup_drive_with_initial_state_structure; use dpp::identity::Identity; mod prove_identity_balance { diff --git a/packages/rs-drive/src/drive/identity/balance/update.rs b/packages/rs-drive/src/drive/identity/balance/update.rs index b1f98fd5e9a..25f6e4000a0 100644 --- a/packages/rs-drive/src/drive/identity/balance/update.rs +++ b/packages/rs-drive/src/drive/identity/balance/update.rs @@ -475,7 +475,7 @@ mod tests { use crate::{ common::helpers::identities::create_test_identity, - tests::helpers::setup::setup_drive_with_initial_state_structure, + common::helpers::setup::setup_drive_with_initial_state_structure, }; mod add_to_identity_balance { diff --git a/packages/rs-drive/src/drive/identity/fetch/fetch_by_public_key_hashes.rs b/packages/rs-drive/src/drive/identity/fetch/fetch_by_public_key_hashes.rs index 33560d152a3..f4c2b720825 100644 --- a/packages/rs-drive/src/drive/identity/fetch/fetch_by_public_key_hashes.rs +++ b/packages/rs-drive/src/drive/identity/fetch/fetch_by_public_key_hashes.rs @@ -278,8 +278,8 @@ impl Drive { #[cfg(test)] mod tests { + use crate::common::helpers::setup::setup_drive; use crate::drive::block_info::BlockInfo; - use crate::tests::helpers::setup::setup_drive; use super::*; diff --git a/packages/rs-drive/src/drive/identity/fetch/full_identity.rs b/packages/rs-drive/src/drive/identity/fetch/full_identity.rs index a6c42ddc93a..249ae620099 100644 --- a/packages/rs-drive/src/drive/identity/fetch/full_identity.rs +++ b/packages/rs-drive/src/drive/identity/fetch/full_identity.rs @@ -152,7 +152,7 @@ impl Drive { #[cfg(test)] mod tests { use super::*; - use crate::tests::helpers::setup::setup_drive_with_initial_state_structure; + use crate::common::helpers::setup::setup_drive_with_initial_state_structure; mod fetch_full_identities { use super::*; diff --git a/packages/rs-drive/src/drive/identity/fetch/prove/full_identities_by_public_key_hashes.rs b/packages/rs-drive/src/drive/identity/fetch/prove/full_identities_by_public_key_hashes.rs index 1db2ee31859..c6d54d02c0a 100644 --- a/packages/rs-drive/src/drive/identity/fetch/prove/full_identities_by_public_key_hashes.rs +++ b/packages/rs-drive/src/drive/identity/fetch/prove/full_identities_by_public_key_hashes.rs @@ -56,8 +56,8 @@ impl Drive { #[cfg(test)] mod tests { use super::*; + use crate::common::helpers::setup::setup_drive_with_initial_state_structure; use crate::drive::block_info::BlockInfo; - use crate::tests::helpers::setup::setup_drive_with_initial_state_structure; use dpp::identity::Identity; use std::collections::BTreeMap; diff --git a/packages/rs-drive/src/drive/identity/fetch/prove/full_identity.rs b/packages/rs-drive/src/drive/identity/fetch/prove/full_identity.rs index 48a386aa7be..fd3443bd357 100644 --- a/packages/rs-drive/src/drive/identity/fetch/prove/full_identity.rs +++ b/packages/rs-drive/src/drive/identity/fetch/prove/full_identity.rs @@ -30,8 +30,8 @@ impl Drive { #[cfg(test)] mod tests { use super::*; + use crate::common::helpers::setup::setup_drive_with_initial_state_structure; use crate::drive::block_info::BlockInfo; - use crate::tests::helpers::setup::setup_drive_with_initial_state_structure; use dpp::identity::Identity; use grovedb::query_result_type::QueryResultType; diff --git a/packages/rs-drive/src/drive/identity/fetch/prove/identity_ids_by_public_key_hashes.rs b/packages/rs-drive/src/drive/identity/fetch/prove/identity_ids_by_public_key_hashes.rs index 83dbed107ca..d38600ec9be 100644 --- a/packages/rs-drive/src/drive/identity/fetch/prove/identity_ids_by_public_key_hashes.rs +++ b/packages/rs-drive/src/drive/identity/fetch/prove/identity_ids_by_public_key_hashes.rs @@ -29,8 +29,8 @@ impl Drive { #[cfg(test)] mod tests { use super::*; + use crate::common::helpers::setup::setup_drive_with_initial_state_structure; use crate::drive::block_info::BlockInfo; - use crate::tests::helpers::setup::setup_drive_with_initial_state_structure; use dpp::identity::Identity; use std::collections::BTreeMap; diff --git a/packages/rs-drive/src/drive/identity/insert.rs b/packages/rs-drive/src/drive/identity/insert.rs index 4162b1be9b2..8b866f85207 100644 --- a/packages/rs-drive/src/drive/identity/insert.rs +++ b/packages/rs-drive/src/drive/identity/insert.rs @@ -161,7 +161,7 @@ impl Drive { #[cfg(test)] mod tests { - use crate::{drive::block_info::BlockInfo, tests::helpers::setup::setup_drive}; + use crate::{common::helpers::setup::setup_drive, drive::block_info::BlockInfo}; use dpp::identity::Identity; use tempfile::TempDir; diff --git a/packages/rs-drive/src/drive/identity/key/fetch.rs b/packages/rs-drive/src/drive/identity/key/fetch.rs index c2b07b5d425..96fbfa5a905 100644 --- a/packages/rs-drive/src/drive/identity/key/fetch.rs +++ b/packages/rs-drive/src/drive/identity/key/fetch.rs @@ -504,8 +504,8 @@ impl Drive { #[cfg(test)] mod tests { + use crate::common::helpers::setup::setup_drive; use crate::drive::block_info::BlockInfo; - use crate::tests::helpers::setup::setup_drive; use dpp::identity::Identity; use super::*; diff --git a/packages/rs-drive/src/drive/identity/update.rs b/packages/rs-drive/src/drive/identity/update.rs index b24fd9995f6..5ef95937c8c 100644 --- a/packages/rs-drive/src/drive/identity/update.rs +++ b/packages/rs-drive/src/drive/identity/update.rs @@ -270,7 +270,7 @@ mod tests { use super::*; use dpp::prelude::*; - use crate::tests::helpers::setup::setup_drive_with_initial_state_structure; + use crate::common::helpers::setup::setup_drive_with_initial_state_structure; mod add_new_keys_to_identity { use super::*; diff --git a/packages/rs-drive/src/drive/identity/withdrawals/delete.rs b/packages/rs-drive/src/drive/identity/withdrawals/delete.rs new file mode 100644 index 00000000000..31a7092e4dd --- /dev/null +++ b/packages/rs-drive/src/drive/identity/withdrawals/delete.rs @@ -0,0 +1,33 @@ +use crate::drive::grove_operations::BatchDeleteApplyType; +use crate::drive::identity::withdrawals::paths::{ + get_withdrawal_transactions_queue_path, WithdrawalTransaction, +}; +use crate::drive::Drive; +use crate::error::Error; +use crate::fee::op::DriveOperation; +use grovedb::{Element, TransactionArg}; + +impl Drive { + pub(crate) fn delete_withdrawal_transaction( + &self, + id: &[u8], + transaction: TransactionArg, + ) -> Result<(Vec), Error> { + let mut drive_operations = vec![]; + + let path = get_withdrawal_transactions_queue_path(); + + self.batch_delete( + path, + id, + // we know that we are not deleting a subtree + BatchDeleteApplyType::StatefulBatchDelete { + is_known_to_be_subtree_with_sum: Some((false, false)), + }, + transaction, + &mut drive_operations, + )?; + + Ok(drive_operations) + } +} diff --git a/packages/rs-drive/src/drive/identity/withdrawals/expired_index.rs b/packages/rs-drive/src/drive/identity/withdrawals/expired_index.rs new file mode 100644 index 00000000000..e91937ab88c --- /dev/null +++ b/packages/rs-drive/src/drive/identity/withdrawals/expired_index.rs @@ -0,0 +1,54 @@ +use crate::drive::grove_operations::BatchDeleteApplyType; +use crate::drive::identity::withdrawals::paths::{ + get_withdrawal_transactions_expired_ids_path, get_withdrawal_transactions_expired_ids_path_vec, +}; +use crate::drive::Drive; +use crate::error::Error; +use crate::fee::op::DriveOperation; +use grovedb::{Element, TransactionArg}; + +impl Drive { + pub(crate) fn insert_withdrawal_expired_index( + &self, + index: u64, + ) -> Result<(Vec), Error> { + let mut drive_operations = vec![]; + + let index_bytes = index.to_be_bytes(); + + let path = get_withdrawal_transactions_expired_ids_path_vec(); + + self.batch_insert( + crate::drive::object_size_info::PathKeyElementInfo::PathKeyElement::<'_, 1>(( + path, + index_bytes.to_vec(), + Element::Item(vec![], None), + )), + &mut drive_operations, + )?; + + Ok(drive_operations) + } + + pub(crate) fn delete_withdrawal_expired_index( + &self, + key: &[u8], + transaction: TransactionArg, + ) -> Result<(Vec), Error> { + let mut drive_operations = vec![]; + + let path: [&[u8]; 2] = get_withdrawal_transactions_expired_ids_path(); + + self.batch_delete( + path, + key, + BatchDeleteApplyType::StatefulBatchDelete { + is_known_to_be_subtree_with_sum: Some((false, false)), + }, + transaction, + &mut drive_operations, + )?; + + Ok(drive_operations) + } +} diff --git a/packages/rs-drive/src/drive/identity/withdrawals/insert.rs b/packages/rs-drive/src/drive/identity/withdrawals/insert.rs new file mode 100644 index 00000000000..411fcade73c --- /dev/null +++ b/packages/rs-drive/src/drive/identity/withdrawals/insert.rs @@ -0,0 +1,33 @@ +use crate::drive::grove_operations::BatchDeleteApplyType; +use crate::drive::identity::withdrawals::paths::{ + get_withdrawal_transactions_queue_path_vec, WithdrawalTransaction, +}; +use crate::drive::object_size_info::PathKeyElementInfo::PathKeyElement; +use crate::drive::Drive; +use crate::error::Error; +use crate::fee::op::DriveOperation; +use grovedb::Element; + +impl Drive { + pub(crate) fn insert_withdrawal_transactions( + &self, + transactions: &[WithdrawalTransaction], + ) -> Result<(Vec), Error> { + let mut drive_operations = vec![]; + + let path = get_withdrawal_transactions_queue_path_vec(); + + for (id, bytes) in transactions { + self.batch_insert( + PathKeyElement::<'_, 1>(( + path.clone(), + id.clone(), + Element::Item(bytes.clone(), None), + )), + &mut drive_operations, + )?; + } + + Ok(drive_operations) + } +} diff --git a/packages/rs-drive/src/drive/identity/withdrawals/mod.rs b/packages/rs-drive/src/drive/identity/withdrawals/mod.rs index 0ffd527b2cf..7b10bb6ccb0 100644 --- a/packages/rs-drive/src/drive/identity/withdrawals/mod.rs +++ b/packages/rs-drive/src/drive/identity/withdrawals/mod.rs @@ -1,3 +1,9 @@ +/// Inserting a withdrawal +pub(crate) mod delete; +/// Inserting or Deleting an expired index +pub(crate) mod expired_index; +/// Inserting a withdrawal +pub(crate) mod insert; /// Functions and constants related to GroveDB paths pub mod paths; /// Functions related to withdrawal queue diff --git a/packages/rs-drive/src/drive/identity/withdrawals/paths.rs b/packages/rs-drive/src/drive/identity/withdrawals/paths.rs index ac6ee715add..592297df71d 100644 --- a/packages/rs-drive/src/drive/identity/withdrawals/paths.rs +++ b/packages/rs-drive/src/drive/identity/withdrawals/paths.rs @@ -14,8 +14,6 @@ pub type WithdrawalTransaction = (Vec, Vec); /// Add operations for creating initial withdrawal state structure pub fn add_initial_withdrawal_state_structure_operations(batch: &mut GroveDbOpBatch) { - batch.add_insert_empty_tree(vec![], vec![RootTree::WithdrawalTransactions as u8]); - batch.add_insert( vec![vec![RootTree::WithdrawalTransactions as u8]], WITHDRAWAL_TRANSACTIONS_COUNTER_ID.to_vec(), diff --git a/packages/rs-drive/src/drive/identity/withdrawals/queue.rs b/packages/rs-drive/src/drive/identity/withdrawals/queue.rs index d186ff47e8b..b5fb2f8b466 100644 --- a/packages/rs-drive/src/drive/identity/withdrawals/queue.rs +++ b/packages/rs-drive/src/drive/identity/withdrawals/queue.rs @@ -25,7 +25,7 @@ impl Drive { if !withdrawals.is_empty() { drive_operation_types.push(DriveOperationType::WithdrawalOperation( WithdrawalOperationType::InsertTransactions { - transactions: withdrawals, + withdrawal_transactions: withdrawals, }, )); } @@ -89,9 +89,9 @@ impl Drive { #[cfg(test)] mod tests { use crate::{ + common::helpers::setup::setup_drive_with_initial_state_structure, drive::{batch::DriveOperationType, block_info::BlockInfo}, fee_pools::epochs::Epoch, - tests::helpers::setup::setup_drive_with_initial_state_structure, }; #[test] diff --git a/packages/rs-drive/src/drive/identity/withdrawals/transaction_index_counter.rs b/packages/rs-drive/src/drive/identity/withdrawals/transaction_index_counter.rs index 8accd4adeb4..516926db73a 100644 --- a/packages/rs-drive/src/drive/identity/withdrawals/transaction_index_counter.rs +++ b/packages/rs-drive/src/drive/identity/withdrawals/transaction_index_counter.rs @@ -3,6 +3,8 @@ use grovedb::{ Element, PathQuery, Query, SizedQuery, TransactionArg, }; +use crate::drive::identity::withdrawals::paths::get_withdrawal_root_path_vec; +use crate::fee::op::DriveOperation; use crate::{ drive::{ batch::{drive_op_batch::WithdrawalOperationType, DriveOperationType}, @@ -17,6 +19,26 @@ use super::paths::{ }; impl Drive { + pub(crate) fn update_transaction_index_counter( + &self, + index: u64, + ) -> Result<(Vec), Error> { + let mut drive_operations = vec![]; + + let path = get_withdrawal_root_path_vec(); + + self.batch_insert( + crate::drive::object_size_info::PathKeyElementInfo::PathKeyRefElement::<'_, 1>(( + path, + &WITHDRAWAL_TRANSACTIONS_COUNTER_ID, + Element::Item(index.to_be_bytes().to_vec(), None), + )), + &mut drive_operations, + )?; + + Ok(drive_operations) + } + /// Get latest withdrawal index in a queue pub fn remove_latest_withdrawal_transaction_index( &self, @@ -124,12 +146,12 @@ mod tests { use grovedb::Element; use crate::{ + common::helpers::setup::setup_drive_with_initial_state_structure, drive::{ block_info::BlockInfo, identity::withdrawals::paths::get_withdrawal_transactions_expired_ids_path, }, fee_pools::epochs::Epoch, - tests::helpers::setup::setup_drive_with_initial_state_structure, }; #[test] diff --git a/packages/rs-drive/src/drive/identity/withdrawals/withdrawal_status.rs b/packages/rs-drive/src/drive/identity/withdrawals/withdrawal_status.rs index 46c89f3bd9c..fbbcae6633d 100644 --- a/packages/rs-drive/src/drive/identity/withdrawals/withdrawal_status.rs +++ b/packages/rs-drive/src/drive/identity/withdrawals/withdrawal_status.rs @@ -1,5 +1,6 @@ use std::collections::BTreeMap; +use dpp::data_contract::document_type::random_document::CreateRandomDocument; use dpp::{ contracts::withdrawals_contract, data_contract::DriveContractExt, document::document_stub::DocumentStub, @@ -87,18 +88,20 @@ impl Drive { let QueryDocumentsOutcome { items, - skipped, - cost, + skipped: _, + cost: _, } = self.query_documents(drive_query, None, transaction)?; let documents = items .iter() .map(|document_cbor| { - DocumentStub::from_cbor(document_cbor, None, None).map_err(|_| { - Error::Drive(DriveError::CorruptedCodeExecution( - "Can't create document from CBOR", - )) - }) + document_type + .document_from_bytes(document_cbor) + .map_err(|e| { + Error::Drive(DriveError::CorruptedDriveState(format!( + "can't create document from bytes : {e}" + ))) + }) }) .collect::, Error>>()?; @@ -168,8 +171,8 @@ impl Drive { let QueryDocumentsOutcome { items, - skipped, - cost, + skipped: _, + cost: _, } = self.query_documents(drive_query, None, transaction)?; let documents = items @@ -201,11 +204,11 @@ mod tests { use dpp::tests::fixtures::get_withdrawals_data_contract_fixture; use serde_json::json; - use crate::tests::helpers::setup::setup_drive_with_initial_state_structure; - use crate::tests::helpers::setup::{setup_document, setup_system_data_contract}; + use crate::common::helpers::setup::setup_drive_with_initial_state_structure; + use crate::common::helpers::setup::{setup_document, setup_system_data_contract}; mod fetch_withdrawal_documents_by_status { - + use dpp::data_contract::DriveContractExt; use dpp::identity::state_transition::identity_credit_withdrawal_transition::Pooling; use super::*; @@ -242,7 +245,17 @@ mod tests { }), ); - setup_document(&drive, &document, &data_contract, Some(&transaction)); + let document_type = data_contract + .document_type_for_name(withdrawals_contract::types::WITHDRAWAL) + .expect("expected to get document type"); + + setup_document( + &drive, + &document, + &data_contract, + document_type, + Some(&transaction), + ); let document = get_withdrawal_document_fixture( &data_contract, @@ -256,7 +269,13 @@ mod tests { }), ); - setup_document(&drive, &document, &data_contract, Some(&transaction)); + setup_document( + &drive, + &document, + &data_contract, + document_type, + Some(&transaction), + ); let documents = drive .fetch_withdrawal_documents_by_status( @@ -279,6 +298,7 @@ mod tests { } mod find_document_by_transaction_id { + use dpp::data_contract::DriveContractExt; use dpp::identity::state_transition::identity_credit_withdrawal_transition::Pooling; use super::*; @@ -306,7 +326,17 @@ mod tests { }), ); - setup_document(&drive, &document, &data_contract, Some(&transaction)); + let document_type = data_contract + .document_type_for_name(withdrawals_contract::types::WITHDRAWAL) + .expect("expected to get document type"); + + setup_document( + &drive, + &document, + &data_contract, + document_type, + Some(&transaction), + ); let found_document = drive .find_document_by_transaction_id(&(0..32).collect::>(), Some(&transaction)) diff --git a/packages/rs-drive/src/drive/query/mod.rs b/packages/rs-drive/src/drive/query/mod.rs index 0667231fc12..e9de2a2af30 100644 --- a/packages/rs-drive/src/drive/query/mod.rs +++ b/packages/rs-drive/src/drive/query/mod.rs @@ -44,7 +44,6 @@ use crate::fee::op::DriveOperation; use crate::query::DriveQuery; use dpp::data_contract::document_type::DocumentType; use dpp::data_contract::DriveContractExt; -use dpp::document::document_stub::DocumentStub; use crate::drive::block_info::BlockInfo; use crate::fee_pools::epochs::Epoch; diff --git a/packages/rs-drive/src/fee_pools/epochs/operations_factory.rs b/packages/rs-drive/src/fee_pools/epochs/operations_factory.rs index fb03f4228dc..055b393b5e7 100644 --- a/packages/rs-drive/src/fee_pools/epochs/operations_factory.rs +++ b/packages/rs-drive/src/fee_pools/epochs/operations_factory.rs @@ -217,7 +217,7 @@ impl Epoch { #[cfg(test)] mod tests { use super::*; - use crate::tests::helpers::setup::{setup_drive, setup_drive_with_initial_state_structure}; + use crate::common::helpers::setup::{setup_drive, setup_drive_with_initial_state_structure}; use chrono::Utc; mod increment_proposer_block_count_operation { diff --git a/packages/rs-drive/src/fee_pools/mod.rs b/packages/rs-drive/src/fee_pools/mod.rs index efcaeaba882..e6ee6539c69 100644 --- a/packages/rs-drive/src/fee_pools/mod.rs +++ b/packages/rs-drive/src/fee_pools/mod.rs @@ -94,7 +94,7 @@ pub fn update_unpaid_epoch_index_operation(epoch_index: EpochIndex) -> GroveDbOp #[cfg(test)] mod tests { use super::*; - use crate::tests::helpers::setup::setup_drive_with_initial_state_structure; + use crate::common::helpers::setup::setup_drive_with_initial_state_structure; mod add_create_fee_pool_trees_operations { use super::*; diff --git a/packages/rs-drive/src/lib.rs b/packages/rs-drive/src/lib.rs index c3ff17eed83..b09e4e44e65 100644 --- a/packages/rs-drive/src/lib.rs +++ b/packages/rs-drive/src/lib.rs @@ -30,7 +30,3 @@ pub mod rpc; pub use dpp; /// GroveDB module pub use grovedb; - -/// Test helpers -#[cfg(feature = "test-helpers")] -pub mod tests; diff --git a/packages/rs-drive/src/tests/helpers/mod.rs b/packages/rs-drive/src/tests/helpers/mod.rs deleted file mode 100644 index 138906d09f7..00000000000 --- a/packages/rs-drive/src/tests/helpers/mod.rs +++ /dev/null @@ -1 +0,0 @@ -pub mod setup; diff --git a/packages/rs-drive/src/tests/mod.rs b/packages/rs-drive/src/tests/mod.rs deleted file mode 100644 index 99a2445f20b..00000000000 --- a/packages/rs-drive/src/tests/mod.rs +++ /dev/null @@ -1,2 +0,0 @@ -/// Everything related to test helpers -pub mod helpers; diff --git a/packages/rs-drive/tests/query_tests.rs b/packages/rs-drive/tests/query_tests.rs index 8cf42bad1a9..d36fdd794e0 100644 --- a/packages/rs-drive/tests/query_tests.rs +++ b/packages/rs-drive/tests/query_tests.rs @@ -47,6 +47,8 @@ use serde_json::json; use tempfile::TempDir; use drive::common; +#[cfg(test)] +use drive::common::helpers::setup::setup_drive; use drive::common::setup_contract; use drive::drive::batch::GroveDbOpBatch; use drive::drive::config::DriveConfig; @@ -57,8 +59,6 @@ use drive::drive::object_size_info::{DocumentAndContractInfo, OwnedDocumentInfo} use drive::drive::Drive; use drive::error::{query::QueryError, Error}; use drive::query::DriveQuery; -#[cfg(test)] -use drive::tests::helpers::setup::setup_drive; use dpp::data_contract::validation::data_contract_validator::DataContractValidator; use dpp::document::document_stub::DocumentStub; diff --git a/packages/rs-drive/tests/query_tests_history.rs b/packages/rs-drive/tests/query_tests_history.rs index c09247c0894..6ebd33ecd7c 100644 --- a/packages/rs-drive/tests/query_tests_history.rs +++ b/packages/rs-drive/tests/query_tests_history.rs @@ -45,7 +45,7 @@ use serde_json::json; use drive::common; -use drive::tests::helpers::setup::setup_drive; +use drive::common::helpers::setup::setup_drive; use drive::contract::Contract; use drive::drive::batch::GroveDbOpBatch; From 9b74a3bc5d41f55d2609090e0d0cbce0cd8126cc Mon Sep 17 00:00:00 2001 From: Quantum Explorer Date: Tue, 7 Feb 2023 19:19:20 +0700 Subject: [PATCH 111/170] more fixes --- .../document_type/random_document.rs | 2 + packages/rs-dpp/src/document/document_stub.rs | 37 +++++++++- .../fixtures/get_withdrawals_data_contract.rs | 23 +++---- .../rs-dpp/src/util/cbor_value/cbor_map.rs | 69 +++++++++++++++---- .../src/common/helpers/fee_pools.rs | 2 + .../rs-drive/src/drive/document/update.rs | 12 +++- 6 files changed, 114 insertions(+), 31 deletions(-) diff --git a/packages/rs-dpp/src/data_contract/document_type/random_document.rs b/packages/rs-dpp/src/data_contract/document_type/random_document.rs index 4657f758175..6aac1bcb1b0 100644 --- a/packages/rs-dpp/src/data_contract/document_type/random_document.rs +++ b/packages/rs-dpp/src/data_contract/document_type/random_document.rs @@ -109,6 +109,7 @@ impl CreateRandomDocument for DocumentType { id, properties, owner_id, + revision: 1, } } @@ -156,6 +157,7 @@ impl CreateRandomDocument for DocumentType { id, properties, owner_id, + revision: 1, } } } diff --git a/packages/rs-dpp/src/document/document_stub.rs b/packages/rs-dpp/src/document/document_stub.rs index b86567eaf10..73f7365b172 100644 --- a/packages/rs-dpp/src/document/document_stub.rs +++ b/packages/rs-dpp/src/document/document_stub.rs @@ -38,7 +38,7 @@ use std::fmt; use std::io::{BufReader, Read}; use ciborium::value::{Integer, Value}; -use integer_encoding::VarIntWriter; +use integer_encoding::{VarInt, VarIntReader, VarIntWriter}; use crate::data_contract::{DataContract, DriveContractExt}; use serde::{Deserialize, Serialize}; @@ -54,6 +54,8 @@ use crate::util::deserializer; use crate::util::deserializer::SplitProtocolVersionOutcome; use crate::ProtocolError; +use crate::document::document_transition::INITIAL_REVISION; +use crate::util::cbor_value::CborBTreeMapHelper; use anyhow::{anyhow, bail}; //todo: rename @@ -71,6 +73,10 @@ pub struct DocumentStub { /// The ID of the document's owner. #[serde(rename = "$ownerId")] pub owner_id: [u8; 32], + + /// The document revision. + #[serde(rename = "$revision")] + pub revision: u64, } impl DocumentStub { @@ -81,6 +87,9 @@ impl DocumentStub { pub fn serialize(&self, document_type: &DocumentType) -> Result, ProtocolError> { let mut buffer: Vec = self.id.as_slice().to_vec(); buffer.extend(self.owner_id.as_slice()); + if document_type.documents_mutable { + buffer.append(&mut self.revision.encode_var_vec()); + } document_type .properties .iter() @@ -115,6 +124,9 @@ impl DocumentStub { let mut buffer: Vec = Vec::try_from(self.id).unwrap(); let mut owner_id = Vec::try_from(self.owner_id).unwrap(); buffer.append(&mut owner_id); + if document_type.documents_mutable { + buffer.append(&mut self.revision.encode_var_vec()); + } document_type .properties .iter() @@ -161,6 +173,17 @@ impl DocumentStub { ) })?; + let revision = if document_type.documents_mutable { + let revision: u64 = buf.read_varint().map_err(|_| { + ProtocolError::DataContractError(DataContractError::CorruptedSerialization( + "error reading varint revision from serialized document", + )) + })?; + revision + } else { + INITIAL_REVISION as u64 + }; + let properties = document_type .properties .iter() @@ -176,6 +199,7 @@ impl DocumentStub { id, properties, owner_id, + revision, }) } @@ -243,11 +267,16 @@ impl DocumentStub { } .expect("document_id must be 32 bytes"); + let revision: u64 = document + .remove_optional_integer("$revision")? + .unwrap_or(INITIAL_REVISION as u64); + // dev-note: properties is everything other than the id and owner id Ok(DocumentStub { properties: document, owner_id, id, + revision, }) } @@ -269,6 +298,7 @@ impl DocumentStub { DataContractError::FieldRequirementUnmet("invalid document id"), )); } + let SplitProtocolVersionOutcome { main_message_bytes: read_document_cbor, .. @@ -283,6 +313,8 @@ impl DocumentStub { )) })?; + let revision: u64 = properties.get_integer("$revision")?; + // dev-note: properties is everything other than the id and owner id Ok(DocumentStub { properties, @@ -292,6 +324,7 @@ impl DocumentStub { id: document_id .try_into() .expect("try_into shouldn't fail, document_id must be 32 bytes"), + revision, }) } @@ -476,7 +509,7 @@ impl DocumentStub { pub fn increment_revision(&mut self) -> Result<(), ProtocolError> { let property_name = "$revision"; - let revision = self.get_u32(property_name)?; + let revision = self.revision; let new_revision = revision .checked_add(1) diff --git a/packages/rs-dpp/src/tests/fixtures/get_withdrawals_data_contract.rs b/packages/rs-dpp/src/tests/fixtures/get_withdrawals_data_contract.rs index 1939d5b5adf..43387b4a951 100644 --- a/packages/rs-dpp/src/tests/fixtures/get_withdrawals_data_contract.rs +++ b/packages/rs-dpp/src/tests/fixtures/get_withdrawals_data_contract.rs @@ -6,6 +6,8 @@ use serde_json::Value; use crate::contracts::withdrawals_contract; use crate::prelude::*; +use crate::data_contract::extra::common::json_document_to_cbor; +use crate::tests::data_contract; use crate::{ data_contract::validation::data_contract_validator::DataContractValidator, data_contract::DataContractFactory, @@ -21,20 +23,17 @@ lazy_static! { } pub fn get_withdrawals_data_contract_fixture(owner_id: Option) -> DataContract { - let protocol_version_validator = - ProtocolVersionValidator::new(LATEST_VERSION, LATEST_VERSION, COMPATIBILITY_MAP.clone()); - let data_contract_validator = DataContractValidator::new(Arc::new(protocol_version_validator)); - let factory = DataContractFactory::new(1, data_contract_validator); + let withdrawal_contract_path = + "../../../contracts/withdrawals/withdrawals-contract-documents.json"; - let owner_id = owner_id.unwrap_or_else(generate_random_identifier_struct); + let withdrawal_cbor = json_document_to_cbor(withdrawal_contract_path, Some(1)) + .expect("expected to get cbor document"); - let withdrawals_schema = WITHDRAWALS_SCHEMA.clone(); - - let mut data_contract = factory - .create(owner_id, withdrawals_schema) - .expect("data in fixture should be correct"); - - data_contract.id = withdrawals_contract::CONTRACT_ID.clone(); + let mut data_contract = DataContract::from_cbor(withdrawal_cbor) + .expect("expected to deserialize withdrawal contract"); + if let Some(owner_id) = owner_id { + data_contract.owner_id = owner_id; + } data_contract } diff --git a/packages/rs-dpp/src/util/cbor_value/cbor_map.rs b/packages/rs-dpp/src/util/cbor_value/cbor_map.rs index 77f779ea024..29e8d54eab8 100644 --- a/packages/rs-dpp/src/util/cbor_value/cbor_map.rs +++ b/packages/rs-dpp/src/util/cbor_value/cbor_map.rs @@ -17,6 +17,11 @@ pub trait CborBTreeMapHelper { fn get_optional_integer>(&self, key: &str) -> Result, ProtocolError>; fn get_integer>(&self, key: &str) -> Result; + fn remove_optional_integer>( + &mut self, + key: &str, + ) -> Result, ProtocolError>; + fn remove_integer>(&mut self, key: &str) -> Result; fn get_optional_bool(&self, key: &str) -> Result, ProtocolError>; fn get_bool(&self, key: &str) -> Result; fn get_optional_inner_value_array<'a, I: FromIterator<&'a CborValue>>( @@ -67,8 +72,9 @@ where } fn get_identifier(&self, key: &str) -> Result<[u8; 32], ProtocolError> { - self.get_optional_identifier(key)? - .ok_or_else(|| ProtocolError::DecodingError(format!("unable to get property {key}"))) + self.get_optional_identifier(key)?.ok_or_else(|| { + ProtocolError::DecodingError(format!("unable to get identifier property {key}")) + }) } fn get_optional_string(&self, key: &str) -> Result, ProtocolError> { @@ -83,8 +89,9 @@ where } fn get_string(&self, key: &str) -> Result { - self.get_optional_string(key)? - .ok_or_else(|| ProtocolError::DecodingError(format!("unable to get property {key}"))) + self.get_optional_string(key)?.ok_or_else(|| { + ProtocolError::DecodingError(format!("unable to get string property {key}")) + }) } fn get_optional_str(&self, key: &str) -> Result, ProtocolError> { @@ -98,8 +105,9 @@ where } fn get_str(&self, key: &str) -> Result<&str, ProtocolError> { - self.get_optional_str(key)? - .ok_or_else(|| ProtocolError::DecodingError(format!("unable to get property {key}"))) + self.get_optional_str(key)?.ok_or_else(|| { + ProtocolError::DecodingError(format!("unable to get str property {key}")) + }) } fn get_optional_integer>( @@ -120,8 +128,9 @@ where } fn get_integer>(&self, key: &str) -> Result { - self.get_optional_integer(key)? - .ok_or_else(|| ProtocolError::DecodingError(format!("unable to get property {key}"))) + self.get_optional_integer(key)?.ok_or_else(|| { + ProtocolError::DecodingError(format!("unable to get integer property {key}")) + }) } fn get_optional_bool(&self, key: &str) -> Result, ProtocolError> { @@ -135,8 +144,32 @@ where } fn get_bool(&self, key: &str) -> Result { - self.get_optional_bool(key)? - .ok_or_else(|| ProtocolError::DecodingError(format!("unable to get property {key}"))) + self.get_optional_bool(key)?.ok_or_else(|| { + ProtocolError::DecodingError(format!("unable to get bool property {key}")) + }) + } + + fn remove_optional_integer>( + &mut self, + key: &str, + ) -> Result, ProtocolError> { + self.remove(key) + .map(|v| { + i128::from(v.borrow().as_integer().ok_or_else(|| { + ProtocolError::DecodingError(format!("{key} must be an integer")) + })?) + .try_into() + .map_err(|_| { + ProtocolError::DecodingError(format!("{key} is out of required bounds")) + }) + }) + .transpose() + } + + fn remove_integer>(&mut self, key: &str) -> Result { + self.remove_optional_integer(key)?.ok_or_else(|| { + ProtocolError::DecodingError(format!("unable to remove integer property {key}")) + }) } fn get_optional_inner_value_array<'a, I: FromIterator<&'a CborValue>>( @@ -157,8 +190,9 @@ where &'a self, key: &str, ) -> Result { - self.get_optional_inner_value_array(key)? - .ok_or_else(|| ProtocolError::DecodingError(format!("unable to get property {key}"))) + self.get_optional_inner_value_array(key)?.ok_or_else(|| { + ProtocolError::DecodingError(format!("unable to get inner value array property {key}")) + }) } fn get_optional_inner_string_array>( @@ -190,8 +224,9 @@ where &self, key: &str, ) -> Result { - self.get_optional_inner_string_array(key)? - .ok_or_else(|| ProtocolError::DecodingError(format!("unable to get property {key}"))) + self.get_optional_inner_string_array(key)?.ok_or_else(|| { + ProtocolError::DecodingError(format!("unable to get inner string property {key}")) + }) } fn get_optional_inner_borrowed_str_value_map< @@ -240,6 +275,10 @@ where key: &str, ) -> Result { self.get_optional_inner_borrowed_str_value_map(key)? - .ok_or_else(|| ProtocolError::DecodingError(format!("unable to get property {key}"))) + .ok_or_else(|| { + ProtocolError::DecodingError(format!( + "unable to get borrowed str value map property {key}" + )) + }) } } diff --git a/packages/rs-drive-abci/src/common/helpers/fee_pools.rs b/packages/rs-drive-abci/src/common/helpers/fee_pools.rs index 6882da564b0..8ebbeac2f54 100644 --- a/packages/rs-drive-abci/src/common/helpers/fee_pools.rs +++ b/packages/rs-drive-abci/src/common/helpers/fee_pools.rs @@ -36,6 +36,7 @@ use std::borrow::Cow; use std::collections::BTreeMap; use ciborium::value::Value; +use dpp::document::document_transition::INITIAL_REVISION; use drive::dpp::identity::Identity; use rand::rngs::StdRng; use rand::{Rng, SeedableRng}; @@ -76,6 +77,7 @@ fn create_test_mn_share_document( id, properties, owner_id: identity_id, + revision: INITIAL_REVISION as u64, }; let document_type = contract diff --git a/packages/rs-drive/src/drive/document/update.rs b/packages/rs-drive/src/drive/document/update.rs index 2d1d81a5212..e5ac9c63a8c 100644 --- a/packages/rs-drive/src/drive/document/update.rs +++ b/packages/rs-drive/src/drive/document/update.rs @@ -80,6 +80,7 @@ use crate::drive::grove_operations::{ }; use crate::fee::result::FeeResult; use dpp::prelude::DataContract; +use dpp::ProtocolError; impl Drive { /// Updates a serialized document given a contract CBOR and returns the associated fee. @@ -368,11 +369,18 @@ impl Drive { if let Element::Item(old_serialized_document, element_flags) = old_document_element { - let document = DocumentStub::from_cbor( + let document_result = DocumentStub::from_cbor( old_serialized_document.as_slice(), None, owner_id, - )?; + ); + let document = match document_result { + Ok(document_result) => Ok(document_result), + Err(_) => DocumentStub::from_bytes( + old_serialized_document.as_slice(), + document_type, + ), + }?; let storage_flags = StorageFlags::map_some_element_flags_ref(&element_flags)?; Ok(DocumentWithoutSerialization(( From 28655948deff452ae9128292184bbc0e4c562584 Mon Sep 17 00:00:00 2001 From: Ivan Shumkov Date: Tue, 7 Feb 2023 21:57:13 +0800 Subject: [PATCH 112/170] fix: get_withdrawals_data_contract_fixture --- .../withdrawals_data_triggers/mod.rs | 53 ++++++++----------- .../fixtures/get_withdrawals_data_contract.rs | 11 +--- 2 files changed, 22 insertions(+), 42 deletions(-) diff --git a/packages/rs-dpp/src/data_trigger/withdrawals_data_triggers/mod.rs b/packages/rs-dpp/src/data_trigger/withdrawals_data_triggers/mod.rs index 8e41266e6c7..6653dec605d 100644 --- a/packages/rs-dpp/src/data_trigger/withdrawals_data_triggers/mod.rs +++ b/packages/rs-dpp/src/data_trigger/withdrawals_data_triggers/mod.rs @@ -21,12 +21,11 @@ where { let mut result = DataTriggerExecutionResult::default(); - let dt_delete = match document_transition { - DocumentTransition::Delete(d) => d, - _ => bail!( + let DocumentTransition::Delete(dt_delete) = document_transition else { + bail!( "the Document Transition {} isn't 'DELETE'", get_from_transition!(document_transition, id) - ), + ); }; let withdrawals: Vec = context @@ -43,39 +42,35 @@ where ) .await?; - if withdrawals.is_empty() { + let Some(withdrawal) = withdrawals.get(0) else { let err = DataTriggerError::DataTriggerConditionError { - data_contract_id: context.data_contract.id.clone(), - document_transition_id: dt_delete.base.id.clone(), + data_contract_id: context.data_contract.id, + document_transition_id: dt_delete.base.id, message: "Withdrawal document was not found".to_string(), - owner_id: Some(context.owner_id.clone()), + owner_id: Some(*context.owner_id), document_transition: Some(DocumentTransition::Delete(dt_delete.clone())), }; result.add_error(err.into()); return Ok(result); - } - - let withdrawal = withdrawals.get(0).unwrap(); + }; let status = withdrawal .get("status") - .ok_or(anyhow!( - "can't get withdrawal status property from the document" - ))? + .ok_or_else(|| anyhow!("can't get withdrawal status property from the document"))? .as_u64() - .ok_or(anyhow!("can't convert withdrawal status to u64"))? as u8; + .ok_or_else(|| anyhow!("can't convert withdrawal status to u64"))? as u8; if status != withdrawals_contract::Status::COMPLETE as u8 || status != withdrawals_contract::Status::EXPIRED as u8 { let err = DataTriggerError::DataTriggerConditionError { - data_contract_id: context.data_contract.id.clone(), - document_transition_id: dt_delete.base.id.clone(), + data_contract_id: context.data_contract.id, + document_transition_id: dt_delete.base.id, message: "withdrawal deletion is allowed only for COMPLETE and EXPIRED statuses" .to_string(), - owner_id: Some(context.owner_id.clone()), + owner_id: Some(*context.owner_id), document_transition: Some(DocumentTransition::Delete(dt_delete.clone())), }; @@ -88,21 +83,15 @@ where } #[cfg(test)] -mod test { - use super::delete_withdrawal_data_trigger; - use crate::{ - contracts::withdrawals_contract, - data_trigger::DataTriggerExecutionContext, - document::{document_transition::DocumentTransition, Document}, - identity::state_transition::identity_credit_withdrawal_transition::Pooling, - state_repository::MockStateRepositoryLike, - state_transition::state_transition_execution_context::StateTransitionExecutionContext, - tests::fixtures::{ - get_data_contract_fixture, get_withdrawal_document_fixture, - get_withdrawals_data_contract_fixture, - }, +mod tests { + use super::*; + use crate::identity::state_transition::identity_credit_withdrawal_transition::Pooling; + use crate::state_repository::MockStateRepositoryLike; + use crate::state_transition::state_transition_execution_context::StateTransitionExecutionContext; + use crate::tests::fixtures::{ + get_data_contract_fixture, get_withdrawal_document_fixture, + get_withdrawals_data_contract_fixture, }; - use serde_json::json; #[tokio::test] async fn should_throw_error_if_withdrawal_not_found() { diff --git a/packages/rs-dpp/src/tests/fixtures/get_withdrawals_data_contract.rs b/packages/rs-dpp/src/tests/fixtures/get_withdrawals_data_contract.rs index 43387b4a951..29dfd8483af 100644 --- a/packages/rs-dpp/src/tests/fixtures/get_withdrawals_data_contract.rs +++ b/packages/rs-dpp/src/tests/fixtures/get_withdrawals_data_contract.rs @@ -3,17 +3,9 @@ use std::sync::Arc; use lazy_static::lazy_static; use serde_json::Value; -use crate::contracts::withdrawals_contract; use crate::prelude::*; use crate::data_contract::extra::common::json_document_to_cbor; -use crate::tests::data_contract; -use crate::{ - data_contract::validation::data_contract_validator::DataContractValidator, - data_contract::DataContractFactory, - tests::utils::generate_random_identifier_struct, - version::{ProtocolVersionValidator, COMPATIBILITY_MAP, LATEST_VERSION}, -}; lazy_static! { static ref WITHDRAWALS_SCHEMA: Value = serde_json::from_str(include_str!( @@ -23,8 +15,7 @@ lazy_static! { } pub fn get_withdrawals_data_contract_fixture(owner_id: Option) -> DataContract { - let withdrawal_contract_path = - "../../../contracts/withdrawals/withdrawals-contract-documents.json"; + let withdrawal_contract_path = "./contracts/withdrawals/withdrawals-contract-documents.json"; let withdrawal_cbor = json_document_to_cbor(withdrawal_contract_path, Some(1)) .expect("expected to get cbor document"); From b135f02a1604f8f522388eff971dad5421ed2d13 Mon Sep 17 00:00:00 2001 From: Quantum Explorer Date: Tue, 7 Feb 2023 21:18:35 +0700 Subject: [PATCH 113/170] added file --- .../withdrawals/withdrawals-contract.json | 137 ++++++++++++++++++ 1 file changed, 137 insertions(+) create mode 100644 packages/rs-dpp/contracts/withdrawals/withdrawals-contract.json diff --git a/packages/rs-dpp/contracts/withdrawals/withdrawals-contract.json b/packages/rs-dpp/contracts/withdrawals/withdrawals-contract.json new file mode 100644 index 00000000000..28e7d20f923 --- /dev/null +++ b/packages/rs-dpp/contracts/withdrawals/withdrawals-contract.json @@ -0,0 +1,137 @@ +{ + "$id": "AcYUCSvAmUwryNsQqkqqD1o3BnFuzepGtR3Mhh2swLk6", + "ownerId": "AcYUCSvAmUwryNsQqkqqD1o3BnFuzepGtR3Mhh2swLk6", + "$schema": "http://json-schema.org/draft-07/schema", + "version": 1, + "documents": { + "withdrawal": { + "description": "Withdrawal document to track underlying transaction", + "type": "object", + "indices": [ + { + "name": "identityStatus", + "properties": [ + { + "$ownerId": "asc" + }, + { + "status": "asc" + }, + { + "$createdAt": "asc" + } + ], + "unique": false + }, + { + "name": "identityRecent", + "properties": [ + { + "$ownerId": "asc" + }, + { + "$updatedAt": "asc" + }, + { + "status": "asc" + } + ], + "unique": false + }, + { + "name": "pooling", + "properties": [ + { + "status": "asc" + }, + { + "pooling": "asc" + }, + { + "coreFeePerByte": "asc" + }, + { + "$updatedAt": "asc" + } + ], + "unique": false + }, + { + "name": "transaction", + "properties": [ + { + "status": "asc" + }, + { + "transactionId": "asc" + } + ], + "unique": false + } + ], + "properties": { + "transactionId": { + "description": "Hash of asset unlock transaction. Populated with untied transaction hash on “pooled” stage and with signed transaction on “broatcasted” stage", + "type": "array", + "byteArray": true, + "minItems": 32, + "maxItems": 32 + }, + "transactionSignHeight": { + "type": "integer", + "description": "The Core height on which transaction was signed", + "minimum": 1 + }, + "transactionIndex": { + "type": "integer", + "description": "Sequential index used to create withdrawal transaction", + "minimum": 1 + }, + "amount": { + "type": "integer", + "description": "The amount to be withdrawn", + "minimum": 1000 + }, + "coreFeePerByte": { + "type": "integer", + "description": "This is the fee that you are willing to spend for this transaction in Duffs/Byte", + "minimum": 1 + }, + "pooling": { + "type": "integer", + "description": "This indicated the level at which Platform should try to pool this transaction", + "enum": [ + 0 + ] + }, + "outputScript": { + "type": "array", + "byteArray": true, + "minItems": 23, + "maxItems": 25 + }, + "status": { + "type": "integer", + "enum": [ + 0, + 1, + 2, + 3, + 4 + ] + } + }, + "additionalProperties": false, + "required": [ + "$createdAt", + "$updatedAt", + "amount", + "coreFeePerByte", + "pooling", + "outputScript", + "transactionIndex", + "status" + ] + } + } +} From 97594db471826e708e72fb8275d543f28e0125ce Mon Sep 17 00:00:00 2001 From: Ivan Shumkov Date: Tue, 7 Feb 2023 22:26:26 +0800 Subject: [PATCH 114/170] test: fix get_withdrawals_data_contract_fixture --- .../fixtures/get_withdrawals_data_contract.rs | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/packages/rs-dpp/src/tests/fixtures/get_withdrawals_data_contract.rs b/packages/rs-dpp/src/tests/fixtures/get_withdrawals_data_contract.rs index 29dfd8483af..02073bee193 100644 --- a/packages/rs-dpp/src/tests/fixtures/get_withdrawals_data_contract.rs +++ b/packages/rs-dpp/src/tests/fixtures/get_withdrawals_data_contract.rs @@ -5,20 +5,22 @@ use serde_json::Value; use crate::prelude::*; -use crate::data_contract::extra::common::json_document_to_cbor; +use crate::util::serializer::value_to_cbor; lazy_static! { - static ref WITHDRAWALS_SCHEMA: Value = serde_json::from_str(include_str!( + static ref WITHDRAWALS_CONTRACT_DOCUMENTS: Value = serde_json::from_str(include_str!( "./../../../contracts/withdrawals/withdrawals-contract-documents.json" )) .expect("withdrawals contract should be valid json"); + static ref WITHDRAWALS_CONTRACT_SCHEMA: Value = serde_json::from_str(include_str!( + "./../../../contracts/withdrawals/withdrawals-contract.json" + )) + .expect("withdrawals contract should be valid json"); } pub fn get_withdrawals_data_contract_fixture(owner_id: Option) -> DataContract { - let withdrawal_contract_path = "./contracts/withdrawals/withdrawals-contract-documents.json"; - - let withdrawal_cbor = json_document_to_cbor(withdrawal_contract_path, Some(1)) - .expect("expected to get cbor document"); + let withdrawal_cbor = value_to_cbor(WITHDRAWALS_CONTRACT_SCHEMA.clone(), Some(1)) + .expect("should convert json to cbor value"); let mut data_contract = DataContract::from_cbor(withdrawal_cbor) .expect("expected to deserialize withdrawal contract"); From 95f5fd0dbd3fce87523469c51a0b50f0566574b7 Mon Sep 17 00:00:00 2001 From: Quantum Explorer Date: Tue, 7 Feb 2023 21:29:25 +0700 Subject: [PATCH 115/170] fix --- .../rs-dpp/src/tests/fixtures/get_withdrawals_data_contract.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/packages/rs-dpp/src/tests/fixtures/get_withdrawals_data_contract.rs b/packages/rs-dpp/src/tests/fixtures/get_withdrawals_data_contract.rs index 02073bee193..cb9ab7832b1 100644 --- a/packages/rs-dpp/src/tests/fixtures/get_withdrawals_data_contract.rs +++ b/packages/rs-dpp/src/tests/fixtures/get_withdrawals_data_contract.rs @@ -2,6 +2,7 @@ use std::sync::Arc; use lazy_static::lazy_static; use serde_json::Value; +use crate::contracts::withdrawals_contract; use crate::prelude::*; @@ -28,5 +29,7 @@ pub fn get_withdrawals_data_contract_fixture(owner_id: Option) -> Da if let Some(owner_id) = owner_id { data_contract.owner_id = owner_id; } + + data_contract.id = withdrawals_contract::CONTRACT_ID.clone(); data_contract } From 00e047d51d042990d4467348cafc3aee6efb45f9 Mon Sep 17 00:00:00 2001 From: Quantum Explorer Date: Tue, 7 Feb 2023 21:34:09 +0700 Subject: [PATCH 116/170] fix --- .../src/drive/identity/withdrawals/withdrawal_status.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/rs-drive/src/drive/identity/withdrawals/withdrawal_status.rs b/packages/rs-drive/src/drive/identity/withdrawals/withdrawal_status.rs index fbbcae6633d..5e83df3a8b1 100644 --- a/packages/rs-drive/src/drive/identity/withdrawals/withdrawal_status.rs +++ b/packages/rs-drive/src/drive/identity/withdrawals/withdrawal_status.rs @@ -178,9 +178,9 @@ impl Drive { let documents = items .iter() .map(|document_cbor| { - DocumentStub::from_cbor(document_cbor, None, None).map_err(|_| { - Error::Drive(DriveError::CorruptedCodeExecution( - "Can't create document from CBOR", + DocumentStub::from_bytes(document_cbor, document_type).map_err(|_| { + Error::Drive(DriveError::CorruptedDriveState( + "can't create document from bytes".to_string(), )) }) }) @@ -189,7 +189,7 @@ impl Drive { let document = documents .get(0) .ok_or(Error::Drive(DriveError::CorruptedCodeExecution( - "Document was not found by transactionId", + "document was not found by transactionId", )))? .clone(); From ad586ecd3a31eed110b65f84140c878cdc9f917d Mon Sep 17 00:00:00 2001 From: Ivan Shumkov Date: Tue, 7 Feb 2023 22:36:06 +0800 Subject: [PATCH 117/170] refactor: small thing --- .../src/tests/fixtures/get_withdrawals_data_contract.rs | 7 +++---- .../src/drive/identity/withdrawals/withdrawal_status.rs | 2 +- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/packages/rs-dpp/src/tests/fixtures/get_withdrawals_data_contract.rs b/packages/rs-dpp/src/tests/fixtures/get_withdrawals_data_contract.rs index cb9ab7832b1..9f4927cc7a5 100644 --- a/packages/rs-dpp/src/tests/fixtures/get_withdrawals_data_contract.rs +++ b/packages/rs-dpp/src/tests/fixtures/get_withdrawals_data_contract.rs @@ -1,8 +1,6 @@ -use std::sync::Arc; - +use crate::contracts::withdrawals_contract; use lazy_static::lazy_static; use serde_json::Value; -use crate::contracts::withdrawals_contract; use crate::prelude::*; @@ -30,6 +28,7 @@ pub fn get_withdrawals_data_contract_fixture(owner_id: Option) -> Da data_contract.owner_id = owner_id; } - data_contract.id = withdrawals_contract::CONTRACT_ID.clone(); + data_contract.id = *withdrawals_contract::CONTRACT_ID; + data_contract } diff --git a/packages/rs-drive/src/drive/identity/withdrawals/withdrawal_status.rs b/packages/rs-drive/src/drive/identity/withdrawals/withdrawal_status.rs index 5e83df3a8b1..a3fb14d469e 100644 --- a/packages/rs-drive/src/drive/identity/withdrawals/withdrawal_status.rs +++ b/packages/rs-drive/src/drive/identity/withdrawals/withdrawal_status.rs @@ -70,7 +70,7 @@ impl Drive { let drive_query = DriveQuery { contract: &contract_fetch_info.contract, - document_type: document_type, + document_type, internal_clauses: InternalClauses { primary_key_in_clause: None, primary_key_equal_clause: None, From b8df075f2a7b624aecb06ba920cba2db95b14618 Mon Sep 17 00:00:00 2001 From: Quantum Explorer Date: Tue, 14 Feb 2023 23:11:45 +0700 Subject: [PATCH 118/170] fixed issues --- Cargo.lock | 98 +-- packages/rs-drive-abci/src/abci/handlers.rs | 3 +- .../src/identity_credit_withdrawal/mod.rs | 25 +- packages/rs-drive-abci/src/state/genesis.rs | 5 +- .../strategy_tests/upgrade_fork_tests.rs | 8 +- .../rs-drive/src/drive/document/update.rs | 650 ++++++++---------- .../src/drive/identity/withdrawals/delete.rs | 2 +- .../identity/withdrawals/expired_index.rs | 4 +- .../src/drive/identity/withdrawals/insert.rs | 2 +- .../withdrawals/transaction_index_counter.rs | 2 +- .../rs-drive/src/drive/object_size_info.rs | 17 + 11 files changed, 384 insertions(+), 432 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 8f55615d2cc..9afcf7a19db 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -341,18 +341,6 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "771fe0050b883fcc3ea2359b1a96bcfbc090b7116eae7c3c512c7a083fdf23d3" -[[package]] -name = "bstr" -version = "0.2.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba3569f383e8f1598449f1a423e72e99569137b47740b1da11ef19af3d5c3223" -dependencies = [ - "lazy_static", - "memchr", - "regex-automata", - "serde", -] - [[package]] name = "bumpalo" version = "3.12.0" @@ -727,13 +715,12 @@ dependencies = [ [[package]] name = "csv" -version = "1.1.6" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22813a6dc45b335f9bade10bf7271dc477e81113e89eb251a0bc2a8a81c536e1" +checksum = "af91f40b7355f82b0a891f50e70399475945bb0b0da4f1700ce60761c9d3e359" dependencies = [ - "bstr", "csv-core", - "itoa 0.4.8", + "itoa", "ryu", "serde", ] @@ -803,9 +790,9 @@ dependencies = [ [[package]] name = "darling" -version = "0.14.2" +version = "0.14.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b0dd3cd20dc6b5a876612a6e5accfe7f3dd883db6d07acfbf14c128f61550dfa" +checksum = "c0808e1bd8671fb44a113a14e13497557533369847788fa2ae912b6ebfce9fa8" dependencies = [ "darling_core", "darling_macro", @@ -813,9 +800,9 @@ dependencies = [ [[package]] name = "darling_core" -version = "0.14.2" +version = "0.14.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a784d2ccaf7c98501746bf0be29b2022ba41fd62a2e622af997a03e9f972859f" +checksum = "001d80444f28e193f30c2f293455da62dcf9a6b29918a4253152ae2b1de592cb" dependencies = [ "fnv", "ident_case", @@ -827,9 +814,9 @@ dependencies = [ [[package]] name = "darling_macro" -version = "0.14.2" +version = "0.14.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7618812407e9402654622dd402b0a89dff9ba93badd6540781526117b92aab7e" +checksum = "b36230598a2d5de7ec1c6f51f72d8a99a9208daff41de2084d06e3fd3ea56685" dependencies = [ "darling_core", "quote", @@ -951,7 +938,7 @@ dependencies = [ "byteorder", "chrono", "ciborium", - "dashcore 0.29.1 (git+https://github.com/dashevo/rust-dashcore?branch=master)", + "dashcore", "data-contracts", "env_logger", "futures", @@ -1154,9 +1141,9 @@ dependencies = [ [[package]] name = "fastrand" -version = "1.8.0" +version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7a407cfaa3385c4ae6b23e84623d48c2798d06e3e6a1878f7f59f17b3f86499" +checksum = "e51093e27b0797c359783294ca4f0a911c270184cb10f85783b118614a1501be" dependencies = [ "instant", ] @@ -1393,22 +1380,13 @@ version = "1.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "eabb4a44450da02c90444cf74558da904edde8fb4e9035a9a6a4e15445af0bd7" -[[package]] -name = "hashbrown" -version = "0.11.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab5ef0d4909ef3724cc8cce6ccc8572c5c817592e9285f5464f8e86f8bd3726e" -dependencies = [ - "ahash", -] - [[package]] name = "hashbrown" version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" dependencies = [ - "ahash", + "ahash 0.7.6", ] [[package]] @@ -1569,12 +1547,6 @@ dependencies = [ "either", ] -[[package]] -name = "itoa" -version = "0.4.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b71991ff56294aa922b450139ee08b3bfc70982c6b2c7562771375cf73542dd4" - [[package]] name = "itoa" version = "1.0.5" @@ -1659,14 +1631,14 @@ name = "jsonschema" version = "0.15.0" source = "git+https://github.com/qrayven/jsonschema-rs?branch=feat-unknown-format-cutsom-keywords#7a1657bc8acce1b4270a26bce72423b4ba3b7c23" dependencies = [ - "ahash", + "ahash 0.7.6", "anyhow", "base64 0.21.0", "bytecount", "fancy-regex", "fraction", "iso8601", - "itoa 1.0.5", + "itoa", "lazy_static", "memchr", "num-cmp", @@ -1864,14 +1836,14 @@ dependencies = [ [[package]] name = "mio" -version = "0.8.5" +version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5d732bc30207a6423068df043e3d02e0735b155ad7ce1a6f76fe2baa5b158de" +checksum = "5b9d9a46eff5b4ff64b45a9e316a6d1e0bc719ef429cbec4dc630684212bfdf9" dependencies = [ "libc", "log", "wasi 0.11.0+wasi-snapshot-preview1", - "windows-sys 0.42.0", + "windows-sys 0.45.0", ] [[package]] @@ -2535,12 +2507,6 @@ dependencies = [ "regex-syntax", ] -[[package]] -name = "regex-automata" -version = "0.1.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132" - [[package]] name = "regex-syntax" version = "0.6.28" @@ -2558,18 +2524,18 @@ dependencies = [ [[package]] name = "rend" -version = "0.3.6" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "79af64b4b6362ffba04eef3a4e10829718a4896dac19daa741851c86781edf95" +checksum = "581008d2099240d37fb08d77ad713bcaec2c4d89d50b5b21a8bb1996bbab68ab" dependencies = [ "bytecheck", ] [[package]] name = "rkyv" -version = "0.7.39" +version = "0.7.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cec2b3485b07d96ddfd3134767b8a447b45ea4eb91448d0a35180ec0ffd5ed15" +checksum = "c30f1d45d9aa61cbc8cd1eb87705470892289bb2d01943e7803b873a57404dc3" dependencies = [ "bytecheck", "hashbrown 0.12.3", @@ -2581,9 +2547,9 @@ dependencies = [ [[package]] name = "rkyv_derive" -version = "0.7.39" +version = "0.7.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6eaedadc88b53e36dd32d940ed21ae4d850d5916f2581526921f553a72ac34c4" +checksum = "ff26ed6c7c4dfc2aa9480b86a60e3c7233543a270a680e10758a507c5a4ce476" dependencies = [ "proc-macro2", "quote", @@ -2790,7 +2756,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cad406b69c91885b5107daf2c29572f6c8cdb3c66826821e286c533490c0bc76" dependencies = [ "indexmap", - "itoa 1.0.5", + "itoa", "ryu", "serde", ] @@ -2808,9 +2774,9 @@ dependencies = [ [[package]] name = "serde_with" -version = "2.1.0" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25bf4a5a814902cd1014dbccfa4d4560fb8432c779471e96e035602519f82eef" +checksum = "30d904179146de381af4c93d3af6ca4984b3152db687dacb9c3c35e86f39809c" dependencies = [ "base64 0.13.1", "chrono", @@ -2824,9 +2790,9 @@ dependencies = [ [[package]] name = "serde_with_macros" -version = "2.1.0" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3452b4c0f6c1e357f73fdb87cd1efabaa12acf328c7a528e252893baeb3f4aa" +checksum = "a1966009f3c05f095697c537312f5415d1e3ed31ce0a56942bac4c771c5c335e" dependencies = [ "darling", "proc-macro2", @@ -2866,9 +2832,9 @@ checksum = "43b2853a4d09f215c24cc5489c992ce46052d359b5109343cbafbf26bc62f8a3" [[package]] name = "signal-hook-registry" -version = "1.4.0" +version = "1.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e51e73328dc4ac0c7ccbda3a494dfa03df1de2f46018127f60c693f2648455b0" +checksum = "d8229b473baa5980ac72ef434c4415e70c4b5e71b423043adb4ba059f89c99a1" dependencies = [ "libc", ] @@ -3117,7 +3083,7 @@ version = "0.3.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a561bf4617eebd33bca6434b988f39ed798e527f51a1e797d0ee4f61c0a38376" dependencies = [ - "itoa 1.0.5", + "itoa", "serde", "time-core", "time-macros", diff --git a/packages/rs-drive-abci/src/abci/handlers.rs b/packages/rs-drive-abci/src/abci/handlers.rs index 6c2bcc46975..efde25dc313 100644 --- a/packages/rs-drive-abci/src/abci/handlers.rs +++ b/packages/rs-drive-abci/src/abci/handlers.rs @@ -260,7 +260,7 @@ mod tests { }; use dpp::util::hash; use drive::common::helpers::identities::create_test_masternode_identities; - use drive::common::helpers::setup::setup_document; + use drive::common::helpers::setup::{setup_document, setup_system_data_contract}; use drive::drive::block_info::BlockInfo; use drive::drive::identity::withdrawals::paths::WithdrawalTransaction; use drive::fee::epoch::CreditsPerEpoch; @@ -274,7 +274,6 @@ mod tests { use crate::abci::messages::{ AfterFinalizeBlockRequest, BlockBeginRequest, BlockEndRequest, BlockFees, }; - use crate::config::PlatformConfig; use crate::test::fixture::abci::static_init_chain_request; use crate::test::helpers::fee_pools::create_test_masternode_share_identities_and_documents; use crate::test::helpers::setup::setup_platform_raw; diff --git a/packages/rs-drive-abci/src/identity_credit_withdrawal/mod.rs b/packages/rs-drive-abci/src/identity_credit_withdrawal/mod.rs index c5b6daf9330..c9a0f828dee 100644 --- a/packages/rs-drive-abci/src/identity_credit_withdrawal/mod.rs +++ b/packages/rs-drive-abci/src/identity_credit_withdrawal/mod.rs @@ -9,11 +9,12 @@ use dashcore::{ hashes::Hash, QuorumHash, Script, TxOut, }; -use dpp::{ - contracts::withdrawals_contract, data_contract::DriveContractExt, - document::document_stub::DocumentStub, identity::convert_credits_to_satoshi, - prelude::Identifier, util::hash, -}; +use drive::dpp::contracts::withdrawals_contract; +use drive::dpp::data_contract::DriveContractExt; +use drive::dpp::document::document_stub::DocumentStub; +use drive::dpp::identifier::Identifier; +use drive::dpp::identity::convert_credits_to_satoshi; +use drive::dpp::util::hash; use drive::{ drive::{ batch::DriveOperationType, block_info::BlockInfo, @@ -508,8 +509,7 @@ mod tests { use drive::{common::helpers::setup::setup_document, rpc::core::MockCoreRPCLike}; use serde_json::json; - use crate::common::helpers::setup::setup_platform_with_initial_state_structure; - use crate::common::helpers::setup::setup_system_data_contract; + use crate::test::helpers::setup::setup_platform_with_initial_state_structure; use dpp::identity::state_transition::identity_credit_withdrawal_transition::Pooling; @@ -517,7 +517,9 @@ mod tests { mod update_withdrawal_statuses { use crate::block::BlockStateInfo; + use crate::test::helpers::setup::setup_platform_with_initial_state_structure; use dpp::data_contract::{DataContract, DriveContractExt}; + use drive::common::helpers::setup::setup_system_data_contract; use super::*; @@ -655,6 +657,7 @@ mod tests { previous_epoch_index: None, is_epoch_change: false, }, + hpmn_count: 100, }, Some(&transaction), ) @@ -693,8 +696,11 @@ mod tests { mod pool_withdrawals_into_transactions { use dpp::data_contract::DriveContractExt; use dpp::identity::state_transition::identity_credit_withdrawal_transition::Pooling; + use drive::common::helpers::setup::setup_system_data_contract; + use drive::dpp::contracts::withdrawals_contract; use crate::block::BlockStateInfo; + use crate::test::helpers::setup::setup_platform_with_initial_state_structure; use super::*; @@ -770,6 +776,7 @@ mod tests { previous_epoch_index: None, is_epoch_change: false, }, + hpmn_count: 100, }, Some(&transaction), ) @@ -803,8 +810,8 @@ mod tests { } mod fetch_core_block_transactions { - use super::*; + use crate::test::helpers::setup::setup_platform_with_initial_state_structure; #[test] fn test_fetches_core_transactions() { @@ -868,11 +875,13 @@ mod tests { } mod build_withdrawal_transactions_from_documents { + use crate::test::helpers::setup::setup_platform_with_initial_state_structure; use dpp::data_contract::DriveContractExt; use dpp::{ document::document_stub::DocumentStub, identity::state_transition::identity_credit_withdrawal_transition::Pooling, }; + use drive::common::helpers::setup::setup_system_data_contract; use drive::drive::identity::withdrawals::paths::WithdrawalTransaction; use itertools::Itertools; diff --git a/packages/rs-drive-abci/src/state/genesis.rs b/packages/rs-drive-abci/src/state/genesis.rs index e940abc2757..903f673455e 100644 --- a/packages/rs-drive-abci/src/state/genesis.rs +++ b/packages/rs-drive-abci/src/state/genesis.rs @@ -269,6 +269,7 @@ impl Platform { id: DPNS_DASH_TLD_DOCUMENT_ID, properties: document_stub_properties, owner_id: contract.owner_id.to_buffer(), + revision: 1, }; let document_type = contract.document_type_for_name("domain")?; @@ -318,8 +319,8 @@ mod tests { assert_eq!( root_hash, [ - 223, 238, 172, 129, 164, 189, 41, 188, 64, 164, 89, 92, 216, 66, 225, 17, 106, - 82, 196, 145, 103, 87, 239, 183, 226, 201, 79, 71, 248, 183, 191, 178, + 110, 6, 47, 121, 177, 99, 0, 7, 150, 5, 202, 92, 21, 81, 169, 64, 87, 150, 198, + 125, 110, 57, 207, 50, 251, 8, 138, 166, 106, 80, 232, 142, ] ) } 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 5e4c536db68..6026bc68ed3 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 @@ -25,10 +25,10 @@ mod tests { }), }; let config = PlatformConfig { - drive_config: Default::default(), verify_sum_trees: true, quorum_size: 100, validator_set_quorum_rotation_block_count: 125, + ..Default::default() }; let twenty_minutes_in_ms = 1000 * 60 * 20; let ChainExecutionOutcome { @@ -219,10 +219,10 @@ mod tests { }), }; let config = PlatformConfig { - drive_config: Default::default(), verify_sum_trees: true, quorum_size: 40, validator_set_quorum_rotation_block_count: 50, + ..Default::default() }; let hour_in_ms = 1000 * 60 * 60; let ChainExecutionOutcome { @@ -391,10 +391,10 @@ mod tests { }), }; let config = PlatformConfig { - drive_config: Default::default(), verify_sum_trees: true, quorum_size: 50, validator_set_quorum_rotation_block_count: 60, + ..Default::default() }; let hour_in_ms = 1000 * 60 * 60; let ChainExecutionOutcome { @@ -638,10 +638,10 @@ mod tests { }), }; let config = PlatformConfig { - drive_config: Default::default(), verify_sum_trees: true, quorum_size: 50, validator_set_quorum_rotation_block_count: 60, + ..Default::default() }; let hour_in_ms = 1000 * 60 * 60; let ChainExecutionOutcome { diff --git a/packages/rs-drive/src/drive/document/update.rs b/packages/rs-drive/src/drive/document/update.rs index b9dc6d32be2..4660bdb91f7 100644 --- a/packages/rs-drive/src/drive/document/update.rs +++ b/packages/rs-drive/src/drive/document/update.rs @@ -303,374 +303,334 @@ impl Drive { let contract = document_and_contract_info.contract; let document_type = document_and_contract_info.document_type; let owner_id = document_and_contract_info.owned_document_info.owner_id; - match document_and_contract_info.owned_document_info.document_info { - DocumentRefAndSerialization((document, _, ref storage_flags)) - | DocumentRefWithoutSerialization((document, ref storage_flags)) => { - // we need to construct the path for documents on the contract - // the path is - // * Document and Contract root tree - // * Contract ID recovered from document - // * 0 to signify Documents and not Contract - let contract_document_type_path = contract_document_type_path( - contract.id.as_bytes(), - document_type.name.as_str(), - ); + let Some((document, storage_flags)) = document_and_contract_info.owned_document_info.document_info.get_borrowed_document_and_storage_flags() else { + return Err(Error::Drive(DriveError::CorruptedCodeExecution("must have document and storage flags"))); + }; + // we need to construct the path for documents on the contract + // the path is + // * Document and Contract root tree + // * Contract ID recovered from document + // * 0 to signify Documents and not Contract + let contract_document_type_path = + contract_document_type_path(contract.id.as_bytes(), document_type.name.as_str()); + + let contract_documents_primary_key_path = contract_documents_primary_key_path( + contract.id.as_bytes(), + document_type.name.as_str(), + ); + + let document_reference = make_document_reference( + document, + document_and_contract_info.document_type, + storage_flags, + ); - let contract_documents_primary_key_path = contract_documents_primary_key_path( + // next we need to get the old document from storage + let old_document_element = if document_type.documents_keep_history { + let contract_documents_keeping_history_primary_key_path_for_document_id = + contract_documents_keeping_history_primary_key_path_for_document_id( contract.id.as_bytes(), document_type.name.as_str(), + document.id.as_slice(), ); + // When keeping document history the 0 is a reference that points to the current value + // O is just on one byte, so we have at most one hop of size 1 (1 byte) + self.grove_get( + contract_documents_keeping_history_primary_key_path_for_document_id, + &[0], + QueryType::StatefulQuery, + transaction, + &mut batch_operations, + )? + } else { + self.grove_get_raw( + contract_documents_primary_key_path, + document.id.as_slice(), + DirectQueryType::StatefulDirectQuery, + transaction, + &mut batch_operations, + )? + }; + + // we need to store the document for it's primary key + // we should be overriding if the document_type does not have history enabled + self.add_document_to_primary_storage( + &document_and_contract_info, + block_info, + true, + estimated_costs_only_with_layer_info, + transaction, + &mut batch_operations, + )?; - let document_reference = make_document_reference( + let old_document_info = if let Some(old_document_element) = old_document_element { + if let Element::Item(old_serialized_document, element_flags) = old_document_element { + let document_result = + DocumentStub::from_cbor(old_serialized_document.as_slice(), None, owner_id); + let document = match document_result { + Ok(document_result) => Ok(document_result), + Err(_) => { + DocumentStub::from_bytes(old_serialized_document.as_slice(), document_type) + } + }?; + let storage_flags = StorageFlags::map_some_element_flags_ref(&element_flags)?; + Ok(DocumentWithoutSerialization(( document, - document_and_contract_info.document_type, - storage_flags.as_ref().map(|flags| flags.as_ref()), - ); + storage_flags.map(Cow::Owned), + ))) + } else { + Err(Error::Drive(DriveError::CorruptedDocumentNotItem( + "old document is not an item", + ))) + }? + } else { + return Err(Error::Drive(DriveError::UpdatingDocumentThatDoesNotExist( + "document being updated does not exist", + ))); + }; - // next we need to get the old document from storage - let old_document_element = if document_type.documents_keep_history { - let contract_documents_keeping_history_primary_key_path_for_document_id = - contract_documents_keeping_history_primary_key_path_for_document_id( - contract.id.as_bytes(), - document_type.name.as_str(), - document.id.as_slice(), - ); - // When keeping document history the 0 is a reference that points to the current value - // O is just on one byte, so we have at most one hop of size 1 (1 byte) - self.grove_get( - contract_documents_keeping_history_primary_key_path_for_document_id, - &[0], - QueryType::StatefulQuery, - transaction, - &mut batch_operations, - )? - } else { - self.grove_get_raw( - contract_documents_primary_key_path, - document.id.as_slice(), - DirectQueryType::StatefulDirectQuery, + let mut batch_insertion_cache: HashSet>> = HashSet::new(); + // fourth we need to store a reference to the document for each index + for index in &document_type.indices { + // at this point the contract path is to the contract documents + // for each index the top index component will already have been added + // when the contract itself was created + let mut index_path: Vec> = contract_document_type_path + .iter() + .map(|&x| Vec::from(x)) + .collect(); + let top_index_property = index.properties.get(0).ok_or(Error::Drive( + DriveError::CorruptedContractIndexes("invalid contract indices"), + ))?; + index_path.push(Vec::from(top_index_property.name.as_bytes())); + + // with the example of the dashpay contract's first index + // the index path is now something like Contracts/ContractID/Documents(1)/$ownerId + let document_top_field = document + .get_raw_for_document_type(&top_index_property.name, document_type, owner_id)? + .unwrap_or_default(); + + let old_document_top_field = old_document_info + .get_raw_for_document_type(&top_index_property.name, document_type, owner_id, None)? + .unwrap_or_default(); + + // if we are not applying that means we are trying to get worst case costs + // which would entail a change on every index + let mut change_occurred_on_index = match &old_document_top_field { + DriveKeyInfo::Key(k) => &document_top_field != k, + DriveKeyInfo::KeyRef(k) => document_top_field.as_slice() != *k, + DriveKeyInfo::KeySize(_) => { + // we should assume true in this worst case cost scenario + true + } + }; + + if change_occurred_on_index { + // here we are inserting an empty tree that will have a subtree of all other index properties + let mut qualified_path = index_path.clone(); + qualified_path.push(document_top_field.clone()); + + if !batch_insertion_cache.contains(&qualified_path) { + let inserted = self.batch_insert_empty_tree_if_not_exists( + PathKeyInfo::PathKeyRef::<0>(( + index_path.clone(), + document_top_field.as_slice(), + )), + storage_flags, + BatchInsertTreeApplyType::StatefulBatchInsertTree, transaction, + previous_batch_operations, &mut batch_operations, - )? - }; + )?; + if inserted { + batch_insertion_cache.insert(qualified_path); + } + } + } - // we need to store the document for it's primary key - // we should be overriding if the document_type does not have history enabled - self.add_document_to_primary_storage( - &document_and_contract_info, - block_info, - true, - estimated_costs_only_with_layer_info, - transaction, - &mut batch_operations, - )?; - - let old_document_info = if let Some(old_document_element) = old_document_element { - if let Element::Item(old_serialized_document, element_flags) = - old_document_element - { - let document_result = DocumentStub::from_cbor( - old_serialized_document.as_slice(), - None, - owner_id, - ); - let document = match document_result { - Ok(document_result) => Ok(document_result), - Err(_) => DocumentStub::from_bytes( - old_serialized_document.as_slice(), - document_type, - ), - }?; - let storage_flags = - StorageFlags::map_some_element_flags_ref(&element_flags)?; - Ok(DocumentWithoutSerialization(( - document, - storage_flags.map(Cow::Owned), - ))) - } else { - Err(Error::Drive(DriveError::CorruptedDocumentNotItem( - "old document is not an item", - ))) - }? - } else { - return Err(Error::Drive(DriveError::UpdatingDocumentThatDoesNotExist( - "document being updated does not exist", - ))); + let mut all_fields_null = document_top_field.is_empty(); + + let mut old_index_path: Vec = index_path + .iter() + .map(|path_item| DriveKeyInfo::Key(path_item.clone())) + .collect(); + // we push the actual value of the index path + index_path.push(document_top_field); + // the index path is now something like Contracts/ContractID/Documents(1)/$ownerId/ + + old_index_path.push(old_document_top_field); + + for i in 1..index.properties.len() { + let index_property = index.properties.get(i).ok_or(Error::Drive( + DriveError::CorruptedContractIndexes("invalid contract indices"), + ))?; + + let document_index_field = document + .get_raw_for_document_type(&index_property.name, document_type, owner_id)? + .unwrap_or_default(); + + let old_document_index_field = old_document_info + .get_raw_for_document_type(&index_property.name, document_type, owner_id, None)? + .unwrap_or_default(); + + // if we are not applying that means we are trying to get worst case costs + // which would entail a change on every index + change_occurred_on_index |= match &old_document_index_field { + DriveKeyInfo::Key(k) => &document_index_field != k, + DriveKeyInfo::KeyRef(k) => document_index_field != *k, + DriveKeyInfo::KeySize(_) => { + // we should assume true in this worst case cost scenario + true + } }; - let mut batch_insertion_cache: HashSet>> = HashSet::new(); - // fourth we need to store a reference to the document for each index - for index in &document_type.indices { - // at this point the contract path is to the contract documents - // for each index the top index component will already have been added - // when the contract itself was created - let mut index_path: Vec> = contract_document_type_path - .iter() - .map(|&x| Vec::from(x)) - .collect(); - let top_index_property = index.properties.get(0).ok_or(Error::Drive( - DriveError::CorruptedContractIndexes("invalid contract indices"), - ))?; - index_path.push(Vec::from(top_index_property.name.as_bytes())); - - // with the example of the dashpay contract's first index - // the index path is now something like Contracts/ContractID/Documents(1)/$ownerId - let document_top_field = document - .get_raw_for_document_type( - &top_index_property.name, - document_type, - owner_id, - )? - .unwrap_or_default(); - - let old_document_top_field = old_document_info - .get_raw_for_document_type( - &top_index_property.name, - document_type, - owner_id, - None, - )? - .unwrap_or_default(); - - // if we are not applying that means we are trying to get worst case costs - // which would entail a change on every index - let mut change_occurred_on_index = match &old_document_top_field { - DriveKeyInfo::Key(k) => &document_top_field != k, - DriveKeyInfo::KeyRef(k) => document_top_field.as_slice() != *k, - DriveKeyInfo::KeySize(_) => { - // we should assume true in this worst case cost scenario - true - } - }; - - if change_occurred_on_index { - // here we are inserting an empty tree that will have a subtree of all other index properties - let mut qualified_path = index_path.clone(); - qualified_path.push(document_top_field.clone()); - - if !batch_insertion_cache.contains(&qualified_path) { - let inserted = self.batch_insert_empty_tree_if_not_exists( - PathKeyInfo::PathKeyRef::<0>(( - index_path.clone(), - document_top_field.as_slice(), - )), - storage_flags.as_ref().map(|flags| flags.as_ref()), - BatchInsertTreeApplyType::StatefulBatchInsertTree, - transaction, - previous_batch_operations, - &mut batch_operations, - )?; - if inserted { - batch_insertion_cache.insert(qualified_path); - } - } - } + if change_occurred_on_index { + // here we are inserting an empty tree that will have a subtree of all other index properties - let mut all_fields_null = document_top_field.is_empty(); - - let mut old_index_path: Vec = index_path - .iter() - .map(|path_item| DriveKeyInfo::Key(path_item.clone())) - .collect(); - // we push the actual value of the index path - index_path.push(document_top_field); - // the index path is now something like Contracts/ContractID/Documents(1)/$ownerId/ - - old_index_path.push(old_document_top_field); - - for i in 1..index.properties.len() { - let index_property = index.properties.get(i).ok_or(Error::Drive( - DriveError::CorruptedContractIndexes("invalid contract indices"), - ))?; - - let document_index_field = document - .get_raw_for_document_type( - &index_property.name, - document_type, - owner_id, - )? - .unwrap_or_default(); - - let old_document_index_field = old_document_info - .get_raw_for_document_type( - &index_property.name, - document_type, - owner_id, - None, - )? - .unwrap_or_default(); - - // if we are not applying that means we are trying to get worst case costs - // which would entail a change on every index - change_occurred_on_index |= match &old_document_index_field { - DriveKeyInfo::Key(k) => &document_index_field != k, - DriveKeyInfo::KeyRef(k) => document_index_field != *k, - DriveKeyInfo::KeySize(_) => { - // we should assume true in this worst case cost scenario - true - } - }; - - if change_occurred_on_index { - // here we are inserting an empty tree that will have a subtree of all other index properties - - let mut qualified_path = index_path.clone(); - qualified_path.push(index_property.name.as_bytes().to_vec()); - - if !batch_insertion_cache.contains(&qualified_path) { - let inserted = self.batch_insert_empty_tree_if_not_exists( - PathKeyInfo::PathKeyRef::<0>(( - index_path.clone(), - index_property.name.as_bytes(), - )), - storage_flags.as_ref().map(|flags| flags.as_ref()), - BatchInsertTreeApplyType::StatefulBatchInsertTree, - transaction, - previous_batch_operations, - &mut batch_operations, - )?; - if inserted { - batch_insertion_cache.insert(qualified_path); - } - } - } + let mut qualified_path = index_path.clone(); + qualified_path.push(index_property.name.as_bytes().to_vec()); - index_path.push(Vec::from(index_property.name.as_bytes())); - old_index_path - .push(DriveKeyInfo::Key(Vec::from(index_property.name.as_bytes()))); - - // Iteration 1. the index path is now something like Contracts/ContractID/Documents(1)/$ownerId//toUserId - // Iteration 2. the index path is now something like Contracts/ContractID/Documents(1)/$ownerId//toUserId//accountReference - - if change_occurred_on_index { - // here we are inserting an empty tree that will have a subtree of all other index properties - - let mut qualified_path = index_path.clone(); - qualified_path.push(document_index_field.clone()); - - if !batch_insertion_cache.contains(&qualified_path) { - let inserted = self.batch_insert_empty_tree_if_not_exists( - PathKeyInfo::PathKeyRef::<0>(( - index_path.clone(), - document_index_field.as_slice(), - )), - storage_flags.as_ref().map(|flags| flags.as_ref()), - BatchInsertTreeApplyType::StatefulBatchInsertTree, - transaction, - previous_batch_operations, - &mut batch_operations, - )?; - if inserted { - batch_insertion_cache.insert(qualified_path); - } - } + if !batch_insertion_cache.contains(&qualified_path) { + let inserted = self.batch_insert_empty_tree_if_not_exists( + PathKeyInfo::PathKeyRef::<0>(( + index_path.clone(), + index_property.name.as_bytes(), + )), + storage_flags, + BatchInsertTreeApplyType::StatefulBatchInsertTree, + transaction, + previous_batch_operations, + &mut batch_operations, + )?; + if inserted { + batch_insertion_cache.insert(qualified_path); } + } + } - all_fields_null &= document_index_field.is_empty(); + index_path.push(Vec::from(index_property.name.as_bytes())); + old_index_path.push(DriveKeyInfo::Key(Vec::from(index_property.name.as_bytes()))); - // we push the actual value of the index path, both for the new and the old - index_path.push(document_index_field); - old_index_path.push(old_document_index_field); - // Iteration 1. the index path is now something like Contracts/ContractID/Documents(1)/$ownerId//toUserId// - // Iteration 2. the index path is now something like Contracts/ContractID/Documents(1)/$ownerId//toUserId//accountReference/ - } + // Iteration 1. the index path is now something like Contracts/ContractID/Documents(1)/$ownerId//toUserId + // Iteration 2. the index path is now something like Contracts/ContractID/Documents(1)/$ownerId//toUserId//accountReference - if change_occurred_on_index { - // we first need to delete the old values - // unique indexes will be stored under key "0" - // non unique indices should have a tree at key "0" that has all elements based off of primary key - - let mut key_info_path = KeyInfoPath::from_vec( - old_index_path - .into_iter() - .map(|key_info| match key_info { - Key(key) => KnownKey(key), - KeyRef(key_ref) => KnownKey(key_ref.to_vec()), - KeySize(key_info) => key_info, - }) - .collect::>(), - ); - - if !index.unique { - key_info_path.push(KnownKey(vec![0])); - - // here we should return an error if the element already exists - self.batch_delete_up_tree_while_empty( - key_info_path, - document.id.as_slice(), - Some(CONTRACT_DOCUMENTS_PATH_HEIGHT), - BatchDeleteUpTreeApplyType::StatefulBatchDelete { - is_known_to_be_subtree_with_sum: Some((false, false)), - }, - transaction, - previous_batch_operations, - &mut batch_operations, - )?; - } else { - // here we should return an error if the element already exists - self.batch_delete_up_tree_while_empty( - key_info_path, - &[0], - Some(CONTRACT_DOCUMENTS_PATH_HEIGHT), - BatchDeleteUpTreeApplyType::StatefulBatchDelete { - is_known_to_be_subtree_with_sum: Some((false, false)), - }, - transaction, - previous_batch_operations, - &mut batch_operations, - )?; - } + if change_occurred_on_index { + // here we are inserting an empty tree that will have a subtree of all other index properties - // unique indexes will be stored under key "0" - // non unique indices should have a tree at key "0" that has all elements based off of primary key - if !index.unique || all_fields_null { - // here we are inserting an empty tree that will have a subtree of all other index properties - self.batch_insert_empty_tree_if_not_exists( - PathKeyInfo::PathKeyRef::<0>((index_path.clone(), &[0])), - storage_flags.as_ref().map(|flags| flags.as_ref()), - BatchInsertTreeApplyType::StatefulBatchInsertTree, - transaction, - previous_batch_operations, - &mut batch_operations, - )?; - index_path.push(vec![0]); - - // here we should return an error if the element already exists - self.batch_insert( - PathKeyRefElement::<0>(( - index_path, - document.id.as_slice(), - document_reference.clone(), - )), - &mut batch_operations, - )?; - } else { - // in one update you can't insert an element twice, so need to check the cache - // here we should return an error if the element already exists - let inserted = self.batch_insert_if_not_exists( - PathKeyRefElement::<0>(( - index_path, - &[0], - document_reference.clone(), - )), - BatchInsertApplyType::StatefulBatchInsert, - transaction, - &mut batch_operations, - )?; - if !inserted { - return Err(Error::Drive(DriveError::CorruptedContractIndexes( - "index already exists", - ))); - } + let mut qualified_path = index_path.clone(); + qualified_path.push(document_index_field.clone()); + + if !batch_insertion_cache.contains(&qualified_path) { + let inserted = self.batch_insert_empty_tree_if_not_exists( + PathKeyInfo::PathKeyRef::<0>(( + index_path.clone(), + document_index_field.as_slice(), + )), + storage_flags, + BatchInsertTreeApplyType::StatefulBatchInsertTree, + transaction, + previous_batch_operations, + &mut batch_operations, + )?; + if inserted { + batch_insertion_cache.insert(qualified_path); } } } + + all_fields_null &= document_index_field.is_empty(); + + // we push the actual value of the index path, both for the new and the old + index_path.push(document_index_field); + old_index_path.push(old_document_index_field); + // Iteration 1. the index path is now something like Contracts/ContractID/Documents(1)/$ownerId//toUserId// + // Iteration 2. the index path is now something like Contracts/ContractID/Documents(1)/$ownerId//toUserId//accountReference/ } - DocumentWithoutSerialization(_) => { - todo!() - } - DocumentEstimatedAverageSize(_) => { - unreachable!() + + if change_occurred_on_index { + // we first need to delete the old values + // unique indexes will be stored under key "0" + // non unique indices should have a tree at key "0" that has all elements based off of primary key + + let mut key_info_path = KeyInfoPath::from_vec( + old_index_path + .into_iter() + .map(|key_info| match key_info { + Key(key) => KnownKey(key), + KeyRef(key_ref) => KnownKey(key_ref.to_vec()), + KeySize(key_info) => key_info, + }) + .collect::>(), + ); + + if !index.unique { + key_info_path.push(KnownKey(vec![0])); + + // here we should return an error if the element already exists + self.batch_delete_up_tree_while_empty( + key_info_path, + document.id.as_slice(), + Some(CONTRACT_DOCUMENTS_PATH_HEIGHT), + BatchDeleteUpTreeApplyType::StatefulBatchDelete { + is_known_to_be_subtree_with_sum: Some((false, false)), + }, + transaction, + previous_batch_operations, + &mut batch_operations, + )?; + } else { + // here we should return an error if the element already exists + self.batch_delete_up_tree_while_empty( + key_info_path, + &[0], + Some(CONTRACT_DOCUMENTS_PATH_HEIGHT), + BatchDeleteUpTreeApplyType::StatefulBatchDelete { + is_known_to_be_subtree_with_sum: Some((false, false)), + }, + transaction, + previous_batch_operations, + &mut batch_operations, + )?; + } + + // unique indexes will be stored under key "0" + // non unique indices should have a tree at key "0" that has all elements based off of primary key + if !index.unique || all_fields_null { + // here we are inserting an empty tree that will have a subtree of all other index properties + self.batch_insert_empty_tree_if_not_exists( + PathKeyInfo::PathKeyRef::<0>((index_path.clone(), &[0])), + storage_flags, + BatchInsertTreeApplyType::StatefulBatchInsertTree, + transaction, + previous_batch_operations, + &mut batch_operations, + )?; + index_path.push(vec![0]); + + // here we should return an error if the element already exists + self.batch_insert( + PathKeyRefElement::<0>(( + index_path, + document.id.as_slice(), + document_reference.clone(), + )), + &mut batch_operations, + )?; + } else { + // in one update you can't insert an element twice, so need to check the cache + // here we should return an error if the element already exists + let inserted = self.batch_insert_if_not_exists( + PathKeyRefElement::<0>((index_path, &[0], document_reference.clone())), + BatchInsertApplyType::StatefulBatchInsert, + transaction, + &mut batch_operations, + )?; + if !inserted { + return Err(Error::Drive(DriveError::CorruptedContractIndexes( + "index already exists", + ))); + } + } } } Ok(batch_operations) diff --git a/packages/rs-drive/src/drive/identity/withdrawals/delete.rs b/packages/rs-drive/src/drive/identity/withdrawals/delete.rs index 31a7092e4dd..3af85abbce7 100644 --- a/packages/rs-drive/src/drive/identity/withdrawals/delete.rs +++ b/packages/rs-drive/src/drive/identity/withdrawals/delete.rs @@ -12,7 +12,7 @@ impl Drive { &self, id: &[u8], transaction: TransactionArg, - ) -> Result<(Vec), Error> { + ) -> Result, Error> { let mut drive_operations = vec![]; let path = get_withdrawal_transactions_queue_path(); diff --git a/packages/rs-drive/src/drive/identity/withdrawals/expired_index.rs b/packages/rs-drive/src/drive/identity/withdrawals/expired_index.rs index e91937ab88c..3d04afd5793 100644 --- a/packages/rs-drive/src/drive/identity/withdrawals/expired_index.rs +++ b/packages/rs-drive/src/drive/identity/withdrawals/expired_index.rs @@ -11,7 +11,7 @@ impl Drive { pub(crate) fn insert_withdrawal_expired_index( &self, index: u64, - ) -> Result<(Vec), Error> { + ) -> Result, Error> { let mut drive_operations = vec![]; let index_bytes = index.to_be_bytes(); @@ -34,7 +34,7 @@ impl Drive { &self, key: &[u8], transaction: TransactionArg, - ) -> Result<(Vec), Error> { + ) -> Result, Error> { let mut drive_operations = vec![]; let path: [&[u8]; 2] = get_withdrawal_transactions_expired_ids_path(); diff --git a/packages/rs-drive/src/drive/identity/withdrawals/insert.rs b/packages/rs-drive/src/drive/identity/withdrawals/insert.rs index 411fcade73c..f5b879921d3 100644 --- a/packages/rs-drive/src/drive/identity/withdrawals/insert.rs +++ b/packages/rs-drive/src/drive/identity/withdrawals/insert.rs @@ -12,7 +12,7 @@ impl Drive { pub(crate) fn insert_withdrawal_transactions( &self, transactions: &[WithdrawalTransaction], - ) -> Result<(Vec), Error> { + ) -> Result, Error> { let mut drive_operations = vec![]; let path = get_withdrawal_transactions_queue_path_vec(); diff --git a/packages/rs-drive/src/drive/identity/withdrawals/transaction_index_counter.rs b/packages/rs-drive/src/drive/identity/withdrawals/transaction_index_counter.rs index 516926db73a..68255c4a619 100644 --- a/packages/rs-drive/src/drive/identity/withdrawals/transaction_index_counter.rs +++ b/packages/rs-drive/src/drive/identity/withdrawals/transaction_index_counter.rs @@ -22,7 +22,7 @@ impl Drive { pub(crate) fn update_transaction_index_counter( &self, index: u64, - ) -> Result<(Vec), Error> { + ) -> Result, Error> { let mut drive_operations = vec![]; let path = get_withdrawal_root_path_vec(); diff --git a/packages/rs-drive/src/drive/object_size_info.rs b/packages/rs-drive/src/drive/object_size_info.rs index 8a440bfa6a5..f8360a3102d 100644 --- a/packages/rs-drive/src/drive/object_size_info.rs +++ b/packages/rs-drive/src/drive/object_size_info.rs @@ -679,6 +679,23 @@ impl<'a> DocumentInfo<'a> { } } + /// Gets the borrowed document + pub fn get_borrowed_document_and_storage_flags( + &self, + ) -> Option<(&DocumentStub, Option<&StorageFlags>)> { + match self { + DocumentInfo::DocumentRefAndSerialization((document, _, storage_flags)) + | DocumentInfo::DocumentRefWithoutSerialization((document, storage_flags)) => { + Some((document, storage_flags.as_ref().map(|flags| flags.as_ref()))) + } + DocumentInfo::DocumentWithoutSerialization((document, storage_flags)) + | DocumentInfo::DocumentAndSerialization((document, _, storage_flags)) => { + Some((document, storage_flags.as_ref().map(|flags| flags.as_ref()))) + } + DocumentInfo::DocumentEstimatedAverageSize(_) => None, + } + } + /// Gets storage flags pub fn get_storage_flags_ref(&self) -> Option<&StorageFlags> { match self { From 573cf895f50715f0e5b652c6b1ab9e49928a0356 Mon Sep 17 00:00:00 2001 From: Djavid Gabibiyan Date: Wed, 15 Feb 2023 00:00:56 +0500 Subject: [PATCH 119/170] chore: linter fix --- .../js-drive/lib/abci/handlers/proposal/beginBlockFactory.js | 2 +- .../test/unit/abci/handlers/proposal/beginBlockFactory.spec.js | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/packages/js-drive/lib/abci/handlers/proposal/beginBlockFactory.js b/packages/js-drive/lib/abci/handlers/proposal/beginBlockFactory.js index 341ca536758..b6ea00508d6 100644 --- a/packages/js-drive/lib/abci/handlers/proposal/beginBlockFactory.js +++ b/packages/js-drive/lib/abci/handlers/proposal/beginBlockFactory.js @@ -64,7 +64,7 @@ function beginBlockFactory( proposerProTxHash, proposedAppVersion, round, - quorumHash, + // quorumHash, TODO: revisit once Tenderdash sents something here } = request; if (proposalBlockExecutionContext.isEmpty()) { diff --git a/packages/js-drive/test/unit/abci/handlers/proposal/beginBlockFactory.spec.js b/packages/js-drive/test/unit/abci/handlers/proposal/beginBlockFactory.spec.js index df9ef9b93ab..c91301cc649 100644 --- a/packages/js-drive/test/unit/abci/handlers/proposal/beginBlockFactory.spec.js +++ b/packages/js-drive/test/unit/abci/handlers/proposal/beginBlockFactory.spec.js @@ -115,7 +115,8 @@ describe('beginBlockFactory', () => { fetch: this.sinon.stub().resolves({ getValue: () => undefined, }), - } + }; + validMasternodesListLength = 400; simplifyMasternodeListMock = { From 8eb08a9198633549e25569f0186335c672f10bba Mon Sep 17 00:00:00 2001 From: Djavid Gabibiyan Date: Wed, 15 Feb 2023 15:32:18 +0500 Subject: [PATCH 120/170] chore: quorumHash --- .../lib/abci/handlers/prepareProposalHandlerFactory.js | 2 +- .../js-drive/lib/abci/handlers/proposal/beginBlockFactory.js | 3 ++- .../lib/abci/handlers/proposal/processProposalFactory.js | 2 +- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/packages/js-drive/lib/abci/handlers/prepareProposalHandlerFactory.js b/packages/js-drive/lib/abci/handlers/prepareProposalHandlerFactory.js index 388c77f98ea..9f36462f661 100644 --- a/packages/js-drive/lib/abci/handlers/prepareProposalHandlerFactory.js +++ b/packages/js-drive/lib/abci/handlers/prepareProposalHandlerFactory.js @@ -93,7 +93,7 @@ function prepareProposalHandlerFactory( const blockFees = { storageFee: 0, processingFee: 0, - refundsPerEpoch: { }, + refundsPerEpoch: {}, }; let validTxCount = 0; diff --git a/packages/js-drive/lib/abci/handlers/proposal/beginBlockFactory.js b/packages/js-drive/lib/abci/handlers/proposal/beginBlockFactory.js index b6ea00508d6..1af0dde938f 100644 --- a/packages/js-drive/lib/abci/handlers/proposal/beginBlockFactory.js +++ b/packages/js-drive/lib/abci/handlers/proposal/beginBlockFactory.js @@ -50,6 +50,7 @@ function beginBlockFactory( * @param {Long} request.proposedAppVersion * @param {ITimestamp} request.time * @param {Buffer} request.proposerProTxHash + * @param {Buffer} request.quorumHash * @param {BaseLogger} contextLogger * * @return {Promise} @@ -64,7 +65,7 @@ function beginBlockFactory( proposerProTxHash, proposedAppVersion, round, - // quorumHash, TODO: revisit once Tenderdash sents something here + quorumHash, } = request; if (proposalBlockExecutionContext.isEmpty()) { diff --git a/packages/js-drive/lib/abci/handlers/proposal/processProposalFactory.js b/packages/js-drive/lib/abci/handlers/proposal/processProposalFactory.js index 449aaccba6f..85907f69401 100644 --- a/packages/js-drive/lib/abci/handlers/proposal/processProposalFactory.js +++ b/packages/js-drive/lib/abci/handlers/proposal/processProposalFactory.js @@ -68,7 +68,7 @@ function processProposalFactory( const blockFees = { storageFee: 0, processingFee: 0, - refundsPerEpoch: { }, + refundsPerEpoch: {}, }; let validTxCount = 0; From c30ec2022db4163094590abd722795d06511f16b Mon Sep 17 00:00:00 2001 From: Djavid Gabibiyan Date: Wed, 15 Feb 2023 15:36:03 +0500 Subject: [PATCH 121/170] chore: quorumHash --- .../js-drive/lib/abci/handlers/proposal/beginBlockFactory.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/packages/js-drive/lib/abci/handlers/proposal/beginBlockFactory.js b/packages/js-drive/lib/abci/handlers/proposal/beginBlockFactory.js index 1af0dde938f..a159db141e4 100644 --- a/packages/js-drive/lib/abci/handlers/proposal/beginBlockFactory.js +++ b/packages/js-drive/lib/abci/handlers/proposal/beginBlockFactory.js @@ -139,8 +139,7 @@ function beginBlockFactory( blockHeight: height.toNumber(), blockTimeMs: proposalBlockExecutionContext.getTimeMs(), proposerProTxHash, - // TODO replace with real value - validatorSetQuorumHash: Buffer.alloc(32), + validatorSetQuorumHash: quorumHash, coreChainLockedHeight, lastSyncedCoreHeight, // TODO: Since we don't have HPMNs now and every masternode can be a validator, From 2868d68e29d197dec3b6785d5b914ae9d69fa132 Mon Sep 17 00:00:00 2001 From: Djavid Gabibiyan Date: Wed, 15 Feb 2023 20:24:00 +0500 Subject: [PATCH 122/170] chore: wip --- .../IdentityPublicKeyStoreRepository.spec.js | 18 ++++++---- ...hronizeMasternodeIdentitiesFactory.spec.js | 16 ++++----- .../withdrawals_data_triggers/mod.rs | 10 +++--- .../fixtures/get_withdrawals_data_contract.rs | 34 ------------------- packages/rs-dpp/src/tests/fixtures/mod.rs | 2 -- packages/rs-drive-abci/src/abci/handlers.rs | 12 +++---- .../src/identity_credit_withdrawal/mod.rs | 24 +++++++------ .../identity/withdrawals/withdrawal_status.rs | 10 +++--- 8 files changed, 50 insertions(+), 76 deletions(-) delete mode 100644 packages/rs-dpp/src/tests/fixtures/get_withdrawals_data_contract.rs diff --git a/packages/js-drive/test/integration/identity/IdentityPublicKeyStoreRepository.spec.js b/packages/js-drive/test/integration/identity/IdentityPublicKeyStoreRepository.spec.js index d673041f153..b51a68f8c25 100644 --- a/packages/js-drive/test/integration/identity/IdentityPublicKeyStoreRepository.spec.js +++ b/packages/js-drive/test/integration/identity/IdentityPublicKeyStoreRepository.spec.js @@ -19,14 +19,20 @@ describe('IdentityPublicKeyStoreRepository', () => { beforeEach(async () => { rsDrive = new Drive('./db/grovedb_test', { - dataContractsGlobalCacheSize: 500, - dataContractsBlockCacheSize: 500, + drive: { + dataContractsGlobalCacheSize: 500, + dataContractsBlockCacheSize: 500, + }, + core: { + rpc: { + url: '127.0.0.1', + username: '', + password: '', + }, + }, }); - store = new GroveDBStore(rsDrive, logger, { - dataContractsGlobalCacheSize: 500, - dataContractsBlockCacheSize: 500, - }); + store = new GroveDBStore(rsDrive, logger); await rsDrive.createInitialStateStructure(); diff --git a/packages/js-drive/test/integration/identity/masternode/synchronizeMasternodeIdentitiesFactory.spec.js b/packages/js-drive/test/integration/identity/masternode/synchronizeMasternodeIdentitiesFactory.spec.js index d32e5129071..ad9cbfd11e3 100644 --- a/packages/js-drive/test/integration/identity/masternode/synchronizeMasternodeIdentitiesFactory.spec.js +++ b/packages/js-drive/test/integration/identity/masternode/synchronizeMasternodeIdentitiesFactory.spec.js @@ -363,7 +363,7 @@ describe('synchronizeMasternodeIdentitiesFactory', () => { beforeEach(async function beforeEach() { coreHeight = 3; - firstSyncAppHash = '14d2b6052ff8d3b86f1ea9e2a4c4abfc55aebebc21c33cb2168b0059e67b3a01'; + firstSyncAppHash = 'b64dc96e18c2d0f5854629d3fd65c61b84c18a98bdeb3c66a911d74dc9c3ffb6'; blockInfo = new BlockInfo(10, 0, 1668702100799); container = await createTestDIContainer(); @@ -680,7 +680,7 @@ describe('synchronizeMasternodeIdentitiesFactory', () => { // Nothing happened - await expectDeterministicAppHash('d49fe295c56149b456184957c3a7593e144d91a8da56b2cb0e25848d656ceba5'); + await expectDeterministicAppHash('4190498f5a8bc3d9a513f509c2ab34d02235bd368b832d47ca0a9afd99cd51a7'); // Core RPC should be called @@ -716,7 +716,7 @@ describe('synchronizeMasternodeIdentitiesFactory', () => { expect(result2.updatedEntities).to.have.lengthOf(0); expect(result2.removedEntities).to.have.lengthOf(0); - await expectDeterministicAppHash('6f88afb152b8062c9efb09a271970d016d0d2f90193ee46163fbb79aaca9e0b2'); + await expectDeterministicAppHash('752027b03c4ba31ce0d7ab86dd5de7bb152a69a07fe9b008bb1b99a9c5ce92dc'); // New masternode identity should be created @@ -800,7 +800,7 @@ describe('synchronizeMasternodeIdentitiesFactory', () => { expect(result.updatedEntities).to.have.lengthOf(0); expect(result.removedEntities).to.have.lengthOf(1); - await expectDeterministicAppHash('db3a5c9e29f9bd70c7c80382aaae2d0a0a94d4ce04567d79fe9b7753393fb43e'); + await expectDeterministicAppHash('665cd7851b312faed1a9aa764c470bf25faf682b6903ba683c513306fb0023ca'); // Masternode identity should stay @@ -868,7 +868,7 @@ describe('synchronizeMasternodeIdentitiesFactory', () => { expect(result.updatedEntities).to.have.lengthOf(0); expect(result.removedEntities).to.have.lengthOf(1); - await expectDeterministicAppHash('db3a5c9e29f9bd70c7c80382aaae2d0a0a94d4ce04567d79fe9b7753393fb43e'); + await expectDeterministicAppHash('665cd7851b312faed1a9aa764c470bf25faf682b6903ba683c513306fb0023ca'); const invalidMasternodeIdentifier = Identifier.from( Buffer.from(invalidSmlEntry.proRegTxHash, 'hex'), @@ -918,7 +918,7 @@ describe('synchronizeMasternodeIdentitiesFactory', () => { expect(result.updatedEntities).to.have.lengthOf(1); expect(result.removedEntities).to.have.lengthOf(1); - await expectDeterministicAppHash('7f720ebd1d7066dde70c32a29bc838efff51cd585d93ef6523f25e4c26c88b6c'); + await expectDeterministicAppHash('cf4f3da4875738c21abaaa7b089c08be84e42b032d742cd3eb1574db9a3e70aa'); // Masternode identity should stay @@ -993,7 +993,7 @@ describe('synchronizeMasternodeIdentitiesFactory', () => { await synchronizeMasternodeIdentities(coreHeight + 1, blockInfo); - await expectDeterministicAppHash('863ed36205e6f7e9d8c09601fd7d524d26535ed826eb2a93092721f9eb038d8c'); + await expectDeterministicAppHash('ac377e46a223bdbe76791333c6d663f6bc9bb8e8022ed96ade53e2519298e5d3'); // Masternode identity should contain new public key @@ -1075,7 +1075,7 @@ describe('synchronizeMasternodeIdentitiesFactory', () => { // Initial sync await synchronizeMasternodeIdentities(coreHeight, blockInfo); - await expectDeterministicAppHash('701fa3c4bc5b0ff48db5e274f4a9346bb0ece8fb0ff345c5dfa3d436e6f8729c'); + await expectDeterministicAppHash('904eed0006446dccfb5ba84c2562417781caabd44c9d750f3be0d16ebec66f29'); const votingIdentifier = createVotingIdentifier(smlFixture[0]); const votingIdentityResult = await identityRepository.fetch( diff --git a/packages/rs-dpp/src/data_trigger/withdrawals_data_triggers/mod.rs b/packages/rs-dpp/src/data_trigger/withdrawals_data_triggers/mod.rs index 6653dec605d..c3ae216233f 100644 --- a/packages/rs-dpp/src/data_trigger/withdrawals_data_triggers/mod.rs +++ b/packages/rs-dpp/src/data_trigger/withdrawals_data_triggers/mod.rs @@ -88,10 +88,8 @@ mod tests { use crate::identity::state_transition::identity_credit_withdrawal_transition::Pooling; use crate::state_repository::MockStateRepositoryLike; use crate::state_transition::state_transition_execution_context::StateTransitionExecutionContext; - use crate::tests::fixtures::{ - get_data_contract_fixture, get_withdrawal_document_fixture, - get_withdrawals_data_contract_fixture, - }; + use crate::system_data_contracts::load_system_data_contract; + use crate::tests::fixtures::{get_data_contract_fixture, get_withdrawal_document_fixture}; #[tokio::test] async fn should_throw_error_if_withdrawal_not_found() { @@ -128,7 +126,9 @@ mod tests { async fn should_throw_error_if_withdrawal_has_wrong_status() { let transition_execution_context = StateTransitionExecutionContext::default(); let mut state_repository = MockStateRepositoryLike::new(); - let data_contract = get_withdrawals_data_contract_fixture(None); + let data_contract = + load_system_data_contract(data_contracts::SystemDataContract::Withdrawals) + .expect("to load system data contract"); let owner_id = data_contract.owner_id().to_owned(); let document = get_withdrawal_document_fixture( diff --git a/packages/rs-dpp/src/tests/fixtures/get_withdrawals_data_contract.rs b/packages/rs-dpp/src/tests/fixtures/get_withdrawals_data_contract.rs deleted file mode 100644 index 9f4927cc7a5..00000000000 --- a/packages/rs-dpp/src/tests/fixtures/get_withdrawals_data_contract.rs +++ /dev/null @@ -1,34 +0,0 @@ -use crate::contracts::withdrawals_contract; -use lazy_static::lazy_static; -use serde_json::Value; - -use crate::prelude::*; - -use crate::util::serializer::value_to_cbor; - -lazy_static! { - static ref WITHDRAWALS_CONTRACT_DOCUMENTS: Value = serde_json::from_str(include_str!( - "./../../../contracts/withdrawals/withdrawals-contract-documents.json" - )) - .expect("withdrawals contract should be valid json"); - static ref WITHDRAWALS_CONTRACT_SCHEMA: Value = serde_json::from_str(include_str!( - "./../../../contracts/withdrawals/withdrawals-contract.json" - )) - .expect("withdrawals contract should be valid json"); -} - -pub fn get_withdrawals_data_contract_fixture(owner_id: Option) -> DataContract { - let withdrawal_cbor = value_to_cbor(WITHDRAWALS_CONTRACT_SCHEMA.clone(), Some(1)) - .expect("should convert json to cbor value"); - - let mut data_contract = DataContract::from_cbor(withdrawal_cbor) - .expect("expected to deserialize withdrawal contract"); - - if let Some(owner_id) = owner_id { - data_contract.owner_id = owner_id; - } - - data_contract.id = *withdrawals_contract::CONTRACT_ID; - - data_contract -} diff --git a/packages/rs-dpp/src/tests/fixtures/mod.rs b/packages/rs-dpp/src/tests/fixtures/mod.rs index 384c724f62c..fd107cc02ff 100644 --- a/packages/rs-dpp/src/tests/fixtures/mod.rs +++ b/packages/rs-dpp/src/tests/fixtures/mod.rs @@ -26,8 +26,6 @@ mod get_dashpay_document_fixture; mod get_document_transitions_fixture; mod get_document_validator_fixture; pub use get_document_validator_fixture::*; -mod get_withdrawals_data_contract; -pub use get_withdrawals_data_contract::*; mod get_masternode_reward_shares_documents_fixture; pub use get_masternode_reward_shares_documents_fixture::*; diff --git a/packages/rs-drive-abci/src/abci/handlers.rs b/packages/rs-drive-abci/src/abci/handlers.rs index efde25dc313..9ed07dadc6a 100644 --- a/packages/rs-drive-abci/src/abci/handlers.rs +++ b/packages/rs-drive-abci/src/abci/handlers.rs @@ -253,11 +253,9 @@ mod tests { use dashcore::BlockHash; use dpp::contracts::withdrawals_contract; use dpp::data_contract::DriveContractExt; - use dpp::document::document_stub::DocumentStub; use dpp::identity::state_transition::identity_credit_withdrawal_transition::Pooling; - use dpp::tests::fixtures::{ - get_withdrawal_document_fixture, get_withdrawals_data_contract_fixture, - }; + use dpp::system_data_contracts::{load_system_data_contract, SystemDataContract}; + use dpp::tests::fixtures::get_withdrawal_document_fixture; use dpp::util::hash; use drive::common::helpers::identities::create_test_masternode_identities; use drive::common::helpers::setup::{setup_document, setup_system_data_contract}; @@ -298,7 +296,8 @@ mod tests { .init_chain(init_chain_request, Some(&transaction)) .expect("should init chain"); - let data_contract = get_withdrawals_data_contract_fixture(None); + let data_contract = load_system_data_contract(SystemDataContract::Withdrawals) + .expect("to load system data contract"); setup_system_data_contract(&platform.drive, &data_contract, Some(&transaction)); @@ -597,7 +596,8 @@ mod tests { setup_system_data_contract( &platform.drive, - &get_withdrawals_data_contract_fixture(None), + &load_system_data_contract(SystemDataContract::Withdrawals) + .expect("to load system data contract"), Some(&transaction), ); diff --git a/packages/rs-drive-abci/src/identity_credit_withdrawal/mod.rs b/packages/rs-drive-abci/src/identity_credit_withdrawal/mod.rs index c9a0f828dee..bd064b58518 100644 --- a/packages/rs-drive-abci/src/identity_credit_withdrawal/mod.rs +++ b/packages/rs-drive-abci/src/identity_credit_withdrawal/mod.rs @@ -502,15 +502,10 @@ mod tests { hashes::hex::{FromHex, ToHex}, BlockHash, }; - use dpp::{ - contracts::withdrawals_contract, - tests::fixtures::{get_withdrawal_document_fixture, get_withdrawals_data_contract_fixture}, - }; + use dpp::{contracts::withdrawals_contract, tests::fixtures::get_withdrawal_document_fixture}; use drive::{common::helpers::setup::setup_document, rpc::core::MockCoreRPCLike}; use serde_json::json; - use crate::test::helpers::setup::setup_platform_with_initial_state_structure; - use dpp::identity::state_transition::identity_credit_withdrawal_transition::Pooling; use crate::{block::BlockExecutionContext, execution::fee_pools::epoch::EpochInfo}; @@ -518,7 +513,10 @@ mod tests { mod update_withdrawal_statuses { use crate::block::BlockStateInfo; use crate::test::helpers::setup::setup_platform_with_initial_state_structure; - use dpp::data_contract::{DataContract, DriveContractExt}; + use dpp::{ + data_contract::{DataContract, DriveContractExt}, + system_data_contracts::{load_system_data_contract, SystemDataContract}, + }; use drive::common::helpers::setup::setup_system_data_contract; use super::*; @@ -577,8 +575,8 @@ mod tests { let transaction = platform.drive.grove.start_transaction(); - let data_contract = - get_withdrawals_data_contract_fixture(Some(withdrawals_contract::OWNER_ID.clone())); + let data_contract = load_system_data_contract(SystemDataContract::Withdrawals) + .expect("to load system data contract"); // TODO: figure out the bug in data contract factory let data_contract = DataContract::from_cbor( @@ -696,6 +694,7 @@ mod tests { mod pool_withdrawals_into_transactions { use dpp::data_contract::DriveContractExt; use dpp::identity::state_transition::identity_credit_withdrawal_transition::Pooling; + use dpp::system_data_contracts::{load_system_data_contract, SystemDataContract}; use drive::common::helpers::setup::setup_system_data_contract; use drive::dpp::contracts::withdrawals_contract; @@ -710,7 +709,8 @@ mod tests { let transaction = platform.drive.grove.start_transaction(); - let data_contract = get_withdrawals_data_contract_fixture(None); + let data_contract = load_system_data_contract(SystemDataContract::Withdrawals) + .expect("to load system data contract"); setup_system_data_contract(&platform.drive, &data_contract, Some(&transaction)); @@ -877,6 +877,7 @@ mod tests { mod build_withdrawal_transactions_from_documents { use crate::test::helpers::setup::setup_platform_with_initial_state_structure; use dpp::data_contract::DriveContractExt; + use dpp::system_data_contracts::{load_system_data_contract, SystemDataContract}; use dpp::{ document::document_stub::DocumentStub, identity::state_transition::identity_credit_withdrawal_transition::Pooling, @@ -893,7 +894,8 @@ mod tests { let transaction = platform.drive.grove.start_transaction(); - let data_contract = get_withdrawals_data_contract_fixture(None); + let data_contract = load_system_data_contract(SystemDataContract::Withdrawals) + .expect("to load system data contract"); setup_system_data_contract(&platform.drive, &data_contract, Some(&transaction)); diff --git a/packages/rs-drive/src/drive/identity/withdrawals/withdrawal_status.rs b/packages/rs-drive/src/drive/identity/withdrawals/withdrawal_status.rs index a3fb14d469e..470388e55fe 100644 --- a/packages/rs-drive/src/drive/identity/withdrawals/withdrawal_status.rs +++ b/packages/rs-drive/src/drive/identity/withdrawals/withdrawal_status.rs @@ -201,7 +201,6 @@ impl Drive { mod tests { use dpp::contracts::withdrawals_contract; use dpp::tests::fixtures::get_withdrawal_document_fixture; - use dpp::tests::fixtures::get_withdrawals_data_contract_fixture; use serde_json::json; use crate::common::helpers::setup::setup_drive_with_initial_state_structure; @@ -210,6 +209,7 @@ mod tests { mod fetch_withdrawal_documents_by_status { use dpp::data_contract::DriveContractExt; use dpp::identity::state_transition::identity_credit_withdrawal_transition::Pooling; + use dpp::system_data_contracts::{load_system_data_contract, SystemDataContract}; use super::*; @@ -219,8 +219,8 @@ mod tests { let transaction = drive.grove.start_transaction(); - let data_contract = - get_withdrawals_data_contract_fixture(Some(withdrawals_contract::OWNER_ID.clone())); + let data_contract = load_system_data_contract(SystemDataContract::Withdrawals) + .expect("to load system data contract"); setup_system_data_contract(&drive, &data_contract, Some(&transaction)); @@ -300,6 +300,7 @@ mod tests { mod find_document_by_transaction_id { use dpp::data_contract::DriveContractExt; use dpp::identity::state_transition::identity_credit_withdrawal_transition::Pooling; + use dpp::system_data_contracts::{load_system_data_contract, SystemDataContract}; use super::*; @@ -309,7 +310,8 @@ mod tests { let transaction = drive.grove.start_transaction(); - let data_contract = get_withdrawals_data_contract_fixture(None); + let data_contract = load_system_data_contract(SystemDataContract::Withdrawals) + .expect("to load system data contract"); setup_system_data_contract(&drive, &data_contract, Some(&transaction)); From 3c146766e8e9ffbb92119fc0769cb286a81c9bcd Mon Sep 17 00:00:00 2001 From: Djavid Gabibiyan Date: Wed, 15 Feb 2023 21:12:01 +0500 Subject: [PATCH 123/170] chore: clippy --- .../src/data_trigger/get_data_triggers_factory.rs | 6 ++++-- ...dentity_credit_withdrawal_transition_factory.rs | 5 +++-- .../state/validate_existing_withdrawal_id.rs | 3 ++- .../src/tests/fixtures/get_dpns_data_contract.rs | 6 ++---- .../src/identity_credit_withdrawal/mod.rs | 8 ++++---- .../src/drive/batch/drive_op_batch/document.rs | 6 +++--- .../src/drive/batch/drive_op_batch/withdrawals.rs | 14 ++------------ packages/rs-drive/src/drive/document/insert.rs | 1 - packages/rs-drive/src/drive/document/update.rs | 6 ++---- .../src/drive/identity/withdrawals/delete.rs | 6 ++---- .../src/drive/identity/withdrawals/insert.rs | 1 - .../src/drive/identity/withdrawals/queue.rs | 4 ++-- .../identity/withdrawals/withdrawal_status.rs | 7 ++++--- 13 files changed, 30 insertions(+), 43 deletions(-) diff --git a/packages/rs-dpp/src/data_trigger/get_data_triggers_factory.rs b/packages/rs-dpp/src/data_trigger/get_data_triggers_factory.rs index 405b76a2c7f..6191164df1d 100644 --- a/packages/rs-dpp/src/data_trigger/get_data_triggers_factory.rs +++ b/packages/rs-dpp/src/data_trigger/get_data_triggers_factory.rs @@ -1,5 +1,7 @@ use std::vec; +use lazy_static::__Deref; + use crate::{ contracts::{ dashpay_contract, dpns_contract, feature_flags_contract, masternode_reward_shares_contract, @@ -55,7 +57,7 @@ fn data_triggers() -> Result, ProtocolError> { Encoding::Base58, )?; let withdrawals_owner_id = withdrawals_contract::OWNER_ID.clone(); - let withdrawals_contract_id = withdrawals_contract::CONTRACT_ID.clone(); + let withdrawals_contract_id = withdrawals_contract::CONTRACT_ID.deref(); let data_triggers = vec![ DataTrigger { @@ -164,7 +166,7 @@ fn data_triggers() -> Result, ProtocolError> { top_level_identity: None, }, DataTrigger { - data_contract_id: withdrawals_contract_id, + data_contract_id: withdrawals_contract_id.clone(), document_type: withdrawals_contract::types::WITHDRAWAL.to_string(), transition_action: Action::Delete, data_trigger_kind: DataTriggerKind::DeleteWithdrawal, diff --git a/packages/rs-dpp/src/identity/state_transition/identity_credit_withdrawal_transition/apply_identity_credit_withdrawal_transition_factory.rs b/packages/rs-dpp/src/identity/state_transition/identity_credit_withdrawal_transition/apply_identity_credit_withdrawal_transition_factory.rs index b12305b0ba8..88f2267a5ee 100644 --- a/packages/rs-dpp/src/identity/state_transition/identity_credit_withdrawal_transition/apply_identity_credit_withdrawal_transition_factory.rs +++ b/packages/rs-dpp/src/identity/state_transition/identity_credit_withdrawal_transition/apply_identity_credit_withdrawal_transition_factory.rs @@ -1,5 +1,6 @@ use anyhow::{anyhow, Result}; use dashcore::{consensus, BlockHeader}; +use lazy_static::__Deref; use std::convert::TryInto; use serde_json::json; @@ -38,7 +39,7 @@ where &self, state_transition: &IdentityCreditWithdrawalTransition, ) -> Result<()> { - let data_contract_id = withdrawals_contract::CONTRACT_ID.clone(); + let data_contract_id = withdrawals_contract::CONTRACT_ID.deref(); let data_contract_owner_id = withdrawals_contract::OWNER_ID.clone(); let maybe_withdrawals_data_contract: Option = self @@ -104,7 +105,7 @@ where id: document_id, document_type, revision: 0, - data_contract_id, + data_contract_id: data_contract_id.clone(), owner_id: data_contract_owner_id.clone(), created_at: Some(document_created_at_millis), updated_at: Some(document_created_at_millis), diff --git a/packages/rs-dpp/src/identity/state_transition/identity_credit_withdrawal_transition/validation/state/validate_existing_withdrawal_id.rs b/packages/rs-dpp/src/identity/state_transition/identity_credit_withdrawal_transition/validation/state/validate_existing_withdrawal_id.rs index efec17bb539..9618688df63 100644 --- a/packages/rs-dpp/src/identity/state_transition/identity_credit_withdrawal_transition/validation/state/validate_existing_withdrawal_id.rs +++ b/packages/rs-dpp/src/identity/state_transition/identity_credit_withdrawal_transition/validation/state/validate_existing_withdrawal_id.rs @@ -1,3 +1,4 @@ +use lazy_static::__Deref; use serde_json::json; use crate::{ @@ -17,7 +18,7 @@ where { let documents: Vec = state_repository .fetch_documents( - &withdrawals_contract::CONTRACT_ID.clone(), + withdrawals_contract::CONTRACT_ID.deref(), withdrawals_contract::types::WITHDRAWAL, json!({ "where": [ diff --git a/packages/rs-dpp/src/tests/fixtures/get_dpns_data_contract.rs b/packages/rs-dpp/src/tests/fixtures/get_dpns_data_contract.rs index 84ca1bc496f..07bcc5bcfd8 100644 --- a/packages/rs-dpp/src/tests/fixtures/get_dpns_data_contract.rs +++ b/packages/rs-dpp/src/tests/fixtures/get_dpns_data_contract.rs @@ -33,9 +33,7 @@ pub fn get_dpns_data_contract_fixture(owner_id: Option) -> DataContr // TODO the pattern is invalid as it's a re2 document_schemas["domain"]["properties"]["normalizedParentDomainName"]["pattern"] = json!(".*"); - let mut data_contract = factory + factory .create(owner_id, document_schemas, Some(defs)) - .expect("data in fixture should be correct"); - - data_contract + .expect("data in fixture should be correct") } diff --git a/packages/rs-drive-abci/src/identity_credit_withdrawal/mod.rs b/packages/rs-drive-abci/src/identity_credit_withdrawal/mod.rs index bd064b58518..0791ec561c1 100644 --- a/packages/rs-drive-abci/src/identity_credit_withdrawal/mod.rs +++ b/packages/rs-drive-abci/src/identity_credit_withdrawal/mod.rs @@ -1,4 +1,4 @@ -use std::collections::HashMap; +use std::{collections::HashMap, ops::Deref}; use dashcore::{ blockdata::transaction::special_transaction::asset_unlock::{ @@ -159,7 +159,7 @@ impl Platform { validator_set_quorum_hash: [u8; 32], transaction: TransactionArg, ) -> Result>, Error> { - let data_contract_id = withdrawals_contract::CONTRACT_ID.clone(); + let data_contract_id = withdrawals_contract::CONTRACT_ID.deref(); let (_, maybe_data_contract) = self.drive.get_contract_with_fetch_info( data_contract_id.to_buffer(), @@ -218,7 +218,7 @@ impl Platform { document.set_bytes( withdrawals_contract::property_names::TRANSACTION_ID, - update_transaction_id.clone(), + update_transaction_id, ); document.set_i64( @@ -278,7 +278,7 @@ impl Platform { block_execution_context: &BlockExecutionContext, transaction: TransactionArg, ) -> Result<(), Error> { - let data_contract_id = withdrawals_contract::CONTRACT_ID.clone(); + let data_contract_id = withdrawals_contract::CONTRACT_ID.deref(); let (_, maybe_data_contract) = self.drive.get_contract_with_fetch_info( data_contract_id.to_buffer(), diff --git a/packages/rs-drive/src/drive/batch/drive_op_batch/document.rs b/packages/rs-drive/src/drive/batch/drive_op_batch/document.rs index 8bafe9489f7..065fde57c5e 100644 --- a/packages/rs-drive/src/drive/batch/drive_op_batch/document.rs +++ b/packages/rs-drive/src/drive/batch/drive_op_batch/document.rs @@ -229,7 +229,7 @@ impl DriveOperationConverter for DocumentOperationType<'_> { document_info, owner_id, }, - contract: &contract, + contract, document_type, }; drive.add_document_for_contract_operations( @@ -348,7 +348,7 @@ impl DriveOperationConverter for DocumentOperationType<'_> { document_info, owner_id, }, - contract: &contract, + contract, document_type, }; drive.update_document_for_contract_operations( @@ -377,7 +377,7 @@ impl DriveOperationConverter for DocumentOperationType<'_> { document_info, owner_id, }, - contract: &contract, + contract, document_type, }; drive.update_document_for_contract_operations( diff --git a/packages/rs-drive/src/drive/batch/drive_op_batch/withdrawals.rs b/packages/rs-drive/src/drive/batch/drive_op_batch/withdrawals.rs index 9ea9f7ae59c..e554ab5d4d1 100644 --- a/packages/rs-drive/src/drive/batch/drive_op_batch/withdrawals.rs +++ b/packages/rs-drive/src/drive/batch/drive_op_batch/withdrawals.rs @@ -1,19 +1,9 @@ use std::collections::HashMap; -use grovedb::{batch::KeyInfoPath, Element, EstimatedLayerInformation, TransactionArg}; +use grovedb::{batch::KeyInfoPath, EstimatedLayerInformation, TransactionArg}; use crate::{ - drive::{ - block_info::BlockInfo, - grove_operations::BatchDeleteApplyType, - identity::withdrawals::paths::{ - get_withdrawal_root_path_vec, get_withdrawal_transactions_expired_ids_path, - get_withdrawal_transactions_expired_ids_path_vec, - get_withdrawal_transactions_queue_path, get_withdrawal_transactions_queue_path_vec, - WithdrawalTransaction, WITHDRAWAL_TRANSACTIONS_COUNTER_ID, - }, - Drive, - }, + drive::{block_info::BlockInfo, identity::withdrawals::paths::WithdrawalTransaction, Drive}, error::Error, fee::op::DriveOperation, }; diff --git a/packages/rs-drive/src/drive/document/insert.rs b/packages/rs-drive/src/drive/document/insert.rs index 153baa694ce..316c697d281 100644 --- a/packages/rs-drive/src/drive/document/insert.rs +++ b/packages/rs-drive/src/drive/document/insert.rs @@ -32,7 +32,6 @@ //! This module implements functions in Drive relevant to inserting documents. //! -use dpp::data_contract::document_type::random_document::CreateRandomDocument; use dpp::data_contract::document_type::{encode_unsigned_integer, IndexLevel}; use dpp::data_contract::DriveContractExt; use grovedb::batch::key_info::KeyInfo; diff --git a/packages/rs-drive/src/drive/document/update.rs b/packages/rs-drive/src/drive/document/update.rs index 4660bdb91f7..17eab0a6f39 100644 --- a/packages/rs-drive/src/drive/document/update.rs +++ b/packages/rs-drive/src/drive/document/update.rs @@ -55,14 +55,13 @@ use crate::drive::document::{ }; use crate::drive::flags::StorageFlags; use crate::drive::object_size_info::DocumentInfo::{ - DocumentEstimatedAverageSize, DocumentRefAndSerialization, DocumentRefWithoutSerialization, - DocumentWithoutSerialization, + DocumentRefAndSerialization, DocumentWithoutSerialization, }; use dpp::document::document_stub::DocumentStub; use crate::drive::object_size_info::PathKeyElementInfo::PathKeyRefElement; use crate::drive::object_size_info::{ - DocumentAndContractInfo, DocumentInfo, DriveKeyInfo, OwnedDocumentInfo, PathKeyInfo, + DocumentAndContractInfo, DriveKeyInfo, OwnedDocumentInfo, PathKeyInfo, }; use crate::drive::Drive; use crate::error::drive::DriveError; @@ -80,7 +79,6 @@ use crate::drive::grove_operations::{ }; use crate::fee::result::FeeResult; use dpp::prelude::DataContract; -use dpp::ProtocolError; impl Drive { /// Updates a serialized document given a contract CBOR and returns the associated fee. diff --git a/packages/rs-drive/src/drive/identity/withdrawals/delete.rs b/packages/rs-drive/src/drive/identity/withdrawals/delete.rs index 3af85abbce7..893c29b5eaf 100644 --- a/packages/rs-drive/src/drive/identity/withdrawals/delete.rs +++ b/packages/rs-drive/src/drive/identity/withdrawals/delete.rs @@ -1,11 +1,9 @@ use crate::drive::grove_operations::BatchDeleteApplyType; -use crate::drive::identity::withdrawals::paths::{ - get_withdrawal_transactions_queue_path, WithdrawalTransaction, -}; +use crate::drive::identity::withdrawals::paths::get_withdrawal_transactions_queue_path; use crate::drive::Drive; use crate::error::Error; use crate::fee::op::DriveOperation; -use grovedb::{Element, TransactionArg}; +use grovedb::TransactionArg; impl Drive { pub(crate) fn delete_withdrawal_transaction( diff --git a/packages/rs-drive/src/drive/identity/withdrawals/insert.rs b/packages/rs-drive/src/drive/identity/withdrawals/insert.rs index f5b879921d3..dbf9692d99d 100644 --- a/packages/rs-drive/src/drive/identity/withdrawals/insert.rs +++ b/packages/rs-drive/src/drive/identity/withdrawals/insert.rs @@ -1,4 +1,3 @@ -use crate::drive::grove_operations::BatchDeleteApplyType; use crate::drive::identity::withdrawals::paths::{ get_withdrawal_transactions_queue_path_vec, WithdrawalTransaction, }; diff --git a/packages/rs-drive/src/drive/identity/withdrawals/queue.rs b/packages/rs-drive/src/drive/identity/withdrawals/queue.rs index b5fb2f8b466..cf096b747ae 100644 --- a/packages/rs-drive/src/drive/identity/withdrawals/queue.rs +++ b/packages/rs-drive/src/drive/identity/withdrawals/queue.rs @@ -32,11 +32,11 @@ impl Drive { } /// Get specified amount of withdrawal transactions from the DB - pub fn dequeue_withdrawal_transactions<'a>( + pub fn dequeue_withdrawal_transactions( &self, max_amount: u16, transaction: TransactionArg, - drive_operation_types: &mut Vec>, + drive_operation_types: &mut Vec, ) -> Result, Error> { let mut query = Query::new(); diff --git a/packages/rs-drive/src/drive/identity/withdrawals/withdrawal_status.rs b/packages/rs-drive/src/drive/identity/withdrawals/withdrawal_status.rs index 470388e55fe..f7c9a2f48eb 100644 --- a/packages/rs-drive/src/drive/identity/withdrawals/withdrawal_status.rs +++ b/packages/rs-drive/src/drive/identity/withdrawals/withdrawal_status.rs @@ -7,6 +7,7 @@ use dpp::{ }; use grovedb::TransactionArg; use indexmap::IndexMap; +use lazy_static::__Deref; use crate::{ drive::{query::QueryDocumentsOutcome, Drive}, @@ -21,7 +22,7 @@ impl Drive { status: u8, transaction: TransactionArg, ) -> Result, Error> { - let data_contract_id = withdrawals_contract::CONTRACT_ID.clone(); + let data_contract_id = withdrawals_contract::CONTRACT_ID.deref(); let contract_fetch_info = self .fetch_contract(data_contract_id.to_buffer(), None, transaction) @@ -114,7 +115,7 @@ impl Drive { original_transaction_id: &[u8], transaction: TransactionArg, ) -> Result { - let data_contract_id = withdrawals_contract::CONTRACT_ID.clone(); + let data_contract_id = withdrawals_contract::CONTRACT_ID.deref(); let contract_fetch_info = self .fetch_contract(data_contract_id.to_buffer(), None, transaction) @@ -153,7 +154,7 @@ impl Drive { let drive_query = DriveQuery { contract: &contract_fetch_info.contract, - document_type: document_type, + document_type, internal_clauses: InternalClauses { primary_key_in_clause: None, primary_key_equal_clause: None, From 5934748cda50dd0705e87fa22f1997e16839d4bf Mon Sep 17 00:00:00 2001 From: Djavid Gabibiyan Date: Wed, 15 Feb 2023 21:12:37 +0500 Subject: [PATCH 124/170] chore: clippy --- packages/rs-drive/src/common/helpers/setup.rs | 3 +-- packages/rs-drive/src/drive/protocol_upgrade/mod.rs | 2 +- packages/rs-drive/src/drive/system/protocol_version.rs | 4 ++-- 3 files changed, 4 insertions(+), 5 deletions(-) diff --git a/packages/rs-drive/src/common/helpers/setup.rs b/packages/rs-drive/src/common/helpers/setup.rs index de60720e8d2..85ea4d0ddb2 100644 --- a/packages/rs-drive/src/common/helpers/setup.rs +++ b/packages/rs-drive/src/common/helpers/setup.rs @@ -38,13 +38,12 @@ use crate::drive::Drive; use crate::fee_pools::epochs::Epoch; use crate::drive::object_size_info::DocumentInfo::{ - DocumentRefAndSerialization, DocumentRefWithoutSerialization, + DocumentRefWithoutSerialization, }; use crate::drive::object_size_info::{DocumentAndContractInfo, OwnedDocumentInfo}; use dpp::data_contract::document_type::DocumentType; use dpp::document::document_stub::DocumentStub; use dpp::{ - contracts::withdrawals_contract, prelude::{DataContract, Document}, }; use grovedb::TransactionArg; diff --git a/packages/rs-drive/src/drive/protocol_upgrade/mod.rs b/packages/rs-drive/src/drive/protocol_upgrade/mod.rs index d5892a799c7..c33fa857af5 100644 --- a/packages/rs-drive/src/drive/protocol_upgrade/mod.rs +++ b/packages/rs-drive/src/drive/protocol_upgrade/mod.rs @@ -2,7 +2,7 @@ use crate::drive::batch::GroveDbOpBatch; use crate::drive::grove_operations::BatchDeleteApplyType::StatefulBatchDelete; use crate::drive::grove_operations::BatchInsertApplyType; use crate::drive::object_size_info::PathKeyElementInfo; -use crate::drive::system::{misc_path, misc_path_vec}; + use crate::drive::{Drive, RootTree}; use crate::error::drive::DriveError; use crate::error::Error; diff --git a/packages/rs-drive/src/drive/system/protocol_version.rs b/packages/rs-drive/src/drive/system/protocol_version.rs index 5c1e56e6a03..6a86a690c7a 100644 --- a/packages/rs-drive/src/drive/system/protocol_version.rs +++ b/packages/rs-drive/src/drive/system/protocol_version.rs @@ -8,8 +8,8 @@ use crate::drive::Drive; use crate::error::drive::DriveError; use crate::error::Error; use crate::fee::op::DriveOperation; -use crate::fee::op::DriveOperation::CalculatedCostOperation; -use costs::CostContext; + + use dpp::util::deserializer::ProtocolVersion; use grovedb::{Element, TransactionArg}; use integer_encoding::VarInt; From 48a0a439b12fb0fd73d25b47e66740a29b8213b1 Mon Sep 17 00:00:00 2001 From: Djavid Gabibiyan Date: Wed, 15 Feb 2023 21:12:55 +0500 Subject: [PATCH 125/170] chore: fmt --- packages/rs-drive/src/common/helpers/setup.rs | 8 ++------ packages/rs-drive/src/drive/system/protocol_version.rs | 1 - 2 files changed, 2 insertions(+), 7 deletions(-) diff --git a/packages/rs-drive/src/common/helpers/setup.rs b/packages/rs-drive/src/common/helpers/setup.rs index 85ea4d0ddb2..8882009563d 100644 --- a/packages/rs-drive/src/common/helpers/setup.rs +++ b/packages/rs-drive/src/common/helpers/setup.rs @@ -37,15 +37,11 @@ use crate::drive::config::DriveConfig; use crate::drive::Drive; use crate::fee_pools::epochs::Epoch; -use crate::drive::object_size_info::DocumentInfo::{ - DocumentRefWithoutSerialization, -}; +use crate::drive::object_size_info::DocumentInfo::DocumentRefWithoutSerialization; use crate::drive::object_size_info::{DocumentAndContractInfo, OwnedDocumentInfo}; use dpp::data_contract::document_type::DocumentType; use dpp::document::document_stub::DocumentStub; -use dpp::{ - prelude::{DataContract, Document}, -}; +use dpp::prelude::{DataContract, Document}; use grovedb::TransactionArg; use tempfile::TempDir; diff --git a/packages/rs-drive/src/drive/system/protocol_version.rs b/packages/rs-drive/src/drive/system/protocol_version.rs index 6a86a690c7a..801d1a43358 100644 --- a/packages/rs-drive/src/drive/system/protocol_version.rs +++ b/packages/rs-drive/src/drive/system/protocol_version.rs @@ -9,7 +9,6 @@ use crate::error::drive::DriveError; use crate::error::Error; use crate::fee::op::DriveOperation; - use dpp::util::deserializer::ProtocolVersion; use grovedb::{Element, TransactionArg}; use integer_encoding::VarInt; From 5a85a514107506f854cce73d9b9df81b0f735163 Mon Sep 17 00:00:00 2001 From: Djavid Gabibiyan Date: Wed, 15 Feb 2023 21:20:30 +0500 Subject: [PATCH 126/170] chore: clippy --- .../data_trigger/get_data_triggers_factory.rs | 10 +++++----- ...ntity_credit_withdrawal_transition_factory.rs | 16 ++++++++-------- .../src/tests/fixtures/get_documents_fixture.rs | 2 +- .../identity/withdrawals/withdrawal_status.rs | 2 +- 4 files changed, 15 insertions(+), 15 deletions(-) diff --git a/packages/rs-dpp/src/data_trigger/get_data_triggers_factory.rs b/packages/rs-dpp/src/data_trigger/get_data_triggers_factory.rs index 6191164df1d..ce786a56568 100644 --- a/packages/rs-dpp/src/data_trigger/get_data_triggers_factory.rs +++ b/packages/rs-dpp/src/data_trigger/get_data_triggers_factory.rs @@ -56,7 +56,7 @@ fn data_triggers() -> Result, ProtocolError> { &masternode_reward_shares_contract::system_ids().contract_id, Encoding::Base58, )?; - let withdrawals_owner_id = withdrawals_contract::OWNER_ID.clone(); + let withdrawals_owner_id = withdrawals_contract::OWNER_ID.deref(); let withdrawals_contract_id = withdrawals_contract::CONTRACT_ID.deref(); let data_triggers = vec![ @@ -152,25 +152,25 @@ fn data_triggers() -> Result, ProtocolError> { top_level_identity: None, }, DataTrigger { - data_contract_id: withdrawals_contract_id.clone(), + data_contract_id: *withdrawals_contract_id, document_type: withdrawals_contract::types::WITHDRAWAL.to_string(), transition_action: Action::Create, data_trigger_kind: DataTriggerKind::DataTriggerReject, top_level_identity: None, }, DataTrigger { - data_contract_id: withdrawals_contract_id.clone(), + data_contract_id: *withdrawals_contract_id, document_type: withdrawals_contract::types::WITHDRAWAL.to_string(), transition_action: Action::Replace, data_trigger_kind: DataTriggerKind::DataTriggerReject, top_level_identity: None, }, DataTrigger { - data_contract_id: withdrawals_contract_id.clone(), + data_contract_id: *withdrawals_contract_id, document_type: withdrawals_contract::types::WITHDRAWAL.to_string(), transition_action: Action::Delete, data_trigger_kind: DataTriggerKind::DeleteWithdrawal, - top_level_identity: Some(withdrawals_owner_id), + top_level_identity: Some(*withdrawals_owner_id), }, ]; Ok(data_triggers) diff --git a/packages/rs-dpp/src/identity/state_transition/identity_credit_withdrawal_transition/apply_identity_credit_withdrawal_transition_factory.rs b/packages/rs-dpp/src/identity/state_transition/identity_credit_withdrawal_transition/apply_identity_credit_withdrawal_transition_factory.rs index 88f2267a5ee..cbde8545b94 100644 --- a/packages/rs-dpp/src/identity/state_transition/identity_credit_withdrawal_transition/apply_identity_credit_withdrawal_transition_factory.rs +++ b/packages/rs-dpp/src/identity/state_transition/identity_credit_withdrawal_transition/apply_identity_credit_withdrawal_transition_factory.rs @@ -40,11 +40,11 @@ where state_transition: &IdentityCreditWithdrawalTransition, ) -> Result<()> { let data_contract_id = withdrawals_contract::CONTRACT_ID.deref(); - let data_contract_owner_id = withdrawals_contract::OWNER_ID.clone(); + let data_contract_owner_id = withdrawals_contract::OWNER_ID.deref(); let maybe_withdrawals_data_contract: Option = self .state_repository - .fetch_data_contract(&data_contract_id, state_transition.get_execution_context()) + .fetch_data_contract(data_contract_id, state_transition.get_execution_context()) .await? .map(TryInto::try_into) .transpose() @@ -75,8 +75,8 @@ where let document_entropy = generate()?; let mut document_id = generate_document_id::generate_document_id( - &data_contract_id, - &data_contract_owner_id, + data_contract_id, + data_contract_owner_id, &document_type, &document_entropy, ); @@ -92,8 +92,8 @@ where let document_entropy = generate()?; document_id = generate_document_id::generate_document_id( - &data_contract_id, - &data_contract_owner_id, + data_contract_id, + data_contract_owner_id, &document_type, &document_entropy, ) @@ -105,8 +105,8 @@ where id: document_id, document_type, revision: 0, - data_contract_id: data_contract_id.clone(), - owner_id: data_contract_owner_id.clone(), + data_contract_id: *data_contract_id, + owner_id: *data_contract_owner_id, created_at: Some(document_created_at_millis), updated_at: Some(document_created_at_millis), data: document_data, diff --git a/packages/rs-dpp/src/tests/fixtures/get_documents_fixture.rs b/packages/rs-dpp/src/tests/fixtures/get_documents_fixture.rs index b4b42c3709f..1d82260a438 100644 --- a/packages/rs-dpp/src/tests/fixtures/get_documents_fixture.rs +++ b/packages/rs-dpp/src/tests/fixtures/get_documents_fixture.rs @@ -120,7 +120,7 @@ pub fn get_withdrawal_document_fixture(data_contract: &DataContract, data: Value factory .create( data_contract.clone(), - data_contract.owner_id.clone(), + data_contract.owner_id, withdrawals_contract::types::WITHDRAWAL.to_string(), data, ) diff --git a/packages/rs-drive/src/drive/identity/withdrawals/withdrawal_status.rs b/packages/rs-drive/src/drive/identity/withdrawals/withdrawal_status.rs index f7c9a2f48eb..30ce0be3ec1 100644 --- a/packages/rs-drive/src/drive/identity/withdrawals/withdrawal_status.rs +++ b/packages/rs-drive/src/drive/identity/withdrawals/withdrawal_status.rs @@ -45,7 +45,7 @@ impl Drive { field: withdrawals_contract::property_names::OWNER_ID.to_string(), operator: crate::query::WhereOperator::Equal, value: ciborium::Value::Bytes( - withdrawals_contract::OWNER_ID.clone().to_buffer().to_vec(), + withdrawals_contract::OWNER_ID.deref().to_buffer().to_vec(), ), }, ); From d5282dbcd568cde679bf6ce4ef62878425fc6c8b Mon Sep 17 00:00:00 2001 From: Djavid Gabibiyan Date: Wed, 15 Feb 2023 21:22:51 +0500 Subject: [PATCH 127/170] chore: clippy --- packages/rs-drive-abci/src/execution/engine.rs | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/packages/rs-drive-abci/src/execution/engine.rs b/packages/rs-drive-abci/src/execution/engine.rs index cc5291a8095..941a60d57fb 100644 --- a/packages/rs-drive-abci/src/execution/engine.rs +++ b/packages/rs-drive-abci/src/execution/engine.rs @@ -2,20 +2,16 @@ use crate::abci::handlers::TenderdashAbci; use crate::abci::messages::{ AfterFinalizeBlockRequest, BlockBeginRequest, BlockEndRequest, BlockFees, }; -use crate::constants::PROTOCOL_VERSION_UPGRADE_PERCENTAGE_NEEDED; use crate::error::execution::ExecutionError; use crate::error::Error; use crate::platform::Platform; -use crate::state::PlatformState; use drive::dpp::identity::PartialIdentity; use drive::dpp::util::deserializer::ProtocolVersion; use drive::drive::batch::DriveOperationType; use drive::drive::block_info::BlockInfo; use drive::error::Error::GroveDB; use drive::fee::result::FeeResult; -use drive::fee_pools::epochs::Epoch; use drive::grovedb::Transaction; -use drive::query::TransactionArg; /// An execution event pub enum ExecutionEvent<'a> { @@ -175,7 +171,7 @@ impl Platform { // println!("Block #{}", block_info.height); - let block_begin_response = self + let _block_begin_response = self .block_begin(block_begin_request, Some(&transaction)) .unwrap_or_else(|e| { panic!( From 1abd5c012125b3ed9fe9623b475cf66c0929a3ef Mon Sep 17 00:00:00 2001 From: Djavid Gabibiyan Date: Wed, 15 Feb 2023 21:25:28 +0500 Subject: [PATCH 128/170] chore: clippy --- packages/rs-drive-abci/src/test/helpers/setup.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/rs-drive-abci/src/test/helpers/setup.rs b/packages/rs-drive-abci/src/test/helpers/setup.rs index 03bfd5f4f15..c33b12e12a8 100644 --- a/packages/rs-drive-abci/src/test/helpers/setup.rs +++ b/packages/rs-drive-abci/src/test/helpers/setup.rs @@ -32,7 +32,6 @@ //! This module defines helper functions related to setting up Platform. //! -use crate::abci::messages::SystemIdentityPublicKeys; use crate::config::PlatformConfig; use crate::platform::Platform; use crate::test::fixture::abci::static_system_identity_public_keys; From 030d37cf3999ee076d51a298c90a6967b0da3ff1 Mon Sep 17 00:00:00 2001 From: Djavid Gabibiyan Date: Wed, 15 Feb 2023 21:39:37 +0500 Subject: [PATCH 129/170] chore: moving helpers --- packages/rs-drive-abci/src/abci/handlers.rs | 3 +-- .../rs-drive-abci/src/identity_credit_withdrawal/mod.rs | 8 ++++---- packages/rs-drive/src/common/helpers/mod.rs | 1 - packages/rs-drive/src/drive/contract/mod.rs | 2 +- .../drive/fee_pools/epochs/credit_distribution_pools.rs | 2 +- packages/rs-drive/src/drive/fee_pools/epochs/mod.rs | 2 +- packages/rs-drive/src/drive/fee_pools/epochs/proposers.rs | 2 +- .../rs-drive/src/drive/fee_pools/epochs/start_block.rs | 2 +- .../rs-drive/src/drive/fee_pools/epochs/start_time.rs | 2 +- packages/rs-drive/src/drive/fee_pools/mod.rs | 2 +- .../rs-drive/src/drive/fee_pools/pending_epoch_refunds.rs | 2 +- .../src/drive/fee_pools/storage_fee_distribution_pool.rs | 2 +- packages/rs-drive/src/drive/fee_pools/unpaid_epoch.rs | 2 +- packages/rs-drive/src/drive/genesis_time.rs | 2 +- packages/rs-drive/src/drive/identity/balance/prove.rs | 2 +- packages/rs-drive/src/drive/identity/balance/update.rs | 2 +- .../drive/identity/fetch/fetch_by_public_key_hashes.rs | 2 +- .../rs-drive/src/drive/identity/fetch/full_identity.rs | 2 +- .../fetch/prove/full_identities_by_public_key_hashes.rs | 2 +- .../src/drive/identity/fetch/prove/full_identity.rs | 2 +- .../fetch/prove/identity_ids_by_public_key_hashes.rs | 2 +- packages/rs-drive/src/drive/identity/insert.rs | 2 +- packages/rs-drive/src/drive/identity/key/fetch.rs | 2 +- packages/rs-drive/src/drive/identity/key/insert.rs | 1 - packages/rs-drive/src/drive/identity/update.rs | 2 +- packages/rs-drive/src/drive/identity/withdrawals/queue.rs | 2 +- .../identity/withdrawals/transaction_index_counter.rs | 2 +- .../src/drive/identity/withdrawals/withdrawal_status.rs | 4 ++-- .../rs-drive/src/fee_pools/epochs/operations_factory.rs | 2 +- packages/rs-drive/src/fee_pools/mod.rs | 2 +- packages/rs-drive/src/lib.rs | 4 ++++ packages/rs-drive/src/tests/helpers/mod.rs | 1 + packages/rs-drive/src/{common => tests}/helpers/setup.rs | 0 packages/rs-drive/src/tests/mod.rs | 2 ++ packages/rs-drive/tests/query_tests.rs | 4 ++-- packages/rs-drive/tests/query_tests_history.rs | 2 +- 36 files changed, 42 insertions(+), 38 deletions(-) create mode 100644 packages/rs-drive/src/tests/helpers/mod.rs rename packages/rs-drive/src/{common => tests}/helpers/setup.rs (100%) create mode 100644 packages/rs-drive/src/tests/mod.rs diff --git a/packages/rs-drive-abci/src/abci/handlers.rs b/packages/rs-drive-abci/src/abci/handlers.rs index 9ed07dadc6a..edb6ebccc71 100644 --- a/packages/rs-drive-abci/src/abci/handlers.rs +++ b/packages/rs-drive-abci/src/abci/handlers.rs @@ -38,7 +38,6 @@ use crate::abci::messages::{ }; use crate::block::{BlockExecutionContext, BlockStateInfo}; use crate::execution::fee_pools::epoch::EpochInfo; -use drive::fee::epoch::GENESIS_EPOCH_INDEX; use drive::grovedb::TransactionArg; use crate::error::execution::ExecutionError; @@ -258,12 +257,12 @@ mod tests { use dpp::tests::fixtures::get_withdrawal_document_fixture; use dpp::util::hash; use drive::common::helpers::identities::create_test_masternode_identities; - use drive::common::helpers::setup::{setup_document, setup_system_data_contract}; use drive::drive::block_info::BlockInfo; use drive::drive::identity::withdrawals::paths::WithdrawalTransaction; use drive::fee::epoch::CreditsPerEpoch; use drive::fee_pools::epochs::Epoch; use drive::rpc::core::MockCoreRPCLike; + use drive::tests::helpers::setup::{setup_document, setup_system_data_contract}; use rust_decimal::prelude::ToPrimitive; use serde_json::json; use std::cmp::Ordering; diff --git a/packages/rs-drive-abci/src/identity_credit_withdrawal/mod.rs b/packages/rs-drive-abci/src/identity_credit_withdrawal/mod.rs index 0791ec561c1..3ccd2ef3a2e 100644 --- a/packages/rs-drive-abci/src/identity_credit_withdrawal/mod.rs +++ b/packages/rs-drive-abci/src/identity_credit_withdrawal/mod.rs @@ -503,7 +503,7 @@ mod tests { BlockHash, }; use dpp::{contracts::withdrawals_contract, tests::fixtures::get_withdrawal_document_fixture}; - use drive::{common::helpers::setup::setup_document, rpc::core::MockCoreRPCLike}; + use drive::{rpc::core::MockCoreRPCLike, tests::helpers::setup::setup_document}; use serde_json::json; use dpp::identity::state_transition::identity_credit_withdrawal_transition::Pooling; @@ -517,7 +517,7 @@ mod tests { data_contract::{DataContract, DriveContractExt}, system_data_contracts::{load_system_data_contract, SystemDataContract}, }; - use drive::common::helpers::setup::setup_system_data_contract; + use drive::tests::helpers::setup::setup_system_data_contract; use super::*; @@ -695,8 +695,8 @@ mod tests { use dpp::data_contract::DriveContractExt; use dpp::identity::state_transition::identity_credit_withdrawal_transition::Pooling; use dpp::system_data_contracts::{load_system_data_contract, SystemDataContract}; - use drive::common::helpers::setup::setup_system_data_contract; use drive::dpp::contracts::withdrawals_contract; + use drive::tests::helpers::setup::setup_system_data_contract; use crate::block::BlockStateInfo; use crate::test::helpers::setup::setup_platform_with_initial_state_structure; @@ -882,8 +882,8 @@ mod tests { document::document_stub::DocumentStub, identity::state_transition::identity_credit_withdrawal_transition::Pooling, }; - use drive::common::helpers::setup::setup_system_data_contract; use drive::drive::identity::withdrawals::paths::WithdrawalTransaction; + use drive::tests::helpers::setup::setup_system_data_contract; use itertools::Itertools; use super::*; diff --git a/packages/rs-drive/src/common/helpers/mod.rs b/packages/rs-drive/src/common/helpers/mod.rs index ece28e30146..990fed2c0e5 100644 --- a/packages/rs-drive/src/common/helpers/mod.rs +++ b/packages/rs-drive/src/common/helpers/mod.rs @@ -1,3 +1,2 @@ pub mod epoch; pub mod identities; -pub mod setup; diff --git a/packages/rs-drive/src/drive/contract/mod.rs b/packages/rs-drive/src/drive/contract/mod.rs index b79470dc7ea..b4dd0adbdc3 100644 --- a/packages/rs-drive/src/drive/contract/mod.rs +++ b/packages/rs-drive/src/drive/contract/mod.rs @@ -1037,7 +1037,7 @@ mod tests { use crate::drive::Drive; use dpp::data_contract::extra::common::json_document_to_cbor; - use crate::common::helpers::setup::setup_drive_with_initial_state_structure; + use crate::tests::helpers::setup::setup_drive_with_initial_state_structure; fn setup_deep_nested_50_contract() -> (Drive, Contract, Vec) { // Todo: make TempDir based on _prefix diff --git a/packages/rs-drive/src/drive/fee_pools/epochs/credit_distribution_pools.rs b/packages/rs-drive/src/drive/fee_pools/epochs/credit_distribution_pools.rs index daa8be714ab..be00cbbee8a 100644 --- a/packages/rs-drive/src/drive/fee_pools/epochs/credit_distribution_pools.rs +++ b/packages/rs-drive/src/drive/fee_pools/epochs/credit_distribution_pools.rs @@ -147,9 +147,9 @@ impl Drive { mod tests { use super::*; - use crate::common::helpers::setup::setup_drive_with_initial_state_structure; use crate::drive::batch::GroveDbOpBatch; use crate::fee_pools::epochs_root_tree_key_constants::KEY_STORAGE_FEE_POOL; + use crate::tests::helpers::setup::setup_drive_with_initial_state_structure; mod get_epoch_storage_credits_for_distribution { use super::*; diff --git a/packages/rs-drive/src/drive/fee_pools/epochs/mod.rs b/packages/rs-drive/src/drive/fee_pools/epochs/mod.rs index ff07c475330..4e49e71c0f2 100644 --- a/packages/rs-drive/src/drive/fee_pools/epochs/mod.rs +++ b/packages/rs-drive/src/drive/fee_pools/epochs/mod.rs @@ -59,7 +59,7 @@ impl Drive { mod tests { use super::*; - use crate::common::helpers::setup::setup_drive_with_initial_state_structure; + use crate::tests::helpers::setup::setup_drive_with_initial_state_structure; mod is_epoch_tree_exists { use super::*; diff --git a/packages/rs-drive/src/drive/fee_pools/epochs/proposers.rs b/packages/rs-drive/src/drive/fee_pools/epochs/proposers.rs index 7f4067ba385..68678520826 100644 --- a/packages/rs-drive/src/drive/fee_pools/epochs/proposers.rs +++ b/packages/rs-drive/src/drive/fee_pools/epochs/proposers.rs @@ -148,8 +148,8 @@ impl Drive { #[cfg(test)] mod tests { use super::*; - use crate::common::helpers::setup::setup_drive_with_initial_state_structure; use crate::drive::batch::GroveDbOpBatch; + use crate::tests::helpers::setup::setup_drive_with_initial_state_structure; mod get_epochs_proposer_block_count { use super::*; diff --git a/packages/rs-drive/src/drive/fee_pools/epochs/start_block.rs b/packages/rs-drive/src/drive/fee_pools/epochs/start_block.rs index 626baa4dc46..591661c32a3 100644 --- a/packages/rs-drive/src/drive/fee_pools/epochs/start_block.rs +++ b/packages/rs-drive/src/drive/fee_pools/epochs/start_block.rs @@ -144,7 +144,7 @@ impl Drive { #[cfg(test)] mod tests { use super::*; - use crate::common::helpers::setup::setup_drive_with_initial_state_structure; + use crate::tests::helpers::setup::setup_drive_with_initial_state_structure; mod get_epoch_start_block_height { use super::*; diff --git a/packages/rs-drive/src/drive/fee_pools/epochs/start_time.rs b/packages/rs-drive/src/drive/fee_pools/epochs/start_time.rs index 5db343933c0..4e0cbe1cd17 100644 --- a/packages/rs-drive/src/drive/fee_pools/epochs/start_time.rs +++ b/packages/rs-drive/src/drive/fee_pools/epochs/start_time.rs @@ -72,7 +72,7 @@ impl Drive { #[cfg(test)] mod tests { - use crate::common::helpers::setup::setup_drive_with_initial_state_structure; + use crate::tests::helpers::setup::setup_drive_with_initial_state_structure; use super::*; diff --git a/packages/rs-drive/src/drive/fee_pools/mod.rs b/packages/rs-drive/src/drive/fee_pools/mod.rs index 92924a8dc32..8a154790ce0 100644 --- a/packages/rs-drive/src/drive/fee_pools/mod.rs +++ b/packages/rs-drive/src/drive/fee_pools/mod.rs @@ -181,7 +181,7 @@ impl Drive { mod tests { use super::*; - use crate::common::helpers::setup::setup_drive_with_initial_state_structure; + use crate::tests::helpers::setup::setup_drive_with_initial_state_structure; mod add_update_epoch_storage_fee_pools_operations { use super::*; diff --git a/packages/rs-drive/src/drive/fee_pools/pending_epoch_refunds.rs b/packages/rs-drive/src/drive/fee_pools/pending_epoch_refunds.rs index f2b90110c30..5376da02281 100644 --- a/packages/rs-drive/src/drive/fee_pools/pending_epoch_refunds.rs +++ b/packages/rs-drive/src/drive/fee_pools/pending_epoch_refunds.rs @@ -219,7 +219,7 @@ pub fn add_update_pending_epoch_refunds_operations( #[cfg(test)] mod tests { use super::*; - use crate::common::helpers::setup::setup_drive_with_initial_state_structure; + use crate::tests::helpers::setup::setup_drive_with_initial_state_structure; mod fetch_and_add_pending_epoch_refunds_to_collection { use super::*; diff --git a/packages/rs-drive/src/drive/fee_pools/storage_fee_distribution_pool.rs b/packages/rs-drive/src/drive/fee_pools/storage_fee_distribution_pool.rs index de98f680bb5..59639002632 100644 --- a/packages/rs-drive/src/drive/fee_pools/storage_fee_distribution_pool.rs +++ b/packages/rs-drive/src/drive/fee_pools/storage_fee_distribution_pool.rs @@ -64,7 +64,7 @@ impl Drive { mod tests { use super::*; - use crate::common::helpers::setup::{setup_drive, setup_drive_with_initial_state_structure}; + use crate::tests::helpers::setup::{setup_drive, setup_drive_with_initial_state_structure}; mod get_storage_fees_from_distribution_pool { use super::*; diff --git a/packages/rs-drive/src/drive/fee_pools/unpaid_epoch.rs b/packages/rs-drive/src/drive/fee_pools/unpaid_epoch.rs index c298ea7b448..edd867df892 100644 --- a/packages/rs-drive/src/drive/fee_pools/unpaid_epoch.rs +++ b/packages/rs-drive/src/drive/fee_pools/unpaid_epoch.rs @@ -68,7 +68,7 @@ impl Drive { mod tests { use super::*; - use crate::common::helpers::setup::{setup_drive, setup_drive_with_initial_state_structure}; + use crate::tests::helpers::setup::{setup_drive, setup_drive_with_initial_state_structure}; mod get_unpaid_epoch_index { use super::*; diff --git a/packages/rs-drive/src/drive/genesis_time.rs b/packages/rs-drive/src/drive/genesis_time.rs index 8dc0488bbca..ca9f41ba713 100644 --- a/packages/rs-drive/src/drive/genesis_time.rs +++ b/packages/rs-drive/src/drive/genesis_time.rs @@ -77,7 +77,7 @@ impl Drive { mod tests { use super::*; - use crate::common::helpers::setup::{setup_drive, setup_drive_with_initial_state_structure}; + use crate::tests::helpers::setup::{setup_drive, setup_drive_with_initial_state_structure}; mod get_genesis_time { use super::*; diff --git a/packages/rs-drive/src/drive/identity/balance/prove.rs b/packages/rs-drive/src/drive/identity/balance/prove.rs index 9df7feb2999..abc394d7206 100644 --- a/packages/rs-drive/src/drive/identity/balance/prove.rs +++ b/packages/rs-drive/src/drive/identity/balance/prove.rs @@ -28,8 +28,8 @@ impl Drive { #[cfg(test)] mod tests { use super::*; - use crate::common::helpers::setup::setup_drive_with_initial_state_structure; use crate::drive::block_info::BlockInfo; + use crate::tests::helpers::setup::setup_drive_with_initial_state_structure; use dpp::identity::Identity; mod prove_identity_balance { diff --git a/packages/rs-drive/src/drive/identity/balance/update.rs b/packages/rs-drive/src/drive/identity/balance/update.rs index 25f6e4000a0..b1f98fd5e9a 100644 --- a/packages/rs-drive/src/drive/identity/balance/update.rs +++ b/packages/rs-drive/src/drive/identity/balance/update.rs @@ -475,7 +475,7 @@ mod tests { use crate::{ common::helpers::identities::create_test_identity, - common::helpers::setup::setup_drive_with_initial_state_structure, + tests::helpers::setup::setup_drive_with_initial_state_structure, }; mod add_to_identity_balance { diff --git a/packages/rs-drive/src/drive/identity/fetch/fetch_by_public_key_hashes.rs b/packages/rs-drive/src/drive/identity/fetch/fetch_by_public_key_hashes.rs index f4c2b720825..33560d152a3 100644 --- a/packages/rs-drive/src/drive/identity/fetch/fetch_by_public_key_hashes.rs +++ b/packages/rs-drive/src/drive/identity/fetch/fetch_by_public_key_hashes.rs @@ -278,8 +278,8 @@ impl Drive { #[cfg(test)] mod tests { - use crate::common::helpers::setup::setup_drive; use crate::drive::block_info::BlockInfo; + use crate::tests::helpers::setup::setup_drive; use super::*; diff --git a/packages/rs-drive/src/drive/identity/fetch/full_identity.rs b/packages/rs-drive/src/drive/identity/fetch/full_identity.rs index 249ae620099..a6c42ddc93a 100644 --- a/packages/rs-drive/src/drive/identity/fetch/full_identity.rs +++ b/packages/rs-drive/src/drive/identity/fetch/full_identity.rs @@ -152,7 +152,7 @@ impl Drive { #[cfg(test)] mod tests { use super::*; - use crate::common::helpers::setup::setup_drive_with_initial_state_structure; + use crate::tests::helpers::setup::setup_drive_with_initial_state_structure; mod fetch_full_identities { use super::*; diff --git a/packages/rs-drive/src/drive/identity/fetch/prove/full_identities_by_public_key_hashes.rs b/packages/rs-drive/src/drive/identity/fetch/prove/full_identities_by_public_key_hashes.rs index c6d54d02c0a..1db2ee31859 100644 --- a/packages/rs-drive/src/drive/identity/fetch/prove/full_identities_by_public_key_hashes.rs +++ b/packages/rs-drive/src/drive/identity/fetch/prove/full_identities_by_public_key_hashes.rs @@ -56,8 +56,8 @@ impl Drive { #[cfg(test)] mod tests { use super::*; - use crate::common::helpers::setup::setup_drive_with_initial_state_structure; use crate::drive::block_info::BlockInfo; + use crate::tests::helpers::setup::setup_drive_with_initial_state_structure; use dpp::identity::Identity; use std::collections::BTreeMap; diff --git a/packages/rs-drive/src/drive/identity/fetch/prove/full_identity.rs b/packages/rs-drive/src/drive/identity/fetch/prove/full_identity.rs index fd3443bd357..48a386aa7be 100644 --- a/packages/rs-drive/src/drive/identity/fetch/prove/full_identity.rs +++ b/packages/rs-drive/src/drive/identity/fetch/prove/full_identity.rs @@ -30,8 +30,8 @@ impl Drive { #[cfg(test)] mod tests { use super::*; - use crate::common::helpers::setup::setup_drive_with_initial_state_structure; use crate::drive::block_info::BlockInfo; + use crate::tests::helpers::setup::setup_drive_with_initial_state_structure; use dpp::identity::Identity; use grovedb::query_result_type::QueryResultType; diff --git a/packages/rs-drive/src/drive/identity/fetch/prove/identity_ids_by_public_key_hashes.rs b/packages/rs-drive/src/drive/identity/fetch/prove/identity_ids_by_public_key_hashes.rs index d38600ec9be..83dbed107ca 100644 --- a/packages/rs-drive/src/drive/identity/fetch/prove/identity_ids_by_public_key_hashes.rs +++ b/packages/rs-drive/src/drive/identity/fetch/prove/identity_ids_by_public_key_hashes.rs @@ -29,8 +29,8 @@ impl Drive { #[cfg(test)] mod tests { use super::*; - use crate::common::helpers::setup::setup_drive_with_initial_state_structure; use crate::drive::block_info::BlockInfo; + use crate::tests::helpers::setup::setup_drive_with_initial_state_structure; use dpp::identity::Identity; use std::collections::BTreeMap; diff --git a/packages/rs-drive/src/drive/identity/insert.rs b/packages/rs-drive/src/drive/identity/insert.rs index 8b866f85207..4162b1be9b2 100644 --- a/packages/rs-drive/src/drive/identity/insert.rs +++ b/packages/rs-drive/src/drive/identity/insert.rs @@ -161,7 +161,7 @@ impl Drive { #[cfg(test)] mod tests { - use crate::{common::helpers::setup::setup_drive, drive::block_info::BlockInfo}; + use crate::{drive::block_info::BlockInfo, tests::helpers::setup::setup_drive}; use dpp::identity::Identity; use tempfile::TempDir; diff --git a/packages/rs-drive/src/drive/identity/key/fetch.rs b/packages/rs-drive/src/drive/identity/key/fetch.rs index 96fbfa5a905..c2b07b5d425 100644 --- a/packages/rs-drive/src/drive/identity/key/fetch.rs +++ b/packages/rs-drive/src/drive/identity/key/fetch.rs @@ -504,8 +504,8 @@ impl Drive { #[cfg(test)] mod tests { - use crate::common::helpers::setup::setup_drive; use crate::drive::block_info::BlockInfo; + use crate::tests::helpers::setup::setup_drive; use dpp::identity::Identity; use super::*; diff --git a/packages/rs-drive/src/drive/identity/key/insert.rs b/packages/rs-drive/src/drive/identity/key/insert.rs index bcb973b6022..0d6a75e441b 100644 --- a/packages/rs-drive/src/drive/identity/key/insert.rs +++ b/packages/rs-drive/src/drive/identity/key/insert.rs @@ -22,7 +22,6 @@ use grovedb::reference_path::ReferencePathType; use grovedb::{Element, EstimatedLayerInformation, TransactionArg}; use integer_encoding::VarInt; -use serde::Serialize; use std::collections::HashMap; pub enum ContractApplyInfo { diff --git a/packages/rs-drive/src/drive/identity/update.rs b/packages/rs-drive/src/drive/identity/update.rs index 5ef95937c8c..b24fd9995f6 100644 --- a/packages/rs-drive/src/drive/identity/update.rs +++ b/packages/rs-drive/src/drive/identity/update.rs @@ -270,7 +270,7 @@ mod tests { use super::*; use dpp::prelude::*; - use crate::common::helpers::setup::setup_drive_with_initial_state_structure; + use crate::tests::helpers::setup::setup_drive_with_initial_state_structure; mod add_new_keys_to_identity { use super::*; diff --git a/packages/rs-drive/src/drive/identity/withdrawals/queue.rs b/packages/rs-drive/src/drive/identity/withdrawals/queue.rs index cf096b747ae..f52c50a1690 100644 --- a/packages/rs-drive/src/drive/identity/withdrawals/queue.rs +++ b/packages/rs-drive/src/drive/identity/withdrawals/queue.rs @@ -89,9 +89,9 @@ impl Drive { #[cfg(test)] mod tests { use crate::{ - common::helpers::setup::setup_drive_with_initial_state_structure, drive::{batch::DriveOperationType, block_info::BlockInfo}, fee_pools::epochs::Epoch, + tests::helpers::setup::setup_drive_with_initial_state_structure, }; #[test] diff --git a/packages/rs-drive/src/drive/identity/withdrawals/transaction_index_counter.rs b/packages/rs-drive/src/drive/identity/withdrawals/transaction_index_counter.rs index 68255c4a619..dcc2ecaee13 100644 --- a/packages/rs-drive/src/drive/identity/withdrawals/transaction_index_counter.rs +++ b/packages/rs-drive/src/drive/identity/withdrawals/transaction_index_counter.rs @@ -146,12 +146,12 @@ mod tests { use grovedb::Element; use crate::{ - common::helpers::setup::setup_drive_with_initial_state_structure, drive::{ block_info::BlockInfo, identity::withdrawals::paths::get_withdrawal_transactions_expired_ids_path, }, fee_pools::epochs::Epoch, + tests::helpers::setup::setup_drive_with_initial_state_structure, }; #[test] diff --git a/packages/rs-drive/src/drive/identity/withdrawals/withdrawal_status.rs b/packages/rs-drive/src/drive/identity/withdrawals/withdrawal_status.rs index 30ce0be3ec1..c8f671ad400 100644 --- a/packages/rs-drive/src/drive/identity/withdrawals/withdrawal_status.rs +++ b/packages/rs-drive/src/drive/identity/withdrawals/withdrawal_status.rs @@ -204,8 +204,8 @@ mod tests { use dpp::tests::fixtures::get_withdrawal_document_fixture; use serde_json::json; - use crate::common::helpers::setup::setup_drive_with_initial_state_structure; - use crate::common::helpers::setup::{setup_document, setup_system_data_contract}; + use crate::tests::helpers::setup::setup_drive_with_initial_state_structure; + use crate::tests::helpers::setup::{setup_document, setup_system_data_contract}; mod fetch_withdrawal_documents_by_status { use dpp::data_contract::DriveContractExt; diff --git a/packages/rs-drive/src/fee_pools/epochs/operations_factory.rs b/packages/rs-drive/src/fee_pools/epochs/operations_factory.rs index 055b393b5e7..fb03f4228dc 100644 --- a/packages/rs-drive/src/fee_pools/epochs/operations_factory.rs +++ b/packages/rs-drive/src/fee_pools/epochs/operations_factory.rs @@ -217,7 +217,7 @@ impl Epoch { #[cfg(test)] mod tests { use super::*; - use crate::common::helpers::setup::{setup_drive, setup_drive_with_initial_state_structure}; + use crate::tests::helpers::setup::{setup_drive, setup_drive_with_initial_state_structure}; use chrono::Utc; mod increment_proposer_block_count_operation { diff --git a/packages/rs-drive/src/fee_pools/mod.rs b/packages/rs-drive/src/fee_pools/mod.rs index e6ee6539c69..efcaeaba882 100644 --- a/packages/rs-drive/src/fee_pools/mod.rs +++ b/packages/rs-drive/src/fee_pools/mod.rs @@ -94,7 +94,7 @@ pub fn update_unpaid_epoch_index_operation(epoch_index: EpochIndex) -> GroveDbOp #[cfg(test)] mod tests { use super::*; - use crate::common::helpers::setup::setup_drive_with_initial_state_structure; + use crate::tests::helpers::setup::setup_drive_with_initial_state_structure; mod add_create_fee_pool_trees_operations { use super::*; diff --git a/packages/rs-drive/src/lib.rs b/packages/rs-drive/src/lib.rs index b09e4e44e65..c3ff17eed83 100644 --- a/packages/rs-drive/src/lib.rs +++ b/packages/rs-drive/src/lib.rs @@ -30,3 +30,7 @@ pub mod rpc; pub use dpp; /// GroveDB module pub use grovedb; + +/// Test helpers +#[cfg(feature = "test-helpers")] +pub mod tests; diff --git a/packages/rs-drive/src/tests/helpers/mod.rs b/packages/rs-drive/src/tests/helpers/mod.rs new file mode 100644 index 00000000000..138906d09f7 --- /dev/null +++ b/packages/rs-drive/src/tests/helpers/mod.rs @@ -0,0 +1 @@ +pub mod setup; diff --git a/packages/rs-drive/src/common/helpers/setup.rs b/packages/rs-drive/src/tests/helpers/setup.rs similarity index 100% rename from packages/rs-drive/src/common/helpers/setup.rs rename to packages/rs-drive/src/tests/helpers/setup.rs diff --git a/packages/rs-drive/src/tests/mod.rs b/packages/rs-drive/src/tests/mod.rs new file mode 100644 index 00000000000..b87c65442fc --- /dev/null +++ b/packages/rs-drive/src/tests/mod.rs @@ -0,0 +1,2 @@ +/// Test helpers +pub mod helpers; diff --git a/packages/rs-drive/tests/query_tests.rs b/packages/rs-drive/tests/query_tests.rs index e923bc75fdd..727fa5dbe07 100644 --- a/packages/rs-drive/tests/query_tests.rs +++ b/packages/rs-drive/tests/query_tests.rs @@ -47,8 +47,6 @@ use serde_json::json; use tempfile::TempDir; use drive::common; -#[cfg(test)] -use drive::common::helpers::setup::setup_drive; use drive::common::setup_contract; use drive::drive::batch::GroveDbOpBatch; use drive::drive::config::DriveConfig; @@ -59,6 +57,8 @@ use drive::drive::object_size_info::{DocumentAndContractInfo, OwnedDocumentInfo} use drive::drive::Drive; use drive::error::{query::QueryError, Error}; use drive::query::DriveQuery; +#[cfg(test)] +use drive::tests::helpers::setup::setup_drive; use dpp::data_contract::validation::data_contract_validator::DataContractValidator; use dpp::document::document_stub::DocumentStub; diff --git a/packages/rs-drive/tests/query_tests_history.rs b/packages/rs-drive/tests/query_tests_history.rs index 6ebd33ecd7c..c09247c0894 100644 --- a/packages/rs-drive/tests/query_tests_history.rs +++ b/packages/rs-drive/tests/query_tests_history.rs @@ -45,7 +45,7 @@ use serde_json::json; use drive::common; -use drive::common::helpers::setup::setup_drive; +use drive::tests::helpers::setup::setup_drive; use drive::contract::Contract; use drive::drive::batch::GroveDbOpBatch; From 57473a63b951f4caebb04b06355b3c7849f1e6e4 Mon Sep 17 00:00:00 2001 From: Djavid Gabibiyan Date: Wed, 15 Feb 2023 21:46:33 +0500 Subject: [PATCH 130/170] chore: PR comments --- packages/rs-dpp/src/errors/non_consensus_error.rs | 7 ++++--- .../validation/state/validate_existing_withdrawal_id.rs | 7 ++----- 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/packages/rs-dpp/src/errors/non_consensus_error.rs b/packages/rs-dpp/src/errors/non_consensus_error.rs index bb68b9084e8..3596f64bdb0 100644 --- a/packages/rs-dpp/src/errors/non_consensus_error.rs +++ b/packages/rs-dpp/src/errors/non_consensus_error.rs @@ -1,7 +1,8 @@ use thiserror::Error; use crate::{ - CompatibleProtocolVersionIsNotDefinedError, InvalidVectorSizeError, SerdeParsingError, + prelude::Identifier, CompatibleProtocolVersionIsNotDefinedError, InvalidVectorSizeError, + SerdeParsingError, }; #[derive(Debug, Error)] @@ -35,8 +36,8 @@ pub enum NonConsensusError { details: String, }, - #[error("Withdrawal with id {id_string} already exists")] - WithdrawalIdAlreadyExists { id_string: String }, + #[error("Withdrawal with id {id} already exists")] + WithdrawalIdAlreadyExists { id: Identifier }, #[error(transparent)] Error(#[from] anyhow::Error), diff --git a/packages/rs-dpp/src/identity/state_transition/identity_credit_withdrawal_transition/validation/state/validate_existing_withdrawal_id.rs b/packages/rs-dpp/src/identity/state_transition/identity_credit_withdrawal_transition/validation/state/validate_existing_withdrawal_id.rs index 9618688df63..7f8d08dd952 100644 --- a/packages/rs-dpp/src/identity/state_transition/identity_credit_withdrawal_transition/validation/state/validate_existing_withdrawal_id.rs +++ b/packages/rs-dpp/src/identity/state_transition/identity_credit_withdrawal_transition/validation/state/validate_existing_withdrawal_id.rs @@ -4,8 +4,7 @@ use serde_json::json; use crate::{ contracts::withdrawals_contract, document::Document, identity::state_transition::identity_credit_withdrawal_transition::IdentityCreditWithdrawalTransition, - prelude::Identifier, state_repository::StateRepositoryLike, util::string_encoding::Encoding, - NonConsensusError, + prelude::Identifier, state_repository::StateRepositoryLike, NonConsensusError, }; pub async fn validate_existing_withdrawal_id( @@ -30,9 +29,7 @@ where .await?; if !documents.is_empty() { - return Err(NonConsensusError::WithdrawalIdAlreadyExists { - id_string: document_id.to_string(Encoding::Base58), - }); + return Err(NonConsensusError::WithdrawalIdAlreadyExists { id: *document_id }); } Ok(()) From 9cfbba9f040d6eae50695dd2bb17b60c0b983975 Mon Sep 17 00:00:00 2001 From: Djavid Gabibiyan Date: Wed, 15 Feb 2023 21:51:31 +0500 Subject: [PATCH 131/170] chore: PR comments --- ...credit_withdrawal_transition_factory_spec.rs | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/packages/rs-dpp/src/tests/identity/state_transition/identity_credit_withdrawal_transition/apply_identity_credit_withdrawal_transition_factory_spec.rs b/packages/rs-dpp/src/tests/identity/state_transition/identity_credit_withdrawal_transition/apply_identity_credit_withdrawal_transition_factory_spec.rs index ccb690add7a..6ae627e3919 100644 --- a/packages/rs-dpp/src/tests/identity/state_transition/identity_credit_withdrawal_transition/apply_identity_credit_withdrawal_transition_factory_spec.rs +++ b/packages/rs-dpp/src/tests/identity/state_transition/identity_credit_withdrawal_transition/apply_identity_credit_withdrawal_transition_factory_spec.rs @@ -36,7 +36,7 @@ mod apply_identity_credit_withdrawal_transition_factory { .apply_identity_credit_withdrawal_transition(&state_transition) .await { - Ok(_) => assert!(false, "should not be able to apply state transition"), + Ok(_) => panic!("should not be able to apply state transition"), Err(e) => { assert_eq!(e.to_string(), "Withdrawals data contract not found"); } @@ -44,12 +44,13 @@ mod apply_identity_credit_withdrawal_transition_factory { } #[tokio::test] - async fn should_call_state_repository_methods() { + async fn should_create_withdrawal_and_reduce_balance() { let block_time_seconds = 1675709306; - let mut state_transition = IdentityCreditWithdrawalTransition::default(); - - state_transition.amount = 10; + let state_transition = IdentityCreditWithdrawalTransition { + amount: 10, + ..Default::default() + }; let mut state_repository = MockStateRepositoryLike::default(); @@ -82,10 +83,8 @@ mod apply_identity_credit_withdrawal_transition_factory { .expect_create_document() .times(1) .withf(move |doc, _| { - let created_at_match = - doc.created_at == Some((block_time_seconds as i64 * 1000) as i64); - let updated_at_match = - doc.created_at == Some((block_time_seconds as i64 * 1000) as i64); + let created_at_match = doc.created_at == Some(block_time_seconds as i64 * 1000); + let updated_at_match = doc.created_at == Some(block_time_seconds as i64 * 1000); let document_data_match = doc.data == json!({ From 2a744a87c2d586de81bf597d3cee8f4a86ea4e81 Mon Sep 17 00:00:00 2001 From: Djavid Gabibiyan Date: Wed, 15 Feb 2023 22:08:12 +0500 Subject: [PATCH 132/170] chore: PR comments --- .../rs-dpp/src/errors/non_consensus_error.rs | 6 +-- ...ty_credit_withdrawal_transition_factory.rs | 45 ++++++++++--------- .../validation/state/mod.rs | 1 - .../state/validate_existing_withdrawal_id.rs | 36 --------------- 4 files changed, 24 insertions(+), 64 deletions(-) delete mode 100644 packages/rs-dpp/src/identity/state_transition/identity_credit_withdrawal_transition/validation/state/validate_existing_withdrawal_id.rs diff --git a/packages/rs-dpp/src/errors/non_consensus_error.rs b/packages/rs-dpp/src/errors/non_consensus_error.rs index 3596f64bdb0..44ad0a627d1 100644 --- a/packages/rs-dpp/src/errors/non_consensus_error.rs +++ b/packages/rs-dpp/src/errors/non_consensus_error.rs @@ -1,8 +1,7 @@ use thiserror::Error; use crate::{ - prelude::Identifier, CompatibleProtocolVersionIsNotDefinedError, InvalidVectorSizeError, - SerdeParsingError, + CompatibleProtocolVersionIsNotDefinedError, InvalidVectorSizeError, SerdeParsingError, }; #[derive(Debug, Error)] @@ -36,9 +35,6 @@ pub enum NonConsensusError { details: String, }, - #[error("Withdrawal with id {id} already exists")] - WithdrawalIdAlreadyExists { id: Identifier }, - #[error(transparent)] Error(#[from] anyhow::Error), } diff --git a/packages/rs-dpp/src/identity/state_transition/identity_credit_withdrawal_transition/apply_identity_credit_withdrawal_transition_factory.rs b/packages/rs-dpp/src/identity/state_transition/identity_credit_withdrawal_transition/apply_identity_credit_withdrawal_transition_factory.rs index cbde8545b94..2a08bc681ae 100644 --- a/packages/rs-dpp/src/identity/state_transition/identity_credit_withdrawal_transition/apply_identity_credit_withdrawal_transition_factory.rs +++ b/packages/rs-dpp/src/identity/state_transition/identity_credit_withdrawal_transition/apply_identity_credit_withdrawal_transition_factory.rs @@ -12,10 +12,7 @@ use crate::{ util::entropy_generator::generate, }; -use super::{ - validation::state::validate_existing_withdrawal_id::validate_existing_withdrawal_id, - IdentityCreditWithdrawalTransition, -}; +use super::IdentityCreditWithdrawalTransition; const PLATFORM_BLOCK_HEADER_TIME_PROPERTY: &str = "time"; const PLATFORM_BLOCK_HEADER_TIME_SECONDS_PROPERTY: &str = "seconds"; @@ -72,23 +69,9 @@ where withdrawals_contract::property_names::STATUS: withdrawals_contract::Status::QUEUED, }); - let document_entropy = generate()?; - - let mut document_id = generate_document_id::generate_document_id( - data_contract_id, - data_contract_owner_id, - &document_type, - &document_entropy, - ); - - while validate_existing_withdrawal_id( - &self.state_repository, - &document_id, - state_transition, - ) - .await - .is_err() - { + let mut document_id; + + loop { let document_entropy = generate()?; document_id = generate_document_id::generate_document_id( @@ -96,7 +79,25 @@ where data_contract_owner_id, &document_type, &document_entropy, - ) + ); + + let documents: Vec = self + .state_repository + .fetch_documents( + withdrawals_contract::CONTRACT_ID.deref(), + withdrawals_contract::types::WITHDRAWAL, + json!({ + "where": [ + ["$id", "==", document_id], + ], + }), + &state_transition.execution_context, + ) + .await?; + + if documents.is_empty() { + break; + } } // TODO: use DocumentFactory once it is complete diff --git a/packages/rs-dpp/src/identity/state_transition/identity_credit_withdrawal_transition/validation/state/mod.rs b/packages/rs-dpp/src/identity/state_transition/identity_credit_withdrawal_transition/validation/state/mod.rs index 4c6fc2fc426..cdad34d2bce 100644 --- a/packages/rs-dpp/src/identity/state_transition/identity_credit_withdrawal_transition/validation/state/mod.rs +++ b/packages/rs-dpp/src/identity/state_transition/identity_credit_withdrawal_transition/validation/state/mod.rs @@ -1,2 +1 @@ -pub mod validate_existing_withdrawal_id; pub mod validate_identity_credit_withdrawal_transition_state; diff --git a/packages/rs-dpp/src/identity/state_transition/identity_credit_withdrawal_transition/validation/state/validate_existing_withdrawal_id.rs b/packages/rs-dpp/src/identity/state_transition/identity_credit_withdrawal_transition/validation/state/validate_existing_withdrawal_id.rs deleted file mode 100644 index 7f8d08dd952..00000000000 --- a/packages/rs-dpp/src/identity/state_transition/identity_credit_withdrawal_transition/validation/state/validate_existing_withdrawal_id.rs +++ /dev/null @@ -1,36 +0,0 @@ -use lazy_static::__Deref; -use serde_json::json; - -use crate::{ - contracts::withdrawals_contract, document::Document, - identity::state_transition::identity_credit_withdrawal_transition::IdentityCreditWithdrawalTransition, - prelude::Identifier, state_repository::StateRepositoryLike, NonConsensusError, -}; - -pub async fn validate_existing_withdrawal_id( - state_repository: &SR, - document_id: &Identifier, - state_transition: &IdentityCreditWithdrawalTransition, -) -> Result<(), NonConsensusError> -where - SR: StateRepositoryLike, -{ - let documents: Vec = state_repository - .fetch_documents( - withdrawals_contract::CONTRACT_ID.deref(), - withdrawals_contract::types::WITHDRAWAL, - json!({ - "where": [ - ["$id", "==", document_id], - ], - }), - &state_transition.execution_context, - ) - .await?; - - if !documents.is_empty() { - return Err(NonConsensusError::WithdrawalIdAlreadyExists { id: *document_id }); - } - - Ok(()) -} From 4a1a9aeb92fa3fab024cfff212fbdb6f9e1ef9b0 Mon Sep 17 00:00:00 2001 From: Djavid Gabibiyan Date: Wed, 15 Feb 2023 23:58:54 +0500 Subject: [PATCH 133/170] chore: PR comments --- packages/rs-dpp/src/document/document_stub.rs | 7 +------ packages/rs-drive-abci/src/abci/handlers.rs | 11 +---------- .../src/identity_credit_withdrawal/mod.rs | 2 +- 3 files changed, 3 insertions(+), 17 deletions(-) diff --git a/packages/rs-dpp/src/document/document_stub.rs b/packages/rs-dpp/src/document/document_stub.rs index 73f7365b172..70023e569ca 100644 --- a/packages/rs-dpp/src/document/document_stub.rs +++ b/packages/rs-dpp/src/document/document_stub.rs @@ -507,18 +507,13 @@ impl DocumentStub { } pub fn increment_revision(&mut self) -> Result<(), ProtocolError> { - let property_name = "$revision"; - let revision = self.revision; let new_revision = revision .checked_add(1) .ok_or(ProtocolError::Overflow("overflow when adding 1"))?; - self.properties.insert( - property_name.to_string(), - Value::Integer(Integer::from(new_revision)), - ); + self.revision = new_revision; Ok(()) } diff --git a/packages/rs-drive-abci/src/abci/handlers.rs b/packages/rs-drive-abci/src/abci/handlers.rs index edb6ebccc71..3947f1a76c4 100644 --- a/packages/rs-drive-abci/src/abci/handlers.rs +++ b/packages/rs-drive-abci/src/abci/handlers.rs @@ -262,7 +262,7 @@ mod tests { use drive::fee::epoch::CreditsPerEpoch; use drive::fee_pools::epochs::Epoch; use drive::rpc::core::MockCoreRPCLike; - use drive::tests::helpers::setup::{setup_document, setup_system_data_contract}; + use drive::tests::helpers::setup::setup_document; use rust_decimal::prelude::ToPrimitive; use serde_json::json; use std::cmp::Ordering; @@ -298,8 +298,6 @@ mod tests { let data_contract = load_system_data_contract(SystemDataContract::Withdrawals) .expect("to load system data contract"); - setup_system_data_contract(&platform.drive, &data_contract, Some(&transaction)); - // Init withdrawal requests let withdrawals: Vec = (0..16) .map(|index: u64| (index.to_be_bytes().to_vec(), vec![index as u8; 32])) @@ -593,13 +591,6 @@ mod tests { .init_chain(init_chain_request, Some(&transaction)) .expect("should init chain"); - setup_system_data_contract( - &platform.drive, - &load_system_data_contract(SystemDataContract::Withdrawals) - .expect("to load system data contract"), - Some(&transaction), - ); - // setup the contract let contract = platform.create_mn_shares_contract(Some(&transaction)); diff --git a/packages/rs-drive-abci/src/identity_credit_withdrawal/mod.rs b/packages/rs-drive-abci/src/identity_credit_withdrawal/mod.rs index 3ccd2ef3a2e..695bd8fde7d 100644 --- a/packages/rs-drive-abci/src/identity_credit_withdrawal/mod.rs +++ b/packages/rs-drive-abci/src/identity_credit_withdrawal/mod.rs @@ -796,7 +796,7 @@ mod tests { ]; for document in updated_documents { - assert_eq!(document.get_u32("$revision").expect("to get $revision"), 2); + assert_eq!(document.revision, 2); let tx_id: Vec = document .get_bytes("transactionId") From 8b1de3523a4413f9e119b5f9b560e9b95824dfeb Mon Sep 17 00:00:00 2001 From: Djavid Gabibiyan Date: Thu, 16 Feb 2023 00:57:59 +0500 Subject: [PATCH 134/170] chore: PR comments --- .../js-drive/lib/dpp/DriveStateRepository.js | 5 +++- .../IdentityBalanceStoreRepository.spec.js | 13 +++++++-- .../unit/dpp/DriveStateRepository.spec.js | 2 ++ .../src/identity_credit_withdrawal/mod.rs | 28 ++++++++++++++---- packages/rs-drive-nodejs/Drive.js | 6 +++- packages/rs-drive-nodejs/src/lib.rs | 29 ++++++++++++++++--- packages/rs-drive-nodejs/test/Drive.spec.js | 6 +++- .../drive/batch/drive_op_batch/withdrawals.rs | 2 +- .../identity/withdrawals/expired_index.rs | 4 +-- .../withdrawals/transaction_index_counter.rs | 28 ++++++++++++------ 10 files changed, 96 insertions(+), 27 deletions(-) diff --git a/packages/js-drive/lib/dpp/DriveStateRepository.js b/packages/js-drive/lib/dpp/DriveStateRepository.js index 5430c96aaeb..173c9f92efa 100644 --- a/packages/js-drive/lib/dpp/DriveStateRepository.js +++ b/packages/js-drive/lib/dpp/DriveStateRepository.js @@ -615,9 +615,12 @@ class DriveStateRepository { * @returns {Promise} */ async fetchLatestWithdrawalTransactionIndex() { - // TODO: handle dry run via passing state transition execution context + const blockInfo = BlockInfo.createFromBlockExecutionContext(this.blockExecutionContext); + return this.rsDrive.fetchLatestWithdrawalTransactionIndex( + blockInfo, this.#options.useTransaction, + this.#options.dryRun, ); } diff --git a/packages/js-drive/test/integration/identity/IdentityBalanceStoreRepository.spec.js b/packages/js-drive/test/integration/identity/IdentityBalanceStoreRepository.spec.js index 22e6ec8eb08..86e79eca563 100644 --- a/packages/js-drive/test/integration/identity/IdentityBalanceStoreRepository.spec.js +++ b/packages/js-drive/test/integration/identity/IdentityBalanceStoreRepository.spec.js @@ -21,8 +21,17 @@ describe('IdentityStoreRepository', () => { beforeEach(async () => { rsDrive = new Drive('./db/grovedb_test', { - dataContractsGlobalCacheSize: 500, - dataContractsBlockCacheSize: 500, + drive: { + dataContractsGlobalCacheSize: 500, + dataContractsBlockCacheSize: 500, + }, + core: { + rpc: { + url: '127.0.0.1', + username: '', + password: '', + }, + }, }); await rsDrive.createInitialStateStructure(); diff --git a/packages/js-drive/test/unit/dpp/DriveStateRepository.spec.js b/packages/js-drive/test/unit/dpp/DriveStateRepository.spec.js index 2e1f4212bb6..a974f8522a7 100644 --- a/packages/js-drive/test/unit/dpp/DriveStateRepository.spec.js +++ b/packages/js-drive/test/unit/dpp/DriveStateRepository.spec.js @@ -703,7 +703,9 @@ describe('DriveStateRepository', () => { expect( rsDriveMock.fetchLatestWithdrawalTransactionIndex, ).to.have.been.calledOnceWithExactly( + blockInfo, repositoryOptions.useTransaction, + repositoryOptions.dryRun, ); }); }); diff --git a/packages/rs-drive-abci/src/identity_credit_withdrawal/mod.rs b/packages/rs-drive-abci/src/identity_credit_withdrawal/mod.rs index 695bd8fde7d..4c21d7593af 100644 --- a/packages/rs-drive-abci/src/identity_credit_withdrawal/mod.rs +++ b/packages/rs-drive-abci/src/identity_credit_withdrawal/mod.rs @@ -297,8 +297,13 @@ impl Platform { transaction, )?; - let withdrawal_transactions = - self.build_withdrawal_transactions_from_documents(&documents, transaction)?; + let mut drive_operations = vec![]; + + let withdrawal_transactions = self.build_withdrawal_transactions_from_documents( + &documents, + &mut drive_operations, + transaction, + )?; let block_info = BlockInfo { time_ms: block_execution_context.block_info.block_time_ms, @@ -306,8 +311,6 @@ impl Platform { epoch: Epoch::new(block_execution_context.epoch_info.current_epoch_index), }; - let mut drive_operations = vec![]; - for document in documents.iter_mut() { let document_id = Identifier::from_bytes(&document.id)?; @@ -418,13 +421,14 @@ impl Platform { pub fn build_withdrawal_transactions_from_documents( &self, documents: &[DocumentStub], + drive_operation_types: &mut Vec, transaction: TransactionArg, ) -> Result, Error> { let mut withdrawals: HashMap = HashMap::new(); let latest_withdrawal_index = self .drive - .remove_latest_withdrawal_transaction_index(transaction)?; + .remove_latest_withdrawal_transaction_index(drive_operation_types, transaction)?; for (i, document) in documents.iter().enumerate() { let output_script_bytes = document @@ -882,6 +886,7 @@ mod tests { document::document_stub::DocumentStub, identity::state_transition::identity_credit_withdrawal_transition::Pooling, }; + use drive::drive::block_info::BlockInfo; use drive::drive::identity::withdrawals::paths::WithdrawalTransaction; use drive::tests::helpers::setup::setup_system_data_contract; use itertools::Itertools; @@ -958,10 +963,21 @@ mod tests { .expect("to create document from cbor"), ]; + let mut batch = vec![]; + let transactions = platform - .build_withdrawal_transactions_from_documents(&documents, Some(&transaction)) + .build_withdrawal_transactions_from_documents( + &documents, + &mut batch, + Some(&transaction), + ) .expect("to build transactions from documents"); + platform + .drive + .apply_drive_operations(batch, true, &BlockInfo::default(), Some(&transaction)) + .expect("to apply drive op batch"); + assert_eq!( transactions .values() diff --git a/packages/rs-drive-nodejs/Drive.js b/packages/rs-drive-nodejs/Drive.js index ebc26a6b7b5..d1ac2239a74 100644 --- a/packages/rs-drive-nodejs/Drive.js +++ b/packages/rs-drive-nodejs/Drive.js @@ -732,13 +732,17 @@ class Drive { /** * Fetch the latest index of the withdrawal transaction in a queue * + * @param {RawBlockInfo} blockInfo * @param {boolean} [useTransaction=false] + * @param {boolean} [dryRun=false] * * @returns {Promise} */ - async fetchLatestWithdrawalTransactionIndex(useTransaction = false) { + async fetchLatestWithdrawalTransactionIndex(blockInfo, useTransaction = false, dryRun = false) { return driveFetchLatestWithdrawalTransactionIndexAsync.call( this.drive, + blockInfo, + !dryRun, useTransaction, ); } diff --git a/packages/rs-drive-nodejs/src/lib.rs b/packages/rs-drive-nodejs/src/lib.rs index bfa72731c09..1687ecade4e 100644 --- a/packages/rs-drive-nodejs/src/lib.rs +++ b/packages/rs-drive-nodejs/src/lib.rs @@ -3323,9 +3323,13 @@ impl PlatformWrapper { fn js_fetch_latest_withdrawal_transaction_index( mut cx: FunctionContext, ) -> JsResult { - let js_using_transaction = cx.argument::(0)?; - let js_callback = cx.argument::(1)?.root(&mut cx); + let js_block_info = cx.argument::(0)?; + let js_apply = cx.argument::(1)?; + let js_using_transaction = cx.argument::(2)?; + let js_callback = cx.argument::(3)?.root(&mut cx); + let apply = js_apply.value(&mut cx); + let block_info = converter::js_object_to_block_info(&mut cx, js_block_info)?; let using_transaction = js_using_transaction.value(&mut cx); let db = cx @@ -3344,10 +3348,27 @@ impl PlatformWrapper { }; let result = transaction_result.and_then(|transaction_arg| { + let mut drive_operation_types = vec![]; + + let result = platform + .drive + .remove_latest_withdrawal_transaction_index( + &mut drive_operation_types, + transaction_arg, + ) + .map_err(|err| err.to_string())?; + platform .drive - .remove_latest_withdrawal_transaction_index(transaction_arg) - .map_err(|err| err.to_string()) + .apply_drive_operations( + drive_operation_types, + apply, + &block_info, + transaction_arg, + ) + .map_err(|err| err.to_string())?; + + Ok(result) }); channel.send(move |mut task_context| { diff --git a/packages/rs-drive-nodejs/test/Drive.spec.js b/packages/rs-drive-nodejs/test/Drive.spec.js index 0b16379735f..7d49e7c4e7a 100644 --- a/packages/rs-drive-nodejs/test/Drive.spec.js +++ b/packages/rs-drive-nodejs/test/Drive.spec.js @@ -986,7 +986,11 @@ describe('Drive', function main() { }); it('should return 0 on the first call', async () => { - const result = await drive.fetchLatestWithdrawalTransactionIndex(); + const result = await drive.fetchLatestWithdrawalTransactionIndex({ + height: 1, + epoch: 1, + timeMs: (new Date()).getTime(), + }); expect(result).to.equal(0); }); diff --git a/packages/rs-drive/src/drive/batch/drive_op_batch/withdrawals.rs b/packages/rs-drive/src/drive/batch/drive_op_batch/withdrawals.rs index e554ab5d4d1..0249a2b9340 100644 --- a/packages/rs-drive/src/drive/batch/drive_op_batch/withdrawals.rs +++ b/packages/rs-drive/src/drive/batch/drive_op_batch/withdrawals.rs @@ -21,7 +21,7 @@ pub enum WithdrawalOperationType<'a> { /// Removes expired index from the tree DeleteExpiredIndex { /// index value - key: &'a [u8], + key: Vec, }, /// Update index counter UpdateIndexCounter { diff --git a/packages/rs-drive/src/drive/identity/withdrawals/expired_index.rs b/packages/rs-drive/src/drive/identity/withdrawals/expired_index.rs index 3d04afd5793..980d9bbf00b 100644 --- a/packages/rs-drive/src/drive/identity/withdrawals/expired_index.rs +++ b/packages/rs-drive/src/drive/identity/withdrawals/expired_index.rs @@ -32,7 +32,7 @@ impl Drive { pub(crate) fn delete_withdrawal_expired_index( &self, - key: &[u8], + key: Vec, transaction: TransactionArg, ) -> Result, Error> { let mut drive_operations = vec![]; @@ -41,7 +41,7 @@ impl Drive { self.batch_delete( path, - key, + &key, BatchDeleteApplyType::StatefulBatchDelete { is_known_to_be_subtree_with_sum: Some((false, false)), }, diff --git a/packages/rs-drive/src/drive/identity/withdrawals/transaction_index_counter.rs b/packages/rs-drive/src/drive/identity/withdrawals/transaction_index_counter.rs index dcc2ecaee13..79e8b0b63c4 100644 --- a/packages/rs-drive/src/drive/identity/withdrawals/transaction_index_counter.rs +++ b/packages/rs-drive/src/drive/identity/withdrawals/transaction_index_counter.rs @@ -14,8 +14,7 @@ use crate::{ }; use super::paths::{ - get_withdrawal_transactions_expired_ids_path, get_withdrawal_transactions_expired_ids_path_vec, - WITHDRAWAL_TRANSACTIONS_COUNTER_ID, + get_withdrawal_transactions_expired_ids_path_vec, WITHDRAWAL_TRANSACTIONS_COUNTER_ID, }; impl Drive { @@ -42,6 +41,7 @@ impl Drive { /// Get latest withdrawal index in a queue pub fn remove_latest_withdrawal_transaction_index( &self, + drive_operation_types: &mut Vec, transaction: TransactionArg, ) -> Result { let mut inner_query = Query::new(); @@ -69,16 +69,16 @@ impl Drive { if let QueryResultElement::KeyElementPairResultItem((key, _)) = expired_index_element_pair { + drive_operation_types.push(DriveOperationType::WithdrawalOperation( + WithdrawalOperationType::DeleteExpiredIndex { key: key.clone() }, + )); + let index = u64::from_be_bytes(key.clone().try_into().map_err(|_| { Error::Drive(DriveError::CorruptedCodeExecution( "Transaction index has wrong length", )) })?); - let path: [&[u8]; 2] = get_withdrawal_transactions_expired_ids_path(); - - self.grove.delete(path, key, None, transaction).unwrap()?; - return Ok(index); } } @@ -176,10 +176,16 @@ mod tests { .apply_drive_operations(batch, true, &block_info, Some(&transaction)) .expect("to apply drive ops"); + let mut batch = vec![]; + let stored_counter = drive - .remove_latest_withdrawal_transaction_index(Some(&transaction)) + .remove_latest_withdrawal_transaction_index(&mut batch, Some(&transaction)) .expect("to withdraw counter"); + drive + .apply_drive_operations(batch, true, &block_info, Some(&transaction)) + .expect("to apply drive ops"); + assert_eq!(stored_counter, counter); } @@ -189,8 +195,10 @@ mod tests { let transaction = drive.grove.start_transaction(); + let mut batch = vec![]; + let stored_counter = drive - .remove_latest_withdrawal_transaction_index(Some(&transaction)) + .remove_latest_withdrawal_transaction_index(&mut batch, Some(&transaction)) .expect("to withdraw counter"); assert_eq!(stored_counter, 0); @@ -218,8 +226,10 @@ mod tests { .unwrap() .expect("to update index counter"); + let mut batch = vec![]; + let stored_counter = drive - .remove_latest_withdrawal_transaction_index(Some(&transaction)) + .remove_latest_withdrawal_transaction_index(&mut batch, Some(&transaction)) .expect("to withdraw counter"); assert_eq!(stored_counter, 42); From cc895aba6fe73bfc999b79ec6c8ec8a3673e41b4 Mon Sep 17 00:00:00 2001 From: Djavid Gabibiyan Date: Thu, 16 Feb 2023 10:09:48 +0500 Subject: [PATCH 135/170] chore: PR comments --- packages/rs-drive-nodejs/test/Drive.spec.js | 6 ------ 1 file changed, 6 deletions(-) diff --git a/packages/rs-drive-nodejs/test/Drive.spec.js b/packages/rs-drive-nodejs/test/Drive.spec.js index 7d49e7c4e7a..931d7d34a07 100644 --- a/packages/rs-drive-nodejs/test/Drive.spec.js +++ b/packages/rs-drive-nodejs/test/Drive.spec.js @@ -1029,9 +1029,6 @@ describe('Drive', function main() { describe('BlockBegin', () => { beforeEach(async () => { - await drive.createInitialStateStructure(); - await drive.createContract(withdrawalsDataContract, blockInfo); - await drive.getAbci().initChain(initChainRequest); }); @@ -1094,9 +1091,6 @@ describe('Drive', function main() { describe('BlockEnd', () => { beforeEach(async () => { - await drive.createInitialStateStructure(); - await drive.createContract(withdrawalsDataContract, blockInfo); - await drive.getAbci().initChain(initChainRequest); await drive.getAbci().blockBegin({ From 8349c8a67099000a49c739c1072c3d6904f6d5c1 Mon Sep 17 00:00:00 2001 From: Ivan Shumkov Date: Thu, 16 Feb 2023 15:15:10 +0800 Subject: [PATCH 136/170] chore(dpp): remove unnecessary schemas --- .../withdrawals-contract-documents.json | 131 ----------------- .../withdrawals/withdrawals-contract.json | 137 ------------------ 2 files changed, 268 deletions(-) delete mode 100644 packages/rs-dpp/contracts/withdrawals/withdrawals-contract-documents.json delete mode 100644 packages/rs-dpp/contracts/withdrawals/withdrawals-contract.json diff --git a/packages/rs-dpp/contracts/withdrawals/withdrawals-contract-documents.json b/packages/rs-dpp/contracts/withdrawals/withdrawals-contract-documents.json deleted file mode 100644 index 3319bb81983..00000000000 --- a/packages/rs-dpp/contracts/withdrawals/withdrawals-contract-documents.json +++ /dev/null @@ -1,131 +0,0 @@ -{ - "withdrawal": { - "description": "Withdrawal document to track underlying transaction", - "type": "object", - "indices": [ - { - "name": "identityStatus", - "properties": [ - { - "$ownerId": "asc" - }, - { - "status": "asc" - }, - { - "$createdAt": "asc" - } - ], - "unique": false - }, - { - "name": "identityRecent", - "properties": [ - { - "$ownerId": "asc" - }, - { - "$updatedAt": "asc" - }, - { - "status": "asc" - } - ], - "unique": false - }, - { - "name": "pooling", - "properties": [ - { - "status": "asc" - }, - { - "pooling": "asc" - }, - { - "coreFeePerByte": "asc" - }, - { - "$updatedAt": "asc" - } - ], - "unique": false - }, - { - "name": "transaction", - "properties": [ - { - "status": "asc" - }, - { - "transactionId": "asc" - } - ], - "unique": false - } - ], - "properties": { - "transactionId": { - "description": "Hash of asset unlock transaction. Populated with untied transaction hash on “pooled” stage and with signed transaction on “broatcasted” stage", - "type": "array", - "byteArray": true, - "minItems": 32, - "maxItems": 32 - }, - "transactionSignHeight": { - "type": "integer", - "description": "The Core height on which transaction was signed", - "minimum": 1 - }, - "transactionIndex": { - "type": "integer", - "description": "Sequential index used to create withdrawal transaction", - "minimum": 1 - }, - "amount": { - "type": "integer", - "description": "The amount to be withdrawn", - "minimum": 1000 - }, - "coreFeePerByte": { - "type": "integer", - "description": "This is the fee that you are willing to spend for this transaction in Duffs/Byte", - "minimum": 1 - }, - "pooling": { - "type": "integer", - "description": "This indicated the level at which Platform should try to pool this transaction", - "enum": [ - 0 - ] - }, - "outputScript": { - "type": "array", - "byteArray": true, - "minItems": 23, - "maxItems": 25 - }, - "status": { - "type": "integer", - "enum": [ - 0, - 1, - 2, - 3, - 4 - ] - } - }, - "additionalProperties": false, - "required": [ - "$createdAt", - "$updatedAt", - "amount", - "coreFeePerByte", - "pooling", - "outputScript", - "transactionIndex", - "status" - ] - } -} diff --git a/packages/rs-dpp/contracts/withdrawals/withdrawals-contract.json b/packages/rs-dpp/contracts/withdrawals/withdrawals-contract.json deleted file mode 100644 index 28e7d20f923..00000000000 --- a/packages/rs-dpp/contracts/withdrawals/withdrawals-contract.json +++ /dev/null @@ -1,137 +0,0 @@ -{ - "$id": "AcYUCSvAmUwryNsQqkqqD1o3BnFuzepGtR3Mhh2swLk6", - "ownerId": "AcYUCSvAmUwryNsQqkqqD1o3BnFuzepGtR3Mhh2swLk6", - "$schema": "http://json-schema.org/draft-07/schema", - "version": 1, - "documents": { - "withdrawal": { - "description": "Withdrawal document to track underlying transaction", - "type": "object", - "indices": [ - { - "name": "identityStatus", - "properties": [ - { - "$ownerId": "asc" - }, - { - "status": "asc" - }, - { - "$createdAt": "asc" - } - ], - "unique": false - }, - { - "name": "identityRecent", - "properties": [ - { - "$ownerId": "asc" - }, - { - "$updatedAt": "asc" - }, - { - "status": "asc" - } - ], - "unique": false - }, - { - "name": "pooling", - "properties": [ - { - "status": "asc" - }, - { - "pooling": "asc" - }, - { - "coreFeePerByte": "asc" - }, - { - "$updatedAt": "asc" - } - ], - "unique": false - }, - { - "name": "transaction", - "properties": [ - { - "status": "asc" - }, - { - "transactionId": "asc" - } - ], - "unique": false - } - ], - "properties": { - "transactionId": { - "description": "Hash of asset unlock transaction. Populated with untied transaction hash on “pooled” stage and with signed transaction on “broatcasted” stage", - "type": "array", - "byteArray": true, - "minItems": 32, - "maxItems": 32 - }, - "transactionSignHeight": { - "type": "integer", - "description": "The Core height on which transaction was signed", - "minimum": 1 - }, - "transactionIndex": { - "type": "integer", - "description": "Sequential index used to create withdrawal transaction", - "minimum": 1 - }, - "amount": { - "type": "integer", - "description": "The amount to be withdrawn", - "minimum": 1000 - }, - "coreFeePerByte": { - "type": "integer", - "description": "This is the fee that you are willing to spend for this transaction in Duffs/Byte", - "minimum": 1 - }, - "pooling": { - "type": "integer", - "description": "This indicated the level at which Platform should try to pool this transaction", - "enum": [ - 0 - ] - }, - "outputScript": { - "type": "array", - "byteArray": true, - "minItems": 23, - "maxItems": 25 - }, - "status": { - "type": "integer", - "enum": [ - 0, - 1, - 2, - 3, - 4 - ] - } - }, - "additionalProperties": false, - "required": [ - "$createdAt", - "$updatedAt", - "amount", - "coreFeePerByte", - "pooling", - "outputScript", - "transactionIndex", - "status" - ] - } - } -} From 785cb7095918333ab0f3e919e44fab98a4f2c688 Mon Sep 17 00:00:00 2001 From: Ivan Shumkov Date: Thu, 16 Feb 2023 15:24:24 +0800 Subject: [PATCH 137/170] refactor: change to fast return --- ...dentity_credit_withdrawal_transition_state.rs | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/packages/rs-dpp/src/identity/state_transition/identity_credit_withdrawal_transition/validation/state/validate_identity_credit_withdrawal_transition_state.rs b/packages/rs-dpp/src/identity/state_transition/identity_credit_withdrawal_transition/validation/state/validate_identity_credit_withdrawal_transition_state.rs index a3eadac4da2..5d0132b7c11 100644 --- a/packages/rs-dpp/src/identity/state_transition/identity_credit_withdrawal_transition/validation/state/validate_identity_credit_withdrawal_transition_state.rs +++ b/packages/rs-dpp/src/identity/state_transition/identity_credit_withdrawal_transition/validation/state/validate_identity_credit_withdrawal_transition_state.rs @@ -33,6 +33,7 @@ where ) -> Result, NonConsensusError> { let mut result: ValidationResult<()> = ValidationResult::default(); + // TODO: Use fetchIdentityBalance let maybe_existing_identity = self .state_repository .fetch_identity( @@ -45,17 +46,14 @@ where .map_err(Into::into) .map_err(|e| NonConsensusError::StateRepositoryFetchError(e.to_string()))?; - let existing_identity = match maybe_existing_identity { - None => { - let err = BasicError::IdentityNotFoundError { - identity_id: state_transition.identity_id, - }; + let Some(existing_identity) = maybe_existing_identity else { + let err = BasicError::IdentityNotFoundError { + identity_id: state_transition.identity_id, + }; - result.add_error(err); + result.add_error(err); - return Ok(result); - } - Some(identity) => identity, + return Ok(result); }; if existing_identity.get_balance() < state_transition.amount { From cbc80ff3d64d0a3618cf5a6551caf7a914abe5b6 Mon Sep 17 00:00:00 2001 From: Ivan Shumkov Date: Thu, 16 Feb 2023 15:24:53 +0800 Subject: [PATCH 138/170] refactor: rename enum for readability --- .../src/contracts/withdrawals_contract.rs | 4 +- .../data_trigger/get_data_triggers_factory.rs | 6 +-- .../withdrawals_data_triggers/mod.rs | 8 ++-- ...ty_credit_withdrawal_transition_factory.rs | 6 +-- .../identityCreditWithdrawal.json | 2 +- .../tests/fixtures/get_documents_fixture.rs | 2 +- ...edit_withdrawal_transition_factory_spec.rs | 2 +- packages/rs-drive-abci/src/abci/handlers.rs | 4 +- .../src/identity_credit_withdrawal/mod.rs | 40 +++++++++---------- .../identity/withdrawals/withdrawal_status.rs | 22 +++++----- 10 files changed, 48 insertions(+), 48 deletions(-) diff --git a/packages/rs-dpp/src/contracts/withdrawals_contract.rs b/packages/rs-dpp/src/contracts/withdrawals_contract.rs index c29f3673c70..c397debfa9b 100644 --- a/packages/rs-dpp/src/contracts/withdrawals_contract.rs +++ b/packages/rs-dpp/src/contracts/withdrawals_contract.rs @@ -4,7 +4,7 @@ use serde_repr::{Deserialize_repr, Serialize_repr}; use crate::prelude::Identifier; -pub mod types { +pub mod document_types { pub const WITHDRAWAL: &str = "withdrawal"; } @@ -34,7 +34,7 @@ pub mod property_names { TryFromPrimitive, IntoPrimitive, )] -pub enum Status { +pub enum WithdrawalStatus { QUEUED = 0, POOLED = 1, BROADCASTED = 2, diff --git a/packages/rs-dpp/src/data_trigger/get_data_triggers_factory.rs b/packages/rs-dpp/src/data_trigger/get_data_triggers_factory.rs index ce786a56568..fad6f09b4a3 100644 --- a/packages/rs-dpp/src/data_trigger/get_data_triggers_factory.rs +++ b/packages/rs-dpp/src/data_trigger/get_data_triggers_factory.rs @@ -153,21 +153,21 @@ fn data_triggers() -> Result, ProtocolError> { }, DataTrigger { data_contract_id: *withdrawals_contract_id, - document_type: withdrawals_contract::types::WITHDRAWAL.to_string(), + document_type: withdrawals_contract::document_types::WITHDRAWAL.to_string(), transition_action: Action::Create, data_trigger_kind: DataTriggerKind::DataTriggerReject, top_level_identity: None, }, DataTrigger { data_contract_id: *withdrawals_contract_id, - document_type: withdrawals_contract::types::WITHDRAWAL.to_string(), + document_type: withdrawals_contract::document_types::WITHDRAWAL.to_string(), transition_action: Action::Replace, data_trigger_kind: DataTriggerKind::DataTriggerReject, top_level_identity: None, }, DataTrigger { data_contract_id: *withdrawals_contract_id, - document_type: withdrawals_contract::types::WITHDRAWAL.to_string(), + document_type: withdrawals_contract::document_types::WITHDRAWAL.to_string(), transition_action: Action::Delete, data_trigger_kind: DataTriggerKind::DeleteWithdrawal, top_level_identity: Some(*withdrawals_owner_id), diff --git a/packages/rs-dpp/src/data_trigger/withdrawals_data_triggers/mod.rs b/packages/rs-dpp/src/data_trigger/withdrawals_data_triggers/mod.rs index c3ae216233f..6e55d8b05ec 100644 --- a/packages/rs-dpp/src/data_trigger/withdrawals_data_triggers/mod.rs +++ b/packages/rs-dpp/src/data_trigger/withdrawals_data_triggers/mod.rs @@ -32,7 +32,7 @@ where .state_repository .fetch_documents( &context.data_contract.id, - withdrawals_contract::types::WITHDRAWAL, + withdrawals_contract::document_types::WITHDRAWAL, json!({ "where" : [ ["$id", "==", dt_delete.base.id], @@ -62,8 +62,8 @@ where .as_u64() .ok_or_else(|| anyhow!("can't convert withdrawal status to u64"))? as u8; - if status != withdrawals_contract::Status::COMPLETE as u8 - || status != withdrawals_contract::Status::EXPIRED as u8 + if status != withdrawals_contract::WithdrawalStatus::COMPLETE as u8 + || status != withdrawals_contract::WithdrawalStatus::EXPIRED as u8 { let err = DataTriggerError::DataTriggerConditionError { data_contract_id: context.data_contract.id, @@ -138,7 +138,7 @@ mod tests { "coreFeePerByte": 1, "pooling": Pooling::Never, "outputScript": (0..23).collect::>(), - "status": withdrawals_contract::Status::BROADCASTED, + "status": withdrawals_contract::WithdrawalStatus::BROADCASTED, "transactionIndex": 1, "transactionSignHeight": 93, "transactionId": vec![1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], diff --git a/packages/rs-dpp/src/identity/state_transition/identity_credit_withdrawal_transition/apply_identity_credit_withdrawal_transition_factory.rs b/packages/rs-dpp/src/identity/state_transition/identity_credit_withdrawal_transition/apply_identity_credit_withdrawal_transition_factory.rs index 2a08bc681ae..92d87fb7992 100644 --- a/packages/rs-dpp/src/identity/state_transition/identity_credit_withdrawal_transition/apply_identity_credit_withdrawal_transition_factory.rs +++ b/packages/rs-dpp/src/identity/state_transition/identity_credit_withdrawal_transition/apply_identity_credit_withdrawal_transition_factory.rs @@ -58,7 +58,7 @@ where let latest_platform_block_header: BlockHeader = consensus::deserialize(&latest_platform_block_header_bytes)?; - let document_type = String::from(withdrawals_contract::types::WITHDRAWAL); + let document_type = String::from(withdrawals_contract::document_types::WITHDRAWAL); let document_created_at_millis: i64 = latest_platform_block_header.time as i64 * 1000i64; let document_data = json!({ @@ -66,7 +66,7 @@ where withdrawals_contract::property_names::CORE_FEE_PER_BYTE: state_transition.core_fee_per_byte, withdrawals_contract::property_names::POOLING: Pooling::Never, withdrawals_contract::property_names::OUTPUT_SCRIPT: state_transition.output_script.as_bytes(), - withdrawals_contract::property_names::STATUS: withdrawals_contract::Status::QUEUED, + withdrawals_contract::property_names::STATUS: withdrawals_contract::WithdrawalStatus::QUEUED, }); let mut document_id; @@ -85,7 +85,7 @@ where .state_repository .fetch_documents( withdrawals_contract::CONTRACT_ID.deref(), - withdrawals_contract::types::WITHDRAWAL, + withdrawals_contract::document_types::WITHDRAWAL, json!({ "where": [ ["$id", "==", document_id], diff --git a/packages/rs-dpp/src/schema/identity/stateTransition/identityCreditWithdrawal.json b/packages/rs-dpp/src/schema/identity/stateTransition/identityCreditWithdrawal.json index 848eca2db42..a9cd7792f46 100644 --- a/packages/rs-dpp/src/schema/identity/stateTransition/identityCreditWithdrawal.json +++ b/packages/rs-dpp/src/schema/identity/stateTransition/identityCreditWithdrawal.json @@ -50,7 +50,7 @@ "revision": { "type": "integer", "minimum": 0, - "description": "State transition revision" + "description": "Target identity revision" } }, "additionalProperties": false, diff --git a/packages/rs-dpp/src/tests/fixtures/get_documents_fixture.rs b/packages/rs-dpp/src/tests/fixtures/get_documents_fixture.rs index 1d82260a438..44a8105af35 100644 --- a/packages/rs-dpp/src/tests/fixtures/get_documents_fixture.rs +++ b/packages/rs-dpp/src/tests/fixtures/get_documents_fixture.rs @@ -121,7 +121,7 @@ pub fn get_withdrawal_document_fixture(data_contract: &DataContract, data: Value .create( data_contract.clone(), data_contract.owner_id, - withdrawals_contract::types::WITHDRAWAL.to_string(), + withdrawals_contract::document_types::WITHDRAWAL.to_string(), data, ) .unwrap() diff --git a/packages/rs-dpp/src/tests/identity/state_transition/identity_credit_withdrawal_transition/apply_identity_credit_withdrawal_transition_factory_spec.rs b/packages/rs-dpp/src/tests/identity/state_transition/identity_credit_withdrawal_transition/apply_identity_credit_withdrawal_transition_factory_spec.rs index 6ae627e3919..ecbef4c00f2 100644 --- a/packages/rs-dpp/src/tests/identity/state_transition/identity_credit_withdrawal_transition/apply_identity_credit_withdrawal_transition_factory_spec.rs +++ b/packages/rs-dpp/src/tests/identity/state_transition/identity_credit_withdrawal_transition/apply_identity_credit_withdrawal_transition_factory_spec.rs @@ -92,7 +92,7 @@ mod apply_identity_credit_withdrawal_transition_factory { "coreFeePerByte": 0, "pooling": Pooling::Never, "outputScript": [], - "status": withdrawals_contract::Status::QUEUED, + "status": withdrawals_contract::WithdrawalStatus::QUEUED, }); created_at_match && updated_at_match && document_data_match diff --git a/packages/rs-drive-abci/src/abci/handlers.rs b/packages/rs-drive-abci/src/abci/handlers.rs index 3947f1a76c4..f5bd982fe40 100644 --- a/packages/rs-drive-abci/src/abci/handlers.rs +++ b/packages/rs-drive-abci/src/abci/handlers.rs @@ -313,7 +313,7 @@ mod tests { "coreFeePerByte": 1, "pooling": Pooling::Never, "outputScript": (0..23).collect::>(), - "status": withdrawals_contract::Status::POOLED, + "status": withdrawals_contract::WithdrawalStatus::POOLED, "transactionIndex": 1, "transactionSignHeight": 93, "transactionId": tx_id, @@ -321,7 +321,7 @@ mod tests { ); let document_type = data_contract - .document_type_for_name(withdrawals_contract::types::WITHDRAWAL) + .document_type_for_name(withdrawals_contract::document_types::WITHDRAWAL) .expect("expected to get document type"); setup_document( diff --git a/packages/rs-drive-abci/src/identity_credit_withdrawal/mod.rs b/packages/rs-drive-abci/src/identity_credit_withdrawal/mod.rs index 4c21d7593af..9d3be4940d0 100644 --- a/packages/rs-drive-abci/src/identity_credit_withdrawal/mod.rs +++ b/packages/rs-drive-abci/src/identity_credit_withdrawal/mod.rs @@ -62,7 +62,7 @@ impl Platform { )?; let mut broadcasted_documents = self.drive.fetch_withdrawal_documents_by_status( - withdrawals_contract::Status::BROADCASTED.into(), + withdrawals_contract::WithdrawalStatus::BROADCASTED.into(), transaction, )?; @@ -107,14 +107,14 @@ impl Platform { > NUMBER_OF_BLOCKS_BEFORE_EXPIRED { let status = if core_transactions.contains(&transaction_id) { - withdrawals_contract::Status::COMPLETE + withdrawals_contract::WithdrawalStatus::COMPLETE } else { self.drive.add_insert_expired_index_operation( transaction_index, &mut drive_operations, ); - withdrawals_contract::Status::EXPIRED + withdrawals_contract::WithdrawalStatus::EXPIRED }; document.set_u8(withdrawals_contract::property_names::STATUS, status.into()); @@ -137,7 +137,7 @@ impl Platform { &contract_fetch_info.contract, contract_fetch_info .contract - .document_type_for_name(withdrawals_contract::types::WITHDRAWAL) + .document_type_for_name(withdrawals_contract::document_types::WITHDRAWAL) .map_err(|_| { Error::Execution(ExecutionError::CorruptedCodeExecution( "Can't fetch withdrawal data contract", @@ -255,7 +255,7 @@ impl Platform { &contract_fetch_info.contract, contract_fetch_info .contract - .document_type_for_name(withdrawals_contract::types::WITHDRAWAL) + .document_type_for_name(withdrawals_contract::document_types::WITHDRAWAL) .map_err(|_| { Error::Execution(ExecutionError::CorruptedCodeExecution( "could not get document type", @@ -293,7 +293,7 @@ impl Platform { ))?; let mut documents = self.drive.fetch_withdrawal_documents_by_status( - withdrawals_contract::Status::QUEUED.into(), + withdrawals_contract::WithdrawalStatus::QUEUED.into(), transaction, )?; @@ -324,7 +324,7 @@ impl Platform { document.set_u8( withdrawals_contract::property_names::STATUS, - withdrawals_contract::Status::POOLED as u8, + withdrawals_contract::WithdrawalStatus::POOLED as u8, ); document.set_i64( @@ -348,7 +348,7 @@ impl Platform { &contract_fetch_info.contract, contract_fetch_info .contract - .document_type_for_name(withdrawals_contract::types::WITHDRAWAL) + .document_type_for_name(withdrawals_contract::document_types::WITHDRAWAL) .map_err(|_| { Error::Execution(ExecutionError::CorruptedCodeExecution( "Can't fetch withdrawal data contract", @@ -599,7 +599,7 @@ mod tests { "coreFeePerByte": 1, "pooling": Pooling::Never, "outputScript": (0..23).collect::>(), - "status": withdrawals_contract::Status::BROADCASTED, + "status": withdrawals_contract::WithdrawalStatus::BROADCASTED, "transactionIndex": 1, "transactionSignHeight": 93, "transactionId": vec![1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], @@ -607,7 +607,7 @@ mod tests { ); let document_type = data_contract - .document_type_for_name(withdrawals_contract::types::WITHDRAWAL) + .document_type_for_name(withdrawals_contract::document_types::WITHDRAWAL) .expect("expected to get document type"); setup_document( @@ -625,7 +625,7 @@ mod tests { "coreFeePerByte": 1, "pooling": Pooling::Never, "outputScript": (0..23).collect::>(), - "status": withdrawals_contract::Status::BROADCASTED, + "status": withdrawals_contract::WithdrawalStatus::BROADCASTED, "transactionIndex": 2, "transactionSignHeight": 10, "transactionId": vec![3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], @@ -668,7 +668,7 @@ mod tests { let documents = platform .drive .fetch_withdrawal_documents_by_status( - withdrawals_contract::Status::EXPIRED.into(), + withdrawals_contract::WithdrawalStatus::EXPIRED.into(), Some(&transaction), ) .expect("to fetch documents by status"); @@ -682,7 +682,7 @@ mod tests { let documents = platform .drive .fetch_withdrawal_documents_by_status( - withdrawals_contract::Status::COMPLETE.into(), + withdrawals_contract::WithdrawalStatus::COMPLETE.into(), Some(&transaction), ) .expect("to fetch documents by status"); @@ -725,13 +725,13 @@ mod tests { "coreFeePerByte": 1, "pooling": Pooling::Never, "outputScript": (0..23).collect::>(), - "status": withdrawals_contract::Status::QUEUED, + "status": withdrawals_contract::WithdrawalStatus::QUEUED, "transactionIndex": 1, }), ); let document_type = data_contract - .document_type_for_name(withdrawals_contract::types::WITHDRAWAL) + .document_type_for_name(withdrawals_contract::document_types::WITHDRAWAL) .expect("expected to get document type"); setup_document( @@ -749,7 +749,7 @@ mod tests { "coreFeePerByte": 1, "pooling": Pooling::Never, "outputScript": (0..23).collect::>(), - "status": withdrawals_contract::Status::QUEUED, + "status": withdrawals_contract::WithdrawalStatus::QUEUED, "transactionIndex": 2, }), ); @@ -789,7 +789,7 @@ mod tests { let updated_documents = platform .drive .fetch_withdrawal_documents_by_status( - withdrawals_contract::Status::POOLED.into(), + withdrawals_contract::WithdrawalStatus::POOLED.into(), Some(&transaction), ) .expect("to fetch withdrawal documents"); @@ -911,13 +911,13 @@ mod tests { "coreFeePerByte": 1, "pooling": Pooling::Never, "outputScript": (0..23).collect::>(), - "status": withdrawals_contract::Status::POOLED, + "status": withdrawals_contract::WithdrawalStatus::POOLED, "transactionIndex": 1, }), ); let document_type = data_contract - .document_type_for_name(withdrawals_contract::types::WITHDRAWAL) + .document_type_for_name(withdrawals_contract::document_types::WITHDRAWAL) .expect("expected to get document type"); setup_document( @@ -935,7 +935,7 @@ mod tests { "coreFeePerByte": 1, "pooling": Pooling::Never, "outputScript": (0..23).collect::>(), - "status": withdrawals_contract::Status::POOLED, + "status": withdrawals_contract::WithdrawalStatus::POOLED, "transactionIndex": 2, }), ); diff --git a/packages/rs-drive/src/drive/identity/withdrawals/withdrawal_status.rs b/packages/rs-drive/src/drive/identity/withdrawals/withdrawal_status.rs index c8f671ad400..8ed2ef291b4 100644 --- a/packages/rs-drive/src/drive/identity/withdrawals/withdrawal_status.rs +++ b/packages/rs-drive/src/drive/identity/withdrawals/withdrawal_status.rs @@ -35,7 +35,7 @@ impl Drive { let document_type = contract_fetch_info .contract - .document_type_for_name(withdrawals_contract::types::WITHDRAWAL)?; + .document_type_for_name(withdrawals_contract::document_types::WITHDRAWAL)?; let mut where_clauses = BTreeMap::new(); @@ -128,7 +128,7 @@ impl Drive { let document_type = contract_fetch_info .contract - .document_type_for_name(withdrawals_contract::types::WITHDRAWAL)?; + .document_type_for_name(withdrawals_contract::document_types::WITHDRAWAL)?; let mut where_clauses = BTreeMap::new(); @@ -147,7 +147,7 @@ impl Drive { field: withdrawals_contract::property_names::STATUS.to_string(), operator: crate::query::WhereOperator::Equal, value: ciborium::Value::Integer( - (withdrawals_contract::Status::POOLED as u8).into(), + (withdrawals_contract::WithdrawalStatus::POOLED as u8).into(), ), }, ); @@ -227,7 +227,7 @@ mod tests { let documents = drive .fetch_withdrawal_documents_by_status( - withdrawals_contract::Status::QUEUED.into(), + withdrawals_contract::WithdrawalStatus::QUEUED.into(), Some(&transaction), ) .expect("to fetch documents by status"); @@ -241,13 +241,13 @@ mod tests { "coreFeePerByte": 1, "pooling": Pooling::Never, "outputScript": (0..23).collect::>(), - "status": withdrawals_contract::Status::QUEUED, + "status": withdrawals_contract::WithdrawalStatus::QUEUED, "transactionIndex": 1, }), ); let document_type = data_contract - .document_type_for_name(withdrawals_contract::types::WITHDRAWAL) + .document_type_for_name(withdrawals_contract::document_types::WITHDRAWAL) .expect("expected to get document type"); setup_document( @@ -265,7 +265,7 @@ mod tests { "coreFeePerByte": 1, "pooling": Pooling::Never, "outputScript": (0..23).collect::>(), - "status": withdrawals_contract::Status::POOLED, + "status": withdrawals_contract::WithdrawalStatus::POOLED, "transactionIndex": 2, }), ); @@ -280,7 +280,7 @@ mod tests { let documents = drive .fetch_withdrawal_documents_by_status( - withdrawals_contract::Status::QUEUED.into(), + withdrawals_contract::WithdrawalStatus::QUEUED.into(), Some(&transaction), ) .expect("to fetch documents by status"); @@ -289,7 +289,7 @@ mod tests { let documents = drive .fetch_withdrawal_documents_by_status( - withdrawals_contract::Status::POOLED.into(), + withdrawals_contract::WithdrawalStatus::POOLED.into(), Some(&transaction), ) .expect("to fetch documents by status"); @@ -323,14 +323,14 @@ mod tests { "coreFeePerByte": 1, "pooling": Pooling::Never, "outputScript": (0..23).collect::>(), - "status": withdrawals_contract::Status::POOLED, + "status": withdrawals_contract::WithdrawalStatus::POOLED, "transactionIndex": 1, "transactionId": (0..32).collect::>(), }), ); let document_type = data_contract - .document_type_for_name(withdrawals_contract::types::WITHDRAWAL) + .document_type_for_name(withdrawals_contract::document_types::WITHDRAWAL) .expect("expected to get document type"); setup_document( From 90afb2827e65436139454793d035b5efb5f066c1 Mon Sep 17 00:00:00 2001 From: Djavid Gabibiyan Date: Thu, 16 Feb 2023 13:17:33 +0500 Subject: [PATCH 139/170] chore(dpp): set max coreFeePerByte --- ...tity_credit_withdrawal_transition_basic.rs | 26 ++++++------------- ...credit_withdrawal_transition_basic_spec.rs | 17 +++++++++++- .../rs-dpp/src/util/is_fibonacci_number.rs | 4 +-- packages/rs-dpp/src/util/json_value/mod.rs | 24 +++++++++++++++++ .../schema/withdrawals-documents.json | 5 ++-- 5 files changed, 53 insertions(+), 23 deletions(-) diff --git a/packages/rs-dpp/src/identity/state_transition/identity_credit_withdrawal_transition/validation/basic/validate_identity_credit_withdrawal_transition_basic.rs b/packages/rs-dpp/src/identity/state_transition/identity_credit_withdrawal_transition/validation/basic/validate_identity_credit_withdrawal_transition_basic.rs index 696d8a7ab46..130192c7bf9 100644 --- a/packages/rs-dpp/src/identity/state_transition/identity_credit_withdrawal_transition/validation/basic/validate_identity_credit_withdrawal_transition_basic.rs +++ b/packages/rs-dpp/src/identity/state_transition/identity_credit_withdrawal_transition/validation/basic/validate_identity_credit_withdrawal_transition_basic.rs @@ -10,7 +10,10 @@ use crate::{ }, contracts::withdrawals_contract, identity::core_script::CoreScript, - util::{is_fibonacci_number::is_fibonacci_number, protocol_data::get_protocol_version}, + util::{ + is_fibonacci_number::is_fibonacci_number, json_value::JsonValueExt, + protocol_data::get_protocol_version, + }, validation::{JsonSchemaValidator, ValidationResult}, version::ProtocolVersionValidator, DashPlatformProtocolInitError, NonConsensusError, SerdeParsingError, @@ -73,25 +76,12 @@ impl IdentityCreditWithdrawalTransitionBasicValidator { } // validate core_fee is in fibonacci sequence - let core_fee = transition_json - .get(withdrawals_contract::property_names::CORE_FEE_PER_BYTE) - .ok_or_else(|| { - SerdeParsingError::new(format!( - "Expected credit withdrawal transition to have {} property", - withdrawals_contract::property_names::CORE_FEE_PER_BYTE - )) - })? - .as_u64() - .ok_or_else(|| { - SerdeParsingError::new(format!( - "Expected {} property to be a uint", - withdrawals_contract::property_names::CORE_FEE_PER_BYTE - )) - })?; + let core_fee_per_byte = + transition_json.get_u32(withdrawals_contract::property_names::CORE_FEE_PER_BYTE)?; - if !is_fibonacci_number(core_fee) { + if !is_fibonacci_number(core_fee_per_byte) { result.add_error(InvalidIdentityCreditWithdrawalTransitionCoreFeeError::new( - core_fee as u32, + core_fee_per_byte, )); } diff --git a/packages/rs-dpp/src/tests/identity/state_transition/identity_credit_withdrawal_transition/validation/basic/validate_identity_credit_withdrawal_transition_basic_spec.rs b/packages/rs-dpp/src/tests/identity/state_transition/identity_credit_withdrawal_transition/validation/basic/validate_identity_credit_withdrawal_transition_basic_spec.rs index e5bca9ca153..6a34d63b4f6 100644 --- a/packages/rs-dpp/src/tests/identity/state_transition/identity_credit_withdrawal_transition/validation/basic/validate_identity_credit_withdrawal_transition_basic_spec.rs +++ b/packages/rs-dpp/src/tests/identity/state_transition/identity_credit_withdrawal_transition/validation/basic/validate_identity_credit_withdrawal_transition_basic_spec.rs @@ -340,6 +340,21 @@ mod validate_identity_credit_withdrawal_transition_basic_factory { assert_eq!(error.keyword().unwrap(), "minimum"); } + #[tokio::test] + pub async fn should_be_not_more_than_u32_max() { + let (mut raw_state_transition, validator) = setup_test(); + + raw_state_transition.set_key_value("coreFeePerByte", u32::MAX as u64 + 1u64); + + let result = validator.validate(&raw_state_transition).await; + + assert!(result.is_err()); + assert_eq!( + result.err().unwrap().to_string(), + "unable convert 4294967296 to u32: out of range integral type conversion attempted" + ); + } + #[tokio::test] pub async fn should_be_in_a_fibonacci_sequence() { let (mut raw_state_transition, validator) = setup_test(); @@ -653,6 +668,6 @@ mod validate_identity_credit_withdrawal_transition_basic_factory { let result = validator.validate(&raw_state_transition).await.unwrap(); - assert_eq!(result.is_valid(), true); + assert!(result.is_valid()); } } diff --git a/packages/rs-dpp/src/util/is_fibonacci_number.rs b/packages/rs-dpp/src/util/is_fibonacci_number.rs index 6f8a554e15c..fab42b93875 100644 --- a/packages/rs-dpp/src/util/is_fibonacci_number.rs +++ b/packages/rs-dpp/src/util/is_fibonacci_number.rs @@ -1,7 +1,7 @@ -fn is_perfect_square(number: u64) -> bool { +fn is_perfect_square(number: u32) -> bool { (number as f64).sqrt().fract() == 0.0 } -pub fn is_fibonacci_number(number: u64) -> bool { +pub fn is_fibonacci_number(number: u32) -> bool { is_perfect_square(5 * number * number + 4) || is_perfect_square(5 * number * number - 4) } diff --git a/packages/rs-dpp/src/util/json_value/mod.rs b/packages/rs-dpp/src/util/json_value/mod.rs index 30f9e425dd7..1e9cb4783c0 100644 --- a/packages/rs-dpp/src/util/json_value/mod.rs +++ b/packages/rs-dpp/src/util/json_value/mod.rs @@ -44,6 +44,7 @@ pub trait JsonValueExt { fn get_string(&self, property_name: &str) -> Result<&str, anyhow::Error>; fn get_i64(&self, property_name: &str) -> Result; fn get_f64(&self, property_name: &str) -> Result; + fn get_u32(&self, property_name: &str) -> Result; fn get_u64(&self, property_name: &str) -> Result; fn get_bytes(&self, property_name: &str) -> Result, anyhow::Error>; /// returns the the mutable JsonValue from provided path. The path is dot-separated string. i.e `properties.id` @@ -171,6 +172,29 @@ impl JsonValueExt for JsonValue { ); } + fn get_u32(&self, property_name: &str) -> Result { + let property_value = self.get(property_name).ok_or_else(|| { + anyhow!( + "the property '{}' doesn't exist in '{:?}'", + property_name, + self + ) + })?; + + if let JsonValue::Number(s) = property_value { + return s + .as_u64() + .ok_or_else(|| anyhow!("unable convert {} to u64", s))? + .try_into() + .map_err(|e| anyhow!("unable convert {} to u32: {}", s, e)); + } + bail!( + "getting property '{}' failed: {:?} isn't a number", + property_name, + property_value + ); + } + fn get_u64(&self, property_name: &str) -> Result { let property_value = self.get(property_name).ok_or_else(|| { anyhow!( diff --git a/packages/withdrawals-contract/schema/withdrawals-documents.json b/packages/withdrawals-contract/schema/withdrawals-documents.json index 3319bb81983..3e7c3d83342 100644 --- a/packages/withdrawals-contract/schema/withdrawals-documents.json +++ b/packages/withdrawals-contract/schema/withdrawals-documents.json @@ -90,7 +90,8 @@ "coreFeePerByte": { "type": "integer", "description": "This is the fee that you are willing to spend for this transaction in Duffs/Byte", - "minimum": 1 + "minimum": 1, + "maximum": 4294967295 }, "pooling": { "type": "integer", @@ -128,4 +129,4 @@ "status" ] } -} +} \ No newline at end of file From b7ae68ebe52051b2fd3d1a0c0a7f096ce98fb411 Mon Sep 17 00:00:00 2001 From: Djavid Gabibiyan Date: Thu, 16 Feb 2023 13:49:39 +0500 Subject: [PATCH 140/170] chore(dpp): additional validation errors --- packages/rs-dpp/src/errors/codes.rs | 1 + .../consensus/abstract_consensus_error.rs | 7 ++++ ...dit_withdrawal_transition_pooling_error.rs | 25 +++++++++++++++ .../errors/consensus/basic/identity/mod.rs | 2 ++ ...tity_credit_withdrawal_transition_basic.rs | 14 ++++++-- .../identityCreditWithdrawal.json | 12 +++++-- ...credit_withdrawal_transition_basic_spec.rs | 32 +++++++++++++++---- packages/rs-dpp/src/util/json_value/mod.rs | 24 ++++++++++++++ .../schema/withdrawals-documents.json | 4 ++- 9 files changed, 109 insertions(+), 12 deletions(-) create mode 100644 packages/rs-dpp/src/errors/consensus/basic/identity/invalid_credit_withdrawal_transition_pooling_error.rs diff --git a/packages/rs-dpp/src/errors/codes.rs b/packages/rs-dpp/src/errors/codes.rs index 102ade95e93..76e358ee21a 100644 --- a/packages/rs-dpp/src/errors/codes.rs +++ b/packages/rs-dpp/src/errors/codes.rs @@ -44,6 +44,7 @@ impl ErrorWithCode for ConsensusError { Self::IdentityInsufficientBalanceError(_) => 4024, Self::InvalidIdentityCreditWithdrawalTransitionCoreFeeError(_) => 4025, Self::InvalidIdentityCreditWithdrawalTransitionOutputScriptError(_) => 4026, + Self::InvalidIdentityCreditWithdrawalTransitionPoolingError(_) => 4027, Self::StateError(e) => e.get_code(), Self::BasicError(e) => e.get_code(), diff --git a/packages/rs-dpp/src/errors/consensus/abstract_consensus_error.rs b/packages/rs-dpp/src/errors/consensus/abstract_consensus_error.rs index 83652786526..50a2cb0607a 100644 --- a/packages/rs-dpp/src/errors/consensus/abstract_consensus_error.rs +++ b/packages/rs-dpp/src/errors/consensus/abstract_consensus_error.rs @@ -25,6 +25,7 @@ use crate::errors::StateError; use super::basic::identity::{ IdentityInsufficientBalanceError, InvalidIdentityCreditWithdrawalTransitionCoreFeeError, InvalidIdentityCreditWithdrawalTransitionOutputScriptError, + InvalidIdentityCreditWithdrawalTransitionPoolingError, }; use super::fee::FeeError; use super::signature::SignatureError; @@ -87,6 +88,11 @@ pub enum ConsensusError { InvalidIdentityCreditWithdrawalTransitionOutputScriptError, ), + #[error("{0}")] + InvalidIdentityCreditWithdrawalTransitionPoolingError( + InvalidIdentityCreditWithdrawalTransitionPoolingError, + ), + #[error(transparent)] StateError(Box), @@ -163,6 +169,7 @@ impl ConsensusError { ConsensusError::IdentityInsufficientBalanceError(_) => 4024, ConsensusError::InvalidIdentityCreditWithdrawalTransitionCoreFeeError(_) => 4025, ConsensusError::InvalidIdentityCreditWithdrawalTransitionOutputScriptError(_) => 4026, + ConsensusError::InvalidIdentityCreditWithdrawalTransitionPoolingError(_) => 4027, ConsensusError::StateError(e) => e.get_code(), ConsensusError::BasicError(e) => e.get_code(), diff --git a/packages/rs-dpp/src/errors/consensus/basic/identity/invalid_credit_withdrawal_transition_pooling_error.rs b/packages/rs-dpp/src/errors/consensus/basic/identity/invalid_credit_withdrawal_transition_pooling_error.rs new file mode 100644 index 00000000000..7f7b88deb69 --- /dev/null +++ b/packages/rs-dpp/src/errors/consensus/basic/identity/invalid_credit_withdrawal_transition_pooling_error.rs @@ -0,0 +1,25 @@ +use thiserror::Error; + +use crate::consensus::ConsensusError; + +#[derive(Error, Debug, Clone, PartialEq, Eq)] +#[error("pooling {pooling:?} should be equal to 0")] +pub struct InvalidIdentityCreditWithdrawalTransitionPoolingError { + pooling: u8, +} + +impl InvalidIdentityCreditWithdrawalTransitionPoolingError { + pub fn new(pooling: u8) -> Self { + Self { pooling } + } + + pub fn pooling(&self) -> u8 { + self.pooling + } +} + +impl From for ConsensusError { + fn from(err: InvalidIdentityCreditWithdrawalTransitionPoolingError) -> Self { + Self::InvalidIdentityCreditWithdrawalTransitionPoolingError(err) + } +} diff --git a/packages/rs-dpp/src/errors/consensus/basic/identity/mod.rs b/packages/rs-dpp/src/errors/consensus/basic/identity/mod.rs index 80d65e7a8ac..2275fb0a624 100644 --- a/packages/rs-dpp/src/errors/consensus/basic/identity/mod.rs +++ b/packages/rs-dpp/src/errors/consensus/basic/identity/mod.rs @@ -10,6 +10,7 @@ pub use invalid_asset_lock_proof_transaction_height_error::*; pub use invalid_asset_lock_transaction_output_return_size::*; pub use invalid_credit_withdrawal_transition_core_fee_error::*; pub use invalid_credit_withdrawal_transition_output_script_error::*; +pub use invalid_credit_withdrawal_transition_pooling_error::*; pub use invalid_identity_asset_lock_transaction_error::*; pub use invalid_identity_asset_lock_transaction_output_error::*; pub use invalid_identity_public_key_data_error::*; @@ -30,6 +31,7 @@ mod invalid_asset_lock_proof_transaction_height_error; mod invalid_asset_lock_transaction_output_return_size; mod invalid_credit_withdrawal_transition_core_fee_error; mod invalid_credit_withdrawal_transition_output_script_error; +mod invalid_credit_withdrawal_transition_pooling_error; mod invalid_identity_asset_lock_transaction_error; mod invalid_identity_asset_lock_transaction_output_error; mod invalid_identity_public_key_data_error; diff --git a/packages/rs-dpp/src/identity/state_transition/identity_credit_withdrawal_transition/validation/basic/validate_identity_credit_withdrawal_transition_basic.rs b/packages/rs-dpp/src/identity/state_transition/identity_credit_withdrawal_transition/validation/basic/validate_identity_credit_withdrawal_transition_basic.rs index 130192c7bf9..0a418164d05 100644 --- a/packages/rs-dpp/src/identity/state_transition/identity_credit_withdrawal_transition/validation/basic/validate_identity_credit_withdrawal_transition_basic.rs +++ b/packages/rs-dpp/src/identity/state_transition/identity_credit_withdrawal_transition/validation/basic/validate_identity_credit_withdrawal_transition_basic.rs @@ -7,6 +7,7 @@ use crate::{ consensus::basic::identity::{ InvalidIdentityCreditWithdrawalTransitionCoreFeeError, InvalidIdentityCreditWithdrawalTransitionOutputScriptError, + InvalidIdentityCreditWithdrawalTransitionPoolingError, }, contracts::withdrawals_contract, identity::core_script::CoreScript, @@ -75,6 +76,17 @@ impl IdentityCreditWithdrawalTransitionBasicValidator { return Ok(result); } + // validate pooling is always equals to 0 + let pooling = transition_json.get_u8(withdrawals_contract::property_names::POOLING)?; + + if pooling > 0 { + result.add_error(InvalidIdentityCreditWithdrawalTransitionPoolingError::new( + pooling, + )); + + return Ok(result); + } + // validate core_fee is in fibonacci sequence let core_fee_per_byte = transition_json.get_u32(withdrawals_contract::property_names::CORE_FEE_PER_BYTE)?; @@ -83,9 +95,7 @@ impl IdentityCreditWithdrawalTransitionBasicValidator { result.add_error(InvalidIdentityCreditWithdrawalTransitionCoreFeeError::new( core_fee_per_byte, )); - } - if !result.is_valid() { return Ok(result); } diff --git a/packages/rs-dpp/src/schema/identity/stateTransition/identityCreditWithdrawal.json b/packages/rs-dpp/src/schema/identity/stateTransition/identityCreditWithdrawal.json index a9cd7792f46..c689d54afd9 100644 --- a/packages/rs-dpp/src/schema/identity/stateTransition/identityCreditWithdrawal.json +++ b/packages/rs-dpp/src/schema/identity/stateTransition/identityCreditWithdrawal.json @@ -19,16 +19,22 @@ }, "amount": { "type": "integer", + "description": "The amount to be withdrawn", "minimum": 1000 }, "coreFeePerByte": { "type": "integer", - "minimum": 1 + "description": "This is the fee that you are willing to spend for this transaction in Duffs/Byte", + "minimum": 1, + "maximum": 4294967295 }, "pooling": { "type": "integer", + "description": "This indicated the level at which Platform should try to pool this transaction", "enum": [ - 0 + 0, + 1, + 2 ] }, "outputScript": { @@ -66,4 +72,4 @@ "signaturePublicKeyId", "revision" ] -} +} \ No newline at end of file diff --git a/packages/rs-dpp/src/tests/identity/state_transition/identity_credit_withdrawal_transition/validation/basic/validate_identity_credit_withdrawal_transition_basic_spec.rs b/packages/rs-dpp/src/tests/identity/state_transition/identity_credit_withdrawal_transition/validation/basic/validate_identity_credit_withdrawal_transition_basic_spec.rs index 6a34d63b4f6..bb54f20d21e 100644 --- a/packages/rs-dpp/src/tests/identity/state_transition/identity_credit_withdrawal_transition/validation/basic/validate_identity_credit_withdrawal_transition_basic_spec.rs +++ b/packages/rs-dpp/src/tests/identity/state_transition/identity_credit_withdrawal_transition/validation/basic/validate_identity_credit_withdrawal_transition_basic_spec.rs @@ -346,13 +346,14 @@ mod validate_identity_credit_withdrawal_transition_basic_factory { raw_state_transition.set_key_value("coreFeePerByte", u32::MAX as u64 + 1u64); - let result = validator.validate(&raw_state_transition).await; + let result = validator.validate(&raw_state_transition).await.unwrap(); - assert!(result.is_err()); - assert_eq!( - result.err().unwrap().to_string(), - "unable convert 4294967296 to u32: out of range integral type conversion attempted" - ); + let errors = assert_consensus_errors!(result, ConsensusError::JsonSchemaError, 1); + + let error = errors.first().unwrap(); + + assert_eq!(error.instance_path().to_string(), "/coreFeePerByte"); + assert_eq!(error.keyword().unwrap(), "maximum"); } #[tokio::test] @@ -432,6 +433,25 @@ mod validate_identity_credit_withdrawal_transition_basic_factory { assert_eq!(error.instance_path().to_string(), "/pooling"); assert_eq!(error.keyword().unwrap(), "enum"); } + + #[tokio::test] + async fn should_constraint_variant_to_0() { + let (mut raw_state_transition, validator) = setup_test(); + + raw_state_transition.set_key_value("pooling", 2); + + let result = validator.validate(&raw_state_transition).await.unwrap(); + + let errors = assert_consensus_errors!( + result, + ConsensusError::InvalidIdentityCreditWithdrawalTransitionPoolingError, + 1 + ); + + let error = errors.first().unwrap(); + + assert_eq!(error.pooling(), 2); + } } mod output_script { diff --git a/packages/rs-dpp/src/util/json_value/mod.rs b/packages/rs-dpp/src/util/json_value/mod.rs index 1e9cb4783c0..09827a12031 100644 --- a/packages/rs-dpp/src/util/json_value/mod.rs +++ b/packages/rs-dpp/src/util/json_value/mod.rs @@ -44,6 +44,7 @@ pub trait JsonValueExt { fn get_string(&self, property_name: &str) -> Result<&str, anyhow::Error>; fn get_i64(&self, property_name: &str) -> Result; fn get_f64(&self, property_name: &str) -> Result; + fn get_u8(&self, property_name: &str) -> Result; fn get_u32(&self, property_name: &str) -> Result; fn get_u64(&self, property_name: &str) -> Result; fn get_bytes(&self, property_name: &str) -> Result, anyhow::Error>; @@ -172,6 +173,29 @@ impl JsonValueExt for JsonValue { ); } + fn get_u8(&self, property_name: &str) -> Result { + let property_value = self.get(property_name).ok_or_else(|| { + anyhow!( + "the property '{}' doesn't exist in '{:?}'", + property_name, + self + ) + })?; + + if let JsonValue::Number(s) = property_value { + return s + .as_u64() + .ok_or_else(|| anyhow!("unable convert {} to u64", s))? + .try_into() + .map_err(|e| anyhow!("unable convert {} to u8: {}", s, e)); + } + bail!( + "getting property '{}' failed: {:?} isn't a number", + property_name, + property_value + ); + } + fn get_u32(&self, property_name: &str) -> Result { let property_value = self.get(property_name).ok_or_else(|| { anyhow!( diff --git a/packages/withdrawals-contract/schema/withdrawals-documents.json b/packages/withdrawals-contract/schema/withdrawals-documents.json index 3e7c3d83342..3d1f5e06e1d 100644 --- a/packages/withdrawals-contract/schema/withdrawals-documents.json +++ b/packages/withdrawals-contract/schema/withdrawals-documents.json @@ -97,7 +97,9 @@ "type": "integer", "description": "This indicated the level at which Platform should try to pool this transaction", "enum": [ - 0 + 0, + 1, + 2 ] }, "outputScript": { From 8203c3ac97ae4bc7613f7f3aa0269e326b18d2d2 Mon Sep 17 00:00:00 2001 From: Djavid Gabibiyan Date: Thu, 16 Feb 2023 14:06:24 +0500 Subject: [PATCH 141/170] chore(wasm-dpp): fix for error --- ...dit_withdrawal_transition_pooling_error.rs | 29 +++++++++++++++++++ .../errors/consensus/basic/identity/mod.rs | 2 ++ .../wasm-dpp/src/errors/consensus_error.rs | 4 +++ 3 files changed, 35 insertions(+) create mode 100644 packages/wasm-dpp/src/errors/consensus/basic/identity/invalid_identity_credit_withdrawal_transition_pooling_error.rs diff --git a/packages/wasm-dpp/src/errors/consensus/basic/identity/invalid_identity_credit_withdrawal_transition_pooling_error.rs b/packages/wasm-dpp/src/errors/consensus/basic/identity/invalid_identity_credit_withdrawal_transition_pooling_error.rs new file mode 100644 index 00000000000..b7494a5b5de --- /dev/null +++ b/packages/wasm-dpp/src/errors/consensus/basic/identity/invalid_identity_credit_withdrawal_transition_pooling_error.rs @@ -0,0 +1,29 @@ +use dpp::consensus::basic::identity::InvalidIdentityCreditWithdrawalTransitionPoolingError; +use dpp::consensus::ConsensusError; +use wasm_bindgen::prelude::*; + +#[wasm_bindgen(js_name=InvalidIdentityCreditWithdrawalTransitionPoolingError)] +pub struct InvalidIdentityCreditWithdrawalTransitionPoolingErrorWasm { + inner: InvalidIdentityCreditWithdrawalTransitionPoolingError, +} + +impl From<&InvalidIdentityCreditWithdrawalTransitionPoolingError> + for InvalidIdentityCreditWithdrawalTransitionPoolingErrorWasm +{ + fn from(e: &InvalidIdentityCreditWithdrawalTransitionPoolingError) -> Self { + Self { inner: e.clone() } + } +} + +#[wasm_bindgen(js_class=InvalidIdentityCreditWithdrawalTransitionPoolingError)] +impl InvalidIdentityCreditWithdrawalTransitionPoolingErrorWasm { + #[wasm_bindgen(js_name=getPooling)] + pub fn pooling(&self) -> u8 { + self.inner.pooling() + } + + #[wasm_bindgen(js_name=getCode)] + pub fn code(&self) -> u32 { + ConsensusError::from(self.inner.clone()).code() + } +} diff --git a/packages/wasm-dpp/src/errors/consensus/basic/identity/mod.rs b/packages/wasm-dpp/src/errors/consensus/basic/identity/mod.rs index 2b25c35fcd4..598830189ef 100644 --- a/packages/wasm-dpp/src/errors/consensus/basic/identity/mod.rs +++ b/packages/wasm-dpp/src/errors/consensus/basic/identity/mod.rs @@ -12,6 +12,7 @@ mod invalid_identity_asset_lock_transaction_error; mod invalid_identity_asset_lock_transaction_output_error; mod invalid_identity_credit_withdrawal_transition_core_fee_error; mod invalid_identity_credit_withdrawal_transition_output_script_error; +mod invalid_identity_credit_withdrawal_transition_pooling_error; pub mod invalid_identity_key_signature_error; mod invalid_identity_public_key_data_error; mod invalid_identity_public_key_security_level_error; @@ -35,6 +36,7 @@ pub use invalid_identity_asset_lock_transaction_error::*; pub use invalid_identity_asset_lock_transaction_output_error::*; pub use invalid_identity_credit_withdrawal_transition_core_fee_error::*; pub use invalid_identity_credit_withdrawal_transition_output_script_error::*; +pub use invalid_identity_credit_withdrawal_transition_pooling_error::*; pub use invalid_identity_key_signature_error::*; pub use invalid_identity_public_key_data_error::*; pub use invalid_identity_public_key_security_level_error::*; diff --git a/packages/wasm-dpp/src/errors/consensus_error.rs b/packages/wasm-dpp/src/errors/consensus_error.rs index b61d74fe605..8290e25fc5e 100644 --- a/packages/wasm-dpp/src/errors/consensus_error.rs +++ b/packages/wasm-dpp/src/errors/consensus_error.rs @@ -17,6 +17,7 @@ use crate::errors::consensus::basic::identity::{ InvalidIdentityAssetLockTransactionOutputErrorWasm, InvalidIdentityCreditWithdrawalTransitionCoreFeeErrorWasm, InvalidIdentityCreditWithdrawalTransitionOutputScriptErrorWasm, + InvalidIdentityCreditWithdrawalTransitionPoolingErrorWasm, InvalidIdentityKeySignatureErrorWasm, InvalidIdentityPublicKeyDataErrorWasm, InvalidIdentityPublicKeySecurityLevelErrorWasm, InvalidInstantAssetLockProofErrorWasm, InvalidInstantAssetLockProofSignatureErrorWasm, MissingMasterPublicKeyErrorWasm, @@ -154,6 +155,9 @@ pub fn from_consensus_error_ref(e: &DPPConsensusError) -> JsValue { DPPConsensusError::InvalidIdentityCreditWithdrawalTransitionOutputScriptError(e) => { InvalidIdentityCreditWithdrawalTransitionOutputScriptErrorWasm::from(e).into() } + DPPConsensusError::InvalidIdentityCreditWithdrawalTransitionPoolingError(e) => { + InvalidIdentityCreditWithdrawalTransitionPoolingErrorWasm::from(e).into() + } DPPConsensusError::IdentityInsufficientBalanceError(e) => { IdentityInsufficientBalanceErrorWasm::from(e).into() } From 1397e8395a89b4330dd49c8cddfc128e2d4f7fb4 Mon Sep 17 00:00:00 2001 From: Djavid Gabibiyan Date: Thu, 16 Feb 2023 16:40:34 +0500 Subject: [PATCH 142/170] chore(rs-abci): do not pass execution context --- packages/rs-drive-abci/src/abci/handlers.rs | 11 +- .../src/identity_credit_withdrawal/mod.rs | 117 +++++++++++------- packages/rs-drive-abci/src/state/genesis.rs | 4 +- 3 files changed, 75 insertions(+), 57 deletions(-) diff --git a/packages/rs-drive-abci/src/abci/handlers.rs b/packages/rs-drive-abci/src/abci/handlers.rs index f5bd982fe40..9d5c82bfa96 100644 --- a/packages/rs-drive-abci/src/abci/handlers.rs +++ b/packages/rs-drive-abci/src/abci/handlers.rs @@ -144,22 +144,19 @@ impl TenderdashAbci for Platform { request.last_synced_core_height }; + self.block_execution_context + .replace(Some(block_execution_context)); + self.update_broadcasted_withdrawal_transaction_statuses( last_synced_core_height, - &block_execution_context, transaction, )?; let unsigned_withdrawal_transaction_bytes = self .fetch_and_prepare_unsigned_withdrawal_transactions( - &block_execution_context, request.validator_set_quorum_hash, transaction, )?; - - self.block_execution_context - .replace(Some(block_execution_context)); - let response = BlockBeginResponse { epoch_info, unsigned_withdrawal_transactions: unsigned_withdrawal_transaction_bytes, @@ -182,7 +179,7 @@ impl TenderdashAbci for Platform { ), ))?; - self.pool_withdrawals_into_transactions_queue(block_execution_context, transaction)?; + self.pool_withdrawals_into_transactions_queue(transaction)?; // Process fees let process_block_fees_outcome = self.process_block_fees( diff --git a/packages/rs-drive-abci/src/identity_credit_withdrawal/mod.rs b/packages/rs-drive-abci/src/identity_credit_withdrawal/mod.rs index 9d3be4940d0..93599d05dc1 100644 --- a/packages/rs-drive-abci/src/identity_credit_withdrawal/mod.rs +++ b/packages/rs-drive-abci/src/identity_credit_withdrawal/mod.rs @@ -26,7 +26,6 @@ use drive::{ use serde_json::Value as JsonValue; use crate::{ - block::BlockExecutionContext, error::{execution::ExecutionError, Error}, platform::Platform, }; @@ -39,9 +38,16 @@ impl Platform { pub fn update_broadcasted_withdrawal_transaction_statuses( &self, last_synced_core_height: u64, - block_execution_context: &BlockExecutionContext, transaction: TransactionArg, ) -> Result<(), Error> { + // Retrieve block execution context + let block_execution_context = self.block_execution_context.borrow(); + let block_execution_context = block_execution_context.as_ref().ok_or(Error::Execution( + ExecutionError::CorruptedCodeExecution( + "block execution context must be set in block begin handler", + ), + ))?; + let data_contract_id = &withdrawals_contract::CONTRACT_ID; let (_, maybe_data_contract) = self.drive.get_contract_with_fetch_info( @@ -155,10 +161,17 @@ impl Platform { /// Prepares a list of an unsigned withdrawal transaction bytes pub fn fetch_and_prepare_unsigned_withdrawal_transactions( &self, - block_execution_context: &BlockExecutionContext, validator_set_quorum_hash: [u8; 32], transaction: TransactionArg, ) -> Result>, Error> { + // Retrieve block execution context + let block_execution_context = self.block_execution_context.borrow(); + let block_execution_context = block_execution_context.as_ref().ok_or(Error::Execution( + ExecutionError::CorruptedCodeExecution( + "block execution context must be set in block begin handler", + ), + ))?; + let data_contract_id = withdrawals_contract::CONTRACT_ID.deref(); let (_, maybe_data_contract) = self.drive.get_contract_with_fetch_info( @@ -275,9 +288,16 @@ impl Platform { /// Pool withdrawal documents into transactions pub fn pool_withdrawals_into_transactions_queue( &self, - block_execution_context: &BlockExecutionContext, transaction: TransactionArg, ) -> Result<(), Error> { + // Retrieve block execution context + let block_execution_context = self.block_execution_context.borrow(); + let block_execution_context = block_execution_context.as_ref().ok_or(Error::Execution( + ExecutionError::CorruptedCodeExecution( + "block execution context must be set in block begin handler", + ), + ))?; + let data_contract_id = withdrawals_contract::CONTRACT_ID.deref(); let (_, maybe_data_contract) = self.drive.get_contract_with_fetch_info( @@ -515,6 +535,8 @@ mod tests { use crate::{block::BlockExecutionContext, execution::fee_pools::epoch::EpochInfo}; mod update_withdrawal_statuses { + use std::cell::RefCell; + use crate::block::BlockStateInfo; use crate::test::helpers::setup::setup_platform_with_initial_state_structure; use dpp::{ @@ -640,29 +662,27 @@ mod tests { Some(&transaction), ); + platform.block_execution_context = RefCell::new(Some(BlockExecutionContext { + block_info: BlockStateInfo { + block_height: 1, + block_time_ms: 1, + previous_block_time_ms: Some(1), + proposer_pro_tx_hash: [ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + ], + core_chain_locked_height: 96, + }, + epoch_info: EpochInfo { + current_epoch_index: 1, + previous_epoch_index: None, + is_epoch_change: false, + }, + hpmn_count: 100, + })); + platform - .update_broadcasted_withdrawal_transaction_statuses( - 95, - &BlockExecutionContext { - block_info: BlockStateInfo { - block_height: 1, - block_time_ms: 1, - previous_block_time_ms: Some(1), - proposer_pro_tx_hash: [ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - ], - core_chain_locked_height: 96, - }, - epoch_info: EpochInfo { - current_epoch_index: 1, - previous_epoch_index: None, - is_epoch_change: false, - }, - hpmn_count: 100, - }, - Some(&transaction), - ) + .update_broadcasted_withdrawal_transaction_statuses(95, Some(&transaction)) .expect("to update withdrawal statuses"); let documents = platform @@ -696,6 +716,8 @@ mod tests { } mod pool_withdrawals_into_transactions { + use std::cell::RefCell; + use dpp::data_contract::DriveContractExt; use dpp::identity::state_transition::identity_credit_withdrawal_transition::Pooling; use dpp::system_data_contracts::{load_system_data_contract, SystemDataContract}; @@ -709,7 +731,7 @@ mod tests { #[test] fn test_pooling() { - let platform = setup_platform_with_initial_state_structure(None); + let mut platform = setup_platform_with_initial_state_structure(None); let transaction = platform.drive.grove.start_transaction(); @@ -762,28 +784,27 @@ mod tests { Some(&transaction), ); + platform.block_execution_context = RefCell::new(Some(BlockExecutionContext { + block_info: BlockStateInfo { + block_height: 1, + block_time_ms: 1, + previous_block_time_ms: Some(1), + proposer_pro_tx_hash: [ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + ], + core_chain_locked_height: 96, + }, + epoch_info: EpochInfo { + current_epoch_index: 1, + previous_epoch_index: None, + is_epoch_change: false, + }, + hpmn_count: 100, + })); + platform - .pool_withdrawals_into_transactions_queue( - &BlockExecutionContext { - block_info: BlockStateInfo { - block_height: 1, - block_time_ms: 1, - previous_block_time_ms: Some(1), - proposer_pro_tx_hash: [ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - ], - core_chain_locked_height: 96, - }, - epoch_info: EpochInfo { - current_epoch_index: 1, - previous_epoch_index: None, - is_epoch_change: false, - }, - hpmn_count: 100, - }, - Some(&transaction), - ) + .pool_withdrawals_into_transactions_queue(Some(&transaction)) .expect("to pool withdrawal documents into transactions"); let updated_documents = platform diff --git a/packages/rs-drive-abci/src/state/genesis.rs b/packages/rs-drive-abci/src/state/genesis.rs index 903f673455e..da6b7387e81 100644 --- a/packages/rs-drive-abci/src/state/genesis.rs +++ b/packages/rs-drive-abci/src/state/genesis.rs @@ -319,8 +319,8 @@ mod tests { assert_eq!( root_hash, [ - 110, 6, 47, 121, 177, 99, 0, 7, 150, 5, 202, 92, 21, 81, 169, 64, 87, 150, 198, - 125, 110, 57, 207, 50, 251, 8, 138, 166, 106, 80, 232, 142, + 59, 16, 30, 145, 9, 47, 66, 85, 133, 88, 194, 109, 241, 15, 226, 214, 163, 196, + 146, 107, 122, 145, 111, 45, 251, 242, 250, 157, 153, 43, 219, 184 ] ) } From fb2a84449b4dd8398b972d9ef1c1e6954d71ed4d Mon Sep 17 00:00:00 2001 From: Djavid Gabibiyan Date: Thu, 16 Feb 2023 17:23:55 +0500 Subject: [PATCH 143/170] chore: wip --- .../src/identity_credit_withdrawal/mod.rs | 115 ++++++++++-------- 1 file changed, 66 insertions(+), 49 deletions(-) diff --git a/packages/rs-drive-abci/src/identity_credit_withdrawal/mod.rs b/packages/rs-drive-abci/src/identity_credit_withdrawal/mod.rs index 93599d05dc1..28de90f781f 100644 --- a/packages/rs-drive-abci/src/identity_credit_withdrawal/mod.rs +++ b/packages/rs-drive-abci/src/identity_credit_withdrawal/mod.rs @@ -67,7 +67,7 @@ impl Platform { block_execution_context.block_info.core_chain_locked_height, )?; - let mut broadcasted_documents = self.drive.fetch_withdrawal_documents_by_status( + let broadcasted_documents = self.drive.fetch_withdrawal_documents_by_status( withdrawals_contract::WithdrawalStatus::BROADCASTED.into(), transaction, )?; @@ -80,66 +80,83 @@ impl Platform { let mut drive_operations: Vec = vec![]; - for document in broadcasted_documents.iter_mut() { - let transaction_sign_height = document - .get_u64(withdrawals_contract::property_names::TRANSACTION_SIGN_HEIGHT) - .map_err(|_| { - Error::Execution(ExecutionError::CorruptedCodeExecution( - "Can't get transactionSignHeight from withdrawal document", - )) - })?; + // Collecting only documents that have been updated + let documents_to_update: Vec = broadcasted_documents + .into_iter() + .map(|mut document| { + let transaction_sign_height = document + .get_u64(withdrawals_contract::property_names::TRANSACTION_SIGN_HEIGHT) + .map_err(|_| { + Error::Execution(ExecutionError::CorruptedCodeExecution( + "Can't get transactionSignHeight from withdrawal document", + )) + })?; - let transaction_id_bytes = document - .get_bytes(withdrawals_contract::property_names::TRANSACTION_ID) - .map_err(|_| { - Error::Execution(ExecutionError::CorruptedCodeExecution( - "Can't get transactionId from withdrawal document", - )) - })?; + let transaction_id_bytes = document + .get_bytes(withdrawals_contract::property_names::TRANSACTION_ID) + .map_err(|_| { + Error::Execution(ExecutionError::CorruptedCodeExecution( + "Can't get transactionId from withdrawal document", + )) + })?; - let transaction_id = hex::encode(transaction_id_bytes); + let transaction_index = document + .get_u64(withdrawals_contract::property_names::TRANSACTION_INDEX) + .map_err(|_| { + Error::Execution(ExecutionError::CorruptedCodeExecution( + "Can't get transactionIdex from withdrawal document", + )) + })?; - let transaction_index = document - .get_u64(withdrawals_contract::property_names::TRANSACTION_INDEX) - .map_err(|_| { - Error::Execution(ExecutionError::CorruptedCodeExecution( - "Can't get transactionIdex from withdrawal document", - )) - })?; + let transaction_id = hex::encode(transaction_id_bytes); + + let current_and_signed_block_height_difference = + block_execution_context.block_info.core_chain_locked_height + - transaction_sign_height; - if core_transactions.contains(&transaction_id) - || block_execution_context.block_info.core_chain_locked_height - - transaction_sign_height + let withdrawal_status = if core_transactions.contains(&transaction_id) { + Some(withdrawals_contract::WithdrawalStatus::COMPLETE) + } else if current_and_signed_block_height_difference > NUMBER_OF_BLOCKS_BEFORE_EXPIRED - { - let status = if core_transactions.contains(&transaction_id) { - withdrawals_contract::WithdrawalStatus::COMPLETE + { + Some(withdrawals_contract::WithdrawalStatus::EXPIRED) } else { - self.drive.add_insert_expired_index_operation( - transaction_index, - &mut drive_operations, - ); - - withdrawals_contract::WithdrawalStatus::EXPIRED + None }; - document.set_u8(withdrawals_contract::property_names::STATUS, status.into()); + if let Some(status) = withdrawal_status { + document.set_u8(withdrawals_contract::property_names::STATUS, status.into()); - document.set_i64( - withdrawals_contract::property_names::UPDATED_AT, - block_info.time_ms.try_into().map_err(|_| { - Error::Execution(ExecutionError::CorruptedCodeExecution( - "Can't convert u64 block time to i64 updated_at", - )) - })?, - ); + document.set_i64( + withdrawals_contract::property_names::UPDATED_AT, + block_info.time_ms.try_into().map_err(|_| { + Error::Execution(ExecutionError::CorruptedCodeExecution( + "Can't convert u64 block time to i64 updated_at", + )) + })?, + ); - document.increment_revision().map_err(Error::Protocol)?; - } - } + document.increment_revision().map_err(Error::Protocol)?; + + if status == withdrawals_contract::WithdrawalStatus::EXPIRED { + self.drive.add_insert_expired_index_operation( + transaction_index, + &mut drive_operations, + ); + } + + Ok(Some(document)) + } else { + Ok(None) + } + }) + .collect::>, Error>>()? + .into_iter() + .flatten() + .collect(); self.drive.add_update_multiple_documents_operations( - &broadcasted_documents, + &documents_to_update, &contract_fetch_info.contract, contract_fetch_info .contract From ec7304809d8f540906881c376bd48526957ed318 Mon Sep 17 00:00:00 2001 From: Ivan Shumkov Date: Thu, 16 Feb 2023 20:43:32 +0800 Subject: [PATCH 144/170] refactor: minor changes --- packages/rs-drive-abci/src/abci/handlers.rs | 40 +++++++++------ .../src/identity_credit_withdrawal/mod.rs | 49 +++++++++---------- 2 files changed, 50 insertions(+), 39 deletions(-) diff --git a/packages/rs-drive-abci/src/abci/handlers.rs b/packages/rs-drive-abci/src/abci/handlers.rs index f5bd982fe40..74584f65bd5 100644 --- a/packages/rs-drive-abci/src/abci/handlers.rs +++ b/packages/rs-drive-abci/src/abci/handlers.rs @@ -115,16 +115,8 @@ impl TenderdashAbci for Platform { )))? }; - // Update versions - let proposed_app_version = request.proposed_app_version; - - self.drive.update_validator_proposed_app_version( - request.proposer_pro_tx_hash, - proposed_app_version, - transaction, - )?; - // Init block execution context + let block_info = BlockStateInfo::from_block_begin_request(&request); let epoch_info = EpochInfo::from_genesis_time_and_block_info(genesis_time_ms, &block_info)?; @@ -135,6 +127,29 @@ impl TenderdashAbci for Platform { hpmn_count: request.total_hpmns, }; + self.block_execution_context + .replace(Some(block_execution_context)); + + // Update protocol version signals + + let proposed_app_version = request.proposed_app_version; + + self.drive.update_validator_proposed_app_version( + request.proposer_pro_tx_hash, + proposed_app_version, + transaction, + )?; + + // Credit withdrawals + + // TODO: Find a way to do not duplicate this 5 lines everywhere + let block_execution_context = self.block_execution_context.borrow(); + let block_execution_context = block_execution_context.as_ref().ok_or(Error::Execution( + ExecutionError::CorruptedCodeExecution( + "block execution context must be set in block begin handler", + ), + ))?; + // If last synced Core block height is not set instead of scanning // number of blocks for asset unlock transactions scan only one // on Core chain locked height by setting last_synced_core_height to the same value @@ -146,20 +161,17 @@ impl TenderdashAbci for Platform { self.update_broadcasted_withdrawal_transaction_statuses( last_synced_core_height, - &block_execution_context, + block_execution_context, transaction, )?; let unsigned_withdrawal_transaction_bytes = self .fetch_and_prepare_unsigned_withdrawal_transactions( - &block_execution_context, + block_execution_context, request.validator_set_quorum_hash, transaction, )?; - self.block_execution_context - .replace(Some(block_execution_context)); - let response = BlockBeginResponse { epoch_info, unsigned_withdrawal_transactions: unsigned_withdrawal_transaction_bytes, diff --git a/packages/rs-drive-abci/src/identity_credit_withdrawal/mod.rs b/packages/rs-drive-abci/src/identity_credit_withdrawal/mod.rs index 9d3be4940d0..c59045d633b 100644 --- a/packages/rs-drive-abci/src/identity_credit_withdrawal/mod.rs +++ b/packages/rs-drive-abci/src/identity_credit_withdrawal/mod.rs @@ -44,27 +44,26 @@ impl Platform { ) -> Result<(), Error> { let data_contract_id = &withdrawals_contract::CONTRACT_ID; - let (_, maybe_data_contract) = self.drive.get_contract_with_fetch_info( + let (_, Some(contract_fetch_info)) = self.drive.get_contract_with_fetch_info( data_contract_id.to_buffer(), - Some(&Epoch::new( - block_execution_context.epoch_info.current_epoch_index, - )), + None, transaction, - )?; - - let contract_fetch_info = maybe_data_contract.ok_or(Error::Execution( - ExecutionError::CorruptedCodeExecution("can't fetch withdrawal data contract"), - ))?; + )? else { + return Err(Error::Execution( + ExecutionError::CorruptedCodeExecution("can't fetch withdrawal data contract"), + )); + }; let core_transactions = self.fetch_core_block_transactions( last_synced_core_height, block_execution_context.block_info.core_chain_locked_height, )?; - let mut broadcasted_documents = self.drive.fetch_withdrawal_documents_by_status( - withdrawals_contract::WithdrawalStatus::BROADCASTED.into(), - transaction, - )?; + let mut broadcasted_withdrawal_documents = + self.drive.fetch_withdrawal_documents_by_status( + withdrawals_contract::WithdrawalStatus::BROADCASTED.into(), + transaction, + )?; let block_info = BlockInfo { time_ms: block_execution_context.block_info.block_time_ms, @@ -74,7 +73,7 @@ impl Platform { let mut drive_operations: Vec = vec![]; - for document in broadcasted_documents.iter_mut() { + for document in broadcasted_withdrawal_documents.iter_mut() { let transaction_sign_height = document .get_u64(withdrawals_contract::property_names::TRANSACTION_SIGN_HEIGHT) .map_err(|_| { @@ -83,30 +82,30 @@ impl Platform { )) })?; - let transaction_id_bytes = document - .get_bytes(withdrawals_contract::property_names::TRANSACTION_ID) + let transaction_index = document + .get_u64(withdrawals_contract::property_names::TRANSACTION_INDEX) .map_err(|_| { Error::Execution(ExecutionError::CorruptedCodeExecution( - "Can't get transactionId from withdrawal document", + "Can't get transactionIndex from withdrawal document", )) })?; - let transaction_id = hex::encode(transaction_id_bytes); - - let transaction_index = document - .get_u64(withdrawals_contract::property_names::TRANSACTION_INDEX) + let transaction_id_bytes = document + .get_bytes(withdrawals_contract::property_names::TRANSACTION_ID) .map_err(|_| { Error::Execution(ExecutionError::CorruptedCodeExecution( - "Can't get transactionIdex from withdrawal document", + "Can't get transactionId from withdrawal document", )) })?; - if core_transactions.contains(&transaction_id) + let transaction_id_hex = hex::encode(transaction_id_bytes); + + if core_transactions.contains(&transaction_id_hex) || block_execution_context.block_info.core_chain_locked_height - transaction_sign_height > NUMBER_OF_BLOCKS_BEFORE_EXPIRED { - let status = if core_transactions.contains(&transaction_id) { + let status = if core_transactions.contains(&transaction_id_hex) { withdrawals_contract::WithdrawalStatus::COMPLETE } else { self.drive.add_insert_expired_index_operation( @@ -133,7 +132,7 @@ impl Platform { } self.drive.add_update_multiple_documents_operations( - &broadcasted_documents, + &broadcasted_withdrawal_documents, &contract_fetch_info.contract, contract_fetch_info .contract From ec765d40efa89b000b6c6c51a68eb0b106f140ec Mon Sep 17 00:00:00 2001 From: Ivan Shumkov Date: Thu, 16 Feb 2023 20:58:42 +0800 Subject: [PATCH 145/170] refactor: update_broadcasted_withdrawal_transaction_statuses --- .../src/identity_credit_withdrawal/mod.rs | 58 +++++++++---------- 1 file changed, 27 insertions(+), 31 deletions(-) diff --git a/packages/rs-drive-abci/src/identity_credit_withdrawal/mod.rs b/packages/rs-drive-abci/src/identity_credit_withdrawal/mod.rs index 558846ed6f2..6175b8f1379 100644 --- a/packages/rs-drive-abci/src/identity_credit_withdrawal/mod.rs +++ b/packages/rs-drive-abci/src/identity_credit_withdrawal/mod.rs @@ -65,7 +65,7 @@ impl Platform { block_execution_context.block_info.core_chain_locked_height, )?; - let broadcasted_documents = self.drive.fetch_withdrawal_documents_by_status( + let broadcasted_withdrawal_documents = self.drive.fetch_withdrawal_documents_by_status( withdrawals_contract::WithdrawalStatus::BROADCASTED.into(), transaction, )?; @@ -79,7 +79,7 @@ impl Platform { let mut drive_operations: Vec = vec![]; // Collecting only documents that have been updated - let documents_to_update: Vec = broadcasted_documents + let documents_to_update: Vec = broadcasted_withdrawal_documents .into_iter() .map(|mut document| { let transaction_sign_height = document @@ -108,45 +108,41 @@ impl Platform { let transaction_id = hex::encode(transaction_id_bytes); - let current_and_signed_block_height_difference = + let block_height_difference = block_execution_context.block_info.core_chain_locked_height - transaction_sign_height; - let withdrawal_status = if core_transactions.contains(&transaction_id) { - Some(withdrawals_contract::WithdrawalStatus::COMPLETE) - } else if current_and_signed_block_height_difference - > NUMBER_OF_BLOCKS_BEFORE_EXPIRED - { - Some(withdrawals_contract::WithdrawalStatus::EXPIRED) + let status; + + if core_transactions.contains(&transaction_id) { + status = withdrawals_contract::WithdrawalStatus::COMPLETE; + } else if block_height_difference > NUMBER_OF_BLOCKS_BEFORE_EXPIRED { + status = withdrawals_contract::WithdrawalStatus::EXPIRED; } else { - None + return Ok(None); }; - if let Some(status) = withdrawal_status { - document.set_u8(withdrawals_contract::property_names::STATUS, status.into()); - - document.set_i64( - withdrawals_contract::property_names::UPDATED_AT, - block_info.time_ms.try_into().map_err(|_| { - Error::Execution(ExecutionError::CorruptedCodeExecution( - "Can't convert u64 block time to i64 updated_at", - )) - })?, - ); + document.set_u8(withdrawals_contract::property_names::STATUS, status.into()); - document.increment_revision().map_err(Error::Protocol)?; + document.set_i64( + withdrawals_contract::property_names::UPDATED_AT, + block_info.time_ms.try_into().map_err(|_| { + Error::Execution(ExecutionError::CorruptedCodeExecution( + "Can't convert u64 block time to i64 updated_at", + )) + })?, + ); - if status == withdrawals_contract::WithdrawalStatus::EXPIRED { - self.drive.add_insert_expired_index_operation( - transaction_index, - &mut drive_operations, - ); - } + document.increment_revision().map_err(Error::Protocol)?; - Ok(Some(document)) - } else { - Ok(None) + if status == withdrawals_contract::WithdrawalStatus::EXPIRED { + self.drive.add_insert_expired_index_operation( + transaction_index, + &mut drive_operations, + ); } + + Ok(Some(document)) }) .collect::>, Error>>()? .into_iter() From 3c9ef30d8f70aead198f1ab043ec37ce5f28dad7 Mon Sep 17 00:00:00 2001 From: Ivan Shumkov Date: Thu, 16 Feb 2023 21:18:05 +0800 Subject: [PATCH 146/170] refactor: fetch_and_prepare_unsigned_withdrawal_transactions --- .../src/identity_credit_withdrawal/mod.rs | 137 +++++++++--------- .../identity/withdrawals/withdrawal_status.rs | 7 +- 2 files changed, 72 insertions(+), 72 deletions(-) diff --git a/packages/rs-drive-abci/src/identity_credit_withdrawal/mod.rs b/packages/rs-drive-abci/src/identity_credit_withdrawal/mod.rs index 6175b8f1379..04384370dd4 100644 --- a/packages/rs-drive-abci/src/identity_credit_withdrawal/mod.rs +++ b/packages/rs-drive-abci/src/identity_credit_withdrawal/mod.rs @@ -185,17 +185,15 @@ impl Platform { let data_contract_id = withdrawals_contract::CONTRACT_ID.deref(); - let (_, maybe_data_contract) = self.drive.get_contract_with_fetch_info( + let (_, Some(contract_fetch_info)) = self.drive.get_contract_with_fetch_info( data_contract_id.to_buffer(), - Some(&Epoch::new( - block_execution_context.epoch_info.current_epoch_index, - )), + None, transaction, - )?; - - let contract_fetch_info = maybe_data_contract.ok_or(Error::Execution( - ExecutionError::CorruptedCodeExecution("Can't fetch withdrawal data contract"), - ))?; + )? else { + return Err(Error::Execution( + ExecutionError::CorruptedCodeExecution("can't fetch withdrawal data contract"), + )); + }; let block_info = BlockInfo { time_ms: block_execution_context.block_info.block_time_ms, @@ -206,76 +204,77 @@ impl Platform { let mut drive_operations: Vec = vec![]; // Get 16 latest withdrawal transactions from the queue - let withdrawal_transactions = self.drive.dequeue_withdrawal_transactions( + let untied_withdrawal_transactions = self.drive.dequeue_withdrawal_transactions( WITHDRAWAL_TRANSACTIONS_QUERY_LIMIT, transaction, &mut drive_operations, )?; - // Appending request_height and quorum_hash to withdrwal transaction + if untied_withdrawal_transactions.is_empty() { + return Ok(Vec::new()); + } + + // Appending request_height and quorum_hash to withdrawal transaction // and pass it to JS Drive for singing and broadcasting - let transactions_and_documents = withdrawal_transactions - .into_iter() - .map(|(_, bytes)| { - let request_info = AssetUnlockRequestInfo { - request_height: block_execution_context.block_info.core_chain_locked_height - as u32, - quorum_hash: QuorumHash::hash(&validator_set_quorum_hash), - }; + let (unsigned_withdrawal_transactions, documents_to_update): (Vec<_>, Vec<_>) = + untied_withdrawal_transactions + .into_iter() + .map(|(_, untied_transaction_bytes)| { + let request_info = AssetUnlockRequestInfo { + request_height: block_execution_context.block_info.core_chain_locked_height + as u32, + quorum_hash: QuorumHash::hash(&validator_set_quorum_hash), + }; + + let mut unsigned_transaction_bytes = vec![]; + + request_info + .consensus_append_to_base_encode( + untied_transaction_bytes.clone(), + &mut unsigned_transaction_bytes, + ) + .map_err(|_| { + Error::Execution(ExecutionError::CorruptedCodeExecution( + "could not add additional request info to asset unlock transaction", + )) + })?; + + let original_transaction_id = hash::hash(untied_transaction_bytes); + let update_transaction_id = hash::hash(unsigned_transaction_bytes.clone()); + + let mut document = self.drive.find_withdrawal_document_by_transaction_id( + &original_transaction_id, + transaction, + )?; + + document.set_bytes( + withdrawals_contract::property_names::TRANSACTION_ID, + update_transaction_id, + ); - let mut bytes_buffer = vec![]; + document.set_i64( + withdrawals_contract::property_names::UPDATED_AT, + block_info.time_ms.try_into().map_err(|_| { + Error::Execution(ExecutionError::CorruptedCodeExecution( + "Can't convert u64 block time to i64 updated_at", + )) + })?, + ); - request_info - .consensus_append_to_base_encode(bytes.clone(), &mut bytes_buffer) - .map_err(|_| { + document.increment_revision().map_err(|_| { Error::Execution(ExecutionError::CorruptedCodeExecution( - "could not add aditional request info to asset unlock transaction", + "Could not increment document revision", )) })?; - let original_transaction_id = hash::hash(bytes); - let update_transaction_id = hash::hash(bytes_buffer.clone()); - - let mut document = self - .drive - .find_document_by_transaction_id(&original_transaction_id, transaction)?; - - document.set_bytes( - withdrawals_contract::property_names::TRANSACTION_ID, - update_transaction_id, - ); - - document.set_i64( - withdrawals_contract::property_names::UPDATED_AT, - block_info.time_ms.try_into().map_err(|_| { - Error::Execution(ExecutionError::CorruptedCodeExecution( - "Can't convert u64 block time to i64 updated_at", - )) - })?, - ); - - document.increment_revision().map_err(|_| { - Error::Execution(ExecutionError::CorruptedCodeExecution( - "Could not increment document revision", - )) - })?; - - Ok((bytes_buffer, document)) - }) - .collect::, DocumentStub)>, Error>>()?; - - let withdrawals = transactions_and_documents - .iter() - .map(|(bytes, _)| bytes.clone()) - .collect(); - - let documents: Vec = transactions_and_documents - .into_iter() - .map(|(_, document)| document) - .collect(); + Ok((unsigned_transaction_bytes, document)) + }) + .collect::, DocumentStub)>, Error>>()? + .into_iter() + .unzip(); self.drive.add_update_multiple_documents_operations( - &documents, + &documents_to_update, &contract_fetch_info.contract, contract_fetch_info .contract @@ -288,12 +287,10 @@ impl Platform { &mut drive_operations, ); - if !drive_operations.is_empty() { - self.drive - .apply_drive_operations(drive_operations, true, &block_info, transaction)?; - } + self.drive + .apply_drive_operations(drive_operations, true, &block_info, transaction)?; - Ok(withdrawals) + Ok(unsigned_withdrawal_transactions) } /// Pool withdrawal documents into transactions diff --git a/packages/rs-drive/src/drive/identity/withdrawals/withdrawal_status.rs b/packages/rs-drive/src/drive/identity/withdrawals/withdrawal_status.rs index 8ed2ef291b4..da831728747 100644 --- a/packages/rs-drive/src/drive/identity/withdrawals/withdrawal_status.rs +++ b/packages/rs-drive/src/drive/identity/withdrawals/withdrawal_status.rs @@ -110,7 +110,7 @@ impl Drive { } /// Find one document by it's transactionId field - pub fn find_document_by_transaction_id( + pub fn find_withdrawal_document_by_transaction_id( &self, original_transaction_id: &[u8], transaction: TransactionArg, @@ -342,7 +342,10 @@ mod tests { ); let found_document = drive - .find_document_by_transaction_id(&(0..32).collect::>(), Some(&transaction)) + .find_withdrawal_document_by_transaction_id( + &(0..32).collect::>(), + Some(&transaction), + ) .expect("to find document by it's transaction id"); assert_eq!(found_document.id.to_vec(), document.id.to_vec()); From 56527ca047c70bf10d921e0ce1b9f8f489635c70 Mon Sep 17 00:00:00 2001 From: Ivan Shumkov Date: Thu, 16 Feb 2023 21:36:05 +0800 Subject: [PATCH 147/170] refactor: more stuff --- packages/rs-drive-abci/src/abci/handlers.rs | 4 +- .../src/identity_credit_withdrawal/mod.rs | 83 ++++++++++--------- .../drive/batch/drive_op_batch/withdrawals.rs | 6 +- .../src/drive/identity/withdrawals/insert.rs | 4 +- .../src/drive/identity/withdrawals/paths.rs | 2 +- .../src/drive/identity/withdrawals/queue.rs | 6 +- 6 files changed, 55 insertions(+), 50 deletions(-) diff --git a/packages/rs-drive-abci/src/abci/handlers.rs b/packages/rs-drive-abci/src/abci/handlers.rs index 6d36637a670..91c1248b1a0 100644 --- a/packages/rs-drive-abci/src/abci/handlers.rs +++ b/packages/rs-drive-abci/src/abci/handlers.rs @@ -256,7 +256,7 @@ mod tests { use dpp::util::hash; use drive::common::helpers::identities::create_test_masternode_identities; use drive::drive::block_info::BlockInfo; - use drive::drive::identity::withdrawals::paths::WithdrawalTransaction; + use drive::drive::identity::withdrawals::paths::WithdrawalTransactionIdAndBytes; use drive::fee::epoch::CreditsPerEpoch; use drive::fee_pools::epochs::Epoch; use drive::rpc::core::MockCoreRPCLike; @@ -297,7 +297,7 @@ mod tests { .expect("to load system data contract"); // Init withdrawal requests - let withdrawals: Vec = (0..16) + let withdrawals: Vec = (0..16) .map(|index: u64| (index.to_be_bytes().to_vec(), vec![index as u8; 32])) .collect(); diff --git a/packages/rs-drive-abci/src/identity_credit_withdrawal/mod.rs b/packages/rs-drive-abci/src/identity_credit_withdrawal/mod.rs index 04384370dd4..62eac9c8f07 100644 --- a/packages/rs-drive-abci/src/identity_credit_withdrawal/mod.rs +++ b/packages/rs-drive-abci/src/identity_credit_withdrawal/mod.rs @@ -18,7 +18,7 @@ use drive::dpp::util::hash; use drive::{ drive::{ batch::DriveOperationType, block_info::BlockInfo, - identity::withdrawals::paths::WithdrawalTransaction, + identity::withdrawals::paths::WithdrawalTransactionIdAndBytes, }, fee_pools::epochs::Epoch, query::TransactionArg, @@ -48,6 +48,12 @@ impl Platform { ), ))?; + let block_info = BlockInfo { + time_ms: block_execution_context.block_info.block_time_ms, + height: block_execution_context.block_info.block_height, + epoch: Epoch::new(block_execution_context.epoch_info.current_epoch_index), + }; + let data_contract_id = &withdrawals_contract::CONTRACT_ID; let (_, Some(contract_fetch_info)) = self.drive.get_contract_with_fetch_info( @@ -70,12 +76,6 @@ impl Platform { transaction, )?; - let block_info = BlockInfo { - time_ms: block_execution_context.block_info.block_time_ms, - height: block_execution_context.block_info.block_height, - epoch: Epoch::new(block_execution_context.epoch_info.current_epoch_index), - }; - let mut drive_operations: Vec = vec![]; // Collecting only documents that have been updated @@ -183,6 +183,12 @@ impl Platform { ), ))?; + let block_info = BlockInfo { + time_ms: block_execution_context.block_info.block_time_ms, + height: block_execution_context.block_info.block_height, + epoch: Epoch::new(block_execution_context.epoch_info.current_epoch_index), + }; + let data_contract_id = withdrawals_contract::CONTRACT_ID.deref(); let (_, Some(contract_fetch_info)) = self.drive.get_contract_with_fetch_info( @@ -195,12 +201,6 @@ impl Platform { )); }; - let block_info = BlockInfo { - time_ms: block_execution_context.block_info.block_time_ms, - height: block_execution_context.block_info.block_height, - epoch: Epoch::new(block_execution_context.epoch_info.current_epoch_index), - }; - let mut drive_operations: Vec = vec![]; // Get 16 latest withdrawal transactions from the queue @@ -306,25 +306,33 @@ impl Platform { ), ))?; + let block_info = BlockInfo { + time_ms: block_execution_context.block_info.block_time_ms, + height: block_execution_context.block_info.block_height, + epoch: Epoch::new(block_execution_context.epoch_info.current_epoch_index), + }; + let data_contract_id = withdrawals_contract::CONTRACT_ID.deref(); - let (_, maybe_data_contract) = self.drive.get_contract_with_fetch_info( + let (_, Some(contract_fetch_info)) = self.drive.get_contract_with_fetch_info( data_contract_id.to_buffer(), - Some(&Epoch::new( - block_execution_context.epoch_info.current_epoch_index, - )), + None, transaction, - )?; - - let contract_fetch_info = maybe_data_contract.ok_or(Error::Execution( - ExecutionError::CorruptedCodeExecution("Can't fetch withdrawal data contract"), - ))?; + )? else { + return Err(Error::Execution( + ExecutionError::CorruptedCodeExecution("can't fetch withdrawal data contract"), + )); + }; let mut documents = self.drive.fetch_withdrawal_documents_by_status( withdrawals_contract::WithdrawalStatus::QUEUED.into(), transaction, )?; + if documents.is_empty() { + return Ok(()); + } + let mut drive_operations = vec![]; let withdrawal_transactions = self.build_withdrawal_transactions_from_documents( @@ -333,17 +341,14 @@ impl Platform { transaction, )?; - let block_info = BlockInfo { - time_ms: block_execution_context.block_info.block_time_ms, - height: block_execution_context.block_info.block_height, - epoch: Epoch::new(block_execution_context.epoch_info.current_epoch_index), - }; - for document in documents.iter_mut() { let document_id = Identifier::from_bytes(&document.id)?; - let transaction_id = - hash::hash(withdrawal_transactions.get(&document_id).unwrap().1.clone()); + let Some((_, transaction_bytes)) = withdrawal_transactions.get(&document_id) else { + return Err(Error::Execution(ExecutionError::CorruptedCodeExecution("transactions must contain a transaction"))) + }; + + let transaction_id = hash::hash(transaction_bytes); document.set_bytes( withdrawals_contract::property_names::TRANSACTION_ID, @@ -385,7 +390,7 @@ impl Platform { &mut drive_operations, ); - let withdrawal_transactions: Vec = withdrawal_transactions + let withdrawal_transactions: Vec = withdrawal_transactions .values() .into_iter() .cloned() @@ -396,10 +401,8 @@ impl Platform { &mut drive_operations, ); - if !drive_operations.is_empty() { - self.drive - .apply_drive_operations(drive_operations, true, &block_info, transaction)?; - } + self.drive + .apply_drive_operations(drive_operations, true, &block_info, transaction)?; Ok(()) } @@ -451,8 +454,8 @@ impl Platform { documents: &[DocumentStub], drive_operation_types: &mut Vec, transaction: TransactionArg, - ) -> Result, Error> { - let mut withdrawals: HashMap = HashMap::new(); + ) -> Result, Error> { + let mut withdrawals: HashMap = HashMap::new(); let latest_withdrawal_index = self .drive @@ -916,7 +919,7 @@ mod tests { identity::state_transition::identity_credit_withdrawal_transition::Pooling, }; use drive::drive::block_info::BlockInfo; - use drive::drive::identity::withdrawals::paths::WithdrawalTransaction; + use drive::drive::identity::withdrawals::paths::WithdrawalTransactionIdAndBytes; use drive::tests::helpers::setup::setup_system_data_contract; use itertools::Itertools; @@ -1012,7 +1015,7 @@ mod tests { .values() .cloned() .sorted() - .collect::>(), + .collect::>(), vec![ ( vec![0, 0, 0, 0, 0, 0, 0, 0], @@ -1033,7 +1036,7 @@ mod tests { ] .into_iter() .sorted() - .collect::>(), + .collect::>(), ); } } diff --git a/packages/rs-drive/src/drive/batch/drive_op_batch/withdrawals.rs b/packages/rs-drive/src/drive/batch/drive_op_batch/withdrawals.rs index 0249a2b9340..f5187e61ce7 100644 --- a/packages/rs-drive/src/drive/batch/drive_op_batch/withdrawals.rs +++ b/packages/rs-drive/src/drive/batch/drive_op_batch/withdrawals.rs @@ -3,7 +3,9 @@ use std::collections::HashMap; use grovedb::{batch::KeyInfoPath, EstimatedLayerInformation, TransactionArg}; use crate::{ - drive::{block_info::BlockInfo, identity::withdrawals::paths::WithdrawalTransaction, Drive}, + drive::{ + block_info::BlockInfo, identity::withdrawals::paths::WithdrawalTransactionIdAndBytes, Drive, + }, error::Error, fee::op::DriveOperation, }; @@ -31,7 +33,7 @@ pub enum WithdrawalOperationType<'a> { /// Insert Core Transaction into queue InsertTransactions { /// transaction id bytes - withdrawal_transactions: &'a [WithdrawalTransaction], + withdrawal_transactions: &'a [WithdrawalTransactionIdAndBytes], }, /// Delete withdrawal DeleteWithdrawalTransaction { diff --git a/packages/rs-drive/src/drive/identity/withdrawals/insert.rs b/packages/rs-drive/src/drive/identity/withdrawals/insert.rs index dbf9692d99d..5d81d9c6cfc 100644 --- a/packages/rs-drive/src/drive/identity/withdrawals/insert.rs +++ b/packages/rs-drive/src/drive/identity/withdrawals/insert.rs @@ -1,5 +1,5 @@ use crate::drive::identity::withdrawals::paths::{ - get_withdrawal_transactions_queue_path_vec, WithdrawalTransaction, + get_withdrawal_transactions_queue_path_vec, WithdrawalTransactionIdAndBytes, }; use crate::drive::object_size_info::PathKeyElementInfo::PathKeyElement; use crate::drive::Drive; @@ -10,7 +10,7 @@ use grovedb::Element; impl Drive { pub(crate) fn insert_withdrawal_transactions( &self, - transactions: &[WithdrawalTransaction], + transactions: &[WithdrawalTransactionIdAndBytes], ) -> Result, Error> { let mut drive_operations = vec![]; diff --git a/packages/rs-drive/src/drive/identity/withdrawals/paths.rs b/packages/rs-drive/src/drive/identity/withdrawals/paths.rs index 592297df71d..612639d94f7 100644 --- a/packages/rs-drive/src/drive/identity/withdrawals/paths.rs +++ b/packages/rs-drive/src/drive/identity/withdrawals/paths.rs @@ -10,7 +10,7 @@ pub const WITHDRAWAL_TRANSACTIONS_QUEUE_ID: [u8; 1] = [1]; pub const WITHDRAWAL_TRANSACTIONS_EXPIRED_IDS: [u8; 1] = [2]; /// Simple type alias for withdrawal transaction with it's id -pub type WithdrawalTransaction = (Vec, Vec); +pub type WithdrawalTransactionIdAndBytes = (Vec, Vec); /// Add operations for creating initial withdrawal state structure pub fn add_initial_withdrawal_state_structure_operations(batch: &mut GroveDbOpBatch) { diff --git a/packages/rs-drive/src/drive/identity/withdrawals/queue.rs b/packages/rs-drive/src/drive/identity/withdrawals/queue.rs index f52c50a1690..f5cb07ed149 100644 --- a/packages/rs-drive/src/drive/identity/withdrawals/queue.rs +++ b/packages/rs-drive/src/drive/identity/withdrawals/queue.rs @@ -13,13 +13,13 @@ use crate::{ error::{drive::DriveError, Error}, }; -use super::paths::{get_withdrawal_transactions_queue_path_vec, WithdrawalTransaction}; +use super::paths::{get_withdrawal_transactions_queue_path_vec, WithdrawalTransactionIdAndBytes}; impl Drive { /// Add insert operations for withdrawal transactions to the batch pub fn add_enqueue_withdrawal_transaction_operations<'a>( &self, - withdrawals: &'a [WithdrawalTransaction], + withdrawals: &'a [WithdrawalTransactionIdAndBytes], drive_operation_types: &mut Vec>, ) { if !withdrawals.is_empty() { @@ -37,7 +37,7 @@ impl Drive { max_amount: u16, transaction: TransactionArg, drive_operation_types: &mut Vec, - ) -> Result, Error> { + ) -> Result, Error> { let mut query = Query::new(); query.insert_item(QueryItem::RangeFull(RangeFull)); From 07b396ef09de8e0cb5e91518bf76aaaf25d58175 Mon Sep 17 00:00:00 2001 From: Ivan Shumkov Date: Thu, 16 Feb 2023 22:06:08 +0800 Subject: [PATCH 148/170] refactor: more stuff --- packages/rs-drive-abci/src/abci/handlers.rs | 2 +- .../src/identity_credit_withdrawal/mod.rs | 13 ++-- packages/rs-drive-nodejs/src/lib.rs | 2 +- .../drive/batch/drive_op_batch/withdrawals.rs | 16 ++--- .../src/drive/identity/withdrawals/delete.rs | 2 +- .../{withdrawal_status.rs => documents.rs} | 0 .../identity/withdrawals/expired_index.rs | 54 -------------- .../src/drive/identity/withdrawals/insert.rs | 5 +- .../src/drive/identity/withdrawals/mod.rs | 11 +-- .../src/drive/identity/withdrawals/paths.rs | 3 - .../src/drive/identity/withdrawals/queue.rs | 3 +- ..._index_counter.rs => transaction_index.rs} | 70 +++++++++++++++++-- 12 files changed, 90 insertions(+), 91 deletions(-) rename packages/rs-drive/src/drive/identity/withdrawals/{withdrawal_status.rs => documents.rs} (100%) delete mode 100644 packages/rs-drive/src/drive/identity/withdrawals/expired_index.rs rename packages/rs-drive/src/drive/identity/withdrawals/{transaction_index_counter.rs => transaction_index.rs} (76%) diff --git a/packages/rs-drive-abci/src/abci/handlers.rs b/packages/rs-drive-abci/src/abci/handlers.rs index 91c1248b1a0..43b897e6344 100644 --- a/packages/rs-drive-abci/src/abci/handlers.rs +++ b/packages/rs-drive-abci/src/abci/handlers.rs @@ -256,7 +256,7 @@ mod tests { use dpp::util::hash; use drive::common::helpers::identities::create_test_masternode_identities; use drive::drive::block_info::BlockInfo; - use drive::drive::identity::withdrawals::paths::WithdrawalTransactionIdAndBytes; + use drive::drive::identity::withdrawals::WithdrawalTransactionIdAndBytes; use drive::fee::epoch::CreditsPerEpoch; use drive::fee_pools::epochs::Epoch; use drive::rpc::core::MockCoreRPCLike; diff --git a/packages/rs-drive-abci/src/identity_credit_withdrawal/mod.rs b/packages/rs-drive-abci/src/identity_credit_withdrawal/mod.rs index 62eac9c8f07..3104508470f 100644 --- a/packages/rs-drive-abci/src/identity_credit_withdrawal/mod.rs +++ b/packages/rs-drive-abci/src/identity_credit_withdrawal/mod.rs @@ -15,11 +15,9 @@ use drive::dpp::document::document_stub::DocumentStub; use drive::dpp::identifier::Identifier; use drive::dpp::identity::convert_credits_to_satoshi; use drive::dpp::util::hash; +use drive::drive::identity::withdrawals::WithdrawalTransactionIdAndBytes; use drive::{ - drive::{ - batch::DriveOperationType, block_info::BlockInfo, - identity::withdrawals::paths::WithdrawalTransactionIdAndBytes, - }, + drive::{batch::DriveOperationType, block_info::BlockInfo}, fee_pools::epochs::Epoch, query::TransactionArg, }; @@ -459,7 +457,10 @@ impl Platform { let latest_withdrawal_index = self .drive - .remove_latest_withdrawal_transaction_index(drive_operation_types, transaction)?; + .fetch_and_remove_latest_withdrawal_transaction_index_operations( + drive_operation_types, + transaction, + )?; for (i, document) in documents.iter().enumerate() { let output_script_bytes = document @@ -919,7 +920,7 @@ mod tests { identity::state_transition::identity_credit_withdrawal_transition::Pooling, }; use drive::drive::block_info::BlockInfo; - use drive::drive::identity::withdrawals::paths::WithdrawalTransactionIdAndBytes; + use drive::drive::identity::withdrawals::WithdrawalTransactionIdAndBytes; use drive::tests::helpers::setup::setup_system_data_contract; use itertools::Itertools; diff --git a/packages/rs-drive-nodejs/src/lib.rs b/packages/rs-drive-nodejs/src/lib.rs index 1687ecade4e..07bc33ef6b0 100644 --- a/packages/rs-drive-nodejs/src/lib.rs +++ b/packages/rs-drive-nodejs/src/lib.rs @@ -3352,7 +3352,7 @@ impl PlatformWrapper { let result = platform .drive - .remove_latest_withdrawal_transaction_index( + .fetch_and_remove_latest_withdrawal_transaction_index_operations( &mut drive_operation_types, transaction_arg, ) diff --git a/packages/rs-drive/src/drive/batch/drive_op_batch/withdrawals.rs b/packages/rs-drive/src/drive/batch/drive_op_batch/withdrawals.rs index f5187e61ce7..a98e4515630 100644 --- a/packages/rs-drive/src/drive/batch/drive_op_batch/withdrawals.rs +++ b/packages/rs-drive/src/drive/batch/drive_op_batch/withdrawals.rs @@ -2,10 +2,9 @@ use std::collections::HashMap; use grovedb::{batch::KeyInfoPath, EstimatedLayerInformation, TransactionArg}; +use crate::drive::identity::withdrawals::WithdrawalTransactionIdAndBytes; use crate::{ - drive::{ - block_info::BlockInfo, identity::withdrawals::paths::WithdrawalTransactionIdAndBytes, Drive, - }, + drive::{block_info::BlockInfo, Drive}, error::Error, fee::op::DriveOperation, }; @@ -54,20 +53,19 @@ impl DriveOperationConverter for WithdrawalOperationType<'_> { ) -> Result, Error> { match self { WithdrawalOperationType::InsertExpiredIndex { index } => { - drive.insert_withdrawal_expired_index(index) + drive.insert_withdrawal_expired_index_operations(index) } WithdrawalOperationType::DeleteExpiredIndex { key } => { - drive.delete_withdrawal_expired_index(key, transaction) + drive.delete_withdrawal_expired_index_operations(key, transaction) } WithdrawalOperationType::UpdateIndexCounter { index } => { - drive.update_transaction_index_counter(index) + drive.update_transaction_index_counter_operations(index) } WithdrawalOperationType::InsertTransactions { withdrawal_transactions, } => drive.insert_withdrawal_transactions(withdrawal_transactions), - WithdrawalOperationType::DeleteWithdrawalTransaction { id } => { - drive.delete_withdrawal_transaction(id.as_slice(), transaction) - } + WithdrawalOperationType::DeleteWithdrawalTransaction { id } => drive + .delete_withdrawal_transaction_from_queue_operations(id.as_slice(), transaction), } } } diff --git a/packages/rs-drive/src/drive/identity/withdrawals/delete.rs b/packages/rs-drive/src/drive/identity/withdrawals/delete.rs index 893c29b5eaf..af966fcde29 100644 --- a/packages/rs-drive/src/drive/identity/withdrawals/delete.rs +++ b/packages/rs-drive/src/drive/identity/withdrawals/delete.rs @@ -6,7 +6,7 @@ use crate::fee::op::DriveOperation; use grovedb::TransactionArg; impl Drive { - pub(crate) fn delete_withdrawal_transaction( + pub(crate) fn delete_withdrawal_transaction_from_queue_operations( &self, id: &[u8], transaction: TransactionArg, diff --git a/packages/rs-drive/src/drive/identity/withdrawals/withdrawal_status.rs b/packages/rs-drive/src/drive/identity/withdrawals/documents.rs similarity index 100% rename from packages/rs-drive/src/drive/identity/withdrawals/withdrawal_status.rs rename to packages/rs-drive/src/drive/identity/withdrawals/documents.rs diff --git a/packages/rs-drive/src/drive/identity/withdrawals/expired_index.rs b/packages/rs-drive/src/drive/identity/withdrawals/expired_index.rs deleted file mode 100644 index 980d9bbf00b..00000000000 --- a/packages/rs-drive/src/drive/identity/withdrawals/expired_index.rs +++ /dev/null @@ -1,54 +0,0 @@ -use crate::drive::grove_operations::BatchDeleteApplyType; -use crate::drive::identity::withdrawals::paths::{ - get_withdrawal_transactions_expired_ids_path, get_withdrawal_transactions_expired_ids_path_vec, -}; -use crate::drive::Drive; -use crate::error::Error; -use crate::fee::op::DriveOperation; -use grovedb::{Element, TransactionArg}; - -impl Drive { - pub(crate) fn insert_withdrawal_expired_index( - &self, - index: u64, - ) -> Result, Error> { - let mut drive_operations = vec![]; - - let index_bytes = index.to_be_bytes(); - - let path = get_withdrawal_transactions_expired_ids_path_vec(); - - self.batch_insert( - crate::drive::object_size_info::PathKeyElementInfo::PathKeyElement::<'_, 1>(( - path, - index_bytes.to_vec(), - Element::Item(vec![], None), - )), - &mut drive_operations, - )?; - - Ok(drive_operations) - } - - pub(crate) fn delete_withdrawal_expired_index( - &self, - key: Vec, - transaction: TransactionArg, - ) -> Result, Error> { - let mut drive_operations = vec![]; - - let path: [&[u8]; 2] = get_withdrawal_transactions_expired_ids_path(); - - self.batch_delete( - path, - &key, - BatchDeleteApplyType::StatefulBatchDelete { - is_known_to_be_subtree_with_sum: Some((false, false)), - }, - transaction, - &mut drive_operations, - )?; - - Ok(drive_operations) - } -} diff --git a/packages/rs-drive/src/drive/identity/withdrawals/insert.rs b/packages/rs-drive/src/drive/identity/withdrawals/insert.rs index 5d81d9c6cfc..c3026180ebc 100644 --- a/packages/rs-drive/src/drive/identity/withdrawals/insert.rs +++ b/packages/rs-drive/src/drive/identity/withdrawals/insert.rs @@ -1,6 +1,5 @@ -use crate::drive::identity::withdrawals::paths::{ - get_withdrawal_transactions_queue_path_vec, WithdrawalTransactionIdAndBytes, -}; +use crate::drive::identity::withdrawals::paths::get_withdrawal_transactions_queue_path_vec; +use crate::drive::identity::withdrawals::WithdrawalTransactionIdAndBytes; use crate::drive::object_size_info::PathKeyElementInfo::PathKeyElement; use crate::drive::Drive; use crate::error::Error; diff --git a/packages/rs-drive/src/drive/identity/withdrawals/mod.rs b/packages/rs-drive/src/drive/identity/withdrawals/mod.rs index 7b10bb6ccb0..8a58a7ebd5b 100644 --- a/packages/rs-drive/src/drive/identity/withdrawals/mod.rs +++ b/packages/rs-drive/src/drive/identity/withdrawals/mod.rs @@ -1,7 +1,7 @@ /// Inserting a withdrawal pub(crate) mod delete; -/// Inserting or Deleting an expired index -pub(crate) mod expired_index; +/// Functions related to updating of a withdrawal status +pub mod documents; /// Inserting a withdrawal pub(crate) mod insert; /// Functions and constants related to GroveDB paths @@ -9,6 +9,7 @@ pub mod paths; /// Functions related to withdrawal queue pub mod queue; /// Functions related to transaction index counter -pub mod transaction_index_counter; -/// Functions related to updating of a withdrawal status -pub mod withdrawal_status; +pub mod transaction_index; + +/// Simple type alias for withdrawal transaction with it's id +pub type WithdrawalTransactionIdAndBytes = (Vec, Vec); diff --git a/packages/rs-drive/src/drive/identity/withdrawals/paths.rs b/packages/rs-drive/src/drive/identity/withdrawals/paths.rs index 612639d94f7..6dc3a53a07c 100644 --- a/packages/rs-drive/src/drive/identity/withdrawals/paths.rs +++ b/packages/rs-drive/src/drive/identity/withdrawals/paths.rs @@ -9,9 +9,6 @@ pub const WITHDRAWAL_TRANSACTIONS_QUEUE_ID: [u8; 1] = [1]; /// constant id for subtree containing expired transaction ids pub const WITHDRAWAL_TRANSACTIONS_EXPIRED_IDS: [u8; 1] = [2]; -/// Simple type alias for withdrawal transaction with it's id -pub type WithdrawalTransactionIdAndBytes = (Vec, Vec); - /// Add operations for creating initial withdrawal state structure pub fn add_initial_withdrawal_state_structure_operations(batch: &mut GroveDbOpBatch) { batch.add_insert( diff --git a/packages/rs-drive/src/drive/identity/withdrawals/queue.rs b/packages/rs-drive/src/drive/identity/withdrawals/queue.rs index f5cb07ed149..e314d8ddff4 100644 --- a/packages/rs-drive/src/drive/identity/withdrawals/queue.rs +++ b/packages/rs-drive/src/drive/identity/withdrawals/queue.rs @@ -5,6 +5,7 @@ use grovedb::{ TransactionArg, }; +use crate::drive::identity::withdrawals::WithdrawalTransactionIdAndBytes; use crate::{ drive::{ batch::{drive_op_batch::WithdrawalOperationType, DriveOperationType}, @@ -13,7 +14,7 @@ use crate::{ error::{drive::DriveError, Error}, }; -use super::paths::{get_withdrawal_transactions_queue_path_vec, WithdrawalTransactionIdAndBytes}; +use super::paths::get_withdrawal_transactions_queue_path_vec; impl Drive { /// Add insert operations for withdrawal transactions to the batch diff --git a/packages/rs-drive/src/drive/identity/withdrawals/transaction_index_counter.rs b/packages/rs-drive/src/drive/identity/withdrawals/transaction_index.rs similarity index 76% rename from packages/rs-drive/src/drive/identity/withdrawals/transaction_index_counter.rs rename to packages/rs-drive/src/drive/identity/withdrawals/transaction_index.rs index 79e8b0b63c4..add6ed41396 100644 --- a/packages/rs-drive/src/drive/identity/withdrawals/transaction_index_counter.rs +++ b/packages/rs-drive/src/drive/identity/withdrawals/transaction_index.rs @@ -3,7 +3,10 @@ use grovedb::{ Element, PathQuery, Query, SizedQuery, TransactionArg, }; -use crate::drive::identity::withdrawals::paths::get_withdrawal_root_path_vec; +use crate::drive::grove_operations::BatchDeleteApplyType; +use crate::drive::identity::withdrawals::paths::{ + get_withdrawal_root_path_vec, get_withdrawal_transactions_expired_ids_path, +}; use crate::fee::op::DriveOperation; use crate::{ drive::{ @@ -18,7 +21,7 @@ use super::paths::{ }; impl Drive { - pub(crate) fn update_transaction_index_counter( + pub(crate) fn update_transaction_index_counter_operations( &self, index: u64, ) -> Result, Error> { @@ -38,8 +41,8 @@ impl Drive { Ok(drive_operations) } - /// Get latest withdrawal index in a queue - pub fn remove_latest_withdrawal_transaction_index( + /// Get and remove latest withdrawal index in a queue + pub fn fetch_and_remove_latest_withdrawal_transaction_index_operations( &self, drive_operation_types: &mut Vec, transaction: TransactionArg, @@ -139,6 +142,50 @@ impl Drive { }, )); } + + pub(crate) fn insert_withdrawal_expired_index_operations( + &self, + index: u64, + ) -> Result, Error> { + let mut drive_operations = vec![]; + + let index_bytes = index.to_be_bytes(); + + let path = get_withdrawal_transactions_expired_ids_path_vec(); + + self.batch_insert( + crate::drive::object_size_info::PathKeyElementInfo::PathKeyElement::<'_, 1>(( + path, + index_bytes.to_vec(), + Element::Item(vec![], None), + )), + &mut drive_operations, + )?; + + Ok(drive_operations) + } + + pub(crate) fn delete_withdrawal_expired_index_operations( + &self, + key: Vec, + transaction: TransactionArg, + ) -> Result, Error> { + let mut drive_operations = vec![]; + + let path: [&[u8]; 2] = get_withdrawal_transactions_expired_ids_path(); + + self.batch_delete( + path, + &key, + BatchDeleteApplyType::StatefulBatchDelete { + is_known_to_be_subtree_with_sum: Some((false, false)), + }, + transaction, + &mut drive_operations, + )?; + + Ok(drive_operations) + } } #[cfg(test)] @@ -179,7 +226,10 @@ mod tests { let mut batch = vec![]; let stored_counter = drive - .remove_latest_withdrawal_transaction_index(&mut batch, Some(&transaction)) + .fetch_and_remove_latest_withdrawal_transaction_index_operations( + &mut batch, + Some(&transaction), + ) .expect("to withdraw counter"); drive @@ -198,7 +248,10 @@ mod tests { let mut batch = vec![]; let stored_counter = drive - .remove_latest_withdrawal_transaction_index(&mut batch, Some(&transaction)) + .fetch_and_remove_latest_withdrawal_transaction_index_operations( + &mut batch, + Some(&transaction), + ) .expect("to withdraw counter"); assert_eq!(stored_counter, 0); @@ -229,7 +282,10 @@ mod tests { let mut batch = vec![]; let stored_counter = drive - .remove_latest_withdrawal_transaction_index(&mut batch, Some(&transaction)) + .fetch_and_remove_latest_withdrawal_transaction_index_operations( + &mut batch, + Some(&transaction), + ) .expect("to withdraw counter"); assert_eq!(stored_counter, 42); From a80c0ce582e722c2904678a44dd7de5f4b91f47b Mon Sep 17 00:00:00 2001 From: Djavid Gabibiyan Date: Thu, 16 Feb 2023 19:41:06 +0500 Subject: [PATCH 149/170] chore: use u32 for block height --- packages/rs-drive-abci/src/abci/messages.rs | 4 ++-- packages/rs-drive-abci/src/block.rs | 2 +- .../src/identity_credit_withdrawal/mod.rs | 10 +++++----- packages/rs-drive/src/rpc/core.rs | 6 +++--- 4 files changed, 11 insertions(+), 11 deletions(-) diff --git a/packages/rs-drive-abci/src/abci/messages.rs b/packages/rs-drive-abci/src/abci/messages.rs index 9986f1f7f05..26912da7cb5 100644 --- a/packages/rs-drive-abci/src/abci/messages.rs +++ b/packages/rs-drive-abci/src/abci/messages.rs @@ -102,9 +102,9 @@ pub struct BlockBeginRequest { /// Validator set quorum hash pub validator_set_quorum_hash: [u8; 32], /// Last synced core height - pub last_synced_core_height: u64, + pub last_synced_core_height: u32, /// Core chain locked height - pub core_chain_locked_height: u64, + pub core_chain_locked_height: u32, /// The total number of HPMNs in the system pub total_hpmns: u32, } diff --git a/packages/rs-drive-abci/src/block.rs b/packages/rs-drive-abci/src/block.rs index c38d72cac75..92b5ca09888 100644 --- a/packages/rs-drive-abci/src/block.rs +++ b/packages/rs-drive-abci/src/block.rs @@ -41,7 +41,7 @@ pub struct BlockStateInfo { /// Block proposer's proTxHash pub proposer_pro_tx_hash: [u8; 32], /// Core chain locked height - pub core_chain_locked_height: u64, + pub core_chain_locked_height: u32, } impl BlockStateInfo { diff --git a/packages/rs-drive-abci/src/identity_credit_withdrawal/mod.rs b/packages/rs-drive-abci/src/identity_credit_withdrawal/mod.rs index 3104508470f..555f2762900 100644 --- a/packages/rs-drive-abci/src/identity_credit_withdrawal/mod.rs +++ b/packages/rs-drive-abci/src/identity_credit_withdrawal/mod.rs @@ -29,13 +29,13 @@ use crate::{ }; const WITHDRAWAL_TRANSACTIONS_QUERY_LIMIT: u16 = 16; -const NUMBER_OF_BLOCKS_BEFORE_EXPIRED: u64 = 48; +const NUMBER_OF_BLOCKS_BEFORE_EXPIRED: u32 = 48; impl Platform { /// Update statuses for broadcasted withdrawals pub fn update_broadcasted_withdrawal_transaction_statuses( &self, - last_synced_core_height: u64, + last_synced_core_height: u32, transaction: TransactionArg, ) -> Result<(), Error> { // Retrieve block execution context @@ -81,7 +81,7 @@ impl Platform { .into_iter() .map(|mut document| { let transaction_sign_height = document - .get_u64(withdrawals_contract::property_names::TRANSACTION_SIGN_HEIGHT) + .get_u32(withdrawals_contract::property_names::TRANSACTION_SIGN_HEIGHT) .map_err(|_| { Error::Execution(ExecutionError::CorruptedCodeExecution( "Can't get transactionSignHeight from withdrawal document", @@ -408,8 +408,8 @@ impl Platform { /// Fetch Core transactions by range of Core heights pub fn fetch_core_block_transactions( &self, - last_synced_core_height: u64, - core_chain_locked_height: u64, + last_synced_core_height: u32, + core_chain_locked_height: u32, ) -> Result, Error> { let mut tx_hashes: Vec = vec![]; diff --git a/packages/rs-drive/src/rpc/core.rs b/packages/rs-drive/src/rpc/core.rs index 0b0d7f20e3e..5a33c415dd9 100644 --- a/packages/rs-drive/src/rpc/core.rs +++ b/packages/rs-drive/src/rpc/core.rs @@ -8,7 +8,7 @@ use serde_json::Value; #[cfg_attr(feature = "fixtures-and-mocks", automock)] pub trait CoreRPCLike { /// Get block hash by height - fn get_block_hash(&self, height: u64) -> Result; + fn get_block_hash(&self, height: u32) -> Result; /// Get block by hash fn get_block(&self, block_hash: &BlockHash) -> Result; @@ -32,8 +32,8 @@ impl DefaultCoreRPC { } impl CoreRPCLike for DefaultCoreRPC { - fn get_block_hash(&self, height: u64) -> Result { - self.inner.get_block_hash(height) + fn get_block_hash(&self, height: u32) -> Result { + self.inner.get_block_hash(height as u64) } fn get_block(&self, block_hash: &BlockHash) -> Result { From 187909d53c5e291dbb4602fa3dc3c925782499b4 Mon Sep 17 00:00:00 2001 From: Djavid Gabibiyan Date: Thu, 16 Feb 2023 20:08:16 +0500 Subject: [PATCH 150/170] chore: inline functions --- ...WithdrawalTransactionIdAndStatusFactory.js | 1 + ...e_identity_credit_withdrawal_state_spec.rs | 4 +- .../src/identity_credit_withdrawal/mod.rs | 3 +- .../drive/batch/drive_op_batch/withdrawals.rs | 95 +++++++++++++++++-- .../src/drive/identity/withdrawals/delete.rs | 31 ------ .../src/drive/identity/withdrawals/insert.rs | 31 ------ .../src/drive/identity/withdrawals/mod.rs | 4 - .../identity/withdrawals/transaction_index.rs | 69 -------------- 8 files changed, 93 insertions(+), 145 deletions(-) delete mode 100644 packages/rs-drive/src/drive/identity/withdrawals/delete.rs delete mode 100644 packages/rs-drive/src/drive/identity/withdrawals/insert.rs diff --git a/packages/js-drive/lib/identity/withdrawals/updateWithdrawalTransactionIdAndStatusFactory.js b/packages/js-drive/lib/identity/withdrawals/updateWithdrawalTransactionIdAndStatusFactory.js index 92a7fe61b53..2a36d7233f3 100644 --- a/packages/js-drive/lib/identity/withdrawals/updateWithdrawalTransactionIdAndStatusFactory.js +++ b/packages/js-drive/lib/identity/withdrawals/updateWithdrawalTransactionIdAndStatusFactory.js @@ -48,6 +48,7 @@ function updateWithdrawalTransactionIdAndStatusFactory( ); for (const document of documents) { + // TODO: set transactionSignHeight! document.set('transactionId', updatedTransactionId); document.set('status', WITHDRAWALS_STATUS_BROADCASTED); document.setRevision(document.getRevision() + 1); diff --git a/packages/rs-dpp/src/tests/identity/state_transition/identity_credit_withdrawal_transition/validation/state/validate_identity_credit_withdrawal_state_spec.rs b/packages/rs-dpp/src/tests/identity/state_transition/identity_credit_withdrawal_transition/validation/state/validate_identity_credit_withdrawal_state_spec.rs index 92026162fd6..599215919c6 100644 --- a/packages/rs-dpp/src/tests/identity/state_transition/identity_credit_withdrawal_transition/validation/state/validate_identity_credit_withdrawal_state_spec.rs +++ b/packages/rs-dpp/src/tests/identity/state_transition/identity_credit_withdrawal_transition/validation/state/validate_identity_credit_withdrawal_state_spec.rs @@ -109,7 +109,7 @@ mod validate_identity_credit_withdrawal_transition_state_factory { .await; match result { - Ok(_) => assert!(false, "should not return Ok result"), + Ok(_) => panic!("should not return Ok result"), Err(e) => assert_eq!(e.to_string(), "Some error"), } } @@ -139,6 +139,6 @@ mod validate_identity_credit_withdrawal_transition_state_factory { .await .unwrap(); - assert_eq!(result.is_valid(), true); + assert!(result.is_valid()); } } diff --git a/packages/rs-drive-abci/src/identity_credit_withdrawal/mod.rs b/packages/rs-drive-abci/src/identity_credit_withdrawal/mod.rs index 555f2762900..dbe9da09b62 100644 --- a/packages/rs-drive-abci/src/identity_credit_withdrawal/mod.rs +++ b/packages/rs-drive-abci/src/identity_credit_withdrawal/mod.rs @@ -219,8 +219,7 @@ impl Platform { .into_iter() .map(|(_, untied_transaction_bytes)| { let request_info = AssetUnlockRequestInfo { - request_height: block_execution_context.block_info.core_chain_locked_height - as u32, + request_height: block_execution_context.block_info.core_chain_locked_height, quorum_hash: QuorumHash::hash(&validator_set_quorum_hash), }; diff --git a/packages/rs-drive/src/drive/batch/drive_op_batch/withdrawals.rs b/packages/rs-drive/src/drive/batch/drive_op_batch/withdrawals.rs index a98e4515630..c674246d859 100644 --- a/packages/rs-drive/src/drive/batch/drive_op_batch/withdrawals.rs +++ b/packages/rs-drive/src/drive/batch/drive_op_batch/withdrawals.rs @@ -1,8 +1,16 @@ use std::collections::HashMap; +use grovedb::Element; use grovedb::{batch::KeyInfoPath, EstimatedLayerInformation, TransactionArg}; +use crate::drive::grove_operations::BatchDeleteApplyType; +use crate::drive::identity::withdrawals::paths::{ + get_withdrawal_root_path_vec, get_withdrawal_transactions_expired_ids_path, + get_withdrawal_transactions_expired_ids_path_vec, get_withdrawal_transactions_queue_path, + get_withdrawal_transactions_queue_path_vec, WITHDRAWAL_TRANSACTIONS_COUNTER_ID, +}; use crate::drive::identity::withdrawals::WithdrawalTransactionIdAndBytes; +use crate::drive::object_size_info::PathKeyElementInfo; use crate::{ drive::{block_info::BlockInfo, Drive}, error::Error, @@ -53,19 +61,94 @@ impl DriveOperationConverter for WithdrawalOperationType<'_> { ) -> Result, Error> { match self { WithdrawalOperationType::InsertExpiredIndex { index } => { - drive.insert_withdrawal_expired_index_operations(index) + let mut drive_operations = vec![]; + + let index_bytes = index.to_be_bytes(); + + let path = get_withdrawal_transactions_expired_ids_path_vec(); + + drive.batch_insert( + PathKeyElementInfo::PathKeyElement::<'_, 1>(( + path, + index_bytes.to_vec(), + Element::Item(vec![], None), + )), + &mut drive_operations, + )?; + + Ok(drive_operations) } WithdrawalOperationType::DeleteExpiredIndex { key } => { - drive.delete_withdrawal_expired_index_operations(key, transaction) + let mut drive_operations = vec![]; + + let path: [&[u8]; 2] = get_withdrawal_transactions_expired_ids_path(); + + drive.batch_delete( + path, + &key, + BatchDeleteApplyType::StatefulBatchDelete { + is_known_to_be_subtree_with_sum: Some((false, false)), + }, + transaction, + &mut drive_operations, + )?; + + Ok(drive_operations) } WithdrawalOperationType::UpdateIndexCounter { index } => { - drive.update_transaction_index_counter_operations(index) + let mut drive_operations = vec![]; + + let path = get_withdrawal_root_path_vec(); + + drive.batch_insert( + PathKeyElementInfo::PathKeyRefElement::<'_, 1>(( + path, + &WITHDRAWAL_TRANSACTIONS_COUNTER_ID, + Element::Item(index.to_be_bytes().to_vec(), None), + )), + &mut drive_operations, + )?; + + Ok(drive_operations) } WithdrawalOperationType::InsertTransactions { withdrawal_transactions, - } => drive.insert_withdrawal_transactions(withdrawal_transactions), - WithdrawalOperationType::DeleteWithdrawalTransaction { id } => drive - .delete_withdrawal_transaction_from_queue_operations(id.as_slice(), transaction), + } => { + let mut drive_operations = vec![]; + + let path = get_withdrawal_transactions_queue_path_vec(); + + for (id, bytes) in withdrawal_transactions { + drive.batch_insert( + PathKeyElementInfo::PathKeyElement::<'_, 1>(( + path.clone(), + id.clone(), + Element::Item(bytes.clone(), None), + )), + &mut drive_operations, + )?; + } + + Ok(drive_operations) + } + WithdrawalOperationType::DeleteWithdrawalTransaction { id } => { + let mut drive_operations = vec![]; + + let path = get_withdrawal_transactions_queue_path(); + + drive.batch_delete( + path, + &id, + // we know that we are not deleting a subtree + BatchDeleteApplyType::StatefulBatchDelete { + is_known_to_be_subtree_with_sum: Some((false, false)), + }, + transaction, + &mut drive_operations, + )?; + + Ok(drive_operations) + } } } } diff --git a/packages/rs-drive/src/drive/identity/withdrawals/delete.rs b/packages/rs-drive/src/drive/identity/withdrawals/delete.rs deleted file mode 100644 index af966fcde29..00000000000 --- a/packages/rs-drive/src/drive/identity/withdrawals/delete.rs +++ /dev/null @@ -1,31 +0,0 @@ -use crate::drive::grove_operations::BatchDeleteApplyType; -use crate::drive::identity::withdrawals::paths::get_withdrawal_transactions_queue_path; -use crate::drive::Drive; -use crate::error::Error; -use crate::fee::op::DriveOperation; -use grovedb::TransactionArg; - -impl Drive { - pub(crate) fn delete_withdrawal_transaction_from_queue_operations( - &self, - id: &[u8], - transaction: TransactionArg, - ) -> Result, Error> { - let mut drive_operations = vec![]; - - let path = get_withdrawal_transactions_queue_path(); - - self.batch_delete( - path, - id, - // we know that we are not deleting a subtree - BatchDeleteApplyType::StatefulBatchDelete { - is_known_to_be_subtree_with_sum: Some((false, false)), - }, - transaction, - &mut drive_operations, - )?; - - Ok(drive_operations) - } -} diff --git a/packages/rs-drive/src/drive/identity/withdrawals/insert.rs b/packages/rs-drive/src/drive/identity/withdrawals/insert.rs deleted file mode 100644 index c3026180ebc..00000000000 --- a/packages/rs-drive/src/drive/identity/withdrawals/insert.rs +++ /dev/null @@ -1,31 +0,0 @@ -use crate::drive::identity::withdrawals::paths::get_withdrawal_transactions_queue_path_vec; -use crate::drive::identity::withdrawals::WithdrawalTransactionIdAndBytes; -use crate::drive::object_size_info::PathKeyElementInfo::PathKeyElement; -use crate::drive::Drive; -use crate::error::Error; -use crate::fee::op::DriveOperation; -use grovedb::Element; - -impl Drive { - pub(crate) fn insert_withdrawal_transactions( - &self, - transactions: &[WithdrawalTransactionIdAndBytes], - ) -> Result, Error> { - let mut drive_operations = vec![]; - - let path = get_withdrawal_transactions_queue_path_vec(); - - for (id, bytes) in transactions { - self.batch_insert( - PathKeyElement::<'_, 1>(( - path.clone(), - id.clone(), - Element::Item(bytes.clone(), None), - )), - &mut drive_operations, - )?; - } - - Ok(drive_operations) - } -} diff --git a/packages/rs-drive/src/drive/identity/withdrawals/mod.rs b/packages/rs-drive/src/drive/identity/withdrawals/mod.rs index 8a58a7ebd5b..f5285349513 100644 --- a/packages/rs-drive/src/drive/identity/withdrawals/mod.rs +++ b/packages/rs-drive/src/drive/identity/withdrawals/mod.rs @@ -1,9 +1,5 @@ -/// Inserting a withdrawal -pub(crate) mod delete; /// Functions related to updating of a withdrawal status pub mod documents; -/// Inserting a withdrawal -pub(crate) mod insert; /// Functions and constants related to GroveDB paths pub mod paths; /// Functions related to withdrawal queue diff --git a/packages/rs-drive/src/drive/identity/withdrawals/transaction_index.rs b/packages/rs-drive/src/drive/identity/withdrawals/transaction_index.rs index add6ed41396..ef2c38c0662 100644 --- a/packages/rs-drive/src/drive/identity/withdrawals/transaction_index.rs +++ b/packages/rs-drive/src/drive/identity/withdrawals/transaction_index.rs @@ -3,11 +3,6 @@ use grovedb::{ Element, PathQuery, Query, SizedQuery, TransactionArg, }; -use crate::drive::grove_operations::BatchDeleteApplyType; -use crate::drive::identity::withdrawals::paths::{ - get_withdrawal_root_path_vec, get_withdrawal_transactions_expired_ids_path, -}; -use crate::fee::op::DriveOperation; use crate::{ drive::{ batch::{drive_op_batch::WithdrawalOperationType, DriveOperationType}, @@ -21,26 +16,6 @@ use super::paths::{ }; impl Drive { - pub(crate) fn update_transaction_index_counter_operations( - &self, - index: u64, - ) -> Result, Error> { - let mut drive_operations = vec![]; - - let path = get_withdrawal_root_path_vec(); - - self.batch_insert( - crate::drive::object_size_info::PathKeyElementInfo::PathKeyRefElement::<'_, 1>(( - path, - &WITHDRAWAL_TRANSACTIONS_COUNTER_ID, - Element::Item(index.to_be_bytes().to_vec(), None), - )), - &mut drive_operations, - )?; - - Ok(drive_operations) - } - /// Get and remove latest withdrawal index in a queue pub fn fetch_and_remove_latest_withdrawal_transaction_index_operations( &self, @@ -142,50 +117,6 @@ impl Drive { }, )); } - - pub(crate) fn insert_withdrawal_expired_index_operations( - &self, - index: u64, - ) -> Result, Error> { - let mut drive_operations = vec![]; - - let index_bytes = index.to_be_bytes(); - - let path = get_withdrawal_transactions_expired_ids_path_vec(); - - self.batch_insert( - crate::drive::object_size_info::PathKeyElementInfo::PathKeyElement::<'_, 1>(( - path, - index_bytes.to_vec(), - Element::Item(vec![], None), - )), - &mut drive_operations, - )?; - - Ok(drive_operations) - } - - pub(crate) fn delete_withdrawal_expired_index_operations( - &self, - key: Vec, - transaction: TransactionArg, - ) -> Result, Error> { - let mut drive_operations = vec![]; - - let path: [&[u8]; 2] = get_withdrawal_transactions_expired_ids_path(); - - self.batch_delete( - path, - &key, - BatchDeleteApplyType::StatefulBatchDelete { - is_known_to_be_subtree_with_sum: Some((false, false)), - }, - transaction, - &mut drive_operations, - )?; - - Ok(drive_operations) - } } #[cfg(test)] From e8829d31a0302b9ed75dd0baf3371acca573454e Mon Sep 17 00:00:00 2001 From: Djavid Gabibiyan Date: Thu, 16 Feb 2023 20:17:02 +0500 Subject: [PATCH 151/170] chore: populate transactionSignHeight --- .../proposal/broadcastWithdrawalTransactionsFactory.js | 1 + .../updateWithdrawalTransactionIdAndStatusFactory.js | 4 +++- .../proposal/broadcastWithdrawalTransactionsFactory.spec.js | 2 ++ .../updateWithdrawalTransactionIdAndStatusFactory.spec.js | 4 +++- 4 files changed, 9 insertions(+), 2 deletions(-) diff --git a/packages/js-drive/lib/abci/handlers/proposal/broadcastWithdrawalTransactionsFactory.js b/packages/js-drive/lib/abci/handlers/proposal/broadcastWithdrawalTransactionsFactory.js index 15c8898ef61..da1bb16bd27 100644 --- a/packages/js-drive/lib/abci/handlers/proposal/broadcastWithdrawalTransactionsFactory.js +++ b/packages/js-drive/lib/abci/handlers/proposal/broadcastWithdrawalTransactionsFactory.js @@ -44,6 +44,7 @@ function broadcastWithdrawalTransactionsFactory( await updateWithdrawalTransactionIdAndStatus( blockInfo, + proposalBlockExecutionContext.getCoreChainLockedHeight(), unsignedWithdrawalTransactionBytes, transactionBytes, { diff --git a/packages/js-drive/lib/identity/withdrawals/updateWithdrawalTransactionIdAndStatusFactory.js b/packages/js-drive/lib/identity/withdrawals/updateWithdrawalTransactionIdAndStatusFactory.js index 2a36d7233f3..2189ddf738f 100644 --- a/packages/js-drive/lib/identity/withdrawals/updateWithdrawalTransactionIdAndStatusFactory.js +++ b/packages/js-drive/lib/identity/withdrawals/updateWithdrawalTransactionIdAndStatusFactory.js @@ -21,6 +21,7 @@ function updateWithdrawalTransactionIdAndStatusFactory( * @typedef updateWithdrawalTransactionIdAndStatus * * @param {BlockInfo} blockInfo + * @param {number} coreChainLockedHeight * @param {Buffer} originalTransactionId * @param {Buffer} updatedTransactionId * @param {Object} options @@ -29,6 +30,7 @@ function updateWithdrawalTransactionIdAndStatusFactory( */ async function updateWithdrawalTransactionIdAndStatus( blockInfo, + coreChainLockedHeight, originalTransactionId, updatedTransactionId, options, @@ -48,7 +50,7 @@ function updateWithdrawalTransactionIdAndStatusFactory( ); for (const document of documents) { - // TODO: set transactionSignHeight! + document.set('transactionSignHeight', coreChainLockedHeight); document.set('transactionId', updatedTransactionId); document.set('status', WITHDRAWALS_STATUS_BROADCASTED); document.setRevision(document.getRevision() + 1); diff --git a/packages/js-drive/test/unit/abci/handlers/proposal/broadcastWithdrawalTransactionsFactory.spec.js b/packages/js-drive/test/unit/abci/handlers/proposal/broadcastWithdrawalTransactionsFactory.spec.js index 7e3ad2a6001..380c83b1c52 100644 --- a/packages/js-drive/test/unit/abci/handlers/proposal/broadcastWithdrawalTransactionsFactory.spec.js +++ b/packages/js-drive/test/unit/abci/handlers/proposal/broadcastWithdrawalTransactionsFactory.spec.js @@ -19,6 +19,7 @@ describe('broadcastWithdrawalTransactionsFactory', () => { }); proposalBlockExecutionContextMock.getHeight.returns(new Long(1)); proposalBlockExecutionContextMock.getTimeMs.returns(1); + proposalBlockExecutionContextMock.getCoreChainLockedHeight.returns(42); coreRpcMock = { sendRawTransaction: this.sinon.stub(), @@ -56,6 +57,7 @@ describe('broadcastWithdrawalTransactionsFactory', () => { ); expect(updateWithdrawalTransactionIdAndStatusMock).to.have.been.calledOnceWithExactly( BlockInfo.createFromBlockExecutionContext(proposalBlockExecutionContextMock), + 42, txBytes, Buffer.concat([txBytes, signature]), { diff --git a/packages/js-drive/test/unit/identity/withdrawals/updateWithdrawalTransactionIdAndStatusFactory.spec.js b/packages/js-drive/test/unit/identity/withdrawals/updateWithdrawalTransactionIdAndStatusFactory.spec.js index 2afe42b2954..fe2d24bf9b9 100644 --- a/packages/js-drive/test/unit/identity/withdrawals/updateWithdrawalTransactionIdAndStatusFactory.spec.js +++ b/packages/js-drive/test/unit/identity/withdrawals/updateWithdrawalTransactionIdAndStatusFactory.spec.js @@ -34,8 +34,9 @@ describe('updateWithdrawalTransactionIdAndStatusFactory', () => { const blockInfo = new BlockInfo(1, 1, 1); const updatedTxId = Buffer.alloc(32, 2); + const coreChainLockedHeight = 42; - await updateWithdrawalTransactionIdAndStatus(blockInfo, Buffer.alloc(0), updatedTxId, { + await updateWithdrawalTransactionIdAndStatus(blockInfo, coreChainLockedHeight, Buffer.alloc(0), updatedTxId, { useTransaction: true, }); @@ -55,6 +56,7 @@ describe('updateWithdrawalTransactionIdAndStatusFactory', () => { documentFixture[0], blockInfo, { useTransaction: true }, ); + expect(documentFixture[0].get('transactionSignHeight')).to.deep.equal(coreChainLockedHeight); expect(documentFixture[0].get('transactionId')).to.deep.equal(updatedTxId); expect(documentFixture[0].get('status')).to.deep.equal(2); expect(documentFixture[0].getRevision()).to.deep.equal(2); From afda779334732a55e163052bf655ea69af505ca9 Mon Sep 17 00:00:00 2001 From: Ivan Shumkov Date: Thu, 16 Feb 2023 23:44:56 +0800 Subject: [PATCH 152/170] refactor: use Revision type --- packages/rs-dpp/src/document/document_stub.rs | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/packages/rs-dpp/src/document/document_stub.rs b/packages/rs-dpp/src/document/document_stub.rs index 70023e569ca..a1150343c69 100644 --- a/packages/rs-dpp/src/document/document_stub.rs +++ b/packages/rs-dpp/src/document/document_stub.rs @@ -55,6 +55,7 @@ use crate::util::deserializer::SplitProtocolVersionOutcome; use crate::ProtocolError; use crate::document::document_transition::INITIAL_REVISION; +use crate::prelude::*; use crate::util::cbor_value::CborBTreeMapHelper; use anyhow::{anyhow, bail}; @@ -76,7 +77,7 @@ pub struct DocumentStub { /// The document revision. #[serde(rename = "$revision")] - pub revision: u64, + pub revision: Revision, } impl DocumentStub { @@ -174,14 +175,14 @@ impl DocumentStub { })?; let revision = if document_type.documents_mutable { - let revision: u64 = buf.read_varint().map_err(|_| { + let revision: Revision = buf.read_varint().map_err(|_| { ProtocolError::DataContractError(DataContractError::CorruptedSerialization( "error reading varint revision from serialized document", )) })?; revision } else { - INITIAL_REVISION as u64 + INITIAL_REVISION as Revision }; let properties = document_type @@ -267,9 +268,9 @@ impl DocumentStub { } .expect("document_id must be 32 bytes"); - let revision: u64 = document + let revision: Revision = document .remove_optional_integer("$revision")? - .unwrap_or(INITIAL_REVISION as u64); + .unwrap_or(INITIAL_REVISION as Revision); // dev-note: properties is everything other than the id and owner id Ok(DocumentStub { @@ -313,7 +314,7 @@ impl DocumentStub { )) })?; - let revision: u64 = properties.get_integer("$revision")?; + let revision: Revision = properties.get_integer("$revision")?; // dev-note: properties is everything other than the id and owner id Ok(DocumentStub { @@ -456,9 +457,8 @@ impl DocumentStub { )))?; if let Value::Integer(s) = property_value { - return (*s) - .try_into() - .map_err(|_| ProtocolError::DecodingError("expected a u32 integer".to_string())); + (*s).try_into() + .map_err(|_| ProtocolError::DecodingError("expected a u32 integer".to_string())) } else { Err(ProtocolError::DecodingError( "expected an integer".to_string(), From 1fec8f762e0472372d08d712511656973b7ae1f8 Mon Sep 17 00:00:00 2001 From: Djavid Gabibiyan Date: Thu, 16 Feb 2023 20:59:13 +0500 Subject: [PATCH 153/170] chore: linter fix --- ...teWithdrawalTransactionIdAndStatusFactory.spec.js | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/packages/js-drive/test/unit/identity/withdrawals/updateWithdrawalTransactionIdAndStatusFactory.spec.js b/packages/js-drive/test/unit/identity/withdrawals/updateWithdrawalTransactionIdAndStatusFactory.spec.js index fe2d24bf9b9..b7a9a2769f4 100644 --- a/packages/js-drive/test/unit/identity/withdrawals/updateWithdrawalTransactionIdAndStatusFactory.spec.js +++ b/packages/js-drive/test/unit/identity/withdrawals/updateWithdrawalTransactionIdAndStatusFactory.spec.js @@ -36,9 +36,15 @@ describe('updateWithdrawalTransactionIdAndStatusFactory', () => { const updatedTxId = Buffer.alloc(32, 2); const coreChainLockedHeight = 42; - await updateWithdrawalTransactionIdAndStatus(blockInfo, coreChainLockedHeight, Buffer.alloc(0), updatedTxId, { - useTransaction: true, - }); + await updateWithdrawalTransactionIdAndStatus( + blockInfo, + coreChainLockedHeight, + Buffer.alloc(0), + updatedTxId, + { + useTransaction: true, + }, + ); expect(fetchDocumentsMock).to.have.been.calledOnceWithExactly( withdrawalsContractId, From d24466c9b1818152ddb720e2759d31e12738b998 Mon Sep 17 00:00:00 2001 From: Djavid Gabibiyan Date: Thu, 16 Feb 2023 21:09:36 +0500 Subject: [PATCH 154/170] chore: rename error --- packages/rs-dpp/src/errors/codes.rs | 2 +- .../consensus/abstract_consensus_error.rs | 8 ++++---- ...edit_withdrawal_transition_pooling_error.rs | 14 ++++++++------ ...ntity_credit_withdrawal_transition_basic.rs | 8 ++++---- ..._credit_withdrawal_transition_basic_spec.rs | 2 +- ...edit_withdrawal_transition_pooling_error.rs | 18 +++++++++--------- .../wasm-dpp/src/errors/consensus_error.rs | 6 +++--- 7 files changed, 30 insertions(+), 28 deletions(-) diff --git a/packages/rs-dpp/src/errors/codes.rs b/packages/rs-dpp/src/errors/codes.rs index 76e358ee21a..d7db9ded82e 100644 --- a/packages/rs-dpp/src/errors/codes.rs +++ b/packages/rs-dpp/src/errors/codes.rs @@ -44,7 +44,7 @@ impl ErrorWithCode for ConsensusError { Self::IdentityInsufficientBalanceError(_) => 4024, Self::InvalidIdentityCreditWithdrawalTransitionCoreFeeError(_) => 4025, Self::InvalidIdentityCreditWithdrawalTransitionOutputScriptError(_) => 4026, - Self::InvalidIdentityCreditWithdrawalTransitionPoolingError(_) => 4027, + Self::NotImplementedIdentityCreditWithdrawalTransitionPoolingError(_) => 4027, Self::StateError(e) => e.get_code(), Self::BasicError(e) => e.get_code(), diff --git a/packages/rs-dpp/src/errors/consensus/abstract_consensus_error.rs b/packages/rs-dpp/src/errors/consensus/abstract_consensus_error.rs index 50a2cb0607a..af8a271d204 100644 --- a/packages/rs-dpp/src/errors/consensus/abstract_consensus_error.rs +++ b/packages/rs-dpp/src/errors/consensus/abstract_consensus_error.rs @@ -25,7 +25,7 @@ use crate::errors::StateError; use super::basic::identity::{ IdentityInsufficientBalanceError, InvalidIdentityCreditWithdrawalTransitionCoreFeeError, InvalidIdentityCreditWithdrawalTransitionOutputScriptError, - InvalidIdentityCreditWithdrawalTransitionPoolingError, + NotImplementedIdentityCreditWithdrawalTransitionPoolingError, }; use super::fee::FeeError; use super::signature::SignatureError; @@ -89,8 +89,8 @@ pub enum ConsensusError { ), #[error("{0}")] - InvalidIdentityCreditWithdrawalTransitionPoolingError( - InvalidIdentityCreditWithdrawalTransitionPoolingError, + NotImplementedIdentityCreditWithdrawalTransitionPoolingError( + NotImplementedIdentityCreditWithdrawalTransitionPoolingError, ), #[error(transparent)] @@ -169,7 +169,7 @@ impl ConsensusError { ConsensusError::IdentityInsufficientBalanceError(_) => 4024, ConsensusError::InvalidIdentityCreditWithdrawalTransitionCoreFeeError(_) => 4025, ConsensusError::InvalidIdentityCreditWithdrawalTransitionOutputScriptError(_) => 4026, - ConsensusError::InvalidIdentityCreditWithdrawalTransitionPoolingError(_) => 4027, + ConsensusError::NotImplementedIdentityCreditWithdrawalTransitionPoolingError(_) => 4027, ConsensusError::StateError(e) => e.get_code(), ConsensusError::BasicError(e) => e.get_code(), diff --git a/packages/rs-dpp/src/errors/consensus/basic/identity/invalid_credit_withdrawal_transition_pooling_error.rs b/packages/rs-dpp/src/errors/consensus/basic/identity/invalid_credit_withdrawal_transition_pooling_error.rs index 7f7b88deb69..8430c8f627e 100644 --- a/packages/rs-dpp/src/errors/consensus/basic/identity/invalid_credit_withdrawal_transition_pooling_error.rs +++ b/packages/rs-dpp/src/errors/consensus/basic/identity/invalid_credit_withdrawal_transition_pooling_error.rs @@ -3,12 +3,14 @@ use thiserror::Error; use crate::consensus::ConsensusError; #[derive(Error, Debug, Clone, PartialEq, Eq)] -#[error("pooling {pooling:?} should be equal to 0")] -pub struct InvalidIdentityCreditWithdrawalTransitionPoolingError { +#[error( + "pooling {pooling:?} should be equal to 0. Other pooling mechanism are not implemented yet" +)] +pub struct NotImplementedIdentityCreditWithdrawalTransitionPoolingError { pooling: u8, } -impl InvalidIdentityCreditWithdrawalTransitionPoolingError { +impl NotImplementedIdentityCreditWithdrawalTransitionPoolingError { pub fn new(pooling: u8) -> Self { Self { pooling } } @@ -18,8 +20,8 @@ impl InvalidIdentityCreditWithdrawalTransitionPoolingError { } } -impl From for ConsensusError { - fn from(err: InvalidIdentityCreditWithdrawalTransitionPoolingError) -> Self { - Self::InvalidIdentityCreditWithdrawalTransitionPoolingError(err) +impl From for ConsensusError { + fn from(err: NotImplementedIdentityCreditWithdrawalTransitionPoolingError) -> Self { + Self::NotImplementedIdentityCreditWithdrawalTransitionPoolingError(err) } } diff --git a/packages/rs-dpp/src/identity/state_transition/identity_credit_withdrawal_transition/validation/basic/validate_identity_credit_withdrawal_transition_basic.rs b/packages/rs-dpp/src/identity/state_transition/identity_credit_withdrawal_transition/validation/basic/validate_identity_credit_withdrawal_transition_basic.rs index 0a418164d05..34ccf4c9525 100644 --- a/packages/rs-dpp/src/identity/state_transition/identity_credit_withdrawal_transition/validation/basic/validate_identity_credit_withdrawal_transition_basic.rs +++ b/packages/rs-dpp/src/identity/state_transition/identity_credit_withdrawal_transition/validation/basic/validate_identity_credit_withdrawal_transition_basic.rs @@ -7,7 +7,7 @@ use crate::{ consensus::basic::identity::{ InvalidIdentityCreditWithdrawalTransitionCoreFeeError, InvalidIdentityCreditWithdrawalTransitionOutputScriptError, - InvalidIdentityCreditWithdrawalTransitionPoolingError, + NotImplementedIdentityCreditWithdrawalTransitionPoolingError, }, contracts::withdrawals_contract, identity::core_script::CoreScript, @@ -80,9 +80,9 @@ impl IdentityCreditWithdrawalTransitionBasicValidator { let pooling = transition_json.get_u8(withdrawals_contract::property_names::POOLING)?; if pooling > 0 { - result.add_error(InvalidIdentityCreditWithdrawalTransitionPoolingError::new( - pooling, - )); + result.add_error( + NotImplementedIdentityCreditWithdrawalTransitionPoolingError::new(pooling), + ); return Ok(result); } diff --git a/packages/rs-dpp/src/tests/identity/state_transition/identity_credit_withdrawal_transition/validation/basic/validate_identity_credit_withdrawal_transition_basic_spec.rs b/packages/rs-dpp/src/tests/identity/state_transition/identity_credit_withdrawal_transition/validation/basic/validate_identity_credit_withdrawal_transition_basic_spec.rs index bb54f20d21e..253ad859f84 100644 --- a/packages/rs-dpp/src/tests/identity/state_transition/identity_credit_withdrawal_transition/validation/basic/validate_identity_credit_withdrawal_transition_basic_spec.rs +++ b/packages/rs-dpp/src/tests/identity/state_transition/identity_credit_withdrawal_transition/validation/basic/validate_identity_credit_withdrawal_transition_basic_spec.rs @@ -444,7 +444,7 @@ mod validate_identity_credit_withdrawal_transition_basic_factory { let errors = assert_consensus_errors!( result, - ConsensusError::InvalidIdentityCreditWithdrawalTransitionPoolingError, + ConsensusError::NotImplementedIdentityCreditWithdrawalTransitionPoolingError, 1 ); diff --git a/packages/wasm-dpp/src/errors/consensus/basic/identity/invalid_identity_credit_withdrawal_transition_pooling_error.rs b/packages/wasm-dpp/src/errors/consensus/basic/identity/invalid_identity_credit_withdrawal_transition_pooling_error.rs index b7494a5b5de..12f3e179f4c 100644 --- a/packages/wasm-dpp/src/errors/consensus/basic/identity/invalid_identity_credit_withdrawal_transition_pooling_error.rs +++ b/packages/wasm-dpp/src/errors/consensus/basic/identity/invalid_identity_credit_withdrawal_transition_pooling_error.rs @@ -1,22 +1,22 @@ -use dpp::consensus::basic::identity::InvalidIdentityCreditWithdrawalTransitionPoolingError; +use dpp::consensus::basic::identity::NotImplementedIdentityCreditWithdrawalTransitionPoolingError; use dpp::consensus::ConsensusError; use wasm_bindgen::prelude::*; -#[wasm_bindgen(js_name=InvalidIdentityCreditWithdrawalTransitionPoolingError)] -pub struct InvalidIdentityCreditWithdrawalTransitionPoolingErrorWasm { - inner: InvalidIdentityCreditWithdrawalTransitionPoolingError, +#[wasm_bindgen(js_name=NotImplementedIdentityCreditWithdrawalTransitionPoolingError)] +pub struct NotImplementedIdentityCreditWithdrawalTransitionPoolingErrorWasm { + inner: NotImplementedIdentityCreditWithdrawalTransitionPoolingError, } -impl From<&InvalidIdentityCreditWithdrawalTransitionPoolingError> - for InvalidIdentityCreditWithdrawalTransitionPoolingErrorWasm +impl From<&NotImplementedIdentityCreditWithdrawalTransitionPoolingError> + for NotImplementedIdentityCreditWithdrawalTransitionPoolingErrorWasm { - fn from(e: &InvalidIdentityCreditWithdrawalTransitionPoolingError) -> Self { + fn from(e: &NotImplementedIdentityCreditWithdrawalTransitionPoolingError) -> Self { Self { inner: e.clone() } } } -#[wasm_bindgen(js_class=InvalidIdentityCreditWithdrawalTransitionPoolingError)] -impl InvalidIdentityCreditWithdrawalTransitionPoolingErrorWasm { +#[wasm_bindgen(js_class=NotImplementedIdentityCreditWithdrawalTransitionPoolingError)] +impl NotImplementedIdentityCreditWithdrawalTransitionPoolingErrorWasm { #[wasm_bindgen(js_name=getPooling)] pub fn pooling(&self) -> u8 { self.inner.pooling() diff --git a/packages/wasm-dpp/src/errors/consensus_error.rs b/packages/wasm-dpp/src/errors/consensus_error.rs index 8290e25fc5e..0365ce06671 100644 --- a/packages/wasm-dpp/src/errors/consensus_error.rs +++ b/packages/wasm-dpp/src/errors/consensus_error.rs @@ -17,10 +17,10 @@ use crate::errors::consensus::basic::identity::{ InvalidIdentityAssetLockTransactionOutputErrorWasm, InvalidIdentityCreditWithdrawalTransitionCoreFeeErrorWasm, InvalidIdentityCreditWithdrawalTransitionOutputScriptErrorWasm, - InvalidIdentityCreditWithdrawalTransitionPoolingErrorWasm, InvalidIdentityKeySignatureErrorWasm, InvalidIdentityPublicKeyDataErrorWasm, InvalidIdentityPublicKeySecurityLevelErrorWasm, InvalidInstantAssetLockProofErrorWasm, InvalidInstantAssetLockProofSignatureErrorWasm, MissingMasterPublicKeyErrorWasm, + NotImplementedIdentityCreditWithdrawalTransitionPoolingErrorWasm, }; use crate::errors::consensus::state::identity::{ DuplicatedIdentityPublicKeyIdStateErrorWasm, DuplicatedIdentityPublicKeyStateErrorWasm, @@ -155,8 +155,8 @@ pub fn from_consensus_error_ref(e: &DPPConsensusError) -> JsValue { DPPConsensusError::InvalidIdentityCreditWithdrawalTransitionOutputScriptError(e) => { InvalidIdentityCreditWithdrawalTransitionOutputScriptErrorWasm::from(e).into() } - DPPConsensusError::InvalidIdentityCreditWithdrawalTransitionPoolingError(e) => { - InvalidIdentityCreditWithdrawalTransitionPoolingErrorWasm::from(e).into() + DPPConsensusError::NotImplementedIdentityCreditWithdrawalTransitionPoolingError(e) => { + NotImplementedIdentityCreditWithdrawalTransitionPoolingErrorWasm::from(e).into() } DPPConsensusError::IdentityInsufficientBalanceError(e) => { IdentityInsufficientBalanceErrorWasm::from(e).into() From f1f45a0f2bfdefe9ca22e75c32f39f11f4516ca0 Mon Sep 17 00:00:00 2001 From: Ivan Shumkov Date: Fri, 17 Feb 2023 00:12:06 +0800 Subject: [PATCH 155/170] style: fix linter warnings --- ...teWithdrawalTransactionIdAndStatusFactory.spec.js | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/packages/js-drive/test/unit/identity/withdrawals/updateWithdrawalTransactionIdAndStatusFactory.spec.js b/packages/js-drive/test/unit/identity/withdrawals/updateWithdrawalTransactionIdAndStatusFactory.spec.js index fe2d24bf9b9..b7a9a2769f4 100644 --- a/packages/js-drive/test/unit/identity/withdrawals/updateWithdrawalTransactionIdAndStatusFactory.spec.js +++ b/packages/js-drive/test/unit/identity/withdrawals/updateWithdrawalTransactionIdAndStatusFactory.spec.js @@ -36,9 +36,15 @@ describe('updateWithdrawalTransactionIdAndStatusFactory', () => { const updatedTxId = Buffer.alloc(32, 2); const coreChainLockedHeight = 42; - await updateWithdrawalTransactionIdAndStatus(blockInfo, coreChainLockedHeight, Buffer.alloc(0), updatedTxId, { - useTransaction: true, - }); + await updateWithdrawalTransactionIdAndStatus( + blockInfo, + coreChainLockedHeight, + Buffer.alloc(0), + updatedTxId, + { + useTransaction: true, + }, + ); expect(fetchDocumentsMock).to.have.been.calledOnceWithExactly( withdrawalsContractId, From b486ff0fc208d099af4431052a15c59be41a03a6 Mon Sep 17 00:00:00 2001 From: Djavid Gabibiyan Date: Thu, 16 Feb 2023 22:14:34 +0500 Subject: [PATCH 156/170] chore: hashes --- ...ynchronizeMasternodeIdentitiesFactory.spec.js | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/packages/js-drive/test/integration/identity/masternode/synchronizeMasternodeIdentitiesFactory.spec.js b/packages/js-drive/test/integration/identity/masternode/synchronizeMasternodeIdentitiesFactory.spec.js index ad9cbfd11e3..834730d5495 100644 --- a/packages/js-drive/test/integration/identity/masternode/synchronizeMasternodeIdentitiesFactory.spec.js +++ b/packages/js-drive/test/integration/identity/masternode/synchronizeMasternodeIdentitiesFactory.spec.js @@ -363,7 +363,7 @@ describe('synchronizeMasternodeIdentitiesFactory', () => { beforeEach(async function beforeEach() { coreHeight = 3; - firstSyncAppHash = 'b64dc96e18c2d0f5854629d3fd65c61b84c18a98bdeb3c66a911d74dc9c3ffb6'; + firstSyncAppHash = '3faf41663866d5a66eb73c504861136233e2b10ae60c459f39573726786b2bd9'; blockInfo = new BlockInfo(10, 0, 1668702100799); container = await createTestDIContainer(); @@ -680,7 +680,7 @@ describe('synchronizeMasternodeIdentitiesFactory', () => { // Nothing happened - await expectDeterministicAppHash('4190498f5a8bc3d9a513f509c2ab34d02235bd368b832d47ca0a9afd99cd51a7'); + await expectDeterministicAppHash('1bc066ff1f1ab91cac098ebdfb396f435336e6e3337dabf13c7bc3757a591507'); // Core RPC should be called @@ -716,7 +716,7 @@ describe('synchronizeMasternodeIdentitiesFactory', () => { expect(result2.updatedEntities).to.have.lengthOf(0); expect(result2.removedEntities).to.have.lengthOf(0); - await expectDeterministicAppHash('752027b03c4ba31ce0d7ab86dd5de7bb152a69a07fe9b008bb1b99a9c5ce92dc'); + await expectDeterministicAppHash('ca0cee6a797d8707cfd48277b2421573f883f38b6c89b3debd47fe0b0cb195eb'); // New masternode identity should be created @@ -800,7 +800,7 @@ describe('synchronizeMasternodeIdentitiesFactory', () => { expect(result.updatedEntities).to.have.lengthOf(0); expect(result.removedEntities).to.have.lengthOf(1); - await expectDeterministicAppHash('665cd7851b312faed1a9aa764c470bf25faf682b6903ba683c513306fb0023ca'); + await expectDeterministicAppHash('f9b6d7f3358b6e2ab4d6bcddf41592ad93cc07f0d3a7d6664f383e261e84f5e7'); // Masternode identity should stay @@ -868,7 +868,7 @@ describe('synchronizeMasternodeIdentitiesFactory', () => { expect(result.updatedEntities).to.have.lengthOf(0); expect(result.removedEntities).to.have.lengthOf(1); - await expectDeterministicAppHash('665cd7851b312faed1a9aa764c470bf25faf682b6903ba683c513306fb0023ca'); + await expectDeterministicAppHash('f9b6d7f3358b6e2ab4d6bcddf41592ad93cc07f0d3a7d6664f383e261e84f5e7'); const invalidMasternodeIdentifier = Identifier.from( Buffer.from(invalidSmlEntry.proRegTxHash, 'hex'), @@ -918,7 +918,7 @@ describe('synchronizeMasternodeIdentitiesFactory', () => { expect(result.updatedEntities).to.have.lengthOf(1); expect(result.removedEntities).to.have.lengthOf(1); - await expectDeterministicAppHash('cf4f3da4875738c21abaaa7b089c08be84e42b032d742cd3eb1574db9a3e70aa'); + await expectDeterministicAppHash('a582e896e609e333b2e0b208040377330d8114031429c09c5ae7fc21b21573b9'); // Masternode identity should stay @@ -993,7 +993,7 @@ describe('synchronizeMasternodeIdentitiesFactory', () => { await synchronizeMasternodeIdentities(coreHeight + 1, blockInfo); - await expectDeterministicAppHash('ac377e46a223bdbe76791333c6d663f6bc9bb8e8022ed96ade53e2519298e5d3'); + await expectDeterministicAppHash('1f6ff4c65a9eee17877dfdc20c9569c47d4b0d901f2a40ea933fcc6a852055b8'); // Masternode identity should contain new public key @@ -1075,7 +1075,7 @@ describe('synchronizeMasternodeIdentitiesFactory', () => { // Initial sync await synchronizeMasternodeIdentities(coreHeight, blockInfo); - await expectDeterministicAppHash('904eed0006446dccfb5ba84c2562417781caabd44c9d750f3be0d16ebec66f29'); + await expectDeterministicAppHash('a57d1dfac825f23f518f5d48d41f9e786ac7018da4993cdf5255c27846bfac55'); const votingIdentifier = createVotingIdentifier(smlFixture[0]); const votingIdentityResult = await identityRepository.fetch( From 7f56597cb40f505da8819bfeaccfcf5bc64f47df Mon Sep 17 00:00:00 2001 From: Djavid Gabibiyan Date: Thu, 16 Feb 2023 22:17:06 +0500 Subject: [PATCH 157/170] chore: remove feature --- packages/rs-drive-abci/Cargo.toml | 2 +- packages/rs-drive/Cargo.toml | 1 - packages/rs-drive/src/lib.rs | 2 +- 3 files changed, 2 insertions(+), 3 deletions(-) diff --git a/packages/rs-drive-abci/Cargo.toml b/packages/rs-drive-abci/Cargo.toml index 2d6dc39c226..6e9600238b9 100644 --- a/packages/rs-drive-abci/Cargo.toml +++ b/packages/rs-drive-abci/Cargo.toml @@ -11,7 +11,7 @@ ciborium = { git="https://github.com/qrayven/ciborium", branch="feat-ser-null-as chrono = "0.4.20" serde = { version = "1.0.132", features = ["derive"] } serde_json = { version="1.0", features=["preserve_order"] } -drive = { path = "../rs-drive", features = ["fixtures-and-mocks", "test-helpers"]} +drive = { path = "../rs-drive", features = ["fixtures-and-mocks"]} thiserror = "1.0.30" rand = "0.8.4" tempfile = "3.3.0" diff --git a/packages/rs-drive/Cargo.toml b/packages/rs-drive/Cargo.toml index 77667431e8e..0861db550ea 100644 --- a/packages/rs-drive/Cargo.toml +++ b/packages/rs-drive/Cargo.toml @@ -58,4 +58,3 @@ harness = false [features] fixtures-and-mocks = ["mockall"] -test-helpers = [] diff --git a/packages/rs-drive/src/lib.rs b/packages/rs-drive/src/lib.rs index c3ff17eed83..723438e7603 100644 --- a/packages/rs-drive/src/lib.rs +++ b/packages/rs-drive/src/lib.rs @@ -32,5 +32,5 @@ pub use dpp; pub use grovedb; /// Test helpers -#[cfg(feature = "test-helpers")] +#[cfg(feature = "fixtures-and-mocks")] pub mod tests; From f03274d8e2ee540961b9254260404a3b97ec7f3c Mon Sep 17 00:00:00 2001 From: Quantum Explorer Date: Fri, 17 Feb 2023 15:04:46 +0700 Subject: [PATCH 158/170] small fix for contract fetching --- .../rs-drive/src/drive/identity/withdrawals/documents.rs | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/packages/rs-drive/src/drive/identity/withdrawals/documents.rs b/packages/rs-drive/src/drive/identity/withdrawals/documents.rs index da831728747..76c325d593e 100644 --- a/packages/rs-drive/src/drive/identity/withdrawals/documents.rs +++ b/packages/rs-drive/src/drive/identity/withdrawals/documents.rs @@ -25,8 +25,8 @@ impl Drive { let data_contract_id = withdrawals_contract::CONTRACT_ID.deref(); let contract_fetch_info = self - .fetch_contract(data_contract_id.to_buffer(), None, transaction) - .unwrap()? + .get_contract_with_fetch_info(data_contract_id.to_buffer(), None, transaction)? + .1 .ok_or_else(|| { Error::Drive(DriveError::CorruptedCodeExecution( "Can't fetch data contract", @@ -39,6 +39,7 @@ impl Drive { let mut where_clauses = BTreeMap::new(); + //todo: make this lazy loaded or const where_clauses.insert( withdrawals_contract::property_names::OWNER_ID.to_string(), WhereClause { @@ -118,8 +119,8 @@ impl Drive { let data_contract_id = withdrawals_contract::CONTRACT_ID.deref(); let contract_fetch_info = self - .fetch_contract(data_contract_id.to_buffer(), None, transaction) - .unwrap()? + .get_contract_with_fetch_info(data_contract_id.to_buffer(), None, transaction)? + .1 .ok_or_else(|| { Error::Drive(DriveError::CorruptedCodeExecution( "Can't fetch data contract", From 84d1867b7ebd4a24505e9257fe0af02eec45528f Mon Sep 17 00:00:00 2001 From: Djavid Gabibiyan Date: Fri, 17 Feb 2023 15:51:02 +0500 Subject: [PATCH 159/170] chore: txIdMap --- .../broadcastWithdrawalTransactionsFactory.js | 23 +++++----- ...WithdrawalTransactionIdAndStatusFactory.js | 16 ++++--- ...dcastWithdrawalTransactionsFactory.spec.js | 5 ++- ...rawalTransactionIdAndStatusFactory.spec.js | 44 +++++++++++++------ ...ty_credit_withdrawal_transition_factory.rs | 2 +- 5 files changed, 57 insertions(+), 33 deletions(-) diff --git a/packages/js-drive/lib/abci/handlers/proposal/broadcastWithdrawalTransactionsFactory.js b/packages/js-drive/lib/abci/handlers/proposal/broadcastWithdrawalTransactionsFactory.js index da1bb16bd27..3bc4818b684 100644 --- a/packages/js-drive/lib/abci/handlers/proposal/broadcastWithdrawalTransactionsFactory.js +++ b/packages/js-drive/lib/abci/handlers/proposal/broadcastWithdrawalTransactionsFactory.js @@ -26,6 +26,8 @@ function broadcastWithdrawalTransactionsFactory( ) { const blockInfo = BlockInfo.createFromBlockExecutionContext(proposalBlockExecutionContext); + const transactionIdMap = {}; + for (const { extension, signature } of (thresholdVoteExtensions || [])) { const withdrawalTransactionHash = extension.toString('hex'); @@ -39,20 +41,21 @@ function broadcastWithdrawalTransactionsFactory( signature, ]); + transactionIdMap[unsignedWithdrawalTransactionBytes.toString('hex')] = transactionBytes; + // TODO: think about Core error handling await coreRpcClient.sendRawTransaction(transactionBytes.toString('hex')); - - await updateWithdrawalTransactionIdAndStatus( - blockInfo, - proposalBlockExecutionContext.getCoreChainLockedHeight(), - unsignedWithdrawalTransactionBytes, - transactionBytes, - { - useTransaction: true, - }, - ); } } + + await updateWithdrawalTransactionIdAndStatus( + blockInfo, + proposalBlockExecutionContext.getCoreChainLockedHeight(), + transactionIdMap, + { + useTransaction: true, + }, + ); } return broadcastWithdrawalTransactions; diff --git a/packages/js-drive/lib/identity/withdrawals/updateWithdrawalTransactionIdAndStatusFactory.js b/packages/js-drive/lib/identity/withdrawals/updateWithdrawalTransactionIdAndStatusFactory.js index 2189ddf738f..95941f7024c 100644 --- a/packages/js-drive/lib/identity/withdrawals/updateWithdrawalTransactionIdAndStatusFactory.js +++ b/packages/js-drive/lib/identity/withdrawals/updateWithdrawalTransactionIdAndStatusFactory.js @@ -22,8 +22,7 @@ function updateWithdrawalTransactionIdAndStatusFactory( * * @param {BlockInfo} blockInfo * @param {number} coreChainLockedHeight - * @param {Buffer} originalTransactionId - * @param {Buffer} updatedTransactionId + * @param {Object} transactionIdMap * @param {Object} options * * @returns {Promise} @@ -31,14 +30,15 @@ function updateWithdrawalTransactionIdAndStatusFactory( async function updateWithdrawalTransactionIdAndStatus( blockInfo, coreChainLockedHeight, - originalTransactionId, - updatedTransactionId, + transactionIdMap, options, ) { + const originalTransactionIds = Object.keys(transactionIdMap).map((key) => Buffer.from(key, 'hex')); + const fetchOptions = { where: [ ['status', '==', WITHDRAWALS_STATUS_POOLED], - ['transactionId', '==', originalTransactionId], + ['transactionId', 'in', originalTransactionIds], ], ...options, }; @@ -50,8 +50,12 @@ function updateWithdrawalTransactionIdAndStatusFactory( ); for (const document of documents) { - document.set('transactionSignHeight', coreChainLockedHeight); + const originalTransactionIdHex = document.get('transactionId').toString('hex'); + + const updatedTransactionId = transactionIdMap[originalTransactionIdHex]; + document.set('transactionId', updatedTransactionId); + document.set('transactionSignHeight', coreChainLockedHeight); document.set('status', WITHDRAWALS_STATUS_BROADCASTED); document.setRevision(document.getRevision() + 1); diff --git a/packages/js-drive/test/unit/abci/handlers/proposal/broadcastWithdrawalTransactionsFactory.spec.js b/packages/js-drive/test/unit/abci/handlers/proposal/broadcastWithdrawalTransactionsFactory.spec.js index 380c83b1c52..11e775a082c 100644 --- a/packages/js-drive/test/unit/abci/handlers/proposal/broadcastWithdrawalTransactionsFactory.spec.js +++ b/packages/js-drive/test/unit/abci/handlers/proposal/broadcastWithdrawalTransactionsFactory.spec.js @@ -52,14 +52,15 @@ describe('broadcastWithdrawalTransactionsFactory', () => { unsignedWithdrawalTransactionsMap, ); + const expectedMap = { [txBytes.toString('hex')]: Buffer.concat([txBytes, signature]) }; + expect(coreRpcMock.sendRawTransaction).to.have.been.calledOnceWithExactly( Buffer.concat([txBytes, signature]).toString('hex'), ); expect(updateWithdrawalTransactionIdAndStatusMock).to.have.been.calledOnceWithExactly( BlockInfo.createFromBlockExecutionContext(proposalBlockExecutionContextMock), 42, - txBytes, - Buffer.concat([txBytes, signature]), + expectedMap, { useTransaction: true, }, diff --git a/packages/js-drive/test/unit/identity/withdrawals/updateWithdrawalTransactionIdAndStatusFactory.spec.js b/packages/js-drive/test/unit/identity/withdrawals/updateWithdrawalTransactionIdAndStatusFactory.spec.js index b7a9a2769f4..ce841b54c02 100644 --- a/packages/js-drive/test/unit/identity/withdrawals/updateWithdrawalTransactionIdAndStatusFactory.spec.js +++ b/packages/js-drive/test/unit/identity/withdrawals/updateWithdrawalTransactionIdAndStatusFactory.spec.js @@ -1,4 +1,4 @@ -const getDocumentFixture = require('@dashevo/dpp/lib/test/fixtures/getDocumentsFixture'); +const getDocumentsFixture = require('@dashevo/dpp/lib/test/fixtures/getDocumentsFixture'); const Identifier = require('@dashevo/dpp/lib/identifier/Identifier'); const updateWithdrawalTransactionIdAndStatusFactory = require('../../../../lib/identity/withdrawals/updateWithdrawalTransactionIdAndStatusFactory'); @@ -9,10 +9,14 @@ describe('updateWithdrawalTransactionIdAndStatusFactory', () => { let withdrawalsContractId; let documentRepositoryMock; let fetchDocumentsMock; - let documentFixture; + let document1Fixture; + let document2Fixture; beforeEach(function beforeEach() { - documentFixture = getDocumentFixture(); + ([document1Fixture, document2Fixture] = getDocumentsFixture()); + + document1Fixture.set('transactionId', Buffer.alloc(32, 1)); + document2Fixture.set('transactionId', Buffer.alloc(32, 3)); withdrawalsContractId = Identifier.from(Buffer.alloc(32)); @@ -21,7 +25,7 @@ describe('updateWithdrawalTransactionIdAndStatusFactory', () => { }; fetchDocumentsMock = this.sinon.stub(); - fetchDocumentsMock.resolves([documentFixture[0]]); + fetchDocumentsMock.resolves([document1Fixture, document2Fixture]); updateWithdrawalTransactionIdAndStatus = updateWithdrawalTransactionIdAndStatusFactory( documentRepositoryMock, @@ -33,14 +37,17 @@ describe('updateWithdrawalTransactionIdAndStatusFactory', () => { it('should update documents transactionId, status and revision', async () => { const blockInfo = new BlockInfo(1, 1, 1); - const updatedTxId = Buffer.alloc(32, 2); const coreChainLockedHeight = 42; + const transactionIdMap = { + [Buffer.alloc(32, 1).toString('hex')]: Buffer.alloc(32, 2), + [Buffer.alloc(32, 3).toString('hex')]: Buffer.alloc(32, 4), + }; + await updateWithdrawalTransactionIdAndStatus( blockInfo, coreChainLockedHeight, - Buffer.alloc(0), - updatedTxId, + transactionIdMap, { useTransaction: true, }, @@ -52,19 +59,28 @@ describe('updateWithdrawalTransactionIdAndStatusFactory', () => { { where: [ ['status', '==', 1], - ['transactionId', '==', Buffer.alloc(0)], + ['transactionId', 'in', [Buffer.alloc(32, 1), Buffer.alloc(32, 3)]], ], useTransaction: true, }, ); - expect(documentRepositoryMock.update).to.have.been.calledOnceWithExactly( - documentFixture[0], blockInfo, { useTransaction: true }, + expect(documentRepositoryMock.update).to.have.been.calledTwice(); + expect(documentRepositoryMock.update.getCall(0).args).to.deep.equal( + [document1Fixture, blockInfo, { useTransaction: true }], ); + expect(documentRepositoryMock.update.getCall(1).args).to.deep.equal( + [document2Fixture, blockInfo, { useTransaction: true }], + ); + + expect(document1Fixture.get('transactionSignHeight')).to.deep.equal(coreChainLockedHeight); + expect(document1Fixture.get('transactionId')).to.deep.equal(Buffer.alloc(32, 2)); + expect(document1Fixture.get('status')).to.deep.equal(2); + expect(document1Fixture.getRevision()).to.deep.equal(2); - expect(documentFixture[0].get('transactionSignHeight')).to.deep.equal(coreChainLockedHeight); - expect(documentFixture[0].get('transactionId')).to.deep.equal(updatedTxId); - expect(documentFixture[0].get('status')).to.deep.equal(2); - expect(documentFixture[0].getRevision()).to.deep.equal(2); + expect(document2Fixture.get('transactionSignHeight')).to.deep.equal(coreChainLockedHeight); + expect(document2Fixture.get('transactionId')).to.deep.equal(Buffer.alloc(32, 4)); + expect(document2Fixture.get('status')).to.deep.equal(2); + expect(document2Fixture.getRevision()).to.deep.equal(2); }); }); diff --git a/packages/rs-dpp/src/identity/state_transition/identity_credit_withdrawal_transition/apply_identity_credit_withdrawal_transition_factory.rs b/packages/rs-dpp/src/identity/state_transition/identity_credit_withdrawal_transition/apply_identity_credit_withdrawal_transition_factory.rs index 92d87fb7992..29e2dac5ff1 100644 --- a/packages/rs-dpp/src/identity/state_transition/identity_credit_withdrawal_transition/apply_identity_credit_withdrawal_transition_factory.rs +++ b/packages/rs-dpp/src/identity/state_transition/identity_credit_withdrawal_transition/apply_identity_credit_withdrawal_transition_factory.rs @@ -107,7 +107,7 @@ where document_type, revision: 0, data_contract_id: *data_contract_id, - owner_id: *data_contract_owner_id, + owner_id: state_transition.identity_id, created_at: Some(document_created_at_millis), updated_at: Some(document_created_at_millis), data: document_data, From 3b61679124b8af0634872aed1760bdd264fd973d Mon Sep 17 00:00:00 2001 From: Djavid Gabibiyan Date: Fri, 17 Feb 2023 16:34:28 +0500 Subject: [PATCH 160/170] chore: do not use contract owner_id for docs --- .../withdrawals_data_triggers/mod.rs | 1 + .../tests/fixtures/get_documents_fixture.rs | 8 ++++-- packages/rs-drive-abci/src/abci/handlers.rs | 4 +++ .../src/identity_credit_withdrawal/mod.rs | 15 +++++++++++ packages/rs-drive-abci/src/state/genesis.rs | 2 -- .../tests/strategy_tests/main.rs | 1 - packages/rs-drive/benches/benchmarks.rs | 1 - .../drive/identity/withdrawals/documents.rs | 25 ++++++++----------- 8 files changed, 37 insertions(+), 20 deletions(-) diff --git a/packages/rs-dpp/src/data_trigger/withdrawals_data_triggers/mod.rs b/packages/rs-dpp/src/data_trigger/withdrawals_data_triggers/mod.rs index 6e55d8b05ec..9517b1122db 100644 --- a/packages/rs-dpp/src/data_trigger/withdrawals_data_triggers/mod.rs +++ b/packages/rs-dpp/src/data_trigger/withdrawals_data_triggers/mod.rs @@ -133,6 +133,7 @@ mod tests { let document = get_withdrawal_document_fixture( &data_contract, + owner_id, json!({ "amount": 1000, "coreFeePerByte": 1, diff --git a/packages/rs-dpp/src/tests/fixtures/get_documents_fixture.rs b/packages/rs-dpp/src/tests/fixtures/get_documents_fixture.rs index 44a8105af35..42d54b33399 100644 --- a/packages/rs-dpp/src/tests/fixtures/get_documents_fixture.rs +++ b/packages/rs-dpp/src/tests/fixtures/get_documents_fixture.rs @@ -110,7 +110,11 @@ fn get_documents( Ok(documents) } -pub fn get_withdrawal_document_fixture(data_contract: &DataContract, data: Value) -> Document { +pub fn get_withdrawal_document_fixture( + data_contract: &DataContract, + owner_id: Identifier, + data: Value, +) -> Document { let factory = DocumentFactory::new( LATEST_VERSION, get_document_validator_fixture(), @@ -120,7 +124,7 @@ pub fn get_withdrawal_document_fixture(data_contract: &DataContract, data: Value factory .create( data_contract.clone(), - data_contract.owner_id, + owner_id, withdrawals_contract::document_types::WITHDRAWAL.to_string(), data, ) diff --git a/packages/rs-drive-abci/src/abci/handlers.rs b/packages/rs-drive-abci/src/abci/handlers.rs index 43b897e6344..5fb3f5f4aae 100644 --- a/packages/rs-drive-abci/src/abci/handlers.rs +++ b/packages/rs-drive-abci/src/abci/handlers.rs @@ -251,6 +251,7 @@ mod tests { use dpp::contracts::withdrawals_contract; use dpp::data_contract::DriveContractExt; use dpp::identity::state_transition::identity_credit_withdrawal_transition::Pooling; + use dpp::prelude::Identifier; use dpp::system_data_contracts::{load_system_data_contract, SystemDataContract}; use dpp::tests::fixtures::get_withdrawal_document_fixture; use dpp::util::hash; @@ -301,11 +302,14 @@ mod tests { .map(|index: u64| (index.to_be_bytes().to_vec(), vec![index as u8; 32])) .collect(); + let owner_id = Identifier::new([1u8; 32]); + for (_, tx_bytes) in withdrawals.iter() { let tx_id = hash::hash(tx_bytes); let document = get_withdrawal_document_fixture( &data_contract, + owner_id, json!({ "amount": 1000, "coreFeePerByte": 1, diff --git a/packages/rs-drive-abci/src/identity_credit_withdrawal/mod.rs b/packages/rs-drive-abci/src/identity_credit_withdrawal/mod.rs index dbe9da09b62..57a5d05e155 100644 --- a/packages/rs-drive-abci/src/identity_credit_withdrawal/mod.rs +++ b/packages/rs-drive-abci/src/identity_credit_withdrawal/mod.rs @@ -552,6 +552,7 @@ mod tests { use crate::test::helpers::setup::setup_platform_with_initial_state_structure; use dpp::{ data_contract::{DataContract, DriveContractExt}, + prelude::Identifier, system_data_contracts::{load_system_data_contract, SystemDataContract}, }; use drive::tests::helpers::setup::setup_system_data_contract; @@ -625,8 +626,11 @@ mod tests { setup_system_data_contract(&platform.drive, &data_contract, Some(&transaction)); + let owner_id = Identifier::new([1u8; 32]); + let document_1 = get_withdrawal_document_fixture( &data_contract, + owner_id, json!({ "amount": 1000, "coreFeePerByte": 1, @@ -653,6 +657,7 @@ mod tests { let document_2 = get_withdrawal_document_fixture( &data_contract, + owner_id, json!({ "amount": 1000, "coreFeePerByte": 1, @@ -731,6 +736,7 @@ mod tests { use dpp::data_contract::DriveContractExt; use dpp::identity::state_transition::identity_credit_withdrawal_transition::Pooling; + use dpp::prelude::Identifier; use dpp::system_data_contracts::{load_system_data_contract, SystemDataContract}; use drive::dpp::contracts::withdrawals_contract; use drive::tests::helpers::setup::setup_system_data_contract; @@ -751,8 +757,11 @@ mod tests { setup_system_data_contract(&platform.drive, &data_contract, Some(&transaction)); + let owner_id = Identifier::new([1u8; 32]); + let document_1 = get_withdrawal_document_fixture( &data_contract, + owner_id, json!({ "amount": 1000, "coreFeePerByte": 1, @@ -777,6 +786,7 @@ mod tests { let document_2 = get_withdrawal_document_fixture( &data_contract, + owner_id, json!({ "amount": 1000, "coreFeePerByte": 1, @@ -913,6 +923,7 @@ mod tests { mod build_withdrawal_transactions_from_documents { use crate::test::helpers::setup::setup_platform_with_initial_state_structure; use dpp::data_contract::DriveContractExt; + use dpp::prelude::Identifier; use dpp::system_data_contracts::{load_system_data_contract, SystemDataContract}; use dpp::{ document::document_stub::DocumentStub, @@ -936,8 +947,11 @@ mod tests { setup_system_data_contract(&platform.drive, &data_contract, Some(&transaction)); + let owner_id = Identifier::new([1u8; 32]); + let document_1 = get_withdrawal_document_fixture( &data_contract, + owner_id, json!({ "amount": 1000, "coreFeePerByte": 1, @@ -962,6 +976,7 @@ mod tests { let document_2 = get_withdrawal_document_fixture( &data_contract, + owner_id, json!({ "amount": 1000, "coreFeePerByte": 1, diff --git a/packages/rs-drive-abci/src/state/genesis.rs b/packages/rs-drive-abci/src/state/genesis.rs index da6b7387e81..46a47fd4dc9 100644 --- a/packages/rs-drive-abci/src/state/genesis.rs +++ b/packages/rs-drive-abci/src/state/genesis.rs @@ -300,8 +300,6 @@ impl Platform { #[cfg(test)] mod tests { - use super::*; - mod create_genesis_state { use crate::test::helpers::setup::setup_platform_with_genesis_state; diff --git a/packages/rs-drive-abci/tests/strategy_tests/main.rs b/packages/rs-drive-abci/tests/strategy_tests/main.rs index 788b88abd7f..4744b9bba30 100644 --- a/packages/rs-drive-abci/tests/strategy_tests/main.rs +++ b/packages/rs-drive-abci/tests/strategy_tests/main.rs @@ -51,7 +51,6 @@ use drive::fee::credits::Credits; use drive::fee_pools::epochs::Epoch; use drive::query::DriveQuery; use drive_abci::abci::handlers::TenderdashAbci; -use drive_abci::abci::messages::{InitChainRequest, SystemIdentityPublicKeys}; use drive_abci::config::PlatformConfig; use drive_abci::execution::engine::ExecutionEvent; use drive_abci::execution::fee_pools::epoch::{EpochInfo, EPOCH_CHANGE_TIME_MS}; diff --git a/packages/rs-drive/benches/benchmarks.rs b/packages/rs-drive/benches/benchmarks.rs index 2f45c04880c..e88c3ac3856 100644 --- a/packages/rs-drive/benches/benchmarks.rs +++ b/packages/rs-drive/benches/benchmarks.rs @@ -39,7 +39,6 @@ use dpp::data_contract::DriveContractExt; use dpp::document::document_stub::DocumentStub; use drive::contract::Contract; use drive::contract::CreateRandomDocument; -use serde::Serialize; criterion_main!(serialization, deserialization); criterion_group!(serialization, test_drive_10_serialization); diff --git a/packages/rs-drive/src/drive/identity/withdrawals/documents.rs b/packages/rs-drive/src/drive/identity/withdrawals/documents.rs index 76c325d593e..85ac07c88ef 100644 --- a/packages/rs-drive/src/drive/identity/withdrawals/documents.rs +++ b/packages/rs-drive/src/drive/identity/withdrawals/documents.rs @@ -40,17 +40,6 @@ impl Drive { let mut where_clauses = BTreeMap::new(); //todo: make this lazy loaded or const - where_clauses.insert( - withdrawals_contract::property_names::OWNER_ID.to_string(), - WhereClause { - field: withdrawals_contract::property_names::OWNER_ID.to_string(), - operator: crate::query::WhereOperator::Equal, - value: ciborium::Value::Bytes( - withdrawals_contract::OWNER_ID.deref().to_buffer().to_vec(), - ), - }, - ); - where_clauses.insert( withdrawals_contract::property_names::STATUS.to_string(), WhereClause { @@ -63,10 +52,10 @@ impl Drive { let mut order_by = IndexMap::new(); order_by.insert( - withdrawals_contract::property_names::CREATE_AT.to_string(), + withdrawals_contract::property_names::UPDATED_AT.to_string(), OrderClause { - field: withdrawals_contract::property_names::CREATE_AT.to_string(), - ascending: false, + field: withdrawals_contract::property_names::UPDATED_AT.to_string(), + ascending: true, }, ); @@ -202,6 +191,7 @@ impl Drive { #[cfg(test)] mod tests { use dpp::contracts::withdrawals_contract; + use dpp::prelude::Identifier; use dpp::tests::fixtures::get_withdrawal_document_fixture; use serde_json::json; @@ -235,8 +225,11 @@ mod tests { assert_eq!(documents.len(), 0); + let owner_id = Identifier::new([1u8; 32]); + let document = get_withdrawal_document_fixture( &data_contract, + owner_id, json!({ "amount": 1000, "coreFeePerByte": 1, @@ -261,6 +254,7 @@ mod tests { let document = get_withdrawal_document_fixture( &data_contract, + owner_id, json!({ "amount": 1000, "coreFeePerByte": 1, @@ -317,8 +311,11 @@ mod tests { setup_system_data_contract(&drive, &data_contract, Some(&transaction)); + let owner_id = Identifier::new([1u8; 32]); + let document = get_withdrawal_document_fixture( &data_contract, + owner_id, json!({ "amount": 1000, "coreFeePerByte": 1, From d889c3f3945b41529856599cae72def8f6657d3b Mon Sep 17 00:00:00 2001 From: Djavid Gabibiyan Date: Fri, 17 Feb 2023 16:58:15 +0500 Subject: [PATCH 161/170] chore: move core rpc module --- Cargo.lock | 3 ++- packages/rs-drive-abci/Cargo.toml | 4 +++- packages/rs-drive-abci/src/abci/handlers.rs | 2 +- .../rs-drive-abci/src/identity_credit_withdrawal/mod.rs | 7 +++++-- packages/rs-drive-abci/src/lib.rs | 3 +++ packages/rs-drive-abci/src/platform.rs | 6 +++--- packages/{rs-drive => rs-drive-abci}/src/rpc/core.rs | 0 packages/{rs-drive => rs-drive-abci}/src/rpc/mod.rs | 0 packages/rs-drive/Cargo.toml | 1 - packages/rs-drive/src/lib.rs | 2 -- 10 files changed, 17 insertions(+), 11 deletions(-) rename packages/{rs-drive => rs-drive-abci}/src/rpc/core.rs (100%) rename packages/{rs-drive => rs-drive-abci}/src/rpc/mod.rs (100%) diff --git a/Cargo.lock b/Cargo.lock index 9afcf7a19db..09bed93e3f8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -981,7 +981,6 @@ dependencies = [ "costs", "criterion", "dashcore", - "dashcore-rpc", "dpp", "enum-map", "grovedb", @@ -1015,10 +1014,12 @@ dependencies = [ "chrono", "ciborium", "dashcore", + "dashcore-rpc", "dpp", "drive", "hex", "itertools", + "mockall", "rand", "rust_decimal", "rust_decimal_macros", diff --git a/packages/rs-drive-abci/Cargo.toml b/packages/rs-drive-abci/Cargo.toml index 6e9600238b9..b650415ddd3 100644 --- a/packages/rs-drive-abci/Cargo.toml +++ b/packages/rs-drive-abci/Cargo.toml @@ -19,12 +19,14 @@ bs58 = "0.4.0" base64 = "0.13.0" hex = "0.4.3" dashcore = { git="https://github.com/dashevo/rust-dashcore", features=["std", "secp-recovery", "rand", "signer", "use-serde"], default-features = false, rev = "51548a4a1b9eca7430f5f3caf94d9784886ff2e9" } +dashcore-rpc = { git="https://github.com/jawid-h/rust-dashcore-rpc", branch="fix/attempt-to-fix" } dpp = { path = "../rs-dpp", features = ["fixtures-and-mocks"]} rust_decimal = "1.2.5" rust_decimal_macros = "1.25.0" +mockall= { version ="0.11", optional = true } [dev-dependencies] itertools = { version = "0.10.5" } [features] -fixtures-and-mocks = [] +fixtures-and-mocks = ["mockall"] diff --git a/packages/rs-drive-abci/src/abci/handlers.rs b/packages/rs-drive-abci/src/abci/handlers.rs index 5fb3f5f4aae..73d957d64ab 100644 --- a/packages/rs-drive-abci/src/abci/handlers.rs +++ b/packages/rs-drive-abci/src/abci/handlers.rs @@ -245,6 +245,7 @@ mod tests { mod handlers { use crate::abci::handlers::TenderdashAbci; use crate::config::PlatformConfig; + use crate::rpc::core::MockCoreRPCLike; use chrono::{Duration, Utc}; use dashcore::hashes::hex::FromHex; use dashcore::BlockHash; @@ -260,7 +261,6 @@ mod tests { use drive::drive::identity::withdrawals::WithdrawalTransactionIdAndBytes; use drive::fee::epoch::CreditsPerEpoch; use drive::fee_pools::epochs::Epoch; - use drive::rpc::core::MockCoreRPCLike; use drive::tests::helpers::setup::setup_document; use rust_decimal::prelude::ToPrimitive; use serde_json::json; diff --git a/packages/rs-drive-abci/src/identity_credit_withdrawal/mod.rs b/packages/rs-drive-abci/src/identity_credit_withdrawal/mod.rs index 57a5d05e155..22a1dc31dab 100644 --- a/packages/rs-drive-abci/src/identity_credit_withdrawal/mod.rs +++ b/packages/rs-drive-abci/src/identity_credit_withdrawal/mod.rs @@ -538,12 +538,15 @@ mod tests { BlockHash, }; use dpp::{contracts::withdrawals_contract, tests::fixtures::get_withdrawal_document_fixture}; - use drive::{rpc::core::MockCoreRPCLike, tests::helpers::setup::setup_document}; + use drive::tests::helpers::setup::setup_document; use serde_json::json; use dpp::identity::state_transition::identity_credit_withdrawal_transition::Pooling; - use crate::{block::BlockExecutionContext, execution::fee_pools::epoch::EpochInfo}; + use crate::{ + block::BlockExecutionContext, execution::fee_pools::epoch::EpochInfo, + rpc::core::MockCoreRPCLike, + }; mod update_withdrawal_statuses { use std::cell::RefCell; diff --git a/packages/rs-drive-abci/src/lib.rs b/packages/rs-drive-abci/src/lib.rs index c7bf00d3db0..ffd140c4684 100644 --- a/packages/rs-drive-abci/src/lib.rs +++ b/packages/rs-drive-abci/src/lib.rs @@ -40,6 +40,9 @@ pub mod state; /// Platform constants pub mod constants; +/// Anything related to 3rd party RPC +pub mod rpc; + // TODO We should compile it only for tests /// Test helpers and fixtures pub mod test; diff --git a/packages/rs-drive-abci/src/platform.rs b/packages/rs-drive-abci/src/platform.rs index e545f01d369..da4a29fea67 100644 --- a/packages/rs-drive-abci/src/platform.rs +++ b/packages/rs-drive-abci/src/platform.rs @@ -34,21 +34,21 @@ use crate::block::BlockExecutionContext; use crate::config::PlatformConfig; use crate::error::execution::ExecutionError; use crate::error::Error; +use crate::rpc::core::{CoreRPCLike, DefaultCoreRPC}; use crate::state::PlatformState; use drive::drive::Drive; -use drive::rpc::core::{CoreRPCLike, DefaultCoreRPC}; use drive::drive::defaults::PROTOCOL_VERSION; use std::cell::RefCell; use std::path::Path; +#[cfg(feature = "fixtures-and-mocks")] +use crate::rpc::core::MockCoreRPCLike; #[cfg(feature = "fixtures-and-mocks")] use dashcore::hashes::hex::FromHex; #[cfg(feature = "fixtures-and-mocks")] use dashcore::BlockHash; #[cfg(feature = "fixtures-and-mocks")] -use drive::rpc::core::MockCoreRPCLike; -#[cfg(feature = "fixtures-and-mocks")] use serde_json::json; /// Platform diff --git a/packages/rs-drive/src/rpc/core.rs b/packages/rs-drive-abci/src/rpc/core.rs similarity index 100% rename from packages/rs-drive/src/rpc/core.rs rename to packages/rs-drive-abci/src/rpc/core.rs diff --git a/packages/rs-drive/src/rpc/mod.rs b/packages/rs-drive-abci/src/rpc/mod.rs similarity index 100% rename from packages/rs-drive/src/rpc/mod.rs rename to packages/rs-drive-abci/src/rpc/mod.rs diff --git a/packages/rs-drive/Cargo.toml b/packages/rs-drive/Cargo.toml index 0861db550ea..9aa12d383d2 100644 --- a/packages/rs-drive/Cargo.toml +++ b/packages/rs-drive/Cargo.toml @@ -31,7 +31,6 @@ bincode = "1.3.3" dpp = { path = "../rs-dpp", features = ["fixtures-and-mocks"]} itertools = { version = "0.10.5" } dashcore = { git="https://github.com/dashevo/rust-dashcore", features=["std", "secp-recovery", "rand", "signer", "use-serde"], default-features = false, rev = "51548a4a1b9eca7430f5f3caf94d9784886ff2e9" } -dashcore-rpc = { git="https://github.com/jawid-h/rust-dashcore-rpc", branch="fix/attempt-to-fix" } mockall= { version ="0.11", optional = true } rust_decimal = "1.2.5" rust_decimal_macros = "1.25.0" diff --git a/packages/rs-drive/src/lib.rs b/packages/rs-drive/src/lib.rs index 723438e7603..0855f8cdd0a 100644 --- a/packages/rs-drive/src/lib.rs +++ b/packages/rs-drive/src/lib.rs @@ -23,8 +23,6 @@ pub mod fee; pub mod fee_pools; /// Query module pub mod query; -/// Everything related to RPC -pub mod rpc; /// DPP module pub use dpp; From 3f24d1bc13ec8c62854da1cb83c53871a3c4c9c1 Mon Sep 17 00:00:00 2001 From: Djavid Gabibiyan Date: Fri, 17 Feb 2023 17:50:13 +0500 Subject: [PATCH 162/170] chore: make features default for now --- packages/rs-dpp/Cargo.toml | 1 + packages/rs-drive-abci/Cargo.toml | 1 + packages/rs-drive/Cargo.toml | 1 + 3 files changed, 3 insertions(+) diff --git a/packages/rs-dpp/Cargo.toml b/packages/rs-dpp/Cargo.toml index b603260f984..4b8b3f6a163 100644 --- a/packages/rs-dpp/Cargo.toml +++ b/packages/rs-dpp/Cargo.toml @@ -45,4 +45,5 @@ tokio = { version ="1.17", features=["full"]} pretty_assertions = { version="1.3.0"} [features] +default = ["fixtures-and-mocks"] fixtures-and-mocks = ["mockall"] diff --git a/packages/rs-drive-abci/Cargo.toml b/packages/rs-drive-abci/Cargo.toml index b650415ddd3..7dd2cf1d962 100644 --- a/packages/rs-drive-abci/Cargo.toml +++ b/packages/rs-drive-abci/Cargo.toml @@ -29,4 +29,5 @@ mockall= { version ="0.11", optional = true } itertools = { version = "0.10.5" } [features] +default = ["fixtures-and-mocks"] fixtures-and-mocks = ["mockall"] diff --git a/packages/rs-drive/Cargo.toml b/packages/rs-drive/Cargo.toml index 9aa12d383d2..50cec9736e6 100644 --- a/packages/rs-drive/Cargo.toml +++ b/packages/rs-drive/Cargo.toml @@ -56,4 +56,5 @@ name = "benchmarks" harness = false [features] +default = ["fixtures-and-mocks"] fixtures-and-mocks = ["mockall"] From db55d19f9aecac294a7bfe1a7acec7021dcc7683 Mon Sep 17 00:00:00 2001 From: Djavid Gabibiyan Date: Fri, 17 Feb 2023 18:45:59 +0500 Subject: [PATCH 163/170] chore: remove default features for wasm-dpp --- packages/wasm-dpp/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/wasm-dpp/Cargo.toml b/packages/wasm-dpp/Cargo.toml index 8780683152e..dd675122cc2 100644 --- a/packages/wasm-dpp/Cargo.toml +++ b/packages/wasm-dpp/Cargo.toml @@ -15,7 +15,7 @@ js-sys = "0.3.53" web-sys = { version = "0.3.6", features = ["console"] } thiserror = { version = "1.0" } serde-wasm-bindgen = "0.4.3" -dpp = { path = "../rs-dpp" } +dpp = { path = "../rs-dpp", default-features = false } itertools = { version="0.10.5"} console_error_panic_hook = { version="0.1.7"} From 1027be661ef4d4f99d22d894a9a7ce75ec485df2 Mon Sep 17 00:00:00 2001 From: Djavid Gabibiyan Date: Fri, 17 Feb 2023 19:05:31 +0500 Subject: [PATCH 164/170] chore: missing owner_id --- .../apply_identity_credit_withdrawal_transition_factory.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/rs-dpp/src/identity/state_transition/identity_credit_withdrawal_transition/apply_identity_credit_withdrawal_transition_factory.rs b/packages/rs-dpp/src/identity/state_transition/identity_credit_withdrawal_transition/apply_identity_credit_withdrawal_transition_factory.rs index 29e2dac5ff1..98971882efe 100644 --- a/packages/rs-dpp/src/identity/state_transition/identity_credit_withdrawal_transition/apply_identity_credit_withdrawal_transition_factory.rs +++ b/packages/rs-dpp/src/identity/state_transition/identity_credit_withdrawal_transition/apply_identity_credit_withdrawal_transition_factory.rs @@ -76,7 +76,7 @@ where document_id = generate_document_id::generate_document_id( data_contract_id, - data_contract_owner_id, + &state_transition.identity_id, &document_type, &document_entropy, ); From c68a9c3d5c615b11253981223718e9169af727a3 Mon Sep 17 00:00:00 2001 From: Djavid Gabibiyan Date: Fri, 17 Feb 2023 19:10:56 +0500 Subject: [PATCH 165/170] chore: remove --all-features --- .github/workflows/rs-checks.yml | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/.github/workflows/rs-checks.yml b/.github/workflows/rs-checks.yml index c2d8226d912..c5ef4b491ef 100644 --- a/.github/workflows/rs-checks.yml +++ b/.github/workflows/rs-checks.yml @@ -29,7 +29,6 @@ jobs: - uses: actions-rs/clippy-check@v1 with: token: ${{ secrets.GITHUB_TOKEN }} - args: --all-features formatting: name: Formatting @@ -64,7 +63,7 @@ jobs: - name: Enable Rust cache uses: Swatinem/rust-cache@v2 - - run: cargo check --package=${{ inputs.package }} --all-features + - run: cargo check --package=${{ inputs.package }} test: name: Tests @@ -84,4 +83,4 @@ jobs: uses: Swatinem/rust-cache@v2 - name: Run tests - run: cargo test --package=${{ inputs.package }} --all-features + run: cargo test --package=${{ inputs.package }} From af032db1994b50e2cb1ce7b19294c254cc73f537 Mon Sep 17 00:00:00 2001 From: Djavid Gabibiyan Date: Fri, 17 Feb 2023 20:01:26 +0500 Subject: [PATCH 166/170] chore: misc --- .github/workflows/rs-checks.yml | 3 ++- .../apply_identity_credit_withdrawal_transition_factory.rs | 1 - 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/rs-checks.yml b/.github/workflows/rs-checks.yml index c5ef4b491ef..50e379f7729 100644 --- a/.github/workflows/rs-checks.yml +++ b/.github/workflows/rs-checks.yml @@ -29,6 +29,7 @@ jobs: - uses: actions-rs/clippy-check@v1 with: token: ${{ secrets.GITHUB_TOKEN }} + args: --all-features formatting: name: Formatting @@ -83,4 +84,4 @@ jobs: uses: Swatinem/rust-cache@v2 - name: Run tests - run: cargo test --package=${{ inputs.package }} + run: cargo test --package=${{ inputs.package }} --all-features diff --git a/packages/rs-dpp/src/identity/state_transition/identity_credit_withdrawal_transition/apply_identity_credit_withdrawal_transition_factory.rs b/packages/rs-dpp/src/identity/state_transition/identity_credit_withdrawal_transition/apply_identity_credit_withdrawal_transition_factory.rs index 98971882efe..b17f11f0505 100644 --- a/packages/rs-dpp/src/identity/state_transition/identity_credit_withdrawal_transition/apply_identity_credit_withdrawal_transition_factory.rs +++ b/packages/rs-dpp/src/identity/state_transition/identity_credit_withdrawal_transition/apply_identity_credit_withdrawal_transition_factory.rs @@ -37,7 +37,6 @@ where state_transition: &IdentityCreditWithdrawalTransition, ) -> Result<()> { let data_contract_id = withdrawals_contract::CONTRACT_ID.deref(); - let data_contract_owner_id = withdrawals_contract::OWNER_ID.deref(); let maybe_withdrawals_data_contract: Option = self .state_repository From 92370f1a3b822dad695dabc4ffc139408ad47dfc Mon Sep 17 00:00:00 2001 From: Djavid Gabibiyan Date: Fri, 17 Feb 2023 21:33:14 +0500 Subject: [PATCH 167/170] chore: yarn reorder --- packages/rs-drive-nodejs/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/rs-drive-nodejs/package.json b/packages/rs-drive-nodejs/package.json index 2298bca6997..7fc523c135b 100644 --- a/packages/rs-drive-nodejs/package.json +++ b/packages/rs-drive-nodejs/package.json @@ -17,8 +17,8 @@ ], "license": "MIT", "devDependencies": { - "@dashevo/withdrawals-contract": "workspace:*", "@dashevo/dashcore-lib": "github:dashevo/dashcore-lib#3527419e8739b5e7d4017028d642dba8851c3e25", + "@dashevo/withdrawals-contract": "workspace:*", "chai": "^4.3.4", "dirty-chai": "^2.0.1", "eslint": "^7.32.0", From 69541d8fcceefbb338d75c076d86ddaa6464e182 Mon Sep 17 00:00:00 2001 From: Djavid Gabibiyan Date: Fri, 17 Feb 2023 21:38:53 +0500 Subject: [PATCH 168/170] chore: change hashes --- ...ynchronizeMasternodeIdentitiesFactory.spec.js | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/packages/js-drive/test/integration/identity/masternode/synchronizeMasternodeIdentitiesFactory.spec.js b/packages/js-drive/test/integration/identity/masternode/synchronizeMasternodeIdentitiesFactory.spec.js index 049aaa64373..34c02f709e4 100644 --- a/packages/js-drive/test/integration/identity/masternode/synchronizeMasternodeIdentitiesFactory.spec.js +++ b/packages/js-drive/test/integration/identity/masternode/synchronizeMasternodeIdentitiesFactory.spec.js @@ -364,7 +364,7 @@ describe('synchronizeMasternodeIdentitiesFactory', function main() { beforeEach(async function beforeEach() { coreHeight = 3; - firstSyncAppHash = '3faf41663866d5a66eb73c504861136233e2b10ae60c459f39573726786b2bd9'; + firstSyncAppHash = 'c55de453e3ea4481f20225efdc12d671f715f0618cf3084bb32e56e75123bfdd'; blockInfo = new BlockInfo(10, 0, 1668702100799); container = await createTestDIContainer(); @@ -684,7 +684,7 @@ describe('synchronizeMasternodeIdentitiesFactory', function main() { // Nothing happened - await expectDeterministicAppHash('1bc066ff1f1ab91cac098ebdfb396f435336e6e3337dabf13c7bc3757a591507'); + await expectDeterministicAppHash('a789fe73ceea6769634b98ae82dddad5013c4711b2a8353d2150b813fb953cb3'); // Core RPC should be called @@ -720,7 +720,7 @@ describe('synchronizeMasternodeIdentitiesFactory', function main() { expect(result2.updatedEntities).to.have.lengthOf(0); expect(result2.removedEntities).to.have.lengthOf(0); - await expectDeterministicAppHash('ca0cee6a797d8707cfd48277b2421573f883f38b6c89b3debd47fe0b0cb195eb'); + await expectDeterministicAppHash('b58bc0499156caea9b930ab0e357f56b20bb191bc7ba97a2eb8941d9ba7a8183'); // New masternode identity should be created @@ -804,7 +804,7 @@ describe('synchronizeMasternodeIdentitiesFactory', function main() { expect(result.updatedEntities).to.have.lengthOf(0); expect(result.removedEntities).to.have.lengthOf(1); - await expectDeterministicAppHash('f9b6d7f3358b6e2ab4d6bcddf41592ad93cc07f0d3a7d6664f383e261e84f5e7'); + await expectDeterministicAppHash('ea28d7339efd80984e53bd06b0d3708611f24862f401997e9cd69328af6a54c2'); // Masternode identity should stay @@ -872,7 +872,7 @@ describe('synchronizeMasternodeIdentitiesFactory', function main() { expect(result.updatedEntities).to.have.lengthOf(0); expect(result.removedEntities).to.have.lengthOf(1); - await expectDeterministicAppHash('f9b6d7f3358b6e2ab4d6bcddf41592ad93cc07f0d3a7d6664f383e261e84f5e7'); + await expectDeterministicAppHash('ea28d7339efd80984e53bd06b0d3708611f24862f401997e9cd69328af6a54c2'); const invalidMasternodeIdentifier = Identifier.from( Buffer.from(invalidSmlEntry.proRegTxHash, 'hex'), @@ -922,7 +922,7 @@ describe('synchronizeMasternodeIdentitiesFactory', function main() { expect(result.updatedEntities).to.have.lengthOf(1); expect(result.removedEntities).to.have.lengthOf(1); - await expectDeterministicAppHash('a582e896e609e333b2e0b208040377330d8114031429c09c5ae7fc21b21573b9'); + await expectDeterministicAppHash('d80a3bbf5e699a0295e4ba734e3729d12bef3001bdd9cdd295673832d05454cf'); // Masternode identity should stay @@ -997,7 +997,7 @@ describe('synchronizeMasternodeIdentitiesFactory', function main() { await synchronizeMasternodeIdentities(coreHeight + 1, blockInfo); - await expectDeterministicAppHash('1f6ff4c65a9eee17877dfdc20c9569c47d4b0d901f2a40ea933fcc6a852055b8'); + await expectDeterministicAppHash('cfc8c439d00c2afab01594dc699ef71c8b23cff66b0302794d3c6b88c44d687c'); // Masternode identity should contain new public key @@ -1079,7 +1079,7 @@ describe('synchronizeMasternodeIdentitiesFactory', function main() { // Initial sync await synchronizeMasternodeIdentities(coreHeight, blockInfo); - await expectDeterministicAppHash('a57d1dfac825f23f518f5d48d41f9e786ac7018da4993cdf5255c27846bfac55'); + await expectDeterministicAppHash('7a5729e3511c5cc98e8452faa6132f0d600e04fef85df0f95f56e59c776de170'); const votingIdentifier = createVotingIdentifier(smlFixture[0]); const votingIdentityResult = await identityRepository.fetch( From 799e757ed64d60f7f687e0e374219f286a6b0f02 Mon Sep 17 00:00:00 2001 From: Djavid Gabibiyan Date: Sat, 18 Feb 2023 01:01:17 +0500 Subject: [PATCH 169/170] chore: fixing query and ordering --- .../handlers/finalizeBlockHandlerFactory.js | 24 +++++++++---------- ...WithdrawalTransactionIdAndStatusFactory.js | 9 ++++++- ...rawalTransactionIdAndStatusFactory.spec.js | 2 +- 3 files changed, 21 insertions(+), 14 deletions(-) diff --git a/packages/js-drive/lib/abci/handlers/finalizeBlockHandlerFactory.js b/packages/js-drive/lib/abci/handlers/finalizeBlockHandlerFactory.js index d574d84996e..1d3dfdaf4fb 100644 --- a/packages/js-drive/lib/abci/handlers/finalizeBlockHandlerFactory.js +++ b/packages/js-drive/lib/abci/handlers/finalizeBlockHandlerFactory.js @@ -97,6 +97,18 @@ function finalizeBlockHandlerFactory( await processProposal(processProposalRequest, contextLogger); } + // Send withdrawal transactions to Core + const unsignedWithdrawalTransactionsMap = proposalBlockExecutionContext + .getWithdrawalTransactionsMap(); + + const { thresholdVoteExtensions } = commitInfo; + + await broadcastWithdrawalTransactions( + proposalBlockExecutionContext, + thresholdVoteExtensions, + unsignedWithdrawalTransactionsMap, + ); + proposalBlockExecutionContext.setLastCommitInfo(commitInfo); // Store proposal block execution context @@ -113,18 +125,6 @@ function finalizeBlockHandlerFactory( // Update last block execution context with proposal data latestBlockExecutionContext.populate(proposalBlockExecutionContext); - // Send withdrawal transactions to Core - const unsignedWithdrawalTransactionsMap = proposalBlockExecutionContext - .getWithdrawalTransactionsMap(); - - const { thresholdVoteExtensions } = commitInfo; - - await broadcastWithdrawalTransactions( - proposalBlockExecutionContext, - thresholdVoteExtensions, - unsignedWithdrawalTransactionsMap, - ); - proposalBlockExecutionContext.reset(); const blockExecutionTimings = executionTimer.stopTimer('blockExecution'); diff --git a/packages/js-drive/lib/identity/withdrawals/updateWithdrawalTransactionIdAndStatusFactory.js b/packages/js-drive/lib/identity/withdrawals/updateWithdrawalTransactionIdAndStatusFactory.js index 95941f7024c..abd8b2c562e 100644 --- a/packages/js-drive/lib/identity/withdrawals/updateWithdrawalTransactionIdAndStatusFactory.js +++ b/packages/js-drive/lib/identity/withdrawals/updateWithdrawalTransactionIdAndStatusFactory.js @@ -1,4 +1,4 @@ -const WITHDRAWALS_DOCUMENT_TYPE = 'withdrawals'; +const WITHDRAWALS_DOCUMENT_TYPE = 'withdrawal'; const WITHDRAWALS_STATUS_POOLED = 1; const WITHDRAWALS_STATUS_BROADCASTED = 2; @@ -35,11 +35,18 @@ function updateWithdrawalTransactionIdAndStatusFactory( ) { const originalTransactionIds = Object.keys(transactionIdMap).map((key) => Buffer.from(key, 'hex')); + if (originalTransactionIds.length === 0) { + return; + } + const fetchOptions = { where: [ ['status', '==', WITHDRAWALS_STATUS_POOLED], ['transactionId', 'in', originalTransactionIds], ], + orderBy: [ + ['transactionId', 'asc'], + ], ...options, }; diff --git a/packages/js-drive/test/unit/identity/withdrawals/updateWithdrawalTransactionIdAndStatusFactory.spec.js b/packages/js-drive/test/unit/identity/withdrawals/updateWithdrawalTransactionIdAndStatusFactory.spec.js index ce841b54c02..a6e568e7a22 100644 --- a/packages/js-drive/test/unit/identity/withdrawals/updateWithdrawalTransactionIdAndStatusFactory.spec.js +++ b/packages/js-drive/test/unit/identity/withdrawals/updateWithdrawalTransactionIdAndStatusFactory.spec.js @@ -55,7 +55,7 @@ describe('updateWithdrawalTransactionIdAndStatusFactory', () => { expect(fetchDocumentsMock).to.have.been.calledOnceWithExactly( withdrawalsContractId, - 'withdrawals', + 'withdrawal', { where: [ ['status', '==', 1], From 5c136594f3ab579733854a1b0e1cded2959523fc Mon Sep 17 00:00:00 2001 From: Djavid Gabibiyan Date: Sat, 18 Feb 2023 01:36:48 +0500 Subject: [PATCH 170/170] chore: fix test case --- .../updateWithdrawalTransactionIdAndStatusFactory.spec.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/packages/js-drive/test/unit/identity/withdrawals/updateWithdrawalTransactionIdAndStatusFactory.spec.js b/packages/js-drive/test/unit/identity/withdrawals/updateWithdrawalTransactionIdAndStatusFactory.spec.js index a6e568e7a22..1985b1b1623 100644 --- a/packages/js-drive/test/unit/identity/withdrawals/updateWithdrawalTransactionIdAndStatusFactory.spec.js +++ b/packages/js-drive/test/unit/identity/withdrawals/updateWithdrawalTransactionIdAndStatusFactory.spec.js @@ -61,6 +61,9 @@ describe('updateWithdrawalTransactionIdAndStatusFactory', () => { ['status', '==', 1], ['transactionId', 'in', [Buffer.alloc(32, 1), Buffer.alloc(32, 3)]], ], + orderBy: [ + ['transactionId', 'asc'], + ], useTransaction: true, }, );