Skip to content

Commit 2684ad4

Browse files
author
Tomasz Kulik
authored
feat: Add IBCv2 Receive packet entrypoint (#628)
1 parent 066cbd6 commit 2684ad4

File tree

16 files changed

+215
-76
lines changed

16 files changed

+215
-76
lines changed

internal/api/bindings.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -633,6 +633,18 @@ struct UnmanagedVector ibc_destination_callback(struct cache_t *cache,
633633
struct GasReport *gas_report,
634634
struct UnmanagedVector *error_msg);
635635

636+
struct UnmanagedVector ibc2_packet_receive(struct cache_t *cache,
637+
struct ByteSliceView checksum,
638+
struct ByteSliceView env,
639+
struct ByteSliceView msg,
640+
struct Db db,
641+
struct GoApi api,
642+
struct GoQuerier querier,
643+
uint64_t gas_limit,
644+
bool print_debug,
645+
struct GasReport *gas_report,
646+
struct UnmanagedVector *error_msg);
647+
636648
struct UnmanagedVector new_unmanaged_vector(bool nil, const uint8_t *ptr, uintptr_t length);
637649

638650
void destroy_unmanaged_vector(struct UnmanagedVector v);

internal/api/lib.go

Lines changed: 44 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -164,11 +164,11 @@ func AnalyzeCode(cache Cache, checksum []byte) (*types.AnalysisReport, error) {
164164
requiredCapabilities := string(copyAndDestroyUnmanagedVector(report.required_capabilities))
165165
entrypoints := string(copyAndDestroyUnmanagedVector(report.entrypoints))
166166
entrypoints_array := strings.Split(entrypoints, ",")
167-
hasEurekaEntryPoints := slices.Contains(entrypoints_array, "eu_recv_packet")
167+
hasIBC2EntryPoints := slices.Contains(entrypoints_array, "ibc2_packet_receive")
168168

169169
res := types.AnalysisReport{
170170
HasIBCEntryPoints: bool(report.has_ibc_entry_points),
171-
HasEurekaEntryPoints: hasEurekaEntryPoints,
171+
HasIBC2EntryPoints: hasIBC2EntryPoints,
172172
RequiredCapabilities: requiredCapabilities,
173173
Entrypoints: entrypoints_array,
174174
ContractMigrateVersion: optionalU64ToPtr(report.contract_migrate_version),
@@ -681,6 +681,48 @@ func IBCPacketReceive(
681681
return copyAndDestroyUnmanagedVector(res), convertGasReport(gasReport), nil
682682
}
683683

684+
func IBC2PacketReceive(
685+
cache Cache,
686+
checksum []byte,
687+
env []byte,
688+
payload []byte,
689+
gasMeter *types.GasMeter,
690+
store types.KVStore,
691+
api *types.GoAPI,
692+
querier *Querier,
693+
gasLimit uint64,
694+
printDebug bool,
695+
) ([]byte, types.GasReport, error) {
696+
cs := makeView(checksum)
697+
defer runtime.KeepAlive(checksum)
698+
e := makeView(env)
699+
defer runtime.KeepAlive(env)
700+
pa := makeView(payload)
701+
defer runtime.KeepAlive(payload)
702+
var pinner runtime.Pinner
703+
pinner.Pin(gasMeter)
704+
checkAndPinAPI(api, pinner)
705+
checkAndPinQuerier(querier, pinner)
706+
defer pinner.Unpin()
707+
708+
callID := startCall()
709+
defer endCall(callID)
710+
711+
dbState := buildDBState(store, callID)
712+
db := buildDB(&dbState, gasMeter)
713+
a := buildAPI(api)
714+
q := buildQuerier(querier)
715+
var gasReport C.GasReport
716+
errmsg := uninitializedUnmanagedVector()
717+
718+
res, err := C.ibc2_packet_receive(cache.ptr, cs, e, pa, db, a, q, cu64(gasLimit), cbool(printDebug), &gasReport, &errmsg)
719+
if err != nil && err.(syscall.Errno) != C.ErrnoValue_Success {
720+
// Depending on the nature of the error, `gasUsed` will either have a meaningful value, or just 0.
721+
return nil, convertGasReport(gasReport), errorWithMessage(err, errmsg)
722+
}
723+
return copyAndDestroyUnmanagedVector(res), convertGasReport(gasReport), nil
724+
}
725+
684726
func IBCPacketAck(
685727
cache Cache,
686728
checksum []byte,

internal/api/lib_test.go

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -596,7 +596,7 @@ func TestInstantiate(t *testing.T) {
596596
res, cost, err := Instantiate(cache, checksum, env, info, msg, &igasMeter, store, api, &querier, TESTING_GAS_LIMIT, TESTING_PRINT_DEBUG)
597597
require.NoError(t, err)
598598
requireOkResponse(t, res, 0)
599-
require.Equal(t, uint64(0xb1fe27), cost.UsedInternally)
599+
require.Equal(t, uint64(0xd35950), cost.UsedInternally)
600600

601601
var result types.ContractResult
602602
err = json.Unmarshal(res, &result)
@@ -627,7 +627,7 @@ func TestExecute(t *testing.T) {
627627
diff := time.Since(start)
628628
require.NoError(t, err)
629629
requireOkResponse(t, res, 0)
630-
require.Equal(t, uint64(0xb1fe27), cost.UsedInternally)
630+
require.Equal(t, uint64(0xd35950), cost.UsedInternally)
631631
t.Logf("Time (%d gas): %s\n", cost.UsedInternally, diff)
632632

633633
// execute with the same store
@@ -640,7 +640,7 @@ func TestExecute(t *testing.T) {
640640
res, cost, err = Execute(cache, checksum, env, info, []byte(`{"release":{}}`), &igasMeter2, store, api, &querier, TESTING_GAS_LIMIT, TESTING_PRINT_DEBUG)
641641
diff = time.Since(start)
642642
require.NoError(t, err)
643-
require.Equal(t, uint64(0x1416da5), cost.UsedInternally)
643+
require.Equal(t, uint64(0x16057d3), cost.UsedInternally)
644644
t.Logf("Time (%d gas): %s\n", cost.UsedInternally, diff)
645645

646646
// make sure it read the balance properly and we got 250 atoms
@@ -747,7 +747,7 @@ func TestExecuteCpuLoop(t *testing.T) {
747747
diff := time.Since(start)
748748
require.NoError(t, err)
749749
requireOkResponse(t, res, 0)
750-
require.Equal(t, uint64(0x79f527), cost.UsedInternally)
750+
require.Equal(t, uint64(0x895c33), cost.UsedInternally)
751751
t.Logf("Time (%d gas): %s\n", cost.UsedInternally, diff)
752752

753753
// execute a cpu loop
@@ -989,7 +989,7 @@ func TestMultipleInstances(t *testing.T) {
989989
require.NoError(t, err)
990990
requireOkResponse(t, res, 0)
991991
// we now count wasm gas charges and db writes
992-
assert.Equal(t, uint64(0xb0c2cd), cost.UsedInternally)
992+
assert.Equal(t, uint64(0xd2189c), cost.UsedInternally)
993993

994994
// instance2 controlled by mary
995995
gasMeter2 := NewMockGasMeter(TESTING_GAS_LIMIT)
@@ -1000,14 +1000,14 @@ func TestMultipleInstances(t *testing.T) {
10001000
res, cost, err = Instantiate(cache, checksum, env, info, msg, &igasMeter2, store2, api, &querier, TESTING_GAS_LIMIT, TESTING_PRINT_DEBUG)
10011001
require.NoError(t, err)
10021002
requireOkResponse(t, res, 0)
1003-
assert.Equal(t, uint64(0xb1760a), cost.UsedInternally)
1003+
assert.Equal(t, uint64(0xd2ce86), cost.UsedInternally)
10041004

10051005
// fail to execute store1 with mary
1006-
resp := exec(t, cache, checksum, "mary", store1, api, querier, 0xa7c5ce)
1006+
resp := exec(t, cache, checksum, "mary", store1, api, querier, 0xbe8534)
10071007
require.Equal(t, "Unauthorized", resp.Err)
10081008

10091009
// succeed to execute store1 with fred
1010-
resp = exec(t, cache, checksum, "fred", store1, api, querier, 0x140e8ad)
1010+
resp = exec(t, cache, checksum, "fred", store1, api, querier, 0x15fce67)
10111011
require.Equal(t, "", resp.Err)
10121012
require.Len(t, resp.Ok.Messages, 1)
10131013
attributes := resp.Ok.Attributes
@@ -1016,7 +1016,7 @@ func TestMultipleInstances(t *testing.T) {
10161016
require.Equal(t, "bob", attributes[1].Value)
10171017

10181018
// succeed to execute store2 with mary
1019-
resp = exec(t, cache, checksum, "mary", store2, api, querier, 0x1412b29)
1019+
resp = exec(t, cache, checksum, "mary", store2, api, querier, 0x160131d)
10201020
require.Equal(t, "", resp.Err)
10211021
require.Len(t, resp.Ok.Messages, 1)
10221022
attributes = resp.Ok.Attributes

internal/api/libwasmvm.x86_64.so

52.7 KB
Binary file not shown.

lib_libwasmvm.go

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -678,6 +678,40 @@ func (vm *VM) IBCDestinationCallback(
678678
return &result, gasReport.UsedInternally, nil
679679
}
680680

681+
// IBCPacketReceive is available on IBC-enabled contracts and is called when an incoming
682+
// packet is received on a channel belonging to this contract
683+
func (vm *VM) IBC2PacketReceive(
684+
checksum Checksum,
685+
env types.Env,
686+
msg types.IBC2PacketReceiveMsg,
687+
store KVStore,
688+
goapi GoAPI,
689+
querier Querier,
690+
gasMeter GasMeter,
691+
gasLimit uint64,
692+
deserCost types.UFraction,
693+
) (*types.IBCReceiveResult, uint64, error) {
694+
envBin, err := json.Marshal(env)
695+
if err != nil {
696+
return nil, 0, err
697+
}
698+
msgBin, err := json.Marshal(msg)
699+
if err != nil {
700+
return nil, 0, err
701+
}
702+
data, gasReport, err := api.IBC2PacketReceive(vm.cache, checksum, envBin, msgBin, &gasMeter, store, &goapi, &querier, gasLimit, vm.printDebug)
703+
if err != nil {
704+
return nil, gasReport.UsedInternally, err
705+
}
706+
707+
var result types.IBCReceiveResult
708+
err = DeserializeResponse(gasLimit, deserCost, &gasReport, data, &result)
709+
if err != nil {
710+
return nil, gasReport.UsedInternally, err
711+
}
712+
return &result, gasReport.UsedInternally, nil
713+
}
714+
681715
func compileCost(code WasmCode) uint64 {
682716
// CostPerByte is how much CosmWasm gas is charged *per byte* for compiling WASM code.
683717
// Benchmarks and numbers (in SDK Gas) were discussed in:

libwasmvm/Cargo.lock

Lines changed: 17 additions & 18 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

libwasmvm/Cargo.toml

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "wasmvm"
3-
version = "2.2.1"
3+
version = "2.2.2"
44
publish = false
55
authors = ["Ethan Frey <ethanfrey@users.noreply.github.com>"]
66
edition = "2021"
@@ -37,19 +37,20 @@ backtraces = []
3737
# "iterator",
3838
# ] }
3939
# Temporarily using CosmWasm's `main` branch until the next release.
40-
# This allows us to build WasmVM with the latest CosmWasm changes to develop Eureka support more easily.
40+
# This allows us to build WasmVM with the latest CosmWasm changes to develop IBC2 support more easily.
4141
# You can also use a different branch or a local path in your branches and change it back to `main`
4242
# when the CosmWasm PR gets merged.
4343
cosmwasm-std = { git = "https://github.com/CosmWasm/cosmwasm.git", branch = "main", features = [
4444
"staking",
4545
"stargate",
4646
"iterator",
47-
"eureka",
47+
"ibc2",
4848
] }
4949
cosmwasm-vm = { git = "https://github.com/CosmWasm/cosmwasm.git", branch = "main", features = [
5050
"staking",
5151
"stargate",
5252
"iterator",
53+
"ibc2",
5354
] }
5455
errno = "0.3.8"
5556
rmp-serde = "1.3.0"

libwasmvm/bindings.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -633,6 +633,18 @@ struct UnmanagedVector ibc_destination_callback(struct cache_t *cache,
633633
struct GasReport *gas_report,
634634
struct UnmanagedVector *error_msg);
635635

636+
struct UnmanagedVector ibc2_packet_receive(struct cache_t *cache,
637+
struct ByteSliceView checksum,
638+
struct ByteSliceView env,
639+
struct ByteSliceView msg,
640+
struct Db db,
641+
struct GoApi api,
642+
struct GoQuerier querier,
643+
uint64_t gas_limit,
644+
bool print_debug,
645+
struct GasReport *gas_report,
646+
struct UnmanagedVector *error_msg);
647+
636648
struct UnmanagedVector new_unmanaged_vector(bool nil, const uint8_t *ptr, uintptr_t length);
637649

638650
void destroy_unmanaged_vector(struct UnmanagedVector v);

0 commit comments

Comments
 (0)