Skip to content

Commit 15d29dc

Browse files
authored
Merge pull request #520 from CosmWasm/ibc-callbacks
IBC Callbacks
2 parents 1de5cd8 + ea935a7 commit 15d29dc

File tree

7 files changed

+313
-10
lines changed

7 files changed

+313
-10
lines changed

internal/api/bindings.h

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -597,6 +597,30 @@ struct UnmanagedVector ibc_packet_timeout(struct cache_t *cache,
597597
struct GasReport *gas_report,
598598
struct UnmanagedVector *error_msg);
599599

600+
struct UnmanagedVector ibc_source_callback(struct cache_t *cache,
601+
struct ByteSliceView checksum,
602+
struct ByteSliceView env,
603+
struct ByteSliceView msg,
604+
struct Db db,
605+
struct GoApi api,
606+
struct GoQuerier querier,
607+
uint64_t gas_limit,
608+
bool print_debug,
609+
struct GasReport *gas_report,
610+
struct UnmanagedVector *error_msg);
611+
612+
struct UnmanagedVector ibc_destination_callback(struct cache_t *cache,
613+
struct ByteSliceView checksum,
614+
struct ByteSliceView env,
615+
struct ByteSliceView msg,
616+
struct Db db,
617+
struct GoApi api,
618+
struct GoQuerier querier,
619+
uint64_t gas_limit,
620+
bool print_debug,
621+
struct GasReport *gas_report,
622+
struct UnmanagedVector *error_msg);
623+
600624
struct UnmanagedVector new_unmanaged_vector(bool nil, const uint8_t *ptr, uintptr_t length);
601625

602626
void destroy_unmanaged_vector(struct UnmanagedVector v);

internal/api/lib.go

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -700,6 +700,90 @@ func IBCPacketTimeout(
700700
return copyAndDestroyUnmanagedVector(res), convertGasReport(gasReport), nil
701701
}
702702

703+
func IBCSourceCallback(
704+
cache Cache,
705+
checksum []byte,
706+
env []byte,
707+
msg []byte,
708+
gasMeter *types.GasMeter,
709+
store types.KVStore,
710+
api *types.GoAPI,
711+
querier *Querier,
712+
gasLimit uint64,
713+
printDebug bool,
714+
) ([]byte, types.GasReport, error) {
715+
cs := makeView(checksum)
716+
defer runtime.KeepAlive(checksum)
717+
e := makeView(env)
718+
defer runtime.KeepAlive(env)
719+
msgBytes := makeView(msg)
720+
defer runtime.KeepAlive(msg)
721+
var pinner runtime.Pinner
722+
pinner.Pin(gasMeter)
723+
checkAndPinAPI(api, pinner)
724+
checkAndPinQuerier(querier, pinner)
725+
defer pinner.Unpin()
726+
727+
callID := startCall()
728+
defer endCall(callID)
729+
730+
dbState := buildDBState(store, callID)
731+
db := buildDB(&dbState, gasMeter)
732+
a := buildAPI(api)
733+
q := buildQuerier(querier)
734+
var gasReport C.GasReport
735+
errmsg := uninitializedUnmanagedVector()
736+
737+
res, err := C.ibc_source_callback(cache.ptr, cs, e, msgBytes, db, a, q, cu64(gasLimit), cbool(printDebug), &gasReport, &errmsg)
738+
if err != nil && err.(syscall.Errno) != C.ErrnoValue_Success {
739+
// Depending on the nature of the error, `gasUsed` will either have a meaningful value, or just 0.
740+
return nil, convertGasReport(gasReport), errorWithMessage(err, errmsg)
741+
}
742+
return copyAndDestroyUnmanagedVector(res), convertGasReport(gasReport), nil
743+
}
744+
745+
func IBCDestinationCallback(
746+
cache Cache,
747+
checksum []byte,
748+
env []byte,
749+
msg []byte,
750+
gasMeter *types.GasMeter,
751+
store types.KVStore,
752+
api *types.GoAPI,
753+
querier *Querier,
754+
gasLimit uint64,
755+
printDebug bool,
756+
) ([]byte, types.GasReport, error) {
757+
cs := makeView(checksum)
758+
defer runtime.KeepAlive(checksum)
759+
e := makeView(env)
760+
defer runtime.KeepAlive(env)
761+
msgBytes := makeView(msg)
762+
defer runtime.KeepAlive(msg)
763+
var pinner runtime.Pinner
764+
pinner.Pin(gasMeter)
765+
checkAndPinAPI(api, pinner)
766+
checkAndPinQuerier(querier, pinner)
767+
defer pinner.Unpin()
768+
769+
callID := startCall()
770+
defer endCall(callID)
771+
772+
dbState := buildDBState(store, callID)
773+
db := buildDB(&dbState, gasMeter)
774+
a := buildAPI(api)
775+
q := buildQuerier(querier)
776+
var gasReport C.GasReport
777+
errmsg := uninitializedUnmanagedVector()
778+
779+
res, err := C.ibc_destination_callback(cache.ptr, cs, e, msgBytes, db, a, q, cu64(gasLimit), cbool(printDebug), &gasReport, &errmsg)
780+
if err != nil && err.(syscall.Errno) != C.ErrnoValue_Success {
781+
// Depending on the nature of the error, `gasUsed` will either have a meaningful value, or just 0.
782+
return nil, convertGasReport(gasReport), errorWithMessage(err, errmsg)
783+
}
784+
return copyAndDestroyUnmanagedVector(res), convertGasReport(gasReport), nil
785+
}
786+
703787
func convertGasReport(report C.GasReport) types.GasReport {
704788
return types.GasReport{
705789
Limit: uint64(report.limit),

lib_libwasmvm.go

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -532,6 +532,75 @@ func (vm *VM) IBCPacketTimeout(
532532
return &result, gasReport.UsedInternally, nil
533533
}
534534

535+
// IBCSourceCallback is available on IBC-enabled contracts with the corresponding entrypoint
536+
// and should be called when the response (ack or timeout) for an outgoing callbacks-enabled packet
537+
// (previously sent by this contract) is received.
538+
func (vm *VM) IBCSourceCallback(
539+
checksum Checksum,
540+
env types.Env,
541+
msg types.IBCSourceCallbackMsg,
542+
store KVStore,
543+
goapi GoAPI,
544+
querier Querier,
545+
gasMeter GasMeter,
546+
gasLimit uint64,
547+
deserCost types.UFraction,
548+
) (*types.IBCBasicResult, uint64, error) {
549+
envBin, err := json.Marshal(env)
550+
if err != nil {
551+
return nil, 0, err
552+
}
553+
msgBin, err := json.Marshal(msg)
554+
if err != nil {
555+
return nil, 0, err
556+
}
557+
data, gasReport, err := api.IBCSourceCallback(vm.cache, checksum, envBin, msgBin, &gasMeter, store, &goapi, &querier, gasLimit, vm.printDebug)
558+
if err != nil {
559+
return nil, gasReport.UsedInternally, err
560+
}
561+
562+
var result types.IBCBasicResult
563+
err = DeserializeResponse(gasLimit, deserCost, &gasReport, data, &result)
564+
if err != nil {
565+
return nil, gasReport.UsedInternally, err
566+
}
567+
return &result, gasReport.UsedInternally, nil
568+
}
569+
570+
// IBCDestinationCallback is available on IBC-enabled contracts with the corresponding entrypoint
571+
// and should be called when an incoming callbacks-enabled IBC packet is received.
572+
func (vm *VM) IBCDestinationCallback(
573+
checksum Checksum,
574+
env types.Env,
575+
msg types.IBCDestinationCallbackMsg,
576+
store KVStore,
577+
goapi GoAPI,
578+
querier Querier,
579+
gasMeter GasMeter,
580+
gasLimit uint64,
581+
deserCost types.UFraction,
582+
) (*types.IBCBasicResult, uint64, error) {
583+
envBin, err := json.Marshal(env)
584+
if err != nil {
585+
return nil, 0, err
586+
}
587+
msgBin, err := json.Marshal(msg)
588+
if err != nil {
589+
return nil, 0, err
590+
}
591+
data, gasReport, err := api.IBCDestinationCallback(vm.cache, checksum, envBin, msgBin, &gasMeter, store, &goapi, &querier, gasLimit, vm.printDebug)
592+
if err != nil {
593+
return nil, gasReport.UsedInternally, err
594+
}
595+
596+
var result types.IBCBasicResult
597+
err = DeserializeResponse(gasLimit, deserCost, &gasReport, data, &result)
598+
if err != nil {
599+
return nil, gasReport.UsedInternally, err
600+
}
601+
return &result, gasReport.UsedInternally, nil
602+
}
603+
535604
func compileCost(code WasmCode) uint64 {
536605
// CostPerByte is how much CosmWasm gas is charged *per byte* for compiling WASM code.
537606
// Benchmarks and numbers (in SDK Gas) were discussed in:

libwasmvm/Cargo.lock

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

libwasmvm/bindings.h

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -597,6 +597,30 @@ struct UnmanagedVector ibc_packet_timeout(struct cache_t *cache,
597597
struct GasReport *gas_report,
598598
struct UnmanagedVector *error_msg);
599599

600+
struct UnmanagedVector ibc_source_callback(struct cache_t *cache,
601+
struct ByteSliceView checksum,
602+
struct ByteSliceView env,
603+
struct ByteSliceView msg,
604+
struct Db db,
605+
struct GoApi api,
606+
struct GoQuerier querier,
607+
uint64_t gas_limit,
608+
bool print_debug,
609+
struct GasReport *gas_report,
610+
struct UnmanagedVector *error_msg);
611+
612+
struct UnmanagedVector ibc_destination_callback(struct cache_t *cache,
613+
struct ByteSliceView checksum,
614+
struct ByteSliceView env,
615+
struct ByteSliceView msg,
616+
struct Db db,
617+
struct GoApi api,
618+
struct GoQuerier querier,
619+
uint64_t gas_limit,
620+
bool print_debug,
621+
struct GasReport *gas_report,
622+
struct UnmanagedVector *error_msg);
623+
600624
struct UnmanagedVector new_unmanaged_vector(bool nil, const uint8_t *ptr, uintptr_t length);
601625

602626
void destroy_unmanaged_vector(struct UnmanagedVector v);

libwasmvm/src/calls.rs

Lines changed: 64 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,10 @@ use time::{format_description::well_known::Rfc3339, OffsetDateTime};
88
use cosmwasm_std::Checksum;
99
use cosmwasm_vm::{
1010
call_execute_raw, call_ibc_channel_close_raw, call_ibc_channel_connect_raw,
11-
call_ibc_channel_open_raw, call_ibc_packet_ack_raw, call_ibc_packet_receive_raw,
12-
call_ibc_packet_timeout_raw, call_instantiate_raw, call_migrate_raw, call_query_raw,
13-
call_reply_raw, call_sudo_raw, Backend, Cache, Instance, InstanceOptions, VmResult,
11+
call_ibc_channel_open_raw, call_ibc_destination_callback_raw, call_ibc_packet_ack_raw,
12+
call_ibc_packet_receive_raw, call_ibc_packet_timeout_raw, call_ibc_source_callback_raw,
13+
call_instantiate_raw, call_migrate_raw, call_query_raw, call_reply_raw, call_sudo_raw, Backend,
14+
Cache, Instance, InstanceOptions, VmResult,
1415
};
1516

1617
use crate::api::GoApi;
@@ -395,6 +396,66 @@ pub extern "C" fn ibc_packet_timeout(
395396
)
396397
}
397398

399+
#[no_mangle]
400+
pub extern "C" fn ibc_source_callback(
401+
cache: *mut cache_t,
402+
checksum: ByteSliceView,
403+
env: ByteSliceView,
404+
msg: ByteSliceView,
405+
db: Db,
406+
api: GoApi,
407+
querier: GoQuerier,
408+
gas_limit: u64,
409+
print_debug: bool,
410+
gas_report: Option<&mut GasReport>,
411+
error_msg: Option<&mut UnmanagedVector>,
412+
) -> UnmanagedVector {
413+
call_2_args(
414+
call_ibc_source_callback_raw,
415+
cache,
416+
checksum,
417+
env,
418+
msg,
419+
db,
420+
api,
421+
querier,
422+
gas_limit,
423+
print_debug,
424+
gas_report,
425+
error_msg,
426+
)
427+
}
428+
429+
#[no_mangle]
430+
pub extern "C" fn ibc_destination_callback(
431+
cache: *mut cache_t,
432+
checksum: ByteSliceView,
433+
env: ByteSliceView,
434+
msg: ByteSliceView,
435+
db: Db,
436+
api: GoApi,
437+
querier: GoQuerier,
438+
gas_limit: u64,
439+
print_debug: bool,
440+
gas_report: Option<&mut GasReport>,
441+
error_msg: Option<&mut UnmanagedVector>,
442+
) -> UnmanagedVector {
443+
call_2_args(
444+
call_ibc_destination_callback_raw,
445+
cache,
446+
checksum,
447+
env,
448+
msg,
449+
db,
450+
api,
451+
querier,
452+
gas_limit,
453+
print_debug,
454+
gas_report,
455+
error_msg,
456+
)
457+
}
458+
398459
type VmFn2Args = fn(
399460
instance: &mut Instance<GoApi, GoStorage, GoQuerier>,
400461
arg1: &[u8],

0 commit comments

Comments
 (0)