Missing Scalar Field Range Check in Scalar Multiplication
There is no field element range check on scalar field proof elements e.g. `proof_l_at_zeta, proof_r_at_zeta, proof_o_at_zeta, proof_s1_at_zeta,proof_s2_at_zeta, proof_grand_product_at_zeta_omega` as mentioned in the step 2 of the verifier's algorithm in the Plonk paper. The scalar multiplication functions `point_mul` and `point_acc_mul` call precompile ECMUL, according to EIP-169 , which would verify the point P is on curve and P.x and P.y is less than the base field modulus, however it doesn't check the scalar `s` is less than scalar field modulus, if `s` is greater than scalar field modulus `r_mod`, it would cause unintended behavior of the contract, specifically if the scalar field proof element `e` are replaced by `e` + `r_mod`, the proof would still pass verification. Although in Plonk's case, there is few attacker vectors could exists be based on this kind of proof malleability.\\n```\\nfunction point\\_mul(dst,src,s, mPtr) {\\n // let mPtr := add(mload(0x40), state\\_last\\_mem)\\n let state := mload(0x40)\\n mstore(mPtr,mload(src))\\n mstore(add(mPtr,0x20),mload(add(src,0x20)))\\n mstore(add(mPtr,0x40),s)\\n let l\\_success := staticcall(sub(gas(), 2000),7,mPtr,0x60,dst,0x40)\\n mstore(add(state, state\\_success), and(l\\_success,mload(add(state, state\\_success))))\\n}\\n\\n// dst <- dst + [s]src (Elliptic curve)\\nfunction point\\_acc\\_mul(dst,src,s, mPtr) {\\n let state := mload(0x40)\\n mstore(mPtr,mload(src))\\n mstore(add(mPtr,0x20),mload(add(src,0x20)))\\n mstore(add(mPtr,0x40),s)\\n let l\\_success := staticcall(sub(gas(), 2000),7,mPtr,0x60,mPtr,0x40)\\n mstore(add(mPtr,0x40),mload(dst))\\n mstore(add(mPtr,0x60),mload(add(dst,0x20)))\\n l\\_success := and(l\\_success, staticcall(sub(gas(), 2000),6,mPtr,0x80,dst, 0x40))\\n mstore(add(state, state\\_success), and(l\\_success,mload(add(state, state\\_success))))\\n}\\n```\\n
Add scalar field range check on scalar multiplication functions `point_mul` and `point_acc_mul` or the scalar field proof elements.
```\\nfunction point\\_mul(dst,src,s, mPtr) {\\n // let mPtr := add(mload(0x40), state\\_last\\_mem)\\n let state := mload(0x40)\\n mstore(mPtr,mload(src))\\n mstore(add(mPtr,0x20),mload(add(src,0x20)))\\n mstore(add(mPtr,0x40),s)\\n let l\\_success := staticcall(sub(gas(), 2000),7,mPtr,0x60,dst,0x40)\\n mstore(add(state, state\\_success), and(l\\_success,mload(add(state, state\\_success))))\\n}\\n\\n// dst <- dst + [s]src (Elliptic curve)\\nfunction point\\_acc\\_mul(dst,src,s, mPtr) {\\n let state := mload(0x40)\\n mstore(mPtr,mload(src))\\n mstore(add(mPtr,0x20),mload(add(src,0x20)))\\n mstore(add(mPtr,0x40),s)\\n let l\\_success := staticcall(sub(gas(), 2000),7,mPtr,0x60,mPtr,0x40)\\n mstore(add(mPtr,0x40),mload(dst))\\n mstore(add(mPtr,0x60),mload(add(dst,0x20)))\\n l\\_success := and(l\\_success, staticcall(sub(gas(), 2000),6,mPtr,0x80,dst, 0x40))\\n mstore(add(state, state\\_success), and(l\\_success,mload(add(state, state\\_success))))\\n}\\n```\\n