Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Running untrusted Javascript in SmartWeave contracts #77

Open
joshbenaron opened this issue Jun 21, 2021 · 4 comments
Open

Running untrusted Javascript in SmartWeave contracts #77

joshbenaron opened this issue Jun 21, 2021 · 4 comments

Comments

@joshbenaron
Copy link

Hey,
I think we're going to need a way to run any JavaScript safely. This is going to be needed for certain things that are coming into the ecosystem such as AMM's. If we are to run random PST contracts in the browser we need to sandbox the code so it's 100% harmless.
I wanted this to be the start of the discussion on the topic. I have a few ideas so far. Sandboxing can be done in two ways:

  1. WASM/WASI inherently sandboxes execution. This won't be easy to do though as V8 (NodeJS JavaScript engine) doesn't support compiling to WASM
  2. Running SmartWeave contracts in its own JS interpreter which can box up the code execution. See an example here: https://github.com/jterrace/js.js

Let me know your thoughts on this.

@joshbenaron joshbenaron changed the title Running untrusted SmartWeave contracts Running untrusted Javascript in SmartWeave contracts Jun 21, 2021
@t8
Copy link

t8 commented Jun 21, 2021

I'll add here that anything utilizing the foreign call protocol (which will hopefully be all SmartWeave token contracts in the future) would be at risk of this without a sandbox environment because users would be able to introduce any code into the execution path of the other contracts.

Technically users could whitelist the contracts that other contracts can read from, however, this naturally puts a large limitation on who can interact with what.

@marcelsud
Copy link

marcelsud commented Jul 7, 2021

What about Quickjs?
https://www.npmjs.com/package/quickjs-emscripten

@littledivy
Copy link
Contributor

Here's a tiny solution for sandboxing contracts on Node.js (please test before using) -

diff --git a/src/contract-load.ts b/src/contract-load.ts
index 35c74fc..b700e5a 100644
--- a/src/contract-load.ts
+++ b/src/contract-load.ts
@@ -4,6 +4,7 @@ import { getTag, normalizeContractSource } from './utils';
 import { ContractHandler } from './contract-step';
 import { SmartWeaveGlobal } from './smartweave-global';
 import BigNumber from 'bignumber.js';
+import * as vm from "vm";

 /**
  * Loads the contract source, initial state and other parameters
@@ -65,11 +66,19 @@ export function createContractExecutionEnvironment(
   contractOwner: string,
 ) {
   const returningSrc = normalizeContractSource(contractSrc);
+
   const swGlobal = new SmartWeaveGlobal(arweave, { id: contractId, owner: contractOwner });
-  const getContractFunction = new Function(returningSrc); // eslint-disable-line
+  const getContractFunction = async (state, interaction) => {
+    let context = vm.createContext({ handle: null, swGlobal, BigNumber, clarity });
+    vm.runInContext(returningSrc, context, {
+      timeout: 10000,
+    });
+
+    return await context.handle(state, interaction);
+  }

   return {
-    handler: getContractFunction(swGlobal, BigNumber, clarity) as ContractHandler,
+    handler: getContractFunction as ContractHandler,
     swGlobal,
   };
 }
diff --git a/src/utils.ts b/src/utils.ts
index 54e1dbe..3823760 100644
--- a/src/utils.ts
+++ b/src/utils.ts
@@ -97,11 +97,9 @@ export function normalizeContractSource(contractSrc: string): string {
     .replace(/}\s*\)\s*\(\)\s*;/g, '');

   return `
-    const [SmartWeave, BigNumber, clarity] = arguments;
     clarity.SmartWeave = SmartWeave;
     class ContractError extends Error { constructor(message) { super(message); this.name = \'ContractError\' } };
     function ContractAssert(cond, message) { if (!cond) throw new ContractError(message) };
     ${contractSrc};
-    return handle;
   `;
 }

For browsers, the first thing that I can think of is using Web Workers and falling back to a QuickJS WASM interpreter.

@joshbenaron
Copy link
Author

Hey @marcelsud @littledivy, thanks for the time you've put into this! As a community we've had a few calls on this topic and we're just working out what direction we should take this in. A lot of it seems to be going towards using WASM as a more portable and sandboxed solution. Feel free to discuss more with me and the community in the dev Discord: https://discord.gg/p8V3QC7J

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants