Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: TSS and Hotkey password Prompt #1574

Closed
wants to merge 15 commits into from
Closed
12 changes: 9 additions & 3 deletions changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,14 @@

## Unreleased

## Version: v12.0.0

### Breaking Changes

TSS and chain validation related queries have been moved from `crosschain` module to `observer` module:
* `PendingNonces` :Changed from `/zeta-chain/crosschain/pendingNonces/{chain_id}/{address}` to `/zeta-chain/observer/pendingNonces/{chain_id}/{address}` . It returns all the pending nonces for a chain id and address. This returns the current pending nonces for the chain.
* `ChainNonces` : Changed from `/zeta-chain/crosschain/chainNonces/{chain_id}` to`/zeta-chain/observer/chainNonces/{chain_id}` . It returns all the chain nonces for a chain id. This returns the current nonce oof the TSS address for the chain.
* `ChainNoncesAll` :Changed from `/zeta-chain/observer/chainNonces` to `/zeta-chain/observer/chainNonces` . It returns all the chain nonces for all chains. This returns the current nonce of the TSS address for all chains.
* `ChainNonces` : Changed from `/zeta-chain/crosschain/chainNonces/{chain_id}` to`/zeta-chain/observer/chainNonces/{chain_id}` . It returns all the chain nonces for a chain id. This returns the current nonce of the TSS address for the chain.
* `ChainNoncesAll` :Changed from `/zeta-chain/crosschain/chainNonces` to `/zeta-chain/observer/chainNonces` . It returns all the chain nonces for all chains. This returns the current nonce of the TSS address for all chains.

All chains now have the same observer set:
* `ObserversByChain`: `/zeta-chain/observer/observers_by_chain/{observation_chain}` has been removed and replaced with `/zeta-chain/observer/observer_set`. All chains have the same observer set.
Expand All @@ -19,7 +21,10 @@ Observer params and core params have been merged into chain params:
* `GetCoreParamsByChain`: Renamed into `GetChainParamsForChain`. `/zeta-chain/observer/get_core_params_by_chain` moved to `/zeta-chain/observer/get_chain_params_by_chain`.

Getting the correct TSS address for Bitcoin now requires proviidng the Bitcoin chain id:
* `GetTssAddress` : Changed from `/zeta-chain/observer/get_tss_address/` to `/zeta-chain/observer/getTssAddress/{bitcoin_chain_id}` . Optional bitcoing chain id can now now passed as a parameter to fetch the correct tss for required BTC chain.This parameter only affects the BTC tss address in the response.
* `GetTssAddress` : Changed from `/zeta-chain/observer/get_tss_address/` to `/zeta-chain/observer/getTssAddress/{bitcoin_chain_id}` . Optional bitcoin chain id can now be passed as a parameter to fetch the correct tss for required BTC chain. This parameter only affects the BTC tss address in the response.

Starting zetaclient now requires two passwords to be input; one for the hotkey and another for the tss key-share.
* `zetaclientd start` : 2 inputs required from stdin
lumtis marked this conversation as resolved.
Show resolved Hide resolved

### Features

Expand All @@ -30,6 +35,7 @@ Getting the correct TSS address for Bitcoin now requires proviidng the Bitcoin c
* enable zetaclients to use dynamic gas price on zetachain - enables >0 min_gas_price in feemarket module
* add static chain data for Sepolia testnet
* added metrics to track the burn rate of the hotkey in the telemetry server as well as prometheus
* [1574](https://github.com/zeta-chain/node/pull/1574) added password prompts for hotkey and tss keyshare in zetaclient
lumtis marked this conversation as resolved.
Show resolved Hide resolved

### Fixes

Expand Down
6 changes: 5 additions & 1 deletion cmd/zetaclientd/keygen_tss.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,9 @@ func GenerateTss(logger zerolog.Logger,
priKey secp256k1.PrivKey,
ts *mc.TelemetryServer,
tssHistoricalList []observertypes.TSS,
metrics *metrics.Metrics) (*mc.TSS, error) {
metrics *metrics.Metrics,
tssPassword string,
hotkeyPassword string) (*mc.TSS, error) {
keygenLogger := logger.With().Str("module", "keygen").Logger()

// Bitcoin chain ID is currently used for using the correct signature format
Expand All @@ -47,6 +49,8 @@ func GenerateTss(logger zerolog.Logger,
tssHistoricalList,
metrics,
bitcoinChainID,
tssPassword,
hotkeyPassword,
)
if err != nil {
keygenLogger.Error().Err(err).Msg("NewTSS error")
Expand Down
33 changes: 30 additions & 3 deletions cmd/zetaclientd/start.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package main

import (
"bufio"
"encoding/json"
"fmt"
"io"
Expand Down Expand Up @@ -45,6 +46,12 @@ func start(_ *cobra.Command, _ []string) error {

SetupConfigForTest()

//Prompt for Hotkey and TSS key-share passwords
hotkeyPass, tssKeyPass, err := promptPasswords()
if err != nil {
return err
}

//Load Config file given path
cfg, err := config.Load(rootArgs.zetaCoreHome)
if err != nil {
Expand Down Expand Up @@ -77,7 +84,7 @@ func start(_ *cobra.Command, _ []string) error {

// CreateZetaBridge: Zetabridge is used for all communication to zetacore , which this client connects to.
// Zetacore accumulates votes , and provides a centralized source of truth for all clients
zetaBridge, err := CreateZetaBridge(cfg, telemetryServer)
zetaBridge, err := CreateZetaBridge(cfg, telemetryServer, hotkeyPass)
if err != nil {
panic(err)
}
Expand Down Expand Up @@ -120,7 +127,7 @@ func start(_ *cobra.Command, _ []string) error {
// The bridgePk is private key for the Hotkey. The Hotkey is used to sign all inbound transactions
// Each node processes a portion of the key stored in ~/.tss by default . Custom location can be specified in config file during init.
// After generating the key , the address is set on the zetacore
bridgePk, err := zetaBridge.GetKeys().GetPrivateKey()
bridgePk, err := zetaBridge.GetKeys().GetPrivateKey(hotkeyPass)
if err != nil {
startLogger.Error().Err(err).Msg("zetabridge getPrivateKey error")
}
Expand Down Expand Up @@ -160,7 +167,7 @@ func start(_ *cobra.Command, _ []string) error {
}

telemetryServer.SetIPAddress(cfg.PublicIP)
tss, err := GenerateTss(masterLogger, cfg, zetaBridge, peers, priKey, telemetryServer, tssHistoricalList, metrics)
tss, err := GenerateTss(masterLogger, cfg, zetaBridge, peers, priKey, telemetryServer, tssHistoricalList, metrics, tssKeyPass, hotkeyPass)
if err != nil {
return err
}
Expand Down Expand Up @@ -309,3 +316,23 @@ func initPreParams(path string) {
}
}
}

func promptPasswords() (string, string, error) {
lumtis marked this conversation as resolved.
Show resolved Hide resolved
reader := bufio.NewReader(os.Stdin)
fmt.Print("HotKey Password: ")
hotKeyPass, err := reader.ReadString('\n')
if err != nil {
return "", "", err
}
fmt.Print("TSS Password: ")
TSSKeyPass, err := reader.ReadString('\n')
if err != nil {
return "", "", err
}

if TSSKeyPass == "" || hotKeyPass == "" {
return "", "", errors.New("hotkey and tss passwords are required to start zetaclient")
kevinssgh marked this conversation as resolved.
Show resolved Hide resolved
}

return hotKeyPass, TSSKeyPass, err
}
6 changes: 3 additions & 3 deletions cmd/zetaclientd/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,15 +15,15 @@ func CreateAuthzSigner(granter string, grantee sdk.AccAddress) {
zetaclient.SetupAuthZSignerList(granter, grantee)
}

func CreateZetaBridge(cfg *config.Config, telemetry *zetaclient.TelemetryServer) (*zetaclient.ZetaCoreBridge, error) {
func CreateZetaBridge(cfg *config.Config, telemetry *zetaclient.TelemetryServer, hotkeyPassword string) (*zetaclient.ZetaCoreBridge, error) {
hotKey := cfg.AuthzHotkey
if cfg.HsmMode {
hotKey = cfg.HsmHotKey
}

chainIP := cfg.ZetaCoreURL

kb, _, err := zetaclient.GetKeyringKeybase(cfg)
kb, _, err := zetaclient.GetKeyringKeybase(cfg, hotkeyPassword)
if err != nil {
return nil, err
}
Expand All @@ -33,7 +33,7 @@ func CreateZetaBridge(cfg *config.Config, telemetry *zetaclient.TelemetryServer)
return nil, err
}

k := zetaclient.NewKeysWithKeybase(kb, granterAddreess, cfg.AuthzHotkey)
k := zetaclient.NewKeysWithKeybase(kb, granterAddreess, cfg.AuthzHotkey, hotkeyPassword)

bridge, err := zetaclient.NewZetaCoreBridge(k, chainIP, hotKey, cfg.ChainID, cfg.HsmMode, telemetry)
if err != nil {
Expand Down
2 changes: 2 additions & 0 deletions contrib/localnet/scripts/password.file
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
password
pass2
4 changes: 2 additions & 2 deletions contrib/localnet/scripts/start-zetaclientd-genesis.sh
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ then
rm ~/.tss/*
MYIP=$(/sbin/ip -o -4 addr list eth0 | awk '{print $4}' | cut -d/ -f1)
zetaclientd init --zetacore-url zetacore0 --chain-id athens_101-1 --operator "$operatorAddress" --log-format=text --public-ip "$MYIP" --keyring-backend "$BACKEND"
zetaclientd start
zetaclientd start < /root/password.file
lumtis marked this conversation as resolved.
Show resolved Hide resolved
else
num=$(echo $HOSTNAME | tr -dc '0-9')
node="zetacore$num"
Expand All @@ -37,5 +37,5 @@ else
done
rm ~/.tss/*
zetaclientd init --peer /ip4/172.20.0.21/tcp/6668/p2p/"$SEED" --zetacore-url "$node" --chain-id athens_101-1 --operator "$operatorAddress" --log-format=text --public-ip "$MYIP" --log-level 0 --keyring-backend "$BACKEND"
zetaclientd start
zetaclientd start < /root/password.file
fi
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -335,6 +335,7 @@ replace (
// use cometbft
github.com/tendermint/tendermint => github.com/cometbft/cometbft v0.34.28
github.com/tendermint/tm-db => github.com/BlockPILabs/cosmos-db v0.0.3
github.com/zeta-chain/go-tss => github.com/zeta-chain/go-tss v0.1.1-0.20240115203400-a5b80e5da933

)

Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -3030,8 +3030,8 @@ github.com/yusufpapurcu/wmi v1.2.2/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQ
github.com/yvasiyarov/go-metrics v0.0.0-20140926110328-57bccd1ccd43/go.mod h1:aX5oPXxHm3bOH+xeAttToC8pqch2ScQN/JoXYupl6xs=
github.com/yvasiyarov/gorelic v0.0.0-20141212073537-a9bba5b9ab50/go.mod h1:NUSPSUX/bi6SeDMUh6brw0nXpxHnc96TguQh0+r/ssA=
github.com/yvasiyarov/newrelic_platform_go v0.0.0-20140908184405-b21fdbd4370f/go.mod h1:GlGEuHIJweS1mbCqG+7vt2nvWLzLLnRHbXz5JKd/Qbg=
github.com/zeta-chain/go-tss v0.1.1-0.20240103170132-35850edf5dbd h1:wv+VGLFX8IhPuoqAVQGAQjlEPWqYjowJgJVNReolJTM=
github.com/zeta-chain/go-tss v0.1.1-0.20240103170132-35850edf5dbd/go.mod h1:+lJfk/qqt+oxXeVuJV+PzpUoxftUfoTRf2eF3qlbyFI=
github.com/zeta-chain/go-tss v0.1.1-0.20240115203400-a5b80e5da933 h1:cx6ZXVmV9LpkYRQER7+sTgu56wdmaU1U5VJcx3rsCwc=
github.com/zeta-chain/go-tss v0.1.1-0.20240115203400-a5b80e5da933/go.mod h1:+lJfk/qqt+oxXeVuJV+PzpUoxftUfoTRf2eF3qlbyFI=
github.com/zeta-chain/keystone/keys v0.0.0-20231105174229-903bc9405da2 h1:gd2uE0X+ZbdFJ8DubxNqLbOVlCB12EgWdzSNRAR82tM=
github.com/zeta-chain/keystone/keys v0.0.0-20231105174229-903bc9405da2/go.mod h1:x7Bkwbzt2W2lQfjOirnff0Dj+tykdbTG1FMJPVPZsvE=
github.com/zeta-chain/protocol-contracts v1.0.2-athens3.0.20230816152528-db7d2bf9144b h1:aZRt5BtXdoDdyrUKwcv3B7mS30m/B854cjKjmnXBE5A=
Expand Down
5 changes: 1 addition & 4 deletions zetaclient/broadcast.go
Original file line number Diff line number Diff line change
Expand Up @@ -134,10 +134,7 @@ func (b *ZetaCoreBridge) GetContext() (client.Context, error) {
}

// if password is needed, set it as input
password, err := b.keys.GetHotkeyPassword()
if err != nil {
return ctx, err
}
password := b.keys.GetHotkeyPassword()
if password != "" {
ctx = ctx.WithInput(strings.NewReader(fmt.Sprintf("%[1]s\n%[1]s\n", password)))
}
Expand Down
51 changes: 12 additions & 39 deletions zetaclient/keys.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ package zetaclient

import (
"bytes"
"errors"
"fmt"
"io"
"os"
Expand All @@ -20,22 +19,21 @@ import (
"github.com/zeta-chain/zetacore/zetaclient/config"
)

// HotkeyPasswordEnvVar is the environment variable used to retrieve the password for the hotkey
const HotkeyPasswordEnvVar = "HOTKEY_PASSWORD"

// Keys manages all the keys used by zeta client
type Keys struct {
signerName string
kb ckeys.Keyring
OperatorAddress sdk.AccAddress
hotkeyPassword string
}

// NewKeysWithKeybase create a new instance of Keys
func NewKeysWithKeybase(kb ckeys.Keyring, granterAddress sdk.AccAddress, granteeName string) *Keys {
func NewKeysWithKeybase(kb ckeys.Keyring, granterAddress sdk.AccAddress, granteeName string, hotkeyPassword string) *Keys {
return &Keys{
signerName: granteeName,
kb: kb,
OperatorAddress: granterAddress,
hotkeyPassword: hotkeyPassword,
}
}

Expand All @@ -44,7 +42,7 @@ func GetGranteeKeyName(signerName string) string {
}

// GetKeyringKeybase return keyring and key info
func GetKeyringKeybase(cfg *config.Config) (ckeys.Keyring, string, error) {
func GetKeyringKeybase(cfg *config.Config, hotkeyPassword string) (ckeys.Keyring, string, error) {
lumtis marked this conversation as resolved.
Show resolved Hide resolved
granteeName := cfg.AuthzHotkey
chainHomeFolder := cfg.ZetaCoreHome
logger := log.Logger.With().Str("module", "GetKeyringKeybase").Logger()
Expand All @@ -55,13 +53,9 @@ func GetKeyringKeybase(cfg *config.Config) (ckeys.Keyring, string, error) {
// read password from env if using keyring backend file
buf := bytes.NewBufferString("")
if cfg.KeyringBackend == config.KeyringBackendFile {
password, err := getHotkeyPassword()
if err != nil {
return nil, "", err
}
buf.WriteString(password)
buf.WriteString(hotkeyPassword)
buf.WriteByte('\n') // the library used by keyring is using ReadLine , which expect a new line
buf.WriteString(password)
buf.WriteString(hotkeyPassword)
buf.WriteByte('\n')
}

Expand Down Expand Up @@ -137,12 +131,7 @@ func (k *Keys) GetAddress() sdk.AccAddress {
}

// GetPrivateKey return the private key
func (k *Keys) GetPrivateKey() (cryptotypes.PrivKey, error) {
password, err := k.GetHotkeyPassword()
if err != nil {
return nil, err
}

func (k *Keys) GetPrivateKey(password string) (cryptotypes.PrivKey, error) {
signer := GetGranteeKeyName(k.signerName)
privKeyArmor, err := k.kb.ExportPrivKeyArmor(signer, password)
if err != nil {
Expand All @@ -160,13 +149,13 @@ func (k *Keys) GetKeybase() ckeys.Keyring {
return k.kb
}

func (k *Keys) GetPubKeySet() (common.PubKeySet, error) {
func (k *Keys) GetPubKeySet(password string) (common.PubKeySet, error) {
pubkeySet := common.PubKeySet{
Secp256k1: "",
Ed25519: "",
}

pK, err := k.GetPrivateKey()
pK, err := k.GetPrivateKey(password)
if err != nil {
return pubkeySet, err
}
Expand All @@ -185,25 +174,9 @@ func (k *Keys) GetPubKeySet() (common.PubKeySet, error) {

// GetHotkeyPassword returns the password to be used
// returns empty if no password is needed
func (k *Keys) GetHotkeyPassword() (string, error) {
func (k *Keys) GetHotkeyPassword() string {
if k.GetKeybase().Backend() == ckeys.BackendFile {
return getHotkeyPassword()
}
return "", nil
}

// getHotkeyPassword retrieves the HOTKEY_PASSWORD environment variable
// and returns an error if it's not defined or shorter than 8 characters.
func getHotkeyPassword() (string, error) {
password := os.Getenv(HotkeyPasswordEnvVar)

if password == "" {
return "", errors.New("HOTKEY_PASSWORD environment variable is not defined, use --keyring-backend-test to use the test keyring")
return k.hotkeyPassword
}

if len(password) < 8 {
return "", errors.New("HOTKEY_PASSWORD should be at least 8 characters long")
}

return password, nil
return ""
}
8 changes: 4 additions & 4 deletions zetaclient/keys_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ func (ks *KeysSuite) TestGetKeyringKeybase(c *C) {
AuthzHotkey: "bob",
ZetaCoreHome: "/Users/test/.zetacored/",
}
_, _, err := GetKeyringKeybase(cfg)
_, _, err := GetKeyringKeybase(cfg, "")
c.Assert(err, NotNil)
}

Expand All @@ -101,15 +101,15 @@ func (ks *KeysSuite) TestNewKeys(c *C) {
ZetaCoreHome: folder,
}

k, _, err := GetKeyringKeybase(cfg)
k, _, err := GetKeyringKeybase(cfg, "")
c.Assert(err, IsNil)
c.Assert(k, NotNil)
granter := cosmos.AccAddress(crypto.AddressHash([]byte("granter")))
ki := NewKeysWithKeybase(k, granter, signerNameForTest)
ki := NewKeysWithKeybase(k, granter, signerNameForTest, "")
kInfo := ki.GetSignerInfo()
c.Assert(kInfo, NotNil)
//c.Assert(kInfo.G, Equals, signerNameForTest)
priKey, err := ki.GetPrivateKey()
priKey, err := ki.GetPrivateKey("")
c.Assert(err, IsNil)
c.Assert(priKey, NotNil)
c.Assert(priKey.Bytes(), HasLen, 32)
Expand Down
9 changes: 6 additions & 3 deletions zetaclient/tss_signer.go
Original file line number Diff line number Diff line change
Expand Up @@ -83,8 +83,10 @@ func NewTSS(
tssHistoricalList []observertypes.TSS,
metrics *metrics.Metrics,
bitcoinChainID int64,
tssPassword string,
hotkeyPassword string,
) (*TSS, error) {
server, err := SetupTSSServer(peer, privkey, preParams, cfg)
server, err := SetupTSSServer(peer, privkey, preParams, cfg, tssPassword)
if err != nil {
return nil, fmt.Errorf("SetupTSSServer error: %w", err)
}
Expand All @@ -101,7 +103,7 @@ func NewTSS(
if err != nil {
return nil, err
}
_, pubkeyInBech32, err := GetKeyringKeybase(cfg)
_, pubkeyInBech32, err := GetKeyringKeybase(cfg, hotkeyPassword)
if err != nil {
return nil, err
}
Expand All @@ -118,7 +120,7 @@ func NewTSS(
return &newTss, nil
}

func SetupTSSServer(peer p2p.AddrList, privkey tmcrypto.PrivKey, preParams *keygen.LocalPreParams, cfg *config.Config) (*tss.TssServer, error) {
func SetupTSSServer(peer p2p.AddrList, privkey tmcrypto.PrivKey, preParams *keygen.LocalPreParams, cfg *config.Config, tssPassword string) (*tss.TssServer, error) {
bootstrapPeers := peer
log.Info().Msgf("Peers AddrList %v", bootstrapPeers)

Expand Down Expand Up @@ -152,6 +154,7 @@ func SetupTSSServer(peer p2p.AddrList, privkey tmcrypto.PrivKey, preParams *keyg
},
preParams, // use pre-generated pre-params if non-nil
IP, // for docker test
tssPassword,
)
if err != nil {
log.Error().Err(err).Msg("NewTSS error")
Expand Down
Loading