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

Node relayer for fuji #133

Open
wants to merge 11 commits into
base: main
Choose a base branch
from
1 change: 1 addition & 0 deletions avalanche/network.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
"strings"

"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"
Expand Down
1 change: 1 addition & 0 deletions constants/constants.go
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ const (
AvalancheGoGitRepo = "https://github.com/ava-labs/avalanchego"
SubnetEVMRepoName = "subnet-evm"

CloudNodeAWMRelayerPath = "/home/ubuntu/.awm-relayer"
AWMRelayerInstallDir = "awm-relayer"
AWMRelayerConfigFilename = "awm-relayer-config.json"

Expand Down
243 changes: 243 additions & 0 deletions examples/interchain_aws.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,243 @@
// Copyright (C) 2024, Ava Labs, Inc. All rights reserved.
// See the file LICENSE for licensing terms.

package examples

import (
"context"
"fmt"
"math/big"
"os"
"time"

"github.com/ava-labs/avalanche-tooling-sdk-go/avalanche"
awsAPI "github.com/ava-labs/avalanche-tooling-sdk-go/cloud/aws"
"github.com/ava-labs/avalanche-tooling-sdk-go/interchain/relayer"
"github.com/ava-labs/avalanche-tooling-sdk-go/key"
"github.com/ava-labs/avalanche-tooling-sdk-go/node"
"github.com/ava-labs/avalanche-tooling-sdk-go/utils"
"github.com/ava-labs/avalanchego/ids"
)

func InterchainAWSExample(
network avalanche.Network,
chain1RPC string,
chain1PK string,
chain1SubnetID ids.ID,
chain1BlockchainID ids.ID,
chain2RPC string,
chain2PK string,
chain2SubnetID ids.ID,
chain2BlockchainID ids.ID,
) error {
ctx := context.Background()

// Get the default cloud parameters for AWS
cp, err := node.GetDefaultCloudParams(ctx, node.AWSCloud)
if err != nil {
panic(err)
}

securityGroupName := "SECURITY_GROUP_NAME"
// Create a new security group in AWS if you do not currently have one in the selected
// AWS region.
sgID, err := awsAPI.CreateSecurityGroup(ctx, securityGroupName, cp.AWSConfig.AWSProfile, cp.Region)
if err != nil {
panic(err)
}
// Set the security group we are using when creating our Avalanche Nodes
cp.AWSConfig.AWSSecurityGroupName = securityGroupName
cp.AWSConfig.AWSSecurityGroupID = sgID

keyPairName := "KEY_PAIR_NAME"
sshPrivateKeyPath := utils.ExpandHome("PRIVATE_KEY_FILEPATH")
// Create a new AWS SSH key pair if you do not currently have one in your selected AWS region.
// Note that the created key pair can only be used in the region that it was created in.
// The private key to the created key pair will be stored in the filepath provided in
// sshPrivateKeyPath.
if err := awsAPI.CreateSSHKeyPair(ctx, cp.AWSConfig.AWSProfile, cp.Region, keyPairName, sshPrivateKeyPath); err != nil {
panic(err)
}
// Set the key pair we are using when creating our Avalanche Nodes
cp.AWSConfig.AWSKeyPair = keyPairName

const (
awmVersion = "v1.4.0"
)

// Create two new Avalanche Validator nodes on Fuji Network on AWS without Elastic IPs
// attached. Once CreateNodes is completed, the validators will begin bootstrapping process
// to Primary Network in Fuji Network. Nodes need to finish bootstrapping process
// before they can validate Avalanche Primary Network / Subnet.
//
// SDK function for nodes to start validating Primary Network / Subnet will be available
// in the next Avalanche Tooling SDK release.
hosts, err := node.CreateNodes(ctx,
&node.NodeParams{
CloudParams: cp,
Count: 1,
Roles: []node.SupportedRole{node.AWMRelayer},
Network: avalanche.FujiNetwork(),
AWMRelayerVersion: awmVersion,
UseStaticIP: false,
SSHPrivateKeyPath: sshPrivateKeyPath,
})
if err != nil {
panic(err)
}
if len(hosts) != 1 {
panic("expected 1 host")
}
awmRelayerHost := hosts[0] // single awm-relayer host

const (
sshTimeout = 120 * time.Second
sshCommandTimeout = 10 * time.Second
)

// Wait for the host to be ready (only needs to be done once for newly created nodes)
fmt.Println("Waiting for SSH shell")
if err := awmRelayerHost.WaitForSSHShell(sshTimeout); err != nil {
panic(err)
}

fmt.Println("Deploying Interchain Messenger to AWS")
chain1RelayerKey, err := key.NewSoft()
if err != nil {
return err
}
chain2RelayerKey, err := key.NewSoft()
if err != nil {
return err
}
chain1RegistryAddress, chain1MessengerAddress, chain2RegistryAddress, chain2MessengerAddress, err := SetupICM(
chain1RPC,
chain1PK,
chain2RPC,
chain2PK,
)
if err != nil {
return err
}
// Get default awm-relayer configuration
relayerConfig, err := awmRelayerHost.GetAMWRelayerConfig()
if err != nil {
panic(err)
}
// Add blockchain chain1 to the relayer config,
// setting it both as source and as destination.
// So the relayer will both listed for new messages in it,
// and send to it new messages from other blockchains.
relayer.AddBlockchainToRelayerConfig(
relayerConfig,
chain1RPC,
"",
chain1SubnetID,
chain1BlockchainID,
chain1RegistryAddress,
chain1MessengerAddress,
chain1RelayerKey.C(),
chain1RelayerKey.PrivKeyHex(),
)
// Add blockchain chain2 to the relayer config,
// setting it both as source and as destination.
// So the relayer will both listed for new messages in it,
// and send to it new messages from other blockchains.
relayer.AddBlockchainToRelayerConfig(
relayerConfig,
chain2RPC,
"",
chain2SubnetID,
chain2BlockchainID,
chain2RegistryAddress,
chain2MessengerAddress,
chain2RelayerKey.C(),
chain2RelayerKey.PrivKeyHex(),
)
// Set awm-relayer configuration for the host
if err := awmRelayerHost.SetAMWRelayerConfig(relayerConfig); err != nil {
panic(err)
}

// Fund each relayer key with 10 TOKENs
// Where TOKEN is the native gas token of each blockchain
// Assumes that the TOKEN decimals are 18, so, this equals
// to 1e18 of the smallest gas amount in each chain
fmt.Printf("Funding relayer keys %s, %s\n", chain1RelayerKey.C(), chain2RelayerKey.C())
desiredRelayerBalance := big.NewInt(0).Mul(big.NewInt(1e18), big.NewInt(10))

// chain1PK will have a balance 10 native gas tokens on chain.
if err := relayer.FundRelayer(
relayerConfig,
chain1BlockchainID,
chain1PK,
nil,
desiredRelayerBalance,
); err != nil {
return err
}
// chain2PK will have a balance 10 native gas tokens on chain2
if err := relayer.FundRelayer(
relayerConfig,
chain2BlockchainID,
chain2PK,
nil,
desiredRelayerBalance,
); err != nil {
return err
}

// send a message from chain1 to chain2
fmt.Println("Verifying message delivery")
if err := TestMessageDelivery(
chain1RPC,
chain1PK,
chain1MessengerAddress,
chain2BlockchainID,
chain2RPC,
chain2MessengerAddress,
[]byte("hello world"),
); err != nil {
return err
}

fmt.Println("Message successfully delivered")

return nil
}

func main() {
chain1RPC := os.Getenv("CHAIN1_RPC")
chain1PK := os.Getenv("CHAIN1_PK")
chain1SubnetID, err := ids.FromString(os.Getenv("CHAIN1_SUBNET_ID"))
if err != nil {
panic(err)
}
chain1BlockchainID, err := ids.FromString(os.Getenv("CHAIN1_BLOCKCHAIN_ID"))
if err != nil {
panic(err)
}
chain2RPC := os.Getenv("CHAIN2_RPC")
chain2PK := os.Getenv("CHAIN2_PK")
chain2SubnetID, err := ids.FromString(os.Getenv("CHAIN2_SUBNET_ID"))
if err != nil {
panic(err)
}
chain2BlockchainID, err := ids.FromString(os.Getenv("CHAIN2_BLOCKCHAIN_ID"))
if err != nil {
panic(err)
}
if err := InterchainAWSExample(
avalanche.FujiNetwork(),
chain1RPC,
chain1PK,
chain1SubnetID,
chain1BlockchainID,
chain2RPC,
chain2PK,
chain2SubnetID,
chain2BlockchainID,
); err != nil {
panic(err)
}
}
26 changes: 26 additions & 0 deletions node/config/awmRelayer.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
// Copyright (C) 2024, Ava Labs, Inc. All rights reserved.
// See the file LICENSE for licensing terms.

package services

import (
"path/filepath"

"github.com/ava-labs/avalanche-tooling-sdk-go/constants"
)

const DockerAWMRelayerPath = "/.awm-relayer"

func GetRemoteAMWRelayerConfig() string {
return filepath.Join(constants.CloudNodeAWMRelayerPath, constants.AWMRelayerConfigFilename)
}

func GetDockerAWMRelayerFolder() string {
return filepath.Join(DockerAWMRelayerPath, "storage")
}

func AWMRelayerFoldersToCreate() []string {
return []string{
filepath.Join(constants.CloudNodeAWMRelayerPath, "storage"),
}
}
15 changes: 11 additions & 4 deletions node/create.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,9 @@ type NodeParams struct {
// AvalancheGoVersion is the version of Avalanche Go to install in the created node
AvalancheGoVersion string

// AWMRelayerVersion is the version of AWM Relayer to install in the created node
AWMRelayerVersion string

// UseStaticIP is whether the created node should have static IP attached to it. Note that
// assigning Static IP to a node may incur additional charges on AWS / GCP. There could also be
// a limit to how many Static IPs you can have in a region in AWS & GCP.
Expand Down Expand Up @@ -272,7 +275,7 @@ func provisionHost(node Node, nodeParams *NodeParams) error {
return err
}
case AWMRelayer:
if err := provisionAWMRelayerHost(node); err != nil {
if err := provisionAWMRelayerHost(node, nodeParams); err != nil {
return err
}
default:
Expand Down Expand Up @@ -329,9 +332,13 @@ func provisionMonitoringHost(node Node) error {
return nil
}

func provisionAWMRelayerHost(node Node) error { // stub
if err := node.ComposeSSHSetupAWMRelayer(); err != nil {
func provisionAWMRelayerHost(node Node, nodeParams *NodeParams) error {
if err := node.RunSSHSetupDockerService(); err != nil {
return err
}
return node.StartDockerComposeService(utils.GetRemoteComposeFile(), constants.ServiceAWMRelayer, constants.SSHLongRunningScriptTimeout)
if err := node.ComposeSSHSetupAWMRelayer(nodeParams.Network, nodeParams.AWMRelayerVersion); err != nil {
return err
}

return node.StartDockerCompose(constants.SSHScriptTimeout)
}
12 changes: 6 additions & 6 deletions node/docker_compose.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,12 @@ import (
)

type dockerComposeInputs struct {
WithMonitoring bool
WithAvalanchego bool
AvalanchegoVersion string
E2E bool
E2EIP string
E2ESuffix string
WithMonitoring bool
WithAvalanchego bool
Version string
E2E bool
E2EIP string
E2ESuffix string
}

//go:embed templates/*.docker-compose.yml
Expand Down
Loading
Loading