github.com/amazechain/amc@v0.1.3/common/crypto/bls/blst/public_key.go (about)

     1  //go:build (android || (linux && amd64) || (linux && arm64) || (darwin && amd64) || (darwin && arm64) || (windows && amd64)) && !blst_disabled
     2  
     3  package blst
     4  
     5  import (
     6  	"fmt"
     7  
     8  	"github.com/amazechain/amc/common/crypto/bls/common"
     9  	"github.com/amazechain/amc/common/hexutil"
    10  	"github.com/amazechain/amc/log"
    11  	lru "github.com/hashicorp/golang-lru"
    12  	"github.com/pkg/errors"
    13  )
    14  
    15  var maxKeys = 1000000
    16  var pubkeyCache, _ = lru.New(maxKeys)
    17  
    18  const (
    19  	BLSPubkeyLength = 48
    20  )
    21  
    22  // PublicKey used in the BLS signature scheme.
    23  type PublicKey struct {
    24  	p *blstPublicKey
    25  }
    26  
    27  // PublicKeyFromBytes creates a BLS public key from a  BigEndian byte slice.
    28  func PublicKeyFromBytes(pubKey []byte) (common.PublicKey, error) {
    29  	if len(pubKey) != BLSPubkeyLength {
    30  		return nil, fmt.Errorf("public key must be %d bytes", BLSPubkeyLength)
    31  	}
    32  	newKey := (*[BLSPubkeyLength]byte)(pubKey)
    33  	if cv, ok := pubkeyCache.Get(*newKey); ok {
    34  		return cv.(*PublicKey).Copy(), nil
    35  	}
    36  	// Subgroup check NOT done when decompressing pubkey.
    37  	p := new(blstPublicKey).Uncompress(pubKey)
    38  	if p == nil {
    39  		return nil, errors.New("could not unmarshal bytes into public key")
    40  	}
    41  	// Subgroup and infinity check
    42  	if !p.KeyValidate() {
    43  		// NOTE: the error is not quite accurate since it includes group check
    44  		return nil, common.ErrInfinitePubKey
    45  	}
    46  	pubKeyObj := &PublicKey{p: p}
    47  	copiedKey := pubKeyObj.Copy()
    48  	cacheKey := *newKey
    49  	pubkeyCache.Add(cacheKey, copiedKey)
    50  	return pubKeyObj, nil
    51  }
    52  
    53  // AggregatePublicKeys aggregates the provided raw public keys into a single key.
    54  func AggregatePublicKeys(pubs [][]byte) (common.PublicKey, error) {
    55  	if len(pubs) == 0 {
    56  		return nil, errors.New("nil or empty public keys")
    57  	}
    58  	agg := new(blstAggregatePublicKey)
    59  	mulP1 := make([]*blstPublicKey, 0, len(pubs))
    60  	for _, pubkey := range pubs {
    61  		pubKeyObj, err := PublicKeyFromBytes(pubkey)
    62  		if err != nil {
    63  			return nil, err
    64  		}
    65  		mulP1 = append(mulP1, pubKeyObj.(*PublicKey).p)
    66  	}
    67  	// No group check needed here since it is done in PublicKeyFromBytes
    68  	// Note the checks could be moved from PublicKeyFromBytes into Aggregate
    69  	// and take advantage of multi-threading.
    70  	agg.Aggregate(mulP1, false)
    71  	return &PublicKey{p: agg.ToAffine()}, nil
    72  }
    73  
    74  // Marshal a public key into a LittleEndian byte slice.
    75  func (p *PublicKey) Marshal() []byte {
    76  	return p.p.Compress()
    77  }
    78  
    79  // Copy the public key to a new pointer reference.
    80  func (p *PublicKey) Copy() common.PublicKey {
    81  	np := *p.p
    82  	return &PublicKey{p: &np}
    83  }
    84  
    85  // IsInfinite checks if the public key is infinite.
    86  func (p *PublicKey) IsInfinite() bool {
    87  	zeroKey := new(blstPublicKey)
    88  	return p.p.Equals(zeroKey)
    89  }
    90  
    91  // Equals checks if the provided public key is equal to
    92  // the current one.
    93  func (p *PublicKey) Equals(p2 common.PublicKey) bool {
    94  	return p.p.Equals(p2.(*PublicKey).p)
    95  }
    96  
    97  // Aggregate two public keys.
    98  func (p *PublicKey) Aggregate(p2 common.PublicKey) common.PublicKey {
    99  
   100  	agg := new(blstAggregatePublicKey)
   101  	// No group check here since it is checked at decompression time
   102  	agg.Add(p.p, false)
   103  	agg.Add(p2.(*PublicKey).p, false)
   104  	p.p = agg.ToAffine()
   105  
   106  	return p
   107  }
   108  
   109  func (p *PublicKey) UnmarshalJSON(input []byte) error {
   110  	log.Infof(string(input))
   111  	log.Info("1111")
   112  	b := make([]byte, 0)
   113  	err := hexutil.UnmarshalFixedText("PublicKey", input, b[:])
   114  	if err != nil {
   115  		return err
   116  	}
   117  	pubkey, err := PublicKeyFromBytes(b)
   118  	if err != nil {
   119  		p = pubkey.(*PublicKey)
   120  	}
   121  	return err
   122  }
   123  
   124  func (p *PublicKey) UnmarshalText(input []byte) error {
   125  	log.Infof(string(input))
   126  	log.Info("1111")
   127  	b := make([]byte, 0)
   128  	err := hexutil.UnmarshalFixedText("PublicKey", input, b[:])
   129  	if err != nil {
   130  		return err
   131  	}
   132  	pubkey, err := PublicKeyFromBytes(b)
   133  	if err != nil {
   134  		p = pubkey.(*PublicKey)
   135  	}
   136  	return err
   137  }
   138  
   139  func (p *PublicKey) MarshalText() ([]byte, error) {
   140  	return hexutil.Bytes(p.Marshal()).MarshalText()
   141  }
   142  
   143  // AggregateMultiplePubkeys aggregates the provided decompressed keys into a single key.
   144  func AggregateMultiplePubkeys(pubkeys []common.PublicKey) common.PublicKey {
   145  	mulP1 := make([]*blstPublicKey, 0, len(pubkeys))
   146  	for _, pubkey := range pubkeys {
   147  		mulP1 = append(mulP1, pubkey.(*PublicKey).p)
   148  	}
   149  	agg := new(blstAggregatePublicKey)
   150  	// No group check needed here since it is done in PublicKeyFromBytes
   151  	// Note the checks could be moved from PublicKeyFromBytes into Aggregate
   152  	// and take advantage of multi-threading.
   153  	agg.Aggregate(mulP1, false)
   154  	return &PublicKey{p: agg.ToAffine()}
   155  }