github.com/koko1123/flow-go-1@v0.29.6/model/bootstrap/node_info.go (about)

     1  // Package bootstrap defines canonical models and encoding for bootstrapping.
     2  package bootstrap
     3  
     4  import (
     5  	"encoding/json"
     6  	"fmt"
     7  	"sort"
     8  	"strings"
     9  
    10  	sdk "github.com/onflow/flow-go-sdk"
    11  	sdkcrypto "github.com/onflow/flow-go-sdk/crypto"
    12  
    13  	"github.com/onflow/flow-go/crypto"
    14  	"github.com/koko1123/flow-go-1/model/encodable"
    15  	"github.com/koko1123/flow-go-1/model/flow"
    16  )
    17  
    18  // NodeInfoType enumerates the two different options for
    19  type NodeInfoType int
    20  
    21  const (
    22  	NodeInfoTypeInvalid NodeInfoType = iota
    23  	NodeInfoTypePublic
    24  	NodeInfoTypePrivate
    25  )
    26  
    27  const (
    28  	DefaultMachineAccountSignAlgo      = sdkcrypto.ECDSA_P256
    29  	DefaultMachineAccountHashAlgo      = sdkcrypto.SHA3_256
    30  	DefaultMachineAccountKeyIndex uint = 0
    31  )
    32  
    33  // ErrMissingPrivateInfo is returned when a method is called on NodeInfo
    34  // that is only valid on instances containing private info.
    35  var ErrMissingPrivateInfo = fmt.Errorf("can not access private information for a public node type")
    36  
    37  // NodeMachineAccountKey contains the private configration need to construct a
    38  // NodeMachineAccountInfo object. This is used as an intemediary by the bootstrap scripts
    39  // for storing the private key before generating a NodeMachineAccountInfo.
    40  type NodeMachineAccountKey struct {
    41  	PrivateKey encodable.MachineAccountPrivKey
    42  }
    43  
    44  // NodeMachineAccountInfo defines the structure for a bootstrapping file containing
    45  // private information about the node's machine account. The machine account is used
    46  // by the protocol software to interact with Flow as a client autonomously as needed, in
    47  // particular to run the DKG and generate root cluster quorum certificates when preparing
    48  // for an epoch.
    49  type NodeMachineAccountInfo struct {
    50  	// Address is the flow address of the machine account, not to be confused
    51  	// with the network address of the node.
    52  	Address string
    53  
    54  	// EncodedPrivateKey is the private key of the machine account
    55  	EncodedPrivateKey []byte
    56  
    57  	// KeyIndex is the index of the key in the associated machine account
    58  	KeyIndex uint
    59  
    60  	// SigningAlgorithm is the algorithm used by the machine account along with
    61  	// the above private key to create cryptographic signatures
    62  	SigningAlgorithm sdkcrypto.SignatureAlgorithm
    63  
    64  	// HashAlgorithm is the algorithm used for hashing
    65  	HashAlgorithm sdkcrypto.HashAlgorithm
    66  }
    67  
    68  func (info NodeMachineAccountInfo) FlowAddress() flow.Address {
    69  	// trim 0x-prefix if present
    70  	addr := info.Address
    71  	if strings.ToLower(addr[:2]) == "0x" {
    72  		addr = addr[2:]
    73  	}
    74  	return flow.HexToAddress(addr)
    75  }
    76  
    77  func (info NodeMachineAccountInfo) SDKAddress() sdk.Address {
    78  	flowAddr := info.FlowAddress()
    79  	var sdkAddr sdk.Address
    80  	copy(sdkAddr[:], flowAddr[:])
    81  	return sdkAddr
    82  }
    83  
    84  func (info NodeMachineAccountInfo) PrivateKey() (crypto.PrivateKey, error) {
    85  	sk, err := crypto.DecodePrivateKey(info.SigningAlgorithm, info.EncodedPrivateKey)
    86  	if err != nil {
    87  		return nil, fmt.Errorf("could not decode machine account private key: %w", err)
    88  	}
    89  	return sk, nil
    90  }
    91  
    92  func (info NodeMachineAccountInfo) MustPrivateKey() crypto.PrivateKey {
    93  	sk, err := info.PrivateKey()
    94  	if err != nil {
    95  		panic(err)
    96  	}
    97  	return sk
    98  }
    99  
   100  // NodeConfig contains configuration information used as input to the
   101  // bootstrap process.
   102  type NodeConfig struct {
   103  	// Role is the flow role of the node (ex Collection, Consensus, ...)
   104  	Role flow.Role
   105  
   106  	// Address is the networking address of the node (IP:PORT), not to be
   107  	// confused with the address of the flow account associated with the node's
   108  	// machine account.
   109  	Address string
   110  
   111  	// Weight is the weight of the node
   112  	Weight uint64
   113  }
   114  
   115  // decodableNodeConfig provides backward-compatible decoding of old models
   116  // which use the Stake field in place of Weight.
   117  type decodableNodeConfig struct {
   118  	Role    flow.Role
   119  	Address string
   120  	Weight  uint64
   121  	// Stake previously was used in place of the Weight field.
   122  	Stake uint64
   123  }
   124  
   125  func (conf *NodeConfig) UnmarshalJSON(b []byte) error {
   126  	var decodable decodableNodeConfig
   127  	err := json.Unmarshal(b, &decodable)
   128  	if err != nil {
   129  		return fmt.Errorf("could not decode json: %w", err)
   130  	}
   131  	// compat: translate Stake fields to Weight
   132  	if decodable.Stake != 0 {
   133  		if decodable.Weight != 0 {
   134  			return fmt.Errorf("invalid NodeConfig with both Stake and Weight fields")
   135  		}
   136  		decodable.Weight = decodable.Stake
   137  	}
   138  	conf.Role = decodable.Role
   139  	conf.Address = decodable.Address
   140  	conf.Weight = decodable.Weight
   141  	return nil
   142  }
   143  
   144  // NodeInfoPriv defines the canonical structure for encoding private node info.
   145  type NodeInfoPriv struct {
   146  	Role           flow.Role
   147  	Address        string
   148  	NodeID         flow.Identifier
   149  	NetworkPrivKey encodable.NetworkPrivKey
   150  	StakingPrivKey encodable.StakingPrivKey
   151  }
   152  
   153  // NodeInfoPub defines the canonical structure for encoding public node info.
   154  type NodeInfoPub struct {
   155  	Role          flow.Role
   156  	Address       string
   157  	NodeID        flow.Identifier
   158  	Weight        uint64
   159  	NetworkPubKey encodable.NetworkPubKey
   160  	StakingPubKey encodable.StakingPubKey
   161  }
   162  
   163  // decodableNodeInfoPub provides backward-compatible decoding of old models
   164  // which use the Stake field in place of Weight.
   165  type decodableNodeInfoPub struct {
   166  	Role          flow.Role
   167  	Address       string
   168  	NodeID        flow.Identifier
   169  	Weight        uint64
   170  	NetworkPubKey encodable.NetworkPubKey
   171  	StakingPubKey encodable.StakingPubKey
   172  	// Stake previously was used in place of the Weight field.
   173  	// Deprecated: supported in decoding for backward-compatibility
   174  	Stake uint64
   175  }
   176  
   177  func (info *NodeInfoPub) UnmarshalJSON(b []byte) error {
   178  	var decodable decodableNodeInfoPub
   179  	err := json.Unmarshal(b, &decodable)
   180  	if err != nil {
   181  		return fmt.Errorf("could not decode json: %w", err)
   182  	}
   183  	// compat: translate Stake fields to Weight
   184  	if decodable.Stake != 0 {
   185  		if decodable.Weight != 0 {
   186  			return fmt.Errorf("invalid NodeInfoPub with both Stake and Weight fields")
   187  		}
   188  		decodable.Weight = decodable.Stake
   189  	}
   190  	info.Role = decodable.Role
   191  	info.Address = decodable.Address
   192  	info.NodeID = decodable.NodeID
   193  	info.Weight = decodable.Weight
   194  	info.NetworkPubKey = decodable.NetworkPubKey
   195  	info.StakingPubKey = decodable.StakingPubKey
   196  	return nil
   197  }
   198  
   199  // NodePrivateKeys is a wrapper for the private keys for a node, comprising all
   200  // sensitive information for a node.
   201  type NodePrivateKeys struct {
   202  	StakingKey crypto.PrivateKey
   203  	NetworkKey crypto.PrivateKey
   204  }
   205  
   206  // NodeInfo contains information for a node. This is used during the bootstrapping
   207  // process to represent each node. When writing node information to disk, use
   208  // `Public` or `Private` to obtain the appropriate canonical structure.
   209  //
   210  // A NodeInfo instance can contain EITHER public keys OR private keys, not both.
   211  // This can be ensured by using only using the provided constructors and NOT
   212  // manually constructing an instance.
   213  type NodeInfo struct {
   214  
   215  	// NodeID is the unique identifier of the node in the network
   216  	NodeID flow.Identifier
   217  
   218  	// Role is the flow role of the node (collection, consensus, etc...)
   219  	Role flow.Role
   220  
   221  	// Address is the networking address of the node (IP:PORT), not to be
   222  	// confused with the address of the flow account associated with the node's
   223  	// machine account.
   224  	Address string
   225  
   226  	// Weight is the weight of the node
   227  	Weight uint64
   228  
   229  	// key information is private
   230  	networkPubKey  crypto.PublicKey
   231  	networkPrivKey crypto.PrivateKey
   232  	stakingPubKey  crypto.PublicKey
   233  	stakingPrivKey crypto.PrivateKey
   234  }
   235  
   236  func NewPublicNodeInfo(
   237  	nodeID flow.Identifier,
   238  	role flow.Role,
   239  	addr string,
   240  	weight uint64,
   241  	networkKey crypto.PublicKey,
   242  	stakingKey crypto.PublicKey,
   243  ) NodeInfo {
   244  	return NodeInfo{
   245  		NodeID:        nodeID,
   246  		Role:          role,
   247  		Address:       addr,
   248  		Weight:        weight,
   249  		networkPubKey: networkKey,
   250  		stakingPubKey: stakingKey,
   251  	}
   252  }
   253  
   254  func NewPrivateNodeInfo(
   255  	nodeID flow.Identifier,
   256  	role flow.Role,
   257  	addr string,
   258  	weight uint64,
   259  	networkKey crypto.PrivateKey,
   260  	stakingKey crypto.PrivateKey,
   261  ) NodeInfo {
   262  	return NodeInfo{
   263  		NodeID:         nodeID,
   264  		Role:           role,
   265  		Address:        addr,
   266  		Weight:         weight,
   267  		networkPrivKey: networkKey,
   268  		stakingPrivKey: stakingKey,
   269  		networkPubKey:  networkKey.PublicKey(),
   270  		stakingPubKey:  stakingKey.PublicKey(),
   271  	}
   272  }
   273  
   274  // Type returns the type of the node info instance.
   275  func (node NodeInfo) Type() NodeInfoType {
   276  	if node.networkPrivKey != nil && node.stakingPrivKey != nil {
   277  		return NodeInfoTypePrivate
   278  	}
   279  	if node.networkPubKey != nil && node.stakingPubKey != nil {
   280  		return NodeInfoTypePublic
   281  	}
   282  	return NodeInfoTypeInvalid
   283  }
   284  
   285  func (node NodeInfo) NetworkPubKey() crypto.PublicKey {
   286  	if node.networkPubKey != nil {
   287  		return node.networkPubKey
   288  	}
   289  	return node.networkPrivKey.PublicKey()
   290  }
   291  
   292  func (node NodeInfo) StakingPubKey() crypto.PublicKey {
   293  	if node.stakingPubKey != nil {
   294  		return node.stakingPubKey
   295  	}
   296  	return node.stakingPrivKey.PublicKey()
   297  }
   298  
   299  func (node NodeInfo) PrivateKeys() (*NodePrivateKeys, error) {
   300  	if node.Type() != NodeInfoTypePrivate {
   301  		return nil, ErrMissingPrivateInfo
   302  	}
   303  	return &NodePrivateKeys{
   304  		StakingKey: node.stakingPrivKey,
   305  		NetworkKey: node.networkPrivKey,
   306  	}, nil
   307  }
   308  
   309  // Private returns the canonical private encodable structure.
   310  func (node NodeInfo) Private() (NodeInfoPriv, error) {
   311  	if node.Type() != NodeInfoTypePrivate {
   312  		return NodeInfoPriv{}, ErrMissingPrivateInfo
   313  	}
   314  
   315  	return NodeInfoPriv{
   316  		Role:           node.Role,
   317  		Address:        node.Address,
   318  		NodeID:         node.NodeID,
   319  		NetworkPrivKey: encodable.NetworkPrivKey{PrivateKey: node.networkPrivKey},
   320  		StakingPrivKey: encodable.StakingPrivKey{PrivateKey: node.stakingPrivKey},
   321  	}, nil
   322  }
   323  
   324  // Public returns the canonical public encodable structure
   325  func (node NodeInfo) Public() NodeInfoPub {
   326  	return NodeInfoPub{
   327  		Role:          node.Role,
   328  		Address:       node.Address,
   329  		NodeID:        node.NodeID,
   330  		Weight:        node.Weight,
   331  		NetworkPubKey: encodable.NetworkPubKey{PublicKey: node.NetworkPubKey()},
   332  		StakingPubKey: encodable.StakingPubKey{PublicKey: node.StakingPubKey()},
   333  	}
   334  }
   335  
   336  // PartnerPublic returns the public data for a partner node.
   337  func (node NodeInfo) PartnerPublic() PartnerNodeInfoPub {
   338  	return PartnerNodeInfoPub{
   339  		Role:          node.Role,
   340  		Address:       node.Address,
   341  		NodeID:        node.NodeID,
   342  		NetworkPubKey: encodable.NetworkPubKey{PublicKey: node.NetworkPubKey()},
   343  		StakingPubKey: encodable.StakingPubKey{PublicKey: node.StakingPubKey()},
   344  	}
   345  }
   346  
   347  // Identity returns the node info as a public Flow identity.
   348  func (node NodeInfo) Identity() *flow.Identity {
   349  	identity := &flow.Identity{
   350  		NodeID:        node.NodeID,
   351  		Address:       node.Address,
   352  		Role:          node.Role,
   353  		Weight:        node.Weight,
   354  		StakingPubKey: node.StakingPubKey(),
   355  		NetworkPubKey: node.NetworkPubKey(),
   356  	}
   357  	return identity
   358  }
   359  
   360  // NodeInfoFromIdentity converts an identity to a public NodeInfo
   361  func NodeInfoFromIdentity(identity *flow.Identity) NodeInfo {
   362  	return NewPublicNodeInfo(
   363  		identity.NodeID,
   364  		identity.Role,
   365  		identity.Address,
   366  		identity.Weight,
   367  		identity.NetworkPubKey,
   368  		identity.StakingPubKey)
   369  }
   370  
   371  func PrivateNodeInfoFromIdentity(identity *flow.Identity, networkKey, stakingKey crypto.PrivateKey) NodeInfo {
   372  	return NewPrivateNodeInfo(
   373  		identity.NodeID,
   374  		identity.Role,
   375  		identity.Address,
   376  		identity.Weight,
   377  		networkKey,
   378  		stakingKey,
   379  	)
   380  }
   381  
   382  func FilterByRole(nodes []NodeInfo, role flow.Role) []NodeInfo {
   383  	var filtered []NodeInfo
   384  	for _, node := range nodes {
   385  		if node.Role != role {
   386  			continue
   387  		}
   388  		filtered = append(filtered, node)
   389  	}
   390  	return filtered
   391  }
   392  
   393  // Sort sorts the NodeInfo list using the given ordering.
   394  func Sort(nodes []NodeInfo, order flow.IdentityOrder) []NodeInfo {
   395  	dup := make([]NodeInfo, len(nodes))
   396  	copy(dup, nodes)
   397  	sort.Slice(dup, func(i, j int) bool {
   398  		return order(dup[i].Identity(), dup[j].Identity())
   399  	})
   400  	return dup
   401  }
   402  
   403  func ToIdentityList(nodes []NodeInfo) flow.IdentityList {
   404  	il := make(flow.IdentityList, 0, len(nodes))
   405  	for _, node := range nodes {
   406  		il = append(il, node.Identity())
   407  	}
   408  	return il
   409  }
   410  
   411  func ToPublicNodeInfoList(nodes []NodeInfo) []NodeInfoPub {
   412  	pub := make([]NodeInfoPub, 0, len(nodes))
   413  	for _, node := range nodes {
   414  		pub = append(pub, node.Public())
   415  	}
   416  	return pub
   417  }