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 }