diff --git a/internal/api/bindings.h b/internal/api/bindings.h
index 6bb960b4d..bf03c9e24 100644
--- a/internal/api/bindings.h
+++ b/internal/api/bindings.h
@@ -139,8 +139,9 @@ typedef struct ByteSliceView {
* // …
* # let mut error_msg = UnmanagedVector::default();
* # let mut used_gas = 0_u64;
+ * # let read_db = db.vtable.read_db.unwrap();
*
- * let go_error: GoError = (db.vtable.read_db)(
+ * let go_error: GoError = read_db(
* db.state,
* db.gas_meter,
* &mut used_gas as *mut u64,
@@ -253,7 +254,7 @@ typedef struct iterator_t {
uint64_t iterator_index;
} iterator_t;
-typedef struct Iterator_vtable {
+typedef struct IteratorVtable {
int32_t (*next)(struct iterator_t,
struct gas_meter_t*,
uint64_t*,
@@ -270,15 +271,15 @@ typedef struct Iterator_vtable {
uint64_t*,
struct UnmanagedVector*,
struct UnmanagedVector*);
-} Iterator_vtable;
+} IteratorVtable;
typedef struct GoIter {
struct gas_meter_t *gas_meter;
struct iterator_t state;
- struct Iterator_vtable vtable;
+ struct IteratorVtable vtable;
} GoIter;
-typedef struct Db_vtable {
+typedef struct DbVtable {
int32_t (*read_db)(struct db_t*,
struct gas_meter_t*,
uint64_t*,
@@ -304,19 +305,19 @@ typedef struct Db_vtable {
int32_t,
struct GoIter*,
struct UnmanagedVector*);
-} Db_vtable;
+} DbVtable;
typedef struct Db {
struct gas_meter_t *gas_meter;
struct db_t *state;
- struct Db_vtable vtable;
+ struct DbVtable vtable;
} Db;
typedef struct api_t {
uint8_t _private[0];
} api_t;
-typedef struct GoApi_vtable {
+typedef struct GoApiVtable {
int32_t (*humanize_address)(const struct api_t*,
struct U8SliceView,
struct UnmanagedVector*,
@@ -327,29 +328,29 @@ typedef struct GoApi_vtable {
struct UnmanagedVector*,
struct UnmanagedVector*,
uint64_t*);
-} GoApi_vtable;
+} GoApiVtable;
typedef struct GoApi {
const struct api_t *state;
- struct GoApi_vtable vtable;
+ struct GoApiVtable vtable;
} GoApi;
typedef struct querier_t {
uint8_t _private[0];
} querier_t;
-typedef struct Querier_vtable {
+typedef struct QuerierVtable {
int32_t (*query_external)(const struct querier_t*,
uint64_t,
uint64_t*,
struct U8SliceView,
struct UnmanagedVector*,
struct UnmanagedVector*);
-} Querier_vtable;
+} QuerierVtable;
typedef struct GoQuerier {
const struct querier_t *state;
- struct Querier_vtable vtable;
+ struct QuerierVtable vtable;
} GoQuerier;
typedef struct GasReport {
diff --git a/internal/api/callbacks.go b/internal/api/callbacks.go
index 2f945dfbc..dc5db74b4 100644
--- a/internal/api/callbacks.go
+++ b/internal/api/callbacks.go
@@ -89,7 +89,7 @@ func recoverPanic(ret *C.GoError) {
/****** DB ********/
-var db_vtable = C.Db_vtable{
+var db_vtable = C.DbVtable{
read_db: C.any_function_t(C.cGet_cgo),
write_db: C.any_function_t(C.cSet_cgo),
remove_db: C.any_function_t(C.cDelete_cgo),
@@ -124,7 +124,7 @@ func buildDB(state *DBState, gm *types.GasMeter) C.Db {
}
}
-var iterator_vtable = C.Iterator_vtable{
+var iterator_vtable = C.IteratorVtable{
next: C.any_function_t(C.cNext_cgo),
next_key: C.any_function_t(C.cNextKey_cgo),
next_value: C.any_function_t(C.cNextValue_cgo),
@@ -358,7 +358,7 @@ func nextPart(ref C.iterator_t, gasMeter *C.gas_meter_t, usedGas *cu64, output *
return C.GoError_None
}
-var api_vtable = C.GoApi_vtable{
+var api_vtable = C.GoApiVtable{
humanize_address: C.any_function_t(C.cHumanAddress_cgo),
canonicalize_address: C.any_function_t(C.cCanonicalAddress_cgo),
}
@@ -429,7 +429,7 @@ func cCanonicalAddress(ptr *C.api_t, src C.U8SliceView, dest *C.UnmanagedVector,
/****** Go Querier ********/
-var querier_vtable = C.Querier_vtable{
+var querier_vtable = C.QuerierVtable{
query_external: C.any_function_t(C.cQueryExternal_cgo),
}
diff --git a/libwasmvm/bindings.h b/libwasmvm/bindings.h
index 6bb960b4d..bf03c9e24 100644
--- a/libwasmvm/bindings.h
+++ b/libwasmvm/bindings.h
@@ -139,8 +139,9 @@ typedef struct ByteSliceView {
* // …
* # let mut error_msg = UnmanagedVector::default();
* # let mut used_gas = 0_u64;
+ * # let read_db = db.vtable.read_db.unwrap();
*
- * let go_error: GoError = (db.vtable.read_db)(
+ * let go_error: GoError = read_db(
* db.state,
* db.gas_meter,
* &mut used_gas as *mut u64,
@@ -253,7 +254,7 @@ typedef struct iterator_t {
uint64_t iterator_index;
} iterator_t;
-typedef struct Iterator_vtable {
+typedef struct IteratorVtable {
int32_t (*next)(struct iterator_t,
struct gas_meter_t*,
uint64_t*,
@@ -270,15 +271,15 @@ typedef struct Iterator_vtable {
uint64_t*,
struct UnmanagedVector*,
struct UnmanagedVector*);
-} Iterator_vtable;
+} IteratorVtable;
typedef struct GoIter {
struct gas_meter_t *gas_meter;
struct iterator_t state;
- struct Iterator_vtable vtable;
+ struct IteratorVtable vtable;
} GoIter;
-typedef struct Db_vtable {
+typedef struct DbVtable {
int32_t (*read_db)(struct db_t*,
struct gas_meter_t*,
uint64_t*,
@@ -304,19 +305,19 @@ typedef struct Db_vtable {
int32_t,
struct GoIter*,
struct UnmanagedVector*);
-} Db_vtable;
+} DbVtable;
typedef struct Db {
struct gas_meter_t *gas_meter;
struct db_t *state;
- struct Db_vtable vtable;
+ struct DbVtable vtable;
} Db;
typedef struct api_t {
uint8_t _private[0];
} api_t;
-typedef struct GoApi_vtable {
+typedef struct GoApiVtable {
int32_t (*humanize_address)(const struct api_t*,
struct U8SliceView,
struct UnmanagedVector*,
@@ -327,29 +328,29 @@ typedef struct GoApi_vtable {
struct UnmanagedVector*,
struct UnmanagedVector*,
uint64_t*);
-} GoApi_vtable;
+} GoApiVtable;
typedef struct GoApi {
const struct api_t *state;
- struct GoApi_vtable vtable;
+ struct GoApiVtable vtable;
} GoApi;
typedef struct querier_t {
uint8_t _private[0];
} querier_t;
-typedef struct Querier_vtable {
+typedef struct QuerierVtable {
int32_t (*query_external)(const struct querier_t*,
uint64_t,
uint64_t*,
struct U8SliceView,
struct UnmanagedVector*,
struct UnmanagedVector*);
-} Querier_vtable;
+} QuerierVtable;
typedef struct GoQuerier {
const struct querier_t *state;
- struct Querier_vtable vtable;
+ struct QuerierVtable vtable;
} GoQuerier;
typedef struct GasReport {
diff --git a/libwasmvm/src/api.rs b/libwasmvm/src/api.rs
index e62f39fe1..b1784d8e0 100644
--- a/libwasmvm/src/api.rs
+++ b/libwasmvm/src/api.rs
@@ -2,6 +2,7 @@ use cosmwasm_vm::{BackendApi, BackendError, BackendResult, GasInfo};
use crate::error::GoError;
use crate::memory::{U8SliceView, UnmanagedVector};
+use crate::Vtable;
// this represents something passed in from the caller side of FFI
// in this case a struct with go function pointers
@@ -13,29 +14,35 @@ pub struct api_t {
// These functions should return GoError but because we don't trust them here, we treat the return value as i32
// and then check it when converting to GoError manually
#[repr(C)]
-#[derive(Copy, Clone)]
-pub struct GoApi_vtable {
- pub humanize_address: extern "C" fn(
- *const api_t,
- U8SliceView,
- *mut UnmanagedVector, // human output
- *mut UnmanagedVector, // error message output
- *mut u64,
- ) -> i32,
- pub canonicalize_address: extern "C" fn(
- *const api_t,
- U8SliceView,
- *mut UnmanagedVector, // canonical output
- *mut UnmanagedVector, // error message output
- *mut u64,
- ) -> i32,
+#[derive(Copy, Clone, Default)]
+pub struct GoApiVtable {
+ pub humanize_address: Option<
+ extern "C" fn(
+ *const api_t,
+ U8SliceView,
+ *mut UnmanagedVector, // human output
+ *mut UnmanagedVector, // error message output
+ *mut u64,
+ ) -> i32,
+ >,
+ pub canonicalize_address: Option<
+ extern "C" fn(
+ *const api_t,
+ U8SliceView,
+ *mut UnmanagedVector, // canonical output
+ *mut UnmanagedVector, // error message output
+ *mut u64,
+ ) -> i32,
+ >,
}
+impl Vtable for GoApiVtable {}
+
#[repr(C)]
#[derive(Copy, Clone)]
pub struct GoApi {
pub state: *const api_t,
- pub vtable: GoApi_vtable,
+ pub vtable: GoApiVtable,
}
// We must declare that these are safe to Send, to use in wasm.
@@ -50,7 +57,11 @@ impl BackendApi for GoApi {
let mut output = UnmanagedVector::default();
let mut error_msg = UnmanagedVector::default();
let mut used_gas = 0_u64;
- let go_error: GoError = (self.vtable.canonicalize_address)(
+ let canonicalize_address = self
+ .vtable
+ .canonicalize_address
+ .expect("vtable function 'canonicalize_address' not set");
+ let go_error: GoError = canonicalize_address(
self.state,
U8SliceView::new(Some(human.as_bytes())),
&mut output as *mut UnmanagedVector,
@@ -79,7 +90,11 @@ impl BackendApi for GoApi {
let mut output = UnmanagedVector::default();
let mut error_msg = UnmanagedVector::default();
let mut used_gas = 0_u64;
- let go_error: GoError = (self.vtable.humanize_address)(
+ let humanize_address = self
+ .vtable
+ .humanize_address
+ .expect("vtable function 'humanize_address' not set");
+ let go_error: GoError = humanize_address(
self.state,
U8SliceView::new(Some(canonical)),
&mut output as *mut UnmanagedVector,
diff --git a/libwasmvm/src/db.rs b/libwasmvm/src/db.rs
index c34fec57f..f762c92ed 100644
--- a/libwasmvm/src/db.rs
+++ b/libwasmvm/src/db.rs
@@ -1,6 +1,7 @@
use crate::gas_meter::gas_meter_t;
use crate::iterator::GoIter;
use crate::memory::{U8SliceView, UnmanagedVector};
+use crate::vtables::Vtable;
// this represents something passed in from the caller side of FFI
#[repr(C)]
@@ -11,48 +12,59 @@ pub struct db_t {
// These functions should return GoError but because we don't trust them here, we treat the return value as i32
// and then check it when converting to GoError manually
#[repr(C)]
-pub struct Db_vtable {
- pub read_db: extern "C" fn(
- *mut db_t,
- *mut gas_meter_t,
- *mut u64,
- U8SliceView,
- *mut UnmanagedVector, // result output
- *mut UnmanagedVector, // error message output
- ) -> i32,
- pub write_db: extern "C" fn(
- *mut db_t,
- *mut gas_meter_t,
- *mut u64,
- U8SliceView,
- U8SliceView,
- *mut UnmanagedVector, // error message output
- ) -> i32,
- pub remove_db: extern "C" fn(
- *mut db_t,
- *mut gas_meter_t,
- *mut u64,
- U8SliceView,
- *mut UnmanagedVector, // error message output
- ) -> i32,
+#[derive(Default)]
+pub struct DbVtable {
+ pub read_db: Option<
+ extern "C" fn(
+ *mut db_t,
+ *mut gas_meter_t,
+ *mut u64,
+ U8SliceView,
+ *mut UnmanagedVector, // result output
+ *mut UnmanagedVector, // error message output
+ ) -> i32,
+ >,
+ pub write_db: Option<
+ extern "C" fn(
+ *mut db_t,
+ *mut gas_meter_t,
+ *mut u64,
+ U8SliceView,
+ U8SliceView,
+ *mut UnmanagedVector, // error message output
+ ) -> i32,
+ >,
+ pub remove_db: Option<
+ extern "C" fn(
+ *mut db_t,
+ *mut gas_meter_t,
+ *mut u64,
+ U8SliceView,
+ *mut UnmanagedVector, // error message output
+ ) -> i32,
+ >,
// order -> Ascending = 1, Descending = 2
// Note: we cannot set gas_meter on the returned GoIter due to cgo memory safety.
// Since we have the pointer in rust already, we must set that manually
- pub scan_db: extern "C" fn(
- *mut db_t,
- *mut gas_meter_t,
- *mut u64,
- U8SliceView,
- U8SliceView,
- i32,
- *mut GoIter,
- *mut UnmanagedVector, // error message output
- ) -> i32,
+ pub scan_db: Option<
+ extern "C" fn(
+ *mut db_t,
+ *mut gas_meter_t,
+ *mut u64,
+ U8SliceView,
+ U8SliceView,
+ i32,
+ *mut GoIter,
+ *mut UnmanagedVector, // error message output
+ ) -> i32,
+ >,
}
+impl Vtable for DbVtable {}
+
#[repr(C)]
pub struct Db {
pub gas_meter: *mut gas_meter_t,
pub state: *mut db_t,
- pub vtable: Db_vtable,
+ pub vtable: DbVtable,
}
diff --git a/libwasmvm/src/iterator.rs b/libwasmvm/src/iterator.rs
index 00b350e29..7f8de7729 100644
--- a/libwasmvm/src/iterator.rs
+++ b/libwasmvm/src/iterator.rs
@@ -4,6 +4,7 @@ use cosmwasm_vm::{BackendError, BackendResult, GasInfo};
use crate::error::GoError;
use crate::gas_meter::gas_meter_t;
use crate::memory::UnmanagedVector;
+use crate::vtables::Vtable;
// Iterator maintains integer references to some tables on the Go side
#[repr(C)]
@@ -18,7 +19,7 @@ pub struct iterator_t {
// and then check it when converting to GoError manually
#[repr(C)]
#[derive(Default)]
-pub struct Iterator_vtable {
+pub struct IteratorVtable {
pub next: Option<
extern "C" fn(
iterator_t,
@@ -49,11 +50,13 @@ pub struct Iterator_vtable {
>,
}
+impl Vtable for IteratorVtable {}
+
#[repr(C)]
pub struct GoIter {
pub gas_meter: *mut gas_meter_t,
pub state: iterator_t,
- pub vtable: Iterator_vtable,
+ pub vtable: IteratorVtable,
}
impl GoIter {
@@ -61,17 +64,15 @@ impl GoIter {
GoIter {
gas_meter,
state: iterator_t::default(),
- vtable: Iterator_vtable::default(),
+ vtable: IteratorVtable::default(),
}
}
pub fn next(&mut self) -> BackendResult