github.com/klaytn/klaytn@v1.12.1/cmd/homi/common/utils.go (about)

     1  // Copyright 2017 AMIS Technologies
     2  // This file is part of the go-ethereum library.
     3  //
     4  // The go-ethereum 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 go-ethereum 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 go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
    16  
    17  package common
    18  
    19  import (
    20  	"crypto/ecdsa"
    21  	"crypto/rand"
    22  	"crypto/sha512"
    23  	"fmt"
    24  	"os"
    25  	"path/filepath"
    26  	"strconv"
    27  	"strings"
    28  
    29  	"github.com/klaytn/klaytn/blockchain/system"
    30  	"github.com/klaytn/klaytn/common"
    31  	"github.com/klaytn/klaytn/common/hexutil"
    32  	"github.com/klaytn/klaytn/crypto"
    33  	"github.com/klaytn/klaytn/crypto/bls"
    34  	"github.com/klaytn/klaytn/log"
    35  	uuid "github.com/satori/go.uuid"
    36  	"github.com/tyler-smith/go-bip32"
    37  	"golang.org/x/crypto/pbkdf2"
    38  )
    39  
    40  const (
    41  	defaultLocalDir  = "/tmp/kdata"
    42  	clientIdentifier = "klay"
    43  )
    44  
    45  var logger = log.NewModuleLogger(log.CMDIstanbul)
    46  
    47  func GenerateRandomDir() (string, error) {
    48  	err := os.MkdirAll(filepath.Join(defaultLocalDir), 0o700)
    49  	if err != nil {
    50  		logger.Error("Failed to create dir", "dir", defaultLocalDir, "err", err)
    51  		return "", err
    52  	}
    53  
    54  	instanceDir := filepath.Join(defaultLocalDir, fmt.Sprintf("%s-%s", clientIdentifier, uuid.NewV4().String()))
    55  	if err := os.MkdirAll(instanceDir, 0o700); err != nil {
    56  		logger.Error("Failed to create dir", "dir", instanceDir, "err", err)
    57  		return "", err
    58  	}
    59  
    60  	return instanceDir, nil
    61  }
    62  
    63  func GenerateKeys(num int) (keys []*ecdsa.PrivateKey, nodekeys []string, addrs []common.Address) {
    64  	for i := 0; i < num; i++ {
    65  		nodekey := RandomHex()[2:]
    66  		nodekeys = append(nodekeys, nodekey)
    67  
    68  		key, err := crypto.HexToECDSA(nodekey)
    69  		if err != nil {
    70  			logger.Error("Failed to generate key", "err", err)
    71  			return nil, nil, nil
    72  		}
    73  		keys = append(keys, key)
    74  
    75  		addr := crypto.PubkeyToAddress(key.PublicKey)
    76  		addrs = append(addrs, addr)
    77  	}
    78  
    79  	return keys, nodekeys, addrs
    80  }
    81  
    82  func GenerateKeysFromMnemonic(num int, mnemonic, path string) (keys []*ecdsa.PrivateKey, nodekeys []string, addrs []common.Address) {
    83  	var key *bip32.Key
    84  
    85  	for _, level := range strings.Split(path, "/") {
    86  		if len(level) == 0 {
    87  			continue
    88  		}
    89  
    90  		if level == "m" {
    91  			seed := pbkdf2.Key([]byte(mnemonic), []byte("mnemonic"), 2048, 64, sha512.New)
    92  			key, _ = bip32.NewMasterKey(seed)
    93  		} else {
    94  			num := uint64(0)
    95  			var err error
    96  			if strings.HasSuffix(level, "'") {
    97  				num, err = strconv.ParseUint(level[:len(level)-1], 10, 32)
    98  				num += 0x80000000
    99  			} else {
   100  				num, err = strconv.ParseUint(level, 10, 32)
   101  			}
   102  			if err != nil {
   103  				logger.Error("Failed to parse path", "err", err)
   104  				return nil, nil, nil
   105  			}
   106  			key, _ = key.NewChildKey(uint32(num))
   107  		}
   108  	}
   109  
   110  	for i := 0; i < num; i++ {
   111  		derived, _ := key.NewChildKey(uint32(i))
   112  		nodekey := hexutil.Encode(derived.Key)[2:]
   113  		nodekeys = append(nodekeys, nodekey)
   114  
   115  		key, err := crypto.HexToECDSA(nodekey)
   116  		if err != nil {
   117  			logger.Error("Failed to generate key", "err", err)
   118  			return nil, nil, nil
   119  		}
   120  		keys = append(keys, key)
   121  
   122  		addr := crypto.PubkeyToAddress(key.PublicKey)
   123  		addrs = append(addrs, addr)
   124  	}
   125  
   126  	return keys, nodekeys, addrs
   127  }
   128  
   129  func GenerateKip113Init(privKeys []*ecdsa.PrivateKey, owner common.Address) system.AllocKip113Init {
   130  	init := system.AllocKip113Init{}
   131  	init.Infos = make(map[common.Address]system.BlsPublicKeyInfo)
   132  
   133  	for i, key := range privKeys {
   134  		blsKey, err := bls.GenerateKey(crypto.FromECDSA(privKeys[i]))
   135  		if err != nil {
   136  			logger.Error("Failed to generate bls key", "err", err)
   137  			continue
   138  		}
   139  		addr := crypto.PubkeyToAddress(key.PublicKey)
   140  		init.Infos[addr] = system.BlsPublicKeyInfo{
   141  			PublicKey: blsKey.PublicKey().Marshal(),
   142  			Pop:       bls.PopProve(blsKey).Marshal(),
   143  		}
   144  	}
   145  
   146  	init.Owner = owner
   147  
   148  	return init
   149  }
   150  
   151  func RandomHex() string {
   152  	b, _ := RandomBytes(32)
   153  	return common.BytesToHash(b).Hex()
   154  }
   155  
   156  func RandomBytes(len int) ([]byte, error) {
   157  	b := make([]byte, len)
   158  	_, _ = rand.Read(b)
   159  
   160  	return b, nil
   161  }
   162  
   163  func copyFile(src string, dst string) {
   164  	data, err := os.ReadFile(src)
   165  	if err != nil {
   166  		logger.Error("Failed to read file", "file", src, "err", err)
   167  		return
   168  	}
   169  	err = os.WriteFile(dst, data, 0o644)
   170  	if err != nil {
   171  		logger.Error("Failed to write file", "file", dst, "err", err)
   172  		return
   173  	}
   174  }