From 10bd47f70bb1f6a275892a549983752519e7f0cf Mon Sep 17 00:00:00 2001 From: dovgopoly Date: Fri, 8 Nov 2024 22:04:08 +0200 Subject: [PATCH] added mod optimization --- .../certificate/signers/CECDSASHA2Signer.sol | 32 ++-- contracts/utils/U384.sol | 141 ++++++++---------- 2 files changed, 80 insertions(+), 93 deletions(-) diff --git a/contracts/certificate/signers/CECDSASHA2Signer.sol b/contracts/certificate/signers/CECDSASHA2Signer.sol index 09832e8..6378eb6 100644 --- a/contracts/certificate/signers/CECDSASHA2Signer.sol +++ b/contracts/certificate/signers/CECDSASHA2Signer.sol @@ -121,11 +121,11 @@ contract CECDSASHA2Signer is ICertificateSigner, Initializable { uint256 RHS = U384.modexp(call, x, 3, p); if (!U384.eqInteger(a, 0)) { - RHS = U384.modadd(call, RHS, U384.modmul(call, x, a, p), p); // x^3 + a*x + RHS = U384.modadd(RHS, U384.modmul(call, x, a, p), p); // x^3 + a*x } if (!U384.eqInteger(b, 0)) { - RHS = U384.modadd(call, RHS, b, p); // x^3 + a*x + b + RHS = U384.modadd(RHS, b, p); // x^3 + a*x + b } return U384.eq(LHS, RHS); @@ -237,11 +237,11 @@ contract CECDSASHA2Signer is ICertificateSigner, Initializable { } uint256 u = U384.modmul(call, y0, z0, p); - U384.modshl1Assign(call, u, p); + U384.modshl1Assign(u, p); x1 = U384.modmul(call, u, x0, p); U384.modmulAssign(call, x1, y0, p); - U384.modshl1Assign(call, x1, p); + U384.modshl1Assign(x1, p); x0 = U384.modexp(call, x0, 2, p); @@ -249,24 +249,24 @@ contract CECDSASHA2Signer is ICertificateSigner, Initializable { z0 = U384.modexp(call, z0, 2, p); U384.modmulAssign(call, z0, a, p); - U384.modaddAssign(call, y1, z0, p); + U384.modaddAssign(y1, z0, p); z1 = U384.modexp(call, y1, 2, p); - U384.modshl1AssignTo(call, x0, x1, p); + U384.modshl1AssignTo(x0, x1, p); uint256 diff = U384.sub(p, x0); - U384.modaddAssign(call, z1, diff, p); + U384.modaddAssign(z1, diff, p); U384.subAssignTo(diff, p, z1); - U384.modaddAssignTo(call, x0, x1, diff, p); + U384.modaddAssignTo(x0, x1, diff, p); U384.modmulAssign(call, x0, y1, p); y0 = U384.modmul(call, y0, u, p); U384.modexpAssign(call, y0, 2, p); - U384.modshl1Assign(call, y0, p); + U384.modshl1Assign(y0, p); U384.subAssignTo(diff, p, y0); - U384.modaddAssignTo(call, y1, x0, diff, p); + U384.modaddAssignTo(y1, x0, diff, p); U384.modmulAssignTo(call, x1, u, z1, p); @@ -331,19 +331,19 @@ contract CECDSASHA2Signer is ICertificateSigner, Initializable { ) internal view returns (uint256 x2, uint256 y2, uint256 z2) { unchecked { uint256 diff = U384.sub(p, t1); - y2 = U384.modadd(call, t0, diff, p); + y2 = U384.modadd(t0, diff, p); U384.subAssignTo(diff, p, u1); - x2 = U384.modadd(call, u0, diff, p); + x2 = U384.modadd(u0, diff, p); uint256 u2 = U384.modexp(call, x2, 2, p); z2 = U384.modexp(call, y2, 2, p); U384.modmulAssign(call, z2, v, p); - u1 = U384.modadd(call, u1, u0, p); + u1 = U384.modadd(u1, u0, p); U384.modmulAssign(call, u1, u2, p); U384.subAssignTo(diff, p, u1); - U384.modaddAssign(call, z2, diff, p); + U384.modaddAssign(z2, diff, p); uint256 u3 = U384.modmul(call, u2, x2, p); @@ -352,12 +352,12 @@ contract CECDSASHA2Signer is ICertificateSigner, Initializable { u0 = U384.modmul(call, u0, u2, p); U384.subAssignTo(diff, p, z2); - U384.modaddAssign(call, u0, diff, p); + U384.modaddAssign(u0, diff, p); U384.modmulAssign(call, y2, u0, p); t0 = U384.modmul(call, t0, u3, p); U384.subAssignTo(diff, p, t0); - U384.modaddAssign(call, y2, diff, p); + U384.modaddAssign(y2, diff, p); U384.modmulAssignTo(call, z2, u3, v, p); } diff --git a/contracts/utils/U384.sol b/contracts/utils/U384.sol index d4f0716..2910100 100644 --- a/contracts/utils/U384.sol +++ b/contracts/utils/U384.sol @@ -224,68 +224,36 @@ library U384 { } } - function modadd( - uint256 call_, - uint256 a_, - uint256 b_, - uint256 m_ - ) internal view returns (uint256 r_) { + function modadd(uint256 a_, uint256 b_, uint256 m_) internal view returns (uint256 r_) { unchecked { r_ = _allocate(SHORT_ALLOCATION); - _add(a_, b_, call_ + 0x60); - - assembly { - mstore(call_, 0x40) - mstore(add(0x20, call_), 0x20) - mstore(add(0x40, call_), 0x40) - mstore(add(0xA0, call_), 0x01) - mstore(add(0xC0, call_), mload(m_)) - mstore(add(0xE0, call_), mload(add(m_, 0x20))) + _add(a_, b_, r_); - pop(staticcall(gas(), 0x5, call_, 0x0100, r_, 0x40)) + if (cmp(r_, m_) >= 0) { + _subFrom(r_, m_); } return r_; } } - function modaddAssign(uint256 call_, uint256 a_, uint256 b_, uint256 m_) internal view { + function modaddAssign(uint256 a_, uint256 b_, uint256 m_) internal view { unchecked { - _add(a_, b_, call_ + 0x60); - - assembly { - mstore(call_, 0x40) - mstore(add(0x20, call_), 0x20) - mstore(add(0x40, call_), 0x40) - mstore(add(0xA0, call_), 0x01) - mstore(add(0xC0, call_), mload(m_)) - mstore(add(0xE0, call_), mload(add(m_, 0x20))) + _addTo(a_, b_); - pop(staticcall(gas(), 0x5, call_, 0x0100, a_, 0x40)) + if (cmp(a_, m_) >= 0) { + return _subFrom(a_, m_); } } } - function modaddAssignTo( - uint256 call_, - uint256 to_, - uint256 a_, - uint256 b_, - uint256 m_ - ) internal view { + function modaddAssignTo(uint256 to_, uint256 a_, uint256 b_, uint256 m_) internal view { unchecked { - _add(a_, b_, call_ + 0x60); + _add(a_, b_, to_); - assembly { - mstore(call_, 0x40) - mstore(add(0x20, call_), 0x20) - mstore(add(0x40, call_), 0x40) - mstore(add(0xA0, call_), 0x01) - mstore(add(0xC0, call_), mload(m_)) - mstore(add(0xE0, call_), mload(add(m_, 0x20))) - - pop(staticcall(gas(), 0x5, call_, 0x0100, to_, 0x40)) + if (cmp(to_, m_) >= 0) { + return _subFrom(to_, m_); } } } @@ -479,55 +447,36 @@ library U384 { } } - function modshl1(uint256 call_, uint256 a_, uint256 m_) internal view returns (uint256 r_) { + function modshl1(uint256 a_, uint256 m_) internal view returns (uint256 r_) { unchecked { r_ = _allocate(SHORT_ALLOCATION); - _shl1(a_, call_ + 0x60); + _shl1(a_, r_); - assembly { - mstore(call_, 0x40) - mstore(add(0x20, call_), 0x20) - mstore(add(0x40, call_), 0x40) - mstore(add(0xA0, call_), 0x01) - mstore(add(0xC0, call_), mload(m_)) - mstore(add(0xE0, call_), mload(add(m_, 0x20))) - - pop(staticcall(gas(), 0x5, call_, 0x0100, r_, 0x40)) + if (cmp(r_, m_) >= 0) { + _subFrom(r_, m_); } + + return r_; } } - function modshl1Assign(uint256 call_, uint256 a_, uint256 m_) internal view { + function modshl1Assign(uint256 a_, uint256 m_) internal view { unchecked { - _shl1(a_, call_ + 0x60); - - assembly { - mstore(call_, 0x40) - mstore(add(0x20, call_), 0x20) - mstore(add(0x40, call_), 0x40) - mstore(add(0xA0, call_), 0x01) - mstore(add(0xC0, call_), mload(m_)) - mstore(add(0xE0, call_), mload(add(m_, 0x20))) + _shl1To(a_); - pop(staticcall(gas(), 0x5, call_, 0x0100, a_, 0x40)) + if (cmp(a_, m_) >= 0) { + _subFrom(a_, m_); } } } - function modshl1AssignTo(uint256 call_, uint256 to_, uint256 a_, uint256 m_) internal view { + function modshl1AssignTo(uint256 to_, uint256 a_, uint256 m_) internal view { unchecked { - _shl1(a_, call_ + 0x60); + _shl1(a_, to_); - assembly { - mstore(call_, 0x40) - mstore(add(0x20, call_), 0x20) - mstore(add(0x40, call_), 0x40) - mstore(add(0xA0, call_), 0x01) - mstore(add(0xC0, call_), mload(m_)) - mstore(add(0xE0, call_), mload(add(m_, 0x20))) - - pop(staticcall(gas(), 0x5, call_, 0x0100, to_, 0x40)) + if (cmp(to_, m_) >= 0) { + _subFrom(to_, m_); } } } @@ -542,6 +491,16 @@ library U384 { } } + function _shl1To(uint256 a_) internal pure { + assembly { + let a0_ := mload(a_) + let a1_ := mload(add(a_, 0x20)) + + mstore(a_, or(shl(1, a0_), shr(255, a1_))) + mstore(add(a_, 0x20), shl(1, a1_)) + } + } + function _add(uint256 a_, uint256 b_, uint256 r_) private pure { assembly { let aWord_ := mload(add(a_, 0x20)) @@ -570,6 +529,34 @@ library U384 { } } + function _subFrom(uint256 a_, uint256 b_) private pure { + assembly { + let aWord_ := mload(add(a_, 0x20)) + let diff_ := sub(aWord_, mload(add(b_, 0x20))) + + mstore(add(a_, 0x20), diff_) + + diff_ := gt(diff_, aWord_) + diff_ := sub(sub(mload(a_), mload(b_)), diff_) + + mstore(a_, diff_) + } + } + + function _addTo(uint256 a_, uint256 b_) private pure { + assembly { + let aWord_ := mload(add(a_, 0x20)) + let sum_ := add(aWord_, mload(add(b_, 0x20))) + + mstore(add(a_, 0x20), sum_) + + sum_ := gt(aWord_, sum_) + sum_ := add(sum_, add(mload(a_), mload(b_))) + + mstore(a_, sum_) + } + } + function _mul(uint256 a_, uint256 b_, uint256 r_) private view { assembly { let a0_ := mload(a_)