Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Add IBCv2 Receive packet entrypoint #628

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Binary file modified internal/api/libwasmvm.x86_64.so
Binary file not shown.
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