Skip to content

Commit

Permalink
use relayer account array in E2E config; a few renaming; add private …
Browse files Browse the repository at this point in the history
…key validation when importing
  • Loading branch information
ws4charlie committed Aug 13, 2024
1 parent e8736a0 commit 98f041a
Show file tree
Hide file tree
Showing 13 changed files with 168 additions and 91 deletions.
4 changes: 2 additions & 2 deletions cmd/zetaclientd/encrypt_tss.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ func init() {
// EncryptTSSFile encrypts the given file with the given secret key
func EncryptTSSFile(_ *cobra.Command, args []string) error {
filePath := args[0]
secretKey := args[1]
password := args[1]

filePath = filepath.Clean(filePath)
data, err := os.ReadFile(filePath)
Expand All @@ -38,7 +38,7 @@ func EncryptTSSFile(_ *cobra.Command, args []string) error {
}

// encrypt the data
cipherText, err := crypto.EncryptAES256GCM(data, secretKey)
cipherText, err := crypto.EncryptAES256GCM(data, password)
if err != nil {
return errors.Wrap(err, "failed to encrypt data")
}
Expand Down
9 changes: 6 additions & 3 deletions cmd/zetaclientd/import_relayer_keys.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,14 @@ import (
)

var CmdImportRelayerKey = &cobra.Command{
Use: "import-relayer-key [network] [private-key] [password] [relayer-key-path]",
Use: "import-relayer-key --network=<network> --private-key=<private-key> --password=<password> --relayer-key-path=<relayer-key-path>",
Short: "Import a relayer private key",
Example: `zetaclientd import-relayer-key --network=7 --private-key=3EMjCcCJg53fMEGVj13UPQpo6py9AKKyLE2qroR4yL1SvAN2tUznBvDKRYjntw7m6Jof1R2CSqjTddL27rEb6sFQ --password=my_password`,
Example: `zetaclientd import-relayer-key --network=7 --private-key=<your_private_key> --password=<your_password>`,
RunE: ImportRelayerKey,
}

var CmdRelayerAddress = &cobra.Command{
Use: "relayer-address [network] [password] [relayer-key-path]",
Use: "relayer-address --network=<network> --password=<password> --relayer-key-path=<relayer-key-path>",
Short: "Show the relayer address",
Example: `zetaclientd relayer-address --network=7 --password=my_password`,
RunE: ShowRelayerAddress,
Expand Down Expand Up @@ -82,6 +82,9 @@ func ImportRelayerKey(_ *cobra.Command, _ []string) error {
if importArgs.password == "" {
return errors.New("must provide a password")
}
if !keys.IsRelayerPrivateKeyValid(importArgs.privateKey, chains.Network(importArgs.network)) {
return errors.New("invalid private key")
}

// resolve the relayer key file path
fileName, err := keys.ResolveRelayerKeyFile(importArgs.relayerKeyPath, chains.Network(importArgs.network))
Expand Down
11 changes: 5 additions & 6 deletions cmd/zetae2e/config/localnet.yml
Original file line number Diff line number Diff line change
Expand Up @@ -55,12 +55,11 @@ policy_accounts:
evm_address: "0xAa9b029BC3EFe4c50045Cf0902c73aAa25b43533"
private_key: "0595CB0CD9BF5264A85A603EC8E43C30ADBB5FD2D9E2EF84C374EA4A65BB616C"
observer_relayer_accounts:
relayer_account_0:
solana_address: "2qBVcNBZCubcnSR3NyCnFjCfkCVUB3G7ECPoaW5rxVjx"
solana_private_key: "3EMjCcCJg53fMEGVj13UPQpo6py9AKKyLE2qroR4yL1SvAN2tUznBvDKRYjntw7m6Jof1R2CSqjTddL27rEb6sFQ"
relayer_account_1:
solana_address: "4kkCV8H38xirwQTkE5kL6FHNtYGHnMQQ7SkCjAxibHFK"
solana_private_key: "5SSv7jWzamtjWNKGiKf3gvCPHcq9mE5x6LhYgzJCKNSxoQ83gFpmMgmg2JS2zdKcBEdwy7y9bvWgX4LBiUpvnrPf"
relayer_accounts:
- solana_address: "2qBVcNBZCubcnSR3NyCnFjCfkCVUB3G7ECPoaW5rxVjx"
solana_private_key: "3EMjCcCJg53fMEGVj13UPQpo6py9AKKyLE2qroR4yL1SvAN2tUznBvDKRYjntw7m6Jof1R2CSqjTddL27rEb6sFQ"
- solana_address: "4kkCV8H38xirwQTkE5kL6FHNtYGHnMQQ7SkCjAxibHFK"
solana_private_key: "5SSv7jWzamtjWNKGiKf3gvCPHcq9mE5x6LhYgzJCKNSxoQ83gFpmMgmg2JS2zdKcBEdwy7y9bvWgX4LBiUpvnrPf"
rpcs:
zevm: "http://zetacore0:8545"
evm: "http://eth:8545"
Expand Down
3 changes: 1 addition & 2 deletions cmd/zetae2e/local/local.go
Original file line number Diff line number Diff line change
Expand Up @@ -353,8 +353,7 @@ func localE2ETest(cmd *cobra.Command, _ []string) {
if testTSSMigration {
runTSSMigrationTest(deployerRunner, logger, verbose, conf)
}
// Verify that there are no trackers left over after tests complete
deployerRunner.EnsureNoTrackers()

// print and validate report
networkReport, err := deployerRunner.GenerateNetworkReport()
if err != nil {
Expand Down
4 changes: 2 additions & 2 deletions contrib/localnet/orchestrator/start-zetae2e.sh
Original file line number Diff line number Diff line change
Expand Up @@ -95,11 +95,11 @@ geth --exec "eth.sendTransaction({from: eth.coinbase, to: '${address}', value: w
solana_url=$(yq -r '.rpcs.solana' config.yml)
solana config set --url "$solana_url" > /dev/null

relayer=$(yq -r '.observer_relayer_accounts.relayer_account_0.solana_address' config.yml)
relayer=$(yq -r '.observer_relayer_accounts.relayer_accounts[0].solana_address' config.yml)
echo "funding solana relayer address ${relayer} with 100 SOL"
solana airdrop 100 "$relayer" > /dev/null

relayer=$(yq -r '.observer_relayer_accounts.relayer_account_1.solana_address' config.yml)
relayer=$(yq -r '.observer_relayer_accounts.relayer_accounts[1].solana_address' config.yml)
echo "funding solana relayer address ${relayer} with 100 SOL"
solana airdrop 100 "$relayer" > /dev/null

Expand Down
2 changes: 1 addition & 1 deletion contrib/localnet/scripts/start-zetaclientd.sh
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ import_relayer_key() {
local num="$1"

# import solana (network=7) relayer private key
privkey_solana=$(yq -r ".observer_relayer_accounts.relayer_account_${num}.solana_private_key" /root/config.yml)
privkey_solana=$(yq -r ".observer_relayer_accounts.relayer_accounts[${num}].solana_private_key" /root/config.yml)
zetaclientd import-relayer-key --network=7 --private-key="$privkey_solana" --password=pass_relayerkey
}

Expand Down
4 changes: 2 additions & 2 deletions e2e/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -80,8 +80,8 @@ type PolicyAccounts struct {

// ObserverRelayerAccounts are the accounts used by the observers to interact with gateway contracts in non-EVM chains (e.g. Solana)
type ObserverRelayerAccounts struct {
RelayerAccount0 Account `yaml:"relayer_account_0"`
RelayerAccount1 Account `yaml:"relayer_account_1"`
// RelayerAccounts contains two relayer accounts used by zetaclient0 and zetaclient1
RelayerAccounts [2]Account `yaml:"relayer_accounts"`
}

// RPCs contains the configuration for the RPC endpoints
Expand Down
38 changes: 20 additions & 18 deletions pkg/crypto/aes256_gcm.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,32 +11,32 @@ import (
"github.com/pkg/errors"
)

// EncryptAES256GCMBase64 encrypts the given string plaintext using AES-256-GCM with the given key and returns the base64-encoded ciphertext.
func EncryptAES256GCMBase64(plaintext string, encryptKey string) (string, error) {
// EncryptAES256GCMBase64 encrypts the given string plaintext using AES-256-GCM with the given password and returns the base64-encoded ciphertext.
func EncryptAES256GCMBase64(plaintext string, password string) (string, error) {
// validate the input
if plaintext == "" {
return "", errors.New("plaintext must not be empty")
}
if encryptKey == "" {
return "", errors.New("encrypt key must not be empty")
if password == "" {
return "", errors.New("password must not be empty")
}

// encrypt the plaintext
ciphertext, err := EncryptAES256GCM([]byte(plaintext), encryptKey)
ciphertext, err := EncryptAES256GCM([]byte(plaintext), password)
if err != nil {
return "", errors.Wrap(err, "failed to encrypt string plaintext")
}
return base64.StdEncoding.EncodeToString(ciphertext), nil
}

// DecryptAES256GCMBase64 decrypts the given base64-encoded ciphertext using AES-256-GCM with the given key.
func DecryptAES256GCMBase64(ciphertextBase64 string, decryptKey string) (string, error) {
// DecryptAES256GCMBase64 decrypts the given base64-encoded ciphertext using AES-256-GCM with the given password.
func DecryptAES256GCMBase64(ciphertextBase64 string, password string) (string, error) {
// validate the input
if ciphertextBase64 == "" {
return "", errors.New("ciphertext must not be empty")
}
if decryptKey == "" {
return "", errors.New("decrypt key must not be empty")
if password == "" {
return "", errors.New("password must not be empty")
}

// decode the base64-encoded ciphertext
Expand All @@ -46,16 +46,17 @@ func DecryptAES256GCMBase64(ciphertextBase64 string, decryptKey string) (string,
}

// decrypt the ciphertext
plaintext, err := DecryptAES256GCM(ciphertext, decryptKey)
plaintext, err := DecryptAES256GCM(ciphertext, password)
if err != nil {
return "", errors.Wrap(err, "failed to decrypt ciphertext")
}
return string(plaintext), nil
}

// EncryptAES256GCM encrypts the given plaintext using AES-256-GCM with the given key.
func EncryptAES256GCM(plaintext []byte, encryptKey string) ([]byte, error) {
block, err := aes.NewCipher(getAESKey(encryptKey))
// EncryptAES256GCM encrypts the given plaintext using AES-256-GCM with the given password.
func EncryptAES256GCM(plaintext []byte, password string) ([]byte, error) {
// create AES cipher
block, err := aes.NewCipher(getAESKey(password))
if err != nil {
return nil, err
}
Expand All @@ -78,9 +79,10 @@ func EncryptAES256GCM(plaintext []byte, encryptKey string) ([]byte, error) {
return ciphertext, nil
}

// DecryptAES256GCM decrypts the given ciphertext using AES-256-GCM with the given key.
func DecryptAES256GCM(ciphertext []byte, encryptKey string) ([]byte, error) {
block, err := aes.NewCipher(getAESKey(encryptKey))
// DecryptAES256GCM decrypts the given ciphertext using AES-256-GCM with the given password.
func DecryptAES256GCM(ciphertext []byte, password string) ([]byte, error) {
// create AES cipher
block, err := aes.NewCipher(getAESKey(password))
if err != nil {
return nil, err
}
Expand All @@ -94,7 +96,7 @@ func DecryptAES256GCM(ciphertext []byte, encryptKey string) ([]byte, error) {
// get the nonce size
nonceSize := gcm.NonceSize()
if len(ciphertext) < nonceSize {
return nil, err
return nil, errors.New("ciphertext too short")
}

// extract the nonce from the ciphertext
Expand All @@ -109,7 +111,7 @@ func DecryptAES256GCM(ciphertext []byte, encryptKey string) ([]byte, error) {
return plaintext, nil
}

// getAESKey uses SHA-256 to create a 32-byte key AES encryption.
// getAESKey uses SHA-256 to create a 32-byte key for AES encryption.
func getAESKey(key string) []byte {
h := sha256.New()
h.Write([]byte(key))
Expand Down
96 changes: 56 additions & 40 deletions pkg/crypto/aes256_gcm_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,32 +10,45 @@ import (

func Test_EncryptDecryptAES256GCM(t *testing.T) {
tests := []struct {
name string
plaintext string
encryptKey string
decryptKey string
modifyFunc func([]byte) []byte
fail bool
name string
plaintext string
encryptPass string
decryptPass string
modifyFunc func([]byte) []byte
fail bool
errMsg string
}{
{
name: "Successful encryption and decryption",
plaintext: "Hello, World!",
encryptKey: "my_password",
decryptKey: "my_password",
fail: false,
name: "Successful encryption and decryption",
plaintext: "Hello, World!",
encryptPass: "my_password",
decryptPass: "my_password",
fail: false,
},
{
name: "Decryption with incorrect key should fail",
plaintext: "Hello, World!",
encryptKey: "my_password",
decryptKey: "my_password2",
fail: true,
name: "Decryption with incorrect key should fail",
plaintext: "Hello, World!",
encryptPass: "my_password",
decryptPass: "my_password2",
fail: true,
},
{
name: "Decryption with corrupted ciphertext should fail",
plaintext: "Hello, World!",
encryptKey: "my_password",
decryptKey: "my_password",
name: "Decryption with ciphertext too short should fail",
plaintext: "Hello, World!",
encryptPass: "my_password",
decryptPass: "my_password",
modifyFunc: func(ciphertext []byte) []byte {
// truncate the ciphertext, nonce size is 12 bytes
return ciphertext[:10]
},
fail: true,
errMsg: "ciphertext too short",
},
{
name: "Decryption with corrupted ciphertext should fail",
plaintext: "Hello, World!",
encryptPass: "my_password",
decryptPass: "my_password",
modifyFunc: func(ciphertext []byte) []byte {
// flip the last bit of the ciphertext
ciphertext[len(ciphertext)-1] ^= 0x01
Expand All @@ -44,10 +57,10 @@ func Test_EncryptDecryptAES256GCM(t *testing.T) {
fail: true,
},
{
name: "Decryption with incorrect nonce should fail",
plaintext: "Hello, World!",
encryptKey: "my_password",
decryptKey: "my_password",
name: "Decryption with incorrect nonce should fail",
plaintext: "Hello, World!",
encryptPass: "my_password",
decryptPass: "my_password",
modifyFunc: func(ciphertext []byte) []byte {
// flip the first bit of the nonce
ciphertext[0] ^= 0x01
Expand All @@ -59,7 +72,7 @@ func Test_EncryptDecryptAES256GCM(t *testing.T) {

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
encrypted, err := crypto.EncryptAES256GCM([]byte(tt.plaintext), tt.encryptKey)
encrypted, err := crypto.EncryptAES256GCM([]byte(tt.plaintext), tt.encryptPass)
require.NoError(t, err)

// modify the encrypted data if needed
Expand All @@ -68,9 +81,12 @@ func Test_EncryptDecryptAES256GCM(t *testing.T) {
}

// decrypt the data
decrypted, err := crypto.DecryptAES256GCM(encrypted, tt.decryptKey)
decrypted, err := crypto.DecryptAES256GCM(encrypted, tt.decryptPass)
if tt.fail {
require.Error(t, err)
if tt.errMsg != "" {
require.Contains(t, err.Error(), tt.errMsg)
}
return
}

Expand All @@ -83,40 +99,40 @@ func Test_EncryptAES256GCMBase64(t *testing.T) {
tests := []struct {
name string
plaintext string
encryptKey string
decryptKey string
encryptPass string
decryptPass string
errorMessage string
}{
{
name: "Successful encryption and decryption",
plaintext: "Hello, World!",
encryptKey: "my_password",
decryptKey: "my_password",
name: "Successful encryption and decryption",
plaintext: "Hello, World!",
encryptPass: "my_password",
decryptPass: "my_password",
},
{
name: "Encryption with empty plaintext should fail",
plaintext: "",
errorMessage: "plaintext must not be empty",
},
{
name: "Encryption with empty encrypt key should fail",
name: "Encryption with empty password should fail",
plaintext: "Hello, World!",
encryptKey: "",
errorMessage: "encrypt key must not be empty",
encryptPass: "",
errorMessage: "password must not be empty",
},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
// encrypt the data
ciphertextBase64, err := crypto.EncryptAES256GCMBase64(tt.plaintext, tt.encryptKey)
ciphertextBase64, err := crypto.EncryptAES256GCMBase64(tt.plaintext, tt.encryptPass)
if tt.errorMessage != "" {
require.ErrorContains(t, err, tt.errorMessage)
return
}

// decrypt the data
decrypted, err := crypto.DecryptAES256GCMBase64(ciphertextBase64, tt.decryptKey)
decrypted, err := crypto.DecryptAES256GCMBase64(ciphertextBase64, tt.decryptPass)
require.NoError(t, err)

require.Equal(t, tt.plaintext, decrypted)
Expand Down Expand Up @@ -146,10 +162,10 @@ func Test_DecryptAES256GCMBase64(t *testing.T) {
errorMessage: "ciphertext must not be empty",
},
{
name: "Decryption with empty decrypt key should fail",
name: "Decryption with empty password should fail",
ciphertextBase64: "CXLWgHdVeZQwVOZZyHeZ5n5VB+eVSLaWFF0v0QOm9DyB7XSiHDwhNwQ=",
decryptKey: "",
errorMessage: "decrypt key must not be empty",
errorMessage: "password must not be empty",
},
{
name: "Decryption with invalid base64 ciphertext should fail",
Expand All @@ -158,7 +174,7 @@ func Test_DecryptAES256GCMBase64(t *testing.T) {
errorMessage: "failed to decode base64 ciphertext",
},
{
name: "Decryption with incorrect decrypt key should fail",
name: "Decryption with incorrect password should fail",
ciphertextBase64: "CXLWgHdVeZQwVOZZyHeZ5n5VB+eVSLaWFF0v0QOm9DyB7XSiHDwhNwQ=",
decryptKey: "my_password2",
errorMessage: "failed to decrypt ciphertext",
Expand Down
2 changes: 1 addition & 1 deletion pkg/crypto/privkey_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import (
"github.com/zeta-chain/zetacore/pkg/crypto"
)

func Test_IsValidSolanaPrivateKey(t *testing.T) {
func Test_SolanaPrivateKeyFromString(t *testing.T) {
tests := []struct {
name string
input string
Expand Down
Loading

0 comments on commit 98f041a

Please sign in to comment.