github.com/ari-anchor/sei-tendermint@v0.0.0-20230519144642-dc826b7b56bb/types/node_key.go (about)

     1  package types
     2  
     3  import (
     4  	"encoding/json"
     5  	"os"
     6  
     7  	"github.com/ari-anchor/sei-tendermint/crypto"
     8  	"github.com/ari-anchor/sei-tendermint/crypto/ed25519"
     9  	"github.com/ari-anchor/sei-tendermint/internal/jsontypes"
    10  	tmos "github.com/ari-anchor/sei-tendermint/libs/os"
    11  )
    12  
    13  //------------------------------------------------------------------------------
    14  // Persistent peer ID
    15  // TODO: encrypt on disk
    16  
    17  // NodeKey is the persistent peer key.
    18  // It contains the nodes private key for authentication.
    19  type NodeKey struct {
    20  	// Canonical ID - hex-encoded pubkey's address (IDByteLength bytes)
    21  	ID NodeID
    22  	// Private key
    23  	PrivKey crypto.PrivKey
    24  }
    25  
    26  type nodeKeyJSON struct {
    27  	ID      NodeID          `json:"id"`
    28  	PrivKey json.RawMessage `json:"priv_key"`
    29  }
    30  
    31  func (nk NodeKey) MarshalJSON() ([]byte, error) {
    32  	pk, err := jsontypes.Marshal(nk.PrivKey)
    33  	if err != nil {
    34  		return nil, err
    35  	}
    36  	return json.Marshal(nodeKeyJSON{
    37  		ID: nk.ID, PrivKey: pk,
    38  	})
    39  }
    40  
    41  func (nk *NodeKey) UnmarshalJSON(data []byte) error {
    42  	var nkjson nodeKeyJSON
    43  	if err := json.Unmarshal(data, &nkjson); err != nil {
    44  		return err
    45  	}
    46  	var pk crypto.PrivKey
    47  	if err := jsontypes.Unmarshal(nkjson.PrivKey, &pk); err != nil {
    48  		return err
    49  	}
    50  	*nk = NodeKey{ID: nkjson.ID, PrivKey: pk}
    51  	return nil
    52  }
    53  
    54  // PubKey returns the peer's PubKey
    55  func (nk NodeKey) PubKey() crypto.PubKey {
    56  	return nk.PrivKey.PubKey()
    57  }
    58  
    59  // SaveAs persists the NodeKey to filePath.
    60  func (nk NodeKey) SaveAs(filePath string) error {
    61  	jsonBytes, err := json.Marshal(nk)
    62  	if err != nil {
    63  		return err
    64  	}
    65  	return os.WriteFile(filePath, jsonBytes, 0600)
    66  }
    67  
    68  // LoadOrGenNodeKey attempts to load the NodeKey from the given filePath. If
    69  // the file does not exist, it generates and saves a new NodeKey.
    70  func LoadOrGenNodeKey(filePath string) (NodeKey, error) {
    71  	if tmos.FileExists(filePath) {
    72  		nodeKey, err := LoadNodeKey(filePath)
    73  		if err != nil {
    74  			return NodeKey{}, err
    75  		}
    76  		return nodeKey, nil
    77  	}
    78  
    79  	nodeKey := GenNodeKey()
    80  
    81  	if err := nodeKey.SaveAs(filePath); err != nil {
    82  		return NodeKey{}, err
    83  	}
    84  
    85  	return nodeKey, nil
    86  }
    87  
    88  // GenNodeKey generates a new node key.
    89  func GenNodeKey() NodeKey {
    90  	privKey := ed25519.GenPrivKey()
    91  	return NodeKey{
    92  		ID:      NodeIDFromPubKey(privKey.PubKey()),
    93  		PrivKey: privKey,
    94  	}
    95  }
    96  
    97  // LoadNodeKey loads NodeKey located in filePath.
    98  func LoadNodeKey(filePath string) (NodeKey, error) {
    99  	jsonBytes, err := os.ReadFile(filePath)
   100  	if err != nil {
   101  		return NodeKey{}, err
   102  	}
   103  	nodeKey := NodeKey{}
   104  	err = json.Unmarshal(jsonBytes, &nodeKey)
   105  	if err != nil {
   106  		return NodeKey{}, err
   107  	}
   108  	nodeKey.ID = NodeIDFromPubKey(nodeKey.PubKey())
   109  	return nodeKey, nil
   110  }