diff --git a/.github/workflows/fuzz.yml b/.github/workflows/fuzz.yml index cf876aa5..4bc1b48e 100644 --- a/.github/workflows/fuzz.yml +++ b/.github/workflows/fuzz.yml @@ -1,6 +1,10 @@ name: FuzzTest -on: [push, pull_request] +on: + push: + pull_request: + schedule: + - cron: '0 * * * *' # hourly jobs: build-and-run-fuzzing: @@ -48,39 +52,42 @@ jobs: version: "11.0" cached: ${{ steps.cache-llvm.outputs.cache-hit }} - - name: test_rlp on x86 with sanitizers - working-directory: ./polyjuice-tests/fuzz - run: make build/test_rlp && ./build/test_rlp - - name: test_contracts on x86 with sanitizers - working-directory: ./polyjuice-tests/fuzz - run: make build/test_contracts && ./build/test_contracts - - name: Set MAX_FUZZ_TIME for different branches run: | if [[ ${{ github.event_name == 'pull_request' }} ]]; then - echo "MAX_FUZZ_TIME=6" >> $GITHUB_ENV + echo "MAX_FUZZ_TIME=60" >> $GITHUB_ENV elif [[ ${{ startsWith(github.base_ref, 'fuzz') }} ]]; then echo "MAX_FUZZ_TIME=3600" >> $GITHUB_ENV else echo "MAX_FUZZ_TIME=60" >> $GITHUB_ENV fi - - - name: Fuzzing Polyjuice Generator 1 hour + echo "trigger type: ${{ github.event.action }}" + if [[ ${{ github.event_name }} == 'schedule' ]]; then + echo "MAX_FUZZ_TIME=3600" >> $GITHUB_ENV + fi + - name: Fuzzing Polyjuice Generator working-directory: polyjuice-tests/fuzz run: | + mkdir -p corpus mkdir -p corpus-cache - ls corpus-cache - make build/polyjuice_generator_fuzzer && \ - ./build/polyjuice_generator_fuzzer corpus corpus-cache \ + echo "num of corpus: $(ls corpus-cache | wc -l)" + echo "fuzz time: ${{ env.MAX_FUZZ_TIME }}" + make build/fuzzer && \ + LLVM_PROFILE_FILE="build/fuzzer.profraw" ./build/fuzzer corpus corpus-cache \ -max_total_time=$MAX_FUZZ_TIME -timeout=120 \ -max_len=25000 -rss_limit_mb=0 # Max data buffer size: 24KB < 25000 bytes + - name: Generate coverage report + working-directory: polyjuice-tests/fuzz + run: | + llvm-profdata merge -sparse build/fuzzer.profraw -o build/fuzzer.profdata + llvm-cov report ./build/fuzzer -instr-profile=build/fuzzer.profdata - name: merge corpus working-directory: polyjuice-tests/fuzz run: | mkdir -p corpus-new - ./build/polyjuice_generator_fuzzer -merge=1 corpus-new corpus-cache corpus + ./build/fuzzer -merge=1 corpus-new corpus-cache corpus rm -rf corpus-cache mv corpus-new corpus-cache diff --git a/.gitignore b/.gitignore index 3cbec8f3..3ada52eb 100644 --- a/.gitignore +++ b/.gitignore @@ -58,4 +58,5 @@ integration-test/ /.vscode/*.log .vscode/c_cpp_properties.json -polyjuice-tests/.vscode/ \ No newline at end of file +polyjuice-tests/.vscode/ +corpus/ diff --git a/.gitmodules b/.gitmodules index af59707c..54e25e04 100644 --- a/.gitmodules +++ b/.gitmodules @@ -28,3 +28,6 @@ [submodule "deps/godwoken-scripts"] path = deps/godwoken-scripts url = https://github.com/nervosnetwork/godwoken-scripts.git +[submodule "deps/gw-syscall-simulator"] + path = deps/gw-syscall-simulator + url = https://github.com/magicalne/gw-syscall-simulator.git diff --git a/c/polyjuice.h b/c/polyjuice.h index 359a28a8..c6e9a434 100644 --- a/c/polyjuice.h +++ b/c/polyjuice.h @@ -44,6 +44,7 @@ #define POLYJUICE_SYSTEM_PREFIX 0xFF #define POLYJUICE_CONTRACT_CODE 0x01 #define POLYJUICE_DESTRUCTED 0x02 +#define POLYJUICE_MAX_DEPTH 277 void polyjuice_build_system_key(uint32_t id, uint8_t polyjuice_field_type, uint8_t key[GW_KEY_BYTES]) { @@ -614,6 +615,13 @@ struct evmc_result call(struct evmc_host_context* context, res.release = release_result; gw_context_t* gw_ctx = context->gw_ctx; + if (msg->depth > POLYJUICE_MAX_DEPTH) { + debug_print_int("call depth exceeded", msg->depth); + res.status_code = EVMC_CALL_DEPTH_EXCEEDED; + context->error_code = FATAL_CALL_DEPTH_EXCEEDED; + return res; + } + precompiled_contract_gas_fn contract_gas; precompiled_contract_fn contract; if (match_precompiled_address(&msg->destination, &contract_gas, &contract)) { @@ -961,6 +969,7 @@ int create_new_account(gw_context_t* ctx, uint8_t script_hash[32]; blake2b_hash(script_hash, new_script_seg.ptr, new_script_seg.size); ret = ctx->sys_create(ctx, new_script_seg.ptr, new_script_seg.size, &new_account_id); + free(new_script_seg.ptr); if (ret != 0) { debug_print_int("sys_create error", ret); @@ -970,7 +979,6 @@ int create_new_account(gw_context_t* ctx, return ret; } } - free(new_script_seg.ptr); *to_id = new_account_id; memcpy((uint8_t *)msg->destination.bytes, eth_addr, 20); debug_print_int(">> new to id", *to_id); @@ -1117,6 +1125,7 @@ int handle_native_token_transfer(gw_context_t* ctx, uint32_t from_id, uint32_t new_account_id; ret = ctx->sys_create(ctx, new_script_seg.ptr, new_script_seg.size, &new_account_id); + free(new_script_seg.ptr); if (ret != 0) { ckb_debug("[handle_native_token_transfer] create new account failed."); return ret; diff --git a/c/polyjuice_errors.h b/c/polyjuice_errors.h index 5b060bf1..7f7b3a81 100644 --- a/c/polyjuice_errors.h +++ b/c/polyjuice_errors.h @@ -7,6 +7,7 @@ */ #define FATAL_POLYJUICE -50 #define FATAL_PRECOMPILED_CONTRACTS -51 +#define FATAL_CALL_DEPTH_EXCEEDED -52 /* Normal errors in polyjuice */ #define ERROR_MOD_EXP -80 diff --git a/deps/gw-syscall-simulator b/deps/gw-syscall-simulator new file mode 160000 index 00000000..5066e167 --- /dev/null +++ b/deps/gw-syscall-simulator @@ -0,0 +1 @@ +Subproject commit 5066e167c9603eeb8a3d7e4effc725a007f39111 diff --git a/polyjuice-tests/fuzz/.gitignore b/polyjuice-tests/fuzz/.gitignore deleted file mode 100644 index 1fab0f90..00000000 --- a/polyjuice-tests/fuzz/.gitignore +++ /dev/null @@ -1,11 +0,0 @@ -/build*/ - -target/ -artifacts/ - -coverage/ -/corpus/* -!/corpus/regression/ -!/corpus/merged/ - -/*CORPUS* diff --git a/polyjuice-tests/fuzz/Makefile b/polyjuice-tests/fuzz/Makefile index e76e77c2..31d579c2 100644 --- a/polyjuice-tests/fuzz/Makefile +++ b/polyjuice-tests/fuzz/Makefile @@ -10,8 +10,8 @@ ifeq ($(OS),Unknown) endif NPROC?=4 -CC=clang CXX=clang++ +CC=clang LLVM_PROFDATA=llvm-profdata LLVM_COV=llvm-cov @@ -22,7 +22,7 @@ SECP_DIR := $(DEPS)/secp256k1-fix SECP256K1_SRC := $(SECP_DIR)/src/ecmult_static_pre_context.h CFLAGS_SECP := -isystem $(SECP_DIR)/src -isystem $(SECP_DIR) -CFLAGS_CKB_STD = -I./ -I$(DEPS)/ckb-c-stdlib -I$(DEPS)/ckb-c-stdlib/molecule +CFLAGS_CKB_STD = -I./ -I$(DEPS)/ckb-c-stdlib -I$(DEPS)/ckb-c-stdlib/molecule -Wno-incompatible-pointer-types CFLAGS_ETHASH := -I$(DEPS)/ethash/include -I$(DEPS)/ethash/lib/ethash -I$(DEPS)/ethash/lib/keccak -I$(DEPS)/ethash/lib/support CFLAGS_EVMONE := -I$(DEPS)/evmone/lib/evmone -I$(DEPS)/evmone/include -I$(DEPS)/evmone/evmc/include -I$(DEPS)/evmone/evmc/tools/ CFLAGS_SMT := -I$(DEPS)/godwoken-scripts/c/deps/sparse-merkle-tree/c @@ -31,11 +31,12 @@ CFLAGS_MBEDTLS := -I$(DEPS)/mbedtls/include CFLAGS_CRYPTO_ALGORITHMS := -I$(DEPS)/crypto-algorithms CFLAGS_INTX := -I$(DEPS)/intx/lib/intx -I$(DEPS)/intx/include CFLAGS_BN128 := -I$(DEPS)/bn128/include -CFLAGS := -Wall -O2 -I../../c -I../../c/ripemd160 $(CFLAGS_CKB_STD) $(CFLAGS_ETHASH) $(CFLAGS_EVMONE) $(CFLAGS_SMT) $(CFLAGS_GODWOKEN) $(CFLAGS_SECP) $(CFLAGS_MBEDTLS) $(CFLAGS_CRYPTO_ALGORITHMS) $(CFLAGS_INTX) $(CFLAGS_BN128) -CXXFLAGS := $(CFLAGS) -std=c++1z -LDFLAGS := -Wl,--gc-sections -SANITIZER_FLAGS := -g -O1 -fsanitize=address,undefined -Wno-incompatible-pointer-types -LIMIT_ERROR := -ferror-limit=1 +CFLAGS_GW_SIM := -I$(DEPS)/gw-syscall-simulator/include +CFLAGS := -Wall -O3 -I../../c -I../../c/ripemd160 $(CFLAGS_CKB_STD) $(CFLAGS_ETHASH) $(CFLAGS_EVMONE) $(CFLAGS_SMT) $(CFLAGS_GODWOKEN) $(CFLAGS_SECP) $(CFLAGS_MBEDTLS) $(CFLAGS_CRYPTO_ALGORITHMS) $(CFLAGS_INTX) $(CFLAGS_BN128) $(CFLAGS_GW_SIM) +CXXFLAGS := $(CFLAGS) -std=c++1z +LDFLAGS := -Wl,--gc-sections,-rpath,$(DEPS)/gw-syscall-simulator/target/debug +SANITIZER_FLAGS := -g -O1 -fsanitize=fuzzer,address,undefined,leak -Wno-incompatible-pointer-types +LIMIT_ERROR := -ferror-limit=10 # TODO: read PROTOCOL_VERSION from deps/godwoken-scripts/c/Makefile MOLC := moleculec @@ -58,38 +59,19 @@ ifeq ($(OS),MacOS) COVERAGE_FLAGS+=-Wl,-U,_LLVMFuzzerCustomMutator -Wl,-U,_LLVMFuzzerInitialize endif -EXTERNAL_HEADERS := $(DEPS)/ckb-c-stdlib-simulator-only/ckb_consts.h - -#TODO: coverage -all: generate-protocol build/polyjuice_generator_fuzzer - -build/polyjuice_generator_fuzzer: generate-protocol $(GENERATOR_DEPS) - $(CXX) $(CFLAGS) $(LDFLAGS) $(SANITIZER_FLAGS) $(LIMIT_ERROR) -fsanitize=fuzzer -Ibuild -o $@ polyjuice_generator_fuzzer.cc $(ALL_OBJS) -build/polyjuice_generator_fuzzer_log: generate-protocol $(GENERATOR_DEPS) - $(CXX) $(CFLAGS) $(LDFLAGS) $(SANITIZER_FLAGS) $(LIMIT_ERROR) -fsanitize=fuzzer -Ibuild -o $@ polyjuice_generator_fuzzer.cc $(ALL_OBJS) -DPOLYJUICE_DEBUG_LOG - -### -# TODO: -show: $(COVERAGE_DIR)/fuzzer.profdata - $(LLVM_COV) show --instr-profile=$(COVERAGE_DIR)/fuzzer.profdata smt_coverage -# TODO: report -report: $(COVERAGE_DIR)/fuzzer.profdata coverage $(EXTERNAL_HEADERS) - $(LLVM_COV) report --show-functions --instr-profile=$(COVERAGE_DIR)/fuzzer.profdata smt_coverage $(EXTERNAL_HEADERS) -# TODO: -coverage: $(EXTERNAL_HEADERS) - clang $(COVERAGE_FLAGS) smt_coverage.c smt_fuzzer.c -o smt_coverage +EXTERNAL_HEADERS := $(DEPS)/ckb-c-stdlib-simulator/ckb_consts.hckb-c-stdlib-simulator-only -# start-fuzzer: fuzzer -# ./smt_fuzzer -max_len=800000 -workers=$(NPROC) -jobs=$(NPROC) corpus +build-gw-syscall-simulator: + cd $(DEPS)/gw-syscall-simulator/ && cargo build -# start-fuzzer2: fuzzer -# ./smt_fuzzer -max_len=800000 corpus +build/fuzzer: generate-protocol $(GENERATOR_DEPS) build-gw-syscall-simulator + $(CXX) $(CFLAGS) $(LDFLAGS) $(SANITIZER_FLAGS) $(LIMIT_ERROR) -fprofile-instr-generate -fcoverage-mapping -L $(DEPS)/gw-syscall-simulator/target/debug -l gw_syscall_simluator -Ibuild -o $@ polyjuice_fuzzer.cc $(ALL_OBJS) +build/fuzzer_log: generate-protocol $(GENERATOR_DEPS) build-gw-syscall-simulator + $(CXX) $(CFLAGS) $(LDFLAGS) $(SANITIZER_FLAGS) $(LIMIT_ERROR) -L $(DEPS)/gw-syscall-simulator/target/debug -l gw_syscall_simluator -Ibuild -o $@ polyjuice_fuzzer.cc $(ALL_OBJS) -DPOLYJUICE_DEBUG_LOG clean: rm -rf $(BUILD)/* -### - build/generator: ../../c/generator.c $(GENERATOR_DEPS) cd $(SECP_DIR) && (git apply workaround-fix-g++-linking.patch || true) && cd - # apply patch $(CXX) $(SANITIZER_FLAGS) $(CFLAGS) $(LDFLAGS) -Ibuild -o $@ ../../c/generator.c $(ALL_OBJS) @@ -179,8 +161,8 @@ build/sha256.o: $(DEPS)/crypto-algorithms/sha256.c build/secp256k1_data_info.h: build/dump_secp256k1_data $< build/dump_secp256k1_data: ../../c/dump_secp256k1_data.c $(SECP256K1_SRC) - mkdir -p build - gcc $(CFLAGS) -o $@ $< + #mkdir -p build + $(CC) $(CFLAGS) -o $@ $< $(SECP256K1_SRC): cd $(SECP_DIR) && (git apply -R workaround-fix-g++-linking.patch || true) && \ chmod +x autogen.sh && ./autogen.sh && \ @@ -202,17 +184,3 @@ build/godwoken.mol: mkdir -p build curl -L -o $@ ${PROTOCOL_SCHEMA_URL}/godwoken.mol - -#TODO: -#%.h: -# ln -s $(CURDIR)/../$@ $(CURDIR)/$@ - -# %.profraw: coverage -# LLVM_PROFILE_FILE=$@ ./smt_coverage $(CORPUS_DIR)/* - -%.profdata: %.profraw - $(LLVM_PROFDATA) merge --sparse $< -o $@ - -.PHONY: all fuzzer coverage report - -.PRECIOUS: $(COVERAGE_DIR)/fuzzer.profraw $(COVERAGE_DIR)/fuzzer.profdata diff --git a/polyjuice-tests/fuzz/README.md b/polyjuice-tests/fuzz/README.md index 6040b114..ba1e567a 100644 --- a/polyjuice-tests/fuzz/README.md +++ b/polyjuice-tests/fuzz/README.md @@ -1,56 +1,62 @@ -# Polyjuice Fuzz Test - -[![FuzzTest](https://github.com/Flouse/godwoken-polyjuice/actions/workflows/fuzz.yml/badge.svg?branch=fuzz-v2)](https://github.com/Flouse/godwoken-polyjuice/actions/workflows/fuzz.yml) - -These two file were created to simulate `gw_syscalls`: -- polyjuice-tests/fuzz/ckb_syscalls.h -- polyjuice-tests/fuzz/mock_godwoken.hpp - -## Polyjuice Generator Fuzzer -```bash -make build/polyjuice_generator_fuzzer -./build/polyjuice_generator_fuzzer corpus -max_total_time=6 - -# or fuzzing in debug mode -make build/polyjuice_generator_fuzzer_log -./build/polyjuice_generator_fuzzer_log corpus -max_total_time=2 -``` - -### General Algorithm -```pseudo code -// pseudo code -Instrument program for code coverage -load pre-defined transactions such as contracts deploying and then execute run_polyjuice() -while(true) { - Choose random input from corpus - Mutate/populate input into transactions - Execute run_polyjuice() and collect coverage - If new coverage/paths are hit add it to corpus (corpus - directory with test-cases) -} -``` - -## test_contracts on x86 with [sanitizers](https://github.com/google/sanitizers) -```bash -make build/test_contracts -./build/test_contracts - -make build/test_rlp -./build/test_rlp -``` - -## How to debug Polyjuice generator on x86? -1. Compile Polyjuice generator on x86 - ```bash - cd fuzz - make build/polyjuice_generator_fuzzer - ``` -2. Construct `pre_defined_test_case` in [polyjuice_generator_fuzzer.cc](./polyjuice_generator_fuzzer.cc) -3. Run `build/polyjuice_generator_fuzzer_log` with GDB debugger, see: [launch.json](../../.vscode/launch.json) - -## Coverage Report[WIP] -TBD - -### Related materials -- https://llvm.org/docs/LibFuzzer.html -- [What makes a good fuzz target](https://github.com/google/fuzzing/blob/master/docs/good-fuzz-target.md) -- [Clang's source-based code coverage](https://clang.llvm.org/docs/SourceBasedCodeCoverage.html) +# Polyjuice fuzz testing + +## Build + +### 1. normal build + +```sh +make build/fuzzer +``` + +### 2. or build with debug log + +```sh +make build/fuzzer_log +``` + +## Run + +Simply just run with: +```sh +build/fuzzer +``` + +Or run `fuzzer_log`: +```sh +build/fuzzer_log +``` + +### Corpus and Seed + +Feeding fuzz testing with some predefined testcases: Seed. (Optional) +And save to `corpus` folder if any good cases are generated during running. + +```sh +build/fuzzer corpus seed +``` + +## Coverage Profile + +To genreate a coverage profile, we need to set `LLVM_PROFILE_FILE` and `max_total_time` first. + +```sh +LLVM_PROFILE_FILE="build/fuzzer.profraw" build/fuzzer corpus -max_total_time=10 +``` + +### Generate .profdata + +```sh +llvm-profdata merge -sparse build/fuzzer.profraw -o build/fuzzer.profdata +``` + +### Show coverage in detail (Optional) + +```sh +llvm-cov show build/fuzzer -instr-profile=build/fuzzer.profdata --show-branches=count --show-expansions > log +``` + +### Report + +```sh +llvm-cov report ./build/fuzzer -instr-profile=build/fuzzer.profdata +``` diff --git a/polyjuice-tests/fuzz/ckb_syscalls.h b/polyjuice-tests/fuzz/ckb_syscalls.h index 366bdb14..a8ef3003 100644 --- a/polyjuice-tests/fuzz/ckb_syscalls.h +++ b/polyjuice-tests/fuzz/ckb_syscalls.h @@ -5,150 +5,76 @@ #include #include #include - -#include "ckb_consts.h" -#include "secp256k1_data_info.h" - -size_t s_INPUT_SIZE = 0; -uint8_t* s_INPUT_DATA = NULL; - -extern "C" int ckb_debug(const char*); -static char debug_buf[64 * 1024]; -void dbg_print(const char* fmt, ...) { - va_list args; - va_start(args, fmt); - vsnprintf(debug_buf, sizeof(debug_buf), fmt, args); - va_end(args); - ckb_debug(debug_buf); -} -void dbg_print_h256(const uint8_t* h256_ptr) { - int offset = sprintf(debug_buf, "H256["); - for (size_t i = 0; i < 31; i++) { - offset += sprintf(debug_buf + offset, "%d, ", *(h256_ptr + i)); - } - sprintf(debug_buf + offset, "%d]", *(h256_ptr + 31)); - ckb_debug(debug_buf); -} -void dbg_print_hex(const uint8_t* ptr, size_t size) { - printf("0x"); - for (size_t i = 0; i < size; i++) { - printf("%02x", ptr[i]); - } - printf("\n"); -} - -#ifndef POLYJUICE_DEBUG_LOG -#undef dbg_print -#undef dbg_print_h256 -#undef dbg_print_hex -#define dbg_print(...) do {} while (0) -#define dbg_print_h256(p) do {} while (0) -#define dbg_print_hex(p) do {} while (0) -#endif - -#define MOCK_SUCCESS 0 - -int ckb_exit(int8_t code) { - printf("ckb_exit, code=%d\n", code); - exit(0); - return MOCK_SUCCESS; -} +#include + +#include "api.h" + +/* syscalls */ +/* Syscall account store / load / create */ +#define GW_SYS_CREATE 3100 +#define GW_SYS_STORE 3101 +#define GW_SYS_LOAD 3102 +#define GW_SYS_LOAD_ACCOUNT_SCRIPT 3105 +/* Syscall call / return */ +#define GW_SYS_SET_RETURN_DATA 3201 +/* Syscall data store / load */ +#define GW_SYS_STORE_DATA 3301 +#define GW_SYS_LOAD_DATA 3302 +/* Syscall load metadata structures */ +#define GW_SYS_LOAD_ROLLUP_CONFIG 3401 +#define GW_SYS_LOAD_TRANSACTION 3402 +#define GW_SYS_LOAD_BLOCKINFO 3403 +#define GW_SYS_GET_BLOCK_HASH 3404 +/* Syscall builtins */ +#define GW_SYS_PAY_FEE 3501 +#define GW_SYS_LOG 3502 +#define GW_SYS_RECOVER_ACCOUNT 3503 + +#define GW_ERROR_NOT_FOUND 83 // Mock implementation for the SYS_ckb_load_cell_data_as_code syscall in // _ckb_load_cell_code. #define syscall(n, a0, a1, a2, a3, a4, a5) \ __internal_syscall(n, (long)(a0), (long)(a1), (long)(a2), (long)(a3), \ - (long)(a4), (long)(a5)) + (long)(a4), (long)(a5)) static int inline __internal_syscall(long n, long _a0, long _a1, long _a2, - long _a3, long _a4, long _a5); + long _a3, long _a4, long _a5); #ifdef GW_GENERATOR #include "generator_utils.h" -#include "mock_godwoken.hpp" #endif -static int inline __internal_syscall(long n, long _a0, long _a1, long _a2, - long _a3, long _a4, long _a5) { +static int inline __internal_syscall(long n, long a0, long a1, long a2, + long a3, long a4, long a5) { switch (n) { - // mock syscall(GW_SYS_LOAD_TRANSACTION, addr, &inner_len, 0, 0, 0, 0) - case GW_SYS_LOAD_TRANSACTION: // Load Layer2 Transaction - return gw_load_transaction_from_raw_tx((uint8_t *)_a0, (uint64_t *)_a1); - - // mock syscall(GW_SYS_LOAD, raw_key, value, 0, 0, 0, 0) - case GW_SYS_LOAD: - dbg_print("====== mock syscall(GW_SYS_LOAD) ======"); - dbg_print("raw_key:"); - dbg_print_h256((uint8_t*)_a0); - gw_sys_load((uint8_t *)_a0, (uint8_t *)_a1); - // always return 0, even the key(_a0) is not found - return MOCK_SUCCESS; - - // mock syscall(GW_SYS_LOAD_DATA, data, &inner_len, offset, data_hash, 0, 0) - case GW_SYS_LOAD_DATA: - /* match ckb_secp256k1_data_hash, load secp256k1_data */ - // TODO: move this to fuzz_init() step - if (0 == memcmp((uint8_t *)_a3, ckb_secp256k1_data_hash, 32)) { - FILE* stream = fopen("./build/secp256k1_data", "rb"); - int ret = fread((uint8_t *)_a0, CKB_SECP256K1_DATA_SIZE, 1, stream); - fclose(stream); - stream = NULL; - if (ret != 1) { // ret = The total number of elements successfully read - return GW_ERROR_NOT_FOUND; - } - *(uint64_t *)_a1 = CKB_SECP256K1_DATA_SIZE; - return MOCK_SUCCESS; - } - return gw_sys_load_data((uint8_t *)_a0, (uint64_t *)_a1, _a2, (uint8_t *)_a3); - - // mock syscall(GW_SYS_STORE_DATA, data_len, data, 0, 0, 0, 0) - case GW_SYS_STORE_DATA: - return gw_store_data(_a0, (uint8_t *)_a1); - - // mock syscall(GW_SYS_SET_RETURN_DATA, *data, len, 0, 0, 0, 0) - case GW_SYS_SET_RETURN_DATA: - dbg_print("mock syscall(GW_SYS_SET_RETURN_DATA)"); - gw_sys_set_return_data((uint8_t *)_a0, _a1); - return MOCK_SUCCESS; - - // mock syscall(GW_SYS_GET_BLOCK_HASH, block_hash, number, 0, 0, 0, 0) - case GW_SYS_GET_BLOCK_HASH: - dbg_print("mock syscall(GW_SYS_GET_BLOCK_HASH"); - gw_sys_get_block_hash((uint8_t *)_a0, _a1); - return MOCK_SUCCESS; - - // mock syscall(GW_SYS_STORE, raw_key, value, 0, 0, 0, 0) + case GW_SYS_CREATE: + return gw_create((uint8_t*)a0, (uint64_t)a1, (uint32_t*)a2); case GW_SYS_STORE: - gw_update_raw((uint8_t *)_a0, (uint8_t *)_a1); - return MOCK_SUCCESS; - - // mock syscall(GW_SYS_LOAD_BLOCKINFO, addr, &inner_len, 0, 0, 0, 0) - case GW_SYS_LOAD_BLOCKINFO: - return gw_sys_load_blockinfo((uint8_t *)_a0, (uint64_t *)_a1); - - // mock syscall(GW_SYS_LOAD_ACCOUNT_SCRIPT, script, &inner_len, offset, account_id, 0, 0) + return gw_store((uint8_t*)a0, (uint8_t*)a1); + case GW_SYS_LOAD: + return gw_load((uint8_t*)a0, (uint8_t*)a1); case GW_SYS_LOAD_ACCOUNT_SCRIPT: - return gw_sys_load_account_script((uint8_t *)_a0, (uint64_t *)_a1, _a2, _a3); - - // mock syscall(GW_SYS_LOAD_ROLLUP_CONFIG, addr, &inner_len, 0, 0, 0, 0) + return gw_load_account_script((void*)a0, (uint64_t*)a1, (uint64_t)a2, (uint32_t)a3); + case GW_SYS_SET_RETURN_DATA: + return gw_set_return_data((uint8_t*)a0, (uint64_t)a1); + case GW_SYS_STORE_DATA: + return gw_store_data((uint8_t*)a0, (uint64_t)a1); + case GW_SYS_LOAD_DATA: + return gw_load_data((void*)a0, (uint64_t*)a1, (uint64_t)a2, (uint8_t*)a3); case GW_SYS_LOAD_ROLLUP_CONFIG: - return gw_sys_load_rollup_config((uint8_t *)_a0, (uint64_t *)_a1); - - // mock syscall(GW_SYS_CREATE, script, script_len, account_id, 0, 0, 0) - case GW_SYS_CREATE: - return gw_sys_create((uint8_t *)_a0, _a1, (uint32_t *)_a2); - - // mock syscall(GW_SYS_LOG, account_id, service_flag, data_length, data, 0, 0) - case GW_SYS_LOG: // TODO: @see emit_evm_result_log - dbg_print("[GW_SYS_LOG] service_flag[%d] account[%d] ", (uint8_t)_a1, _a1); - return 0; - - // mock syscall(GW_SYS_PAY_FEE, payer_addr, short_addr_len, sudt_id, &amount, 0, 0) + return gw_load_rollup_config((uint8_t*)a0, (uint64_t*)a1); + case GW_SYS_LOAD_TRANSACTION: + return gw_load_tx((void*)a0, (uint64_t*)a1); + case GW_SYS_LOAD_BLOCKINFO: + return gw_load_block_info((void*)a0, (uint64_t*)a1); + case GW_SYS_GET_BLOCK_HASH: + return gw_get_block_hash((uint8_t*)a0, (uint64_t)a1); case GW_SYS_PAY_FEE: - // TODO: payer: payer_addr[short_addr_len] - dbg_print("[mock SYS_PAY_FEE] sudt_id: %d, amount: %ld", - (uint32_t)_a2, *(uint128_t *)_a3); return 0; - + case GW_SYS_LOG: + return gw_log((uint32_t)a0, (uint8_t)a1, (uint64_t)a2, (uint8_t*)a3); + case GW_SYS_RECOVER_ACCOUNT: + return 0; default: return GW_ERROR_NOT_FOUND; } diff --git a/polyjuice-tests/fuzz/corpus/regression/ASAN-Deadlysignal-crash-6f3702a66330ed540a7d42305dbd4bd4d17a71ed b/polyjuice-tests/fuzz/corpus/regression/ASAN-Deadlysignal-crash-6f3702a66330ed540a7d42305dbd4bd4d17a71ed deleted file mode 100644 index 68fb19e5..00000000 Binary files a/polyjuice-tests/fuzz/corpus/regression/ASAN-Deadlysignal-crash-6f3702a66330ed540a7d42305dbd4bd4d17a71ed and /dev/null differ diff --git a/polyjuice-tests/fuzz/corpus/regression/crash-invalid_evmc_call_kind-bacf98820dec04240e7cd642d82caee2d101d340 b/polyjuice-tests/fuzz/corpus/regression/crash-invalid_evmc_call_kind-bacf98820dec04240e7cd642d82caee2d101d340 deleted file mode 100644 index cde2d6e8..00000000 Binary files a/polyjuice-tests/fuzz/corpus/regression/crash-invalid_evmc_call_kind-bacf98820dec04240e7cd642d82caee2d101d340 and /dev/null differ diff --git a/polyjuice-tests/fuzz/corpus/regression/data_len_0-bbc41c6f36ffa2427d747c699157eda798918b1f b/polyjuice-tests/fuzz/corpus/regression/data_len_0-bbc41c6f36ffa2427d747c699157eda798918b1f deleted file mode 100644 index 0adc4ff8..00000000 Binary files a/polyjuice-tests/fuzz/corpus/regression/data_len_0-bbc41c6f36ffa2427d747c699157eda798918b1f and /dev/null differ diff --git a/polyjuice-tests/fuzz/corpus/regression/get_code_size-timeout b/polyjuice-tests/fuzz/corpus/regression/get_code_size-timeout deleted file mode 100644 index 553a5ef0..00000000 Binary files a/polyjuice-tests/fuzz/corpus/regression/get_code_size-timeout and /dev/null differ diff --git a/polyjuice-tests/fuzz/corpus/regression/global-buffer-overflow-e21cb854facce1ea3475dc37d6aba45f2e4e5fef b/polyjuice-tests/fuzz/corpus/regression/global-buffer-overflow-e21cb854facce1ea3475dc37d6aba45f2e4e5fef deleted file mode 100644 index acaae50e..00000000 Binary files a/polyjuice-tests/fuzz/corpus/regression/global-buffer-overflow-e21cb854facce1ea3475dc37d6aba45f2e4e5fef and /dev/null differ diff --git a/polyjuice-tests/fuzz/corpus/regression/invalid_evmc_status_code b/polyjuice-tests/fuzz/corpus/regression/invalid_evmc_status_code deleted file mode 100644 index 7fec782e..00000000 Binary files a/polyjuice-tests/fuzz/corpus/regression/invalid_evmc_status_code and /dev/null differ diff --git a/polyjuice-tests/fuzz/corpus/regression/raw_tx_call_getChainId b/polyjuice-tests/fuzz/corpus/regression/raw_tx_call_getChainId deleted file mode 100644 index f6f9a56f..00000000 Binary files a/polyjuice-tests/fuzz/corpus/regression/raw_tx_call_getChainId and /dev/null differ diff --git a/polyjuice-tests/fuzz/corpus/regression/raw_tx_deploy_getChainId_contract b/polyjuice-tests/fuzz/corpus/regression/raw_tx_deploy_getChainId_contract deleted file mode 100644 index e75974fb..00000000 Binary files a/polyjuice-tests/fuzz/corpus/regression/raw_tx_deploy_getChainId_contract and /dev/null differ diff --git a/polyjuice-tests/fuzz/mock_godwoken.hpp b/polyjuice-tests/fuzz/mock_godwoken.hpp deleted file mode 100644 index 3c6a8455..00000000 --- a/polyjuice-tests/fuzz/mock_godwoken.hpp +++ /dev/null @@ -1,489 +0,0 @@ -#include - -#include -#include -#include - -#include - -using namespace std; -using namespace evmc; - -class MockedGodwoken : public MockedHost { -public: - uint32_t account_count = 0; - unordered_map state; - unordered_map code_store; - uint8_t rollup_config[GW_MAX_ROLLUP_CONFIG_SIZE]; - uint32_t rollup_config_size; - - result call(const evmc_message& msg) noexcept override { - auto result = MockedHost::call(msg); - return result; - } - - /// Overwrite get_block_hash (EVMC host method). - /// disable blockhashes record - bytes32 get_block_hash(int64_t block_number) const noexcept override { - return block_hash; - } -}; - -struct fuzz_input { - evmc_revision rev{}; - evmc_message msg{}; - bytes raw_tx; - MockedGodwoken mock_gw; - - /// Creates invalid input. - fuzz_input() noexcept { msg.gas = -1; } - - explicit operator bool() const noexcept { return msg.gas != -1; } -}; -auto in = fuzz_input{}; -MockedGodwoken* gw_host = &in.mock_gw; - - -extern "C" int ckb_debug(const char* str) { - cout << "[debug] " << str << endl; - return 0; -} - -#ifndef POLYJUICE_DEBUG_LOG -#undef ckb_debug -#define ckb_debug(s) do {} while (0) -#endif - -inline ostream& operator<<(ostream& stream, const bytes32& b32) { - stream << "H256["; - for (size_t i = 0; i < 31; i++) - stream << (uint16_t)b32.bytes[i] << ", "; - return stream << (uint16_t)b32.bytes[31] << ']'; -} -inline ostream& operator<<(ostream& stream, const bytes& bs) { - for (auto &&i : bs){ - stream << (uint16_t)i << ' '; - } - return stream; -} - -bytes32 u256_to_bytes32(const uint8_t u8[32]) { - auto ret = bytes32{}; - memcpy(ret.bytes, u8, 32); - return ret; -} - -// void dbg_print_bytes32(bytes32& b32) { -// dbg_print(<< b32); -// } - -extern "C" void gw_update_raw(const uint8_t k[GW_KEY_BYTES], const uint8_t v[GW_KEY_BYTES]){ - in.mock_gw.state[u256_to_bytes32(k)] = u256_to_bytes32(v); -} - -/* store code or script */ -extern "C" int gw_store_data(const uint64_t len, uint8_t *data) { - uint8_t script_hash[GW_KEY_BYTES]; - blake2b_hash(script_hash, data, len); - - - if (len < 0 || len > GW_MAX_DATA_SIZE) { - dbg_print("[gw_store_data] !!!!!! warning: data_len = %ld !!!!!!", len); - dbg_print("Exceeded max store data size"); - return GW_FATAL_INVALID_DATA; - } - - // store(data_hash_key, H256::one) insert data hash into SMT - uint8_t data_hash_key[GW_KEY_BYTES]; - gw_build_data_hash_key(script_hash, data_hash_key); - uint32_t one = 1; - uint8_t h256_one[GW_VALUE_BYTES] = {0}; - memcpy(h256_one, &one, sizeof(uint32_t)); - gw_update_raw(data_hash_key, h256_one); - - gw_host->code_store[u256_to_bytes32(script_hash)] = bytes((uint8_t *)data, len); - return 0; -} - -extern "C" int gw_sys_load_data(uint8_t *addr, - uint64_t *len_ptr, - uint64_t offset, - uint8_t data_hash[GW_KEY_BYTES]) { - auto search = gw_host->code_store.find(u256_to_bytes32(data_hash)); - if (search == gw_host->code_store.end()) { - return GW_ERROR_NOT_FOUND; - } - *len_ptr = search->second.size(); - search->second.copy(addr, *len_ptr); - return 0; -} - -void print_state() { - for (auto kv : gw_host->state) { - cout << "\t key:\t" << kv.first << endl << "\t value:\t" << kv.second << endl; - } -} - -// sys_load from state -extern "C" int gw_sys_load(const uint8_t k[GW_KEY_BYTES], uint8_t v[GW_KEY_BYTES]) { - auto search = gw_host->state.find(u256_to_bytes32(k)); - if (search == gw_host->state.end()) { - dbg_print("gw_sys_load failed, missing key:"); - dbg_print_h256(k); - // dbg_print("all the state as following:"); - // print_state(); - return GW_ERROR_NOT_FOUND; - } - memcpy(v, search->second.bytes, GW_KEY_BYTES); - return 0; -} - -// load raw layer2 transaction data from fuzzInput.raw_tx -extern "C" int gw_load_transaction_from_raw_tx(uint8_t* addr, uint64_t* len) { - *len = in.raw_tx.size(); - in.raw_tx.copy(addr, *len); - return 0; -} - -extern "C" void gw_sys_set_return_data(uint8_t* addr, uint64_t len) { - // should not make a new result - // in.mock_gw.call_result = make_result(evmc_status_code{}, 0, addr, len); - dbg_print("gw_sys_set_return_data:"); - // cout << bytes(addr, len) << endl; -} - -extern "C" void gw_sys_get_block_hash(uint8_t block_hash[GW_KEY_BYTES], uint64_t number) { - memcpy(block_hash, gw_host->get_block_hash(number).bytes, GW_KEY_BYTES); -} - -extern "C" int gw_sys_load_blockinfo(uint8_t* bi_addr, uint64_t* len_ptr) { - /** - * TODO: block_info fuzzInput - * struct BlockInfo { - * block_producer_id: Uint32, - * number: Uint64, - * timestamp: Uint64} - */ - const uint8_t mock_new_block_info[] = {0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; - *len_ptr = sizeof(mock_new_block_info); - dbg_print("mock_new_block_info to " - "{0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}"); - memcpy((uint8_t*)bi_addr, mock_new_block_info, *len_ptr); - return 0; -} - -extern "C" int gw_sys_load_script_hash_by_account_id(const uint32_t account_id, uint8_t script_hash[GW_KEY_BYTES]) { - // dbg_print("sys_get_script_hash_by_account_id account_id = %d", account_id); - - uint8_t key[32] = {0}; - gw_build_account_field_key(account_id, GW_ACCOUNT_SCRIPT_HASH, key); - return gw_sys_load(key, script_hash); - - // FIXME read script_hash from mock State+CodeStore - // static const uint8_t test_script_hash[6][32] = { - // {231, 196, 69, 164, 212, 229, 83, 6, 137, 240, 237, 105, 234, 223, 101, 133, 197, 66, 85, 214, 112, 85, 87, 71, 17, 170, 138, 126, 128, 173, 186, 76}, - // {50, 15, 9, 23, 166, 82, 42, 69, 226, 148, 203, 184, 168, 8, 210, 62, 226, 187, 187, 21, 122, 141, 152, 55, 88, 230, 63, 204, 23, 3, 166, 102}, - // {221, 60, 233, 16, 227, 19, 49, 118, 137, 43, 193, 160, 145, 21, 141, 6, 43, 206, 191, 210, 105, 160, 112, 23, 155, 184, 101, 113, 47, 247, 216, 122}, - // {48, 160, 141, 250, 92, 214, 34, 124, 231, 78, 106, 179, 173, 80, 61, 55, 161, 156, 45, 114, 214, 222, 9, 77, 4, 104, 52, 44, 30, 149, 27, 36}, - // {103, 167, 175, 25, 71, 242, 5, 31, 102, 236, 38, 188, 223, 212, 241, 99, 13, 4, 40, 150, 151, 55, 40, 147, 64, 29, 108, 50, 37, 159, 55, 137}, - // {125, 181, 86, 185, 69, 172, 188, 175, 36, 25, 118, 119, 114, 72, 199, 183, 204, 25, 147, 120, 109, 220, 192, 171, 10, 235, 47, 230, 42, 210, 169, 223}}; -} - -// extern "C" int gw_sys_get_script_hash_by_short_address(uint8_t *script_hash_addr, -// uint8_t *prefix_addr, -// uint64_t prefix_len) { -// for (auto pair : gw_host->code_store) { -// if (0 == memcmp(pair.first.bytes, prefix_addr, prefix_len)) { -// memcpy(script_hash_addr, pair.first.bytes, sizeof(pair.first.bytes)); -// return 0; -// } -// } - -// dbg_print("gw_sys_get_script_hash_by_short_address failed"); -// return GW_ERROR_NOT_FOUND; -// } - -extern "C" int gw_sys_load_account_id_by_script_hash(uint8_t *script_hash, - uint32_t *account_id_ptr) { - uint8_t raw_id_key[GW_KEY_BYTES]; - gw_build_script_hash_to_account_id_key(script_hash, raw_id_key); - uint8_t result_addr[GW_KEY_BYTES]; - int ret = gw_sys_load(raw_id_key, result_addr); - if (ret != 0) return ret; - *account_id_ptr = *((uint32_t *)result_addr); - return 0; -} - -extern "C" int gw_sys_load_account_script(uint8_t *script_addr, - uint64_t *len_ptr, - const uint64_t offset, - const uint32_t account_id) { - uint8_t script_hash[GW_KEY_BYTES]; - int ret = gw_sys_load_script_hash_by_account_id(account_id, script_hash); - if (ret != 0) { - return ret; - } - return gw_sys_load_data(script_addr, len_ptr, offset, script_hash); -} - -extern "C" int gw_sys_load_rollup_config(uint8_t *addr, - uint64_t *len_ptr) { - *len_ptr = gw_host->rollup_config_size; - memcpy(addr, gw_host->rollup_config, *len_ptr); - return 0; -} - -/// mock_mint_sudt on layer2 -void mock_mint_sudt(uint32_t sudt_id, uint32_t account_id, uint128_t balance) -{ - uint8_t script_hash[GW_KEY_BYTES] = {0}; - gw_sys_load_script_hash_by_account_id(account_id, script_hash); - - // _sudt_build_key - uint8_t key[GW_KEY_BYTES + 8] = {0}; - uint64_t key_len = DEFAULT_SHORT_SCRIPT_HASH_LEN + 8; - const uint32_t SUDT_KEY_FLAG_BALANCE = 1; - const uint32_t short_script_hash_len = DEFAULT_SHORT_SCRIPT_HASH_LEN; - memcpy(key, (uint8_t *)(&SUDT_KEY_FLAG_BALANCE), sizeof(uint32_t)); - memcpy(key + 4, (uint8_t *)(&short_script_hash_len), sizeof(uint32_t)); - memcpy(key + 8, script_hash, short_script_hash_len); - uint8_t raw_key[GW_KEY_BYTES]; - gw_build_account_key(sudt_id, key, key_len, raw_key); - - uint8_t value[32] = {0}; - *(uint128_t *)value = balance; - - // sys_store balance - gw_update_raw(raw_key, value); -} - -extern "C" int gw_sys_create(uint8_t *script, uint64_t script_len, uint32_t *account_id_ptr) { - int ret = 0; - - // Return error if script_hash is exists - uint8_t script_hash[GW_KEY_BYTES]; - blake2b_hash(script_hash, script, script_len); - if (0 == gw_sys_load_account_id_by_script_hash(script_hash, account_id_ptr)) { - dbg_print("script_hash is exists"); - return GW_ERROR_DUPLICATED_SCRIPT_HASH; - } - - // check script hash type - mol_seg_t script_seg; - script_seg.ptr = script; - script_seg.size = script_len; - mol_seg_t hash_type_seg = MolReader_Script_get_hash_type(&script_seg); - const uint8_t SCRIPT_HASH_TYPE_TYPE = 1; - if ((*(uint8_t *)hash_type_seg.ptr) != SCRIPT_HASH_TYPE_TYPE) { - dbg_print("script hash type = %d", *(uint8_t *)hash_type_seg.ptr); - return GW_ERROR_UNKNOWN_SCRIPT_CODE_HASH; - } - -#pragma push_macro("errno") -#undef errno - // Check script validity - mol_seg_t code_hash_seg = MolReader_Script_get_code_hash(&script_seg); - if (code_hash_seg.size != 32) { - dbg_print("[GW_FATAL_INVALID_DATA] MolReader_Script_get_code_hash"); - return GW_FATAL_INVALID_DATA; - } - /* check allowed EOA list */ - mol_seg_t rollup_config_seg = {gw_host->rollup_config, gw_host->rollup_config_size}; - mol_seg_t eoa_list_seg = - MolReader_RollupConfig_get_allowed_eoa_type_hashes(&rollup_config_seg); - uint32_t len = MolReader_Byte32Vec_length(&eoa_list_seg); - bool is_eos_account = false; - for (uint32_t i = 0; i < len; i++) { - mol_seg_res_t allowed_code_hash_res = MolReader_Byte32Vec_get(&eoa_list_seg, i); - if (memcmp(allowed_code_hash_res.seg.ptr, hash_type_seg.ptr, code_hash_seg.size) != 0) { - continue; - } - if (allowed_code_hash_res.errno != MOL_OK || - allowed_code_hash_res.seg.size != code_hash_seg.size) { - ckb_debug("disallow script because eoa code_hash is invalid"); - return GW_FATAL_INVALID_DATA; - } else { - is_eos_account = true; - break; - } - } - if (!is_eos_account) { - /* check allowed contract list */ - mol_seg_t contract_list_seg = - MolReader_RollupConfig_get_allowed_contract_type_hashes(&rollup_config_seg); - len = MolReader_Byte32Vec_length(&contract_list_seg); - - for (uint32_t i = 0; i < len; i++) { - mol_seg_res_t allowed_code_hash_res = MolReader_Byte32Vec_get(&contract_list_seg, i); - if (memcmp(allowed_code_hash_res.seg.ptr, code_hash_seg.ptr, - code_hash_seg.size) != 0) continue; - if (allowed_code_hash_res.errno != MOL_OK || - allowed_code_hash_res.seg.size != code_hash_seg.size) { - ckb_debug("disallow script because contract code_hash is invalid"); - return GW_FATAL_INVALID_DATA; - } else { - // check that contract'script must start with a 32 bytes rollup_script_hash - mol_seg_t args_seg = MolReader_Script_get_args(&script_seg); - mol_seg_t raw_args_seg = MolReader_Bytes_raw_bytes(&args_seg); - if (raw_args_seg.size < 32) { - ckb_debug("disallow contract script because args is less than 32 bytes"); - return GW_ERROR_INVALID_ACCOUNT_SCRIPT; - } - // check contract script short length - if (memcmp(g_rollup_script_hash, raw_args_seg.ptr, 32) != 0) { - ckb_debug("disallow contract script because args is not start with " - "rollup_script_hash"); - return GW_ERROR_INVALID_ACCOUNT_SCRIPT; - } - } - } - } -#pragma pop_macro("errno") - - //TODO: use create_account_from_script fn - /* Same logic from State::create_account() */ - uint32_t id = gw_host->account_count; // tmp - const uint8_t zero_nonce[GW_VALUE_BYTES] = {0}; - uint8_t account_key[GW_KEY_BYTES]; - - // store(account_nonce_key -> zero_nonce) - gw_build_account_field_key(id, GW_ACCOUNT_NONCE, account_key); - gw_update_raw(account_key, zero_nonce); - - // store(script_hash_key -> script_hash) - gw_build_account_field_key(id, GW_ACCOUNT_SCRIPT_HASH, account_key); - gw_update_raw(account_key, script_hash); - - // store(script_hash -> account_id) - uint8_t script_hash_to_id_key[GW_KEY_BYTES]; - uint8_t script_hash_to_id_value[GW_VALUE_BYTES] = {0}; - gw_build_script_hash_to_account_id_key(script_hash, script_hash_to_id_key); - memcpy(script_hash_to_id_value, (uint8_t *)(&id), 4); - gw_update_raw(script_hash_to_id_key, script_hash_to_id_value); - - // store(script hash -> script_hash) - uint8_t short_script_hash_to_script_key[32] = {0}; - ret = gw_build_short_script_hash_to_script_hash_key( - script_hash, GW_DEFAULT_SHORT_SCRIPT_HASH_LEN, - short_script_hash_to_script_key - ); - if (ret != 0) return ret; - gw_update_raw(short_script_hash_to_script_key, script_hash); - - // insert script: store_data(script_hash -> script) - ret = gw_store_data(script_len, script); - if (ret != 0) return ret; - - // account_count++ - gw_host->account_count++; - - // return id - *account_id_ptr = id; - dbg_print("new account id = %d was created.", id); - - return ret; -} - -// void create_account(uint8_t script_hash[GW_KEY_BYTES], uint32_t id) { -// } - -// create account by script and return the new account id -uint32_t create_account_from_script(uint8_t *script, uint64_t script_len) { - // uint8_t script_hash_type; - // memcpy(&script_hash_type, script + 8, sizeof(uint8_t)); - // dbg_print("script_hash_type = %d", script_hash_type); - // TODO: - // if (script_hash_type != 1) { //TODO: - // dbg_print("AccountError::UnknownScript"); - // } - - // store_data(script_hash -> script) - uint8_t script_hash[GW_KEY_BYTES]; - blake2b_hash(script_hash, script, script_len); - gw_store_data(script_len, script); - - // create account with script_hash - uint32_t id = gw_host->account_count; - const uint8_t zero_nonce[GW_VALUE_BYTES] = {0}; - - // store(account_nonce_key -> zero_nonce) - uint8_t account_nonce_key[GW_KEY_BYTES]; - gw_build_account_field_key(id, GW_ACCOUNT_NONCE, account_nonce_key); - gw_update_raw(account_nonce_key, zero_nonce); - - // store(script_hash_key -> script_hash) - uint8_t account_script_hash_key[GW_KEY_BYTES]; - gw_build_account_field_key(id, GW_ACCOUNT_SCRIPT_HASH, account_script_hash_key); - gw_update_raw(account_script_hash_key, script_hash); - - // store(script_hash -> account_id) - uint8_t script_hash_to_id_key[GW_KEY_BYTES]; - uint8_t script_hash_to_id_value[GW_VALUE_BYTES] = {0}; - gw_build_script_hash_to_account_id_key(script_hash, script_hash_to_id_key); - // FIXME: id may be more than 256 - memcpy(script_hash_to_id_value, (uint8_t *)(&id), 4); - gw_update_raw(script_hash_to_id_key, script_hash_to_id_value); - - /* init short script hash -> script_hash */ - uint8_t short_script_hash_to_script_key[32] = {0}; - gw_build_short_script_hash_to_script_hash_key( - script_hash, GW_DEFAULT_SHORT_SCRIPT_HASH_LEN, - short_script_hash_to_script_key - ); - gw_update_raw(short_script_hash_to_script_key, script_hash); - - // account_count++ - dbg_print("new account id = %d was created.", id); - return gw_host->account_count++; -} - -int init() { - // init block_hash - gw_host->block_hash = bytes32({7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7}); - - // TODO: build RollupConfig, @see polyjuice-tests/src/helper.rs - // init rollup_config - const uint8_t rollup_config[] = {189, 1, 0, 0, 60, 0, 0, 0, 92, 0, 0, 0, 124, 0, 0, 0, 156, 0, 0, 0, 188, 0, 0, 0, 220, 0, 0, 0, 252, 0, 0, 0, 28, 1, 0, 0, 60, 1, 0, 0, 68, 1, 0, 0, 76, 1, 0, 0, 84, 1, 0, 0, 85, 1, 0, 0, 89, 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, 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, 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, 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, 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, 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, 0, 0, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 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, 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, 3, 0, 0, 0, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 22, 32, 241, 19, 215, 157, 151, 224, 246, 229, 9, 24, 60, 121, 13, 182, 82, 23, 174, 212, 233, 95, 5, 215, 202, 209, 205, 163, 74, 191, 27, 11}; - gw_host->rollup_config_size = sizeof(rollup_config); - memcpy(gw_host->rollup_config, rollup_config, gw_host->rollup_config_size); - - -// TODO: build_script() -// build_script(g_script_code_hash, g_script_hash_type, script_args, SCRIPT_ARGS_LEN, &new_script_seg); - - uint32_t new_id = -1; - // id = 0 - bytes reserved_account_script - = from_hex("35000000100000003000000031000000a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a10100000000"); - new_id = create_account_from_script((uint8_t *)reserved_account_script.data(), - reserved_account_script.size()); - // id = 1 - bytes ckb_account_script - = from_hex("75000000100000003000000031000000a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a20140000000a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a90000000000000000000000000000000000000000000000000000000000000000"); - new_id = create_account_from_script((uint8_t *)ckb_account_script.data(), - ckb_account_script.size()); - // id = 2 - bytes meta_account_script - = from_hex("590000001000000030000000310000001620f113d79d97e0f6e509183c790db65217aed4e95f05d7cad1cda34abf1b0b0124000000a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a901000000"); - new_id = create_account_from_script((uint8_t *)meta_account_script.data(), - meta_account_script.size()); - // id = 3 - bytes block_producer_script = from_hex("69000000100000003000000031000000aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa0134000000a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a99999999999999999999999999999999999999999"); - new_id = create_account_from_script((uint8_t *)block_producer_script.data(), - block_producer_script.size()); - // id = 4 - bytes build_eth_l2_script = from_hex("69000000100000003000000031000000aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa0134000000a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a90101010101010101010101010101010101010101"); - - new_id = create_account_from_script((uint8_t *)build_eth_l2_script.data(), - build_eth_l2_script.size()); - mock_mint_sudt(1, new_id, 40000); - - // TODO: init destructed key - const uint8_t zero_nonce[32] = {0}; - const uint8_t poly_destructed_key[32] = {5, 0, 0, 0, 255, 2, 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}; - gw_update_raw(poly_destructed_key, zero_nonce); - - print_state(); - - return 0; -} diff --git a/polyjuice-tests/fuzz/polyjuice_fuzzer.cc b/polyjuice-tests/fuzz/polyjuice_fuzzer.cc new file mode 100644 index 00000000..6afd26d5 --- /dev/null +++ b/polyjuice-tests/fuzz/polyjuice_fuzzer.cc @@ -0,0 +1,138 @@ +#include +#include +#include +#include +#include +#include +#include + +#include "api.h" +#include "ckb_syscalls.h" +#define GW_GENERATOR +#define CKB_C_STDLIB_CKB_SYSCALLS_H_ +#define CREATOR_ID 1 +#define CHAIN_ID 1 +#include "polyjuice.h" +#include "godwoken.h" + +inline evmc::address generate_interesting_address(uint8_t b) noexcept +{ + const auto s = (b >> 6) & 0b11; + const auto fill = (b >> 5) & 0b1; + const auto above = (b >> 4) & 0b1; + const auto val = b & 0b1111; + + auto z = evmc::address{}; + + const size_t size = s == 3 ? 20 : 1 << s; + + if (fill) + { + for (auto i = sizeof(z) - size; i < sizeof(z); ++i) + z.bytes[i] = 0xff; + } + + if (above) + z.bytes[sizeof(z) - size % sizeof(z) - 1] ^= val; + else + z.bytes[sizeof(z) - size] ^= val << 4; + + return z; +} + +mol_seg_t build_Bytes(uint8_t* ptr, uint32_t len) { + mol_builder_t b; + mol_seg_res_t res; + MolBuilder_Bytes_init(&b); + for (uint32_t i = 0; i < len; i++) { + MolBuilder_Bytes_push(&b, ptr[i]); + } + res = MolBuilder_Bytes_build(b); + return res.seg; +} + +extern "C" int LLVMFuzzerTestOneInput(uint8_t *data, size_t size) { + + if (size < 76) { + return -1; + } + gw_reset(); + uint8_t kind = ((data[0] >> 3) & 0b1) == 0 ? 0 : 3; // call: 0; create: 3 + uint8_t native_transfer = (data[1] >> 3) & 0b1; // 1: native transfer tag + + evmc::address from_addr = generate_interesting_address(data[2]); + evmc::address to_addr = generate_interesting_address(data[3]); + evmc::address transfer_to = generate_interesting_address(data[4]); + + // mock from_id + int offset = 5; + uint8_t mint[16] = {0}; + memcpy(mint, data + offset, 16); + offset += 16; + uint32_t from_id; + gw_create_eoa_account(from_addr.bytes, mint, &from_id); + + uint32_t to_id; + // mock to_id by creating contract account with code + if (kind == 0) { + gw_create_contract_account(to_addr.bytes, mint, data, size, &to_id); + } else { + to_id = CREATOR_ID; + } + + uint8_t gas_price[16] = {0}; + memcpy(gas_price, data + offset, 16); + offset += 16; + uint8_t gas_limit[8] = {0}; + memcpy(gas_limit, data + offset, 8); + offset += 8; + + uint8_t value[16]; + memcpy(value, data + offset, 16); + offset += 16; + + // mock tx + mol_builder_t b; + MolBuilder_RawL2Transaction_init(&b); + uint64_t chain_id = (uint64_t) CHAIN_ID; + MolBuilder_RawL2Transaction_set_chain_id(&b, (uint8_t*)(&chain_id), 8); + MolBuilder_RawL2Transaction_set_from_id(&b, (uint8_t*)(&from_id), 4); + MolBuilder_RawL2Transaction_set_to_id(&b, (uint8_t*)(&to_id), 4); + uint32_t nonce = 0; + MolBuilder_RawL2Transaction_set_nonce(&b, (uint8_t*)(&nonce), 4); + uint8_t prefix[7] = {0xFF, 0xFF, 0xFF, 'P', 'O', 'L', 'Y'}; + uint8_t args[4096]; + memcpy(args, prefix, 7); // prefix POLY + args[7] = kind; // EVMC_CREATE + uint32_t args_offset = 8; + memcpy(args+args_offset, gas_limit, 8); // gas + args_offset += 8; + memcpy(args+args_offset, gas_price, 16); // gas_price + args_offset += 16; + memcpy(args+args_offset, value, 16); // value + args_offset += 16; + uint32_t data_size = (uint32_t)size; + memcpy(args+args_offset, (uint8_t*)(&data_size), 4); // input data size + args_offset += 4; + memcpy(args+args_offset, data, size); //input data + args_offset += size; + + if (native_transfer == 1) { + memcpy(args+args_offset, transfer_to.bytes, 20); // native transfer to + args_offset += 20; + } + + mol_seg_t bytes = build_Bytes(args, args_offset); + MolBuilder_RawL2Transaction_set_args(&b, bytes.ptr, bytes.size); + free(bytes.ptr); + + mol_seg_res_t res = MolBuilder_RawL2Transaction_build(b); + if (MolReader_RawL2Transaction_verify(&res.seg, false) == MOL_OK) { + gw_set_tx(res.seg.ptr, res.seg.size); + int ret = run_polyjuice(); + debug_print_int("polyjuice ret:", ret); + free(res.seg.ptr); + return 0; + } + return -1; // not add to corpus +} diff --git a/polyjuice-tests/fuzz/polyjuice_generator_fuzzer.cc b/polyjuice-tests/fuzz/polyjuice_generator_fuzzer.cc deleted file mode 100644 index 6f3f8431..00000000 --- a/polyjuice-tests/fuzz/polyjuice_generator_fuzzer.cc +++ /dev/null @@ -1,146 +0,0 @@ -#include -#include - -#define GW_GENERATOR -/** - * Layer 2 contract generator - * The generator supposed to be run off-chain. - * generator dynamic linking with the layer2 contract code, - * and provides layer2 syscalls. - * - * A program should be able to generate a post state after run the generator, - * and should be able to use the states to construct a transaction that satifies - * the validator. - */ -#include "polyjuice.h" - -#define ASSERT_EQ(A, B) assert_eq(A, B, #A, #B, __FILE__, __LINE__) - -struct test_case { - bytes raw_tx; - bytes expected_result{}; -}; - -bool execute_predefined_transactions() { - static int ret = init(); - // TODO: ASSERT_EQ(0, ret) - if (ret != 0) { - dbg_print("failed to init mock_godwoken"); - __builtin_trap(); - } - - // tmp code - // return true; - - bool all_good = true; - // raw_msg built by RawL2Transaction builder - const test_case pre_defined_test_cases[] = { - {// create account and deploy getChainId contract - bytes({73, 1, 0, 0, 20, 0, 0, 0, 24, 0, 0, 0, 28, 0, 0, 0, 32, 0, 0, 0, 4, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 37, 1, 0, 0, 255, 255, 255, 80, 79, 76, 89, 3, 240, 85, 0, 0, 0, 0, 0, 0, 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, 241, 0, 0, 0, 96, 128, 96, 64, 82, 52, 128, 21, 97, 0, 17, 87, 96, 0, 96, 0, 253, 91, 80, 97, 0, 23, 86, 91, 96, 204, 128, 97, 0, 37, 96, 0, 57, 96, 0, 243, 254, 96, 128, 96, 64, 82, 52, 128, 21, 96, 16, 87, 96, 0, 96, 0, 253, 91, 80, 96, 4, 54, 16, 96, 44, 87, 96, 0, 53, 96, 224, 28, 128, 99, 109, 76, 230, 60, 20, 96, 50, 87, 96, 44, 86, 91, 96, 0, 96, 0, 253, 91, 96, 56, 96, 76, 86, 91, 96, 64, 81, 96, 67, 145, 144, 96, 112, 86, 91, 96, 64, 81, 128, 145, 3, 144, 243, 91, 96, 0, 96, 0, 70, 144, 80, 128, 145, 80, 80, 96, 92, 86, 80, 91, 144, 86, 96, 149, 86, 91, 96, 105, 129, 96, 138, 86, 91, 130, 82, 91, 80, 80, 86, 91, 96, 0, 96, 32, 130, 1, 144, 80, 96, 131, 96, 0, 131, 1, 132, 96, 98, 86, 91, 91, 146, 145, 80, 80, 86, 91, 96, 0, 129, 144, 80, 91, 145, 144, 80, 86, 91, 254, 162, 100, 105, 112, 102, 115, 88, 34, 18, 32, 3, 36, 140, 112, 116, 35, 57, 185, 199, 86, 232, 210, 111, 220, 122, 33, 250, 178, 163, 13, 127, 44, 169, 160, 247, 149, 71, 178, 184, 168, 61, 64, 100, 115, 111, 108, 99, 67, 0, 8, 2, 0, 51}), - bytes{}}, - {// call getChainId contract - bytes({92, 0, 0, 0, 20, 0, 0, 0, 24, 0, 0, 0, 28, 0, 0, 0, 32, 0, 0, 0, 4, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 56, 0, 0, 0, 255, 255, 255, 80, 79, 76, 89, 0, 8, 82, 0, 0, 0, 0, 0, 0, 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, 4, 0, 0, 0, 109, 76, 230, 60}), - bytes({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, 2})}, - - /* simple_storage test case */ - // {bytes({89, 1, 0, 0, 20, 0, 0, 0, 24, 0, 0, 0, 28, 0, 0, 0, 32, 0, 0, 0, 4, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 53, 1, 0, 0, 255, 255, 255, 80, 79, 76, 89, 3, 240, 85, 0, 0, 0, 0, 0, 0, 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, 1, 1, 0, 0, 96, 128, 96, 64, 82, 91, 96, 123, 96, 0, 96, 0, 80, 129, 144, 144, 144, 85, 80, 91, 97, 0, 24, 86, 91, 96, 219, 128, 97, 0, 38, 96, 0, 57, 96, 0, 243, 254, 96, 128, 96, 64, 82, 96, 4, 54, 16, 96, 41, 87, 96, 0, 53, 96, 224, 28, 128, 99, 96, 254, 71, 177, 20, 96, 47, 87, 128, 99, 109, 76, 230, 60, 20, 96, 91, 87, 96, 41, 86, 91, 96, 0, 96, 0, 253, 91, 96, 89, 96, 4, 128, 54, 3, 96, 32, 129, 16, 21, 96, 68, 87, 96, 0, 96, 0, 253, 91, 129, 1, 144, 128, 128, 53, 144, 96, 32, 1, 144, 146, 145, 144, 80, 80, 80, 96, 132, 86, 91, 0, 91, 52, 128, 21, 96, 103, 87, 96, 0, 96, 0, 253, 91, 80, 96, 110, 96, 148, 86, 91, 96, 64, 81, 128, 130, 129, 82, 96, 32, 1, 145, 80, 80, 96, 64, 81, 128, 145, 3, 144, 243, 91, 128, 96, 0, 96, 0, 80, 129, 144, 144, 144, 85, 80, 91, 80, 86, 91, 96, 0, 96, 0, 96, 0, 80, 84, 144, 80, 96, 162, 86, 91, 144, 86, 254, 162, 100, 105, 112, 102, 115, 88, 34, 18, 32, 4, 77, 175, 78, 52, 173, 255, 198, 28, 59, 185, 232, 244, 0, 97, 115, 25, 114, 211, 45, 181, 184, 194, 188, 151, 81, 35, 218, 158, 152, 140, 62, 100, 115, 111, 108, 99, 67, 0, 6, 6, 0, 51}), - // bytes({})}, - - // {bytes({124, 0, 0, 0, 20, 0, 0, 0, 24, 0, 0, 0, 28, 0, 0, 0, 32, 0, 0, 0, 4, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 88, 0, 0, 0, 255, 255, 255, 80, 79, 76, 89, 0, 8, 82, 0, 0, 0, 0, 0, 0, 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, 36, 0, 0, 0, 96, 254, 71, 177, 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, 13, 16}), - // bytes({})}, - - // {bytes({}), - // bytes({})}, - - // {bytes({}), - // bytes({})}, - // {// deploy BlockInfo contract - // bytes({107, 4, 0, 0, 20, 0, 0, 0, 24, 0, 0, 0, 28, 0, 0, 0, 32, 0, 0, 0, 4, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 71, 4, 0, 0, 255, 255, 255, 80, 79, 76, 89, 3, 0, 113, 2, 0, 0, 0, 0, 0, 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, 19, 4, 0, 0, 96, 128, 96, 64, 82, 91, 96, 0, 64, 96, 0, 96, 0, 80, 129, 144, 144, 96, 0, 25, 22, 144, 85, 80, 68, 96, 1, 96, 0, 80, 129, 144, 144, 144, 85, 80, 69, 96, 2, 96, 0, 80, 129, 144, 144, 144, 85, 80, 67, 96, 3, 96, 0, 80, 129, 144, 144, 144, 85, 80, 66, 96, 4, 96, 0, 80, 129, 144, 144, 144, 85, 80, 65, 96, 5, 96, 0, 97, 1, 0, 10, 129, 84, 129, 115, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 2, 25, 22, 144, 131, 115, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 22, 2, 23, 144, 85, 80, 115, 161, 173, 34, 122, 211, 105, 245, 147, 181, 243, 208, 204, 147, 74, 104, 26, 80, 129, 28, 178, 115, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 22, 96, 5, 96, 0, 144, 84, 144, 97, 1, 0, 10, 144, 4, 115, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 22, 115, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 22, 20, 21, 21, 97, 0, 249, 87, 96, 0, 96, 0, 253, 91, 127, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 96, 0, 27, 96, 0, 96, 0, 80, 84, 96, 0, 25, 22, 20, 21, 21, 97, 1, 52, 87, 96, 0, 96, 0, 253, 91, 98, 190, 188, 32, 96, 2, 96, 0, 80, 84, 20, 21, 21, 97, 1, 75, 87, 96, 0, 96, 0, 253, 91, 91, 97, 1, 81, 86, 91, 97, 2, 179, 128, 97, 1, 96, 96, 0, 57, 96, 0, 243, 254, 96, 128, 96, 64, 82, 52, 128, 21, 97, 0, 17, 87, 96, 0, 96, 0, 253, 91, 80, 96, 4, 54, 16, 97, 0, 103, 87, 96, 0, 53, 96, 224, 28, 128, 99, 24, 142, 195, 86, 20, 97, 0, 109, 87, 128, 99, 26, 147, 209, 195, 20, 97, 0, 139, 87, 128, 99, 182, 186, 255, 227, 20, 97, 0, 169, 87, 128, 99, 209, 168, 42, 157, 20, 97, 0, 199, 87, 128, 99, 242, 201, 236, 216, 20, 97, 0, 229, 87, 128, 99, 246, 201, 147, 136, 20, 97, 1, 3, 87, 97, 0, 103, 86, 91, 96, 0, 96, 0, 253, 91, 97, 0, 117, 97, 1, 33, 86, 91, 96, 64, 81, 97, 0, 130, 145, 144, 97, 2, 22, 86, 91, 96, 64, 81, 128, 145, 3, 144, 243, 91, 97, 0, 147, 97, 1, 51, 86, 91, 96, 64, 81, 97, 0, 160, 145, 144, 97, 2, 22, 86, 91, 96, 64, 81, 128, 145, 3, 144, 243, 91, 97, 0, 177, 97, 1, 69, 86, 91, 96, 64, 81, 97, 0, 190, 145, 144, 97, 2, 22, 86, 91, 96, 64, 81, 128, 145, 3, 144, 243, 91, 97, 0, 207, 97, 1, 87, 86, 91, 96, 64, 81, 97, 0, 220, 145, 144, 97, 1, 222, 86, 91, 96, 64, 81, 128, 145, 3, 144, 243, 91, 97, 0, 237, 97, 1, 134, 86, 91, 96, 64, 81, 97, 0, 250, 145, 144, 97, 2, 22, 86, 91, 96, 64, 81, 128, 145, 3, 144, 243, 91, 97, 1, 11, 97, 1, 152, 86, 91, 96, 64, 81, 97, 1, 24, 145, 144, 97, 1, 250, 86, 91, 96, 64, 81, 128, 145, 3, 144, 243, 91, 96, 0, 96, 4, 96, 0, 80, 84, 144, 80, 97, 1, 48, 86, 91, 144, 86, 91, 96, 0, 96, 2, 96, 0, 80, 84, 144, 80, 97, 1, 66, 86, 91, 144, 86, 91, 96, 0, 96, 1, 96, 0, 80, 84, 144, 80, 97, 1, 84, 86, 91, 144, 86, 91, 96, 0, 96, 5, 96, 0, 144, 84, 144, 97, 1, 0, 10, 144, 4, 115, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 22, 144, 80, 97, 1, 131, 86, 91, 144, 86, 91, 96, 0, 96, 3, 96, 0, 80, 84, 144, 80, 97, 1, 149, 86, 91, 144, 86, 91, 96, 0, 96, 0, 96, 0, 80, 84, 144, 80, 97, 1, 167, 86, 91, 144, 86, 97, 2, 124, 86, 91, 97, 1, 183, 129, 97, 2, 50, 86, 91, 130, 82, 91, 80, 80, 86, 91, 97, 1, 199, 129, 97, 2, 69, 86, 91, 130, 82, 91, 80, 80, 86, 91, 97, 1, 215, 129, 97, 2, 113, 86, 91, 130, 82, 91, 80, 80, 86, 91, 96, 0, 96, 32, 130, 1, 144, 80, 97, 1, 243, 96, 0, 131, 1, 132, 97, 1, 174, 86, 91, 91, 146, 145, 80, 80, 86, 91, 96, 0, 96, 32, 130, 1, 144, 80, 97, 2, 15, 96, 0, 131, 1, 132, 97, 1, 190, 86, 91, 91, 146, 145, 80, 80, 86, 91, 96, 0, 96, 32, 130, 1, 144, 80, 97, 2, 43, 96, 0, 131, 1, 132, 97, 1, 206, 86, 91, 91, 146, 145, 80, 80, 86, 91, 96, 0, 97, 2, 61, 130, 97, 2, 80, 86, 91, 144, 80, 91, 145, 144, 80, 86, 91, 96, 0, 129, 144, 80, 91, 145, 144, 80, 86, 91, 96, 0, 115, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 130, 22, 144, 80, 91, 145, 144, 80, 86, 91, 96, 0, 129, 144, 80, 91, 145, 144, 80, 86, 91, 254, 162, 100, 105, 112, 102, 115, 88, 34, 18, 32, 113, 236, 22, 117, 175, 248, 197, 236, 108, 166, 237, 165, 131, 213, 225, 213, 35, 139, 217, 89, 232, 176, 199, 158, 172, 177, 24, 183, 62, 194, 199, 114, 100, 115, 111, 108, 99, 67, 0, 8, 2, 0, 51}), - // bytes({})}, - - // {// getGenesisHash() fn_sighash: f6c99388 - // bytes({92, 0, 0, 0, 20, 0, 0, 0, 24, 0, 0, 0, 28, 0, 0, 0, 32, 0, 0, 0, 4, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 56, 0, 0, 0, 255, 255, 255, 80, 79, 76, 89, 0, 8, 82, 0, 0, 0, 0, 0, 0, 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, 4, 0, 0, 0, 246, 201, 147, 136}), - // from_hex("0707070707070707070707070707070707070707070707070707070707070707")}, - - // // getDifficulty() => 2500000000000000, fn_sighash: b6baffe3 - // bytes({92, 0, 0, 0, 20, 0, 0, 0, 24, 0, 0, 0, 28, 0, 0, 0, 32, 0, 0, 0, 4, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 56, 0, 0, 0, 255, 255, 255, 80, 79, 76, 89, 0, 8, 82, 0, 0, 0, 0, 0, 0, 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, 4, 0, 0, 0, 182, 186, 255, 227}), - // from_hex(""), - - // // getGasLimit() fn_sighash: 1a93d1c3 - // bytes({92, 0, 0, 0, 20, 0, 0, 0, 24, 0, 0, 0, 28, 0, 0, 0, 32, 0, 0, 0, 4, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 56, 0, 0, 0, 255, 255, 255, 80, 79, 76, 89, 0, 8, 82, 0, 0, 0, 0, 0, 0, 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, 4, 0, 0, 0, 26, 147, 209, 195}), - // // getNumber() fn_sighash: f2c9ecd8 - // bytes({92, 0, 0, 0, 20, 0, 0, 0, 24, 0, 0, 0, 28, 0, 0, 0, 32, 0, 0, 0, 4, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 56, 0, 0, 0, 255, 255, 255, 80, 79, 76, 89, 0, 8, 82, 0, 0, 0, 0, 0, 0, 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, 4, 0, 0, 0, 242, 201, 236, 216}), - // // getTimestamp() fn_sighash: 188ec356 - // bytes({92, 0, 0, 0, 20, 0, 0, 0, 24, 0, 0, 0, 28, 0, 0, 0, 32, 0, 0, 0, 4, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 56, 0, 0, 0, 255, 255, 255, 80, 79, 76, 89, 0, 8, 82, 0, 0, 0, 0, 0, 0, 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, 4, 0, 0, 0, 24, 142, 195, 86}), - // // getCoinbase() fn_sighash: d1a82a9d - // bytes({92, 0, 0, 0, 20, 0, 0, 0, 24, 0, 0, 0, 28, 0, 0, 0, 32, 0, 0, 0, 4, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 56, 0, 0, 0, 255, 255, 255, 80, 79, 76, 89, 0, 8, 82, 0, 0, 0, 0, 0, 0, 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, 4, 0, 0, 0, 209, 168, 42, 157}) - // 000000000000000000000000a1ad227ad369f593b5f3d0cc934a681a50811cb2 - }; - - for (auto &&tc : pre_defined_test_cases) { - static uint raw_tx_idx = 0; - in.raw_tx = tc.raw_tx; // load_l2_transaction from pre_defined_test_cases - - ret = run_polyjuice(); - if (ret != 0) { - dbg_print("run_polyjuice failed, result_code: %d", ret); - all_good = false; - // __builtin_trap(); - } - //TODO: print RunResult as evmc_result and assert the result is expected - if (tc.expected_result.size() > 0) { - // TODO: - // ASSERT_EQ(bytes_view(tc.expected_result,) - // ) - } - ++raw_tx_idx; - dbg_print("====================== pre_defined_test_cases[%d] finished ======================", raw_tx_idx); - } - - if (!all_good) { - dbg_print("warn: execute_predefined_transactions failed \n"); - __builtin_trap(); - } - dbg_print("Predefined_transactions are all good.\n"); - return all_good; -} - -bool is_predefined_test_passed = execute_predefined_transactions(); -extern "C" int LLVMFuzzerTestOneInput(uint8_t *data, size_t size) { - dbg_print("Input Data Size: %d", size); - - mol_seg_t l2transaction_seg; - l2transaction_seg.ptr = data; - l2transaction_seg.size = size; - if (MolReader_RawL2Transaction_verify(&l2transaction_seg, false) == MOL_OK) { - mol_seg_t args_bytes_seg = MolReader_RawL2Transaction_get_args(&l2transaction_seg); - mol_seg_t args_seg = MolReader_Bytes_raw_bytes(&args_bytes_seg); - if (args_seg.size >= 8 + 8 + 16 + 16 + 4) { - // reduce gas_limit to avoid timeout while fuzzing - int64_t gas_limit; - memcpy(&gas_limit, args_seg.ptr + 8, sizeof(int64_t)); - dbg_print("gas_limit: %ld", gas_limit); - if (gas_limit > 5500000) { - // The recommended gas limit in EIP-150 is 5.5 million. - // (std::numeric_limits::max() >> 40) is close to 5.5 * 10^6 - // We make the max_gas_limit less than (std::numeric_limits::max() >> 38). - gas_limit = gas_limit >> 38; - dbg_print("gas_limit: %ld", gas_limit); - memcpy(args_seg.ptr + 8, &gas_limit, sizeof(int64_t)); - } - } - } - - in.raw_tx = bytes(data, size); - - // const auto res = polyjuice_execute(); - run_polyjuice(); - - //TODO: check the RunResult - - // temp code - // if (size >= 0) - // __builtin_trap(); - - return 0; -}