Skip to content

Commit

Permalink
Integrate new asc features and a simple standard library
Browse files Browse the repository at this point in the history
  • Loading branch information
dcodeIO authored and axic committed Jun 28, 2018
1 parent efed05d commit 4e925c3
Show file tree
Hide file tree
Showing 14 changed files with 628 additions and 116 deletions.
23 changes: 3 additions & 20 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,25 +7,8 @@ The AssemblyScript project in this repository is a proof of concept barebones "E
1. Use [WebassemblyStudio](https://webassembly.studio/) or another IDE to bootstrap the project and edit `main.ts`.
2. If using WebassemblyStudio, download the project code.
3. Navigate to the top directory of the project and run `npm install`.
4. Run `npm build` to compile the AssemblyScript source to WASM bytecode. Find the compiled `wasm.out` file in the `out/` directory. At this point you have a valid WASM binary but it's not ready to be deployed onto Ethereum just yet. You need to fix the import names and namespaces. We're working on a tool to automate this process but for now this must be done by hand.
5. If you haven't already, download and compile the [WebAssembly binary toolkit (WABT)](https://github.com/WebAssembly/wabt):
```
> git clone --recursive https://github.com/WebAssembly/wabt ~/wabt
> cd ~/wabt
> make
```
6. Use WABT to convert the WASM bytecode to WAST (WebAssembly text format). This will let us edit the raw WAST.
```
> ~/wabt/bin/wasm2wat main.wasm > main.wast
```
7. Open `main.wast` in your favorite text editor. For each `import` at the top, change the `"env"` namespace to `"ethereum"` and remove the `ethereum_` from the name of the function to import. For example, this:
```
(import "env" "ethereum_getCallDataSize" (func $main/ethereum_getCallDataSize (type $t1)))
```
Should become this:
```
(import "ethereum" "getCallDataSize" (func $main/ethereum_getCallDataSize (type $t1)))
```
You now have valid ewasm-compatible WAST which is ready to be deployed to the ewasm testnet using a tool such as [ewasm-studio](https://github.com/ewasm/ewasm-studio). If you need to compile this back to WASM bytecode, you can do so using the `wabt/bin/wat2wasm` compiler.
4. Run `npm run build` to compile the AssemblyScript source to WASM bytecode. Find the compiled `main.wasm` file in the `build/` directory. At this point you have a valid WASM binary.

You now have a valid ewasm-compatible WAST which is ready to be deployed to the ewasm testnet using a tool such as [ewasm-studio](https://github.com/ewasm/ewasm-studio).

Another option is to test the code using `testeth`. See [this example](https://github.com/lrettig/tests/blob/wrc20-challenge/src/GeneralStateTestsFiller/stEWASMTests/wrc20ChallengeFiller.yml) of a test filler that fully tests this code.
1 change: 1 addition & 0 deletions assembly/lib/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Custom Ethereum standard library.
14 changes: 14 additions & 0 deletions assembly/lib/ethereum.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
// This file provides syntax highlighting for a TypeScript IDE

declare function finish(dataOffset: i32, length: i32): void;
declare function revert(dataOffset: i32, length: i32): void;
declare function callDataCopy(resultOffset: i32, dataOffset: i32, length: i32): void;
declare function getCallDataSize(): i32;
declare function getCaller(dataOffset: i32): void;
declare function storageStore(pathOffset: i32, valueOffset: i32): void;
declare function storageLoad(pathOffset: i32, resultOffset: i32): void;
declare function printMemHex(dataOffset: i32, length: i32): void;

declare function allocate_memory(size: usize): usize;
declare function free_memory(ptr: usize): void;
declare function reset_memory(): void;
10 changes: 10 additions & 0 deletions assembly/lib/ethereum.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"extends": "../../node_modules/assemblyscript/std/assembly.json",
"files": [
"../../node_modules/assemblyscript/std/assembly.d.ts",
"./ethereum.d.ts"
],
"include": [
"./**/*.ts"
]
}
23 changes: 23 additions & 0 deletions assembly/lib/ethereum.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
// This file sets up functions provided by the VM for use with AssemblyScript

import "allocator/arena";

@external("return")
export declare function finish(dataOffset: i32, length: i32): void;

export declare function revert(dataOffset: i32, length: i32): void;

export declare function callDataCopy(resultOffset: i32, dataOffset: i32, length: i32): void;

export declare function getCallDataSize(): i32;

export declare function getCaller(dataOffset: i32): void;

export declare function storageStore(pathOffset: i32, valueOffset: i32): void;

export declare function storageLoad(pathOffset: i32, resultOffset: i32): void;

@external("debug", "printMemHex")
export declare function printMemHex(dataOffset: i32, length: i32): void;

// TODO: need to implement a nice wrapper over the native functions which use native types and handles the memory.
6 changes: 6 additions & 0 deletions assembly/lib/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"extends": "../../node_modules/assemblyscript/std/assembly.json",
"include": [
"./**/*.ts"
]
}
84 changes: 0 additions & 84 deletions assembly/main.ts

This file was deleted.

74 changes: 74 additions & 0 deletions assembly/src/main.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
const DEBUG = false;

// ewasm main function
export function main(): void {
// assume the memory is already expanded..
// ethereum_return(0, ethereum_callDataSize())

// Make sure we have enough args
if (getCallDataSize() < 4)
revert(0, 0);

var ptrSelector = <i32>allocate_memory(4);
callDataCopy(ptrSelector, 0, 4);
var selector = load<i32>(ptrSelector);
switch(selector) {
case 0x9993021a:
do_balance();
break;
case 0x5d359fbd:
do_transfer();
break;
default:
revert(0, 0);
}
}

function do_balance(): void {
if (getCallDataSize() !== 24)
revert(0, 0);

var ptrAddress = <i32>allocate_memory(20);
callDataCopy(ptrAddress, 4, 20);
var ptrBalance = <i32>allocate_memory(32);
storageLoad(ptrAddress, ptrBalance);
if (DEBUG) {
printMemHex(ptrAddress, 32);
printMemHex(ptrBalance, 32);
}
finish(ptrBalance, 32);
}

function do_transfer(): void {
if (getCallDataSize() !== 32)
revert(0, 0);

var ptrSender = <i32>allocate_memory(32);
getCaller(ptrSender);
var ptrRecipient = <i32>allocate_memory(32);
callDataCopy(ptrRecipient, 4, 20);
var ptrValue = <i32>allocate_memory(32);
callDataCopy(ptrValue, 24, 8);
// debug_printMemHex(ptrValue, 32);
var ptrSenderBalance = <i32>allocate_memory(32);
var ptrRecipientBalance = <i32>allocate_memory(32);
storageLoad(ptrSender, ptrSenderBalance);
storageLoad(ptrRecipient, ptrRecipientBalance);
if (DEBUG) {
printMemHex(ptrSender, 32);
printMemHex(ptrRecipient, 32);
printMemHex(ptrSenderBalance, 32);
printMemHex(ptrRecipientBalance, 32);
}
var senderBalance = load<i32>(ptrSenderBalance);
var recipientBalance = load<i32>(ptrRecipientBalance);
var value = load<i32>(ptrValue);

if (senderBalance < value)
revert(0, 0);

store<i32>(ptrSenderBalance, senderBalance - value);
store<i32>(ptrRecipientBalance, recipientBalance + value);
storageStore(ptrSender, ptrSenderBalance);
storageStore(ptrRecipient, ptrRecipientBalance);
}
6 changes: 6 additions & 0 deletions assembly/src/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"extends": "../lib/ethereum.json",
"include": [
"./**/*.ts"
]
}
6 changes: 0 additions & 6 deletions assembly/tsconfig.json

This file was deleted.

2 changes: 2 additions & 0 deletions build/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
*.wasm
*.map
Loading

0 comments on commit 4e925c3

Please sign in to comment.