diff --git a/contracts/eosio.bios/eosio.bios.abi b/contracts/eosio.bios/eosio.bios.abi index 454a7c0d1684d68372733f108c04800fcf210068..217a3ff00b8e734f42b515fceb4d821bdb82e66d 100644 --- a/contracts/eosio.bios/eosio.bios.abi +++ b/contracts/eosio.bios/eosio.bios.abi @@ -48,36 +48,6 @@ "fields": [ {"name":"value", "type":"string"} ] - },{ - "name": "transfer", - "base": "", - "fields": [ - {"name":"from", "type":"account_name"}, - {"name":"to", "type":"account_name"}, - {"name":"quantity", "type":"asset"}, - {"name":"memo", "type":"string"} - ] - },{ - "name": "issue", - "base": "", - "fields": [ - {"name":"to", "type":"account_name"}, - {"name":"quantity", "type":"asset"} - ] - },{ - "name": "account", - "base": "", - "fields": [ - {"name":"currency", "type":"uint64"}, - {"name":"balance", "type":"uint64"} - ] - },{ - "name": "currency_stats", - "base": "", - "fields": [ - {"name":"currency", "type":"uint64"}, - {"name":"supply", "type":"uint64"} - ] }], "actions": [{ "name": "setalimits", @@ -97,25 +67,7 @@ },{ "name": "nonce", "type": "nonce" - },{ - "name": "transfer", - "type": "transfer" - },{ - "name": "issue", - "type": "issue" } ], - "tables": [{ - "name": "account", - "type": "account", - "index_type": "i64", - "key_names" : ["currency"], - "key_types" : ["uint64"] - },{ - "name": "stat", - "type": "currency_stats", - "index_type": "i64", - "key_names" : ["currency"], - "key_types" : ["uint64"] - }] + "tables": [] } diff --git a/libraries/abi_generator/abi_generator.cpp b/libraries/abi_generator/abi_generator.cpp index 149ed505fe35a1ac26d229ab26eeed372c1fa6f2..35466a8fff1e5259fcd4082168ac9f10286dbe83 100644 --- a/libraries/abi_generator/abi_generator.cpp +++ b/libraries/abi_generator/abi_generator.cpp @@ -68,7 +68,7 @@ string abi_generator::translate_type(const string& type_name) { else if (type_name == "unsigned long" || type_name == "uint32_t") built_in_type = "uint32"; else if (type_name == "unsigned short" || type_name == "uint16_t") built_in_type = "uint16"; else if (type_name == "unsigned char" || type_name == "uint8_t") built_in_type = "uint8"; - + else if (type_name == "long long" || type_name == "int64_t") built_in_type = "int64"; else if (type_name == "long" || type_name == "int32_t") built_in_type = "int32"; else if (type_name == "short" || type_name == "int16_t") built_in_type = "int16"; @@ -77,23 +77,89 @@ string abi_generator::translate_type(const string& type_name) { return built_in_type; } +bool abi_generator::inspect_type_methods_for_actions(const Decl* decl) { try { + + const auto* rec_decl = dyn_cast(decl); + if(rec_decl == nullptr) return false; + + const auto* type = rec_decl->getTypeForDecl(); + ABI_ASSERT(type != nullptr); + if( !type->isStructureOrClassType() ) { + return false; + } + + bool at_least_one_action = false; + for(const auto* method : rec_decl->methods()) { + + const RawComment* raw_comment = ast_context->getRawCommentForDeclNoCache(method); + if( raw_comment == nullptr) continue; + + SourceManager& source_manager = ast_context->getSourceManager(); + string raw_text = raw_comment->getRawText(source_manager); + regex r(R"(@abi (action))"); + + smatch smatch; + if(regex_search(raw_text, smatch, r)){ + + auto method_name = method->getNameAsString(); + ABI_ASSERT(find_struct(method_name) == nullptr, "action already exists ${method_name}", ("method_name",method_name)); + + struct_def abi_struct; + for(const auto* p : method->parameters() ) { + clang::QualType qt = p->getOriginalType().getNonReferenceType(); + qt.setLocalFastQualifiers(0); + + string field_name = p->getNameAsString(); + string field_type_name = add_type(qt); + + field_def struct_field{field_name, field_type_name}; + ABI_ASSERT(is_builtin_type(get_vector_element_type(struct_field.type)) + || find_struct(get_vector_element_type(struct_field.type)) + || find_type(get_vector_element_type(struct_field.type)) + , "Unknown type ${type} [${abi}]",("type",struct_field.type)("abi",*output)); + + type_size[string(struct_field.type)] = is_vector(struct_field.type) ? 0 : ast_context->getTypeSize(qt); + abi_struct.fields.push_back(struct_field); + } + + abi_struct.name = method_name; + abi_struct.base = ""; + + output->structs.push_back(abi_struct); + + full_types[method_name] = method_name; + + output->actions.push_back({method_name, method_name}); + at_least_one_action = true; + } + + } + + return at_least_one_action; + +} FC_CAPTURE_AND_RETHROW() } + void abi_generator::handle_decl(const Decl* decl) { try { ABI_ASSERT(decl != nullptr); ABI_ASSERT(output != nullptr); ABI_ASSERT(ast_context != nullptr); - //ASTContext& ctx = decl->getASTContext(); - const RawComment* raw_comment = ast_context->getRawCommentForDeclNoCache(decl); - - if(!raw_comment) return; - SourceManager& source_manager = ast_context->getSourceManager(); - auto file_name = source_manager.getFilename(raw_comment->getLocStart()); + auto file_name = source_manager.getFilename(decl->getLocStart()); if ( !abi_context.empty() && !file_name.startswith(abi_context) ) { return; } + if(inspect_type_methods_for_actions(decl)) { + return; + } + + const RawComment* raw_comment = ast_context->getRawCommentForDeclNoCache(decl); + if(raw_comment == nullptr) { + return; + } + string raw_text = raw_comment->getRawText(source_manager); regex r(R"(@abi (action|table)((?: [a-z0-9]+)*))"); @@ -103,7 +169,7 @@ void abi_generator::handle_decl(const Decl* decl) { try { if(smatch.size() == 3) { auto type = smatch[1].str(); - + vector params; auto string_params = smatch[2].str(); boost::trim(string_params); @@ -116,7 +182,7 @@ void abi_generator::handle_decl(const Decl* decl) { try { ABI_ASSERT(action_decl != nullptr); auto qt = action_decl->getTypeForDecl()->getCanonicalTypeInternal(); - + auto type_name = add_struct(qt); ABI_ASSERT(!is_builtin_type(type_name), "A built-in type with the same name exists, try using another name: ${type_name}", ("type_name",type_name)); @@ -151,7 +217,7 @@ void abi_generator::handle_decl(const Decl* decl) { try { table_def table; table.name = boost::algorithm::to_lower_copy(boost::erase_all_copy(type_name, "_")); table.type = type_name; - + if(params.size() >= 1) { table.name = params[0]; } @@ -173,9 +239,9 @@ void abi_generator::handle_decl(const Decl* decl) { try { } } } - + raw_text = smatch.suffix(); - } + } } FC_CAPTURE_AND_RETHROW() } @@ -193,11 +259,11 @@ bool abi_generator::is_string(const string& type) { void abi_generator::get_all_fields(const struct_def& s, vector& fields) { abi_serializer abis(*output); - + for(const auto& field : s.fields) { fields.push_back(field); } - + if(s.base.size()) { const auto* base = find_struct(s.base); ABI_ASSERT(base, "Unable to find base type ${type}",("type",s.base)); @@ -246,7 +312,7 @@ void abi_generator::guess_key_names(table_def& table, const struct_def s) { if( table.index_type == "i64i64i64" || table.index_type == "i128i128" || table.index_type == "i64") { - + table.key_names.clear(); table.key_types.clear(); @@ -342,7 +408,7 @@ bool abi_generator::is_elaborated(const clang::QualType& qt) { } bool abi_generator::is_vector(const clang::QualType& vqt) { - + QualType qt(vqt); if ( is_elaborated(qt) ) @@ -404,7 +470,7 @@ clang::QualType abi_generator::add_typedef(const clang::QualType& tqt) { abi_typedef.new_type_name = new_type_name; abi_typedef.type = translate_type(underlying_type_name); const auto* td = find_type(abi_typedef.new_type_name); - + if(!td && !is_struct_specialization(underlying_type) ) { output->types.push_back(abi_typedef); } else { @@ -424,7 +490,7 @@ clang::CXXRecordDecl::base_class_range abi_generator::get_struct_bases(const cla const auto* td_decl = qt->getAs()->getDecl(); qt = td_decl->getUnderlyingType().getUnqualifiedType(); } - + const auto* record_type = qt->getAs(); ABI_ASSERT(record_type != nullptr); auto cxxrecord_decl = clang::dyn_cast(record_type->getDecl()); @@ -455,7 +521,7 @@ string abi_generator::add_vector(const clang::QualType& vqt) { auto vector_element_type = get_vector_element_type(qt); ABI_ASSERT(!is_vector(vector_element_type), "Only one-dimensional arrays are supported"); - + add_type(vector_element_type); auto vector_element_type_str = translate_type(get_type_name(vector_element_type)); @@ -492,7 +558,7 @@ string abi_generator::add_type(const clang::QualType& tqt) { if( is_struct(qt) ) { return add_struct(qt, full_type_name); } - + ABI_ASSERT(false, "types can only be: vector, struct, class or a built-in type. (${type}) ", ("type",get_type_name(qt))); return type_name; } @@ -513,7 +579,7 @@ string abi_generator::add_struct(const clang::QualType& sqt, string full_name) { } auto name = remove_namespace(full_name); - + ABI_ASSERT(is_struct(qt), "Only struct and class are supported. ${full_name}",("full_name",full_name)); if( find_struct(name) ) { @@ -543,7 +609,7 @@ string abi_generator::add_struct(const clang::QualType& sqt, string full_name) { struct_def abi_struct; for (const clang::FieldDecl* field : get_struct_fields(qt) ) { clang::QualType qt = field->getType(); - + string field_name = field->getNameAsString(); string field_type_name = add_type(qt); @@ -561,7 +627,7 @@ string abi_generator::add_struct(const clang::QualType& sqt, string full_name) { abi_struct.base = base_name; output->structs.push_back(abi_struct); - + full_types[name] = full_name; return name; } diff --git a/libraries/abi_generator/include/eosio/abi_generator/abi_generator.hpp b/libraries/abi_generator/include/eosio/abi_generator/abi_generator.hpp index 1fd4d1868dab10dad548db2d8ec2dd4190a05031..4949c8cc506cb4854946d08d11acfb376b72e6b0 100644 --- a/libraries/abi_generator/include/eosio/abi_generator/abi_generator.hpp +++ b/libraries/abi_generator/include/eosio/abi_generator/abi_generator.hpp @@ -124,6 +124,7 @@ namespace eosio { void handle_tagdecl_definition(TagDecl* tag_decl); private: + bool inspect_type_methods_for_actions(const Decl* decl); string remove_namespace(const string& full_name); diff --git a/tests/wasm_tests/dice_tests.cpp b/tests/wasm_tests/dice_tests.cpp index 3cf7850f269db6631e61b168e383198974947af3..3464fe624b650dc6183ca5ea6940f913372b6fd4 100644 --- a/tests/wasm_tests/dice_tests.cpp +++ b/tests/wasm_tests/dice_tests.cpp @@ -105,7 +105,7 @@ struct dice_tester : tester { action act( {{account, config::active_name}}, offer_bet_t{amount, account, commitment} ); trx.actions.push_back(act); - set_tapos(trx); + set_transaction_headers(trx); trx.sign(get_private_key( account, "active" ), chain_id_type()); control->push_transaction(packed_transaction(trx,packed_transaction::none)); } @@ -115,7 +115,7 @@ struct dice_tester : tester { action act( {{account, config::active_name}}, cancel_offer_t{commitment} ); trx.actions.push_back(act); - set_tapos(trx); + set_transaction_headers(trx); trx.sign(get_private_key( account, "active" ), chain_id_type()); control->push_transaction(packed_transaction(trx,packed_transaction::none)); } @@ -125,7 +125,7 @@ struct dice_tester : tester { action act( {{account, config::active_name}}, deposit_t{account, amount} ); trx.actions.push_back(act); - set_tapos(trx); + set_transaction_headers(trx); trx.sign(get_private_key( account, "active" ), chain_id_type()); control->push_transaction(packed_transaction(trx,packed_transaction::none)); } @@ -135,7 +135,7 @@ struct dice_tester : tester { action act( {{account, config::active_name}}, withdraw_t{account, amount} ); trx.actions.push_back(act); - set_tapos(trx); + set_transaction_headers(trx); trx.sign(get_private_key( account, "active" ), chain_id_type()); control->push_transaction(packed_transaction(trx,packed_transaction::none)); } @@ -145,7 +145,7 @@ struct dice_tester : tester { action act( {{account, config::active_name}}, reveal_t{commitment, source} ); trx.actions.push_back(act); - set_tapos(trx); + set_transaction_headers(trx); trx.sign(get_private_key( account, "active" ), chain_id_type()); control->push_transaction(packed_transaction(trx,packed_transaction::none)); }