code.vegaprotocol.io/vega@v0.79.0/core/validators/announce_node.go (about)

     1  // Copyright (C) 2023 Gobalsky Labs Limited
     2  //
     3  // This program is free software: you can redistribute it and/or modify
     4  // it under the terms of the GNU Affero General Public License as
     5  // published by the Free Software Foundation, either version 3 of the
     6  // License, or (at your option) any later version.
     7  //
     8  // This program is distributed in the hope that it will be useful,
     9  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    10  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    11  // GNU Affero General Public License for more details.
    12  //
    13  // You should have received a copy of the GNU Affero General Public License
    14  // along with this program.  If not, see <http://www.gnu.org/licenses/>.
    15  
    16  package validators
    17  
    18  import (
    19  	"context"
    20  	"encoding/base64"
    21  	"encoding/hex"
    22  	"errors"
    23  	"fmt"
    24  
    25  	"code.vegaprotocol.io/vega/core/nodewallets/eth/clef"
    26  	vgcrypto "code.vegaprotocol.io/vega/libs/crypto"
    27  	signatures "code.vegaprotocol.io/vega/libs/crypto/signature"
    28  	commandspb "code.vegaprotocol.io/vega/protos/vega/commands/v1"
    29  
    30  	"github.com/ethereum/go-ethereum/crypto"
    31  )
    32  
    33  var ErrMissingRequiredAnnounceNodeFields = errors.New("missing required announce node fields")
    34  
    35  func (t *Topology) ProcessAnnounceNode(
    36  	ctx context.Context, an *commandspb.AnnounceNode,
    37  ) error {
    38  	if err := VerifyAnnounceNode(an); err != nil {
    39  		return err
    40  	}
    41  
    42  	if err := t.AddNewNode(ctx, an, ValidatorStatusPending); err != nil {
    43  		return err
    44  	}
    45  
    46  	// if it is use that has annouce, we can now set our flag to be a validator. How exciting.
    47  	if an.Id == t.SelfNodeID() {
    48  		t.SetIsValidator()
    49  	}
    50  	return nil
    51  }
    52  
    53  type Signer interface {
    54  	Sign([]byte) ([]byte, error)
    55  	Algo() string
    56  }
    57  
    58  type Verifier interface {
    59  	Verify([]byte, []byte) error
    60  }
    61  
    62  // SignAnnounceNode adds the signature for the ethereum and
    63  // Vega address / pubkeys.
    64  func VerifyAnnounceNode(an *commandspb.AnnounceNode) error {
    65  	// just ensure the node address is checksumed
    66  	an.EthereumAddress = vgcrypto.EthereumChecksumAddress(an.EthereumAddress)
    67  
    68  	buf, err := makeAnnounceNodeSignableMessage(an)
    69  	if err != nil {
    70  		return err
    71  	}
    72  
    73  	vegas, err := hex.DecodeString(an.GetVegaSignature().Value)
    74  	if err != nil {
    75  		return err
    76  	}
    77  	vegaPubKey, err := hex.DecodeString(an.GetVegaPubKey())
    78  	if err != nil {
    79  		return err
    80  	}
    81  	if err := signatures.VerifyVegaSignature(buf, vegas, vegaPubKey); err != nil {
    82  		return err
    83  	}
    84  
    85  	eths, err := hex.DecodeString(an.GetEthereumSignature().Value)
    86  	if err != nil {
    87  		return err
    88  	}
    89  
    90  	if err := signatures.VerifyEthereumSignature(buf, eths, an.EthereumAddress); err != nil {
    91  		return err
    92  	}
    93  
    94  	if err := VerifyTendermintKey(an.ChainPubKey); err != nil {
    95  		return err
    96  	}
    97  
    98  	return nil
    99  }
   100  
   101  func VerifyTendermintKey(tmKey string) error {
   102  	_, err := base64.StdEncoding.DecodeString(tmKey)
   103  	return err
   104  }
   105  
   106  // SignAnnounceNode adds the signature for the ethereum and
   107  // Vega address / pubkeys.
   108  func SignAnnounceNode(
   109  	an *commandspb.AnnounceNode,
   110  	vegaSigner Signer,
   111  	ethSigner Signer,
   112  ) error {
   113  	buf, err := makeAnnounceNodeSignableMessage(an)
   114  	if err != nil {
   115  		return err
   116  	}
   117  
   118  	vegaSignature, err := vegaSigner.Sign(buf)
   119  	if err != nil {
   120  		return err
   121  	}
   122  
   123  	if ethSigner.Algo() != clef.ClefAlgoType {
   124  		buf = crypto.Keccak256(buf)
   125  	}
   126  	ethereumSignature, err := ethSigner.Sign(buf)
   127  	if err != nil {
   128  		return err
   129  	}
   130  
   131  	an.EthereumSignature = &commandspb.Signature{
   132  		Value: hex.EncodeToString(ethereumSignature),
   133  		Algo:  ethSigner.Algo(),
   134  	}
   135  
   136  	an.VegaSignature = &commandspb.Signature{
   137  		Value: hex.EncodeToString(vegaSignature),
   138  		Algo:  vegaSigner.Algo(),
   139  	}
   140  
   141  	return nil
   142  }
   143  
   144  func makeAnnounceNodeSignableMessage(an *commandspb.AnnounceNode) ([]byte, error) {
   145  	if len(an.Id) <= 0 || len(an.VegaPubKey) <= 0 || an.VegaPubKeyIndex == 0 || len(an.ChainPubKey) <= 0 || len(an.EthereumAddress) <= 0 || an.FromEpoch == 0 || len(an.InfoUrl) <= 0 || len(an.Name) <= 0 || len(an.AvatarUrl) <= 0 || len(an.Country) <= 0 {
   146  		return nil, ErrMissingRequiredAnnounceNodeFields
   147  	}
   148  
   149  	msg := an.Id + an.VegaPubKey + fmt.Sprintf("%d", an.VegaPubKeyIndex) + an.ChainPubKey + an.EthereumAddress + fmt.Sprintf("%d", an.FromEpoch) + an.InfoUrl + an.Name + an.AvatarUrl + an.Country
   150  
   151  	return []byte(msg), nil
   152  }