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 api call_callable_point and validate_dynamic_link_interface #103

Merged
merged 27 commits into from
Apr 14, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
b2f5219
build: change depending cosmwasm
loloicci Mar 19, 2023
432ca0a
feat: add call_callable_point in rust
loloicci Mar 19, 2023
adb7b25
feat: add CallCallablePoint to api
loloicci Mar 19, 2023
584294c
feat: implement CallCallblePoint to VM
loloicci Mar 19, 2023
bd4e14e
chore: go fmt and add comments to rust
loloicci Mar 19, 2023
c92e9e5
fix: cargo clippy
loloicci Mar 30, 2023
dd815d5
feat: add validate_interface to libwasmvm
loloicci Mar 30, 2023
4181db1
feat: add ValidateDynamicLinkInterface to api
loloicci Mar 20, 2023
6772f57
feat: implement ValidateDynamicLinkInterface to vm
loloicci Mar 22, 2023
ca2e6ce
refactor: improve some tests
loloicci Apr 3, 2023
d9ac07e
feat: improve call callable point
loloicci Apr 7, 2023
13e4a47
feat: add api call callable point
loloicci Mar 20, 2023
6324adc
feat: improve call callable point
loloicci Apr 7, 2023
c110ba7
build: build libwasmvm
loloicci Apr 7, 2023
9ade760
feat: improve call callable point
loloicci Apr 7, 2023
581366d
build: build libwasmvm
loloicci Apr 9, 2023
a7946bb
chore: fix a comment in api/lib.go
loloicci Apr 10, 2023
66ba6cd
test: rename and improve a test of call callable point
loloicci Apr 11, 2023
2c6450b
test: add a test for readonly call callable point
loloicci Apr 11, 2023
fc45d72
fix: cost gas even if call callable point fails because of permission
loloicci Apr 11, 2023
4970376
Merge branch 'rust-go-pointer' into rust-go-pointer-api
loloicci Apr 12, 2023
4a4b014
Merge branch 'rust-go-pointer-validate' into rust-go-pointer-api
loloicci Apr 12, 2023
ecd386e
Merge remote-tracking branch 'origin/dynamic_link' into rust-go-point…
loloicci Apr 12, 2023
3124420
chore: go fmt
loloicci Apr 12, 2023
d15af8a
test: remove TestDynamicReadWritePermission and fix gas value
loloicci Apr 12, 2023
4172322
test: remove unused wasm
loloicci Apr 12, 2023
f163904
refactor: remove unused code
loloicci Apr 13, 2023
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 @@ -297,6 +297,8 @@ typedef struct GoApi_vtable {
int32_t (*humanize_address)(const struct api_t*, struct U8SliceView, struct UnmanagedVector*, struct UnmanagedVector*, uint64_t*);
int32_t (*canonicalize_address)(const struct api_t*, struct U8SliceView, struct UnmanagedVector*, struct UnmanagedVector*, uint64_t*);
int32_t (*get_contract_env)(const struct api_t*, struct U8SliceView, uint64_t, struct UnmanagedVector*, struct cache_t**, struct Db*, struct GoQuerier*, struct UnmanagedVector*, struct UnmanagedVector*, uint64_t*, uint64_t*);
int32_t (*call_callable_point)(const struct api_t*, struct U8SliceView, struct U8SliceView, struct U8SliceView, bool, struct U8SliceView, uint64_t, struct UnmanagedVector*, struct UnmanagedVector*, uint64_t*);
int32_t (*validate_interface)(const struct api_t*, struct U8SliceView, struct U8SliceView, struct UnmanagedVector*, struct UnmanagedVector*, uint64_t*);
} GoApi_vtable;

typedef struct GoApi {
Expand Down Expand Up @@ -504,6 +506,28 @@ struct UnmanagedVector ibc_packet_timeout(struct cache_t *cache,
struct UnmanagedVector *attributes,
struct UnmanagedVector *error_msg);

struct UnmanagedVector call_callable_point(struct ByteSliceView name,
struct cache_t *cache,
struct ByteSliceView checksum,
bool is_readonly,
struct ByteSliceView callstack,
struct ByteSliceView env,
struct ByteSliceView args,
struct Db db,
struct GoApi api,
struct GoQuerier querier,
uint64_t gas_limit,
bool print_debug,
uint64_t *gas_used,
struct UnmanagedVector *events,
struct UnmanagedVector *attributes,
struct UnmanagedVector *error_msg);

struct UnmanagedVector validate_interface(struct cache_t *cache,
struct ByteSliceView checksum,
struct ByteSliceView expected_interface,
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
79 changes: 73 additions & 6 deletions internal/api/callbacks.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ typedef GoError (*next_db_fn)(iterator_t idx, gas_meter_t *gas_meter, uint64_t *
typedef GoError (*humanize_address_fn)(api_t *ptr, U8SliceView src, UnmanagedVector *dest, UnmanagedVector *errOut, uint64_t *used_gas);
typedef GoError (*canonicalize_address_fn)(api_t *ptr, U8SliceView src, UnmanagedVector *dest, UnmanagedVector *errOut, uint64_t *used_gas);
typedef GoError (*get_contract_env_fn)(api_t *ptr, U8SliceView contractAddr, UnmanagedVector *contractEnvOut, cache_t **cachePtrOut, Db *dbOut, GoQuerier* querierOut, UnmanagedVector *checksumOut, UnmanagedVector *errOut, uint64_t *used_gas);
typedef GoError (*call_callable_point_fn)(api_t *ptr, U8SliceView contractAddr, U8SliceView name, U8SliceView args, bool isReadonly, U8SliceView callstack, uint64_t gasLimit, UnmanagedVector *result, UnmanagedVector *errOut, uint64_t *used_gas);
typedef GoError (*validate_interface_fn)(api_t *ptr, U8SliceView contractAddr, U8SliceView expectedInterface, UnmanagedVector *result, UnmanagedVector *errOut, uint64_t *used_gas);
typedef GoError (*query_external_fn)(querier_t *ptr, uint64_t gas_limit, uint64_t *used_gas, U8SliceView request, UnmanagedVector *result, UnmanagedVector *errOut);

// forward declarations (db)
Expand All @@ -30,6 +32,8 @@ GoError cNext_cgo(iterator_t *ptr, gas_meter_t *gas_meter, uint64_t *used_gas, U
GoError cHumanAddress_cgo(api_t *ptr, U8SliceView src, UnmanagedVector *dest, UnmanagedVector *errOut, uint64_t *used_gas);
GoError cCanonicalAddress_cgo(api_t *ptr, U8SliceView src, UnmanagedVector *dest, UnmanagedVector *errOut, uint64_t *used_gas);
GoError cGetContractEnv_cgo(api_t *ptr, U8SliceView contractAddr, uint64_t inputLength, UnmanagedVector *contractEnvOut, cache_t **cachePtrOut, Db *dbOut, GoQuerier* querierOut, UnmanagedVector *checksumOut, UnmanagedVector *errOut, uint64_t *instantiate_cost, uint64_t *used_gas);
GoError cCallCallablePoint_cgo(api_t *ptr, U8SliceView contractAddr, U8SliceView name, U8SliceView args, bool isReadonly, U8SliceView callstack, uint64_t gasLimit, UnmanagedVector *result, UnmanagedVector *errOut, uint64_t *used_gas);
GoError cValidateInterface_cgo(api_t *ptr, U8SliceView contractAddr, U8SliceView expectedInterface, UnmanagedVector *result, UnmanagedVector *errOut, uint64_t *used_gas);
// and querier
GoError cQueryExternal_cgo(querier_t *ptr, uint64_t gas_limit, uint64_t *used_gas, U8SliceView request, UnmanagedVector *result, UnmanagedVector *errOut);

Expand Down Expand Up @@ -345,21 +349,27 @@ func cNext(ref C.iterator_t, gasMeter *C.gas_meter_t, usedGas *C.uint64_t, key *
/***** GoAPI *******/

type (
HumanizeAddress func([]byte) (string, uint64, error)
CanonicalizeAddress func(string) ([]byte, uint64, error)
GetContractEnv func(string, uint64) (Env, *Cache, KVStore, Querier, GasMeter, []byte, uint64, uint64, error)
HumanizeAddress func([]byte) (string, uint64, error)
CanonicalizeAddress func(string) ([]byte, uint64, error)
GetContractEnv func(string, uint64) (Env, *Cache, KVStore, Querier, GasMeter, []byte, uint64, uint64, error)
APICallCallablePoint func(string, []byte, []byte, bool, []byte, uint64) ([]byte, uint64, error)
APIValidateInterface func(string, []byte) ([]byte, uint64, error)
)

type GoAPI struct {
HumanAddress HumanizeAddress
CanonicalAddress CanonicalizeAddress
GetContractEnv GetContractEnv
HumanAddress HumanizeAddress
CanonicalAddress CanonicalizeAddress
GetContractEnv GetContractEnv
CallCallablePoint APICallCallablePoint
ValidateInterface APIValidateInterface
}

var api_vtable = C.GoApi_vtable{
humanize_address: (C.humanize_address_fn)(C.cHumanAddress_cgo),
canonicalize_address: (C.canonicalize_address_fn)(C.cCanonicalAddress_cgo),
get_contract_env: (C.get_contract_env_fn)(C.cGetContractEnv_cgo),
call_callable_point: (C.call_callable_point_fn)(C.cCallCallablePoint_cgo),
validate_interface: (C.validate_interface_fn)(C.cValidateInterface_cgo),
}

// contract: original pointer/struct referenced must live longer than C.GoApi struct
Expand Down Expand Up @@ -470,6 +480,63 @@ func cGetContractEnv(ptr *C.api_t, contractAddr C.U8SliceView, inputLength cu64,
return C.GoError_None
}

//export cCallCallablePoint
func cCallCallablePoint(ptr *C.api_t, contractAddr C.U8SliceView, name C.U8SliceView, args C.U8SliceView, isReadonly bool, callstack C.U8SliceView, gasLimit cu64, result *C.UnmanagedVector, errOut *C.UnmanagedVector, used_gas *cu64) (ret C.GoError) {
defer recoverPanic(&ret)

if result == nil || errOut == nil {
return C.GoError_BadArgument
}
if !(*result).is_none || !(*errOut).is_none {
panic("Got a non-none UnmanagedVector we're about to override. This is a bug because someone has to drop the old one.")
}

api := (*GoAPI)(unsafe.Pointer(ptr))
a := string(copyU8Slice(contractAddr))
as := copyU8Slice(args)
n := copyU8Slice(name)
s := copyU8Slice(callstack)
l := uint64(gasLimit)
res, cost, err := api.CallCallablePoint(a, n, as, isReadonly, s, l)

*used_gas = cu64(cost)
if err != nil {
// store the actual error message in the return buffer
*errOut = newUnmanagedVector([]byte(err.Error()))
return C.GoError_User
}

*result = newUnmanagedVector(res)
return C.GoError_None
}

//export cValidateInterface
func cValidateInterface(ptr *C.api_t, contractAddr C.U8SliceView, expectedInterface C.U8SliceView, result *C.UnmanagedVector, errOut *C.UnmanagedVector, used_gas *cu64) (ret C.GoError) {
defer recoverPanic(&ret)

if result == nil || errOut == nil {
return C.GoError_BadArgument
}
if !(*result).is_none || !(*errOut).is_none {
panic("Got a non-none UnmanagedVector we're about to override. This is a bug because someone has to drop the old one.")
}

api := (*GoAPI)(unsafe.Pointer(ptr))
a := string(copyU8Slice(contractAddr))
i := copyU8Slice(expectedInterface)
res, cost, err := api.ValidateInterface(a, i)

*used_gas = cu64(cost)
if err != nil {
// store the actual error message in the return buffer
*errOut = newUnmanagedVector([]byte(err.Error()))
return C.GoError_User
}

*result = newUnmanagedVector(res)
return C.GoError_None
}

/****** Go Querier ********/

var querier_vtable = C.Querier_vtable{
Expand Down
9 changes: 9 additions & 0 deletions internal/api/callbacks_cgo.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@ GoError cNext(iterator_t *ptr, gas_meter_t *gas_meter, uint64_t *used_gas, Unman
GoError cHumanAddress(api_t *ptr, U8SliceView src, UnmanagedVector *dest, UnmanagedVector *errOut, uint64_t *used_gas);
GoError cCanonicalAddress(api_t *ptr, U8SliceView src, UnmanagedVector *dest, UnmanagedVector *errOut, uint64_t *used_gas);
GoError cGetContractEnv(api_t *ptr, U8SliceView contractAddr, uint64_t input_length, UnmanagedVector *contractEnvOut, cache_t **cachePtrOut, Db *dbOut, GoQuerier* querierOut, UnmanagedVector *checksumOut, UnmanagedVector *errOut, uint64_t *instantiate_cost, uint64_t *used_gas);
GoError cCallCallablePoint(api_t *ptr, U8SliceView contractAddr, U8SliceView name, U8SliceView args, bool isReadonly, U8SliceView callstack, uint64_t gasLimit, UnmanagedVector *result, UnmanagedVector *errOut, uint64_t *used_gas);
GoError cValidateInterface(api_t *ptr, U8SliceView contractAddr, U8SliceView expectedInterface, UnmanagedVector *result, UnmanagedVector *errOut, uint64_t *used_gas);

// imports (querier)
GoError cQueryExternal(querier_t *ptr, uint64_t gas_limit, uint64_t *used_gas, U8SliceView request, UnmanagedVector *result, UnmanagedVector *errOut);

Expand Down Expand Up @@ -47,6 +50,12 @@ GoError cHumanAddress_cgo(api_t *ptr, U8SliceView src, UnmanagedVector *dest, Un
GoError cGetContractEnv_cgo(api_t *ptr, U8SliceView contractAddr, uint64_t input_length, UnmanagedVector *contractEnvOut, cache_t **cachePtrOut, Db *dbOut, GoQuerier* querierOut, UnmanagedVector *checksumOut, UnmanagedVector *errOut, uint64_t *instantiate_cost, uint64_t *used_gas) {
return cGetContractEnv(ptr, contractAddr, input_length, contractEnvOut, cachePtrOut, dbOut, querierOut, checksumOut, errOut, instantiate_cost, used_gas);
}
GoError cCallCallablePoint_cgo(api_t *ptr, U8SliceView contractAddr, U8SliceView name, U8SliceView args, bool isReadonly, U8SliceView callstack, uint64_t gasLimit, UnmanagedVector *result, UnmanagedVector *errOut, uint64_t *used_gas) {
return cCallCallablePoint(ptr, contractAddr, name, args, isReadonly, callstack, gasLimit, result, errOut, used_gas);
}
GoError cValidateInterface_cgo(api_t *ptr, U8SliceView contractAddr, U8SliceView expectedInterface, UnmanagedVector *result, UnmanagedVector *errOut, uint64_t *used_gas) {
return cValidateInterface(ptr, contractAddr, expectedInterface, result, errOut, used_gas);
}

// Gateway functions (querier)
GoError cQueryExternal_cgo(querier_t *ptr, uint64_t gas_limit, uint64_t *used_gas, U8SliceView request, UnmanagedVector *result, UnmanagedVector *errOut) {
Expand Down
74 changes: 74 additions & 0 deletions internal/api/lib.go
Original file line number Diff line number Diff line change
Expand Up @@ -608,6 +608,80 @@ func IBCPacketTimeout(
return copyAndDestroyUnmanagedVector(res), copyAndDestroyUnmanagedVector(events), copyAndDestroyUnmanagedVector(attributes), uint64(gasUsed), nil
}

// name: Serialized string
// args: Serialized [][]byte
// callstack: Serialized []string
// returned gasUsed: used gas without instantiation cost
func CallCallablePoint(
name []byte,
cache Cache,
checksum []byte,
isReadonly bool,
callstack []byte,
env []byte,
args []byte,
gasMeter *GasMeter,
store KVStore,
api *GoAPI,
querier *Querier,
gasLimit uint64,
printDebug bool,
) ([]byte, []byte, []byte, uint64, error) {
n := makeView(name)
defer runtime.KeepAlive(name)
cs := makeView(checksum)
defer runtime.KeepAlive(checksum)
e := makeView(env)
defer runtime.KeepAlive(env)
s := makeView(callstack)
defer runtime.KeepAlive(callstack)
as := makeView(args)
defer runtime.KeepAlive(args)

callID := startCall()
defer endCall(callID)

dbState := buildDBState(store, callID)
db := buildDB(&dbState, gasMeter)
a := buildAPI(api)
q := buildQuerier(querier)
var gasUsed cu64
errmsg := newUnmanagedVector(nil)
events := newUnmanagedVector(nil)
attributes := newUnmanagedVector(nil)

res, err := C.call_callable_point(n, cache.ptr, cs, cbool(isReadonly), s, e, as, db, a, q, cu64(gasLimit), cbool(printDebug), &gasUsed, &events, &attributes, &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, nil, nil, uint64(gasUsed), errorWithMessage(err, errmsg)
}
if isReadonly {
return copyAndDestroyUnmanagedVector(res), nil, nil, uint64(gasUsed), nil
} else {
return copyAndDestroyUnmanagedVector(res), copyAndDestroyUnmanagedVector(events), copyAndDestroyUnmanagedVector(attributes), uint64(gasUsed), nil
}
}

// returns: result, systemerr
//
// result: serialized Option<String> which None means true, Some(e) means false and the reason is e.
func ValidateDynamicLinkInterface(
cache Cache,
checksum []byte,
expectedInterface []byte,
) ([]byte, error) {
cs := makeView(checksum)
defer runtime.KeepAlive(checksum)
ei := makeView(expectedInterface)
defer runtime.KeepAlive(expectedInterface)
errmsg := newUnmanagedVector(nil)
res, err := C.validate_interface(cache.ptr, cs, ei, &errmsg)
if err != nil && err.(syscall.Errno) != C.ErrnoValue_Success {
return nil, errorWithMessage(err, errmsg)
}
return copyAndDestroyUnmanagedVector(res), nil
}

/**** To error module ***/

func errorWithMessage(err error, b C.UnmanagedVector) error {
Expand Down
Loading