From 8bcddb2a15a828dc788440083142f31e54ced557 Mon Sep 17 00:00:00 2001 From: Kevin Heifner Date: Wed, 11 Dec 2019 13:33:13 -0500 Subject: [PATCH 1/9] WIP add set_action_return_value --- libraries/chain/controller.cpp | 8 ++++++++ .../chain/include/eosio/chain/action_receipt.hpp | 13 ++++++++++++- .../eosio/chain/protocol_feature_manager.hpp | 1 + .../webassembly/eos-vm-oc/intrinsic_mapping.hpp | 3 ++- libraries/chain/protocol_feature_manager.cpp | 11 +++++++++++ libraries/chain/wasm_interface.cpp | 8 ++++++++ 6 files changed, 42 insertions(+), 2 deletions(-) diff --git a/libraries/chain/controller.cpp b/libraries/chain/controller.cpp index 4744f521e72..9cee576673a 100644 --- a/libraries/chain/controller.cpp +++ b/libraries/chain/controller.cpp @@ -317,6 +317,7 @@ struct controller_impl { set_activation_handler(); set_activation_handler(); set_activation_handler(); + set_activation_handler(); self.irreversible_block.connect([this](const block_state_ptr& bsp) { wasmif.current_lib(bsp->block_num); @@ -3301,6 +3302,13 @@ void controller_impl::on_activation +void controller_impl::on_activation() { + db.modify( db.get(), [&]( auto& ps ) { + add_intrinsic_to_whitelist( ps.whitelisted_intrinsics, "set_action_return_value" ); + } ); +} + /// End of protocol feature activation handlers diff --git a/libraries/chain/include/eosio/chain/action_receipt.hpp b/libraries/chain/include/eosio/chain/action_receipt.hpp index 78ef25c7c00..6b2e9b1e65c 100644 --- a/libraries/chain/include/eosio/chain/action_receipt.hpp +++ b/libraries/chain/include/eosio/chain/action_receipt.hpp @@ -16,7 +16,18 @@ namespace eosio { namespace chain { fc::unsigned_int code_sequence = 0; ///< total number of setcodes fc::unsigned_int abi_sequence = 0; ///< total number of setabis - digest_type digest()const { return digest_type::hash(*this); } + digest_type digest()const { + digest_type::encoder e; + fc::raw::pack(e, receiver); + fc::raw::pack(e, act_digest); + fc::raw::pack(e, global_sequence); + fc::raw::pack(e, recv_sequence); + fc::raw::pack(e, auth_sequence); + fc::raw::pack(e, code_sequence); + fc::raw::pack(e, abi_sequence); + + return e.result(); + } }; } } /// namespace eosio::chain diff --git a/libraries/chain/include/eosio/chain/protocol_feature_manager.hpp b/libraries/chain/include/eosio/chain/protocol_feature_manager.hpp index 81d22c15b0e..98a80443e9e 100644 --- a/libraries/chain/include/eosio/chain/protocol_feature_manager.hpp +++ b/libraries/chain/include/eosio/chain/protocol_feature_manager.hpp @@ -23,6 +23,7 @@ enum class builtin_protocol_feature_t : uint32_t { ram_restrictions, webauthn_key, wtmsig_block_signatures, + action_return_value, }; struct protocol_feature_subjective_restrictions { diff --git a/libraries/chain/include/eosio/chain/webassembly/eos-vm-oc/intrinsic_mapping.hpp b/libraries/chain/include/eosio/chain/webassembly/eos-vm-oc/intrinsic_mapping.hpp index 022df920918..54f0fbbb1cd 100644 --- a/libraries/chain/include/eosio/chain/webassembly/eos-vm-oc/intrinsic_mapping.hpp +++ b/libraries/chain/include/eosio/chain/webassembly/eos-vm-oc/intrinsic_mapping.hpp @@ -248,7 +248,8 @@ constexpr auto intrinsic_table = boost::hana::make_tuple( "eosio_injection._eosio_i32_to_f64"_s, "eosio_injection._eosio_i64_to_f64"_s, "eosio_injection._eosio_ui32_to_f64"_s, - "eosio_injection._eosio_ui64_to_f64"_s + "eosio_injection._eosio_ui64_to_f64"_s, + "env.set_action_return_value"_s ); }}} \ No newline at end of file diff --git a/libraries/chain/protocol_feature_manager.cpp b/libraries/chain/protocol_feature_manager.cpp index d61a7fe25c4..f43eb562661 100644 --- a/libraries/chain/protocol_feature_manager.cpp +++ b/libraries/chain/protocol_feature_manager.cpp @@ -183,6 +183,17 @@ and may have additional signatures in a block extension with ID `2`. Privileged Contracts: may continue to use `set_proposed_producers` as they have; may use a new `set_proposed_producers_ex` intrinsic to access extended features. +*/ + {} + } ) + ( builtin_protocol_feature_t::action_return_value, builtin_protocol_feature_spec{ + "ACTION_RETURN_VALUE", + fc::variant("69b064c5178e2738e144ed6caa9349a3995370d78db29e494b3126ebd9111966").as(), + // SHA256 hash of the raw message below within the comment delimiters (do not modify message below). +/* +Builtin protocol feature: ACTION_RETURN_VALUE + +Enables new `set_action_return_value` intrinsic which sets a value that is included in action_receipt. */ {} } ) diff --git a/libraries/chain/wasm_interface.cpp b/libraries/chain/wasm_interface.cpp index c29bb77838c..8923919af7c 100644 --- a/libraries/chain/wasm_interface.cpp +++ b/libraries/chain/wasm_interface.cpp @@ -1134,6 +1134,13 @@ class action_api : public context_aware_api { name current_receiver() { return context.get_receiver(); } + + void set_action_return_value( array_ptr packed_variant, uint32_t datalen ) { + datastream ds( packed_variant, datalen ); + fc::variant v; + fc::raw::unpack(ds, v); + //todo set v + } }; class console_api : public context_aware_api { @@ -1964,6 +1971,7 @@ REGISTER_INTRINSICS(action_api, (read_action_data, int(int, int) ) (action_data_size, int() ) (current_receiver, int64_t() ) + (set_action_return_value,void(int, int) ) ); REGISTER_INTRINSICS(authorization_api, From a91bcd01692341a18bfcb8c4f0cb9de5bcd2a74c Mon Sep 17 00:00:00 2001 From: Kevin Heifner Date: Thu, 12 Dec 2019 18:31:51 -0500 Subject: [PATCH 2/9] Add set_action_return_value with std::vector type --- libraries/chain/apply_context.cpp | 9 +++- .../include/eosio/chain/action_receipt.hpp | 14 +++++-- .../include/eosio/chain/apply_context.hpp | 1 + libraries/chain/wasm_interface.cpp | 4 +- .../state_history_serialization.hpp | 9 +++- .../state_history_plugin_abi.cpp | 14 ++++++- unittests/misc_tests.cpp | 16 +++++++ unittests/protocol_feature_tests.cpp | 42 +++++++++++++++++++ 8 files changed, 100 insertions(+), 9 deletions(-) diff --git a/libraries/chain/apply_context.cpp b/libraries/chain/apply_context.cpp index f11d4d6c8ce..6e521d18bfc 100644 --- a/libraries/chain/apply_context.cpp +++ b/libraries/chain/apply_context.cpp @@ -57,6 +57,7 @@ void apply_context::exec_one() const account_metadata_object* receiver_account = nullptr; try { try { + action_return_value.clear(); receiver_account = &db.get( receiver ); privileged = receiver_account->is_privileged(); auto native = control.find_apply_handler( receiver, act->account, act->name ); @@ -143,7 +144,13 @@ void apply_context::exec_one() r.auth_sequence[auth.actor] = next_auth_sequence( auth.actor ); } - trx_context.executed_action_receipt_digests.emplace_back( r.digest() ); + uint32_t version = 0; + if( control.is_builtin_activated( builtin_protocol_feature_t::action_return_value ) ) { + set_field( version, builtin_protocol_feature_t::action_return_value, true ); + r.return_value.emplace( action_return_value ); + } + + trx_context.executed_action_receipt_digests.emplace_back( r.digest( version ) ); finalize_trace( trace, start ); diff --git a/libraries/chain/include/eosio/chain/action_receipt.hpp b/libraries/chain/include/eosio/chain/action_receipt.hpp index 6b2e9b1e65c..21720f6c232 100644 --- a/libraries/chain/include/eosio/chain/action_receipt.hpp +++ b/libraries/chain/include/eosio/chain/action_receipt.hpp @@ -1,6 +1,7 @@ #pragma once #include +#include namespace eosio { namespace chain { @@ -15,8 +16,12 @@ namespace eosio { namespace chain { flat_map auth_sequence; fc::unsigned_int code_sequence = 0; ///< total number of setcodes fc::unsigned_int abi_sequence = 0; ///< total number of setabis + fc::optional> return_value; ///< return value of the action - digest_type digest()const { + /// @param version of digest to calculate + /// 0 for original version + /// set_field( version, builtin_protocol_feature_t::action_return_value, true ) for version of digest with return_value + digest_type digest(uint32_t version)const { digest_type::encoder e; fc::raw::pack(e, receiver); fc::raw::pack(e, act_digest); @@ -25,11 +30,14 @@ namespace eosio { namespace chain { fc::raw::pack(e, auth_sequence); fc::raw::pack(e, code_sequence); fc::raw::pack(e, abi_sequence); - + if( has_field( version, builtin_protocol_feature_t::action_return_value ) ) { + fc::raw::pack(e, return_value); + } return e.result(); } }; } } /// namespace eosio::chain -FC_REFLECT( eosio::chain::action_receipt, (receiver)(act_digest)(global_sequence)(recv_sequence)(auth_sequence)(code_sequence)(abi_sequence) ) +FC_REFLECT( eosio::chain::action_receipt, + (receiver)(act_digest)(global_sequence)(recv_sequence)(auth_sequence)(code_sequence)(abi_sequence)(return_value) ) diff --git a/libraries/chain/include/eosio/chain/apply_context.hpp b/libraries/chain/include/eosio/chain/apply_context.hpp index 3a5889248bf..c50c10daca5 100644 --- a/libraries/chain/include/eosio/chain/apply_context.hpp +++ b/libraries/chain/include/eosio/chain/apply_context.hpp @@ -571,6 +571,7 @@ class apply_context { bool context_free = false; public: + std::vector action_return_value; generic_index idx64; generic_index idx128; generic_index idx256; diff --git a/libraries/chain/wasm_interface.cpp b/libraries/chain/wasm_interface.cpp index 8923919af7c..342aaf1edf8 100644 --- a/libraries/chain/wasm_interface.cpp +++ b/libraries/chain/wasm_interface.cpp @@ -1137,9 +1137,7 @@ class action_api : public context_aware_api { void set_action_return_value( array_ptr packed_variant, uint32_t datalen ) { datastream ds( packed_variant, datalen ); - fc::variant v; - fc::raw::unpack(ds, v); - //todo set v + fc::raw::unpack(ds, context.action_return_value); } }; diff --git a/plugins/state_history_plugin/include/eosio/state_history_plugin/state_history_serialization.hpp b/plugins/state_history_plugin/include/eosio/state_history_plugin/state_history_serialization.hpp index c1fd3f509bc..276337d155e 100644 --- a/plugins/state_history_plugin/include/eosio/state_history_plugin/state_history_serialization.hpp +++ b/plugins/state_history_plugin/include/eosio/state_history_plugin/state_history_serialization.hpp @@ -531,7 +531,11 @@ datastream& operator<<(datastream& ds, const history_serial_wrapper datastream& operator<<(datastream& ds, const history_serial_wrapper& obj) { - fc::raw::pack(ds, fc::unsigned_int(0)); + if (!obj.obj.return_value) { + fc::raw::pack( ds, fc::unsigned_int( 0 )); + } else { + fc::raw::pack( ds, fc::unsigned_int( 1 )); + } fc::raw::pack(ds, as_type(obj.obj.receiver.to_uint64_t())); fc::raw::pack(ds, as_type(obj.obj.act_digest)); fc::raw::pack(ds, as_type(obj.obj.global_sequence)); @@ -539,6 +543,9 @@ datastream& operator<<(datastream& ds, const history_serial_wrapper>(obj.obj.auth_sequence)); fc::raw::pack(ds, as_type(obj.obj.code_sequence)); fc::raw::pack(ds, as_type(obj.obj.abi_sequence)); + if (obj.obj.return_value) { + fc::raw::pack(ds, as_type>(*obj.obj.return_value)); + } return ds; } diff --git a/plugins/state_history_plugin/state_history_plugin_abi.cpp b/plugins/state_history_plugin/state_history_plugin_abi.cpp index 766c747d3d1..2e8aa9e46b2 100644 --- a/plugins/state_history_plugin/state_history_plugin_abi.cpp +++ b/plugins/state_history_plugin/state_history_plugin_abi.cpp @@ -85,6 +85,18 @@ extern const char* const state_history_plugin_abi = R"({ { "name": "abi_sequence", "type": "varuint32" } ] }, + { + "name": "action_receipt_v1", "fields": [ + { "name": "receiver", "type": "name" }, + { "name": "act_digest", "type": "checksum256" }, + { "name": "global_sequence", "type": "uint64" }, + { "name": "recv_sequence", "type": "uint64" }, + { "name": "auth_sequence", "type": "account_auth_sequence[]" }, + { "name": "code_sequence", "type": "varuint32" }, + { "name": "abi_sequence", "type": "varuint32" }, + { "name": "return_value", "type": "xxx" } + ] + }, { "name": "account_delta", "fields": [ { "name": "account", "type": "name" }, @@ -500,7 +512,7 @@ extern const char* const state_history_plugin_abi = R"({ { "name": "request", "types": ["get_status_request_v0", "get_blocks_request_v0", "get_blocks_ack_request_v0"] }, { "name": "result", "types": ["get_status_result_v0", "get_blocks_result_v0"] }, - { "name": "action_receipt", "types": ["action_receipt_v0"] }, + { "name": "action_receipt", "types": ["action_receipt_v0", "action_receipt_v1"] }, { "name": "action_trace", "types": ["action_trace_v0"] }, { "name": "partial_transaction", "types": ["partial_transaction_v0"] }, { "name": "transaction_trace", "types": ["transaction_trace_v0"] }, diff --git a/unittests/misc_tests.cpp b/unittests/misc_tests.cpp index 6e465674092..ee3c654b853 100644 --- a/unittests/misc_tests.cpp +++ b/unittests/misc_tests.cpp @@ -1110,6 +1110,22 @@ BOOST_AUTO_TEST_CASE(stable_priority_queue_test) { } FC_LOG_AND_RETHROW() } +BOOST_AUTO_TEST_CASE(action_receipt_digest) { + try { + action_receipt ar{ .receiver = eosio::name("hi"), .act_digest = fc::sha256("0101"), + .global_sequence = 3, .recv_sequence = 4, + .auth_sequence = {{eosio::name("name"), 13}}, + .code_sequence = 5, + .abi_sequence = 6 }; + auto d = digest_type::hash(ar); + uint32_t version = 0; + eosio::chain::set_field( version, builtin_protocol_feature_t::action_return_value, true ); + BOOST_REQUIRE_EQUAL( ar.digest(version), d ); + BOOST_REQUIRE_NE( ar.digest(0), d ); + + } FC_LOG_AND_RETHROW() +} + BOOST_AUTO_TEST_SUITE_END() diff --git a/unittests/protocol_feature_tests.cpp b/unittests/protocol_feature_tests.cpp index 4874d4e5354..8afede4ddad 100644 --- a/unittests/protocol_feature_tests.cpp +++ b/unittests/protocol_feature_tests.cpp @@ -1739,4 +1739,46 @@ BOOST_AUTO_TEST_CASE( wtmsig_block_signing_inflight_extension_test ) { try { } FC_LOG_AND_RETHROW() } +static const char import_set_action_return_value_wast[] = R"=====( +(module + (import "env" "set_action_return_value" (func $set_action_return_value (param i32 i32))) + (memory $0 1) + (export "apply" (func $apply)) + (func $apply (param $0 i64) (param $1 i64) (param $2 i64) + (call $set_action_return_value + (i32.const 0) + (i32.const 43) + ) + ) + (data (i32.const 8) "\01\00\00\00\00\00\85\5C\34\00\03\EB\CF\44\B4\5A\71\D4\F2\25\76\8F\60\2D\1E\2E\2B\25\EF\77\9E\E9\89\7F\E7\44\BF\1A\16\E8\54\23\D5") +) +)====="; + +BOOST_AUTO_TEST_CASE( set_action_return_value_test ) { try { + tester c( setup_policy::preactivate_feature_and_new_bios ); + + const auto& pfm = c.control->get_protocol_feature_manager(); + const auto& d = pfm.get_builtin_digest(builtin_protocol_feature_t::action_return_value); + BOOST_REQUIRE(d); + + const auto& alice_account = account_name("alice"); + c.create_accounts( {alice_account} ); + c.produce_block(); + + BOOST_CHECK_EXCEPTION( c.set_code( alice_account, import_set_action_return_value_wast ), + wasm_exception, + fc_exception_message_is( "env.set_action_return_value unresolveable" ) ); + + c.preactivate_protocol_features( {*d} ); + c.produce_block(); + + // ensure it now resolves + c.set_code( alice_account, import_set_action_return_value_wast ); + + // ensure it can be called + BOOST_REQUIRE_EQUAL(c.push_action(action({{ alice_account, permission_name("active") }}, alice_account, action_name(), {} ), alice_account.to_uint64_t()), c.success()); + + c.produce_block(); +} FC_LOG_AND_RETHROW() } + BOOST_AUTO_TEST_SUITE_END() From 16f3a199c3223723b425b2ba011d64ae89882105 Mon Sep 17 00:00:00 2001 From: Kevin Heifner Date: Fri, 13 Dec 2019 11:44:24 -0500 Subject: [PATCH 3/9] move action_return_value --- libraries/chain/apply_context.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/chain/apply_context.cpp b/libraries/chain/apply_context.cpp index 6e521d18bfc..e4620cdd59d 100644 --- a/libraries/chain/apply_context.cpp +++ b/libraries/chain/apply_context.cpp @@ -147,7 +147,7 @@ void apply_context::exec_one() uint32_t version = 0; if( control.is_builtin_activated( builtin_protocol_feature_t::action_return_value ) ) { set_field( version, builtin_protocol_feature_t::action_return_value, true ); - r.return_value.emplace( action_return_value ); + r.return_value.emplace( std::move( action_return_value ) ); } trx_context.executed_action_receipt_digests.emplace_back( r.digest( version ) ); From cb0e4d21910dca97330073458a77a681a8d1ec58 Mon Sep 17 00:00:00 2001 From: Kevin Heifner Date: Fri, 13 Dec 2019 11:44:47 -0500 Subject: [PATCH 4/9] Fix capture of return value --- libraries/chain/wasm_interface.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/libraries/chain/wasm_interface.cpp b/libraries/chain/wasm_interface.cpp index 342aaf1edf8..b31fe63d838 100644 --- a/libraries/chain/wasm_interface.cpp +++ b/libraries/chain/wasm_interface.cpp @@ -1135,9 +1135,8 @@ class action_api : public context_aware_api { return context.get_receiver(); } - void set_action_return_value( array_ptr packed_variant, uint32_t datalen ) { - datastream ds( packed_variant, datalen ); - fc::raw::unpack(ds, context.action_return_value); + void set_action_return_value( array_ptr packed_blob, uint32_t datalen ) { + context.action_return_value = std::vector( packed_blob.value, packed_blob.value + datalen ); } }; From 525e16d3af07055dc6ce8cbf7662dc1f30df4cad Mon Sep 17 00:00:00 2001 From: Kevin Heifner Date: Fri, 13 Dec 2019 14:16:55 -0500 Subject: [PATCH 5/9] Use assign --- libraries/chain/wasm_interface.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/chain/wasm_interface.cpp b/libraries/chain/wasm_interface.cpp index b31fe63d838..7ad3032177b 100644 --- a/libraries/chain/wasm_interface.cpp +++ b/libraries/chain/wasm_interface.cpp @@ -1136,7 +1136,7 @@ class action_api : public context_aware_api { } void set_action_return_value( array_ptr packed_blob, uint32_t datalen ) { - context.action_return_value = std::vector( packed_blob.value, packed_blob.value + datalen ); + context.action_return_value.assign( packed_blob.value, packed_blob.value + datalen ); } }; From c8ab34b8459444ce7ceac466bc11b0f09ee08b8c Mon Sep 17 00:00:00 2001 From: Kevin Heifner Date: Fri, 13 Dec 2019 14:18:00 -0500 Subject: [PATCH 6/9] Add tests for set_action_return_value of various types --- unittests/api_tests.cpp | 53 ++++++++++++++++--- .../test-contracts/test_api/test_action.cpp | 16 ++++++ 2 files changed, 62 insertions(+), 7 deletions(-) diff --git a/unittests/api_tests.cpp b/unittests/api_tests.cpp index 7f40f291ef2..096180ab013 100644 --- a/unittests/api_tests.cpp +++ b/unittests/api_tests.cpp @@ -3,7 +3,6 @@ #include #include #include -#include #include #include @@ -22,19 +21,13 @@ #include #include #include -#include #include #include -#include #include #include #include -#include -#include -#include -#include #include #include @@ -591,6 +584,10 @@ BOOST_AUTO_TEST_CASE(ram_billing_in_notify_tests) { try { fc::temp_directory tempdir; validating_tester chain( tempdir, true ); chain.execute_setup_policy( setup_policy::preactivate_feature_and_new_bios ); + const auto& pfm = chain.control->get_protocol_feature_manager(); + const auto& d = pfm.get_builtin_digest(builtin_protocol_feature_t::action_return_value); // testapi requires this + BOOST_REQUIRE(d); + chain.preactivate_protocol_features( {*d} ); chain.produce_blocks(2); chain.create_account( N(testapi) ); @@ -2356,6 +2353,8 @@ BOOST_FIXTURE_TEST_CASE(action_ordinal_test, TESTER) { try { BOOST_REQUIRE_EQUAL(atrace[0].act.account, N(testapi)); BOOST_REQUIRE_EQUAL(atrace[0].act.name, TEST_METHOD("test_action", "test_action_ordinal1")); BOOST_REQUIRE_EQUAL(atrace[0].receipt.valid(), true); + BOOST_REQUIRE_EQUAL(atrace[0].receipt->return_value.valid(), true); + BOOST_REQUIRE_EQUAL(fc::raw::unpack(*atrace[0].receipt->return_value), unsigned_int(1) ); int start_gseq = atrace[0].receipt->global_sequence; BOOST_REQUIRE_EQUAL((int)atrace[1].action_ordinal,2); @@ -2365,6 +2364,8 @@ BOOST_FIXTURE_TEST_CASE(action_ordinal_test, TESTER) { try { BOOST_REQUIRE_EQUAL(atrace[1].act.account, N(testapi)); BOOST_REQUIRE_EQUAL(atrace[1].act.name, TEST_METHOD("test_action", "test_action_ordinal1")); BOOST_REQUIRE_EQUAL(atrace[1].receipt.valid(), true); + BOOST_REQUIRE_EQUAL(atrace[1].receipt->return_value.valid(), true); + BOOST_REQUIRE_EQUAL(fc::raw::unpack(*atrace[1].receipt->return_value), "bob" ); BOOST_REQUIRE_EQUAL(atrace[1].receipt->global_sequence, start_gseq + 1); BOOST_REQUIRE_EQUAL((int)atrace[2].action_ordinal, 3); @@ -2374,6 +2375,8 @@ BOOST_FIXTURE_TEST_CASE(action_ordinal_test, TESTER) { try { BOOST_REQUIRE_EQUAL(atrace[2].act.account, N(testapi)); BOOST_REQUIRE_EQUAL(atrace[2].act.name, TEST_METHOD("test_action", "test_action_ordinal2")); BOOST_REQUIRE_EQUAL(atrace[2].receipt.valid(), true); + BOOST_REQUIRE_EQUAL(atrace[2].receipt->return_value.valid(), true); + BOOST_REQUIRE_EQUAL(fc::raw::unpack(*atrace[2].receipt->return_value), name("five") ); BOOST_REQUIRE_EQUAL(atrace[2].receipt->global_sequence, start_gseq + 4); BOOST_REQUIRE_EQUAL((int)atrace[3].action_ordinal, 4); @@ -2383,6 +2386,8 @@ BOOST_FIXTURE_TEST_CASE(action_ordinal_test, TESTER) { try { BOOST_REQUIRE_EQUAL(atrace[3].act.account, N(testapi)); BOOST_REQUIRE_EQUAL(atrace[3].act.name, TEST_METHOD("test_action", "test_action_ordinal3")); BOOST_REQUIRE_EQUAL(atrace[3].receipt.valid(), true); + BOOST_REQUIRE_EQUAL(atrace[3].receipt->return_value.valid(), true); + BOOST_REQUIRE_EQUAL(fc::raw::unpack(*atrace[3].receipt->return_value), unsigned_int(9) ); BOOST_REQUIRE_EQUAL(atrace[3].receipt->global_sequence, start_gseq + 8); BOOST_REQUIRE_EQUAL((int)atrace[4].action_ordinal, 5); @@ -2392,6 +2397,8 @@ BOOST_FIXTURE_TEST_CASE(action_ordinal_test, TESTER) { try { BOOST_REQUIRE_EQUAL(atrace[4].act.account, N(testapi)); BOOST_REQUIRE_EQUAL(atrace[4].act.name, TEST_METHOD("test_action", "test_action_ordinal1")); BOOST_REQUIRE_EQUAL(atrace[4].receipt.valid(), true); + BOOST_REQUIRE_EQUAL(atrace[4].receipt->return_value.valid(), true); + BOOST_REQUIRE_EQUAL(fc::raw::unpack(*atrace[4].receipt->return_value), "charlie" ); BOOST_REQUIRE_EQUAL(atrace[4].receipt->global_sequence, start_gseq + 2); BOOST_REQUIRE_EQUAL((int)atrace[5].action_ordinal, 6); @@ -2401,6 +2408,8 @@ BOOST_FIXTURE_TEST_CASE(action_ordinal_test, TESTER) { try { BOOST_REQUIRE_EQUAL(atrace[5].act.account, N(bob)); BOOST_REQUIRE_EQUAL(atrace[5].act.name, TEST_METHOD("test_action", "test_action_ordinal_foo")); BOOST_REQUIRE_EQUAL(atrace[5].receipt.valid(), true); + BOOST_REQUIRE_EQUAL(atrace[5].receipt->return_value.valid(), true); + BOOST_REQUIRE_EQUAL(fc::raw::unpack(*atrace[5].receipt->return_value), 13.23 ); BOOST_REQUIRE_EQUAL(atrace[5].receipt->global_sequence, start_gseq + 9); BOOST_REQUIRE_EQUAL((int)atrace[6].action_ordinal, 7); @@ -2410,6 +2419,8 @@ BOOST_FIXTURE_TEST_CASE(action_ordinal_test, TESTER) { try { BOOST_REQUIRE_EQUAL(atrace[6].act.account, N(testapi)); BOOST_REQUIRE_EQUAL(atrace[6].act.name, TEST_METHOD("test_action", "test_action_ordinal1")); BOOST_REQUIRE_EQUAL(atrace[6].receipt.valid(), true); + BOOST_REQUIRE_EQUAL(atrace[6].receipt->return_value.valid(), true); + BOOST_REQUIRE_EQUAL(fc::raw::unpack(*atrace[6].receipt->return_value), "david" ); BOOST_REQUIRE_EQUAL(atrace[6].receipt->global_sequence, start_gseq + 3); BOOST_REQUIRE_EQUAL((int)atrace[7].action_ordinal, 8); @@ -2419,6 +2430,8 @@ BOOST_FIXTURE_TEST_CASE(action_ordinal_test, TESTER) { try { BOOST_REQUIRE_EQUAL(atrace[7].act.account, N(charlie)); BOOST_REQUIRE_EQUAL(atrace[7].act.name, TEST_METHOD("test_action", "test_action_ordinal_bar")); BOOST_REQUIRE_EQUAL(atrace[7].receipt.valid(), true); + BOOST_REQUIRE_EQUAL(atrace[7].receipt->return_value.valid(), true); + BOOST_REQUIRE_EQUAL(fc::raw::unpack(*atrace[7].receipt->return_value), 11.42f ); BOOST_REQUIRE_EQUAL(atrace[7].receipt->global_sequence, start_gseq + 10); BOOST_REQUIRE_EQUAL((int)atrace[8].action_ordinal, 9); @@ -2428,6 +2441,8 @@ BOOST_FIXTURE_TEST_CASE(action_ordinal_test, TESTER) { try { BOOST_REQUIRE_EQUAL(atrace[8].act.account, N(testapi)); BOOST_REQUIRE_EQUAL(atrace[8].act.name, TEST_METHOD("test_action", "test_action_ordinal2")); BOOST_REQUIRE_EQUAL(atrace[8].receipt.valid(), true); + BOOST_REQUIRE_EQUAL(atrace[8].receipt->return_value.valid(), true); + BOOST_REQUIRE_EQUAL(fc::raw::unpack(*atrace[8].receipt->return_value), true ); BOOST_REQUIRE_EQUAL(atrace[8].receipt->global_sequence, start_gseq + 5); BOOST_REQUIRE_EQUAL((int)atrace[9].action_ordinal, 10); @@ -2437,6 +2452,8 @@ BOOST_FIXTURE_TEST_CASE(action_ordinal_test, TESTER) { try { BOOST_REQUIRE_EQUAL(atrace[9].act.account, N(testapi)); BOOST_REQUIRE_EQUAL(atrace[9].act.name, TEST_METHOD("test_action", "test_action_ordinal2")); BOOST_REQUIRE_EQUAL(atrace[9].receipt.valid(), true); + BOOST_REQUIRE_EQUAL(atrace[9].receipt->return_value.valid(), true); + BOOST_REQUIRE_EQUAL(fc::raw::unpack(*atrace[9].receipt->return_value), signed_int(7) ); BOOST_REQUIRE_EQUAL(atrace[9].receipt->global_sequence, start_gseq + 6); BOOST_REQUIRE_EQUAL((int)atrace[10].action_ordinal, 11); @@ -2446,6 +2463,8 @@ BOOST_FIXTURE_TEST_CASE(action_ordinal_test, TESTER) { try { BOOST_REQUIRE_EQUAL(atrace[10].act.account, N(testapi)); BOOST_REQUIRE_EQUAL(atrace[10].act.name, TEST_METHOD("test_action", "test_action_ordinal4")); BOOST_REQUIRE_EQUAL(atrace[10].receipt.valid(), true); + BOOST_REQUIRE_EQUAL(atrace[10].receipt->return_value.valid(), true); // return value not set is still a return value, it is just empty + BOOST_REQUIRE_EQUAL(atrace[10].receipt->return_value->size(), 0 ); // state_history_plugin keys off presence of return_value for version of receipt BOOST_REQUIRE_EQUAL(atrace[10].receipt->global_sequence, start_gseq + 7); } FC_LOG_AND_RETHROW() } @@ -2561,6 +2580,8 @@ BOOST_FIXTURE_TEST_CASE(action_ordinal_failtest2, TESTER) { try { BOOST_REQUIRE_EQUAL(atrace[0].act.account, N(testapi)); BOOST_REQUIRE_EQUAL(atrace[0].act.name, TEST_METHOD("test_action", "test_action_ordinal1")); BOOST_REQUIRE_EQUAL(atrace[0].receipt.valid(), true); + BOOST_REQUIRE_EQUAL(atrace[0].receipt->return_value.valid(), true); + BOOST_REQUIRE_EQUAL(fc::raw::unpack(*atrace[0].receipt->return_value), unsigned_int(1) ); BOOST_REQUIRE_EQUAL(atrace[0].except.valid(), false); int start_gseq = atrace[0].receipt->global_sequence; @@ -2572,6 +2593,8 @@ BOOST_FIXTURE_TEST_CASE(action_ordinal_failtest2, TESTER) { try { BOOST_REQUIRE_EQUAL(atrace[1].act.account, N(testapi)); BOOST_REQUIRE_EQUAL(atrace[1].act.name, TEST_METHOD("test_action", "test_action_ordinal1")); BOOST_REQUIRE_EQUAL(atrace[1].receipt.valid(), true); + BOOST_REQUIRE_EQUAL(atrace[1].receipt->return_value.valid(), true); + BOOST_REQUIRE_EQUAL(fc::raw::unpack(*atrace[1].receipt->return_value), "bob" ); BOOST_REQUIRE_EQUAL(atrace[1].receipt->global_sequence, start_gseq + 1); // not executed @@ -2680,6 +2703,8 @@ BOOST_FIXTURE_TEST_CASE(action_ordinal_failtest3, TESTER) { try { BOOST_REQUIRE_EQUAL(atrace[0].act.account, N(testapi)); BOOST_REQUIRE_EQUAL(atrace[0].act.name, TEST_METHOD("test_action", "test_action_ordinal1")); BOOST_REQUIRE_EQUAL(atrace[0].receipt.valid(), true); + BOOST_REQUIRE_EQUAL(atrace[0].receipt->return_value.valid(), true); + BOOST_REQUIRE_EQUAL(fc::raw::unpack(*atrace[0].receipt->return_value), unsigned_int(1) ); BOOST_REQUIRE_EQUAL(atrace[0].except.valid(), false); int start_gseq = atrace[0].receipt->global_sequence; @@ -2691,6 +2716,8 @@ BOOST_FIXTURE_TEST_CASE(action_ordinal_failtest3, TESTER) { try { BOOST_REQUIRE_EQUAL(atrace[1].act.account, N(testapi)); BOOST_REQUIRE_EQUAL(atrace[1].act.name, TEST_METHOD("test_action", "test_action_ordinal1")); BOOST_REQUIRE_EQUAL(atrace[1].receipt.valid(), true); + BOOST_REQUIRE_EQUAL(atrace[1].receipt->return_value.valid(), true); + BOOST_REQUIRE_EQUAL(fc::raw::unpack(*atrace[1].receipt->return_value), "bob" ); BOOST_REQUIRE_EQUAL(atrace[1].receipt->global_sequence, start_gseq + 1); // executed @@ -2701,6 +2728,8 @@ BOOST_FIXTURE_TEST_CASE(action_ordinal_failtest3, TESTER) { try { BOOST_REQUIRE_EQUAL(atrace[2].act.account, N(testapi)); BOOST_REQUIRE_EQUAL(atrace[2].act.name, TEST_METHOD("test_action", "test_action_ordinal2")); BOOST_REQUIRE_EQUAL(atrace[2].receipt.valid(), true); + BOOST_REQUIRE_EQUAL(atrace[2].receipt->return_value.valid(), true); + BOOST_REQUIRE_EQUAL(fc::raw::unpack(*atrace[2].receipt->return_value), name("five") ); BOOST_REQUIRE_EQUAL(atrace[2].receipt->global_sequence, start_gseq + 4); // fails here @@ -2722,6 +2751,8 @@ BOOST_FIXTURE_TEST_CASE(action_ordinal_failtest3, TESTER) { try { BOOST_REQUIRE_EQUAL(atrace[4].act.account, N(testapi)); BOOST_REQUIRE_EQUAL(atrace[4].act.name, TEST_METHOD("test_action", "test_action_ordinal1")); BOOST_REQUIRE_EQUAL(atrace[4].receipt.valid(), true); + BOOST_REQUIRE_EQUAL(atrace[4].receipt->return_value.valid(), true); + BOOST_REQUIRE_EQUAL(fc::raw::unpack(*atrace[4].receipt->return_value), "charlie" ); BOOST_REQUIRE_EQUAL(atrace[4].receipt->global_sequence, start_gseq + 2); // not executed @@ -2742,6 +2773,8 @@ BOOST_FIXTURE_TEST_CASE(action_ordinal_failtest3, TESTER) { try { BOOST_REQUIRE_EQUAL(atrace[6].act.account, N(testapi)); BOOST_REQUIRE_EQUAL(atrace[6].act.name, TEST_METHOD("test_action", "test_action_ordinal1")); BOOST_REQUIRE_EQUAL(atrace[6].receipt.valid(), true); + BOOST_REQUIRE_EQUAL(atrace[6].receipt->return_value.valid(), true); + BOOST_REQUIRE_EQUAL(fc::raw::unpack(*atrace[6].receipt->return_value), "david" ); BOOST_REQUIRE_EQUAL(atrace[6].receipt->global_sequence, start_gseq + 3); // not executed @@ -2762,6 +2795,8 @@ BOOST_FIXTURE_TEST_CASE(action_ordinal_failtest3, TESTER) { try { BOOST_REQUIRE_EQUAL(atrace[8].act.account, N(testapi)); BOOST_REQUIRE_EQUAL(atrace[8].act.name, TEST_METHOD("test_action", "test_action_ordinal2")); BOOST_REQUIRE_EQUAL(atrace[8].receipt.valid(), true); + BOOST_REQUIRE_EQUAL(atrace[8].receipt->return_value.valid(), true); + BOOST_REQUIRE_EQUAL(fc::raw::unpack(*atrace[8].receipt->return_value), true ); BOOST_REQUIRE_EQUAL(atrace[8].receipt->global_sequence, start_gseq + 5); // executed @@ -2772,6 +2807,8 @@ BOOST_FIXTURE_TEST_CASE(action_ordinal_failtest3, TESTER) { try { BOOST_REQUIRE_EQUAL(atrace[9].act.account, N(testapi)); BOOST_REQUIRE_EQUAL(atrace[9].act.name, TEST_METHOD("test_action", "test_action_ordinal2")); BOOST_REQUIRE_EQUAL(atrace[9].receipt.valid(), true); + BOOST_REQUIRE_EQUAL(atrace[9].receipt->return_value.valid(), true); + BOOST_REQUIRE_EQUAL(fc::raw::unpack(*atrace[9].receipt->return_value), signed_int(7) ); BOOST_REQUIRE_EQUAL(atrace[9].receipt->global_sequence, start_gseq + 6); // executed @@ -2782,6 +2819,8 @@ BOOST_FIXTURE_TEST_CASE(action_ordinal_failtest3, TESTER) { try { BOOST_REQUIRE_EQUAL(atrace[10].act.account, N(testapi)); BOOST_REQUIRE_EQUAL(atrace[10].act.name, TEST_METHOD("test_action", "test_action_ordinal4")); BOOST_REQUIRE_EQUAL(atrace[10].receipt.valid(), true); + BOOST_REQUIRE_EQUAL(atrace[10].receipt->return_value.valid(), true); + BOOST_REQUIRE_EQUAL(atrace[10].receipt->return_value->size(), 0 ); BOOST_REQUIRE_EQUAL(atrace[10].receipt->global_sequence, start_gseq + 7); } FC_LOG_AND_RETHROW() } diff --git a/unittests/test-contracts/test_api/test_action.cpp b/unittests/test-contracts/test_api/test_action.cpp index 1b20249fc0e..648f9780b02 100644 --- a/unittests/test-contracts/test_api/test_action.cpp +++ b/unittests/test-contracts/test_api/test_action.cpp @@ -10,6 +10,11 @@ #include "test_api.hpp" +extern "C" { + __attribute__((eosio_wasm_import)) + void set_action_return_value(const char*, size_t); +} + using namespace eosio; void test_action::read_action_normal() { @@ -276,6 +281,7 @@ void test_action::test_action_ordinal1(uint64_t receiver, uint64_t code, uint64_ std::tuple<>()); act2.send(); // -> exec 9 + set_action_return_value( &eosio::pack(unsigned_int(1))[0], eosio::pack_size(unsigned_int(1)) ); eosio::require_recipient( "charlie"_n ); // -> exec 3 which would then cause execution of 11 } else if (receiver == "bob"_n.value) { @@ -285,6 +291,7 @@ void test_action::test_action_ordinal1(uint64_t receiver, uint64_t code, uint64_ std::tuple<>()); act1.send(); // -> exec 10 + set_action_return_value( &eosio::pack(std::string("bob"))[0], eosio::pack_size(std::string("bob")) ); eosio::require_recipient( "david"_n ); // -> exec 4 } else if (receiver == "charlie"_n.value) { print("exec 3"); @@ -293,12 +300,14 @@ void test_action::test_action_ordinal1(uint64_t receiver, uint64_t code, uint64_ std::tuple<>()); // exec 11 act1.send(); + set_action_return_value( &eosio::pack(std::string("charlie"))[0], eosio::pack_size(std::string("charlie")) ); if (is_account("fail3"_n)) { eosio_assert(false, "fail at point 3"); } } else if (receiver == "david"_n.value) { print("exec 4"); + set_action_return_value( &eosio::pack(std::string("david"))[0], eosio::pack_size(std::string("david")) ); } else { eosio_assert(false, "assert failed at test_action::test_action_ordinal1"); } @@ -314,16 +323,20 @@ void test_action::test_action_ordinal2(uint64_t receiver, uint64_t code, uint64_ name(WASM_TEST_ACTION("test_action", "test_action_ordinal4")), std::tuple<>()); act1.send(); // -> exec 8 + set_action_return_value( &eosio::pack("five"_n)[0], eosio::pack_size("five"_n) ); } else if (receiver == "david"_n.value) { print("exec 6"); + set_action_return_value( &eosio::pack(true)[0], eosio::pack_size(true) ); } else if (receiver == "erin"_n.value) { print("exec 7"); + set_action_return_value( &eosio::pack(signed_int(7))[0], eosio::pack_size(signed_int(7)) ); } else { eosio_assert(false, "assert failed at test_action::test_action_ordinal2"); } } void test_action::test_action_ordinal4(uint64_t receiver, uint64_t code, uint64_t action) { print("exec 8"); + // no set_action_return_value } void test_action::test_action_ordinal3(uint64_t receiver, uint64_t code, uint64_t action) { print("exec 9"); @@ -331,10 +344,13 @@ void test_action::test_action_ordinal3(uint64_t receiver, uint64_t code, uint64_ if (is_account("failnine"_n)) { eosio_assert(false, "fail at point 9"); } + set_action_return_value( &eosio::pack(unsigned_int(9))[0], eosio::pack_size(unsigned_int(9)) ); } void test_action::test_action_ordinal_foo(uint64_t receiver, uint64_t code, uint64_t action) { print("exec 10"); + set_action_return_value( &eosio::pack(13.23)[0], eosio::pack_size(13.23) ); } void test_action::test_action_ordinal_bar(uint64_t receiver, uint64_t code, uint64_t action) { print("exec 11"); + set_action_return_value( &eosio::pack(11.42f)[0], eosio::pack_size(11.42f) ); } From dcfd4ff6150bbb6cd581e2e79c980c1125e9c749 Mon Sep 17 00:00:00 2001 From: Kevin Heifner Date: Fri, 13 Dec 2019 17:04:25 -0500 Subject: [PATCH 7/9] Update action_receipt.return_value to be bytes --- .../eosio/state_history_plugin/state_history_serialization.hpp | 2 +- plugins/state_history_plugin/state_history_plugin_abi.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/state_history_plugin/include/eosio/state_history_plugin/state_history_serialization.hpp b/plugins/state_history_plugin/include/eosio/state_history_plugin/state_history_serialization.hpp index 276337d155e..df5832f066d 100644 --- a/plugins/state_history_plugin/include/eosio/state_history_plugin/state_history_serialization.hpp +++ b/plugins/state_history_plugin/include/eosio/state_history_plugin/state_history_serialization.hpp @@ -544,7 +544,7 @@ datastream& operator<<(datastream& ds, const history_serial_wrapper(obj.obj.code_sequence)); fc::raw::pack(ds, as_type(obj.obj.abi_sequence)); if (obj.obj.return_value) { - fc::raw::pack(ds, as_type>(*obj.obj.return_value)); + fc::raw::pack(ds, as_type(*obj.obj.return_value)); } return ds; } diff --git a/plugins/state_history_plugin/state_history_plugin_abi.cpp b/plugins/state_history_plugin/state_history_plugin_abi.cpp index 2e8aa9e46b2..a63b1b2fca7 100644 --- a/plugins/state_history_plugin/state_history_plugin_abi.cpp +++ b/plugins/state_history_plugin/state_history_plugin_abi.cpp @@ -94,7 +94,7 @@ extern const char* const state_history_plugin_abi = R"({ { "name": "auth_sequence", "type": "account_auth_sequence[]" }, { "name": "code_sequence", "type": "varuint32" }, { "name": "abi_sequence", "type": "varuint32" }, - { "name": "return_value", "type": "xxx" } + { "name": "return_value", "type": "bytes" } ] }, { From 12735301012910d5335f26c180952aaffa412b81 Mon Sep 17 00:00:00 2001 From: Kevin Heifner Date: Mon, 16 Dec 2019 12:16:06 -0600 Subject: [PATCH 8/9] Update test_api.wasm for modified test_api to support not building contracts for test --- .../test-contracts/test_api/test_api.wasm | Bin 70317 -> 73020 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/unittests/test-contracts/test_api/test_api.wasm b/unittests/test-contracts/test_api/test_api.wasm index 5fd5ff870c31a5c1f981d91ba652ec3261e0982d..9f213362e17278970c101a71308b66674e534f4a 100755 GIT binary patch delta 15231 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 V{Dcg7&)kfOB~*}Pi!w}-{ue1E3_Jh; delta 12579 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 From d71e541005a0594d65d463d28f029d4ec12213cb Mon Sep 17 00:00:00 2001 From: Kevin Heifner Date: Mon, 16 Dec 2019 16:15:41 -0600 Subject: [PATCH 9/9] Use set_field correctly --- libraries/chain/apply_context.cpp | 2 +- unittests/misc_tests.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/libraries/chain/apply_context.cpp b/libraries/chain/apply_context.cpp index e4620cdd59d..1afba333342 100644 --- a/libraries/chain/apply_context.cpp +++ b/libraries/chain/apply_context.cpp @@ -146,7 +146,7 @@ void apply_context::exec_one() uint32_t version = 0; if( control.is_builtin_activated( builtin_protocol_feature_t::action_return_value ) ) { - set_field( version, builtin_protocol_feature_t::action_return_value, true ); + version = set_field( version, builtin_protocol_feature_t::action_return_value, true ); r.return_value.emplace( std::move( action_return_value ) ); } diff --git a/unittests/misc_tests.cpp b/unittests/misc_tests.cpp index ee3c654b853..12fe5ee93ae 100644 --- a/unittests/misc_tests.cpp +++ b/unittests/misc_tests.cpp @@ -1119,7 +1119,7 @@ BOOST_AUTO_TEST_CASE(action_receipt_digest) { .abi_sequence = 6 }; auto d = digest_type::hash(ar); uint32_t version = 0; - eosio::chain::set_field( version, builtin_protocol_feature_t::action_return_value, true ); + version = eosio::chain::set_field( version, builtin_protocol_feature_t::action_return_value, true ); BOOST_REQUIRE_EQUAL( ar.digest(version), d ); BOOST_REQUIRE_NE( ar.digest(0), d );