diff --git a/chain/cosmos/wasm/wasm.go b/chain/cosmos/wasm/wasm.go index abbfd7c52..46886314a 100644 --- a/chain/cosmos/wasm/wasm.go +++ b/chain/cosmos/wasm/wasm.go @@ -14,4 +14,4 @@ func WasmEncoding() *testutil.TestEncodingConfig { wasmtypes.RegisterInterfaces(cfg.InterfaceRegistry) return &cfg -} \ No newline at end of file +} diff --git a/chain/penumbra/penumbra_app_node.go b/chain/penumbra/penumbra_app_node.go index 96e3ade70..f85bfd3e5 100644 --- a/chain/penumbra/penumbra_app_node.go +++ b/chain/penumbra/penumbra_app_node.go @@ -18,6 +18,7 @@ import ( "go.uber.org/zap" ) +// PenumbraAppNode represents an instance of pcli. type PenumbraAppNode struct { log *zap.Logger @@ -36,6 +37,19 @@ type PenumbraAppNode struct { hostGRPCPort string } +// NewPenumbraAppNode creates a new instance of PenumbraAppNode with the provided parameters. +// It initializes the PenumbraAppNode struct, sets the logger, index, chain, Docker client, +// network ID, test name, and Docker image. +// It also creates a container lifecycle instance with the provided logger, Docker client, +// and node name. +// Next, it creates a Docker volume with labels for cleanup and owner identification. +// If volume creation fails, an error is returned. +// The volume name is set to the PenumbraAppNode volume name. +// The volume owner is set using the provided context, Docker client, volume name, image reference, +// test name, and UID/GID from the Docker image. +// If volume owner setting fails, an error is returned. +// Finally, the created PenumbraAppNode instance is returned along with a nil error, +// or a nil PenumbraAppNode and a non-nil error if any step in the process fails. func NewPenumbraAppNode( ctx context.Context, log *zap.Logger, @@ -60,6 +74,7 @@ func NewPenumbraAppNode( if err != nil { return nil, fmt.Errorf("creating penumbra volume: %w", err) } + pn.VolumeName = pv.Name if err := dockerutil.SetVolumeOwner(ctx, dockerutil.VolumeOwnerOptions{ Log: log, @@ -91,37 +106,43 @@ var exposedPorts = nat.PortSet{ nat.Port(metricsPort): {}, } -// Name of the test node container +// Name of the test node container. func (p *PenumbraAppNode) Name() string { return fmt.Sprintf("pd-%d-%s-%s", p.Index, p.Chain.Config().ChainID, p.TestName) } -// the hostname of the test node container +// HostName returns the hostname of the test node container. func (p *PenumbraAppNode) HostName() string { return dockerutil.CondenseHostName(p.Name()) } -// Bind returns the home folder bind point for running the node +// Bind returns the home folder bind point for running the node. func (p *PenumbraAppNode) Bind() []string { return []string{fmt.Sprintf("%s:%s", p.VolumeName, p.HomeDir())} } +// HomeDir returns the home directory location in the Docker filesystem. func (p *PenumbraAppNode) HomeDir() string { return "/home/heighliner" } +// CreateKey attempts to initialize a new pcli config file with a newly generated FullViewingKey and CustodyKey. func (p *PenumbraAppNode) CreateKey(ctx context.Context, keyName string) error { keyPath := filepath.Join(p.HomeDir(), "keys", keyName) pdUrl := fmt.Sprintf("http://%s:8080", p.HostName()) cmd := []string{"pcli", "--home", keyPath, "init", "--grpc-url", pdUrl, "soft-kms", "generate"} + _, stderr, err := p.Exec(ctx, cmd, nil) - // already exists error is okay + + // key already exists, error is okay if err != nil && !strings.Contains(string(stderr), "not empty;, refusing to initialize") { return err } + return nil } +// PcliConfig represents the config.toml file associated with an instance of pcli. type PcliConfig struct { GrpcURL string `toml:"grpc_url"` FullViewingKey string `toml:"full_viewing_key"` @@ -143,6 +164,7 @@ func (p *PenumbraAppNode) ReadFile(ctx context.Context, relPath string) ([]byte, return fileBz, nil } +// FullViewingKey attempts to read the FullViewingKey from the config.toml file associated with this instance of pcli. func (p *PenumbraAppNode) FullViewingKey(ctx context.Context, keyName string) (string, error) { keyPath := filepath.Join(p.HomeDir(), "keys", keyName) fileBz, err := p.ReadFile(ctx, keyPath+"config.toml") @@ -170,15 +192,15 @@ func (p *PenumbraAppNode) RecoverKey(ctx context.Context, keyName, mnemonic stri _, stderr, err := p.Exec(ctx, cmd, nil) - // already exists error is okay + // key already exists, error is okay if err != nil && !strings.Contains(string(stderr), "already exists, refusing to overwrite it") { return err } + return nil } -// initializes validator definition template file -// wallet must be generated first +// InitValidatorFile initializes validator definition template file, wallet must be generated first. func (p *PenumbraAppNode) InitValidatorFile(ctx context.Context, valKeyName string) error { keyPath := filepath.Join(p.HomeDir(), "keys", valKeyName) cmd := []string{ @@ -187,22 +209,31 @@ func (p *PenumbraAppNode) InitValidatorFile(ctx context.Context, valKeyName stri "validator", "definition", "template", "--file", p.ValidatorDefinitionTemplateFilePathContainer(), } + _, _, err := p.Exec(ctx, cmd, nil) return err } +// ValidatorDefinitionTemplateFilePathContainer returns the path to the validator.toml file associated with +// this instance of pcli. func (p *PenumbraAppNode) ValidatorDefinitionTemplateFilePathContainer() string { return filepath.Join(p.HomeDir(), "validator.toml") } +// ValidatorsInputFileContainer returns the path to the validators.json file associated with +// this instance of pcli. func (p *PenumbraAppNode) ValidatorsInputFileContainer() string { return filepath.Join(p.HomeDir(), "validators.json") } +// AllocationsInputFileContainer returns the path to the allocations.csv file that should be used +// to generate the genesis file before spinning up the network from a fresh genesis. func (p *PenumbraAppNode) AllocationsInputFileContainer() string { return filepath.Join(p.HomeDir(), "allocations.csv") } +// genesisFileContent attempts to read the contents of the genesis.json file associated with the +// network that we are attempting to initialize from genesis. func (p *PenumbraAppNode) genesisFileContent(ctx context.Context) ([]byte, error) { fr := dockerutil.NewFileRetriever(p.log, p.DockerClient, p.TestName) gen, err := fr.SingleFileContent(ctx, p.VolumeName, ".penumbra/testnet_data/node0/cometbft/config/genesis.json") @@ -213,6 +244,9 @@ func (p *PenumbraAppNode) genesisFileContent(ctx context.Context) ([]byte, error return gen, nil } +// GenerateGenesisFile attempts to create the validators.json file and the allocations.csv file, write the files to +// the Docker filesystem, and then generate the directory structure containing necessary files to create a +// new testnet from genesis via an instance of pd. func (p *PenumbraAppNode) GenerateGenesisFile( ctx context.Context, chainID string, @@ -255,9 +289,9 @@ func (p *PenumbraAppNode) GenerateGenesisFile( return err } +// GetAddress attempts to return a Penumbra address associated with a specified key name. func (p *PenumbraAppNode) GetAddress(ctx context.Context, keyName string) ([]byte, error) { keyPath := filepath.Join(p.HomeDir(), "keys", keyName) - //pdUrl := fmt.Sprintf("http://%s:8080", p.HostName()) cmd := []string{"pcli", "--home", keyPath, "view", "address"} stdout, _, err := p.Exec(ctx, cmd, nil) @@ -273,10 +307,10 @@ func (p *PenumbraAppNode) GetAddress(ctx context.Context, keyName string) ([]byt return []byte(addr), nil } +// GetBalance attempts to query the token balances for a specified key name via an instance of pcli. // TODO we need to change the func sig to take a denom then filter out the target denom bal from stdout func (p *PenumbraAppNode) GetBalance(ctx context.Context, keyName string) (int64, error) { keyPath := filepath.Join(p.HomeDir(), "keys", keyName) - //pdUrl := fmt.Sprintf("http://%s:8080", p.HostName()) cmd := []string{"pcli", "--home", keyPath, "view", "balance"} stdout, _, err := p.Exec(ctx, cmd, nil) @@ -288,26 +322,43 @@ func (p *PenumbraAppNode) GetBalance(ctx context.Context, keyName string) (int64 return 0, nil } +// GetAddressBech32m retrieves the address associated with the specified key name. +// It executes the 'pcli' command and parses the output to find the desired address. +// The 'pcli' command is executed with the '--home' flag and the home directory of the app node. +// If no address is found for the key name, it returns an error indicating that the address was not found. +// The function returns the retrieved address as a string and an error if any occurred. func (p *PenumbraAppNode) GetAddressBech32m(ctx context.Context, keyName string) (string, error) { cmd := []string{"pcli", "--home", p.HomeDir(), "addr", "list"} stdout, _, err := p.Exec(ctx, cmd, nil) if err != nil { return "", err } + addresses := strings.Split(string(stdout), "\n") for _, address := range addresses { fields := strings.Fields(address) if len(fields) < 3 { continue } + if fields[1] == keyName { return fields[2], nil } } - return "", errors.New("address not found") + return "", errors.New("address not found") } +// CreateNodeContainer creates a container for the PenumbraAppNode. +// It starts the PenumbraAppNode process with the specified tendermintAddress. +// The container is created using the CreateContainer method of the containerLifecycle object. +// The container is named using p.TestName. +// It is assigned the p.NetworkID network and runs on the p.Image image. +// The container also exposes the abciPort, grpcPort, and metricsPort. +// The container's home directory is set to p.HomeDir(). +// The command to start the PenumbraAppNode process is constructed using the pd command and its arguments. +// Additional environment variables can be set using the env parameter. +// The method returns any errors encountered during the container creation process. func (p *PenumbraAppNode) CreateNodeContainer(ctx context.Context, tendermintAddress string) error { cmd := []string{ "pd", "start", @@ -318,18 +369,24 @@ func (p *PenumbraAppNode) CreateNodeContainer(ctx context.Context, tendermintAdd "--home", p.HomeDir(), } - // TODO: remove after debugging - env := []string{ - "RUST_LOG=debug", - } + // env can be used to set environment variables to do things like set RUST_LOG=debug. + var env []string return p.containerLifecycle.CreateContainer(ctx, p.TestName, p.NetworkID, p.Image, exposedPorts, p.Bind(), p.HostName(), cmd, env) } +// StopContainer stops the running container for the PenumbraAppNode. func (p *PenumbraAppNode) StopContainer(ctx context.Context) error { return p.containerLifecycle.StopContainer(ctx) } +// StartContainer starts the test node container. +// It calls the StartContainer method of the containerLifecycle field to start the container. +// If an error occurs, it is returned. +// It then calls the GetHostPorts method of the containerLifecycle field to retrieve the host ports for RPC and gRPC. +// If an error occurs, it is returned. +// The obtained host ports are assigned to the hostRPCPort and hostGRPCPort fields of the PenumbraAppNode struct. +// Finally, nil is returned if everything is successful. func (p *PenumbraAppNode) StartContainer(ctx context.Context) error { if err := p.containerLifecycle.StartContainer(ctx); err != nil { return err @@ -345,7 +402,7 @@ func (p *PenumbraAppNode) StartContainer(ctx context.Context) error { return nil } -// Exec run a container for a specific job and block until the container exits +// Exec run a container for a specific job and blocks until the container exits. func (p *PenumbraAppNode) Exec(ctx context.Context, cmd []string, env []string) ([]byte, []byte, error) { job := dockerutil.NewImage(p.log, p.DockerClient, p.NetworkID, p.TestName, p.Image.Repository, p.Image.Version) opts := dockerutil.ContainerOptions{ @@ -353,10 +410,29 @@ func (p *PenumbraAppNode) Exec(ctx context.Context, cmd []string, env []string) Env: env, User: p.Image.UidGid, } + res := job.Run(ctx, cmd, opts) return res.Stdout, res.Stderr, res.Err } +// SendIBCTransfer sends an IBC transfer from the current node to a specified address and channel. +// +// Parameters: +// - ctx: The context of the method call. +// - channelID: The ID of the channel to send the transfer. +// - keyName: The name of the key used for signing the transaction. +// - amount: The amount to transfer (including address and denomination). +// - opts: Additional options for the transfer. +// +// Returns: +// - tx: The transaction information for the IBC transfer (partially filled). +// - error: An error if the transfer fails. +// +// Note: The `SendIBCTransfer` method uses the `pcli` command-line tool to execute a transaction +// +// to withdraw tokens from the specified channel and send them to the specified address. +// The `tx` object returned represents the transaction information for the IBC transfer. +// The function currently does not fill in all details of the `tx` object and requires further implementation. func (p *PenumbraAppNode) SendIBCTransfer(ctx context.Context, channelID, keyName string, amount ibc.WalletAmount, opts ibc.TransferOptions) (ibc.Tx, error) { keyPath := filepath.Join(p.HomeDir(), "keys", keyName) diff --git a/chain/penumbra/penumbra_chain.go b/chain/penumbra/penumbra_chain.go index 6067d76c1..e59c0692e 100644 --- a/chain/penumbra/penumbra_chain.go +++ b/chain/penumbra/penumbra_chain.go @@ -68,6 +68,7 @@ type PenumbraGenesisAppStateAllocation struct { Address string `json:"address"` } +// NewPenumbraChain returns a new instance of PenumbraChain. func NewPenumbraChain(log *zap.Logger, testName string, chainConfig ibc.ChainConfig, numValidators int, numFullNodes int) *PenumbraChain { registry := codectypes.NewInterfaceRegistry() cryptocodec.RegisterInterfaces(registry) @@ -84,40 +85,44 @@ func NewPenumbraChain(log *zap.Logger, testName string, chainConfig ibc.ChainCon } } +// Acknowledgements implements Chain interface. func (c *PenumbraChain) Acknowledgements(ctx context.Context, height uint64) ([]ibc.PacketAcknowledgement, error) { panic("implement me") } +// Timeouts implements Chain interface. func (c *PenumbraChain) Timeouts(ctx context.Context, height uint64) ([]ibc.PacketTimeout, error) { panic("implement me") } -// Implements Chain interface +// Config returns the Chain's ChainConfig. func (c *PenumbraChain) Config() ibc.ChainConfig { return c.cfg } -// Implements Chain interface +// Initialize creates the test node objects required for bootstrapping tests. func (c *PenumbraChain) Initialize(ctx context.Context, testName string, cli *client.Client, networkID string) error { return c.initializeChainNodes(ctx, testName, cli, networkID) } -// Exec implements chain interface. +// Exec attempts to execute an arbitrary cmd with specified env variables and returns the output returned to +// both stdout and stderr. func (c *PenumbraChain) Exec(ctx context.Context, cmd []string, env []string) (stdout, stderr []byte, err error) { return c.getFullNode().PenumbraAppNode.Exec(ctx, cmd, env) } +// getFullNode returns the first configured validator node in the network. func (c *PenumbraChain) getFullNode() *PenumbraNode { // use first validator return c.PenumbraNodes[0] } -// Implements Chain interface +// GetRPCAddress returns the RPC address associated with an underlying node's Tendermint host name. func (c *PenumbraChain) GetRPCAddress() string { return fmt.Sprintf("http://%s:26657", c.getFullNode().TendermintNode.HostName()) } -// Implements Chain interface +// GetGRPCAddress returns the GRPC address associated with an underlying node's Tendermint host name. func (c *PenumbraChain) GetGRPCAddress() string { return fmt.Sprintf("%s:9090", c.getFullNode().TendermintNode.HostName()) } @@ -134,6 +139,7 @@ func (c *PenumbraChain) GetHostGRPCAddress() string { return c.getFullNode().PenumbraAppNode.hostGRPCPort } +// HomeDir returns the PenumbraAppNode's home directory in the Docker filesystem. func (c *PenumbraChain) HomeDir() string { return c.getFullNode().PenumbraAppNode.HomeDir() } @@ -165,9 +171,8 @@ func (c *PenumbraChain) GetAddress(ctx context.Context, keyName string) ([]byte, return fn.PenumbraAppNode.GetAddress(ctx, keyName) } -// BuildWallet will return a Penumbra wallet -// If mnemonic != "", it will restore using that mnemonic -// If mnemonic == "", it will create a new key +// BuildWallet will return a Penumbra wallet. +// If mnemonic != "", it will restore using that mnemonic. If mnemonic == "", it will create a new key. func (c *PenumbraChain) BuildWallet(ctx context.Context, keyName string, mnemonic string) (ibc.Wallet, error) { if mnemonic != "" { if err := c.RecoverKey(ctx, keyName, mnemonic); err != nil { @@ -238,6 +243,7 @@ func (c *PenumbraChain) SendIBCTransfer( return fn.PenumbraClientNodes[keyName].SendIBCTransfer(ctx, channelID, amount, options) } +// ExportState implements Chain interface. func (c *PenumbraChain) ExportState(ctx context.Context, height int64) (string, error) { panic("implement me") } @@ -271,7 +277,7 @@ func (c *PenumbraChain) GetGasFeesInNativeDenom(gasPaid int64) int64 { return int64(fees) } -// creates the test node objects required for bootstrapping tests +// initializeChainNodes creates the test node objects required for bootstrapping tests. func (c *PenumbraChain) initializeChainNodes( ctx context.Context, testName string, @@ -298,6 +304,7 @@ func (c *PenumbraChain) initializeChainNodes( _ = rc.Close() } } + for i := 0; i < count; i++ { pn, err := NewPenumbraNode(ctx, i, c, cli, networkID, testName, chainCfg.Images[0], chainCfg.Images[1]) if err != nil { @@ -305,6 +312,7 @@ func (c *PenumbraChain) initializeChainNodes( } penumbraNodes = append(penumbraNodes, &pn) } + c.PenumbraNodes = penumbraNodes return nil @@ -332,6 +340,8 @@ type ValidatorWithIntPower struct { PubKeyBase64 string } +// Start sets up everything needed, (validators, gentx, fullnodes, peering, additional accounts), +// for the chain to start from genesis. func (c *PenumbraChain) Start(testName string, ctx context.Context, additionalGenesisWallets ...ibc.WalletAmount) error { validators := c.PenumbraNodes[:c.numValidators] fullnodes := c.PenumbraNodes[c.numValidators:] @@ -345,6 +355,7 @@ func (c *PenumbraChain) Start(testName string, ctx context.Context, additionalGe for i, v := range validators { v := v i := i + keyName := fmt.Sprintf("%s-%d", valKey, i) eg.Go(func() error { if err := v.TendermintNode.InitValidatorFiles(egCtx); err != nil { @@ -473,7 +484,7 @@ func (c *PenumbraChain) Start(testName string, ctx context.Context, additionalGe return c.start(ctx) } -// Bootstraps the chain and starts it from genesis +// start bootstraps the chain and starts it from genesis. func (c *PenumbraChain) start(ctx context.Context) error { // Copy the penumbra genesis to all tendermint nodes. genesisContent, err := c.PenumbraNodes[0].PenumbraAppNode.genesisFileContent(ctx) @@ -588,6 +599,8 @@ func (c *PenumbraChain) start(ctx context.Context) error { return eg.Wait() } +// CreateClientNode initializes a new instance of pclientd, with the FullViewingKey and CustodyKey, +// associated with the specified keyName. func (c *PenumbraChain) CreateClientNode( ctx context.Context, keyName string, diff --git a/chain/penumbra/penumbra_client_node.go b/chain/penumbra/penumbra_client_node.go index b5aa9a1ab..20a7830ad 100644 --- a/chain/penumbra/penumbra_client_node.go +++ b/chain/penumbra/penumbra_client_node.go @@ -17,7 +17,7 @@ import ( "github.com/docker/go-connections/nat" assetv1alpha1 "github.com/strangelove-ventures/interchaintest/v8/chain/penumbra/core/asset/v1alpha1" ibcv1alpha1 "github.com/strangelove-ventures/interchaintest/v8/chain/penumbra/core/component/ibc/v1alpha1" - shielded_poolv1alpha1 "github.com/strangelove-ventures/interchaintest/v8/chain/penumbra/core/component/shielded_pool/v1alpha1" + shieldedpoolv1alpha1 "github.com/strangelove-ventures/interchaintest/v8/chain/penumbra/core/component/shielded_pool/v1alpha1" keysv1alpha1 "github.com/strangelove-ventures/interchaintest/v8/chain/penumbra/core/keys/v1alpha1" numv1alpha1 "github.com/strangelove-ventures/interchaintest/v8/chain/penumbra/core/num/v1alpha1" custodyv1alpha1 "github.com/strangelove-ventures/interchaintest/v8/chain/penumbra/custody/v1alpha1" @@ -30,6 +30,7 @@ import ( "google.golang.org/grpc/credentials/insecure" ) +// PenumbraClientNode represents an instance of pclientd. type PenumbraClientNode struct { log *zap.Logger @@ -51,6 +52,8 @@ type PenumbraClientNode struct { hostGRPCPort string } +// NewClientNode attempts to initialize a new instance of pclientd. +// It then attempts to create the Docker container lifecycle and the Docker volume before setting the volume owner. func NewClientNode( ctx context.Context, log *zap.Logger, @@ -88,6 +91,7 @@ func NewClientNode( if err != nil { return nil, fmt.Errorf("creating pclientd volume: %w", err) } + p.VolumeName = tv.Name if err := dockerutil.SetVolumeOwner(ctx, dockerutil.VolumeOwnerOptions{ Log: log, @@ -109,25 +113,35 @@ const ( pclientdPort = "8081/tcp" ) +// pclientdPorts is a variable of type nat.PortSet that represents the set of ports used by the pclientd service. +// Declaration: +// +// var pclientdPorts = nat.PortSet{ +// nat.Port(pclientdPort): {}, +// } +// +// Example usage: +// func (p *Penumbra var pclientdPorts = nat.PortSet{ nat.Port(pclientdPort): {}, } -// Name of the test node container +// Name of the test node container. func (p *PenumbraClientNode) Name() string { return fmt.Sprintf("pclientd-%d-%s-%s-%s", p.Index, p.KeyName, p.Chain.Config().ChainID, p.TestName) } -// the hostname of the test node container +// HostName returns the hostname of the test node container. func (p *PenumbraClientNode) HostName() string { return dockerutil.CondenseHostName(p.Name()) } -// Bind returns the home folder bind point for running the node +// Bind returns the home folder bind point for running the node. func (p *PenumbraClientNode) Bind() []string { return []string{fmt.Sprintf("%s:%s", p.VolumeName, p.HomeDir())} } +// HomeDir returns the home directory for this instance of pclientd in the Docker filesystem. func (p *PenumbraClientNode) HomeDir() string { return "/home/pclientd" } @@ -156,6 +170,13 @@ func (p *PenumbraClientNode) GetAddress(ctx context.Context) ([]byte, error) { return resp.Address.Inner, nil } +// SendFunds sends funds from the PenumbraClientNode to a specified address. +// It generates a transaction plan, gets authorization data for the transaction, +// builds and signs the transaction, and broadcasts it. +// Parameters: +// - ctx: The context of the operation. +// - amount: The amount of funds to send, including the address and denomination. +// Returns an error if any step of the process fails. func (p *PenumbraClientNode) SendFunds(ctx context.Context, amount ibc.WalletAmount) error { channel, err := grpc.Dial(p.hostGRPCPort, grpc.WithTransportCredentials(insecure.NewCredentials())) if err != nil { @@ -224,6 +245,10 @@ func (p *PenumbraClientNode) SendFunds(ctx context.Context, amount ibc.WalletAmo return nil } +// SendIBCTransfer sends an IBC transfer from the current PenumbraClientNode to a specified destination address on a specified channel. +// It dials a gRPC connection to the hostGRPCPort, and if successful, closes the connection before returning. It returns an error if dialing the gRPC connection fails. +// The function validates the address string on the current PenumbraClientNode instance. If the address string is empty, it returns an error. +// It translates the amount to a big integer and creates an `ibcv1alpha1.Ics20Withdrawal` with the amount, denom, destination address, return address, timeout height, timeout timestamp func (p *PenumbraClientNode) SendIBCTransfer( ctx context.Context, channelID string, @@ -239,7 +264,7 @@ func (p *PenumbraClientNode) SendIBCTransfer( } defer channel.Close() - // TODO may need to be more defensive than this. additionally we may want to validate the addr string + // TODO may need to be more defensive than this, additionally we may want to validate the addr string. if p.addrString == "" { return ibc.Tx{}, fmt.Errorf("address string was not cached on pclientd instance for key with name %s", p.KeyName) } @@ -330,6 +355,22 @@ func (p *PenumbraClientNode) SendIBCTransfer( }, nil } +// GetBalance retrieves the balance of a specific denom for the PenumbraClientNode. +// +// This method establishes a gRPC connection to the PenumbraClientNode using the hostGRPCPort information. +// It then creates a client for the ViewProtocolService and constructs a BalancesRequest with an AccountFilter and AssetIdFilter. +// A Balances stream response is obtained from the server. +// The balances are collected in a slice until the stream is done, or an error occurs. +// If no balances are found, an error is returned. +// Otherwise, the first balance in the slice is used to construct a math.Int value and returned. +// +// Parameters: +// - ctx: The context.Context used for the gRPC connection. +// - denom: The denomination of the asset to get the balance for. +// +// Returns: +// - math.Int: The balance of the specified denom. +// - error: An error if any occurred during the balance retrieval. func (p *PenumbraClientNode) GetBalance(ctx context.Context, denom string) (math.Int, error) { channel, err := grpc.Dial( p.hostGRPCPort, @@ -380,7 +421,9 @@ func (p *PenumbraClientNode) GetBalance(ctx context.Context, denom string) (math } // translateHiAndLo takes the high and low order bytes and decodes the two uint64 values into the single int128 value -// they represent. Since Go does not support native uint128 we make use of the big.Int type. +// they represent. +// +// Since Go does not support native uint128 we make use of the big.Int type. // see: https://github.com/penumbra-zone/penumbra/blob/4d175986f385e00638328c64d729091d45eb042a/crates/core/crypto/src/asset/amount.rs#L220-L240 func translateHiAndLo(hi, lo uint64) math.Int { hiBig := big.NewInt(0).SetUint64(hi) @@ -394,7 +437,7 @@ func translateHiAndLo(hi, lo uint64) math.Int { return math.NewIntFromBigInt(i) } -// translateBigInt converts a Cosmos SDK Int, which is a wrapper around Go's big.Int, into two uint64 values +// translateBigInt converts a Cosmos SDK Int, which is a wrapper around Go's big.Int, into two uint64 values. func translateBigInt(i math.Int) (uint64, uint64) { bz := i.BigInt().Bytes() @@ -430,8 +473,8 @@ func (p *PenumbraClientNode) GetDenomMetadata(ctx context.Context, assetId *asse } defer channel.Close() - queryClient := shielded_poolv1alpha1.NewQueryServiceClient(channel) - req := &shielded_poolv1alpha1.DenomMetadataByIdRequest{ + queryClient := shieldedpoolv1alpha1.NewQueryServiceClient(channel) + req := &shieldedpoolv1alpha1.DenomMetadataByIdRequest{ ChainId: p.Chain.Config().ChainID, AssetId: assetId, } @@ -471,6 +514,7 @@ func (p *PenumbraClientNode) Initialize(ctx context.Context, pdAddress, spendKey return p.WriteFile(ctx, buf.Bytes(), "config.toml") } +// CreateNodeContainer creates a container for the Penumbra client node. func (p *PenumbraClientNode) CreateNodeContainer(ctx context.Context) error { cmd := []string{ "pclientd", @@ -478,16 +522,18 @@ func (p *PenumbraClientNode) CreateNodeContainer(ctx context.Context) error { "start", } + // env can be used to set environment variables for this instance of pclientd to do things like set RUST_LOG=debug var env []string - env = append(env, "RUST_LOG=debug") return p.containerLifecycle.CreateContainer(ctx, p.TestName, p.NetworkID, p.Image, pclientdPorts, p.Bind(), p.HostName(), cmd, env) } +// StopContainer stops the container associated with the PenumbraClientNode. func (p *PenumbraClientNode) StopContainer(ctx context.Context) error { return p.containerLifecycle.StopContainer(ctx) } +// StartContainer starts the test node container. func (p *PenumbraClientNode) StartContainer(ctx context.Context) error { if err := p.containerLifecycle.StartContainer(ctx); err != nil { return err @@ -503,7 +549,7 @@ func (p *PenumbraClientNode) StartContainer(ctx context.Context) error { return nil } -// Exec run a container for a specific job and block until the container exits +// Exec runs a container for a specific job and blocks until the container exits. func (p *PenumbraClientNode) Exec(ctx context.Context, cmd []string, env []string) ([]byte, []byte, error) { job := dockerutil.NewImage(p.log, p.DockerClient, p.NetworkID, p.TestName, p.Image.Repository, p.Image.Version) opts := dockerutil.ContainerOptions{ @@ -511,6 +557,7 @@ func (p *PenumbraClientNode) Exec(ctx context.Context, cmd []string, env []strin Env: env, User: p.Image.UidGid, } + res := job.Run(ctx, cmd, opts) return res.Stdout, res.Stderr, res.Err } diff --git a/chain/penumbra/penumbra_client_node_test.go b/chain/penumbra/penumbra_client_node_test.go index 7111f2f92..b0fae7c2b 100644 --- a/chain/penumbra/penumbra_client_node_test.go +++ b/chain/penumbra/penumbra_client_node_test.go @@ -9,6 +9,7 @@ import ( "github.com/stretchr/testify/require" ) +// TestBigIntDecoding tests the decoding of big integers. func TestBigIntDecoding(t *testing.T) { bigInt := math.NewInt(11235813) hi, lo := translateBigInt(bigInt) @@ -23,6 +24,13 @@ func TestBigIntDecoding(t *testing.T) { require.True(t, converted.Equal(bInt)) } +// TestIbcTransferTimeout tests the function ibcTransferTimeouts +// in order to verify that it behaves correctly under different scenarios. +// Scenario 1: both timeout values equal zero - return default timeout values +// Scenario 2: options has nil timeout value - return default timeout values +// Scenario 3: both timeout values equal non-zero values - use specified timeout values +// Scenario 4: only nanoseconds equals non-zero value - use specified value for timestamp and zero for height +// Scenario 5: only height equals non-zero value - use specified value for height and zero for timestamp func TestIbcTransferTimeout(t *testing.T) { defaultHeight, defaultTimestamp := defaultTransferTimeouts() zero := uint64(0) diff --git a/chain/penumbra/penumbra_node.go b/chain/penumbra/penumbra_node.go index 9e18cfdfc..1fdebf5be 100644 --- a/chain/penumbra/penumbra_node.go +++ b/chain/penumbra/penumbra_node.go @@ -11,6 +11,8 @@ import ( "go.uber.org/zap" ) +// PenumbraNode reporesents a node in the Penumbra network which consists of one instance of Tendermint, +// an instance of pcli, and zero or more instances of pclientd. type PenumbraNode struct { TendermintNode *tendermint.TendermintNode PenumbraAppNode *PenumbraAppNode @@ -19,10 +21,10 @@ type PenumbraNode struct { addrString string } +// PenumbraNodes is a slice of pointers that point to instances of PenumbraNode in memory. type PenumbraNodes []*PenumbraNode -// NewChainNode returns a penumbra chain node with tendermint and penumbra nodes -// with docker volumes created. +// NewPenumbraNode returns a penumbra chain node with tendermint and penumbra nodes, along with docker volumes created. func NewPenumbraNode( ctx context.Context, i int, @@ -51,6 +53,8 @@ func NewPenumbraNode( }, nil } +// CreateClientNode initializes a new instance of pclientd, with the specified FullViewingKey and CustodyKey, +// before attempting to create and start pclientd in a new Docker container. func (p *PenumbraNode) CreateClientNode( ctx context.Context, log *zap.Logger, diff --git a/chain/penumbra/wallet.go b/chain/penumbra/wallet.go index 0033bfb6c..41cbc88af 100644 --- a/chain/penumbra/wallet.go +++ b/chain/penumbra/wallet.go @@ -6,6 +6,7 @@ import ( var _ ibc.Wallet = &PenumbraWallet{} +// PenumbraWallet represents a wallet for the Penumbra application. type PenumbraWallet struct { mnemonic string address []byte @@ -13,6 +14,7 @@ type PenumbraWallet struct { chainCfg ibc.ChainConfig } +// NewWallet creates a new instance of PenumbraWallet with the provided parameters func NewWallet(keyname string, address []byte, mnemonic string, chainCfg ibc.ChainConfig) *PenumbraWallet { return &PenumbraWallet{ mnemonic: mnemonic, @@ -22,25 +24,29 @@ func NewWallet(keyname string, address []byte, mnemonic string, chainCfg ibc.Cha } } +// KeyName returns the key name associated with a PenumbraWallet instance. func (w *PenumbraWallet) KeyName() string { return w.keyName } -// Get Address formatted with chain's prefix +// FormattedAddress returns the formatted address associated with a PenumbraWallet instance. func (w *PenumbraWallet) FormattedAddress() string { return string(w.address) } -// Get mnemonic, only used for relayer wallets +// Mnemonic returns the mnemonic associated with a PenumbraWallet instance. func (w *PenumbraWallet) Mnemonic() string { return w.mnemonic } -// Get Address +// Address returns the slice of bytes representing this PenumbraWallet instance's address. func (w *PenumbraWallet) Address() []byte { return w.address } +// FormattedAddressWithPrefix returns the formatted address string with a given prefix. +// The prefix is a string that will be appended to the beginning of the address. +// It takes the address stored in the PenumbraWallet instance and converts it to a string. func (w *PenumbraWallet) FormattedAddressWithPrefix(prefix string) string { return string(w.address) } diff --git a/contract/cosmwasm/compile.go b/contract/cosmwasm/compile.go index e83e72e65..710ed50bb 100644 --- a/contract/cosmwasm/compile.go +++ b/contract/cosmwasm/compile.go @@ -2,11 +2,11 @@ package cosmwasm import ( "context" - "path/filepath" "fmt" - "runtime" "io" "os" + "path/filepath" + "runtime" "github.com/docker/docker/api/types" "github.com/docker/docker/api/types/container" @@ -71,17 +71,17 @@ func compile(image string, optVersion string, repoPath string) (string, error) { }, &container.HostConfig{ Mounts: []mount.Mount{ { - Type: mount.TypeBind, + Type: mount.TypeBind, Source: repoPathFull, Target: "/code", }, { - Type: mount.TypeVolume, - Source: filepath.Base(repoPathFull)+"_cache", + Type: mount.TypeVolume, + Source: filepath.Base(repoPathFull) + "_cache", Target: cacheDir, }, { - Type: mount.TypeVolume, + Type: mount.TypeVolume, Source: "registry_cache", Target: "/usr/local/cargo/registry", }, @@ -131,4 +131,4 @@ func compile(image string, optVersion string, repoPath string) (string, error) { } return repoPathFull, nil -} \ No newline at end of file +} diff --git a/contract/cosmwasm/rust_optimizer.go b/contract/cosmwasm/rust_optimizer.go index ae5e880ff..8cb6fc5ba 100644 --- a/contract/cosmwasm/rust_optimizer.go +++ b/contract/cosmwasm/rust_optimizer.go @@ -1,26 +1,26 @@ package cosmwasm import ( - "path/filepath" "fmt" "os" + "path/filepath" "strings" ) type Contract struct { - DockerImage string - Version string - RelativePath string + DockerImage string + Version string + RelativePath string wasmBinPathChan chan string - errChan chan error + errChan chan error } // NewContract return a contract struct, populated with defaults and its relative path // relativePath is the relative path to the contract on local machine func NewContract(relativePath string) *Contract { return &Contract{ - DockerImage: "cosmwasm/rust-optimizer", - Version: "0.14.0", + DockerImage: "cosmwasm/rust-optimizer", + Version: "0.14.0", RelativePath: relativePath, } } @@ -38,7 +38,8 @@ func (c *Contract) WithVersion(version string) *Contract { } // Compile will compile the contract -// cosmwasm/rust-optimizer is the expected docker image +// +// cosmwasm/rust-optimizer is the expected docker image func (c *Contract) Compile() *Contract { c.wasmBinPathChan = make(chan string) c.errChan = make(chan error, 1) @@ -83,4 +84,4 @@ func (c *Contract) WaitForCompile() (string, error) { case contractBinary = <-c.wasmBinPathChan: } return contractBinary, nil -} \ No newline at end of file +} diff --git a/contract/cosmwasm/workspace_optimizer.go b/contract/cosmwasm/workspace_optimizer.go index b42bfbb00..c23e573cf 100644 --- a/contract/cosmwasm/workspace_optimizer.go +++ b/contract/cosmwasm/workspace_optimizer.go @@ -2,26 +2,26 @@ package cosmwasm import ( "bufio" - "path/filepath" "fmt" "os" + "path/filepath" "strings" ) type Workspace struct { - DockerImage string - Version string - RelativePath string + DockerImage string + Version string + RelativePath string wasmBinariesChan chan map[string]string - errChan chan error + errChan chan error } // NewWorkspace returns a workspace struct, populated with defaults and its relative path // relativePath is the relative path to the workspace on local machine func NewWorkspace(relativePath string) *Workspace { return &Workspace{ - DockerImage: "cosmwasm/workspace-optimizer", - Version: "0.14.0", + DockerImage: "cosmwasm/workspace-optimizer", + Version: "0.14.0", RelativePath: relativePath, } } @@ -39,7 +39,9 @@ func (w *Workspace) WithVersion(version string) *Workspace { } // Compile will compile the workspace's contracts -// cosmwasm/workspace-optimizer is the expected docker image +// +// cosmwasm/workspace-optimizer is the expected docker image +// // The workspace object is returned, call WaitForCompile() to get results func (w *Workspace) Compile() *Workspace { w.wasmBinariesChan = make(chan map[string]string) @@ -95,4 +97,4 @@ func (w *Workspace) WaitForCompile() (map[string]string, error) { case contractBinaries = <-w.wasmBinariesChan: } return contractBinaries, nil -} \ No newline at end of file +} diff --git a/relayer/hyperspace/hyperspace_commander.go b/relayer/hyperspace/hyperspace_commander.go index e98544ddf..da42d12dc 100644 --- a/relayer/hyperspace/hyperspace_commander.go +++ b/relayer/hyperspace/hyperspace_commander.go @@ -30,7 +30,7 @@ type pathConfiguration struct { // pathChainConfig holds all values that will be required when interacting with a path. type pathChainConfig struct { - chainID string + chainID string } func (hyperspaceCommander) Name() string {