Skip to content

Commit

Permalink
feat: Add IBCv2 Receive packet entrypoint
Browse files Browse the repository at this point in the history
  • Loading branch information
kulikthebird committed Mar 6, 2025
1 parent 066cbd6 commit 34d7da5
Show file tree
Hide file tree
Showing 13 changed files with 331 additions and 1,096 deletions.
12 changes: 12 additions & 0 deletions internal/api/bindings.h
Original file line number Diff line number Diff line change
Expand Up @@ -633,6 +633,18 @@ struct UnmanagedVector ibc_destination_callback(struct cache_t *cache,
struct GasReport *gas_report,
struct UnmanagedVector *error_msg);

struct UnmanagedVector ibcv2_packet_receive(struct cache_t *cache,
struct ByteSliceView checksum,
struct ByteSliceView env,
struct ByteSliceView msg,
struct Db db,
struct GoApi api,
struct GoQuerier querier,
uint64_t gas_limit,
bool print_debug,
struct GasReport *gas_report,
struct UnmanagedVector *error_msg);

struct UnmanagedVector new_unmanaged_vector(bool nil, const uint8_t *ptr, uintptr_t length);

void destroy_unmanaged_vector(struct UnmanagedVector v);
Expand Down
46 changes: 44 additions & 2 deletions internal/api/lib.go
Original file line number Diff line number Diff line change
Expand Up @@ -164,11 +164,11 @@ func AnalyzeCode(cache Cache, checksum []byte) (*types.AnalysisReport, error) {
requiredCapabilities := string(copyAndDestroyUnmanagedVector(report.required_capabilities))
entrypoints := string(copyAndDestroyUnmanagedVector(report.entrypoints))
entrypoints_array := strings.Split(entrypoints, ",")
hasEurekaEntryPoints := slices.Contains(entrypoints_array, "eu_recv_packet")
hasIBCv2EntryPoints := slices.Contains(entrypoints_array, "ibcv2_packet_receive")

res := types.AnalysisReport{
HasIBCEntryPoints: bool(report.has_ibc_entry_points),
HasEurekaEntryPoints: hasEurekaEntryPoints,
HasIBCv2EntryPoints: hasIBCv2EntryPoints,
RequiredCapabilities: requiredCapabilities,
Entrypoints: entrypoints_array,
ContractMigrateVersion: optionalU64ToPtr(report.contract_migrate_version),
Expand Down Expand Up @@ -681,6 +681,48 @@ func IBCPacketReceive(
return copyAndDestroyUnmanagedVector(res), convertGasReport(gasReport), nil
}

func IBCv2PacketReceive(
cache Cache,
checksum []byte,
env []byte,
payload []byte,
gasMeter *types.GasMeter,
store types.KVStore,
api *types.GoAPI,
querier *Querier,
gasLimit uint64,
printDebug bool,
) ([]byte, types.GasReport, error) {
cs := makeView(checksum)
defer runtime.KeepAlive(checksum)
e := makeView(env)
defer runtime.KeepAlive(env)
pa := makeView(payload)
defer runtime.KeepAlive(payload)
var pinner runtime.Pinner
pinner.Pin(gasMeter)
checkAndPinAPI(api, pinner)
checkAndPinQuerier(querier, pinner)
defer pinner.Unpin()

callID := startCall()
defer endCall(callID)

dbState := buildDBState(store, callID)
db := buildDB(&dbState, gasMeter)
a := buildAPI(api)
q := buildQuerier(querier)
var gasReport C.GasReport
errmsg := uninitializedUnmanagedVector()

res, err := C.ibcv2_packet_receive(cache.ptr, cs, e, pa, db, a, q, cu64(gasLimit), cbool(printDebug), &gasReport, &errmsg)
if err != nil && err.(syscall.Errno) != C.ErrnoValue_Success {
// Depending on the nature of the error, `gasUsed` will either have a meaningful value, or just 0.
return nil, convertGasReport(gasReport), errorWithMessage(err, errmsg)
}
return copyAndDestroyUnmanagedVector(res), convertGasReport(gasReport), nil
}

func IBCPacketAck(
cache Cache,
checksum []byte,
Expand Down
34 changes: 34 additions & 0 deletions lib_libwasmvm.go
Original file line number Diff line number Diff line change
Expand Up @@ -678,6 +678,40 @@ func (vm *VM) IBCDestinationCallback(
return &result, gasReport.UsedInternally, nil
}

// IBCPacketReceive is available on IBC-enabled contracts and is called when an incoming
// packet is received on a channel belonging to this contract
func (vm *VM) IBCv2PacketReceive(
checksum Checksum,
env types.Env,
msg types.IBCv2PacketReceiveMsg,
store KVStore,
goapi GoAPI,
querier Querier,
gasMeter GasMeter,
gasLimit uint64,
deserCost types.UFraction,
) (*types.IBCReceiveResult, uint64, error) {
envBin, err := json.Marshal(env)
if err != nil {
return nil, 0, err
}
msgBin, err := json.Marshal(msg)
if err != nil {
return nil, 0, err
}
data, gasReport, err := api.IBCv2PacketReceive(vm.cache, checksum, envBin, msgBin, &gasMeter, store, &goapi, &querier, gasLimit, vm.printDebug)
if err != nil {
return nil, gasReport.UsedInternally, err
}

var result types.IBCReceiveResult
err = DeserializeResponse(gasLimit, deserCost, &gasReport, data, &result)
if err != nil {
return nil, gasReport.UsedInternally, err
}
return &result, gasReport.UsedInternally, nil
}

func compileCost(code WasmCode) uint64 {
// CostPerByte is how much CosmWasm gas is charged *per byte* for compiling WASM code.
// Benchmarks and numbers (in SDK Gas) were discussed in:
Expand Down
Loading

0 comments on commit 34d7da5

Please sign in to comment.