Skip to content

Commit

Permalink
Add BLS key to AddPermissionlessValidatorTx for the Primary Network (
Browse files Browse the repository at this point in the history
…#1987)

Co-authored-by: Dan Laine <[email protected]>
Co-authored-by: Patrick O'Grady <[email protected]>
  • Loading branch information
3 people authored Sep 21, 2022
1 parent 9a0dccc commit fb6bb81
Show file tree
Hide file tree
Showing 50 changed files with 1,316 additions and 65 deletions.
8 changes: 1 addition & 7 deletions .github/workflows/build-and-test-mac-windows.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,14 +19,8 @@ jobs:
- uses: actions/checkout@v3
- uses: actions/setup-go@v3
with:
go-version: '1.18'
go-version: '1.19'
check-latest: true
# Downgrade mingw due to a regression causing tests with --race enabled to
# fail. See: https://github.com/actions/virtual-environments/issues/5841
- name: Install mingw 10.2.0
if: matrix.os == 'windows-latest'
shell: powershell
run: Choco-Install -PackageName mingw -ArgumentList "--version", "10.2.0", "--allow-downgrade"
- name: build_test
shell: bash
run: .github/workflows/build_and_test.sh
7 changes: 5 additions & 2 deletions .github/workflows/build-and-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,15 @@ on:
jobs:
run_build_unit_tests:
name: build_unit_test
runs-on: ubuntu-latest
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [macos-11, macos-12, ubuntu-20.04, ubuntu-22.04, windows-latest, [self-hosted, linux, ARM64, bionic]]
steps:
- uses: actions/checkout@v3
- uses: actions/setup-go@v3
with:
go-version: '1.18'
go-version: '1.19'
check-latest: true
- name: build_test
shell: bash
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/build-linux-binaries.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ jobs:
- uses: actions/checkout@v3
- uses: actions/setup-go@v3
with:
go-version: '1.18'
go-version: '1.19'
check-latest: true
- run: go version

Expand Down Expand Up @@ -52,7 +52,7 @@ jobs:
- uses: actions/checkout@v3
- uses: actions/setup-go@v3
with:
go-version: '1.18'
go-version: '1.19'
check-latest: true
- run: go version

Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/build-macos-release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ jobs:
- uses: actions/checkout@v3
- uses: actions/setup-go@v3
with:
go-version: '1.18'
go-version: '1.19'
check-latest: true
- run: go version

Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/build-public-api.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ jobs:
- uses: actions/checkout@v3
- uses: actions/setup-go@v3
with:
go-version: '1.18'
go-version: '1.19'
check-latest: true
- run: go version

Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/build-ubuntu-amd64-release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ jobs:
- uses: actions/checkout@v3
- uses: actions/setup-go@v3
with:
go-version: '1.18'
go-version: '1.19'
check-latest: true
- run: go version

Expand Down Expand Up @@ -52,7 +52,7 @@ jobs:
- uses: actions/checkout@v3
- uses: actions/setup-go@v3
with:
go-version: '1.18'
go-version: '1.19'
check-latest: true
- run: go version

Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/build-ubuntu-arm64-release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ jobs:
- uses: actions/checkout@v3
- uses: actions/setup-go@v3
with:
go-version: '1.18'
go-version: '1.19'
check-latest: true
- run: go version

Expand Down Expand Up @@ -52,7 +52,7 @@ jobs:
- uses: actions/checkout@v3
- uses: actions/setup-go@v3
with:
go-version: '1.18'
go-version: '1.19'
check-latest: true
- run: go version

Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/build-win-release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ jobs:
- uses: actions/checkout@v3
- uses: actions/setup-go@v3
with:
go-version: '1.18'
go-version: '1.19'
check-latest: true
- run: go version

Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ jobs:
- name: Set up Go
uses: actions/setup-go@v3
with:
go-version: '1.18'
go-version: '1.19'
check-latest: true
- name: Run GoReleaser
uses: goreleaser/goreleaser-action@v2
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/test.e2e.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ jobs:
- name: Set up Go
uses: actions/setup-go@v3
with:
go-version: '1.18'
go-version: '1.19'
check-latest: true
- name: Build the avalanchego binaries
shell: bash
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/test.upgrade.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ jobs:
- name: Set up Go
uses: actions/setup-go@v3
with:
go-version: '1.18'
go-version: '1.19'
check-latest: true
- name: Build the avalanchego binaries
shell: bash
Expand Down
7 changes: 4 additions & 3 deletions api/info/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,15 @@ import (

"github.com/ava-labs/avalanchego/ids"
"github.com/ava-labs/avalanchego/utils/rpc"
"github.com/ava-labs/avalanchego/vms/platformvm/signer"
)

var _ Client = &client{}

// Client interface for an Info API Client
type Client interface {
GetNodeVersion(context.Context, ...rpc.Option) (*GetNodeVersionReply, error)
GetNodeID(context.Context, ...rpc.Option) (ids.NodeID, error)
GetNodeID(context.Context, ...rpc.Option) (ids.NodeID, *signer.ProofOfPossession, error)
GetNodeIP(context.Context, ...rpc.Option) (string, error)
GetNetworkID(context.Context, ...rpc.Option) (uint32, error)
GetNetworkName(context.Context, ...rpc.Option) (string, error)
Expand Down Expand Up @@ -46,10 +47,10 @@ func (c *client) GetNodeVersion(ctx context.Context, options ...rpc.Option) (*Ge
return res, err
}

func (c *client) GetNodeID(ctx context.Context, options ...rpc.Option) (ids.NodeID, error) {
func (c *client) GetNodeID(ctx context.Context, options ...rpc.Option) (ids.NodeID, *signer.ProofOfPossession, error) {
res := &GetNodeIDReply{}
err := c.requester.SendRequest(ctx, "getNodeID", struct{}{}, res, options...)
return res.NodeID, err
return res.NodeID, res.NodePOP, err
}

func (c *client) GetNodeIP(ctx context.Context, options ...rpc.Option) (string, error) {
Expand Down
6 changes: 5 additions & 1 deletion api/info/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import (
"github.com/ava-labs/avalanchego/utils/logging"
"github.com/ava-labs/avalanchego/version"
"github.com/ava-labs/avalanchego/vms"
"github.com/ava-labs/avalanchego/vms/platformvm/signer"
)

var (
Expand All @@ -45,6 +46,7 @@ type Info struct {
type Parameters struct {
Version *version.Application
NodeID ids.NodeID
NodePOP *signer.ProofOfPossession
NetworkID uint32
TxFee uint64
CreateAssetTxFee uint64
Expand Down Expand Up @@ -114,14 +116,16 @@ func (service *Info) GetNodeVersion(_ *http.Request, _ *struct{}, reply *GetNode

// GetNodeIDReply are the results from calling GetNodeID
type GetNodeIDReply struct {
NodeID ids.NodeID `json:"nodeID"`
NodeID ids.NodeID `json:"nodeID"`
NodePOP *signer.ProofOfPossession `json:"nodePOP"`
}

// GetNodeID returns the node ID of this node
func (service *Info) GetNodeID(_ *http.Request, _ *struct{}, reply *GetNodeIDReply) error {
service.log.Debug("Info: GetNodeID called")

reply.NodeID = service.NodeID
reply.NodePOP = service.NodePOP
return nil
}

Expand Down
85 changes: 76 additions & 9 deletions config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (
"encoding/json"
"errors"
"fmt"
"io/fs"
"math"
"net"
"os"
Expand Down Expand Up @@ -36,10 +37,12 @@ import (
"github.com/ava-labs/avalanchego/snow/networking/tracker"
"github.com/ava-labs/avalanchego/staking"
"github.com/ava-labs/avalanchego/utils/constants"
"github.com/ava-labs/avalanchego/utils/crypto/bls"
"github.com/ava-labs/avalanchego/utils/dynamicip"
"github.com/ava-labs/avalanchego/utils/ips"
"github.com/ava-labs/avalanchego/utils/logging"
"github.com/ava-labs/avalanchego/utils/password"
"github.com/ava-labs/avalanchego/utils/perms"
"github.com/ava-labs/avalanchego/utils/profiler"
"github.com/ava-labs/avalanchego/utils/storage"
"github.com/ava-labs/avalanchego/utils/timer"
Expand Down Expand Up @@ -72,8 +75,8 @@ var (
errStakeMaxConsumptionBelowMin = errors.New("stake max consumption can't be less than min stake consumption")
errStakeMintingPeriodBelowMin = errors.New("stake minting period can't be less than max stake duration")
errCannotWhitelistPrimaryNetwork = errors.New("cannot whitelist primary network")
errStakingKeyContentUnset = fmt.Errorf("%s key not set but %s set", StakingKeyContentKey, StakingCertContentKey)
errStakingCertContentUnset = fmt.Errorf("%s key set but %s not set", StakingKeyContentKey, StakingCertContentKey)
errStakingKeyContentUnset = fmt.Errorf("%s key not set but %s set", StakingTLSKeyContentKey, StakingCertContentKey)
errStakingCertContentUnset = fmt.Errorf("%s key set but %s not set", StakingTLSKeyContentKey, StakingCertContentKey)
)

func GetRunnerConfig(v *viper.Viper) (runner.Config, error) {
Expand Down Expand Up @@ -651,7 +654,7 @@ func getProfilerConfig(v *viper.Viper) (profiler.Config, error) {
}

func getStakingTLSCertFromFlag(v *viper.Viper) (tls.Certificate, error) {
stakingKeyRawContent := v.GetString(StakingKeyContentKey)
stakingKeyRawContent := v.GetString(StakingTLSKeyContentKey)
stakingKeyContent, err := base64.StdEncoding.DecodeString(stakingKeyRawContent)
if err != nil {
return tls.Certificate{}, fmt.Errorf("unable to decode base64 content: %w", err)
Expand All @@ -673,11 +676,11 @@ func getStakingTLSCertFromFlag(v *viper.Viper) (tls.Certificate, error) {

func getStakingTLSCertFromFile(v *viper.Viper) (tls.Certificate, error) {
// Parse the staking key/cert paths and expand environment variables
stakingKeyPath := GetExpandedArg(v, StakingKeyPathKey)
stakingKeyPath := GetExpandedArg(v, StakingTLSKeyPathKey)
stakingCertPath := GetExpandedArg(v, StakingCertPathKey)

// If staking key/cert locations are specified but not found, error
if v.IsSet(StakingKeyPathKey) || v.IsSet(StakingCertPathKey) {
if v.IsSet(StakingTLSKeyPathKey) || v.IsSet(StakingCertPathKey) {
if _, err := os.Stat(stakingKeyPath); os.IsNotExist(err) {
return tls.Certificate{}, fmt.Errorf("couldn't find staking key at %s", stakingKeyPath)
} else if _, err := os.Stat(stakingCertPath); os.IsNotExist(err) {
Expand Down Expand Up @@ -709,23 +712,83 @@ func getStakingTLSCert(v *viper.Viper) (tls.Certificate, error) {
}

switch {
case v.IsSet(StakingKeyContentKey) && !v.IsSet(StakingCertContentKey):
case v.IsSet(StakingTLSKeyContentKey) && !v.IsSet(StakingCertContentKey):
return tls.Certificate{}, errStakingCertContentUnset
case !v.IsSet(StakingKeyContentKey) && v.IsSet(StakingCertContentKey):
case !v.IsSet(StakingTLSKeyContentKey) && v.IsSet(StakingCertContentKey):
return tls.Certificate{}, errStakingKeyContentUnset
case v.IsSet(StakingKeyContentKey) && v.IsSet(StakingCertContentKey):
case v.IsSet(StakingTLSKeyContentKey) && v.IsSet(StakingCertContentKey):
return getStakingTLSCertFromFlag(v)
default:
return getStakingTLSCertFromFile(v)
}
}

func getStakingSigner(v *viper.Viper) (*bls.SecretKey, error) {
if v.GetBool(StakingEphemeralSignerEnabledKey) {
key, err := bls.NewSecretKey()
if err != nil {
return nil, fmt.Errorf("couldn't generate ephemeral signing key: %w", err)
}
return key, nil
}

if v.IsSet(StakingSignerKeyContentKey) {
signerKeyRawContent := v.GetString(StakingSignerKeyContentKey)
signerKeyContent, err := base64.StdEncoding.DecodeString(signerKeyRawContent)
if err != nil {
return nil, fmt.Errorf("unable to decode base64 content: %w", err)
}
key, err := bls.SecretKeyFromBytes(signerKeyContent)
if err != nil {
return nil, fmt.Errorf("couldn't parse signing key: %w", err)
}
return key, nil
}

signingKeyPath := GetExpandedArg(v, StakingSignerKeyPathKey)
_, err := os.Stat(signingKeyPath)
if !errors.Is(err, fs.ErrNotExist) {
signingKeyBytes, err := os.ReadFile(signingKeyPath)
if err != nil {
return nil, err
}
key, err := bls.SecretKeyFromBytes(signingKeyBytes)
if err != nil {
return nil, fmt.Errorf("couldn't parse signing key: %w", err)
}
return key, nil
}

if v.IsSet(StakingSignerKeyPathKey) {
return nil, errors.New("missing staking signing key file")
}

key, err := bls.NewSecretKey()
if err != nil {
return nil, fmt.Errorf("couldn't generate new signing key: %w", err)
}

if err := os.MkdirAll(filepath.Dir(signingKeyPath), perms.ReadWriteExecute); err != nil {
return nil, fmt.Errorf("couldn't create path for signing key at %s: %w", signingKeyPath, err)
}

keyBytes := bls.SecretKeyToBytes(key)
if err := os.WriteFile(signingKeyPath, keyBytes, perms.ReadWrite); err != nil {
return nil, fmt.Errorf("couldn't write new signing key to %s: %w", signingKeyPath, err)
}
if err := os.Chmod(signingKeyPath, perms.ReadOnly); err != nil {
return nil, fmt.Errorf("couldn't restrict permissions on new signing key at %s: %w", signingKeyPath, err)
}
return key, nil
}

func getStakingConfig(v *viper.Viper, networkID uint32) (node.StakingConfig, error) {
config := node.StakingConfig{
EnableStaking: v.GetBool(StakingEnabledKey),
DisabledStakingWeight: v.GetUint64(StakingDisabledWeightKey),
StakingKeyPath: GetExpandedArg(v, StakingKeyPathKey),
StakingKeyPath: GetExpandedArg(v, StakingTLSKeyPathKey),
StakingCertPath: GetExpandedArg(v, StakingCertPathKey),
StakingSignerPath: GetExpandedArg(v, StakingSignerKeyPathKey),
}
if !config.EnableStaking && config.DisabledStakingWeight == 0 {
return node.StakingConfig{}, errInvalidStakerWeights
Expand All @@ -740,6 +803,10 @@ func getStakingConfig(v *viper.Viper, networkID uint32) (node.StakingConfig, err
if err != nil {
return node.StakingConfig{}, err
}
config.StakingSigningKey, err = getStakingSigner(v)
if err != nil {
return node.StakingConfig{}, err
}
if networkID != constants.MainnetID && networkID != constants.FujiID {
config.UptimeRequirement = v.GetFloat64(UptimeRequirementKey)
config.MinValidatorStake = v.GetUint64(MinValidatorStakeKey)
Expand Down
Loading

0 comments on commit fb6bb81

Please sign in to comment.