github.com/okex/exchain@v1.8.0/libs/tendermint/p2p/key.go (about)

     1  package p2p
     2  
     3  import (
     4  	"bytes"
     5  	"encoding/hex"
     6  	"fmt"
     7  	"io/ioutil"
     8  
     9  	"github.com/okex/exchain/libs/tendermint/crypto"
    10  	"github.com/okex/exchain/libs/tendermint/crypto/ed25519"
    11  	tmos "github.com/okex/exchain/libs/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  // BytesToPubKey returns the PubKey corresponding to the given ID.
    48  func BytesToPubKey(b []byte) crypto.PubKey {
    49  	var pub crypto.PubKey
    50  	if err := cdc.UnmarshalBinaryBare(b, &pub); err != nil {
    51  		return nil
    52  	}
    53  	return pub
    54  }
    55  
    56  // LoadOrGenNodeKey attempts to load the NodeKey from the given filePath.
    57  // If the file does not exist, it generates and saves a new NodeKey.
    58  func LoadOrGenNodeKey(filePath string) (*NodeKey, error) {
    59  	if tmos.FileExists(filePath) {
    60  		nodeKey, err := LoadNodeKey(filePath)
    61  		if err != nil {
    62  			return nil, err
    63  		}
    64  		return nodeKey, nil
    65  	}
    66  	return genNodeKey(filePath)
    67  }
    68  
    69  func LoadOrGenNodeKeyByIndex(filePath string, index int) (*NodeKey, error) {
    70  	if tmos.FileExists(filePath) {
    71  		nodeKey, err := LoadNodeKey(filePath)
    72  		if err != nil {
    73  			return nil, err
    74  		}
    75  		return nodeKey, nil
    76  	}
    77  	return genNodeKeyByIndex(filePath, index)
    78  }
    79  
    80  func LoadNodeKey(filePath string) (*NodeKey, error) {
    81  	jsonBytes, err := ioutil.ReadFile(filePath)
    82  	if err != nil {
    83  		return nil, err
    84  	}
    85  	nodeKey := new(NodeKey)
    86  	err = cdc.UnmarshalJSON(jsonBytes, nodeKey)
    87  	if err != nil {
    88  		return nil, fmt.Errorf("error reading NodeKey from %v: %v", filePath, err)
    89  	}
    90  	return nodeKey, nil
    91  }
    92  
    93  func genNodeKey(filePath string) (*NodeKey, error) {
    94  	privKey := ed25519.GenPrivKey()
    95  	nodeKey := &NodeKey{
    96  		PrivKey: privKey,
    97  	}
    98  
    99  	jsonBytes, err := cdc.MarshalJSON(nodeKey)
   100  	if err != nil {
   101  		return nil, err
   102  	}
   103  	err = ioutil.WriteFile(filePath, jsonBytes, 0600)
   104  	if err != nil {
   105  		return nil, err
   106  	}
   107  	return nodeKey, nil
   108  }
   109  
   110  func genNodeKeyByIndex(filePath string, index int) (*NodeKey, error) {
   111  	if index < 0 {
   112  		return genNodeKey(filePath)
   113  	}
   114  
   115  	privKey := ed25519.GenPrivKeyFromSecret([]byte(fmt.Sprintf("secret%d", index)))
   116  	nodeKey := &NodeKey{
   117  		PrivKey: privKey,
   118  	}
   119  
   120  	jsonBytes, err := cdc.MarshalJSON(nodeKey)
   121  	if err != nil {
   122  		return nil, err
   123  	}
   124  	err = ioutil.WriteFile(filePath, jsonBytes, 0600)
   125  	if err != nil {
   126  		return nil, err
   127  	}
   128  	return nodeKey, nil
   129  }
   130  
   131  //------------------------------------------------------------------------------
   132  
   133  // MakePoWTarget returns the big-endian encoding of 2^(targetBits - difficulty) - 1.
   134  // It can be used as a Proof of Work target.
   135  // NOTE: targetBits must be a multiple of 8 and difficulty must be less than targetBits.
   136  func MakePoWTarget(difficulty, targetBits uint) []byte {
   137  	if targetBits%8 != 0 {
   138  		panic(fmt.Sprintf("targetBits (%d) not a multiple of 8", targetBits))
   139  	}
   140  	if difficulty >= targetBits {
   141  		panic(fmt.Sprintf("difficulty (%d) >= targetBits (%d)", difficulty, targetBits))
   142  	}
   143  	targetBytes := targetBits / 8
   144  	zeroPrefixLen := (int(difficulty) / 8)
   145  	prefix := bytes.Repeat([]byte{0}, zeroPrefixLen)
   146  	mod := (difficulty % 8)
   147  	if mod > 0 {
   148  		nonZeroPrefix := byte(1<<(8-mod) - 1)
   149  		prefix = append(prefix, nonZeroPrefix)
   150  	}
   151  	tailLen := int(targetBytes) - len(prefix)
   152  	return append(prefix, bytes.Repeat([]byte{0xFF}, tailLen)...)
   153  }