diff --git a/src/othentic/BLSAuthLibrary.sol b/src/othentic/BLSAuthLibrary.sol new file mode 100644 index 0000000..f87abfa --- /dev/null +++ b/src/othentic/BLSAuthLibrary.sol @@ -0,0 +1,51 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity >=0.8.25; + +/*______ __ __ __ __ + / \ / | / | / | / | +/$$$$$$ | _$$ |_ $$ |____ ______ _______ _$$ |_ $$/ _______ +$$ | $$ |/ $$ | $$ \ / \ / \ / $$ | / | / | +$$ | $$ |$$$$$$/ $$$$$$$ |/$$$$$$ |$$$$$$$ |$$$$$$/ $$ |/$$$$$$$/ +$$ | $$ | $$ | __ $$ | $$ |$$ $$ |$$ | $$ | $$ | __ $$ |$$ | +$$ \__$$ | $$ |/ |$$ | $$ |$$$$$$$$/ $$ | $$ | $$ |/ |$$ |$$ \_____ +$$ $$/ $$ $$/ $$ | $$ |$$ |$$ | $$ | $$ $$/ $$ |$$ | + $$$$$$/ $$$$/ $$/ $$/ $$$$$$$/ $$/ $$/ $$$$/ $$/ $$$$$$$/ +*/ + +import { BLS } from "./OthenticBLS.sol"; + +import "forge-std/console2.sol"; + +library OthenticBLSAuthLibrary { + using BLS for uint256[2]; + + bytes32 internal constant DOMAIN = keccak256("OthenticBLSAuth"); + + struct Signature { + uint256[2] signature; + } + + /// @dev because of backwards compatibility issues, _signature is memory + /// even though it should be calldata. Once old registration is removed, adjust accordingly + function isValidSignature( + Signature memory _signature, + address _signer, + address _contract, + uint256[4] memory _blsKey + ) internal view returns (bool) { + /// @dev signature verification succeeds if signature and pubkey are empty + if (!_signature.signature.isValidSignature()) return false; + + uint256[2] memory _messageHash = _message(_signer, _contract); + (bool _callSuccess, bool _result) = _signature.signature.verifySingle(_blsKey, _messageHash); + return _callSuccess && _result; + } + + /// @dev uses abi.encode twice because of the way the bls signatures are implemented in the CLI + /// if we want to reduce more gas we should look into how polygon implemented it + function _message(address _signer, address _contract) internal view returns (uint256[2] memory) { + // slither-disable-next-line calls-loop + bytes32 _hash = keccak256(abi.encode(_signer, _contract, block.chainid)); + return BLS.hashToPoint(DOMAIN, abi.encode(_hash)); + } +} diff --git a/src/othentic/ModExp.sol b/src/othentic/ModExp.sol new file mode 100644 index 0000000..24a7a53 --- /dev/null +++ b/src/othentic/ModExp.sol @@ -0,0 +1,685 @@ +// SPDX-License-Identifier: MIT + +/* MIT License + +Copyright (c) 2021 Hubble-Project + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + +*/ + +pragma solidity >=0.8.19; + +/** + @title Compute Inverse by Modular Exponentiation + @notice Compute $input^(N - 2) mod N$ using Addition Chain method. + Where N = 0x30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47 + and N - 2 = 0x30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd45 + @dev the function body is generated with the modified addchain script + see https://github.com/kobigurk/addchain/commit/2c37a2ace567a9bdc680b4e929c94aaaa3ec700f + */ +library ModexpInverse { + /** + * @notice computes inverse + * @dev computes $input^(N - 2) mod N$ using Addition Chain method. + * @param t2 the number to get the inverse of (uint256) + * @return t0 the inverse (uint256) + */ + function run(uint256 t2) internal pure returns (uint256 t0) { + // solhint-disable-next-line no-inline-assembly + assembly { + let n := 0x30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47 + t0 := mulmod(t2, t2, n) + let t5 := mulmod(t0, t2, n) + let t1 := mulmod(t5, t0, n) + let t3 := mulmod(t5, t5, n) + let t8 := mulmod(t1, t0, n) + let t4 := mulmod(t3, t5, n) + let t6 := mulmod(t3, t1, n) + t0 := mulmod(t3, t3, n) + let t7 := mulmod(t8, t3, n) + t3 := mulmod(t4, t3, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t5, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t2, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t2, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t8, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t8, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t2, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t8, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t2, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t5, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t7, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t1, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t5, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t8, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t1, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t2, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t6, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t7, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t1, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t5, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t1, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t5, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t6, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t6, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t1, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t8, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t6, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t1, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t4, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t6, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t2, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t8, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t8, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t1, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t2, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t7, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t3, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t2, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t2, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t5, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t6, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t5, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t5, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t3, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t4, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t3, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t1, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t2, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t1, n) + } + } +} + +/** + @title Compute Square Root by Modular Exponentiation + @notice Compute $input^{(N + 1) / 4} mod N$ using Addition Chain method. + Where N = 0x30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47 + and (N + 1) / 4 = 0xc19139cb84c680a6e14116da060561765e05aa45a1c72a34f082305b61f3f52 + */ +library ModexpSqrt { + /** + * @notice computes square root by modular exponentation + * @dev Compute $input^{(N + 1) / 4} mod N$ using Addition Chain method + * @param t6 the number to derive the square root of + * @return t0 the square root + */ + function run(uint256 t6) internal pure returns (uint256 t0) { + // solhint-disable-next-line no-inline-assembly + assembly { + let n := 0x30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47 + + t0 := mulmod(t6, t6, n) + let t4 := mulmod(t0, t6, n) + let t2 := mulmod(t4, t0, n) + let t3 := mulmod(t4, t4, n) + let t8 := mulmod(t2, t0, n) + let t1 := mulmod(t3, t4, n) + let t5 := mulmod(t3, t2, n) + t0 := mulmod(t3, t3, n) + let t7 := mulmod(t8, t3, n) + t3 := mulmod(t1, t3, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t4, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t6, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t6, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t8, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t8, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t6, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t8, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t6, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t4, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t7, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t2, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t4, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t8, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t2, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t6, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t5, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t7, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t2, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t4, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t2, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t4, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t5, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t5, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t2, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t8, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t5, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t2, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t1, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t5, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t6, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t8, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t8, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t2, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t6, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t7, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t3, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t6, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t6, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t4, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t5, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t4, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t4, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t3, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t1, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t3, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t2, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t0, n) + t0 := mulmod(t0, t1, n) + t0 := mulmod(t0, t0, n) + } + } +} diff --git a/src/othentic/OthenticBLS.sol b/src/othentic/OthenticBLS.sol new file mode 100644 index 0000000..1a207a2 --- /dev/null +++ b/src/othentic/OthenticBLS.sol @@ -0,0 +1,450 @@ +// SPDX-License-Identifier: MIT + +/* MIT License + +Copyright (c) 2021 Hubble-Project (natspec added by Polygon Technology) + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + +*/ + +pragma solidity >=0.8.19; + +import {ModexpInverse, ModexpSqrt} from "./ModExp.sol"; + +/** + @title Boneh–Lynn–Shacham (BLS) signature scheme on Barreto-Naehrig 254 bit curve (BN-254) + @notice BLS signature aggregation reduces the size of signature data to store on-chain + @dev points on G1 are used for signatures and messages, and on G2 for public keys + @dev Adapted to be an internal library instead of an abstract contract + */ +library BLS { + error InvalidPublicKeyCount(); + error InvalidPublicKeyMessageCount(); + error BNAddCallFailed(); + error InvalidFieldElement(); + error BadFTMappingImplementation(); + + // Field order + // prettier-ignore + uint256 private constant N = 21888242871839275222246405745257275088696311157297823662689037894645226208583; + + // Negated generator of G2 + // prettier-ignore + uint256 private constant N_G2_X1 = 11559732032986387107991004021392285783925812861821192530917403151452391805634; + // prettier-ignore + uint256 private constant N_G2_X0 = 10857046999023057135944570762232829481370756359578518086990519993285655852781; + // prettier-ignore + uint256 private constant N_G2_Y1 = 17805874995975841540914202342111839520379459829704422454583296818431106115052; + // prettier-ignore + uint256 private constant N_G2_Y0 = 13392588948715843804641432497768002650278120570034223513918757245338268106653; + + // sqrt(-3) + // prettier-ignore + uint256 private constant Z0 = 0x0000000000000000b3c4d79d41a91759a9e4c7e359b6b89eaec68e62effffffd; + // (sqrt(-3) - 1) / 2 + // prettier-ignore + uint256 private constant Z1 = 0x000000000000000059e26bcea0d48bacd4f263f1acdb5c4f5763473177fffffe; + + // prettier-ignore + uint256 private constant T24 = 0x1000000000000000000000000000000000000000000000000; + // prettier-ignore + uint256 private constant MASK24 = 0xffffffffffffffffffffffffffffffffffffffffffffffff; + + function verifySingle( + uint256[2] memory signature, + uint256[4] memory pubkey, + uint256[2] memory message + ) internal view returns (bool, bool) { + uint256[12] memory input = [ + signature[0], + signature[1], + N_G2_X1, + N_G2_X0, + N_G2_Y1, + N_G2_Y0, + message[0], + message[1], + pubkey[1], + pubkey[0], + pubkey[3], + pubkey[2] + ]; + uint256[1] memory out; + + bool callSuccess; + // solhint-disable-next-line no-inline-assembly + assembly { + callSuccess := staticcall(gas(), 8, input, 384, out, 0x20) + } + if (!callSuccess) { + return (false, false); + } + return (out[0] != 0, true); + } + + function verifyMultiple( + uint256[2] calldata signature, + uint256[4][] calldata pubkeys, + uint256[2][] calldata messages + ) internal view returns (bool checkResult, bool callSuccess) { + uint256 size = pubkeys.length; + if (size == 0) revert InvalidPublicKeyCount(); + if (size != messages.length) revert InvalidPublicKeyMessageCount(); + uint256 inputSize = (size + 1) * 6; + uint256[] memory input = new uint256[](inputSize); + input[0] = signature[0]; + input[1] = signature[1]; + input[2] = N_G2_X1; + input[3] = N_G2_X0; + input[4] = N_G2_Y1; + input[5] = N_G2_Y0; + for (uint256 i = 0; i < size; i++) { + input[i * 6 + 6] = messages[i][0]; + input[i * 6 + 7] = messages[i][1]; + input[i * 6 + 8] = pubkeys[i][1]; + input[i * 6 + 9] = pubkeys[i][0]; + input[i * 6 + 10] = pubkeys[i][3]; + input[i * 6 + 11] = pubkeys[i][2]; + } + uint256[1] memory out; + + // solhint-disable-next-line no-inline-assembly + assembly { + callSuccess := staticcall(gas(), 8, add(input, 0x20), mul(inputSize, 0x20), out, 0x20) + } + if (!callSuccess) { + return (false, false); + } + return (out[0] != 0, true); + } + + function verifyMultipleSameMsg( + uint256[2] calldata signature, + uint256[4][] calldata pubkeys, + uint256[2] calldata message + ) internal view returns (bool checkResult, bool callSuccess) { + uint256 size = pubkeys.length; + if (size == 0) revert InvalidPublicKeyCount(); + uint256 inputSize = (size + 1) * 6; + uint256[] memory input = new uint256[](inputSize); + input[0] = signature[0]; + input[1] = signature[1]; + input[2] = N_G2_X1; + input[3] = N_G2_X0; + input[4] = N_G2_Y1; + input[5] = N_G2_Y0; + for (uint256 i = 0; i < size; i++) { + input[i * 6 + 6] = message[0]; + input[i * 6 + 7] = message[1]; + input[i * 6 + 8] = pubkeys[i][1]; + input[i * 6 + 9] = pubkeys[i][0]; + input[i * 6 + 10] = pubkeys[i][3]; + input[i * 6 + 11] = pubkeys[i][2]; + } + uint256[1] memory out; + + // solhint-disable-next-line no-inline-assembly + assembly { + callSuccess := staticcall(gas(), 8, add(input, 0x20), mul(inputSize, 0x20), out, 0x20) + } + if (!callSuccess) { + return (false, false); + } + return (out[0] != 0, true); + } + + function hashToPoint(bytes32 domain, bytes memory message) internal view returns (uint256[2] memory) { + uint256[2] memory u = hashToField(domain, message); + uint256[2] memory p0 = mapToPoint(u[0]); + uint256[2] memory p1 = mapToPoint(u[1]); + uint256[4] memory bnAddInput; + bnAddInput[0] = p0[0]; + bnAddInput[1] = p0[1]; + bnAddInput[2] = p1[0]; + bnAddInput[3] = p1[1]; + bool success; + // solhint-disable-next-line no-inline-assembly + assembly { + success := staticcall(sub(gas(), 2000), 6, bnAddInput, 128, p0, 64) + switch success + case 0 { + invalid() + } + } + if (!success) revert BNAddCallFailed(); + return p0; + } + + function mapToPoint(uint256 _x) internal pure returns (uint256[2] memory p) { + if (_x >= N) revert InvalidFieldElement(); + uint256 x = _x; + + (, bool decision) = sqrt(x); + + uint256 a0 = mulmod(x, x, N); + a0 = addmod(a0, 4, N); + uint256 a1 = mulmod(x, Z0, N); + uint256 a2 = mulmod(a1, a0, N); + a2 = inverse(a2); + a1 = mulmod(a1, a1, N); + a1 = mulmod(a1, a2, N); + + // x1 + a1 = mulmod(x, a1, N); + x = addmod(Z1, N - a1, N); + // check curve + a1 = mulmod(x, x, N); + a1 = mulmod(a1, x, N); + a1 = addmod(a1, 3, N); + bool found; + (a1, found) = sqrt(a1); + if (found) { + if (!decision) { + a1 = N - a1; + } + return [x, a1]; + } + + // x2 + x = N - addmod(x, 1, N); + // check curve + a1 = mulmod(x, x, N); + a1 = mulmod(a1, x, N); + a1 = addmod(a1, 3, N); + (a1, found) = sqrt(a1); + if (found) { + if (!decision) { + a1 = N - a1; + } + return [x, a1]; + } + + // x3 + x = mulmod(a0, a0, N); + x = mulmod(x, x, N); + x = mulmod(x, a2, N); + x = mulmod(x, a2, N); + x = addmod(x, 1, N); + // must be on curve + a1 = mulmod(x, x, N); + a1 = mulmod(a1, x, N); + a1 = addmod(a1, 3, N); + (a1, found) = sqrt(a1); + // solhint-disable-next-line reason-string + if (!found) revert BadFTMappingImplementation(); + if (!decision) { + a1 = N - a1; + } + return [x, a1]; + } + + function isValidSignature(uint256[2] memory signature) internal pure returns (bool) { + if ((signature[0] >= N) || (signature[1] >= N)) { + return false; + } else { + return isOnCurveG1(signature); + } + } + + function isOnCurveG1(uint256[2] memory point) internal pure returns (bool _isOnCurve) { + // solhint-disable-next-line no-inline-assembly + assembly { + let t0 := mload(point) + let t1 := mload(add(point, 32)) + let t2 := mulmod(t0, t0, N) + t2 := mulmod(t2, t0, N) + t2 := addmod(t2, 3, N) + t1 := mulmod(t1, t1, N) + _isOnCurve := eq(t1, t2) + } + } + + function isOnCurveG2(uint256[4] memory point) internal pure returns (bool _isOnCurve) { + // solhint-disable-next-line no-inline-assembly + assembly { + // x0, x1 + let t0 := mload(point) + let t1 := mload(add(point, 32)) + // x0 ^ 2 + let t2 := mulmod(t0, t0, N) + // x1 ^ 2 + let t3 := mulmod(t1, t1, N) + // 3 * x0 ^ 2 + let t4 := add(add(t2, t2), t2) + // 3 * x1 ^ 2 + let t5 := addmod(add(t3, t3), t3, N) + // x0 * (x0 ^ 2 - 3 * x1 ^ 2) + t2 := mulmod(add(t2, sub(N, t5)), t0, N) + // x1 * (3 * x0 ^ 2 - x1 ^ 2) + t3 := mulmod(add(t4, sub(N, t3)), t1, N) + + // x ^ 3 + b + t0 := addmod(t2, 0x2b149d40ceb8aaae81be18991be06ac3b5b4c5e559dbefa33267e6dc24a138e5, N) + t1 := addmod(t3, 0x009713b03af0fed4cd2cafadeed8fdf4a74fa084e52d1852e4a2bd0685c315d2, N) + + // y0, y1 + t2 := mload(add(point, 64)) + t3 := mload(add(point, 96)) + // y ^ 2 + t4 := mulmod(addmod(t2, t3, N), addmod(t2, sub(N, t3), N), N) + t3 := mulmod(shl(1, t2), t3, N) + + // y ^ 2 == x ^ 3 + b + _isOnCurve := and(eq(t0, t4), eq(t1, t3)) + } + } + + /** + * @notice returns square root of a uint256 value + * @param xx the value to take the square root of + * @return x the uint256 value of the root + * @return hasRoot a bool indicating if there is a square root + */ + function sqrt(uint256 xx) internal pure returns (uint256 x, bool hasRoot) { + x = ModexpSqrt.run(xx); + hasRoot = mulmod(x, x, N) == xx; + } + + /** + * @notice inverts a uint256 value + * @param a uint256 value to invert + * @return uint256 of the value of the inverse + */ + function inverse(uint256 a) internal pure returns (uint256) { + return ModexpInverse.run(a); + } + + function hashToField(bytes32 domain, bytes memory messages) internal pure returns (uint256[2] memory) { + bytes memory _msg = expandMsgTo96(domain, messages); + uint256 u0; + uint256 u1; + uint256 a0; + uint256 a1; + // solhint-disable-next-line no-inline-assembly + assembly { + let p := add(_msg, 24) + u1 := and(mload(p), MASK24) + p := add(_msg, 48) + u0 := and(mload(p), MASK24) + a0 := addmod(mulmod(u1, T24, N), u0, N) + p := add(_msg, 72) + u1 := and(mload(p), MASK24) + p := add(_msg, 96) + u0 := and(mload(p), MASK24) + a1 := addmod(mulmod(u1, T24, N), u0, N) + } + return [a0, a1]; + } + + function expandMsgTo96(bytes32 domain, bytes memory message) internal pure returns (bytes memory) { + // zero<64>|msg|lib_str<2>|I2OSP(0, 1)<1>|dst|dst_len<1> + uint256 t0 = message.length; + bytes memory msg0 = new bytes(32 + t0 + 64 + 4); + bytes memory out = new bytes(96); + // b0 + // solhint-disable-next-line no-inline-assembly + assembly { + let p := add(msg0, 96) + for { + let z := 0 + } lt(z, t0) { + z := add(z, 32) + } { + mstore(add(p, z), mload(add(message, add(z, 32)))) + } + p := add(p, t0) + + mstore8(p, 0) + p := add(p, 1) + mstore8(p, 96) + p := add(p, 1) + mstore8(p, 0) + p := add(p, 1) + + mstore(p, domain) + p := add(p, 32) + mstore8(p, 32) + } + bytes32 b0 = sha256(msg0); + bytes32 bi; + t0 = 32 + 34; + + // resize intermediate message + // solhint-disable-next-line no-inline-assembly + assembly { + mstore(msg0, t0) + } + + // b1 + + // solhint-disable-next-line no-inline-assembly + assembly { + mstore(add(msg0, 32), b0) + mstore8(add(msg0, 64), 1) + mstore(add(msg0, 65), domain) + mstore8(add(msg0, add(32, 65)), 32) + } + + bi = sha256(msg0); + + // solhint-disable-next-line no-inline-assembly + assembly { + mstore(add(out, 32), bi) + } + + // b2 + + // solhint-disable-next-line no-inline-assembly + assembly { + let t := xor(b0, bi) + mstore(add(msg0, 32), t) + mstore8(add(msg0, 64), 2) + mstore(add(msg0, 65), domain) + mstore8(add(msg0, add(32, 65)), 32) + } + + bi = sha256(msg0); + + // solhint-disable-next-line no-inline-assembly + assembly { + mstore(add(out, 64), bi) + } + + // b3 + + // solhint-disable-next-line no-inline-assembly + assembly { + let t := xor(b0, bi) + mstore(add(msg0, 32), t) + mstore8(add(msg0, 64), 3) + mstore(add(msg0, 65), domain) + mstore8(add(msg0, add(32, 65)), 32) + } + + bi = sha256(msg0); + + // solhint-disable-next-line no-inline-assembly + assembly { + mstore(add(out, 96), bi) + } + + return out; + } +} diff --git a/test/AlignedLayer.t.sol b/test/AlignedLayer.t.sol new file mode 100644 index 0000000..b396b1e --- /dev/null +++ b/test/AlignedLayer.t.sol @@ -0,0 +1,56 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.24; + +import "../test/TestSetup.sol"; +import "../test/CryptoTestHelpers.t.sol"; + +contract AlignedLayerTest is TestSetup, CryptoTestHelper { + + function test_registerAlignedLayer() public { + initializeRealisticFork(MAINNET_FORK); + upgradeAvsContracts(); + + IRegistryCoordinator registryCoordinator = IRegistryCoordinator(address(0xA8CC0749b4409c3c47012323E625aEcBA92f64b9)); + address serviceManager = address(0xeF2A435e5EE44B2041100EF8cbC8ae035166606c); + + uint256 operatorId = 1; + address operator = address(avsOperatorManager.avsOperators(operatorId)); + + // re-configure signer for testing + uint256 signerKey = 0x1234abcd; + { + address signer = vm.addr(signerKey); + vm.prank(admin); + avsOperatorManager.updateEcdsaSigner(operatorId, signer); + } + + // generate + sign the pubkey registration params with BLS key + IBLSApkRegistry.PubkeyRegistrationParams memory blsPubkeyRegistrationParams; + { + uint256 blsPrivKey = 0xaaaabbbb; + + // generate the hash we need to sign with the BLS key + BN254.G1Point memory blsPubkeyRegistrationHash = registryCoordinator.pubkeyRegistrationMessageHash(operator); + + // sign + blsPubkeyRegistrationParams = generateSignedPubkeyRegistrationParams(blsPubkeyRegistrationHash, blsPrivKey); + } + + // generate + sign operator registration digest with signer ECDSA key + ISignatureUtils.SignatureWithSaltAndExpiry memory signatureWithSaltAndExpiry; + { + address avsDirectory = address(0x135DDa560e946695d6f155dACaFC6f1F25C1F5AF); + signatureWithSaltAndExpiry = generateAvsRegistrationSignature(avsDirectory, operator, serviceManager, signerKey); + } + + // register + { + bytes memory quorums = hex"00"; + string memory socket = "https://test-socket"; + + vm.prank(operator); + registryCoordinator.registerOperator(quorums, socket, blsPubkeyRegistrationParams, signatureWithSaltAndExpiry); + } + } + +} diff --git a/test/Gasp.t.sol b/test/Gasp.t.sol new file mode 100644 index 0000000..efc37c0 --- /dev/null +++ b/test/Gasp.t.sol @@ -0,0 +1,64 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.24; + +import "../test/TestSetup.sol"; +import "../test/CryptoTestHelpers.t.sol"; + +interface IGaspUnpauser { + function unpause(uint256 status) external; +} + +contract GaspTest is TestSetup, CryptoTestHelper { + + function test_registerGasp() public { + initializeRealisticFork(MAINNET_FORK); + upgradeAvsContracts(); + + IRegistryCoordinator gaspRegistryCoordinator = IRegistryCoordinator(address(0x9A986296d45C327dAa5998519AE1B3757F1e6Ba1)); + address gaspServiceManager = address(0x3aDdEb54ddd43Eb40235eC32DfA7928F28A44bb5); + + uint256 operatorId = 1; + address operator = address(avsOperatorManager.avsOperators(operatorId)); + + // re-configure signer for testing + uint256 signerKey = 0x1234abcd; + { + address signer = vm.addr(signerKey); + vm.prank(admin); + avsOperatorManager.updateEcdsaSigner(operatorId, signer); + } + + // generate + sign the pubkey registration params with BLS key + IBLSApkRegistry.PubkeyRegistrationParams memory blsPubkeyRegistrationParams; + { + uint256 blsPrivKey = 0xaaaabbbb; + + // generate the hash we need to sign with the BLS key + BN254.G1Point memory blsPubkeyRegistrationHash = gaspRegistryCoordinator.pubkeyRegistrationMessageHash(operator); + + // sign + blsPubkeyRegistrationParams = generateSignedPubkeyRegistrationParams(blsPubkeyRegistrationHash, blsPrivKey); + } + + // generate + sign operator registration digest with signer ECDSA key + ISignatureUtils.SignatureWithSaltAndExpiry memory signatureWithSaltAndExpiry; + { + address avsDirectory = address(0x135DDa560e946695d6f155dACaFC6f1F25C1F5AF); + signatureWithSaltAndExpiry = generateAvsRegistrationSignature(avsDirectory, operator, gaspServiceManager, signerKey); + } + + // unpause their contracts + vm.prank(gaspRegistryCoordinator.owner()); + IGaspUnpauser(address(gaspRegistryCoordinator)).unpause(0); + + // register + { + bytes memory quorums = hex"00"; + string memory socket = "https://test-socket"; + + vm.prank(operator); + gaspRegistryCoordinator.registerOperator(quorums, socket, blsPubkeyRegistrationParams, signatureWithSaltAndExpiry); + } + } + +} diff --git a/test/Predicate.t.sol b/test/Predicate.t.sol new file mode 100644 index 0000000..0653c89 --- /dev/null +++ b/test/Predicate.t.sol @@ -0,0 +1,47 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.24; + +import "../test/TestSetup.sol"; +import "../test/CryptoTestHelpers.t.sol"; + +import "../src/eigenlayer-interfaces/IAVSDirectory.sol"; + +interface IPredicateRegistry { + function registerOperatorToAVS(address _operatorSigningKey, ISignatureUtils.SignatureWithSaltAndExpiry memory _operatorSignature) external; +} + +contract PredicateTest is TestSetup, CryptoTestHelper { + + function test_registerPredicate() public { + initializeRealisticFork(MAINNET_FORK); + upgradeAvsContracts(); + + IPredicateRegistry predicateRegsitry = IPredicateRegistry(address(0xaCB91045B8bBa06f9026e1A30855B6C4A1c5BaC6)); + address serviceManager = address(predicateRegsitry); // registry contract is used as the service manager + + uint256 operatorId = 1; + address operator = address(avsOperatorManager.avsOperators(operatorId)); + + // re-configure signer for testing + uint256 signerKey = 0x1234abcd; + address signer = vm.addr(signerKey); + { + vm.prank(admin); + avsOperatorManager.updateEcdsaSigner(operatorId, signer); + } + + // generate + sign operator registration digest with signer ECDSA key + ISignatureUtils.SignatureWithSaltAndExpiry memory signatureWithSaltAndExpiry; + { + address avsDirectory = address(0x135DDa560e946695d6f155dACaFC6f1F25C1F5AF); + signatureWithSaltAndExpiry = generateAvsRegistrationSignature(avsDirectory, operator, serviceManager, signerKey); + } + + // key controlled by the node operator, not us + uint256 externalSigningKey = 0x0987654321; + address externalSigningAddress = vm.addr(externalSigningKey); + + vm.prank(operator); + predicateRegsitry.registerOperatorToAVS(externalSigningAddress, signatureWithSaltAndExpiry); + } +} diff --git a/test/Ungate.t.sol b/test/Ungate.t.sol index 998eea2..43fa71d 100644 --- a/test/Ungate.t.sol +++ b/test/Ungate.t.sol @@ -133,6 +133,7 @@ contract UngateTest is TestSetup, CryptoTestHelper { blsSignature[0] = blsPubkeyRegistrationParams.pubkeyRegistrationSignature.X; blsSignature[1] = blsPubkeyRegistrationParams.pubkeyRegistrationSignature.Y; + // XXX: verification precompile expects little endian for G2 hence reversing the parts of each point blsPubkey[0] = blsPubkeyRegistrationParams.pubkeyG2.X[1]; blsPubkey[1] = blsPubkeyRegistrationParams.pubkeyG2.X[0];