diff --git a/Makefile b/Makefile index 5ddd8dc..f747c9b 100644 --- a/Makefile +++ b/Makefile @@ -2,7 +2,8 @@ SRC=src/index.js src/bare-agent.js src/index.html DID_SRC=src/ledger.did src/governance.did NIX_SRC=default.nix ic-qr-scanner.nix node-env.nix node-packages.nix shell.nix NPM_SRC=webpack.config.js src/simple.min.css -ALL_SRC=$(SRC) $(DID_SRC) $(NIX_SRC) $(NPM_SRC) +OTHER_SRC=src/manifest.json src/favicon.ico src/logo.png +ALL_SRC=$(SRC) $(DID_SRC) $(NIX_SRC) $(NPM_SRC) $(OTHER_SRC) all: fmt build @@ -18,13 +19,21 @@ dist/index.html dist/main.bundle.js &: $(SRC) $(DID_SRC) $(NPM_SRC) fmt: $(SRC) webpack.config.js prettier -w $(SRC) webpack.config.js -dist/monic.wasm: dist/index.html - cd dist && sh ../monic.sh index.html - sha256sum dist/index.html dist/monic.wasm +dist/app.o: dist/app.c + clang --target=wasm32 -c -O3 $^ -o $@ -install: dist/monic.wasm - install -D dist/monic.did ${out}/bin/ic-qr-scanner.did - install -D dist/monic.wasm ${out}/bin/ic-qr-scanner.wasm +dist/app.wasm: dist/app.o + wasm-ld --no-entry --export-dynamic --allow-undefined $^ -o $@ + +dist/app.did: + touch $@ + +dist/app.c: dist/index.html $(OTHER_SRC) + echo -e "/,./dist/index.html\n/manifest.json,./src/manifest.json\n/logo.png,./src/logo.png\n/favicon.ico,./src/favicon.ico" | sh epic.sh > $@ + +install: dist/app.wasm dist/app.did + install -D dist/app.did ${out}/bin/ic-qr-scanner.did + install -D dist/app.wasm ${out}/bin/ic-qr-scanner.wasm dist/canister_ids.json: canister_ids.json cd dist && ln -s ../canister_ids.json . @@ -33,7 +42,7 @@ result : $(ALL_SRC) nix-build ic-qr-scanner.nix dfx.json: - echo '{"canisters":{"monic":{"type":"custom","candid":"result/bin/ic-qr-scanner.did","wasm":"result/bin/ic-qr-scanner.wasm","build":""}}}' > dfx.json + echo '{"canisters":{"app":{"type":"custom","candid":"result/bin/ic-qr-scanner.did","wasm":"result/bin/ic-qr-scanner.wasm","build":""}}}' > $@ release: result dfx.json dfx deploy --network=ic @@ -41,7 +50,4 @@ release: result dfx.json clean: rm -rf dist result dfx.json .dfx -nix-build: - cp `nix-build ic-qr-scanner.nix`/bin/* . - -.PHONY: all fmt build release install clean nix-build +.PHONY: all fmt build release install clean diff --git a/README.md b/README.md index 1d3fd8a..869ecd8 100644 --- a/README.md +++ b/README.md @@ -38,7 +38,7 @@ Module hash: 0xde6c0dfa550b39f0d8ec19c0eac488fdf9201530a61f9bbfe97554eaad0c357c ``` Acknowledgement: -* Single page deployment on IC using the minimalistic tool [monic], courtesy of [blynn]. +* Single page deployment on IC using the minimalistic tool [epic], courtesy of [blynn]. * QR scanning is from [zbar.wasm]. * CSS is from [Simple.css]. @@ -47,7 +47,7 @@ Acknowledgement: [Add to Home screen]: https://developer.mozilla.org/en-US/docs/Web/Progressive_web_apps/Add_to_home_screen [zbar.wasm]: https://github.com/samsam2310/zbar.wasm [Simple.css]: https://simplecss.org -[monic]: https://fmfd2-7qaaa-aaaae-aaapq-cai.raw.ic0.app +[epic]: https://fxa77-fiaaa-aaaae-aaana-cai.raw.ic0.app/epic [blynn]: https://crypto.stanford.edu/~blynn To learn more about developing apps on the Internet Computer, see the following documentation available online: diff --git a/canister_ids.json b/canister_ids.json index 23f9f24..9427398 100644 --- a/canister_ids.json +++ b/canister_ids.json @@ -1,5 +1,5 @@ { - "monic": { + "app": { "ic": "p5deo-6aaaa-aaaab-aaaxq-cai" } -} \ No newline at end of file +} diff --git a/epic.sh b/epic.sh new file mode 100755 index 0000000..0f60080 --- /dev/null +++ b/epic.sh @@ -0,0 +1,104 @@ +#!/usr/bin/env bash +# This tool is taken from https://fxa77-fiaaa-aaaae-aaana-cai.raw.ic0.app/epic + +set -e +n=0 +while read x; do + path=$(echo "$x" | cut -d, -f1) + file=$(echo "$x" | cut -d, -f2) + echo "char file$n[]={" + cat $file | xxd -p | sed 's/../0x&,/g' + echo "};" + tab[$n]="$path,file$n,sizeof(file$n)" + n=$((n+1)) +done +cat << EOF +typedef unsigned size_t; +int strcmp(const char*s1,const char*s2){ +if (*s1==*s2) { + return *s1 ? strcmp(s1+1,s2+1) : 0; +} else return 1; +} +EOF +( +echo "struct pathdesc {char*name;char*contents;unsigned contents_size;};"; +echo "%%"; +printf '%s\n' "${tab[@]}"; +) | gperf -t +cat << EOF +#define WASM_IMPORT(m,n) __attribute__((import_module(m))) __attribute__((import_name(n))); +#define WASM_EXPORT(n) asm(n) __attribute__((visibility("default"))) +void arg_data_copy(void *, int, int) WASM_IMPORT("ic0", "msg_arg_data_copy"); +void reply_data_append(void *, int) WASM_IMPORT("ic0", "msg_reply_data_append"); +void reply(void) WASM_IMPORT("ic0", "msg_reply"); + +typedef unsigned u; +u arg_i; +u byte() { + char buf[1]; + arg_data_copy(buf, arg_i++, 1); + return *buf; +} +u leb128() { + u n = 0, base = 1; + for(;;) { + u d = byte(); + if (d <= 127) return base*d + n; + n += base*(d - 128); + base *= 128; + } +} +void scan_type() { + u n; + switch(byte()) { + case 0x6e: // Opt + case 0x6d: // Vec. + scan_type(); + break; + case 0x6c: // Rec. + case 0x6b: // Variant. + n = leb128(); + while(n--) leb128(), scan_type(); + break; + } +} + +char path[16384]; + +void go() WASM_EXPORT("canister_query http_request"); +void go() { + u n = 4; + while(n--) byte(); // "DIDL" + n = leb128(); // Type table. + while(n--) scan_type(); + leb128(); // Arg count. Expect 1. + byte(); // Expect type #0, a record. + + char hdr[] = "DIDL\x03\x6c\x03\xa2\xf5\xed\x88\x04\x01\xc6\xa4\xa1\x98\x06\x02\x9a\xa1\xb2\xf9\x0c\x7a\x6d\x7b\x6d\x7f\x01\x00"; + char ftr[] = "\x00\xc8\x00"; + char not_found[] = "\x03" "404\x00\x94\x01"; + reply_data_append(hdr, sizeof(hdr) - 1); + + char buf[5]; + u path_size = leb128(); + arg_data_copy(path, arg_i, path_size); + for (n = 0; n < path_size; n++) if (path[n] == '?') { path_size = n; break; } + path[path_size] = 0; + struct pathdesc *p = in_word_set(path, path_size); + if (!p) { + reply_data_append(not_found, sizeof(not_found) - 1); + } else { + n = p->contents_size; + int i; + for (i = 0; i < 4; i++) { + buf[i] = (n & 127) | 128; + n >>= 7; + } + buf[i] = n; + reply_data_append(buf, 5); + reply_data_append(p->contents, p->contents_size); + reply_data_append(ftr, sizeof(ftr) - 1); + } + reply(); +} +EOF diff --git a/ic-qr-scanner.nix b/ic-qr-scanner.nix index c02d6bb..6f1660f 100644 --- a/ic-qr-scanner.nix +++ b/ic-qr-scanner.nix @@ -29,6 +29,7 @@ in stdenv.mkDerivation { nativeBuildInputs = [ nodejs gnumake + gperf nodePackages.prettier nodePackages.webpack xxd diff --git a/monic.sh b/monic.sh deleted file mode 100755 index 252fe2c..0000000 --- a/monic.sh +++ /dev/null @@ -1,59 +0,0 @@ -#! /usr/bin/env bash -# This tool is taken from https://p5deo-6aaaa-aaaab-aaaxq-cai.raw.ic0.app/. - -set -e -function mkC() { -echo "char msg[] = {" -cat $1 | xxd -p | sed 's/../0x&,/g' -echo "};" -cat<>= 7; - } - buf[i] = n; - - reply_data_append(buf, 5); - reply_data_append(msg, sizeof(msg)); - reply_data_append(ftr, sizeof(ftr) - 1); - reply(); -} -EOF -} -command -v clang >/dev/null 2>&1 || { echo >&2 "Please install clang"; exit 1; } -linker=wasm-ld -command -v $linker >/dev/null 2>&1 || { - linker=wasm-ld-11 - command -v $linker >/dev/null 2>&1 || { - echo >&2 "Please install wasm-ld-10 or wasm-ld-11"; exit 1; - } -} - -if [ "$1" == "" ]; then -echo Usage: $0 FILE -exit 1 -fi -if [ ! -f $1 ]; then -echo No such file: $1 -exit 1 -fi -mkC $1 > monic.c -wcc="clang --target=wasm32 -c -O3" -wld="$linker --no-entry --export-dynamic --allow-undefined" -$wcc monic.c -$wld monic.o -o monic.wasm -touch monic.did -echo '{"canisters":{"monic":{"type":"custom","candid":"monic.did","wasm":"monic.wasm","build":""}}}' > dfx.json diff --git a/shell.nix b/shell.nix index 5e603bf..45ef9ba 100644 --- a/shell.nix +++ b/shell.nix @@ -5,6 +5,7 @@ stdenv.mkDerivation { nativeBuildInputs = [ nodejs gnumake + gperf nodePackages.prettier nodePackages.node2nix pkgsCross.wasi32.buildPackages.clang_10 diff --git a/src/favicon.ico b/src/favicon.ico new file mode 100644 index 0000000..f83d96e Binary files /dev/null and b/src/favicon.ico differ diff --git a/src/index.html b/src/index.html index 1216c87..f3c12b3 100644 --- a/src/index.html +++ b/src/index.html @@ -4,6 +4,7 @@ <%= htmlWebpackPlugin.options.title %> +