Skip to content

Commit 8b80469

Browse files
authored
Merge pull request #380 from AntelopeIO/merge_main
[main --> 5.0.0-dev1] Merge main to release/5.0.0-dev1
2 parents fb6ad1b + 2ae2708 commit 8b80469

File tree

12 files changed

+227
-7
lines changed

12 files changed

+227
-7
lines changed

cdt-llvm

libraries/eosiolib/contracts/eosio/contract.hpp

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,12 @@ namespace eosio {
2929
*/
3030
class contract {
3131
public:
32+
enum class exec_type_t : uint8_t {
33+
action,
34+
call,
35+
unknown
36+
};
37+
3238
/**
3339
* Construct a new contract given the contract name
3440
*
@@ -75,7 +81,27 @@ class contract {
7581
*/
7682
inline const datastream<const char*>& get_datastream()const { return _ds; }
7783

84+
/**
85+
* Whether this contract is for a sync call
86+
*
87+
* @return bool - Whether this contract is for a sync call
88+
*/
89+
inline bool is_sync_call()const {
90+
check(_exec_type != exec_type_t::unknown, "too early to call is_sync_call(). _exec_type has not been set yet");
91+
return (_exec_type == exec_type_t::call);
92+
}
93+
94+
/**
95+
* Set the exectution type.
96+
*
97+
* @param type - The exectution type to be set.
98+
*/
99+
inline void set_exec_type(exec_type_t type) {
100+
_exec_type = type;
101+
}
102+
78103
protected:
104+
79105
/**
80106
* The name of the account this contract is deployed on.
81107
*/
@@ -90,5 +116,10 @@ class contract {
90116
* The datastream for this contract
91117
*/
92118
datastream<const char*> _ds = datastream<const char*>(nullptr, 0);
119+
120+
/**
121+
* The execution type: action or sync call
122+
*/
123+
exec_type_t _exec_type = exec_type_t::unknown;
93124
};
94125
}

libraries/eosiolib/contracts/eosio/detail.hpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,11 @@ namespace eosio { namespace detail {
4646
template <typename T>
4747
struct is_same<T,bool> { static constexpr bool value = std::is_integral<T>::value; };
4848

49+
// Full specialization to resolve ambiguity introduced by partial specializations
50+
// of is_same<bool,U> and is_same<T,bool>
51+
template <>
52+
struct is_same<bool, bool> { static constexpr bool value = true; };
53+
4954
template <size_t N, size_t I, auto Arg, auto... Args>
5055
struct get_nth_impl { static constexpr auto value = get_nth_impl<N,I+1,Args...>::value; };
5156

tests/integration/call_tests.cpp

Lines changed: 41 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -140,12 +140,11 @@ BOOST_AUTO_TEST_CASE(mixed_action_call_tags_test) { try {
140140
BOOST_REQUIRE_NO_THROW(t.push_action("caller"_n, "hstmulprmtst"_n, "caller"_n, {}));
141141

142142
// Make sure we can push an action using `sum`.
143-
//BOOST_REQUIRE_NO_THROW(t.push_action("callee"_n, "sum"_n, "callee"_n,
144-
t.push_action("callee"_n, "sum"_n, "callee"_n,
143+
BOOST_REQUIRE_NO_THROW(t.push_action("callee"_n, "sum"_n, "callee"_n,
145144
mvo()
146145
("a", 1)
147146
("b", 2)
148-
("c", 3)); //);
147+
("c", 3)));
149148
} FC_LOG_AND_RETHROW() }
150149

151150
// Verify the receiver contract with only one sync call function works
@@ -234,4 +233,43 @@ BOOST_AUTO_TEST_CASE(addr_book_tests) { try {
234233
BOOST_REQUIRE_NO_THROW(t.push_action("caller"_n, "get"_n, "caller"_n, mvo() ("user", "alice")));
235234
} FC_LOG_AND_RETHROW() }
236235

236+
// For a function tagged as both `action` and `call`, verify is_sync_call()
237+
// returns true if tagged as `call` and false if tagged as `action`.
238+
BOOST_AUTO_TEST_CASE(is_sync_call_test) { try {
239+
call_tester t({
240+
{"caller"_n, contracts::caller_wasm(), contracts::caller_abi().data()},
241+
{"callee"_n, contracts::callee_wasm(), contracts::callee_abi().data()}
242+
});
243+
244+
// issynccall() is tagged as both `action` and `call`, and returns
245+
// is_sync_call(). makesynccall() calls issynccall() as a sync call
246+
// and returns its result. So the current action return value must be
247+
// true.
248+
auto trx_trace = t.push_action("caller"_n, "makesynccall"_n, "caller"_n, {});
249+
auto& action_trace = trx_trace->action_traces[0];
250+
bool return_value = fc::raw::unpack<bool>(action_trace.return_value);
251+
BOOST_REQUIRE(return_value == true);
252+
253+
// Call issynccall() directly as an action. Since issynccall()
254+
// returns is_sync_call(), the current action return value must be false.
255+
trx_trace = t.push_action("callee"_n, "issynccall"_n, "callee"_n, {});
256+
auto& action_trace1 = trx_trace->action_traces[0];
257+
return_value = fc::raw::unpack<bool>(action_trace1.return_value);
258+
BOOST_REQUIRE(return_value == false);
259+
} FC_LOG_AND_RETHROW() }
260+
261+
// Verify customized sync call entry function, without sync call tag
262+
BOOST_AUTO_TEST_CASE(customized_call_entry_func_test1) { try {
263+
call_tester t({{"receiver"_n, contracts::cust_entry_wasm(), contracts::cust_entry_abi().data()}});
264+
265+
BOOST_REQUIRE_NO_THROW(t.push_action("receiver"_n, "cusentrytst1"_n, "receiver"_n, {}));
266+
} FC_LOG_AND_RETHROW() }
267+
268+
// Verify customized sync call entry function, with sync call tag
269+
BOOST_AUTO_TEST_CASE(customized_call_entry_func_test2) { try {
270+
call_tester t({{"receiver"_n, contracts::cust_entry_wasm(), contracts::cust_entry_abi().data()}});
271+
272+
BOOST_REQUIRE_NO_THROW(t.push_action("receiver"_n, "cusentrytst2"_n, "receiver"_n, {}));
273+
} FC_LOG_AND_RETHROW() }
274+
237275
BOOST_AUTO_TEST_SUITE_END()

tests/integration/contracts.hpp.in

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,5 +54,7 @@ namespace eosio::testing {
5454
static std::vector<char> addr_book_callee_abi() { return read_abi("${CMAKE_BINARY_DIR}/../unit/test_contracts/sync_call_addr_book_callee.abi"); }
5555
static std::vector<uint8_t> addr_book_caller_wasm() { return read_wasm("${CMAKE_BINARY_DIR}/../unit/test_contracts/sync_call_addr_book_caller.wasm"); }
5656
static std::vector<char> addr_book_caller_abi() { return read_abi("${CMAKE_BINARY_DIR}/../unit/test_contracts/sync_call_addr_book_caller.abi"); }
57+
static std::vector<uint8_t> cust_entry_wasm() { return read_wasm("${CMAKE_BINARY_DIR}/../unit/test_contracts/sync_call_cust_entry.wasm"); }
58+
static std::vector<char> cust_entry_abi() { return read_abi("${CMAKE_BINARY_DIR}/../unit/test_contracts/sync_call_cust_entry.abi"); }
5759
};
5860
} //ns eosio::testing

tests/toolchain/build-pass/separate_cpp_hpp.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
#include <eosio/eosio.hpp>
22

3-
class [[eosio::contract]] separate_cpp_hpp : eosio::contract {
3+
class [[eosio::contract]] separate_cpp_hpp : public eosio::contract {
44
public:
55
using contract::contract;
66

tests/unit/test_contracts/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ add_contract(sync_call_not_supported sync_call_not_supported sync_call_not_suppo
1919
add_contract(sync_call_single_func sync_call_single_func sync_call_single_func.cpp)
2020
add_contract(sync_call_addr_book_callee sync_call_addr_book_callee sync_call_addr_book_callee.cpp)
2121
add_contract(sync_call_addr_book_caller sync_call_addr_book_caller sync_call_addr_book_caller.cpp)
22+
add_contract(sync_call_cust_entry sync_call_cust_entry sync_call_cust_entry.cpp)
2223
add_contract(capi_tests capi_tests capi/capi.c capi/action.c capi/chain.c capi/crypto.c capi/db.c capi/permission.c
2324
capi/print.c capi/privileged.c capi/system.c capi/transaction.c capi/call.c)
2425

tests/unit/test_contracts/sync_call_callee.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,3 +31,6 @@ struct1_t sync_call_callee::pass_multi_structs(struct1_t s1, int32_t m, struct2_
3131
return { .a = s1.a * m + s2.c, .b = s1.b * m + s2.d };
3232
}
3333

34+
bool sync_call_callee::issynccall() {
35+
return is_sync_call();
36+
}

tests/unit/test_contracts/sync_call_callee.hpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,11 @@ class [[eosio::contract]] sync_call_callee : public eosio::contract{
3838
[[eosio::call]]
3939
struct1_t pass_multi_structs(struct1_t s1, int32_t m, struct2_t s2);
4040

41+
// return is_sync_call()
42+
[[eosio::action, eosio::call]]
43+
bool issynccall();
44+
using issynccall_func = eosio::call_wrapper<"issynccall"_i, &sync_call_callee::issynccall>;
45+
4146
using return_ten_func = eosio::call_wrapper<"return_ten"_i, &sync_call_callee::return_ten>;
4247
using echo_input_func = eosio::call_wrapper<"echo_input"_i, &sync_call_callee::echo_input>;
4348
using void_func_func = eosio::call_wrapper<"void_func"_i, &sync_call_callee::void_func>;

tests/unit/test_contracts/sync_call_caller.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -172,4 +172,11 @@ class [[eosio::contract]] sync_call_caller : public eosio::contract{
172172
status = eosio::call("callee"_n, 0, bad_version_data.data(), bad_version_data.size());
173173
eosio::check(status == -10000, "call did not return -10000 for invalid version");
174174
}
175+
176+
// Call issynccall as a sync call and return its return value
177+
[[eosio::action]]
178+
bool makesynccall() {
179+
sync_call_callee::issynccall_func is_sync_call_func{ "callee"_n };
180+
return is_sync_call_func();
181+
}
175182
};

0 commit comments

Comments
 (0)