github.com/klaytn/klaytn@v1.12.1/blockchain/system/kip113.go (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  package system
    18  
    19  import (
    20  	"encoding/hex"
    21  	"encoding/json"
    22  	"math/big"
    23  	"sort"
    24  	"strings"
    25  
    26  	"github.com/klaytn/klaytn/accounts/abi/bind"
    27  	"github.com/klaytn/klaytn/common"
    28  	contracts "github.com/klaytn/klaytn/contracts/system_contracts"
    29  	"github.com/klaytn/klaytn/crypto/bls"
    30  )
    31  
    32  type BlsPublicKeyInfo struct {
    33  	PublicKey []byte
    34  	Pop       []byte
    35  	VerifyErr error // Nil if valid. Must check before use.
    36  }
    37  
    38  func newBlsPublicKeyInfo(publicKey []byte, pop []byte) BlsPublicKeyInfo {
    39  	return BlsPublicKeyInfo{
    40  		PublicKey: publicKey,
    41  		Pop:       pop,
    42  		VerifyErr: verifyBlsPublicKeyInfo(publicKey, pop),
    43  	}
    44  }
    45  
    46  func verifyBlsPublicKeyInfo(publicKey []byte, pop []byte) error {
    47  	pk, err := bls.PublicKeyFromBytes(publicKey)
    48  	if err != nil {
    49  		return err
    50  	}
    51  
    52  	sig, err := bls.SignatureFromBytes(pop)
    53  	if err != nil {
    54  		return err
    55  	}
    56  
    57  	if !bls.PopVerify(pk, sig) {
    58  		return ErrKip113BadPop
    59  	}
    60  
    61  	return nil
    62  }
    63  
    64  type BlsPublicKeyInfos map[common.Address]BlsPublicKeyInfo
    65  
    66  func (infos BlsPublicKeyInfos) String() string {
    67  	obj := make(map[string]string)
    68  	for addr, info := range infos {
    69  		obj[addr.Hex()] = hex.EncodeToString(info.PublicKey)
    70  	}
    71  	j, _ := json.Marshal(obj)
    72  	return string(j)
    73  }
    74  
    75  type AllocKip113Init struct {
    76  	Infos BlsPublicKeyInfos
    77  	Owner common.Address
    78  }
    79  
    80  func AllocKip113Proxy(init AllocKip113Init) map[common.Hash]common.Hash {
    81  	if init.Infos == nil {
    82  		return nil
    83  	}
    84  	storage := make(map[common.Hash]common.Hash)
    85  
    86  	// Overall storage layout for KIP113 contract:
    87  	//
    88  	// | Name          | Type                                                | Slot | Offset | Bytes |
    89  	// |---------------|-----------------------------------------------------|------|--------|-------|
    90  	// | _initialized  | uint8                                               | 0    | 0      | 1     |
    91  	// | _initializing | bool                                                | 0    | 1      | 1     |
    92  	// | __gap         | uint256[50]                                         | 1    | 0      | 1600  |
    93  	// | __gap         | uint256[50]                                         | 51   | 0      | 1600  |
    94  	// | __gap         | uint256[50]                                         | 101  | 0      | 1600  |
    95  	// | _owner        | address                                             | 151  | 0      | 20    |
    96  	// | __gap         | uint256[49]                                         | 152  | 0      | 1568  |
    97  	// | allNodeIds    | address[]                                           | 201  | 0      | 32    |
    98  	// | record        | mapping(address => struct IKIP113.BlsPublicKeyInfo) | 202  | 0      | 32    |
    99  	//
   100  	// We need to consider the following:
   101  	storage[lpad32(0)] = lpad32([]byte{0, 1}) // false, 1
   102  	storage[lpad32(151)] = lpad32(init.Owner)
   103  
   104  	addrs := make([]common.Address, 0)
   105  	for addr := range init.Infos {
   106  		addrs = append(addrs, addr)
   107  	}
   108  	sort.Slice(addrs, func(i, j int) bool {
   109  		return strings.Compare(addrs[i].Hex(), addrs[j].Hex()) > 0
   110  	})
   111  
   112  	// slot[201]: address[] allNodeIds;
   113  	// - addrs.length @ 0
   114  	// - addrs[i] @ Hash(201) + i
   115  	storage[lpad32(201)] = lpad32(len(addrs))
   116  	for i, addr := range addrs {
   117  		addrSlot := calcArraySlot(201, 1, i, 0)
   118  		storage[addrSlot] = lpad32(addr)
   119  	}
   120  
   121  	// slot[202]: mapping(address => BlsPublicKeyInfo) record;
   122  	// - infos[x].publicKey.length @ Hash(x, 202)      = el
   123  	// - infos[x].publicKey        @ Hash(el) + 0..1
   124  	// - infos[x].pop.length       @ Hash(x, 202) + 1  = el
   125  	// - infos[x].pop              @ Hash(el) + 0..2
   126  	for addr, info := range init.Infos {
   127  		// The below slot calculation assumes 48-byte and 96-byte Solidity `bytes` values.
   128  		if len(info.PublicKey) != 48 || len(info.Pop) != 96 {
   129  			logger.Crit("Invalid AllocKip113Init")
   130  		}
   131  
   132  		pubSlot := calcMappingSlot(202, addr, 0)
   133  		popSlot := calcMappingSlot(202, addr, 1)
   134  
   135  		for k, v := range allocDynamicData(pubSlot, info.PublicKey) {
   136  			storage[k] = v
   137  		}
   138  		for k, v := range allocDynamicData(popSlot, info.Pop) {
   139  			storage[k] = v
   140  		}
   141  	}
   142  
   143  	return storage
   144  }
   145  
   146  func AllocKip113Logic() map[common.Hash]common.Hash {
   147  	storage := make(map[common.Hash]common.Hash)
   148  
   149  	// We only need to case about _initialized, which is max(uint8).
   150  	storage[lpad32(0)] = lpad32([]byte{0xff})
   151  
   152  	return storage
   153  }
   154  
   155  func ReadKip113All(backend bind.ContractCaller, contractAddr common.Address, num *big.Int) (BlsPublicKeyInfos, error) {
   156  	caller, err := contracts.NewIKIP113Caller(contractAddr, backend)
   157  	if err != nil {
   158  		return nil, err
   159  	}
   160  
   161  	opts := &bind.CallOpts{BlockNumber: num}
   162  	ret, err := caller.GetAllBlsInfo(opts)
   163  	if err != nil {
   164  		return nil, err
   165  	}
   166  
   167  	if len(ret.NodeIdList) != len(ret.PubkeyList) {
   168  		return nil, ErrKip113BadResult
   169  	}
   170  
   171  	infos := make(BlsPublicKeyInfos)
   172  	for i := 0; i < len(ret.NodeIdList); i++ {
   173  		addr := ret.NodeIdList[i]
   174  		infos[addr] = newBlsPublicKeyInfo(
   175  			ret.PubkeyList[i].PublicKey,
   176  			ret.PubkeyList[i].Pop,
   177  		)
   178  	}
   179  
   180  	return infos, err
   181  }