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

add primary validator example #118

Merged
merged 59 commits into from
Aug 23, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
59 commits
Select commit Hold shift + click to select a range
c96ce75
add primary validator example
sukantoraymond Aug 8, 2024
235d6d7
remove print
sukantoraymond Aug 8, 2024
8594732
add example of validate primary network
sukantoraymond Aug 9, 2024
53acf86
remove fmt print
sukantoraymond Aug 9, 2024
0ab6af8
add subnet valdiator
sukantoraymond Aug 9, 2024
e4a7022
fix lint
sukantoraymond Aug 10, 2024
d90e2a0
change file name
sukantoraymond Aug 19, 2024
d946844
change validatorparams to primary network validator params
sukantoraymond Aug 19, 2024
bf6aa31
update generate staking files
sukantoraymond Aug 19, 2024
e258762
fix example
sukantoraymond Aug 20, 2024
b85398d
fix example
sukantoraymond Aug 20, 2024
f9e1c49
fix example
sukantoraymond Aug 20, 2024
4e05bf8
fix example
sukantoraymond Aug 20, 2024
df5ece7
Merge branch 'add-primary-validator' into add-subnet-validator-example
sukantoraymond Aug 21, 2024
71868f0
add subnet validator
sukantoraymond Aug 21, 2024
3e16c32
revert SetSubnetAuthMultisig
sukantoraymond Aug 22, 2024
c7f74d4
address comments
sukantoraymond Aug 22, 2024
2041101
remove unused constants
sukantoraymond Aug 22, 2024
424a6f3
update example
sukantoraymond Aug 22, 2024
75133a9
fix lint
sukantoraymond Aug 22, 2024
9a9a9fe
Merge branch 'add-primary-validator' into add-subnet-validator-example
sukantoraymond Aug 22, 2024
53aeb73
fix merge
sukantoraymond Aug 22, 2024
d295cf5
fix merge
sukantoraymond Aug 22, 2024
d0ddb61
fix merge
sukantoraymond Aug 22, 2024
a638db7
move validator
sukantoraymond Aug 22, 2024
87c9443
move subnet validator
sukantoraymond Aug 22, 2024
e59ca3e
update example
sukantoraymond Aug 22, 2024
bab121f
update example
sukantoraymond Aug 22, 2024
5fd58e4
update example
sukantoraymond Aug 22, 2024
2b55216
update example
sukantoraymond Aug 22, 2024
b96e284
update example
sukantoraymond Aug 22, 2024
723aa48
update example
sukantoraymond Aug 22, 2024
dd0fc42
update example
sukantoraymond Aug 22, 2024
2c74d45
update example
sukantoraymond Aug 22, 2024
40738f3
update example
sukantoraymond Aug 22, 2024
5078b2f
update example
sukantoraymond Aug 22, 2024
c5fce65
update example
sukantoraymond Aug 22, 2024
12f0e86
update example
sukantoraymond Aug 22, 2024
fb71900
update example
sukantoraymond Aug 22, 2024
461440f
update example
sukantoraymond Aug 22, 2024
c6f9dd0
update example
sukantoraymond Aug 22, 2024
c1f1730
update example
sukantoraymond Aug 22, 2024
a51d199
revert changes
sukantoraymond Aug 22, 2024
939ca4e
fix lint
sukantoraymond Aug 22, 2024
0adfc47
fix lint
sukantoraymond Aug 22, 2024
efb998b
add subnet validator example
sukantoraymond Aug 22, 2024
ae06017
fix lint
sukantoraymond Aug 22, 2024
b184302
add example
sukantoraymond Aug 22, 2024
16e9f2f
add example
sukantoraymond Aug 22, 2024
df386b9
update example
sukantoraymond Aug 23, 2024
ce57100
update example
sukantoraymond Aug 23, 2024
e17cde5
update example
sukantoraymond Aug 23, 2024
fe59f1e
fix lint
sukantoraymond Aug 23, 2024
69f2cb4
update example
sukantoraymond Aug 23, 2024
5a207c6
update example
sukantoraymond Aug 23, 2024
a3da517
fix lint
sukantoraymond Aug 23, 2024
2aecb5a
Merge pull request #120 from ava-labs/add-subnet-validator-example
sukantoraymond Aug 23, 2024
ef4471b
change validator name
sukantoraymond Aug 23, 2024
a638afe
update readme
sukantoraymond Aug 23, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
185 changes: 176 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,19 +5,21 @@ The official Avalanche Tooling Go SDK library.
*** Please note that this SDK is in experimental mode, major changes to the SDK are to be expected
in between releases ***

Current version (v0.2.0) currently supports:
Current version (v0.3.0) currently supports:
- Create Subnet and Create Blockchain in a Subnet in Fuji / Mainnet.
- Create Avalanche Node (Validator / API / Monitoring / Load Test Node) & install all required
dependencies (AvalancheGo, gcc, Promtail, Grafana, etc).
- Enable Avalanche nodes to validate Primary Network
- Adding Validators to a Subnet
- Ledger SDK

Currently, only stored keys are supported for transaction building and signing, ledger support is
coming soon.

Future SDK releases will contain the following features (in order of priority):
- Additional Nodes SDK features (Have Avalanche nodes validate a Subnet & Primary Network)
- Additional Subnet SDK features (i.e. Adding Validators to a Subnet, Custom Subnets)
- Additional Nodes SDK features (Devnet)
- Additional Subnet SDK features (Custom Subnets)
- Teleporter SDK
- Ledger SDK

## Getting Started

Expand All @@ -41,6 +43,8 @@ This examples also shows how to create a key pair to pay for transactions, how t
object that will be used to build and sign CreateSubnetTx and CreateChainTx and how to commit these
transactions on chain.

More examples can be found at examples directory.

```go
package main

Expand Down Expand Up @@ -74,7 +78,7 @@ func DeploySubnet() {
// Key that will be used for paying the transaction fees of CreateSubnetTx and CreateChainTx
// NewKeychain will generate a new key pair in the provided path if no .pk file currently
// exists in the provided path
keychain, _ := keychain.NewKeychain(network, "KEY_PATH")
keychain, _ := keychain.NewKeychain(network, "KEY_PATH", nil)

// In this example, we are using the fee-paying key generated above also as control key
// and subnet auth key
Expand All @@ -91,10 +95,9 @@ func DeploySubnet() {
// CreateSubnetTx.
//
// All keys in subnetAuthKeys have to sign the transaction before the transaction
// can be committed on chain
subnetAuthKeys := controlKeys
subnetAuthKeys := keychain.Addresses().List()
threshold := 1
newSubnet.SetSubnetCreateParams(controlKeys, uint32(threshold))
newSubnet.SetSubnetControlParams(controlKeys, uint32(threshold))

wallet, _ := wallet.New(
context.Background(),
Expand All @@ -115,7 +118,7 @@ func DeploySubnet() {
// we need to wait to allow the transaction to reach other nodes in Fuji
time.Sleep(2 * time.Second)

newSubnet.SetBlockchainCreateParams(subnetAuthKeys)
newSubnet.SetSubnetAuthKeys(subnetAuthKeys)
// Build and Sign CreateChainTx with our fee paying key (which is also our subnet auth key)
deployChainTx, _ := newSubnet.CreateBlockchainTx(wallet)
// Commit our CreateChainTx on chain
Expand All @@ -125,6 +128,111 @@ func DeploySubnet() {
fmt.Printf("blockchainID %s \n", blockchainID.String())
}

// Add a validator to Subnet
func AddSubnetValidator() {
// We are using existing Subnet that we have already deployed on Fuji
subnetParams := subnet.SubnetParams{
GenesisFilePath: "GENESIS_FILE_PATH",
Name: "SUBNET_NAME",
}

newSubnet, err := subnet.New(&subnetParams)
if err != nil {
panic(err)
}

subnetID, err := ids.FromString("SUBNET_ID")
if err != nil {
panic(err)
}

// Genesis doesn't contain the deployed Subnet's SubnetID, we need to first set the Subnet ID
newSubnet.SetSubnetID(subnetID)

// We are using existing host
node := node.Node{
// NodeID is Avalanche Node ID of the node
NodeID: "NODE_ID",
// IP address of the node
IP: "NODE_IP_ADDRESS",
// SSH configuration for the node
SSHConfig: node.SSHConfig{
User: constants.RemoteHostUser,
PrivateKeyPath: "NODE_KEYPAIR_PRIVATE_KEY_PATH",
},
// Role is the role that we expect the host to be (Validator, API, AWMRelayer, Loadtest or
// Monitor)
Roles: []node.SupportedRole{node.Validator},
}

// Here we are assuming that the node is currently validating the Primary Network, which is
// a requirement before the node can start validating a Subnet.
// To have a node validate the Primary Network, call node.ValidatePrimaryNetwork
// Now we are calling the node to start tracking the Subnet
subnetIDsToValidate := []string{newSubnet.SubnetID.String()}
if err := node.SyncSubnets(subnetIDsToValidate); err != nil {
panic(err)
}

// Node is now tracking the Subnet

// Key that will be used for paying the transaction fees of Subnet AddValidator Tx
//
// In our example, this Key is also the control Key to the Subnet, so we are going to use
// this key to also sign the Subnet AddValidator tx
network := avalanche.FujiNetwork()
keychain, err := keychain.NewKeychain(network, "PRIVATE_KEY_FILEPATH", nil)
if err != nil {
panic(err)
}

wallet, err := wallet.New(
context.Background(),
&primary.WalletConfig{
URI: network.Endpoint,
AVAXKeychain: keychain.Keychain,
EthKeychain: secp256k1fx.NewKeychain(),
PChainTxsToFetch: set.Of(subnetID),
},
)
if err != nil {
panic(err)
}

nodeID, err := ids.NodeIDFromString(node.NodeID)
if err != nil {
panic(err)
}

validatorParams := validator.SubnetValidatorParams{
NodeID: nodeID,
// Validate Subnet for 48 hours
Duration: 48 * time.Hour,
Weight: 20,
}

// We need to set Subnet Auth Keys for this transaction since Subnet AddValidator is
// a Subnet-changing transaction
//
// In this example, the example Subnet was created with only 1 key as control key with a threshold of 1
// and the control key is the key contained in the keychain object, so we are going to use the
// key contained in the keychain object as the Subnet Auth Key for Subnet AddValidator tx
subnetAuthKeys := keychain.Addresses().List()
newSubnet.SetSubnetAuthKeys(subnetAuthKeys)

addValidatorTx, err := newSubnet.AddValidator(wallet, validatorParams)
if err != nil {
panic(err)
}

// Since it has the required signatures, we will now commit the transaction on chain
txID, err := newSubnet.Commit(*addValidatorTx, wallet, true)
if err != nil {
panic(err)
}
fmt.Printf("obtained tx id %s", txID.String())
}

func getDefaultSubnetEVMGenesis() subnet.SubnetParams {
allocation := core.GenesisAlloc{}
defaultAmount, _ := new(big.Int).SetString(vm.DefaultEvmAirdropAmount, 10)
Expand Down Expand Up @@ -153,6 +261,8 @@ centralized Grafana Dashboard where you can view metrics relevant to any Validat
the monitoring node is linked to as well as a centralized logs for the X/P/C Chain and Subnet logs
for the Validator & API nodes. An example on how the dashboard and logs look like can be found at https://docs.avax.network/tooling/cli-create-nodes/create-a-validator-aws

More examples can be found at examples directory.

```go
package main

Expand Down Expand Up @@ -278,4 +388,61 @@ func CreateNodes() {
panic(err)
}
}

func ValidatePrimaryNetwork() {
// We are using existing host
node := node.Node{
// NodeID is Avalanche Node ID of the node
NodeID: "NODE_ID",
// IP address of the node
IP: "NODE_IP_ADDRESS",
// SSH configuration for the node
SSHConfig: node.SSHConfig{
User: constants.RemoteHostUser,
PrivateKeyPath: "NODE_KEYPAIR_PRIVATE_KEY_PATH",
},
// Role of the node can be Validator, API, AWMRelayer, Loadtest, or Monitor
Roles: []node.SupportedRole{node.Validator},
}

nodeID, err := ids.NodeIDFromString(node.NodeID)
if err != nil {
panic(err)
}

validatorParams := validator.PrimaryNetworkValidatorParams{
NodeID: nodeID,
// Validate Primary Network for 48 hours
Duration: 48 * time.Hour,
// Stake 2 AVAX
StakeAmount: 2 * units.Avax,
}

// Key that will be used for paying the transaction fee of AddValidator Tx
network := avalanche.FujiNetwork()
keychain, err := keychain.NewKeychain(network, "PRIVATE_KEY_FILEPATH", nil)
if err != nil {
panic(err)
}

wallet, err := wallet.New(
context.Background(),
&primary.WalletConfig{
URI: network.Endpoint,
AVAXKeychain: keychain.Keychain,
EthKeychain: secp256k1fx.NewKeychain(),
PChainTxsToFetch: nil,
},
)
if err != nil {
panic(err)
}

txID, err := node.ValidatePrimaryNetwork(avalanche.FujiNetwork(), validatorParams, wallet)
if err != nil {
panic(err)
}
fmt.Printf("obtained tx id %s", txID.String())
}

```
4 changes: 0 additions & 4 deletions avalanche/log.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,6 @@ import (
"os"
)

//
// Public constants
//

const (
// LevelNull sets a logger to show no messages at all.
LevelNull Level = 0
Expand Down
14 changes: 14 additions & 0 deletions avalanche/network.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,11 @@
package avalanche

import (
"github.com/ava-labs/avalanche-tooling-sdk-go/utils"
"github.com/ava-labs/avalanchego/genesis"
"github.com/ava-labs/avalanchego/ids"
"github.com/ava-labs/avalanchego/utils/constants"
"github.com/ava-labs/avalanchego/vms/platformvm"
)

type NetworkKind int64
Expand Down Expand Up @@ -90,3 +93,14 @@ func (n Network) GenesisParams() *genesis.Params {
}
return nil
}

func (n Network) GetMinStakingAmount() (uint64, error) {
pClient := platformvm.NewClient(n.Endpoint)
ctx, cancel := utils.GetAPIContext()
defer cancel()
minValStake, _, err := pClient.GetMinStake(ctx, ids.Empty)
if err != nil {
return 0, err
}
return minValStake, nil
}
2 changes: 1 addition & 1 deletion cloud/gcp/gcp.go
Original file line number Diff line number Diff line change
Expand Up @@ -238,7 +238,7 @@ func (c *GcpCloud) SetupInstances(
}
instances := make([]*compute.Instance, numNodes)
instancesChan := make(chan *compute.Instance, numNodes)
sshKey := fmt.Sprintf("%s:%s", constants.AnsibleSSHUser, strings.TrimSuffix(sshPublicKey, "\n"))
sshKey := fmt.Sprintf("%s:%s", constants.RemoteHostUser, strings.TrimSuffix(sshPublicKey, "\n"))
automaticRestart := true

instancePrefix := utils.RandomString(5)
Expand Down
15 changes: 6 additions & 9 deletions constants/constants.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,17 +42,14 @@ const (
SSHFileOpsTimeout = 100 * time.Second
SSHPOSTTimeout = 10 * time.Second
SSHScriptTimeout = 2 * time.Minute
AnsibleSSHUser = "ubuntu"
RemoteHostUser = "ubuntu"

// node
CloudNodeCLIConfigBasePath = "/home/ubuntu/.avalanche-cli/"
CloudNodeConfigBasePath = "/home/ubuntu/.avalanchego/"
CloudNodeSubnetVMBinaryPath = "/home/ubuntu/.avalanchego/plugins/%s"
CloudNodeStakingPath = "/home/ubuntu/.avalanchego/staking/"
CloudNodeConfigPath = "/home/ubuntu/.avalanchego/configs/"
ServicesDir = "services"
DashboardsDir = "dashboards"

CloudNodeCLIConfigBasePath = "/home/ubuntu/.avalanche-cli/"
CloudNodeStakingPath = "/home/ubuntu/.avalanchego/staking/"
CloudNodeConfigPath = "/home/ubuntu/.avalanchego/configs/"
ServicesDir = "services"
DashboardsDir = "dashboards"
// services
ServiceAvalanchego = "avalanchego"
ServicePromtail = "promtail"
Expand Down
9 changes: 0 additions & 9 deletions examples/node.go
Original file line number Diff line number Diff line change
Expand Up @@ -102,15 +102,6 @@ func CreateNodes() {
}
}

// examle of how to reconfigure the created nodes to track a subnet
subnetIDsToValidate := []string{"xxxxxxxxxxxxxxxxxxxyyyyyyyyyyyyyyyzzzzzzzzzzzzzzz"}
for _, h := range hosts {
fmt.Println("Reconfiguring node %s to track subnet %s", h.NodeID, subnetIDsToValidate)
if err := h.SyncSubnets(subnetIDsToValidate); err != nil {
panic(err)
}
}

// Create a monitoring node.
// Monitoring node enables you to have a centralized Grafana Dashboard where you can view
// metrics relevant to any Validator & API nodes that the monitoring node is linked to as well
Expand Down
Loading
Loading