diff --git a/main/ecrecover/addFpEc.zkasm b/main/ecrecover/addFpEc.zkasm index 46af08ef..9fd42436 100644 --- a/main/ecrecover/addFpEc.zkasm +++ b/main/ecrecover/addFpEc.zkasm @@ -23,6 +23,4 @@ addFpEc: ${_addFpEc_AC % const.FPEC} => C ; A + C (256 bits) %FPEC => A - E :ARITH - - :RETURN \ No newline at end of file + E :ARITH,RETURN \ No newline at end of file diff --git a/main/ecrecover/checkSqrtFpEc.zkasm b/main/ecrecover/checkSqrtFpEc.zkasm index 27bd70d3..224eeb69 100644 --- a/main/ecrecover/checkSqrtFpEc.zkasm +++ b/main/ecrecover/checkSqrtFpEc.zkasm @@ -5,13 +5,12 @@ ;; (FpEc-1)/2 = 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffff 7ffffe17 ;; (*) 222 x 1, 1 x 0, 22 x 1, 4 x 0, 1 x 1, 1 x 0, 3 x 1 ;; (*) 222 x SM, S, 22 x SM, 4 x S, 1 x SM, 1 x S, 3 x SM (S=square M=multiplication) -;; +;; BLOCK: 1 2 3 4 5 6 7 ;; (*) 222 + initial initialization ;; ;; return 1 => no sqrts 0 => has solutions ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -VAR GLOBAL checkSqrtFpEc_index VAR GLOBAL checkSqrtFpEc_base VAR GLOBAL checkSqrtFpEc_RR @@ -20,70 +19,1527 @@ checkSqrtFpEc: RR :MSTORE(checkSqrtFpEc_RR) C :MSTORE(checkSqrtFpEc_base) -; 222 x SM - 221 :MSTORE(checkSqrtFpEc_index) -checkSqrtFpEc_Loop1: - :CALL(sqFpEc) - $ => A :MLOAD(checkSqrtFpEc_base) - C => B - :CALL(mulFpEc) - $ => E :MLOAD(checkSqrtFpEc_index) - E - 1 => E :JMPN(checkSqrtFpEc_EndLoop1) - E :MSTORE(checkSqrtFpEc_index) - :JMP(checkSqrtFpEc_Loop1) -checkSqrtFpEc_EndLoop1: - -; 1 x S - :CALL(sqFpEc) - -; 22 x SM - 21 :MSTORE(checkSqrtFpEc_index) -checkSqrtFpEc_Loop2: - :CALL(sqFpEc) - $ => A :MLOAD(checkSqrtFpEc_base) - C => B - :CALL(mulFpEc) - $ => E :MLOAD(checkSqrtFpEc_index) - E - 1 => E :JMPN(checkSqrtFpEc_EndLoop2) - E :MSTORE(checkSqrtFpEc_index) - :JMP(checkSqrtFpEc_Loop2) -checkSqrtFpEc_EndLoop2: - -; 4 x S - 3 :MSTORE(checkSqrtFpEc_index) -checkSqrtFpEc_Loop3: - :CALL(sqFpEc) - $ => E :MLOAD(checkSqrtFpEc_index) - E - 1 => E :JMPN(checkSqrtFpEc_EndLoop3) - E :MSTORE(checkSqrtFpEc_index) - :JMP(checkSqrtFpEc_Loop3) -checkSqrtFpEc_EndLoop3: - -; 1 x SM - :CALL(sqFpEc) - $ => A :MLOAD(checkSqrtFpEc_base) - C => B - :CALL(mulFpEc) + ; === BLOCK1: 1/222 SM === -; 1 x S - :CALL(sqFpEc) + :CALL(sqFpEc) + $ => A :MLOAD(checkSqrtFpEc_base) + C => B :CALL(mulFpEc) -; 3 x SM - 2 :MSTORE(checkSqrtFpEc_index) -checkSqrtFpEc_Loop4: - :CALL(sqFpEc) - $ => A :MLOAD(checkSqrtFpEc_base) - C => B - :CALL(mulFpEc) - $ => E :MLOAD(checkSqrtFpEc_index) - E - 1 => E :JMPN(checkSqrtFpEc_EndLoop4) - E :MSTORE(checkSqrtFpEc_index) - :JMP(checkSqrtFpEc_Loop4) -checkSqrtFpEc_EndLoop4: - C => B - %FPEC_MINUS_ONE => A - $ => A :EQ + ; === BLOCK1: 2/222 SM === - $ => RR :MLOAD(checkSqrtFpEc_RR) - :RETURN + :CALL(sqFpEc) + $ => A :MLOAD(checkSqrtFpEc_base) + C => B :CALL(mulFpEc) + + ; === BLOCK1: 3/222 SM === + + :CALL(sqFpEc) + $ => A :MLOAD(checkSqrtFpEc_base) + C => B :CALL(mulFpEc) + + ; === BLOCK1: 4/222 SM === + + :CALL(sqFpEc) + $ => A :MLOAD(checkSqrtFpEc_base) + C => B :CALL(mulFpEc) + + ; === BLOCK1: 5/222 SM === + + :CALL(sqFpEc) + $ => A :MLOAD(checkSqrtFpEc_base) + C => B :CALL(mulFpEc) + + ; === BLOCK1: 6/222 SM === + + :CALL(sqFpEc) + $ => A :MLOAD(checkSqrtFpEc_base) + C => B :CALL(mulFpEc) + + ; === BLOCK1: 7/222 SM === + + :CALL(sqFpEc) + $ => A :MLOAD(checkSqrtFpEc_base) + C => B :CALL(mulFpEc) + + ; === BLOCK1: 8/222 SM === + + :CALL(sqFpEc) + $ => A :MLOAD(checkSqrtFpEc_base) + C => B :CALL(mulFpEc) + + ; === BLOCK1: 9/222 SM === + + :CALL(sqFpEc) + $ => A :MLOAD(checkSqrtFpEc_base) + C => B :CALL(mulFpEc) + + ; === BLOCK1: 10/222 SM === + + :CALL(sqFpEc) + $ => A :MLOAD(checkSqrtFpEc_base) + C => B :CALL(mulFpEc) + + ; === BLOCK1: 11/222 SM === + + :CALL(sqFpEc) + $ => A :MLOAD(checkSqrtFpEc_base) + C => B :CALL(mulFpEc) + + ; === BLOCK1: 12/222 SM === + + :CALL(sqFpEc) + $ => A :MLOAD(checkSqrtFpEc_base) + C => B :CALL(mulFpEc) + + ; === BLOCK1: 13/222 SM === + + :CALL(sqFpEc) + $ => A :MLOAD(checkSqrtFpEc_base) + C => B :CALL(mulFpEc) + + ; === BLOCK1: 14/222 SM === + + :CALL(sqFpEc) + $ => A :MLOAD(checkSqrtFpEc_base) + C => B :CALL(mulFpEc) + + ; === BLOCK1: 15/222 SM === + + :CALL(sqFpEc) + $ => A :MLOAD(checkSqrtFpEc_base) + C => B :CALL(mulFpEc) + + ; === BLOCK1: 16/222 SM === + + :CALL(sqFpEc) + $ => A :MLOAD(checkSqrtFpEc_base) + C => B :CALL(mulFpEc) + + ; === BLOCK1: 17/222 SM === + + :CALL(sqFpEc) + $ => A :MLOAD(checkSqrtFpEc_base) + C => B :CALL(mulFpEc) + + ; === BLOCK1: 18/222 SM === + + :CALL(sqFpEc) + $ => A :MLOAD(checkSqrtFpEc_base) + C => B :CALL(mulFpEc) + + ; === BLOCK1: 19/222 SM === + + :CALL(sqFpEc) + $ => A :MLOAD(checkSqrtFpEc_base) + C => B :CALL(mulFpEc) + + ; === BLOCK1: 20/222 SM === + + :CALL(sqFpEc) + $ => A :MLOAD(checkSqrtFpEc_base) + C => B :CALL(mulFpEc) + + ; === BLOCK1: 21/222 SM === + + :CALL(sqFpEc) + $ => A :MLOAD(checkSqrtFpEc_base) + C => B :CALL(mulFpEc) + + ; === BLOCK1: 22/222 SM === + + :CALL(sqFpEc) + $ => A :MLOAD(checkSqrtFpEc_base) + C => B :CALL(mulFpEc) + + ; === BLOCK1: 23/222 SM === + + :CALL(sqFpEc) + $ => A :MLOAD(checkSqrtFpEc_base) + C => B :CALL(mulFpEc) + + ; === BLOCK1: 24/222 SM === + + :CALL(sqFpEc) + $ => A :MLOAD(checkSqrtFpEc_base) + C => B :CALL(mulFpEc) + + ; === BLOCK1: 25/222 SM === + + :CALL(sqFpEc) + $ => A :MLOAD(checkSqrtFpEc_base) + C => B :CALL(mulFpEc) + + ; === BLOCK1: 26/222 SM === + + :CALL(sqFpEc) + $ => A :MLOAD(checkSqrtFpEc_base) + C => B :CALL(mulFpEc) + + ; === BLOCK1: 27/222 SM === + + :CALL(sqFpEc) + $ => A :MLOAD(checkSqrtFpEc_base) + C => B :CALL(mulFpEc) + + ; === BLOCK1: 28/222 SM === + + :CALL(sqFpEc) + $ => A :MLOAD(checkSqrtFpEc_base) + C => B :CALL(mulFpEc) + + ; === BLOCK1: 29/222 SM === + + :CALL(sqFpEc) + $ => A :MLOAD(checkSqrtFpEc_base) + C => B :CALL(mulFpEc) + + ; === BLOCK1: 30/222 SM === + + :CALL(sqFpEc) + $ => A :MLOAD(checkSqrtFpEc_base) + C => B :CALL(mulFpEc) + + ; === BLOCK1: 31/222 SM === + + :CALL(sqFpEc) + $ => A :MLOAD(checkSqrtFpEc_base) + C => B :CALL(mulFpEc) + + ; === BLOCK1: 32/222 SM === + + :CALL(sqFpEc) + $ => A :MLOAD(checkSqrtFpEc_base) + C => B :CALL(mulFpEc) + + ; === BLOCK1: 33/222 SM === + + :CALL(sqFpEc) + $ => A :MLOAD(checkSqrtFpEc_base) + C => B :CALL(mulFpEc) + + ; === BLOCK1: 34/222 SM === + + :CALL(sqFpEc) + $ => A :MLOAD(checkSqrtFpEc_base) + C => B :CALL(mulFpEc) + + ; === BLOCK1: 35/222 SM === + + :CALL(sqFpEc) + $ => A :MLOAD(checkSqrtFpEc_base) + C => B :CALL(mulFpEc) + + ; === BLOCK1: 36/222 SM === + + :CALL(sqFpEc) + $ => A :MLOAD(checkSqrtFpEc_base) + C => B :CALL(mulFpEc) + + ; === BLOCK1: 37/222 SM === + + :CALL(sqFpEc) + $ => A :MLOAD(checkSqrtFpEc_base) + C => B :CALL(mulFpEc) + + ; === BLOCK1: 38/222 SM === + + :CALL(sqFpEc) + $ => A :MLOAD(checkSqrtFpEc_base) + C => B :CALL(mulFpEc) + + ; === BLOCK1: 39/222 SM === + + :CALL(sqFpEc) + $ => A :MLOAD(checkSqrtFpEc_base) + C => B :CALL(mulFpEc) + + ; === BLOCK1: 40/222 SM === + + :CALL(sqFpEc) + $ => A :MLOAD(checkSqrtFpEc_base) + C => B :CALL(mulFpEc) + + ; === BLOCK1: 41/222 SM === + + :CALL(sqFpEc) + $ => A :MLOAD(checkSqrtFpEc_base) + C => B :CALL(mulFpEc) + + ; === BLOCK1: 42/222 SM === + + :CALL(sqFpEc) + $ => A :MLOAD(checkSqrtFpEc_base) + C => B :CALL(mulFpEc) + + ; === BLOCK1: 43/222 SM === + + :CALL(sqFpEc) + $ => A :MLOAD(checkSqrtFpEc_base) + C => B :CALL(mulFpEc) + + ; === BLOCK1: 44/222 SM === + + :CALL(sqFpEc) + $ => A :MLOAD(checkSqrtFpEc_base) + C => B :CALL(mulFpEc) + + ; === BLOCK1: 45/222 SM === + + :CALL(sqFpEc) + $ => A :MLOAD(checkSqrtFpEc_base) + C => B :CALL(mulFpEc) + + ; === BLOCK1: 46/222 SM === + + :CALL(sqFpEc) + $ => A :MLOAD(checkSqrtFpEc_base) + C => B :CALL(mulFpEc) + + ; === BLOCK1: 47/222 SM === + + :CALL(sqFpEc) + $ => A :MLOAD(checkSqrtFpEc_base) + C => B :CALL(mulFpEc) + + ; === BLOCK1: 48/222 SM === + + :CALL(sqFpEc) + $ => A :MLOAD(checkSqrtFpEc_base) + C => B :CALL(mulFpEc) + + ; === BLOCK1: 49/222 SM === + + :CALL(sqFpEc) + $ => A :MLOAD(checkSqrtFpEc_base) + C => B :CALL(mulFpEc) + + ; === BLOCK1: 50/222 SM === + + :CALL(sqFpEc) + $ => A :MLOAD(checkSqrtFpEc_base) + C => B :CALL(mulFpEc) + + ; === BLOCK1: 51/222 SM === + + :CALL(sqFpEc) + $ => A :MLOAD(checkSqrtFpEc_base) + C => B :CALL(mulFpEc) + + ; === BLOCK1: 52/222 SM === + + :CALL(sqFpEc) + $ => A :MLOAD(checkSqrtFpEc_base) + C => B :CALL(mulFpEc) + + ; === BLOCK1: 53/222 SM === + + :CALL(sqFpEc) + $ => A :MLOAD(checkSqrtFpEc_base) + C => B :CALL(mulFpEc) + + ; === BLOCK1: 54/222 SM === + + :CALL(sqFpEc) + $ => A :MLOAD(checkSqrtFpEc_base) + C => B :CALL(mulFpEc) + + ; === BLOCK1: 55/222 SM === + + :CALL(sqFpEc) + $ => A :MLOAD(checkSqrtFpEc_base) + C => B :CALL(mulFpEc) + + ; === BLOCK1: 56/222 SM === + + :CALL(sqFpEc) + $ => A :MLOAD(checkSqrtFpEc_base) + C => B :CALL(mulFpEc) + + ; === BLOCK1: 57/222 SM === + + :CALL(sqFpEc) + $ => A :MLOAD(checkSqrtFpEc_base) + C => B :CALL(mulFpEc) + + ; === BLOCK1: 58/222 SM === + + :CALL(sqFpEc) + $ => A :MLOAD(checkSqrtFpEc_base) + C => B :CALL(mulFpEc) + + ; === BLOCK1: 59/222 SM === + + :CALL(sqFpEc) + $ => A :MLOAD(checkSqrtFpEc_base) + C => B :CALL(mulFpEc) + + ; === BLOCK1: 60/222 SM === + + :CALL(sqFpEc) + $ => A :MLOAD(checkSqrtFpEc_base) + C => B :CALL(mulFpEc) + + ; === BLOCK1: 61/222 SM === + + :CALL(sqFpEc) + $ => A :MLOAD(checkSqrtFpEc_base) + C => B :CALL(mulFpEc) + + ; === BLOCK1: 62/222 SM === + + :CALL(sqFpEc) + $ => A :MLOAD(checkSqrtFpEc_base) + C => B :CALL(mulFpEc) + + ; === BLOCK1: 63/222 SM === + + :CALL(sqFpEc) + $ => A :MLOAD(checkSqrtFpEc_base) + C => B :CALL(mulFpEc) + + ; === BLOCK1: 64/222 SM === + + :CALL(sqFpEc) + $ => A :MLOAD(checkSqrtFpEc_base) + C => B :CALL(mulFpEc) + + ; === BLOCK1: 65/222 SM === + + :CALL(sqFpEc) + $ => A :MLOAD(checkSqrtFpEc_base) + C => B :CALL(mulFpEc) + + ; === BLOCK1: 66/222 SM === + + :CALL(sqFpEc) + $ => A :MLOAD(checkSqrtFpEc_base) + C => B :CALL(mulFpEc) + + ; === BLOCK1: 67/222 SM === + + :CALL(sqFpEc) + $ => A :MLOAD(checkSqrtFpEc_base) + C => B :CALL(mulFpEc) + + ; === BLOCK1: 68/222 SM === + + :CALL(sqFpEc) + $ => A :MLOAD(checkSqrtFpEc_base) + C => B :CALL(mulFpEc) + + ; === BLOCK1: 69/222 SM === + + :CALL(sqFpEc) + $ => A :MLOAD(checkSqrtFpEc_base) + C => B :CALL(mulFpEc) + + ; === BLOCK1: 70/222 SM === + + :CALL(sqFpEc) + $ => A :MLOAD(checkSqrtFpEc_base) + C => B :CALL(mulFpEc) + + ; === BLOCK1: 71/222 SM === + + :CALL(sqFpEc) + $ => A :MLOAD(checkSqrtFpEc_base) + C => B :CALL(mulFpEc) + + ; === BLOCK1: 72/222 SM === + + :CALL(sqFpEc) + $ => A :MLOAD(checkSqrtFpEc_base) + C => B :CALL(mulFpEc) + + ; === BLOCK1: 73/222 SM === + + :CALL(sqFpEc) + $ => A :MLOAD(checkSqrtFpEc_base) + C => B :CALL(mulFpEc) + + ; === BLOCK1: 74/222 SM === + + :CALL(sqFpEc) + $ => A :MLOAD(checkSqrtFpEc_base) + C => B :CALL(mulFpEc) + + ; === BLOCK1: 75/222 SM === + + :CALL(sqFpEc) + $ => A :MLOAD(checkSqrtFpEc_base) + C => B :CALL(mulFpEc) + + ; === BLOCK1: 76/222 SM === + + :CALL(sqFpEc) + $ => A :MLOAD(checkSqrtFpEc_base) + C => B :CALL(mulFpEc) + + ; === BLOCK1: 77/222 SM === + + :CALL(sqFpEc) + $ => A :MLOAD(checkSqrtFpEc_base) + C => B :CALL(mulFpEc) + + ; === BLOCK1: 78/222 SM === + + :CALL(sqFpEc) + $ => A :MLOAD(checkSqrtFpEc_base) + C => B :CALL(mulFpEc) + + ; === BLOCK1: 79/222 SM === + + :CALL(sqFpEc) + $ => A :MLOAD(checkSqrtFpEc_base) + C => B :CALL(mulFpEc) + + ; === BLOCK1: 80/222 SM === + + :CALL(sqFpEc) + $ => A :MLOAD(checkSqrtFpEc_base) + C => B :CALL(mulFpEc) + + ; === BLOCK1: 81/222 SM === + + :CALL(sqFpEc) + $ => A :MLOAD(checkSqrtFpEc_base) + C => B :CALL(mulFpEc) + + ; === BLOCK1: 82/222 SM === + + :CALL(sqFpEc) + $ => A :MLOAD(checkSqrtFpEc_base) + C => B :CALL(mulFpEc) + + ; === BLOCK1: 83/222 SM === + + :CALL(sqFpEc) + $ => A :MLOAD(checkSqrtFpEc_base) + C => B :CALL(mulFpEc) + + ; === BLOCK1: 84/222 SM === + + :CALL(sqFpEc) + $ => A :MLOAD(checkSqrtFpEc_base) + C => B :CALL(mulFpEc) + + ; === BLOCK1: 85/222 SM === + + :CALL(sqFpEc) + $ => A :MLOAD(checkSqrtFpEc_base) + C => B :CALL(mulFpEc) + + ; === BLOCK1: 86/222 SM === + + :CALL(sqFpEc) + $ => A :MLOAD(checkSqrtFpEc_base) + C => B :CALL(mulFpEc) + + ; === BLOCK1: 87/222 SM === + + :CALL(sqFpEc) + $ => A :MLOAD(checkSqrtFpEc_base) + C => B :CALL(mulFpEc) + + ; === BLOCK1: 88/222 SM === + + :CALL(sqFpEc) + $ => A :MLOAD(checkSqrtFpEc_base) + C => B :CALL(mulFpEc) + + ; === BLOCK1: 89/222 SM === + + :CALL(sqFpEc) + $ => A :MLOAD(checkSqrtFpEc_base) + C => B :CALL(mulFpEc) + + ; === BLOCK1: 90/222 SM === + + :CALL(sqFpEc) + $ => A :MLOAD(checkSqrtFpEc_base) + C => B :CALL(mulFpEc) + + ; === BLOCK1: 91/222 SM === + + :CALL(sqFpEc) + $ => A :MLOAD(checkSqrtFpEc_base) + C => B :CALL(mulFpEc) + + ; === BLOCK1: 92/222 SM === + + :CALL(sqFpEc) + $ => A :MLOAD(checkSqrtFpEc_base) + C => B :CALL(mulFpEc) + + ; === BLOCK1: 93/222 SM === + + :CALL(sqFpEc) + $ => A :MLOAD(checkSqrtFpEc_base) + C => B :CALL(mulFpEc) + + ; === BLOCK1: 94/222 SM === + + :CALL(sqFpEc) + $ => A :MLOAD(checkSqrtFpEc_base) + C => B :CALL(mulFpEc) + + ; === BLOCK1: 95/222 SM === + + :CALL(sqFpEc) + $ => A :MLOAD(checkSqrtFpEc_base) + C => B :CALL(mulFpEc) + + ; === BLOCK1: 96/222 SM === + + :CALL(sqFpEc) + $ => A :MLOAD(checkSqrtFpEc_base) + C => B :CALL(mulFpEc) + + ; === BLOCK1: 97/222 SM === + + :CALL(sqFpEc) + $ => A :MLOAD(checkSqrtFpEc_base) + C => B :CALL(mulFpEc) + + ; === BLOCK1: 98/222 SM === + + :CALL(sqFpEc) + $ => A :MLOAD(checkSqrtFpEc_base) + C => B :CALL(mulFpEc) + + ; === BLOCK1: 99/222 SM === + + :CALL(sqFpEc) + $ => A :MLOAD(checkSqrtFpEc_base) + C => B :CALL(mulFpEc) + + ; === BLOCK1: 100/222 SM === + + :CALL(sqFpEc) + $ => A :MLOAD(checkSqrtFpEc_base) + C => B :CALL(mulFpEc) + + ; === BLOCK1: 101/222 SM === + + :CALL(sqFpEc) + $ => A :MLOAD(checkSqrtFpEc_base) + C => B :CALL(mulFpEc) + + ; === BLOCK1: 102/222 SM === + + :CALL(sqFpEc) + $ => A :MLOAD(checkSqrtFpEc_base) + C => B :CALL(mulFpEc) + + ; === BLOCK1: 103/222 SM === + + :CALL(sqFpEc) + $ => A :MLOAD(checkSqrtFpEc_base) + C => B :CALL(mulFpEc) + + ; === BLOCK1: 104/222 SM === + + :CALL(sqFpEc) + $ => A :MLOAD(checkSqrtFpEc_base) + C => B :CALL(mulFpEc) + + ; === BLOCK1: 105/222 SM === + + :CALL(sqFpEc) + $ => A :MLOAD(checkSqrtFpEc_base) + C => B :CALL(mulFpEc) + + ; === BLOCK1: 106/222 SM === + + :CALL(sqFpEc) + $ => A :MLOAD(checkSqrtFpEc_base) + C => B :CALL(mulFpEc) + + ; === BLOCK1: 107/222 SM === + + :CALL(sqFpEc) + $ => A :MLOAD(checkSqrtFpEc_base) + C => B :CALL(mulFpEc) + + ; === BLOCK1: 108/222 SM === + + :CALL(sqFpEc) + $ => A :MLOAD(checkSqrtFpEc_base) + C => B :CALL(mulFpEc) + + ; === BLOCK1: 109/222 SM === + + :CALL(sqFpEc) + $ => A :MLOAD(checkSqrtFpEc_base) + C => B :CALL(mulFpEc) + + ; === BLOCK1: 110/222 SM === + + :CALL(sqFpEc) + $ => A :MLOAD(checkSqrtFpEc_base) + C => B :CALL(mulFpEc) + + ; === BLOCK1: 111/222 SM === + + :CALL(sqFpEc) + $ => A :MLOAD(checkSqrtFpEc_base) + C => B :CALL(mulFpEc) + + ; === BLOCK1: 112/222 SM === + + :CALL(sqFpEc) + $ => A :MLOAD(checkSqrtFpEc_base) + C => B :CALL(mulFpEc) + + ; === BLOCK1: 113/222 SM === + + :CALL(sqFpEc) + $ => A :MLOAD(checkSqrtFpEc_base) + C => B :CALL(mulFpEc) + + ; === BLOCK1: 114/222 SM === + + :CALL(sqFpEc) + $ => A :MLOAD(checkSqrtFpEc_base) + C => B :CALL(mulFpEc) + + ; === BLOCK1: 115/222 SM === + + :CALL(sqFpEc) + $ => A :MLOAD(checkSqrtFpEc_base) + C => B :CALL(mulFpEc) + + ; === BLOCK1: 116/222 SM === + + :CALL(sqFpEc) + $ => A :MLOAD(checkSqrtFpEc_base) + C => B :CALL(mulFpEc) + + ; === BLOCK1: 117/222 SM === + + :CALL(sqFpEc) + $ => A :MLOAD(checkSqrtFpEc_base) + C => B :CALL(mulFpEc) + + ; === BLOCK1: 118/222 SM === + + :CALL(sqFpEc) + $ => A :MLOAD(checkSqrtFpEc_base) + C => B :CALL(mulFpEc) + + ; === BLOCK1: 119/222 SM === + + :CALL(sqFpEc) + $ => A :MLOAD(checkSqrtFpEc_base) + C => B :CALL(mulFpEc) + + ; === BLOCK1: 120/222 SM === + + :CALL(sqFpEc) + $ => A :MLOAD(checkSqrtFpEc_base) + C => B :CALL(mulFpEc) + + ; === BLOCK1: 121/222 SM === + + :CALL(sqFpEc) + $ => A :MLOAD(checkSqrtFpEc_base) + C => B :CALL(mulFpEc) + + ; === BLOCK1: 122/222 SM === + + :CALL(sqFpEc) + $ => A :MLOAD(checkSqrtFpEc_base) + C => B :CALL(mulFpEc) + + ; === BLOCK1: 123/222 SM === + + :CALL(sqFpEc) + $ => A :MLOAD(checkSqrtFpEc_base) + C => B :CALL(mulFpEc) + + ; === BLOCK1: 124/222 SM === + + :CALL(sqFpEc) + $ => A :MLOAD(checkSqrtFpEc_base) + C => B :CALL(mulFpEc) + + ; === BLOCK1: 125/222 SM === + + :CALL(sqFpEc) + $ => A :MLOAD(checkSqrtFpEc_base) + C => B :CALL(mulFpEc) + + ; === BLOCK1: 126/222 SM === + + :CALL(sqFpEc) + $ => A :MLOAD(checkSqrtFpEc_base) + C => B :CALL(mulFpEc) + ; === BLOCK1: 127/222 SM === + + :CALL(sqFpEc) + $ => A :MLOAD(checkSqrtFpEc_base) + C => B :CALL(mulFpEc) + + ; === BLOCK1: 128/222 SM === + + :CALL(sqFpEc) + $ => A :MLOAD(checkSqrtFpEc_base) + C => B :CALL(mulFpEc) + + ; === BLOCK1: 129/222 SM === + + :CALL(sqFpEc) + $ => A :MLOAD(checkSqrtFpEc_base) + C => B :CALL(mulFpEc) + + ; === BLOCK1: 130/222 SM === + + :CALL(sqFpEc) + $ => A :MLOAD(checkSqrtFpEc_base) + C => B :CALL(mulFpEc) + + ; === BLOCK1: 131/222 SM === + + :CALL(sqFpEc) + $ => A :MLOAD(checkSqrtFpEc_base) + C => B :CALL(mulFpEc) + + ; === BLOCK1: 132/222 SM === + + :CALL(sqFpEc) + $ => A :MLOAD(checkSqrtFpEc_base) + C => B :CALL(mulFpEc) + + ; === BLOCK1: 133/222 SM === + + :CALL(sqFpEc) + $ => A :MLOAD(checkSqrtFpEc_base) + C => B :CALL(mulFpEc) + + ; === BLOCK1: 134/222 SM === + + :CALL(sqFpEc) + $ => A :MLOAD(checkSqrtFpEc_base) + C => B :CALL(mulFpEc) + + ; === BLOCK1: 135/222 SM === + + :CALL(sqFpEc) + $ => A :MLOAD(checkSqrtFpEc_base) + C => B :CALL(mulFpEc) + + ; === BLOCK1: 136/222 SM === + + :CALL(sqFpEc) + $ => A :MLOAD(checkSqrtFpEc_base) + C => B :CALL(mulFpEc) + + ; === BLOCK1: 137/222 SM === + + :CALL(sqFpEc) + $ => A :MLOAD(checkSqrtFpEc_base) + C => B :CALL(mulFpEc) + + ; === BLOCK1: 138/222 SM === + + :CALL(sqFpEc) + $ => A :MLOAD(checkSqrtFpEc_base) + C => B :CALL(mulFpEc) + + ; === BLOCK1: 139/222 SM === + + :CALL(sqFpEc) + $ => A :MLOAD(checkSqrtFpEc_base) + C => B :CALL(mulFpEc) + + ; === BLOCK1: 140/222 SM === + + :CALL(sqFpEc) + $ => A :MLOAD(checkSqrtFpEc_base) + C => B :CALL(mulFpEc) + + ; === BLOCK1: 141/222 SM === + + :CALL(sqFpEc) + $ => A :MLOAD(checkSqrtFpEc_base) + C => B :CALL(mulFpEc) + + ; === BLOCK1: 142/222 SM === + + :CALL(sqFpEc) + $ => A :MLOAD(checkSqrtFpEc_base) + C => B :CALL(mulFpEc) + + ; === BLOCK1: 143/222 SM === + + :CALL(sqFpEc) + $ => A :MLOAD(checkSqrtFpEc_base) + C => B :CALL(mulFpEc) + + ; === BLOCK1: 144/222 SM === + + :CALL(sqFpEc) + $ => A :MLOAD(checkSqrtFpEc_base) + C => B :CALL(mulFpEc) + + ; === BLOCK1: 145/222 SM === + + :CALL(sqFpEc) + $ => A :MLOAD(checkSqrtFpEc_base) + C => B :CALL(mulFpEc) + + ; === BLOCK1: 146/222 SM === + + :CALL(sqFpEc) + $ => A :MLOAD(checkSqrtFpEc_base) + C => B :CALL(mulFpEc) + + ; === BLOCK1: 147/222 SM === + + :CALL(sqFpEc) + $ => A :MLOAD(checkSqrtFpEc_base) + C => B :CALL(mulFpEc) + + ; === BLOCK1: 148/222 SM === + + :CALL(sqFpEc) + $ => A :MLOAD(checkSqrtFpEc_base) + C => B :CALL(mulFpEc) + + ; === BLOCK1: 149/222 SM === + + :CALL(sqFpEc) + $ => A :MLOAD(checkSqrtFpEc_base) + C => B :CALL(mulFpEc) + + ; === BLOCK1: 150/222 SM === + + :CALL(sqFpEc) + $ => A :MLOAD(checkSqrtFpEc_base) + C => B :CALL(mulFpEc) + + ; === BLOCK1: 151/222 SM === + + :CALL(sqFpEc) + $ => A :MLOAD(checkSqrtFpEc_base) + C => B :CALL(mulFpEc) + + ; === BLOCK1: 152/222 SM === + + :CALL(sqFpEc) + $ => A :MLOAD(checkSqrtFpEc_base) + C => B :CALL(mulFpEc) + + ; === BLOCK1: 153/222 SM === + + :CALL(sqFpEc) + $ => A :MLOAD(checkSqrtFpEc_base) + C => B :CALL(mulFpEc) + + ; === BLOCK1: 154/222 SM === + + :CALL(sqFpEc) + $ => A :MLOAD(checkSqrtFpEc_base) + C => B :CALL(mulFpEc) + + ; === BLOCK1: 155/222 SM === + + :CALL(sqFpEc) + $ => A :MLOAD(checkSqrtFpEc_base) + C => B :CALL(mulFpEc) + + ; === BLOCK1: 156/222 SM === + + :CALL(sqFpEc) + $ => A :MLOAD(checkSqrtFpEc_base) + C => B :CALL(mulFpEc) + + ; === BLOCK1: 157/222 SM === + + :CALL(sqFpEc) + $ => A :MLOAD(checkSqrtFpEc_base) + C => B :CALL(mulFpEc) + + ; === BLOCK1: 158/222 SM === + + :CALL(sqFpEc) + $ => A :MLOAD(checkSqrtFpEc_base) + C => B :CALL(mulFpEc) + + ; === BLOCK1: 159/222 SM === + + :CALL(sqFpEc) + $ => A :MLOAD(checkSqrtFpEc_base) + C => B :CALL(mulFpEc) + + ; === BLOCK1: 160/222 SM === + + :CALL(sqFpEc) + $ => A :MLOAD(checkSqrtFpEc_base) + C => B :CALL(mulFpEc) + + ; === BLOCK1: 161/222 SM === + + :CALL(sqFpEc) + $ => A :MLOAD(checkSqrtFpEc_base) + C => B :CALL(mulFpEc) + + ; === BLOCK1: 162/222 SM === + + :CALL(sqFpEc) + $ => A :MLOAD(checkSqrtFpEc_base) + C => B :CALL(mulFpEc) + + ; === BLOCK1: 163/222 SM === + + :CALL(sqFpEc) + $ => A :MLOAD(checkSqrtFpEc_base) + C => B :CALL(mulFpEc) + + ; === BLOCK1: 164/222 SM === + + :CALL(sqFpEc) + $ => A :MLOAD(checkSqrtFpEc_base) + C => B :CALL(mulFpEc) + + ; === BLOCK1: 165/222 SM === + + :CALL(sqFpEc) + $ => A :MLOAD(checkSqrtFpEc_base) + C => B :CALL(mulFpEc) + + ; === BLOCK1: 166/222 SM === + + :CALL(sqFpEc) + $ => A :MLOAD(checkSqrtFpEc_base) + C => B :CALL(mulFpEc) + + ; === BLOCK1: 167/222 SM === + + :CALL(sqFpEc) + $ => A :MLOAD(checkSqrtFpEc_base) + C => B :CALL(mulFpEc) + + ; === BLOCK1: 168/222 SM === + + :CALL(sqFpEc) + $ => A :MLOAD(checkSqrtFpEc_base) + C => B :CALL(mulFpEc) + + ; === BLOCK1: 169/222 SM === + + :CALL(sqFpEc) + $ => A :MLOAD(checkSqrtFpEc_base) + C => B :CALL(mulFpEc) + + ; === BLOCK1: 170/222 SM === + + :CALL(sqFpEc) + $ => A :MLOAD(checkSqrtFpEc_base) + C => B :CALL(mulFpEc) + + ; === BLOCK1: 171/222 SM === + + :CALL(sqFpEc) + $ => A :MLOAD(checkSqrtFpEc_base) + C => B :CALL(mulFpEc) + + ; === BLOCK1: 172/222 SM === + + :CALL(sqFpEc) + $ => A :MLOAD(checkSqrtFpEc_base) + C => B :CALL(mulFpEc) + + ; === BLOCK1: 173/222 SM === + + :CALL(sqFpEc) + $ => A :MLOAD(checkSqrtFpEc_base) + C => B :CALL(mulFpEc) + + ; === BLOCK1: 174/222 SM === + + :CALL(sqFpEc) + $ => A :MLOAD(checkSqrtFpEc_base) + C => B :CALL(mulFpEc) + + ; === BLOCK1: 175/222 SM === + + :CALL(sqFpEc) + $ => A :MLOAD(checkSqrtFpEc_base) + C => B :CALL(mulFpEc) + + ; === BLOCK1: 176/222 SM === + + :CALL(sqFpEc) + $ => A :MLOAD(checkSqrtFpEc_base) + C => B :CALL(mulFpEc) + + ; === BLOCK1: 177/222 SM === + + :CALL(sqFpEc) + $ => A :MLOAD(checkSqrtFpEc_base) + C => B :CALL(mulFpEc) + + ; === BLOCK1: 178/222 SM === + + :CALL(sqFpEc) + $ => A :MLOAD(checkSqrtFpEc_base) + C => B :CALL(mulFpEc) + + ; === BLOCK1: 179/222 SM === + + :CALL(sqFpEc) + $ => A :MLOAD(checkSqrtFpEc_base) + C => B :CALL(mulFpEc) + + ; === BLOCK1: 180/222 SM === + + :CALL(sqFpEc) + $ => A :MLOAD(checkSqrtFpEc_base) + C => B :CALL(mulFpEc) + + ; === BLOCK1: 181/222 SM === + + :CALL(sqFpEc) + $ => A :MLOAD(checkSqrtFpEc_base) + C => B :CALL(mulFpEc) + + ; === BLOCK1: 182/222 SM === + + :CALL(sqFpEc) + $ => A :MLOAD(checkSqrtFpEc_base) + C => B :CALL(mulFpEc) + + ; === BLOCK1: 183/222 SM === + + :CALL(sqFpEc) + $ => A :MLOAD(checkSqrtFpEc_base) + C => B :CALL(mulFpEc) + + ; === BLOCK1: 184/222 SM === + + :CALL(sqFpEc) + $ => A :MLOAD(checkSqrtFpEc_base) + C => B :CALL(mulFpEc) + + ; === BLOCK1: 185/222 SM === + + :CALL(sqFpEc) + $ => A :MLOAD(checkSqrtFpEc_base) + C => B :CALL(mulFpEc) + + ; === BLOCK1: 186/222 SM === + + :CALL(sqFpEc) + $ => A :MLOAD(checkSqrtFpEc_base) + C => B :CALL(mulFpEc) + + ; === BLOCK1: 187/222 SM === + + :CALL(sqFpEc) + $ => A :MLOAD(checkSqrtFpEc_base) + C => B :CALL(mulFpEc) + + ; === BLOCK1: 188/222 SM === + + :CALL(sqFpEc) + $ => A :MLOAD(checkSqrtFpEc_base) + C => B :CALL(mulFpEc) + + ; === BLOCK1: 189/222 SM === + + :CALL(sqFpEc) + $ => A :MLOAD(checkSqrtFpEc_base) + C => B :CALL(mulFpEc) + + ; === BLOCK1: 190/222 SM === + + :CALL(sqFpEc) + $ => A :MLOAD(checkSqrtFpEc_base) + C => B :CALL(mulFpEc) + + ; === BLOCK1: 191/222 SM === + + :CALL(sqFpEc) + $ => A :MLOAD(checkSqrtFpEc_base) + C => B :CALL(mulFpEc) + + ; === BLOCK1: 192/222 SM === + + :CALL(sqFpEc) + $ => A :MLOAD(checkSqrtFpEc_base) + C => B :CALL(mulFpEc) + + ; === BLOCK1: 193/222 SM === + + :CALL(sqFpEc) + $ => A :MLOAD(checkSqrtFpEc_base) + C => B :CALL(mulFpEc) + + ; === BLOCK1: 194/222 SM === + + :CALL(sqFpEc) + $ => A :MLOAD(checkSqrtFpEc_base) + C => B :CALL(mulFpEc) + + ; === BLOCK1: 195/222 SM === + + :CALL(sqFpEc) + $ => A :MLOAD(checkSqrtFpEc_base) + C => B :CALL(mulFpEc) + + ; === BLOCK1: 196/222 SM === + + :CALL(sqFpEc) + $ => A :MLOAD(checkSqrtFpEc_base) + C => B :CALL(mulFpEc) + + ; === BLOCK1: 197/222 SM === + + :CALL(sqFpEc) + $ => A :MLOAD(checkSqrtFpEc_base) + C => B :CALL(mulFpEc) + + ; === BLOCK1: 198/222 SM === + + :CALL(sqFpEc) + $ => A :MLOAD(checkSqrtFpEc_base) + C => B :CALL(mulFpEc) + + ; === BLOCK1: 199/222 SM === + + :CALL(sqFpEc) + $ => A :MLOAD(checkSqrtFpEc_base) + C => B :CALL(mulFpEc) + + ; === BLOCK1: 200/222 SM === + + :CALL(sqFpEc) + $ => A :MLOAD(checkSqrtFpEc_base) + C => B :CALL(mulFpEc) + + ; === BLOCK1: 201/222 SM === + + :CALL(sqFpEc) + $ => A :MLOAD(checkSqrtFpEc_base) + C => B :CALL(mulFpEc) + + ; === BLOCK1: 202/222 SM === + + :CALL(sqFpEc) + $ => A :MLOAD(checkSqrtFpEc_base) + C => B :CALL(mulFpEc) + + ; === BLOCK1: 203/222 SM === + + :CALL(sqFpEc) + $ => A :MLOAD(checkSqrtFpEc_base) + C => B :CALL(mulFpEc) + + ; === BLOCK1: 204/222 SM === + + :CALL(sqFpEc) + $ => A :MLOAD(checkSqrtFpEc_base) + C => B :CALL(mulFpEc) + + ; === BLOCK1: 205/222 SM === + + :CALL(sqFpEc) + $ => A :MLOAD(checkSqrtFpEc_base) + C => B :CALL(mulFpEc) + + ; === BLOCK1: 206/222 SM === + + :CALL(sqFpEc) + $ => A :MLOAD(checkSqrtFpEc_base) + C => B :CALL(mulFpEc) + + ; === BLOCK1: 207/222 SM === + + :CALL(sqFpEc) + $ => A :MLOAD(checkSqrtFpEc_base) + C => B :CALL(mulFpEc) + + ; === BLOCK1: 208/222 SM === + + :CALL(sqFpEc) + $ => A :MLOAD(checkSqrtFpEc_base) + C => B :CALL(mulFpEc) + + ; === BLOCK1: 209/222 SM === + + :CALL(sqFpEc) + $ => A :MLOAD(checkSqrtFpEc_base) + C => B :CALL(mulFpEc) + + ; === BLOCK1: 210/222 SM === + + :CALL(sqFpEc) + $ => A :MLOAD(checkSqrtFpEc_base) + C => B :CALL(mulFpEc) + + ; === BLOCK1: 211/222 SM === + + :CALL(sqFpEc) + $ => A :MLOAD(checkSqrtFpEc_base) + C => B :CALL(mulFpEc) + + ; === BLOCK1: 212/222 SM === + + :CALL(sqFpEc) + $ => A :MLOAD(checkSqrtFpEc_base) + C => B :CALL(mulFpEc) + + ; === BLOCK1: 213/222 SM === + + :CALL(sqFpEc) + $ => A :MLOAD(checkSqrtFpEc_base) + C => B :CALL(mulFpEc) + + ; === BLOCK1: 214/222 SM === + + :CALL(sqFpEc) + $ => A :MLOAD(checkSqrtFpEc_base) + C => B :CALL(mulFpEc) + + ; === BLOCK1: 215/222 SM === + + :CALL(sqFpEc) + $ => A :MLOAD(checkSqrtFpEc_base) + C => B :CALL(mulFpEc) + + ; === BLOCK1: 216/222 SM === + + :CALL(sqFpEc) + $ => A :MLOAD(checkSqrtFpEc_base) + C => B :CALL(mulFpEc) + + ; === BLOCK1: 217/222 SM === + + :CALL(sqFpEc) + $ => A :MLOAD(checkSqrtFpEc_base) + C => B :CALL(mulFpEc) + + ; === BLOCK1: 218/222 SM === + + :CALL(sqFpEc) + $ => A :MLOAD(checkSqrtFpEc_base) + C => B :CALL(mulFpEc) + + ; === BLOCK1: 219/222 SM === + + :CALL(sqFpEc) + $ => A :MLOAD(checkSqrtFpEc_base) + C => B :CALL(mulFpEc) + + ; === BLOCK1: 220/222 SM === + + :CALL(sqFpEc) + $ => A :MLOAD(checkSqrtFpEc_base) + C => B :CALL(mulFpEc) + + ; === BLOCK1: 221/222 SM === + + :CALL(sqFpEc) + $ => A :MLOAD(checkSqrtFpEc_base) + C => B :CALL(mulFpEc) + + ; === BLOCK1: 222/222 SM === + + :CALL(sqFpEc) + $ => A :MLOAD(checkSqrtFpEc_base) + C => B :CALL(mulFpEc) + + + + ; === BLOCK2: 1/1 S === + + :CALL(sqFpEc) + + + + ; === BLOCK3: 1/22 SM === + + :CALL(sqFpEc) + $ => A :MLOAD(checkSqrtFpEc_base) + C => B :CALL(mulFpEc) + + ; === BLOCK3: 2/22 SM === + + :CALL(sqFpEc) + $ => A :MLOAD(checkSqrtFpEc_base) + C => B :CALL(mulFpEc) + + ; === BLOCK3: 3/22 SM === + + :CALL(sqFpEc) + $ => A :MLOAD(checkSqrtFpEc_base) + C => B :CALL(mulFpEc) + + ; === BLOCK3: 4/22 SM === + + :CALL(sqFpEc) + $ => A :MLOAD(checkSqrtFpEc_base) + C => B :CALL(mulFpEc) + + ; === BLOCK3: 5/22 SM === + + :CALL(sqFpEc) + $ => A :MLOAD(checkSqrtFpEc_base) + C => B :CALL(mulFpEc) + + ; === BLOCK3: 6/22 SM === + + :CALL(sqFpEc) + $ => A :MLOAD(checkSqrtFpEc_base) + C => B :CALL(mulFpEc) + + ; === BLOCK3: 7/22 SM === + + :CALL(sqFpEc) + $ => A :MLOAD(checkSqrtFpEc_base) + C => B :CALL(mulFpEc) + + ; === BLOCK3: 8/22 SM === + + :CALL(sqFpEc) + $ => A :MLOAD(checkSqrtFpEc_base) + C => B :CALL(mulFpEc) + + ; === BLOCK3: 9/22 SM === + + :CALL(sqFpEc) + $ => A :MLOAD(checkSqrtFpEc_base) + C => B :CALL(mulFpEc) + + ; === BLOCK3: 10/22 SM === + + :CALL(sqFpEc) + $ => A :MLOAD(checkSqrtFpEc_base) + C => B :CALL(mulFpEc) + + ; === BLOCK3: 11/22 SM === + + :CALL(sqFpEc) + $ => A :MLOAD(checkSqrtFpEc_base) + C => B :CALL(mulFpEc) + + ; === BLOCK3: 12/22 SM === + + :CALL(sqFpEc) + $ => A :MLOAD(checkSqrtFpEc_base) + C => B :CALL(mulFpEc) + + ; === BLOCK3: 13/22 SM === + + :CALL(sqFpEc) + $ => A :MLOAD(checkSqrtFpEc_base) + C => B :CALL(mulFpEc) + + ; === BLOCK3: 14/22 SM === + + :CALL(sqFpEc) + $ => A :MLOAD(checkSqrtFpEc_base) + C => B :CALL(mulFpEc) + + ; === BLOCK3: 15/22 SM === + + :CALL(sqFpEc) + $ => A :MLOAD(checkSqrtFpEc_base) + C => B :CALL(mulFpEc) + + ; === BLOCK3: 16/22 SM === + + :CALL(sqFpEc) + $ => A :MLOAD(checkSqrtFpEc_base) + C => B :CALL(mulFpEc) + + ; === BLOCK3: 17/22 SM === + + :CALL(sqFpEc) + $ => A :MLOAD(checkSqrtFpEc_base) + C => B :CALL(mulFpEc) + + ; === BLOCK3: 18/22 SM === + + :CALL(sqFpEc) + $ => A :MLOAD(checkSqrtFpEc_base) + C => B :CALL(mulFpEc) + + ; === BLOCK3: 19/22 SM === + + :CALL(sqFpEc) + $ => A :MLOAD(checkSqrtFpEc_base) + C => B :CALL(mulFpEc) + + ; === BLOCK3: 20/22 SM === + + :CALL(sqFpEc) + $ => A :MLOAD(checkSqrtFpEc_base) + C => B :CALL(mulFpEc) + + ; === BLOCK3: 21/22 SM === + + :CALL(sqFpEc) + $ => A :MLOAD(checkSqrtFpEc_base) + C => B :CALL(mulFpEc) + + ; === BLOCK3: 22/22 SM === + + :CALL(sqFpEc) + $ => A :MLOAD(checkSqrtFpEc_base) + C => B :CALL(mulFpEc) + + + ; === BLOCK4: 1/4 S === + + :CALL(sqFpEc) + + ; === BLOCK4: 2/4 S === + + :CALL(sqFpEc) + + ; === BLOCK4: 3/4 S === + + :CALL(sqFpEc) + + ; === BLOCK4: 4/4 S === + + :CALL(sqFpEc) + + + ; === BLOCK5: 1/1 SM === + + :CALL(sqFpEc) + $ => A :MLOAD(checkSqrtFpEc_base) + C => B :CALL(mulFpEc) + + + ; === BLOCK6: 1 SM === + + :CALL(sqFpEc) + + ; === BLOCK7: 1/3 SM === + + :CALL(sqFpEc) + $ => A :MLOAD(checkSqrtFpEc_base) + C => B :CALL(mulFpEc) + + ; === BLOCK7: 2/3 SM === + + :CALL(sqFpEc) + $ => A :MLOAD(checkSqrtFpEc_base) + C => B :CALL(mulFpEc) + + ; === BLOCK7: 3/3 SM === + + :CALL(sqFpEc) + $ => A :MLOAD(checkSqrtFpEc_base) + C => B :CALL(mulFpEc) + + + C => B + %FPEC_MINUS_ONE => A + $ => RR :MLOAD(checkSqrtFpEc_RR) + $ => A :EQ,RETURN diff --git a/main/ecrecover/constEc.zkasm b/main/ecrecover/constEc.zkasm index 25bc991c..f17f43a2 100644 --- a/main/ecrecover/constEc.zkasm +++ b/main/ecrecover/constEc.zkasm @@ -1,5 +1,6 @@ CONSTL %FPEC = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2Fn CONSTL %FPEC_MINUS_ONE = %FPEC - 1 +CONSTL %FNEC_DIV_TWO = 57896044618658097711785492504343953926418782139537452191302581570759080747169n CONSTL %FPEC_C2_256 = 0x1000003D1n CONSTL %FPEC_NON_SQRT = (1n << 256n) - 1n diff --git a/main/ecrecover/ecrecover.zkasm b/main/ecrecover/ecrecover.zkasm index aa4492ea..aeb467c7 100644 --- a/main/ecrecover/ecrecover.zkasm +++ b/main/ecrecover/ecrecover.zkasm @@ -1,7 +1,7 @@ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; -;; ecrecover A = hash, B = r, C = s, D = v -;; E = result +;; ecrecover in: A = hash, B = r, C = s, D = v +;; out: A = result, B = result_code ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; @@ -16,10 +16,12 @@ VAR GLOBAL ecrecover_k1 VAR GLOBAL ecrecover_k2 VAR GLOBAL ecrecover_RR VAR GLOBAL ecrecover_v_parity +VAR GLOBAL ecrecover_s_upperlimit INCLUDE "constEc.zkasm" -; ERROR CODES +; ERROR CODES (B) +; 0 - no error ; 1 - r is zero (0) ; 2 - r is too big ; 3 - s is zero (0) @@ -28,17 +30,23 @@ INCLUDE "constEc.zkasm" ; 6 - not exists sqrt of y ; 100 - fail sqrt, but has solution (!!!) -ecrecover: +ecrecover_precompiled: + %FNEC_MINUS_ONE :MSTORE(ecrecover_s_upperlimit),JMP(ecrecover_store_args) - %MAX_CNT_BINARY - CNT_BINARY - 800 :JMPN(outOfCountersBinary) - %MAX_CNT_ARITH - CNT_ARITH - 500 :JMPN(outOfCountersArith) +ecrecover_tx: + %FNEC_DIV_TWO :MSTORE(ecrecover_s_upperlimit) + +ecrecover_store_args: + + %MAX_CNT_BINARY - CNT_BINARY - 1100 :JMPN(outOfCountersBinary) + %MAX_CNT_ARITH - CNT_ARITH - 1100 :JMPN(outOfCountersArith) + %MAX_CNT_STEPS - STEP - 6400 :JMPN(outOfCountersStep) A :MSTORE(ecrecover_hash) B :MSTORE(ecrecover_r) C :MSTORE(ecrecover_s) D :MSTORE(ecrecover_v) -ecrecover_params_by_var: ; save RR to call return at end of routine RR :MSTORE(ecrecover_RR) @@ -50,65 +58,54 @@ ecrecover_params_by_var: $ :LT,JMPC(ecrecover_r_is_too_big) - ; s in [1, FNEC-1] + ; s in [1, ecrecover_s_upperlimit] + $ => A :MLOAD(ecrecover_s_upperlimit) $ => B :MLOAD(ecrecover_s) $ :LT,JMPC(ecrecover_s_is_too_big) 0n => A $ :EQ,JMPC(ecrecover_s_is_zero) ; r and s in [1, FNEC-1] - $ => A :MLOAD(ecrecover_r) - - :CALL(invFnEc) + $ => A :MLOAD(ecrecover_r),CALL(invFnEc) B :MSTORE(ecrecover_r_inv) 0x1Bn => B $ => A :MLOAD(ecrecover_v) - $ => E :EQ - - E - 1 :JMPN(ecrecover_v_not_eq_1b) + $ => E :EQ,JMPNC(ecrecover_v_not_eq_1b) ; ecrecover_v_eq_1b: - 0n :MSTORE(ecrecover_v_parity) - :JMP(ecrecover_v_ok) + 0n :MSTORE(ecrecover_v_parity),JMP(ecrecover_v_ok) ecrecover_v_not_eq_1b: 0x1Cn => B - $ => E :EQ - E - 1 :JMPN(ecrecover_v_not_eq_1b1c) + $ => E :EQ,JMPNC(ecrecover_v_not_eq_1b1c) ; ecrecover_v_eq_1c: - 1n :MSTORE(ecrecover_v_parity) - :JMP(ecrecover_v_ok) + 1n :MSTORE(ecrecover_v_parity),JMP(ecrecover_v_ok) ecrecover_v_ok: + ; + ; y^2 = x^3 + 7 + ; ; A*B*A + 7 = calculate y from x - $ => A,B :MLOAD(ecrecover_r) - :CALL(mulFpEc) + $ => A,B :MLOAD(ecrecover_r),CALL(mulFpEc) C => A - $ => B :MLOAD(ecrecover_r) - :CALL(mulFpEc) + $ => B :MLOAD(ecrecover_r),CALL(mulFpEc) - 7 => A - :CALL(addFpEc) + 7 => A :CALL(addFpEc) - ;; ----- A * 2**31 + B * 2**31 :JMPN(end) + C :MSTORE(ecrecover_y2),CALL(sqrtFpEc) - C :MSTORE(ecrecover_y2) - - ;; TODO: VERIFICATE ROOT ;; If has root y ** (p-1)/2 = 1, if -1 => no root, not valid signature - :CALL(sqrtFpEc) + %FPEC_NON_SQRT => A C => B - $ => E :EQ - E - 1 :JMPN(ecrecover_has_sqrt) + $ => E :EQ,JMPNC(ecrecover_has_sqrt) ; hasn't sqrt, now verify - $ => C :MLOAD(ecrecover_y2) - :CALL(checkSqrtFpEc) + $ => C :MLOAD(ecrecover_y2),CALL(checkSqrtFpEc) ; check must return on A register 1, because the root has no solution 1 :ASSERT,JMP(ecrecover_not_exists_sqrt_of_y) @@ -117,13 +114,12 @@ ecrecover_has_sqrt: ; (v == 1c) ecrecover_y_parity = 0x01 ; ecrevover_y xor ecrecover_y_parity => 0 same parity, 1 different parity + ; B = y = sqrtFpEc(y^2) 0x01n => A $ => A :AND $ => B :MLOAD(ecrecover_v_parity) - $ => E :XOR - - E - 1 :JMPN(ecrecover_v_y2_same_parity) + $ :XOR,JMPZ(ecrecover_v_y2_same_parity) ; calculate neg(ecrecover_y) C = (A:FPEC) - (B:ecrecovery_y) %FPEC => A @@ -137,21 +133,17 @@ ecrecover_v_y2_same_parity: ; C = (hash * inv_r) % n $ => A :MLOAD(ecrecover_hash) - $ => B :MLOAD(ecrecover_r_inv) - :CALL(mulFnEc) + $ => B :MLOAD(ecrecover_r_inv),CALL(mulFnEc) ; C = n - (hash * inv_r) % n - ${const.FNEC - C} => A + ${const.FNEC - C} => A :MSTORE(mulPointEc_k1) 1 => B 0 => D %FNEC :ARITH - A :MSTORE(mulPointEc_k1) - $ => A :MLOAD(ecrecover_s) - $ => B :MLOAD(ecrecover_r_inv) - :CALL(mulFnEc) + $ => B :MLOAD(ecrecover_r_inv),CALL(mulFnEc) ; C = (s * inv_r) % n C :MSTORE(mulPointEc_k2) @@ -163,9 +155,7 @@ ecrecover_v_y2_same_parity: A :MSTORE(mulPointEc_p2_x) $ => A :MLOAD(ecrecover_y) - A :MSTORE(mulPointEc_p2_y) - - :CALL(mulPointEc) + A :MSTORE(mulPointEc_p2_y),CALL(mulPointEc) ; generate keccak of public key to obtain ethereum address @@ -173,9 +163,6 @@ ecrecover_v_y2_same_parity: E + 1 => E :MSTORE(lastHashKIdUsed) 0 => HASHPOS 32 => D - ; check keccak counters - $ => A :MLOAD(cntKeccakPreProcess) - %MAX_CNT_KECCAK_F - CNT_KECCAK_F - A - 1 :JMPN(outOfCountersKeccak) $ => A :MLOAD(mulPointEc_p3_x) @@ -186,13 +173,14 @@ ecrecover_v_y2_same_parity: A :HASHK(E) 64 :HASHKLEN(E) + $ => A :MLOAD(cntKeccakPreProcess) + %MAX_CNT_KECCAK_F - CNT_KECCAK_F - A - 1 :JMPN(outOfCountersKeccak) $ => A :HASHKDIGEST(E) ; for address take only last 20 bytes 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFn => B $ => A :AND - - :JMP(ecrecover_end) + 0 => B :JMP(ecrecover_end) ; ERRORS ecrecover_r_is_zero: @@ -217,7 +205,7 @@ ecrecover_error: 0 => A ecrecover_end: - $ => RR :MLOAD(ecrecover_RR) + $ => RR :MLOAD(ecrecover_RR) :RETURN INCLUDE "addFpEc.zkasm" diff --git a/main/ecrecover/end.zkasm b/main/ecrecover/end.zkasm deleted file mode 100644 index 70756cbf..00000000 --- a/main/ecrecover/end.zkasm +++ /dev/null @@ -1,53 +0,0 @@ - -end: - 0 => A,B,C,D,E,CTX, SP, PC, GAS, MAXMEM, SR ; Set all registers to 0 - -longLoop: - ;STEP-0x10000+40 : JMPN(longLoop2) - ;STEP-0x20000+40 : JMPN(longLoop2) - STEP-0x80000+40 : JMPN(longLoop2) - - : JMP(finalLoop) -longLoop2: - 0 - 0 - 0 - 0 ; 4 - 0 - 0 - 0 - 0 ; 8 - 0 - 0 - 0 - 0 ; 12 - 0 - 0 - 0 - 0 ; 16 - 0 - 0 - 0 - 0 ; 20 - 0 - 0 - 0 - 0 ; 24 - 0 - 0 - 0 - 0 ; 28 - 0 - 0 - 0 - 0 : JMP(longLoop) ; 32 - - -finalLoop: -; STEP-0x10000+2 : JMPN(finalLoop) ; 2 ** 16 -; STEP-0x20000+2 : JMPN(finalLoop) ; 2 ** 17 - STEP-0x80000+2 : JMPN(finalLoop) ; 2 ** 19 - - : JMP(start) - -opINVALID: \ No newline at end of file diff --git a/main/ecrecover/invFnEc.zkasm b/main/ecrecover/invFnEc.zkasm index edf6a1aa..7288bba4 100644 --- a/main/ecrecover/invFnEc.zkasm +++ b/main/ecrecover/invFnEc.zkasm @@ -15,13 +15,11 @@ invFnEc: invFnEc_normalized: 0 => C - ; TODO !!! control A < FNEC - ; B = inv(A) - ${var _invFnEc_A = inverseFnEc(A)} => B :MSTORE(invFnEc_tmp); + ${var _invFnEc_A = inverseFnEc(A)} => B :MSTORE(invFnEc_tmp) ; A * B + 0 = [D] * 2 ** 256 + [E] - ${var _invFnEc_AB = A * B} + $${var _invFnEc_AB = A * B} ${_invFnEc_AB >> 256} => D ${_invFnEc_AB} => E :ARITH @@ -36,6 +34,4 @@ invFnEc_normalized: %FNEC => A E :ARITH - $ => B :MLOAD(invFnEc_tmp) - - :RETURN \ No newline at end of file + $ => B :MLOAD(invFnEc_tmp), RETURN \ No newline at end of file diff --git a/main/ecrecover/invFpEc.zkasm b/main/ecrecover/invFpEc.zkasm index 2b34c0b9..57883107 100644 --- a/main/ecrecover/invFpEc.zkasm +++ b/main/ecrecover/invFpEc.zkasm @@ -35,6 +35,4 @@ invFpEc_normalized: %FPEC => A E :ARITH - $ => B :MLOAD(invFpEc_tmp) - - :RETURN \ No newline at end of file + $ => B :MLOAD(invFpEc_tmp),RETURN \ No newline at end of file diff --git a/main/ecrecover/mulFnEc.zkasm b/main/ecrecover/mulFnEc.zkasm index 3f0e2363..4e289548 100644 --- a/main/ecrecover/mulFnEc.zkasm +++ b/main/ecrecover/mulFnEc.zkasm @@ -28,6 +28,4 @@ mulFnEc: ${_mulFnEc_AB / const.FNEC} => B %FNEC => A - E :ARITH - - :RETURN \ No newline at end of file + E :ARITH,RETURN \ No newline at end of file diff --git a/main/ecrecover/mulFpEc.zkasm b/main/ecrecover/mulFpEc.zkasm index 2e12a653..11d8ed4a 100644 --- a/main/ecrecover/mulFpEc.zkasm +++ b/main/ecrecover/mulFpEc.zkasm @@ -28,6 +28,4 @@ mulFpEc: ${_mulFpEc_AB / const.FPEC} => B %FPEC => A - E :ARITH - - :RETURN \ No newline at end of file + E :ARITH,RETURN \ No newline at end of file diff --git a/main/ecrecover/mulPointEc.zkasm b/main/ecrecover/mulPointEc.zkasm index da52be14..d6d65784 100644 --- a/main/ecrecover/mulPointEc.zkasm +++ b/main/ecrecover/mulPointEc.zkasm @@ -13,18 +13,20 @@ VAR GLOBAL mulPointEc_k2 VAR GLOBAL mulPointEc_p3_x VAR GLOBAL mulPointEc_p3_y VAR GLOBAL mulPointEc_RR -VAR GLOBAL mulPointEc_bits VAR GLOBAL mulPointEc_p12_x VAR GLOBAL mulPointEc_p12_y -VAR GLOBAL mulPointEc_p3_no_infinity +VAR GLOBAL mulPointEc_HASHPOS ; TODO protect all cases mulPointEc: RR :MSTORE(mulPointEc_RR) - 255n :MSTORE(mulPointEc_bits) - 0n :MSTORE(mulPointEc_p3_no_infinity) + HASHPOS :MSTORE(mulPointEc_HASHPOS) + + 256 => RCX + + ; HASHPOS used to mulPointEc_p3_no_infinity + 0n => HASHPOS :MSTORE(mulPointEc_p3_x) - 0n :MSTORE(mulPointEc_p3_x) 0n :MSTORE(mulPointEc_p3_y) $ => A :MLOAD(mulPointEc_p1_x) @@ -55,59 +57,48 @@ mulPointEc: ; mulPointEc_loop: - %MAX_CNT_BINARY - CNT_BINARY - 10 :JMPN(outOfCountersBinary) $ => A,B :MLOAD(mulPointEc_k1) ; E = A*2 [carry] => bit 255 = 1 - $ => E :ADD,JMPC(mulPointEc_k11) + $ => E :ADD,MSTORE(mulPointEc_k1),JMPC(mulPointEc_k11) ; high_bit(k1) == 0 high_bit(k2) == ?? mulPointEc_k10: ; store E on multipointEc_k1, E was A*2 equivalent SHL and 255 bit on carry. - E :MSTORE(mulPointEc_k1) $ => A,B :MLOAD(mulPointEc_k2) ; E = A*2 [carry] => bit 255 = 1 - $ => E :ADD,JMPC(mulPointEc_k10_k21) + $ => E :ADD,MSTORE(mulPointEc_k2),JMPC(mulPointEc_k10_k21) ; high_bit(k1) == 0 high_bit(k2) == 0 mulPointEc_k10_k20: - ; store E on multipointEc_k2, E was A*2 equivalent SHL and 255 bit on carry. - E :MSTORE(mulPointEc_k2) $ => A :MLOAD(mulPointEc_p3_x) - $ => B :MLOAD(mulPointEc_p3_y) - :JMP(mulPointEc_square) + $ => B :MLOAD(mulPointEc_p3_y), JMP(mulPointEc_square) ; high_bit(k1) == 1 high_bit(k2) == ?? mulPointEc_k11: - E :MSTORE(mulPointEc_k1) $ => A,B :MLOAD(mulPointEc_k2) - $ => E :ADD,JMPC(mulPointEc_k11_k21) + $ => E :ADD,MSTORE(mulPointEc_k2),JMPC(mulPointEc_k11_k21) ; high_bit(k1) == 1 high_bit(k2) == 0 mulPointEc_k11_k20: $ => C :MLOAD(mulPointEc_p1_x) - $ => D :MLOAD(mulPointEc_p1_y) - :JMP(mulPointEc_p2_loaded) + $ => D :MLOAD(mulPointEc_p1_y), JMP(mulPointEc_p2_loaded) ; high_bit(k1) == 1 high_bit(k2) == 1 mulPointEc_k11_k21: $ => C :MLOAD(mulPointEc_p12_x) - $ => D :MLOAD(mulPointEc_p12_y) - :JMP(mulPointEc_p2_loaded) + $ => D :MLOAD(mulPointEc_p12_y), JMP(mulPointEc_p2_loaded) ; high_bit(k1) == 0 high_bit(k2) == 1 mulPointEc_k10_k21: $ => C :MLOAD(mulPointEc_p2_x) - $ => D :MLOAD(mulPointEc_p2_y) - :JMP(mulPointEc_p2_loaded) + $ => D :MLOAD(mulPointEc_p2_y), JMP(mulPointEc_p2_loaded) ; in this point C,D have point to be add mulPointEc_p2_loaded: - E :MSTORE(mulPointEc_k2) ; check if p3 has a value, isn't point at infinity. - $ => A :MLOAD(mulPointEc_p3_no_infinity) - 1 :MSTORE(mulPointEc_p3_no_infinity) - A - 1 :JMPN(mulPointEc_p3_assignment) + HASHPOS :JMPZ(mulPointEc_p3_assignment) + 1 => HASHPOS C => A ; point_x $ => B :MLOAD(mulPointEc_p3_x) @@ -118,37 +109,28 @@ mulPointEc_p2_loaded: $ => B :MLOAD(mulPointEc_p3_y) ${xAddPointEc(A,B,C,D)} => E :MSTORE(mulPointEc_p3_x) - ${yAddPointEc(A,B,C,D)} :ARITH_ECADD_DIFFERENT, MSTORE(mulPointEc_p3_y) + ${yAddPointEc(A,B,C,D)} => B :ARITH_ECADD_DIFFERENT, MSTORE(mulPointEc_p3_y) mulPointEc_after_add: - E => A - $ => B :MLOAD(mulPointEc_p3_y) - - :JMP(mulPointEc_square) + E => A :JMP(mulPointEc_square) mulPointEc_p3_assignment: + 1 => HASHPOS C => A :MSTORE(mulPointEc_p3_x) D => B :MSTORE(mulPointEc_p3_y) mulPointEc_square: - $ => C :MLOAD(mulPointEc_bits) - C - 1 :JMPN(mulPointEc_end_loop) - C - 1 :MSTORE(mulPointEc_bits) - - $ => C :MLOAD(mulPointEc_p3_no_infinity) - ; if not data in p3, p3 was empty, no dblPointEc - C - 1 :JMPN(mulPointEc_loop) + RCX - 1 => RCX :JMPZ(mulPointEc_end_loop) + HASHPOS :JMPZ(mulPointEc_loop) $ => A :MLOAD(mulPointEc_p3_x) $ => B :MLOAD(mulPointEc_p3_y) ${xDblPointEc(A,B)} => E :MSTORE(mulPointEc_p3_x) - ${yDblPointEc(A,B)} :ARITH_ECADD_SAME, MSTORE(mulPointEc_p3_y) - - :JMP(mulPointEc_loop) + ${yDblPointEc(A,B)} :ARITH_ECADD_SAME, MSTORE(mulPointEc_p3_y), JMP(mulPointEc_loop) mulPointEc_x_equals_before_add: D => A ; D contains y of point to add (depends of bits k1,k2) @@ -157,21 +139,18 @@ mulPointEc_x_equals_before_add: ; x1 = x2 and y1 != y2 ; ASSUME y1 = -y2 - 0n :MSTORE(mulPointEc_p3_no_infinity) - 0n :MSTORE(mulPointEc_p3_x) - 0n :MSTORE(mulPointEc_p3_y) - :JMP(mulPointEc_square) + ; same instruction put HASHPOS and mulPointEc_p3_x to 0. + 0n => HASHPOS :MSTORE(mulPointEc_p3_x) + 0n :MSTORE(mulPointEc_p3_y), JMP(mulPointEc_square) mulPointEc_same_point_to_add: C => A D => B ${xDblPointEc(A,B)} => E :MSTORE(mulPointEc_p3_x) - ${yDblPointEc(A,B)} :ARITH_ECADD_SAME, MSTORE(mulPointEc_p3_y) - - :JMP(mulPointEc_after_add) + ${yDblPointEc(A,B)} => B :ARITH_ECADD_SAME, MSTORE(mulPointEc_p3_y), JMP(mulPointEc_after_add) mulPointEc_end_loop: - $ => RR :MLOAD(mulPointEc_RR) - :RETURN + $ => RR :MLOAD(mulPointEc_RR) + $ => HASHPOS :MLOAD(mulPointEc_HASHPOS), RETURN diff --git a/main/ecrecover/sqFpEc.zkasm b/main/ecrecover/sqFpEc.zkasm index 74b2f1ee..21299558 100644 --- a/main/ecrecover/sqFpEc.zkasm +++ b/main/ecrecover/sqFpEc.zkasm @@ -29,6 +29,4 @@ sqFpEc: ${_sqFpEc_AA / const.FPEC} => B %FPEC => A - E :ARITH - - :RETURN \ No newline at end of file + E :ARITH,RETURN \ No newline at end of file diff --git a/main/ecrecover/sqrtFpEc.zkasm b/main/ecrecover/sqrtFpEc.zkasm index a936d0c7..ca03cc0b 100644 --- a/main/ecrecover/sqrtFpEc.zkasm +++ b/main/ecrecover/sqrtFpEc.zkasm @@ -36,8 +36,7 @@ sqrtFpEc: %FPEC => A E :ARITH - $ => C :MLOAD(sqrtFpC_res) + $ => C :MLOAD(sqrtFpC_res),RETURN sqrtFpEc_End: - :RETURN \ No newline at end of file diff --git a/main/precompiled/pre-ecrecover.zkasm b/main/precompiled/pre-ecrecover.zkasm index 768fe883..007d4f3e 100644 --- a/main/precompiled/pre-ecrecover.zkasm +++ b/main/precompiled/pre-ecrecover.zkasm @@ -9,27 +9,12 @@ funcECRECOVER: ; read data stored in SP + %CALLDATA_OFFSET ; hash [32 bytes], v [32 bytes], r [32 bytes], s [32 bytes] %CALLDATA_OFFSET => SP - $ => E :MLOAD(SP++) ; hash - $ => A :MLOAD(SP++) ; v - ; check v range [27, 28] - 27 => B - $ :LT, JMPC(endECRECOVER) - A => B - 28 => A - $ :LT, JMPC(endECRECOVER) - B => D - E => A + $ => A :MLOAD(SP++) ; hash + $ => D :MLOAD(SP++) ; v $ => B :MLOAD(SP++) ; r - ; check r range [0, secp256k1n] - ;0 - ${comp_gt(B, 115792089237316195423570985008687907852837564279074904382605163141518161494337)} :JMPN(endECRECOVER) $ => C :MLOAD(SP) ; s - ; check s range [0, secp256k1n/2 + 1] - ;0 - ${comp_gt(C, 57896044618658097711785492504343953926418782139537452191302581570759080747169)} :JMPN(endECRECOVER) - ; compute ecrecover - :CALL(ecrecover) - 0 => B - $ => B :EQ - 0 - B :JMPN(endECRECOVER) + :CALL(ecrecover_precompiled) ; in: [A: hash, B: r, C: s, D: v], out: [A: result_ecrecover] + B :JMPNZ(endECRECOVER) ; prepare return data $ => E :MLOAD(retCallOffset) ; $ => C :MLOAD(retCallLength) ; always 32 diff --git a/main/process-tx.zkasm b/main/process-tx.zkasm index 4187c9e7..a1715f86 100644 --- a/main/process-tx.zkasm +++ b/main/process-tx.zkasm @@ -38,7 +38,7 @@ processTx: $ => B :MLOAD(txR) $ => C :MLOAD(txS) $ => D :MLOAD(txV) - :CALL(ecrecover) + :CALL(ecrecover_tx) ; Check result is non-zero checkAndSaveFrom: 0 => B diff --git a/test/ecrecover.zkasm b/test/ecrecover.zkasm new file mode 100644 index 00000000..eb9f904a --- /dev/null +++ b/test/ecrecover.zkasm @@ -0,0 +1,422 @@ +;;;;;;;;;;;; +;; ecrecover_tx +;;;;;;;;;;;; +INCLUDE "../main/constants.zkasm" +VAR GLOBAL lastHashKIdUsed +VAR GLOBAL cntKeccakPreProcess +start: + + STEP => A + 0 :ASSERT + + -1 :MSTORE(lastHashKIdUsed) + +repeat_ecrecover_test: + + + ; #100 first valid ecrecover_tx + + 0xd9eba16ed0ecae432b71fe008c98cc872bb4cc214d3220a36f365326cf807d68n => A + 0xddd0a7290af9526056b4e35a077b9a11b513aa0028ec6c9880948544508f3c63n => B + 0x265e99e47ad31bb2cab9646c504576b3abc6939a1710afc08cbf3034d73214b8n => C + 0x1cn => D + :CALL(ecrecover_tx) + 0x14791697260e4c9a71f18484c9f997b308e59325n :ASSERT + + ; #0 valid ecrecover_tx + + 0x3cc4cb050478c49877188e4fbd022f35ccb41cee02d9d4417194cbf7ebc1eeben => A + 0x7dff8b06f4914ff0be0e02edf967ce8f13224cb4819e3833b777867db61f8a62n => B + 0x2bcf13b5e4f34a04a77344d5943e0228ba2e787583036325450c889d597a16c4n => C + 0x1bn => D + :CALL(ecrecover_tx) + 0xbec80D04A24CD4D811876fF40F31260C339d63C2n :ASSERT + + ; #1 valid ecrecover_tx + + 0xee43d51baa54831bfd9b03c4b17b59a594378d777e418020c3358f1822cec07dn => A + 0xea678b4b3ebde1e877401b1bf67fd59e17c0eb75e6da8ecd9cc38620099e0c65n => B + 0x2b954333cfe2b4bf97c4abbcede04a5edda0688b9e965a4bff3d6a45bed2a6e8n => C + 0x1bn => D + :CALL(ecrecover_tx) + 0xd571a2180a8647e77adfc109C49bd2137c7a71b5n :ASSERT + + ; #2 valid ecrecover_tx + + 0xfd98b0bfc9eecc813b958263c08db17c932bfe1c2ae7c21a12bb42860d9d9c1fn => A + 0x86b2f6d4bae0e1e1139bc29378fd243d33de35822652144b0b04af346cbf3ad2n => B + 0x5ec4a8672d44b21bdc2203ab8adab6ae53d4c57a2d832090cab710f26600e2fcn => C + 0x1bn => D + :CALL(ecrecover_tx) + 0x52855436E41c2671759d54103e71A3d5Fe27439Cn :ASSERT + + ; #3 valid ecrecover_tx + + 0xc401c7d7baa568f5928028def2818ec62b70db9b738ab3f4d36326dac17839e5n => A + 0x4a95890f1102c6a6684815f4274d68d64d6deb59e5d524d1a6394256dd188b33n => B + 0x3e53619fe2f4c67ac8ff4103da0740fd7c912be5b176329a74764bd790e42f51n => C + 0x1bn => D + :CALL(ecrecover_tx) + 0xA4E24c3ea459D50409dd31Cf1C35A222ADA889fan :ASSERT + + ; #4 valid ecrecover_tx + + 0x60049b234e7fd86ba5354613066d0d67ccdd993d5322656c56562d48c208002an => A + 0xf06fbfb021b185a599ec35b0c4a85f5c329abee4f91c4027cb90210c66868e99n => B + 0x1e0e24cab3e119fea57b012b25bfd65f710fe567a53d1a414208f0385f37be1cn => C + 0x1bn => D + :CALL(ecrecover_tx) + 0x2302Fdd6dB52D32b84cc7648Fb9d8978a005E382n :ASSERT + + ; #5 valid ecrecover_tx + + 0xfda892e54ef8d0fc5d34f3c78fd9262ebc97c448eec72348340c902ff8f82d86n => A + 0xe9713e52d8ca16c7723ea73ff89244d1c5bfe6611f56d8a2cebcf25f546c0bb3n => B + 0x627566979c5b6e3a5b8e06ba56f22eed367a9b54ed9c3c54d01a29012435fe02n => C + 0x1cn => D + :CALL(ecrecover_tx) + 0xCc665b2CaA43684c99f0EB59751DC1a8C4dBd9Een :ASSERT + + ; #6 valid ecrecover_tx + + 0x1df5d6cd09999848b734ef91a35a31840b6f4f7bc42fa4005ef44a3a0da75fd7n => A + 0x8c661a2e0ae1ffe716d34e6d1ceacfd75326da91bf3af225ed675602a00ebf21n => B + 0x3de21452fd054750ae68326d7781ed903b278bb1ac1f52fb8f55e8a4c9954000n => C + 0x1bn => D + :CALL(ecrecover_tx) + 0x1F34358a423C2FED839090Dd943A728Dbd711e62n :ASSERT + + ; #7 valid ecrecover_tx + + 0x84254d72d3a17a61a1ff7dbef2cbb063f2913a407a15ee6012168ce0ce5bc500n => A + 0x4937d15fdde73a18520a70b8e8f6fb05e9c172d8b04b02c0246cd5c9fa76ff97n => B + 0x70ac180d31a5336bc902e317c6b5850b151ea7a2cff0595c61d67bf49d1fc210n => C + 0x1bn => D + :CALL(ecrecover_tx) + 0x0C470e0895Bbe22A5cFeD06002e29e8ADCEB59E1n :ASSERT + + ; #8 valid ecrecover_tx + + 0xcbfb5477b23d3f14e821799805060a4be3dc7ec51f007ac78b810941a5693723n => A + 0x465e8a566e29f97b29980b458bff07cdeff5e020f38d541c3a980eb4642b4606n => B + 0x531eaeeeec12998af811c435a79a737d3dbb7411ed4d937080b6201a46703bf0n => C + 0x1bn => D + :CALL(ecrecover_tx) + 0x6777D222b69b69F41ee3DBFCf6baee332999f347n :ASSERT + + ; #9 valid ecrecover_tx + + 0xf27fb8414a5aaed947f91ff458ea71f6eed0b8949d3da51ad7325047aba2e081n => A + 0x493b8ca6e09c06450508b8eae88bf8103548b71135e1d8721b935a8822f28890n => B + 0x4dea2362974bb205c48e92bd88761b454f2f4e085dfb9beb0706588b6eb852a8n => C + 0x1cn => D + :CALL(ecrecover_tx) + 0x1f56A9F3Ca1F284978478D9363D2b345B23B198Bn :ASSERT + + ; #10 valid ecrecover_tx + + 0x7d7e073c17eb159ad8372f82f9fa700a77a8a09dbfa7ccc2561504993be9cccan => A + 0x8c23081e8211029ca641fe88235387a54d875b2fd64df1dbe87fb438316db708n => B + 0x41c8e2f71966a6553c03d9477145366764399a6ad23c2efdabbdf7004d21a7b7n => C + 0x1bn => D + :CALL(ecrecover_tx) + 0x6a7C3804E52D9B089767eA5D26232F9096F7B50en :ASSERT + + ; #11 valid ecrecover_tx + + 0x8aec5831f7b02d4f714878d3729975afd5435e61e738a119ddca2e9777e04183n => A + 0x49b0018d05b6f36d461339633082c8a032543c4f4c5ae6af56ff5e48fd943372n => B + 0x34f096b3ee06d00f330697bddbe5e25d9207e5ccac214eb94ce96ed4507393c1n => C + 0x1bn => D + :CALL(ecrecover_tx) + 0xdD6F178Fa6ed5859154301C686C3cd12192CcC0An :ASSERT + + ; #12 valid ecrecover_tx + + 0xc2c0f5c01b3e244bd9f40da627cfefbc45c53e76f26798cc195de61e3438585fn => A + 0x4a06e1f0012017c68294911be669e953e01c41f97b31e4f6830af4200d4bf253n => B + 0x2eafb33fbb92b512175812972ce89e54e50f28ecf27a051b4f2291da2cf0e1f3n => C + 0x1cn => D + :CALL(ecrecover_tx) + 0x5fFd05d8565FA51BB1aE1E4c7b980e1C91d2c939n :ASSERT + + ; #13 valid ecrecover_tx + + 0x1430fc999d7bfa8954983e43f80a27a07eb4845037bc344fc128b453f76877a3n => A + 0x88843aea48fff6790cb6f9657e1650e1386aa73a6bed50e8db2467d06445bed8n => B + 0x779ce085139a5fc49f33431c9d4794a16732d497158570690662ed779fb22eadn => C + 0x1cn => D + :CALL(ecrecover_tx) + 0xF329e07AFade0Fb45a599993dF4313DFaB5f80A6n :ASSERT + + ; #14 valid ecrecover_tx + + 0x8bc6619ef176973b22e4a0f0f81a6cd5badf091e452f910de38162b18c2f2ff6n => A + 0x347faebc1fc4c014692ffc7284fa28596d1494c29f29cdc52fa1c8d57ded6a5dn => B + 0x597a18da2e6c3c1eaa56d9611f50bf3d161a05e542afd29cf416b80f82ee5ef9n => C + 0x1cn => D + :CALL(ecrecover_tx) + 0x411559B990Fd50F1DF20B4D3780C4185d113A9Een :ASSERT + + ; #15 valid ecrecover_tx + + 0xb3dc90532569a73ab8fc3d41d6df176833133be5a697f076392f51001c715006n => A + 0xaf4592a0ec76c84bb587b1bdd3b77b1207f7fd572e118f4278a80ec7c89666b9n => B + 0x0cb4bd62edd2d286b883d32006b799532737b5b90ed4a03ce0a6868a2f10edb6n => C + 0x1bn => D + :CALL(ecrecover_tx) + 0xB2E1a1FbfdAE0743f4539166309B72BB737716b1n :ASSERT + + ; #16 valid ecrecover_tx + + 0xc7367ffedb65fe022fa06a8c2855c69547cca19ee828d6615e5f7decafccbdc8n => A + 0xb7fd2fa91dd0ba816b37f4ad9b507ad3b32ec2a445544fabb0e231c5aeeefb18n => B + 0x244c004f8b78dc3a3c3db9bda9b39d6e6b11b9397baaf29d0529b7bac9490742n => C + 0x1cn => D + :CALL(ecrecover_tx) + 0x95DdaFE17e5550FF8ac7b2EF9D365d067aa7Ae91n :ASSERT + + ; #17 valid ecrecover_tx + + 0x898a015948f4e12fe71bb3f6015410f33d0b67842b551599762b51fecad5577cn => A + 0xa0d427856db72164abc59666e34cd4accb689f1800f71384d797a729c003598bn => B + 0x514d41eca750ebe03d75ed7182d81168af198760e3ac5077c5d88d1f85656039n => C + 0x1cn => D + :CALL(ecrecover_tx) + 0x9D39Cfa3F2e98CA109c45F28735436798CBBDEF8n :ASSERT + + ; #18 valid ecrecover_tx + + 0xadd47d80decfc50037d37430ccdda08b3d39831e5355e99bfe5e08e00531182en => A + 0xf74a32e691a8e0ee1b55fa4aeeebfb3eed091108ce03f7ef449846044f228d4an => B + 0x308af50fef22673ae4a83c5e80c4f316829490b57a561c9f45a1570286d94e41n => C + 0x1bn => D + :CALL(ecrecover_tx) + 0x4AB0c3d24dfF7E98e16Edd61269997D089E97c9fn :ASSERT + + ; #19 valid ecrecover_tx + + 0x8fc27577b5290a3ab0d3407969123c719c475a28e687d943f88ac5abadf83420n => A + 0x8b9d9e9c4201b9b2d351b5dde35c0ebefa5446c2dbdd5e30dca02af69d8c29bdn => B + 0x047fb2ba1e4cc0a059ee64aae40d4ba48e6d3265426f602be275d286e45917f6n => C + 0x1bn => D + :CALL(ecrecover_tx) + 0xd02c6aAB18d3f40AA994A5B7F3c2be14B34EAB6en :ASSERT + + ; #20 mess == change 1 bit + + 0x256e9aea5e197a1f1af7a3e85a3212fa4049a3ba34c2289b4c860fc0b0c64ef3n => A + 0x9242685bf161793cc25603c231bc2f568eb630ea16aa137d2664ac8038825608n => B + 0x4f8ae3bd7535248d0bd448298cc2e2071e56992d0774dc340c368ae950852adan => C + 0x1bn => D + :CALL(ecrecover_tx) + 0x34E325D8023eb901c39747338C587b098fB75dF4n :ASSERT + + ; #21 mess == 0 + + 0x0000000000000000000000000000000000000000000000000000000000000000n => A + 0x9242685bf161793cc25603c231bc2f568eb630ea16aa137d2664ac8038825608n => B + 0x4f8ae3bd7535248d0bd448298cc2e2071e56992d0774dc340c368ae950852adan => C + 0x1bn => D + :CALL(ecrecover_tx) + 0x2a558C4cD662E0b74E289d746AEA2f8cf8e54f7cn :ASSERT + + ; #22 mess == field + + 0xfffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141n => A + 0x9242685bf161793cc25603c231bc2f568eb630ea16aa137d2664ac8038825608n => B + 0x4f8ae3bd7535248d0bd448298cc2e2071e56992d0774dc340c368ae950852adan => C + 0x1bn => D + :CALL(ecrecover_tx) + 0x2a558C4cD662E0b74E289d746AEA2f8cf8e54f7cn :ASSERT + + ; #23 mess == field - 1 + + 0xfffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364140n => A + 0x9242685bf161793cc25603c231bc2f568eb630ea16aa137d2664ac8038825608n => B + 0x4f8ae3bd7535248d0bd448298cc2e2071e56992d0774dc340c368ae950852adan => C + 0x1bn => D + :CALL(ecrecover_tx) + 0xc41ABa9e06fac6976618820d04D247FfD38f62FFn :ASSERT + + ; #24 mess == field + 1 + + 0xfffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364142n => A + 0x9242685bf161793cc25603c231bc2f568eb630ea16aa137d2664ac8038825608n => B + 0x4f8ae3bd7535248d0bd448298cc2e2071e56992d0774dc340c368ae950852adan => C + 0x1bn => D + :CALL(ecrecover_tx) + 0x7a343F50dd8fAFa76406F6Ee4dA1796FF9A06109n :ASSERT + + ; #25 mess == 1 + + 0x0000000000000000000000000000000000000000000000000000000000000001n => A + 0x9242685bf161793cc25603c231bc2f568eb630ea16aa137d2664ac8038825608n => B + 0x4f8ae3bd7535248d0bd448298cc2e2071e56992d0774dc340c368ae950852adan => C + 0x1bn => D + :CALL(ecrecover_tx) + 0x7a343F50dd8fAFa76406F6Ee4dA1796FF9A06109n :ASSERT + + ; #26 flip v: 28 --> 27. Valid ecrecover_tx + + 0x456e9aea5e197a1f1af7a3e85a3212fa4049a3ba34c2289b4c860fc0b0c64ef3n => A + 0x9242685bf161793cc25603c231bc2f568eb630ea16aa137d2664ac8038825608n => B + 0x4f8ae3bd7535248d0bd448298cc2e2071e56992d0774dc340c368ae950852adan => C + 0x1bn => D + :CALL(ecrecover_tx) + 0xE077fd3C958303e36309B9EE20AE9D3D59817232n :ASSERT + + ; #27 v < 27 + + 0x456e9aea5e197a1f1af7a3e85a3212fa4049a3ba34c2289b4c860fc0b0c64ef3n => A + 0x9242685bf161793cc25603c231bc2f568eb630ea16aa137d2664ac8038825608n => B + 0x4f8ae3bd7535248d0bd448298cc2e2071e56992d0774dc340c368ae950852adan => C + 0x1an => D + :CALL(ecrecover_tx) + 0x0000000000000000000000000000000000000000n :ASSERT + + ; #28 v > 28 + + 0x456e9aea5e197a1f1af7a3e85a3212fa4049a3ba34c2289b4c860fc0b0c64ef3n => A + 0x9242685bf161793cc25603c231bc2f568eb630ea16aa137d2664ac8038825608n => B + 0x4f8ae3bd7535248d0bd448298cc2e2071e56992d0774dc340c368ae950852adan => C + 0x1dn => D + :CALL(ecrecover_tx) + 0x0000000000000000000000000000000000000000n :ASSERT + + ; #29 r == 0 + + 0x456e9aea5e197a1f1af7a3e85a3212fa4049a3ba34c2289b4c860fc0b0c64ef3n => A + 0x0000000000000000000000000000000000000000000000000000000000000000n => B + 0x4f8ae3bd7535248d0bd448298cc2e2071e56992d0774dc340c368ae950852adan => C + 0x1cn => D + :CALL(ecrecover_tx) + 0x0000000000000000000000000000000000000000n :ASSERT + + ; #30 r == field + + 0x456e9aea5e197a1f1af7a3e85a3212fa4049a3ba34c2289b4c860fc0b0c64ef3n => A + 0xfffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141n => B + 0x4f8ae3bd7535248d0bd448298cc2e2071e56992d0774dc340c368ae950852adan => C + 0x1cn => D + :CALL(ecrecover_tx) + 0x0000000000000000000000000000000000000000n :ASSERT + + ; #31 r > field + + 0x456e9aea5e197a1f1af7a3e85a3212fa4049a3ba34c2289b4c860fc0b0c64ef3n => A + 0xfffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364142n => B + 0x4f8ae3bd7535248d0bd448298cc2e2071e56992d0774dc340c368ae950852adan => C + 0x1cn => D + :CALL(ecrecover_tx) + 0x0000000000000000000000000000000000000000n :ASSERT + + ; #32 r = field - 1 + + 0x456e9aea5e197a1f1af7a3e85a3212fa4049a3ba34c2289b4c860fc0b0c64ef3n => A + 0xfffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364140n => B + 0x4f8ae3bd7535248d0bd448298cc2e2071e56992d0774dc340c368ae950852adan => C + 0x1cn => D + :CALL(ecrecover_tx) + 0x0000000000000000000000000000000000000000n :ASSERT + + ; #33 s == 0 + + 0x456e9aea5e197a1f1af7a3e85a3212fa4049a3ba34c2289b4c860fc0b0c64ef3n => A + 0x9242685bf161793cc25603c231bc2f568eb630ea16aa137d2664ac8038825608n => B + 0x0000000000000000000000000000000000000000000000000000000000000000n => C + 0x1cn => D + :CALL(ecrecover_tx) + 0x0000000000000000000000000000000000000000n :ASSERT + + ; #34 s == field/2 + 1. Valid + + 0x456e9aea5e197a1f1af7a3e85a3212fa4049a3ba34c2289b4c860fc0b0c64ef3n => A + 0x9242685bf161793cc25603c231bc2f568eb630ea16aa137d2664ac8038825608n => B + 0x7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a1n => C + 0x1cn => D + :CALL(ecrecover_tx) + 0x4ef445CADd8bEe8A02bc79b30A97e6Fe3AE3B7a3n :ASSERT + + ; #35 s == field/2. Valid + + 0x456e9aea5e197a1f1af7a3e85a3212fa4049a3ba34c2289b4c860fc0b0c64ef3n => A + 0x9242685bf161793cc25603c231bc2f568eb630ea16aa137d2664ac8038825608n => B + 0x7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0n => C + 0x1cn => D + :CALL(ecrecover_tx) + 0xB29F65aA401660dfa96ecD7eB28134d87E9a618Dn :ASSERT + + ; #36 s == field/2 + 2. Valid (precompiled) + + 0x456e9aea5e197a1f1af7a3e85a3212fa4049a3ba34c2289b4c860fc0b0c64ef3n => A + 0x9242685bf161793cc25603c231bc2f568eb630ea16aa137d2664ac8038825608n => B + 0x7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a2n => C + 0x1cn => D + :CALL(ecrecover_precompiled) + 0xfE706AA7fe3455F29e0F5553D9C780Be3Bd54564n :ASSERT + + ; #36' s == field/2 + 2. Invalid (tx) + + 0x456e9aea5e197a1f1af7a3e85a3212fa4049a3ba34c2289b4c860fc0b0c64ef3n => A + 0x9242685bf161793cc25603c231bc2f568eb630ea16aa137d2664ac8038825608n => B + 0x7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a2n => C + 0x1cn => D + :CALL(ecrecover_tx) + 0n :ASSERT + B => A + 4n :ASSERT + + ; #37 s == field + + 0x456e9aea5e197a1f1af7a3e85a3212fa4049a3ba34c2289b4c860fc0b0c64ef3n => A + 0x9242685bf161793cc25603c231bc2f568eb630ea16aa137d2664ac8038825608n => B + 0xfffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141n => C + 0x1cn => D + :CALL(ecrecover_tx) + 0x0000000000000000000000000000000000000000n :ASSERT + B => A + 4n :ASSERT + + ; #38 s == field - 1 + + 0x456e9aea5e197a1f1af7a3e85a3212fa4049a3ba34c2289b4c860fc0b0c64ef3n => A + 0x9242685bf161793cc25603c231bc2f568eb630ea16aa137d2664ac8038825608n => B + 0xfffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364140n => C + 0x1cn => D + :CALL(ecrecover_precompiled) + 0xc846e2E4Ab85A761042265B9A8d995345432A60en :ASSERT + + ; #38' s == field - 1 + + 0x456e9aea5e197a1f1af7a3e85a3212fa4049a3ba34c2289b4c860fc0b0c64ef3n => A + 0x9242685bf161793cc25603c231bc2f568eb630ea16aa137d2664ac8038825608n => B + 0xfffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364140n => C + 0x1cn => D + :CALL(ecrecover_tx) + 0x0000000000000000000000000000000000000000n :ASSERT + B => A + 4n :ASSERT + + ; #39 s == field + 1 + + 0x456e9aea5e197a1f1af7a3e85a3212fa4049a3ba34c2289b4c860fc0b0c64ef3n => A + 0x9242685bf161793cc25603c231bc2f568eb630ea16aa137d2664ac8038825608n => B + 0xfffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364142n => C + 0x1cn => D + :CALL(ecrecover_tx) + 0x0000000000000000000000000000000000000000n :ASSERT + + :JMP(end) + +INCLUDE "../main/ecrecover/ecrecover.zkasm" + +end: + 0 => A,B,C,D,E,CTX, SP, PC, GAS, MAXMEM, SR, HASHPOS, RR, RCX + +finalizeExecution: +finalWait: + ${beforeLast()} : JMPN(finalWait) + + : JMP(start) +opINVALID: \ No newline at end of file