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

IBC Callbacks #520

Merged
merged 10 commits into from
Jun 26, 2024
Merged
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
24 changes: 24 additions & 0 deletions internal/api/bindings.h
Original file line number Diff line number Diff line change
Expand Up @@ -597,6 +597,30 @@ struct UnmanagedVector ibc_packet_timeout(struct cache_t *cache,
struct GasReport *gas_report,
struct UnmanagedVector *error_msg);

struct UnmanagedVector ibc_source_callback(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 ibc_destination_callback(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
84 changes: 84 additions & 0 deletions internal/api/lib.go
Original file line number Diff line number Diff line change
Expand Up @@ -700,6 +700,90 @@ func IBCPacketTimeout(
return copyAndDestroyUnmanagedVector(res), convertGasReport(gasReport), nil
}

func IBCSourceCallback(
cache Cache,
checksum []byte,
env []byte,
msg []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)
msgBytes := makeView(msg)
defer runtime.KeepAlive(msg)
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.ibc_source_callback(cache.ptr, cs, e, msgBytes, 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 IBCDestinationCallback(
cache Cache,
checksum []byte,
env []byte,
msg []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)
msgBytes := makeView(msg)
defer runtime.KeepAlive(msg)
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.ibc_destination_callback(cache.ptr, cs, e, msgBytes, 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 convertGasReport(report C.GasReport) types.GasReport {
return types.GasReport{
Limit: uint64(report.limit),
Expand Down
69 changes: 69 additions & 0 deletions lib_libwasmvm.go
Original file line number Diff line number Diff line change
Expand Up @@ -532,6 +532,75 @@ func (vm *VM) IBCPacketTimeout(
return &result, gasReport.UsedInternally, nil
}

// IBCSourceCallback is available on IBC-enabled contracts with the corresponding entrypoint
// and should be called when the response (ack or timeout) for an outgoing callbacks-enabled packet
// (previously sent by this contract) is received.
func (vm *VM) IBCSourceCallback(
checksum Checksum,
env types.Env,
msg types.IBCSourceCallbackMsg,
store KVStore,
goapi GoAPI,
querier Querier,
gasMeter GasMeter,
gasLimit uint64,
deserCost types.UFraction,
) (*types.IBCBasicResult, 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.IBCSourceCallback(vm.cache, checksum, envBin, msgBin, &gasMeter, store, &goapi, &querier, gasLimit, vm.printDebug)
if err != nil {
return nil, gasReport.UsedInternally, err
}

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

// IBCDestinationCallback is available on IBC-enabled contracts with the corresponding entrypoint
// and should be called when an incoming callbacks-enabled IBC packet is received.
func (vm *VM) IBCDestinationCallback(
checksum Checksum,
env types.Env,
msg types.IBCDestinationCallbackMsg,
store KVStore,
goapi GoAPI,
querier Querier,
gasMeter GasMeter,
gasLimit uint64,
deserCost types.UFraction,
) (*types.IBCBasicResult, 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.IBCDestinationCallback(vm.cache, checksum, envBin, msgBin, &gasMeter, store, &goapi, &querier, gasLimit, vm.printDebug)
if err != nil {
return nil, gasReport.UsedInternally, err
}

var result types.IBCBasicResult
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
14 changes: 7 additions & 7 deletions libwasmvm/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

24 changes: 24 additions & 0 deletions libwasmvm/bindings.h
Original file line number Diff line number Diff line change
Expand Up @@ -597,6 +597,30 @@ struct UnmanagedVector ibc_packet_timeout(struct cache_t *cache,
struct GasReport *gas_report,
struct UnmanagedVector *error_msg);

struct UnmanagedVector ibc_source_callback(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 ibc_destination_callback(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
67 changes: 64 additions & 3 deletions libwasmvm/src/calls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,10 @@ use time::{format_description::well_known::Rfc3339, OffsetDateTime};
use cosmwasm_std::Checksum;
use cosmwasm_vm::{
call_execute_raw, call_ibc_channel_close_raw, call_ibc_channel_connect_raw,
call_ibc_channel_open_raw, call_ibc_packet_ack_raw, call_ibc_packet_receive_raw,
call_ibc_packet_timeout_raw, call_instantiate_raw, call_migrate_raw, call_query_raw,
call_reply_raw, call_sudo_raw, Backend, Cache, Instance, InstanceOptions, VmResult,
call_ibc_channel_open_raw, call_ibc_destination_callback_raw, call_ibc_packet_ack_raw,
call_ibc_packet_receive_raw, call_ibc_packet_timeout_raw, call_ibc_source_callback_raw,
call_instantiate_raw, call_migrate_raw, call_query_raw, call_reply_raw, call_sudo_raw, Backend,
Cache, Instance, InstanceOptions, VmResult,
};

use crate::api::GoApi;
Expand Down Expand Up @@ -395,6 +396,66 @@ pub extern "C" fn ibc_packet_timeout(
)
}

#[no_mangle]
pub extern "C" fn ibc_source_callback(
cache: *mut cache_t,
checksum: ByteSliceView,
env: ByteSliceView,
msg: ByteSliceView,
db: Db,
api: GoApi,
querier: GoQuerier,
gas_limit: u64,
print_debug: bool,
gas_report: Option<&mut GasReport>,
error_msg: Option<&mut UnmanagedVector>,
) -> UnmanagedVector {
call_2_args(
call_ibc_source_callback_raw,
cache,
checksum,
env,
msg,
db,
api,
querier,
gas_limit,
print_debug,
gas_report,
error_msg,
)
}

#[no_mangle]
pub extern "C" fn ibc_destination_callback(
cache: *mut cache_t,
checksum: ByteSliceView,
env: ByteSliceView,
msg: ByteSliceView,
db: Db,
api: GoApi,
querier: GoQuerier,
gas_limit: u64,
print_debug: bool,
gas_report: Option<&mut GasReport>,
error_msg: Option<&mut UnmanagedVector>,
) -> UnmanagedVector {
call_2_args(
call_ibc_destination_callback_raw,
cache,
checksum,
env,
msg,
db,
api,
querier,
gas_limit,
print_debug,
gas_report,
error_msg,
)
}

type VmFn2Args = fn(
instance: &mut Instance<GoApi, GoStorage, GoQuerier>,
arg1: &[u8],
Expand Down
Loading
Loading