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

[Docs] Readme rewrite #19

Merged
merged 11 commits into from
Jun 28, 2024
410 changes: 178 additions & 232 deletions README.md

Large diffs are not rendered by default.

71 changes: 71 additions & 0 deletions account.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
package sdk

import (
"context"

"github.com/cosmos/cosmos-sdk/codec"
cdctypes "github.com/cosmos/cosmos-sdk/codec/types"
cryptocodec "github.com/cosmos/cosmos-sdk/crypto/codec"
cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types"
"github.com/cosmos/cosmos-sdk/types"
accounttypes "github.com/cosmos/cosmos-sdk/x/auth/types"
grpc "github.com/cosmos/gogoproto/grpc"
grpcoptions "google.golang.org/grpc"
)

var queryCodec *codec.ProtoCodec

// init initializes the codec for the account module
func init() {
reg := cdctypes.NewInterfaceRegistry()
accounttypes.RegisterInterfaces(reg)
cryptocodec.RegisterInterfaces(reg)
queryCodec = codec.NewProtoCodec(reg)
}

// AccountClient is used to interact with the account module.
//
// For example, it can be used to get the public key corresponding to an address.
type AccountClient struct {
PoktNodeAccountFetcher
}

// GetPubKeyFromAddress returns the public key of the account with the given address.
// It queries the account module using the gRPC query client.
func (ac *AccountClient) GetPubKeyFromAddress(
ctx context.Context,
address string,
) (pubKey cryptotypes.PubKey, err error) {
req := &accounttypes.QueryAccountRequest{Address: address}
res, err := ac.PoktNodeAccountFetcher.Account(ctx, req)
if err != nil {
return nil, err
}

var fetchedAccount types.AccountI
if err = queryCodec.UnpackAny(res.Account, &fetchedAccount); err != nil {
return nil, err
}

return fetchedAccount.GetPubKey(), nil
}

// NewPoktNodeAccountFetcher returns the default implementation of the PoktNodeAccountFetcher interfce.

Check warning on line 53 in account.go

View workflow job for this annotation

GitHub Actions / misspell

[misspell] account.go#L53

"interfce" is a misspelling of "interface"
Raw output
./account.go:53:94: "interfce" is a misspelling of "interface"
// It connects to a POKT full node, through the account module's query client, to get account data.
func NewPoktNodeAccountFetcher(grpcConn grpc.ClientConn) PoktNodeAccountFetcher {
return accounttypes.NewQueryClient(grpcConn)
}

// PoktNodeAccountFetcher is used by the AccountClient to fetch accounts using
// poktroll request/response types.
//
// Most users can rely on the default implementation provided by NewPoktNodeAccountFetcher function.
// A custom implementation of this interface can be used to gain more granular
// control over the interactions of the AccountClient with the POKT full node.
type PoktNodeAccountFetcher interface {
Account(
context.Context,
*accounttypes.QueryAccountRequest,
...grpcoptions.CallOption,
) (*accounttypes.QueryAccountResponse, error)
}
91 changes: 83 additions & 8 deletions application.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,14 @@ package sdk

import (
"context"
"errors"
"fmt"
"slices"

"github.com/cosmos/gogoproto/grpc"
cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types"
"github.com/pokt-network/poktroll/pkg/crypto/rings"
"github.com/pokt-network/poktroll/x/application/types"
"github.com/pokt-network/ring-go"
)

// ApplicationClient is the interface to interact with the on-chain application-module.
Expand All @@ -20,16 +25,10 @@ import (
// the blockchain for the same data multiple times, but such a cache would need to be invalidated by
// listening to the relevant events such as MsgStakeApplication, MsgUnstakeApplication etc...
type ApplicationClient struct {
// TODO_TECHDEBT: Replace QueryClient with a PoktNodeAccountFetcher interface.
types.QueryClient
}

// NewApplicationClient creates a new application client with the provided gRPC connection.
func NewApplicationClient(grpcConn grpc.ClientConn) *ApplicationClient {
return &ApplicationClient{
QueryClient: types.NewQueryClient(grpcConn),
}
}

// GetAllApplications returns all applications in the network.
// TODO_TECHDEBT: Add filtering options to this method once they are supported by the on-chain module.
func (ac *ApplicationClient) GetAllApplications(
Expand Down Expand Up @@ -57,3 +56,79 @@ func (ac *ApplicationClient) GetApplication(

return res.Application, nil
}

// GetApplicationsDelegatingToGateway returns the application addresses that are
// delegating to the given gateway address.
func (ac *ApplicationClient) GetApplicationsDelegatingToGateway(
ctx context.Context,
gatewayAddress string,
sessionEndHeight uint64,
) ([]string, error) {
allApplications, err := ac.GetAllApplications(ctx)
if err != nil {
return nil, fmt.Errorf("GetApplicationsDelegatingToGateway: error getting all applications: %w", err)
}

gatewayDelegatingApplications := make([]string, 0)
for _, application := range allApplications {
// Get the gateways that are delegated to the application
// at the query height and check if the given gateway address is in the list.
gatewaysDelegatedTo := rings.GetRingAddressesAtSessionEndHeight(&application, sessionEndHeight)
if slices.Contains(gatewaysDelegatedTo, gatewayAddress) {
// The application is delegating to the given gateway address, add it to the list.
gatewayDelegatingApplications = append(gatewayDelegatingApplications, application.Address)
}
}

return gatewayDelegatingApplications, nil
}

type ApplicationRing struct {
types.Application
PublicKeyFetcher
}

// GetRing returns the ring for the application until the current session end height.
// The ring is created using the application's public key and the public keys of
// the gateways that are currently delegated from the application.
func (a ApplicationRing) GetRing(
ctx context.Context,
sessionEndHeight uint64,
) (addressRing *ring.Ring, err error) {
if a.PublicKeyFetcher == nil {
return nil, errors.New("GetRing: Public Key Fetcher not set")
}

// Get the gateway addresses that are delegated from the application at the query height.
currentGatewayAddresses := rings.GetRingAddressesAtSessionEndHeight(&a.Application, sessionEndHeight)

ringAddresses := make([]string, 0)
ringAddresses = append(ringAddresses, a.Application.Address)

// If there are no current gateway addresses, use the application address as the ring address.
if len(currentGatewayAddresses) == 0 {
ringAddresses = append(ringAddresses, a.Application.Address)
} else {
ringAddresses = append(ringAddresses, currentGatewayAddresses...)
}

ringPubKeys := make([]cryptotypes.PubKey, 0, len(ringAddresses))
for _, address := range ringAddresses {
pubKey, err := a.PublicKeyFetcher.GetPubKeyFromAddress(ctx, address)
if err != nil {
return nil, err
}
ringPubKeys = append(ringPubKeys, pubKey)
}

return rings.GetRingFromPubKeys(ringPubKeys)
}

// PublicKeyFetcher specifies an interface that allows getting the public
// key corresponding to an address.
// It is used by the ApplicationRing struct to construct the Application's Ring
// for signing relay requests.
// The AccountClient struct provides an implementation of this interface.
type PublicKeyFetcher interface {
GetPubKeyFromAddress(context.Context, string) (cryptotypes.PubKey, error)
}
17 changes: 10 additions & 7 deletions block.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,9 @@ import (
)

// TODO_IDEA: The BlockClient could leverage websockets to get notified about new blocks
// and cache the latest block height to avoid querying the blockchain for it every time.
// and cache the latest block height to avoid querying the blockchain for it every time.

// BlockClient is a concrete types used to interact with the on-chain block module.
// BlockClient is a concrete type used to interact with the on-chain block module.
// For example, it can be used to get the latest block height.
//
// For obtaining the latest height, BlockClient uses a POKT full node's status
Expand Down Expand Up @@ -42,9 +42,12 @@ func (bc *BlockClient) LatestBlockHeight(ctx context.Context) (height int64, err
// NewPoktNodeStatusFetcher returns the default implementation of the PoktNodeStatusFetcher interface.
// It connects, through a cometbft RPC HTTP client, to a POKT full node to get its status.
func NewPoktNodeStatusFetcher(queryNodeRpcUrl string) (PoktNodeStatusFetcher, error) {
// TODO_IMPROVE: drop the cosmos dependency and directly use cometbft rpchttp.New, once the latter publishes a release that includes this functionality.
// Directly using the cometbft will simplify the code by both reducing imported repos and removing the cosmos wrapper which we don't use.
// This can be done once there is a cometbft release that includes the following version: github.com/cometbft/cometbft v1.0.0-alpha.2.0.20240530055211-ae27f7eb3c08
// TODO_IMPROVE: drop the cosmos dependency and directly use cometbft rpchttp.New,
// once the latter publishes a release that includes this functionality.
// Directly using the cometbft will simplify the code by both reducing imported
// repos and removing the cosmos wrapper which we don't use.
// This can be done once there is a cometbft release that includes the following
// version: github.com/cometbft/cometbft v1.0.0-alpha.2.0.20240530055211-ae27f7eb3c08
statusFetcher, err := cosmos.NewClientFromNode(queryNodeRpcUrl)
if err != nil {
return nil, fmt.Errorf("error constructing a default POKT full node status fetcher: %w", err)
Expand All @@ -57,8 +60,8 @@ func NewPoktNodeStatusFetcher(queryNodeRpcUrl string) (PoktNodeStatusFetcher, er
// The BlokClient extracts the latest height from this status struct.
//
// Most users can rely on the default implementation provided by NewPoktNodeStatusFetcher function.
// A custom implementation of this interface can be used to gain more granular control over the interactions
// of the BlockClient with the POKT full node.
// A custom implementation of this interface can be used to gain more granular control
// over the interactions of the BlockClient with the POKT full node.
type PoktNodeStatusFetcher interface {
Status(ctx context.Context) (*ctypes.ResultStatus, error)
}
59 changes: 0 additions & 59 deletions clients/account.go

This file was deleted.

38 changes: 0 additions & 38 deletions clients/params.go

This file was deleted.

58 changes: 0 additions & 58 deletions clients/relay.go

This file was deleted.

Loading
Loading