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

     1  // (c) 2019 Dapper Labs - ALL RIGHTS RESERVED
     2  
     3  package flow
     4  
     5  import (
     6  	"encoding/json"
     7  	"fmt"
     8  
     9  	"github.com/onflow/flow-go/crypto"
    10  	"github.com/onflow/flow-go/crypto/hash"
    11  )
    12  
    13  // Account represents an account on the Flow network.
    14  //
    15  // An account can be an externally owned account or a contract account with code.
    16  type Account struct {
    17  	Address   Address
    18  	Balance   uint64
    19  	Keys      []AccountPublicKey
    20  	Contracts map[string][]byte
    21  }
    22  
    23  // AccountPublicKey is a public key associated with an account.
    24  //
    25  // An account public key contains the public key, signing and hashing algorithms, and a key weight.
    26  type AccountPublicKey struct {
    27  	Index     int
    28  	PublicKey crypto.PublicKey
    29  	SignAlgo  crypto.SigningAlgorithm
    30  	HashAlgo  hash.HashingAlgorithm
    31  	SeqNumber uint64
    32  	Weight    int
    33  	Revoked   bool
    34  }
    35  
    36  func (a AccountPublicKey) MarshalJSON() ([]byte, error) {
    37  	return json.Marshal(struct {
    38  		PublicKey []byte
    39  		SignAlgo  crypto.SigningAlgorithm
    40  		HashAlgo  hash.HashingAlgorithm
    41  		SeqNumber uint64
    42  		Weight    int
    43  	}{
    44  		a.PublicKey.Encode(),
    45  		a.SignAlgo,
    46  		a.HashAlgo,
    47  		a.SeqNumber,
    48  		a.Weight,
    49  	})
    50  }
    51  
    52  func (a *AccountPublicKey) UnmarshalJSON(data []byte) error {
    53  	temp := struct {
    54  		PublicKey []byte
    55  		SignAlgo  crypto.SigningAlgorithm
    56  		HashAlgo  hash.HashingAlgorithm
    57  		SeqNumber uint64
    58  		Weight    int
    59  	}{}
    60  	err := json.Unmarshal(data, &temp)
    61  	if err != nil {
    62  		return err
    63  	}
    64  	if a == nil {
    65  		a = new(AccountPublicKey)
    66  	}
    67  	a.PublicKey, err = crypto.DecodePublicKey(temp.SignAlgo, temp.PublicKey)
    68  	if err != nil {
    69  		return err
    70  	}
    71  	a.SignAlgo = temp.SignAlgo
    72  	a.HashAlgo = temp.HashAlgo
    73  	a.SeqNumber = temp.SeqNumber
    74  	a.Weight = temp.Weight
    75  	return nil
    76  }
    77  
    78  // Validate returns an error if this account key is invalid.
    79  //
    80  // An account key can be invalid for the following reasons:
    81  // - It specifies an incompatible signature/hash algorithm pairing
    82  // - (TODO) It specifies a negative key weight
    83  func (a AccountPublicKey) Validate() error {
    84  	if !CompatibleAlgorithms(a.SignAlgo, a.HashAlgo) {
    85  		return fmt.Errorf(
    86  			"signing algorithm (%s) is incompatible with hashing algorithm (%s)",
    87  			a.SignAlgo,
    88  			a.HashAlgo,
    89  		)
    90  	}
    91  	return nil
    92  }
    93  
    94  // AccountPrivateKey is a private key associated with an account.
    95  type AccountPrivateKey struct {
    96  	PrivateKey crypto.PrivateKey
    97  	SignAlgo   crypto.SigningAlgorithm
    98  	HashAlgo   hash.HashingAlgorithm
    99  }
   100  
   101  // PublicKey returns a weighted public key.
   102  func (a AccountPrivateKey) PublicKey(weight int) AccountPublicKey {
   103  	return AccountPublicKey{
   104  		PublicKey: a.PrivateKey.PublicKey(),
   105  		SignAlgo:  a.SignAlgo,
   106  		HashAlgo:  a.HashAlgo,
   107  		Weight:    weight,
   108  	}
   109  }
   110  
   111  func (a AccountPrivateKey) MarshalJSON() ([]byte, error) {
   112  	return json.Marshal(struct {
   113  		PrivateKey []byte
   114  		SignAlgo   crypto.SigningAlgorithm
   115  		HashAlgo   hash.HashingAlgorithm
   116  	}{
   117  		a.PrivateKey.Encode(),
   118  		a.SignAlgo,
   119  		a.HashAlgo,
   120  	})
   121  }
   122  
   123  // CompatibleAlgorithms returns true if the signature and hash algorithms are compatible.
   124  func CompatibleAlgorithms(sigAlgo crypto.SigningAlgorithm, hashAlgo hash.HashingAlgorithm) bool {
   125  	switch sigAlgo {
   126  	case crypto.ECDSAP256, crypto.ECDSASecp256k1:
   127  		switch hashAlgo {
   128  		case hash.SHA2_256, hash.SHA3_256:
   129  			return true
   130  		}
   131  	}
   132  	return false
   133  }