Skip to content

Commit ae430b4

Browse files
committed
Pass abi serialization max time to abi_serializer constructor.
1 parent 2284d35 commit ae430b4

25 files changed

+103
-101
lines changed

libraries/abi_generator/abi_generator.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -318,7 +318,7 @@ bool abi_generator::is_string(const string& type) {
318318
}
319319

320320
void abi_generator::get_all_fields(const struct_def& s, vector<field_def>& fields) {
321-
abi_serializer abis(*output);
321+
abi_serializer abis(*output, fc::seconds(1)); // No risk to client side serialization taking a long time
322322

323323
for(const auto& field : s.fields) {
324324
fields.push_back(field);

libraries/chain/abi_serializer.cpp

+15-14
Original file line numberDiff line numberDiff line change
@@ -49,9 +49,9 @@ namespace eosio { namespace chain {
4949
);
5050
}
5151

52-
abi_serializer::abi_serializer( const abi_def& abi ) {
52+
abi_serializer::abi_serializer( const abi_def& abi, const fc::microseconds& max_serialization_time ) {
5353
configure_built_in_types();
54-
set_abi(abi);
54+
set_abi(abi, max_serialization_time);
5555
}
5656

5757
void abi_serializer::configure_built_in_types() {
@@ -97,7 +97,8 @@ namespace eosio { namespace chain {
9797
built_in_types.emplace("extended_asset", pack_unpack<extended_asset>());
9898
}
9999

100-
void abi_serializer::set_abi(const abi_def& abi) {
100+
void abi_serializer::set_abi(const abi_def& abi, const fc::microseconds& max_serialization_time) {
101+
const fc::time_point deadline = fc::time_point::now() + max_serialization_time;
101102
typedefs.clear();
102103
structs.clear();
103104
actions.clear();
@@ -108,8 +109,8 @@ namespace eosio { namespace chain {
108109
structs[st.name] = st;
109110

110111
for( const auto& td : abi.types ) {
111-
FC_ASSERT(is_type(td.type), "invalid type", ("type",td.type));
112-
FC_ASSERT(!is_type(td.new_type_name), "type already exists", ("new_type_name",td.new_type_name));
112+
FC_ASSERT(_is_type(td.type, 0, deadline, max_serialization_time), "invalid type", ("type",td.type));
113+
FC_ASSERT(!_is_type(td.new_type_name, 0, deadline, max_serialization_time), "type already exists", ("new_type_name",td.new_type_name));
113114
typedefs[td.new_type_name] = td.type;
114115
}
115116

@@ -132,7 +133,7 @@ namespace eosio { namespace chain {
132133
FC_ASSERT( tables.size() == abi.tables.size() );
133134
FC_ASSERT( error_messages.size() == abi.error_messages.size() );
134135

135-
validate();
136+
validate(max_serialization_time);
136137
}
137138

138139
bool abi_serializer::is_builtin_type(const type_name& type)const {
@@ -176,12 +177,12 @@ namespace eosio { namespace chain {
176177
}
177178
}
178179

179-
bool abi_serializer::_is_type(const type_name& rtype, size_t recursion_depth, const fc::time_point& deadline)const {
180+
bool abi_serializer::_is_type(const type_name& rtype, size_t recursion_depth, const fc::time_point& deadline, const fc::microseconds& max_serialization_time)const {
180181
FC_ASSERT( fc::time_point::now() < deadline, "serialization time limit ${t}us exceeded", ("t", max_serialization_time) );
181182
if( ++recursion_depth > max_recursion_depth) return false;
182183
auto type = fundamental_type(rtype);
183184
if( built_in_types.find(type) != built_in_types.end() ) return true;
184-
if( typedefs.find(type) != typedefs.end() ) return _is_type(typedefs.find(type)->second, recursion_depth, deadline);
185+
if( typedefs.find(type) != typedefs.end() ) return _is_type(typedefs.find(type)->second, recursion_depth, deadline, max_serialization_time);
185186
if( structs.find(type) != structs.end() ) return true;
186187
return false;
187188
}
@@ -192,7 +193,7 @@ namespace eosio { namespace chain {
192193
return itr->second;
193194
}
194195

195-
void abi_serializer::validate()const {
196+
void abi_serializer::validate(const fc::microseconds& max_serialization_time)const {
196197
const fc::time_point deadline = fc::time_point::now() + max_serialization_time;
197198
for( const auto& t : typedefs ) { try {
198199
vector<type_name> types_seen{t.first, t.second};
@@ -205,7 +206,7 @@ namespace eosio { namespace chain {
205206
}
206207
} FC_CAPTURE_AND_RETHROW( (t) ) }
207208
for( const auto& t : typedefs ) { try {
208-
FC_ASSERT(is_type(t.second), "", ("type",t.second) );
209+
FC_ASSERT(_is_type(t.second, 0, deadline, max_serialization_time), "", ("type",t.second) );
209210
} FC_CAPTURE_AND_RETHROW( (t) ) }
210211
for( const auto& s : structs ) { try {
211212
if( s.second.base != type_name() ) {
@@ -221,17 +222,17 @@ namespace eosio { namespace chain {
221222
}
222223
for( const auto& field : s.second.fields ) { try {
223224
FC_ASSERT( fc::time_point::now() < deadline, "serialization time limit ${t}us exceeded", ("t", max_serialization_time) );
224-
FC_ASSERT(is_type(field.type) );
225+
FC_ASSERT(_is_type(field.type, 0, deadline, max_serialization_time) );
225226
} FC_CAPTURE_AND_RETHROW( (field) ) }
226227
} FC_CAPTURE_AND_RETHROW( (s) ) }
227228
for( const auto& a : actions ) { try {
228229
FC_ASSERT( fc::time_point::now() < deadline, "serialization time limit ${t}us exceeded", ("t", max_serialization_time) );
229-
FC_ASSERT(is_type(a.second), "", ("type",a.second) );
230+
FC_ASSERT(_is_type(a.second, 0, deadline, max_serialization_time), "", ("type",a.second) );
230231
} FC_CAPTURE_AND_RETHROW( (a) ) }
231232

232233
for( const auto& t : tables ) { try {
233234
FC_ASSERT( fc::time_point::now() < deadline, "serialization time limit ${t}us exceeded", ("t", max_serialization_time) );
234-
FC_ASSERT(is_type(t.second), "", ("type",t.second) );
235+
FC_ASSERT(_is_type(t.second, 0, deadline, max_serialization_time), "", ("type",t.second) );
235236
} FC_CAPTURE_AND_RETHROW( (t) ) }
236237
}
237238

@@ -369,7 +370,7 @@ namespace eosio { namespace chain {
369370
{ try {
370371
FC_ASSERT( ++recursion_depth < max_recursion_depth, "recursive definition, max_recursion_depth ${r} ", ("r", max_recursion_depth) );
371372
FC_ASSERT( fc::time_point::now() < deadline, "serialization time limit ${t}us exceeded", ("t", max_serialization_time) );
372-
if( !is_type(type) ) {
373+
if( !_is_type(type, recursion_depth, deadline, max_serialization_time) ) {
373374
return var.as<bytes>();
374375
}
375376

libraries/chain/include/eosio/chain/abi_serializer.hpp

+7-7
Original file line numberDiff line numberDiff line change
@@ -27,16 +27,14 @@ namespace impl {
2727
*/
2828
struct abi_serializer {
2929
abi_serializer(){ configure_built_in_types(); }
30-
explicit abi_serializer( const abi_def& abi );
31-
void set_abi(const abi_def& abi);
32-
33-
void validate()const;
30+
abi_serializer( const abi_def& abi, const fc::microseconds& max_serialization_time );
31+
void set_abi(const abi_def& abi, const fc::microseconds& max_serialization_time);
3432

3533
type_name resolve_type(const type_name& t)const;
3634
bool is_array(const type_name& type)const;
3735
bool is_optional(const type_name& type)const;
38-
bool is_type(const type_name& type)const {
39-
return _is_type(type, 0, fc::time_point::now() + max_serialization_time);
36+
bool is_type(const type_name& type, const fc::microseconds& max_serialization_time)const {
37+
return _is_type(type, 0, fc::time_point::now() + max_serialization_time, max_serialization_time);
4038
}
4139
bool is_builtin_type(const type_name& type)const;
4240
bool is_integer(const type_name& type) const;
@@ -117,7 +115,9 @@ struct abi_serializer {
117115
void _binary_to_variant(const type_name& type, fc::datastream<const char*>& stream, fc::mutable_variant_object& obj,
118116
size_t recursion_depth, const fc::time_point& deadline, const fc::microseconds& max_serialization_time)const;
119117

120-
bool _is_type(const type_name& type, size_t recursion_depth, const fc::time_point& deadline)const;
118+
bool _is_type(const type_name& type, size_t recursion_depth, const fc::time_point& deadline, const fc::microseconds& max_serialization_time)const;
119+
120+
void validate(const fc::microseconds& max_serialization_time)const;
121121

122122
friend struct impl::abi_from_variant;
123123
friend struct impl::abi_to_variant;

libraries/chain/include/eosio/chain/controller.hpp

+5-3
Original file line numberDiff line numberDiff line change
@@ -219,13 +219,13 @@ namespace eosio { namespace chain {
219219
wasm_interface& get_wasm_interface();
220220

221221

222-
optional<abi_serializer> get_abi_serializer( account_name n )const {
222+
optional<abi_serializer> get_abi_serializer( account_name n, const fc::microseconds& max_serialization_time )const {
223223
if( n.good() ) {
224224
try {
225225
const auto& a = get_account( n );
226226
abi_def abi;
227227
if( abi_serializer::to_abi( a.abi, abi ))
228-
return abi_serializer( abi );
228+
return abi_serializer( abi, max_serialization_time );
229229
} FC_CAPTURE_AND_LOG((n))
230230
}
231231
return optional<abi_serializer>();
@@ -234,7 +234,9 @@ namespace eosio { namespace chain {
234234
template<typename T>
235235
fc::variant to_variant_with_abi( const T& obj, const fc::microseconds& max_serialization_time ) {
236236
fc::variant pretty_output;
237-
abi_serializer::to_variant( obj, pretty_output, [&]( account_name n ){ return get_abi_serializer( n ); }, max_serialization_time);
237+
abi_serializer::to_variant( obj, pretty_output,
238+
[&]( account_name n ){ return get_abi_serializer( n, max_serialization_time ); },
239+
max_serialization_time);
238240
return pretty_output;
239241
}
240242

libraries/testing/include/eosio/testing/tester.hpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -229,7 +229,7 @@ namespace eosio { namespace testing {
229229
const auto& accnt = control->db().get<account_object, by_name>( name );
230230
abi_def abi;
231231
if( abi_serializer::to_abi( accnt.abi, abi )) {
232-
return abi_serializer( abi );
232+
return abi_serializer( abi, abi_serializer_max_time );
233233
}
234234
return optional<abi_serializer>();
235235
} FC_RETHROW_EXCEPTIONS( error, "Failed to find or parse ABI for ${name}", ("name", name))

libraries/testing/tester.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -428,7 +428,7 @@ namespace eosio { namespace testing {
428428
const variant_object& data )const { try {
429429
const auto& acnt = control->get_account(code);
430430
auto abi = acnt.get_abi();
431-
chain::abi_serializer abis(abi);
431+
chain::abi_serializer abis(abi, abi_serializer_max_time);
432432
// auto a = control->get_account(code).get_abi();
433433

434434
string action_type_name = abis.get_action_type(acttype);

plugins/chain_plugin/chain_plugin.cpp

+13-13
Original file line numberDiff line numberDiff line change
@@ -910,7 +910,7 @@ static fc::variant get_global_row( const database& db, const abi_def& abi, const
910910
read_only::get_producers_result read_only::get_producers( const read_only::get_producers_params& p ) const {
911911
const abi_def abi = eosio::chain_apis::get_abi(db, N(eosio));
912912
const auto table_type = get_table_type(abi, N(producers));
913-
const abi_serializer abis{ abi };
913+
const abi_serializer abis{ abi, abi_serializer_max_time };
914914
EOS_ASSERT(table_type == KEYi64, chain::contract_table_query_exception, "Invalid table type ${type} for table producers", ("type",table_type));
915915

916916
const auto& d = db.db();
@@ -969,13 +969,13 @@ read_only::get_producer_schedule_result read_only::get_producer_schedule( const
969969

970970
template<typename Api>
971971
struct resolver_factory {
972-
static auto make(const Api *api) {
973-
return [api](const account_name &name) -> optional<abi_serializer> {
974-
const auto *accnt = api->db.db().template find<account_object, by_name>(name);
972+
static auto make(const Api* api, const fc::microseconds& max_serialization_time) {
973+
return [api, max_serialization_time](const account_name &name) -> optional<abi_serializer> {
974+
const auto* accnt = api->db.db().template find<account_object, by_name>(name);
975975
if (accnt != nullptr) {
976976
abi_def abi;
977977
if (abi_serializer::to_abi(accnt->abi, abi)) {
978-
return abi_serializer(abi);
978+
return abi_serializer(abi, max_serialization_time);
979979
}
980980
}
981981

@@ -985,8 +985,8 @@ struct resolver_factory {
985985
};
986986

987987
template<typename Api>
988-
auto make_resolver(const Api *api) {
989-
return resolver_factory<Api>::make(api);
988+
auto make_resolver(const Api* api, const fc::microseconds& max_serialization_time) {
989+
return resolver_factory<Api>::make(api, max_serialization_time);
990990
}
991991

992992
fc::variant read_only::get_block(const read_only::get_block_params& params) const {
@@ -1003,7 +1003,7 @@ fc::variant read_only::get_block(const read_only::get_block_params& params) cons
10031003
EOS_ASSERT( block, unknown_block_exception, "Could not find block: ${block}", ("block", params.block_num_or_id));
10041004

10051005
fc::variant pretty_output;
1006-
abi_serializer::to_variant(*block, pretty_output, make_resolver(this), abi_serializer_max_time);
1006+
abi_serializer::to_variant(*block, pretty_output, make_resolver(this, abi_serializer_max_time), abi_serializer_max_time);
10071007

10081008
uint32_t ref_block_prefix = block->id()._hash[1];
10091009

@@ -1049,7 +1049,7 @@ void read_write::push_transaction(const read_write::push_transaction_params& par
10491049

10501050
try {
10511051
auto pretty_input = std::make_shared<packed_transaction>();
1052-
auto resolver = make_resolver(this);
1052+
auto resolver = make_resolver(this, abi_serializer_max_time);
10531053
try {
10541054
abi_serializer::from_variant(params, *pretty_input, resolver, abi_serializer_max_time);
10551055
} EOS_RETHROW_EXCEPTIONS(chain::packed_transaction_type_exception, "Invalid packed transaction")
@@ -1193,7 +1193,7 @@ read_only::get_account_results read_only::get_account( const get_account_params&
11931193
//const abi_def abi = get_abi( db, N(eosio) );
11941194
abi_def abi;
11951195
if( abi_serializer::to_abi(code_account.abi, abi) ) {
1196-
abi_serializer abis( abi );
1196+
abi_serializer abis( abi, abi_serializer_max_time );
11971197
//get_table_rows_ex<key_value_index, by_scope_primary>(p,abi);
11981198

11991199
const auto token_code = N(eosio.token);
@@ -1275,7 +1275,7 @@ read_only::abi_json_to_bin_result read_only::abi_json_to_bin( const read_only::a
12751275

12761276
abi_def abi;
12771277
if( abi_serializer::to_abi(code_account->abi, abi) ) {
1278-
abi_serializer abis( abi );
1278+
abi_serializer abis( abi, abi_serializer_max_time );
12791279
auto action_type = abis.get_action_type(params.action);
12801280
EOS_ASSERT(!action_type.empty(), action_validate_exception, "Unknown action ${action} in contract ${contract}", ("action", params.action)("contract", params.code));
12811281
try {
@@ -1295,7 +1295,7 @@ read_only::abi_bin_to_json_result read_only::abi_bin_to_json( const read_only::a
12951295
const auto& code_account = db.db().get<account_object,by_name>( params.code );
12961296
abi_def abi;
12971297
if( abi_serializer::to_abi(code_account.abi, abi) ) {
1298-
abi_serializer abis( abi );
1298+
abi_serializer abis( abi, abi_serializer_max_time );
12991299
result.args = abis.binary_to_variant( abis.get_action_type( params.action ), params.binargs, abi_serializer_max_time );
13001300
} else {
13011301
EOS_ASSERT(false, abi_not_found_exception, "No ABI found for ${contract}", ("contract", params.code));
@@ -1305,7 +1305,7 @@ read_only::abi_bin_to_json_result read_only::abi_bin_to_json( const read_only::a
13051305

13061306
read_only::get_required_keys_result read_only::get_required_keys( const get_required_keys_params& params )const {
13071307
transaction pretty_input;
1308-
auto resolver = make_resolver(this);
1308+
auto resolver = make_resolver(this, abi_serializer_max_time);
13091309
try {
13101310
abi_serializer::from_variant(params.transaction, pretty_input, resolver, abi_serializer_max_time);
13111311
} EOS_RETHROW_EXCEPTIONS(chain::transaction_type_exception, "Invalid transaction")

plugins/chain_plugin/include/eosio/chain_plugin/chain_plugin.hpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -302,7 +302,7 @@ class read_only {
302302
uint64_t scope = convert_to_type<uint64_t>(p.scope, "scope");
303303

304304
abi_serializer abis;
305-
abis.set_abi(abi);
305+
abis.set_abi(abi, abi_serializer_max_time);
306306
const auto* t_id = d.find<chain::table_id_object, chain::by_code_scope_table>(boost::make_tuple(p.code, scope, p.table));
307307
if (t_id != nullptr) {
308308
const auto &idx = d.get_index<IndexType, Scope>();

plugins/txn_test_gen_plugin/txn_test_gen_plugin.cpp

+5-3
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,8 @@ struct txn_test_gen_plugin_impl {
124124
auto chainid = app().get_plugin<chain_plugin>().get_chain_id();
125125
auto abi_serializer_max_time = app().get_plugin<chain_plugin>().get_abi_serializer_max_time();
126126

127+
abi_serializer eosio_token_serializer{fc::json::from_string(eosio_token_abi).as<abi_def>(), abi_serializer_max_time};
128+
127129
fc::crypto::private_key txn_test_receiver_A_priv_key = fc::crypto::private_key::regenerate(fc::sha256(std::string(64, 'a')));
128130
fc::crypto::private_key txn_test_receiver_B_priv_key = fc::crypto::private_key::regenerate(fc::sha256(std::string(64, 'b')));
129131
fc::crypto::private_key txn_test_receiver_C_priv_key = fc::crypto::private_key::regenerate(fc::sha256(std::string(64, 'c')));
@@ -244,6 +246,7 @@ struct txn_test_gen_plugin_impl {
244246

245247
controller& cc = app().get_plugin<chain_plugin>().chain();
246248
auto abi_serializer_max_time = app().get_plugin<chain_plugin>().get_abi_serializer_max_time();
249+
abi_serializer eosio_token_serializer{fc::json::from_string(eosio_token_abi).as<abi_def>(), abi_serializer_max_time};
247250
//create the actions here
248251
act_a_to_b.account = N(txn.test.t);
249252
act_a_to_b.name = N(transfer);
@@ -293,14 +296,15 @@ struct txn_test_gen_plugin_impl {
293296
try {
294297
controller& cc = app().get_plugin<chain_plugin>().chain();
295298
auto chainid = app().get_plugin<chain_plugin>().get_chain_id();
299+
auto abi_serializer_max_time = app().get_plugin<chain_plugin>().get_abi_serializer_max_time();
296300

297301
name sender("txn.test.a");
298302
name recipient("txn.test.b");
299303
fc::crypto::private_key a_priv_key = fc::crypto::private_key::regenerate(fc::sha256(std::string(64, 'a')));
300304
fc::crypto::private_key b_priv_key = fc::crypto::private_key::regenerate(fc::sha256(std::string(64, 'b')));
301305

302306
static uint64_t nonce = static_cast<uint64_t>(fc::time_point::now().sec_since_epoch()) << 32;
303-
abi_serializer eosio_serializer(cc.db().find<account_object, by_name>(config::system_account_name)->get_abi());
307+
abi_serializer eosio_serializer(cc.db().find<account_object, by_name>(config::system_account_name)->get_abi(), abi_serializer_max_time);
304308

305309
uint32_t reference_block_num = cc.last_irreversible_block_num();
306310
if (txn_reference_block_lag >= 0) {
@@ -362,8 +366,6 @@ struct txn_test_gen_plugin_impl {
362366
action act_b_to_a;
363367

364368
int32_t txn_reference_block_lag;
365-
366-
abi_serializer eosio_token_serializer{fc::json::from_string(eosio_token_abi).as<abi_def>()};
367369
};
368370

369371
txn_test_gen_plugin::txn_test_gen_plugin() {}

programs/cleos/main.cpp

+2-2
Original file line numberDiff line numberDiff line change
@@ -2553,11 +2553,11 @@ int main( int argc, char** argv ) {
25532553
});
25542554

25552555
//resolver for ABI serializer to decode actions in proposed transaction in multisig contract
2556-
auto resolver = [](const name& code) -> optional<abi_serializer> {
2556+
auto resolver = [abi_serializer_max_time](const name& code) -> optional<abi_serializer> {
25572557
auto result = call(get_code_func, fc::mutable_variant_object("account_name", code.to_string()));
25582558
if (result["abi"].is_object()) {
25592559
//std::cout << "ABI: " << fc::json::to_pretty_string(result) << std::endl;
2560-
return optional<abi_serializer>(abi_serializer(result["abi"].as<abi_def>()));
2560+
return optional<abi_serializer>(abi_serializer(result["abi"].as<abi_def>(), abi_serializer_max_time));
25612561
} else {
25622562
std::cerr << "ABI for contract " << code.to_string() << " not found. Action data will be shown in hex only." << std::endl;
25632563
return optional<abi_serializer>();

programs/eosio-abigen/main.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ int main(int argc, const char **argv) { abi_def output; try {
8888
if(!result) {
8989
result = Tool.run(create_factory(abi_verbose, abi_opt_sfs, abi_context, output, contract, actions).get());
9090
if(!result) {
91-
abi_serializer(output).validate();
91+
abi_serializer abis(output, fc::seconds(1)); // No risk to client side serialization taking a long time
9292
fc::variant vabi;
9393
to_variant(output, vabi);
9494

0 commit comments

Comments
 (0)