Implement field_reflector and assert_op

This commit is contained in:
theoreticalbts 2015-06-19 15:48:00 -04:00
parent a2b9bc6d27
commit da77990b72
19 changed files with 817 additions and 7 deletions

View file

@ -1,17 +1,42 @@
file(GLOB HEADERS "include/graphene/chain/*.hpp") file(GLOB HEADERS "include/graphene/chain/*.hpp")
add_executable( field_reflector
field_reflector.cpp
types.cpp
type_id.cpp
address.cpp
key_object.cpp
${HEADERS} )
target_include_directories( field_reflector
PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/include" )
target_link_libraries( field_reflector fc graphene_db )
add_custom_command( OUTPUT db_reflect_cmp.cpp
COMMAND field_reflector db_reflect_cmp.tmpl db_reflect_cmp.cpp.new
COMMAND ${CMAKE_COMMAND} -E copy_if_different db_reflect_cmp.cpp.new db_reflect_cmp.cpp
COMMAND ${CMAKE_COMMAND} -E remove db_reflect_cmp.cpp.new
DEPENDS field_reflector db_reflect_cmp.tmpl
)
## SORT .cpp by most likely to change / break compile ## SORT .cpp by most likely to change / break compile
add_library( graphene_chain add_library( graphene_chain
types.cpp types.cpp
type_id.cpp type_id.cpp
db_reflect_cmp.cpp
address.cpp address.cpp
asset.cpp asset.cpp
predicate.cpp
operations.cpp operations.cpp
evaluator.cpp evaluator.cpp
global_parameters_evaluator.cpp global_parameters_evaluator.cpp
account_evaluator.cpp account_evaluator.cpp
assert_evaluator.cpp
witness_evaluator.cpp witness_evaluator.cpp
delegate_evaluator.cpp delegate_evaluator.cpp
asset_evaluator.cpp asset_evaluator.cpp

View file

@ -0,0 +1,92 @@
/*
* Copyright (c) 2015, Cryptonomex, Inc.
* All rights reserved.
*
* This source code is provided for evaluation in private test networks only, until September 8, 2015. After this date, this license expires and
* the code may not be used, modified or distributed for any purpose. Redistribution and use in source and binary forms, with or without modification,
* are permitted until September 8, 2015, provided that the following conditions are met:
*
* 1. The code and/or derivative works are used only for private test networks consisting of no more than 10 P2P nodes.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <graphene/chain/assert_evaluator.hpp>
#include <graphene/chain/database.hpp>
#include <graphene/chain/predicate.hpp>
#include <sstream>
namespace graphene { namespace chain {
namespace detail {
struct predicate_check_visitor
{
predicate_check_visitor( const database& d ): _db(d){}
typedef bool result_type;
template<typename Predicate> bool operator()( const Predicate& pred )const
{
return pred.check_predicate( _db );
}
const database& _db;
};
} // graphene::chain::detail
void_result assert_evaluator::do_evaluate( const assert_operation& o )
{
const database& _db = db();
uint32_t skip = _db.get_node_properties().skip_flags;
// TODO: Skip flags
if( skip & database::skip_assert_evaluation )
return void_result();
for( const vector<char>& s_pred : o.predicates )
{
std::istringstream is( string( s_pred.begin(), s_pred.end() ) );
// de-serialize just the static_variant tag
unsigned_int t;
fc::raw::unpack( is, t );
// everyone checks: delegates must have allocated an opcode for it
FC_ASSERT( t < _db.get_global_properties().parameters.max_predicate_opcode );
if( t >= predicate::count() )
{
//
// delegates allocated an opcode, but our client doesn't know
// the semantics (i.e. we are running an old client)
//
// skip_unknown_predicate indicates we're cool with assuming
// unknown predicates pass
//
if( skip & database::skip_unknown_predicate )
continue;
//
// ok, unknown predicate must die
//
FC_ASSERT( false, "unknown predicate" );
}
// rewind to beginning, unpack it, and check it
is.clear();
is.seekg(0);
predicate pred;
fc::raw::unpack( is, pred );
bool pred_passed = pred.visit( detail::predicate_check_visitor( _db ) );
FC_ASSERT( pred_passed );
}
return void_result();
}
void_result assert_evaluator::do_apply( const assert_operation& o )
{
// assert_operation is always a no-op
return void_result();
}
} } // graphene::chain

View file

@ -36,6 +36,7 @@
#include <graphene/chain/account_evaluator.hpp> #include <graphene/chain/account_evaluator.hpp>
#include <graphene/chain/asset_evaluator.hpp> #include <graphene/chain/asset_evaluator.hpp>
#include <graphene/chain/assert_evaluator.hpp>
#include <graphene/chain/custom_evaluator.hpp> #include <graphene/chain/custom_evaluator.hpp>
#include <graphene/chain/delegate_evaluator.hpp> #include <graphene/chain/delegate_evaluator.hpp>
#include <graphene/chain/global_parameters_evaluator.hpp> #include <graphene/chain/global_parameters_evaluator.hpp>
@ -73,6 +74,7 @@ void database::initialize_evaluators()
register_evaluator<asset_update_feed_producers_evaluator>(); register_evaluator<asset_update_feed_producers_evaluator>();
register_evaluator<asset_settle_evaluator>(); register_evaluator<asset_settle_evaluator>();
register_evaluator<asset_global_settle_evaluator>(); register_evaluator<asset_global_settle_evaluator>();
register_evaluator<assert_evaluator>();
register_evaluator<limit_order_create_evaluator>(); register_evaluator<limit_order_create_evaluator>();
register_evaluator<limit_order_cancel_evaluator>(); register_evaluator<limit_order_cancel_evaluator>();
register_evaluator<call_order_update_evaluator>(); register_evaluator<call_order_update_evaluator>();

View file

@ -0,0 +1,43 @@
/*
* Copyright (c) 2015, Cryptonomex, Inc.
* All rights reserved.
*
* This source code is provided for evaluation in private test networks only, until September 8, 2015. After this date, this license expires and
* the code may not be used, modified or distributed for any purpose. Redistribution and use in source and binary forms, with or without modification,
* are permitted until September 8, 2015, provided that the following conditions are met:
*
* 1. The code and/or derivative works are used only for private test networks consisting of no more than 10 P2P nodes.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
${generated_file_banner}
/*
object_descriptor = ${object_descriptor}
*/
#include <graphene/chain/db_reflect_cmp.hpp>
#include <graphene/chain/db_reflect_cmp_impl.hpp>
#include <graphene/chain/wild_object.hpp>
#include <graphene/db/object_database.hpp>
namespace graphene { namespace chain { namespace impl {
bool cmp_attr_impl(
const object& obj,
uint16_t field_num,
const vector<char>& lit,
uint8_t opc
)
{
${cmp_attr_impl_body}
}
} } } // graphene::chain::detail

View file

@ -0,0 +1,233 @@
/*
* Copyright (c) 2015, Cryptonomex, Inc.
* All rights reserved.
*
* This source code is provided for evaluation in private test networks only, until September 8, 2015. After this date, this license expires and
* the code may not be used, modified or distributed for any purpose. Redistribution and use in source and binary forms, with or without modification,
* are permitted until September 8, 2015, provided that the following conditions are met:
*
* 1. The code and/or derivative works are used only for private test networks consisting of no more than 10 P2P nodes.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <fc/io/json.hpp>
#include <fc/variant.hpp>
#include <fc/variant_object.hpp>
#include <graphene/chain/wild_object.hpp>
#include <algorithm>
#include <iostream>
#include <map>
#include <sstream>
#include <string>
#include <vector>
using namespace graphene::chain;
fc::mutable_variant_object g_vo_object_types;
std::vector< fc::mutable_variant_object > g_vo_fields;
struct serialize_object_type_member_visitor
{
public:
template<typename Member, class Class, Member (Class::*member)>
void operator()( const char* name )const
{
fc::mutable_variant_object vo;
vo["name"] = name;
vo["type"] = fc::get_typename<Member>::name();
vo["id"] = g_vo_fields.size();
g_vo_fields.push_back( vo );
}
};
struct serialize_object_type_visitor
{
typedef void result_type;
int t = 0;
serialize_object_type_visitor(int _t ):t(_t){}
template<typename Type>
result_type operator()( const Type& op )const
{
fc::mutable_variant_object vo;
vo["space_id"] = Type::space_id;
vo["type_id"] = Type::type_id;
g_vo_fields.clear();
// visit all members
fc::reflector<Type>::visit( serialize_object_type_member_visitor() );
vo["fields"] = g_vo_fields;
g_vo_object_types[ fc::get_typename<Type>::name() ] = vo;
}
};
struct getattr_switch_table_entry
{
uint32_t _switch_val; // (space << 24) | (type << 16) | fieldnum
string _object_typename;
string _field_typename;
string _field_name;
};
vector< getattr_switch_table_entry > build_switch_table()
{
vector< getattr_switch_table_entry > result;
for( const auto& item : g_vo_object_types )
{
const variant_object& vo = item.value().get_object();
uint32_t top = (vo["space_id"].as_uint64() << 24) | (vo["type_id"].as_uint64() << 16);
for( const auto& field : vo["fields"].get_array() )
{
getattr_switch_table_entry e;
e._switch_val = top | field["id"].as_uint64();
e._object_typename = item.key();
e._field_typename = field["type"].get_string();
e._field_name = field["name"].get_string();
result.push_back( e );
}
}
std::sort( result.begin(), result.end(),
[]( const getattr_switch_table_entry& a,
const getattr_switch_table_entry& b )
{
return a._switch_val < b._switch_val;
} );
return result;
}
std::string generate_cmp_attr_impl( const vector< getattr_switch_table_entry >& switch_table )
{
std::ostringstream out;
// switch( space )
// switch( type )
// switch( fieldnum )
// switch( opc )
std::map< uint8_t,
std::map< uint8_t,
std::map< uint16_t,
const getattr_switch_table_entry* > > > index;
for( const getattr_switch_table_entry& e : switch_table )
{
uint8_t sp = (e._switch_val >> 24) & 0xFF;
uint8_t ty = (e._switch_val >> 16) & 0xFF;
uint16_t fn = (e._switch_val ) & 0xFFFF;
auto& i0 = index;
if( i0.find( sp ) == i0.end() )
i0[sp] = std::map< uint8_t, std::map< uint16_t, const getattr_switch_table_entry* > >();
auto& i1 = i0[sp];
if( i1.find( ty ) == i1.end() )
i1[ty] = std::map< uint16_t, const getattr_switch_table_entry* >();
auto& i2 = i1[ty];
i2[fn] = &e;
}
out << " switch( obj.id.space() )\n"
" {\n";
for( const auto& e0 : index )
{
out << " case " << int( e0.first ) << ":\n"
" switch( obj.id.type() )\n"
" {\n";
for( const auto& e1 : e0.second )
{
out << " case " << int( e1.first ) << ":\n"
" switch( field_num )\n"
" {\n";
for( const auto& e2 : e1.second )
{
const std::string& ft = e2.second->_field_typename;
const std::string& ot = e2.second->_object_typename;
const std::string& fn = e2.second->_field_name;
out << " case " << int( e2.first ) << ":\n"
" {\n"
" // " << ft
<< " " << ot
<< "." << fn
<< "\n"
" const " << ft << "& dbval = object_database::cast< " << ot << " >( obj )." << fn << ";\n"
" return _cmp< " << ft << " >( dbval, lit, opc );\n"
" }\n";
}
out << " default:\n"
" FC_ASSERT( false, \"unrecognized field_num\" );\n"
" }\n";
}
out << " default:\n"
" FC_ASSERT( false, \"unrecognized object type\" );\n"
" }\n";
}
out << " default:\n"
" FC_ASSERT( false, \"unrecognized object space\" );\n"
" }\n";
return out.str();
}
static const char generated_file_banner[] =
"// _ _ __ _ _ //\n"
"// | | | | / _(_) | //\n"
"// __ _ ___ _ __ ___ _ __ __ _| |_ ___ __| | | |_ _| | ___ //\n"
"// / _` |/ _ \\ '_ \\ / _ \\ '__/ _` | __/ _ \\/ _` | | _| | |/ _ \\ //\n"
"// | (_| | __/ | | | __/ | | (_| | || __/ (_| | | | | | | __/ //\n"
"// \\__, |\\___|_| |_|\\___|_| \\__,_|\\__\\___|\\__,_| |_| |_|_|\\___| //\n"
"// __/ | //\n"
"// |___/ //\n"
"// //\n"
"// Generated by: programs/field_reflector/main.cpp //\n"
"// //\n"
"// Warning: This is a generated file, any changes made here will be //\n"
"// overwritten by the build process. If you need to change what //\n"
"// is generated here, you should either modify the reflected //\n"
"// types, or modify the code generator itself. //\n"
"// //\n"
;
int main( int argc, char** argv )
{
try
{
if( argc != 3 )
{
std::cout << "syntax: " << argv[0] << " <template_filename> <output_filename>\n";
return 1;
}
graphene::chain::impl::wild_object wo;
for( int32_t i = 0; i < wo.count(); ++i )
{
wo.set_which(i);
wo.visit( serialize_object_type_visitor(i) );
}
vector< getattr_switch_table_entry > switch_table = build_switch_table();
fc::mutable_variant_object tmpl_params;
tmpl_params["generated_file_banner"] = generated_file_banner;
tmpl_params["object_descriptor"] = fc::json::to_string( g_vo_object_types );
tmpl_params["cmp_attr_impl_body"] = generate_cmp_attr_impl( switch_table );
std::ifstream template_file( argv[1] );
std::stringstream ss;
ss << template_file.rdbuf();
std::string result = fc::format_string( ss.str(), tmpl_params );
std::ofstream result_file( argv[2] );
result_file << result;
}
catch ( const fc::exception& e ){ edump((e.to_detail_string())); }
return 0;
}

View file

@ -0,0 +1,34 @@
/*
* Copyright (c) 2015, Cryptonomex, Inc.
* All rights reserved.
*
* This source code is provided for evaluation in private test networks only, until September 8, 2015. After this date, this license expires and
* the code may not be used, modified or distributed for any purpose. Redistribution and use in source and binary forms, with or without modification,
* are permitted until September 8, 2015, provided that the following conditions are met:
*
* 1. The code and/or derivative works are used only for private test networks consisting of no more than 10 P2P nodes.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#pragma once
#include <graphene/chain/evaluator.hpp>
#include <graphene/chain/operations.hpp>
#include <graphene/chain/database.hpp>
namespace graphene { namespace chain {
class assert_evaluator : public evaluator<assert_evaluator>
{
public:
typedef assert_operation operation_type;
void_result do_evaluate( const assert_operation& o );
void_result do_apply( const assert_operation& o );
};
} } // graphene::chain

View file

@ -83,6 +83,7 @@
#define GRAPHENE_DEFAULT_CASHBACK_VESTING_THRESHOLD (GRAPHENE_BLOCKCHAIN_PRECISION*int64_t(100)) #define GRAPHENE_DEFAULT_CASHBACK_VESTING_THRESHOLD (GRAPHENE_BLOCKCHAIN_PRECISION*int64_t(100))
#define GRAPHENE_DEFAULT_BURN_PERCENT_OF_FEE (20*GRAPHENE_1_PERCENT) #define GRAPHENE_DEFAULT_BURN_PERCENT_OF_FEE (20*GRAPHENE_1_PERCENT)
#define GRAPHENE_WITNESS_PAY_PERCENT_PRECISION (1000000000) #define GRAPHENE_WITNESS_PAY_PERCENT_PRECISION (1000000000)
#define GRAPHENE_DEFAULT_MAX_ASSERT_OPCODE 1
#define GRAPHENE_GENESIS_TIMESTAMP (1431700000) /// Should be divisible by GRAPHENE_DEFAULT_BLOCK_INTERVAL #define GRAPHENE_GENESIS_TIMESTAMP (1431700000) /// Should be divisible by GRAPHENE_DEFAULT_BLOCK_INTERVAL
// counter initialization values used to derive near and far future seeds for shuffling witnesses // counter initialization values used to derive near and far future seeds for shuffling witnesses

View file

@ -109,7 +109,7 @@ namespace graphene { namespace chain {
{ {
skip_nothing = 0x00, skip_nothing = 0x00,
skip_delegate_signature = 0x01, ///< used while reindexing skip_delegate_signature = 0x01, ///< used while reindexing
skip_transaction_signatures = 0x02, ///< used by non delegate nodes skip_transaction_signatures = 0x02, ///< used by non-witness nodes
skip_undo_block = 0x04, ///< used while reindexing skip_undo_block = 0x04, ///< used while reindexing
skip_undo_transaction = 0x08, ///< used while applying block skip_undo_transaction = 0x08, ///< used while applying block
skip_transaction_dupe_check = 0x10, ///< used while reindexing skip_transaction_dupe_check = 0x10, ///< used while reindexing
@ -117,7 +117,9 @@ namespace graphene { namespace chain {
skip_block_size_check = 0x40, ///< used when applying locally generated transactions skip_block_size_check = 0x40, ///< used when applying locally generated transactions
skip_tapos_check = 0x80, ///< used while reindexing -- note this skips expiration check as well skip_tapos_check = 0x80, ///< used while reindexing -- note this skips expiration check as well
skip_authority_check = 0x100, ///< used while reindexing -- disables any checking of authority on transactions skip_authority_check = 0x100, ///< used while reindexing -- disables any checking of authority on transactions
skip_merkle_check = 0x200 ///< used while reindexing skip_merkle_check = 0x200, ///< used while reindexing
skip_assert_evaluation = 0x400, ///< used while reindexing
skip_unknown_predicate = 0x800 ///< used by non-witness nodes to allow unknown predicates
}; };
void open(const fc::path& data_dir, const genesis_state_type& initial_allocation = genesis_state_type()); void open(const fc::path& data_dir, const genesis_state_type& initial_allocation = genesis_state_type());

View file

@ -0,0 +1,60 @@
/*
* Copyright (c) 2015, Cryptonomex, Inc.
* All rights reserved.
*
* This source code is provided for evaluation in private test networks only, until September 8, 2015. After this date, this license expires and
* the code may not be used, modified or distributed for any purpose. Redistribution and use in source and binary forms, with or without modification,
* are permitted until September 8, 2015, provided that the following conditions are met:
*
* 1. The code and/or derivative works are used only for private test networks consisting of no more than 10 P2P nodes.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#pragma once
#include <vector>
#include <graphene/db/object.hpp>
namespace graphene { namespace chain {
enum comparison_opcode
{
opc_equal_to,
opc_not_equal_to,
opc_greater,
opc_less,
opc_greater_equal,
opc_less_equal
};
namespace impl {
/**
* Compare the given field of the given object to the literal string.
* The comparison opcode is specified by opc, which should be one
* of comparison_opcode.
*
* The default behavior is to only allow opc_equal_to or
* opc_not_equal_to, and implement these based on comparing the
* serialized field to the given bytes.
*
* To override the default behavior, provide a template override
* for _cmp() in db_reflect_cmp_impl.hpp. Beware adding such an
* override will create a witness-only hardfork!
*/
bool cmp_attr_impl(
const graphene::db::object& obj,
uint16_t field_num,
const std::vector<char>& lit,
uint8_t opc
);
}
} }

View file

@ -0,0 +1,115 @@
/*
* Copyright (c) 2015, Cryptonomex, Inc.
* All rights reserved.
*
* This source code is provided for evaluation in private test networks only, until September 8, 2015. After this date, this license expires and
* the code may not be used, modified or distributed for any purpose. Redistribution and use in source and binary forms, with or without modification,
* are permitted until September 8, 2015, provided that the following conditions are met:
*
* 1. The code and/or derivative works are used only for private test networks consisting of no more than 10 P2P nodes.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#pragma once
#include <fc/io/raw.hpp>
#include <cstdint>
#include <vector>
//
// This file implements the comparison used by the assert op.
// The entry point for comparison is _cmp(), it can be specialized for
// different types. The default implementation defers to _ser_eq_cmp()
// which only allows equality comparisons, and asserts
//
namespace graphene { namespace chain { namespace impl {
// useful for types which have all comparison ops implemented
template< typename T >
static bool _full_cmp( const T& a, const T& b, uint8_t opc )
{
switch( opc )
{
case opc_equal_to:
return (a == b);
case opc_not_equal_to:
return (a != b);
case opc_greater:
return (a > b);
case opc_less:
return (a < b);
case opc_greater_equal:
return (a >= b);
case opc_less_equal:
return (a <= b);
default:
FC_ASSERT( false, "unknown comparison operator" );
}
}
// useful for types which have operator== implemented
template< typename T >
static bool _eq_cmp( const T& a, const T& b, uint8_t opc )
{
switch( opc )
{
case opc_equal_to:
return (a == b);
case opc_not_equal_to:
return !(a == b);
default:
FC_ASSERT( false, "unknown comparison operator" );
}
}
// works for every serializable type
template< typename T >
static bool _ser_eq_cmp( const T& a, const std::vector<char>& b, uint8_t opc )
{
std::vector< char > _a = fc::raw::pack( a );
return _eq_cmp( _a, b, opc );
}
/*
static bool _cmp( const fc::sha224& a, const fc::sha224& b, uint8_t opc )
{
assert( a.data_size() == b.data_size() );
int result = memcmp( a.data(), b.data(), a.data_size() );
switch( opc )
{
case opc_equal_to:
return (result == 0);
case opc_not_equal_to:
return (result != 0);
case opc_greater:
return (result > 0);
case opc_less:
return (result < 0);
case opc_greater_equal:
return (result >= 0);
case opc_less_equal:
return (result <= 0);
default:
FC_ASSERT( false, "unknown comparison operator" );
}
}
*/
// _cmp needs to be specialized for types which don't have overloads
// for all comparison operators
template< typename T >
static bool _cmp( const T& a, const std::vector<char>& b, uint8_t opc )
{
return _ser_eq_cmp( a, b, opc );
}
} } } // graphene::chain::detail

View file

@ -102,6 +102,25 @@ namespace graphene { namespace chain {
* @{ * @{
*/ */
/**
* @brief assert that some conditions are true.
* @ingroup operations
*/
struct assert_operation
{
asset fee;
account_id_type fee_paying_account;
vector< vector< char > > predicates;
flat_set<account_id_type> required_auths;
account_id_type fee_payer()const { return fee_paying_account; }
void get_required_auth(flat_set<account_id_type>& active_auth_set, flat_set<account_id_type>&)const;
share_type calculate_fee( const fee_schedule_type& k )const{ return k.assert_op_fee; }
void validate()const;
void get_balance_delta( balance_accumulator& acc, const operation_result& result = asset())const { acc.adjust( fee_payer(), -fee ); }
};
/** /**
* @brief reserves a new ID to refer to a particular key or address. * @brief reserves a new ID to refer to a particular key or address.
* @ingroup operations * @ingroup operations
@ -1339,7 +1358,8 @@ namespace graphene { namespace chain {
vesting_balance_create_operation, vesting_balance_create_operation,
vesting_balance_withdraw_operation, vesting_balance_withdraw_operation,
worker_create_operation, worker_create_operation,
custom_operation custom_operation,
assert_operation
> operation; > operation;
/// @} // operations group /// @} // operations group
@ -1568,6 +1588,8 @@ FC_REFLECT( graphene::chain::worker_create_operation,
(fee)(owner)(work_begin_date)(work_end_date)(daily_pay)(initializer) ) (fee)(owner)(work_begin_date)(work_end_date)(daily_pay)(initializer) )
FC_REFLECT( graphene::chain::custom_operation, (fee)(payer)(required_auths)(id)(data) ) FC_REFLECT( graphene::chain::custom_operation, (fee)(payer)(required_auths)(id)(data) )
FC_REFLECT( graphene::chain::assert_operation, (fee)(fee_paying_account)(predicates)(required_auths) )
FC_REFLECT( graphene::chain::void_result, ) FC_REFLECT( graphene::chain::void_result, )
FC_REFLECT_TYPENAME( graphene::chain::operation ) FC_REFLECT_TYPENAME( graphene::chain::operation )

View file

@ -0,0 +1,60 @@
/*
* Copyright (c) 2015, Cryptonomex, Inc.
* All rights reserved.
*
* This source code is provided for evaluation in private test networks only, until September 8, 2015. After this date, this license expires and
* the code may not be used, modified or distributed for any purpose. Redistribution and use in source and binary forms, with or without modification,
* are permitted until September 8, 2015, provided that the following conditions are met:
*
* 1. The code and/or derivative works are used only for private test networks consisting of no more than 10 P2P nodes.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#pragma once
#include <graphene/chain/types.hpp>
#include <vector>
namespace graphene { namespace chain {
class database;
class pred_field_lit_cmp
{
public:
pred_field_lit_cmp(
object_id_type obj_id,
uint16_t field_num,
const vector<char>& lit,
uint8_t opc
) :
_obj_id( obj_id ),
_field_num( field_num ),
_lit( lit ),
_opc( opc )
{}
pred_field_lit_cmp() {} // necessary for instantiating static_variant
~pred_field_lit_cmp() {}
bool check_predicate( const database& db )const;
object_id_type _obj_id;
uint16_t _field_num;
vector<char> _lit;
uint8_t _opc;
};
typedef static_variant<
pred_field_lit_cmp
> predicate;
} }
FC_REFLECT( graphene::chain::pred_field_lit_cmp, (_obj_id)(_field_num)(_lit)(_opc) );

View file

@ -375,6 +375,7 @@ namespace graphene { namespace chain {
uint32_t global_settle_fee; uint32_t global_settle_fee;
uint32_t worker_create_fee; ///< the cost to create a new worker uint32_t worker_create_fee; ///< the cost to create a new worker
uint32_t worker_delete_fee; ///< the cost to delete a worker uint32_t worker_delete_fee; ///< the cost to delete a worker
uint32_t assert_op_fee; ///< fee per assert operation
}; };
@ -429,6 +430,7 @@ namespace graphene { namespace chain {
bool allow_non_member_whitelists = false; ///< true if non-member accounts may set whitelists and blacklists; false otherwise bool allow_non_member_whitelists = false; ///< true if non-member accounts may set whitelists and blacklists; false otherwise
share_type witness_pay_per_block = GRAPHENE_DEFAULT_WITNESS_PAY_PER_BLOCK; ///< CORE to be allocated to witnesses (per block) share_type witness_pay_per_block = GRAPHENE_DEFAULT_WITNESS_PAY_PER_BLOCK; ///< CORE to be allocated to witnesses (per block)
share_type worker_budget_per_day = GRAPHENE_DEFAULT_WORKER_BUDGET_PER_DAY; ///< CORE to be allocated to workers (per day) share_type worker_budget_per_day = GRAPHENE_DEFAULT_WORKER_BUDGET_PER_DAY; ///< CORE to be allocated to workers (per day)
uint16_t max_predicate_opcode = GRAPHENE_DEFAULT_MAX_ASSERT_OPCODE; ///< predicate_opcode must be less than this number
void validate()const void validate()const
{ {
@ -548,6 +550,7 @@ FC_REFLECT( graphene::chain::fee_schedule_type,
(global_settle_fee) (global_settle_fee)
(worker_create_fee) (worker_create_fee)
(worker_delete_fee) (worker_delete_fee)
(assert_op_fee)
) )
FC_REFLECT( graphene::chain::chain_parameters, FC_REFLECT( graphene::chain::chain_parameters,
@ -574,6 +577,7 @@ FC_REFLECT( graphene::chain::chain_parameters,
(allow_non_member_whitelists) (allow_non_member_whitelists)
(witness_pay_per_block) (witness_pay_per_block)
(worker_budget_per_day) (worker_budget_per_day)
(max_predicate_opcode)
) )
FC_REFLECT_TYPENAME( graphene::chain::share_type ) FC_REFLECT_TYPENAME( graphene::chain::share_type )

View file

@ -0,0 +1,61 @@
/*
* Copyright (c) 2015, Cryptonomex, Inc.
* All rights reserved.
*
* This source code is provided for evaluation in private test networks only, until September 8, 2015. After this date, this license expires and
* the code may not be used, modified or distributed for any purpose. Redistribution and use in source and binary forms, with or without modification,
* are permitted until September 8, 2015, provided that the following conditions are met:
*
* 1. The code and/or derivative works are used only for private test networks consisting of no more than 10 P2P nodes.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#pragma once
#include <fc/static_variant.hpp>
#include <graphene/chain/account_object.hpp>
#include <graphene/chain/call_order_object.hpp>
#include <graphene/chain/delegate_object.hpp>
#include <graphene/chain/key_object.hpp>
#include <graphene/chain/limit_order_object.hpp>
#include <graphene/chain/operation_history_object.hpp>
#include <graphene/chain/proposal_object.hpp>
#include <graphene/chain/vesting_balance_object.hpp>
#include <graphene/chain/withdraw_permission_object.hpp>
#include <graphene/chain/witness_object.hpp>
namespace graphene { namespace chain { namespace impl {
/**
* A static_variant of all object types.
*
* Used by field_reflector, this ultimately determines the object
* types which may be inspected by pred_field_lit_cmp.
*/
typedef fc::static_variant<
//null_object,
//base_object,
key_object,
account_object,
asset_object,
force_settlement_object,
delegate_object,
witness_object,
limit_order_object,
call_order_object,
//custom_object,
proposal_object,
operation_history_object,
withdraw_permission_object,
vesting_balance_object,
worker_object
> wild_object;
} } }

View file

@ -813,4 +813,14 @@ share_type account_upgrade_operation::calculate_fee(const fee_schedule_type& k)
return k.membership_annual_fee; return k.membership_annual_fee;
} }
void assert_operation::validate()const
{
FC_ASSERT( fee.amount >= 0 );
}
void assert_operation::get_required_auth(flat_set<account_id_type>& active_auth_set, flat_set<account_id_type>&)const
{
active_auth_set.insert(fee_paying_account);
active_auth_set.insert(required_auths.begin(), required_auths.end());
}
} } // namespace graphene::chain } } // namespace graphene::chain

View file

@ -0,0 +1,34 @@
/*
* Copyright (c) 2015, Cryptonomex, Inc.
* All rights reserved.
*
* This source code is provided for evaluation in private test networks only, until September 8, 2015. After this date, this license expires and
* the code may not be used, modified or distributed for any purpose. Redistribution and use in source and binary forms, with or without modification,
* are permitted until September 8, 2015, provided that the following conditions are met:
*
* 1. The code and/or derivative works are used only for private test networks consisting of no more than 10 P2P nodes.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <graphene/chain/assert_evaluator.hpp>
#include <graphene/chain/database.hpp>
#include <graphene/chain/db_reflect_cmp.hpp>
#include <graphene/chain/predicate.hpp>
#include <sstream>
#include <vector>
namespace graphene { namespace chain {
bool pred_field_lit_cmp::check_predicate( const database& db )const
{
return graphene::chain::impl::cmp_attr_impl( db.get_object( _obj_id ), _field_num, _lit, _opc );
}
} } // graphene::chain

View file

@ -2,13 +2,13 @@
#include <graphene/chain/account_object.hpp> #include <graphene/chain/account_object.hpp>
#include <graphene/chain/asset_object.hpp> #include <graphene/chain/asset_object.hpp>
#include <graphene/chain/block_summary_object.hpp> #include <graphene/chain/block_summary_object.hpp>
#include <graphene/chain/call_order_object.hpp>
#include <graphene/chain/delegate_object.hpp> #include <graphene/chain/delegate_object.hpp>
#include <graphene/chain/global_property_object.hpp> #include <graphene/chain/global_property_object.hpp>
#include <graphene/chain/key_object.hpp> #include <graphene/chain/key_object.hpp>
#include <graphene/chain/limit_order_object.hpp> #include <graphene/chain/limit_order_object.hpp>
#include <graphene/chain/operation_history_object.hpp> #include <graphene/chain/operation_history_object.hpp>
#include <graphene/chain/proposal_object.hpp> #include <graphene/chain/proposal_object.hpp>
#include <graphene/chain/short_order_object.hpp>
#include <graphene/chain/transaction_object.hpp> #include <graphene/chain/transaction_object.hpp>
#include <graphene/chain/vesting_balance_object.hpp> #include <graphene/chain/vesting_balance_object.hpp>
#include <graphene/chain/withdraw_permission_object.hpp> #include <graphene/chain/withdraw_permission_object.hpp>
@ -60,9 +60,6 @@ const uint8_t operation_history_object::type_id;
const uint8_t proposal_object::space_id; const uint8_t proposal_object::space_id;
const uint8_t proposal_object::type_id; const uint8_t proposal_object::type_id;
const uint8_t short_order_object::space_id;
const uint8_t short_order_object::type_id;
const uint8_t transaction_object::space_id; const uint8_t transaction_object::space_id;
const uint8_t transaction_object::type_id; const uint8_t transaction_object::type_id;

View file

@ -243,6 +243,9 @@ struct operation_get_impacted_accounts
void operator()( const worker_create_operation& )const void operator()( const worker_create_operation& )const
{} {}
void operator()( const assert_operation& )const
{}
}; };
account_create_observer::~account_create_observer() account_create_observer::~account_create_observer()

View file

@ -0,0 +1,12 @@
add_executable( field_reflector main.cpp )
if( UNIX AND NOT APPLE )
set(rt_library rt )
endif()
#find_package( Gperftools QUIET )
#if( GPERFTOOLS_FOUND )
# message( STATUS "Found gperftools; compiling client with TCMalloc")
# list( APPEND PLATFORM_SPECIFIC_LIBS tcmalloc )
#endif()
target_link_libraries( field_reflector
PRIVATE graphene_app graphene_net graphene_chain graphene_utilities graphene_wallet fc ${CMAKE_DL_LIBS} ${PLATFORM_SPECIFIC_LIBS} )