feat: move VM2 to a plugin (#393)

This commit is contained in:
Asia
2023-04-17 14:34:01 +02:00
committed by GitHub
parent 830104fe5a
commit f1b4b3da73
13 changed files with 72 additions and 117 deletions

View File

@@ -13,6 +13,8 @@ jobs:
version: 'latest' version: 'latest'
- name: Install modules - name: Install modules
run: yarn run: yarn
- name: Build package
run: yarn build
- name: Run unit tests - name: Run unit tests
run: yarn test:unit run: yarn test:unit
- name: Run integration tests [basic] - name: Run integration tests [basic]
@@ -24,7 +26,7 @@ jobs:
- name: Run regression tests - name: Run regression tests
run: yarn test:regression run: yarn test:regression
- name: Test example rust contracts - name: Test example rust contracts
run: yarn build && yarn build:test:wasm run: yarn build:test:wasm
- name: Trigger integration tests - name: Trigger integration tests
if: github.ref_name == 'main' if: github.ref_name == 'main'
run: > run: >
@@ -35,4 +37,3 @@ jobs:
-H "X-GitHub-Api-Version: 2022-11-28" -H "X-GitHub-Api-Version: 2022-11-28"
https://api.github.com/repos/warp-contracts/warp-integration-tests/dispatches https://api.github.com/repos/warp-contracts/warp-integration-tests/dispatches
-d '{"event_type":"sdk_push","client_payload":{"ref":"${{github.ref}}","sha":"${{github.sha}}"}}' -d '{"event_type":"sdk_push","client_payload":{"ref":"${{github.ref}}","sha":"${{github.sha}}"}}'

View File

@@ -20,6 +20,8 @@
"build:types": "tsc -b tsconfig.types.json", "build:types": "tsc -b tsconfig.types.json",
"bundle": "node bundle.js", "bundle": "node bundle.js",
"build": "yarn run clean && yarn build:cjs && yarn build:mjs && yarn mjs:burn:in:hell && yarn build:types && yarn bundle", "build": "yarn run clean && yarn build:cjs && yarn build:mjs && yarn mjs:burn:in:hell && yarn build:types && yarn bundle",
"install:warp": "yarn add -D warp-contracts@file:./lib/cjs",
"remove:warp": "yarn remove warp-contracts",
"format": "prettier --write 'src/**/*.ts'", "format": "prettier --write 'src/**/*.ts'",
"clean": "rimraf ./lib", "clean": "rimraf ./lib",
"lint": "eslint . --ext .ts --max-warnings=0", "lint": "eslint . --ext .ts --max-warnings=0",
@@ -30,17 +32,18 @@
"version": "yarn format && git add -A src", "version": "yarn format && git add -A src",
"postversion": "git push origin HEAD && git push --tags", "postversion": "git push origin HEAD && git push --tags",
"yalc:publish": "yarn build && yalc publish --push", "yalc:publish": "yarn build && yalc publish --push",
"test": "jest", "argument": "echo \"The value of --foo is ${file} end of script\"",
"test:unit": "jest ./src/__tests__/unit", "test": "yarn install:warp && jest ${file} && yarn remove:warp",
"test:unit:cache": "jest ./src/__tests__/unit/cache-leveldb.test.ts", "test:unit": "file=./src/__tests__/unit yarn test",
"test:unit:cache:real": "jest ./src/__tests__/unit/cache-leveldb-real-data.test.ts", "test:unit:cache": "file=./src/__tests__/unit/cache-leveldb.test.ts yarn test",
"test:integration": "jest ./src/__tests__/integration", "test:unit:cache:real": "file=./src/__tests__/unit/cache-leveldb-real-data.test.ts yarn test",
"test:integration:basic": "jest ./src/__tests__/integration/basic", "test:integration": "file=./src/__tests__/integration yarn test",
"test:integration:basic:load": "jest --silent=false --detectOpenHandles ./src/__tests__/integration/basic/contract-loading.test.ts ", "test:integration:basic": "file=./src/__tests__/integration/basic yarn test",
"test:integration:basic:arweave": "jest ./src/__tests__/integration/basic/arweave-transactions-loading", "test:integration:basic:load": "--silent=false --detectOpenHandles file=./src/__tests__/integration/basic/contract-loading.test.ts yarn test",
"test:integration:internal-writes": "jest ./src/__tests__/integration/internal-writes", "test:integration:basic:arweave": "file=./src/__tests__/integration/basic/arweave-transactions-loading yarn test",
"test:integration:wasm": "jest ./src/__tests__/integration/wasm", "test:integration:internal-writes": "file=./src/__tests__/integration/internal-writes yarn test",
"test:regression": "node ./node_modules/.bin/jest ./src/__tests__/regression", "test:integration:wasm": "file=./src/__tests__/integration/wasm yarn test",
"test:regression": "yarn install:warp && node ./node_modules/.bin/jest ./src/__tests__/regression && yarn remove:warp",
"build:toy-contract": "wasm-pack build --target nodejs --dev --out-name rust-contract crates/toy-contract", "build:toy-contract": "wasm-pack build --target nodejs --dev --out-name rust-contract crates/toy-contract",
"test:toy-contract": "jest crates/toy-contract/tests", "test:toy-contract": "jest crates/toy-contract/tests",
"build:pst": "wasm-pack build --target nodejs --dev --out-name rust-contract crates/pst/contract/implementation", "build:pst": "wasm-pack build --target nodejs --dev --out-name rust-contract crates/pst/contract/implementation",
@@ -50,7 +53,7 @@
"format:json-bindings:pst": "eslint 'crates/pst/contract/definition/bindings/json/*.json' --fix", "format:json-bindings:pst": "eslint 'crates/pst/contract/definition/bindings/json/*.json' --fix",
"format:ts-bindings:pst": "eslint 'crates/pst/contract/definition/bindings/ts/*.ts' --fix", "format:ts-bindings:pst": "eslint 'crates/pst/contract/definition/bindings/ts/*.ts' --fix",
"test:pst": "jest crates/pst/tests", "test:pst": "jest crates/pst/tests",
"build:test:wasm": "yarn build:toy-contract && yarn test:toy-contract && yarn build:pst && yarn gen-bindings:pst && yarn test:pst" "build:test:wasm": "yarn install:warp && yarn build:toy-contract && yarn test:toy-contract && yarn build:pst && yarn gen-bindings:pst && yarn test:pst"
}, },
"license": "MIT", "license": "MIT",
"author": "Redstone Team <dev@redstone.finance>", "author": "Redstone Team <dev@redstone.finance>",
@@ -88,7 +91,6 @@
"safe-stable-stringify": "2.4.1", "safe-stable-stringify": "2.4.1",
"stream-buffers": "^3.0.2", "stream-buffers": "^3.0.2",
"unzipit": "^1.4.0", "unzipit": "^1.4.0",
"vm2": "3.9.15",
"warp-isomorphic": "1.0.4", "warp-isomorphic": "1.0.4",
"warp-wasm-metering": "1.0.1" "warp-wasm-metering": "1.0.1"
}, },
@@ -114,7 +116,8 @@
"ts-jest": "^28.0.7", "ts-jest": "^28.0.7",
"ts-node": "^10.2.1", "ts-node": "^10.2.1",
"typescript": "^4.9.5", "typescript": "^4.9.5",
"warp-contracts-plugin-deploy": "1.0.0-beta.16", "warp-contracts-plugin-deploy": "^1.0.3",
"warp-contracts-plugin-vm2": "1.0.0",
"ws": "^8.11.0" "ws": "^8.11.0"
}, },
"resolutions": { "resolutions": {
@@ -131,7 +134,6 @@
"fs": false, "fs": false,
"path": false, "path": false,
"crypto": false, "crypto": false,
"vm2": false,
"archiver": false, "archiver": false,
"stream-buffers": false, "stream-buffers": false,
"constants": false, "constants": false,

View File

@@ -9,9 +9,11 @@ import { Warp } from '../../../core/Warp';
import { WarpFactory } from '../../../core/WarpFactory'; import { WarpFactory } from '../../../core/WarpFactory';
import { LoggerFactory } from '../../../logging/LoggerFactory'; import { LoggerFactory } from '../../../logging/LoggerFactory';
import { DeployPlugin } from 'warp-contracts-plugin-deploy'; import { DeployPlugin } from 'warp-contracts-plugin-deploy';
import { VM2Plugin } from 'warp-contracts-plugin-vm2';
let arlocal: ArLocal; let arlocal: ArLocal;
let warp: Warp; let warp: Warp;
let warpVm: Warp;
let contract: Contract<any>; let contract: Contract<any>;
let contractVM: Contract<any>; let contractVM: Contract<any>;
@@ -29,6 +31,7 @@ describe('Testing the Warp client', () => {
LoggerFactory.INST.logLevel('error'); LoggerFactory.INST.logLevel('error');
warp = WarpFactory.forLocal(1800).use(new DeployPlugin()); warp = WarpFactory.forLocal(1800).use(new DeployPlugin());
warpVm = WarpFactory.forLocal(1800).use(new DeployPlugin()).use(new VM2Plugin());
({ jwk: wallet } = await warp.generateWallet()); ({ jwk: wallet } = await warp.generateWallet());
contractSrc = fs.readFileSync(path.join(__dirname, '../data/very-complicated-contract.js'), 'utf8'); contractSrc = fs.readFileSync(path.join(__dirname, '../data/very-complicated-contract.js'), 'utf8');
@@ -43,8 +46,7 @@ describe('Testing the Warp client', () => {
contract = warp.contract(contractTxId).setEvaluationOptions({ contract = warp.contract(contractTxId).setEvaluationOptions({
mineArLocalBlocks: false mineArLocalBlocks: false
}); });
contractVM = warp.contract(contractTxId).setEvaluationOptions({ contractVM = warpVm.contract(contractTxId).setEvaluationOptions({
useVM2: true,
mineArLocalBlocks: false mineArLocalBlocks: false
}); });
contract.connect(wallet); contract.connect(wallet);

View File

@@ -9,6 +9,7 @@ import { Warp } from '../../../core/Warp';
import { WarpFactory } from '../../../core/WarpFactory'; import { WarpFactory } from '../../../core/WarpFactory';
import { LoggerFactory } from '../../../logging/LoggerFactory'; import { LoggerFactory } from '../../../logging/LoggerFactory';
import { DeployPlugin } from 'warp-contracts-plugin-deploy'; import { DeployPlugin } from 'warp-contracts-plugin-deploy';
import { VM2Plugin } from 'warp-contracts-plugin-vm2';
interface ExampleContractState { interface ExampleContractState {
counter: number; counter: number;
@@ -31,6 +32,7 @@ describe('Testing the Warp client', () => {
let arlocal: ArLocal; let arlocal: ArLocal;
let warp: Warp; let warp: Warp;
let warpVm: Warp;
let contract: Contract<ExampleContractState>; let contract: Contract<ExampleContractState>;
let contractInitData: Contract<ExampleContractState>; let contractInitData: Contract<ExampleContractState>;
let contractVM: Contract<ExampleContractState>; let contractVM: Contract<ExampleContractState>;
@@ -43,6 +45,7 @@ describe('Testing the Warp client', () => {
LoggerFactory.INST.logLevel('error'); LoggerFactory.INST.logLevel('error');
warp = WarpFactory.forLocal(1810).use(new DeployPlugin()); warp = WarpFactory.forLocal(1810).use(new DeployPlugin());
warpVm = WarpFactory.forLocal(1810).use(new DeployPlugin()).use(new VM2Plugin());
({ jwk: wallet } = await warp.generateWallet()); ({ jwk: wallet } = await warp.generateWallet());
contractSrc = fs.readFileSync(path.join(__dirname, '../data/example-contract.js'), 'utf8'); contractSrc = fs.readFileSync(path.join(__dirname, '../data/example-contract.js'), 'utf8');
@@ -65,8 +68,7 @@ describe('Testing the Warp client', () => {
contract = warp.contract<ExampleContractState>(contractTxId).setEvaluationOptions({ contract = warp.contract<ExampleContractState>(contractTxId).setEvaluationOptions({
mineArLocalBlocks: false mineArLocalBlocks: false
}); });
contractVM = warp.contract<ExampleContractState>(contractTxId).setEvaluationOptions({ contractVM = warpVm.contract<ExampleContractState>(contractTxId).setEvaluationOptions({
useVM2: true,
mineArLocalBlocks: false mineArLocalBlocks: false
}); });
contractInitData = warp.contract<ExampleContractState>(contractInitDataTxId).setEvaluationOptions({ contractInitData = warp.contract<ExampleContractState>(contractInitDataTxId).setEvaluationOptions({

View File

@@ -11,6 +11,7 @@ import { Warp } from '../../../core/Warp';
import { WarpFactory } from '../../../core/WarpFactory'; import { WarpFactory } from '../../../core/WarpFactory';
import { LoggerFactory } from '../../../logging/LoggerFactory'; import { LoggerFactory } from '../../../logging/LoggerFactory';
import { DeployPlugin } from 'warp-contracts-plugin-deploy'; import { DeployPlugin } from 'warp-contracts-plugin-deploy';
import { VM2Plugin } from 'warp-contracts-plugin-vm2';
describe('Testing the Profit Sharing Token', () => { describe('Testing the Profit Sharing Token', () => {
let contractSrc: string; let contractSrc: string;
@@ -23,6 +24,7 @@ describe('Testing the Profit Sharing Token', () => {
let arweave: Arweave; let arweave: Arweave;
let arlocal: ArLocal; let arlocal: ArLocal;
let warp: Warp; let warp: Warp;
let warpVm: Warp;
let pst: PstContract; let pst: PstContract;
let pstVM: PstContract; let pstVM: PstContract;
@@ -34,6 +36,7 @@ describe('Testing the Profit Sharing Token', () => {
LoggerFactory.INST.logLevel('error'); LoggerFactory.INST.logLevel('error');
warp = WarpFactory.forLocal(1820).use(new DeployPlugin()); warp = WarpFactory.forLocal(1820).use(new DeployPlugin());
warpVm = WarpFactory.forLocal(1820).use(new DeployPlugin()).use(new VM2Plugin());
({ arweave } = warp); ({ arweave } = warp);
({ jwk: wallet, address: walletAddress } = await warp.generateWallet()); ({ jwk: wallet, address: walletAddress } = await warp.generateWallet());
@@ -61,9 +64,7 @@ describe('Testing the Profit Sharing Token', () => {
// connecting to the PST contract // connecting to the PST contract
pst = warp.pst(contractTxId); pst = warp.pst(contractTxId);
pstVM = warp.pst(contractTxId).setEvaluationOptions({ pstVM = warpVm.pst(contractTxId);
useVM2: true
}) as PstContract;
// connecting wallet to the PST contract // connecting wallet to the PST contract
pst.connect(wallet); pst.connect(wallet);

View File

@@ -10,6 +10,7 @@ import { Warp } from '../../../core/Warp';
import { WarpFactory } from '../../../core/WarpFactory'; import { WarpFactory } from '../../../core/WarpFactory';
import { LoggerFactory } from '../../../logging/LoggerFactory'; import { LoggerFactory } from '../../../logging/LoggerFactory';
import { DeployPlugin } from 'warp-contracts-plugin-deploy'; import { DeployPlugin } from 'warp-contracts-plugin-deploy';
import { VM2Plugin } from 'warp-contracts-plugin-vm2';
interface ExampleContractState { interface ExampleContractState {
counter: number; counter: number;
@@ -52,6 +53,7 @@ describe('Testing internal writes', () => {
let arlocal: ArLocal; let arlocal: ArLocal;
let warp: Warp; let warp: Warp;
let warpVm: Warp;
let calleeContract: Contract<ExampleContractState>; let calleeContract: Contract<ExampleContractState>;
let calleeContractVM: Contract<ExampleContractState>; let calleeContractVM: Contract<ExampleContractState>;
let callingContract: Contract<ExampleContractState>; let callingContract: Contract<ExampleContractState>;
@@ -75,6 +77,7 @@ describe('Testing internal writes', () => {
async function deployContracts() { async function deployContracts() {
warp = WarpFactory.forLocal(port).use(new DeployPlugin()); warp = WarpFactory.forLocal(port).use(new DeployPlugin());
warpVm = WarpFactory.forLocal(port).use(new DeployPlugin()).use(new VM2Plugin());
({ jwk: wallet } = await warp.generateWallet()); ({ jwk: wallet } = await warp.generateWallet());
callingContractSrc = fs.readFileSync(path.join(__dirname, '../data/writing-contract.js'), 'utf8'); callingContractSrc = fs.readFileSync(path.join(__dirname, '../data/writing-contract.js'), 'utf8');
@@ -101,11 +104,10 @@ describe('Testing internal writes', () => {
mineArLocalBlocks: false mineArLocalBlocks: false
}) })
.connect(wallet); .connect(wallet);
calleeContractVM = warp calleeContractVM = warpVm
.contract<ExampleContractState>(calleeTxId) .contract<ExampleContractState>(calleeTxId)
.setEvaluationOptions({ .setEvaluationOptions({
internalWrites: true, internalWrites: true,
useVM2: true,
mineArLocalBlocks: false mineArLocalBlocks: false
}) })
.connect(wallet); .connect(wallet);
@@ -117,11 +119,10 @@ describe('Testing internal writes', () => {
mineArLocalBlocks: false mineArLocalBlocks: false
}) })
.connect(wallet); .connect(wallet);
callingContractVM = warp callingContractVM = warpVm
.contract<ExampleContractState>(callingTxId) .contract<ExampleContractState>(callingTxId)
.setEvaluationOptions({ .setEvaluationOptions({
internalWrites: true, internalWrites: true,
useVM2: true,
mineArLocalBlocks: false mineArLocalBlocks: false
}) })
.connect(wallet); .connect(wallet);
@@ -272,10 +273,10 @@ describe('Testing internal writes', () => {
}); });
const calleeContract2VM = WarpFactory.forLocal(port) const calleeContract2VM = WarpFactory.forLocal(port)
.use(new DeployPlugin()) .use(new DeployPlugin())
.use(new VM2Plugin())
.contract<ExampleContractState>(calleeTxId) .contract<ExampleContractState>(calleeTxId)
.setEvaluationOptions({ .setEvaluationOptions({
internalWrites: true, internalWrites: true
useVM2: true
}); });
expect((await calleeContract2.readState()).cachedValue.state.counter).toEqual(634); expect((await calleeContract2.readState()).cachedValue.state.counter).toEqual(634);
expect((await calleeContract2VM.readState()).cachedValue.state.counter).toEqual(634); expect((await calleeContract2VM.readState()).cachedValue.state.counter).toEqual(634);

View File

@@ -7,6 +7,7 @@ import { WarpFactory, defaultCacheOptions, defaultWarpGwOptions } from '../../co
import { LoggerFactory } from '../../logging/LoggerFactory'; import { LoggerFactory } from '../../logging/LoggerFactory';
import { SourceType } from '../../core/modules/impl/WarpGatewayInteractionsLoader'; import { SourceType } from '../../core/modules/impl/WarpGatewayInteractionsLoader';
import { DeployPlugin } from 'warp-contracts-plugin-deploy'; import { DeployPlugin } from 'warp-contracts-plugin-deploy';
import { VM2Plugin } from 'warp-contracts-plugin-vm2';
const stringify = require('safe-stable-stringify'); const stringify = require('safe-stable-stringify');
@@ -125,9 +126,9 @@ describe.each(chunkedVm)('v1 compare.suite (VM2) %#', (contracts: string[]) => {
.use(new DeployPlugin()); .use(new DeployPlugin());
const result2 = await warp const result2 = await warp
.use(new VM2Plugin())
.contract(contractTxId) .contract(contractTxId)
.setEvaluationOptions({ .setEvaluationOptions({
useVM2: true,
unsafeClient: 'allow', unsafeClient: 'allow',
allowBigInt: true allowBigInt: true
}) })

View File

@@ -28,7 +28,6 @@ describe('Evaluation options evaluator', () => {
unsafeClient: 'throw', unsafeClient: 'throw',
updateCacheForEachInteraction: false, updateCacheForEachInteraction: false,
useKVStorage: false, useKVStorage: false,
useVM2: false,
waitForConfirmation: false, waitForConfirmation: false,
useConstructor: false, useConstructor: false,
walletBalanceUrl: 'http://nyc-1.dev.arweave.net:1984/' walletBalanceUrl: 'http://nyc-1.dev.arweave.net:1984/'
@@ -36,7 +35,6 @@ describe('Evaluation options evaluator', () => {
contract.setEvaluationOptions({ contract.setEvaluationOptions({
allowBigInt: true, allowBigInt: true,
useVM2: true,
internalWrites: true, internalWrites: true,
gasLimit: 3453453 gasLimit: 3453453
}); });
@@ -44,7 +42,6 @@ describe('Evaluation options evaluator', () => {
expect( expect(
new EvaluationOptionsEvaluator(contract.evaluationOptions(), { new EvaluationOptionsEvaluator(contract.evaluationOptions(), {
allowBigInt: true, allowBigInt: true,
useVM2: true,
internalWrites: true, internalWrites: true,
gasLimit: 3453453 gasLimit: 3453453
}).rootOptions }).rootOptions
@@ -68,7 +65,6 @@ describe('Evaluation options evaluator', () => {
unsafeClient: 'throw', unsafeClient: 'throw',
updateCacheForEachInteraction: false, updateCacheForEachInteraction: false,
useKVStorage: false, useKVStorage: false,
useVM2: true,
waitForConfirmation: false, waitForConfirmation: false,
useConstructor: false, useConstructor: false,
walletBalanceUrl: 'http://nyc-1.dev.arweave.net:1984/' walletBalanceUrl: 'http://nyc-1.dev.arweave.net:1984/'
@@ -76,7 +72,6 @@ describe('Evaluation options evaluator', () => {
const contract2 = warp.contract(null).setEvaluationOptions({ const contract2 = warp.contract(null).setEvaluationOptions({
internalWrites: true, internalWrites: true,
useVM2: true,
unsafeClient: 'allow', unsafeClient: 'allow',
gasLimit: 2222, gasLimit: 2222,
maxCallDepth: 5 maxCallDepth: 5
@@ -102,7 +97,6 @@ describe('Evaluation options evaluator', () => {
unsafeClient: 'allow', unsafeClient: 'allow',
updateCacheForEachInteraction: false, updateCacheForEachInteraction: false,
useKVStorage: false, useKVStorage: false,
useVM2: true,
waitForConfirmation: false, waitForConfirmation: false,
useConstructor: false, useConstructor: false,
walletBalanceUrl: 'http://nyc-1.dev.arweave.net:1984/' walletBalanceUrl: 'http://nyc-1.dev.arweave.net:1984/'
@@ -110,9 +104,9 @@ describe('Evaluation options evaluator', () => {
expect(function () { expect(function () {
const result = new EvaluationOptionsEvaluator(contract2.evaluationOptions(), { const result = new EvaluationOptionsEvaluator(contract2.evaluationOptions(), {
useVM2: false internalWrites: false
}).rootOptions; }).rootOptions;
}).toThrow('Option {useVM2} differs.'); }).toThrow('Option {internalWrites} differs.');
}); });
it('should properly set foreign evaluation options - unsafeClient - allow', async () => { it('should properly set foreign evaluation options - unsafeClient - allow', async () => {

View File

@@ -99,7 +99,6 @@ export class EvaluationOptionsEvaluator {
sourceType: () => this.rootOptions['sourceType'], sourceType: () => this.rootOptions['sourceType'],
sequencerUrl: () => this.rootOptions['sequencerUrl'], sequencerUrl: () => this.rootOptions['sequencerUrl'],
gasLimit: () => this.rootOptions['gasLimit'], gasLimit: () => this.rootOptions['gasLimit'],
useVM2: () => this.rootOptions['useVM2'],
allowBigInt: () => this.rootOptions['allowBigInt'], // not sure about this allowBigInt: () => this.rootOptions['allowBigInt'], // not sure about this
walletBalanceUrl: () => this.rootOptions['walletBalanceUrl'], walletBalanceUrl: () => this.rootOptions['walletBalanceUrl'],
mineArLocalBlocks: () => this.rootOptions['mineArLocalBlocks'], mineArLocalBlocks: () => this.rootOptions['mineArLocalBlocks'],

View File

@@ -6,7 +6,8 @@ export const knownWarpPlugins = [
'evaluation-progress', 'evaluation-progress',
'fetch-options', 'fetch-options',
'deploy', 'deploy',
'contract-blacklist' 'contract-blacklist',
'vm2'
] as const; ] as const;
type WarpPluginPartialType = `smartweave-extension-${string}`; type WarpPluginPartialType = `smartweave-extension-${string}`;
export type WarpKnownPluginType = (typeof knownWarpPlugins)[number]; export type WarpKnownPluginType = (typeof knownWarpPlugins)[number];

View File

@@ -132,8 +132,6 @@ export class DefaultEvaluationOptions implements EvaluationOptions {
sourceType = SourceType.BOTH; sourceType = SourceType.BOTH;
useVM2 = false;
unsafeClient = 'throw' as const; unsafeClient = 'throw' as const;
allowBigInt = false; allowBigInt = false;
@@ -201,12 +199,6 @@ export interface EvaluationOptions {
gasLimit: number; gasLimit: number;
// Whether js contracts' code should be run within vm2 sandbox (https://github.com/patriksimek/vm2#vm2-----)
// it greatly enhances security - at a cost of performance.
// use for contracts that you cannot trust.
// this obviously works only in a node.js env.
useVM2: boolean;
// Whether using unsafe client should be allowed // Whether using unsafe client should be allowed
// allow - allows to evaluate contracts with SmartWeave.unsafeClient calls // allow - allows to evaluate contracts with SmartWeave.unsafeClient calls
// skip - skips all the transactions the make calls to unsafeClient (including all nested calls) // skip - skips all the transactions the make calls to unsafeClient (including all nested calls)

View File

@@ -1,6 +1,5 @@
import Arweave from 'arweave'; import Arweave from 'arweave';
import { rustWasmImports, WarpContractsCrateVersion } from './wasm/rust-wasm-imports'; import { rustWasmImports, WarpContractsCrateVersion } from './wasm/rust-wasm-imports';
import * as vm2 from 'vm2';
import { ContractDefinition } from '../../../core/ContractDefinition'; import { ContractDefinition } from '../../../core/ContractDefinition';
import { ExecutionContext } from '../../../core/ExecutionContext'; import { ExecutionContext } from '../../../core/ExecutionContext';
import { GQLNodeInterface } from '../../../legacy/gqlResult'; import { GQLNodeInterface } from '../../../legacy/gqlResult';
@@ -16,6 +15,7 @@ import { Warp } from '../../Warp';
import { isBrowser } from '../../../utils/utils'; import { isBrowser } from '../../../utils/utils';
import { Buffer } from 'warp-isomorphic'; import { Buffer } from 'warp-isomorphic';
import { InteractionState } from '../../../contract/states/InteractionState'; import { InteractionState } from '../../../contract/states/InteractionState';
import { WarpLogger } from '../../../logging/WarpLogger';
// 'require' to fix esbuild adding same lib in both cjs and esm format // 'require' to fix esbuild adding same lib in both cjs and esm format
// https://github.com/evanw/esbuild/issues/1950 // https://github.com/evanw/esbuild/issues/1950
@@ -166,7 +166,7 @@ export class HandlerExecutorFactory implements ExecutorFactory<HandlerApi<unknow
this.logger.info(`WASM ${contractDefinition.srcWasmLang} handler created in ${benchmark.elapsed()}`); this.logger.info(`WASM ${contractDefinition.srcWasmLang} handler created in ${benchmark.elapsed()}`);
return new WasmHandlerApi(swGlobal, contractDefinition, jsExports || wasmInstance.exports); return new WasmHandlerApi(swGlobal, contractDefinition, jsExports || wasmInstance.exports);
} else { } else {
const normalizedSource = normalizeContractSource(contractDefinition.src, evaluationOptions.useVM2); const normalizedSource = normalizeContractSource(contractDefinition.src, warp.hasPlugin('vm2'));
if (normalizedSource.includes('unsafeClient')) { if (normalizedSource.includes('unsafeClient')) {
switch (evaluationOptions.unsafeClient) { switch (evaluationOptions.unsafeClient) {
case 'allow': { case 'allow': {
@@ -192,42 +192,9 @@ export class HandlerExecutorFactory implements ExecutorFactory<HandlerApi<unknow
throw new Error('Using BigInt is not allowed by default. Use EvaluationOptions.allowBigInt flag.'); throw new Error('Using BigInt is not allowed by default. Use EvaluationOptions.allowBigInt flag.');
} }
} }
if (evaluationOptions.useVM2) { if (warp.hasPlugin('vm2')) {
const vmScript = new vm2.VMScript(normalizedSource); const vm2Plugin = warp.loadPlugin<VM2PluginInput, HandlerApi<State>>('vm2');
const typedArrays = { return vm2Plugin.process({ normalizedSource, swGlobal, logger: this.logger, contractDefinition });
Int8Array: Int8Array,
Uint8Array: Uint8Array,
Uint8ClampedArray: Uint8ClampedArray,
Int16Array: Int16Array,
Uint16Array: Uint16Array,
Int32Array: Int32Array,
Uint32Array: Uint32Array,
Float32Array: Float32Array,
Float64Array: Float64Array,
BigInt64Array: BigInt64Array,
BigUint64Array: BigUint64Array
};
const vm = new vm2.NodeVM({
console: 'off',
sandbox: {
SmartWeave: swGlobal,
BigNumber: BigNumber,
logger: this.logger,
ContractError: ContractError,
ContractAssert: function (cond, message) {
if (!cond) throw new ContractError(message);
},
//https://github.com/patriksimek/vm2/issues/484#issuecomment-1327479592
...typedArrays
},
compiler: 'javascript',
eval: false,
wasm: false,
allowAsync: true,
wrapper: 'commonjs'
});
return new JsHandlerApi(swGlobal, contractDefinition, vm.run(vmScript));
} else if (warp.hasPlugin('ivm-handler-api')) { } else if (warp.hasPlugin('ivm-handler-api')) {
const ivmPlugin = warp.loadPlugin<IvmPluginInput, HandlerApi<State>>('ivm-handler-api'); const ivmPlugin = warp.loadPlugin<IvmPluginInput, HandlerApi<State>>('ivm-handler-api');
return ivmPlugin.process({ return ivmPlugin.process({
@@ -326,3 +293,10 @@ export interface IvmPluginInput {
swGlobal: SmartWeaveGlobal; swGlobal: SmartWeaveGlobal;
contractDefinition: ContractDefinition<unknown>; contractDefinition: ContractDefinition<unknown>;
} }
export interface VM2PluginInput {
normalizedSource: string;
swGlobal: SmartWeaveGlobal;
logger: WarpLogger;
contractDefinition: ContractDefinition<unknown>;
}

View File

@@ -2543,7 +2543,7 @@ bech32@1.1.4:
resolved "https://registry.yarnpkg.com/bech32/-/bech32-1.1.4.tgz#e38c9f37bf179b8eb16ae3a772b40c356d4832e9" resolved "https://registry.yarnpkg.com/bech32/-/bech32-1.1.4.tgz#e38c9f37bf179b8eb16ae3a772b40c356d4832e9"
integrity sha512-s0IrSOzLlbvX7yp4WBfPITzpAU8sqQcpsmwXDiKwrG4r491vwCO/XpejasRNl0piBMe/DvP4Tz0mIS/X1DPJBQ== integrity sha512-s0IrSOzLlbvX7yp4WBfPITzpAU8sqQcpsmwXDiKwrG4r491vwCO/XpejasRNl0piBMe/DvP4Tz0mIS/X1DPJBQ==
bignumber.js@9.1.1, bignumber.js@^9.0.0, bignumber.js@^9.0.1, bignumber.js@^9.0.2: bignumber.js@9.1.1, bignumber.js@^9.0.0, bignumber.js@^9.0.1, bignumber.js@^9.0.2, bignumber.js@^9.1.1:
version "9.1.1" version "9.1.1"
resolved "https://registry.yarnpkg.com/bignumber.js/-/bignumber.js-9.1.1.tgz#c4df7dc496bd849d4c9464344c1aa74228b4dac6" resolved "https://registry.yarnpkg.com/bignumber.js/-/bignumber.js-9.1.1.tgz#c4df7dc496bd849d4c9464344c1aa74228b4dac6"
integrity sha512-pHm4LsMJ6lzgNGVfZHjMoO8sdoRhOzOH4MLmY65Jg70bpxCKu5iOHNJyfF6OyvYw7t8Fpf35RuzUyqnQsj8Vig== integrity sha512-pHm4LsMJ6lzgNGVfZHjMoO8sdoRhOzOH4MLmY65Jg70bpxCKu5iOHNJyfF6OyvYw7t8Fpf35RuzUyqnQsj8Vig==
@@ -7447,10 +7447,10 @@ vm-browserify@^1.0.1:
resolved "https://registry.yarnpkg.com/vm-browserify/-/vm-browserify-1.1.2.tgz#78641c488b8e6ca91a75f511e7a3b32a86e5dda0" resolved "https://registry.yarnpkg.com/vm-browserify/-/vm-browserify-1.1.2.tgz#78641c488b8e6ca91a75f511e7a3b32a86e5dda0"
integrity sha512-2ham8XPWTONajOR0ohOKOHXkm3+gaBmGut3SRuu75xLd/RRaY6vqgh8NBYYk7+RW3u5AtzPQZG8F10LHkl0lAQ== integrity sha512-2ham8XPWTONajOR0ohOKOHXkm3+gaBmGut3SRuu75xLd/RRaY6vqgh8NBYYk7+RW3u5AtzPQZG8F10LHkl0lAQ==
vm2@3.9.13: vm2@^3.9.16:
version "3.9.13" version "3.9.16"
resolved "https://registry.yarnpkg.com/vm2/-/vm2-3.9.13.tgz#774a1a3d73b9b90b1aa45bcc5f25e349f2eef649" resolved "https://registry.yarnpkg.com/vm2/-/vm2-3.9.16.tgz#0fbc2a265f7bf8b837cea6f4a908f88a3f93b8e6"
integrity sha512-0rvxpB8P8Shm4wX2EKOiMp7H2zq+HUE/UwodY0pCZXs9IffIKZq6vUti5OgkVCTakKo9e/fgO4X1fkwfjWxE3Q== integrity sha512-3T9LscojNTxdOyG+e8gFeyBXkMlOBYDoF6dqZbj+MPVHi9x10UfiTAJIobuchRCp3QvC+inybTbMJIUrLsig0w==
dependencies: dependencies:
acorn "^8.7.0" acorn "^8.7.0"
acorn-walk "^8.2.0" acorn-walk "^8.2.0"
@@ -7462,37 +7462,22 @@ walker@^1.0.8:
dependencies: dependencies:
makeerror "1.0.12" makeerror "1.0.12"
warp-contracts-plugin-deploy@1.0.0-beta.16: warp-contracts-plugin-deploy@^1.0.3:
version "1.0.0-beta.16" version "1.0.3"
resolved "https://registry.yarnpkg.com/warp-contracts-plugin-deploy/-/warp-contracts-plugin-deploy-1.0.0-beta.16.tgz#cd2a0472e1272f3ab238ab3137e394413a494f7e" resolved "https://registry.yarnpkg.com/warp-contracts-plugin-deploy/-/warp-contracts-plugin-deploy-1.0.3.tgz#9ca7cd53b4a7cd1b015881f1d369659bb6f9075b"
integrity sha512-66OYLIXM5FkyYxABfOGcTi+lk/XRU2Q1n3Wm3Jr12GrrO/NyC1WFi1q/dquCtrkoN5kesNIDOp8+i17cIHEBlA== integrity sha512-zDF/yqHbxIDImtVKxE/hbIz824PjPOc0aXONQtnR7do0MFdF7eJqeAAA5a2W5WTHN3cplvej6y7vSv6f/E2dEg==
dependencies: dependencies:
arbundles "^0.7.3" arbundles "^0.7.3"
arlocal "^1.1.59" arlocal "^1.1.59"
node-stdlib-browser "^1.2.0" node-stdlib-browser "^1.2.0"
warp-contracts "1.2.43-beta.21"
warp-contracts@1.2.43-beta.21: warp-contracts-plugin-vm2@1.0.0:
version "1.2.43-beta.21" version "1.0.0"
resolved "https://registry.yarnpkg.com/warp-contracts/-/warp-contracts-1.2.43-beta.21.tgz#55a7b661a7218073ce96d82e8cb0ffb2c342ad1f" resolved "https://registry.yarnpkg.com/warp-contracts-plugin-vm2/-/warp-contracts-plugin-vm2-1.0.0.tgz#f55914a228102f3bda7dafc197c395078fa0e190"
integrity sha512-2ZRCWULNDeSduhgS7iNbApyECSsCOtyHgPn9AuSFlpnB7z0Z7SfIRSuycG8zDqbnIPxrkumKrsT4O4oG0uxjiA== integrity sha512-3XubaZ9eeRbBtMDwmTAewZk6WYgtcg9g44vATqH5vmn2wdPWIBcrBX3gA7XQIDbqPcLPpIgifMDZiQJSNwYZDA==
dependencies: dependencies:
"@idena/vrf-js" "^1.0.1" bignumber.js "^9.1.1"
archiver "^5.3.0" vm2 "^3.9.16"
arweave "^1.12.4"
async-mutex "^0.4.0"
bignumber.js "9.1.1"
elliptic "^6.5.4"
events "3.3.0"
fast-copy "^3.0.0"
level "^8.0.0"
memory-level "^1.0.0"
safe-stable-stringify "2.4.1"
stream-buffers "^3.0.2"
unzipit "^1.4.0"
vm2 "3.9.13"
warp-isomorphic "1.0.0"
warp-wasm-metering "1.0.1"
warp-isomorphic@1.0.0: warp-isomorphic@1.0.0:
version "1.0.0" version "1.0.0"