Merge pull request #22 from jacqueswww/substrate

Substrate Examples
This commit is contained in:
Jacques Wagener 2020-01-21 12:29:46 +02:00 committed by GitHub
commit a18f3ce052
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
21 changed files with 623 additions and 35 deletions

3
.gitignore vendored
View File

@ -3,4 +3,7 @@ tools/wabt/*
tools/abi_gen
examples/*.wasm
.priv_key_hex
*.wasm
tests/ee/ewasm-scout/
tests/substrate/node_modules/

View File

@ -9,18 +9,28 @@ NLVM_WAMS32_FLAGS= --nlvm.target=wasm32 --gc:none -l:--no-entry -l:--allow-undef
DOCKER_NLVM_C=$(DOCKER_NLVM) $(PATH_PARAMS) $(NLVM_WAMS32_FLAGS) c
# Use nim + clang
DOCKER_NIM_CLANG=docker run -e HOME='/tmp/' --user $(user_id):$(user_id) -w /code/ -v $(pwd):/code/ --entrypoint="/usr/bin/nim" jacqueswww/nimclang --verbosity:2
DOCKER_NIM_CLANG_PASS_FLAGS = --passC:"--target=wasm32-unknown-unknown-wasm" \
--passL:"--target=wasm32-unknown-unknown-wasm" --passC:"-I./include" --clang.options.linker:"-nostdlib -Wl,--no-entry,--allow-undefined,--strip-all,--export-dynamic"
DOCKER_NIM_CLANG_FLAGS=$(DOCKER_NIM_CLANG_PASS_FLAGS) --os:standalone --cpu:i386 --cc:clang --gc:none --nomain -d:release
CLANG_OPTIONS_LINKER=-nostdlib -Wl,--no-entry,--allow-undefined,--strip-all,--export-dynamic
# Ewasm
DOCKER_NIM_CLANG_C=$(DOCKER_NIM_CLANG) --cc:clang $(PATH_PARAMS) c
DOCKER_NIM_CLANG_WASM32_C=$(DOCKER_NIM_CLANG) $(DOCKER_NIM_CLANG_FLAGS) $(PATH_PARAMS) c
DOCKER_NIM_CLANG_PASS_FLAGS_EWASM = --passC:"--target=wasm32-unknown-unknown-wasm" \
--passL:"--target=wasm32-unknown-unknown-wasm" --passC:"-I./include" --clang.options.linker:"$(CLANG_OPTIONS_LINKER)"
DOCKER_NIM_CLANG_FLAGS_EWASM=$(DOCKER_NIM_CLANG_PASS_FLAGS_EWASM) --os:standalone --cpu:i386 --cc:clang --gc:none --nomain -d:release
DOCKER_NIM_CLANG_EWASM_C=$(DOCKER_NIM_CLANG) $(DOCKER_NIM_CLANG_FLAGS_EWASM) $(PATH_PARAMS) c
# Substrate
DOCKER_NIM_CLANG_PASS_FLAGS_SUBSTRATE = --passC:"--target=wasm32-unknown-unknown-wasm" \
--passL:"--target=wasm32-unknown-unknown-wasm" --passC:"-I./include" \
--clang.options.linker:"$(CLANG_OPTIONS_LINKER),--import-memory,--max-memory=131072"
DOCKER_NIM_CLANG_FLAGS_SUBSTRATE=$(DOCKER_NIM_CLANG_PASS_FLAGS_SUBSTRATE) --os:standalone --cpu:i386 --cc:clang --gc:none --nomain -d:release
SUBSTRATE_NIMC=$(DOCKER_NIM_CLANG) $(DOCKER_NIM_CLANG_FLAGS_SUBSTRATE) $(PATH_PARAMS) c
ifdef USE_NLVM
NIMC=$(DOCKER_NLVM_C)
WASM32_NIMC=$(DOCKER_NLVM_C)
EWASM_NIMC=$(DOCKER_NLVM_C)
else
NIMC=$(DOCKER_NIM_CLANG_C)
WASM32_NIMC=$(DOCKER_NIM_CLANG_WASM32_C)
EWASM_NIMC=$(DOCKER_NIM_CLANG_EWASM_C)
endif
.PHONY: all
@ -59,30 +69,42 @@ vendors:
cd vendors
git submodule update --init
.PHONY: king_of_the_hill
king_of_the_hill:
$(WASM32_NIMC) --out:examples/king_of_the_hill.wasm examples/king_of_the_hill.nim
.PHONY: ewasm_king_of_the_hill
ewasm_king_of_the_hill:
$(EWASM_NIMC) --out:examples/king_of_the_hill.wasm examples/king_of_the_hill.nim
$(POSTPROCESS) examples/king_of_the_hill.wasm
.PHONY: examples
examples: king_of_the_hill
$(WASM32_NIMC) --out:examples/registry.wasm examples/registry.nim
ewasm-examples: ewasm_king_of_the_hill
$(EWASM_NIMC) --out:examples/registry.wasm examples/registry.nim
$(POSTPROCESS) examples/registry.wasm
$(WASM32_NIMC) --out:examples/balances.wasm examples/balances.nim
$(EWASM_NIMC) --out:examples/balances.wasm examples/balances.nim
$(POSTPROCESS) examples/balances.wasm
$(WASM32_NIMC) --out:examples/erc20.wasm examples/erc20.nim
$(EWASM_NIMC) --out:examples/erc20.wasm examples/erc20.nim
$(POSTPROCESS) examples/erc20.wasm
$(WASM32_NIMC) --out:examples/default_func.wasm examples/default_func.nim
$(EWASM_NIMC) --out:examples/default_func.wasm examples/default_func.nim
$(POSTPROCESS) examples/default_func.wasm
.PHONY: ee-examples
ee-examples:
$(WASM32_NIMC) --out:examples/ee/helloworld.wasm examples/ee/helloworld.nim
$(WASM32_NIMC) --out:examples/ee/bazaar.wasm examples/ee/bazaar.nim
$(EWASM_NIMC) --out:examples/ee/helloworld.wasm examples/ee/helloworld.nim
$(EWASM_NIMC) --out:examples/ee/block_echo.wasm examples/ee/block_echo.nim
.PHONY: test-ee
test-ee: ee-examples
cd tests/ee/; \
./test.sh
SUBSTRATE_POSTPROCESS=tools/substrate_postprocess.sh
.PHONY: substrate-examples
substrate-examples:
$(SUBSTRATE_NIMC) --out:examples/substrate/hello_world.wasm examples/substrate/hello_world.nim
$(SUBSTRATE_POSTPROCESS) examples/substrate/hello_world.wasm
$(SUBSTRATE_NIMC) --out:examples/substrate/setter.wasm examples/substrate/setter.nim
$(SUBSTRATE_POSTPROCESS) examples/substrate/setter.wasm
.PHONY: test-substrate
test-substrate: substrate-examples
cd tests/substrate; \
SUBSTRATE_PATH="${HOME}/.cargo/bin/substrate" ./test.sh

View File

@ -1,17 +0,0 @@
import system/alloc
import ../../nimplay/ee_runtime
proc main() {.exportwasm.} =
var
pre_state_root {.noinit.}: array[32, byte]
post_state_root {.noinit.}: array[32, byte]
eth2_loadPreStateRoot(addr pre_state_root)
var
block_data_size = eth2_blockDataSize()
block_data = alloc(block_data_size)
eth2_blockDataCopy(addr block_data, 0, block_data_size)
eth2_savePostStateRoot(addr post_state_root)

View File

@ -0,0 +1,24 @@
import ../../nimplay/ee_runtime
{.compile: "malloc.c".}
proc malloc(n: int): pointer {.importc.}
proc copy_into_ba(to_ba: var auto, offset: int, from_ba: auto) =
for i, x in from_ba:
if offset + i > sizeof(to_ba) - 1:
break
to_ba[offset + i] = x
proc main() {.exportwasm.} =
var
pre_state_root {.noinit.}: array[32, byte]
post_state_root {.noinit.}: array[32, byte]
eth2_loadPreStateRoot(addr pre_state_root)
var
block_data_size = eth2_blockDataSize()
block_data = malloc(block_data_size.int)
eth2_blockDataCopy(block_data, 0, block_data_size)
copyMem(addr post_state_root, block_data, 32)
eth2_savePostStateRoot(addr post_state_root[0])

View File

@ -4,3 +4,11 @@ proc rawoutput(s: string) =
revert(cstring(s), s.len.int32)
proc panic(s: string) = rawoutput(s)
{.pop.}
# Try LLVm builtin unreachable:
# void myabort(void) __attribute__((noreturn));
# void myabort(void) {
# asm("int3");
# __builtin_unreachable();
# }

View File

@ -0,0 +1,14 @@
import ../../nimplay/substrate_runtime
# Init function.
proc deploy(): uint32 {.exportwasm.} =
0
# Main function.
proc call(): uint32 {.exportwasm.} =
var
s = cstring("Hello world!")
ext_println(s, s.len.int32)
ext_scratch_write(s, s.len.int32)
0 # return

View File

@ -0,0 +1,13 @@
extern unsigned char __heap_base;
unsigned int bump_pointer = &__heap_base;
void* malloc(int n) {
unsigned int r = bump_pointer ;
bump_pointer += n;
return (void *)r;
}
void free(void* p) {
// lol
}

View File

@ -0,0 +1,6 @@
{.push stack_trace: off, profiler:off.}
proc ext_println*(offset: pointer, length: uint32) {.noreturn, cdecl, importc.}
proc rawoutput(s: string) =
ext_println(cstring(s), s.len.uint32)
proc panic(s: string) = rawoutput(s)
{.pop.}

View File

@ -0,0 +1,73 @@
import ../../nimplay/substrate_runtime
{.compile: "malloc.c".}
proc malloc(n: int): pointer {.importc.}
type
Action = enum
Set = 0'u8, Get = 1'u8, SelfEvict = 2'u8
# Init function.
proc deploy(): uint32 {.exportwasm.} =
0
proc get_scratch(): (pointer, int32) =
var
scratch_size = ext_scratch_size()
mem_ptr = malloc(scratch_size.int)
ext_scratch_read(mem_ptr, 0, scratch_size)
(mem_ptr, scratch_size)
proc print(s: cstring) =
ext_println(s, s.len.int32)
proc incr_pointer(oldp: pointer): pointer =
var newp = cast[pointer](cast[uint](oldp) + 1u)
newp
proc set_val_in_store(scratch_ptr: pointer, scratch_size: int32) =
print("Set".cstring)
var
key: array[32, byte] = [
2'u8, 2'u8, 2'u8, 2'u8, 2'u8, 2'u8, 2'u8, 2'u8, 2'u8,
2'u8, 2'u8, 2'u8, 2'u8, 2'u8, 2'u8, 2'u8, 2'u8, 2'u8,
2'u8, 2'u8, 2'u8, 2'u8, 2'u8, 2'u8, 2'u8, 2'u8, 2'u8,
2'u8, 2'u8, 2'u8, 2'u8, 2'u8
]
offset_ptr = incr_pointer(scratch_ptr)
ext_set_storage(addr key, 1.int32 , offset_ptr, scratch_size - 1)
# Main function.
proc call(): uint32 {.exportwasm.} =
var
selector: uint8
(scratch_ptr, scratch_size) = get_scratch()
copyMem(addr selector, scratch_ptr, 1)
case selector
of Action.Set.ord:
set_val_in_store(scratch_ptr, scratch_size)
of Action.Get.ord:
print("Get: Todo".cstring)
of Action.SelfEvict.ord:
print("SelfEvict: Todo".cstring)
else:
print("Unknown action passed".cstring)
0 # return
# sys::ext_set_storage(
# key.as_ptr() as u32,
# 1,
# value.as_ptr() as u32,
# value.len() as u32,
# )
# block_data = malloc(block_data_size.int)
# eth2_blockDataCopy(block_data, 0, block_data_size)
# copyMem(addr post_state_root, block_data, 32)

View File

@ -0,0 +1,30 @@
import macros
{.push cdecl, importc.}
proc ext_address*()
proc ext_block_number*()
proc ext_gas_left*()
proc ext_gas_price*()
proc ext_get_storage*(key_ptr: pointer): int32
proc ext_now*()
proc ext_println*(str_ptr: pointer, str_len: int32) # experimental; will be removed.
proc ext_random_seed*()
proc ext_scratch_read*(dest_ptr: pointer, offset: int32, len: int32)
proc ext_scratch_size*(): int32
proc ext_scratch_write*(src_ptr: pointer, len: int32)
proc ext_set_rent_allowance*(value_ptr: pointer, value_len: int32)
proc ext_set_storage*(key_ptr: pointer, value_non_null: int32, value_ptr: pointer, value_len: int32)
proc ext_value_transferred*()
{.pop.}
macro exportwasm*(p: untyped): untyped =
expectKind(p, nnkProcDef)
result = p
result.addPragma(newIdentNode("exportc"))
result.addPragma(
newColonExpr(
newIdentNode("codegenDecl"), newLit("__attribute__ ((visibility (\"default\"))) $# $#$#")
)
)

41
tests/ee/test.sh Executable file
View File

@ -0,0 +1,41 @@
#!/bin/bash
CARGO_HOME="${CARGO_HOME:-$HOME/.cargo}"
RUST_VERSION="nightly"
REPO_DIR="ewasm-scout"
REPO_URL="https://github.com/ewasm/scout.git"
SCOUT_TEST_FILES=./*.yml
if [[ -e $REPO_DIR ]]; then
rm -v $REPO_DIR/*.yml
cp $SCOUT_TEST_FILES $REPO_DIR/
cd $REPO_DIR
git pull
else
git clone $REPO_URL $REPO_DIR
rm -v $REPO_DIR/*.yml
cp $SCOUT_TEST_FILES $REPO_DIR/
cd $REPO_DIR
fi
if [[ ! -e $CARGO_HOME ]]; then
echo "Fetching rustup"
curl https://sh.rustup.rs -sSf | sh -s -- -y --no-modify-path --default-toolchain $RUST_VERSION
fi
rustup target add wasm32-unknown-unknown
rustup component add rustfmt
rustup update
cargo install chisel
# make build
cargo build --release
# make test
# target/release/phase2-scout $SCOUT_TEST_FILE
for testfile in $SCOUT_TEST_FILES
do
echo $testfile
RUST_LOG=debug target/release/phase2-scout $testfile || exit
break
done

View File

@ -0,0 +1,13 @@
beacon_state:
execution_scripts:
- ../../../examples/ee/block_echo.wasm
shard_pre_state:
exec_env_states:
- "0000000000000000000000000000000000000000000000000000000000000000"
shard_blocks:
- env: 0
data: "fafbfcfdfef0f0f0f0f0ffffffffffffffffffffffffffffffffe6e5e4e3e2e1"
shard_post_state:
exec_env_states:
- "fafbfcfdfef0f0f0f0f0ffffffffffffffffffffffffffffffffe6e5e4e3e2e1"

View File

@ -0,0 +1,33 @@
{
"name": "srml-contract-waterfall-nimplay",
"version": "1.0.0",
"main": "index.js",
"author": "Sergey Shulepov <sergei@parity.io>",
"contributors": [
"Stefanie Doll <stefie@parity.io>"
],
"license": "MIT",
"dependencies": {
"@polkadot/api": "^0.97.0-beta.39",
"@polkadot/api-contract": "^0.97.0-beta.39",
"blakejs": "^1.1.0",
"typescript": "^3.6.4"
},
"devDependencies": {
"@types/jest": "^24.0.18",
"@types/node": "^10.12.18",
"@typescript-eslint/eslint-plugin": "^2.6.0",
"@typescript-eslint/parser": "^2.6.0",
"bn.js": "^5.0.0",
"eslint": "^6.6.0",
"jest": "^24.9.0",
"ts-jest": "^24.1.0",
"ts-loader": "^5.3.2"
},
"jest": {
"preset": "ts-jest/presets/js-with-ts"
},
"scripts": {
"test": "NODE_ENV=abc jest"
}
}

22
tests/substrate/test.sh Executable file
View File

@ -0,0 +1,22 @@
#!/bin/bash
if [ -z "$SUBSTRATE_PATH" ]; then
echo "Please specify the path to substrate in the SUBSTRATE_PATH environment variable"
exit 1
fi
if [ ! -f "$SUBSTRATE_PATH" ]; then
echo "$SUBSTRATE_PATH doesn't exist"
exit 2
fi
# Purge dev chain and then spin up the substrate node in background
$SUBSTRATE_PATH purge-chain --dev -y
$SUBSTRATE_PATH --dev -l debug &
SUBSTRATE_PID=$!
# # Execute tests
yarn && yarn test --verbose
# # Kill the spawned substrate node
kill -9 $SUBSTRATE_PID

View File

@ -0,0 +1,9 @@
import BN from "bn.js";
export const WSURL = "ws://127.0.0.1:9944";
export const DOT: BN = new BN("1000000000000000");
export const CREATION_FEE: BN = DOT.muln(200);
export const GAS_REQUIRED = 50000;
export const ALICE = "5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY";
export const BOB = "5FHneW46xGXgs5mUiveU4sbTyGBzmstUspZC92UhjJM694ty";

View File

@ -0,0 +1,111 @@
// Adapted from https://github.com/paritytech/srml-contracts-waterfall/
import { ApiPromise, SubmittableResult, WsProvider } from "@polkadot/api";
import { Abi } from '@polkadot/api-contract';
import testKeyring from "@polkadot/keyring/testing";
import { u8aToHex } from "@polkadot/util";
import { randomAsU8a } from "@polkadot/util-crypto";
import { KeyringPair } from "@polkadot/keyring/types";
import { Option } from "@polkadot/types";
import { Address, ContractInfo, Hash } from "@polkadot/types/interfaces";
import { ALICE, CREATION_FEE, WSURL } from "./consts";
import {
callContract,
instantiate,
getContractStorage,
putCode
} from "./utils";
// This is a test account that is going to be created and funded each test.
const keyring = testKeyring({ type: "sr25519" });
const alicePair = keyring.getPair(ALICE);
let testAccount: KeyringPair;
let api: ApiPromise;
beforeAll((): void => {
jest.setTimeout(30000);
});
beforeEach(
async (done): Promise<() => void> => {
api = await ApiPromise.create({ provider: new WsProvider(WSURL) });
testAccount = keyring.addFromSeed(randomAsU8a(32));
return api.tx.balances
.transfer(testAccount.address, CREATION_FEE.muln(3))
.signAndSend(alicePair, (result: SubmittableResult): void => {
if (
result.status.isFinalized &&
result.findRecord("system", "ExtrinsicSuccess")
) {
console.log("New test account has been created.");
done();
}
});
}
);
describe("Nimplay Hellow World", () => {
test("Can deploy and execute", async (done): Promise<void> => {
const codeHash = await putCode(
api,
testAccount,
"../../../examples/substrate/hello_world.wasm"
);
expect(codeHash).toBeDefined();
const address: Address = await instantiate(
api,
testAccount,
codeHash,
"0x00",
CREATION_FEE
);
expect(address).toBeDefined();
await callContract(api, testAccount, address, "0x00");
done();
});
});
describe("Nimplay Storage Setter", () => {
test("Setter: Can deploy and execute", async (done): Promise<void> => {
// See https://github.com/paritytech/srml-contracts-waterfall/issues/6 for info about
// how to get the STORAGE_KEY of an instantiated contract
const STORAGE_KEY = (new Uint8Array(32)).fill(2);
// Deploy contract code on chain and retrieve the code hash
const codeHash = await putCode(
api,
testAccount,
"../../../examples/substrate/setter.wasm"
);
expect(codeHash).toBeDefined();
// Instantiate a new contract instance and retrieve the contracts address
const address: Address = await instantiate(
api,
testAccount,
codeHash,
"0x00",
CREATION_FEE
);
expect(address).toBeDefined();
const initialValue: Uint8Array = await getContractStorage(
api,
address,
STORAGE_KEY
);
expect(initialValue).toBeDefined();
expect(initialValue.toString()).toEqual("");
await callContract(api, testAccount, address, "0x00");
var val_hex = "03".repeat(32);
// "0x00" indicates calling "Set" Action
await callContract(api, testAccount, address, "0x00" + val_hex);
const newValue = await getContractStorage(api, address, STORAGE_KEY);
expect(newValue.toString()).toEqual("0x" + val_hex);
done();
});
});

View File

@ -0,0 +1,107 @@
import { ApiPromise, SubmittableResult } from "@polkadot/api";
import { KeyringPair } from "@polkadot/keyring/types";
import { Option, StorageData } from "@polkadot/types";
import { Address, ContractInfo, Hash } from "@polkadot/types/interfaces";
import BN from "bn.js";
import fs from "fs";
import path from "path";
const blake = require('blakejs')
import { GAS_REQUIRED } from "./consts";
export async function sendAndReturnFinalized(signer: KeyringPair, tx: any) {
return new Promise(function(resolve, reject) {
tx.signAndSend(signer, (result: SubmittableResult) => {
if (result.status.isFinalized) {
// Return result of the submittable extrinsic after the transfer is finalized
resolve(result as SubmittableResult);
}
if (
result.status.isDropped ||
result.status.isInvalid ||
result.status.isUsurped
) {
reject(result as SubmittableResult);
console.error("ERROR: Transaction could not be finalized.");
}
});
});
}
export async function putCode(
api: ApiPromise,
signer: KeyringPair,
fileName: string,
gasRequired: number = GAS_REQUIRED
): Promise<Hash> {
const wasmCode = fs
.readFileSync(path.join(__dirname, fileName))
.toString("hex");
const tx = api.tx.contracts.putCode(gasRequired, `0x${wasmCode}`);
const result: any = await sendAndReturnFinalized(signer, tx);
const record = result.findRecord("contracts", "CodeStored");
if (!record) {
console.error("ERROR: No code stored after executing putCode()");
}
// Return code hash.
return record.event.data[0];
}
export async function instantiate(
api: ApiPromise,
signer: KeyringPair,
codeHash: Hash,
inputData: any,
endowment: BN,
gasRequired: number = GAS_REQUIRED
): Promise<Address> {
const tx = api.tx.contracts.instantiate(
endowment,
gasRequired,
codeHash,
inputData
);
const result: any = await sendAndReturnFinalized(signer, tx);
const record = result.findRecord("contracts", "Instantiated");
if (!record) {
console.error("ERROR: No new instantiated contract");
}
// Return the address of instantiated contract.
return record.event.data[1];
}
export async function callContract(
api: ApiPromise,
signer: KeyringPair,
contractAddress: Address,
inputData: any,
gasRequired: number = GAS_REQUIRED,
endowment: number = 0
): Promise<void> {
const tx = api.tx.contracts.call(
contractAddress,
endowment,
gasRequired,
inputData
);
await sendAndReturnFinalized(signer, tx);
}
export async function getContractStorage(
api: ApiPromise,
contractAddress: Address,
storageKey: Uint8Array
): Promise<StorageData> {
const contractInfo = await api.query.contracts.contractInfoOf(
contractAddress
);
// Return the value of the contracts storage
const storageKeyBlake2b = blake.blake2bHex(storageKey, null, 32);
return await api.rpc.state.getChildStorage(
(contractInfo as Option<ContractInfo>).unwrap().asAlive.trieId,
'0x' + storageKeyBlake2b
);
}

View File

@ -0,0 +1,24 @@
{
"compilerOptions": {
"target": "esnext",
"module": "commonjs",
"lib": ["dom", "es2018"],
"resolveJsonModule": true,
"strict": true,
"noImplicitAny": true,
"strictNullChecks": true,
"strictFunctionTypes": true,
"strictBindCallApply": true,
"strictPropertyInitialization": true,
"noImplicitThis": true,
"alwaysStrict": true,
"allowJs": true,
"esModuleInterop": true
},
"exclude": [
"contracts/rust",
"lib",
"node_modules",
]
}

View File

@ -0,0 +1,24 @@
{
"compilerOptions": {
"target": "esnext",
"module": "commonjs",
"lib": ["dom", "es2018"],
"resolveJsonModule": true,
"strict": true,
"noImplicitAny": true,
"strictNullChecks": true,
"strictFunctionTypes": true,
"strictBindCallApply": true,
"strictPropertyInitialization": true,
"noImplicitThis": true,
"alwaysStrict": true,
"allowJs": true,
"esModuleInterop": true
},
"exclude": [
"contracts/rust",
"lib",
"node_modules",
]
}

9
tests/substrate/utils.ts Normal file
View File

@ -0,0 +1,9 @@
import BN from "bn.js";
export const WSURL = "ws://127.0.0.1:9944";
export const DOT: BN = new BN("1000000000000000");
export const CREATION_FEE: BN = DOT.muln(200);
export const GAS_REQUIRED = 50000;
export const ALICE = "5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY";
export const BOB = "5FHneW46xGXgs5mUiveU4sbTyGBzmstUspZC92UhjJM694ty";

19
tools/substrate_postprocess.sh Executable file
View File

@ -0,0 +1,19 @@
#!/bin/bash
WASM_FILE=$1
set -ex
#wasm2wat="tools/wabt/build/wasm2wat"
#wat2wasm="tools/wabt/build/wat2wasm"
wasm2wat="docker run --entrypoint=wasm2wat -w /code/ -v $(pwd):/code/ jacqueswww/nimclang "
wat2wasm="docker run --entrypoint=wat2wasm -w /code/ -v $(pwd):/code/ jacqueswww/nimclang "
# Replace "env" with "ethereum"
$wasm2wat "$WASM_FILE" |
sed '/(export.*deploy\|call.*/! s/(export.*//g' > ./wasm.tmp
$wat2wasm -o "$WASM_FILE" ./wasm.tmp
rm ./wasm.tmp