github.com/klaytn/klaytn@v1.12.1/contracts/system_contracts/kip113/KIP113.sol (about)

     1  // Copyright 2023 The klaytn Authors
     2  // This file is part of the klaytn library.
     3  //
     4  // The klaytn library is free software: you can redistribute it and/or modify
     5  // it under the terms of the GNU Lesser General Public License as published by
     6  // the Free Software Foundation, either version 3 of the License, or
     7  // (at your option) any later version.
     8  //
     9  // The klaytn library is distributed in the hope that it will be useful,
    10  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    11  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    12  // GNU Lesser General Public License for more details.
    13  //
    14  // You should have received a copy of the GNU Lesser General Public License
    15  // along with the klaytn library. If not, see <http://www.gnu.org/licenses/>.
    16  
    17  // SPDX-License-Identifier: LGPL-3.0-only
    18  pragma solidity ^0.8.18;
    19  
    20  import "./IKIP113.sol";
    21  import "./IAddressBook.sol";
    22  import "../lib/Initializable.sol";
    23  import "../lib/UUPSUpgradeable.sol";
    24  import "../lib/OwnableUpgradeable.sol";
    25  
    26  contract KIP113 is Initializable, UUPSUpgradeable, OwnableUpgradeable, IKIP113 {
    27      IAddressBook public constant abook = IAddressBook(0x0000000000000000000000000000000000000400);
    28      bytes32 public constant ZERO48HASH = 0xc980e59163ce244bb4bb6211f48c7b46f88a4f40943e84eb99bdc41e129bd293; // keccak256(hex"00"*48)
    29      bytes32 public constant ZERO96HASH = 0x46700b4d40ac5c35af2c22dda2787a91eb567b06c924a8fb8ae9a05b20c08c21; // keccak256(hex"00"*96)
    30  
    31      address[] public allNodeIds;
    32      mapping(address => BlsPublicKeyInfo) public record; // cnNodeId => BlsPublicKeyInfo
    33  
    34      event Registered(address cnNodeId, bytes publicKey, bytes pop);
    35      event Unregistered(address cnNodeId, bytes publicKey, bytes pop);
    36  
    37      modifier onlyValidPublicKey(bytes calldata publicKey) {
    38          require(publicKey.length == 48, "Public key must be 48 bytes");
    39          require(keccak256(publicKey) != ZERO48HASH, "Public key cannot be zero");
    40          // TODO: verify more with EIP-2537
    41          _;
    42      }
    43  
    44      modifier onlyValidPop(bytes calldata pop) {
    45          require(pop.length == 96, "Pop must be 96 bytes");
    46          require(keccak256(pop) != ZERO96HASH, "Pop cannot be zero");
    47          // TODO: verify more with EIP-2537
    48          _;
    49      }
    50  
    51      /// @custom:oz-upgrades-unsafe-allow constructor
    52      constructor() {
    53          _disableInitializers();
    54      }
    55  
    56      function initialize() public initializer {
    57          __Ownable_init();
    58          __UUPSUpgradeable_init();
    59      }
    60  
    61      function register(
    62          address cnNodeId,
    63          bytes calldata publicKey,
    64          bytes calldata pop
    65      ) external virtual onlyOwner onlyValidPublicKey(publicKey) onlyValidPop(pop) {
    66          require(isCN(cnNodeId), "cnNodeId is not in AddressBook");
    67          if (record[cnNodeId].publicKey.length == 0) {
    68              allNodeIds.push(cnNodeId);
    69          }
    70  
    71          record[cnNodeId] = BlsPublicKeyInfo(publicKey, pop);
    72          emit Registered(cnNodeId, publicKey, pop);
    73      }
    74  
    75      function unregister(address cnNodeId) external virtual onlyOwner {
    76          require(!isCN(cnNodeId), "CN is still in AddressBook");
    77          require(record[cnNodeId].publicKey.length != 0, "CN is not registered");
    78  
    79          _removeCnNodeId(cnNodeId);
    80          emit Unregistered(cnNodeId, record[cnNodeId].publicKey, record[cnNodeId].pop);
    81          delete record[cnNodeId];
    82      }
    83  
    84      function _removeCnNodeId(address cnNodeId) private {
    85          for (uint256 i = 0; i < allNodeIds.length; i++) {
    86              if (allNodeIds[i] == cnNodeId) {
    87                  allNodeIds[i] = allNodeIds[allNodeIds.length - 1];
    88                  allNodeIds.pop();
    89                  return;
    90              }
    91          }
    92      }
    93  
    94      function getAllBlsInfo()
    95          external
    96          view
    97          virtual
    98          returns (address[] memory nodeIdList, BlsPublicKeyInfo[] memory pubkeyList)
    99      {
   100          nodeIdList = new address[](allNodeIds.length);
   101          pubkeyList = new BlsPublicKeyInfo[](allNodeIds.length);
   102  
   103          for (uint256 i = 0; i < nodeIdList.length; i++) {
   104              nodeIdList[i] = allNodeIds[i];
   105              pubkeyList[i] = record[allNodeIds[i]];
   106          }
   107      }
   108  
   109      function isCN(address target) internal view virtual returns (bool) {
   110          try abook.getCnInfo(target) {
   111              return true;
   112          } catch {
   113              return false;
   114          }
   115      }
   116  
   117      function _authorizeUpgrade(address newImplementation) internal virtual override onlyOwner {}
   118  }