pairing

package
v0.33.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jan 8, 2024 License: Apache-2.0 Imports: 29 Imported by: 0

README

x/pairing

Abstract

This document specifies the pairing module of Lava Protocol.

The pairing module is responsible for handling providers staking, providers freezing, calulating the providers pairing list for consumers, punishing unresponsive providers and handling providers relay payment requests.

The Pairing Engine is a sophisticated algorithmic mechanism designed to match consumers with the most appropriate service providers, considering a wide array of inputs and constraints. It upholds the network's principles of fairness, security, and quality of service, while ensuring each consumer's experience is personalized and in line with their specific requirements.

The pairing module is one of Lava's core modules and is closely connected to the subscription, dualstaking and epochstorage modules. To fully understand they all work together, please also refer to their respective READMEs.

Contents

Concepts

Providers

Providers are entities that have access to blockchains and want to monetize that access by providing services to consumers. Providers stake tokens under a geolocation and supported specifications (e.g. Ethereum JSON-RPC in U.S. East), once active they must provide service to consumers. Providers run the lava process and the desired blockchain or service (e.g. Ethereum JSON-RPC) they are providing access for.

Stake

When a provider stakes, a new stake entry is created on-chain. A stake entry is defined as follows:

type StakeEntry struct {
	Stake               Coin        // stake amount
	Address             string      // provider Lava address
	StakeAppliedBlock   uint64      // the block in which the stake is active
	Endpoints           []Endpoint  // a list of endpoints
	Geolocation         int32       // supported geolocation
	Chain               string      // chain in which the provider is staked on
	Moniker             string      // non-unique human name
	DelegateTotal       Coin        // total delegations
	DelegateLimit       Coin        // max amount of delegations the provider accepts
	DelegateCommission  uint64      // commission for delegation
}

Note, the Coin type is from Cosmos-SDK (cosmos.base.v1beta1.Coin). A provider can accept delegations to increase its effective stake, which increases its chances of being selected in the pairing process. The provider can also set a delegation limit, which determines the maximum value of delegations they can accept. This limit is in place to prevent delegators from increasing the provider's effective stake to a level where the provider is overwhelmed with more consumers than they can handle in the pairing process. For more details about delegations, refer to the dualstaking module README.

An provider's endpoint is defined as follows:

type Endpoint struct {
	IPPORT        string    // IP + port
	Geolocation   int32     // supported geolocation
	Addons        []string  // list of supported add-ons
	ApiInterfaces []string  // list of supported API interfaces
	Extensions    []string  // list of supported extensions
}

A consumer sends requests to a provider's endpoint to communicate with them. The aggregated geolocations of all the provider's endpoints should be equal to the geolocation field present in the provider's stake entry. Other than that, the Addons, ApiInterfaces and Extensions specify the "extra" features the provider supports. To get more details about those, see the spec module README.

Stake entries' storage is managed by the epochstorage module. For more details, see its README.

Unstake

A provider can unstake and retrieve their coins. When a provider unstakes, they are removed from the pairing list starting from the next epoch. After a specified number of blocks called UnstakeHoldBlocks (a parameter of the epochstorage module), the provider is eligible to receive their coins back.

Freeze

Freeze Mode enables the Provider to temporarily suspend their node's operation during maintenance to avoid bad Quality of Service (QoS). Freeze/Unfreeze is applied on the next Epoch. The Provider can initiate multiple Freeze actions with one command.

Pairing

The Pairing Engine is a core component of the Lava Network, responsible for connecting consumers with the most suitable service providers. It operates on a complex array of inputs, including the strictest policies defined at the plan, subscription, and project levels. These policies set the boundaries for service provisioning, ensuring that consumers' specific requirements are met while adhering to the network's overarching rules.

The Pairing Engine takes into account a diverse range of parameters to make informed matchmaking decisions. This includes a list of available providers, each with their unique service offerings, preferred geolocation, available addons and extensions, and additional factors. Importantly, this pairing mechanism is deterministic, and recalculates the pairing list every epoch.

Furthermore, the Pairing Engine has the ability to filter out irrelevant providers, such as those that may be frozen or jailed due to non-compliance with network rules. Additionally, it factors in the stake held by each provider, giving those with higher stakes a greater chance of being selected.

The selection process is also enriched by pseudorandomization, enhancing the security and unpredictability of the pairings. A changing seed, derived from the Lava blockchain hashes, is introduced to the selection algorithm. This seed is unique per consumer, achieved by incorporating the consumer's address as a "salt," which ensures that each consumer's pairings are distinct and less susceptible to prediction or manipulation.

Finally, providers are assigned scores based on QoS metrics, including latency, availability, and synchronization. This scoring system ensures that the Pairing Engine selects providers that best match the specific QoS requirements of the consumer's cluster. Providers with superior QoS scores receive preference in the pairing process.

Filters

When calculating the pairing list of providers for a consumer, filters are applied to exclude unwanted providers. These providers may be frozen, jailed, not supporting the required geolocation, and more. All filters are initialized according to the effective (strictest) policy of the consumer's project.

The current pairing filters are:

Filter What it does
Freeze excludes frozen providers
Add-on excludes providers not supporting required add-ons
Geolocation excludes providers not supporting required geolocations
Selected providers excludes providers that are not in the policy's selected providers allow-list

Some filters support a "mix" behavior, where the filter does not exclude all providers, but instead creates a mix of providers that pass the filter and providers that do not pass the filter.

All filters are implementing the following interface:

type Filter interface {
	Filter(ctx sdk.Context, providers []epochstoragetypes.StakeEntry, currentEpoch uint64) []bool
	InitFilter(strictestPolicy planstypes.Policy) bool // return if filter is usable (by the policy)
	IsMix() bool
}
Scores

The scoring mechanism is used to select providers during the pairing process. This mechanism is applied after the full list of providers has been filtered using the pairing filters.

The pairing scoring process involves the following steps:

  1. Collect pairing requirements and strategy from the policy.
  2. Generate pairing slots with requirements (one slot per provider).
  3. Compute the pairing score of each provider with respect to each slot.
  4. Pick a provider for each slot with a pseudo-random weighted choice.

Pairing requirements describe the policy-imposed requirements for paired providers. Those include geolocation constraints, stake amount, and expectations regarding QoS ranking of selected providers. Pairing requirements must satisfy the ScoreReq interface:

type ScoreReq interface {
	Init(policy planstypes.Policy) bool
	Score(score PairingScore) math.Uint // calculates the score of a provider for a specific score requirement
	GetName() string
	Equal(other ScoreReq) bool
	GetReqForSlot(policy planstypes.Policy, slotIdx int) ScoreReq // returns the score requirement for a slot given policy limitations
}

A pairing slot represents a single provider slot in the pairing list (The number of slots for pairing is defined by the policy). Each pairing slot holds a set of pairing requirements (a pairing slot may repeat). For example, a policy may state that the pairing list has 6 slots, and providers should be located in Asia and Europe. This can be satisfied with a pairing list that has 3 (identical) slots that require providers in Asia and 3 (identical) slots that require providers in Europe. A pairing slot is defined as follows:

type PairingSlot struct {
	Reqs  map[string]ScoreReq // example: "geoReq": geo Score req object with EU requirement
	Index int
}

The Reqs map holds pairing requirements names that point to ScoreReq object. Continuing the example from above, slot A's map can contain: "geoReq": GeoReq{geo: "EU"} and slot B's map can contain: "geoReq": GeoReq{geo: "AS"} (the map is filled according to GetReqForSlot()'s output).

A pairing score describes the suitability of a provider for a pairing slot (under a given strategy). The score depends on the slot's requirements: for example, given a slot which requires geolocation in Asia, a provider in Asia will generally get higher score than one in Europe. The score is calculated for each <provider, slot> combination.

A pairing score is defined as follows:

type PairingScore struct {
	Provider            *StakeEntry
	Score               math.Uint  // total score according to all the pairing requirements
	ScoreComponents     map[string]math.Uint  // score components by pairing requirements
	SkipForSelection    bool
	SlotFiltering       map[int]struct{} // slot indexes here are skipped
	QosExcellenceReport pairingtypes.QualityOfServiceReport
}

Finally, we calculate the score of each provider for a specific slot and select a provider using a pseudo-random weighted choice. It should be noted that a provider that best meets the policy requirements will have a higher score and therefore a greater chance of being selected. Additionally, a provider's stake is a factor in the scoring process. Thus, a provider with a large stake will also have a higher chance of being chosen. Consequently, providers with a significant stake are more likely to be selected. However, the score mechanism also encourages providers to excel in other metrics in order to attract more consumers for pairing.

Quality Of Service
Excellence QoS

The Lava Network places a strong emphasis on delivering exceptional Quality of Service (QoS) to its consumers. To ensure this, consumers actively participate in monitoring and customizing their QoS metrics. They gauge provider performance by measuring latency in provider responses relative to a benchmark, assessing data freshness in comparison to the fastest provider, and evaluating the percentage of error or timeout responses in the availability metric. These scores are diligently recorded and sent on-chain alongside the relay proofs of service, creating a transparent and accountable system.

To further enhance the integrity of the QoS scores, updates are aggregated across all consumers in a manner that safeguards against false reports. Negative reports are weighted by usage, meaning that a consumer must actively use and pay a provider to diminish their QoS score. This mechanism discourages users from artificially lowering a provider's score.

These QoS excellence metrics only affect pairings and are aggregated over time with a decay function that favors the latest data, meaning providers can improve, and those providers that their service fails will be impacted to affect fewer users. This approach ensures that the QoS system remains dynamic and responsive, benefiting providers striving to enhance their services while minimizing the impact of service failures on a broader scale.

QoS

In the Lava Network, alongside the comprehensive Quality of Service of Excellence metrics, there exists an additional metric known as Passable QoS. Unlike Excellence QoS, which offers a broad range of values, Passable QoS operates on a binary scale, either assigning a value of 0 or 1, averaged over relays. This metric simplifies the evaluation of service quality to a binary determination, indicating whether a relay meets the Passable QoS threshold, meaning it provides a level of service deemed acceptable for use.

The Passable QoS score directly influences the total payout for a specific payment; however, it's important to note that only 50% of the payout is exposed to this metric (can be changed via governance). This allocation ensures a balance between incentivizing excellent service and discouraging poor performance.

Pairing Verification

The calculation of the pairing list is deterministic and depends on the current epoch. The pseudo-random factor only applies when pairing a specific provider with a consumer. Therefore, the pairing list can be recalculated using the consumer's address, block, and chain ID.

Pairing verification is used by the provider to determine whether to offer service for a consumer request. If the provider decides to serve a consumer that fails pairing verification, it will not receive payment for the service it provided.

Unresponsiveness

Providers can get punished for being unresponsive to consumer requests. If a provider wishes to stop getting paired with consumers for any reason to avoid getting punished, it can freeze itself. Currently, the punishment for being unresponsive is freezing. In the future, providers will be jailed for this kind of behaviour.

When a consumer is getting paired with a provider, it sends requests for service. If provider A is unresponsive after a few tries, the consumer switches to another provider from its pairing list, provider B, and send requests to it. When communicatting with provider B, the consumer appends the address of provider A to its request, thus adding the current request's CU to provider A's "complainers CU" counter.

Every epoch start, the amount of complainers CU is compared with the amount of serviced CU of each provider across a few epochs back. If the complainers CU is higher, the provider is considered unresponsive and gets punished. The number of epochs back is determined by the recommendedEpochNumToCollectPayment parameter

Static Providers

Static providers are Lava chain providers that offer services to any consumer without relying on pairing. This feature allows new consumers to communicate with the Lava chain without a centralized provider. For example, when a new consumer wants to start using Lava, it needs to obtain its pairing list from a Lava node. However, since it initially does not have a list of providers to communicate with, it can use the static providers list to obtain its initial pairing list.

To clarify, a consumer cannot randomly find a Lava provider's endpoint and receive service from it because a provider will only serve consumers whose pairing with it can be verified. Therefore, the consumer must obtain the providers' pairing list from a Lava node.

Note that unstaking static providers will have their coins returned after a longer period of time compared to regular ("dynamic") providers due to their special status.

Payments

The Lava network connects blockchain data providers with consumers who need access to that data. Once a pairing is established, a consumer can send a message to the provider to request a specific blockchain query. The provider then sends a relay request to the blockchain, retrieves the required information, and forwards it to the consumer. After completing the requested service, the provider sends a relay payment transaction to the Lava network to receive payment.

Here is the workflow for Lava's payment mechanism:

  1. The provider sends a relay payment transaction, which is signed by the consumer.
  2. The reported CU (compute units) from the relay payment transaction is tracked.
  3. Upon a subscription's month expiry, all the providers' tracked CU are reviewed, and payments are sent for their accumulated services.
CU Tracking

The goal of CU tracking is to keep records of serviced CUs by the providers to a specific subscription, in order to determine the amount of payment they should receive at the end of the month of said subscription. When a relay payment transaction occurs, the number of CUs associated with each relay is counted and saved under the provider who initiated the transaction. At the end of each subscription end of month, the CU tracker is reset for all providers that serviced this subscription.

Providers Payment

Providers receive payments once a month. These payments are funded by the funds that consumers paid for their subscriptions. The amount of coins to be sent to each provider depends on the number of tracked CUs they had over the previous month. The payment is calculated using the following formula:

Payment = subscription\_price * \frac{provider\_tracked\_CU}{total\_CU\_used\_by\_subscription}

Explaining the formula, the provider receives a portion of the subscription price. This portion is calculated by dividing the amount of CU that the provider serviced for the consumer by the total amount of CU that the consumer used, which may involve multiple providers. It is important to note that the total CU and tracked CU are counted separately for each chain, such as ETH and STRK.

The rewards for providers can increase if the consumer exceeds the allotted CU for their subscription. For more detailed information, please refer to the README of the subscription module.

Additionally, it should be noted that the providers' rewards are influenced by factors such as adjustment factor, community/validators' contributions and bonus rewards. For further information, please consult the README of the rewards module.

Storage

Successful provider payments are stored on-chain. This is done to avoid double spend attacks (in which a provider tries to get paid twice for the same relay) and to track CU for the current epoch (and limit it by the policy restrictions).

Payments are stored using the following objects:

// holds all the payments of a specific epoch
type EpochPayments struct {
	Index                      string   
	ProviderPaymentStorageKeys []string 
}
// holds all the payments of a specific epoch for a specific provider
type ProviderPaymentStorage struct {
	Index                                  string   
	Epoch                                  uint64   
	UniquePaymentStorageClientProviderKeys []string  // list of payments
	ComplainersTotalCu                     uint64    // amount of complainers CU for unresponsiveness
}
// holds a payment for a specific provider in a specific epoch
type UniquePaymentStorageClientProvider struct {
	Index  string 
	Block  uint64 
	UsedCU uint64 
}

Parameters

The pairing module contains the following parameters:

Key Type Default Value
QoSWeight math.LegacyDec 0.5
EpochBlocksOverlap uint64 5
RecommendedEpochNumToCollectPayment uint64 3
QoSWeight

QoSWeight determines the weight of passable QoS score in the provider payment calculation. For example, say that a provider has a lower QoS than the passable QoS, the QoS weight determines how much of the provider's payment will be deducted from not passing the minimum QoS (QoS weight = 40% --> 40% of the provider's payment is deducted).

EpochBlocksOverlap

EpochBlocksOverlap is the number of blocks a consumer waits before interacting with a provider from a new pairing list to let providers that are behind the latest block to catch up with the chain.

RecommendedEpochNumToCollectPayment

RecommendedEpochNumToCollectPayment is the recommended max number of epochs for providers to claim payments. It's also used for determining unresponsiveness.

Queries

The pairing module supports the following queries:

Query Arguments What it does
account-info address (string) detailed summary of a Lava account
effective-policy chain-id (string), project developer/index (string) shows a project's effective policy
get-pairing chain-id (string), consumer (string) shows a consumer's providers pairing list
list-epoch-payments none show all epochPayment objects
list-provider-payment-storage none show all providerPaymentStorage objects
list-unique-payment-storage-client-provider none show all uniquePaymentStorageClientProvider objects
provider-monthly-payout provider (string) show the current monthly payout for a specific provider
providers chain-id (string) show all the providers staked on a specific chain
sdk-pairing none query used by Lava-SDK to get all the required pairing info
show-epoch-payments index (string) show an epochPayment object by index
show-provider-payment-storage index (string) show a providerPaymentStorage object by index
show-unique-payment-storage-client-provider index (string) show an uniquePaymentStorageClientProvider object by index
static-providers-list chain-id (string) show the list of static providers for a specific chain
subscription-monthly-payout consumer (string) show the current monthly payout for a specific consumer
user-entry consumer (string), chain-id (string), block (uint64) show the remaining allowed CU for the current epoch for a consumer
verify-pairing chain-id (string), consumer (string), provider (string), block (uint64) verify the provider was in the consumer's pairing list on a specific block
params none shows the module's parameters

For more details on payment storage objects (epochPayment, providerPaymentStorage, uniquePaymentStorageClientProvider), see the EpochStorage module's README.

Transactions

All the transactions below require setting the --from flag and gas related flags (other required flags of specific commands will be shown in the TX arguments). Also, state changes from these transactions are applied at different times, depending on the transaction. Some changes take effect immediately, while others may have a delay before they are applied.

The pairing module supports the following transactions:

Transaction Arguments What it does
bulk-stake-provider chain-ids ([]string), amount (Coin), endpoints ([]Endpoint), geolocation (int32), {repeat args for another bulk}, validator (string, optional), --provider-moniker (string) stake provider in multiple chains with multiple endpoints with one command
freeze chain-ids ([]string) freeze a provider in multiple chains
modify-provider chain-id (string) modify a provider's stake entry (use the TX optional flags)
relay-payment chain-id (string) automatically generated TX used by a provider to request payment for their service
simulate-relay-payment consumer-key (string), chainId (string) simulate a relay payment TX
stake-provider chain-id (string), amount (Coin), endpoints ([]Endpoint), geolocation (int32), validator (string, optional), --provider-moniker (string) stake a provider in a chain with multiple endpoints
unfreeze chain-ids ([]string) unfreeze a provider in multiple chains
unstake-provider chain-ids ([]string), validator (string, optional) unstake a provider from multiple chains

Note, the Coin type is from Cosmos-SDK (cosmos.base.v1beta1.Coin). From the CLI, use 100ulava to assign a Coin argument. The Endpoint type defines a provider endpoint. From the CLI, use "my-provider-grpc-addr.com:9090,1" for one endpoint (includes the endpoint's URL+port and the endpoint's geolocation). When it comes to staking-related transactions, the geolocation argument should encompass the geolocations of all the endpoints combined.

Proposals

The pairing module supports the provider unstake proposal, which is designed to address malicious providers and compel them to unstake from the chain.

To send the proposal, use the following commands:

lavad tx gov submit-legacy-proposal unstake <proposal_json_1>,<proposal_json_2> --from alice <gas-flags>
lavad tx gov vote <latest_proposal_id> yes --from alice <gas-flags>

A valid unstake JSON proposal format:

{
    "proposal": {
        "title": "Unstake proposal",
        "description": "A proposal for unstaking providers",
        "providers_info": [
            {
                "provider": "lava@1q0q74n8hgme7hrmhrvjgfq2dzhchjulqr526y7",
                "chain_id": "*"
            },
            {
                "provider": "lava@1rx5g4j65ztzu29pv5wrn4s2rcjkhkhcxztplv9",
                "chain_id": "ETH1"
            }
        ]
    },
    "deposit": "10000000ulava"
}

Events

The pairing module has the following events:

Event When it happens
stake_new_provider a successful provider stake
stake_update_provider a successful provider stake entry modification
provider_unstake_commit a successful provider unstake (before receiving the funds back)
relay_payment a successful relay payment
provider_reported a successful provider report for unresponsiveness
provider_latest_block_report a successful report of latest block of a provider
rejected_cu a successful relay payment that rejected some of the relays
unstake_gov_proposal a successful unstake gov proposal

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func ExportGenesis

func ExportGenesis(ctx sdk.Context, k keeper.Keeper) *types.GenesisState

ExportGenesis returns the capability module's exported genesis.

func InitGenesis

func InitGenesis(ctx sdk.Context, k keeper.Keeper, genState types.GenesisState)

InitGenesis initializes the capability module's state from a provided genesis state.

func NewHandler

func NewHandler(k keeper.Keeper) sdk.Handler

NewHandler ...

func NewPairingProposalsHandler

func NewPairingProposalsHandler(k keeper.Keeper) v1beta1.Handler

NewPlanProposalsHandler creates a new governance Handler for a Plan

Types

type AppModule

type AppModule struct {
	AppModuleBasic
	// contains filtered or unexported fields
}

AppModule implements the AppModule interface for the capability module.

func NewAppModule

func NewAppModule(
	cdc codec.Codec,
	keeper keeper.Keeper,
	accountKeeper types.AccountKeeper,
	bankKeeper types.BankKeeper,
) AppModule

func (AppModule) BeginBlock

func (am AppModule) BeginBlock(ctx sdk.Context, _ abci.RequestBeginBlock)

BeginBlock executes all ABCI BeginBlock logic respective to the capability module.

func (AppModule) ConsensusVersion

func (AppModule) ConsensusVersion() uint64

ConsensusVersion implements ConsensusVersion.

func (AppModule) EndBlock

EndBlock executes all ABCI EndBlock logic respective to the capability module. It returns no validator updates.

func (AppModule) ExportGenesis

func (am AppModule) ExportGenesis(ctx sdk.Context, cdc codec.JSONCodec) json.RawMessage

ExportGenesis returns the capability module's exported genesis state as raw JSON bytes.

func (AppModule) GenerateGenesisState

func (AppModule) GenerateGenesisState(simState *module.SimulationState)

GenerateGenesisState creates a randomized GenState of the module

func (AppModule) InitGenesis

func (am AppModule) InitGenesis(ctx sdk.Context, cdc codec.JSONCodec, gs json.RawMessage) []abci.ValidatorUpdate

InitGenesis performs the capability module's genesis initialization It returns no validator updates.

func (AppModule) Name

func (am AppModule) Name() string

Name returns the capability module's name.

func (AppModule) ProposalContents

ProposalContents doesn't return any content functions for governance proposals

func (AppModule) ProposalMsgs

TODO: Add weighted proposals

func (AppModule) RegisterInvariants

func (am AppModule) RegisterInvariants(_ sdk.InvariantRegistry)

RegisterInvariants registers the capability module's invariants.

func (AppModule) RegisterServices

func (am AppModule) RegisterServices(cfg module.Configurator)

RegisterServices registers a GRPC query service to respond to the module-specific GRPC queries.

func (AppModule) RegisterStoreDecoder

func (am AppModule) RegisterStoreDecoder(_ sdk.StoreDecoderRegistry)

RegisterStoreDecoder registers a decoder

func (AppModule) WeightedOperations

func (am AppModule) WeightedOperations(simState module.SimulationState) []simtypes.WeightedOperation

WeightedOperations returns the all the gov module operations with their respective weights.

type AppModuleBasic

type AppModuleBasic struct {
	// contains filtered or unexported fields
}

AppModuleBasic implements the AppModuleBasic interface for the capability module.

func NewAppModuleBasic

func NewAppModuleBasic(cdc codec.BinaryCodec) AppModuleBasic

func (AppModuleBasic) DefaultGenesis

func (AppModuleBasic) DefaultGenesis(cdc codec.JSONCodec) json.RawMessage

DefaultGenesis returns the capability module's default genesis state.

func (AppModuleBasic) GetQueryCmd

func (AppModuleBasic) GetQueryCmd() *cobra.Command

GetQueryCmd returns the capability module's root query command.

func (AppModuleBasic) GetTxCmd

func (a AppModuleBasic) GetTxCmd() *cobra.Command

GetTxCmd returns the capability module's root tx command.

func (AppModuleBasic) Name

func (AppModuleBasic) Name() string

Name returns the capability module's name.

func (AppModuleBasic) RegisterCodec

func (AppModuleBasic) RegisterCodec(cdc *codec.LegacyAmino)

func (AppModuleBasic) RegisterGRPCGatewayRoutes

func (AppModuleBasic) RegisterGRPCGatewayRoutes(clientCtx client.Context, mux *runtime.ServeMux)

RegisterGRPCGatewayRoutes registers the gRPC Gateway routes for the module.

func (AppModuleBasic) RegisterInterfaces

func (a AppModuleBasic) RegisterInterfaces(reg cdctypes.InterfaceRegistry)

RegisterInterfaces registers the module's interface types

func (AppModuleBasic) RegisterLegacyAminoCodec

func (AppModuleBasic) RegisterLegacyAminoCodec(cdc *codec.LegacyAmino)

func (AppModuleBasic) RegisterRESTRoutes

func (AppModuleBasic) RegisterRESTRoutes(clientCtx client.Context, rtr *mux.Router)

RegisterRESTRoutes registers the capability module's REST service handlers.

func (AppModuleBasic) ValidateGenesis

func (AppModuleBasic) ValidateGenesis(cdc codec.JSONCodec, config client.TxEncodingConfig, bz json.RawMessage) error

ValidateGenesis performs genesis state validation for the capability module.

Directories

Path Synopsis
cli
Package types is a reverse proxy.
Package types is a reverse proxy.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL