From ebaa1b72efbb3910f9e3a3ee795d61525f9ddd3d Mon Sep 17 00:00:00 2001 From: Eduardo Diaz edjroz Date: Thu, 16 Mar 2023 17:33:51 -0400 Subject: [PATCH 1/4] add a basic typescript impl --- spec/client/ics-008-wasm-client/README.md | 108 +++++++++++----------- 1 file changed, 54 insertions(+), 54 deletions(-) diff --git a/spec/client/ics-008-wasm-client/README.md b/spec/client/ics-008-wasm-client/README.md index a9f2faa9c..b28b856f3 100644 --- a/spec/client/ics-008-wasm-client/README.md +++ b/spec/client/ics-008-wasm-client/README.md @@ -29,8 +29,7 @@ Once the IBC network broadly adopts dynamically upgradable clients, a chain may Another reason why this interface is beneficial is that it removes the dependency between Light clients and the Go programming language. Using WASM as a compilation target, light clients can be written in any programming language whose toolchain includes WASM as a compilation target. Examples of these are Go, Rust, C, and C++. -### Def -ions +### Defions Functions & terms are as defined in [ICS 2](../../core/ics-002-client-semantics). @@ -83,7 +82,7 @@ const maxGasLimit = uint64(0x7FFFFFFFFFFFFFFF) ```typescript function consumeGas(ctx: sdk.Context, gas: uint64) { - let consumed := gas / GasMultiplier + let consumed = gas / GasMultiplier ctx.GasMeter().ConsumeGas(consumed, "wasm contract") // throw OutOfGas error if we ran out (got exactly to zero due to better limit enforcing) if ctx.GasMeter().IsOutOfGas() { @@ -94,9 +93,9 @@ const maxGasLimit = uint64(0x7FFFFFFFFFFFFFFF) ### Calling a contract -```go +```typescript // Calls vm.Execute with internally constructed Gas meter and environment -func callContract(codeID []byte, ctx sdk.Context, store sdk.KVStore, msg []byte) (*types.Response, error) {} +function callContract(codeID: []byte, ctx: sdk.Context, store: sdk.KVStore, msg []byte): [*types.Response, error] {} ``` ```typescript @@ -239,8 +238,8 @@ Wasm client misbehaviour checking determines whether or not two conflicting head function checkForMisbehaviour( clientState: ClientState, misbehaviour: Misbehaviour) { - store = getStore("clients/{identifier}") - codeHandle = clientState.codeHandle() + let store = getStore("clients/{identifier}") + let codeHandle = clientState.codeHandle() assert(codeHandle.handleMisbehaviour(store, clientState, misbehaviour)) } ``` @@ -257,11 +256,11 @@ function upgradeClientState( newClientState: ClientState, height: Height, proof: CommitmentPrefix) { - codeHandle = clientState.codeHandle() + let codeHandle = clientState.codeHandle() assert(codeHandle.verifyNewClientState(clientState, newClientState, height, proof)) // update client state - clientState = newClientState + let clientState = newClientState set("clients/{identifier}", clientState) } ``` @@ -271,14 +270,14 @@ function upgradeClientState( Wasm client state verification functions check a Merkle proof against a previously validated commitment root. ```typescript - function () VerifyUpgradeAndUpdateState( + function VerifyUpgradeAndUpdateState( c: ClientState, - store: KVStore, - newClient: ClientState, - newConsState: ConsensusState, - proofUpgradeClient: []byte, - proofUpgradeConsState: []byte, - ) error { + store: KVStore, + newClient: ClientState, + newConsState: ConsensusState, + proofUpgradeClient: []byte, + proofUpgradeConsState: []byte, + ): error { // last height of current counterparty chain must be client's latest height let lastHeight = c.LatestHeight let err = GetConsensusState(store, cdc, lastHeight) @@ -291,21 +290,21 @@ Wasm client state verification functions check a Merkle proof against a previous function VerifyMembership( c: ClientState, - clientStore: KVStore, - height: Height, - delayTimePeriod: uint64, - delayBlockPeriod: uint64, - proof: []byte, - path: Path, - value :[]byte, - ) error { + clientStore: KVStore, + height: Height, + delayTimePeriod: uint64, + delayBlockPeriod: uint64, + proof: []byte, + path: Path, + value :[]byte, + ): error { const VerifyClientMessage = "verify_membership" - encodedData := packData(height, delayTimePeriod, delayBlockPeriod, proof, path, value, VerifyClientMessage) - _, err := callContract(c.CodeId, ctx, clientStore, encodedData) + let encodedData = packData(height, delayTimePeriod, delayBlockPeriod, proof, path, value, VerifyClientMessage) + let [ _, err ] = callContract(c.CodeId, ctx, clientStore, encodedData) return err } - func (c ClientState) VerifyNonMembership( + func VerifyNonMembership( ctx sdk.Context, clientStore sdk.KVStore, cdc codec.BinaryCodec, @@ -314,11 +313,11 @@ Wasm client state verification functions check a Merkle proof against a previous delayBlockPeriod uint64, proof []byte, path []byte, -) error { - const VerifyClientMessage = "verify_non_membership" - encodedData := packData(height, delayTimePeriod, delayBlockPeriod, proof, path, value, VerifyClientMessage) - _, err := callContract(c.CodeId, ctx, clientStore, encodedData) - return err +): error { + const VerifyClientMessage = "verify_non_membership" + let encodedData = packData(height, delayTimePeriod, delayBlockPeriod, proof, path, value, VerifyClientMessage) + let [_, err] = callContract(c.CodeId, ctx, clientStore, encodedData) + return err } func (c ClientState) VerifyClientMessage(ctx sdk.Context, cdc codec.BinaryCodec, clientStore sdk.KVStore, clientMsg exported.ClientMessage) error { @@ -327,30 +326,33 @@ func (c ClientState) VerifyClientMessage(ctx sdk.Context, cdc codec.BinaryCodec, return err } -func (c ClientState) CheckForMisbehaviour(ctx sdk.Context, cdc codec.BinaryCodec, clientStore sdk.KVStore, msg exported.ClientMessage) bool { - wasmMisbehaviour, ok := msg.(*Misbehaviour) +func CheckForMisbehaviour(ctx: sdk.Context, cdc: codec.BinaryCodec, clientStore: sdk.KVStore, msg: exported.ClientMessage): bool { + let [ wasmMisbehaviour, ok ] = msg.(*Misbehaviour) if !ok { return false } - encodedData := packData(wasmMisbehaviour) - _, err := call[contractResult](encodedData, &c, ctx, clientStore) - if err != nil { - panic(err) - } + encodedData := packData(wasmMisbehaviour) + try { + call[contractResult](encodedData, &c, ctx, clientStore) + } catch(err) { + throw(err) + } return true } // UpdateStateOnMisbehaviour should perform appropriate state changes on a client state given that misbehaviour has been detected and verified -func (c ClientState) UpdateStateOnMisbehaviour(ctx sdk.Context, cdc codec.BinaryCodec, clientStore sdk.KVStore, clientMsg exported.ClientMessage) { +func (c ClientState) UpdateStateOnMisbehaviour(ctx: sdk.Context, cdc: codec.BinaryCodec, clientStore: sdk.KVStore, clientMsg: exported.ClientMessage) { encodedData := packData(clientMsg, c) - _, err = callContract(c.CodeId, ctx, clientStore, encodedData) - if err != nil { - panic(err) - } + try{ + callContract(c.CodeId, ctx, clientStore, encodedData) + } catch (err) { + throw err + } + } -func (c ClientState) UpdateState(ctx sdk.Context, cdc codec.BinaryCodec, clientStore sdk.KVStore, clientMsg exported.ClientMessage) []exported.Height { +func (c ClientState) UpdateState(ctx: sdk.Context, cdc: codec.BinaryCodec, clientStore: sdk.KVStore, clientMsg: exported.ClientMessage): []exported.Height { clientMsgConcrete := make(map[string]interface{}) switch clientMsg := clientMsg.(type) { case *Header: @@ -359,16 +361,15 @@ func (c ClientState) UpdateState(ctx sdk.Context, cdc codec.BinaryCodec, clientS clientMsgConcrete["misbehaviour"] = clientMsg } encodedData := packData(clientMsgConcrete) - output, err := call[contractResult]( encodedData := packData(clientMsgConcrete) -, &c, ctx, clientStore) - if err != nil { - panic(err) - } - if err := json.Unmarshal(output.Data, &c); err != nil { - panic(sdkerrors.Wrapf(ErrUnableToUnmarshalPayload, fmt.Sprintf("underlying error: %s", err.Error()))) + try { + output, err := call[contractResult](encodedData := packData(clientMsgConcrete), &c, ctx, clientStore) + json.Unmarshal(output.Data, c) + } catch (err) { + throw err + } } -func CheckSubstituteAndUpdateState(ctx sdk.Context, cdc codec.BinaryCodec, subjectClientStore, substituteClientStore sdk.KVStore, substituteClient ClientState) error { +func CheckSubstituteAndUpdateState(ctx: sdk.Context, cdc: codec.BinaryCodec, subjectClientStore: sdk.KVStore, substituteClientStore: sdk.KVStore, substituteClient: ClientState) error { var ( SubjectPrefix = []byte("subject/") SubstitutePrefix = []byte("substitute/") @@ -393,7 +394,6 @@ func CheckSubstituteAndUpdateState(ctx sdk.Context, cdc codec.BinaryCodec, subje return nil } - SetClientState(clientStore, cdc, &c) return []exported.Height{c.LatestHeight} } From 647bef53729e294a4af418fe233d20bb7e0a0ea0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Eduardo=20D=C3=ADaz?= Date: Sun, 19 Mar 2023 18:34:01 -0400 Subject: [PATCH 2/4] Update spec/client/ics-008-wasm-client/README.md MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Eduardo Díaz --- spec/client/ics-008-wasm-client/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/client/ics-008-wasm-client/README.md b/spec/client/ics-008-wasm-client/README.md index b28b856f3..76ca64166 100644 --- a/spec/client/ics-008-wasm-client/README.md +++ b/spec/client/ics-008-wasm-client/README.md @@ -327,7 +327,7 @@ func (c ClientState) VerifyClientMessage(ctx sdk.Context, cdc codec.BinaryCodec, } func CheckForMisbehaviour(ctx: sdk.Context, cdc: codec.BinaryCodec, clientStore: sdk.KVStore, msg: exported.ClientMessage): bool { - let [ wasmMisbehaviour, ok ] = msg.(*Misbehaviour) + let { wasmMisbehaviour, ok } = msg.Misbehaviour if !ok { return false } From 01eb856ffa8d4db3ae6f20526a7d58e48913aaa2 Mon Sep 17 00:00:00 2001 From: Eduardo Diaz edjroz Date: Sun, 19 Mar 2023 18:37:19 -0400 Subject: [PATCH 3/4] fix deconstruct syntax --- spec/client/ics-008-wasm-client/README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/spec/client/ics-008-wasm-client/README.md b/spec/client/ics-008-wasm-client/README.md index 76ca64166..ac0fcfd3e 100644 --- a/spec/client/ics-008-wasm-client/README.md +++ b/spec/client/ics-008-wasm-client/README.md @@ -104,7 +104,7 @@ function (codeID: cosmwasm.Checksum, ctx: sdk.Context, store: sdk.KVStore, env: Sender: "", Funds: nil, }; - let [resp, gasUsed, err] = executeVM(codeID, env, msgInfo, msg, store, gasMeter, gasMeter.Limit()); + let {resp, gasUsed, err} = executeVM(codeID, env, msgInfo, msg, store, gasMeter, gasMeter.Limit()); consumeGas(ctx, gasUsed); return [resp, err] } @@ -300,7 +300,7 @@ Wasm client state verification functions check a Merkle proof against a previous ): error { const VerifyClientMessage = "verify_membership" let encodedData = packData(height, delayTimePeriod, delayBlockPeriod, proof, path, value, VerifyClientMessage) - let [ _, err ] = callContract(c.CodeId, ctx, clientStore, encodedData) + let { _, err } = callContract(c.CodeId, ctx, clientStore, encodedData) return err } @@ -316,7 +316,7 @@ Wasm client state verification functions check a Merkle proof against a previous ): error { const VerifyClientMessage = "verify_non_membership" let encodedData = packData(height, delayTimePeriod, delayBlockPeriod, proof, path, value, VerifyClientMessage) - let [_, err] = callContract(c.CodeId, ctx, clientStore, encodedData) + let {_, err} = callContract(c.CodeId, ctx, clientStore, encodedData) return err } From 729f0e213a50059666c659f0d018e73680be6d39 Mon Sep 17 00:00:00 2001 From: Eduardo Diaz edjroz Date: Sun, 19 Mar 2023 18:55:34 -0400 Subject: [PATCH 4/4] fix formatting --- spec/client/ics-008-wasm-client/README.md | 106 +++++++++++----------- 1 file changed, 53 insertions(+), 53 deletions(-) diff --git a/spec/client/ics-008-wasm-client/README.md b/spec/client/ics-008-wasm-client/README.md index ac0fcfd3e..ad6a22b2d 100644 --- a/spec/client/ics-008-wasm-client/README.md +++ b/spec/client/ics-008-wasm-client/README.md @@ -271,62 +271,62 @@ Wasm client state verification functions check a Merkle proof against a previous ```typescript function VerifyUpgradeAndUpdateState( - c: ClientState, - store: KVStore, - newClient: ClientState, - newConsState: ConsensusState, - proofUpgradeClient: []byte, - proofUpgradeConsState: []byte, + c: ClientState, + store: KVStore, + newClient: ClientState, + newConsState: ConsensusState, + proofUpgradeClient: []byte, + proofUpgradeConsState: []byte, ): error { - // last height of current counterparty chain must be client's latest height - let lastHeight = c.LatestHeight - let err = GetConsensusState(store, cdc, lastHeight) - assert(err == null) - let encodedData = packData(newClient, proofUpgradeClient, proofUpgradeConsState) - let err = callContract(c.CodeId, ctx, store, encodedData) - assert(err == null) - return null + // last height of current counterparty chain must be client's latest height + let lastHeight = c.LatestHeight + let err = GetConsensusState(store, cdc, lastHeight) + assert(err == null) + let encodedData = packData(newClient, proofUpgradeClient, proofUpgradeConsState) + let err = callContract(c.CodeId, ctx, store, encodedData) + assert(err == null) + return null } function VerifyMembership( - c: ClientState, - clientStore: KVStore, - height: Height, - delayTimePeriod: uint64, - delayBlockPeriod: uint64, - proof: []byte, - path: Path, - value :[]byte, + c: ClientState, + clientStore: KVStore, + height: Height, + delayTimePeriod: uint64, + delayBlockPeriod: uint64, + proof: []byte, + path: Path, + value :[]byte, ): error { - const VerifyClientMessage = "verify_membership" - let encodedData = packData(height, delayTimePeriod, delayBlockPeriod, proof, path, value, VerifyClientMessage) - let { _, err } = callContract(c.CodeId, ctx, clientStore, encodedData) - return err + const VerifyClientMessage = "verify_membership" + let encodedData = packData(height, delayTimePeriod, delayBlockPeriod, proof, path, value, VerifyClientMessage) + let { _, err } = callContract(c.CodeId, ctx, clientStore, encodedData) + return err } - func VerifyNonMembership( - ctx sdk.Context, - clientStore sdk.KVStore, - cdc codec.BinaryCodec, - height exported.Height, - delayTimePeriod uint64, - delayBlockPeriod uint64, - proof []byte, - path []byte, -): error { - const VerifyClientMessage = "verify_non_membership" - let encodedData = packData(height, delayTimePeriod, delayBlockPeriod, proof, path, value, VerifyClientMessage) - let {_, err} = callContract(c.CodeId, ctx, clientStore, encodedData) - return err + function VerifyNonMembership( + ctx: sdk.Context, + clientStore: sdk.KVStore, + cdc: codec.BinaryCodec, + height: exported.Height, + delayTimePeriod: int, + delayBlockPeriod: int, + proof: []byte, + path: []byte, + ): error { + const VerifyClientMessage = "verify_non_membership" + let encodedData = packData(height, delayTimePeriod, delayBlockPeriod, proof, path, value, VerifyClientMessage) + let {_, err} = callContract(c.CodeId, ctx, clientStore, encodedData) + return err } -func (c ClientState) VerifyClientMessage(ctx sdk.Context, cdc codec.BinaryCodec, clientStore sdk.KVStore, clientMsg exported.ClientMessage) error { - encodedData := packData(clientMsg, c) +function VerifyClientMessage(ctx: sdk.Context, cdc: codec.BinaryCodec, clientStore: sdk.KVStore, clientMsg: exported.ClientMessage): error { + encodedData := packData(clientMsg, c) _, err := call[contractResult](encodedData, &c, ctx, clientStore) return err } -func CheckForMisbehaviour(ctx: sdk.Context, cdc: codec.BinaryCodec, clientStore: sdk.KVStore, msg: exported.ClientMessage): bool { +function CheckForMisbehaviour(ctx: sdk.Context, cdc: codec.BinaryCodec, clientStore: sdk.KVStore, msg: exported.ClientMessage): bool { let { wasmMisbehaviour, ok } = msg.Misbehaviour if !ok { return false @@ -342,7 +342,7 @@ func CheckForMisbehaviour(ctx: sdk.Context, cdc: codec.BinaryCodec, clientStore } // UpdateStateOnMisbehaviour should perform appropriate state changes on a client state given that misbehaviour has been detected and verified -func (c ClientState) UpdateStateOnMisbehaviour(ctx: sdk.Context, cdc: codec.BinaryCodec, clientStore: sdk.KVStore, clientMsg: exported.ClientMessage) { +function UpdateStateOnMisbehaviour(ctx: sdk.Context, cdc: codec.BinaryCodec, clientStore: sdk.KVStore, clientMsg: exported.ClientMessage) { encodedData := packData(clientMsg, c) try{ callContract(c.CodeId, ctx, clientStore, encodedData) @@ -352,7 +352,7 @@ func (c ClientState) UpdateStateOnMisbehaviour(ctx: sdk.Context, cdc: codec.Bina } -func (c ClientState) UpdateState(ctx: sdk.Context, cdc: codec.BinaryCodec, clientStore: sdk.KVStore, clientMsg: exported.ClientMessage): []exported.Height { +function UpdateState(ctx: sdk.Context, cdc: codec.BinaryCodec, clientStore: sdk.KVStore, clientMsg: exported.ClientMessage): []exported.Height { clientMsgConcrete := make(map[string]interface{}) switch clientMsg := clientMsg.(type) { case *Header: @@ -369,7 +369,7 @@ func (c ClientState) UpdateState(ctx: sdk.Context, cdc: codec.BinaryCodec, clien } } -func CheckSubstituteAndUpdateState(ctx: sdk.Context, cdc: codec.BinaryCodec, subjectClientStore: sdk.KVStore, substituteClientStore: sdk.KVStore, substituteClient: ClientState) error { +function CheckSubstituteAndUpdateState(ctx: sdk.Context, cdc: codec.BinaryCodec, subjectClientStore: sdk.KVStore, substituteClientStore: sdk.KVStore, substituteClient: ClientState): error { var ( SubjectPrefix = []byte("subject/") SubstitutePrefix = []byte("substitute/") @@ -408,8 +408,8 @@ pointers to `KVStore`s if needed), pointing to a code hash, and a `sdk.GasMeter` for gas usage during the execution of the function. -```go -func (c *CodeHandle) isValidClientState(ctx sdk.Context, clientState ClientState, height u64) (*types.Response, error) { +```typescript +function isValidClientState(ctx: sdk.Context, clientState: ClientState, height: int): {*types.Response, error} { clientStateData := json.Serialize(clientState) packedData := pack(clientStateData, height) // VM specific code to call Wasm contract @@ -418,8 +418,8 @@ func (c *CodeHandle) isValidClientState(ctx sdk.Context, clientState ClientState } ``` -```go -func callContract(codeID []byte, ctx sdk.Context, store sdk.KVStore, msg []byte) (*types.Response, error) { +```typescript +function callContract(codeID: []byte, ctx: sdk.Context, store: sdk.KVStore, msg: []byte): {*types.Response, error} { gasMeter := ctx.GasMeter() chainID := ctx.BlockHeader().ChainID height := ctx.BlockHeader().Height @@ -446,15 +446,15 @@ func callContract(codeID []byte, ctx sdk.Context, store sdk.KVStore, msg []byte) } ``` -```go -func callContractWithEnvAndMeter(codeID cosmwasm.Checksum, ctx sdk.Context, store sdk.KVStore, env types.Env, gasMeter sdk.GasMeter, msg []byte) (*types.Response, error) { +```typescript +function callContractWithEnvAndMeter(codeID: cosmwasm.Checksum, ctx: sdk.Context, store: sdk.KVStore, env: types.Env, gasMeter: sdk.GasMeter, msg: []byte): {*types.Response, error} { msgInfo := types.MessageInfo{} desercost := types.UFraction{Numerator: 1, Denominator: 1} resp, gasUsed, err := WasmVM.Execute(codeID, env, msgInfo, msg, store, cosmwasm.GoAPI{}, nil, gasMeter, gasMeter.Limit(), desercost) if &ctx != nil { consumeGas(ctx, gasUsed) } - return resp, err + return {resp, err} } ```