From d366157fa5ebe58d66d592a03b654d72ad07b1f1 Mon Sep 17 00:00:00 2001 From: poemm <36397285+poemm@users.noreply.github.com> Date: Sun, 10 Feb 2019 16:13:24 -0600 Subject: [PATCH 1/7] add C example, handwritten example, and generic tester --- C/Makefile | 10 + C/README.md | 1 + C/wrc20.c | 133 ++++++ C/wrc20.syms | 10 + C/wrc20.wasm | Bin 0 -> 1431 bytes .../wrc20_handwritten_faster_get_balance.wat | 185 ++++++++ .../wrc20_handwritten_faster_transfer.wat | 186 ++++++++ tester/README.md | 25 ++ tester/footer1.txt | 30 ++ tester/footer2.txt | 30 ++ tester/generate_wrc20_filler.py | 29 ++ tester/header.txt | 116 +++++ tester/wrc20_handwritten.json | 71 +++ tester/wrc20_handwritten.wasm | Bin 0 -> 600 bytes tester/wrc20_handwritten.wat | 260 +++++++++++ tester/wrc20_handwrittenFiller.yml | 409 ++++++++++++++++++ 16 files changed, 1495 insertions(+) create mode 100644 C/Makefile create mode 100644 C/README.md create mode 100644 C/wrc20.c create mode 100644 C/wrc20.syms create mode 100755 C/wrc20.wasm create mode 100644 handwritten/wrc20_handwritten_faster_get_balance.wat create mode 100644 handwritten/wrc20_handwritten_faster_transfer.wat create mode 100644 tester/README.md create mode 100644 tester/footer1.txt create mode 100644 tester/footer2.txt create mode 100644 tester/generate_wrc20_filler.py create mode 100644 tester/header.txt create mode 100644 tester/wrc20_handwritten.json create mode 100644 tester/wrc20_handwritten.wasm create mode 100644 tester/wrc20_handwritten.wat create mode 100644 tester/wrc20_handwrittenFiller.yml diff --git a/C/Makefile b/C/Makefile new file mode 100644 index 0000000..dbec17b --- /dev/null +++ b/C/Makefile @@ -0,0 +1,10 @@ +.PHONY: all + +LLVM_BUILD_DIR=/path/to/llvm-build + +all: + $(LLVM_BUILD_DIR)/bin/clang -cc1 -Ofast -emit-llvm -triple=wasm32-unknown-unknown-wasm wrc20.c + $(LLVM_BUILD_DIR)/bin/llc -O3 -filetype=obj wrc20.ll -o wrc20.o + $(LLVM_BUILD_DIR)/bin/wasm-ld --no-entry wrc20.o -o wrc20.wasm --strip-all -allow-undefined-file=wrc20.syms -export=_main + rm wrc20.ll wrc20.o + diff --git a/C/README.md b/C/README.md new file mode 100644 index 0000000..4e41fb5 --- /dev/null +++ b/C/README.md @@ -0,0 +1 @@ +To see how to convert `wrc20.wasm` to be meet ewasm requirements, see the tutorial https://github.com/ewasm/testnet/blob/e86d665364adfde7232feaaae178c31543734ff2/c_cpp_guide.md . diff --git a/C/wrc20.c b/C/wrc20.c new file mode 100644 index 0000000..beaae47 --- /dev/null +++ b/C/wrc20.c @@ -0,0 +1,133 @@ + + +// to avoid includes from libc, just hard-code things +typedef unsigned char uint8_t; +typedef int uint32_t; +typedef unsigned long long uint64_t; + + +// types used for Ethereum stuff +typedef uint8_t* bytes; // an array of bytes with unrestricted length +typedef uint8_t bytes32[32]; // an array of 32 bytes +typedef uint8_t address[20]; // an array of 20 bytes +typedef unsigned __int128 u128; // a 128 bit number, represented as a 16 bytes long little endian unsigned integer in memory +//typedef uint256_t u256; // a 256 bit number, represented as a 32 bytes long little endian unsigned integer in memory +typedef uint32_t i32; // same as i32 in WebAssembly +typedef uint32_t i32ptr; // same as i32 in WebAssembly, but treated as a pointer to a WebAssembly memory offset +typedef uint64_t i64; // same as i64 in WebAssembly + +// functions for ethereum stuff +void useGas(i64 amount); +void getCaller(i32ptr* resultOffset); + // memory offset to load the address into (address) +i32 getCallDataSize(); +void callDataCopy(i32ptr* resultOffset, i32 dataOffset, i32 length); + // memory offset to load data into (bytes), the offset in the input data, the length of data to copy +void revert(i32ptr* dataOffset, i32 dataLength); +void finish(i32ptr* dataOffset, i32 dataLength); +void storageStore(i32ptr* pathOffset, i32ptr* resultOffset); +void storageLoad(i32ptr* pathOffset, i32ptr* resultOffset); + //the memory offset to load the path from (bytes32), the memory offset to store/load the result at (bytes32) +void printMemHex(i32ptr* offset, i32 length); +void printStorageHex(i32ptr* key); + + +i64 reverse_bytes(i64 a){ + i64 b = 0; + b += (a & 0xff00000000000000)>>56; + b += (a & 0x00ff000000000000)>>40; + b += (a & 0x0000ff0000000000)>>24; + b += (a & 0x000000ff00000000)>>8; + b += (a & 0x00000000ff000000)<<8; + b += (a & 0x0000000000ff0000)<<24; + b += (a & 0x000000000000ff00)<<40; + b += (a & 0x00000000000000ff)<<56; + return b; +} + + +// global data used in next function, will be allocated to WebAssembly memory +bytes32 addy[1] = {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}; +bytes32 balance[1] = {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}; + +void do_balance() { + if (getCallDataSize() != 24) + revert(0, 0); + + // get address to check balance of, note: padded to 32 bytes since used as key + callDataCopy((i32ptr*)addy, 4, 20); + + // get balance + storageLoad((i32ptr*)addy, (i32ptr*)balance); + + // return balance + finish((i32ptr*)balance, 32); +} + + +// global data used in next function, will be allocated to WebAssembly memory +bytes32 sender[1] = {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}; +bytes32 recipient[1] = {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}; +bytes32 value[1] = {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}; +bytes32 recipient_balance[1] = {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}; +bytes32 sender_balance[1] = {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}; + +void do_transfer() { + if (getCallDataSize() != 32) + revert(0, 0); + + // get caller + getCaller((i32ptr*)sender); + + // get recipient from message at byte 4, length 20 + callDataCopy((i32ptr*)recipient, 4, 20); + + // get amount to transfer from message at byte 24, length 8 + callDataCopy((i32ptr*)value, 24, 8); + *(i64*)value = reverse_bytes(*(i64*)value); + + // get balances + storageLoad((i32ptr*)sender, (i32ptr*)sender_balance); + storageLoad((i32ptr*)recipient, (i32ptr*)recipient_balance); + *(i64*)sender_balance = reverse_bytes(*(i64*)sender_balance); + *(i64*)recipient_balance = reverse_bytes(*(i64*)recipient_balance); + + // make sure sender has enough + if (*(i64*)sender_balance < *(i64*)value) + revert(0, 0); + + // adjust balances + * (i64*)sender_balance -= * (i64*)value; + * (i64*)recipient_balance += * (i64*)value; + + // store results + *(i64*)sender_balance = reverse_bytes(*(i64*)sender_balance); + *(i64*)recipient_balance = reverse_bytes(*(i64*)recipient_balance); + storageStore((i32ptr*)sender, (i32ptr*)sender_balance); + storageStore((i32ptr*)recipient, (i32ptr*)recipient_balance); + +} + + +// global data used in next function, will be allocated to WebAssembly memory +i32 selector[1] = {0}; + +void _main(void) { + if (getCallDataSize() < 4) + revert(0, 0); + + // get first four bytes of message, use for calling + callDataCopy((i32ptr*)selector, 0, 4); //from byte 0, length 4 + + // call function based on selector value + switch (*selector) { + case 0x1a029399: + do_balance(); + break; + case 0xbd9f355d: + do_transfer(); + break; + default: + revert(0, 0); + } +} diff --git a/C/wrc20.syms b/C/wrc20.syms new file mode 100644 index 0000000..edaded0 --- /dev/null +++ b/C/wrc20.syms @@ -0,0 +1,10 @@ +useGas +getCaller +getCallDataSize +callDataCopy +revert +finish +storageStore +storageLoad +printMemHex +printStorageHex diff --git a/C/wrc20.wasm b/C/wrc20.wasm new file mode 100755 index 0000000000000000000000000000000000000000..b446f778155b8ddbc755f683e88d5df82b47b040 GIT binary patch literal 1431 zcmds1y>1gh5T4mRpY1G>uK>v%XID-^?R0n@1QMc4M{_>#l30p=bhaWH0=M8`IlKW~ zI*@n?KLRg+x&U4i}E*+@RUVL=)ARfj0otFy0di_Klt7HUd!L8@n`d)u924-DiIO-?y zfqK%9+b+m|(dl)DhYl38LsbHtPRPRd%`Rm^JnnfpFNXs}%y9(f-{C3Bt20le@OQc> ziu^s#@2YM;88Z-3bg1G%^ei4Kj$2XGHjE?HYjc*1x^brm#jVeIZUTSgkiTJ#K${0- z_;4Gfd4snW3OS#dDR@t73u{YH-VWXo)@K%%Wg)|6+YTpZ6`HkKQ~%5G4xP zD5WaaIc2e>+u_7uvk9T@vam*otFp7F>$kV0QdyOuvWl)SAt8j2ootk9M%1LjkiFh; zDt8Ga+DsYKf0RKU@x?S#x|BVCyk0mV7bI;Xb|-DtU=0a1M((OFzkR>Hd}TT%^ySA- zAHL$FZCoBzzR^MYX4eotr@nHsC0mBUsij&HfmyQiS{sT>M3A~5F6`gxzkmJ!70i6V literal 0 HcmV?d00001 diff --git a/handwritten/wrc20_handwritten_faster_get_balance.wat b/handwritten/wrc20_handwritten_faster_get_balance.wat new file mode 100644 index 0000000..94cb9ab --- /dev/null +++ b/handwritten/wrc20_handwritten_faster_get_balance.wat @@ -0,0 +1,185 @@ +(module + (func $revert (import "ethereum" "revert") (param i32 i32)) + (func $finish (import "ethereum" "finish") (param i32 i32)) + (func $getCallDataSize (import "ethereum" "getCallDataSize") (result i32)) + (func $callDataCopy (import "ethereum" "callDataCopy") (param i32 i32 i32)) + (func $storageLoad (import "ethereum" "storageLoad") (param i32 i32)) + (func $storageStore (import "ethereum" "storageStore") (param i32 i32)) + (func $getTxOrigin (import "ethereum" "getTxOrigin") (param i32)) + (func $getCaller (import "ethereum" "getCaller") (param i32)) + (memory (export "memory") 1) + (func (export "main") + block + block + call $getCallDataSize + i32.const 4 + i32.ge_u + br_if 0 + i32.const 0 + i32.const 0 + call $revert + br 1 + end + i32.const 0 ;;selector, 4 bytes + i32.const 0 + i32.const 4 + call $callDataCopy + block + i32.const 0 ;;load selector + i32.load + i32.const 0x1a029399 + i32.eq + i32.eqz + br_if 0 + call $do_balance + br 1 + end + block + i32.const 0 ;;load selector + i32.load + i32.const 0xbd9f355d + i32.eq + i32.eqz + br_if 0 + call $do_transfer + br 1 + end + i32.const 0 + i32.const 0 + call $revert + end) + (func $do_balance + block + block + call $getCallDataSize + i32.const 24 + i32.eq + br_if 0 + i32.const 0 + i32.const 0 + call $revert + br 1 + end + i32.const 0 ;;address to bytes 0-31, last 12 bytes are 0-padded + i32.const 4 + i32.const 20 + call $callDataCopy + i32.const 0 ;; get token balance of address in bytes 0-31, put in bytes 32-63 + i32.const 32 + call $storageLoad + i32.const 32 ;; return first 8 bytes of balance + i32.const 8 + call $finish + end) + (func $do_transfer + (local i64 i64 i64) ;;sender_balance, recipient_balance, value + block + block + call $getCallDataSize + i32.const 32 + i32.eq + br_if 0 + i32.const 0 + i32.const 0 + call $revert + br 1 + end + ;; memory bytes 0 32 64 + ;; senderAddy recipientAddy tmpForTokenValues + i32.const 0 ;;sender address to bytes 0-19 (storage key uses bytes 0-31) + call $getCaller + i32.const 32 ;;recipient address to bytes 32-51 (storage key uses bytes 32-63) + i32.const 4 + i32.const 20 + call $callDataCopy + i32.const 64 ;;temporarily put transfer_value in bytes 64-71, reverse 8 msb, put in in local 0 + i32.const 24 + i32.const 8 + call $callDataCopy + i32.const 64 + i64.load + call $i64.reverse_bytes + set_local 0 + i32.const 0 ;;temporarily put sender_balance into bytes 64-95, reverse 8 msb, put it in local 1 + i32.const 64 + call $storageLoad + i32.const 64 + i64.load + call $i64.reverse_bytes + set_local 1 + i32.const 32 ;;temporarily put recipient_balance into bytes 64-95, reverse 8 msb, put in local 2 + i32.const 64 + call $storageLoad + i32.const 64 + i64.load + call $i64.reverse_bytes + set_local 2 + block ;; if transver_value < sender_balance, then revert + get_local 0 + get_local 1 + i64.le_u + br_if 0 + i32.const 0 + i32.const 0 + call $revert + br 1 + end + get_local 1 ;;sender_balance -= value + get_local 0 + i64.sub + set_local 1 + get_local 2 ;;recipient_balance += value + get_local 0 + i64.add + set_local 2 + i32.const 64 ;;reverse sender_balance, write to memory, put in storage + get_local 1 + call $i64.reverse_bytes + i64.store + i32.const 0 + i32.const 64 + call $storageStore + i32.const 64 ;;reverse recipient_balance, write to memory, put in storage + get_local 2 + call $i64.reverse_bytes + i64.store + i32.const 32 + i32.const 64 + call $storageStore + end) + (func $i64.reverse_bytes (param i64) (result i64) + (local i64 i64) ;;iter variable, val to return + block + loop + get_local 1 ;;iter variable + i64.const 8 + i64.ge_u + br_if 1 + get_local 0 ;;original + i64.const 56 ;;shift left + get_local 1 + i64.const 8 + i64.mul + i64.sub + i64.shl + i64.const 56 ;;shift right + i64.shr_u + i64.const 56 ;;shift left + i64.const 8 + get_local 1 + i64.mul + i64.sub + i64.shl + get_local 2 ;;update + i64.add + set_local 2 + get_local 1 ;;iter+=1 + i64.const 1 + i64.add + set_local 1 + br 0 + end + end + get_local 2 + ) +) diff --git a/handwritten/wrc20_handwritten_faster_transfer.wat b/handwritten/wrc20_handwritten_faster_transfer.wat new file mode 100644 index 0000000..b77a23b --- /dev/null +++ b/handwritten/wrc20_handwritten_faster_transfer.wat @@ -0,0 +1,186 @@ +(module + (func $revert (import "ethereum" "revert") (param i32 i32)) + (func $finish (import "ethereum" "finish") (param i32 i32)) + (func $getCallDataSize (import "ethereum" "getCallDataSize") (result i32)) + (func $callDataCopy (import "ethereum" "callDataCopy") (param i32 i32 i32)) + (func $storageLoad (import "ethereum" "storageLoad") (param i32 i32)) + (func $storageStore (import "ethereum" "storageStore") (param i32 i32)) + (func $getTxOrigin (import "ethereum" "getTxOrigin") (param i32)) + (func $getCaller (import "ethereum" "getCaller") (param i32)) + (memory (export "memory") 1) + (func (export "main") + block + block + call $getCallDataSize + i32.const 4 + i32.ge_u + br_if 0 + i32.const 0 + i32.const 0 + call $revert + br 1 + end + i32.const 0 ;;selector, 4 bytes + i32.const 0 + i32.const 4 + call $callDataCopy + block + i32.const 0 ;;load selector + i32.load + i32.const 0x1a029399 + i32.eq + i32.eqz + br_if 0 + call $do_balance + br 1 + end + block + i32.const 0 ;;load selector + i32.load + i32.const 0xbd9f355d + i32.eq + i32.eqz + br_if 0 + call $do_transfer + br 1 + end + i32.const 0 + i32.const 0 + call $revert + end) + (func $do_balance + block + block + call $getCallDataSize + i32.const 24 + i32.eq + br_if 0 + i32.const 0 + i32.const 0 + call $revert + br 1 + end + i32.const 0 ;;address to bytes 0-31, last 12 bytes are 0-padded + i32.const 4 + i32.const 20 + call $callDataCopy + i32.const 0 ;; get token balance of address in bytes 0-31, put in bytes 32-63 + i32.const 32 + call $storageLoad + i32.const 32 ;; reverse bytes and put back in memory + i32.const 32 + i64.load + call $i64.reverse_bytes + i64.store + i32.const 32 ;; return first 8 bytes of balance + i32.const 8 + call $finish + end) + (func $do_transfer + (local i64 i64 i64) ;;sender_balance, recipient_balance, value + block + block + call $getCallDataSize + i32.const 32 + i32.eq + br_if 0 + i32.const 0 + i32.const 0 + call $revert + br 1 + end + ;; memory bytes 0 32 64 + ;; senderAddy recipientAddy tmpForTokenValues + i32.const 0 ;;sender address to bytes 0-19 (storage key uses bytes 0-31) + call $getCaller + i32.const 32 ;;recipient address to bytes 32-51 (storage key uses bytes 32-63) + i32.const 4 + i32.const 20 + call $callDataCopy + i32.const 64 ;;temporarily put transfer_value in bytes 64-71, reverse 8 msb, put in in local 0 + i32.const 24 + i32.const 8 + call $callDataCopy + i32.const 64 + i64.load + call $i64.reverse_bytes + set_local 0 + i32.const 0 ;;temporarily put sender_balance into bytes 64-95, reverse 8 msb, put it in local 1 + i32.const 64 + call $storageLoad + i32.const 64 + i64.load + set_local 1 + i32.const 32 ;;temporarily put recipient_balance into bytes 64-95, reverse 8 msb, put in local 2 + i32.const 64 + call $storageLoad + i32.const 64 + i64.load + set_local 2 + block ;; if transver_value < sender_balance, then revert + get_local 0 + get_local 1 + i64.le_u + br_if 0 + i32.const 0 + i32.const 0 + call $revert + br 1 + end + get_local 1 ;;sender_balance -= value + get_local 0 + i64.sub + set_local 1 + get_local 2 ;;recipient_balance += value + get_local 0 + i64.add + set_local 2 + i32.const 64 ;;reverse sender_balance, write to memory, put in storage + get_local 1 + i64.store + i32.const 0 + i32.const 64 + call $storageStore + i32.const 64 ;;reverse recipient_balance, write to memory, put in storage + get_local 2 + i64.store + i32.const 32 + i32.const 64 + call $storageStore + end) + (func $i64.reverse_bytes (param i64) (result i64) + (local i64 i64) ;;iter variable, val to return + block + loop + get_local 1 ;;iter variable + i64.const 8 + i64.ge_u + br_if 1 + get_local 0 ;;original + i64.const 56 ;;shift left + get_local 1 + i64.const 8 + i64.mul + i64.sub + i64.shl + i64.const 56 ;;shift right + i64.shr_u + i64.const 56 ;;shift left + i64.const 8 + get_local 1 + i64.mul + i64.sub + i64.shl + get_local 2 ;;update + i64.add + set_local 2 + get_local 1 ;;iter+=1 + i64.const 1 + i64.add + set_local 1 + br 0 + end + end + get_local 2 + ) +) diff --git a/tester/README.md b/tester/README.md new file mode 100644 index 0000000..9757cf8 --- /dev/null +++ b/tester/README.md @@ -0,0 +1,25 @@ +# Generates a test filler around wrc20.wat + +WRC20 is defined up to the interface, and each implementation can internally store balances in their own way. So first choose a footer.txt with the correct internal representation of your initial state, it is in the curly braces at the top. + +Generate the test filler. + +```sh +python3 generate_wrc20_filler.py wrc20.wat footer1.txt +``` + +The output is `wrc20Filler.yml`. You need an ewasm client which can handle yml fillers. For example, we follow notes from the ewasm benchmarking repo which also uses the test system. + +```sh +TEST_DIR= +TESTETH_EXEC= +HERA_SO= + +cp wrc20Filler.yml $TEST_DIR/src/GeneralStateTestsFiller/stEWASMTests/ + +# fill the test +ETHEREUM_TEST_PATH=$TEST_DIR $TESTETH_EXEC -t GeneralStateTests/stEWASMTests -- --filltests --vm $HERA_SO --evmc engine=binaryen --singlenet "Byzantium" --singletest wrc20 + +# execute the test +ETHEREUM_TEST_PATH=$TEST_DIR $TESTETH_EXEC -t GeneralStateTests/stEWASMTests -- --vm $HERA_SO --evmc engine=binaryen --singlenet "Byzantium" --singletest wrc20 +``` diff --git a/tester/footer1.txt b/tester/footer1.txt new file mode 100644 index 0000000..c3c65b3 --- /dev/null +++ b/tester/footer1.txt @@ -0,0 +1,30 @@ + nonce: '' + storage: { + "0xeD09375DC6B20050d242d1611af97eE4A6E93CAd000000000000000000000000" : "0x40420f0000000000000000000000000000000000000000000000000000000000" + } + expect: + - indexes: + data: !!int -1 + gas: !!int -1 + value: !!int -1 + network: + - ALL + result: + eD09375DC6B20050d242d1611af97eE4A6E93CAd: + storage: { + "0x0000000000000000000000000000000000000000000000000000000000000000" : "0x00000000000f4240000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000001" : "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000002" : "0x000000000007a120000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000003" : "0x000000000007a120000000000000000000000000000000000000000000000000" + } + transaction: + data: + - '' + gasLimit: + - '0x5000001' + gasPrice: '0x01' + nonce: '0x00' + secretKey: 45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8 + to: '0xeD09375DC6B20050d242d1611af97eE4A6E93CAd' + value: + - '0' diff --git a/tester/footer2.txt b/tester/footer2.txt new file mode 100644 index 0000000..6e71084 --- /dev/null +++ b/tester/footer2.txt @@ -0,0 +1,30 @@ + nonce: '' + storage: { + "0xeD09375DC6B20050d242d1611af97eE4A6E93CAd000000000000000000000000" : "0x00000000000f4240000000000000000000000000000000000000000000000000" + } + expect: + - indexes: + data: !!int -1 + gas: !!int -1 + value: !!int -1 + network: + - ALL + result: + eD09375DC6B20050d242d1611af97eE4A6E93CAd: + storage: { + "0x0000000000000000000000000000000000000000000000000000000000000000" : "0x00000000000f4240000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000001" : "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000002" : "0x000000000007a120000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000003" : "0x000000000007a120000000000000000000000000000000000000000000000000" + } + transaction: + data: + - '' + gasLimit: + - '0x5000001' + gasPrice: '0x01' + nonce: '0x00' + secretKey: 45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8 + to: '0xeD09375DC6B20050d242d1611af97eE4A6E93CAd' + value: + - '0' diff --git a/tester/generate_wrc20_filler.py b/tester/generate_wrc20_filler.py new file mode 100644 index 0000000..9d3e5ca --- /dev/null +++ b/tester/generate_wrc20_filler.py @@ -0,0 +1,29 @@ +#!/usr/bin/env python3 + +def generate_filler_from_wat(name, footer_filename): + name = name.split(".")[0] + + # first the name at top of the filler, then the "header" + f_filler = open(name+"Filler.yml",'w') + f_filler.write("# Test WRC20, see https://gist.github.com/axic/16158c5c88fbc7b1d09dfa8c658bc363\n") + f_filler.write("---\n") + f_filler.write(name+":\n") + f_header = open("header.txt", 'r') + for line in f_header: + f_filler.write(line) + + # next the wat file + f_wat = open(name+".wat", 'r') + for line in f_wat: + #f_filler.write(" "+line) + f_filler.write(" "+line) + + # finally footer + f_footer = open(footer_filename, 'r') + for line in f_footer: + f_filler.write(line) + + +if __name__ == "__main__": + import sys + generate_filler_from_wat(sys.argv[1], sys.argv[2]) diff --git a/tester/header.txt b/tester/header.txt new file mode 100644 index 0000000..a319d58 --- /dev/null +++ b/tester/header.txt @@ -0,0 +1,116 @@ + env: + currentCoinbase: 2adc25665018aa1fe0e6bc666dac8fc2697ff9ba + currentDifficulty: '0x020000' + currentGasLimit: '89128960' + currentNumber: '1' + currentTimestamp: '1000' + previousHash: 5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6 + pre: + 0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b: + balance: '100000000000' + code: '' + nonce: '0' + storage: {} + 0xeD09375DC6B20050d242d1611af97eE4A6E93CAd: + balance: '100000000000' + code: | + (module + (import "ethereum" "storageStore" (func $storageStore (param i32 i32))) + (import "ethereum" "call" (func $call (param i64 i32 i32 i32 i32) (result i32))) + (import "ethereum" "returnDataCopy" (func $returnDataCopy (param i32 i32 i32))) + (import "debug" "printStorageHex" (func $printStorageHex (param i32))) + (import "debug" "printMemHex" (func $printMemHex (param i32 i32))) + (memory 1) + + ;; memory looks like this + ;; 0 | 32 | 64 | 96... + ;; address of contract | wei to send | storage key to store returned value | calldata and returndata... + + ;; address of contract to call + (data (i32.const 0) "\b9\4f\53\74\fc\e5\ed\bc\8e\2a\86\97\c1\53\31\67\7e\6e\bf\0b") + + ;; first message to query balance + (data (i32.const 96) "\99\93\02\1a\ed\09\37\5d\c6\b2\00\50\d2\42\d1\61\1a\f9\7e\e4\a6\e9\3c\ad") + ;; first return value will become + ;;(data (i32.const 120) "\00\00\00\00\00\0f\42\40") + + ;; second message to transfer tokens + (data (i32.const 152) "\5d\35\9f\bd\e9\29\cf\25\44\36\3b\dc\ee\4a\97\65\15\d5\f9\77\58\ef\47\6c\00\00\00\00\00\07\a1\20") ;; second message returns nothing + + ;; third message (same as first) + (data (i32.const 216) "\99\93\02\1a\ed\09\37\5d\c6\b2\00\50\d2\42\d1\61\1a\f9\7e\e4\a6\e9\3c\ad") + ;; third return value will become + ;;(data (i32.const 240) "\00\00\00\00\00\07\a1\20") + + ;; fourth message to query balance + (data (i32.const 272) "\99\93\02\1a\e9\29\cf\25\44\36\3b\dc\ee\4a\97\65\15\d5\f9\77\58\ef\47\6c") + ;; fourth return value will become + ;;(data (i32.const 304) "\00\00\00\00\00\07\a1\20") + + (export "main" (func $main)) + (export "memory" (memory 0)) + (func $main + + + ;; call the precompile at address b94...f0b and send value 0 Eth + ;; gas addrOffset valOffset dataOffset dataLength + (drop (call $call (i64.const 200000) (i32.const 0) (i32.const 32) (i32.const 96) (i32.const 24))) + ;; get return data + ;; resultOffset dataOffset length + (call $returnDataCopy (i32.const 120) (i32.const 0) (i32.const 8)) + ;; store result in storage + (i32.store8 (i32.const 95) (i32.const 0)) + ;; pathOffset valueOffset + (call $storageStore (i32.const 64) (i32.const 120)) + (call $printMemHex (i32.const 120) (i32.const 32)) + (call $printStorageHex (i32.const 64)) + + ;; call the precompile at address b94...f0b and send value 0 Eth + ;; gas addrOffset valOffset dataOffset dataLength + (drop (call $call (i64.const 200000) (i32.const 0) (i32.const 32) (i32.const 152) (i32.const 32))) + ;; get return data + ;; resultOffset dataOffset length + (call $returnDataCopy (i32.const 184) (i32.const 0) (i32.const 0)) + ;; store result in storage + (i32.store8 (i32.const 95) (i32.const 1)) + ;; pathOffset valueOffset + (call $storageStore (i32.const 64) (i32.const 184)) + (call $printMemHex (i32.const 184) (i32.const 32)) + (call $printStorageHex (i32.const 64)) + + + ;; call the precompile at address b94...f0b and send value 0 Eth + ;; gas addrOffset valOffset dataOffset dataLength + (drop (call $call (i64.const 200000) (i32.const 0) (i32.const 32) (i32.const 216) (i32.const 24))) + ;; get return data + ;; resultOffset dataOffset length + (call $returnDataCopy (i32.const 240) (i32.const 0) (i32.const 8)) + ;; store result in storage + (i32.store8 (i32.const 95) (i32.const 2)) + ;; pathOffset valueOffset + (call $storageStore (i32.const 64) (i32.const 240)) + (call $printMemHex (i32.const 240) (i32.const 32)) + (call $printStorageHex (i32.const 64)) + + + ;; call the precompile at address b94...f0b and send value 0 Eth + ;; gas addrOffset valOffset dataOffset dataLength + (drop (call $call (i64.const 200000) (i32.const 0) (i32.const 32) (i32.const 272) (i32.const 24))) + ;; get return data + ;; resultOffset dataOffset length + (call $returnDataCopy (i32.const 304) (i32.const 0) (i32.const 8)) + ;; store result in storage + (i32.store8 (i32.const 95) (i32.const 3)) + ;; pathOffset valueOffset + (call $storageStore (i32.const 64) (i32.const 304)) + (call $printMemHex (i32.const 304) (i32.const 32)) + (call $printStorageHex (i32.const 64)) + + ) + ) + nonce: '0' + storage: {} + + b94f5374fce5edbc8e2a8697c15331677e6ebf0b: + balance: '100000000000' + code: | diff --git a/tester/wrc20_handwritten.json b/tester/wrc20_handwritten.json new file mode 100644 index 0000000..7717bc4 --- /dev/null +++ b/tester/wrc20_handwritten.json @@ -0,0 +1,71 @@ +{ + "wrc20_handwritten" : { + "_info" : { + "comment" : "", + "filledwith" : "testeth 1.5.0-alpha.7", + "lllcversion" : "Error getting LLLC Version", + "source" : "src/GeneralStateTestsFiller/stEWASMTests/wrc20_handwrittenFiller.yml", + "sourceHash" : "6e46f318009c34852867e9250da0b8b60812d2feb05621467e6051fda9616266" + }, + "env" : { + "currentCoinbase" : "0x2adc25665018aa1fe0e6bc666dac8fc2697ff9ba", + "currentDifficulty" : "0x020000", + "currentGasLimit" : "0x05500000", + "currentNumber" : "0x01", + "currentTimestamp" : "0x03e8", + "previousHash" : "0x5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6" + }, + "post" : { + "Byzantium" : [ + { + "hash" : "0x20fb4b51d2c369a7c4f50c781ed4f48f290aaec16f7c17c80ed8eadb0132c286", + "indexes" : { + "data" : 0, + "gas" : 0, + "value" : 0 + }, + "logs" : "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347" + } + ] + }, + "pre" : { + "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { + "balance" : "0x174876e800", + "code" : "", + "nonce" : "0x00", + "storage" : { + } + }, + "0xb94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { + "balance" : "0x174876e800", + "code" : "0x0061736d01000000012f0a60027f7f006000017f60037f7f7f0060017f0060000060017e017e60027f7f006000017f60037f7f7f0060017f0002b3010808657468657265756d06726576657274000608657468657265756d0666696e697368000608657468657265756d0f67657443616c6c4461746153697a65000708657468657265756d0c63616c6c44617461436f7079000808657468657265756d0b73746f726167654c6f6164000608657468657265756d0c73746f7261676553746f7265000608657468657265756d0b67657454784f726967696e000908657468657265756d0967657443616c6c65720009030504040404050503010001071102066d656d6f72790200046d61696e00080adb0204510002400240100241044f0d004100410010000c010b4100410041041003024041002802004199a78ad00146450d0010090c010b0240410028020041ddeafcec7b46450d00100a0c010b4100410010000b0b37000240024010024118460d004100410010000c010b410041044114100341004120100441204120290300100b3703004120410810010b0b940101037e0240024010024120460d004100410010000c010b41001007412041044114100341c00041184108100341c000290300100b2100410041c000100441c0002903002101412041c000100441c0002903002102024020002001580d004100410010000c010b200120007d2101200220007c210241c0002001370300410041c000100541c0002002370300412041c00010050b0b3901027e02400340200142085a0d0120004238200142087e7d864238884238420820017e7d8620027c2102200142017c21010c000b000b20020b", + "nonce" : "0x00", + "storage" : { + "0xed09375dc6b20050d242d1611af97ee4a6e93cad000000000000000000000000" : "0x40420f0000000000000000000000000000000000000000000000000000000000" + } + }, + "0xed09375dc6b20050d242d1611af97ee4a6e93cad" : { + "balance" : "0x174876e800", + "code" : "0x0061736d01000000011c0560027f7f0060057e7f7f7f7f017f60037f7f7f0060017f00600000026f0508657468657265756d0c73746f7261676553746f7265000008657468657265756d0463616c6c000108657468657265756d0e72657475726e44617461436f707900020564656275670f7072696e7453746f7261676548657800030564656275670b7072696e744d656d4865780000030201040503010001071102046d61696e0005066d656d6f727902000ad90101d6010042c09a0c4100412041e000411810011a41f80041004108100241df0041003a000041c00041f800100041f8004120100441c000100342c09a0c41004120419801412010011a41b80141004100100241df0041013a000041c00041b801100041b8014120100441c000100342c09a0c4100412041d801411810011a41f00141004108100241df0041023a000041c00041f001100041f0014120100441c000100342c09a0c41004120419002411810011a41b00241004108100241df0041033a000041c00041b002100041b0024120100441c00010030b0b9a01050041000b14b94f5374fce5edbc8e2a8697c15331677e6ebf0b0041e0000b189993021aed09375dc6b20050d242d1611af97ee4a6e93cad004198010b205d359fbde929cf2544363bdcee4a976515d5f97758ef476c000000000007a1200041d8010b189993021aed09375dc6b20050d242d1611af97ee4a6e93cad004190020b189993021ae929cf2544363bdcee4a976515d5f97758ef476c", + "nonce" : "0x00", + "storage" : { + } + } + }, + "transaction" : { + "data" : [ + "0x" + ], + "gasLimit" : [ + "0x5000001" + ], + "gasPrice" : "0x01", + "nonce" : "0x00", + "secretKey" : "0x45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "to" : "0xeD09375DC6B20050d242d1611af97eE4A6E93CAd", + "value" : [ + "0x00" + ] + } + } +} \ No newline at end of file diff --git a/tester/wrc20_handwritten.wasm b/tester/wrc20_handwritten.wasm new file mode 100644 index 0000000000000000000000000000000000000000..9659de84948160e571ffb32d7b328ad515714b9b GIT binary patch literal 600 zcmY+AJx;?w5QS%E?O?KrSR{%R6zdL7KuWKHR7ePg0#U_+C9#AFatz`pKOI8UG@O6~ zaDg0w8i@-ajzGaUm|*O}GjHGf_Q?OujuYu;e9Ay18>e`)t zbX+3U3c1avwxmnGVgG73jl1y~h&g4kxY(v3gzNC*x&i?gmZ_51q@P|BI7!4Aulh#L z9#BAmBIE4V!SJh~hB6d6ovGC#qd>}yUt**6 zpXitsC77#~W3JLE}NGiAD`0A2n$h`ow09d5amv%~$#<#S~Y{CK8ttfyU4~taCJM=HqyD7dG$1 UX6R|;SremJ$Dxlk{s)@mH$L)y$^ZZW literal 0 HcmV?d00001 diff --git a/tester/wrc20_handwritten.wat b/tester/wrc20_handwritten.wat new file mode 100644 index 0000000..e92594a --- /dev/null +++ b/tester/wrc20_handwritten.wat @@ -0,0 +1,260 @@ +(module + (type $0 (func (param i32 i32))) + (type $1 (func (result i32))) + (type $2 (func (param i32 i32 i32))) + (type $3 (func (param i32))) + (type $4 (func)) + (type $5 (func (param i64) (result i64))) + (memory $0 1) + (import "ethereum" "revert" (func $fimport$0 (param i32 i32))) + (import "ethereum" "finish" (func $fimport$1 (param i32 i32))) + (import "ethereum" "getCallDataSize" (func $fimport$2 (result i32))) + (import "ethereum" "callDataCopy" (func $fimport$3 (param i32 i32 i32))) + (import "ethereum" "storageLoad" (func $fimport$4 (param i32 i32))) + (import "ethereum" "storageStore" (func $fimport$5 (param i32 i32))) + (import "ethereum" "getTxOrigin" (func $fimport$6 (param i32))) + (import "ethereum" "getCaller" (func $fimport$7 (param i32))) + (export "memory" (memory $0)) + (export "main" (func $0)) + (func $0 (; 8 ;) (type $4) + (block $label$1 + (block $label$2 + (br_if $label$2 + (i32.ge_u + (call $fimport$2) + (i32.const 4) + ) + ) + (call $fimport$0 + (i32.const 0) + (i32.const 0) + ) + (br $label$1) + ) + (call $fimport$3 + (i32.const 0) + (i32.const 0) + (i32.const 4) + ) + (block $label$3 + (br_if $label$3 + (i32.eqz + (i32.eq + (i32.load + (i32.const 0) + ) + (i32.const 436376473) + ) + ) + ) + (call $1) + (br $label$1) + ) + (block $label$4 + (br_if $label$4 + (i32.eqz + (i32.eq + (i32.load + (i32.const 0) + ) + (i32.const -1113639587) + ) + ) + ) + (call $2) + (br $label$1) + ) + (call $fimport$0 + (i32.const 0) + (i32.const 0) + ) + ) + ) + (func $1 (; 9 ;) (type $4) + (block $label$1 + (block $label$2 + (br_if $label$2 + (i32.eq + (call $fimport$2) + (i32.const 24) + ) + ) + (call $fimport$0 + (i32.const 0) + (i32.const 0) + ) + (br $label$1) + ) + (call $fimport$3 + (i32.const 0) + (i32.const 4) + (i32.const 20) + ) + (call $fimport$4 + (i32.const 0) + (i32.const 32) + ) + (i64.store + (i32.const 32) + (call $3 + (i64.load + (i32.const 32) + ) + ) + ) + (call $fimport$1 + (i32.const 32) + (i32.const 8) + ) + ) + ) + (func $2 (; 10 ;) (type $4) + (local $0 i64) + (local $1 i64) + (local $2 i64) + (block $label$1 + (block $label$2 + (br_if $label$2 + (i32.eq + (call $fimport$2) + (i32.const 32) + ) + ) + (call $fimport$0 + (i32.const 0) + (i32.const 0) + ) + (br $label$1) + ) + (call $fimport$7 + (i32.const 0) + ) + (call $fimport$3 + (i32.const 32) + (i32.const 4) + (i32.const 20) + ) + (call $fimport$3 + (i32.const 64) + (i32.const 24) + (i32.const 8) + ) + (set_local $0 + (call $3 + (i64.load + (i32.const 64) + ) + ) + ) + (call $fimport$4 + (i32.const 0) + (i32.const 64) + ) + (set_local $1 + (i64.load + (i32.const 64) + ) + ) + (call $fimport$4 + (i32.const 32) + (i32.const 64) + ) + (set_local $2 + (i64.load + (i32.const 64) + ) + ) + (block $label$3 + (br_if $label$3 + (i64.le_u + (get_local $0) + (get_local $1) + ) + ) + (call $fimport$0 + (i32.const 0) + (i32.const 0) + ) + (br $label$1) + ) + (set_local $1 + (i64.sub + (get_local $1) + (get_local $0) + ) + ) + (set_local $2 + (i64.add + (get_local $2) + (get_local $0) + ) + ) + (i64.store + (i32.const 64) + (get_local $1) + ) + (call $fimport$5 + (i32.const 0) + (i32.const 64) + ) + (i64.store + (i32.const 64) + (get_local $2) + ) + (call $fimport$5 + (i32.const 32) + (i32.const 64) + ) + ) + ) + (func $3 (; 11 ;) (type $5) (param $0 i64) (result i64) + (local $1 i64) + (local $2 i64) + (block $label$1 + (loop $label$2 + (br_if $label$1 + (i64.ge_u + (get_local $1) + (i64.const 8) + ) + ) + (set_local $2 + (i64.add + (i64.shl + (i64.shr_u + (i64.shl + (get_local $0) + (i64.sub + (i64.const 56) + (i64.mul + (get_local $1) + (i64.const 8) + ) + ) + ) + (i64.const 56) + ) + (i64.sub + (i64.const 56) + (i64.mul + (i64.const 8) + (get_local $1) + ) + ) + ) + (get_local $2) + ) + ) + (set_local $1 + (i64.add + (get_local $1) + (i64.const 1) + ) + ) + (br $label$2) + ) + ) + (get_local $2) + ) +) + diff --git a/tester/wrc20_handwrittenFiller.yml b/tester/wrc20_handwrittenFiller.yml new file mode 100644 index 0000000..06a20f2 --- /dev/null +++ b/tester/wrc20_handwrittenFiller.yml @@ -0,0 +1,409 @@ +# Test WRC20, see https://gist.github.com/axic/16158c5c88fbc7b1d09dfa8c658bc363 +--- +wrc20_handwritten: + env: + currentCoinbase: 2adc25665018aa1fe0e6bc666dac8fc2697ff9ba + currentDifficulty: '0x020000' + currentGasLimit: '89128960' + currentNumber: '1' + currentTimestamp: '1000' + previousHash: 5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6 + pre: + 0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b: + balance: '100000000000' + code: '' + nonce: '0' + storage: {} + 0xeD09375DC6B20050d242d1611af97eE4A6E93CAd: + balance: '100000000000' + code: | + (module + (import "ethereum" "storageStore" (func $storageStore (param i32 i32))) + (import "ethereum" "call" (func $call (param i64 i32 i32 i32 i32) (result i32))) + (import "ethereum" "returnDataCopy" (func $returnDataCopy (param i32 i32 i32))) + (import "debug" "printStorageHex" (func $printStorageHex (param i32))) + (import "debug" "printMemHex" (func $printMemHex (param i32 i32))) + (memory 1) + + ;; memory looks like this + ;; 0 | 32 | 64 | 96... + ;; address of contract | wei to send | storage key to store returned value | calldata and returndata... + + ;; address of contract to call + (data (i32.const 0) "\b9\4f\53\74\fc\e5\ed\bc\8e\2a\86\97\c1\53\31\67\7e\6e\bf\0b") + + ;; first message to query balance + (data (i32.const 96) "\99\93\02\1a\ed\09\37\5d\c6\b2\00\50\d2\42\d1\61\1a\f9\7e\e4\a6\e9\3c\ad") + ;; first return value will become + ;;(data (i32.const 120) "\00\00\00\00\00\0f\42\40") + + ;; second message to transfer tokens + (data (i32.const 152) "\5d\35\9f\bd\e9\29\cf\25\44\36\3b\dc\ee\4a\97\65\15\d5\f9\77\58\ef\47\6c\00\00\00\00\00\07\a1\20") ;; second message returns nothing + + ;; third message (same as first) + (data (i32.const 216) "\99\93\02\1a\ed\09\37\5d\c6\b2\00\50\d2\42\d1\61\1a\f9\7e\e4\a6\e9\3c\ad") + ;; third return value will become + ;;(data (i32.const 240) "\00\00\00\00\00\07\a1\20") + + ;; fourth message to query balance + (data (i32.const 272) "\99\93\02\1a\e9\29\cf\25\44\36\3b\dc\ee\4a\97\65\15\d5\f9\77\58\ef\47\6c") + ;; fourth return value will become + ;;(data (i32.const 304) "\00\00\00\00\00\07\a1\20") + + (export "main" (func $main)) + (export "memory" (memory 0)) + (func $main + + + ;; call the precompile at address b94...f0b and send value 0 Eth + ;; gas addrOffset valOffset dataOffset dataLength + (drop (call $call (i64.const 200000) (i32.const 0) (i32.const 32) (i32.const 96) (i32.const 24))) + ;; get return data + ;; resultOffset dataOffset length + (call $returnDataCopy (i32.const 120) (i32.const 0) (i32.const 8)) + ;; store result in storage + (i32.store8 (i32.const 95) (i32.const 0)) + ;; pathOffset valueOffset + (call $storageStore (i32.const 64) (i32.const 120)) + (call $printMemHex (i32.const 120) (i32.const 32)) + (call $printStorageHex (i32.const 64)) + + ;; call the precompile at address b94...f0b and send value 0 Eth + ;; gas addrOffset valOffset dataOffset dataLength + (drop (call $call (i64.const 200000) (i32.const 0) (i32.const 32) (i32.const 152) (i32.const 32))) + ;; get return data + ;; resultOffset dataOffset length + (call $returnDataCopy (i32.const 184) (i32.const 0) (i32.const 0)) + ;; store result in storage + (i32.store8 (i32.const 95) (i32.const 1)) + ;; pathOffset valueOffset + (call $storageStore (i32.const 64) (i32.const 184)) + (call $printMemHex (i32.const 184) (i32.const 32)) + (call $printStorageHex (i32.const 64)) + + + ;; call the precompile at address b94...f0b and send value 0 Eth + ;; gas addrOffset valOffset dataOffset dataLength + (drop (call $call (i64.const 200000) (i32.const 0) (i32.const 32) (i32.const 216) (i32.const 24))) + ;; get return data + ;; resultOffset dataOffset length + (call $returnDataCopy (i32.const 240) (i32.const 0) (i32.const 8)) + ;; store result in storage + (i32.store8 (i32.const 95) (i32.const 2)) + ;; pathOffset valueOffset + (call $storageStore (i32.const 64) (i32.const 240)) + (call $printMemHex (i32.const 240) (i32.const 32)) + (call $printStorageHex (i32.const 64)) + + + ;; call the precompile at address b94...f0b and send value 0 Eth + ;; gas addrOffset valOffset dataOffset dataLength + (drop (call $call (i64.const 200000) (i32.const 0) (i32.const 32) (i32.const 272) (i32.const 24))) + ;; get return data + ;; resultOffset dataOffset length + (call $returnDataCopy (i32.const 304) (i32.const 0) (i32.const 8)) + ;; store result in storage + (i32.store8 (i32.const 95) (i32.const 3)) + ;; pathOffset valueOffset + (call $storageStore (i32.const 64) (i32.const 304)) + (call $printMemHex (i32.const 304) (i32.const 32)) + (call $printStorageHex (i32.const 64)) + + ) + ) + nonce: '0' + storage: {} + + b94f5374fce5edbc8e2a8697c15331677e6ebf0b: + balance: '100000000000' + code: | + (module + (type $0 (func (param i32 i32))) + (type $1 (func (result i32))) + (type $2 (func (param i32 i32 i32))) + (type $3 (func (param i32))) + (type $4 (func)) + (type $5 (func (param i64) (result i64))) + (memory $0 1) + (import "ethereum" "revert" (func $fimport$0 (param i32 i32))) + (import "ethereum" "finish" (func $fimport$1 (param i32 i32))) + (import "ethereum" "getCallDataSize" (func $fimport$2 (result i32))) + (import "ethereum" "callDataCopy" (func $fimport$3 (param i32 i32 i32))) + (import "ethereum" "storageLoad" (func $fimport$4 (param i32 i32))) + (import "ethereum" "storageStore" (func $fimport$5 (param i32 i32))) + (import "ethereum" "getTxOrigin" (func $fimport$6 (param i32))) + (import "ethereum" "getCaller" (func $fimport$7 (param i32))) + (export "memory" (memory $0)) + (export "main" (func $0)) + (func $0 (; 8 ;) (type $4) + (block $label$1 + (block $label$2 + (br_if $label$2 + (i32.ge_u + (call $fimport$2) + (i32.const 4) + ) + ) + (call $fimport$0 + (i32.const 0) + (i32.const 0) + ) + (br $label$1) + ) + (call $fimport$3 + (i32.const 0) + (i32.const 0) + (i32.const 4) + ) + (block $label$3 + (br_if $label$3 + (i32.eqz + (i32.eq + (i32.load + (i32.const 0) + ) + (i32.const 436376473) + ) + ) + ) + (call $1) + (br $label$1) + ) + (block $label$4 + (br_if $label$4 + (i32.eqz + (i32.eq + (i32.load + (i32.const 0) + ) + (i32.const -1113639587) + ) + ) + ) + (call $2) + (br $label$1) + ) + (call $fimport$0 + (i32.const 0) + (i32.const 0) + ) + ) + ) + (func $1 (; 9 ;) (type $4) + (block $label$1 + (block $label$2 + (br_if $label$2 + (i32.eq + (call $fimport$2) + (i32.const 24) + ) + ) + (call $fimport$0 + (i32.const 0) + (i32.const 0) + ) + (br $label$1) + ) + (call $fimport$3 + (i32.const 0) + (i32.const 4) + (i32.const 20) + ) + (call $fimport$4 + (i32.const 0) + (i32.const 32) + ) + (i64.store + (i32.const 32) + (call $3 + (i64.load + (i32.const 32) + ) + ) + ) + (call $fimport$1 + (i32.const 32) + (i32.const 8) + ) + ) + ) + (func $2 (; 10 ;) (type $4) + (local $0 i64) + (local $1 i64) + (local $2 i64) + (block $label$1 + (block $label$2 + (br_if $label$2 + (i32.eq + (call $fimport$2) + (i32.const 32) + ) + ) + (call $fimport$0 + (i32.const 0) + (i32.const 0) + ) + (br $label$1) + ) + (call $fimport$7 + (i32.const 0) + ) + (call $fimport$3 + (i32.const 32) + (i32.const 4) + (i32.const 20) + ) + (call $fimport$3 + (i32.const 64) + (i32.const 24) + (i32.const 8) + ) + (set_local $0 + (call $3 + (i64.load + (i32.const 64) + ) + ) + ) + (call $fimport$4 + (i32.const 0) + (i32.const 64) + ) + (set_local $1 + (i64.load + (i32.const 64) + ) + ) + (call $fimport$4 + (i32.const 32) + (i32.const 64) + ) + (set_local $2 + (i64.load + (i32.const 64) + ) + ) + (block $label$3 + (br_if $label$3 + (i64.le_u + (get_local $0) + (get_local $1) + ) + ) + (call $fimport$0 + (i32.const 0) + (i32.const 0) + ) + (br $label$1) + ) + (set_local $1 + (i64.sub + (get_local $1) + (get_local $0) + ) + ) + (set_local $2 + (i64.add + (get_local $2) + (get_local $0) + ) + ) + (i64.store + (i32.const 64) + (get_local $1) + ) + (call $fimport$5 + (i32.const 0) + (i32.const 64) + ) + (i64.store + (i32.const 64) + (get_local $2) + ) + (call $fimport$5 + (i32.const 32) + (i32.const 64) + ) + ) + ) + (func $3 (; 11 ;) (type $5) (param $0 i64) (result i64) + (local $1 i64) + (local $2 i64) + (block $label$1 + (loop $label$2 + (br_if $label$1 + (i64.ge_u + (get_local $1) + (i64.const 8) + ) + ) + (set_local $2 + (i64.add + (i64.shl + (i64.shr_u + (i64.shl + (get_local $0) + (i64.sub + (i64.const 56) + (i64.mul + (get_local $1) + (i64.const 8) + ) + ) + ) + (i64.const 56) + ) + (i64.sub + (i64.const 56) + (i64.mul + (i64.const 8) + (get_local $1) + ) + ) + ) + (get_local $2) + ) + ) + (set_local $1 + (i64.add + (get_local $1) + (i64.const 1) + ) + ) + (br $label$2) + ) + ) + (get_local $2) + ) + ) + + nonce: '' + storage: { + "0xeD09375DC6B20050d242d1611af97eE4A6E93CAd000000000000000000000000" : "0x40420f0000000000000000000000000000000000000000000000000000000000" + } + expect: + - indexes: + data: !!int -1 + gas: !!int -1 + value: !!int -1 + network: + - ALL + result: + eD09375DC6B20050d242d1611af97eE4A6E93CAd: + storage: { + "0x0000000000000000000000000000000000000000000000000000000000000000" : "0x00000000000f4240000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000001" : "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000002" : "0x000000000007a120000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000003" : "0x000000000007a120000000000000000000000000000000000000000000000000" + } + transaction: + data: + - '' + gasLimit: + - '0x5000001' + gasPrice: '0x01' + nonce: '0x00' + secretKey: 45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8 + to: '0xeD09375DC6B20050d242d1611af97eE4A6E93CAd' + value: + - '0' From a27f8aa4b7ec6d54f4bb34a466f3bfd142829f9f Mon Sep 17 00:00:00 2001 From: poemm <36397285+poemm@users.noreply.github.com> Date: Sun, 10 Feb 2019 16:15:45 -0600 Subject: [PATCH 2/7] typo --- handwritten/wrc20_handwritten_faster_get_balance.wat | 1 - handwritten/wrc20_handwritten_faster_transfer.wat | 1 - 2 files changed, 2 deletions(-) diff --git a/handwritten/wrc20_handwritten_faster_get_balance.wat b/handwritten/wrc20_handwritten_faster_get_balance.wat index 94cb9ab..5cef5f9 100644 --- a/handwritten/wrc20_handwritten_faster_get_balance.wat +++ b/handwritten/wrc20_handwritten_faster_get_balance.wat @@ -5,7 +5,6 @@ (func $callDataCopy (import "ethereum" "callDataCopy") (param i32 i32 i32)) (func $storageLoad (import "ethereum" "storageLoad") (param i32 i32)) (func $storageStore (import "ethereum" "storageStore") (param i32 i32)) - (func $getTxOrigin (import "ethereum" "getTxOrigin") (param i32)) (func $getCaller (import "ethereum" "getCaller") (param i32)) (memory (export "memory") 1) (func (export "main") diff --git a/handwritten/wrc20_handwritten_faster_transfer.wat b/handwritten/wrc20_handwritten_faster_transfer.wat index b77a23b..bfc321e 100644 --- a/handwritten/wrc20_handwritten_faster_transfer.wat +++ b/handwritten/wrc20_handwritten_faster_transfer.wat @@ -5,7 +5,6 @@ (func $callDataCopy (import "ethereum" "callDataCopy") (param i32 i32 i32)) (func $storageLoad (import "ethereum" "storageLoad") (param i32 i32)) (func $storageStore (import "ethereum" "storageStore") (param i32 i32)) - (func $getTxOrigin (import "ethereum" "getTxOrigin") (param i32)) (func $getCaller (import "ethereum" "getCaller") (param i32)) (memory (export "memory") 1) (func (export "main") From 11dc6bf3ddf6f62da928058dffa74be29005ea48 Mon Sep 17 00:00:00 2001 From: poemm <36397285+poemm@users.noreply.github.com> Date: Sun, 10 Feb 2019 16:30:09 -0600 Subject: [PATCH 3/7] add corresponding wasm --- C/wrc20_ewasmified.wasm | Bin 0 -> 1271 bytes .../wrc20_handwritten_faster_get_balance.wasm | Bin 0 -> 573 bytes .../wrc20_handwritten_faster_transfer.wasm | Bin 0 -> 577 bytes 3 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 C/wrc20_ewasmified.wasm create mode 100644 handwritten/wrc20_handwritten_faster_get_balance.wasm create mode 100644 handwritten/wrc20_handwritten_faster_transfer.wasm diff --git a/C/wrc20_ewasmified.wasm b/C/wrc20_ewasmified.wasm new file mode 100644 index 0000000000000000000000000000000000000000..6a314bfc593830ff662a40b2cc43c41b1860f8b2 GIT binary patch literal 1271 zcmds1!EVzq82*1dac#V*nFLaAxIL98=x)><0ts>3jZ-5qTcu?kX+Rom#M02z@dij7 za^p4f2)qDN4?Ce9cH}StcA7?gfnG=y+u!g1&zF4vCqq0-5CBlIFc@ATm`w`s( zFlG*TOuk`@o9xh}=3UZ0Fxg&wbo3<7;{C}71JG=-)Vw!o2G~TlUe%d<)00ymOlz3m6~4!Z|n)c8mS@n}7bDg>Vod0N`$}Ns|dQ0Vho{Nfo9yKE^nvDds(!v~6tf zqFik6ZJYr7lbcSjGia}ot(HydVYhn}CSjxVU;$U=(pARm{o5hXipxRLkHeNd?T6QE zNu>-oxN6sUA$!5bAcX7ia$SLd`EANYHtNSi0w)SPJ;)b7$vFq|$ya2YvoaXo3Q8zb zVH_pMH?T)w-riq7@Z`7*%H!&ietrM`JkDt$>ro)(!7{OOvYF_Z9VIwdE5~T#DU@=G zD8|_Udeg3QY+AI;z*N{T%nbGgsA4spZU!8)1jybEK;&!Cc(FEtMh#C@)TCilCAMo+ z#Y2&0xhbFpm}j|C){uBO;cE=M%QCkIwN#Fuo`c#;PzyYbtTk~Qa~xH%#Q)bM{{V{& Bb>RR2 literal 0 HcmV?d00001 diff --git a/handwritten/wrc20_handwritten_faster_transfer.wasm b/handwritten/wrc20_handwritten_faster_transfer.wasm new file mode 100644 index 0000000000000000000000000000000000000000..005c3f359ffb45292ae19e3b6169a0f3a89553bd GIT binary patch literal 577 zcmY+AzfQw25XSG$NgL``7>R*_!P(#m=oqKa2??Pth^Y~nwo*e;8juS8vmwOHg2c{i z^bwemcmc#CFmP!Dr1s#upTGP3$q)@=1OVJFwP`kkHsGu+W?6+<$Hx?>^nzv2rd^xZ z>$sHI8=Is6|Ky@~*&B8XWW8h4M%3@`M`_gR-CDpuarG?cjltCj=#R@`I!L09Jsd>m z1*d9`TYPH^d@X;$CLo0C@N!*&faMJ;#Wo%!BLXLmdY4eHypwYb6i}eZI7c-wycJYY zW`%K-puoTmfq8y?e8c8J4V1^Xzx3nt`|EB&*YX(!QttgaZZ%gO9kZzf`)cJFZS<}H zRoN5V8&9E>Pl#fghtaE}s>Gt@_#Dg@>xG%a!obgx&Vel#z(-aVTB1OM#*;!4jT$CC zYSJ+FiNzYT6blzOYiSvZU0f;aNE}K88bj~2#-m|9E2oqDu>KI%Lr){un%Igtj(x21 HA83+4R&aL1 literal 0 HcmV?d00001 From 905163f4ea0759eea2d08acc30ac79edc176f78e Mon Sep 17 00:00:00 2001 From: poemm <36397285+poemm@users.noreply.github.com> Date: Sun, 10 Feb 2019 17:09:29 -0600 Subject: [PATCH 4/7] make generator more convenient --- tester/README.md | 4 +++- tester/generate_wrc20_filler.py | 10 +++++----- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/tester/README.md b/tester/README.md index 9757cf8..de39ed7 100644 --- a/tester/README.md +++ b/tester/README.md @@ -2,10 +2,12 @@ WRC20 is defined up to the interface, and each implementation can internally store balances in their own way. So first choose a footer.txt with the correct internal representation of your initial state, it is in the curly braces at the top. +We have a script to wrap a `wrc20.wat` into an ewasm test which executes each of the four tests in the original description of wrc20 https://gist.github.com/axic/16158c5c88fbc7b1d09dfa8c658bc363 . + Generate the test filler. ```sh -python3 generate_wrc20_filler.py wrc20.wat footer1.txt +python3 generate_wrc20_filler.py wrc20.wat header.txt footer1.txt ``` The output is `wrc20Filler.yml`. You need an ewasm client which can handle yml fillers. For example, we follow notes from the ewasm benchmarking repo which also uses the test system. diff --git a/tester/generate_wrc20_filler.py b/tester/generate_wrc20_filler.py index 9d3e5ca..722b95e 100644 --- a/tester/generate_wrc20_filler.py +++ b/tester/generate_wrc20_filler.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 - -def generate_filler_from_wat(name, footer_filename): + +def generate_filler_from_wat(name, header_filename, footer_filename): name = name.split(".")[0] # first the name at top of the filler, then the "header" @@ -8,7 +8,7 @@ def generate_filler_from_wat(name, footer_filename): f_filler.write("# Test WRC20, see https://gist.github.com/axic/16158c5c88fbc7b1d09dfa8c658bc363\n") f_filler.write("---\n") f_filler.write(name+":\n") - f_header = open("header.txt", 'r') + f_header = open(header_filename, 'r') for line in f_header: f_filler.write(line) @@ -22,8 +22,8 @@ def generate_filler_from_wat(name, footer_filename): f_footer = open(footer_filename, 'r') for line in f_footer: f_filler.write(line) - + if __name__ == "__main__": import sys - generate_filler_from_wat(sys.argv[1], sys.argv[2]) + generate_filler_from_wat(sys.argv[1], sys.argv[2], sys.argv[3]) From 5c12adfa869184b0a5a38f59d59a1fda84011bc3 Mon Sep 17 00:00:00 2001 From: poemm <36397285+poemm@users.noreply.github.com> Date: Sun, 10 Feb 2019 17:27:07 -0600 Subject: [PATCH 5/7] recompile C version --- C/Makefile | 3 ++- C/wrc20.wasm | Bin 1431 -> 1422 bytes C/wrc20_ewasmified.wasm | Bin 1271 -> 1262 bytes 3 files changed, 2 insertions(+), 1 deletion(-) diff --git a/C/Makefile b/C/Makefile index dbec17b..48e259d 100644 --- a/C/Makefile +++ b/C/Makefile @@ -1,6 +1,7 @@ .PHONY: all -LLVM_BUILD_DIR=/path/to/llvm-build +#LLVM_BUILD_DIR=/path/to/llvm-build +LLVM_BUILD_DIR=/home/user/repos/benchmarking/wasmception/build/llvm all: $(LLVM_BUILD_DIR)/bin/clang -cc1 -Ofast -emit-llvm -triple=wasm32-unknown-unknown-wasm wrc20.c diff --git a/C/wrc20.wasm b/C/wrc20.wasm index b446f778155b8ddbc755f683e88d5df82b47b040..0d4889a24f6bbbfcdc93f448181c68bb1b5bd8e7 100755 GIT binary patch delta 64 zcmbQv-N&uKkXW3{$iTqBD9)O|z*wKaRA0}Kz+4X^8G)E#qGlr_%f{8+%sdQ^cVGQ^ QQ|-pfpun)%i6xW~0RC$cegFUf delta 73 zcmeC+;G6FHfM9rm)EE~_iXX0USy!-0U Qn`$>+1_g%Ar+;G6FFJLjoI+0|XNlmNK$#JocW6 Xht2Wst3Pk5-FO)k*ft+z)@1|$_=Xm# From fb1b2b3ee11d51cc406700eb89fddfe79957a158 Mon Sep 17 00:00:00 2001 From: poemm <36397285+poemm@users.noreply.github.com> Date: Sun, 10 Feb 2019 18:01:55 -0600 Subject: [PATCH 6/7] fixes --- tester/footer1.txt | 2 +- tester/header.txt | 20 ++++++++++---------- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/tester/footer1.txt b/tester/footer1.txt index c3c65b3..6e71084 100644 --- a/tester/footer1.txt +++ b/tester/footer1.txt @@ -1,6 +1,6 @@ nonce: '' storage: { - "0xeD09375DC6B20050d242d1611af97eE4A6E93CAd000000000000000000000000" : "0x40420f0000000000000000000000000000000000000000000000000000000000" + "0xeD09375DC6B20050d242d1611af97eE4A6E93CAd000000000000000000000000" : "0x00000000000f4240000000000000000000000000000000000000000000000000" } expect: - indexes: diff --git a/tester/header.txt b/tester/header.txt index a319d58..2b34df3 100644 --- a/tester/header.txt +++ b/tester/header.txt @@ -18,8 +18,8 @@ (import "ethereum" "storageStore" (func $storageStore (param i32 i32))) (import "ethereum" "call" (func $call (param i64 i32 i32 i32 i32) (result i32))) (import "ethereum" "returnDataCopy" (func $returnDataCopy (param i32 i32 i32))) - (import "debug" "printStorageHex" (func $printStorageHex (param i32))) - (import "debug" "printMemHex" (func $printMemHex (param i32 i32))) + ;;(import "debug" "printStorageHex" (func $printStorageHex (param i32))) + ;;(import "debug" "printMemHex" (func $printMemHex (param i32 i32))) (memory 1) ;; memory looks like this @@ -62,8 +62,8 @@ (i32.store8 (i32.const 95) (i32.const 0)) ;; pathOffset valueOffset (call $storageStore (i32.const 64) (i32.const 120)) - (call $printMemHex (i32.const 120) (i32.const 32)) - (call $printStorageHex (i32.const 64)) + ;;(call $printMemHex (i32.const 120) (i32.const 32)) + ;;(call $printStorageHex (i32.const 64)) ;; call the precompile at address b94...f0b and send value 0 Eth ;; gas addrOffset valOffset dataOffset dataLength @@ -75,8 +75,8 @@ (i32.store8 (i32.const 95) (i32.const 1)) ;; pathOffset valueOffset (call $storageStore (i32.const 64) (i32.const 184)) - (call $printMemHex (i32.const 184) (i32.const 32)) - (call $printStorageHex (i32.const 64)) + ;;(call $printMemHex (i32.const 184) (i32.const 32)) + ;;(call $printStorageHex (i32.const 64)) ;; call the precompile at address b94...f0b and send value 0 Eth @@ -89,8 +89,8 @@ (i32.store8 (i32.const 95) (i32.const 2)) ;; pathOffset valueOffset (call $storageStore (i32.const 64) (i32.const 240)) - (call $printMemHex (i32.const 240) (i32.const 32)) - (call $printStorageHex (i32.const 64)) + ;;(call $printMemHex (i32.const 240) (i32.const 32)) + ;;(call $printStorageHex (i32.const 64)) ;; call the precompile at address b94...f0b and send value 0 Eth @@ -103,8 +103,8 @@ (i32.store8 (i32.const 95) (i32.const 3)) ;; pathOffset valueOffset (call $storageStore (i32.const 64) (i32.const 304)) - (call $printMemHex (i32.const 304) (i32.const 32)) - (call $printStorageHex (i32.const 64)) + ;;(call $printMemHex (i32.const 304) (i32.const 32)) + ;;(call $printStorageHex (i32.const 64)) ) ) From 3553ea7c87fcb1012e6d76c28ba0cbe878fe55c2 Mon Sep 17 00:00:00 2001 From: poemm <36397285+poemm@users.noreply.github.com> Date: Tue, 26 Feb 2019 13:07:26 -0600 Subject: [PATCH 7/7] add tester footer3.txt --- tester/footer3.txt | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 tester/footer3.txt diff --git a/tester/footer3.txt b/tester/footer3.txt new file mode 100644 index 0000000..c3c65b3 --- /dev/null +++ b/tester/footer3.txt @@ -0,0 +1,30 @@ + nonce: '' + storage: { + "0xeD09375DC6B20050d242d1611af97eE4A6E93CAd000000000000000000000000" : "0x40420f0000000000000000000000000000000000000000000000000000000000" + } + expect: + - indexes: + data: !!int -1 + gas: !!int -1 + value: !!int -1 + network: + - ALL + result: + eD09375DC6B20050d242d1611af97eE4A6E93CAd: + storage: { + "0x0000000000000000000000000000000000000000000000000000000000000000" : "0x00000000000f4240000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000001" : "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000002" : "0x000000000007a120000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000003" : "0x000000000007a120000000000000000000000000000000000000000000000000" + } + transaction: + data: + - '' + gasLimit: + - '0x5000001' + gasPrice: '0x01' + nonce: '0x00' + secretKey: 45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8 + to: '0xeD09375DC6B20050d242d1611af97eE4A6E93CAd' + value: + - '0'