diff --git a/.github/workflows/main.yaml b/.github/workflows/main.yaml index a02bb7d7..ad2c002b 100644 --- a/.github/workflows/main.yaml +++ b/.github/workflows/main.yaml @@ -6,7 +6,7 @@ name: Test executor inputs on: workflow_dispatch: pull_request: - branches: [main, develop] + branches: [main, develop, develop-etrog, feature/fork-etrog, feature/l1-info-tree] jobs: build: diff --git a/.gitignore b/.gitignore index 6b7d518d..e9602ef7 100644 --- a/.gitignore +++ b/.gitignore @@ -75,3 +75,5 @@ tools/parallel-tests .vscode/launch.json + +.vscode/settings.json diff --git a/counters/counters-executor.js b/counters/counters-executor.js index a72d65eb..a1213669 100644 --- a/counters/counters-executor.js +++ b/counters/counters-executor.js @@ -1,18 +1,23 @@ +/* eslint-disable import/no-extraneous-dependencies */ +/* eslint-disable no-use-before-define */ +/* eslint-disable no-restricted-syntax */ const path = require('path'); const fs = require('fs'); const smMain = require('@0xpolygonhermez/zkevm-proverjs/src/sm/sm_main/sm_main'); + const fileCachePil = path.join(__dirname, '../node_modules/@0xpolygonhermez/zkevm-proverjs/cache-main-pil.json'); -const empty_input = require('@0xpolygonhermez/zkevm-proverjs/test/inputs/empty_input.json') +const emptyInput = require('@0xpolygonhermez/zkevm-proverjs/test/inputs/empty_input.json'); const buildPoseidon = require('@0xpolygonhermez/zkevm-commonjs').getPoseidon; + const pathMainPil = path.join(__dirname, '../node_modules/@0xpolygonhermez/zkevm-proverjs/pil/main.pil'); const { newCommitPolsArray } = require('pilcom'); const { compile } = require('pilcom'); -const zkasm = require("@0xpolygonhermez/zkasmcom"); +const zkasm = require('@0xpolygonhermez/zkasmcom'); + const testFilesDir = path.join(__dirname, './tests'); const { argv } = require('yargs'); async function main() { - // Compile pil const cmPols = await compilePil(); @@ -20,8 +25,8 @@ async function main() { const files = getTestFiles(); // Run all zkasm files - for (let file of files) { - await runTest(file, cmPols) + for (const file of files) { + await runTest(file, cmPols); } } @@ -30,27 +35,28 @@ async function runTest(testName, cmPols) { // Compile rom const configZkasm = { defines: [], - allowUndefinedLabels: true + allowUndefinedLabels: true, }; const rom = await zkasm.compile(zkasmFile, null, configZkasm); const config = { debug: true, stepsN: 8388608, - } - console.log(`Running ${testName}`) + }; + console.log(`Running ${testName}`); // Execute test - const res = await smMain.execute(cmPols.Main, empty_input, rom, config); - console.log(res.counters) + const res = await smMain.execute(cmPols.Main, emptyInput, rom, config); + console.log(res.counters); } // Get all zkasm counter test files function getTestFiles() { - if(argv.test){ - return [`${argv.test}.zkasm`] + if (argv.test) { + return [`${argv.test}.zkasm`]; } - const files = fs.readdirSync(testFilesDir).filter(name => name.endsWith('.zkasm')) - return files + const files = fs.readdirSync(testFilesDir).filter((name) => name.endsWith('.zkasm')); + + return files; } async function compilePil() { @@ -60,14 +66,15 @@ async function compilePil() { const pilConfig = { defines: { N: 4096 }, namespaces: ['Main', 'Global'], - disableUnusedError: true + disableUnusedError: true, }; const p = await compile(F, pathMainPil, null, pilConfig); fs.writeFileSync(fileCachePil, `${JSON.stringify(p, null, 1)}\n`, 'utf8'); } const pil = JSON.parse(fs.readFileSync(fileCachePil)); + return newCommitPolsArray(pil); } -main() \ No newline at end of file +main(); diff --git a/counters/countersConstants.zkasm b/counters/countersConstants.zkasm index 5712a24c..7e72db47 100644 --- a/counters/countersConstants.zkasm +++ b/counters/countersConstants.zkasm @@ -233,7 +233,7 @@ CONST %OPCODECOPY_CNT_PADDING_PG = 0 CONST %OPCODECOPY_CNT_POSEIDON_G = 0 ; opEXTCODECOPY - COMPLEX - hardcoded values at test CONST %OPEXTCODECOPY_STEP = 2000 -CONST %OPEXTCODECOPY_CNT_BINARY = 105 +CONST %OPEXTCODECOPY_CNT_BINARY = 104 CONST %OPEXTCODECOPY_CNT_ARITH = 4 CONST %OPEXTCODECOPY_CNT_KECCAK_F = 0 CONST %OPEXTCODECOPY_CNT_MEM_ALIGN = 43 @@ -248,8 +248,8 @@ CONST %OPCREATE_CNT_MEM_ALIGN = 0 CONST %OPCREATE_CNT_PADDING_PG = 0 CONST %OPCREATE_CNT_POSEIDON_G = 23 ; opCREATE2 - COMPLEX - hardcoded values at test -CONST %OPCREATE2_STEP = 500 -CONST %OPCREATE2_CNT_BINARY = 22 +CONST %OPCREATE2_STEP = 400 +CONST %OPCREATE2_CNT_BINARY = 21 CONST %OPCREATE2_CNT_ARITH = 2 CONST %OPCREATE2_CNT_KECCAK_F = 0 CONST %OPCREATE2_CNT_MEM_ALIGN = 0 diff --git a/counters/endIncludes.zkasm b/counters/endIncludes.zkasm index aea4e436..c7e4d263 100644 --- a/counters/endIncludes.zkasm +++ b/counters/endIncludes.zkasm @@ -1,5 +1,5 @@ INCLUDE "../main/load-tx-rlp-utils.zkasm" -INCLUDE "../main/2-exp.zkasm" +INCLUDE "../main/tables/2-exp.zkasm" INCLUDE "../main/vars.zkasm" INCLUDE "../main/utils.zkasm" INCLUDE "../main/opcodes/calldata-returndata-code.zkasm" @@ -14,4 +14,5 @@ INCLUDE "../main/opcodes/logs.zkasm" INCLUDE "../main/opcodes/stack-operations.zkasm" INCLUDE "../main/opcodes/storage-memory.zkasm" INCLUDE "../main/touched.zkasm" -INCLUDE "../main/end.zkasm" \ No newline at end of file +INCLUDE "../main/end.zkasm" +INCLUDE "../main/block-info.zkasm" \ No newline at end of file diff --git a/counters/tests/opBLOCKHASH.zkasm b/counters/tests/opBLOCKHASH.zkasm index f534d4e0..0679c951 100644 --- a/counters/tests/opBLOCKHASH.zkasm +++ b/counters/tests/opBLOCKHASH.zkasm @@ -5,7 +5,7 @@ start: operation: 2 :HASHK1(0) - 10 :MSTORE(txCount) + 10 :MSTORE(blockNum) 1 :MSTORE(SP++) :JMP(opBLOCKHASH) checkCounters: diff --git a/main/block-info.zkasm b/main/block-info.zkasm new file mode 100644 index 00000000..4fa3e22a --- /dev/null +++ b/main/block-info.zkasm @@ -0,0 +1,204 @@ +VAR GLOBAL tmpSR +VAR GLOBAL currentLogIndex + +initBlockInfoTree: + 0 :MSTORE(blockInfoSR), RETURN + +; @info Save blockInfo root when a new context is created +checkpointBlockInfoTree: + $ => B :MLOAD(currentLogIndex) + B :MSTORE(initLogIndex) + $ => B :MLOAD(blockInfoSR) + B :MSTORE(initBlockInfoSR), RETURN + +; @info Back to initial blockInfo root +revertBlockInfoTree: + $ => A :MLOAD(initLogIndex) + A :MSTORE(currentLogIndex) + $ => A :MLOAD(initBlockInfoSR) + A :MSTORE(blockInfoSR), RETURN + +; @info Fill Block Info tree with initial block values +setupNewBlockInfoTree: + ; checks zk-counters + %MAX_CNT_STEPS - STEP - 50 :JMPN(outOfCountersStep) + %MAX_CNT_POSEIDON_G - CNT_POSEIDON_G - %MAX_CNT_POSEIDON_SLOAD_SSTORE*7 :JMPN(outOfCountersPoseidon) + %MAX_CNT_BINARY - CNT_BINARY - 7 :JMPN(outOfCountersBinary) + + ; save current state root & load block info root + SR :MSTORE(tmpSR) + $ => SR :MLOAD(blockInfoSR) + + ; Insert previous block hash + ; key: H([blockHeaderParams[0:4], blockHeaderParams[4:8], blockHeaderParams[8:12], blockHeaderParams[12:16], blockHeaderParams[16:20], 0, SMT_KEY_BLOCK_HEADER_PARAM, 0], [hk0[0], hk0[1], hk0[2], hk0[3]]) + ; value: previousBlockHash + %INDEX_BLOCK_HEADER_PARAM_BLOCK_HASH => A + %SMT_KEY_BLOCK_HEADER_PARAM => B + 0 => C + $ => D :MLOAD(previousBlockHash) + $ => SR :SSTORE + + ; Insert coinbase address + ; key: H([blockHeaderParams[0:4], blockHeaderParams[4:8], blockHeaderParams[8:12], blockHeaderParams[12:16], blockHeaderParams[16:20], 0, SMT_KEY_BLOCK_HEADER_PARAM, 0], [hk0[0], hk0[1], hk0[2], hk0[3]]) + ; value: sequencerAddr + %INDEX_BLOCK_HEADER_PARAM_COINBASE => A + %SMT_KEY_BLOCK_HEADER_PARAM => B + 0 => C + $ => D :MLOAD(sequencerAddr) + $ => SR :SSTORE + + ; Insert block number + ; key: H([blockHeaderParams[0:4], blockHeaderParams[4:8], blockHeaderParams[8:12], blockHeaderParams[12:16], blockHeaderParams[16:20], 0, SMT_KEY_BLOCK_HEADER_PARAM, 0], [hk0[0], hk0[1], hk0[2], hk0[3]]) + ; value: blockNum + %INDEX_BLOCK_HEADER_PARAM_NUMBER => A + %SMT_KEY_BLOCK_HEADER_PARAM => B + 0 => C + $ => D :MLOAD(blockNum) + $ => SR :SSTORE + + ; Insert block gas limit + ; key: H([blockHeaderParams[0:4], blockHeaderParams[4:8], blockHeaderParams[8:12], blockHeaderParams[12:16], blockHeaderParams[16:20], 0, SMT_KEY_BLOCK_HEADER_PARAM, 0], [hk0[0], hk0[1], hk0[2], hk0[3]]) + ; value: block gas limit + %INDEX_BLOCK_HEADER_PARAM_GAS_LIMIT => A + %SMT_KEY_BLOCK_HEADER_PARAM => B + 0 => C + %BLOCK_GAS_LIMIT => D + $ => SR :SSTORE + + ; Insert block timestamp + ; key: H([blockHeaderParams[0:4], blockHeaderParams[4:8], blockHeaderParams[8:12], blockHeaderParams[12:16], blockHeaderParams[16:20], 0, SMT_KEY_BLOCK_HEADER_PARAM, 0], [hk0[0], hk0[1], hk0[2], hk0[3]]) + ; value: timestamp + %INDEX_BLOCK_HEADER_PARAM_TIMESTAMP => A + %SMT_KEY_BLOCK_HEADER_PARAM => B + 0 => C + $ => D :MLOAD(timestamp) + $ => SR :SSTORE + + ; Insert block new ger + ; key: H([blockHeaderParams[0:4], blockHeaderParams[4:8], blockHeaderParams[8:12], blockHeaderParams[12:16], blockHeaderParams[16:20], 0, SMT_KEY_BLOCK_HEADER_PARAM, 0], [hk0[0], hk0[1], hk0[2], hk0[3]]) + ; value: GER + %INDEX_BLOCK_HEADER_PARAM_GER => A + %SMT_KEY_BLOCK_HEADER_PARAM => B + 0 => C + $ => D :MLOAD(gerL1InfoTree) + $ => SR :SSTORE + + ; Insert block new blockHashL1 + ; key: H([blockHeaderParams[0:4], blockHeaderParams[4:8], blockHeaderParams[8:12], blockHeaderParams[12:16], blockHeaderParams[16:20], 0, SMT_KEY_BLOCK_HEADER_PARAM, 0], [hk0[0], hk0[1], hk0[2], hk0[3]]) + ; value: blockHashL1 + %INDEX_BLOCK_HEADER_PARAM_BLOCK_HASH_L1 => A + %SMT_KEY_BLOCK_HEADER_PARAM => B + 0 => C + $ => D :MLOAD(blockHashL1InfoTree) + $ => SR :SSTORE + + ; Restore current SR + SR :MSTORE(blockInfoSR) + $ => SR :MLOAD(tmpSR), RETURN + +; @info Fill Block Info tree with tx receipt values +fillBlockInfoTreeWithTxReceipt: + ; checks zk-counters + %MAX_CNT_STEPS - STEP - 50 :JMPN(outOfCountersStep) + %MAX_CNT_POSEIDON_G - CNT_POSEIDON_G - %MAX_CNT_POSEIDON_SLOAD_SSTORE*4 :JMPN(outOfCountersPoseidon) + %MAX_CNT_BINARY - CNT_BINARY - 4 :JMPN(outOfCountersBinary) + ; save current state root & load block info root + SR :MSTORE(tmpSR) + $ => SR :MLOAD(blockInfoSR) + ; Insert transaction hash + ; key: H([txIndex[0:4], txIndex[4:8], txIndex[8:12], txIndex[12:16], txIndex[16:20], 0, SMT_KEY_BLOCK_HEADER_TRANSACTION_HASH, 0], [hk0[0], hk0[1], hk0[2], hk0[3]]) + ; value: txHash + $ => A :MLOAD(txIndex) + %SMT_KEY_BLOCK_HEADER_TRANSACTION_HASH => B + 0 => C + $ => D :MLOAD(l2TxHash) + $ => SR :SSTORE + + ; Insert transaction status + ; key: H([txIndex[0:4], txIndex[4:8], txIndex[8:12], txIndex[12:16], txIndex[16:20], 0, SMT_KEY_BLOCK_HEADER_STATUS, 0], [hk0[0], hk0[1], hk0[2], hk0[3]]) + ; value: txStatus + %SMT_KEY_BLOCK_HEADER_STATUS => B + 0 => C + $ => D :MLOAD(txStatus) + $ => SR :SSTORE + + ; Insert transaction cumulativeGasUsed + ; key: H([txIndex[0:4], txIndex[4:8], txIndex[8:12], txIndex[12:16], txIndex[16:20], 0, SMT_KEY_BLOCK_HEADER_CUMULATIVE_GAS_USED, 0], [hk0[0], hk0[1], hk0[2], hk0[3]]) + ; value: txStatus + %SMT_KEY_BLOCK_HEADER_CUMULATIVE_GAS_USED => B + 0 => C + $ => D :MLOAD(cumulativeGasUsed) + $ => SR :SSTORE + + ; Insert transaction effectivePercentage + ; key: H([txIndex[0:4], txIndex[4:8], txIndex[8:12], txIndex[12:16], txIndex[16:20], 0, SMT_KEY_BLOCK_HEADER_CUMULATIVE_GAS_USED, 0], [hk0[0], hk0[1], hk0[2], hk0[3]]) + ; value: effectivePercentage + %SMT_KEY_BLOCK_HEADER_EFFECTIVE_PERCENTAGE => B + 0 => C + $ => D :MLOAD(effectivePercentageRLP) + $ => SR :SSTORE + + ; Restore current SR + SR :MSTORE(blockInfoSR) + $ => SR :MLOAD(tmpSR), RETURN + +; @info Fill Block Info tree with block gas used at the end of block processing and Store block Info Root in storage +consolidateBlock: + ; checks zk-counters + %MAX_CNT_STEPS - STEP - 20 :JMPN(outOfCountersStep) + %MAX_CNT_POSEIDON_G - CNT_POSEIDON_G - %MAX_CNT_POSEIDON_SLOAD_SSTORE*2 :JMPN(outOfCountersPoseidon) + %MAX_CNT_BINARY - CNT_BINARY - 2 :JMPN(outOfCountersBinary) + ; save current state root & load block info root + SR :MSTORE(tmpSR) + $ => SR :MLOAD(blockInfoSR) + + ; Insert transaction cumulativeGasUsed + ; key: H([blockHeaderParams[0:4], blockHeaderParams[4:8], blockHeaderParams[8:12], blockHeaderParams[12:16], blockHeaderParams[16:20], 0, SMT_KEY_BLOCK_HEADER_PARAM, 0], [hk0[0], hk0[1], hk0[2], hk0[3]]) + ; value: txStatus + %INDEX_BLOCK_HEADER_PARAM_GAS_USED => A + %SMT_KEY_BLOCK_HEADER_PARAM => B + 0 => C + $ => D :MLOAD(cumulativeGasUsed) + $ => SR :SSTORE + + ; Restore current SR + SR :MSTORE(blockInfoSR) + $ => SR :MLOAD(tmpSR) + +finalConsolidateBlockInfoTree: + ; Store block Info Root in storage + %ADDRESS_SYSTEM => A + %SMT_KEY_SC_STORAGE => B + %BLOCK_INFO_ROOT_STORAGE_POS => C +writeBlockInfoRoot: + $ => D :MLOAD(blockInfoSR) + $ => SR :SSTORE + $${eventLog(onFinishBlock)} + :RETURN + +; @info add new log hash to block info tree +; @in D => Value to store (linearPoseidon(log_data + log_topics)) +fillBlockInfoTreeWithLog: + ; checks zk-counters + %MAX_CNT_STEPS - STEP - 20 :JMPN(outOfCountersStep) + %MAX_CNT_POSEIDON_G - CNT_POSEIDON_G - %MAX_CNT_POSEIDON_SLOAD_SSTORE :JMPN(outOfCountersPoseidon) + %MAX_CNT_BINARY - CNT_BINARY - 1 :JMPN(outOfCountersBinary) + ; save current state root & load block info root + SR :MSTORE(tmpSR) + $ => SR :MLOAD(blockInfoSR) + + ; Retrieve and update currentLogIndex + $ => C :MLOAD(currentLogIndex) + C + 1 :MSTORE(currentLogIndex) + + ; Insert new log to block info tree + ; key: H([logIndexKey[0:4], logIndexKey[4:8], logIndexKey[8:12], logIndexKey[12:16], logIndexKey[16:20], 0, SMT_KEY_BLOCK_HEADER_LOGS, 0], [hk0[0], hk0[1], hk0[2], hk0[3]]) + ; hk0: H([logIndex[0:4], logIndex[4:8], logIndex[8:12], logIndex[12:16], logIndex[16:20], logIndex[20:24], logIndex[24:28], logIndex[28:32], [0, 0, 0, 0]) + ; value: linearPoseidon(log_data + log_topics) + $ => A :MLOAD(txIndex) + %SMT_KEY_BLOCK_HEADER_LOGS => B + $ => SR :SSTORE + + ; Restore current SR + SR :MSTORE(blockInfoSR) + $ => SR :MLOAD(tmpSR), RETURN \ No newline at end of file diff --git a/main/constants.zkasm b/main/constants.zkasm index 4b2e41ec..2d6b650a 100644 --- a/main/constants.zkasm +++ b/main/constants.zkasm @@ -4,13 +4,22 @@ CONSTL %ADDRESS_SYSTEM = 0x000000000000000000000000000000005ca1ab1en CONST %MAX_STACK_SIZE = 1024 CONST %BATCH_DIFFICULTY = 0 CONST %TX_GAS_LIMIT = 30000000 +CONSTL %BLOCK_GAS_LIMIT = 2**64-1 +CONST %MAX_MEM_EXPANSION_BYTES = 0x3fffe0 +CONST %FORK_ID = 7 +CONST %L1INFO_TREE_LEVELS = 32 +CONST %CALLDATA_RESERVED_CTX = 1 +CONSTL %FOUR_GOLDILOCKS = 0xffffffff00000001ffffffff00000001ffffffff00000001ffffffff00000001n + +; GER manager storage positions constants CONST %GLOBAL_EXIT_ROOT_STORAGE_POS = 0 CONST %LOCAL_EXIT_ROOT_STORAGE_POS = 1 -CONST %LAST_TX_STORAGE_POS = 0 + +; System address storage positions constants +CONST %LAST_BLOCK_STORAGE_POS = 0 CONST %STATE_ROOT_STORAGE_POS = 1 -CONST %MAX_MEM_EXPANSION_BYTES = 0x3fffe0 -CONST %FORK_ID = 6 -CONST %CALLDATA_RESERVED_CTX = 1 +CONST %TIMESTAMP_STORAGE_POS = 2 +CONST %BLOCK_INFO_ROOT_STORAGE_POS = 3 ; RLP CONST %MIN_VALUE_SHORT = 128 @@ -27,6 +36,24 @@ CONST %SMT_KEY_SC_LENGTH = 4 CONST %SMT_KEY_TOUCHED_ADDR = 5 CONST %SMT_KEY_TOUCHED_SLOTS = 6 +; SMT block header constants +CONST %SMT_KEY_BLOCK_HEADER_PARAM = 7 +CONST %SMT_KEY_BLOCK_HEADER_TRANSACTION_HASH = 8 +CONST %SMT_KEY_BLOCK_HEADER_STATUS = 9 +CONST %SMT_KEY_BLOCK_HEADER_CUMULATIVE_GAS_USED = 10 +CONST %SMT_KEY_BLOCK_HEADER_LOGS = 11 +CONST %SMT_KEY_BLOCK_HEADER_EFFECTIVE_PERCENTAGE = 12 + +; SMT block header data leaf keys +CONST %INDEX_BLOCK_HEADER_PARAM_BLOCK_HASH = 0 +CONST %INDEX_BLOCK_HEADER_PARAM_COINBASE = 1 +CONST %INDEX_BLOCK_HEADER_PARAM_NUMBER = 2 +CONST %INDEX_BLOCK_HEADER_PARAM_GAS_LIMIT = 3 +CONST %INDEX_BLOCK_HEADER_PARAM_TIMESTAMP = 4 +CONST %INDEX_BLOCK_HEADER_PARAM_GER = 5 +CONST %INDEX_BLOCK_HEADER_PARAM_BLOCK_HASH_L1 = 6 +CONST %INDEX_BLOCK_HEADER_PARAM_GAS_USED = 7 + ; GAS CONST %BASE_TX_GAS = 21000 CONST %BASE_TX_DEPLOY_GAS = 53000 @@ -43,12 +70,17 @@ CONST %CALL_STIPEND = 2300 CONST %ECRECOVER_GAS = 3000 ; Elliptic curve sender recovery gas price CONST %IDENTITY_GAS = 15 ; Base price for a data copy operation CONST %IDENTITY_WORD_GAS = 3 ; Per-work price for a data copy operation +CONST %ECADD_GAS = 150; ecAdd gas price +CONST %ECMUL_GAS = 6000; ecMul gas price +CONST %ECPAIRING_GAS = 45000; ecPairing gas price +CONST %SHA2_256_GAS = 60 ; sha256 static gas +CONST %SHA2_256_WORD_GAS = 12 ; sha256 word gas CONST %KECCAK_GAS = 30 ; Once per KECCAK256 operation. CONST %KECCAK_WORD_GAS = 6 ; Once per word of the KECCAK256 operation's data. CONST %LOG_GAS = 375 ; Per LOG* operation. CONST %LOG_TOPIC_GAS = 375 ; Per LOG topic operation. CONST %JUMP_DEST_GAS = 1 ; Once per JUMPDEST operation. -CONST %WARM_STORGE_READ_GAS = 100 ; WarmStorageReadCostEIP2929 +CONST %WARM_STORAGE_READ_GAS = 100 ; WarmStorageReadCostEIP2929 CONST %COLD_ACCOUNT_ACCESS_COST_REDUCED = 2500 ; ColdAccountAccessCostEIP2929 reduced(2600) CONST %COLD_ACCOUNT_ACCESS_COST = 2600 ; ColdAccountAccessCostEIP2929 CONST %EXP_BYTE_GAS = 50 ; was raised to 50 during Eip158 (Spurious Dragon) @@ -80,6 +112,7 @@ CONST %MAX_CNT_MEM_ALIGN_LIMIT = %TOTAL_STEPS_LIMIT / 32 CONST %MAX_CNT_KECCAK_F_LIMIT = (%TOTAL_STEPS_LIMIT / 155286) * 44 CONST %MAX_CNT_PADDING_PG_LIMIT = (%TOTAL_STEPS_LIMIT / 56) CONST %MAX_CNT_POSEIDON_G_LIMIT = (%TOTAL_STEPS_LIMIT / 30) +CONST %MAX_CNT_SHA256_F_LIMIT = ((%TOTAL_STEPS_LIMIT - 1) / 31488) * 7 CONST %SAFE_RANGE = 20 ; safe guard counters to not take into account (%RANGE = 1 / SAFE_RANGE) @@ -90,7 +123,8 @@ CONST %MAX_CNT_MEM_ALIGN = %MAX_CNT_MEM_ALIGN_LIMIT - (%MAX_CNT_MEM_ALIGN_LIMIT CONST %MAX_CNT_KECCAK_F = %MAX_CNT_KECCAK_F_LIMIT - (%MAX_CNT_KECCAK_F_LIMIT / %SAFE_RANGE) CONST %MAX_CNT_PADDING_PG = %MAX_CNT_PADDING_PG_LIMIT - (%MAX_CNT_PADDING_PG_LIMIT / %SAFE_RANGE) CONST %MAX_CNT_POSEIDON_G = %MAX_CNT_POSEIDON_G_LIMIT - (%MAX_CNT_POSEIDON_G_LIMIT / %SAFE_RANGE) -CONST %MAX_CNT_POSEIDON_SLOAD_SSTORE = 257 +CONST %MAX_CNT_SHA256_F = %MAX_CNT_SHA256_F_LIMIT - (%MAX_CNT_SHA256_F_LIMIT / %SAFE_RANGE) +CONST %MAX_CNT_POSEIDON_SLOAD_SSTORE = 518 CONST %MIN_CNT_KECCAK_BATCH = 1 ; minimum necessary keccaks to compute global hash @@ -98,4 +132,13 @@ CONST %MIN_CNT_KECCAK_BATCH = 1 ; minimum necessary keccaks to compute global ha CONSTL %MAX_NONCE = 0xffffffffffffffffn CONSTL %MAX_UINT_256 = 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffn CONST %CODE_SIZE_LIMIT = 0x6000 -CONST %BYTECODE_STARTS_EF = 0xEF \ No newline at end of file +CONST %BYTECODE_STARTS_EF = 0xEF +CONST %MAX_SIZE_MODEXP = 1024 +CONST %MAX_GAS_WORD_MODEXP = 9487 +CONSTL %MAX_GAS_IT_MODEXP = 90000000 ; %TX_GAS_LIMIT * 3 + +; CONSTANTS TX CHANGEL2BLOCK +CONST %CHANGE_L2_BLOCK_TX_TYPE = 0x0b +CONST %DELTA_TIMESTAMP_NUM_BYTES = 4 +CONST %INDEX_L1INFOTREE_NUM_BYTES = 4 +CONST %TX_TYPE_NUM_BYTES = 1 diff --git a/main/ecrecover/ecrecover.zkasm b/main/ecrecover/ecrecover.zkasm index 29294bbc..ebe99b09 100644 --- a/main/ecrecover/ecrecover.zkasm +++ b/main/ecrecover/ecrecover.zkasm @@ -181,7 +181,7 @@ k1_c_is_not_zero: ; FNEC - A = FNEC - (hash * inv_r) % FNEC A => B %FNEC => A - ; B != 0 ==> multPointEc_k1 = FNEC - B + ; B != 0 ==> mulPointEc_k1 = FNEC - B ; k1 is alias-free $ :SUB, MSTORE(mulPointEc_k1) @@ -208,7 +208,7 @@ k1_calculated: A :MSTORE(mulPointEc_p2_x) ; y isn't an alias because was checked before - ; (r,y) is a point of curve because it satisfacts the curve equation + ; (r,y) is a point of curve because it satisfies the curve equation $ => A :MLOAD(ecrecover_y) ; [steps: 120, bin: 10, arith: 15] A :MSTORE(mulPointEc_p2_y),CALL(mulPointEc) diff --git a/main/ecrecover/mulPointEc.zkasm b/main/ecrecover/mulPointEc.zkasm index 648382e5..2f25b941 100644 --- a/main/ecrecover/mulPointEc.zkasm +++ b/main/ecrecover/mulPointEc.zkasm @@ -1,6 +1,6 @@ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; -;; mulPointEc (p1_x,p1_y,p2_x,p2_y,k1,k2) = (p3_x, p3_y, HASPOS) +;; mulPointEc (p1_x,p1_y,p2_x,p2_y,k1,k2) = (p3_x, p3_y, HASHPOS) ;; ;; PRE: p1_x, p1_y, p2_x, p2_y, k1, k2 are alias-free ;; POST: p3_x, p3_y is alias-free HASHPOS = [0,1] @@ -41,10 +41,10 @@ VAR GLOBAL mulPointEc_RCX ; + number_of_bits_1(k1|k2) * arith // additions ; + (256 - left_bits_zero(k1|k2) * arith // squares ; + 24 * 256 steps // get bits k1,k2 + additions + squares (steps, regular) -; - (24 - 8) * left_bits_zero(k1|k2) * steps // get bits k1,k2 + additions + squares (steps firts bits = 0) +; - (24 - 8) * left_bits_zero(k1|k2) * steps // get bits k1,k2 + additions + squares (steps first bits = 0) ; - (24 - 12) * number_of_bits_1(k1|k2) * steps // get bits k1,k2 + additions + squares (k1,k2 bits = 0) ; + (3 - 5) steps // last part - last part square no done -; - 1 arith // first asignation +; - 1 arith // first assignation ; ; ; RESOURCES (worst case): 512 arith + 512 binaries + 6160 steps // 18 + 256 * 24 - 2 = 6160 @@ -265,7 +265,7 @@ mulPointEc_x_equals_before_add: ; C: point2.x ; D: point2.y - ; p3_x == C, check if points are same or a point was oposite point + ; p3_x == C, check if points are same or a point was opposite point ${ D == mem.mulPointEc_p3_y } :JMPNZ(mulPointEc_same_point_to_add) diff --git a/main/end.zkasm b/main/end.zkasm index c10363de..78d7e172 100644 --- a/main/end.zkasm +++ b/main/end.zkasm @@ -1,4 +1,4 @@ finalWait: ${beforeLast()} :JMPN(finalWait) - ; Set all registers to 0 except inputs: B (oldstateRoot), C (oldAccInputHash), SP (oldNumBatch), GAS (chainID) & CTX (forkID) + ; Set all registers to 0 except inputs: B (oldStateRoot), C (oldAccInputHash), SP (oldNumBatch), GAS (chainID) & CTX (forkID) 0 => A, D, E, PC, SR, HASHPOS, RR, RCX :JMP(start) \ No newline at end of file diff --git a/main/l2-tx-hash.zkasm b/main/l2-tx-hash.zkasm new file mode 100644 index 00000000..deb5ae77 --- /dev/null +++ b/main/l2-tx-hash.zkasm @@ -0,0 +1,159 @@ +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; Compute l2TxHash for legacy and preEIP155 transactions +;; +;; - preEIP155 (message to sign in Ethereum: rlp[nonce, gasprice, gaslimit, to, value, data]) +;; [ 1 bytes ] txType = 0 +;; [ 8 bytes ] nonce +;; [ 32 bytes ] gasPrice +;; [ 8 bytes ] gasLimit +;; [ 1 bytes ] deployment ('0': no deloyment, '1': deployment) +;; [ 20 bytes ] to (0 bytes if it is a deployment) +;; [ 32 bytes ] value +;; [ 3 bytes ] dataLength +;; [ XX bytes ] data +;; [ 20 bytes ] from +;; +;; +;; - Legacy (message to sign in Ethereum: rlp[nonce, gasprice, gaslimit, to, value, data, chainId, 0, 0]) +;; [ 1 bytes ] txType = 1 +;; [ 8 bytes ] nonce +;; [ 32 bytes ] gasPrice +;; [ 8 bytes ] gasLimit +;; [ 1 bytes ] deployment ('0': no deloyment, '1': deployment) +;; [ 20 bytes ] to (0 bytes if it is a deployment) +;; [ 32 bytes ] value +;; [ 3 bytes ] dataLength +;; [ XX bytes ] data +;; [ 8 bytes ] chainId +;; [ 20 bytes ] from +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + + +VAR CTX l2TxHashPointer ; Pointer to l2TxHash hash address +VAR CTX l2HASHP ; pointer to the l2TxHash to store the bytes +VAR GLOBAL tmpVar_HASHPOS_L2HashTx ; temporary variable register HASHPOS +VAR GLOBAL tmpVar_A_L2HashTx ; temporary variable register A +VAR GLOBAL tmpVar_D_L2HashTx ; temporary variable register D +VAR GLOBAL tmpVar_E_L2HashTx ; temporary variable register E + +;; Check counters to do the hashp and initialize HASHPOS of the l2TxHash +initL2HashTx: + ; check one binary available to perform correctly the HASHPDIGEST + %MAX_CNT_BINARY - CNT_BINARY - 1 :JMPN(outOfCountersBinary) + ; reserve one byte for the txType in the l2HashTx + ; txType will be known at the end of the RLP parsing + 1 :MSTORE(l2HASHP), RETURN + +;; Write generic bytes to the l2TxHash +; @in A => value to write +; @in D => bytes size to write +addL2HashTx: + ; store temporary register values + E :MSTORE(tmpVar_E_L2HashTx) + HASHPOS :MSTORE(tmpVar_HASHPOS_L2HashTx) + + ; load pointer l2HashTx and write bytes + $ => E :MLOAD(l2TxHashPointer) + $ => HASHPOS :MLOAD(l2HASHP) + A :HASHP(E) + HASHPOS :MSTORE(l2HASHP) + + ; load temporary register values + $ => E :MLOAD(tmpVar_E_L2HashTx) + $ => HASHPOS :MLOAD(tmpVar_HASHPOS_L2HashTx), RETURN + +;; Write 1 byte to l2TxHash: flag deployment = 1 ('0': no deployment transaction, '1': deployment transaction) +addL2HashTx_isDeploy: + ; store temporary register values + A :MSTORE(tmpVar_A_L2HashTx) + E :MSTORE(tmpVar_E_L2HashTx) + HASHPOS :MSTORE(tmpVar_HASHPOS_L2HashTx) + + ; load pointer l2HashTx and write deployment flag + $ => E :MLOAD(l2TxHashPointer) + $ => HASHPOS :MLOAD(l2HASHP) + 1 :HASHP1(E) + HASHPOS :MSTORE(l2HASHP) + + ; load temporary register values + $ => A :MLOAD(tmpVar_A_L2HashTx) + $ => E :MLOAD(tmpVar_E_L2HashTx) + $ => HASHPOS :MLOAD(tmpVar_HASHPOS_L2HashTx), RETURN + +;; Write 1 byte to l2TxHash: flag deployment = 0 ('0': no deployment transaction, '1': deployment transaction) +addL2HashTx_isNotDeploy: + ; store temporary register values + E :MSTORE(tmpVar_E_L2HashTx) + HASHPOS :MSTORE(tmpVar_HASHPOS_L2HashTx) + + ; load pointer l2HashTx and write deployment flag + $ => E :MLOAD(l2TxHashPointer) + $ => HASHPOS :MLOAD(l2HASHP) + 0 :HASHP1(E) + HASHPOS :MSTORE(l2HASHP) + + ; load temporary register values + $ => E :MLOAD(tmpVar_E_L2HashTx) + $ => HASHPOS :MLOAD(tmpVar_HASHPOS_L2HashTx), RETURN + +;; Write 3 bytes to l2TxHash: data length +addL2HashTx_dataLength: + ; store temporary register values + A :MSTORE(tmpVar_A_L2HashTx) + D :MSTORE(tmpVar_D_L2HashTx) + E :MSTORE(tmpVar_E_L2HashTx) + HASHPOS :MSTORE(tmpVar_HASHPOS_L2HashTx) + + ; load pointer l2HashTx and write data length + $ => E :MLOAD(l2TxHashPointer) + $ => HASHPOS :MLOAD(l2HASHP) + 3 => D + $ => A :MLOAD(txCalldataLen) + A :HASHP(E) + HASHPOS :MSTORE(l2HASHP) + + ; load temporary register values + $ => A :MLOAD(tmpVar_A_L2HashTx) + $ => D :MLOAD(tmpVar_D_L2HashTx) + $ => E :MLOAD(tmpVar_E_L2HashTx) + $ => HASHPOS :MLOAD(tmpVar_HASHPOS_L2HashTx), RETURN + +;; Write 1 byte to l2TxHash: txType +; note: HASHPOS is not reovered and the outcome register is the l2TxHash length +addL2HashTx_txType: + ; store temporary register values + A :MSTORE(tmpVar_A_L2HashTx) + E :MSTORE(tmpVar_E_L2HashTx) + HASHPOS :MSTORE(tmpVar_HASHPOS_L2HashTx) + + ; load pointer l2HashTx and write txType + $ => E :MLOAD(l2TxHashPointer) + ; write txType in the first byte of the l2TxHash + 0 => HASHPOS + $ => A :MLOAD(isPreEIP155), JMPZ(addL2HashTx_txType_write_1) + 0 :HASHP1(E), JMP(addL2HashTx_txType_finish) +addL2HashTx_txType_write_1: + 1 :HASHP1(E) +addL2HashTx_txType_finish: + ; load temporary register values + $ => A :MLOAD(tmpVar_A_L2HashTx) + $ => E :MLOAD(tmpVar_E_L2HashTx) + $ => HASHPOS :MLOAD(tmpVar_HASHPOS_L2HashTx), RETURN + +;; Closes l2TxHash and store the result +closeL2TxHash: + ; store temporary register values + E :MSTORE(tmpVar_E_L2HashTx) + HASHPOS :MSTORE(tmpVar_HASHPOS_L2HashTx) + + ; load HASHPOS l2TxHash + $ => HASHPOS :MLOAD(l2HASHP) + $ => E :MLOAD(l2TxHashPointer) + HASHPOS :HASHPLEN(E) + ; digest l2TxHash + $ => E :HASHPDIGEST(E) + E :MSTORE(l2TxHash) + + ; load temporary register values + $ => E :MLOAD(tmpVar_E_L2HashTx) + $ => HASHPOS :MLOAD(tmpVar_HASHPOS_L2HashTx), RETURN \ No newline at end of file diff --git a/main/load-change-l2-block-utils.zkasm b/main/load-change-l2-block-utils.zkasm new file mode 100644 index 00000000..6041c2b0 --- /dev/null +++ b/main/load-change-l2-block-utils.zkasm @@ -0,0 +1,11 @@ +;; get D bytes from transaction bytes +;@in D: number of bytes to get +;@in C: current data parsed pointer +;@out A: D bytes from batch data at offset C +getChangeL2TxBytes: + $ => A :MLOAD(batchL2DataLength) + $ => B :MLOAD(batchL2DataParsed) + A - B - C - D :JMPN(invalidDecodeChangeL2Block) + ${getTxs(p,D)} => A + $${p = p + D} + :RETURN \ No newline at end of file diff --git a/main/load-change-l2-block.zkasm b/main/load-change-l2-block.zkasm new file mode 100644 index 00000000..e26e7415 --- /dev/null +++ b/main/load-change-l2-block.zkasm @@ -0,0 +1,28 @@ +INCLUDE "load-change-l2-block-utils.zkasm" +;;;;;;;;;;;;;;;;;; +;; ChangeL2BlockTx: +;; - fields: [type | deltaTimestamp | indexL1InfoTree ] +;; - bytes: [ 1 | 4 | 4 ] +;;;;;;;;;;;;;;;;;; + +decodeChangeL2BlockTx: + ; No changeL2BlockTx allowed at forced batches + $ :MLOAD(isForced), JMPNZ(invalidDecodeChangeL2Block) + + ; Decode deltaTimestamp / 4 bytes + %DELTA_TIMESTAMP_NUM_BYTES => D :CALL(getChangeL2TxBytes) + C + D => C :CALL(addBatchHashData) + A :MSTORE(deltaTimestamp) + ; Decode indexL1InfoTree / 4 bytes + %INDEX_L1INFOTREE_NUM_BYTES => D :CALL(getChangeL2TxBytes) + C + D => C :CALL(addBatchHashData) + A :MSTORE(indexL1InfoTree) + 1 :MSTORE(isChangeL2BlockTx), JMP(finishLoadChangeL2BlockTx) + +finishLoadChangeL2BlockTx: +;; update bytes parsed + $ => A :MLOAD(batchL2DataParsed) + A + C :MSTORE(batchL2DataParsed) +;; increase number of transaction to process + $ => A :MLOAD(pendingTxs) + A + 1 :MSTORE(pendingTxs), JMP(txLoopRLP) \ No newline at end of file diff --git a/main/load-tx-rlp-utils.zkasm b/main/load-tx-rlp-utils.zkasm index 93639d06..e81d810a 100644 --- a/main/load-tx-rlp-utils.zkasm +++ b/main/load-tx-rlp-utils.zkasm @@ -9,6 +9,9 @@ addBatchHashData: $ => E :MLOAD(lastHashKIdUsed), RETURN ;; get D bytes from transaction bytes +;@in D: number of bytes to get +;@in C: current data parsed pointer +;@out A: D bytes from batch data at offset C getTxBytes: $ => A :MLOAD(batchL2DataLength) $ => B :MLOAD(batchL2DataParsed) @@ -17,7 +20,9 @@ getTxBytes: $${p = p + D} :RETURN -;; Add bytes to generate ethereum transaction hash. transactionHash = H_keccak(rlp(nonce, gasprice, gaslimit, to, value, data, chainId, 0, 0)) +;; Add bytes to generate ethereum signed message +;; - legacy transaction: signedMessage = H_keccak(rlp(nonce, gasprice, gaslimit, to, value, data, chainId, 0, 0)) +;; - pre EIP-155: signedMessage = H_keccak(rlp(nonce, gasprice, gaslimit, to, value, data)) addHashTx: $ => A :MLOAD(txRLPLength) A - HASHPOS - D :JMPN(invalidTxRLP) @@ -30,6 +35,7 @@ addHashTxBegin: A :HASHK(E) C + D => C :RETURN + ;; Check short value is over 127. Error RLP: single byte < 0x80 are not prefixed checkShortRLP: D - 1 :JMPNZ(skipCheckShort) @@ -56,11 +62,11 @@ skipCheckShortData: VAR GLOBAL tmpVarAcheckNonLeadingZeros VAR GLOBAL tmpVarZkPCcheckNonLeadingZeros checkNonLeadingZeros: - RR :MSTORE(tmpVarZkPCcheckNonLeadingZeros) - A :MSTORE(tmpVarAcheckNonLeadingZeros) + RR :MSTORE(tmpVarZkPCcheckNonLeadingZeros) + A :MSTORE(tmpVarAcheckNonLeadingZeros) ; set value to B and get its - A => B :CALL(getLenBytes) ; in: [B: number] out: [A: byte length of B] + A => B :CALL(getLenBytes) ; in: [B: number] out: [A: byte length of B] ; check (bytes length - encoded length) are not equal - D - A :JMPNZ(invalidTxRLP) - $ => RR :MLOAD(tmpVarZkPCcheckNonLeadingZeros) - $ => A :MLOAD(tmpVarAcheckNonLeadingZeros), RETURN \ No newline at end of file + D - A :JMPNZ(invalidTxRLP) + $ => RR :MLOAD(tmpVarZkPCcheckNonLeadingZeros) + $ => A :MLOAD(tmpVarAcheckNonLeadingZeros), RETURN \ No newline at end of file diff --git a/main/load-tx-rlp.zkasm b/main/load-tx-rlp.zkasm index ca6f7c91..b7f846bf 100644 --- a/main/load-tx-rlp.zkasm +++ b/main/load-tx-rlp.zkasm @@ -1,4 +1,7 @@ INCLUDE "load-tx-rlp-utils.zkasm" +INCLUDE "load-change-l2-block.zkasm" +INCLUDE "l2-tx-hash.zkasm" + ; Blocks RLP parsing ; A - Initialization ; B - Read and check RLP fields. Fill 'batchHashData' and Ethereum signed transaction bytes @@ -8,8 +11,13 @@ INCLUDE "load-tx-rlp-utils.zkasm" ;;;;;;;;;;;;;;;;;; ;; A - Initialization -;; - Data to parse: [rlp(nonce, gasprice, gaslimit, to, value, data, chainId, 0, 0)|r|s|v] -;; - Signed Ethereum transaction: H_keccak(rlp(nonce, gasprice, gaslimit, to, value, data, chainId, 0, 0)) +;; - Data to parse +;; - legacy transaction: [rlp(nonce, gasprice, gaslimit, to, value, data, chainId, 0, 0)|r|s|v|effectivePercentage] +;; - pre EIP-155 transaction (https://eips.ethereum.org/EIPS/eip-155): [rlp(nonce, gasprice, gaslimit, to, value, data)|r|s|v|effectivePercentage] +;; - internal transaction changeL2Block: [txType, deltaTimestamp, indexL1InfoTree] +;; - Signed Ethereum transaction +;; - legacy transaction: H_keccak(rlp(nonce, gasprice, gaslimit, to, value, data, chainId, 0, 0)) +;; - pre EIP-155 transaction: H_keccak(rlp(nonce, gasprice, gaslimit, to, value, data)) ;; - RLP encoding information: https://ethereum.org/en/developers/docs/data-structures-and-encoding/rlp ;; - Entire batch is discarded (no transaction is processed) if any error is found ;;;;;;;;;;;;;;;;;; @@ -19,27 +27,41 @@ loadTx_rlp: $ => D :MLOAD(cntKeccakPreProcess) %MAX_CNT_KECCAK_F - CNT_KECCAK_F - 1 - D :JMPN(outOfCountersKeccak) - ; A new hash with position 0 is started - 0 => HASHPOS - - ; We get a new hashId - $ => E :MLOAD(lastHashKIdUsed) - E+1 => E :MSTORE(lastHashKIdUsed) ; Pointer to next RLP bytes to read 0 => C - + ; Check it is a change L2 block transaction + %TX_TYPE_NUM_BYTES => D + ; batchL2DataLength is not zero (at least 1 byte), checked at main + ${getTxs(p,D)} => A + $${p = p + D} + C + D => C :CALL(addBatchHashData) + A - %CHANGE_L2_BLOCK_TX_TYPE :JMPZ(decodeChangeL2BlockTx) +checkFirstTxType: + ; First transaction must be a change L2 block transaction if it is NOT a forced batch + $ :MLOAD(pendingTxs), JMPNZ(loadTx_rlp_continue) + ; If it is not forced and it is not a change L2 block transaction, we discard the entire batch + $ :MLOAD(isForced), JMPZ(invalidNotFirstTxChangeL2Block) + +loadTx_rlp_continue: + ; We get a new hashId + $ => E :MLOAD(nextHashPId) + E :MSTORE(l2TxHashPointer) + E + 1 :MSTORE(nextHashPId) + $ => E :MLOAD(lastHashKIdUsed) + E + 1 => E :MSTORE(lastHashKIdUsed) ;;;;;;;;;;;;;;;;;; ;; B - Read and check RLP fields. Fill 'batchHashData' and Ethereum signed transaction bytes ;;;;;;;;;;;;;;;;;; ;; Read RLP list length - ; Should be a list - 1 => D :CALL(addHashTxBegin) - :CALL(addBatchHashData) + ; Add first byte to tx hash and batch hash + ; A new hash with position 0 is started + 0 => HASHPOS + A :HASHK(E) A - 0xc0 :JMPN(invalidTxRLP) A - 0xf8 :JMPN(shortList) ; do not allow lists over 2**24 bytes length - ; Transaction could not have more than 300.000 due to smart contract limitation (keccaks counters) + ; Transaction could not have more than 120.000 due to smart contract limitation (keccaks counters) ; meaning that the RLP encoding is wrong A - 0xfb :JMPN(longList, invalidTxRLP) @@ -54,12 +76,15 @@ shortList: endList: A + C => B :MSTORE(txRLPLength) - ; Check enough zk counters to digest tx hash + ; Check enough keccak zk counters to digest tx hash + ; We don't check poseidon counters spent for l2 tx hash computing because the number of poseidon counters available is x100 the number of keccak available + ; so while rlp parsing, keccaks will always be the bottleneck B + 1 :MSTORE(arithA) 136 :MSTORE(arithB), CALL(divARITH); in: [arithA, arithB] out: [arithRes1: arithA/arithB, arithRes2: arithA%arithB] $ => B :MLOAD(arithRes1) $ => D :MLOAD(cntKeccakPreProcess) - %MAX_CNT_KECCAK_F - CNT_KECCAK_F - B - D - 1:JMPN(outOfCountersKeccak) + %MAX_CNT_KECCAK_F - CNT_KECCAK_F - B - D - 1 :JMPN(outOfCountersKeccak) + :CALL (initL2HashTx) ;; Read RLP 'nonce' ; 64 bits max @@ -71,17 +96,18 @@ nonceREAD: A - 0x89 :JMPN(shortNonce, invalidTxRLP) nonce0: - 0 => A :MSTORE(lengthNonce), JMP(endNonce) + 0 => A :MSTORE(lengthNonce), JMP(endNonce) shortNonce: A - 0x80 => D - D :MSTORE(lengthNonce), CALL(addHashTx) + D :MSTORE(lengthNonce),CALL(addHashTx) :CALL(addBatchHashData) :CALL(checkShortRLP) :CALL(checkNonLeadingZeros) endNonce: - A :MSTORE(txNonce) + 8 => D + A :MSTORE(txNonce), CALL(addL2HashTx) ;; Read RLP 'gas price' ; 256 bits max @@ -102,7 +128,8 @@ shortGasPrice: :CALL(checkNonLeadingZeros) endGasPrice: - A :MSTORE(txGasPriceRLP) + 32 => D + A :MSTORE(txGasPriceRLP), CALL(addL2HashTx) ;; Read RLP 'gas limit' @@ -124,7 +151,8 @@ shortGasLimit: :CALL(checkNonLeadingZeros) endGasLimit: - A :MSTORE(txGasLimit) + 8 => D + A :MSTORE(txGasLimit), CALL(addL2HashTx) ;; Read RLP 'to' ; 160 bits or empty @@ -137,10 +165,13 @@ toREAD: A - 0x95 :JMPN(shortTo, invalidTxRLP) noTo: - 1 :MSTORE(isCreateContract), JMP(endTo) + 1 :MSTORE(isCreateContract), CALL(addL2HashTx_isDeploy) + :JMP(endTo) shortTo: A - 0x80 => D :CALL(addHashTx) + :CALL(addL2HashTx_isNotDeploy) + :CALL(addL2HashTx) :CALL(addBatchHashData) A :MSTORE(txDestAddr) A :MSTORE(storageAddr) @@ -166,7 +197,8 @@ shortValue: :CALL(checkNonLeadingZeros) endValue: - A :MSTORE(txValue) + 32 => D + A :MSTORE(txValue), CALL(addL2HashTx) ;; Read RLP 'data' ; should not be a list @@ -180,15 +212,16 @@ dataREAD: 1 => D :CALL(addHashTx) :CALL(addBatchHashData) A - 0x80 :JMPN(veryShortData) - A - 0x81 :JMPN(endData) + A - 0x81 :JMPN(zeroBytesData) A - 0xb8 :JMPN(shortData) ; do not allow string over 2**24 bytes length - ; Transaction could not have more than 300.000 due to smart contract limitation (keccaks counters) + ; Transaction could not have more than 120.000 due to smart contract limitation (keccaks counters) ; meaning that the RLP encoding is wrong A - 0xbb :JMPN(longData, invalidTxRLP) veryShortData: - 1 :MSTORE(txCalldataLen) + 1 :MSTORE(txCalldataLen), CALL(addL2HashTx_dataLength) + :CALL(addL2HashTx) 31 => D :CALL(SHLarith) ; in: [A: value, D: #bytes to left shift] out: [A: shifted result] ; Store current CTX CTX => B @@ -204,7 +237,8 @@ veryShortData: shortData: $ => D :MLOAD(batchHashPos) D :MSTORE(dataStarts) - A - 0x80 => B :MSTORE(txCalldataLen), JMP(readData) + A - 0x80 => B :MSTORE(txCalldataLen), CALL(addL2HashTx_dataLength) + :JMP(readData) longData: A - 0xb7 => D :CALL(addHashTx) @@ -213,13 +247,13 @@ longData: :CALL(checkNonLeadingZeros) $ => D :MLOAD(batchHashPos) D :MSTORE(dataStarts) - A => B :MSTORE(txCalldataLen) + A => B :MSTORE(txCalldataLen), CALL(addL2HashTx_dataLength) readData: 32 => D B - D :JMPN(readDataFinal) B - D :MSTORE(txDataRead), CALL(addHashTx) - $ => E :MLOAD(globalCalldataMemoryOffset) + $ => E :MLOAD(globalCalldataMemoryOffset), CALL(addL2HashTx) ; Store current CTX CTX => B ; Store calldata to calldata CTX's memory @@ -233,6 +267,7 @@ readData: readDataFinal: B - 1 :JMPN(endData) B => D :CALL(addHashTx) + :CALL(addL2HashTx) 32 - D => D :CALL(SHLarith); in: [A: value, D: #bytes to left shift] out: [A: shifted result] $ => E :MLOAD(globalCalldataMemoryOffset) ; Store current CTX @@ -245,12 +280,16 @@ readDataFinal: E + 1 :MSTORE(globalCalldataMemoryOffset) 32 - D => D :CALL(addBatchHashByteByByte); in: [A: bytes to add, D: bytes length] out: [E: lastHashKIdUsed, A: shifted bytes to add] :CALL(checkShortDataRLP) + :JMP(endData) + +zeroBytesData: + :CALL(addL2HashTx_dataLength) endData: - ; Check all bytes read to detect pre EIP-155 tx - C => A + ; Check all bytes read to detect pre EIP-155 tx, if bytes read are the same as txLength, we reached the end, so it's a pre EIP-155 tx + ; txRLPLength and C is at most 120.000 bytes, no need to use a binary for comparison $ => B :MLOAD(txRLPLength) - $ :EQ,JMPC(setPreEIP155Flag) + C - B :JMPZ(setPreEIP155Flag) ;; Read RLP 'chainId' ; 64 bits max @@ -272,22 +311,23 @@ shortChainId: :CALL(checkNonLeadingZeros) endChainId: - A :MSTORE(txChainId) + 8 => D + A :MSTORE(txChainId), CALL(addL2HashTx) ;; Read RLP last two values (0, 0) 2 => D :CALL(addHashTx) :CALL(addBatchHashData) - 0x8080 => B - $ :EQ,JMPC(sizeVerification, invalidTxRLP) + ; We compare the last two bytes of the RLP with 0x8080, no need to use a binary + A - 0x8080 :JMPZ(sizeVerification, invalidTxRLP) setPreEIP155Flag: 1 :MSTORE(isPreEIP155) ;; size verification ; checks RLP length read at the RLP header with bytes read during RLP parsing sizeVerification: - C => A + ; txRLPLength and C is at most 120.000 bytes, no need to use a binary for comparison $ => B :MLOAD(txRLPLength) - $ :EQ,JMPC(sizeVerificationSuccess, invalidTxRLP) + C - B :JMPZ(sizeVerificationSuccess, invalidTxRLP) sizeVerificationSuccess: HASHPOS :HASHKLEN(E) @@ -318,9 +358,11 @@ effectivePercentageTx: 1 => D :CALL(getTxBytes) A :MSTORE(effectivePercentageRLP) C + D => C :CALL(addBatchHashData) + ;;;;;;;;; ;; D - Finish RLP parsing ;;;;;;;;; +finishLoadRLP: ;; update bytes parsed $ => A :MLOAD(batchL2DataParsed) A + C :MSTORE(batchL2DataParsed) @@ -329,13 +371,37 @@ effectivePercentageTx: A + 1 :MSTORE(pendingTxs) ;; compute signature $ => A :HASHKDIGEST(E) - A :MSTORE(txHash), JMP(txLoopRLP) + A :MSTORE(txHash) + +;; Compute L2txHash +;; Get source address from tx signature + $ => B :MLOAD(txR) + $ => C :MLOAD(txS) + $ => D :MLOAD(txV), CALL(ecrecover_tx) +checkAndSaveFrom: + ; warning: we need to insert one transition step between label `checkAndSafeFrom` and `MSTORE(txSrcAddr)` to allow unsigned transactions from executor + 20 => D + ; save ecrecover error code + B :MSTORE(ecrecoverErrorCode) + ; save 'from' to l2TxHash + A :MSTORE(txSrcAddr), CALL(addL2HashTx) + ; save 'txType' to l2TxHash + :CALL(addL2HashTx_txType) + ; close l2 tx hash + :CALL(closeL2TxHash) + :JMP(txLoopRLP) ;;;;;;;;; ;; E - Handler error RLP fields ;;;;;;;;; invalidTxRLP: - $${eventLog(onError, invalidRLP)} :JMP(appendTxsInit) + $${eventLog(onError, invalidRLP)} :JMP(appendTxsInit) + +invalidDecodeChangeL2Block: + $${eventLog(onError, invalidDecodeChangeL2Block)} :JMP(appendTxsInit) + +invalidNotFirstTxChangeL2Block: + $${eventLog(onError, invalidNotFirstTxChangeL2Block)} :JMP(appendTxsInit) appendTxsInit: ;; Append all missing 'batchL2Data' to 'batchDataHash' bytes @@ -362,4 +428,4 @@ finalAppendTxs: C + D => C endAppendTxs: - HASHPOS :MSTORE(batchHashPos),JMP(processTxsEnd) + HASHPOS :MSTORE(batchHashPos),JMP(finalizeBatch) diff --git a/main/main.zkasm b/main/main.zkasm index fecd9f08..84818323 100644 --- a/main/main.zkasm +++ b/main/main.zkasm @@ -3,9 +3,9 @@ INCLUDE "vars.zkasm" ; Blocks zkROM ; A - Load initial registers into memory: oldStateRoot (B), oldAccInputHash (C), oldNumBatch (SP) & chainID (GAS) -; B - Set batch global variables +; B - Compute keccaks needed to finish the batch ; C - Loop parsing RLP transactions -; D - Loop processing transactions +; D - Load blockNum variable & Loop processing transactions ; E - Batch computations: get newLocalExitRoot, assert transactions size, compute batchHashData & compute newAccInputHash ; F - Finalize execution @@ -14,72 +14,45 @@ start: ; main zkROM entry point ;; A - Load input variables ;;;;;;;;;;;;;;;;;; STEP => A - 0 :ASSERT ; Ensure it is the beginning of the execution + 0 :ASSERT ; Ensure it is the beginning of the execution - CTX :MSTORE(forkID) - CTX - %FORK_ID :JMPNZ(failAssert) + CTX :MSTORE(forkID) + CTX - %FORK_ID :JMPNZ(failAssert) - B :MSTORE(oldStateRoot) - C :MSTORE(oldAccInputHash) - SP :MSTORE(oldNumBatch) - GAS :MSTORE(chainID) ; assumed to be less than 32 bits + B => A :MSTORE(oldStateRoot) - ${getGlobalExitRoot()} :MSTORE(globalExitRoot) - ${getSequencerAddr()} :MSTORE(sequencerAddr) - ${getTimestamp()} :MSTORE(timestamp) - ${getTxsLen()} :MSTORE(batchL2DataLength) ; less than 300.000 bytes. Enforced by the smart contract + ; safety check that the input root is indeed inside the range limit of 4 goldilocks fields elements + %FOUR_GOLDILOCKS => B + 1 :LT4 - B => SR ;set initial state root + C :MSTORE(oldAccInputHash) + SP :MSTORE(oldNumBatch) + GAS :MSTORE(chainID) ; assumed to be less than 32 bits + ${getL1InfoRoot()} :MSTORE(l1InfoRoot) + ${getSequencerAddr()} :MSTORE(sequencerAddr) + ${getTimestampLimit()} :MSTORE(timestampLimit) + ${getTxsLen()} :MSTORE(batchL2DataLength) ; less than 120000 bytes. Enforced by the smart contract + ${getForcedBlockHashL1()} => A :MSTORE(forcedBlockHashL1) + + ;set initial state root + $ => SR :MLOAD(oldStateRoot) + SR :MSTORE(batchSR) ; Increase batch number - SP + 1 :MSTORE(newNumBatch) + SP + 1 :MSTORE(newNumBatch) + ; compute isForced flag + 0 => B + $ :EQ, JMPC(computeKeccaks) + 1 :MSTORE(isForced) ;;;;;;;;;;;;;;;;;; -;; B - Set batch global variables -;; - set globalExitRoot in Bridge contract -;; - load transaction count from system smart contract -;; - compute keccaks needed to finish the batch +;; B - Compute keccaks needed to finish the batch ;;;;;;;;;;;;;;;;;; +computeKeccaks: $${eventLog(onStartBatch, C)} - $ => A :MLOAD(globalExitRoot) - 0 => B - $ :EQ, JMPC(skipSetGlobalExitRoot) - -;; Set global exit root -setGlobalExitRoot: - 0 => HASHPOS - $ => E :MLOAD(lastHashKIdUsed) - E+1 => E :MSTORE(lastHashKIdUsed) - - 32 => D - A :HASHK(E) - %GLOBAL_EXIT_ROOT_STORAGE_POS :HASHK(E) ; Storage position of the global exit root map - HASHPOS :HASHKLEN(E) - $ => C :HASHKDIGEST(E) - - %ADDRESS_GLOBAL_EXIT_ROOT_MANAGER_L2 => A - %SMT_KEY_SC_STORAGE => B - - ; read timestamp given the globalExitRoot - ; skip overwrite timestamp if it is different than 0 - ; Since timestamp is enforced by the smart contract it is safe to compare only 32 bits in 'op0' with JMPNZ - $ => D :SLOAD, JMPNZ(skipSetGlobalExitRoot) - - $ => D :MLOAD(timestamp) - $ => SR :SSTORE ; Store 'timestamp' in storage position 'keccak256(globalExitRoot, 0)' - -skipSetGlobalExitRoot: - SR :MSTORE(batchSR) - ; Load current tx count - %LAST_TX_STORAGE_POS => C - %ADDRESS_SYSTEM => A - %SMT_KEY_SC_STORAGE => B - $ => D :SLOAD - D :MSTORE(txCount) - ; Compute necessary keccak counters to finish batch - $ => A :MLOAD(batchL2DataLength) + $ => A :MLOAD(batchL2DataLength) ; Divide the total data length + 1 by 136 to obtain the keccak counter increment. ; 136 is the value used by the prover to increment keccak counters A + 1 :MSTORE(arithA) @@ -95,47 +68,75 @@ skipSetGlobalExitRoot: ;; - If an error is found in any transaction, the batch will not process any transaction ;;;;;;;;;;;;;;;;;; - E+1 => E :MSTORE(lastHashKIdUsed) - 0 :MSTORE(batchHashPos) - E :MSTORE(batchHashDataId) - $ => A :MLOAD(lastCtxUsed) - A + %CALLDATA_RESERVED_CTX => A :MSTORE(ctxTxToUse) ; Points at first context to be used when processing transactions. We reserve ctx = 1 for calldata - A :MSTORE(lastCtxUsed) + 1 => E :MSTORE(lastHashKIdUsed) + 0 :MSTORE(batchHashPos) + E :MSTORE(batchHashDataId) + $ => A :MLOAD(lastCtxUsed) + A + %CALLDATA_RESERVED_CTX => A :MSTORE(ctxTxToUse) ; Points at first context to be used when processing transactions. We reserve ctx = 1 for calldata + A :MSTORE(lastCtxUsed) $${var p = 0} ; set flag isLoadingRLP to 1 - 1 :MSTORE(isLoadingRLP) + 1 :MSTORE(isLoadingRLP) txLoopRLP: - $ => A :MLOAD(lastCtxUsed) - A+1 => CTX :MSTORE(lastCtxUsed) - - $ => A :MLOAD(batchL2DataLength) - $ => C :MLOAD(batchL2DataParsed) - C - A :JMPN(loadTx_rlp, endCheckRLP) + $ => A :MLOAD(lastCtxUsed) + A+1 => CTX :MSTORE(lastCtxUsed) + ; If batchL2DataLength is zero, we finalize batch + $ => A :MLOAD(batchL2DataLength), JMPZ(finalizeBatch) + $ => C :MLOAD(batchL2DataParsed) + C - A :JMPN(loadTx_rlp, endCheckRLP) endCheckRLP: ; set flag isLoadingRLP to 0 - 0 :MSTORE(isLoadingRLP) - :JMP(txLoop) + 0 :MSTORE(isLoadingRLP) ;;;;;;;;;;;;;;;;;; -;; D - Loop processing transactions -;; - Load transaction data and interpret it +;; D - Load blockNum variable +;; - Loop processing transactions +;; - Load transaction data and interpret it ;;;;;;;;;;;;;;;;;; -txLoop: - $ => A :MLOAD(pendingTxs) - A - 1 :MSTORE(pendingTxs), JMPN(processTxsEnd) +setBlockNum: + %LAST_BLOCK_STORAGE_POS => C + %ADDRESS_SYSTEM => A + %SMT_KEY_SC_STORAGE => B + $ :SLOAD,MSTORE(blockNum) + ; If forced batch ==> process a forced changeL2BlockTx + $ :MLOAD(isForced), JMPZ(txLoop, handleForcedBatch) - $ => A :MLOAD(ctxTxToUse) ; Load first context used by transaction - A + 1 => CTX :MSTORE(ctxTxToUse),JMP(processTx) +handleForcedBatch: + 1 :MSTORE(currentTx), JMP(processChangeL2Block) + +txLoop: + $ => A :MLOAD(pendingTxs) + A - 1 :MSTORE(pendingTxs), JMPN(processTxsEnd) + $ => A :MLOAD(currentTx) + A + 1 :MSTORE(currentTx) + $ => A :MLOAD(ctxTxToUse) ; Load first context used by transaction + A + 1 => CTX :MSTORE(ctxTxToUse) + ; Detect if transaction is a change L2 block tx + ; Store initial state at the beginning of the transaction + SR :MSTORE(originSR) + $ => A :MLOAD(isChangeL2BlockTx) + A - 1 :JMPZ(processChangeL2Block, processTx) -processTxEnd: - :CALL(updateSystemData) processTxFinished: - $${eventLog(onFinishTx)} :JMP(txLoop) + %MAX_CNT_BINARY - CNT_BINARY - 1 :JMPN(outOfCountersBinary) + ; Increase cumulativeGasUsed + $ => A :MLOAD(txGasLimit) + A - GAS => A + $ => B :MLOAD(cumulativeGasUsed) + $ :ADD, MSTORE(cumulativeGasUsed), CALL(fillBlockInfoTreeWithTxReceipt) + ; Increase txIndex + $ => A :MLOAD(txIndex) + A + 1 :MSTORE(txIndex) +processIntrinsicTxFinished: + $${eventLog(onFinishTx)} :JMP(txLoop) processTxsEnd: + ; Write values at storage at the end of block processing + :CALL(consolidateBlock) +finalizeBatch: ;;;;;;;;;;;;;;;;;; ;; E - Batch asserts & computations: @@ -145,28 +146,33 @@ processTxsEnd: ;; - compute newAccInputHash ;;;;;;;;;;;;;;;;;; +;; Batch must be always end correctly +;; Meaning that enough zk-counters should be available to finalize it +;; - 'keccaks' are reserved at the very beginning of the batch in order to be able to perform the final 'accInputHash' hash +;; - the rest of counters will not overflow since it is added a %SAFE_RANGE bandwith + ;; Get local exit root ; Read 'localExitRoot' variable from GLOBAL_EXIT_ROOT_MANAGER_L2 and store ; it to the 'newLocalExitRoot' input %ADDRESS_GLOBAL_EXIT_ROOT_MANAGER_L2 => A %SMT_KEY_SC_STORAGE => B %LOCAL_EXIT_ROOT_STORAGE_POS => C - $ => A :SLOAD - A :MSTORE(newLocalExitRoot) + $ => A :SLOAD + A :MSTORE(newLocalExitRoot) ;; Transactions size verification ; Ensure bytes added to compute the 'batchHashData' matches the number of bytes loaded from input - $ => A :MLOAD(batchHashPos) - $ :MLOAD(batchL2DataLength), ASSERT + $ => A :MLOAD(batchHashPos) + $ :MLOAD(batchL2DataLength), ASSERT ;; Compute 'batchHashData' A => HASHPOS - $ => E :MLOAD(batchHashDataId) + $ => E :MLOAD(batchHashDataId) - HASHPOS :HASHKLEN(E) - $ => A :HASHKDIGEST(E) + HASHPOS :HASHKLEN(E) + $ => A :HASHKDIGEST(E) - A :MSTORE(batchHashData) + A :MSTORE(batchHashData) ;; Compute 'newAccInputHash' 0 => HASHPOS @@ -178,17 +184,22 @@ processTxsEnd: $ => A :MLOAD(batchHashData) A :HASHK(0) - $ => A :MLOAD(globalExitRoot) + $ => A :MLOAD(l1InfoRoot) A :HASHK(0) 8 => D - $ => A :MLOAD(timestamp) + $ => A :MLOAD(timestampLimit) A :HASHK(0) 20 => D $ => A :MLOAD(sequencerAddr) A :HASHK(0) + 32 => D + $ => A :MLOAD(forcedBlockHashL1) + A :HASHK(0) + + ; finish accInputHash HASHPOS :HASHKLEN(0) $ => C :HASHKDIGEST(0) @@ -198,6 +209,11 @@ processTxsEnd: ;;;;;;;;;;;;;;;;;; ;; F - Finalize execution ;;;;;;;;;;;;;;;;;; + ; safety check that the output root is indeed inside the range limit of 4 goldilocks fields elements + SR => A + %FOUR_GOLDILOCKS => B + 1 :LT4 + ; Set output registers $ => D :MLOAD(newAccInputHash) $ => E :MLOAD(newLocalExitRoot) @@ -215,5 +231,7 @@ processTxsEnd: INCLUDE "end.zkasm" INCLUDE "load-tx-rlp.zkasm" INCLUDE "process-tx.zkasm" +INCLUDE "process-change-l2-block.zkasm" INCLUDE "utils.zkasm" +INCLUDE "block-info.zkasm" diff --git a/main/modexp/array_lib/array_add_AGTB.zkasm b/main/modexp/array_lib/array_add_AGTB.zkasm new file mode 100644 index 00000000..62816554 --- /dev/null +++ b/main/modexp/array_lib/array_add_AGTB.zkasm @@ -0,0 +1,123 @@ +;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; PRE: len(inA) >= len(inB) +;; +;; +;; array_add_AGTB: +;; in: +;; · C ∈ [1, 32], the len of inA +;; · D ∈ [1, 32], the len of inB +;; · inA ∈ [0, 2²⁵⁶ - 1]^C, the first input array +;; · inB ∈ [0, 2²⁵⁶ - 1]^D, the second input array +;; +;; output: +;; · out = inA + inB, with len(out) <= C + 1 +;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +; function array_add_AGTB(a: bigint[], b: bigint[], base: bigint): bigint[] { +; const alen = a.length; +; const blen = b.length; +; let result = new Array(alen); +; let sum = 0n; +; let carry = 0n; +; for (let i = 0; i < blen; i++) { +; sum = a[i] + b[i] + carry; +; carry = sum >= base ? 1n : 0n; +; out[i] = sum - carry * base; +; } +; for (let i = blen; i < alen; i++) { +; sum = a[i] + carry; +; carry = sum == base ? 1n : 0n; // the past carry is at most 1n +; out[i] = sum - carry * base; +; } + +; if (carry === 1n) { +; result.push(carry); +; } +; return result; +; } + +; NOTE: It's unoptimized for the case where len(inB) = 1. Use array_add_short instead. + +VAR GLOBAL array_add_AGTB_inA[%ARRAY_MAX_LEN] +VAR GLOBAL array_add_AGTB_inB[%ARRAY_MAX_LEN] +VAR GLOBAL array_add_AGTB_out[%ARRAY_MAX_LEN_PLUS_ONE] +VAR GLOBAL array_add_AGTB_len_inA +VAR GLOBAL array_add_AGTB_len_inB +VAR GLOBAL array_add_AGTB_len_out + +VAR GLOBAL array_add_AGTB_carry + +VAR GLOBAL array_add_AGTB_RR + +array_add_AGTB: + %MAX_CNT_BINARY - CNT_BINARY - 2*D - C+ D :JMPN(outOfCountersBinary) + %MAX_CNT_STEPS - STEP - 5 - 14*D - 3 - 9*C+9*D - 8 :JMPN(outOfCountersStep) + + RR :MSTORE(array_add_AGTB_RR) + + C :MSTORE(array_add_AGTB_len_inA) + D :MSTORE(array_add_AGTB_len_inB) + + 0 => E ; index in loops + 0 :MSTORE(array_add_AGTB_carry) + +array_add_AGTB_loopZero2inB: + ; The result will be stored as D·base + C + + 0 => D ; reset the carry chunk + + ; a[i] + b[i], where a[i],b[i] ∈ [0,base-1]: This number cannot be GT base + (base - 2), two chunks + $ => A :MLOAD(array_add_AGTB_inA + E) + $ => B :MLOAD(array_add_AGTB_inB + E) + $ => C :ADD, JMPNC(__array_add_AGTB_continue_1) + 1 => D + __array_add_AGTB_continue_1: + + ; sum = (a[i] + b[i]) + carry: This number cannot be GT base + (base - 1), two chunks + $ => A :MLOAD(array_add_AGTB_carry) + C => B + $ => C :ADD, JMPNC(__array_add_AGTB_continue_2) + 1 => D + __array_add_AGTB_continue_2: + + C :MSTORE(array_add_AGTB_out + E) + D :MSTORE(array_add_AGTB_carry) + + E + 1 => E,A + $ => B :MLOAD(array_add_AGTB_len_inB) + B - A :JMPZ(array_add_AGTB_loop_index_check, array_add_AGTB_loopZero2inB) + +array_add_AGTB_loop_index_check: + $ => B :MLOAD(array_add_AGTB_len_inA) + B - A :JMPZ(array_add_AGTB_check_carry) + +array_add_AGTB_loopInB2InA: + 0 => D ; reset the carry chunk + + ; sum = a[i] + carry: This number cannot be GT base, two chunks + $ => A :MLOAD(array_add_AGTB_inA + E) + $ => B :MLOAD(array_add_AGTB_carry) + $ => C :ADD, JMPNC(__array_add_AGTB_continue_3) + 1 => D + __array_add_AGTB_continue_3: + + C :MSTORE(array_add_AGTB_out + E) + D :MSTORE(array_add_AGTB_carry) + + E + 1 => E,A + $ => B :MLOAD(array_add_AGTB_len_inA) + B - A :JMPZ(array_add_AGTB_check_carry, array_add_AGTB_loopInB2InA) + +array_add_AGTB_check_carry: + D => A + A :JMPZ(__array_add_AGTB_continue_4) + ; In this case, the carry = 1 and we should append it to the result + 1 :MSTORE(array_add_AGTB_out + E) + E + 1 :MSTORE(array_add_AGTB_len_out) + :JMP(array_add_AGTB_end) + __array_add_AGTB_continue_4: + E :MSTORE(array_add_AGTB_len_out) + +array_add_AGTB_end: + $ => RR :MLOAD(array_add_AGTB_RR) + :RETURN \ No newline at end of file diff --git a/main/modexp/array_lib/array_add_short.zkasm b/main/modexp/array_lib/array_add_short.zkasm new file mode 100644 index 00000000..6fe10b0b --- /dev/null +++ b/main/modexp/array_lib/array_add_short.zkasm @@ -0,0 +1,85 @@ +;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; +;; array_add_short: +;; in: +;; · C ∈ [1, 32], the len of inA +;; · inA ∈ [0, 2²⁵⁶ - 1]^C, the first input array +;; · inB ∈ [0, 2²⁵⁶ - 1], the second input +;; +;; output: +;; · out = inA + inB, with len(out) <= C + 1 +;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +; function array_add_short(a: bigint[], b: bigint, base: bigint): bigint[] { +; const alen = a.length; +; let result = new Array(alen); +; let sum = 0n; +; let carry = b; +; for (let i = 0; i < alen; i++) { +; sum = a[i] + carry; +; carry = sum >= base ? 1n : 0n; +; out[i] = sum - carry * base; +; } + +; if (carry === 1n) { +; result.push(carry); +; } +; return result; +; } + +VAR GLOBAL array_add_short_inA[%ARRAY_MAX_LEN] +VAR GLOBAL array_add_short_inB +VAR GLOBAL array_add_short_out[%ARRAY_MAX_LEN_PLUS_ONE] +VAR GLOBAL array_add_short_len_inA +VAR GLOBAL array_add_short_len_out + +VAR GLOBAL array_add_short_carry + +VAR GLOBAL array_add_short_RR + +array_add_short: + %MAX_CNT_BINARY - CNT_BINARY - C :JMPN(outOfCountersBinary) + %MAX_CNT_STEPS - STEP - 5 - 10*C - 8 :JMPN(outOfCountersStep) + + RR :MSTORE(array_add_short_RR) + + C :MSTORE(array_add_short_len_inA) + + 0 => E ; index in loops + $ => A :MLOAD(array_add_short_inB) + A :MSTORE(array_add_short_carry) + +array_add_short_loopZero2inA: + ; The result will be stored as D·base + C + + 0 => D ; reset the carry chunk + + ; a[i] + carry, where a[i] ∈ [0,base-1]: + ; · If i = 0, then carry = inB and then the number cannot be GT base + (base - 2), two chunks + ; · Otherwise, the number cannot be GT base, two chunks + $ => A :MLOAD(array_add_short_inA + E) + $ => B :MLOAD(array_add_short_carry) + $ => C :ADD, JMPNC(__array_add_short_continue_1) + 1 => D + __array_add_short_continue_1: + + C :MSTORE(array_add_short_out + E) + D :MSTORE(array_add_short_carry) + + E + 1 => E,A + $ => B :MLOAD(array_add_short_len_inA) + B - A :JMPZ(array_add_short_check_carry, array_add_short_loopZero2inA) + +array_add_short_check_carry: + D => A + A :JMPZ(__array_add_short_continue_2) + ; In this case, the carry = 1 and we should append it to the result + 1 :MSTORE(array_add_short_out + E) + E + 1 :MSTORE(array_add_short_len_out) + :JMP(array_add_short_end) + __array_add_short_continue_2: + E :MSTORE(array_add_short_len_out) + +array_add_short_end: + $ => RR :MLOAD(array_add_short_RR) + :RETURN \ No newline at end of file diff --git a/main/modexp/array_lib/array_div.zkasm b/main/modexp/array_lib/array_div.zkasm new file mode 100644 index 00000000..9a1e4e5e --- /dev/null +++ b/main/modexp/array_lib/array_div.zkasm @@ -0,0 +1,215 @@ +;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; PRE: The input arrays have been trimmed; +;; POST: The quotient and remainder are trimmed. +;; +;; array_div: +;; in: +;; · C ∈ [1, 32], the len of inA +;; · D ∈ [1, 32], the len of inB +;; · inA ∈ [0, 2²⁵⁶ - 1]^C, the first input array +;; · inB ∈ [0, 2²⁵⁶ - 1]^D, the second input array +;; +;; output: +;; · [quo,rem] = [inA / inB, inA % inB], with len(quo) <= C - D + 1, len(rem) <= D +;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +; function array_div(a: bigint[], b: bigint[], base: bigint): bigint[] { +; if (a === [0n]) { +; if (b === [0n]) { +; throw new Error("Division by zero"); +; } +; return [0n, 0n]; +; } else if (b === [0n]) { +; throw new Error("Division by zero"); +; } +; +; if (a === b) { +; return [1n, 0n]; +; } else if (a < b) { +; return [0n, a]; +; } +; +; if (b.length === 1) { +; return array_div_short(a, b, base); +; } +; return array_div_long(a, b, base); +; } + +VAR GLOBAL array_div_inA[%ARRAY_MAX_LEN] +VAR GLOBAL array_div_inB[%ARRAY_MAX_LEN] +VAR GLOBAL array_div_quo[%ARRAY_MAX_LEN] +VAR GLOBAL array_div_rem[%ARRAY_MAX_LEN] + +VAR GLOBAL array_div_len_inA +VAR GLOBAL array_div_len_inB +VAR GLOBAL array_div_len_quo +VAR GLOBAL array_div_len_rem + +VAR GLOBAL array_div_RR + +; ERROR CODES (B) +; 0 - no error +; 1 - inB is zero + +array_div: + %MAX_CNT_BINARY - CNT_BINARY - 2 :JMPN(outOfCountersBinary) + %MAX_CNT_STEPS - STEP - 12 - 3*C - 3*D - 1 :JMPN(outOfCountersStep) + + RR :MSTORE(array_div_RR) + + C :MSTORE(array_div_len_inA) + D :MSTORE(array_div_len_inB) + + ; Let's cover the edge cases + 1 => B + ; 1] Is C == 1 and inA == 0? + C - B :JMPNZ(__array_div_inA_continue) + $ => A :MLOAD(array_div_inA) + $ :LT, JMPC(array_div_inA_is_zero) + __array_div_inA_continue: + + ; 2] Is D == 1 and inB == 0? + D - B :JMPNZ(__array_div_inB_continue_1) + $ => A :MLOAD(array_div_inB) + $ :LT, JMPC(array_div_inB_is_zero) + __array_div_inB_continue_1: + + ; 3] Check if inA = inB or inA < inB + C - 1 => RR + D - 1 => E +array_div_compare_inA: + $ => A :MLOAD(array_div_inA + RR) + A :MSTORE(array_compare_inA + RR) + RR - 1 => RR :JMPN(array_div_compare_inB, array_div_compare_inA) + +array_div_compare_inB: + $ => A :MLOAD(array_div_inB + E) + A :MSTORE(array_compare_inB + E) + E - 1 => E :JMPN(array_div_compare, array_div_compare_inB) + +array_div_compare: + :CALL(array_compare) + + %MAX_CNT_STEPS - STEP - 5 - 3*C - 3*D - 1 :JMPN(outOfCountersStep) + + $ => A :MLOAD(array_compare_result), JMPZ(array_div_prep_inALTinB) + A - 1 :JMPZ(array_div_same_input) + ; From here, inA > inB + + C - 1 => RR + D - 1 => E + D - 1 :JMPZ(array_div_inA_to_div_short, array_div_inA_to_div_long); worst case is div long + +; Begin of edge cases +array_div_inA_is_zero: + ;Is D == 1 and inB == 0? 0/0 is undefined + D - B :JMPNZ(__array_div_inB_continue_2) + $ => A :MLOAD(array_div_inB) + $ :LT, JMPC(array_div_inB_is_zero) + __array_div_inB_continue_2: + ; From here, inB != 0 + + ; Return [q,r] = [0,0] and len(q) = 1, len(r) = 1 + 0 :MSTORE(array_div_quo) + 0 :MSTORE(array_div_rem) + 1 :MSTORE(array_div_len_quo) + 1 :MSTORE(array_div_len_rem) + 0 => B :JMP(array_div_end) + +array_div_inB_is_zero: + ; Error, you cannot divide by 0 + 1 => B :JMP(array_div_end) + +array_div_same_input: + 1 :MSTORE(array_div_quo) + 0 :MSTORE(array_div_rem) + 1 :MSTORE(array_div_len_quo) + 1 :MSTORE(array_div_len_rem) + 0 => B :JMP(array_div_end) + +array_div_prep_inALTinB: + C :MSTORE(array_div_len_rem) + 1 :MSTORE(array_div_len_quo) + + %MAX_CNT_STEPS - STEP - 1 - 4*C - 2 :JMPN(outOfCountersStep) + + C - 1 => RR +array_div_inALTinB: + $ => A :MLOAD(array_div_inA + RR) + A :MSTORE(array_div_rem + RR) + RR - 1 => RR :JMPN(array_div_inALTinB_before_end, array_div_inALTinB) + +array_div_inALTinB_before_end: + 0 :MSTORE(array_div_quo) + 0 => B :JMP(array_div_end) +; End of edge cases + +; Long +array_div_inA_to_div_long: + $ => A :MLOAD(array_div_inA + RR) + A :MSTORE(array_div_long_inA + RR) + RR - 1 => RR :JMPN(array_div_inB_to_div_long, array_div_inA_to_div_long) + +array_div_inB_to_div_long: + $ => A :MLOAD(array_div_inB + E) + A :MSTORE(array_div_long_inB + E) + E - 1 => E :JMPN(array_div_compute_long, array_div_inB_to_div_long) + +array_div_compute_long: + :CALL(array_div_long) + + %MAX_CNT_STEPS - STEP - 7 :JMPN(outOfCountersStep) + + $ => C :MLOAD(array_div_long_len_quo) + $ => D :MLOAD(array_div_long_len_rem) + C :MSTORE(array_div_len_quo) + D :MSTORE(array_div_len_rem) + C - 1 => RR + D - 1 => E + + %MAX_CNT_STEPS - STEP - 3*C - 3*D - 2 :JMPN(outOfCountersStep) + +array_div_assign_long_quo: + $ => A :MLOAD(array_div_long_quo + RR) + A :MSTORE(array_div_quo + RR) + RR - 1 => RR :JMPN(array_div_assign_long_rem, array_div_assign_long_quo) + +array_div_assign_long_rem: + $ => A :MLOAD(array_div_long_rem + E) + A :MSTORE(array_div_rem + E) + E - 1 => E :JMPN(array_div_end, array_div_assign_long_rem) + +; Short +array_div_inA_to_div_short: + $ => A :MLOAD(array_div_inA + RR) + A :MSTORE(array_div_short_inA + RR) + RR - 1 => RR :JMPN(array_div_inB_to_div_short, array_div_inA_to_div_short) + +array_div_inB_to_div_short: + $ => A :MLOAD(array_div_inB) + A :MSTORE(array_div_short_inB) + +array_div_compute_short: + :CALL(array_div_short) + + %MAX_CNT_STEPS - STEP - 5 :JMPN(outOfCountersStep) + + $ => C :MLOAD(array_div_short_len_quo) + C :MSTORE(array_div_len_quo) + 1 :MSTORE(array_div_len_rem) + C - 1 => RR + + %MAX_CNT_STEPS - STEP - 3*C - 4 :JMPN(outOfCountersStep) + +array_div_assign_short_quo: + $ => A :MLOAD(array_div_short_quo + RR) + A :MSTORE(array_div_quo + RR) + RR - 1 => RR :JMPN(array_div_assign_short_rem, array_div_assign_short_quo) + +array_div_assign_short_rem: + $ => A :MLOAD(array_div_short_rem) + A :MSTORE(array_div_rem) + +array_div_end: + $ => RR :MLOAD(array_div_RR) + :RETURN \ No newline at end of file diff --git a/main/modexp/array_lib/array_div_long.zkasm b/main/modexp/array_lib/array_div_long.zkasm new file mode 100644 index 00000000..95d17a08 --- /dev/null +++ b/main/modexp/array_lib/array_div_long.zkasm @@ -0,0 +1,284 @@ +;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; PRE: The input arrays have been trimmed. +;; POST: The quotient and remainder are trimmed. +;; +;; array_div_long: +;; in: +;; · C ∈ [1, 32], the len of inA +;; · D ∈ [1, 32], the len of inB +;; · inA ∈ [0, 2²⁵⁶ - 1]^C, the first input array +;; · inB ∈ [0, 2²⁵⁶ - 1]^D, the second input array +;; +;; output: +;; · [quo,rem] = [inA / inB, inA % inB], with len(quo) <= C - D + 1, len(rem) <= D +;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +; function array_div_long(a: bigint[], b: bigint[], base: bigint): bigint[] { +; if (a === [0n]) { +; if (b === [0n]) { +; throw new Error("Division by zero"); +; } +; return [0n, 0n]; +; } else if (b === [0n]) { +; throw new Error("Division by zero"); +; } +; +; if (a === b) { +; return [1n, 0n]; +; } else if (a < b) { +; return [0n, a]; +; } +; } + +; NOTE: This function receives the actual result from the helper (avoiding the need of computing divisions); +; checks the correctness of the result and returns the result to the caller + +VAR GLOBAL array_div_long_inA[%ARRAY_MAX_LEN] +VAR GLOBAL array_div_long_inB[%ARRAY_MAX_LEN] +VAR GLOBAL array_div_long_quo[%ARRAY_MAX_LEN] +VAR GLOBAL array_div_long_rem[%ARRAY_MAX_LEN] + +VAR GLOBAL array_div_long_len_inA +VAR GLOBAL array_div_long_len_inB +VAR GLOBAL array_div_long_len_quo +VAR GLOBAL array_div_long_len_rem + +VAR GLOBAL array_div_long_RR + +; ERROR CODES (B) +; 0 - no error +; 1 - inB is zero + +array_div_long: + %MAX_CNT_BINARY - CNT_BINARY - 2 :JMPN(outOfCountersBinary) + %MAX_CNT_STEPS - STEP - 12 - 3*C - 3*D - 1 :JMPN(outOfCountersStep) + + RR :MSTORE(array_div_long_RR) + + C :MSTORE(array_div_long_len_inA) + D :MSTORE(array_div_long_len_inB) + + ; Let's cover the edge cases + 1 => B + ; 1] Is C == 1 and inA == 0? + C - B :JMPNZ(__array_div_long_inA_continue) + $ => A :MLOAD(array_div_long_inA) + $ :LT, JMPC(array_div_long_inA_is_zero) + __array_div_long_inA_continue: + + ; 2] Is D == 1 and inB == 0? + D - B :JMPNZ(__array_div_long_inB_continue_1) + $ => A :MLOAD(array_div_long_inB) + $ :LT, JMPC(array_div_long_inB_is_zero) + __array_div_long_inB_continue_1: + + ; 3] Check if inA = inB or inA < inB + C - 1 => RR + D - 1 => E +array_div_long_compare_inA1: + $ => A :MLOAD(array_div_long_inA + RR) + A :MSTORE(array_compare_inA + RR) + RR - 1 => RR :JMPN(array_div_long_compare_inB1, array_div_long_compare_inA1) + +array_div_long_compare_inB1: + $ => A :MLOAD(array_div_long_inB + E) + A :MSTORE(array_compare_inB + E) + E - 1 => E :JMPN(array_div_long_compare1, array_div_long_compare_inB1) + +array_div_long_compare1: + :CALL(array_compare) + + %MAX_CNT_BINARY - CNT_BINARY - 1 :JMPN(outOfCountersBinary) + %MAX_CNT_STEPS - STEP - 12 - 4*%ARRAY_MAX_LEN - 3*D - 1 :JMPN(outOfCountersStep) + + $ => A :MLOAD(array_compare_result), JMPZ(array_div_long_prep_inALTinB) + A - 1 :JMPZ(array_div_long_same_input) + ; From here, inA > inB + + ; Strategy: Divide outside and check the result inside + $${MPdiv(addr.array_div_long_inA,mem.array_div_long_len_inA,addr.array_div_long_inB,mem.array_div_long_len_inB)} + + :JMP(array_div_long_prepare_mul_quo_inB) + +; Begin of edge cases +array_div_long_inA_is_zero: + ; Is D == 1 and inB == 0? 0/0 is undefined + D - B :JMPNZ(__array_div_long_inB_continue_2) + $ => A :MLOAD(array_div_long_inB) + $ :LT, JMPC(array_div_long_inB_is_zero) + __array_div_long_inB_continue_2: + ; From here, inA == 0 and inB != 0 + + ; Return [q,r] = [0,0] and len(q) = 1, len(r) = 1 + 0 :MSTORE(array_div_long_quo) + 0 :MSTORE(array_div_long_rem) + 1 :MSTORE(array_div_long_len_quo) + 1 :MSTORE(array_div_long_len_rem) + 0 => B :JMP(array_div_long_end) + +array_div_long_inB_is_zero: + ; Error, you cannot divide by 0 + 1 => B :JMP(array_div_long_end) + +array_div_long_same_input: + ; if inA = inB, then return [1, 0] and len(q) = 1, len(r) = 1 + 1 :MSTORE(array_div_long_quo) + 0 :MSTORE(array_div_long_rem) + 1 :MSTORE(array_div_long_len_quo) + 1 :MSTORE(array_div_long_len_rem) + 0 => B :JMP(array_div_long_end) + +array_div_long_prep_inALTinB: + ; if inA < inB, then return [0, inA] and len(q) = 1, len(r) = C + 1 :MSTORE(array_div_long_len_quo) + C :MSTORE(array_div_long_len_rem) + + %MAX_CNT_STEPS - STEP - 1 - 3*C - 2 :JMPN(outOfCountersStep) + + C - 1 => RR +array_div_long_inALTinB: + $ => A :MLOAD(array_div_long_inA + RR) + A :MSTORE(array_div_long_rem + RR) + RR - 1 => RR :JMPN(array_div_long_inALTinB_before_end, array_div_long_inALTinB) + +array_div_long_inALTinB_before_end: + 0 :MSTORE(array_div_long_quo) + 0 => B :JMP(array_div_long_end) +; End of edge cases + +array_div_long_prepare_mul_quo_inB: + $0{receiveLenQuotient()} => C + + ; The received length must be between 1 and %ARRAY_MAX_LEN + C - 1 => RR :JMPN(failAssert) ; If C = 0, then fail + %ARRAY_MAX_LEN - C :JMPN(failAssert) ; If C > %ARRAY_MAX_LEN, then fail + ; From here, 1 <= C <= %ARRAY_MAX_LEN + + ; To avoid non-determinism, we must ensure that the quotient is trimmed + ; i.e., that its last chunk is not 0 + ${receiveQuotientChunk(RR)} => A + 0 => B + 0 :EQ + ; From here, the quotient is trimmed + + C :MSTORE(array_div_long_len_quo) + $ => D :MLOAD(array_div_long_len_inB) + C - 1 => RR + D - 1 => E + + ; save the first non-zero chunk of quo + A :MSTORE(array_div_long_quo + RR) + A :MSTORE(array_mul_inA + RR) + RR - 1 => RR :JMPN(array_div_long_inB_to_mul) + +array_div_long_quo_to_mul: + ${receiveQuotientChunk(RR)} => A + A :MSTORE(array_div_long_quo + RR) + A :MSTORE(array_mul_inA + RR) + RR - 1 => RR :JMPN(array_div_long_inB_to_mul, array_div_long_quo_to_mul) + +array_div_long_inB_to_mul: + $ => A :MLOAD(array_div_long_inB + E) + A :MSTORE(array_mul_inB + E) + E - 1 => E :JMPN(array_div_long_mul_quo_inB, array_div_long_inB_to_mul) + +array_div_long_mul_quo_inB: + :CALL(array_mul) + + $ => D :MLOAD(array_div_long_len_inB) + %MAX_CNT_BINARY - CNT_BINARY - 1 :JMPN(outOfCountersBinary) + %MAX_CNT_STEPS - STEP - 8 - 3*%ARRAY_MAX_LEN - 3*D - 1 :JMPN(outOfCountersStep) + + ; Check the remainder + $0{receiveLenRemainder()} => D + + ; 1] The received length must be between 1 and %ARRAY_MAX_LEN + D - 1 => E :JMPN(failAssert) ; If D = 0, then fail + %ARRAY_MAX_LEN - D :JMPN(failAssert) ; If D > %ARRAY_MAX_LEN, then fail + ; From here, 1 <= D <= %ARRAY_MAX_LEN + + ; 2] To avoid non-determinism, we must ensure that the remainder is trimmed + ; i.e., that its last chunk is not 0 + ${receiveRemainderChunk(E)} => A + 0 => B + 0 :EQ + ; From here, the remainder is trimmed + + ; 3] Finally, we must ensure that the remainder is lower than inB + $ => C :MLOAD(array_div_long_len_inB) + C - 1 => RR + D - 1 => E + + ; save the first non-zero chunk of rem + A :MSTORE(array_compare_inB + E) + E - 1 => E :JMPN(array_div_long_compare_inB2) + +array_div_long_compare_rem: + ${receiveRemainderChunk(E)} => A + A :MSTORE(array_compare_inB + E) + E - 1 => E :JMPN(array_div_long_compare_inB2, array_div_long_compare_rem) + +array_div_long_compare_inB2: + $ => A :MLOAD(array_div_long_inB + RR) + A :MSTORE(array_compare_inA + RR) + RR - 1 => RR :JMPN(array_div_long_compare2, array_div_long_compare_inB2) + +array_div_long_compare2: + :CALL(array_compare) + + %MAX_CNT_STEPS - STEP - 5 - 3*%ARRAY_MAX_LEN - 4*%ARRAY_MAX_LEN - 1 :JMPN(outOfCountersStep) + + 2 :MLOAD(array_compare_result) + + D :MSTORE(array_div_long_len_rem) + + ; prepare output and remainder to be added + $ => C :MLOAD(array_mul_len_out) + C - 1 => RR + D - 1 => E + +array_div_long_res_to_add: + $ => A :MLOAD(array_mul_out + RR) + A :MSTORE(array_add_AGTB_inA + RR) + RR - 1 => RR :JMPN(array_div_long_rem_to_add, array_div_long_res_to_add) + +array_div_long_rem_to_add: + $ => A :MLOAD(array_compare_inB + E) ; Load the remainder used in the comparison + A :MSTORE(array_div_long_rem + E) + A :MSTORE(array_add_AGTB_inB + E) + E - 1 => E :JMPN(array_div_long_add_res_rem, array_div_long_rem_to_add) + +array_div_long_add_res_rem: + :CALL(array_add_AGTB) + + %MAX_CNT_STEPS - STEP - 5 :JMPN(outOfCountersStep) + + ; prepare next + $ => C :MLOAD(array_add_AGTB_len_out) + $ => D :MLOAD(array_div_long_len_inA) + C - 1 => RR + D - 1 => E + + %MAX_CNT_STEPS - STEP - 3*%ARRAY_MAX_LEN - 3*D - 1 :JMPN(outOfCountersStep) + +array_div_long_compare_inA2: + $ => A :MLOAD(array_add_AGTB_out + RR) + A :MSTORE(array_compare_inA + RR) + RR - 1 => RR :JMPN(array_div_long_compare_inB3, array_div_long_compare_inA2) + +array_div_long_compare_inB3: + $ => A :MLOAD(array_div_long_inA + E) + A :MSTORE(array_compare_inB + E) + E - 1 => E :JMPN(array_div_long_compare3, array_div_long_compare_inB3) + +array_div_long_compare3: + :CALL(array_compare) + + %MAX_CNT_STEPS - STEP - 4 :JMPN(outOfCountersStep) + + 1 :MLOAD(array_compare_result) + 0 => B + +array_div_long_end: + $ => RR :MLOAD(array_div_long_RR) + :RETURN \ No newline at end of file diff --git a/main/modexp/array_lib/array_div_short.zkasm b/main/modexp/array_lib/array_div_short.zkasm new file mode 100644 index 00000000..577b57ad --- /dev/null +++ b/main/modexp/array_lib/array_div_short.zkasm @@ -0,0 +1,222 @@ +;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; PRE: The input arrays have been trimmed. +;; POST: The quotient is trimmed. +;; +;; array_div_short: +;; in: +;; · C ∈ [1, 32], the len of inA +;; · inA ∈ [0, 2²⁵⁶ - 1]^C, the first input array +;; · inB ∈ [0, 2²⁵⁶ - 1], the second input +;; +;; output: +;; · [quo,rem] = [inA / inB[0], inA % inB[0]], with len(quo) <= C, len(rem) = 1 +;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +; function array_div_short(a: bigint[], b: bigint, base: bigint): bigint[] { +; if (a === [0n]) { +; if (b === 0n) { +; throw new Error("Division by zero"); +; } +; return [0n, 0n]; +; } else if (b === 0n) { +; throw new Error("Division by zero"); +; } +; +; if (a === b) { +; return [1n, 0n]; +; } else if (a < b) { +; return [0n, a]; +; } +; } + +; NOTE: This function receives the actual result from the helper (avoiding the need of computing divisions); +; checks the correctness of the result and returns the result to the caller + +VAR GLOBAL array_div_short_inA[%ARRAY_MAX_LEN] +VAR GLOBAL array_div_short_inB +VAR GLOBAL array_div_short_quo[%ARRAY_MAX_LEN] +VAR GLOBAL array_div_short_rem + +VAR GLOBAL array_div_short_len_inA +VAR GLOBAL array_div_short_len_quo + +VAR GLOBAL array_div_short_RR + +; ERROR CODES (B) +; 0 - no error +; 1 - inB is zero + +array_div_short: + %MAX_CNT_BINARY - CNT_BINARY - 2 :JMPN(outOfCountersBinary) + %MAX_CNT_STEPS - STEP - 11 - 3*C - 3 :JMPN(outOfCountersStep) + + RR :MSTORE(array_div_short_RR) + + C :MSTORE(array_div_short_len_inA) + C :MSTORE(array_div_short_len_quo) + + ; Let's cover the edge cases + 1 => B + ; 1] Is C == 1 and inA == 0? + C - B :JMPNZ(__array_div_short_inA_continue) + $ => A :MLOAD(array_div_short_inA) + $ :LT, JMPC(array_div_short_inA_is_zero) + __array_div_short_inA_continue: + + ; 2] Is inB == 0? + $ => A :MLOAD(array_div_short_inB) + $ :LT, JMPC(array_div_short_inB_is_zero) + + ; Check whether inA = inB or inA < inB + C - 1 => RR + 1 => D +array_div_short_inA_to_compare1: + $ => A :MLOAD(array_div_short_inA + RR) + A :MSTORE(array_compare_inA + RR) + RR - 1 => RR :JMPN(array_div_short_inB_to_compare, array_div_short_inA_to_compare1) + +array_div_short_inB_to_compare: + $ => A :MLOAD(array_div_short_inB) + A :MSTORE(array_compare_inB) + +array_div_short_compare_inA_inB: + :CALL(array_compare) + + %MAX_CNT_BINARY - CNT_BINARY - 1 :JMPN(outOfCountersBinary) + %MAX_CNT_STEPS - STEP - 10 - 4*%ARRAY_MAX_LEN - 3 :JMPN(outOfCountersStep) + + $ => A :MLOAD(array_compare_result), JMPZ(array_div_short_inALTinB) + A - 1 :JMPZ(array_div_short_same_input) + ; From here, inA > inB + + ; Strategy: Divide outside and check the result inside + $${MPdiv_short(addr.array_div_short_inA,mem.array_div_short_len_inA,mem.array_div_short_inB)} + + :JMP(array_div_short_prepare_mul_quo_inB) + +; Begin of edge cases +array_div_short_inA_is_zero: + ; Is inB == 0? 0/0 is undefined + $ => A :MLOAD(array_div_short_inB) + $ :LT, JMPC(array_div_short_inB_is_zero) + ; From here, inB != 0 + + ; Return [q,r] = [0,0] and len(q) = 1, len(r) = 1 + 0 :MSTORE(array_div_short_quo) + 0 :MSTORE(array_div_short_rem) + 1 :MSTORE(array_div_short_len_quo) + 0 => B :JMP(array_div_short_end) + +array_div_short_inB_is_zero: + ; Error, you cannot divide by 0 + 1 => B :JMP(array_div_short_end) + +array_div_short_same_input: + ; If inA = inB, then the result is [1,0] since inA = 1·inB + 0 + 1 :MSTORE(array_div_short_quo) + 1 :MSTORE(array_div_short_len_quo) + 0 :MSTORE(array_div_short_rem) + 0 => B :JMP(array_div_short_end) + +array_div_short_inALTinB: + ; If inA < inB, then the result is [0, inA] since inA = 0·inB + inA + 0 :MSTORE(array_div_short_quo) + 1 :MSTORE(array_div_short_len_quo) + $ => A :MLOAD(array_div_short_inA) + A :MSTORE(array_div_short_rem) + 0 => B :JMP(array_div_short_end) +; End of edge cases + +array_div_short_prepare_mul_quo_inB: + $0{receiveLenQuotient_short()} => C + + ; The received length must be between 1 and %ARRAY_MAX_LEN + C - 1 => RR :JMPN(failAssert) ; If C = 0, then fail + %ARRAY_MAX_LEN - C :JMPN(failAssert) ; If C > %ARRAY_MAX_LEN, then fail + ; From here, 1 <= C <= %ARRAY_MAX_LEN + + ; To avoid non-determinism, we must ensure that the quotient is trimmed + ; i.e., that its last chunk is not 0 + ${receiveQuotientChunk_short(RR)} => A + 0 => B + 0 :EQ + ; From here, the quotient is trimmed + + C :MSTORE(array_div_short_len_quo) + C - 1 => RR + + ; save the first non-zero chunk of quo + A :MSTORE(array_div_short_quo + RR) + A :MSTORE(array_mul_short_inA + RR) + RR - 1 => RR :JMPN(array_div_short_inB_to_mul) + +array_div_short_quo_to_mul: + ${receiveQuotientChunk_short(RR)} => A + A :MSTORE(array_div_short_quo + RR) + A :MSTORE(array_mul_short_inA + RR) + RR - 1 => RR :JMPN(array_div_short_inB_to_mul, array_div_short_quo_to_mul) + +array_div_short_inB_to_mul: + $ => A :MLOAD(array_div_short_inB) + A :MSTORE(array_mul_short_inB) + +array_div_short_mul_quo_inB: + :CALL(array_mul_short) + + %MAX_CNT_BINARY - CNT_BINARY - 1 :JMPN(outOfCountersBinary) + %MAX_CNT_STEPS - STEP - 2 - 3*%ARRAY_MAX_LEN - 6 :JMPN(outOfCountersStep) + + ; prepare next + $ => C :MLOAD(array_mul_short_len_out) + C - 1 => RR + +array_div_short_result_to_add: + $ => A :MLOAD(array_mul_short_out + RR) + A :MSTORE(array_add_short_inA + RR) + RR - 1 => RR :JMPN(array_div_short_rem_to_add, array_div_short_result_to_add) + +array_div_short_rem_to_add: + ${receiveRemainderChunk_short()} => A + + ; We must ensure the the remaider is lower than inB + $ => B :MLOAD(array_div_short_inB) + 1 :LT + + A :MSTORE(array_div_short_rem) + A :MSTORE(array_add_short_inB) + +array_div_short_add_result_rem: + :CALL(array_add_short) + + %MAX_CNT_STEPS - STEP - 5 :JMPN(outOfCountersStep) + + ; prepare next + $ => C :MLOAD(array_add_short_len_out) + $ => D :MLOAD(array_div_short_len_inA) + C - 1 => RR + D - 1 => E + + %MAX_CNT_STEPS - STEP - 3*%ARRAY_MAX_LEN - 3*D - 1 :JMPN(outOfCountersStep) + +array_div_short_result_to_compare: + $ => A :MLOAD(array_add_short_out + RR) + A :MSTORE(array_compare_inA + RR) + RR - 1 => RR :JMPN(array_div_short_inA_to_compare2, array_div_short_result_to_compare) + +array_div_short_inA_to_compare2: + $ => A :MLOAD(array_div_short_inA + E) + A :MSTORE(array_compare_inB + E) + E - 1 => E :JMPN(array_div_short_compare_result_inA, array_div_short_inA_to_compare2) + +array_div_short_compare_result_inA: + :CALL(array_compare) + + %MAX_CNT_STEPS - STEP - 4 :JMPN(outOfCountersStep) + + 1 :MLOAD(array_compare_result) + + 0 => B ; error code + +array_div_short_end: + $ => RR :MLOAD(array_div_short_RR) + :RETURN \ No newline at end of file diff --git a/main/modexp/array_lib/array_mul.zkasm b/main/modexp/array_lib/array_mul.zkasm new file mode 100644 index 00000000..e4551c1b --- /dev/null +++ b/main/modexp/array_lib/array_mul.zkasm @@ -0,0 +1,97 @@ +;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; POST: out is trimmed +;; +;; array_mul: +;; in: +;; · C ∈ [1, 32], the len of inA +;; · D ∈ [1, 32], the len of inB +;; · inA ∈ [0, 2²⁵⁶ - 1]^C, the first input array +;; · inB ∈ [0, 2²⁵⁶ - 1]^D, the second input array +;; +;; output: +;; · out = inA·inB, with len(out) <= C + D +;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +; function array_mul(a: bigint[], b: bigint[], base: bigint): bigint[] { +; if (b.length === 1) { +; return array_mul_short(a, b, base); +; } +; return array_mul_long(a, b, base); +; } + +VAR GLOBAL array_mul_inA[%ARRAY_MAX_LEN] +VAR GLOBAL array_mul_inB[%ARRAY_MAX_LEN] +VAR GLOBAL array_mul_out[%ARRAY_MAX_LEN_DOUBLED] +VAR GLOBAL array_mul_len_inA +VAR GLOBAL array_mul_len_inB +VAR GLOBAL array_mul_len_out + +VAR GLOBAL array_mul_RR + +array_mul: + %MAX_CNT_STEPS - STEP - 6 - 3*C - 3*D - 1 :JMPN(outOfCountersStep) + + RR :MSTORE(array_mul_RR) + + C :MSTORE(array_mul_len_inA) + D :MSTORE(array_mul_len_inB) + + C - 1 => RR + D - 1 => E + D - 1 :JMPZ(array_mul_inA_to_mul_short) ; worst case is mul long +; Long +array_mul_inA_to_mul_long: + $ => A :MLOAD(array_mul_inA + RR) + A :MSTORE(array_mul_long_inA + RR) + RR - 1 => RR :JMPN(array_mul_inB_to_mul_long, array_mul_inA_to_mul_long) + +array_mul_inB_to_mul_long: + $ => A :MLOAD(array_mul_inB + E) + A :MSTORE(array_mul_long_inB + E) + E - 1 => E :JMPN(array_mul_compute_long, array_mul_inB_to_mul_long) + +array_mul_compute_long: + :CALL(array_mul_long) + + %MAX_CNT_STEPS - STEP - 4 :JMPN(outOfCountersStep) + + $ => C :MLOAD(array_mul_long_len_out) + C :MSTORE(array_mul_len_out) + C - 1 => RR + + %MAX_CNT_STEPS - STEP - 3*C - 2 :JMPN(outOfCountersStep) + +array_mul_assign_long: + $ => A :MLOAD(array_mul_long_out + RR) + A :MSTORE(array_mul_out + RR) + RR - 1 => RR :JMPN(array_mul_end, array_mul_assign_long) + +; Short +array_mul_inA_to_mul_short: + $ => A :MLOAD(array_mul_inA + RR) + A :MSTORE(array_mul_short_inA + RR) + RR - 1 => RR :JMPN(array_mul_inB_to_mul_short, array_mul_inA_to_mul_short) + +array_mul_inB_to_mul_short: + $ => A :MLOAD(array_mul_inB) + A :MSTORE(array_mul_short_inB) + +array_mul_compute_short: + :CALL(array_mul_short) + + %MAX_CNT_STEPS - STEP - 4 :JMPN(outOfCountersStep) + + $ => C :MLOAD(array_mul_short_len_out) + C :MSTORE(array_mul_len_out) + C - 1 => RR + + %MAX_CNT_STEPS - STEP - 3*C - 2 :JMPN(outOfCountersStep) + +array_mul_assign_short: + $ => A :MLOAD(array_mul_short_out + RR) + A :MSTORE(array_mul_out + RR) + RR - 1 => RR :JMPN(array_mul_end, array_mul_assign_short) + +array_mul_end: + $ => RR :MLOAD(array_mul_RR) + :RETURN \ No newline at end of file diff --git a/main/modexp/array_lib/array_mul_long.zkasm b/main/modexp/array_lib/array_mul_long.zkasm new file mode 100644 index 00000000..28dea0ef --- /dev/null +++ b/main/modexp/array_lib/array_mul_long.zkasm @@ -0,0 +1,156 @@ +;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; PRE: len(inB) >= 2 +;; POST: out is trimmed +;; +;; array_mul_long: +;; in: +;; · C ∈ [1, 32], the len of inA +;; · D ∈ [1, 32], the len of inB +;; · inA ∈ [0, 2²⁵⁶ - 1]^C, the first input array +;; · inB ∈ [0, 2²⁵⁶ - 1]^D, the second input array +;; +;; output: +;; · out = inA·inB, with len(out) <= C + D +;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +; function array_mul_long(a: bigint[], b: bigint[], base: bigint): bigint[] { +; const alen = a.length; +; const blen = b.length; +; const len = alen + blen; +; const result = new Array(len).fill(0n); +; let product: bigint; +; let carry: bigint; +; for (let i = 0; i < alen; i++) { +; for (let j = 0; j < blen; j++) { +; product = a[i] * b[j] + out[i+j]; +; carry = product / base; +; out[i+j] = product - carry * base; +; out[i + j + 1] += carry; +; } +; } +; trim(result); +; return result; +; } + +VAR GLOBAL array_mul_long_inA[%ARRAY_MAX_LEN] +VAR GLOBAL array_mul_long_inB[%ARRAY_MAX_LEN] +VAR GLOBAL array_mul_long_out[%ARRAY_MAX_LEN_DOUBLED] +VAR GLOBAL array_mul_long_len_inA +VAR GLOBAL array_mul_long_len_inB +VAR GLOBAL array_mul_long_len_out + +VAR GLOBAL array_mul_long_out_chunk_2 + +VAR GLOBAL array_mul_long_RR + +array_mul_long: + %MAX_CNT_ARITH - CNT_ARITH - 1 :JMPN(outOfCountersArith) + %MAX_CNT_STEPS - STEP - 9 :JMPN(outOfCountersStep) + + C => A + D => B + 0 => C,D + ${A*B} => E :ARITH + A => C + B => D + ; E holds C*D + + %MAX_CNT_BINARY - CNT_BINARY - 4*E :JMPN(outOfCountersBinary) + %MAX_CNT_ARITH - CNT_ARITH - E :JMPN(outOfCountersArith) + %MAX_CNT_STEPS - STEP - 7 - 2*C - 2*D - 33*E - 2 - 3*C - 1 :JMPN(outOfCountersStep) + + RR :MSTORE(array_mul_long_RR) + + C :MSTORE(array_mul_long_len_inA) + D :MSTORE(array_mul_long_len_inB) + C + D :MSTORE(array_mul_long_len_out) + 0 :MSTORE(array_mul_long_out_chunk_2) ; initialize the out chunk 2 + + C + D - 1 => E ; auxiliar index + 0 => RCX ; first index in loops + 0 => RR ; second index in loops + +array_mul_long_clean_out: + 0 :MSTORE(array_mul_long_out + E) + E - 1 => E :JMPN(array_mul_long_loopZero2inB, array_mul_long_clean_out) + +; Begin of branching +array_mul_long_loop_index_check: + RCX + 1 => RCX + $ => B :MLOAD(array_mul_long_len_inA) + B - RCX :JMPZ(array_mul_long_prep_trim_in) + + 0 => RR ; reset the second index +; End of branching + +array_mul_long_loopZero2inB: + ; The result will be stored as D·base + C + + RCX => E + ; 1] a[i]·b[j], where a[i],b[j] ∈ [0,base-1]: This number cannot be GT (base - 2)·base + 1, two chunks + $ => A :MLOAD(array_mul_long_inA + E) + $ => B :MLOAD(array_mul_long_inB + RR) + 0 => C + $${var _arrayLongMul_AB = A*B} + ${_arrayLongMul_AB >> 256} => D + ${_arrayLongMul_AB} => E :ARITH + + ; 2] product = a[i]·b[j] + out[i+j], where out[i+j] ∈ [0,base-1]: This number cannot be GT (base - 1)·base, two chunks + E => A + RCX + RR => E + $ => B :MLOAD(array_mul_long_out + E) + $ => C :ADD, JMPNC(__array_mul_long_no_carry_continue_1) + ;----------------- + ; Since here D ∈ [0, base - 2], there cannot be carry in the following addition + D => A + 1 => B + $ => D :ADD + ;----------------- + __array_mul_long_no_carry_continue_1: + $ => A :MLOAD(array_mul_long_out_chunk_2) ; out_chunk_2 ∈ [0,1] + D => B + $ => D :ADD ; the number is of two chunks, no carry can be generated here + + ; NOTE: It cannot happen that a[i]·b[j] + out[i+j] produces carry and out_chunk_2 is 1. + + ; out[i+j] = product - carry·B + C :MSTORE(array_mul_long_out + E) + + ; out[i+j+1] += carry, where carry ∈ [0,base-1]: This number cannot be GT base + (base-3), two chunks + E + 1 => E + $ => A :MLOAD(array_mul_long_out + E) + D => B + $ => C :ADD, JMPNC(__array_mul_long_no_carry_continue_2) + ;----------------- + 1 :MSTORE(array_mul_long_out_chunk_2) + :JMP(__array_mul_long_carry_continue) + __array_mul_long_no_carry_continue_2: + 0 :MSTORE(array_mul_long_out_chunk_2) + __array_mul_long_carry_continue: + ;----------------- + + C :MSTORE(array_mul_long_out + E) + + RR + 1 => RR + $ => B :MLOAD(array_mul_long_len_inB) + B - RR :JMPZ(array_mul_long_loop_index_check, array_mul_long_loopZero2inB) + +array_mul_long_prep_trim_in: + $ => C :MLOAD(array_mul_long_len_out) + C - 1 => E + +array_mul_long_trim_in: + $ => A :MLOAD(array_mul_long_out + E) + A :MSTORE(array_trim_in + E) + E - 1 => E :JMPN(array_mul_long_trim, array_mul_long_trim_in) + +array_mul_long_trim: + :CALL(array_trim) + + %MAX_CNT_STEPS - STEP - 3 :JMPN(outOfCountersStep) + + C :MSTORE(array_mul_long_len_out) + +array_mul_long_end: + $ => RR :MLOAD(array_mul_long_RR) + :RETURN \ No newline at end of file diff --git a/main/modexp/array_lib/array_mul_short.zkasm b/main/modexp/array_lib/array_mul_short.zkasm new file mode 100644 index 00000000..d850064c --- /dev/null +++ b/main/modexp/array_lib/array_mul_short.zkasm @@ -0,0 +1,127 @@ +;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; POST: out is trimmed +;; +;; array_mul_short: +;; in: +;; · C ∈ [1, 32], the len of inA +;; · inA ∈ [0, 2²⁵⁶ - 1]^C, the first input array +;; · inB ∈ [0, 2²⁵⁶ - 1], the second input +;; +;; output: +;; · out = inA·inB, with len(out) <= C + 1 +;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +; function array_mul_short(a: bigint[], b: bigint, base: bigint): bigint[] { +; const alen = a.length; +; const len = alen; +; const result = new Array(len).fill(0n); +; let product: bigint; +; let carry = 0n; +; let i; +; for (i = 0; i < alen; i++) { +; product = a[i] * b + carry; +; carry = product / base; +; out[i] = product - carry * base; +; } + +; if (carry > 0n) { +; result.push(carry); +; } + +; trim(result); +; return result; +; } + +VAR GLOBAL array_mul_short_inA[%ARRAY_MAX_LEN] +VAR GLOBAL array_mul_short_inB +VAR GLOBAL array_mul_short_out[%ARRAY_MAX_LEN_PLUS_ONE] +VAR GLOBAL array_mul_short_len_inA +VAR GLOBAL array_mul_short_len_out + +VAR GLOBAL array_mul_short_carry + +VAR GLOBAL array_mul_short_RR + +array_mul_short: + %MAX_CNT_BINARY - CNT_BINARY - 2*C :JMPN(outOfCountersBinary) + %MAX_CNT_ARITH - CNT_ARITH - C :JMPN(outOfCountersArith) + %MAX_CNT_STEPS - STEP - 6 - 2*C-2 - 18*C - 6 :JMPN(outOfCountersStep) + + RR :MSTORE(array_mul_short_RR) + + C :MSTORE(array_mul_short_len_inA) + C + 1 :MSTORE(array_mul_short_len_out) + + C => E ; auxiliar index + 0 => RCX ; index in loops + 0 :MSTORE(array_mul_short_carry) + +array_mul_short_clean_out: + 0 :MSTORE(array_mul_short_out + E) + E - 1 => E :JMPN(array_mul_short_loopZero2inA, array_mul_short_clean_out) + +array_mul_short_loopZero2inA: + ; The result will be stored as D·base + C + + RCX => E + ; 1] a[i] * b, where a[i],b ∈ [0,base-1]: This number cannot be GT (base - 2)·base + 1, two chunks + $ => A :MLOAD(array_mul_short_inA + E) + $ => B :MLOAD(array_mul_short_inB) + 0 => C + $${var _arrayShortMul_AB = A*B} + ${_arrayShortMul_AB >> 256} => D + ${_arrayShortMul_AB} => E :ARITH + + ; 2] product = a[i] * b + carry, where carry ∈ [0,base-1]: This number cannot be GT (base - 1)·base, two chunks + E => A + $ => B :MLOAD(array_mul_short_carry) + $ => C :ADD, JMPNC(__array_mul_short_no_carry_continue) + ;----------------- + ; Since here D ∈ [0, base - 2], there cannot be carry in the following addition + D => A + 1 => B + $ => D :ADD + ;----------------- + __array_mul_short_no_carry_continue: + + ; carry = product / base + D :MSTORE(array_mul_short_carry) + + ; out[i] = product - carry·base + RCX => E + C :MSTORE(array_mul_short_out + E) + + RCX + 1 => RCX + $ => B :MLOAD(array_mul_short_len_inA) + B - RCX :JMPZ(array_mul_short_carry_check, array_mul_short_loopZero2inA) + +; If the last carry > 0, we need to insert it to the output +array_mul_short_carry_check: + $ => A :MLOAD(array_mul_short_carry) + 0 => B + $ :EQ, JMPC(array_mul_short_prep_trim_in) + + RCX => E + A :MSTORE(array_mul_short_out + E) + +array_mul_short_prep_trim_in: + $ => C :MLOAD(array_mul_short_len_out) + C - 1 => E + + %MAX_CNT_STEPS - STEP - 3*C - 1 :JMPN(outOfCountersStep) + +array_mul_short_trim_in: + $ => A :MLOAD(array_mul_short_out + E) + A :MSTORE(array_trim_in + E) + E - 1 => E :JMPZ(array_mul_short_trim, array_mul_short_trim_in) + +array_mul_short_trim: + :CALL(array_trim) + + %MAX_CNT_STEPS - STEP - 3 :JMPN(outOfCountersStep) + + C :MSTORE(array_mul_short_len_out) + +array_mul_short_end: + $ => RR :MLOAD(array_mul_short_RR) + :RETURN \ No newline at end of file diff --git a/main/modexp/array_lib/array_square.zkasm b/main/modexp/array_lib/array_square.zkasm new file mode 100644 index 00000000..e42ed6a5 --- /dev/null +++ b/main/modexp/array_lib/array_square.zkasm @@ -0,0 +1,246 @@ +;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; POST: out is trimmed +;; +;; array_square: +;; in: +;; · C ∈ [1, 32], the len of in +;; · in ∈ [0, 2²⁵⁶- 1]^C, the input array +;; +;; output: +;; · out = in², with len(out) <= 2·C +;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +; function array_square(a: bigint[], base: bigint): bigint[] { +; let len = a.length; +; let out = new Array(2*len).fill(0n); +; let product: bigint; +; let carry: bigint; +; for (let i = 0; i < len; i++) { +; carry = 0n - a[i] * a[i]; +; for (var j = i; j < len; j++) { +; product = 2n * (a[i] * a[j]) + out[i+j] + carry; +; carry = product / base; + +; out[i+j] = product - carry * base; +; } +; out[i + len] = carry; +; } +; trim(out); +; return out; +; } + +; Matrix visualization: https://hackmd.io/C9KQPGoaSICStIQQFweBlw?view + +VAR GLOBAL array_square_in[%ARRAY_MAX_LEN] +VAR GLOBAL array_square_out[%ARRAY_MAX_LEN_DOUBLED] +VAR GLOBAL array_square_len_in +VAR GLOBAL array_square_len_out + +VAR GLOBAL array_square_carry_chunk_1 +VAR GLOBAL array_square_carry_chunk_2 +VAR GLOBAL array_square_carry_sign ; 0 if negative, 1 if positive +VAR GLOBAL array_square_chunk_3 +VAR GLOBAL array_square_aiaj_chunk_2 +VAR GLOBAL array_square_out_chunk_2 + +VAR GLOBAL array_square_RR + +array_square: + %MAX_CNT_ARITH - CNT_ARITH - 1 :JMPN(outOfCountersArith) + %MAX_CNT_STEPS - STEP - 7 :JMPN(outOfCountersStep) + + C => A,B + 0 => C,D + ${A*A} => E :ARITH + A => C + ; E holds C*C + + %MAX_CNT_BINARY - CNT_BINARY - 9*E :JMPN(outOfCountersBinary) + %MAX_CNT_ARITH - CNT_ARITH - 1 - 2*E :JMPN(outOfCountersArith) + %MAX_CNT_STEPS - STEP - 5 - 2*C - 68*E - 2 :JMPN(outOfCountersStep) + + RR :MSTORE(array_square_RR) + + C :MSTORE(array_square_len_in) + C + C :MSTORE(array_square_len_out) + + 0 :MSTORE(array_square_chunk_3) ; initialize the third chunk + 0 :MSTORE(array_square_out_chunk_2) ; initialize the second chunk of out + + 0 => RCX,RR ; first and second indexes in loops + C + C - 1 => E +array_square_clean_out: + 0 :MSTORE(array_square_out + E) + E - 1 => E :JMPN(array_square_ai_times_ai, array_square_clean_out) + +; Begin of branching +; We perform subtraction of a value with three chunks +; Therefore, the subtraction can produce carry until the highest chunk +; e.g. (base² + y) - (y+1) = 0 +array_square_is_negative_1: + $ => C :SUB, JMPNC(__return_array_square_is_negative_1) + ;----------------- + D => A + 1 => B + $ => D :SUB, JMPNC(__return_array_square_is_negative_1) + 0 :MSTORE(array_square_chunk_3) + :JMP(__return_array_square_is_negative_1) + ;----------------- + + +array_square_is_negative_2: + $ => D :SUB, JMPNC(__return_array_square_is_negative_2) + ;----------------- + 0 :MSTORE(array_square_chunk_3) + :JMP(__return_array_square_is_negative_2) + ;----------------- + +array_square_loop_index_check: + ; out[i + len] = carry + $ => A :MLOAD(array_square_carry_chunk_1) + RCX + B => E + A :MSTORE(array_square_out + E) + + $ => A :MLOAD(array_square_carry_chunk_2) + A :MSTORE(array_square_out_chunk_2) + + ; update indices + RCX + 1 => RCX,RR,A + B - A :JMPZ(array_square_prep_trim_in) ; This subtraction is safe +; End of branching + +array_square_ai_times_ai: + ; carry = 0 - a[i]·a[i] + ; a[i]·a[i], where a[i] ∈ [0,base-1]: This number cannot be GT (base - 2)·base + 1, two chunks + $ => A,B :MLOAD(array_square_in + RR) + 0 => C + $${var _arraySquare_aiai = A*B} + ${_arraySquare_aiai >> 256} => D + ${_arraySquare_aiai} => E :ARITH + E :MSTORE(array_square_carry_chunk_1) + D :MSTORE(array_square_carry_chunk_2) + 0 :MSTORE(array_square_carry_sign) + +array_square_loopRR2len: + ; product = 2·(a[i]·a[j]) + out[i+j] + carry (in the worst case, this is a 3-chunk number) + ; The result will be stored as array_square_chunk_3·base² + D·base + C + + ; 1] a[i]·a[j], where a[i],a[j] ∈ [0,base-1]: This number cannot be GT (base - 2)·base + 1, two chunks + RCX => E + $ => A :MLOAD(array_square_in + E) + $ => B :MLOAD(array_square_in + RR) + 0 => C + $${var _arraySquare_aiaj = A*B} + ${_arraySquare_aiaj >> 256} => D + ${_arraySquare_aiaj} => E :ARITH + D :MSTORE(array_square_aiaj_chunk_2) + + ; 2] 2·a[i]·a[j]: This number cannot be GT base² + (base - 4)·base + 2, three chunks + E => A,B + $ => C :ADD, JMPNC(__array_square_no_carry_continue_1) + ;----------------- + ; Since here D ∈ [0, base - 2], there cannot be carry in the following addition + D => A + 1 => B + $ => D :ADD + ;----------------- + __array_square_no_carry_continue_1: + $ => A :MLOAD(array_square_aiaj_chunk_2) + D => B + $ => D :ADD, JMPNC(__array_square_no_carry_continue_2) + ;----------------- + 1 :MSTORE(array_square_chunk_3) + ;----------------- + __array_square_no_carry_continue_2: + + ; 3] 2·a[i]·a[j] + out[i+j]: + ; a) j < len-1: This number cannot be GT base² + (base - 3)·base + 1, as out[i+j] < base + ; b) j == len-1: This number cannot be GT base² + (base - 3)·base + base - 1, as out[i + len] <= base + (base - 3) + ; In both cases, three chunks + RCX + RR => E + $ => A :MLOAD(array_square_out + E) + C => B + $ => C :ADD, JMPNC(__array_square_no_carry_continue_3) + ;----------------- + ; Since here D ∈ [0, base - 1], there can be carry in the following addition + D => A + 1 => B + $ => D :ADD, JMPNC(__array_square_no_carry_continue_3) + 1 :MSTORE(array_square_chunk_3) + ;----------------- + __array_square_no_carry_continue_3: + + ; The output can have two chunks only if j == len-1, so we must jump the following block of code if j < len-1 + RR + 1 => A + $ => B :MLOAD(array_square_len_in) + B - A :JMPNZ(__array_square_no_carry_continue_4) ; This subtraction is safe + ; Add the second output chunk + $ => A :MLOAD(array_square_out_chunk_2) + D => B + $ => D :ADD, JMPNC(__array_square_no_carry_continue_4) + ;----------------- + 1 :MSTORE(array_square_chunk_3) + ;----------------- + __array_square_no_carry_continue_4: + + ; 4] product = 2·a[i]·a[j] + out[i+j] + carry: This number cannot be GT base² + (base - 2)·base, three chunks + C => A + $ => B :MLOAD(array_square_carry_chunk_1) + $ :MLOAD(array_square_carry_sign), JMPZ(array_square_is_negative_1) + $ => C :ADD, JMPNC(__array_square_no_carry_continue_5) + ;----------------- + ; Since here D ∈ [0, base - 1], there can be carry in the following addition + D => A + 1 => B + $ => D :ADD, JMPNC(__array_square_no_carry_continue_5) + 1 :MSTORE(array_square_chunk_3) + ;----------------- + __array_square_no_carry_continue_5: + __return_array_square_is_negative_1: + + D => A + $ => B :MLOAD(array_square_carry_chunk_2) + $ :MLOAD(array_square_carry_sign), JMPZ(array_square_is_negative_2) + $ => D :ADD, JMPNC(__array_square_no_carry_continue_6) + ;----------------- + 1 :MSTORE(array_square_chunk_3) + ;----------------- + __array_square_no_carry_continue_6: + __return_array_square_is_negative_2: + + ; carry = product / base; This number cannot be greater than base + (base - 2) + D :MSTORE(array_square_carry_chunk_1) + $ => A :MLOAD(array_square_chunk_3) + A :MSTORE(array_square_carry_chunk_2) + 1 :MSTORE(array_square_carry_sign) + + ; out[i+j] = product - carry·base; + RCX + RR => E + C :MSTORE(array_square_out + E) + 0 :MSTORE(array_square_chunk_3) ; reset the third chunk + + RR + 1 => RR + $ => B :MLOAD(array_square_len_in) + B - RR :JMPZ(array_square_loop_index_check, array_square_loopRR2len) ; This subtraction is safe + +array_square_prep_trim_in: + $ => C :MLOAD(array_square_len_out) + + %MAX_CNT_STEPS - STEP - 1 - 3*C - 1 :JMPN(outOfCountersStep) + + C - 1 => E +array_square_trim_in: + $ => A :MLOAD(array_square_out + E) + A :MSTORE(array_trim_in + E) + E - 1 => E :JMPN(array_square_trim, array_square_trim_in) + +array_square_trim: + :CALL(array_trim) + + %MAX_CNT_STEPS - STEP - 3 :JMPN(outOfCountersStep) + + C :MSTORE(array_square_len_out) + +array_square_end: + $ => RR :MLOAD(array_square_RR) + :RETURN \ No newline at end of file diff --git a/main/modexp/array_lib/unused/array_add.zkasm b/main/modexp/array_lib/unused/array_add.zkasm new file mode 100644 index 00000000..1ef8df4e --- /dev/null +++ b/main/modexp/array_lib/unused/array_add.zkasm @@ -0,0 +1,100 @@ +;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; +;; array_add: +;; in: +;; · C ∈ [1, 32], the len of inA +;; · D ∈ [1, 32], the len of inB +;; · inA ∈ [0, 2²⁵⁶ - 1]^C, the first input array +;; · inB ∈ [0, 2²⁵⁶ - 1]^D, the second input array +;; +;; output: +;; · out = inA + inB, with len(out) <= C + 1 +;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +VAR GLOBAL array_add_inA[%ARRAY_MAX_LEN] +VAR GLOBAL array_add_inB[%ARRAY_MAX_LEN] +VAR GLOBAL array_add_out[%ARRAY_MAX_LEN_PLUS_ONE] +VAR GLOBAL array_add_len_inA +VAR GLOBAL array_add_len_inB +VAR GLOBAL array_add_len_out + +VAR GLOBAL array_add_RR + +array_add: + RR :MSTORE(array_add_RR) + C :MSTORE(array_add_len_inA) + D :MSTORE(array_add_len_inB) + 0 => RR,E + + D => A + C => B + $ :LT, JMPC(array_add_inA_to_add_AGTB) + +; BGTA +array_add_prep_BGTA: + C => A + D => C + A => D + +array_add_inA_to_add_BGTA: + $ => A :MLOAD(array_add_inB + RR) + A :MSTORE(array_add_AGTB_inA + RR) + RR + 1 => RR + RR => A + D => B + $ :EQ, JMPC(array_add_inB_to_add_BGTA, array_add_inA_to_add_BGTA) + +array_add_inB_to_add_BGTA: + $ => A :MLOAD(array_add_inA + E) + A :MSTORE(array_add_AGTB_inB + E) + E + 1 => E + E => A + C => B + $ :EQ, JMPC(array_add_compute_BGTA, array_add_inB_to_add_BGTA) + +array_add_compute_BGTA: + :CALL(array_add_AGTB) + $ => C :MLOAD(array_add_AGTB_len_out) + C :MSTORE(array_add_len_out) + 0 => RR +array_add_assign_BGTA: + $ => A :MLOAD(array_add_AGTB_out + RR) + A :MSTORE(array_add_out + RR) + RR + 1 => RR + RR => A + C => B + $ :EQ, JMPC(array_add_end, array_add_assign_BGTA) + +; AGTB +array_add_inA_to_add_AGTB: + $ => A :MLOAD(array_add_inA + RR) + A :MSTORE(array_add_AGTB_inA + RR) + RR + 1 => RR + RR => A + C => B + $ :EQ, JMPC(array_add_inB_to_add_AGTB, array_add_inA_to_add_AGTB) + +array_add_inB_to_add_AGTB: + $ => A :MLOAD(array_add_inB + E) + A :MSTORE(array_add_AGTB_inB + E) + E + 1 => E + E => A + D => B + $ :EQ, JMPC(array_add_compute_AGTB, array_add_inB_to_add_AGTB) + +array_add_compute_AGTB: + :CALL(array_add_AGTB) + $ => C :MLOAD(array_add_AGTB_len_out) + C :MSTORE(array_add_len_out) + 0 => RR +array_add_assign_AGTB: + $ => A :MLOAD(array_add_AGTB_out + RR) + A :MSTORE(array_add_out + RR) + RR + 1 => RR + RR => A + C => B + $ :EQ, JMPC(array_add_end, array_add_assign_AGTB) + +array_add_end: + $ => RR :MLOAD(array_add_RR) + :RETURN \ No newline at end of file diff --git a/main/modexp/array_lib/unused/array_is_odd.zkasm b/main/modexp/array_lib/unused/array_is_odd.zkasm new file mode 100644 index 00000000..d28a60be --- /dev/null +++ b/main/modexp/array_lib/unused/array_is_odd.zkasm @@ -0,0 +1,23 @@ +;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; PRE: The input arrays have been trimmed. +;; +;; array_is_odd: +;; in: +;; · in ∈ [0, 2²⁵⁶ - 1]*, the input array +;; output: +;; · 1, if in is an odd number +;; · 0, otherwise +;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +; NOTE: The base is 2^256, so I only need to check if the first chunk is odd to conclude that the whole number is odd. + +VAR GLOBAL array_is_odd_in +VAR GLOBAL array_is_odd_result + +array_is_odd: + $ => A :MLOAD(array_is_odd_in) + 1 => B + $ => A :AND + A :MSTORE(array_is_odd_result) + :RETURN \ No newline at end of file diff --git a/main/modexp/array_lib/unused/array_is_one.zkasm b/main/modexp/array_lib/unused/array_is_one.zkasm new file mode 100644 index 00000000..90f86d8d --- /dev/null +++ b/main/modexp/array_lib/unused/array_is_one.zkasm @@ -0,0 +1,33 @@ +;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; PRE: The input arrays have been trimmed. +;; +;; array_is_one: +;; in: +;; · C ∈ [1, 32], the len of in +;; · in ∈ [0, 2²⁵⁶ - 1]^C, the input array +;; output: +;; · 1, if in = 1 +;; · 0, otherwise +;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +VAR GLOBAL array_is_one_in +VAR GLOBAL array_is_one_result + +array_is_one: + ; Is C == 1 and in == 1? + C => A + 1 => B + $ :EQ, JMPNC(__array_is_one_continue) + $ => A :MLOAD(array_is_one_in) + $ :EQ, JMPC(array_is_one_sure) + __array_is_one_continue: + + 0 :MSTORE(array_is_one_result) + :JMP(array_is_one_end) + +array_is_one_sure: + 1 :MSTORE(array_is_one_result) + +array_is_one_end: + :RETURN \ No newline at end of file diff --git a/main/modexp/array_lib/unused/array_is_zero.zkasm b/main/modexp/array_lib/unused/array_is_zero.zkasm new file mode 100644 index 00000000..022f310f --- /dev/null +++ b/main/modexp/array_lib/unused/array_is_zero.zkasm @@ -0,0 +1,34 @@ +;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; PRE: The input arrays have been trimmed. +;; +;; array_is_zero: +;; in: +;; · C ∈ [1, 32], the len of in +;; · in ∈ [0, 2²⁵⁶ - 1]^C, the input array +;; output: +;; · 1, if in = 0 +;; · 0, otherwise +;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +VAR GLOBAL array_is_zero_in +VAR GLOBAL array_is_zero_result + +array_is_zero: + ; Is C == 1 and in == 0? + C => A + 1 => B + $ :EQ, JMPNC(__array_is_zero_continue) + 0 => B + $ => A :MLOAD(array_is_zero_in) + $ :EQ, JMPC(array_is_zero_sure) + __array_is_zero_continue: + + 0 :MSTORE(array_is_zero_result) + :JMP(array_is_zero_end) + +array_is_zero_sure: + 1 :MSTORE(array_is_zero_result) + +array_is_zero_end: + :RETURN \ No newline at end of file diff --git a/main/modexp/array_lib/unused/array_sub_AGTB.zkasm b/main/modexp/array_lib/unused/array_sub_AGTB.zkasm new file mode 100644 index 00000000..6f292c82 --- /dev/null +++ b/main/modexp/array_lib/unused/array_sub_AGTB.zkasm @@ -0,0 +1,111 @@ +;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; PRE: inA >= inB +;; +;; array_sub_AGTB: +;; in: +;; · C ∈ [1, 32], the len of inA +;; · D ∈ [1, 32], the len of inB +;; · inA ∈ [0, 2²⁵⁶ - 1]^C, the first input array +;; · inB ∈ [0, 2²⁵⁶ - 1]^D, the second input array +;; +;; output: +;; · out = inA - inB, with len(out) <= C +;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +VAR GLOBAL array_sub_AGTB_inA[%ARRAY_MAX_LEN] +VAR GLOBAL array_sub_AGTB_inB[%ARRAY_MAX_LEN] +VAR GLOBAL array_sub_AGTB_out[%ARRAY_MAX_LEN] +VAR GLOBAL array_sub_AGTB_len_inA +VAR GLOBAL array_sub_AGTB_len_inB + +VAR GLOBAL array_sub_AGTB_carry + +VAR GLOBAL array_sub_AGTB_RR + +array_sub_AGTB: + RR :MSTORE(array_sub_AGTB_RR) + C :MSTORE(array_sub_AGTB_len_inA) + D :MSTORE(array_sub_AGTB_len_inB) + + 0 => E ; index in loops + 0 :MSTORE(array_sub_AGTB_carry) + :JMP(array_sub_AGTB_loopZero2inB) + +array_sub_AGTB_add_carry: + 1 => D + :JMP(return_array_sub_AGTB_add_carry) + +array_sub_AGTB_sub_carry: + D => A + 1 => B + $ :SUB, JMPC(array_sub_AGTB_set_carry_to_1, array_sub_AGTB_set_carry_tp_0) + +array_sub_AGTB_set_carry_to_1: + 1 :MSTORE(array_sub_AGTB_carry) + :JMP(return_array_sub_AGTB_sub_carry) + +array_sub_AGTB_set_carry_tp_0: + 0 :MSTORE(array_sub_AGTB_carry) + :JMP(return_array_sub_AGTB_sub_carry) + +array_sub_AGTB_loopZero2inB: + 0 => D ; cleanup + + ; diff = a[i] - (b[i] + carry) + $ => A :MLOAD(array_sub_AGTB_inB + E) + $ => B :MLOAD(array_sub_AGTB_carry) + $ => C :ADD, JMPC(array_sub_AGTB_add_carry) + return_array_sub_AGTB_add_carry: + + $ => A :MLOAD(array_sub_AGTB_inA + E) + C => B + $ => C :SUB, JMPC(array_sub_AGTB_sub_carry) + 0 :MSTORE(array_sub_AGTB_carry) + return_array_sub_AGTB_sub_carry: + + C :MSTORE(array_sub_AGTB_out + E) + + E + 1 => E + E => A + $ => B :MLOAD(array_sub_AGTB_len_inB) + $ :EQ, JMPC(array_sub_AGTB_loop_index_check1, array_sub_AGTB_loopZero2inB) + +array_sub_AGTB_loop_index_check1: + E => A + $ => B :MLOAD(array_sub_AGTB_len_inA) + $ :EQ, JMPC(array_sub_AGTB_end) + +array_sub_AGTB_loopInB2InA: + ; diff = a[i] - carry + $ => A :MLOAD(array_sub_AGTB_inA + E) + $ => B :MLOAD(array_sub_AGTB_carry) + $ => C :SUB, JMPC(array_sub_AGTB_loopInB2InA_cont) + C :MSTORE(array_sub_AGTB_out + E) + E + 1 => E + :JMP(array_sub_AGTB_loop_index_check2) + +array_sub_AGTB_loopInB2InA_cont: + C :MSTORE(array_sub_AGTB_out + E) + + E + 1 => E + E => A + $ => B :MLOAD(array_sub_AGTB_len_inA) + $ :EQ, JMPC(array_sub_AGTB_end, array_sub_AGTB_loopInB2InA) + +array_sub_AGTB_loop_index_check2: + E => A + $ => B :MLOAD(array_sub_AGTB_len_inA) + $ :EQ, JMPC(array_sub_AGTB_end) + +array_sub_AGTB_loop_final: + $ => A :MLOAD(array_sub_AGTB_inA + E) + A :MSTORE(array_sub_AGTB_out + E) + + E + 1 => E + E => A + $ => B :MLOAD(array_sub_AGTB_len_inA) + $ :EQ, JMPC(array_sub_AGTB_end, array_sub_AGTB_loop_final) + +array_sub_AGTB_end: + $ => RR :MLOAD(array_sub_AGTB_RR) + :RETURN \ No newline at end of file diff --git a/main/modexp/array_lib/unused/array_unshift.zkasm b/main/modexp/array_lib/unused/array_unshift.zkasm new file mode 100644 index 00000000..a42033c2 --- /dev/null +++ b/main/modexp/array_lib/unused/array_unshift.zkasm @@ -0,0 +1,37 @@ +;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; +;; array_unshift: +;; in: +;; · C ∈ [1, 32], the len of in = [in[0], in[1], ..., in[C - 1]] +;; · in ∈ [0, 2²⁵⁶ - 1]^C, the input array +;; · D ∈ [0, 2²⁵⁶ - 1], the element to unshift +;; +;; output: +;; · in = [D, in[0], in[1], ..., in[C - 1]] +;; · len = C + 1 +;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +VAR GLOBAL array_unshift_in[%ARRAY_MAX_LEN] +VAR GLOBAL array_unshift_len + +VAR GLOBAL array_unshift_RR + +array_unshift: + RR :MSTORE(array_unshift_RR) + + C + 1 :MSTORE(array_unshift_len) + + C :JMPZ(array_unshift_end) + +array_unshift_loop: + C - 1 => E + $ => A :MLOAD(array_unshift_in + E) + C => E + A :MSTORE(array_unshift_in + E) + C - 1 => C :JMPZ(array_unshift_end) + :JMP(array_unshift_loop) + +array_unshift_end: + D :MSTORE(array_unshift_in) + $ => RR :MLOAD(array_unshift_RR) + :RETURN \ No newline at end of file diff --git a/main/modexp/array_lib/utils/array_compare.zkasm b/main/modexp/array_lib/utils/array_compare.zkasm new file mode 100644 index 00000000..39388f56 --- /dev/null +++ b/main/modexp/array_lib/utils/array_compare.zkasm @@ -0,0 +1,82 @@ +;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; PRE: The input arrays have been trimmed. +;; +;; array_compare: +;; in: +;; · C ∈ [1, 32], the len of inA +;; · D ∈ [1, 32], the len of inB +;; · inA ∈ [0, 2²⁵⁶ - 1]^C, the first input array +;; · inB ∈ [0, 2²⁵⁶ - 1]^D, the second input array +;; +;; output: +;; · 2, if inA > inB +;; · 1, if inA = inB +;; · 0, if inA < inB +;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +; function array_compare(a: bigint[], b: bigint[]): number { +; const alen = a.length; +; const blen = b.length; +; if (alen !== blen) { +; return alen >= blen ? 1 : -1; +; } +; for (let i = alen - 1; i >= 0; i--) { +; if (a[i] !== b[i]) { +; return a[i] > b[i] ? 1 : -1; +; } +; } +; return 0; +; } + +; ---------------------------------- +; Five possible paths: +; · inA > inB and lenA > lenB. +; · inA > inB and lenA = lenB. +; · inA = inB. (worst case) +; · inA < inB and lenA < lenB. +; · inA < inB and lenA = lenB. +; ---------------------------------- + +VAR GLOBAL array_compare_inA[%ARRAY_MAX_LEN] +VAR GLOBAL array_compare_inB[%ARRAY_MAX_LEN] + +VAR GLOBAL array_compare_result + +VAR GLOBAL array_compare_RR + +array_compare: + %MAX_CNT_BINARY - CNT_BINARY - 2*C :JMPN(outOfCountersBinary) + %MAX_CNT_STEPS - STEP - 4 - 7*C - 4 :JMPN(outOfCountersStep) + + RR :MSTORE(array_compare_RR) + + ; Start by comparing the lengths of the arrays + C - D :JMPN(array_compare_ALTB) + D - C :JMPN(array_compare_AGTB) + + C - 1 => E +array_compare_same_len: + $ => A :MLOAD(array_compare_inA + E) + $ => B :MLOAD(array_compare_inB + E) + $ :LT, JMPC(array_compare_ALTB) + + $ => A :MLOAD(array_compare_inB + E) + $ => B :MLOAD(array_compare_inA + E) + $ :LT, JMPC(array_compare_AGTB) + + E - 1 => E :JMPN(array_compare_AEQB, array_compare_same_len) + +array_compare_AGTB: + 2 :MSTORE(array_compare_result) + :JMP(array_compare_end) + +array_compare_AEQB: + 1 :MSTORE(array_compare_result) + :JMP(array_compare_end) + +array_compare_ALTB: + 0 :MSTORE(array_compare_result) + +array_compare_end: + $ => RR :MLOAD(array_compare_RR) + :RETURN \ No newline at end of file diff --git a/main/modexp/array_lib/utils/array_trim.zkasm b/main/modexp/array_lib/utils/array_trim.zkasm new file mode 100644 index 00000000..efb9b750 --- /dev/null +++ b/main/modexp/array_lib/utils/array_trim.zkasm @@ -0,0 +1,49 @@ +;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; +;; array_trim: +;; in: +;; · C ∈ [1, 3636], the len of in +;; · in ∈ [0, 2²⁵⁶ - 1]^C, the input array +;; +;; output: +;; · C, the new length of in +;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +; function array_trim(a: bigint[]): void { +; let i = a.length; +; +; while (a[--i] === 0n); +; +; a.length = i + 1; +; } + +VAR GLOBAL array_trim_in[%ARRAY_MAX_LEN_DOUBLED] + +VAR GLOBAL array_trim_RR + +array_trim: + %MAX_CNT_STEPS - STEP - 5 :JMPN(outOfCountersStep) + + RR :MSTORE(array_trim_RR) + + 0 => B ; used for comparison in the whole loop + + C => E + ; scan from the last chunk to the first chunks until we find a non-zero chunk + ; in case of zero input array, we return 1 +array_trim_loop: + %MAX_CNT_BINARY - CNT_BINARY - 1 :JMPN(outOfCountersBinary) + %MAX_CNT_STEPS - STEP - 3 :JMPN(outOfCountersStep) + + E - 1 => E :JMPZ(array_trim_end) + + $ => A :MLOAD(array_trim_in + E) + $ :EQ, JMPZ(array_trim_end, array_trim_loop) + +array_trim_end: + %MAX_CNT_STEPS - STEP - 2 :JMPN(outOfCountersStep) + + $ => RR :MLOAD(array_trim_RR) + + E + 1 => C :RETURN diff --git a/main/modexp/constants.zkasm b/main/modexp/constants.zkasm new file mode 100644 index 00000000..37c22310 --- /dev/null +++ b/main/modexp/constants.zkasm @@ -0,0 +1,5 @@ +; See the discussion [https://github.com/0xPolygonHermez/zkevm-rom-internal/issues/43] for more details. +CONST %ARRAY_MAX_LEN = 32 +CONST %ARRAY_MAX_LEN_PLUS_ONE = 33 +CONST %ARRAY_MAX_LEN_DOUBLED = 64 +CONST %MODEXP_MAX_LEN = 32 \ No newline at end of file diff --git a/main/modexp/modexp.zkasm b/main/modexp/modexp.zkasm new file mode 100644 index 00000000..6491c42a --- /dev/null +++ b/main/modexp/modexp.zkasm @@ -0,0 +1,296 @@ +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; PRE: B, E, M have been trimmed. +;; POST: out is trimmed +;; +;; modexp: +;; ---------------------------------------- +;; input: +;; · Blen ∈ [1, 32], the len of B +;; · Elen ∈ [1, 32], the len of E +;; · Mlen ∈ [1, 32], the len of M +;; · B ∈ [0, 2²⁵⁶ - 1]^Blen, the base represented in little-endian +;; · E ∈ [0, 2²⁵⁶ - 1]^Elen, the exponent represented in little-endian +;; · M ∈ [0, 2²⁵⁶ - 1]^Mlen, the modulus represented in little-endian +;; +;; output: +;; · B^E (mod M) ∈ [0, 2²⁵⁶ - 1]^Mlen +;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +;; function modexp(b: bigint[], exp: bigint[], mod: bigint[], base: bigint): bigint[] { +;; if (array_is_zero(mod) || array_is_one(mod)) return [0n]; +;; if (array_is_zero(b)) return [0n]; +;; if (array_is_one(b)) return [1n]; +;; if (array_is_zero(e)) return [1n]; +;; +;; let r = [1n]; +;; let base = array_div(b, mod, base)[1]; +;; while (!array_is_zero(exp)) { +;; if (array_is_zero(base)) return [0n]; +;; if (isOdd(exp)) { +;; r = array_div(array_mul(r, base, base),mod,base)[1]; +;; } +;; exp = array_div_short(exp, 2n, base)[0]; +;; base = array_div(array_square(base, base),mod,base)[1]; +;; } +;; return r; +;; }; + +;; RESOURCES (assuming a worst case scenario): +;; ------------------------------------------- +;; cost(pre_loop) = 3·cost(isZero) + 2·cost(isOne) + cost(array_div) +;; nIterations = ⌊log₂(E)⌋ + 1 +;; nTimesEIsOdd = HammingWeight(E) (i.e., number of 1s in the binary representation of E) +;; nTimesEIsEven = nIterations - nTimesEIsOdd +;; cost(iteration1) (if E is odd) = cost(isZero) + cost(isOdd) + 2·cost(array_div) + cost(array_mul) + cost(array_div_short) + cost(array_square) +;; cost(iteration2) (if E is even) = cost(isZero) + cost(isOdd) + cost(array_div) + cost(array_div_short) + cost(array_square) +;; ------------ +;; cost(total) = cost(pre_loop) + nTimesEIsOdd·cost(iteration1) + nTimesEIsEven·cost(iteration2) +;; ------------ + +VAR GLOBAL modexp_Blen +VAR GLOBAL modexp_Elen +VAR GLOBAL modexp_Mlen +VAR GLOBAL modexp_B[%MODEXP_MAX_LEN] +VAR GLOBAL modexp_E[%MODEXP_MAX_LEN] +VAR GLOBAL modexp_M[%MODEXP_MAX_LEN] + +VAR GLOBAL modexp_out[%MODEXP_MAX_LEN] +VAR GLOBAL modexp_outlen + +VAR GLOBAL modexp_RR + +modexp: + + %MAX_CNT_STEPS - STEP - 8 :JMPN(outOfCountersStep) + + RR :MSTORE(modexp_RR) + + ; I do not need to cover edge cases here since they are covered in the pre-modexp file + ; Therefore, I can assume that M > 1, B > 1, E > 0 + + 1 :MSTORE(modexp_out) + 1 :MSTORE(modexp_outlen) + + ; prepare for computing B % M + $ => C :MLOAD(modexp_Blen) + $ => D :MLOAD(modexp_Mlen) + C - 1 => RR + D - 1 => E + + %MAX_CNT_STEPS - STEP - 3*C - 3*D - 1 :JMPN(outOfCountersStep) + +; Compute B = B % M +; ------------------- +modexp_B_to_div: + $ => A :MLOAD(modexp_B + RR) + A :MSTORE(array_div_inA + RR) + RR - 1 => RR :JMPN(modexp_M_to_div1, modexp_B_to_div) + +modexp_M_to_div1: + $ => A :MLOAD(modexp_M + E) + A :MSTORE(array_div_inB + E) + E - 1 => E :JMPN(modexp_div_B_and_M, modexp_M_to_div1) + +modexp_div_B_and_M: + :CALL(array_div) + + %MAX_CNT_STEPS - STEP - 4 :JMPN(outOfCountersStep) + + $ => C :MLOAD(array_div_len_rem) + C :MSTORE(modexp_Blen) + C - 1 => RR + + %MAX_CNT_STEPS - STEP - 3*C :JMPN(outOfCountersStep) + +modexp_rem_from_div1: + $ => A :MLOAD(array_div_rem + RR) + A :MSTORE(modexp_B + RR) + RR - 1 => RR :JMPN(modexp_pre_loop, modexp_rem_from_div1) +; ------------------- + +; Begin of edge cases +modexp_B_is_zero: + ; (0^E) % M = 0. + 1 :MSTORE(modexp_outlen) + 0 :MSTORE(modexp_out), JMP(modexp_end) +; End of edge cases + +; Begin of branching +modexp_loop_multiply: + $ => C :MLOAD(modexp_outlen) + $ => D :MLOAD(modexp_Blen) + C - 1 => RR + D - 1 => E + + %MAX_CNT_STEPS - STEP - 3*C - 3*D - 1 :JMPN(outOfCountersStep) + +; Compute out * B +; ------------------- +modexp_out_to_mul_long: + $ => A :MLOAD(modexp_out + RR) + A :MSTORE(array_mul_inA + RR) + RR - 1 => RR :JMPN(modexp_B_to_mul_long, modexp_out_to_mul_long) + +modexp_B_to_mul_long: + $ => A :MLOAD(modexp_B + E) + A :MSTORE(array_mul_inB + E) + E - 1 => E :JMPN(modexp_mul_long_out_and_B, modexp_B_to_mul_long) + +modexp_mul_long_out_and_B: + :CALL(array_mul) + + %MAX_CNT_STEPS - STEP - 5 :JMPN(outOfCountersStep) + + $ => C :MLOAD(array_mul_len_out) + $ => D :MLOAD(modexp_Mlen) + C - 1 => RR + D - 1 => E + + %MAX_CNT_STEPS - STEP - 3*C - 3*D - 1 :JMPN(outOfCountersStep) + +; Compute out = (out * B) % M +modexp_out_to_div1: + $ => A :MLOAD(array_mul_out + RR) + A :MSTORE(array_div_inA + RR) + RR - 1 => RR :JMPN(modexp_M_to_div, modexp_out_to_div1) + +modexp_M_to_div: + $ => A :MLOAD(modexp_M + E) + A :MSTORE(array_div_inB + E) + E - 1 => E :JMPN(modexp_div_out_and_M2, modexp_M_to_div) + +modexp_div_out_and_M2: + :CALL(array_div) + + %MAX_CNT_STEPS - STEP - 4 :JMPN(outOfCountersStep) + + $ => C :MLOAD(array_div_len_rem) + C :MSTORE(modexp_outlen) + C - 1 => RR + + %MAX_CNT_STEPS - STEP - 3*C - 1 :JMPN(outOfCountersStep) + +modexp_rem_from_div2: + $ => A :MLOAD(array_div_rem + RR) + A :MSTORE(modexp_out + RR) + RR - 1 => RR :JMPN(return_modexp_loop_multiply, modexp_rem_from_div2) +; ------------------- +; End of branching + +modexp_pre_loop: +; In the worst case, the exponent is odd in each iteration + %MAX_CNT_BINARY - CNT_BINARY - 3 :JMPN(outOfCountersBinary) + %MAX_CNT_STEPS - STEP - 13 :JMPN(outOfCountersStep) + + ; Is Elen = 1 and E = 0? + 1 => B + $ => A :MLOAD(modexp_Elen) + A - B :JMPNZ(__modexp_E_continue) + $ => A :MLOAD(modexp_E) + $ :LT, JMPC(modexp_end) ; we are done + __modexp_E_continue: + +modexp_loop: + ; Is Blen = 1 and B = 0? + $ => A :MLOAD(modexp_Blen) + A - B :JMPNZ(__modexp_B_continue) + $ => A :MLOAD(modexp_B) + $ :LT, JMPC(modexp_B_is_zero) + __modexp_B_continue: + + ; Is E is odd? + ; The base is 2^256, so I only need to check if the first chunk is odd to conclude that the whole number is odd. + $ => A :MLOAD(modexp_E) + 1 => B + $ :AND, JMPNZ(modexp_loop_multiply) + return_modexp_loop_multiply: + + %MAX_CNT_STEPS - STEP - 3 :JMPN(outOfCountersStep) + + $ => C :MLOAD(modexp_Elen) + C - 1 => RR + + %MAX_CNT_STEPS - STEP - 3*C - 2 :JMPN(outOfCountersStep) + +; Compute E = E // 2 +; ------------------- +modexp_E_to_div_short: + $ => A :MLOAD(modexp_E + RR) + A :MSTORE(array_div_short_inA + RR) + RR - 1 => RR :JMPN(modexp_div_E_and_2, modexp_E_to_div_short) + +modexp_div_E_and_2: + 2 :MSTORE(array_div_short_inB) + :CALL(array_div_short) + + %MAX_CNT_STEPS - STEP - 4 :JMPN(outOfCountersStep) + + $ => C :MLOAD(array_div_short_len_quo) + C :MSTORE(modexp_Elen) + C - 1 => RR + + %MAX_CNT_STEPS - STEP - 3*C - 3 :JMPN(outOfCountersStep) + +modexp_quo_from_div_short: + $ => A :MLOAD(array_div_short_quo + RR) + A :MSTORE(modexp_E + RR) + RR - 1 => RR :JMPN(modexp_pre_B_square, modexp_quo_from_div_short) +; ------------------- + +; Compute B^2 +; ------------------- +modexp_pre_B_square: + $ => C :MLOAD(modexp_Blen) + C - 1 => RR + + %MAX_CNT_STEPS - STEP - 3*C - 1 :JMPN(outOfCountersStep) + +modexp_B_to_square1: + $ => A :MLOAD(modexp_B + RR) + A :MSTORE(array_square_in + RR) + RR - 1 => RR :JMPN(modexp_square_B, modexp_B_to_square1) + +modexp_square_B: + :CALL(array_square) + + %MAX_CNT_STEPS - STEP - 5 :JMPN(outOfCountersStep) + + $ => C :MLOAD(array_square_len_out) + $ => D :MLOAD(modexp_Mlen) + C - 1 => RR + D - 1 => E + + %MAX_CNT_STEPS - STEP - 3*C - 3*D - 1 :JMPN(outOfCountersStep) + +; Compute B = (B^2) % M +modexp_out_to_div2: + $ => A :MLOAD(array_square_out + RR) + A :MSTORE(array_div_inA + RR) + RR - 1 => RR :JMPN(modexp_M_to_div2, modexp_out_to_div2) + +modexp_M_to_div2: + $ => A :MLOAD(modexp_M + E) + A :MSTORE(array_div_inB + E) + E - 1 => E :JMPN(modexp_div_out_and_M1, modexp_M_to_div2) + +modexp_div_out_and_M1: + :CALL(array_div) + + %MAX_CNT_STEPS - STEP - 4 :JMPN(outOfCountersStep) + + $ => C :MLOAD(array_div_len_rem) + C :MSTORE(modexp_Blen) + C - 1 => RR + + %MAX_CNT_STEPS - STEP - 3*C - 2 :JMPN(outOfCountersStep) + +modexp_rem_from_div3: + $ => A :MLOAD(array_div_rem + RR) + A :MSTORE(modexp_B + RR) + RR - 1 => RR :JMPN(modexp_pre_loop, modexp_rem_from_div3) +; ------------------- + +modexp_end: + $ => RR :MLOAD(modexp_RR) + :RETURN diff --git a/main/modexp/modexp_utils.zkasm b/main/modexp/modexp_utils.zkasm new file mode 100644 index 00000000..39d5b019 --- /dev/null +++ b/main/modexp/modexp_utils.zkasm @@ -0,0 +1,230 @@ +VAR GLOBAL tmpVarAmodexp +VAR GLOBAL tmpVarBmodexp +VAR GLOBAL tmpVarCmodexp +VAR GLOBAL tmpVarDmodexp +VAR GLOBAL offsetInitModexp +VAR GLOBAL tmpVarEmodexp +VAR GLOBAL tmpZkPCmodexp +VAR GLOBAL modExpArrayIndex + +modexp_getBase: + %MAX_CNT_STEPS - STEP - 15 :JMPN(outOfCountersStep) + + RR :MSTORE(tmpZkPCmodexp) + A :MSTORE(tmpVarAmodexp) + B :MSTORE(tmpVarBmodexp) + C :MSTORE(tmpVarCmodexp) + D :MSTORE(tmpVarDmodexp) + ; offset init + E :MSTORE(offsetInitModexp) + ;E = offset final + E + C => E + 0 :MSTORE(modExpArrayIndex) + 0 :MSTORE(modexp_Blen) + 32 :MSTORE(readXFromCalldataLength) + +modexp_getBaseLoop: + + %MAX_CNT_BINARY - CNT_BINARY - 6 :JMPN(outOfCountersBinary) + %MAX_CNT_STEPS - STEP - 100 :JMPN(outOfCountersStep) + ; C length to read + C => A + 0 => B + ; if C (length) == 0 --> modexp_saveBaseLen + $ :EQ,JMPC(modexp_saveBaseLen) + 32 => B + ; if C (length) < 32 --> modexp_getBaseMloadX + $ :LT,JMPC(modexp_getBaseMloadX) + E - 32 => E + E :MSTORE(readXFromCalldataOffset), CALL(readFromCalldataOffset); in: [readXFromCalldataOffset: offset value, readXFromCalldataLength: length value], out: [readXFromCalldataResult: result value] + $ => A :MLOAD(readXFromCalldataResult) + C - 32 => C :JMP(modexp_getBaseMstore) + +modexp_getBaseMloadX: + C :MSTORE(readXFromCalldataLength) + E - C => E + E :MSTORE(readXFromCalldataOffset), CALL(readFromCalldataOffset); in: [readXFromCalldataOffset: offset value, readXFromCalldataLength: length value], out: [readXFromCalldataResult: result value] + $ => A :MLOAD(readXFromCalldataResult) + 32 - C => D :CALL(SHRarith) + 0 => C + +modexp_getBaseMstore: + ; mstore base at index E + E :MSTORE(tmpVarEmodexp) + $ => E :MLOAD(modExpArrayIndex) + A :MSTORE(modexp_B+E) + ; update modExpArrayIndex + 1 + E + 1 => B :MSTORE(modExpArrayIndex) + +modexp_getBaseFinal: + $ => E :MLOAD(tmpVarEmodexp),JMP(modexp_getBaseLoop) + +modexp_saveBaseLen: + + %MAX_CNT_BINARY - CNT_BINARY - 2 :JMPN(outOfCountersBinary) + %MAX_CNT_STEPS - STEP - 20 :JMPN(outOfCountersStep) + + ; if modExpArrayIndex == 0 --> modexp_getReturn + $ => A :MLOAD(modExpArrayIndex) + 0 => B + $ :EQ,JMPC(modexp_getReturn) + ; update modExpArrayIndex = modExpArrayIndex - 1 + A - 1 => E :MSTORE(modExpArrayIndex) + ; get value of the last index + $ => A :MLOAD(modexp_B + E) + ; if last value == 0 --> modexp_saveBaseLen + $ :EQ,JMPC(modexp_saveBaseLen) + ; else Blen == modExpArrayIndex + 1 + E + 1 :MSTORE(modexp_Blen),JMP(modexp_getReturn) + +modexp_getExp: + + %MAX_CNT_STEPS - STEP - 15 :JMPN(outOfCountersStep) + + RR :MSTORE(tmpZkPCmodexp) + A :MSTORE(tmpVarAmodexp) + B :MSTORE(tmpVarBmodexp) + C :MSTORE(tmpVarCmodexp) + D :MSTORE(tmpVarDmodexp) + ; offset init + E :MSTORE(offsetInitModexp) + ;E = offset final + E + C => E + 0 :MSTORE(modExpArrayIndex) + 0 :MSTORE(modexp_Elen) + 32 :MSTORE(readXFromCalldataLength) + +modexp_getExpLoop: + + %MAX_CNT_BINARY - CNT_BINARY - 6 :JMPN(outOfCountersBinary) + %MAX_CNT_STEPS - STEP - 100 :JMPN(outOfCountersStep) + ; C length to read + C => A + 0 => B + ; if C (length) == 0 --> modexp_saveExpLen + $ :EQ,JMPC(modexp_saveExpLen) + 32 => B + ; if C (length) < 32 --> modexp_getExpMloadX + $ :LT,JMPC(modexp_getExpMloadX) + E - 32 => E + E :MSTORE(readXFromCalldataOffset), CALL(readFromCalldataOffset); in: [readXFromCalldataOffset: offset value, readXFromCalldataLength: length value], out: [readXFromCalldataResult: result value] + $ => A :MLOAD(readXFromCalldataResult) + C - 32 => C :JMP(modexp_getExpMstore) + +modexp_getExpMloadX: + C :MSTORE(readXFromCalldataLength) + E - C => E + E :MSTORE(readXFromCalldataOffset), CALL(readFromCalldataOffset); in: [readXFromCalldataOffset: offset value, readXFromCalldataLength: length value], out: [readXFromCalldataResult: result value] + $ => A :MLOAD(readXFromCalldataResult) + 32 - C => D :CALL(SHRarith) + 0 => C + +modexp_getExpMstore: + ; mstore exp at index E + E :MSTORE(tmpVarEmodexp) + $ => E :MLOAD(modExpArrayIndex) + A :MSTORE(modexp_E+E) + ; update modExpArrayIndex + 1 + E + 1 => B :MSTORE(modExpArrayIndex) + +modexp_getExpFinal: + $ => E :MLOAD(tmpVarEmodexp),JMP(modexp_getExpLoop) + +modexp_saveExpLen: + + %MAX_CNT_BINARY - CNT_BINARY - 2 :JMPN(outOfCountersBinary) + %MAX_CNT_STEPS - STEP - 20 :JMPN(outOfCountersStep) + + ; if modExpArrayIndex == 0 --> modexp_getReturn + $ => A :MLOAD(modExpArrayIndex) + 0 => B + $ :EQ,JMPC(modexp_getReturn) + ; update modExpArrayIndex = modExpArrayIndex - 1 + A - 1 => E :MSTORE(modExpArrayIndex) + ; get value of the last index + $ => A :MLOAD(modexp_E + E) + ; if last value == 0 --> modexp_saveExpLen + $ :EQ,JMPC(modexp_saveExpLen) + ; else Elen == modExpArrayIndex + 1 + E + 1 :MSTORE(modexp_Elen),JMP(modexp_getReturn) + +modexp_getMod: + + %MAX_CNT_STEPS - STEP - 15 :JMPN(outOfCountersStep) + + RR :MSTORE(tmpZkPCmodexp) + A :MSTORE(tmpVarAmodexp) + B :MSTORE(tmpVarBmodexp) + C :MSTORE(tmpVarCmodexp) + D :MSTORE(tmpVarDmodexp) + ; offset init + E :MSTORE(offsetInitModexp) + ;E = offset final + E + C => E + 0 :MSTORE(modExpArrayIndex) + 0 :MSTORE(modexp_Mlen) + 32 :MSTORE(readXFromCalldataLength) + +modexp_getModLoop: + + %MAX_CNT_BINARY - CNT_BINARY - 6 :JMPN(outOfCountersBinary) + %MAX_CNT_STEPS - STEP - 100 :JMPN(outOfCountersStep) + ; C length to read + C => A + 0 => B + ; if C (length) == 0 --> modexp_saveModLen + $ :EQ,JMPC(modexp_saveModLen) + 32 => B + ; if C (length) < 32 --> modexp_getModMloadX + $ :LT,JMPC(modexp_getModMloadX) + E - 32 => E + E :MSTORE(readXFromCalldataOffset), CALL(readFromCalldataOffset); in: [readXFromCalldataOffset: offset value, readXFromCalldataLength: length value], out: [readXFromCalldataResult: result value] + $ => A :MLOAD(readXFromCalldataResult) + C - 32 => C :JMP(modexp_getModMstore) + +modexp_getModMloadX: + C :MSTORE(readXFromCalldataLength) + E - C => E + E :MSTORE(readXFromCalldataOffset), CALL(readFromCalldataOffset); in: [readXFromCalldataOffset: offset value, readXFromCalldataLength: length value], out: [readXFromCalldataResult: result value] + $ => A :MLOAD(readXFromCalldataResult) + 32 - C => D :CALL(SHRarith) + 0 => C + +modexp_getModMstore: + ; mstore mod at index E + E :MSTORE(tmpVarEmodexp) + $ => E :MLOAD(modExpArrayIndex) + A :MSTORE(modexp_M+E) + ; update modExpArrayIndex + 1 + E + 1 => B :MSTORE(modExpArrayIndex) + +modexp_getModFinal: + $ => E :MLOAD(tmpVarEmodexp),JMP(modexp_getModLoop) + +modexp_saveModLen: + + %MAX_CNT_BINARY - CNT_BINARY - 2 :JMPN(outOfCountersBinary) + %MAX_CNT_STEPS - STEP - 20 :JMPN(outOfCountersStep) + + ; if modExpArrayIndex == 0 --> modexp_getReturn + $ => A :MLOAD(modExpArrayIndex) + 0 => B + $ :EQ,JMPC(modexp_getReturn) + ; update modExpArrayIndex = modExpArrayIndex - 1 + A - 1 => E :MSTORE(modExpArrayIndex) + ; get value of the last index + $ => A :MLOAD(modexp_M + E) + ; if last value == 0 --> modexp_saveModLen + $ :EQ,JMPC(modexp_saveModLen) + ; else Mlen == modExpArrayIndex + 1 + E + 1 :MSTORE(modexp_Mlen),JMP(modexp_getReturn) + +modexp_getReturn: + $ => RR :MLOAD(tmpZkPCmodexp) + $ => A :MLOAD(tmpVarAmodexp) + $ => B :MLOAD(tmpVarBmodexp) + $ => C :MLOAD(tmpVarCmodexp) + $ => D :MLOAD(tmpVarDmodexp) + $ => E :MLOAD(offsetInitModexp) + E + C => E + :RETURN diff --git a/main/opcodes/arithmetic.zkasm b/main/opcodes/arithmetic.zkasm index ae78d117..97652330 100644 --- a/main/opcodes/arithmetic.zkasm +++ b/main/opcodes/arithmetic.zkasm @@ -1,6 +1,6 @@ /** - * @link [Link EVM behaviour --> evm.codes?] + * @link [https://www.evm.codes/#01?fork=berlin] * @zk-counters * - 20 steps * - 1 binary diff --git a/main/opcodes/block.zkasm b/main/opcodes/block.zkasm index 174478df..a72452f3 100644 --- a/main/opcodes/block.zkasm +++ b/main/opcodes/block.zkasm @@ -22,7 +22,7 @@ opBLOCKHASH: GAS - %GAS_EXT_STEP => GAS :JMPN(outOfGas) $ => B :MLOAD(SP) ; [blockNumber => B] - ; If block number does not exist in the smart conract system, it will return 0 + ; If block number does not exist in the smart contract system, it will return 0 ; Create key for the batch hash mapping key ; set bytes length to D @@ -94,16 +94,12 @@ opTIMESTAMP: opNUMBER: ; checks zk-counters %MAX_CNT_STEPS - STEP - 10 :JMPN(outOfCountersStep) - %MAX_CNT_BINARY - CNT_BINARY - 1 :JMPN(outOfCountersBinary) ; check out-of-gas GAS - %GAS_QUICK_STEP => GAS :JMPN(outOfGas) - ; Get current tx count - $ => A :MLOAD(txCount) - 1 => B - - ; call binary:add state machine and push to the stack - $ :ADD, MSTORE(SP++); [blockNumber => SP] + ; Get current block number + $ => A :MLOAD(blockNum) + A :MSTORE(SP++); [blockNumber => SP] ; check stack overflow %MAX_STACK_SIZE - SP :JMPN(stackOverflow, readCode) @@ -141,8 +137,8 @@ opGASLIMIT: ; check out-of-gas GAS-%GAS_QUICK_STEP => GAS :JMPN(outOfGas) - ; constant tx gas limit - %TX_GAS_LIMIT => A + ; constant block gas limit + %BLOCK_GAS_LIMIT => A A :MSTORE(SP++); [gasLimit => SP] ; check stack overflow %MAX_STACK_SIZE - SP :JMPN(stackOverflow, readCode) diff --git a/main/opcodes/calldata-returndata-code.zkasm b/main/opcodes/calldata-returndata-code.zkasm index fd85e440..2514b80a 100644 --- a/main/opcodes/calldata-returndata-code.zkasm +++ b/main/opcodes/calldata-returndata-code.zkasm @@ -97,7 +97,7 @@ opCALLDATACOPY: $ => E :MLOAD(lastMemOffset) ; Recover size at C $ => C :MLOAD(lastMemLength) - ; If is a calldataCopy called from codeCopy, copy code from calldata alloccation, else if is a create contract, return 0 + ; If is a calldataCopy called from codeCopy, copy code from calldata allocation, else if is a create contract, return 0 $ :MLOAD(isCalldataCopyFromCodeCopy), JMPNZ(continueOpCalldatacopyFromCodeCopy) $ :MLOAD(isCreateContract), JMPNZ(opCALLDATACOPY0, continueOpCalldatacopy) continueOpCalldatacopyFromCodeCopy: @@ -351,7 +351,7 @@ opEXTCODESIZE: $ => A :MLOAD(SP), CALL(maskAddress); [address => A]; in: [A: address] out: [A: masked address] :CALL(isColdAddress); in: [A: address] out: [D: 0 if warm, 1 if cold] ; check out-of-gas - GAS - %WARM_STORGE_READ_GAS - D * %COLD_ACCOUNT_ACCESS_COST_REDUCED => GAS :JMPN(outOfGas) + GAS - %WARM_STORAGE_READ_GAS - D * %COLD_ACCOUNT_ACCESS_COST_REDUCED => GAS :JMPN(outOfGas) ; set key for smt smart contract length query %SMT_KEY_SC_LENGTH => B 0 => C @@ -386,7 +386,7 @@ opEXTCODECOPY: :CALL(isColdAddress); in: [A: address] out: [D: 0 if warm, 1 if cold] ; check out-of-gas - GAS - %WARM_STORGE_READ_GAS - D * %COLD_ACCOUNT_ACCESS_COST_REDUCED => GAS :JMPN(outOfGas) + GAS - %WARM_STORAGE_READ_GAS - D * %COLD_ACCOUNT_ACCESS_COST_REDUCED => GAS :JMPN(outOfGas) :CALL(opEXTCODECOPYLoadBytecode) $ => C :MLOAD(SP+2); [destOffset => C] $ => D :MLOAD(SP+1); [offset => D] @@ -436,17 +436,14 @@ opEXTCODECOPYLoadBytecode: %SMT_KEY_SC_LENGTH => B 0 => C $ => D :SLOAD - D :MSTORE(tmpContractLength) ; if length is 0, nothing to check - A => E - 0 => A - D => B - $ :EQ, JMPC(opEXTCODECOPYCheckHashEnd) + ; after the implementation of EIP170, the maximum bytecode size is 24.576 bytes, less than 2**32 + D :MSTORE(tmpContractLength), JMPZ(opEXTCODECOPYCheckHashEnd) ; check poseidon counters ; 56 is the value used by the prover to increment poseidon counters depending on the hash length RR :MSTORE(tmpZkPCext) - B + 1 :MSTORE(arithA) + D + 1 :MSTORE(arithA) 56 :MSTORE(arithB), CALL(divARITH); in: [arithA, arithB] out: [arithRes1: arithA/arithB, arithRes2: arithA%arithB] $ => RR :MLOAD(tmpZkPCext) $ => B :MLOAD(arithRes1) @@ -454,7 +451,6 @@ opEXTCODECOPYLoadBytecode: %MAX_CNT_PADDING_PG_LIMIT - CNT_PADDING_PG - 1 - B :JMPN(outOfCountersPadding) ; set key for smt smart contract code query - E => A %SMT_KEY_SC_CODE => B 0 => C $ => A :SLOAD @@ -543,7 +539,7 @@ opRETURNDATACOPY: ; if retDataLength < offset + size -> OOG A - B - C :JMPN(outOfGas) - ; E ret data offset (memory pointer) of last context, B offset in return data that want to retrive + ; E ret data offset (memory pointer) of last context, B offset in return data that want to retrieve E + B => B ; memory pointer where start to copy memory ;${3*((C+31)/32)} C+31 => A @@ -615,7 +611,7 @@ opEXTCODEHASH: $ => A :MLOAD(SP), CALL(maskAddress); [address => A]; in: [A: address] out: [A: masked address] :CALL(isColdAddress); in: [A: address] out: [D: 0 if warm, 1 if cold] ; check out-of-gas - GAS - %WARM_STORGE_READ_GAS - D * %COLD_ACCOUNT_ACCESS_COST_REDUCED => GAS :JMPN(outOfGas) + GAS - %WARM_STORAGE_READ_GAS - D * %COLD_ACCOUNT_ACCESS_COST_REDUCED => GAS :JMPN(outOfGas) ; set key for smt smart contract code hash query %SMT_KEY_SC_CODE => B 0 => C diff --git a/main/opcodes/context-information.zkasm b/main/opcodes/context-information.zkasm index 2c105471..372a6961 100644 --- a/main/opcodes/context-information.zkasm +++ b/main/opcodes/context-information.zkasm @@ -73,7 +73,7 @@ opBALANCE: $ => D :SLOAD D :MSTORE(SP-1), CALL(isColdAddress); [balance(D) => SP]; in: [A: address] out: [D: 0 if warm, 1 if cold] ; check out-of-gas - GAS - %WARM_STORGE_READ_GAS - D * %COLD_ACCOUNT_ACCESS_COST_REDUCED => GAS :JMPN(outOfGas, readCode) + GAS - %WARM_STORAGE_READ_GAS - D * %COLD_ACCOUNT_ACCESS_COST_REDUCED => GAS :JMPN(outOfGas, readCode) /** * @link [https://www.evm.codes/#32?fork=berlin] diff --git a/main/opcodes/create-terminate-context.zkasm b/main/opcodes/create-terminate-context.zkasm index febcae8e..92ad41d3 100644 --- a/main/opcodes/create-terminate-context.zkasm +++ b/main/opcodes/create-terminate-context.zkasm @@ -28,7 +28,7 @@ opSTOPend: CTX :MSTORE(currentCTX) ; restore retDataCTX, no return data in stop 0 :MSTORE(retDataCTX) - ; handle gas reund + ; handle gas refund $ => B :MLOAD(gasCTX) A :MSTORE(gasRefund) GAS + B => GAS @@ -36,10 +36,7 @@ opSTOPend: $ => SP :MLOAD(lastSP) $ => PC :MLOAD(lastPC) ; store stack output - D :MSTORE(SP++) - ; decrease depth - $ => A :MLOAD(depth) - A - 1 :MSTORE(depth), JMP(readCode) + D :MSTORE(SP++), JMP(readCode) /** * @link [https://www.evm.codes/#f0?fork=berlin] @@ -54,17 +51,13 @@ opSTOPend: opCREATE: ; checks zk-counters %MAX_CNT_STEPS - STEP - 200 :JMPN(outOfCountersStep) - %MAX_CNT_BINARY - CNT_BINARY - 3 :JMPN(outOfCountersBinary) + %MAX_CNT_BINARY - CNT_BINARY - 4 :JMPN(outOfCountersBinary) %MAX_CNT_POSEIDON_G - CNT_POSEIDON_G - %MAX_CNT_POSEIDON_SLOAD_SSTORE*3 :JMPN(outOfCountersPoseidon) ; check out-of-gas GAS - %CREATE_GAS => GAS :JMPN(outOfGas) GAS :MSTORE(gasCall) - ; increase depth - $ => A :MLOAD(depth) - A + 1 :MSTORE(depth) - ; check stack underflow SP - 3 :JMPN(stackUnderflow) ; check is static @@ -148,16 +141,13 @@ opCREATE: $ => A :MLOAD(argsLengthCall) ; set calldata pointers to current CTX A :MSTORE(txCalldataLen), CALL(saveCalldataPointer) - $ => A :MLOAD(valueCall) + $ => A :MLOAD(valueCall), CALL(checkpointBlockInfoTree) ; Save touched root when a new context is created A :MSTORE(txValue), CALL(checkpointTouched) :JMP(txType) opCreateFail: - ; decrease depth - $ => A :MLOAD(depth) - A - 1 :MSTORE(depth) - + ; return 0 if create fails 0 :MSTORE(retDataCTX) 0 :MSTORE(SP++), JMP(readCode); [0 => SP] @@ -175,9 +165,6 @@ opCALL: ; checks zk-counters %MAX_CNT_STEPS - STEP - 200 :JMPN(outOfCountersStep) %MAX_CNT_BINARY - CNT_BINARY - 3 :JMPN(outOfCountersBinary) - ; increase depth - $ => A :MLOAD(depth) - A + 1 :MSTORE(depth) ; check stack underflow SP - 7 :JMPN(stackUnderflow) SP - 1 => SP @@ -228,7 +215,7 @@ opCALL2: ;gas_cost = memory_expansion_cost + code_execution_cost + address_access_cost + positive_value_cost + value_to_empty_account_cost ; Calculate address_access_cost: 100 for warm account, 2600 for cold account - GAS - %WARM_STORGE_READ_GAS - D * %COLD_ACCOUNT_ACCESS_COST_REDUCED => GAS :JMPN(outOfGas) + GAS - %WARM_STORAGE_READ_GAS - D * %COLD_ACCOUNT_ACCESS_COST_REDUCED => GAS :JMPN(outOfGas) ; Calculate positive_value_cost, if value call > 0 -> 9000 $ => B :MLOAD(valueCall) 0 => A @@ -281,6 +268,7 @@ opCALLend: A :MSTORE(txCalldataLen), CALL(saveCalldataPointer) ; save touched root when a new context is created :CALL(checkpointTouched) + :CALL(checkpointBlockInfoTree) :JMP(txType) /** @@ -296,9 +284,6 @@ opCALLCODE: ; checks zk-counters %MAX_CNT_STEPS - STEP - 200 :JMPN(outOfCountersStep) %MAX_CNT_BINARY - CNT_BINARY - 2 :JMPN(outOfCountersBinary) - ; increase depth - $ => A :MLOAD(depth) - A + 1 :MSTORE(depth) ; check stack underflow SP - 7 :JMPN(stackUnderflow) SP - 1 => SP @@ -339,12 +324,12 @@ opCALLCODE: ;gas_cost = memory_expansion_cost + code_execution_cost + address_access_cost + positive_value_cost ; Calculate address_access_cost: 100 for warm account, 2600 for cold account - GAS - %WARM_STORGE_READ_GAS - D * %COLD_ACCOUNT_ACCESS_COST_REDUCED => GAS :JMPN(outOfGas) + GAS - %WARM_STORAGE_READ_GAS - D * %COLD_ACCOUNT_ACCESS_COST_REDUCED => GAS :JMPN(outOfGas) ; Calculate positive_value_cost, if value call > 0 -> 9000 $ => B :MLOAD(valueCall) 0 => A $ :EQ,JMPC(opCALLCODEend) - ; Substract gas if the call has value + ; Subtract gas if the call has value GAS - %CALL_VALUE_TRANSFER_GAS => GAS :JMPN(outOfGas) opCALLCODEend: @@ -389,6 +374,7 @@ opCALLCODEend: A :MSTORE(txCalldataLen), CALL(saveCalldataPointer) ; Save touched root when a new context is created :CALL(checkpointTouched) + :CALL(checkpointBlockInfoTree) :JMP(txType) /** * @link [https://www.evm.codes/#f3?fork=berlin] @@ -480,10 +466,7 @@ opRETURNend: ; restore origin CTX values $ => SP :MLOAD(lastSP) $ => PC :MLOAD(lastPC) - 1 :MSTORE(SP++); [1 => SP] - ; decrease depth - $ => A :MLOAD(depth) - A - 1 :MSTORE(depth), JMP(readCode) + 1 :MSTORE(SP++), JMP(readCode); [1 => SP] opRETURNdeploy: ; code size limit = 0x6000 @@ -497,7 +480,7 @@ opRETURNcreate: ; checks zk-counters %MAX_CNT_STEPS - STEP - 400 :JMPN(outOfCountersStep) %MAX_CNT_POSEIDON_G - CNT_POSEIDON_G - %MAX_CNT_POSEIDON_SLOAD_SSTORE*2 :JMPN(outOfCountersPoseidon) - + %MAX_CNT_BINARY - CNT_BINARY - 2 :JMPN(outOfCountersBinary) ; save offset memory and length to compute contract hash E :MSTORE(memOffsetLinearPoseidon) C :MSTORE(memSizeLinearPoseidon), CALL(checkBytecodeStartsEF) ; in: [memOffset], out: [startsWithEF] @@ -529,10 +512,7 @@ opRETURNcreateEnd: ; set SP and PC $ => SP :MLOAD(lastSP) $ => PC :MLOAD(lastPC) - A :MSTORE(SP++); [createContractAddress(A) => SP] - ; decrease depth - $ => A :MLOAD(depth) - A - 1 :MSTORE(depth), JMP(readCode) + A :MSTORE(SP++), JMP(readCode); [createContractAddress(A) => SP] /** * @link [https://www.evm.codes/#f4?fork=berlin] @@ -545,9 +525,7 @@ opRETURNcreateEnd: opDELEGATECALL: ; checks zk-counters %MAX_CNT_STEPS - STEP - 400 :JMPN(outOfCountersStep) - ; increase depth - $ => A :MLOAD(depth) - A + 1 :MSTORE(depth) + ; check stack underflow SP - 6 :JMPN(stackUnderflow) SP - 1 => SP @@ -586,7 +564,7 @@ opDELEGATECALL: $ => A :MLOAD(addrCall) :CALL(isColdAddress); in: [A: address] out: [D: 0 if warm, 1 if cold] ;gas_cost = base_gas + gas_sent_with_call - GAS - %WARM_STORGE_READ_GAS - D * %COLD_ACCOUNT_ACCESS_COST_REDUCED => GAS :JMPN(outOfGas) + GAS - %WARM_STORAGE_READ_GAS - D * %COLD_ACCOUNT_ACCESS_COST_REDUCED => GAS :JMPN(outOfGas) ; transition to new CTX $ => C :MLOAD(txSrcAddr) @@ -626,6 +604,7 @@ opDELEGATECALLend: A :MSTORE(txCalldataLen), CALL(saveCalldataPointer) ; Save touched root when a new context is created :CALL(checkpointTouched) + :CALL(checkpointBlockInfoTree) :JMP(txType) /** @@ -641,15 +620,11 @@ opDELEGATECALLend: opCREATE2: ; checks zk-counters %MAX_CNT_STEPS - STEP - 400 :JMPN(outOfCountersStep) - %MAX_CNT_BINARY - CNT_BINARY - 4 :JMPN(outOfCountersBinary) + %MAX_CNT_BINARY - CNT_BINARY - 5 :JMPN(outOfCountersBinary) %MAX_CNT_POSEIDON_G - CNT_POSEIDON_G - %MAX_CNT_POSEIDON_SLOAD_SSTORE*2 :JMPN(outOfCountersPoseidon) ; check out-of-gas GAS - %CREATE_2_GAS => GAS :JMPN(outOfGas) - ; increase depth - $ => A :MLOAD(depth) - A + 1 :MSTORE(depth) - ; check stack underflow SP - 4 :JMPN(stackUnderflow) ; check is static @@ -672,7 +647,7 @@ opCREATE2: ; store current CTX to auxiliary var for later usage CTX :MSTORE(originAuxCTX) - ; cost to hash the initialisation code + ; cost to hash the initialization code C + 31 :MSTORE(arithA) 32 :MSTORE(arithB), CALL(divARITH); in: [arithA, arithB] out: [arithRes1: arithA/arithB, arithRes2: arithA%arithB] $ => C :MLOAD(arithRes1) @@ -746,7 +721,7 @@ opCREATE2: $ => A :MLOAD(argsLengthCall) ; set calldata pointers to current CTX A :MSTORE(txCalldataLen), CALL(saveCalldataPointer) - $ => A :MLOAD(valueCall) + $ => A :MLOAD(valueCall), CALL(checkpointBlockInfoTree) ; Save touched root when a new context is created A :MSTORE(txValue), CALL(checkpointTouched) :JMP(txType) @@ -762,9 +737,6 @@ opCREATE2: opSTATICCALL: ; checks zk-counters %MAX_CNT_STEPS - STEP - 300 :JMPN(outOfCountersStep) - ; increase depth - $ => A :MLOAD(depth) - A + 1 :MSTORE(depth) ; check stack underflow SP - 6 :JMPN(stackUnderflow) SP - 1 => SP @@ -797,7 +769,7 @@ opSTATICCALL: ; check if an address is cold. If it is, add it to the touched tree $ => A :MLOAD(addrCall), CALL(isColdAddress); in: [A: address] out: [D: 0 if warm, 1 if cold] ;gas_cost = base_gas + gas_sent_with_call - GAS - %WARM_STORGE_READ_GAS - D * %COLD_ACCOUNT_ACCESS_COST_REDUCED => GAS :JMPN(outOfGas) + GAS - %WARM_STORAGE_READ_GAS - D * %COLD_ACCOUNT_ACCESS_COST_REDUCED => GAS :JMPN(outOfGas) ; setup vars for next CTX $ => D :MLOAD(storageAddr) @@ -831,6 +803,7 @@ opSTATICCALL: A :MSTORE(txCalldataLen), CALL(saveCalldataPointer) ; save touched root when a new context is created :CALL(checkpointTouched) + :CALL(checkpointBlockInfoTree) :JMP(txType) /** * @link [https://www.evm.codes/#fd?fork=berlin] @@ -849,7 +822,7 @@ opREVERT: ; revert touched accounts $ => SR :MLOAD(initSR), CALL(revertTouched) - $ => E :MLOAD(SP+1); [offset => E] + $ => E :MLOAD(SP+1), CALL(revertBlockInfoTree); [offset => E] $ => C :MLOAD(SP); [size => C] E :MSTORE(retDataOffset) C :MSTORE(retDataLength) @@ -863,7 +836,7 @@ opREVERT: $${eventLog(onError, revert)} 0 :MSTORE(gasRefund) ; if origin ctx is 0, end tx - B :JMPZ(handleGas) + B :JMPZ(handleGasFromError) ; decrease CTX $ => A :MLOAD(currentCTX) B => CTX @@ -917,10 +890,7 @@ opREVERTend: CTX :MSTORE(currentCTX) $ => SP :MLOAD(lastSP) $ => PC :MLOAD(lastPC) - 0 :MSTORE(SP++); [0 => SP] - ; decrease depth - $ => A :MLOAD(depth) - A - 1 :MSTORE(depth), JMP(readCode) + 0 :MSTORE(SP++), JMP(readCode); [0 => SP] VAR GLOBAL sendAllAddress ; SELFDESTRUCT is deprecated and EIP-4758 is implemented: https://eips.ethereum.org/EIPS/eip-4758 @@ -938,7 +908,7 @@ VAR GLOBAL sendAllAddress opSENDALL: ; checks zk-counters %MAX_CNT_STEPS - STEP - 400 :JMPN(outOfCountersStep) - %MAX_CNT_BINARY - CNT_BINARY - 2 :JMPN(outOfCountersBinary) + %MAX_CNT_BINARY - CNT_BINARY - 4 :JMPN(outOfCountersBinary) %MAX_CNT_POSEIDON_G - CNT_POSEIDON_G - %MAX_CNT_POSEIDON_SLOAD_SSTORE*4 :JMPN(outOfCountersPoseidon) ; check out-of-gas GAS - %SENDALL_GAS => GAS :JMPN(outOfGas) @@ -1026,10 +996,8 @@ opSENDALLendContinue: ; restore origin CTX values $ => SP :MLOAD(lastSP) $ => PC :MLOAD(lastPC) - D :MSTORE(SP++); [output => SP] - ; decrease depth - $ => A :MLOAD(depth) - A - 1 :MSTORE(depth), JMP(readCode) + D :MSTORE(SP++), JMP(readCode); [output => SP] + /** * @link [https://www.evm.codes/#fe?fork=berlin] * @zk-counters diff --git a/main/opcodes/logs.zkasm b/main/opcodes/logs.zkasm index b73e1dcb..ca8f75fa 100644 --- a/main/opcodes/logs.zkasm +++ b/main/opcodes/logs.zkasm @@ -7,6 +7,8 @@ * - stack input: [offset, size, topic] * - stack output: none */ + VAR GLOBAL opLogAux + opLOG0: ; checks zk-counters %MAX_CNT_STEPS - STEP - 100 :JMPN(outOfCountersStep) @@ -37,10 +39,7 @@ opLOG0: GAS => A ; check out-of-gas $ :LT,JMPC(outOfGas) - GAS - B => GAS - $ => B :MLOAD(nextFreeLogIndex) ; load logIndex - B + 1 :MSTORE(nextFreeLogIndex), JMP(opLOGLoop) ; store next free log index - + GAS - B => GAS :JMP(initLogLoop) opLOG1: %MAX_CNT_STEPS - STEP - 100 :JMPN(outOfCountersStep) @@ -60,9 +59,7 @@ opLOG1: GAS => A ; check out-of-gas $ :LT,JMPC(outOfGas) - GAS - B => GAS - $ => B :MLOAD(nextFreeLogIndex) - B + 1 :MSTORE(nextFreeLogIndex), JMP(opLOGLoop) + GAS - B => GAS :JMP(initLogLoop) opLOG2: @@ -83,9 +80,7 @@ opLOG2: GAS => A ; check out-of-gas $ :LT,JMPC(outOfGas) - GAS - B => GAS - $ => B :MLOAD(nextFreeLogIndex) - B + 1 :MSTORE(nextFreeLogIndex), JMP(opLOGLoop) + GAS - B => GAS :JMP(initLogLoop) opLOG3: @@ -106,9 +101,7 @@ opLOG3: GAS => A ; check out-of-gas $ :LT,JMPC(outOfGas) - GAS - B => GAS - $ => B :MLOAD(nextFreeLogIndex) - B + 1 :MSTORE(nextFreeLogIndex), JMP(opLOGLoop) + GAS - B => GAS :JMP(initLogLoop) opLOG4: @@ -129,39 +122,69 @@ opLOG4: GAS => A ; check out-of-gas $ :LT,JMPC(outOfGas) - GAS - B => GAS - $ => B :MLOAD(nextFreeLogIndex) - B + 1 :MSTORE(nextFreeLogIndex), JMP(opLOGLoop) - -opLOGLoop: + GAS - B => GAS :JMP(initLogLoop) + +initLogLoop: + ; check poseidon counters + ; 56 is the value used by the prover to increment poseidon counters depending on the hash length + C :MSTORE(arithA) + 56 :MSTORE(arithB), CALL(divARITH); in: [arithA, arithB] out: [arithRes1: arithA/arithB, arithRes2: arithA%arithB] + $ => B :MLOAD(arithRes1) + ; We count B and also the number of topics, as max is 4 topics of 32 bytes each 32*4/56 = 2.2 -> 3 + %MAX_CNT_POSEIDON_G - CNT_POSEIDON_G - 4 - B :JMPN(outOfCountersPoseidon) + %MAX_CNT_PADDING_PG_LIMIT - CNT_PADDING_PG - 4 - B :JMPN(outOfCountersPadding) + 0 => HASHPOS + 32 => D + $ => B :MLOAD(currentLogIndex) +logLoop: ; checks zk-counters %MAX_CNT_STEPS - STEP - 100 :JMPN(outOfCountersStep) C :JMPZ(opSaveTopicsInit) ; load next 32 bytes - C - 32 :JMPN(opLOGFinal) + C - 32 :JMPN(opLogFinal) :CALL(MLOAD32); in: [E: offset] out: [A: value] + E :MSTORE(opLogAux) + $ => E :MLOAD(nextHashPId) + A :HASHP(E) + $ => E :MLOAD(opLogAux) $${storeLog(B, 0, A)} ; storeLog(indexLog, isTopic, bytesToStore) - C - 32 => C :JMP(opLOGLoop) + C - 32 => C :JMP(logLoop) -opLOGFinal: +opLogFinal: ; load last C bytes :CALL(MLOADX); in: [E: offset, C: length] out: [A: value, E: new offset] $${storeLog(B, 0, A)}; storeLog(indexLog, isTopic, bytesToStore) + 32 - C => D :CALL(SHRarith); in: [A: value, D: #bytes to right shift] out: [A: shifted result] + C => D + $ => E :MLOAD(nextHashPId) + A :HASHP(E) :JMP(opSaveTopicsInit) ; instruction added to allow executing $$ function opSaveTopicsInit: ; save topics $ => A :MLOAD(numTopics) + $ => E :MLOAD(nextHashPId) + 32 => D opSaveTopicsLoop: ; checks zk-counters %MAX_CNT_STEPS - STEP - 100 :JMPN(outOfCountersStep) - A :JMPZ(readCode) + A :JMPZ(finishSaveTopics) ; check stack underflow SP - 1 => SP ; check out-of-gas - GAS - %LOG_TOPIC_GAS => GAS :JMPN(outOfGas) - $ => C :MLOAD(SP) ; [topic => C] + GAS - %LOG_TOPIC_GAS => GAS :JMPN(outOfGas) + $ => C :MLOAD(SP) ; [topic => C] + C :HASHP(E) $${storeLog(B, 1, C)} ; storeLog(indexLog, isTopic, bytesToStore) - A - 1 => A :JMP(opSaveTopicsLoop) + A - 1 => A :JMP(opSaveTopicsLoop) + +finishSaveTopics: + %MAX_CNT_BINARY - CNT_BINARY - 1 :JMPN(outOfCountersBinary) + ; Update nextHashPId + E + 1 :MSTORE(nextHashPId) + ; Compute hash of the log + HASHPOS :HASHPLEN(E) + $ => D :HASHPDIGEST(E), CALL(fillBlockInfoTreeWithLog); in: [D: linearPoseidon(log_data + log_topics)] + :JMP(readCode) \ No newline at end of file diff --git a/main/opcodes/stack-operations.zkasm b/main/opcodes/stack-operations.zkasm index b19dbc50..5bd3af0b 100644 --- a/main/opcodes/stack-operations.zkasm +++ b/main/opcodes/stack-operations.zkasm @@ -234,7 +234,7 @@ opAuxPUSHBcreate: B - PC => C :JMPZ(opfinalPUSHBcreate) opAuxPUSHBcreate2: - ; set length to read to C for MOLADX call + ; set length to read to C for MLOADX call :CALL(MLOADX); in: [E: offset, C: length] out: [A: value, E: new offset] ; increase to PC the length of the read bytes PC + D => PC diff --git a/main/pairings/BN254/addPointBN254.zkasm b/main/pairings/BN254/addPointBN254.zkasm new file mode 100644 index 00000000..8c2cf80b --- /dev/null +++ b/main/pairings/BN254/addPointBN254.zkasm @@ -0,0 +1,245 @@ +;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; PRE: P1,P2 ∈ E'(Fp2) +;; POST: The resulting coordinates are in the range [0,BN254_P) because if falls back to FP2 arithmetic +;; +;; addPointBN254: +;; in: P1 = (P1.x1 + P1.x2·u, P1.y1 + P1.y2·u), P2 = (P2.x1 + P2.x2·u, P2.y1 + P2.y2·u) ∈ E'(Fp2) +;; out: P1 + P2 = (P3.x1 + P3.x2·u, P3.y1 + P3.y2·u) ∈ E'(Fp2) +;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +; addPointBN254 assumes both P1 and P2 belong to E'(Fp2), since it is checked in the pairing. +; However, it must be implemented if addPointBN254 wants to be used independently. + +; Since the curve is E'/Fp2: y² = x³ + 3/(9+u), there is no issue in representing the point at infinity as (0, 0). + +VAR GLOBAL addPointBN254_P1_x1 +VAR GLOBAL addPointBN254_P1_x2 +VAR GLOBAL addPointBN254_P1_y1 +VAR GLOBAL addPointBN254_P1_y2 +VAR GLOBAL addPointBN254_P2_x1 +VAR GLOBAL addPointBN254_P2_x2 +VAR GLOBAL addPointBN254_P2_y1 +VAR GLOBAL addPointBN254_P2_y2 +VAR GLOBAL addPointBN254_P3_x1 +VAR GLOBAL addPointBN254_P3_x2 +VAR GLOBAL addPointBN254_P3_y1 +VAR GLOBAL addPointBN254_P3_y2 +VAR GLOBAL addPointBN254_lambda_x +VAR GLOBAL addPointBN254_lambda_y +VAR GLOBAL addPointBN254_RR + +addPointBN254: + RR :MSTORE(addPointBN254_RR) + + ; Is P1 = O? + 0n => B + $ => A :MLOAD(addPointBN254_P1_x1) + $ :EQ, JMPNC(__addPointBN254_P1_continue) + $ => A :MLOAD(addPointBN254_P1_x2) + $ :EQ, JMPNC(__addPointBN254_P1_continue) + $ => A :MLOAD(addPointBN254_P1_y1) + $ :EQ, JMPNC(__addPointBN254_P1_continue) + $ => A :MLOAD(addPointBN254_P1_y2) + $ :EQ, JMPC(addPointBN254_P1_is_zero) + __addPointBN254_P1_continue: + + ; Is P2 = 0? + 0n => B + $ => A :MLOAD(addPointBN254_P2_x1) + $ :EQ, JMPNC(__addPointBN254_P2_continue) + $ => A :MLOAD(addPointBN254_P2_x2) + $ :EQ, JMPNC(__addPointBN254_P2_continue) + $ => A :MLOAD(addPointBN254_P2_y1) + $ :EQ, JMPNC(__addPointBN254_P2_continue) + $ => A :MLOAD(addPointBN254_P2_y2) + $ :EQ, JMPC(addPointBN254_P2_is_zero) + __addPointBN254_P2_continue: + + ; P1 and P2 are not 0, let's check whether they are different points, the same point or inverses of each other + ; Is P1.x == P2.x? + $ => A :MLOAD(addPointBN254_P1_x1) + $ => B :MLOAD(addPointBN254_P2_x1) + $ :EQ, JMPNC(addPointBN254_different) + $ => A :MLOAD(addPointBN254_P1_x2) + $ => B :MLOAD(addPointBN254_P2_x2) + $ :EQ, JMPNC(addPointBN254_different) + + ; Is P1.y == P2.y? + $ => A :MLOAD(addPointBN254_P1_y1) + $ => B :MLOAD(addPointBN254_P2_y1) + $ :EQ, JMPNC(addPointBN254_P1_and_P2_are_inverted) + $ => A :MLOAD(addPointBN254_P1_y2) + $ => B :MLOAD(addPointBN254_P2_y2) + $ :EQ, JMPNC(addPointBN254_P1_and_P2_are_inverted) + + ; P1 == P2 + :JMP(addPointBN254_same) + +addPointBN254_P1_is_zero: + ; P3 = P2 + $ => A :MLOAD(addPointBN254_P2_x1) + $ => B :MLOAD(addPointBN254_P2_x2) + $ => C :MLOAD(addPointBN254_P2_y1) + $ => D :MLOAD(addPointBN254_P2_y2) + A :MSTORE(addPointBN254_P3_x1) + B :MSTORE(addPointBN254_P3_x2) + C :MSTORE(addPointBN254_P3_y1) + D :MSTORE(addPointBN254_P3_y2) + + :JMP(addPointBN254_end) + +addPointBN254_P2_is_zero: + ; P3 = P1 + $ => A :MLOAD(addPointBN254_P1_x1) + $ => B :MLOAD(addPointBN254_P1_x2) + $ => C :MLOAD(addPointBN254_P1_y1) + $ => D :MLOAD(addPointBN254_P1_y2) + A :MSTORE(addPointBN254_P3_x1) + B :MSTORE(addPointBN254_P3_x2) + C :MSTORE(addPointBN254_P3_y1) + D :MSTORE(addPointBN254_P3_y2) + + :JMP(addPointBN254_end) + +addPointBN254_P1_and_P2_are_inverted: + ; Check -P1.y == P2.y + %BN254_P => A + $ => B :MLOAD(addPointBN254_P1_y1) + $ => C :SUB + $ => B :MLOAD(addPointBN254_P1_y2) + $ => D :SUB + + $ => A :MLOAD(addPointBN254_P2_y1) + C :ASSERT + $ => A :MLOAD(addPointBN254_P2_y2) + D :ASSERT + + ; P3 = O + 0n :MSTORE(addPointBN254_P3_x1) + 0n :MSTORE(addPointBN254_P3_x2) + 0n :MSTORE(addPointBN254_P3_y1) + 0n :MSTORE(addPointBN254_P3_y2) + + :JMP(addPointBN254_end) + +addPointBN254_same: + $ => A :MLOAD(addPointBN254_P1_y1) + $ => B :MLOAD(addPointBN254_P1_y2) + $ => C :MLOAD(addPointBN254_P1_y1) + $ => D :MLOAD(addPointBN254_P1_y2), CALL(addFp2BN254) + ; E + C·u = 2y + + E => A + C => B :CALL(invFp2BN254) + ; C + D·u = 1 / 2y + + 3n => A :CALL(escalarMulFp2BN254) + ; E + C·u = 3/2y + + $ => A :MLOAD(addPointBN254_P1_x1) + $ => B :MLOAD(addPointBN254_P1_x2) + C => D + E => C :CALL(mulFp2BN254) + ; E + C·u = 3x/2y + + $ => A :MLOAD(addPointBN254_P1_x1) + $ => B :MLOAD(addPointBN254_P1_x2) + C => D + E => C :CALL(mulFp2BN254) + ; E + C·u = lambda = 3x²/2y + + E :MSTORE(addPointBN254_lambda_x) + C :MSTORE(addPointBN254_lambda_y) + ; E + C·u = lambda + + E => A + C => B :CALL(squareFp2BN254) + ; E + C·u = lambda² + + E => A + C => B + $ => C :MLOAD(addPointBN254_P1_x1) + $ => D :MLOAD(addPointBN254_P1_x2), CALL(subFp2BN254) + ; E + C·u = lambda² - x + + E => A + C => B + $ => C :MLOAD(addPointBN254_P1_x1) + $ => D :MLOAD(addPointBN254_P1_x2), CALL(subFp2BN254) + ; E + C·u = lambda² - x - x + + :JMP(addPointBN254_common_calculate) + +addPointBN254_different: + $ => A :MLOAD(addPointBN254_P2_x1) + $ => B :MLOAD(addPointBN254_P2_x2) + $ => C :MLOAD(addPointBN254_P1_x1) + $ => D :MLOAD(addPointBN254_P1_x2), CALL(subFp2BN254) + ; E + C·u = P2.x - P1.x + + E => A + C => B :CALL(invFp2BN254) + ; C + D·u = 1 / (P2_x - P1_x) + C :MSTORE(addPointBN254_lambda_x) + D :MSTORE(addPointBN254_lambda_y) + + $ => A :MLOAD(addPointBN254_P2_y1) + $ => B :MLOAD(addPointBN254_P2_y2) + $ => C :MLOAD(addPointBN254_P1_y1) + $ => D :MLOAD(addPointBN254_P1_y2), CALL(subFp2BN254) + ; E + C·u = P2.y - P1.y + + $ => A :MLOAD(addPointBN254_lambda_x) + $ => B :MLOAD(addPointBN254_lambda_y) + C => D + E => C :CALL(mulFp2BN254) + ; E + C·u = lambda = (P2_y - P1_y) / (P2_x - P1_x) + E :MSTORE(addPointBN254_lambda_x) + C :MSTORE(addPointBN254_lambda_y) + + E => A + C => B :CALL(squareFp2BN254) + ; E + C·u = lambda² + + E => A + C => B + $ => C :MLOAD(addPointBN254_P1_x1) + $ => D :MLOAD(addPointBN254_P1_x2), CALL(subFp2BN254) + ; E + C·u = lambda² - P1.x + + E => A + C => B + $ => C :MLOAD(addPointBN254_P2_x1) + $ => D :MLOAD(addPointBN254_P2_x2), CALL(subFp2BN254) + ; E + C·u = lambda² - P1.x - P2.x + +addPointBN254_common_calculate: + E :MSTORE(addPointBN254_P3_x1) + C :MSTORE(addPointBN254_P3_x2) + ; P3.x = lambda² - P1.x - P2.x + + $ => A :MLOAD(addPointBN254_P1_x1) + $ => B :MLOAD(addPointBN254_P1_x2) + C => D + E => C :CALL(subFp2BN254) + ; E + C·u = P1.x - P3.x + + $ => A :MLOAD(addPointBN254_lambda_x) + $ => B :MLOAD(addPointBN254_lambda_y) + C => D + E => C :CALL(mulFp2BN254) + ; E + C·u = lambda·(P1.x - P3.x) + + E => A + C => B + $ => C :MLOAD(addPointBN254_P1_y1) + $ => D :MLOAD(addPointBN254_P1_y2), CALL(subFp2BN254) + ; E + C·u = lambda·(P1.x - P3.x) - P1.y + + E :MSTORE(addPointBN254_P3_y1) + C :MSTORE(addPointBN254_P3_y2) + +addPointBN254_end: + $ => RR :MLOAD(addPointBN254_RR) + :RETURN \ No newline at end of file diff --git a/main/pairings/BN254/ecAdd.zkasm b/main/pairings/BN254/ecAdd.zkasm new file mode 100644 index 00000000..089116f7 --- /dev/null +++ b/main/pairings/BN254/ecAdd.zkasm @@ -0,0 +1,312 @@ +;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; POST: The resulting coordinates are in the range [0,BN254_P) because if falls back to FP arithmetic +;; +;; ecAdd: +;; in: P1 = (P1.x, P1.y), P2 = (P2.x, P2.y) ∈ E(Fp) +;; out: P1 + P2 = (P3.x, P3.y) ∈ E(Fp) +;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +; Since the curve is E/Fp: y² = x³ + 3, there is no issue in representing the point at infinity as (0, 0). + +VAR GLOBAL ecAdd_P1_x +VAR GLOBAL ecAdd_P1_y +VAR GLOBAL ecAdd_P1_y_inv +VAR GLOBAL ecAdd_P2_x +VAR GLOBAL ecAdd_P2_y +VAR GLOBAL ecAdd_P3_x +VAR GLOBAL ecAdd_P3_y +VAR GLOBAL ecAdd_lambda + +VAR GLOBAL ecAdd_RR + +; ERROR CODES (B) +; 0 - no error +; 1 - P1_x is too big +; 2 - P1_y is too big +; 3 - P2_x is too big +; 4 - P2_y is too big +; 5 - P1 is not in E(Fp) +; 6 - P2 is not in E(Fp) + +ecAdd: + RR :MSTORE(ecAdd_RR) + + %BN254_P_MINUS_ONE => A + $ => B :MLOAD(ecAdd_P1_x) + $ :LT, JMPC(ecAdd_P1x_too_big) + $ => B :MLOAD(ecAdd_P1_y) + $ :LT, JMPC(ecAdd_P1y_too_big) + $ => B :MLOAD(ecAdd_P2_x) + $ :LT, JMPC(ecAdd_P2x_too_big) + $ => B :MLOAD(ecAdd_P2_y) + $ :LT, JMPC(ecAdd_P2y_too_big) + + ; Is P1 = O? + 0n => B + $ => A :MLOAD(ecAdd_P1_x) + $ :EQ, JMPNC(__ecAdd_P1_continue) + $ => A :MLOAD(ecAdd_P1_y) + $ :EQ, JMPC(ecAdd_P1_is_zero) + __ecAdd_P1_continue: + + ; Is P2 = O? + 0n => B + $ => A :MLOAD(ecAdd_P2_x) + $ :EQ, JMPNC(__ecAdd_P2_continue1) + $ => A :MLOAD(ecAdd_P2_y) + $ :EQ, JMPC(ecAdd_P2_is_zero) + __ecAdd_P2_continue1: + + ; 1] Check if P1 is in E(Fp) + ; P1 in E iff (P1.y)² == (P1.x)³ + 3 (mod p) + ; 1.1] Compute LHS and RHS + $ => A :MLOAD(ecAdd_P1_x), CALL(squareFpBN254) + ; B = (P1.x)² + + $ => A :MLOAD(ecAdd_P1_x), CALL(mulFpBN254) + ; C = (P1.x)³ + + %BN254_E_B => A :CALL(addFpBN254) + ; C = (P1.x)³ + 3 + C :MSTORE(ecAdd_P3_x) + + $ => A :MLOAD(ecAdd_P1_y), CALL(squareFpBN254) + ; B = (Py)² + + ; 1.2] Check if LHS == RHS + B => A + $ => B :MLOAD(ecAdd_P3_x) + $ :EQ, JMPNC(ecAdd_P1_is_not_in_E) + + ; 2] check if P2 is in E(Fp) + ; P2 in E iff (P2.y)² == (P2.x)³ + 3 (mod p) + ; 2.1] Compute LHS and RHS + $ => A :MLOAD(ecAdd_P2_x), CALL(squareFpBN254) + ; B = (P2.x)² + + $ => A :MLOAD(ecAdd_P2_x), CALL(mulFpBN254) + ; C = (P2.x)³ + + %BN254_E_B => A :CALL(addFpBN254) + ; C = (P2.x)³ + 3 + C :MSTORE(ecAdd_P3_x) + + $ => A :MLOAD(ecAdd_P2_y), CALL(squareFpBN254) + ; B = (Py)² + + ; 2.2] Check if LHS == RHS + B => A + $ => B :MLOAD(ecAdd_P3_x) + $ :EQ, JMPNC(ecAdd_P2_is_not_in_E) + + ; P1 and P2 are not 0, let's check whether they are different points, the same point or inverses of each other + $ => A :MLOAD(ecAdd_P1_x) + $ => B :MLOAD(ecAdd_P2_x) + + ; Is P1.x == P2.x? + $ :EQ, JMPNC(ecAdd_different) + + $ => A :MLOAD(ecAdd_P1_y) + $ => B :MLOAD(ecAdd_P2_y) + + ; Is P1.y == P2.y? + $ :EQ, JMPNC(ecAdd_P1_and_P2_are_inverted) + + ; P1 == P2 + :JMP(ecAdd_same) + +ecAdd_P1_is_zero: + ; Is P2 = 0? + 0n => B + $ => A :MLOAD(ecAdd_P2_x) + $ :EQ, JMPNC(__ecAdd_P2_continue2) + $ => A :MLOAD(ecAdd_P2_y) + $ :EQ, JMPC(ecAdd_P1_and_P2_are_zero) + __ecAdd_P2_continue2: + + ; P2 in E iff (P2.y)² == (P2.x)³ + 3 (mod p) + ; 1] Compute LHS and RHS + $ => A :MLOAD(ecAdd_P2_x), CALL(squareFpBN254) + ; B = (P2.x)² + + $ => A :MLOAD(ecAdd_P2_x), CALL(mulFpBN254) + ; C = (P2.x)³ + + %BN254_E_B => A :CALL(addFpBN254) + ; C = (P2.x)³ + 3 + C :MSTORE(ecAdd_P3_x) + + $ => A :MLOAD(ecAdd_P2_y), CALL(squareFpBN254) + ; B = (Py)² + + ; 2] Check if LHS == RHS + B => A + $ => B :MLOAD(ecAdd_P3_x) + $ :EQ, JMPNC(ecAdd_P2_is_not_in_E) + + ; P3 = P2 + $ => A :MLOAD(ecAdd_P2_x) + $ => B :MLOAD(ecAdd_P2_y) + A :MSTORE(ecAdd_P3_x) + B :MSTORE(ecAdd_P3_y) + + :JMP(ecAdd_correct) + +ecAdd_P2_is_zero: + ; P1 in E iff (P1.y)² == (P1.x)³ + 3 (mod p) + ; 1] Compute LHS and RHS + $ => A :MLOAD(ecAdd_P1_x), CALL(squareFpBN254) + ; B = (P1.x)² + + $ => A :MLOAD(ecAdd_P1_x), CALL(mulFpBN254) + ; C = (P1.x)³ + + %BN254_E_B => A :CALL(addFpBN254) + ; C = (P1.x)³ + 3 + C :MSTORE(ecAdd_P3_x) + + $ => A :MLOAD(ecAdd_P1_y), CALL(squareFpBN254) + ; B = (Py)² + + ; 2] Check if LHS == RHS + B => A + $ => B :MLOAD(ecAdd_P3_x) + $ :EQ, JMPNC(ecAdd_P1_is_not_in_E) + + ; P3 = P1 + $ => A :MLOAD(ecAdd_P1_x) + $ => B :MLOAD(ecAdd_P1_y) + A :MSTORE(ecAdd_P3_x) + B :MSTORE(ecAdd_P3_y) + + :JMP(ecAdd_correct) + +ecAdd_P1_and_P2_are_zero: + ; P3 = 0 + 0n :MSTORE(ecAdd_P3_x) + 0n :MSTORE(ecAdd_P3_y) + + :JMP(ecAdd_correct) + +ecAdd_P1_and_P2_are_inverted: + ; P3 = 0 + 0n :MSTORE(ecAdd_P3_x) + 0n :MSTORE(ecAdd_P3_y) + + :JMP(ecAdd_correct) + +ecAdd_same: + $ => A :MLOAD(ecAdd_P1_y) + $ => C :MLOAD(ecAdd_P1_y), CALL(addFpBN254) + ; C = 2y + + C => A :CALL(invFpBN254) + ; B = 1 / 2y + B :MSTORE(ecAdd_P1_y_inv) + + B => A,C :CALL(addFpBN254) + C => A + $ => C :MLOAD(ecAdd_P1_y_inv), CALL(addFpBN254) + ; C = 3/2y + + C => A + $ => B :MLOAD(ecAdd_P1_x), CALL(mulFpBN254) + ; C = 3x/2y + + C => A + $ => B :MLOAD(ecAdd_P1_x), CALL(mulFpBN254) + ; C = lambda = 3x²/2y + + C :MSTORE(ecAdd_lambda) + ; C = lambda + + C => A :CALL(squareFpBN254) + ; B = lambda² + + B => A + $ => C :MLOAD(ecAdd_P1_x), CALL(subFpBN254) + ; C = lambda² - x + + C => A + $ => C :MLOAD(ecAdd_P1_x), CALL(subFpBN254) + ; C = lambda² - x - x + + :JMP(ecAdd_common_calculate) + +ecAdd_different: + $ => A :MLOAD(ecAdd_P2_x) + $ => C :MLOAD(ecAdd_P1_x), CALL(subFpBN254) + ; C = P2.x - P1.x + + C => A :CALL(invFpBN254) + ; B = 1 / (P2.x - P1.x) + B :MSTORE(ecAdd_lambda) + + $ => A :MLOAD(ecAdd_P2_y) + $ => C :MLOAD(ecAdd_P1_y), CALL(subFpBN254) + ; C = P2.y - P1.y + + C => A + $ => B :MLOAD(ecAdd_lambda), CALL(mulFpBN254) + ; C = lambda = (P2.y - P1.y) / (P2.x - P1.x) + C :MSTORE(ecAdd_lambda) + + C => A :CALL(squareFpBN254) + ; B = lambda² + + B => A + $ => C :MLOAD(ecAdd_P1_x), CALL(subFpBN254) + ; C = lambda² - P1.x + + C => A + $ => C :MLOAD(ecAdd_P2_x), CALL(subFpBN254) + ; C = lambda² - P1.x - P2.x + +ecAdd_common_calculate: + C :MSTORE(ecAdd_P3_x) + ; P3.x = lambda² - P1.x - P2.x + + $ => A :MLOAD(ecAdd_P1_x), CALL(subFpBN254) + ; C = P1.x - P3.x + + $ => A :MLOAD(ecAdd_lambda) + C => B :CALL(mulFpBN254) + ; C = lambda·(P1.x - P3.x) + + C => A + $ => C :MLOAD(ecAdd_P1_y), CALL(subFpBN254) + ; C = lambda·(P1.x - P3.x) - P1.y + + C :MSTORE(ecAdd_P3_y) + + :JMP(ecAdd_correct) + +; ERRORS +ecAdd_P1x_too_big: + 1 => B :JMP(ecAdd_error) + +ecAdd_P1y_too_big: + 2 => B :JMP(ecAdd_error) + +ecAdd_P2x_too_big: + 3 => B :JMP(ecAdd_error) + +ecAdd_P2y_too_big: + 4 => B :JMP(ecAdd_error) + +ecAdd_P1_is_not_in_E: + 5 => B :JMP(ecAdd_error) + +ecAdd_P2_is_not_in_E: + 6 => B :JMP(ecAdd_error) + +ecAdd_correct: + 0 => B :JMP(ecAdd_end) + +ecAdd_error: + 0 => A + +ecAdd_end: + $ => RR :MLOAD(ecAdd_RR) + :RETURN \ No newline at end of file diff --git a/main/pairings/BN254/ecMul.zkasm b/main/pairings/BN254/ecMul.zkasm new file mode 100644 index 00000000..1fecd4fc --- /dev/null +++ b/main/pairings/BN254/ecMul.zkasm @@ -0,0 +1,159 @@ +;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; POST: The resulting coordinates are in the range [0,BN254_P) because if falls back to FP arithmetic +;; +;; ecMul: +;; in: k, P = (P.x, P.y) ∈ E(Fp), where k ∈ [0,r-1] +;; out: k·P = (Q.x, Q.y) ∈ E(Fp) +;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +; Since the curve is E/Fp: y² = x³ + 3, there is no issue in representing the point at infinity as (0, 0). + +VAR GLOBAL ecMul_k +VAR GLOBAL ecMul_P_x +VAR GLOBAL ecMul_P_y +VAR GLOBAL ecMul_Q_x +VAR GLOBAL ecMul_Q_y + +VAR GLOBAL ecMul_RR + +; ERROR CODES (B) +; 0 - no error +; 1 - P_x is too big +; 2 - P_y is too big +; 3 - P is not in E(Fp) + +ecMul: + RR :MSTORE(ecMul_RR) + + %BN254_P_MINUS_ONE => A + $ => B :MLOAD(ecMul_P_x) + $ :LT, JMPC(ecMul_Px_too_big) + $ => B :MLOAD(ecMul_P_y) + $ :LT, JMPC(ecMul_Py_too_big) + + ; Is P = O? + 0n => B + $ => A :MLOAD(ecMul_P_x) + $ :EQ, JMPNC(__ecMul_P_continue) + $ => A :MLOAD(ecMul_P_y) + $ :EQ, JMPC(ecMul_P_is_zero) + __ecMul_P_continue: + + ; 1] Check if P is in E(Fp) + ; P in E iff (P.y)² == (P.x)³ + 3 (mod p) + ; 1.1] Compute LHS and RHS + $ => A :MLOAD(ecMul_P_x), CALL(squareFpBN254) + ; B = (P.x)² + + $ => A :MLOAD(ecMul_P_x), CALL(mulFpBN254) + ; C = (P.x)³ + + %BN254_E_B => A :CALL(addFpBN254) + ; C = (P.x)³ + 3 + C :MSTORE(ecMul_Q_x) + + $ => A :MLOAD(ecMul_P_y), CALL(squareFpBN254) + ; B = (Py)² + + ; 1.2] Check if LHS == RHS + B => A + $ => B :MLOAD(ecMul_Q_x) + $ :EQ, JMPNC(ecMul_P_is_not_in_E) + + ; Is k ∈ [1,r-1]? + $ => B :MLOAD(ecMul_k), CALL(reduceFrBN254) + A :MSTORE(ecMul_k) + 0n => B + $ :EQ, JMPC(ecMul_k_is_zero) + + 257 => RCX + + $ => A :MLOAD(ecMul_P_x) + $ => C :MLOAD(ecMul_P_y) + A :MSTORE(ecMul_Q_x) + C :MSTORE(ecMul_Q_y) + + :JMP(ecMul_find_MSB_k) + +ecMul_P_is_zero: + ; Q = O + 0n :MSTORE(ecMul_Q_x) + 0n :MSTORE(ecMul_Q_y) + + :JMP(ecMul_correct) + +ecMul_k_is_zero: + ; Q = O + 0n :MSTORE(ecMul_Q_x) + 0n :MSTORE(ecMul_Q_y) + + :JMP(ecMul_correct) + +ecMul_find_MSB_k: + RCX - 1 => RCX + $ => A,B :MLOAD(ecMul_k) + ; E = 2A + $ => E :ADD,MSTORE(ecMul_k), JMPNC(ecMul_find_MSB_k) + + +ecMul_loop: + RCX - 1 => RCX :JMPZ(ecMul_correct) + + ; We always double + $ => A :MLOAD(ecMul_Q_x) + $ => B :MLOAD(ecMul_Q_y) + A :MSTORE(ecAdd_P1_x) + B :MSTORE(ecAdd_P1_y) + A :MSTORE(ecAdd_P2_x) + B :MSTORE(ecAdd_P2_y), CALL(ecAdd) + ; Q = Q + Q + + $ => A :MLOAD(ecAdd_P3_x) + $ => B :MLOAD(ecAdd_P3_y) + A :MSTORE(ecMul_Q_x) + B :MSTORE(ecMul_Q_y) + + ; We check if the MSB b of k is either 1 or 0. If b==1, we should add P to Q. + ; Then, update the value of k. + $ => A,B :MLOAD(ecMul_k) + ; E = 2A + $ => E :ADD, MSTORE(ecMul_k), JMPNC(ecMul_loop) + +ecMul_add: + ; We add + $ => A :MLOAD(ecMul_Q_x) + $ => B :MLOAD(ecMul_Q_y) + $ => C :MLOAD(ecMul_P_x) + $ => D :MLOAD(ecMul_P_y) + A :MSTORE(ecAdd_P1_x) + B :MSTORE(ecAdd_P1_y) + C :MSTORE(ecAdd_P2_x) + D :MSTORE(ecAdd_P2_y), CALL(ecAdd) + ; Q = Q + P + + $ => A :MLOAD(ecAdd_P3_x) + $ => B :MLOAD(ecAdd_P3_y) + A :MSTORE(ecMul_Q_x) + B :MSTORE(ecMul_Q_y), JMP(ecMul_loop) + + +; ERRORS +ecMul_Px_too_big: + 1 => B :JMP(ecMul_error) + +ecMul_Py_too_big: + 2 => B :JMP(ecMul_error) + +ecMul_P_is_not_in_E: + 3 => B :JMP(ecMul_error) + +ecMul_correct: + 0 => B :JMP(ecMul_end) + +ecMul_error: + 0 => A + +ecMul_end: + $ => RR :MLOAD(ecMul_RR) + :RETURN \ No newline at end of file diff --git a/main/pairings/BN254/escalarMulBN254.zkasm b/main/pairings/BN254/escalarMulBN254.zkasm new file mode 100644 index 00000000..c0e0764a --- /dev/null +++ b/main/pairings/BN254/escalarMulBN254.zkasm @@ -0,0 +1,155 @@ +;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; PRE: P ∈ E'(Fp2) +;; POST: The resulting coordinates are in the range [0,BN254_P) because if falls back to addPointBN254 +;; +;; +;; escalarMulBN254: +;; in: k, P = (P.x1 + P.x2·u, P.y1 + P.y2·u) ∈ E'(Fp2), where k ∈ [0,r-1] +;; out: k·P = (Q.x1 + Q.x2·u, Q.y1 + Q.y2·u) ∈ E'(Fp2) +;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +; escalarMulBN254 assumes P belong to E'(Fp2), since it is checked in the pairing. +; However, it must be implemented if escalarMulBN254 wants to be used independently. + +; Since the curve is E'/Fp2: y² = x³ + 3/(9+u), there is no issue in representing the point at infinity as (0, 0). + +VAR GLOBAL escalarMulBN254_k +VAR GLOBAL escalarMulBN254_P_x1 +VAR GLOBAL escalarMulBN254_P_x2 +VAR GLOBAL escalarMulBN254_P_y1 +VAR GLOBAL escalarMulBN254_P_y2 +VAR GLOBAL escalarMulBN254_Q_x1 +VAR GLOBAL escalarMulBN254_Q_x2 +VAR GLOBAL escalarMulBN254_Q_y1 +VAR GLOBAL escalarMulBN254_Q_y2 + +VAR GLOBAL escalarMulBN254_RR + + +escalarMulBN254: + RR :MSTORE(escalarMulBN254_RR) + + ; Is P = O? + 0n => B + $ => A :MLOAD(escalarMulBN254_P_x1) + $ :EQ, JMPNC(__escalarMulBN254_P_continue) + $ => A :MLOAD(escalarMulBN254_P_x2) + $ :EQ, JMPNC(__escalarMulBN254_P_continue) + $ => A :MLOAD(escalarMulBN254_P_y1) + $ :EQ, JMPNC(__escalarMulBN254_P_continue) + $ => A :MLOAD(escalarMulBN254_P_y2) + $ :EQ, JMPC(escalarMulBN254_P_is_zero) + __escalarMulBN254_P_continue: + + ; Is k = 0? + $ => B :MLOAD(escalarMulBN254_k), CALL(reduceFrBN254) + A :MSTORE(escalarMulBN254_k) + 0n => B + $ :EQ, JMPC(escalarMulBN254_k_is_zero) + + 257 => RCX + + $ => A :MLOAD(escalarMulBN254_P_x1) + $ => B :MLOAD(escalarMulBN254_P_x2) + $ => C :MLOAD(escalarMulBN254_P_y1) + $ => D :MLOAD(escalarMulBN254_P_y2) + A :MSTORE(escalarMulBN254_Q_x1) + B :MSTORE(escalarMulBN254_Q_x2) + C :MSTORE(escalarMulBN254_Q_y1) + D :MSTORE(escalarMulBN254_Q_y2) + + :JMP(escalarMulBN254_find_MSB_k) + +escalarMulBN254_P_is_zero: + ; Q = O + 0n :MSTORE(escalarMulBN254_Q_x1) + 0n :MSTORE(escalarMulBN254_Q_x2) + 0n :MSTORE(escalarMulBN254_Q_y1) + 0n :MSTORE(escalarMulBN254_Q_y2) + + :JMP(escalarMulBN254_end) + +escalarMulBN254_k_is_zero: + ; Q = O + 0n :MSTORE(escalarMulBN254_Q_x1) + 0n :MSTORE(escalarMulBN254_Q_x2) + 0n :MSTORE(escalarMulBN254_Q_y1) + 0n :MSTORE(escalarMulBN254_Q_y2) + + :JMP(escalarMulBN254_end) + +escalarMulBN254_find_MSB_k: + RCX - 1 => RCX + $ => A,B :MLOAD(escalarMulBN254_k) + ; E = 2A + $ => E :ADD,MSTORE(escalarMulBN254_k), JMPNC(escalarMulBN254_find_MSB_k) + + +escalarMulBN254_loop: + RCX - 1 => RCX :JMPZ(escalarMulBN254_end) + + ; We always double + $ => A :MLOAD(escalarMulBN254_Q_x1) + $ => B :MLOAD(escalarMulBN254_Q_x2) + $ => C :MLOAD(escalarMulBN254_Q_y1) + $ => D :MLOAD(escalarMulBN254_Q_y2) + A :MSTORE(addPointBN254_P1_x1) + B :MSTORE(addPointBN254_P1_x2) + C :MSTORE(addPointBN254_P1_y1) + D :MSTORE(addPointBN254_P1_y2) + A :MSTORE(addPointBN254_P2_x1) + B :MSTORE(addPointBN254_P2_x2) + C :MSTORE(addPointBN254_P2_y1) + D :MSTORE(addPointBN254_P2_y2), CALL(addPointBN254) + ; Q = Q + Q + + $ => A :MLOAD(addPointBN254_P3_x1) + $ => B :MLOAD(addPointBN254_P3_x2) + $ => C :MLOAD(addPointBN254_P3_y1) + $ => D :MLOAD(addPointBN254_P3_y2) + A :MSTORE(escalarMulBN254_Q_x1) + B :MSTORE(escalarMulBN254_Q_x2) + C :MSTORE(escalarMulBN254_Q_y1) + D :MSTORE(escalarMulBN254_Q_y2) + + ; We check if the MSB b of k is either 1 or 0. If b==1, we should add P to Q. + ; Then, update the value of k. + $ => A,B :MLOAD(escalarMulBN254_k) + ; E = 2A + $ => E :ADD,MSTORE(escalarMulBN254_k), JMPNC(escalarMulBN254_loop) + +escalarMulBN254_add: + ; We add + $ => A :MLOAD(escalarMulBN254_Q_x1) + $ => B :MLOAD(escalarMulBN254_Q_x2) + $ => C :MLOAD(escalarMulBN254_Q_y1) + $ => D :MLOAD(escalarMulBN254_Q_y2) + A :MSTORE(addPointBN254_P1_x1) + B :MSTORE(addPointBN254_P1_x2) + C :MSTORE(addPointBN254_P1_y1) + D :MSTORE(addPointBN254_P1_y2) + + $ => A :MLOAD(escalarMulBN254_P_x1) + $ => B :MLOAD(escalarMulBN254_P_x2) + $ => C :MLOAD(escalarMulBN254_P_y1) + $ => D :MLOAD(escalarMulBN254_P_y2) + A :MSTORE(addPointBN254_P2_x1) + B :MSTORE(addPointBN254_P2_x2) + C :MSTORE(addPointBN254_P2_y1) + D :MSTORE(addPointBN254_P2_y2), CALL(addPointBN254) + ; Q = Q + P + + $ => A :MLOAD(addPointBN254_P3_x1) + $ => B :MLOAD(addPointBN254_P3_x2) + $ => C :MLOAD(addPointBN254_P3_y1) + $ => D :MLOAD(addPointBN254_P3_y2) + A :MSTORE(escalarMulBN254_Q_x1) + B :MSTORE(escalarMulBN254_Q_x2) + C :MSTORE(escalarMulBN254_Q_y1) + D :MSTORE(escalarMulBN254_Q_y2), JMP(escalarMulBN254_loop) + + +escalarMulBN254_end: + $ => RR :MLOAD(escalarMulBN254_RR) + :RETURN \ No newline at end of file diff --git a/main/pairings/BN254/lineDiffPointsBN254.zkasm b/main/pairings/BN254/lineDiffPointsBN254.zkasm new file mode 100644 index 00000000..a0baac1b --- /dev/null +++ b/main/pairings/BN254/lineDiffPointsBN254.zkasm @@ -0,0 +1,83 @@ +;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; PRE: P1,P2 ∈ E'(Fp2) with P1 != P2,-P2 and Q ∈ E(Fp) +;; POST: The result is in the range [0,BN254_P) because if falls back to FP2 arithmetic +;; +;; lineDiffPointsBN254: +;; in: P1 = (P1.x1 + P1.x2·u, P1.y1 + P1.y2·u), P2 = (P2.x1 + P2.x2·u, P2.y1 + P2.y2·u) ∈ E'(Fp2) +;; and Q = (Q.x,Q.y) ∈ E(Fp) +;; out: line_{twist(P1), twist(P2)}(Q) = (P2.x - P1.x)·Q.y·w² + (P1.y - P2.y)·Q.x·w³ + (P1.x·P2.y - P2.x·P1.y)·w⁵ ∈ Fp12 +;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +; The precondition is ensured by the pairing. +; However, it must be implemented if lineDiffPointsBN254 wants to be used independently. + +VAR GLOBAL lineDiffPointsBN254_P1_x1 +VAR GLOBAL lineDiffPointsBN254_P1_x2 +VAR GLOBAL lineDiffPointsBN254_P1_y1 +VAR GLOBAL lineDiffPointsBN254_P1_y2 +VAR GLOBAL lineDiffPointsBN254_P2_x1 +VAR GLOBAL lineDiffPointsBN254_P2_x2 +VAR GLOBAL lineDiffPointsBN254_P2_y1 +VAR GLOBAL lineDiffPointsBN254_P2_y2 +VAR GLOBAL lineDiffPointsBN254_Q_x +VAR GLOBAL lineDiffPointsBN254_Q_y + +VAR GLOBAL lineDiffPointsBN254_P2x_P1y_x +VAR GLOBAL lineDiffPointsBN254_P2x_P1y_y + +VAR GLOBAL lineDiffPointsBN254_l12_x +VAR GLOBAL lineDiffPointsBN254_l12_y +VAR GLOBAL lineDiffPointsBN254_l22_x +VAR GLOBAL lineDiffPointsBN254_l22_y +VAR GLOBAL lineDiffPointsBN254_l23_x +VAR GLOBAL lineDiffPointsBN254_l23_y + +VAR GLOBAL lineDiffPointsBN254_RR + +lineDiffPointsBN254: + RR :MSTORE(lineDiffPointsBN254_RR) + + ; 1] (P2.x - P1.x)·Q.y + $ => A :MLOAD(lineDiffPointsBN254_P2_x1) + $ => B :MLOAD(lineDiffPointsBN254_P2_x2) + $ => C :MLOAD(lineDiffPointsBN254_P1_x1) + $ => D :MLOAD(lineDiffPointsBN254_P1_x2), CALL(subFp2BN254) + $ => A :MLOAD(lineDiffPointsBN254_Q_y) + C => D + E => C :CALL(escalarMulFp2BN254) + E :MSTORE(lineDiffPointsBN254_l12_x) + C :MSTORE(lineDiffPointsBN254_l12_y) + + ; 2] (P1.y - P2.y)·Q.x + $ => A :MLOAD(lineDiffPointsBN254_P1_y1) + $ => B :MLOAD(lineDiffPointsBN254_P1_y2) + $ => C :MLOAD(lineDiffPointsBN254_P2_y1) + $ => D :MLOAD(lineDiffPointsBN254_P2_y2), CALL(subFp2BN254) + $ => A :MLOAD(lineDiffPointsBN254_Q_x) + C => D + E => C :CALL(escalarMulFp2BN254) + E :MSTORE(lineDiffPointsBN254_l22_x) + C :MSTORE(lineDiffPointsBN254_l22_y) + + ; 3] (P1.x·P2.y - P2.x·P1.y) + $ => A :MLOAD(lineDiffPointsBN254_P2_x1) + $ => B :MLOAD(lineDiffPointsBN254_P2_x2) + $ => C :MLOAD(lineDiffPointsBN254_P1_y1) + $ => D :MLOAD(lineDiffPointsBN254_P1_y2), CALL(mulFp2BN254) + E :MSTORE(lineDiffPointsBN254_P2x_P1y_x) + C :MSTORE(lineDiffPointsBN254_P2x_P1y_y) + + $ => A :MLOAD(lineDiffPointsBN254_P1_x1) + $ => B :MLOAD(lineDiffPointsBN254_P1_x2) + $ => C :MLOAD(lineDiffPointsBN254_P2_y1) + $ => D :MLOAD(lineDiffPointsBN254_P2_y2), CALL(mulFp2BN254) + E => A + C => B + $ => C :MLOAD(lineDiffPointsBN254_P2x_P1y_x) + $ => D :MLOAD(lineDiffPointsBN254_P2x_P1y_y), CALL(subFp2BN254) + E :MSTORE(lineDiffPointsBN254_l23_x) + C :MSTORE(lineDiffPointsBN254_l23_y) + + $ => RR :MLOAD(lineDiffPointsBN254_RR) + :RETURN \ No newline at end of file diff --git a/main/pairings/BN254/lineSamePointsBN254.zkasm b/main/pairings/BN254/lineSamePointsBN254.zkasm new file mode 100644 index 00000000..5bdec945 --- /dev/null +++ b/main/pairings/BN254/lineSamePointsBN254.zkasm @@ -0,0 +1,96 @@ +;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; PRE: P ∈ E'(Fp2) and Q ∈ E(Fp) +;; POST: The result is in the range [0,BN254_P) because if falls back to FP2 arithmetic +;; +;; lineSamePointsBN254: +;; in: P = (P.x1 + P.x2·u, P.y1 + P.y2·u) ∈ E'(Fp2) and Q = (Q.x,Q.y) ∈ E(Fp) +;; out: line_{twist(P), twist(P)}(Q) = (3·P.x1³ - 2·P.y1²)·(9 + u) + (2·Q.y·P.y1)·w³ + (-3·Q.x·P.x1²)·w⁴ ∈ Fp12 +;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +; The precondition is ensured by the pairing. +; However, it must be implemented if lineSamePointsBN254 wants to be used independently. + +VAR GLOBAL lineSamePointsBN254_P_x1 +VAR GLOBAL lineSamePointsBN254_P_x2 +VAR GLOBAL lineSamePointsBN254_P_y1 +VAR GLOBAL lineSamePointsBN254_P_y2 +VAR GLOBAL lineSamePointsBN254_Q_x +VAR GLOBAL lineSamePointsBN254_Q_y + +VAR GLOBAL lineSamePointsBN254_P_x1_square +VAR GLOBAL lineSamePointsBN254_P_x2_square +VAR GLOBAL lineSamePointsBN254_P_y1_square +VAR GLOBAL lineSamePointsBN254_P_y2_square + +VAR GLOBAL lineSamePointsBN254_l11_x +VAR GLOBAL lineSamePointsBN254_l11_y +VAR GLOBAL lineSamePointsBN254_l13_x +VAR GLOBAL lineSamePointsBN254_l13_y +VAR GLOBAL lineSamePointsBN254_l22_x +VAR GLOBAL lineSamePointsBN254_l22_y + +VAR GLOBAL lineSamePointsBN254_RR + +lineSamePointsBN254: + RR :MSTORE(lineSamePointsBN254_RR) + + ; 1] (3·P.x1³ - 2·P.y1²)·(9 + u) + $ => A :MLOAD(lineSamePointsBN254_P_y1) + $ => B :MLOAD(lineSamePointsBN254_P_y2), CALL(squareFp2BN254) + C => D + E => C + 2n => A :CALL(escalarMulFp2BN254) + E :MSTORE(lineSamePointsBN254_P_y1_square) + C :MSTORE(lineSamePointsBN254_P_y2_square) + + $ => A :MLOAD(lineSamePointsBN254_P_x1) + $ => B :MLOAD(lineSamePointsBN254_P_x2), CALL(squareFp2BN254) + ; save it for the last step + E :MSTORE(lineSamePointsBN254_P_x1_square) + C :MSTORE(lineSamePointsBN254_P_x2_square) + E => A + C => B + $ => C :MLOAD(lineSamePointsBN254_P_x1) + $ => D :MLOAD(lineSamePointsBN254_P_x2), CALL(mulFp2BN254) + C => D + E => C + 3n => A :CALL(escalarMulFp2BN254) + + E => A + C => B + $ => C :MLOAD(lineSamePointsBN254_P_y1_square) + $ => D :MLOAD(lineSamePointsBN254_P_y2_square), CALL(subFp2BN254) + + E => A + C => B + 9n => C + 1n => D :CALL(mulFp2BN254) + + E :MSTORE(lineSamePointsBN254_l11_x) + C :MSTORE(lineSamePointsBN254_l11_y) + + + ; 2] 2·Q.y·P.y1 + 2n => A + $ => B :MLOAD(lineSamePointsBN254_Q_y), CALL(mulFpBN254) + + C => A + $ => C :MLOAD(lineSamePointsBN254_P_y1) + $ => D :MLOAD(lineSamePointsBN254_P_y2), CALL(escalarMulFp2BN254) + + E :MSTORE(lineSamePointsBN254_l22_x) + C :MSTORE(lineSamePointsBN254_l22_y) + + ; 3] -3·Q.x·P.x1² + %BN254_P - 3n => A ; This clearly assumes that %BN254_P >= 3n + $ => B :MLOAD(lineSamePointsBN254_Q_x), CALL(mulFpBN254) + C => A + $ => C :MLOAD(lineSamePointsBN254_P_x1_square) + $ => D :MLOAD(lineSamePointsBN254_P_x2_square), CALL(escalarMulFp2BN254) + + E :MSTORE(lineSamePointsBN254_l13_x) + C :MSTORE(lineSamePointsBN254_l13_y) + + $ => RR :MLOAD(lineSamePointsBN254_RR) + :RETURN \ No newline at end of file diff --git a/main/pairings/FP12BN254/CYCLOFP12BN254/compressFp12BN254.zkasm b/main/pairings/FP12BN254/CYCLOFP12BN254/compressFp12BN254.zkasm new file mode 100644 index 00000000..4908a396 --- /dev/null +++ b/main/pairings/FP12BN254/CYCLOFP12BN254/compressFp12BN254.zkasm @@ -0,0 +1,49 @@ +;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; +;; compressFp12BN254: +;; in: a = a0 + a2·w + a4·w² + a1·w³ + a3·w⁴ + a5·w⁵ ∈ GΦ6(p²), where ai ∈ Fp2 +;; out: C(a) = [a2,a3,a4,a5] ∈ Fp2⁴ +;; +;; NOTE: If the input does not belong to the cyclotomic subgroup GΦ6(p²), then the compression-decompression +;; technique is not well defined. This means that D(C(a)) != a. +;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +VAR GLOBAL compressFp12BN254_a0_x +VAR GLOBAL compressFp12BN254_a0_y +VAR GLOBAL compressFp12BN254_a2_x +VAR GLOBAL compressFp12BN254_a2_y +VAR GLOBAL compressFp12BN254_a4_x +VAR GLOBAL compressFp12BN254_a4_y +VAR GLOBAL compressFp12BN254_a1_x +VAR GLOBAL compressFp12BN254_a1_y +VAR GLOBAL compressFp12BN254_a3_x +VAR GLOBAL compressFp12BN254_a3_y +VAR GLOBAL compressFp12BN254_a5_x +VAR GLOBAL compressFp12BN254_a5_y +VAR GLOBAL compressFp12BN254_Ca2_x +VAR GLOBAL compressFp12BN254_Ca2_y +VAR GLOBAL compressFp12BN254_Ca3_x +VAR GLOBAL compressFp12BN254_Ca3_y +VAR GLOBAL compressFp12BN254_Ca4_x +VAR GLOBAL compressFp12BN254_Ca4_y +VAR GLOBAL compressFp12BN254_Ca5_x +VAR GLOBAL compressFp12BN254_Ca5_y + +compressFp12BN254: + $ => A :MLOAD(compressFp12BN254_a2_x) + $ => B :MLOAD(compressFp12BN254_a2_y) + A :MSTORE(compressFp12BN254_Ca2_x) + B :MSTORE(compressFp12BN254_Ca2_y) + $ => A :MLOAD(compressFp12BN254_a3_x) + $ => B :MLOAD(compressFp12BN254_a3_y) + A :MSTORE(compressFp12BN254_Ca3_x) + B :MSTORE(compressFp12BN254_Ca3_y) + $ => A :MLOAD(compressFp12BN254_a4_x) + $ => B :MLOAD(compressFp12BN254_a4_y) + A :MSTORE(compressFp12BN254_Ca4_x) + B :MSTORE(compressFp12BN254_Ca4_y) + $ => A :MLOAD(compressFp12BN254_a5_x) + $ => B :MLOAD(compressFp12BN254_a5_y) + A :MSTORE(compressFp12BN254_Ca5_x) + B :MSTORE(compressFp12BN254_Ca5_y) + :RETURN \ No newline at end of file diff --git a/main/pairings/FP12BN254/CYCLOFP12BN254/decompressFp12BN254.zkasm b/main/pairings/FP12BN254/CYCLOFP12BN254/decompressFp12BN254.zkasm new file mode 100644 index 00000000..64cd2665 --- /dev/null +++ b/main/pairings/FP12BN254/CYCLOFP12BN254/decompressFp12BN254.zkasm @@ -0,0 +1,236 @@ +;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; POST: The result is in the range [0,BN254_P) because if falls back to FP2 arithmetic +;; +;; decompressFp12BN254: +;; in: [a2,a3,a4,a5] ∈ Fp2⁴, where ai ∈ Fp2 +;; out: D(a) = a0 + a2·w + a4·w² + a1·w³ + a3·w⁴ + a5·w⁵ ∈ GΦ6(p²), where: +;; - if a2 != 0, then: +;; · a1 = (a5²·(9+u) + 3·a4² - 2·a3)/(4·a2) +;; · a0 = (2·a1² + a2·a5 - 3·a3·a4)(9+u) + 1 +;; - if a2 == 0, then: +;; · a1 = (2·a4·a5)/a3 +;; · a0 = (2·a1² - 3·a3·a4)(9+u) + 1 +;; +;; NOTE: If the input is not of the form C(a), where a ∈ GΦ6(p²), then the compression-decompression +;; technique is not well defined. This means that D(C(a)) != a. +;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +VAR GLOBAL decompressFp12BN254_Ca2_x +VAR GLOBAL decompressFp12BN254_Ca2_y +VAR GLOBAL decompressFp12BN254_Ca3_x +VAR GLOBAL decompressFp12BN254_Ca3_y +VAR GLOBAL decompressFp12BN254_Ca4_x +VAR GLOBAL decompressFp12BN254_Ca4_y +VAR GLOBAL decompressFp12BN254_Ca5_x +VAR GLOBAL decompressFp12BN254_Ca5_y +VAR GLOBAL decompressFp12BN254_a0_x +VAR GLOBAL decompressFp12BN254_a0_y +VAR GLOBAL decompressFp12BN254_a2_x +VAR GLOBAL decompressFp12BN254_a2_y +VAR GLOBAL decompressFp12BN254_a4_x +VAR GLOBAL decompressFp12BN254_a4_y +VAR GLOBAL decompressFp12BN254_a1_x +VAR GLOBAL decompressFp12BN254_a1_y +VAR GLOBAL decompressFp12BN254_a3_x +VAR GLOBAL decompressFp12BN254_a3_y +VAR GLOBAL decompressFp12BN254_a5_x +VAR GLOBAL decompressFp12BN254_a5_y + +VAR GLOBAL decompressFp12BN254_Ca3inv_x +VAR GLOBAL decompressFp12BN254_Ca3inv_y +VAR GLOBAL decompressFp12BN254_twoCa1sq_x +VAR GLOBAL decompressFp12BN254_twoCa1sq_y +VAR GLOBAL decompressFp12BN254_threeCa3Ca4_x +VAR GLOBAL decompressFp12BN254_threeCa3Ca4_y + +VAR GLOBAL decompressFp12BN254_fourCa2inv_x +VAR GLOBAL decompressFp12BN254_fourCa2inv_y +VAR GLOBAL decompressFp12BN254_twoCa1sq2_x +VAR GLOBAL decompressFp12BN254_twoCa1sq2_y +VAR GLOBAL decompressFp12BN254_Ca5sq_x +VAR GLOBAL decompressFp12BN254_Ca5sq_y +VAR GLOBAL decompressFp12BN254_threeCa4sq_x +VAR GLOBAL decompressFp12BN254_threeCa4sq_y +VAR GLOBAL decompressFp12BN254_sum_x +VAR GLOBAL decompressFp12BN254_sum_y + +VAR GLOBAL decompressFp12BN254_RR + +decompressFp12BN254: + RR :MSTORE(decompressFp12BN254_RR) + + ; Move Ca2, Ca3, Ca4, Ca5 to a2, a3, a4, a5 + $ => A :MLOAD(decompressFp12BN254_Ca2_x) + $ => B :MLOAD(decompressFp12BN254_Ca2_y) + A :MSTORE(decompressFp12BN254_a2_x) + B :MSTORE(decompressFp12BN254_a2_y) + $ => A :MLOAD(decompressFp12BN254_Ca3_x) + $ => B :MLOAD(decompressFp12BN254_Ca3_y) + A :MSTORE(decompressFp12BN254_a3_x) + B :MSTORE(decompressFp12BN254_a3_y) + $ => A :MLOAD(decompressFp12BN254_Ca4_x) + $ => B :MLOAD(decompressFp12BN254_Ca4_y) + A :MSTORE(decompressFp12BN254_a4_x) + B :MSTORE(decompressFp12BN254_a4_y) + $ => A :MLOAD(decompressFp12BN254_Ca5_x) + $ => B :MLOAD(decompressFp12BN254_Ca5_y) + A :MSTORE(decompressFp12BN254_a5_x) + B :MSTORE(decompressFp12BN254_a5_y) + + ; Is Ca2 = 0? + 0n => B + $ => A :MLOAD(decompressFp12BN254_Ca2_x) + $ :EQ, JMPNC(__decompressFp12BN254_Ca2_continue) + $ => A :MLOAD(decompressFp12BN254_Ca2_y) + $ :EQ, JMPC(decompressFp12BN254_Ca2_is_zero) + __decompressFp12BN254_Ca2_continue: + + :JMP(decompressFp12BN254_Ca2_is_not_zero) + +decompressFp12BN254_Ca2_is_zero: + ; 1] Compute a1 = (2·a4·a5)/a3 + $ => A :MLOAD(decompressFp12BN254_Ca3_x) + $ => B :MLOAD(decompressFp12BN254_Ca3_y), CALL(invFp2BN254) + C :MSTORE(decompressFp12BN254_Ca3inv_x) + D :MSTORE(decompressFp12BN254_Ca3inv_y) + + 2n => A + $ => C :MLOAD(decompressFp12BN254_Ca4_x) + $ => D :MLOAD(decompressFp12BN254_Ca4_y), CALL(escalarMulFp2BN254) + E => A + C => B + $ => C :MLOAD(decompressFp12BN254_Ca5_x) + $ => D :MLOAD(decompressFp12BN254_Ca5_y), CALL(mulFp2BN254) + E => A + C => B + $ => C :MLOAD(decompressFp12BN254_Ca3inv_x) + $ => D :MLOAD(decompressFp12BN254_Ca3inv_y), CALL(mulFp2BN254) + E :MSTORE(decompressFp12BN254_a1_x) + C :MSTORE(decompressFp12BN254_a1_y) + + ; 2] Compute a0 = (2·a1² - 3·a3·a4)(9+u) + 1 + $ => A :MLOAD(decompressFp12BN254_a1_x) + $ => B :MLOAD(decompressFp12BN254_a1_y), CALL(squareFp2BN254) + 2n => A + C => D + E => C :CALL(escalarMulFp2BN254) + E :MSTORE(decompressFp12BN254_twoCa1sq_x) + C :MSTORE(decompressFp12BN254_twoCa1sq_y) + + 3n => A + $ => C :MLOAD(decompressFp12BN254_Ca3_x) + $ => D :MLOAD(decompressFp12BN254_Ca3_y), CALL(escalarMulFp2BN254) + E => A + C => B + $ => C :MLOAD(decompressFp12BN254_Ca4_x) + $ => D :MLOAD(decompressFp12BN254_Ca4_y), CALL(mulFp2BN254) + E :MSTORE(decompressFp12BN254_threeCa3Ca4_x) + C :MSTORE(decompressFp12BN254_threeCa3Ca4_y) + + $ => A :MLOAD(decompressFp12BN254_twoCa1sq_x) + $ => B :MLOAD(decompressFp12BN254_twoCa1sq_y) + C => D + E => C :CALL(subFp2BN254) + E => A + C => B + 9n => C + 1n => D :CALL(mulFp2BN254) + C :MSTORE(decompressFp12BN254_a0_y) + E => A + 1n => C :CALL(addFpBN254) + C :MSTORE(decompressFp12BN254_a0_x) + + :JMP(decompressFp12BN254_end) + + +decompressFp12BN254_Ca2_is_not_zero: + ; 1] Compute a1 = (a5²·(9+u) + 3·a4² - 2·a3)/(4·a2) + 4n => A + $ => C :MLOAD(decompressFp12BN254_Ca2_x) + $ => D :MLOAD(decompressFp12BN254_Ca2_y), CALL(escalarMulFp2BN254) + E => A + C => B :CALL(invFp2BN254) + C :MSTORE(decompressFp12BN254_fourCa2inv_x) + D :MSTORE(decompressFp12BN254_fourCa2inv_y) + + $ => A :MLOAD(decompressFp12BN254_Ca5_x) + $ => B :MLOAD(decompressFp12BN254_Ca5_y), CALL(squareFp2BN254) + E => A + C => B + 9n => C + 1n => D :CALL(mulFp2BN254) + E :MSTORE(decompressFp12BN254_Ca5sq_x) + C :MSTORE(decompressFp12BN254_Ca5sq_y) + + $ => A :MLOAD(decompressFp12BN254_Ca4_x) + $ => B :MLOAD(decompressFp12BN254_Ca4_y), CALL(squareFp2BN254) + 3n => A + C => D + E => C :CALL(escalarMulFp2BN254) + E :MSTORE(decompressFp12BN254_threeCa4sq_x) + C :MSTORE(decompressFp12BN254_threeCa4sq_y) + + 2n => A + $ => C :MLOAD(decompressFp12BN254_Ca3_x) + $ => D :MLOAD(decompressFp12BN254_Ca3_y), CALL(escalarMulFp2BN254) + $ => A :MLOAD(decompressFp12BN254_threeCa4sq_x) + $ => B :MLOAD(decompressFp12BN254_threeCa4sq_y) + C => D + E => C :CALL(subFp2BN254) + E => A + C => B + $ => C :MLOAD(decompressFp12BN254_Ca5sq_x) + $ => D :MLOAD(decompressFp12BN254_Ca5sq_y), CALL(addFp2BN254) + E => A + C => B + $ => C :MLOAD(decompressFp12BN254_fourCa2inv_x) + $ => D :MLOAD(decompressFp12BN254_fourCa2inv_y), CALL(mulFp2BN254) + E :MSTORE(decompressFp12BN254_a1_x) + C :MSTORE(decompressFp12BN254_a1_y) + + ; 2] Compute a0 = (2·a1² + a2·a5 - 3·a3·a4)(9+u) + 1 + $ => A :MLOAD(decompressFp12BN254_a1_x) + $ => B :MLOAD(decompressFp12BN254_a1_y), CALL(squareFp2BN254) + 2n => A + C => D + E => C :CALL(escalarMulFp2BN254) + E :MSTORE(decompressFp12BN254_twoCa1sq2_x) + C :MSTORE(decompressFp12BN254_twoCa1sq2_y) + + $ => A :MLOAD(decompressFp12BN254_Ca2_x) + $ => B :MLOAD(decompressFp12BN254_Ca2_y) + $ => C :MLOAD(decompressFp12BN254_Ca5_x) + $ => D :MLOAD(decompressFp12BN254_Ca5_y), CALL(mulFp2BN254) + E => A + C => B + $ => C :MLOAD(decompressFp12BN254_twoCa1sq2_x) + $ => D :MLOAD(decompressFp12BN254_twoCa1sq2_y), CALL(addFp2BN254) + + E :MSTORE(decompressFp12BN254_sum_x) + C :MSTORE(decompressFp12BN254_sum_y) + + $ => A :MLOAD(decompressFp12BN254_Ca3_x) + $ => B :MLOAD(decompressFp12BN254_Ca3_y) + $ => C :MLOAD(decompressFp12BN254_Ca4_x) + $ => D :MLOAD(decompressFp12BN254_Ca4_y), CALL(mulFp2BN254) + 3n => A + C => D + E => C :CALL(escalarMulFp2BN254) + $ => A :MLOAD(decompressFp12BN254_sum_x) + $ => B :MLOAD(decompressFp12BN254_sum_y) + C => D + E => C :CALL(subFp2BN254) + E => A + C => B + 9n => C + 1n => D :CALL(mulFp2BN254) + C :MSTORE(decompressFp12BN254_a0_y) + E => A + 1n => C :CALL(addFpBN254) + C :MSTORE(decompressFp12BN254_a0_x) + + :JMP(decompressFp12BN254_end) + +decompressFp12BN254_end: + $ => RR :MLOAD(decompressFp12BN254_RR) + :RETURN \ No newline at end of file diff --git a/main/pairings/FP12BN254/CYCLOFP12BN254/expByXCompCycloFp12BN254.zkasm b/main/pairings/FP12BN254/CYCLOFP12BN254/expByXCompCycloFp12BN254.zkasm new file mode 100644 index 00000000..4cfad725 --- /dev/null +++ b/main/pairings/FP12BN254/CYCLOFP12BN254/expByXCompCycloFp12BN254.zkasm @@ -0,0 +1,444 @@ +;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; POST: The result is in the range [0,BN254_P) because if falls back to FP12 arithmetic +;; +;; expByXCompCycloFp12BN254: +;; in: x, a = a0 + a2·w + a4·w² + a1·w³ + a3·w⁴ + a5·w⁵ ∈ GΦ6(p²), where x = 4965661367192848881 and ai ∈ Fp2 +;; out: a^x = c0 + c2·w + c4·w² + c1·w³ + c3·w⁴ + c5·w⁵ ∈ ∈ GΦ6(p²) +;; +;; NOTE: The output is not guaranteed to be in GΦ6(p²), if the input isn't. +;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +VAR GLOBAL expByXCompCycloFp12BN254_a0_x +VAR GLOBAL expByXCompCycloFp12BN254_a0_y +VAR GLOBAL expByXCompCycloFp12BN254_a2_x +VAR GLOBAL expByXCompCycloFp12BN254_a2_y +VAR GLOBAL expByXCompCycloFp12BN254_a4_x +VAR GLOBAL expByXCompCycloFp12BN254_a4_y +VAR GLOBAL expByXCompCycloFp12BN254_a1_x +VAR GLOBAL expByXCompCycloFp12BN254_a1_y +VAR GLOBAL expByXCompCycloFp12BN254_a3_x +VAR GLOBAL expByXCompCycloFp12BN254_a3_y +VAR GLOBAL expByXCompCycloFp12BN254_a5_x +VAR GLOBAL expByXCompCycloFp12BN254_a5_y +VAR GLOBAL expByXCompCycloFp12BN254_c0_x +VAR GLOBAL expByXCompCycloFp12BN254_c0_y +VAR GLOBAL expByXCompCycloFp12BN254_c2_x +VAR GLOBAL expByXCompCycloFp12BN254_c2_y +VAR GLOBAL expByXCompCycloFp12BN254_c4_x +VAR GLOBAL expByXCompCycloFp12BN254_c4_y +VAR GLOBAL expByXCompCycloFp12BN254_c1_x +VAR GLOBAL expByXCompCycloFp12BN254_c1_y +VAR GLOBAL expByXCompCycloFp12BN254_c3_x +VAR GLOBAL expByXCompCycloFp12BN254_c3_y +VAR GLOBAL expByXCompCycloFp12BN254_c5_x +VAR GLOBAL expByXCompCycloFp12BN254_c5_y + +VAR GLOBAL expByXCompCycloFp12BN254_RR + +expByXCompCycloFp12BN254: + RR :MSTORE(expByXCompCycloFp12BN254_RR) + + ; Is a = 0? + 0n => B + $ => A :MLOAD(expByXCompCycloFp12BN254_a0_x) + $ :EQ, JMPNC(__expByXCompCycloFp12BN254_a_continue1) + $ => A :MLOAD(expByXCompCycloFp12BN254_a0_y) + $ :EQ, JMPNC(__expByXCompCycloFp12BN254_a_continue1) + $ => A :MLOAD(expByXCompCycloFp12BN254_a2_x) + $ :EQ, JMPNC(__expByXCompCycloFp12BN254_a_continue1) + $ => A :MLOAD(expByXCompCycloFp12BN254_a2_y) + $ :EQ, JMPNC(__expByXCompCycloFp12BN254_a_continue1) + $ => A :MLOAD(expByXCompCycloFp12BN254_a4_x) + $ :EQ, JMPNC(__expByXCompCycloFp12BN254_a_continue1) + $ => A :MLOAD(expByXCompCycloFp12BN254_a4_y) + $ :EQ, JMPNC(__expByXCompCycloFp12BN254_a_continue1) + $ => A :MLOAD(expByXCompCycloFp12BN254_a1_x) + $ :EQ, JMPNC(__expByXCompCycloFp12BN254_a_continue1) + $ => A :MLOAD(expByXCompCycloFp12BN254_a1_y) + $ :EQ, JMPNC(__expByXCompCycloFp12BN254_a_continue1) + $ => A :MLOAD(expByXCompCycloFp12BN254_a3_x) + $ :EQ, JMPNC(__expByXCompCycloFp12BN254_a_continue1) + $ => A :MLOAD(expByXCompCycloFp12BN254_a3_y) + $ :EQ, JMPNC(__expByXCompCycloFp12BN254_a_continue1) + $ => A :MLOAD(expByXCompCycloFp12BN254_a5_x) + $ :EQ, JMPNC(__expByXCompCycloFp12BN254_a_continue1) + $ => A :MLOAD(expByXCompCycloFp12BN254_a5_y) + $ :EQ, JMPC(expByXCompCycloFp12BN254_a_is_zero) + __expByXCompCycloFp12BN254_a_continue1: + + ; Is a = 1? + 1n => B + $ => A :MLOAD(expByXCompCycloFp12BN254_a0_x) + $ :EQ, JMPNC(__expByXCompCycloFp12BN254_a_continue2) + 0n => B + $ => A :MLOAD(expByXCompCycloFp12BN254_a0_y) + $ :EQ, JMPNC(__expByXCompCycloFp12BN254_a_continue2) + $ => A :MLOAD(expByXCompCycloFp12BN254_a2_x) + $ :EQ, JMPNC(__expByXCompCycloFp12BN254_a_continue2) + $ => A :MLOAD(expByXCompCycloFp12BN254_a2_y) + $ :EQ, JMPNC(__expByXCompCycloFp12BN254_a_continue2) + $ => A :MLOAD(expByXCompCycloFp12BN254_a4_x) + $ :EQ, JMPNC(__expByXCompCycloFp12BN254_a_continue2) + $ => A :MLOAD(expByXCompCycloFp12BN254_a4_y) + $ :EQ, JMPNC(__expByXCompCycloFp12BN254_a_continue2) + $ => A :MLOAD(expByXCompCycloFp12BN254_a1_x) + $ :EQ, JMPNC(__expByXCompCycloFp12BN254_a_continue2) + $ => A :MLOAD(expByXCompCycloFp12BN254_a1_y) + $ :EQ, JMPNC(__expByXCompCycloFp12BN254_a_continue2) + $ => A :MLOAD(expByXCompCycloFp12BN254_a3_x) + $ :EQ, JMPNC(__expByXCompCycloFp12BN254_a_continue2) + $ => A :MLOAD(expByXCompCycloFp12BN254_a3_y) + $ :EQ, JMPNC(__expByXCompCycloFp12BN254_a_continue2) + $ => A :MLOAD(expByXCompCycloFp12BN254_a5_x) + $ :EQ, JMPNC(__expByXCompCycloFp12BN254_a_continue2) + $ => A :MLOAD(expByXCompCycloFp12BN254_a5_y) + $ :EQ, JMPC(expByXCompCycloFp12BN254_a_is_one) + __expByXCompCycloFp12BN254_a_continue2: + + 59 => RCX + + ; We manually compute the first iterations to avoid branching: 10001 + + ; 1] First bit is 1 and second bit is 0, so set c = a, + ; compress the input and compute the compressed square C(a²) + $ => A :MLOAD(expByXCompCycloFp12BN254_a0_x) + $ => B :MLOAD(expByXCompCycloFp12BN254_a0_y) + A :MSTORE(expByXCompCycloFp12BN254_c0_x) + B :MSTORE(expByXCompCycloFp12BN254_c0_y) + A :MSTORE(compressFp12BN254_a0_x) + B :MSTORE(compressFp12BN254_a0_y) + $ => A :MLOAD(expByXCompCycloFp12BN254_a2_x) + $ => B :MLOAD(expByXCompCycloFp12BN254_a2_y) + A :MSTORE(expByXCompCycloFp12BN254_c2_x) + B :MSTORE(expByXCompCycloFp12BN254_c2_y) + A :MSTORE(compressFp12BN254_a2_x) + B :MSTORE(compressFp12BN254_a2_y) + $ => A :MLOAD(expByXCompCycloFp12BN254_a4_x) + $ => B :MLOAD(expByXCompCycloFp12BN254_a4_y) + A :MSTORE(expByXCompCycloFp12BN254_c4_x) + B :MSTORE(expByXCompCycloFp12BN254_c4_y) + A :MSTORE(compressFp12BN254_a4_x) + B :MSTORE(compressFp12BN254_a4_y) + $ => A :MLOAD(expByXCompCycloFp12BN254_a1_x) + $ => B :MLOAD(expByXCompCycloFp12BN254_a1_y) + A :MSTORE(expByXCompCycloFp12BN254_c1_x) + B :MSTORE(expByXCompCycloFp12BN254_c1_y) + A :MSTORE(compressFp12BN254_a1_x) + B :MSTORE(compressFp12BN254_a1_y) + $ => A :MLOAD(expByXCompCycloFp12BN254_a3_x) + $ => B :MLOAD(expByXCompCycloFp12BN254_a3_y) + A :MSTORE(expByXCompCycloFp12BN254_c3_x) + B :MSTORE(expByXCompCycloFp12BN254_c3_y) + A :MSTORE(compressFp12BN254_a3_x) + B :MSTORE(compressFp12BN254_a3_y) + $ => A :MLOAD(expByXCompCycloFp12BN254_a5_x) + $ => B :MLOAD(expByXCompCycloFp12BN254_a5_y) + A :MSTORE(expByXCompCycloFp12BN254_c5_x) + B :MSTORE(expByXCompCycloFp12BN254_c5_y) + A :MSTORE(compressFp12BN254_a5_x) + B :MSTORE(compressFp12BN254_a5_y), CALL(compressFp12BN254) + + $ => A :MLOAD(compressFp12BN254_Ca2_x) + $ => B :MLOAD(compressFp12BN254_Ca2_y) + A :MSTORE(squareCompCycloFp12BN254_Ca2_x) + B :MSTORE(squareCompCycloFp12BN254_Ca2_y) + $ => A :MLOAD(compressFp12BN254_Ca3_x) + $ => B :MLOAD(compressFp12BN254_Ca3_y) + A :MSTORE(squareCompCycloFp12BN254_Ca3_x) + B :MSTORE(squareCompCycloFp12BN254_Ca3_y) + $ => A :MLOAD(compressFp12BN254_Ca4_x) + $ => B :MLOAD(compressFp12BN254_Ca4_y) + A :MSTORE(squareCompCycloFp12BN254_Ca4_x) + B :MSTORE(squareCompCycloFp12BN254_Ca4_y) + $ => A :MLOAD(compressFp12BN254_Ca5_x) + $ => B :MLOAD(compressFp12BN254_Ca5_y) + A :MSTORE(squareCompCycloFp12BN254_Ca5_x) + B :MSTORE(squareCompCycloFp12BN254_Ca5_y), CALL(squareCompCycloFp12BN254) + + ; 2] Third bit is 0, so compute C(c⁴) + $ => A :MLOAD(squareCompCycloFp12BN254_Cb2_x) + $ => B :MLOAD(squareCompCycloFp12BN254_Cb2_y) + A :MSTORE(squareCompCycloFp12BN254_Ca2_x) + B :MSTORE(squareCompCycloFp12BN254_Ca2_y) + $ => A :MLOAD(squareCompCycloFp12BN254_Cb3_x) + $ => B :MLOAD(squareCompCycloFp12BN254_Cb3_y) + A :MSTORE(squareCompCycloFp12BN254_Ca3_x) + B :MSTORE(squareCompCycloFp12BN254_Ca3_y) + $ => A :MLOAD(squareCompCycloFp12BN254_Cb4_x) + $ => B :MLOAD(squareCompCycloFp12BN254_Cb4_y) + A :MSTORE(squareCompCycloFp12BN254_Ca4_x) + B :MSTORE(squareCompCycloFp12BN254_Ca4_y) + $ => A :MLOAD(squareCompCycloFp12BN254_Cb5_x) + $ => B :MLOAD(squareCompCycloFp12BN254_Cb5_y) + A :MSTORE(squareCompCycloFp12BN254_Ca5_x) + B :MSTORE(squareCompCycloFp12BN254_Ca5_y), CALL(squareCompCycloFp12BN254) + + ; 3] Fourth bit is 0, so compute C(c⁸) + $ => A :MLOAD(squareCompCycloFp12BN254_Cb2_x) + $ => B :MLOAD(squareCompCycloFp12BN254_Cb2_y) + A :MSTORE(squareCompCycloFp12BN254_Ca2_x) + B :MSTORE(squareCompCycloFp12BN254_Ca2_y) + $ => A :MLOAD(squareCompCycloFp12BN254_Cb3_x) + $ => B :MLOAD(squareCompCycloFp12BN254_Cb3_y) + A :MSTORE(squareCompCycloFp12BN254_Ca3_x) + B :MSTORE(squareCompCycloFp12BN254_Ca3_y) + $ => A :MLOAD(squareCompCycloFp12BN254_Cb4_x) + $ => B :MLOAD(squareCompCycloFp12BN254_Cb4_y) + A :MSTORE(squareCompCycloFp12BN254_Ca4_x) + B :MSTORE(squareCompCycloFp12BN254_Ca4_y) + $ => A :MLOAD(squareCompCycloFp12BN254_Cb5_x) + $ => B :MLOAD(squareCompCycloFp12BN254_Cb5_y) + A :MSTORE(squareCompCycloFp12BN254_Ca5_x) + B :MSTORE(squareCompCycloFp12BN254_Ca5_y), CALL(squareCompCycloFp12BN254) + + ; 4] Fifth bit is 1, so compute C(c¹⁶), decompress to obtain c¹⁶ and multiply by a + $ => A :MLOAD(squareCompCycloFp12BN254_Cb2_x) + $ => B :MLOAD(squareCompCycloFp12BN254_Cb2_y) + A :MSTORE(squareCompCycloFp12BN254_Ca2_x) + B :MSTORE(squareCompCycloFp12BN254_Ca2_y) + $ => A :MLOAD(squareCompCycloFp12BN254_Cb3_x) + $ => B :MLOAD(squareCompCycloFp12BN254_Cb3_y) + A :MSTORE(squareCompCycloFp12BN254_Ca3_x) + B :MSTORE(squareCompCycloFp12BN254_Ca3_y) + $ => A :MLOAD(squareCompCycloFp12BN254_Cb4_x) + $ => B :MLOAD(squareCompCycloFp12BN254_Cb4_y) + A :MSTORE(squareCompCycloFp12BN254_Ca4_x) + B :MSTORE(squareCompCycloFp12BN254_Ca4_y) + $ => A :MLOAD(squareCompCycloFp12BN254_Cb5_x) + $ => B :MLOAD(squareCompCycloFp12BN254_Cb5_y) + A :MSTORE(squareCompCycloFp12BN254_Ca5_x) + B :MSTORE(squareCompCycloFp12BN254_Ca5_y), CALL(squareCompCycloFp12BN254) + + $ => A :MLOAD(squareCompCycloFp12BN254_Cb2_x) + $ => B :MLOAD(squareCompCycloFp12BN254_Cb2_y) + A :MSTORE(decompressFp12BN254_Ca2_x) + B :MSTORE(decompressFp12BN254_Ca2_y) + $ => A :MLOAD(squareCompCycloFp12BN254_Cb3_x) + $ => B :MLOAD(squareCompCycloFp12BN254_Cb3_y) + A :MSTORE(decompressFp12BN254_Ca3_x) + B :MSTORE(decompressFp12BN254_Ca3_y) + $ => A :MLOAD(squareCompCycloFp12BN254_Cb4_x) + $ => B :MLOAD(squareCompCycloFp12BN254_Cb4_y) + A :MSTORE(decompressFp12BN254_Ca4_x) + B :MSTORE(decompressFp12BN254_Ca4_y) + $ => A :MLOAD(squareCompCycloFp12BN254_Cb5_x) + $ => B :MLOAD(squareCompCycloFp12BN254_Cb5_y) + A :MSTORE(decompressFp12BN254_Ca5_x) + B :MSTORE(decompressFp12BN254_Ca5_y), CALL(decompressFp12BN254) + + $ => A :MLOAD(expByXCompCycloFp12BN254_c0_x) + $ => B :MLOAD(expByXCompCycloFp12BN254_c0_y) + A :MSTORE(mulFp12BN254_a11_x) + B :MSTORE(mulFp12BN254_a11_y) + $ => A :MLOAD(expByXCompCycloFp12BN254_c2_x) + $ => B :MLOAD(expByXCompCycloFp12BN254_c2_y) + A :MSTORE(mulFp12BN254_a21_x) + B :MSTORE(mulFp12BN254_a21_y) + $ => A :MLOAD(expByXCompCycloFp12BN254_c4_x) + $ => B :MLOAD(expByXCompCycloFp12BN254_c4_y) + A :MSTORE(mulFp12BN254_a12_x) + B :MSTORE(mulFp12BN254_a12_y) + $ => A :MLOAD(expByXCompCycloFp12BN254_c1_x) + $ => B :MLOAD(expByXCompCycloFp12BN254_c1_y) + A :MSTORE(mulFp12BN254_a22_x) + B :MSTORE(mulFp12BN254_a22_y) + $ => A :MLOAD(expByXCompCycloFp12BN254_c3_x) + $ => B :MLOAD(expByXCompCycloFp12BN254_a3_y) + A :MSTORE(mulFp12BN254_a13_x) + B :MSTORE(mulFp12BN254_a13_y) + $ => A :MLOAD(expByXCompCycloFp12BN254_c5_x) + $ => B :MLOAD(expByXCompCycloFp12BN254_c5_y) + A :MSTORE(mulFp12BN254_a23_x) + B :MSTORE(mulFp12BN254_a23_y) + $ => A :MLOAD(decompressFp12BN254_a0_x) + $ => B :MLOAD(decompressFp12BN254_a0_y) + A :MSTORE(mulFp12BN254_b11_x) + B :MSTORE(mulFp12BN254_b11_y) + $ => A :MLOAD(decompressFp12BN254_a2_x) + $ => B :MLOAD(decompressFp12BN254_a2_y) + A :MSTORE(mulFp12BN254_b21_x) + B :MSTORE(mulFp12BN254_b21_y) + $ => A :MLOAD(decompressFp12BN254_a4_x) + $ => B :MLOAD(decompressFp12BN254_a4_y) + A :MSTORE(mulFp12BN254_b12_x) + B :MSTORE(mulFp12BN254_b12_y) + $ => A :MLOAD(decompressFp12BN254_a1_x) + $ => B :MLOAD(decompressFp12BN254_a1_y) + A :MSTORE(mulFp12BN254_b22_x) + B :MSTORE(mulFp12BN254_b22_y) + $ => A :MLOAD(decompressFp12BN254_a3_x) + $ => B :MLOAD(decompressFp12BN254_a3_y) + A :MSTORE(mulFp12BN254_b13_x) + B :MSTORE(mulFp12BN254_b13_y) + $ => A :MLOAD(decompressFp12BN254_a5_x) + $ => B :MLOAD(decompressFp12BN254_a5_y) + A :MSTORE(mulFp12BN254_b23_x) + B :MSTORE(mulFp12BN254_b23_y), CALL(mulFp12BN254) + + :JMP(expByXCompCycloFp12BN254_loop) + +expByXCompCycloFp12BN254_a_is_zero: + ; c = 0 + 0n :MSTORE(expByXCompCycloFp12BN254_c0_x) + 0n :MSTORE(expByXCompCycloFp12BN254_c0_y) + 0n :MSTORE(expByXCompCycloFp12BN254_c2_x) + 0n :MSTORE(expByXCompCycloFp12BN254_c2_y) + 0n :MSTORE(expByXCompCycloFp12BN254_c4_x) + 0n :MSTORE(expByXCompCycloFp12BN254_c4_y) + 0n :MSTORE(expByXCompCycloFp12BN254_c1_x) + 0n :MSTORE(expByXCompCycloFp12BN254_c1_y) + 0n :MSTORE(expByXCompCycloFp12BN254_c3_x) + 0n :MSTORE(expByXCompCycloFp12BN254_c3_y) + 0n :MSTORE(expByXCompCycloFp12BN254_c5_x) + 0n :MSTORE(expByXCompCycloFp12BN254_c5_y) + + :JMP(expByXCompCycloFp12BN254_end) + +expByXCompCycloFp12BN254_a_is_one: + ; c = 1 + 1n :MSTORE(expByXCompCycloFp12BN254_c0_x) + 0n :MSTORE(expByXCompCycloFp12BN254_c0_y) + 0n :MSTORE(expByXCompCycloFp12BN254_c2_x) + 0n :MSTORE(expByXCompCycloFp12BN254_c2_y) + 0n :MSTORE(expByXCompCycloFp12BN254_c4_x) + 0n :MSTORE(expByXCompCycloFp12BN254_c4_y) + 0n :MSTORE(expByXCompCycloFp12BN254_c1_x) + 0n :MSTORE(expByXCompCycloFp12BN254_c1_y) + 0n :MSTORE(expByXCompCycloFp12BN254_c3_x) + 0n :MSTORE(expByXCompCycloFp12BN254_c3_y) + 0n :MSTORE(expByXCompCycloFp12BN254_c5_x) + 0n :MSTORE(expByXCompCycloFp12BN254_c5_y) + + :JMP(expByXCompCycloFp12BN254_end) + +expByXCompCycloFp12BN254_loop: + RCX - 1 => RCX :JMPZ(expByXCompCycloFp12BN254_last) + + ; We always square (in compressed form): C(c²) + ; We square C(c²) and store the result + $ => A :MLOAD(squareCompCycloFp12BN254_Cb2_x) + $ => B :MLOAD(squareCompCycloFp12BN254_Cb2_y) + A :MSTORE(squareCompCycloFp12BN254_Ca2_x) + B :MSTORE(squareCompCycloFp12BN254_Ca2_y) + $ => A :MLOAD(squareCompCycloFp12BN254_Cb3_x) + $ => B :MLOAD(squareCompCycloFp12BN254_Cb3_y) + A :MSTORE(squareCompCycloFp12BN254_Ca3_x) + B :MSTORE(squareCompCycloFp12BN254_Ca3_y) + $ => A :MLOAD(squareCompCycloFp12BN254_Cb4_x) + $ => B :MLOAD(squareCompCycloFp12BN254_Cb4_y) + A :MSTORE(squareCompCycloFp12BN254_Ca4_x) + B :MSTORE(squareCompCycloFp12BN254_Ca4_y) + $ => A :MLOAD(squareCompCycloFp12BN254_Cb5_x) + $ => B :MLOAD(squareCompCycloFp12BN254_Cb5_y) + A :MSTORE(squareCompCycloFp12BN254_Ca5_x) + B :MSTORE(squareCompCycloFp12BN254_Ca5_y), CALL(squareCompCycloFp12BN254) + + ; We check if the MSB b of x is either 1 or 0 + RCX-1 => RR + :CALL(@xBinDecompBN254 + RR) + + ; if bit = 0, then repeat + B :JMPZ(expByXCompCycloFp12BN254_loop) + + ; else, multiply by the last result + +expByXCompCycloFp12BN254_multiply: + $ => A :MLOAD(squareCompCycloFp12BN254_Cb2_x) + $ => B :MLOAD(squareCompCycloFp12BN254_Cb2_y) + A :MSTORE(decompressFp12BN254_Ca2_x) + B :MSTORE(decompressFp12BN254_Ca2_y) + $ => A :MLOAD(squareCompCycloFp12BN254_Cb3_x) + $ => B :MLOAD(squareCompCycloFp12BN254_Cb3_y) + A :MSTORE(decompressFp12BN254_Ca3_x) + B :MSTORE(decompressFp12BN254_Ca3_y) + $ => A :MLOAD(squareCompCycloFp12BN254_Cb4_x) + $ => B :MLOAD(squareCompCycloFp12BN254_Cb4_y) + A :MSTORE(decompressFp12BN254_Ca4_x) + B :MSTORE(decompressFp12BN254_Ca4_y) + $ => A :MLOAD(squareCompCycloFp12BN254_Cb5_x) + $ => B :MLOAD(squareCompCycloFp12BN254_Cb5_y) + A :MSTORE(decompressFp12BN254_Ca5_x) + B :MSTORE(decompressFp12BN254_Ca5_y), CALL(decompressFp12BN254) + + $ => A :MLOAD(mulFp12BN254_c11_x) + $ => B :MLOAD(mulFp12BN254_c11_y) + A :MSTORE(mulFp12BN254_a11_x) + B :MSTORE(mulFp12BN254_a11_y) + $ => A :MLOAD(mulFp12BN254_c12_x) + $ => B :MLOAD(mulFp12BN254_c12_y) + A :MSTORE(mulFp12BN254_a12_x) + B :MSTORE(mulFp12BN254_a12_y) + $ => A :MLOAD(mulFp12BN254_c13_x) + $ => B :MLOAD(mulFp12BN254_c13_y) + A :MSTORE(mulFp12BN254_a13_x) + B :MSTORE(mulFp12BN254_a13_y) + $ => A :MLOAD(mulFp12BN254_c21_x) + $ => B :MLOAD(mulFp12BN254_c21_y) + A :MSTORE(mulFp12BN254_a21_x) + B :MSTORE(mulFp12BN254_a21_y) + $ => A :MLOAD(mulFp12BN254_c22_x) + $ => B :MLOAD(mulFp12BN254_c22_y) + A :MSTORE(mulFp12BN254_a22_x) + B :MSTORE(mulFp12BN254_a22_y) + $ => A :MLOAD(mulFp12BN254_c23_x) + $ => B :MLOAD(mulFp12BN254_c23_y) + A :MSTORE(mulFp12BN254_a23_x) + B :MSTORE(mulFp12BN254_a23_y) + $ => A :MLOAD(decompressFp12BN254_a0_x) + $ => B :MLOAD(decompressFp12BN254_a0_y) + A :MSTORE(mulFp12BN254_b11_x) + B :MSTORE(mulFp12BN254_b11_y) + $ => A :MLOAD(decompressFp12BN254_a2_x) + $ => B :MLOAD(decompressFp12BN254_a2_y) + A :MSTORE(mulFp12BN254_b21_x) + B :MSTORE(mulFp12BN254_b21_y) + $ => A :MLOAD(decompressFp12BN254_a4_x) + $ => B :MLOAD(decompressFp12BN254_a4_y) + A :MSTORE(mulFp12BN254_b12_x) + B :MSTORE(mulFp12BN254_b12_y) + $ => A :MLOAD(decompressFp12BN254_a1_x) + $ => B :MLOAD(decompressFp12BN254_a1_y) + A :MSTORE(mulFp12BN254_b22_x) + B :MSTORE(mulFp12BN254_b22_y) + $ => A :MLOAD(decompressFp12BN254_a3_x) + $ => B :MLOAD(decompressFp12BN254_a3_y) + A :MSTORE(mulFp12BN254_b13_x) + B :MSTORE(mulFp12BN254_b13_y) + $ => A :MLOAD(decompressFp12BN254_a5_x) + $ => B :MLOAD(decompressFp12BN254_a5_y) + A :MSTORE(mulFp12BN254_b23_x) + B :MSTORE(mulFp12BN254_b23_y), CALL(mulFp12BN254) + + :JMP(expByXCompCycloFp12BN254_loop) + +expByXCompCycloFp12BN254_last: + ; Last asignments + $ => A :MLOAD(mulFp12BN254_c11_x) + $ => B :MLOAD(mulFp12BN254_c11_y) + A :MSTORE(expByXCompCycloFp12BN254_c0_x) + B :MSTORE(expByXCompCycloFp12BN254_c0_y) + $ => A :MLOAD(mulFp12BN254_c12_x) + $ => B :MLOAD(mulFp12BN254_c12_y) + A :MSTORE(expByXCompCycloFp12BN254_c4_x) + B :MSTORE(expByXCompCycloFp12BN254_c4_y) + $ => A :MLOAD(mulFp12BN254_c13_x) + $ => B :MLOAD(mulFp12BN254_c13_y) + A :MSTORE(expByXCompCycloFp12BN254_c3_x) + B :MSTORE(expByXCompCycloFp12BN254_c3_y) + $ => A :MLOAD(mulFp12BN254_c21_x) + $ => B :MLOAD(mulFp12BN254_c21_y) + A :MSTORE(expByXCompCycloFp12BN254_c2_x) + B :MSTORE(expByXCompCycloFp12BN254_c2_y) + $ => A :MLOAD(mulFp12BN254_c22_x) + $ => B :MLOAD(mulFp12BN254_c22_y) + A :MSTORE(expByXCompCycloFp12BN254_c1_x) + B :MSTORE(expByXCompCycloFp12BN254_c1_y) + $ => A :MLOAD(mulFp12BN254_c23_x) + $ => B :MLOAD(mulFp12BN254_c23_y) + A :MSTORE(expByXCompCycloFp12BN254_c5_x) + B :MSTORE(expByXCompCycloFp12BN254_c5_y) + +expByXCompCycloFp12BN254_end: + $ => RR :MLOAD(expByXCompCycloFp12BN254_RR) + :RETURN + diff --git a/main/pairings/FP12BN254/CYCLOFP12BN254/squareCompCycloFp12BN254.zkasm b/main/pairings/FP12BN254/CYCLOFP12BN254/squareCompCycloFp12BN254.zkasm new file mode 100644 index 00000000..63d576d5 --- /dev/null +++ b/main/pairings/FP12BN254/CYCLOFP12BN254/squareCompCycloFp12BN254.zkasm @@ -0,0 +1,212 @@ +;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; POST: The result is in the range [0,BN254_P) because if falls back to FP2 arithmetic +;; +;; squareCompCycloFp12BN254: +;; in: [a2,a3,a4,a5] ∈ Fp2⁴, where ai ∈ Fp2 +;; out: C(a²) = [b2, b3, b4, b5] ∈ Fp2⁴, where: +;; - b2 = 2(a2 + 3·(9+u)·B45) +;; - b3 = 3·(A45 - (10+u)·B45) - 2·a3 +;; - b4 = 3·(A23 - (10+u)·B23) - 2·a4 +;; - b5 = 2·(a5 + 3·B23) +;; - A23 = (a2 + a3)·(a2 + (9+u)·a3) +;; - A45 = (a4 + a5)·(a4 + (9+u)·a5) +;; - B23 = a2·a3 +;; - B45 = a4·a5 +;; +;; NOTE: If the input is not of the form C(a), where a ∈ GΦ6(p²), then the compression-decompression +;; technique will not be well defined after the squaring. This means that D(C(a²)) != a². +;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +VAR GLOBAL squareCompCycloFp12BN254_Ca2_x +VAR GLOBAL squareCompCycloFp12BN254_Ca2_y +VAR GLOBAL squareCompCycloFp12BN254_Ca3_x +VAR GLOBAL squareCompCycloFp12BN254_Ca3_y +VAR GLOBAL squareCompCycloFp12BN254_Ca4_x +VAR GLOBAL squareCompCycloFp12BN254_Ca4_y +VAR GLOBAL squareCompCycloFp12BN254_Ca5_x +VAR GLOBAL squareCompCycloFp12BN254_Ca5_y +VAR GLOBAL squareCompCycloFp12BN254_Cb2_x +VAR GLOBAL squareCompCycloFp12BN254_Cb2_y +VAR GLOBAL squareCompCycloFp12BN254_Cb3_x +VAR GLOBAL squareCompCycloFp12BN254_Cb3_y +VAR GLOBAL squareCompCycloFp12BN254_Cb4_x +VAR GLOBAL squareCompCycloFp12BN254_Cb4_y +VAR GLOBAL squareCompCycloFp12BN254_Cb5_x +VAR GLOBAL squareCompCycloFp12BN254_Cb5_y + +VAR GLOBAL squareCompCycloFp12BN254_B23_x +VAR GLOBAL squareCompCycloFp12BN254_B23_y +VAR GLOBAL squareCompCycloFp12BN254_B45_x +VAR GLOBAL squareCompCycloFp12BN254_B45_y +VAR GLOBAL squareCompCycloFp12BN254_A23_x +VAR GLOBAL squareCompCycloFp12BN254_A23_y +VAR GLOBAL squareCompCycloFp12BN254_A45_x +VAR GLOBAL squareCompCycloFp12BN254_A45_y + +VAR GLOBAL squareCompCycloFp12BN254_A23right_x +VAR GLOBAL squareCompCycloFp12BN254_A23right_y +VAR GLOBAL squareCompCycloFp12BN254_A45right_x +VAR GLOBAL squareCompCycloFp12BN254_A45right_y + +VAR GLOBAL squareCompCycloFp12BN254_twoCa3_x +VAR GLOBAL squareCompCycloFp12BN254_twoCa3_y + +VAR GLOBAL squareCompCycloFp12BN254_twoCa4_x +VAR GLOBAL squareCompCycloFp12BN254_twoCa4_y + +VAR GLOBAL squareCompCycloFp12BN254_RR + +squareCompCycloFp12BN254: + RR :MSTORE(squareCompCycloFp12BN254_RR) + + ; 1] B23 = a2·a3, B45 = a4·a5 + $ => A :MLOAD(squareCompCycloFp12BN254_Ca2_x) + $ => B :MLOAD(squareCompCycloFp12BN254_Ca2_y) + $ => C :MLOAD(squareCompCycloFp12BN254_Ca3_x) + $ => D :MLOAD(squareCompCycloFp12BN254_Ca3_y), CALL(mulFp2BN254) + E :MSTORE(squareCompCycloFp12BN254_B23_x) + C :MSTORE(squareCompCycloFp12BN254_B23_y) + + $ => A :MLOAD(squareCompCycloFp12BN254_Ca4_x) + $ => B :MLOAD(squareCompCycloFp12BN254_Ca4_y) + $ => C :MLOAD(squareCompCycloFp12BN254_Ca5_x) + $ => D :MLOAD(squareCompCycloFp12BN254_Ca5_y), CALL(mulFp2BN254) + E :MSTORE(squareCompCycloFp12BN254_B45_x) + C :MSTORE(squareCompCycloFp12BN254_B45_y) + + ; 2] A23 = (a2 + a3)·(a2 + (9+u)·a3) + 9n => A + 1n => B + $ => C :MLOAD(squareCompCycloFp12BN254_Ca3_x) + $ => D :MLOAD(squareCompCycloFp12BN254_Ca3_y), CALL(mulFp2BN254) + E => A + C => B + $ => C :MLOAD(squareCompCycloFp12BN254_Ca2_x) + $ => D :MLOAD(squareCompCycloFp12BN254_Ca2_y), CALL(addFp2BN254) + E :MSTORE(squareCompCycloFp12BN254_A23right_x) + C :MSTORE(squareCompCycloFp12BN254_A23right_y) + + $ => A :MLOAD(squareCompCycloFp12BN254_Ca2_x) + $ => B :MLOAD(squareCompCycloFp12BN254_Ca2_y) + $ => C :MLOAD(squareCompCycloFp12BN254_Ca3_x) + $ => D :MLOAD(squareCompCycloFp12BN254_Ca3_y), CALL(addFp2BN254) + E => A + C => B + $ => C :MLOAD(squareCompCycloFp12BN254_A23right_x) + $ => D :MLOAD(squareCompCycloFp12BN254_A23right_y), CALL(mulFp2BN254) + E :MSTORE(squareCompCycloFp12BN254_A23_x) + C :MSTORE(squareCompCycloFp12BN254_A23_y) + + ; 3] A45 = (a4 + a5)·(a4 + (9+u)·a5) + 9n => A + 1n => B + $ => C :MLOAD(squareCompCycloFp12BN254_Ca5_x) + $ => D :MLOAD(squareCompCycloFp12BN254_Ca5_y), CALL(mulFp2BN254) + E => A + C => B + $ => C :MLOAD(squareCompCycloFp12BN254_Ca4_x) + $ => D :MLOAD(squareCompCycloFp12BN254_Ca4_y), CALL(addFp2BN254) + E :MSTORE(squareCompCycloFp12BN254_A45right_x) + C :MSTORE(squareCompCycloFp12BN254_A45right_y) + + $ => A :MLOAD(squareCompCycloFp12BN254_Ca4_x) + $ => B :MLOAD(squareCompCycloFp12BN254_Ca4_y) + $ => C :MLOAD(squareCompCycloFp12BN254_Ca5_x) + $ => D :MLOAD(squareCompCycloFp12BN254_Ca5_y), CALL(addFp2BN254) + E => A + C => B + $ => C :MLOAD(squareCompCycloFp12BN254_A45right_x) + $ => D :MLOAD(squareCompCycloFp12BN254_A45right_y), CALL(mulFp2BN254) + E :MSTORE(squareCompCycloFp12BN254_A45_x) + C :MSTORE(squareCompCycloFp12BN254_A45_y) + + ; 4] b2 = 2(a2 + 3·(9+u)·B45) + 9n => A + 1n => B + $ => C :MLOAD(squareCompCycloFp12BN254_B45_x) + $ => D :MLOAD(squareCompCycloFp12BN254_B45_y), CALL(mulFp2BN254) + 3n => A + C => D + E => C :CALL(escalarMulFp2BN254) + E => A + C => B + $ => C :MLOAD(squareCompCycloFp12BN254_Ca2_x) + $ => D :MLOAD(squareCompCycloFp12BN254_Ca2_y), CALL(addFp2BN254) + 2n => A + C => D + E => C :CALL(escalarMulFp2BN254) + E :MSTORE(squareCompCycloFp12BN254_Cb2_x) + C :MSTORE(squareCompCycloFp12BN254_Cb2_y) + + ; 5] b3 = 3·(A45 - (10+u)·B45) - 2·a3 + 2n => A + $ => C :MLOAD(squareCompCycloFp12BN254_Ca3_x) + $ => D :MLOAD(squareCompCycloFp12BN254_Ca3_y), CALL(escalarMulFp2BN254) + E :MSTORE(squareCompCycloFp12BN254_twoCa3_x) + C :MSTORE(squareCompCycloFp12BN254_twoCa3_y) + + 10n => A + 1n => B + $ => C :MLOAD(squareCompCycloFp12BN254_B45_x) + $ => D :MLOAD(squareCompCycloFp12BN254_B45_y), CALL(mulFp2BN254) + $ => A :MLOAD(squareCompCycloFp12BN254_A45_x) + $ => B :MLOAD(squareCompCycloFp12BN254_A45_y) + C => D + E => C :CALL(subFp2BN254) + + 3n => A + C => D + E => C :CALL(escalarMulFp2BN254) + + E => A + C => B + $ => C :MLOAD(squareCompCycloFp12BN254_twoCa3_x) + $ => D :MLOAD(squareCompCycloFp12BN254_twoCa3_y), CALL(subFp2BN254) + E :MSTORE(squareCompCycloFp12BN254_Cb3_x) + C :MSTORE(squareCompCycloFp12BN254_Cb3_y) + + ; 6] b4 = 3·(A23 - (10+u)·B23) - 2·a4 + 2n => A + $ => C :MLOAD(squareCompCycloFp12BN254_Ca4_x) + $ => D :MLOAD(squareCompCycloFp12BN254_Ca4_y), CALL(escalarMulFp2BN254) + E :MSTORE(squareCompCycloFp12BN254_twoCa4_x) + C :MSTORE(squareCompCycloFp12BN254_twoCa4_y) + + 10n => A + 1n => B + $ => C :MLOAD(squareCompCycloFp12BN254_B23_x) + $ => D :MLOAD(squareCompCycloFp12BN254_B23_y), CALL(mulFp2BN254) + $ => A :MLOAD(squareCompCycloFp12BN254_A23_x) + $ => B :MLOAD(squareCompCycloFp12BN254_A23_y) + C => D + E => C :CALL(subFp2BN254) + + 3n => A + C => D + E => C :CALL(escalarMulFp2BN254) + + E => A + C => B + $ => C :MLOAD(squareCompCycloFp12BN254_twoCa4_x) + $ => D :MLOAD(squareCompCycloFp12BN254_twoCa4_y), CALL(subFp2BN254) + E :MSTORE(squareCompCycloFp12BN254_Cb4_x) + C :MSTORE(squareCompCycloFp12BN254_Cb4_y) + + ; 7] b5 = 2·(a5 + 3·B23) + 3n => A + $ => C :MLOAD(squareCompCycloFp12BN254_B23_x) + $ => D :MLOAD(squareCompCycloFp12BN254_B23_y), CALL(escalarMulFp2BN254) + E => A + C => B + $ => C :MLOAD(squareCompCycloFp12BN254_Ca5_x) + $ => D :MLOAD(squareCompCycloFp12BN254_Ca5_y), CALL(addFp2BN254) + 2n => A + C => D + E => C :CALL(escalarMulFp2BN254) + + E :MSTORE(squareCompCycloFp12BN254_Cb5_x) + C :MSTORE(squareCompCycloFp12BN254_Cb5_y) + + $ => RR :MLOAD(squareCompCycloFp12BN254_RR) + :RETURN + diff --git a/main/pairings/FP12BN254/CYCLOFP12BN254/squareCycloFp12BN254.zkasm b/main/pairings/FP12BN254/CYCLOFP12BN254/squareCycloFp12BN254.zkasm new file mode 100644 index 00000000..6b965120 --- /dev/null +++ b/main/pairings/FP12BN254/CYCLOFP12BN254/squareCycloFp12BN254.zkasm @@ -0,0 +1,228 @@ +;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; POST: The result is in the range [0,BN254_P) because if falls back to FP4/FP2 arithmetic +;; +;; squareCycloFp12BN254: +;; in: (a1 + a2·w) ∈ GΦ6(p²), where ai ∈ Fp6 +;; out: (c1 + c2·w) = (a1 + a2·w)² ∈ GΦ6(p²) +;; +;; NOTE: The output is not guaranteed to be in GΦ6(p²), if the input isn't. +;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +VAR GLOBAL squareCycloFp12BN254_a11_x +VAR GLOBAL squareCycloFp12BN254_a11_y +VAR GLOBAL squareCycloFp12BN254_a12_x +VAR GLOBAL squareCycloFp12BN254_a12_y +VAR GLOBAL squareCycloFp12BN254_a13_x +VAR GLOBAL squareCycloFp12BN254_a13_y +VAR GLOBAL squareCycloFp12BN254_a21_x +VAR GLOBAL squareCycloFp12BN254_a21_y +VAR GLOBAL squareCycloFp12BN254_a22_x +VAR GLOBAL squareCycloFp12BN254_a22_y +VAR GLOBAL squareCycloFp12BN254_a23_x +VAR GLOBAL squareCycloFp12BN254_a23_y +VAR GLOBAL squareCycloFp12BN254_c11_x +VAR GLOBAL squareCycloFp12BN254_c11_y +VAR GLOBAL squareCycloFp12BN254_c12_x +VAR GLOBAL squareCycloFp12BN254_c12_y +VAR GLOBAL squareCycloFp12BN254_c13_x +VAR GLOBAL squareCycloFp12BN254_c13_y +VAR GLOBAL squareCycloFp12BN254_c21_x +VAR GLOBAL squareCycloFp12BN254_c21_y +VAR GLOBAL squareCycloFp12BN254_c22_x +VAR GLOBAL squareCycloFp12BN254_c22_y +VAR GLOBAL squareCycloFp12BN254_c23_x +VAR GLOBAL squareCycloFp12BN254_c23_y + +VAR GLOBAL squareCycloFp12BN254_t11_x +VAR GLOBAL squareCycloFp12BN254_t11_y +VAR GLOBAL squareCycloFp12BN254_t22_x +VAR GLOBAL squareCycloFp12BN254_t22_y +VAR GLOBAL squareCycloFp12BN254_t23_x +VAR GLOBAL squareCycloFp12BN254_t23_y +VAR GLOBAL squareCycloFp12BN254_t12_x +VAR GLOBAL squareCycloFp12BN254_t12_y +VAR GLOBAL squareCycloFp12BN254_t13_x +VAR GLOBAL squareCycloFp12BN254_t13_y +VAR GLOBAL squareCycloFp12BN254_aux_x +VAR GLOBAL squareCycloFp12BN254_aux_y +VAR GLOBAL squareCycloFp12BN254_t21_x +VAR GLOBAL squareCycloFp12BN254_t21_y + +VAR GLOBAL squareCycloFp12BN254_RR + +squareCycloFp12BN254: + RR :MSTORE(squareCycloFp12BN254_RR) + + ; 1] [t11,t22] = (a11 + a22·V)² + $ => A :MLOAD(squareCycloFp12BN254_a11_x) + $ => B :MLOAD(squareCycloFp12BN254_a11_y) + $ => C :MLOAD(squareCycloFp12BN254_a22_x) + $ => D :MLOAD(squareCycloFp12BN254_a22_y) + A :MSTORE(squareFp4BN254_a1_x) + B :MSTORE(squareFp4BN254_a1_y) + C :MSTORE(squareFp4BN254_a2_x) + D :MSTORE(squareFp4BN254_a2_y), CALL(squareFp4BN254) + $ => A :MLOAD(squareFp4BN254_c1_x) + $ => B :MLOAD(squareFp4BN254_c1_y) + $ => C :MLOAD(squareFp4BN254_c2_x) + $ => D :MLOAD(squareFp4BN254_c2_y) + A :MSTORE(squareCycloFp12BN254_t11_x) + B :MSTORE(squareCycloFp12BN254_t11_y) + C :MSTORE(squareCycloFp12BN254_t22_x) + D :MSTORE(squareCycloFp12BN254_t22_y) + + ; 2] [t23,t12] = (a21 + a13·V)² + $ => A :MLOAD(squareCycloFp12BN254_a21_x) + $ => B :MLOAD(squareCycloFp12BN254_a21_y) + $ => C :MLOAD(squareCycloFp12BN254_a13_x) + $ => D :MLOAD(squareCycloFp12BN254_a13_y) + A :MSTORE(squareFp4BN254_a1_x) + B :MSTORE(squareFp4BN254_a1_y) + C :MSTORE(squareFp4BN254_a2_x) + D :MSTORE(squareFp4BN254_a2_y), CALL(squareFp4BN254) + $ => A :MLOAD(squareFp4BN254_c1_x) + $ => B :MLOAD(squareFp4BN254_c1_y) + $ => C :MLOAD(squareFp4BN254_c2_x) + $ => D :MLOAD(squareFp4BN254_c2_y) + A :MSTORE(squareCycloFp12BN254_t23_x) + B :MSTORE(squareCycloFp12BN254_t23_y) + C :MSTORE(squareCycloFp12BN254_t12_x) + D :MSTORE(squareCycloFp12BN254_t12_y) + + ; 3] [t13,aux] = (a12 + a23·V)² + $ => A :MLOAD(squareCycloFp12BN254_a12_x) + $ => B :MLOAD(squareCycloFp12BN254_a12_y) + $ => C :MLOAD(squareCycloFp12BN254_a23_x) + $ => D :MLOAD(squareCycloFp12BN254_a23_y) + A :MSTORE(squareFp4BN254_a1_x) + B :MSTORE(squareFp4BN254_a1_y) + C :MSTORE(squareFp4BN254_a2_x) + D :MSTORE(squareFp4BN254_a2_y), CALL(squareFp4BN254) + $ => A :MLOAD(squareFp4BN254_c1_x) + $ => B :MLOAD(squareFp4BN254_c1_y) + $ => C :MLOAD(squareFp4BN254_c2_x) + $ => D :MLOAD(squareFp4BN254_c2_y) + A :MSTORE(squareCycloFp12BN254_t13_x) + B :MSTORE(squareCycloFp12BN254_t13_y) + C :MSTORE(squareCycloFp12BN254_aux_x) + D :MSTORE(squareCycloFp12BN254_aux_y) + + ; 4] t21 = aux·(9+u) + $ => A :MLOAD(squareCycloFp12BN254_aux_x) + $ => B :MLOAD(squareCycloFp12BN254_aux_y) + 9n => C + 1n => D :CALL(mulFp2BN254) + E :MSTORE(squareCycloFp12BN254_t21_x) + C :MSTORE(squareCycloFp12BN254_t21_y) + + ; 5] c11 = -2·a11 + 3·t11 + %BN254_P - 2n => A + $ => C :MLOAD(squareCycloFp12BN254_a11_x) + $ => D :MLOAD(squareCycloFp12BN254_a11_y), CALL(escalarMulFp2BN254) + E :MSTORE(squareCycloFp12BN254_a11_x) + C :MSTORE(squareCycloFp12BN254_a11_y) + + 3n => A + $ => C :MLOAD(squareCycloFp12BN254_t11_x) + $ => D :MLOAD(squareCycloFp12BN254_t11_y), CALL(escalarMulFp2BN254) + + E => A + C => B + $ => C :MLOAD(squareCycloFp12BN254_a11_x) + $ => D :MLOAD(squareCycloFp12BN254_a11_y), CALL(addFp2BN254) + E :MSTORE(squareCycloFp12BN254_c11_x) + C :MSTORE(squareCycloFp12BN254_c11_y) + + ; 6] c12 = -2·a12 + 3·t23 + %BN254_P - 2n => A + $ => C :MLOAD(squareCycloFp12BN254_a12_x) + $ => D :MLOAD(squareCycloFp12BN254_a12_y), CALL(escalarMulFp2BN254) + E :MSTORE(squareCycloFp12BN254_a12_x) + C :MSTORE(squareCycloFp12BN254_a12_y) + + 3n => A + $ => C :MLOAD(squareCycloFp12BN254_t23_x) + $ => D :MLOAD(squareCycloFp12BN254_t23_y), CALL(escalarMulFp2BN254) + + E => A + C => B + $ => C :MLOAD(squareCycloFp12BN254_a12_x) + $ => D :MLOAD(squareCycloFp12BN254_a12_y), CALL(addFp2BN254) + E :MSTORE(squareCycloFp12BN254_c12_x) + C :MSTORE(squareCycloFp12BN254_c12_y) + + ; 7] c13 = -2·a13 + 3·t13 + %BN254_P - 2n => A + $ => C :MLOAD(squareCycloFp12BN254_a13_x) + $ => D :MLOAD(squareCycloFp12BN254_a13_y), CALL(escalarMulFp2BN254) + E :MSTORE(squareCycloFp12BN254_a13_x) + C :MSTORE(squareCycloFp12BN254_a13_y) + + 3n => A + $ => C :MLOAD(squareCycloFp12BN254_t13_x) + $ => D :MLOAD(squareCycloFp12BN254_t13_y), CALL(escalarMulFp2BN254) + + E => A + C => B + $ => C :MLOAD(squareCycloFp12BN254_a13_x) + $ => D :MLOAD(squareCycloFp12BN254_a13_y), CALL(addFp2BN254) + E :MSTORE(squareCycloFp12BN254_c13_x) + C :MSTORE(squareCycloFp12BN254_c13_y) + + ; 8] c21 = 2·a21 + 3·t21 + 2n => A + $ => C :MLOAD(squareCycloFp12BN254_a21_x) + $ => D :MLOAD(squareCycloFp12BN254_a21_y), CALL(escalarMulFp2BN254) + E :MSTORE(squareCycloFp12BN254_a21_x) + C :MSTORE(squareCycloFp12BN254_a21_y) + + 3n => A + $ => C :MLOAD(squareCycloFp12BN254_t21_x) + $ => D :MLOAD(squareCycloFp12BN254_t21_y), CALL(escalarMulFp2BN254) + + E => A + C => B + $ => C :MLOAD(squareCycloFp12BN254_a21_x) + $ => D :MLOAD(squareCycloFp12BN254_a21_y), CALL(addFp2BN254) + E :MSTORE(squareCycloFp12BN254_c21_x) + C :MSTORE(squareCycloFp12BN254_c21_y) + + ; 9] c22 = 2·a22 + 3·t22 + 2n => A + $ => C :MLOAD(squareCycloFp12BN254_a22_x) + $ => D :MLOAD(squareCycloFp12BN254_a22_y), CALL(escalarMulFp2BN254) + E :MSTORE(squareCycloFp12BN254_a22_x) + C :MSTORE(squareCycloFp12BN254_a22_y) + + 3n => A + $ => C :MLOAD(squareCycloFp12BN254_t22_x) + $ => D :MLOAD(squareCycloFp12BN254_t22_y), CALL(escalarMulFp2BN254) + + E => A + C => B + $ => C :MLOAD(squareCycloFp12BN254_a22_x) + $ => D :MLOAD(squareCycloFp12BN254_a22_y), CALL(addFp2BN254) + E :MSTORE(squareCycloFp12BN254_c22_x) + C :MSTORE(squareCycloFp12BN254_c22_y) + + ; 9] c23 = 2·a23 + 3·t12 + 2n => A + $ => C :MLOAD(squareCycloFp12BN254_a23_x) + $ => D :MLOAD(squareCycloFp12BN254_a23_y), CALL(escalarMulFp2BN254) + E :MSTORE(squareCycloFp12BN254_a23_x) + C :MSTORE(squareCycloFp12BN254_a23_y) + + 3n => A + $ => C :MLOAD(squareCycloFp12BN254_t12_x) + $ => D :MLOAD(squareCycloFp12BN254_t12_y), CALL(escalarMulFp2BN254) + + E => A + C => B + $ => C :MLOAD(squareCycloFp12BN254_a23_x) + $ => D :MLOAD(squareCycloFp12BN254_a23_y), CALL(addFp2BN254) + E :MSTORE(squareCycloFp12BN254_c23_x) + C :MSTORE(squareCycloFp12BN254_c23_y) + + + $ => RR :MLOAD(squareCycloFp12BN254_RR) + :RETURN \ No newline at end of file diff --git a/main/pairings/FP12BN254/CYCLOFP12BN254/xBinDecompBN254.zkasm b/main/pairings/FP12BN254/CYCLOFP12BN254/xBinDecompBN254.zkasm new file mode 100644 index 00000000..2aae4630 --- /dev/null +++ b/main/pairings/FP12BN254/CYCLOFP12BN254/xBinDecompBN254.zkasm @@ -0,0 +1,64 @@ +;; +;; parameter of BN254 x = 4965661367192848881, which can be expressed in (little-endian) binary as: +;; 100011111001000010010110010100100010110101001001100101110010001 +;; + +xBinDecompBN254: + 1 => B :RETURN + 0 => B :RETURN + 0 => B :RETURN + 0 => B :RETURN + 1 => B :RETURN + 0 => B :RETURN + 0 => B :RETURN + 1 => B :RETURN + 1 => B :RETURN + 1 => B :RETURN + 0 => B :RETURN + 1 => B :RETURN + 0 => B :RETURN + 0 => B :RETURN + 1 => B :RETURN + 1 => B :RETURN + 0 => B :RETURN + 0 => B :RETURN + 1 => B :RETURN + 0 => B :RETURN + 0 => B :RETURN + 1 => B :RETURN + 0 => B :RETURN + 1 => B :RETURN + 0 => B :RETURN + 1 => B :RETURN + 1 => B :RETURN + 0 => B :RETURN + 1 => B :RETURN + 0 => B :RETURN + 0 => B :RETURN + 0 => B :RETURN + 1 => B :RETURN + 0 => B :RETURN + 0 => B :RETURN + 1 => B :RETURN + 0 => B :RETURN + 1 => B :RETURN + 0 => B :RETURN + 0 => B :RETURN + 1 => B :RETURN + 1 => B :RETURN + 0 => B :RETURN + 1 => B :RETURN + 0 => B :RETURN + 0 => B :RETURN + 1 => B :RETURN + 0 => B :RETURN + 0 => B :RETURN + 0 => B :RETURN + 0 => B :RETURN + 1 => B :RETURN + 0 => B :RETURN + 0 => B :RETURN + 1 => B :RETURN + 1 => B :RETURN + 1 => B :RETURN + 1 => B :RETURN \ No newline at end of file diff --git a/main/pairings/FP12BN254/frob2Fp12BN254.zkasm b/main/pairings/FP12BN254/frob2Fp12BN254.zkasm new file mode 100644 index 00000000..b09bcfec --- /dev/null +++ b/main/pairings/FP12BN254/frob2Fp12BN254.zkasm @@ -0,0 +1,80 @@ +;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; POST: The result is in the range [0,BN254_P) because if falls back to FP2 arithmetic +;; +;; frob2Fp12BN254: +;; in: (a1 + a2·w) = ((a11 + a12v + a13v²) + (a21 + a22v + a23v²)) ∈ Fp12, where ai ∈ Fp6 and aij ∈ Fp2 +;; out: (a1 + a2·w)ᵖ˙ᵖ = (c1 + c2·w) ∈ Fp12, where: +;; - c1 = a11 + a12·γ22·v + a13·γ24·v² +;; - c2 = a21·γ21 + a22·γ23·v + a23·γ25·v² +;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +VAR GLOBAL frob2Fp12BN254_a11_x +VAR GLOBAL frob2Fp12BN254_a11_y +VAR GLOBAL frob2Fp12BN254_a12_x +VAR GLOBAL frob2Fp12BN254_a12_y +VAR GLOBAL frob2Fp12BN254_a13_x +VAR GLOBAL frob2Fp12BN254_a13_y +VAR GLOBAL frob2Fp12BN254_a21_x +VAR GLOBAL frob2Fp12BN254_a21_y +VAR GLOBAL frob2Fp12BN254_a22_x +VAR GLOBAL frob2Fp12BN254_a22_y +VAR GLOBAL frob2Fp12BN254_a23_x +VAR GLOBAL frob2Fp12BN254_a23_y +VAR GLOBAL frob2Fp12BN254_c11_x +VAR GLOBAL frob2Fp12BN254_c11_y +VAR GLOBAL frob2Fp12BN254_c12_x +VAR GLOBAL frob2Fp12BN254_c12_y +VAR GLOBAL frob2Fp12BN254_c13_x +VAR GLOBAL frob2Fp12BN254_c13_y +VAR GLOBAL frob2Fp12BN254_c21_x +VAR GLOBAL frob2Fp12BN254_c21_y +VAR GLOBAL frob2Fp12BN254_c22_x +VAR GLOBAL frob2Fp12BN254_c22_y +VAR GLOBAL frob2Fp12BN254_c23_x +VAR GLOBAL frob2Fp12BN254_c23_y + +VAR GLOBAL frob2Fp12BN254_RR + +frob2Fp12BN254: + RR :MSTORE(frob2Fp12BN254_RR) + + ; 1] c1 = a11 + a12·γ22·v + a13·γ24·v² + $ => A :MLOAD(frob2Fp12BN254_a11_x) + $ => B :MLOAD(frob2Fp12BN254_a11_y) + A :MSTORE(frob2Fp12BN254_c11_x) + B :MSTORE(frob2Fp12BN254_c11_y) + + %FROBENIUS_GAMMA22 => A + $ => C :MLOAD(frob2Fp12BN254_a12_x) + $ => D :MLOAD(frob2Fp12BN254_a12_y), CALL(escalarMulFp2BN254) + E :MSTORE(frob2Fp12BN254_c12_x) + C :MSTORE(frob2Fp12BN254_c12_y) + + %FROBENIUS_GAMMA24 => A + $ => C :MLOAD(frob2Fp12BN254_a13_x) + $ => D :MLOAD(frob2Fp12BN254_a13_y), CALL(escalarMulFp2BN254) + E :MSTORE(frob2Fp12BN254_c13_x) + C :MSTORE(frob2Fp12BN254_c13_y) + + ; 2] c2 = a21·γ21 + a22·γ23·v + a23·γ25·v² + %FROBENIUS_GAMMA21 => A + $ => C :MLOAD(frob2Fp12BN254_a21_x) + $ => D :MLOAD(frob2Fp12BN254_a21_y), CALL(escalarMulFp2BN254) + E :MSTORE(frob2Fp12BN254_c21_x) + C :MSTORE(frob2Fp12BN254_c21_y) + + %FROBENIUS_GAMMA23 => A + $ => C :MLOAD(frob2Fp12BN254_a22_x) + $ => D :MLOAD(frob2Fp12BN254_a22_y), CALL(escalarMulFp2BN254) + E :MSTORE(frob2Fp12BN254_c22_x) + C :MSTORE(frob2Fp12BN254_c22_y) + + %FROBENIUS_GAMMA25 => A + $ => C :MLOAD(frob2Fp12BN254_a23_x) + $ => D :MLOAD(frob2Fp12BN254_a23_y), CALL(escalarMulFp2BN254) + E :MSTORE(frob2Fp12BN254_c23_x) + C :MSTORE(frob2Fp12BN254_c23_y) + + $ => RR :MLOAD(frob2Fp12BN254_RR) + :RETURN \ No newline at end of file diff --git a/main/pairings/FP12BN254/frob3Fp12BN254.zkasm b/main/pairings/FP12BN254/frob3Fp12BN254.zkasm new file mode 100644 index 00000000..a1731e36 --- /dev/null +++ b/main/pairings/FP12BN254/frob3Fp12BN254.zkasm @@ -0,0 +1,96 @@ +;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; POST: The result is in the range [0,BN254_P) because if falls back to FP2 arithmetic +;; +;; frob3Fp12BN254: +;; in: (a1 + a2·w) = ((a11 + a12v + a13v²) + (a21 + a22v + a23v²)) ∈ Fp12, where ai ∈ Fp6 and aij ∈ Fp2 +;; out: (a1 + a2·w)ᵖ˙ᵖ˙ᵖ = (c1 + c2·w) ∈ Fp12, where: +;; - c1 = a̅11 + a̅12·γ32·v + a̅13·γ34·v² +;; - c2 = a̅21·γ31 + a̅22·γ33·v + a̅23·γ35·v² +;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +VAR GLOBAL frob3Fp12BN254_a11_x +VAR GLOBAL frob3Fp12BN254_a11_y +VAR GLOBAL frob3Fp12BN254_a12_x +VAR GLOBAL frob3Fp12BN254_a12_y +VAR GLOBAL frob3Fp12BN254_a13_x +VAR GLOBAL frob3Fp12BN254_a13_y +VAR GLOBAL frob3Fp12BN254_a21_x +VAR GLOBAL frob3Fp12BN254_a21_y +VAR GLOBAL frob3Fp12BN254_a22_x +VAR GLOBAL frob3Fp12BN254_a22_y +VAR GLOBAL frob3Fp12BN254_a23_x +VAR GLOBAL frob3Fp12BN254_a23_y +VAR GLOBAL frob3Fp12BN254_c11_x +VAR GLOBAL frob3Fp12BN254_c11_y +VAR GLOBAL frob3Fp12BN254_c12_x +VAR GLOBAL frob3Fp12BN254_c12_y +VAR GLOBAL frob3Fp12BN254_c13_x +VAR GLOBAL frob3Fp12BN254_c13_y +VAR GLOBAL frob3Fp12BN254_c21_x +VAR GLOBAL frob3Fp12BN254_c21_y +VAR GLOBAL frob3Fp12BN254_c22_x +VAR GLOBAL frob3Fp12BN254_c22_y +VAR GLOBAL frob3Fp12BN254_c23_x +VAR GLOBAL frob3Fp12BN254_c23_y + +VAR GLOBAL frob3Fp12BN254_RR + +frob3Fp12BN254: + RR :MSTORE(frob3Fp12BN254_RR) + + ; 1] c1 = a̅11 + a̅12·γ32·v + a̅13·γ34·v² + $ => A :MLOAD(frob3Fp12BN254_a11_x) + A :MSTORE(frob3Fp12BN254_c11_x) + %BN254_P => A + $ => B :MLOAD(frob3Fp12BN254_a11_y) + $ :SUB, MSTORE(frob3Fp12BN254_c11_y) + + %BN254_P => A + $ => B :MLOAD(frob3Fp12BN254_a12_y) + $ => B :SUB + $ => A :MLOAD(frob3Fp12BN254_a12_x) + %FROBENIUS_GAMMA321 => C + %FROBENIUS_GAMMA322 => D :CALL(mulFp2BN254) + E :MSTORE(frob3Fp12BN254_c12_x) + C :MSTORE(frob3Fp12BN254_c12_y) + + %BN254_P => A + $ => B :MLOAD(frob3Fp12BN254_a13_y) + $ => B :SUB + $ => A :MLOAD(frob3Fp12BN254_a13_x) + %FROBENIUS_GAMMA341 => C + %FROBENIUS_GAMMA342 => D :CALL(mulFp2BN254) + E :MSTORE(frob3Fp12BN254_c13_x) + C :MSTORE(frob3Fp12BN254_c13_y) + + ; 2] c2 = a̅21·γ11 + a̅22·γ13·v + a̅23·γ15·v² + %BN254_P => A + $ => B :MLOAD(frob3Fp12BN254_a21_y) + $ => B :SUB + $ => A :MLOAD(frob3Fp12BN254_a21_x) + %FROBENIUS_GAMMA311 => C + %FROBENIUS_GAMMA312 => D :CALL(mulFp2BN254) + E :MSTORE(frob3Fp12BN254_c21_x) + C :MSTORE(frob3Fp12BN254_c21_y) + + %BN254_P => A + $ => B :MLOAD(frob3Fp12BN254_a22_y) + $ => B :SUB + $ => A :MLOAD(frob3Fp12BN254_a22_x) + %FROBENIUS_GAMMA331 => C + %FROBENIUS_GAMMA332 => D :CALL(mulFp2BN254) + E :MSTORE(frob3Fp12BN254_c22_x) + C :MSTORE(frob3Fp12BN254_c22_y) + + %BN254_P => A + $ => B :MLOAD(frob3Fp12BN254_a23_y) + $ => B :SUB + $ => A :MLOAD(frob3Fp12BN254_a23_x) + %FROBENIUS_GAMMA351 => C + %FROBENIUS_GAMMA352 => D :CALL(mulFp2BN254) + E :MSTORE(frob3Fp12BN254_c23_x) + C :MSTORE(frob3Fp12BN254_c23_y) + + $ => RR :MLOAD(frob3Fp12BN254_RR) + :RETURN \ No newline at end of file diff --git a/main/pairings/FP12BN254/frobFp12BN254.zkasm b/main/pairings/FP12BN254/frobFp12BN254.zkasm new file mode 100644 index 00000000..8e951c64 --- /dev/null +++ b/main/pairings/FP12BN254/frobFp12BN254.zkasm @@ -0,0 +1,96 @@ +;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; POST: The result is in the range [0,BN254_P) because if falls back to FP2 arithmetic +;; +;; frobFp12BN254: +;; in: (a1 + a2·w) = ((a11 + a12v + a13v²) + (a21 + a22v + a23v²)·w) ∈ Fp12, where ai ∈ Fp6 and aij ∈ Fp2 +;; out: (a1 + a2·w)ᵖ = (c1 + c2·w) ∈ Fp12, where: +;; - c1 = a̅11 + a̅12·γ12·v + a̅13·γ14·v² +;; - c2 = a̅21·γ11 + a̅22·γ13·v + a̅23·γ15·v² +;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +VAR GLOBAL frobFp12BN254_a11_x +VAR GLOBAL frobFp12BN254_a11_y +VAR GLOBAL frobFp12BN254_a12_x +VAR GLOBAL frobFp12BN254_a12_y +VAR GLOBAL frobFp12BN254_a13_x +VAR GLOBAL frobFp12BN254_a13_y +VAR GLOBAL frobFp12BN254_a21_x +VAR GLOBAL frobFp12BN254_a21_y +VAR GLOBAL frobFp12BN254_a22_x +VAR GLOBAL frobFp12BN254_a22_y +VAR GLOBAL frobFp12BN254_a23_x +VAR GLOBAL frobFp12BN254_a23_y +VAR GLOBAL frobFp12BN254_c11_x +VAR GLOBAL frobFp12BN254_c11_y +VAR GLOBAL frobFp12BN254_c12_x +VAR GLOBAL frobFp12BN254_c12_y +VAR GLOBAL frobFp12BN254_c13_x +VAR GLOBAL frobFp12BN254_c13_y +VAR GLOBAL frobFp12BN254_c21_x +VAR GLOBAL frobFp12BN254_c21_y +VAR GLOBAL frobFp12BN254_c22_x +VAR GLOBAL frobFp12BN254_c22_y +VAR GLOBAL frobFp12BN254_c23_x +VAR GLOBAL frobFp12BN254_c23_y + +VAR GLOBAL frobFp12BN254_RR + +frobFp12BN254: + RR :MSTORE(frobFp12BN254_RR) + + ; 1] c1 = a̅11 + a̅12·γ12·v + a̅13·γ14·v² + $ => A :MLOAD(frobFp12BN254_a11_x) + A :MSTORE(frobFp12BN254_c11_x) + %BN254_P => A + $ => B :MLOAD(frobFp12BN254_a11_y) + $ :SUB, MSTORE(frobFp12BN254_c11_y) + + %BN254_P => A + $ => B :MLOAD(frobFp12BN254_a12_y) + $ => B :SUB + $ => A :MLOAD(frobFp12BN254_a12_x) + %FROBENIUS_GAMMA121 => C + %FROBENIUS_GAMMA122 => D :CALL(mulFp2BN254) + E :MSTORE(frobFp12BN254_c12_x) + C :MSTORE(frobFp12BN254_c12_y) + + %BN254_P => A + $ => B :MLOAD(frobFp12BN254_a13_y) + $ => B :SUB + $ => A :MLOAD(frobFp12BN254_a13_x) + %FROBENIUS_GAMMA141 => C + %FROBENIUS_GAMMA142 => D :CALL(mulFp2BN254) + E :MSTORE(frobFp12BN254_c13_x) + C :MSTORE(frobFp12BN254_c13_y) + + ; 2] c2 = a̅21·γ11 + a̅22·γ13·v + a̅23·γ15·v² + %BN254_P => A + $ => B :MLOAD(frobFp12BN254_a21_y) + $ => B :SUB + $ => A :MLOAD(frobFp12BN254_a21_x) + %FROBENIUS_GAMMA111 => C + %FROBENIUS_GAMMA112 => D :CALL(mulFp2BN254) + E :MSTORE(frobFp12BN254_c21_x) + C :MSTORE(frobFp12BN254_c21_y) + + %BN254_P => A + $ => B :MLOAD(frobFp12BN254_a22_y) + $ => B :SUB + $ => A :MLOAD(frobFp12BN254_a22_x) + %FROBENIUS_GAMMA131 => C + %FROBENIUS_GAMMA132 => D :CALL(mulFp2BN254) + E :MSTORE(frobFp12BN254_c22_x) + C :MSTORE(frobFp12BN254_c22_y) + + %BN254_P => A + $ => B :MLOAD(frobFp12BN254_a23_y) + $ => B :SUB + $ => A :MLOAD(frobFp12BN254_a23_x) + %FROBENIUS_GAMMA151 => C + %FROBENIUS_GAMMA152 => D :CALL(mulFp2BN254) + E :MSTORE(frobFp12BN254_c23_x) + C :MSTORE(frobFp12BN254_c23_y) + + $ => RR :MLOAD(frobFp12BN254_RR) + :RETURN \ No newline at end of file diff --git a/main/pairings/FP12BN254/inverseFp12BN254.zkasm b/main/pairings/FP12BN254/inverseFp12BN254.zkasm new file mode 100644 index 00000000..6d9a1b09 --- /dev/null +++ b/main/pairings/FP12BN254/inverseFp12BN254.zkasm @@ -0,0 +1,289 @@ +;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; POST: The result is in the range [0,BN254_P) because if falls back to FP6 arithmetic +;; +;; inverseFp12BN254: +;; in: (a1 + a2·w) ∈ Fp12, where ai ∈ Fp6 +;; out: (a1 + a2·w)⁻¹ = (c1 + c2·w) ∈ Fp12, where: +;; - c1 = a1·(a1² - a2²·v)⁻¹ +;; - c2 = -a2·(a1² - a2²·v)⁻¹ +;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +VAR GLOBAL inverseFp12BN254_a11_x +VAR GLOBAL inverseFp12BN254_a11_y +VAR GLOBAL inverseFp12BN254_a12_x +VAR GLOBAL inverseFp12BN254_a12_y +VAR GLOBAL inverseFp12BN254_a13_x +VAR GLOBAL inverseFp12BN254_a13_y +VAR GLOBAL inverseFp12BN254_a21_x +VAR GLOBAL inverseFp12BN254_a21_y +VAR GLOBAL inverseFp12BN254_a22_x +VAR GLOBAL inverseFp12BN254_a22_y +VAR GLOBAL inverseFp12BN254_a23_x +VAR GLOBAL inverseFp12BN254_a23_y +VAR GLOBAL inverseFp12BN254_c11_x +VAR GLOBAL inverseFp12BN254_c11_y +VAR GLOBAL inverseFp12BN254_c12_x +VAR GLOBAL inverseFp12BN254_c12_y +VAR GLOBAL inverseFp12BN254_c13_x +VAR GLOBAL inverseFp12BN254_c13_y +VAR GLOBAL inverseFp12BN254_c21_x +VAR GLOBAL inverseFp12BN254_c21_y +VAR GLOBAL inverseFp12BN254_c22_x +VAR GLOBAL inverseFp12BN254_c22_y +VAR GLOBAL inverseFp12BN254_c23_x +VAR GLOBAL inverseFp12BN254_c23_y + +VAR GLOBAL inverseFp12BN254_a1square1_x +VAR GLOBAL inverseFp12BN254_a1square1_y +VAR GLOBAL inverseFp12BN254_a1square2_x +VAR GLOBAL inverseFp12BN254_a1square2_y +VAR GLOBAL inverseFp12BN254_a1square3_x +VAR GLOBAL inverseFp12BN254_a1square3_y +VAR GLOBAL inverseFp12BN254_a2square1_x +VAR GLOBAL inverseFp12BN254_a2square1_y +VAR GLOBAL inverseFp12BN254_a2square2_x +VAR GLOBAL inverseFp12BN254_a2square2_y +VAR GLOBAL inverseFp12BN254_a2square3_x +VAR GLOBAL inverseFp12BN254_a2square3_y + +VAR GLOBAL inverseFp12BN254_a1sqsubva2sq1_x +VAR GLOBAL inverseFp12BN254_a1sqsubva2sq1_y +VAR GLOBAL inverseFp12BN254_a1sqsubva2sq2_x +VAR GLOBAL inverseFp12BN254_a1sqsubva2sq2_y +VAR GLOBAL inverseFp12BN254_a1sqsubva2sq3_x +VAR GLOBAL inverseFp12BN254_a1sqsubva2sq3_y +VAR GLOBAL inverseFp12BN254_va2square1_x +VAR GLOBAL inverseFp12BN254_va2square1_y +VAR GLOBAL inverseFp12BN254_va2square2_x +VAR GLOBAL inverseFp12BN254_va2square2_y +VAR GLOBAL inverseFp12BN254_va2square3_x +VAR GLOBAL inverseFp12BN254_va2square3_y + +VAR GLOBAL inverseFp12BN254_final1_x +VAR GLOBAL inverseFp12BN254_final1_y +VAR GLOBAL inverseFp12BN254_final2_x +VAR GLOBAL inverseFp12BN254_final2_y +VAR GLOBAL inverseFp12BN254_final3_x +VAR GLOBAL inverseFp12BN254_final3_y + +VAR GLOBAL inverseFp12BN254_RR + +inverseFp12BN254: + RR :MSTORE(inverseFp12BN254_RR) + + ; 1] a1² + $ => A :MLOAD(inverseFp12BN254_a11_x) + $ => B :MLOAD(inverseFp12BN254_a11_y) + A :MSTORE(squareFp6BN254_a1_x) + B :MSTORE(squareFp6BN254_a1_y) + $ => A :MLOAD(inverseFp12BN254_a12_x) + $ => B :MLOAD(inverseFp12BN254_a12_y) + A :MSTORE(squareFp6BN254_a2_x) + B :MSTORE(squareFp6BN254_a2_y) + $ => A :MLOAD(inverseFp12BN254_a13_x) + $ => B :MLOAD(inverseFp12BN254_a13_y) + A :MSTORE(squareFp6BN254_a3_x) + B :MSTORE(squareFp6BN254_a3_y), CALL(squareFp6BN254) + $ => A :MLOAD(squareFp6BN254_c1_x) + $ => B :MLOAD(squareFp6BN254_c1_y) + A :MSTORE(inverseFp12BN254_a1square1_x) + B :MSTORE(inverseFp12BN254_a1square1_y) + $ => A :MLOAD(squareFp6BN254_c2_x) + $ => B :MLOAD(squareFp6BN254_c2_y) + A :MSTORE(inverseFp12BN254_a1square2_x) + B :MSTORE(inverseFp12BN254_a1square2_y) + $ => A :MLOAD(squareFp6BN254_c3_x) + $ => B :MLOAD(squareFp6BN254_c3_y) + A :MSTORE(inverseFp12BN254_a1square3_x) + B :MSTORE(inverseFp12BN254_a1square3_y) + + ; 2] a2² + $ => A :MLOAD(inverseFp12BN254_a21_x) + $ => B :MLOAD(inverseFp12BN254_a21_y) + A :MSTORE(squareFp6BN254_a1_x) + B :MSTORE(squareFp6BN254_a1_y) + $ => A :MLOAD(inverseFp12BN254_a22_x) + $ => B :MLOAD(inverseFp12BN254_a22_y) + A :MSTORE(squareFp6BN254_a2_x) + B :MSTORE(squareFp6BN254_a2_y) + $ => A :MLOAD(inverseFp12BN254_a23_x) + $ => B :MLOAD(inverseFp12BN254_a23_y) + A :MSTORE(squareFp6BN254_a3_x) + B :MSTORE(squareFp6BN254_a3_y), CALL(squareFp6BN254) + $ => A :MLOAD(squareFp6BN254_c1_x) + $ => B :MLOAD(squareFp6BN254_c1_y) + A :MSTORE(inverseFp12BN254_a2square1_x) + B :MSTORE(inverseFp12BN254_a2square1_y) + $ => A :MLOAD(squareFp6BN254_c2_x) + $ => B :MLOAD(squareFp6BN254_c2_y) + A :MSTORE(inverseFp12BN254_a2square2_x) + B :MSTORE(inverseFp12BN254_a2square2_y) + $ => A :MLOAD(squareFp6BN254_c3_x) + $ => B :MLOAD(squareFp6BN254_c3_y) + A :MSTORE(inverseFp12BN254_a2square3_x) + B :MSTORE(inverseFp12BN254_a2square3_y) + + ; 3] (a1² - v·a2²)⁻¹ + $ => A :MLOAD(inverseFp12BN254_a2square1_x) + $ => B :MLOAD(inverseFp12BN254_a2square1_y) + A :MSTORE(sparseMulAFp6BN254_a1_x) + B :MSTORE(sparseMulAFp6BN254_a1_y) + $ => A :MLOAD(inverseFp12BN254_a2square2_x) + $ => B :MLOAD(inverseFp12BN254_a2square2_y) + A :MSTORE(sparseMulAFp6BN254_a2_x) + B :MSTORE(sparseMulAFp6BN254_a2_y) + $ => A :MLOAD(inverseFp12BN254_a2square3_x) + $ => B :MLOAD(inverseFp12BN254_a2square3_y) + A :MSTORE(sparseMulAFp6BN254_a3_x) + B :MSTORE(sparseMulAFp6BN254_a3_y) + 1n :MSTORE(sparseMulAFp6BN254_b2_x) + 0n :MSTORE(sparseMulAFp6BN254_b2_y), CALL(sparseMulAFp6BN254) + $ => A :MLOAD(sparseMulAFp6BN254_c1_x) + $ => B :MLOAD(sparseMulAFp6BN254_c1_y) + A :MSTORE(inverseFp12BN254_va2square1_x) + B :MSTORE(inverseFp12BN254_va2square1_y) + $ => A :MLOAD(sparseMulAFp6BN254_c2_x) + $ => B :MLOAD(sparseMulAFp6BN254_c2_y) + A :MSTORE(inverseFp12BN254_va2square2_x) + B :MSTORE(inverseFp12BN254_va2square2_y) + $ => A :MLOAD(sparseMulAFp6BN254_c3_x) + $ => B :MLOAD(sparseMulAFp6BN254_c3_y) + A :MSTORE(inverseFp12BN254_va2square3_x) + B :MSTORE(inverseFp12BN254_va2square3_y) + + $ => A :MLOAD(inverseFp12BN254_a1square1_x) + $ => B :MLOAD(inverseFp12BN254_a1square1_y) + A :MSTORE(subFp6BN254_a1_x) + B :MSTORE(subFp6BN254_a1_y) + $ => A :MLOAD(inverseFp12BN254_a1square2_x) + $ => B :MLOAD(inverseFp12BN254_a1square2_y) + A :MSTORE(subFp6BN254_a2_x) + B :MSTORE(subFp6BN254_a2_y) + $ => A :MLOAD(inverseFp12BN254_a1square3_x) + $ => B :MLOAD(inverseFp12BN254_a1square3_y) + A :MSTORE(subFp6BN254_a3_x) + B :MSTORE(subFp6BN254_a3_y) + $ => A :MLOAD(inverseFp12BN254_va2square1_x) + $ => B :MLOAD(inverseFp12BN254_va2square1_y) + A :MSTORE(subFp6BN254_b1_x) + B :MSTORE(subFp6BN254_b1_y) + $ => A :MLOAD(inverseFp12BN254_va2square2_x) + $ => B :MLOAD(inverseFp12BN254_va2square2_y) + A :MSTORE(subFp6BN254_b2_x) + B :MSTORE(subFp6BN254_b2_y) + $ => A :MLOAD(inverseFp12BN254_va2square3_x) + $ => B :MLOAD(inverseFp12BN254_va2square3_y) + A :MSTORE(subFp6BN254_b3_x) + B :MSTORE(subFp6BN254_b3_y), CALL(subFp6BN254) + $ => A :MLOAD(subFp6BN254_c1_x) + $ => B :MLOAD(subFp6BN254_c1_y) + A :MSTORE(inverseFp6BN254_a1_x) + B :MSTORE(inverseFp6BN254_a1_y) + $ => A :MLOAD(subFp6BN254_c2_x) + $ => B :MLOAD(subFp6BN254_c2_y) + A :MSTORE(inverseFp6BN254_a2_x) + B :MSTORE(inverseFp6BN254_a2_y) + $ => A :MLOAD(subFp6BN254_c3_x) + $ => B :MLOAD(subFp6BN254_c3_y) + A :MSTORE(inverseFp6BN254_a3_x) + B :MSTORE(inverseFp6BN254_a3_y), CALL(inverseFp6BN254) + $ => A :MLOAD(inverseFp6BN254_c1_x) + $ => B :MLOAD(inverseFp6BN254_c1_y) + A :MSTORE(inverseFp12BN254_final1_x) + B :MSTORE(inverseFp12BN254_final1_y) + $ => A :MLOAD(inverseFp6BN254_c2_x) + $ => B :MLOAD(inverseFp6BN254_c2_y) + A :MSTORE(inverseFp12BN254_final2_x) + B :MSTORE(inverseFp12BN254_final2_y) + $ => A :MLOAD(inverseFp6BN254_c3_x) + $ => B :MLOAD(inverseFp6BN254_c3_y) + A :MSTORE(inverseFp12BN254_final3_x) + B :MSTORE(inverseFp12BN254_final3_y) + + ; 4] c1 = a1·(a1² - a2²·v)⁻¹ + $ => A :MLOAD(inverseFp12BN254_a11_x) + $ => B :MLOAD(inverseFp12BN254_a11_y) + A :MSTORE(mulFp6BN254_a1_x) + B :MSTORE(mulFp6BN254_a1_y) + $ => A :MLOAD(inverseFp12BN254_a12_x) + $ => B :MLOAD(inverseFp12BN254_a12_y) + A :MSTORE(mulFp6BN254_a2_x) + B :MSTORE(mulFp6BN254_a2_y) + $ => A :MLOAD(inverseFp12BN254_a13_x) + $ => B :MLOAD(inverseFp12BN254_a13_y) + A :MSTORE(mulFp6BN254_a3_x) + B :MSTORE(mulFp6BN254_a3_y) + $ => A :MLOAD(inverseFp12BN254_final1_x) + $ => B :MLOAD(inverseFp12BN254_final1_y) + A :MSTORE(mulFp6BN254_b1_x) + B :MSTORE(mulFp6BN254_b1_y) + $ => A :MLOAD(inverseFp12BN254_final2_x) + $ => B :MLOAD(inverseFp12BN254_final2_y) + A :MSTORE(mulFp6BN254_b2_x) + B :MSTORE(mulFp6BN254_b2_y) + $ => A :MLOAD(inverseFp12BN254_final3_x) + $ => B :MLOAD(inverseFp12BN254_final3_y) + A :MSTORE(mulFp6BN254_b3_x) + B :MSTORE(mulFp6BN254_b3_y), CALL(mulFp6BN254) + $ => A :MLOAD(mulFp6BN254_c1_x) + $ => B :MLOAD(mulFp6BN254_c1_y) + A :MSTORE(inverseFp12BN254_c11_x) + B :MSTORE(inverseFp12BN254_c11_y) + $ => A :MLOAD(mulFp6BN254_c2_x) + $ => B :MLOAD(mulFp6BN254_c2_y) + A :MSTORE(inverseFp12BN254_c12_x) + B :MSTORE(inverseFp12BN254_c12_y) + $ => A :MLOAD(mulFp6BN254_c3_x) + $ => B :MLOAD(mulFp6BN254_c3_y) + A :MSTORE(inverseFp12BN254_c13_x) + B :MSTORE(inverseFp12BN254_c13_y) + + ; 4] c2 = -a2·(a1² - a2²·v)⁻¹ + %BN254_P => A + $ => B :MLOAD(inverseFp12BN254_a21_x) + $ :SUB, MSTORE(mulFp6BN254_a1_x) + %BN254_P => A + $ => B :MLOAD(inverseFp12BN254_a21_y) + $ :SUB, MSTORE(mulFp6BN254_a1_y) + %BN254_P => A + $ => B :MLOAD(inverseFp12BN254_a22_x) + $ :SUB, MSTORE(mulFp6BN254_a2_x) + %BN254_P => A + $ => B :MLOAD(inverseFp12BN254_a22_y) + $ :SUB, MSTORE(mulFp6BN254_a2_y) + %BN254_P => A + $ => B :MLOAD(inverseFp12BN254_a23_x) + $ :SUB, MSTORE(mulFp6BN254_a3_x) + %BN254_P => A + $ => B :MLOAD(inverseFp12BN254_a23_y) + $ :SUB, MSTORE(mulFp6BN254_a3_y) + + $ => A :MLOAD(inverseFp12BN254_final1_x) + $ => B :MLOAD(inverseFp12BN254_final1_y) + A :MSTORE(mulFp6BN254_b1_x) + B :MSTORE(mulFp6BN254_b1_y) + $ => A :MLOAD(inverseFp12BN254_final2_x) + $ => B :MLOAD(inverseFp12BN254_final2_y) + A :MSTORE(mulFp6BN254_b2_x) + B :MSTORE(mulFp6BN254_b2_y) + $ => A :MLOAD(inverseFp12BN254_final3_x) + $ => B :MLOAD(inverseFp12BN254_final3_y) + A :MSTORE(mulFp6BN254_b3_x) + B :MSTORE(mulFp6BN254_b3_y), CALL(mulFp6BN254) + $ => A :MLOAD(mulFp6BN254_c1_x) + $ => B :MLOAD(mulFp6BN254_c1_y) + A :MSTORE(inverseFp12BN254_c21_x) + B :MSTORE(inverseFp12BN254_c21_y) + $ => A :MLOAD(mulFp6BN254_c2_x) + $ => B :MLOAD(mulFp6BN254_c2_y) + A :MSTORE(inverseFp12BN254_c22_x) + B :MSTORE(inverseFp12BN254_c22_y) + $ => A :MLOAD(mulFp6BN254_c3_x) + $ => B :MLOAD(mulFp6BN254_c3_y) + A :MSTORE(inverseFp12BN254_c23_x) + B :MSTORE(inverseFp12BN254_c23_y) + + + $ => RR :MLOAD(inverseFp12BN254_RR) + :RETURN \ No newline at end of file diff --git a/main/pairings/FP12BN254/mulFp12BN254.zkasm b/main/pairings/FP12BN254/mulFp12BN254.zkasm new file mode 100644 index 00000000..6d721c1e --- /dev/null +++ b/main/pairings/FP12BN254/mulFp12BN254.zkasm @@ -0,0 +1,408 @@ +;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; POST: The result is in the range [0,BN254_P) because if falls back to FP6 arithmetic +;; +;; mulFp12BN254: +;; in: (a1 + a2·w),(b1 + b2·w) ∈ Fp12, where ai,bi ∈ Fp6 +;; out: (a1 + a2·w)·(b1 + b2·w) = (c1 + c2·w) ∈ Fp12, where: +;; - c1 = a1·b1 + a2·b2·v +;; - c2 = (a1+a2)·(b1+b2) - a1·b1 - a2·b2 +;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +VAR GLOBAL mulFp12BN254_a11_x +VAR GLOBAL mulFp12BN254_a11_y +VAR GLOBAL mulFp12BN254_a12_x +VAR GLOBAL mulFp12BN254_a12_y +VAR GLOBAL mulFp12BN254_a13_x +VAR GLOBAL mulFp12BN254_a13_y +VAR GLOBAL mulFp12BN254_a21_x +VAR GLOBAL mulFp12BN254_a21_y +VAR GLOBAL mulFp12BN254_a22_x +VAR GLOBAL mulFp12BN254_a22_y +VAR GLOBAL mulFp12BN254_a23_x +VAR GLOBAL mulFp12BN254_a23_y +VAR GLOBAL mulFp12BN254_b11_x +VAR GLOBAL mulFp12BN254_b11_y +VAR GLOBAL mulFp12BN254_b12_x +VAR GLOBAL mulFp12BN254_b12_y +VAR GLOBAL mulFp12BN254_b13_x +VAR GLOBAL mulFp12BN254_b13_y +VAR GLOBAL mulFp12BN254_b21_x +VAR GLOBAL mulFp12BN254_b21_y +VAR GLOBAL mulFp12BN254_b22_x +VAR GLOBAL mulFp12BN254_b22_y +VAR GLOBAL mulFp12BN254_b23_x +VAR GLOBAL mulFp12BN254_b23_y +VAR GLOBAL mulFp12BN254_c11_x +VAR GLOBAL mulFp12BN254_c11_y +VAR GLOBAL mulFp12BN254_c12_x +VAR GLOBAL mulFp12BN254_c12_y +VAR GLOBAL mulFp12BN254_c13_x +VAR GLOBAL mulFp12BN254_c13_y +VAR GLOBAL mulFp12BN254_c21_x +VAR GLOBAL mulFp12BN254_c21_y +VAR GLOBAL mulFp12BN254_c22_x +VAR GLOBAL mulFp12BN254_c22_y +VAR GLOBAL mulFp12BN254_c23_x +VAR GLOBAL mulFp12BN254_c23_y + +VAR GLOBAL mulFp12BN254_a1b1mul1_x +VAR GLOBAL mulFp12BN254_a1b1mul1_y +VAR GLOBAL mulFp12BN254_a1b1mul2_x +VAR GLOBAL mulFp12BN254_a1b1mul2_y +VAR GLOBAL mulFp12BN254_a1b1mul3_x +VAR GLOBAL mulFp12BN254_a1b1mul3_y +VAR GLOBAL mulFp12BN254_a2b2mul1_x +VAR GLOBAL mulFp12BN254_a2b2mul1_y +VAR GLOBAL mulFp12BN254_a2b2mul2_x +VAR GLOBAL mulFp12BN254_a2b2mul2_y +VAR GLOBAL mulFp12BN254_a2b2mul3_x +VAR GLOBAL mulFp12BN254_a2b2mul3_y +VAR GLOBAL mulFp12BN254_a2b2vmul1_x +VAR GLOBAL mulFp12BN254_a2b2vmul1_y +VAR GLOBAL mulFp12BN254_a2b2vmul2_x +VAR GLOBAL mulFp12BN254_a2b2vmul2_y +VAR GLOBAL mulFp12BN254_a2b2vmul3_x +VAR GLOBAL mulFp12BN254_a2b2vmul3_y + +VAR GLOBAL mulFp12BN254_a1a2sum1_x +VAR GLOBAL mulFp12BN254_a1a2sum1_y +VAR GLOBAL mulFp12BN254_a1a2sum2_x +VAR GLOBAL mulFp12BN254_a1a2sum2_y +VAR GLOBAL mulFp12BN254_a1a2sum3_x +VAR GLOBAL mulFp12BN254_a1a2sum3_y +VAR GLOBAL mulFp12BN254_b1b2sum1_x +VAR GLOBAL mulFp12BN254_b1b2sum1_y +VAR GLOBAL mulFp12BN254_b1b2sum2_x +VAR GLOBAL mulFp12BN254_b1b2sum2_y +VAR GLOBAL mulFp12BN254_b1b2sum3_x +VAR GLOBAL mulFp12BN254_b1b2sum3_y + +VAR GLOBAL mulFp12BN254_RR + +mulFp12BN254: + RR :MSTORE(mulFp12BN254_RR) + + ; 1] a1·b1 + $ => A :MLOAD(mulFp12BN254_a11_x) + $ => B :MLOAD(mulFp12BN254_a11_y) + A :MSTORE(mulFp6BN254_a1_x) + B :MSTORE(mulFp6BN254_a1_y) + $ => A :MLOAD(mulFp12BN254_a12_x) + $ => B :MLOAD(mulFp12BN254_a12_y) + A :MSTORE(mulFp6BN254_a2_x) + B :MSTORE(mulFp6BN254_a2_y) + $ => A :MLOAD(mulFp12BN254_a13_x) + $ => B :MLOAD(mulFp12BN254_a13_y) + A :MSTORE(mulFp6BN254_a3_x) + B :MSTORE(mulFp6BN254_a3_y) + + $ => A :MLOAD(mulFp12BN254_b11_x) + $ => B :MLOAD(mulFp12BN254_b11_y) + A :MSTORE(mulFp6BN254_b1_x) + B :MSTORE(mulFp6BN254_b1_y) + $ => A :MLOAD(mulFp12BN254_b12_x) + $ => B :MLOAD(mulFp12BN254_b12_y) + A :MSTORE(mulFp6BN254_b2_x) + B :MSTORE(mulFp6BN254_b2_y) + $ => A :MLOAD(mulFp12BN254_b13_x) + $ => B :MLOAD(mulFp12BN254_b13_y) + A :MSTORE(mulFp6BN254_b3_x) + B :MSTORE(mulFp6BN254_b3_y), CALL(mulFp6BN254) + $ => A :MLOAD(mulFp6BN254_c1_x) + $ => B :MLOAD(mulFp6BN254_c1_y) + A :MSTORE(mulFp12BN254_a1b1mul1_x) + B :MSTORE(mulFp12BN254_a1b1mul1_y) + $ => A :MLOAD(mulFp6BN254_c2_x) + $ => B :MLOAD(mulFp6BN254_c2_y) + A :MSTORE(mulFp12BN254_a1b1mul2_x) + B :MSTORE(mulFp12BN254_a1b1mul2_y) + $ => A :MLOAD(mulFp6BN254_c3_x) + $ => B :MLOAD(mulFp6BN254_c3_y) + A :MSTORE(mulFp12BN254_a1b1mul3_x) + B :MSTORE(mulFp12BN254_a1b1mul3_y) + + ; 2] a2·b2 + $ => A :MLOAD(mulFp12BN254_a21_x) + $ => B :MLOAD(mulFp12BN254_a21_y) + A :MSTORE(mulFp6BN254_a1_x) + B :MSTORE(mulFp6BN254_a1_y) + $ => A :MLOAD(mulFp12BN254_a22_x) + $ => B :MLOAD(mulFp12BN254_a22_y) + A :MSTORE(mulFp6BN254_a2_x) + B :MSTORE(mulFp6BN254_a2_y) + $ => A :MLOAD(mulFp12BN254_a23_x) + $ => B :MLOAD(mulFp12BN254_a23_y) + A :MSTORE(mulFp6BN254_a3_x) + B :MSTORE(mulFp6BN254_a3_y) + + $ => A :MLOAD(mulFp12BN254_b21_x) + $ => B :MLOAD(mulFp12BN254_b21_y) + A :MSTORE(mulFp6BN254_b1_x) + B :MSTORE(mulFp6BN254_b1_y) + $ => A :MLOAD(mulFp12BN254_b22_x) + $ => B :MLOAD(mulFp12BN254_b22_y) + A :MSTORE(mulFp6BN254_b2_x) + B :MSTORE(mulFp6BN254_b2_y) + $ => A :MLOAD(mulFp12BN254_b23_x) + $ => B :MLOAD(mulFp12BN254_b23_y) + A :MSTORE(mulFp6BN254_b3_x) + B :MSTORE(mulFp6BN254_b3_y), CALL(mulFp6BN254) + $ => A :MLOAD(mulFp6BN254_c1_x) + $ => B :MLOAD(mulFp6BN254_c1_y) + A :MSTORE(mulFp12BN254_a2b2mul1_x) + B :MSTORE(mulFp12BN254_a2b2mul1_y) + $ => A :MLOAD(mulFp6BN254_c2_x) + $ => B :MLOAD(mulFp6BN254_c2_y) + A :MSTORE(mulFp12BN254_a2b2mul2_x) + B :MSTORE(mulFp12BN254_a2b2mul2_y) + $ => A :MLOAD(mulFp6BN254_c3_x) + $ => B :MLOAD(mulFp6BN254_c3_y) + A :MSTORE(mulFp12BN254_a2b2mul3_x) + B :MSTORE(mulFp12BN254_a2b2mul3_y) + + ; 3] a2·b2·v + $ => A :MLOAD(mulFp12BN254_a2b2mul1_x) + $ => B :MLOAD(mulFp12BN254_a2b2mul1_y) + A :MSTORE(sparseMulAFp6BN254_a1_x) + B :MSTORE(sparseMulAFp6BN254_a1_y) + $ => A :MLOAD(mulFp12BN254_a2b2mul2_x) + $ => B :MLOAD(mulFp12BN254_a2b2mul2_y) + A :MSTORE(sparseMulAFp6BN254_a2_x) + B :MSTORE(sparseMulAFp6BN254_a2_y) + $ => A :MLOAD(mulFp12BN254_a2b2mul3_x) + $ => B :MLOAD(mulFp12BN254_a2b2mul3_y) + A :MSTORE(sparseMulAFp6BN254_a3_x) + B :MSTORE(sparseMulAFp6BN254_a3_y) + + 1n :MSTORE(sparseMulAFp6BN254_b2_x) + 0n :MSTORE(sparseMulAFp6BN254_b2_y), CALL(sparseMulAFp6BN254) + $ => A :MLOAD(sparseMulAFp6BN254_c1_x) + $ => B :MLOAD(sparseMulAFp6BN254_c1_y) + A :MSTORE(mulFp12BN254_a2b2vmul1_x) + B :MSTORE(mulFp12BN254_a2b2vmul1_y) + $ => A :MLOAD(sparseMulAFp6BN254_c2_x) + $ => B :MLOAD(sparseMulAFp6BN254_c2_y) + A :MSTORE(mulFp12BN254_a2b2vmul2_x) + B :MSTORE(mulFp12BN254_a2b2vmul2_y) + $ => A :MLOAD(sparseMulAFp6BN254_c3_x) + $ => B :MLOAD(sparseMulAFp6BN254_c3_y) + A :MSTORE(mulFp12BN254_a2b2vmul3_x) + B :MSTORE(mulFp12BN254_a2b2vmul3_y) + + ; 4] c1 = a1·b1 + a2·b2·v + $ => A :MLOAD(mulFp12BN254_a1b1mul1_x) + $ => B :MLOAD(mulFp12BN254_a1b1mul1_y) + A :MSTORE(addFp6BN254_a1_x) + B :MSTORE(addFp6BN254_a1_y) + $ => A :MLOAD(mulFp12BN254_a1b1mul2_x) + $ => B :MLOAD(mulFp12BN254_a1b1mul2_y) + A :MSTORE(addFp6BN254_a2_x) + B :MSTORE(addFp6BN254_a2_y) + $ => A :MLOAD(mulFp12BN254_a1b1mul3_x) + $ => B :MLOAD(mulFp12BN254_a1b1mul3_y) + A :MSTORE(addFp6BN254_a3_x) + B :MSTORE(addFp6BN254_a3_y) + + $ => A :MLOAD(mulFp12BN254_a2b2vmul1_x) + $ => B :MLOAD(mulFp12BN254_a2b2vmul1_y) + A :MSTORE(addFp6BN254_b1_x) + B :MSTORE(addFp6BN254_b1_y) + $ => A :MLOAD(mulFp12BN254_a2b2vmul2_x) + $ => B :MLOAD(mulFp12BN254_a2b2vmul2_y) + A :MSTORE(addFp6BN254_b2_x) + B :MSTORE(addFp6BN254_b2_y) + $ => A :MLOAD(mulFp12BN254_a2b2vmul3_x) + $ => B :MLOAD(mulFp12BN254_a2b2vmul3_y) + A :MSTORE(addFp6BN254_b3_x) + B :MSTORE(addFp6BN254_b3_y), CALL(addFp6BN254) + + $ => A :MLOAD(addFp6BN254_c1_x) + $ => B :MLOAD(addFp6BN254_c1_y) + A :MSTORE(mulFp12BN254_c11_x) + B :MSTORE(mulFp12BN254_c11_y) + $ => A :MLOAD(addFp6BN254_c2_x) + $ => B :MLOAD(addFp6BN254_c2_y) + A :MSTORE(mulFp12BN254_c12_x) + B :MSTORE(mulFp12BN254_c12_y) + $ => A :MLOAD(addFp6BN254_c3_x) + $ => B :MLOAD(addFp6BN254_c3_y) + A :MSTORE(mulFp12BN254_c13_x) + B :MSTORE(mulFp12BN254_c13_y) + + ; 4] a1+a2 + $ => A :MLOAD(mulFp12BN254_a11_x) + $ => B :MLOAD(mulFp12BN254_a11_y) + A :MSTORE(addFp6BN254_a1_x) + B :MSTORE(addFp6BN254_a1_y) + $ => A :MLOAD(mulFp12BN254_a12_x) + $ => B :MLOAD(mulFp12BN254_a12_y) + A :MSTORE(addFp6BN254_a2_x) + B :MSTORE(addFp6BN254_a2_y) + $ => A :MLOAD(mulFp12BN254_a13_x) + $ => B :MLOAD(mulFp12BN254_a13_y) + A :MSTORE(addFp6BN254_a3_x) + B :MSTORE(addFp6BN254_a3_y) + + $ => A :MLOAD(mulFp12BN254_a21_x) + $ => B :MLOAD(mulFp12BN254_a21_y) + A :MSTORE(addFp6BN254_b1_x) + B :MSTORE(addFp6BN254_b1_y) + $ => A :MLOAD(mulFp12BN254_a22_x) + $ => B :MLOAD(mulFp12BN254_a22_y) + A :MSTORE(addFp6BN254_b2_x) + B :MSTORE(addFp6BN254_b2_y) + $ => A :MLOAD(mulFp12BN254_a23_x) + $ => B :MLOAD(mulFp12BN254_a23_y) + A :MSTORE(addFp6BN254_b3_x) + B :MSTORE(addFp6BN254_b3_y), CALL(addFp6BN254) + + $ => A :MLOAD(addFp6BN254_c1_x) + $ => B :MLOAD(addFp6BN254_c1_y) + A :MSTORE(mulFp12BN254_a1a2sum1_x) + B :MSTORE(mulFp12BN254_a1a2sum1_y) + $ => A :MLOAD(addFp6BN254_c2_x) + $ => B :MLOAD(addFp6BN254_c2_y) + A :MSTORE(mulFp12BN254_a1a2sum2_x) + B :MSTORE(mulFp12BN254_a1a2sum2_y) + $ => A :MLOAD(addFp6BN254_c3_x) + $ => B :MLOAD(addFp6BN254_c3_y) + A :MSTORE(mulFp12BN254_a1a2sum3_x) + B :MSTORE(mulFp12BN254_a1a2sum3_y) + + + ; 5] b1+b2 + $ => A :MLOAD(mulFp12BN254_b11_x) + $ => B :MLOAD(mulFp12BN254_b11_y) + A :MSTORE(addFp6BN254_a1_x) + B :MSTORE(addFp6BN254_a1_y) + $ => A :MLOAD(mulFp12BN254_b12_x) + $ => B :MLOAD(mulFp12BN254_b12_y) + A :MSTORE(addFp6BN254_a2_x) + B :MSTORE(addFp6BN254_a2_y) + $ => A :MLOAD(mulFp12BN254_b13_x) + $ => B :MLOAD(mulFp12BN254_b13_y) + A :MSTORE(addFp6BN254_a3_x) + B :MSTORE(addFp6BN254_a3_y) + + $ => A :MLOAD(mulFp12BN254_b21_x) + $ => B :MLOAD(mulFp12BN254_b21_y) + A :MSTORE(addFp6BN254_b1_x) + B :MSTORE(addFp6BN254_b1_y) + $ => A :MLOAD(mulFp12BN254_b22_x) + $ => B :MLOAD(mulFp12BN254_b22_y) + A :MSTORE(addFp6BN254_b2_x) + B :MSTORE(addFp6BN254_b2_y) + $ => A :MLOAD(mulFp12BN254_b23_x) + $ => B :MLOAD(mulFp12BN254_b23_y) + A :MSTORE(addFp6BN254_b3_x) + B :MSTORE(addFp6BN254_b3_y), CALL(addFp6BN254) + + $ => A :MLOAD(addFp6BN254_c1_x) + $ => B :MLOAD(addFp6BN254_c1_y) + A :MSTORE(mulFp12BN254_b1b2sum1_x) + B :MSTORE(mulFp12BN254_b1b2sum1_y) + $ => A :MLOAD(addFp6BN254_c2_x) + $ => B :MLOAD(addFp6BN254_c2_y) + A :MSTORE(mulFp12BN254_b1b2sum2_x) + B :MSTORE(mulFp12BN254_b1b2sum2_y) + $ => A :MLOAD(addFp6BN254_c3_x) + $ => B :MLOAD(addFp6BN254_c3_y) + A :MSTORE(mulFp12BN254_b1b2sum3_x) + B :MSTORE(mulFp12BN254_b1b2sum3_y) + + ; 7] c2 = (a1+a2)·(b1+b2) - a1·b1 - a2·b2 + $ => A :MLOAD(mulFp12BN254_a1a2sum1_x) + $ => B :MLOAD(mulFp12BN254_a1a2sum1_y) + A :MSTORE(mulFp6BN254_a1_x) + B :MSTORE(mulFp6BN254_a1_y) + $ => A :MLOAD(mulFp12BN254_a1a2sum2_x) + $ => B :MLOAD(mulFp12BN254_a1a2sum2_y) + A :MSTORE(mulFp6BN254_a2_x) + B :MSTORE(mulFp6BN254_a2_y) + $ => A :MLOAD(mulFp12BN254_a1a2sum3_x) + $ => B :MLOAD(mulFp12BN254_a1a2sum3_y) + A :MSTORE(mulFp6BN254_a3_x) + B :MSTORE(mulFp6BN254_a3_y) + + + $ => A :MLOAD(mulFp12BN254_b1b2sum1_x) + $ => B :MLOAD(mulFp12BN254_b1b2sum1_y) + A :MSTORE(mulFp6BN254_b1_x) + B :MSTORE(mulFp6BN254_b1_y) + $ => A :MLOAD(mulFp12BN254_b1b2sum2_x) + $ => B :MLOAD(mulFp12BN254_b1b2sum2_y) + A :MSTORE(mulFp6BN254_b2_x) + B :MSTORE(mulFp6BN254_b2_y) + $ => A :MLOAD(mulFp12BN254_b1b2sum3_x) + $ => B :MLOAD(mulFp12BN254_b1b2sum3_y) + A :MSTORE(mulFp6BN254_b3_x) + B :MSTORE(mulFp6BN254_b3_y), CALL(mulFp6BN254) + + $ => A :MLOAD(mulFp6BN254_c1_x) + $ => B :MLOAD(mulFp6BN254_c1_y) + A :MSTORE(subFp6BN254_a1_x) + B :MSTORE(subFp6BN254_a1_y) + $ => A :MLOAD(mulFp6BN254_c2_x) + $ => B :MLOAD(mulFp6BN254_c2_y) + A :MSTORE(subFp6BN254_a2_x) + B :MSTORE(subFp6BN254_a2_y) + $ => A :MLOAD(mulFp6BN254_c3_x) + $ => B :MLOAD(mulFp6BN254_c3_y) + A :MSTORE(subFp6BN254_a3_x) + B :MSTORE(subFp6BN254_a3_y) + + $ => A :MLOAD(mulFp12BN254_a1b1mul1_x) + $ => B :MLOAD(mulFp12BN254_a1b1mul1_y) + A :MSTORE(subFp6BN254_b1_x) + B :MSTORE(subFp6BN254_b1_y) + $ => A :MLOAD(mulFp12BN254_a1b1mul2_x) + $ => B :MLOAD(mulFp12BN254_a1b1mul2_y) + A :MSTORE(subFp6BN254_b2_x) + B :MSTORE(subFp6BN254_b2_y) + $ => A :MLOAD(mulFp12BN254_a1b1mul3_x) + $ => B :MLOAD(mulFp12BN254_a1b1mul3_y) + A :MSTORE(subFp6BN254_b3_x) + B :MSTORE(subFp6BN254_b3_y), CALL(subFp6BN254) + + $ => A :MLOAD(subFp6BN254_c1_x) + $ => B :MLOAD(subFp6BN254_c1_y) + A :MSTORE(subFp6BN254_a1_x) + B :MSTORE(subFp6BN254_a1_y) + $ => A :MLOAD(subFp6BN254_c2_x) + $ => B :MLOAD(subFp6BN254_c2_y) + A :MSTORE(subFp6BN254_a2_x) + B :MSTORE(subFp6BN254_a2_y) + $ => A :MLOAD(subFp6BN254_c3_x) + $ => B :MLOAD(subFp6BN254_c3_y) + A :MSTORE(subFp6BN254_a3_x) + B :MSTORE(subFp6BN254_a3_y) + + $ => A :MLOAD(mulFp12BN254_a2b2mul1_x) + $ => B :MLOAD(mulFp12BN254_a2b2mul1_y) + A :MSTORE(subFp6BN254_b1_x) + B :MSTORE(subFp6BN254_b1_y) + $ => A :MLOAD(mulFp12BN254_a2b2mul2_x) + $ => B :MLOAD(mulFp12BN254_a2b2mul2_y) + A :MSTORE(subFp6BN254_b2_x) + B :MSTORE(subFp6BN254_b2_y) + $ => A :MLOAD(mulFp12BN254_a2b2mul3_x) + $ => B :MLOAD(mulFp12BN254_a2b2mul3_y) + A :MSTORE(subFp6BN254_b3_x) + B :MSTORE(subFp6BN254_b3_y), CALL(subFp6BN254) + + $ => A :MLOAD(subFp6BN254_c1_x) + $ => B :MLOAD(subFp6BN254_c1_y) + A :MSTORE(mulFp12BN254_c21_x) + B :MSTORE(mulFp12BN254_c21_y) + $ => A :MLOAD(subFp6BN254_c2_x) + $ => B :MLOAD(subFp6BN254_c2_y) + A :MSTORE(mulFp12BN254_c22_x) + B :MSTORE(mulFp12BN254_c22_y) + $ => A :MLOAD(subFp6BN254_c3_x) + $ => B :MLOAD(subFp6BN254_c3_y) + A :MSTORE(mulFp12BN254_c23_x) + B :MSTORE(mulFp12BN254_c23_y) + + $ => RR :MLOAD(mulFp12BN254_RR) + :RETURN \ No newline at end of file diff --git a/main/pairings/FP12BN254/sparseMulAFp12BN254.zkasm b/main/pairings/FP12BN254/sparseMulAFp12BN254.zkasm new file mode 100644 index 00000000..9646b0a3 --- /dev/null +++ b/main/pairings/FP12BN254/sparseMulAFp12BN254.zkasm @@ -0,0 +1,296 @@ +;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; POST: The result is in the range [0,BN254_P) because if falls back to FP6 arithmetic +;; +;; sparseMulAFp12BN254: +;; in: (a1 + a2·w),(b1 + b2·w) ∈ Fp12, where ai ∈ Fp6, b1 = b12·v and b2 = b22·v + b23·v², with b12,b22,b23 ∈ Fp2 +;; out: (a1 + a2·w)·(b1 + b2·w) = (c1 + c2·w) ∈ Fp12, where: +;; - c1 = a1·b1 + a2·b2·v +;; - c2 = (a1+a2)·[(b12+b22)·v + b23·v²] - a1·b1 - a2·b2 +;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +VAR GLOBAL sparseMulAFp12BN254_a11_x +VAR GLOBAL sparseMulAFp12BN254_a11_y +VAR GLOBAL sparseMulAFp12BN254_a12_x +VAR GLOBAL sparseMulAFp12BN254_a12_y +VAR GLOBAL sparseMulAFp12BN254_a13_x +VAR GLOBAL sparseMulAFp12BN254_a13_y +VAR GLOBAL sparseMulAFp12BN254_a21_x +VAR GLOBAL sparseMulAFp12BN254_a21_y +VAR GLOBAL sparseMulAFp12BN254_a22_x +VAR GLOBAL sparseMulAFp12BN254_a22_y +VAR GLOBAL sparseMulAFp12BN254_a23_x +VAR GLOBAL sparseMulAFp12BN254_a23_y + +VAR GLOBAL sparseMulAFp12BN254_b12_x +VAR GLOBAL sparseMulAFp12BN254_b12_y +VAR GLOBAL sparseMulAFp12BN254_b22_x +VAR GLOBAL sparseMulAFp12BN254_b22_y +VAR GLOBAL sparseMulAFp12BN254_b23_x +VAR GLOBAL sparseMulAFp12BN254_b23_y + +VAR GLOBAL sparseMulAFp12BN254_c11_x +VAR GLOBAL sparseMulAFp12BN254_c11_y +VAR GLOBAL sparseMulAFp12BN254_c12_x +VAR GLOBAL sparseMulAFp12BN254_c12_y +VAR GLOBAL sparseMulAFp12BN254_c13_x +VAR GLOBAL sparseMulAFp12BN254_c13_y +VAR GLOBAL sparseMulAFp12BN254_c21_x +VAR GLOBAL sparseMulAFp12BN254_c21_y +VAR GLOBAL sparseMulAFp12BN254_c22_x +VAR GLOBAL sparseMulAFp12BN254_c22_y +VAR GLOBAL sparseMulAFp12BN254_c23_x +VAR GLOBAL sparseMulAFp12BN254_c23_y + +VAR GLOBAL sparseMulAFp12BN254_a1b1mul1_x +VAR GLOBAL sparseMulAFp12BN254_a1b1mul1_y +VAR GLOBAL sparseMulAFp12BN254_a1b1mul2_x +VAR GLOBAL sparseMulAFp12BN254_a1b1mul2_y +VAR GLOBAL sparseMulAFp12BN254_a1b1mul3_x +VAR GLOBAL sparseMulAFp12BN254_a1b1mul3_y +VAR GLOBAL sparseMulAFp12BN254_a2b2mul1_x +VAR GLOBAL sparseMulAFp12BN254_a2b2mul1_y +VAR GLOBAL sparseMulAFp12BN254_a2b2mul2_x +VAR GLOBAL sparseMulAFp12BN254_a2b2mul2_y +VAR GLOBAL sparseMulAFp12BN254_a2b2mul3_x +VAR GLOBAL sparseMulAFp12BN254_a2b2mul3_y + +VAR GLOBAL sparseMulAFp12BN254_aux2_x +VAR GLOBAL sparseMulAFp12BN254_aux2_y + +VAR GLOBAL sparseMulAFp12BN254_RR + +sparseMulAFp12BN254: + RR :MSTORE(sparseMulAFp12BN254_RR) + + ; 1] a1·b1, a2·b2 + $ => A :MLOAD(sparseMulAFp12BN254_a11_x) + $ => B :MLOAD(sparseMulAFp12BN254_a11_y) + A :MSTORE(sparseMulAFp6BN254_a1_x) + B :MSTORE(sparseMulAFp6BN254_a1_y) + $ => A :MLOAD(sparseMulAFp12BN254_a12_x) + $ => B :MLOAD(sparseMulAFp12BN254_a12_y) + A :MSTORE(sparseMulAFp6BN254_a2_x) + B :MSTORE(sparseMulAFp6BN254_a2_y) + $ => A :MLOAD(sparseMulAFp12BN254_a13_x) + $ => B :MLOAD(sparseMulAFp12BN254_a13_y) + A :MSTORE(sparseMulAFp6BN254_a3_x) + B :MSTORE(sparseMulAFp6BN254_a3_y) + $ => A :MLOAD(sparseMulAFp12BN254_b12_x) + $ => B :MLOAD(sparseMulAFp12BN254_b12_y) + A :MSTORE(sparseMulAFp6BN254_b2_x) + B :MSTORE(sparseMulAFp6BN254_b2_y), CALL(sparseMulAFp6BN254) + $ => A :MLOAD(sparseMulAFp6BN254_c1_x) + $ => B :MLOAD(sparseMulAFp6BN254_c1_y) + A :MSTORE(sparseMulAFp12BN254_a1b1mul1_x) + B :MSTORE(sparseMulAFp12BN254_a1b1mul1_y) + $ => A :MLOAD(sparseMulAFp6BN254_c2_x) + $ => B :MLOAD(sparseMulAFp6BN254_c2_y) + A :MSTORE(sparseMulAFp12BN254_a1b1mul2_x) + B :MSTORE(sparseMulAFp12BN254_a1b1mul2_y) + $ => A :MLOAD(sparseMulAFp6BN254_c3_x) + $ => B :MLOAD(sparseMulAFp6BN254_c3_y) + A :MSTORE(sparseMulAFp12BN254_a1b1mul3_x) + B :MSTORE(sparseMulAFp12BN254_a1b1mul3_y) + + $ => A :MLOAD(sparseMulAFp12BN254_a21_x) + $ => B :MLOAD(sparseMulAFp12BN254_a21_y) + A :MSTORE(sparseMulBFp6BN254_a1_x) + B :MSTORE(sparseMulBFp6BN254_a1_y) + $ => A :MLOAD(sparseMulAFp12BN254_a22_x) + $ => B :MLOAD(sparseMulAFp12BN254_a22_y) + A :MSTORE(sparseMulBFp6BN254_a2_x) + B :MSTORE(sparseMulBFp6BN254_a2_y) + $ => A :MLOAD(sparseMulAFp12BN254_a23_x) + $ => B :MLOAD(sparseMulAFp12BN254_a23_y) + A :MSTORE(sparseMulBFp6BN254_a3_x) + B :MSTORE(sparseMulBFp6BN254_a3_y) + $ => A :MLOAD(sparseMulAFp12BN254_b22_x) + $ => B :MLOAD(sparseMulAFp12BN254_b22_y) + A :MSTORE(sparseMulBFp6BN254_b2_x) + B :MSTORE(sparseMulBFp6BN254_b2_y) + $ => A :MLOAD(sparseMulAFp12BN254_b23_x) + $ => B :MLOAD(sparseMulAFp12BN254_b23_y) + A :MSTORE(sparseMulBFp6BN254_b3_x) + B :MSTORE(sparseMulBFp6BN254_b3_y), CALL(sparseMulBFp6BN254) + $ => A :MLOAD(sparseMulBFp6BN254_c1_x) + $ => B :MLOAD(sparseMulBFp6BN254_c1_y) + A :MSTORE(sparseMulAFp12BN254_a2b2mul1_x) + B :MSTORE(sparseMulAFp12BN254_a2b2mul1_y) + $ => A :MLOAD(sparseMulBFp6BN254_c2_x) + $ => B :MLOAD(sparseMulBFp6BN254_c2_y) + A :MSTORE(sparseMulAFp12BN254_a2b2mul2_x) + B :MSTORE(sparseMulAFp12BN254_a2b2mul2_y) + $ => A :MLOAD(sparseMulBFp6BN254_c3_x) + $ => B :MLOAD(sparseMulBFp6BN254_c3_y) + A :MSTORE(sparseMulAFp12BN254_a2b2mul3_x) + B :MSTORE(sparseMulAFp12BN254_a2b2mul3_y) + + ; 2] c1 = a1·b1 + a2·b2·v + $ => A :MLOAD(sparseMulAFp12BN254_a2b2mul1_x) + $ => B :MLOAD(sparseMulAFp12BN254_a2b2mul1_y) + A :MSTORE(sparseMulAFp6BN254_a1_x) + B :MSTORE(sparseMulAFp6BN254_a1_y) + $ => A :MLOAD(sparseMulAFp12BN254_a2b2mul2_x) + $ => B :MLOAD(sparseMulAFp12BN254_a2b2mul2_y) + A :MSTORE(sparseMulAFp6BN254_a2_x) + B :MSTORE(sparseMulAFp6BN254_a2_y) + $ => A :MLOAD(sparseMulAFp12BN254_a2b2mul3_x) + $ => B :MLOAD(sparseMulAFp12BN254_a2b2mul3_y) + A :MSTORE(sparseMulAFp6BN254_a3_x) + B :MSTORE(sparseMulAFp6BN254_a3_y) + 1n :MSTORE(sparseMulAFp6BN254_b2_x) + 0n :MSTORE(sparseMulAFp6BN254_b2_y), CALL(sparseMulAFp6BN254) + $ => A :MLOAD(sparseMulAFp6BN254_c1_x) + $ => B :MLOAD(sparseMulAFp6BN254_c1_y) + A :MSTORE(addFp6BN254_a1_x) + B :MSTORE(addFp6BN254_a1_y) + $ => A :MLOAD(sparseMulAFp6BN254_c2_x) + $ => B :MLOAD(sparseMulAFp6BN254_c2_y) + A :MSTORE(addFp6BN254_a2_x) + B :MSTORE(addFp6BN254_a2_y) + $ => A :MLOAD(sparseMulAFp6BN254_c3_x) + $ => B :MLOAD(sparseMulAFp6BN254_c3_y) + A :MSTORE(addFp6BN254_a3_x) + B :MSTORE(addFp6BN254_a3_y) + $ => A :MLOAD(sparseMulAFp12BN254_a1b1mul1_x) + $ => B :MLOAD(sparseMulAFp12BN254_a1b1mul1_y) + A :MSTORE(addFp6BN254_b1_x) + B :MSTORE(addFp6BN254_b1_y) + $ => A :MLOAD(sparseMulAFp12BN254_a1b1mul2_x) + $ => B :MLOAD(sparseMulAFp12BN254_a1b1mul2_y) + A :MSTORE(addFp6BN254_b2_x) + B :MSTORE(addFp6BN254_b2_y) + $ => A :MLOAD(sparseMulAFp12BN254_a1b1mul3_x) + $ => B :MLOAD(sparseMulAFp12BN254_a1b1mul3_y) + A :MSTORE(addFp6BN254_b3_x) + B :MSTORE(addFp6BN254_b3_y), CALL(addFp6BN254) + $ => A :MLOAD(addFp6BN254_c1_x) + $ => B :MLOAD(addFp6BN254_c1_y) + A :MSTORE(sparseMulAFp12BN254_c11_x) + B :MSTORE(sparseMulAFp12BN254_c11_y) + $ => A :MLOAD(addFp6BN254_c2_x) + $ => B :MLOAD(addFp6BN254_c2_y) + A :MSTORE(sparseMulAFp12BN254_c12_x) + B :MSTORE(sparseMulAFp12BN254_c12_y) + $ => A :MLOAD(addFp6BN254_c3_x) + $ => B :MLOAD(addFp6BN254_c3_y) + A :MSTORE(sparseMulAFp12BN254_c13_x) + B :MSTORE(sparseMulAFp12BN254_c13_y) + + ; 3] aux = (b12+b22)·v + b23·v² + $ => A :MLOAD(sparseMulAFp12BN254_b12_x) + $ => B :MLOAD(sparseMulAFp12BN254_b12_y) + $ => C :MLOAD(sparseMulAFp12BN254_b22_x) + $ => D :MLOAD(sparseMulAFp12BN254_b22_y), CALL(addFp2BN254) + E :MSTORE(sparseMulAFp12BN254_aux2_x) + C :MSTORE(sparseMulAFp12BN254_aux2_y) + + ; 4] c2 = (a1+a2)·aux - a1·b1 - a2·b2 + $ => A :MLOAD(sparseMulAFp12BN254_a11_x) + $ => B :MLOAD(sparseMulAFp12BN254_a11_y) + A :MSTORE(addFp6BN254_a1_x) + B :MSTORE(addFp6BN254_a1_y) + $ => A :MLOAD(sparseMulAFp12BN254_a12_x) + $ => B :MLOAD(sparseMulAFp12BN254_a12_y) + A :MSTORE(addFp6BN254_a2_x) + B :MSTORE(addFp6BN254_a2_y) + $ => A :MLOAD(sparseMulAFp12BN254_a13_x) + $ => B :MLOAD(sparseMulAFp12BN254_a13_y) + A :MSTORE(addFp6BN254_a3_x) + B :MSTORE(addFp6BN254_a3_y) + $ => A :MLOAD(sparseMulAFp12BN254_a21_x) + $ => B :MLOAD(sparseMulAFp12BN254_a21_y) + A :MSTORE(addFp6BN254_b1_x) + B :MSTORE(addFp6BN254_b1_y) + $ => A :MLOAD(sparseMulAFp12BN254_a22_x) + $ => B :MLOAD(sparseMulAFp12BN254_a22_y) + A :MSTORE(addFp6BN254_b2_x) + B :MSTORE(addFp6BN254_b2_y) + $ => A :MLOAD(sparseMulAFp12BN254_a23_x) + $ => B :MLOAD(sparseMulAFp12BN254_a23_y) + A :MSTORE(addFp6BN254_b3_x) + B :MSTORE(addFp6BN254_b3_y), CALL(addFp6BN254) + $ => A :MLOAD(addFp6BN254_c1_x) + $ => B :MLOAD(addFp6BN254_c1_y) + A :MSTORE(sparseMulBFp6BN254_a1_x) + B :MSTORE(sparseMulBFp6BN254_a1_y) + $ => A :MLOAD(addFp6BN254_c2_x) + $ => B :MLOAD(addFp6BN254_c2_y) + A :MSTORE(sparseMulBFp6BN254_a2_x) + B :MSTORE(sparseMulBFp6BN254_a2_y) + $ => A :MLOAD(addFp6BN254_c3_x) + $ => B :MLOAD(addFp6BN254_c3_y) + A :MSTORE(sparseMulBFp6BN254_a3_x) + B :MSTORE(sparseMulBFp6BN254_a3_y) + $ => A :MLOAD(sparseMulAFp12BN254_aux2_x) + $ => B :MLOAD(sparseMulAFp12BN254_aux2_y) + A :MSTORE(sparseMulBFp6BN254_b2_x) + B :MSTORE(sparseMulBFp6BN254_b2_y) + $ => A :MLOAD(sparseMulAFp12BN254_b23_x) + $ => B :MLOAD(sparseMulAFp12BN254_b23_y) + A :MSTORE(sparseMulBFp6BN254_b3_x) + B :MSTORE(sparseMulBFp6BN254_b3_y), CALL(sparseMulBFp6BN254) + $ => A :MLOAD(sparseMulBFp6BN254_c1_x) + $ => B :MLOAD(sparseMulBFp6BN254_c1_y) + A :MSTORE(subFp6BN254_a1_x) + B :MSTORE(subFp6BN254_a1_y) + $ => A :MLOAD(sparseMulBFp6BN254_c2_x) + $ => B :MLOAD(sparseMulBFp6BN254_c2_y) + A :MSTORE(subFp6BN254_a2_x) + B :MSTORE(subFp6BN254_a2_y) + $ => A :MLOAD(sparseMulBFp6BN254_c3_x) + $ => B :MLOAD(sparseMulBFp6BN254_c3_y) + A :MSTORE(subFp6BN254_a3_x) + B :MSTORE(subFp6BN254_a3_y) + $ => A :MLOAD(sparseMulAFp12BN254_a1b1mul1_x) + $ => B :MLOAD(sparseMulAFp12BN254_a1b1mul1_y) + A :MSTORE(subFp6BN254_b1_x) + B :MSTORE(subFp6BN254_b1_y) + $ => A :MLOAD(sparseMulAFp12BN254_a1b1mul2_x) + $ => B :MLOAD(sparseMulAFp12BN254_a1b1mul2_y) + A :MSTORE(subFp6BN254_b2_x) + B :MSTORE(subFp6BN254_b2_y) + $ => A :MLOAD(sparseMulAFp12BN254_a1b1mul3_x) + $ => B :MLOAD(sparseMulAFp12BN254_a1b1mul3_y) + A :MSTORE(subFp6BN254_b3_x) + B :MSTORE(subFp6BN254_b3_y), CALL(subFp6BN254) + $ => A :MLOAD(subFp6BN254_c1_x) + $ => B :MLOAD(subFp6BN254_c1_y) + A :MSTORE(subFp6BN254_a1_x) + B :MSTORE(subFp6BN254_a1_y) + $ => A :MLOAD(subFp6BN254_c2_x) + $ => B :MLOAD(subFp6BN254_c2_y) + A :MSTORE(subFp6BN254_a2_x) + B :MSTORE(subFp6BN254_a2_y) + $ => A :MLOAD(subFp6BN254_c3_x) + $ => B :MLOAD(subFp6BN254_c3_y) + A :MSTORE(subFp6BN254_a3_x) + B :MSTORE(subFp6BN254_a3_y) + $ => A :MLOAD(sparseMulAFp12BN254_a2b2mul1_x) + $ => B :MLOAD(sparseMulAFp12BN254_a2b2mul1_y) + A :MSTORE(subFp6BN254_b1_x) + B :MSTORE(subFp6BN254_b1_y) + $ => A :MLOAD(sparseMulAFp12BN254_a2b2mul2_x) + $ => B :MLOAD(sparseMulAFp12BN254_a2b2mul2_y) + A :MSTORE(subFp6BN254_b2_x) + B :MSTORE(subFp6BN254_b2_y) + $ => A :MLOAD(sparseMulAFp12BN254_a2b2mul3_x) + $ => B :MLOAD(sparseMulAFp12BN254_a2b2mul3_y) + A :MSTORE(subFp6BN254_b3_x) + B :MSTORE(subFp6BN254_b3_y), CALL(subFp6BN254) + $ => A :MLOAD(subFp6BN254_c1_x) + $ => B :MLOAD(subFp6BN254_c1_y) + A :MSTORE(sparseMulAFp12BN254_c21_x) + B :MSTORE(sparseMulAFp12BN254_c21_y) + $ => A :MLOAD(subFp6BN254_c2_x) + $ => B :MLOAD(subFp6BN254_c2_y) + A :MSTORE(sparseMulAFp12BN254_c22_x) + B :MSTORE(sparseMulAFp12BN254_c22_y) + $ => A :MLOAD(subFp6BN254_c3_x) + $ => B :MLOAD(subFp6BN254_c3_y) + A :MSTORE(sparseMulAFp12BN254_c23_x) + B :MSTORE(sparseMulAFp12BN254_c23_y) + + $ => RR :MLOAD(sparseMulAFp12BN254_RR) + :RETURN \ No newline at end of file diff --git a/main/pairings/FP12BN254/sparseMulBFp12BN254.zkasm b/main/pairings/FP12BN254/sparseMulBFp12BN254.zkasm new file mode 100644 index 00000000..535ca8dd --- /dev/null +++ b/main/pairings/FP12BN254/sparseMulBFp12BN254.zkasm @@ -0,0 +1,291 @@ +;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; POST: The result is in the range [0,BN254_P) because if falls back to FP6 arithmetic +;; +;; sparseMulBFp12BN254: +;; in: (a1 + a2·w),(b1 + b2·w) ∈ Fp12, where ai ∈ Fp6, b1 = b11 + b13·v² and b2 = b22·v, with b11,b13,b22 ∈ Fp2 +;; out: (a1 + a2·w)·(b1 + b2·w) = (c1 + c2·w) ∈ Fp12, where: +;; - c1 = a1·b1 + a2·b2·v +;; - c2 = (a1+a2)·(b11 + b22·v + b13·v²) - a1·b1 - a2·b2 +;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +VAR GLOBAL sparseMulBFp12BN254_a11_x +VAR GLOBAL sparseMulBFp12BN254_a11_y +VAR GLOBAL sparseMulBFp12BN254_a12_x +VAR GLOBAL sparseMulBFp12BN254_a12_y +VAR GLOBAL sparseMulBFp12BN254_a13_x +VAR GLOBAL sparseMulBFp12BN254_a13_y +VAR GLOBAL sparseMulBFp12BN254_a21_x +VAR GLOBAL sparseMulBFp12BN254_a21_y +VAR GLOBAL sparseMulBFp12BN254_a22_x +VAR GLOBAL sparseMulBFp12BN254_a22_y +VAR GLOBAL sparseMulBFp12BN254_a23_x +VAR GLOBAL sparseMulBFp12BN254_a23_y + +VAR GLOBAL sparseMulBFp12BN254_b11_x +VAR GLOBAL sparseMulBFp12BN254_b11_y +VAR GLOBAL sparseMulBFp12BN254_b13_x +VAR GLOBAL sparseMulBFp12BN254_b13_y +VAR GLOBAL sparseMulBFp12BN254_b22_x +VAR GLOBAL sparseMulBFp12BN254_b22_y + +VAR GLOBAL sparseMulBFp12BN254_c11_x +VAR GLOBAL sparseMulBFp12BN254_c11_y +VAR GLOBAL sparseMulBFp12BN254_c12_x +VAR GLOBAL sparseMulBFp12BN254_c12_y +VAR GLOBAL sparseMulBFp12BN254_c13_x +VAR GLOBAL sparseMulBFp12BN254_c13_y +VAR GLOBAL sparseMulBFp12BN254_c21_x +VAR GLOBAL sparseMulBFp12BN254_c21_y +VAR GLOBAL sparseMulBFp12BN254_c22_x +VAR GLOBAL sparseMulBFp12BN254_c22_y +VAR GLOBAL sparseMulBFp12BN254_c23_x +VAR GLOBAL sparseMulBFp12BN254_c23_y + +VAR GLOBAL sparseMulBFp12BN254_a1b1mul1_x +VAR GLOBAL sparseMulBFp12BN254_a1b1mul1_y +VAR GLOBAL sparseMulBFp12BN254_a1b1mul2_x +VAR GLOBAL sparseMulBFp12BN254_a1b1mul2_y +VAR GLOBAL sparseMulBFp12BN254_a1b1mul3_x +VAR GLOBAL sparseMulBFp12BN254_a1b1mul3_y +VAR GLOBAL sparseMulBFp12BN254_a2b2mul1_x +VAR GLOBAL sparseMulBFp12BN254_a2b2mul1_y +VAR GLOBAL sparseMulBFp12BN254_a2b2mul2_x +VAR GLOBAL sparseMulBFp12BN254_a2b2mul2_y +VAR GLOBAL sparseMulBFp12BN254_a2b2mul3_x +VAR GLOBAL sparseMulBFp12BN254_a2b2mul3_y + +VAR GLOBAL sparseMulBFp12BN254_RR + +sparseMulBFp12BN254: + RR :MSTORE(sparseMulBFp12BN254_RR) + + ; 1] a1·b1, a2·b2 + $ => A :MLOAD(sparseMulBFp12BN254_a11_x) + $ => B :MLOAD(sparseMulBFp12BN254_a11_y) + A :MSTORE(sparseMulCFp6BN254_a1_x) + B :MSTORE(sparseMulCFp6BN254_a1_y) + $ => A :MLOAD(sparseMulBFp12BN254_a12_x) + $ => B :MLOAD(sparseMulBFp12BN254_a12_y) + A :MSTORE(sparseMulCFp6BN254_a2_x) + B :MSTORE(sparseMulCFp6BN254_a2_y) + $ => A :MLOAD(sparseMulBFp12BN254_a13_x) + $ => B :MLOAD(sparseMulBFp12BN254_a13_y) + A :MSTORE(sparseMulCFp6BN254_a3_x) + B :MSTORE(sparseMulCFp6BN254_a3_y) + $ => A :MLOAD(sparseMulBFp12BN254_b11_x) + $ => B :MLOAD(sparseMulBFp12BN254_b11_y) + A :MSTORE(sparseMulCFp6BN254_b1_x) + B :MSTORE(sparseMulCFp6BN254_b1_y) + $ => A :MLOAD(sparseMulBFp12BN254_b13_x) + $ => B :MLOAD(sparseMulBFp12BN254_b13_y) + A :MSTORE(sparseMulCFp6BN254_b3_x) + B :MSTORE(sparseMulCFp6BN254_b3_y), CALL(sparseMulCFp6BN254) + $ => A :MLOAD(sparseMulCFp6BN254_c1_x) + $ => B :MLOAD(sparseMulCFp6BN254_c1_y) + A :MSTORE(sparseMulBFp12BN254_a1b1mul1_x) + B :MSTORE(sparseMulBFp12BN254_a1b1mul1_y) + $ => A :MLOAD(sparseMulCFp6BN254_c2_x) + $ => B :MLOAD(sparseMulCFp6BN254_c2_y) + A :MSTORE(sparseMulBFp12BN254_a1b1mul2_x) + B :MSTORE(sparseMulBFp12BN254_a1b1mul2_y) + $ => A :MLOAD(sparseMulCFp6BN254_c3_x) + $ => B :MLOAD(sparseMulCFp6BN254_c3_y) + A :MSTORE(sparseMulBFp12BN254_a1b1mul3_x) + B :MSTORE(sparseMulBFp12BN254_a1b1mul3_y) + + $ => A :MLOAD(sparseMulBFp12BN254_a21_x) + $ => B :MLOAD(sparseMulBFp12BN254_a21_y) + A :MSTORE(sparseMulAFp6BN254_a1_x) + B :MSTORE(sparseMulAFp6BN254_a1_y) + $ => A :MLOAD(sparseMulBFp12BN254_a22_x) + $ => B :MLOAD(sparseMulBFp12BN254_a22_y) + A :MSTORE(sparseMulAFp6BN254_a2_x) + B :MSTORE(sparseMulAFp6BN254_a2_y) + $ => A :MLOAD(sparseMulBFp12BN254_a23_x) + $ => B :MLOAD(sparseMulBFp12BN254_a23_y) + A :MSTORE(sparseMulAFp6BN254_a3_x) + B :MSTORE(sparseMulAFp6BN254_a3_y) + $ => A :MLOAD(sparseMulBFp12BN254_b22_x) + $ => B :MLOAD(sparseMulBFp12BN254_b22_y) + A :MSTORE(sparseMulAFp6BN254_b2_x) + B :MSTORE(sparseMulAFp6BN254_b2_y), CALL(sparseMulAFp6BN254) + $ => A :MLOAD(sparseMulAFp6BN254_c1_x) + $ => B :MLOAD(sparseMulAFp6BN254_c1_y) + A :MSTORE(sparseMulBFp12BN254_a2b2mul1_x) + B :MSTORE(sparseMulBFp12BN254_a2b2mul1_y) + $ => A :MLOAD(sparseMulAFp6BN254_c2_x) + $ => B :MLOAD(sparseMulAFp6BN254_c2_y) + A :MSTORE(sparseMulBFp12BN254_a2b2mul2_x) + B :MSTORE(sparseMulBFp12BN254_a2b2mul2_y) + $ => A :MLOAD(sparseMulAFp6BN254_c3_x) + $ => B :MLOAD(sparseMulAFp6BN254_c3_y) + A :MSTORE(sparseMulBFp12BN254_a2b2mul3_x) + B :MSTORE(sparseMulBFp12BN254_a2b2mul3_y) + + ; 2] c1 = a1·b1 + a2·b2·v + $ => A :MLOAD(sparseMulBFp12BN254_a2b2mul1_x) + $ => B :MLOAD(sparseMulBFp12BN254_a2b2mul1_y) + A :MSTORE(sparseMulAFp6BN254_a1_x) + B :MSTORE(sparseMulAFp6BN254_a1_y) + $ => A :MLOAD(sparseMulBFp12BN254_a2b2mul2_x) + $ => B :MLOAD(sparseMulBFp12BN254_a2b2mul2_y) + A :MSTORE(sparseMulAFp6BN254_a2_x) + B :MSTORE(sparseMulAFp6BN254_a2_y) + $ => A :MLOAD(sparseMulBFp12BN254_a2b2mul3_x) + $ => B :MLOAD(sparseMulBFp12BN254_a2b2mul3_y) + A :MSTORE(sparseMulAFp6BN254_a3_x) + B :MSTORE(sparseMulAFp6BN254_a3_y) + 1n :MSTORE(sparseMulAFp6BN254_b2_x) + 0n :MSTORE(sparseMulAFp6BN254_b2_y), CALL(sparseMulAFp6BN254) + $ => A :MLOAD(sparseMulAFp6BN254_c1_x) + $ => B :MLOAD(sparseMulAFp6BN254_c1_y) + A :MSTORE(addFp6BN254_a1_x) + B :MSTORE(addFp6BN254_a1_y) + $ => A :MLOAD(sparseMulAFp6BN254_c2_x) + $ => B :MLOAD(sparseMulAFp6BN254_c2_y) + A :MSTORE(addFp6BN254_a2_x) + B :MSTORE(addFp6BN254_a2_y) + $ => A :MLOAD(sparseMulAFp6BN254_c3_x) + $ => B :MLOAD(sparseMulAFp6BN254_c3_y) + A :MSTORE(addFp6BN254_a3_x) + B :MSTORE(addFp6BN254_a3_y) + $ => A :MLOAD(sparseMulBFp12BN254_a1b1mul1_x) + $ => B :MLOAD(sparseMulBFp12BN254_a1b1mul1_y) + A :MSTORE(addFp6BN254_b1_x) + B :MSTORE(addFp6BN254_b1_y) + $ => A :MLOAD(sparseMulBFp12BN254_a1b1mul2_x) + $ => B :MLOAD(sparseMulBFp12BN254_a1b1mul2_y) + A :MSTORE(addFp6BN254_b2_x) + B :MSTORE(addFp6BN254_b2_y) + $ => A :MLOAD(sparseMulBFp12BN254_a1b1mul3_x) + $ => B :MLOAD(sparseMulBFp12BN254_a1b1mul3_y) + A :MSTORE(addFp6BN254_b3_x) + B :MSTORE(addFp6BN254_b3_y), CALL(addFp6BN254) + $ => A :MLOAD(addFp6BN254_c1_x) + $ => B :MLOAD(addFp6BN254_c1_y) + A :MSTORE(sparseMulBFp12BN254_c11_x) + B :MSTORE(sparseMulBFp12BN254_c11_y) + $ => A :MLOAD(addFp6BN254_c2_x) + $ => B :MLOAD(addFp6BN254_c2_y) + A :MSTORE(sparseMulBFp12BN254_c12_x) + B :MSTORE(sparseMulBFp12BN254_c12_y) + $ => A :MLOAD(addFp6BN254_c3_x) + $ => B :MLOAD(addFp6BN254_c3_y) + A :MSTORE(sparseMulBFp12BN254_c13_x) + B :MSTORE(sparseMulBFp12BN254_c13_y) + + ; aux = b11 + b22·v + b13·v² + + ; 3] c2 = (a1+a2)·aux - a1·b1 - a2·b2 + $ => A :MLOAD(sparseMulBFp12BN254_a11_x) + $ => B :MLOAD(sparseMulBFp12BN254_a11_y) + A :MSTORE(addFp6BN254_a1_x) + B :MSTORE(addFp6BN254_a1_y) + $ => A :MLOAD(sparseMulBFp12BN254_a12_x) + $ => B :MLOAD(sparseMulBFp12BN254_a12_y) + A :MSTORE(addFp6BN254_a2_x) + B :MSTORE(addFp6BN254_a2_y) + $ => A :MLOAD(sparseMulBFp12BN254_a13_x) + $ => B :MLOAD(sparseMulBFp12BN254_a13_y) + A :MSTORE(addFp6BN254_a3_x) + B :MSTORE(addFp6BN254_a3_y) + $ => A :MLOAD(sparseMulBFp12BN254_a21_x) + $ => B :MLOAD(sparseMulBFp12BN254_a21_y) + A :MSTORE(addFp6BN254_b1_x) + B :MSTORE(addFp6BN254_b1_y) + $ => A :MLOAD(sparseMulBFp12BN254_a22_x) + $ => B :MLOAD(sparseMulBFp12BN254_a22_y) + A :MSTORE(addFp6BN254_b2_x) + B :MSTORE(addFp6BN254_b2_y) + $ => A :MLOAD(sparseMulBFp12BN254_a23_x) + $ => B :MLOAD(sparseMulBFp12BN254_a23_y) + A :MSTORE(addFp6BN254_b3_x) + B :MSTORE(addFp6BN254_b3_y), CALL(addFp6BN254) + $ => A :MLOAD(addFp6BN254_c1_x) + $ => B :MLOAD(addFp6BN254_c1_y) + A :MSTORE(mulFp6BN254_a1_x) + B :MSTORE(mulFp6BN254_a1_y) + $ => A :MLOAD(addFp6BN254_c2_x) + $ => B :MLOAD(addFp6BN254_c2_y) + A :MSTORE(mulFp6BN254_a2_x) + B :MSTORE(mulFp6BN254_a2_y) + $ => A :MLOAD(addFp6BN254_c3_x) + $ => B :MLOAD(addFp6BN254_c3_y) + A :MSTORE(mulFp6BN254_a3_x) + B :MSTORE(mulFp6BN254_a3_y) + $ => A :MLOAD(sparseMulBFp12BN254_b11_x) + $ => B :MLOAD(sparseMulBFp12BN254_b11_y) + A :MSTORE(mulFp6BN254_b1_x) + B :MSTORE(mulFp6BN254_b1_y) + $ => A :MLOAD(sparseMulBFp12BN254_b22_x) + $ => B :MLOAD(sparseMulBFp12BN254_b22_y) + A :MSTORE(mulFp6BN254_b2_x) + B :MSTORE(mulFp6BN254_b2_y) + $ => A :MLOAD(sparseMulBFp12BN254_b13_x) + $ => B :MLOAD(sparseMulBFp12BN254_b13_y) + A :MSTORE(mulFp6BN254_b3_x) + B :MSTORE(mulFp6BN254_b3_y), CALL(mulFp6BN254) + $ => A :MLOAD(mulFp6BN254_c1_x) + $ => B :MLOAD(mulFp6BN254_c1_y) + A :MSTORE(subFp6BN254_a1_x) + B :MSTORE(subFp6BN254_a1_y) + $ => A :MLOAD(mulFp6BN254_c2_x) + $ => B :MLOAD(mulFp6BN254_c2_y) + A :MSTORE(subFp6BN254_a2_x) + B :MSTORE(subFp6BN254_a2_y) + $ => A :MLOAD(mulFp6BN254_c3_x) + $ => B :MLOAD(mulFp6BN254_c3_y) + A :MSTORE(subFp6BN254_a3_x) + B :MSTORE(subFp6BN254_a3_y) + $ => A :MLOAD(sparseMulBFp12BN254_a1b1mul1_x) + $ => B :MLOAD(sparseMulBFp12BN254_a1b1mul1_y) + A :MSTORE(subFp6BN254_b1_x) + B :MSTORE(subFp6BN254_b1_y) + $ => A :MLOAD(sparseMulBFp12BN254_a1b1mul2_x) + $ => B :MLOAD(sparseMulBFp12BN254_a1b1mul2_y) + A :MSTORE(subFp6BN254_b2_x) + B :MSTORE(subFp6BN254_b2_y) + $ => A :MLOAD(sparseMulBFp12BN254_a1b1mul3_x) + $ => B :MLOAD(sparseMulBFp12BN254_a1b1mul3_y) + A :MSTORE(subFp6BN254_b3_x) + B :MSTORE(subFp6BN254_b3_y), CALL(subFp6BN254) + $ => A :MLOAD(subFp6BN254_c1_x) + $ => B :MLOAD(subFp6BN254_c1_y) + A :MSTORE(subFp6BN254_a1_x) + B :MSTORE(subFp6BN254_a1_y) + $ => A :MLOAD(subFp6BN254_c2_x) + $ => B :MLOAD(subFp6BN254_c2_y) + A :MSTORE(subFp6BN254_a2_x) + B :MSTORE(subFp6BN254_a2_y) + $ => A :MLOAD(subFp6BN254_c3_x) + $ => B :MLOAD(subFp6BN254_c3_y) + A :MSTORE(subFp6BN254_a3_x) + B :MSTORE(subFp6BN254_a3_y) + $ => A :MLOAD(sparseMulBFp12BN254_a2b2mul1_x) + $ => B :MLOAD(sparseMulBFp12BN254_a2b2mul1_y) + A :MSTORE(subFp6BN254_b1_x) + B :MSTORE(subFp6BN254_b1_y) + $ => A :MLOAD(sparseMulBFp12BN254_a2b2mul2_x) + $ => B :MLOAD(sparseMulBFp12BN254_a2b2mul2_y) + A :MSTORE(subFp6BN254_b2_x) + B :MSTORE(subFp6BN254_b2_y) + $ => A :MLOAD(sparseMulBFp12BN254_a2b2mul3_x) + $ => B :MLOAD(sparseMulBFp12BN254_a2b2mul3_y) + A :MSTORE(subFp6BN254_b3_x) + B :MSTORE(subFp6BN254_b3_y), CALL(subFp6BN254) + $ => A :MLOAD(subFp6BN254_c1_x) + $ => B :MLOAD(subFp6BN254_c1_y) + A :MSTORE(sparseMulBFp12BN254_c21_x) + B :MSTORE(sparseMulBFp12BN254_c21_y) + $ => A :MLOAD(subFp6BN254_c2_x) + $ => B :MLOAD(subFp6BN254_c2_y) + A :MSTORE(sparseMulBFp12BN254_c22_x) + B :MSTORE(sparseMulBFp12BN254_c22_y) + $ => A :MLOAD(subFp6BN254_c3_x) + $ => B :MLOAD(subFp6BN254_c3_y) + A :MSTORE(sparseMulBFp12BN254_c23_x) + B :MSTORE(sparseMulBFp12BN254_c23_y) + + $ => RR :MLOAD(sparseMulBFp12BN254_RR) + :RETURN \ No newline at end of file diff --git a/main/pairings/FP12BN254/squareFp12BN254.zkasm b/main/pairings/FP12BN254/squareFp12BN254.zkasm new file mode 100644 index 00000000..b554b83d --- /dev/null +++ b/main/pairings/FP12BN254/squareFp12BN254.zkasm @@ -0,0 +1,376 @@ +;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; POST: The result is in the range [0,BN254_P) because if falls back to FP6 arithmetic +;; +;; squareFp12BN254: +;; in: (a1 + a2·w) ∈ Fp12, where ai ∈ Fp6 +;; out: (a1 + a2·w)² = (c1 + c2·w) ∈ Fp12, where: +;; - c1 = (a1-a2)·(a1-a2·v) + a1·a2 + a1·a2·v +;; - c2 = 2·a1·a2 +;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +VAR GLOBAL squareFp12BN254_a11_x +VAR GLOBAL squareFp12BN254_a11_y +VAR GLOBAL squareFp12BN254_a12_x +VAR GLOBAL squareFp12BN254_a12_y +VAR GLOBAL squareFp12BN254_a13_x +VAR GLOBAL squareFp12BN254_a13_y +VAR GLOBAL squareFp12BN254_a21_x +VAR GLOBAL squareFp12BN254_a21_y +VAR GLOBAL squareFp12BN254_a22_x +VAR GLOBAL squareFp12BN254_a22_y +VAR GLOBAL squareFp12BN254_a23_x +VAR GLOBAL squareFp12BN254_a23_y +VAR GLOBAL squareFp12BN254_c11_x +VAR GLOBAL squareFp12BN254_c11_y +VAR GLOBAL squareFp12BN254_c12_x +VAR GLOBAL squareFp12BN254_c12_y +VAR GLOBAL squareFp12BN254_c13_x +VAR GLOBAL squareFp12BN254_c13_y +VAR GLOBAL squareFp12BN254_c21_x +VAR GLOBAL squareFp12BN254_c21_y +VAR GLOBAL squareFp12BN254_c22_x +VAR GLOBAL squareFp12BN254_c22_y +VAR GLOBAL squareFp12BN254_c23_x +VAR GLOBAL squareFp12BN254_c23_y + +VAR GLOBAL squareFp12BN254_a1a2mul1_x +VAR GLOBAL squareFp12BN254_a1a2mul1_y +VAR GLOBAL squareFp12BN254_a1a2mul2_x +VAR GLOBAL squareFp12BN254_a1a2mul2_y +VAR GLOBAL squareFp12BN254_a1a2mul3_x +VAR GLOBAL squareFp12BN254_a1a2mul3_y + +VAR GLOBAL squareFp12BN254_a2vmul1_x +VAR GLOBAL squareFp12BN254_a2vmul1_y +VAR GLOBAL squareFp12BN254_a2vmul2_x +VAR GLOBAL squareFp12BN254_a2vmul2_y +VAR GLOBAL squareFp12BN254_a2vmul3_x +VAR GLOBAL squareFp12BN254_a2vmul3_y + +VAR GLOBAL squareFp12BN254_a1a2vmul1_x +VAR GLOBAL squareFp12BN254_a1a2vmul1_y +VAR GLOBAL squareFp12BN254_a1a2vmul2_x +VAR GLOBAL squareFp12BN254_a1a2vmul2_y +VAR GLOBAL squareFp12BN254_a1a2vmul3_x +VAR GLOBAL squareFp12BN254_a1a2vmul3_y + +VAR GLOBAL squareFp12BN254_a1a2sub1_x +VAR GLOBAL squareFp12BN254_a1a2sub1_y +VAR GLOBAL squareFp12BN254_a1a2sub2_x +VAR GLOBAL squareFp12BN254_a1a2sub2_y +VAR GLOBAL squareFp12BN254_a1a2sub3_x +VAR GLOBAL squareFp12BN254_a1a2sub3_y +VAR GLOBAL squareFp12BN254_a1a2vsub1_x +VAR GLOBAL squareFp12BN254_a1a2vsub1_y +VAR GLOBAL squareFp12BN254_a1a2vsub2_x +VAR GLOBAL squareFp12BN254_a1a2vsub2_y +VAR GLOBAL squareFp12BN254_a1a2vsub3_x +VAR GLOBAL squareFp12BN254_a1a2vsub3_y + +VAR GLOBAL squareFp12BN254_RR + +squareFp12BN254: + RR :MSTORE(squareFp12BN254_RR) + + ; 1] a1·a2 + $ => A :MLOAD(squareFp12BN254_a11_x) + $ => B :MLOAD(squareFp12BN254_a11_y) + A :MSTORE(mulFp6BN254_a1_x) + B :MSTORE(mulFp6BN254_a1_y) + $ => A :MLOAD(squareFp12BN254_a12_x) + $ => B :MLOAD(squareFp12BN254_a12_y) + A :MSTORE(mulFp6BN254_a2_x) + B :MSTORE(mulFp6BN254_a2_y) + $ => A :MLOAD(squareFp12BN254_a13_x) + $ => B :MLOAD(squareFp12BN254_a13_y) + A :MSTORE(mulFp6BN254_a3_x) + B :MSTORE(mulFp6BN254_a3_y) + + $ => A :MLOAD(squareFp12BN254_a21_x) + $ => B :MLOAD(squareFp12BN254_a21_y) + A :MSTORE(mulFp6BN254_b1_x) + B :MSTORE(mulFp6BN254_b1_y) + $ => A :MLOAD(squareFp12BN254_a22_x) + $ => B :MLOAD(squareFp12BN254_a22_y) + A :MSTORE(mulFp6BN254_b2_x) + B :MSTORE(mulFp6BN254_b2_y) + $ => A :MLOAD(squareFp12BN254_a23_x) + $ => B :MLOAD(squareFp12BN254_a23_y) + A :MSTORE(mulFp6BN254_b3_x) + B :MSTORE(mulFp6BN254_b3_y), CALL(mulFp6BN254) + $ => A :MLOAD(mulFp6BN254_c1_x) + $ => B :MLOAD(mulFp6BN254_c1_y) + A :MSTORE(squareFp12BN254_a1a2mul1_x) + B :MSTORE(squareFp12BN254_a1a2mul1_y) + $ => A :MLOAD(mulFp6BN254_c2_x) + $ => B :MLOAD(mulFp6BN254_c2_y) + A :MSTORE(squareFp12BN254_a1a2mul2_x) + B :MSTORE(squareFp12BN254_a1a2mul2_y) + $ => A :MLOAD(mulFp6BN254_c3_x) + $ => B :MLOAD(mulFp6BN254_c3_y) + A :MSTORE(squareFp12BN254_a1a2mul3_x) + B :MSTORE(squareFp12BN254_a1a2mul3_y) + + ; 2] a2·v + $ => A :MLOAD(squareFp12BN254_a21_x) + $ => B :MLOAD(squareFp12BN254_a21_y) + A :MSTORE(sparseMulAFp6BN254_a1_x) + B :MSTORE(sparseMulAFp6BN254_a1_y) + $ => A :MLOAD(squareFp12BN254_a22_x) + $ => B :MLOAD(squareFp12BN254_a22_y) + A :MSTORE(sparseMulAFp6BN254_a2_x) + B :MSTORE(sparseMulAFp6BN254_a2_y) + $ => A :MLOAD(squareFp12BN254_a23_x) + $ => B :MLOAD(squareFp12BN254_a23_y) + A :MSTORE(sparseMulAFp6BN254_a3_x) + B :MSTORE(sparseMulAFp6BN254_a3_y) + + 1n :MSTORE(sparseMulAFp6BN254_b2_x) + 0n :MSTORE(sparseMulAFp6BN254_b2_y), CALL(sparseMulAFp6BN254) + $ => A :MLOAD(sparseMulAFp6BN254_c1_x) + $ => B :MLOAD(sparseMulAFp6BN254_c1_y) + A :MSTORE(squareFp12BN254_a2vmul1_x) + B :MSTORE(squareFp12BN254_a2vmul1_y) + $ => A :MLOAD(sparseMulAFp6BN254_c2_x) + $ => B :MLOAD(sparseMulAFp6BN254_c2_y) + A :MSTORE(squareFp12BN254_a2vmul2_x) + B :MSTORE(squareFp12BN254_a2vmul2_y) + $ => A :MLOAD(sparseMulAFp6BN254_c3_x) + $ => B :MLOAD(sparseMulAFp6BN254_c3_y) + A :MSTORE(squareFp12BN254_a2vmul3_x) + B :MSTORE(squareFp12BN254_a2vmul3_y) + + ; 2] a1·a2·v + $ => A :MLOAD(squareFp12BN254_a1a2mul1_x) + $ => B :MLOAD(squareFp12BN254_a1a2mul1_y) + A :MSTORE(sparseMulAFp6BN254_a1_x) + B :MSTORE(sparseMulAFp6BN254_a1_y) + $ => A :MLOAD(squareFp12BN254_a1a2mul2_x) + $ => B :MLOAD(squareFp12BN254_a1a2mul2_y) + A :MSTORE(sparseMulAFp6BN254_a2_x) + B :MSTORE(sparseMulAFp6BN254_a2_y) + $ => A :MLOAD(squareFp12BN254_a1a2mul3_x) + $ => B :MLOAD(squareFp12BN254_a1a2mul3_y) + A :MSTORE(sparseMulAFp6BN254_a3_x) + B :MSTORE(sparseMulAFp6BN254_a3_y) + + 1n :MSTORE(sparseMulAFp6BN254_b2_x) + 0n :MSTORE(sparseMulAFp6BN254_b2_y), CALL(sparseMulAFp6BN254) + $ => A :MLOAD(sparseMulAFp6BN254_c1_x) + $ => B :MLOAD(sparseMulAFp6BN254_c1_y) + A :MSTORE(squareFp12BN254_a1a2vmul1_x) + B :MSTORE(squareFp12BN254_a1a2vmul1_y) + $ => A :MLOAD(sparseMulAFp6BN254_c2_x) + $ => B :MLOAD(sparseMulAFp6BN254_c2_y) + A :MSTORE(squareFp12BN254_a1a2vmul2_x) + B :MSTORE(squareFp12BN254_a1a2vmul2_y) + $ => A :MLOAD(sparseMulAFp6BN254_c3_x) + $ => B :MLOAD(sparseMulAFp6BN254_c3_y) + A :MSTORE(squareFp12BN254_a1a2vmul3_x) + B :MSTORE(squareFp12BN254_a1a2vmul3_y) + + ; 3] c2 = 2·a1·a2 + $ => A :MLOAD(squareFp12BN254_a1a2mul1_x) + $ => B :MLOAD(squareFp12BN254_a1a2mul1_y) + A :MSTORE(escalarMulFp6BN254_a1_x) + B :MSTORE(escalarMulFp6BN254_a1_y) + $ => A :MLOAD(squareFp12BN254_a1a2mul2_x) + $ => B :MLOAD(squareFp12BN254_a1a2mul2_y) + A :MSTORE(escalarMulFp6BN254_a2_x) + B :MSTORE(escalarMulFp6BN254_a2_y) + $ => A :MLOAD(squareFp12BN254_a1a2mul3_x) + $ => B :MLOAD(squareFp12BN254_a1a2mul3_y) + A :MSTORE(escalarMulFp6BN254_a3_x) + B :MSTORE(escalarMulFp6BN254_a3_y) + + 2n :MSTORE(escalarMulFp6BN254_b), CALL(escalarMulFp6BN254) + $ => A :MLOAD(escalarMulFp6BN254_c1_x) + $ => B :MLOAD(escalarMulFp6BN254_c1_y) + A :MSTORE(squareFp12BN254_c21_x) + B :MSTORE(squareFp12BN254_c21_y) + $ => A :MLOAD(escalarMulFp6BN254_c2_x) + $ => B :MLOAD(escalarMulFp6BN254_c2_y) + A :MSTORE(squareFp12BN254_c22_x) + B :MSTORE(squareFp12BN254_c22_y) + $ => A :MLOAD(escalarMulFp6BN254_c3_x) + $ => B :MLOAD(escalarMulFp6BN254_c3_y) + A :MSTORE(squareFp12BN254_c23_x) + B :MSTORE(squareFp12BN254_c23_y) + + ; 4] a1-a2 + $ => A :MLOAD(squareFp12BN254_a11_x) + $ => B :MLOAD(squareFp12BN254_a11_y) + A :MSTORE(subFp6BN254_a1_x) + B :MSTORE(subFp6BN254_a1_y) + $ => A :MLOAD(squareFp12BN254_a12_x) + $ => B :MLOAD(squareFp12BN254_a12_y) + A :MSTORE(subFp6BN254_a2_x) + B :MSTORE(subFp6BN254_a2_y) + $ => A :MLOAD(squareFp12BN254_a13_x) + $ => B :MLOAD(squareFp12BN254_a13_y) + A :MSTORE(subFp6BN254_a3_x) + B :MSTORE(subFp6BN254_a3_y) + + $ => A :MLOAD(squareFp12BN254_a21_x) + $ => B :MLOAD(squareFp12BN254_a21_y) + A :MSTORE(subFp6BN254_b1_x) + B :MSTORE(subFp6BN254_b1_y) + $ => A :MLOAD(squareFp12BN254_a22_x) + $ => B :MLOAD(squareFp12BN254_a22_y) + A :MSTORE(subFp6BN254_b2_x) + B :MSTORE(subFp6BN254_b2_y) + $ => A :MLOAD(squareFp12BN254_a23_x) + $ => B :MLOAD(squareFp12BN254_a23_y) + A :MSTORE(subFp6BN254_b3_x) + B :MSTORE(subFp6BN254_b3_y), CALL(subFp6BN254) + + $ => A :MLOAD(subFp6BN254_c1_x) + $ => B :MLOAD(subFp6BN254_c1_y) + A :MSTORE(squareFp12BN254_a1a2sub1_x) + B :MSTORE(squareFp12BN254_a1a2sub1_y) + $ => A :MLOAD(subFp6BN254_c2_x) + $ => B :MLOAD(subFp6BN254_c2_y) + A :MSTORE(squareFp12BN254_a1a2sub2_x) + B :MSTORE(squareFp12BN254_a1a2sub2_y) + $ => A :MLOAD(subFp6BN254_c3_x) + $ => B :MLOAD(subFp6BN254_c3_y) + A :MSTORE(squareFp12BN254_a1a2sub3_x) + B :MSTORE(squareFp12BN254_a1a2sub3_y) + + + ; 5] a1-a2·v + $ => A :MLOAD(squareFp12BN254_a11_x) + $ => B :MLOAD(squareFp12BN254_a11_y) + A :MSTORE(subFp6BN254_a1_x) + B :MSTORE(subFp6BN254_a1_y) + $ => A :MLOAD(squareFp12BN254_a12_x) + $ => B :MLOAD(squareFp12BN254_a12_y) + A :MSTORE(subFp6BN254_a2_x) + B :MSTORE(subFp6BN254_a2_y) + $ => A :MLOAD(squareFp12BN254_a13_x) + $ => B :MLOAD(squareFp12BN254_a13_y) + A :MSTORE(subFp6BN254_a3_x) + B :MSTORE(subFp6BN254_a3_y) + + $ => A :MLOAD(squareFp12BN254_a2vmul1_x) + $ => B :MLOAD(squareFp12BN254_a2vmul1_y) + A :MSTORE(subFp6BN254_b1_x) + B :MSTORE(subFp6BN254_b1_y) + $ => A :MLOAD(squareFp12BN254_a2vmul2_x) + $ => B :MLOAD(squareFp12BN254_a2vmul2_y) + A :MSTORE(subFp6BN254_b2_x) + B :MSTORE(subFp6BN254_b2_y) + $ => A :MLOAD(squareFp12BN254_a2vmul3_x) + $ => B :MLOAD(squareFp12BN254_a2vmul3_y) + A :MSTORE(subFp6BN254_b3_x) + B :MSTORE(subFp6BN254_b3_y), CALL(subFp6BN254) + + $ => A :MLOAD(subFp6BN254_c1_x) + $ => B :MLOAD(subFp6BN254_c1_y) + A :MSTORE(squareFp12BN254_a1a2vsub1_x) + B :MSTORE(squareFp12BN254_a1a2vsub1_y) + $ => A :MLOAD(subFp6BN254_c2_x) + $ => B :MLOAD(subFp6BN254_c2_y) + A :MSTORE(squareFp12BN254_a1a2vsub2_x) + B :MSTORE(squareFp12BN254_a1a2vsub2_y) + $ => A :MLOAD(subFp6BN254_c3_x) + $ => B :MLOAD(subFp6BN254_c3_y) + A :MSTORE(squareFp12BN254_a1a2vsub3_x) + B :MSTORE(squareFp12BN254_a1a2vsub3_y) + + ; 7] c1 = (a1-a2)·(a1-a2·v) + a1·a2 + a1·a2·v + $ => A :MLOAD(squareFp12BN254_a1a2sub1_x) + $ => B :MLOAD(squareFp12BN254_a1a2sub1_y) + A :MSTORE(mulFp6BN254_a1_x) + B :MSTORE(mulFp6BN254_a1_y) + $ => A :MLOAD(squareFp12BN254_a1a2sub2_x) + $ => B :MLOAD(squareFp12BN254_a1a2sub2_y) + A :MSTORE(mulFp6BN254_a2_x) + B :MSTORE(mulFp6BN254_a2_y) + $ => A :MLOAD(squareFp12BN254_a1a2sub3_x) + $ => B :MLOAD(squareFp12BN254_a1a2sub3_y) + A :MSTORE(mulFp6BN254_a3_x) + B :MSTORE(mulFp6BN254_a3_y) + + + $ => A :MLOAD(squareFp12BN254_a1a2vsub1_x) + $ => B :MLOAD(squareFp12BN254_a1a2vsub1_y) + A :MSTORE(mulFp6BN254_b1_x) + B :MSTORE(mulFp6BN254_b1_y) + $ => A :MLOAD(squareFp12BN254_a1a2vsub2_x) + $ => B :MLOAD(squareFp12BN254_a1a2vsub2_y) + A :MSTORE(mulFp6BN254_b2_x) + B :MSTORE(mulFp6BN254_b2_y) + $ => A :MLOAD(squareFp12BN254_a1a2vsub3_x) + $ => B :MLOAD(squareFp12BN254_a1a2vsub3_y) + A :MSTORE(mulFp6BN254_b3_x) + B :MSTORE(mulFp6BN254_b3_y), CALL(mulFp6BN254) + + $ => A :MLOAD(mulFp6BN254_c1_x) + $ => B :MLOAD(mulFp6BN254_c1_y) + A :MSTORE(addFp6BN254_a1_x) + B :MSTORE(addFp6BN254_a1_y) + $ => A :MLOAD(mulFp6BN254_c2_x) + $ => B :MLOAD(mulFp6BN254_c2_y) + A :MSTORE(addFp6BN254_a2_x) + B :MSTORE(addFp6BN254_a2_y) + $ => A :MLOAD(mulFp6BN254_c3_x) + $ => B :MLOAD(mulFp6BN254_c3_y) + A :MSTORE(addFp6BN254_a3_x) + B :MSTORE(addFp6BN254_a3_y) + + $ => A :MLOAD(squareFp12BN254_a1a2mul1_x) + $ => B :MLOAD(squareFp12BN254_a1a2mul1_y) + A :MSTORE(addFp6BN254_b1_x) + B :MSTORE(addFp6BN254_b1_y) + $ => A :MLOAD(squareFp12BN254_a1a2mul2_x) + $ => B :MLOAD(squareFp12BN254_a1a2mul2_y) + A :MSTORE(addFp6BN254_b2_x) + B :MSTORE(addFp6BN254_b2_y) + $ => A :MLOAD(squareFp12BN254_a1a2mul3_x) + $ => B :MLOAD(squareFp12BN254_a1a2mul3_y) + A :MSTORE(addFp6BN254_b3_x) + B :MSTORE(addFp6BN254_b3_y), CALL(addFp6BN254) + + $ => A :MLOAD(addFp6BN254_c1_x) + $ => B :MLOAD(addFp6BN254_c1_y) + A :MSTORE(addFp6BN254_a1_x) + B :MSTORE(addFp6BN254_a1_y) + $ => A :MLOAD(addFp6BN254_c2_x) + $ => B :MLOAD(addFp6BN254_c2_y) + A :MSTORE(addFp6BN254_a2_x) + B :MSTORE(addFp6BN254_a2_y) + $ => A :MLOAD(addFp6BN254_c3_x) + $ => B :MLOAD(addFp6BN254_c3_y) + A :MSTORE(addFp6BN254_a3_x) + B :MSTORE(addFp6BN254_a3_y) + + $ => A :MLOAD(squareFp12BN254_a1a2vmul1_x) + $ => B :MLOAD(squareFp12BN254_a1a2vmul1_y) + A :MSTORE(addFp6BN254_b1_x) + B :MSTORE(addFp6BN254_b1_y) + $ => A :MLOAD(squareFp12BN254_a1a2vmul2_x) + $ => B :MLOAD(squareFp12BN254_a1a2vmul2_y) + A :MSTORE(addFp6BN254_b2_x) + B :MSTORE(addFp6BN254_b2_y) + $ => A :MLOAD(squareFp12BN254_a1a2vmul3_x) + $ => B :MLOAD(squareFp12BN254_a1a2vmul3_y) + A :MSTORE(addFp6BN254_b3_x) + B :MSTORE(addFp6BN254_b3_y), CALL(addFp6BN254) + + $ => A :MLOAD(addFp6BN254_c1_x) + $ => B :MLOAD(addFp6BN254_c1_y) + A :MSTORE(squareFp12BN254_c11_x) + B :MSTORE(squareFp12BN254_c11_y) + $ => A :MLOAD(addFp6BN254_c2_x) + $ => B :MLOAD(addFp6BN254_c2_y) + A :MSTORE(squareFp12BN254_c12_x) + B :MSTORE(squareFp12BN254_c12_y) + $ => A :MLOAD(addFp6BN254_c3_x) + $ => B :MLOAD(addFp6BN254_c3_y) + A :MSTORE(squareFp12BN254_c13_x) + B :MSTORE(squareFp12BN254_c13_y) + + $ => RR :MLOAD(squareFp12BN254_RR) + :RETURN \ No newline at end of file diff --git a/main/pairings/FP2BN254/addFp2BN254.zkasm b/main/pairings/FP2BN254/addFp2BN254.zkasm new file mode 100644 index 00000000..a48b9a9e --- /dev/null +++ b/main/pairings/FP2BN254/addFp2BN254.zkasm @@ -0,0 +1,19 @@ +;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; POST: ARITH_BN254_ADDFP2 ensures that the result is in the range [0,BN254_P) +;; +;; addFp2BN254: +;; in: (A + B·u), (C + D·u) ∈ Fp2, where A,B,C,D ∈ Fp +;; out: E + C·u = (A + C) + (B + D)·u ∈ Fp2 +;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +VAR GLOBAL addFp2BN254_i + +addFp2BN254: + ; Compute and check the mul + ; A + C = [E] + (q0·BN254_P) + ; B + D = [OP] + (q1·BN254_P) + ${ARITH_BN254_ADDFP2(A,C)} => E + ${ARITH_BN254_ADDFP2(B,D)} :MSTORE(addFp2BN254_i), ARITH_BN254_ADDFP2 + + $ => C :MLOAD(addFp2BN254_i), RETURN diff --git a/main/pairings/FP2BN254/escalarMulFp2BN254.zkasm b/main/pairings/FP2BN254/escalarMulFp2BN254.zkasm new file mode 100644 index 00000000..1814aec3 --- /dev/null +++ b/main/pairings/FP2BN254/escalarMulFp2BN254.zkasm @@ -0,0 +1,20 @@ +;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; POST: ARITH_BN254_MULFP2 ensures that the result is in the range [0,BN254_P) +;; +;; escalarMulFp2BN254: +;; in: A ∈ Fp, (C + D·u) ∈ Fp2, where C,D ∈ Fp +;; out: E + C·u = (A·C) + (A·D)·u ∈ Fp2 +;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +VAR GLOBAL escalarMulFp2BN254_i + +escalarMulFp2BN254: + ; Compute and check the mul + ; A·C - 0·D = [E] + (q0·BN254_P) + ; A·D + 0·C = [OP] + (q1·BN254_P) + 0n => B + ${ARITH_BN254_MULFP2_X(A,B,C,D)} => E + ${ARITH_BN254_MULFP2_Y(A,B,C,D)} :MSTORE(escalarMulFp2BN254_i), ARITH_BN254_MULFP2 + + $ => C :MLOAD(escalarMulFp2BN254_i), RETURN \ No newline at end of file diff --git a/main/pairings/FP2BN254/invFp2BN254.zkasm b/main/pairings/FP2BN254/invFp2BN254.zkasm new file mode 100644 index 00000000..0635b151 --- /dev/null +++ b/main/pairings/FP2BN254/invFp2BN254.zkasm @@ -0,0 +1,66 @@ +;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; POST: The result is in the range [0,BN254_P) +;; +;; invFp2BN254 +;; in: (A + B·u) ∈ Fp2, where A,B ∈ Fp +;; out: C + D·u = (A·(A² + B²)⁻¹) + (-B·(A² + B²)⁻¹)·u ∈ Fp2 +;; +;; NOTE: On input 0, it returns 0 +;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +VAR GLOBAL invFp2BN254_x +VAR GLOBAL invFp2BN254_y + +VAR GLOBAL invFp2BN254_RR + +invFp2BN254: + RR :MSTORE(invFp2BN254_RR) + + B :MSTORE(invFp2BN254_y) + ; Normalization of A,B + %BN254_P => B + $ :LT, JMPC(__invFp2BN254_reduce_A_continue) + :CALL(reduceFpBN254) + __invFp2BN254_reduce_A_continue: + A :MSTORE(invFp2BN254_x) + $ => A :MLOAD(invFp2BN254_y) + %BN254_P => B + $ :LT, JMPC(__invFp2BN254_reduce_B_continue) + :CALL(reduceFpBN254) + __invFp2BN254_reduce_B_continue: + A :MSTORE(invFp2BN254_y) + ; From here, it is guaranteed that A,B ∈ [0,BN254_P) + +invFp2BN254_zero_check: + ; Check if A = B = 0, and if so, return 0 + $ => B :MLOAD(invFp2BN254_x) + 0 => A + $ :EQ, JMPNC(invFp2BN254_normalized) + $ => B :MLOAD(invFp2BN254_y) + $ :EQ, JMPC(invFp2BN254_input_is_zero) + +invFp2BN254_normalized: + $ => A :MLOAD(invFp2BN254_x) + $ => B :MLOAD(invFp2BN254_y) + ; Remember that an element y ∈ Fp2 is the inverse of x ∈ Fp2 if and only if x·y = 1 in Fp2 + ; We therefore check that (A + B·u)·(C + D·u) = 1 + 0·u + ; A·[C] - B·[D] = 1 + (q0·BN254_P) + ; A·[D] + B·[C] = 0 + (q1·BN254_P) + ${fp2InvBN254_x(mem.invFp2BN254_x,mem.invFp2BN254_y)} => C + ${fp2InvBN254_y(mem.invFp2BN254_x,mem.invFp2BN254_y)} => D + 1n => E + 0n :ARITH_BN254_MULFP2 + + ; Check that the resulting elements are lower than BN254_P + %BN254_P => B + C => A + 1 :LT + D => A + 1 :LT, JMP(invFp2BN254_end) + +invFp2BN254_input_is_zero: + 0 => C,D + +invFp2BN254_end: + $ => RR :MLOAD(invFp2BN254_RR) + :RETURN \ No newline at end of file diff --git a/main/pairings/FP2BN254/mulFp2BN254.zkasm b/main/pairings/FP2BN254/mulFp2BN254.zkasm new file mode 100644 index 00000000..46c85799 --- /dev/null +++ b/main/pairings/FP2BN254/mulFp2BN254.zkasm @@ -0,0 +1,19 @@ +;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; POST: ARITH_BN254_MULFP2 ensures that the result is in the range [0,BN254_P) +;; +;; mulFp2BN254: +;; in: (A + B·u), (C + D·u) ∈ Fp2, where A,B,C,D ∈ Fp +;; out: E + C·u = (A·C - B·D) + (A·D + B·C)·u ∈ Fp2 +;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +VAR GLOBAL mulFp2BN254_i + +mulFp2BN254: + ; Compute and check the mul + ; A·C - B·D = [E] + (q0·BN254_P) + ; A·D + B·C = [OP] + (q1·BN254_P) + ${ARITH_BN254_MULFP2_X(A,B,C,D)} => E + ${ARITH_BN254_MULFP2_Y(A,B,C,D)} :MSTORE(mulFp2BN254_i), ARITH_BN254_MULFP2 + + $ => C :MLOAD(mulFp2BN254_i), RETURN \ No newline at end of file diff --git a/main/pairings/FP2BN254/squareFp2BN254.zkasm b/main/pairings/FP2BN254/squareFp2BN254.zkasm new file mode 100644 index 00000000..e5d738e6 --- /dev/null +++ b/main/pairings/FP2BN254/squareFp2BN254.zkasm @@ -0,0 +1,21 @@ +;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; POST: ARITH_BN254_MULFP2 ensures that the result is in the range [0,BN254_P) +;; +;; squareFp2BN254: +;; in: (A + B·u) ∈ Fp2, where A,B ∈ Fp +;; out: E + C·u = (A - B)·(A + B) + (2·A·B)·u ∈ Fp2 +;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +VAR GLOBAL squareFp2BN254_i + +squareFp2BN254: + ; Compute and check the squaring + ; A·A - B·B = [E] + (q0·BN254_P) + ; A·B + B·A = [OP] + (q1·BN254_P) + A => C + B => D + ${ARITH_BN254_MULFP2_X(A,B,A,B)} => E + ${ARITH_BN254_MULFP2_Y(A,B,A,B)} :MSTORE(squareFp2BN254_i), ARITH_BN254_MULFP2 + + $ => C :MLOAD(squareFp2BN254_i), RETURN \ No newline at end of file diff --git a/main/pairings/FP2BN254/subFp2BN254.zkasm b/main/pairings/FP2BN254/subFp2BN254.zkasm new file mode 100644 index 00000000..9dc84720 --- /dev/null +++ b/main/pairings/FP2BN254/subFp2BN254.zkasm @@ -0,0 +1,19 @@ +;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; POST: ARITH_BN254_SUBFP2 ensures that the result is in the range [0,BN254_P) +;; +;; subFp2BN254: +;; in: (A + B·u), (C + D·u) ∈ Fp2, where A,B,C,D ∈ Fp +;; out: E + C·u = (A - C) + (B - D)·u ∈ Fp2 +;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +VAR GLOBAL subFp2BN254_i + +subFp2BN254: + ; Compute and check the mul + ; A - C = [E] + (q0·BN254_P) + ; B - D = [OP] + (q1·BN254_P) + ${ARITH_BN254_SUBFP2(A,C)} => E + ${ARITH_BN254_SUBFP2(B,D)} :MSTORE(subFp2BN254_i), ARITH_BN254_SUBFP2 + + $ => C :MLOAD(subFp2BN254_i), RETURN diff --git a/main/pairings/FP4BN254/squareFp4BN254.zkasm b/main/pairings/FP4BN254/squareFp4BN254.zkasm new file mode 100644 index 00000000..ef064800 --- /dev/null +++ b/main/pairings/FP4BN254/squareFp4BN254.zkasm @@ -0,0 +1,76 @@ +;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; POST: The result is in the range [0,BN254_P) because if falls back to FP2 arithmetic +;; +;; squareFp4BN254: +;; in: (a1 + a2·V) ∈ Fp4, where ai ∈ Fp2 +;; out: (c1 + c2·V) ∈ Fp4, where: +;; - c1 = a2²·(9 + u) + a1² +;; - c2 = (a1 + a2)² - a1² - a2² +;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +VAR GLOBAL squareFp4BN254_a1_x +VAR GLOBAL squareFp4BN254_a1_y +VAR GLOBAL squareFp4BN254_a2_x +VAR GLOBAL squareFp4BN254_a2_y +VAR GLOBAL squareFp4BN254_c1_x +VAR GLOBAL squareFp4BN254_c1_y +VAR GLOBAL squareFp4BN254_c2_x +VAR GLOBAL squareFp4BN254_c2_y + +VAR GLOBAL squareFp4BN254_a1square_x +VAR GLOBAL squareFp4BN254_a1square_y +VAR GLOBAL squareFp4BN254_a2square_x +VAR GLOBAL squareFp4BN254_a2square_y + +VAR GLOBAL squareFp4BN254_RR + +squareFp4BN254: + RR :MSTORE(squareFp4BN254_RR) + + ; 1] a1² + $ => A :MLOAD(squareFp4BN254_a1_x) + $ => B :MLOAD(squareFp4BN254_a1_y), CALL(squareFp2BN254) + E :MSTORE(squareFp4BN254_a1square_x) + C :MSTORE(squareFp4BN254_a1square_y) + + ; 2] a2² + $ => A :MLOAD(squareFp4BN254_a2_x) + $ => B :MLOAD(squareFp4BN254_a2_y), CALL(squareFp2BN254) + E :MSTORE(squareFp4BN254_a2square_x) + C :MSTORE(squareFp4BN254_a2square_y) + + ; 3] c1 = a2²·(9 + u) + a1² + $ => A :MLOAD(squareFp4BN254_a2square_x) + $ => B :MLOAD(squareFp4BN254_a2square_y) + 9n => C + 1n => D :CALL(mulFp2BN254) + + E => A + C => B + $ => C :MLOAD(squareFp4BN254_a1square_x) + $ => D :MLOAD(squareFp4BN254_a1square_y), CALL(addFp2BN254) + E :MSTORE(squareFp4BN254_c1_x) + C :MSTORE(squareFp4BN254_c1_y) + + ; 4] c2 = (a1 + a2)² - a1² - a2² + $ => A :MLOAD(squareFp4BN254_a1_x) + $ => B :MLOAD(squareFp4BN254_a1_y) + $ => C :MLOAD(squareFp4BN254_a2_x) + $ => D :MLOAD(squareFp4BN254_a2_y), CALL(addFp2BN254) + E => A + C => B :CALL(squareFp2BN254) + + E => A + C => B + $ => C :MLOAD(squareFp4BN254_a1square_x) + $ => D :MLOAD(squareFp4BN254_a1square_y), CALL(subFp2BN254) + E => A + C => B + $ => C :MLOAD(squareFp4BN254_a2square_x) + $ => D :MLOAD(squareFp4BN254_a2square_y), CALL(subFp2BN254) + E :MSTORE(squareFp4BN254_c2_x) + C :MSTORE(squareFp4BN254_c2_y) + + $ => RR :MLOAD(squareFp4BN254_RR) + :RETURN \ No newline at end of file diff --git a/main/pairings/FP6BN254/addFp6BN254.zkasm b/main/pairings/FP6BN254/addFp6BN254.zkasm new file mode 100644 index 00000000..8854b6bd --- /dev/null +++ b/main/pairings/FP6BN254/addFp6BN254.zkasm @@ -0,0 +1,59 @@ +;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; POST: The result is in the range [0,BN254_P) because if falls back to FP2 arithmetic +;; +;; addFp6BN254: +;; in: (a1 + a2·v + a3·v²),(b1 + b2·v + b3·v²) ∈ Fp6, where ai,bi ∈ Fp2 +;; out: (c1 + c2·v + c3·v²) = (a1+b1) + (a2+b2)·v + (a3+b3)·v² ∈ Fp6 +;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +VAR GLOBAL addFp6BN254_a1_x +VAR GLOBAL addFp6BN254_a1_y +VAR GLOBAL addFp6BN254_a2_x +VAR GLOBAL addFp6BN254_a2_y +VAR GLOBAL addFp6BN254_a3_x +VAR GLOBAL addFp6BN254_a3_y +VAR GLOBAL addFp6BN254_b1_x +VAR GLOBAL addFp6BN254_b1_y +VAR GLOBAL addFp6BN254_b2_x +VAR GLOBAL addFp6BN254_b2_y +VAR GLOBAL addFp6BN254_b3_x +VAR GLOBAL addFp6BN254_b3_y +VAR GLOBAL addFp6BN254_c1_x +VAR GLOBAL addFp6BN254_c1_y +VAR GLOBAL addFp6BN254_c2_x +VAR GLOBAL addFp6BN254_c2_y +VAR GLOBAL addFp6BN254_c3_x +VAR GLOBAL addFp6BN254_c3_y + +VAR GLOBAL addFp6BN254_RR + +addFp6BN254: + RR :MSTORE(addFp6BN254_RR) + + ; 1] c1 = a1+b1 + $ => A :MLOAD(addFp6BN254_a1_x) + $ => B :MLOAD(addFp6BN254_a1_y) + $ => C :MLOAD(addFp6BN254_b1_x) + $ => D :MLOAD(addFp6BN254_b1_y), CALL(addFp2BN254) + E :MSTORE(addFp6BN254_c1_x) + C :MSTORE(addFp6BN254_c1_y) + + ; 2] c2 = a2+b2 + $ => A :MLOAD(addFp6BN254_a2_x) + $ => B :MLOAD(addFp6BN254_a2_y) + $ => C :MLOAD(addFp6BN254_b2_x) + $ => D :MLOAD(addFp6BN254_b2_y), CALL(addFp2BN254) + E :MSTORE(addFp6BN254_c2_x) + C :MSTORE(addFp6BN254_c2_y) + + ; 3] c3 = a3+b3 + $ => A :MLOAD(addFp6BN254_a3_x) + $ => B :MLOAD(addFp6BN254_a3_y) + $ => C :MLOAD(addFp6BN254_b3_x) + $ => D :MLOAD(addFp6BN254_b3_y), CALL(addFp2BN254) + E :MSTORE(addFp6BN254_c3_x) + C :MSTORE(addFp6BN254_c3_y) + + $ => RR :MLOAD(addFp6BN254_RR) + :RETURN \ No newline at end of file diff --git a/main/pairings/FP6BN254/escalarMulFp6BN254.zkasm b/main/pairings/FP6BN254/escalarMulFp6BN254.zkasm new file mode 100644 index 00000000..878abcd5 --- /dev/null +++ b/main/pairings/FP6BN254/escalarMulFp6BN254.zkasm @@ -0,0 +1,51 @@ +;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; POST: The result is in the range [0,BN254_P) because if falls back to FP2 arithmetic +;; +;; escalarMulFp6BN254: +;; in: b ∈ Fp, (a1 + a2·v + a3·v²) ∈ Fp6, where ai ∈ Fp2 +;; out: (c1 + c2·v + c3·v²) = (a1·b) + (a2·b)·v + (a3·b)·v² ∈ Fp6 +;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +VAR GLOBAL escalarMulFp6BN254_a1_x +VAR GLOBAL escalarMulFp6BN254_a1_y +VAR GLOBAL escalarMulFp6BN254_a2_x +VAR GLOBAL escalarMulFp6BN254_a2_y +VAR GLOBAL escalarMulFp6BN254_a3_x +VAR GLOBAL escalarMulFp6BN254_a3_y +VAR GLOBAL escalarMulFp6BN254_b +VAR GLOBAL escalarMulFp6BN254_c1_x +VAR GLOBAL escalarMulFp6BN254_c1_y +VAR GLOBAL escalarMulFp6BN254_c2_x +VAR GLOBAL escalarMulFp6BN254_c2_y +VAR GLOBAL escalarMulFp6BN254_c3_x +VAR GLOBAL escalarMulFp6BN254_c3_y + +VAR GLOBAL escalarMulFp6BN254_RR + +escalarMulFp6BN254: + RR :MSTORE(escalarMulFp6BN254_RR) + + ; 1] c1 = a1·b + $ => A :MLOAD(escalarMulFp6BN254_b) + $ => C :MLOAD(escalarMulFp6BN254_a1_x) + $ => D :MLOAD(escalarMulFp6BN254_a1_y), CALL(escalarMulFp2BN254) + E :MSTORE(escalarMulFp6BN254_c1_x) + C :MSTORE(escalarMulFp6BN254_c1_y) + + ; 2] c2 = a2·b + $ => A :MLOAD(escalarMulFp6BN254_b) + $ => C :MLOAD(escalarMulFp6BN254_a2_x) + $ => D :MLOAD(escalarMulFp6BN254_a2_y), CALL(escalarMulFp2BN254) + E :MSTORE(escalarMulFp6BN254_c2_x) + C :MSTORE(escalarMulFp6BN254_c2_y) + + ; 3] c3 = a3·b + $ => A :MLOAD(escalarMulFp6BN254_b) + $ => C :MLOAD(escalarMulFp6BN254_a3_x) + $ => D :MLOAD(escalarMulFp6BN254_a3_y), CALL(escalarMulFp2BN254) + E :MSTORE(escalarMulFp6BN254_c3_x) + C :MSTORE(escalarMulFp6BN254_c3_y) + + $ => RR :MLOAD(escalarMulFp6BN254_RR) + :RETURN \ No newline at end of file diff --git a/main/pairings/FP6BN254/inverseFp6BN254.zkasm b/main/pairings/FP6BN254/inverseFp6BN254.zkasm new file mode 100644 index 00000000..d43a0a7f --- /dev/null +++ b/main/pairings/FP6BN254/inverseFp6BN254.zkasm @@ -0,0 +1,208 @@ +;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; POST: The result is in the range [0,BN254_P) because if falls back to FP2 arithmetic +;; +;; inverseFp6BN254: +;; in: (a1 + a2·v + a3·v²) ∈ Fp6, where ai ∈ Fp2 +;; out: (c1 + c2·v + c3·v²) ∈ Fp6, where: +;; - c1 = (a1² - (9 + u)·(a2·a3))·(a1·c1mid + xi·(a3·c2mid + a2·c3mid))⁻¹ +;; - c2 = ((9 + u)·a3² - (a1·a2))·(a1·c1mid + xi·(a3·c2mid + a2·c3mid))⁻¹ +;; - c3 = (a2²-a1·a3)·(a1·c1mid + xi·(a3·c2mid + a2·c3mid))⁻¹ +;; with +;; * c1mid = a1² - (9 + u)·(a2·a3) +;; * c2mid = (9 + u)·a3² - (a1·a2) +;; * c3mid = a2² - (a1·a3) +;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +VAR GLOBAL inverseFp6BN254_a1_x +VAR GLOBAL inverseFp6BN254_a1_y +VAR GLOBAL inverseFp6BN254_a2_x +VAR GLOBAL inverseFp6BN254_a2_y +VAR GLOBAL inverseFp6BN254_a3_x +VAR GLOBAL inverseFp6BN254_a3_y +VAR GLOBAL inverseFp6BN254_c1_x +VAR GLOBAL inverseFp6BN254_c1_y +VAR GLOBAL inverseFp6BN254_c2_x +VAR GLOBAL inverseFp6BN254_c2_y +VAR GLOBAL inverseFp6BN254_c3_x +VAR GLOBAL inverseFp6BN254_c3_y + +VAR GLOBAL inverseFp6BN254_a1square_x +VAR GLOBAL inverseFp6BN254_a1square_y +VAR GLOBAL inverseFp6BN254_a2square_x +VAR GLOBAL inverseFp6BN254_a2square_y +VAR GLOBAL inverseFp6BN254_a3square_x +VAR GLOBAL inverseFp6BN254_a3square_y +VAR GLOBAL inverseFp6BN254_a1a2mul_x +VAR GLOBAL inverseFp6BN254_a1a2mul_y +VAR GLOBAL inverseFp6BN254_a1a3mul_x +VAR GLOBAL inverseFp6BN254_a1a3mul_y +VAR GLOBAL inverseFp6BN254_a2a3mul_x +VAR GLOBAL inverseFp6BN254_a2a3mul_y +VAR GLOBAL inverseFp6BN254_c1mid_x +VAR GLOBAL inverseFp6BN254_c1mid_y +VAR GLOBAL inverseFp6BN254_c2mid_x +VAR GLOBAL inverseFp6BN254_c2mid_y +VAR GLOBAL inverseFp6BN254_c3mid_x +VAR GLOBAL inverseFp6BN254_c3mid_y +VAR GLOBAL inverseFp6BN254_im_x +VAR GLOBAL inverseFp6BN254_im_y + +VAR GLOBAL inverseFp6BN254_a3c2mid_x +VAR GLOBAL inverseFp6BN254_a3c2mid_y + +VAR GLOBAL inverseFp6BN254_xia2c3mid_x +VAR GLOBAL inverseFp6BN254_xia2c3mid_y +VAR GLOBAL inverseFp6BN254_last_x +VAR GLOBAL inverseFp6BN254_last_y + +VAR GLOBAL inverseFp6BN254_RR + +inverseFp6BN254: + RR :MSTORE(inverseFp6BN254_RR) + + ; 1] a1² + $ => A :MLOAD(inverseFp6BN254_a1_x) + $ => B :MLOAD(inverseFp6BN254_a1_y), CALL(squareFp2BN254) + E :MSTORE(inverseFp6BN254_a1square_x) + C :MSTORE(inverseFp6BN254_a1square_y) + + ; 2] a2² + $ => A :MLOAD(inverseFp6BN254_a2_x) + $ => B :MLOAD(inverseFp6BN254_a2_y), CALL(squareFp2BN254) + E :MSTORE(inverseFp6BN254_a2square_x) + C :MSTORE(inverseFp6BN254_a2square_y) + + ; 3] a3² + $ => A :MLOAD(inverseFp6BN254_a3_x) + $ => B :MLOAD(inverseFp6BN254_a3_y), CALL(squareFp2BN254) + E :MSTORE(inverseFp6BN254_a3square_x) + C :MSTORE(inverseFp6BN254_a3square_y) + + ; 4] a1·a2 + $ => A :MLOAD(inverseFp6BN254_a1_x) + $ => B :MLOAD(inverseFp6BN254_a1_y) + $ => C :MLOAD(inverseFp6BN254_a2_x) + $ => D :MLOAD(inverseFp6BN254_a2_y), CALL(mulFp2BN254) + E :MSTORE(inverseFp6BN254_a1a2mul_x) + C :MSTORE(inverseFp6BN254_a1a2mul_y) + + ; 5] a1·a3 + $ => A :MLOAD(inverseFp6BN254_a1_x) + $ => B :MLOAD(inverseFp6BN254_a1_y) + $ => C :MLOAD(inverseFp6BN254_a3_x) + $ => D :MLOAD(inverseFp6BN254_a3_y), CALL(mulFp2BN254) + E :MSTORE(inverseFp6BN254_a1a3mul_x) + C :MSTORE(inverseFp6BN254_a1a3mul_y) + + ; 6] a2·a3 + $ => A :MLOAD(inverseFp6BN254_a2_x) + $ => B :MLOAD(inverseFp6BN254_a2_y) + $ => C :MLOAD(inverseFp6BN254_a3_x) + $ => D :MLOAD(inverseFp6BN254_a3_y), CALL(mulFp2BN254) + E :MSTORE(inverseFp6BN254_a2a3mul_x) + C :MSTORE(inverseFp6BN254_a2a3mul_y) + + ; 7] c1mid = a1² - (9 + u)·(a2·a3) + 9n => A + 1n => B + $ => C :MLOAD(inverseFp6BN254_a2a3mul_x) + $ => D :MLOAD(inverseFp6BN254_a2a3mul_y), CALL(mulFp2BN254) + $ => A :MLOAD(inverseFp6BN254_a1square_x) + $ => B :MLOAD(inverseFp6BN254_a1square_y) + C => D + E => C :CALL(subFp2BN254) + + E :MSTORE(inverseFp6BN254_c1mid_x) + C :MSTORE(inverseFp6BN254_c1mid_y) + + ; 8] c2mid = (9 + u)·a3² - (a1·a2) + 9n => A + 1n => B + $ => C :MLOAD(inverseFp6BN254_a3square_x) + $ => D :MLOAD(inverseFp6BN254_a3square_y), CALL(mulFp2BN254) + E => A + C => B + $ => C :MLOAD(inverseFp6BN254_a1a2mul_x) + $ => D :MLOAD(inverseFp6BN254_a1a2mul_y), CALL(subFp2BN254) + E :MSTORE(inverseFp6BN254_c2mid_x) + C :MSTORE(inverseFp6BN254_c2mid_y) + + ; 9] c3mid = a2² - (a1·a3) + $ => A :MLOAD(inverseFp6BN254_a2square_x) + $ => B :MLOAD(inverseFp6BN254_a2square_y) + $ => C :MLOAD(inverseFp6BN254_a1a3mul_x) + $ => D :MLOAD(inverseFp6BN254_a1a3mul_y), CALL(subFp2BN254) + E :MSTORE(inverseFp6BN254_c3mid_x) + C :MSTORE(inverseFp6BN254_c3mid_y) + + ; 10] im = a1·c1mid + $ => A :MLOAD(inverseFp6BN254_a1_x) + $ => B :MLOAD(inverseFp6BN254_a1_y) + $ => C :MLOAD(inverseFp6BN254_c1mid_x) + $ => D :MLOAD(inverseFp6BN254_c1mid_y), CALL(mulFp2BN254) + E :MSTORE(inverseFp6BN254_im_x) + C :MSTORE(inverseFp6BN254_im_y) + + ; 11] last = (im + xi·(a3·c2mid + a2·c3mid))⁻¹ + $ => A :MLOAD(inverseFp6BN254_a3_x) + $ => B :MLOAD(inverseFp6BN254_a3_y) + $ => C :MLOAD(inverseFp6BN254_c2mid_x) + $ => D :MLOAD(inverseFp6BN254_c2mid_y), CALL(mulFp2BN254) + E :MSTORE(inverseFp6BN254_a3c2mid_x) + C :MSTORE(inverseFp6BN254_a3c2mid_y) + + $ => A :MLOAD(inverseFp6BN254_a2_x) + $ => B :MLOAD(inverseFp6BN254_a2_y) + $ => C :MLOAD(inverseFp6BN254_c3mid_x) + $ => D :MLOAD(inverseFp6BN254_c3mid_y), CALL(mulFp2BN254) + + $ => A :MLOAD(inverseFp6BN254_a3c2mid_x) + $ => B :MLOAD(inverseFp6BN254_a3c2mid_y) + C => D + E => C :CALL(addFp2BN254) + + 9n => A + 1n => B + C => D + E => C :CALL(mulFp2BN254) + + $ => A :MLOAD(inverseFp6BN254_im_x) + $ => B :MLOAD(inverseFp6BN254_im_y) + C => D + E => C :CALL(addFp2BN254) + + E => A + C => B + $ => C :MLOAD(inverseFp6BN254_xia2c3mid_x) + $ => D :MLOAD(inverseFp6BN254_xia2c3mid_y), CALL(addFp2BN254) + E => A + C => B :CALL(invFp2BN254) + + C :MSTORE(inverseFp6BN254_last_x) + D :MSTORE(inverseFp6BN254_last_y) + + ; 12] c1 = c1mid·last, c2 = c2mid·last, c3 = c3mid·last + $ => A :MLOAD(inverseFp6BN254_c1mid_x) + $ => B :MLOAD(inverseFp6BN254_c1mid_y) + $ => C :MLOAD(inverseFp6BN254_last_x) + $ => D :MLOAD(inverseFp6BN254_last_y), CALL(mulFp2BN254) + E :MSTORE(inverseFp6BN254_c1_x) + C :MSTORE(inverseFp6BN254_c1_y) + + $ => A :MLOAD(inverseFp6BN254_c2mid_x) + $ => B :MLOAD(inverseFp6BN254_c2mid_y) + $ => C :MLOAD(inverseFp6BN254_last_x) + $ => D :MLOAD(inverseFp6BN254_last_y), CALL(mulFp2BN254) + E :MSTORE(inverseFp6BN254_c2_x) + C :MSTORE(inverseFp6BN254_c2_y) + + $ => A :MLOAD(inverseFp6BN254_c3mid_x) + $ => B :MLOAD(inverseFp6BN254_c3mid_y) + $ => C :MLOAD(inverseFp6BN254_last_x) + $ => D :MLOAD(inverseFp6BN254_last_y), CALL(mulFp2BN254) + E :MSTORE(inverseFp6BN254_c3_x) + C :MSTORE(inverseFp6BN254_c3_y) + + $ => RR :MLOAD(inverseFp6BN254_RR) + :RETURN \ No newline at end of file diff --git a/main/pairings/FP6BN254/mulFp6BN254.zkasm b/main/pairings/FP6BN254/mulFp6BN254.zkasm new file mode 100644 index 00000000..a907ab17 --- /dev/null +++ b/main/pairings/FP6BN254/mulFp6BN254.zkasm @@ -0,0 +1,201 @@ +;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; POST: The result is in the range [0,BN254_P) because if falls back to FP2 arithmetic +;; +;; mulFp6BN254: +;; in: (a1 + a2·v + a3·v²),(b1 + b2·v + b3·v²) ∈ Fp6, where ai,bi ∈ Fp2 +;; out: (c1 + c2·v + c3·v²) ∈ Fp6, where: +;; - c1 = [(a2+a3)·(b2+b3) - a2·b2 - a3·b3]·(9+u) + a1·b1 +;; - c2 = (a1+a2)·(b1+b2) - a1·b1 - a2·b2 + (9+u)·(a3·b3) +;; - c3 = (a1+a3)·(b1+b3) - a1·b1 + a2·b2 - a3·b3 +;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +VAR GLOBAL mulFp6BN254_a1_x +VAR GLOBAL mulFp6BN254_a1_y +VAR GLOBAL mulFp6BN254_a2_x +VAR GLOBAL mulFp6BN254_a2_y +VAR GLOBAL mulFp6BN254_a3_x +VAR GLOBAL mulFp6BN254_a3_y +VAR GLOBAL mulFp6BN254_b1_x +VAR GLOBAL mulFp6BN254_b1_y +VAR GLOBAL mulFp6BN254_b2_x +VAR GLOBAL mulFp6BN254_b2_y +VAR GLOBAL mulFp6BN254_b3_x +VAR GLOBAL mulFp6BN254_b3_y +VAR GLOBAL mulFp6BN254_c1_x +VAR GLOBAL mulFp6BN254_c1_y +VAR GLOBAL mulFp6BN254_c2_x +VAR GLOBAL mulFp6BN254_c2_y +VAR GLOBAL mulFp6BN254_c3_x +VAR GLOBAL mulFp6BN254_c3_y + +VAR GLOBAL mulFp6BN254_a1b1mul_x +VAR GLOBAL mulFp6BN254_a1b1mul_y +VAR GLOBAL mulFp6BN254_a2b2mul_x +VAR GLOBAL mulFp6BN254_a2b2mul_y +VAR GLOBAL mulFp6BN254_a3b3mul_x +VAR GLOBAL mulFp6BN254_a3b3mul_y +VAR GLOBAL mulFp6BN254_a3b3ximul_x +VAR GLOBAL mulFp6BN254_a3b3ximul_y + +VAR GLOBAL mulFp6BN254_a2a3sum_x +VAR GLOBAL mulFp6BN254_a2a3sum_y +VAR GLOBAL mulFp6BN254_b2b3sum_x +VAR GLOBAL mulFp6BN254_b2b3sum_y +VAR GLOBAL mulFp6BN254_a1a2sum_x +VAR GLOBAL mulFp6BN254_a1a2sum_y +VAR GLOBAL mulFp6BN254_b1b2sum_x +VAR GLOBAL mulFp6BN254_b1b2sum_y +VAR GLOBAL mulFp6BN254_a1a3sum_x +VAR GLOBAL mulFp6BN254_a1a3sum_y +VAR GLOBAL mulFp6BN254_b1b3sum_x +VAR GLOBAL mulFp6BN254_b1b3sum_y + +VAR GLOBAL mulFp6BN254_RR + +mulFp6BN254: + RR :MSTORE(mulFp6BN254_RR) + + ; 1] a1·b1, a2·b2, a3·b3, a3·b3·(9+u) + $ => A :MLOAD(mulFp6BN254_a1_x) + $ => B :MLOAD(mulFp6BN254_a1_y) + $ => C :MLOAD(mulFp6BN254_b1_x) + $ => D :MLOAD(mulFp6BN254_b1_y), CALL(mulFp2BN254) + E :MSTORE(mulFp6BN254_a1b1mul_x) + C :MSTORE(mulFp6BN254_a1b1mul_y) + + $ => A :MLOAD(mulFp6BN254_a2_x) + $ => B :MLOAD(mulFp6BN254_a2_y) + $ => C :MLOAD(mulFp6BN254_b2_x) + $ => D :MLOAD(mulFp6BN254_b2_y), CALL(mulFp2BN254) + E :MSTORE(mulFp6BN254_a2b2mul_x) + C :MSTORE(mulFp6BN254_a2b2mul_y) + + $ => A :MLOAD(mulFp6BN254_a3_x) + $ => B :MLOAD(mulFp6BN254_a3_y) + $ => C :MLOAD(mulFp6BN254_b3_x) + $ => D :MLOAD(mulFp6BN254_b3_y), CALL(mulFp2BN254) + E :MSTORE(mulFp6BN254_a3b3mul_x) + C :MSTORE(mulFp6BN254_a3b3mul_y) + + E => A + C => B + 9n => C + 1n => D :CALL(mulFp2BN254) + + E :MSTORE(mulFp6BN254_a3b3ximul_x) + C :MSTORE(mulFp6BN254_a3b3ximul_y) + + ; 2] a2+a3, b2+b3, a1+a2, b1+b2, a1+a3, b1+b3 + $ => A :MLOAD(mulFp6BN254_a2_x) + $ => B :MLOAD(mulFp6BN254_a2_y) + $ => C :MLOAD(mulFp6BN254_a3_x) + $ => D :MLOAD(mulFp6BN254_a3_y), CALL(addFp2BN254) + E :MSTORE(mulFp6BN254_a2a3sum_x) + C :MSTORE(mulFp6BN254_a2a3sum_y) + + $ => A :MLOAD(mulFp6BN254_b2_x) + $ => B :MLOAD(mulFp6BN254_b2_y) + $ => C :MLOAD(mulFp6BN254_b3_x) + $ => D :MLOAD(mulFp6BN254_b3_y), CALL(addFp2BN254) + E :MSTORE(mulFp6BN254_b2b3sum_x) + C :MSTORE(mulFp6BN254_b2b3sum_y) + + $ => A :MLOAD(mulFp6BN254_a1_x) + $ => B :MLOAD(mulFp6BN254_a1_y) + $ => C :MLOAD(mulFp6BN254_a2_x) + $ => D :MLOAD(mulFp6BN254_a2_y), CALL(addFp2BN254) + E :MSTORE(mulFp6BN254_a1a2sum_x) + C :MSTORE(mulFp6BN254_a1a2sum_y) + + $ => A :MLOAD(mulFp6BN254_b1_x) + $ => B :MLOAD(mulFp6BN254_b1_y) + $ => C :MLOAD(mulFp6BN254_b2_x) + $ => D :MLOAD(mulFp6BN254_b2_y), CALL(addFp2BN254) + E :MSTORE(mulFp6BN254_b1b2sum_x) + C :MSTORE(mulFp6BN254_b1b2sum_y) + + $ => A :MLOAD(mulFp6BN254_a1_x) + $ => B :MLOAD(mulFp6BN254_a1_y) + $ => C :MLOAD(mulFp6BN254_a3_x) + $ => D :MLOAD(mulFp6BN254_a3_y), CALL(addFp2BN254) + E :MSTORE(mulFp6BN254_a1a3sum_x) + C :MSTORE(mulFp6BN254_a1a3sum_y) + + $ => A :MLOAD(mulFp6BN254_b1_x) + $ => B :MLOAD(mulFp6BN254_b1_y) + $ => C :MLOAD(mulFp6BN254_b3_x) + $ => D :MLOAD(mulFp6BN254_b3_y), CALL(addFp2BN254) + E :MSTORE(mulFp6BN254_b1b3sum_x) + C :MSTORE(mulFp6BN254_b1b3sum_y) + + ; 3] c1 + $ => A :MLOAD(mulFp6BN254_a2a3sum_x) + $ => B :MLOAD(mulFp6BN254_a2a3sum_y) + $ => C :MLOAD(mulFp6BN254_b2b3sum_x) + $ => D :MLOAD(mulFp6BN254_b2b3sum_y), CALL(mulFp2BN254) + + E => A + C => B + $ => C :MLOAD(mulFp6BN254_a2b2mul_x) + $ => D :MLOAD(mulFp6BN254_a2b2mul_y), CALL(subFp2BN254) + E => A + C => B + $ => C :MLOAD(mulFp6BN254_a3b3mul_x) + $ => D :MLOAD(mulFp6BN254_a3b3mul_y), CALL(subFp2BN254) + E => A + C => B + 9n => C + 1n => D :CALL(mulFp2BN254) + + E => A + C => B + $ => C :MLOAD(mulFp6BN254_a1b1mul_x) + $ => D :MLOAD(mulFp6BN254_a1b1mul_y), CALL(addFp2BN254) + E :MSTORE(mulFp6BN254_c1_x) + C :MSTORE(mulFp6BN254_c1_y) + + ; 4] c2 + $ => A :MLOAD(mulFp6BN254_a1a2sum_x) + $ => B :MLOAD(mulFp6BN254_a1a2sum_y) + $ => C :MLOAD(mulFp6BN254_b1b2sum_x) + $ => D :MLOAD(mulFp6BN254_b1b2sum_y), CALL(mulFp2BN254) + + E => A + C => B + $ => C :MLOAD(mulFp6BN254_a1b1mul_x) + $ => D :MLOAD(mulFp6BN254_a1b1mul_y), CALL(subFp2BN254) + E => A + C => B + $ => C :MLOAD(mulFp6BN254_a2b2mul_x) + $ => D :MLOAD(mulFp6BN254_a2b2mul_y), CALL(subFp2BN254) + E => A + C => B + $ => C :MLOAD(mulFp6BN254_a3b3ximul_x) + $ => D :MLOAD(mulFp6BN254_a3b3ximul_y), CALL(addFp2BN254) + E :MSTORE(mulFp6BN254_c2_x) + C :MSTORE(mulFp6BN254_c2_y) + + ; 5] c3 + $ => A :MLOAD(mulFp6BN254_a1a3sum_x) + $ => B :MLOAD(mulFp6BN254_a1a3sum_y) + $ => C :MLOAD(mulFp6BN254_b1b3sum_x) + $ => D :MLOAD(mulFp6BN254_b1b3sum_y), CALL(mulFp2BN254) + + E => A + C => B + $ => C :MLOAD(mulFp6BN254_a1b1mul_x) + $ => D :MLOAD(mulFp6BN254_a1b1mul_y), CALL(subFp2BN254) + E => A + C => B + $ => C :MLOAD(mulFp6BN254_a2b2mul_x) + $ => D :MLOAD(mulFp6BN254_a2b2mul_y), CALL(addFp2BN254) + E => A + C => B + $ => C :MLOAD(mulFp6BN254_a3b3mul_x) + $ => D :MLOAD(mulFp6BN254_a3b3mul_y), CALL(subFp2BN254) + E :MSTORE(mulFp6BN254_c3_x) + C :MSTORE(mulFp6BN254_c3_y) + + $ => RR :MLOAD(mulFp6BN254_RR) + :RETURN \ No newline at end of file diff --git a/main/pairings/FP6BN254/sparseMulAFp6BN254.zkasm b/main/pairings/FP6BN254/sparseMulAFp6BN254.zkasm new file mode 100644 index 00000000..76d33d26 --- /dev/null +++ b/main/pairings/FP6BN254/sparseMulAFp6BN254.zkasm @@ -0,0 +1,65 @@ +;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; POST: The result is in the range [0,BN254_P) because if falls back to FP2 arithmetic +;; +;; sparseMulAFp6BN254: +;; in: (a1 + a2·v + a3·v²),b2·v ∈ Fp6, where ai,b2 ∈ Fp2 +;; out: (c1 + c2·v + c3·v²) ∈ Fp6, where: +;; - c1 = b2·a3·(9+u) +;; - c2 = b2·a1 +;; - c3 = b2·a2 +;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +VAR GLOBAL sparseMulAFp6BN254_a1_x +VAR GLOBAL sparseMulAFp6BN254_a1_y +VAR GLOBAL sparseMulAFp6BN254_a2_x +VAR GLOBAL sparseMulAFp6BN254_a2_y +VAR GLOBAL sparseMulAFp6BN254_a3_x +VAR GLOBAL sparseMulAFp6BN254_a3_y + +VAR GLOBAL sparseMulAFp6BN254_b2_x +VAR GLOBAL sparseMulAFp6BN254_b2_y + +VAR GLOBAL sparseMulAFp6BN254_c1_x +VAR GLOBAL sparseMulAFp6BN254_c1_y +VAR GLOBAL sparseMulAFp6BN254_c2_x +VAR GLOBAL sparseMulAFp6BN254_c2_y +VAR GLOBAL sparseMulAFp6BN254_c3_x +VAR GLOBAL sparseMulAFp6BN254_c3_y + +VAR GLOBAL sparseMulAFp6BN254_RR + +sparseMulAFp6BN254: + RR :MSTORE(sparseMulAFp6BN254_RR) + + ; 1] c1 = b2·a3·(9+u) + $ => A :MLOAD(sparseMulAFp6BN254_b2_x) + $ => B :MLOAD(sparseMulAFp6BN254_b2_y) + $ => C :MLOAD(sparseMulAFp6BN254_a3_x) + $ => D :MLOAD(sparseMulAFp6BN254_a3_y), CALL(mulFp2BN254) + E => A + C => B + 9n => C + 1n => D :CALL(mulFp2BN254) + + E :MSTORE(sparseMulAFp6BN254_c1_x) + C :MSTORE(sparseMulAFp6BN254_c1_y) + + ; 2] c2 = b2·a1 + $ => A :MLOAD(sparseMulAFp6BN254_b2_x) + $ => B :MLOAD(sparseMulAFp6BN254_b2_y) + $ => C :MLOAD(sparseMulAFp6BN254_a1_x) + $ => D :MLOAD(sparseMulAFp6BN254_a1_y), CALL(mulFp2BN254) + E :MSTORE(sparseMulAFp6BN254_c2_x) + C :MSTORE(sparseMulAFp6BN254_c2_y) + + ; 3] c3 = b2·a2 + $ => A :MLOAD(sparseMulAFp6BN254_b2_x) + $ => B :MLOAD(sparseMulAFp6BN254_b2_y) + $ => C :MLOAD(sparseMulAFp6BN254_a2_x) + $ => D :MLOAD(sparseMulAFp6BN254_a2_y), CALL(mulFp2BN254) + E :MSTORE(sparseMulAFp6BN254_c3_x) + C :MSTORE(sparseMulAFp6BN254_c3_y) + + $ => RR :MLOAD(sparseMulAFp6BN254_RR) + :RETURN \ No newline at end of file diff --git a/main/pairings/FP6BN254/sparseMulBFp6BN254.zkasm b/main/pairings/FP6BN254/sparseMulBFp6BN254.zkasm new file mode 100644 index 00000000..e5353ee5 --- /dev/null +++ b/main/pairings/FP6BN254/sparseMulBFp6BN254.zkasm @@ -0,0 +1,134 @@ +;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; POST: The result is in the range [0,BN254_P) because if falls back to FP2 arithmetic +;; +;; sparseMulBFp6BN254: +;; in: (a1 + a2·v + a3·v²),(b2·v + b3·v²) ∈ Fp6, where ai,bi ∈ Fp2 +;; out: (c1 + c2·v + c3·v²) ∈ Fp6, where: +;; - c1 = [(a2 + a3)·(b2 + b3) - a2·b2 - a3·b3]·(9+u) +;; - c2 = a1·b2 + a3·b3·(9+u) +;; - c3 = (a1 + a3)·b3 - a3·b3 + a2·b2 +;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +VAR GLOBAL sparseMulBFp6BN254_a1_x +VAR GLOBAL sparseMulBFp6BN254_a1_y +VAR GLOBAL sparseMulBFp6BN254_a2_x +VAR GLOBAL sparseMulBFp6BN254_a2_y +VAR GLOBAL sparseMulBFp6BN254_a3_x +VAR GLOBAL sparseMulBFp6BN254_a3_y + +VAR GLOBAL sparseMulBFp6BN254_b2_x +VAR GLOBAL sparseMulBFp6BN254_b2_y +VAR GLOBAL sparseMulBFp6BN254_b3_x +VAR GLOBAL sparseMulBFp6BN254_b3_y + +VAR GLOBAL sparseMulBFp6BN254_c1_x +VAR GLOBAL sparseMulBFp6BN254_c1_y +VAR GLOBAL sparseMulBFp6BN254_c2_x +VAR GLOBAL sparseMulBFp6BN254_c2_y +VAR GLOBAL sparseMulBFp6BN254_c3_x +VAR GLOBAL sparseMulBFp6BN254_c3_y + +VAR GLOBAL sparseMulBFp6BN254_a2b2_x +VAR GLOBAL sparseMulBFp6BN254_a2b2_y +VAR GLOBAL sparseMulBFp6BN254_a3b3_x +VAR GLOBAL sparseMulBFp6BN254_a3b3_y +VAR GLOBAL sparseMulBFp6BN254_a2a3sum_x +VAR GLOBAL sparseMulBFp6BN254_a2a3sum_y +VAR GLOBAL sparseMulBFp6BN254_a1b2_x +VAR GLOBAL sparseMulBFp6BN254_a1b2_y + +VAR GLOBAL sparseMulBFp6BN254_RR + +sparseMulBFp6BN254: + RR :MSTORE(sparseMulBFp6BN254_RR) + + ; 1] a2·b2, a3·b3 + $ => A :MLOAD(sparseMulBFp6BN254_a2_x) + $ => B :MLOAD(sparseMulBFp6BN254_a2_y) + $ => C :MLOAD(sparseMulBFp6BN254_b2_x) + $ => D :MLOAD(sparseMulBFp6BN254_b2_y), CALL(mulFp2BN254) + E :MSTORE(sparseMulBFp6BN254_a2b2_x) + C :MSTORE(sparseMulBFp6BN254_a2b2_y) + + $ => A :MLOAD(sparseMulBFp6BN254_a3_x) + $ => B :MLOAD(sparseMulBFp6BN254_a3_y) + $ => C :MLOAD(sparseMulBFp6BN254_b3_x) + $ => D :MLOAD(sparseMulBFp6BN254_b3_y), CALL(mulFp2BN254) + E :MSTORE(sparseMulBFp6BN254_a3b3_x) + C :MSTORE(sparseMulBFp6BN254_a3b3_y) + + ; 2] c1 = ((a2 + a3)·(b2 + b3) - a2·b2 - a3·b3)·(9+u) + $ => A :MLOAD(sparseMulBFp6BN254_a2_x) + $ => B :MLOAD(sparseMulBFp6BN254_a2_y) + $ => C :MLOAD(sparseMulBFp6BN254_a3_x) + $ => D :MLOAD(sparseMulBFp6BN254_a3_y), CALL(addFp2BN254) + E :MSTORE(sparseMulBFp6BN254_a2a3sum_x) + C :MSTORE(sparseMulBFp6BN254_a2a3sum_y) + + $ => A :MLOAD(sparseMulBFp6BN254_b2_x) + $ => B :MLOAD(sparseMulBFp6BN254_b2_y) + $ => C :MLOAD(sparseMulBFp6BN254_b3_x) + $ => D :MLOAD(sparseMulBFp6BN254_b3_y), CALL(addFp2BN254) + E => A + C => B + $ => C :MLOAD(sparseMulBFp6BN254_a2a3sum_x) + $ => D :MLOAD(sparseMulBFp6BN254_a2a3sum_y), CALL(mulFp2BN254) + E => A + C => B + $ => C :MLOAD(sparseMulBFp6BN254_a2b2_x) + $ => D :MLOAD(sparseMulBFp6BN254_a2b2_y), CALL(subFp2BN254) + E => A + C => B + $ => C :MLOAD(sparseMulBFp6BN254_a3b3_x) + $ => D :MLOAD(sparseMulBFp6BN254_a3b3_y), CALL(subFp2BN254) + E => A + C => B + 9n => C + 1n => D :CALL(mulFp2BN254) + + E :MSTORE(sparseMulBFp6BN254_c1_x) + C :MSTORE(sparseMulBFp6BN254_c1_y) + + ; 3] c2 = a1·b2 + a3·b3·(9+u) + $ => A :MLOAD(sparseMulBFp6BN254_a1_x) + $ => B :MLOAD(sparseMulBFp6BN254_a1_y) + $ => C :MLOAD(sparseMulBFp6BN254_b2_x) + $ => D :MLOAD(sparseMulBFp6BN254_b2_y), CALL(mulFp2BN254) + E :MSTORE(sparseMulBFp6BN254_a1b2_x) + C :MSTORE(sparseMulBFp6BN254_a1b2_y) + + $ => A :MLOAD(sparseMulBFp6BN254_a3b3_x) + $ => B :MLOAD(sparseMulBFp6BN254_a3b3_y) + 9n => C + 1n => D :CALL(mulFp2BN254) + + E => A + C => B + $ => C :MLOAD(sparseMulBFp6BN254_a1b2_x) + $ => D :MLOAD(sparseMulBFp6BN254_a1b2_y), CALL(addFp2BN254) + E :MSTORE(sparseMulBFp6BN254_c2_x) + C :MSTORE(sparseMulBFp6BN254_c2_y) + + ; 4] c3 = (a1 + a3)·b3 - a3·b3 + a2·b2 + $ => A :MLOAD(sparseMulBFp6BN254_a1_x) + $ => B :MLOAD(sparseMulBFp6BN254_a1_y) + $ => C :MLOAD(sparseMulBFp6BN254_a3_x) + $ => D :MLOAD(sparseMulBFp6BN254_a3_y), CALL(addFp2BN254) + E => A + C => B + $ => C :MLOAD(sparseMulBFp6BN254_b3_x) + $ => D :MLOAD(sparseMulBFp6BN254_b3_y), CALL(mulFp2BN254) + E => A + C => B + $ => C :MLOAD(sparseMulBFp6BN254_a3b3_x) + $ => D :MLOAD(sparseMulBFp6BN254_a3b3_y), CALL(subFp2BN254) + E => A + C => B + $ => C :MLOAD(sparseMulBFp6BN254_a2b2_x) + $ => D :MLOAD(sparseMulBFp6BN254_a2b2_y), CALL(addFp2BN254) + E :MSTORE(sparseMulBFp6BN254_c3_x) + C :MSTORE(sparseMulBFp6BN254_c3_y) + + $ => RR :MLOAD(sparseMulBFp6BN254_RR) + :RETURN \ No newline at end of file diff --git a/main/pairings/FP6BN254/sparseMulCFp6BN254.zkasm b/main/pairings/FP6BN254/sparseMulCFp6BN254.zkasm new file mode 100644 index 00000000..6c07be82 --- /dev/null +++ b/main/pairings/FP6BN254/sparseMulCFp6BN254.zkasm @@ -0,0 +1,128 @@ +;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; POST: The result is in the range [0,BN254_P) because if falls back to FP2 arithmetic +;; +;; sparseMulCFp6BN254: +;; in: (a1 + a2·v + a3·v²),(b1 + b3·v²) ∈ Fp6, where ai,bi ∈ Fp2 +;; out: (c1 + c2·v + c3·v²) ∈ Fp6, where: +;; - c1 = a1·b1 + a2·b3·(9+u) +;; - c2 = a2·b1 + a3·b3·(9+u) +;; - c3 = (a1 + a3)·(b1 + b3) - a1·b1 - a3·b3 +;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +VAR GLOBAL sparseMulCFp6BN254_a1_x +VAR GLOBAL sparseMulCFp6BN254_a1_y +VAR GLOBAL sparseMulCFp6BN254_a2_x +VAR GLOBAL sparseMulCFp6BN254_a2_y +VAR GLOBAL sparseMulCFp6BN254_a3_x +VAR GLOBAL sparseMulCFp6BN254_a3_y + +VAR GLOBAL sparseMulCFp6BN254_b1_x +VAR GLOBAL sparseMulCFp6BN254_b1_y +VAR GLOBAL sparseMulCFp6BN254_b3_x +VAR GLOBAL sparseMulCFp6BN254_b3_y + +VAR GLOBAL sparseMulCFp6BN254_c1_x +VAR GLOBAL sparseMulCFp6BN254_c1_y +VAR GLOBAL sparseMulCFp6BN254_c2_x +VAR GLOBAL sparseMulCFp6BN254_c2_y +VAR GLOBAL sparseMulCFp6BN254_c3_x +VAR GLOBAL sparseMulCFp6BN254_c3_y + +VAR GLOBAL sparseMulCFp6BN254_a1b1_x +VAR GLOBAL sparseMulCFp6BN254_a1b1_y +VAR GLOBAL sparseMulCFp6BN254_a3b3_x +VAR GLOBAL sparseMulCFp6BN254_a3b3_y +VAR GLOBAL sparseMulCFp6BN254_a2b1_x +VAR GLOBAL sparseMulCFp6BN254_a2b1_y +VAR GLOBAL sparseMulCFp6BN254_a1a3sum_x +VAR GLOBAL sparseMulCFp6BN254_a1a3sum_y + +VAR GLOBAL sparseMulCFp6BN254_RR + +sparseMulCFp6BN254: + RR :MSTORE(sparseMulCFp6BN254_RR) + + ; 1] a1·b1, a3·b3 + $ => A :MLOAD(sparseMulCFp6BN254_a1_x) + $ => B :MLOAD(sparseMulCFp6BN254_a1_y) + $ => C :MLOAD(sparseMulCFp6BN254_b1_x) + $ => D :MLOAD(sparseMulCFp6BN254_b1_y), CALL(mulFp2BN254) + E :MSTORE(sparseMulCFp6BN254_a1b1_x) + C :MSTORE(sparseMulCFp6BN254_a1b1_y) + + $ => A :MLOAD(sparseMulCFp6BN254_a3_x) + $ => B :MLOAD(sparseMulCFp6BN254_a3_y) + $ => C :MLOAD(sparseMulCFp6BN254_b3_x) + $ => D :MLOAD(sparseMulCFp6BN254_b3_y), CALL(mulFp2BN254) + E :MSTORE(sparseMulCFp6BN254_a3b3_x) + C :MSTORE(sparseMulCFp6BN254_a3b3_y) + + ; 2] c1 = a1·b1 + a2·b3·(9+u) + $ => A :MLOAD(sparseMulCFp6BN254_a2_x) + $ => B :MLOAD(sparseMulCFp6BN254_a2_y) + $ => C :MLOAD(sparseMulCFp6BN254_b3_x) + $ => D :MLOAD(sparseMulCFp6BN254_b3_y), CALL(mulFp2BN254) + E => A + C => B + 9n => C + 1n => D :CALL(mulFp2BN254) + + E => A + C => B + $ => C :MLOAD(sparseMulCFp6BN254_a1b1_x) + $ => D :MLOAD(sparseMulCFp6BN254_a1b1_y), CALL(addFp2BN254) + E :MSTORE(sparseMulCFp6BN254_c1_x) + C :MSTORE(sparseMulCFp6BN254_c1_y) + + ; 3] c2 = a2·b1 + a3·b3·(9+u) + $ => A :MLOAD(sparseMulCFp6BN254_a2_x) + $ => B :MLOAD(sparseMulCFp6BN254_a2_y) + $ => C :MLOAD(sparseMulCFp6BN254_b1_x) + $ => D :MLOAD(sparseMulCFp6BN254_b1_y), CALL(mulFp2BN254) + E :MSTORE(sparseMulCFp6BN254_a2b1_x) + C :MSTORE(sparseMulCFp6BN254_a2b1_y) + + $ => A :MLOAD(sparseMulCFp6BN254_a3b3_x) + $ => B :MLOAD(sparseMulCFp6BN254_a3b3_y) + 9n => C + 1n => D :CALL(mulFp2BN254) + + E => A + C => B + $ => C :MLOAD(sparseMulCFp6BN254_a2b1_x) + $ => D :MLOAD(sparseMulCFp6BN254_a2b1_y), CALL(addFp2BN254) + E :MSTORE(sparseMulCFp6BN254_c2_x) + C :MSTORE(sparseMulCFp6BN254_c2_y) + + + ; 4] c3 = (a1 + a3)·(b1 + b3) - a1·b1 - a3·b3 + $ => A :MLOAD(sparseMulCFp6BN254_a1_x) + $ => B :MLOAD(sparseMulCFp6BN254_a1_y) + $ => C :MLOAD(sparseMulCFp6BN254_a3_x) + $ => D :MLOAD(sparseMulCFp6BN254_a3_y), CALL(addFp2BN254) + E :MSTORE(sparseMulCFp6BN254_a1a3sum_x) + C :MSTORE(sparseMulCFp6BN254_a1a3sum_y) + + $ => A :MLOAD(sparseMulCFp6BN254_b1_x) + $ => B :MLOAD(sparseMulCFp6BN254_b1_y) + $ => C :MLOAD(sparseMulCFp6BN254_b3_x) + $ => D :MLOAD(sparseMulCFp6BN254_b3_y), CALL(addFp2BN254) + E => A + C => B + $ => C :MLOAD(sparseMulCFp6BN254_a1a3sum_x) + $ => D :MLOAD(sparseMulCFp6BN254_a1a3sum_y), CALL(mulFp2BN254) + E => A + C => B + $ => C :MLOAD(sparseMulCFp6BN254_a1b1_x) + $ => D :MLOAD(sparseMulCFp6BN254_a1b1_y), CALL(subFp2BN254) + E => A + C => B + $ => C :MLOAD(sparseMulCFp6BN254_a3b3_x) + $ => D :MLOAD(sparseMulCFp6BN254_a3b3_y), CALL(subFp2BN254) + E :MSTORE(sparseMulCFp6BN254_c3_x) + C :MSTORE(sparseMulCFp6BN254_c3_y) + + + $ => RR :MLOAD(sparseMulCFp6BN254_RR) + :RETURN \ No newline at end of file diff --git a/main/pairings/FP6BN254/squareFp6BN254.zkasm b/main/pairings/FP6BN254/squareFp6BN254.zkasm new file mode 100644 index 00000000..fc9b62af --- /dev/null +++ b/main/pairings/FP6BN254/squareFp6BN254.zkasm @@ -0,0 +1,147 @@ +;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; POST: The result is in the range [0,BN254_P) because if falls back to FP2 arithmetic +;; +;; squareFp6BN254: +;; in: (a1 + a2·v + a3·v²) ∈ Fp6, where ai ∈ Fp2 +;; out: (c1 + c2·v + c3·v²) ∈ Fp6, where: +;; - c1 = 2·a2·a3·(9 + u) + a1² +;; - c2 = a3²·(9 + u) + 2·a1·a2 +;; - c3 = 2·a1·a2 - a3² + (a1 - a2 + a3)² + 2·a2·a3 - a1² +;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +VAR GLOBAL squareFp6BN254_a1_x +VAR GLOBAL squareFp6BN254_a1_y +VAR GLOBAL squareFp6BN254_a2_x +VAR GLOBAL squareFp6BN254_a2_y +VAR GLOBAL squareFp6BN254_a3_x +VAR GLOBAL squareFp6BN254_a3_y +VAR GLOBAL squareFp6BN254_c1_x +VAR GLOBAL squareFp6BN254_c1_y +VAR GLOBAL squareFp6BN254_c2_x +VAR GLOBAL squareFp6BN254_c2_y +VAR GLOBAL squareFp6BN254_c3_x +VAR GLOBAL squareFp6BN254_c3_y + +VAR GLOBAL squareFp6BN254_2a1a2mul_x +VAR GLOBAL squareFp6BN254_2a1a2mul_y +VAR GLOBAL squareFp6BN254_a3square_x +VAR GLOBAL squareFp6BN254_a3square_y +VAR GLOBAL squareFp6BN254_2a1a2a3sqsub_x +VAR GLOBAL squareFp6BN254_2a1a2a3sqsub_y +VAR GLOBAL squareFp6BN254_a1square_x +VAR GLOBAL squareFp6BN254_a1square_y +VAR GLOBAL squareFp6BN254_a1a2a3sub_x +VAR GLOBAL squareFp6BN254_a1a2a3sub_y +VAR GLOBAL squareFp6BN254_2a2a3mul_x +VAR GLOBAL squareFp6BN254_2a2a3mul_y + +VAR GLOBAL squareFp6BN254_RR + +squareFp6BN254: + RR :MSTORE(squareFp6BN254_RR) + + ; 1] 2·a1·a2 + $ => A :MLOAD(squareFp6BN254_a1_x) + $ => B :MLOAD(squareFp6BN254_a1_y) + $ => C :MLOAD(squareFp6BN254_a2_x) + $ => D :MLOAD(squareFp6BN254_a2_y), CALL(mulFp2BN254) + 2n => A + C => D + E => C :CALL(escalarMulFp2BN254) + + E :MSTORE(squareFp6BN254_2a1a2mul_x) + C :MSTORE(squareFp6BN254_2a1a2mul_y) + + ; 2] a3² + $ => A :MLOAD(squareFp6BN254_a3_x) + $ => B :MLOAD(squareFp6BN254_a3_y), CALL(squareFp2BN254) + E :MSTORE(squareFp6BN254_a3square_x) + C :MSTORE(squareFp6BN254_a3square_y) + + ; 3] c2 = a3²·(9 + u) + 2·a1·a2 + $ => A :MLOAD(squareFp6BN254_a3square_x) + $ => B :MLOAD(squareFp6BN254_a3square_y) + 9n => C + 1n => D :CALL(mulFp2BN254) + + $ => A :MLOAD(squareFp6BN254_2a1a2mul_x) + $ => B :MLOAD(squareFp6BN254_2a1a2mul_y) + C => D + E => C :CALL(addFp2BN254) + + E :MSTORE(squareFp6BN254_c2_x) + C :MSTORE(squareFp6BN254_c2_y) + + ; 4] 2·a1·a2 - a3² + $ => A :MLOAD(squareFp6BN254_2a1a2mul_x) + $ => B :MLOAD(squareFp6BN254_2a1a2mul_y) + $ => C :MLOAD(squareFp6BN254_a3square_x) + $ => D :MLOAD(squareFp6BN254_a3square_y), CALL(subFp2BN254) + E :MSTORE(squareFp6BN254_2a1a2a3sqsub_x) + C :MSTORE(squareFp6BN254_2a1a2a3sqsub_y) + + ; 5] a1² + $ => A :MLOAD(squareFp6BN254_a1_x) + $ => B :MLOAD(squareFp6BN254_a1_y), CALL(squareFp2BN254) + E :MSTORE(squareFp6BN254_a1square_x) + C :MSTORE(squareFp6BN254_a1square_y) + + ; 6] (a1 - a2 + a3)² + $ => A :MLOAD(squareFp6BN254_a1_x) + $ => B :MLOAD(squareFp6BN254_a1_y) + $ => C :MLOAD(squareFp6BN254_a2_x) + $ => D :MLOAD(squareFp6BN254_a2_y), CALL(subFp2BN254) + E => A + C => B + $ => C :MLOAD(squareFp6BN254_a3_x) + $ => D :MLOAD(squareFp6BN254_a3_y), CALL(addFp2BN254) + E => A + C => B :CALL(squareFp2BN254) + + E :MSTORE(squareFp6BN254_a1a2a3sub_x) + C :MSTORE(squareFp6BN254_a1a2a3sub_y) + + ; 7] 2·a2·a3 + $ => A :MLOAD(squareFp6BN254_a2_x) + $ => B :MLOAD(squareFp6BN254_a2_y) + $ => C :MLOAD(squareFp6BN254_a3_x) + $ => D :MLOAD(squareFp6BN254_a3_y), CALL(mulFp2BN254) + 2n => A + C => D + E => C :CALL(escalarMulFp2BN254) + + E :MSTORE(squareFp6BN254_2a2a3mul_x) + C :MSTORE(squareFp6BN254_2a2a3mul_y) + + ; 8] c1 = 2·a2·a3·(9 + u) + a1² + $ => A :MLOAD(squareFp6BN254_2a2a3mul_x) + $ => B :MLOAD(squareFp6BN254_2a2a3mul_y) + 9n => C + 1n => D :CALL(mulFp2BN254) + + E => A + C => B + $ => C :MLOAD(squareFp6BN254_a1square_x) + $ => D :MLOAD(squareFp6BN254_a1square_y), CALL(addFp2BN254) + E :MSTORE(squareFp6BN254_c1_x) + C :MSTORE(squareFp6BN254_c1_y) + + ; 9] c3 = 2·a1·a2 - a3² + (a1 - a2 + a3)² + 2·a2·a3 - a1² + $ => A :MLOAD(squareFp6BN254_2a1a2a3sqsub_x) + $ => B :MLOAD(squareFp6BN254_2a1a2a3sqsub_y) + $ => C :MLOAD(squareFp6BN254_a1a2a3sub_x) + $ => D :MLOAD(squareFp6BN254_a1a2a3sub_y), CALL(addFp2BN254) + E => A + C => B + $ => C :MLOAD(squareFp6BN254_2a2a3mul_x) + $ => D :MLOAD(squareFp6BN254_2a2a3mul_y), CALL(addFp2BN254) + E => A + C => B + $ => C :MLOAD(squareFp6BN254_a1square_x) + $ => D :MLOAD(squareFp6BN254_a1square_y), CALL(subFp2BN254) + E :MSTORE(squareFp6BN254_c3_x) + C :MSTORE(squareFp6BN254_c3_y) + + $ => RR :MLOAD(squareFp6BN254_RR) + :RETURN \ No newline at end of file diff --git a/main/pairings/FP6BN254/subFp6BN254.zkasm b/main/pairings/FP6BN254/subFp6BN254.zkasm new file mode 100644 index 00000000..af0ab16f --- /dev/null +++ b/main/pairings/FP6BN254/subFp6BN254.zkasm @@ -0,0 +1,59 @@ +;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; POST: The result is in the range [0,BN254_P) because if falls back to FP2 arithmetic +;; +;; subFp6BN254: +;; in: (a1 + a2·v + a3·v²),(b1 + b2·v + b3·v²) ∈ Fp6, where ai,bi ∈ Fp2 +;; out: (c1 + c2·v + c3·v²) = (a1-b1) + (a2-b2)·v + (a3-b3)·v² ∈ Fp6 +;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +VAR GLOBAL subFp6BN254_a1_x +VAR GLOBAL subFp6BN254_a1_y +VAR GLOBAL subFp6BN254_a2_x +VAR GLOBAL subFp6BN254_a2_y +VAR GLOBAL subFp6BN254_a3_x +VAR GLOBAL subFp6BN254_a3_y +VAR GLOBAL subFp6BN254_b1_x +VAR GLOBAL subFp6BN254_b1_y +VAR GLOBAL subFp6BN254_b2_x +VAR GLOBAL subFp6BN254_b2_y +VAR GLOBAL subFp6BN254_b3_x +VAR GLOBAL subFp6BN254_b3_y +VAR GLOBAL subFp6BN254_c1_x +VAR GLOBAL subFp6BN254_c1_y +VAR GLOBAL subFp6BN254_c2_x +VAR GLOBAL subFp6BN254_c2_y +VAR GLOBAL subFp6BN254_c3_x +VAR GLOBAL subFp6BN254_c3_y + +VAR GLOBAL subFp6BN254_RR + +subFp6BN254: + RR :MSTORE(subFp6BN254_RR) + + ; 1] c1 = a1-b1 + $ => A :MLOAD(subFp6BN254_a1_x) + $ => B :MLOAD(subFp6BN254_a1_y) + $ => C :MLOAD(subFp6BN254_b1_x) + $ => D :MLOAD(subFp6BN254_b1_y), CALL(subFp2BN254) + E :MSTORE(subFp6BN254_c1_x) + C :MSTORE(subFp6BN254_c1_y) + + ; 2] c2 = a2-b2 + $ => A :MLOAD(subFp6BN254_a2_x) + $ => B :MLOAD(subFp6BN254_a2_y) + $ => C :MLOAD(subFp6BN254_b2_x) + $ => D :MLOAD(subFp6BN254_b2_y), CALL(subFp2BN254) + E :MSTORE(subFp6BN254_c2_x) + C :MSTORE(subFp6BN254_c2_y) + + ; 3] c3 = a3-b3 + $ => A :MLOAD(subFp6BN254_a3_x) + $ => B :MLOAD(subFp6BN254_a3_y) + $ => C :MLOAD(subFp6BN254_b3_x) + $ => D :MLOAD(subFp6BN254_b3_y), CALL(subFp2BN254) + E :MSTORE(subFp6BN254_c3_x) + C :MSTORE(subFp6BN254_c3_y) + + $ => RR :MLOAD(subFp6BN254_RR) + :RETURN \ No newline at end of file diff --git a/main/pairings/FPBN254/addFpBN254.zkasm b/main/pairings/FPBN254/addFpBN254.zkasm new file mode 100644 index 00000000..3c6043c7 --- /dev/null +++ b/main/pairings/FPBN254/addFpBN254.zkasm @@ -0,0 +1,29 @@ +;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; POST: The result is in the range [0,BN254_P) +;; +;; addFpBN254: +;; in: A,C ∈ Fp +;; out: C = A + C (mod BN254_P) ∈ Fp +;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +addFpBN254: + ; 1] Compute and check the sum over Z + ; A·[1] + C = [D]·2²⁵⁶ + [E] + 1 => B + $${var _addFpBN254_AC = A + C} + ${_addFpBN254_AC >> 256} => D + ${_addFpBN254_AC} => E :ARITH + + ; 2] Check it over Fp, that is, it must be satisfied that: + ; [BN254_P]·[(A+C) / p] + [(A+C) % p] = D·2²⁵⁶ + E + ; where C < BN254_P + %BN254_P => A + ${_addFpBN254_AC / const.BN254_P} => B ; quotient (256 bits) + ${_addFpBN254_AC % const.BN254_P} => C ; residue (256 bits) + E :ARITH + + ; 3] Check that the result is lower than BN254_P + A => B + C => A + 1 :LT, RETURN \ No newline at end of file diff --git a/main/pairings/FPBN254/invFpBN254.zkasm b/main/pairings/FPBN254/invFpBN254.zkasm new file mode 100644 index 00000000..bf61486d --- /dev/null +++ b/main/pairings/FPBN254/invFpBN254.zkasm @@ -0,0 +1,55 @@ +;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; POST: The result is in the range [0,BN254_P) +;; +;; invFpBN254: +;; in: A ∈ Fp +;; out: B = A⁻¹ (mod BN254_P) ∈ Fp +;; +;; NOTE: On input 0, it returns 0 +;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +VAR GLOBAL invFpBN254_tmp +VAR GLOBAL invFpBN254_RR + +invFpBN254: + RR :MSTORE(invFpBN254_RR) + + ; Normalization of A + %BN254_P => B + $ :LT, JMPC(invFpBN254_zero_check) + :CALL(reduceFpBN254) + ; From here, it is guaranteed that A ∈ [0,BN254_P) + +invFpBN254_zero_check: + ; Check if A = 0, and if so, return 0 + 0 => B + $ :EQ, JMPC(invFpBN254_A_is_zero) + +invFpBN254_normalized: + ; 1] Compute and check the inverse over Z + ; A·A⁻¹ + [0] = [D]·2²⁵⁶ + [E] + 0 => C + ${var _invFpBN254_A = fpBN254inv(A)} => B :MSTORE(invFpBN254_tmp); + $${var _invFpBN254_AB = A * _invFpBN254_A} + ${_invFpBN254_AB >> 256} => D + ${_invFpBN254_AB} => E :ARITH + + ; 2] Check it over Fp, that is, it must be satisfied that: + ; [BN254_P]·[(A·A⁻¹) / BN254_P] + [1] = D·2²⁵⁶ + E + %BN254_P => A + ${_invFpBN254_AB / const.BN254_P} => B ; quotient (256 bits) + 1n => C ; residue (1 bit) + E :ARITH + + ; 3] Check that the result is lower than BN254_P + A => B + $ => A :MLOAD(invFpBN254_tmp) + 1 :LT + A => B :JMP(invFpBN254_end) + +invFpBN254_A_is_zero: + 0 => B + +invFpBN254_end: + $ => RR :MLOAD(invFpBN254_RR) + :RETURN \ No newline at end of file diff --git a/main/pairings/FPBN254/mulFpBN254.zkasm b/main/pairings/FPBN254/mulFpBN254.zkasm new file mode 100644 index 00000000..b77ac02e --- /dev/null +++ b/main/pairings/FPBN254/mulFpBN254.zkasm @@ -0,0 +1,29 @@ +;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; POST: The result is in the range [0,BN254_P) +;; +;; mulFpBN254: +;; in: A,B ∈ Fp +;; out: C = A·B (mod BN254_P) ∈ Fp +;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +mulFpBN254: + ; 1] Compute and check the sum over Z + ; A·B + [0] = [D]·2²⁵⁶ + [E] + 0 => C + $${var _mulFpBN254_AB = A*B} + ${_mulFpBN254_AB >> 256} => D + ${_mulFpBN254_AB} => E :ARITH + + ; 2] Check it over Fp, that is, it must be satisfied that: + ; [BN254_P]·[(A·B) / p] + [C / p] = D·2²⁵⁶ + E + ; where C < BN254_P + %BN254_P => A + ${_mulFpBN254_AB / const.BN254_P} => B ; quotient (256 bits) + ${_mulFpBN254_AB % const.BN254_P} => C ; residue (256 bits) + E :ARITH + + ; 3] Check that the result is lower than BN254_P + A => B + C => A + 1 :LT, RETURN \ No newline at end of file diff --git a/main/pairings/FPBN254/reduceFpBN254.zkasm b/main/pairings/FPBN254/reduceFpBN254.zkasm new file mode 100644 index 00000000..59929e79 --- /dev/null +++ b/main/pairings/FPBN254/reduceFpBN254.zkasm @@ -0,0 +1,25 @@ +;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; POST: The result is in the range [0,BN254_P) +;; +;; reduceFpBN254: +;; in: A ∈ [0, 2²⁵⁶-1] +;; out: A (mod BN254_P) ∈ Fp +;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +VAR GLOBAL reduceFpBN254_tmp + +reduceFpBN254: + ; 1] It must be satisfied that: + ; [BN254_P]·[A / p] + [A % p] = [0]·2²⁵⁶ + A + A :MSTORE(reduceFpBN254_tmp) + ${A / const.BN254_P} => B ; quotient (256 bits) + ${A % const.BN254_P} => C ; residue (256 bits) + %BN254_P => A + 0n => D + $ :MLOAD(reduceFpBN254_tmp), ARITH + + ; 2] Check the the residue is less than p + A => B + C => A + 1 :LT, RETURN \ No newline at end of file diff --git a/main/pairings/FPBN254/squareFpBN254.zkasm b/main/pairings/FPBN254/squareFpBN254.zkasm new file mode 100644 index 00000000..9b8ced1b --- /dev/null +++ b/main/pairings/FPBN254/squareFpBN254.zkasm @@ -0,0 +1,31 @@ +;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; POST: The result is in the range [0,BN254_P) +;; +;; squareFpBN254: +;; in: A ∈ Fp +;; out: B = A² (mod BN254_P) ∈ Fp +;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +squareFpBN254: + ; 1] Compute and check the inverse over Z + ; A·A + [0] = [D]·2²⁵⁶ + [E] + A => B + 0 => C + $${var _squareFpBN254_AA = A * A} + ${_squareFpBN254_AA >> 256} => D + ${_squareFpBN254_AA} => E :ARITH + + ; 2] Check it over Fp, that is, it must be satisfied that: + ; [BN254_P]·[A² / p] + [A² % p] = D·2²⁵⁶ + E + ; where C < BN254_P + %BN254_P => A + ${_squareFpBN254_AA / const.BN254_P} => B ; quotient (256 bits) + ${_squareFpBN254_AA % const.BN254_P} => C ; residue (256 bits) + E :ARITH + + ; 3] Check that the result is lower than BN254_P + A => B + C => A + 1 :LT + A => B :RETURN \ No newline at end of file diff --git a/main/pairings/FPBN254/subFpBN254.zkasm b/main/pairings/FPBN254/subFpBN254.zkasm new file mode 100644 index 00000000..517bcb58 --- /dev/null +++ b/main/pairings/FPBN254/subFpBN254.zkasm @@ -0,0 +1,30 @@ +;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; POST: The result is in the range [0,BN254_P) +;; +;; subFpBN254: +;; in: A,C ∈ Fp +;; out: C = A - C (mod BN254_P) ∈ Fp +;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +subFpBN254: + ; 1] Compute and check the sub over Z + ; A·[1] + [BN254_P-C] = [D]·2²⁵⁶ + [E] + 1 => B + ${const.BN254_P - C} => C + $${var _subFpBN254_AC = A + C} + ${_subFpBN254_AC >> 256} => D + ${_subFpBN254_AC} => E :ARITH + + ; 2] Check it over Fp, that is, it must be satisfied that: + ; [BN254_P]·[(A - C) / p] + [(A - C) % p] = D·2²⁵⁶ + E + ; where C < BN254_P + %BN254_P => A + ${_subFpBN254_AC / const.BN254_P} => B ; quotient (256 bits) + ${_subFpBN254_AC % const.BN254_P} => C ; residue (256 bits) + E :ARITH + + ; 3] Check that the result is lower than BN254_P + A => B + C => A + 1 :LT, RETURN \ No newline at end of file diff --git a/main/pairings/FRBN254/reduceFrBN254.zkasm b/main/pairings/FRBN254/reduceFrBN254.zkasm new file mode 100644 index 00000000..927bf85b --- /dev/null +++ b/main/pairings/FRBN254/reduceFrBN254.zkasm @@ -0,0 +1,25 @@ +;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; POST: The result is in the range [0,r) +;; +;; reduceFrBN254: +;; in: B ∈ [0, 2²⁵⁶-1] +;; out: A = B (mod BN254_R) ∈ Fr +;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +VAR GLOBAL reduceFrBN254_tmp + +reduceFrBN254: + ; 1] It must be satisfied that: + ; [BN254_R]·[B / r] + [B % r] = [0]·2²⁵⁶ + E + B :MSTORE(reduceFrBN254_tmp) + ${B % const.BN254_R} => C ; residue (256 bits) + ${B / const.BN254_R} => B ; quotient (256 bits) + %BN254_R => A + 0n => D + $ :MLOAD(reduceFrBN254_tmp), ARITH + + ; 2] Check the the residue is less than r + A => B + C => A + 1 :LT, RETURN \ No newline at end of file diff --git a/main/pairings/constants.zkasm b/main/pairings/constants.zkasm new file mode 100644 index 00000000..9811197e --- /dev/null +++ b/main/pairings/constants.zkasm @@ -0,0 +1,62 @@ +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; +;; Constants of the optimal Ate pairing over the BN254 curve +;; e: G1 x G2 --> GT +;; where G1 = E(Fp)[r] = E(Fp), G2 = E'(Fp2)[r] and GT = mu_r (the r-th roots of unity over Fp12* over the curves: +;; E/Fp: y² = x³ + 3, E'/Fp2: y² = x³ + 3/(9+u) +;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +; Basic constants: X = "BN family parameter", P = "base field order", R = "scalar field order" +; CONSTL %BN254_X = 4965661367192848881n ; Unused, just for reference +CONSTL %BN254_P = 21888242871839275222246405745257275088696311157297823662689037894645226208583n ; 36n * X ** 4n + 36n * X ** 3n + 24n * X ** 2n + 6n * X + 1n +; NOTE: It is satisfied that 5·p < 2²⁵⁶ < 6·p +CONSTL %BN254_P_MINUS_ONE = 21888242871839275222246405745257275088696311157297823662689037894645226208582n +CONSTL %BN254_R = 21888242871839275222246405745257275088548364400416034343698204186575808495617n ; 36n * X ** 4n + 36n * X ** 3n + 18n * X ** 2n + 6n * X + 1n +CONSTL %BN254_R_MINUS_ONE = 21888242871839275222246405745257275088548364400416034343698204186575808495616n + +; Precomputed values: 3/(9+u) and 6x² +CONSTL %BN254_E_B = 3n +CONSTL %BN254_ETWISTED_B_X = 19485874751759354771024239261021720505790618469301721065564631296452457478373n +CONSTL %BN254_ETWISTED_B_Y = 266929791119991161246907387137283842545076965332900288569378510910307636690n +CONSTL %BN254_SIX_TIMES_X_SQ = 147946756881789318990833708069417712966n + +; Coordinates of the generator of the group G1 +CONSTL %PAIRING_P1X = 1n +CONSTL %PAIRING_P1Y = 2n + +; Coordinates of the generator of the group G2 +CONSTL %PAIRING_P2X1 = 10857046999023057135944570762232829481370756359578518086990519993285655852781n +CONSTL %PAIRING_P2X2 = 11559732032986387107991004021392285783925812861821192530917403151452391805634n +CONSTL %PAIRING_P2Y1 = 8495653923123431417604973247489272438418190587263600148770280649306958101930n +CONSTL %PAIRING_P2Y2 = 4082367875863433681332203403145435568316851327593401208105741076214120093531n + +; Precomputed frobenius operator constants. These are used to compute f^p, f^p2 and f^p3 cheaply, where f ∈ Fp12 +; See: https://hackmd.io/kcEJAWISQ56eE6YpBnurgw#Frobenius-Operator +CONSTL %FROBENIUS_GAMMA111 = 8376118865763821496583973867626364092589906065868298776909617916018768340080n +CONSTL %FROBENIUS_GAMMA112 = 16469823323077808223889137241176536799009286646108169935659301613961712198316n +CONSTL %FROBENIUS_GAMMA121 = 21575463638280843010398324269430826099269044274347216827212613867836435027261n +CONSTL %FROBENIUS_GAMMA122 = 10307601595873709700152284273816112264069230130616436755625194854815875713954n +CONSTL %FROBENIUS_GAMMA131 = 2821565182194536844548159561693502659359617185244120367078079554186484126554n +CONSTL %FROBENIUS_GAMMA132 = 3505843767911556378687030309984248845540243509899259641013678093033130930403n +CONSTL %FROBENIUS_GAMMA131_NEGATED = 19066677689644738377698246183563772429336693972053703295610958340458742082029n ;%BN254_P - %FROBENIUS_GAMMA131 +CONSTL %FROBENIUS_GAMMA132_NEGATED = 18382399103927718843559375435273026243156067647398564021675359801612095278180n ;%BN254_P - %FROBENIUS_GAMMA132 +CONSTL %FROBENIUS_GAMMA141 = 2581911344467009335267311115468803099551665605076196740867805258568234346338n +CONSTL %FROBENIUS_GAMMA142 = 19937756971775647987995932169929341994314640652964949448313374472400716661030n +CONSTL %FROBENIUS_GAMMA151 = 685108087231508774477564247770172212460312782337200605669322048753928464687n +CONSTL %FROBENIUS_GAMMA152 = 8447204650696766136447902020341177575205426561248465145919723016860428151883n +CONSTL %FROBENIUS_GAMMA21 = 21888242871839275220042445260109153167277707414472061641714758635765020556617n +CONSTL %FROBENIUS_GAMMA22 = 21888242871839275220042445260109153167277707414472061641714758635765020556616n +CONSTL %FROBENIUS_GAMMA23 = 21888242871839275222246405745257275088696311157297823662689037894645226208582n +CONSTL %FROBENIUS_GAMMA24 = 2203960485148121921418603742825762020974279258880205651966n +CONSTL %FROBENIUS_GAMMA25 = 2203960485148121921418603742825762020974279258880205651967n +CONSTL %FROBENIUS_GAMMA311 = 11697423496358154304825782922584725312912383441159505038794027105778954184319n +CONSTL %FROBENIUS_GAMMA312 = 303847389135065887422783454877609941456349188919719272345083954437860409601n +CONSTL %FROBENIUS_GAMMA321 = 3772000881919853776433695186713858239009073593817195771773381919316419345261n +CONSTL %FROBENIUS_GAMMA322 = 2236595495967245188281701248203181795121068902605861227855261137820944008926n +CONSTL %FROBENIUS_GAMMA331 = 19066677689644738377698246183563772429336693972053703295610958340458742082029n +CONSTL %FROBENIUS_GAMMA332 = 18382399103927718843559375435273026243156067647398564021675359801612095278180n +CONSTL %FROBENIUS_GAMMA341 = 5324479202449903542726783395506214481928257762400643279780343368557297135718n +CONSTL %FROBENIUS_GAMMA342 = 16208900380737693084919495127334387981393726419856888799917914180988844123039n +CONSTL %FROBENIUS_GAMMA351 = 8941241848238582420466759817324047081148088512956452953208002715982955420483n +CONSTL %FROBENIUS_GAMMA352 = 10338197737521362862238855242243140895517409139741313354160881284257516364953n \ No newline at end of file diff --git a/main/pairings/ecPairing.zkasm b/main/pairings/ecPairing.zkasm new file mode 100644 index 00000000..16c235d2 --- /dev/null +++ b/main/pairings/ecPairing.zkasm @@ -0,0 +1,244 @@ +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; PRE: The number of inputs n is no larger than 2³²-1 +;; +;; ecPairing: +;; input: P1,...,Pn ∈ G1 and Q1,...,Qn ∈ G2, where G1 = E(Fp)[r] = E(Fp), G2 = E'(Fp2)[r] and +;; the curves are E/Fp: y² = x³ + 3 and E'/Fp2: y² = x³ + 3/(9+u) +;; output: 1 if e(P1,Q1)·...·e(Pn,Qn) = 1, 0 otherwise; where e: G1 x G2 -> GT is +;; the optimal Ate pairing over the BN254 curve and GT = mu_r (the r-th roots of unity over Fp12* +;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +VAR GLOBAL ecPairing_ninputs + +VAR GLOBAL ecPairing_mul_f11_x +VAR GLOBAL ecPairing_mul_f11_y +VAR GLOBAL ecPairing_mul_f12_x +VAR GLOBAL ecPairing_mul_f12_y +VAR GLOBAL ecPairing_mul_f13_x +VAR GLOBAL ecPairing_mul_f13_y +VAR GLOBAL ecPairing_mul_f21_x +VAR GLOBAL ecPairing_mul_f21_y +VAR GLOBAL ecPairing_mul_f22_x +VAR GLOBAL ecPairing_mul_f22_y +VAR GLOBAL ecPairing_mul_f23_x +VAR GLOBAL ecPairing_mul_f23_y + +VAR GLOBAL ecPairing_result + +VAR GLOBAL ecPairing_RR + +; ERROR CODES (B) +; 0 - no error +; 1 - error found in some input + +ecPairing: + RR :MSTORE(ecPairing_RR) + + ; clean the result + 0n :MSTORE(ecPairing_result) + + $ => A :MLOAD(ecPairing_ninputs), JMPZ(ecPairing_0_inputs) + + ; Initialize the multiplication with 1 + 1n :MSTORE(ecPairing_mul_f11_x) + 0n :MSTORE(ecPairing_mul_f11_y) + 0n :MSTORE(ecPairing_mul_f12_x) + 0n :MSTORE(ecPairing_mul_f12_y) + 0n :MSTORE(ecPairing_mul_f13_x) + 0n :MSTORE(ecPairing_mul_f13_y) + 0n :MSTORE(ecPairing_mul_f21_x) + 0n :MSTORE(ecPairing_mul_f21_y) + 0n :MSTORE(ecPairing_mul_f22_x) + 0n :MSTORE(ecPairing_mul_f22_y) + 0n :MSTORE(ecPairing_mul_f23_x) + 0n :MSTORE(ecPairing_mul_f23_y) + + :JMP(ecPairing_Miller_loop) + +ecPairing_0_inputs: + 1 :MSTORE(ecPairing_result) + :JMP(ecPairing_correct) + +ecPairing_Miller_loop: + $ => E :MLOAD(readXFromCalldataOffset) + 32 :MSTORE(readXFromCalldataLength) + E + 32 => E :MSTORE(readXFromCalldataOffset), CALL(readFromCalldataOffset); in: [readXFromCalldataOffset: offset value, readXFromCalldataLength: length value], out: [readXFromCalldataResult: result value] + $ => A :MLOAD(readXFromCalldataResult) + A :MSTORE(halfPairingBN254_P_x) + E + 32 => E :MSTORE(readXFromCalldataOffset), CALL(readFromCalldataOffset); in: [readXFromCalldataOffset: offset value, readXFromCalldataLength: length value], out: [readXFromCalldataResult: result value] + $ => A :MLOAD(readXFromCalldataResult) + A :MSTORE(halfPairingBN254_P_y) + E + 32 => E :MSTORE(readXFromCalldataOffset), CALL(readFromCalldataOffset); in: [readXFromCalldataOffset: offset value, readXFromCalldataLength: length value], out: [readXFromCalldataResult: result value] + $ => A :MLOAD(readXFromCalldataResult) + A :MSTORE(halfPairingBN254_Q_x2) + E + 32 => E :MSTORE(readXFromCalldataOffset), CALL(readFromCalldataOffset); in: [readXFromCalldataOffset: offset value, readXFromCalldataLength: length value], out: [readXFromCalldataResult: result value] + $ => A :MLOAD(readXFromCalldataResult) + A :MSTORE(halfPairingBN254_Q_x1) + E + 32 => E :MSTORE(readXFromCalldataOffset), CALL(readFromCalldataOffset); in: [readXFromCalldataOffset: offset value, readXFromCalldataLength: length value], out: [readXFromCalldataResult: result value] + $ => A :MLOAD(readXFromCalldataResult) + A :MSTORE(halfPairingBN254_Q_y2) + E + 32 => E :MSTORE(readXFromCalldataOffset), CALL(readFromCalldataOffset); in: [readXFromCalldataOffset: offset value, readXFromCalldataLength: length value], out: [readXFromCalldataResult: result value] + $ => A :MLOAD(readXFromCalldataResult) + A :MSTORE(halfPairingBN254_Q_y1), CALL(halfPairingBN254) + + ; Check if the error code (B) of halfPairingBN254 is not 0, meaning there is an error in some of the inputs + B :JMPNZ(ecPairing_input_error) + + ; Multiply the current value of mul by the result of the Miller loop of the current 6-tuple + $ => A :MLOAD(ecPairing_mul_f11_x) + $ => B :MLOAD(ecPairing_mul_f11_y) + $ => C :MLOAD(ecPairing_mul_f12_x) + $ => D :MLOAD(ecPairing_mul_f12_y) + A :MSTORE(mulFp12BN254_a11_x) + B :MSTORE(mulFp12BN254_a11_y) + C :MSTORE(mulFp12BN254_a12_x) + D :MSTORE(mulFp12BN254_a12_y) + $ => A :MLOAD(ecPairing_mul_f13_x) + $ => B :MLOAD(ecPairing_mul_f13_y) + $ => C :MLOAD(ecPairing_mul_f21_x) + $ => D :MLOAD(ecPairing_mul_f21_y) + A :MSTORE(mulFp12BN254_a13_x) + B :MSTORE(mulFp12BN254_a13_y) + C :MSTORE(mulFp12BN254_a21_x) + D :MSTORE(mulFp12BN254_a21_y) + $ => A :MLOAD(ecPairing_mul_f22_x) + $ => B :MLOAD(ecPairing_mul_f22_y) + $ => C :MLOAD(ecPairing_mul_f23_x) + $ => D :MLOAD(ecPairing_mul_f23_y) + A :MSTORE(mulFp12BN254_a22_x) + B :MSTORE(mulFp12BN254_a22_y) + C :MSTORE(mulFp12BN254_a23_x) + D :MSTORE(mulFp12BN254_a23_y) + $ => A :MLOAD(halfPairingBN254_f11_x) + $ => B :MLOAD(halfPairingBN254_f11_y) + $ => C :MLOAD(halfPairingBN254_f12_x) + $ => D :MLOAD(halfPairingBN254_f12_y) + A :MSTORE(mulFp12BN254_b11_x) + B :MSTORE(mulFp12BN254_b11_y) + C :MSTORE(mulFp12BN254_b12_x) + D :MSTORE(mulFp12BN254_b12_y) + $ => A :MLOAD(halfPairingBN254_f13_x) + $ => B :MLOAD(halfPairingBN254_f13_y) + $ => C :MLOAD(halfPairingBN254_f21_x) + $ => D :MLOAD(halfPairingBN254_f21_y) + A :MSTORE(mulFp12BN254_b13_x) + B :MSTORE(mulFp12BN254_b13_y) + C :MSTORE(mulFp12BN254_b21_x) + D :MSTORE(mulFp12BN254_b21_y) + $ => A :MLOAD(halfPairingBN254_f22_x) + $ => B :MLOAD(halfPairingBN254_f22_y) + $ => C :MLOAD(halfPairingBN254_f23_x) + $ => D :MLOAD(halfPairingBN254_f23_y) + A :MSTORE(mulFp12BN254_b22_x) + B :MSTORE(mulFp12BN254_b22_y) + C :MSTORE(mulFp12BN254_b23_x) + D :MSTORE(mulFp12BN254_b23_y), CALL(mulFp12BN254) + + $ => A :MLOAD(mulFp12BN254_c11_x) + $ => B :MLOAD(mulFp12BN254_c11_y) + $ => C :MLOAD(mulFp12BN254_c12_x) + $ => D :MLOAD(mulFp12BN254_c12_y) + A :MSTORE(ecPairing_mul_f11_x) + B :MSTORE(ecPairing_mul_f11_y) + C :MSTORE(ecPairing_mul_f12_x) + D :MSTORE(ecPairing_mul_f12_y) + $ => A :MLOAD(mulFp12BN254_c13_x) + $ => B :MLOAD(mulFp12BN254_c13_y) + $ => C :MLOAD(mulFp12BN254_c21_x) + $ => D :MLOAD(mulFp12BN254_c21_y) + A :MSTORE(ecPairing_mul_f13_x) + B :MSTORE(ecPairing_mul_f13_y) + C :MSTORE(ecPairing_mul_f21_x) + D :MSTORE(ecPairing_mul_f21_y) + $ => A :MLOAD(mulFp12BN254_c22_x) + $ => B :MLOAD(mulFp12BN254_c22_y) + $ => C :MLOAD(mulFp12BN254_c23_x) + $ => D :MLOAD(mulFp12BN254_c23_y) + A :MSTORE(ecPairing_mul_f22_x) + B :MSTORE(ecPairing_mul_f22_y) + C :MSTORE(ecPairing_mul_f23_x) + D :MSTORE(ecPairing_mul_f23_y) + + $ => A :MLOAD(ecPairing_ninputs) + A - 1 => A :JMPZ(ecPairing_final_exponentiation) + A :MSTORE(ecPairing_ninputs) + :JMP(ecPairing_Miller_loop) + +ecPairing_final_exponentiation: + $ => A :MLOAD(mulFp12BN254_c11_x) + $ => B :MLOAD(mulFp12BN254_c11_y) + $ => C :MLOAD(mulFp12BN254_c12_x) + $ => D :MLOAD(mulFp12BN254_c12_y) + A :MSTORE(finalExpBN254_f11_x) + B :MSTORE(finalExpBN254_f11_y) + C :MSTORE(finalExpBN254_f12_x) + D :MSTORE(finalExpBN254_f12_y) + $ => A :MLOAD(mulFp12BN254_c13_x) + $ => B :MLOAD(mulFp12BN254_c13_y) + $ => C :MLOAD(mulFp12BN254_c21_x) + $ => D :MLOAD(mulFp12BN254_c21_y) + A :MSTORE(finalExpBN254_f13_x) + B :MSTORE(finalExpBN254_f13_y) + C :MSTORE(finalExpBN254_f21_x) + D :MSTORE(finalExpBN254_f21_y) + $ => A :MLOAD(mulFp12BN254_c22_x) + $ => B :MLOAD(mulFp12BN254_c22_y) + $ => C :MLOAD(mulFp12BN254_c23_x) + $ => D :MLOAD(mulFp12BN254_c23_y) + A :MSTORE(finalExpBN254_f22_x) + B :MSTORE(finalExpBN254_f22_y) + C :MSTORE(finalExpBN254_f23_x) + D :MSTORE(finalExpBN254_f23_y), CALL(finalExpBN254) + + ; Check whether the result is 1 or not + 1n => B + $ => A :MLOAD(finalExpBN254_f11_x) + $ :EQ, JMPNC(__finalExpBN254_result_continue) + 0n => B + $ => A :MLOAD(finalExpBN254_f11_y) + $ :EQ, JMPNC(__finalExpBN254_result_continue) + $ => A :MLOAD(finalExpBN254_f12_x) + $ :EQ, JMPNC(__finalExpBN254_result_continue) + $ => A :MLOAD(finalExpBN254_f12_y) + $ :EQ, JMPNC(__finalExpBN254_result_continue) + $ => A :MLOAD(finalExpBN254_f13_x) + $ :EQ, JMPNC(__finalExpBN254_result_continue) + $ => A :MLOAD(finalExpBN254_f13_y) + $ :EQ, JMPNC(__finalExpBN254_result_continue) + $ => A :MLOAD(finalExpBN254_f21_x) + $ :EQ, JMPNC(__finalExpBN254_result_continue) + $ => A :MLOAD(finalExpBN254_f21_y) + $ :EQ, JMPNC(__finalExpBN254_result_continue) + $ => A :MLOAD(finalExpBN254_f22_x) + $ :EQ, JMPNC(__finalExpBN254_result_continue) + $ => A :MLOAD(finalExpBN254_f22_y) + $ :EQ, JMPNC(__finalExpBN254_result_continue) + $ => A :MLOAD(finalExpBN254_f23_x) + $ :EQ, JMPNC(__finalExpBN254_result_continue) + $ => A :MLOAD(finalExpBN254_f23_y) + $ :EQ, JMPC(ecPairing_equation_is_satisfied) + __finalExpBN254_result_continue: + + ; the pairing equation is not satisfied, then output 0 + 0 :MSTORE(ecPairing_result) + :JMP(ecPairing_correct) + +ecPairing_equation_is_satisfied: + ; the pairing equation is satisfied, then output 1 + 1 :MSTORE(ecPairing_result) + :JMP(ecPairing_correct) + +; ERRORS +ecPairing_input_error: + 1 => B :JMP(ecPairing_error) + +ecPairing_correct: + 0 => B :JMP(ecPairing_end) + +ecPairing_error: + 0 => A + +ecPairing_end: + $ => RR :MLOAD(ecPairing_RR) + :RETURN \ No newline at end of file diff --git a/main/pairings/finalExpBN254.zkasm b/main/pairings/finalExpBN254.zkasm new file mode 100644 index 00000000..8dfae38a --- /dev/null +++ b/main/pairings/finalExpBN254.zkasm @@ -0,0 +1,2095 @@ +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; POST: The result is in the range [0,BN254_P) because if falls back to FP12 arithmetic +;; +;; finalExpBN254: +;; input: f ∈ Fp12 +;; output: f^((p¹²-1)/r) +;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +VAR GLOBAL finalExpBN254_f11_x +VAR GLOBAL finalExpBN254_f11_y +VAR GLOBAL finalExpBN254_f12_x +VAR GLOBAL finalExpBN254_f12_y +VAR GLOBAL finalExpBN254_f13_x +VAR GLOBAL finalExpBN254_f13_y +VAR GLOBAL finalExpBN254_f21_x +VAR GLOBAL finalExpBN254_f21_y +VAR GLOBAL finalExpBN254_f22_x +VAR GLOBAL finalExpBN254_f22_y +VAR GLOBAL finalExpBN254_f23_x +VAR GLOBAL finalExpBN254_f23_y + +VAR GLOBAL finalExpBN254_mx11_x +VAR GLOBAL finalExpBN254_mx11_y +VAR GLOBAL finalExpBN254_mx12_x +VAR GLOBAL finalExpBN254_mx12_y +VAR GLOBAL finalExpBN254_mx13_x +VAR GLOBAL finalExpBN254_mx13_y +VAR GLOBAL finalExpBN254_mx21_x +VAR GLOBAL finalExpBN254_mx21_y +VAR GLOBAL finalExpBN254_mx22_x +VAR GLOBAL finalExpBN254_mx22_y +VAR GLOBAL finalExpBN254_mx23_x +VAR GLOBAL finalExpBN254_mx23_y +VAR GLOBAL finalExpBN254_mxx11_x +VAR GLOBAL finalExpBN254_mxx11_y +VAR GLOBAL finalExpBN254_mxx12_x +VAR GLOBAL finalExpBN254_mxx12_y +VAR GLOBAL finalExpBN254_mxx13_x +VAR GLOBAL finalExpBN254_mxx13_y +VAR GLOBAL finalExpBN254_mxx21_x +VAR GLOBAL finalExpBN254_mxx21_y +VAR GLOBAL finalExpBN254_mxx22_x +VAR GLOBAL finalExpBN254_mxx22_y +VAR GLOBAL finalExpBN254_mxx23_x +VAR GLOBAL finalExpBN254_mxx23_y +VAR GLOBAL finalExpBN254_mxxx11_x +VAR GLOBAL finalExpBN254_mxxx11_y +VAR GLOBAL finalExpBN254_mxxx12_x +VAR GLOBAL finalExpBN254_mxxx12_y +VAR GLOBAL finalExpBN254_mxxx13_x +VAR GLOBAL finalExpBN254_mxxx13_y +VAR GLOBAL finalExpBN254_mxxx21_x +VAR GLOBAL finalExpBN254_mxxx21_y +VAR GLOBAL finalExpBN254_mxxx22_x +VAR GLOBAL finalExpBN254_mxxx22_y +VAR GLOBAL finalExpBN254_mxxx23_x +VAR GLOBAL finalExpBN254_mxxx23_y +VAR GLOBAL finalExpBN254_mp11_x +VAR GLOBAL finalExpBN254_mp11_y +VAR GLOBAL finalExpBN254_mp12_x +VAR GLOBAL finalExpBN254_mp12_y +VAR GLOBAL finalExpBN254_mp13_x +VAR GLOBAL finalExpBN254_mp13_y +VAR GLOBAL finalExpBN254_mp21_x +VAR GLOBAL finalExpBN254_mp21_y +VAR GLOBAL finalExpBN254_mp22_x +VAR GLOBAL finalExpBN254_mp22_y +VAR GLOBAL finalExpBN254_mp23_x +VAR GLOBAL finalExpBN254_mp23_y +VAR GLOBAL finalExpBN254_mpp11_x +VAR GLOBAL finalExpBN254_mpp11_y +VAR GLOBAL finalExpBN254_mpp12_x +VAR GLOBAL finalExpBN254_mpp12_y +VAR GLOBAL finalExpBN254_mpp13_x +VAR GLOBAL finalExpBN254_mpp13_y +VAR GLOBAL finalExpBN254_mpp21_x +VAR GLOBAL finalExpBN254_mpp21_y +VAR GLOBAL finalExpBN254_mpp22_x +VAR GLOBAL finalExpBN254_mpp22_y +VAR GLOBAL finalExpBN254_mpp23_x +VAR GLOBAL finalExpBN254_mpp23_y +VAR GLOBAL finalExpBN254_mppp11_x +VAR GLOBAL finalExpBN254_mppp11_y +VAR GLOBAL finalExpBN254_mppp12_x +VAR GLOBAL finalExpBN254_mppp12_y +VAR GLOBAL finalExpBN254_mppp13_x +VAR GLOBAL finalExpBN254_mppp13_y +VAR GLOBAL finalExpBN254_mppp21_x +VAR GLOBAL finalExpBN254_mppp21_y +VAR GLOBAL finalExpBN254_mppp22_x +VAR GLOBAL finalExpBN254_mppp22_y +VAR GLOBAL finalExpBN254_mppp23_x +VAR GLOBAL finalExpBN254_mppp23_y +VAR GLOBAL finalExpBN254_mxp11_x +VAR GLOBAL finalExpBN254_mxp11_y +VAR GLOBAL finalExpBN254_mxp12_x +VAR GLOBAL finalExpBN254_mxp12_y +VAR GLOBAL finalExpBN254_mxp13_x +VAR GLOBAL finalExpBN254_mxp13_y +VAR GLOBAL finalExpBN254_mxp21_x +VAR GLOBAL finalExpBN254_mxp21_y +VAR GLOBAL finalExpBN254_mxp22_x +VAR GLOBAL finalExpBN254_mxp22_y +VAR GLOBAL finalExpBN254_mxp23_x +VAR GLOBAL finalExpBN254_mxp23_y +VAR GLOBAL finalExpBN254_mxxp11_x +VAR GLOBAL finalExpBN254_mxxp11_y +VAR GLOBAL finalExpBN254_mxxp12_x +VAR GLOBAL finalExpBN254_mxxp12_y +VAR GLOBAL finalExpBN254_mxxp13_x +VAR GLOBAL finalExpBN254_mxxp13_y +VAR GLOBAL finalExpBN254_mxxp21_x +VAR GLOBAL finalExpBN254_mxxp21_y +VAR GLOBAL finalExpBN254_mxxp22_x +VAR GLOBAL finalExpBN254_mxxp22_y +VAR GLOBAL finalExpBN254_mxxp23_x +VAR GLOBAL finalExpBN254_mxxp23_y +VAR GLOBAL finalExpBN254_mxxxp11_x +VAR GLOBAL finalExpBN254_mxxxp11_y +VAR GLOBAL finalExpBN254_mxxxp12_x +VAR GLOBAL finalExpBN254_mxxxp12_y +VAR GLOBAL finalExpBN254_mxxxp13_x +VAR GLOBAL finalExpBN254_mxxxp13_y +VAR GLOBAL finalExpBN254_mxxxp21_x +VAR GLOBAL finalExpBN254_mxxxp21_y +VAR GLOBAL finalExpBN254_mxxxp22_x +VAR GLOBAL finalExpBN254_mxxxp22_y +VAR GLOBAL finalExpBN254_mxxxp23_x +VAR GLOBAL finalExpBN254_mxxxp23_y +VAR GLOBAL finalExpBN254_mxxpp11_x +VAR GLOBAL finalExpBN254_mxxpp11_y +VAR GLOBAL finalExpBN254_mxxpp12_x +VAR GLOBAL finalExpBN254_mxxpp12_y +VAR GLOBAL finalExpBN254_mxxpp13_x +VAR GLOBAL finalExpBN254_mxxpp13_y +VAR GLOBAL finalExpBN254_mxxpp21_x +VAR GLOBAL finalExpBN254_mxxpp21_y +VAR GLOBAL finalExpBN254_mxxpp22_x +VAR GLOBAL finalExpBN254_mxxpp22_y +VAR GLOBAL finalExpBN254_mxxpp23_x +VAR GLOBAL finalExpBN254_mxxpp23_y + +VAR GLOBAL finalExpBN254_y1_11_x +VAR GLOBAL finalExpBN254_y1_11_y +VAR GLOBAL finalExpBN254_y1_12_x +VAR GLOBAL finalExpBN254_y1_12_y +VAR GLOBAL finalExpBN254_y1_13_x +VAR GLOBAL finalExpBN254_y1_13_y +VAR GLOBAL finalExpBN254_y1_21_x +VAR GLOBAL finalExpBN254_y1_21_y +VAR GLOBAL finalExpBN254_y1_22_x +VAR GLOBAL finalExpBN254_y1_22_y +VAR GLOBAL finalExpBN254_y1_23_x +VAR GLOBAL finalExpBN254_y1_23_y +VAR GLOBAL finalExpBN254_y2_11_x +VAR GLOBAL finalExpBN254_y2_11_y +VAR GLOBAL finalExpBN254_y2_12_x +VAR GLOBAL finalExpBN254_y2_12_y +VAR GLOBAL finalExpBN254_y2_13_x +VAR GLOBAL finalExpBN254_y2_13_y +VAR GLOBAL finalExpBN254_y2_21_x +VAR GLOBAL finalExpBN254_y2_21_y +VAR GLOBAL finalExpBN254_y2_22_x +VAR GLOBAL finalExpBN254_y2_22_y +VAR GLOBAL finalExpBN254_y2_23_x +VAR GLOBAL finalExpBN254_y2_23_y + +VAR GLOBAL finalExpBN254_y4_11_x +VAR GLOBAL finalExpBN254_y4_11_y +VAR GLOBAL finalExpBN254_y4_12_x +VAR GLOBAL finalExpBN254_y4_12_y +VAR GLOBAL finalExpBN254_y4_13_x +VAR GLOBAL finalExpBN254_y4_13_y +VAR GLOBAL finalExpBN254_y4_21_x +VAR GLOBAL finalExpBN254_y4_21_y +VAR GLOBAL finalExpBN254_y4_22_x +VAR GLOBAL finalExpBN254_y4_22_y +VAR GLOBAL finalExpBN254_y4_23_x +VAR GLOBAL finalExpBN254_y4_23_y +VAR GLOBAL finalExpBN254_y5_11_x +VAR GLOBAL finalExpBN254_y5_11_y +VAR GLOBAL finalExpBN254_y5_12_x +VAR GLOBAL finalExpBN254_y5_12_y +VAR GLOBAL finalExpBN254_y5_13_x +VAR GLOBAL finalExpBN254_y5_13_y +VAR GLOBAL finalExpBN254_y5_21_x +VAR GLOBAL finalExpBN254_y5_21_y +VAR GLOBAL finalExpBN254_y5_22_x +VAR GLOBAL finalExpBN254_y5_22_y +VAR GLOBAL finalExpBN254_y5_23_x +VAR GLOBAL finalExpBN254_y5_23_y +VAR GLOBAL finalExpBN254_y6_11_x +VAR GLOBAL finalExpBN254_y6_11_y +VAR GLOBAL finalExpBN254_y6_12_x +VAR GLOBAL finalExpBN254_y6_12_y +VAR GLOBAL finalExpBN254_y6_13_x +VAR GLOBAL finalExpBN254_y6_13_y +VAR GLOBAL finalExpBN254_y6_21_x +VAR GLOBAL finalExpBN254_y6_21_y +VAR GLOBAL finalExpBN254_y6_22_x +VAR GLOBAL finalExpBN254_y6_22_y +VAR GLOBAL finalExpBN254_y6_23_x +VAR GLOBAL finalExpBN254_y6_23_y +VAR GLOBAL finalExpBN254_y7_11_x +VAR GLOBAL finalExpBN254_y7_11_y +VAR GLOBAL finalExpBN254_y7_12_x +VAR GLOBAL finalExpBN254_y7_12_y +VAR GLOBAL finalExpBN254_y7_13_x +VAR GLOBAL finalExpBN254_y7_13_y +VAR GLOBAL finalExpBN254_y7_21_x +VAR GLOBAL finalExpBN254_y7_21_y +VAR GLOBAL finalExpBN254_y7_22_x +VAR GLOBAL finalExpBN254_y7_22_y +VAR GLOBAL finalExpBN254_y7_23_x +VAR GLOBAL finalExpBN254_y7_23_y + +VAR GLOBAL finalExpBN254_T11_11_x +VAR GLOBAL finalExpBN254_T11_11_y +VAR GLOBAL finalExpBN254_T11_12_x +VAR GLOBAL finalExpBN254_T11_12_y +VAR GLOBAL finalExpBN254_T11_13_x +VAR GLOBAL finalExpBN254_T11_13_y +VAR GLOBAL finalExpBN254_T11_21_x +VAR GLOBAL finalExpBN254_T11_21_y +VAR GLOBAL finalExpBN254_T11_22_x +VAR GLOBAL finalExpBN254_T11_22_y +VAR GLOBAL finalExpBN254_T11_23_x +VAR GLOBAL finalExpBN254_T11_23_y +VAR GLOBAL finalExpBN254_T21_11_x +VAR GLOBAL finalExpBN254_T21_11_y +VAR GLOBAL finalExpBN254_T21_12_x +VAR GLOBAL finalExpBN254_T21_12_y +VAR GLOBAL finalExpBN254_T21_13_x +VAR GLOBAL finalExpBN254_T21_13_y +VAR GLOBAL finalExpBN254_T21_21_x +VAR GLOBAL finalExpBN254_T21_21_y +VAR GLOBAL finalExpBN254_T21_22_x +VAR GLOBAL finalExpBN254_T21_22_y +VAR GLOBAL finalExpBN254_T21_23_x +VAR GLOBAL finalExpBN254_T21_23_y +VAR GLOBAL finalExpBN254_T12_11_x +VAR GLOBAL finalExpBN254_T12_11_y +VAR GLOBAL finalExpBN254_T12_12_x +VAR GLOBAL finalExpBN254_T12_12_y +VAR GLOBAL finalExpBN254_T12_13_x +VAR GLOBAL finalExpBN254_T12_13_y +VAR GLOBAL finalExpBN254_T12_21_x +VAR GLOBAL finalExpBN254_T12_21_y +VAR GLOBAL finalExpBN254_T12_22_x +VAR GLOBAL finalExpBN254_T12_22_y +VAR GLOBAL finalExpBN254_T12_23_x +VAR GLOBAL finalExpBN254_T12_23_y +VAR GLOBAL finalExpBN254_T23_11_x +VAR GLOBAL finalExpBN254_T23_11_y +VAR GLOBAL finalExpBN254_T23_12_x +VAR GLOBAL finalExpBN254_T23_12_y +VAR GLOBAL finalExpBN254_T23_13_x +VAR GLOBAL finalExpBN254_T23_13_y +VAR GLOBAL finalExpBN254_T23_21_x +VAR GLOBAL finalExpBN254_T23_21_y +VAR GLOBAL finalExpBN254_T23_22_x +VAR GLOBAL finalExpBN254_T23_22_y +VAR GLOBAL finalExpBN254_T23_23_x +VAR GLOBAL finalExpBN254_T23_23_y +VAR GLOBAL finalExpBN254_T24_11_x +VAR GLOBAL finalExpBN254_T24_11_y +VAR GLOBAL finalExpBN254_T24_12_x +VAR GLOBAL finalExpBN254_T24_12_y +VAR GLOBAL finalExpBN254_T24_13_x +VAR GLOBAL finalExpBN254_T24_13_y +VAR GLOBAL finalExpBN254_T24_21_x +VAR GLOBAL finalExpBN254_T24_21_y +VAR GLOBAL finalExpBN254_T24_22_x +VAR GLOBAL finalExpBN254_T24_22_y +VAR GLOBAL finalExpBN254_T24_23_x +VAR GLOBAL finalExpBN254_T24_23_y + +VAR GLOBAL finalExpBN254_RR + +finalExpBN254: + RR :MSTORE(finalExpBN254_RR) + + ; The easy part: + ; =========================================== + ; 1] f^(p⁶-1) = f̅·f⁻¹ + $ => A :MLOAD(finalExpBN254_f11_x) + $ => B :MLOAD(finalExpBN254_f11_y) + A :MSTORE(inverseFp12BN254_a11_x) + B :MSTORE(inverseFp12BN254_a11_y) + $ => A :MLOAD(finalExpBN254_f12_x) + $ => B :MLOAD(finalExpBN254_f12_y) + A :MSTORE(inverseFp12BN254_a12_x) + B :MSTORE(inverseFp12BN254_a12_y) + $ => A :MLOAD(finalExpBN254_f13_x) + $ => B :MLOAD(finalExpBN254_f13_y) + A :MSTORE(inverseFp12BN254_a13_x) + B :MSTORE(inverseFp12BN254_a13_y) + $ => A :MLOAD(finalExpBN254_f21_x) + $ => B :MLOAD(finalExpBN254_f21_y) + A :MSTORE(inverseFp12BN254_a21_x) + B :MSTORE(inverseFp12BN254_a21_y) + $ => A :MLOAD(finalExpBN254_f22_x) + $ => B :MLOAD(finalExpBN254_f22_y) + A :MSTORE(inverseFp12BN254_a22_x) + B :MSTORE(inverseFp12BN254_a22_y) + $ => A :MLOAD(finalExpBN254_f23_x) + $ => B :MLOAD(finalExpBN254_f23_y) + A :MSTORE(inverseFp12BN254_a23_x) + B :MSTORE(inverseFp12BN254_a23_y), CALL(inverseFp12BN254) + + $ => A :MLOAD(inverseFp12BN254_c11_x) + $ => B :MLOAD(inverseFp12BN254_c11_y) + A :MSTORE(mulFp12BN254_b11_x) + B :MSTORE(mulFp12BN254_b11_y) + $ => A :MLOAD(inverseFp12BN254_c12_x) + $ => B :MLOAD(inverseFp12BN254_c12_y) + A :MSTORE(mulFp12BN254_b12_x) + B :MSTORE(mulFp12BN254_b12_y) + $ => A :MLOAD(inverseFp12BN254_c13_x) + $ => B :MLOAD(inverseFp12BN254_c13_y) + A :MSTORE(mulFp12BN254_b13_x) + B :MSTORE(mulFp12BN254_b13_y) + $ => A :MLOAD(inverseFp12BN254_c21_x) + $ => B :MLOAD(inverseFp12BN254_c21_y) + A :MSTORE(mulFp12BN254_b21_x) + B :MSTORE(mulFp12BN254_b21_y) + $ => A :MLOAD(inverseFp12BN254_c22_x) + $ => B :MLOAD(inverseFp12BN254_c22_y) + A :MSTORE(mulFp12BN254_b22_x) + B :MSTORE(mulFp12BN254_b22_y) + $ => A :MLOAD(inverseFp12BN254_c23_x) + $ => B :MLOAD(inverseFp12BN254_c23_y) + A :MSTORE(mulFp12BN254_b23_x) + B :MSTORE(mulFp12BN254_b23_y) + $ => A :MLOAD(finalExpBN254_f11_x) + $ => B :MLOAD(finalExpBN254_f11_y) + A :MSTORE(mulFp12BN254_a11_x) + B :MSTORE(mulFp12BN254_a11_y) + $ => A :MLOAD(finalExpBN254_f12_x) + $ => B :MLOAD(finalExpBN254_f12_y) + A :MSTORE(mulFp12BN254_a12_x) + B :MSTORE(mulFp12BN254_a12_y) + $ => A :MLOAD(finalExpBN254_f13_x) + $ => B :MLOAD(finalExpBN254_f13_y) + A :MSTORE(mulFp12BN254_a13_x) + B :MSTORE(mulFp12BN254_a13_y) + + %BN254_P => A + $ => B :MLOAD(finalExpBN254_f21_x) + $ :SUB, MSTORE(mulFp12BN254_a21_x) + %BN254_P => A + $ => B :MLOAD(finalExpBN254_f21_y) + $ :SUB, MSTORE(mulFp12BN254_a21_y) + %BN254_P => A + $ => B :MLOAD(finalExpBN254_f22_x) + $ :SUB, MSTORE(mulFp12BN254_a22_x) + %BN254_P => A + $ => B :MLOAD(finalExpBN254_f22_y) + $ :SUB, MSTORE(mulFp12BN254_a22_y) + %BN254_P => A + $ => B :MLOAD(finalExpBN254_f23_x) + $ :SUB, MSTORE(mulFp12BN254_a23_x) + %BN254_P => A + $ => B :MLOAD(finalExpBN254_f23_y) + $ :SUB, MSTORE(mulFp12BN254_a23_y), CALL(mulFp12BN254) + + $ => A :MLOAD(mulFp12BN254_c11_x) + $ => B :MLOAD(mulFp12BN254_c11_y) + A :MSTORE(finalExpBN254_f11_x) + B :MSTORE(finalExpBN254_f11_y) + $ => A :MLOAD(mulFp12BN254_c12_x) + $ => B :MLOAD(mulFp12BN254_c12_y) + A :MSTORE(finalExpBN254_f12_x) + B :MSTORE(finalExpBN254_f12_y) + $ => A :MLOAD(mulFp12BN254_c13_x) + $ => B :MLOAD(mulFp12BN254_c13_y) + A :MSTORE(finalExpBN254_f13_x) + B :MSTORE(finalExpBN254_f13_y) + $ => A :MLOAD(mulFp12BN254_c21_x) + $ => B :MLOAD(mulFp12BN254_c21_y) + A :MSTORE(finalExpBN254_f21_x) + B :MSTORE(finalExpBN254_f21_y) + $ => A :MLOAD(mulFp12BN254_c22_x) + $ => B :MLOAD(mulFp12BN254_c22_y) + A :MSTORE(finalExpBN254_f22_x) + B :MSTORE(finalExpBN254_f22_y) + $ => A :MLOAD(mulFp12BN254_c23_x) + $ => B :MLOAD(mulFp12BN254_c23_y) + A :MSTORE(finalExpBN254_f23_x) + B :MSTORE(finalExpBN254_f23_y) + + ; 2] f^(p⁶-1)(p²-1) = (f^(p⁶-1))^p²·f^(p⁶-1) + $ => A :MLOAD(finalExpBN254_f11_x) + $ => B :MLOAD(finalExpBN254_f11_y) + A :MSTORE(frob2Fp12BN254_a11_x) + B :MSTORE(frob2Fp12BN254_a11_y) + $ => A :MLOAD(finalExpBN254_f12_x) + $ => B :MLOAD(finalExpBN254_f12_y) + A :MSTORE(frob2Fp12BN254_a12_x) + B :MSTORE(frob2Fp12BN254_a12_y) + $ => A :MLOAD(finalExpBN254_f13_x) + $ => B :MLOAD(finalExpBN254_f13_y) + A :MSTORE(frob2Fp12BN254_a13_x) + B :MSTORE(frob2Fp12BN254_a13_y) + $ => A :MLOAD(finalExpBN254_f21_x) + $ => B :MLOAD(finalExpBN254_f21_y) + A :MSTORE(frob2Fp12BN254_a21_x) + B :MSTORE(frob2Fp12BN254_a21_y) + $ => A :MLOAD(finalExpBN254_f22_x) + $ => B :MLOAD(finalExpBN254_f22_y) + A :MSTORE(frob2Fp12BN254_a22_x) + B :MSTORE(frob2Fp12BN254_a22_y) + $ => A :MLOAD(finalExpBN254_f23_x) + $ => B :MLOAD(finalExpBN254_f23_y) + A :MSTORE(frob2Fp12BN254_a23_x) + B :MSTORE(frob2Fp12BN254_a23_y), CALL(frob2Fp12BN254) + + $ => A :MLOAD(frob2Fp12BN254_c11_x) + $ => B :MLOAD(frob2Fp12BN254_c11_y) + A :MSTORE(mulFp12BN254_a11_x) + B :MSTORE(mulFp12BN254_a11_y) + $ => A :MLOAD(frob2Fp12BN254_c12_x) + $ => B :MLOAD(frob2Fp12BN254_c12_y) + A :MSTORE(mulFp12BN254_a12_x) + B :MSTORE(mulFp12BN254_a12_y) + $ => A :MLOAD(frob2Fp12BN254_c13_x) + $ => B :MLOAD(frob2Fp12BN254_c13_y) + A :MSTORE(mulFp12BN254_a13_x) + B :MSTORE(mulFp12BN254_a13_y) + $ => A :MLOAD(frob2Fp12BN254_c21_x) + $ => B :MLOAD(frob2Fp12BN254_c21_y) + A :MSTORE(mulFp12BN254_a21_x) + B :MSTORE(mulFp12BN254_a21_y) + $ => A :MLOAD(frob2Fp12BN254_c22_x) + $ => B :MLOAD(frob2Fp12BN254_c22_y) + A :MSTORE(mulFp12BN254_a22_x) + B :MSTORE(mulFp12BN254_a22_y) + $ => A :MLOAD(frob2Fp12BN254_c23_x) + $ => B :MLOAD(frob2Fp12BN254_c23_y) + A :MSTORE(mulFp12BN254_a23_x) + B :MSTORE(mulFp12BN254_a23_y) + $ => A :MLOAD(finalExpBN254_f11_x) + $ => B :MLOAD(finalExpBN254_f11_y) + A :MSTORE(mulFp12BN254_b11_x) + B :MSTORE(mulFp12BN254_b11_y) + $ => A :MLOAD(finalExpBN254_f12_x) + $ => B :MLOAD(finalExpBN254_f12_y) + A :MSTORE(mulFp12BN254_b12_x) + B :MSTORE(mulFp12BN254_b12_y) + $ => A :MLOAD(finalExpBN254_f13_x) + $ => B :MLOAD(finalExpBN254_f13_y) + A :MSTORE(mulFp12BN254_b13_x) + B :MSTORE(mulFp12BN254_b13_y) + $ => A :MLOAD(finalExpBN254_f21_x) + $ => B :MLOAD(finalExpBN254_f21_y) + A :MSTORE(mulFp12BN254_b21_x) + B :MSTORE(mulFp12BN254_b21_y) + $ => A :MLOAD(finalExpBN254_f22_x) + $ => B :MLOAD(finalExpBN254_f22_y) + A :MSTORE(mulFp12BN254_b22_x) + B :MSTORE(mulFp12BN254_b22_y) + $ => A :MLOAD(finalExpBN254_f23_x) + $ => B :MLOAD(finalExpBN254_f23_y) + A :MSTORE(mulFp12BN254_b23_x) + B :MSTORE(mulFp12BN254_b23_y), CALL(mulFp12BN254) + + $ => A :MLOAD(mulFp12BN254_c11_x) + $ => B :MLOAD(mulFp12BN254_c11_y) + A :MSTORE(finalExpBN254_f11_x) + B :MSTORE(finalExpBN254_f11_y) + $ => A :MLOAD(mulFp12BN254_c12_x) + $ => B :MLOAD(mulFp12BN254_c12_y) + A :MSTORE(finalExpBN254_f12_x) + B :MSTORE(finalExpBN254_f12_y) + $ => A :MLOAD(mulFp12BN254_c13_x) + $ => B :MLOAD(mulFp12BN254_c13_y) + A :MSTORE(finalExpBN254_f13_x) + B :MSTORE(finalExpBN254_f13_y) + $ => A :MLOAD(mulFp12BN254_c21_x) + $ => B :MLOAD(mulFp12BN254_c21_y) + A :MSTORE(finalExpBN254_f21_x) + B :MSTORE(finalExpBN254_f21_y) + $ => A :MLOAD(mulFp12BN254_c22_x) + $ => B :MLOAD(mulFp12BN254_c22_y) + A :MSTORE(finalExpBN254_f22_x) + B :MSTORE(finalExpBN254_f22_y) + $ => A :MLOAD(mulFp12BN254_c23_x) + $ => B :MLOAD(mulFp12BN254_c23_y) + A :MSTORE(finalExpBN254_f23_x) + B :MSTORE(finalExpBN254_f23_y) + ; =========================================== + + ; The hard part: + ; =========================================== + ; 1] m^x, (m^x)^x, (m^{x²})^x + $ => A :MLOAD(finalExpBN254_f11_x) + $ => B :MLOAD(finalExpBN254_f11_y) + A :MSTORE(expByXCompCycloFp12BN254_a0_x) + B :MSTORE(expByXCompCycloFp12BN254_a0_y) + $ => A :MLOAD(finalExpBN254_f12_x) + $ => B :MLOAD(finalExpBN254_f12_y) + A :MSTORE(expByXCompCycloFp12BN254_a4_x) + B :MSTORE(expByXCompCycloFp12BN254_a4_y) + $ => A :MLOAD(finalExpBN254_f13_x) + $ => B :MLOAD(finalExpBN254_f13_y) + A :MSTORE(expByXCompCycloFp12BN254_a3_x) + B :MSTORE(expByXCompCycloFp12BN254_a3_y) + $ => A :MLOAD(finalExpBN254_f21_x) + $ => B :MLOAD(finalExpBN254_f21_y) + A :MSTORE(expByXCompCycloFp12BN254_a2_x) + B :MSTORE(expByXCompCycloFp12BN254_a2_y) + $ => A :MLOAD(finalExpBN254_f22_x) + $ => B :MLOAD(finalExpBN254_f22_y) + A :MSTORE(expByXCompCycloFp12BN254_a1_x) + B :MSTORE(expByXCompCycloFp12BN254_a1_y) + $ => A :MLOAD(finalExpBN254_f23_x) + $ => B :MLOAD(finalExpBN254_f23_y) + A :MSTORE(expByXCompCycloFp12BN254_a5_x) + B :MSTORE(expByXCompCycloFp12BN254_a5_y), CALL(expByXCompCycloFp12BN254) + + $ => A :MLOAD(expByXCompCycloFp12BN254_c0_x) + $ => B :MLOAD(expByXCompCycloFp12BN254_c0_y) + A :MSTORE(finalExpBN254_mx11_x) + B :MSTORE(finalExpBN254_mx11_y) + $ => A :MLOAD(expByXCompCycloFp12BN254_c2_x) + $ => B :MLOAD(expByXCompCycloFp12BN254_c2_y) + A :MSTORE(finalExpBN254_mx21_x) + B :MSTORE(finalExpBN254_mx21_y) + $ => A :MLOAD(expByXCompCycloFp12BN254_c4_x) + $ => B :MLOAD(expByXCompCycloFp12BN254_c4_y) + A :MSTORE(finalExpBN254_mx12_x) + B :MSTORE(finalExpBN254_mx12_y) + $ => A :MLOAD(expByXCompCycloFp12BN254_c1_x) + $ => B :MLOAD(expByXCompCycloFp12BN254_c1_y) + A :MSTORE(finalExpBN254_mx22_x) + B :MSTORE(finalExpBN254_mx22_y) + $ => A :MLOAD(expByXCompCycloFp12BN254_c3_x) + $ => B :MLOAD(expByXCompCycloFp12BN254_c3_y) + A :MSTORE(finalExpBN254_mx13_x) + B :MSTORE(finalExpBN254_mx13_y) + $ => A :MLOAD(expByXCompCycloFp12BN254_c5_x) + $ => B :MLOAD(expByXCompCycloFp12BN254_c5_y) + A :MSTORE(finalExpBN254_mx23_x) + B :MSTORE(finalExpBN254_mx23_y) + + $ => A :MLOAD(finalExpBN254_mx11_x) + $ => B :MLOAD(finalExpBN254_mx11_y) + A :MSTORE(expByXCompCycloFp12BN254_a0_x) + B :MSTORE(expByXCompCycloFp12BN254_a0_y) + $ => A :MLOAD(finalExpBN254_mx12_x) + $ => B :MLOAD(finalExpBN254_mx12_y) + A :MSTORE(expByXCompCycloFp12BN254_a4_x) + B :MSTORE(expByXCompCycloFp12BN254_a4_y) + $ => A :MLOAD(finalExpBN254_mx13_x) + $ => B :MLOAD(finalExpBN254_mx13_y) + A :MSTORE(expByXCompCycloFp12BN254_a3_x) + B :MSTORE(expByXCompCycloFp12BN254_a3_y) + $ => A :MLOAD(finalExpBN254_mx21_x) + $ => B :MLOAD(finalExpBN254_mx21_y) + A :MSTORE(expByXCompCycloFp12BN254_a2_x) + B :MSTORE(expByXCompCycloFp12BN254_a2_y) + $ => A :MLOAD(finalExpBN254_mx22_x) + $ => B :MLOAD(finalExpBN254_mx22_y) + A :MSTORE(expByXCompCycloFp12BN254_a1_x) + B :MSTORE(expByXCompCycloFp12BN254_a1_y) + $ => A :MLOAD(finalExpBN254_mx23_x) + $ => B :MLOAD(finalExpBN254_mx23_y) + A :MSTORE(expByXCompCycloFp12BN254_a5_x) + B :MSTORE(expByXCompCycloFp12BN254_a5_y), CALL(expByXCompCycloFp12BN254) + + $ => A :MLOAD(expByXCompCycloFp12BN254_c0_x) + $ => B :MLOAD(expByXCompCycloFp12BN254_c0_y) + A :MSTORE(finalExpBN254_mxx11_x) + B :MSTORE(finalExpBN254_mxx11_y) + $ => A :MLOAD(expByXCompCycloFp12BN254_c2_x) + $ => B :MLOAD(expByXCompCycloFp12BN254_c2_y) + A :MSTORE(finalExpBN254_mxx21_x) + B :MSTORE(finalExpBN254_mxx21_y) + $ => A :MLOAD(expByXCompCycloFp12BN254_c4_x) + $ => B :MLOAD(expByXCompCycloFp12BN254_c4_y) + A :MSTORE(finalExpBN254_mxx12_x) + B :MSTORE(finalExpBN254_mxx12_y) + $ => A :MLOAD(expByXCompCycloFp12BN254_c1_x) + $ => B :MLOAD(expByXCompCycloFp12BN254_c1_y) + A :MSTORE(finalExpBN254_mxx22_x) + B :MSTORE(finalExpBN254_mxx22_y) + $ => A :MLOAD(expByXCompCycloFp12BN254_c3_x) + $ => B :MLOAD(expByXCompCycloFp12BN254_c3_y) + A :MSTORE(finalExpBN254_mxx13_x) + B :MSTORE(finalExpBN254_mxx13_y) + $ => A :MLOAD(expByXCompCycloFp12BN254_c5_x) + $ => B :MLOAD(expByXCompCycloFp12BN254_c5_y) + A :MSTORE(finalExpBN254_mxx23_x) + B :MSTORE(finalExpBN254_mxx23_y) + + $ => A :MLOAD(finalExpBN254_mxx11_x) + $ => B :MLOAD(finalExpBN254_mxx11_y) + A :MSTORE(expByXCompCycloFp12BN254_a0_x) + B :MSTORE(expByXCompCycloFp12BN254_a0_y) + $ => A :MLOAD(finalExpBN254_mxx12_x) + $ => B :MLOAD(finalExpBN254_mxx12_y) + A :MSTORE(expByXCompCycloFp12BN254_a4_x) + B :MSTORE(expByXCompCycloFp12BN254_a4_y) + $ => A :MLOAD(finalExpBN254_mxx13_x) + $ => B :MLOAD(finalExpBN254_mxx13_y) + A :MSTORE(expByXCompCycloFp12BN254_a3_x) + B :MSTORE(expByXCompCycloFp12BN254_a3_y) + $ => A :MLOAD(finalExpBN254_mxx21_x) + $ => B :MLOAD(finalExpBN254_mxx21_y) + A :MSTORE(expByXCompCycloFp12BN254_a2_x) + B :MSTORE(expByXCompCycloFp12BN254_a2_y) + $ => A :MLOAD(finalExpBN254_mxx22_x) + $ => B :MLOAD(finalExpBN254_mxx22_y) + A :MSTORE(expByXCompCycloFp12BN254_a1_x) + B :MSTORE(expByXCompCycloFp12BN254_a1_y) + $ => A :MLOAD(finalExpBN254_mxx23_x) + $ => B :MLOAD(finalExpBN254_mxx23_y) + A :MSTORE(expByXCompCycloFp12BN254_a5_x) + B :MSTORE(expByXCompCycloFp12BN254_a5_y), CALL(expByXCompCycloFp12BN254) + + $ => A :MLOAD(expByXCompCycloFp12BN254_c0_x) + $ => B :MLOAD(expByXCompCycloFp12BN254_c0_y) + A :MSTORE(finalExpBN254_mxxx11_x) + B :MSTORE(finalExpBN254_mxxx11_y) + $ => A :MLOAD(expByXCompCycloFp12BN254_c2_x) + $ => B :MLOAD(expByXCompCycloFp12BN254_c2_y) + A :MSTORE(finalExpBN254_mxxx21_x) + B :MSTORE(finalExpBN254_mxxx21_y) + $ => A :MLOAD(expByXCompCycloFp12BN254_c4_x) + $ => B :MLOAD(expByXCompCycloFp12BN254_c4_y) + A :MSTORE(finalExpBN254_mxxx12_x) + B :MSTORE(finalExpBN254_mxxx12_y) + $ => A :MLOAD(expByXCompCycloFp12BN254_c1_x) + $ => B :MLOAD(expByXCompCycloFp12BN254_c1_y) + A :MSTORE(finalExpBN254_mxxx22_x) + B :MSTORE(finalExpBN254_mxxx22_y) + $ => A :MLOAD(expByXCompCycloFp12BN254_c3_x) + $ => B :MLOAD(expByXCompCycloFp12BN254_c3_y) + A :MSTORE(finalExpBN254_mxxx13_x) + B :MSTORE(finalExpBN254_mxxx13_y) + $ => A :MLOAD(expByXCompCycloFp12BN254_c5_x) + $ => B :MLOAD(expByXCompCycloFp12BN254_c5_y) + A :MSTORE(finalExpBN254_mxxx23_x) + B :MSTORE(finalExpBN254_mxxx23_y) + + ; 2] m^p, m^p², m^p³, (m^x)^p, (m^x²)^p, (m^x³)^p, (m^x²)^p² + $ => A :MLOAD(finalExpBN254_f11_x) + $ => B :MLOAD(finalExpBN254_f11_y) + A :MSTORE(frobFp12BN254_a11_x) + B :MSTORE(frobFp12BN254_a11_y) + $ => A :MLOAD(finalExpBN254_f12_x) + $ => B :MLOAD(finalExpBN254_f12_y) + A :MSTORE(frobFp12BN254_a12_x) + B :MSTORE(frobFp12BN254_a12_y) + $ => A :MLOAD(finalExpBN254_f13_x) + $ => B :MLOAD(finalExpBN254_f13_y) + A :MSTORE(frobFp12BN254_a13_x) + B :MSTORE(frobFp12BN254_a13_y) + $ => A :MLOAD(finalExpBN254_f21_x) + $ => B :MLOAD(finalExpBN254_f21_y) + A :MSTORE(frobFp12BN254_a21_x) + B :MSTORE(frobFp12BN254_a21_y) + $ => A :MLOAD(finalExpBN254_f22_x) + $ => B :MLOAD(finalExpBN254_f22_y) + A :MSTORE(frobFp12BN254_a22_x) + B :MSTORE(frobFp12BN254_a22_y) + $ => A :MLOAD(finalExpBN254_f23_x) + $ => B :MLOAD(finalExpBN254_f23_y) + A :MSTORE(frobFp12BN254_a23_x) + B :MSTORE(frobFp12BN254_a23_y), CALL(frobFp12BN254) + + $ => A :MLOAD(frobFp12BN254_c11_x) + $ => B :MLOAD(frobFp12BN254_c11_y) + A :MSTORE(finalExpBN254_mp11_x) + B :MSTORE(finalExpBN254_mp11_y) + $ => A :MLOAD(frobFp12BN254_c12_x) + $ => B :MLOAD(frobFp12BN254_c12_y) + A :MSTORE(finalExpBN254_mp12_x) + B :MSTORE(finalExpBN254_mp12_y) + $ => A :MLOAD(frobFp12BN254_c13_x) + $ => B :MLOAD(frobFp12BN254_c13_y) + A :MSTORE(finalExpBN254_mp13_x) + B :MSTORE(finalExpBN254_mp13_y) + $ => A :MLOAD(frobFp12BN254_c21_x) + $ => B :MLOAD(frobFp12BN254_c21_y) + A :MSTORE(finalExpBN254_mp21_x) + B :MSTORE(finalExpBN254_mp21_y) + $ => A :MLOAD(frobFp12BN254_c22_x) + $ => B :MLOAD(frobFp12BN254_c22_y) + A :MSTORE(finalExpBN254_mp22_x) + B :MSTORE(finalExpBN254_mp22_y) + $ => A :MLOAD(frobFp12BN254_c23_x) + $ => B :MLOAD(frobFp12BN254_c23_y) + A :MSTORE(finalExpBN254_mp23_x) + B :MSTORE(finalExpBN254_mp23_y) + + $ => A :MLOAD(finalExpBN254_f11_x) + $ => B :MLOAD(finalExpBN254_f11_y) + A :MSTORE(frob2Fp12BN254_a11_x) + B :MSTORE(frob2Fp12BN254_a11_y) + $ => A :MLOAD(finalExpBN254_f12_x) + $ => B :MLOAD(finalExpBN254_f12_y) + A :MSTORE(frob2Fp12BN254_a12_x) + B :MSTORE(frob2Fp12BN254_a12_y) + $ => A :MLOAD(finalExpBN254_f13_x) + $ => B :MLOAD(finalExpBN254_f13_y) + A :MSTORE(frob2Fp12BN254_a13_x) + B :MSTORE(frob2Fp12BN254_a13_y) + $ => A :MLOAD(finalExpBN254_f21_x) + $ => B :MLOAD(finalExpBN254_f21_y) + A :MSTORE(frob2Fp12BN254_a21_x) + B :MSTORE(frob2Fp12BN254_a21_y) + $ => A :MLOAD(finalExpBN254_f22_x) + $ => B :MLOAD(finalExpBN254_f22_y) + A :MSTORE(frob2Fp12BN254_a22_x) + B :MSTORE(frob2Fp12BN254_a22_y) + $ => A :MLOAD(finalExpBN254_f23_x) + $ => B :MLOAD(finalExpBN254_f23_y) + A :MSTORE(frob2Fp12BN254_a23_x) + B :MSTORE(frob2Fp12BN254_a23_y), CALL(frob2Fp12BN254) + + $ => A :MLOAD(frob2Fp12BN254_c11_x) + $ => B :MLOAD(frob2Fp12BN254_c11_y) + A :MSTORE(finalExpBN254_mpp11_x) + B :MSTORE(finalExpBN254_mpp11_y) + $ => A :MLOAD(frob2Fp12BN254_c12_x) + $ => B :MLOAD(frob2Fp12BN254_c12_y) + A :MSTORE(finalExpBN254_mpp12_x) + B :MSTORE(finalExpBN254_mpp12_y) + $ => A :MLOAD(frob2Fp12BN254_c13_x) + $ => B :MLOAD(frob2Fp12BN254_c13_y) + A :MSTORE(finalExpBN254_mpp13_x) + B :MSTORE(finalExpBN254_mpp13_y) + $ => A :MLOAD(frob2Fp12BN254_c21_x) + $ => B :MLOAD(frob2Fp12BN254_c21_y) + A :MSTORE(finalExpBN254_mpp21_x) + B :MSTORE(finalExpBN254_mpp21_y) + $ => A :MLOAD(frob2Fp12BN254_c22_x) + $ => B :MLOAD(frob2Fp12BN254_c22_y) + A :MSTORE(finalExpBN254_mpp22_x) + B :MSTORE(finalExpBN254_mpp22_y) + $ => A :MLOAD(frob2Fp12BN254_c23_x) + $ => B :MLOAD(frob2Fp12BN254_c23_y) + A :MSTORE(finalExpBN254_mpp23_x) + B :MSTORE(finalExpBN254_mpp23_y) + + $ => A :MLOAD(finalExpBN254_f11_x) + $ => B :MLOAD(finalExpBN254_f11_y) + A :MSTORE(frob3Fp12BN254_a11_x) + B :MSTORE(frob3Fp12BN254_a11_y) + $ => A :MLOAD(finalExpBN254_f12_x) + $ => B :MLOAD(finalExpBN254_f12_y) + A :MSTORE(frob3Fp12BN254_a12_x) + B :MSTORE(frob3Fp12BN254_a12_y) + $ => A :MLOAD(finalExpBN254_f13_x) + $ => B :MLOAD(finalExpBN254_f13_y) + A :MSTORE(frob3Fp12BN254_a13_x) + B :MSTORE(frob3Fp12BN254_a13_y) + $ => A :MLOAD(finalExpBN254_f21_x) + $ => B :MLOAD(finalExpBN254_f21_y) + A :MSTORE(frob3Fp12BN254_a21_x) + B :MSTORE(frob3Fp12BN254_a21_y) + $ => A :MLOAD(finalExpBN254_f22_x) + $ => B :MLOAD(finalExpBN254_f22_y) + A :MSTORE(frob3Fp12BN254_a22_x) + B :MSTORE(frob3Fp12BN254_a22_y) + $ => A :MLOAD(finalExpBN254_f23_x) + $ => B :MLOAD(finalExpBN254_f23_y) + A :MSTORE(frob3Fp12BN254_a23_x) + B :MSTORE(frob3Fp12BN254_a23_y), CALL(frob3Fp12BN254) + + $ => A :MLOAD(frob3Fp12BN254_c11_x) + $ => B :MLOAD(frob3Fp12BN254_c11_y) + A :MSTORE(finalExpBN254_mppp11_x) + B :MSTORE(finalExpBN254_mppp11_y) + $ => A :MLOAD(frob3Fp12BN254_c12_x) + $ => B :MLOAD(frob3Fp12BN254_c12_y) + A :MSTORE(finalExpBN254_mppp12_x) + B :MSTORE(finalExpBN254_mppp12_y) + $ => A :MLOAD(frob3Fp12BN254_c13_x) + $ => B :MLOAD(frob3Fp12BN254_c13_y) + A :MSTORE(finalExpBN254_mppp13_x) + B :MSTORE(finalExpBN254_mppp13_y) + $ => A :MLOAD(frob3Fp12BN254_c21_x) + $ => B :MLOAD(frob3Fp12BN254_c21_y) + A :MSTORE(finalExpBN254_mppp21_x) + B :MSTORE(finalExpBN254_mppp21_y) + $ => A :MLOAD(frob3Fp12BN254_c22_x) + $ => B :MLOAD(frob3Fp12BN254_c22_y) + A :MSTORE(finalExpBN254_mppp22_x) + B :MSTORE(finalExpBN254_mppp22_y) + $ => A :MLOAD(frob3Fp12BN254_c23_x) + $ => B :MLOAD(frob3Fp12BN254_c23_y) + A :MSTORE(finalExpBN254_mppp23_x) + B :MSTORE(finalExpBN254_mppp23_y) + + $ => A :MLOAD(finalExpBN254_mx11_x) + $ => B :MLOAD(finalExpBN254_mx11_y) + A :MSTORE(frobFp12BN254_a11_x) + B :MSTORE(frobFp12BN254_a11_y) + $ => A :MLOAD(finalExpBN254_mx12_x) + $ => B :MLOAD(finalExpBN254_mx12_y) + A :MSTORE(frobFp12BN254_a12_x) + B :MSTORE(frobFp12BN254_a12_y) + $ => A :MLOAD(finalExpBN254_mx13_x) + $ => B :MLOAD(finalExpBN254_mx13_y) + A :MSTORE(frobFp12BN254_a13_x) + B :MSTORE(frobFp12BN254_a13_y) + $ => A :MLOAD(finalExpBN254_mx21_x) + $ => B :MLOAD(finalExpBN254_mx21_y) + A :MSTORE(frobFp12BN254_a21_x) + B :MSTORE(frobFp12BN254_a21_y) + $ => A :MLOAD(finalExpBN254_mx22_x) + $ => B :MLOAD(finalExpBN254_mx22_y) + A :MSTORE(frobFp12BN254_a22_x) + B :MSTORE(frobFp12BN254_a22_y) + $ => A :MLOAD(finalExpBN254_mx23_x) + $ => B :MLOAD(finalExpBN254_mx23_y) + A :MSTORE(frobFp12BN254_a23_x) + B :MSTORE(frobFp12BN254_a23_y), CALL(frobFp12BN254) + + $ => A :MLOAD(frobFp12BN254_c11_x) + $ => B :MLOAD(frobFp12BN254_c11_y) + A :MSTORE(finalExpBN254_mxp11_x) + B :MSTORE(finalExpBN254_mxp11_y) + $ => A :MLOAD(frobFp12BN254_c12_x) + $ => B :MLOAD(frobFp12BN254_c12_y) + A :MSTORE(finalExpBN254_mxp12_x) + B :MSTORE(finalExpBN254_mxp12_y) + $ => A :MLOAD(frobFp12BN254_c13_x) + $ => B :MLOAD(frobFp12BN254_c13_y) + A :MSTORE(finalExpBN254_mxp13_x) + B :MSTORE(finalExpBN254_mxp13_y) + $ => A :MLOAD(frobFp12BN254_c21_x) + $ => B :MLOAD(frobFp12BN254_c21_y) + A :MSTORE(finalExpBN254_mxp21_x) + B :MSTORE(finalExpBN254_mxp21_y) + $ => A :MLOAD(frobFp12BN254_c22_x) + $ => B :MLOAD(frobFp12BN254_c22_y) + A :MSTORE(finalExpBN254_mxp22_x) + B :MSTORE(finalExpBN254_mxp22_y) + $ => A :MLOAD(frobFp12BN254_c23_x) + $ => B :MLOAD(frobFp12BN254_c23_y) + A :MSTORE(finalExpBN254_mxp23_x) + B :MSTORE(finalExpBN254_mxp23_y) + + $ => A :MLOAD(finalExpBN254_mxx11_x) + $ => B :MLOAD(finalExpBN254_mxx11_y) + A :MSTORE(frobFp12BN254_a11_x) + B :MSTORE(frobFp12BN254_a11_y) + $ => A :MLOAD(finalExpBN254_mxx12_x) + $ => B :MLOAD(finalExpBN254_mxx12_y) + A :MSTORE(frobFp12BN254_a12_x) + B :MSTORE(frobFp12BN254_a12_y) + $ => A :MLOAD(finalExpBN254_mxx13_x) + $ => B :MLOAD(finalExpBN254_mxx13_y) + A :MSTORE(frobFp12BN254_a13_x) + B :MSTORE(frobFp12BN254_a13_y) + $ => A :MLOAD(finalExpBN254_mxx21_x) + $ => B :MLOAD(finalExpBN254_mxx21_y) + A :MSTORE(frobFp12BN254_a21_x) + B :MSTORE(frobFp12BN254_a21_y) + $ => A :MLOAD(finalExpBN254_mxx22_x) + $ => B :MLOAD(finalExpBN254_mxx22_y) + A :MSTORE(frobFp12BN254_a22_x) + B :MSTORE(frobFp12BN254_a22_y) + $ => A :MLOAD(finalExpBN254_mxx23_x) + $ => B :MLOAD(finalExpBN254_mxx23_y) + A :MSTORE(frobFp12BN254_a23_x) + B :MSTORE(frobFp12BN254_a23_y), CALL(frobFp12BN254) + + $ => A :MLOAD(frobFp12BN254_c11_x) + $ => B :MLOAD(frobFp12BN254_c11_y) + A :MSTORE(finalExpBN254_mxxp11_x) + B :MSTORE(finalExpBN254_mxxp11_y) + $ => A :MLOAD(frobFp12BN254_c12_x) + $ => B :MLOAD(frobFp12BN254_c12_y) + A :MSTORE(finalExpBN254_mxxp12_x) + B :MSTORE(finalExpBN254_mxxp12_y) + $ => A :MLOAD(frobFp12BN254_c13_x) + $ => B :MLOAD(frobFp12BN254_c13_y) + A :MSTORE(finalExpBN254_mxxp13_x) + B :MSTORE(finalExpBN254_mxxp13_y) + $ => A :MLOAD(frobFp12BN254_c21_x) + $ => B :MLOAD(frobFp12BN254_c21_y) + A :MSTORE(finalExpBN254_mxxp21_x) + B :MSTORE(finalExpBN254_mxxp21_y) + $ => A :MLOAD(frobFp12BN254_c22_x) + $ => B :MLOAD(frobFp12BN254_c22_y) + A :MSTORE(finalExpBN254_mxxp22_x) + B :MSTORE(finalExpBN254_mxxp22_y) + $ => A :MLOAD(frobFp12BN254_c23_x) + $ => B :MLOAD(frobFp12BN254_c23_y) + A :MSTORE(finalExpBN254_mxxp23_x) + B :MSTORE(finalExpBN254_mxxp23_y) + + $ => A :MLOAD(finalExpBN254_mxxx11_x) + $ => B :MLOAD(finalExpBN254_mxxx11_y) + A :MSTORE(frobFp12BN254_a11_x) + B :MSTORE(frobFp12BN254_a11_y) + $ => A :MLOAD(finalExpBN254_mxxx12_x) + $ => B :MLOAD(finalExpBN254_mxxx12_y) + A :MSTORE(frobFp12BN254_a12_x) + B :MSTORE(frobFp12BN254_a12_y) + $ => A :MLOAD(finalExpBN254_mxxx13_x) + $ => B :MLOAD(finalExpBN254_mxxx13_y) + A :MSTORE(frobFp12BN254_a13_x) + B :MSTORE(frobFp12BN254_a13_y) + $ => A :MLOAD(finalExpBN254_mxxx21_x) + $ => B :MLOAD(finalExpBN254_mxxx21_y) + A :MSTORE(frobFp12BN254_a21_x) + B :MSTORE(frobFp12BN254_a21_y) + $ => A :MLOAD(finalExpBN254_mxxx22_x) + $ => B :MLOAD(finalExpBN254_mxxx22_y) + A :MSTORE(frobFp12BN254_a22_x) + B :MSTORE(frobFp12BN254_a22_y) + $ => A :MLOAD(finalExpBN254_mxxx23_x) + $ => B :MLOAD(finalExpBN254_mxxx23_y) + A :MSTORE(frobFp12BN254_a23_x) + B :MSTORE(frobFp12BN254_a23_y), CALL(frobFp12BN254) + + $ => A :MLOAD(frobFp12BN254_c11_x) + $ => B :MLOAD(frobFp12BN254_c11_y) + A :MSTORE(finalExpBN254_mxxxp11_x) + B :MSTORE(finalExpBN254_mxxxp11_y) + $ => A :MLOAD(frobFp12BN254_c12_x) + $ => B :MLOAD(frobFp12BN254_c12_y) + A :MSTORE(finalExpBN254_mxxxp12_x) + B :MSTORE(finalExpBN254_mxxxp12_y) + $ => A :MLOAD(frobFp12BN254_c13_x) + $ => B :MLOAD(frobFp12BN254_c13_y) + A :MSTORE(finalExpBN254_mxxxp13_x) + B :MSTORE(finalExpBN254_mxxxp13_y) + $ => A :MLOAD(frobFp12BN254_c21_x) + $ => B :MLOAD(frobFp12BN254_c21_y) + A :MSTORE(finalExpBN254_mxxxp21_x) + B :MSTORE(finalExpBN254_mxxxp21_y) + $ => A :MLOAD(frobFp12BN254_c22_x) + $ => B :MLOAD(frobFp12BN254_c22_y) + A :MSTORE(finalExpBN254_mxxxp22_x) + B :MSTORE(finalExpBN254_mxxxp22_y) + $ => A :MLOAD(frobFp12BN254_c23_x) + $ => B :MLOAD(frobFp12BN254_c23_y) + A :MSTORE(finalExpBN254_mxxxp23_x) + B :MSTORE(finalExpBN254_mxxxp23_y) + + $ => A :MLOAD(finalExpBN254_mxx11_x) + $ => B :MLOAD(finalExpBN254_mxx11_y) + A :MSTORE(frob2Fp12BN254_a11_x) + B :MSTORE(frob2Fp12BN254_a11_y) + $ => A :MLOAD(finalExpBN254_mxx12_x) + $ => B :MLOAD(finalExpBN254_mxx12_y) + A :MSTORE(frob2Fp12BN254_a12_x) + B :MSTORE(frob2Fp12BN254_a12_y) + $ => A :MLOAD(finalExpBN254_mxx13_x) + $ => B :MLOAD(finalExpBN254_mxx13_y) + A :MSTORE(frob2Fp12BN254_a13_x) + B :MSTORE(frob2Fp12BN254_a13_y) + $ => A :MLOAD(finalExpBN254_mxx21_x) + $ => B :MLOAD(finalExpBN254_mxx21_y) + A :MSTORE(frob2Fp12BN254_a21_x) + B :MSTORE(frob2Fp12BN254_a21_y) + $ => A :MLOAD(finalExpBN254_mxx22_x) + $ => B :MLOAD(finalExpBN254_mxx22_y) + A :MSTORE(frob2Fp12BN254_a22_x) + B :MSTORE(frob2Fp12BN254_a22_y) + $ => A :MLOAD(finalExpBN254_mxx23_x) + $ => B :MLOAD(finalExpBN254_mxx23_y) + A :MSTORE(frob2Fp12BN254_a23_x) + B :MSTORE(frob2Fp12BN254_a23_y), CALL(frob2Fp12BN254) + + $ => A :MLOAD(frob2Fp12BN254_c11_x) + $ => B :MLOAD(frob2Fp12BN254_c11_y) + A :MSTORE(finalExpBN254_mxxpp11_x) + B :MSTORE(finalExpBN254_mxxpp11_y) + $ => A :MLOAD(frob2Fp12BN254_c12_x) + $ => B :MLOAD(frob2Fp12BN254_c12_y) + A :MSTORE(finalExpBN254_mxxpp12_x) + B :MSTORE(finalExpBN254_mxxpp12_y) + $ => A :MLOAD(frob2Fp12BN254_c13_x) + $ => B :MLOAD(frob2Fp12BN254_c13_y) + A :MSTORE(finalExpBN254_mxxpp13_x) + B :MSTORE(finalExpBN254_mxxpp13_y) + $ => A :MLOAD(frob2Fp12BN254_c21_x) + $ => B :MLOAD(frob2Fp12BN254_c21_y) + A :MSTORE(finalExpBN254_mxxpp21_x) + B :MSTORE(finalExpBN254_mxxpp21_y) + $ => A :MLOAD(frob2Fp12BN254_c22_x) + $ => B :MLOAD(frob2Fp12BN254_c22_y) + A :MSTORE(finalExpBN254_mxxpp22_x) + B :MSTORE(finalExpBN254_mxxpp22_y) + $ => A :MLOAD(frob2Fp12BN254_c23_x) + $ => B :MLOAD(frob2Fp12BN254_c23_y) + A :MSTORE(finalExpBN254_mxxpp23_x) + B :MSTORE(finalExpBN254_mxxpp23_y) + + ; 3] y1 = m^p·m^p²·m^p³ + $ => A :MLOAD(finalExpBN254_mp11_x) + $ => B :MLOAD(finalExpBN254_mp11_y) + A :MSTORE(mulFp12BN254_a11_x) + B :MSTORE(mulFp12BN254_a11_y) + $ => A :MLOAD(finalExpBN254_mp12_x) + $ => B :MLOAD(finalExpBN254_mp12_y) + A :MSTORE(mulFp12BN254_a12_x) + B :MSTORE(mulFp12BN254_a12_y) + $ => A :MLOAD(finalExpBN254_mp13_x) + $ => B :MLOAD(finalExpBN254_mp13_y) + A :MSTORE(mulFp12BN254_a13_x) + B :MSTORE(mulFp12BN254_a13_y) + $ => A :MLOAD(finalExpBN254_mp21_x) + $ => B :MLOAD(finalExpBN254_mp21_y) + A :MSTORE(mulFp12BN254_a21_x) + B :MSTORE(mulFp12BN254_a21_y) + $ => A :MLOAD(finalExpBN254_mp22_x) + $ => B :MLOAD(finalExpBN254_mp22_y) + A :MSTORE(mulFp12BN254_a22_x) + B :MSTORE(mulFp12BN254_a22_y) + $ => A :MLOAD(finalExpBN254_mp23_x) + $ => B :MLOAD(finalExpBN254_mp23_y) + A :MSTORE(mulFp12BN254_a23_x) + B :MSTORE(mulFp12BN254_a23_y) + $ => A :MLOAD(finalExpBN254_mpp11_x) + $ => B :MLOAD(finalExpBN254_mpp11_y) + A :MSTORE(mulFp12BN254_b11_x) + B :MSTORE(mulFp12BN254_b11_y) + $ => A :MLOAD(finalExpBN254_mpp12_x) + $ => B :MLOAD(finalExpBN254_mpp12_y) + A :MSTORE(mulFp12BN254_b12_x) + B :MSTORE(mulFp12BN254_b12_y) + $ => A :MLOAD(finalExpBN254_mpp13_x) + $ => B :MLOAD(finalExpBN254_mpp13_y) + A :MSTORE(mulFp12BN254_b13_x) + B :MSTORE(mulFp12BN254_b13_y) + $ => A :MLOAD(finalExpBN254_mpp21_x) + $ => B :MLOAD(finalExpBN254_mpp21_y) + A :MSTORE(mulFp12BN254_b21_x) + B :MSTORE(mulFp12BN254_b21_y) + $ => A :MLOAD(finalExpBN254_mpp22_x) + $ => B :MLOAD(finalExpBN254_mpp22_y) + A :MSTORE(mulFp12BN254_b22_x) + B :MSTORE(mulFp12BN254_b22_y) + $ => A :MLOAD(finalExpBN254_mpp23_x) + $ => B :MLOAD(finalExpBN254_mpp23_y) + A :MSTORE(mulFp12BN254_b23_x) + B :MSTORE(mulFp12BN254_b23_y), CALL(mulFp12BN254) + + $ => A :MLOAD(mulFp12BN254_c11_x) + $ => B :MLOAD(mulFp12BN254_c11_y) + A :MSTORE(mulFp12BN254_a11_x) + B :MSTORE(mulFp12BN254_a11_y) + $ => A :MLOAD(mulFp12BN254_c12_x) + $ => B :MLOAD(mulFp12BN254_c12_y) + A :MSTORE(mulFp12BN254_a12_x) + B :MSTORE(mulFp12BN254_a12_y) + $ => A :MLOAD(mulFp12BN254_c13_x) + $ => B :MLOAD(mulFp12BN254_c13_y) + A :MSTORE(mulFp12BN254_a13_x) + B :MSTORE(mulFp12BN254_a13_y) + $ => A :MLOAD(mulFp12BN254_c21_x) + $ => B :MLOAD(mulFp12BN254_c21_y) + A :MSTORE(mulFp12BN254_a21_x) + B :MSTORE(mulFp12BN254_a21_y) + $ => A :MLOAD(mulFp12BN254_c22_x) + $ => B :MLOAD(mulFp12BN254_c22_y) + A :MSTORE(mulFp12BN254_a22_x) + B :MSTORE(mulFp12BN254_a22_y) + $ => A :MLOAD(mulFp12BN254_c23_x) + $ => B :MLOAD(mulFp12BN254_c23_y) + A :MSTORE(mulFp12BN254_a23_x) + B :MSTORE(mulFp12BN254_a23_y) + $ => A :MLOAD(finalExpBN254_mppp11_x) + $ => B :MLOAD(finalExpBN254_mppp11_y) + A :MSTORE(mulFp12BN254_b11_x) + B :MSTORE(mulFp12BN254_b11_y) + $ => A :MLOAD(finalExpBN254_mppp12_x) + $ => B :MLOAD(finalExpBN254_mppp12_y) + A :MSTORE(mulFp12BN254_b12_x) + B :MSTORE(mulFp12BN254_b12_y) + $ => A :MLOAD(finalExpBN254_mppp13_x) + $ => B :MLOAD(finalExpBN254_mppp13_y) + A :MSTORE(mulFp12BN254_b13_x) + B :MSTORE(mulFp12BN254_b13_y) + $ => A :MLOAD(finalExpBN254_mppp21_x) + $ => B :MLOAD(finalExpBN254_mppp21_y) + A :MSTORE(mulFp12BN254_b21_x) + B :MSTORE(mulFp12BN254_b21_y) + $ => A :MLOAD(finalExpBN254_mppp22_x) + $ => B :MLOAD(finalExpBN254_mppp22_y) + A :MSTORE(mulFp12BN254_b22_x) + B :MSTORE(mulFp12BN254_b22_y) + $ => A :MLOAD(finalExpBN254_mppp23_x) + $ => B :MLOAD(finalExpBN254_mppp23_y) + A :MSTORE(mulFp12BN254_b23_x) + B :MSTORE(mulFp12BN254_b23_y), CALL(mulFp12BN254) + + $ => A :MLOAD(mulFp12BN254_c11_x) + $ => B :MLOAD(mulFp12BN254_c11_y) + A :MSTORE(finalExpBN254_y1_11_x) + B :MSTORE(finalExpBN254_y1_11_y) + $ => A :MLOAD(mulFp12BN254_c12_x) + $ => B :MLOAD(mulFp12BN254_c12_y) + A :MSTORE(finalExpBN254_y1_12_x) + B :MSTORE(finalExpBN254_y1_12_y) + $ => A :MLOAD(mulFp12BN254_c13_x) + $ => B :MLOAD(mulFp12BN254_c13_y) + A :MSTORE(finalExpBN254_y1_13_x) + B :MSTORE(finalExpBN254_y1_13_y) + $ => A :MLOAD(mulFp12BN254_c21_x) + $ => B :MLOAD(mulFp12BN254_c21_y) + A :MSTORE(finalExpBN254_y1_21_x) + B :MSTORE(finalExpBN254_y1_21_y) + $ => A :MLOAD(mulFp12BN254_c22_x) + $ => B :MLOAD(mulFp12BN254_c22_y) + A :MSTORE(finalExpBN254_y1_22_x) + B :MSTORE(finalExpBN254_y1_22_y) + $ => A :MLOAD(mulFp12BN254_c23_x) + $ => B :MLOAD(mulFp12BN254_c23_y) + A :MSTORE(finalExpBN254_y1_23_x) + B :MSTORE(finalExpBN254_y1_23_y) + + ; 4] y2 = m̅ + $ => A :MLOAD(finalExpBN254_f11_x) + $ => B :MLOAD(finalExpBN254_f11_y) + A :MSTORE(finalExpBN254_y2_11_x) + B :MSTORE(finalExpBN254_y2_11_y) + $ => A :MLOAD(finalExpBN254_f12_x) + $ => B :MLOAD(finalExpBN254_f12_y) + A :MSTORE(finalExpBN254_y2_12_x) + B :MSTORE(finalExpBN254_y2_12_y) + $ => A :MLOAD(finalExpBN254_f13_x) + $ => B :MLOAD(finalExpBN254_f13_y) + A :MSTORE(finalExpBN254_y2_13_x) + B :MSTORE(finalExpBN254_y2_13_y) + + %BN254_P => A + $ => B :MLOAD(finalExpBN254_f21_x) + $ :SUB, MSTORE(finalExpBN254_y2_21_x) + %BN254_P => A + $ => B :MLOAD(finalExpBN254_f21_y) + $ :SUB, MSTORE(finalExpBN254_y2_21_y) + %BN254_P => A + $ => B :MLOAD(finalExpBN254_f22_x) + $ :SUB, MSTORE(finalExpBN254_y2_22_x) + %BN254_P => A + $ => B :MLOAD(finalExpBN254_f22_y) + $ :SUB, MSTORE(finalExpBN254_y2_22_y) + %BN254_P => A + $ => B :MLOAD(finalExpBN254_f23_x) + $ :SUB, MSTORE(finalExpBN254_y2_23_x) + %BN254_P => A + $ => B :MLOAD(finalExpBN254_f23_y) + $ :SUB, MSTORE(finalExpBN254_y2_23_y) + + ; 5] y3 = (m^x²)^p² + ; This has already been computed + + ; 6] y4 = \bar{(m^x)^p} + $ => A :MLOAD(finalExpBN254_mxp11_x) + $ => B :MLOAD(finalExpBN254_mxp11_y) + A :MSTORE(finalExpBN254_y4_11_x) + B :MSTORE(finalExpBN254_y4_11_y) + $ => A :MLOAD(finalExpBN254_mxp12_x) + $ => B :MLOAD(finalExpBN254_mxp12_y) + A :MSTORE(finalExpBN254_y4_12_x) + B :MSTORE(finalExpBN254_y4_12_y) + $ => A :MLOAD(finalExpBN254_mxp13_x) + $ => B :MLOAD(finalExpBN254_mxp13_y) + A :MSTORE(finalExpBN254_y4_13_x) + B :MSTORE(finalExpBN254_y4_13_y) + + %BN254_P => A + $ => B :MLOAD(finalExpBN254_mxp21_x) + $ :SUB, MSTORE(finalExpBN254_y4_21_x) + %BN254_P => A + $ => B :MLOAD(finalExpBN254_mxp21_y) + $ :SUB, MSTORE(finalExpBN254_y4_21_y) + %BN254_P => A + $ => B :MLOAD(finalExpBN254_mxp22_x) + $ :SUB, MSTORE(finalExpBN254_y4_22_x) + %BN254_P => A + $ => B :MLOAD(finalExpBN254_mxp22_y) + $ :SUB, MSTORE(finalExpBN254_y4_22_y) + %BN254_P => A + $ => B :MLOAD(finalExpBN254_mxp23_x) + $ :SUB, MSTORE(finalExpBN254_y4_23_x) + %BN254_P => A + $ => B :MLOAD(finalExpBN254_mxp23_y) + $ :SUB, MSTORE(finalExpBN254_y4_23_y) + + ; 7] y5 = \bar{m^x·(m^x²)^p} + $ => A :MLOAD(finalExpBN254_mx11_x) + $ => B :MLOAD(finalExpBN254_mx11_y) + A :MSTORE(mulFp12BN254_a11_x) + B :MSTORE(mulFp12BN254_a11_y) + $ => A :MLOAD(finalExpBN254_mx12_x) + $ => B :MLOAD(finalExpBN254_mx12_y) + A :MSTORE(mulFp12BN254_a12_x) + B :MSTORE(mulFp12BN254_a12_y) + $ => A :MLOAD(finalExpBN254_mx13_x) + $ => B :MLOAD(finalExpBN254_mx13_y) + A :MSTORE(mulFp12BN254_a13_x) + B :MSTORE(mulFp12BN254_a13_y) + $ => A :MLOAD(finalExpBN254_mx21_x) + $ => B :MLOAD(finalExpBN254_mx21_y) + A :MSTORE(mulFp12BN254_a21_x) + B :MSTORE(mulFp12BN254_a21_y) + $ => A :MLOAD(finalExpBN254_mx22_x) + $ => B :MLOAD(finalExpBN254_mx22_y) + A :MSTORE(mulFp12BN254_a22_x) + B :MSTORE(mulFp12BN254_a22_y) + $ => A :MLOAD(finalExpBN254_mx23_x) + $ => B :MLOAD(finalExpBN254_mx23_y) + A :MSTORE(mulFp12BN254_a23_x) + B :MSTORE(mulFp12BN254_a23_y) + $ => A :MLOAD(finalExpBN254_mxxp11_x) + $ => B :MLOAD(finalExpBN254_mxxp11_y) + A :MSTORE(mulFp12BN254_b11_x) + B :MSTORE(mulFp12BN254_b11_y) + $ => A :MLOAD(finalExpBN254_mxxp12_x) + $ => B :MLOAD(finalExpBN254_mxxp12_y) + A :MSTORE(mulFp12BN254_b12_x) + B :MSTORE(mulFp12BN254_b12_y) + $ => A :MLOAD(finalExpBN254_mxxp13_x) + $ => B :MLOAD(finalExpBN254_mxxp13_y) + A :MSTORE(mulFp12BN254_b13_x) + B :MSTORE(mulFp12BN254_b13_y) + $ => A :MLOAD(finalExpBN254_mxxp21_x) + $ => B :MLOAD(finalExpBN254_mxxp21_y) + A :MSTORE(mulFp12BN254_b21_x) + B :MSTORE(mulFp12BN254_b21_y) + $ => A :MLOAD(finalExpBN254_mxxp22_x) + $ => B :MLOAD(finalExpBN254_mxxp22_y) + A :MSTORE(mulFp12BN254_b22_x) + B :MSTORE(mulFp12BN254_b22_y) + $ => A :MLOAD(finalExpBN254_mxxp23_x) + $ => B :MLOAD(finalExpBN254_mxxp23_y) + A :MSTORE(mulFp12BN254_b23_x) + B :MSTORE(mulFp12BN254_b23_y), CALL(mulFp12BN254) + + $ => A :MLOAD(mulFp12BN254_c11_x) + $ => B :MLOAD(mulFp12BN254_c11_y) + A :MSTORE(finalExpBN254_y5_11_x) + B :MSTORE(finalExpBN254_y5_11_y) + $ => A :MLOAD(mulFp12BN254_c12_x) + $ => B :MLOAD(mulFp12BN254_c12_y) + A :MSTORE(finalExpBN254_y5_12_x) + B :MSTORE(finalExpBN254_y5_12_y) + $ => A :MLOAD(mulFp12BN254_c13_x) + $ => B :MLOAD(mulFp12BN254_c13_y) + A :MSTORE(finalExpBN254_y5_13_x) + B :MSTORE(finalExpBN254_y5_13_y) + + %BN254_P => A + $ => B :MLOAD(mulFp12BN254_c21_x) + $ :SUB, MSTORE(finalExpBN254_y5_21_x) + %BN254_P => A + $ => B :MLOAD(mulFp12BN254_c21_y) + $ :SUB, MSTORE(finalExpBN254_y5_21_y) + %BN254_P => A + $ => B :MLOAD(mulFp12BN254_c22_x) + $ :SUB, MSTORE(finalExpBN254_y5_22_x) + %BN254_P => A + $ => B :MLOAD(mulFp12BN254_c22_y) + $ :SUB, MSTORE(finalExpBN254_y5_22_y) + %BN254_P => A + $ => B :MLOAD(mulFp12BN254_c23_x) + $ :SUB, MSTORE(finalExpBN254_y5_23_x) + %BN254_P => A + $ => B :MLOAD(mulFp12BN254_c23_y) + $ :SUB, MSTORE(finalExpBN254_y5_23_y) + + ; 8] y6 = \bar{m^x²} + $ => A :MLOAD(finalExpBN254_mxx11_x) + $ => B :MLOAD(finalExpBN254_mxx11_y) + A :MSTORE(finalExpBN254_y6_11_x) + B :MSTORE(finalExpBN254_y6_11_y) + $ => A :MLOAD(finalExpBN254_mxx12_x) + $ => B :MLOAD(finalExpBN254_mxx12_y) + A :MSTORE(finalExpBN254_y6_12_x) + B :MSTORE(finalExpBN254_y6_12_y) + $ => A :MLOAD(finalExpBN254_mxx13_x) + $ => B :MLOAD(finalExpBN254_mxx13_y) + A :MSTORE(finalExpBN254_y6_13_x) + B :MSTORE(finalExpBN254_y6_13_y) + + %BN254_P => A + $ => B :MLOAD(finalExpBN254_mxx21_x) + $ :SUB, MSTORE(finalExpBN254_y6_21_x) + %BN254_P => A + $ => B :MLOAD(finalExpBN254_mxx21_y) + $ :SUB, MSTORE(finalExpBN254_y6_21_y) + %BN254_P => A + $ => B :MLOAD(finalExpBN254_mxx22_x) + $ :SUB, MSTORE(finalExpBN254_y6_22_x) + %BN254_P => A + $ => B :MLOAD(finalExpBN254_mxx22_y) + $ :SUB, MSTORE(finalExpBN254_y6_22_y) + %BN254_P => A + $ => B :MLOAD(finalExpBN254_mxx23_x) + $ :SUB, MSTORE(finalExpBN254_y6_23_x) + %BN254_P => A + $ => B :MLOAD(finalExpBN254_mxx23_y) + $ :SUB, MSTORE(finalExpBN254_y6_23_y) + + ; 9] y7 = \bar{m^x³·(m^x³)^p} + $ => A :MLOAD(finalExpBN254_mxxx11_x) + $ => B :MLOAD(finalExpBN254_mxxx11_y) + A :MSTORE(mulFp12BN254_a11_x) + B :MSTORE(mulFp12BN254_a11_y) + $ => A :MLOAD(finalExpBN254_mxxx12_x) + $ => B :MLOAD(finalExpBN254_mxxx12_y) + A :MSTORE(mulFp12BN254_a12_x) + B :MSTORE(mulFp12BN254_a12_y) + $ => A :MLOAD(finalExpBN254_mxxx13_x) + $ => B :MLOAD(finalExpBN254_mxxx13_y) + A :MSTORE(mulFp12BN254_a13_x) + B :MSTORE(mulFp12BN254_a13_y) + $ => A :MLOAD(finalExpBN254_mxxx21_x) + $ => B :MLOAD(finalExpBN254_mxxx21_y) + A :MSTORE(mulFp12BN254_a21_x) + B :MSTORE(mulFp12BN254_a21_y) + $ => A :MLOAD(finalExpBN254_mxxx22_x) + $ => B :MLOAD(finalExpBN254_mxxx22_y) + A :MSTORE(mulFp12BN254_a22_x) + B :MSTORE(mulFp12BN254_a22_y) + $ => A :MLOAD(finalExpBN254_mxxx23_x) + $ => B :MLOAD(finalExpBN254_mxxx23_y) + A :MSTORE(mulFp12BN254_a23_x) + B :MSTORE(mulFp12BN254_a23_y) + $ => A :MLOAD(finalExpBN254_mxxxp11_x) + $ => B :MLOAD(finalExpBN254_mxxxp11_y) + A :MSTORE(mulFp12BN254_b11_x) + B :MSTORE(mulFp12BN254_b11_y) + $ => A :MLOAD(finalExpBN254_mxxxp12_x) + $ => B :MLOAD(finalExpBN254_mxxxp12_y) + A :MSTORE(mulFp12BN254_b12_x) + B :MSTORE(mulFp12BN254_b12_y) + $ => A :MLOAD(finalExpBN254_mxxxp13_x) + $ => B :MLOAD(finalExpBN254_mxxxp13_y) + A :MSTORE(mulFp12BN254_b13_x) + B :MSTORE(mulFp12BN254_b13_y) + $ => A :MLOAD(finalExpBN254_mxxxp21_x) + $ => B :MLOAD(finalExpBN254_mxxxp21_y) + A :MSTORE(mulFp12BN254_b21_x) + B :MSTORE(mulFp12BN254_b21_y) + $ => A :MLOAD(finalExpBN254_mxxxp22_x) + $ => B :MLOAD(finalExpBN254_mxxxp22_y) + A :MSTORE(mulFp12BN254_b22_x) + B :MSTORE(mulFp12BN254_b22_y) + $ => A :MLOAD(finalExpBN254_mxxxp23_x) + $ => B :MLOAD(finalExpBN254_mxxxp23_y) + A :MSTORE(mulFp12BN254_b23_x) + B :MSTORE(mulFp12BN254_b23_y), CALL(mulFp12BN254) + + $ => A :MLOAD(mulFp12BN254_c11_x) + $ => B :MLOAD(mulFp12BN254_c11_y) + A :MSTORE(finalExpBN254_y7_11_x) + B :MSTORE(finalExpBN254_y7_11_y) + $ => A :MLOAD(mulFp12BN254_c12_x) + $ => B :MLOAD(mulFp12BN254_c12_y) + A :MSTORE(finalExpBN254_y7_12_x) + B :MSTORE(finalExpBN254_y7_12_y) + $ => A :MLOAD(mulFp12BN254_c13_x) + $ => B :MLOAD(mulFp12BN254_c13_y) + A :MSTORE(finalExpBN254_y7_13_x) + B :MSTORE(finalExpBN254_y7_13_y) + + %BN254_P => A + $ => B :MLOAD(mulFp12BN254_c21_x) + $ :SUB, MSTORE(finalExpBN254_y7_21_x) + %BN254_P => A + $ => B :MLOAD(mulFp12BN254_c21_y) + $ :SUB, MSTORE(finalExpBN254_y7_21_y) + %BN254_P => A + $ => B :MLOAD(mulFp12BN254_c22_x) + $ :SUB, MSTORE(finalExpBN254_y7_22_x) + %BN254_P => A + $ => B :MLOAD(mulFp12BN254_c22_y) + $ :SUB, MSTORE(finalExpBN254_y7_22_y) + %BN254_P => A + $ => B :MLOAD(mulFp12BN254_c23_x) + $ :SUB, MSTORE(finalExpBN254_y7_23_x) + %BN254_P => A + $ => B :MLOAD(mulFp12BN254_c23_y) + $ :SUB, MSTORE(finalExpBN254_y7_23_y) + + ; 10] Compute y1·y2²·y3⁶·y4¹²·y5¹⁸·y6³⁰·y7³⁶ as follows + + ; 10.1] T11 = y7²·y5·y6 + $ => A :MLOAD(finalExpBN254_y7_11_x) + $ => B :MLOAD(finalExpBN254_y7_11_y) + A :MSTORE(squareCycloFp12BN254_a11_x) + B :MSTORE(squareCycloFp12BN254_a11_y) + $ => A :MLOAD(finalExpBN254_y7_12_x) + $ => B :MLOAD(finalExpBN254_y7_12_y) + A :MSTORE(squareCycloFp12BN254_a12_x) + B :MSTORE(squareCycloFp12BN254_a12_y) + $ => A :MLOAD(finalExpBN254_y7_13_x) + $ => B :MLOAD(finalExpBN254_y7_13_y) + A :MSTORE(squareCycloFp12BN254_a13_x) + B :MSTORE(squareCycloFp12BN254_a13_y) + $ => A :MLOAD(finalExpBN254_y7_21_x) + $ => B :MLOAD(finalExpBN254_y7_21_y) + A :MSTORE(squareCycloFp12BN254_a21_x) + B :MSTORE(squareCycloFp12BN254_a21_y) + $ => A :MLOAD(finalExpBN254_y7_22_x) + $ => B :MLOAD(finalExpBN254_y7_22_y) + A :MSTORE(squareCycloFp12BN254_a22_x) + B :MSTORE(squareCycloFp12BN254_a22_y) + $ => A :MLOAD(finalExpBN254_y7_23_x) + $ => B :MLOAD(finalExpBN254_y7_23_y) + A :MSTORE(squareCycloFp12BN254_a23_x) + B :MSTORE(squareCycloFp12BN254_a23_y), CALL(squareCycloFp12BN254) + + $ => A :MLOAD(squareCycloFp12BN254_c11_x) + $ => B :MLOAD(squareCycloFp12BN254_c11_y) + A :MSTORE(mulFp12BN254_a11_x) + B :MSTORE(mulFp12BN254_a11_y) + $ => A :MLOAD(squareCycloFp12BN254_c12_x) + $ => B :MLOAD(squareCycloFp12BN254_c12_y) + A :MSTORE(mulFp12BN254_a12_x) + B :MSTORE(mulFp12BN254_a12_y) + $ => A :MLOAD(squareCycloFp12BN254_c13_x) + $ => B :MLOAD(squareCycloFp12BN254_c13_y) + A :MSTORE(mulFp12BN254_a13_x) + B :MSTORE(mulFp12BN254_a13_y) + $ => A :MLOAD(squareCycloFp12BN254_c21_x) + $ => B :MLOAD(squareCycloFp12BN254_c21_y) + A :MSTORE(mulFp12BN254_a21_x) + B :MSTORE(mulFp12BN254_a21_y) + $ => A :MLOAD(squareCycloFp12BN254_c22_x) + $ => B :MLOAD(squareCycloFp12BN254_c22_y) + A :MSTORE(mulFp12BN254_a22_x) + B :MSTORE(mulFp12BN254_a22_y) + $ => A :MLOAD(squareCycloFp12BN254_c23_x) + $ => B :MLOAD(squareCycloFp12BN254_c23_y) + A :MSTORE(mulFp12BN254_a23_x) + B :MSTORE(mulFp12BN254_a23_y) + $ => A :MLOAD(finalExpBN254_y5_11_x) + $ => B :MLOAD(finalExpBN254_y5_11_y) + A :MSTORE(mulFp12BN254_b11_x) + B :MSTORE(mulFp12BN254_b11_y) + $ => A :MLOAD(finalExpBN254_y5_12_x) + $ => B :MLOAD(finalExpBN254_y5_12_y) + A :MSTORE(mulFp12BN254_b12_x) + B :MSTORE(mulFp12BN254_b12_y) + $ => A :MLOAD(finalExpBN254_y5_13_x) + $ => B :MLOAD(finalExpBN254_y5_13_y) + A :MSTORE(mulFp12BN254_b13_x) + B :MSTORE(mulFp12BN254_b13_y) + $ => A :MLOAD(finalExpBN254_y5_21_x) + $ => B :MLOAD(finalExpBN254_y5_21_y) + A :MSTORE(mulFp12BN254_b21_x) + B :MSTORE(mulFp12BN254_b21_y) + $ => A :MLOAD(finalExpBN254_y5_22_x) + $ => B :MLOAD(finalExpBN254_y5_22_y) + A :MSTORE(mulFp12BN254_b22_x) + B :MSTORE(mulFp12BN254_b22_y) + $ => A :MLOAD(finalExpBN254_y5_23_x) + $ => B :MLOAD(finalExpBN254_y5_23_y) + A :MSTORE(mulFp12BN254_b23_x) + B :MSTORE(mulFp12BN254_b23_y), CALL(mulFp12BN254) + + $ => A :MLOAD(mulFp12BN254_c11_x) + $ => B :MLOAD(mulFp12BN254_c11_y) + A :MSTORE(mulFp12BN254_a11_x) + B :MSTORE(mulFp12BN254_a11_y) + $ => A :MLOAD(mulFp12BN254_c12_x) + $ => B :MLOAD(mulFp12BN254_c12_y) + A :MSTORE(mulFp12BN254_a12_x) + B :MSTORE(mulFp12BN254_a12_y) + $ => A :MLOAD(mulFp12BN254_c13_x) + $ => B :MLOAD(mulFp12BN254_c13_y) + A :MSTORE(mulFp12BN254_a13_x) + B :MSTORE(mulFp12BN254_a13_y) + $ => A :MLOAD(mulFp12BN254_c21_x) + $ => B :MLOAD(mulFp12BN254_c21_y) + A :MSTORE(mulFp12BN254_a21_x) + B :MSTORE(mulFp12BN254_a21_y) + $ => A :MLOAD(mulFp12BN254_c22_x) + $ => B :MLOAD(mulFp12BN254_c22_y) + A :MSTORE(mulFp12BN254_a22_x) + B :MSTORE(mulFp12BN254_a22_y) + $ => A :MLOAD(mulFp12BN254_c23_x) + $ => B :MLOAD(mulFp12BN254_c23_y) + A :MSTORE(mulFp12BN254_a23_x) + B :MSTORE(mulFp12BN254_a23_y) + $ => A :MLOAD(finalExpBN254_y6_11_x) + $ => B :MLOAD(finalExpBN254_y6_11_y) + A :MSTORE(mulFp12BN254_b11_x) + B :MSTORE(mulFp12BN254_b11_y) + $ => A :MLOAD(finalExpBN254_y6_12_x) + $ => B :MLOAD(finalExpBN254_y6_12_y) + A :MSTORE(mulFp12BN254_b12_x) + B :MSTORE(mulFp12BN254_b12_y) + $ => A :MLOAD(finalExpBN254_y6_13_x) + $ => B :MLOAD(finalExpBN254_y6_13_y) + A :MSTORE(mulFp12BN254_b13_x) + B :MSTORE(mulFp12BN254_b13_y) + $ => A :MLOAD(finalExpBN254_y6_21_x) + $ => B :MLOAD(finalExpBN254_y6_21_y) + A :MSTORE(mulFp12BN254_b21_x) + B :MSTORE(mulFp12BN254_b21_y) + $ => A :MLOAD(finalExpBN254_y6_22_x) + $ => B :MLOAD(finalExpBN254_y6_22_y) + A :MSTORE(mulFp12BN254_b22_x) + B :MSTORE(mulFp12BN254_b22_y) + $ => A :MLOAD(finalExpBN254_y6_23_x) + $ => B :MLOAD(finalExpBN254_y6_23_y) + A :MSTORE(mulFp12BN254_b23_x) + B :MSTORE(mulFp12BN254_b23_y), CALL(mulFp12BN254) + + $ => A :MLOAD(mulFp12BN254_c11_x) + $ => B :MLOAD(mulFp12BN254_c11_y) + A :MSTORE(finalExpBN254_T11_11_x) + B :MSTORE(finalExpBN254_T11_11_y) + $ => A :MLOAD(mulFp12BN254_c12_x) + $ => B :MLOAD(mulFp12BN254_c12_y) + A :MSTORE(finalExpBN254_T11_12_x) + B :MSTORE(finalExpBN254_T11_12_y) + $ => A :MLOAD(mulFp12BN254_c13_x) + $ => B :MLOAD(mulFp12BN254_c13_y) + A :MSTORE(finalExpBN254_T11_13_x) + B :MSTORE(finalExpBN254_T11_13_y) + $ => A :MLOAD(mulFp12BN254_c21_x) + $ => B :MLOAD(mulFp12BN254_c21_y) + A :MSTORE(finalExpBN254_T11_21_x) + B :MSTORE(finalExpBN254_T11_21_y) + $ => A :MLOAD(mulFp12BN254_c22_x) + $ => B :MLOAD(mulFp12BN254_c22_y) + A :MSTORE(finalExpBN254_T11_22_x) + B :MSTORE(finalExpBN254_T11_22_y) + $ => A :MLOAD(mulFp12BN254_c23_x) + $ => B :MLOAD(mulFp12BN254_c23_y) + A :MSTORE(finalExpBN254_T11_23_x) + B :MSTORE(finalExpBN254_T11_23_y) + + ; 10.2] T21 = T11·y4·y6 + $ => A :MLOAD(finalExpBN254_T11_11_x) + $ => B :MLOAD(finalExpBN254_T11_11_y) + A :MSTORE(mulFp12BN254_a11_x) + B :MSTORE(mulFp12BN254_a11_y) + $ => A :MLOAD(finalExpBN254_T11_12_x) + $ => B :MLOAD(finalExpBN254_T11_12_y) + A :MSTORE(mulFp12BN254_a12_x) + B :MSTORE(mulFp12BN254_a12_y) + $ => A :MLOAD(finalExpBN254_T11_13_x) + $ => B :MLOAD(finalExpBN254_T11_13_y) + A :MSTORE(mulFp12BN254_a13_x) + B :MSTORE(mulFp12BN254_a13_y) + $ => A :MLOAD(finalExpBN254_T11_21_x) + $ => B :MLOAD(finalExpBN254_T11_21_y) + A :MSTORE(mulFp12BN254_a21_x) + B :MSTORE(mulFp12BN254_a21_y) + $ => A :MLOAD(finalExpBN254_T11_22_x) + $ => B :MLOAD(finalExpBN254_T11_22_y) + A :MSTORE(mulFp12BN254_a22_x) + B :MSTORE(mulFp12BN254_a22_y) + $ => A :MLOAD(finalExpBN254_T11_23_x) + $ => B :MLOAD(finalExpBN254_T11_23_y) + A :MSTORE(mulFp12BN254_a23_x) + B :MSTORE(mulFp12BN254_a23_y) + $ => A :MLOAD(finalExpBN254_y4_11_x) + $ => B :MLOAD(finalExpBN254_y4_11_y) + A :MSTORE(mulFp12BN254_b11_x) + B :MSTORE(mulFp12BN254_b11_y) + $ => A :MLOAD(finalExpBN254_y4_12_x) + $ => B :MLOAD(finalExpBN254_y4_12_y) + A :MSTORE(mulFp12BN254_b12_x) + B :MSTORE(mulFp12BN254_b12_y) + $ => A :MLOAD(finalExpBN254_y4_13_x) + $ => B :MLOAD(finalExpBN254_y4_13_y) + A :MSTORE(mulFp12BN254_b13_x) + B :MSTORE(mulFp12BN254_b13_y) + $ => A :MLOAD(finalExpBN254_y4_21_x) + $ => B :MLOAD(finalExpBN254_y4_21_y) + A :MSTORE(mulFp12BN254_b21_x) + B :MSTORE(mulFp12BN254_b21_y) + $ => A :MLOAD(finalExpBN254_y4_22_x) + $ => B :MLOAD(finalExpBN254_y4_22_y) + A :MSTORE(mulFp12BN254_b22_x) + B :MSTORE(mulFp12BN254_b22_y) + $ => A :MLOAD(finalExpBN254_y4_23_x) + $ => B :MLOAD(finalExpBN254_y4_23_y) + A :MSTORE(mulFp12BN254_b23_x) + B :MSTORE(mulFp12BN254_b23_y), CALL(mulFp12BN254) + + $ => A :MLOAD(mulFp12BN254_c11_x) + $ => B :MLOAD(mulFp12BN254_c11_y) + A :MSTORE(mulFp12BN254_a11_x) + B :MSTORE(mulFp12BN254_a11_y) + $ => A :MLOAD(mulFp12BN254_c12_x) + $ => B :MLOAD(mulFp12BN254_c12_y) + A :MSTORE(mulFp12BN254_a12_x) + B :MSTORE(mulFp12BN254_a12_y) + $ => A :MLOAD(mulFp12BN254_c13_x) + $ => B :MLOAD(mulFp12BN254_c13_y) + A :MSTORE(mulFp12BN254_a13_x) + B :MSTORE(mulFp12BN254_a13_y) + $ => A :MLOAD(mulFp12BN254_c21_x) + $ => B :MLOAD(mulFp12BN254_c21_y) + A :MSTORE(mulFp12BN254_a21_x) + B :MSTORE(mulFp12BN254_a21_y) + $ => A :MLOAD(mulFp12BN254_c22_x) + $ => B :MLOAD(mulFp12BN254_c22_y) + A :MSTORE(mulFp12BN254_a22_x) + B :MSTORE(mulFp12BN254_a22_y) + $ => A :MLOAD(mulFp12BN254_c23_x) + $ => B :MLOAD(mulFp12BN254_c23_y) + A :MSTORE(mulFp12BN254_a23_x) + B :MSTORE(mulFp12BN254_a23_y) + $ => A :MLOAD(finalExpBN254_y6_11_x) + $ => B :MLOAD(finalExpBN254_y6_11_y) + A :MSTORE(mulFp12BN254_b11_x) + B :MSTORE(mulFp12BN254_b11_y) + $ => A :MLOAD(finalExpBN254_y6_12_x) + $ => B :MLOAD(finalExpBN254_y6_12_y) + A :MSTORE(mulFp12BN254_b12_x) + B :MSTORE(mulFp12BN254_b12_y) + $ => A :MLOAD(finalExpBN254_y6_13_x) + $ => B :MLOAD(finalExpBN254_y6_13_y) + A :MSTORE(mulFp12BN254_b13_x) + B :MSTORE(mulFp12BN254_b13_y) + $ => A :MLOAD(finalExpBN254_y6_21_x) + $ => B :MLOAD(finalExpBN254_y6_21_y) + A :MSTORE(mulFp12BN254_b21_x) + B :MSTORE(mulFp12BN254_b21_y) + $ => A :MLOAD(finalExpBN254_y6_22_x) + $ => B :MLOAD(finalExpBN254_y6_22_y) + A :MSTORE(mulFp12BN254_b22_x) + B :MSTORE(mulFp12BN254_b22_y) + $ => A :MLOAD(finalExpBN254_y6_23_x) + $ => B :MLOAD(finalExpBN254_y6_23_y) + A :MSTORE(mulFp12BN254_b23_x) + B :MSTORE(mulFp12BN254_b23_y), CALL(mulFp12BN254) + + $ => A :MLOAD(mulFp12BN254_c11_x) + $ => B :MLOAD(mulFp12BN254_c11_y) + A :MSTORE(finalExpBN254_T21_11_x) + B :MSTORE(finalExpBN254_T21_11_y) + $ => A :MLOAD(mulFp12BN254_c12_x) + $ => B :MLOAD(mulFp12BN254_c12_y) + A :MSTORE(finalExpBN254_T21_12_x) + B :MSTORE(finalExpBN254_T21_12_y) + $ => A :MLOAD(mulFp12BN254_c13_x) + $ => B :MLOAD(mulFp12BN254_c13_y) + A :MSTORE(finalExpBN254_T21_13_x) + B :MSTORE(finalExpBN254_T21_13_y) + $ => A :MLOAD(mulFp12BN254_c21_x) + $ => B :MLOAD(mulFp12BN254_c21_y) + A :MSTORE(finalExpBN254_T21_21_x) + B :MSTORE(finalExpBN254_T21_21_y) + $ => A :MLOAD(mulFp12BN254_c22_x) + $ => B :MLOAD(mulFp12BN254_c22_y) + A :MSTORE(finalExpBN254_T21_22_x) + B :MSTORE(finalExpBN254_T21_22_y) + $ => A :MLOAD(mulFp12BN254_c23_x) + $ => B :MLOAD(mulFp12BN254_c23_y) + A :MSTORE(finalExpBN254_T21_23_x) + B :MSTORE(finalExpBN254_T21_23_y) + + ; 10.3] T12 = T11·y3 + $ => A :MLOAD(finalExpBN254_T11_11_x) + $ => B :MLOAD(finalExpBN254_T11_11_y) + A :MSTORE(mulFp12BN254_a11_x) + B :MSTORE(mulFp12BN254_a11_y) + $ => A :MLOAD(finalExpBN254_T11_12_x) + $ => B :MLOAD(finalExpBN254_T11_12_y) + A :MSTORE(mulFp12BN254_a12_x) + B :MSTORE(mulFp12BN254_a12_y) + $ => A :MLOAD(finalExpBN254_T11_13_x) + $ => B :MLOAD(finalExpBN254_T11_13_y) + A :MSTORE(mulFp12BN254_a13_x) + B :MSTORE(mulFp12BN254_a13_y) + $ => A :MLOAD(finalExpBN254_T11_21_x) + $ => B :MLOAD(finalExpBN254_T11_21_y) + A :MSTORE(mulFp12BN254_a21_x) + B :MSTORE(mulFp12BN254_a21_y) + $ => A :MLOAD(finalExpBN254_T11_22_x) + $ => B :MLOAD(finalExpBN254_T11_22_y) + A :MSTORE(mulFp12BN254_a22_x) + B :MSTORE(mulFp12BN254_a22_y) + $ => A :MLOAD(finalExpBN254_T11_23_x) + $ => B :MLOAD(finalExpBN254_T11_23_y) + A :MSTORE(mulFp12BN254_a23_x) + B :MSTORE(mulFp12BN254_a23_y) + $ => A :MLOAD(finalExpBN254_mxxpp11_x) + $ => B :MLOAD(finalExpBN254_mxxpp11_y) + A :MSTORE(mulFp12BN254_b11_x) + B :MSTORE(mulFp12BN254_b11_y) + $ => A :MLOAD(finalExpBN254_mxxpp12_x) + $ => B :MLOAD(finalExpBN254_mxxpp12_y) + A :MSTORE(mulFp12BN254_b12_x) + B :MSTORE(mulFp12BN254_b12_y) + $ => A :MLOAD(finalExpBN254_mxxpp13_x) + $ => B :MLOAD(finalExpBN254_mxxpp13_y) + A :MSTORE(mulFp12BN254_b13_x) + B :MSTORE(mulFp12BN254_b13_y) + $ => A :MLOAD(finalExpBN254_mxxpp21_x) + $ => B :MLOAD(finalExpBN254_mxxpp21_y) + A :MSTORE(mulFp12BN254_b21_x) + B :MSTORE(mulFp12BN254_b21_y) + $ => A :MLOAD(finalExpBN254_mxxpp22_x) + $ => B :MLOAD(finalExpBN254_mxxpp22_y) + A :MSTORE(mulFp12BN254_b22_x) + B :MSTORE(mulFp12BN254_b22_y) + $ => A :MLOAD(finalExpBN254_mxxpp23_x) + $ => B :MLOAD(finalExpBN254_mxxpp23_y) + A :MSTORE(mulFp12BN254_b23_x) + B :MSTORE(mulFp12BN254_b23_y), CALL(mulFp12BN254) + + $ => A :MLOAD(mulFp12BN254_c11_x) + $ => B :MLOAD(mulFp12BN254_c11_y) + A :MSTORE(finalExpBN254_T12_11_x) + B :MSTORE(finalExpBN254_T12_11_y) + $ => A :MLOAD(mulFp12BN254_c12_x) + $ => B :MLOAD(mulFp12BN254_c12_y) + A :MSTORE(finalExpBN254_T12_12_x) + B :MSTORE(finalExpBN254_T12_12_y) + $ => A :MLOAD(mulFp12BN254_c13_x) + $ => B :MLOAD(mulFp12BN254_c13_y) + A :MSTORE(finalExpBN254_T12_13_x) + B :MSTORE(finalExpBN254_T12_13_y) + $ => A :MLOAD(mulFp12BN254_c21_x) + $ => B :MLOAD(mulFp12BN254_c21_y) + A :MSTORE(finalExpBN254_T12_21_x) + B :MSTORE(finalExpBN254_T12_21_y) + $ => A :MLOAD(mulFp12BN254_c22_x) + $ => B :MLOAD(mulFp12BN254_c22_y) + A :MSTORE(finalExpBN254_T12_22_x) + B :MSTORE(finalExpBN254_T12_22_y) + $ => A :MLOAD(mulFp12BN254_c23_x) + $ => B :MLOAD(mulFp12BN254_c23_y) + A :MSTORE(finalExpBN254_T12_23_x) + B :MSTORE(finalExpBN254_T12_23_y) + + ; 10.4] T22 = T21²·T12 + $ => A :MLOAD(finalExpBN254_T21_11_x) + $ => B :MLOAD(finalExpBN254_T21_11_y) + A :MSTORE(squareCycloFp12BN254_a11_x) + B :MSTORE(squareCycloFp12BN254_a11_y) + $ => A :MLOAD(finalExpBN254_T21_12_x) + $ => B :MLOAD(finalExpBN254_T21_12_y) + A :MSTORE(squareCycloFp12BN254_a12_x) + B :MSTORE(squareCycloFp12BN254_a12_y) + $ => A :MLOAD(finalExpBN254_T21_13_x) + $ => B :MLOAD(finalExpBN254_T21_13_y) + A :MSTORE(squareCycloFp12BN254_a13_x) + B :MSTORE(squareCycloFp12BN254_a13_y) + $ => A :MLOAD(finalExpBN254_T21_21_x) + $ => B :MLOAD(finalExpBN254_T21_21_y) + A :MSTORE(squareCycloFp12BN254_a21_x) + B :MSTORE(squareCycloFp12BN254_a21_y) + $ => A :MLOAD(finalExpBN254_T21_22_x) + $ => B :MLOAD(finalExpBN254_T21_22_y) + A :MSTORE(squareCycloFp12BN254_a22_x) + B :MSTORE(squareCycloFp12BN254_a22_y) + $ => A :MLOAD(finalExpBN254_T21_23_x) + $ => B :MLOAD(finalExpBN254_T21_23_y) + A :MSTORE(squareCycloFp12BN254_a23_x) + B :MSTORE(squareCycloFp12BN254_a23_y), CALL(squareCycloFp12BN254) + + $ => A :MLOAD(squareCycloFp12BN254_c11_x) + $ => B :MLOAD(squareCycloFp12BN254_c11_y) + A :MSTORE(mulFp12BN254_a11_x) + B :MSTORE(mulFp12BN254_a11_y) + $ => A :MLOAD(squareCycloFp12BN254_c12_x) + $ => B :MLOAD(squareCycloFp12BN254_c12_y) + A :MSTORE(mulFp12BN254_a12_x) + B :MSTORE(mulFp12BN254_a12_y) + $ => A :MLOAD(squareCycloFp12BN254_c13_x) + $ => B :MLOAD(squareCycloFp12BN254_c13_y) + A :MSTORE(mulFp12BN254_a13_x) + B :MSTORE(mulFp12BN254_a13_y) + $ => A :MLOAD(squareCycloFp12BN254_c21_x) + $ => B :MLOAD(squareCycloFp12BN254_c21_y) + A :MSTORE(mulFp12BN254_a21_x) + B :MSTORE(mulFp12BN254_a21_y) + $ => A :MLOAD(squareCycloFp12BN254_c22_x) + $ => B :MLOAD(squareCycloFp12BN254_c22_y) + A :MSTORE(mulFp12BN254_a22_x) + B :MSTORE(mulFp12BN254_a22_y) + $ => A :MLOAD(squareCycloFp12BN254_c23_x) + $ => B :MLOAD(squareCycloFp12BN254_c23_y) + A :MSTORE(mulFp12BN254_a23_x) + B :MSTORE(mulFp12BN254_a23_y) + $ => A :MLOAD(finalExpBN254_T12_11_x) + $ => B :MLOAD(finalExpBN254_T12_11_y) + A :MSTORE(mulFp12BN254_b11_x) + B :MSTORE(mulFp12BN254_b11_y) + $ => A :MLOAD(finalExpBN254_T12_12_x) + $ => B :MLOAD(finalExpBN254_T12_12_y) + A :MSTORE(mulFp12BN254_b12_x) + B :MSTORE(mulFp12BN254_b12_y) + $ => A :MLOAD(finalExpBN254_T12_13_x) + $ => B :MLOAD(finalExpBN254_T12_13_y) + A :MSTORE(mulFp12BN254_b13_x) + B :MSTORE(mulFp12BN254_b13_y) + $ => A :MLOAD(finalExpBN254_T12_21_x) + $ => B :MLOAD(finalExpBN254_T12_21_y) + A :MSTORE(mulFp12BN254_b21_x) + B :MSTORE(mulFp12BN254_b21_y) + $ => A :MLOAD(finalExpBN254_T12_22_x) + $ => B :MLOAD(finalExpBN254_T12_22_y) + A :MSTORE(mulFp12BN254_b22_x) + B :MSTORE(mulFp12BN254_b22_y) + $ => A :MLOAD(finalExpBN254_T12_23_x) + $ => B :MLOAD(finalExpBN254_T12_23_y) + A :MSTORE(mulFp12BN254_b23_x) + B :MSTORE(mulFp12BN254_b23_y), CALL(mulFp12BN254) + + ; 10.5] T23 = T22² + $ => A :MLOAD(mulFp12BN254_c11_x) + $ => B :MLOAD(mulFp12BN254_c11_y) + A :MSTORE(squareCycloFp12BN254_a11_x) + B :MSTORE(squareCycloFp12BN254_a11_y) + $ => A :MLOAD(mulFp12BN254_c12_x) + $ => B :MLOAD(mulFp12BN254_c12_y) + A :MSTORE(squareCycloFp12BN254_a12_x) + B :MSTORE(squareCycloFp12BN254_a12_y) + $ => A :MLOAD(mulFp12BN254_c13_x) + $ => B :MLOAD(mulFp12BN254_c13_y) + A :MSTORE(squareCycloFp12BN254_a13_x) + B :MSTORE(squareCycloFp12BN254_a13_y) + $ => A :MLOAD(mulFp12BN254_c21_x) + $ => B :MLOAD(mulFp12BN254_c21_y) + A :MSTORE(squareCycloFp12BN254_a21_x) + B :MSTORE(squareCycloFp12BN254_a21_y) + $ => A :MLOAD(mulFp12BN254_c22_x) + $ => B :MLOAD(mulFp12BN254_c22_y) + A :MSTORE(squareCycloFp12BN254_a22_x) + B :MSTORE(squareCycloFp12BN254_a22_y) + $ => A :MLOAD(mulFp12BN254_c23_x) + $ => B :MLOAD(mulFp12BN254_c23_y) + A :MSTORE(squareCycloFp12BN254_a23_x) + B :MSTORE(squareCycloFp12BN254_a23_y), CALL(squareCycloFp12BN254) + + $ => A :MLOAD(squareCycloFp12BN254_c11_x) + $ => B :MLOAD(squareCycloFp12BN254_c11_y) + A :MSTORE(finalExpBN254_T23_11_x) + B :MSTORE(finalExpBN254_T23_11_y) + $ => A :MLOAD(squareCycloFp12BN254_c12_x) + $ => B :MLOAD(squareCycloFp12BN254_c12_y) + A :MSTORE(finalExpBN254_T23_12_x) + B :MSTORE(finalExpBN254_T23_12_y) + $ => A :MLOAD(squareCycloFp12BN254_c13_x) + $ => B :MLOAD(squareCycloFp12BN254_c13_y) + A :MSTORE(finalExpBN254_T23_13_x) + B :MSTORE(finalExpBN254_T23_13_y) + $ => A :MLOAD(squareCycloFp12BN254_c21_x) + $ => B :MLOAD(squareCycloFp12BN254_c21_y) + A :MSTORE(finalExpBN254_T23_21_x) + B :MSTORE(finalExpBN254_T23_21_y) + $ => A :MLOAD(squareCycloFp12BN254_c22_x) + $ => B :MLOAD(squareCycloFp12BN254_c22_y) + A :MSTORE(finalExpBN254_T23_22_x) + B :MSTORE(finalExpBN254_T23_22_y) + $ => A :MLOAD(squareCycloFp12BN254_c23_x) + $ => B :MLOAD(squareCycloFp12BN254_c23_y) + A :MSTORE(finalExpBN254_T23_23_x) + B :MSTORE(finalExpBN254_T23_23_y) + + ; 10.6] T24 = T23·y1 + $ => A :MLOAD(finalExpBN254_T23_11_x) + $ => B :MLOAD(finalExpBN254_T23_11_y) + A :MSTORE(mulFp12BN254_a11_x) + B :MSTORE(mulFp12BN254_a11_y) + $ => A :MLOAD(finalExpBN254_T23_12_x) + $ => B :MLOAD(finalExpBN254_T23_12_y) + A :MSTORE(mulFp12BN254_a12_x) + B :MSTORE(mulFp12BN254_a12_y) + $ => A :MLOAD(finalExpBN254_T23_13_x) + $ => B :MLOAD(finalExpBN254_T23_13_y) + A :MSTORE(mulFp12BN254_a13_x) + B :MSTORE(mulFp12BN254_a13_y) + $ => A :MLOAD(finalExpBN254_T23_21_x) + $ => B :MLOAD(finalExpBN254_T23_21_y) + A :MSTORE(mulFp12BN254_a21_x) + B :MSTORE(mulFp12BN254_a21_y) + $ => A :MLOAD(finalExpBN254_T23_22_x) + $ => B :MLOAD(finalExpBN254_T23_22_y) + A :MSTORE(mulFp12BN254_a22_x) + B :MSTORE(mulFp12BN254_a22_y) + $ => A :MLOAD(finalExpBN254_T23_23_x) + $ => B :MLOAD(finalExpBN254_T23_23_y) + A :MSTORE(mulFp12BN254_a23_x) + B :MSTORE(mulFp12BN254_a23_y) + $ => A :MLOAD(finalExpBN254_y1_11_x) + $ => B :MLOAD(finalExpBN254_y1_11_y) + A :MSTORE(mulFp12BN254_b11_x) + B :MSTORE(mulFp12BN254_b11_y) + $ => A :MLOAD(finalExpBN254_y1_12_x) + $ => B :MLOAD(finalExpBN254_y1_12_y) + A :MSTORE(mulFp12BN254_b12_x) + B :MSTORE(mulFp12BN254_b12_y) + $ => A :MLOAD(finalExpBN254_y1_13_x) + $ => B :MLOAD(finalExpBN254_y1_13_y) + A :MSTORE(mulFp12BN254_b13_x) + B :MSTORE(mulFp12BN254_b13_y) + $ => A :MLOAD(finalExpBN254_y1_21_x) + $ => B :MLOAD(finalExpBN254_y1_21_y) + A :MSTORE(mulFp12BN254_b21_x) + B :MSTORE(mulFp12BN254_b21_y) + $ => A :MLOAD(finalExpBN254_y1_22_x) + $ => B :MLOAD(finalExpBN254_y1_22_y) + A :MSTORE(mulFp12BN254_b22_x) + B :MSTORE(mulFp12BN254_b22_y) + $ => A :MLOAD(finalExpBN254_y1_23_x) + $ => B :MLOAD(finalExpBN254_y1_23_y) + A :MSTORE(mulFp12BN254_b23_x) + B :MSTORE(mulFp12BN254_b23_y), CALL(mulFp12BN254) + + $ => A :MLOAD(mulFp12BN254_c11_x) + $ => B :MLOAD(mulFp12BN254_c11_y) + A :MSTORE(finalExpBN254_T24_11_x) + B :MSTORE(finalExpBN254_T24_11_y) + $ => A :MLOAD(mulFp12BN254_c12_x) + $ => B :MLOAD(mulFp12BN254_c12_y) + A :MSTORE(finalExpBN254_T24_12_x) + B :MSTORE(finalExpBN254_T24_12_y) + $ => A :MLOAD(mulFp12BN254_c13_x) + $ => B :MLOAD(mulFp12BN254_c13_y) + A :MSTORE(finalExpBN254_T24_13_x) + B :MSTORE(finalExpBN254_T24_13_y) + $ => A :MLOAD(mulFp12BN254_c21_x) + $ => B :MLOAD(mulFp12BN254_c21_y) + A :MSTORE(finalExpBN254_T24_21_x) + B :MSTORE(finalExpBN254_T24_21_y) + $ => A :MLOAD(mulFp12BN254_c22_x) + $ => B :MLOAD(mulFp12BN254_c22_y) + A :MSTORE(finalExpBN254_T24_22_x) + B :MSTORE(finalExpBN254_T24_22_y) + $ => A :MLOAD(mulFp12BN254_c23_x) + $ => B :MLOAD(mulFp12BN254_c23_y) + A :MSTORE(finalExpBN254_T24_23_x) + B :MSTORE(finalExpBN254_T24_23_y) + + + ; 10.7] T13 = T23·y2 + $ => A :MLOAD(finalExpBN254_T23_11_x) + $ => B :MLOAD(finalExpBN254_T23_11_y) + A :MSTORE(mulFp12BN254_a11_x) + B :MSTORE(mulFp12BN254_a11_y) + $ => A :MLOAD(finalExpBN254_T23_12_x) + $ => B :MLOAD(finalExpBN254_T23_12_y) + A :MSTORE(mulFp12BN254_a12_x) + B :MSTORE(mulFp12BN254_a12_y) + $ => A :MLOAD(finalExpBN254_T23_13_x) + $ => B :MLOAD(finalExpBN254_T23_13_y) + A :MSTORE(mulFp12BN254_a13_x) + B :MSTORE(mulFp12BN254_a13_y) + $ => A :MLOAD(finalExpBN254_T23_21_x) + $ => B :MLOAD(finalExpBN254_T23_21_y) + A :MSTORE(mulFp12BN254_a21_x) + B :MSTORE(mulFp12BN254_a21_y) + $ => A :MLOAD(finalExpBN254_T23_22_x) + $ => B :MLOAD(finalExpBN254_T23_22_y) + A :MSTORE(mulFp12BN254_a22_x) + B :MSTORE(mulFp12BN254_a22_y) + $ => A :MLOAD(finalExpBN254_T23_23_x) + $ => B :MLOAD(finalExpBN254_T23_23_y) + A :MSTORE(mulFp12BN254_a23_x) + B :MSTORE(mulFp12BN254_a23_y) + $ => A :MLOAD(finalExpBN254_y2_11_x) + $ => B :MLOAD(finalExpBN254_y2_11_y) + A :MSTORE(mulFp12BN254_b11_x) + B :MSTORE(mulFp12BN254_b11_y) + $ => A :MLOAD(finalExpBN254_y2_12_x) + $ => B :MLOAD(finalExpBN254_y2_12_y) + A :MSTORE(mulFp12BN254_b12_x) + B :MSTORE(mulFp12BN254_b12_y) + $ => A :MLOAD(finalExpBN254_y2_13_x) + $ => B :MLOAD(finalExpBN254_y2_13_y) + A :MSTORE(mulFp12BN254_b13_x) + B :MSTORE(mulFp12BN254_b13_y) + $ => A :MLOAD(finalExpBN254_y2_21_x) + $ => B :MLOAD(finalExpBN254_y2_21_y) + A :MSTORE(mulFp12BN254_b21_x) + B :MSTORE(mulFp12BN254_b21_y) + $ => A :MLOAD(finalExpBN254_y2_22_x) + $ => B :MLOAD(finalExpBN254_y2_22_y) + A :MSTORE(mulFp12BN254_b22_x) + B :MSTORE(mulFp12BN254_b22_y) + $ => A :MLOAD(finalExpBN254_y2_23_x) + $ => B :MLOAD(finalExpBN254_y2_23_y) + A :MSTORE(mulFp12BN254_b23_x) + B :MSTORE(mulFp12BN254_b23_y), CALL(mulFp12BN254) + + + ; 10.8] T14 = T13²·T24 + $ => A :MLOAD(mulFp12BN254_c11_x) + $ => B :MLOAD(mulFp12BN254_c11_y) + A :MSTORE(squareCycloFp12BN254_a11_x) + B :MSTORE(squareCycloFp12BN254_a11_y) + $ => A :MLOAD(mulFp12BN254_c12_x) + $ => B :MLOAD(mulFp12BN254_c12_y) + A :MSTORE(squareCycloFp12BN254_a12_x) + B :MSTORE(squareCycloFp12BN254_a12_y) + $ => A :MLOAD(mulFp12BN254_c13_x) + $ => B :MLOAD(mulFp12BN254_c13_y) + A :MSTORE(squareCycloFp12BN254_a13_x) + B :MSTORE(squareCycloFp12BN254_a13_y) + $ => A :MLOAD(mulFp12BN254_c21_x) + $ => B :MLOAD(mulFp12BN254_c21_y) + A :MSTORE(squareCycloFp12BN254_a21_x) + B :MSTORE(squareCycloFp12BN254_a21_y) + $ => A :MLOAD(mulFp12BN254_c22_x) + $ => B :MLOAD(mulFp12BN254_c22_y) + A :MSTORE(squareCycloFp12BN254_a22_x) + B :MSTORE(squareCycloFp12BN254_a22_y) + $ => A :MLOAD(mulFp12BN254_c23_x) + $ => B :MLOAD(mulFp12BN254_c23_y) + A :MSTORE(squareCycloFp12BN254_a23_x) + B :MSTORE(squareCycloFp12BN254_a23_y), CALL(squareCycloFp12BN254) + + $ => A :MLOAD(squareCycloFp12BN254_c11_x) + $ => B :MLOAD(squareCycloFp12BN254_c11_y) + A :MSTORE(mulFp12BN254_a11_x) + B :MSTORE(mulFp12BN254_a11_y) + $ => A :MLOAD(squareCycloFp12BN254_c12_x) + $ => B :MLOAD(squareCycloFp12BN254_c12_y) + A :MSTORE(mulFp12BN254_a12_x) + B :MSTORE(mulFp12BN254_a12_y) + $ => A :MLOAD(squareCycloFp12BN254_c13_x) + $ => B :MLOAD(squareCycloFp12BN254_c13_y) + A :MSTORE(mulFp12BN254_a13_x) + B :MSTORE(mulFp12BN254_a13_y) + $ => A :MLOAD(squareCycloFp12BN254_c21_x) + $ => B :MLOAD(squareCycloFp12BN254_c21_y) + A :MSTORE(mulFp12BN254_a21_x) + B :MSTORE(mulFp12BN254_a21_y) + $ => A :MLOAD(squareCycloFp12BN254_c22_x) + $ => B :MLOAD(squareCycloFp12BN254_c22_y) + A :MSTORE(mulFp12BN254_a22_x) + B :MSTORE(mulFp12BN254_a22_y) + $ => A :MLOAD(squareCycloFp12BN254_c23_x) + $ => B :MLOAD(squareCycloFp12BN254_c23_y) + A :MSTORE(mulFp12BN254_a23_x) + B :MSTORE(mulFp12BN254_a23_y) + $ => A :MLOAD(finalExpBN254_T24_11_x) + $ => B :MLOAD(finalExpBN254_T24_11_y) + A :MSTORE(mulFp12BN254_b11_x) + B :MSTORE(mulFp12BN254_b11_y) + $ => A :MLOAD(finalExpBN254_T24_12_x) + $ => B :MLOAD(finalExpBN254_T24_12_y) + A :MSTORE(mulFp12BN254_b12_x) + B :MSTORE(mulFp12BN254_b12_y) + $ => A :MLOAD(finalExpBN254_T24_13_x) + $ => B :MLOAD(finalExpBN254_T24_13_y) + A :MSTORE(mulFp12BN254_b13_x) + B :MSTORE(mulFp12BN254_b13_y) + $ => A :MLOAD(finalExpBN254_T24_21_x) + $ => B :MLOAD(finalExpBN254_T24_21_y) + A :MSTORE(mulFp12BN254_b21_x) + B :MSTORE(mulFp12BN254_b21_y) + $ => A :MLOAD(finalExpBN254_T24_22_x) + $ => B :MLOAD(finalExpBN254_T24_22_y) + A :MSTORE(mulFp12BN254_b22_x) + B :MSTORE(mulFp12BN254_b22_y) + $ => A :MLOAD(finalExpBN254_T24_23_x) + $ => B :MLOAD(finalExpBN254_T24_23_y) + A :MSTORE(mulFp12BN254_b23_x) + B :MSTORE(mulFp12BN254_b23_y), CALL(mulFp12BN254) + ; =========================================== + + ; Assing the result. + $ => A :MLOAD(mulFp12BN254_c11_x) + $ => B :MLOAD(mulFp12BN254_c11_y) + A :MSTORE(finalExpBN254_f11_x) + B :MSTORE(finalExpBN254_f11_y) + $ => A :MLOAD(mulFp12BN254_c12_x) + $ => B :MLOAD(mulFp12BN254_c12_y) + A :MSTORE(finalExpBN254_f12_x) + B :MSTORE(finalExpBN254_f12_y) + $ => A :MLOAD(mulFp12BN254_c13_x) + $ => B :MLOAD(mulFp12BN254_c13_y) + A :MSTORE(finalExpBN254_f13_x) + B :MSTORE(finalExpBN254_f13_y) + $ => A :MLOAD(mulFp12BN254_c21_x) + $ => B :MLOAD(mulFp12BN254_c21_y) + A :MSTORE(finalExpBN254_f21_x) + B :MSTORE(finalExpBN254_f21_y) + $ => A :MLOAD(mulFp12BN254_c22_x) + $ => B :MLOAD(mulFp12BN254_c22_y) + A :MSTORE(finalExpBN254_f22_x) + B :MSTORE(finalExpBN254_f22_y) + $ => A :MLOAD(mulFp12BN254_c23_x) + $ => B :MLOAD(mulFp12BN254_c23_y) + A :MSTORE(finalExpBN254_f23_x) + B :MSTORE(finalExpBN254_f23_y) + +finalExpBN254_end: + $ => RR :MLOAD(finalExpBN254_RR) + :RETURN \ No newline at end of file diff --git a/main/pairings/halfPairingBN254.zkasm b/main/pairings/halfPairingBN254.zkasm new file mode 100644 index 00000000..98250839 --- /dev/null +++ b/main/pairings/halfPairingBN254.zkasm @@ -0,0 +1,428 @@ +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; +;; halfPairingBN254: +;; input: P ∈ G1 and Q ∈ G2 +;; output: It returns 1 if either P = 0 or Q = 0 and f_{r,Q}(P) ∈ Fp12 otherwise +;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +VAR GLOBAL halfPairingBN254_P_x +VAR GLOBAL halfPairingBN254_P_y +VAR GLOBAL halfPairingBN254_Q_x1 +VAR GLOBAL halfPairingBN254_Q_x2 +VAR GLOBAL halfPairingBN254_Q_y1 +VAR GLOBAL halfPairingBN254_Q_y2 + +VAR GLOBAL halfPairingBN254_f11_x +VAR GLOBAL halfPairingBN254_f11_y +VAR GLOBAL halfPairingBN254_f12_x +VAR GLOBAL halfPairingBN254_f12_y +VAR GLOBAL halfPairingBN254_f13_x +VAR GLOBAL halfPairingBN254_f13_y +VAR GLOBAL halfPairingBN254_f21_x +VAR GLOBAL halfPairingBN254_f21_y +VAR GLOBAL halfPairingBN254_f22_x +VAR GLOBAL halfPairingBN254_f22_y +VAR GLOBAL halfPairingBN254_f23_x +VAR GLOBAL halfPairingBN254_f23_y + +VAR GLOBAL halfPairingBN254_RR + +VAR GLOBAL halfPairingBN254_P_x3 +VAR GLOBAL halfPairingBN254_Q_RHS_x +VAR GLOBAL halfPairingBN254_Q_RHS_y +VAR GLOBAL halfPairingBN254_psi_x1 +VAR GLOBAL halfPairingBN254_psi_x2 +VAR GLOBAL halfPairingBN254_psi_y1 +VAR GLOBAL halfPairingBN254_psi_y2 + +; ERROR CODES (B) +; 0 - no error +; 1 - P_x is too big +; 2 - P_y is too big +; 3 - Q_x1 is too big +; 4 - Q_x2 is too big +; 5 - Q_y1 is too big +; 6 - Q_y2 is too big +; 7 - P is not in G1 +; 8 - Q is not in G2 + +halfPairingBN254: + RR :MSTORE(halfPairingBN254_RR) + + %BN254_P_MINUS_ONE => A + $ => B :MLOAD(halfPairingBN254_P_x) + $ :LT, JMPC(halfPairingBN254_Px_too_big) + $ => B :MLOAD(halfPairingBN254_P_y) + $ :LT, JMPC(halfPairingBN254_Py_too_big) + $ => B :MLOAD(halfPairingBN254_Q_x1) + $ :LT, JMPC(halfPairingBN254_Qx1_too_big) + $ => B :MLOAD(halfPairingBN254_Q_x2) + $ :LT, JMPC(halfPairingBN254_Qx2_too_big) + $ => B :MLOAD(halfPairingBN254_Q_y1) + $ :LT, JMPC(halfPairingBN254_Qy1_too_big) + $ => B :MLOAD(halfPairingBN254_Q_y2) + $ :LT, JMPC(halfPairingBN254_Qy2_too_big) + + ; Is P = O? + 0n => B + $ => A :MLOAD(halfPairingBN254_P_x) + $ :EQ, JMPNC(__halfPairingBN254_P_continue) + $ => A :MLOAD(halfPairingBN254_P_y) + $ :EQ, JMPC(halfPairingBN254_P_is_zero) + __halfPairingBN254_P_continue: + + ; Is Q = O? + $ => A :MLOAD(halfPairingBN254_Q_x1) + $ :EQ, JMPNC(__halfPairingBN254_Q_continue1) + $ => A :MLOAD(halfPairingBN254_Q_x2) + $ :EQ, JMPNC(__halfPairingBN254_Q_continue1) + $ => A :MLOAD(halfPairingBN254_Q_y1) + $ :EQ, JMPNC(__halfPairingBN254_Q_continue1) + $ => A :MLOAD(halfPairingBN254_Q_y2) + $ :EQ, JMPC(halfPairingBN254_Q_is_zero) + __halfPairingBN254_Q_continue1: + + :JMP(halfPairingBN254_P_subgroup_check) + +halfPairingBN254_P_is_zero: + ; Is Q = O? + $ => A :MLOAD(halfPairingBN254_Q_x1) + $ :EQ, JMPNC(__halfPairingBN254_Q_continue2) + $ => A :MLOAD(halfPairingBN254_Q_x2) + $ :EQ, JMPNC(__halfPairingBN254_Q_continue2) + $ => A :MLOAD(halfPairingBN254_Q_y1) + $ :EQ, JMPNC(__halfPairingBN254_Q_continue2) + $ => A :MLOAD(halfPairingBN254_Q_y2) + $ :EQ, JMPC(halfPairingBN254_P_and_Q_are_zero) + __halfPairingBN254_Q_continue2: + + ; Check that Q is in G2 + ; Q in G2 iff Q in E' and psi(Q) == [6x²]Q as proven in Proposition 3 of 2022/352 + + ; 1] Check if Q is in E'(Fp2) + ; Q in E' iff (Q.y1 + Q.y2·u)² == (Q.x1 + Q.x2·u)³ + 3/(9+u) + ; 1.1] Compute LHS and RHS + $ => A :MLOAD(halfPairingBN254_Q_x1) + $ => B :MLOAD(halfPairingBN254_Q_x2), CALL(squareFp2BN254) + ; E + C·u = (Q.x1 + Q.x2·u)² + + E => A + C => B + $ => C :MLOAD(halfPairingBN254_Q_x1) + $ => D :MLOAD(halfPairingBN254_Q_x2), CALL(mulFp2BN254) + ; E + C·u = (Q.x1 + Q.x2·u)³ + + E => A + C => B + %BN254_ETWISTED_B_X => C + %BN254_ETWISTED_B_Y => D :CALL(addFp2BN254) + ; E + C·u = (Q.x1 + Q.x2·u)³ + 3/(9+u) + E :MSTORE(halfPairingBN254_Q_RHS_x) + C :MSTORE(halfPairingBN254_Q_RHS_y) + + $ => A :MLOAD(halfPairingBN254_Q_y1) + $ => B :MLOAD(halfPairingBN254_Q_y2), CALL(squareFp2BN254) + ; E + C·u = (Q.y1 + Q.y2·u)² + + ; 1.2] Check if LHS == RHS + E => A + $ => B :MLOAD(halfPairingBN254_Q_RHS_x) + $ :EQ, JMPNC(halfPairingBN254_Q_is_not_in_G2) + + C => A + $ => B :MLOAD(halfPairingBN254_Q_RHS_y) + $ :EQ, JMPNC(halfPairingBN254_Q_is_not_in_G2) + + ; 2] Check if psi(Q) == [6x²]Q + ; 2.1] Compute psi(Q) + %BN254_P => A + $ => B :MLOAD(halfPairingBN254_Q_x2) + $ => D :SUB ; D = -Qx2 + %FROBENIUS_GAMMA121 => A + %FROBENIUS_GAMMA122 => B + $ => C :MLOAD(halfPairingBN254_Q_x1), CALL(mulFp2BN254) + E :MSTORE(halfPairingBN254_psi_x1) + C :MSTORE(halfPairingBN254_psi_x2) + + %BN254_P => A + $ => B :MLOAD(halfPairingBN254_Q_y2) + $ => D :SUB ; D = -Qy2 + %FROBENIUS_GAMMA131 => A + %FROBENIUS_GAMMA132 => B + $ => C :MLOAD(halfPairingBN254_Q_y1), CALL(mulFp2BN254) + E :MSTORE(halfPairingBN254_psi_y1) + C :MSTORE(halfPairingBN254_psi_y2) + + ; 2.2] Compute [6x²]Q + $ => A :MLOAD(halfPairingBN254_Q_x1) + $ => B :MLOAD(halfPairingBN254_Q_x2) + $ => C :MLOAD(halfPairingBN254_Q_y1) + $ => D :MLOAD(halfPairingBN254_Q_y2) + A :MSTORE(escalarMulBN254_P_x1) + B :MSTORE(escalarMulBN254_P_x2) + C :MSTORE(escalarMulBN254_P_y1) + D :MSTORE(escalarMulBN254_P_y2) + %BN254_SIX_TIMES_X_SQ :MSTORE(escalarMulBN254_k), CALL(escalarMulBN254) + + + ; 2.3] Check if psi(Q) == [6x²]Q + $ => A :MLOAD(halfPairingBN254_psi_x1) + $ => B :MLOAD(escalarMulBN254_Q_x1) + $ :EQ, JMPNC(halfPairingBN254_Q_is_not_in_G2) + + $ => A :MLOAD(halfPairingBN254_psi_x2) + $ => B :MLOAD(escalarMulBN254_Q_x2) + $ :EQ, JMPNC(halfPairingBN254_Q_is_not_in_G2) + + $ => A :MLOAD(halfPairingBN254_psi_y1) + $ => B :MLOAD(escalarMulBN254_Q_y1) + $ :EQ, JMPNC(halfPairingBN254_Q_is_not_in_G2) + + $ => A :MLOAD(halfPairingBN254_psi_y2) + $ => B :MLOAD(escalarMulBN254_Q_y2) + $ :EQ, JMPNC(halfPairingBN254_Q_is_not_in_G2) + + ; e(O,Q) = 1 + 1n :MSTORE(halfPairingBN254_f11_x) + 0n :MSTORE(halfPairingBN254_f11_y) + 0n :MSTORE(halfPairingBN254_f12_x) + 0n :MSTORE(halfPairingBN254_f12_y) + 0n :MSTORE(halfPairingBN254_f13_x) + 0n :MSTORE(halfPairingBN254_f13_y) + 0n :MSTORE(halfPairingBN254_f21_x) + 0n :MSTORE(halfPairingBN254_f21_y) + 0n :MSTORE(halfPairingBN254_f22_x) + 0n :MSTORE(halfPairingBN254_f22_y) + 0n :MSTORE(halfPairingBN254_f23_x) + 0n :MSTORE(halfPairingBN254_f23_y) + + 0 => B :JMP(halfPairingBN254_end) + +halfPairingBN254_Q_is_zero: + ; Check that P is in G1 + ; P in G1 iff (Py)² == (Px)³ + 3 (mod p) + ; 1] Compute LHS and RHS + $ => A,B :MLOAD(halfPairingBN254_P_x), CALL(mulFpBN254); C = (Px)² + C => A ; A = (Px)² + $ => B :MLOAD(halfPairingBN254_P_x), CALL(mulFpBN254); C = (Px)³ + + %BN254_E_B => A :CALL(addFpBN254) ; C = (Px)³ + 3 + C :MSTORE(halfPairingBN254_P_x3) ; halfPairingBN254_P_x3 = (Px)³ + 3 + + $ => A,B :MLOAD(halfPairingBN254_P_y), CALL(mulFpBN254); C = (Py)² + + ; 2] Check if LHS == RHS + C => A + $ => B :MLOAD(halfPairingBN254_P_x3) + $ :EQ, JMPNC(halfPairingBN254_P_is_not_in_G1) + + ; e(P,O) = 1 + 1n :MSTORE(halfPairingBN254_f11_x) + 0n :MSTORE(halfPairingBN254_f11_y) + 0n :MSTORE(halfPairingBN254_f12_x) + 0n :MSTORE(halfPairingBN254_f12_y) + 0n :MSTORE(halfPairingBN254_f13_x) + 0n :MSTORE(halfPairingBN254_f13_y) + 0n :MSTORE(halfPairingBN254_f21_x) + 0n :MSTORE(halfPairingBN254_f21_y) + 0n :MSTORE(halfPairingBN254_f22_x) + 0n :MSTORE(halfPairingBN254_f22_y) + 0n :MSTORE(halfPairingBN254_f23_x) + 0n :MSTORE(halfPairingBN254_f23_y) + + 0 => B :JMP(halfPairingBN254_end) + +halfPairingBN254_P_and_Q_are_zero: + ; e(O,O) = 1 + 1n :MSTORE(halfPairingBN254_f11_x) + 0n :MSTORE(halfPairingBN254_f11_y) + 0n :MSTORE(halfPairingBN254_f12_x) + 0n :MSTORE(halfPairingBN254_f12_y) + 0n :MSTORE(halfPairingBN254_f13_x) + 0n :MSTORE(halfPairingBN254_f13_y) + 0n :MSTORE(halfPairingBN254_f21_x) + 0n :MSTORE(halfPairingBN254_f21_y) + 0n :MSTORE(halfPairingBN254_f22_x) + 0n :MSTORE(halfPairingBN254_f22_y) + 0n :MSTORE(halfPairingBN254_f23_x) + 0n :MSTORE(halfPairingBN254_f23_y) + + 0 => B :JMP(halfPairingBN254_end) + +halfPairingBN254_P_subgroup_check: + ; Check that P is in G1 + ; P in G1 iff (Py)² == (Px)³ + 3 (mod p) + ; 1] Compute LHS and RHS + $ => A,B :MLOAD(halfPairingBN254_P_x), CALL(mulFpBN254); C = (Px)² + C => A ; A = (Px)² + $ => B :MLOAD(halfPairingBN254_P_x), CALL(mulFpBN254); C = (Px)³ + + %BN254_E_B => A :CALL(addFpBN254) ; C = (Px)³ + 3 + C :MSTORE(halfPairingBN254_P_x3) ; halfPairingBN254_P_x3 = (Px)³ + 3 + + $ => A,B :MLOAD(halfPairingBN254_P_y), CALL(mulFpBN254); C = (Py)² + + ; 2] Check if LHS == RHS + C => A + $ => B :MLOAD(halfPairingBN254_P_x3) + $ :EQ, JMPNC(halfPairingBN254_P_is_not_in_G1) + +halfPairingBN254_Q_subgroup_check: + ; Check that Q is in G2 + ; Q in G2 iff Q in E' and psi(Q) == [6x²]Q as proven in Proposition 3 of 2022/352 + + ; 1] Check if Q is in E'(Fp2) + ; Q in E' iff (Q.y1 + Q.y2·u)² == (Q.x1 + Q.x2·u)³ + 3/(9+u) + ; 1.1] Compute LHS and RHS + $ => A :MLOAD(halfPairingBN254_Q_x1) + $ => B :MLOAD(halfPairingBN254_Q_x2), CALL(squareFp2BN254) + ; E + C·u = (Q.x1 + Q.x2·u)² + + E => A + C => B + $ => C :MLOAD(halfPairingBN254_Q_x1) + $ => D :MLOAD(halfPairingBN254_Q_x2), CALL(mulFp2BN254) + ; E + C·u = (Q.x1 + Q.x2·u)³ + + E => A + C => B + %BN254_ETWISTED_B_X => C + %BN254_ETWISTED_B_Y => D :CALL(addFp2BN254) + ; E + C·u = (Q.x1 + Q.x2·u)³ + 3/(9+u) + E :MSTORE(halfPairingBN254_Q_RHS_x) + C :MSTORE(halfPairingBN254_Q_RHS_y) + + $ => A :MLOAD(halfPairingBN254_Q_y1) + $ => B :MLOAD(halfPairingBN254_Q_y2), CALL(squareFp2BN254) + ; E + C·u = (Q.y1 + Q.y2·u)² + + ; 1.2] Check if LHS == RHS + E => A + $ => B :MLOAD(halfPairingBN254_Q_RHS_x) + $ :EQ, JMPNC(halfPairingBN254_Q_is_not_in_G2) + + C => A + $ => B :MLOAD(halfPairingBN254_Q_RHS_y) + $ :EQ, JMPNC(halfPairingBN254_Q_is_not_in_G2) + + ; 2] Check if psi(Q) == [6x²]Q + ; 2.1] Compute psi(Q) + %BN254_P => A + $ => B :MLOAD(halfPairingBN254_Q_x2) + $ => D :SUB ; D = -Qx2 + %FROBENIUS_GAMMA121 => A + %FROBENIUS_GAMMA122 => B + $ => C :MLOAD(halfPairingBN254_Q_x1), CALL(mulFp2BN254) + E :MSTORE(halfPairingBN254_psi_x1) + C :MSTORE(halfPairingBN254_psi_x2) + + %BN254_P => A + $ => B :MLOAD(halfPairingBN254_Q_y2) + $ => D :SUB ; D = -Qx2 + %FROBENIUS_GAMMA131 => A + %FROBENIUS_GAMMA132 => B + $ => C :MLOAD(halfPairingBN254_Q_y1), CALL(mulFp2BN254) + E :MSTORE(halfPairingBN254_psi_y1) + C :MSTORE(halfPairingBN254_psi_y2) + + ; 2.2] Compute [6x²]Q + $ => A :MLOAD(halfPairingBN254_Q_x1) + $ => B :MLOAD(halfPairingBN254_Q_x2) + $ => C :MLOAD(halfPairingBN254_Q_y1) + $ => D :MLOAD(halfPairingBN254_Q_y2) + A :MSTORE(escalarMulBN254_P_x1) + B :MSTORE(escalarMulBN254_P_x2) + C :MSTORE(escalarMulBN254_P_y1) + D :MSTORE(escalarMulBN254_P_y2) + %BN254_SIX_TIMES_X_SQ :MSTORE(escalarMulBN254_k), CALL(escalarMulBN254) + + + ; 2.3] Check if psi(Q) == [6x²]Q + $ => A :MLOAD(halfPairingBN254_psi_x1) + $ => B :MLOAD(escalarMulBN254_Q_x1) + $ :EQ, JMPNC(halfPairingBN254_Q_is_not_in_G2) + + $ => A :MLOAD(halfPairingBN254_psi_x2) + $ => B :MLOAD(escalarMulBN254_Q_x2) + $ :EQ, JMPNC(halfPairingBN254_Q_is_not_in_G2) + + $ => A :MLOAD(halfPairingBN254_psi_y1) + $ => B :MLOAD(escalarMulBN254_Q_y1) + $ :EQ, JMPNC(halfPairingBN254_Q_is_not_in_G2) + + $ => A :MLOAD(halfPairingBN254_psi_y2) + $ => B :MLOAD(escalarMulBN254_Q_y2) + $ :EQ, JMPNC(halfPairingBN254_Q_is_not_in_G2) + +halfPairingBN254_Miller_loop: + $ => A :MLOAD(halfPairingBN254_P_x) + $ => B :MLOAD(halfPairingBN254_P_y) + A :MSTORE(millerLoopBN254_P_x) + B :MSTORE(millerLoopBN254_P_y) + $ => A :MLOAD(halfPairingBN254_Q_x1) + $ => B :MLOAD(halfPairingBN254_Q_x2) + $ => C :MLOAD(halfPairingBN254_Q_y1) + $ => D :MLOAD(halfPairingBN254_Q_y2) + A :MSTORE(millerLoopBN254_Q_x1) + B :MSTORE(millerLoopBN254_Q_x2) + C :MSTORE(millerLoopBN254_Q_y1) + D :MSTORE(millerLoopBN254_Q_y2), CALL(millerLoopBN254) + $ => A :MLOAD(millerLoopBN254_f11_x) + $ => B :MLOAD(millerLoopBN254_f11_y) + A :MSTORE(halfPairingBN254_f11_x) + B :MSTORE(halfPairingBN254_f11_y) + $ => A :MLOAD(millerLoopBN254_f12_x) + $ => B :MLOAD(millerLoopBN254_f12_y) + A :MSTORE(halfPairingBN254_f12_x) + B :MSTORE(halfPairingBN254_f12_y) + $ => A :MLOAD(millerLoopBN254_f13_x) + $ => B :MLOAD(millerLoopBN254_f13_y) + A :MSTORE(halfPairingBN254_f13_x) + B :MSTORE(halfPairingBN254_f13_y) + $ => A :MLOAD(millerLoopBN254_f21_x) + $ => B :MLOAD(millerLoopBN254_f21_y) + A :MSTORE(halfPairingBN254_f21_x) + B :MSTORE(halfPairingBN254_f21_y) + $ => A :MLOAD(millerLoopBN254_f22_x) + $ => B :MLOAD(millerLoopBN254_f22_y) + A :MSTORE(halfPairingBN254_f22_x) + B :MSTORE(halfPairingBN254_f22_y) + $ => A :MLOAD(millerLoopBN254_f23_x) + $ => B :MLOAD(millerLoopBN254_f23_y) + A :MSTORE(halfPairingBN254_f23_x) + B :MSTORE(halfPairingBN254_f23_y) + + 0 => B :JMP(halfPairingBN254_end) + +; ERRORS +halfPairingBN254_Px_too_big: + 1 => B :JMP(halfPairingBN254_error) + +halfPairingBN254_Py_too_big: + 2 => B :JMP(halfPairingBN254_error) + +halfPairingBN254_Qx1_too_big: + 3 => B :JMP(halfPairingBN254_error) + +halfPairingBN254_Qx2_too_big: + 4 => B :JMP(halfPairingBN254_error) + +halfPairingBN254_Qy1_too_big: + 5 => B :JMP(halfPairingBN254_error) + +halfPairingBN254_Qy2_too_big: + 6 => B :JMP(halfPairingBN254_error) + +halfPairingBN254_P_is_not_in_G1: + 7 => B :JMP(halfPairingBN254_error) + +halfPairingBN254_Q_is_not_in_G2: + 8 => B :JMP(halfPairingBN254_error) + +halfPairingBN254_error: + 0 => A + +halfPairingBN254_end: + $ => RR :MLOAD(halfPairingBN254_RR) + :RETURN \ No newline at end of file diff --git a/main/pairings/loopLengthBN254.zkasm b/main/pairings/loopLengthBN254.zkasm new file mode 100644 index 00000000..38896eb9 --- /dev/null +++ b/main/pairings/loopLengthBN254.zkasm @@ -0,0 +1,75 @@ +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; +;; loopLengthBN254: +;; output: A digit of the (little-endian) pseudobinary representation of the loop length +;; of the optimal ate pairing over the BN254: +;; 0001010-1001-100100110-10010-1000011100-100100000-1001100-1000110-1001011 +;; +;; NOTE: The loop length is precisely 6·%BN254_X + 2, that is 29793968203157093288. +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +loopLengthBN254: + 0 => B :RETURN + 0 => B :RETURN + 0 => B :RETURN + 1 => B :RETURN + 0 => B :RETURN + 1 => B :RETURN + 0 => B :RETURN + -1 => B :RETURN + 0 => B :RETURN + 0 => B :RETURN + 1 => B :RETURN + -1 => B :RETURN + 0 => B :RETURN + 0 => B :RETURN + 1 => B :RETURN + 0 => B :RETURN + 0 => B :RETURN + 1 => B :RETURN + 1 => B :RETURN + 0 => B :RETURN + -1 => B :RETURN + 0 => B :RETURN + 0 => B :RETURN + 1 => B :RETURN + 0 => B :RETURN + -1 => B :RETURN + 0 => B :RETURN + 0 => B :RETURN + 0 => B :RETURN + 0 => B :RETURN + 1 => B :RETURN + 1 => B :RETURN + 1 => B :RETURN + 0 => B :RETURN + 0 => B :RETURN + -1 => B :RETURN + 0 => B :RETURN + 0 => B :RETURN + 1 => B :RETURN + 0 => B :RETURN + 0 => B :RETURN + 0 => B :RETURN + 0 => B :RETURN + 0 => B :RETURN + -1 => B :RETURN + 0 => B :RETURN + 0 => B :RETURN + 1 => B :RETURN + 1 => B :RETURN + 0 => B :RETURN + 0 => B :RETURN + -1 => B :RETURN + 0 => B :RETURN + 0 => B :RETURN + 0 => B :RETURN + 1 => B :RETURN + 1 => B :RETURN + 0 => B :RETURN + -1 => B :RETURN + 0 => B :RETURN + 0 => B :RETURN + 1 => B :RETURN + 0 => B :RETURN + 1 => B :RETURN \ No newline at end of file diff --git a/main/pairings/millerLoopBN254.zkasm b/main/pairings/millerLoopBN254.zkasm new file mode 100644 index 00000000..2e339258 --- /dev/null +++ b/main/pairings/millerLoopBN254.zkasm @@ -0,0 +1,741 @@ +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; POST: The result is in the range [0,BN254_P) because if falls back to FP12 arithmetic +;; +;; millerLoopBN254: +;; input: P ∈ G1 and Q ∈ G2 +;; output: f_{r,Q}(P) ∈ Fp12 +;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +VAR GLOBAL millerLoopBN254_P_x +VAR GLOBAL millerLoopBN254_P_y +VAR GLOBAL millerLoopBN254_Q_x1 +VAR GLOBAL millerLoopBN254_Q_x2 +VAR GLOBAL millerLoopBN254_Q_y1 +VAR GLOBAL millerLoopBN254_Q_y2 + +VAR GLOBAL millerLoopBN254_Frobenius1_Q_x1 +VAR GLOBAL millerLoopBN254_Frobenius1_Q_x2 +VAR GLOBAL millerLoopBN254_Frobenius1_Q_y1 +VAR GLOBAL millerLoopBN254_Frobenius1_Q_y2 +VAR GLOBAL millerLoopBN254_nFrobenius2_Q_x1 +VAR GLOBAL millerLoopBN254_nFrobenius2_Q_x2 + +VAR GLOBAL millerLoopBN254_R_x1 +VAR GLOBAL millerLoopBN254_R_x2 +VAR GLOBAL millerLoopBN254_R_y1 +VAR GLOBAL millerLoopBN254_R_y2 +VAR GLOBAL millerLoopBN254_f11_x +VAR GLOBAL millerLoopBN254_f11_y +VAR GLOBAL millerLoopBN254_f12_x +VAR GLOBAL millerLoopBN254_f12_y +VAR GLOBAL millerLoopBN254_f13_x +VAR GLOBAL millerLoopBN254_f13_y +VAR GLOBAL millerLoopBN254_f21_x +VAR GLOBAL millerLoopBN254_f21_y +VAR GLOBAL millerLoopBN254_f22_x +VAR GLOBAL millerLoopBN254_f22_y +VAR GLOBAL millerLoopBN254_f23_x +VAR GLOBAL millerLoopBN254_f23_y +VAR GLOBAL millerLoopBN254_fsquare11_x +VAR GLOBAL millerLoopBN254_fsquare11_y +VAR GLOBAL millerLoopBN254_fsquare12_x +VAR GLOBAL millerLoopBN254_fsquare12_y +VAR GLOBAL millerLoopBN254_fsquare13_x +VAR GLOBAL millerLoopBN254_fsquare13_y +VAR GLOBAL millerLoopBN254_fsquare21_x +VAR GLOBAL millerLoopBN254_fsquare21_y +VAR GLOBAL millerLoopBN254_fsquare22_x +VAR GLOBAL millerLoopBN254_fsquare22_y +VAR GLOBAL millerLoopBN254_fsquare23_x +VAR GLOBAL millerLoopBN254_fsquare23_y + +VAR GLOBAL millerLoopBN254_RR + +millerLoopBN254: + RR :MSTORE(millerLoopBN254_RR) + + 65 => RCX + + ; Initiliaze Miller loop with R = Q and f = 1 + $ => A :MLOAD(millerLoopBN254_Q_x1) + $ => B :MLOAD(millerLoopBN254_Q_x2) + $ => C :MLOAD(millerLoopBN254_Q_y1) + $ => D :MLOAD(millerLoopBN254_Q_y2) + A :MSTORE(millerLoopBN254_R_x1) + B :MSTORE(millerLoopBN254_R_x2) + C :MSTORE(millerLoopBN254_R_y1) + D :MSTORE(millerLoopBN254_R_y2) + 1n :MSTORE(millerLoopBN254_f11_x) + 0n :MSTORE(millerLoopBN254_f11_y) + 0n :MSTORE(millerLoopBN254_f12_x) + 0n :MSTORE(millerLoopBN254_f12_y) + 0n :MSTORE(millerLoopBN254_f13_x) + 0n :MSTORE(millerLoopBN254_f13_y) + 0n :MSTORE(millerLoopBN254_f21_x) + 0n :MSTORE(millerLoopBN254_f21_y) + 0n :MSTORE(millerLoopBN254_f22_x) + 0n :MSTORE(millerLoopBN254_f22_y) + 0n :MSTORE(millerLoopBN254_f23_x) + 0n :MSTORE(millerLoopBN254_f23_y) + +millerLoopBN254_loop: + RCX - 1 => RCX :JMPZ(millerLoopBN254_last_two_lines) + + ; 1] f = f² · line_{twist(R),twist(R)}(P) + + ; f² + $ => A :MLOAD(millerLoopBN254_f11_x) + $ => B :MLOAD(millerLoopBN254_f11_y) + A :MSTORE(squareFp12BN254_a11_x) + B :MSTORE(squareFp12BN254_a11_y) + $ => A :MLOAD(millerLoopBN254_f12_x) + $ => B :MLOAD(millerLoopBN254_f12_y) + A :MSTORE(squareFp12BN254_a12_x) + B :MSTORE(squareFp12BN254_a12_y) + $ => A :MLOAD(millerLoopBN254_f13_x) + $ => B :MLOAD(millerLoopBN254_f13_y) + A :MSTORE(squareFp12BN254_a13_x) + B :MSTORE(squareFp12BN254_a13_y) + $ => A :MLOAD(millerLoopBN254_f21_x) + $ => B :MLOAD(millerLoopBN254_f21_y) + A :MSTORE(squareFp12BN254_a21_x) + B :MSTORE(squareFp12BN254_a21_y) + $ => A :MLOAD(millerLoopBN254_f22_x) + $ => B :MLOAD(millerLoopBN254_f22_y) + A :MSTORE(squareFp12BN254_a22_x) + B :MSTORE(squareFp12BN254_a22_y) + $ => A :MLOAD(millerLoopBN254_f23_x) + $ => B :MLOAD(millerLoopBN254_f23_y) + A :MSTORE(squareFp12BN254_a23_x) + B :MSTORE(squareFp12BN254_a23_y), CALL(squareFp12BN254) + + $ => A :MLOAD(squareFp12BN254_c11_x) + $ => B :MLOAD(squareFp12BN254_c11_y) + A :MSTORE(millerLoopBN254_fsquare11_x) + B :MSTORE(millerLoopBN254_fsquare11_y) + $ => A :MLOAD(squareFp12BN254_c12_x) + $ => B :MLOAD(squareFp12BN254_c12_y) + A :MSTORE(millerLoopBN254_fsquare12_x) + B :MSTORE(millerLoopBN254_fsquare12_y) + $ => A :MLOAD(squareFp12BN254_c13_x) + $ => B :MLOAD(squareFp12BN254_c13_y) + A :MSTORE(millerLoopBN254_fsquare13_x) + B :MSTORE(millerLoopBN254_fsquare13_y) + $ => A :MLOAD(squareFp12BN254_c21_x) + $ => B :MLOAD(squareFp12BN254_c21_y) + A :MSTORE(millerLoopBN254_fsquare21_x) + B :MSTORE(millerLoopBN254_fsquare21_y) + $ => A :MLOAD(squareFp12BN254_c22_x) + $ => B :MLOAD(squareFp12BN254_c22_y) + A :MSTORE(millerLoopBN254_fsquare22_x) + B :MSTORE(millerLoopBN254_fsquare22_y) + $ => A :MLOAD(squareFp12BN254_c23_x) + $ => B :MLOAD(squareFp12BN254_c23_y) + A :MSTORE(millerLoopBN254_fsquare23_x) + B :MSTORE(millerLoopBN254_fsquare23_y) + + ; line_{twist(R),twist(R)}(P) + $ => A :MLOAD(millerLoopBN254_R_x1) + $ => B :MLOAD(millerLoopBN254_R_x2) + $ => C :MLOAD(millerLoopBN254_R_y1) + $ => D :MLOAD(millerLoopBN254_R_y2) + A :MSTORE(lineSamePointsBN254_P_x1) + B :MSTORE(lineSamePointsBN254_P_x2) + C :MSTORE(lineSamePointsBN254_P_y1) + D :MSTORE(lineSamePointsBN254_P_y2) + $ => A :MLOAD(millerLoopBN254_P_x) + $ => B :MLOAD(millerLoopBN254_P_y) + A :MSTORE(lineSamePointsBN254_Q_x) + B :MSTORE(lineSamePointsBN254_Q_y), CALL(lineSamePointsBN254) + + $ => A :MLOAD(millerLoopBN254_fsquare11_x) + $ => B :MLOAD(millerLoopBN254_fsquare11_y) + A :MSTORE(sparseMulBFp12BN254_a11_x) + B :MSTORE(sparseMulBFp12BN254_a11_y) + $ => A :MLOAD(millerLoopBN254_fsquare12_x) + $ => B :MLOAD(millerLoopBN254_fsquare12_y) + A :MSTORE(sparseMulBFp12BN254_a12_x) + B :MSTORE(sparseMulBFp12BN254_a12_y) + $ => A :MLOAD(millerLoopBN254_fsquare13_x) + $ => B :MLOAD(millerLoopBN254_fsquare13_y) + A :MSTORE(sparseMulBFp12BN254_a13_x) + B :MSTORE(sparseMulBFp12BN254_a13_y) + $ => A :MLOAD(millerLoopBN254_fsquare21_x) + $ => B :MLOAD(millerLoopBN254_fsquare21_y) + A :MSTORE(sparseMulBFp12BN254_a21_x) + B :MSTORE(sparseMulBFp12BN254_a21_y) + $ => A :MLOAD(millerLoopBN254_fsquare22_x) + $ => B :MLOAD(millerLoopBN254_fsquare22_y) + A :MSTORE(sparseMulBFp12BN254_a22_x) + B :MSTORE(sparseMulBFp12BN254_a22_y) + $ => A :MLOAD(millerLoopBN254_fsquare23_x) + $ => B :MLOAD(millerLoopBN254_fsquare23_y) + A :MSTORE(sparseMulBFp12BN254_a23_x) + B :MSTORE(sparseMulBFp12BN254_a23_y) + + ; f² · line_{twist(R),twist(R)}(P) + $ => A :MLOAD(lineSamePointsBN254_l11_x) + $ => B :MLOAD(lineSamePointsBN254_l11_y) + A :MSTORE(sparseMulBFp12BN254_b11_x) + B :MSTORE(sparseMulBFp12BN254_b11_y) + $ => A :MLOAD(lineSamePointsBN254_l13_x) + $ => B :MLOAD(lineSamePointsBN254_l13_y) + A :MSTORE(sparseMulBFp12BN254_b13_x) + B :MSTORE(sparseMulBFp12BN254_b13_y) + $ => A :MLOAD(lineSamePointsBN254_l22_x) + $ => B :MLOAD(lineSamePointsBN254_l22_y) + A :MSTORE(sparseMulBFp12BN254_b22_x) + B :MSTORE(sparseMulBFp12BN254_b22_y), CALL(sparseMulBFp12BN254) + + $ => A :MLOAD(sparseMulBFp12BN254_c11_x) + $ => B :MLOAD(sparseMulBFp12BN254_c11_y) + A :MSTORE(millerLoopBN254_f11_x) + B :MSTORE(millerLoopBN254_f11_y) + $ => A :MLOAD(sparseMulBFp12BN254_c12_x) + $ => B :MLOAD(sparseMulBFp12BN254_c12_y) + A :MSTORE(millerLoopBN254_f12_x) + B :MSTORE(millerLoopBN254_f12_y) + $ => A :MLOAD(sparseMulBFp12BN254_c13_x) + $ => B :MLOAD(sparseMulBFp12BN254_c13_y) + A :MSTORE(millerLoopBN254_f13_x) + B :MSTORE(millerLoopBN254_f13_y) + $ => A :MLOAD(sparseMulBFp12BN254_c21_x) + $ => B :MLOAD(sparseMulBFp12BN254_c21_y) + A :MSTORE(millerLoopBN254_f21_x) + B :MSTORE(millerLoopBN254_f21_y) + $ => A :MLOAD(sparseMulBFp12BN254_c22_x) + $ => B :MLOAD(sparseMulBFp12BN254_c22_y) + A :MSTORE(millerLoopBN254_f22_x) + B :MSTORE(millerLoopBN254_f22_y) + $ => A :MLOAD(sparseMulBFp12BN254_c23_x) + $ => B :MLOAD(sparseMulBFp12BN254_c23_y) + A :MSTORE(millerLoopBN254_f23_x) + B :MSTORE(millerLoopBN254_f23_y) + + ; 2] R = 2·R + $ => A :MLOAD(millerLoopBN254_R_x1) + $ => B :MLOAD(millerLoopBN254_R_x2) + $ => C :MLOAD(millerLoopBN254_R_y1) + $ => D :MLOAD(millerLoopBN254_R_y2) + A :MSTORE(addPointBN254_P1_x1) + A :MSTORE(addPointBN254_P2_x1) + B :MSTORE(addPointBN254_P1_x2) + B :MSTORE(addPointBN254_P2_x2) + C :MSTORE(addPointBN254_P1_y1) + C :MSTORE(addPointBN254_P2_y1) + D :MSTORE(addPointBN254_P1_y2) + D :MSTORE(addPointBN254_P2_y2), CALL(addPointBN254) + + $ => A :MLOAD(addPointBN254_P3_x1) + $ => B :MLOAD(addPointBN254_P3_x2) + $ => C :MLOAD(addPointBN254_P3_y1) + $ => D :MLOAD(addPointBN254_P3_y2) + A :MSTORE(millerLoopBN254_R_x1) + B :MSTORE(millerLoopBN254_R_x2) + C :MSTORE(millerLoopBN254_R_y1) + D :MSTORE(millerLoopBN254_R_y2) + + RCX-1 => RR + :CALL(@loopLengthBN254 + RR) + + ; if bit = -1, then sub + B :JMPN(millerLoopBN254_sub) + + ; if bit = 0, then repeat + B :JMPZ(millerLoopBN254_loop) + + ; if bit = 1, then add + +millerLoopBN254_add: + ; 1] f = f · line_{twist(R),twist(Q)}(P) + ; line_{twist(R),twist(Q)}(P) + $ => A :MLOAD(millerLoopBN254_R_x1) + $ => B :MLOAD(millerLoopBN254_R_x2) + $ => C :MLOAD(millerLoopBN254_R_y1) + $ => D :MLOAD(millerLoopBN254_R_y2) + A :MSTORE(lineDiffPointsBN254_P1_x1) + B :MSTORE(lineDiffPointsBN254_P1_x2) + C :MSTORE(lineDiffPointsBN254_P1_y1) + D :MSTORE(lineDiffPointsBN254_P1_y2) + $ => A :MLOAD(millerLoopBN254_Q_x1) + $ => B :MLOAD(millerLoopBN254_Q_x2) + $ => C :MLOAD(millerLoopBN254_Q_y1) + $ => D :MLOAD(millerLoopBN254_Q_y2) + A :MSTORE(lineDiffPointsBN254_P2_x1) + B :MSTORE(lineDiffPointsBN254_P2_x2) + C :MSTORE(lineDiffPointsBN254_P2_y1) + D :MSTORE(lineDiffPointsBN254_P2_y2) + $ => A :MLOAD(millerLoopBN254_P_x) + $ => B :MLOAD(millerLoopBN254_P_y) + A :MSTORE(lineDiffPointsBN254_Q_x) + B :MSTORE(lineDiffPointsBN254_Q_y), CALL(lineDiffPointsBN254) + + $ => A :MLOAD(millerLoopBN254_f11_x) + $ => B :MLOAD(millerLoopBN254_f11_y) + A :MSTORE(sparseMulAFp12BN254_a11_x) + B :MSTORE(sparseMulAFp12BN254_a11_y) + $ => A :MLOAD(millerLoopBN254_f12_x) + $ => B :MLOAD(millerLoopBN254_f12_y) + A :MSTORE(sparseMulAFp12BN254_a12_x) + B :MSTORE(sparseMulAFp12BN254_a12_y) + $ => A :MLOAD(millerLoopBN254_f13_x) + $ => B :MLOAD(millerLoopBN254_f13_y) + A :MSTORE(sparseMulAFp12BN254_a13_x) + B :MSTORE(sparseMulAFp12BN254_a13_y) + $ => A :MLOAD(millerLoopBN254_f21_x) + $ => B :MLOAD(millerLoopBN254_f21_y) + A :MSTORE(sparseMulAFp12BN254_a21_x) + B :MSTORE(sparseMulAFp12BN254_a21_y) + $ => A :MLOAD(millerLoopBN254_f22_x) + $ => B :MLOAD(millerLoopBN254_f22_y) + A :MSTORE(sparseMulAFp12BN254_a22_x) + B :MSTORE(sparseMulAFp12BN254_a22_y) + $ => A :MLOAD(millerLoopBN254_f23_x) + $ => B :MLOAD(millerLoopBN254_f23_y) + A :MSTORE(sparseMulAFp12BN254_a23_x) + B :MSTORE(sparseMulAFp12BN254_a23_y) + + ; f · line_{twist(R),twist(Q)}(P) + $ => A :MLOAD(lineDiffPointsBN254_l12_x) + $ => B :MLOAD(lineDiffPointsBN254_l12_y) + A :MSTORE(sparseMulAFp12BN254_b12_x) + B :MSTORE(sparseMulAFp12BN254_b12_y) + $ => A :MLOAD(lineDiffPointsBN254_l22_x) + $ => B :MLOAD(lineDiffPointsBN254_l22_y) + A :MSTORE(sparseMulAFp12BN254_b22_x) + B :MSTORE(sparseMulAFp12BN254_b22_y) + $ => A :MLOAD(lineDiffPointsBN254_l23_x) + $ => B :MLOAD(lineDiffPointsBN254_l23_y) + A :MSTORE(sparseMulAFp12BN254_b23_x) + B :MSTORE(sparseMulAFp12BN254_b23_y), CALL(sparseMulAFp12BN254) + + $ => A :MLOAD(sparseMulAFp12BN254_c11_x) + $ => B :MLOAD(sparseMulAFp12BN254_c11_y) + A :MSTORE(millerLoopBN254_f11_x) + B :MSTORE(millerLoopBN254_f11_y) + $ => A :MLOAD(sparseMulAFp12BN254_c12_x) + $ => B :MLOAD(sparseMulAFp12BN254_c12_y) + A :MSTORE(millerLoopBN254_f12_x) + B :MSTORE(millerLoopBN254_f12_y) + $ => A :MLOAD(sparseMulAFp12BN254_c13_x) + $ => B :MLOAD(sparseMulAFp12BN254_c13_y) + A :MSTORE(millerLoopBN254_f13_x) + B :MSTORE(millerLoopBN254_f13_y) + $ => A :MLOAD(sparseMulAFp12BN254_c21_x) + $ => B :MLOAD(sparseMulAFp12BN254_c21_y) + A :MSTORE(millerLoopBN254_f21_x) + B :MSTORE(millerLoopBN254_f21_y) + $ => A :MLOAD(sparseMulAFp12BN254_c22_x) + $ => B :MLOAD(sparseMulAFp12BN254_c22_y) + A :MSTORE(millerLoopBN254_f22_x) + B :MSTORE(millerLoopBN254_f22_y) + $ => A :MLOAD(sparseMulAFp12BN254_c23_x) + $ => B :MLOAD(sparseMulAFp12BN254_c23_y) + A :MSTORE(millerLoopBN254_f23_x) + B :MSTORE(millerLoopBN254_f23_y) + + ; 2] R = R + Q + $ => A :MLOAD(millerLoopBN254_R_x1) + $ => B :MLOAD(millerLoopBN254_R_x2) + $ => C :MLOAD(millerLoopBN254_R_y1) + $ => D :MLOAD(millerLoopBN254_R_y2) + A :MSTORE(addPointBN254_P1_x1) + B :MSTORE(addPointBN254_P1_x2) + C :MSTORE(addPointBN254_P1_y1) + D :MSTORE(addPointBN254_P1_y2) + $ => A :MLOAD(millerLoopBN254_Q_x1) + $ => B :MLOAD(millerLoopBN254_Q_x2) + $ => C :MLOAD(millerLoopBN254_Q_y1) + $ => D :MLOAD(millerLoopBN254_Q_y2) + A :MSTORE(addPointBN254_P2_x1) + B :MSTORE(addPointBN254_P2_x2) + C :MSTORE(addPointBN254_P2_y1) + D :MSTORE(addPointBN254_P2_y2), CALL(addPointBN254) + + $ => A :MLOAD(addPointBN254_P3_x1) + $ => B :MLOAD(addPointBN254_P3_x2) + $ => C :MLOAD(addPointBN254_P3_y1) + $ => D :MLOAD(addPointBN254_P3_y2) + A :MSTORE(millerLoopBN254_R_x1) + B :MSTORE(millerLoopBN254_R_x2) + C :MSTORE(millerLoopBN254_R_y1) + D :MSTORE(millerLoopBN254_R_y2) + + :JMP(millerLoopBN254_loop) + + +millerLoopBN254_sub: + ; 1] f = f · line_{twist(R),twist(-Q)}(P) + ; line_{twist(R),twist(-Q)}(P) + $ => A :MLOAD(millerLoopBN254_R_x1) + $ => B :MLOAD(millerLoopBN254_R_x2) + $ => C :MLOAD(millerLoopBN254_R_y1) + $ => D :MLOAD(millerLoopBN254_R_y2) + A :MSTORE(lineDiffPointsBN254_P1_x1) + B :MSTORE(lineDiffPointsBN254_P1_x2) + C :MSTORE(lineDiffPointsBN254_P1_y1) + D :MSTORE(lineDiffPointsBN254_P1_y2) + $ => A :MLOAD(millerLoopBN254_Q_x1) + $ => B :MLOAD(millerLoopBN254_Q_x2) + A :MSTORE(lineDiffPointsBN254_P2_x1) + B :MSTORE(lineDiffPointsBN254_P2_x2) + + %BN254_P => A + $ => B :MLOAD(millerLoopBN254_Q_y1) + $ :SUB, MSTORE(lineDiffPointsBN254_P2_y1) + %BN254_P => A + $ => B :MLOAD(millerLoopBN254_Q_y2) + $ :SUB, MSTORE(lineDiffPointsBN254_P2_y2) + + $ => A :MLOAD(millerLoopBN254_P_x) + $ => B :MLOAD(millerLoopBN254_P_y) + A :MSTORE(lineDiffPointsBN254_Q_x) + B :MSTORE(lineDiffPointsBN254_Q_y), CALL(lineDiffPointsBN254) + + $ => A :MLOAD(millerLoopBN254_f11_x) + $ => B :MLOAD(millerLoopBN254_f11_y) + A :MSTORE(sparseMulAFp12BN254_a11_x) + B :MSTORE(sparseMulAFp12BN254_a11_y) + $ => A :MLOAD(millerLoopBN254_f12_x) + $ => B :MLOAD(millerLoopBN254_f12_y) + A :MSTORE(sparseMulAFp12BN254_a12_x) + B :MSTORE(sparseMulAFp12BN254_a12_y) + $ => A :MLOAD(millerLoopBN254_f13_x) + $ => B :MLOAD(millerLoopBN254_f13_y) + A :MSTORE(sparseMulAFp12BN254_a13_x) + B :MSTORE(sparseMulAFp12BN254_a13_y) + $ => A :MLOAD(millerLoopBN254_f21_x) + $ => B :MLOAD(millerLoopBN254_f21_y) + A :MSTORE(sparseMulAFp12BN254_a21_x) + B :MSTORE(sparseMulAFp12BN254_a21_y) + $ => A :MLOAD(millerLoopBN254_f22_x) + $ => B :MLOAD(millerLoopBN254_f22_y) + A :MSTORE(sparseMulAFp12BN254_a22_x) + B :MSTORE(sparseMulAFp12BN254_a22_y) + $ => A :MLOAD(millerLoopBN254_f23_x) + $ => B :MLOAD(millerLoopBN254_f23_y) + A :MSTORE(sparseMulAFp12BN254_a23_x) + B :MSTORE(sparseMulAFp12BN254_a23_y) + + ; ; f · line_{twist(R),twist(-Q)}(P) + $ => A :MLOAD(lineDiffPointsBN254_l12_x) + $ => B :MLOAD(lineDiffPointsBN254_l12_y) + A :MSTORE(sparseMulAFp12BN254_b12_x) + B :MSTORE(sparseMulAFp12BN254_b12_y) + $ => A :MLOAD(lineDiffPointsBN254_l22_x) + $ => B :MLOAD(lineDiffPointsBN254_l22_y) + A :MSTORE(sparseMulAFp12BN254_b22_x) + B :MSTORE(sparseMulAFp12BN254_b22_y) + $ => A :MLOAD(lineDiffPointsBN254_l23_x) + $ => B :MLOAD(lineDiffPointsBN254_l23_y) + A :MSTORE(sparseMulAFp12BN254_b23_x) + B :MSTORE(sparseMulAFp12BN254_b23_y), CALL(sparseMulAFp12BN254) + + $ => A :MLOAD(sparseMulAFp12BN254_c11_x) + $ => B :MLOAD(sparseMulAFp12BN254_c11_y) + A :MSTORE(millerLoopBN254_f11_x) + B :MSTORE(millerLoopBN254_f11_y) + $ => A :MLOAD(sparseMulAFp12BN254_c12_x) + $ => B :MLOAD(sparseMulAFp12BN254_c12_y) + A :MSTORE(millerLoopBN254_f12_x) + B :MSTORE(millerLoopBN254_f12_y) + $ => A :MLOAD(sparseMulAFp12BN254_c13_x) + $ => B :MLOAD(sparseMulAFp12BN254_c13_y) + A :MSTORE(millerLoopBN254_f13_x) + B :MSTORE(millerLoopBN254_f13_y) + $ => A :MLOAD(sparseMulAFp12BN254_c21_x) + $ => B :MLOAD(sparseMulAFp12BN254_c21_y) + A :MSTORE(millerLoopBN254_f21_x) + B :MSTORE(millerLoopBN254_f21_y) + $ => A :MLOAD(sparseMulAFp12BN254_c22_x) + $ => B :MLOAD(sparseMulAFp12BN254_c22_y) + A :MSTORE(millerLoopBN254_f22_x) + B :MSTORE(millerLoopBN254_f22_y) + $ => A :MLOAD(sparseMulAFp12BN254_c23_x) + $ => B :MLOAD(sparseMulAFp12BN254_c23_y) + A :MSTORE(millerLoopBN254_f23_x) + B :MSTORE(millerLoopBN254_f23_y) + + ; 2] R = R - Q + $ => A :MLOAD(millerLoopBN254_R_x1) + $ => B :MLOAD(millerLoopBN254_R_x2) + $ => C :MLOAD(millerLoopBN254_R_y1) + $ => D :MLOAD(millerLoopBN254_R_y2) + A :MSTORE(addPointBN254_P1_x1) + B :MSTORE(addPointBN254_P1_x2) + C :MSTORE(addPointBN254_P1_y1) + D :MSTORE(addPointBN254_P1_y2) + $ => A :MLOAD(millerLoopBN254_Q_x1) + $ => B :MLOAD(millerLoopBN254_Q_x2) + A :MSTORE(addPointBN254_P2_x1) + B :MSTORE(addPointBN254_P2_x2) + %BN254_P => A + $ => B :MLOAD(millerLoopBN254_Q_y1) + $ :SUB, MSTORE(addPointBN254_P2_y1) + %BN254_P => A + $ => B :MLOAD(millerLoopBN254_Q_y2) + $ :SUB, MSTORE(addPointBN254_P2_y2), CALL(addPointBN254) + + + $ => A :MLOAD(addPointBN254_P3_x1) + $ => B :MLOAD(addPointBN254_P3_x2) + $ => C :MLOAD(addPointBN254_P3_y1) + $ => D :MLOAD(addPointBN254_P3_y2) + A :MSTORE(millerLoopBN254_R_x1) + B :MSTORE(millerLoopBN254_R_x2) + C :MSTORE(millerLoopBN254_R_y1) + D :MSTORE(millerLoopBN254_R_y2) + + :JMP(millerLoopBN254_loop) + +millerLoopBN254_last_two_lines: + ; 1] Given Q = (x,y) with x,y ∈ Fp2, compute Frobenius1(Q) = (\gamma12·x̄, \gamma13·ȳ) + %BN254_P => A + $ => B :MLOAD(millerLoopBN254_Q_x2) + $ => B :SUB + $ => A :MLOAD(millerLoopBN254_Q_x1) + %FROBENIUS_GAMMA121 => C + %FROBENIUS_GAMMA122 => D :CALL(mulFp2BN254) + + E :MSTORE(millerLoopBN254_Frobenius1_Q_x1) + C :MSTORE(millerLoopBN254_Frobenius1_Q_x2) + + %BN254_P => A + $ => B :MLOAD(millerLoopBN254_Q_y2) + $ => B :SUB + $ => A :MLOAD(millerLoopBN254_Q_y1) + %FROBENIUS_GAMMA131 => C + %FROBENIUS_GAMMA132 => D :CALL(mulFp2BN254) + + E :MSTORE(millerLoopBN254_Frobenius1_Q_y1) + C :MSTORE(millerLoopBN254_Frobenius1_Q_y2) + + + ; 2] f = f · line_{twist(R),twist(Frobenius1(Q))}(P) + ; line_{twist(R),twist(Frobenius1(Q))}(P) + $ => A :MLOAD(millerLoopBN254_R_x1) + $ => B :MLOAD(millerLoopBN254_R_x2) + $ => C :MLOAD(millerLoopBN254_R_y1) + $ => D :MLOAD(millerLoopBN254_R_y2) + A :MSTORE(lineDiffPointsBN254_P1_x1) + B :MSTORE(lineDiffPointsBN254_P1_x2) + C :MSTORE(lineDiffPointsBN254_P1_y1) + D :MSTORE(lineDiffPointsBN254_P1_y2) + $ => A :MLOAD(millerLoopBN254_Frobenius1_Q_x1) + $ => B :MLOAD(millerLoopBN254_Frobenius1_Q_x2) + $ => C :MLOAD(millerLoopBN254_Frobenius1_Q_y1) + $ => D :MLOAD(millerLoopBN254_Frobenius1_Q_y2) + A :MSTORE(lineDiffPointsBN254_P2_x1) + B :MSTORE(lineDiffPointsBN254_P2_x2) + C :MSTORE(lineDiffPointsBN254_P2_y1) + D :MSTORE(lineDiffPointsBN254_P2_y2) + + $ => A :MLOAD(millerLoopBN254_P_x) + $ => B :MLOAD(millerLoopBN254_P_y) + A :MSTORE(lineDiffPointsBN254_Q_x) + B :MSTORE(lineDiffPointsBN254_Q_y), CALL(lineDiffPointsBN254) + + $ => A :MLOAD(millerLoopBN254_f11_x) + $ => B :MLOAD(millerLoopBN254_f11_y) + A :MSTORE(sparseMulAFp12BN254_a11_x) + B :MSTORE(sparseMulAFp12BN254_a11_y) + $ => A :MLOAD(millerLoopBN254_f12_x) + $ => B :MLOAD(millerLoopBN254_f12_y) + A :MSTORE(sparseMulAFp12BN254_a12_x) + B :MSTORE(sparseMulAFp12BN254_a12_y) + $ => A :MLOAD(millerLoopBN254_f13_x) + $ => B :MLOAD(millerLoopBN254_f13_y) + A :MSTORE(sparseMulAFp12BN254_a13_x) + B :MSTORE(sparseMulAFp12BN254_a13_y) + $ => A :MLOAD(millerLoopBN254_f21_x) + $ => B :MLOAD(millerLoopBN254_f21_y) + A :MSTORE(sparseMulAFp12BN254_a21_x) + B :MSTORE(sparseMulAFp12BN254_a21_y) + $ => A :MLOAD(millerLoopBN254_f22_x) + $ => B :MLOAD(millerLoopBN254_f22_y) + A :MSTORE(sparseMulAFp12BN254_a22_x) + B :MSTORE(sparseMulAFp12BN254_a22_y) + $ => A :MLOAD(millerLoopBN254_f23_x) + $ => B :MLOAD(millerLoopBN254_f23_y) + A :MSTORE(sparseMulAFp12BN254_a23_x) + B :MSTORE(sparseMulAFp12BN254_a23_y) + + ; f · line_{twist(R),twist(Frobenius1(Q))}(P) + $ => A :MLOAD(lineDiffPointsBN254_l12_x) + $ => B :MLOAD(lineDiffPointsBN254_l12_y) + A :MSTORE(sparseMulAFp12BN254_b12_x) + B :MSTORE(sparseMulAFp12BN254_b12_y) + $ => A :MLOAD(lineDiffPointsBN254_l22_x) + $ => B :MLOAD(lineDiffPointsBN254_l22_y) + A :MSTORE(sparseMulAFp12BN254_b22_x) + B :MSTORE(sparseMulAFp12BN254_b22_y) + $ => A :MLOAD(lineDiffPointsBN254_l23_x) + $ => B :MLOAD(lineDiffPointsBN254_l23_y) + A :MSTORE(sparseMulAFp12BN254_b23_x) + B :MSTORE(sparseMulAFp12BN254_b23_y), CALL(sparseMulAFp12BN254) + + $ => A :MLOAD(sparseMulAFp12BN254_c11_x) + $ => B :MLOAD(sparseMulAFp12BN254_c11_y) + A :MSTORE(millerLoopBN254_f11_x) + B :MSTORE(millerLoopBN254_f11_y) + $ => A :MLOAD(sparseMulAFp12BN254_c12_x) + $ => B :MLOAD(sparseMulAFp12BN254_c12_y) + A :MSTORE(millerLoopBN254_f12_x) + B :MSTORE(millerLoopBN254_f12_y) + $ => A :MLOAD(sparseMulAFp12BN254_c13_x) + $ => B :MLOAD(sparseMulAFp12BN254_c13_y) + A :MSTORE(millerLoopBN254_f13_x) + B :MSTORE(millerLoopBN254_f13_y) + $ => A :MLOAD(sparseMulAFp12BN254_c21_x) + $ => B :MLOAD(sparseMulAFp12BN254_c21_y) + A :MSTORE(millerLoopBN254_f21_x) + B :MSTORE(millerLoopBN254_f21_y) + $ => A :MLOAD(sparseMulAFp12BN254_c22_x) + $ => B :MLOAD(sparseMulAFp12BN254_c22_y) + A :MSTORE(millerLoopBN254_f22_x) + B :MSTORE(millerLoopBN254_f22_y) + $ => A :MLOAD(sparseMulAFp12BN254_c23_x) + $ => B :MLOAD(sparseMulAFp12BN254_c23_y) + A :MSTORE(millerLoopBN254_f23_x) + B :MSTORE(millerLoopBN254_f23_y) + + ; 3] R = R + Frobenius1(Q) + $ => A :MLOAD(millerLoopBN254_R_x1) + $ => B :MLOAD(millerLoopBN254_R_x2) + $ => C :MLOAD(millerLoopBN254_R_y1) + $ => D :MLOAD(millerLoopBN254_R_y2) + A :MSTORE(addPointBN254_P1_x1) + B :MSTORE(addPointBN254_P1_x2) + C :MSTORE(addPointBN254_P1_y1) + D :MSTORE(addPointBN254_P1_y2) + $ => A :MLOAD(millerLoopBN254_Frobenius1_Q_x1) + $ => B :MLOAD(millerLoopBN254_Frobenius1_Q_x2) + $ => C :MLOAD(millerLoopBN254_Frobenius1_Q_y1) + $ => D :MLOAD(millerLoopBN254_Frobenius1_Q_y2) + A :MSTORE(addPointBN254_P2_x1) + B :MSTORE(addPointBN254_P2_x2) + C :MSTORE(addPointBN254_P2_y1) + D :MSTORE(addPointBN254_P2_y2), CALL(addPointBN254) + + $ => A :MLOAD(addPointBN254_P3_x1) + $ => B :MLOAD(addPointBN254_P3_x2) + $ => C :MLOAD(addPointBN254_P3_y1) + $ => D :MLOAD(addPointBN254_P3_y2) + A :MSTORE(millerLoopBN254_R_x1) + B :MSTORE(millerLoopBN254_R_x2) + C :MSTORE(millerLoopBN254_R_y1) + D :MSTORE(millerLoopBN254_R_y2) + + ; 4] Given Frobenius1(Q) = (x,y) with x,y ∈ Fp2, compute -Frobenius2(Q) = (\gamma12·x̄, -\gamma13·ȳ) + + %BN254_P => A + $ => B :MLOAD(millerLoopBN254_Frobenius1_Q_x2) + $ => B :SUB + $ => A :MLOAD(millerLoopBN254_Frobenius1_Q_x1) + %FROBENIUS_GAMMA121 => C + %FROBENIUS_GAMMA122 => D :CALL(mulFp2BN254) + + E :MSTORE(millerLoopBN254_nFrobenius2_Q_x1) + C :MSTORE(millerLoopBN254_nFrobenius2_Q_x2) + + + %BN254_P => A + $ => B :MLOAD(millerLoopBN254_Frobenius1_Q_y2) + $ => B :SUB + $ => A :MLOAD(millerLoopBN254_Frobenius1_Q_y1) + %FROBENIUS_GAMMA131_NEGATED => C + %FROBENIUS_GAMMA132_NEGATED => D :CALL(mulFp2BN254) + + + ; 5] f = f · line_{twist(R),twist(-Frobenius2(Q))}(P) + ; line_{twist(R),twist(-Frobenius2(Q))}(P) + $ => A :MLOAD(millerLoopBN254_nFrobenius2_Q_x1) + $ => B :MLOAD(millerLoopBN254_nFrobenius2_Q_x2) + C => D + E => C + A :MSTORE(lineDiffPointsBN254_P2_x1) + B :MSTORE(lineDiffPointsBN254_P2_x2) + C :MSTORE(lineDiffPointsBN254_P2_y1) + D :MSTORE(lineDiffPointsBN254_P2_y2) + $ => A :MLOAD(millerLoopBN254_R_x1) + $ => B :MLOAD(millerLoopBN254_R_x2) + $ => C :MLOAD(millerLoopBN254_R_y1) + $ => D :MLOAD(millerLoopBN254_R_y2) + A :MSTORE(lineDiffPointsBN254_P1_x1) + B :MSTORE(lineDiffPointsBN254_P1_x2) + C :MSTORE(lineDiffPointsBN254_P1_y1) + D :MSTORE(lineDiffPointsBN254_P1_y2) + + $ => A :MLOAD(millerLoopBN254_P_x) + $ => B :MLOAD(millerLoopBN254_P_y) + A :MSTORE(lineDiffPointsBN254_Q_x) + B :MSTORE(lineDiffPointsBN254_Q_y), CALL(lineDiffPointsBN254) + + $ => A :MLOAD(millerLoopBN254_f11_x) + $ => B :MLOAD(millerLoopBN254_f11_y) + A :MSTORE(sparseMulAFp12BN254_a11_x) + B :MSTORE(sparseMulAFp12BN254_a11_y) + $ => A :MLOAD(millerLoopBN254_f12_x) + $ => B :MLOAD(millerLoopBN254_f12_y) + A :MSTORE(sparseMulAFp12BN254_a12_x) + B :MSTORE(sparseMulAFp12BN254_a12_y) + $ => A :MLOAD(millerLoopBN254_f13_x) + $ => B :MLOAD(millerLoopBN254_f13_y) + A :MSTORE(sparseMulAFp12BN254_a13_x) + B :MSTORE(sparseMulAFp12BN254_a13_y) + $ => A :MLOAD(millerLoopBN254_f21_x) + $ => B :MLOAD(millerLoopBN254_f21_y) + A :MSTORE(sparseMulAFp12BN254_a21_x) + B :MSTORE(sparseMulAFp12BN254_a21_y) + $ => A :MLOAD(millerLoopBN254_f22_x) + $ => B :MLOAD(millerLoopBN254_f22_y) + A :MSTORE(sparseMulAFp12BN254_a22_x) + B :MSTORE(sparseMulAFp12BN254_a22_y) + $ => A :MLOAD(millerLoopBN254_f23_x) + $ => B :MLOAD(millerLoopBN254_f23_y) + A :MSTORE(sparseMulAFp12BN254_a23_x) + B :MSTORE(sparseMulAFp12BN254_a23_y) + + ; f · line_{twist(R),twist(-Frobenius2(Q))}(P) + $ => A :MLOAD(lineDiffPointsBN254_l12_x) + $ => B :MLOAD(lineDiffPointsBN254_l12_y) + A :MSTORE(sparseMulAFp12BN254_b12_x) + B :MSTORE(sparseMulAFp12BN254_b12_y) + $ => A :MLOAD(lineDiffPointsBN254_l22_x) + $ => B :MLOAD(lineDiffPointsBN254_l22_y) + A :MSTORE(sparseMulAFp12BN254_b22_x) + B :MSTORE(sparseMulAFp12BN254_b22_y) + $ => A :MLOAD(lineDiffPointsBN254_l23_x) + $ => B :MLOAD(lineDiffPointsBN254_l23_y) + A :MSTORE(sparseMulAFp12BN254_b23_x) + B :MSTORE(sparseMulAFp12BN254_b23_y), CALL(sparseMulAFp12BN254) + + $ => A :MLOAD(sparseMulAFp12BN254_c11_x) + $ => B :MLOAD(sparseMulAFp12BN254_c11_y) + A :MSTORE(millerLoopBN254_f11_x) + B :MSTORE(millerLoopBN254_f11_y) + $ => A :MLOAD(sparseMulAFp12BN254_c12_x) + $ => B :MLOAD(sparseMulAFp12BN254_c12_y) + A :MSTORE(millerLoopBN254_f12_x) + B :MSTORE(millerLoopBN254_f12_y) + $ => A :MLOAD(sparseMulAFp12BN254_c13_x) + $ => B :MLOAD(sparseMulAFp12BN254_c13_y) + A :MSTORE(millerLoopBN254_f13_x) + B :MSTORE(millerLoopBN254_f13_y) + $ => A :MLOAD(sparseMulAFp12BN254_c21_x) + $ => B :MLOAD(sparseMulAFp12BN254_c21_y) + A :MSTORE(millerLoopBN254_f21_x) + B :MSTORE(millerLoopBN254_f21_y) + $ => A :MLOAD(sparseMulAFp12BN254_c22_x) + $ => B :MLOAD(sparseMulAFp12BN254_c22_y) + A :MSTORE(millerLoopBN254_f22_x) + B :MSTORE(millerLoopBN254_f22_y) + $ => A :MLOAD(sparseMulAFp12BN254_c23_x) + $ => B :MLOAD(sparseMulAFp12BN254_c23_y) + A :MSTORE(millerLoopBN254_f23_x) + B :MSTORE(millerLoopBN254_f23_y) + +millerLoopBN254_end: + $ => RR :MLOAD(millerLoopBN254_RR) + :RETURN \ No newline at end of file diff --git a/main/pairings/pairingBN254.zkasm b/main/pairings/pairingBN254.zkasm new file mode 100644 index 00000000..4ab37b6f --- /dev/null +++ b/main/pairings/pairingBN254.zkasm @@ -0,0 +1,481 @@ +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; +;; Optimal Ate Pairing e: G1 x G2 -> GT over the BN254 curve +;; where G1 = E(Fp)[r] = E(Fp), G2 = E'(Fp2)[r] and GT = mu_r (the r-th roots of unity over Fp12* +;; the involved curves are E/Fp: y² = x³ + 3 and E'/Fp2: y² = x³ + 3/(9+u) +;; pairingBN254: +;; input: P ∈ G1 and Q ∈ G2 +;; output: e(P,Q) ∈ GT +;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +VAR GLOBAL pairingBN254_P_x +VAR GLOBAL pairingBN254_P_y +VAR GLOBAL pairingBN254_Q_x1 +VAR GLOBAL pairingBN254_Q_x2 +VAR GLOBAL pairingBN254_Q_y1 +VAR GLOBAL pairingBN254_Q_y2 + +VAR GLOBAL pairingBN254_f11_x +VAR GLOBAL pairingBN254_f11_y +VAR GLOBAL pairingBN254_f12_x +VAR GLOBAL pairingBN254_f12_y +VAR GLOBAL pairingBN254_f13_x +VAR GLOBAL pairingBN254_f13_y +VAR GLOBAL pairingBN254_f21_x +VAR GLOBAL pairingBN254_f21_y +VAR GLOBAL pairingBN254_f22_x +VAR GLOBAL pairingBN254_f22_y +VAR GLOBAL pairingBN254_f23_x +VAR GLOBAL pairingBN254_f23_y + +VAR GLOBAL pairingBN254_RR + +VAR GLOBAL pairingBN254_P_x3 +VAR GLOBAL pairingBN254_Q_RHS_x +VAR GLOBAL pairingBN254_Q_RHS_y +VAR GLOBAL pairingBN254_psi_x1 +VAR GLOBAL pairingBN254_psi_x2 +VAR GLOBAL pairingBN254_psi_y1 +VAR GLOBAL pairingBN254_psi_y2 + +; ERROR CODES (B) +; 0 - no error +; 1 - P_x is too big +; 2 - P_y is too big +; 3 - Q_x1 is too big +; 4 - Q_x2 is too big +; 5 - Q_y1 is too big +; 6 - Q_y2 is too big +; 7 - P is not in G1 +; 8 - Q is not in G2 + +pairingBN254: + RR :MSTORE(pairingBN254_RR) + + %BN254_P_MINUS_ONE => A + $ => B :MLOAD(pairingBN254_P_x) + $ :LT, JMPC(pairingBN254_Px_too_big) + $ => B :MLOAD(pairingBN254_P_y) + $ :LT, JMPC(pairingBN254_Py_too_big) + $ => B :MLOAD(pairingBN254_Q_x1) + $ :LT, JMPC(pairingBN254_Qx1_too_big) + $ => B :MLOAD(pairingBN254_Q_x2) + $ :LT, JMPC(pairingBN254_Qx2_too_big) + $ => B :MLOAD(pairingBN254_Q_y1) + $ :LT, JMPC(pairingBN254_Qy1_too_big) + $ => B :MLOAD(pairingBN254_Q_y2) + $ :LT, JMPC(pairingBN254_Qy2_too_big) + + ; Is P = O? + 0n => B + $ => A :MLOAD(pairingBN254_P_x) + $ :EQ, JMPNC(__pairingBN254_P_continue) + $ => A :MLOAD(pairingBN254_P_y) + $ :EQ, JMPC(pairingBN254_P_is_zero) + __pairingBN254_P_continue: + + ; Is Q = O? + $ => A :MLOAD(pairingBN254_Q_x1) + $ :EQ, JMPNC(__pairingBN254_Q_continue1) + $ => A :MLOAD(pairingBN254_Q_x2) + $ :EQ, JMPNC(__pairingBN254_Q_continue1) + $ => A :MLOAD(pairingBN254_Q_y1) + $ :EQ, JMPNC(__pairingBN254_Q_continue1) + $ => A :MLOAD(pairingBN254_Q_y2) + $ :EQ, JMPC(pairingBN254_Q_is_zero) + __pairingBN254_Q_continue1: + + :JMP(pairingBN254_P_subgroup_check) + + +pairingBN254_P_is_zero: + ; Is Q = O? + $ => A :MLOAD(pairingBN254_Q_x1) + $ :EQ, JMPNC(__pairingBN254_Q_continue2) + $ => A :MLOAD(pairingBN254_Q_x2) + $ :EQ, JMPNC(__pairingBN254_Q_continue2) + $ => A :MLOAD(pairingBN254_Q_y1) + $ :EQ, JMPNC(__pairingBN254_Q_continue2) + $ => A :MLOAD(pairingBN254_Q_y2) + $ :EQ, JMPC(pairingBN254_P_and_Q_are_zero) + __pairingBN254_Q_continue2: + + ; Check that Q is in G2 + ; Q in G2 iff Q in E' and psi(Q) == [6x²]Q as proven in Proposition 3 of 2022/352 + + ; 1] Check if Q is in E'(Fp2) + ; Q in E' iff (Q.y1 + Q.y2·u)² == (Q.x1 + Q.x2·u)³ + 3/(9+u) + ; 1.1] Compute LHS and RHS + $ => A :MLOAD(pairingBN254_Q_x1) + $ => B :MLOAD(pairingBN254_Q_x2), CALL(squareFp2BN254) + ; E + C·u = (Q.x1 + Q.x2·u)² + + E => A + C => B + $ => C :MLOAD(pairingBN254_Q_x1) + $ => D :MLOAD(pairingBN254_Q_x2), CALL(mulFp2BN254) + ; E + C·u = (Q.x1 + Q.x2·u)³ + + E => A + C => B + %BN254_ETWISTED_B_X => C + %BN254_ETWISTED_B_Y => D :CALL(addFp2BN254) + ; E + C·u = (Q.x1 + Q.x2·u)³ + 3/(9+u) + E :MSTORE(pairingBN254_Q_RHS_x) + C :MSTORE(pairingBN254_Q_RHS_y) + + $ => A :MLOAD(pairingBN254_Q_y1) + $ => B :MLOAD(pairingBN254_Q_y2), CALL(squareFp2BN254) + ; E + C·u = (Q.y1 + Q.y2·u)² + + ; 1.2] Check if LHS == RHS + E => A + $ => B :MLOAD(pairingBN254_Q_RHS_x) + $ :EQ, JMPNC(pairingBN254_Q_is_not_in_G2) + + C => A + $ => B :MLOAD(pairingBN254_Q_RHS_y) + $ :EQ, JMPNC(pairingBN254_Q_is_not_in_G2) + + ; 2] Check if psi(Q) == [6x²]Q + ; 2.1] Compute psi(Q) + %BN254_P => A + $ => B :MLOAD(pairingBN254_Q_x2) + $ => D :SUB ; D = -Qx2 + %FROBENIUS_GAMMA121 => A + %FROBENIUS_GAMMA122 => B + $ => C :MLOAD(pairingBN254_Q_x1), CALL(mulFp2BN254) + E :MSTORE(pairingBN254_psi_x1) + C :MSTORE(pairingBN254_psi_x2) + + %BN254_P => A + $ => B :MLOAD(pairingBN254_Q_y2) + $ => D :SUB ; D = -Qy2 + %FROBENIUS_GAMMA131 => A + %FROBENIUS_GAMMA132 => B + $ => C :MLOAD(pairingBN254_Q_y1), CALL(mulFp2BN254) + E :MSTORE(pairingBN254_psi_y1) + C :MSTORE(pairingBN254_psi_y2) + + ; 2.2] Compute [6x²]Q + $ => A :MLOAD(pairingBN254_Q_x1) + $ => B :MLOAD(pairingBN254_Q_x2) + $ => C :MLOAD(pairingBN254_Q_y1) + $ => D :MLOAD(pairingBN254_Q_y2) + A :MSTORE(escalarMulBN254_P_x1) + B :MSTORE(escalarMulBN254_P_x2) + C :MSTORE(escalarMulBN254_P_y1) + D :MSTORE(escalarMulBN254_P_y2) + %BN254_SIX_TIMES_X_SQ :MSTORE(escalarMulBN254_k), CALL(escalarMulBN254) + + + ; 2.3] Check if psi(Q) == [6x²]Q + $ => A :MLOAD(pairingBN254_psi_x1) + $ => B :MLOAD(escalarMulBN254_Q_x1) + $ :EQ, JMPNC(pairingBN254_Q_is_not_in_G2) + + $ => A :MLOAD(pairingBN254_psi_x2) + $ => B :MLOAD(escalarMulBN254_Q_x2) + $ :EQ, JMPNC(pairingBN254_Q_is_not_in_G2) + + $ => A :MLOAD(pairingBN254_psi_y1) + $ => B :MLOAD(escalarMulBN254_Q_y1) + $ :EQ, JMPNC(pairingBN254_Q_is_not_in_G2) + + $ => A :MLOAD(pairingBN254_psi_y2) + $ => B :MLOAD(escalarMulBN254_Q_y2) + $ :EQ, JMPNC(pairingBN254_Q_is_not_in_G2) + + ; e(O,Q) = 1 + 1n :MSTORE(pairingBN254_f11_x) + 0n :MSTORE(pairingBN254_f11_y) + 0n :MSTORE(pairingBN254_f12_x) + 0n :MSTORE(pairingBN254_f12_y) + 0n :MSTORE(pairingBN254_f13_x) + 0n :MSTORE(pairingBN254_f13_y) + 0n :MSTORE(pairingBN254_f21_x) + 0n :MSTORE(pairingBN254_f21_y) + 0n :MSTORE(pairingBN254_f22_x) + 0n :MSTORE(pairingBN254_f22_y) + 0n :MSTORE(pairingBN254_f23_x) + 0n :MSTORE(pairingBN254_f23_y) + + 0 => B :JMP(pairingBN254_end) + +pairingBN254_Q_is_zero: + ; Check that P is in G1 + ; P in G1 iff (Py)² == (Px)³ + 3 (mod p) + ; 1] Compute LHS and RHS + $ => A,B :MLOAD(pairingBN254_P_x), CALL(mulFpBN254); C = (Px)² + C => A ; A = (Px)² + $ => B :MLOAD(pairingBN254_P_x), CALL(mulFpBN254); C = (Px)³ + + %BN254_E_B => A :CALL(addFpBN254) ; C = (Px)³ + 3 + C :MSTORE(pairingBN254_P_x3) ; pairingBN254_P_x3 = (Px)³ + 3 + + $ => A,B :MLOAD(pairingBN254_P_y), CALL(mulFpBN254); C = (Py)² + + ; 2] Check if LHS == RHS + C => A + $ => B :MLOAD(pairingBN254_P_x3) + $ :EQ, JMPNC(pairingBN254_P_is_not_in_G1) + + ; e(P,O) = 1 + 1n :MSTORE(pairingBN254_f11_x) + 0n :MSTORE(pairingBN254_f11_y) + 0n :MSTORE(pairingBN254_f12_x) + 0n :MSTORE(pairingBN254_f12_y) + 0n :MSTORE(pairingBN254_f13_x) + 0n :MSTORE(pairingBN254_f13_y) + 0n :MSTORE(pairingBN254_f21_x) + 0n :MSTORE(pairingBN254_f21_y) + 0n :MSTORE(pairingBN254_f22_x) + 0n :MSTORE(pairingBN254_f22_y) + 0n :MSTORE(pairingBN254_f23_x) + 0n :MSTORE(pairingBN254_f23_y) + + 0 => B :JMP(pairingBN254_end) + +pairingBN254_P_and_Q_are_zero: + ; e(O,O) = 1 + 1n :MSTORE(pairingBN254_f11_x) + 0n :MSTORE(pairingBN254_f11_y) + 0n :MSTORE(pairingBN254_f12_x) + 0n :MSTORE(pairingBN254_f12_y) + 0n :MSTORE(pairingBN254_f13_x) + 0n :MSTORE(pairingBN254_f13_y) + 0n :MSTORE(pairingBN254_f21_x) + 0n :MSTORE(pairingBN254_f21_y) + 0n :MSTORE(pairingBN254_f22_x) + 0n :MSTORE(pairingBN254_f22_y) + 0n :MSTORE(pairingBN254_f23_x) + 0n :MSTORE(pairingBN254_f23_y) + +pairingBN254_P_subgroup_check: + ; Check that P is in G1 + ; P in G1 iff (Py)² == (Px)³ + 3 (mod p) + ; 1] Compute LHS and RHS + $ => A,B :MLOAD(pairingBN254_P_x), CALL(mulFpBN254); C = (Px)² + C => A ; A = (Px)² + $ => B :MLOAD(pairingBN254_P_x), CALL(mulFpBN254); C = (Px)³ + + %BN254_E_B => A :CALL(addFpBN254) ; C = (Px)³ + 3 + C :MSTORE(pairingBN254_P_x3) ; pairingBN254_P_x3 = (Px)³ + 3 + + $ => A,B :MLOAD(pairingBN254_P_y), CALL(mulFpBN254); C = (Py)² + + ; 2] Check if LHS == RHS + C => A + $ => B :MLOAD(pairingBN254_P_x3) + $ :EQ, JMPNC(pairingBN254_P_is_not_in_G1) + +pairingBN254_Q_subgroup_check: + ; Check that Q is in G2 + ; Q in G2 iff Q in E' and psi(Q) == [6x²]Q as proven in Proposition 3 of 2022/352 + + ; 1] Check if Q is in E'(Fp2) + ; Q in E' iff (Q.y1 + Q.y2·u)² == (Q.x1 + Q.x2·u)³ + 3/(9+u) + ; 1.1] Compute LHS and RHS + $ => A :MLOAD(pairingBN254_Q_x1) + $ => B :MLOAD(pairingBN254_Q_x2), CALL(squareFp2BN254) + ; E + C·u = (Q.x1 + Q.x2·u)² + + E => A + C => B + $ => C :MLOAD(pairingBN254_Q_x1) + $ => D :MLOAD(pairingBN254_Q_x2), CALL(mulFp2BN254) + ; E + C·u = (Q.x1 + Q.x2·u)³ + + E => A + C => B + %BN254_ETWISTED_B_X => C + %BN254_ETWISTED_B_Y => D :CALL(addFp2BN254) + ; E + C·u = (Q.x1 + Q.x2·u)³ + 3/(9+u) + E :MSTORE(pairingBN254_Q_RHS_x) + C :MSTORE(pairingBN254_Q_RHS_y) + + $ => A :MLOAD(pairingBN254_Q_y1) + $ => B :MLOAD(pairingBN254_Q_y2), CALL(squareFp2BN254) + ; E + C·u = (Q.y1 + Q.y2·u)² + + ; 1.2] Check if LHS == RHS + E => A + $ => B :MLOAD(pairingBN254_Q_RHS_x) + $ :EQ, JMPNC(pairingBN254_Q_is_not_in_G2) + + C => A + $ => B :MLOAD(pairingBN254_Q_RHS_y) + $ :EQ, JMPNC(pairingBN254_Q_is_not_in_G2) + + ; 2] Check if psi(Q) == [6x²]Q + ; 2.1] Compute psi(Q) + %BN254_P => A + $ => B :MLOAD(pairingBN254_Q_x2) + $ => D :SUB ; D = -Qx2 + %FROBENIUS_GAMMA121 => A + %FROBENIUS_GAMMA122 => B + $ => C :MLOAD(pairingBN254_Q_x1), CALL(mulFp2BN254) + E :MSTORE(pairingBN254_psi_x1) + C :MSTORE(pairingBN254_psi_x2) + + %BN254_P => A + $ => B :MLOAD(pairingBN254_Q_y2) + $ => D :SUB ; D = -Qx2 + %FROBENIUS_GAMMA131 => A + %FROBENIUS_GAMMA132 => B + $ => C :MLOAD(pairingBN254_Q_y1), CALL(mulFp2BN254) + E :MSTORE(pairingBN254_psi_y1) + C :MSTORE(pairingBN254_psi_y2) + + ; 2.2] Compute [6x²]Q + $ => A :MLOAD(pairingBN254_Q_x1) + $ => B :MLOAD(pairingBN254_Q_x2) + $ => C :MLOAD(pairingBN254_Q_y1) + $ => D :MLOAD(pairingBN254_Q_y2) + A :MSTORE(escalarMulBN254_P_x1) + B :MSTORE(escalarMulBN254_P_x2) + C :MSTORE(escalarMulBN254_P_y1) + D :MSTORE(escalarMulBN254_P_y2) + %BN254_SIX_TIMES_X_SQ :MSTORE(escalarMulBN254_k), CALL(escalarMulBN254) + + + ; 2.3] Check if psi(Q) == [6x²]Q + $ => A :MLOAD(pairingBN254_psi_x1) + $ => B :MLOAD(escalarMulBN254_Q_x1) + $ :EQ, JMPNC(pairingBN254_Q_is_not_in_G2) + + $ => A :MLOAD(pairingBN254_psi_x2) + $ => B :MLOAD(escalarMulBN254_Q_x2) + $ :EQ, JMPNC(pairingBN254_Q_is_not_in_G2) + + $ => A :MLOAD(pairingBN254_psi_y1) + $ => B :MLOAD(escalarMulBN254_Q_y1) + $ :EQ, JMPNC(pairingBN254_Q_is_not_in_G2) + + $ => A :MLOAD(pairingBN254_psi_y2) + $ => B :MLOAD(escalarMulBN254_Q_y2) + $ :EQ, JMPNC(pairingBN254_Q_is_not_in_G2) + +pairingBN254_Miller_loop: + $ => A :MLOAD(pairingBN254_P_x) + $ => B :MLOAD(pairingBN254_P_y) + A :MSTORE(millerLoopBN254_P_x) + B :MSTORE(millerLoopBN254_P_y) + $ => A :MLOAD(pairingBN254_Q_x1) + $ => B :MLOAD(pairingBN254_Q_x2) + $ => C :MLOAD(pairingBN254_Q_y1) + $ => D :MLOAD(pairingBN254_Q_y2) + A :MSTORE(millerLoopBN254_Q_x1) + B :MSTORE(millerLoopBN254_Q_x2) + C :MSTORE(millerLoopBN254_Q_y1) + D :MSTORE(millerLoopBN254_Q_y2), CALL(millerLoopBN254) + $ => A :MLOAD(millerLoopBN254_f11_x) + $ => B :MLOAD(millerLoopBN254_f11_y) + A :MSTORE(pairingBN254_f11_x) + B :MSTORE(pairingBN254_f11_y) + $ => A :MLOAD(millerLoopBN254_f12_x) + $ => B :MLOAD(millerLoopBN254_f12_y) + A :MSTORE(pairingBN254_f12_x) + B :MSTORE(pairingBN254_f12_y) + $ => A :MLOAD(millerLoopBN254_f13_x) + $ => B :MLOAD(millerLoopBN254_f13_y) + A :MSTORE(pairingBN254_f13_x) + B :MSTORE(pairingBN254_f13_y) + $ => A :MLOAD(millerLoopBN254_f21_x) + $ => B :MLOAD(millerLoopBN254_f21_y) + A :MSTORE(pairingBN254_f21_x) + B :MSTORE(pairingBN254_f21_y) + $ => A :MLOAD(millerLoopBN254_f22_x) + $ => B :MLOAD(millerLoopBN254_f22_y) + A :MSTORE(pairingBN254_f22_x) + B :MSTORE(pairingBN254_f22_y) + $ => A :MLOAD(millerLoopBN254_f23_x) + $ => B :MLOAD(millerLoopBN254_f23_y) + A :MSTORE(pairingBN254_f23_x) + B :MSTORE(pairingBN254_f23_y) + + +pairingBN254_final_exponentiation: + $ => A :MLOAD(pairingBN254_f11_x) + $ => B :MLOAD(pairingBN254_f11_y) + A :MSTORE(finalExpBN254_f11_x) + B :MSTORE(finalExpBN254_f11_y) + $ => A :MLOAD(pairingBN254_f12_x) + $ => B :MLOAD(pairingBN254_f12_y) + A :MSTORE(finalExpBN254_f12_x) + B :MSTORE(finalExpBN254_f12_y) + $ => A :MLOAD(pairingBN254_f13_x) + $ => B :MLOAD(pairingBN254_f13_y) + A :MSTORE(finalExpBN254_f13_x) + B :MSTORE(finalExpBN254_f13_y) + $ => A :MLOAD(pairingBN254_f21_x) + $ => B :MLOAD(pairingBN254_f21_y) + A :MSTORE(finalExpBN254_f21_x) + B :MSTORE(finalExpBN254_f21_y) + $ => A :MLOAD(pairingBN254_f22_x) + $ => B :MLOAD(pairingBN254_f22_y) + A :MSTORE(finalExpBN254_f22_x) + B :MSTORE(finalExpBN254_f22_y) + $ => A :MLOAD(pairingBN254_f23_x) + $ => B :MLOAD(pairingBN254_f23_y) + A :MSTORE(finalExpBN254_f23_x) + B :MSTORE(finalExpBN254_f23_y), CALL(finalExpBN254) + $ => A :MLOAD(finalExpBN254_f11_x) + $ => B :MLOAD(finalExpBN254_f11_y) + A :MSTORE(pairingBN254_f11_x) + B :MSTORE(pairingBN254_f11_y) + $ => A :MLOAD(finalExpBN254_f12_x) + $ => B :MLOAD(finalExpBN254_f12_y) + A :MSTORE(pairingBN254_f12_x) + B :MSTORE(pairingBN254_f12_y) + $ => A :MLOAD(finalExpBN254_f13_x) + $ => B :MLOAD(finalExpBN254_f13_y) + A :MSTORE(pairingBN254_f13_x) + B :MSTORE(pairingBN254_f13_y) + $ => A :MLOAD(finalExpBN254_f21_x) + $ => B :MLOAD(finalExpBN254_f21_y) + A :MSTORE(pairingBN254_f21_x) + B :MSTORE(pairingBN254_f21_y) + $ => A :MLOAD(finalExpBN254_f22_x) + $ => B :MLOAD(finalExpBN254_f22_y) + A :MSTORE(pairingBN254_f22_x) + B :MSTORE(pairingBN254_f22_y) + $ => A :MLOAD(finalExpBN254_f23_x) + $ => B :MLOAD(finalExpBN254_f23_y) + A :MSTORE(pairingBN254_f23_x) + B :MSTORE(pairingBN254_f23_y) + + 0 => B :JMP(pairingBN254_end) + +; ERRORS +pairingBN254_Px_too_big: + 1 => B :JMP(pairingBN254_error) + +pairingBN254_Py_too_big: + 2 => B :JMP(pairingBN254_error) + +pairingBN254_Qx1_too_big: + 3 => B :JMP(pairingBN254_error) + +pairingBN254_Qx2_too_big: + 4 => B :JMP(pairingBN254_error) + +pairingBN254_Qy1_too_big: + 5 => B :JMP(pairingBN254_error) + +pairingBN254_Qy2_too_big: + 6 => B :JMP(pairingBN254_error) + +pairingBN254_P_is_not_in_G1: + 7 => B :JMP(pairingBN254_error) + +pairingBN254_Q_is_not_in_G2: + 8 => B :JMP(pairingBN254_error) + +pairingBN254_error: + 0 => A + +pairingBN254_end: + $ => RR :MLOAD(pairingBN254_RR) + :RETURN \ No newline at end of file diff --git a/main/pairings/unused/addFp12BN254.zkasm b/main/pairings/unused/addFp12BN254.zkasm new file mode 100644 index 00000000..2aa760cd --- /dev/null +++ b/main/pairings/unused/addFp12BN254.zkasm @@ -0,0 +1,130 @@ +;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; +;; addFp12BN254: +;; in: (a1 + a2·w),(b1 + b2·w) ∈ Fp12, where ai,bi ∈ Fp6 +;; out: (c1 + c2·w) = (a1+b1) + (a2+b2)·w ∈ Fp12 +;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +VAR GLOBAL addFp12BN254_a11_x +VAR GLOBAL addFp12BN254_a11_y +VAR GLOBAL addFp12BN254_a12_x +VAR GLOBAL addFp12BN254_a12_y +VAR GLOBAL addFp12BN254_a13_x +VAR GLOBAL addFp12BN254_a13_y +VAR GLOBAL addFp12BN254_a21_x +VAR GLOBAL addFp12BN254_a21_y +VAR GLOBAL addFp12BN254_a22_x +VAR GLOBAL addFp12BN254_a22_y +VAR GLOBAL addFp12BN254_a23_x +VAR GLOBAL addFp12BN254_a23_y +VAR GLOBAL addFp12BN254_b11_x +VAR GLOBAL addFp12BN254_b11_y +VAR GLOBAL addFp12BN254_b12_x +VAR GLOBAL addFp12BN254_b12_y +VAR GLOBAL addFp12BN254_b13_x +VAR GLOBAL addFp12BN254_b13_y +VAR GLOBAL addFp12BN254_b21_x +VAR GLOBAL addFp12BN254_b21_y +VAR GLOBAL addFp12BN254_b22_x +VAR GLOBAL addFp12BN254_b22_y +VAR GLOBAL addFp12BN254_b23_x +VAR GLOBAL addFp12BN254_b23_y +VAR GLOBAL addFp12BN254_c11_x +VAR GLOBAL addFp12BN254_c11_y +VAR GLOBAL addFp12BN254_c12_x +VAR GLOBAL addFp12BN254_c12_y +VAR GLOBAL addFp12BN254_c13_x +VAR GLOBAL addFp12BN254_c13_y +VAR GLOBAL addFp12BN254_c21_x +VAR GLOBAL addFp12BN254_c21_y +VAR GLOBAL addFp12BN254_c22_x +VAR GLOBAL addFp12BN254_c22_y +VAR GLOBAL addFp12BN254_c23_x +VAR GLOBAL addFp12BN254_c23_y + +VAR GLOBAL addFp12BN254_RR + +addFp12BN254: + RR :MSTORE(addFp12BN254_RR) + + ; 1] c1 = a1 + b1 + $ => A :MLOAD(addFp12BN254_a11_x) + $ => B :MLOAD(addFp12BN254_a11_y) + A :MSTORE(addFp6BN254_a1_x) + B :MSTORE(addFp6BN254_a1_y) + $ => A :MLOAD(addFp12BN254_a12_x) + $ => B :MLOAD(addFp12BN254_a12_y) + A :MSTORE(addFp6BN254_a2_x) + B :MSTORE(addFp6BN254_a2_y) + $ => A :MLOAD(addFp12BN254_a13_x) + $ => B :MLOAD(addFp12BN254_a13_y) + A :MSTORE(addFp6BN254_a3_x) + B :MSTORE(addFp6BN254_a3_y) + + $ => A :MLOAD(addFp12BN254_b11_x) + $ => B :MLOAD(addFp12BN254_b11_y) + A :MSTORE(addFp6BN254_b1_x) + B :MSTORE(addFp6BN254_b1_y) + $ => A :MLOAD(addFp12BN254_b12_x) + $ => B :MLOAD(addFp12BN254_b12_y) + A :MSTORE(addFp6BN254_b2_x) + B :MSTORE(addFp6BN254_b2_y) + $ => A :MLOAD(addFp12BN254_b13_x) + $ => B :MLOAD(addFp12BN254_b13_y) + A :MSTORE(addFp6BN254_b3_x) + B :MSTORE(addFp6BN254_b3_y), CALL(addFp6BN254) + $ => A :MLOAD(addFp6BN254_c1_x) + $ => B :MLOAD(addFp6BN254_c1_y) + A :MSTORE(addFp12BN254_c11_x) + B :MSTORE(addFp12BN254_c11_y) + $ => A :MLOAD(addFp6BN254_c2_x) + $ => B :MLOAD(addFp6BN254_c2_y) + A :MSTORE(addFp12BN254_c12_x) + B :MSTORE(addFp12BN254_c12_y) + $ => A :MLOAD(addFp6BN254_c3_x) + $ => B :MLOAD(addFp6BN254_c3_y) + A :MSTORE(addFp12BN254_c13_x) + B :MSTORE(addFp12BN254_c13_y) + + ; 2] c2 = a2 + b2 + $ => A :MLOAD(addFp12BN254_a21_x) + $ => B :MLOAD(addFp12BN254_a21_y) + A :MSTORE(addFp6BN254_a1_x) + B :MSTORE(addFp6BN254_a1_y) + $ => A :MLOAD(addFp12BN254_a22_x) + $ => B :MLOAD(addFp12BN254_a22_y) + A :MSTORE(addFp6BN254_a2_x) + B :MSTORE(addFp6BN254_a2_y) + $ => A :MLOAD(addFp12BN254_a23_x) + $ => B :MLOAD(addFp12BN254_a23_y) + A :MSTORE(addFp6BN254_a3_x) + B :MSTORE(addFp6BN254_a3_y) + + $ => A :MLOAD(addFp12BN254_b21_x) + $ => B :MLOAD(addFp12BN254_b21_y) + A :MSTORE(addFp6BN254_b1_x) + B :MSTORE(addFp6BN254_b1_y) + $ => A :MLOAD(addFp12BN254_b22_x) + $ => B :MLOAD(addFp12BN254_b22_y) + A :MSTORE(addFp6BN254_b2_x) + B :MSTORE(addFp6BN254_b2_y) + $ => A :MLOAD(addFp12BN254_b23_x) + $ => B :MLOAD(addFp12BN254_b23_y) + A :MSTORE(addFp6BN254_b3_x) + B :MSTORE(addFp6BN254_b3_y), CALL(addFp6BN254) + $ => A :MLOAD(addFp6BN254_c1_x) + $ => B :MLOAD(addFp6BN254_c1_y) + A :MSTORE(addFp12BN254_c21_x) + B :MSTORE(addFp12BN254_c21_y) + $ => A :MLOAD(addFp6BN254_c2_x) + $ => B :MLOAD(addFp6BN254_c2_y) + A :MSTORE(addFp12BN254_c22_x) + B :MSTORE(addFp12BN254_c22_y) + $ => A :MLOAD(addFp6BN254_c3_x) + $ => B :MLOAD(addFp6BN254_c3_y) + A :MSTORE(addFp12BN254_c23_x) + B :MSTORE(addFp12BN254_c23_y) + + $ => RR :MLOAD(addFp12BN254_RR) + :RETURN \ No newline at end of file diff --git a/main/pairings/unused/expByXCycloFp12BN254.zkasm b/main/pairings/unused/expByXCycloFp12BN254.zkasm new file mode 100644 index 00000000..4fe01f18 --- /dev/null +++ b/main/pairings/unused/expByXCycloFp12BN254.zkasm @@ -0,0 +1,411 @@ +;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; +;; expByXCycloFp12BN254: +;; in: x, (a1 + a2·w) ∈ GΦ6(p²), where ai ∈ Fp6 and x = 4965661367192848881 +;; out: (c1 + c2·w) = (a1 + a2·w)^x ∈ GΦ6(p²) +;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +VAR GLOBAL expByXCycloFp12BN254_a11_x +VAR GLOBAL expByXCycloFp12BN254_a11_y +VAR GLOBAL expByXCycloFp12BN254_a12_x +VAR GLOBAL expByXCycloFp12BN254_a12_y +VAR GLOBAL expByXCycloFp12BN254_a13_x +VAR GLOBAL expByXCycloFp12BN254_a13_y +VAR GLOBAL expByXCycloFp12BN254_a21_x +VAR GLOBAL expByXCycloFp12BN254_a21_y +VAR GLOBAL expByXCycloFp12BN254_a22_x +VAR GLOBAL expByXCycloFp12BN254_a22_y +VAR GLOBAL expByXCycloFp12BN254_a23_x +VAR GLOBAL expByXCycloFp12BN254_a23_y +VAR GLOBAL expByXCycloFp12BN254_c11_x +VAR GLOBAL expByXCycloFp12BN254_c11_y +VAR GLOBAL expByXCycloFp12BN254_c12_x +VAR GLOBAL expByXCycloFp12BN254_c12_y +VAR GLOBAL expByXCycloFp12BN254_c13_x +VAR GLOBAL expByXCycloFp12BN254_c13_y +VAR GLOBAL expByXCycloFp12BN254_c21_x +VAR GLOBAL expByXCycloFp12BN254_c21_y +VAR GLOBAL expByXCycloFp12BN254_c22_x +VAR GLOBAL expByXCycloFp12BN254_c22_y +VAR GLOBAL expByXCycloFp12BN254_c23_x +VAR GLOBAL expByXCycloFp12BN254_c23_y + +VAR GLOBAL expByXCycloFp12BN254_neg_a21_x +VAR GLOBAL expByXCycloFp12BN254_neg_a21_y +VAR GLOBAL expByXCycloFp12BN254_neg_a22_x +VAR GLOBAL expByXCycloFp12BN254_neg_a22_y +VAR GLOBAL expByXCycloFp12BN254_neg_a23_x +VAR GLOBAL expByXCycloFp12BN254_neg_a23_y + +VAR GLOBAL expByXCycloFp12BN254_RR + +expByXCycloFp12BN254: + RR :MSTORE(expByXCycloFp12BN254_RR) + + ; Is a = 0? + 0n => B + $ => A :MLOAD(expByXCycloFp12BN254_a11_x) + $ :EQ, JMPNC(__expByXCycloFp12BN254_a_continue1) + $ => A :MLOAD(expByXCycloFp12BN254_a11_y) + $ :EQ, JMPNC(__expByXCycloFp12BN254_a_continue1) + $ => A :MLOAD(expByXCycloFp12BN254_a12_x) + $ :EQ, JMPNC(__expByXCycloFp12BN254_a_continue1) + $ => A :MLOAD(expByXCycloFp12BN254_a12_y) + $ :EQ, JMPNC(__expByXCycloFp12BN254_a_continue1) + $ => A :MLOAD(expByXCycloFp12BN254_a13_x) + $ :EQ, JMPNC(__expByXCycloFp12BN254_a_continue1) + $ => A :MLOAD(expByXCycloFp12BN254_a13_y) + $ :EQ, JMPNC(__expByXCycloFp12BN254_a_continue1) + $ => A :MLOAD(expByXCycloFp12BN254_a21_x) + $ :EQ, JMPNC(__expByXCycloFp12BN254_a_continue1) + $ => A :MLOAD(expByXCycloFp12BN254_a21_y) + $ :EQ, JMPNC(__expByXCycloFp12BN254_a_continue1) + $ => A :MLOAD(expByXCycloFp12BN254_a22_x) + $ :EQ, JMPNC(__expByXCycloFp12BN254_a_continue1) + $ => A :MLOAD(expByXCycloFp12BN254_a22_y) + $ :EQ, JMPNC(__expByXCycloFp12BN254_a_continue1) + $ => A :MLOAD(expByXCycloFp12BN254_a23_x) + $ :EQ, JMPNC(__expByXCycloFp12BN254_a_continue1) + $ => A :MLOAD(expByXCycloFp12BN254_a23_y) + $ :EQ, JMPC(expByXCycloFp12BN254_a_is_zero) + __expByXCycloFp12BN254_a_continue1: + + ; Is a = 1? + 1n => B + $ => A :MLOAD(expByXCycloFp12BN254_a11_x) + $ :EQ, JMPNC(__expByXCycloFp12BN254_a_continue2) + 0n => B + $ => A :MLOAD(expByXCycloFp12BN254_a11_y) + $ :EQ, JMPNC(__expByXCycloFp12BN254_a_continue2) + $ => A :MLOAD(expByXCycloFp12BN254_a12_x) + $ :EQ, JMPNC(__expByXCycloFp12BN254_a_continue2) + $ => A :MLOAD(expByXCycloFp12BN254_a12_y) + $ :EQ, JMPNC(__expByXCycloFp12BN254_a_continue2) + $ => A :MLOAD(expByXCycloFp12BN254_a13_x) + $ :EQ, JMPNC(__expByXCycloFp12BN254_a_continue2) + $ => A :MLOAD(expByXCycloFp12BN254_a13_y) + $ :EQ, JMPNC(__expByXCycloFp12BN254_a_continue2) + $ => A :MLOAD(expByXCycloFp12BN254_a21_x) + $ :EQ, JMPNC(__expByXCycloFp12BN254_a_continue2) + $ => A :MLOAD(expByXCycloFp12BN254_a21_y) + $ :EQ, JMPNC(__expByXCycloFp12BN254_a_continue2) + $ => A :MLOAD(expByXCycloFp12BN254_a22_x) + $ :EQ, JMPNC(__expByXCycloFp12BN254_a_continue2) + $ => A :MLOAD(expByXCycloFp12BN254_a22_y) + $ :EQ, JMPNC(__expByXCycloFp12BN254_a_continue2) + $ => A :MLOAD(expByXCycloFp12BN254_a23_x) + $ :EQ, JMPNC(__expByXCycloFp12BN254_a_continue2) + $ => A :MLOAD(expByXCycloFp12BN254_a23_y) + $ :EQ, JMPC(expByXCycloFp12BN254_a_is_one) + __expByXCycloFp12BN254_a_continue2: + + 63 => RCX + + ; Initiliaze the loop with c = a and compute the conjugate of a + $ => A :MLOAD(expByXCycloFp12BN254_a11_x) + $ => B :MLOAD(expByXCycloFp12BN254_a11_y) + A :MSTORE(expByXCycloFp12BN254_c11_x) + B :MSTORE(expByXCycloFp12BN254_c11_y) + $ => A :MLOAD(expByXCycloFp12BN254_a12_x) + $ => B :MLOAD(expByXCycloFp12BN254_a12_y) + A :MSTORE(expByXCycloFp12BN254_c12_x) + B :MSTORE(expByXCycloFp12BN254_c12_y) + $ => A :MLOAD(expByXCycloFp12BN254_a13_x) + $ => B :MLOAD(expByXCycloFp12BN254_a13_y) + A :MSTORE(expByXCycloFp12BN254_c13_x) + B :MSTORE(expByXCycloFp12BN254_c13_y) + + %BN254_P => A + $ => B :MLOAD(expByXCycloFp12BN254_a21_x) + B :MSTORE(expByXCycloFp12BN254_c21_x) + $ :SUB, MSTORE(expByXCycloFp12BN254_neg_a21_x) + %BN254_P => A + $ => B :MLOAD(expByXCycloFp12BN254_a21_y) + B :MSTORE(expByXCycloFp12BN254_c21_y) + $ :SUB, MSTORE(expByXCycloFp12BN254_neg_a21_y) + %BN254_P => A + $ => B :MLOAD(expByXCycloFp12BN254_a22_x) + B :MSTORE(expByXCycloFp12BN254_c22_x) + $ :SUB, MSTORE(expByXCycloFp12BN254_neg_a22_x) + %BN254_P => A + $ => B :MLOAD(expByXCycloFp12BN254_a22_y) + B :MSTORE(expByXCycloFp12BN254_c22_y) + $ :SUB, MSTORE(expByXCycloFp12BN254_neg_a22_y) + %BN254_P => A + $ => B :MLOAD(expByXCycloFp12BN254_a23_x) + B :MSTORE(expByXCycloFp12BN254_c23_x) + $ :SUB, MSTORE(expByXCycloFp12BN254_neg_a23_x) + %BN254_P => A + $ => B :MLOAD(expByXCycloFp12BN254_a23_y) + B :MSTORE(expByXCycloFp12BN254_c23_y) + $ :SUB, MSTORE(expByXCycloFp12BN254_neg_a23_y) + + :JMP(expByXCycloFp12BN254_loop) + +expByXCycloFp12BN254_a_is_zero: + ; c = 0 + 0n :MSTORE(expByXCycloFp12BN254_c11_x) + 0n :MSTORE(expByXCycloFp12BN254_c11_y) + 0n :MSTORE(expByXCycloFp12BN254_c12_x) + 0n :MSTORE(expByXCycloFp12BN254_c12_y) + 0n :MSTORE(expByXCycloFp12BN254_c13_x) + 0n :MSTORE(expByXCycloFp12BN254_c13_y) + 0n :MSTORE(expByXCycloFp12BN254_c21_x) + 0n :MSTORE(expByXCycloFp12BN254_c21_y) + 0n :MSTORE(expByXCycloFp12BN254_c22_x) + 0n :MSTORE(expByXCycloFp12BN254_c22_y) + 0n :MSTORE(expByXCycloFp12BN254_c23_x) + 0n :MSTORE(expByXCycloFp12BN254_c23_y) + + :JMP(expByXCycloFp12BN254_end) + +expByXCycloFp12BN254_a_is_one: + ; c = 1 + 1n :MSTORE(expByXCycloFp12BN254_c11_x) + 0n :MSTORE(expByXCycloFp12BN254_c11_y) + 0n :MSTORE(expByXCycloFp12BN254_c12_x) + 0n :MSTORE(expByXCycloFp12BN254_c12_y) + 0n :MSTORE(expByXCycloFp12BN254_c13_x) + 0n :MSTORE(expByXCycloFp12BN254_c13_y) + 0n :MSTORE(expByXCycloFp12BN254_c21_x) + 0n :MSTORE(expByXCycloFp12BN254_c21_y) + 0n :MSTORE(expByXCycloFp12BN254_c22_x) + 0n :MSTORE(expByXCycloFp12BN254_c22_y) + 0n :MSTORE(expByXCycloFp12BN254_c23_x) + 0n :MSTORE(expByXCycloFp12BN254_c23_y) + + :JMP(expByXCycloFp12BN254_end) + +expByXCycloFp12BN254_loop: + RCX - 1 => RCX :JMPZ(expByXCycloFp12BN254_end) + + ; We always square: c = c^2 + $ => A :MLOAD(expByXCycloFp12BN254_c11_x) + $ => B :MLOAD(expByXCycloFp12BN254_c11_y) + A :MSTORE(squareCycloFp12BN254_a11_x) + B :MSTORE(squareCycloFp12BN254_a11_y) + $ => A :MLOAD(expByXCycloFp12BN254_c12_x) + $ => B :MLOAD(expByXCycloFp12BN254_c12_y) + A :MSTORE(squareCycloFp12BN254_a12_x) + B :MSTORE(squareCycloFp12BN254_a12_y) + $ => A :MLOAD(expByXCycloFp12BN254_c13_x) + $ => B :MLOAD(expByXCycloFp12BN254_c13_y) + A :MSTORE(squareCycloFp12BN254_a13_x) + B :MSTORE(squareCycloFp12BN254_a13_y) + $ => A :MLOAD(expByXCycloFp12BN254_c21_x) + $ => B :MLOAD(expByXCycloFp12BN254_c21_y) + A :MSTORE(squareCycloFp12BN254_a21_x) + B :MSTORE(squareCycloFp12BN254_a21_y) + $ => A :MLOAD(expByXCycloFp12BN254_c22_x) + $ => B :MLOAD(expByXCycloFp12BN254_c22_y) + A :MSTORE(squareCycloFp12BN254_a22_x) + B :MSTORE(squareCycloFp12BN254_a22_y) + $ => A :MLOAD(expByXCycloFp12BN254_c23_x) + $ => B :MLOAD(expByXCycloFp12BN254_c23_y) + A :MSTORE(squareCycloFp12BN254_a23_x) + B :MSTORE(squareCycloFp12BN254_a23_y), CALL(squareCycloFp12BN254) + + ; c = c^2 + $ => A :MLOAD(squareCycloFp12BN254_c11_x) + $ => B :MLOAD(squareCycloFp12BN254_c11_y) + A :MSTORE(expByXCycloFp12BN254_c11_x) + B :MSTORE(expByXCycloFp12BN254_c11_y) + $ => A :MLOAD(squareCycloFp12BN254_c12_x) + $ => B :MLOAD(squareCycloFp12BN254_c12_y) + A :MSTORE(expByXCycloFp12BN254_c12_x) + B :MSTORE(expByXCycloFp12BN254_c12_y) + $ => A :MLOAD(squareCycloFp12BN254_c13_x) + $ => B :MLOAD(squareCycloFp12BN254_c13_y) + A :MSTORE(expByXCycloFp12BN254_c13_x) + B :MSTORE(expByXCycloFp12BN254_c13_y) + $ => A :MLOAD(squareCycloFp12BN254_c21_x) + $ => B :MLOAD(squareCycloFp12BN254_c21_y) + A :MSTORE(expByXCycloFp12BN254_c21_x) + B :MSTORE(expByXCycloFp12BN254_c21_y) + $ => A :MLOAD(squareCycloFp12BN254_c22_x) + $ => B :MLOAD(squareCycloFp12BN254_c22_y) + A :MSTORE(expByXCycloFp12BN254_c22_x) + B :MSTORE(expByXCycloFp12BN254_c22_y) + $ => A :MLOAD(squareCycloFp12BN254_c23_x) + $ => B :MLOAD(squareCycloFp12BN254_c23_y) + A :MSTORE(expByXCycloFp12BN254_c23_x) + B :MSTORE(expByXCycloFp12BN254_c23_y) + + ; For the following, keep in mind that a ∈ GΦ6(p²) and therefore + ; computing the conjugate is the same as computing the inverse. + + ; We check if the MSB b of x is either 1, 0 or -1. + ; - If b == 1, we should multiply a to c. + ; - If b == -1, we should multiply a̅ to c. + + RCX-1 => RR + :CALL(@xPseudoBinDecompBN254 + RR) + + ; if bit = -1, then multiply by conjugate + B :JMPN(expByXCycloFp12BN254_multiply_by_conjugate) + + ; if bit = 0, then repeat + B :JMPZ(expByXCycloFp12BN254_loop) + + ; else, multiply by a + +expByXCycloFp12BN254_multiply: + ; c·a + $ => A :MLOAD(expByXCycloFp12BN254_a11_x) + $ => B :MLOAD(expByXCycloFp12BN254_a11_y) + A :MSTORE(mulFp12BN254_a11_x) + B :MSTORE(mulFp12BN254_a11_y) + $ => A :MLOAD(expByXCycloFp12BN254_a12_x) + $ => B :MLOAD(expByXCycloFp12BN254_a12_y) + A :MSTORE(mulFp12BN254_a12_x) + B :MSTORE(mulFp12BN254_a12_y) + $ => A :MLOAD(expByXCycloFp12BN254_a13_x) + $ => B :MLOAD(expByXCycloFp12BN254_a13_y) + A :MSTORE(mulFp12BN254_a13_x) + B :MSTORE(mulFp12BN254_a13_y) + $ => A :MLOAD(expByXCycloFp12BN254_a21_x) + $ => B :MLOAD(expByXCycloFp12BN254_a21_y) + A :MSTORE(mulFp12BN254_a21_x) + B :MSTORE(mulFp12BN254_a21_y) + $ => A :MLOAD(expByXCycloFp12BN254_a22_x) + $ => B :MLOAD(expByXCycloFp12BN254_a22_y) + A :MSTORE(mulFp12BN254_a22_x) + B :MSTORE(mulFp12BN254_a22_y) + $ => A :MLOAD(expByXCycloFp12BN254_a23_x) + $ => B :MLOAD(expByXCycloFp12BN254_a23_y) + A :MSTORE(mulFp12BN254_a23_x) + B :MSTORE(mulFp12BN254_a23_y) + $ => A :MLOAD(expByXCycloFp12BN254_c11_x) + $ => B :MLOAD(expByXCycloFp12BN254_c11_y) + A :MSTORE(mulFp12BN254_b11_x) + B :MSTORE(mulFp12BN254_b11_y) + $ => A :MLOAD(expByXCycloFp12BN254_c12_x) + $ => B :MLOAD(expByXCycloFp12BN254_c12_y) + A :MSTORE(mulFp12BN254_b12_x) + B :MSTORE(mulFp12BN254_b12_y) + $ => A :MLOAD(expByXCycloFp12BN254_c13_x) + $ => B :MLOAD(expByXCycloFp12BN254_c13_y) + A :MSTORE(mulFp12BN254_b13_x) + B :MSTORE(mulFp12BN254_b13_y) + $ => A :MLOAD(expByXCycloFp12BN254_c21_x) + $ => B :MLOAD(expByXCycloFp12BN254_c21_y) + A :MSTORE(mulFp12BN254_b21_x) + B :MSTORE(mulFp12BN254_b21_y) + $ => A :MLOAD(expByXCycloFp12BN254_c22_x) + $ => B :MLOAD(expByXCycloFp12BN254_c22_y) + A :MSTORE(mulFp12BN254_b22_x) + B :MSTORE(mulFp12BN254_b22_y) + $ => A :MLOAD(expByXCycloFp12BN254_c23_x) + $ => B :MLOAD(expByXCycloFp12BN254_c23_y) + A :MSTORE(mulFp12BN254_b23_x) + B :MSTORE(mulFp12BN254_b23_y), CALL(mulFp12BN254) + + ; c = c·a + $ => A :MLOAD(mulFp12BN254_c11_x) + $ => B :MLOAD(mulFp12BN254_c11_y) + A :MSTORE(expByXCycloFp12BN254_c11_x) + B :MSTORE(expByXCycloFp12BN254_c11_y) + $ => A :MLOAD(mulFp12BN254_c12_x) + $ => B :MLOAD(mulFp12BN254_c12_y) + A :MSTORE(expByXCycloFp12BN254_c12_x) + B :MSTORE(expByXCycloFp12BN254_c12_y) + $ => A :MLOAD(mulFp12BN254_c13_x) + $ => B :MLOAD(mulFp12BN254_c13_y) + A :MSTORE(expByXCycloFp12BN254_c13_x) + B :MSTORE(expByXCycloFp12BN254_c13_y) + $ => A :MLOAD(mulFp12BN254_c21_x) + $ => B :MLOAD(mulFp12BN254_c21_y) + A :MSTORE(expByXCycloFp12BN254_c21_x) + B :MSTORE(expByXCycloFp12BN254_c21_y) + $ => A :MLOAD(mulFp12BN254_c22_x) + $ => B :MLOAD(mulFp12BN254_c22_y) + A :MSTORE(expByXCycloFp12BN254_c22_x) + B :MSTORE(expByXCycloFp12BN254_c22_y) + $ => A :MLOAD(mulFp12BN254_c23_x) + $ => B :MLOAD(mulFp12BN254_c23_y) + A :MSTORE(expByXCycloFp12BN254_c23_x) + B :MSTORE(expByXCycloFp12BN254_c23_y) + :JMP(expByXCycloFp12BN254_loop) + +expByXCycloFp12BN254_multiply_by_conjugate: + ; c·a̅ + $ => A :MLOAD(expByXCycloFp12BN254_a11_x) + $ => B :MLOAD(expByXCycloFp12BN254_a11_y) + A :MSTORE(mulFp12BN254_a11_x) + B :MSTORE(mulFp12BN254_a11_y) + $ => A :MLOAD(expByXCycloFp12BN254_a12_x) + $ => B :MLOAD(expByXCycloFp12BN254_a12_y) + A :MSTORE(mulFp12BN254_a12_x) + B :MSTORE(mulFp12BN254_a12_y) + $ => A :MLOAD(expByXCycloFp12BN254_a13_x) + $ => B :MLOAD(expByXCycloFp12BN254_a13_y) + A :MSTORE(mulFp12BN254_a13_x) + B :MSTORE(mulFp12BN254_a13_y) + $ => A :MLOAD(expByXCycloFp12BN254_neg_a21_x) + $ => B :MLOAD(expByXCycloFp12BN254_neg_a21_y) + A :MSTORE(mulFp12BN254_a21_x) + B :MSTORE(mulFp12BN254_a21_y) + $ => A :MLOAD(expByXCycloFp12BN254_neg_a22_x) + $ => B :MLOAD(expByXCycloFp12BN254_neg_a22_y) + A :MSTORE(mulFp12BN254_a22_x) + B :MSTORE(mulFp12BN254_a22_y) + $ => A :MLOAD(expByXCycloFp12BN254_neg_a23_x) + $ => B :MLOAD(expByXCycloFp12BN254_neg_a23_y) + A :MSTORE(mulFp12BN254_a23_x) + B :MSTORE(mulFp12BN254_a23_y) + $ => A :MLOAD(expByXCycloFp12BN254_c11_x) + $ => B :MLOAD(expByXCycloFp12BN254_c11_y) + A :MSTORE(mulFp12BN254_b11_x) + B :MSTORE(mulFp12BN254_b11_y) + $ => A :MLOAD(expByXCycloFp12BN254_c12_x) + $ => B :MLOAD(expByXCycloFp12BN254_c12_y) + A :MSTORE(mulFp12BN254_b12_x) + B :MSTORE(mulFp12BN254_b12_y) + $ => A :MLOAD(expByXCycloFp12BN254_c13_x) + $ => B :MLOAD(expByXCycloFp12BN254_c13_y) + A :MSTORE(mulFp12BN254_b13_x) + B :MSTORE(mulFp12BN254_b13_y) + $ => A :MLOAD(expByXCycloFp12BN254_c21_x) + $ => B :MLOAD(expByXCycloFp12BN254_c21_y) + A :MSTORE(mulFp12BN254_b21_x) + B :MSTORE(mulFp12BN254_b21_y) + $ => A :MLOAD(expByXCycloFp12BN254_c22_x) + $ => B :MLOAD(expByXCycloFp12BN254_c22_y) + A :MSTORE(mulFp12BN254_b22_x) + B :MSTORE(mulFp12BN254_b22_y) + $ => A :MLOAD(expByXCycloFp12BN254_c23_x) + $ => B :MLOAD(expByXCycloFp12BN254_c23_y) + A :MSTORE(mulFp12BN254_b23_x) + B :MSTORE(mulFp12BN254_b23_y), CALL(mulFp12BN254) + + ; c = c·a̅ + $ => A :MLOAD(mulFp12BN254_c11_x) + $ => B :MLOAD(mulFp12BN254_c11_y) + A :MSTORE(expByXCycloFp12BN254_c11_x) + B :MSTORE(expByXCycloFp12BN254_c11_y) + $ => A :MLOAD(mulFp12BN254_c12_x) + $ => B :MLOAD(mulFp12BN254_c12_y) + A :MSTORE(expByXCycloFp12BN254_c12_x) + B :MSTORE(expByXCycloFp12BN254_c12_y) + $ => A :MLOAD(mulFp12BN254_c13_x) + $ => B :MLOAD(mulFp12BN254_c13_y) + A :MSTORE(expByXCycloFp12BN254_c13_x) + B :MSTORE(expByXCycloFp12BN254_c13_y) + $ => A :MLOAD(mulFp12BN254_c21_x) + $ => B :MLOAD(mulFp12BN254_c21_y) + A :MSTORE(expByXCycloFp12BN254_c21_x) + B :MSTORE(expByXCycloFp12BN254_c21_y) + $ => A :MLOAD(mulFp12BN254_c22_x) + $ => B :MLOAD(mulFp12BN254_c22_y) + A :MSTORE(expByXCycloFp12BN254_c22_x) + B :MSTORE(expByXCycloFp12BN254_c22_y) + $ => A :MLOAD(mulFp12BN254_c23_x) + $ => B :MLOAD(mulFp12BN254_c23_y) + A :MSTORE(expByXCycloFp12BN254_c23_x) + B :MSTORE(expByXCycloFp12BN254_c23_y) + :JMP(expByXCycloFp12BN254_loop) + +expByXCycloFp12BN254_end: + $ => RR :MLOAD(expByXCycloFp12BN254_RR) + :RETURN \ No newline at end of file diff --git a/main/pairings/unused/expFp12BN254.zkasm b/main/pairings/unused/expFp12BN254.zkasm new file mode 100644 index 00000000..b6c5e463 --- /dev/null +++ b/main/pairings/unused/expFp12BN254.zkasm @@ -0,0 +1,333 @@ +;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; +;; expFp12BN254: +;; in: e, (a1 + a2·w) ∈ Fp12, where e ∈ [0,p¹²-2] ai ∈ Fp6 +;; out: (a1 + a2·w)^e = (c1 + c2·w) ∈ Fp12 +;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +; Comment: We use this algorithm with a very small e (i.e., it fits in 32 bits), but it must be adpated to use it with a bigger e +; Comment: In some cases, we can speed this algorithm up by using pseudobinary encoding instead of binary encoding + +VAR GLOBAL expFp12BN254_e +VAR GLOBAL expFp12BN254_a11_x +VAR GLOBAL expFp12BN254_a11_y +VAR GLOBAL expFp12BN254_a12_x +VAR GLOBAL expFp12BN254_a12_y +VAR GLOBAL expFp12BN254_a13_x +VAR GLOBAL expFp12BN254_a13_y +VAR GLOBAL expFp12BN254_a21_x +VAR GLOBAL expFp12BN254_a21_y +VAR GLOBAL expFp12BN254_a22_x +VAR GLOBAL expFp12BN254_a22_y +VAR GLOBAL expFp12BN254_a23_x +VAR GLOBAL expFp12BN254_a23_y +VAR GLOBAL expFp12BN254_c11_x +VAR GLOBAL expFp12BN254_c11_y +VAR GLOBAL expFp12BN254_c12_x +VAR GLOBAL expFp12BN254_c12_y +VAR GLOBAL expFp12BN254_c13_x +VAR GLOBAL expFp12BN254_c13_y +VAR GLOBAL expFp12BN254_c21_x +VAR GLOBAL expFp12BN254_c21_y +VAR GLOBAL expFp12BN254_c22_x +VAR GLOBAL expFp12BN254_c22_y +VAR GLOBAL expFp12BN254_c23_x +VAR GLOBAL expFp12BN254_c23_y + +VAR GLOBAL expFp12BN254_RR + +expFp12BN254: + RR :MSTORE(expFp12BN254_RR) + + ; Trivial cases: + ; 1] Is a = 0? + 0n => B + $ => A :MLOAD(expFp12BN254_a11_x) + $ :EQ, JMPNC(__expFp12BN254_a_continue1) + $ => A :MLOAD(expFp12BN254_a11_y) + $ :EQ, JMPNC(__expFp12BN254_a_continue1) + $ => A :MLOAD(expFp12BN254_a12_x) + $ :EQ, JMPNC(__expFp12BN254_a_continue1) + $ => A :MLOAD(expFp12BN254_a12_y) + $ :EQ, JMPNC(__expFp12BN254_a_continue1) + $ => A :MLOAD(expFp12BN254_a13_x) + $ :EQ, JMPNC(__expFp12BN254_a_continue1) + $ => A :MLOAD(expFp12BN254_a13_y) + $ :EQ, JMPNC(__expFp12BN254_a_continue1) + $ => A :MLOAD(expFp12BN254_a21_x) + $ :EQ, JMPNC(__expFp12BN254_a_continue1) + $ => A :MLOAD(expFp12BN254_a21_y) + $ :EQ, JMPNC(__expFp12BN254_a_continue1) + $ => A :MLOAD(expFp12BN254_a22_x) + $ :EQ, JMPNC(__expFp12BN254_a_continue1) + $ => A :MLOAD(expFp12BN254_a22_y) + $ :EQ, JMPNC(__expFp12BN254_a_continue1) + $ => A :MLOAD(expFp12BN254_a23_x) + $ :EQ, JMPNC(__expFp12BN254_a_continue1) + $ => A :MLOAD(expFp12BN254_a23_y) + $ :EQ, JMPC(expFp12BN254_a_is_zero) + __expFp12BN254_a_continue1: + + ; 2] Is a = 1? + 1n => B + $ => A :MLOAD(expFp12BN254_a11_x) + $ :EQ, JMPNC(__expFp12BN254_a_continue2) + 0n => B + $ => A :MLOAD(expFp12BN254_a11_y) + $ :EQ, JMPNC(__expFp12BN254_a_continue2) + $ => A :MLOAD(expFp12BN254_a12_x) + $ :EQ, JMPNC(__expFp12BN254_a_continue2) + $ => A :MLOAD(expFp12BN254_a12_y) + $ :EQ, JMPNC(__expFp12BN254_a_continue2) + $ => A :MLOAD(expFp12BN254_a13_x) + $ :EQ, JMPNC(__expFp12BN254_a_continue2) + $ => A :MLOAD(expFp12BN254_a13_y) + $ :EQ, JMPNC(__expFp12BN254_a_continue2) + $ => A :MLOAD(expFp12BN254_a21_x) + $ :EQ, JMPNC(__expFp12BN254_a_continue2) + $ => A :MLOAD(expFp12BN254_a21_y) + $ :EQ, JMPNC(__expFp12BN254_a_continue2) + $ => A :MLOAD(expFp12BN254_a22_x) + $ :EQ, JMPNC(__expFp12BN254_a_continue2) + $ => A :MLOAD(expFp12BN254_a22_y) + $ :EQ, JMPNC(__expFp12BN254_a_continue2) + $ => A :MLOAD(expFp12BN254_a23_x) + $ :EQ, JMPNC(__expFp12BN254_a_continue2) + $ => A :MLOAD(expFp12BN254_a23_y) + $ :EQ, JMPC(expFp12BN254_a_is_one) + __expFp12BN254_a_continue2: + + ; 3] Is e = 0? + $ => A :MLOAD(expFp12BN254_e) + 0n => B + $ :EQ, JMPC(expFp12BN254_e_is_zero) + + 257 => RCX + + $ => A :MLOAD(expFp12BN254_a11_x) + $ => B :MLOAD(expFp12BN254_a11_y) + A :MSTORE(expFp12BN254_c11_x) + B :MSTORE(expFp12BN254_c11_y) + $ => A :MLOAD(expFp12BN254_a12_x) + $ => B :MLOAD(expFp12BN254_a12_y) + A :MSTORE(expFp12BN254_c12_x) + B :MSTORE(expFp12BN254_c12_y) + $ => A :MLOAD(expFp12BN254_a13_x) + $ => B :MLOAD(expFp12BN254_a13_y) + A :MSTORE(expFp12BN254_c13_x) + B :MSTORE(expFp12BN254_c13_y) + $ => A :MLOAD(expFp12BN254_a21_x) + $ => B :MLOAD(expFp12BN254_a21_y) + A :MSTORE(expFp12BN254_c21_x) + B :MSTORE(expFp12BN254_c21_y) + $ => A :MLOAD(expFp12BN254_a22_x) + $ => B :MLOAD(expFp12BN254_a22_y) + A :MSTORE(expFp12BN254_c22_x) + B :MSTORE(expFp12BN254_c22_y) + $ => A :MLOAD(expFp12BN254_a23_x) + $ => B :MLOAD(expFp12BN254_a23_y) + A :MSTORE(expFp12BN254_c23_x) + B :MSTORE(expFp12BN254_c23_y) + + :JMP(expFp12BN254_find_MSB_e) + +expFp12BN254_a_is_zero: + ; I define 0^0 = 0 for simplicity + 0n :MSTORE(expFp12BN254_c11_x) + 0n :MSTORE(expFp12BN254_c11_y) + 0n :MSTORE(expFp12BN254_c12_x) + 0n :MSTORE(expFp12BN254_c12_y) + 0n :MSTORE(expFp12BN254_c13_x) + 0n :MSTORE(expFp12BN254_c13_y) + 0n :MSTORE(expFp12BN254_c21_x) + 0n :MSTORE(expFp12BN254_c21_y) + 0n :MSTORE(expFp12BN254_c22_x) + 0n :MSTORE(expFp12BN254_c22_y) + 0n :MSTORE(expFp12BN254_c23_x) + 0n :MSTORE(expFp12BN254_c23_y) + + :JMP(expFp12BN254_end) + +expFp12BN254_a_is_one: + ; 1^e = 1 + 1n :MSTORE(expFp12BN254_c11_x) + 0n :MSTORE(expFp12BN254_c11_y) + 0n :MSTORE(expFp12BN254_c12_x) + 0n :MSTORE(expFp12BN254_c12_y) + 0n :MSTORE(expFp12BN254_c13_x) + 0n :MSTORE(expFp12BN254_c13_y) + 0n :MSTORE(expFp12BN254_c21_x) + 0n :MSTORE(expFp12BN254_c21_y) + 0n :MSTORE(expFp12BN254_c22_x) + 0n :MSTORE(expFp12BN254_c22_y) + 0n :MSTORE(expFp12BN254_c23_x) + 0n :MSTORE(expFp12BN254_c23_y) + + :JMP(expFp12BN254_end) + +expFp12BN254_e_is_zero: + ; a^0 = 1 + 1n :MSTORE(expFp12BN254_c11_x) + 0n :MSTORE(expFp12BN254_c11_y) + 0n :MSTORE(expFp12BN254_c12_x) + 0n :MSTORE(expFp12BN254_c12_y) + 0n :MSTORE(expFp12BN254_c13_x) + 0n :MSTORE(expFp12BN254_c13_y) + 0n :MSTORE(expFp12BN254_c21_x) + 0n :MSTORE(expFp12BN254_c21_y) + 0n :MSTORE(expFp12BN254_c22_x) + 0n :MSTORE(expFp12BN254_c22_y) + 0n :MSTORE(expFp12BN254_c23_x) + 0n :MSTORE(expFp12BN254_c23_y) + + :JMP(expFp12BN254_end) + +expFp12BN254_find_MSB_e: + RCX - 1 => RCX + $ => A,B :MLOAD(expFp12BN254_e) + ; E = 2A + $ => E :ADD,MSTORE(expFp12BN254_e), JMPNC(expFp12BN254_find_MSB_e) + + +expFp12BN254_loop: + RCX - 1 => RCX :JMPZ(expFp12BN254_end) + + ; We always square: c = c^2 + $ => A :MLOAD(expFp12BN254_c11_x) + $ => B :MLOAD(expFp12BN254_c11_y) + A :MSTORE(squareFp12BN254_a11_x) + B :MSTORE(squareFp12BN254_a11_y) + $ => A :MLOAD(expFp12BN254_c12_x) + $ => B :MLOAD(expFp12BN254_c12_y) + A :MSTORE(squareFp12BN254_a12_x) + B :MSTORE(squareFp12BN254_a12_y) + $ => A :MLOAD(expFp12BN254_c13_x) + $ => B :MLOAD(expFp12BN254_c13_y) + A :MSTORE(squareFp12BN254_a13_x) + B :MSTORE(squareFp12BN254_a13_y) + $ => A :MLOAD(expFp12BN254_c21_x) + $ => B :MLOAD(expFp12BN254_c21_y) + A :MSTORE(squareFp12BN254_a21_x) + B :MSTORE(squareFp12BN254_a21_y) + $ => A :MLOAD(expFp12BN254_c22_x) + $ => B :MLOAD(expFp12BN254_c22_y) + A :MSTORE(squareFp12BN254_a22_x) + B :MSTORE(squareFp12BN254_a22_y) + $ => A :MLOAD(expFp12BN254_c23_x) + $ => B :MLOAD(expFp12BN254_c23_y) + A :MSTORE(squareFp12BN254_a23_x) + B :MSTORE(squareFp12BN254_a23_y), CALL(squareFp12BN254) + + ; c = c^2 + $ => A :MLOAD(squareFp12BN254_c11_x) + $ => B :MLOAD(squareFp12BN254_c11_y) + A :MSTORE(expFp12BN254_c11_x) + B :MSTORE(expFp12BN254_c11_y) + $ => A :MLOAD(squareFp12BN254_c12_x) + $ => B :MLOAD(squareFp12BN254_c12_y) + A :MSTORE(expFp12BN254_c12_x) + B :MSTORE(expFp12BN254_c12_y) + $ => A :MLOAD(squareFp12BN254_c13_x) + $ => B :MLOAD(squareFp12BN254_c13_y) + A :MSTORE(expFp12BN254_c13_x) + B :MSTORE(expFp12BN254_c13_y) + $ => A :MLOAD(squareFp12BN254_c21_x) + $ => B :MLOAD(squareFp12BN254_c21_y) + A :MSTORE(expFp12BN254_c21_x) + B :MSTORE(expFp12BN254_c21_y) + $ => A :MLOAD(squareFp12BN254_c22_x) + $ => B :MLOAD(squareFp12BN254_c22_y) + A :MSTORE(expFp12BN254_c22_x) + B :MSTORE(expFp12BN254_c22_y) + $ => A :MLOAD(squareFp12BN254_c23_x) + $ => B :MLOAD(squareFp12BN254_c23_y) + A :MSTORE(expFp12BN254_c23_x) + B :MSTORE(expFp12BN254_c23_y) + + ; 2] We check if the MSB b of e is either 1 or 0. If b==1, we should multiply a to c. + ; Then, update the value of e. + $ => A,B :MLOAD(expFp12BN254_e) + ; E = 2A + $ => E :ADD,MSTORE(expFp12BN254_e), JMPNC(expFp12BN254_loop) + +expFp12BN254_multiply: + $ => A :MLOAD(expFp12BN254_a11_x) + $ => B :MLOAD(expFp12BN254_a11_y) + A :MSTORE(mulFp12BN254_a11_x) + B :MSTORE(mulFp12BN254_a11_y) + $ => A :MLOAD(expFp12BN254_a12_x) + $ => B :MLOAD(expFp12BN254_a12_y) + A :MSTORE(mulFp12BN254_a12_x) + B :MSTORE(mulFp12BN254_a12_y) + $ => A :MLOAD(expFp12BN254_a13_x) + $ => B :MLOAD(expFp12BN254_a13_y) + A :MSTORE(mulFp12BN254_a13_x) + B :MSTORE(mulFp12BN254_a13_y) + $ => A :MLOAD(expFp12BN254_a21_x) + $ => B :MLOAD(expFp12BN254_a21_y) + A :MSTORE(mulFp12BN254_a21_x) + B :MSTORE(mulFp12BN254_a21_y) + $ => A :MLOAD(expFp12BN254_a22_x) + $ => B :MLOAD(expFp12BN254_a22_y) + A :MSTORE(mulFp12BN254_a22_x) + B :MSTORE(mulFp12BN254_a22_y) + $ => A :MLOAD(expFp12BN254_a23_x) + $ => B :MLOAD(expFp12BN254_a23_y) + A :MSTORE(mulFp12BN254_a23_x) + B :MSTORE(mulFp12BN254_a23_y) + $ => A :MLOAD(expFp12BN254_c11_x) + $ => B :MLOAD(expFp12BN254_c11_y) + A :MSTORE(mulFp12BN254_b11_x) + B :MSTORE(mulFp12BN254_b11_y) + $ => A :MLOAD(expFp12BN254_c12_x) + $ => B :MLOAD(expFp12BN254_c12_y) + A :MSTORE(mulFp12BN254_b12_x) + B :MSTORE(mulFp12BN254_b12_y) + $ => A :MLOAD(expFp12BN254_c13_x) + $ => B :MLOAD(expFp12BN254_c13_y) + A :MSTORE(mulFp12BN254_b13_x) + B :MSTORE(mulFp12BN254_b13_y) + $ => A :MLOAD(expFp12BN254_c21_x) + $ => B :MLOAD(expFp12BN254_c21_y) + A :MSTORE(mulFp12BN254_b21_x) + B :MSTORE(mulFp12BN254_b21_y) + $ => A :MLOAD(expFp12BN254_c22_x) + $ => B :MLOAD(expFp12BN254_c22_y) + A :MSTORE(mulFp12BN254_b22_x) + B :MSTORE(mulFp12BN254_b22_y) + $ => A :MLOAD(expFp12BN254_c23_x) + $ => B :MLOAD(expFp12BN254_c23_y) + A :MSTORE(mulFp12BN254_b23_x) + B :MSTORE(mulFp12BN254_b23_y), CALL(mulFp12BN254) + + ; c = c·a + $ => A :MLOAD(mulFp12BN254_c11_x) + $ => B :MLOAD(mulFp12BN254_c11_y) + A :MSTORE(expFp12BN254_c11_x) + B :MSTORE(expFp12BN254_c11_y) + $ => A :MLOAD(mulFp12BN254_c12_x) + $ => B :MLOAD(mulFp12BN254_c12_y) + A :MSTORE(expFp12BN254_c12_x) + B :MSTORE(expFp12BN254_c12_y) + $ => A :MLOAD(mulFp12BN254_c13_x) + $ => B :MLOAD(mulFp12BN254_c13_y) + A :MSTORE(expFp12BN254_c13_x) + B :MSTORE(expFp12BN254_c13_y) + $ => A :MLOAD(mulFp12BN254_c21_x) + $ => B :MLOAD(mulFp12BN254_c21_y) + A :MSTORE(expFp12BN254_c21_x) + B :MSTORE(expFp12BN254_c21_y) + $ => A :MLOAD(mulFp12BN254_c22_x) + $ => B :MLOAD(mulFp12BN254_c22_y) + A :MSTORE(expFp12BN254_c22_x) + B :MSTORE(expFp12BN254_c22_y) + $ => A :MLOAD(mulFp12BN254_c23_x) + $ => B :MLOAD(mulFp12BN254_c23_y) + A :MSTORE(expFp12BN254_c23_x) + B :MSTORE(expFp12BN254_c23_y) + :JMP(expFp12BN254_loop) + +expFp12BN254_end: + $ => RR :MLOAD(expFp12BN254_RR) + :RETURN \ No newline at end of file diff --git a/main/pairings/unused/subFp12BN254.zkasm b/main/pairings/unused/subFp12BN254.zkasm new file mode 100644 index 00000000..92c8b830 --- /dev/null +++ b/main/pairings/unused/subFp12BN254.zkasm @@ -0,0 +1,130 @@ +;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; +;; subFp12BN254: +;; in: (a1 + a2·w),(b1 + b2·w) ∈ Fp12, where ai,bi ∈ Fp6 +;; out: (c1 + c2·w) = (a1-b1) + (a2-b2)·w ∈ Fp12 +;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +VAR GLOBAL subFp12BN254_a11_x +VAR GLOBAL subFp12BN254_a11_y +VAR GLOBAL subFp12BN254_a12_x +VAR GLOBAL subFp12BN254_a12_y +VAR GLOBAL subFp12BN254_a13_x +VAR GLOBAL subFp12BN254_a13_y +VAR GLOBAL subFp12BN254_a21_x +VAR GLOBAL subFp12BN254_a21_y +VAR GLOBAL subFp12BN254_a22_x +VAR GLOBAL subFp12BN254_a22_y +VAR GLOBAL subFp12BN254_a23_x +VAR GLOBAL subFp12BN254_a23_y +VAR GLOBAL subFp12BN254_b11_x +VAR GLOBAL subFp12BN254_b11_y +VAR GLOBAL subFp12BN254_b12_x +VAR GLOBAL subFp12BN254_b12_y +VAR GLOBAL subFp12BN254_b13_x +VAR GLOBAL subFp12BN254_b13_y +VAR GLOBAL subFp12BN254_b21_x +VAR GLOBAL subFp12BN254_b21_y +VAR GLOBAL subFp12BN254_b22_x +VAR GLOBAL subFp12BN254_b22_y +VAR GLOBAL subFp12BN254_b23_x +VAR GLOBAL subFp12BN254_b23_y +VAR GLOBAL subFp12BN254_c11_x +VAR GLOBAL subFp12BN254_c11_y +VAR GLOBAL subFp12BN254_c12_x +VAR GLOBAL subFp12BN254_c12_y +VAR GLOBAL subFp12BN254_c13_x +VAR GLOBAL subFp12BN254_c13_y +VAR GLOBAL subFp12BN254_c21_x +VAR GLOBAL subFp12BN254_c21_y +VAR GLOBAL subFp12BN254_c22_x +VAR GLOBAL subFp12BN254_c22_y +VAR GLOBAL subFp12BN254_c23_x +VAR GLOBAL subFp12BN254_c23_y + +VAR GLOBAL subFp12BN254_RR + +subFp12BN254: + RR :MSTORE(subFp12BN254_RR) + + ; 1] c1 = a1 - b1 + $ => A :MLOAD(subFp12BN254_a11_x) + $ => B :MLOAD(subFp12BN254_a11_y) + A :MSTORE(subFp6BN254_a1_x) + B :MSTORE(subFp6BN254_a1_y) + $ => A :MLOAD(subFp12BN254_a12_x) + $ => B :MLOAD(subFp12BN254_a12_y) + A :MSTORE(subFp6BN254_a2_x) + B :MSTORE(subFp6BN254_a2_y) + $ => A :MLOAD(subFp12BN254_a13_x) + $ => B :MLOAD(subFp12BN254_a13_y) + A :MSTORE(subFp6BN254_a3_x) + B :MSTORE(subFp6BN254_a3_y) + + $ => A :MLOAD(subFp12BN254_b11_x) + $ => B :MLOAD(subFp12BN254_b11_y) + A :MSTORE(subFp6BN254_b1_x) + B :MSTORE(subFp6BN254_b1_y) + $ => A :MLOAD(subFp12BN254_b12_x) + $ => B :MLOAD(subFp12BN254_b12_y) + A :MSTORE(subFp6BN254_b2_x) + B :MSTORE(subFp6BN254_b2_y) + $ => A :MLOAD(subFp12BN254_b13_x) + $ => B :MLOAD(subFp12BN254_b13_y) + A :MSTORE(subFp6BN254_b3_x) + B :MSTORE(subFp6BN254_b3_y), CALL(subFp6BN254) + $ => A :MLOAD(subFp6BN254_c1_x) + $ => B :MLOAD(subFp6BN254_c1_y) + A :MSTORE(subFp12BN254_c11_x) + B :MSTORE(subFp12BN254_c11_y) + $ => A :MLOAD(subFp6BN254_c2_x) + $ => B :MLOAD(subFp6BN254_c2_y) + A :MSTORE(subFp12BN254_c12_x) + B :MSTORE(subFp12BN254_c12_y) + $ => A :MLOAD(subFp6BN254_c3_x) + $ => B :MLOAD(subFp6BN254_c3_y) + A :MSTORE(subFp12BN254_c13_x) + B :MSTORE(subFp12BN254_c13_y) + + ; 2] c2 = a2 - b2 + $ => A :MLOAD(subFp12BN254_a21_x) + $ => B :MLOAD(subFp12BN254_a21_y) + A :MSTORE(subFp6BN254_a1_x) + B :MSTORE(subFp6BN254_a1_y) + $ => A :MLOAD(subFp12BN254_a22_x) + $ => B :MLOAD(subFp12BN254_a22_y) + A :MSTORE(subFp6BN254_a2_x) + B :MSTORE(subFp6BN254_a2_y) + $ => A :MLOAD(subFp12BN254_a23_x) + $ => B :MLOAD(subFp12BN254_a23_y) + A :MSTORE(subFp6BN254_a3_x) + B :MSTORE(subFp6BN254_a3_y) + + $ => A :MLOAD(subFp12BN254_b21_x) + $ => B :MLOAD(subFp12BN254_b21_y) + A :MSTORE(subFp6BN254_b1_x) + B :MSTORE(subFp6BN254_b1_y) + $ => A :MLOAD(subFp12BN254_b22_x) + $ => B :MLOAD(subFp12BN254_b22_y) + A :MSTORE(subFp6BN254_b2_x) + B :MSTORE(subFp6BN254_b2_y) + $ => A :MLOAD(subFp12BN254_b23_x) + $ => B :MLOAD(subFp12BN254_b23_y) + A :MSTORE(subFp6BN254_b3_x) + B :MSTORE(subFp6BN254_b3_y), CALL(subFp6BN254) + $ => A :MLOAD(subFp6BN254_c1_x) + $ => B :MLOAD(subFp6BN254_c1_y) + A :MSTORE(subFp12BN254_c21_x) + B :MSTORE(subFp12BN254_c21_y) + $ => A :MLOAD(subFp6BN254_c2_x) + $ => B :MLOAD(subFp6BN254_c2_y) + A :MSTORE(subFp12BN254_c22_x) + B :MSTORE(subFp12BN254_c22_y) + $ => A :MLOAD(subFp6BN254_c3_x) + $ => B :MLOAD(subFp6BN254_c3_y) + A :MSTORE(subFp12BN254_c23_x) + B :MSTORE(subFp12BN254_c23_y) + + $ => RR :MLOAD(subFp12BN254_RR) + :RETURN \ No newline at end of file diff --git a/main/pairings/unused/xPseudoBinDecompBN254.zkasm b/main/pairings/unused/xPseudoBinDecompBN254.zkasm new file mode 100644 index 00000000..933b1886 --- /dev/null +++ b/main/pairings/unused/xPseudoBinDecompBN254.zkasm @@ -0,0 +1,68 @@ +;; +;; parameter of BN254 x = 4965661367192848881, which can be expressed in (little-endian) pseudobinary as: +;; 1000-1000010100001001011001010010001011010100100110010-1001010001 +;; + +xPseudoBinDecompBN254: + 1 => B :RETURN + 0 => B :RETURN + 0 => B :RETURN + 0 => B :RETURN + -1 => B :RETURN + 0 => B :RETURN + 0 => B :RETURN + 0 => B :RETURN + 0 => B :RETURN + 1 => B :RETURN + 0 => B :RETURN + 1 => B :RETURN + 0 => B :RETURN + 0 => B :RETURN + 0 => B :RETURN + 0 => B :RETURN + 1 => B :RETURN + 0 => B :RETURN + 0 => B :RETURN + 1 => B :RETURN + 0 => B :RETURN + 1 => B :RETURN + 1 => B :RETURN + 0 => B :RETURN + 0 => B :RETURN + 1 => B :RETURN + 0 => B :RETURN + 1 => B :RETURN + 0 => B :RETURN + 0 => B :RETURN + 1 => B :RETURN + 0 => B :RETURN + 0 => B :RETURN + 0 => B :RETURN + 1 => B :RETURN + 0 => B :RETURN + 1 => B :RETURN + 1 => B :RETURN + 0 => B :RETURN + 1 => B :RETURN + 0 => B :RETURN + 1 => B :RETURN + 0 => B :RETURN + 0 => B :RETURN + 1 => B :RETURN + 0 => B :RETURN + 0 => B :RETURN + 1 => B :RETURN + 1 => B :RETURN + 0 => B :RETURN + 0 => B :RETURN + 1 => B :RETURN + 0 => B :RETURN + -1 => B :RETURN + 0 => B :RETURN + 0 => B :RETURN + 1 => B :RETURN + 0 => B :RETURN + 1 => B :RETURN + 0 => B :RETURN + 0 => B :RETURN + 0 => B :RETURN \ No newline at end of file diff --git a/main/pairings/utilsTests/expCycloFp12BN254.zkasm b/main/pairings/utilsTests/expCycloFp12BN254.zkasm new file mode 100644 index 00000000..6dac4e07 --- /dev/null +++ b/main/pairings/utilsTests/expCycloFp12BN254.zkasm @@ -0,0 +1,334 @@ +;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; POST: The result is in the range [0,BN254_P) because if falls back to FP12 arithmetic +;; +;; expCycloFp12BN254: +;; in: e, (a1 + a2·w) ∈ GΦ6(p²), where e ∈ [0,p¹²-2] ai ∈ Fp6 +;; out: (c1 + c2·w) = (a1 + a2·w)^e ∈ GΦ6(p²) +;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +; Comment: We use this algorithm with a very small e (i.e., it fits in 32 bits), but it must be adpated to use it with a bigger e +; Comment: In some cases, we can speed this algorithm up by using pseudobinary encoding instead of binary encoding + +VAR GLOBAL expCycloFp12BN254_e +VAR GLOBAL expCycloFp12BN254_a11_x +VAR GLOBAL expCycloFp12BN254_a11_y +VAR GLOBAL expCycloFp12BN254_a12_x +VAR GLOBAL expCycloFp12BN254_a12_y +VAR GLOBAL expCycloFp12BN254_a13_x +VAR GLOBAL expCycloFp12BN254_a13_y +VAR GLOBAL expCycloFp12BN254_a21_x +VAR GLOBAL expCycloFp12BN254_a21_y +VAR GLOBAL expCycloFp12BN254_a22_x +VAR GLOBAL expCycloFp12BN254_a22_y +VAR GLOBAL expCycloFp12BN254_a23_x +VAR GLOBAL expCycloFp12BN254_a23_y +VAR GLOBAL expCycloFp12BN254_c11_x +VAR GLOBAL expCycloFp12BN254_c11_y +VAR GLOBAL expCycloFp12BN254_c12_x +VAR GLOBAL expCycloFp12BN254_c12_y +VAR GLOBAL expCycloFp12BN254_c13_x +VAR GLOBAL expCycloFp12BN254_c13_y +VAR GLOBAL expCycloFp12BN254_c21_x +VAR GLOBAL expCycloFp12BN254_c21_y +VAR GLOBAL expCycloFp12BN254_c22_x +VAR GLOBAL expCycloFp12BN254_c22_y +VAR GLOBAL expCycloFp12BN254_c23_x +VAR GLOBAL expCycloFp12BN254_c23_y + +VAR GLOBAL expCycloFp12BN254_RR + +expCycloFp12BN254: + RR :MSTORE(expCycloFp12BN254_RR) + + ; Trivial cases: + ; 1] Is a = 0? + 0n => B + $ => A :MLOAD(expCycloFp12BN254_a11_x) + $ :EQ, JMPNC(__expCycloFp12BN254_a_continue1) + $ => A :MLOAD(expCycloFp12BN254_a11_y) + $ :EQ, JMPNC(__expCycloFp12BN254_a_continue1) + $ => A :MLOAD(expCycloFp12BN254_a12_x) + $ :EQ, JMPNC(__expCycloFp12BN254_a_continue1) + $ => A :MLOAD(expCycloFp12BN254_a12_y) + $ :EQ, JMPNC(__expCycloFp12BN254_a_continue1) + $ => A :MLOAD(expCycloFp12BN254_a13_x) + $ :EQ, JMPNC(__expCycloFp12BN254_a_continue1) + $ => A :MLOAD(expCycloFp12BN254_a13_y) + $ :EQ, JMPNC(__expCycloFp12BN254_a_continue1) + $ => A :MLOAD(expCycloFp12BN254_a21_x) + $ :EQ, JMPNC(__expCycloFp12BN254_a_continue1) + $ => A :MLOAD(expCycloFp12BN254_a21_y) + $ :EQ, JMPNC(__expCycloFp12BN254_a_continue1) + $ => A :MLOAD(expCycloFp12BN254_a22_x) + $ :EQ, JMPNC(__expCycloFp12BN254_a_continue1) + $ => A :MLOAD(expCycloFp12BN254_a22_y) + $ :EQ, JMPNC(__expCycloFp12BN254_a_continue1) + $ => A :MLOAD(expCycloFp12BN254_a23_x) + $ :EQ, JMPNC(__expCycloFp12BN254_a_continue1) + $ => A :MLOAD(expCycloFp12BN254_a23_y) + $ :EQ, JMPC(expCycloFp12BN254_a_is_zero) + __expCycloFp12BN254_a_continue1: + + ; 2] Is a = 1? + 1n => B + $ => A :MLOAD(expCycloFp12BN254_a11_x) + $ :EQ, JMPNC(__expCycloFp12BN254_a_continue2) + 0n => B + $ => A :MLOAD(expCycloFp12BN254_a11_y) + $ :EQ, JMPNC(__expCycloFp12BN254_a_continue2) + $ => A :MLOAD(expCycloFp12BN254_a12_x) + $ :EQ, JMPNC(__expCycloFp12BN254_a_continue2) + $ => A :MLOAD(expCycloFp12BN254_a12_y) + $ :EQ, JMPNC(__expCycloFp12BN254_a_continue2) + $ => A :MLOAD(expCycloFp12BN254_a13_x) + $ :EQ, JMPNC(__expCycloFp12BN254_a_continue2) + $ => A :MLOAD(expCycloFp12BN254_a13_y) + $ :EQ, JMPNC(__expCycloFp12BN254_a_continue2) + $ => A :MLOAD(expCycloFp12BN254_a21_x) + $ :EQ, JMPNC(__expCycloFp12BN254_a_continue2) + $ => A :MLOAD(expCycloFp12BN254_a21_y) + $ :EQ, JMPNC(__expCycloFp12BN254_a_continue2) + $ => A :MLOAD(expCycloFp12BN254_a22_x) + $ :EQ, JMPNC(__expCycloFp12BN254_a_continue2) + $ => A :MLOAD(expCycloFp12BN254_a22_y) + $ :EQ, JMPNC(__expCycloFp12BN254_a_continue2) + $ => A :MLOAD(expCycloFp12BN254_a23_x) + $ :EQ, JMPNC(__expCycloFp12BN254_a_continue2) + $ => A :MLOAD(expCycloFp12BN254_a23_y) + $ :EQ, JMPC(expCycloFp12BN254_a_is_one) + __expCycloFp12BN254_a_continue2: + + ; 3] Check if e = 0 + $ => A :MLOAD(expCycloFp12BN254_e) + 0n => B + $ :EQ, JMPC(expCycloFp12BN254_e_is_zero) + + 257 => RCX + + $ => A :MLOAD(expCycloFp12BN254_a11_x) + $ => B :MLOAD(expCycloFp12BN254_a11_y) + A :MSTORE(expCycloFp12BN254_c11_x) + B :MSTORE(expCycloFp12BN254_c11_y) + $ => A :MLOAD(expCycloFp12BN254_a12_x) + $ => B :MLOAD(expCycloFp12BN254_a12_y) + A :MSTORE(expCycloFp12BN254_c12_x) + B :MSTORE(expCycloFp12BN254_c12_y) + $ => A :MLOAD(expCycloFp12BN254_a13_x) + $ => B :MLOAD(expCycloFp12BN254_a13_y) + A :MSTORE(expCycloFp12BN254_c13_x) + B :MSTORE(expCycloFp12BN254_c13_y) + $ => A :MLOAD(expCycloFp12BN254_a21_x) + $ => B :MLOAD(expCycloFp12BN254_a21_y) + A :MSTORE(expCycloFp12BN254_c21_x) + B :MSTORE(expCycloFp12BN254_c21_y) + $ => A :MLOAD(expCycloFp12BN254_a22_x) + $ => B :MLOAD(expCycloFp12BN254_a22_y) + A :MSTORE(expCycloFp12BN254_c22_x) + B :MSTORE(expCycloFp12BN254_c22_y) + $ => A :MLOAD(expCycloFp12BN254_a23_x) + $ => B :MLOAD(expCycloFp12BN254_a23_y) + A :MSTORE(expCycloFp12BN254_c23_x) + B :MSTORE(expCycloFp12BN254_c23_y) + + :JMP(expCycloFp12BN254_find_MSB_e) + +expCycloFp12BN254_a_is_zero: + ; I define 0^0 = 0 for simplicity + 0n :MSTORE(expCycloFp12BN254_c11_x) + 0n :MSTORE(expCycloFp12BN254_c11_y) + 0n :MSTORE(expCycloFp12BN254_c12_x) + 0n :MSTORE(expCycloFp12BN254_c12_y) + 0n :MSTORE(expCycloFp12BN254_c13_x) + 0n :MSTORE(expCycloFp12BN254_c13_y) + 0n :MSTORE(expCycloFp12BN254_c21_x) + 0n :MSTORE(expCycloFp12BN254_c21_y) + 0n :MSTORE(expCycloFp12BN254_c22_x) + 0n :MSTORE(expCycloFp12BN254_c22_y) + 0n :MSTORE(expCycloFp12BN254_c23_x) + 0n :MSTORE(expCycloFp12BN254_c23_y) + + :JMP(expCycloFp12BN254_end) + +expCycloFp12BN254_a_is_one: + ; c = 1 + 1n :MSTORE(expCycloFp12BN254_c11_x) + 0n :MSTORE(expCycloFp12BN254_c11_y) + 0n :MSTORE(expCycloFp12BN254_c12_x) + 0n :MSTORE(expCycloFp12BN254_c12_y) + 0n :MSTORE(expCycloFp12BN254_c13_x) + 0n :MSTORE(expCycloFp12BN254_c13_y) + 0n :MSTORE(expCycloFp12BN254_c21_x) + 0n :MSTORE(expCycloFp12BN254_c21_y) + 0n :MSTORE(expCycloFp12BN254_c22_x) + 0n :MSTORE(expCycloFp12BN254_c22_y) + 0n :MSTORE(expCycloFp12BN254_c23_x) + 0n :MSTORE(expCycloFp12BN254_c23_y) + + :JMP(expCycloFp12BN254_end) + +expCycloFp12BN254_e_is_zero: + ; c = 1 + 1n :MSTORE(expCycloFp12BN254_c11_x) + 0n :MSTORE(expCycloFp12BN254_c11_y) + 0n :MSTORE(expCycloFp12BN254_c12_x) + 0n :MSTORE(expCycloFp12BN254_c12_y) + 0n :MSTORE(expCycloFp12BN254_c13_x) + 0n :MSTORE(expCycloFp12BN254_c13_y) + 0n :MSTORE(expCycloFp12BN254_c21_x) + 0n :MSTORE(expCycloFp12BN254_c21_y) + 0n :MSTORE(expCycloFp12BN254_c22_x) + 0n :MSTORE(expCycloFp12BN254_c22_y) + 0n :MSTORE(expCycloFp12BN254_c23_x) + 0n :MSTORE(expCycloFp12BN254_c23_y) + + :JMP(expCycloFp12BN254_end) + +expCycloFp12BN254_find_MSB_e: + RCX - 1 => RCX + $ => A,B :MLOAD(expCycloFp12BN254_e) + ; E = 2A + $ => E :ADD,MSTORE(expCycloFp12BN254_e), JMPNC(expCycloFp12BN254_find_MSB_e) + + +expCycloFp12BN254_loop: + RCX - 1 => RCX :JMPZ(expCycloFp12BN254_end) + + ; We always square: c = c^2 + $ => A :MLOAD(expCycloFp12BN254_c11_x) + $ => B :MLOAD(expCycloFp12BN254_c11_y) + A :MSTORE(squareCycloFp12BN254_a11_x) + B :MSTORE(squareCycloFp12BN254_a11_y) + $ => A :MLOAD(expCycloFp12BN254_c12_x) + $ => B :MLOAD(expCycloFp12BN254_c12_y) + A :MSTORE(squareCycloFp12BN254_a12_x) + B :MSTORE(squareCycloFp12BN254_a12_y) + $ => A :MLOAD(expCycloFp12BN254_c13_x) + $ => B :MLOAD(expCycloFp12BN254_c13_y) + A :MSTORE(squareCycloFp12BN254_a13_x) + B :MSTORE(squareCycloFp12BN254_a13_y) + $ => A :MLOAD(expCycloFp12BN254_c21_x) + $ => B :MLOAD(expCycloFp12BN254_c21_y) + A :MSTORE(squareCycloFp12BN254_a21_x) + B :MSTORE(squareCycloFp12BN254_a21_y) + $ => A :MLOAD(expCycloFp12BN254_c22_x) + $ => B :MLOAD(expCycloFp12BN254_c22_y) + A :MSTORE(squareCycloFp12BN254_a22_x) + B :MSTORE(squareCycloFp12BN254_a22_y) + $ => A :MLOAD(expCycloFp12BN254_c23_x) + $ => B :MLOAD(expCycloFp12BN254_c23_y) + A :MSTORE(squareCycloFp12BN254_a23_x) + B :MSTORE(squareCycloFp12BN254_a23_y), CALL(squareCycloFp12BN254) + + ; c = c^2 + $ => A :MLOAD(squareCycloFp12BN254_c11_x) + $ => B :MLOAD(squareCycloFp12BN254_c11_y) + A :MSTORE(expCycloFp12BN254_c11_x) + B :MSTORE(expCycloFp12BN254_c11_y) + $ => A :MLOAD(squareCycloFp12BN254_c12_x) + $ => B :MLOAD(squareCycloFp12BN254_c12_y) + A :MSTORE(expCycloFp12BN254_c12_x) + B :MSTORE(expCycloFp12BN254_c12_y) + $ => A :MLOAD(squareCycloFp12BN254_c13_x) + $ => B :MLOAD(squareCycloFp12BN254_c13_y) + A :MSTORE(expCycloFp12BN254_c13_x) + B :MSTORE(expCycloFp12BN254_c13_y) + $ => A :MLOAD(squareCycloFp12BN254_c21_x) + $ => B :MLOAD(squareCycloFp12BN254_c21_y) + A :MSTORE(expCycloFp12BN254_c21_x) + B :MSTORE(expCycloFp12BN254_c21_y) + $ => A :MLOAD(squareCycloFp12BN254_c22_x) + $ => B :MLOAD(squareCycloFp12BN254_c22_y) + A :MSTORE(expCycloFp12BN254_c22_x) + B :MSTORE(expCycloFp12BN254_c22_y) + $ => A :MLOAD(squareCycloFp12BN254_c23_x) + $ => B :MLOAD(squareCycloFp12BN254_c23_y) + A :MSTORE(expCycloFp12BN254_c23_x) + B :MSTORE(expCycloFp12BN254_c23_y) + + ; 2] We check if the MSB b of e is either 1 or 0. If b==1, we should multiply a to c. + ; Then, update the value of e. + $ => A,B :MLOAD(expCycloFp12BN254_e) + ; E = 2A + $ => E :ADD,MSTORE(expCycloFp12BN254_e), JMPNC(expCycloFp12BN254_loop) + +expCycloFp12BN254_multiply: + $ => A :MLOAD(expCycloFp12BN254_a11_x) + $ => B :MLOAD(expCycloFp12BN254_a11_y) + A :MSTORE(mulFp12BN254_a11_x) + B :MSTORE(mulFp12BN254_a11_y) + $ => A :MLOAD(expCycloFp12BN254_a12_x) + $ => B :MLOAD(expCycloFp12BN254_a12_y) + A :MSTORE(mulFp12BN254_a12_x) + B :MSTORE(mulFp12BN254_a12_y) + $ => A :MLOAD(expCycloFp12BN254_a13_x) + $ => B :MLOAD(expCycloFp12BN254_a13_y) + A :MSTORE(mulFp12BN254_a13_x) + B :MSTORE(mulFp12BN254_a13_y) + $ => A :MLOAD(expCycloFp12BN254_a21_x) + $ => B :MLOAD(expCycloFp12BN254_a21_y) + A :MSTORE(mulFp12BN254_a21_x) + B :MSTORE(mulFp12BN254_a21_y) + $ => A :MLOAD(expCycloFp12BN254_a22_x) + $ => B :MLOAD(expCycloFp12BN254_a22_y) + A :MSTORE(mulFp12BN254_a22_x) + B :MSTORE(mulFp12BN254_a22_y) + $ => A :MLOAD(expCycloFp12BN254_a23_x) + $ => B :MLOAD(expCycloFp12BN254_a23_y) + A :MSTORE(mulFp12BN254_a23_x) + B :MSTORE(mulFp12BN254_a23_y) + $ => A :MLOAD(expCycloFp12BN254_c11_x) + $ => B :MLOAD(expCycloFp12BN254_c11_y) + A :MSTORE(mulFp12BN254_b11_x) + B :MSTORE(mulFp12BN254_b11_y) + $ => A :MLOAD(expCycloFp12BN254_c12_x) + $ => B :MLOAD(expCycloFp12BN254_c12_y) + A :MSTORE(mulFp12BN254_b12_x) + B :MSTORE(mulFp12BN254_b12_y) + $ => A :MLOAD(expCycloFp12BN254_c13_x) + $ => B :MLOAD(expCycloFp12BN254_c13_y) + A :MSTORE(mulFp12BN254_b13_x) + B :MSTORE(mulFp12BN254_b13_y) + $ => A :MLOAD(expCycloFp12BN254_c21_x) + $ => B :MLOAD(expCycloFp12BN254_c21_y) + A :MSTORE(mulFp12BN254_b21_x) + B :MSTORE(mulFp12BN254_b21_y) + $ => A :MLOAD(expCycloFp12BN254_c22_x) + $ => B :MLOAD(expCycloFp12BN254_c22_y) + A :MSTORE(mulFp12BN254_b22_x) + B :MSTORE(mulFp12BN254_b22_y) + $ => A :MLOAD(expCycloFp12BN254_c23_x) + $ => B :MLOAD(expCycloFp12BN254_c23_y) + A :MSTORE(mulFp12BN254_b23_x) + B :MSTORE(mulFp12BN254_b23_y), CALL(mulFp12BN254) + + ; c = c·a + $ => A :MLOAD(mulFp12BN254_c11_x) + $ => B :MLOAD(mulFp12BN254_c11_y) + A :MSTORE(expCycloFp12BN254_c11_x) + B :MSTORE(expCycloFp12BN254_c11_y) + $ => A :MLOAD(mulFp12BN254_c12_x) + $ => B :MLOAD(mulFp12BN254_c12_y) + A :MSTORE(expCycloFp12BN254_c12_x) + B :MSTORE(expCycloFp12BN254_c12_y) + $ => A :MLOAD(mulFp12BN254_c13_x) + $ => B :MLOAD(mulFp12BN254_c13_y) + A :MSTORE(expCycloFp12BN254_c13_x) + B :MSTORE(expCycloFp12BN254_c13_y) + $ => A :MLOAD(mulFp12BN254_c21_x) + $ => B :MLOAD(mulFp12BN254_c21_y) + A :MSTORE(expCycloFp12BN254_c21_x) + B :MSTORE(expCycloFp12BN254_c21_y) + $ => A :MLOAD(mulFp12BN254_c22_x) + $ => B :MLOAD(mulFp12BN254_c22_y) + A :MSTORE(expCycloFp12BN254_c22_x) + B :MSTORE(expCycloFp12BN254_c22_y) + $ => A :MLOAD(mulFp12BN254_c23_x) + $ => B :MLOAD(mulFp12BN254_c23_y) + A :MSTORE(expCycloFp12BN254_c23_x) + B :MSTORE(expCycloFp12BN254_c23_y) + :JMP(expCycloFp12BN254_loop) + +expCycloFp12BN254_end: + $ => RR :MLOAD(expCycloFp12BN254_RR) + :RETURN \ No newline at end of file diff --git a/main/precompiled/end.zkasm b/main/precompiled/end.zkasm index 14383eb7..ed75777b 100644 --- a/main/precompiled/end.zkasm +++ b/main/precompiled/end.zkasm @@ -1,9 +1,42 @@ preEnd: $ => B :MLOAD(gasCTX) B + GAS => GAS - ; decrease depth - $ => A :MLOAD(depth) - A - 1 :MSTORE(depth) $ => SP :MLOAD(lastSP) $ => PC :MLOAD(lastPC) - 1 :MSTORE(SP++), JMP(readCode) \ No newline at end of file + 1 :MSTORE(SP++), JMP(readCode) + +preEndFail: + $ => SR :MLOAD(initSR), CALL(revertTouched) + :CALL(revertBlockInfoTree) + ;remaining gas = 0 + $ => A :MLOAD(originCTX), JMPZ(errorAtFirstContext) + A => CTX + ; Add return data context value to origin context + ; Clear return data context + 0 :MSTORE(retDataCTX) + CTX :MSTORE(currentCTX) + $ => GAS :MLOAD(gasCTX) + $ => SP :MLOAD(lastSP) + $ => PC :MLOAD(lastPC) + 0 :MSTORE(SP++), JMP(readCode) + +; 'preGAS' is the gas on the modExp precompiled before extracting the gas consumed +VAR GLOBAL preGAS + +preFailModExpLength: + $ => SR :MLOAD(initSR), CALL(revertTouched) + :CALL(revertBlockInfoTree) + $ => A :MLOAD(originCTX), JMPZ(errorAtFirstContext) + A => CTX + ; Add return data context value to origin context + ; Clear return data context + 0 :MSTORE(retDataCTX) + CTX :MSTORE(currentCTX) + $ => A :MLOAD(gasCTX) + $ => B :MLOAD(preGAS) + A + B + GAS => GAS + ; set 0 to preGAS for the next iteration + 0 :MSTORE(preGAS) + $ => SP :MLOAD(lastSP) + $ => PC :MLOAD(lastPC) + 0 :MSTORE(SP++), JMP(readCode) \ No newline at end of file diff --git a/main/precompiled/identity.zkasm b/main/precompiled/identity.zkasm index e353a665..5a177028 100644 --- a/main/precompiled/identity.zkasm +++ b/main/precompiled/identity.zkasm @@ -1,6 +1,15 @@ +/** + * @link [https://www.evm.codes/precompiled#0x04?fork=berlin] + * @zk-counters + * - dynamic steps: 100 + * - dynamic binary: 1 + * @process-precompiled + * - stack input: [data] + * - stack output: [data] + */ IDENTITY: %MAX_CNT_STEPS - STEP - 100 :JMPN(outOfCountersStep) - %MAX_CNT_BINARY - CNT_BINARY - 1 :JMPN(outOfCountersBinary) + %MAX_CNT_BINARY - CNT_BINARY - 1 :JMPN(outOfCountersBinary) ; Move balances if value > 0 just before executing the contract CALL $ => B :MLOAD(txValue) 0 => A @@ -87,4 +96,4 @@ IDENTITYreturnFinal: IDENTITYend: $ => CTX :MLOAD(originCTX) - CTX :MSTORE(currentCTX), JMP(preEnd) + CTX :MSTORE(currentCTX), JMP(preEnd) \ No newline at end of file diff --git a/main/precompiled/pre-ecAdd.zkasm b/main/precompiled/pre-ecAdd.zkasm new file mode 100644 index 00000000..eaaf7a16 --- /dev/null +++ b/main/precompiled/pre-ecAdd.zkasm @@ -0,0 +1,84 @@ +/** + * @link [https://www.evm.codes/precompiled#0x06?fork=berlin] + * @zk-counters + * - dynamic steps: 500 + * - dynamic arith: 50 + * - dynamic binary: 10 + * @process-precompiled + * - stack input: [x1, y1, x2, y2] + * - stack output: [x, y] + */ +funcEcAdd: + %MAX_CNT_ARITH - CNT_ARITH - 50 :JMPN(outOfCountersArith) + %MAX_CNT_BINARY - CNT_BINARY - 50 :JMPN(outOfCountersBinary) + %MAX_CNT_STEPS - STEP - 800 :JMPN(outOfCountersStep) + + ; Move balances if value > 0 just before executing the contract CALL + $ => B :MLOAD(txValue) + 0 => A + zkPC+2 => RR + $ :LT, JMPC(moveBalances) + + GAS - %ECADD_GAS => GAS :JMPN(outOfGas) ; gas static = 150 + + ; read data stored in calldata + ; x1 [32 bytes], y1 [32 bytes], x2 [32 bytes], y2 [32 bytes] + 32 :MSTORE(readXFromCalldataLength) + 0 => E :MSTORE(readXFromCalldataOffset), CALL(readFromCalldataOffset); in: [readXFromCalldataOffset: offset value, readXFromCalldataLength: length value], out: [readXFromCalldataResult: result value] + $ => A :MLOAD(readXFromCalldataResult) ; x1 + A :MSTORE(ecAdd_P1_x) + E + 32 => E :MSTORE(readXFromCalldataOffset), CALL(readFromCalldataOffset); in: [readXFromCalldataOffset: offset value, readXFromCalldataLength: length value], out: [readXFromCalldataResult: result value] + $ => A :MLOAD(readXFromCalldataResult) ; y1 + A :MSTORE(ecAdd_P1_y) + E + 32 => E :MSTORE(readXFromCalldataOffset), CALL(readFromCalldataOffset); in: [readXFromCalldataOffset: offset value, readXFromCalldataLength: length value], out: [readXFromCalldataResult: result value] + $ => A :MLOAD(readXFromCalldataResult) ; x2 + A :MSTORE(ecAdd_P2_x) + E + 32 => E :MSTORE(readXFromCalldataOffset), CALL(readFromCalldataOffset); in: [readXFromCalldataOffset: offset value, readXFromCalldataLength: length value], out: [readXFromCalldataResult: result value] + $ => A :MLOAD(readXFromCalldataResult) ; y2 + A :MSTORE(ecAdd_P2_y),CALL(ecAdd) + + ; check error + B :JMPNZ(preEndFail) + + ; write ecAdd data into memory + 0 => E + $ => A :MLOAD(ecAdd_P3_x) + A :MSTORE(bytesToStore), CALL(MSTORE32); in: [bytesToStore, E: offset] out: [E: new offset] + $ => A :MLOAD(ecAdd_P3_y) + A :MSTORE(bytesToStore), CALL(MSTORE32); in: [bytesToStore, E: offset] out: [E: new offset] + + ; prepare return data + 0 :MSTORE(retDataOffset) + 64 :MSTORE(retDataLength) + $ => A :MLOAD(originCTX), JMPZ(handleGas) + ; set retDataCTX + $ => B :MLOAD(currentCTX) + A => CTX + B :MSTORE(retDataCTX) + B => CTX + + ; write result ecAdd into previous context memory + $ => C :MLOAD(retCallLength), JMPZ(preEndECADD) + $ => E :MLOAD(retCallOffset) + + $ => CTX :MLOAD(originCTX) + $ => A :MLOAD(ecAdd_P3_x) + A :MSTORE(bytesToStore) + C - 32 :JMPN(continueEcAdd) + C - 32 => C + :CALL(MSTORE32); in: [bytesToStore, E: offset] out: [E: new offset] + $ => A :MLOAD(ecAdd_P3_y) + A :MSTORE(bytesToStore) + C - 32 :JMPN(continueEcAdd) + :CALL(MSTORE32); in: [bytesToStore, E: offset] out: [E: new offset] + :JMP(endECADD) + +continueEcAdd: + :CALL(MSTOREX); in: [bytesToStore, E: offset, C: length] out: [E: new offset] + :JMP(endECADD) + +preEndECADD: + $ => CTX :MLOAD(originCTX) + +endECADD: + CTX :MSTORE(currentCTX), JMP(preEnd) diff --git a/main/precompiled/pre-ecMul.zkasm b/main/precompiled/pre-ecMul.zkasm new file mode 100644 index 00000000..2c143390 --- /dev/null +++ b/main/precompiled/pre-ecMul.zkasm @@ -0,0 +1,82 @@ +/** + * @link [https://www.evm.codes/precompiled#0x07?fork=berlin] + * @zk-counters + * - dynamic steps: 130000 + * - dynamic arith: 20000 + * - dynamic binary: 4000 + * @process-precompiled + * - stack input: [x1, y1, s] + * - stack output: [x, y] + */ +funcEcMul: + + %MAX_CNT_BINARY - CNT_BINARY - 4000 :JMPN(outOfCountersBinary) + %MAX_CNT_ARITH - CNT_ARITH - 20000 :JMPN(outOfCountersArith) + %MAX_CNT_STEPS - STEP - 130000 :JMPN(outOfCountersStep) + + ; Move balances if value > 0 just before executing the contract CALL + $ => B :MLOAD(txValue) + 0 => A + zkPC+2 => RR + $ :LT, JMPC(moveBalances) + + GAS - %ECMUL_GAS => GAS :JMPN(outOfGas) ; gas static = 6000 + + ; read data stored in calldata + ; x1 [32 bytes], y1 [32 bytes], k [32 bytes] + 32 :MSTORE(readXFromCalldataLength) + 0 => E :MSTORE(readXFromCalldataOffset), CALL(readFromCalldataOffset); in: [readXFromCalldataOffset: offset value, readXFromCalldataLength: length value], out: [readXFromCalldataResult: result value] + $ => A :MLOAD(readXFromCalldataResult) ; x1 + A :MSTORE(ecMul_P_x) + E + 32 => E :MSTORE(readXFromCalldataOffset), CALL(readFromCalldataOffset); in: [readXFromCalldataOffset: offset value, readXFromCalldataLength: length value], out: [readXFromCalldataResult: result value] + $ => A :MLOAD(readXFromCalldataResult) ; y1 + A :MSTORE(ecMul_P_y) + E + 32 => E :MSTORE(readXFromCalldataOffset), CALL(readFromCalldataOffset); in: [readXFromCalldataOffset: offset value, readXFromCalldataLength: length value], out: [readXFromCalldataResult: result value] + $ => A :MLOAD(readXFromCalldataResult) ; k + A :MSTORE(ecMul_k),CALL(ecMul) + + ; check error + B :JMPNZ(preEndFail) + + ; write ecMul data into memory + 0 => E + $ => A :MLOAD(ecMul_Q_x) + A :MSTORE(bytesToStore), CALL(MSTORE32); in: [bytesToStore, E: offset] out: [E: new offset] + $ => A :MLOAD(ecMul_Q_y) + A :MSTORE(bytesToStore), CALL(MSTORE32); in: [bytesToStore, E: offset] out: [E: new offset] + + ; prepare return data + 0 :MSTORE(retDataOffset) + 64 :MSTORE(retDataLength) + $ => A :MLOAD(originCTX), JMPZ(handleGas) + ; set retDataCTX + $ => B :MLOAD(currentCTX) + A => CTX + B :MSTORE(retDataCTX) + B => CTX + + ; write result ecMul into previous context memory + $ => C :MLOAD(retCallLength), JMPZ(preEndECMUL) + $ => E :MLOAD(retCallOffset) + + $ => CTX :MLOAD(originCTX) + $ => A :MLOAD(ecMul_Q_x) + A :MSTORE(bytesToStore) + C - 32 :JMPN(continueEcMul) + C - 32 => C + :CALL(MSTORE32); in: [bytesToStore, E: offset] out: [E: new offset] + $ => A :MLOAD(ecMul_Q_y) + A :MSTORE(bytesToStore) + C - 32 :JMPN(continueEcMul) + :CALL(MSTORE32); in: [bytesToStore, E: offset] out: [E: new offset] + :JMP(endECMUL) + +continueEcMul: + :CALL(MSTOREX); in: [bytesToStore, E: offset, C: length] out: [E: new offset] + :JMP(endECMUL) + +preEndECMUL: + $ => CTX :MLOAD(originCTX) + +endECMUL: + CTX :MSTORE(currentCTX), JMP(preEnd) \ No newline at end of file diff --git a/main/precompiled/pre-ecPairing.zkasm b/main/precompiled/pre-ecPairing.zkasm new file mode 100644 index 00000000..b3319509 --- /dev/null +++ b/main/precompiled/pre-ecPairing.zkasm @@ -0,0 +1,82 @@ +/** + * @link [https://www.evm.codes/precompiled#0x08?fork=berlin] + * @zk-counters + * - dynamic steps: 50000, 550000, 700000,... + * - dynamic arith: 4000, 43000, 56000,... + * - dynamic binary: 400, 700, 1100,... + * @process-precompiled + * - stack input: [x1, y1, x2, y2, ..., xk, yk] + * - stack output: [success] + * @note For implementation details, see: https://hackmd.io/kcEJAWISQ56eE6YpBnurgw?view + */ + +funcEcPairing: + ; Move balances if value > 0 just before executing the contract CALL + $ => B :MLOAD(txValue) + 0 => A + zkPC+2 => RR + $ :LT, JMPC(moveBalances) + + GAS - %ECPAIRING_GAS => GAS :JMPN(outOfGas) ; gas static = 45000 + + 1 => C + $ => B :MLOAD(txCalldataLen),JMPZ(continueInput0) + B :MSTORE(arithA) + 192 :MSTORE(arithB), CALL(divARITH); in: [arithA, arithB] out: [arithRes1: arithA/arithB, arithRes2: arithA%arithB] + $ => A :MLOAD(arithRes2), JMPNZ(preEndFail) + $ => A :MLOAD(arithRes1) + A :MSTORE(ecPairing_ninputs) + + GAS - 34000*A => GAS :JMPN(outOfGas) ; gas = 34000 * inputsLength + A - 1 :JMPZ(counters6) + A - 2 => A + + %MAX_CNT_BINARY - CNT_BINARY - 700 - 400*A :JMPN(outOfCountersBinary) + %MAX_CNT_ARITH - CNT_ARITH - 45000 - 14000*A :JMPN(outOfCountersArith) + %MAX_CNT_STEPS - STEP - 550000 - 200000*A :JMPN(outOfCountersStep) + :JMP(afterCounts) + +counters6: + + %MAX_CNT_BINARY - CNT_BINARY - 400 :JMPN(outOfCountersBinary) + %MAX_CNT_ARITH - CNT_ARITH - 4000 :JMPN(outOfCountersArith) + %MAX_CNT_STEPS - STEP - 50000 :JMPN(outOfCountersStep) + +afterCounts: + -32 :MSTORE(readXFromCalldataOffset),CALL(ecPairing) + B :JMPNZ(preEndFail) + $ => C :MLOAD(ecPairing_result) + +continueInput0: + + ; write ecAdd data into memory + 0 => E + C :MSTORE(bytesToStore), CALL(MSTORE32); in: [bytesToStore, E: offset] out: [E: new offset] + + ; prepare return data + 0 :MSTORE(retDataOffset) + 32 :MSTORE(retDataLength) + $ => A :MLOAD(originCTX), JMPZ(handleGas) + ; set retDataCTX + $ => B :MLOAD(currentCTX) + A => CTX + B :MSTORE(retDataCTX) + B => CTX + + ; write result ecpairing into previous context memory + $ => C :MLOAD(retCallLength) + $ => E :MLOAD(retCallOffset) + + ; ecpairing result is in bytesToStore + C - 32 :JMPN(continueECPAIRING) + 32 => C + +continueECPAIRING: + $ => CTX :MLOAD(originCTX), CALL(MSTOREX) ; in: [bytesToStore, E: offset, C: length] out: [E: new offset] + :JMP(endECPAIRING) + +preEndECPAIRING: + $ => CTX :MLOAD(originCTX) + +endECPAIRING: + CTX :MSTORE(currentCTX), JMP(preEnd) \ No newline at end of file diff --git a/main/precompiled/pre-ecrecover.zkasm b/main/precompiled/pre-ecrecover.zkasm index 6458f96c..ba2eb694 100644 --- a/main/precompiled/pre-ecrecover.zkasm +++ b/main/precompiled/pre-ecrecover.zkasm @@ -1,3 +1,13 @@ +/** + * @link [https://www.evm.codes/precompiled#0x01?fork=berlin] + * @zk-counters + * - dynamic steps: + * - dynamic arith: + * - dynamic binary: + * @process-precompiled + * - stack input: [hash, v, r, s] + * - stack output: [publicAddress] + */ funcECRECOVER: ; Move balances if value > 0 just before executing the contract CALL $ => B :MLOAD(txValue) diff --git a/main/precompiled/pre-modexp.zkasm b/main/precompiled/pre-modexp.zkasm new file mode 100644 index 00000000..6e0e26d3 --- /dev/null +++ b/main/precompiled/pre-modexp.zkasm @@ -0,0 +1,348 @@ +/** + * @link [https://www.evm.codes/precompiled#0x05?fork=berlin] + * @zk-counters + * - dynamic steps: + * - dynamic arith: + * - dynamic binary: + * @process-precompiled + * - stack input: [x1, y1, x2, y2] + * - stack output: [x, y] + * @note We work with unbounded and unsigned integers represented in (little-endian) chunks of 256 bits. + * @note After a few discussions, we decided to set the maximum input length of the base, modulus and exponent to 32. + * See [https://github.com/0xPolygonHermez/zkevm-rom-internal/issues/43] for more details. + */ +INCLUDE "../modexp/constants.zkasm" + +INCLUDE "../modexp/modexp.zkasm" +INCLUDE "../modexp/modexp_utils.zkasm" + +INCLUDE "../modexp/array_lib/utils/array_trim.zkasm" +INCLUDE "../modexp/array_lib/utils/array_compare.zkasm" + +INCLUDE "../modexp/array_lib/array_add_AGTB.zkasm" +INCLUDE "../modexp/array_lib/array_add_short.zkasm" +INCLUDE "../modexp/array_lib/array_mul_long.zkasm" +INCLUDE "../modexp/array_lib/array_mul_short.zkasm" +INCLUDE "../modexp/array_lib/array_mul.zkasm" +INCLUDE "../modexp/array_lib/array_square.zkasm" +INCLUDE "../modexp/array_lib/array_div_short.zkasm" +INCLUDE "../modexp/array_lib/array_div_long.zkasm" +INCLUDE "../modexp/array_lib/array_div.zkasm" + +VAR GLOBAL multiplication_complexity + +VAR GLOBAL modexp_Bsize +VAR GLOBAL modexp_Esize +VAR GLOBAL modexp_Msize +VAR GLOBAL modexp_Mend +VAR GLOBAL modexp_offset +VAR GLOBAL modexp_returnIndex +VAR GLOBAL modexp_returnFirstIndex +VAR GLOBAL modexp_returnIndexRem +VAR GLOBAL expLenBits + +funcModexp: + + %MAX_CNT_BINARY - CNT_BINARY - 20 :JMPN(outOfCountersBinary) + %MAX_CNT_ARITH - CNT_ARITH - 2 :JMPN(outOfCountersArith) + %MAX_CNT_STEPS - STEP - 400 :JMPN(outOfCountersStep) + + ; Move balances if value > 0 just before executing the contract CALL + $ => B :MLOAD(txValue) + 0 => A + zkPC + 2 => RR + $ :LT, JMPC(moveBalances) + + ; read data stored in calldata + ; Bsize [32 bytes], Esize [32 bytes], Msize [32 bytes] + ; Bsize [32 bytes] + 32 :MSTORE(readXFromCalldataLength) + 0 => E :MSTORE(readXFromCalldataOffset), CALL(readFromCalldataOffset); in: [readXFromCalldataOffset: offset value, readXFromCalldataLength: length value], out: [readXFromCalldataResult: result value] + $ => A :MLOAD(readXFromCalldataResult) + A :MSTORE(modexp_Bsize) ;Bsize = base size + ; Esize [32 bytes] + E + 32 => E :MSTORE(readXFromCalldataOffset), CALL(readFromCalldataOffset); in: [readXFromCalldataOffset: offset value, readXFromCalldataLength: length value], out: [readXFromCalldataResult: result value] + $ => A :MLOAD(readXFromCalldataResult) + A :MSTORE(modexp_Esize) ;Esize = exp size + ; Msize [32 bytes] + E + 32 => E :MSTORE(readXFromCalldataOffset), CALL(readFromCalldataOffset); in: [readXFromCalldataOffset: offset value, readXFromCalldataLength: length value], out: [readXFromCalldataResult: result value] + $ => A :MLOAD(readXFromCalldataResult) + A :MSTORE(modexp_Msize) ;Msize = mod size + ; store offset modexp num values + E + 32 => E + E :MSTORE(modexp_offset) + ; get exp offset = 96 bytes (Bsize | Esize | Msize) + Bsize + $ => A :MLOAD(modexp_Bsize) + 96 => B + $ => A :ADD + $ => B :MLOAD(txCalldataLen) + ; expLenBits = bit length of first 32 bytes of exp + 0 :MSTORE(expLenBits) + ; if 96 + Bsize (exp offset) < txCalldataLen --> setExpBits, else --> expLenBits = 0 + $ :LT, JMPC(setExpBits, setMaxLen) + +setExpBits: + ; E exp offset + A => E + $ => A,C :MLOAD(modexp_Esize) + 33 => B + ; A, C = Esize + ; if Esize <= 32 --> setExpBitsContinue + $ => B :LT, JMPC(setExpBitsContinue) + 32 => C + +setExpBitsContinue: + ; read a length of bytes (C) from exp offset (E) + C :MSTORE(readXFromCalldataLength) + E :MSTORE(readXFromCalldataOffset), CALL(readFromCalldataOffset); in: [readXFromCalldataOffset: offset value, readXFromCalldataLength: length value], out: [readXFromCalldataResult: result value] + $ => A :MLOAD(readXFromCalldataResult) + ; A = first 32 bytes of exp + 32 - C => D :CALL(SHRarith) + A => B :CALL(getLenBits); A bits length first 32 bytes + ; A = bit length of first 32 bytes of exp + A :JMPZ(setMaxLen) + A - 1 :MSTORE(expLenBits) + +setMaxLen: + ; set B with max length (max(Blen, Mlen)) + $ => B :MLOAD(modexp_Msize) + $ => A :MLOAD(modexp_Bsize) + $ :LT, JMPC(calculateGas) + A => B + +; B: max_length = max(Blen, Mlen) +calculateGas: + + %MAX_CNT_BINARY - CNT_BINARY - 10 :JMPN(outOfCountersBinary) + %MAX_CNT_ARITH - CNT_ARITH - 2 :JMPN(outOfCountersArith) + %MAX_CNT_STEPS - STEP - 120 :JMPN(outOfCountersStep) + + B :MSTORE(arithA) + 7 :MSTORE(arithB), CALL(addARITH) + ; check arith overflow + $ :MLOAD(addArithOverflow), JMPNZ(outOfGas) + $ => B :MLOAD(arithRes1) + B :MSTORE(arithA) + 8 :MSTORE(arithB), CALL(divARITH) + ; B: words = (max_length + 7) / 8 + $ => B :MLOAD(arithRes1) + %MAX_GAS_WORD_MODEXP => A + $ :LT, JMPC(outOfGas) + ; A: multiplication_complexity = words**2 + B :MSTORE(arithA) + B :MSTORE(arithB), CALL(mulARITH) + $ => A :MLOAD(arithRes1) + A :MSTORE(multiplication_complexity), JMPZ(dynamicGas) + + $ => A :MLOAD(modexp_Esize) + 33 => B + ; if Esize <= 32 --> modexp_expLT32 + $ => B :LT, JMPC(modexp_expLT32) + ;elif Esize > 32: iteration_count = (8 * (Esize - 32)) + ((exponent & (2**256 - 1)).bit_length() - 1) + A :MSTORE(arithA) + 32 :MSTORE(arithB), CALL(subARITH) + $ => A :MLOAD(arithRes1) + A :MSTORE(arithA) + 8 :MSTORE(arithB), CALL(mulARITH) + ; check arith overflow + $ :MLOAD(mulArithOverflowFlag), JMPNZ(outOfGas) + ; A = 8 * (Esize - 32) + $ => A :MLOAD(arithRes1) + $ => B :MLOAD(expLenBits) + ; iteration_count = (8 * (Esize - 32)) + ((exponent & (2**256 - 1)).bit_length() - 1) + A :MSTORE(arithA) + B :MSTORE(arithB), CALL(addARITH) + ; check arith overflow + $ :MLOAD(addArithOverflow), JMPNZ(outOfGas) + $ => E :MLOAD(arithRes1), JMP(finalGas) + ; E = iteration_count + +modexp_expLT32: + $ => E :MLOAD(expLenBits) + +finalGas: + E => B + %MAX_GAS_IT_MODEXP => A + $ :LT, JMPC(outOfGas) + 1 => A + $ :LT, JMPC(dynamicGas) + 1 => E + +dynamicGas: + + %MAX_CNT_BINARY - CNT_BINARY - 9 :JMPN(outOfCountersBinary) + %MAX_CNT_ARITH - CNT_ARITH - 3 :JMPN(outOfCountersArith) + %MAX_CNT_STEPS - STEP - 55 :JMPN(outOfCountersStep) + + ; E = calculate_iteration_count = max(iteration_count, 1) + $ => A :MLOAD(multiplication_complexity) + A :MSTORE(arithA) + E :MSTORE(arithB), CALL(mulARITH) + ; check arith overflow + $ :MLOAD(mulArithOverflowFlag), JMPNZ(outOfGas) + ; A = multiplication_complexity * iteration_count + $ => A :MLOAD(arithRes1) + A :MSTORE(arithA) + 3 :MSTORE(arithB), CALL(divARITH) + ; A = multiplication_complexity * iteration_count / 3 + $ => A :MLOAD(arithRes1) + %TX_GAS_LIMIT => B + $ :LT, JMPNC(outOfGas) + 200 => B + $ :LT, JMPC(lastChecks) + A => B + +lastChecks: + B :MSTORE(preGAS) + ; B = max(200, multiplication_complexity * iteration_count / 3) + GAS - B => GAS :JMPN(outOfGas) + ; check first modulo size and base size to match ethereum specification + 0 => A + $ => B :MLOAD(modexp_Msize) + $ :EQ, JMPC(save0outMod0) ; if Msize = 0 --> save0outMod0 + ; Msize > 0 from here + $ => B :MLOAD(modexp_Bsize) + $ :EQ, JMPC(save0out) ; if Bsize = 0 --> save0out + ; Bsize > 0 from here + + ; Check maximum length allowed in the zkEVM reagrding the modExp + ; If parameters (length > %MAX_SIZE_MODEXP) --> zkEVM does a revert returning all the gas consumed + %MAX_SIZE_MODEXP => A + $ => B :MLOAD(modexp_Bsize) + $ :LT, JMPC(preFailModExpLength) ; if Bsize > MAX_SIZE_MODEXP --> preFailModExpLength + $ => B :MLOAD(modexp_Esize) + $ :LT, JMPC(preFailModExpLength) ; if Esize > MAX_SIZE_MODEXP --> preFailModExpLength + $ => B :MLOAD(modexp_Msize) + $ :LT, JMPC(preFailModExpLength) ; if Msize > MAX_SIZE_MODEXP --> preFailModExpLength + ; get base value + $ => E :MLOAD(modexp_offset) ; This is used in modexp_getBase, modexp_getExp and modexp_getMod + $ => C :MLOAD(modexp_Bsize) + :CALL(modexp_getBase) + ; get exp value + $ => C :MLOAD(modexp_Esize) + :CALL(modexp_getExp) + ; get mod value + $ => C :MLOAD(modexp_Msize) + :CALL(modexp_getMod) + 1 => B + ; if mod == 0 --> return 0 + $ => A :MLOAD(modexp_Mlen), JMPZ(save0out) + ; if Mlen != 1 --> checkExpLen + $ :EQ, JMPNC(checkExpLen) + ; if Mlen == 1 && mod == 1 --> return 0 + $ => A :MLOAD(modexp_M) + $ :EQ, JMPC(save0out) + +checkExpLen: + ; if exp == 0 --> return 1 + $ => A :MLOAD(modexp_Elen), JMPZ(save1out) + +checkBaseLen: + ; if base == 0 --> return 0 + $ => A :MLOAD(modexp_Blen), JMPZ(save0out) + ; if Blen != 1 --> callMODEXP + $ :EQ, JMPNC(callMODEXP) + ; if Blen == 1 && base == 1 --> return 1 + $ => A :MLOAD(modexp_B) + $ :EQ, JMPC(save1out) + +callMODEXP: + :CALL(modexp) + :JMP(finalMODEXP) + +save1out: + 1 :MSTORE(modexp_out), JMP(finalMODEXP) + +save0out: + $ => B :MLOAD(modexp_Msize) + %MAX_SIZE_MODEXP => A + $ :LT,JMPC(preFailModExpLength) + 0 :MSTORE(modexp_out), JMP(finalMODEXP) + +save0outMod0: + 0 :MSTORE(modexp_out), JMP(preEndMODEXP) + +finalMODEXP: + %MAX_CNT_STEPS - STEP - 100 :JMPN(outOfCountersStep) + + ; write data into memory + 0 => B + $ => C :MLOAD(modexp_Msize) + C :MSTORE(arithA) + 32 :MSTORE(arithB), CALL(divARITH) + $ => E :MLOAD(arithRes1) + E :MSTORE(modexp_returnFirstIndex) + $ => A :MLOAD(arithRes2) + A :MSTORE(modexp_returnIndexRem), JMPZ(memoryLoop) + ; if Msize % 32 > 0, copy last bytes, else --> memoryLoop + A => C + $ => A :MLOAD(modexp_out+E) + 32 - C => D :CALL(SHLarith) + A :MSTORE(bytesToStore) + B => E + :CALL(MSTOREX) ; in: [bytesToStore, E: offset, C: length] out: [E: new offset] + E => B + $ => A :MLOAD(modexp_Msize) + A - C => C :JMPZ(modexpReturn) + $ => E :MLOAD(modexp_returnFirstIndex) + +memoryLoop: + + %MAX_CNT_BINARY - CNT_BINARY - 2 :JMPN(outOfCountersBinary) + %MAX_CNT_STEPS - STEP - 50 :JMPN(outOfCountersStep) + + E - 1 => E :MSTORE(modexp_returnIndex) + $ => A :MLOAD(modexp_out+E) + A :MSTORE(bytesToStore) + B => E + :CALL(MSTORE32) ; in: [bytesToStore, E: offset] out: [E: new offset] + E => B + $ => E :MLOAD(modexp_returnIndex) + C - 32 => C :JMPNZ(memoryLoop) + +modexpReturn: + %MAX_CNT_STEPS - STEP - 100 :JMPN(outOfCountersStep) + + ; prepare return data + 0 :MSTORE(retDataOffset) + $ => C :MLOAD(modexp_Msize) + C :MSTORE(retDataLength) + $ => B :MLOAD(retCallOffset) + $ => A :MLOAD(originCTX), JMPZ(handleGas) + ; set retDataCTX + $ => E :MLOAD(currentCTX) + A => CTX + E :MSTORE(retDataCTX) + + $ => E :MLOAD(modexp_returnFirstIndex) + $ => A :MLOAD(modexp_returnIndexRem), JMPZ(returnLoop) + A => C + $ => A :MLOAD(modexp_out+E) + 32 - C => D :CALL(SHLarith) + A :MSTORE(bytesToStore) + B => E + :CALL(MSTOREX) ; in: [bytesToStore, E: offset, C: length] out: [E: new offset] + E => B + $ => A :MLOAD(modexp_Msize) + A - C => C :JMPZ(endMODEXP) + $ => E :MLOAD(modexp_returnFirstIndex) + +returnLoop: + %MAX_CNT_BINARY - CNT_BINARY - 2 :JMPN(outOfCountersBinary) + %MAX_CNT_STEPS - STEP - 50 :JMPN(outOfCountersStep) + + E - 1 => E :MSTORE(modexp_returnIndex) + $ => A :MLOAD(modexp_out+E) + A :MSTORE(bytesToStore) + B => E + :CALL(MSTORE32) ; in: [bytesToStore, E: offset] out: [E: new offset] + E => B + $ => E :MLOAD(modexp_returnIndex) + C - 32 => C :JMPZ(endMODEXP, returnLoop) + +preEndMODEXP: + $ => A :MLOAD(originCTX), JMPZ(handleGas) + A => CTX + +endMODEXP: + CTX :MSTORE(currentCTX), JMP(preEnd) \ No newline at end of file diff --git a/main/precompiled/pre-sha2-256.zkasm b/main/precompiled/pre-sha2-256.zkasm new file mode 100644 index 00000000..5b5b00dc --- /dev/null +++ b/main/precompiled/pre-sha2-256.zkasm @@ -0,0 +1,125 @@ +/** + * @link [https://www.evm.codes/precompiled#0x02?fork=berlin] + * @zk-counters + * - dynamic steps: + * - dynamic binary: + * @process-precompiled + * - stack input: [data] + * - stack output: [hash] + */ +VAR GLOBAL sha256DataOffset +VAR GLOBAL sha256DataId +VAR GLOBAL sha256Hash +VAR GLOBAL tmpZkSHA256 + +funcSHA256: + %MAX_CNT_STEPS - STEP - 100 :JMPN(outOfCountersStep) + %MAX_CNT_BINARY - CNT_BINARY - 1 :JMPN(outOfCountersBinary) + + ; Move balances if value > 0 just before executing the contract CALL + $ => B :MLOAD(txValue) + 0 => A + zkPC+2 => RR + $ :LT, JMPC(moveBalances) + + ; GAS - staticGas + GAS - %SHA2_256_GAS => GAS :JMPN(outOfGas) + + $ => C :MLOAD(txCalldataLen) + + ;words => A === (C+31)/32 => A + C + 31 => A + A :MSTORE(arithA) + 32 :MSTORE(arithB), CALL(divARITH); in: [arithA, arithB] out: [arithRes1: arithA/arithB, arithRes2: arithA%arithB] + $ => A :MLOAD(arithRes1) + + ; GAS - dynamicGas + GAS - %SHA2_256_WORD_GAS*A => GAS :JMPN(outOfGas) + + ; Compute necessary sha256 counters to finish the full hash + ; Divide the total data length + 1 by 64 to obtain the sha256 counter increment + ; 64 is the value used by the prover to increment sha256 counters + C + 1 :MSTORE(arithA) + 64 :MSTORE(arithB), CALL(divARITH); in: [arithA, arithB] out: [arithRes1: arithA/arithB, arithRes2: arithA%arithB] + $ => A :MLOAD(arithRes1) + + ; check enough sha256 counters left + %MAX_CNT_SHA256_F - CNT_SHA256_F - A :JMPN(outOfCountersSha256) + + ; prepare retData + 0 :MSTORE(retDataOffset) + 32 :MSTORE(retDataLength) + 32 :MSTORE(readXFromCalldataLength) + 0 => HASHPOS + :CALL(SHA256data) + ; get & update sha256Data ID + $ => E :MLOAD(sha256DataId) + E + 1 :MSTORE(sha256DataId) + + ; copy sha256 to memory (hash 32 bytes) + 0 => E + A :MSTORE(bytesToStore), CALL(MSTORE32); in: [bytesToStore, E: offset] out: [E: new offset] + +SHA256dataReturn: + ; handle CTX + $ => A :MLOAD(originCTX), JMPZ(handleGas) + ; set retDataCTX + $ => B :MLOAD(currentCTX) + A => CTX + B :MSTORE(retDataCTX) + B => CTX + ; copy sha256 to retData (hash 32 bytes) + $ => C :MLOAD(retCallLength) + $ => E :MLOAD(retCallOffset) + $ => CTX :MLOAD(originCTX) + C - 32 :JMPN(continueSHA256dataReturn) + 32 => C + +continueSHA256dataReturn: + $ => A :MLOAD(sha256Hash) + ; MSTORE memory origin CTX + A :MSTORE(bytesToStore), CALL(MSTOREX) ; in: [bytesToStore, E: offset, C: length] out: [E: new offset] + ; set currentCTX + CTX :MSTORE(currentCTX), JMP(preEnd) + +SHA256data: + RR :MSTORE(tmpZkSHA256) + 0 => E :MSTORE(sha256DataOffset) + +SHA256dataLoop: + %MAX_CNT_STEPS - STEP - 50 :JMPN(outOfCountersStep) + + ; Copy from calldata to hashS + C :JMPZ(computeSHA256) + C - 32 :JMPN(SHA256dataFinal) + $ => E :MLOAD(sha256DataOffset) + E :MSTORE(readXFromCalldataOffset), CALL(readFromCalldataOffset); in: [readXFromCalldataOffset: offset value, readXFromCalldataLength: length value], out: [readXFromCalldataResult: result value] + $ => A :MLOAD(readXFromCalldataResult) + E + 32 => E :MSTORE(sha256DataOffset) + + $ => E :MLOAD(sha256DataId) + 32 => D + A :HASHS(E) + C - 32 => C :JMP(SHA256dataLoop) + +SHA256dataFinal: + %MAX_CNT_STEPS - STEP - 300 :JMPN(outOfCountersStep) + + $ => E :MLOAD(sha256DataOffset) + C :MSTORE(readXFromCalldataLength) + E :MSTORE(readXFromCalldataOffset), CALL(readFromCalldataOffset); in: [readXFromCalldataOffset: offset value, readXFromCalldataLength: length value], out: [readXFromCalldataResult: result value] + $ => A :MLOAD(readXFromCalldataResult) + 32 - C => D :CALL(SHRarith) + $ => E :MLOAD(sha256DataId) + C => D + A :HASHS(E) + +computeSHA256: + %MAX_CNT_STEPS - STEP - 20 :JMPN(outOfCountersStep) + + $ => E :MLOAD(sha256DataId) + HASHPOS :HASHSLEN(E) + $ => A :HASHSDIGEST(E) + A :MSTORE(sha256Hash) + $ => RR :MLOAD(tmpZkSHA256) + :RETURN \ No newline at end of file diff --git a/main/precompiled/revert-precompiled.zkasm b/main/precompiled/revert-precompiled.zkasm index cfcef93d..dc7b7cf4 100644 --- a/main/precompiled/revert-precompiled.zkasm +++ b/main/precompiled/revert-precompiled.zkasm @@ -5,7 +5,7 @@ revertPrecompiled: ; revert touched accounts $ => SR :MLOAD(initSR), CALL(revertTouched) $${eventLog(onError, revert)} - + :CALL(revertBlockInfoTree) ; check if it is the first context $ => A :MLOAD(originCTX), JMPZ(handleGas) ; first context A => CTX :MSTORE(currentCTX) @@ -22,8 +22,4 @@ revertPrecompiled: $ => PC :MLOAD(lastPC) ; write 0 in previous context stack - 0 :MSTORE(SP++) - - ; decrease depth - $ => A :MLOAD(depth) - A - 1 :MSTORE(depth), JMP(readCode) \ No newline at end of file + 0 :MSTORE(SP++), JMP(readCode) \ No newline at end of file diff --git a/main/precompiled/selector.zkasm b/main/precompiled/selector.zkasm index a503909d..c81a55e0 100644 --- a/main/precompiled/selector.zkasm +++ b/main/precompiled/selector.zkasm @@ -1,11 +1,65 @@ INCLUDE "pre-ecrecover.zkasm" INCLUDE "revert-precompiled.zkasm" INCLUDE "identity.zkasm" +INCLUDE "pre-ecAdd.zkasm" +INCLUDE "pre-ecMul.zkasm" +INCLUDE "pre-ecPairing.zkasm" +INCLUDE "pre-modexp.zkasm" +INCLUDE "pre-sha2-256.zkasm" +INCLUDE "../pairings/constants.zkasm" +INCLUDE "../pairings/BN254/ecAdd.zkasm" +INCLUDE "../pairings/BN254/ecMul.zkasm" +INCLUDE "../pairings/ecPairing.zkasm" +INCLUDE "../pairings/FRBN254/reduceFrBN254.zkasm" +INCLUDE "../pairings/FPBN254/addFpBN254.zkasm" +INCLUDE "../pairings/FPBN254/subFpBN254.zkasm" +INCLUDE "../pairings/FPBN254/mulFpBN254.zkasm" +INCLUDE "../pairings/FPBN254/squareFpBN254.zkasm" +INCLUDE "../pairings/FPBN254/invFpBN254.zkasm" +INCLUDE "../pairings/FPBN254/reduceFpBN254.zkasm" +INCLUDE "../pairings/FP2BN254/addFp2BN254.zkasm" +INCLUDE "../pairings/FP2BN254/subFp2BN254.zkasm" +INCLUDE "../pairings/FP2BN254/mulFp2BN254.zkasm" +INCLUDE "../pairings/FP2BN254/squareFp2BN254.zkasm" +INCLUDE "../pairings/FP2BN254/escalarMulFp2BN254.zkasm" +INCLUDE "../pairings/FP2BN254/invFp2BN254.zkasm" +INCLUDE "../pairings/FP4BN254/squareFp4BN254.zkasm" +INCLUDE "../pairings/FP6BN254/addFp6BN254.zkasm" +INCLUDE "../pairings/FP6BN254/subFp6BN254.zkasm" +INCLUDE "../pairings/FP6BN254/mulFp6BN254.zkasm" +INCLUDE "../pairings/FP6BN254/escalarMulFp6BN254.zkasm" +INCLUDE "../pairings/FP6BN254/sparseMulAFp6BN254.zkasm" +INCLUDE "../pairings/FP6BN254/sparseMulBFp6BN254.zkasm" +INCLUDE "../pairings/FP6BN254/sparseMulCFp6BN254.zkasm" +INCLUDE "../pairings/FP6BN254/squareFp6BN254.zkasm" +INCLUDE "../pairings/FP6BN254/inverseFp6BN254.zkasm" +INCLUDE "../pairings/FP12BN254/mulFp12BN254.zkasm" +INCLUDE "../pairings/FP12BN254/sparseMulAFp12BN254.zkasm" +INCLUDE "../pairings/FP12BN254/sparseMulBFp12BN254.zkasm" +INCLUDE "../pairings/FP12BN254/squareFp12BN254.zkasm" +INCLUDE "../pairings/FP12BN254/inverseFp12BN254.zkasm" +INCLUDE "../pairings/FP12BN254/frobFp12BN254.zkasm" +INCLUDE "../pairings/FP12BN254/frob2Fp12BN254.zkasm" +INCLUDE "../pairings/FP12BN254/frob3Fp12BN254.zkasm" +INCLUDE "../pairings/FP12BN254/CYCLOFP12BN254/xBinDecompBN254.zkasm" +INCLUDE "../pairings/FP12BN254/CYCLOFP12BN254/compressFp12BN254.zkasm" +INCLUDE "../pairings/FP12BN254/CYCLOFP12BN254/decompressFp12BN254.zkasm" +INCLUDE "../pairings/FP12BN254/CYCLOFP12BN254/squareCompCycloFp12BN254.zkasm" +INCLUDE "../pairings/FP12BN254/CYCLOFP12BN254/squareCycloFp12BN254.zkasm" +INCLUDE "../pairings/FP12BN254/CYCLOFP12BN254/expByXCompCycloFp12BN254.zkasm" +INCLUDE "../pairings/BN254/addPointBN254.zkasm" +INCLUDE "../pairings/BN254/escalarMulBN254.zkasm" +INCLUDE "../pairings/BN254/lineSamePointsBN254.zkasm" +INCLUDE "../pairings/BN254/lineDiffPointsBN254.zkasm" +INCLUDE "../pairings/halfPairingBN254.zkasm" +INCLUDE "../pairings/millerLoopBN254.zkasm" +INCLUDE "../pairings/loopLengthBN254.zkasm" +INCLUDE "../pairings/finalExpBN254.zkasm" INCLUDE "end.zkasm" /** * Selector precompiled contract to run - * Current precompiled supported: ECRECOVER & IDENTITY + * Current precompiled supported: ECRECOVER, SHA2-256, IDENTITY, MODEXP, ECADD, ECMUL, ECPAIRING * @param {A} - Precompiled address * @dev Any call to an unsupported precompiled will result in a revert * - All gas is refunded @@ -13,11 +67,11 @@ INCLUDE "end.zkasm" */ selectorPrecompiled: A - 2 :JMPN(funcECRECOVER) - A - 3 :JMPN(revertPrecompiled) ;:JMPN(SHA256) + A - 3 :JMPN(funcSHA256) A - 4 :JMPN(revertPrecompiled) ;:JMPN(RIPEMD160) A - 5 :JMPN(IDENTITY) - A - 6 :JMPN(revertPrecompiled) ;:JMPN(MODEXP) - A - 7 :JMPN(revertPrecompiled) ;:JMPN(ECADD) - A - 8 :JMPN(revertPrecompiled) ;:JMPN(ECMUL) - A - 9 :JMPN(revertPrecompiled) ;:JMPN(ECPAIRING) - A - 10 :JMPN(revertPrecompiled) ;:JMPN(BLAKE2F) \ No newline at end of file + A - 6 :JMPN(funcModexp) + A - 7 :JMPN(funcEcAdd) + A - 8 :JMPN(funcEcMul) + A - 9 :JMPN(funcEcPairing) + A - 10 :JMPN(revertPrecompiled) ;:JMPN(BLAKE2F) \ No newline at end of file diff --git a/main/process-change-l2-block.zkasm b/main/process-change-l2-block.zkasm new file mode 100644 index 00000000..75581d64 --- /dev/null +++ b/main/process-change-l2-block.zkasm @@ -0,0 +1,147 @@ +processChangeL2Block: + + ; checks zk-counters + %MAX_CNT_POSEIDON_G - CNT_POSEIDON_G - %MAX_CNT_POSEIDON_SLOAD_SSTORE*6 :JMPN(outOfCountersPoseidon) + $ => A :MLOAD(cntKeccakPreProcess) + %MAX_CNT_KECCAK_F - CNT_KECCAK_F - A - 2 :JMPN(outOfCountersKeccak) + %MAX_CNT_STEPS - STEP - 500 :JMPN(outOfCountersStep) + %MAX_CNT_BINARY - CNT_BINARY - 8 :JMPN(outOfCountersBinary) + + ; If it is not the first transaction, we must consolidate previous block + $ => A :MLOAD(currentTx) + A - 1 :JMPZ(continueProcessChangeL2Block) + :CALL(consolidateBlock) + +continueProcessChangeL2Block: + $${eventLog(onStartBlock)} + ; Reset tx index, logIndex and cumulative gas used + 0 :MSTORE(txIndex) + 0 :MSTORE(cumulativeGasUsed) + 0 :MSTORE(currentLogIndex) + ;; Set block hash (current state root) on storage + ; Update state root mapping + 32 => D + 0 => HASHPOS ; A new hash with position 0 is started + $ => E :MLOAD(lastHashKIdUsed) + E + 1 => E :MSTORE(lastHashKIdUsed) + + %ADDRESS_SYSTEM => A + %SMT_KEY_SC_STORAGE => B + $ => C :MLOAD(blockNum) + C :HASHK(E) + %STATE_ROOT_STORAGE_POS :HASHK(E) + HASHPOS :HASHKLEN(E) + $ => C :HASHKDIGEST(E) + SR => D :MSTORE(previousBlockHash) + $ => SR :SSTORE, CALL(initBlockInfoTree) + + ; Read block number, increase it by 1 and write it + ; Get last block number + $ => A :MLOAD(blockNum) + + ; Update last block number at system storage + 1 => B + $ => D :ADD, MSTORE(blockNum) + %LAST_BLOCK_STORAGE_POS => C + %ADDRESS_SYSTEM => A + %SMT_KEY_SC_STORAGE => B + $ => SR :SSTORE + + ; Load current timestamp + %TIMESTAMP_STORAGE_POS => C + %ADDRESS_SYSTEM => A + %SMT_KEY_SC_STORAGE => B + $ => A :SLOAD ; currentTimestamp => A + + $ => B :MLOAD(timestampLimit) ; timestampLimit => B + + ; If it is NOT a forced tx ==> verify Timestamp & L1InfoRoot + $ :MLOAD(isForced), JMPZ(verifyTimestampAndL1InfoRoot) + + ; forced batch + ; - update timestamp only if currentTimestamp < limitTimestamp + ; - set blockHash to default + $ => C :MLOAD(forcedBlockHashL1) + C :MSTORE(blockHashL1InfoTree) + A :MSTORE(timestamp) + $ :LT, JMPNC(initSetGERL1InfoTree) + +newForcedTimestamp: + B :MSTORE(timestamp), JMP(setNewTimestamp) + +verifyTimestampAndL1InfoRoot: + $ => B :MLOAD(deltaTimestamp) + ; Addition of two values of 8 bytes [B: currentTimestamp(A) + deltaTimestamp(B)] + $ => B :ADD, MSTORE(timestamp) + + ; Verify (currentTimestamp + deltaTimestamp) <= limitTimestamp + $ => A :MLOAD(timestampLimit) + $ :LT, JMPC(invalidChangeL2BlockLimitTimestamp) + + ; Set new timestamp + %TIMESTAMP_STORAGE_POS => C + %ADDRESS_SYSTEM => A + %SMT_KEY_SC_STORAGE => B + $ => D :MLOAD(timestamp) + $ => SR :SSTORE + + ; check indexL1InfoTree != 0 to verify data L1InfoTree + $ :MLOAD(indexL1InfoTree), JMPZ(skipSetGERL1InfoTree) + +${getL1InfoGER(mem.indexL1InfoTree)} => A :MSTORE(gerL1InfoTree) +${getL1InfoBlockHash(mem.indexL1InfoTree)} => B :MSTORE(blockHashL1InfoTree) +${getL1InfoTimestamp(mem.indexL1InfoTree)} => C :MSTORE(timestampL1InfoTree) + :CALL(verifyMerkleProof) + + ; Verify (currentTimestamp + deltaTimestamp) >= l1InfoRoot.timestamp + $ => A :MLOAD(timestamp) + $ => B :MLOAD(timestampL1InfoTree) + $ :LT, JMPC(invalidChangeL2BlockMinTimestamp, initSetGERL1InfoTree) + +setNewTimestamp: + ; Set new timestamp + %TIMESTAMP_STORAGE_POS => C + %ADDRESS_SYSTEM => A + %SMT_KEY_SC_STORAGE => B + $ => D :MLOAD(timestamp) + $ => SR :SSTORE + +initSetGERL1InfoTree: + ; Set new GER + $ => A :MLOAD(gerL1InfoTree) + ; If it is a forced tx ==> gerL1InfoTree = l1InfoRoot + $ :MLOAD(isForced), JMPZ(setGERL1InfoTree) + $ => A :MLOAD(l1InfoRoot) + A :MSTORE(gerL1InfoTree) + +setGERL1InfoTree: + 0 => B + ; Do not set if zero + $ :EQ, JMPC(skipSetGERL1InfoTree) + 0 => HASHPOS + $ => E :MLOAD(lastHashKIdUsed) + E + 1 => E :MSTORE(lastHashKIdUsed) + + 32 => D + A :HASHK(E) + %GLOBAL_EXIT_ROOT_STORAGE_POS :HASHK(E) ; Storage position of the global exit root map + HASHPOS :HASHKLEN(E) + $ => C :HASHKDIGEST(E) + + ; read blockHashL1InfoTree given the l1InfoRoot + ; skip overwrite blockHashL1 if it is different than 0 (already set) + %ADDRESS_GLOBAL_EXIT_ROOT_MANAGER_L2 => A + %SMT_KEY_SC_STORAGE => B + $ => A :SLOAD + 0 => B + $ :EQ, JMPNC(skipSetGERL1InfoTree) + + ; write blockhashL1 + %ADDRESS_GLOBAL_EXIT_ROOT_MANAGER_L2 => A + %SMT_KEY_SC_STORAGE => B + $ => D :MLOAD(blockHashL1InfoTree) + $ => SR :SSTORE ; Store 'blockHashL1InfoTree' in storage position 'keccak256(gerL1InfoTree, 0)' + +skipSetGERL1InfoTree: + :CALL(setupNewBlockInfoTree) + :JMP(txLoop) \ No newline at end of file diff --git a/main/process-tx.zkasm b/main/process-tx.zkasm index 0fa24e22..07dc98dd 100644 --- a/main/process-tx.zkasm +++ b/main/process-tx.zkasm @@ -2,7 +2,7 @@ INCLUDE "map-opcodes.zkasm" INCLUDE "precompiled/selector.zkasm" INCLUDE "ecrecover/ecrecover.zkasm" INCLUDE "touched.zkasm" -INCLUDE "2-exp.zkasm" +INCLUDE "tables/2-exp.zkasm" ; Blocks process txs ; A - Verify ecdsa signature @@ -26,26 +26,18 @@ processTx: ;; Store init state ;;;;;;;;; - ; Store initial state at the beginning of the transaction - SR :MSTORE(originSR) SR :MSTORE(initSR) CTX :MSTORE(currentCTX) + ; Minimum of 100000 steps left to process a tx - %MAX_CNT_STEPS - STEP - 100000 :JMPN(outOfCountersStep) - %MAX_CNT_BINARY - CNT_BINARY - 100 :JMPN(outOfCountersBinary) - %MAX_CNT_ARITH - CNT_ARITH - 2 :JMPN(outOfCountersArith) + %MAX_CNT_STEPS - STEP - 100000 :JMPN(outOfCountersStep) + %MAX_CNT_BINARY - CNT_BINARY - 100 :JMPN(outOfCountersBinary) + %MAX_CNT_ARITH - CNT_ARITH - 2 :JMPN(outOfCountersArith) - $ => A :MLOAD(txHash) ; Check the signature - $ => B :MLOAD(txR) - $ => C :MLOAD(txS) - $ => D :MLOAD(txV), CALL(ecrecover_tx) - ; Check result is non-zero -checkAndSaveFrom: - 0 => B - A :MSTORE(txSrcAddr) + $ => A :MLOAD(txSrcAddr) A :MSTORE(txSrcOriginAddr) - $ :EQ,JMPC(invalidIntrinsicTxSignature) + $ :MLOAD(ecrecoverErrorCode), JMPNZ(invalidIntrinsicTxSignature) ;;;;;;;;;;;;;;;;;; ;; B - Verify tx.sender does not have any code deployed (EIP3607) @@ -69,8 +61,9 @@ endCheckChainId: ;; Reset warm/cold information $ => A :MLOAD(txSrcOriginAddr), CALL(initTouchedTree) :CALL(isColdAddress) ; add tx.origin to touched addresses - 0 :MSTORE(depth) ; Initial depth is 0 +; Set tx status to success by default + 1 :MSTORE(txStatus),CALL(checkpointBlockInfoTree) ;; Set gasPrice global var depending on effectivePercentage [0-255] -> txGasPrice = Floor((gasPrice * (effectivePercentage + 1)) / 256) ; gasPrice => A $ => A :MLOAD(txGasPriceRLP) @@ -85,12 +78,12 @@ endCheckChainId: ; get value above 256 bits ${_effGasPriceShifted >> 256} => D ; compute ARITH - ${_effGasPriceShifted} => E :ARITH + ${_effGasPriceShifted} => E :ARITH ; txGasPrice = _effGasPriceShifted / 256 256 => B ; (_effGasPriceShifted / 256)(A) * 256(B) + (_effGasPriceShifted % 256)(C) = D * 2**256 + op(E) - ${_effGasPriceShifted / 256} => A :MSTORE(txGasPrice) + ${_effGasPriceShifted / 256} => A :MSTORE(txGasPrice) ${_effGasPriceShifted % 256} => C ; compute ARITH E :ARITH @@ -143,7 +136,7 @@ addGas: 0 => C :JMP(loopBytes) loopBytes: - %MAX_CNT_STEPS - STEP - 10 :JMPN(outOfCountersStep) + %MAX_CNT_STEPS - STEP - 10 :JMPN(outOfCountersStep) A - C - 1 :JMPN(endCalldataIntrinsicGas) E => B $ => E :MLOAD(batchHashDataId) @@ -187,16 +180,16 @@ endCalldataIntrinsicGas: C => A $ :LT, JMPC(invalidIntrinsicTxBalance) - ; Substract (gas price * gas limit) from caller balance + ; Subtract (gas price * gas limit) from caller balance C :MSTORE(arithA) D :MSTORE(arithB), CALL(subARITH) - ; Substracted balance result in D + ; Subtracted balance result in D $ => D :MLOAD(arithRes1) $ => A :MLOAD(txSrcOriginAddr) 0 => B,C $ => SR :SSTORE - ; Store state root with upfront cost substracted and nonce increased + ; Store state root with upfront cost subtracted and nonce increased SR :MSTORE(initSR) ; Substract intrinsic gas @@ -279,7 +272,7 @@ create2: 136 :MSTORE(arithB), CALL(divARITH); in: [arithA, arithB] out: [arithRes1: arithA/arithB, arithRes2: arithA%arithB] $ => B :MLOAD(arithRes1) $ => A :MLOAD(cntKeccakPreProcess) - ; -2 because we will use one more keccack for generating contract address + ; -2 because we will use one more keccak for generating contract address %MAX_CNT_KECCAK_F - CNT_KECCAK_F - A - 2 - B :JMPN(outOfCountersKeccak) $ => CTX :MLOAD(originCTX) @@ -333,10 +326,10 @@ endContractAddress: ;; deploy contract in state-tree deploy: - %MAX_CNT_STEPS - STEP - 200 :JMPN(outOfCountersStep) + %MAX_CNT_STEPS - STEP - 200 :JMPN(outOfCountersStep) %MAX_CNT_POSEIDON_G - CNT_POSEIDON_G - %MAX_CNT_POSEIDON_SLOAD_SSTORE*3 :JMPN(outOfCountersPoseidon) - %MAX_CNT_BINARY - CNT_BINARY - 3 :JMPN(outOfCountersBinary) - :CALL(isColdAddress) ; add address to touched addresses + %MAX_CNT_BINARY - CNT_BINARY - 3 :JMPN(outOfCountersBinary) + :CALL(isColdAddress) ; add address to touched addresses ; check if address is deployable ( nonce == bytecode == 0) A => E @@ -464,9 +457,9 @@ readCode: ;; Compute and save hash bytecode and bytecode length in the state-tree endDeploy: ; checks zk-counters - %MAX_CNT_STEPS - STEP - 400 :JMPN(outOfCountersStep) + %MAX_CNT_STEPS - STEP - 400 :JMPN(outOfCountersStep) %MAX_CNT_POSEIDON_G - CNT_POSEIDON_G - %MAX_CNT_POSEIDON_SLOAD_SSTORE*2 :JMPN(outOfCountersPoseidon) - + %MAX_CNT_BINARY - CNT_BINARY - 2 :JMPN(outOfCountersBinary) ; called from `opRETURNDeploy` which has: C --> length, E --> offset ; only when first context ends on deploy ; If length is 0 do not modify state-tree @@ -489,7 +482,7 @@ endDeploy: $ => A :MLOAD(createContractAddress) 0 => C %SMT_KEY_SC_CODE => B - $ => SR :SSTORE + $ => SR :SSTORE, JMP(handleGas) ;;;;;;;;;;;;;;;;;; ;; G - Handle GAS @@ -497,11 +490,14 @@ endDeploy: ;; - Return gas not used to caller ;; - Pay gas to sequencer ;;;;;;;;;;;;;;;;;; - +handleGasFromError: + ; Set tx status to failure + 0 :MSTORE(txStatus) ;; compute maximum gas to refund handleGas: - %MAX_CNT_STEPS - STEP - 200 :JMPN(outOfCountersStep) + %MAX_CNT_STEPS - STEP - 200 :JMPN(outOfCountersStep) %MAX_CNT_POSEIDON_G - CNT_POSEIDON_G - %MAX_CNT_POSEIDON_SLOAD_SSTORE*4 :JMPN(outOfCountersPoseidon) + %MAX_CNT_BINARY - CNT_BINARY - 2 :JMPN(outOfCountersBinary) 0 => A $ => B :MLOAD(gasRefund), JMPZ(refundGas) $ => A :MLOAD(txGasLimit) @@ -557,35 +553,34 @@ sendGasSeq: $ => D :MLOAD(arithRes1) $ => A :MLOAD(sequencerAddr) 0 => B,C ; balance key smt - $ => SR :SSTORE, JMP(processTxEnd) + $ => SR :SSTORE, JMP(processTxFinished) ;; handle invalid transaction due to intrinsic checks invalidIntrinsicTxSignature: - $${eventLog(onError, intrinsic_invalid_signature)} :JMP(handleIntrinsicError) + $${eventLog(onError, intrinsic_invalid_signature)} :JMP(handleIntrinsicError) invalidIntrinsicTxChainId: - $${eventLog(onError, intrinsic_invalid_chain_id)} :JMP(handleIntrinsicError) + $${eventLog(onError, intrinsic_invalid_chain_id)} :JMP(handleIntrinsicError) invalidIntrinsicTxNonce: - $${eventLog(onError, intrinsic_invalid_nonce)} :JMP(handleIntrinsicError) + $${eventLog(onError, intrinsic_invalid_nonce)} :JMP(handleIntrinsicError) invalidIntrinsicTxGasLimit: - $${eventLog(onError, intrinsic_invalid_gas_limit)} :JMP(handleIntrinsicError) + $${eventLog(onError, intrinsic_invalid_gas_limit)} :JMP(handleIntrinsicError) invalidIntrinsicTxGasOverflow: - $${eventLog(onError, intrinsic_invalid_gas_overflow)} :JMP(handleIntrinsicError) + $${eventLog(onError, intrinsic_invalid_gas_overflow)} :JMP(handleIntrinsicError) invalidIntrinsicTxBalance: - $${eventLog(onError, intrinsic_invalid_balance)} :JMP(handleIntrinsicError) + $${eventLog(onError, intrinsic_invalid_balance)} :JMP(handleIntrinsicError) invalidIntrinsicBatchGasLimit: - $${eventLog(onError, intrinsic_invalid_batch_gas_limit)} :JMP(handleIntrinsicError) + $${eventLog(onError, intrinsic_invalid_batch_gas_limit)}:JMP(handleIntrinsicError) invalidIntrinsicTxSenderCode: - $${eventLog(onError, intrinsic_invalid_sender_code)} :JMP(handleIntrinsicError) - + $${eventLog(onError, intrinsic_invalid_sender_code)} :JMP(handleIntrinsicError) handleIntrinsicError: - $ => SR :MLOAD(originSR), JMP(processTxFinished) + $ => SR :MLOAD(originSR), JMP(processIntrinsicTxFinished) ;; handle error no more bytecode to read defaultOpCode: diff --git a/main/2-exp.zkasm b/main/tables/2-exp.zkasm similarity index 100% rename from main/2-exp.zkasm rename to main/tables/2-exp.zkasm diff --git a/main/touched.zkasm b/main/touched.zkasm index 6ca50e67..32b82c67 100644 --- a/main/touched.zkasm +++ b/main/touched.zkasm @@ -22,8 +22,8 @@ revertTouched: ; @out D => if the address is cold [0 if warm, 1 if cold] isColdAddress: ; checks zk-counters - %MAX_CNT_STEPS - STEP - 100 :JMPN(outOfCountersStep) - %MAX_CNT_BINARY - CNT_BINARY - 2 :JMPN(outOfCountersBinary) + %MAX_CNT_STEPS - STEP - 100 :JMPN(outOfCountersStep) + %MAX_CNT_BINARY - CNT_BINARY - 3 :JMPN(outOfCountersBinary) %MAX_CNT_POSEIDON_G - CNT_POSEIDON_G - %MAX_CNT_POSEIDON_SLOAD_SSTORE*2 :JMPN(outOfCountersPoseidon) ; store previous registers values temporary B :MSTORE(tmpB) @@ -80,8 +80,9 @@ finishColdPrecompiled: ; @out A => if the storage slot is cold [0 if warm, 1 if cold] isColdSlot: ; checks zk-counters - %MAX_CNT_STEPS - STEP - 100 :JMPN(outOfCountersStep) + %MAX_CNT_STEPS - STEP - 100 :JMPN(outOfCountersStep) %MAX_CNT_POSEIDON_G - CNT_POSEIDON_G - %MAX_CNT_POSEIDON_SLOAD_SSTORE*2 :JMPN(outOfCountersPoseidon) + %MAX_CNT_BINARY - CNT_BINARY - 1 :JMPN(outOfCountersBinary) ; store previous registers values temporary B :MSTORE(tmpB) D :MSTORE(tmpD) @@ -94,10 +95,10 @@ isColdSlot: ; read from touched tree if slot is warm ; A register already set %SMT_KEY_TOUCHED_SLOTS => B - $ => D :SLOAD, JMPZ(markWarmSlot) + $ => D :SLOAD, JMPZ(markWarmSlot) ; slot is warm. A = 0 - 0 => A :JMP(finishColdSlot) + 0 => A :JMP(finishColdSlot) ; set address to warm and return 0 markWarmSlot: diff --git a/main/utils.zkasm b/main/utils.zkasm index d7314dcd..45d5637a 100644 --- a/main/utils.zkasm +++ b/main/utils.zkasm @@ -1,6 +1,6 @@ ; @info Get absolute value and sign ; @in A => number to convert -; @out A => Absolut value of A +; @out A => Absolute value of A ; @out B => Sign of A [1 if negative, 0 positive] abs: ; check zk-counters @@ -39,8 +39,8 @@ getLenBytes: getLenBytesLoop: ; checks zk-counters - %MAX_CNT_STEPS - STEP - 10 :JMPN(outOfCountersStep) - %MAX_CNT_BINARY - CNT_BINARY - 1 :JMPN(outOfCountersBinary) + %MAX_CNT_STEPS - STEP - 10 :JMPN(outOfCountersStep) + %MAX_CNT_BINARY - CNT_BINARY - 1 :JMPN(outOfCountersBinary) 0 => B ; if A is zero, finish counter @@ -77,8 +77,8 @@ getLenBits: getLenBitsLoop: ; checks zk-counters - %MAX_CNT_STEPS - STEP - 10 :JMPN(outOfCountersStep) - %MAX_CNT_BINARY - CNT_BINARY - 1 :JMPN(outOfCountersBinary) + %MAX_CNT_STEPS - STEP - 10 :JMPN(outOfCountersStep) + %MAX_CNT_BINARY - CNT_BINARY - 1 :JMPN(outOfCountersBinary) 0 => B ; if B is zero, finish counter $ :EQ,JMPC(getLenBitsEnd) @@ -126,9 +126,9 @@ MSTOREX: ; @out E => new offset MSTORE32: ; checks zk-counters - %MAX_CNT_STEPS - STEP - 50 :JMPN(outOfCountersStep) - %MAX_CNT_BINARY - CNT_BINARY - 1 :JMPN(outOfCountersBinary) - %MAX_CNT_MEM_ALIGN - CNT_MEM_ALIGN - 1 :JMPN(outOfCountersMemalign) + %MAX_CNT_STEPS - STEP - 50 :JMPN(outOfCountersStep) + %MAX_CNT_BINARY - CNT_BINARY - 1 :JMPN(outOfCountersBinary) + %MAX_CNT_MEM_ALIGN - CNT_MEM_ALIGN - 1 :JMPN(outOfCountersMemalign) ; store current registries RR :MSTORE(tmpZkPCmstore) A :MSTORE(tmpVarAmstore) @@ -270,9 +270,9 @@ VAR GLOBAL isMLOADX ; @out E => new offset MLOADX: ; check zk-counters - %MAX_CNT_STEPS - STEP - 100 :JMPN(outOfCountersStep) - %MAX_CNT_BINARY - CNT_BINARY - 2 :JMPN(outOfCountersBinary) - %MAX_CNT_MEM_ALIGN - CNT_MEM_ALIGN - 1 :JMPN(outOfCountersMemalign) + %MAX_CNT_STEPS - STEP - 100 :JMPN(outOfCountersStep) + %MAX_CNT_BINARY - CNT_BINARY - 2 :JMPN(outOfCountersBinary) + %MAX_CNT_MEM_ALIGN - CNT_MEM_ALIGN - 1 :JMPN(outOfCountersMemalign) 32 - C :JMPN(errorMLOADMSTORE) 32 - C - 1 :JMPN(MLOAD32) @@ -284,9 +284,9 @@ MLOADX: ; @out E => new offset MLOAD32: ; check zk-counters - %MAX_CNT_STEPS - STEP - 100 :JMPN(outOfCountersStep) - %MAX_CNT_BINARY - CNT_BINARY - 2 :JMPN(outOfCountersBinary) - %MAX_CNT_MEM_ALIGN - CNT_MEM_ALIGN - 1 :JMPN(outOfCountersMemalign) + %MAX_CNT_STEPS - STEP - 100 :JMPN(outOfCountersStep) + %MAX_CNT_BINARY - CNT_BINARY - 2 :JMPN(outOfCountersBinary) + %MAX_CNT_MEM_ALIGN - CNT_MEM_ALIGN - 1 :JMPN(outOfCountersMemalign) ; store current registries RR :MSTORE(tmpZkPCmload) B :MSTORE(tmpVarBmload) @@ -299,7 +299,7 @@ MLOAD32: initMLOAD: :CALL(offsetUtil); in: [A: offset] out: [E: offset/32, C: offset%32] - ; if C has value, bytes splitted in two memory slots + ; if C has value, bytes split in two memory slots C :JMPNZ(memAlignOptionMLOAD) ; load memory from one slot $ => A :MLOAD(MEM:E) @@ -348,8 +348,8 @@ VAR GLOBAL tmpVarDemptyAcc ; @out E => isEmpty => 1 = true, 0 = false isEmptyAccount: ; check zk-counters - %MAX_CNT_STEPS - STEP - 50 :JMPN(outOfCountersStep) - %MAX_CNT_BINARY - CNT_BINARY - 3 :JMPN(outOfCountersBinary) + %MAX_CNT_STEPS - STEP - 50 :JMPN(outOfCountersStep) + %MAX_CNT_BINARY - CNT_BINARY - 3 :JMPN(outOfCountersBinary) %MAX_CNT_POSEIDON_G - CNT_POSEIDON_G - %MAX_CNT_POSEIDON_SLOAD_SSTORE*3 :JMPN(outOfCountersPoseidon) ; store current registries @@ -457,7 +457,7 @@ VAR GLOBAL tmpZkPCsaveMem ; @in: lastMemLength: size of the bytes to copy saveMem: ; check zk-counters - %MAX_CNT_STEPS - STEP - 100 :JMPN(outOfCountersStep) + %MAX_CNT_STEPS - STEP - 100 :JMPN(outOfCountersStep) %MAX_CNT_BINARY - CNT_BINARY - 5 :JMPN(outOfCountersBinary) RR :MSTORE(tmpZkPCsaveMem) A :MSTORE(tmpVarAsaveMem) @@ -559,7 +559,7 @@ setAddArithOverflow: finishAddArith: $ => RR :MLOAD(tmpZkPCArith), JMP(loadTmp) -; @info binary substraction +; @info binary subtraction ; @in: arithA: minuend value ; @in: arithB: subtrahend value ; @out: arithRes1: arithA - arithB @@ -660,18 +660,18 @@ divisorSmallerDiv: :RETURN loadTmp: - $ => A :MLOAD(tmpVarAArith) - $ => B :MLOAD(tmpVarBArith) - $ => C :MLOAD(tmpVarCArith) - $ => D :MLOAD(tmpVarDArith) - $ => E :MLOAD(tmpVarEArith), RETURN + $ => A :MLOAD(tmpVarAArith) + $ => B :MLOAD(tmpVarBArith) + $ => C :MLOAD(tmpVarCArith) + $ => D :MLOAD(tmpVarDArith) + $ => E :MLOAD(tmpVarEArith), RETURN storeTmp: - A :MSTORE(tmpVarAArith) - B :MSTORE(tmpVarBArith) - C :MSTORE(tmpVarCArith) - D :MSTORE(tmpVarDArith) - E :MSTORE(tmpVarEArith), RETURN + A :MSTORE(tmpVarAArith) + B :MSTORE(tmpVarBArith) + C :MSTORE(tmpVarCArith) + D :MSTORE(tmpVarDArith) + E :MSTORE(tmpVarEArith), RETURN VAR GLOBAL tmpSHXZkPC VAR GLOBAL tmpSHXZkPC2 @@ -756,9 +756,9 @@ SHRarithfinal: ;@out A - A << D => A SHLarith: ; check zk-counters - %MAX_CNT_STEPS - STEP - 100 :JMPN(outOfCountersStep) - %MAX_CNT_BINARY - CNT_BINARY - 4 :JMPN(outOfCountersBinary) - %MAX_CNT_ARITH - CNT_ARITH - 2 :JMPN(outOfCountersArith) + %MAX_CNT_STEPS - STEP - 100 :JMPN(outOfCountersStep) + %MAX_CNT_BINARY - CNT_BINARY - 4 :JMPN(outOfCountersBinary) + %MAX_CNT_ARITH - CNT_ARITH - 2 :JMPN(outOfCountersArith) RR :MSTORE(tmpSHXZkPC2) B :MSTORE(tmpVarBSHX) C :MSTORE(tmpVarCSHX) @@ -777,9 +777,9 @@ SHLarith: :JMP(SHLarithinit) SHLarithBit: ; check zk-counters - %MAX_CNT_STEPS - STEP - 100 :JMPN(outOfCountersStep) - %MAX_CNT_BINARY - CNT_BINARY - 2 :JMPN(outOfCountersBinary) - %MAX_CNT_ARITH - CNT_ARITH - 1 :JMPN(outOfCountersArith) + %MAX_CNT_STEPS - STEP - 100 :JMPN(outOfCountersStep) + %MAX_CNT_BINARY - CNT_BINARY - 2 :JMPN(outOfCountersBinary) + %MAX_CNT_ARITH - CNT_ARITH - 1 :JMPN(outOfCountersArith) RR :MSTORE(tmpSHXZkPC2) B :MSTORE(tmpVarBSHX) C :MSTORE(tmpVarCSHX) @@ -826,47 +826,52 @@ SHLarithfinal: ; out of counters full tracer event trigger outOfCountersStep: - $${eventLog(onError, OOCS)} :JMP(handleBatchError) + $${eventLog(onError, OOCS)} :JMP(handleBatchError) outOfCountersKeccak: - $${eventLog(onError, OOCK)} :JMP(handleBatchError) + $${eventLog(onError, OOCK)} :JMP(handleBatchError) outOfCountersBinary: - $${eventLog(onError, OOCB)} :JMP(handleBatchError) + $${eventLog(onError, OOCB)} :JMP(handleBatchError) outOfCountersMemalign: - $${eventLog(onError, OOCM)} :JMP(handleBatchError) + $${eventLog(onError, OOCM)} :JMP(handleBatchError) outOfCountersArith: - $${eventLog(onError, OOCA)} :JMP(handleBatchError) + $${eventLog(onError, OOCA)} :JMP(handleBatchError) outOfCountersPadding: - $${eventLog(onError, OOCPA)} :JMP(handleBatchError) + $${eventLog(onError, OOCPA)} :JMP(handleBatchError) outOfCountersPoseidon: - $${eventLog(onError, OOCPO)} :JMP(handleBatchError) + $${eventLog(onError, OOCPO)} :JMP(handleBatchError) +outOfCountersSha256: + $${eventLog(onError, OOCSH)} :JMP(handleBatchError) +invalidChangeL2BlockLimitTimestamp: + $${eventLog(onError, invalid_change_l2_block_limit_timestamp)} :JMP(handleBatchError) +invalidChangeL2BlockMinTimestamp: + $${eventLog(onError, invalid_change_l2_block_min_timestamp)} :JMP(handleBatchError) outOfGas: - $${eventLog(onError, OOG)} :JMP(handleError) + $${eventLog(onError, OOG)} :JMP(handleError) invalidJump: - $${eventLog(onError, invalidJump)} :JMP(handleError) + $${eventLog(onError, invalidJump)} :JMP(handleError) invalidOpcode: - $${eventLog(onError, invalidOpcode)} :JMP(handleError) + $${eventLog(onError, invalidOpcode)} :JMP(handleError) stackUnderflow: - $${eventLog(onError, underflow)} :JMP(handleError) + $${eventLog(onError, underflow)} :JMP(handleError) stackOverflow: - $${eventLog(onError, overflow)} :JMP(handleError) + $${eventLog(onError, overflow)} :JMP(handleError) deployAddressCollision: - $${eventLog(onError, invalidAddressCollision)} :JMP(handleError) + $${eventLog(onError, invalidAddressCollision)} :JMP(handleError) invalidStaticTx: - $${eventLog(onError, invalidStaticTx)} :JMP(handleError) + $${eventLog(onError, invalidStaticTx)} :JMP(handleError) invalidCodeSize: - $${eventLog(onError, invalidCodeSize)} :JMP(handleError) + $${eventLog(onError, invalidCodeSize)} :JMP(handleError) invalidCodeStartsEF: - $${eventLog(onError, invalidCodeStartsEF)} :JMP(handleError) + $${eventLog(onError, invalidCodeStartsEF)} :JMP(handleError) handleError: - %MAX_CNT_STEPS - STEP - 500 :JMPN(outOfCountersStep) - %MAX_CNT_BINARY - CNT_BINARY - 2 :JMPN(outOfCountersBinary) + %MAX_CNT_STEPS - STEP - 500 :JMPN(outOfCountersStep) + %MAX_CNT_BINARY - CNT_BINARY - 2 :JMPN(outOfCountersBinary) ;revert all state changes $ => SR :MLOAD(initSR), CALL(revertTouched) - ;remaining gas = 0 - $ => A :MLOAD(originCTX) - 0 => B - $ :EQ,JMPC(firstContextInvalid) + :CALL(revertBlockInfoTree) + + $ => A :MLOAD(originCTX), JMPZ(errorAtFirstContext) A => CTX ; Add return data context value to origin context ; Clear return data context @@ -875,21 +880,22 @@ handleError: $ => GAS :MLOAD(gasCTX) $ => SP :MLOAD(lastSP) $ => PC :MLOAD(lastPC) - 0 :MSTORE(SP++) - $ => A :MLOAD(depth) - A - 1 :MSTORE(depth), JMP(readCode) + 0 :MSTORE(SP++), JMP(readCode) handleBatchError: ; restore init state root and finish batch - $ => SR :MLOAD(batchSR) + $ => SR :MLOAD(batchSR) ; if batch error is triggered while parsing the RLP, it jumps to 'appendTxsInit' ; to fill the missing bytes to complete 'batchDataHash' $ :MLOAD(isLoadingRLP),JMPNZ(appendTxsInit) - $${eventLog(onFinishTx)} :JMP(processTxsEnd) + $${eventLog(onFinishTx)} :JMP(finalizeBatch) -firstContextInvalid: +errorAtFirstContext: + ; Set tx status to failure + 0 :MSTORE(txStatus) ;save Root and jump to send gas to sequencer 0 :MSTORE(gasRefund) + ;remaining gas = 0 0 => GAS :JMP(sendGasSeq) VAR GLOBAL tmpVarAoffsetUtil @@ -929,8 +935,8 @@ moveBalances: ;;;;;;;; ; evmCALL (Move Balances) ;;;;;;;; - %MAX_CNT_STEPS - STEP - 50 :JMPN(outOfCountersStep) - %MAX_CNT_BINARY - CNT_BINARY - 3 :JMPN(outOfCountersBinary) + %MAX_CNT_STEPS - STEP - 50 :JMPN(outOfCountersStep) + %MAX_CNT_BINARY - CNT_BINARY - 5 :JMPN(outOfCountersBinary) %MAX_CNT_POSEIDON_G - CNT_POSEIDON_G - %MAX_CNT_POSEIDON_SLOAD_SSTORE*4 :JMPN(outOfCountersPoseidon) ;Check if is a delegate call $ => A :MLOAD(isDelegateCall), JMPNZ(endMoveBalances) @@ -982,10 +988,7 @@ invalidCall: GAS + A => GAS $ => SP :MLOAD(lastSP) $ => PC :MLOAD(lastPC) - 0 :MSTORE(SP++) - ; decrease depth - $ => A :MLOAD(depth) - A - 1 :MSTORE(depth), JMP(readCode) + 0 :MSTORE(SP++), JMP(readCode) VAR GLOBAL pushBytes VAR GLOBAL numBlocks @@ -997,8 +1000,8 @@ VAR GLOBAL accumulator ; @in D => bytes to read ; @out E => value read readPush: - %MAX_CNT_STEPS - STEP - 20 :JMPN(outOfCountersStep) - %MAX_CNT_BINARY - CNT_BINARY - 1 :JMPN(outOfCountersBinary) + %MAX_CNT_STEPS - STEP - 20 :JMPN(outOfCountersStep) + %MAX_CNT_BINARY - CNT_BINARY - 1 :JMPN(outOfCountersBinary) D :MSTORE(pushBytes) D => A 0 :MSTORE(accumulator) @@ -1022,8 +1025,8 @@ readPush: 0 => B readPushBlock: - %MAX_CNT_STEPS - STEP - 20 :JMPN(outOfCountersStep) - %MAX_CNT_BINARY - CNT_BINARY - 1 :JMPN(outOfCountersBinary) + %MAX_CNT_STEPS - STEP - 20 :JMPN(outOfCountersStep) + %MAX_CNT_BINARY - CNT_BINARY - 1 :JMPN(outOfCountersBinary) ; load hash contract identifier $ => E :MLOAD(contractHashId) $ => A :MLOAD(numBlocks) @@ -1060,13 +1063,13 @@ endRotate: B + 1 => B :JMP(readPushBlock) endPushInit: - $ => A :MLOAD(leftBytes), JMPZ(finalPush) + $ => A :MLOAD(leftBytes), JMPZ(finalPush) 0 => C - 0 => B :JMP(endPushLoop) + 0 => B :JMP(endPushLoop) endPushLoop: - %MAX_CNT_STEPS - STEP - 20 :JMPN(outOfCountersStep) - %MAX_CNT_BINARY - CNT_BINARY - 4 :JMPN(outOfCountersBinary) + %MAX_CNT_STEPS - STEP - 20 :JMPN(outOfCountersStep) + %MAX_CNT_BINARY - CNT_BINARY - 4 :JMPN(outOfCountersBinary) $ => A :MLOAD(leftBytes) $ :EQ, JMPC(endPushFinal) @@ -1076,7 +1079,7 @@ endPushLoop: B - 1 => A :JMP(computeFactorLoop) computeFactorLoop: - %MAX_CNT_STEPS - STEP - 10 :JMPN(outOfCountersStep) + %MAX_CNT_STEPS - STEP - 10 :JMPN(outOfCountersStep) A :JMPN(computeFactorEnd) 256*D => D A - 1 => A :JMP(computeFactorLoop) @@ -1123,8 +1126,8 @@ addBatchHashByteByByte: 1 => D utilsAddBatchHashBytebyByteLoop: - %MAX_CNT_STEPS - STEP - 50 :JMPN(outOfCountersStep) - %MAX_CNT_BINARY - CNT_BINARY - 1 :JMPN(outOfCountersBinary) + %MAX_CNT_STEPS - STEP - 50 :JMPN(outOfCountersStep) + %MAX_CNT_BINARY - CNT_BINARY - 1 :JMPN(outOfCountersBinary) 32 - D => D $ => A :MLOAD(auxBytes), CALL(SHRarith); in: [A: value, D: #bytes to right shift] out: [A: shifted result] ; get last byte in A @@ -1154,7 +1157,7 @@ VAR GLOBAL tmpZkPCEF ; @internalParam {memOffset} memory offset to read bytes from ; @internalParam {startsWithEF} flag to indicate if first deployed byte on the bytecode is 0xEF checkBytecodeStartsEF: - %MAX_CNT_STEPS - STEP - 50 :JMPN(outOfCountersStep) + %MAX_CNT_STEPS - STEP - 50 :JMPN(outOfCountersStep) ; save temporary registers A :MSTORE(tmpVarAEF) B :MSTORE(tmpVarBEF) @@ -1201,8 +1204,8 @@ VAR GLOBAL memSizeLinearPoseidon ; @internalParam {memSize} memory size to read bytes from ; @out D => resulting linear poseidon hashPoseidonLinearFromMemory: - %MAX_CNT_STEPS - STEP - 50 :JMPN(outOfCountersStep) - %MAX_CNT_BINARY - CNT_BINARY - 1 :JMPN(outOfCountersBinary) + %MAX_CNT_STEPS - STEP - 50 :JMPN(outOfCountersStep) + %MAX_CNT_BINARY - CNT_BINARY - 1 :JMPN(outOfCountersBinary) A :MSTORE(tmpVarAhashP) B :MSTORE(tmpVarBhashP) C :MSTORE(tmpVarChashP) @@ -1264,48 +1267,13 @@ VAR GLOBAL tmpVarBmask ; @in A => address not masked ; @out A => masked address maskAddress: - %MAX_CNT_STEPS - STEP - 10 :JMPN(outOfCountersStep) - %MAX_CNT_BINARY - CNT_BINARY - 1 :JMPN(outOfCountersBinary) + %MAX_CNT_STEPS - STEP - 10 :JMPN(outOfCountersStep) + %MAX_CNT_BINARY - CNT_BINARY - 1 :JMPN(outOfCountersBinary) B :MSTORE(tmpVarBmask) 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFn => B $ => A :AND $ => B :MLOAD(tmpVarBmask), RETURN -;@info: updates the address system storage with current batch and state root -updateSystemData: - ; check keccak counters - $ => A :MLOAD(cntKeccakPreProcess) - %MAX_CNT_KECCAK_F - CNT_KECCAK_F - A - 1 :JMPN(outOfCountersKeccak) - ; checks zk-counters - %MAX_CNT_STEPS - STEP - 50 :JMPN(outOfCountersStep) - %MAX_CNT_POSEIDON_G - CNT_POSEIDON_G - %MAX_CNT_POSEIDON_SLOAD_SSTORE*2 :JMPN(outOfCountersPoseidon) - %MAX_CNT_BINARY - CNT_BINARY - 1 :JMPN(outOfCountersBinary) - - ; Get last tx count - $ => A :MLOAD(txCount) - ;Update last tx Count at system storage - 1 => B - $ => D :ADD, MSTORE(txCount) - - %LAST_TX_STORAGE_POS => C - %ADDRESS_SYSTEM => A - %SMT_KEY_SC_STORAGE => B - $ => SR :SSTORE - - ;Update state root mapping - D => A - 32 => D - 0 => HASHPOS ; A new hash with position 0 is started - $ => E :MLOAD(lastHashKIdUsed) - E + 1 => E :MSTORE(lastHashKIdUsed) - A :HASHK(E) - %STATE_ROOT_STORAGE_POS :HASHK(E) - HASHPOS :HASHKLEN(E) - $ => C :HASHKDIGEST(E) - %ADDRESS_SYSTEM => A - SR => D - $ => SR :SSTORE, RETURN - VAR GLOBAL tmpVarAmulmod VAR GLOBAL tmpVarBmulmod VAR GLOBAL tmpVarDmulmod @@ -1318,7 +1286,7 @@ VAR GLOBAL tmpZkPCmulmod ; @out C utilMULMOD: ; checks zk-counters - %MAX_CNT_STEPS - STEP - 100 :JMPN(outOfCountersStep) + %MAX_CNT_STEPS - STEP - 100 :JMPN(outOfCountersStep) %MAX_CNT_BINARY - CNT_BINARY - 4 :JMPN(outOfCountersBinary) %MAX_CNT_ARITH - CNT_ARITH - 2 :JMPN(outOfCountersArith) @@ -1464,8 +1432,8 @@ expAD: ; - 3 ARITH: 1 in divARITH + 1 in 2*mulARITH ; - 5 BINARIES: 5 in divARITH ; - 100 steps (rounded up): 37 in divARITH + 11 in 2*mulARITH + 18 self - %MAX_CNT_BINARY - CNT_BINARY - 2*A :JMPN(outOfCountersBinary) - %MAX_CNT_STEPS - STEP - 50*A :JMPN(outOfCountersStep) + %MAX_CNT_BINARY - CNT_BINARY - 2*A :JMPN(outOfCountersBinary) + %MAX_CNT_STEPS - STEP - 50*A :JMPN(outOfCountersStep) expADloop: ;A exp @@ -1516,6 +1484,617 @@ failAssert: 1 => A 2 :ASSERT +VAR GLOBAL tmpZkPCVerifyMerkleProof +;@info verifies L1Info data with sibilings +;@in A: ger +;@in B: blockhashL1 +;@in C: timestamp +verifyMerkleProof: + ; check zk-counters + $ => E :MLOAD(cntKeccakPreProcess) + + ; 1 keccak for the leaf and 32 for the L1InfoTree + %MAX_CNT_KECCAK_F - CNT_KECCAK_F - E - 33 :JMPN(outOfCountersKeccak) + ; 7 steps at most per bit + 21 statics + %MAX_CNT_STEPS - STEP - 7 * 32 - 21 :JMPN(outOfCountersStep) + + RR :MSTORE(tmpZkPCVerifyMerkleProof) + + ;;;;;;;;;;;;;;;;;;;;; + ;; compute leaf value + ;;;;;;;;;;;;;;;;;;;;; + + ; new keccak address + $ => E :MLOAD(lastHashKIdUsed) + E + 1 => E :MSTORE(lastHashKIdUsed) + + ; add gerL1InfoTree (32 bytes) + 0 => HASHPOS + 32 => D + A :HASHK(E) + + ; add blockHashL1 (32 bytes) + B :HASHK(E) + + ; add timestamp (8 bytes) + 8 => D + C :HASHK(E) + + ; compute l1InfoTree Leaf value + HASHPOS :HASHKLEN(E) + $ => C :HASHKDIGEST(E) ; initial value + + ; initialization registers for smt verify + 0 => D, A + + $ => B :MLOAD(indexL1InfoTree) + + ; prepare new hash + $ => E :MLOAD(lastHashKIdUsed) + E + 1 => E :MSTORE(lastHashKIdUsed) + 32 => D + + ; - Start loop 32 levels: + ; - provide each 'indexL1InfoTree' bit to either hash left/right the merkle tree nodes + ; - compute linear combination of 'indexL1InfoTree' bits to match the 'indexL1InfoTree' itself at the end of the loop + + ; BIT 0 + 0 => HASHPOS + ${B & 0x00000001} :JMPZ(hashLeft0) + +hashRight0: + ${getSmtProof(mem.indexL1InfoTree, 0)} :HASHK(E+0) + C :HASHK(E+0) + A + 0x00000001 => A :JMP(hashBranchEnd0) + +hashLeft0: + C :HASHK(E+0) + ${getSmtProof(mem.indexL1InfoTree, 0)} :HASHK(E+0) + +hashBranchEnd0: + HASHPOS :HASHKLEN(E+0) + $ => C :HASHKDIGEST(E+0) + + ; BIT 1 + 0 => HASHPOS + ${B & 0x00000002} :JMPZ(hashLeft1) + +hashRight1: + ${getSmtProof(mem.indexL1InfoTree, 1)} :HASHK(E+1) + C :HASHK(E+1) + A + 0x00000002 => A :JMP(hashBranchEnd1) + +hashLeft1: + C :HASHK(E+1) + ${getSmtProof(mem.indexL1InfoTree, 1)} :HASHK(E+1) + +hashBranchEnd1: + HASHPOS :HASHKLEN(E+1) + $ => C :HASHKDIGEST(E+1) + + ; BIT 2 + 0 => HASHPOS + ${B & 0x00000004} :JMPZ(hashLeft2) + +hashRight2: + ${getSmtProof(mem.indexL1InfoTree, 2)} :HASHK(E+2) + C :HASHK(E+2) + A + 0x00000004 => A :JMP(hashBranchEnd2) + +hashLeft2: + C :HASHK(E+2) + ${getSmtProof(mem.indexL1InfoTree, 2)} :HASHK(E+2) + +hashBranchEnd2: + HASHPOS :HASHKLEN(E+2) + $ => C :HASHKDIGEST(E+2) + + ; BIT 3 + 0 => HASHPOS + ${B & 0x00000008} :JMPZ(hashLeft3) + +hashRight3: + ${getSmtProof(mem.indexL1InfoTree, 3)} :HASHK(E+3) + C :HASHK(E+3) + A + 0x00000008 => A :JMP(hashBranchEnd3) + +hashLeft3: + C :HASHK(E+3) + ${getSmtProof(mem.indexL1InfoTree, 3)} :HASHK(E+3) + +hashBranchEnd3: + HASHPOS :HASHKLEN(E+3) + $ => C :HASHKDIGEST(E+3) + + ; BIT 4 + 0 => HASHPOS + ${B & 0x00000010} :JMPZ(hashLeft4) + +hashRight4: + ${getSmtProof(mem.indexL1InfoTree, 4)} :HASHK(E+4) + C :HASHK(E+4) + A + 0x00000010 => A :JMP(hashBranchEnd4) + +hashLeft4: + C :HASHK(E+4) + ${getSmtProof(mem.indexL1InfoTree, 4)} :HASHK(E+4) + +hashBranchEnd4: + HASHPOS :HASHKLEN(E+4) + $ => C :HASHKDIGEST(E+4) + + ; BIT 5 + 0 => HASHPOS + ${B & 0x00000020} :JMPZ(hashLeft5) + +hashRight5: + ${getSmtProof(mem.indexL1InfoTree, 5)} :HASHK(E+5) + C :HASHK(E+5) + A + 0x00000020 => A :JMP(hashBranchEnd5) + +hashLeft5: + C :HASHK(E+5) + ${getSmtProof(mem.indexL1InfoTree, 5)} :HASHK(E+5) + +hashBranchEnd5: + HASHPOS :HASHKLEN(E+5) + $ => C :HASHKDIGEST(E+5) + + ; BIT 6 + 0 => HASHPOS + ${B & 0x00000040} :JMPZ(hashLeft6) + +hashRight6: + ${getSmtProof(mem.indexL1InfoTree, 6)} :HASHK(E+6) + C :HASHK(E+6) + A + 0x00000040 => A :JMP(hashBranchEnd6) + +hashLeft6: + C :HASHK(E+6) + ${getSmtProof(mem.indexL1InfoTree, 6)} :HASHK(E+6) + +hashBranchEnd6: + HASHPOS :HASHKLEN(E+6) + $ => C :HASHKDIGEST(E+6) + + ; BIT 7 + 0 => HASHPOS + ${B & 0x00000080} :JMPZ(hashLeft7) + +hashRight7: + ${getSmtProof(mem.indexL1InfoTree, 7)} :HASHK(E+7) + C :HASHK(E+7) + A + 0x00000080 => A :JMP(hashBranchEnd7) + +hashLeft7: + C :HASHK(E+7) + ${getSmtProof(mem.indexL1InfoTree, 7)} :HASHK(E+7) + +hashBranchEnd7: + HASHPOS :HASHKLEN(E+7) + $ => C :HASHKDIGEST(E+7) + + ; BIT 8 + 0 => HASHPOS + ${B & 0x00000100} :JMPZ(hashLeft8) + +hashRight8: + ${getSmtProof(mem.indexL1InfoTree, 8)} :HASHK(E+8) + C :HASHK(E+8) + A + 0x00000100 => A :JMP(hashBranchEnd8) + +hashLeft8: + C :HASHK(E+8) + ${getSmtProof(mem.indexL1InfoTree, 8)} :HASHK(E+8) + +hashBranchEnd8: + HASHPOS :HASHKLEN(E+8) + $ => C :HASHKDIGEST(E+8) + + ; BIT 9 + 0 => HASHPOS + ${B & 0x00000200} :JMPZ(hashLeft9) + +hashRight9: + ${getSmtProof(mem.indexL1InfoTree, 9)} :HASHK(E+9) + C :HASHK(E+9) + A + 0x00000200 => A :JMP(hashBranchEnd9) + +hashLeft9: + C :HASHK(E+9) + ${getSmtProof(mem.indexL1InfoTree, 9)} :HASHK(E+9) + +hashBranchEnd9: + HASHPOS :HASHKLEN(E+9) + $ => C :HASHKDIGEST(E+9) + + ; BIT 10 + 0 => HASHPOS + ${B & 0x00000400} :JMPZ(hashLeft10) + +hashRight10: + ${getSmtProof(mem.indexL1InfoTree, 10)} :HASHK(E+10) + C :HASHK(E+10) + A + 0x00000400 => A :JMP(hashBranchEnd10) + +hashLeft10: + C :HASHK(E+10) + ${getSmtProof(mem.indexL1InfoTree, 10)} :HASHK(E+10) + +hashBranchEnd10: + HASHPOS :HASHKLEN(E+10) + $ => C :HASHKDIGEST(E+10) + + ; BIT 11 + 0 => HASHPOS + ${B & 0x00000800} :JMPZ(hashLeft11) + +hashRight11: + ${getSmtProof(mem.indexL1InfoTree, 11)} :HASHK(E+11) + C :HASHK(E+11) + A + 0x00000800 => A :JMP(hashBranchEnd11) + +hashLeft11: + C :HASHK(E+11) + ${getSmtProof(mem.indexL1InfoTree, 11)} :HASHK(E+11) + +hashBranchEnd11: + HASHPOS :HASHKLEN(E+11) + $ => C :HASHKDIGEST(E+11) + + + ; BIT 12 + 0 => HASHPOS + ${B & 0x00001000} :JMPZ(hashLeft12) + +hashRight12: + ${getSmtProof(mem.indexL1InfoTree, 12)} :HASHK(E+12) + C :HASHK(E+12) + A + 0x00001000 => A :JMP(hashBranchEnd12) + +hashLeft12: + C :HASHK(E+12) + ${getSmtProof(mem.indexL1InfoTree, 12)} :HASHK(E+12) + +hashBranchEnd12: + HASHPOS :HASHKLEN(E+12) + $ => C :HASHKDIGEST(E+12) + + ; BIT 13 + 0 => HASHPOS + ${B & 0x00002000} :JMPZ(hashLeft13) + +hashRight13: + ${getSmtProof(mem.indexL1InfoTree, 13)} :HASHK(E+13) + C :HASHK(E+13) + A + 0x00002000 => A :JMP(hashBranchEnd13) + +hashLeft13: + C :HASHK(E+13) + ${getSmtProof(mem.indexL1InfoTree, 13)} :HASHK(E+13) + +hashBranchEnd13: + HASHPOS :HASHKLEN(E+13) + $ => C :HASHKDIGEST(E+13) + + ; BIT 14 + 0 => HASHPOS + ${B & 0x00004000} :JMPZ(hashLeft14) + +hashRight14: + ${getSmtProof(mem.indexL1InfoTree, 14)} :HASHK(E+14) + C :HASHK(E+14) + A + 0x00004000 => A :JMP(hashBranchEnd14) + +hashLeft14: + C :HASHK(E+14) + ${getSmtProof(mem.indexL1InfoTree, 14)} :HASHK(E+14) + +hashBranchEnd14: + HASHPOS :HASHKLEN(E+14) + $ => C :HASHKDIGEST(E+14) + + ; BIT 15 + 0 => HASHPOS + ${B & 0x00008000} :JMPZ(hashLeft15) + +hashRight15: + ${getSmtProof(mem.indexL1InfoTree, 15)} :HASHK(E+15) + C :HASHK(E+15) + A + 0x00008000 => A :JMP(hashBranchEnd15) + +hashLeft15: + C :HASHK(E+15) + ${getSmtProof(mem.indexL1InfoTree, 15)} :HASHK(E+15) + +hashBranchEnd15: + HASHPOS :HASHKLEN(E+15) + $ => C :HASHKDIGEST(E+15) + + ; BIT 16 + 0 => HASHPOS + ${B & 0x00010000} :JMPZ(hashLeft16) + +hashRight16: + ${getSmtProof(mem.indexL1InfoTree, 16)} :HASHK(E+16) + C :HASHK(E+16) + A + 0x00010000 => A :JMP(hashBranchEnd16) + +hashLeft16: + C :HASHK(E+16) + ${getSmtProof(mem.indexL1InfoTree, 16)} :HASHK(E+16) + +hashBranchEnd16: + HASHPOS :HASHKLEN(E+16) + $ => C :HASHKDIGEST(E+16) + + ; BIT 17 + 0 => HASHPOS + ${B & 0x00020000} :JMPZ(hashLeft17) + +hashRight17: + ${getSmtProof(mem.indexL1InfoTree, 17)} :HASHK(E+17) + C :HASHK(E+17) + A + 0x00020000 => A :JMP(hashBranchEnd17) + +hashLeft17: + C :HASHK(E+17) + ${getSmtProof(mem.indexL1InfoTree, 17)} :HASHK(E+17) + +hashBranchEnd17: + HASHPOS :HASHKLEN(E+17) + $ => C :HASHKDIGEST(E+17) + + ; BIT 18 + 0 => HASHPOS + ${B & 0x00040000} :JMPZ(hashLeft18) + +hashRight18: + ${getSmtProof(mem.indexL1InfoTree, 18)} :HASHK(E+18) + C :HASHK(E+18) + A + 0x00040000 => A :JMP(hashBranchEnd18) + +hashLeft18: + C :HASHK(E+18) + ${getSmtProof(mem.indexL1InfoTree, 18)} :HASHK(E+18) + +hashBranchEnd18: + HASHPOS :HASHKLEN(E+18) + $ => C :HASHKDIGEST(E+18) + + ; BIT 19 + 0 => HASHPOS + ${B & 0x00080000} :JMPZ(hashLeft19) + +hashRight19: + ${getSmtProof(mem.indexL1InfoTree, 19)} :HASHK(E+19) + C :HASHK(E+19) + A + 0x00080000 => A :JMP(hashBranchEnd19) + +hashLeft19: + C :HASHK(E+19) + ${getSmtProof(mem.indexL1InfoTree, 19)} :HASHK(E+19) + +hashBranchEnd19: + HASHPOS :HASHKLEN(E+19) + $ => C :HASHKDIGEST(E+19) + + ; BIT 20 + 0 => HASHPOS + ${B & 0x00100000} :JMPZ(hashLeft20) + +hashRight20: + ${getSmtProof(mem.indexL1InfoTree, 20)} :HASHK(E+20) + C :HASHK(E+20) + A + 0x00100000 => A :JMP(hashBranchEnd20) + +hashLeft20: + C :HASHK(E+20) + ${getSmtProof(mem.indexL1InfoTree, 20)} :HASHK(E+20) + +hashBranchEnd20: + HASHPOS :HASHKLEN(E+20) + $ => C :HASHKDIGEST(E+20) + + ; BIT 21 + 0 => HASHPOS + ${B & 0x00200000} :JMPZ(hashLeft21) + +hashRight21: + ${getSmtProof(mem.indexL1InfoTree, 21)} :HASHK(E+21) + C :HASHK(E+21) + A + 0x00200000 => A :JMP(hashBranchEnd21) + +hashLeft21: + C :HASHK(E+21) + ${getSmtProof(mem.indexL1InfoTree, 21)} :HASHK(E+21) + +hashBranchEnd21: + HASHPOS :HASHKLEN(E+21) + $ => C :HASHKDIGEST(E+21) + + ; BIT 22 + 0 => HASHPOS + ${B & 0x00400000} :JMPZ(hashLeft22) + +hashRight22: + ${getSmtProof(mem.indexL1InfoTree, 22)} :HASHK(E+22) + C :HASHK(E+22) + A + 0x00400000 => A :JMP(hashBranchEnd22) + +hashLeft22: + C :HASHK(E+22) + ${getSmtProof(mem.indexL1InfoTree, 22)} :HASHK(E+22) + +hashBranchEnd22: + HASHPOS :HASHKLEN(E+22) + $ => C :HASHKDIGEST(E+22) + + ; BIT 23 + 0 => HASHPOS + ${B & 0x00800000} :JMPZ(hashLeft23) + +hashRight23: + ${getSmtProof(mem.indexL1InfoTree, 23)} :HASHK(E+23) + C :HASHK(E+23) + A + 0x00800000 => A :JMP(hashBranchEnd23) + +hashLeft23: + C :HASHK(E+23) + ${getSmtProof(mem.indexL1InfoTree, 23)} :HASHK(E+23) + +hashBranchEnd23: + HASHPOS :HASHKLEN(E+23) + $ => C :HASHKDIGEST(E+23) + + ; BIT 24 + 0 => HASHPOS + ${B & 0x01000000} :JMPZ(hashLeft24) + +hashRight24: + ${getSmtProof(mem.indexL1InfoTree, 24)} :HASHK(E+24) + C :HASHK(E+24) + A + 0x01000000 => A :JMP(hashBranchEnd24) + +hashLeft24: + C :HASHK(E+24) + ${getSmtProof(mem.indexL1InfoTree, 24)} :HASHK(E+24) + +hashBranchEnd24: + HASHPOS :HASHKLEN(E+24) + $ => C :HASHKDIGEST(E+24) + + ; BIT 25 + 0 => HASHPOS + ${B & 0x02000000} :JMPZ(hashLeft25) + +hashRight25: + ${getSmtProof(mem.indexL1InfoTree, 25)} :HASHK(E+25) + C :HASHK(E+25) + A + 0x02000000 => A :JMP(hashBranchEnd25) + +hashLeft25: + C :HASHK(E+25) + ${getSmtProof(mem.indexL1InfoTree, 25)} :HASHK(E+25) + +hashBranchEnd25: + HASHPOS :HASHKLEN(E+25) + $ => C :HASHKDIGEST(E+25) + + ; BIT 26 + 0 => HASHPOS + ${B & 0x04000000} :JMPZ(hashLeft26) + +hashRight26: + ${getSmtProof(mem.indexL1InfoTree, 26)} :HASHK(E+26) + C :HASHK(E+26) + A + 0x04000000 => A :JMP(hashBranchEnd26) + +hashLeft26: + C :HASHK(E+26) + ${getSmtProof(mem.indexL1InfoTree, 26)} :HASHK(E+26) + +hashBranchEnd26: + HASHPOS :HASHKLEN(E+26) + $ => C :HASHKDIGEST(E+26) + + ; BIT 27 + 0 => HASHPOS + ${B & 0x08000000} :JMPZ(hashLeft27) + +hashRight27: + ${getSmtProof(mem.indexL1InfoTree, 27)} :HASHK(E+27) + C :HASHK(E+27) + A + 0x08000000 => A :JMP(hashBranchEnd27) + +hashLeft27: + C :HASHK(E+27) + ${getSmtProof(mem.indexL1InfoTree, 27)} :HASHK(E+27) + +hashBranchEnd27: + HASHPOS :HASHKLEN(E+27) + $ => C :HASHKDIGEST(E+27) + + ; BIT 28 + 0 => HASHPOS + ${B & 0x10000000} :JMPZ(hashLeft28) + +hashRight28: + ${getSmtProof(mem.indexL1InfoTree, 28)} :HASHK(E+28) + C :HASHK(E+28) + A + 0x10000000 => A :JMP(hashBranchEnd28) + +hashLeft28: + C :HASHK(E+28) + ${getSmtProof(mem.indexL1InfoTree, 28)} :HASHK(E+28) + +hashBranchEnd28: + HASHPOS :HASHKLEN(E+28) + $ => C :HASHKDIGEST(E+28) + + ; BIT 29 + 0 => HASHPOS + ${B & 0x20000000} :JMPZ(hashLeft29) + +hashRight29: + ${getSmtProof(mem.indexL1InfoTree, 29)} :HASHK(E+29) + C :HASHK(E+29) + A + 0x20000000 => A :JMP(hashBranchEnd29) + +hashLeft29: + C :HASHK(E+29) + ${getSmtProof(mem.indexL1InfoTree, 29)} :HASHK(E+29) + +hashBranchEnd29: + HASHPOS :HASHKLEN(E+29) + $ => C :HASHKDIGEST(E+29) + + ; BIT 30 + 0 => HASHPOS + ${B & 0x40000000} :JMPZ(hashLeft30) + +hashRight30: + ${getSmtProof(mem.indexL1InfoTree, 30)} :HASHK(E+30) + C :HASHK(E+30) + A + 0x40000000 => A :JMP(hashBranchEnd30) + +hashLeft30: + C :HASHK(E+30) + ${getSmtProof(mem.indexL1InfoTree, 30)} :HASHK(E+30) + +hashBranchEnd30: + HASHPOS :HASHKLEN(E+30) + $ => C :HASHKDIGEST(E+30) + + ; BIT 31 + 0 => HASHPOS + ${B & 0x80000000} :JMPZ(hashLeft31) + +hashRight31: + ${getSmtProof(mem.indexL1InfoTree, 31)} :HASHK(E+31) + C :HASHK(E+31) + A + 0x80000000 => A :JMP(hashBranchEnd31) + +hashLeft31: + C :HASHK(E+31) + ${getSmtProof(mem.indexL1InfoTree, 31)} :HASHK(E+31) + +hashBranchEnd31: + HASHPOS :HASHKLEN(E+31) + $ => C :HASHKDIGEST(E+31) + + ; verify linear combination of 'indexL1InfoTree' + B :ASSERT + E + 31 => E :MSTORE(lastHashKIdUsed) + + +verifyMerkleProofEnd: + $ => A :MLOAD(l1InfoRoot) + C :ASSERT + +verifyMerkleProofReturn: + $ => RR :MLOAD(tmpZkPCVerifyMerkleProof) + :RETURN VAR GLOBAL tmpZkPCreadXFromOffset VAR GLOBAL readXFromCalldataOffset diff --git a/main/vars.zkasm b/main/vars.zkasm index a14069d6..63ec168f 100644 --- a/main/vars.zkasm +++ b/main/vars.zkasm @@ -1,16 +1,20 @@ ; Input variables VAR GLOBAL oldStateRoot ; Previous state-tree root VAR GLOBAL oldAccInputHash ; Previous accumulated input hash -VAR GLOBAL globalExitRoot ; Global exit-tree root +VAR GLOBAL l1InfoRoot ; Global exit-tree root VAR GLOBAL oldNumBatch ; Previous batch processed VAR GLOBAL sequencerAddr ; Coinbase address which will receive the fees VAR GLOBAL batchHashData ; batchHashData = H_keccak( transactions ) +VAR GLOBAL timestampLimit ; timestampLimit of the batch VAR GLOBAL timestamp ; Current batch timestamp VAR GLOBAL chainID ; Current batch chain id VAR GLOBAL forkID ; Fork identifier +VAR GLOBAL forcedBlockHashL1 ; blockHash ¡n L1 when a forced transaction has been done +VAR GLOBAL isForced ; Flag to determine if the batch is forced +VAR GLOBAL cumulativeGasUsed ; cumulative gas used in the block ; Output variables -VAR GLOBAL newAccInputHash ; Final accumulated input hash. newAccInputHash = H_keccak( oldAccInputHash | batchHashData | globalExitRoot | timestamp | sequencerAddr ) +VAR GLOBAL newAccInputHash ; Final accumulated input hash. newAccInputHash = H_keccak( oldAccInputHash | batchHashData | l1InfoRoot | timestamp | sequencerAddr ) VAR GLOBAL newLocalExitRoot ; Updated local exit tree root VAR GLOBAL newNumBatch ; Current batch processed @@ -34,14 +38,15 @@ VAR GLOBAL valueCall ; value parameter when creating a new context VAR GLOBAL argsLengthCall ; size of the calldata creating a new context VAR GLOBAL txSrcOriginAddr ; origin address of a tx VAR GLOBAL txGasPrice ; transaction parameter: 'gasPrice' global var -VAR GLOBAL depth ; Current depth execution VAR GLOBAL cntKeccakPreProcess ; Number of keccak counters needed to finish the batch -VAR GLOBAL nextFreeLogIndex ; pointer to the next free slot to store information in LOG opcode VAR GLOBAL originSR ; State root before processing each transaction VAR GLOBAL batchSR ; State root before processing any transaction -VAR GLOBAL txCount ; Current transaction count +VAR GLOBAL blockNum ; Current block number +VAR GLOBAL previousBlockHash ; Previous block hash +VAR GLOBAL currentTx ; Current tx index in batch +VAR GLOBAL blockInfoSR ; block info tree root VAR GLOBAL touchedSR ; touched tree root VAR GLOBAL numTopics ; number of topics depending on LOG opcode call VAR GLOBAL auxSR ; auxiliary variable. Temporary state root @@ -50,6 +55,7 @@ VAR GLOBAL txDataRead ; aux variable to check transaction 'data' left that needs VAR GLOBAL isLoadingRLP ; flag to determine if the function is called from RLP loop VAR GLOBAL globalCalldataMemoryOffset ; Aux variable to store current calldata memory offset at calldata CTX's memory +VAR GLOBAL txIndex ; index of the current tx in the block VAR CTX txGasLimit ; transaction parameter: 'gas limit' VAR CTX txDestAddr ; transaction parameter: 'to' VAR CTX storageAddr ; address which the storage will be modified @@ -62,13 +68,16 @@ VAR CTX txS ; transaction parameter: ecdsa signature S VAR CTX txR ; transaction parameter: ecdsa signature R VAR CTX txV ; transaction parameter: ecdsa signature V VAR CTX txSrcAddr ; address that sends a transaction 'message.sender' +VAR CTX ecrecoverErrorCode ; ecrecover result error code +VAR CTX txStatus ; flag indicating success or failure of current transaction VAR CTX txHash ; signed tx hash +VAR CTX l2TxHash ; L2 tx hash linearPoseidon[nonce, gasPrice, gasLimit, to, value, data, from] VAR CTX txCalldataLen ; calldata length VAR CTX isCreateContract ; flag to determine if a transaction will create a new contract VAR CTX createContractAddress ; address computed of a new contract VAR CTX lengthNonce ; 'nonce' length used when computing a new contract address VAR CTX gasRefund ; keeps track of the transaction gas refund -VAR CTX initSR ; state-tree once the initial upfront cost is substracted and nonce is increased +VAR CTX initSR ; state-tree once the initial upfront cost is subtracted and nonce is increased VAR CTX memLength ; current memory size VAR CTX lastMemLength ; length of bytes to copy to memory VAR CTX lastMemoryExpansionCost ; cost of the last memory expansion @@ -94,4 +103,13 @@ VAR CTX salt ; CREATE2 parameter 'salt' used to compute new contract address VAR CTX gasCTX ; remaining gas in the origin CTX when a new context is created VAR CTX dataStarts; hash position where the transaction 'data' starts in the batchHashData VAR CTX isPreEIP155 ; flag to check if the current tx is legacy, previous to Spurious Dragon (EIP-155) -VAR CTX initTouchedSR ; touched root once a new context begins \ No newline at end of file +VAR CTX initTouchedSR ; touched root once a new context begins +VAR CTX initBlockInfoSR ; block info root once a new context begins +VAR CTX initLogIndex ; log index once a new context begins + +VAR CTX deltaTimestamp ; delta timestamp of the current change L2 block tx +VAR CTX indexL1InfoTree ; indexL1InfoTree of the current change L2 block tx +VAR CTX gerL1InfoTree ; new GER of the current change L2 block tx +VAR CTX blockHashL1InfoTree ; new BlockhashL1 of the current change L2 block tx +VAR CTX timestampL1InfoTree ; new timestamp of the current change L2 block tx +VAR CTX isChangeL2BlockTx ; flag to determine if the current tx is a change L2 block tx diff --git a/package.json b/package.json index a6158fe8..4d136136 100644 --- a/package.json +++ b/package.json @@ -18,7 +18,7 @@ "test:counters": "node counters/counters-executor.js", "test:calldatacopy": "mkdir -p build && npx zkasm test/opcalldatacopy.zkasm -o build/opcalldatacopy.test.json", "test:mstorex": "mkdir -p build && npx zkasm test/mstorex.zkasm -o build/mstorex.test.json", - "test:zkasm": "node tools/run-tests-zkasm.js ./test", + "test:zkasm": "node tools/run-tests-zkasm.js ./test --helpers ../main/helper.js", "eslint": "npx eslint tools/**.js && npx eslint counters/counters-executor.js", "eslint:fix": "npx eslint tools/**.js --fix && npx eslint counters/counters-executor.js --fix", "test:gen": "node tools/gen-parallel-tests.js", @@ -37,18 +37,18 @@ "url": "https://github.com/0xPolygonHermez/zkevm-rom.git" }, "dependencies": { - "@0xpolygonhermez/zkasmcom": "https://github.com/0xPolygonHermez/zkasmcom.git#v1.0.0", + "@0xpolygonhermez/zkasmcom": "https://github.com/0xPolygonHermez/zkasmcom.git#v2.0.0-rc.2-fork.7", "yargs": "^17.5.1" }, "devDependencies": { - "@0xpolygonhermez/zkevm-proverjs": "github:0xPolygonHermez/zkevm-proverjs-internal#fix/ecrecover-alias-diffequals-sqrt", - "@0xpolygonhermez/zkevm-testvectors": "github:0xPolygonHermez/zkevm-testvectors#feature/update-fork", - "@0xpolygonhermez/zkevm-commonjs": "github:0xPolygonHermez/zkevm-commonjs#v2.0.0-fork.5", - "mocha": "^9.1.3", + "@0xpolygonhermez/zkevm-commonjs": "github:0xPolygonHermez/zkevm-commonjs#v4.0.0-rc.4-fork.7", + "@0xpolygonhermez/zkevm-proverjs": "github:0xPolygonHermez/zkevm-proverjs-internal#b651f11268981a9af6667fba624cb2ce638cb2fb", + "@0xpolygonhermez/zkevm-testvectors": "github:0xPolygonHermez/zkevm-testvectors-internal#v4.0.0-rc.4-fork.7", "chai": "^4.3.6", "chalk": "^3.0.0", "eslint": "^8.25.0", "eslint-config-airbnb-base": "^15.0.0", - "eslint-plugin-mocha": "^10.1.0" + "eslint-plugin-mocha": "^10.1.0", + "mocha": "^10.2.0" } } diff --git a/test/ecrecover.zkasm b/test/ecrecover.zkasm index 1999e51d..bff8bf55 100644 --- a/test/ecrecover.zkasm +++ b/test/ecrecover.zkasm @@ -293,7 +293,7 @@ repeat_ecrecover_test: 0x4f8ae3bd7535248d0bd448298cc2e2071e56992d0774dc340c368ae950852adan => C 0x1an => D :CALL(ecrecover_tx) - 0x0000000000000000000000000000000000000000n :ASSERT + 0 :ASSERT ; #28 v > 28 @@ -302,7 +302,7 @@ repeat_ecrecover_test: 0x4f8ae3bd7535248d0bd448298cc2e2071e56992d0774dc340c368ae950852adan => C 0x1dn => D :CALL(ecrecover_tx) - 0x0000000000000000000000000000000000000000n :ASSERT + 0 :ASSERT ; #29 r == 0 @@ -311,7 +311,7 @@ repeat_ecrecover_test: 0x4f8ae3bd7535248d0bd448298cc2e2071e56992d0774dc340c368ae950852adan => C 0x1cn => D :CALL(ecrecover_tx) - 0x0000000000000000000000000000000000000000n :ASSERT + 0 :ASSERT ; #30 r == field @@ -320,7 +320,7 @@ repeat_ecrecover_test: 0x4f8ae3bd7535248d0bd448298cc2e2071e56992d0774dc340c368ae950852adan => C 0x1cn => D :CALL(ecrecover_tx) - 0x0000000000000000000000000000000000000000n :ASSERT + 0 :ASSERT ; #31 r > field @@ -329,7 +329,7 @@ repeat_ecrecover_test: 0x4f8ae3bd7535248d0bd448298cc2e2071e56992d0774dc340c368ae950852adan => C 0x1cn => D :CALL(ecrecover_tx) - 0x0000000000000000000000000000000000000000n :ASSERT + 0 :ASSERT ; #32 r = field - 1 @@ -338,7 +338,7 @@ repeat_ecrecover_test: 0x4f8ae3bd7535248d0bd448298cc2e2071e56992d0774dc340c368ae950852adan => C 0x1cn => D :CALL(ecrecover_tx) - 0x0000000000000000000000000000000000000000n :ASSERT + 0 :ASSERT ; #33 s == 0 @@ -347,7 +347,7 @@ repeat_ecrecover_test: 0x0000000000000000000000000000000000000000000000000000000000000000n => C 0x1cn => D :CALL(ecrecover_tx) - 0x0000000000000000000000000000000000000000n :ASSERT + 0 :ASSERT ; #34 s == field/2 + 1. Valid (precompiled) @@ -405,7 +405,7 @@ repeat_ecrecover_test: 0xfffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141n => C 0x1cn => D :CALL(ecrecover_tx) - 0x0000000000000000000000000000000000000000n :ASSERT + 0 :ASSERT B => A 4n :ASSERT @@ -425,7 +425,7 @@ repeat_ecrecover_test: 0xfffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364140n => C 0x1cn => D :CALL(ecrecover_tx) - 0x0000000000000000000000000000000000000000n :ASSERT + 0 :ASSERT B => A 4n :ASSERT @@ -436,7 +436,7 @@ repeat_ecrecover_test: 0xfffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364142n => C 0x1cn => D :CALL(ecrecover_tx) - 0x0000000000000000000000000000000000000000n :ASSERT + 0 :ASSERT edge_cases: @@ -489,7 +489,7 @@ edge_cases: 0x7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a1n => C ; s 0x1bn => D :CALL(ecrecover_precompiled) - 0x0000000000000000000000000000000000000000n :ASSERT + 0 :ASSERT B => A 7 :ASSERT diff --git a/test/lt4-test.zkasm b/test/lt4-test.zkasm new file mode 100644 index 00000000..b6d915d1 --- /dev/null +++ b/test/lt4-test.zkasm @@ -0,0 +1,38 @@ +start: + CONSTL %FOUR_GL = 0xffffffff00000001ffffffff00000001ffffffff00000001ffffffff00000001n + ; less than 4 goldilocks + 0 => A + %FOUR_GL => B + 1 :LT4 + + ; equal than 4 goldilocks + %FOUR_GL => A + %FOUR_GL => B + 0 :LT4 + + ; equal than 4 goldilocks (just 3 elements) + %FOUR_GL => A + 1 => B + $ => A :SUB + %FOUR_GL => B + 0 :LT4 + + ; less than 4 goldilocks (just 1 unit in all elements) + %FOUR_GL => A + 0x1000000000000000100000000000000010000000000000001n => B + $ => A :SUB + %FOUR_GL => B + 1 :LT4 + + ; more than 4 goldilocks (just 1 unit in all elements) + %FOUR_GL => A + 0x1000000000000000100000000000000010000000000000001n => B + $ => A :ADD + %FOUR_GL => B + 0 :LT4 + + + 0 => A,B,C,D,E,CTX, SP, PC, GAS, SR, HASHPOS, RR ; Set all registers to 0 + :JMP(finalizeExecution) + +INCLUDE "../main/main.zkasm" \ No newline at end of file diff --git a/test/testArrayArith.zkasm b/test/testArrayArith.zkasm new file mode 100644 index 00000000..2374a8de --- /dev/null +++ b/test/testArrayArith.zkasm @@ -0,0 +1,1099 @@ +; constants needed by executor C++ +INCLUDE "../main/constants.zkasm" + +CONSTL %ARRAY_BASE_MINUS_ONE = 115792089237316195423570985008687907853269984665640564039457584007913129639935n ; 2^256 + +VAR GLOBAL lastHashKId +VAR GLOBAL lastHashPId + +VAR GLOBAL initial_A +VAR GLOBAL initial_B +VAR GLOBAL initial_C +VAR GLOBAL initial_D +VAR GLOBAL initial_E +VAR GLOBAL initial_CTX +VAR GLOBAL initial_SP +VAR GLOBAL initial_PC +VAR GLOBAL initial_GAS +VAR GLOBAL initial_SR +VAR GLOBAL initial_RR +VAR GLOBAL initial_HASHPOS +VAR GLOBAL initial_RCX + +start: + + STEP => A + 0 :ASSERT + + A :MSTORE(initial_A) + B :MSTORE(initial_B) + C :MSTORE(initial_C) + D :MSTORE(initial_D) + E :MSTORE(initial_E) + CTX :MSTORE(initial_CTX) + SP :MSTORE(initial_SP) + PC :MSTORE(initial_PC) + GAS :MSTORE(initial_GAS) + SR :MSTORE(initial_SR) + RR :MSTORE(initial_RR) + HASHPOS :MSTORE(initial_HASHPOS) + RCX :MSTORE(initial_RCX) + 0 => A,B,C,D,E,CTX, SP, PC, GAS, SR, RR, HASHPOS, RCX + + -1 :MSTORE(lastHashKId) + -1 :MSTORE(lastHashPId) + + ; addition with len(inA) >= len(inB) + ; --------------------------------------------------------------- + ; 1] [2**256-1,2**256-1,2**256-1] + [2**256-1,2**256-1] + 3 => C + 2 => D + 115792089237316195423570985008687907853269984665640564039457584007913129639935n :MSTORE(array_add_AGTB_inA) + 1 => E + 115792089237316195423570985008687907853269984665640564039457584007913129639935n :MSTORE(array_add_AGTB_inA + E) + 2 => E + 115792089237316195423570985008687907853269984665640564039457584007913129639935n :MSTORE(array_add_AGTB_inA + E) + 115792089237316195423570985008687907853269984665640564039457584007913129639935n :MSTORE(array_add_AGTB_inB) + 1 => E + 115792089237316195423570985008687907853269984665640564039457584007913129639935n :MSTORE(array_add_AGTB_inB + E) + :CALL(array_add_AGTB) + 115792089237316195423570985008687907853269984665640564039457584007913129639934n :MLOAD(array_add_AGTB_out) + 1 => E + 115792089237316195423570985008687907853269984665640564039457584007913129639935n :MLOAD(array_add_AGTB_out + E) + 2 => E + 0n :MLOAD(array_add_AGTB_out + E) + 3 => E + 1n :MLOAD(array_add_AGTB_out + E) + 4 :MLOAD(array_add_AGTB_len_out) + ; --------------------------------------------------------------- + + ; short addition + ; --------------------------------------------------------------- + ; 1] [2**256-1,2**256-1,2**256-1] + [2**256-1] + 3 => C + 115792089237316195423570985008687907853269984665640564039457584007913129639935n :MSTORE(array_add_short_inA) + 1 => E + 115792089237316195423570985008687907853269984665640564039457584007913129639935n :MSTORE(array_add_short_inA + E) + 2 => E + 115792089237316195423570985008687907853269984665640564039457584007913129639935n :MSTORE(array_add_short_inA + E) + 115792089237316195423570985008687907853269984665640564039457584007913129639935n :MSTORE(array_add_short_inB) + :CALL(array_add_short) + 115792089237316195423570985008687907853269984665640564039457584007913129639934n :MLOAD(array_add_short_out) + 1 => E + 0n :MLOAD(array_add_short_out + E) + 2 => E + 0n :MLOAD(array_add_short_out + E) + 3 => E + 1n :MLOAD(array_add_short_out + E) + 4 :MLOAD(array_add_short_len_out) + ; --------------------------------------------------------------- + + ; multiplication + ; --------------------------------------------------------------- + ; 1] len(inB) = len(inA) and inB > inA + 3 => C + 3 => D + 5n :MSTORE(array_mul_inA) + 1 => E + 6n :MSTORE(array_mul_inA + E) + 2 => E + 7n :MSTORE(array_mul_inA + E) + + 2n :MSTORE(array_mul_inB) + 1 => E + 3n :MSTORE(array_mul_inB + E) + 2 => E + 4n :MSTORE(array_mul_inB + E) + :CALL(array_mul) + 10n :MLOAD(array_mul_out) + 1 => E + 27n :MLOAD(array_mul_out + E) + 2 => E + 52n :MLOAD(array_mul_out + E) + 3 => E + 45n :MLOAD(array_mul_out + E) + 4 => E + 28n :MLOAD(array_mul_out + E) + 5 :MLOAD(array_mul_len_out) + + ; 2] len(inB) != len(inA) + 2 => C + 3 => D + 5n :MSTORE(array_mul_inA) + 1 => E + 6n :MSTORE(array_mul_inA + E) + + 11n :MSTORE(array_mul_inB) + 1 => E + 21n :MSTORE(array_mul_inB + E) + 2 => E + 16n :MSTORE(array_mul_inB + E) + :CALL(array_mul) + 55n :MLOAD(array_mul_out) + 1 => E + 171n :MLOAD(array_mul_out + E) + 2 => E + 206n :MLOAD(array_mul_out + E) + 3 => E + 96n :MLOAD(array_mul_out + E) + 4 :MLOAD(array_mul_len_out) + ; --------------------------------------------------------------- + + ; short multiplication + ; --------------------------------------------------------------- + ; 1] [a, a, a] * a + 3 => C + 1 => D + 115792089237316195423570985008687907853269984665640564039457584007913129639935n :MSTORE(array_mul_inA) + 1 => E + 115792089237316195423570985008687907853269984665640564039457584007913129639935n :MSTORE(array_mul_inA + E) + 2 => E + 115792089237316195423570985008687907853269984665640564039457584007913129639935n :MSTORE(array_mul_inA + E) + + 115792089237316195423570985008687907853269984665640564039457584007913129639935n :MSTORE(array_mul_inB) + :CALL(array_mul) + 1n :MLOAD(array_mul_out) + 1 => E + 115792089237316195423570985008687907853269984665640564039457584007913129639935n :MLOAD(array_mul_out + E) + 2 => E + 115792089237316195423570985008687907853269984665640564039457584007913129639935n :MLOAD(array_mul_out + E) + 3 => E + 115792089237316195423570985008687907853269984665640564039457584007913129639934n :MLOAD(array_mul_out + E) + 4 :MLOAD(array_mul_len_out) + + ; 2] [a, 100, a, 6] * 400 + 4 => C + 1 => D + 115792089237316195423570985008687907853269984665640564039457584007913129639935n :MSTORE(array_mul_inA) + 1 => E + 100n :MSTORE(array_mul_inA + E) + 2 => E + 115792089237316195423570985008687907853269984665640564039457584007913129639935n :MSTORE(array_mul_inA + E) + 3 => E + 6n :MSTORE(array_mul_inA + E) + + 400n :MSTORE(array_mul_inB) + :CALL(array_mul) + 115792089237316195423570985008687907853269984665640564039457584007913129639536n :MLOAD(array_mul_out) + 1 => E + 40399n :MLOAD(array_mul_out + E) + 2 => E + 115792089237316195423570985008687907853269984665640564039457584007913129639536n :MLOAD(array_mul_out + E) + 3 => E + 2799n :MLOAD(array_mul_out + E) + 4 :MLOAD(array_mul_len_out) + ; --------------------------------------------------------------- + + ; squaring + ; --------------------------------------------------------------- + ; 1] [4n, 4n, 4n, 3n, 2n, 4n] + 6 => C + 4n :MSTORE(array_square_in) + 1 => E + 4n :MSTORE(array_square_in + E) + 2 => E + 4n :MSTORE(array_square_in + E) + 3 => E + 3n :MSTORE(array_square_in + E) + 4 => E + 2n :MSTORE(array_square_in + E) + 5 => E + 4n :MSTORE(array_square_in + E) + :CALL(array_square) + 16n :MLOAD(array_square_out) + 1 => E + 32n :MLOAD(array_square_out + E) + 2 => E + 48n :MLOAD(array_square_out + E) + 3 => E + 56n :MLOAD(array_square_out + E) + 4 => E + 56n :MLOAD(array_square_out + E) + 5 => E + 72n :MLOAD(array_square_out + E) + 6 => E + 57n :MLOAD(array_square_out + E) + 7 => E + 44n :MLOAD(array_square_out + E) + 8 => E + 28n :MLOAD(array_square_out + E) + 9 => E + 16n :MLOAD(array_square_out + E) + 10 => E + 16n :MLOAD(array_square_out + E) + 11 :MLOAD(array_square_len_out) + + ; 2] [49625181101706940895816136432294817651401421999560241731196107431962769845690n, 16541727033902313631938712144098272550467140666520080577065369143987589948564n, 2n] + 3 => C + 49625181101706940895816136432294817651401421999560241731196107431962769845690n :MSTORE(array_square_in) + 1 => E + 16541727033902313631938712144098272550467140666520080577065369143987589948564n :MSTORE(array_square_in + E) + 2 => E + 2n :MSTORE(array_square_in + E) + :CALL(array_square) + 73256219721567388941442868066720921294925908666017499698432349066230755486500n :MLOAD(array_square_out) + 1 => E + 59077596549651120114066829086065259108811216666143144918090604085669964102021n :MLOAD(array_square_out + E) + 2 => E + 75619323583553433746005541230163531659278357332663225495155973229657554050588n :MLOAD(array_square_out + E) + 3 => E + 68530011997595299332317521739835700566221011332726048104985100739377158358338n :MLOAD(array_square_out + E) + 4 => E + 4n :MLOAD(array_square_out + E) + 5 :MLOAD(array_square_len_out) + + ; 3] [108509871213644914495224788117262720812102234692915980461799068728781566717980n, 97610657482852136417037764955262109743864410230427530868747251158690618238750n, 3n] + 3 => C + 108509871213644914495224788117262720812102234692915980461799068728781566717980n :MSTORE(array_square_in) + 1 => E + 97610657482852136417037764955262109743864410230427530868747251158690618238750n :MSTORE(array_square_in + E) + 2 => E + 3n :MSTORE(array_square_in + E) + :CALL(array_square) + 82987931714326364316120253427931880709278140571418487333162713377057429160720n :MLOAD(array_square_out) + 1 => E + 4257238595720679277571917967782652353394431698489248379634099239588181418140n :MLOAD(array_square_out + E) + 2 => E + 15209178211456919413336795740141505754388379695813905932093982440742677791802n :MLOAD(array_square_out + E) + 3 => E + 88987534839350135473536361176867192550264928852523682165693061442019881855583n :MLOAD(array_square_out + E) + 4 => E + 14n :MLOAD(array_square_out + E) + 5 :MLOAD(array_square_len_out) + + ; 4] [94296684984090328915786319894647341212298256830891608529662243544763352873524n,85801804490443701075961240310880668636621463408258506144468684495763969931231n] + 2 => C + 94296684984090328915786319894647341212298256830891608529662243544763352873524n :MSTORE(array_square_in) + 1 => E + 85801804490443701075961240310880668636621463408258506144468684495763969931231n :MSTORE(array_square_in + E) + :CALL(array_square) + 56476742620324943499420425449441725188859143808665910845865775685761970051728n :MLOAD(array_square_out) + 1 => E + 15939360972613038527243286761436595585964755988147232278935003110685006573864n :MLOAD(array_square_out + E) + 2 => E + 71885101902860809166787972884705167254384530826288829047389464757277834814455n :MLOAD(array_square_out + E) + 3 => E + 63579038104476977130956937454941822659502127575865339775268690127769381598323n :MLOAD(array_square_out + E) + 4 :MLOAD(array_square_len_out) + + ; 5] [ARRAY_BASE-1,ARRAY_BASE/2+1,ARRAY_BASE-2] + ; this covers the edge case where the addition 2·a_i·a_j + out[i + j] produces a third chunk carry + 3 => C + 115792089237316195423570985008687907853269984665640564039457584007913129639935n :MSTORE(array_square_in) + 1 => E + 57896044618658097711785492504343953926634992332820282019728792003956564819969n :MSTORE(array_square_in + E) + 2 => E + 115792089237316195423570985008687907853269984665640564039457584007913129639934n :MSTORE(array_square_in + E) + :CALL(array_square) + 1n :MLOAD(array_square_out) + 1 => E + 115792089237316195423570985008687907853269984665640564039457584007913129639932n :MLOAD(array_square_out + E) + 2 => E + 6n :MLOAD(array_square_out + E) + 3 => E + 28948022309329048855892746252171976963317496166410141009864396001978282409976n :MLOAD(array_square_out + E) + 4 => E + 6n :MLOAD(array_square_out + E) + 5 => E + 115792089237316195423570985008687907853269984665640564039457584007913129639933n :MLOAD(array_square_out + E) + 6 :MLOAD(array_square_len_out) + + ; 6] [ARRAY_BASE/2+1,ARRAY_BASE/2+1,ARRAY_BASE-2] + ; this covers the edge case where out[i + j] has a non-zero second chunk (i.e., when j == len -1) + ; and it produces carry when added to the second chunk of 2·a_i·a_j + 3 => C + 57896044618658097711785492504343953926634992332820282019728792003956564819969n :MSTORE(array_square_in) + 1 => E + 57896044618658097711785492504343953926634992332820282019728792003956564819969n :MSTORE(array_square_in + E) + 2 => E + 115792089237316195423570985008687907853269984665640564039457584007913129639934n :MSTORE(array_square_in + E) + :CALL(array_square) + 1n :MLOAD(array_square_out) + 1 => E + 28948022309329048855892746252171976963317496166410141009864396001978282409987n :MLOAD(array_square_out + E) + 2 => E + 57896044618658097711785492504343953926634992332820282019728792003956564819967n :MLOAD(array_square_out + E) + 3 => E + 28948022309329048855892746252171976963317496166410141009864396001978282409981n :MLOAD(array_square_out + E) + 4 => E + 5n :MLOAD(array_square_out + E) + 5 => E + 115792089237316195423570985008687907853269984665640564039457584007913129639933n :MLOAD(array_square_out + E) + 6 :MLOAD(array_square_len_out) + + ; 7] [ARRAY_BASE/2+1,ARRAY_BASE-1,ARRAY_BASE-2] + ; this covers the edge case where carry has a non-zero second chunk + ; and it produces carry when added to the second chunk of 2·a_i·a_j + out[i + j] + 3 => C + 57896044618658097711785492504343953926634992332820282019728792003956564819969n :MSTORE(array_square_in) + 1 => E + 115792089237316195423570985008687907853269984665640564039457584007913129639935n :MSTORE(array_square_in + E) + 2 => E + 115792089237316195423570985008687907853269984665640564039457584007913129639934n :MSTORE(array_square_in + E) + :CALL(array_square) + 1n :MLOAD(array_square_out) + 1 => E + 28948022309329048855892746252171976963317496166410141009864396001978282409983n :MLOAD(array_square_out + E) + 2 => E + 115792089237316195423570985008687907853269984665640564039457584007913129639934n :MLOAD(array_square_out + E) + 3 => E + 2n :MLOAD(array_square_out + E) + 4 => E + 0n :MLOAD(array_square_out + E) + 5 => E + 115792089237316195423570985008687907853269984665640564039457584007913129639934n :MLOAD(array_square_out + E) + 6 :MLOAD(array_square_len_out) + + ; 8] [272043482145244634591109928786079352n,81877371507464127617551201542979628307507432471243237061821853600756754782485n,176318528146701254200802196825427983451687n] + ; this covers the edge case where carry is of the form -a_i·a_i + ; and it produces carry when added to the second chunk of 2·a_i·a_i + out[i + i] + ; e.g., when the subtraction is of the form (base² + y) - (y+1) = 0 + ;---------------------- + ; I obtained a (3-chunk) input by solving the system of inequalities: + ; 2·x² + z = base² + y + ; x² > y + ; 0 < x,y,z < base + ; (x,y ∈ ℕ and z ∈ 2ℕ) + ; where x = a_1 and z = out[2]. The solution ensures that 2·a_1·a_1 + out[2] > base², while 2·a_1·a_1 + out[2] - a_1·a_1 < base² + ; Then I simply found an appropriate pair of a_0,a_2 such that 2·a_0·a_2 = out[2] + 3 => C + 272043482145244634591109928786079352n :MSTORE(array_square_in) + 1 => E + 81877371507464127617551201542979628307507432471243237061821853600756754782485n :MSTORE(array_square_in + E) + 2 => E + 176318528146701254200802196825427983451687n :MSTORE(array_square_in + E) + :CALL(array_square) + 74007656177710036293062386420979166962778595461878138943934059640739904n :MLOAD(array_square_out) + 1 => E + 107309681785116775741345228420276669267595434811710002878660662063722468151216n :MLOAD(array_square_out + E) + 2 => E + 47966306363752936198863311407838158502039511278988772633471074046272807492009n :MLOAD(array_square_out + E) + 3 => E + 109177356221965282998310125805498648173787805805410017775027543248980737204326n :MLOAD(array_square_out + E) + 4 => E + 15873116718318493168742852298661062116740566009918431601066595319216311981693n :MLOAD(array_square_out + E) + 5 => E + 268483n :MLOAD(array_square_out + E) + 6 :MLOAD(array_square_len_out) + ; --------------------------------------------------------------- + + ; division + ; --------------------------------------------------------------- + ; 1] [9n, 8n, 7n, 6n] / 8n + 4 => C + 1 => D + 9n :MSTORE(array_div_inA) + 1 => E + 8n :MSTORE(array_div_inA + E) + 2 => E + 7n :MSTORE(array_div_inA + E) + 3 => E + 6n :MSTORE(array_div_inA + E) + + 8n :MSTORE(array_div_inB) + :CALL(array_div) + 1n :MLOAD(array_div_quo) + 1 => E + 101318078082651670995624611882601919371611236582435493534525386006923988434945n :MLOAD(array_div_quo + E) + 2 => E + 86844066927987146567678238756515930889952488499230423029593188005934847229952n :MLOAD(array_div_quo + E) + 1n :MLOAD(array_div_rem) + 3 :MLOAD(array_div_len_quo) + + ; 2] [a, 7n, a, 12n, a, 20n, a, 80n] / a + 8 => C + 1 => D + 115792089237316195423570985008687907853269984665640564039457584007913129639935n :MSTORE(array_div_inA) + 1 => E + 7n :MSTORE(array_div_inA + E) + 2 => E + 115792089237316195423570985008687907853269984665640564039457584007913129639935n :MSTORE(array_div_inA + E) + 3 => E + 12n :MSTORE(array_div_inA + E) + 4 => E + 115792089237316195423570985008687907853269984665640564039457584007913129639935n :MSTORE(array_div_inA + E) + 5 => E + 20n :MSTORE(array_div_inA + E) + 6 => E + 115792089237316195423570985008687907853269984665640564039457584007913129639935n :MSTORE(array_div_inA + E) + 7 => E + 80n :MSTORE(array_div_inA + E) + + 115792089237316195423570985008687907853269984665640564039457584007913129639935n :MSTORE(array_div_inB) + :CALL(array_div) + 120n :MLOAD(array_div_quo) + 1 => E + 112n :MLOAD(array_div_quo + E) + 2 => E + 113n :MLOAD(array_div_quo + E) + 3 => E + 100n :MLOAD(array_div_quo + E) + 4 => E + 101n :MLOAD(array_div_quo + E) + 5 => E + 80n :MLOAD(array_div_quo + E) + 6 => E + 81n :MLOAD(array_div_quo + E) + 119n :MLOAD(array_div_rem) + 7 :MLOAD(array_div_len_quo) + + ; 3] inA == 0, inB != 0, len(inB) == 1 + 1 => C + 1 => D + 0n :MSTORE(array_div_inA) + + 8n :MSTORE(array_div_inB) + :CALL(array_div) + 0n :MLOAD(array_div_quo) + 0n :MLOAD(array_div_rem) + 1 :MLOAD(array_div_len_quo) + + 1 => C + 1 => D + 0n :MSTORE(array_div_short_inA) + 8n :MSTORE(array_div_short_inB) + :CALL(array_div_short) + 0n :MLOAD(array_div_short_quo) + 0n :MLOAD(array_div_short_rem) + 1 :MLOAD(array_div_short_len_quo) + + ; 4] inA == 0, inB != 0, len(inB) > 1 + 1 => C + 2 => D + 0n :MSTORE(array_div_inA) + + 8n :MSTORE(array_div_inB) + 1 => E + 1n :MSTORE(array_div_inB + E) + :CALL(array_div) + 0n :MLOAD(array_div_quo) + 0n :MLOAD(array_div_rem) + + 1 => C + 2 => D + 0n :MSTORE(array_div_long_inA) + 8n :MSTORE(array_div_long_inB) + 1 => E + 8n :MSTORE(array_div_long_inB + E) + :CALL(array_div_long) + 0n :MLOAD(array_div_long_quo) + 0n :MLOAD(array_div_long_rem) + 1 :MLOAD(array_div_long_len_quo) + + ; 5] inA != 0, inB == 0 -> error + 1 => C + 1 => D + 8n :MSTORE(array_div_long_inA) + 0n :MSTORE(array_div_long_inB) + :CALL(array_div_long) + 1 => A + B :ASSERT + + 2 => C + 1 => D + 0n :MSTORE(array_div_inA) + 1 => E + 30n :MSTORE(array_div_inA + E) + + 0n :MSTORE(array_div_inB) + :CALL(array_div) + 1 => A + B :ASSERT + + ; 6] inA == inB == 0 -> error + 1 => C + 1 => D + 0n :MSTORE(array_div_long_inA) + 0n :MSTORE(array_div_long_inB) + :CALL(array_div_long) + 1 => A + B :ASSERT + + 1 => C + 1 => D + 0n :MSTORE(array_div_short_inA) + 0n :MSTORE(array_div_short_inB) + :CALL(array_div_short) + 1 => A + B :ASSERT + + ; 7] inA == inB + 1 => C + 1 => D + 10n :MSTORE(array_div_inA) + 10n :MSTORE(array_div_inB) + :CALL(array_div) + 1n :MLOAD(array_div_quo) + 0n :MLOAD(array_div_rem) + 1 :MLOAD(array_div_len_quo) + + 2 => C + 2 => D + 10n :MSTORE(array_div_inA) + 1 => E + 30n :MSTORE(array_div_inA + E) + + 10n :MSTORE(array_div_inB) + 1 => E + 30n :MSTORE(array_div_inB + E) + :CALL(array_div) + 1n :MLOAD(array_div_quo) + 0n :MLOAD(array_div_rem) + + 1 => C + 1 => D + 10n :MSTORE(array_div_long_inA) + 10n :MSTORE(array_div_long_inB) + :CALL(array_div_long) + 1n :MLOAD(array_div_long_quo) + 0n :MLOAD(array_div_long_rem) + 1 :MLOAD(array_div_long_len_quo) + + 1 => C + 1 => D + 10n :MSTORE(array_div_short_inA) + 10n :MSTORE(array_div_short_inB) + :CALL(array_div_short) + 1n :MLOAD(array_div_short_quo) + 0n :MLOAD(array_div_short_rem) + 1 :MLOAD(array_div_short_len_quo) + + ; 8] inA < inB + 1 => C + 1 => D + 10n :MSTORE(array_div_inA) + 11n :MSTORE(array_div_inB) + :CALL(array_div) + 0n :MLOAD(array_div_quo) + 10n :MLOAD(array_div_rem) + 1 :MLOAD(array_div_len_quo) + + 2 => C + 3 => D + 10n :MSTORE(array_div_inA) + 1 => E + 30n :MSTORE(array_div_inA + E) + + 6n :MSTORE(array_div_inB) + 1 => E + 7n :MSTORE(array_div_inB + E) + 2 => E + 8n :MSTORE(array_div_inB + E) + :CALL(array_div) + 0n :MLOAD(array_div_quo) + 10n :MLOAD(array_div_rem) + 1 => E + 30n :MSTORE(array_div_rem + E) + + 1 => C + 1 => D + 10n :MSTORE(array_div_long_inA) + 11n :MSTORE(array_div_long_inB) + :CALL(array_div_long) + 0n :MLOAD(array_div_long_quo) + 10n :MLOAD(array_div_long_rem) + 1 :MLOAD(array_div_long_len_quo) + + 1 => C + 1 => D + 10n :MSTORE(array_div_short_inA) + 11n :MSTORE(array_div_short_inB) + :CALL(array_div_short) + 0n :MLOAD(array_div_short_quo) + 10n :MLOAD(array_div_short_rem) + 1 :MLOAD(array_div_short_len_quo) + + ; 9] [28948022309329048855892746252171976963317496166410141009864396001978282409984n, 1n] / 2 + 2 => C + 1 => D + 28948022309329048855892746252171976963317496166410141009864396001978282409984n :MSTORE(array_div_inA) + 1 => E + 1n :MSTORE(array_div_inA + E) + + 2n :MSTORE(array_div_inB) + :CALL(array_div) + 72370055773322622139731865630429942408293740416025352524660990004945706024960n :MLOAD(array_div_quo) + 1 :MLOAD(array_div_len_quo) + + ; 10] [72370055773322622139731865630429942408293740416025352524660990004945706024960n] / 2 + 1 => C + 1 => D + 72370055773322622139731865630429942408293740416025352524660990004945706024960n :MSTORE(array_div_inA) + 2n :MSTORE(array_div_inB) + :CALL(array_div) + 36185027886661311069865932815214971204146870208012676262330495002472853012480n :MLOAD(array_div_quo) + 1 :MLOAD(array_div_len_quo) + + ; 11] len(inB) = len(inA) and inB > inA + 4 => C + 2 => D + 9n :MSTORE(array_div_inA) + 1 => E + 8n :MSTORE(array_div_inA + E) + 2 => E + 7n :MSTORE(array_div_inA + E) + 3 => E + 6n :MSTORE(array_div_inA + E) + + 8n :MSTORE(array_div_inB) + 1 => E + 1n :MSTORE(array_div_inB + E) + :CALL(array_div) + 335n :MLOAD(array_div_quo) + 1 => E + 115792089237316195423570985008687907853269984665640564039457584007913129639895n :MLOAD(array_div_quo + E) + 2 => E + 5n :MLOAD(array_div_quo + E) + 115792089237316195423570985008687907853269984665640564039457584007913129637265n :MLOAD(array_div_rem) + + ; 12] [a, 7n, a, 12n, a, 20n, a, 80n] / [a, a, a, a, 100n] + 8 => C + 5 => D + 115792089237316195423570985008687907853269984665640564039457584007913129639935n :MSTORE(array_div_inA) + 1 => E + 7n :MSTORE(array_div_inA + E) + 2 => E + 115792089237316195423570985008687907853269984665640564039457584007913129639935n :MSTORE(array_div_inA + E) + 3 => E + 12n :MSTORE(array_div_inA + E) + 4 => E + 115792089237316195423570985008687907853269984665640564039457584007913129639935n :MSTORE(array_div_inA + E) + 5 => E + 20n :MSTORE(array_div_inA + E) + 6 => E + 115792089237316195423570985008687907853269984665640564039457584007913129639935n :MSTORE(array_div_inA + E) + 7 => E + 80n :MSTORE(array_div_inA + E) + + 115792089237316195423570985008687907853269984665640564039457584007913129639935n :MSTORE(array_div_inB) + 1 => E + 115792089237316195423570985008687907853269984665640564039457584007913129639935n :MSTORE(array_div_inB + E) + 2 => E + 115792089237316195423570985008687907853269984665640564039457584007913129639935n :MSTORE(array_div_inB + E) + 3 => E + 115792089237316195423570985008687907853269984665640564039457584007913129639935n :MSTORE(array_div_inB + E) + 4 => E + 100n :MSTORE(array_div_inB + E) + :CALL(array_div) + 87130681010257731209815790699606742543054641926620622445532439451498988639951n :MLOAD(array_div_quo) + 1 => E + 76812574048516684092863920748337523031377118540573443471719387411189897879957n :MLOAD(array_div_quo + E) + 2 => E + 92862962655669424052566829561422975605097710474424610764317468362781816839948n :MLOAD(array_div_quo + E) + 87130681010257731209815790699606742543054641926620622445532439451498988639950n :MLOAD(array_div_rem) + 1 => E + 76812574048516684092863920748337523031377118540573443471719387411189897879965n :MLOAD(array_div_rem + E) + 2 => E + 92862962655669424052566829561422975605097710474424610764317468362781816839947n :MLOAD(array_div_rem + E) + 3 => E + 13n :MLOAD(array_div_rem + E) + 4 => E + 84n :MLOAD(array_div_rem + E) + + ; 13] [82987931714326364316120253427931880709278140571418487333162713377057429160720n,4257238595720679277571917967782652353394431698489248379634099239588181418140n,15209178211456919413336795740141505754388379695813905932093982440742677791802n,88987534839350135473536361176867192550264928852523682165693061442019881855583n,14n], [4n, 6n, 7n] + 5 => C + 3 => D + 82987931714326364316120253427931880709278140571418487333162713377057429160720n :MSTORE(array_div_inA) + 1 => E + 4257238595720679277571917967782652353394431698489248379634099239588181418140n :MSTORE(array_div_inA + E) + 2 => E + 15209178211456919413336795740141505754388379695813905932093982440742677791802n :MSTORE(array_div_inA + E) + 3 => E + 88987534839350135473536361176867192550264928852523682165693061442019881855583n :MSTORE(array_div_inA + E) + 4 => E + 14n :MSTORE(array_div_inA + E) + + 4n :MSTORE(array_div_inB) + 1 => E + 6n :MSTORE(array_div_inB + E) + 2 => E + 7n :MSTORE(array_div_inB + E) + :CALL(array_div) + 90526669110436282262084097418054683975846294708417529350769755852355732618090n :MLOAD(array_div_quo) + 1 => E + 12712504977050019353362337310981027507180704121789097452241865920288554550795n :MLOAD(array_div_quo + E) + 2 => E + 2n :MLOAD(array_div_quo + E) + 68257522984529821538496818781776868365702915734670062048456441991373887608168n :MLOAD(array_div_rem) + 1 => E + 104999739448800080833043894267657885589213754954671066702793604491778345346033n :MSTORE(array_div_rem + E) + 2 => E + 4n :MSTORE(array_div_rem + E) + 3 :MLOAD(array_div_len_quo) + 3 :MLOAD(array_div_len_rem) + + ; 14] [0n,0n,0n,0n,87552057494100699607633960453116574392480272162273084008350826812719088235449n,29405388739667337424543497575767709934732594998639086405406332616399343873602n,370491411790392985199n], [0n, 0n, 8238129386n, 23102318237n] + 7 => C + 4 => D + 0n :MSTORE(array_div_inA) + 1 => E + 0n :MSTORE(array_div_inA + E) + 2 => E + 0n :MSTORE(array_div_inA + E) + 3 => E + 0n :MSTORE(array_div_inA + E) + 4 => E + 87552057494100699607633960453116574392480272162273084008350826812719088235449n :MSTORE(array_div_inA + E) + 5 => E + 29405388739667337424543497575767709934732594998639086405406332616399343873602n :MSTORE(array_div_inA + E) + 6 => E + 370491411790392985199n :MSTORE(array_div_inA + E) + + 0n :MSTORE(array_div_inB) + 1 => E + 0n :MSTORE(array_div_inB + E) + 2 => E + 8238129386n :MSTORE(array_div_inB + E) + 3 => E + 23102318237n :MSTORE(array_div_inB + E) + :CALL(array_div) + 10624890954144362706283399919870985530330343554129711486796784890935496833177n :MLOAD(array_div_quo) + 1 => E + 12699239907746414269759600684072701206520647567004427767570235373004025148518n :MLOAD(array_div_quo + E) + 2 => E + 62973947849727744055941265906651873030488901951864462234513788026171769471385n :MLOAD(array_div_quo + E) + 3 => E + 16036979838n :MLOAD(array_div_quo + E) + 0n :MLOAD(array_div_rem) + 1 => E + 0n :MSTORE(array_div_rem + E) + 2 => E + 43811746908501644357293832343774991028053014234938611947183500936834952782886n :MSTORE(array_div_rem + E) + 3 => E + 6019321230n :MSTORE(array_div_rem + E) + 4 :MLOAD(array_div_len_quo) + 4 :MLOAD(array_div_len_rem) + + ; 15] [7n], [7719472615821079694904732333912527190217998977709370935963838933860875309329n, 17n] + 1 => C + 2 => D + 7n :MSTORE(array_div_inA) + 7719472615821079694904732333912527190217998977709370935963838933860875309329n :MSTORE(array_div_inB) + 1 => E + 17n :MSTORE(array_div_inB + E) + :CALL(array_div) + 0n :MLOAD(array_div_quo) + 7n :MLOAD(array_div_rem) + 1 :MLOAD(array_div_len_quo) + 1 :MLOAD(array_div_len_rem) + + ; 16] [9,12,16,2,0,2**256-4], [2**256-1,2**256-1] + 6 => C + 2 => D + 9n :MSTORE(array_div_inA) + 115792089237316195423570985008687907853269984665640564039457584007913129639935n :MSTORE(array_div_inB) + 1 => E + 12n :MSTORE(array_div_inA + E) + 115792089237316195423570985008687907853269984665640564039457584007913129639935n :MSTORE(array_div_inB + E) + 2 => E + 16n :MSTORE(array_div_inA + E) + 3 => E + 2n :MSTORE(array_div_inA + E) + 4 => E + 0n :MSTORE(array_div_inA + E) + 5 => E + 115792089237316195423570985008687907853269984665640564039457584007913129639932n :MSTORE(array_div_inA + E) + :CALL(array_div) + 4 :MLOAD(array_div_len_quo) + 2 :MLOAD(array_div_len_rem) + 17n :MLOAD(array_div_quo) + 26n :MLOAD(array_div_rem) + 1 => E + 115792089237316195423570985008687907853269984665640564039457584007913129639934n :MLOAD(array_div_quo + E) + 10n :MLOAD(array_div_rem + E) + 2 => E + 0n :MLOAD(array_div_quo + E) + 3 => E + 115792089237316195423570985008687907853269984665640564039457584007913129639932n :MLOAD(array_div_quo + E) + ; --------------------------------------------------------------- + + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + ;; UNUSED + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + + ; addition + ; --------------------------------------------------------------- + ; 1] len(inA) = len(inB) + 3 => C + 3 => D + 115792089237316195423570985008687907853269984665640564039457584007913129639935n :MSTORE(array_add_inA) + 1 => E + 115792089237316195423570985008687907853269984665640564039457584007913129639935n :MSTORE(array_add_inA + E) + 2 => E + 115792089237316195423570985008687907853269984665640564039457584007913129639935n :MSTORE(array_add_inA + E) + + 115792089237316195423570985008687907853269984665640564039457584007913129639935n :MSTORE(array_add_inB) + 1 => E + 115792089237316195423570985008687907853269984665640564039457584007913129639935n :MSTORE(array_add_inB + E) + 2 => E + 115792089237316195423570985008687907853269984665640564039457584007913129639935n :MSTORE(array_add_inB + E) + :CALL(array_add) + 115792089237316195423570985008687907853269984665640564039457584007913129639934n :MLOAD(array_add_out) + 1 => E + 115792089237316195423570985008687907853269984665640564039457584007913129639935n :MLOAD(array_add_out + E) + 2 => E + 115792089237316195423570985008687907853269984665640564039457584007913129639935n :MLOAD(array_add_out + E) + 3 => E + 1n :MLOAD(array_add_out + E) + 4 :MLOAD(array_add_len_out) + + ; 2] len(inA) = len(inB) + 1 + 3 => C + 2 => D + 115792089237316195423570985008687907853269984665640564039457584007913129639935n :MSTORE(array_add_inA) + 1 => E + 115792089237316195423570985008687907853269984665640564039457584007913129639935n :MSTORE(array_add_inA + E) + 2 => E + 115792089237316195423570985008687907853269984665640564039457584007913129639935n :MSTORE(array_add_inA + E) + + 115792089237316195423570985008687907853269984665640564039457584007913129639935n :MSTORE(array_add_inB) + 1 => E + 115792089237316195423570985008687907853269984665640564039457584007913129639935n :MSTORE(array_add_inB + E) + :CALL(array_add) + 115792089237316195423570985008687907853269984665640564039457584007913129639934n :MLOAD(array_add_out) + 1 => E + 115792089237316195423570985008687907853269984665640564039457584007913129639935n :MLOAD(array_add_out + E) + 2 => E + 0n :MLOAD(array_add_out + E) + 3 => E + 1n :MLOAD(array_add_out + E) + 4 :MLOAD(array_add_len_out) + + ; 3] len(inA) = len(inB) + 3 + 7 => C + 4 => D + 0n :MSTORE(array_add_inA) + 1 => E + 0n :MSTORE(array_add_inA + E) + 2 => E + 71980342328814551066277152664912916825216970430701952092274083071078176857050n :MSTORE(array_add_inA + E) + 3 => E + 115792089237316195423570985008687907853269984665640564039457584007907110318705n :MSTORE(array_add_inA + E) + 4 => E + 87552057494100699607633960453116574392480272162273084008350826812719088235448n :MSTORE(array_add_inA + E) + 5 => E + 29405388739667337424543497575767709934732594998639086405406332616399343873602n :MSTORE(array_add_inA + E) + 6 => E + 370491411790392985199n :MSTORE(array_add_inA + E) + + 0n :MSTORE(array_add_inB) + 1 => E + 0n :MSTORE(array_add_inB + E) + 2 => E + 43811746908501644357293832343774991028053014234938611947183500936834952782886n :MSTORE(array_add_inB + E) + 3 => E + 6019321230n :MSTORE(array_add_inB + E) + :CALL(array_add) + 0n :MLOAD(array_add_out) + 1 => E + 0n :MLOAD(array_add_out + E) + 2 => E + 0n :MLOAD(array_add_out + E) + 3 => E + 0n :MLOAD(array_add_out + E) + 4 => E + 87552057494100699607633960453116574392480272162273084008350826812719088235449n :MLOAD(array_add_out + E) + 5 => E + 29405388739667337424543497575767709934732594998639086405406332616399343873602n :MLOAD(array_add_out + E) + 6 => E + 370491411790392985199n :MLOAD(array_add_out + E) + 7 :MLOAD(array_add_len_out) + + ; 4] len(inA) = len(inB) - 3 + 4 => C + 7 => D + 0n :MSTORE(array_add_inA) + 1 => E + 0n :MSTORE(array_add_inA + E) + 2 => E + 43811746908501644357293832343774991028053014234938611947183500936834952782886n :MSTORE(array_add_inA + E) + 3 => E + 6019321230n :MSTORE(array_add_inA + E) + + 0n :MSTORE(array_add_inB) + 1 => E + 0n :MSTORE(array_add_inB + E) + 2 => E + 71980342328814551066277152664912916825216970430701952092274083071078176857050n :MSTORE(array_add_inB + E) + 3 => E + 115792089237316195423570985008687907853269984665640564039457584007907110318705n :MSTORE(array_add_inB + E) + 4 => E + 87552057494100699607633960453116574392480272162273084008350826812719088235448n :MSTORE(array_add_inB + E) + 5 => E + 29405388739667337424543497575767709934732594998639086405406332616399343873602n :MSTORE(array_add_inB + E) + 6 => E + 370491411790392985199n :MSTORE(array_add_inB + E) + :CALL(array_add) + 0n :MLOAD(array_add_out) + 1 => E + 0n :MLOAD(array_add_out + E) + 2 => E + 0n :MLOAD(array_add_out + E) + 3 => E + 0n :MLOAD(array_add_out + E) + 4 => E + 87552057494100699607633960453116574392480272162273084008350826812719088235449n :MLOAD(array_add_out + E) + 5 => E + 29405388739667337424543497575767709934732594998639086405406332616399343873602n :MLOAD(array_add_out + E) + 6 => E + 370491411790392985199n :MLOAD(array_add_out + E) + 7 :MLOAD(array_add_len_out) + ; --------------------------------------------------------------- + + ; subtraction with len(inA) >= len(inB) + ; --------------------------------------------------------------- + ; 1] len(inA) > len(inB) and inA_i >= inb_i for all i + 3 => C + 2 => D + 5n :MSTORE(array_sub_AGTB_inA) + 1 => E + 6n :MSTORE(array_sub_AGTB_inA + E) + 2 => E + 7n :MSTORE(array_sub_AGTB_inA + E) + + 2n :MSTORE(array_sub_AGTB_inB) + 1 => E + 3n :MSTORE(array_sub_AGTB_inB + E) + :CALL(array_sub_AGTB) + 3n :MLOAD(array_sub_AGTB_out) + 1 => E + 3n :MLOAD(array_sub_AGTB_out + E) + 2 => E + 7n :MLOAD(array_sub_AGTB_out + E) + + ; 2] len(inA) > len(inB) and inA_i < inb_i for some i + 3 => C + 2 => D + 5n :MSTORE(array_sub_AGTB_inA) + 1 => E + 6n :MSTORE(array_sub_AGTB_inA + E) + 2 => E + 7n :MSTORE(array_sub_AGTB_inA + E) + + 6n :MSTORE(array_sub_AGTB_inB) + 1 => E + 3n :MSTORE(array_sub_AGTB_inB + E) + :CALL(array_sub_AGTB) + 115792089237316195423570985008687907853269984665640564039457584007913129639935n :MLOAD(array_sub_AGTB_out) + 1 => E + 2n :MLOAD(array_sub_AGTB_out + E) + 2 => E + 7n :MLOAD(array_sub_AGTB_out + E) + + ; 3] len(inA) > len(inB) and inA_i < inB_i for all i lower than len(inA) + 3 => C + 2 => D + 5n :MSTORE(array_sub_AGTB_inA) + 1 => E + 1n :MSTORE(array_sub_AGTB_inA + E) + 2 => E + 7n :MSTORE(array_sub_AGTB_inA + E) + + 6n :MSTORE(array_sub_AGTB_inB) + 1 => E + 8n :MSTORE(array_sub_AGTB_inB + E) + :CALL(array_sub_AGTB) + 115792089237316195423570985008687907853269984665640564039457584007913129639935n :MLOAD(array_sub_AGTB_out) + 1 => E + 115792089237316195423570985008687907853269984665640564039457584007913129639928n :MLOAD(array_sub_AGTB_out + E) + 2 => E + 6n :MLOAD(array_sub_AGTB_out + E) + + ; 4] len(inB) > len(inA) and inB_i < inA_i for all i lower than len(inB) + 3 => C + 2 => D + 6n :MSTORE(array_sub_AGTB_inB) + 1 => E + 8n :MSTORE(array_sub_AGTB_inB + E) + + 5n :MSTORE(array_sub_AGTB_inA) + 1 => E + 1n :MSTORE(array_sub_AGTB_inA + E) + 2 => E + 7n :MSTORE(array_sub_AGTB_inA + E) + :CALL(array_sub_AGTB) + 115792089237316195423570985008687907853269984665640564039457584007913129639935n :MLOAD(array_sub_AGTB_out) + 1 => E + 115792089237316195423570985008687907853269984665640564039457584007913129639928n :MLOAD(array_sub_AGTB_out + E) + 2 => E + 6n :MLOAD(array_sub_AGTB_out + E) + + ; 5] len(inB) = len(inA) and inB > inA + 3 => C + 3 => D + 6n :MSTORE(array_sub_AGTB_inB) + 1 => E + 8n :MSTORE(array_sub_AGTB_inB + E) + 2 => E + 8n :MSTORE(array_sub_AGTB_inB + E) + + 7n :MSTORE(array_sub_AGTB_inA) + 1 => E + 8n :MSTORE(array_sub_AGTB_inA + E) + 2 => E + 8n :MSTORE(array_sub_AGTB_inA + E) + :CALL(array_sub_AGTB) + 1n :MLOAD(array_sub_AGTB_out) + 1 => E + 0n :MLOAD(array_sub_AGTB_out + E) + 2 => E + 0n :MLOAD(array_sub_AGTB_out + E) + ; --------------------------------------------------------------- + + :JMP(end) + +outOfCountersBinary: + ${dump(CNT_BINARY)} :JMP(end) +outOfCountersStep: + ${dump(STEP)} :JMP(end) +outOfCountersArith: + ${dump(CNT_ARITH)} :JMP(end) + +;@info function to force a failed assert +failAssert: + 1 => A + 2 :ASSERT + +end: + + $ => A :MLOAD(initial_A) + $ => B :MLOAD(initial_B) + $ => C :MLOAD(initial_C) + $ => D :MLOAD(initial_D) + $ => E :MLOAD(initial_E) + $ => CTX :MLOAD(initial_CTX) + $ => SP :MLOAD(initial_SP) + $ => PC :MLOAD(initial_PC) + $ => GAS :MLOAD(initial_GAS) + $ => SR :MLOAD(initial_SR) + $ => RR :MLOAD(initial_RR) + $ => HASHPOS :MLOAD(initial_HASHPOS) + $ => RCX :MLOAD(initial_RCX) + +; label finalizeExecution needed by executor C++ +finalizeExecution: + ${beforeLast()} : JMPN(finalizeExecution) + + : JMP(start) +opINVALID: +; label checkAndSaveFrom needed by executor C++ +checkAndSaveFrom: + :JMP(opINVALID) + +INCLUDE "../main/modexp/constants.zkasm" + +INCLUDE "../main/modexp/array_lib/utils/array_trim.zkasm" +INCLUDE "../main/modexp/array_lib/utils/array_compare.zkasm" + +INCLUDE "../main/modexp/array_lib/array_add_short.zkasm" +INCLUDE "../main/modexp/array_lib/array_add_AGTB.zkasm" +INCLUDE "../main/modexp/array_lib/array_mul_long.zkasm" +INCLUDE "../main/modexp/array_lib/array_mul_short.zkasm" +INCLUDE "../main/modexp/array_lib/array_mul.zkasm" +INCLUDE "../main/modexp/array_lib/array_square.zkasm" +INCLUDE "../main/modexp/array_lib/array_div_long.zkasm" +INCLUDE "../main/modexp/array_lib/array_div_short.zkasm" +INCLUDE "../main/modexp/array_lib/array_div.zkasm" + +INCLUDE "../main/modexp/array_lib/unused/array_sub_AGTB.zkasm" +INCLUDE "../main/modexp/array_lib/unused/array_add.zkasm" \ No newline at end of file diff --git a/test/testArrayUtils.zkasm b/test/testArrayUtils.zkasm new file mode 100644 index 00000000..2cc3dc13 --- /dev/null +++ b/test/testArrayUtils.zkasm @@ -0,0 +1,335 @@ +; constants needed by executor C++ +INCLUDE "../main/constants.zkasm" + +VAR GLOBAL lastHashKId +VAR GLOBAL lastHashPId + +VAR GLOBAL initial_A +VAR GLOBAL initial_B +VAR GLOBAL initial_C +VAR GLOBAL initial_D +VAR GLOBAL initial_E +VAR GLOBAL initial_CTX +VAR GLOBAL initial_SP +VAR GLOBAL initial_PC +VAR GLOBAL initial_GAS +VAR GLOBAL initial_SR +VAR GLOBAL initial_RR +VAR GLOBAL initial_HASHPOS +VAR GLOBAL initial_RCX + +; Fix better notation for the above + +start: + + STEP => A + 0 :ASSERT + + A :MSTORE(initial_A) + B :MSTORE(initial_B) + C :MSTORE(initial_C) + D :MSTORE(initial_D) + E :MSTORE(initial_E) + CTX :MSTORE(initial_CTX) + SP :MSTORE(initial_SP) + PC :MSTORE(initial_PC) + GAS :MSTORE(initial_GAS) + SR :MSTORE(initial_SR) + RR :MSTORE(initial_RR) + HASHPOS :MSTORE(initial_HASHPOS) + RCX :MSTORE(initial_RCX) + 0 => A,B,C,D,E,CTX, SP, PC, GAS, SR, RR, HASHPOS, RCX + + -1 :MSTORE(lastHashKId) + -1 :MSTORE(lastHashPId) + +; array_compare +; --------------------------------------------------------------- +; 1] inA = [5,6,7], inB = [2,3]. len(inA) > len(inB) should return 2 +array_compare_test_1: + 3 => C + 2 => D + 5n :MSTORE(array_compare_inA) + 1 => E + 6n :MSTORE(array_compare_inA + E) + 2 => E + 7n :MSTORE(array_compare_inA + E) + 2n :MSTORE(array_compare_inB) + 1 => E + 3n :MSTORE(array_compare_inB + E) + :CALL(array_compare) + 2 :MLOAD(array_compare_result) + +; 2] inA = [5,6], inB = [2,3,4]. len(inA) < len(inB) should return 0 +array_compare_test_2: + 2 => C + 3 => D + 5n :MSTORE(array_compare_inA) + 1 => E + 6n :MSTORE(array_compare_inA + E) + 2n :MSTORE(array_compare_inB) + 1 => E + 3n :MSTORE(array_compare_inB + E) + 2 => E + 4n :MSTORE(array_compare_inB + E) + :CALL(array_compare) + 0 :MLOAD(array_compare_result) + + + +; 3] inA = [5,6,7], inB = [5,6,6]. len(inA) = len(inB) but inA > inB should return 2 +array_compare_test_3: + 3 => C + 3 => D + 5n :MSTORE(array_compare_inA) + 1 => E + 6n :MSTORE(array_compare_inA + E) + 2 => E + 7n :MSTORE(array_compare_inA + E) + 5n :MSTORE(array_compare_inB) + 1 => E + 6n :MSTORE(array_compare_inB + E) + 2 => E + 6n :MSTORE(array_compare_inB + E) + :CALL(array_compare) + 2 :MLOAD(array_compare_result) + +; 4] inA = [5,6,6], inB = [5,6,7]. len(inA) = len(inB) but inA < inB should return 0 +array_compare_test_4: + 3 => C + 3 => D + 5n :MSTORE(array_compare_inA) + 1 => E + 6n :MSTORE(array_compare_inA + E) + 2 => E + 6n :MSTORE(array_compare_inA + E) + + 5n :MSTORE(array_compare_inB) + 1 => E + 6n :MSTORE(array_compare_inB + E) + 2 => E + 7n :MSTORE(array_compare_inB + E) + :CALL(array_compare) + 0 :MLOAD(array_compare_result) + +; 5] inA = [5,6,6], inB = [5,6,6]. inA = inB should return 1 +array_compare_test_5: + 3 => C + 3 => D + 5n :MSTORE(array_compare_inA) + 1 => E + 6n :MSTORE(array_compare_inA + E) + 2 => E + 6n :MSTORE(array_compare_inA + E) + 5n :MSTORE(array_compare_inB) + 1 => E + 6n :MSTORE(array_compare_inB + E) + 2 => E + 6n :MSTORE(array_compare_inB + E) + :CALL(array_compare) + 1 :MLOAD(array_compare_result) +; --------------------------------------------------------------- + +; array unshift +; --------------------------------------------------------------- +; 1] in = [3] and D = 5 => in = [5,3] +array_unshift_test_1: + 1 => C + 3n :MSTORE(array_unshift_in) + 5 => D + :CALL(array_unshift) + 5n :MLOAD(array_unshift_in) + 1 => E + 3n :MLOAD(array_unshift_in + E) + 2 :MLOAD(array_unshift_len) + +; 2] in = [2,1,1] and D = 5 => in = [5,2,1,1] +array_unshift_test_2: + 3 => C + 5 => D + 2n :MSTORE(array_unshift_in) + 1 => E + 1n :MSTORE(array_unshift_in + E) + 2 => E + 1n :MSTORE(array_unshift_in + E) + :CALL(array_unshift) + 5n :MLOAD(array_unshift_in) + 1 => E + 2n :MLOAD(array_unshift_in + E) + 2 => E + 1n :MLOAD(array_unshift_in + E) + 3 => E + 1n :MLOAD(array_unshift_in + E) + 4 :MLOAD(array_unshift_len) +; --------------------------------------------------------------- + +; array trim +; --------------------------------------------------------------- +; 1] [2,1,0] should return 2 +array_trim_test_1: + 3 => C + 2n :MSTORE(array_trim_in) + 1 => E + 1n :MSTORE(array_trim_in + E) + 2 => E + 0n :MSTORE(array_trim_in + E) + :CALL(array_trim) + 2 => A + C :ASSERT + +; 2] [2,1,0,2] should return 4 +array_trim_test_2: + 4 => C + 2n :MSTORE(array_trim_in) + 1 => E + 1n :MSTORE(array_trim_in + E) + 2 => E + 0n :MSTORE(array_trim_in + E) + 3 => E + 2n :MSTORE(array_trim_in + E) + :CALL(array_trim) + 4 => A + C :ASSERT + +; 3] [0,0,0,0,0,0] should return 1 +array_trim_test_3: + 6 => C + 0n :MSTORE(array_trim_in) + 1 => E + 0n :MSTORE(array_trim_in + E) + 2 => E + 0n :MSTORE(array_trim_in + E) + 3 => E + 0n :MSTORE(array_trim_in + E) + 4 => E + 0n :MSTORE(array_trim_in + E) + 5 => E + 0n :MSTORE(array_trim_in + E) + :CALL(array_trim) + 1 => A + C :ASSERT + +; 4] [0] should return 1 +array_trim_test_4: + 1 => C + 0n :MSTORE(array_trim_in) + :CALL(array_trim) + 1 => A + C :ASSERT +; --------------------------------------------------------------- + +; array is zero +; --------------------------------------------------------------- +; 1] [2,1] should return 0 +array_is_zero_test_1: + 2 => C + 2n :MSTORE(array_is_zero_in) + 1 => E + 1n :MSTORE(array_is_zero_in + E) + :CALL(array_is_zero) + 0 :MLOAD(array_is_zero_result) + +; 2] [0] should return 1 +array_is_zero_test_2: + 1 => C + 0n :MSTORE(array_is_zero_in) + :CALL(array_is_zero) + 1 :MLOAD(array_is_zero_result) + +; 3] [5] should return 0 +array_is_zero_test_3: + 1 => C + 5n :MSTORE(array_is_zero_in) + :CALL(array_is_zero) + 0 :MLOAD(array_is_zero_result) +; --------------------------------------------------------------- + +; array is one +; --------------------------------------------------------------- +; 1] [2,1] should return 0 +array_is_one_test_1: + 2 => C + 2n :MSTORE(array_is_one_in) + 1 => E + 1n :MSTORE(array_is_one_in + E) + :CALL(array_is_one) + 0 :MLOAD(array_is_one_result) + +; 2] [1] should return 1 +array_is_one_test_2: + 1 => C + 1n :MSTORE(array_is_one_in) + :CALL(array_is_one) + 1 :MLOAD(array_is_one_result) + +; 3] [5] should return 0 +array_is_one_test_3: + 1 => C + 5n :MSTORE(array_is_one_in) + :CALL(array_is_one) + 0 :MLOAD(array_is_one_result) +; --------------------------------------------------------------- + +; array is odd +; --------------------------------------------------------------- +; 1] [2,1] should return 0 +array_is_odd_test_1: + 2n :MSTORE(array_is_odd_in) + 1 => E + 1n :MSTORE(array_is_odd_in + E) + :CALL(array_is_odd) + 0 :MLOAD(array_is_odd_result) + +; 2] [5] should return 1 +array_is_odd_test_2: + 5n :MSTORE(array_is_odd_in) + :CALL(array_is_odd) + 1 :MLOAD(array_is_odd_result) + +; 2] [3, 2] should return 1 +array_is_odd_test_3: + 3n :MSTORE(array_is_odd_in) + 1 => E + 2n :MSTORE(array_is_odd_in + E) + :CALL(array_is_odd) + 1 :MLOAD(array_is_odd_result) +; --------------------------------------------------------------- + +outOfCountersBinary: +outOfCountersStep: + +end: + + $ => A :MLOAD(initial_A) + $ => B :MLOAD(initial_B) + $ => C :MLOAD(initial_C) + $ => D :MLOAD(initial_D) + $ => E :MLOAD(initial_E) + $ => CTX :MLOAD(initial_CTX) + $ => SP :MLOAD(initial_SP) + $ => PC :MLOAD(initial_PC) + $ => GAS :MLOAD(initial_GAS) + $ => SR :MLOAD(initial_SR) + $ => RR :MLOAD(initial_RR) + $ => HASHPOS :MLOAD(initial_HASHPOS) + $ => RCX :MLOAD(initial_RCX) + +; label finalizeExecution needed by executor C++ +finalizeExecution: + ${beforeLast()} :JMPN(finalizeExecution) + + :JMP(start) +opINVALID: +; label checkAndSaveFrom needed by executor C++ +checkAndSaveFrom: + :JMP(opINVALID) + +INCLUDE "../main/modexp/constants.zkasm" + +INCLUDE "../main/modexp/array_lib/utils/array_compare.zkasm" +INCLUDE "../main/modexp/array_lib/utils/array_trim.zkasm" + +INCLUDE "../main/modexp/array_lib/unused/array_is_zero.zkasm" +INCLUDE "../main/modexp/array_lib/unused/array_is_one.zkasm" +INCLUDE "../main/modexp/array_lib/unused/array_is_odd.zkasm" +INCLUDE "../main/modexp/array_lib/unused/array_unshift.zkasm" \ No newline at end of file diff --git a/test/testCycloFp12ArithBN254.zkasm b/test/testCycloFp12ArithBN254.zkasm new file mode 100644 index 00000000..63872930 --- /dev/null +++ b/test/testCycloFp12ArithBN254.zkasm @@ -0,0 +1,548 @@ +; constants needed by executor C++ +CONST %N = 2**19 +CONST %MAX_CNT_STEPS_LIMIT = %N +CONST %MAX_CNT_ARITH_LIMIT = %N +CONST %MAX_CNT_BINARY_LIMIT = %N +CONST %MAX_CNT_MEM_ALIGN_LIMIT = %N +CONST %MAX_CNT_KECCAK_F_LIMIT = %N +CONST %MAX_CNT_PADDING_PG_LIMIT = %N +CONST %MAX_CNT_POSEIDON_G_LIMIT = %N + +CONSTL %BN254_P = 21888242871839275222246405745257275088696311157297823662689037894645226208583n + +VAR GLOBAL test + +VAR GLOBAL lastHashKId +VAR GLOBAL lastHashPId + +VAR GLOBAL initial_A +VAR GLOBAL initial_B +VAR GLOBAL initial_C +VAR GLOBAL initial_D +VAR GLOBAL initial_E +VAR GLOBAL initial_CTX +VAR GLOBAL initial_SP +VAR GLOBAL initial_PC +VAR GLOBAL initial_GAS +VAR GLOBAL initial_SR +VAR GLOBAL initial_RR +VAR GLOBAL initial_HASHPOS +VAR GLOBAL initial_RCX + +start: + + STEP => A + 0 :ASSERT + + + A :MSTORE(initial_A) + B :MSTORE(initial_B) + C :MSTORE(initial_C) + D :MSTORE(initial_D) + E :MSTORE(initial_E) + CTX :MSTORE(initial_CTX) + SP :MSTORE(initial_SP) + PC :MSTORE(initial_PC) + GAS :MSTORE(initial_GAS) + SR :MSTORE(initial_SR) + RR :MSTORE(initial_RR) + HASHPOS :MSTORE(initial_HASHPOS) + RCX :MSTORE(initial_RCX) + 0 => A,B,C,D,E,CTX, SP, PC, GAS, SR, RR, HASHPOS, RCX + + -1 :MSTORE(lastHashKId) + -1 :MSTORE(lastHashPId) + + ; 1] Compression and decompression: It must happen that D(C(a)) = a + 12879671296228341798957541889042068293248913689212425431224938470232546313254n :MSTORE(compressFp12BN254_a0_x) + 3326450555199805883965490851796414254830144151329718176108864533289444035270n :MSTORE(compressFp12BN254_a0_y) + 11706129207700151979042100288958216850158405562525260961392090752318820540155n :MSTORE(compressFp12BN254_a2_x) + 13581688218243497693010389261307054804658398598414171976249347555990073884710n :MSTORE(compressFp12BN254_a2_y) + 20034916004680903865371475524544157810838259782601065778963371780592670397755n :MSTORE(compressFp12BN254_a4_x) + 18196221800554323016660057972017335112712278872243164622794778048181747904770n :MSTORE(compressFp12BN254_a4_y) + 865661210072615391091663782916883487315505694294592934212781713437127182959n :MSTORE(compressFp12BN254_a1_x) + 5364456672142552956341240304849409513108281743490635067211876654163672173225n :MSTORE(compressFp12BN254_a1_y) + 2650685350723162073065693030364953757603657135232283880472468071129041178893n :MSTORE(compressFp12BN254_a3_x) + 1415534485628002925645978830263295545820817030311522411523977773123510463790n :MSTORE(compressFp12BN254_a3_y) + 11182696274116283149832659131689911508224992839995672842130064887471806829782n :MSTORE(compressFp12BN254_a5_x) + 13862086431460254638576437312497952755826436162922426416336796129991391475329n :MSTORE(compressFp12BN254_a5_y) + :CALL(compressFp12BN254) + 11706129207700151979042100288958216850158405562525260961392090752318820540155n :MLOAD(compressFp12BN254_Ca2_x) + 13581688218243497693010389261307054804658398598414171976249347555990073884710n :MLOAD(compressFp12BN254_Ca2_y) + 2650685350723162073065693030364953757603657135232283880472468071129041178893n :MLOAD(compressFp12BN254_Ca3_x) + 1415534485628002925645978830263295545820817030311522411523977773123510463790n :MLOAD(compressFp12BN254_Ca3_y) + 20034916004680903865371475524544157810838259782601065778963371780592670397755n :MLOAD(compressFp12BN254_Ca4_x) + 18196221800554323016660057972017335112712278872243164622794778048181747904770n :MLOAD(compressFp12BN254_Ca4_y) + 11182696274116283149832659131689911508224992839995672842130064887471806829782n :MLOAD(compressFp12BN254_Ca5_x) + 13862086431460254638576437312497952755826436162922426416336796129991391475329n :MLOAD(compressFp12BN254_Ca5_y) + + 11706129207700151979042100288958216850158405562525260961392090752318820540155n :MSTORE(decompressFp12BN254_Ca2_x) + 13581688218243497693010389261307054804658398598414171976249347555990073884710n :MSTORE(decompressFp12BN254_Ca2_y) + 2650685350723162073065693030364953757603657135232283880472468071129041178893n :MSTORE(decompressFp12BN254_Ca3_x) + 1415534485628002925645978830263295545820817030311522411523977773123510463790n :MSTORE(decompressFp12BN254_Ca3_y) + 20034916004680903865371475524544157810838259782601065778963371780592670397755n :MSTORE(decompressFp12BN254_Ca4_x) + 18196221800554323016660057972017335112712278872243164622794778048181747904770n :MSTORE(decompressFp12BN254_Ca4_y) + 11182696274116283149832659131689911508224992839995672842130064887471806829782n :MSTORE(decompressFp12BN254_Ca5_x) + 13862086431460254638576437312497952755826436162922426416336796129991391475329n :MSTORE(decompressFp12BN254_Ca5_y) + :CALL(decompressFp12BN254) + 12879671296228341798957541889042068293248913689212425431224938470232546313254n :MLOAD(decompressFp12BN254_a0_x) + 3326450555199805883965490851796414254830144151329718176108864533289444035270n :MLOAD(decompressFp12BN254_a0_y) + 11706129207700151979042100288958216850158405562525260961392090752318820540155n :MLOAD(decompressFp12BN254_a2_x) + 13581688218243497693010389261307054804658398598414171976249347555990073884710n :MLOAD(decompressFp12BN254_a2_y) + 20034916004680903865371475524544157810838259782601065778963371780592670397755n :MLOAD(decompressFp12BN254_a4_x) + 18196221800554323016660057972017335112712278872243164622794778048181747904770n :MLOAD(decompressFp12BN254_a4_y) + 865661210072615391091663782916883487315505694294592934212781713437127182959n :MLOAD(decompressFp12BN254_a1_x) + 5364456672142552956341240304849409513108281743490635067211876654163672173225n :MLOAD(decompressFp12BN254_a1_y) + 2650685350723162073065693030364953757603657135232283880472468071129041178893n :MLOAD(decompressFp12BN254_a3_x) + 1415534485628002925645978830263295545820817030311522411523977773123510463790n :MLOAD(decompressFp12BN254_a3_y) + 11182696274116283149832659131689911508224992839995672842130064887471806829782n :MLOAD(decompressFp12BN254_a5_x) + 13862086431460254638576437312497952755826436162922426416336796129991391475329n :MLOAD(decompressFp12BN254_a5_y) + + 0n :MSTORE(decompressFp12BN254_Ca2_x) + 0n :MSTORE(decompressFp12BN254_Ca2_y) + 2650685350723162073065693030364953757603657135232283880472468071129041178893n :MSTORE(decompressFp12BN254_Ca3_x) + 1415534485628002925645978830263295545820817030311522411523977773123510463790n :MSTORE(decompressFp12BN254_Ca3_y) + 20034916004680903865371475524544157810838259782601065778963371780592670397755n :MSTORE(decompressFp12BN254_Ca4_x) + 18196221800554323016660057972017335112712278872243164622794778048181747904770n :MSTORE(decompressFp12BN254_Ca4_y) + 11182696274116283149832659131689911508224992839995672842130064887471806829782n :MSTORE(decompressFp12BN254_Ca5_x) + 13862086431460254638576437312497952755826436162922426416336796129991391475329n :MSTORE(decompressFp12BN254_Ca5_y) + :CALL(decompressFp12BN254) + 3082566802732947271293720222661142209591143484576084617328875773438864732397n :MLOAD(decompressFp12BN254_a0_x) + 6753192725715184303833194625336959866779003056329959595176212784417709284236n :MLOAD(decompressFp12BN254_a0_y) + 0n :MLOAD(decompressFp12BN254_a2_x) + 0n :MLOAD(decompressFp12BN254_a2_y) + 20034916004680903865371475524544157810838259782601065778963371780592670397755n :MLOAD(decompressFp12BN254_a4_x) + 18196221800554323016660057972017335112712278872243164622794778048181747904770n :MLOAD(decompressFp12BN254_a4_y) + 19725038294210990876095311608776995374658210593840653608871004828604621493298n :MLOAD(decompressFp12BN254_a1_x) + 9667536184264952931246834743665147146209943690267032273162296061012209804352n :MLOAD(decompressFp12BN254_a1_y) + 2650685350723162073065693030364953757603657135232283880472468071129041178893n :MLOAD(decompressFp12BN254_a3_x) + 1415534485628002925645978830263295545820817030311522411523977773123510463790n :MLOAD(decompressFp12BN254_a3_y) + 11182696274116283149832659131689911508224992839995672842130064887471806829782n :MLOAD(decompressFp12BN254_a5_x) + 13862086431460254638576437312497952755826436162922426416336796129991391475329n :MLOAD(decompressFp12BN254_a5_y) + + ; 2] Squaring + 12879671296228341798957541889042068293248913689212425431224938470232546313254n :MSTORE(squareCycloFp12BN254_a11_x) + 3326450555199805883965490851796414254830144151329718176108864533289444035270n :MSTORE(squareCycloFp12BN254_a11_y) + 20034916004680903865371475524544157810838259782601065778963371780592670397755n :MSTORE(squareCycloFp12BN254_a12_x) + 18196221800554323016660057972017335112712278872243164622794778048181747904770n :MSTORE(squareCycloFp12BN254_a12_y) + 2650685350723162073065693030364953757603657135232283880472468071129041178893n :MSTORE(squareCycloFp12BN254_a13_x) + 1415534485628002925645978830263295545820817030311522411523977773123510463790n :MSTORE(squareCycloFp12BN254_a13_y) + 11706129207700151979042100288958216850158405562525260961392090752318820540155n :MSTORE(squareCycloFp12BN254_a21_x) + 13581688218243497693010389261307054804658398598414171976249347555990073884710n :MSTORE(squareCycloFp12BN254_a21_y) + 865661210072615391091663782916883487315505694294592934212781713437127182959n :MSTORE(squareCycloFp12BN254_a22_x) + 5364456672142552956341240304849409513108281743490635067211876654163672173225n :MSTORE(squareCycloFp12BN254_a22_y) + 11182696274116283149832659131689911508224992839995672842130064887471806829782n :MSTORE(squareCycloFp12BN254_a23_x) + 13862086431460254638576437312497952755826436162922426416336796129991391475329n :MSTORE(squareCycloFp12BN254_a23_y) + :CALL(squareCycloFp12BN254) + 2098026393950394559493690260865166581266928315924710629633888310320006689795n :MLOAD(squareCycloFp12BN254_c11_x) + 1846888720299666666109042029094532002505741710678796245911331796963733914187n :MLOAD(squareCycloFp12BN254_c11_y) + 6856859212192321831831255712736216614951508355737406292407364405936415355512n :MLOAD(squareCycloFp12BN254_c12_x) + 17209588680055969912485542074372495831925486815137906387799790601911548657525n :MLOAD(squareCycloFp12BN254_c12_y) + 15781046857382959121140505691131389728661226093902862303002526578701400754315n :MLOAD(squareCycloFp12BN254_c13_x) + 8625093555241362381542545391636743832938050376057983419042860774659518282797n :MLOAD(squareCycloFp12BN254_c13_y) + 14351778565182200844681812560787756136192441388960773363087263587389322671562n :MLOAD(squareCycloFp12BN254_c21_x) + 15695337662963643544813486120899631949921737819129690254830667492646284393382n :MLOAD(squareCycloFp12BN254_c21_y) + 5570195873148749154672896518046181211644563497843962677067647498629814883385n :MLOAD(squareCycloFp12BN254_c22_x) + 14991026153829150387150002728101017951749162083560649689008171461754623678203n :MLOAD(squareCycloFp12BN254_c22_y) + 18987338659195924269172748027172054817706283508452795151531146694958273165690n :MLOAD(squareCycloFp12BN254_c23_x) + 8860539994207234999664733841364243523346939192669625740842082601247122017n :MLOAD(squareCycloFp12BN254_c23_y) + + ; 3] Squaring in Compressed Form: It must happen that D(C(a²)) = a² + 11706129207700151979042100288958216850158405562525260961392090752318820540155n :MSTORE(squareCompCycloFp12BN254_Ca2_x) + 13581688218243497693010389261307054804658398598414171976249347555990073884710n :MSTORE(squareCompCycloFp12BN254_Ca2_y) + 2650685350723162073065693030364953757603657135232283880472468071129041178893n :MSTORE(squareCompCycloFp12BN254_Ca3_x) + 1415534485628002925645978830263295545820817030311522411523977773123510463790n :MSTORE(squareCompCycloFp12BN254_Ca3_y) + 20034916004680903865371475524544157810838259782601065778963371780592670397755n :MSTORE(squareCompCycloFp12BN254_Ca4_x) + 18196221800554323016660057972017335112712278872243164622794778048181747904770n :MSTORE(squareCompCycloFp12BN254_Ca4_y) + 11182696274116283149832659131689911508224992839995672842130064887471806829782n :MSTORE(squareCompCycloFp12BN254_Ca5_x) + 13862086431460254638576437312497952755826436162922426416336796129991391475329n :MSTORE(squareCompCycloFp12BN254_Ca5_y) + :CALL(squareCompCycloFp12BN254) + 14351778565182200844681812560787756136192441388960773363087263587389322671562n :MLOAD(squareCompCycloFp12BN254_Cb2_x) + 15695337662963643544813486120899631949921737819129690254830667492646284393382n :MLOAD(squareCompCycloFp12BN254_Cb2_y) + 15781046857382959121140505691131389728661226093902862303002526578701400754315n :MLOAD(squareCompCycloFp12BN254_Cb3_x) + 8625093555241362381542545391636743832938050376057983419042860774659518282797n :MLOAD(squareCompCycloFp12BN254_Cb3_y) + 6856859212192321831831255712736216614951508355737406292407364405936415355512n :MLOAD(squareCompCycloFp12BN254_Cb4_x) + 17209588680055969912485542074372495831925486815137906387799790601911548657525n :MLOAD(squareCompCycloFp12BN254_Cb4_y) + 18987338659195924269172748027172054817706283508452795151531146694958273165690n :MLOAD(squareCompCycloFp12BN254_Cb5_x) + 8860539994207234999664733841364243523346939192669625740842082601247122017n :MLOAD(squareCompCycloFp12BN254_Cb5_y) + $ => A :MLOAD(squareCompCycloFp12BN254_Cb2_x) + $ => B :MLOAD(squareCompCycloFp12BN254_Cb2_y) + $ => C :MLOAD(squareCompCycloFp12BN254_Cb3_x) + $ => D :MLOAD(squareCompCycloFp12BN254_Cb3_y) + A :MSTORE(decompressFp12BN254_Ca2_x) + B :MSTORE(decompressFp12BN254_Ca2_y) + C :MSTORE(decompressFp12BN254_Ca3_x) + D :MSTORE(decompressFp12BN254_Ca3_y) + $ => A :MLOAD(squareCompCycloFp12BN254_Cb4_x) + $ => B :MLOAD(squareCompCycloFp12BN254_Cb4_y) + $ => C :MLOAD(squareCompCycloFp12BN254_Cb5_x) + $ => D :MLOAD(squareCompCycloFp12BN254_Cb5_y) + A :MSTORE(decompressFp12BN254_Ca4_x) + B :MSTORE(decompressFp12BN254_Ca4_y) + C :MSTORE(decompressFp12BN254_Ca5_x) + D :MSTORE(decompressFp12BN254_Ca5_y) + :CALL(decompressFp12BN254) + 2098026393950394559493690260865166581266928315924710629633888310320006689795n :MLOAD(decompressFp12BN254_a0_x) + 1846888720299666666109042029094532002505741710678796245911331796963733914187n :MLOAD(decompressFp12BN254_a0_y) + 14351778565182200844681812560787756136192441388960773363087263587389322671562n :MLOAD(decompressFp12BN254_a2_x) + 15695337662963643544813486120899631949921737819129690254830667492646284393382n :MLOAD(decompressFp12BN254_a2_y) + 6856859212192321831831255712736216614951508355737406292407364405936415355512n :MLOAD(decompressFp12BN254_a4_x) + 17209588680055969912485542074372495831925486815137906387799790601911548657525n :MLOAD(decompressFp12BN254_a4_y) + 5570195873148749154672896518046181211644563497843962677067647498629814883385n :MLOAD(decompressFp12BN254_a1_x) + 14991026153829150387150002728101017951749162083560649689008171461754623678203n :MLOAD(decompressFp12BN254_a1_y) + 15781046857382959121140505691131389728661226093902862303002526578701400754315n :MLOAD(decompressFp12BN254_a3_x) + 8625093555241362381542545391636743832938050376057983419042860774659518282797n :MLOAD(decompressFp12BN254_a3_y) + 18987338659195924269172748027172054817706283508452795151531146694958273165690n :MLOAD(decompressFp12BN254_a5_x) + 8860539994207234999664733841364243523346939192669625740842082601247122017n :MLOAD(decompressFp12BN254_a5_y) + + ; 4] Exponentiation + 0n :MSTORE(expCycloFp12BN254_e) + 0n :MSTORE(expCycloFp12BN254_a11_x) + 0n :MSTORE(expCycloFp12BN254_a11_y) + 0n :MSTORE(expCycloFp12BN254_a12_x) + 0n :MSTORE(expCycloFp12BN254_a12_y) + 0n :MSTORE(expCycloFp12BN254_a13_x) + 0n :MSTORE(expCycloFp12BN254_a13_y) + 0n :MSTORE(expCycloFp12BN254_a21_x) + 0n :MSTORE(expCycloFp12BN254_a21_y) + 0n :MSTORE(expCycloFp12BN254_a22_x) + 0n :MSTORE(expCycloFp12BN254_a22_y) + 0n :MSTORE(expCycloFp12BN254_a23_x) + 0n :MSTORE(expCycloFp12BN254_a23_y) + :CALL(expCycloFp12BN254) + 0n :MLOAD(expCycloFp12BN254_c11_x) + 0n :MLOAD(expCycloFp12BN254_c11_y) + 0n :MLOAD(expCycloFp12BN254_c12_x) + 0n :MLOAD(expCycloFp12BN254_c12_y) + 0n :MLOAD(expCycloFp12BN254_c13_x) + 0n :MLOAD(expCycloFp12BN254_c13_y) + 0n :MLOAD(expCycloFp12BN254_c21_x) + 0n :MLOAD(expCycloFp12BN254_c21_y) + 0n :MLOAD(expCycloFp12BN254_c22_x) + 0n :MLOAD(expCycloFp12BN254_c22_y) + 0n :MLOAD(expCycloFp12BN254_c23_x) + 0n :MLOAD(expCycloFp12BN254_c23_y) + + 10n :MSTORE(expCycloFp12BN254_e) + 0n :MSTORE(expCycloFp12BN254_a11_x) + 0n :MSTORE(expCycloFp12BN254_a11_y) + 0n :MSTORE(expCycloFp12BN254_a12_x) + 0n :MSTORE(expCycloFp12BN254_a12_y) + 0n :MSTORE(expCycloFp12BN254_a13_x) + 0n :MSTORE(expCycloFp12BN254_a13_y) + 0n :MSTORE(expCycloFp12BN254_a21_x) + 0n :MSTORE(expCycloFp12BN254_a21_y) + 0n :MSTORE(expCycloFp12BN254_a22_x) + 0n :MSTORE(expCycloFp12BN254_a22_y) + 0n :MSTORE(expCycloFp12BN254_a23_x) + 0n :MSTORE(expCycloFp12BN254_a23_y) + :CALL(expCycloFp12BN254) + 0n :MLOAD(expCycloFp12BN254_c11_x) + 0n :MLOAD(expCycloFp12BN254_c11_y) + 0n :MLOAD(expCycloFp12BN254_c12_x) + 0n :MLOAD(expCycloFp12BN254_c12_y) + 0n :MLOAD(expCycloFp12BN254_c13_x) + 0n :MLOAD(expCycloFp12BN254_c13_y) + 0n :MLOAD(expCycloFp12BN254_c21_x) + 0n :MLOAD(expCycloFp12BN254_c21_y) + 0n :MLOAD(expCycloFp12BN254_c22_x) + 0n :MLOAD(expCycloFp12BN254_c22_y) + 0n :MLOAD(expCycloFp12BN254_c23_x) + 0n :MLOAD(expCycloFp12BN254_c23_y) + + 0n :MSTORE(expCycloFp12BN254_e) + 1n :MSTORE(expCycloFp12BN254_a11_x) + 0n :MSTORE(expCycloFp12BN254_a11_y) + 0n :MSTORE(expCycloFp12BN254_a12_x) + 0n :MSTORE(expCycloFp12BN254_a12_y) + 0n :MSTORE(expCycloFp12BN254_a13_x) + 0n :MSTORE(expCycloFp12BN254_a13_y) + 0n :MSTORE(expCycloFp12BN254_a21_x) + 0n :MSTORE(expCycloFp12BN254_a21_y) + 0n :MSTORE(expCycloFp12BN254_a22_x) + 0n :MSTORE(expCycloFp12BN254_a22_y) + 0n :MSTORE(expCycloFp12BN254_a23_x) + 0n :MSTORE(expCycloFp12BN254_a23_y) + :CALL(expCycloFp12BN254) + 1n :MLOAD(expCycloFp12BN254_c11_x) + 0n :MLOAD(expCycloFp12BN254_c11_y) + 0n :MLOAD(expCycloFp12BN254_c12_x) + 0n :MLOAD(expCycloFp12BN254_c12_y) + 0n :MLOAD(expCycloFp12BN254_c13_x) + 0n :MLOAD(expCycloFp12BN254_c13_y) + 0n :MLOAD(expCycloFp12BN254_c21_x) + 0n :MLOAD(expCycloFp12BN254_c21_y) + 0n :MLOAD(expCycloFp12BN254_c22_x) + 0n :MLOAD(expCycloFp12BN254_c22_y) + 0n :MLOAD(expCycloFp12BN254_c23_x) + 0n :MLOAD(expCycloFp12BN254_c23_y) + + 0n :MSTORE(expCycloFp12BN254_e) + 2n :MSTORE(expCycloFp12BN254_a11_x) + 0n :MSTORE(expCycloFp12BN254_a11_y) + 0n :MSTORE(expCycloFp12BN254_a12_x) + 0n :MSTORE(expCycloFp12BN254_a12_y) + 0n :MSTORE(expCycloFp12BN254_a13_x) + 0n :MSTORE(expCycloFp12BN254_a13_y) + 0n :MSTORE(expCycloFp12BN254_a21_x) + 0n :MSTORE(expCycloFp12BN254_a21_y) + 0n :MSTORE(expCycloFp12BN254_a22_x) + 0n :MSTORE(expCycloFp12BN254_a22_y) + 0n :MSTORE(expCycloFp12BN254_a23_x) + 0n :MSTORE(expCycloFp12BN254_a23_y) + :CALL(expCycloFp12BN254) + 1n :MLOAD(expCycloFp12BN254_c11_x) + 0n :MLOAD(expCycloFp12BN254_c11_y) + 0n :MLOAD(expCycloFp12BN254_c12_x) + 0n :MLOAD(expCycloFp12BN254_c12_y) + 0n :MLOAD(expCycloFp12BN254_c13_x) + 0n :MLOAD(expCycloFp12BN254_c13_y) + 0n :MLOAD(expCycloFp12BN254_c21_x) + 0n :MLOAD(expCycloFp12BN254_c21_y) + 0n :MLOAD(expCycloFp12BN254_c22_x) + 0n :MLOAD(expCycloFp12BN254_c22_y) + 0n :MLOAD(expCycloFp12BN254_c23_x) + 0n :MLOAD(expCycloFp12BN254_c23_y) + + 4965661367192848881n :MSTORE(expCycloFp12BN254_e) + 12879671296228341798957541889042068293248913689212425431224938470232546313254n :MSTORE(expCycloFp12BN254_a11_x) + 3326450555199805883965490851796414254830144151329718176108864533289444035270n :MSTORE(expCycloFp12BN254_a11_y) + 20034916004680903865371475524544157810838259782601065778963371780592670397755n :MSTORE(expCycloFp12BN254_a12_x) + 18196221800554323016660057972017335112712278872243164622794778048181747904770n :MSTORE(expCycloFp12BN254_a12_y) + 2650685350723162073065693030364953757603657135232283880472468071129041178893n :MSTORE(expCycloFp12BN254_a13_x) + 1415534485628002925645978830263295545820817030311522411523977773123510463790n :MSTORE(expCycloFp12BN254_a13_y) + 11706129207700151979042100288958216850158405562525260961392090752318820540155n :MSTORE(expCycloFp12BN254_a21_x) + 13581688218243497693010389261307054804658398598414171976249347555990073884710n :MSTORE(expCycloFp12BN254_a21_y) + 865661210072615391091663782916883487315505694294592934212781713437127182959n :MSTORE(expCycloFp12BN254_a22_x) + 5364456672142552956341240304849409513108281743490635067211876654163672173225n :MSTORE(expCycloFp12BN254_a22_y) + 11182696274116283149832659131689911508224992839995672842130064887471806829782n :MSTORE(expCycloFp12BN254_a23_x) + 13862086431460254638576437312497952755826436162922426416336796129991391475329n :MSTORE(expCycloFp12BN254_a23_y) + :CALL(expCycloFp12BN254) + 8622123276929149313920900390800567957350463902034345693686819104151152922572n :MLOAD(expCycloFp12BN254_c11_x) + 8670626622362378075940101766943937502063808822022259182641087586661549444087n :MLOAD(expCycloFp12BN254_c11_y) + 17677799802795013101301829823610804881266875691488004414652375004895811278559n :MLOAD(expCycloFp12BN254_c12_x) + 8272841324134833464040573295664197017808088708485767794513847108589815911499n :MLOAD(expCycloFp12BN254_c12_y) + 9190911511691766859289188288177517604435774623843629661940012957026870785904n :MLOAD(expCycloFp12BN254_c13_x) + 18364099160954539591912436449937202384011431251285107932512938026494677069261n :MLOAD(expCycloFp12BN254_c13_y) + 19407988223605275774004312333801897121509906148567729782984282773586873391901n :MLOAD(expCycloFp12BN254_c21_x) + 15711652497826967457911333154250406880785527028595026050702704710166760791736n :MLOAD(expCycloFp12BN254_c21_y) + 16450402722786864781692733695027245893014266492802042336563706983420459072544n :MLOAD(expCycloFp12BN254_c22_x) + 11669304897933026204553226847848522415487901344170781144466032622467776938641n :MLOAD(expCycloFp12BN254_c22_y) + 14005155248465440637906492674345786073382135452928153479559868247493919227266n :MLOAD(expCycloFp12BN254_c23_x) + 20231158774990444129983338146063043702239109464764996510430767078543929636660n :MLOAD(expCycloFp12BN254_c23_y) + + ; 5] Exponentiation by x + 0n :MSTORE(expByXCycloFp12BN254_a11_x) + 0n :MSTORE(expByXCycloFp12BN254_a11_y) + 0n :MSTORE(expByXCycloFp12BN254_a12_x) + 0n :MSTORE(expByXCycloFp12BN254_a12_y) + 0n :MSTORE(expByXCycloFp12BN254_a13_x) + 0n :MSTORE(expByXCycloFp12BN254_a13_y) + 0n :MSTORE(expByXCycloFp12BN254_a21_x) + 0n :MSTORE(expByXCycloFp12BN254_a21_y) + 0n :MSTORE(expByXCycloFp12BN254_a22_x) + 0n :MSTORE(expByXCycloFp12BN254_a22_y) + 0n :MSTORE(expByXCycloFp12BN254_a23_x) + 0n :MSTORE(expByXCycloFp12BN254_a23_y) + :CALL(expByXCycloFp12BN254) + 0n :MLOAD(expByXCycloFp12BN254_c11_x) + 0n :MLOAD(expByXCycloFp12BN254_c11_y) + 0n :MLOAD(expByXCycloFp12BN254_c12_x) + 0n :MLOAD(expByXCycloFp12BN254_c12_y) + 0n :MLOAD(expByXCycloFp12BN254_c13_x) + 0n :MLOAD(expByXCycloFp12BN254_c13_y) + 0n :MLOAD(expByXCycloFp12BN254_c21_x) + 0n :MLOAD(expByXCycloFp12BN254_c21_y) + 0n :MLOAD(expByXCycloFp12BN254_c22_x) + 0n :MLOAD(expByXCycloFp12BN254_c22_y) + 0n :MLOAD(expByXCycloFp12BN254_c23_x) + 0n :MLOAD(expByXCycloFp12BN254_c23_y) + + 1n :MSTORE(expByXCycloFp12BN254_a11_x) + 0n :MSTORE(expByXCycloFp12BN254_a11_y) + 0n :MSTORE(expByXCycloFp12BN254_a12_x) + 0n :MSTORE(expByXCycloFp12BN254_a12_y) + 0n :MSTORE(expByXCycloFp12BN254_a13_x) + 0n :MSTORE(expByXCycloFp12BN254_a13_y) + 0n :MSTORE(expByXCycloFp12BN254_a21_x) + 0n :MSTORE(expByXCycloFp12BN254_a21_y) + 0n :MSTORE(expByXCycloFp12BN254_a22_x) + 0n :MSTORE(expByXCycloFp12BN254_a22_y) + 0n :MSTORE(expByXCycloFp12BN254_a23_x) + 0n :MSTORE(expByXCycloFp12BN254_a23_y) + :CALL(expByXCycloFp12BN254) + 1n :MLOAD(expByXCycloFp12BN254_c11_x) + 0n :MLOAD(expByXCycloFp12BN254_c11_y) + 0n :MLOAD(expByXCycloFp12BN254_c12_x) + 0n :MLOAD(expByXCycloFp12BN254_c12_y) + 0n :MLOAD(expByXCycloFp12BN254_c13_x) + 0n :MLOAD(expByXCycloFp12BN254_c13_y) + 0n :MLOAD(expByXCycloFp12BN254_c21_x) + 0n :MLOAD(expByXCycloFp12BN254_c21_y) + 0n :MLOAD(expByXCycloFp12BN254_c22_x) + 0n :MLOAD(expByXCycloFp12BN254_c22_y) + 0n :MLOAD(expByXCycloFp12BN254_c23_x) + 0n :MLOAD(expByXCycloFp12BN254_c23_y) + + 12879671296228341798957541889042068293248913689212425431224938470232546313254n :MSTORE(expByXCycloFp12BN254_a11_x) + 3326450555199805883965490851796414254830144151329718176108864533289444035270n :MSTORE(expByXCycloFp12BN254_a11_y) + 20034916004680903865371475524544157810838259782601065778963371780592670397755n :MSTORE(expByXCycloFp12BN254_a12_x) + 18196221800554323016660057972017335112712278872243164622794778048181747904770n :MSTORE(expByXCycloFp12BN254_a12_y) + 2650685350723162073065693030364953757603657135232283880472468071129041178893n :MSTORE(expByXCycloFp12BN254_a13_x) + 1415534485628002925645978830263295545820817030311522411523977773123510463790n :MSTORE(expByXCycloFp12BN254_a13_y) + 11706129207700151979042100288958216850158405562525260961392090752318820540155n :MSTORE(expByXCycloFp12BN254_a21_x) + 13581688218243497693010389261307054804658398598414171976249347555990073884710n :MSTORE(expByXCycloFp12BN254_a21_y) + 865661210072615391091663782916883487315505694294592934212781713437127182959n :MSTORE(expByXCycloFp12BN254_a22_x) + 5364456672142552956341240304849409513108281743490635067211876654163672173225n :MSTORE(expByXCycloFp12BN254_a22_y) + 11182696274116283149832659131689911508224992839995672842130064887471806829782n :MSTORE(expByXCycloFp12BN254_a23_x) + 13862086431460254638576437312497952755826436162922426416336796129991391475329n :MSTORE(expByXCycloFp12BN254_a23_y) + :CALL(expByXCycloFp12BN254) + 8622123276929149313920900390800567957350463902034345693686819104151152922572n :MLOAD(expByXCycloFp12BN254_c11_x) + 8670626622362378075940101766943937502063808822022259182641087586661549444087n :MLOAD(expByXCycloFp12BN254_c11_y) + 17677799802795013101301829823610804881266875691488004414652375004895811278559n :MLOAD(expByXCycloFp12BN254_c12_x) + 8272841324134833464040573295664197017808088708485767794513847108589815911499n :MLOAD(expByXCycloFp12BN254_c12_y) + 9190911511691766859289188288177517604435774623843629661940012957026870785904n :MLOAD(expByXCycloFp12BN254_c13_x) + 18364099160954539591912436449937202384011431251285107932512938026494677069261n :MLOAD(expByXCycloFp12BN254_c13_y) + 19407988223605275774004312333801897121509906148567729782984282773586873391901n :MLOAD(expByXCycloFp12BN254_c21_x) + 15711652497826967457911333154250406880785527028595026050702704710166760791736n :MLOAD(expByXCycloFp12BN254_c21_y) + 16450402722786864781692733695027245893014266492802042336563706983420459072544n :MLOAD(expByXCycloFp12BN254_c22_x) + 11669304897933026204553226847848522415487901344170781144466032622467776938641n :MLOAD(expByXCycloFp12BN254_c22_y) + 14005155248465440637906492674345786073382135452928153479559868247493919227266n :MLOAD(expByXCycloFp12BN254_c23_x) + 20231158774990444129983338146063043702239109464764996510430767078543929636660n :MLOAD(expByXCycloFp12BN254_c23_y) + + + ; 6] Exponentiation by x using the compression/decompression technique + 0n :MSTORE(expByXCompCycloFp12BN254_a0_x) + 0n :MSTORE(expByXCompCycloFp12BN254_a0_y) + 0n :MSTORE(expByXCompCycloFp12BN254_a2_x) + 0n :MSTORE(expByXCompCycloFp12BN254_a2_y) + 0n :MSTORE(expByXCompCycloFp12BN254_a4_x) + 0n :MSTORE(expByXCompCycloFp12BN254_a4_y) + 0n :MSTORE(expByXCompCycloFp12BN254_a1_x) + 0n :MSTORE(expByXCompCycloFp12BN254_a1_y) + 0n :MSTORE(expByXCompCycloFp12BN254_a3_x) + 0n :MSTORE(expByXCompCycloFp12BN254_a3_y) + 0n :MSTORE(expByXCompCycloFp12BN254_a5_x) + 0n :MSTORE(expByXCompCycloFp12BN254_a5_y) + :CALL(expByXCompCycloFp12BN254) + 0n :MLOAD(expByXCompCycloFp12BN254_c0_x) + 0n :MLOAD(expByXCompCycloFp12BN254_c0_y) + 0n :MLOAD(expByXCompCycloFp12BN254_c2_x) + 0n :MLOAD(expByXCompCycloFp12BN254_c2_y) + 0n :MLOAD(expByXCompCycloFp12BN254_c4_x) + 0n :MLOAD(expByXCompCycloFp12BN254_c4_y) + 0n :MLOAD(expByXCompCycloFp12BN254_c1_x) + 0n :MLOAD(expByXCompCycloFp12BN254_c1_y) + 0n :MLOAD(expByXCompCycloFp12BN254_c3_x) + 0n :MLOAD(expByXCompCycloFp12BN254_c3_y) + 0n :MLOAD(expByXCompCycloFp12BN254_c5_x) + 0n :MLOAD(expByXCompCycloFp12BN254_c5_y) + + 1n :MSTORE(expByXCompCycloFp12BN254_a0_x) + 0n :MSTORE(expByXCompCycloFp12BN254_a0_y) + 0n :MSTORE(expByXCompCycloFp12BN254_a2_x) + 0n :MSTORE(expByXCompCycloFp12BN254_a2_y) + 0n :MSTORE(expByXCompCycloFp12BN254_a4_x) + 0n :MSTORE(expByXCompCycloFp12BN254_a4_y) + 0n :MSTORE(expByXCompCycloFp12BN254_a1_x) + 0n :MSTORE(expByXCompCycloFp12BN254_a1_y) + 0n :MSTORE(expByXCompCycloFp12BN254_a3_x) + 0n :MSTORE(expByXCompCycloFp12BN254_a3_y) + 0n :MSTORE(expByXCompCycloFp12BN254_a5_x) + 0n :MSTORE(expByXCompCycloFp12BN254_a5_y) + :CALL(expByXCompCycloFp12BN254) + 1n :MLOAD(expByXCompCycloFp12BN254_c0_x) + 0n :MLOAD(expByXCompCycloFp12BN254_c0_y) + 0n :MLOAD(expByXCompCycloFp12BN254_c2_x) + 0n :MLOAD(expByXCompCycloFp12BN254_c2_y) + 0n :MLOAD(expByXCompCycloFp12BN254_c4_x) + 0n :MLOAD(expByXCompCycloFp12BN254_c4_y) + 0n :MLOAD(expByXCompCycloFp12BN254_c1_x) + 0n :MLOAD(expByXCompCycloFp12BN254_c1_y) + 0n :MLOAD(expByXCompCycloFp12BN254_c3_x) + 0n :MLOAD(expByXCompCycloFp12BN254_c3_y) + 0n :MLOAD(expByXCompCycloFp12BN254_c5_x) + 0n :MLOAD(expByXCompCycloFp12BN254_c5_y) + + 12879671296228341798957541889042068293248913689212425431224938470232546313254n :MSTORE(expByXCompCycloFp12BN254_a0_x) + 3326450555199805883965490851796414254830144151329718176108864533289444035270n :MSTORE(expByXCompCycloFp12BN254_a0_y) + 11706129207700151979042100288958216850158405562525260961392090752318820540155n :MSTORE(expByXCompCycloFp12BN254_a2_x) + 13581688218243497693010389261307054804658398598414171976249347555990073884710n :MSTORE(expByXCompCycloFp12BN254_a2_y) + 20034916004680903865371475524544157810838259782601065778963371780592670397755n :MSTORE(expByXCompCycloFp12BN254_a4_x) + 18196221800554323016660057972017335112712278872243164622794778048181747904770n :MSTORE(expByXCompCycloFp12BN254_a4_y) + 865661210072615391091663782916883487315505694294592934212781713437127182959n :MSTORE(expByXCompCycloFp12BN254_a1_x) + 5364456672142552956341240304849409513108281743490635067211876654163672173225n :MSTORE(expByXCompCycloFp12BN254_a1_y) + 2650685350723162073065693030364953757603657135232283880472468071129041178893n :MSTORE(expByXCompCycloFp12BN254_a3_x) + 1415534485628002925645978830263295545820817030311522411523977773123510463790n :MSTORE(expByXCompCycloFp12BN254_a3_y) + 11182696274116283149832659131689911508224992839995672842130064887471806829782n :MSTORE(expByXCompCycloFp12BN254_a5_x) + 13862086431460254638576437312497952755826436162922426416336796129991391475329n :MSTORE(expByXCompCycloFp12BN254_a5_y) + :CALL(expByXCompCycloFp12BN254) + 8622123276929149313920900390800567957350463902034345693686819104151152922572n :MLOAD(expByXCompCycloFp12BN254_c0_x) + 8670626622362378075940101766943937502063808822022259182641087586661549444087n :MLOAD(expByXCompCycloFp12BN254_c0_y) + 19407988223605275774004312333801897121509906148567729782984282773586873391901n :MLOAD(expByXCompCycloFp12BN254_c2_x) + 15711652497826967457911333154250406880785527028595026050702704710166760791736n :MLOAD(expByXCompCycloFp12BN254_c2_y) + 17677799802795013101301829823610804881266875691488004414652375004895811278559n :MLOAD(expByXCompCycloFp12BN254_c4_x) + 8272841324134833464040573295664197017808088708485767794513847108589815911499n :MLOAD(expByXCompCycloFp12BN254_c4_y) + 16450402722786864781692733695027245893014266492802042336563706983420459072544n :MLOAD(expByXCompCycloFp12BN254_c1_x) + 11669304897933026204553226847848522415487901344170781144466032622467776938641n :MLOAD(expByXCompCycloFp12BN254_c1_y) + 9190911511691766859289188288177517604435774623843629661940012957026870785904n :MLOAD(expByXCompCycloFp12BN254_c3_x) + 18364099160954539591912436449937202384011431251285107932512938026494677069261n :MLOAD(expByXCompCycloFp12BN254_c3_y) + 14005155248465440637906492674345786073382135452928153479559868247493919227266n :MLOAD(expByXCompCycloFp12BN254_c5_x) + 20231158774990444129983338146063043702239109464764996510430767078543929636660n :MLOAD(expByXCompCycloFp12BN254_c5_y) + +end: + + $ => A :MLOAD(initial_A) + $ => B :MLOAD(initial_B) + $ => C :MLOAD(initial_C) + $ => D :MLOAD(initial_D) + $ => E :MLOAD(initial_E) + $ => CTX :MLOAD(initial_CTX) + $ => SP :MLOAD(initial_SP) + $ => PC :MLOAD(initial_PC) + $ => GAS :MLOAD(initial_GAS) + $ => SR :MLOAD(initial_SR) + $ => RR :MLOAD(initial_RR) + $ => HASHPOS :MLOAD(initial_HASHPOS) + $ => RCX :MLOAD(initial_RCX) + +; label finalizeExecution needed by executor C++ +finalizeExecution: + ${beforeLast()} : JMPN(finalizeExecution) + + : JMP(start) +opINVALID: +; label checkAndSaveFrom needed by executor C++ +checkAndSaveFrom: + :JMP(opINVALID) + +INCLUDE "../main/pairings/FPBN254/reduceFpBN254.zkasm" +INCLUDE "../main/pairings/FPBN254/addFpBN254.zkasm" + +INCLUDE "../main/pairings/FP2BN254/addFp2BN254.zkasm" +INCLUDE "../main/pairings/FP2BN254/subFp2BN254.zkasm" +INCLUDE "../main/pairings/FP2BN254/invFp2BN254.zkasm" +INCLUDE "../main/pairings/FP2BN254/mulFp2BN254.zkasm" +INCLUDE "../main/pairings/FP2BN254/squareFp2BN254.zkasm" +INCLUDE "../main/pairings/FP2BN254/escalarMulFp2BN254.zkasm" + +INCLUDE "../main/pairings/FP4BN254/squareFp4BN254.zkasm" + +INCLUDE "../main/pairings/FP6BN254/addFp6BN254.zkasm" +INCLUDE "../main/pairings/FP6BN254/subFp6BN254.zkasm" +INCLUDE "../main/pairings/FP6BN254/sparseMulAFp6BN254.zkasm" +INCLUDE "../main/pairings/FP6BN254/mulFp6BN254.zkasm" + +INCLUDE "../main/pairings/FP12BN254/mulFp12BN254.zkasm" + +INCLUDE "../main/pairings/FP12BN254/CYCLOFP12BN254/xBinDecompBN254.zkasm" +INCLUDE "../main/pairings/FP12BN254/CYCLOFP12BN254/compressFp12BN254.zkasm" +INCLUDE "../main/pairings/FP12BN254/CYCLOFP12BN254/decompressFp12BN254.zkasm" +INCLUDE "../main/pairings/FP12BN254/CYCLOFP12BN254/squareCompCycloFp12BN254.zkasm" +INCLUDE "../main/pairings/FP12BN254/CYCLOFP12BN254/expByXCompCycloFp12BN254.zkasm" +INCLUDE "../main/pairings/FP12BN254/CYCLOFP12BN254/squareCycloFp12BN254.zkasm" + +INCLUDE "../main/pairings/utilsTests/expCycloFp12BN254.zkasm" + +INCLUDE "../main/pairings/unused/xPseudoBinDecompBN254.zkasm" +INCLUDE "../main/pairings/unused/expByXCycloFp12BN254.zkasm" \ No newline at end of file diff --git a/test/testEcAdd.zkasm b/test/testEcAdd.zkasm new file mode 100644 index 00000000..20d75426 --- /dev/null +++ b/test/testEcAdd.zkasm @@ -0,0 +1,252 @@ +; constants needed by executor C++ +CONST %N = 2**19 +CONST %MAX_CNT_STEPS_LIMIT = %N +CONST %MAX_CNT_ARITH_LIMIT = %N +CONST %MAX_CNT_BINARY_LIMIT = %N +CONST %MAX_CNT_MEM_ALIGN_LIMIT = %N +CONST %MAX_CNT_KECCAK_F_LIMIT = %N +CONST %MAX_CNT_PADDING_PG_LIMIT = %N +CONST %MAX_CNT_POSEIDON_G_LIMIT = %N + +CONSTL %BN254_P = 21888242871839275222246405745257275088696311157297823662689037894645226208583n +CONSTL %BN254_P_MINUS_ONE = 21888242871839275222246405745257275088696311157297823662689037894645226208582n +CONSTL %BN254_E_B = 3n + +VAR GLOBAL lastHashKId +VAR GLOBAL lastHashPId + +VAR GLOBAL initial_A +VAR GLOBAL initial_B +VAR GLOBAL initial_C +VAR GLOBAL initial_D +VAR GLOBAL initial_E +VAR GLOBAL initial_CTX +VAR GLOBAL initial_SP +VAR GLOBAL initial_PC +VAR GLOBAL initial_GAS +VAR GLOBAL initial_SR +VAR GLOBAL initial_RR +VAR GLOBAL initial_HASHPOS +VAR GLOBAL initial_RCX + +start: + + STEP => A + 0 :ASSERT + + + A :MSTORE(initial_A) + B :MSTORE(initial_B) + C :MSTORE(initial_C) + D :MSTORE(initial_D) + E :MSTORE(initial_E) + CTX :MSTORE(initial_CTX) + SP :MSTORE(initial_SP) + PC :MSTORE(initial_PC) + GAS :MSTORE(initial_GAS) + SR :MSTORE(initial_SR) + RR :MSTORE(initial_RR) + HASHPOS :MSTORE(initial_HASHPOS) + RCX :MSTORE(initial_RCX) + 0 => A,B,C,D,E,CTX, SP, PC, GAS, SR, RR, HASHPOS, RCX + + -1 :MSTORE(lastHashKId) + -1 :MSTORE(lastHashPId) + + ; 1] 0 + 0 = 0 + 0n :MSTORE(ecAdd_P1_x) + 0n :MSTORE(ecAdd_P1_y) + 0n :MSTORE(ecAdd_P2_x) + 0n :MSTORE(ecAdd_P2_y) + :CALL(ecAdd) + 0n :MLOAD(ecAdd_P3_x) + 0n :MLOAD(ecAdd_P3_y) + + + ; 2] 0 + P = P + 0n :MSTORE(ecAdd_P1_x) + 0n :MSTORE(ecAdd_P1_y) + 1n :MSTORE(ecAdd_P2_x) + 2n :MSTORE(ecAdd_P2_y) + :CALL(ecAdd) + 1n :MLOAD(ecAdd_P3_x) + 2n :MLOAD(ecAdd_P3_y) + + ; 3] P + 0 = P + 1n :MSTORE(ecAdd_P1_x) + 2n :MSTORE(ecAdd_P1_y) + 0n :MSTORE(ecAdd_P2_x) + 0n :MSTORE(ecAdd_P2_y) + :CALL(ecAdd) + 1n :MLOAD(ecAdd_P3_x) + 2n :MLOAD(ecAdd_P3_y) + + ; 4] P1 not in range + 21888242871839275222246405745257275088696311157297823662689037894645226208584n :MSTORE(ecAdd_P1_x) + 2n :MSTORE(ecAdd_P1_y) + 3n :MSTORE(ecAdd_P2_x) + 3n :MSTORE(ecAdd_P2_y) + :CALL(ecAdd) + 1 => A + 1 :EQ + + 1n :MSTORE(ecAdd_P1_x) + 21888242871839275222246405745257275088696311157297823662689037894645226208585n :MSTORE(ecAdd_P1_y) + 3n :MSTORE(ecAdd_P2_x) + 3n :MSTORE(ecAdd_P2_y) + :CALL(ecAdd) + 2 => A + 1 :EQ + + ; 5] P2 not in range + 1n :MSTORE(ecAdd_P1_x) + 2n :MSTORE(ecAdd_P1_y) + 21888242871839275222246405745257275088696311157297823662689037894645226208583n :MSTORE(ecAdd_P2_x) + 0n :MSTORE(ecAdd_P2_y) + :CALL(ecAdd) + 3 => A + 1 :EQ + + 1n :MSTORE(ecAdd_P1_x) + 2n :MSTORE(ecAdd_P1_y) + 0n :MSTORE(ecAdd_P2_x) + 21888242871839275222246405745257275088696311157297823662689037894645226208583n :MSTORE(ecAdd_P2_y) + :CALL(ecAdd) + 4 => A + 1 :EQ + + ; 6] P1 not in E + 1n :MSTORE(ecAdd_P1_x) + 0n :MSTORE(ecAdd_P1_y) + 0n :MSTORE(ecAdd_P2_x) + 0n :MSTORE(ecAdd_P2_y) + :CALL(ecAdd) + 5 => A + 1 :EQ + + 1n :MSTORE(ecAdd_P1_x) + 0n :MSTORE(ecAdd_P1_y) + 1n :MSTORE(ecAdd_P2_x) + 2n :MSTORE(ecAdd_P2_y) + :CALL(ecAdd) + 5 => A + 1 :EQ + + ; 7] P2 not in E + 0n :MSTORE(ecAdd_P1_x) + 0n :MSTORE(ecAdd_P1_y) + 1n :MSTORE(ecAdd_P2_x) + 0n :MSTORE(ecAdd_P2_y) + :CALL(ecAdd) + 6 => A + 1 :EQ + + 1n :MSTORE(ecAdd_P1_x) + 2n :MSTORE(ecAdd_P1_y) + 1n :MSTORE(ecAdd_P2_x) + 0n :MSTORE(ecAdd_P2_y) + :CALL(ecAdd) + 6 => A + 1 :EQ + + ; 8] P + (-P) = 0 + 10744596414106452074759370245733544594153395043370666422502510773307029471145n :MSTORE(ecAdd_P1_x) + 848677436511517736191562425154572367705380862894644942948681172815252343932n :MSTORE(ecAdd_P1_y) + 10744596414106452074759370245733544594153395043370666422502510773307029471145n :MSTORE(ecAdd_P2_x) + 21039565435327757486054843320102702720990930294403178719740356721829973864651n :MSTORE(ecAdd_P2_y) + :CALL(ecAdd) + 0n :MLOAD(ecAdd_P3_x) + 0n :MLOAD(ecAdd_P3_y) + + ; 9] P + Q when P != Q + 2893332206675025542079383054128180540025417352513932043566889211329192179032n :MSTORE(ecAdd_P1_x) + 6530629491743359417280396166892081514007566149119717903717756741482263401518n :MSTORE(ecAdd_P1_y) + 15490799329273967747501973647822742581714860109251269127154113506193693607878n :MSTORE(ecAdd_P2_x) + 4229358293223510599397432508631487048670295788986070026939193461742686527076n :MSTORE(ecAdd_P2_y) + :CALL(ecAdd) + 13154776318592227270778558029295227935378730842313609923118896637591559850250n :MLOAD(ecAdd_P3_x) + 11035980320923476543935377623718958678920911311849399323950347759358969041431n :MLOAD(ecAdd_P3_y) + 1745860766704548035074878643814414425056208216948549237180537806484993001172n :MSTORE(ecAdd_P1_x) + 10428992577810537311515619307712828512800028181521723820412159824785899508051n :MSTORE(ecAdd_P1_y) + 10744596414106452074759370245733544594153395043370666422502510773307029471145n :MSTORE(ecAdd_P2_x) + 848677436511517736191562425154572367705380862894644942948681172815252343932n :MSTORE(ecAdd_P2_y) + :CALL(ecAdd) + 20109137777308224484751705964830245061785572657602899297228633767392913518415n :MLOAD(ecAdd_P3_x) + 14499175368639637950478596677291617168262069295802020711454610174461584835979n :MLOAD(ecAdd_P3_y) + + ; 10] P + P + 2893332206675025542079383054128180540025417352513932043566889211329192179032n :MSTORE(ecAdd_P1_x) + 6530629491743359417280396166892081514007566149119717903717756741482263401518n :MSTORE(ecAdd_P1_y) + 2893332206675025542079383054128180540025417352513932043566889211329192179032n :MSTORE(ecAdd_P2_x) + 6530629491743359417280396166892081514007566149119717903717756741482263401518n :MSTORE(ecAdd_P2_y) + :CALL(ecAdd) + 11220622501868821308995844886766009822833441579384302982823096531245924405698n :MLOAD(ecAdd_P3_x) + 2355690023525969090855462437460037724073976772193253577110863269987724684477n :MLOAD(ecAdd_P3_y) + 15490799329273967747501973647822742581714860109251269127154113506193693607878n :MSTORE(ecAdd_P1_x) + 4229358293223510599397432508631487048670295788986070026939193461742686527076n :MSTORE(ecAdd_P1_y) + 15490799329273967747501973647822742581714860109251269127154113506193693607878n :MSTORE(ecAdd_P2_x) + 4229358293223510599397432508631487048670295788986070026939193461742686527076n :MSTORE(ecAdd_P2_y) + :CALL(ecAdd) + 14301632400969957113316344359548233118734763289927867040319376723985850943059n :MLOAD(ecAdd_P3_x) + 19259402839901377893267670172732143592044261932601111690978918426524987173751n :MLOAD(ecAdd_P3_y) + 1745860766704548035074878643814414425056208216948549237180537806484993001172n :MSTORE(ecAdd_P1_x) + 10428992577810537311515619307712828512800028181521723820412159824785899508051n :MSTORE(ecAdd_P1_y) + 1745860766704548035074878643814414425056208216948549237180537806484993001172n :MSTORE(ecAdd_P2_x) + 10428992577810537311515619307712828512800028181521723820412159824785899508051n :MSTORE(ecAdd_P2_y) + :CALL(ecAdd) + 7635241416710394435863784018619353890364763495262225661273147225960091861733n :MLOAD(ecAdd_P3_x) + 21716464559528323959695889215160185865818678200951896286120725092340748527691n :MLOAD(ecAdd_P3_y) + 10744596414106452074759370245733544594153395043370666422502510773307029471145n :MSTORE(ecAdd_P1_x) + 848677436511517736191562425154572367705380862894644942948681172815252343932n :MSTORE(ecAdd_P1_y) + 10744596414106452074759370245733544594153395043370666422502510773307029471145n :MSTORE(ecAdd_P2_x) + 848677436511517736191562425154572367705380862894644942948681172815252343932n :MSTORE(ecAdd_P2_y) + :CALL(ecAdd) + 4444740815889402603535294170722302758225367627362056425101568584910268024244n :MLOAD(ecAdd_P3_x) + 10537263096529483164618820017164668921386457028564663708352735080900270541420n :MLOAD(ecAdd_P3_y) + + ; 11] Worst case scenario in terms of ARITH calls and therefore in terms of number of steps + ; In this case, we only need to perform a doubling, since the cost of ecAdd is constant + ; on its input and doubling strictly dominates addition in terms of cost. + 2893332206675025542079383054128180540025417352513932043566889211329192179032n :MSTORE(ecAdd_P1_x) + 6530629491743359417280396166892081514007566149119717903717756741482263401518n :MSTORE(ecAdd_P1_y) + 2893332206675025542079383054128180540025417352513932043566889211329192179032n :MSTORE(ecAdd_P2_x) + 6530629491743359417280396166892081514007566149119717903717756741482263401518n :MSTORE(ecAdd_P2_y) + :CALL(ecAdd) + 11220622501868821308995844886766009822833441579384302982823096531245924405698n :MLOAD(ecAdd_P3_x) + 2355690023525969090855462437460037724073976772193253577110863269987724684477n :MLOAD(ecAdd_P3_y) + +end: + + $ => A :MLOAD(initial_A) + $ => B :MLOAD(initial_B) + $ => C :MLOAD(initial_C) + $ => D :MLOAD(initial_D) + $ => E :MLOAD(initial_E) + $ => CTX :MLOAD(initial_CTX) + $ => SP :MLOAD(initial_SP) + $ => PC :MLOAD(initial_PC) + $ => GAS :MLOAD(initial_GAS) + $ => SR :MLOAD(initial_SR) + $ => RR :MLOAD(initial_RR) + $ => HASHPOS :MLOAD(initial_HASHPOS) + $ => RCX :MLOAD(initial_RCX) + +; label finalizeExecution needed by executor C++ +finalizeExecution: + ${beforeLast()} : JMPN(finalizeExecution) + + : JMP(start) +opINVALID: +; label checkAndSaveFrom needed by executor C++ +checkAndSaveFrom: + :JMP(opINVALID) + + +INCLUDE "../main/pairings/BN254/ecAdd.zkasm" + +INCLUDE "../main/pairings/FPBN254/reduceFpBN254.zkasm" +INCLUDE "../main/pairings/FPBN254/addFpBN254.zkasm" +INCLUDE "../main/pairings/FPBN254/subFpBN254.zkasm" +INCLUDE "../main/pairings/FPBN254/mulFpBN254.zkasm" +INCLUDE "../main/pairings/FPBN254/squareFpBN254.zkasm" +INCLUDE "../main/pairings/FPBN254/invFpBN254.zkasm" \ No newline at end of file diff --git a/test/testEcMul.zkasm b/test/testEcMul.zkasm new file mode 100644 index 00000000..992b61fc --- /dev/null +++ b/test/testEcMul.zkasm @@ -0,0 +1,231 @@ +; constants needed by executor C++ +CONST %N = 2**19 +CONST %MAX_CNT_STEPS_LIMIT = %N +CONST %MAX_CNT_ARITH_LIMIT = %N +CONST %MAX_CNT_BINARY_LIMIT = %N +CONST %MAX_CNT_MEM_ALIGN_LIMIT = %N +CONST %MAX_CNT_KECCAK_F_LIMIT = %N +CONST %MAX_CNT_PADDING_PG_LIMIT = %N +CONST %MAX_CNT_POSEIDON_G_LIMIT = %N + +CONSTL %BN254_P = 21888242871839275222246405745257275088696311157297823662689037894645226208583n +CONSTL %BN254_P_MINUS_ONE = 21888242871839275222246405745257275088696311157297823662689037894645226208582n +CONSTL %BN254_R = 21888242871839275222246405745257275088548364400416034343698204186575808495617n +CONSTL %BN254_E_B = 3n + +VAR GLOBAL lastHashKId +VAR GLOBAL lastHashPId + +VAR GLOBAL initial_A +VAR GLOBAL initial_B +VAR GLOBAL initial_C +VAR GLOBAL initial_D +VAR GLOBAL initial_E +VAR GLOBAL initial_CTX +VAR GLOBAL initial_SP +VAR GLOBAL initial_PC +VAR GLOBAL initial_GAS +VAR GLOBAL initial_SR +VAR GLOBAL initial_RR +VAR GLOBAL initial_HASHPOS +VAR GLOBAL initial_RCX + +start: + + STEP => A + 0 :ASSERT + + + A :MSTORE(initial_A) + B :MSTORE(initial_B) + C :MSTORE(initial_C) + D :MSTORE(initial_D) + E :MSTORE(initial_E) + CTX :MSTORE(initial_CTX) + SP :MSTORE(initial_SP) + PC :MSTORE(initial_PC) + GAS :MSTORE(initial_GAS) + SR :MSTORE(initial_SR) + RR :MSTORE(initial_RR) + HASHPOS :MSTORE(initial_HASHPOS) + RCX :MSTORE(initial_RCX) + 0 => A,B,C,D,E,CTX, SP, PC, GAS, SR, RR, HASHPOS, RCX + + -1 :MSTORE(lastHashKId) + -1 :MSTORE(lastHashPId) + + ; 1] 0·O = O + 0n :MSTORE(ecMul_k) + 0n :MSTORE(ecMul_P_x) + 0n :MSTORE(ecMul_P_y) + :CALL(ecMul) + 0n :MLOAD(ecMul_Q_x) + 0n :MLOAD(ecMul_Q_y) + + ; 2] k·O = O + 5n :MSTORE(ecMul_k) + 0n :MSTORE(ecMul_P_x) + 0n :MSTORE(ecMul_P_y) + :CALL(ecMul) + 0n :MLOAD(ecMul_Q_x) + 0n :MLOAD(ecMul_Q_y) + + ; 3] 0·P = O, where P != O + 0n :MSTORE(ecMul_k) + 1n :MSTORE(ecMul_P_x) + 2n :MSTORE(ecMul_P_y) + :CALL(ecMul) + 0n :MLOAD(ecMul_Q_x) + 0n :MLOAD(ecMul_Q_y) + + ; 4] P not in range + 0n :MSTORE(ecMul_k) + 21888242871839275222246405745257275088696311157297823662689037894645226208584n :MSTORE(ecMul_P_x) + 2n :MSTORE(ecMul_P_y) + :CALL(ecMul) + 1 => A + 1 :EQ + + 0n :MSTORE(ecMul_k) + 1n :MSTORE(ecMul_P_x) + 21888242871839275222246405745257275088696311157297823662689037894645226208585n :MSTORE(ecMul_P_y) + :CALL(ecMul) + 2 => A + 1 :EQ + + ; 5] P not in E + 0n :MSTORE(ecMul_k) + 1n :MSTORE(ecMul_P_x) + 0n :MSTORE(ecMul_P_y) + :CALL(ecMul) + 3 => A + 1 :EQ + + 65n :MSTORE(ecMul_k) + 1n :MSTORE(ecMul_P_x) + 0n :MSTORE(ecMul_P_y) + :CALL(ecMul) + 3 => A + 1 :EQ + + ; 6] k·P when k != 0 + 1n :MSTORE(ecMul_k) + 1n :MSTORE(ecMul_P_x) + 2n :MSTORE(ecMul_P_y) + :CALL(ecMul) + 1n :MLOAD(ecMul_Q_x) + 2n :MLOAD(ecMul_Q_y) + + 2n :MSTORE(ecMul_k) + 1n :MSTORE(ecMul_P_x) + 2n :MSTORE(ecMul_P_y) + :CALL(ecMul) + 1368015179489954701390400359078579693043519447331113978918064868415326638035n :MLOAD(ecMul_Q_x) + 9918110051302171585080402603319702774565515993150576347155970296011118125764n :MLOAD(ecMul_Q_y) + 65n :MSTORE(ecMul_k) + 1n :MSTORE(ecMul_P_x) + 2n :MSTORE(ecMul_P_y) + :CALL(ecMul) + 21184532036463169063041779836861514142873086093180850953095098556309204188255n :MLOAD(ecMul_Q_x) + 16870949628445799017882714788639508275834535486794531840392367353784571921174n :MLOAD(ecMul_Q_y) + 10000000089n :MSTORE(ecMul_k) + 1n :MSTORE(ecMul_P_x) + 2n :MSTORE(ecMul_P_y) + :CALL(ecMul) + 4768044760451824005417871472283223457728569810854115125480649095031772328870n :MLOAD(ecMul_Q_x) + 21389337952468851259287213083493638952853622949895525580347877121675081015727n :MLOAD(ecMul_Q_y) + 57n :MSTORE(ecMul_k) + 1745860766704548035074878643814414425056208216948549237180537806484993001172n :MSTORE(ecMul_P_x) + 10428992577810537311515619307712828512800028181521723820412159824785899508051n :MSTORE(ecMul_P_y) + :CALL(ecMul) + 21092868577100313210583214784627729175513062432513303686654820611840644382013n :MLOAD(ecMul_Q_x) + 10293123368529248350591404721829100625076077203595282162629899903703630633665n :MLOAD(ecMul_Q_y) + 123456789n :MSTORE(ecMul_k) + 1745860766704548035074878643814414425056208216948549237180537806484993001172n :MSTORE(ecMul_P_x) + 10428992577810537311515619307712828512800028181521723820412159824785899508051n :MSTORE(ecMul_P_y) + :CALL(ecMul) + 9551410454255481932113938269904288675272239827491596157984458647610565008967n :MLOAD(ecMul_Q_x) + 17781856861347070862134441477208204792978952663354273425763774350233183876915n :MLOAD(ecMul_Q_y) + 21888242871839275222246405745257275088548364400416034343698204186575808495617n :MSTORE(ecMul_k) + 1n :MSTORE(ecMul_P_x) + 2n :MSTORE(ecMul_P_y) + :CALL(ecMul) + 0n :MLOAD(ecMul_Q_x) + 0n :MLOAD(ecMul_Q_y) + + 21888242871839275222246405745257275088548364400416034343698204186575808495618n :MSTORE(ecMul_k) + 1n :MSTORE(ecMul_P_x) + 2n :MSTORE(ecMul_P_y) + :CALL(ecMul) + 1n :MLOAD(ecMul_Q_x) + 2n :MLOAD(ecMul_Q_y) + + 21888242871839275222246405745257275088696311157297823662689037894645226208583n :MSTORE(ecMul_k) + 1n :MSTORE(ecMul_P_x) + 2n :MSTORE(ecMul_P_y) + :CALL(ecMul) + 7793429943220682609834519115512946233910458086191548249060013461061457526887n :MLOAD(ecMul_Q_x) + 16460968250425543446028981775631045522280113359306664586749259656855967130574n :MLOAD(ecMul_Q_y) + + 21888242871839275222246405745257275088696311157297823662689037894645226208584n :MSTORE(ecMul_k) + 1n :MSTORE(ecMul_P_x) + 2n :MSTORE(ecMul_P_y) + :CALL(ecMul) + 15886422571275617715400903250697722692198979607302343556925904858625057687404n :MLOAD(ecMul_Q_x) + 9788557113822741943783365060165103517008620829146475047263378292709661309554n :MLOAD(ecMul_Q_y) + 115792089237316195423570985008687907853269984665640564039457584007913129639935n :MSTORE(ecMul_k) + 1n :MSTORE(ecMul_P_x) + 2n :MSTORE(ecMul_P_y) + :CALL(ecMul) + 21415159568991615317144600033915305503576371596506956373206836402282692989778n :MLOAD(ecMul_Q_x) + 8573070896319864868535933562264623076420652926303237982078693068147657243287n :MLOAD(ecMul_Q_y) + + ; 7] Worst case scenario in terms of ARITH calls and therefore in terms of number of steps. + ; In ecMul, this should be the scalar multiplication with scalar with higer Hamming weight + ; that is lower than r, which in this case is 2^253 - 1. + 14474011154664524427946373126085988481658748083205070504932198000989141204991n :MSTORE(ecMul_k) + 1n :MSTORE(ecMul_P_x) + 2n :MSTORE(ecMul_P_y) + :CALL(ecMul) + 3739418567393436576913511739065691570763034865122368432616000129799288055432n :MLOAD(ecMul_Q_x) + 18298856760603404171434473181920219106007178146585940397845192637485681860518n :MLOAD(ecMul_Q_y) + + +end: + + $ => A :MLOAD(initial_A) + $ => B :MLOAD(initial_B) + $ => C :MLOAD(initial_C) + $ => D :MLOAD(initial_D) + $ => E :MLOAD(initial_E) + $ => CTX :MLOAD(initial_CTX) + $ => SP :MLOAD(initial_SP) + $ => PC :MLOAD(initial_PC) + $ => GAS :MLOAD(initial_GAS) + $ => SR :MLOAD(initial_SR) + $ => RR :MLOAD(initial_RR) + $ => HASHPOS :MLOAD(initial_HASHPOS) + $ => RCX :MLOAD(initial_RCX) + +; label finalizeExecution needed by executor C++ +finalizeExecution: + ${beforeLast()} : JMPN(finalizeExecution) + + : JMP(start) +opINVALID: +; label checkAndSaveFrom needed by executor C++ +checkAndSaveFrom: + :JMP(opINVALID) + + +INCLUDE "../main/pairings/BN254/ecMul.zkasm" +INCLUDE "../main/pairings/BN254/ecAdd.zkasm" + +INCLUDE "../main/pairings/FRBN254/reduceFrBN254.zkasm" + +INCLUDE "../main/pairings/FPBN254/reduceFpBN254.zkasm" +INCLUDE "../main/pairings/FPBN254/addFpBN254.zkasm" +INCLUDE "../main/pairings/FPBN254/subFpBN254.zkasm" +INCLUDE "../main/pairings/FPBN254/mulFpBN254.zkasm" +INCLUDE "../main/pairings/FPBN254/squareFpBN254.zkasm" +INCLUDE "../main/pairings/FPBN254/invFpBN254.zkasm" \ No newline at end of file diff --git a/test/testEcPairing.zkasm b/test/testEcPairing.zkasm new file mode 100644 index 00000000..a29a5be1 --- /dev/null +++ b/test/testEcPairing.zkasm @@ -0,0 +1,436 @@ +; constants needed by executor C++ +CONST %N = 2**19 +;CONST %MAX_CNT_STEPS_LIMIT = %N +;CONST %MAX_CNT_ARITH_LIMIT = %N +;CONST %MAX_CNT_BINARY_LIMIT = %N +;CONST %MAX_CNT_MEM_ALIGN_LIMIT = %N +;CONST %MAX_CNT_KECCAK_F_LIMIT = %N +;CONST %MAX_CNT_PADDING_PG_LIMIT = %N +;CONST %MAX_CNT_POSEIDON_G_LIMIT = %N + +VAR GLOBAL lastHashKId +VAR GLOBAL lastHashPId + +VAR GLOBAL initial_A +VAR GLOBAL initial_B +VAR GLOBAL initial_C +VAR GLOBAL initial_D +VAR GLOBAL initial_E +VAR GLOBAL initial_CTX +VAR GLOBAL initial_SP +VAR GLOBAL initial_PC +VAR GLOBAL initial_GAS +VAR GLOBAL initial_SR +VAR GLOBAL initial_RR +VAR GLOBAL initial_HASHPOS +VAR GLOBAL initial_RCX + +start: + STEP => A + 0 :ASSERT + + A :MSTORE(initial_A) + B :MSTORE(initial_B) + C :MSTORE(initial_C) + D :MSTORE(initial_D) + E :MSTORE(initial_E) + CTX :MSTORE(initial_CTX) + SP :MSTORE(initial_SP) + PC :MSTORE(initial_PC) + GAS :MSTORE(initial_GAS) + SR :MSTORE(initial_SR) + RR :MSTORE(initial_RR) + HASHPOS :MSTORE(initial_HASHPOS) + RCX :MSTORE(initial_RCX) + 0 => A,B,C,D,E,CTX, SP, PC, GAS, SR, RR, HASHPOS, RCX + + -1 :MSTORE(lastHashKId) + -1 :MSTORE(lastHashPId) + + ; 1] 0 inputs should return 1 + 0 :MSTORE(ecPairing_ninputs) + :CALL(ecPairing) + 0 => A + B :ASSERT + 1 :MLOAD(ecPairing_result) + + ; 2] Tests with 6 inputs + ; 2.1] Fails and returns nothing if the input is invalid + 1 :MSTORE(ecPairing_ninputs) + 32*6 :MSTORE(txCalldataLen) + -32 :MSTORE(readXFromCalldataOffset) + 0 => E + 0n :MSTORE(MEM:E) + 1n :MSTORE(MEM:E + 1) + 2046729899889901964437012741252570163462327955511008570480857952505584629957n :MSTORE(MEM:E + 2) + 4351401811647638138392695977895401859084096897123577305203754529537814663109n :MSTORE(MEM:E + 3) + 14316075702276096164483565793667862351398527813470041574939773541551376891710n :MSTORE(MEM:E + 4) + 322506915963699862059245473966830598387691259163658767351233132602858049743n :MSTORE(MEM:E + 5) + :CALL(ecPairing) + 1 => A + B :ASSERT + + 1 :MSTORE(ecPairing_ninputs) + 32*6 :MSTORE(txCalldataLen) + -32 :MSTORE(readXFromCalldataOffset) + 0 => E + 0n :MSTORE(MEM:E) + 0n :MSTORE(MEM:E + 1) + 2046729899889901964437012741252570163462327955511008570480857952505584629957n :MSTORE(MEM:E + 2) + 4351401811647638138392695977895401859084096897123577305203754529537814663108n :MSTORE(MEM:E + 3) + 14316075702276096164483565793667862351398527813470041574939773541551376891710n :MSTORE(MEM:E + 4) + 322506915963699862059245473966830598387691259163658767351233132602858049743n :MSTORE(MEM:E + 5) + :CALL(ecPairing) + 1 => A + B :ASSERT + + 1 :MSTORE(ecPairing_ninputs) + 32*6 :MSTORE(txCalldataLen) + -32 :MSTORE(readXFromCalldataOffset) + 0 => E + 1n :MSTORE(MEM:E) + 2n :MSTORE(MEM:E + 1) + 2046729899889901964437012741252570163462327955511008570480857952505584629957n :MSTORE(MEM:E + 2) + 4351401811647638138392695977895401859084096897123577305203754529537814663108n :MSTORE(MEM:E + 3) + 14316075702276096164483565793667862351398527813470041574939773541551376891710n :MSTORE(MEM:E + 4) + 322506915963699862059245473966830598387691259163658767351233132602858049743n :MSTORE(MEM:E + 5) + :CALL(ecPairing) + 1 => A + B :ASSERT + + 1 :MSTORE(ecPairing_ninputs) + 32*6 :MSTORE(txCalldataLen) + -32 :MSTORE(readXFromCalldataOffset) + 0 => E + 1n :MSTORE(MEM:E) + 1n :MSTORE(MEM:E + 1) + 0n :MSTORE(MEM:E + 2) + 0n :MSTORE(MEM:E + 3) + 0n :MSTORE(MEM:E + 4) + 0n :MSTORE(MEM:E + 5) + :CALL(ecPairing) + 1 => A + B :ASSERT + + 1 :MSTORE(ecPairing_ninputs) + 32*6 :MSTORE(txCalldataLen) + -32 :MSTORE(readXFromCalldataOffset) + 0 => E + 0n :MSTORE(MEM:E) + 0n :MSTORE(MEM:E + 1) + 1n :MSTORE(MEM:E + 2) + 2n :MSTORE(MEM:E + 3) + 3n :MSTORE(MEM:E + 4) + 3n :MSTORE(MEM:E + 5) + :CALL(ecPairing) + 1 => A + B :ASSERT + + ; 2.2] Fails if some input is not in range + 1 :MSTORE(ecPairing_ninputs) + 32*6 :MSTORE(txCalldataLen) + -32 :MSTORE(readXFromCalldataOffset) + 0 => E + 21888242871839275222246405745257275088696311157297823662689037894645226208583n :MSTORE(MEM:E) + 1n :MSTORE(MEM:E + 1) + 0n :MSTORE(MEM:E + 2) + 0n :MSTORE(MEM:E + 3) + 0n :MSTORE(MEM:E + 4) + 0n :MSTORE(MEM:E + 5) + :CALL(ecPairing) + 1 => A + B :ASSERT + + 1 :MSTORE(ecPairing_ninputs) + 32*6 :MSTORE(txCalldataLen) + -32 :MSTORE(readXFromCalldataOffset) + 0 => E + 1n :MSTORE(MEM:E) + 21888242871839275222246405745257275088696311157297823662689037894645226208583n :MSTORE(MEM:E + 1) + 0n :MSTORE(MEM:E + 2) + 0n :MSTORE(MEM:E + 3) + 0n :MSTORE(MEM:E + 4) + 0n :MSTORE(MEM:E + 5) + :CALL(ecPairing) + 1 => A + B :ASSERT + + 1 :MSTORE(ecPairing_ninputs) + 32*6 :MSTORE(txCalldataLen) + -32 :MSTORE(readXFromCalldataOffset) + 0 => E + 1n :MSTORE(MEM:E) + 2n :MSTORE(MEM:E + 1) + 21888242871839275222246405745257275088696311157297823662689037894645226208583n :MSTORE(MEM:E + 2) + 0n :MSTORE(MEM:E + 3) + 0n :MSTORE(MEM:E + 4) + 0n :MSTORE(MEM:E + 5) + :CALL(ecPairing) + 1 => A + B :ASSERT + + 1 :MSTORE(ecPairing_ninputs) + 32*6 :MSTORE(txCalldataLen) + -32 :MSTORE(readXFromCalldataOffset) + 0 => E + 1n :MSTORE(MEM:E) + 2n :MSTORE(MEM:E + 1) + 0n :MSTORE(MEM:E + 2) + 21888242871839275222246405745257275088696311157297823662689037894645226208583n :MSTORE(MEM:E + 3) + 0n :MSTORE(MEM:E + 4) + 0n :MSTORE(MEM:E + 5) + :CALL(ecPairing) + 1 => A + B :ASSERT + + 1 :MSTORE(ecPairing_ninputs) + 32*6 :MSTORE(txCalldataLen) + -32 :MSTORE(readXFromCalldataOffset) + 0 => E + 1n :MSTORE(MEM:E) + 2n :MSTORE(MEM:E + 1) + 0n :MSTORE(MEM:E + 2) + 0n :MSTORE(MEM:E + 3) + 21888242871839275222246405745257275088696311157297823662689037894645226208583n :MSTORE(MEM:E + 4) + 0n :MSTORE(MEM:E + 5) + :CALL(ecPairing) + 1 => A + B :ASSERT + + 1 :MSTORE(ecPairing_ninputs) + 32*6 :MSTORE(txCalldataLen) + -32 :MSTORE(readXFromCalldataOffset) + 0 => E + 1n :MSTORE(MEM:E) + 2n :MSTORE(MEM:E + 1) + 0n :MSTORE(MEM:E + 2) + 0n :MSTORE(MEM:E + 3) + 0n :MSTORE(MEM:E + 4) + 21888242871839275222246405745257275088696311157297823662689037894645226208583n :MSTORE(MEM:E + 5) + :CALL(ecPairing) + 1 => A + B :ASSERT + + ; 2.3] Degenerate tests: e(0,Q) = 1 or e(P,0) = 1 therefore the pairing equation is trivally satisfied + ; and in fact this is the only possibility for the pairing equation to be satisfied with one pair of P,Q + 1 :MSTORE(ecPairing_ninputs) + 32*6 :MSTORE(txCalldataLen) + -32 :MSTORE(readXFromCalldataOffset) + 0 => E + 0n :MSTORE(MEM:E) + 0n :MSTORE(MEM:E + 1) + 2046729899889901964437012741252570163462327955511008570480857952505584629957n :MSTORE(MEM:E + 2) + 4351401811647638138392695977895401859084096897123577305203754529537814663109n :MSTORE(MEM:E + 3) + 14316075702276096164483565793667862351398527813470041574939773541551376891710n :MSTORE(MEM:E + 4) + 322506915963699862059245473966830598387691259163658767351233132602858049743n :MSTORE(MEM:E + 5) + :CALL(ecPairing) + 0 => A + B :ASSERT + 1 :MLOAD(ecPairing_result) + + 1 :MSTORE(ecPairing_ninputs) + 32*6 :MSTORE(txCalldataLen) + -32 :MSTORE(readXFromCalldataOffset) + 0 => E + 1n :MSTORE(MEM:E) + 2n :MSTORE(MEM:E + 1) + 0n :MSTORE(MEM:E + 2) + 0n :MSTORE(MEM:E + 3) + 0n :MSTORE(MEM:E + 4) + 0n :MSTORE(MEM:E + 5) + :CALL(ecPairing) + 0 => A + B :ASSERT + 1 :MLOAD(ecPairing_result) + + 1 :MSTORE(ecPairing_ninputs) + 32*6 :MSTORE(txCalldataLen) + -32 :MSTORE(readXFromCalldataOffset) + 0 => E + 0n :MSTORE(MEM:E) + 0n :MSTORE(MEM:E + 1) + 11559732032986387107991004021392285783925812861821192530917403151452391805634n :MSTORE(MEM:E + 2) + 10857046999023057135944570762232829481370756359578518086990519993285655852781n :MSTORE(MEM:E + 3) + 4082367875863433681332203403145435568316851327593401208105741076214120093531n :MSTORE(MEM:E + 4) + 8495653923123431417604973247489272438418190587263600148770280649306958101930n :MSTORE(MEM:E + 5) + :CALL(ecPairing) + 0 => A + B :ASSERT + 1 :MLOAD(ecPairing_result) + + 1 :MSTORE(ecPairing_ninputs) + 32*6 :MSTORE(txCalldataLen) + -32 :MSTORE(readXFromCalldataOffset) + + 0 => E + 0n :MSTORE(MEM:E) + 0n :MSTORE(MEM:E + 1) + 11509234998032783125480266028213992619847908725038453197451386571405359529652n :MSTORE(MEM:E + 2) + 4099696940551850412667065443628214990719002449715926250279745743126938401735n :MSTORE(MEM:E + 3) + 19060191254988907833052035421850065496347936631097225966803157637464336346786n :MSTORE(MEM:E + 4) + 16129402215257578064845163124174157135534373400489420174780024516864802406908n :MSTORE(MEM:E + 5) + :CALL(ecPairing) + 0 => A + B :ASSERT + 1 :MLOAD(ecPairing_result) + + ; 3] Tests with 12 inputs + + ; Ethereum example + 2 :MSTORE(ecPairing_ninputs) + 32*6*2 :MSTORE(txCalldataLen) + -32 :MSTORE(readXFromCalldataOffset) + 0 => E + 20333349487611174579608837001148061570648440167819460274134014152400656275674n :MSTORE(MEM:E) + 19928268888036365434500215951569291213336085054454884806456691094014419998198n :MSTORE(MEM:E + 1) + 14335504872549532354210489828671972911333347940534076142795111812609903378108n :MSTORE(MEM:E + 2) + 15548973838770842196102442698708122006189018193868154757846481038796366125273n :MSTORE(MEM:E + 3) + 19822981108166058814837087071162475941148726886187076297764129491697321004944n :MSTORE(MEM:E + 4) + 21654797034782659092642090020723114658730107139270194997413654453096686856286n :MSTORE(MEM:E + 5) + 1n :MSTORE(MEM:E + 6) + 21888242871839275222246405745257275088696311157297823662689037894645226208581n :MSTORE(MEM:E + 7) + 11509234998032783125480266028213992619847908725038453197451386571405359529652n :MSTORE(MEM:E + 8) + 4099696940551850412667065443628214990719002449715926250279745743126938401735n :MSTORE(MEM:E + 9) + 19060191254988907833052035421850065496347936631097225966803157637464336346786n :MSTORE(MEM:E + 10) + 16129402215257578064845163124174157135534373400489420174780024516864802406908n :MSTORE(MEM:E + 11) + :CALL(ecPairing) + 0 => A + B :ASSERT + 1 :MLOAD(ecPairing_result) + + ; KZG proof with one poly and one evaluation + 2 :MSTORE(ecPairing_ninputs) + 32*6*2 :MSTORE(txCalldataLen) + -32 :MSTORE(readXFromCalldataOffset) + 0 => E + 20593188969319011263398594823255811823444990825298196162496264072013322991388n :MSTORE(MEM:E) + 20958531318718262179638310844977035402258325676941759254411716094948903283238n :MSTORE(MEM:E + 1) + 19014538453489502551198430834271851224745298622671277274539119640314913863353n :MSTORE(MEM:E + 2) + 4011274991290276638756079424799286249285264639232842260296401218902340006571n :MSTORE(MEM:E + 3) + 5493217260886730300768636259682920882409386426126823957476482234761131640151n :MSTORE(MEM:E + 4) + 18471742500483808444303896273620229467289887099913869033627754256214290219997n :MSTORE(MEM:E + 5) + 3526892542800189419786189901545486150149308978725362430328886936745555020543n :MSTORE(MEM:E + 6) + 2119286186166371280112264238015778473404141003919064027522145193839708208181n :MSTORE(MEM:E + 7) + 11559732032986387107991004021392285783925812861821192530917403151452391805634n :MSTORE(MEM:E + 8) + 10857046999023057135944570762232829481370756359578518086990519993285655852781n :MSTORE(MEM:E + 9) + 4082367875863433681332203403145435568316851327593401208105741076214120093531n :MSTORE(MEM:E + 10) + 8495653923123431417604973247489272438418190587263600148770280649306958101930n :MSTORE(MEM:E + 11) + :CALL(ecPairing) + 0 => A + B :ASSERT + 1 :MLOAD(ecPairing_result) + + ; KZG proof with one poly and one evaluation + 2 :MSTORE(ecPairing_ninputs) + 32*6*2 :MSTORE(txCalldataLen) + -32 :MSTORE(readXFromCalldataOffset) + 0 => E + 7732322222446307127032679746925673403013840763103947213960757438494804067267n :MSTORE(MEM:E) + 8619360092012773279112944586645719683585858765189162557863470404130431808723n :MSTORE(MEM:E + 1) + 7754062701624777074058760614745676120554164137217320298195308357000412149840n :MSTORE(MEM:E + 2) + 4480687189204505779534873101802061566996023148878380905742776654135663383221n :MSTORE(MEM:E + 3) + 18744429014512523574338799100424477374744612401726532054975840530120472566n :MSTORE(MEM:E + 4) + 16667361185745910936700318129097219900413959552154798924397125501722669434888n :MSTORE(MEM:E + 5) + 595801121933130257838893357109567932541713044978712091132608377833002940532n :MSTORE(MEM:E + 6) + 15681552092527426161541501125159206079106959026991100968107368848241580050483n :MSTORE(MEM:E + 7) + 11559732032986387107991004021392285783925812861821192530917403151452391805634n :MSTORE(MEM:E + 8) + 10857046999023057135944570762232829481370756359578518086990519993285655852781n :MSTORE(MEM:E + 9) + 4082367875863433681332203403145435568316851327593401208105741076214120093531n :MSTORE(MEM:E + 10) + 8495653923123431417604973247489272438418190587263600148770280649306958101930n :MSTORE(MEM:E + 11) + :CALL(ecPairing) + 0 => A + B :ASSERT + 1 :MLOAD(ecPairing_result) + + ; 4] Tests with 18 inputs + 3 :MSTORE(ecPairing_ninputs) + 32*6*3 :MSTORE(txCalldataLen) + -32 :MSTORE(readXFromCalldataOffset) + 0 => E + 7732322222446307127032679746925673403013840763103947213960757438494804067267n :MSTORE(MEM:E) + 8619360092012773279112944586645719683585858765189162557863470404130431808723n :MSTORE(MEM:E + 1) + 7754062701624777074058760614745676120554164137217320298195308357000412149840n :MSTORE(MEM:E + 2) + 4480687189204505779534873101802061566996023148878380905742776654135663383221n :MSTORE(MEM:E + 3) + 18744429014512523574338799100424477374744612401726532054975840530120472566n :MSTORE(MEM:E + 4) + 16667361185745910936700318129097219900413959552154798924397125501722669434888n :MSTORE(MEM:E + 5) + 595801121933130257838893357109567932541713044978712091132608377833002940532n :MSTORE(MEM:E + 6) + 15681552092527426161541501125159206079106959026991100968107368848241580050483n :MSTORE(MEM:E + 7) + 11559732032986387107991004021392285783925812861821192530917403151452391805634n :MSTORE(MEM:E + 8) + 10857046999023057135944570762232829481370756359578518086990519993285655852781n :MSTORE(MEM:E + 9) + 4082367875863433681332203403145435568316851327593401208105741076214120093531n :MSTORE(MEM:E + 10) + 8495653923123431417604973247489272438418190587263600148770280649306958101930n :MSTORE(MEM:E + 11) + 1n :MSTORE(MEM:E + 12) + 2n :MSTORE(MEM:E + 13) + 0n :MSTORE(MEM:E + 14) + 0n :MSTORE(MEM:E + 15) + 0n :MSTORE(MEM:E + 16) + 0n :MSTORE(MEM:E + 17) + :CALL(ecPairing) + 0 => A + B :ASSERT + 1 :MLOAD(ecPairing_result) + + 3 :MSTORE(ecPairing_ninputs) + 32*6*3 :MSTORE(txCalldataLen) + -32 :MSTORE(readXFromCalldataOffset) + 0 => E + 20408625067408993290064640368727791004970573998302586029702220794326757674498n :MSTORE(MEM:E) + 16305464745216061320718924810220361252899630638785881184214175311729150579496n :MSTORE(MEM:E + 1) + 19366297632879679637284621799459008574776307690134846433263569915955921902826n :MSTORE(MEM:E + 2) + 7402184029652592179271650707149396214555402416834379616679103713331638701004n :MSTORE(MEM:E + 3) + 13233069919494729038860025360853108843397419493559475327647450442468969143158n :MSTORE(MEM:E + 4) + 10493112377715503836766497500954305714610771526749266396762372159550562853087n :MSTORE(MEM:E + 5) + 6065896804174124393372571703959114319291624137637105019419069942189555692569n :MSTORE(MEM:E + 6) + 1817372094771574002977021734119138264961743925299214620753363200235482672254n :MSTORE(MEM:E + 7) + 19366297632879679637284621799459008574776307690134846433263569915955921902826n :MSTORE(MEM:E + 8) + 7402184029652592179271650707149396214555402416834379616679103713331638701004n :MSTORE(MEM:E + 9) + 13233069919494729038860025360853108843397419493559475327647450442468969143158n :MSTORE(MEM:E + 10) + 10493112377715503836766497500954305714610771526749266396762372159550562853087n :MSTORE(MEM:E + 11) + 5155695327752856721154364733178772660419613502017586895566245903460009198248n :MSTORE(MEM:E + 12) + 17870951736543108265510715325941304521966082260796939666348236029204261385066n :MSTORE(MEM:E + 13) + 11559732032986387107991004021392285783925812861821192530917403151452391805634n :MSTORE(MEM:E + 14) + 10857046999023057135944570762232829481370756359578518086990519993285655852781n :MSTORE(MEM:E + 15) + 4082367875863433681332203403145435568316851327593401208105741076214120093531n :MSTORE(MEM:E + 16) + 8495653923123431417604973247489272438418190587263600148770280649306958101930n :MSTORE(MEM:E + 17) + :CALL(ecPairing) + 0 => A + B :ASSERT + 1 :MLOAD(ecPairing_result) + + ; 5] Tests with 24 inputs + 4 :MSTORE(ecPairing_ninputs) + 32*6*4 :MSTORE(txCalldataLen) + -32 :MSTORE(readXFromCalldataOffset) + 0 => E + 1153563745531144946586097928621095258348432585499389732309707300454996283289n :MSTORE(MEM:E) + 7370404687973809887690049462468892748861464831518247317487007737601322454777n :MSTORE(MEM:E+1) + 9376055848676368316410365621777214987372973768688270899357881297879508822452n :MSTORE(MEM:E+2) + 19738309004667351906306506105426292998739264612662465709107894554928292805496n :MSTORE(MEM:E+3) + 285143926121120094170748007008262512509578107228129423236125884572189904421n :MSTORE(MEM:E+4) + 10279962913447536422932523162364510093030414102832227875578519449385249705476n :MSTORE(MEM:E+5) + 8576791937965657966843713337336683588215881223744955532549571901036035091965n :MSTORE(MEM:E+6) + 20999102966105130950411191886633074956452730563320480529699815227954081231322n :MSTORE(MEM:E+7) + 9376055848676368316410365621777214987372973768688270899357881297879508822452n :MSTORE(MEM:E+8) + 19738309004667351906306506105426292998739264612662465709107894554928292805496n :MSTORE(MEM:E+9) + 285143926121120094170748007008262512509578107228129423236125884572189904421n :MSTORE(MEM:E+10) + 10279962913447536422932523162364510093030414102832227875578519449385249705476n :MSTORE(MEM:E+11) + 18556379486610508840908277815073629329531616761731760569700551412487192333649n :MSTORE(MEM:E+12) + 17673868103043290791894327402153901008120365354485186198280340860768344163073n :MSTORE(MEM:E+13) + 11559732032986387107991004021392285783925812861821192530917403151452391805634n :MSTORE(MEM:E+14) + 10857046999023057135944570762232829481370756359578518086990519993285655852781n :MSTORE(MEM:E+15) + 4082367875863433681332203403145435568316851327593401208105741076214120093531n :MSTORE(MEM:E+16) + 8495653923123431417604973247489272438418190587263600148770280649306958101930n :MSTORE(MEM:E+17) + 20364104435611758595377721340560864676183708759135257849771131236782155536356n :MSTORE(MEM:E+18) + 6044194345605039714961350342623860353524318320217972076629496104743557530117n :MSTORE(MEM:E+19) + 11559732032986387107991004021392285783925812861821192530917403151452391805634n :MSTORE(MEM:E+20) + 10857046999023057135944570762232829481370756359578518086990519993285655852781n :MSTORE(MEM:E+21) + 4082367875863433681332203403145435568316851327593401208105741076214120093531n :MSTORE(MEM:E+22) + 8495653923123431417604973247489272438418190587263600148770280649306958101930n :MSTORE(MEM:E+23) + :CALL(ecPairing) + 0 => A + B :ASSERT + 1 :MLOAD(ecPairing_result) + + :JMP(finalizeExecution) + +INCLUDE "../main/main.zkasm" \ No newline at end of file diff --git a/test/testFinalExpBn254.zkasm b/test/testFinalExpBn254.zkasm new file mode 100644 index 00000000..6e182304 --- /dev/null +++ b/test/testFinalExpBn254.zkasm @@ -0,0 +1,139 @@ +; constants needed by executor C++ +CONST %N = 2**19 +CONST %MAX_CNT_STEPS_LIMIT = %N +CONST %MAX_CNT_ARITH_LIMIT = %N +CONST %MAX_CNT_BINARY_LIMIT = %N +CONST %MAX_CNT_MEM_ALIGN_LIMIT = %N +CONST %MAX_CNT_KECCAK_F_LIMIT = %N +CONST %MAX_CNT_PADDING_PG_LIMIT = %N +CONST %MAX_CNT_POSEIDON_G_LIMIT = %N + +VAR GLOBAL lastHashKId +VAR GLOBAL lastHashPId + +VAR GLOBAL initial_A +VAR GLOBAL initial_B +VAR GLOBAL initial_C +VAR GLOBAL initial_D +VAR GLOBAL initial_E +VAR GLOBAL initial_CTX +VAR GLOBAL initial_SP +VAR GLOBAL initial_PC +VAR GLOBAL initial_GAS +VAR GLOBAL initial_SR +VAR GLOBAL initial_RR +VAR GLOBAL initial_HASHPOS +VAR GLOBAL initial_RCX + +start: + + STEP => A + 0 :ASSERT + + + A :MSTORE(initial_A) + B :MSTORE(initial_B) + C :MSTORE(initial_C) + D :MSTORE(initial_D) + E :MSTORE(initial_E) + CTX :MSTORE(initial_CTX) + SP :MSTORE(initial_SP) + PC :MSTORE(initial_PC) + GAS :MSTORE(initial_GAS) + SR :MSTORE(initial_SR) + RR :MSTORE(initial_RR) + HASHPOS :MSTORE(initial_HASHPOS) + RCX :MSTORE(initial_RCX) + 0 => A,B,C,D,E,CTX, SP, PC, GAS, SR, RR, HASHPOS, RCX + + -1 :MSTORE(lastHashKId) + -1 :MSTORE(lastHashPId) + + 13640254227245024655838601068231183157721360561601028708811475275217122101072n :MSTORE(finalExpBN254_f11_x) + 19308417300657558492615098636528930118171456086181403615599560648373004008445n :MSTORE(finalExpBN254_f11_y) + 11600807028088028070223911119334614254604789223029238428546002219857166268982n :MSTORE(finalExpBN254_f12_x) + 4879406373235938927297467572708988980645988929154072556290202741257062565094n :MSTORE(finalExpBN254_f12_y) + 4171685090913488783052266386653991584736187693807813444268445186114207424938n :MSTORE(finalExpBN254_f13_x) + 1277573873092817905392452044933753278511826457458184982228668801202320403016n :MSTORE(finalExpBN254_f13_y) + 14431703268682647902296102635071887590346322924866425403256046961671041030534n :MSTORE(finalExpBN254_f21_x) + 11898392435919290118390574221795784387718317590754683868792519816848089304255n :MSTORE(finalExpBN254_f21_y) + 583787015380908422861158991038392109634638768690762169717364137330743074526n :MSTORE(finalExpBN254_f22_x) + 13126870183170761631152540488140870675640427576483291663794972909787720839738n :MSTORE(finalExpBN254_f22_y) + 6457767870676104874999362178075129079810053093666926870765167604207462152679n :MSTORE(finalExpBN254_f23_x) + 12911511138445339632082563502636262379527290965988664015632615336010308825090n :MSTORE(finalExpBN254_f23_y) + :CALL(finalExpBN254) + 13413524510323321318921703539856938196252165859353070108808910520379565591578n :MLOAD(finalExpBN254_f11_x) + 3548381829456735642031500506306367847474828769923557674325753657986253436214n :MLOAD(finalExpBN254_f11_y) + 11258588180307399598255242775094467208478122055367286369273756816466078325984n :MLOAD(finalExpBN254_f12_x) + 15692415863664227683780306499051704744181486071132299317385971936570963983778n :MLOAD(finalExpBN254_f12_y) + 14331327121685823241734822812072572580994818894715351943735993854561590776973n :MLOAD(finalExpBN254_f13_x) + 5829057651356763815288519037751619402051833008237861839412688801032331829766n :MLOAD(finalExpBN254_f13_y) + 15475783993587934296880977452723101772140252350911606731569729596277613550216n :MLOAD(finalExpBN254_f21_x) + 5097655688415311910623889733978393264040884000272175630800968927057028195666n :MLOAD(finalExpBN254_f21_y) + 11451831001542370722617744987566735321553462342240810632153337322850540201855n :MLOAD(finalExpBN254_f22_x) + 10214880648406402761779167726229820911960967566000435639888288131094179536430n :MLOAD(finalExpBN254_f22_y) + 7513746461017094458199399930075345786758663515755635567834665490471393582925n :MLOAD(finalExpBN254_f23_x) + 1522857835029638585907442329762418957365351568194442821861575097484378991036n :MLOAD(finalExpBN254_f23_y) + + +end: + + $ => A :MLOAD(initial_A) + $ => B :MLOAD(initial_B) + $ => C :MLOAD(initial_C) + $ => D :MLOAD(initial_D) + $ => E :MLOAD(initial_E) + $ => CTX :MLOAD(initial_CTX) + $ => SP :MLOAD(initial_SP) + $ => PC :MLOAD(initial_PC) + $ => GAS :MLOAD(initial_GAS) + $ => SR :MLOAD(initial_SR) + $ => RR :MLOAD(initial_RR) + $ => HASHPOS :MLOAD(initial_HASHPOS) + $ => RCX :MLOAD(initial_RCX) + +; label finalizeExecution needed by executor C++ +finalizeExecution: + ${beforeLast()} : JMPN(finalizeExecution) + + : JMP(start) +opINVALID: +; label checkAndSaveFrom needed by executor C++ +checkAndSaveFrom: + :JMP(opINVALID) + +INCLUDE "../main/pairings/constants.zkasm" + +INCLUDE "../main/pairings/finalExpBN254.zkasm" + +INCLUDE "../main/pairings/FPBN254/reduceFpBN254.zkasm" +INCLUDE "../main/pairings/FPBN254/addFpBN254.zkasm" + +INCLUDE "../main/pairings/FP2BN254/addFp2BN254.zkasm" +INCLUDE "../main/pairings/FP2BN254/subFp2BN254.zkasm" +INCLUDE "../main/pairings/FP2BN254/mulFp2BN254.zkasm" +INCLUDE "../main/pairings/FP2BN254/squareFp2BN254.zkasm" +INCLUDE "../main/pairings/FP2BN254/escalarMulFp2BN254.zkasm" +INCLUDE "../main/pairings/FP2BN254/invFp2BN254.zkasm" + +INCLUDE "../main/pairings/FP4BN254/squareFp4BN254.zkasm" + +INCLUDE "../main/pairings/FP6BN254/addFp6BN254.zkasm" +INCLUDE "../main/pairings/FP6BN254/subFp6BN254.zkasm" +INCLUDE "../main/pairings/FP6BN254/mulFp6BN254.zkasm" +INCLUDE "../main/pairings/FP6BN254/sparseMulAFp6BN254.zkasm" +INCLUDE "../main/pairings/FP6BN254/squareFp6BN254.zkasm" +INCLUDE "../main/pairings/FP6BN254/inverseFp6BN254.zkasm" + +INCLUDE "../main/pairings/FP12BN254/mulFp12BN254.zkasm" +INCLUDE "../main/pairings/FP12BN254/inverseFp12BN254.zkasm" +INCLUDE "../main/pairings/FP12BN254/frobFp12BN254.zkasm" +INCLUDE "../main/pairings/FP12BN254/frob2Fp12BN254.zkasm" +INCLUDE "../main/pairings/FP12BN254/frob3Fp12BN254.zkasm" + +INCLUDE "../main/pairings/FP12BN254/CYCLOFP12BN254/xBinDecompBN254.zkasm" +INCLUDE "../main/pairings/FP12BN254/CYCLOFP12BN254/compressFp12BN254.zkasm" +INCLUDE "../main/pairings/FP12BN254/CYCLOFP12BN254/decompressFp12BN254.zkasm" +INCLUDE "../main/pairings/FP12BN254/CYCLOFP12BN254/squareCompCycloFp12BN254.zkasm" +INCLUDE "../main/pairings/FP12BN254/CYCLOFP12BN254/squareCycloFp12BN254.zkasm" +INCLUDE "../main/pairings/FP12BN254/CYCLOFP12BN254/expByXCompCycloFp12BN254.zkasm" \ No newline at end of file diff --git a/test/testFp12ArithBN254.zkasm b/test/testFp12ArithBN254.zkasm new file mode 100644 index 00000000..f387ba2b --- /dev/null +++ b/test/testFp12ArithBN254.zkasm @@ -0,0 +1,692 @@ +; constants needed by executor C++ +CONST %N = 2**19 +CONST %MAX_CNT_STEPS_LIMIT = %N +CONST %MAX_CNT_ARITH_LIMIT = %N +CONST %MAX_CNT_BINARY_LIMIT = %N +CONST %MAX_CNT_MEM_ALIGN_LIMIT = %N +CONST %MAX_CNT_KECCAK_F_LIMIT = %N +CONST %MAX_CNT_PADDING_PG_LIMIT = %N +CONST %MAX_CNT_POSEIDON_G_LIMIT = %N + +INCLUDE "../main/pairings/constants.zkasm" + +VAR GLOBAL test + +VAR GLOBAL lastHashKId +VAR GLOBAL lastHashPId + +VAR GLOBAL initial_A +VAR GLOBAL initial_B +VAR GLOBAL initial_C +VAR GLOBAL initial_D +VAR GLOBAL initial_E +VAR GLOBAL initial_CTX +VAR GLOBAL initial_SP +VAR GLOBAL initial_PC +VAR GLOBAL initial_GAS +VAR GLOBAL initial_SR +VAR GLOBAL initial_RR +VAR GLOBAL initial_HASHPOS +VAR GLOBAL initial_RCX + +start: + + STEP => A + 0 :ASSERT + + + A :MSTORE(initial_A) + B :MSTORE(initial_B) + C :MSTORE(initial_C) + D :MSTORE(initial_D) + E :MSTORE(initial_E) + CTX :MSTORE(initial_CTX) + SP :MSTORE(initial_SP) + PC :MSTORE(initial_PC) + GAS :MSTORE(initial_GAS) + SR :MSTORE(initial_SR) + RR :MSTORE(initial_RR) + HASHPOS :MSTORE(initial_HASHPOS) + RCX :MSTORE(initial_RCX) + 0 => A,B,C,D,E,CTX, SP, PC, GAS, SR, RR, HASHPOS, RCX + + -1 :MSTORE(lastHashKId) + -1 :MSTORE(lastHashPId) + + ; 1] Multiplication + 10n :MSTORE(mulFp12BN254_a11_x) + 2n :MSTORE(mulFp12BN254_a11_y) + 5n :MSTORE(mulFp12BN254_a12_x) + 13n :MSTORE(mulFp12BN254_a12_y) + 7n :MSTORE(mulFp12BN254_a13_x) + 5n :MSTORE(mulFp12BN254_a13_y) + 10n :MSTORE(mulFp12BN254_a21_x) + 2n :MSTORE(mulFp12BN254_a21_y) + 5n :MSTORE(mulFp12BN254_a22_x) + 13n :MSTORE(mulFp12BN254_a22_y) + 7n :MSTORE(mulFp12BN254_a23_x) + 5n :MSTORE(mulFp12BN254_a23_y) + 78n :MSTORE(mulFp12BN254_b11_x) + 5n :MSTORE(mulFp12BN254_b11_y) + 3n :MSTORE(mulFp12BN254_b12_x) + 193n :MSTORE(mulFp12BN254_b12_y) + 20n :MSTORE(mulFp12BN254_b13_x) + 2n :MSTORE(mulFp12BN254_b13_y) + 1n :MSTORE(mulFp12BN254_b21_x) + 0n :MSTORE(mulFp12BN254_b21_y) + 0n :MSTORE(mulFp12BN254_b22_x) + 3n :MSTORE(mulFp12BN254_b22_y) + 69n :MSTORE(mulFp12BN254_b23_x) + 27n :MSTORE(mulFp12BN254_b23_y) + :CALL(mulFp12BN254) + 21888242871839275222246405745257275088696311157297823662689037894645226204895n :MLOAD(mulFp12BN254_c11_x) + 18516n :MLOAD(mulFp12BN254_c11_y) + 21888242871839275222246405745257275088696311157297823662689037894645226208376n :MLOAD(mulFp12BN254_c12_x) + 13589n :MLOAD(mulFp12BN254_c12_y) + 820n :MLOAD(mulFp12BN254_c13_x) + 6686n :MLOAD(mulFp12BN254_c13_y) + 21888242871839275222246405745257275088696311157297823662689037894645226198655n :MLOAD(mulFp12BN254_c21_x) + 23518n :MLOAD(mulFp12BN254_c21_y) + 3622n :MLOAD(mulFp12BN254_c22_x) + 9328n :MLOAD(mulFp12BN254_c22_y) + 21888242871839275222246405745257275088696311157297823662689037894645226207410n :MLOAD(mulFp12BN254_c23_x) + 1917n :MLOAD(mulFp12BN254_c23_y) + + 2n :MSTORE(mulFp12BN254_a11_x) + 4n :MSTORE(mulFp12BN254_a11_y) + 0n :MSTORE(mulFp12BN254_a12_x) + 0n :MSTORE(mulFp12BN254_a12_y) + 0n :MSTORE(mulFp12BN254_a13_x) + 5n :MSTORE(mulFp12BN254_a13_y) + 5n :MSTORE(mulFp12BN254_a21_x) + 10n :MSTORE(mulFp12BN254_a21_y) + 20n :MSTORE(mulFp12BN254_a22_x) + 30n :MSTORE(mulFp12BN254_a22_y) + 7n :MSTORE(mulFp12BN254_a23_x) + 69n :MSTORE(mulFp12BN254_a23_y) + 78n :MSTORE(mulFp12BN254_b11_x) + 14n :MSTORE(mulFp12BN254_b11_y) + 2n :MSTORE(mulFp12BN254_b12_x) + 1n :MSTORE(mulFp12BN254_b12_y) + 2n :MSTORE(mulFp12BN254_b13_x) + 10n :MSTORE(mulFp12BN254_b13_y) + 100n :MSTORE(mulFp12BN254_b21_x) + 99n :MSTORE(mulFp12BN254_b21_y) + 88n :MSTORE(mulFp12BN254_b22_x) + 77n :MSTORE(mulFp12BN254_b22_y) + 20n :MSTORE(mulFp12BN254_b23_x) + 2n :MSTORE(mulFp12BN254_b23_y) + :CALL(mulFp12BN254) + 21888242871839275222246405745257275088696311157297823662689037894645226137236n :MLOAD(mulFp12BN254_c11_x) + 101671n :MLOAD(mulFp12BN254_c11_y) + 21888242871839275222246405745257275088696311157297823662689037894645226161169n :MLOAD(mulFp12BN254_c12_x) + 62447n :MLOAD(mulFp12BN254_c12_y) + 21888242871839275222246405745257275088696311157297823662689037894645226205801n :MLOAD(mulFp12BN254_c13_x) + 19211n :MLOAD(mulFp12BN254_c13_y) + 21888242871839275222246405745257275088696311157297823662689037894645226201492n :MLOAD(mulFp12BN254_c21_x) + 8353n :MLOAD(mulFp12BN254_c21_y) + 21888242871839275222246405745257275088696311157297823662689037894645226203109n :MLOAD(mulFp12BN254_c22_x) + 5237n :MLOAD(mulFp12BN254_c22_y) + 21888242871839275222246405745257275088696311157297823662689037894645226207620n :MLOAD(mulFp12BN254_c23_x) + 6214n :MLOAD(mulFp12BN254_c23_y) + + ; 2] Squaring + 2n :MSTORE(squareFp12BN254_a11_x) + 4n :MSTORE(squareFp12BN254_a11_y) + 0n :MSTORE(squareFp12BN254_a12_x) + 0n :MSTORE(squareFp12BN254_a12_y) + 0n :MSTORE(squareFp12BN254_a13_x) + 5n :MSTORE(squareFp12BN254_a13_y) + 5n :MSTORE(squareFp12BN254_a21_x) + 10n :MSTORE(squareFp12BN254_a21_y) + 20n :MSTORE(squareFp12BN254_a22_x) + 30n :MSTORE(squareFp12BN254_a22_y) + 7n :MSTORE(squareFp12BN254_a23_x) + 69n :MSTORE(squareFp12BN254_a23_y) + :CALL(squareFp12BN254) + 21888242871839275222246405745257275088696311157297823662689037894645226190251n :MLOAD(squareFp12BN254_c11_x) + 16476n :MLOAD(squareFp12BN254_c11_y) + 21888242871839275222246405745257275088696311157297823662689037894645226170363n :MLOAD(squareFp12BN254_c12_x) + 24835n :MLOAD(squareFp12BN254_c12_y) + 21888242871839275222246405745257275088696311157297823662689037894645226164769n :MLOAD(squareFp12BN254_c13_x) + 4702n :MLOAD(squareFp12BN254_c13_y) + 21888242871839275222246405745257275088696311157297823662689037894645226205623n :MLOAD(squareFp12BN254_c21_x) + 1580n :MLOAD(squareFp12BN254_c21_y) + 21888242871839275222246405745257275088696311157297823662689037894645226202143n :MLOAD(squareFp12BN254_c22_x) + 220n :MLOAD(squareFp12BN254_c22_y) + 21888242871839275222246405745257275088696311157297823662689037894645226207959n :MLOAD(squareFp12BN254_c23_x) + 382n :MLOAD(squareFp12BN254_c23_y) + + 12879671296228341798957541889042068293248913689212425431224938470232546313254n :MSTORE(squareFp12BN254_a11_x) + 3326450555199805883965490851796414254830144151329718176108864533289444035270n :MSTORE(squareFp12BN254_a11_y) + 20034916004680903865371475524544157810838259782601065778963371780592670397755n :MSTORE(squareFp12BN254_a12_x) + 18196221800554323016660057972017335112712278872243164622794778048181747904770n :MSTORE(squareFp12BN254_a12_y) + 2650685350723162073065693030364953757603657135232283880472468071129041178893n :MSTORE(squareFp12BN254_a13_x) + 1415534485628002925645978830263295545820817030311522411523977773123510463790n :MSTORE(squareFp12BN254_a13_y) + 11706129207700151979042100288958216850158405562525260961392090752318820540155n :MSTORE(squareFp12BN254_a21_x) + 13581688218243497693010389261307054804658398598414171976249347555990073884710n :MSTORE(squareFp12BN254_a21_y) + 865661210072615391091663782916883487315505694294592934212781713437127182959n :MSTORE(squareFp12BN254_a22_x) + 5364456672142552956341240304849409513108281743490635067211876654163672173225n :MSTORE(squareFp12BN254_a22_y) + 11182696274116283149832659131689911508224992839995672842130064887471806829782n :MSTORE(squareFp12BN254_a23_x) + 13862086431460254638576437312497952755826436162922426416336796129991391475329n :MSTORE(squareFp12BN254_a23_y) + :CALL(squareFp12BN254) + 2098026393950394559493690260865166581266928315924710629633888310320006689795n :MLOAD(squareFp12BN254_c11_x) + 1846888720299666666109042029094532002505741710678796245911331796963733914187n :MLOAD(squareFp12BN254_c11_y) + 6856859212192321831831255712736216614951508355737406292407364405936415355512n :MLOAD(squareFp12BN254_c12_x) + 17209588680055969912485542074372495831925486815137906387799790601911548657525n :MLOAD(squareFp12BN254_c12_y) + 15781046857382959121140505691131389728661226093902862303002526578701400754315n :MLOAD(squareFp12BN254_c13_x) + 8625093555241362381542545391636743832938050376057983419042860774659518282797n :MLOAD(squareFp12BN254_c13_y) + 14351778565182200844681812560787756136192441388960773363087263587389322671562n :MLOAD(squareFp12BN254_c21_x) + 15695337662963643544813486120899631949921737819129690254830667492646284393382n :MLOAD(squareFp12BN254_c21_y) + 5570195873148749154672896518046181211644563497843962677067647498629814883385n :MLOAD(squareFp12BN254_c22_x) + 14991026153829150387150002728101017951749162083560649689008171461754623678203n :MLOAD(squareFp12BN254_c22_y) + 18987338659195924269172748027172054817706283508452795151531146694958273165690n :MLOAD(squareFp12BN254_c23_x) + 8860539994207234999664733841364243523346939192669625740842082601247122017n :MLOAD(squareFp12BN254_c23_y) + + ; 3] Inversion + 0n :MSTORE(inverseFp12BN254_a11_x) + 0n :MSTORE(inverseFp12BN254_a11_y) + 0n :MSTORE(inverseFp12BN254_a12_x) + 0n :MSTORE(inverseFp12BN254_a12_y) + 0n :MSTORE(inverseFp12BN254_a13_x) + 0n :MSTORE(inverseFp12BN254_a13_y) + 0n :MSTORE(inverseFp12BN254_a21_x) + 0n :MSTORE(inverseFp12BN254_a21_y) + 0n :MSTORE(inverseFp12BN254_a22_x) + 0n :MSTORE(inverseFp12BN254_a22_y) + 0n :MSTORE(inverseFp12BN254_a23_x) + 0n :MSTORE(inverseFp12BN254_a23_y) + :CALL(inverseFp12BN254) + 0n :MLOAD(inverseFp12BN254_c11_x) + 0n :MLOAD(inverseFp12BN254_c11_y) + 0n :MLOAD(inverseFp12BN254_c12_x) + 0n :MLOAD(inverseFp12BN254_c12_y) + 0n :MLOAD(inverseFp12BN254_c13_x) + 0n :MLOAD(inverseFp12BN254_c13_y) + 0n :MLOAD(inverseFp12BN254_c21_x) + 0n :MLOAD(inverseFp12BN254_c21_y) + 0n :MLOAD(inverseFp12BN254_c22_x) + 0n :MLOAD(inverseFp12BN254_c22_y) + 0n :MLOAD(inverseFp12BN254_c23_x) + 0n :MLOAD(inverseFp12BN254_c23_y) + + 2n :MSTORE(inverseFp12BN254_a11_x) + 4n :MSTORE(inverseFp12BN254_a11_y) + 0n :MSTORE(inverseFp12BN254_a12_x) + 0n :MSTORE(inverseFp12BN254_a12_y) + 0n :MSTORE(inverseFp12BN254_a13_x) + 5n :MSTORE(inverseFp12BN254_a13_y) + 5n :MSTORE(inverseFp12BN254_a21_x) + 10n :MSTORE(inverseFp12BN254_a21_y) + 20n :MSTORE(inverseFp12BN254_a22_x) + 30n :MSTORE(inverseFp12BN254_a22_y) + 7n :MSTORE(inverseFp12BN254_a23_x) + 69n :MSTORE(inverseFp12BN254_a23_y) + :CALL(inverseFp12BN254) + 20888671201298710215559703514044964345994874487104175886056878644554404140739n :MLOAD(inverseFp12BN254_c11_x) + 18341611945458884647361257454040416792770938911765857382502174274013923134382n :MLOAD(inverseFp12BN254_c11_y) + 17212264596994956074343974726440644554067711720592905218425974958919607539075n :MLOAD(inverseFp12BN254_c12_x) + 6732381207586209376886879348286689555260828461769669735069071849456515851212n :MLOAD(inverseFp12BN254_c12_y) + 21368147715739918891454619601590918042420736987188643135495514508402788769683n :MLOAD(inverseFp12BN254_c13_x) + 3663521624002505260290817291830274755837177609996429331224604043807131463817n :MLOAD(inverseFp12BN254_c13_y) + 3032132887036960235387737000759039646563507175772143153015916596005685046007n :MLOAD(inverseFp12BN254_c21_x) + 13055139790251789501688599598738101973446402124156655452735772999414040890403n :MLOAD(inverseFp12BN254_c21_y) + 6517756700633644793630942808183387771630781381170479363578086592172656898770n :MLOAD(inverseFp12BN254_c22_x) + 395650894991045560122132702409515890328368535989210404180801859598882957185n :MLOAD(inverseFp12BN254_c22_y) + 8570196145412438361611057965650768730501569553533068267820731323855389368346n :MLOAD(inverseFp12BN254_c23_x) + 7491118698937156772874143978394611345783939114329232646099076078308797709778n :MLOAD(inverseFp12BN254_c23_y) + + ; 4] Frobenius 1 + 2n :MSTORE(frobFp12BN254_a11_x) + 4n :MSTORE(frobFp12BN254_a11_y) + 0n :MSTORE(frobFp12BN254_a12_x) + 0n :MSTORE(frobFp12BN254_a12_y) + 0n :MSTORE(frobFp12BN254_a13_x) + 5n :MSTORE(frobFp12BN254_a13_y) + 5n :MSTORE(frobFp12BN254_a21_x) + 10n :MSTORE(frobFp12BN254_a21_y) + 20n :MSTORE(frobFp12BN254_a22_x) + 30n :MSTORE(frobFp12BN254_a22_y) + 7n :MSTORE(frobFp12BN254_a23_x) + 69n :MSTORE(frobFp12BN254_a23_y) + :CALL(frobFp12BN254) + 2n :MLOAD(frobFp12BN254_c11_x) + 21888242871839275222246405745257275088696311157297823662689037894645226208579n :MLOAD(frobFp12BN254_c11_y) + 0n :MLOAD(frobFp12BN254_c12_x) + 0n :MLOAD(frobFp12BN254_c12_y) + 12135813371521139050994037868617609616787958635633452590810720783422678470818n :MLOAD(frobFp12BN254_c13_x) + 8978686149504228545909850167913259590937983131916839958350011601804054476893n :MLOAD(frobFp12BN254_c13_y) + 9584641713043712721593590042581712654775596374742780276939764667903927806313n :MLOAD(frobFp12BN254_c21_x) + 20476170829590101375852353274876318157843683729155685571889366804266103799363n :MLOAD(frobFp12BN254_c21_y) + 8388916578362501695849260316596592932525470900775430933148668612207026983089n :MLOAD(frobFp12BN254_c22_x) + 7358162764234297459542225094137172218712665797959405470620213129713321020023n :MLOAD(frobFp12BN254_c22_y) + 18558562840876269057841639761243305870292532112761084078231157243871160309578n :MLOAD(frobFp12BN254_c23_x) + 11857974535903257516183381046246360366676403947472414230254839754001932999778n :MLOAD(frobFp12BN254_c23_y) + + ; 5] Frobenius 2 + 2n :MSTORE(frob2Fp12BN254_a11_x) + 4n :MSTORE(frob2Fp12BN254_a11_y) + 0n :MSTORE(frob2Fp12BN254_a12_x) + 0n :MSTORE(frob2Fp12BN254_a12_y) + 0n :MSTORE(frob2Fp12BN254_a13_x) + 5n :MSTORE(frob2Fp12BN254_a13_y) + 5n :MSTORE(frob2Fp12BN254_a21_x) + 10n :MSTORE(frob2Fp12BN254_a21_y) + 20n :MSTORE(frob2Fp12BN254_a22_x) + 30n :MSTORE(frob2Fp12BN254_a22_y) + 7n :MSTORE(frob2Fp12BN254_a23_x) + 69n :MSTORE(frob2Fp12BN254_a23_y) + :CALL(frob2Fp12BN254) + 2n :MLOAD(frob2Fp12BN254_c11_x) + 4n :MLOAD(frob2Fp12BN254_c11_y) + 0n :MLOAD(frob2Fp12BN254_c12_x) + 0n :MLOAD(frob2Fp12BN254_c12_y) + 0n :MLOAD(frob2Fp12BN254_c13_x) + 11019802425740609607093018714128810104871396294401028259830n :MLOAD(frob2Fp12BN254_c13_y) + 21888242871839275211226603319516665481603292443169013557817641600244197948753n :MLOAD(frob2Fp12BN254_c21_x) + 21888242871839275200206800893776055874510273729040203452946245305843169688923n :MLOAD(frob2Fp12BN254_c21_y) + 21888242871839275222246405745257275088696311157297823662689037894645226208563n :MLOAD(frob2Fp12BN254_c22_x) + 21888242871839275222246405745257275088696311157297823662689037894645226208553n :MLOAD(frob2Fp12BN254_c22_y) + 15427723396036853449930226199780334146819954812161439563769n :MLOAD(frob2Fp12BN254_c23_x) + 152073273475220412577883658254977579447225268862734189985723n :MLOAD(frob2Fp12BN254_c23_y) + + ; 6] Frobenius 3 + 2n :MSTORE(frob3Fp12BN254_a11_x) + 4n :MSTORE(frob3Fp12BN254_a11_y) + 0n :MSTORE(frob3Fp12BN254_a12_x) + 0n :MSTORE(frob3Fp12BN254_a12_y) + 0n :MSTORE(frob3Fp12BN254_a13_x) + 5n :MSTORE(frob3Fp12BN254_a13_y) + 5n :MSTORE(frob3Fp12BN254_a21_x) + 10n :MSTORE(frob3Fp12BN254_a21_y) + 20n :MSTORE(frob3Fp12BN254_a22_x) + 30n :MSTORE(frob3Fp12BN254_a22_y) + 7n :MSTORE(frob3Fp12BN254_a23_x) + 69n :MSTORE(frob3Fp12BN254_a23_y) + :CALL(frob3Fp12BN254) + 2n :MLOAD(frob3Fp12BN254_c11_x) + 21888242871839275222246405745257275088696311157297823662689037894645226208579n :MLOAD(frob3Fp12BN254_c11_y) + 0n :MLOAD(frob3Fp12BN254_c12_x) + 0n :MLOAD(frob3Fp12BN254_c12_y) + 15379773288170639757858258400900114640879698627390973011522457221008541989446n :MLOAD(frob3Fp12BN254_c13_x) + 17154089731429032730858894512983477767751333502592430926476358946503966738576n :MLOAD(frob3Fp12BN254_c13_y) + 17749105629462879953863937671185175801732786780399070592042899283982922600439n :MLOAD(frob3Fp12BN254_c21_x) + 15874459213129437722334522520084447110335778476790487949919376082271117456313n :MLOAD(frob3Fp12BN254_c21_y) + 13499326293476773526397145428660682156170840256522392729540369282438199225494n :MLOAD(frob3Fp12BN254_c22_x) + 14530080107604977762704180651120102869983645359338418192068824764931905188560n :MLOAD(frob3Fp12BN254_c22_y) + 9835836312269481659124129352040423254366959727421963915440501313066399824733n :MLOAD(frob3Fp12BN254_c23_x) + 2627768430169233579625702931774614886811535516639531274999928953109345755919n :MLOAD(frob3Fp12BN254_c23_y) + + ; 7] Sparse Multiplication A + 2n :MSTORE(sparseMulAFp12BN254_a11_x) + 4n :MSTORE(sparseMulAFp12BN254_a11_y) + 0n :MSTORE(sparseMulAFp12BN254_a12_x) + 0n :MSTORE(sparseMulAFp12BN254_a12_y) + 0n :MSTORE(sparseMulAFp12BN254_a13_x) + 5n :MSTORE(sparseMulAFp12BN254_a13_y) + 5n :MSTORE(sparseMulAFp12BN254_a21_x) + 10n :MSTORE(sparseMulAFp12BN254_a21_y) + 20n :MSTORE(sparseMulAFp12BN254_a22_x) + 30n :MSTORE(sparseMulAFp12BN254_a22_y) + 7n :MSTORE(sparseMulAFp12BN254_a23_x) + 69n :MSTORE(sparseMulAFp12BN254_a23_y) + 7n :MSTORE(sparseMulAFp12BN254_b12_x) + 6n :MSTORE(sparseMulAFp12BN254_b12_y) + 7n :MSTORE(sparseMulAFp12BN254_b22_x) + 83n :MSTORE(sparseMulAFp12BN254_b22_y) + 2n :MSTORE(sparseMulAFp12BN254_b23_x) + 29n :MSTORE(sparseMulAFp12BN254_b23_y) + :CALL(sparseMulAFp12BN254) + 21888242871839275222246405745257275088696311157297823662689037894645226182573n :MLOAD(sparseMulAFp12BN254_c11_x) + 15970n :MLOAD(sparseMulAFp12BN254_c11_y) + 21888242871839275222246405745257275088696311157297823662689037894645226148297n :MLOAD(sparseMulAFp12BN254_c12_x) + 8868n :MLOAD(sparseMulAFp12BN254_c12_y) + 21888242871839275222246405745257275088696311157297823662689037894645226189564n :MLOAD(sparseMulAFp12BN254_c13_x) + 1567n :MLOAD(sparseMulAFp12BN254_c13_y) + 21888242871839275222246405745257275088696311157297823662689037894645226201003n :MLOAD(sparseMulAFp12BN254_c21_x) + 4260n :MLOAD(sparseMulAFp12BN254_c21_y) + 21888242871839275222246405745257275088696311157297823662689037894645226206925n :MLOAD(sparseMulAFp12BN254_c22_x) + 239n :MLOAD(sparseMulAFp12BN254_c22_y) + 21888242871839275222246405745257275088696311157297823662689037894645226208431n :MLOAD(sparseMulAFp12BN254_c23_x) + 396n :MLOAD(sparseMulAFp12BN254_c23_y) + + ; 8] Sparse Multiplication B + 2n :MSTORE(sparseMulBFp12BN254_a11_x) + 4n :MSTORE(sparseMulBFp12BN254_a11_y) + 0n :MSTORE(sparseMulBFp12BN254_a12_x) + 0n :MSTORE(sparseMulBFp12BN254_a12_y) + 0n :MSTORE(sparseMulBFp12BN254_a13_x) + 5n :MSTORE(sparseMulBFp12BN254_a13_y) + 5n :MSTORE(sparseMulBFp12BN254_a21_x) + 10n :MSTORE(sparseMulBFp12BN254_a21_y) + 20n :MSTORE(sparseMulBFp12BN254_a22_x) + 30n :MSTORE(sparseMulBFp12BN254_a22_y) + 7n :MSTORE(sparseMulBFp12BN254_a23_x) + 69n :MSTORE(sparseMulBFp12BN254_a23_y) + 7n :MSTORE(sparseMulBFp12BN254_b11_x) + 6n :MSTORE(sparseMulBFp12BN254_b11_y) + 7n :MSTORE(sparseMulBFp12BN254_b13_x) + 83n :MSTORE(sparseMulBFp12BN254_b13_y) + 2n :MSTORE(sparseMulBFp12BN254_b22_x) + 29n :MSTORE(sparseMulBFp12BN254_b22_y) + :CALL(sparseMulBFp12BN254) + 21888242871839275222246405745257275088696311157297823662689037894645226200463n :MLOAD(sparseMulBFp12BN254_c11_x) + 4970n :MLOAD(sparseMulBFp12BN254_c11_y) + 21888242871839275222246405745257275088696311157297823662689037894645226186589n :MLOAD(sparseMulBFp12BN254_c12_x) + 982n :MLOAD(sparseMulBFp12BN254_c12_y) + 21888242871839275222246405745257275088696311157297823662689037894645226207955n :MLOAD(sparseMulBFp12BN254_c13_x) + 394n :MLOAD(sparseMulBFp12BN254_c13_y) + 21888242871839275222246405745257275088696311157297823662689037894645226184223n :MLOAD(sparseMulBFp12BN254_c21_x) + 14525n :MLOAD(sparseMulBFp12BN254_c21_y) + 21888242871839275222246405745257275088696311157297823662689037894645226156265n :MLOAD(sparseMulBFp12BN254_c22_x) + 4294n :MLOAD(sparseMulBFp12BN254_c22_y) + 21888242871839275222246405745257275088696311157297823662689037894645226207423n :MLOAD(sparseMulBFp12BN254_c23_x) + 1010n :MLOAD(sparseMulBFp12BN254_c23_y) + + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + ;; UNUSED + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + + ; 1] Addition + 10n :MSTORE(addFp12BN254_a11_x) + 2n :MSTORE(addFp12BN254_a11_y) + 5n :MSTORE(addFp12BN254_a12_x) + 13n :MSTORE(addFp12BN254_a12_y) + 7n :MSTORE(addFp12BN254_a13_x) + 5n :MSTORE(addFp12BN254_a13_y) + 10n :MSTORE(addFp12BN254_a21_x) + 2n :MSTORE(addFp12BN254_a21_y) + 5n :MSTORE(addFp12BN254_a22_x) + 13n :MSTORE(addFp12BN254_a22_y) + 7n :MSTORE(addFp12BN254_a23_x) + 5n :MSTORE(addFp12BN254_a23_y) + 78n :MSTORE(addFp12BN254_b11_x) + 5n :MSTORE(addFp12BN254_b11_y) + 3n :MSTORE(addFp12BN254_b12_x) + 193n :MSTORE(addFp12BN254_b12_y) + 20n :MSTORE(addFp12BN254_b13_x) + 2n :MSTORE(addFp12BN254_b13_y) + 1n :MSTORE(addFp12BN254_b21_x) + 0n :MSTORE(addFp12BN254_b21_y) + 0n :MSTORE(addFp12BN254_b22_x) + 3n :MSTORE(addFp12BN254_b22_y) + 69n :MSTORE(addFp12BN254_b23_x) + 27n :MSTORE(addFp12BN254_b23_y) + :CALL(addFp12BN254) + 88n :MLOAD(addFp12BN254_c11_x) + 7n :MLOAD(addFp12BN254_c11_y) + 8n :MLOAD(addFp12BN254_c12_x) + 206n :MLOAD(addFp12BN254_c12_y) + 27n :MLOAD(addFp12BN254_c13_x) + 7n :MLOAD(addFp12BN254_c13_y) + 11n :MLOAD(addFp12BN254_c21_x) + 2n :MLOAD(addFp12BN254_c21_y) + 5n :MLOAD(addFp12BN254_c22_x) + 16n :MLOAD(addFp12BN254_c22_y) + 76n :MLOAD(addFp12BN254_c23_x) + 32n :MLOAD(addFp12BN254_c23_y) + + ; 2] Subtraction + 10n :MSTORE(subFp12BN254_a11_x) + 2n :MSTORE(subFp12BN254_a11_y) + 5n :MSTORE(subFp12BN254_a12_x) + 13n :MSTORE(subFp12BN254_a12_y) + 7n :MSTORE(subFp12BN254_a13_x) + 5n :MSTORE(subFp12BN254_a13_y) + 10n :MSTORE(subFp12BN254_a21_x) + 2n :MSTORE(subFp12BN254_a21_y) + 5n :MSTORE(subFp12BN254_a22_x) + 13n :MSTORE(subFp12BN254_a22_y) + 7n :MSTORE(subFp12BN254_a23_x) + 5n :MSTORE(subFp12BN254_a23_y) + 78n :MSTORE(subFp12BN254_b11_x) + 5n :MSTORE(subFp12BN254_b11_y) + 3n :MSTORE(subFp12BN254_b12_x) + 193n :MSTORE(subFp12BN254_b12_y) + 20n :MSTORE(subFp12BN254_b13_x) + 2n :MSTORE(subFp12BN254_b13_y) + 1n :MSTORE(subFp12BN254_b21_x) + 0n :MSTORE(subFp12BN254_b21_y) + 0n :MSTORE(subFp12BN254_b22_x) + 3n :MSTORE(subFp12BN254_b22_y) + 69n :MSTORE(subFp12BN254_b23_x) + 27n :MSTORE(subFp12BN254_b23_y) + :CALL(subFp12BN254) + 21888242871839275222246405745257275088696311157297823662689037894645226208515n :MLOAD(subFp12BN254_c11_x) + 21888242871839275222246405745257275088696311157297823662689037894645226208580n :MLOAD(subFp12BN254_c11_y) + 2n :MLOAD(subFp12BN254_c12_x) + 21888242871839275222246405745257275088696311157297823662689037894645226208403n :MLOAD(subFp12BN254_c12_y) + 21888242871839275222246405745257275088696311157297823662689037894645226208570n :MLOAD(subFp12BN254_c13_x) + 3n :MLOAD(subFp12BN254_c13_y) + 9n :MLOAD(subFp12BN254_c21_x) + 2n :MLOAD(subFp12BN254_c21_y) + 5n :MLOAD(subFp12BN254_c22_x) + 10n :MLOAD(subFp12BN254_c22_y) + 21888242871839275222246405745257275088696311157297823662689037894645226208521n :MLOAD(subFp12BN254_c23_x) + 21888242871839275222246405745257275088696311157297823662689037894645226208561n :MLOAD(subFp12BN254_c23_y) + + ; 3] Exponentiation + ; 1) 0^0 = 0 + 0n :MSTORE(expFp12BN254_e) + 0n :MSTORE(expFp12BN254_a11_x) + 0n :MSTORE(expFp12BN254_a11_y) + 0n :MSTORE(expFp12BN254_a12_x) + 0n :MSTORE(expFp12BN254_a12_y) + 0n :MSTORE(expFp12BN254_a13_x) + 0n :MSTORE(expFp12BN254_a13_y) + 0n :MSTORE(expFp12BN254_a21_x) + 0n :MSTORE(expFp12BN254_a21_y) + 0n :MSTORE(expFp12BN254_a22_x) + 0n :MSTORE(expFp12BN254_a22_y) + 0n :MSTORE(expFp12BN254_a23_x) + 0n :MSTORE(expFp12BN254_a23_y) + :CALL(expFp12BN254) + 0n :MLOAD(expFp12BN254_c11_x) + 0n :MLOAD(expFp12BN254_c11_y) + 0n :MLOAD(expFp12BN254_c12_x) + 0n :MLOAD(expFp12BN254_c12_y) + 0n :MLOAD(expFp12BN254_c13_x) + 0n :MLOAD(expFp12BN254_c13_y) + 0n :MLOAD(expFp12BN254_c21_x) + 0n :MLOAD(expFp12BN254_c21_y) + 0n :MLOAD(expFp12BN254_c22_x) + 0n :MLOAD(expFp12BN254_c22_y) + 0n :MLOAD(expFp12BN254_c23_x) + 0n :MLOAD(expFp12BN254_c23_y) + + ; 2) 0^e = 0 with e != 0 + 10n :MSTORE(expFp12BN254_e) + 0n :MSTORE(expFp12BN254_a11_x) + 0n :MSTORE(expFp12BN254_a11_y) + 0n :MSTORE(expFp12BN254_a12_x) + 0n :MSTORE(expFp12BN254_a12_y) + 0n :MSTORE(expFp12BN254_a13_x) + 0n :MSTORE(expFp12BN254_a13_y) + 0n :MSTORE(expFp12BN254_a21_x) + 0n :MSTORE(expFp12BN254_a21_y) + 0n :MSTORE(expFp12BN254_a22_x) + 0n :MSTORE(expFp12BN254_a22_y) + 0n :MSTORE(expFp12BN254_a23_x) + 0n :MSTORE(expFp12BN254_a23_y) + :CALL(expFp12BN254) + 0n :MLOAD(expFp12BN254_c11_x) + 0n :MLOAD(expFp12BN254_c11_y) + 0n :MLOAD(expFp12BN254_c12_x) + 0n :MLOAD(expFp12BN254_c12_y) + 0n :MLOAD(expFp12BN254_c13_x) + 0n :MLOAD(expFp12BN254_c13_y) + 0n :MLOAD(expFp12BN254_c21_x) + 0n :MLOAD(expFp12BN254_c21_y) + 0n :MLOAD(expFp12BN254_c22_x) + 0n :MLOAD(expFp12BN254_c22_y) + 0n :MLOAD(expFp12BN254_c23_x) + 0n :MLOAD(expFp12BN254_c23_y) + + ; 3.1) 1^0 = 1 + 0n :MSTORE(expFp12BN254_e) + 1n :MSTORE(expFp12BN254_a11_x) + 0n :MSTORE(expFp12BN254_a11_y) + 0n :MSTORE(expFp12BN254_a12_x) + 0n :MSTORE(expFp12BN254_a12_y) + 0n :MSTORE(expFp12BN254_a13_x) + 0n :MSTORE(expFp12BN254_a13_y) + 0n :MSTORE(expFp12BN254_a21_x) + 0n :MSTORE(expFp12BN254_a21_y) + 0n :MSTORE(expFp12BN254_a22_x) + 0n :MSTORE(expFp12BN254_a22_y) + 0n :MSTORE(expFp12BN254_a23_x) + 0n :MSTORE(expFp12BN254_a23_y) + :CALL(expFp12BN254) + 1n :MLOAD(expFp12BN254_c11_x) + 0n :MLOAD(expFp12BN254_c11_y) + 0n :MLOAD(expFp12BN254_c12_x) + 0n :MLOAD(expFp12BN254_c12_y) + 0n :MLOAD(expFp12BN254_c13_x) + 0n :MLOAD(expFp12BN254_c13_y) + 0n :MLOAD(expFp12BN254_c21_x) + 0n :MLOAD(expFp12BN254_c21_y) + 0n :MLOAD(expFp12BN254_c22_x) + 0n :MLOAD(expFp12BN254_c22_y) + 0n :MLOAD(expFp12BN254_c23_x) + 0n :MLOAD(expFp12BN254_c23_y) + + ; 3.2) a^0 = 1 with a > 1 + 0n :MSTORE(expFp12BN254_e) + 2n :MSTORE(expFp12BN254_a11_x) + 0n :MSTORE(expFp12BN254_a11_y) + 0n :MSTORE(expFp12BN254_a12_x) + 0n :MSTORE(expFp12BN254_a12_y) + 0n :MSTORE(expFp12BN254_a13_x) + 0n :MSTORE(expFp12BN254_a13_y) + 0n :MSTORE(expFp12BN254_a21_x) + 0n :MSTORE(expFp12BN254_a21_y) + 0n :MSTORE(expFp12BN254_a22_x) + 0n :MSTORE(expFp12BN254_a22_y) + 0n :MSTORE(expFp12BN254_a23_x) + 0n :MSTORE(expFp12BN254_a23_y) + :CALL(expFp12BN254) + 1n :MLOAD(expFp12BN254_c11_x) + 0n :MLOAD(expFp12BN254_c11_y) + 0n :MLOAD(expFp12BN254_c12_x) + 0n :MLOAD(expFp12BN254_c12_y) + 0n :MLOAD(expFp12BN254_c13_x) + 0n :MLOAD(expFp12BN254_c13_y) + 0n :MLOAD(expFp12BN254_c21_x) + 0n :MLOAD(expFp12BN254_c21_y) + 0n :MLOAD(expFp12BN254_c22_x) + 0n :MLOAD(expFp12BN254_c22_y) + 0n :MLOAD(expFp12BN254_c23_x) + 0n :MLOAD(expFp12BN254_c23_y) + + ; 4) Small example + 167n :MSTORE(expFp12BN254_e) + 2n :MSTORE(expFp12BN254_a11_x) + 4n :MSTORE(expFp12BN254_a11_y) + 0n :MSTORE(expFp12BN254_a12_x) + 0n :MSTORE(expFp12BN254_a12_y) + 0n :MSTORE(expFp12BN254_a13_x) + 5n :MSTORE(expFp12BN254_a13_y) + 5n :MSTORE(expFp12BN254_a21_x) + 10n :MSTORE(expFp12BN254_a21_y) + 20n :MSTORE(expFp12BN254_a22_x) + 30n :MSTORE(expFp12BN254_a22_y) + 7n :MSTORE(expFp12BN254_a23_x) + 69n :MSTORE(expFp12BN254_a23_y) + :CALL(expFp12BN254) + 20586466107674193719139483068538172518814581654122963093910816135984072539339n :MLOAD(expFp12BN254_c11_x) + 5953152173779773418366712639682598574554542297764337418575574775937014969989n :MLOAD(expFp12BN254_c11_y) + 3661221552326322626584296132914038982026189413490444409336642019079026110580n :MLOAD(expFp12BN254_c12_x) + 20307132177350548649365896131720817832905154290927819017533246898384788331797n :MLOAD(expFp12BN254_c12_y) + 6554555865226798697690787889597704881283210849129154679946065129492384662441n :MLOAD(expFp12BN254_c13_x) + 3734827310994017806686109338552434684262950155862064206859738515342034657482n :MLOAD(expFp12BN254_c13_y) + 12833166236118024621207291725677388530384380602869578473315220328428476013127n :MLOAD(expFp12BN254_c21_x) + 4283613850875227600923719261463876211784033209984079537562941239663105744102n :MLOAD(expFp12BN254_c21_y) + 1362526929780209469431909191206089688453294120749489634524494745650488027728n :MLOAD(expFp12BN254_c22_x) + 9956431918991355996517300910757034285810490343731619009685769604165956972299n :MLOAD(expFp12BN254_c22_y) + 4130369998871020954078407548456754295747138847271917082666014536095464174364n :MLOAD(expFp12BN254_c23_x) + 1685641307692274787278258791922218462843126978449545532205987451962723928051n :MLOAD(expFp12BN254_c23_y) + + ; 5) Big example + 123456789n :MSTORE(expFp12BN254_e) + 12879671296228341798957541889042068293248913689212425431224938470232546313254n :MSTORE(expFp12BN254_a11_x) + 3326450555199805883965490851796414254830144151329718176108864533289444035270n :MSTORE(expFp12BN254_a11_y) + 20034916004680903865371475524544157810838259782601065778963371780592670397755n :MSTORE(expFp12BN254_a12_x) + 18196221800554323016660057972017335112712278872243164622794778048181747904770n :MSTORE(expFp12BN254_a12_y) + 2650685350723162073065693030364953757603657135232283880472468071129041178893n :MSTORE(expFp12BN254_a13_x) + 1415534485628002925645978830263295545820817030311522411523977773123510463790n :MSTORE(expFp12BN254_a13_y) + 11706129207700151979042100288958216850158405562525260961392090752318820540155n :MSTORE(expFp12BN254_a21_x) + 13581688218243497693010389261307054804658398598414171976249347555990073884710n :MSTORE(expFp12BN254_a21_y) + 865661210072615391091663782916883487315505694294592934212781713437127182959n :MSTORE(expFp12BN254_a22_x) + 5364456672142552956341240304849409513108281743490635067211876654163672173225n :MSTORE(expFp12BN254_a22_y) + 11182696274116283149832659131689911508224992839995672842130064887471806829782n :MSTORE(expFp12BN254_a23_x) + 13862086431460254638576437312497952755826436162922426416336796129991391475329n :MSTORE(expFp12BN254_a23_y) + :CALL(expFp12BN254) + 9142802627783465593784550980810782727704583580322919181640530262912683835706n :MLOAD(expFp12BN254_c11_x) + 19736874964269248324216922850918903092400740214902232906683421321363422544357n :MLOAD(expFp12BN254_c11_y) + 9476200663504583903004483007751205251215508180544679553549510605575011163386n :MLOAD(expFp12BN254_c12_x) + 14186756296199578735747739817754651119620054607441288968678361496476074454054n :MLOAD(expFp12BN254_c12_y) + 10811240079738065614702763572796448667972493770153862713781508146531351529275n :MLOAD(expFp12BN254_c13_x) + 6916893165906060112199703736125165648798333038384173213301776553630314914213n :MLOAD(expFp12BN254_c13_y) + 11668055882291754411787223452140593554367736493306160926568664665506066150091n :MLOAD(expFp12BN254_c21_x) + 16585699975551858978680527368328456609554018944982648222232641881312088417111n :MLOAD(expFp12BN254_c21_y) + 9954544605243092097823114175115201680862638136567273250934647601724164887142n :MLOAD(expFp12BN254_c22_x) + 18147343955385037719970517295541563914369052645949029345280746768598576659961n :MLOAD(expFp12BN254_c22_y) + 2894810207171007395751896130534905544170418813733418015224386592699923578372n :MLOAD(expFp12BN254_c23_x) + 18124993142426825678658622810384924838784371007656354124172463271771994460493n :MLOAD(expFp12BN254_c23_y) + + + $ => A :MLOAD(initial_A) + $ => B :MLOAD(initial_B) + $ => C :MLOAD(initial_C) + $ => D :MLOAD(initial_D) + $ => E :MLOAD(initial_E) + $ => CTX :MLOAD(initial_CTX) + $ => SP :MLOAD(initial_SP) + $ => PC :MLOAD(initial_PC) + $ => GAS :MLOAD(initial_GAS) + $ => SR :MLOAD(initial_SR) + $ => RR :MLOAD(initial_RR) + $ => HASHPOS :MLOAD(initial_HASHPOS) + $ => RCX :MLOAD(initial_RCX) + +; label finalizeExecution needed by executor C++ +finalizeExecution: + ${beforeLast()} : JMPN(finalizeExecution) + + : JMP(start) +opINVALID: +; label checkAndSaveFrom needed by executor C++ +checkAndSaveFrom: + :JMP(opINVALID) + +INCLUDE "../main/pairings/FPBN254/reduceFpBN254.zkasm" + +INCLUDE "../main/pairings/FP2BN254/addFp2BN254.zkasm" +INCLUDE "../main/pairings/FP2BN254/subFp2BN254.zkasm" +INCLUDE "../main/pairings/FP2BN254/mulFp2BN254.zkasm" +INCLUDE "../main/pairings/FP2BN254/squareFp2BN254.zkasm" +INCLUDE "../main/pairings/FP2BN254/invFp2BN254.zkasm" +INCLUDE "../main/pairings/FP2BN254/escalarMulFp2BN254.zkasm" + +INCLUDE "../main/pairings/FP6BN254/addFp6BN254.zkasm" +INCLUDE "../main/pairings/FP6BN254/subFp6BN254.zkasm" +INCLUDE "../main/pairings/FP6BN254/mulFp6BN254.zkasm" +INCLUDE "../main/pairings/FP6BN254/escalarMulFp6BN254.zkasm" +INCLUDE "../main/pairings/FP6BN254/sparseMulAFp6BN254.zkasm" +INCLUDE "../main/pairings/FP6BN254/sparseMulBFp6BN254.zkasm" +INCLUDE "../main/pairings/FP6BN254/sparseMulCFp6BN254.zkasm" +INCLUDE "../main/pairings/FP6BN254/squareFp6BN254.zkasm" +INCLUDE "../main/pairings/FP6BN254/inverseFp6BN254.zkasm" + +INCLUDE "../main/pairings/FP12BN254/mulFp12BN254.zkasm" +INCLUDE "../main/pairings/FP12BN254/sparseMulAFp12BN254.zkasm" +INCLUDE "../main/pairings/FP12BN254/sparseMulBFp12BN254.zkasm" +INCLUDE "../main/pairings/FP12BN254/squareFp12BN254.zkasm" +INCLUDE "../main/pairings/FP12BN254/inverseFp12BN254.zkasm" +INCLUDE "../main/pairings/FP12BN254/frobFp12BN254.zkasm" +INCLUDE "../main/pairings/FP12BN254/frob2Fp12BN254.zkasm" +INCLUDE "../main/pairings/FP12BN254/frob3Fp12BN254.zkasm" + +INCLUDE "../main/pairings/unused/addFp12BN254.zkasm" +INCLUDE "../main/pairings/unused/subFp12BN254.zkasm" +INCLUDE "../main/pairings/unused/expFp12BN254.zkasm" diff --git a/test/testFp2ArithBN254.zkasm b/test/testFp2ArithBN254.zkasm new file mode 100644 index 00000000..0c51cd3d --- /dev/null +++ b/test/testFp2ArithBN254.zkasm @@ -0,0 +1,185 @@ +; constants needed by executor C++ +CONST %N = 2**19 +CONST %MAX_CNT_STEPS_LIMIT = %N +CONST %MAX_CNT_ARITH_LIMIT = %N +CONST %MAX_CNT_BINARY_LIMIT = %N +CONST %MAX_CNT_MEM_ALIGN_LIMIT = %N +CONST %MAX_CNT_KECCAK_F_LIMIT = %N +CONST %MAX_CNT_PADDING_PG_LIMIT = %N +CONST %MAX_CNT_POSEIDON_G_LIMIT = %N + +CONSTL %BN254_P = 21888242871839275222246405745257275088696311157297823662689037894645226208583n + +VAR GLOBAL lastHashKId +VAR GLOBAL lastHashPId + +VAR GLOBAL initial_A +VAR GLOBAL initial_B +VAR GLOBAL initial_C +VAR GLOBAL initial_D +VAR GLOBAL initial_E +VAR GLOBAL initial_CTX +VAR GLOBAL initial_SP +VAR GLOBAL initial_PC +VAR GLOBAL initial_GAS +VAR GLOBAL initial_SR +VAR GLOBAL initial_RR +VAR GLOBAL initial_HASHPOS +VAR GLOBAL initial_RCX + +start: + + STEP => A + 0 :ASSERT + + + A :MSTORE(initial_A) + B :MSTORE(initial_B) + C :MSTORE(initial_C) + D :MSTORE(initial_D) + E :MSTORE(initial_E) + CTX :MSTORE(initial_CTX) + SP :MSTORE(initial_SP) + PC :MSTORE(initial_PC) + GAS :MSTORE(initial_GAS) + SR :MSTORE(initial_SR) + RR :MSTORE(initial_RR) + HASHPOS :MSTORE(initial_HASHPOS) + RCX :MSTORE(initial_RCX) + 0 => A,B,C,D,E,CTX, SP, PC, GAS, SR, RR, HASHPOS, RCX + + -1 :MSTORE(lastHashKId) + -1 :MSTORE(lastHashPId) + + ; 1] Addition + 1n => A + 2n => B + 3n => C + 4n => D + :CALL(addFp2BN254) + E => A + 4n :ASSERT + C => A + 6n :ASSERT + + ; 2] Subtraction + 1n => A + 4n => B + 3n => C + 2n => D + :CALL(subFp2BN254) + E => A + 21888242871839275222246405745257275088696311157297823662689037894645226208581n :ASSERT + C => A + 2n :ASSERT + + ; 3] Inversion + 0n => A + 0n => B + :CALL(invFp2BN254) + C => A + 0 :ASSERT + D => A + 0 :ASSERT + + 2n => A + 0n => B + :CALL(invFp2BN254) + C => A + 10944121435919637611123202872628637544348155578648911831344518947322613104292n :ASSERT + D => A + 0 :ASSERT + + 0n => A + 2n => B + :CALL(invFp2BN254) + C => A + 0 :ASSERT + D => A + 10944121435919637611123202872628637544348155578648911831344518947322613104291n :ASSERT + + 1n => A + 2n => B + :CALL(invFp2BN254) + C => A + 13132945723103565133347843447154365053217786694378694197613422736787135725150n :ASSERT + D => A + 17510594297471420177797124596205820070957048925838258930151230315716180966866n :ASSERT + + 1n => A + 4n => B + :CALL(invFp2BN254) + C => A + 5150174793373947111116801351825241197340308507599487920632714798740053225549n :ASSERT + D => A + 1287543698343486777779200337956310299335077126899871980158178699685013306387n :ASSERT + + %BN254_P => A + 0n => B + :CALL(invFp2BN254) + C => A + 0 :ASSERT + D => A + 0 :ASSERT + + 0n => A + %BN254_P => B + :CALL(invFp2BN254) + C => A + 0 :ASSERT + D => A + 0 :ASSERT + + ; 4] Squaring + 1n => A + 4n => B + :CALL(squareFp2BN254) + E => A + 21888242871839275222246405745257275088696311157297823662689037894645226208568n :ASSERT + C => A + 8n :ASSERT + + ; 5] Escalar Multiplication + 3n => A + 6n => C + 4n => D + :CALL(escalarMulFp2BN254) + E => A + 18n :ASSERT + C => A + 12n :ASSERT + + +end: + + $ => A :MLOAD(initial_A) + $ => B :MLOAD(initial_B) + $ => C :MLOAD(initial_C) + $ => D :MLOAD(initial_D) + $ => E :MLOAD(initial_E) + $ => CTX :MLOAD(initial_CTX) + $ => SP :MLOAD(initial_SP) + $ => PC :MLOAD(initial_PC) + $ => GAS :MLOAD(initial_GAS) + $ => SR :MLOAD(initial_SR) + $ => RR :MLOAD(initial_RR) + $ => HASHPOS :MLOAD(initial_HASHPOS) + $ => RCX :MLOAD(initial_RCX) + +; label finalizeExecution needed by executor C++ +finalizeExecution: + ${beforeLast()} : JMPN(finalizeExecution) + + : JMP(start) +opINVALID: +; label checkAndSaveFrom needed by executor C++ +checkAndSaveFrom: + :JMP(opINVALID) + +INCLUDE "../main/pairings/FPBN254/reduceFpBN254.zkasm" + +INCLUDE "../main/pairings/FP2BN254/addFp2BN254.zkasm" +INCLUDE "../main/pairings/FP2BN254/subFp2BN254.zkasm" +INCLUDE "../main/pairings/FP2BN254/invFp2BN254.zkasm" +INCLUDE "../main/pairings/FP2BN254/squareFp2BN254.zkasm" +INCLUDE "../main/pairings/FP2BN254/escalarMulFp2BN254.zkasm" \ No newline at end of file diff --git a/test/testFp4ArithBN254.zkasm b/test/testFp4ArithBN254.zkasm new file mode 100644 index 00000000..eb7eb356 --- /dev/null +++ b/test/testFp4ArithBN254.zkasm @@ -0,0 +1,128 @@ +; constants needed by executor C++ +CONST %N = 2**19 +CONST %MAX_CNT_STEPS_LIMIT = %N +CONST %MAX_CNT_ARITH_LIMIT = %N +CONST %MAX_CNT_BINARY_LIMIT = %N +CONST %MAX_CNT_MEM_ALIGN_LIMIT = %N +CONST %MAX_CNT_KECCAK_F_LIMIT = %N +CONST %MAX_CNT_PADDING_PG_LIMIT = %N +CONST %MAX_CNT_POSEIDON_G_LIMIT = %N + +CONSTL %BN254_P = 21888242871839275222246405745257275088696311157297823662689037894645226208583n + +VAR GLOBAL test + +VAR GLOBAL lastHashKId +VAR GLOBAL lastHashPId + +VAR GLOBAL initial_A +VAR GLOBAL initial_B +VAR GLOBAL initial_C +VAR GLOBAL initial_D +VAR GLOBAL initial_E +VAR GLOBAL initial_CTX +VAR GLOBAL initial_SP +VAR GLOBAL initial_PC +VAR GLOBAL initial_GAS +VAR GLOBAL initial_SR +VAR GLOBAL initial_RR +VAR GLOBAL initial_HASHPOS +VAR GLOBAL initial_RCX + +start: + + STEP => A + 0 :ASSERT + + + A :MSTORE(initial_A) + B :MSTORE(initial_B) + C :MSTORE(initial_C) + D :MSTORE(initial_D) + E :MSTORE(initial_E) + CTX :MSTORE(initial_CTX) + SP :MSTORE(initial_SP) + PC :MSTORE(initial_PC) + GAS :MSTORE(initial_GAS) + SR :MSTORE(initial_SR) + RR :MSTORE(initial_RR) + HASHPOS :MSTORE(initial_HASHPOS) + RCX :MSTORE(initial_RCX) + 0 => A,B,C,D,E,CTX, SP, PC, GAS, SR, RR, HASHPOS, RCX + + -1 :MSTORE(lastHashKId) + -1 :MSTORE(lastHashPId) + + ; 1] Squaring + 10n :MSTORE(squareFp4BN254_a1_x) + 2n :MSTORE(squareFp4BN254_a1_y) + 5n :MSTORE(squareFp4BN254_a2_x) + 13n :MSTORE(squareFp4BN254_a2_y) + :CALL(squareFp4BN254) + 21888242871839275222246405745257275088696311157297823662689037894645226207253n :MLOAD(squareFp4BN254_c1_x) + 1066n :MLOAD(squareFp4BN254_c1_y) + 48n :MLOAD(squareFp4BN254_c2_x) + 280n :MLOAD(squareFp4BN254_c2_y) + + 11706129207700151979042100288958216850158405562525260961392090752318820540155n :MSTORE(squareFp4BN254_a1_x) + 13581688218243497693010389261307054804658398598414171976249347555990073884710n :MSTORE(squareFp4BN254_a1_y) + 2650685350723162073065693030364953757603657135232283880472468071129041178893n :MSTORE(squareFp4BN254_a2_x) + 1415534485628002925645978830263295545820817030311522411523977773123510463790n :MSTORE(squareFp4BN254_a2_y) + :CALL(squareFp4BN254) + 15642230407184709854191402253941510745542675973646512616778035989040585383674n :MLOAD(squareFp4BN254_c1_x) + 10571263136441780241186417424383296989551244467442137323566769601209939419494n :MLOAD(squareFp4BN254_c1_y) + 6170062994267544397251278503016502296650869661919757709986684938219961904903n :MLOAD(squareFp4BN254_c2_x) + 12649805430863841208195335781539094665986469361747095927044787835518047599036n :MLOAD(squareFp4BN254_c2_y) + + 12879671296228341798957541889042068293248913689212425431224938470232546313254n :MSTORE(squareFp4BN254_a1_x) + 3326450555199805883965490851796414254830144151329718176108864533289444035270n :MSTORE(squareFp4BN254_a1_y) + 865661210072615391091663782916883487315505694294592934212781713437127182959n :MSTORE(squareFp4BN254_a2_x) + 5364456672142552956341240304849409513108281743490635067211876654163672173225n :MSTORE(squareFp4BN254_a2_y) + :CALL(squareFp4BN254) + 16581870619415451126551726594735526085487022283882461718257601048476775174962n :MLOAD(squareFp4BN254_c1_x) + 17425425191459276292844278407733970229852884109311293307835712217611024800631n :MLOAD(squareFp4BN254_c1_y) + 8575705441614264531578658232489896441903287755517533490443707322133595575350n :MLOAD(squareFp4BN254_c2_x) + 1420704269848014824822507372800732975177532865526459851528139384475759777251n :MLOAD(squareFp4BN254_c2_y) + + 20034916004680903865371475524544157810838259782601065778963371780592670397755n :MSTORE(squareFp4BN254_a1_x) + 18196221800554323016660057972017335112712278872243164622794778048181747904770n :MSTORE(squareFp4BN254_a1_y) + 11182696274116283149832659131689911508224992839995672842130064887471806829782n :MSTORE(squareFp4BN254_a2_x) + 13862086431460254638576437312497952755826436162922426416336796129991391475329n :MSTORE(squareFp4BN254_a2_y) + :CALL(squareFp4BN254) + 21619634434169277903921567747458615807087054226321025796441846170083311843089n :MLOAD(squareFp4BN254_c1_x) + 11114801799445547818360302932473536671091998531326283968259951405183921806320n :MLOAD(squareFp4BN254_c1_y) + 13146343736154811194795223124891192023354979304499035796722737687445144937601n :MLOAD(squareFp4BN254_c2_x) + 4599958258989867272310306821691486925189277480266178822728743054647870795549n :MLOAD(squareFp4BN254_c2_y) + +end: + + $ => A :MLOAD(initial_A) + $ => B :MLOAD(initial_B) + $ => C :MLOAD(initial_C) + $ => D :MLOAD(initial_D) + $ => E :MLOAD(initial_E) + $ => CTX :MLOAD(initial_CTX) + $ => SP :MLOAD(initial_SP) + $ => PC :MLOAD(initial_PC) + $ => GAS :MLOAD(initial_GAS) + $ => SR :MLOAD(initial_SR) + $ => RR :MLOAD(initial_RR) + $ => HASHPOS :MLOAD(initial_HASHPOS) + $ => RCX :MLOAD(initial_RCX) + +; label finalizeExecution needed by executor C++ +finalizeExecution: + ${beforeLast()} : JMPN(finalizeExecution) + + : JMP(start) +opINVALID: +; label checkAndSaveFrom needed by executor C++ +checkAndSaveFrom: + :JMP(opINVALID) + +INCLUDE "../main/pairings/FP2BN254/addFp2BN254.zkasm" +INCLUDE "../main/pairings/FP2BN254/subFp2BN254.zkasm" +INCLUDE "../main/pairings/FP2BN254/mulFp2BN254.zkasm" +INCLUDE "../main/pairings/FP2BN254/squareFp2BN254.zkasm" + +INCLUDE "../main/pairings/FP4BN254/squareFp4BN254.zkasm" \ No newline at end of file diff --git a/test/testFp6ArithBN254.zkasm b/test/testFp6ArithBN254.zkasm new file mode 100644 index 00000000..5259b73b --- /dev/null +++ b/test/testFp6ArithBN254.zkasm @@ -0,0 +1,260 @@ +; constants needed by executor C++ +CONST %N = 2**19 +CONST %MAX_CNT_STEPS_LIMIT = %N +CONST %MAX_CNT_ARITH_LIMIT = %N +CONST %MAX_CNT_BINARY_LIMIT = %N +CONST %MAX_CNT_MEM_ALIGN_LIMIT = %N +CONST %MAX_CNT_KECCAK_F_LIMIT = %N +CONST %MAX_CNT_PADDING_PG_LIMIT = %N +CONST %MAX_CNT_POSEIDON_G_LIMIT = %N + +CONSTL %BN254_P = 21888242871839275222246405745257275088696311157297823662689037894645226208583n + +VAR GLOBAL test + +VAR GLOBAL lastHashKId +VAR GLOBAL lastHashPId + +VAR GLOBAL initial_A +VAR GLOBAL initial_B +VAR GLOBAL initial_C +VAR GLOBAL initial_D +VAR GLOBAL initial_E +VAR GLOBAL initial_CTX +VAR GLOBAL initial_SP +VAR GLOBAL initial_PC +VAR GLOBAL initial_GAS +VAR GLOBAL initial_SR +VAR GLOBAL initial_RR +VAR GLOBAL initial_HASHPOS +VAR GLOBAL initial_RCX + +start: + + STEP => A + 0 :ASSERT + + + A :MSTORE(initial_A) + B :MSTORE(initial_B) + C :MSTORE(initial_C) + D :MSTORE(initial_D) + E :MSTORE(initial_E) + CTX :MSTORE(initial_CTX) + SP :MSTORE(initial_SP) + PC :MSTORE(initial_PC) + GAS :MSTORE(initial_GAS) + SR :MSTORE(initial_SR) + RR :MSTORE(initial_RR) + HASHPOS :MSTORE(initial_HASHPOS) + RCX :MSTORE(initial_RCX) + 0 => A,B,C,D,E,CTX, SP, PC, GAS, SR, RR, HASHPOS, RCX + + -1 :MSTORE(lastHashKId) + -1 :MSTORE(lastHashPId) + + ; 1] Addition + 10n :MSTORE(addFp6BN254_a1_x) + 2n :MSTORE(addFp6BN254_a1_y) + 5n :MSTORE(addFp6BN254_a2_x) + 13n :MSTORE(addFp6BN254_a2_y) + 7n :MSTORE(addFp6BN254_a3_x) + 5n :MSTORE(addFp6BN254_a3_y) + 9n :MSTORE(addFp6BN254_b1_x) + 1n :MSTORE(addFp6BN254_b1_y) + 1n :MSTORE(addFp6BN254_b2_x) + 2n :MSTORE(addFp6BN254_b2_y) + 14n :MSTORE(addFp6BN254_b3_x) + 3n :MSTORE(addFp6BN254_b3_y) + :CALL(addFp6BN254) + 19n :MLOAD(addFp6BN254_c1_x) + 3n :MLOAD(addFp6BN254_c1_y) + 6n :MLOAD(addFp6BN254_c2_x) + 15n :MLOAD(addFp6BN254_c2_y) + 21n :MLOAD(addFp6BN254_c3_x) + 8n :MLOAD(addFp6BN254_c3_y) + + ; 2] Subtraction + 10n :MSTORE(subFp6BN254_a1_x) + 2n :MSTORE(subFp6BN254_a1_y) + 5n :MSTORE(subFp6BN254_a2_x) + 13n :MSTORE(subFp6BN254_a2_y) + 7n :MSTORE(subFp6BN254_a3_x) + 5n :MSTORE(subFp6BN254_a3_y) + 9n :MSTORE(subFp6BN254_b1_x) + 1n :MSTORE(subFp6BN254_b1_y) + 1n :MSTORE(subFp6BN254_b2_x) + 2n :MSTORE(subFp6BN254_b2_y) + 14n :MSTORE(subFp6BN254_b3_x) + 3n :MSTORE(subFp6BN254_b3_y) + :CALL(subFp6BN254) + 1n :MLOAD(subFp6BN254_c1_x) + 1n :MLOAD(subFp6BN254_c1_y) + 4n :MLOAD(subFp6BN254_c2_x) + 11n :MLOAD(subFp6BN254_c2_y) + 21888242871839275222246405745257275088696311157297823662689037894645226208576n :MLOAD(subFp6BN254_c3_x) + 2n :MLOAD(subFp6BN254_c3_y) + + ; 3] Multiplication + 10n :MSTORE(mulFp6BN254_a1_x) + 2n :MSTORE(mulFp6BN254_a1_y) + 5n :MSTORE(mulFp6BN254_a2_x) + 13n :MSTORE(mulFp6BN254_a2_y) + 7n :MSTORE(mulFp6BN254_a3_x) + 5n :MSTORE(mulFp6BN254_a3_y) + 9n :MSTORE(mulFp6BN254_b1_x) + 1n :MSTORE(mulFp6BN254_b1_y) + 1n :MSTORE(mulFp6BN254_b2_x) + 2n :MSTORE(mulFp6BN254_b2_y) + 14n :MSTORE(mulFp6BN254_b3_x) + 2n :MSTORE(mulFp6BN254_b3_y) + :CALL(mulFp6BN254) + 246n :MLOAD(mulFp6BN254_c1_x) + 1968n :MLOAD(mulFp6BN254_c1_y) + 746n :MLOAD(mulFp6BN254_c2_x) + 988n :MLOAD(mulFp6BN254_c2_y) + 173n :MLOAD(mulFp6BN254_c3_x) + 123n :MLOAD(mulFp6BN254_c3_y) + + ; 4] Square + 10n :MSTORE(squareFp6BN254_a1_x) + 2n :MSTORE(squareFp6BN254_a1_y) + 5n :MSTORE(squareFp6BN254_a2_x) + 13n :MSTORE(squareFp6BN254_a2_y) + 7n :MSTORE(squareFp6BN254_a3_x) + 5n :MSTORE(squareFp6BN254_a3_y) + :CALL(squareFp6BN254) + 21888242871839275222246405745257275088696311157297823662689037894645226207907n :MLOAD(squareFp6BN254_c1_x) + 2068n :MLOAD(squareFp6BN254_c1_y) + 194n :MLOAD(squareFp6BN254_c2_x) + 934n :MLOAD(squareFp6BN254_c2_y) + 21888242871839275222246405745257275088696311157297823662689037894645226208559n :MLOAD(squareFp6BN254_c3_x) + 258n :MLOAD(squareFp6BN254_c3_y) + + ; 5] Inverse + 0n :MSTORE(inverseFp6BN254_a1_x) + 0n :MSTORE(inverseFp6BN254_a1_y) + 0n :MSTORE(inverseFp6BN254_a2_x) + 0n :MSTORE(inverseFp6BN254_a2_y) + 0n :MSTORE(inverseFp6BN254_a3_x) + 0n :MSTORE(inverseFp6BN254_a3_y) + :CALL(inverseFp6BN254) + 0n :MLOAD(inverseFp6BN254_c1_x) + 0n :MLOAD(inverseFp6BN254_c1_y) + 0n :MLOAD(inverseFp6BN254_c2_x) + 0n :MLOAD(inverseFp6BN254_c2_y) + 0n :MLOAD(inverseFp6BN254_c3_x) + 0n :MLOAD(inverseFp6BN254_c3_y) + + 10n :MSTORE(inverseFp6BN254_a1_x) + 2n :MSTORE(inverseFp6BN254_a1_y) + 5n :MSTORE(inverseFp6BN254_a2_x) + 13n :MSTORE(inverseFp6BN254_a2_y) + 7n :MSTORE(inverseFp6BN254_a3_x) + 5n :MSTORE(inverseFp6BN254_a3_y) + :CALL(inverseFp6BN254) + 5783650677754332851980206846879135451516056759867773021970105892178521520613n :MLOAD(inverseFp6BN254_c1_x) + 18013759458838322471361728283975517938597408816356047328991338914305007310576n :MLOAD(inverseFp6BN254_c1_y) + 18110874882414180653560035658613063208901925857749522062575191314371766555250n :MLOAD(inverseFp6BN254_c2_x) + 17807280852945820517699726487578389146070561376290295053174148308721316478672n :MLOAD(inverseFp6BN254_c2_y) + 14149695447230733832672344969363233706238986964811686150151922078523920094032n :MLOAD(inverseFp6BN254_c3_x) + 8319081930844559069109603696113388970848243877139140810016204850690606105497n :MLOAD(inverseFp6BN254_c3_y) + + ; 6] Sparse Multiplication A + 10n :MSTORE(sparseMulAFp6BN254_a1_x) + 2n :MSTORE(sparseMulAFp6BN254_a1_y) + 5n :MSTORE(sparseMulAFp6BN254_a2_x) + 13n :MSTORE(sparseMulAFp6BN254_a2_y) + 7n :MSTORE(sparseMulAFp6BN254_a3_x) + 5n :MSTORE(sparseMulAFp6BN254_a3_y) + 5n :MSTORE(sparseMulAFp6BN254_b2_x) + 78n :MSTORE(sparseMulAFp6BN254_b2_y) + :CALL(sparseMulAFp6BN254) + 21888242871839275222246405745257275088696311157297823662689037894645226204817n :MLOAD(sparseMulAFp6BN254_c1_x) + 4784n :MLOAD(sparseMulAFp6BN254_c1_y) + 21888242871839275222246405745257275088696311157297823662689037894645226208477n :MLOAD(sparseMulAFp6BN254_c2_x) + 790n :MLOAD(sparseMulAFp6BN254_c2_y) + 21888242871839275222246405745257275088696311157297823662689037894645226207594n :MLOAD(sparseMulAFp6BN254_c3_x) + 455n :MLOAD(sparseMulAFp6BN254_c3_y) + + ; 7] Sparse Multiplication B + 10n :MSTORE(sparseMulBFp6BN254_a1_x) + 2n :MSTORE(sparseMulBFp6BN254_a1_y) + 5n :MSTORE(sparseMulBFp6BN254_a2_x) + 13n :MSTORE(sparseMulBFp6BN254_a2_y) + 7n :MSTORE(sparseMulBFp6BN254_a3_x) + 5n :MSTORE(sparseMulBFp6BN254_a3_y) + 3n :MSTORE(sparseMulBFp6BN254_b2_x) + 100n :MSTORE(sparseMulBFp6BN254_b2_y) + 17n :MSTORE(sparseMulBFp6BN254_b3_x) + 8n :MSTORE(sparseMulBFp6BN254_b3_y) + :CALL(sparseMulBFp6BN254) + 21888242871839275222246405745257275088696311157297823662689037894645226203125n :MLOAD(sparseMulBFp6BN254_c1_x) + 8286n :MLOAD(sparseMulBFp6BN254_c1_y) + 400n :MLOAD(sparseMulBFp6BN254_c2_x) + 2354n :MLOAD(sparseMulBFp6BN254_c2_y) + 21888242871839275222246405745257275088696311157297823662689037894645226207452n :MLOAD(sparseMulBFp6BN254_c3_x) + 653n :MLOAD(sparseMulBFp6BN254_c3_y) + + ; 8] Sparse Multiplication C + 10n :MSTORE(sparseMulCFp6BN254_a1_x) + 2n :MSTORE(sparseMulCFp6BN254_a1_y) + 5n :MSTORE(sparseMulCFp6BN254_a2_x) + 13n :MSTORE(sparseMulCFp6BN254_a2_y) + 7n :MSTORE(sparseMulCFp6BN254_a3_x) + 5n :MSTORE(sparseMulCFp6BN254_a3_y) + 3n :MSTORE(sparseMulCFp6BN254_b1_x) + 100n :MSTORE(sparseMulCFp6BN254_b1_y) + 17n :MSTORE(sparseMulCFp6BN254_b3_x) + 8n :MSTORE(sparseMulCFp6BN254_b3_y) + :CALL(sparseMulCFp6BN254) + 21888242871839275222246405745257275088696311157297823662689037894645226207981n :MLOAD(sparseMulCFp6BN254_c1_x) + 3336n :MLOAD(sparseMulCFp6BN254_c1_y) + 21888242871839275222246405745257275088696311157297823662689037894645226207868n :MLOAD(sparseMulCFp6BN254_c2_x) + 1887n :MLOAD(sparseMulCFp6BN254_c2_y) + 21888242871839275222246405745257275088696311157297823662689037894645226208258n :MLOAD(sparseMulCFp6BN254_c3_x) + 829n :MLOAD(sparseMulCFp6BN254_c3_y) + +end: + + $ => A :MLOAD(initial_A) + $ => B :MLOAD(initial_B) + $ => C :MLOAD(initial_C) + $ => D :MLOAD(initial_D) + $ => E :MLOAD(initial_E) + $ => CTX :MLOAD(initial_CTX) + $ => SP :MLOAD(initial_SP) + $ => PC :MLOAD(initial_PC) + $ => GAS :MLOAD(initial_GAS) + $ => SR :MLOAD(initial_SR) + $ => RR :MLOAD(initial_RR) + $ => HASHPOS :MLOAD(initial_HASHPOS) + $ => RCX :MLOAD(initial_RCX) + +; label finalizeExecution needed by executor C++ +finalizeExecution: + ${beforeLast()} : JMPN(finalizeExecution) + + : JMP(start) +opINVALID: +; label checkAndSaveFrom needed by executor C++ +checkAndSaveFrom: + :JMP(opINVALID) + +INCLUDE "../main/pairings/FPBN254/reduceFpBN254.zkasm" + +INCLUDE "../main/pairings/FP2BN254/addFp2BN254.zkasm" +INCLUDE "../main/pairings/FP2BN254/subFp2BN254.zkasm" +INCLUDE "../main/pairings/FP2BN254/mulFp2BN254.zkasm" +INCLUDE "../main/pairings/FP2BN254/invFp2BN254.zkasm" +INCLUDE "../main/pairings/FP2BN254/squareFp2BN254.zkasm" +INCLUDE "../main/pairings/FP2BN254/escalarMulFp2BN254.zkasm" + +INCLUDE "../main/pairings/FP6BN254/addFp6BN254.zkasm" +INCLUDE "../main/pairings/FP6BN254/subFp6BN254.zkasm" +INCLUDE "../main/pairings/FP6BN254/mulFp6BN254.zkasm" +INCLUDE "../main/pairings/FP6BN254/squareFp6BN254.zkasm" +INCLUDE "../main/pairings/FP6BN254/inverseFp6BN254.zkasm" +INCLUDE "../main/pairings/FP6BN254/sparseMulAFp6BN254.zkasm" +INCLUDE "../main/pairings/FP6BN254/sparseMulBFp6BN254.zkasm" +INCLUDE "../main/pairings/FP6BN254/sparseMulCFp6BN254.zkasm" \ No newline at end of file diff --git a/test/testFpArithBN254.zkasm b/test/testFpArithBN254.zkasm new file mode 100644 index 00000000..3b2bc356 --- /dev/null +++ b/test/testFpArithBN254.zkasm @@ -0,0 +1,159 @@ +; constants needed by executor C++ +CONST %N = 2**19 +CONST %MAX_CNT_STEPS_LIMIT = %N +CONST %MAX_CNT_ARITH_LIMIT = %N +CONST %MAX_CNT_BINARY_LIMIT = %N +CONST %MAX_CNT_MEM_ALIGN_LIMIT = %N +CONST %MAX_CNT_KECCAK_F_LIMIT = %N +CONST %MAX_CNT_PADDING_PG_LIMIT = %N +CONST %MAX_CNT_POSEIDON_G_LIMIT = %N + +CONSTL %BN254_P = 21888242871839275222246405745257275088696311157297823662689037894645226208583n +CONSTL %BN254_P_MINUS_ONE = 21888242871839275222246405745257275088696311157297823662689037894645226208582n +CONSTL %BN254_P_BY_TWO = 43776485743678550444492811490514550177392622314595647325378075789290452417166n + +VAR GLOBAL lastHashKId +VAR GLOBAL lastHashPId + +VAR GLOBAL initial_A +VAR GLOBAL initial_B +VAR GLOBAL initial_C +VAR GLOBAL initial_D +VAR GLOBAL initial_E +VAR GLOBAL initial_CTX +VAR GLOBAL initial_SP +VAR GLOBAL initial_PC +VAR GLOBAL initial_GAS +VAR GLOBAL initial_SR +VAR GLOBAL initial_RR +VAR GLOBAL initial_HASHPOS +VAR GLOBAL initial_RCX + +start: + + STEP => A + 0 :ASSERT + + + A :MSTORE(initial_A) + B :MSTORE(initial_B) + C :MSTORE(initial_C) + D :MSTORE(initial_D) + E :MSTORE(initial_E) + CTX :MSTORE(initial_CTX) + SP :MSTORE(initial_SP) + PC :MSTORE(initial_PC) + GAS :MSTORE(initial_GAS) + SR :MSTORE(initial_SR) + RR :MSTORE(initial_RR) + HASHPOS :MSTORE(initial_HASHPOS) + RCX :MSTORE(initial_RCX) + 0 => A,B,C,D,E,CTX, SP, PC, GAS, SR, RR, HASHPOS, RCX + + -1 :MSTORE(lastHashKId) + -1 :MSTORE(lastHashPId) + + ; 1] Addition + 1n => A + 3n => C + :CALL(addFpBN254) + C => A + 4n :ASSERT + + ; 2] Subtraction + 2n => A + 3n => C + :CALL(subFpBN254) + C => A + %BN254_P_MINUS_ONE :ASSERT + + ; 3] Squaring + ${const.BN254_P - 2} => A + :CALL(squareFpBN254) + B => A + 4n :ASSERT + + ; 4] Inversion + 0n => A + :CALL(invFpBN254) + B => A + 0n :ASSERT + + %BN254_P + %BN254_P => A + :CALL(invFpBN254) + B => A + 0n :ASSERT + + %BN254_P + %BN254_P + %BN254_P => A + :CALL(invFpBN254) + B => A + 0n :ASSERT + + %BN254_P + %BN254_P + %BN254_P + %BN254_P => A + :CALL(invFpBN254) + B => A + 0n :ASSERT + + %BN254_P + %BN254_P + %BN254_P + %BN254_P + %BN254_P => A + :CALL(invFpBN254) + B => A + 0n :ASSERT + + 2n => A + :CALL(invFpBN254) + B => A + 10944121435919637611123202872628637544348155578648911831344518947322613104292n :ASSERT + + ; 5] Reduction + 0n => A + :CALL(reduceFpBN254) + 0n :ASSERT + + %BN254_P => A + :CALL(reduceFpBN254) + 0n :ASSERT + + %BN254_P + 1n => A + :CALL(reduceFpBN254) + 1n :ASSERT + + %BN254_P + %BN254_P_MINUS_ONE => A + :CALL(reduceFpBN254) + %BN254_P_MINUS_ONE :ASSERT + + %BN254_P_BY_TWO => A + :CALL(reduceFpBN254) + 0n :ASSERT + + +end: + + $ => A :MLOAD(initial_A) + $ => B :MLOAD(initial_B) + $ => C :MLOAD(initial_C) + $ => D :MLOAD(initial_D) + $ => E :MLOAD(initial_E) + $ => CTX :MLOAD(initial_CTX) + $ => SP :MLOAD(initial_SP) + $ => PC :MLOAD(initial_PC) + $ => GAS :MLOAD(initial_GAS) + $ => SR :MLOAD(initial_SR) + $ => RR :MLOAD(initial_RR) + $ => HASHPOS :MLOAD(initial_HASHPOS) + $ => RCX :MLOAD(initial_RCX) + +; label finalizeExecution needed by executor C++ +finalizeExecution: + ${beforeLast()} : JMPN(finalizeExecution) + + : JMP(start) +opINVALID: +; label checkAndSaveFrom needed by executor C++ +checkAndSaveFrom: + :JMP(opINVALID) + +INCLUDE "../main/pairings/FPBN254/reduceFpBN254.zkasm" +INCLUDE "../main/pairings/FPBN254/addFpBN254.zkasm" +INCLUDE "../main/pairings/FPBN254/subFpBN254.zkasm" +INCLUDE "../main/pairings/FPBN254/squareFpBN254.zkasm" +INCLUDE "../main/pairings/FPBN254/invFpBN254.zkasm" \ No newline at end of file diff --git a/test/testFrArithBN254.zkasm b/test/testFrArithBN254.zkasm new file mode 100644 index 00000000..0ae8cfa7 --- /dev/null +++ b/test/testFrArithBN254.zkasm @@ -0,0 +1,113 @@ +; constants needed by executor C++ +CONST %N = 2**19 +CONST %MAX_CNT_STEPS_LIMIT = %N +CONST %MAX_CNT_ARITH_LIMIT = %N +CONST %MAX_CNT_BINARY_LIMIT = %N +CONST %MAX_CNT_MEM_ALIGN_LIMIT = %N +CONST %MAX_CNT_KECCAK_F_LIMIT = %N +CONST %MAX_CNT_PADDING_PG_LIMIT = %N +CONST %MAX_CNT_POSEIDON_G_LIMIT = %N + +INCLUDE "../main/pairings/constants.zkasm" + +VAR GLOBAL lastHashKId +VAR GLOBAL lastHashPId + +VAR GLOBAL initial_A +VAR GLOBAL initial_B +VAR GLOBAL initial_C +VAR GLOBAL initial_D +VAR GLOBAL initial_E +VAR GLOBAL initial_CTX +VAR GLOBAL initial_SP +VAR GLOBAL initial_PC +VAR GLOBAL initial_GAS +VAR GLOBAL initial_SR +VAR GLOBAL initial_RR +VAR GLOBAL initial_HASHPOS +VAR GLOBAL initial_RCX + +start: + + STEP => A + 0 :ASSERT + + + A :MSTORE(initial_A) + B :MSTORE(initial_B) + C :MSTORE(initial_C) + D :MSTORE(initial_D) + E :MSTORE(initial_E) + CTX :MSTORE(initial_CTX) + SP :MSTORE(initial_SP) + PC :MSTORE(initial_PC) + GAS :MSTORE(initial_GAS) + SR :MSTORE(initial_SR) + RR :MSTORE(initial_RR) + HASHPOS :MSTORE(initial_HASHPOS) + RCX :MSTORE(initial_RCX) + 0 => A,B,C,D,E,CTX, SP, PC, GAS, SR, RR, HASHPOS, RCX + + -1 :MSTORE(lastHashKId) + -1 :MSTORE(lastHashPId) + + ; 1] Reduction + 3n => B + :CALL(reduceFrBN254) + C => A + 3n => B :ASSERT + + %BN254_R => B + :CALL(reduceFrBN254) + C => A + 0n => B :ASSERT + + 21888242871839275222246405745257275088548364400416034343698204186575808495618n => B + :CALL(reduceFrBN254) + C => A + 1n => B :ASSERT + + %BN254_P => B + :CALL(reduceFrBN254) + C => A + %BN254_SIX_TIMES_X_SQ => B :ASSERT + + 21888242871839275222246405745257275088696311157297823662689037894645226208584n => B + :CALL(reduceFrBN254) + C => A + 147946756881789318990833708069417712967n => B :ASSERT + + 115792089237316195423570985008687907853269984665640564039457584007913129639935n => B + :CALL(reduceFrBN254) + C => A + 6350874878119819312338956282401532410528162663560392320966563075034087161850n => B :ASSERT + + +end: + + $ => A :MLOAD(initial_A) + $ => B :MLOAD(initial_B) + $ => C :MLOAD(initial_C) + $ => D :MLOAD(initial_D) + $ => E :MLOAD(initial_E) + $ => CTX :MLOAD(initial_CTX) + $ => SP :MLOAD(initial_SP) + $ => PC :MLOAD(initial_PC) + $ => GAS :MLOAD(initial_GAS) + $ => SR :MLOAD(initial_SR) + $ => RR :MLOAD(initial_RR) + $ => HASHPOS :MLOAD(initial_HASHPOS) + $ => RCX :MLOAD(initial_RCX) + +; label finalizeExecution needed by executor C++ +finalizeExecution: + ${beforeLast()} : JMPN(finalizeExecution) + + : JMP(start) +opINVALID: +; label checkAndSaveFrom needed by executor C++ +checkAndSaveFrom: + :JMP(opINVALID) + + +INCLUDE "../main/pairings/FRBN254/reduceFrBN254.zkasm" \ No newline at end of file diff --git a/test/testHalfPairingBN254.zkasm b/test/testHalfPairingBN254.zkasm new file mode 100644 index 00000000..a37ef1f0 --- /dev/null +++ b/test/testHalfPairingBN254.zkasm @@ -0,0 +1,285 @@ +; constants needed by executor C++ +CONST %N = 2**19 +CONST %MAX_CNT_STEPS_LIMIT = %N +CONST %MAX_CNT_ARITH_LIMIT = %N +CONST %MAX_CNT_BINARY_LIMIT = %N +CONST %MAX_CNT_MEM_ALIGN_LIMIT = %N +CONST %MAX_CNT_KECCAK_F_LIMIT = %N +CONST %MAX_CNT_PADDING_PG_LIMIT = %N +CONST %MAX_CNT_POSEIDON_G_LIMIT = %N + +INCLUDE "../main/pairings/constants.zkasm" + +VAR GLOBAL lastHashKId +VAR GLOBAL lastHashPId + +VAR GLOBAL initial_A +VAR GLOBAL initial_B +VAR GLOBAL initial_C +VAR GLOBAL initial_D +VAR GLOBAL initial_E +VAR GLOBAL initial_CTX +VAR GLOBAL initial_SP +VAR GLOBAL initial_PC +VAR GLOBAL initial_GAS +VAR GLOBAL initial_SR +VAR GLOBAL initial_RR +VAR GLOBAL initial_HASHPOS +VAR GLOBAL initial_RCX + +start: + + STEP => A + 0 :ASSERT + + + A :MSTORE(initial_A) + B :MSTORE(initial_B) + C :MSTORE(initial_C) + D :MSTORE(initial_D) + E :MSTORE(initial_E) + CTX :MSTORE(initial_CTX) + SP :MSTORE(initial_SP) + PC :MSTORE(initial_PC) + GAS :MSTORE(initial_GAS) + SR :MSTORE(initial_SR) + RR :MSTORE(initial_RR) + HASHPOS :MSTORE(initial_HASHPOS) + RCX :MSTORE(initial_RCX) + 0 => A,B,C,D,E,CTX, SP, PC, GAS, SR, RR, HASHPOS, RCX + + -1 :MSTORE(lastHashKId) + -1 :MSTORE(lastHashPId) + + ; 1] P = Q = 0 + 0n :MSTORE(halfPairingBN254_P_x) + 0n :MSTORE(halfPairingBN254_P_y) + 0n :MSTORE(halfPairingBN254_Q_x1) + 0n :MSTORE(halfPairingBN254_Q_x2) + 0n :MSTORE(halfPairingBN254_Q_y1) + 0n :MSTORE(halfPairingBN254_Q_y2) + :CALL(halfPairingBN254) + 1n :MLOAD(halfPairingBN254_f11_x) + 0n :MLOAD(halfPairingBN254_f11_y) + 0n :MLOAD(halfPairingBN254_f12_x) + 0n :MLOAD(halfPairingBN254_f12_y) + 0n :MLOAD(halfPairingBN254_f13_x) + 0n :MLOAD(halfPairingBN254_f13_y) + 0n :MLOAD(halfPairingBN254_f21_x) + 0n :MLOAD(halfPairingBN254_f21_y) + 0n :MLOAD(halfPairingBN254_f22_x) + 0n :MLOAD(halfPairingBN254_f22_y) + 0n :MLOAD(halfPairingBN254_f23_x) + 0n :MLOAD(halfPairingBN254_f23_y) + + ; 2] P = 0, Q ∈ G2\{0} + 0n :MSTORE(halfPairingBN254_P_x) + 0n :MSTORE(halfPairingBN254_P_y) + 4351401811647638138392695977895401859084096897123577305203754529537814663109n :MSTORE(halfPairingBN254_Q_x1) + 2046729899889901964437012741252570163462327955511008570480857952505584629957n :MSTORE(halfPairingBN254_Q_x2) + 322506915963699862059245473966830598387691259163658767351233132602858049743n :MSTORE(halfPairingBN254_Q_y1) + 14316075702276096164483565793667862351398527813470041574939773541551376891710n :MSTORE(halfPairingBN254_Q_y2) + :CALL(halfPairingBN254) + 1n :MLOAD(halfPairingBN254_f11_x) + 0n :MLOAD(halfPairingBN254_f11_y) + 0n :MLOAD(halfPairingBN254_f12_x) + 0n :MLOAD(halfPairingBN254_f12_y) + 0n :MLOAD(halfPairingBN254_f13_x) + 0n :MLOAD(halfPairingBN254_f13_y) + 0n :MLOAD(halfPairingBN254_f21_x) + 0n :MLOAD(halfPairingBN254_f21_y) + 0n :MLOAD(halfPairingBN254_f22_x) + 0n :MLOAD(halfPairingBN254_f22_y) + 0n :MLOAD(halfPairingBN254_f23_x) + 0n :MLOAD(halfPairingBN254_f23_y) + + ; 3] P ∈ G1\{0}, Q = 0 + 1368015179489954701390400359078579693043519447331113978918064868415326638035n :MSTORE(halfPairingBN254_P_x) + 9918110051302171585080402603319702774565515993150576347155970296011118125764n :MSTORE(halfPairingBN254_P_y) + 0n :MSTORE(halfPairingBN254_Q_x1) + 0n :MSTORE(halfPairingBN254_Q_x2) + 0n :MSTORE(halfPairingBN254_Q_y1) + 0n :MSTORE(halfPairingBN254_Q_y2) + :CALL(halfPairingBN254) + 1n :MLOAD(halfPairingBN254_f11_x) + 0n :MLOAD(halfPairingBN254_f11_y) + 0n :MLOAD(halfPairingBN254_f12_x) + 0n :MLOAD(halfPairingBN254_f12_y) + 0n :MLOAD(halfPairingBN254_f13_x) + 0n :MLOAD(halfPairingBN254_f13_y) + 0n :MLOAD(halfPairingBN254_f21_x) + 0n :MLOAD(halfPairingBN254_f21_y) + 0n :MLOAD(halfPairingBN254_f22_x) + 0n :MLOAD(halfPairingBN254_f22_y) + 0n :MLOAD(halfPairingBN254_f23_x) + 0n :MLOAD(halfPairingBN254_f23_y) + + ; 3] Px too big + %BN254_P :MSTORE(halfPairingBN254_P_x) + 0n :MSTORE(halfPairingBN254_P_y) + 0n :MSTORE(halfPairingBN254_Q_x1) + 0n :MSTORE(halfPairingBN254_Q_x2) + 0n :MSTORE(halfPairingBN254_Q_y1) + 0n :MSTORE(halfPairingBN254_Q_y2) + :CALL(halfPairingBN254) + B => A + 1 :ASSERT + + ; 4] Py too big + 0n :MSTORE(halfPairingBN254_P_x) + %BN254_P :MSTORE(halfPairingBN254_P_y) + 0n :MSTORE(halfPairingBN254_Q_x1) + 0n :MSTORE(halfPairingBN254_Q_x2) + 0n :MSTORE(halfPairingBN254_Q_y1) + 0n :MSTORE(halfPairingBN254_Q_y2) + :CALL(halfPairingBN254) + B => A + 2 :ASSERT + + ; 5] Qx1 too big + 0n :MSTORE(halfPairingBN254_P_x) + 0n :MSTORE(halfPairingBN254_P_y) + %BN254_P :MSTORE(halfPairingBN254_Q_x1) + 0n :MSTORE(halfPairingBN254_Q_x2) + 0n :MSTORE(halfPairingBN254_Q_y1) + 0n :MSTORE(halfPairingBN254_Q_y2) + :CALL(halfPairingBN254) + B => A + 3 :ASSERT + + ; 6] Qx2 too big + 0n :MSTORE(halfPairingBN254_P_x) + 0n :MSTORE(halfPairingBN254_P_y) + 0n :MSTORE(halfPairingBN254_Q_x1) + %BN254_P :MSTORE(halfPairingBN254_Q_x2) + 0n :MSTORE(halfPairingBN254_Q_y1) + 0n :MSTORE(halfPairingBN254_Q_y2) + :CALL(halfPairingBN254) + B => A + 4 :ASSERT + + ; 7] Qy1 too big + 0n :MSTORE(halfPairingBN254_P_x) + 0n :MSTORE(halfPairingBN254_P_y) + 0n :MSTORE(halfPairingBN254_Q_x1) + 0n :MSTORE(halfPairingBN254_Q_x2) + %BN254_P :MSTORE(halfPairingBN254_Q_y1) + 0n :MSTORE(halfPairingBN254_Q_y2) + :CALL(halfPairingBN254) + B => A + 5 :ASSERT + + ; 8] Qy2 too big + 0n :MSTORE(halfPairingBN254_P_x) + 0n :MSTORE(halfPairingBN254_P_y) + 0n :MSTORE(halfPairingBN254_Q_x1) + 0n :MSTORE(halfPairingBN254_Q_x2) + 0n :MSTORE(halfPairingBN254_Q_y1) + %BN254_P :MSTORE(halfPairingBN254_Q_y2) + :CALL(halfPairingBN254) + B => A + 6 :ASSERT + + ; 9] P ∉ G1 + 1n :MSTORE(halfPairingBN254_P_x) + 0n :MSTORE(halfPairingBN254_P_y) + 0n :MSTORE(halfPairingBN254_Q_x1) + 0n :MSTORE(halfPairingBN254_Q_x2) + 0n :MSTORE(halfPairingBN254_Q_y1) + 0n :MSTORE(halfPairingBN254_Q_y2) + :CALL(halfPairingBN254) + B => A + 7 :ASSERT + + ; 10] Q ∉ G2 + 0n :MSTORE(halfPairingBN254_P_x) + 0n :MSTORE(halfPairingBN254_P_y) + 1n :MSTORE(halfPairingBN254_Q_x1) + 0n :MSTORE(halfPairingBN254_Q_x2) + 0n :MSTORE(halfPairingBN254_Q_y1) + 0n :MSTORE(halfPairingBN254_Q_y2) + :CALL(halfPairingBN254) + B => A + 8 :ASSERT + + ; 11] Normal example + 1368015179489954701390400359078579693043519447331113978918064868415326638035n :MSTORE(halfPairingBN254_P_x) + 9918110051302171585080402603319702774565515993150576347155970296011118125764n :MSTORE(halfPairingBN254_P_y) + 4351401811647638138392695977895401859084096897123577305203754529537814663109n :MSTORE(halfPairingBN254_Q_x1) + 2046729899889901964437012741252570163462327955511008570480857952505584629957n :MSTORE(halfPairingBN254_Q_x2) + 322506915963699862059245473966830598387691259163658767351233132602858049743n :MSTORE(halfPairingBN254_Q_y1) + 14316075702276096164483565793667862351398527813470041574939773541551376891710n :MSTORE(halfPairingBN254_Q_y2) + :CALL(halfPairingBN254) + 13640254227245024655838601068231183157721360561601028708811475275217122101072n :MLOAD(halfPairingBN254_f11_x) + 19308417300657558492615098636528930118171456086181403615599560648373004008445n :MLOAD(halfPairingBN254_f11_y) + 11600807028088028070223911119334614254604789223029238428546002219857166268982n :MLOAD(halfPairingBN254_f12_x) + 4879406373235938927297467572708988980645988929154072556290202741257062565094n :MLOAD(halfPairingBN254_f12_y) + 4171685090913488783052266386653991584736187693807813444268445186114207424938n :MLOAD(halfPairingBN254_f13_x) + 1277573873092817905392452044933753278511826457458184982228668801202320403016n :MLOAD(halfPairingBN254_f13_y) + 14431703268682647902296102635071887590346322924866425403256046961671041030534n :MLOAD(halfPairingBN254_f21_x) + 11898392435919290118390574221795784387718317590754683868792519816848089304255n :MLOAD(halfPairingBN254_f21_y) + 583787015380908422861158991038392109634638768690762169717364137330743074526n :MLOAD(halfPairingBN254_f22_x) + 13126870183170761631152540488140870675640427576483291663794972909787720839738n :MLOAD(halfPairingBN254_f22_y) + 6457767870676104874999362178075129079810053093666926870765167604207462152679n :MLOAD(halfPairingBN254_f23_x) + 12911511138445339632082563502636262379527290965988664015632615336010308825090n :MLOAD(halfPairingBN254_f23_y) + +end: + + $ => A :MLOAD(initial_A) + $ => B :MLOAD(initial_B) + $ => C :MLOAD(initial_C) + $ => D :MLOAD(initial_D) + $ => E :MLOAD(initial_E) + $ => CTX :MLOAD(initial_CTX) + $ => SP :MLOAD(initial_SP) + $ => PC :MLOAD(initial_PC) + $ => GAS :MLOAD(initial_GAS) + $ => SR :MLOAD(initial_SR) + $ => RR :MLOAD(initial_RR) + $ => HASHPOS :MLOAD(initial_HASHPOS) + $ => RCX :MLOAD(initial_RCX) + +; label finalizeExecution needed by executor C++ +finalizeExecution: + ${beforeLast()} : JMPN(finalizeExecution) + + : JMP(start) +opINVALID: +; label checkAndSaveFrom needed by executor C++ +checkAndSaveFrom: + :JMP(opINVALID) + +INCLUDE "../main/pairings/halfPairingBN254.zkasm" + +INCLUDE "../main/pairings/FRBN254/reduceFrBN254.zkasm" + +INCLUDE "../main/pairings/FPBN254/reduceFpBN254.zkasm" +INCLUDE "../main/pairings/FPBN254/addFpBN254.zkasm" +INCLUDE "../main/pairings/FPBN254/mulFpBN254.zkasm" + +INCLUDE "../main/pairings/FP2BN254/addFp2BN254.zkasm" +INCLUDE "../main/pairings/FP2BN254/subFp2BN254.zkasm" +INCLUDE "../main/pairings/FP2BN254/mulFp2BN254.zkasm" +INCLUDE "../main/pairings/FP2BN254/squareFp2BN254.zkasm" +INCLUDE "../main/pairings/FP2BN254/escalarMulFp2BN254.zkasm" +INCLUDE "../main/pairings/FP2BN254/invFp2BN254.zkasm" + +INCLUDE "../main/pairings/FP6BN254/addFp6BN254.zkasm" +INCLUDE "../main/pairings/FP6BN254/subFp6BN254.zkasm" +INCLUDE "../main/pairings/FP6BN254/mulFp6BN254.zkasm" +INCLUDE "../main/pairings/FP6BN254/escalarMulFp6BN254.zkasm" +INCLUDE "../main/pairings/FP6BN254/sparseMulAFp6BN254.zkasm" +INCLUDE "../main/pairings/FP6BN254/sparseMulBFp6BN254.zkasm" +INCLUDE "../main/pairings/FP6BN254/sparseMulCFp6BN254.zkasm" + +INCLUDE "../main/pairings/FP12BN254/sparseMulAFp12BN254.zkasm" +INCLUDE "../main/pairings/FP12BN254/sparseMulBFp12BN254.zkasm" +INCLUDE "../main/pairings/FP12BN254/squareFp12BN254.zkasm" + +INCLUDE "../main/pairings/BN254/addPointBN254.zkasm" +INCLUDE "../main/pairings/BN254/escalarMulBN254.zkasm" +INCLUDE "../main/pairings/BN254/lineSamePointsBN254.zkasm" +INCLUDE "../main/pairings/BN254/lineDiffPointsBN254.zkasm" + +INCLUDE "../main/pairings/millerLoopBN254.zkasm" +INCLUDE "../main/pairings/loopLengthBN254.zkasm" \ No newline at end of file diff --git a/test/testModExp.zkasm b/test/testModExp.zkasm new file mode 100644 index 00000000..1b3c6095 --- /dev/null +++ b/test/testModExp.zkasm @@ -0,0 +1,586 @@ +; constants needed by executor C++ +INCLUDE "../main/constants.zkasm" + +VAR GLOBAL lastHashKId +VAR GLOBAL lastHashPId + +VAR GLOBAL initial_A +VAR GLOBAL initial_B +VAR GLOBAL initial_C +VAR GLOBAL initial_D +VAR GLOBAL initial_E +VAR GLOBAL initial_CTX +VAR GLOBAL initial_SP +VAR GLOBAL initial_PC +VAR GLOBAL initial_GAS +VAR GLOBAL initial_SR +VAR GLOBAL initial_RR +VAR GLOBAL initial_HASHPOS +VAR GLOBAL initial_RCX + +start: + + STEP => A + 0 :ASSERT + + A :MSTORE(initial_A) + B :MSTORE(initial_B) + C :MSTORE(initial_C) + D :MSTORE(initial_D) + E :MSTORE(initial_E) + CTX :MSTORE(initial_CTX) + SP :MSTORE(initial_SP) + PC :MSTORE(initial_PC) + GAS :MSTORE(initial_GAS) + SR :MSTORE(initial_SR) + RR :MSTORE(initial_RR) + HASHPOS :MSTORE(initial_HASHPOS) + RCX :MSTORE(initial_RCX) + 0 => A,B,C,D,E,CTX, SP, PC, GAS, SR, RR, HASHPOS, RCX + + -1 :MSTORE(lastHashKId) + -1 :MSTORE(lastHashPId) + + ; ; UPDATE: Edge cases are not handled by the modexp function directly + ; ; EDGE CASES TESTS + ; ; --------------------------------------------------------------------------------------------- + ; ; 1] B == 0, E != 0, M != 0 should return 0 + ; 1 :MSTORE(modexp_Blen) + ; 1 :MSTORE(modexp_Elen) + ; 1 :MSTORE(modexp_Mlen) + + ; 0n :MSTORE(modexp_B) + ; 3n :MSTORE(modexp_E) + ; 4n :MSTORE(modexp_M) + ; :CALL(modexp) + + ; 0n :MLOAD(modexp_out) + ; 1 :MLOAD(modexp_outlen) + + ; 1 :MSTORE(modexp_Blen) + ; 2 :MSTORE(modexp_Elen) + ; 2 :MSTORE(modexp_Mlen) + + ; 0n :MSTORE(modexp_B) + ; 0n :MSTORE(modexp_E) + ; 1 => E + ; 1n :MSTORE(modexp_E + E) + ; 0n :MSTORE(modexp_M) + ; 1 => E + ; 1n :MSTORE(modexp_M + E) + ; :CALL(modexp) + + ; 0n :MLOAD(modexp_out) + ; 1 :MLOAD(modexp_outlen) + + ; ; 2] B != 0, E == 0, M != 0 should return 1 + ; 1 :MSTORE(modexp_Blen) + ; 1 :MSTORE(modexp_Elen) + ; 1 :MSTORE(modexp_Mlen) + + ; 2n :MSTORE(modexp_B) + ; 0n :MSTORE(modexp_E) + ; 4n :MSTORE(modexp_M) + ; :CALL(modexp) + + ; 1n :MLOAD(modexp_out) + ; 1 :MLOAD(modexp_outlen) + + ; 2 :MSTORE(modexp_Blen) + ; 1 :MSTORE(modexp_Elen) + ; 2 :MSTORE(modexp_Mlen) + + ; 2n :MSTORE(modexp_B) + ; 1 => E + ; 4n :MSTORE(modexp_B + E) + ; 0n :MSTORE(modexp_E) + ; 0n :MSTORE(modexp_M) + ; 1 => E + ; 1n :MSTORE(modexp_M + E) + ; :CALL(modexp) + + ; 1n :MLOAD(modexp_out) + ; 1 :MLOAD(modexp_outlen) + + ; ; 3] B != 0, E != 0, M == 0 should return 0 + ; 1 :MSTORE(modexp_Blen) + ; 1 :MSTORE(modexp_Elen) + ; 1 :MSTORE(modexp_Mlen) + + ; 2n :MSTORE(modexp_B) + ; 1n :MSTORE(modexp_E) + ; 0n :MSTORE(modexp_M) + ; :CALL(modexp) + ; 0n :MLOAD(modexp_out) + ; 1 :MLOAD(modexp_outlen) + + ; 2 :MSTORE(modexp_Blen) + ; 2 :MSTORE(modexp_Elen) + ; 1 :MSTORE(modexp_Mlen) + + ; 2n :MSTORE(modexp_B) + ; 1 => E + ; 4n :MSTORE(modexp_B + E) + ; 0n :MSTORE(modexp_E) + ; 1 => E + ; 4n :MSTORE(modexp_E + E) + ; 0n :MSTORE(modexp_M) + ; :CALL(modexp) + + ; 0n :MLOAD(modexp_out) + ; 1 :MLOAD(modexp_outlen) + + ; ; 4] B != 0, E != 0, M == 1 should return 0 + ; 1 :MSTORE(modexp_Blen) + ; 1 :MSTORE(modexp_Elen) + ; 1 :MSTORE(modexp_Mlen) + + ; 2n :MSTORE(modexp_B) + ; 1n :MSTORE(modexp_E) + ; 1n :MSTORE(modexp_M) + ; :CALL(modexp) + ; 0n :MLOAD(modexp_out) + ; 1 :MLOAD(modexp_outlen) + + ; 2 :MSTORE(modexp_Blen) + ; 2 :MSTORE(modexp_Elen) + ; 1 :MSTORE(modexp_Mlen) + + ; 2n :MSTORE(modexp_B) + ; 1 => E + ; 4n :MSTORE(modexp_B + E) + ; 0n :MSTORE(modexp_E) + ; 1 => E + ; 4n :MSTORE(modexp_E + E) + ; 1n :MSTORE(modexp_M) + ; :CALL(modexp) + + ; 0n :MLOAD(modexp_out) + ; 1 :MLOAD(modexp_outlen) + + ; ; 5] B == 0, E == 0, M != 0 should return 0^0 = 0 + ; 1 :MSTORE(modexp_Blen) + ; 1 :MSTORE(modexp_Elen) + ; 1 :MSTORE(modexp_Mlen) + + ; 0n :MSTORE(modexp_B) + ; 0n :MSTORE(modexp_E) + ; 4n :MSTORE(modexp_M) + ; :CALL(modexp) + + ; 0n :MLOAD(modexp_out) + ; 1 :MLOAD(modexp_outlen) + + ; 1 :MSTORE(modexp_Blen) + ; 1 :MSTORE(modexp_Elen) + ; 2 :MSTORE(modexp_Mlen) + + ; 0n :MSTORE(modexp_B) + ; 0n :MSTORE(modexp_E) + ; 0n :MSTORE(modexp_M) + ; 1 => E + ; 1n :MSTORE(modexp_M + E) + ; :CALL(modexp) + + ; 0n :MLOAD(modexp_out) + ; 1 :MLOAD(modexp_outlen) + + ; ; 6] B == 0, E != 0, M == 0 should return 0 + ; 1 :MSTORE(modexp_Blen) + ; 1 :MSTORE(modexp_Elen) + ; 1 :MSTORE(modexp_Mlen) + + ; 0n :MSTORE(modexp_B) + ; 4n :MSTORE(modexp_E) + ; 0n :MSTORE(modexp_M) + ; :CALL(modexp) + + ; 0n :MLOAD(modexp_out) + ; 1 :MLOAD(modexp_outlen) + + ; 1 :MSTORE(modexp_Blen) + ; 2 :MSTORE(modexp_Elen) + ; 1 :MSTORE(modexp_Mlen) + + ; 0n :MSTORE(modexp_B) + ; 0n :MSTORE(modexp_E) + ; 1 => E + ; 1n :MSTORE(modexp_E + E) + ; 0n :MSTORE(modexp_M) + ; :CALL(modexp) + + ; 0n :MLOAD(modexp_out) + ; 1 :MLOAD(modexp_outlen) + + ; ; 7] B != 0, E == 0, M == 0 should return 0 + ; 1 :MSTORE(modexp_Blen) + ; 1 :MSTORE(modexp_Elen) + ; 1 :MSTORE(modexp_Mlen) + + ; 1n :MSTORE(modexp_B) + ; 0n :MSTORE(modexp_E) + ; 0n :MSTORE(modexp_M) + ; :CALL(modexp) + + ; 0n :MLOAD(modexp_out) + ; 1 :MLOAD(modexp_outlen) + + ; 2 :MSTORE(modexp_Blen) + ; 1 :MSTORE(modexp_Elen) + ; 1 :MSTORE(modexp_Mlen) + + ; 0n :MSTORE(modexp_B) + ; 1 => E + ; 1n :MSTORE(modexp_B + E) + ; 0n :MSTORE(modexp_E) + ; 0n :MSTORE(modexp_M) + ; :CALL(modexp) + + ; 0n :MLOAD(modexp_out) + ; 1 :MLOAD(modexp_outlen) + + ; ; 8] B == 0, E == 0, M == 0 should return 0 + ; 1 :MSTORE(modexp_Blen) + ; 1 :MSTORE(modexp_Elen) + ; 1 :MSTORE(modexp_Mlen) + + ; 0n :MSTORE(modexp_B) + ; 0n :MSTORE(modexp_E) + ; 0n :MSTORE(modexp_M) + ; :CALL(modexp) + + ; 0n :MLOAD(modexp_out) + ; 1 :MLOAD(modexp_outlen) + ; ; --------------------------------------------------------------------------------------------- + + ; 256 BITS EXPONENT TESTS + ; --------------------------------------------------------------------------------------------- + ; 1] B == k·M (at any point of the exponentiations) should return 0 + 1 :MSTORE(modexp_Blen) + 1 :MSTORE(modexp_Elen) + 1 :MSTORE(modexp_Mlen) + 4n :MSTORE(modexp_B) + 78n :MSTORE(modexp_E) + 4n :MSTORE(modexp_M) + :CALL(modexp) + 0n :MLOAD(modexp_out) + 1 :MLOAD(modexp_outlen) + + 1 :MSTORE(modexp_Blen) + 1 :MSTORE(modexp_Elen) + 1 :MSTORE(modexp_Mlen) + 8n :MSTORE(modexp_B) + 78n :MSTORE(modexp_E) + 4n :MSTORE(modexp_M) + :CALL(modexp) + 0n :MLOAD(modexp_out) + 1 :MLOAD(modexp_outlen) + + 1 :MSTORE(modexp_Blen) + 1 :MSTORE(modexp_Elen) + 1 :MSTORE(modexp_Mlen) + 2n :MSTORE(modexp_B) + 2n :MSTORE(modexp_E) + 4n :MSTORE(modexp_M) + :CALL(modexp) + 0n :MLOAD(modexp_out) + 1 :MLOAD(modexp_outlen) + + ; 2] B = [100n, 2831023n, 0n, 73916234139162n], E = [2n**256n - 1n], M = [0n, 0n, 8238129386n, 23102318237n] + ; Hamming weight of E is 256 + 4 :MSTORE(modexp_Blen) + 1 :MSTORE(modexp_Elen) + 4 :MSTORE(modexp_Mlen) + + 100n :MSTORE(modexp_B) + 1 => E + 2831023n :MSTORE(modexp_B + E) + 2 => E + 0n :MSTORE(modexp_B + E) + 3 => E + 73916234139162n :MSTORE(modexp_B + E) + 115792089237316195423570985008687907853269984665640564039457584007913129639935n :MSTORE(modexp_E) + 0n :MSTORE(modexp_M) + 1 => E + 0n :MSTORE(modexp_M + E) + 2 => E + 8238129386n :MSTORE(modexp_M + E) + 3 => E + 23102318237n :MSTORE(modexp_M + E) + :CALL(modexp) + 0n :MLOAD(modexp_out) + 1 => E + 0n :MLOAD(modexp_out + E) + 2 => E + 25636070175539943947777314844209202718110211581133019863886488575898865601868n :MLOAD(modexp_out + E) + 3 => E + 4679155145n :MLOAD(modexp_out + E) + 4 :MLOAD(modexp_outlen) + + ; 3] B = [100n, 2831023n, 0n, 73916234139162n, 100n, 2831023n, 0n, 73916234139162n,100n, 2831023n, 0n, 73916234139162n], E = [903741926349715234612309461283471234n], M = [0n, 0n, 8238129386n, 23102318237n, 1892397612351n, 7246598123051n, 8238129386n, 1264591241237897123126n] + ; Hamming weight of E is 120 + 12 :MSTORE(modexp_Blen) + 1 :MSTORE(modexp_Elen) + 8 :MSTORE(modexp_Mlen) + + 100n :MSTORE(modexp_B) + 1 => E + 2831023n :MSTORE(modexp_B + E) + 2 => E + 0n :MSTORE(modexp_B + E) + 3 => E + 73916234139162n :MSTORE(modexp_B + E) + 4 => E + 100n :MSTORE(modexp_B + E) + 5 => E + 2831023n :MSTORE(modexp_B + E) + 6 => E + 0n :MSTORE(modexp_B + E) + 7 => E + 73916234139162n :MSTORE(modexp_B + E) + 8 => E + 100n :MSTORE(modexp_B + E) + 9 => E + 2831023n :MSTORE(modexp_B + E) + 10 => E + 0n :MSTORE(modexp_B + E) + 11 => E + 73916234139162n :MSTORE(modexp_B + E) + 903741926349715234612309461283471234n :MSTORE(modexp_E) + 0n :MSTORE(modexp_M) + 1 => E + 0n :MSTORE(modexp_M + E) + 2 => E + 8238129386n :MSTORE(modexp_M + E) + 3 => E + 23102318237n :MSTORE(modexp_M + E) + 4 => E + 1892397612351n :MSTORE(modexp_M + E) + 5 => E + 7246598123051n :MSTORE(modexp_M + E) + 6 => E + 8238129386n :MSTORE(modexp_M + E) + 7 => E + 1264591241237897123126n :MSTORE(modexp_M + E) + :CALL(modexp) + 0n :MLOAD(modexp_out) + 1 => E + 0n :MLOAD(modexp_out + E) + 2 => E + 14984469305990977542353827078899382678368215018946198341845725551977623627446n :MLOAD(modexp_out + E) + 3 => E + 68986200907052834988812862957862042564780541926701277492865197684364096948359n :MLOAD(modexp_out + E) + 4 => E + 19960171666179366961875030436152164148711578520678689062449823687317995303656n :MLOAD(modexp_out + E) + 5 => E + 10163909190618518832451417682132582498490814809943760852308996448668923869413n :MLOAD(modexp_out + E) + 6 => E + 29735535392706191114764336807325502135962613879333248096358552087717155148899n :MLOAD(modexp_out + E) + 7 => E + 511131288598502431475n :MLOAD(modexp_out + E) + 8 :MLOAD(modexp_outlen) + + ; 4] B = [7n], E = [110n], M = [7719472615821079694904732333912527190217998977709370935963838933860875309329n, 17n] + ; Hamming weight of E is 5 + 1 :MSTORE(modexp_Blen) + 1 :MSTORE(modexp_Elen) + 2 :MSTORE(modexp_Mlen) + + 7n :MSTORE(modexp_B) + 110n :MSTORE(modexp_E) + 7719472615821079694904732333912527190217998977709370935963838933860875309329n :MSTORE(modexp_M) + 1 => E + 17n :MSTORE(modexp_M + E) + :CALL(modexp) + 81730215206688390341255830729934766338330049967253209305087427132484271882414n :MLOAD(modexp_out) + 1 => E + 13n :MLOAD(modexp_out + E) + 2 :MLOAD(modexp_outlen) + ; --------------------------------------------------------------------------------------------- + + ; 512 BITS EXPONENT TESTS + ; --------------------------------------------------------------------------------------------- + ; 1] B = [2n, 1n, 1n, 1n], E = [3n, 5n], M = [4n, 6n, 7n] + ; Hamming weight of E is 4 + 4 :MSTORE(modexp_Blen) + 2 :MSTORE(modexp_Elen) + 3 :MSTORE(modexp_Mlen) + + 2n :MSTORE(modexp_B) + 1 => E + 1n :MSTORE(modexp_B + E) + 2 => E + 1n :MSTORE(modexp_B + E) + 3 => E + 1n :MSTORE(modexp_B + E) + 3n :MSTORE(modexp_E) + 1 => E + 5n :MSTORE(modexp_E + E) + 4n :MSTORE(modexp_M) + 1 => E + 6n :MSTORE(modexp_M + E) + 2 => E + 7n :MSTORE(modexp_M + E) + :CALL(modexp) + 16799222018138169590613227618843456355247327644003751420511040302320945803948n :MLOAD(modexp_out) + 1 => E + 67226185770814561827024093064262870237432709513661454124124794094744315370418n :MLOAD(modexp_out + E) + 2 => E + 1n :MLOAD(modexp_out + E) + 3 :MLOAD(modexp_outlen) + + ; 2] B = [2n, 1n, 1n, 1n], E = [2n**256n - 1n, 2n**256n - 1n], M = [4n, 6n, 7n] + ; Hamming weight of E is 512 + 4 :MSTORE(modexp_Blen) + 2 :MSTORE(modexp_Elen) + 3 :MSTORE(modexp_Mlen) + + 2n :MSTORE(modexp_B) + 1 => E + 1n :MSTORE(modexp_B + E) + 2 => E + 1n :MSTORE(modexp_B + E) + 3 => E + 1n :MSTORE(modexp_B + E) + 115792089237316195423570985008687907853269984665640564039457584007913129639935n :MSTORE(modexp_E) + 1 => E + 115792089237316195423570985008687907853269984665640564039457584007913129639935n :MSTORE(modexp_E + E) + 4n :MSTORE(modexp_M) + 1 => E + 6n :MSTORE(modexp_M + E) + 2 => E + 7n :MSTORE(modexp_M + E) + :CALL(modexp) + 111873638420780286093512129901489267041413036926649390648147612881355784341812n :MLOAD(modexp_out) + 1 => E + 11181991619082508729788448443921623930160246165837402400671610626538926623319n :MLOAD(modexp_out + E) + 2 => E + 2n :MLOAD(modexp_out + E) + 3 :MLOAD(modexp_outlen) + ; --------------------------------------------------------------------------------------------- + + ; 768 BITS EXPONENT TESTS + ; --------------------------------------------------------------------------------------------- + ; --------------------------------------------------------------------------------------------- + + ; 1024 BITS EXPONENT TESTS + ; --------------------------------------------------------------------------------------------- + ; --------------------------------------------------------------------------------------------- + +; ; SINGLETON TESTS TO ENSURE THE MAXIMUM INPUT LENGTH WE CAN ACHIEVE IN EACH OF BASE, EXPONENT +; ; AND MODULUS WITHOUT OVERFLOWING EITHER THE ARITH, BINARY OF STEPS COUNTERS +; ; --------------------------------------------------------------------------------------------- +; ; 1] B = [2n:1818n], E = [1n], M = [2n] +; ; Hamming weight of E is 1 +; 1818 :MSTORE(modexp_Blen) +; 1 :MSTORE(modexp_Elen) +; 1 :MSTORE(modexp_Mlen) + +; 1818 => E +; singleton_test1_copy_in_loop: +; E - 1 => E +; 2 :MSTORE(modexp_B + E) +; E :JMPZ(singleton_test1_modexp, singleton_test1_copy_in_loop) + +; singleton_test1_modexp: +; 1n :MSTORE(modexp_E) +; 2n :MSTORE(modexp_M) +; :CALL(modexp) +; 0n :MLOAD(modexp_out) +; 1 :MLOAD(modexp_outlen) + +; ; 2] B = [2n], E = [1n], M = [2n:1818] +; ; Hamming weight of E is 1 +; 1 :MSTORE(modexp_Blen) +; 1 :MSTORE(modexp_Elen) +; 1818 :MSTORE(modexp_Mlen) + +; 1818 => E +; singleton_test2_copy_in_loop: +; E - 1 => E +; 1 :MSTORE(modexp_M + E) +; E :JMPZ(singleton_test2_modexp, singleton_test2_copy_in_loop) + +; singleton_test2_modexp: +; 2n :MSTORE(modexp_B) +; 1n :MSTORE(modexp_E) +; :CALL(modexp) +; 2n :MLOAD(modexp_out) +; 1 :MLOAD(modexp_outlen) + +; ; 3] B = [2n], E = [1n:1818], M = [2n] +; ; Hamming weight of E is 1818 +; 1 :MSTORE(modexp_Blen) +; 1818 :MSTORE(modexp_Elen) +; 1 :MSTORE(modexp_Mlen) + +; 1818 => E +; singleton_test3_copy_in_loop: +; E - 1 => E +; 1 :MSTORE(modexp_E + E) +; E :JMPZ(singleton_test3_modexp, singleton_test3_copy_in_loop) + +; singleton_test3_modexp: +; 2n :MSTORE(modexp_B) +; 2n :MSTORE(modexp_M) +; :CALL(modexp) +; 0n :MLOAD(modexp_out) +; 1 :MLOAD(modexp_outlen) +; ; --------------------------------------------------------------------------------------------- + + :JMP(end) + +outOfCountersBinary: + ${dump(CNT_BINARY)} :JMP(end) +outOfCountersStep: + ${dump(STEP)} :JMP(end) +outOfCountersArith: + ${dump(CNT_ARITH)} :JMP(end) + +;@info function to force a failed assert +failAssert: + 1 => A + 2 :ASSERT + +end: + + $ => A :MLOAD(initial_A) + $ => B :MLOAD(initial_B) + $ => C :MLOAD(initial_C) + $ => D :MLOAD(initial_D) + $ => E :MLOAD(initial_E) + $ => CTX :MLOAD(initial_CTX) + $ => SP :MLOAD(initial_SP) + $ => PC :MLOAD(initial_PC) + $ => GAS :MLOAD(initial_GAS) + $ => SR :MLOAD(initial_SR) + $ => RR :MLOAD(initial_RR) + $ => HASHPOS :MLOAD(initial_HASHPOS) + $ => RCX :MLOAD(initial_RCX) + +; label finalizeExecution needed by executor C++ +finalizeExecution: + ${beforeLast()} : JMPN(finalizeExecution) + + : JMP(start) +opINVALID: +; label checkAndSaveFrom needed by executor C++ +checkAndSaveFrom: + :JMP(opINVALID) + +INCLUDE "../main/modexp/constants.zkasm" + +INCLUDE "../main/modexp/array_lib/utils/array_trim.zkasm" +INCLUDE "../main/modexp/array_lib/utils/array_compare.zkasm" + +INCLUDE "../main/modexp/array_lib/array_add_AGTB.zkasm" +INCLUDE "../main/modexp/array_lib/array_add_short.zkasm" +INCLUDE "../main/modexp/array_lib/array_mul_long.zkasm" +INCLUDE "../main/modexp/array_lib/array_mul_short.zkasm" +INCLUDE "../main/modexp/array_lib/array_mul.zkasm" +INCLUDE "../main/modexp/array_lib/array_square.zkasm" +INCLUDE "../main/modexp/array_lib/array_div_short.zkasm" +INCLUDE "../main/modexp/array_lib/array_div_long.zkasm" +INCLUDE "../main/modexp/array_lib/array_div.zkasm" + +INCLUDE "../main/modexp/modexp.zkasm" \ No newline at end of file diff --git a/test/testModExpReturn.zkasm b/test/testModExpReturn.zkasm new file mode 100644 index 00000000..cc25ca0c --- /dev/null +++ b/test/testModExpReturn.zkasm @@ -0,0 +1,81 @@ +; constants needed by executor C++ +start: + + STEP => A + 0 :ASSERT + + 2 => CTX + 1 :MSTORE(originCTX) + 2 :MSTORE(currentCTX) + 128 :MSTORE(retCallLength) + 0 :MSTORE(retCallOffset) + 4*32 :MSTORE(modexp_Bsize) + 32 :MSTORE(modexp_Esize) + 4*32 :MSTORE(modexp_Msize) + + CTX => A + + ; 256 BITS EXPONENT TESTS + ; --------------------------------------------------------------------------------------------- + ; 1] B = [100n, 2831023n, 0n, 73916234139162n], E = [2n**256n - 1n], M = [0n, 0n, 8238129386n, 23102318237n] + ; Hamming weight of E is 256 + 4 :MSTORE(modexp_Blen) + 1 :MSTORE(modexp_Elen) + 4 :MSTORE(modexp_Mlen) + + 100n :MSTORE(modexp_B) + 1 => E + 2831023n :MSTORE(modexp_B + E) + 2 => E + 0n :MSTORE(modexp_B + E) + 3 => E + 73916234139162n :MSTORE(modexp_B + E) + 115792089237316195423570985008687907853269984665640564039457584007913129639935n :MSTORE(modexp_E) + 0n :MSTORE(modexp_M) + 1 => E + 0n :MSTORE(modexp_M + E) + 2 => E + 8238129386n :MSTORE(modexp_M + E) + 3 => E + 23102318237n :MSTORE(modexp_M + E) + :JMP(callMODEXP) + +INCLUDE "../main/main.zkasm" + +VAR GLOBAL testModexp1 +VAR GLOBAL testModexp2 +VAR GLOBAL testModexp3 +VAR GLOBAL testModexp4 + +preEnd: + 0n :MLOAD(modexp_out) + 1 => E + 0n :MLOAD(modexp_out + E) + 2 => E + 25636070175539943947777314844209202718110211581133019863886488575898865601868n :MLOAD(modexp_out + E) + 3 => E + 4679155145n :MLOAD(modexp_out + E) + 4 :MLOAD(modexp_outlen) + ; get return data + 1 => CTX + $ => E :MLOAD(retCallOffset),CALL(MLOAD32) + A :MSTORE(testModexp1) + :CALL(MLOAD32) + A :MSTORE(testModexp2) + :CALL(MLOAD32) + A :MSTORE(testModexp3) + :CALL(MLOAD32) + A :MSTORE(testModexp4) + ;assert return data === memory + 2 => CTX + 0 => E :CALL(MLOAD32) + A :MLOAD(testModexp1) + :CALL(MLOAD32) + A :MLOAD(testModexp2) + :CALL(MLOAD32) + A :MLOAD(testModexp3) + :CALL(MLOAD32) + A :MLOAD(testModexp4) + +0 => A,B,C,D,E,CTX, SP, PC, GAS, SR, HASHPOS, RR ; Set all registers to 0 + :JMP(finalizeExecution) \ No newline at end of file diff --git a/test/testPairingBN254.zkasm b/test/testPairingBN254.zkasm new file mode 100644 index 00000000..3a2ed975 --- /dev/null +++ b/test/testPairingBN254.zkasm @@ -0,0 +1,463 @@ +; constants needed by executor C++ +CONST %N = 2**19 +CONST %MAX_CNT_STEPS_LIMIT = %N +CONST %MAX_CNT_ARITH_LIMIT = %N +CONST %MAX_CNT_BINARY_LIMIT = %N +CONST %MAX_CNT_MEM_ALIGN_LIMIT = %N +CONST %MAX_CNT_KECCAK_F_LIMIT = %N +CONST %MAX_CNT_PADDING_PG_LIMIT = %N +CONST %MAX_CNT_POSEIDON_G_LIMIT = %N + +VAR GLOBAL lastHashKId +VAR GLOBAL lastHashPId + +VAR GLOBAL initial_A +VAR GLOBAL initial_B +VAR GLOBAL initial_C +VAR GLOBAL initial_D +VAR GLOBAL initial_E +VAR GLOBAL initial_CTX +VAR GLOBAL initial_SP +VAR GLOBAL initial_PC +VAR GLOBAL initial_GAS +VAR GLOBAL initial_SR +VAR GLOBAL initial_RR +VAR GLOBAL initial_HASHPOS +VAR GLOBAL initial_RCX + +start: + + STEP => A + 0 :ASSERT + + + A :MSTORE(initial_A) + B :MSTORE(initial_B) + C :MSTORE(initial_C) + D :MSTORE(initial_D) + E :MSTORE(initial_E) + CTX :MSTORE(initial_CTX) + SP :MSTORE(initial_SP) + PC :MSTORE(initial_PC) + GAS :MSTORE(initial_GAS) + SR :MSTORE(initial_SR) + RR :MSTORE(initial_RR) + HASHPOS :MSTORE(initial_HASHPOS) + RCX :MSTORE(initial_RCX) + 0 => A,B,C,D,E,CTX, SP, PC, GAS, SR, RR, HASHPOS, RCX + + -1 :MSTORE(lastHashKId) + -1 :MSTORE(lastHashPId) + + ; Generators P,Q + + ; 1] Degenerate tests: e(0,Q) = e(P,0) = e(0,0) = 1 + 0n :MSTORE(pairingBN254_P_x) + 0n :MSTORE(pairingBN254_P_y) + 4351401811647638138392695977895401859084096897123577305203754529537814663109n :MSTORE(pairingBN254_Q_x1) + 2046729899889901964437012741252570163462327955511008570480857952505584629957n :MSTORE(pairingBN254_Q_x2) + 322506915963699862059245473966830598387691259163658767351233132602858049743n :MSTORE(pairingBN254_Q_y1) + 14316075702276096164483565793667862351398527813470041574939773541551376891710n :MSTORE(pairingBN254_Q_y2) + :CALL(pairingBN254) + 1n :MLOAD(pairingBN254_f11_x) + 0n :MLOAD(pairingBN254_f11_y) + 0n :MLOAD(pairingBN254_f12_x) + 0n :MLOAD(pairingBN254_f12_y) + 0n :MLOAD(pairingBN254_f13_x) + 0n :MLOAD(pairingBN254_f13_y) + 0n :MLOAD(pairingBN254_f21_x) + 0n :MLOAD(pairingBN254_f21_y) + 0n :MLOAD(pairingBN254_f22_x) + 0n :MLOAD(pairingBN254_f22_y) + 0n :MLOAD(pairingBN254_f23_x) + 0n :MLOAD(pairingBN254_f23_y) + + 1368015179489954701390400359078579693043519447331113978918064868415326638035n :MSTORE(pairingBN254_P_x) + 9918110051302171585080402603319702774565515993150576347155970296011118125764n :MSTORE(pairingBN254_P_y) + 0n :MSTORE(pairingBN254_Q_x1) + 0n :MSTORE(pairingBN254_Q_x2) + 0n :MSTORE(pairingBN254_Q_y1) + 0n :MSTORE(pairingBN254_Q_y2) + :CALL(pairingBN254) + 1n :MLOAD(pairingBN254_f11_x) + 0n :MLOAD(pairingBN254_f11_y) + 0n :MLOAD(pairingBN254_f12_x) + 0n :MLOAD(pairingBN254_f12_y) + 0n :MLOAD(pairingBN254_f13_x) + 0n :MLOAD(pairingBN254_f13_y) + 0n :MLOAD(pairingBN254_f21_x) + 0n :MLOAD(pairingBN254_f21_y) + 0n :MLOAD(pairingBN254_f22_x) + 0n :MLOAD(pairingBN254_f22_y) + 0n :MLOAD(pairingBN254_f23_x) + 0n :MLOAD(pairingBN254_f23_y) + + 0n :MSTORE(pairingBN254_P_x) + 0n :MSTORE(pairingBN254_P_y) + 0n :MSTORE(pairingBN254_Q_x1) + 0n :MSTORE(pairingBN254_Q_x2) + 0n :MSTORE(pairingBN254_Q_y1) + 0n :MSTORE(pairingBN254_Q_y2) + :CALL(pairingBN254) + 1n :MLOAD(pairingBN254_f11_x) + 0n :MLOAD(pairingBN254_f11_y) + 0n :MLOAD(pairingBN254_f12_x) + 0n :MLOAD(pairingBN254_f12_y) + 0n :MLOAD(pairingBN254_f13_x) + 0n :MLOAD(pairingBN254_f13_y) + 0n :MLOAD(pairingBN254_f21_x) + 0n :MLOAD(pairingBN254_f21_y) + 0n :MLOAD(pairingBN254_f22_x) + 0n :MLOAD(pairingBN254_f22_y) + 0n :MLOAD(pairingBN254_f23_x) + 0n :MLOAD(pairingBN254_f23_y) + + ; 2] P not in range + 21888242871839275222246405745257275088696311157297823662689037894645226208583n :MSTORE(pairingBN254_P_x) + 0n :MSTORE(pairingBN254_P_y) + 1n :MSTORE(pairingBN254_Q_x1) + 2n :MSTORE(pairingBN254_Q_x2) + 3n :MSTORE(pairingBN254_Q_y1) + 4n :MSTORE(pairingBN254_Q_y2) + :CALL(pairingBN254) + 1 => A + 1 :EQ + + 0n :MSTORE(pairingBN254_P_x) + 21888242871839275222246405745257275088696311157297823662689037894645226208583n :MSTORE(pairingBN254_P_y) + 1n :MSTORE(pairingBN254_Q_x1) + 2n :MSTORE(pairingBN254_Q_x2) + 3n :MSTORE(pairingBN254_Q_y1) + 4n :MSTORE(pairingBN254_Q_y2) + :CALL(pairingBN254) + 2 => A + 1 :EQ + + ; 3] Q not in range + 0n :MSTORE(pairingBN254_P_x) + 0n :MSTORE(pairingBN254_P_y) + 21888242871839275222246405745257275088696311157297823662689037894645226208583n :MSTORE(pairingBN254_Q_x1) + 2n :MSTORE(pairingBN254_Q_x2) + 3n :MSTORE(pairingBN254_Q_y1) + 4n :MSTORE(pairingBN254_Q_y2) + :CALL(pairingBN254) + 3 => A + 1 :EQ + + 0n :MSTORE(pairingBN254_P_x) + 0n :MSTORE(pairingBN254_P_y) + 1n :MSTORE(pairingBN254_Q_x1) + 21888242871839275222246405745257275088696311157297823662689037894645226208583n :MSTORE(pairingBN254_Q_x2) + 3n :MSTORE(pairingBN254_Q_y1) + 4n :MSTORE(pairingBN254_Q_y2) + :CALL(pairingBN254) + 4 => A + 1 :EQ + + 0n :MSTORE(pairingBN254_P_x) + 0n :MSTORE(pairingBN254_P_y) + 1n :MSTORE(pairingBN254_Q_x1) + 2n :MSTORE(pairingBN254_Q_x2) + 21888242871839275222246405745257275088696311157297823662689037894645226208583n :MSTORE(pairingBN254_Q_y1) + 4n :MSTORE(pairingBN254_Q_y2) + :CALL(pairingBN254) + 5 => A + 1 :EQ + + 0n :MSTORE(pairingBN254_P_x) + 0n :MSTORE(pairingBN254_P_y) + 1n :MSTORE(pairingBN254_Q_x1) + 2n :MSTORE(pairingBN254_Q_x2) + 3n :MSTORE(pairingBN254_Q_y1) + 21888242871839275222246405745257275088696311157297823662689037894645226208583n :MSTORE(pairingBN254_Q_y2) + :CALL(pairingBN254) + 6 => A + 1 :EQ + + ; 4] P not in G1 + 1n :MSTORE(pairingBN254_P_x) + 1n :MSTORE(pairingBN254_P_y) + 0n :MSTORE(pairingBN254_Q_x1) + 0n :MSTORE(pairingBN254_Q_x2) + 0n :MSTORE(pairingBN254_Q_y1) + 0n :MSTORE(pairingBN254_Q_y2) + :CALL(pairingBN254) + 7 => A + 1 :EQ + + ; 5] Q not in G2 + 0n :MSTORE(pairingBN254_P_x) + 0n :MSTORE(pairingBN254_P_y) + 13952973379259391431794065814946995996741015657664522404741834284791195202656n :MSTORE(pairingBN254_Q_x1) + 10904417650644905372723866879625669404817699819926286815323845522270190436451n :MSTORE(pairingBN254_Q_x2) + 12292403207927938194042684085166933223459250332097452603928615449631462314854n :MSTORE(pairingBN254_Q_y1) + 3535501093699632689489376651381121898720279562088698464643486166587401099479n :MSTORE(pairingBN254_Q_y2) + :CALL(pairingBN254) + 8 => A + 1 :EQ + + ; 6] Bilinearity test: e(2P,12Q) = e(P,12Q)² = e(2P,Q)¹² = e(P,Q)²⁴ = e(12P,2Q) + ; e(2P,12Q) + 1368015179489954701390400359078579693043519447331113978918064868415326638035n :MSTORE(pairingBN254_P_x) + 9918110051302171585080402603319702774565515993150576347155970296011118125764n :MSTORE(pairingBN254_P_y) + 4351401811647638138392695977895401859084096897123577305203754529537814663109n :MSTORE(pairingBN254_Q_x1) + 2046729899889901964437012741252570163462327955511008570480857952505584629957n :MSTORE(pairingBN254_Q_x2) + 322506915963699862059245473966830598387691259163658767351233132602858049743n :MSTORE(pairingBN254_Q_y1) + 14316075702276096164483565793667862351398527813470041574939773541551376891710n :MSTORE(pairingBN254_Q_y2) + :CALL(pairingBN254) + 13413524510323321318921703539856938196252165859353070108808910520379565591578n :MLOAD(pairingBN254_f11_x) + 3548381829456735642031500506306367847474828769923557674325753657986253436214n :MLOAD(pairingBN254_f11_y) + 11258588180307399598255242775094467208478122055367286369273756816466078325984n :MLOAD(pairingBN254_f12_x) + 15692415863664227683780306499051704744181486071132299317385971936570963983778n :MLOAD(pairingBN254_f12_y) + 14331327121685823241734822812072572580994818894715351943735993854561590776973n :MLOAD(pairingBN254_f13_x) + 5829057651356763815288519037751619402051833008237861839412688801032331829766n :MLOAD(pairingBN254_f13_y) + 15475783993587934296880977452723101772140252350911606731569729596277613550216n :MLOAD(pairingBN254_f21_x) + 5097655688415311910623889733978393264040884000272175630800968927057028195666n :MLOAD(pairingBN254_f21_y) + 11451831001542370722617744987566735321553462342240810632153337322850540201855n :MLOAD(pairingBN254_f22_x) + 10214880648406402761779167726229820911960967566000435639888288131094179536430n :MLOAD(pairingBN254_f22_y) + 7513746461017094458199399930075345786758663515755635567834665490471393582925n :MLOAD(pairingBN254_f23_x) + 1522857835029638585907442329762418957365351568194442821861575097484378991036n :MLOAD(pairingBN254_f23_y) + + ; e(P,12Q)² + 1n :MSTORE(pairingBN254_P_x) + 2n :MSTORE(pairingBN254_P_y) + 4351401811647638138392695977895401859084096897123577305203754529537814663109n :MSTORE(pairingBN254_Q_x1) + 2046729899889901964437012741252570163462327955511008570480857952505584629957n :MSTORE(pairingBN254_Q_x2) + 322506915963699862059245473966830598387691259163658767351233132602858049743n :MSTORE(pairingBN254_Q_y1) + 14316075702276096164483565793667862351398527813470041574939773541551376891710n :MSTORE(pairingBN254_Q_y2) + :CALL(pairingBN254) + 2n :MSTORE(expCycloFp12BN254_e) + $ => A :MLOAD(pairingBN254_f11_x) + $ => B :MLOAD(pairingBN254_f11_y) + A :MSTORE(expCycloFp12BN254_a11_x) + B :MSTORE(expCycloFp12BN254_a11_y) + $ => A :MLOAD(pairingBN254_f12_x) + $ => B :MLOAD(pairingBN254_f12_y) + A :MSTORE(expCycloFp12BN254_a12_x) + B :MSTORE(expCycloFp12BN254_a12_y) + $ => A :MLOAD(pairingBN254_f13_x) + $ => B :MLOAD(pairingBN254_f13_y) + A :MSTORE(expCycloFp12BN254_a13_x) + B :MSTORE(expCycloFp12BN254_a13_y) + $ => A :MLOAD(pairingBN254_f21_x) + $ => B :MLOAD(pairingBN254_f21_y) + A :MSTORE(expCycloFp12BN254_a21_x) + B :MSTORE(expCycloFp12BN254_a21_y) + $ => A :MLOAD(pairingBN254_f22_x) + $ => B :MLOAD(pairingBN254_f22_y) + A :MSTORE(expCycloFp12BN254_a22_x) + B :MSTORE(expCycloFp12BN254_a22_y) + $ => A :MLOAD(pairingBN254_f23_x) + $ => B :MLOAD(pairingBN254_f23_y) + A :MSTORE(expCycloFp12BN254_a23_x) + B :MSTORE(expCycloFp12BN254_a23_y) + :CALL(expCycloFp12BN254) + 13413524510323321318921703539856938196252165859353070108808910520379565591578n :MLOAD(expCycloFp12BN254_c11_x) + 3548381829456735642031500506306367847474828769923557674325753657986253436214n :MLOAD(expCycloFp12BN254_c11_y) + 11258588180307399598255242775094467208478122055367286369273756816466078325984n :MLOAD(expCycloFp12BN254_c12_x) + 15692415863664227683780306499051704744181486071132299317385971936570963983778n :MLOAD(expCycloFp12BN254_c12_y) + 14331327121685823241734822812072572580994818894715351943735993854561590776973n :MLOAD(expCycloFp12BN254_c13_x) + 5829057651356763815288519037751619402051833008237861839412688801032331829766n :MLOAD(expCycloFp12BN254_c13_y) + 15475783993587934296880977452723101772140252350911606731569729596277613550216n :MLOAD(expCycloFp12BN254_c21_x) + 5097655688415311910623889733978393264040884000272175630800968927057028195666n :MLOAD(expCycloFp12BN254_c21_y) + 11451831001542370722617744987566735321553462342240810632153337322850540201855n :MLOAD(expCycloFp12BN254_c22_x) + 10214880648406402761779167726229820911960967566000435639888288131094179536430n :MLOAD(expCycloFp12BN254_c22_y) + 7513746461017094458199399930075345786758663515755635567834665490471393582925n :MLOAD(expCycloFp12BN254_c23_x) + 1522857835029638585907442329762418957365351568194442821861575097484378991036n :MLOAD(expCycloFp12BN254_c23_y) + + ; e(2P,Q)¹² + 1368015179489954701390400359078579693043519447331113978918064868415326638035n :MSTORE(pairingBN254_P_x) + 9918110051302171585080402603319702774565515993150576347155970296011118125764n :MSTORE(pairingBN254_P_y) + 10857046999023057135944570762232829481370756359578518086990519993285655852781n :MSTORE(pairingBN254_Q_x1) + 11559732032986387107991004021392285783925812861821192530917403151452391805634n :MSTORE(pairingBN254_Q_x2) + 8495653923123431417604973247489272438418190587263600148770280649306958101930n :MSTORE(pairingBN254_Q_y1) + 4082367875863433681332203403145435568316851327593401208105741076214120093531n :MSTORE(pairingBN254_Q_y2) + :CALL(pairingBN254) + 12n :MSTORE(expCycloFp12BN254_e) + $ => A :MLOAD(pairingBN254_f11_x) + $ => B :MLOAD(pairingBN254_f11_y) + A :MSTORE(expCycloFp12BN254_a11_x) + B :MSTORE(expCycloFp12BN254_a11_y) + $ => A :MLOAD(pairingBN254_f12_x) + $ => B :MLOAD(pairingBN254_f12_y) + A :MSTORE(expCycloFp12BN254_a12_x) + B :MSTORE(expCycloFp12BN254_a12_y) + $ => A :MLOAD(pairingBN254_f13_x) + $ => B :MLOAD(pairingBN254_f13_y) + A :MSTORE(expCycloFp12BN254_a13_x) + B :MSTORE(expCycloFp12BN254_a13_y) + $ => A :MLOAD(pairingBN254_f21_x) + $ => B :MLOAD(pairingBN254_f21_y) + A :MSTORE(expCycloFp12BN254_a21_x) + B :MSTORE(expCycloFp12BN254_a21_y) + $ => A :MLOAD(pairingBN254_f22_x) + $ => B :MLOAD(pairingBN254_f22_y) + A :MSTORE(expCycloFp12BN254_a22_x) + B :MSTORE(expCycloFp12BN254_a22_y) + $ => A :MLOAD(pairingBN254_f23_x) + $ => B :MLOAD(pairingBN254_f23_y) + A :MSTORE(expCycloFp12BN254_a23_x) + B :MSTORE(expCycloFp12BN254_a23_y) + :CALL(expCycloFp12BN254) + 13413524510323321318921703539856938196252165859353070108808910520379565591578n :MLOAD(expCycloFp12BN254_c11_x) + 3548381829456735642031500506306367847474828769923557674325753657986253436214n :MLOAD(expCycloFp12BN254_c11_y) + 11258588180307399598255242775094467208478122055367286369273756816466078325984n :MLOAD(expCycloFp12BN254_c12_x) + 15692415863664227683780306499051704744181486071132299317385971936570963983778n :MLOAD(expCycloFp12BN254_c12_y) + 14331327121685823241734822812072572580994818894715351943735993854561590776973n :MLOAD(expCycloFp12BN254_c13_x) + 5829057651356763815288519037751619402051833008237861839412688801032331829766n :MLOAD(expCycloFp12BN254_c13_y) + 15475783993587934296880977452723101772140252350911606731569729596277613550216n :MLOAD(expCycloFp12BN254_c21_x) + 5097655688415311910623889733978393264040884000272175630800968927057028195666n :MLOAD(expCycloFp12BN254_c21_y) + 11451831001542370722617744987566735321553462342240810632153337322850540201855n :MLOAD(expCycloFp12BN254_c22_x) + 10214880648406402761779167726229820911960967566000435639888288131094179536430n :MLOAD(expCycloFp12BN254_c22_y) + 7513746461017094458199399930075345786758663515755635567834665490471393582925n :MLOAD(expCycloFp12BN254_c23_x) + 1522857835029638585907442329762418957365351568194442821861575097484378991036n :MLOAD(expCycloFp12BN254_c23_y) + + ; e(P,Q)²⁴ + 1n :MSTORE(pairingBN254_P_x) + 2n :MSTORE(pairingBN254_P_y) + 10857046999023057135944570762232829481370756359578518086990519993285655852781n :MSTORE(pairingBN254_Q_x1) + 11559732032986387107991004021392285783925812861821192530917403151452391805634n :MSTORE(pairingBN254_Q_x2) + 8495653923123431417604973247489272438418190587263600148770280649306958101930n :MSTORE(pairingBN254_Q_y1) + 4082367875863433681332203403145435568316851327593401208105741076214120093531n :MSTORE(pairingBN254_Q_y2) + :CALL(pairingBN254) + 24n :MSTORE(expCycloFp12BN254_e) + $ => A :MLOAD(pairingBN254_f11_x) + $ => B :MLOAD(pairingBN254_f11_y) + A :MSTORE(expCycloFp12BN254_a11_x) + B :MSTORE(expCycloFp12BN254_a11_y) + $ => A :MLOAD(pairingBN254_f12_x) + $ => B :MLOAD(pairingBN254_f12_y) + A :MSTORE(expCycloFp12BN254_a12_x) + B :MSTORE(expCycloFp12BN254_a12_y) + $ => A :MLOAD(pairingBN254_f13_x) + $ => B :MLOAD(pairingBN254_f13_y) + A :MSTORE(expCycloFp12BN254_a13_x) + B :MSTORE(expCycloFp12BN254_a13_y) + $ => A :MLOAD(pairingBN254_f21_x) + $ => B :MLOAD(pairingBN254_f21_y) + A :MSTORE(expCycloFp12BN254_a21_x) + B :MSTORE(expCycloFp12BN254_a21_y) + $ => A :MLOAD(pairingBN254_f22_x) + $ => B :MLOAD(pairingBN254_f22_y) + A :MSTORE(expCycloFp12BN254_a22_x) + B :MSTORE(expCycloFp12BN254_a22_y) + $ => A :MLOAD(pairingBN254_f23_x) + $ => B :MLOAD(pairingBN254_f23_y) + A :MSTORE(expCycloFp12BN254_a23_x) + B :MSTORE(expCycloFp12BN254_a23_y) + :CALL(expCycloFp12BN254) + 13413524510323321318921703539856938196252165859353070108808910520379565591578n :MLOAD(expCycloFp12BN254_c11_x) + 3548381829456735642031500506306367847474828769923557674325753657986253436214n :MLOAD(expCycloFp12BN254_c11_y) + 11258588180307399598255242775094467208478122055367286369273756816466078325984n :MLOAD(expCycloFp12BN254_c12_x) + 15692415863664227683780306499051704744181486071132299317385971936570963983778n :MLOAD(expCycloFp12BN254_c12_y) + 14331327121685823241734822812072572580994818894715351943735993854561590776973n :MLOAD(expCycloFp12BN254_c13_x) + 5829057651356763815288519037751619402051833008237861839412688801032331829766n :MLOAD(expCycloFp12BN254_c13_y) + 15475783993587934296880977452723101772140252350911606731569729596277613550216n :MLOAD(expCycloFp12BN254_c21_x) + 5097655688415311910623889733978393264040884000272175630800968927057028195666n :MLOAD(expCycloFp12BN254_c21_y) + 11451831001542370722617744987566735321553462342240810632153337322850540201855n :MLOAD(expCycloFp12BN254_c22_x) + 10214880648406402761779167726229820911960967566000435639888288131094179536430n :MLOAD(expCycloFp12BN254_c22_y) + 7513746461017094458199399930075345786758663515755635567834665490471393582925n :MLOAD(expCycloFp12BN254_c23_x) + 1522857835029638585907442329762418957365351568194442821861575097484378991036n :MLOAD(expCycloFp12BN254_c23_y) + + ; e(12P,2Q) + 17108685722251241369314020928988529881027530433467445791267465866135602972753n :MSTORE(pairingBN254_P_x) + 20666112440056908034039013737427066139426903072479162670940363761207457724060n :MSTORE(pairingBN254_P_y) + 18029695676650738226693292988307914797657423701064905010927197838374790804409n :MSTORE(pairingBN254_Q_x1) + 14583779054894525174450323658765874724019480979794335525732096752006891875705n :MSTORE(pairingBN254_Q_x2) + 2140229616977736810657479771656733941598412651537078903776637920509952744750n :MSTORE(pairingBN254_Q_y1) + 11474861747383700316476719153975578001603231366361248090558603872215261634898n :MSTORE(pairingBN254_Q_y2) + :CALL(pairingBN254) + 13413524510323321318921703539856938196252165859353070108808910520379565591578n :MLOAD(expCycloFp12BN254_c11_x) + 3548381829456735642031500506306367847474828769923557674325753657986253436214n :MLOAD(expCycloFp12BN254_c11_y) + 11258588180307399598255242775094467208478122055367286369273756816466078325984n :MLOAD(expCycloFp12BN254_c12_x) + 15692415863664227683780306499051704744181486071132299317385971936570963983778n :MLOAD(expCycloFp12BN254_c12_y) + 14331327121685823241734822812072572580994818894715351943735993854561590776973n :MLOAD(expCycloFp12BN254_c13_x) + 5829057651356763815288519037751619402051833008237861839412688801032331829766n :MLOAD(expCycloFp12BN254_c13_y) + 15475783993587934296880977452723101772140252350911606731569729596277613550216n :MLOAD(expCycloFp12BN254_c21_x) + 5097655688415311910623889733978393264040884000272175630800968927057028195666n :MLOAD(expCycloFp12BN254_c21_y) + 11451831001542370722617744987566735321553462342240810632153337322850540201855n :MLOAD(expCycloFp12BN254_c22_x) + 10214880648406402761779167726229820911960967566000435639888288131094179536430n :MLOAD(expCycloFp12BN254_c22_y) + 7513746461017094458199399930075345786758663515755635567834665490471393582925n :MLOAD(expCycloFp12BN254_c23_x) + 1522857835029638585907442329762418957365351568194442821861575097484378991036n :MLOAD(expCycloFp12BN254_c23_y) + +end: + + $ => A :MLOAD(initial_A) + $ => B :MLOAD(initial_B) + $ => C :MLOAD(initial_C) + $ => D :MLOAD(initial_D) + $ => E :MLOAD(initial_E) + $ => CTX :MLOAD(initial_CTX) + $ => SP :MLOAD(initial_SP) + $ => PC :MLOAD(initial_PC) + $ => GAS :MLOAD(initial_GAS) + $ => SR :MLOAD(initial_SR) + $ => RR :MLOAD(initial_RR) + $ => HASHPOS :MLOAD(initial_HASHPOS) + $ => RCX :MLOAD(initial_RCX) + +; label finalizeExecution needed by executor C++ +finalizeExecution: + ${beforeLast()} : JMPN(finalizeExecution) + + : JMP(start) +opINVALID: +; label checkAndSaveFrom needed by executor C++ +checkAndSaveFrom: + :JMP(opINVALID) + +INCLUDE "../main/pairings/constants.zkasm" + +INCLUDE "../main/pairings/pairingBN254.zkasm" + +INCLUDE "../main/pairings/FRBN254/reduceFrBN254.zkasm" + +INCLUDE "../main/pairings/FPBN254/addFpBN254.zkasm" +INCLUDE "../main/pairings/FPBN254/mulFpBN254.zkasm" +INCLUDE "../main/pairings/FPBN254/reduceFpBN254.zkasm" + +INCLUDE "../main/pairings/FP2BN254/addFp2BN254.zkasm" +INCLUDE "../main/pairings/FP2BN254/subFp2BN254.zkasm" +INCLUDE "../main/pairings/FP2BN254/mulFp2BN254.zkasm" +INCLUDE "../main/pairings/FP2BN254/squareFp2BN254.zkasm" +INCLUDE "../main/pairings/FP2BN254/escalarMulFp2BN254.zkasm" +INCLUDE "../main/pairings/FP2BN254/invFp2BN254.zkasm" + +INCLUDE "../main/pairings/FP4BN254/squareFp4BN254.zkasm" + +INCLUDE "../main/pairings/FP6BN254/addFp6BN254.zkasm" +INCLUDE "../main/pairings/FP6BN254/subFp6BN254.zkasm" +INCLUDE "../main/pairings/FP6BN254/mulFp6BN254.zkasm" +INCLUDE "../main/pairings/FP6BN254/escalarMulFp6BN254.zkasm" +INCLUDE "../main/pairings/FP6BN254/sparseMulAFp6BN254.zkasm" +INCLUDE "../main/pairings/FP6BN254/sparseMulBFp6BN254.zkasm" +INCLUDE "../main/pairings/FP6BN254/sparseMulCFp6BN254.zkasm" +INCLUDE "../main/pairings/FP6BN254/squareFp6BN254.zkasm" +INCLUDE "../main/pairings/FP6BN254/inverseFp6BN254.zkasm" + +INCLUDE "../main/pairings/FP12BN254/mulFp12BN254.zkasm" +INCLUDE "../main/pairings/FP12BN254/sparseMulAFp12BN254.zkasm" +INCLUDE "../main/pairings/FP12BN254/sparseMulBFp12BN254.zkasm" +INCLUDE "../main/pairings/FP12BN254/squareFp12BN254.zkasm" +INCLUDE "../main/pairings/FP12BN254/inverseFp12BN254.zkasm" +INCLUDE "../main/pairings/FP12BN254/frobFp12BN254.zkasm" +INCLUDE "../main/pairings/FP12BN254/frob2Fp12BN254.zkasm" +INCLUDE "../main/pairings/FP12BN254/frob3Fp12BN254.zkasm" + +INCLUDE "../main/pairings/FP12BN254/CYCLOFP12BN254/xBinDecompBN254.zkasm" +INCLUDE "../main/pairings/FP12BN254/CYCLOFP12BN254/compressFp12BN254.zkasm" +INCLUDE "../main/pairings/FP12BN254/CYCLOFP12BN254/decompressFp12BN254.zkasm" +INCLUDE "../main/pairings/FP12BN254/CYCLOFP12BN254/squareCompCycloFp12BN254.zkasm" +INCLUDE "../main/pairings/FP12BN254/CYCLOFP12BN254/squareCycloFp12BN254.zkasm" +INCLUDE "../main/pairings/FP12BN254/CYCLOFP12BN254/expByXCompCycloFp12BN254.zkasm" + +INCLUDE "../main/pairings/BN254/addPointBN254.zkasm" +INCLUDE "../main/pairings/BN254/escalarMulBN254.zkasm" +INCLUDE "../main/pairings/BN254/lineSamePointsBN254.zkasm" +INCLUDE "../main/pairings/BN254/lineDiffPointsBN254.zkasm" + +INCLUDE "../main/pairings/millerLoopBN254.zkasm" +INCLUDE "../main/pairings/loopLengthBN254.zkasm" +INCLUDE "../main/pairings/finalExpBN254.zkasm" + +INCLUDE "../main/pairings/utilsTests/expCycloFp12BN254.zkasm" \ No newline at end of file diff --git a/test/testPointArithBN254.zkasm b/test/testPointArithBN254.zkasm new file mode 100644 index 00000000..786e05ae --- /dev/null +++ b/test/testPointArithBN254.zkasm @@ -0,0 +1,270 @@ +; constants needed by executor C++ +CONST %N = 2**19 +CONST %MAX_CNT_STEPS_LIMIT = %N +CONST %MAX_CNT_ARITH_LIMIT = %N +CONST %MAX_CNT_BINARY_LIMIT = %N +CONST %MAX_CNT_MEM_ALIGN_LIMIT = %N +CONST %MAX_CNT_KECCAK_F_LIMIT = %N +CONST %MAX_CNT_PADDING_PG_LIMIT = %N +CONST %MAX_CNT_POSEIDON_G_LIMIT = %N + +INCLUDE "../main/pairings/constants.zkasm" + +VAR GLOBAL lastHashKId +VAR GLOBAL lastHashPId + +VAR GLOBAL initial_A +VAR GLOBAL initial_B +VAR GLOBAL initial_C +VAR GLOBAL initial_D +VAR GLOBAL initial_E +VAR GLOBAL initial_CTX +VAR GLOBAL initial_SP +VAR GLOBAL initial_PC +VAR GLOBAL initial_GAS +VAR GLOBAL initial_SR +VAR GLOBAL initial_RR +VAR GLOBAL initial_HASHPOS +VAR GLOBAL initial_RCX + +start: + + STEP => A + 0 :ASSERT + + + A :MSTORE(initial_A) + B :MSTORE(initial_B) + C :MSTORE(initial_C) + D :MSTORE(initial_D) + E :MSTORE(initial_E) + CTX :MSTORE(initial_CTX) + SP :MSTORE(initial_SP) + PC :MSTORE(initial_PC) + GAS :MSTORE(initial_GAS) + SR :MSTORE(initial_SR) + RR :MSTORE(initial_RR) + HASHPOS :MSTORE(initial_HASHPOS) + RCX :MSTORE(initial_RCX) + 0 => A,B,C,D,E,CTX, SP, PC, GAS, SR, RR, HASHPOS, RCX + + -1 :MSTORE(lastHashKId) + -1 :MSTORE(lastHashPId) + + + ; 1] Point addition + ; 0 + 0 = 0 + 0n :MSTORE(addPointBN254_P1_x1) + 0n :MSTORE(addPointBN254_P1_x2) + 0n :MSTORE(addPointBN254_P1_y1) + 0n :MSTORE(addPointBN254_P1_y2) + 0n :MSTORE(addPointBN254_P2_x1) + 0n :MSTORE(addPointBN254_P2_x2) + 0n :MSTORE(addPointBN254_P2_y1) + 0n :MSTORE(addPointBN254_P2_y2) + :CALL(addPointBN254) + 0n :MLOAD(addPointBN254_P3_x1) + 0n :MLOAD(addPointBN254_P3_x2) + 0n :MLOAD(addPointBN254_P3_y1) + 0n :MLOAD(addPointBN254_P3_y2) + + ; 0 + P2 = P2 + 0n :MSTORE(addPointBN254_P1_x1) + 0n :MSTORE(addPointBN254_P1_x2) + 0n :MSTORE(addPointBN254_P1_y1) + 0n :MSTORE(addPointBN254_P1_y2) + 10857046999023057135944570762232829481370756359578518086990519993285655852781n :MSTORE(addPointBN254_P2_x1) + 11559732032986387107991004021392285783925812861821192530917403151452391805634n :MSTORE(addPointBN254_P2_x2) + 8495653923123431417604973247489272438418190587263600148770280649306958101930n :MSTORE(addPointBN254_P2_y1) + 4082367875863433681332203403145435568316851327593401208105741076214120093531n :MSTORE(addPointBN254_P2_y2) + :CALL(addPointBN254) + 10857046999023057135944570762232829481370756359578518086990519993285655852781n :MLOAD(addPointBN254_P3_x1) + 11559732032986387107991004021392285783925812861821192530917403151452391805634n :MLOAD(addPointBN254_P3_x2) + 8495653923123431417604973247489272438418190587263600148770280649306958101930n :MLOAD(addPointBN254_P3_y1) + 4082367875863433681332203403145435568316851327593401208105741076214120093531n :MLOAD(addPointBN254_P3_y2) + + ; P1 + 0 = P1 + 18029695676650738226693292988307914797657423701064905010927197838374790804409n :MSTORE(addPointBN254_P1_x1) + 14583779054894525174450323658765874724019480979794335525732096752006891875705n :MSTORE(addPointBN254_P1_x2) + 2140229616977736810657479771656733941598412651537078903776637920509952744750n :MSTORE(addPointBN254_P1_y1) + 11474861747383700316476719153975578001603231366361248090558603872215261634898n :MSTORE(addPointBN254_P1_y2) + 0n :MSTORE(addPointBN254_P2_x1) + 0n :MSTORE(addPointBN254_P2_x2) + 0n :MSTORE(addPointBN254_P2_y1) + 0n :MSTORE(addPointBN254_P2_y2) + :CALL(addPointBN254) + 18029695676650738226693292988307914797657423701064905010927197838374790804409n :MLOAD(addPointBN254_P3_x1) + 14583779054894525174450323658765874724019480979794335525732096752006891875705n :MLOAD(addPointBN254_P3_x2) + 2140229616977736810657479771656733941598412651537078903776637920509952744750n :MLOAD(addPointBN254_P3_y1) + 11474861747383700316476719153975578001603231366361248090558603872215261634898n :MLOAD(addPointBN254_P3_y2) + + ; P1 + (-P1) = 0 + 10857046999023057135944570762232829481370756359578518086990519993285655852781n :MSTORE(addPointBN254_P1_x1) + 11559732032986387107991004021392285783925812861821192530917403151452391805634n :MSTORE(addPointBN254_P1_x2) + 8495653923123431417604973247489272438418190587263600148770280649306958101930n :MSTORE(addPointBN254_P1_y1) + 4082367875863433681332203403145435568316851327593401208105741076214120093531n :MSTORE(addPointBN254_P1_y2) + 10857046999023057135944570762232829481370756359578518086990519993285655852781n :MSTORE(addPointBN254_P2_x1) + 11559732032986387107991004021392285783925812861821192530917403151452391805634n :MSTORE(addPointBN254_P2_x2) + 13392588948715843804641432497768002650278120570034223513918757245338268106653n :MSTORE(addPointBN254_P2_y1) + 17805874995975841540914202342111839520379459829704422454583296818431106115052n :MSTORE(addPointBN254_P2_y2) + :CALL(addPointBN254) + 0n :MLOAD(addPointBN254_P3_x1) + 0n :MLOAD(addPointBN254_P3_x2) + 0n :MLOAD(addPointBN254_P3_y1) + 0n :MLOAD(addPointBN254_P3_y2) + + ; P1 + P1 = 2·P1 + 10857046999023057135944570762232829481370756359578518086990519993285655852781n :MSTORE(addPointBN254_P1_x1) + 11559732032986387107991004021392285783925812861821192530917403151452391805634n :MSTORE(addPointBN254_P1_x2) + 8495653923123431417604973247489272438418190587263600148770280649306958101930n :MSTORE(addPointBN254_P1_y1) + 4082367875863433681332203403145435568316851327593401208105741076214120093531n :MSTORE(addPointBN254_P1_y2) + 10857046999023057135944570762232829481370756359578518086990519993285655852781n :MSTORE(addPointBN254_P2_x1) + 11559732032986387107991004021392285783925812861821192530917403151452391805634n :MSTORE(addPointBN254_P2_x2) + 8495653923123431417604973247489272438418190587263600148770280649306958101930n :MSTORE(addPointBN254_P2_y1) + 4082367875863433681332203403145435568316851327593401208105741076214120093531n :MSTORE(addPointBN254_P2_y2) + :CALL(addPointBN254) + 18029695676650738226693292988307914797657423701064905010927197838374790804409n :MLOAD(addPointBN254_P3_x1) + 14583779054894525174450323658765874724019480979794335525732096752006891875705n :MLOAD(addPointBN254_P3_x2) + 2140229616977736810657479771656733941598412651537078903776637920509952744750n :MLOAD(addPointBN254_P3_y1) + 11474861747383700316476719153975578001603231366361248090558603872215261634898n :MLOAD(addPointBN254_P3_y2) + + ; P1 + P2 = P3 + 18029695676650738226693292988307914797657423701064905010927197838374790804409n :MSTORE(addPointBN254_P1_x1) + 14583779054894525174450323658765874724019480979794335525732096752006891875705n :MSTORE(addPointBN254_P1_x2) + 2140229616977736810657479771656733941598412651537078903776637920509952744750n :MSTORE(addPointBN254_P1_y1) + 11474861747383700316476719153975578001603231366361248090558603872215261634898n :MSTORE(addPointBN254_P1_y2) + 10857046999023057135944570762232829481370756359578518086990519993285655852781n :MSTORE(addPointBN254_P2_x1) + 11559732032986387107991004021392285783925812861821192530917403151452391805634n :MSTORE(addPointBN254_P2_x2) + 8495653923123431417604973247489272438418190587263600148770280649306958101930n :MSTORE(addPointBN254_P2_y1) + 4082367875863433681332203403145435568316851327593401208105741076214120093531n :MSTORE(addPointBN254_P2_y2) + :CALL(addPointBN254) + 2725019753478801796453339367788033689375851816420509565303521482350756874229n :MLOAD(addPointBN254_P3_x1) + 7273165102799931111715871471550377909735733521218303035754523677688038059653n :MLOAD(addPointBN254_P3_x2) + 2512659008974376214222774206987427162027254181373325676825515531566330959255n :MLOAD(addPointBN254_P3_y1) + 957874124722006818841961785324909313781880061366718538693995380805373202866n :MLOAD(addPointBN254_P3_y2) + + ; 2] Escalar multiplication + 0n :MSTORE(escalarMulBN254_k) + 10857046999023057135944570762232829481370756359578518086990519993285655852781n :MSTORE(escalarMulBN254_P_x1) + 11559732032986387107991004021392285783925812861821192530917403151452391805634n :MSTORE(escalarMulBN254_P_x2) + 8495653923123431417604973247489272438418190587263600148770280649306958101930n :MSTORE(escalarMulBN254_P_y1) + 4082367875863433681332203403145435568316851327593401208105741076214120093531n :MSTORE(escalarMulBN254_P_y2) + :CALL(escalarMulBN254) + 0n :MLOAD(escalarMulBN254_Q_x1) + 0n :MLOAD(escalarMulBN254_Q_x2) + 0n :MLOAD(escalarMulBN254_Q_y1) + 0n :MLOAD(escalarMulBN254_Q_y2) + + %BN254_SIX_TIMES_X_SQ :MSTORE(escalarMulBN254_k) + 0n :MSTORE(escalarMulBN254_P_x1) + 0n :MSTORE(escalarMulBN254_P_x2) + 0n :MSTORE(escalarMulBN254_P_y1) + 0n :MSTORE(escalarMulBN254_P_y2) + :CALL(escalarMulBN254) + 0n :MLOAD(escalarMulBN254_Q_x1) + 0n :MLOAD(escalarMulBN254_Q_x2) + 0n :MLOAD(escalarMulBN254_Q_y1) + 0n :MLOAD(escalarMulBN254_Q_y2) + + %BN254_SIX_TIMES_X_SQ :MSTORE(escalarMulBN254_k) + 10857046999023057135944570762232829481370756359578518086990519993285655852781n :MSTORE(escalarMulBN254_P_x1) + 11559732032986387107991004021392285783925812861821192530917403151452391805634n :MSTORE(escalarMulBN254_P_x2) + 8495653923123431417604973247489272438418190587263600148770280649306958101930n :MSTORE(escalarMulBN254_P_y1) + 4082367875863433681332203403145435568316851327593401208105741076214120093531n :MSTORE(escalarMulBN254_P_y2) + :CALL(escalarMulBN254) + 13824868563399673693405984206252027284526901521624614945388441201916943098448n :MLOAD(escalarMulBN254_Q_x1) + 6070174842523651825461006324987645339257276059765462992338211551285097849152n :MLOAD(escalarMulBN254_Q_x2) + 4224873494559498571787136390356590572898009346319218613936276445484292886657n :MLOAD(escalarMulBN254_Q_y1) + 14979195929948718632567968180703131754953567972706796447883440492471033097811n :MLOAD(escalarMulBN254_Q_y2) + + %BN254_R :MSTORE(escalarMulBN254_k) + 10857046999023057135944570762232829481370756359578518086990519993285655852781n :MSTORE(escalarMulBN254_P_x1) + 11559732032986387107991004021392285783925812861821192530917403151452391805634n :MSTORE(escalarMulBN254_P_x2) + 8495653923123431417604973247489272438418190587263600148770280649306958101930n :MSTORE(escalarMulBN254_P_y1) + 4082367875863433681332203403145435568316851327593401208105741076214120093531n :MSTORE(escalarMulBN254_P_y2) + :CALL(escalarMulBN254) + 0n :MLOAD(escalarMulBN254_Q_x1) + 0n :MLOAD(escalarMulBN254_Q_x2) + 0n :MLOAD(escalarMulBN254_Q_y1) + 0n :MLOAD(escalarMulBN254_Q_y2) + + ; 3] Tangent line to a point + 10857046999023057135944570762232829481370756359578518086990519993285655852781n :MSTORE(lineSamePointsBN254_P_x1) + 11559732032986387107991004021392285783925812861821192530917403151452391805634n :MSTORE(lineSamePointsBN254_P_x2) + 8495653923123431417604973247489272438418190587263600148770280649306958101930n :MSTORE(lineSamePointsBN254_P_y1) + 4082367875863433681332203403145435568316851327593401208105741076214120093531n :MSTORE(lineSamePointsBN254_P_y2) + 1n :MSTORE(lineSamePointsBN254_Q_x) + 2n :MSTORE(lineSamePointsBN254_Q_y) + :CALL(lineSamePointsBN254) + 5866721355212621053956121605984270769408822799517647453365718615957338215267n :MLOAD(lineSamePointsBN254_l11_x) + 10805765471263851218954508755716868212208493914051915959293621483915454724277n :MLOAD(lineSamePointsBN254_l11_y) + 441787448737107494458538247410558220237964585327985295018200621859384744906n :MLOAD(lineSamePointsBN254_l13_x) + 16376088161625424614405301418083801678984212103591999741784373000936238959085n :MLOAD(lineSamePointsBN254_l13_y) + 12094372820654450448173487244699814664976451191756576932392084702582606199137n :MLOAD(lineSamePointsBN254_l22_x) + 16329471503453734725328813612581742273267405310373604832422964304856480374124n :MLOAD(lineSamePointsBN254_l22_y) + + ; 4] Line passing through two different points + 10857046999023057135944570762232829481370756359578518086990519993285655852781n :MSTORE(lineDiffPointsBN254_P1_x1) + 11559732032986387107991004021392285783925812861821192530917403151452391805634n :MSTORE(lineDiffPointsBN254_P1_x2) + 8495653923123431417604973247489272438418190587263600148770280649306958101930n :MSTORE(lineDiffPointsBN254_P1_y1) + 4082367875863433681332203403145435568316851327593401208105741076214120093531n :MSTORE(lineDiffPointsBN254_P1_y2) + 18029695676650738226693292988307914797657423701064905010927197838374790804409n :MSTORE(lineDiffPointsBN254_P2_x1) + 14583779054894525174450323658765874724019480979794335525732096752006891875705n :MSTORE(lineDiffPointsBN254_P2_x2) + 2140229616977736810657479771656733941598412651537078903776637920509952744750n :MSTORE(lineDiffPointsBN254_P2_y1) + 11474861747383700316476719153975578001603231366361248090558603872215261634898n :MSTORE(lineDiffPointsBN254_P2_y2) + 1n :MSTORE(lineDiffPointsBN254_Q_x) + 2n :MSTORE(lineDiffPointsBN254_Q_y) + :CALL(lineDiffPointsBN254) + 14345297355255362181497444452150170632573334682972773847873355690178269903256n :MLOAD(lineDiffPointsBN254_l12_x) + 6048094043816276132918639274747177880187336235946285989629387201109000140142n :MLOAD(lineDiffPointsBN254_l12_y) + 6355424306145694606947493475832538496819777935726521244993642728797005357180n :MLOAD(lineDiffPointsBN254_l22_x) + 14495749000319008587101889994427132655409931118529976780236175098644084667216n :MLOAD(lineDiffPointsBN254_l22_y) + 4617834131706974237889373560251879390068389218389281828469153443366136187126n :MLOAD(lineDiffPointsBN254_l23_x) + 18535807517613687025007129469892030737201813557688282181535107728189048279364n :MLOAD(lineDiffPointsBN254_l23_y) + + +end: + + $ => A :MLOAD(initial_A) + $ => B :MLOAD(initial_B) + $ => C :MLOAD(initial_C) + $ => D :MLOAD(initial_D) + $ => E :MLOAD(initial_E) + $ => CTX :MLOAD(initial_CTX) + $ => SP :MLOAD(initial_SP) + $ => PC :MLOAD(initial_PC) + $ => GAS :MLOAD(initial_GAS) + $ => SR :MLOAD(initial_SR) + $ => RR :MLOAD(initial_RR) + $ => HASHPOS :MLOAD(initial_HASHPOS) + $ => RCX :MLOAD(initial_RCX) + +; label finalizeExecution needed by executor C++ +finalizeExecution: + ${beforeLast()} : JMPN(finalizeExecution) + + : JMP(start) +opINVALID: +; label checkAndSaveFrom needed by executor C++ +checkAndSaveFrom: + :JMP(opINVALID) + + +INCLUDE "../main/pairings/FRBN254/reduceFrBN254.zkasm" + +INCLUDE "../main/pairings/FPBN254/reduceFpBN254.zkasm" +INCLUDE "../main/pairings/FPBN254/addFpBN254.zkasm" +INCLUDE "../main/pairings/FPBN254/subFpBN254.zkasm" +INCLUDE "../main/pairings/FPBN254/mulFpBN254.zkasm" + +INCLUDE "../main/pairings/FP2BN254/addFp2BN254.zkasm" +INCLUDE "../main/pairings/FP2BN254/subFp2BN254.zkasm" +INCLUDE "../main/pairings/FP2BN254/escalarMulFp2BN254.zkasm" +INCLUDE "../main/pairings/FP2BN254/mulFp2BN254.zkasm" +INCLUDE "../main/pairings/FP2BN254/squareFp2BN254.zkasm" +INCLUDE "../main/pairings/FP2BN254/invFp2BN254.zkasm" + +INCLUDE "../main/pairings/BN254/addPointBN254.zkasm" +INCLUDE "../main/pairings/BN254/escalarMulBN254.zkasm" +INCLUDE "../main/pairings/BN254/lineSamePointsBN254.zkasm" +INCLUDE "../main/pairings/BN254/lineDiffPointsBN254.zkasm" \ No newline at end of file diff --git a/test/testSHA256.zkasm b/test/testSHA256.zkasm new file mode 100644 index 00000000..d1b025f1 --- /dev/null +++ b/test/testSHA256.zkasm @@ -0,0 +1,27 @@ + +start: + STEP => A + 0 :ASSERT ; Ensure it is the beginning of the execution + 1 => C :MSTORE(txCalldataLen) + 1 :MSTORE(originCTX) + 1 :MSTORE(calldataCTX) + 1 => CTX + 0 => E + 0xFF00000000000000000000000000000000000000000000000000000000000000n :MSTORE(MEM:E) + + 2 :MSTORE(currentCTX) + 2 => CTX + + $ => E :MLOAD(sha256DataId) + 0 => E :MSTORE(sha256DataOffset) + 0 => HASHPOS + RR :MSTORE(tmpZkSHA256) + :CALL(SHA256data) + $ => E :MLOAD(sha256Hash) + + 0xa8100ae6aa1940d0b663bb31cd466142ebbdbd5187131b92d93818987832eb89n => A + E :ASSERT + + :JMP(finalizeExecution) + +INCLUDE "../main/main.zkasm" diff --git a/tools/gen-parallel-tests.js b/tools/gen-parallel-tests.js index edcb8672..3d03aaef 100644 --- a/tools/gen-parallel-tests.js +++ b/tools/gen-parallel-tests.js @@ -10,7 +10,7 @@ const buildPoseidon = require('@0xpolygonhermez/zkevm-commonjs').getPoseidon; const folderPaths = [ '../node_modules/@0xpolygonhermez/zkevm-testvectors/inputs-executor', - '../node_modules/@0xpolygonhermez/zkevm-testvectors/tools/ethereum-tests/GeneralStateTests', + '../node_modules/@0xpolygonhermez/zkevm-testvectors/inputs-executor/ethereum-tests/GeneralStateTests', ]; const fileCachePil = path.join(__dirname, '../node_modules/@0xpolygonhermez/zkevm-proverjs/cache-main-pil.json'); @@ -41,12 +41,13 @@ async function main() { const inputsPath = path.join(__dirname, folder); fs.readdirSync(inputsPath).forEach((file) => { const filePath = path.join(inputsPath, file); - if (file.endsWith('.json')) { + // Remove json lists that are generated with gen inputs script and are not inputs + if (file.endsWith('.json') && !file.includes('testsOOC-list.json') && !file.includes('tests30M-list.json')) { inputs.push(filePath); - } else if (fs.statSync(filePath).isDirectory()) { + } else if (fs.statSync(filePath).isDirectory() && !filePath.includes('tests-OOC')) { fs.readdirSync(filePath).forEach((subFile) => { const subFilePath = path.join(filePath, subFile); - if (subFile.endsWith('.json')) { + if (subFile.endsWith('.json') && !subFile.includes('testsOOC-list.json') && !subFile.includes('tests30M-list.json')) { inputs.push(subFilePath); } }); diff --git a/tools/get-not-used-labels.js b/tools/get-not-used-labels.js new file mode 100644 index 00000000..f582e0b4 --- /dev/null +++ b/tools/get-not-used-labels.js @@ -0,0 +1,31 @@ +const fs = require('fs'); +const rom = require('../build/rom.json'); + +async function main() { + const labelsAddr = Object.values(rom.labels); + const { program } = rom; + for (let i = 0; i < program.length; i++) { + const { jmpAddr, elseAddr } = program[i]; + if (jmpAddr) { + const indexJmp = labelsAddr.indexOf(jmpAddr); + if (indexJmp !== -1) { + labelsAddr.splice(indexJmp, 1); + } + } + if (elseAddr) { + const indexElse = labelsAddr.indexOf(elseAddr); + if (indexElse !== -1) { + labelsAddr.splice(indexElse, 1); + } + } + } + const filteredLabels = []; + for (let j = 0; j < labelsAddr.length; j++) { + filteredLabels.push(Object.keys(rom.labels).find((key) => rom.labels[key] === labelsAddr[j])); + } + console.log(filteredLabels); + await fs.writeFileSync('no-used-labels.json', JSON.stringify(filteredLabels, null, 2)); + // await fs.writeFileSync('no-used-labelsAddr-Addr.json', JSON.stringify(labelsAddr, null, 2)); +} + +main(); diff --git a/tools/modexp-utils/README.md b/tools/modexp-utils/README.md new file mode 100644 index 00000000..37bd479b --- /dev/null +++ b/tools/modexp-utils/README.md @@ -0,0 +1,5 @@ +## Notes + +The file `modexp-test-gen.js` automatically geneates a zkasm file, executes it some specified number of times and outputs a json file containing the record of the counters. At this moment, it is hardcoded to work for the operation `array_div(array_mul(a, b),c)`, where `a` and `b` was chosen to be $2^{256} - 3$, while `c` was chosen to be $2^{256} - 1$ to achieve the maximum complexity in the operation. + +The `modexp-test-init.sage` takes the counters in the json file and, for each different counter, interpolates the multivariate polynomial (having as evaluation points the lenght of the inputs in the previous file) that evaluates to the counters. \ No newline at end of file diff --git a/tools/modexp-utils/modexp-test-gen.js b/tools/modexp-utils/modexp-test-gen.js new file mode 100644 index 00000000..8079d415 --- /dev/null +++ b/tools/modexp-utils/modexp-test-gen.js @@ -0,0 +1,168 @@ +const fs = require('fs'); +const path = require('path'); +const { execSync } = require('child_process'); + +const filePath = path.join(__dirname, 'tmpTest.zkasm'); + +const fileBefore = +`; constants needed by executor C++ +CONST %N = 2**19 +CONST %MAX_CNT_STEPS_LIMIT = %N +CONST %MAX_CNT_ARITH_LIMIT = %N +CONST %MAX_CNT_BINARY_LIMIT = %N +CONST %MAX_CNT_MEM_ALIGN_LIMIT = %N +CONST %MAX_CNT_KECCAK_F_LIMIT = %N +CONST %MAX_CNT_PADDING_PG_LIMIT = %N +CONST %MAX_CNT_POSEIDON_G_LIMIT = %N + +VAR GLOBAL lastHashKId +VAR GLOBAL lastHashPId + +VAR GLOBAL initial_A +VAR GLOBAL initial_B +VAR GLOBAL initial_C +VAR GLOBAL initial_D +VAR GLOBAL initial_E +VAR GLOBAL initial_CTX +VAR GLOBAL initial_SP +VAR GLOBAL initial_PC +VAR GLOBAL initial_GAS +VAR GLOBAL initial_SR +VAR GLOBAL initial_RR +VAR GLOBAL initial_HASHPOS +VAR GLOBAL initial_RCX + +start: + + STEP => A + 0 :ASSERT + + A :MSTORE(initial_A) + B :MSTORE(initial_B) + C :MSTORE(initial_C) + D :MSTORE(initial_D) + E :MSTORE(initial_E) + CTX :MSTORE(initial_CTX) + SP :MSTORE(initial_SP) + PC :MSTORE(initial_PC) + GAS :MSTORE(initial_GAS) + SR :MSTORE(initial_SR) + RR :MSTORE(initial_RR) + HASHPOS :MSTORE(initial_HASHPOS) + RCX :MSTORE(initial_RCX) + 0 => A,B,C,D,E,CTX, SP, PC, GAS, SR, RR, HASHPOS, RCX + + -1 :MSTORE(lastHashKId) + -1 :MSTORE(lastHashPId) +`; +const fileAfter = +` +end: + + $ => A :MLOAD(initial_A) + $ => B :MLOAD(initial_B) + $ => C :MLOAD(initial_C) + $ => D :MLOAD(initial_D) + $ => E :MLOAD(initial_E) + $ => CTX :MLOAD(initial_CTX) + $ => SP :MLOAD(initial_SP) + $ => PC :MLOAD(initial_PC) + $ => GAS :MLOAD(initial_GAS) + $ => SR :MLOAD(initial_SR) + $ => RR :MLOAD(initial_RR) + $ => HASHPOS :MLOAD(initial_HASHPOS) + $ => RCX :MLOAD(initial_RCX) + +; label finalizeExecution needed by executor C++ +finalizeExecution: + \${beforeLast()} : JMPN(finalizeExecution) + + : JMP(start) +opINVALID: +; label checkAndSaveFrom needed by executor C++ +checkAndSaveFrom: + :JMP(opINVALID) + +INCLUDE "../main/modexp/array_lib/utils/array_trim.zkasm" +INCLUDE "../main/modexp/array_lib/utils/array_compare.zkasm" + +INCLUDE "../main/modexp/array_lib/array_add_AGTB.zkasm" +INCLUDE "../main/modexp/array_lib/array_add_short.zkasm" +INCLUDE "../main/modexp/array_lib/array_mul.zkasm" +INCLUDE "../main/modexp/array_lib/array_mul_long.zkasm" +INCLUDE "../main/modexp/array_lib/array_mul_short.zkasm" +INCLUDE "../main/modexp/array_lib/array_div.zkasm" +INCLUDE "../main/modexp/array_lib/array_div_long.zkasm" +INCLUDE "../main/modexp/array_lib/array_div_short.zkasm" +`; + +const counters = []; + +for (let i = 1; i <= 5; i++) { + for (let j = 1; j <= i; j++) { + for (let k = 1; k <= j; k++) { + console.log(`Test (${i},${j},${k}):`); + + // Define the test + let fileTest1 = `\t${i} => C\n\t${j} => D\n\t115792089237316195423570985008687907853269984665640564039457584007913129639933n :MSTORE(array_mul_inA)\n\t115792089237316195423570985008687907853269984665640564039457584007913129639933n :MSTORE(array_mul_inB)\n` + + for (let l = 1; l < j; l++) { + fileTest1 += `\t${l} => E\n\t115792089237316195423570985008687907853269984665640564039457584007913129639933n :MSTORE(array_mul_inA + E)\n` + fileTest1 += `\t115792089237316195423570985008687907853269984665640564039457584007913129639933n :MSTORE(array_mul_inB + E)\n` + } + + for (let l = j; l < i; l++) { + fileTest1 += `\t${l} => E\n\t115792089237316195423570985008687907853269984665640564039457584007913129639933n :MSTORE(array_mul_inA + E)\n` + } + + const fileTest2 = `\t\t:CALL(array_mul)\n\t${i+j} => C\n\t${k} => D\n\t` + + let fileTest3 =`$ => A :MLOAD(array_mul_out)\n\tA :MSTORE(array_div_inA)\n\t115792089237316195423570985008687907853269984665640564039457584007913129639935n :MSTORE(array_div_inB)\n\t` + + for (let l = 1; l < k; l++) { + fileTest3 += `${l} => E\n\t$ => A :MLOAD(array_mul_out + E)\n\tA :MSTORE(array_div_inA + E)\n\t115792089237316195423570985008687907853269984665640564039457584007913129639935n :MSTORE(array_div_inB + E)\n\t` + } + + for (let l = k; l < i + j; l++) { + fileTest3 += `${l} => E\n\t$ => A :MLOAD(array_mul_out + E)\n\tA :MSTORE(array_div_inA + E)\n\t` + } + + fileTest3 += `:CALL(array_div)\n`; + + const fileTest = fileTest1 + fileTest2 + fileTest3; + + // Create the file + fs.writeFileSync(filePath, fileBefore + fileTest + fileAfter); + + const output = execSync( + `node node_modules/@0xpolygonhermez/zkevm-proverjs/test/zkasmtest.js ${filePath} -H ./main/modexp/helper.js -N "2**24" -d` + ).toString(); + + // Capture the counters + const pattern = /cntArith: (\d+)n,\n cntBinary: (\d+)n,\n cntKeccakF: (\d+)n,\n cntMemAlign: (\d+)n,\n cntPoseidonG: (\d+)n,\n cntPaddingPG: (\d+)n,\n cntSteps: (\d+)/; + const matches = output.match(pattern); + + if (matches) { + const [,cntArith, cntBinary, , , , , cntSteps] = matches.map(Number); + const testCounters = { + lenR: i, + lenB: j, + lenM: k, + cntArith, + cntBinary, + cntSteps, + }; + console.log(testCounters); + counters.push(testCounters); + } else { + console.log('Something wrong happened with the output'); + } + + // Delete the file + fs.unlinkSync(filePath); + } + } +} + +// Write the counters to a JSON file +fs.writeFileSync(path.join(__dirname, 'modexp-counters.json'), JSON.stringify(counters)); diff --git a/tools/modexp-utils/modexp-test-int.sage b/tools/modexp-utils/modexp-test-int.sage new file mode 100644 index 00000000..26b5e2e0 --- /dev/null +++ b/tools/modexp-utils/modexp-test-int.sage @@ -0,0 +1,37 @@ +import json +import os + +dir_path = os.path.dirname(os.path.realpath(__file__)) + +with open(dir_path + '/modexp-counters.json') as f: + data = json.load(f) + +points = [] +valuesArith = [] +valuesBinary = [] +valuesSteps = [] +for i in range(0, len(data)): + points.append([data[i]['lenR'],data[i]['lenB'],data[i]['lenM']]) + valuesArith.append(data[i]['cntArith']) + valuesBinary.append(data[i]['cntBinary']) + valuesSteps.append(data[i]['cntSteps']) + +R. = PolynomialRing(QQ) + +def findInterpolation(points, values): + for i in range(1, 11): + for j in range(1, i+1): + for k in range(1, j+1): + try: + f = R.interpolation([i,j,k], points, values) + return f + except: + pass + +f1 = findInterpolation(points, valuesArith) +f2 = findInterpolation(points, valuesBinary) +f3 = findInterpolation(points, valuesSteps) +print("f1",f1) +print("f2",f2) +print("f3",f3) +print(f1(3,2,1), f2(3,2,1), f3(3,2,1)) \ No newline at end of file diff --git a/tools/parallel-tests-sample/sample.test.js b/tools/parallel-tests-sample/sample.test.js index b3b2b992..178750b4 100644 --- a/tools/parallel-tests-sample/sample.test.js +++ b/tools/parallel-tests-sample/sample.test.js @@ -1,3 +1,6 @@ +/* eslint-disable global-require */ +/* eslint-disable import/no-dynamic-require */ +/* eslint-disable no-use-before-define */ /* eslint-disable import/no-extraneous-dependencies */ /* eslint-disable import/extensions */ /* eslint-disable import/no-unresolved */ @@ -9,6 +12,7 @@ const { newCommitPolsArray } = require('pilcom'); const smMain = require('@0xpolygonhermez/zkevm-proverjs/src/sm/sm_main/sm_main'); let rom = require('../../build/rom.json'); + let stepsN = 2 ** 23; let counters = false; @@ -27,26 +31,32 @@ it(`${nameFile}`, async () => { const pil = JSON.parse(fs.readFileSync(fileCachePil)); const cmPols = newCommitPolsArray(pil); if (input.gasLimit) { - rom = require(`../../build/rom-${input.gasLimit}.test.json`) + rom = require(`../../build/rom-${input.gasLimit}.test.json`); } if (input.stepsN) { - stepsN = input.stepsN + stepsN = input.stepsN; counters = true; } + await runTest(cmPols, stepsN); + + expect(true).to.be.equal(true); +}); + +async function runTest(cmPols, steps) { try { const config = { debug: true, debugInfo: { inputName: path.basename(inputPath), }, - stepsN: stepsN, + stepsN: steps, counters, assertOutputs: true, }; + await smMain.execute(cmPols.Main, input, rom, config); } catch (err) { - fs.writeFileSync(checkerDir, `Failed test ${inputPath}`); + fs.writeFileSync(checkerDir, `Failed test ${inputPath} - ${err}}`); throw err; } - expect(true).to.be.equal(true); -}); +} diff --git a/tools/run-tests-zkasm.js b/tools/run-tests-zkasm.js index 904c1f10..95e8db08 100644 --- a/tools/run-tests-zkasm.js +++ b/tools/run-tests-zkasm.js @@ -22,16 +22,22 @@ async function main() { const pathZkasm = path.join(process.cwd(), process.argv[2]); const files = await getTestFiles(pathZkasm); + let wasFailed = false; // Run all zkasm files // eslint-disable-next-line no-restricted-syntax console.log(chalk.yellow('--> Start running zkasm files')); for (const file of files) { - if (file.includes('ignore')) - continue; - await runTest(file, cmPols); + if (file.includes('ignore')) { continue; } + if (await runTest(file, cmPols) == 1) { + wasFailed = true; + } + } + if (wasFailed) { + process.exit(1); } } +// returns true if test succeed and false if test failed async function runTest(pathTest, cmPols) { // Compile rom const configZkasm = { @@ -40,15 +46,16 @@ async function runTest(pathTest, cmPols) { allowOverwriteLabels: true, }; - const rom = await zkasm.compile(pathTest, null, configZkasm); const config = { debug: true, stepsN: 8388608, assertOutputs: false, }; - + let failed = false; // execute zkasm tests try { + console.log(chalk.blue(' --> start'), pathTest); + const rom = await zkasm.compile(pathTest, null, configZkasm); const result = await smMain.execute(cmPols.Main, emptyInput, rom, config); console.log(chalk.green(' --> pass'), pathTest); if (argv.verbose) { @@ -62,8 +69,11 @@ async function runTest(pathTest, cmPols) { } } catch (e) { console.log(chalk.red(' --> fail'), pathTest); - throw new Error(e); + console.log(e); + failed = true; } + + return failed; } main();