From 7ec9ea6c00d8bb4228b33309eb32d5053ce981a9 Mon Sep 17 00:00:00 2001 From: Bart Wyatt Date: Tue, 14 Nov 2017 15:22:52 -0500 Subject: [PATCH] nuked databse plugin, restored abi_serializer functions in chain and chain plugin --- libraries/chain/CMakeLists.txt | 1 + libraries/chain/contracts/abi_serializer.cpp | 277 +++++++++++++++ .../chain/contracts/chain_initializer.cpp | 138 +++++++- libraries/chain/contracts/eos_contract.cpp | 30 +- .../include/eosio/chain/account_object.hpp | 8 +- .../eosio/chain/contracts/abi_serializer.hpp | 77 ++++ .../chain/contracts/chain_initializer.hpp | 4 +- .../eosio/chain/contracts/eos_contract.hpp | 2 + .../include/eosio/chain/contracts/types.hpp | 334 ++++++++---------- plugins/CMakeLists.txt | 1 - plugins/chain_plugin/CMakeLists.txt | 2 +- plugins/chain_plugin/chain_plugin.cpp | 57 +-- .../include/eos/chain_plugin/chain_plugin.hpp | 24 +- plugins/database_plugin/CMakeLists.txt | 16 - plugins/database_plugin/database_plugin.cpp | 77 ---- .../eos/database_plugin/database_plugin.hpp | 41 --- 16 files changed, 690 insertions(+), 399 deletions(-) create mode 100644 libraries/chain/contracts/abi_serializer.cpp create mode 100644 libraries/chain/include/eosio/chain/contracts/abi_serializer.hpp delete mode 100644 plugins/database_plugin/CMakeLists.txt delete mode 100644 plugins/database_plugin/database_plugin.cpp delete mode 100644 plugins/database_plugin/include/eos/database_plugin/database_plugin.hpp diff --git a/libraries/chain/CMakeLists.txt b/libraries/chain/CMakeLists.txt index 77bde4cd0..d734dcc7f 100644 --- a/libraries/chain/CMakeLists.txt +++ b/libraries/chain/CMakeLists.txt @@ -22,6 +22,7 @@ add_library( eos_chain contracts/staked_balance_objects.cpp contracts/chain_initializer.cpp contracts/genesis_state.cpp + contracts/abi_serializer.cpp ${HEADERS} diff --git a/libraries/chain/contracts/abi_serializer.cpp b/libraries/chain/contracts/abi_serializer.cpp new file mode 100644 index 000000000..a373f89b3 --- /dev/null +++ b/libraries/chain/contracts/abi_serializer.cpp @@ -0,0 +1,277 @@ +/** + * @file + * @copyright defined in eos/LICENSE.txt + */ +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace boost; + +namespace eosio { namespace chain { namespace contracts { + + using boost::algorithm::ends_with; + using std::string; + + template + inline fc::variant variant_from_stream(fc::datastream& stream) { + T temp; + fc::raw::unpack( stream, temp ); + return fc::variant(temp); + } + + template + auto pack_unpack() { + return std::make_pair( + []( fc::datastream& stream, bool is_array) -> fc::variant { + if( is_array ) + return variant_from_stream>(stream); + return variant_from_stream(stream); + }, + []( const fc::variant& var, fc::datastream& ds, bool is_array ){ + if( is_array ) + fc::raw::pack( ds, var.as>() ); + else + fc::raw::pack( ds, var.as()); + } + ); + } + + abi_serializer::abi_serializer( const abi_def& abi ) { + configure_built_in_types(); + set_abi(abi); + } + + void abi_serializer::configure_built_in_types() { + //public_key.hpp + built_in_types.emplace("public_key", pack_unpack()); + + //asset.hpp + built_in_types.emplace("asset", pack_unpack()); + built_in_types.emplace("price", pack_unpack()); + + //native.hpp + built_in_types.emplace("string", pack_unpack()); + built_in_types.emplace("time", pack_unpack()); + built_in_types.emplace("signature", pack_unpack()); + built_in_types.emplace("checksum", pack_unpack()); + built_in_types.emplace("field_name", pack_unpack()); + built_in_types.emplace("fixed_string32", pack_unpack()); + built_in_types.emplace("fixed_string16", pack_unpack()); + built_in_types.emplace("type_name", pack_unpack()); + built_in_types.emplace("bytes", pack_unpack()); + built_in_types.emplace("uint8", pack_unpack()); + built_in_types.emplace("uint16", pack_unpack()); + built_in_types.emplace("uint32", pack_unpack()); + built_in_types.emplace("uint64", pack_unpack()); + built_in_types.emplace("uint128", pack_unpack()); + built_in_types.emplace("uint256", pack_unpack()); + built_in_types.emplace("int8", pack_unpack()); + built_in_types.emplace("int16", pack_unpack()); + built_in_types.emplace("int32", pack_unpack()); + built_in_types.emplace("int64", pack_unpack()); + built_in_types.emplace("name", pack_unpack()); + built_in_types.emplace("field", pack_unpack()); + built_in_types.emplace("struct_def", pack_unpack()); + built_in_types.emplace("fields", pack_unpack>()); + built_in_types.emplace("account_name", pack_unpack()); + built_in_types.emplace("permission_name", pack_unpack()); + built_in_types.emplace("action_name", pack_unpack()); + built_in_types.emplace("scope_name", pack_unpack()); + built_in_types.emplace("permission_level", pack_unpack()); + built_in_types.emplace("action", pack_unpack()); + built_in_types.emplace("permission_level_weight", pack_unpack()); + built_in_types.emplace("transaction", pack_unpack()); + built_in_types.emplace("signed_transaction", pack_unpack()); + built_in_types.emplace("key_weight", pack_unpack()); + built_in_types.emplace("authority", pack_unpack()); + built_in_types.emplace("chain_config", pack_unpack()); + built_in_types.emplace("type_def", pack_unpack()); + built_in_types.emplace("action", pack_unpack()); + built_in_types.emplace("table", pack_unpack()); + built_in_types.emplace("abi", pack_unpack()); + built_in_types.emplace("nonce", pack_unpack()); + } + + void abi_serializer::set_abi(const abi_def& abi) { + typedefs.clear(); + structs.clear(); + actions.clear(); + tables.clear(); + + for( const auto& td : abi.types ) { + FC_ASSERT(is_type(td.type), "invalid type", ("type",td.type)); + typedefs[td.new_type_name] = td.type; + } + + for( const auto& st : abi.structs ) + structs[st.name] = st; + + for( const auto& a : abi.actions ) + actions[a.name] = a.type; + + for( const auto& t : abi.tables ) + tables[t.name] = t.type; + + /** + * The ABI vector may contain duplicates which would make it + * an invalid ABI + */ + FC_ASSERT( typedefs.size() == abi.types.size() ); + FC_ASSERT( structs.size() == abi.structs.size() ); + FC_ASSERT( actions.size() == abi.actions.size() ); + FC_ASSERT( tables.size() == abi.tables.size() ); + } + + bool abi_serializer::is_array(const type_name& type)const { + return ends_with(string(type), "[]"); + } + + type_name abi_serializer::array_type(const type_name& type)const { + if( !is_array(type) ) return type; + return type_name(string(type).substr(0, type.size()-2)); + } + + bool abi_serializer::is_type(const type_name& rtype)const { + auto type = array_type(rtype); + if( built_in_types.find(type) != built_in_types.end() ) return true; + if( typedefs.find(type) != typedefs.end() ) return is_type(typedefs.find(type)->second); + if( structs.find(type) != structs.end() ) return true; + return false; + } + + const struct_def& abi_serializer::get_struct(const type_name& type)const { + auto itr = structs.find(resolve_type(type) ); + FC_ASSERT( itr != structs.end(), "Unknown struct ${type}", ("type",type) ); + return itr->second; + } + + void abi_serializer::validate()const { + for( const auto& t : typedefs ) { try { + vector types_seen{t.first, t.second}; + auto itr = typedefs.find(t.second); + while( itr != typedefs.end() ) { + FC_ASSERT( find(types_seen.begin(), types_seen.end(), itr->second) == types_seen.end(), "Circular reference in type ${type}", ("type",t.first) ); + types_seen.emplace_back(itr->second); + itr = typedefs.find(itr->second); + } + } FC_CAPTURE_AND_RETHROW( (t) ) } + for( const auto& t : typedefs ) { try { + FC_ASSERT(is_type(t.second), "", ("type",t.second) ); + } FC_CAPTURE_AND_RETHROW( (t) ) } + for( const auto& s : structs ) { try { + if( s.second.base != type_name() ) { + struct_def current = s.second; + vector types_seen{current.name}; + while( current.base != type_name() ) { + const auto& base = get_struct(current.base); //<-- force struct to inherit from another struct + FC_ASSERT( find(types_seen.begin(), types_seen.end(), base.name) == types_seen.end(), "Circular reference in struct ${type}", ("type",s.second.name) ); + types_seen.emplace_back(base.name); + current = base; + } + } + for( const auto& field : s.second.fields ) { try { + FC_ASSERT(is_type(field.type) ); + } FC_CAPTURE_AND_RETHROW( (field) ) } + } FC_CAPTURE_AND_RETHROW( (s) ) } + for( const auto& a : actions ) { try { + FC_ASSERT(is_type(a.second), "", ("type",a.second) ); + } FC_CAPTURE_AND_RETHROW( (a) ) } + + for( const auto& t : tables ) { try { + FC_ASSERT(is_type(t.second), "", ("type",t.second) ); + } FC_CAPTURE_AND_RETHROW( (t) ) } + } + + type_name abi_serializer::resolve_type(const type_name& type)const { + auto itr = typedefs.find(type); + if( itr != typedefs.end() ) + return resolve_type(itr->second); + return type; + } + + void abi_serializer::binary_to_variant(const type_name& type, fc::datastream& stream, + fc::mutable_variant_object& obj)const { + const auto& st = get_struct(type); + if( st.base != type_name() ) { + binary_to_variant(resolve_type(st.base), stream, obj); + } + for( const auto& field : st.fields ) { + obj( field.name, binary_to_variant(resolve_type(field.type), stream) ); + } + } + + fc::variant abi_serializer::binary_to_variant(const type_name& type, fc::datastream& stream)const + { + type_name rtype = resolve_type(type); + auto btype = built_in_types.find(array_type(rtype) ); + if( btype != built_in_types.end() ) { + return btype->second.first(stream, is_array(rtype)); + } + + fc::mutable_variant_object mvo; + binary_to_variant(rtype, stream, mvo); + return fc::variant( std::move(mvo) ); + } + + fc::variant abi_serializer::binary_to_variant(const type_name& type, const bytes& binary)const{ + fc::datastream ds( binary.data(), binary.size() ); + return binary_to_variant(type, ds); + } + + void abi_serializer::variant_to_binary(const type_name& type, const fc::variant& var, fc::datastream& ds)const + { try { + auto rtype = resolve_type(type); + + auto btype = built_in_types.find(array_type(rtype)); + if( btype != built_in_types.end() ) { + btype->second.second(var, ds, is_array(rtype)); + } else { + + const auto& st = get_struct(rtype); + const auto& vo = var.get_object(); + + if( st.base != type_name() ) { + variant_to_binary(resolve_type(st.base), var, ds); + } + for( const auto& field : st.fields ) { + if( vo.contains( string(field.name).c_str() ) ) { + variant_to_binary(field.type, vo[field.name], ds); + } + else { + /// TODO: default construct field and write it out + FC_ASSERT( !"missing field in variant object", "Missing '${f}' in variant object", ("f",field.name) ); + } + } + } + } FC_CAPTURE_AND_RETHROW( (type)(var) ) } + + bytes abi_serializer::variant_to_binary(const type_name& type, const fc::variant& var)const { + if( !is_type(type) ) { + return var.as(); + } + + bytes temp( 1024*1024 ); + fc::datastream ds(temp.data(), temp.size() ); + variant_to_binary(type, var, ds); + temp.resize(ds.tellp()); + return temp; + } + + type_name abi_serializer::get_action_type(name action)const { + auto itr = actions.find(action); + if( itr != actions.end() ) return itr->second; + return type_name(); + } + type_name abi_serializer::get_table_type(name action)const { + auto itr = tables.find(action); + if( itr != tables.end() ) return itr->second; + return type_name(); + } + +} } } diff --git a/libraries/chain/contracts/chain_initializer.cpp b/libraries/chain/contracts/chain_initializer.cpp index 8df6ef65f..3ec0ff3c3 100644 --- a/libraries/chain/contracts/chain_initializer.cpp +++ b/libraries/chain/contracts/chain_initializer.cpp @@ -51,16 +51,18 @@ void chain_initializer::register_types(chain_controller& chain, chainbase::datab SET_APP_HANDLER( eos, eos, okproducer, eosio ); SET_APP_HANDLER( eos, eos, setproxy, eosio ); SET_APP_HANDLER( eos, eos, setcode, eosio ); + SET_APP_HANDLER( eos, eos, setabi, eosio ); SET_APP_HANDLER( eos, eos, updateauth, eosio ); SET_APP_HANDLER( eos, eos, deleteauth, eosio ); SET_APP_HANDLER( eos, eos, linkauth, eosio ); - SET_APP_HANDLER( eos, eos, unlinkauth, eosio ); + SET_APP_HANDLER( eos, eos, unlinkauth, eosio ); + SET_APP_HANDLER( eos, eos, nonce, eosio ); } -/* -abi chain_initializer::eos_contract_abi() + +abi_def chain_initializer::eos_contract_abi() { - abi eos_abi; + abi_def eos_abi; eos_abi.types.push_back( type_def{"account_name","name"} ); eos_abi.types.push_back( type_def{"share_type","int64"} ); eos_abi.actions.push_back( action_def{name("transfer"), "transfer"} ); @@ -71,28 +73,128 @@ abi chain_initializer::eos_contract_abi() eos_abi.actions.push_back( action_def{name("setproducer"), "setproducer"} ); eos_abi.actions.push_back( action_def{name("setproxy"), "setproxy"} ); eos_abi.actions.push_back( action_def{name("setcode"), "setcode"} ); + eos_abi.actions.push_back( action_def{name("setabi"), "setabi"} ); eos_abi.actions.push_back( action_def{name("linkauth"), "linkauth"} ); eos_abi.actions.push_back( action_def{name("unlinkauth"), "unlinkauth"} ); eos_abi.actions.push_back( action_def{name("updateauth"), "updateauth"} ); eos_abi.actions.push_back( action_def{name("deleteauth"), "deleteauth"} ); eos_abi.actions.push_back( action_def{name("newaccount"), "newaccount"} ); - eos_abi.structs.push_back( eosio::get_struct::type() ); - eos_abi.structs.push_back( eosio::get_struct::type() ); - eos_abi.structs.push_back( eosio::get_struct::type() ); - eos_abi.structs.push_back( eosio::get_struct::type() ); - eos_abi.structs.push_back( eosio::get_struct::type() ); - eos_abi.structs.push_back( eosio::get_struct::type() ); - eos_abi.structs.push_back( eosio::get_struct::type() ); - eos_abi.structs.push_back( eosio::get_struct::type() ); - eos_abi.structs.push_back( eosio::get_struct::type() ); - eos_abi.structs.push_back( eosio::get_struct::type() ); - eos_abi.structs.push_back( eosio::get_struct::type() ); - eos_abi.structs.push_back( eosio::get_struct::type() ); - eos_abi.structs.push_back( eosio::get_struct::type() ); + eos_abi.actions.push_back( action_def{name("nonce"), "nonce"} ); + eos_abi.structs.emplace_back( struct_def { + "transfer", "", { + {"from", "account_name"}, + {"to", "account_name"}, + {"amount", "uint64"}, + {"memo", "string"}, + } + }); + + eos_abi.structs.emplace_back( struct_def { + "lock", "", { + {"from", "account_name"}, + {"to", "account_name"}, + {"amount", "share_type"}, + } + }); + + eos_abi.structs.emplace_back( struct_def { + "unlock", "", { + {"account", "account_name"}, + {"amount", "share_type"}, + } + }); + + eos_abi.structs.emplace_back( struct_def { + "claim", "", { + {"account", "account_name"}, + {"amount", "share_type"}, + } + }); + + eos_abi.structs.emplace_back( struct_def { + "okproducer", "", { + {"voter", "account_name"}, + {"producer", "account_name"}, + {"approve", "int8"}, + } + }); + + eos_abi.structs.emplace_back( struct_def { + "setproducer", "", { + {"name", "account_name"}, + {"key", "public_key"}, + {"configuration", "chain_config"}, + } + }); + + eos_abi.structs.emplace_back( struct_def { + "setproxy", "", { + {"stakeholder", "account_name"}, + {"proxy", "account_name"}, + } + }); + + eos_abi.structs.emplace_back( struct_def { + "setcode", "", { + {"account", "account_name"}, + {"vmtype", "uint8"}, + {"vmversion", "uint8"}, + {"code", "bytes"} + } + }); + + eos_abi.structs.emplace_back( struct_def { + "updateauth", "", { + {"account", "account_name"}, + {"permission", "permission_name"}, + {"parent", "permission_name"}, + {"authority", "authority"}, + } + }); + + eos_abi.structs.emplace_back( struct_def { + "linkauth", "", { + {"account", "account_name"}, + {"code", "account_name"}, + {"type", "action_name"}, + {"requirement", "permission_name"}, + } + }); + + eos_abi.structs.emplace_back( struct_def { + "unlinkauth", "", { + {"account", "account_name"}, + {"code", "account_name"}, + {"type", "action_name"}, + } + }); + + eos_abi.structs.emplace_back( struct_def { + "deleteauth", "", { + {"account", "account_name"}, + {"permission", "permission_name"}, + } + }); + + eos_abi.structs.emplace_back( struct_def { + "newaccount", "", { + {"creator", "account_name"}, + {"name", "account_name"}, + {"owner", "authority"}, + {"active", "authority"}, + {"recovery", "authority"}, + {"deposit", "asset"}, + } + }); + + eos_abi.structs.emplace_back( struct_def { + "nonce", "", { + {"value", "name"} + } + }); return eos_abi; } -*/ std::vector chain_initializer::prepare_database( chain_controller& chain, chainbase::database& db) { diff --git a/libraries/chain/contracts/eos_contract.cpp b/libraries/chain/contracts/eos_contract.cpp index fae9faae9..e421e5e55 100644 --- a/libraries/chain/contracts/eos_contract.cpp +++ b/libraries/chain/contracts/eos_contract.cpp @@ -20,7 +20,7 @@ #include #include -//#include +#include namespace eosio { namespace chain { namespace contracts { @@ -191,12 +191,6 @@ void apply_eos_setcode(apply_context& context) { FC_ASSERT( act.vmtype == 0 ); FC_ASSERT( act.vmversion == 0 ); - /// if an ABI is specified make sure it is well formed and doesn't - /// reference any undefined types - // abiSerializer( act.abi ).validate(); - // todo: figure out abi serilization location - - const auto& account = db.get(act.account); // wlog( "set code: ${size}", ("size",act.code.size())); db.modify( account, [&]( auto& a ) { @@ -206,13 +200,29 @@ void apply_eos_setcode(apply_context& context) { a.code.resize( act.code.size() ); memcpy( a.code.data(), act.code.data(), act.code.size() ); - //a.set_abi( act.abi ); }); apply_context init_context( context.mutable_controller, context.mutable_db, context.trx, context.act, act.account ); wasm_interface::get().init( init_context ); } +void apply_eos_setabi(apply_context& context) { + auto& db = context.mutable_db; + auto act = context.act.as(); + + context.require_authorization(act.account); + + /// if an ABI is specified make sure it is well formed and doesn't + /// reference any undefined types + abi_serializer(act.abi).validate(); + // todo: figure out abi serilization location + + const auto& account = db.get(act.account); + db.modify( account, [&]( auto& a ) { + a.set_abi( act.abi ); + }); +} + void apply_eos_claim(apply_context& context) { auto claim = context.act.as(); @@ -481,4 +491,8 @@ void apply_eos_unlinkauth(apply_context& context) { db.remove(*link); } +void apply_eos_nonce(apply_context&) { + /// do nothing +} + } } } // namespace eosio::chain::contracts diff --git a/libraries/chain/include/eosio/chain/account_object.hpp b/libraries/chain/include/eosio/chain/account_object.hpp index 28f9a0659..a99cb3b22 100644 --- a/libraries/chain/include/eosio/chain/account_object.hpp +++ b/libraries/chain/include/eosio/chain/account_object.hpp @@ -6,13 +6,14 @@ #include #include #include +#include #include "multi_index_includes.hpp" namespace eosio { namespace chain { class account_object : public chainbase::object { - OBJECT_CTOR(account_object,(code)) + OBJECT_CTOR(account_object,(code)(abi)) id_type id; account_name name; @@ -22,15 +23,14 @@ namespace eosio { namespace chain { block_timestamp_type creation_date; shared_vector code; - /* + shared_vector abi; - void set_abi( const eosio::types::Abi& a ) { + void set_abi( const eosio::chain::contracts::abi_def& a ) { abi.resize( fc::raw::pack_size( a ) ); fc::datastream ds( abi.data(), abi.size() ); fc::raw::pack( ds, a ); } - */ }; using account_id_type = account_object::id_type; diff --git a/libraries/chain/include/eosio/chain/contracts/abi_serializer.hpp b/libraries/chain/include/eosio/chain/contracts/abi_serializer.hpp new file mode 100644 index 000000000..0aea258d1 --- /dev/null +++ b/libraries/chain/include/eosio/chain/contracts/abi_serializer.hpp @@ -0,0 +1,77 @@ +/** + * @file + * @copyright defined in eos/LICENSE.txt + */ +#pragma once +#include + +namespace eosio { namespace chain { namespace contracts { + +using std::map; +using std::string; +using std::function; +using std::pair; + +/** + * Describes the binary representation message and table contents so that it can + * be converted to and from JSON. + */ +struct abi_serializer { + abi_serializer(){ configure_built_in_types(); } + abi_serializer( const abi_def& abi ); + void set_abi(const abi_def& abi); + + map typedefs; + map structs; + map actions; + map tables; + + typedef std::function&, bool)> unpack_function; + typedef std::function&, bool)> pack_function; + + map> built_in_types; + void configure_built_in_types(); + + bool has_cycle(const vector>& sedges)const; + void validate()const; + + type_name resolve_type(const type_name& t)const; + bool is_array(const type_name& type)const; + bool is_type(const type_name& type)const; + bool is_struct(const type_name& type)const; + + type_name array_type(const type_name& type)const; + + const struct_def& get_struct(const type_name& type)const; + + type_name get_action_type(name action)const; + type_name get_table_type(name action)const; + + fc::variant binary_to_variant(const type_name& type, const bytes& binary)const; + bytes variant_to_binary(const type_name& type, const fc::variant& var)const; + + fc::variant binary_to_variant(const type_name& type, fc::datastream& binary)const; + void variant_to_binary(const type_name& type, const fc::variant& var, fc::datastream& ds)const; + + template + static bool is_empty_abi(const Vec& abi_vec) + { + return abi_vec.size() <= 4; + } + + template + static bool to_abi(const Vec& abi_vec, abi_def& abi) + { + if( !is_empty_abi(abi_vec) ) { /// 4 == packsize of empty Abi + fc::datastream ds( abi_vec.data(), abi_vec.size() ); + fc::raw::unpack( ds, abi ); + return true; + } + return false; + } + + private: + void binary_to_variant(const type_name& type, fc::datastream& stream, fc::mutable_variant_object& obj)const; +}; + +} } } // eosio::chain::contracts diff --git a/libraries/chain/include/eosio/chain/contracts/chain_initializer.hpp b/libraries/chain/include/eosio/chain/contracts/chain_initializer.hpp index d68a9db49..e3d3f1b94 100644 --- a/libraries/chain/include/eosio/chain/contracts/chain_initializer.hpp +++ b/libraries/chain/include/eosio/chain/contracts/chain_initializer.hpp @@ -5,7 +5,7 @@ #pragma once #include - +#include #include namespace eosio { namespace chain { namespace contracts { @@ -25,7 +25,7 @@ namespace eosio { namespace chain { namespace contracts { std::vector prepare_database(chain::chain_controller& chain, chainbase::database& db); - // static abi eos_contract_abi(); + static abi_def eos_contract_abi(); private: genesis_state_type genesis; diff --git a/libraries/chain/include/eosio/chain/contracts/eos_contract.hpp b/libraries/chain/include/eosio/chain/contracts/eos_contract.hpp index a56bff816..fba03bb1a 100644 --- a/libraries/chain/include/eosio/chain/contracts/eos_contract.hpp +++ b/libraries/chain/include/eosio/chain/contracts/eos_contract.hpp @@ -19,9 +19,11 @@ namespace eosio { namespace chain { namespace contracts { void apply_eos_setproducer(apply_context&); void apply_eos_setproxy(apply_context&); void apply_eos_setcode(apply_context&); + void apply_eos_setabi(apply_context&); void apply_eos_updateauth(apply_context&); void apply_eos_deleteauth(apply_context&); void apply_eos_linkauth(apply_context&); void apply_eos_unlinkauth(apply_context&); + void apply_eos_nonce(apply_context&); } } } /// namespace eosio::contracts diff --git a/libraries/chain/include/eosio/chain/contracts/types.hpp b/libraries/chain/include/eosio/chain/contracts/types.hpp index 920cf65a8..5ca9d0fad 100644 --- a/libraries/chain/include/eosio/chain/contracts/types.hpp +++ b/libraries/chain/include/eosio/chain/contracts/types.hpp @@ -1,19 +1,116 @@ #pragma once +#include +#include #include #include +#include + namespace eosio { namespace chain { namespace contracts { +using namespace boost::multiprecision; + +template +using uint_t = number >; +template +using int_t = number >; + +using uint8 = uint_t<8>; +using uint16 = uint_t<16>; +using uint32 = uint_t<32>; +using uint64 = uint_t<64>; + +using fixed_string32 = fc::fixed_string>; +using fixed_string16 = fc::fixed_string<>; +using type_name = fixed_string32; +using field_name = fixed_string16; +using table_name = name; + + +struct type_def { + type_def() = default; + type_def(const type_name& new_type_name, const type_name& type) + :new_type_name(new_type_name), type(type) + {} + + type_name new_type_name; + type_name type; +}; + +struct field_def { + field_def() = default; + field_def(const field_name& name, const type_name& type) + :name(name), type(type) + {} + + field_name name; + type_name type; + + bool operator==(const field_def& other) const { + return std::tie(name, type) == std::tie(other.name, other.type); + } +}; + +struct struct_def { + struct_def() = default; + struct_def(const type_name& name, const type_name& base, const vector& fields) + :name(name), base(base), fields(fields) + {} + + type_name name; + type_name base; + vector fields; + + bool operator==(const struct_def& other) const { + return std::tie(name, base, fields) == std::tie(other.name, other.base, other.fields); + } +}; + +struct action_def { + action_def() = default; + action_def(const action_name& name, const type_name& type) + :name(name), type(type) + {} + + action_name name; + type_name type; +}; + +struct table_def { + table_def() = default; + table_def(const table_name& name, const type_name& index_type, const vector& key_names, const vector& key_types, const type_name& type) + :name(name), index_type(index_type), key_names(key_names), key_types(key_types), type(type) + {} + + table_name name; // the name of the table + type_name index_type; // the kind of index, i64, i128i128, etc + vector key_names; // names for the keys defined by key_types + vector key_types; // the type of key parameters + type_name type; // type of binary data stored in this table +}; + +struct abi_def { + abi_def() = default; + abi_def(const vector& types, const vector& structs, const vector& actions, const vector& tables) + :types(types), structs(structs), actions(actions), tables(tables) + {} + + vector types; + vector structs; + vector actions; + vector tables; +}; + struct transfer { transfer() = default; - transfer(const account_name& from, const account_name& to, const uint64_t& amount, const string& memo) + transfer(const account_name& from, const account_name& to, const uint64& amount, const string& memo) :from(from), to(to), amount(amount), memo(memo) {} account_name from; account_name to; - uint64_t amount; + uint64 amount; string memo; static name get_scope() { @@ -25,23 +122,6 @@ struct transfer { } }; -/* -template<> -struct get_struct { - static const struct_def& type() { - static struct_def result = - { "transfer", "", { - {"from", "account_name"}, - {"to", "account_name"}, - {"amount", "uint64_t"}, - {"memo", "string"}, - } - }; - return result; - } -}; -*/ - struct lock { lock() = default; lock(const account_name& from, const account_name& to, const share_type& amount) @@ -61,21 +141,6 @@ struct lock { } }; -/* -template<> -struct get_struct { - static const struct_def& type() { - static struct_def result = { "lock", "", { - {"from", "account_name"}, - {"to", "account_name"}, - {"amount", "share_type"}, - } - }; - return result; - } -}; -*/ - struct unlock { unlock() = default; unlock(const account_name& account, const share_type& amount) @@ -94,19 +159,6 @@ struct unlock { } }; -/* -template<> struct get_struct { - static const struct_def& type() { - static struct_def result = { "unlock", "", { - {"account", "account_name"}, - {"amount", "share_type"}, - } - }; - return result; - } -}; -*/ - struct claim { claim() = default; claim(const account_name& account, const share_type& amount) @@ -125,20 +177,6 @@ struct claim { } }; -/* -template<> struct get_struct { - static const struct_def& type() { - static struct_def result = { "claim", "", { - {"account", "account_name"}, - {"amount", "share_type"}, - } - }; - return result; - } -}; -*/ - - struct newaccount { newaccount() = default; newaccount(const account_name& creator, const account_name& name, const authority& owner, const authority& active, const authority& recovery, const asset& deposit) @@ -161,34 +199,16 @@ struct newaccount { } }; -/* -template<> struct get_struct { - static const struct_def& type() { - static struct_def result = { "newaccount", "", { - {"creator", "account_name"}, - {"name", "account_name"}, - {"owner", "authority"}, - {"active", "authority"}, - {"recovery", "authority"}, - {"deposit", "asset"}, - } - }; - return result; - } -}; -*/ - struct setcode { setcode() = default; - setcode(const account_name& account, const uint8_t& vmtype, const uint8_t& vmversion, const bytes& code/*, const abi& abi*/) + setcode(const account_name& account, const uint8& vmtype, const uint8& vmversion, const bytes& code/*, const abi& abi*/) :account(account), vmtype(vmtype), vmversion(vmversion), code(code)//, abi(abi) {} account_name account; - uint8_t vmtype; - uint8_t vmversion; + uint8 vmtype; + uint8 vmversion; bytes code; - // abi abi; static scope_name get_scope() { return config::system_account_name; @@ -199,21 +219,23 @@ struct setcode { } }; -/* -template<> struct get_struct { - static const struct_def& type() { - static struct_def result = { "setcode", "", { - {"account", "account_name"}, - {"vmtype", "uint8_t"}, - {"vmversion", "uint8_t"}, - {"code", "bytes"} -// {"abi", "abi"}, - } - }; - return result; +struct setabi { + setabi() = default; + setabi(const account_name& account, const abi_def& abi) + :account(account), abi(abi) + {} + + account_name account; + abi_def abi; + + static scope_name get_scope() { + return config::system_account_name; + } + + static action_name get_name() { + return N(setabi); } }; -*/ struct setproducer { setproducer() = default; @@ -234,20 +256,6 @@ struct setproducer { } }; -/* -template<> struct get_struct { - static const struct_def& type() { - static struct_def result = { "setproducer", "", { - {"name", "account_name"}, - {"key", "public_key"}, - {"configuration", "chain_config"}, - } - }; - return result; - } -}; -*/ - struct okproducer { okproducer() = default; okproducer(const account_name& voter, const account_name& producer, const int8_t& approve) @@ -267,20 +275,6 @@ struct okproducer { } }; -/* -template<> struct get_struct { - static const struct_def& type() { - static struct_def result = { "okproducer", "", { - {"voter", "account_name"}, - {"producer", "account_name"}, - {"approve", "int8_t"}, - } - }; - return result; - } -}; -*/ - struct setproxy { setproxy() = default; setproxy(const account_name& stakeholder, const account_name& proxy) @@ -299,19 +293,6 @@ struct setproxy { } }; -/* -template<> struct get_struct { - static const struct_def& type() { - static struct_def result = { "setproxy", "", { - {"stakeholder", "account_name"}, - {"proxy", "account_name"}, - } - }; - return result; - } -}; -*/ - struct updateauth { updateauth() = default; updateauth(const account_name& account, const permission_name& permission, const permission_name& parent, const authority& authority) @@ -321,7 +302,7 @@ struct updateauth { account_name account; permission_name permission; permission_name parent; - authority authority; + authority authority; static scope_name get_scope() { return config::system_account_name; @@ -332,21 +313,6 @@ struct updateauth { } }; -/* -template<> struct get_struct { - static const struct_def& type() { - static struct_def result = { "updateauth", "", { - {"account", "account_name"}, - {"permission", "permission_name"}, - {"parent", "permission_name"}, - {"authority", "authority"}, - } - }; - return result; - } -}; -*/ - struct deleteauth { deleteauth() = default; deleteauth(const account_name& account, const permission_name& permission) @@ -365,19 +331,6 @@ struct deleteauth { } }; -/* -template<> struct get_struct { - static const struct_def& type() { - static struct_def result = { "deleteauth", "", { - {"account", "account_name"}, - {"permission", "permission_name"}, - } - }; - return result; - } -}; -*/ - struct linkauth { linkauth() = default; linkauth(const account_name& account, const account_name& code, const action_name& type, const permission_name& requirement) @@ -386,7 +339,7 @@ struct linkauth { account_name account; account_name code; - action_name type; + action_name type; permission_name requirement; static scope_name get_scope() { @@ -398,21 +351,6 @@ struct linkauth { } }; -/* -template<> struct get_struct { - static const struct_def& type() { - static struct_def result = { "linkauth", "", { - {"account", "account_name"}, - {"code", "account_name"}, - {"type", "action_name"}, - {"requirement", "permission_name"}, - } - }; - return result; - } -}; -*/ - struct unlinkauth { unlinkauth() = default; unlinkauth(const account_name& account, const account_name& code, const action_name& type) @@ -432,28 +370,39 @@ struct unlinkauth { } }; -/* -template<> struct get_struct { - static const struct_def& type() { - static struct_def result = { "unlinkauth", "", { - {"account", "account_name"}, - {"code", "account_name"}, - {"type", "action_name"}, - } - }; - return result; +using nonce_type = name; +struct nonce { + nonce() = default; + nonce(const nonce_type& value) + :value(value) + {} + + nonce_type value; + + static scope_name get_scope() { + return config::system_account_name; + } + + static action_name get_name() { + return N(nonce); } }; -*/ } } } /// namespace eosio::chain::contracts +FC_REFLECT( eosio::chain::contracts::type_def , (new_type_name)(type) ) +FC_REFLECT( eosio::chain::contracts::field_def , (name)(type) ) +FC_REFLECT( eosio::chain::contracts::struct_def , (name)(base)(fields) ) +FC_REFLECT( eosio::chain::contracts::action_def , (name)(type) ) +FC_REFLECT( eosio::chain::contracts::table_def , (name)(index_type)(key_names)(key_types)(type) ) +FC_REFLECT( eosio::chain::contracts::abi_def , (types)(structs)(actions)(tables) ) FC_REFLECT( eosio::chain::contracts::transfer , (from)(to)(amount)(memo) ) FC_REFLECT( eosio::chain::contracts::lock , (from)(to)(amount) ) FC_REFLECT( eosio::chain::contracts::unlock , (account)(amount) ) FC_REFLECT( eosio::chain::contracts::claim , (account)(amount) ) FC_REFLECT( eosio::chain::contracts::newaccount , (creator)(name)(owner)(active)(recovery)(deposit) ) FC_REFLECT( eosio::chain::contracts::setcode , (account)(vmtype)(vmversion)(code) ) //abi +FC_REFLECT( eosio::chain::contracts::setabi , (account)(abi) ) FC_REFLECT( eosio::chain::contracts::setproducer , (name)(key)(configuration) ) FC_REFLECT( eosio::chain::contracts::okproducer , (voter)(producer)(approve) ) FC_REFLECT( eosio::chain::contracts::setproxy , (stakeholder)(proxy) ) @@ -461,3 +410,4 @@ FC_REFLECT( eosio::chain::contracts::updateauth , (account FC_REFLECT( eosio::chain::contracts::deleteauth , (account)(permission) ) FC_REFLECT( eosio::chain::contracts::linkauth , (account)(code)(type)(requirement) ) FC_REFLECT( eosio::chain::contracts::unlinkauth , (account)(code)(type) ) +FC_REFLECT( eosio::chain::contracts::nonce , (value) ) diff --git a/plugins/CMakeLists.txt b/plugins/CMakeLists.txt index 05f5c08eb..2308fd493 100644 --- a/plugins/CMakeLists.txt +++ b/plugins/CMakeLists.txt @@ -1,7 +1,6 @@ add_subdirectory(net_plugin) #add_subdirectory(p2p_plugin) add_subdirectory(http_plugin) -add_subdirectory(database_plugin) add_subdirectory(db_plugin) add_subdirectory(chain_plugin) add_subdirectory(chain_api_plugin) diff --git a/plugins/chain_plugin/CMakeLists.txt b/plugins/chain_plugin/CMakeLists.txt index 6ac16f0ae..61f7f54a9 100644 --- a/plugins/chain_plugin/CMakeLists.txt +++ b/plugins/chain_plugin/CMakeLists.txt @@ -3,7 +3,7 @@ add_library( chain_plugin chain_plugin.cpp ${HEADERS} ) -target_link_libraries( chain_plugin database_plugin db_plugin eos_native_contract eos_chain appbase ) +target_link_libraries( chain_plugin db_plugin eos_native_contract eos_chain appbase ) target_include_directories( chain_plugin PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/include" ) install( TARGETS diff --git a/plugins/chain_plugin/chain_plugin.cpp b/plugins/chain_plugin/chain_plugin.cpp index 2a8599749..fc680dae7 100644 --- a/plugins/chain_plugin/chain_plugin.cpp +++ b/plugins/chain_plugin/chain_plugin.cpp @@ -136,15 +136,16 @@ void chain_plugin::plugin_initialize(const variables_map& options) { } if (options.at("replay-blockchain").as()) { + fc::remove_all(app().data_dir() / default_shared_memory_dir); ilog("Replay requested: wiping database"); - app().get_plugin().wipe_database(); if (db_plugin* db = app().find_plugin()) { db->wipe_database(); } } if (options.at("resync-blockchain").as()) { + fc::remove_all(app().data_dir() / default_shared_memory_dir); ilog("Resync requested: wiping blocks"); - app().get_plugin().wipe_database(); + if (db_plugin* db = app().find_plugin()) { db->wipe_database(); } @@ -192,10 +193,8 @@ using applied_irreversible_block_func = typename decltype(((chain_controller*)nu void chain_plugin::plugin_startup() { try { - auto& db = app().get_plugin().db(); optional applied_func; - FC_ASSERT( fc::exists( my->genesis_file ), "unable to find genesis file '${f}', check --genesis-json argument", ("f",my->genesis_file.generic_string()) ); @@ -292,28 +291,27 @@ read_only::get_info_results read_only::get_info(const read_only::get_info_params }; } -#warning TODO: ABI -/*types::abi getAbi( const chain_controller& db, const name& account ) { +abi_def get_abi( const chain_controller& db, const name& account ) { const auto& d = db.get_database(); const auto& code_accnt = d.get( account ); - eosio::types::abi abi; - types::abi_serializer::to_abi(code_accnt.abi, abi); + abi_def abi; + abi_serializer::to_abi(code_accnt.abi, abi); return abi; } -string getTableType( const types::abi& abi, const name& tablename ) { +string get_table_type( const abi_def& abi, const name& table_name ) { for( const auto& t : abi.tables ) { - if( t.table_name == tablename ){ + if( t.name == table_name ){ return t.index_type; } } - FC_ASSERT( !"ABI does not define table", "Table ${table} not specified in ABI", ("table",tablename) ); + FC_ASSERT( !"ABI does not define table", "Table ${table} not specified in ABI", ("table",table_name) ); } read_only::get_table_rows_result read_only::get_table_rows( const read_only::get_table_rows_params& p )const { - const types::abi abi = getAbi( db, p.code ); - auto table_type = getTableType( abi, p.table ); + const abi_def abi = get_abi( db, p.code ); + auto table_type = get_table_type( abi, p.table ); auto table_key = PRIMARY; if( table_type == KEYi64 ) { @@ -335,7 +333,7 @@ read_only::get_table_rows_result read_only::get_table_rows( const read_only::get } FC_ASSERT( false, "invalid table type/key ${type}/${key}", ("type",table_type)("key",table_key)("abi",abi)); } -*/ + read_only::get_block_results read_only::get_block(const read_only::get_block_params& params) const { try { if (auto block = db.fetch_block_by_id(fc::json::from_string(params.block_num_or_id).as())) @@ -390,11 +388,12 @@ read_only::get_code_results read_only::get_code( const get_code_params& params ) result.wast = wasm_to_wast( (const uint8_t*)accnt.code.data(), accnt.code.size() ); result.code_hash = fc::sha256::hash( accnt.code.data(), accnt.code.size() ); } -#warning TODO: ABI - /*eosio::types::abi abi; - if( types::abi_serializer::to_abi(accnt.abi, abi) ) { + + abi_def abi; + if( abi_serializer::to_abi(accnt.abi, abi) ) { result.abi = std::move(abi); - }*/ + } + return result; } @@ -436,19 +435,27 @@ read_only::get_account_results read_only::get_account( const get_account_params& return result; } -#warning TODO: ABI -/* -read_only::abi_json_to_bin_result read_only::abi_json_to_bin( const read_only::abi_json_to_bin_params& params )const { +read_only::abi_json_to_bin_result read_only::abi_json_to_bin( const read_only::abi_json_to_bin_params& params )const try { abi_json_to_bin_result result; - result.binargs = db.message_to_binary( params.code, params.action, params.args ); + const auto& code_account = db.get_database().get( params.code ); + abi_def abi; + if( abi_serializer::to_abi(code_account.abi, abi) ) { + abi_serializer abis( abi ); + result.binargs = abis.variant_to_binary( abis.get_action_type( params.action ), params.args ); + } return result; -} +} FC_CAPTURE_AND_RETHROW( (params.code)(params.action)(params.args) ) + read_only::abi_bin_to_json_result read_only::abi_bin_to_json( const read_only::abi_bin_to_json_params& params )const { abi_bin_to_json_result result; - result.args = db.message_from_binary( params.code, params.action, params.binargs ); + const auto& code_account = db.get_database().get( params.code ); + abi_def abi; + if( abi_serializer::to_abi(code_account.abi, abi) ) { + abi_serializer abis( abi ); + result.args = abis.binary_to_variant( abis.get_action_type( params.action ), params.binargs ); + } return result; } - */ read_only::get_required_keys_result read_only::get_required_keys( const get_required_keys_params& params )const { signed_transaction pretty_input; diff --git a/plugins/chain_plugin/include/eos/chain_plugin/chain_plugin.hpp b/plugins/chain_plugin/include/eos/chain_plugin/chain_plugin.hpp index bee6b5499..9e76fffee 100644 --- a/plugins/chain_plugin/include/eos/chain_plugin/chain_plugin.hpp +++ b/plugins/chain_plugin/include/eos/chain_plugin/chain_plugin.hpp @@ -11,11 +11,7 @@ #include #include #include - -// TODO: hook in new abi stuff here -//#include - -#include +#include #include @@ -33,6 +29,8 @@ namespace eosio { using chain::asset; using chain::authority; using chain::account_name; + using chain::contracts::abi_def; + using chain::contracts::abi_serializer; namespace chain_apis { struct empty{}; @@ -95,7 +93,7 @@ public: name name; string wast; fc::sha256 code_hash; - //optional abi; + optional abi; }; struct get_code_params { @@ -212,13 +210,12 @@ public: } template - read_only::get_table_rows_result get_table_rows_ex( const read_only::get_table_rows_params& p/*, const types::abi& abi */)const { + read_only::get_table_rows_result get_table_rows_ex( const read_only::get_table_rows_params& p, const abi_def& abi )const { read_only::get_table_rows_result result; const auto& d = db.get_database(); - // TODO: ABI stuff - //types::abi_serializer abis; - //abis.setAbi(abi); + abi_serializer abis; + abis.set_abi(abi); const auto& idx = d.get_index(); auto lower = idx.lower_bound( boost::make_tuple(p.scope, p.code, p.table ) ); @@ -241,7 +238,7 @@ public: copy_row(*itr, data); if( p.json ) { - //result.rows.emplace_back(abis.binary_to_variant(abis.get_table_type(p.table), data) ); + result.rows.emplace_back(abis.binary_to_variant(abis.get_table_type(p.table), data) ); } else { result.rows.emplace_back(fc::variant(data)); } @@ -284,7 +281,7 @@ public: class chain_plugin : public plugin { public: - APPBASE_PLUGIN_REQUIRES((database_plugin)) + APPBASE_PLUGIN_REQUIRES() chain_plugin(); virtual ~chain_plugin(); @@ -337,8 +334,7 @@ FC_REFLECT( eosio::chain_apis::read_only::get_table_rows_params, (json)(table_ke FC_REFLECT( eosio::chain_apis::read_only::get_table_rows_result, (rows)(more) ); FC_REFLECT( eosio::chain_apis::read_only::get_account_results, (name)(eos_balance)(staked_balance)(unstaking_balance)(last_unstaking_time)(permissions)(producer) ) -//TODO: ABI STUFF -FC_REFLECT( eosio::chain_apis::read_only::get_code_results, (name)(code_hash)(wast)/*(abi)*/ ) +FC_REFLECT( eosio::chain_apis::read_only::get_code_results, (name)(code_hash)(wast)(abi) ) FC_REFLECT( eosio::chain_apis::read_only::get_account_params, (name) ) FC_REFLECT( eosio::chain_apis::read_only::get_code_params, (name) ) FC_REFLECT( eosio::chain_apis::read_only::producer_info, (name) ) diff --git a/plugins/database_plugin/CMakeLists.txt b/plugins/database_plugin/CMakeLists.txt deleted file mode 100644 index 98657879f..000000000 --- a/plugins/database_plugin/CMakeLists.txt +++ /dev/null @@ -1,16 +0,0 @@ -file(GLOB HEADERS "include/eos/database_plugin/*.hpp") -add_library( database_plugin - database_plugin.cpp - ${HEADERS} ) - -target_link_libraries( database_plugin appbase chainbase fc ) -target_include_directories( database_plugin PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/include" ) - -install( TARGETS - database_plugin - - RUNTIME DESTINATION bin - LIBRARY DESTINATION lib - ARCHIVE DESTINATION lib -) -install( FILES ${HEADERS} DESTINATION "include/eos/database_plugin" ) diff --git a/plugins/database_plugin/database_plugin.cpp b/plugins/database_plugin/database_plugin.cpp deleted file mode 100644 index a13ba3530..000000000 --- a/plugins/database_plugin/database_plugin.cpp +++ /dev/null @@ -1,77 +0,0 @@ -/** - * @file - * @copyright defined in eos/LICENSE.txt - */ -#include - -#include -#include - -namespace eosio { - -class database_plugin_impl { -public: - bool readonly = false; - uint64_t shared_memory_size = 0; - bfs::path shared_memory_dir; - - fc::optional db; -}; - -database_plugin::database_plugin() : my(new database_plugin_impl){} -database_plugin::~database_plugin(){} - -void database_plugin::set_program_options(options_description&, options_description& cfg) { - cfg.add_options() - ("readonly", bpo::value()->default_value(false), "open the database in read only mode") - ("shared-file-dir", bpo::value()->default_value("blockchain"), - "the location of the chain shared memory files (absolute path or relative to application data dir)") - ("shared-file-size", bpo::value()->default_value(8*1024), - "Minimum size MB of database shared memory file") - ; -} - -void database_plugin::wipe_database() { - if (!my->shared_memory_dir.empty() && !my->db.valid()) - fc::remove_all(my->shared_memory_dir); - else - elog("ERROR: database_plugin::wipe_database() called before configuration or after startup. Ignoring."); -} - -void database_plugin::plugin_initialize(const variables_map& options) { - my->shared_memory_dir = app().data_dir() / "blockchain"; - if(options.count("shared-file-dir")) { - auto sfd = options.at("shared-file-dir").as(); - if(sfd.is_relative()) - my->shared_memory_dir = app().data_dir() / sfd; - else - my->shared_memory_dir = sfd; - } - my->shared_memory_size = options.at("shared-file-size").as() * 1024 * 1024; - my->readonly = options.at("readonly").as(); -} - -void database_plugin::plugin_startup() { - using chainbase::database; - my->db = chainbase::database(my->shared_memory_dir, - my->readonly? database::read_only : database::read_write, - my->shared_memory_size); -} - -void database_plugin::plugin_shutdown() { - ilog("closing database"); - my->db.reset(); - ilog("database closed successfully"); -} - -chainbase::database& database_plugin::db() { - assert(my->db.valid()); - return *my->db; -} - -const chainbase::database& database_plugin::db() const { - assert(my->db.valid()); - return *my->db; -} - -} diff --git a/plugins/database_plugin/include/eos/database_plugin/database_plugin.hpp b/plugins/database_plugin/include/eos/database_plugin/database_plugin.hpp deleted file mode 100644 index 6f01c515e..000000000 --- a/plugins/database_plugin/include/eos/database_plugin/database_plugin.hpp +++ /dev/null @@ -1,41 +0,0 @@ -/** - * @file - * @copyright defined in eos/LICENSE.txt - */ -#pragma once -#include - -#include - -namespace eosio { -using namespace appbase; - -/** - * This is a template plugin, intended to serve as a starting point for making new plugins - */ -class database_plugin : public appbase::plugin { -public: - database_plugin(); - virtual ~database_plugin(); - - APPBASE_PLUGIN_REQUIRES() - virtual void set_program_options(options_description&, options_description& cfg) override; - - // This may only be called after plugin_initialize() and before plugin_startup()! - void wipe_database(); - - void plugin_initialize(const variables_map& options); - void plugin_startup(); - void plugin_shutdown(); - - - // This may only be called after plugin_startup()! - chainbase::database& db(); - // This may only be called after plugin_startup()! - const chainbase::database& db() const; - -private: - std::unique_ptr my; -}; - -} -- GitLab