From 211f460d5fb186daa46449b1aefce0879ed6f2b9 Mon Sep 17 00:00:00 2001 From: William Morriss Date: Tue, 26 May 2026 02:44:21 -0500 Subject: [PATCH 1/5] chore(fmt): add uncrustify brace-style check and make fmt target Assisted-by: Claude:claude-sonnet-4-6 --- .github/workflows/fmt.yml | 22 ++++++++++++++++++++++ .uncrustify.cfg | 23 +++++++++++++++++++++++ Makefile | 4 +++- 3 files changed, 48 insertions(+), 1 deletion(-) create mode 100644 .github/workflows/fmt.yml create mode 100644 .uncrustify.cfg diff --git a/.github/workflows/fmt.yml b/.github/workflows/fmt.yml new file mode 100644 index 0000000..e8ff3df --- /dev/null +++ b/.github/workflows/fmt.yml @@ -0,0 +1,22 @@ +name: fmt + +on: + push: + branches: ["main", "master"] + pull_request: + branches: ["main", "master"] + +jobs: + uncrustify: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v4 + + - name: Install uncrustify + run: sudo apt-get install -y uncrustify + + - name: Check brace style + run: > + find . -path ./.git -prune -o -path ./secp256k1 -prune -o \( -name '*.c' -o -name '*.h' \) -print + | xargs uncrustify -c .uncrustify.cfg --check diff --git a/.uncrustify.cfg b/.uncrustify.cfg new file mode 100644 index 0000000..fa441bb --- /dev/null +++ b/.uncrustify.cfg @@ -0,0 +1,23 @@ +# Enforce brace style only — all other options at default (ignore) + +# Preserve existing indentation style (spaces, 4-wide) +indent_with_tabs = 0 +indent_columns = 4 + +# Add braces to braceless single-line control blocks +mod_full_brace_if = add +mod_full_brace_for = add +mod_full_brace_while = add +mod_full_brace_do = add + +# Ensure the body is on its own line (not inlined after the opening brace) +nl_after_brace_open = true + +# Space between closing ) of condition and opening { +sp_sparen_brace = add + +# Don't expand one-line braced assignments/initializers, as in 'x = { 1, 2 };' +nl_assign_leave_one_liners = true + +# One statement per line — splits 'a = 1; b = 2;' and struct members +nl_after_semicolon = true diff --git a/Makefile b/Makefile index 5a50ad7..4193147 100644 --- a/Makefile +++ b/Makefile @@ -16,7 +16,7 @@ LIBS=$(patsubst src/%.cpp, lib/%.o, $(wildcard src/*.cpp)) $(patsubst src/%.m, l INTEGRATIONS=$(addprefix tst/in/,$(shell ls tst/in)) $(addprefix tst/dio,$(shell ls tst/*.json)) -.PHONY: default all clean again check distcheck dist-check force-version +.PHONY: default all clean again check distcheck dist-check force-version fmt .SECONDARY: default: all all: $(EXECS) $(TESTS) README.md @@ -25,6 +25,8 @@ clean: make -C secp256k1 clean again: clean all check: $(addprefix .pass/,$(TESTS) $(INTEGRATIONS)) +fmt: + find . -path ./.git -prune -o -path ./secp256k1 -prune -o \( -name '*.c' -o -name '*.h' \) -print | xargs uncrustify -c .uncrustify.cfg --replace --no-backup FNM=\([-+a-z_A-Z0-9/]*\) .make/%.d: %.m From 4d801f0b53609943bc6661f20560fc066871bdc3 Mon Sep 17 00:00:00 2001 From: William Morriss Date: Tue, 26 May 2026 09:05:15 -0500 Subject: [PATCH 2/5] style: add sp_else_brace and indent_paren_close to uncrustify config Assisted-by: Claude:claude-sonnet-4-6 --- .uncrustify.cfg | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/.uncrustify.cfg b/.uncrustify.cfg index fa441bb..65ae0d4 100644 --- a/.uncrustify.cfg +++ b/.uncrustify.cfg @@ -16,8 +16,14 @@ nl_after_brace_open = true # Space between closing ) of condition and opening { sp_sparen_brace = add +# Space between else/catch and opening { +sp_else_brace = add + # Don't expand one-line braced assignments/initializers, as in 'x = { 1, 2 };' nl_assign_leave_one_liners = true # One statement per line — splits 'a = 1; b = 2;' and struct members nl_after_semicolon = true + +# Align closing ) with the statement, not the arguments +indent_paren_close = -1 From ec3e6b20ca80c50d7bcd5ab70bfcf25f8709f598 Mon Sep 17 00:00:00 2001 From: William Morriss Date: Tue, 26 May 2026 09:08:10 -0500 Subject: [PATCH 3/5] doc(uncrustify): reorganize and rewrite some explanations --- .uncrustify.cfg | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/.uncrustify.cfg b/.uncrustify.cfg index 65ae0d4..9895671 100644 --- a/.uncrustify.cfg +++ b/.uncrustify.cfg @@ -1,6 +1,6 @@ # Enforce brace style only — all other options at default (ignore) -# Preserve existing indentation style (spaces, 4-wide) +# indentation style (4 spaces) indent_with_tabs = 0 indent_columns = 4 @@ -13,16 +13,16 @@ mod_full_brace_do = add # Ensure the body is on its own line (not inlined after the opening brace) nl_after_brace_open = true +# Don't expand one-line braced assignments/initializers, as in 'x = { 1, 2 };' +nl_assign_leave_one_liners = true + # Space between closing ) of condition and opening { sp_sparen_brace = add # Space between else/catch and opening { sp_else_brace = add -# Don't expand one-line braced assignments/initializers, as in 'x = { 1, 2 };' -nl_assign_leave_one_liners = true - -# One statement per line — splits 'a = 1; b = 2;' and struct members +# One statement per line (splits 'a = 1; b = 2;' and struct members) nl_after_semicolon = true # Align closing ) with the statement, not the arguments From 9d4d7616279528acd9166ac3e21fe59e837b9bd8 Mon Sep 17 00:00:00 2001 From: William Morriss Date: Tue, 26 May 2026 09:19:52 -0500 Subject: [PATCH 4/5] style: apply make fmt across all C source files Assisted-by: Claude:claude-sonnet-4-6 --- evm.c | 139 +-- include/address.h | 72 +- include/dec.h | 20 +- include/evm.h | 2 +- include/hex.h | 44 +- include/keccak.h | 6 +- include/labelQueue.h | 4 +- include/ops.h | 512 +++++------ include/precompiles.h | 22 +- include/scanstack.h | 2 +- include/uint256.h | 42 +- include/vector.h | 80 +- ops.c | 2 +- precompiles.c | 2 +- src/dio.c | 920 ++++++++++---------- src/disassemble.c | 14 +- src/evm.c | 1932 +++++++++++++++++++++-------------------- src/keccak.c | 205 ++--- src/ops.c | 499 ++++++----- src/precompiles.c | 6 +- src/scan.c | 94 +- src/uint256.c | 93 +- tst/dio.c | 114 +-- tst/evm.c | 142 +-- 24 files changed, 2563 insertions(+), 2405 deletions(-) diff --git a/evm.c b/evm.c index 041099b..398f403 100644 --- a/evm.c +++ b/evm.c @@ -91,7 +91,9 @@ static void assemble(const char *contents) { programLength += 11; } - for (; programLength--;) printf("%02x", *programStart++); + for (; programLength--;) { + printf("%02x", *programStart++); + } putchar('\n'); } @@ -162,7 +164,9 @@ static void execute(const char *contents) { } fputs("returnData\":\"0x", stdout); } - for (;result.returnData.size--;) printf("%02x", *result.returnData.content++); + for (; result.returnData.size--;) { + printf("%02x", *result.returnData.content++); + } if (outputJson) { fputs("\"}", stdout); } @@ -182,53 +186,54 @@ int main(int argc, char *const argv[]) { int option; char *contents = NULL; - while ((option = getopt_long(argc, argv, "cCdgjlo:suvw:x", long_options, NULL)) != -1) + while ((option = getopt_long(argc, argv, "cCdgjlo:suvw:x", long_options, NULL)) != -1) { switch (option) { - case 'c': - wrapMinConstructor = 1; - break; - case 'C': - wrapUniversalConstructor = 1; - break; - case 'd': - inverse = 1; - break; - case 'j': - labelJumpdests = 1; - break; - case 'o': - contents = optarg; - break; - case 'x': - runtime = 1; - break; - case 'g': - includeGas = 1; - break; - case 's': - includeStatus = 1; - break; - case 'l': - includeLogs = 1; - break; - case 'u': - updateConfigFile = 1; - break; - case 'v': - puts(evm_build_version); - return 0; - case 'w': - if (configFile == NULL) { - evmInit(); - } - configFile = optarg; - loadConfig(configFile, updateConfigFile); - break; - case '?': - default: - USAGE; - return 1; + case 'c': + wrapMinConstructor = 1; + break; + case 'C': + wrapUniversalConstructor = 1; + break; + case 'd': + inverse = 1; + break; + case 'j': + labelJumpdests = 1; + break; + case 'o': + contents = optarg; + break; + case 'x': + runtime = 1; + break; + case 'g': + includeGas = 1; + break; + case 's': + includeStatus = 1; + break; + case 'l': + includeLogs = 1; + break; + case 'u': + updateConfigFile = 1; + break; + case 'v': + puts(evm_build_version); + return 0; + case 'w': + if (configFile == NULL) { + evmInit(); + } + configFile = optarg; + loadConfig(configFile, updateConfigFile); + break; + case '?': + default: + USAGE; + return 1; } + } if (inverse && wrapMinConstructor) { fputs("-c cannot be used with -d\n", stderr); USAGE; @@ -315,27 +320,29 @@ int main(int argc, char *const argv[]) { subprogram(input); // free is redundant with program termination but makes valgrind happy free(input); - } else for (int i = optind; i < argc; i++) { - int fd = open(argv[i], O_RDONLY); - if (fd == -1) { - perror(argv[i]); - _exit(1); - } + } else { + for (int i = optind; i < argc; i++) { + int fd = open(argv[i], O_RDONLY); + if (fd == -1) { + perror(argv[i]); + _exit(1); + } - struct stat fstatus; - int fstatSuccess = fstat(fd, &fstatus); - if (fstatSuccess == -1) { - perror(argv[i]); - _exit(1); - } - - contents = mmap(NULL, fstatus.st_size, PROT_READ, MAP_PRIVATE | MAP_FILE, fd, 0); - if (contents == NULL) { - perror(argv[i]); + struct stat fstatus; + int fstatSuccess = fstat(fd, &fstatus); + if (fstatSuccess == -1) { + perror(argv[i]); + _exit(1); + } + + contents = mmap(NULL, fstatus.st_size, PROT_READ, MAP_PRIVATE | MAP_FILE, fd, 0); + if (contents == NULL) { + perror(argv[i]); + } + subprogram(contents); + munmap(contents, fstatus.st_size); + close(fd); } - subprogram(contents); - munmap(contents, fstatus.st_size); - close(fd); } return 0; } diff --git a/include/address.h b/include/address.h index a148e67..cebacf7 100644 --- a/include/address.h +++ b/include/address.h @@ -75,57 +75,57 @@ static inline void AddressToUint256(uint256_t *dst, address_t *src) { UPPER(UPPER_P(dst)) = 0; LOWER(UPPER_P(dst)) = ( ((uint64_t)src->address[0] << 24ull) - | ((uint64_t)src->address[1] << 16ull) - | ((uint64_t)src->address[2] << 8ull) - | ((uint64_t)src->address[3]) + | ((uint64_t)src->address[1] << 16ull) + | ((uint64_t)src->address[2] << 8ull) + | ((uint64_t)src->address[3]) ); UPPER(LOWER_P(dst)) = ( ((uint64_t)src->address[4] << 56ull) - | ((uint64_t)src->address[5] << 48ull) - | ((uint64_t)src->address[6] << 40ull) - | ((uint64_t)src->address[7] << 32ull) - | ((uint64_t)src->address[8] << 24ull) - | ((uint64_t)src->address[9] << 16ull) - | ((uint64_t)src->address[10] << 8ull) - | ((uint64_t)src->address[11]) + | ((uint64_t)src->address[5] << 48ull) + | ((uint64_t)src->address[6] << 40ull) + | ((uint64_t)src->address[7] << 32ull) + | ((uint64_t)src->address[8] << 24ull) + | ((uint64_t)src->address[9] << 16ull) + | ((uint64_t)src->address[10] << 8ull) + | ((uint64_t)src->address[11]) ); LOWER(LOWER_P(dst)) = ( ((uint64_t)src->address[12] << 56ull) - | ((uint64_t)src->address[13] << 48ull) - | ((uint64_t)src->address[14] << 40ull) - | ((uint64_t)src->address[15] << 32ull) - | ((uint64_t)src->address[16] << 24ull) - | ((uint64_t)src->address[17] << 16ull) - | ((uint64_t)src->address[18] << 8ull) - | ((uint64_t)src->address[19]) + | ((uint64_t)src->address[13] << 48ull) + | ((uint64_t)src->address[14] << 40ull) + | ((uint64_t)src->address[15] << 32ull) + | ((uint64_t)src->address[16] << 24ull) + | ((uint64_t)src->address[17] << 16ull) + | ((uint64_t)src->address[18] << 8ull) + | ((uint64_t)src->address[19]) ); } #define fprintAddress(file, addr) fprintf(file, "0x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x", \ - addr.address[0], addr.address[1], addr.address[2], addr.address[3], addr.address[4], addr.address[5], addr.address[6], addr.address[7], addr.address[8], addr.address[9], addr.address[10],\ - addr.address[11], addr.address[12], addr.address[13], addr.address[14], addr.address[15], addr.address[16], addr.address[17], addr.address[18], addr.address[19]\ + addr.address[0], addr.address[1], addr.address[2], addr.address[3], addr.address[4], addr.address[5], addr.address[6], addr.address[7], addr.address[8], addr.address[9], addr.address[10], \ + addr.address[11], addr.address[12], addr.address[13], addr.address[14], addr.address[15], addr.address[16], addr.address[17], addr.address[18], addr.address[19] \ ) static inline int AddressIsPrecompile(const address_t address) { return !address.address[0] && - !address.address[1] && - !address.address[2] && - !address.address[3] && - !address.address[4] && - !address.address[5] && - !address.address[6] && - !address.address[7] && - !address.address[8] && - !address.address[9] && - !address.address[10] && - !address.address[11] && - !address.address[12] && - !address.address[13] && - !address.address[14] && - !address.address[15] && - !address.address[16] && - !address.address[17]; + !address.address[1] && + !address.address[2] && + !address.address[3] && + !address.address[4] && + !address.address[5] && + !address.address[6] && + !address.address[7] && + !address.address[8] && + !address.address[9] && + !address.address[10] && + !address.address[11] && + !address.address[12] && + !address.address[13] && + !address.address[14] && + !address.address[15] && + !address.address[16] && + !address.address[17]; } // assumes AddressIsPrecompile diff --git a/include/dec.h b/include/dec.h index b931f18..d673c46 100644 --- a/include/dec.h +++ b/include/dec.h @@ -1,14 +1,14 @@ #define DECCHARS \ -DEC(0) \ -DEC(1) \ -DEC(2) \ -DEC(3) \ -DEC(4) \ -DEC(5) \ -DEC(6) \ -DEC(7) \ -DEC(8) \ -DEC(9) \ + DEC(0) \ + DEC(1) \ + DEC(2) \ + DEC(3) \ + DEC(4) \ + DEC(5) \ + DEC(6) \ + DEC(7) \ + DEC(8) \ + DEC(9) \ static inline int isDecimal(char h) { return (h >= '0' && h <= '9') || (h == '-'); diff --git a/include/evm.h b/include/evm.h index ec8c128..9fc6102 100644 --- a/include/evm.h +++ b/include/evm.h @@ -133,4 +133,4 @@ result_t evmConstruct(address_t from, address_t to, uint64_t gas, val_t value, d // TODO gasPrice, basefee, blockNumber result_t txCall(address_t from, uint64_t gas, address_t to, val_t value, data_t input, const accessList_t *accessList); // TODO accessList -result_t txCreate(address_t from, uint64_t gas, val_t value, data_t input/*, const accessList_t *accessList*/); +result_t txCreate(address_t from, uint64_t gas, val_t value, data_t input /*, const accessList_t *accessList*/); diff --git a/include/hex.h b/include/hex.h index 2d77fcb..6549aa7 100644 --- a/include/hex.h +++ b/include/hex.h @@ -2,28 +2,28 @@ #include #define HEXCHARS \ -HEX(a) \ -HEX(A) \ -HEX(b) \ -HEX(B) \ -HEX(c) \ -HEX(C) \ -HEX(d) \ -HEX(D) \ -HEX(e) \ -HEX(E) \ -HEX(f) \ -HEX(F) \ -HEX(0) \ -HEX(1) \ -HEX(2) \ -HEX(3) \ -HEX(4) \ -HEX(5) \ -HEX(6) \ -HEX(7) \ -HEX(8) \ -HEX(9) \ + HEX(a) \ + HEX(A) \ + HEX(b) \ + HEX(B) \ + HEX(c) \ + HEX(C) \ + HEX(d) \ + HEX(D) \ + HEX(e) \ + HEX(E) \ + HEX(f) \ + HEX(F) \ + HEX(0) \ + HEX(1) \ + HEX(2) \ + HEX(3) \ + HEX(4) \ + HEX(5) \ + HEX(6) \ + HEX(7) \ + HEX(8) \ + HEX(9) \ static inline uint8_t hexString8ToUint8(const uint8_t hexString8) { if ('0' <= hexString8 && hexString8 <= '9') { diff --git a/include/keccak.h b/include/keccak.h index 486032a..0d11299 100644 --- a/include/keccak.h +++ b/include/keccak.h @@ -5,13 +5,13 @@ #include #define decshake(bits) \ - int shake##bits(uint8_t*, size_t, const uint8_t*, size_t); + int shake ## bits(uint8_t*, size_t, const uint8_t*, size_t); #define decsha3(bits) \ - int sha3_##bits(uint8_t*, size_t, const uint8_t*, size_t); + int sha3_ ## bits(uint8_t*, size_t, const uint8_t*, size_t); #define deckeccak(bits) \ - int keccak_##bits(uint8_t*, size_t, const uint8_t*, size_t); + int keccak_ ## bits(uint8_t*, size_t, const uint8_t*, size_t); //decshake(128) //decshake(256) diff --git a/include/labelQueue.h b/include/labelQueue.h index 4456419..2ca0e1d 100644 --- a/include/labelQueue.h +++ b/include/labelQueue.h @@ -75,7 +75,7 @@ static void registerLabel(jump_t jump) { static uint32_t firstLabelAfter(uint32_t pc) { // inclusive - uint32_t begin = 0; + uint32_t begin = 0; // exclusive uint32_t end = labelCount; while (begin < end) { @@ -95,7 +95,7 @@ static void incrementLabelLocations(uint32_t after, uint32_t by) { labelLocations[i] += by; int after = labelLocations[i] >= 256; if (before && after) { - // TODO shift label positions + // TODO shift label positions } } } diff --git a/include/ops.h b/include/ops.h index c67c1a6..71310db 100644 --- a/include/ops.h +++ b/include/ops.h @@ -4,262 +4,262 @@ #include "gas.h" // OP(code,name,argCount,retCount,gas) #define OPS \ -OP(0x00,STOP,0,0,G_ZERO) \ -OP(0x01,ADD,2,1,G_VERYLOW) \ -OP(0x02,MUL,2,1,G_LOW) \ -OP(0x03,SUB,2,1,G_VERYLOW) \ -OP(0x04,DIV,2,1,G_LOW) \ -OP(0x05,SDIV,2,1,G_LOW) \ -OP(0x06,MOD,2,1,G_LOW) \ -OP(0x07,SMOD,2,1,G_LOW) \ -OP(0x08,ADDMOD,3,1,G_MID) \ -OP(0x09,MULMOD,3,1,G_MID) \ -OP(0x0a,EXP,2,1,G_EXP) \ -OP(0x0b,SIGNEXTEND,2,1,G_LOW) \ -OP(0x0c,ASSERT_0x0c,2,1,G_ZERO) \ -OP(0x0d,ASSERT_0x0d,2,1,G_ZERO) \ -OP(0x0e,ASSERT_0x0e,2,1,G_ZERO) \ -OP(0x0f,ASSERT_0x0f,2,1,G_ZERO) \ -OP(0x10,LT,2,1,G_VERYLOW) \ -OP(0x11,GT,2,1,G_VERYLOW) \ -OP(0x12,SLT,2,1,G_VERYLOW) \ -OP(0x13,SGT,2,1,G_VERYLOW) \ -OP(0x14,EQ,2,1,G_VERYLOW) \ -OP(0x15,ISZERO,1,1,G_VERYLOW) \ -OP(0x16,AND,2,1,G_VERYLOW) \ -OP(0x17,OR,2,1,G_VERYLOW) \ -OP(0x18,XOR,2,1,G_VERYLOW) \ -OP(0x19,NOT,1,1,G_VERYLOW) \ -OP(0x1a,BYTE,2,1,G_VERYLOW) \ -OP(0x1b,SHL,2,1,G_VERYLOW) \ -OP(0x1c,SHR,2,1,G_VERYLOW) \ -OP(0x1d,SAR,2,1,G_VERYLOW) \ -OP(0x1e,CLZ,1,1,G_LOW) \ -OP(0x1f,ASSERT_0x1f,2,1,G_ZERO) \ -OP(0x20,SHA3,2,1,G_KECCAK) \ -OP(0x21,ASSERT_0x21,2,1,G_ZERO) \ -OP(0x22,ASSERT_0x22,2,1,G_ZERO) \ -OP(0x23,ASSERT_0x23,2,1,G_ZERO) \ -OP(0x24,ASSERT_0x24,2,1,G_ZERO) \ -OP(0x25,ASSERT_0x25,2,1,G_ZERO) \ -OP(0x26,ASSERT_0x26,2,1,G_ZERO) \ -OP(0x27,ASSERT_0x27,2,1,G_ZERO) \ -OP(0x28,ASSERT_0x28,2,1,G_ZERO) \ -OP(0x29,ASSERT_0x29,2,1,G_ZERO) \ -OP(0x2a,ASSERT_0x2a,2,1,G_ZERO) \ -OP(0x2b,ASSERT_0x2b,2,1,G_ZERO) \ -OP(0x2c,ASSERT_0x2c,2,1,G_ZERO) \ -OP(0x2d,ASSERT_0x2d,2,1,G_ZERO) \ -OP(0x2e,ASSERT_0x2e,2,1,G_ZERO) \ -OP(0x2f,ASSERT_0x2f,2,1,G_ZERO) \ -OP(0x30,ADDRESS,0,1,G_BASE) \ -OP(0x31,BALANCE,1,1,G_ACCESS) \ -OP(0x32,ORIGIN,0,1,G_BASE) \ -OP(0x33,CALLER,0,1,G_BASE) \ -OP(0x34,CALLVALUE,0,1,G_BASE) \ -OP(0x35,CALLDATALOAD,1,1,G_VERYLOW) \ -OP(0x36,CALLDATASIZE,0,1,G_BASE) \ -OP(0x37,CALLDATACOPY,3,0,G_COPY) \ -OP(0x38,CODESIZE,0,1,G_BASE) \ -OP(0x39,CODECOPY,3,0,G_COPY) \ -OP(0x3a,GASPRICE,0,1,G_BASE) \ -OP(0x3b,EXTCODESIZE,1,1,G_ACCESS) \ -OP(0x3c,EXTCODECOPY,4,0,G_ACCESS) \ -OP(0x3d,RETURNDATASIZE,0,1,G_BASE) \ -OP(0x3e,RETURNDATACOPY,3,0,G_COPY) \ -OP(0x3f,EXTCODEHASH,1,1,G_ACCESS) \ -OP(0x40,BLOCKHASH,1,1,G_BLOCKHASH) \ -OP(0x41,COINBASE,0,1,G_BASE) \ -OP(0x42,TIMESTAMP,0,1,G_BASE) \ -OP(0x43,NUMBER,0,1,G_BASE) \ -OP(0x44,PREVRANDAO,0,1,G_BASE) \ -OP(0x45,GASLIMIT,0,1,G_BASE) \ -OP(0x46,CHAINID,0,1,G_BASE) \ -OP(0x47,SELFBALANCE,0,1,G_LOW) \ -OP(0x48,BASEFEE,0,1,G_BASE) \ -OP(0x49,BLOBHASH,0,1,G_ZERO) \ -OP(0x4a,BLOBBASEFEE,0,1,G_ZERO) \ -OP(0x4b,ASSERT_0x4b,0,1,G_ZERO) \ -OP(0x4c,ASSERT_0x4c,0,1,G_ZERO) \ -OP(0x4d,ASSERT_0x4d,0,1,G_ZERO) \ -OP(0x4e,ASSERT_0x4e,0,1,G_ZERO) \ -OP(0x4f,ASSERT_0x4f,0,1,G_ZERO) \ -OP(0x50,POP,1,0,G_BASE) \ -OP(0x51,MLOAD,1,1,G_VERYLOW) \ -OP(0x52,MSTORE,2,0,G_VERYLOW) \ -OP(0x53,MSTORE8,2,0,G_VERYLOW) \ -OP(0x54,SLOAD,1,1,G_ACCESS) \ -OP(0x55,SSTORE,2,0,G_ACCESS) \ -OP(0x56,JUMP,1,0,G_MID) \ -OP(0x57,JUMPI,2,0,G_HIGH) \ -OP(0x58,PC,0,1,G_BASE) \ -OP(0x59,MSIZE,0,1,G_BASE) \ -OP(0x5a,GAS,0,1,G_BASE) \ -OP(0x5b,JUMPDEST,0,0,G_JUMPDEST) \ -OP(0x5c,TLOAD,1,1,G_ACCESS) \ -OP(0x5d,TSTORE,2,0,G_ACCESS) \ -OP(0x5e,MCOPY,3,0,G_COPY) \ -OP(0x5f,PUSH0,0,1,G_BASE) \ -OP(0x60,PUSH1,0,1,G_VERYLOW) \ -OP(0x61,PUSH2,0,1,G_VERYLOW) \ -OP(0x62,PUSH3,0,1,G_VERYLOW) \ -OP(0x63,PUSH4,0,1,G_VERYLOW) \ -OP(0x64,PUSH5,0,1,G_VERYLOW) \ -OP(0x65,PUSH6,0,1,G_VERYLOW) \ -OP(0x66,PUSH7,0,1,G_VERYLOW) \ -OP(0x67,PUSH8,0,1,G_VERYLOW) \ -OP(0x68,PUSH9,0,1,G_VERYLOW) \ -OP(0x69,PUSH10,0,1,G_VERYLOW) \ -OP(0x6a,PUSH11,0,1,G_VERYLOW) \ -OP(0x6b,PUSH12,0,1,G_VERYLOW) \ -OP(0x6c,PUSH13,0,1,G_VERYLOW) \ -OP(0x6d,PUSH14,0,1,G_VERYLOW) \ -OP(0x6e,PUSH15,0,1,G_VERYLOW) \ -OP(0x6f,PUSH16,0,1,G_VERYLOW) \ -OP(0x70,PUSH17,0,1,G_VERYLOW) \ -OP(0x71,PUSH18,0,1,G_VERYLOW) \ -OP(0x72,PUSH19,0,1,G_VERYLOW) \ -OP(0x73,PUSH20,0,1,G_VERYLOW) \ -OP(0x74,PUSH21,0,1,G_VERYLOW) \ -OP(0x75,PUSH22,0,1,G_VERYLOW) \ -OP(0x76,PUSH23,0,1,G_VERYLOW) \ -OP(0x77,PUSH24,0,1,G_VERYLOW) \ -OP(0x78,PUSH25,0,1,G_VERYLOW) \ -OP(0x79,PUSH26,0,1,G_VERYLOW) \ -OP(0x7a,PUSH27,0,1,G_VERYLOW) \ -OP(0x7b,PUSH28,0,1,G_VERYLOW) \ -OP(0x7c,PUSH29,0,1,G_VERYLOW) \ -OP(0x7d,PUSH30,0,1,G_VERYLOW) \ -OP(0x7e,PUSH31,0,1,G_VERYLOW) \ -OP(0x7f,PUSH32,0,1,G_VERYLOW) \ -OP(0x80,DUP1,0,1,G_VERYLOW) \ -OP(0x81,DUP2,0,1,G_VERYLOW) \ -OP(0x82,DUP3,0,1,G_VERYLOW) \ -OP(0x83,DUP4,0,1,G_VERYLOW) \ -OP(0x84,DUP5,0,1,G_VERYLOW) \ -OP(0x85,DUP6,0,1,G_VERYLOW) \ -OP(0x86,DUP7,0,1,G_VERYLOW) \ -OP(0x87,DUP8,0,1,G_VERYLOW) \ -OP(0x88,DUP9,0,1,G_VERYLOW) \ -OP(0x89,DUP10,0,1,G_VERYLOW) \ -OP(0x8a,DUP11,0,1,G_VERYLOW) \ -OP(0x8b,DUP12,0,1,G_VERYLOW) \ -OP(0x8c,DUP13,0,1,G_VERYLOW) \ -OP(0x8d,DUP14,0,1,G_VERYLOW) \ -OP(0x8e,DUP15,0,1,G_VERYLOW) \ -OP(0x8f,DUP16,0,1,G_VERYLOW) \ -OP(0x90,SWAP1,0,0,G_VERYLOW) \ -OP(0x91,SWAP2,0,0,G_VERYLOW) \ -OP(0x92,SWAP3,0,0,G_VERYLOW) \ -OP(0x93,SWAP4,0,0,G_VERYLOW) \ -OP(0x94,SWAP5,0,0,G_VERYLOW) \ -OP(0x95,SWAP6,0,0,G_VERYLOW) \ -OP(0x96,SWAP7,0,0,G_VERYLOW) \ -OP(0x97,SWAP8,0,0,G_VERYLOW) \ -OP(0x98,SWAP9,0,0,G_VERYLOW) \ -OP(0x99,SWAP10,0,0,G_VERYLOW) \ -OP(0x9a,SWAP11,0,0,G_VERYLOW) \ -OP(0x9b,SWAP12,0,0,G_VERYLOW) \ -OP(0x9c,SWAP13,0,0,G_VERYLOW) \ -OP(0x9d,SWAP14,0,0,G_VERYLOW) \ -OP(0x9e,SWAP15,0,0,G_VERYLOW) \ -OP(0x9f,SWAP16,0,0,G_VERYLOW) \ -OP(0xa0,LOG0,2,0,G_LOG) \ -OP(0xa1,LOG1,3,0,G_LOG + G_LOGTOPIC) \ -OP(0xa2,LOG2,4,0,G_LOG + 2 * G_LOGTOPIC) \ -OP(0xa3,LOG3,5,0,G_LOG + 3 * G_LOGTOPIC) \ -OP(0xa4,LOG4,6,0,G_LOG + 4 * G_LOGTOPIC) \ -OP(0xa5,ASSERT_0xa5,7,0,G_ZERO) \ -OP(0xa6,ASSERT_0xa6,7,0,G_ZERO) \ -OP(0xa7,ASSERT_0xa7,7,0,G_ZERO) \ -OP(0xa8,ASSERT_0xa8,7,0,G_ZERO) \ -OP(0xa9,ASSERT_0xa9,7,0,G_ZERO) \ -OP(0xaa,ASSERT_0xaa,7,0,G_ZERO) \ -OP(0xab,ASSERT_0xab,7,0,G_ZERO) \ -OP(0xac,ASSERT_0xac,7,0,G_ZERO) \ -OP(0xad,ASSERT_0xad,7,0,G_ZERO) \ -OP(0xae,ASSERT_0xae,7,0,G_ZERO) \ -OP(0xaf,ASSERT_0xaf,7,0,G_ZERO) \ -OP(0xb0,ASSERT_0xb0,7,0,G_ZERO) \ -OP(0xb1,ASSERT_0xb1,7,0,G_ZERO) \ -OP(0xb2,ASSERT_0xb2,7,0,G_ZERO) \ -OP(0xb3,ASSERT_0xb3,7,0,G_ZERO) \ -OP(0xb4,ASSERT_0xb4,7,0,G_ZERO) \ -OP(0xb5,ASSERT_0xb5,7,0,G_ZERO) \ -OP(0xb6,ASSERT_0xb6,7,0,G_ZERO) \ -OP(0xb7,ASSERT_0xb7,7,0,G_ZERO) \ -OP(0xb8,ASSERT_0xb8,7,0,G_ZERO) \ -OP(0xb9,ASSERT_0xb9,7,0,G_ZERO) \ -OP(0xba,ASSERT_0xba,7,0,G_ZERO) \ -OP(0xbb,ASSERT_0xbb,7,0,G_ZERO) \ -OP(0xbc,ASSERT_0xbc,7,0,G_ZERO) \ -OP(0xbd,ASSERT_0xbd,7,0,G_ZERO) \ -OP(0xbe,ASSERT_0xbe,7,0,G_ZERO) \ -OP(0xbf,ASSERT_0xbf,7,0,G_ZERO) \ -OP(0xc0,ASSERT_0xc0,7,0,G_ZERO) \ -OP(0xc1,ASSERT_0xc1,7,0,G_ZERO) \ -OP(0xc2,ASSERT_0xc2,7,0,G_ZERO) \ -OP(0xc3,ASSERT_0xc3,7,0,G_ZERO) \ -OP(0xc4,ASSERT_0xc4,7,0,G_ZERO) \ -OP(0xc5,ASSERT_0xc5,7,0,G_ZERO) \ -OP(0xc6,ASSERT_0xc6,7,0,G_ZERO) \ -OP(0xc7,ASSERT_0xc7,7,0,G_ZERO) \ -OP(0xc8,ASSERT_0xc8,7,0,G_ZERO) \ -OP(0xc9,ASSERT_0xc9,7,0,G_ZERO) \ -OP(0xca,ASSERT_0xca,7,0,G_ZERO) \ -OP(0xcb,ASSERT_0xcb,7,0,G_ZERO) \ -OP(0xcc,ASSERT_0xcc,7,0,G_ZERO) \ -OP(0xcd,ASSERT_0xcd,7,0,G_ZERO) \ -OP(0xce,ASSERT_0xce,7,0,G_ZERO) \ -OP(0xcf,ASSERT_0xcf,7,0,G_ZERO) \ -OP(0xd0,ASSERT_0xd0,7,0,G_ZERO) \ -OP(0xd1,ASSERT_0xd1,7,0,G_ZERO) \ -OP(0xd2,ASSERT_0xd2,7,0,G_ZERO) \ -OP(0xd3,ASSERT_0xd3,7,0,G_ZERO) \ -OP(0xd4,ASSERT_0xd4,7,0,G_ZERO) \ -OP(0xd5,ASSERT_0xd5,7,0,G_ZERO) \ -OP(0xd6,ASSERT_0xd6,7,0,G_ZERO) \ -OP(0xd7,ASSERT_0xd7,7,0,G_ZERO) \ -OP(0xd8,ASSERT_0xd8,7,0,G_ZERO) \ -OP(0xd9,ASSERT_0xd9,7,0,G_ZERO) \ -OP(0xda,ASSERT_0xda,7,0,G_ZERO) \ -OP(0xdb,ASSERT_0xdb,7,0,G_ZERO) \ -OP(0xdc,ASSERT_0xdc,7,0,G_ZERO) \ -OP(0xdd,ASSERT_0xdd,7,0,G_ZERO) \ -OP(0xde,ASSERT_0xde,7,0,G_ZERO) \ -OP(0xdf,ASSERT_0xdf,7,0,G_ZERO) \ -OP(0xe0,ASSERT_0xe0,7,0,G_ZERO) \ -OP(0xe1,ASSERT_0xe1,7,0,G_ZERO) \ -OP(0xe2,ASSERT_0xe2,7,0,G_ZERO) \ -OP(0xe3,ASSERT_0xe3,7,0,G_ZERO) \ -OP(0xe4,ASSERT_0xe4,7,0,G_ZERO) \ -OP(0xe5,ASSERT_0xe5,7,0,G_ZERO) \ -OP(0xe6,ASSERT_0xe6,7,0,G_ZERO) \ -OP(0xe7,ASSERT_0xe7,7,0,G_ZERO) \ -OP(0xe8,ASSERT_0xe8,7,0,G_ZERO) \ -OP(0xe9,ASSERT_0xe9,7,0,G_ZERO) \ -OP(0xea,ASSERT_0xea,7,0,G_ZERO) \ -OP(0xeb,ASSERT_0xeb,7,0,G_ZERO) \ -OP(0xec,ASSERT_0xec,7,0,G_ZERO) \ -OP(0xed,ASSERT_0xed,7,0,G_ZERO) \ -OP(0xee,ASSERT_0xee,7,0,G_ZERO) \ -OP(0xef,ASSERT_0xef,7,0,G_ZERO) \ -OP(0xf0,CREATE,3,1,G_CREATE) \ -OP(0xf1,CALL,7,1,G_ACCESS) \ -OP(0xf2,CALLCODE,7,1,G_ACCESS) \ -OP(0xf3,RETURN,2,0,G_ZERO) \ -OP(0xf4,DELEGATECALL,6,1,G_ACCESS) \ -OP(0xf5,CREATE2,4,1,G_CREATE) \ -OP(0xf6,ASSERT_0xf6,4,1,G_AUTH) \ -OP(0xf7,ASSERT_0xf7,8,1,G_ACCESS) \ -OP(0xf8,ASSERT_0xf8,6,1,G_ZERO) \ -OP(0xf9,ASSERT_0xf9,6,1,G_ZERO) \ -OP(0xfa,STATICCALL,6,1,G_ACCESS) \ -OP(0xfb,ASSERT_0xfb,6,1,G_ZERO) \ -OP(0xfc,ASSERT_0xfc,6,1,G_ZERO) \ -OP(0xfd,REVERT,2,0,G_ZERO) \ -OP(0xfe,INVALID,0,0,G_ZERO) \ -OP(0xff,SELFDESTRUCT,1,0,G_SELFDESTRUCT) + OP(0x00,STOP,0,0,G_ZERO) \ + OP(0x01,ADD,2,1,G_VERYLOW) \ + OP(0x02,MUL,2,1,G_LOW) \ + OP(0x03,SUB,2,1,G_VERYLOW) \ + OP(0x04,DIV,2,1,G_LOW) \ + OP(0x05,SDIV,2,1,G_LOW) \ + OP(0x06,MOD,2,1,G_LOW) \ + OP(0x07,SMOD,2,1,G_LOW) \ + OP(0x08,ADDMOD,3,1,G_MID) \ + OP(0x09,MULMOD,3,1,G_MID) \ + OP(0x0a,EXP,2,1,G_EXP) \ + OP(0x0b,SIGNEXTEND,2,1,G_LOW) \ + OP(0x0c,ASSERT_0x0c,2,1,G_ZERO) \ + OP(0x0d,ASSERT_0x0d,2,1,G_ZERO) \ + OP(0x0e,ASSERT_0x0e,2,1,G_ZERO) \ + OP(0x0f,ASSERT_0x0f,2,1,G_ZERO) \ + OP(0x10,LT,2,1,G_VERYLOW) \ + OP(0x11,GT,2,1,G_VERYLOW) \ + OP(0x12,SLT,2,1,G_VERYLOW) \ + OP(0x13,SGT,2,1,G_VERYLOW) \ + OP(0x14,EQ,2,1,G_VERYLOW) \ + OP(0x15,ISZERO,1,1,G_VERYLOW) \ + OP(0x16,AND,2,1,G_VERYLOW) \ + OP(0x17,OR,2,1,G_VERYLOW) \ + OP(0x18,XOR,2,1,G_VERYLOW) \ + OP(0x19,NOT,1,1,G_VERYLOW) \ + OP(0x1a,BYTE,2,1,G_VERYLOW) \ + OP(0x1b,SHL,2,1,G_VERYLOW) \ + OP(0x1c,SHR,2,1,G_VERYLOW) \ + OP(0x1d,SAR,2,1,G_VERYLOW) \ + OP(0x1e,CLZ,1,1,G_LOW) \ + OP(0x1f,ASSERT_0x1f,2,1,G_ZERO) \ + OP(0x20,SHA3,2,1,G_KECCAK) \ + OP(0x21,ASSERT_0x21,2,1,G_ZERO) \ + OP(0x22,ASSERT_0x22,2,1,G_ZERO) \ + OP(0x23,ASSERT_0x23,2,1,G_ZERO) \ + OP(0x24,ASSERT_0x24,2,1,G_ZERO) \ + OP(0x25,ASSERT_0x25,2,1,G_ZERO) \ + OP(0x26,ASSERT_0x26,2,1,G_ZERO) \ + OP(0x27,ASSERT_0x27,2,1,G_ZERO) \ + OP(0x28,ASSERT_0x28,2,1,G_ZERO) \ + OP(0x29,ASSERT_0x29,2,1,G_ZERO) \ + OP(0x2a,ASSERT_0x2a,2,1,G_ZERO) \ + OP(0x2b,ASSERT_0x2b,2,1,G_ZERO) \ + OP(0x2c,ASSERT_0x2c,2,1,G_ZERO) \ + OP(0x2d,ASSERT_0x2d,2,1,G_ZERO) \ + OP(0x2e,ASSERT_0x2e,2,1,G_ZERO) \ + OP(0x2f,ASSERT_0x2f,2,1,G_ZERO) \ + OP(0x30,ADDRESS,0,1,G_BASE) \ + OP(0x31,BALANCE,1,1,G_ACCESS) \ + OP(0x32,ORIGIN,0,1,G_BASE) \ + OP(0x33,CALLER,0,1,G_BASE) \ + OP(0x34,CALLVALUE,0,1,G_BASE) \ + OP(0x35,CALLDATALOAD,1,1,G_VERYLOW) \ + OP(0x36,CALLDATASIZE,0,1,G_BASE) \ + OP(0x37,CALLDATACOPY,3,0,G_COPY) \ + OP(0x38,CODESIZE,0,1,G_BASE) \ + OP(0x39,CODECOPY,3,0,G_COPY) \ + OP(0x3a,GASPRICE,0,1,G_BASE) \ + OP(0x3b,EXTCODESIZE,1,1,G_ACCESS) \ + OP(0x3c,EXTCODECOPY,4,0,G_ACCESS) \ + OP(0x3d,RETURNDATASIZE,0,1,G_BASE) \ + OP(0x3e,RETURNDATACOPY,3,0,G_COPY) \ + OP(0x3f,EXTCODEHASH,1,1,G_ACCESS) \ + OP(0x40,BLOCKHASH,1,1,G_BLOCKHASH) \ + OP(0x41,COINBASE,0,1,G_BASE) \ + OP(0x42,TIMESTAMP,0,1,G_BASE) \ + OP(0x43,NUMBER,0,1,G_BASE) \ + OP(0x44,PREVRANDAO,0,1,G_BASE) \ + OP(0x45,GASLIMIT,0,1,G_BASE) \ + OP(0x46,CHAINID,0,1,G_BASE) \ + OP(0x47,SELFBALANCE,0,1,G_LOW) \ + OP(0x48,BASEFEE,0,1,G_BASE) \ + OP(0x49,BLOBHASH,0,1,G_ZERO) \ + OP(0x4a,BLOBBASEFEE,0,1,G_ZERO) \ + OP(0x4b,ASSERT_0x4b,0,1,G_ZERO) \ + OP(0x4c,ASSERT_0x4c,0,1,G_ZERO) \ + OP(0x4d,ASSERT_0x4d,0,1,G_ZERO) \ + OP(0x4e,ASSERT_0x4e,0,1,G_ZERO) \ + OP(0x4f,ASSERT_0x4f,0,1,G_ZERO) \ + OP(0x50,POP,1,0,G_BASE) \ + OP(0x51,MLOAD,1,1,G_VERYLOW) \ + OP(0x52,MSTORE,2,0,G_VERYLOW) \ + OP(0x53,MSTORE8,2,0,G_VERYLOW) \ + OP(0x54,SLOAD,1,1,G_ACCESS) \ + OP(0x55,SSTORE,2,0,G_ACCESS) \ + OP(0x56,JUMP,1,0,G_MID) \ + OP(0x57,JUMPI,2,0,G_HIGH) \ + OP(0x58,PC,0,1,G_BASE) \ + OP(0x59,MSIZE,0,1,G_BASE) \ + OP(0x5a,GAS,0,1,G_BASE) \ + OP(0x5b,JUMPDEST,0,0,G_JUMPDEST) \ + OP(0x5c,TLOAD,1,1,G_ACCESS) \ + OP(0x5d,TSTORE,2,0,G_ACCESS) \ + OP(0x5e,MCOPY,3,0,G_COPY) \ + OP(0x5f,PUSH0,0,1,G_BASE) \ + OP(0x60,PUSH1,0,1,G_VERYLOW) \ + OP(0x61,PUSH2,0,1,G_VERYLOW) \ + OP(0x62,PUSH3,0,1,G_VERYLOW) \ + OP(0x63,PUSH4,0,1,G_VERYLOW) \ + OP(0x64,PUSH5,0,1,G_VERYLOW) \ + OP(0x65,PUSH6,0,1,G_VERYLOW) \ + OP(0x66,PUSH7,0,1,G_VERYLOW) \ + OP(0x67,PUSH8,0,1,G_VERYLOW) \ + OP(0x68,PUSH9,0,1,G_VERYLOW) \ + OP(0x69,PUSH10,0,1,G_VERYLOW) \ + OP(0x6a,PUSH11,0,1,G_VERYLOW) \ + OP(0x6b,PUSH12,0,1,G_VERYLOW) \ + OP(0x6c,PUSH13,0,1,G_VERYLOW) \ + OP(0x6d,PUSH14,0,1,G_VERYLOW) \ + OP(0x6e,PUSH15,0,1,G_VERYLOW) \ + OP(0x6f,PUSH16,0,1,G_VERYLOW) \ + OP(0x70,PUSH17,0,1,G_VERYLOW) \ + OP(0x71,PUSH18,0,1,G_VERYLOW) \ + OP(0x72,PUSH19,0,1,G_VERYLOW) \ + OP(0x73,PUSH20,0,1,G_VERYLOW) \ + OP(0x74,PUSH21,0,1,G_VERYLOW) \ + OP(0x75,PUSH22,0,1,G_VERYLOW) \ + OP(0x76,PUSH23,0,1,G_VERYLOW) \ + OP(0x77,PUSH24,0,1,G_VERYLOW) \ + OP(0x78,PUSH25,0,1,G_VERYLOW) \ + OP(0x79,PUSH26,0,1,G_VERYLOW) \ + OP(0x7a,PUSH27,0,1,G_VERYLOW) \ + OP(0x7b,PUSH28,0,1,G_VERYLOW) \ + OP(0x7c,PUSH29,0,1,G_VERYLOW) \ + OP(0x7d,PUSH30,0,1,G_VERYLOW) \ + OP(0x7e,PUSH31,0,1,G_VERYLOW) \ + OP(0x7f,PUSH32,0,1,G_VERYLOW) \ + OP(0x80,DUP1,0,1,G_VERYLOW) \ + OP(0x81,DUP2,0,1,G_VERYLOW) \ + OP(0x82,DUP3,0,1,G_VERYLOW) \ + OP(0x83,DUP4,0,1,G_VERYLOW) \ + OP(0x84,DUP5,0,1,G_VERYLOW) \ + OP(0x85,DUP6,0,1,G_VERYLOW) \ + OP(0x86,DUP7,0,1,G_VERYLOW) \ + OP(0x87,DUP8,0,1,G_VERYLOW) \ + OP(0x88,DUP9,0,1,G_VERYLOW) \ + OP(0x89,DUP10,0,1,G_VERYLOW) \ + OP(0x8a,DUP11,0,1,G_VERYLOW) \ + OP(0x8b,DUP12,0,1,G_VERYLOW) \ + OP(0x8c,DUP13,0,1,G_VERYLOW) \ + OP(0x8d,DUP14,0,1,G_VERYLOW) \ + OP(0x8e,DUP15,0,1,G_VERYLOW) \ + OP(0x8f,DUP16,0,1,G_VERYLOW) \ + OP(0x90,SWAP1,0,0,G_VERYLOW) \ + OP(0x91,SWAP2,0,0,G_VERYLOW) \ + OP(0x92,SWAP3,0,0,G_VERYLOW) \ + OP(0x93,SWAP4,0,0,G_VERYLOW) \ + OP(0x94,SWAP5,0,0,G_VERYLOW) \ + OP(0x95,SWAP6,0,0,G_VERYLOW) \ + OP(0x96,SWAP7,0,0,G_VERYLOW) \ + OP(0x97,SWAP8,0,0,G_VERYLOW) \ + OP(0x98,SWAP9,0,0,G_VERYLOW) \ + OP(0x99,SWAP10,0,0,G_VERYLOW) \ + OP(0x9a,SWAP11,0,0,G_VERYLOW) \ + OP(0x9b,SWAP12,0,0,G_VERYLOW) \ + OP(0x9c,SWAP13,0,0,G_VERYLOW) \ + OP(0x9d,SWAP14,0,0,G_VERYLOW) \ + OP(0x9e,SWAP15,0,0,G_VERYLOW) \ + OP(0x9f,SWAP16,0,0,G_VERYLOW) \ + OP(0xa0,LOG0,2,0,G_LOG) \ + OP(0xa1,LOG1,3,0,G_LOG + G_LOGTOPIC) \ + OP(0xa2,LOG2,4,0,G_LOG + 2 * G_LOGTOPIC) \ + OP(0xa3,LOG3,5,0,G_LOG + 3 * G_LOGTOPIC) \ + OP(0xa4,LOG4,6,0,G_LOG + 4 * G_LOGTOPIC) \ + OP(0xa5,ASSERT_0xa5,7,0,G_ZERO) \ + OP(0xa6,ASSERT_0xa6,7,0,G_ZERO) \ + OP(0xa7,ASSERT_0xa7,7,0,G_ZERO) \ + OP(0xa8,ASSERT_0xa8,7,0,G_ZERO) \ + OP(0xa9,ASSERT_0xa9,7,0,G_ZERO) \ + OP(0xaa,ASSERT_0xaa,7,0,G_ZERO) \ + OP(0xab,ASSERT_0xab,7,0,G_ZERO) \ + OP(0xac,ASSERT_0xac,7,0,G_ZERO) \ + OP(0xad,ASSERT_0xad,7,0,G_ZERO) \ + OP(0xae,ASSERT_0xae,7,0,G_ZERO) \ + OP(0xaf,ASSERT_0xaf,7,0,G_ZERO) \ + OP(0xb0,ASSERT_0xb0,7,0,G_ZERO) \ + OP(0xb1,ASSERT_0xb1,7,0,G_ZERO) \ + OP(0xb2,ASSERT_0xb2,7,0,G_ZERO) \ + OP(0xb3,ASSERT_0xb3,7,0,G_ZERO) \ + OP(0xb4,ASSERT_0xb4,7,0,G_ZERO) \ + OP(0xb5,ASSERT_0xb5,7,0,G_ZERO) \ + OP(0xb6,ASSERT_0xb6,7,0,G_ZERO) \ + OP(0xb7,ASSERT_0xb7,7,0,G_ZERO) \ + OP(0xb8,ASSERT_0xb8,7,0,G_ZERO) \ + OP(0xb9,ASSERT_0xb9,7,0,G_ZERO) \ + OP(0xba,ASSERT_0xba,7,0,G_ZERO) \ + OP(0xbb,ASSERT_0xbb,7,0,G_ZERO) \ + OP(0xbc,ASSERT_0xbc,7,0,G_ZERO) \ + OP(0xbd,ASSERT_0xbd,7,0,G_ZERO) \ + OP(0xbe,ASSERT_0xbe,7,0,G_ZERO) \ + OP(0xbf,ASSERT_0xbf,7,0,G_ZERO) \ + OP(0xc0,ASSERT_0xc0,7,0,G_ZERO) \ + OP(0xc1,ASSERT_0xc1,7,0,G_ZERO) \ + OP(0xc2,ASSERT_0xc2,7,0,G_ZERO) \ + OP(0xc3,ASSERT_0xc3,7,0,G_ZERO) \ + OP(0xc4,ASSERT_0xc4,7,0,G_ZERO) \ + OP(0xc5,ASSERT_0xc5,7,0,G_ZERO) \ + OP(0xc6,ASSERT_0xc6,7,0,G_ZERO) \ + OP(0xc7,ASSERT_0xc7,7,0,G_ZERO) \ + OP(0xc8,ASSERT_0xc8,7,0,G_ZERO) \ + OP(0xc9,ASSERT_0xc9,7,0,G_ZERO) \ + OP(0xca,ASSERT_0xca,7,0,G_ZERO) \ + OP(0xcb,ASSERT_0xcb,7,0,G_ZERO) \ + OP(0xcc,ASSERT_0xcc,7,0,G_ZERO) \ + OP(0xcd,ASSERT_0xcd,7,0,G_ZERO) \ + OP(0xce,ASSERT_0xce,7,0,G_ZERO) \ + OP(0xcf,ASSERT_0xcf,7,0,G_ZERO) \ + OP(0xd0,ASSERT_0xd0,7,0,G_ZERO) \ + OP(0xd1,ASSERT_0xd1,7,0,G_ZERO) \ + OP(0xd2,ASSERT_0xd2,7,0,G_ZERO) \ + OP(0xd3,ASSERT_0xd3,7,0,G_ZERO) \ + OP(0xd4,ASSERT_0xd4,7,0,G_ZERO) \ + OP(0xd5,ASSERT_0xd5,7,0,G_ZERO) \ + OP(0xd6,ASSERT_0xd6,7,0,G_ZERO) \ + OP(0xd7,ASSERT_0xd7,7,0,G_ZERO) \ + OP(0xd8,ASSERT_0xd8,7,0,G_ZERO) \ + OP(0xd9,ASSERT_0xd9,7,0,G_ZERO) \ + OP(0xda,ASSERT_0xda,7,0,G_ZERO) \ + OP(0xdb,ASSERT_0xdb,7,0,G_ZERO) \ + OP(0xdc,ASSERT_0xdc,7,0,G_ZERO) \ + OP(0xdd,ASSERT_0xdd,7,0,G_ZERO) \ + OP(0xde,ASSERT_0xde,7,0,G_ZERO) \ + OP(0xdf,ASSERT_0xdf,7,0,G_ZERO) \ + OP(0xe0,ASSERT_0xe0,7,0,G_ZERO) \ + OP(0xe1,ASSERT_0xe1,7,0,G_ZERO) \ + OP(0xe2,ASSERT_0xe2,7,0,G_ZERO) \ + OP(0xe3,ASSERT_0xe3,7,0,G_ZERO) \ + OP(0xe4,ASSERT_0xe4,7,0,G_ZERO) \ + OP(0xe5,ASSERT_0xe5,7,0,G_ZERO) \ + OP(0xe6,ASSERT_0xe6,7,0,G_ZERO) \ + OP(0xe7,ASSERT_0xe7,7,0,G_ZERO) \ + OP(0xe8,ASSERT_0xe8,7,0,G_ZERO) \ + OP(0xe9,ASSERT_0xe9,7,0,G_ZERO) \ + OP(0xea,ASSERT_0xea,7,0,G_ZERO) \ + OP(0xeb,ASSERT_0xeb,7,0,G_ZERO) \ + OP(0xec,ASSERT_0xec,7,0,G_ZERO) \ + OP(0xed,ASSERT_0xed,7,0,G_ZERO) \ + OP(0xee,ASSERT_0xee,7,0,G_ZERO) \ + OP(0xef,ASSERT_0xef,7,0,G_ZERO) \ + OP(0xf0,CREATE,3,1,G_CREATE) \ + OP(0xf1,CALL,7,1,G_ACCESS) \ + OP(0xf2,CALLCODE,7,1,G_ACCESS) \ + OP(0xf3,RETURN,2,0,G_ZERO) \ + OP(0xf4,DELEGATECALL,6,1,G_ACCESS) \ + OP(0xf5,CREATE2,4,1,G_CREATE) \ + OP(0xf6,ASSERT_0xf6,4,1,G_AUTH) \ + OP(0xf7,ASSERT_0xf7,8,1,G_ACCESS) \ + OP(0xf8,ASSERT_0xf8,6,1,G_ZERO) \ + OP(0xf9,ASSERT_0xf9,6,1,G_ZERO) \ + OP(0xfa,STATICCALL,6,1,G_ACCESS) \ + OP(0xfb,ASSERT_0xfb,6,1,G_ZERO) \ + OP(0xfc,ASSERT_0xfc,6,1,G_ZERO) \ + OP(0xfd,REVERT,2,0,G_ZERO) \ + OP(0xfe,INVALID,0,0,G_ZERO) \ + OP(0xff,SELFDESTRUCT,1,0,G_SELFDESTRUCT) typedef enum { diff --git a/include/precompiles.h b/include/precompiles.h index 7503d3e..2b9155c 100644 --- a/include/precompiles.h +++ b/include/precompiles.h @@ -1,15 +1,15 @@ #define PRECOMPILES \ -PRECOMPILE(HOLE,0x0,1) \ -PRECOMPILE(ECRECOVER,0x1,1) \ -PRECOMPILE(SHA2_256,0x2,0) \ -PRECOMPILE(RIPEMD160,0x3,0) \ -PRECOMPILE(IDENTITY,0x4,1) \ -PRECOMPILE(MODEXP,0x5,0) \ -PRECOMPILE(EC_ADD,0x6,0) \ -PRECOMPILE(EC_MUL,0x7,0) \ -PRECOMPILE(EC_PAIRING,0x8,0) \ -PRECOMPILE(BLACK2F,0x9,0) \ -PRECOMPILE(ZKG_POINT,0xa,0) + PRECOMPILE(HOLE,0x0,1) \ + PRECOMPILE(ECRECOVER,0x1,1) \ + PRECOMPILE(SHA2_256,0x2,0) \ + PRECOMPILE(RIPEMD160,0x3,0) \ + PRECOMPILE(IDENTITY,0x4,1) \ + PRECOMPILE(MODEXP,0x5,0) \ + PRECOMPILE(EC_ADD,0x6,0) \ + PRECOMPILE(EC_MUL,0x7,0) \ + PRECOMPILE(EC_PAIRING,0x8,0) \ + PRECOMPILE(BLACK2F,0x9,0) \ + PRECOMPILE(ZKG_POINT,0xa,0) typedef enum precompile { #define PRECOMPILE(name,address,supported) name, diff --git a/include/scanstack.h b/include/scanstack.h index de74e09..252399c 100644 --- a/include/scanstack.h +++ b/include/scanstack.h @@ -18,7 +18,7 @@ static inline void scanstackPush(op_t op) { static inline void scanstackPushData(const data_t *data) { size_t pos = data->size; - while (pos --> 0) { + while (pos--> 0) { scanstack[scanstackIndex++] = data->content[pos]; } } diff --git a/include/uint256.h b/include/uint256.h index 08e4e06..1520abc 100644 --- a/include/uint256.h +++ b/include/uint256.h @@ -1,19 +1,19 @@ /******************************************************************************* -* Ledger Ethereum App -* (c) 2016-2019 Ledger -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -********************************************************************************/ + * Ledger Ethereum App + * (c) 2016-2019 Ledger + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + ********************************************************************************/ // Adapted from https://github.com/calccrypto/uint256_t @@ -24,11 +24,17 @@ #include #include -typedef struct uint128_t { uint64_t elements[2]; } __attribute__((__packed__)) uint128_t; +typedef struct uint128_t { + uint64_t elements[2]; +} __attribute__((__packed__)) uint128_t; -typedef struct uint256_t { uint128_t elements[2]; } __attribute__((__packed__)) uint256_t; +typedef struct uint256_t { + uint128_t elements[2]; +} __attribute__((__packed__)) uint256_t; -typedef struct uint512_t { uint256_t elements[2]; } __attribute__((__packed__)) uint512_t; +typedef struct uint512_t { + uint256_t elements[2]; +} __attribute__((__packed__)) uint512_t; #define UPPER_P(x) (x)->elements[0] #define LOWER_P(x) (x)->elements[1] diff --git a/include/vector.h b/include/vector.h index 881d173..026d64f 100644 --- a/include/vector.h +++ b/include/vector.h @@ -2,43 +2,43 @@ #include #include -#define VECTOR(type, vector)\ -typedef struct vector {\ - size_t num_ ## type ## s;\ - type ## _t *type ## s;\ - size_t buffer_size;\ -} vector ## _t;\ -static inline void vector ## _init(vector ## _t *vector, size_t buffer_size) {\ - vector->num_ ## type ## s = 0;\ - vector->buffer_size = buffer_size;\ - vector->type ## s = calloc(buffer_size, sizeof(type ## _t));\ -}\ -static inline void vector ## _destroy(vector ## _t *vector) {\ - free(vector->type ## s);\ -}\ -static inline void vector ## _append(vector ## _t *vector, type ## _t t) {\ - if (vector->num_ ## type ## s >= vector->buffer_size) {\ - vector->buffer_size <<= 1;\ - type ## _t *buffer = calloc(vector->buffer_size, sizeof(*buffer));\ - memcpy(buffer, vector->type ## s, sizeof(*buffer) * (vector->buffer_size >> 1));\ - free(vector->type ## s);\ - vector->type ## s = buffer;\ - }\ - vector->type ## s[vector->num_ ## type ## s++] = t;\ -}\ -static inline void vector ## _ensure(vector ## _t *vector, size_t capacity) {\ - if (vector->buffer_size < capacity) {\ - vector->buffer_size = capacity;\ - type ## _t *buffer = calloc(capacity, sizeof(*buffer));\ - memcpy(buffer, vector->type ## s, sizeof(*buffer) * vector->num_ ## type ## s);\ - free(vector->type ## s);\ - vector->type ## s = buffer;\ - }\ -}\ -static inline void vector ## _trimTo(vector ## _t *vector, uint16_t index) {\ - memmove(&vector->type ## s[0], &vector->type ## s[index], (vector->num_ ## type ## s - index) * sizeof(type ## _t));\ - vector->num_ ## type ## s -= index;\ -}\ -static inline type ## _t vector ## _pop(vector ## _t *vector) {\ - return vector->type ## s[--vector->num_ ## type ## s];\ -} +#define VECTOR(type, vector) \ + typedef struct vector { \ + size_t num_ ## type ## s; \ + type ## _t *type ## s; \ + size_t buffer_size; \ + } vector ## _t; \ + static inline void vector ## _init(vector ## _t *vector, size_t buffer_size) { \ + vector->num_ ## type ## s = 0; \ + vector->buffer_size = buffer_size; \ + vector->type ## s = calloc(buffer_size, sizeof(type ## _t)); \ + } \ + static inline void vector ## _destroy(vector ## _t *vector) { \ + free(vector->type ## s); \ + } \ + static inline void vector ## _append(vector ## _t *vector, type ## _t t) { \ + if (vector->num_ ## type ## s >= vector->buffer_size) { \ + vector->buffer_size <<= 1; \ + type ## _t *buffer = calloc(vector->buffer_size, sizeof(*buffer)); \ + memcpy(buffer, vector->type ## s, sizeof(*buffer) * (vector->buffer_size >> 1)); \ + free(vector->type ## s); \ + vector->type ## s = buffer; \ + } \ + vector->type ## s[vector->num_ ## type ## s++] = t; \ + } \ + static inline void vector ## _ensure(vector ## _t *vector, size_t capacity) { \ + if (vector->buffer_size < capacity) { \ + vector->buffer_size = capacity; \ + type ## _t *buffer = calloc(capacity, sizeof(*buffer)); \ + memcpy(buffer, vector->type ## s, sizeof(*buffer) * vector->num_ ## type ## s); \ + free(vector->type ## s); \ + vector->type ## s = buffer; \ + } \ + } \ + static inline void vector ## _trimTo(vector ## _t *vector, uint16_t index) { \ + memmove(&vector->type ## s[0], &vector->type ## s[index], (vector->num_ ## type ## s - index) * sizeof(type ## _t)); \ + vector->num_ ## type ## s -= index; \ + } \ + static inline type ## _t vector ## _pop(vector ## _t *vector) { \ + return vector->type ## s[--vector->num_ ## type ## s]; \ + } diff --git a/ops.c b/ops.c index 7bc5f61..4a828c4 100644 --- a/ops.c +++ b/ops.c @@ -3,7 +3,7 @@ const char *opnames = "" #define OP(opcode,opname,argCount,retCount,gas) #opname " " -OPS + OPS #undef OP ; diff --git a/precompiles.c b/precompiles.c index 1a08770..108145f 100644 --- a/precompiles.c +++ b/precompiles.c @@ -3,7 +3,7 @@ const char *precompiles = "" #define PRECOMPILE(name,address,supported) "| `" #name "` | `" #address "` | " #supported " |\n" -PRECOMPILES + PRECOMPILES #undef PRECOMPILE ; diff --git a/src/dio.c b/src/dio.c index bbd18b0..4f8ed8d 100644 --- a/src/dio.c +++ b/src/dio.c @@ -14,15 +14,15 @@ static inline int jsonIgnores(char ch) { return ch != '{' - && ch != '}' - && ch != '[' - && ch != ']' - && ch != ',' - && ch != ':' - && ch != '"' - && (ch < '0' || ch > '9') - && (ch < 'A' || ch > 'Z') - && (ch < 'a' || ch > 'z') + && ch != '}' + && ch != '[' + && ch != ']' + && ch != ',' + && ch != ':' + && ch != '"' + && (ch < '0' || ch > '9') + && (ch < 'A' || ch > 'Z') + && (ch < 'a' || ch > 'z') ; } @@ -66,7 +66,9 @@ static void jsonSkipExpectedChar(const char **iter, char expected) { static const char *jsonScanStr(const char **iter) { jsonScanChar(iter, '"'); const char *start = *iter; - for (char ch; (ch = **iter) != '"' && ch; (*iter)++); + for (char ch; (ch = **iter) != '"' && ch; (*iter)++) { + ; + } jsonSkipExpectedChar(iter, '"'); return start; } @@ -96,7 +98,8 @@ static void jsonSkipEntryValue(const char **iter) { top--; } continue; - } else switch (**iter) { + } else { + switch (**iter) { case '[': case '{': case '"': @@ -112,6 +115,7 @@ static void jsonSkipEntryValue(const char **iter) { jsonFailExpectingChar(']', '}'); } break; + } } } fprintf(stderr, "Unexpected entry is too deep at line %" PRIu64 "\n", lineNumber); @@ -405,26 +409,28 @@ static void jsonScanLogTopics(const char **iter, logChanges_t *log) { jsonScanChar(iter, '['); jsonScanWaste(iter); uint256_t topics[MAX_LOG_TOPICS]; - if (**iter != ']') do { - const char *topic = jsonScanStr(iter); - jsonSkipExpectedChar(&topic, '0'); - jsonSkipExpectedChar(&topic, 'x'); - clear256(topics+log->topicCount); - while (*topic != '"') { - shiftl256((topics+log->topicCount), 4, (topics+log->topicCount)); - LOWER(LOWER_P((topics+log->topicCount))) |= hexString8ToUint8(*topic); - topic++; - } - log->topicCount++; - jsonScanWaste(iter); - if (**iter == ',') { - jsonSkipExpectedChar(iter, ','); + if (**iter != ']') { + do { + const char *topic = jsonScanStr(iter); + jsonSkipExpectedChar(&topic, '0'); + jsonSkipExpectedChar(&topic, 'x'); + clear256(topics+log->topicCount); + while (*topic != '"') { + shiftl256((topics+log->topicCount), 4, (topics+log->topicCount)); + LOWER(LOWER_P((topics+log->topicCount))) |= hexString8ToUint8(*topic); + topic++; + } + log->topicCount++; jsonScanWaste(iter); - continue; - } else { - break; - } - } while (1); + if (**iter == ',') { + jsonSkipExpectedChar(iter, ','); + jsonScanWaste(iter); + continue; + } else { + break; + } + } while (1); + } jsonSkipExpectedChar(iter, ']'); log->topics = calloc(log->topicCount, sizeof(uint256_t)); for (uint16_t i = log->topicCount; i--> 0;) { @@ -450,32 +456,34 @@ static void jsonScanLog(const char **iter, logChanges_t **prev) { log->prev = *prev; *prev = log; jsonScanWaste(iter); - if (**iter != '}') do { - const char *logHeading = jsonScanStr(iter); - size_t logHeadingLen = *iter - logHeading - 1; - jsonScanChar(iter, ':'); - if (logHeadingLen == 6 && *logHeading == 't') { - // topics - jsonScanLogTopics(iter, log); - } else if (logHeadingLen == 4 && *logHeading == 'd') { - // data - jsonScanData(iter, &log->data); - } else { - fprintf(stderr, "Unexpected log heading: "); - for (size_t i = 0; i < logHeadingLen; i++) { - fputc(logHeading[i], stderr); + if (**iter != '}') { + do { + const char *logHeading = jsonScanStr(iter); + size_t logHeadingLen = *iter - logHeading - 1; + jsonScanChar(iter, ':'); + if (logHeadingLen == 6 && *logHeading == 't') { + // topics + jsonScanLogTopics(iter, log); + } else if (logHeadingLen == 4 && *logHeading == 'd') { + // data + jsonScanData(iter, &log->data); + } else { + fprintf(stderr, "Unexpected log heading: "); + for (size_t i = 0; i < logHeadingLen; i++) { + fputc(logHeading[i], stderr); + } + fputc('\n', stderr); + _exit(1); } - fputc('\n', stderr); - _exit(1); - } - jsonScanWaste(iter); - if (**iter == ',') { - jsonSkipExpectedChar(iter, ','); jsonScanWaste(iter); - } else { - break; - } - } while (1); + if (**iter == ',') { + jsonSkipExpectedChar(iter, ','); + jsonScanWaste(iter); + } else { + break; + } + } while (1); + } jsonSkipExpectedChar(iter, '}'); } @@ -494,18 +502,20 @@ static void jsonScanAccountLogs(const char **iter, logsEntry_t **prev) { jsonScanChar(iter, '['); jsonScanWaste(iter); - if (**iter != ']') do { - jsonScanLog(iter, &accountLogs->logs); + if (**iter != ']') { + do { + jsonScanLog(iter, &accountLogs->logs); - jsonScanWaste(iter); - if (**iter == ',') { - jsonSkipExpectedChar(iter, ','); jsonScanWaste(iter); - continue; - } else { - break; - } - } while (1); + if (**iter == ',') { + jsonSkipExpectedChar(iter, ','); + jsonScanWaste(iter); + continue; + } else { + break; + } + } while (1); + } jsonSkipExpectedChar(iter, ']'); } @@ -535,234 +545,242 @@ static testEntry_t *jsonScanTestEntry(const char **iter) { jsonScanChar(iter, '{'); jsonScanWaste(iter); - if (**iter != '}') do { - const char *testHeading = jsonScanStr(iter); - size_t testHeadingLen = *iter - testHeading - 1; - jsonScanChar(iter, ':'); - if (testHeadingLen == 10 && *testHeading == 'a') { - // accessList - jsonScanChar(iter, '{'); - jsonScanWaste(iter); - if (**iter != '}') do { - accessList_t *accessList = calloc(1, sizeof(accessList_t)); - accessList->prev = test->accessList; - test->accessList = accessList; - const char *accessListAccount = jsonScanStr(iter); - size_t accessListAccountLen = *iter - accessListAccount - 1; - if (accessListAccountLen != 42) { - fprintf(stderr, "Unexpected address length %zu\n", accessListAccountLen); - _exit(1); + if (**iter != '}') { + do { + const char *testHeading = jsonScanStr(iter); + size_t testHeadingLen = *iter - testHeading - 1; + jsonScanChar(iter, ':'); + if (testHeadingLen == 10 && *testHeading == 'a') { + // accessList + jsonScanChar(iter, '{'); + jsonScanWaste(iter); + if (**iter != '}') { + do { + accessList_t *accessList = calloc(1, sizeof(accessList_t)); + accessList->prev = test->accessList; + test->accessList = accessList; + const char *accessListAccount = jsonScanStr(iter); + size_t accessListAccountLen = *iter - accessListAccount - 1; + if (accessListAccountLen != 42) { + fprintf(stderr, "Unexpected address length %zu\n", accessListAccountLen); + _exit(1); + } + accessList->address = AddressFromHex42(accessListAccount); + + jsonScanChar(iter, ':'); + + jsonScanChar(iter, '['); + if (**iter != ']') { + do { + const char *accessListSlot = jsonScanStr(iter); + + jsonSkipExpectedChar(&accessListSlot, '0'); + jsonSkipExpectedChar(&accessListSlot, 'x'); + + + accessListStorage_t *slot = calloc(1, sizeof(accessListStorage_t)); + slot->prev = accessList->storage; + accessList->storage = slot; + + while (*accessListSlot != '"') { + shiftl256(&slot->key, 4, &slot->key); + LOWER(LOWER(slot->key)) |= hexString8ToUint8(*accessListSlot); + accessListSlot++; + } + + jsonScanWaste(iter); + if (**iter == ',') { + jsonSkipExpectedChar(iter, ','); + jsonScanWaste(iter); + continue; + } else { + break; + } + } while (1); + } + jsonScanChar(iter, ']'); + jsonScanWaste(iter); + if (**iter == ',') { + jsonSkipExpectedChar(iter, ','); + jsonScanWaste(iter); + continue; + } else { + break; + } + } while (1); } - accessList->address = AddressFromHex42(accessListAccount); - - jsonScanChar(iter, ':'); - - jsonScanChar(iter, '['); - if (**iter != ']') do { - const char *accessListSlot = jsonScanStr(iter); - - jsonSkipExpectedChar(&accessListSlot, '0'); - jsonSkipExpectedChar(&accessListSlot, 'x'); - - - accessListStorage_t *slot = calloc(1, sizeof(accessListStorage_t)); - slot->prev = accessList->storage; - accessList->storage = slot; - - while (*accessListSlot != '"') { - shiftl256(&slot->key, 4, &slot->key); - LOWER(LOWER(slot->key)) |= hexString8ToUint8(*accessListSlot); - accessListSlot++; - } + jsonScanChar(iter, '}'); + } else if (testHeadingLen == 4 && *testHeading == 'l') { + // logs + jsonScanChar(iter, '{'); + jsonScanWaste(iter); + if (**iter != '}') { + do { + jsonScanAccountLogs(iter, &test->logs); - jsonScanWaste(iter); - if (**iter == ',') { - jsonSkipExpectedChar(iter, ','); jsonScanWaste(iter); - continue; - } else { - break; + if (**iter == ',') { + jsonSkipExpectedChar(iter, ','); + jsonScanWaste(iter); + continue; + } else { + break; + } + } while (1); + } + jsonSkipExpectedChar(iter, '}'); + } else { + const char *testValue = jsonScanStr(iter); + size_t testValueLength = *iter - testValue - 1; + if (testHeadingLen == 5 && *testHeading == 'i') { + // input + jsonSkipExpectedChar(&testValue, '0'); + jsonSkipExpectedChar(&testValue, 'x'); + test->input.size = (testValueLength - 2) / 2; + test->input.content = malloc(test->input.size); + uint32_t whitespaceCount = 0; + for (size_t i = 0; i < test->input.size; i++) { + char curr = testValue[i * 2 + whitespaceCount]; + if (jsonIgnores(curr)) { + if (whitespaceCount++ & 1) { + test->input.size--; + } + if (curr == '\n') { + lineNumber++; + } + i--; + continue; + } + test->input.content[i] = hexString16ToUint8(testValue + i * 2 + whitespaceCount); + } + } else if (testHeadingLen == 4 && *testHeading == 'n') { + // name + test->name = malloc(testValueLength + 1); + strncpy(test->name, testValue, testValueLength); + test->name[testValueLength] = '\0'; + } else if (testHeadingLen == 5 && *testHeading == 'd') { + // debug + jsonSkipExpectedChar(&testValue, '0'); + jsonSkipExpectedChar(&testValue, 'x'); + testValueLength -= 2; + for (size_t i = 0; i < testValueLength; i++) { + test->debug <<= 4; + test->debug |= hexString8ToUint8(testValue[i]); + } + } else if (testHeadingLen == 11 && *testHeading == 'b') { + // blockNumber + test->blockNumber = malloc(8); + *test->blockNumber = 0; + jsonSkipExpectedChar(&testValue, '0'); + jsonSkipExpectedChar(&testValue, 'x'); + testValueLength -= 2; + for (size_t i = 0; i < testValueLength; i++) { + *test->blockNumber <<= 4; + *test->blockNumber |= hexString8ToUint8(testValue[i]); + } + } else if (testHeadingLen == 9 && *testHeading == 't') { + // timestamp + test->timestamp = malloc(8); + *test->timestamp = 0; + jsonSkipExpectedChar(&testValue, '0'); + jsonSkipExpectedChar(&testValue, 'x'); + testValueLength -= 2; + for (size_t i = 0; i < testValueLength; i++) { + *test->timestamp <<= 4; + *test->timestamp |= hexString8ToUint8(testValue[i]); + } + } else if (testHeadingLen == 6 && *testHeading == 'o') { + // output + test->outputSpecified = true; + jsonSkipExpectedChar(&testValue, '0'); + jsonSkipExpectedChar(&testValue, 'x'); + test->output.size = (testValueLength - 2) / 2; + test->output.content = malloc(test->output.size); + for (size_t i = 0; i < test->output.size; i++) { + test->output.content[i] = hexString16ToUint8(testValue + i * 2); + } + } else if (testHeadingLen == 5 && *testHeading == 'v') { + // value + jsonSkipExpectedChar(&testValue, '0'); + jsonSkipExpectedChar(&testValue, 'x'); + while (*testValue != '"') { + test->value[0] <<= 4; + test->value[0] |= test->value[1] >> 28; + test->value[1] <<= 4; + test->value[1] |= test->value[2] >> 28; + test->value[2] <<= 4; + test->value[2] |= hexString8ToUint8(*testValue); + testValue++; + } + } else if (testHeadingLen == 4 && *testHeading == 'f') { + // from + jsonSkipExpectedChar(&testValue, '0'); + jsonSkipExpectedChar(&testValue, 'x'); + for (unsigned int i = 0; i < 20; i++) { + test->from.address[i] = hexString16ToUint8(testValue); + testValue += 2; + } + } else if (testHeadingLen == 2 && *testHeading == 't') { + // to + if (test->to) { + free(test->to); + } + test->to = jsonReadAddress(&testValue); + } else if (testHeadingLen == 7 && *testHeading == 'g') { + // gasUsed + jsonSkipExpectedChar(&testValue, '0'); + jsonSkipExpectedChar(&testValue, 'x'); + test->result.gasUsedBegin = testValue; + testValueLength -= 2; + test->result.gasUsedEnd = testValue + testValueLength; + for (size_t i = 0; i < testValueLength; i++) { + test->gasUsed <<= 4; + test->gasUsed |= hexString8ToUint8(testValue[i]); + } + } else if (testHeadingLen == 3 && *testHeading == 'g') { + // gas + jsonSkipExpectedChar(&testValue, '0'); + jsonSkipExpectedChar(&testValue, 'x'); + while (*testValue != '"') { + test->gas <<= 4; + test->gas |= hexString8ToUint8(*testValue); + testValue++; + } + } else if (testHeadingLen == 2 && *testHeading == 'o') { + // op + const char *end; + test->op = parseOp(testValue, &end); + } else if (testHeadingLen == 6 && *testHeading == 's') { + // status + jsonSkipExpectedChar(&testValue, '0'); + jsonSkipExpectedChar(&testValue, 'x'); + clear256(&test->status); + while (*testValue != '"') { + shiftl256(&test->status, 4, &test->status); + LOWER(LOWER(test->status)) |= hexString8ToUint8(*testValue); + testValue++; } - } while (1); - jsonScanChar(iter, ']'); - jsonScanWaste(iter); - if (**iter == ',') { - jsonSkipExpectedChar(iter, ','); - jsonScanWaste(iter); - continue; } else { - break; + fputs("Unexpected test heading: ", stderr); + for (size_t i = 0; i < testHeadingLen; i++) { + fputc(testHeading[i], stderr); + } + fputc('\n', stderr); } - } while (1); - jsonScanChar(iter, '}'); - } else if (testHeadingLen == 4 && *testHeading == 'l') { - // logs - jsonScanChar(iter, '{'); + } + if (test->result.gasUsedEnd == NULL) { + test->result.gasUsedEnd = *iter; + } jsonScanWaste(iter); - if (**iter != '}') do { - jsonScanAccountLogs(iter, &test->logs); - + if (**iter == ',') { + jsonSkipExpectedChar(iter, ','); jsonScanWaste(iter); - if (**iter == ',') { - jsonSkipExpectedChar(iter, ','); - jsonScanWaste(iter); - continue; - } else { - break; - } - } while (1); - jsonSkipExpectedChar(iter, '}'); - } else { - const char *testValue = jsonScanStr(iter); - size_t testValueLength = *iter - testValue - 1; - if (testHeadingLen == 5 && *testHeading == 'i') { - // input - jsonSkipExpectedChar(&testValue, '0'); - jsonSkipExpectedChar(&testValue, 'x'); - test->input.size = (testValueLength - 2) / 2; - test->input.content = malloc(test->input.size); - uint32_t whitespaceCount = 0; - for (size_t i = 0; i < test->input.size; i++) { - char curr = testValue[i * 2 + whitespaceCount]; - if (jsonIgnores(curr)) { - if (whitespaceCount++ & 1) { - test->input.size--; - } - if (curr == '\n') { - lineNumber++; - } - i--; - continue; - } - test->input.content[i] = hexString16ToUint8(testValue + i * 2 + whitespaceCount); - } - } else if (testHeadingLen == 4 && *testHeading == 'n') { - // name - test->name = malloc(testValueLength + 1); - strncpy(test->name, testValue, testValueLength); - test->name[testValueLength] = '\0'; - } else if (testHeadingLen == 5 && *testHeading == 'd') { - // debug - jsonSkipExpectedChar(&testValue, '0'); - jsonSkipExpectedChar(&testValue, 'x'); - testValueLength -= 2; - for (size_t i = 0; i < testValueLength; i++) { - test->debug <<= 4; - test->debug |= hexString8ToUint8(testValue[i]); - } - } else if (testHeadingLen == 11 && *testHeading == 'b') { - // blockNumber - test->blockNumber = malloc(8); - *test->blockNumber = 0; - jsonSkipExpectedChar(&testValue, '0'); - jsonSkipExpectedChar(&testValue, 'x'); - testValueLength -= 2; - for (size_t i = 0; i < testValueLength; i++) { - *test->blockNumber <<= 4; - *test->blockNumber |= hexString8ToUint8(testValue[i]); - } - } else if (testHeadingLen == 9 && *testHeading == 't') { - // timestamp - test->timestamp = malloc(8); - *test->timestamp = 0; - jsonSkipExpectedChar(&testValue, '0'); - jsonSkipExpectedChar(&testValue, 'x'); - testValueLength -= 2; - for (size_t i = 0; i < testValueLength; i++) { - *test->timestamp <<= 4; - *test->timestamp |= hexString8ToUint8(testValue[i]); - } - } else if (testHeadingLen == 6 && *testHeading == 'o') { - // output - test->outputSpecified = true; - jsonSkipExpectedChar(&testValue, '0'); - jsonSkipExpectedChar(&testValue, 'x'); - test->output.size = (testValueLength - 2) / 2; - test->output.content = malloc(test->output.size); - for (size_t i = 0; i < test->output.size; i++) { - test->output.content[i] = hexString16ToUint8(testValue + i * 2); - } - } else if (testHeadingLen == 5 && *testHeading == 'v') { - // value - jsonSkipExpectedChar(&testValue, '0'); - jsonSkipExpectedChar(&testValue, 'x'); - while (*testValue != '"') { - test->value[0] <<= 4; - test->value[0] |= test->value[1] >> 28; - test->value[1] <<= 4; - test->value[1] |= test->value[2] >> 28; - test->value[2] <<= 4; - test->value[2] |= hexString8ToUint8(*testValue); - testValue++; - } - } else if (testHeadingLen == 4 && *testHeading == 'f') { - // from - jsonSkipExpectedChar(&testValue, '0'); - jsonSkipExpectedChar(&testValue, 'x'); - for (unsigned int i = 0; i < 20; i++) { - test->from.address[i] = hexString16ToUint8(testValue); - testValue += 2; - } - } else if (testHeadingLen == 2 && *testHeading == 't') { - // to - if (test->to) { - free(test->to); - } - test->to = jsonReadAddress(&testValue); - } else if (testHeadingLen == 7 && *testHeading == 'g') { - // gasUsed - jsonSkipExpectedChar(&testValue, '0'); - jsonSkipExpectedChar(&testValue, 'x'); - test->result.gasUsedBegin = testValue; - testValueLength -= 2; - test->result.gasUsedEnd = testValue + testValueLength; - for (size_t i = 0; i < testValueLength; i++) { - test->gasUsed <<= 4; - test->gasUsed |= hexString8ToUint8(testValue[i]); - } - } else if (testHeadingLen == 3 && *testHeading == 'g') { - // gas - jsonSkipExpectedChar(&testValue, '0'); - jsonSkipExpectedChar(&testValue, 'x'); - while (*testValue != '"') { - test->gas <<= 4; - test->gas |= hexString8ToUint8(*testValue); - testValue++; - } - } else if (testHeadingLen == 2 && *testHeading == 'o') { - // op - const char *end; - test->op = parseOp(testValue, &end); - } else if (testHeadingLen == 6 && *testHeading == 's') { - // status - jsonSkipExpectedChar(&testValue, '0'); - jsonSkipExpectedChar(&testValue, 'x'); - clear256(&test->status); - while (*testValue != '"') { - shiftl256(&test->status, 4, &test->status); - LOWER(LOWER(test->status)) |= hexString8ToUint8(*testValue); - testValue++; - } + continue; } else { - fputs("Unexpected test heading: ", stderr); - for (size_t i = 0; i < testHeadingLen; i++) { - fputc(testHeading[i], stderr); - } - fputc('\n', stderr); + break; } - } - if (test->result.gasUsedEnd == NULL) { - test->result.gasUsedEnd = *iter; - } - jsonScanWaste(iter); - if (**iter == ',') { - jsonSkipExpectedChar(iter, ','); - jsonScanWaste(iter); - continue; - } else { - break; - } - } while (1); else { + } while (1); + } else { // empty test entry test->result.gasUsedEnd = *iter; test->result.emptyTest = true; @@ -785,184 +803,186 @@ static void jsonScanEntry(const char **iter) { jsonScanChar(iter, ':'); jsonScanWaste(iter); switch(*(uint32_t *)heading) { - case 'rdda': - // address - entry.address = jsonReadAddressString(iter); - break; - case 'alab': - // balance - // TODO support decimal integer - jsonSkipExpectedChar(iter, '"'); + case 'rdda': + // address + entry.address = jsonReadAddressString(iter); + break; + case 'alab': + // balance + // TODO support decimal integer + jsonSkipExpectedChar(iter, '"'); + jsonSkipExpectedChar(iter, '0'); + jsonSkipExpectedChar(iter, 'x'); + while (**iter != '"') { + entry.balance[0] <<= 4; + entry.balance[0] |= entry.balance[1] >> 28; + entry.balance[1] <<= 4; + entry.balance[1] |= entry.balance[2] >> 28; + entry.balance[2] <<= 4; + entry.balance[2] |= hexString8ToUint8(**iter); + (*iter)++; + } + jsonSkipExpectedChar(iter, '"'); + break; + case 'cnon': + // nonce + // TODO support decimal integer + jsonSkipExpectedChar(iter, '"'); + jsonSkipExpectedChar(iter, '0'); + jsonSkipExpectedChar(iter, 'x'); + while (**iter != '"') { + entry.nonce <<= 4; + entry.nonce |= hexString8ToUint8(**iter); + (*iter)++; + } + jsonSkipExpectedChar(iter, '"'); + break; + case 'aerc': + // creator + entry.creator = jsonReadAddressString(iter); + break; + case 'tini': + // init, initcode, initCode + { + const char *start = jsonScanStr(iter); + if (*(uint16_t *)start == 'x0') { + jsonSkipExpectedChar(&start, '0'); + jsonSkipExpectedChar(&start, 'x'); + entry.initCode.size = (*iter - start) / 2; + entry.initCode.content = calloc(entry.initCode.size, 1); + for (unsigned int i = 0; i < entry.initCode.size; i++) { + entry.initCode.content[i] = hexString16ToUint8(start); + start += 2; + } + } else { + size_t len = *iter - start - 1; + char *initcodePath = malloc(len + 1); + memcpy(initcodePath, start, len); + initcodePath[len] = '\0'; + entry.initCode = assemblePath(initcodePath); + free(initcodePath); + } + } + break; + case 'edoc': + // code + { + const char *start = jsonScanStr(iter); + if (*(uint16_t *)start == 'x0') { + jsonSkipExpectedChar(&start, '0'); + jsonSkipExpectedChar(&start, 'x'); + entry.code.size = (*iter - start) / 2; + entry.code.content = calloc(entry.code.size, 1); + for (unsigned int i = 0; i < entry.code.size; i++) { + entry.code.content[i] = hexString16ToUint8(start); + start += 2; + } + } else { + size_t len = *iter - start - 1; + entry.path = malloc(len + 1); + memcpy(entry.path, start, len); + entry.path[len] = '\0'; + entry.code = assemblePath(entry.path); + } + } + break; + case 'opmi': + // import + { + const char *start = jsonScanStr(iter); + size_t len = *iter - start - 1; + entry.importPath = malloc(len + 1); + memcpy(entry.importPath, start, len); + entry.importPath[len] = '\0'; + } + break; + case 'snoc': + if (headingLen == 9) { + // construct + const char *start = jsonScanStr(iter); + size_t len = *iter - start - 1; + entry.path = malloc(len + 1); + memcpy(entry.path, start, len); + entry.path[len] = '\0'; + entry.initCode = defaultConstructorForPath(entry.path); + } else { + // constructTest + entry.constructTest = jsonScanTestEntry(iter); + } + break; + case 'tset': + // tests + { + jsonSkipExpectedChar(iter, '['); + jsonScanWaste(iter); + if (**iter != ']') { + do { + testEntry_t *test = jsonScanTestEntry(iter); + test->prev = entry.tests; + entry.tests = test; + if (**iter == ',') { + jsonSkipExpectedChar(iter, ','); + jsonScanWaste(iter); + continue; + } else { + break; + } + } while (1); + } + jsonScanChar(iter, ']'); + } + break; + case 'rots': + // storage + jsonScanChar(iter, '{'); + do { + storageEntry_t *storageEntry = malloc(sizeof(storageEntry_t)); + storageEntry->prev = entry.storage; + entry.storage = storageEntry; + jsonScanChar(iter, '"'); jsonSkipExpectedChar(iter, '0'); jsonSkipExpectedChar(iter, 'x'); + clear256(&storageEntry->key); while (**iter != '"') { - entry.balance[0] <<= 4; - entry.balance[0] |= entry.balance[1] >> 28; - entry.balance[1] <<= 4; - entry.balance[1] |= entry.balance[2] >> 28; - entry.balance[2] <<= 4; - entry.balance[2] |= hexString8ToUint8(**iter); + shiftl256(&storageEntry->key, 4, &storageEntry->key); + LOWER(LOWER(storageEntry->key)) |= hexString8ToUint8(**iter); (*iter)++; } jsonSkipExpectedChar(iter, '"'); - break; - case 'cnon': - // nonce - // TODO support decimal integer - jsonSkipExpectedChar(iter, '"'); + jsonScanChar(iter, ':'); + jsonScanChar(iter, '"'); jsonSkipExpectedChar(iter, '0'); jsonSkipExpectedChar(iter, 'x'); + clear256(&storageEntry->value); while (**iter != '"') { - entry.nonce <<= 4; - entry.nonce |= hexString8ToUint8(**iter); + shiftl256(&storageEntry->value, 4, &storageEntry->value); + LOWER(LOWER(storageEntry->value)) |= hexString8ToUint8(**iter); (*iter)++; } jsonSkipExpectedChar(iter, '"'); - break; - case 'aerc': - // creator - entry.creator = jsonReadAddressString(iter); - break; - case 'tini': - // init, initcode, initCode - { - const char *start = jsonScanStr(iter); - if (*(uint16_t *)start == 'x0') { - jsonSkipExpectedChar(&start, '0'); - jsonSkipExpectedChar(&start, 'x'); - entry.initCode.size = (*iter - start) / 2; - entry.initCode.content = calloc(entry.initCode.size, 1); - for (unsigned int i = 0; i < entry.initCode.size; i++) { - entry.initCode.content[i] = hexString16ToUint8(start); - start += 2; - } - } else { - size_t len = *iter - start - 1; - char *initcodePath = malloc(len + 1); - memcpy(initcodePath, start, len); - initcodePath[len] = '\0'; - entry.initCode = assemblePath(initcodePath); - free(initcodePath); - } - } - break; - case 'edoc': - // code - { - const char *start = jsonScanStr(iter); - if (*(uint16_t *)start == 'x0') { - jsonSkipExpectedChar(&start, '0'); - jsonSkipExpectedChar(&start, 'x'); - entry.code.size = (*iter - start) / 2; - entry.code.content = calloc(entry.code.size, 1); - for (unsigned int i = 0; i < entry.code.size; i++) { - entry.code.content[i] = hexString16ToUint8(start); - start += 2; - } - } else { - size_t len = *iter - start - 1; - entry.path = malloc(len + 1); - memcpy(entry.path, start, len); - entry.path[len] = '\0'; - entry.code = assemblePath(entry.path); - } - } - break; - case 'opmi': - // import - { - const char *start = jsonScanStr(iter); - size_t len = *iter - start - 1; - entry.importPath = malloc(len + 1); - memcpy(entry.importPath, start, len); - entry.importPath[len] = '\0'; - } - break; - case 'snoc': - if (headingLen == 9) { - // construct - const char *start = jsonScanStr(iter); - size_t len = *iter - start - 1; - entry.path = malloc(len + 1); - memcpy(entry.path, start, len); - entry.path[len] = '\0'; - entry.initCode = defaultConstructorForPath(entry.path); - } else { - // constructTest - entry.constructTest = jsonScanTestEntry(iter); - } - break; - case 'tset': - // tests - { - jsonSkipExpectedChar(iter, '['); + if (**iter == ',') { + jsonSkipExpectedChar(iter, ','); jsonScanWaste(iter); - if (**iter != ']') do { - testEntry_t *test = jsonScanTestEntry(iter); - test->prev = entry.tests; - entry.tests = test; - if (**iter == ',') { - jsonSkipExpectedChar(iter, ','); - jsonScanWaste(iter); - continue; - } else { - break; - } - } while (1); - jsonScanChar(iter, ']'); - } - break; - case 'rots': - // storage - jsonScanChar(iter, '{'); - do { - storageEntry_t *storageEntry = malloc(sizeof(storageEntry_t)); - storageEntry->prev = entry.storage; - entry.storage = storageEntry; - jsonScanChar(iter, '"'); - jsonSkipExpectedChar(iter, '0'); - jsonSkipExpectedChar(iter, 'x'); - clear256(&storageEntry->key); - while (**iter != '"') { - shiftl256(&storageEntry->key, 4, &storageEntry->key); - LOWER(LOWER(storageEntry->key)) |= hexString8ToUint8(**iter); - (*iter)++; - } - jsonSkipExpectedChar(iter, '"'); - jsonScanChar(iter, ':'); - jsonScanChar(iter, '"'); - jsonSkipExpectedChar(iter, '0'); - jsonSkipExpectedChar(iter, 'x'); - clear256(&storageEntry->value); - while (**iter != '"') { - shiftl256(&storageEntry->value, 4, &storageEntry->value); - LOWER(LOWER(storageEntry->value)) |= hexString8ToUint8(**iter); - (*iter)++; - } - jsonSkipExpectedChar(iter, '"'); - if (**iter == ',') { - jsonSkipExpectedChar(iter, ','); - jsonScanWaste(iter); - continue; - } else { - break; - } - } while (1); - jsonScanChar(iter, '}'); - break; - default: - { - const char *end = heading - 1; - jsonScanStr(&end); - size_t headingLen = end - heading - 1; - char *headingCopy = malloc(sizeof(headingLen + 1)); - memcpy(headingCopy, heading, headingLen); - headingCopy[headingLen] = '\0'; - fprintf(stderr, "Unexpected entry heading \"%s\" on line %" PRIu64 "\n", headingCopy, lineNumber); - free(headingCopy); + continue; + } else { + break; } - jsonSkipEntryValue(iter); - break; + } while (1); + jsonScanChar(iter, '}'); + break; + default: + { + const char *end = heading - 1; + jsonScanStr(&end); + size_t headingLen = end - heading - 1; + char *headingCopy = malloc(sizeof(headingLen + 1)); + memcpy(headingCopy, heading, headingLen); + headingCopy[headingLen] = '\0'; + fprintf(stderr, "Unexpected entry heading \"%s\" on line %" PRIu64 "\n", headingCopy, lineNumber); + free(headingCopy); + } + jsonSkipEntryValue(iter); + break; } jsonScanWaste(iter); if (**iter == ',') { @@ -1004,10 +1024,10 @@ void applyConfig(const char *json) { typedef char char_t; VECTOR(char, file); -#define file_append(file, str, strlen)\ - file_ensure(&file, file.num_chars + strlen);\ - memcpy(file.chars + file.num_chars, str, strlen);\ - file.num_chars += strlen +#define file_append(file, str, strlen) \ + file_ensure(&file, file.num_chars + strlen); \ + memcpy(file.chars + file.num_chars, str, strlen); \ + file.num_chars += strlen // FIXME these can use the wrong indentation #define NEWLINE_INDENT "\n " diff --git a/src/disassemble.c b/src/disassemble.c index 4a62d22..8e1d6c0 100644 --- a/src/disassemble.c +++ b/src/disassemble.c @@ -88,14 +88,14 @@ statement_t labelForPc(pc_t pc) { char *str = calloc(bufLen, 1); size_t strLen = (size_t) snprintf(str, bufLen, "%u:", pc); /* TODO label - for (uint8_t i = 0; i < strLen - 1; i++) { + for (uint8_t i = 0; i < strLen - 1; i++) { str[i] += 'a' - '0'; - } - */ + } + */ return (statement_t) { - strLen, - str, - bufLen, + strLen, + str, + bufLen, }; } @@ -165,7 +165,7 @@ int disassembleValid(const char **iter) { void disassembleFinalize() { for (size_t j = 0; j < jumpdests.num_pcs; j++) { - size_t jumpdest = jumpdests.pcs[j]; + size_t jumpdest = jumpdests.pcs[j]; for (size_t i = 0; i < stack.num_statements; i++) { // TODO scan for label } diff --git a/src/evm.c b/src/evm.c index 4c17b5d..3cf06c2 100644 --- a/src/evm.c +++ b/src/evm.c @@ -28,10 +28,10 @@ uint16_t fprintLog(FILE *file, const logChanges_t *log, int showLogIndex) { fputs("\",\"topics\":[", file); for (uint8_t i = log->topicCount; i-->0;) { fprintf(file, "\"0x%016" PRIx64 "%016" PRIx64 "%016" PRIx64 "%016" PRIx64 "\"", - UPPER(UPPER(log->topics[i])), - LOWER(UPPER(log->topics[i])), - UPPER(LOWER(log->topics[i])), - LOWER(LOWER(log->topics[i])) + UPPER(UPPER(log->topics[i])), + LOWER(UPPER(log->topics[i])), + UPPER(LOWER(log->topics[i])), + LOWER(LOWER(log->topics[i])) ); if (i) { fputc(',', file); @@ -95,10 +95,10 @@ uint16_t fprintLogDiff(FILE *file, const logChanges_t *log, const logChanges_t * } else { for (uint8_t i = log->topicCount; i-->0;) { fprintf(file, "\"0x%016" PRIx64 "%016" PRIx64 "%016" PRIx64 "%016" PRIx64 "\"", - UPPER(UPPER(log->topics[i])), - LOWER(UPPER(log->topics[i])), - UPPER(LOWER(log->topics[i])), - LOWER(LOWER(log->topics[i])) + UPPER(UPPER(log->topics[i])), + LOWER(UPPER(log->topics[i])), + UPPER(LOWER(log->topics[i])), + LOWER(LOWER(log->topics[i])) ); if (i) { fputc(',', file); @@ -143,7 +143,7 @@ static inline void DataCopy(data_t *dst, const data_t *src) { static inline void BalanceAdd(val_t to, val_t amount) { uint32_t carry = 0; uint8_t i = 3; - while (i --> 0) { + while (i--> 0) { uint32_t result = carry + to[i] + amount[i]; if (result < amount[i]) { carry = 1; @@ -158,7 +158,7 @@ static inline bool BalanceSub(val_t from, val_t amount) { uint32_t borrow = 0; uint8_t i = 3; val_t result; - while (i --> 0) { + while (i--> 0) { result[i] = from[i] - amount[i] - borrow; if (result[i] > from[i]) { borrow = 1; @@ -263,7 +263,7 @@ static inline void dumpMemory(memory_t *memory) { if (memory->num_uint8s % 32 == 0) { return; } - for (uint32_t i = 32 - memory->num_uint8s % 32; i --> 0;) { + for (uint32_t i = 32 - memory->num_uint8s % 32; i--> 0;) { fputs("00", stderr); } fputc('\n', stderr); @@ -333,7 +333,9 @@ uint16_t depthOf(context_t *context) { } void fRepeat(FILE *file, const char *str, uint16_t times) { - if (!times) return; + if (!times) { + return; + } fputs(str, file); fRepeat(file, str, times - 1); } @@ -374,7 +376,9 @@ static account_t *getAccount(const address_t address) { } } account_t *result = accounts; - while (result < emptyAccount && !AddressEqual(&result->address, &address)) result++; + while (result < emptyAccount && !AddressEqual(&result->address, &address)) { + result++; + } if (result == emptyAccount) { emptyAccount++; AddressCopy(result->address, address); @@ -389,7 +393,7 @@ static account_t *getAccount(const address_t address) { void evmInit() { callstack.next = callstack.bottom; - while (emptyAccount --> accounts) { + while (emptyAccount--> accounts) { storage_t *storage = emptyAccount->storage; while (storage != NULL) { void *toFree = storage; @@ -629,63 +633,63 @@ static result_t doSupportedPrecompile(precompile_t precompile, context_t *callCo result.returnData.size = 0; \ return result #define APPLY_GAS_COST(required) \ - gasCost = required; \ - if (callContext->gas < gasCost) { \ - OUT_OF_GAS; \ - } \ - callContext->gas -= gasCost + gasCost = required; \ + if (callContext->gas < gasCost) { \ + OUT_OF_GAS; \ + } \ + callContext->gas -= gasCost switch (precompile) { - case HOLE: - result.returnData.size = 0; - return result; - case ECRECOVER: - { - APPLY_GAS_COST(3000); - uint8_t input[128]; - memset(input, 0, 128); - size_t copyLen = callContext->callData.size < 128 ? callContext->callData.size : 128; - memcpy(input, callContext->callData.content, copyLen); - // v is at bytes [32..63]: upper 31 bytes must be 0, last byte must be 27 or 28 - for (int i = 32; i < 63; i++) { - if (input[i] != 0) { - result.returnData.size = 0; - return result; - } - } - int v = input[63]; - if (v != 27 && v != 28) { - result.returnData.size = 0; - return result; - } - int recid = v - 27; - secp256k1_ecdsa_recoverable_signature sig; - if (!secp256k1_ecdsa_recoverable_signature_parse_compact(secp256k1_context_static, &sig, input + 64, recid)) { - result.returnData.size = 0; - return result; - } - secp256k1_pubkey pubkey; - if (!secp256k1_ecdsa_recover(secp256k1_context_static, &pubkey, &sig, input)) { - result.returnData.size = 0; - return result; - } - uint8_t pubkeyBytes[65]; - size_t pubkeyLen = 65; - secp256k1_ec_pubkey_serialize(secp256k1_context_static, pubkeyBytes, &pubkeyLen, &pubkey, SECP256K1_EC_UNCOMPRESSED); - result.returnData.size = 32; - result.returnData.content = malloc(32); - keccak_256(result.returnData.content, 32, pubkeyBytes + 1, 64); - memset(result.returnData.content, 0, 12); + case HOLE: + result.returnData.size = 0; + return result; + case ECRECOVER: + { + APPLY_GAS_COST(3000); + uint8_t input[128]; + memset(input, 0, 128); + size_t copyLen = callContext->callData.size < 128 ? callContext->callData.size : 128; + memcpy(input, callContext->callData.content, copyLen); + // v is at bytes [32..63]: upper 31 bytes must be 0, last byte must be 27 or 28 + for (int i = 32; i < 63; i++) { + if (input[i] != 0) { + result.returnData.size = 0; return result; } - case IDENTITY: - APPLY_GAS_COST(15 + 3 * ((callContext->callData.size + 31) / 32)); - result.returnData.size = callContext->callData.size; - result.returnData.content = malloc(callContext->callData.size); - memcpy(result.returnData.content, callContext->callData.content, callContext->callData.size); + } + int v = input[63]; + if (v != 27 && v != 28) { + result.returnData.size = 0; return result; - default: - assert(0); + } + int recid = v - 27; + secp256k1_ecdsa_recoverable_signature sig; + if (!secp256k1_ecdsa_recoverable_signature_parse_compact(secp256k1_context_static, &sig, input + 64, recid)) { + result.returnData.size = 0; + return result; + } + secp256k1_pubkey pubkey; + if (!secp256k1_ecdsa_recover(secp256k1_context_static, &pubkey, &sig, input)) { + result.returnData.size = 0; + return result; + } + uint8_t pubkeyBytes[65]; + size_t pubkeyLen = 65; + secp256k1_ec_pubkey_serialize(secp256k1_context_static, pubkeyBytes, &pubkeyLen, &pubkey, SECP256K1_EC_UNCOMPRESSED); + result.returnData.size = 32; + result.returnData.content = malloc(32); + keccak_256(result.returnData.content, 32, pubkeyBytes + 1, 64); + memset(result.returnData.content, 0, 12); + return result; + } + case IDENTITY: + APPLY_GAS_COST(15 + 3 * ((callContext->callData.size + 31) / 32)); + result.returnData.size = callContext->callData.size; + result.returnData.content = malloc(callContext->callData.size); + memcpy(result.returnData.content, callContext->callData.content, callContext->callData.size); + return result; + default: + assert(0); } #undef APPLY_GAS_COST #undef OUT_OF_GAS @@ -763,12 +767,12 @@ static result_t doCall(context_t *callContext) { fprintf(stderr, "op %s\n", opString[op]); } #define FAIL_INVALID \ - callContext->gas = 0; \ - result.returnData.size = 0; \ - return result + callContext->gas = 0; \ + result.returnData.size = 0; \ + return result #define OUT_OF_GAS \ - fprintf(stderr, "Out of gas at pc %" PRIu64 " op %s\n", pc - 1, opString[op]);\ - FAIL_INVALID + fprintf(stderr, "Out of gas at pc %" PRIu64 " op %s\n", pc - 1, opString[op]); \ + FAIL_INVALID if ( (callContext->top < callContext->bottom + argCount[op]) || (op >= DUP1 && op <= DUP16 && callContext->top - (op - PUSH32) < callContext->bottom) @@ -785,7 +789,7 @@ static result_t doCall(context_t *callContext) { // CALL is permitted without CALLVALUE break; } - // intentional fallthrough + // intentional fallthrough case LOG0: case LOG1: case LOG2: @@ -813,936 +817,938 @@ static result_t doCall(context_t *callContext) { FAIL_INVALID; } switch (op) { - case PUSH0: - case PUSH1: - case PUSH2: - case PUSH3: - case PUSH4: - case PUSH5: - case PUSH6: - case PUSH7: - case PUSH8: - case PUSH9: - case PUSH10: - case PUSH11: - case PUSH12: - case PUSH13: - case PUSH14: - case PUSH15: - case PUSH16: - case PUSH17: - case PUSH18: - case PUSH19: - case PUSH20: - case PUSH21: - case PUSH22: - case PUSH23: - case PUSH24: - case PUSH25: - case PUSH26: - case PUSH27: - case PUSH28: - case PUSH29: - case PUSH30: - case PUSH31: - case PUSH32: - ; - uint8_t pushSize = op - PUSH0; - bzero(buffer, 32 - pushSize); - memcpy(buffer + 32 - pushSize, callContext->code.content + pc, pushSize); - readu256BE(buffer, callContext->top - 1); - pc += pushSize; - break; - case DUP1: - case DUP2: - case DUP3: - case DUP4: - case DUP5: - case DUP6: - case DUP7: - case DUP8: - case DUP9: - case DUP10: - case DUP11: - case DUP12: - case DUP13: - case DUP14: - case DUP15: - case DUP16: - copy256(callContext->top - 1, callContext->top - (op - PUSH31)); - break; - case SWAP1: - case SWAP2: - case SWAP3: - case SWAP4: - case SWAP5: - case SWAP6: - case SWAP7: - case SWAP8: - case SWAP9: - case SWAP10: - case SWAP11: - case SWAP12: - case SWAP13: - case SWAP14: - case SWAP15: - case SWAP16: - memcpy(buffer, callContext->top - 1, 32); - memcpy(callContext->top - 1, callContext->top - (op - DUP15), 32); - memcpy(callContext->top - (op - DUP15), buffer, 32); - break; - case SHA3: - { - uint64_t src = LOWER(LOWER_P(callContext->top)); - uint64_t size = LOWER(LOWER_P(callContext->top - 1)); - if ( - UPPER(UPPER_P(callContext->top)) || LOWER(UPPER_P(callContext->top)) || UPPER(LOWER_P(callContext->top)) - || UPPER(UPPER_P(callContext->top - 1)) || LOWER(UPPER_P(callContext->top - 1)) || UPPER(LOWER_P(callContext->top - 1)) - || size > src + size - || !ensureMemory(callContext, src + size) + case PUSH0: + case PUSH1: + case PUSH2: + case PUSH3: + case PUSH4: + case PUSH5: + case PUSH6: + case PUSH7: + case PUSH8: + case PUSH9: + case PUSH10: + case PUSH11: + case PUSH12: + case PUSH13: + case PUSH14: + case PUSH15: + case PUSH16: + case PUSH17: + case PUSH18: + case PUSH19: + case PUSH20: + case PUSH21: + case PUSH22: + case PUSH23: + case PUSH24: + case PUSH25: + case PUSH26: + case PUSH27: + case PUSH28: + case PUSH29: + case PUSH30: + case PUSH31: + case PUSH32: + ; + uint8_t pushSize = op - PUSH0; + bzero(buffer, 32 - pushSize); + memcpy(buffer + 32 - pushSize, callContext->code.content + pc, pushSize); + readu256BE(buffer, callContext->top - 1); + pc += pushSize; + break; + case DUP1: + case DUP2: + case DUP3: + case DUP4: + case DUP5: + case DUP6: + case DUP7: + case DUP8: + case DUP9: + case DUP10: + case DUP11: + case DUP12: + case DUP13: + case DUP14: + case DUP15: + case DUP16: + copy256(callContext->top - 1, callContext->top - (op - PUSH31)); + break; + case SWAP1: + case SWAP2: + case SWAP3: + case SWAP4: + case SWAP5: + case SWAP6: + case SWAP7: + case SWAP8: + case SWAP9: + case SWAP10: + case SWAP11: + case SWAP12: + case SWAP13: + case SWAP14: + case SWAP15: + case SWAP16: + memcpy(buffer, callContext->top - 1, 32); + memcpy(callContext->top - 1, callContext->top - (op - DUP15), 32); + memcpy(callContext->top - (op - DUP15), buffer, 32); + break; + case SHA3: + { + uint64_t src = LOWER(LOWER_P(callContext->top)); + uint64_t size = LOWER(LOWER_P(callContext->top - 1)); + if ( + UPPER(UPPER_P(callContext->top)) || LOWER(UPPER_P(callContext->top)) || UPPER(LOWER_P(callContext->top)) + || UPPER(UPPER_P(callContext->top - 1)) || LOWER(UPPER_P(callContext->top - 1)) || UPPER(LOWER_P(callContext->top - 1)) + || size > src + size + || !ensureMemory(callContext, src + size) ) { - OUT_OF_GAS; - } - uint64_t gasCost = G_KECCAK_WORD * ((size + 31) / 32); - if (gasCost > callContext->gas) { - OUT_OF_GAS; - } - callContext->gas -= gasCost; - uint8_t result[32]; - keccak_256(result, 32, callContext->memory.uint8s + src, size); - readu256BE(result, callContext->top - 1); - } - break; - case ADDRESS: - AddressToUint256(callContext->top - 1, &callContext->account->address); - break; - case CALLER: - AddressToUint256(callContext->top - 1, &callContext->caller); - break; - case ORIGIN: - AddressToUint256(callContext->top - 1, &callstack.bottom[0].caller); - break; - case POP: - // intentional fallthrough - case JUMPDEST: - break; - case ADD: - add256(callContext->top, callContext->top - 1, callContext->top - 1); - break; - case SUB: - minus256(callContext->top, callContext->top - 1, callContext->top - 1); - break; - case MUL: - mul256(callContext->top, callContext->top - 1, callContext->top - 1); - break; - case DIV: - if (!zero256(callContext->top - 1)) - divmod256(callContext->top, callContext->top - 1, callContext->top - 1, callContext->top + 1); - break; - case SDIV: - if (!zero256(callContext->top - 1)) { - bool negative = false; - uint256_t zero; - clear256(&zero); - if (UPPER(UPPER_P(callContext->top)) >= 0x8000000000000000) { - negative = !negative; - minus256(&zero, callContext->top, callContext->top); - } - if (UPPER(UPPER_P(callContext->top - 1)) >= 0x8000000000000000) { - negative = !negative; - minus256(&zero, callContext->top - 1, callContext->top - 1); - } - divmod256(callContext->top, callContext->top - 1, callContext->top - 1, callContext->top + 1); - if (negative) { - minus256(&zero, callContext->top - 1, callContext->top - 1); - } - } - break; - case MOD: - if (!zero256(callContext->top - 1)) - divmod256(callContext->top, callContext->top - 1, callContext->top + 1, callContext->top - 1); - break; - case SMOD: - if (!zero256(callContext->top - 1)) { - bool negative = false; - uint256_t zero; - clear256(&zero); - if (UPPER(UPPER_P(callContext->top)) >= 0x8000000000000000) { - negative = true; - minus256(&zero, callContext->top, callContext->top); - } - if (UPPER(UPPER_P(callContext->top - 1)) >= 0x8000000000000000) { - minus256(&zero, callContext->top - 1, callContext->top - 1); - } - divmod256(callContext->top, callContext->top - 1, callContext->top + 1, callContext->top - 1); - if (negative) { - minus256(&zero, callContext->top - 1, callContext->top - 1); - } - } - break; - case XOR: - xor256(callContext->top, callContext->top - 1, callContext->top - 1); - break; - case OR: - or256(callContext->top, callContext->top - 1, callContext->top - 1); - break; - case AND: - and256(callContext->top, callContext->top - 1, callContext->top - 1); - break; - case NOT: - not256(callContext->top - 1, callContext->top - 1); - break; - case BYTE: - { - uint64_t index = LOWER(LOWER_P(callContext->top)); - uint256_t *target = callContext->top - 1; - if (UPPER(UPPER_P(callContext->top)) || LOWER(UPPER_P(callContext->top)) || UPPER(LOWER_P(callContext->top)) || index >= 32) { - clear256(target); - } else { - shiftr256(target, 248 - index * 8, target); - UPPER(UPPER_P(target)) = 0; - LOWER(UPPER_P(target)) = 0; - UPPER(LOWER_P(target)) = 0; - LOWER(LOWER_P(target)) &= 0xff; - } + OUT_OF_GAS; + } + uint64_t gasCost = G_KECCAK_WORD * ((size + 31) / 32); + if (gasCost > callContext->gas) { + OUT_OF_GAS; + } + callContext->gas -= gasCost; + uint8_t result[32]; + keccak_256(result, 32, callContext->memory.uint8s + src, size); + readu256BE(result, callContext->top - 1); + } + break; + case ADDRESS: + AddressToUint256(callContext->top - 1, &callContext->account->address); + break; + case CALLER: + AddressToUint256(callContext->top - 1, &callContext->caller); + break; + case ORIGIN: + AddressToUint256(callContext->top - 1, &callstack.bottom[0].caller); + break; + case POP: + // intentional fallthrough + case JUMPDEST: + break; + case ADD: + add256(callContext->top, callContext->top - 1, callContext->top - 1); + break; + case SUB: + minus256(callContext->top, callContext->top - 1, callContext->top - 1); + break; + case MUL: + mul256(callContext->top, callContext->top - 1, callContext->top - 1); + break; + case DIV: + if (!zero256(callContext->top - 1)) { + divmod256(callContext->top, callContext->top - 1, callContext->top - 1, callContext->top + 1); + } + break; + case SDIV: + if (!zero256(callContext->top - 1)) { + bool negative = false; + uint256_t zero; + clear256(&zero); + if (UPPER(UPPER_P(callContext->top)) >= 0x8000000000000000) { + negative = !negative; + minus256(&zero, callContext->top, callContext->top); } - break; - case SHL: - { - uint256_t *shiftAmount = callContext->top; - if (UPPER(UPPER_P(shiftAmount)) || LOWER(UPPER_P(shiftAmount)) || UPPER(LOWER_P(shiftAmount)) || LOWER(LOWER_P(shiftAmount)) > 256) { - clear256(callContext->top - 1); - } else { - shiftl256(callContext->top - 1, LOWER(LOWER_P(shiftAmount)), callContext->top - 1); - } + if (UPPER(UPPER_P(callContext->top - 1)) >= 0x8000000000000000) { + negative = !negative; + minus256(&zero, callContext->top - 1, callContext->top - 1); } - break; - case SHR: - { - uint256_t *shiftAmount = callContext->top; - if (UPPER(UPPER_P(shiftAmount)) || LOWER(UPPER_P(shiftAmount)) || UPPER(LOWER_P(shiftAmount)) || LOWER(LOWER_P(shiftAmount)) > 256) { - clear256(callContext->top - 1); - } else { - shiftr256(callContext->top - 1, LOWER(LOWER_P(shiftAmount)), callContext->top - 1); - } + divmod256(callContext->top, callContext->top - 1, callContext->top - 1, callContext->top + 1); + if (negative) { + minus256(&zero, callContext->top - 1, callContext->top - 1); } - break; - case SAR: - { - uint256_t *shiftAmount = callContext->top; - if (UPPER(UPPER_P(shiftAmount)) || LOWER(UPPER_P(shiftAmount)) || UPPER(LOWER_P(shiftAmount)) || LOWER(LOWER_P(shiftAmount)) > 256) { - if (UPPER(UPPER_P(callContext->top - 1)) < 0x8000000000000000) { - clear256(callContext->top - 1); - } else { - UPPER(UPPER_P(callContext->top - 1)) = 0xffffffffffffffff; - LOWER(UPPER_P(callContext->top - 1)) = 0xffffffffffffffff; - UPPER(LOWER_P(callContext->top - 1)) = 0xffffffffffffffff; - LOWER(LOWER_P(callContext->top - 1)) = 0xffffffffffffffff; - } - } else { - shiftar256(callContext->top - 1, LOWER(LOWER_P(shiftAmount)), callContext->top - 1); - } + } + break; + case MOD: + if (!zero256(callContext->top - 1)) { + divmod256(callContext->top, callContext->top - 1, callContext->top + 1, callContext->top - 1); + } + break; + case SMOD: + if (!zero256(callContext->top - 1)) { + bool negative = false; + uint256_t zero; + clear256(&zero); + if (UPPER(UPPER_P(callContext->top)) >= 0x8000000000000000) { + negative = true; + minus256(&zero, callContext->top, callContext->top); } - break; - case CLZ: - { - uint64_t zeros = clz256(callContext->top - 1); - UPPER(UPPER_P(callContext->top - 1)) = 0; - LOWER(UPPER_P(callContext->top - 1)) = 0; - UPPER(LOWER_P(callContext->top - 1)) = 0; - LOWER(LOWER_P(callContext->top - 1)) = zeros; + if (UPPER(UPPER_P(callContext->top - 1)) >= 0x8000000000000000) { + minus256(&zero, callContext->top - 1, callContext->top - 1); } - break; - case ADDMOD: - if (zero256(callContext->top - 1)) { - clear256(callContext->top - 1); - } else { - addmod256(callContext->top + 1, callContext->top, callContext->top - 1, callContext->top - 1); + divmod256(callContext->top, callContext->top - 1, callContext->top + 1, callContext->top - 1); + if (negative) { + minus256(&zero, callContext->top - 1, callContext->top - 1); } - break; - case MULMOD: - if (zero256(callContext->top - 1)) { + } + break; + case XOR: + xor256(callContext->top, callContext->top - 1, callContext->top - 1); + break; + case OR: + or256(callContext->top, callContext->top - 1, callContext->top - 1); + break; + case AND: + and256(callContext->top, callContext->top - 1, callContext->top - 1); + break; + case NOT: + not256(callContext->top - 1, callContext->top - 1); + break; + case BYTE: + { + uint64_t index = LOWER(LOWER_P(callContext->top)); + uint256_t *target = callContext->top - 1; + if (UPPER(UPPER_P(callContext->top)) || LOWER(UPPER_P(callContext->top)) || UPPER(LOWER_P(callContext->top)) || index >= 32) { + clear256(target); + } else { + shiftr256(target, 248 - index * 8, target); + UPPER(UPPER_P(target)) = 0; + LOWER(UPPER_P(target)) = 0; + UPPER(LOWER_P(target)) = 0; + LOWER(LOWER_P(target)) &= 0xff; + } + } + break; + case SHL: + { + uint256_t *shiftAmount = callContext->top; + if (UPPER(UPPER_P(shiftAmount)) || LOWER(UPPER_P(shiftAmount)) || UPPER(LOWER_P(shiftAmount)) || LOWER(LOWER_P(shiftAmount)) > 256) { + clear256(callContext->top - 1); + } else { + shiftl256(callContext->top - 1, LOWER(LOWER_P(shiftAmount)), callContext->top - 1); + } + } + break; + case SHR: + { + uint256_t *shiftAmount = callContext->top; + if (UPPER(UPPER_P(shiftAmount)) || LOWER(UPPER_P(shiftAmount)) || UPPER(LOWER_P(shiftAmount)) || LOWER(LOWER_P(shiftAmount)) > 256) { + clear256(callContext->top - 1); + } else { + shiftr256(callContext->top - 1, LOWER(LOWER_P(shiftAmount)), callContext->top - 1); + } + } + break; + case SAR: + { + uint256_t *shiftAmount = callContext->top; + if (UPPER(UPPER_P(shiftAmount)) || LOWER(UPPER_P(shiftAmount)) || UPPER(LOWER_P(shiftAmount)) || LOWER(LOWER_P(shiftAmount)) > 256) { + if (UPPER(UPPER_P(callContext->top - 1)) < 0x8000000000000000) { clear256(callContext->top - 1); } else { - mulmod256(callContext->top + 1, callContext->top, callContext->top - 1, callContext->top - 1); + UPPER(UPPER_P(callContext->top - 1)) = 0xffffffffffffffff; + LOWER(UPPER_P(callContext->top - 1)) = 0xffffffffffffffff; + UPPER(LOWER_P(callContext->top - 1)) = 0xffffffffffffffff; + LOWER(LOWER_P(callContext->top - 1)) = 0xffffffffffffffff; } + } else { + shiftar256(callContext->top - 1, LOWER(LOWER_P(shiftAmount)), callContext->top - 1); + } + } + break; + case CLZ: + { + uint64_t zeros = clz256(callContext->top - 1); + UPPER(UPPER_P(callContext->top - 1)) = 0; + LOWER(UPPER_P(callContext->top - 1)) = 0; + UPPER(LOWER_P(callContext->top - 1)) = 0; + LOWER(LOWER_P(callContext->top - 1)) = zeros; + } + break; + case ADDMOD: + if (zero256(callContext->top - 1)) { + clear256(callContext->top - 1); + } else { + addmod256(callContext->top + 1, callContext->top, callContext->top - 1, callContext->top - 1); + } + break; + case MULMOD: + if (zero256(callContext->top - 1)) { + clear256(callContext->top - 1); + } else { + mulmod256(callContext->top + 1, callContext->top, callContext->top - 1, callContext->top - 1); + } + break; + case EXP: + { + uint32_t bitLen = bits256(callContext->top - 1); + uint32_t bytes = (bitLen + 7) / 8; + uint64_t gasCost = bytes * G_EXPBYTE; + if (gasCost > callContext->gas) { + OUT_OF_GAS; + } + callContext->gas -= gasCost; + exp256(callContext->top, callContext->top - 1, callContext->top - 1); + } + break; + case SIGNEXTEND: + { + if (UPPER(UPPER_P(callContext->top)) || LOWER(UPPER_P(callContext->top)) || UPPER(LOWER_P(callContext->top)) || LOWER(LOWER_P(callContext->top)) > 30) { break; - case EXP: - { - uint32_t bitLen = bits256(callContext->top - 1); - uint32_t bytes = (bitLen + 7) / 8; - uint64_t gasCost = bytes * G_EXPBYTE; - if (gasCost > callContext->gas) { - OUT_OF_GAS; - } - callContext->gas -= gasCost; - exp256(callContext->top, callContext->top - 1, callContext->top - 1); - } + } + uint8_t signBit = 8 * LOWER(LOWER_P(callContext->top)) + 8; + signextend256(callContext->top - 1, signBit, callContext->top - 1); + } + break; + case LT: + LOWER(LOWER_P(callContext->top - 1)) = gt256(callContext->top - 1, callContext->top); + bzero(callContext->top - 1, 24); + break; + case GT: + LOWER(LOWER_P(callContext->top - 1)) = gt256(callContext->top, callContext->top - 1); + bzero(callContext->top - 1, 24); + break; + case SLT: + LOWER(LOWER_P(callContext->top - 1)) = sgt256(callContext->top - 1, callContext->top); + bzero(callContext->top - 1, 24); + break; + case SGT: + LOWER(LOWER_P(callContext->top - 1)) = sgt256(callContext->top, callContext->top - 1); + bzero(callContext->top - 1, 24); + break; + case EQ: + LOWER(LOWER_P(callContext->top - 1)) = equal256(callContext->top, callContext->top - 1); + bzero(callContext->top - 1, 24); + break; + case ISZERO: + LOWER(LOWER_P(callContext->top - 1)) = zero256(callContext->top - 1); + bzero(callContext->top - 1, 24); + break; + case PC: + bzero(callContext->top - 1, 24); + LOWER(LOWER_P(callContext->top - 1)) = pc - 1; + break; + case JUMPI: + if (zero256(callContext->top)) { break; - case SIGNEXTEND: - { - if (UPPER(UPPER_P(callContext->top)) || LOWER(UPPER_P(callContext->top)) || UPPER(LOWER_P(callContext->top)) || LOWER(LOWER_P(callContext->top)) > 30) { + } + // intentional fallthorugh + case JUMP: + { + uint256_t *dst = callContext->top + (op - JUMP); + if (UPPER(UPPER_P(dst)) || UPPER(LOWER_P(dst)) || LOWER(UPPER_P(dst))) { + fprintf(stderr, "%s destination has upper bits set\n", opString[op]); + FAIL_INVALID; + } + pc = LOWER(LOWER_P(dst)); + } + if (pc >= callContext->code.size) { + fprintf(stderr, "%s out of bounds %" PRIu64 " >= %lu\n", opString[op], pc, callContext->code.size); + FAIL_INVALID; + } + if (callContext->code.content[pc] != JUMPDEST) { + fprintf(stderr, "%s to invalid destination %" PRIu64 " (%s)\n", opString[op], pc, opString[callContext->code.content[pc]]); + FAIL_INVALID; + } + // Verify the JUMPDEST byte is a real instruction, not PUSH data. + // Backward scan: PUSH_n covers at most n <= 32 data bytes ahead. + // If no candidate found, skip the more expensive forward scan. + { + uint64_t lookback = pc < 32 ? pc : 32; + bool needForwardScan = false; + for (uint64_t i = 1; i <= lookback; i++) { + uint8_t cb = callContext->code.content[pc - i]; + if (cb >= PUSH1 && cb <= PUSH32 && cb - PUSH0 >= i) { + needForwardScan = true; break; } - uint8_t signBit = 8 * LOWER(LOWER_P(callContext->top)) + 8; - signextend256(callContext->top - 1, signBit, callContext->top - 1); - } - break; - case LT: - LOWER(LOWER_P(callContext->top - 1)) = gt256(callContext->top - 1, callContext->top); - bzero(callContext->top - 1, 24); - break; - case GT: - LOWER(LOWER_P(callContext->top - 1)) = gt256(callContext->top, callContext->top - 1); - bzero(callContext->top - 1, 24); - break; - case SLT: - LOWER(LOWER_P(callContext->top - 1)) = sgt256(callContext->top - 1, callContext->top); - bzero(callContext->top - 1, 24); - break; - case SGT: - LOWER(LOWER_P(callContext->top - 1)) = sgt256(callContext->top, callContext->top - 1); - bzero(callContext->top - 1, 24); - break; - case EQ: - LOWER(LOWER_P(callContext->top - 1)) = equal256(callContext->top, callContext->top - 1); - bzero(callContext->top - 1, 24); - break; - case ISZERO: - LOWER(LOWER_P(callContext->top - 1)) = zero256(callContext->top - 1); - bzero(callContext->top - 1, 24); - break; - case PC: - bzero(callContext->top - 1, 24); - LOWER(LOWER_P(callContext->top - 1)) = pc - 1; - break; - case JUMPI: - if (zero256(callContext->top)) { - break; - } - // intentional fallthorugh - case JUMP: - { - uint256_t *dst = callContext->top + (op - JUMP); - if (UPPER(UPPER_P(dst)) || UPPER(LOWER_P(dst)) || LOWER(UPPER_P(dst))) { - fprintf(stderr, "%s destination has upper bits set\n", opString[op]); - FAIL_INVALID; - } - pc = LOWER(LOWER_P(dst)); - } - if (pc >= callContext->code.size) { - fprintf(stderr, "%s out of bounds %" PRIu64 " >= %lu\n", opString[op], pc, callContext->code.size); - FAIL_INVALID; } - if (callContext->code.content[pc] != JUMPDEST) { - fprintf(stderr, "%s to invalid destination %" PRIu64 " (%s)\n", opString[op], pc, opString[callContext->code.content[pc]]); - FAIL_INVALID; - } - // Verify the JUMPDEST byte is a real instruction, not PUSH data. - // Backward scan: PUSH_n covers at most n <= 32 data bytes ahead. - // If no candidate found, skip the more expensive forward scan. - { - uint64_t lookback = pc < 32 ? pc : 32; - bool needForwardScan = false; - for (uint64_t i = 1; i <= lookback; i++) { - uint8_t cb = callContext->code.content[pc - i]; - if (cb >= PUSH1 && cb <= PUSH32 && cb - PUSH0 >= i) { - needForwardScan = true; - break; - } - } - if (needForwardScan) { - uint64_t fpc = 0; - while (fpc < pc) { - uint8_t cb = callContext->code.content[fpc]; - if (cb >= PUSH1 && cb <= PUSH32) { - uint8_t n = cb - PUSH0; - if (fpc + n >= pc) { - fprintf(stderr, "%s to JUMPDEST inside PUSH%u data at %" PRIu64 "\n", opString[op], n, pc); - FAIL_INVALID; - } - fpc += 1 + n; - } else { - fpc++; + if (needForwardScan) { + uint64_t fpc = 0; + while (fpc < pc) { + uint8_t cb = callContext->code.content[fpc]; + if (cb >= PUSH1 && cb <= PUSH32) { + uint8_t n = cb - PUSH0; + if (fpc + n >= pc) { + fprintf(stderr, "%s to JUMPDEST inside PUSH%u data at %" PRIu64 "\n", opString[op], n, pc); + FAIL_INVALID; } + fpc += 1 + n; + } else { + fpc++; } } } - break; - default: - fprintf(stderr, "Unsupported opcode %u (%s)\n", op, opString[op]); - FAIL_INVALID; - case STOP: - LOWER(LOWER(result.status)) = 1; - result.returnData.size = 0; - return result; - case GAS: - bzero(callContext->top - 1, 24); - LOWER(LOWER_P(callContext->top - 1)) = callContext->gas; - break; - case RETURNDATASIZE: - bzero(callContext->top - 1, 24); - LOWER(LOWER_P(callContext->top - 1)) = callContext->returnData.size; - break; - case CALLDATASIZE: - bzero(callContext->top - 1, 24); - LOWER(LOWER_P(callContext->top - 1)) = callContext->callData.size; - break; - case EXTCODESIZE: - { - account_t *account = warmAccount(callContext, AddressFromUint256(callContext->top - 1)); - if (account == NULL) { - OUT_OF_GAS; - } - bzero(callContext->top - 1, 24); - LOWER(LOWER_P(callContext->top - 1)) = account->code.size; - } - break; - case CODESIZE: - bzero(callContext->top - 1, 24); - LOWER(LOWER_P(callContext->top - 1)) = callContext->code.size; - break; - case MSIZE: + } + break; + default: + fprintf(stderr, "Unsupported opcode %u (%s)\n", op, opString[op]); + FAIL_INVALID; + case STOP: + LOWER(LOWER(result.status)) = 1; + result.returnData.size = 0; + return result; + case GAS: + bzero(callContext->top - 1, 24); + LOWER(LOWER_P(callContext->top - 1)) = callContext->gas; + break; + case RETURNDATASIZE: + bzero(callContext->top - 1, 24); + LOWER(LOWER_P(callContext->top - 1)) = callContext->returnData.size; + break; + case CALLDATASIZE: + bzero(callContext->top - 1, 24); + LOWER(LOWER_P(callContext->top - 1)) = callContext->callData.size; + break; + case EXTCODESIZE: + { + account_t *account = warmAccount(callContext, AddressFromUint256(callContext->top - 1)); + if (account == NULL) { + OUT_OF_GAS; + } + bzero(callContext->top - 1, 24); + LOWER(LOWER_P(callContext->top - 1)) = account->code.size; + } + break; + case CODESIZE: + bzero(callContext->top - 1, 24); + LOWER(LOWER_P(callContext->top - 1)) = callContext->code.size; + break; + case MSIZE: + clear256(callContext->top - 1); + uint64_t scratch = callContext->memory.num_uint8s; + if (scratch % 32) { + scratch += 32 - scratch % 32; + } + LOWER(LOWER_P(callContext->top - 1)) = scratch; + break; + case MSTORE: + { + if (!ensureMemory(callContext, 32 + LOWER(LOWER_P(callContext->top + 1)))) { + OUT_OF_GAS; + } + uint8_t *loc = (callContext->memory.uint8s + LOWER(LOWER_P(callContext->top + 1))); + dumpu256BE(callContext->top, loc); + } + break; + case MSTORE8: + { + if (!ensureMemory(callContext, 1 + LOWER(LOWER_P(callContext->top + 1)))) { + OUT_OF_GAS; + } + uint8_t *loc = (callContext->memory.uint8s + LOWER(LOWER_P(callContext->top + 1))); + *loc = LOWER(LOWER_P(callContext->top)); + } + break; + case MLOAD: + if (UPPER(LOWER_P(callContext->top - 1)) || LOWER(UPPER_P(callContext->top - 1)) || UPPER(UPPER_P(callContext->top - 1))) { + OUT_OF_GAS; + } + if (!ensureMemory(callContext, 32 + LOWER(LOWER_P(callContext->top - 1)))) { + OUT_OF_GAS; + } + readu256BE(callContext->memory.uint8s + LOWER(LOWER_P(callContext->top - 1)), callContext->top - 1); + break; + case CALLDATALOAD: + if (UPPER(LOWER_P(callContext->top - 1)) || LOWER(UPPER_P(callContext->top - 1)) || UPPER(UPPER_P(callContext->top - 1)) || LOWER(LOWER_P(callContext->top - 1)) >= callContext->callData.size) { clear256(callContext->top - 1); - uint64_t scratch = callContext->memory.num_uint8s; - if (scratch % 32) { - scratch += 32 - scratch % 32; - } - LOWER(LOWER_P(callContext->top - 1)) = scratch; - break; - case MSTORE: - { - if (!ensureMemory(callContext, 32 + LOWER(LOWER_P(callContext->top + 1)))) { - OUT_OF_GAS; - } - uint8_t *loc = (callContext->memory.uint8s + LOWER(LOWER_P(callContext->top + 1))); - dumpu256BE(callContext->top, loc); + } else if (LOWER(LOWER_P(callContext->top - 1)) + 32 > callContext->callData.size) { + uint8_t partial[32]; + bzero(partial, 32); + memcpy(partial, callContext->callData.content + LOWER(LOWER_P(callContext->top - 1)), callContext->callData.size - LOWER(LOWER_P(callContext->top - 1))); + readu256BE(partial, callContext->top - 1); + } else { + readu256BE(callContext->callData.content + LOWER(LOWER_P(callContext->top - 1)), callContext->top - 1); + } + break; + case LOG0: + case LOG1: + case LOG2: + case LOG3: + case LOG4: + { + uint8_t topicCount = op - LOG0; + uint64_t src = LOWER(LOWER_P(callContext->top + topicCount + 1)); + uint64_t size = LOWER(LOWER_P(callContext->top + topicCount)); + if ( + src + size < size + || UPPER(UPPER_P(callContext->top + topicCount)) || LOWER(UPPER_P(callContext->top + topicCount)) || UPPER(LOWER_P(callContext->top + topicCount)) + || UPPER(UPPER_P(callContext->top + topicCount + 1)) || LOWER(UPPER_P(callContext->top + topicCount + 1)) || UPPER(LOWER_P(callContext->top + topicCount + 1)) + || !ensureMemory(callContext, src + size) + ) { + OUT_OF_GAS; + } + uint64_t gasCost = /*topicCount * G_LOGTOPIC +*/ G_LOGDATA * size; + if (gasCost > callContext->gas) { + OUT_OF_GAS; + } + callContext->gas -= gasCost; + logChanges_t *log = malloc(sizeof(logChanges_t)); + log->logIndex = logIndex++; + log->topicCount = topicCount; + if (topicCount) { + size_t topicSize = topicCount * sizeof(uint256_t); + log->topics = malloc(topicSize); + memcpy(log->topics, callContext->top, topicSize); + } else { + log->topics = NULL; + } + if (size) { + log->data.size = size; + log->data.content = malloc(size); + memcpy(log->data.content, callContext->memory.uint8s + src, log->data.size); + } else { + log->data.size = 0; + log->data.content = NULL; + } + + stateChanges_t *stateChanges = getCurrentAccountStateChanges(&result, callContext); + if (SHOW_LOGS) { + fprintf(stderr, "\033[94m"); + fprintLog(stderr, log, true); + fprintf(stderr, "\033[0m\n"); + } + log->prev = stateChanges->logChanges; + stateChanges->logChanges = log; + } + break; + case CALLDATACOPY: + case EXTCODECOPY: + case RETURNDATACOPY: + case MCOPY: + case CODECOPY: + { + const data_t *code; + uint64_t start = LOWER(LOWER_P(callContext->top + 1)); + uint64_t size = LOWER(LOWER_P(callContext->top)); + switch (op) { + case EXTCODECOPY: + { + account_t *account = warmAccount(callContext, AddressFromUint256(callContext->top + 3)); + if (account == NULL) { + OUT_OF_GAS; } + code = &account->code; + } + break; + case CALLDATACOPY: + code = &callContext->callData; break; - case MSTORE8: - { - if (!ensureMemory(callContext, 1 + LOWER(LOWER_P(callContext->top + 1)))) { - OUT_OF_GAS; - } - uint8_t *loc = (callContext->memory.uint8s + LOWER(LOWER_P(callContext->top + 1))); - *loc = LOWER(LOWER_P(callContext->top)); + case RETURNDATACOPY: + code = &callContext->returnData; + if ( + UPPER(LOWER_P(callContext->top + 1)) || LOWER(UPPER_P(callContext->top + 1)) || UPPER(UPPER_P(callContext->top + 1)) + || start + size > code->size) { + FAIL_INVALID; } break; - case MLOAD: - if (UPPER(LOWER_P(callContext->top - 1)) || LOWER(UPPER_P(callContext->top - 1)) || UPPER(UPPER_P(callContext->top - 1))) { - OUT_OF_GAS; - } - if (!ensureMemory(callContext, 32 + LOWER(LOWER_P(callContext->top - 1)))) { + case MCOPY: + if ( + UPPER(LOWER_P(callContext->top + 1)) + || LOWER(UPPER_P(callContext->top + 1)) + || UPPER(UPPER_P(callContext->top + 1)) + || !ensureMemory(callContext, start + size)) { OUT_OF_GAS; } - readu256BE(callContext->memory.uint8s + LOWER(LOWER_P(callContext->top - 1)), callContext->top - 1); - break; - case CALLDATALOAD: - if (UPPER(LOWER_P(callContext->top - 1)) || LOWER(UPPER_P(callContext->top - 1)) || UPPER(UPPER_P(callContext->top - 1)) || LOWER(LOWER_P(callContext->top - 1)) >= callContext->callData.size) { - clear256(callContext->top - 1); - } else if (LOWER(LOWER_P(callContext->top - 1)) + 32 > callContext->callData.size) { - uint8_t partial[32]; - bzero(partial, 32); - memcpy(partial, callContext->callData.content + LOWER(LOWER_P(callContext->top - 1)), callContext->callData.size - LOWER(LOWER_P(callContext->top - 1))); - readu256BE(partial, callContext->top - 1); - } else { - readu256BE(callContext->callData.content + LOWER(LOWER_P(callContext->top - 1)), callContext->top - 1); - } + code = (data_t *)(&callContext->memory); break; - case LOG0: - case LOG1: - case LOG2: - case LOG3: - case LOG4: - { - uint8_t topicCount = op - LOG0; - uint64_t src = LOWER(LOWER_P(callContext->top + topicCount + 1)); - uint64_t size = LOWER(LOWER_P(callContext->top + topicCount)); - if ( - src + size < size - || UPPER(UPPER_P(callContext->top + topicCount)) || LOWER(UPPER_P(callContext->top + topicCount)) || UPPER(LOWER_P(callContext->top + topicCount)) - || UPPER(UPPER_P(callContext->top + topicCount + 1)) || LOWER(UPPER_P(callContext->top + topicCount + 1)) || UPPER(LOWER_P(callContext->top + topicCount + 1)) - || !ensureMemory(callContext, src + size) + case CODECOPY: + code = &callContext->code; + } + uint64_t dst = LOWER(LOWER_P(callContext->top + 2)); + if ( + UPPER(LOWER_P(callContext->top + 2)) || LOWER(UPPER_P(callContext->top + 2)) || UPPER(UPPER_P(callContext->top + 2)) + || (UPPER(LOWER_P(callContext->top)) || LOWER(UPPER_P(callContext->top)) || UPPER(UPPER_P(callContext->top))) + || dst + size < dst + || !ensureMemory(callContext, dst + size) ) { - OUT_OF_GAS; - } - uint64_t gasCost = /*topicCount * G_LOGTOPIC +*/ G_LOGDATA * size; - if (gasCost > callContext->gas) { - OUT_OF_GAS; - } - callContext->gas -= gasCost; - logChanges_t *log = malloc(sizeof(logChanges_t)); - log->logIndex = logIndex++; - log->topicCount = topicCount; - if (topicCount) { - size_t topicSize = topicCount * sizeof(uint256_t); - log->topics = malloc(topicSize); - memcpy(log->topics, callContext->top, topicSize); - } else { - log->topics = NULL; - } - if (size) { - log->data.size = size; - log->data.content = malloc(size); - memcpy(log->data.content, callContext->memory.uint8s + src, log->data.size); + OUT_OF_GAS; + } + uint64_t words = (size + 31) / 32; + uint64_t gasCost = G_COPY * words; + if (gasCost > callContext->gas) { + OUT_OF_GAS; + } + callContext->gas -= gasCost; + if ( + UPPER(LOWER_P(callContext->top + 1)) || LOWER(UPPER_P(callContext->top + 1)) || UPPER(UPPER_P(callContext->top + 1)) + || start > code->size + ) { + bzero(callContext->memory.uint8s + dst, size); + } else if (start + size > code->size) { + uint64_t copySize = code->size - start; + memcpy(callContext->memory.uint8s + dst, code->content + start, copySize); + bzero(callContext->memory.uint8s + dst + copySize, size - copySize); + } else { + memcpy(callContext->memory.uint8s + dst, code->content + start, size); + } + } + break; + case SSTORE: + { + if (callContext->gas <= G_CALLSTIPEND - G_ACCESS) { + OUT_OF_GAS; + } + uint64_t warmBefore = getAccountStorage(callContext->account, callContext->top + 1)->warm; + storage_t *storage = warmStorage(callContext, callContext->top + 1, G_COLD_STORAGE); + if (storage == NULL) { + OUT_OF_GAS; + } + // https://eips.ethereum.org/EIPS/eip-2200 + if (!equal256(&storage->value, callContext->top)) { + if (equal256(&storage->value, &storage->original)) { + uint64_t gasCost; + if (zero256(&storage->original)) { + gasCost = G_SSET - G_ACCESS; } else { - log->data.size = 0; - log->data.content = NULL; - } - - stateChanges_t *stateChanges = getCurrentAccountStateChanges(&result, callContext); - if (SHOW_LOGS) { - fprintf(stderr, "\033[94m"); - fprintLog(stderr, log, true); - fprintf(stderr, "\033[0m\n"); - } - log->prev = stateChanges->logChanges; - stateChanges->logChanges = log; - } - break; - case CALLDATACOPY: - case EXTCODECOPY: - case RETURNDATACOPY: - case MCOPY: - case CODECOPY: - { - const data_t *code; - uint64_t start = LOWER(LOWER_P(callContext->top + 1)); - uint64_t size = LOWER(LOWER_P(callContext->top)); - switch (op) { - case EXTCODECOPY: - { - account_t *account = warmAccount(callContext, AddressFromUint256(callContext->top + 3)); - if (account == NULL) { - OUT_OF_GAS; - } - code = &account->code; - } - break; - case CALLDATACOPY: - code = &callContext->callData; - break; - case RETURNDATACOPY: - code = &callContext->returnData; - if ( - UPPER(LOWER_P(callContext->top + 1)) || LOWER(UPPER_P(callContext->top + 1)) || UPPER(UPPER_P(callContext->top + 1)) - || start + size > code->size) { - FAIL_INVALID; - } - break; - case MCOPY: - if ( - UPPER(LOWER_P(callContext->top + 1)) - || LOWER(UPPER_P(callContext->top + 1)) - || UPPER(UPPER_P(callContext->top + 1)) - || !ensureMemory(callContext, start + size)) { - OUT_OF_GAS; + gasCost = G_SRESET - G_ACCESS; + if (zero256(callContext->top)) { + refundCounter += R_CLEAR; } - code = (data_t *)(&callContext->memory); - break; - case CODECOPY: - code = &callContext->code; - } - uint64_t dst = LOWER(LOWER_P(callContext->top + 2)); - if ( - UPPER(LOWER_P(callContext->top + 2)) || LOWER(UPPER_P(callContext->top + 2)) || UPPER(UPPER_P(callContext->top + 2)) - || (UPPER(LOWER_P(callContext->top)) || LOWER(UPPER_P(callContext->top)) || UPPER(UPPER_P(callContext->top))) - || dst + size < dst - || !ensureMemory(callContext, dst + size) - ) { - OUT_OF_GAS; } - uint64_t words = (size + 31) / 32; - uint64_t gasCost = G_COPY * words; if (gasCost > callContext->gas) { OUT_OF_GAS; } callContext->gas -= gasCost; - if ( - UPPER(LOWER_P(callContext->top + 1)) || LOWER(UPPER_P(callContext->top + 1)) || UPPER(UPPER_P(callContext->top + 1)) - || start > code->size - ) { - bzero(callContext->memory.uint8s + dst, size); - } else if (start + size > code->size) { - uint64_t copySize = code->size - start; - memcpy(callContext->memory.uint8s + dst, code->content + start, copySize); - bzero(callContext->memory.uint8s + dst + copySize, size - copySize); - } else { - memcpy(callContext->memory.uint8s + dst, code->content + start, size); - } - } - break; - case SSTORE: - { - if (callContext->gas <= G_CALLSTIPEND - G_ACCESS) { - OUT_OF_GAS; - } - uint64_t warmBefore = getAccountStorage(callContext->account, callContext->top + 1)->warm; - storage_t *storage = warmStorage(callContext, callContext->top + 1, G_COLD_STORAGE); - if (storage == NULL) { - OUT_OF_GAS; + } else { + if (!zero256(&storage->original)) { + if (zero256(&storage->value)) { + refundCounter -= R_CLEAR; + } else if (zero256(callContext->top)) { + refundCounter += R_CLEAR; + } } - // https://eips.ethereum.org/EIPS/eip-2200 - if (!equal256(&storage->value, callContext->top)) { - if (equal256(&storage->value, &storage->original)) { - uint64_t gasCost; - if (zero256(&storage->original)) { - gasCost = G_SSET - G_ACCESS; - } else { - gasCost = G_SRESET - G_ACCESS; - if (zero256(callContext->top)) { - refundCounter += R_CLEAR; - } - } - if (gasCost > callContext->gas) { - OUT_OF_GAS; - } - callContext->gas -= gasCost; + if (equal256(&storage->original, callContext->top)) { + if (zero256(&storage->original)) { + refundCounter += G_SSET - G_ACCESS; } else { - if (!zero256(&storage->original)) { - if (zero256(&storage->value)) { - refundCounter -= R_CLEAR; - } else if (zero256(callContext->top)) { - refundCounter += R_CLEAR; - } - } - if (equal256(&storage->original, callContext->top)) { - if (zero256(&storage->original)) { - refundCounter += G_SSET - G_ACCESS; - } else { - refundCounter += G_SRESET - G_ACCESS; - } - } + refundCounter += G_SRESET - G_ACCESS; } } - // track state changes in result in case of REVERT or exception - stateChanges_t *changes = getCurrentAccountStateChanges(&result, callContext); - storageChanges_t *change = malloc(sizeof(storageChanges_t)); - copy256(&change->key, &storage->key); - copy256(&change->before, &storage->value); - copy256(&change->after, callContext->top); - change->warm = warmBefore; - change->prev = changes->storageChanges; - changes->storageChanges = change; - copy256(&storage->value, callContext->top); - } - break; - case SLOAD: - { - uint64_t warmBefore = getAccountStorage(callContext->account, callContext->top - 1)->warm; - storage_t *storage = warmStorage(callContext, callContext->top - 1, G_COLD_STORAGE - G_ACCESS); - if (storage == NULL) { - OUT_OF_GAS; - } - copy256(callContext->top - 1, &storage->value); - // track access list changes in result in case of REVERT or exception - stateChanges_t *changes = getCurrentAccountStateChanges(&result, callContext); - storageChanges_t *change = malloc(sizeof(storageChanges_t)); - copy256(&change->key, &storage->key); - copy256(&change->before, &storage->value); - copy256(&change->after, &storage->value); - change->warm = warmBefore; - change->prev = changes->storageChanges; - changes->storageChanges = change; - } - break; - case TLOAD: - { - tstorage_t *storage = getAccountTransientStorage(callContext->account, callContext->top -1); - if (storage->warm == evmIteration) { - copy256(callContext->top - 1, &storage->value); - } else { - clear256(callContext->top - 1); - } - } - break; - case TSTORE: - { - tstorage_t *storage = getAccountTransientStorage(callContext->account, callContext->top + 1); - copy256(&storage->value, callContext->top); - storage->warm = evmIteration; } - break; - case COINBASE: - // TODO allow configuration for coinbase - AddressToUint256(callContext->top - 1, &coinbase); - break; - case TIMESTAMP: - UPPER(UPPER_P(callContext->top - 1)) = 0; - LOWER(UPPER_P(callContext->top - 1)) = 0; - UPPER(LOWER_P(callContext->top - 1)) = 0; - LOWER(LOWER_P(callContext->top - 1)) = timestamp; - break; - case NUMBER: - UPPER(UPPER_P(callContext->top - 1)) = 0; - LOWER(UPPER_P(callContext->top - 1)) = 0; - UPPER(LOWER_P(callContext->top - 1)) = 0; - LOWER(LOWER_P(callContext->top - 1)) = blockNumber; - break; - case CALLVALUE: - UPPER(UPPER_P(callContext->top - 1)) = 0; - LOWER(UPPER_P(callContext->top - 1)) = 0; - UPPER(LOWER_P(callContext->top - 1)) = callContext->callValue[0]; - LOWER(LOWER_P(callContext->top - 1)) = callContext->callValue[2] | ((uint64_t) callContext->callValue[1] << 32); + } + // track state changes in result in case of REVERT or exception + stateChanges_t *changes = getCurrentAccountStateChanges(&result, callContext); + storageChanges_t *change = malloc(sizeof(storageChanges_t)); + copy256(&change->key, &storage->key); + copy256(&change->before, &storage->value); + copy256(&change->after, callContext->top); + change->warm = warmBefore; + change->prev = changes->storageChanges; + changes->storageChanges = change; + copy256(&storage->value, callContext->top); + } + break; + case SLOAD: + { + uint64_t warmBefore = getAccountStorage(callContext->account, callContext->top - 1)->warm; + storage_t *storage = warmStorage(callContext, callContext->top - 1, G_COLD_STORAGE - G_ACCESS); + if (storage == NULL) { + OUT_OF_GAS; + } + copy256(callContext->top - 1, &storage->value); + // track access list changes in result in case of REVERT or exception + stateChanges_t *changes = getCurrentAccountStateChanges(&result, callContext); + storageChanges_t *change = malloc(sizeof(storageChanges_t)); + copy256(&change->key, &storage->key); + copy256(&change->before, &storage->value); + copy256(&change->after, &storage->value); + change->warm = warmBefore; + change->prev = changes->storageChanges; + changes->storageChanges = change; + } + break; + case TLOAD: + { + tstorage_t *storage = getAccountTransientStorage(callContext->account, callContext->top -1); + if (storage->warm == evmIteration) { + copy256(callContext->top - 1, &storage->value); + } else { + clear256(callContext->top - 1); + } + } + break; + case TSTORE: + { + tstorage_t *storage = getAccountTransientStorage(callContext->account, callContext->top + 1); + copy256(&storage->value, callContext->top); + storage->warm = evmIteration; + } + break; + case COINBASE: + // TODO allow configuration for coinbase + AddressToUint256(callContext->top - 1, &coinbase); + break; + case TIMESTAMP: + UPPER(UPPER_P(callContext->top - 1)) = 0; + LOWER(UPPER_P(callContext->top - 1)) = 0; + UPPER(LOWER_P(callContext->top - 1)) = 0; + LOWER(LOWER_P(callContext->top - 1)) = timestamp; + break; + case NUMBER: + UPPER(UPPER_P(callContext->top - 1)) = 0; + LOWER(UPPER_P(callContext->top - 1)) = 0; + UPPER(LOWER_P(callContext->top - 1)) = 0; + LOWER(LOWER_P(callContext->top - 1)) = blockNumber; + break; + case CALLVALUE: + UPPER(UPPER_P(callContext->top - 1)) = 0; + LOWER(UPPER_P(callContext->top - 1)) = 0; + UPPER(LOWER_P(callContext->top - 1)) = callContext->callValue[0]; + LOWER(LOWER_P(callContext->top - 1)) = callContext->callValue[2] | ((uint64_t) callContext->callValue[1] << 32); + break; + case CHAINID: + // TODO allow configuration for chainId + UPPER(UPPER_P(callContext->top - 1)) = 0; + LOWER(UPPER_P(callContext->top - 1)) = 0; + UPPER(LOWER_P(callContext->top - 1)) = 0; + LOWER(LOWER_P(callContext->top - 1)) = 1; + break; + case SELFBALANCE: + UPPER(UPPER_P(callContext->top - 1)) = 0; + LOWER(UPPER_P(callContext->top - 1)) = 0; + UPPER(LOWER_P(callContext->top - 1)) = callContext->account->balance[0]; + LOWER(LOWER_P(callContext->top - 1)) = callContext->account->balance[2] | ((uint64_t) callContext->account->balance[1] << 32); + break; + case BALANCE: + { + account_t *account = warmAccount(callContext, AddressFromUint256(callContext->top - 1)); + if (account == NULL) { + OUT_OF_GAS; + } + UPPER(UPPER_P(callContext->top - 1)) = 0; + LOWER(UPPER_P(callContext->top - 1)) = 0; + UPPER(LOWER_P(callContext->top - 1)) = account->balance[0]; + LOWER(LOWER_P(callContext->top - 1)) = account->balance[2] | ((uint64_t) account->balance[1] << 32); + } + break; + case CREATE: + { + data_t input; + input.size = LOWER(LOWER_P(callContext->top - 1)); + uint64_t src = LOWER(LOWER_P(callContext->top)); + if (!ensureMemory(callContext, src + input.size)) { + OUT_OF_GAS; + } + input.content = callContext->memory.uint8s + src; + val_t value; + value[0] = UPPER(LOWER_P(callContext->top + 1)); + value[1] = LOWER(LOWER_P(callContext->top + 1)) >> 32; + value[2] = LOWER(LOWER_P(callContext->top + 1)); + + // apply R function before L function + uint64_t rGas = initcodeGas(&input); + if (callContext->gas < rGas) { + OUT_OF_GAS; + } + callContext->gas -= rGas; + uint64_t gas = L(callContext->gas); + callContext->gas -= gas; + + result_t createResult = evmCreate(callContext->account, gas, value, input); + callContext->gas += createResult.gasRemaining; + mergeStateChanges(&result.stateChanges, createResult.stateChanges); + callContext->returnData = createResult.returnData; + if (!zero256(&createResult.status)) { + callContext->returnData.size = 0; // EIP-211: success = empty buffer + } + copy256(callContext->top - 1, &createResult.status); + } + break; + case CREATE2: + { + data_t input; + input.size = LOWER(LOWER_P(callContext->top)); + uint64_t src = LOWER(LOWER_P(callContext->top + 1)); + if (!ensureMemory(callContext, src + input.size)) { + OUT_OF_GAS; + } + input.content = callContext->memory.uint8s + src; + if (UPPER(UPPER_P(callContext->top + 2)) + || LOWER(UPPER_P(callContext->top + 2)) + || UPPER(LOWER_P(callContext->top + 2)) >> 32) { + callContext->returnData.size = 0; + clear256(callContext->top - 1); break; - case CHAINID: - // TODO allow configuration for chainId - UPPER(UPPER_P(callContext->top - 1)) = 0; - LOWER(UPPER_P(callContext->top - 1)) = 0; - UPPER(LOWER_P(callContext->top - 1)) = 0; - LOWER(LOWER_P(callContext->top - 1)) = 1; - break; - case SELFBALANCE: - UPPER(UPPER_P(callContext->top - 1)) = 0; - LOWER(UPPER_P(callContext->top - 1)) = 0; - UPPER(LOWER_P(callContext->top - 1)) = callContext->account->balance[0]; - LOWER(LOWER_P(callContext->top - 1)) = callContext->account->balance[2] | ((uint64_t) callContext->account->balance[1] << 32); - break; - case BALANCE: - { - account_t *account = warmAccount(callContext, AddressFromUint256(callContext->top - 1)); - if (account == NULL) { - OUT_OF_GAS; - } - UPPER(UPPER_P(callContext->top - 1)) = 0; - LOWER(UPPER_P(callContext->top - 1)) = 0; - UPPER(LOWER_P(callContext->top - 1)) = account->balance[0]; - LOWER(LOWER_P(callContext->top - 1)) = account->balance[2] | ((uint64_t) account->balance[1] << 32); - } - break; - case CREATE: - { - data_t input; - input.size = LOWER(LOWER_P(callContext->top - 1)); - uint64_t src = LOWER(LOWER_P(callContext->top)); - if (!ensureMemory(callContext, src + input.size)) { - OUT_OF_GAS; - } - input.content = callContext->memory.uint8s + src; - val_t value; - value[0] = UPPER(LOWER_P(callContext->top + 1)); - value[1] = LOWER(LOWER_P(callContext->top + 1)) >> 32; - value[2] = LOWER(LOWER_P(callContext->top + 1)); - - // apply R function before L function - uint64_t rGas = initcodeGas(&input); - if (callContext->gas < rGas) { - OUT_OF_GAS; - } - callContext->gas -= rGas; - uint64_t gas = L(callContext->gas); - callContext->gas -= gas; - - result_t createResult = evmCreate(callContext->account, gas, value, input); - callContext->gas += createResult.gasRemaining; - mergeStateChanges(&result.stateChanges, createResult.stateChanges); - callContext->returnData = createResult.returnData; - if (!zero256(&createResult.status)) { - callContext->returnData.size = 0; // EIP-211: success = empty buffer - } - copy256(callContext->top - 1, &createResult.status); - } - break; - case CREATE2: - { - data_t input; - input.size = LOWER(LOWER_P(callContext->top)); - uint64_t src = LOWER(LOWER_P(callContext->top + 1)); - if (!ensureMemory(callContext, src + input.size)) { - OUT_OF_GAS; - } - input.content = callContext->memory.uint8s + src; - if (UPPER(UPPER_P(callContext->top + 2)) - || LOWER(UPPER_P(callContext->top + 2)) - || UPPER(LOWER_P(callContext->top + 2)) >> 32) { - callContext->returnData.size = 0; - clear256(callContext->top - 1); - break; - } - val_t value; - value[0] = UPPER(LOWER_P(callContext->top + 2)); - value[1] = LOWER(LOWER_P(callContext->top + 2)) >> 32; - value[2] = LOWER(LOWER_P(callContext->top + 2)); - const uint256_t *salt = callContext->top - 1; - - // apply R function before L function; CREATE2 adds keccak word cost - uint64_t rGas = initcodeGas(&input) + G_KECCAK_WORD * ((input.size + 31) >> 5); - if (callContext->gas < rGas) { - OUT_OF_GAS; - } - callContext->gas -= rGas; - uint64_t gas = L(callContext->gas); - callContext->gas -= gas; - - result_t createResult = evmCreate2(callContext->account, gas, value, input, salt); - callContext->gas += createResult.gasRemaining; - mergeStateChanges(&result.stateChanges, createResult.stateChanges); - callContext->returnData = createResult.returnData; - if (!zero256(&createResult.status)) { - callContext->returnData.size = 0; // EIP-211: success = empty buffer - } - copy256(callContext->top - 1, &createResult.status); - } - break; - case CALL: - { - data_t input; - input.size = LOWER(LOWER_P(callContext->top + 1)); - uint64_t src = LOWER(LOWER_P(callContext->top + 2)); - uint64_t dst = LOWER(LOWER_P(callContext->top)); - uint64_t gas = LOWER(LOWER_P(callContext->top + 5)); - val_t value; - value[0] = UPPER(LOWER_P(callContext->top + 3)); - value[1] = LOWER(LOWER_P(callContext->top + 3)) >> 32; - value[2] = LOWER(LOWER_P(callContext->top + 3)); - uint64_t outSize = LOWER(LOWER_P(callContext->top - 1)); - if (!ensureMemory(callContext, src + input.size)) { - OUT_OF_GAS; - } - if (!ensureMemory(callContext, dst + outSize)) { - OUT_OF_GAS; - } - input.content = callContext->memory.uint8s + src; - // C_EXTRA - address_t to = AddressFromUint256(callContext->top + 4); - account_t *toAccount = warmAccount(callContext, to); - if (toAccount == NULL) { - OUT_OF_GAS; - } - uint64_t gasCost = 0; - if (value[0] || value[1] || value[2]) { - gasCost += G_CALLVALUE; - if (AccountDead(toAccount)) { - gasCost += G_NEWACCOUNT; - } - } - if (gasCost > callContext->gas) { - OUT_OF_GAS; - } - callContext->gas -= gasCost; - if (UPPER(UPPER_P(callContext->top + 5)) || LOWER(UPPER_P(callContext->top + 5)) || UPPER(LOWER_P(callContext->top + 5)) || gas > L(callContext->gas)) { - gas = L(callContext->gas); - } - callContext->gas -= gas; - if (value[0] || value[1] || value[2]) { - gas += G_CALLSTIPEND; - } - result_t callResult = evmCall(callContext->account->address, gas, to, value, input); - callContext->gas += callResult.gasRemaining; - mergeStateChanges(&result.stateChanges, callResult.stateChanges); - callContext->returnData = callResult.returnData; - if (callContext->returnData.size < outSize) { - outSize = callContext->returnData.size; - } - memcpy(callContext->memory.uint8s + dst, callResult.returnData.content, outSize); - copy256(callContext->top - 1, &callResult.status); - } - break; - case DELEGATECALL: - { - data_t input; - input.size = LOWER(LOWER_P(callContext->top + 1)); - uint64_t src = LOWER(LOWER_P(callContext->top + 2)); - uint64_t dst = LOWER(LOWER_P(callContext->top)); - uint64_t gas = LOWER(LOWER_P(callContext->top + 4)); - uint64_t outSize = LOWER(LOWER_P(callContext->top - 1)); - if (!ensureMemory(callContext, src + input.size)) { - OUT_OF_GAS; - } - if (!ensureMemory(callContext, dst + outSize)) { - OUT_OF_GAS; - } - input.content = callContext->memory.uint8s + src; - // C_EXTRA - address_t to = AddressFromUint256(callContext->top + 3); - account_t *toAccount = warmAccount(callContext, to); - if (toAccount == NULL) { - OUT_OF_GAS; - } - uint64_t gasCost = 0; - if (gasCost > callContext->gas) { - OUT_OF_GAS; - } - callContext->gas -= gasCost; - if (UPPER(UPPER_P(callContext->top + 4)) || LOWER(UPPER_P(callContext->top + 4)) || UPPER(LOWER_P(callContext->top + 4)) || gas > L(callContext->gas)) { - gas = L(callContext->gas); - } - callContext->gas -= gas; - result_t delegateCallResult = evmDelegateCall(gas, toAccount, input); - callContext->gas += delegateCallResult.gasRemaining; - mergeStateChanges(&result.stateChanges, delegateCallResult.stateChanges); - callContext->returnData = delegateCallResult.returnData; - if (callContext->returnData.size < outSize) { - outSize = callContext->returnData.size; - } - memcpy(callContext->memory.uint8s + dst, delegateCallResult.returnData.content, outSize); - copy256(callContext->top - 1, &delegateCallResult.status); - } - break; - case STATICCALL: - { - data_t input; - input.size = LOWER(LOWER_P(callContext->top + 1)); - uint64_t src = LOWER(LOWER_P(callContext->top + 2)); - uint64_t dst = LOWER(LOWER_P(callContext->top)); - uint64_t gas = LOWER(LOWER_P(callContext->top + 4)); - uint64_t outSize = LOWER(LOWER_P(callContext->top - 1)); - if (!ensureMemory(callContext, src + input.size)) { - OUT_OF_GAS; - } - if (!ensureMemory(callContext, dst + outSize)) { - OUT_OF_GAS; - } - input.content = callContext->memory.uint8s + src; - // C_EXTRA - address_t to = AddressFromUint256(callContext->top + 3); - account_t *toAccount = warmAccount(callContext, to); - if (toAccount == NULL) { - OUT_OF_GAS; - } - uint64_t gasCost = 0; - if (gasCost > callContext->gas) { - OUT_OF_GAS; - } - callContext->gas -= gasCost; - if (UPPER(UPPER_P(callContext->top + 4)) || LOWER(UPPER_P(callContext->top + 4)) || UPPER(LOWER_P(callContext->top + 4)) || gas > L(callContext->gas)) { - gas = L(callContext->gas); - } - callContext->gas -= gas; - result_t callResult = evmStaticCall(callContext->account->address, gas, to, input); - callContext->gas += callResult.gasRemaining; - mergeStateChanges(&result.stateChanges, callResult.stateChanges); - callContext->returnData = callResult.returnData; - if (callContext->returnData.size < outSize) { - outSize = callContext->returnData.size; - } - memcpy(callContext->memory.uint8s + dst, callResult.returnData.content, outSize); - copy256(callContext->top - 1, &callResult.status); + } + val_t value; + value[0] = UPPER(LOWER_P(callContext->top + 2)); + value[1] = LOWER(LOWER_P(callContext->top + 2)) >> 32; + value[2] = LOWER(LOWER_P(callContext->top + 2)); + const uint256_t *salt = callContext->top - 1; + + // apply R function before L function; CREATE2 adds keccak word cost + uint64_t rGas = initcodeGas(&input) + G_KECCAK_WORD * ((input.size + 31) >> 5); + if (callContext->gas < rGas) { + OUT_OF_GAS; + } + callContext->gas -= rGas; + uint64_t gas = L(callContext->gas); + callContext->gas -= gas; + + result_t createResult = evmCreate2(callContext->account, gas, value, input, salt); + callContext->gas += createResult.gasRemaining; + mergeStateChanges(&result.stateChanges, createResult.stateChanges); + callContext->returnData = createResult.returnData; + if (!zero256(&createResult.status)) { + callContext->returnData.size = 0; // EIP-211: success = empty buffer + } + copy256(callContext->top - 1, &createResult.status); + } + break; + case CALL: + { + data_t input; + input.size = LOWER(LOWER_P(callContext->top + 1)); + uint64_t src = LOWER(LOWER_P(callContext->top + 2)); + uint64_t dst = LOWER(LOWER_P(callContext->top)); + uint64_t gas = LOWER(LOWER_P(callContext->top + 5)); + val_t value; + value[0] = UPPER(LOWER_P(callContext->top + 3)); + value[1] = LOWER(LOWER_P(callContext->top + 3)) >> 32; + value[2] = LOWER(LOWER_P(callContext->top + 3)); + uint64_t outSize = LOWER(LOWER_P(callContext->top - 1)); + if (!ensureMemory(callContext, src + input.size)) { + OUT_OF_GAS; + } + if (!ensureMemory(callContext, dst + outSize)) { + OUT_OF_GAS; + } + input.content = callContext->memory.uint8s + src; + // C_EXTRA + address_t to = AddressFromUint256(callContext->top + 4); + account_t *toAccount = warmAccount(callContext, to); + if (toAccount == NULL) { + OUT_OF_GAS; + } + uint64_t gasCost = 0; + if (value[0] || value[1] || value[2]) { + gasCost += G_CALLVALUE; + if (AccountDead(toAccount)) { + gasCost += G_NEWACCOUNT; } - break; - case RETURN: - LOWER(LOWER(result.status)) = 1; - // intentional fallthrough - case REVERT: - if (!ensureMemory(callContext, LOWER(LOWER_P(callContext->top + 1)) + LOWER(LOWER_P(callContext->top)))) { - OUT_OF_GAS; + } + if (gasCost > callContext->gas) { + OUT_OF_GAS; + } + callContext->gas -= gasCost; + if (UPPER(UPPER_P(callContext->top + 5)) || LOWER(UPPER_P(callContext->top + 5)) || UPPER(LOWER_P(callContext->top + 5)) || gas > L(callContext->gas)) { + gas = L(callContext->gas); + } + callContext->gas -= gas; + if (value[0] || value[1] || value[2]) { + gas += G_CALLSTIPEND; + } + result_t callResult = evmCall(callContext->account->address, gas, to, value, input); + callContext->gas += callResult.gasRemaining; + mergeStateChanges(&result.stateChanges, callResult.stateChanges); + callContext->returnData = callResult.returnData; + if (callContext->returnData.size < outSize) { + outSize = callContext->returnData.size; + } + memcpy(callContext->memory.uint8s + dst, callResult.returnData.content, outSize); + copy256(callContext->top - 1, &callResult.status); + } + break; + case DELEGATECALL: + { + data_t input; + input.size = LOWER(LOWER_P(callContext->top + 1)); + uint64_t src = LOWER(LOWER_P(callContext->top + 2)); + uint64_t dst = LOWER(LOWER_P(callContext->top)); + uint64_t gas = LOWER(LOWER_P(callContext->top + 4)); + uint64_t outSize = LOWER(LOWER_P(callContext->top - 1)); + if (!ensureMemory(callContext, src + input.size)) { + OUT_OF_GAS; + } + if (!ensureMemory(callContext, dst + outSize)) { + OUT_OF_GAS; + } + input.content = callContext->memory.uint8s + src; + // C_EXTRA + address_t to = AddressFromUint256(callContext->top + 3); + account_t *toAccount = warmAccount(callContext, to); + if (toAccount == NULL) { + OUT_OF_GAS; + } + uint64_t gasCost = 0; + if (gasCost > callContext->gas) { + OUT_OF_GAS; + } + callContext->gas -= gasCost; + if (UPPER(UPPER_P(callContext->top + 4)) || LOWER(UPPER_P(callContext->top + 4)) || UPPER(LOWER_P(callContext->top + 4)) || gas > L(callContext->gas)) { + gas = L(callContext->gas); + } + callContext->gas -= gas; + result_t delegateCallResult = evmDelegateCall(gas, toAccount, input); + callContext->gas += delegateCallResult.gasRemaining; + mergeStateChanges(&result.stateChanges, delegateCallResult.stateChanges); + callContext->returnData = delegateCallResult.returnData; + if (callContext->returnData.size < outSize) { + outSize = callContext->returnData.size; + } + memcpy(callContext->memory.uint8s + dst, delegateCallResult.returnData.content, outSize); + copy256(callContext->top - 1, &delegateCallResult.status); + } + break; + case STATICCALL: + { + data_t input; + input.size = LOWER(LOWER_P(callContext->top + 1)); + uint64_t src = LOWER(LOWER_P(callContext->top + 2)); + uint64_t dst = LOWER(LOWER_P(callContext->top)); + uint64_t gas = LOWER(LOWER_P(callContext->top + 4)); + uint64_t outSize = LOWER(LOWER_P(callContext->top - 1)); + if (!ensureMemory(callContext, src + input.size)) { + OUT_OF_GAS; + } + if (!ensureMemory(callContext, dst + outSize)) { + OUT_OF_GAS; + } + input.content = callContext->memory.uint8s + src; + // C_EXTRA + address_t to = AddressFromUint256(callContext->top + 3); + account_t *toAccount = warmAccount(callContext, to); + if (toAccount == NULL) { + OUT_OF_GAS; + } + uint64_t gasCost = 0; + if (gasCost > callContext->gas) { + OUT_OF_GAS; + } + callContext->gas -= gasCost; + if (UPPER(UPPER_P(callContext->top + 4)) || LOWER(UPPER_P(callContext->top + 4)) || UPPER(LOWER_P(callContext->top + 4)) || gas > L(callContext->gas)) { + gas = L(callContext->gas); + } + callContext->gas -= gas; + result_t callResult = evmStaticCall(callContext->account->address, gas, to, input); + callContext->gas += callResult.gasRemaining; + mergeStateChanges(&result.stateChanges, callResult.stateChanges); + callContext->returnData = callResult.returnData; + if (callContext->returnData.size < outSize) { + outSize = callContext->returnData.size; + } + memcpy(callContext->memory.uint8s + dst, callResult.returnData.content, outSize); + copy256(callContext->top - 1, &callResult.status); + } + break; + case RETURN: + LOWER(LOWER(result.status)) = 1; + // intentional fallthrough + case REVERT: + if (!ensureMemory(callContext, LOWER(LOWER_P(callContext->top + 1)) + LOWER(LOWER_P(callContext->top)))) { + OUT_OF_GAS; + } + result.returnData.content = callContext->memory.uint8s + LOWER(LOWER_P(callContext->top + 1)); + result.returnData.size = LOWER(LOWER_P(callContext->top)); + if (SHOW_CALLS) { + INDENT; + if (zero256(&result.status)) { + fprintf(stderr, "\033[0;31m"); } - result.returnData.content = callContext->memory.uint8s + LOWER(LOWER_P(callContext->top + 1)); - result.returnData.size = LOWER(LOWER_P(callContext->top)); - if (SHOW_CALLS) { - INDENT; - if (zero256(&result.status)) { - fprintf(stderr, "\033[0;31m"); - } - fprintf(stderr, "output: "); - fprintData(stderr, result.returnData); - fprintf(stderr, "\n"); - if (zero256(&result.status)) { - fprintf(stderr, "\033[0m"); - } + fprintf(stderr, "output: "); + fprintData(stderr, result.returnData); + fprintf(stderr, "\n"); + if (zero256(&result.status)) { + fprintf(stderr, "\033[0m"); } - return result; + } + return result; } } #undef OUT_OF_GAS @@ -1859,8 +1865,8 @@ static result_t evmCall(address_t from, uint64_t gas, address_t to, val_t value, account_t *fromAccount = getAccount(from); if (!BalanceSub(fromAccount->balance, value)) { fprintf(stderr, "Insufficient balance [0x%08x%08x%08x] for call (need [0x%08x%08x%08x])\n", - fromAccount->balance[0], fromAccount->balance[1], fromAccount->balance[2], - value[0], value[1], value[2] + fromAccount->balance[0], fromAccount->balance[1], fromAccount->balance[2], + value[0], value[1], value[2] ); result_t result; @@ -2011,8 +2017,8 @@ result_t txCall(address_t from, uint64_t gas, address_t to, val_t value, data_t result_t evmCreate(account_t *fromAccount, uint64_t gas, val_t value, data_t input) { if (!BalanceSub(fromAccount->balance, value)) { fprintf(stderr, "Insufficient balance [0x%08x%08x%08x] for create (need [0x%08x%08x%08x])\n", - fromAccount->balance[0], fromAccount->balance[1], fromAccount->balance[2], - value[0], value[1], value[2] + fromAccount->balance[0], fromAccount->balance[1], fromAccount->balance[2], + value[0], value[1], value[2] ); result_t result; @@ -2029,8 +2035,8 @@ result_t evmCreate(account_t *fromAccount, uint64_t gas, val_t value, data_t inp static result_t evmCreate2(account_t *fromAccount, uint64_t gas, val_t value, data_t input, const uint256_t *salt) { if (!BalanceSub(fromAccount->balance, value)) { fprintf(stderr, "Insufficient balance [0x%08x%08x%08x] for create2 (need [0x%08x%08x%08x])\n", - fromAccount->balance[0], fromAccount->balance[1], fromAccount->balance[2], - value[0], value[1], value[2] + fromAccount->balance[0], fromAccount->balance[1], fromAccount->balance[2], + value[0], value[1], value[2] ); result_t result; result.gasRemaining = gas; diff --git a/src/keccak.c b/src/keccak.c index ec4120a..d7b7275 100644 --- a/src/keccak.c +++ b/src/keccak.c @@ -18,22 +18,28 @@ /*** Constants. ***/ static const uint8_t rho[24] = \ - { 1, 3, 6, 10, 15, 21, +{ + 1, 3, 6, 10, 15, 21, 28, 36, 45, 55, 2, 14, 27, 41, 56, 8, 25, 43, - 62, 18, 39, 61, 20, 44}; + 62, 18, 39, 61, 20, 44 +}; static const uint8_t pi[24] = \ - {10, 7, 11, 17, 18, 3, +{ + 10, 7, 11, 17, 18, 3, 5, 16, 8, 21, 24, 4, - 15, 23, 19, 13, 12, 2, - 20, 14, 22, 9, 6, 1}; + 15, 23, 19, 13, 12, 2, + 20, 14, 22, 9, 6, 1 +}; static const uint64_t RC[24] = \ - {1ULL, 0x8082ULL, 0x800000000000808aULL, 0x8000000080008000ULL, - 0x808bULL, 0x80000001ULL, 0x8000000080008081ULL, 0x8000000000008009ULL, - 0x8aULL, 0x88ULL, 0x80008009ULL, 0x8000000aULL, - 0x8000808bULL, 0x800000000000008bULL, 0x8000000000008089ULL, 0x8000000000008003ULL, - 0x8000000000008002ULL, 0x8000000000000080ULL, 0x800aULL, 0x800000008000000aULL, - 0x8000000080008081ULL, 0x8000000000008080ULL, 0x80000001ULL, 0x8000000080008008ULL}; +{ + 1ULL, 0x8082ULL, 0x800000000000808aULL, 0x8000000080008000ULL, + 0x808bULL, 0x80000001ULL, 0x8000000080008081ULL, 0x8000000000008009ULL, + 0x8aULL, 0x88ULL, 0x80008009ULL, 0x8000000aULL, + 0x8000808bULL, 0x800000000000008bULL, 0x8000000000008089ULL, 0x8000000000008003ULL, + 0x8000000000008002ULL, 0x8000000000000080ULL, 0x800aULL, 0x800000008000000aULL, + 0x8000000080008081ULL, 0x8000000000008080ULL, 0x80000001ULL, 0x8000000080008008ULL +}; /*** Helper macros to unroll the permutation. ***/ #define rol(x, s) (((x) << s) | ((x) >> (64 - s))) @@ -41,42 +47,47 @@ static const uint64_t RC[24] = \ #define REPEAT24(e) REPEAT6(e e e e) #define REPEAT5(e) e e e e e #define FOR5(v, s, e) \ - v = 0; \ - REPEAT5(e; v += s;) + v = 0; \ + REPEAT5(e; v += s; ) /*** Keccak-f[1600] ***/ static inline void keccakf(void* state) { - uint64_t* a = (uint64_t*)state; - uint64_t b[5] = {0}; - uint64_t t = 0; - uint8_t x, y; - - for (int i = 0; i < 24; i++) { - // Theta - FOR5(x, 1, - b[x] = 0; - FOR5(y, 5, - b[x] ^= a[x + y]; )) - FOR5(x, 1, - FOR5(y, 5, - a[y + x] ^= b[(x + 4) % 5] ^ rol(b[(x + 1) % 5], 1); )) - // Rho and pi - t = a[1]; - x = 0; - REPEAT24(b[0] = a[pi[x]]; - a[pi[x]] = rol(t, rho[x]); - t = b[0]; - x++; ) - // Chi - FOR5(y, - 5, - FOR5(x, 1, - b[x] = a[y + x];) - FOR5(x, 1, - a[y + x] = b[x] ^ ((~b[(x + 1) % 5]) & b[(x + 2) % 5]); )) - // Iota - a[0] ^= RC[i]; - } + uint64_t* a = (uint64_t*)state; + uint64_t b[5] = {0}; + uint64_t t = 0; + uint8_t x, y; + + for (int i = 0; i < 24; i++) { + // Theta + FOR5(x, 1, + b[x] = 0; + FOR5(y, 5, + b[x] ^= a[x + y]; + )) + FOR5(x, 1, + FOR5(y, 5, + a[y + x] ^= b[(x + 4) % 5] ^ rol(b[(x + 1) % 5], 1); + )) + // Rho and pi + t = a[1]; + x = 0; + REPEAT24(b[0] = a[pi[x]]; + a[pi[x]] = rol(t, rho[x]); + t = b[0]; + x++; + ) + // Chi + FOR5(y, + 5, + FOR5(x, 1, + b[x] = a[y + x]; + ) + FOR5(x, 1, + a[y + x] = b[x] ^ ((~b[(x + 1) % 5]) & b[(x + 2) % 5]); + )) + // Iota + a[0] ^= RC[i]; + } } /******** The FIPS202-defined functions. ********/ @@ -85,19 +96,19 @@ static inline void keccakf(void* state) { #define _(S) do { S } while (0) #define FOR(i, ST, L, S) \ - _(for (size_t i = 0; i < L; i += ST) { S; }) + _(for (size_t i = 0; i < L; i += ST) { S; }) #define mkapply_ds(NAME, S) \ - static inline void NAME(uint8_t* dst, \ - const uint8_t* src, \ - size_t len) { \ - FOR(i, 1, len, S); \ - } + static inline void NAME(uint8_t* dst, \ + const uint8_t* src, \ + size_t len) { \ + FOR(i, 1, len, S); \ + } #define mkapply_sd(NAME, S) \ - static inline void NAME(const uint8_t* src, \ - uint8_t* dst, \ - size_t len) { \ - FOR(i, 1, len, S); \ - } + static inline void NAME(const uint8_t* src, \ + uint8_t* dst, \ + size_t len) { \ + FOR(i, 1, len, S); \ + } mkapply_ds(xorin, dst[i] ^= src[i]) // xorin mkapply_sd(setout, dst[i] = src[i]) // setout @@ -107,60 +118,60 @@ mkapply_sd(setout, dst[i] = src[i]) // setout // Fold P*F over the full blocks of an input. #define foldP(I, L, F) \ - while (L >= rate) { \ - F(a, I, rate); \ - P(a); \ - I += rate; \ - L -= rate; \ - } + while (L >= rate) { \ + F(a, I, rate); \ + P(a); \ + I += rate; \ + L -= rate; \ + } /** The sponge-based hash construction. **/ static inline int hash(uint8_t* out, size_t outlen, const uint8_t* in, size_t inlen, size_t rate, uint8_t delim) { - if ((out == NULL) || ((in == NULL) && inlen != 0) || (rate >= Plen)) { - return -1; - } - uint8_t a[Plen] = {0}; - // Absorb input. - foldP(in, inlen, xorin); - // Xor in the DS and pad frame. - a[inlen] ^= delim; - a[rate - 1] ^= 0x80; - // Xor in the last block. - xorin(a, in, inlen); - // Apply P - P(a); - // Squeeze output. - foldP(out, outlen, setout); - setout(a, out, outlen); - memset(a, 0, 200); - return 0; + if ((out == NULL) || ((in == NULL) && inlen != 0) || (rate >= Plen)) { + return -1; + } + uint8_t a[Plen] = {0}; + // Absorb input. + foldP(in, inlen, xorin); + // Xor in the DS and pad frame. + a[inlen] ^= delim; + a[rate - 1] ^= 0x80; + // Xor in the last block. + xorin(a, in, inlen); + // Apply P + P(a); + // Squeeze output. + foldP(out, outlen, setout); + setout(a, out, outlen); + memset(a, 0, 200); + return 0; } /*** Helper macros to define SHA3 and SHAKE instances. ***/ #define defshake(bits) \ - int shake##bits(uint8_t* out, size_t outlen, \ - const uint8_t* in, size_t inlen) { \ - return hash(out, outlen, in, inlen, 200 - (bits / 4), 0x1f); \ - } + int shake ## bits(uint8_t* out, size_t outlen, \ + const uint8_t* in, size_t inlen) { \ + return hash(out, outlen, in, inlen, 200 - (bits / 4), 0x1f); \ + } #define defsha3(bits) \ - int sha3_##bits(uint8_t* out, size_t outlen, \ - const uint8_t* in, size_t inlen) { \ - if (outlen > (bits/8)) { \ - return -1; \ - } \ - return hash(out, outlen, in, inlen, 200 - (bits / 4), 0x06); \ - } + int sha3_ ## bits(uint8_t* out, size_t outlen, \ + const uint8_t* in, size_t inlen) { \ + if (outlen > (bits/8)) { \ + return -1; \ + } \ + return hash(out, outlen, in, inlen, 200 - (bits / 4), 0x06); \ + } #define defkeccak(bits) \ - int keccak_##bits(uint8_t* out, size_t outlen, \ - const uint8_t* in, size_t inlen) { \ - if (outlen > (bits/8)) { \ - return -1; \ - } \ - return hash(out, outlen, in, inlen, 200 - (bits / 4), 0x01); \ - } + int keccak_ ## bits(uint8_t* out, size_t outlen, \ + const uint8_t* in, size_t inlen) { \ + if (outlen > (bits/8)) { \ + return -1; \ + } \ + return hash(out, outlen, in, inlen, 200 - (bits / 4), 0x01); \ + } /*** FIPS202 SHAKE VOFs ***/ diff --git a/src/ops.c b/src/ops.c index 04d0384..a6623fb 100644 --- a/src/ops.c +++ b/src/ops.c @@ -20,247 +20,306 @@ const uint64_t gasCost[NUM_OPCODES] = { const char *opString[NUM_OPCODES] = { #define OP(index,name,in,out,gas) #name, - OPS + OPS #undef OP }; op_t parseOp(const char *start, const char **endOut) { switch (*(uint32_t *)start) { - case 'RDDA': *endOut = start + 7; return ADDRESS; - case 'MDDA': *endOut = start + 6; return ADDMOD; - case 'ALAB': *endOut = start + 7; return BALANCE; - case 'BOLB': + case 'RDDA': *endOut = start + 7; + return ADDRESS; + case 'MDDA': *endOut = start + 6; + return ADDMOD; + case 'ALAB': *endOut = start + 7; + return BALANCE; + case 'BOLB': + switch (*(uint32_t *)(start += 4)) { + case 'HSAH': *endOut = start + 4; + return BLOBHASH; + case 'ESAB': *endOut = start + 7; + return BLOBBASEFEE; + } + case 'COLB': *endOut = start + 9; + return BLOCKHASH; + case 'ETYB': *endOut = start + 4; + return BYTE; + case 'LLAC': + switch (*(uint16_t *)(start += 4)) { + case 'OC': *endOut = start + 4; + return CALLCODE; + case 'AD': + *endOut = start + 8; switch (*(uint32_t *)(start += 4)) { - case 'HSAH': *endOut = start + 4; return BLOBHASH; - case 'ESAB': *endOut = start + 7; return BLOBBASEFEE; + case 'DAOL': return CALLDATALOAD; + case 'YPOC': return CALLDATACOPY; + case 'EZIS': return CALLDATASIZE; } - case 'COLB': *endOut = start + 9; return BLOCKHASH; - case 'ETYB': *endOut = start + 4; return BYTE; - case 'LLAC': - switch (*(uint16_t *)(start += 4)) { - case 'OC': *endOut = start + 4; return CALLCODE; - case 'AD': - *endOut = start + 8; - switch (*(uint32_t *)(start += 4)) { - case 'DAOL': return CALLDATALOAD; - case 'YPOC': return CALLDATACOPY; - case 'EZIS': return CALLDATASIZE; - } - case 'RE': *endOut = start + 2; return CALLER; - case 'AV': *endOut = start + 5; return CALLVALUE; + case 'RE': *endOut = start + 2; + return CALLER; + case 'AV': *endOut = start + 5; + return CALLVALUE; + } + *endOut = start; + return CALL; + case 'IAHC': + *endOut = start + 7; + return CHAINID; + case 'EDOC': + switch (*(uint32_t *)(start += 4)) { + case 'EZIS': *endOut = start + 4; + return CODESIZE; + case 'YPOC': *endOut = start + 4; + return CODECOPY; + } + case 'NIOC': *endOut = start + 8; + return COINBASE; + case 'AERC': + start += 5; + if ('2E' == *(uint16_t *)start) { + *endOut = start + 2; + return CREATE2; + } else { + *endOut = start + 1; + return CREATE; + } + case 'ELED': *endOut = start + 12; + return DELEGATECALL; + case '1PUD': + *endOut = start + 5; + switch (*(uint8_t *)(start += 4)) { + case '0': return DUP10; + case '1': return DUP11; + case '2': return DUP12; + case '3': return DUP13; + case '4': return DUP14; + case '5': return DUP15; + case '6': return DUP16; + } + *endOut = start; + return DUP1; + case '2PUD': *endOut = start + 4; + return DUP2; + case '3PUD': *endOut = start + 4; + return DUP3; + case '4PUD': *endOut = start + 4; + return DUP4; + case '5PUD': *endOut = start + 4; + return DUP5; + case '6PUD': *endOut = start + 4; + return DUP6; + case '7PUD': *endOut = start + 4; + return DUP7; + case '8PUD': *endOut = start + 4; + return DUP8; + case '9PUD': *endOut = start + 4; + return DUP9; + case 'PAWS': + *endOut = start + 5; + switch (*(uint8_t *)(start += 4)) { + case '2': return SWAP2; + case '3': return SWAP3; + case '4': return SWAP4; + case '5': return SWAP5; + case '6': return SWAP6; + case '7': return SWAP7; + case '8': return SWAP8; + case '9': return SWAP9; + case '1': + *endOut = start + 2; + switch (*(uint8_t *)(start += 1)) { + case '0': return SWAP10; + case '1': return SWAP11; + case '2': return SWAP12; + case '3': return SWAP13; + case '4': return SWAP14; + case '5': return SWAP15; + case '6': return SWAP16; } *endOut = start; - return CALL; - case 'IAHC': - *endOut = start + 7; - return CHAINID; - case 'EDOC': - switch (*(uint32_t *)(start += 4)) { - case 'EZIS': *endOut = start + 4; return CODESIZE; - case 'YPOC': *endOut = start + 4; return CODECOPY; - } - case 'NIOC': *endOut = start + 8; return COINBASE; - case 'AERC': - start += 5; - if ('2E' == *(uint16_t *)start) { - *endOut = start + 2; - return CREATE2; - } else { - *endOut = start + 1; - return CREATE; - } - case 'ELED': *endOut = start + 12; return DELEGATECALL; - case '1PUD': - *endOut = start + 5; - switch (*(uint8_t *)(start += 4)) { - case '0': return DUP10; - case '1': return DUP11; - case '2': return DUP12; - case '3': return DUP13; - case '4': return DUP14; - case '5': return DUP15; - case '6': return DUP16; + return SWAP1; + } + case 'CTXE': + switch (*(uint32_t *)(start += 4)) { + case 'CEDO': *endOut = start + 7; + return EXTCODECOPY; + case 'HEDO': *endOut = start + 7; + return EXTCODEHASH; + case 'SEDO': *endOut = start + 7; + return EXTCODESIZE; + } + case 'ESAB': + *endOut = start + 7; + return BASEFEE; + case 'ESSA': + *endOut = start + 11; + return (op_t)hexString16ToUint8(start + 9); + case 'LSAG': *endOut = start + 8; + return GASLIMIT; + case 'PSAG': *endOut = start + 8; + return GASPRICE; + case 'AVNI': *endOut = start + 7; + return INVALID; + case 'EZSI': *endOut = start + 6; + return ISZERO; + case 'PMUJ': + switch (*(uint8_t *)(start + 4)) { + case 'D': *endOut = start + 8; + return JUMPDEST; + case 'I': *endOut = start + 5; + return JUMPI; + } + *endOut = start + 4; + return JUMP; + case '0GOL': *endOut = start + 4; + return LOG0; + case '1GOL': *endOut = start + 4; + return LOG1; + case '2GOL': *endOut = start + 4; + return LOG2; + case '3GOL': *endOut = start + 4; + return LOG3; + case '4GOL': *endOut = start + 4; + return LOG4; + case 'AOLM': *endOut = start + 5; + return MLOAD; + case 'ZISM': *endOut = start + 5; + return MSIZE; + case 'POCM': *endOut = start + 5; + return MCOPY; + case 'AOLT': *endOut = start + 5; + return TLOAD; + case 'OTST': *endOut = start + 6; + return TSTORE; + case 'OTSM': + switch (*(uint8_t *)(start + 6)) { + case '8': *endOut = start + 7; + return MSTORE8; + } + *endOut = start + 6; + return MSTORE; + case 'MLUM': *endOut = start + 6; + return MULMOD; + case 'BMUN': *endOut = start + 6; + return NUMBER; + case 'GIRO': *endOut = start + 6; + return ORIGIN; + case 'VERP': *endOut = start + 10; + return PREVRANDAO; + case 'HSUP': + *endOut = start + 5; + switch (*(uint8_t *)(start + 4)) { + case '2': + *endOut = start + 6; + switch (*(uint8_t *)(start + 5)) { + case '0': return PUSH20; + case '1': return PUSH21; + case '2': return PUSH22; + case '3': return PUSH23; + case '4': return PUSH24; + case '5': return PUSH25; + case '6': return PUSH26; + case '7': return PUSH27; + case '8': return PUSH28; + case '9': return PUSH29; } - *endOut = start; return DUP1; - case '2PUD': *endOut = start + 4; return DUP2; - case '3PUD': *endOut = start + 4; return DUP3; - case '4PUD': *endOut = start + 4; return DUP4; - case '5PUD': *endOut = start + 4; return DUP5; - case '6PUD': *endOut = start + 4; return DUP6; - case '7PUD': *endOut = start + 4; return DUP7; - case '8PUD': *endOut = start + 4; return DUP8; - case '9PUD': *endOut = start + 4; return DUP9; - case 'PAWS': *endOut = start + 5; - switch (*(uint8_t *)(start += 4)) { - case '2': return SWAP2; - case '3': return SWAP3; - case '4': return SWAP4; - case '5': return SWAP5; - case '6': return SWAP6; - case '7': return SWAP7; - case '8': return SWAP8; - case '9': return SWAP9; - case '1': - *endOut = start + 2; - switch (*(uint8_t *)(start += 1)) { - case '0': return SWAP10; - case '1': return SWAP11; - case '2': return SWAP12; - case '3': return SWAP13; - case '4': return SWAP14; - case '5': return SWAP15; - case '6': return SWAP16; - } - *endOut = start; - return SWAP1; - } - case 'CTXE': - switch (*(uint32_t *)(start += 4)) { - case 'CEDO': *endOut = start + 7; return EXTCODECOPY; - case 'HEDO': *endOut = start + 7; return EXTCODEHASH; - case 'SEDO': *endOut = start + 7; return EXTCODESIZE; - } - case 'ESAB': - *endOut = start + 7; - return BASEFEE; - case 'ESSA': - *endOut = start + 11; - return (op_t)hexString16ToUint8(start + 9); - case 'LSAG': *endOut = start + 8; return GASLIMIT; - case 'PSAG': *endOut = start + 8; return GASPRICE; - case 'AVNI': *endOut = start + 7; return INVALID; - case 'EZSI': *endOut = start + 6; return ISZERO; - case 'PMUJ': - switch (*(uint8_t *)(start + 4)) { - case 'D': *endOut = start + 8; return JUMPDEST; - case 'I': *endOut = start + 5; return JUMPI; - } - *endOut = start + 4; - return JUMP; - case '0GOL': *endOut = start + 4; return LOG0; - case '1GOL': *endOut = start + 4; return LOG1; - case '2GOL': *endOut = start + 4; return LOG2; - case '3GOL': *endOut = start + 4; return LOG3; - case '4GOL': *endOut = start + 4; return LOG4; - case 'AOLM': *endOut = start + 5; return MLOAD; - case 'ZISM': *endOut = start + 5; return MSIZE; - case 'POCM': *endOut = start + 5; return MCOPY; - case 'AOLT': *endOut = start + 5; return TLOAD; - case 'OTST': *endOut = start + 6; return TSTORE; - case 'OTSM': - switch (*(uint8_t *)(start + 6)) { - case '8': *endOut = start + 7; return MSTORE8; - } + return PUSH2; + case '3': *endOut = start + 6; - return MSTORE; - case 'MLUM': *endOut = start + 6; return MULMOD; - case 'BMUN': *endOut = start + 6; return NUMBER; - case 'GIRO': *endOut = start + 6; return ORIGIN; - case 'VERP': *endOut = start + 10; return PREVRANDAO; - case 'HSUP': - *endOut = start + 5; - switch (*(uint8_t *)(start + 4)) { - case '2': - *endOut = start + 6; - switch (*(uint8_t *)(start + 5)) { - case '0': return PUSH20; - case '1': return PUSH21; - case '2': return PUSH22; - case '3': return PUSH23; - case '4': return PUSH24; - case '5': return PUSH25; - case '6': return PUSH26; - case '7': return PUSH27; - case '8': return PUSH28; - case '9': return PUSH29; - } - *endOut = start + 5; - return PUSH2; - case '3': - *endOut = start + 6; - switch (*(uint8_t *)(start + 5)) { - case '0': return PUSH30; - case '1': return PUSH31; - case '2': return PUSH32; - } - *endOut = start + 5; - return PUSH3; - case '0': return PUSH0; - case '4': return PUSH4; - case '5': return PUSH5; - case '6': return PUSH6; - case '7': return PUSH7; - case '8': return PUSH8; - case '9': return PUSH9; - case '1': - *endOut = start + 6; - switch (*(uint8_t *)(start + 5)) { - case '0': return PUSH10; - case '1': return PUSH11; - case '2': return PUSH12; - case '3': return PUSH13; - case '4': return PUSH14; - case '5': return PUSH15; - case '6': return PUSH16; - case '7': return PUSH17; - case '8': return PUSH18; - case '9': return PUSH19; - } - *endOut = start + 5; - return PUSH1; - } - case 'UTER': - *endOut = start + 14; - switch (*(uint32_t *)(start + 8)) { - case 'ISAT': return RETURNDATASIZE; - case 'OCAT': return RETURNDATACOPY; + switch (*(uint8_t *)(start + 5)) { + case '0': return PUSH30; + case '1': return PUSH31; + case '2': return PUSH32; } + *endOut = start + 5; + return PUSH3; + case '0': return PUSH0; + case '4': return PUSH4; + case '5': return PUSH5; + case '6': return PUSH6; + case '7': return PUSH7; + case '8': return PUSH8; + case '9': return PUSH9; + case '1': *endOut = start + 6; - return RETURN; - case 'EVER': *endOut = start + 6; return REVERT; - case 'FLES': - switch (*(uint32_t *)(start + 4)) { - case 'ALAB': *endOut = start + 11; return SELFBALANCE; - case 'TSED': *endOut = start + 12; return SELFDESTRUCT; + switch (*(uint8_t *)(start + 5)) { + case '0': return PUSH10; + case '1': return PUSH11; + case '2': return PUSH12; + case '3': return PUSH13; + case '4': return PUSH14; + case '5': return PUSH15; + case '6': return PUSH16; + case '7': return PUSH17; + case '8': return PUSH18; + case '9': return PUSH19; } - case 'NGIS': *endOut = start + 10; return SIGNEXTEND; - case 'VIDS': *endOut = start + 4; return SDIV; - case '3AHS': *endOut = start + 4; return SHA3; - case 'AOLS': *endOut = start + 5; return SLOAD; - case 'OTSS': *endOut = start + 6; return SSTORE; - case 'TATS': *endOut = start + 10; return STATICCALL; - case 'DOMS': *endOut = start + 4; return SMOD; - case 'POTS': *endOut = start + 4; return STOP; - case 'EMIT': *endOut = start + 9; return TIMESTAMP; + *endOut = start + 5; + return PUSH1; + } + case 'UTER': + *endOut = start + 14; + switch (*(uint32_t *)(start + 8)) { + case 'ISAT': return RETURNDATASIZE; + case 'OCAT': return RETURNDATACOPY; + } + *endOut = start + 6; + return RETURN; + case 'EVER': *endOut = start + 6; + return REVERT; + case 'FLES': + switch (*(uint32_t *)(start + 4)) { + case 'ALAB': *endOut = start + 11; + return SELFBALANCE; + case 'TSED': *endOut = start + 12; + return SELFDESTRUCT; + } + case 'NGIS': *endOut = start + 10; + return SIGNEXTEND; + case 'VIDS': *endOut = start + 4; + return SDIV; + case '3AHS': *endOut = start + 4; + return SHA3; + case 'AOLS': *endOut = start + 5; + return SLOAD; + case 'OTSS': *endOut = start + 6; + return SSTORE; + case 'TATS': *endOut = start + 10; + return STATICCALL; + case 'DOMS': *endOut = start + 4; + return SMOD; + case 'POTS': *endOut = start + 4; + return STOP; + case 'EMIT': *endOut = start + 9; + return TIMESTAMP; } *endOut = start + 3; switch ((*(uint32_t *)start) & 0x00ffffff) { - case 'DDA': return ADD; - case 'DNA': return AND; - case 'ZLC': return CLZ; - case 'VID': return DIV; - case 'PXE': return EXP; - case 'BUS': return SUB; - case 'ROX': return XOR; - case 'SAG': return GAS; - case 'DOM': return MOD; - case 'LHS': return SHL; - case 'RAS': return SAR; - case 'RHS': return SHR; - case 'LUM': return MUL; - case 'TON': return NOT; - case 'POP': return POP; - case 'TGS': return SGT; - case 'TLS': return SLT; + case 'DDA': return ADD; + case 'DNA': return AND; + case 'ZLC': return CLZ; + case 'VID': return DIV; + case 'PXE': return EXP; + case 'BUS': return SUB; + case 'ROX': return XOR; + case 'SAG': return GAS; + case 'DOM': return MOD; + case 'LHS': return SHL; + case 'RAS': return SAR; + case 'RHS': return SHR; + case 'LUM': return MUL; + case 'TON': return NOT; + case 'POP': return POP; + case 'TGS': return SGT; + case 'TLS': return SLT; } *endOut = start + 2; switch (*(uint16_t *)start) { - case 'QE': return EQ; - case 'TG': return GT; - case 'TL': return LT; - case 'RO': return OR; - case 'CP': return PC; + case 'QE': return EQ; + case 'TG': return GT; + case 'TL': return LT; + case 'RO': return OR; + case 'CP': return PC; } fputs("Unknown op: ", stderr); fputs(start, stderr); diff --git a/src/precompiles.c b/src/precompiles.c index e259b3c..882dec4 100644 --- a/src/precompiles.c +++ b/src/precompiles.c @@ -9,9 +9,9 @@ const char *precompileName[KNOWN_PRECOMPILES] = { int PrecompileIsSupported(precompile_t precompile) { switch (precompile) { #define PRECOMPILE(name,address,supported) case name: return supported; - PRECOMPILES + PRECOMPILES #undef PRECOMPILE - default: - return 0; + default: + return 0; } } diff --git a/src/scan.c b/src/scan.c index 90083a7..4638312 100644 --- a/src/scan.c +++ b/src/scan.c @@ -12,18 +12,18 @@ static inline int shouldIgnore(char ch) { return ch != '(' - && ch != ')' - && ch != ',' - && ch != ':' - && ch != '/' - && ch != '"' - && ch != '-' - && ch != '{' - && ch != '}' - && ch != '#' - && (ch < '0' || ch > '9') - && (ch < 'A' || ch > 'Z') - && (ch < 'a' || ch > 'z') + && ch != ')' + && ch != ',' + && ch != ':' + && ch != '/' + && ch != '"' + && ch != '-' + && ch != '{' + && ch != '}' + && ch != '#' + && (ch < '0' || ch > '9') + && (ch < 'A' || ch > 'Z') + && (ch < 'a' || ch > 'z') ; } @@ -60,7 +60,9 @@ static int isAssemble(const char *iter) { static op_t parseHex(const char **iter) { const char *start = *iter; - while (isHex(**iter)) ++(*iter); + while (isHex(**iter)) { + ++(*iter); + } uint8_t words = 0; const char *end = *iter; while (end > start) { @@ -89,7 +91,7 @@ op_t parseDecimal(const char **iter, int negative) { uint64_t words[4] = {0,0,0,0}; while (isDecimal(**iter)) { // multiply number by 10 - for (uint8_t i = 4; i --> 0;) { + for (uint8_t i = 4; i--> 0;) { // long multiplication uint64_t s0, s1, s2, s3; @@ -114,7 +116,9 @@ op_t parseDecimal(const char **iter, int negative) { words[j] += carry; if (carry > words[j]) { carry = 1; - } else break; + } else { + break; + } } } uint8_t digit = *((*iter)++) - '0'; @@ -123,16 +127,20 @@ op_t parseDecimal(const char **iter, int negative) { words[i] += digit; if (digit > words[i]) { digit = 1; - } else break; + } else { + break; + } } } if (negative) { // negate via -x = ~x + 1 - for (uint8_t i = 4; i --> 0;) { + for (uint8_t i = 4; i--> 0;) { words[i] = ~words[i]; } // add 1 with carry - for (uint8_t i = 0; !++words[i++];); + for (uint8_t i = 0; !++words[i++];) { + ; + } } uint64_t isNonzero = words[0] | words[1] | words[2] | words[3]; if (!isNonzero) { @@ -140,8 +148,8 @@ op_t parseDecimal(const char **iter, int negative) { } uint8_t start = 0; // determine start - for (uint8_t i = 4; i --> 0;) { - for (uint8_t j = 8; j --> 0;) { + for (uint8_t i = 4; i--> 0;) { + for (uint8_t j = 8; j--> 0;) { uint64_t shift = j * 8; uint8_t byte = (words[i] & (0xffllu << shift)) >> shift; if (byte) { @@ -204,22 +212,26 @@ static void scanChar(const char **iter, char expected) { static inline int isPathChar(char ch) { return ch == '/' - || ch == '-' - || ch == '_' - || ch == '.' - || (ch >= '0' && ch <= '9') - || (ch >= 'A' && ch <= 'Z') - || (ch >= 'a' && ch <= 'z') + || ch == '-' + || ch == '_' + || ch == '.' + || (ch >= '0' && ch <= '9') + || (ch >= 'A' && ch <= 'Z') + || (ch >= 'a' && ch <= 'z') ; } static void scanPath(const char **iter) { // TODO: Support unsafe characters with escape (\) - while (isPathChar(**iter)) (*iter)++; + while (isPathChar(**iter)) { + (*iter)++; + } } static void scanComment(const char **iter) { - for (char ch; (ch = **iter) != '\n'; (*iter)++); + for (char ch; (ch = **iter) != '\n'; (*iter)++) { + ; + } lineNumber++; (*iter)++; } @@ -254,7 +266,9 @@ static inline char scanWaste(const char **iter) { static void scanLabel(const char **iter) { const char *start = *iter; - for (char ch; isLowerCase(**iter); (*iter)++); + for (char ch; isLowerCase(**iter); (*iter)++) { + ; + } const char *end = *iter; char next = scanWaste(iter); if (next == ':') { @@ -277,7 +291,9 @@ static void scanDataSection(const char **iter) { fprintf(stderr, "Data section keys should be lowercase; instead found unexpected character %c at line %u\n", *start, lineNumber); exit(1); } - for (char ch; isLowerCase(**iter); (*iter)++); + for (char ch; isLowerCase(**iter); (*iter)++) { + ; + } const char *end = *iter; char next = scanWaste(iter); if (next != ':') { @@ -353,7 +369,9 @@ static void scanDataLen(const char **iter) { if (!isLowerCase(*start)) { fprintf(stderr, "Data section #keys should be lowercase; instead found unexpected character %c at line %u\n", *start, lineNumber); } - for (char ch; isLowerCase(**iter); (*iter)++); + for (char ch; isLowerCase(**iter); (*iter)++) { + ; + } const char *end = *iter; scanstackPushLabel(start, end - start, CODESIZE); @@ -364,11 +382,11 @@ static void scanDataLen(const char **iter) { static int tryParsePrecompile(const char **iter, uint8_t *addr) { #define PRECOMPILE(name, address, supported) \ - if (strncmp(*iter, #name, sizeof(#name) - 1) == 0) { \ - *addr = address; \ - *iter += sizeof(#name) - 1; \ - return 1; \ - } + if (strncmp(*iter, #name, sizeof(#name) - 1) == 0) { \ + *addr = address; \ + *iter += sizeof(#name) - 1; \ + return 1; \ + } PRECOMPILES #undef PRECOMPILE return 0; @@ -476,7 +494,9 @@ op_t scanNextOp(const char **iter) { labelQueuePush(jump, type); return type; } - } else return scanstackPop(); + } else { + return scanstackPop(); + } } static void shiftProgram(op_t* begin, uint32_t *programLength, uint32_t offset, uint32_t amount) { diff --git a/src/uint256.c b/src/uint256.c index dd51346..1dcbe43 100644 --- a/src/uint256.c +++ b/src/uint256.c @@ -1,19 +1,19 @@ /******************************************************************************* -* Ledger Ethereum App -* (c) 2016-2019 Ledger -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -********************************************************************************/ + * Ledger Ethereum App + * (c) 2016-2019 Ledger + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + ********************************************************************************/ // Adapted from https://github.com/calccrypto/uint256_t @@ -259,8 +259,12 @@ void shiftr512(const uint512_t *number, uint32_t value, uint512_t *target) { void shiftar256(const uint256_t *number, uint32_t value, uint256_t *target) { bool positive = (UPPER(UPPER_P(number)) < 0x8000000000000000); shiftr256(number, value, target); - if (positive) return; - if (!value) return; + if (positive) { + return; + } + if (!value) { + return; + } if (value >= 64) { UPPER(UPPER_P(target)) = 0xffffffffffffffffllu; if (value >= 128) { @@ -320,12 +324,29 @@ uint32_t bits512(const uint512_t *number) { static uint64_t clz64(uint64_t number) { // binary search uint64_t zeros = 0; - if (!(number & 0xFFFFFFFF00000000)) { zeros += 32; number <<= 32; } - if (!(number & 0xFFFF000000000000)) { zeros += 16; number <<= 16; } - if (!(number & 0xFF00000000000000)) { zeros += 8; number <<= 8; } - if (!(number & 0xF000000000000000)) { zeros += 4; number <<= 4; } - if (!(number & 0xC000000000000000)) { zeros += 2; number <<= 2; } - if (!(number & 0x8000000000000000)) { zeros += 1; } + if (!(number & 0xFFFFFFFF00000000)) { + zeros += 32; + number <<= 32; + } + if (!(number & 0xFFFF000000000000)) { + zeros += 16; + number <<= 16; + } + if (!(number & 0xFF00000000000000)) { + zeros += 8; + number <<= 8; + } + if (!(number & 0xF000000000000000)) { + zeros += 4; + number <<= 4; + } + if (!(number & 0xC000000000000000)) { + zeros += 2; + number <<= 2; + } + if (!(number & 0x8000000000000000)) { + zeros += 1; + } return zeros; } @@ -514,16 +535,20 @@ void not256(const uint256_t *number, uint256_t *target) { } void mul128(const uint128_t *number1, const uint128_t *number2, uint128_t *target) { - uint64_t top[4] = {UPPER_P(number1) >> 32, UPPER_P(number1) & 0xffffffff, - LOWER_P(number1) >> 32, LOWER_P(number1) & 0xffffffff}; - uint64_t bottom[4] = {UPPER_P(number2) >> 32, UPPER_P(number2) & 0xffffffff, - LOWER_P(number2) >> 32, - LOWER_P(number2) & 0xffffffff}; + uint64_t top[4] = { + UPPER_P(number1) >> 32, UPPER_P(number1) & 0xffffffff, + LOWER_P(number1) >> 32, LOWER_P(number1) & 0xffffffff + }; + uint64_t bottom[4] = { + UPPER_P(number2) >> 32, UPPER_P(number2) & 0xffffffff, + LOWER_P(number2) >> 32, + LOWER_P(number2) & 0xffffffff + }; uint64_t products[4][4]; uint128_t tmp, tmp2; - for (uint8_t y = 4; y --> 0;) { - for (uint8_t x = 4; x --> 0;) { + for (uint8_t y = 4; y--> 0;) { + for (uint8_t x = 4; x--> 0;) { products[3 - x][y] = top[x] * bottom[y]; } } @@ -576,8 +601,8 @@ void mul256(const uint256_t *number1, const uint256_t *number2, uint256_t *targe LOWER(bottom[3]) = LOWER(LOWER_P(number2)); uint128_t products[4][4]; - for (uint8_t y = 4; y --> 0;) { - for (uint8_t x = 4; x --> 0;) { + for (uint8_t y = 4; y--> 0;) { + for (uint8_t x = 4; x--> 0;) { mul128(&top[x], &bottom[y], &products[x][y]); } } @@ -667,8 +692,8 @@ void mul512(const uint512_t *number1, const uint512_t *number2, uint512_t *targe copy128(&LOWER(bottom[3]), &LOWER(LOWER_P(number2))); uint256_t products[4][4]; - for (uint8_t y = 4; y --> 0;) { - for (uint8_t x = 4; x --> 0;) { + for (uint8_t y = 4; y--> 0;) { + for (uint8_t x = 4; x--> 0;) { mul256(&top[x], &bottom[y], &products[x][y]); } } diff --git a/tst/dio.c b/tst/dio.c index 37a6fcc..c3d09fc 100644 --- a/tst/dio.c +++ b/tst/dio.c @@ -8,11 +8,11 @@ void test_applyConfig_code() { evmInit(); const char config[] = "[" - "{" - "\"address\":\"0x80d9b122dc3a16fdc41f96cf010ffe7e38d227c3\"," - "\"code\":\"0x383d3d39383df3\"" - "}" - "]"; + "{" + "\"address\":\"0x80d9b122dc3a16fdc41f96cf010ffe7e38d227c3\"," + "\"code\":\"0x383d3d39383df3\"" + "}" + "]"; applyConfig(config); uint64_t gas = 21019; @@ -27,8 +27,8 @@ void test_applyConfig_code() { result_t result = txCall(from, gas, to, val, input, NULL); op_t expected[] = { - CODESIZE, RETURNDATASIZE, RETURNDATASIZE, CODECOPY, - CODESIZE, RETURNDATASIZE, RETURN + CODESIZE, RETURNDATASIZE, RETURNDATASIZE, CODECOPY, + CODESIZE, RETURNDATASIZE, RETURN }; assert(result.returnData.size == sizeof(expected)); assert(memcmp(expected, result.returnData.content, result.returnData.size) == 0); @@ -41,14 +41,14 @@ void test_applyConfig_storage() { evmInit(); const char config[] = "[" - "{" - "\"address\":\"0x80d9b122dc3a16fdc41f96cf010ffe7e38d227c3\"," - "\"code\":\"0x5f545f52595ff3\"," - "\"storage\":{" - "\"0x00\": \"0x12340000567800009abc0000def0\"" - "}" - "}" - "]"; + "{" + "\"address\":\"0x80d9b122dc3a16fdc41f96cf010ffe7e38d227c3\"," + "\"code\":\"0x5f545f52595ff3\"," + "\"storage\":{" + "\"0x00\": \"0x12340000567800009abc0000def0\"" + "}" + "}" + "]"; applyConfig(config); uint64_t gas = 23114; @@ -80,12 +80,12 @@ void test_applyConfig_balance() { evmInit(); const char config[] = "[" - "{" - "\"address\":\"0x80d9b122dc3a16fdc41f96cf010ffe7e38d227c3\"," - "\"code\":\"0x475f52595ff3\"," - "\"balance\":\"0x1234005678009abc00def0\"" - "}" - "]"; + "{" + "\"address\":\"0x80d9b122dc3a16fdc41f96cf010ffe7e38d227c3\"," + "\"code\":\"0x475f52595ff3\"," + "\"balance\":\"0x1234005678009abc00def0\"" + "}" + "]"; applyConfig(config); uint64_t gas = 21017; @@ -116,12 +116,12 @@ void test_applyConfig_construct() { evmInit(); const char config[] = "[" - "{" - "\"address\":\"0x80d9b122dc3a16fdc41f96cf010ffe7e38d227c3\"," - "\"construct\":\"tst/in/quine.evm\"," - "\"code\":\"0x383d3d39383df3\"" - "}" - "]"; + "{" + "\"address\":\"0x80d9b122dc3a16fdc41f96cf010ffe7e38d227c3\"," + "\"construct\":\"tst/in/quine.evm\"," + "\"code\":\"0x383d3d39383df3\"" + "}" + "]"; applyConfig(config); uint64_t gas = 0x521b; @@ -150,13 +150,13 @@ void test_applyConfig_constructTest() { evmInit(); const char config[] = "[" - "{" - "\"address\":\"0x80d9b122dc3a16fdc41f96cf010ffe7e38d227c3\"," - "\"construct\":\"tst/in/quine.evm\"," - "\"code\":\"0x383d3d39383df3\"," - "\"constructTest\":{}" - "}" - "]"; + "{" + "\"address\":\"0x80d9b122dc3a16fdc41f96cf010ffe7e38d227c3\"," + "\"construct\":\"tst/in/quine.evm\"," + "\"code\":\"0x383d3d39383df3\"," + "\"constructTest\":{}" + "}" + "]"; applyConfig(config); uint64_t gas = 0x521b; @@ -184,29 +184,29 @@ void test_applyConfig_tests() { evmInit(); const char config[] = "[" - "{" - "\"address\":\"0x80d9b122dc3a16fdc41f96cf010ffe7e38d227c3\"," - "\"code\":\"0x60213610600e576020355f3555005b5f35545f52595ff3\"," - "\"tests\":" - "[" - "{" - "\"op\": \"STATICCALL\"," - "\"input\": \"0x0000000000000000000000000000000000000000000000000000000000000000\"," - "\"output\": \"0x0000000000000000000000000000000000000000000000000000000000000000\"" - "}," - "{" - "\"op\": \"CALL\"," - "\"input\": \"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001\"," - "\"output\": \"0x\"" - "}," - "{" - "\"op\": \"STATICCALL\"," - "\"input\": \"0x0000000000000000000000000000000000000000000000000000000000000000\"," - "\"output\": \"0x0000000000000000000000000000000000000000000000000000000000000001\"" - "}" - "]" - "}" - "]"; + "{" + "\"address\":\"0x80d9b122dc3a16fdc41f96cf010ffe7e38d227c3\"," + "\"code\":\"0x60213610600e576020355f3555005b5f35545f52595ff3\"," + "\"tests\":" + "[" + "{" + "\"op\": \"STATICCALL\"," + "\"input\": \"0x0000000000000000000000000000000000000000000000000000000000000000\"," + "\"output\": \"0x0000000000000000000000000000000000000000000000000000000000000000\"" + "}," + "{" + "\"op\": \"CALL\"," + "\"input\": \"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001\"," + "\"output\": \"0x\"" + "}," + "{" + "\"op\": \"STATICCALL\"," + "\"input\": \"0x0000000000000000000000000000000000000000000000000000000000000000\"," + "\"output\": \"0x0000000000000000000000000000000000000000000000000000000000000001\"" + "}" + "]" + "}" + "]"; applyConfig(config); uint64_t gas = 0x5a63; diff --git a/tst/evm.c b/tst/evm.c index 7625a4b..0b492c7 100644 --- a/tst/evm.c +++ b/tst/evm.c @@ -7,42 +7,42 @@ #include "ops.h" #include "evm.h" -#define assertStderr(expectedErr, statement)\ - int rw[2];\ - pipe(rw);\ - int savedStderr = dup(2);\ - close(2);\ - dup2(rw[1], 2);\ - close(rw[1]);\ - statement;\ - close(2);\ - dup2(savedStderr, 2);\ - clearerr(stderr);\ - close(savedStderr);\ - size_t strSize = strlen(expectedErr) + 1;\ - char *actualErr = malloc(strSize);\ - ssize_t red = read(rw[0], actualErr, strSize);\ - if (red == -1) {\ - perror("read");\ - exit(1);\ - }\ - actualErr[red] = 0;\ - if (red != strSize - 1) {\ - fprintf(stderr, "stderr length mismatch\nexpected[%zu]: \"%s\"\nactual[%zd]: \"%s\"\n", strSize, expectedErr, red, actualErr);\ - exit(1);\ - }\ - close(rw[0]);\ - if (memcmp(expectedErr, actualErr, strSize) != 0) {\ - fprintf(stderr, "stderr mismatch\nexpected[%zu]: \"%s\"\nactual[%zd]: \"%s\"\n", strSize, expectedErr, red, actualErr);\ - exit(1);\ - } +#define assertStderr(expectedErr, statement) \ + int rw[2]; \ + pipe(rw); \ + int savedStderr = dup(2); \ + close(2); \ + dup2(rw[1], 2); \ + close(rw[1]); \ + statement; \ + close(2); \ + dup2(savedStderr, 2); \ + clearerr(stderr); \ + close(savedStderr); \ + size_t strSize = strlen(expectedErr) + 1; \ + char *actualErr = malloc(strSize); \ + ssize_t red = read(rw[0], actualErr, strSize); \ + if (red == -1) { \ + perror("read"); \ + exit(1); \ + } \ + actualErr[red] = 0; \ + if (red != strSize - 1) { \ + fprintf(stderr, "stderr length mismatch\nexpected[%zu]: \"%s\"\nactual[%zd]: \"%s\"\n", strSize, expectedErr, red, actualErr); \ + exit(1); \ + } \ + close(rw[0]); \ + if (memcmp(expectedErr, actualErr, strSize) != 0) { \ + fprintf(stderr, "stderr mismatch\nexpected[%zu]: \"%s\"\nactual[%zd]: \"%s\"\n", strSize, expectedErr, red, actualErr); \ + exit(1); \ + } -#define assertFailedInvalid(result)\ - assert(UPPER(UPPER(result.status)) == 0);\ - assert(LOWER(UPPER(result.status)) == 0);\ - assert(UPPER(LOWER(result.status)) == 0);\ - assert(LOWER(LOWER(result.status)) == 0);\ - assert(result.gasRemaining == 0) +#define assertFailedInvalid(result) \ + assert(UPPER(UPPER(result.status)) == 0); \ + assert(LOWER(UPPER(result.status)) == 0); \ + assert(UPPER(LOWER(result.status)) == 0); \ + assert(LOWER(LOWER(result.status)) == 0); \ + assert(result.gasRemaining == 0) void test_stop() { evmInit(); @@ -1302,10 +1302,10 @@ void test_extcodecopy() { gas = 57035; // 385952385f59395f353b5f595f353c595ff3 #define PROGRAM_EXTCODECOPY \ - CODESIZE, MSIZE, MSTORE, \ - CODESIZE, PUSH0, MSIZE, CODECOPY, \ - PUSH0, CALLDATALOAD, EXTCODESIZE, PUSH0, MSIZE, PUSH0, CALLDATALOAD, EXTCODECOPY, \ - MSIZE, PUSH0, RETURN + CODESIZE, MSIZE, MSTORE, \ + CODESIZE, PUSH0, MSIZE, CODECOPY, \ + PUSH0, CALLDATALOAD, EXTCODESIZE, PUSH0, MSIZE, PUSH0, CALLDATALOAD, EXTCODECOPY, \ + MSIZE, PUSH0, RETURN op_t extcodecopy[] = { PROGRAM_EXTCODECOPY }; @@ -1387,20 +1387,20 @@ void test_deepCall() { evmInit(); // 3d3580600757005b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01805952590259595f34305af1603c57595ffd5b595ff3 #define PROGRAM_DIVE \ - RETURNDATASIZE, CALLDATALOAD, \ - DUP1, PUSH1, 0x07, JUMPI, STOP, JUMPDEST, \ - PUSH32, \ - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, \ - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, \ - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, \ - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, \ - ADD, \ - DUP1, MSIZE, MSTORE, \ - MSIZE, MUL, MSIZE, MSIZE, PUSH0, CALLVALUE, ADDRESS, GAS, CALL, \ - PUSH1, 60, JUMPI, \ - MSIZE, PUSH0, REVERT, \ - JUMPDEST, \ - MSIZE, PUSH0, RETURN + RETURNDATASIZE, CALLDATALOAD, \ + DUP1, PUSH1, 0x07, JUMPI, STOP, JUMPDEST, \ + PUSH32, \ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, \ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, \ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, \ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, \ + ADD, \ + DUP1, MSIZE, MSTORE, \ + MSIZE, MUL, MSIZE, MSIZE, PUSH0, CALLVALUE, ADDRESS, GAS, CALL, \ + PUSH1, 60, JUMPI, \ + MSIZE, PUSH0, REVERT, \ + JUMPDEST, \ + MSIZE, PUSH0, RETURN op_t dive[] = { PROGRAM_DIVE @@ -2087,18 +2087,18 @@ void test_create() { // 345ff3 #define STOP_CALLVALUE_CONSTRUCTOR \ - CALLVALUE, PUSH0, RETURN + CALLVALUE, PUSH0, RETURN // 62345ff359526003601d6001f08059523b595234595247595230315952595ffd #define CREATE_REVERT \ - PUSH3, STOP_CALLVALUE_CONSTRUCTOR, MSIZE, MSTORE, \ - PUSH1, 0x03, PUSH1, 0x1d, PUSH1, 0x01, CREATE, \ - DUP1, MSIZE, MSTORE, \ - EXTCODESIZE, MSIZE, MSTORE, \ - CALLVALUE, MSIZE, MSTORE, \ - SELFBALANCE, MSIZE, MSTORE, \ - ADDRESS, BALANCE, MSIZE, MSTORE, \ - MSIZE, PUSH0, REVERT + PUSH3, STOP_CALLVALUE_CONSTRUCTOR, MSIZE, MSTORE, \ + PUSH1, 0x03, PUSH1, 0x1d, PUSH1, 0x01, CREATE, \ + DUP1, MSIZE, MSTORE, \ + EXTCODESIZE, MSIZE, MSTORE, \ + CALLVALUE, MSIZE, MSTORE, \ + SELFBALANCE, MSIZE, MSTORE, \ + ADDRESS, BALANCE, MSIZE, MSTORE, \ + MSIZE, PUSH0, REVERT op_t createRevert[] = { CREATE_REVERT @@ -2215,9 +2215,9 @@ void test_createOutOfGas() { // 385f5f39385f5ff0385ff3 #define PROGRAM_CREATE_OUT_OF_GAS \ - CODESIZE, PUSH0, PUSH0, CODECOPY, \ - CODESIZE, PUSH0, PUSH0, CREATE, \ - CODESIZE, PUSH0, RETURN + CODESIZE, PUSH0, PUSH0, CODECOPY, \ + CODESIZE, PUSH0, PUSH0, CREATE, \ + CODESIZE, PUSH0, RETURN op_t recursiveOOG[] = { PROGRAM_CREATE_OUT_OF_GAS @@ -2263,7 +2263,9 @@ void test_create2() { uint64_t gas = 1000000; val_t value; data_t empty = {0, NULL}; - value[0] = 0; value[1] = 0; value[2] = 0; + value[0] = 0; + value[1] = 0; + value[2] = 0; empty.size = 0; op_t code[] = { @@ -2297,7 +2299,9 @@ void test_create2InsufficientBalance() { uint64_t gas = 1000000; val_t value; data_t input = {0, NULL}; - value[0] = 0; value[1] = 0; value[2] = 0; + value[0] = 0; + value[1] = 0; + value[2] = 0; input.size = 0; op_t code[] = { @@ -2343,8 +2347,8 @@ void test_returnDataCopyOOB() { evmMockCode(inner_addr, inner_data); #define INNER_ADDR \ - 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, \ - 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc + 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, \ + 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc op_t outer[] = { PUSH0, PUSH0, PUSH0, PUSH0, PUSH0, PUSH20, INNER_ADDR, GAS, CALL, PUSH1, 5, PUSH1, 6, PUSH0, RETURNDATACOPY, From 465644498f5724a7fe9d3c9f589e49c6ee2fc615 Mon Sep 17 00:00:00 2001 From: William Morriss Date: Tue, 26 May 2026 09:39:43 -0500 Subject: [PATCH 5/5] style: fprintAddress linebreak --- include/address.h | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/include/address.h b/include/address.h index cebacf7..4b9c442 100644 --- a/include/address.h +++ b/include/address.h @@ -101,10 +101,11 @@ static inline void AddressToUint256(uint256_t *dst, address_t *src) { ); } -#define fprintAddress(file, addr) fprintf(file, "0x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x", \ - addr.address[0], addr.address[1], addr.address[2], addr.address[3], addr.address[4], addr.address[5], addr.address[6], addr.address[7], addr.address[8], addr.address[9], addr.address[10], \ - addr.address[11], addr.address[12], addr.address[13], addr.address[14], addr.address[15], addr.address[16], addr.address[17], addr.address[18], addr.address[19] \ -) +#define fprintAddress(file, addr) \ + fprintf(file, "0x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x", \ + addr.address[0], addr.address[1], addr.address[2], addr.address[3], addr.address[4], addr.address[5], addr.address[6], addr.address[7], addr.address[8], addr.address[9], addr.address[10], \ + addr.address[11], addr.address[12], addr.address[13], addr.address[14], addr.address[15], addr.address[16], addr.address[17], addr.address[18], addr.address[19] \ + ) static inline int AddressIsPrecompile(const address_t address) {