github.com/pokt-network/tendermint@v0.32.11-0.20230426215212-59310158d3e9/p2p/key.go (about)

     1  package p2p
     2  
     3  import (
     4  	"bytes"
     5  	"encoding/hex"
     6  	"fmt"
     7  	"io/ioutil"
     8  
     9  	"github.com/tendermint/tendermint/crypto"
    10  	"github.com/tendermint/tendermint/crypto/ed25519"
    11  	tmos "github.com/tendermint/tendermint/libs/os"
    12  )
    13  
    14  // ID is a hex-encoded crypto.Address
    15  type ID string
    16  
    17  // IDByteLength is the length of a crypto.Address. Currently only 20.
    18  // TODO: support other length addresses ?
    19  const IDByteLength = crypto.AddressSize
    20  
    21  //------------------------------------------------------------------------------
    22  // Persistent peer ID
    23  // TODO: encrypt on disk
    24  
    25  // NodeKey is the persistent peer key.
    26  // It contains the nodes private key for authentication.
    27  type NodeKey struct {
    28  	PrivKey crypto.PrivKey `json:"priv_key"` // our priv key
    29  }
    30  
    31  // ID returns the peer's canonical ID - the hash of its public key.
    32  func (nodeKey *NodeKey) ID() ID {
    33  	return PubKeyToID(nodeKey.PubKey())
    34  }
    35  
    36  // PubKey returns the peer's PubKey
    37  func (nodeKey *NodeKey) PubKey() crypto.PubKey {
    38  	return nodeKey.PrivKey.PubKey()
    39  }
    40  
    41  // PubKeyToID returns the ID corresponding to the given PubKey.
    42  // It's the hex-encoding of the pubKey.Address().
    43  func PubKeyToID(pubKey crypto.PubKey) ID {
    44  	return ID(hex.EncodeToString(pubKey.Address()))
    45  }
    46  
    47  // LoadOrGenNodeKey attempts to load the NodeKey from the given filePath.
    48  // If the file does not exist, it generates and saves a new NodeKey.
    49  func LoadOrGenNodeKey(filePath string) (*NodeKey, error) {
    50  	if tmos.FileExists(filePath) {
    51  		nodeKey, err := LoadNodeKey(filePath)
    52  		if err != nil {
    53  			return nil, err
    54  		}
    55  		return nodeKey, nil
    56  	}
    57  	return genNodeKey(filePath)
    58  }
    59  
    60  func LoadNodeKey(filePath string) (*NodeKey, error) {
    61  	jsonBytes, err := ioutil.ReadFile(filePath)
    62  	if err != nil {
    63  		return nil, err
    64  	}
    65  	nodeKey := new(NodeKey)
    66  	err = cdc.UnmarshalJSON(jsonBytes, nodeKey)
    67  	if err != nil {
    68  		return nil, fmt.Errorf("error reading NodeKey from %v: %v", filePath, err)
    69  	}
    70  	return nodeKey, nil
    71  }
    72  
    73  func genNodeKey(filePath string) (*NodeKey, error) {
    74  	privKey := ed25519.GenPrivKey()
    75  	nodeKey := &NodeKey{
    76  		PrivKey: privKey,
    77  	}
    78  
    79  	jsonBytes, err := cdc.MarshalJSON(nodeKey)
    80  	if err != nil {
    81  		return nil, err
    82  	}
    83  	err = ioutil.WriteFile(filePath, jsonBytes, 0600)
    84  	if err != nil {
    85  		return nil, err
    86  	}
    87  	return nodeKey, nil
    88  }
    89  
    90  //------------------------------------------------------------------------------
    91  
    92  // MakePoWTarget returns the big-endian encoding of 2^(targetBits - difficulty) - 1.
    93  // It can be used as a Proof of Work target.
    94  // NOTE: targetBits must be a multiple of 8 and difficulty must be less than targetBits.
    95  func MakePoWTarget(difficulty, targetBits uint) []byte {
    96  	if targetBits%8 != 0 {
    97  		panic(fmt.Sprintf("targetBits (%d) not a multiple of 8", targetBits))
    98  	}
    99  	if difficulty >= targetBits {
   100  		panic(fmt.Sprintf("difficulty (%d) >= targetBits (%d)", difficulty, targetBits))
   101  	}
   102  	targetBytes := targetBits / 8
   103  	zeroPrefixLen := (int(difficulty) / 8)
   104  	prefix := bytes.Repeat([]byte{0}, zeroPrefixLen)
   105  	mod := (difficulty % 8)
   106  	if mod > 0 {
   107  		nonZeroPrefix := byte(1<<(8-mod) - 1)
   108  		prefix = append(prefix, nonZeroPrefix)
   109  	}
   110  	tailLen := int(targetBytes) - len(prefix)
   111  	return append(prefix, bytes.Repeat([]byte{0xFF}, tailLen)...)
   112  }