-
Notifications
You must be signed in to change notification settings - Fork 33
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[IBC] Add ICS-02 Client Interfaces (#932)
- Loading branch information
Showing
7 changed files
with
462 additions
and
177 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
syntax = "proto3"; | ||
|
||
package core; | ||
|
||
option go_package = "github.com/pokt-network/pocket/ibc/client/light_client/types"; | ||
|
||
import "google/protobuf/timestamp.proto"; | ||
import "google/protobuf/duration.proto"; | ||
import "proofs.proto"; | ||
import "wasm.proto"; | ||
import "block.proto"; | ||
|
||
// PocketConsensusState defines the ibc client consensus state for Pocket | ||
message PocketConsensusState { | ||
google.protobuf.Timestamp timestamp = 1; // unix nano timestamp of the block | ||
string state_hash = 2; // hex encoded root state tree hash | ||
map<string, string> state_tree_hashes = 3; // map of state tree hashes; map[TreeName]hex(TreeRootHash) | ||
string next_val_set_hash = 4; // hex encoded sha3_256 hash of the next validator set | ||
} | ||
|
||
// PocketClientState defines the ibc client state for Pocket | ||
message PocketClientState { | ||
string network_id = 1; // network identifier string | ||
Fraction trust_level = 2; // fraction of the validator set that is required to sign off on new blocks | ||
google.protobuf.Duration trusting_period = 3; // the duration of the period since the LastestTimestamp where the state can be upgraded | ||
google.protobuf.Duration unbonding_period = 4; // the duration of the staking unbonding period | ||
google.protobuf.Duration max_clock_drift = 5; // the max duration a new header's time can be in the future | ||
Height latest_height = 6; // the latest height the client was updated to | ||
uint64 frozen_height = 7; // the height at which the client was frozen due to a misbehaviour | ||
ProofSpec proof_spec = 8; // ics23 proof spec used in verifying proofs | ||
// RESEARCH: Figure out exactly what this is for in tendermint, why it is needed and if we need it also | ||
// repeated string upgrade_path = 9; // the upgrade path for the new client state | ||
} | ||
|
||
// Fraction defines a positive rational number | ||
message Fraction { | ||
uint64 numerator = 1; | ||
uint64 denominator = 2; | ||
} | ||
|
||
// PocketHeader defines the ibc client header for the Pocket network | ||
message PocketHeader { | ||
BlockHeader block_header = 1; // pocket consensus block header | ||
ValidatorSet validator_set = 2; // new validator set for the updating client | ||
// the consensus state at trusted_height must be within the unbonding_period to correctly verify the new header | ||
Height trusted_height = 3; // height of the ConsensusState stored used to verify the new header | ||
// trusted_validators must hash to the ConsensusState.NextValSetHash as this is the last trusted validator set | ||
// hashed using SHA3Hash(validatorSetBytes) in shared/crypto/sha3.go | ||
ValidatorSet trusted_validators = 4; // already stored validator set used to verify the update | ||
} | ||
|
||
// PocketMisbehaviour defines the ibc client misbehaviour for the Pocket network | ||
// | ||
// The two conflicting headers are submitted as evidence to verify the Pocket | ||
// network has misbehaved. | ||
message PocketMisbehaviour { | ||
PocketHeader header_1 = 1; // the first header | ||
PocketHeader header_2 = 2; // the second header | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
syntax = "proto3"; | ||
|
||
package core; | ||
|
||
option go_package = "github.com/pokt-network/pocket/ibc/client/types"; | ||
|
||
// ClientState for a Wasm light client | ||
message ClientState { | ||
bytes data = 1; // opaque data passed to the wasm client | ||
bytes wasm_checksum = 2; // checksum of the wasm client code | ||
Height recent_height = 3; // latest height of the client | ||
} | ||
|
||
// ConsensusState for a Wasm light client | ||
message ConsensusState { | ||
bytes data = 1; // opaque data passed to the wasm client | ||
uint64 timestamp = 2; // unix nano timestamp of the block | ||
} | ||
|
||
// Header for a Wasm light client | ||
message Header { | ||
bytes data = 1; // opaque data passed to the wasm client | ||
Height height = 2; // height of the header | ||
} | ||
|
||
// Misbehaviour for a Wasm light client | ||
message Misbehaviour { | ||
bytes data = 1; // opaque data passed to the wasm client | ||
} | ||
|
||
// Height represents the height of a client | ||
message Height { | ||
uint64 revision_number = 1; | ||
uint64 revision_height = 2; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,212 @@ | ||
package modules | ||
|
||
//go:generate mockgen -destination=./mocks/ibc_client_module_mock.go github.com/pokt-network/pocket/shared/modules ClientManager | ||
|
||
import ( | ||
"google.golang.org/protobuf/proto" | ||
) | ||
|
||
type ClientStatus string | ||
|
||
const ( | ||
ClientManagerModuleName = "client_manager" | ||
|
||
// Client Status types | ||
ActiveStatus ClientStatus = "active" | ||
ExpiredStatus ClientStatus = "expired" | ||
FrozenStatus ClientStatus = "frozen" | ||
UnauthorizedStatus ClientStatus = "unauthorized" | ||
UnknownStatus ClientStatus = "unknown" | ||
) | ||
|
||
type ClientManagerOption func(ClientManager) | ||
|
||
type clientManagerFactory = FactoryWithOptions[ClientManager, ClientManagerOption] | ||
|
||
// ClientManager is the interface that defines the methods needed to interact with an | ||
// IBC light client it manages the different lifecycle methods for the different clients | ||
// https://github.com/cosmos/ibc/tree/main/spec/core/ics-002-client-semantics | ||
type ClientManager interface { | ||
Submodule | ||
clientManagerFactory | ||
|
||
// === Client Lifecycle Management === | ||
|
||
// CreateClient creates a new client with the given client state and initial consensus state | ||
// and initialises its unique identifier in the IBC store | ||
CreateClient(ClientState, ConsensusState) (string, error) | ||
|
||
// UpdateClient updates an existing client with the given ClientMessage, given that | ||
// the ClientMessage can be verified using the existing ClientState and ConsensusState | ||
UpdateClient(identifier string, clientMessage ClientMessage) error | ||
|
||
// UpgradeClient upgrades an existing client with the given identifier using the | ||
// ClientState and ConsenusState provided. It can only do so if the new client | ||
// was committed to by the old client at the specified upgrade height | ||
UpgradeClient( | ||
identifier string, | ||
clientState ClientState, consensusState ConsensusState, | ||
proofUpgradeClient, proofUpgradeConsState []byte, | ||
) error | ||
|
||
// === Client Queries === | ||
|
||
// GetConsensusState returns the ConsensusState at the given height for the given client | ||
GetConsensusState(identifier string, height Height) (ConsensusState, error) | ||
|
||
// GetClientState returns the ClientState for the given client | ||
GetClientState(identifier string) (ClientState, error) | ||
|
||
// GetHostConsensusState returns the ConsensusState at the given height for the host chain | ||
GetHostConsensusState(height Height) (ConsensusState, error) | ||
|
||
// GetHostClientState returns the ClientState at the provided height for the host chain | ||
GetHostClientState(height Height) (ClientState, error) | ||
|
||
// GetCurrentHeight returns the current IBC client height of the network | ||
GetCurrentHeight() (Height, error) | ||
|
||
// VerifyHostClientState verifies the client state for a client running on a | ||
// counterparty chain is valid, checking against the current host client state | ||
VerifyHostClientState(ClientState) error | ||
} | ||
|
||
// ClientState is an interface that defines the methods required by a clients | ||
// implementation of their own client state object | ||
// | ||
// ClientState is an opaque data structure defined by a client type. It may keep | ||
// arbitrary internal state to track verified roots and past misbehaviours. | ||
type ClientState interface { | ||
proto.Message | ||
|
||
GetData() []byte | ||
GetWasmChecksum() []byte | ||
ClientType() string | ||
GetLatestHeight() Height | ||
Validate() error | ||
|
||
// Status returns the status of the client. Only Active clients are allowed | ||
// to process packets. | ||
Status(clientStore ProvableStore) ClientStatus | ||
|
||
// GetTimestampAtHeight must return the timestamp for the consensus state | ||
// associated with the provided height. | ||
GetTimestampAtHeight(clientStore ProvableStore, height Height) (uint64, error) | ||
|
||
// Initialise is called upon client creation, it allows the client to perform | ||
// validation on the initial consensus state and set the client state, | ||
// consensus state and any client-specific metadata necessary for correct | ||
// light client operation in the provided client store. | ||
Initialise(clientStore ProvableStore, consensusState ConsensusState) error | ||
|
||
// VerifyMembership is a generic proof verification method which verifies a | ||
// proof of the existence of a value at a given CommitmentPath at the | ||
// specified height. The path is expected to be the full CommitmentPath | ||
VerifyMembership( | ||
clientStore ProvableStore, | ||
height Height, | ||
delayTimePeriod, delayBlockPeriod uint64, | ||
proof, path, value []byte, | ||
) error | ||
|
||
// VerifyNonMembership is a generic proof verification method which verifies | ||
// the absence of a given CommitmentPath at a specified height. The path is | ||
// expected to be the full CommitmentPath | ||
VerifyNonMembership( | ||
clientStore ProvableStore, | ||
height Height, | ||
delayTimePeriod, delayBlockPeriod uint64, | ||
proof, path []byte, | ||
) error | ||
|
||
// VerifyClientMessage verifies a ClientMessage. A ClientMessage could be a | ||
// Header, Misbehaviour, or batch update. It must handle each type of | ||
// ClientMessage appropriately. Calls to CheckForMisbehaviour, UpdateState, | ||
// and UpdateStateOnMisbehaviour will assume that the content of the | ||
// ClientMessage has been verified and can be trusted. An error should be | ||
// returned if the ClientMessage fails to verify. | ||
VerifyClientMessage(clientStore ProvableStore, clientMsg ClientMessage) error | ||
|
||
// Checks for evidence of a misbehaviour in Header or Misbehaviour type. | ||
// It assumes the ClientMessage has already been verified. | ||
CheckForMisbehaviour(clientStore ProvableStore, clientMsg ClientMessage) bool | ||
|
||
// UpdateStateOnMisbehaviour should perform appropriate state changes on a | ||
// client state given that misbehaviour has been detected and verified | ||
UpdateStateOnMisbehaviour(clientStore ProvableStore, clientMsg ClientMessage) error | ||
|
||
// UpdateState updates and stores as necessary any associated information | ||
// for an IBC client, such as the ClientState and corresponding ConsensusState. | ||
// Upon successful update, a consensus height is returned. | ||
// It assumes the ClientMessage has already been verified. | ||
UpdateState(clientStore ProvableStore, clientMsg ClientMessage) (Height, error) | ||
|
||
// Upgrade functions | ||
// NOTE: proof heights are not included as upgrade to a new revision is expected to pass only on the last | ||
// height committed by the current revision. Clients are responsible for ensuring that the planned last | ||
// height of the current revision is somehow encoded in the proof verification process. | ||
// This is to ensure that no premature upgrades occur, since upgrade plans committed to by the counterparty | ||
// may be cancelled or modified before the last planned height. | ||
// If the upgrade is verified, the upgraded client and consensus states must be set in the client store. | ||
VerifyUpgradeAndUpdateState( | ||
clientStore ProvableStore, | ||
newClient ClientState, | ||
newConsState ConsensusState, | ||
proofUpgradeClient, | ||
proofUpgradeConsState []byte, | ||
) error | ||
} | ||
|
||
// ConsensusState is an interface that defines the methods required by a clients | ||
// implementation of their own consensus state object | ||
// | ||
// ConsensusState is an opaque data structure defined by a client type, used by the | ||
// validity predicate to verify new commits & state roots. Likely the structure will | ||
// contain the last commit produced by the consensus process, including signatures | ||
// and validator set metadata. | ||
type ConsensusState interface { | ||
proto.Message | ||
|
||
GetData() []byte | ||
ClientType() string | ||
GetTimestamp() uint64 | ||
ValidateBasic() error | ||
} | ||
|
||
// ClientMessage is an interface that defines the methods required by a clients | ||
// implementation of their own client message object | ||
// | ||
// A ClientMessage is an opaque data structure defined by a client type which | ||
// provides information to update the client. ClientMessages can be submitted | ||
// to an associated client to add new ConsensusState(s) and/or update the | ||
// ClientState. They likely contain a height, a proof, a commitment root, and | ||
// possibly updates to the validity predicate. | ||
type ClientMessage interface { | ||
proto.Message | ||
|
||
GetData() []byte | ||
ClientType() string | ||
ValidateBasic() error | ||
} | ||
|
||
// Height is an interface that defines the methods required by a clients | ||
// implementation of their own height object | ||
// | ||
// Heights usually have two components: revision number and revision height. | ||
type Height interface { | ||
IsZero() bool | ||
LT(Height) bool | ||
LTE(Height) bool | ||
EQ(Height) bool | ||
GT(Height) bool | ||
GTE(Height) bool | ||
Increment() Height | ||
Decrement() Height | ||
GetRevisionNumber() uint64 | ||
GetRevisionHeight() uint64 | ||
ToString() string // must define a determinstic `String()` method not the generated protobuf method | ||
} | ||
|
||
func (s ClientStatus) String() string { | ||
return string(s) | ||
} |
Oops, something went wrong.