From 8247e9bcdcae364f230ae7c192605c6af486a6b2 Mon Sep 17 00:00:00 2001 From: alrxy Date: Tue, 26 Nov 2024 14:23:46 +0700 Subject: [PATCH] refactor: rename ed25519 to eddsa, key storage to extensions, add base key manager --- .../SelfRegisterEd25519Middleware.sol | 6 +-- .../SelfRegisterMiddleware.sol | 2 +- .../SimplePosMiddleware.sol | 6 +-- .../sqrt-task-network/SqrtTaskMiddleware.sol | 4 +- src/libraries/{Ed25519.sol => EdDSA.sol} | 12 ++--- src/managers/KeyManager.sol | 45 ++++++++++++++++ src/middleware/BaseMiddleware.sol | 46 ++++------------ .../key-storages}/KeyStorage256.sol | 9 ++-- .../key-storages}/KeyStorageBytes.sol | 14 ++--- .../extensions/key-storages/NoKeyStorage.sol | 52 +++++++++++++++++++ .../sigs/{Ed25519Sig.sol => EdDSASig.sol} | 14 ++--- 11 files changed, 140 insertions(+), 70 deletions(-) rename src/libraries/{Ed25519.sol => EdDSA.sol} (92%) create mode 100644 src/managers/KeyManager.sol rename src/{key-storage => middleware/extensions/key-storages}/KeyStorage256.sol (93%) rename src/{key-storage => middleware/extensions/key-storages}/KeyStorageBytes.sol (92%) create mode 100644 src/middleware/extensions/key-storages/NoKeyStorage.sol rename src/middleware/extensions/sigs/{Ed25519Sig.sol => EdDSASig.sol} (80%) diff --git a/src/examples/self-register-network/SelfRegisterEd25519Middleware.sol b/src/examples/self-register-network/SelfRegisterEd25519Middleware.sol index 0c06061..aa4067f 100644 --- a/src/examples/self-register-network/SelfRegisterEd25519Middleware.sol +++ b/src/examples/self-register-network/SelfRegisterEd25519Middleware.sol @@ -15,14 +15,14 @@ import {SelfRegisterOperators} from "../../middleware/extensions/operators/SelfR import {NoAccessManager} from "../../middleware/extensions/access-managers/NoAccessManager.sol"; import {TimestampCapture} from "../../middleware/extensions/capture-timestamps/TimestampCapture.sol"; -import {KeyStorage256} from "../../key-storage/KeyStorage256.sol"; -import {Ed25519Sig} from "../../middleware/extensions/sigs/Ed25519Sig.sol"; +import {KeyStorage256} from "../../middleware/extensions/key-storages/KeyStorage256.sol"; +import {EdDSASig} from "../../middleware/extensions/sigs/EdDSASig.sol"; contract SelfRegisterEd25519Middleware is SharedVaults, SelfRegisterOperators, KeyStorage256, - Ed25519Sig, + EdDSASig, NoAccessManager, TimestampCapture { diff --git a/src/examples/self-register-network/SelfRegisterMiddleware.sol b/src/examples/self-register-network/SelfRegisterMiddleware.sol index 6b7738a..a063e35 100644 --- a/src/examples/self-register-network/SelfRegisterMiddleware.sol +++ b/src/examples/self-register-network/SelfRegisterMiddleware.sol @@ -16,7 +16,7 @@ import {ECDSASig} from "../../middleware/extensions/sigs/ECDSASig.sol"; import {NoAccessManager} from "../../middleware/extensions/access-managers/NoAccessManager.sol"; import {TimestampCapture} from "../../middleware/extensions/capture-timestamps/TimestampCapture.sol"; -import {KeyStorage256} from "../../key-storage/KeyStorage256.sol"; +import {KeyStorage256} from "../../middleware/extensions/key-storages/KeyStorage256.sol"; contract SelfRegisterMiddleware is SharedVaults, diff --git a/src/examples/simple-pos-network/SimplePosMiddleware.sol b/src/examples/simple-pos-network/SimplePosMiddleware.sol index 9f8620b..5a4b05b 100644 --- a/src/examples/simple-pos-network/SimplePosMiddleware.sol +++ b/src/examples/simple-pos-network/SimplePosMiddleware.sol @@ -14,7 +14,7 @@ import {SharedVaults} from "../../middleware/extensions/SharedVaults.sol"; import {Operators} from "../../middleware/extensions/operators/Operators.sol"; import {OwnableAccessManager} from "../../middleware/extensions/access-managers/OwnableAccessManager.sol"; import {EpochCapture} from "../../middleware/extensions/capture-timestamps/EpochCapture.sol"; -import {KeyStorage256} from "../../key-storage/KeyStorage256.sol"; +import {KeyStorage256} from "../../middleware/extensions/key-storages/KeyStorage256.sol"; contract SimplePosMiddleware is SharedVaults, Operators, KeyStorage256, OwnableAccessManager, EpochCapture { using Subnetwork for address; @@ -104,7 +104,7 @@ contract SimplePosMiddleware is SharedVaults, Operators, KeyStorage256, OwnableA address operator = operators[i]; // Get the operator address bytes32 key = abi.decode(operatorKey(operator), (bytes32)); // Get the key for the operator - if (key == bytes32(0) || !keyWasActiveAt(getCaptureTimestamp(), key)) { + if (key == bytes32(0) || !keyWasActiveAt(getCaptureTimestamp(), abi.encode(key))) { continue; // Skip if the key is inactive } @@ -180,7 +180,7 @@ contract SimplePosMiddleware is SharedVaults, Operators, KeyStorage256, OwnableA revert NotExistKeySlash(); // Revert if the operator does not exist } - if (!keyWasActiveAt(epochStart, key)) { + if (!keyWasActiveAt(epochStart, abi.encode(key))) { revert InactiveKeySlash(); // Revert if the key is inactive } diff --git a/src/examples/sqrt-task-network/SqrtTaskMiddleware.sol b/src/examples/sqrt-task-network/SqrtTaskMiddleware.sol index a08c458..51f43fd 100644 --- a/src/examples/sqrt-task-network/SqrtTaskMiddleware.sol +++ b/src/examples/sqrt-task-network/SqrtTaskMiddleware.sol @@ -14,13 +14,13 @@ import {BaseMiddleware} from "../../middleware/BaseMiddleware.sol"; import {SharedVaults} from "../../middleware/extensions/SharedVaults.sol"; import {Operators} from "../../middleware/extensions/operators/Operators.sol"; import {OwnableAccessManager} from "../../middleware/extensions/access-managers/OwnableAccessManager.sol"; -import {KeyStorage256} from "../../key-storage/KeyStorage256.sol"; +import {NoKeyStorage} from "../../middleware/extensions/key-storages/NoKeyStorage.sol"; import {TimestampCapture} from "../../middleware/extensions/capture-timestamps/TimestampCapture.sol"; contract SqrtTaskMiddleware is SharedVaults, Operators, - KeyStorage256, + NoKeyStorage, EIP712, OwnableAccessManager, TimestampCapture diff --git a/src/libraries/Ed25519.sol b/src/libraries/EdDSA.sol similarity index 92% rename from src/libraries/Ed25519.sol rename to src/libraries/EdDSA.sol index 2969fe8..0dc0284 100644 --- a/src/libraries/Ed25519.sol +++ b/src/libraries/EdDSA.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity ^0.8.26; +pragma solidity ^0.8.25; import {SCL_EIP6565} from "@crypto-lib/lib/libSCL_EIP6565.sol"; import {SCL_sha512} from "@crypto-lib/hash/SCL_sha512.sol"; @@ -8,13 +8,13 @@ import {p, d, pMINUS_1} from "@crypto-lib/fields/SCL_wei25519.sol"; import {ModInv} from "@crypto-lib/modular/SCL_modular.sol"; /** - * @title Ed25519 - * @notice Library for verifying Ed25519 signatures on the Edwards curve - * @dev Implements signature verification and point decompression for Ed25519 + * @title EdDSA + * @notice Library for verifying EdDSA signatures on the Ed25519 curve + * @dev Implements signature verification and point decompression for EdDSA */ -library Ed25519 { +library EdDSA { /** - * @notice Verifies an Ed25519 signature against a message and public key + * @notice Verifies an EdDSA signature against a message and public key * @param message The message that was signed * @param signature The signature to verify, encoded as (r,s) coordinates * @param pubkey The compressed public key to verify against diff --git a/src/managers/KeyManager.sol b/src/managers/KeyManager.sol new file mode 100644 index 0000000..203c979 --- /dev/null +++ b/src/managers/KeyManager.sol @@ -0,0 +1,45 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.25; + +import {BaseManager} from "./BaseManager.sol"; + +/** + * @title KeyManager + * @notice Abstract contract for managing keys + */ +abstract contract KeyManager is BaseManager { + /** + * @notice Updates the key associated with an operator + * @param operator The address of the operator + * @param key The key to update + */ + + function _updateKey(address operator, bytes memory key) internal virtual; + + /** + * @notice Returns the operator address associated with a given key + * @param key The key for which to find the associated operator + * @return The address of the operator linked to the specified key + */ + function operatorByKey( + bytes memory key + ) public view virtual returns (address); + + /** + * @notice Returns the current or previous key for a given operator + * @dev Returns the previous key if the key was updated in the current epoch + * @param operator The address of the operator + * @return The key associated with the specified operator + */ + function operatorKey( + address operator + ) public view virtual returns (bytes memory); + + /** + * @notice Checks if a key was active at a specific timestamp + * @param timestamp The timestamp to check + * @param key The key to check + * @return True if the key was active at the timestamp, false otherwise + */ + function keyWasActiveAt(uint48 timestamp, bytes memory key) public view virtual returns (bool); +} diff --git a/src/middleware/BaseMiddleware.sol b/src/middleware/BaseMiddleware.sol index bcb5956..4bbcdb7 100644 --- a/src/middleware/BaseMiddleware.sol +++ b/src/middleware/BaseMiddleware.sol @@ -1,44 +1,16 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.25; -import {IVault} from "@symbiotic/interfaces/vault/IVault.sol"; -import {IBaseDelegator} from "@symbiotic/interfaces/delegator/IBaseDelegator.sol"; -import {Subnetwork} from "@symbiotic/contracts/libraries/Subnetwork.sol"; - -import {Time} from "@openzeppelin/contracts/utils/types/Time.sol"; -import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol"; -import {Math} from "@openzeppelin/contracts/utils/math/Math.sol"; - import {VaultManager} from "../managers/VaultManager.sol"; import {OperatorManager} from "../managers/OperatorManager.sol"; import {AccessManager} from "../managers/AccessManager.sol"; +import {KeyManager} from "../managers/KeyManager.sol"; -abstract contract BaseMiddleware is VaultManager, OperatorManager, AccessManager { - using Subnetwork for address; - /** - * @notice Updates the key associated with an operator - * @param operator The address of the operator - * @param key The key to update - */ - - function _updateKey(address operator, bytes memory key) internal virtual; - - /** - * @notice Returns the operator address associated with a given key - * @param key The key for which to find the associated operator - * @return The address of the operator linked to the specified key - */ - function operatorByKey( - bytes memory key - ) public view virtual returns (address); - - /** - * @notice Returns the current or previous key for a given operator - * @dev Returns the previous key if the key was updated in the current epoch - * @param operator The address of the operator - * @return The key associated with the specified operator - */ - function operatorKey( - address operator - ) public view virtual returns (bytes memory); -} +/** + * @title BaseMiddleware + * @notice Abstract base contract that combines core manager functionality + * @dev Inherits from VaultManager, OperatorManager, AccessManager and KeyManager to provide + * comprehensive middleware capabilities for vault and operator management, access control, + * and key management + */ +abstract contract BaseMiddleware is VaultManager, OperatorManager, AccessManager, KeyManager {} diff --git a/src/key-storage/KeyStorage256.sol b/src/middleware/extensions/key-storages/KeyStorage256.sol similarity index 93% rename from src/key-storage/KeyStorage256.sol rename to src/middleware/extensions/key-storages/KeyStorage256.sol index e153e41..281033b 100644 --- a/src/key-storage/KeyStorage256.sol +++ b/src/middleware/extensions/key-storages/KeyStorage256.sol @@ -1,8 +1,8 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.25; -import {BaseMiddleware} from "../middleware/BaseMiddleware.sol"; -import {PauseableEnumerableSet} from "../libraries/PauseableEnumerableSet.sol"; +import {BaseMiddleware} from "../../BaseMiddleware.sol"; +import {PauseableEnumerableSet} from "../../../libraries/PauseableEnumerableSet.sol"; import {Time} from "@openzeppelin/contracts/utils/types/Time.sol"; @@ -71,11 +71,12 @@ abstract contract KeyStorage256 is BaseMiddleware { /** * @notice Checks if a key was active at a specific timestamp * @param timestamp The timestamp to check - * @param key The key to check + * @param key_ The key to check * @return True if the key was active at the timestamp, false otherwise */ - function keyWasActiveAt(uint48 timestamp, bytes32 key) public view returns (bool) { + function keyWasActiveAt(uint48 timestamp, bytes memory key_) public view override returns (bool) { KeyStorage256Storage storage s = _getStorage(); + bytes32 key = abi.decode(key_, (bytes32)); return s.keys[s.keyToOperator[key]].wasActiveAt(timestamp, key); } diff --git a/src/key-storage/KeyStorageBytes.sol b/src/middleware/extensions/key-storages/KeyStorageBytes.sol similarity index 92% rename from src/key-storage/KeyStorageBytes.sol rename to src/middleware/extensions/key-storages/KeyStorageBytes.sol index 0f0b2b2..62ef739 100644 --- a/src/key-storage/KeyStorageBytes.sol +++ b/src/middleware/extensions/key-storages/KeyStorageBytes.sol @@ -1,8 +1,8 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.25; -import {BaseManager} from "../managers/BaseManager.sol"; -import {PauseableEnumerableSet} from "../libraries/PauseableEnumerableSet.sol"; +import {BaseMiddleware} from "../../BaseMiddleware.sol"; +import {PauseableEnumerableSet} from "../../../libraries/PauseableEnumerableSet.sol"; import {Time} from "@openzeppelin/contracts/utils/types/Time.sol"; @@ -11,7 +11,7 @@ import {Time} from "@openzeppelin/contracts/utils/types/Time.sol"; * @notice Manages storage and validation of operator keys * @dev Extends BaseManager to provide key management functionality */ -abstract contract KeyStorageBytes is BaseManager { +abstract contract KeyStorageBytes is BaseMiddleware { using PauseableEnumerableSet for PauseableEnumerableSet.BytesSet; using PauseableEnumerableSet for PauseableEnumerableSet.Status; @@ -45,7 +45,7 @@ abstract contract KeyStorageBytes is BaseManager { */ function operatorByKey( bytes memory key - ) public view returns (address) { + ) public view override returns (address) { KeyStorageBytesStorage storage $ = _getStorage(); return $._keyToOperator[key]; } @@ -57,7 +57,7 @@ abstract contract KeyStorageBytes is BaseManager { */ function operatorKey( address operator - ) public view returns (bytes memory) { + ) public view override returns (bytes memory) { KeyStorageBytesStorage storage $ = _getStorage(); bytes[] memory active = $._keys[operator].getActive(getCaptureTimestamp()); if (active.length == 0) { @@ -72,7 +72,7 @@ abstract contract KeyStorageBytes is BaseManager { * @param key The key to check * @return True if the key was active at the timestamp, false otherwise */ - function keyWasActiveAt(uint48 timestamp, bytes memory key) public view returns (bool) { + function keyWasActiveAt(uint48 timestamp, bytes memory key) public view override returns (bool) { KeyStorageBytesStorage storage $ = _getStorage(); return $._keys[$._keyToOperator[key]].wasActiveAt(timestamp, key); } @@ -85,7 +85,7 @@ abstract contract KeyStorageBytes is BaseManager { * @custom:throws DuplicateKey if key is already registered to another operator * @custom:throws MaxDisabledKeysReached if operator has too many disabled keys */ - function _updateKey(address operator, bytes memory key) internal { + function _updateKey(address operator, bytes memory key) internal override { KeyStorageBytesStorage storage $ = _getStorage(); bytes32 keyHash = keccak256(key); diff --git a/src/middleware/extensions/key-storages/NoKeyStorage.sol b/src/middleware/extensions/key-storages/NoKeyStorage.sol new file mode 100644 index 0000000..659d2f2 --- /dev/null +++ b/src/middleware/extensions/key-storages/NoKeyStorage.sol @@ -0,0 +1,52 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.25; + +import {BaseMiddleware} from "../../BaseMiddleware.sol"; + +/** + * @title NoKeyStorage + * @notice A middleware extension that provides no key storage functionality + * @dev Implements BaseMiddleware and always reverts on key operations + */ +abstract contract NoKeyStorage is BaseMiddleware { + bool public constant NoKeyStorageEnabled = true; + + error KeyStorageDisabled(); + + /** + * @notice Gets the operator address associated with a key + * @param key The key to lookup (unused) + * @return The operator address (always reverts) + */ + function operatorByKey(bytes memory key) public pure override returns (address) { + revert KeyStorageDisabled(); + } + + /** + * @notice Gets an operator's active key + * @param operator The operator address to lookup (unused) + * @return The operator's key (always reverts) + */ + function operatorKey(address operator) public pure override returns (bytes memory) { + revert KeyStorageDisabled(); + } + + /** + * @notice Checks if a key was active at a specific timestamp + * @param timestamp The timestamp to check (unused) + * @param key The key to check (unused) + * @return Whether key was active (always reverts) + */ + function keyWasActiveAt(uint48 timestamp, bytes memory key) public pure override returns (bool) { + revert KeyStorageDisabled(); + } + + /** + * @notice Updates an operator's key + * @param operator The operator address (unused) + * @param key The new key (unused) + */ + function _updateKey(address operator, bytes memory key) internal virtual override { + revert KeyStorageDisabled(); + } +} diff --git a/src/middleware/extensions/sigs/Ed25519Sig.sol b/src/middleware/extensions/sigs/EdDSASig.sol similarity index 80% rename from src/middleware/extensions/sigs/Ed25519Sig.sol rename to src/middleware/extensions/sigs/EdDSASig.sol index ea41282..35a8435 100644 --- a/src/middleware/extensions/sigs/Ed25519Sig.sol +++ b/src/middleware/extensions/sigs/EdDSASig.sol @@ -1,16 +1,16 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.25; -import {Ed25519} from "../../../libraries/Ed25519.sol"; +import {EdDSA} from "../../../libraries/EdDSA.sol"; import {BaseSig} from "./BaseSig.sol"; /** - * @title Ed25519Sig - * @notice Contract for verifying Ed25519 signatures against operator keys - * @dev Implements BaseSig interface using Ed25519 signature verification + * @title EdDSASig + * @notice Contract for verifying EdDSA signatures over Ed25519 against operator keys + * @dev Implements BaseSig interface using EdDSA signature verification */ -abstract contract Ed25519Sig is BaseSig { - bool public constant Ed25519SigEnabled = true; +abstract contract EdDSASig is BaseSig { + bool public constant EdDSASigEnabled = true; /** * @notice Verifies that a signature was created by the owner of a key @@ -40,6 +40,6 @@ abstract contract Ed25519Sig is BaseSig { * @dev Wrapper around Ed25519.verify which handles decompression and curve operations */ function verify(bytes memory message, bytes memory signature, bytes32 key) internal returns (bool) { - return Ed25519.verify(message, signature, key); + return EdDSA.verify(message, signature, key); } }