merge master

This commit is contained in:
Daniel Larimer 2015-06-18 15:31:30 -04:00
commit 0a5954db70
34 changed files with 641 additions and 872 deletions

View file

@ -66,6 +66,7 @@ IF(NOT "${Boost_VERSION}" MATCHES "1.53(.*)")
ENDIF()
if( WIN32 )
message( STATUS "Configuring Graphene on WIN32")
set( DB_VERSION 60 )
set( BDB_STATIC_LIBS 1 )
@ -98,13 +99,6 @@ if( WIN32 )
SET(TCL_LIBRARY ${TCL_LIBS})
else( WIN32 ) # Apple AND Linux
list(APPEND LEVELDB_BUILD_DEFINES LEVELDB_PLATFORM_POSIX LEVELDB_ATOMIC_PRESENT)
if( APPLE )
list(APPEND LEVELDB_BUILD_DEFINES OS_MACOSX)
else() # Linux
list(APPEND LEVELDB_BUILD_DEFINES OS_LINUX)
list(APPEND LEVELDB_BUILD_LIBRARIES pthread)
endif()
find_library(READLINE_LIBRARIES NAMES readline)
find_path(READLINE_INCLUDE_DIR readline/readline.h)

View file

@ -149,9 +149,10 @@ namespace detail {
fc::create_directories(_data_dir / "blockchain/dblock");
auto nathan_key = fc::ecc::private_key::regenerate(fc::sha256::hash(string("nathan")));
genesis_allocation initial_allocation = {{graphene::chain::public_key_type(nathan_key.get_public_key()), 1}};
genesis_state_type initial_state;
initial_state.allocation_targets.emplace_back("nathan", address(public_key_type(nathan_key.get_public_key())), 1);
if( _options->count("genesis-json") )
initial_allocation = fc::json::from_file(_options->at("genesis-json").as<boost::filesystem::path>()).as<genesis_allocation>();
initial_state = fc::json::from_file(_options->at("genesis-json").as<boost::filesystem::path>()).as<genesis_state_type>();
else
dlog("Allocating all stake to ${key}", ("key", utilities::key_to_wif(nathan_key)));
@ -161,12 +162,12 @@ namespace detail {
if( _options->count("replay-blockchain") )
{
ilog("Replaying blockchain on user request.");
_chain_db->reindex(_data_dir/"blockchain", initial_allocation);
_chain_db->reindex(_data_dir/"blockchain", initial_state);
} else if( clean )
_chain_db->open(_data_dir / "blockchain", initial_allocation);
_chain_db->open(_data_dir / "blockchain", initial_state);
else {
wlog("Detected unclean shutdown. Replaying blockchain...");
_chain_db->reindex(_data_dir / "blockchain", initial_allocation);
_chain_db->reindex(_data_dir / "blockchain", initial_state);
}
reset_p2p_node(_data_dir);

View file

@ -53,6 +53,7 @@ namespace graphene { namespace chain {
checksum_type signed_block::calculate_merkle_root()const
{
if( transactions.size() == 0 ) return checksum_type();
vector<digest_type> ids;
ids.resize( ((transactions.size() + 1)/2)*2 );
for( uint32_t i = 0; i < transactions.size(); ++i )

View file

@ -1,3 +1,20 @@
/*
* 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/block_database.hpp>
namespace graphene { namespace chain {
@ -8,7 +25,7 @@ struct index_entry
uint32_t block_size = 0;
block_id_type block_id;
};
}}
}}
FC_REFLECT( graphene::chain::index_entry, (block_pos)(block_size)(block_id) );
namespace graphene { namespace chain {
@ -117,73 +134,98 @@ block_id_type block_database::fetch_block_id( uint32_t block_num )const
optional<signed_block> block_database::fetch_optional( const block_id_type& id )const
{ try {
index_entry e;
auto index_pos = sizeof(e)*block_header::num_from_id(id);
_block_num_to_pos.seekg( 0, _block_num_to_pos.end );
FC_ASSERT( _block_num_to_pos.tellg() > index_pos );
_block_num_to_pos.seekg( index_pos );
_block_num_to_pos.read( (char*)&e, sizeof(e) );
if( e.block_id != id ) return optional<signed_block>();
vector<char> data( e.block_size );
_blocks.seekg( e.block_pos );
_blocks.read( data.data(), e.block_size );
auto result = fc::raw::unpack<signed_block>(data);
FC_ASSERT( result.id() == e.block_id );
return result;
} FC_CAPTURE_AND_RETHROW( (id) ) }
{
try
{
index_entry e;
auto index_pos = sizeof(e)*block_header::num_from_id(id);
_block_num_to_pos.seekg( 0, _block_num_to_pos.end );
FC_ASSERT( _block_num_to_pos.tellg() > index_pos );
_block_num_to_pos.seekg( index_pos );
_block_num_to_pos.read( (char*)&e, sizeof(e) );
if( e.block_id != id ) return optional<signed_block>();
vector<char> data( e.block_size );
_blocks.seekg( e.block_pos );
_blocks.read( data.data(), e.block_size );
auto result = fc::raw::unpack<signed_block>(data);
FC_ASSERT( result.id() == e.block_id );
return result;
}
catch (const fc::exception&)
{
}
catch (const std::exception&)
{
}
return optional<signed_block>();
}
optional<signed_block> block_database::fetch_by_number( uint32_t block_num )const
{ try {
index_entry e;
auto index_pos = sizeof(e)*block_num;
_block_num_to_pos.seekg( 0, _block_num_to_pos.end );
FC_ASSERT( _block_num_to_pos.tellg() > index_pos );
{
try
{
index_entry e;
auto index_pos = sizeof(e)*block_num;
_block_num_to_pos.seekg( 0, _block_num_to_pos.end );
FC_ASSERT( _block_num_to_pos.tellg() > index_pos );
_block_num_to_pos.seekg( index_pos, _block_num_to_pos.beg );
// wdump((int64_t(_block_num_to_pos.tellg())) );
_block_num_to_pos.read( (char*)&e, sizeof(e) );
// wdump((block_num)(e));
_block_num_to_pos.seekg( index_pos, _block_num_to_pos.beg );
_block_num_to_pos.read( (char*)&e, sizeof(e) );
vector<char> data( e.block_size );
_blocks.seekg( e.block_pos );
_blocks.read( data.data(), e.block_size );
auto result = fc::raw::unpack<signed_block>(data);
FC_ASSERT( result.id() == e.block_id );
return result;
} FC_CAPTURE_AND_RETHROW( (block_num) ) }
vector<char> data( e.block_size );
_blocks.seekg( e.block_pos );
_blocks.read( data.data(), e.block_size );
auto result = fc::raw::unpack<signed_block>(data);
FC_ASSERT( result.id() == e.block_id );
return result;
}
catch (const fc::exception&)
{
}
catch (const std::exception&)
{
}
return optional<signed_block>();
}
optional<signed_block> block_database::last()const
{
index_entry e;
_block_num_to_pos.seekg( 0, _block_num_to_pos.end );
if( _block_num_to_pos.tellp() < sizeof(index_entry) )
return optional<signed_block>();
_block_num_to_pos.seekg( -sizeof(index_entry), _block_num_to_pos.end );
_block_num_to_pos.read( (char*)&e, sizeof(e) );
while( e.block_size == 0 && _blocks.tellg() > 0 )
try
{
_block_num_to_pos.seekg( -sizeof(index_entry), _block_num_to_pos.cur );
index_entry e;
_block_num_to_pos.seekg( 0, _block_num_to_pos.end );
if( _block_num_to_pos.tellp() < sizeof(index_entry) )
return optional<signed_block>();
_block_num_to_pos.seekg( -sizeof(index_entry), _block_num_to_pos.end );
_block_num_to_pos.read( (char*)&e, sizeof(e) );
while( e.block_size == 0 && _blocks.tellg() > 0 )
{
_block_num_to_pos.seekg( -sizeof(index_entry), _block_num_to_pos.cur );
_block_num_to_pos.read( (char*)&e, sizeof(e) );
}
if( e.block_size == 0 )
return optional<signed_block>();
vector<char> data( e.block_size );
_blocks.seekg( e.block_pos );
_blocks.read( data.data(), e.block_size );
auto result = fc::raw::unpack<signed_block>(data);
return result;
}
if( e.block_size == 0 )
return optional<signed_block>();
vector<char> data( e.block_size );
_blocks.seekg( e.block_pos );
_blocks.read( data.data(), e.block_size );
auto result = fc::raw::unpack<signed_block>(data);
//wdump((result));
return result;
catch (const fc::exception&)
{
}
catch (const std::exception&)
{
}
return optional<signed_block>();
}
} }

View file

@ -81,7 +81,18 @@ const signed_transaction& database::get_recent_transaction(const transaction_id_
* @return true if we switched forks as a result of this push.
*/
bool database::push_block( const signed_block& new_block, uint32_t skip )
{
bool result;
with_skip_flags( skip, [&]()
{
result = _push_block( new_block );
} );
return result;
}
bool database::_push_block( const signed_block& new_block )
{ try {
uint32_t skip = get_node_properties().skip_flags;
if( !(skip&skip_fork_db) )
{
auto new_head = _fork_db.push_block( new_block );
@ -182,12 +193,23 @@ bool database::push_block( const signed_block& new_block, uint32_t skip )
*/
processed_transaction database::push_transaction( const signed_transaction& trx, uint32_t skip )
{
processed_transaction result;
with_skip_flags( skip, [&]()
{
result = _push_transaction( trx );
} );
return result;
}
processed_transaction database::_push_transaction( const signed_transaction& trx )
{
uint32_t skip = get_node_properties().skip_flags;
//wdump((trx.digest())(trx.id()));
// If this is the first transaction pushed after applying a block, start a new undo session.
// This allows us to quickly rewind to the clean state of the head block, in case a new block arrives.
if( !_pending_block_session ) _pending_block_session = _undo_db.start_undo_session();
auto session = _undo_db.start_undo_session();
auto processed_trx = apply_transaction( trx, skip );
auto processed_trx = _apply_transaction( trx );
_pending_block.transactions.push_back(processed_trx);
FC_ASSERT( (skip & skip_block_size_check) ||
@ -240,8 +262,23 @@ signed_block database::generate_block(
const fc::ecc::private_key& block_signing_private_key,
uint32_t skip /* = 0 */
)
{
signed_block result;
with_skip_flags( skip, [&]()
{
result = _generate_block( when, witness_id, block_signing_private_key );
} );
return result;
}
signed_block database::_generate_block(
fc::time_point_sec when,
witness_id_type witness_id,
const fc::ecc::private_key& block_signing_private_key
)
{
try {
uint32_t skip = get_node_properties().skip_flags;
uint32_t slot_num = get_slot_at_time( when );
witness_id_type scheduled_witness = get_scheduled_witness( slot_num ).first;
FC_ASSERT( scheduled_witness == witness_id );
@ -322,7 +359,17 @@ const vector<operation_history_object>& database::get_applied_operations() const
//////////////////// private methods ////////////////////
void database::apply_block( const signed_block& next_block, uint32_t skip )
{
with_skip_flags( skip, [&]()
{
_apply_block( next_block );
} );
return;
}
void database::_apply_block( const signed_block& next_block )
{ try {
uint32_t skip = get_node_properties().skip_flags;
_applied_ops.clear();
FC_ASSERT( (skip & skip_merkle_check) || next_block.transaction_merkle_root == next_block.calculate_merkle_root(), "", ("next_block.transaction_merkle_root",next_block.transaction_merkle_root)("calc",next_block.calculate_merkle_root())("next_block",next_block)("id",next_block.id()) );
@ -375,16 +422,27 @@ void database::apply_block( const signed_block& next_block, uint32_t skip )
update_pending_block(next_block, current_block_interval);
} FC_CAPTURE_AND_RETHROW( (next_block.block_num())(skip) ) }
} FC_CAPTURE_AND_RETHROW( (next_block.block_num()) ) }
processed_transaction database::apply_transaction( const signed_transaction& trx, uint32_t skip )
{
processed_transaction result;
with_skip_flags( skip, [&]()
{
result = _apply_transaction( trx );
} );
return result;
}
processed_transaction database::_apply_transaction( const signed_transaction& trx )
{ try {
uint32_t skip = get_node_properties().skip_flags;
trx.validate();
auto& trx_idx = get_mutable_index_type<transaction_index>();
auto trx_id = trx.id();
FC_ASSERT( (skip & skip_transaction_dupe_check) ||
trx_idx.indices().get<by_trx_id>().find(trx_id) == trx_idx.indices().get<by_trx_id>().end() );
transaction_evaluation_state eval_state(this, skip&skip_authority_check );
transaction_evaluation_state eval_state(this);
const chain_parameters& chain_parameters = get_global_properties().parameters;
eval_state._trx = &trx;

View file

@ -63,4 +63,14 @@ decltype( chain_parameters::block_interval ) database::block_interval( )const
return get_global_properties().parameters.block_interval;
}
const node_property_object& database::get_node_properties()const
{
return _node_property_object;
}
node_property_object& database::node_properties()
{
return _node_property_object;
}
} }

View file

@ -124,7 +124,7 @@ void database::initialize_indexes()
add_index< primary_index< simple_index< witness_schedule_object > > >();
}
void database::init_genesis(const genesis_allocation& initial_allocation)
void database::init_genesis(const genesis_state_type& genesis_state)
{ try {
_undo_db.disable();
@ -219,7 +219,7 @@ void database::init_genesis(const genesis_allocation& initial_allocation)
for( const witness_id_type& wit : init_witnesses )
p.active_witnesses.insert( wit );
p.next_available_vote_id = delegates_and_witnesses * 2;
p.chain_id = fc::digest(initial_allocation);
p.chain_id = fc::digest(genesis_state);
});
(void)properties;
@ -250,11 +250,11 @@ void database::init_genesis(const genesis_allocation& initial_allocation)
assert( get_balance(account_id_type(), asset_id_type()) == asset(dyn_asset.current_supply) );
(void)core_asset;
if( !initial_allocation.empty() )
if( !genesis_state.allocation_targets.empty() )
{
share_type total_allocation = 0;
for( const auto& handout : initial_allocation )
total_allocation += handout.second;
for( const auto& handout : genesis_state.allocation_targets )
total_allocation += handout.weight;
auto mangle_to_name = [](const fc::static_variant<public_key_type, address>& key) {
string addr = string(key.which() == std::decay<decltype(key)>::type::tag<address>::value? key.get<address>()
@ -273,22 +273,22 @@ void database::init_genesis(const genesis_allocation& initial_allocation)
fc::time_point start_time = fc::time_point::now();
for( const auto& handout : initial_allocation )
for( const auto& handout : genesis_state.allocation_targets )
{
asset amount(handout.second);
asset amount(handout.weight);
amount.amount = ((fc::uint128(amount.amount.value) * GRAPHENE_INITIAL_SUPPLY)/total_allocation.value).to_uint64();
if( amount.amount == 0 )
{
wlog("Skipping zero allocation to ${k}", ("k", handout.first));
wlog("Skipping zero allocation to ${k}", ("k", handout.name));
continue;
}
signed_transaction trx;
trx.operations.emplace_back(key_create_operation({asset(), genesis_account.id, handout.first}));
trx.operations.emplace_back(key_create_operation({asset(), genesis_account.id, handout.addr}));
relative_key_id_type key_id(0);
authority account_authority(1, key_id, 1);
account_create_operation cop;
cop.name = mangle_to_name(handout.first);
cop.name = handout.name;
cop.registrar = account_id_type(1);
cop.active = account_authority;
cop.owner = account_authority;
@ -322,7 +322,7 @@ void database::init_genesis(const genesis_allocation& initial_allocation)
fc::microseconds duration = fc::time_point::now() - start_time;
ilog("Finished allocating to ${n} accounts in ${t} milliseconds.",
("n", initial_allocation.size())("t", duration.count() / 1000));
("n", genesis_state.allocation_targets.size())("t", duration.count() / 1000));
}
_undo_db.enable();

View file

@ -272,8 +272,7 @@ void database::process_budget()
});
modify(dpo, [&]( dynamic_global_property_object& _dpo )
{
// Should this be +=?
_dpo.witness_budget = witness_budget;
_dpo.witness_budget += witness_budget;
_dpo.last_budget_time = now;
});
@ -406,8 +405,10 @@ void database::perform_chain_maintenance(const signed_block& next_block, const g
next_maintenance_time = time_point_sec() +
(((next_block.timestamp.sec_since_epoch() / maintenance_interval) + 1) * maintenance_interval);
else
next_maintenance_time += maintenance_interval;
assert( next_maintenance_time > next_block.timestamp );
// It's possible we have missed blocks for at least a maintenance interval.
// In this case, we'll need to bump the next maintenance time more than once.
do next_maintenance_time += maintenance_interval;
while( next_maintenance_time < head_block_time() );
}
modify(get_dynamic_global_properties(), [next_maintenance_time](dynamic_global_property_object& d) {

View file

@ -33,7 +33,7 @@ database::~database(){
_pending_block_session->commit();
}
void database::open( const fc::path& data_dir, const genesis_allocation& initial_allocation )
void database::open( const fc::path& data_dir, const genesis_state_type& initial_allocation )
{ try {
// ilog("Open database in ${d}", ("d", data_dir));
object_database::open( data_dir );
@ -55,7 +55,7 @@ void database::open( const fc::path& data_dir, const genesis_allocation& initial
} FC_CAPTURE_AND_RETHROW( (data_dir) ) }
void database::reindex(fc::path data_dir, const genesis_allocation& initial_allocation)
void database::reindex(fc::path data_dir, const genesis_state_type& initial_allocation)
{ try {
wipe(data_dir, false);
open(data_dir, initial_allocation);

View file

@ -118,18 +118,21 @@ void database::clear_expired_proposals()
void database::clear_expired_orders()
{
transaction_evaluation_state cancel_context(this, true);
with_skip_flags(
get_node_properties().skip_flags | skip_authority_check, [&](){
transaction_evaluation_state cancel_context(this);
//Cancel expired limit orders
auto& limit_index = get_index_type<limit_order_index>().indices().get<by_expiration>();
while( !limit_index.empty() && limit_index.begin()->expiration <= head_block_time() )
{
limit_order_cancel_operation canceler;
const limit_order_object& order = *limit_index.begin();
canceler.fee_paying_account = order.seller;
canceler.order = order.id;
apply_operation(cancel_context, canceler);
}
//Cancel expired limit orders
auto& limit_index = get_index_type<limit_order_index>().indices().get<by_expiration>();
while( !limit_index.empty() && limit_index.begin()->expiration <= head_block_time() )
{
limit_order_cancel_operation canceler;
const limit_order_object& order = *limit_index.begin();
canceler.fee_paying_account = order.seller;
canceler.order = order.id;
apply_operation(cancel_context, canceler);
}
});
//Process expired force settlement orders

View file

@ -95,13 +95,6 @@ namespace graphene { namespace chain {
}
}
/*
bool generic_evaluator::verify_signature( const key_object& k )
{
return trx_state->_skip_signature_check || trx_state->signed_by( k.id );
}
*/
object_id_type generic_evaluator::get_relative_id( object_id_type rel_id )const
{
if( rel_id.space() == relative_protocol_ids )

View file

@ -1,3 +1,20 @@
/*
* 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 <fstream>
#include <graphene/chain/block.hpp>

View file

@ -20,6 +20,7 @@
#include <graphene/chain/block.hpp>
#include <graphene/chain/asset.hpp>
#include <graphene/chain/global_property_object.hpp>
#include <graphene/chain/node_property_object.hpp>
#include <graphene/chain/account_object.hpp>
#include <graphene/chain/asset_object.hpp>
#include <graphene/chain/fork_database.hpp>
@ -38,7 +39,55 @@ namespace graphene { namespace chain {
using graphene::db::abstract_object;
using graphene::db::object;
typedef vector<std::pair<fc::static_variant<address, public_key_type>, share_type >> genesis_allocation;
struct genesis_state_type {
struct allocation_target_type {
allocation_target_type(const string& name = string(), const address& addr = address(), share_type weight = share_type())
: name(name), addr(addr), weight(weight){}
string name;
address addr;
share_type weight;
};
struct initial_witness_type {
/// Must correspond to one of the allocation targets.
string owner_name;
public_key_type block_signing_key;
secret_hash_type initial_secret;
};
struct initial_committee_member_type {
/// Must correspond to one of the allocation targets.
string owner_name;
};
chain_parameters initial_parameters;
vector<allocation_target_type> allocation_targets;
vector<initial_witness_type> initial_witnesses;
vector<initial_committee_member_type> initial_committee;
};
namespace detail
{
/**
* Class used to help the with_skip_flags implementation.
* It must be defined in this header because it must be
* available to the with_skip_flags implementation,
* which is a template and therefore must also be defined
* in this header.
*/
struct skip_flags_restorer
{
skip_flags_restorer( node_property_object& npo, uint32_t old_skip_flags )
: _npo( npo ), _old_skip_flags( old_skip_flags )
{}
~skip_flags_restorer()
{
_npo.skip_flags = _old_skip_flags;
}
node_property_object& _npo;
uint32_t _old_skip_flags;
};
}
/**
* @class database
@ -67,14 +116,14 @@ namespace graphene { namespace chain {
skip_merkle_check = 0x200 ///< used while reindexing
};
void open(const fc::path& data_dir, const genesis_allocation& initial_allocation = genesis_allocation());
void open(const fc::path& data_dir, const genesis_state_type& initial_allocation = genesis_state_type());
/**
* @brief Rebuild object graph from block history and open detabase
*
* This method may be called after or instead of @ref database::open, and will rebuild the object graph by
* replaying blockchain history. When this method exits successfully, the database will be open.
*/
void reindex(fc::path data_dir, const genesis_allocation& initial_allocation = genesis_allocation());
void reindex(fc::path data_dir, const genesis_state_type& initial_allocation = genesis_state_type());
/**
* @brief wipe Delete database from disk, and potentially the raw chain as well.
@ -100,6 +149,9 @@ namespace graphene { namespace chain {
bool push_block( const signed_block& b, uint32_t skip = skip_nothing );
processed_transaction push_transaction( const signed_transaction& trx, uint32_t skip = skip_nothing );
bool _push_block( const signed_block& b );
processed_transaction _push_transaction( const signed_transaction& trx );
///@throws fc::exception if the proposed transaction fails to apply.
processed_transaction push_proposal( const proposal_object& proposal );
@ -107,7 +159,12 @@ namespace graphene { namespace chain {
const fc::time_point_sec when,
witness_id_type witness_id,
const fc::ecc::private_key& block_signing_private_key,
uint32_t skip = 0
uint32_t skip
);
signed_block _generate_block(
const fc::time_point_sec when,
witness_id_type witness_id,
const fc::ecc::private_key& block_signing_private_key
);
void pop_block();
@ -192,6 +249,7 @@ namespace graphene { namespace chain {
const asset_object& get_core_asset()const;
const global_property_object& get_global_properties()const;
const dynamic_global_property_object& get_dynamic_global_properties()const;
const node_property_object& get_node_properties()const;
const fee_schedule_type& current_fee_schedule()const;
time_point_sec head_block_time()const;
@ -200,12 +258,31 @@ namespace graphene { namespace chain {
decltype( chain_parameters::block_interval ) block_interval( )const;
node_property_object& node_properties();
/**
* Set the skip_flags to the given value, call callback,
* then reset skip_flags to their previous value after
* callback is done.
*/
template< typename Lambda >
void with_skip_flags(
uint32_t skip_flags,
Lambda callback )
{
node_property_object& npo = node_properties();
detail::skip_flags_restorer restorer( npo, npo.skip_flags );
npo.skip_flags = skip_flags;
callback();
return;
}
//////////////////// db_init.cpp ////////////////////
void initialize_evaluators();
/// Reset the object graph in-memory
void initialize_indexes();
void init_genesis(const genesis_allocation& initial_allocation = genesis_allocation());
void init_genesis(const genesis_state_type& genesis_state = genesis_state_type());
template<typename EvaluatorType>
void register_evaluator()
@ -323,12 +400,15 @@ namespace graphene { namespace chain {
void apply_block( const signed_block& next_block, uint32_t skip = skip_nothing );
processed_transaction apply_transaction( const signed_transaction& trx, uint32_t skip = skip_nothing );
void _apply_block( const signed_block& next_block );
processed_transaction _apply_transaction( const signed_transaction& trx );
operation_result apply_operation( transaction_evaluation_state& eval_state, const operation& op );
///Steps involved in applying a new block
///@{
const witness_object& validate_block_header( uint32_t skip, const signed_block& next_block )const;
const witness_object& _validate_block_header( const signed_block& next_block )const;
void create_block_summary(const signed_block& next_block);
//////////////////// db_update.cpp ////////////////////
@ -392,6 +472,8 @@ namespace graphene { namespace chain {
vector<uint64_t> _witness_count_histogram_buffer;
vector<uint64_t> _committee_count_histogram_buffer;
uint64_t _total_voting_stake;
node_property_object _node_property_object;
};
namespace detail
@ -421,3 +503,8 @@ namespace graphene { namespace chain {
}
} }
FC_REFLECT(graphene::chain::genesis_state_type::allocation_target_type, (name)(addr)(weight))
FC_REFLECT(graphene::chain::genesis_state_type::initial_witness_type, (owner_name)(block_signing_key)(initial_secret))
FC_REFLECT(graphene::chain::genesis_state_type::initial_committee_member_type, (owner_name))
FC_REFLECT(graphene::chain::genesis_state_type, (initial_parameters)(allocation_targets)(initial_witnesses)(initial_committee))

View file

@ -0,0 +1,41 @@
/*
* 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/db/object.hpp>
namespace graphene { namespace chain {
/**
* @brief Contains per-node database configuration.
*
* Transactions are evaluated differently based on per-node state.
* Settings here may change based on whether the node is syncing or up-to-date.
* Or whether the node is a witness node. Or if we're processing a
* transaction in a witness-signed block vs. a fresh transaction
* from the p2p network. Or configuration-specified tradeoffs of
* performance/hardfork resilience vs. paranoia.
*/
class node_property_object
{
public:
node_property_object() : skip_flags(0) {}
~node_property_object(){}
uint32_t skip_flags;
};
} } // graphene::chain

View file

@ -33,8 +33,8 @@ namespace graphene { namespace chain {
class transaction_evaluation_state
{
public:
transaction_evaluation_state( database* db = nullptr, bool skip_authority_check = false )
:_db(db),_skip_authority_check(skip_authority_check){}
transaction_evaluation_state( database* db = nullptr )
:_db(db){}
bool check_authority( const account_object&, authority::classification auth_class = authority::active, int depth = 0 );
@ -55,7 +55,6 @@ namespace graphene { namespace chain {
const signed_transaction* _trx = nullptr;
database* _db = nullptr;
bool _skip_authority_check = false;
bool _is_proposed_trx = false;
};
} } // namespace graphene::chain

View file

@ -93,13 +93,16 @@ void_result proposal_update_evaluator::do_evaluate(const proposal_update_operati
FC_ASSERT( _proposal->available_owner_approvals.find(id) != _proposal->available_owner_approvals.end(),
"", ("id", id)("available", _proposal->available_owner_approvals) );
}
for( key_id_type id : o.key_approvals_to_add )
if( (d.get_node_properties().skip_flags & database::skip_authority_check) == 0 )
{
FC_ASSERT( trx_state->signed_by(id) || trx_state->_skip_authority_check );
}
for( key_id_type id : o.key_approvals_to_remove )
{
FC_ASSERT( trx_state->signed_by(id) || trx_state->_skip_authority_check );
for( key_id_type id : o.key_approvals_to_add )
{
FC_ASSERT( trx_state->signed_by(id) );
}
for( key_id_type id : o.key_approvals_to_remove )
{
FC_ASSERT( trx_state->signed_by(id) );
}
}
return void_result();

View file

@ -25,7 +25,9 @@
namespace graphene { namespace chain {
bool transaction_evaluation_state::check_authority( const account_object& account, authority::classification auth_class, int depth )
{
if( _skip_authority_check || approved_by.find(make_pair(account.id, auth_class)) != approved_by.end() )
if( (!_is_proposed_trx) && (_db->get_node_properties().skip_flags & database::skip_authority_check) )
return true;
if( approved_by.find(make_pair(account.id, auth_class)) != approved_by.end() )
return true;
FC_ASSERT( account.id.instance() != 0 || _is_proposed_trx );

View file

@ -1,224 +0,0 @@
/*
* 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/db/level_map.hpp>
#include <fc/thread/thread.hpp>
#include <map>
namespace graphene { namespace db {
template<typename Key, typename Value, class CacheType = std::map<Key,Value>>
class cached_level_map
{
public:
void open( const fc::path& dir, bool create = true, size_t leveldb_cache_size = 0, bool write_through = true, bool sync_on_write = false )
{ try {
_db.open( dir, create, leveldb_cache_size );
for( auto itr = _db.begin(); itr.valid(); ++itr )
_cache.emplace_hint( _cache.end(), itr.key(), itr.value() );
_write_through = write_through;
_sync_on_write = sync_on_write;
} FC_CAPTURE_AND_RETHROW( (dir)(create)(leveldb_cache_size)(write_through)(sync_on_write) ) }
void close()
{ try {
if( _db.is_open() ) flush();
_db.close();
_cache.clear();
_dirty_store.clear();
_dirty_remove.clear();
} FC_CAPTURE_AND_RETHROW() }
void set_write_through( bool write_through )
{ try {
if( write_through == _write_through )
return;
if( write_through )
flush();
_write_through = write_through;
} FC_CAPTURE_AND_RETHROW( (write_through) ) }
void flush()
{ try {
typename level_map<Key, Value>::write_batch batch = _db.create_batch( _sync_on_write );
for( const auto& key : _dirty_store )
batch.store( key, _cache.at( key ) );
for( const auto& key : _dirty_remove )
batch.remove( key );
batch.commit();
_dirty_store.clear();
_dirty_remove.clear();
} FC_CAPTURE_AND_RETHROW() }
fc::optional<Value> fetch_optional( const Key& key )const
{ try {
const auto itr = _cache.find( key );
if( itr != _cache.end() )
return itr->second;
return fc::optional<Value>();
} FC_CAPTURE_AND_RETHROW( (key) ) }
Value fetch( const Key& key )const
{ try {
const auto itr = _cache.find( key );
if( itr != _cache.end() )
return itr->second;
FC_CAPTURE_AND_THROW( fc::key_not_found_exception, (key) );
} FC_CAPTURE_AND_RETHROW( (key) ) }
void store( const Key& key, const Value& value )
{ try {
_cache[ key ] = value;
if( _write_through )
{
_db.store( key, value, _sync_on_write );
}
else
{
_dirty_store.insert( key );
_dirty_remove.erase( key );
}
} FC_CAPTURE_AND_RETHROW( (key)(value) ) }
void remove( const Key& key )
{ try {
_cache.erase( key );
if( _write_through )
{
_db.remove( key, _sync_on_write );
}
else
{
_dirty_store.erase( key );
_dirty_remove.insert( key );
}
} FC_CAPTURE_AND_RETHROW( (key) ) }
size_t size()const
{ try {
return _cache.size();
} FC_CAPTURE_AND_RETHROW() }
bool last( Key& key )const
{ try {
const auto ritr = _cache.crbegin();
if( ritr != _cache.crend() )
{
key = ritr->first;
return true;
}
return false;
} FC_CAPTURE_AND_RETHROW( (key) ) }
bool last( Key& key, Value& value )
{ try {
const auto ritr = _cache.crbegin();
if( ritr != _cache.crend() )
{
key = ritr->first;
value = ritr->second;
return true;
}
return false;
} FC_CAPTURE_AND_RETHROW( (key)(value) ) }
class iterator
{
public:
iterator(){}
bool valid()const { return _it != _end; }
Key key()const { return _it->first; }
Value value()const { return _it->second; }
iterator& operator++() { ++_it; return *this; }
iterator operator++(int) {
auto backup = *this;
++_it;
return backup;
}
iterator& operator--()
{
if( _it == _begin )
_it = _end;
else
--_it;
return *this;
}
iterator operator--(int) {
auto backup = *this;
operator--();
return backup;
}
void reset() { _it = _end; }
protected:
friend class cached_level_map;
iterator( typename CacheType::const_iterator it, typename CacheType::const_iterator begin, typename CacheType::const_iterator end )
:_it(it),_begin(begin),_end(end)
{ }
typename CacheType::const_iterator _it;
typename CacheType::const_iterator _begin;
typename CacheType::const_iterator _end;
};
iterator begin()const
{
return iterator( _cache.begin(), _cache.begin(), _cache.end() );
}
iterator last()const
{
if( _cache.empty() )
return iterator( _cache.end(), _cache.begin(), _cache.end() );
return iterator( --_cache.end(), _cache.begin(), _cache.end() );
}
iterator find( const Key& key )const
{
return iterator( _cache.find(key), _cache.begin(), _cache.end() );
}
iterator lower_bound( const Key& key )const
{
return iterator( _cache.lower_bound(key), _cache.begin(), _cache.end() );
}
// TODO: Iterate over cache instead
void export_to_json( const fc::path& path )const
{ try {
_db.export_to_json( path );
} FC_CAPTURE_AND_RETHROW( (path) ) }
private:
level_map<Key, Value> _db;
CacheType _cache;
std::set<Key> _dirty_store;
std::set<Key> _dirty_remove;
bool _write_through = true;
bool _sync_on_write = false;
};
} }

View file

@ -1,143 +0,0 @@
/*
* 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/db/level_map.hpp>
namespace graphene { namespace db {
template<typename K, typename V>
class fast_level_map
{
level_map<K, V> _ldb;
fc::optional<fc::path> _ldb_path;
bool _ldb_enabled = true;
std::unordered_map<K, V> _cache;
public:
~fast_level_map()
{
close();
}
void open( const fc::path& path )
{ try {
FC_ASSERT( !_ldb_path.valid() );
_ldb_path = path;
_ldb.open( *_ldb_path );
_cache.reserve( _ldb.size() );
for( auto iter = _ldb.begin(); iter.valid(); ++iter )
_cache.emplace( iter.key(), iter.value() );
} FC_CAPTURE_AND_RETHROW( (path) ) }
void close()
{ try {
if( _ldb_path.valid() )
{
if( !_ldb_enabled ) toggle_leveldb( true );
_ldb.close();
_ldb_path = fc::optional<fc::path>();
}
_cache.clear();
} FC_CAPTURE_AND_RETHROW() }
void toggle_leveldb( const bool enabled )
{ try {
FC_ASSERT( _ldb_path.valid() );
if( enabled == _ldb_enabled )
return;
if( enabled )
{
_ldb.open( *_ldb_path );
auto batch = _ldb.create_batch();
for( const auto& item : _cache )
batch.store( item.first, item.second );
batch.commit();
}
else
{
_ldb.close();
fc::remove_all( *_ldb_path );
}
_ldb_enabled = enabled;
} FC_CAPTURE_AND_RETHROW( (enabled) ) }
void store( const K& key, const V& value )
{ try {
_cache[ key ] = value;
if( _ldb_enabled )
_ldb.store( key, value );
} FC_CAPTURE_AND_RETHROW( (key)(value) ) }
void remove( const K& key )
{ try {
_cache.erase( key );
if( _ldb_enabled )
_ldb.remove( key );
} FC_CAPTURE_AND_RETHROW( (key) ) }
auto empty()const -> decltype( _cache.empty() )
{
return _cache.empty();
}
auto size()const -> decltype( _cache.size() )
{
return _cache.size();
}
auto count( const K& key )const -> decltype( _cache.count( key ) )
{
return _cache.count( key );
}
auto unordered_begin()const -> decltype( _cache.cbegin() )
{
return _cache.cbegin();
}
auto unordered_end()const -> decltype( _cache.cend() )
{
return _cache.cend();
}
auto unordered_find( const K& key )const -> decltype( _cache.find( key ) )
{
return _cache.find( key );
}
auto ordered_first()const -> decltype( _ldb.begin() )
{ try {
return _ldb.begin();
} FC_CAPTURE_AND_RETHROW() }
auto ordered_last()const -> decltype( _ldb.last() )
{ try {
return _ldb.last();
} FC_CAPTURE_AND_RETHROW() }
auto ordered_lower_bound( const K& key )const -> decltype( _ldb.lower_bound( key ) )
{ try {
return _ldb.lower_bound( key );
} FC_CAPTURE_AND_RETHROW( (key) ) }
};
} } // graphene::db

View file

@ -1,132 +0,0 @@
/*
* 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 <leveldb/db.h>
#include <leveldb/comparator.h>
#include <fc/reflect/reflect.hpp>
#include <fc/io/raw.hpp>
#include <fc/exception/exception.hpp>
#include <functional>
#include <map>
namespace fc { class path; }
/**
* This code has no graphene dependencies, and it
* could be moved to fc, if fc ever adds a leveldb dependency
*
* This code enables legacy databases files created by older programs to
* be upgraded to the current database formats. Whenever a database is first opened,
* this code checks if the database is stored in an old format and looks for an
* upgrade function to upgrade it to the current format. If found, the objects
* in the database will be immediately upgraded to the current format.
*
* Upgrades are performed by executing a series of chained copy constructors
* from the legacy object format to the current object format. This means
* that only one new copy constructor typically needs to be written to support
* upgrading any previous version of the object when an object type is modified.
*
* - Database versioning is only supported for changes to database value types
* (databases with modified key types cannot currently be upgraded).
* - The database versioning code requires that fc::get_typename is defined for
* all value types which are to be versioned.
*/
/*
Below is a simple example of how client code needs to be written to support
database versioning. Originally, a database stored values of record0, and
record was typedef'd to be record0. A new type record1 was created to add
"new_field" to record type, and record was typedef'd to record1. The typedef
is used to minimize required changes to the client code that references
record objects.
@code
struct record0
{
record0() : points(0) {}
double points;
};
FC_REFLECT( record0, (points) )
REGISTER_DB_OBJECT(record,0) //This creates an upgrade function for record0 databases
struct record1
{
record1() : points(0), new_field("EMPTY") {}
record1(const record0& r0) //convert from record0 to record1 for legacy files
{
key = r0.key;
new_field = "EMPTY";
}
std::string new_field;
double points;
};
FC_REFLECT( record1, (points)(new_field) )
typedef record1 record; //current databases store record1 objects
@endcode
*/
namespace graphene { namespace db {
typedef std::function<void(leveldb::DB*)> upgrade_db_function;
class upgrade_db_mapper
{
public:
static upgrade_db_mapper& instance();
int32_t add_type( const std::string& type_name, const upgrade_db_function& function);
std::map<std::string,upgrade_db_function> _upgrade_db_function_registry;
};
#define REGISTER_DB_OBJECT(TYPE,VERSIONNUM) \
void UpgradeDb ## TYPE ## VERSIONNUM(leveldb::DB* dbase) \
{ \
std::unique_ptr<leveldb::Iterator> dbase_itr( dbase->NewIterator(leveldb::ReadOptions()) ); \
dbase_itr->SeekToFirst(); \
if( dbase_itr->status().IsNotFound() ) /*if empty database, do nothing*/ \
return; \
if( !dbase_itr->status().ok() ) \
FC_THROW_EXCEPTION( exception, "database error: ${msg}", ("msg", dbase_itr->status().ToString() ) ); \
while( dbase_itr->Valid() ) /* convert dbase objects from legacy TypeVersionNum to current Type */ \
{ \
TYPE ## VERSIONNUM old_value; /*load old record type*/ \
fc::datastream<const char*> dstream( dbase_itr->value().data(), dbase_itr->value().size() ); \
fc::raw::unpack( dstream, old_value ); \
TYPE new_value(old_value); /*convert to new record type*/ \
leveldb::Slice key_slice = dbase_itr->key(); \
auto vec = fc::raw::pack(new_value); \
leveldb::Slice value_slice( vec.data(), vec.size() ); \
auto status = dbase->Put( leveldb::WriteOptions(), key_slice, value_slice ); \
if( !status.ok() ) \
{ \
FC_THROW_EXCEPTION( exception, "database error: ${msg}", ("msg", status.ToString() ) ); \
} \
dbase_itr->Next(); \
} /*while*/ \
} \
static int dummyResult ## TYPE ## VERSIONNUM = \
upgrade_db_mapper::instance()->add_type(fc::get_typename<TYPE ## VERSIONNUM>::name(), UpgradeDb ## TYPE ## VERSIONNUM);
void try_upgrade_db( const fc::path& dir, leveldb::DB* dbase, const char* record_type, size_t record_type_size );
} } // namespace db

View file

@ -1,6 +0,0 @@
#pragma once
#include <BaseTsd.h>
typedef SSIZE_T ssize_t;
#include "../../../leveldb/include/leveldb/db.h"

View file

@ -1 +0,0 @@
/* empty unistd to allow leveldb to compile with msvc which is missing this file */

View file

@ -1,5 +0,0 @@
This directory contains the files needed to make the stock LevelDB distribution
from https://github.com/bitcoin/leveldb.git compile on Windows with Visual C++.
Add this 'include' directory to yur include path before the regular includes
only when building leveldb (it isn't needed when compiling code that uses
leveldb).

View file

@ -17,6 +17,7 @@
*/
#include <graphene/witness/witness.hpp>
#include <graphene/chain/database.hpp>
#include <graphene/chain/witness_object.hpp>
#include <graphene/time/time.hpp>
@ -176,7 +177,8 @@ void witness_plugin::block_production_loop()
auto block = db.generate_block(
scheduled_time,
scheduled_witness,
_private_keys[ scheduled_key ]
_private_keys[ scheduled_key ],
graphene::chain::database::skip_nothing
);
ilog("Generated block #${n} with timestamp ${t} at time ${c}",
("n", block.block_num())("t", block.timestamp)("c", now));

View file

@ -40,7 +40,7 @@ BOOST_AUTO_TEST_CASE( two_node_network )
fc::temp_directory app_dir;
fc::temp_directory app2_dir;
fc::temp_file genesis_json;
fc::json::save_to_file(genesis_allocation(), genesis_json.path());
fc::json::save_to_file(genesis_state_type(), genesis_json.path());
fc::time_point_sec now( GRAPHENE_GENESIS_TIMESTAMP );
@ -86,7 +86,7 @@ BOOST_AUTO_TEST_CASE( two_node_network )
now += GRAPHENE_DEFAULT_BLOCK_INTERVAL;
app2.p2p_node()->broadcast(graphene::net::block_message(db2->generate_block(
now, db2->get_scheduled_witness( 1 ).first, genesis_key )));
now, db2->get_scheduled_witness( 1 ).first, genesis_key, database::skip_nothing )));
fc::usleep(fc::milliseconds(500));
BOOST_CHECK_EQUAL(app1.p2p_node()->get_connection_count(), 1);

View file

@ -44,7 +44,7 @@ BOOST_AUTO_TEST_CASE( operation_sanity_check )
BOOST_AUTO_TEST_CASE( genesis_and_persistence_bench )
{
try {
genesis_allocation allocation;
genesis_state_type genesis_state;
#ifdef NDEBUG
ilog("Running in release mode.");
@ -57,14 +57,15 @@ BOOST_AUTO_TEST_CASE( genesis_and_persistence_bench )
#endif
for( int i = 0; i < account_count; ++i )
allocation.emplace_back(public_key_type(fc::ecc::private_key::regenerate(fc::digest(i)).get_public_key()),
GRAPHENE_INITIAL_SUPPLY / account_count);
genesis_state.allocation_targets.emplace_back("target"+fc::to_string(i),
public_key_type(fc::ecc::private_key::regenerate(fc::digest(i)).get_public_key()),
GRAPHENE_INITIAL_SUPPLY / account_count);
fc::temp_directory data_dir(fc::current_path());
{
database db;
db.open(data_dir.path(), allocation);
db.open(data_dir.path(), genesis_state);
for( int i = 11; i < account_count + 11; ++i)
BOOST_CHECK(db.get_balance(account_id_type(i), asset_id_type()).amount == GRAPHENE_INITIAL_SUPPLY / account_count);
@ -110,7 +111,7 @@ BOOST_AUTO_TEST_CASE( genesis_and_persistence_bench )
auto start_time = fc::time_point::now();
wlog( "about to start reindex..." );
db.reindex(data_dir.path(), allocation);
db.reindex(data_dir.path(), genesis_state);
ilog("Replayed database in ${t} milliseconds.", ("t", (fc::time_point::now() - start_time).count() / 1000));
for( int i = 0; i < blocks_to_produce; ++i )

View file

@ -72,6 +72,8 @@ database_fixture::~database_fixture()
verify_account_history_plugin_index();
}
BOOST_CHECK( db.get_node_properties().skip_flags == database::skip_nothing );
if( data_dir )
db.close();
return;
@ -92,11 +94,6 @@ string database_fixture::generate_anon_acct_name()
return "anon-acct-x" + std::to_string( anon_acct_count++ );
}
void database_fixture::_push_transaction( const signed_transaction& tx, uint32_t skip_flags, const char* file, int line )
{
db.push_transaction( tx, skip_flags );
}
void database_fixture::verify_asset_supplies( )const
{
//wlog("*** Begin asset supply verification ***");
@ -268,8 +265,9 @@ void database_fixture::generate_blocks(fc::time_point_sec timestamp, bool miss_i
{
if( miss_intermediate_blocks )
{
generate_block();
auto slots_to_miss = db.get_slot_at_time(timestamp) - 1;
assert(slots_to_miss > 0);
if( slots_to_miss <= 0 ) return;
generate_block(~0, generate_private_key("genesis"), slots_to_miss);
return;
}
@ -835,4 +833,18 @@ int64_t database_fixture::get_balance( const account_object& account, const asse
return db.get_balance(account.get_id(), a.get_id()).amount.value;
}
namespace test {
bool _push_block( database& db, const signed_block& b, uint32_t skip_flags /* = 0 */ )
{
return db.push_block( b, skip_flags);
}
processed_transaction _push_transaction( database& db, const signed_transaction& tx, uint32_t skip_flags /* = 0 */ )
{
return db.push_transaction( tx, skip_flags );
}
} // graphene::chain::test
} } // graphene::chain

View file

@ -24,6 +24,12 @@
using namespace graphene::db;
#define PUSH_TX \
graphene::chain::test::_push_transaction
#define PUSH_BLOCK \
graphene::chain::test::_push_block
// See below
#define REQUIRE_OP_VALIDATION_SUCCESS( op, field, value ) \
{ \
@ -65,9 +71,6 @@ using namespace graphene::db;
/// i.e. This allows a test on update_account to begin with the database at the end state of create_account.
#define INVOKE(test) ((struct test*)this)->test_method(); trx.clear()
#define PUSH_TX( tx, skip_flags ) \
_push_transaction( tx, skip_flags, __FILE__, __LINE__ )
#define PREP_ACTOR(name) \
fc::ecc::private_key name ## _private_key = generate_private_key(BOOST_PP_STRINGIZE(name)); \
key_id_type name ## _key_id = register_key(name ## _private_key.get_public_key()).get_id();
@ -111,7 +114,6 @@ struct database_fixture {
static fc::ecc::private_key generate_private_key(string seed);
string generate_anon_acct_name();
void _push_transaction( const signed_transaction& tx, uint32_t skip_flags, const char* file, int line );
void verify_asset_supplies( )const;
void verify_account_history_plugin_index( )const;
void open_database();
@ -129,7 +131,7 @@ struct database_fixture {
* @brief Generates blocks until the head block time matches or exceeds timestamp
* @param timestamp target time to generate blocks until
*/
void generate_blocks(fc::time_point_sec timestamp, bool miss_intermediate_blocks = false);
void generate_blocks(fc::time_point_sec timestamp, bool miss_intermediate_blocks = true);
account_create_operation make_account(
const std::string& name = "nathan",
@ -211,4 +213,9 @@ struct database_fixture {
int64_t get_balance( const account_object& account, const asset_object& a )const;
};
namespace test {
bool _push_block( database& db, const signed_block& b, uint32_t skip_flags = 0 );
processed_transaction _push_transaction( database& db, const signed_transaction& tx, uint32_t skip_flags = 0 );
}
} }

View file

@ -48,7 +48,7 @@ BOOST_AUTO_TEST_CASE( simple_single_signature )
transfer_operation op = {asset(),nathan.id, account_id_type(), core.amount(500)};
trx.operations.push_back(op);
sign(trx, key.id, nathan_key);
db.push_transaction(trx, database::skip_transaction_dupe_check);
PUSH_TX( db, trx, database::skip_transaction_dupe_check );
BOOST_CHECK_EQUAL(get_balance(nathan, core), old_balance - 500);
} catch (fc::exception& e) {
@ -80,7 +80,7 @@ BOOST_AUTO_TEST_CASE( any_two_of_three )
op.owner = *op.active;
trx.operations.push_back(op);
sign(trx, key1.id,nathan_key1);
db.push_transaction(trx, database::skip_transaction_dupe_check);
PUSH_TX( db, trx, database::skip_transaction_dupe_check );
trx.operations.clear();
trx.signatures.clear();
} FC_CAPTURE_AND_RETHROW ((nathan.active)(key1))
@ -88,27 +88,27 @@ BOOST_AUTO_TEST_CASE( any_two_of_three )
transfer_operation op = {asset(), nathan.id, account_id_type(), core.amount(500)};
trx.operations.push_back(op);
sign(trx, key1.id,nathan_key1);
BOOST_CHECK_THROW(db.push_transaction(trx, database::skip_transaction_dupe_check), fc::exception);
BOOST_CHECK_THROW(PUSH_TX( db, trx, database::skip_transaction_dupe_check ), fc::exception);
sign(trx, key2.id,nathan_key2);
db.push_transaction(trx, database::skip_transaction_dupe_check);
PUSH_TX( db, trx, database::skip_transaction_dupe_check );
BOOST_CHECK_EQUAL(get_balance(nathan, core), old_balance - 500);
trx.signatures.clear();
sign(trx, key2.id,nathan_key2);
sign(trx, key3.id,nathan_key3);
db.push_transaction(trx, database::skip_transaction_dupe_check);
PUSH_TX( db, trx, database::skip_transaction_dupe_check );
BOOST_CHECK_EQUAL(get_balance(nathan, core), old_balance - 1000);
trx.signatures.clear();
sign(trx, key1.id,nathan_key1);
sign(trx, key3.id,nathan_key3);
db.push_transaction(trx, database::skip_transaction_dupe_check);
PUSH_TX( db, trx, database::skip_transaction_dupe_check );
BOOST_CHECK_EQUAL(get_balance(nathan, core), old_balance - 1500);
trx.signatures.clear();
//sign(trx, fc::ecc::private_key::generate());
sign(trx, key3.id,nathan_key3);
BOOST_CHECK_THROW(db.push_transaction(trx, database::skip_transaction_dupe_check), fc::exception);
BOOST_CHECK_THROW(PUSH_TX( db, trx, database::skip_transaction_dupe_check ), fc::exception);
BOOST_CHECK_EQUAL(get_balance(nathan, core), old_balance - 1500);
} catch (fc::exception& e) {
edump((e.to_detail_string()));
@ -133,7 +133,7 @@ BOOST_AUTO_TEST_CASE( recursive_accounts )
make_child_op.owner = authority(2, account_id_type(parent1.id), 1, account_id_type(parent2.id), 1);
make_child_op.active = authority(2, account_id_type(parent1.id), 1, account_id_type(parent2.id), 1);
trx.operations.push_back(make_child_op);
db.push_transaction(trx, ~0);
PUSH_TX( db, trx, ~0 );
trx.operations.clear();
}
@ -142,17 +142,17 @@ BOOST_AUTO_TEST_CASE( recursive_accounts )
transfer_operation op = {asset(), child.id, account_id_type(), core.amount(500)};
trx.operations.push_back(op);
BOOST_CHECK_THROW(db.push_transaction(trx, database::skip_transaction_dupe_check), fc::exception);
BOOST_CHECK_THROW(PUSH_TX( db, trx, database::skip_transaction_dupe_check ), fc::exception);
sign(trx, key1.id,parent1_key);
sign(trx, key1.id,parent1_key);
sign(trx, key1.id,parent1_key);
sign(trx, key1.id,parent1_key);
BOOST_CHECK_THROW(db.push_transaction(trx, database::skip_transaction_dupe_check), fc::exception);
BOOST_CHECK_THROW(PUSH_TX( db, trx, database::skip_transaction_dupe_check ), fc::exception);
trx.signatures.clear();
sign(trx, key2.id,parent2_key);
BOOST_CHECK_THROW(db.push_transaction(trx, database::skip_transaction_dupe_check), fc::exception);
BOOST_CHECK_THROW(PUSH_TX( db, trx, database::skip_transaction_dupe_check ), fc::exception);
sign(trx, key1.id,parent1_key);
db.push_transaction(trx, database::skip_transaction_dupe_check);
PUSH_TX( db, trx, database::skip_transaction_dupe_check );
BOOST_CHECK_EQUAL(get_balance(child, core), old_balance - 500);
trx.operations.clear();
trx.signatures.clear();
@ -167,7 +167,7 @@ BOOST_AUTO_TEST_CASE( recursive_accounts )
trx.operations.push_back(op);
sign(trx, key1.id,parent1_key);
sign(trx, key2.id,parent2_key);
db.push_transaction(trx, database::skip_transaction_dupe_check);
PUSH_TX( db, trx, database::skip_transaction_dupe_check );
BOOST_REQUIRE_EQUAL(child.active.auths.size(), 3);
trx.operations.clear();
trx.signatures.clear();
@ -175,18 +175,18 @@ BOOST_AUTO_TEST_CASE( recursive_accounts )
op = {asset(),child.id, account_id_type(), core.amount(500)};
trx.operations.push_back(op);
BOOST_CHECK_THROW(db.push_transaction(trx, database::skip_transaction_dupe_check), fc::exception);
BOOST_CHECK_THROW(PUSH_TX( db, trx, database::skip_transaction_dupe_check ), fc::exception);
sign(trx, key1.id,parent1_key);
BOOST_CHECK_THROW(db.push_transaction(trx, database::skip_transaction_dupe_check), fc::exception);
BOOST_CHECK_THROW(PUSH_TX( db, trx, database::skip_transaction_dupe_check ), fc::exception);
trx.signatures.clear();
sign(trx, key2.id,parent2_key);
BOOST_CHECK_THROW(db.push_transaction(trx, database::skip_transaction_dupe_check), fc::exception);
BOOST_CHECK_THROW(PUSH_TX( db, trx, database::skip_transaction_dupe_check ), fc::exception);
sign(trx, key1.id, parent1_key);
db.push_transaction(trx, database::skip_transaction_dupe_check);
PUSH_TX( db, trx, database::skip_transaction_dupe_check );
BOOST_CHECK_EQUAL(get_balance(child, core), old_balance - 1000);
trx.signatures.clear();
sign(trx, child_key_obj.id, child_key);
db.push_transaction(trx, database::skip_transaction_dupe_check);
PUSH_TX( db, trx, database::skip_transaction_dupe_check );
BOOST_CHECK_EQUAL(get_balance(child, core), old_balance - 1500);
trx.operations.clear();
trx.signatures.clear();
@ -204,7 +204,7 @@ BOOST_AUTO_TEST_CASE( recursive_accounts )
op.active = authority(1, grandparent_key_obj.get_id(), 1);
op.owner = *op.active;
trx.operations.push_back(op);
db.push_transaction(trx, ~0);
PUSH_TX( db, trx, ~0 );
trx.operations.clear();
trx.signatures.clear();
}
@ -212,9 +212,9 @@ BOOST_AUTO_TEST_CASE( recursive_accounts )
trx.operations.push_back(op);
sign(trx, key1.id, parent1_key);
sign(trx, key2.id, parent2_key);
BOOST_CHECK_THROW(db.push_transaction(trx, database::skip_transaction_dupe_check), fc::exception);
BOOST_CHECK_THROW(PUSH_TX( db, trx, database::skip_transaction_dupe_check ), fc::exception);
sign(trx, grandparent_key_obj.id, grandparent_key);
db.push_transaction(trx, database::skip_transaction_dupe_check);
PUSH_TX( db, trx, database::skip_transaction_dupe_check );
BOOST_CHECK_EQUAL(get_balance(child, core), old_balance - 2000);
trx.operations.clear();
trx.signatures.clear();
@ -225,7 +225,7 @@ BOOST_AUTO_TEST_CASE( recursive_accounts )
op.active = authority(1, account_id_type(), 1);
op.owner = *op.active;
trx.operations.push_back(op);
db.push_transaction(trx, ~0);
PUSH_TX( db, trx, ~0 );
trx.operations.clear();
trx.signatures.clear();
}
@ -235,9 +235,9 @@ BOOST_AUTO_TEST_CASE( recursive_accounts )
sign(trx, grandparent_key_obj.id,grandparent_key);
sign(trx, key_id_type(), generate_private_key("genesis"));
//Fails due to recursion depth.
BOOST_CHECK_THROW(db.push_transaction(trx, database::skip_transaction_dupe_check), fc::exception);
BOOST_CHECK_THROW(PUSH_TX( db, trx, database::skip_transaction_dupe_check ), fc::exception);
sign(trx, child_key_obj.id, child_key);
db.push_transaction(trx, database::skip_transaction_dupe_check);
PUSH_TX( db, trx, database::skip_transaction_dupe_check );
BOOST_CHECK_EQUAL(get_balance(child, core), old_balance - 2500);
trx.operations.clear();
trx.signatures.clear();
@ -248,7 +248,7 @@ BOOST_AUTO_TEST_CASE( recursive_accounts )
op.active = authority(1, account_id_type(child.id), 1);
op.owner = *op.active;
trx.operations.push_back(op);
db.push_transaction(trx, ~0);
PUSH_TX( db, trx, ~0 );
trx.operations.clear();
trx.signatures.clear();
}
@ -256,7 +256,7 @@ BOOST_AUTO_TEST_CASE( recursive_accounts )
trx.operations.push_back(op);
sign(trx, key2.id, parent2_key);
//Fails due to recursion depth.
BOOST_CHECK_THROW(db.push_transaction(trx, database::skip_transaction_dupe_check), fc::exception);
BOOST_CHECK_THROW(PUSH_TX( db, trx, database::skip_transaction_dupe_check ), fc::exception);
} catch (fc::exception& e) {
edump((e.to_detail_string()));
throw;
@ -301,7 +301,7 @@ BOOST_AUTO_TEST_CASE( proposed_single_account )
trx.operations.push_back(op);
trx.set_expiration(db.head_block_id());
sign(trx, this->genesis_key, genesis_key);
const proposal_object& proposal = db.get<proposal_object>(db.push_transaction(trx).operation_results.front().get<object_id_type>());
const proposal_object& proposal = db.get<proposal_object>(PUSH_TX( db, trx ).operation_results.front().get<object_id_type>());
BOOST_CHECK_EQUAL(proposal.required_active_approvals.size(), 1);
BOOST_CHECK_EQUAL(proposal.available_active_approvals.size(), 0);
@ -312,11 +312,11 @@ BOOST_AUTO_TEST_CASE( proposed_single_account )
trx.operations = {proposal_update_operation{account_id_type(), asset(), proposal.id,{nathan.id},flat_set<account_id_type>{},flat_set<account_id_type>{},flat_set<account_id_type>{},flat_set<key_id_type>{},flat_set<key_id_type>{}}};
trx.sign( this->genesis_key, genesis_key );
//Genesis may not add nathan's approval.
BOOST_CHECK_THROW(db.push_transaction(trx), fc::exception);
BOOST_CHECK_THROW(PUSH_TX( db, trx ), fc::exception);
trx.operations = {proposal_update_operation{account_id_type(), asset(), proposal.id,{account_id_type()},flat_set<account_id_type>{},flat_set<account_id_type>{},flat_set<account_id_type>{},flat_set<key_id_type>{},flat_set<key_id_type>{}}};
trx.sign( key_id_type(), genesis_key );
//Genesis has no stake in the transaction.
BOOST_CHECK_THROW(db.push_transaction(trx), fc::exception);
BOOST_CHECK_THROW(PUSH_TX( db, trx ), fc::exception);
trx.signatures.clear();
trx.operations = {proposal_update_operation{nathan.id, asset(), proposal.id,{nathan.id},flat_set<account_id_type>{},flat_set<account_id_type>{},flat_set<account_id_type>{},flat_set<key_id_type>{},flat_set<key_id_type>{}}};
@ -326,7 +326,7 @@ BOOST_AUTO_TEST_CASE( proposed_single_account )
//trx.signatures = {nathan_key3.sign_compact(trx.digest()), nathan_key2.sign_compact(trx.digest())};
BOOST_CHECK_EQUAL(get_balance(nathan, core), nathan_start_balance.amount.value);
db.push_transaction(trx);
PUSH_TX( db, trx );
BOOST_CHECK_EQUAL(get_balance(nathan, core), nathan_start_balance.amount.value - 100);
} catch (fc::exception& e) {
edump((e.to_detail_string()));
@ -354,7 +354,7 @@ BOOST_AUTO_TEST_CASE( genesis_authority )
trx.operations.push_back(transfer_operation({asset(), account_id_type(), nathan.id, asset(100000)}));
sign(trx, key_id_type(), genesis_key);
BOOST_CHECK_THROW(db.push_transaction(trx), fc::exception);
BOOST_CHECK_THROW(PUSH_TX( db, trx ), fc::exception);
auto sign = [&] { trx.signatures.clear(); trx.sign(nathan_key_id,nathan_key); };
@ -366,16 +366,16 @@ BOOST_AUTO_TEST_CASE( genesis_authority )
sign();
// The review period isn't set yet. Make sure it throws.
BOOST_REQUIRE_THROW( db.push_transaction(trx), fc::exception );
BOOST_REQUIRE_THROW( PUSH_TX( db, trx ), fc::exception );
pop.review_period_seconds = global_params.genesis_proposal_review_period / 2;
trx.operations.back() = pop;
sign();
// The review period is too short. Make sure it throws.
BOOST_REQUIRE_THROW( db.push_transaction(trx), fc::exception );
BOOST_REQUIRE_THROW( PUSH_TX( db, trx ), fc::exception );
pop.review_period_seconds = global_params.genesis_proposal_review_period;
trx.operations.back() = pop;
sign();
proposal_object prop = db.get<proposal_object>(db.push_transaction(trx).operation_results.front().get<object_id_type>());
proposal_object prop = db.get<proposal_object>(PUSH_TX( db, trx ).operation_results.front().get<object_id_type>());
BOOST_REQUIRE(db.find_object(prop.id));
BOOST_CHECK(prop.expiration_time == pop.expiration_time);
@ -396,7 +396,7 @@ BOOST_AUTO_TEST_CASE( genesis_authority )
uop.key_approvals_to_add.emplace();
trx.operations.push_back(uop);
trx.sign(key_id_type(), genesis_key);
db.push_transaction(trx);
PUSH_TX( db, trx );
BOOST_CHECK_EQUAL(get_balance(nathan, asset_id_type()(db)), 0);
BOOST_CHECK(db.get<proposal_object>(prop.id).is_authorized_to_execute(&db));
@ -406,7 +406,7 @@ BOOST_AUTO_TEST_CASE( genesis_authority )
trx.operations.back() = uop;
trx.sign(key_id_type(), genesis_key);
// Should throw because the transaction is now in review.
BOOST_CHECK_THROW(db.push_transaction(trx), fc::exception);
BOOST_CHECK_THROW(PUSH_TX( db, trx ), fc::exception);
generate_blocks(prop.expiration_time);
BOOST_CHECK_EQUAL(get_balance(nathan, asset_id_type()(db)), 100000);
@ -445,7 +445,7 @@ BOOST_FIXTURE_TEST_CASE( fired_delegates, database_fixture )
pop.proposed_ops.emplace_back(transfer_operation({asset(),account_id_type(), nathan->id, asset(100000)}));
trx.operations.push_back(pop);
sign(trx, key_id_type(), genesis_key);
const proposal_object& prop = db.get<proposal_object>(db.push_transaction(trx).operation_results.front().get<object_id_type>());
const proposal_object& prop = db.get<proposal_object>(PUSH_TX( db, trx ).operation_results.front().get<object_id_type>());
proposal_id_type pid = prop.id;
BOOST_CHECK(!prop.is_authorized_to_execute(&db));
@ -456,7 +456,7 @@ BOOST_FIXTURE_TEST_CASE( fired_delegates, database_fixture )
uop.key_approvals_to_add.emplace();
trx.operations.back() = uop;
trx.sign(key_id_type(), genesis_key);
db.push_transaction(trx);
PUSH_TX( db, trx );
BOOST_CHECK(prop.is_authorized_to_execute(&db));
//Time passes... the proposal is now in its review period.
@ -468,6 +468,7 @@ BOOST_FIXTURE_TEST_CASE( fired_delegates, database_fixture )
BOOST_CHECK(pid(db).is_authorized_to_execute(&db));
nathan = &get_account("nathan");
// no money yet
BOOST_CHECK_EQUAL(get_balance(*nathan, asset_id_type()(db)), 5000);
{
@ -478,20 +479,24 @@ BOOST_FIXTURE_TEST_CASE( fired_delegates, database_fixture )
op.new_options->votes = delegates;
trx.operations.push_back(op);
trx.set_expiration(db.head_block_time() + GRAPHENE_DEFAULT_MAX_TIME_UNTIL_EXPIRATION);
db.push_transaction(trx, ~0);
PUSH_TX( db, trx, ~0 );
trx.operations.clear();
}
// still no money
BOOST_CHECK_EQUAL(get_balance(*nathan, asset_id_type()(db)), 5000);
//Time passes... the set of active delegates gets updated.
generate_blocks(maintenance_time);
//The proposal is no longer authorized, because the active delegates got changed.
BOOST_CHECK(!pid(db).is_authorized_to_execute(&db));
// still no money
BOOST_CHECK_EQUAL(get_balance(*nathan, asset_id_type()(db)), 5000);
//Time passes... the proposal has now expired.
generate_blocks(pid(db).expiration_time);
BOOST_CHECK(db.find(pid) == nullptr);
//Nathan didn't get any more money because the proposal was rejected.
nathan = &get_account("nathan");
//Nathan never got any more money because the proposal was rejected.
BOOST_CHECK_EQUAL(get_balance(*nathan, asset_id_type()(db)), 5000);
} FC_LOG_AND_RETHROW() }
@ -524,7 +529,7 @@ BOOST_FIXTURE_TEST_CASE( proposal_two_accounts, database_fixture )
pop.expiration_time = db.head_block_time() + fc::days(1);
trx.operations.push_back(pop);
trx.sign(nathan_key_obj.id,nathan_key);
db.push_transaction(trx);
PUSH_TX( db, trx );
trx.clear();
}
@ -541,7 +546,7 @@ BOOST_FIXTURE_TEST_CASE( proposal_two_accounts, database_fixture )
uop.fee_paying_account = nathan.get_id();
trx.operations.push_back(uop);
trx.sign(nathan_key_obj.id,nathan_key);
db.push_transaction(trx);
PUSH_TX( db, trx );
trx.clear();
BOOST_CHECK(db.find_object(pid) != nullptr);
@ -550,9 +555,9 @@ BOOST_FIXTURE_TEST_CASE( proposal_two_accounts, database_fixture )
uop.active_approvals_to_add = {dan.get_id()};
trx.operations.push_back(uop);
trx.sign(nathan_key_obj.id,nathan_key);
BOOST_REQUIRE_THROW(db.push_transaction(trx), fc::exception);
BOOST_REQUIRE_THROW(PUSH_TX( db, trx ), fc::exception);
trx.sign(dan_key_obj.id,dan_key);
db.push_transaction(trx);
PUSH_TX( db, trx );
BOOST_CHECK(db.find_object(pid) == nullptr);
}
@ -588,7 +593,7 @@ BOOST_FIXTURE_TEST_CASE( proposal_delete, database_fixture )
pop.expiration_time = db.head_block_time() + fc::days(1);
trx.operations.push_back(pop);
trx.sign(nathan_key_obj.id,nathan_key);
db.push_transaction(trx);
PUSH_TX( db, trx );
trx.clear();
}
@ -604,7 +609,7 @@ BOOST_FIXTURE_TEST_CASE( proposal_delete, database_fixture )
uop.active_approvals_to_add.insert(nathan.get_id());
trx.operations.push_back(uop);
trx.sign(nathan_key_obj.id,nathan_key);
db.push_transaction(trx);
PUSH_TX( db, trx );
trx.clear();
BOOST_CHECK(!prop.is_authorized_to_execute(&db));
BOOST_CHECK_EQUAL(prop.available_active_approvals.size(), 1);
@ -612,7 +617,7 @@ BOOST_FIXTURE_TEST_CASE( proposal_delete, database_fixture )
std::swap(uop.active_approvals_to_add, uop.active_approvals_to_remove);
trx.operations.push_back(uop);
trx.sign(nathan_key_obj.id,nathan_key);
db.push_transaction(trx);
PUSH_TX( db, trx );
trx.clear();
BOOST_CHECK(!prop.is_authorized_to_execute(&db));
BOOST_CHECK_EQUAL(prop.available_active_approvals.size(), 0);
@ -625,7 +630,7 @@ BOOST_FIXTURE_TEST_CASE( proposal_delete, database_fixture )
dop.proposal = pid;
trx.operations.push_back(dop);
trx.sign(nathan_key_obj.id,nathan_key);
db.push_transaction(trx);
PUSH_TX( db, trx );
BOOST_CHECK(db.find_object(pid) == nullptr);
BOOST_CHECK_EQUAL(get_balance(nathan, asset_id_type()(db)), 100000);
}
@ -666,7 +671,7 @@ BOOST_FIXTURE_TEST_CASE( proposal_owner_authority_delete, database_fixture )
pop.expiration_time = db.head_block_time() + fc::days(1);
trx.operations.push_back(pop);
trx.sign(nathan_key_obj.id,nathan_key);
db.push_transaction(trx);
PUSH_TX( db, trx );
trx.clear();
}
@ -682,7 +687,7 @@ BOOST_FIXTURE_TEST_CASE( proposal_owner_authority_delete, database_fixture )
uop.owner_approvals_to_add.insert(nathan.get_id());
trx.operations.push_back(uop);
trx.sign(nathan_key_obj.id,nathan_key);
db.push_transaction(trx);
PUSH_TX( db, trx );
trx.clear();
BOOST_CHECK(!prop.is_authorized_to_execute(&db));
BOOST_CHECK_EQUAL(prop.available_owner_approvals.size(), 1);
@ -690,7 +695,7 @@ BOOST_FIXTURE_TEST_CASE( proposal_owner_authority_delete, database_fixture )
std::swap(uop.owner_approvals_to_add, uop.owner_approvals_to_remove);
trx.operations.push_back(uop);
trx.sign(nathan_key_obj.id,nathan_key);
db.push_transaction(trx);
PUSH_TX( db, trx );
trx.clear();
BOOST_CHECK(!prop.is_authorized_to_execute(&db));
BOOST_CHECK_EQUAL(prop.available_owner_approvals.size(), 0);
@ -704,7 +709,7 @@ BOOST_FIXTURE_TEST_CASE( proposal_owner_authority_delete, database_fixture )
dop.using_owner_authority = true;
trx.operations.push_back(dop);
trx.sign(nathan_key_obj.id,nathan_key);
db.push_transaction(trx);
PUSH_TX( db, trx );
BOOST_CHECK(db.find_object(pid) == nullptr);
BOOST_CHECK_EQUAL(get_balance(nathan, asset_id_type()(db)), 100000);
}
@ -745,7 +750,7 @@ BOOST_FIXTURE_TEST_CASE( proposal_owner_authority_complete, database_fixture )
pop.expiration_time = db.head_block_time() + fc::days(1);
trx.operations.push_back(pop);
trx.sign(nathan_key_obj.id,nathan_key);
db.push_transaction(trx);
PUSH_TX( db, trx );
trx.clear();
}
@ -763,7 +768,7 @@ BOOST_FIXTURE_TEST_CASE( proposal_owner_authority_complete, database_fixture )
trx.operations.push_back(uop);
trx.sign(nathan_key_obj.id,nathan_key);
trx.sign(dan_key_obj.id,dan_key);
db.push_transaction(trx);
PUSH_TX( db, trx );
trx.clear();
BOOST_CHECK(!prop.is_authorized_to_execute(&db));
BOOST_CHECK_EQUAL(prop.available_key_approvals.size(), 1);
@ -772,7 +777,7 @@ BOOST_FIXTURE_TEST_CASE( proposal_owner_authority_complete, database_fixture )
trx.operations.push_back(uop);
trx.sign(nathan_key_obj.id,nathan_key);
trx.sign(dan_key_obj.id,dan_key);
db.push_transaction(trx);
PUSH_TX( db, trx );
trx.clear();
BOOST_CHECK(!prop.is_authorized_to_execute(&db));
BOOST_CHECK_EQUAL(prop.available_key_approvals.size(), 0);
@ -783,7 +788,7 @@ BOOST_FIXTURE_TEST_CASE( proposal_owner_authority_complete, database_fixture )
trx.operations.push_back(uop);
trx.sign(nathan_key_obj.id,nathan_key);
trx.sign(dan_key_obj.id,dan_key);
db.push_transaction(trx);
PUSH_TX( db, trx );
trx.clear();
BOOST_CHECK(!prop.is_authorized_to_execute(&db));
BOOST_CHECK_EQUAL(prop.available_key_approvals.size(), 1);
@ -792,7 +797,7 @@ BOOST_FIXTURE_TEST_CASE( proposal_owner_authority_complete, database_fixture )
uop.owner_approvals_to_add.insert(nathan.get_id());
trx.operations.push_back(uop);
trx.sign(nathan_key_obj.id,nathan_key);
db.push_transaction(trx);
PUSH_TX( db, trx );
trx.clear();
BOOST_CHECK(db.find_object(pid) == nullptr);
}
@ -842,7 +847,7 @@ BOOST_FIXTURE_TEST_CASE( max_authority_membership, database_fixture )
kc_op.key_data = public_key_type( privkey.get_public_key() );
tx.operations.push_back( kc_op );
}
ptx = db.push_transaction(tx, ~0);
ptx = PUSH_TX( db, tx, ~0 );
vector<key_id_type> key_ids;
@ -882,11 +887,11 @@ BOOST_FIXTURE_TEST_CASE( max_authority_membership, database_fixture )
if( num_keys > max_authority_membership )
{
BOOST_REQUIRE_THROW(db.push_transaction(tx, ~0), fc::exception);
BOOST_REQUIRE_THROW(PUSH_TX( db, tx, ~0 ), fc::exception);
}
else
{
db.push_transaction(tx, ~0);
PUSH_TX( db, tx, ~0 );
}
return;
};
@ -942,38 +947,37 @@ BOOST_FIXTURE_TEST_CASE( bogus_signature, database_fixture )
xfer_op.get<transfer_operation>().get_required_auth(active_set, owner_set);
// wdump( (active_set)(owner_set)(alice_key_id) (alice_account_object) );
PUSH_TX( trx, skip );
PUSH_TX( db, trx, skip );
trx.operations.push_back( xfer_op );
// Alice's signature is now invalid
//edump((trx));
BOOST_REQUIRE_THROW( PUSH_TX( trx, skip ), fc::exception );
BOOST_REQUIRE_THROW( PUSH_TX( db, trx, skip ), fc::exception );
// Re-sign, now OK (sig is replaced)
trx.sign( alice_key_id, alice_key );
PUSH_TX( trx, skip );
PUSH_TX( db, trx, skip );
trx.signatures.clear();
trx.sign( charlie_key_id, alice_key );
// Sign with Alice's key (valid) claiming to be Charlie
BOOST_REQUIRE_THROW( PUSH_TX( trx, skip ), fc::exception );
BOOST_REQUIRE_THROW( PUSH_TX( db, trx, skip ), fc::exception );
// and with Charlie's key (invalid) claiming to be Alice
trx.sign( charlie_key_id, alice_key );
BOOST_REQUIRE_THROW( PUSH_TX( trx, skip ), fc::exception );
BOOST_REQUIRE_THROW( PUSH_TX( db, trx, skip ), fc::exception );
trx.signatures.clear();
// okay, now sign ONLY with Charlie's key claiming to be Alice
trx.sign( charlie_key_id, alice_key );
BOOST_REQUIRE_THROW( PUSH_TX( trx, skip ), fc::exception );
BOOST_REQUIRE_THROW( PUSH_TX( db, trx, skip ), fc::exception );
trx.signatures.clear();
trx.operations.pop_back();
trx.sign( alice_key_id, alice_key );
trx.sign( charlie_key_id, charlie_key );
// Signed by third-party Charlie (irrelevant key, not in authority)
PUSH_TX( trx, skip );
PUSH_TX( db, trx, skip );
trx.operations.push_back( xfer_op );
trx.sign( alice_key_id, alice_key );
// Alice's sig is valid but Charlie's is invalid
BOOST_REQUIRE_THROW( PUSH_TX( trx, skip ), fc::exception );
BOOST_REQUIRE_THROW( PUSH_TX( db, trx, skip ), fc::exception );
}
FC_LOG_AND_RETHROW()
}
@ -1000,7 +1004,7 @@ BOOST_FIXTURE_TEST_CASE( voting_account, database_fixture )
op.new_options->num_committee = 1;
trx.operations.push_back(op);
trx.sign(nathan_key_id, nathan_private_key);
db.push_transaction(trx);
PUSH_TX( db, trx );
trx.clear();
}
{
@ -1012,11 +1016,11 @@ BOOST_FIXTURE_TEST_CASE( voting_account, database_fixture )
trx.operations.push_back(op);
trx.sign(vikram_key_id, vikram_private_key);
// Fails because num_committee is larger than the cardinality of committee members being voted for
BOOST_CHECK_THROW(db.push_transaction(trx), fc::exception);
BOOST_CHECK_THROW(PUSH_TX( db, trx ), fc::exception);
op.new_options->num_committee = 3;
trx.operations = {op};
trx.sign(vikram_key_id, vikram_private_key);
db.push_transaction(trx);
PUSH_TX( db, trx );
trx.clear();
}

View file

@ -116,8 +116,8 @@ BOOST_AUTO_TEST_CASE( generate_empty_blocks )
auto delegate_priv_key = fc::ecc::private_key::regenerate(fc::sha256::hash(string("genesis")) );
{
database db;
db.open(data_dir.path(), genesis_allocation() );
b = db.generate_block( now, db.get_scheduled_witness( 1 ).first, delegate_priv_key );
db.open(data_dir.path(), genesis_state_type() );
b = db.generate_block( now, db.get_scheduled_witness( 1 ).first, delegate_priv_key, database::skip_nothing );
for( uint32_t i = 1; i < 200; ++i )
{
@ -127,7 +127,7 @@ BOOST_AUTO_TEST_CASE( generate_empty_blocks )
witness_id_type cur_witness = db.get_scheduled_witness( 1 ).first;
// TODO: Uncomment this when witness scheduling implemented
BOOST_CHECK( cur_witness != prev_witness );
b = db.generate_block( now, cur_witness, delegate_priv_key );
b = db.generate_block( now, cur_witness, delegate_priv_key, database::skip_nothing );
BOOST_CHECK( b.witness == cur_witness );
}
db.close();
@ -145,7 +145,7 @@ BOOST_AUTO_TEST_CASE( generate_empty_blocks )
witness_id_type cur_witness = db.get_scheduled_witness( 1 ).first;
// TODO: Uncomment this when witness scheduling implemented
BOOST_CHECK( cur_witness != prev_witness );
b = db.generate_block( now, cur_witness, delegate_priv_key );
b = db.generate_block( now, cur_witness, delegate_priv_key, database::skip_nothing );
}
BOOST_CHECK_EQUAL( db.head_block_num(), 400 );
}
@ -161,14 +161,14 @@ BOOST_AUTO_TEST_CASE( undo_block )
fc::temp_directory data_dir;
{
database db;
db.open(data_dir.path(), genesis_allocation() );
db.open(data_dir.path(), genesis_state_type() );
fc::time_point_sec now( GRAPHENE_GENESIS_TIMESTAMP );
auto delegate_priv_key = fc::ecc::private_key::regenerate(fc::sha256::hash(string("genesis")) );
for( uint32_t i = 0; i < 5; ++i )
{
now += db.block_interval();
auto b = db.generate_block( now, db.get_scheduled_witness( 1 ).first, delegate_priv_key );
auto b = db.generate_block( now, db.get_scheduled_witness( 1 ).first, delegate_priv_key, database::skip_nothing );
}
BOOST_CHECK( db.head_block_num() == 5 );
db.pop_block();
@ -186,7 +186,7 @@ BOOST_AUTO_TEST_CASE( undo_block )
for( uint32_t i = 0; i < 5; ++i )
{
now += db.block_interval();
auto b = db.generate_block( now, db.get_scheduled_witness( 1 ).first, delegate_priv_key );
auto b = db.generate_block( now, db.get_scheduled_witness( 1 ).first, delegate_priv_key, database::skip_nothing );
}
BOOST_CHECK( db.head_block_num() == 7 );
}
@ -204,32 +204,32 @@ BOOST_AUTO_TEST_CASE( fork_blocks )
fc::time_point_sec now( GRAPHENE_GENESIS_TIMESTAMP );
database db1;
db1.open( data_dir1.path(), genesis_allocation() );
db1.open(data_dir1.path(), genesis_state_type());
database db2;
db2.open( data_dir2.path(), genesis_allocation() );
db2.open(data_dir2.path(), genesis_state_type());
auto delegate_priv_key = fc::ecc::private_key::regenerate(fc::sha256::hash(string("genesis")) );
for( uint32_t i = 0; i < 10; ++i )
{
now += db1.block_interval();
auto b = db1.generate_block( now, db1.get_scheduled_witness( 1 ).first, delegate_priv_key );
auto b = db1.generate_block(now, db1.get_scheduled_witness(1).first, delegate_priv_key, database::skip_nothing);
try {
db2.push_block(b);
PUSH_BLOCK( db2, b );
} FC_CAPTURE_AND_RETHROW( ("db2") );
}
for( uint32_t i = 10; i < 13; ++i )
{
now += db1.block_interval();
auto b = db1.generate_block( now, db1.get_scheduled_witness( 1 ).first, delegate_priv_key );
auto b = db1.generate_block(now, db1.get_scheduled_witness(1).first, delegate_priv_key, database::skip_nothing);
}
string db1_tip = db1.head_block_id().str();
for( uint32_t i = 13; i < 16; ++i )
{
now += db2.block_interval();
auto b = db2.generate_block( now, db2.get_scheduled_witness( db2.get_slot_at_time( now ) ).first, delegate_priv_key );
auto b = db2.generate_block(now, db2.get_scheduled_witness(db2.get_slot_at_time(now)).first, delegate_priv_key, database::skip_nothing);
// notify both databases of the new block.
// only db2 should switch to the new fork, db1 should not
db1.push_block(b);
PUSH_BLOCK( db1, b );
BOOST_CHECK_EQUAL(db1.head_block_id().str(), db1_tip);
BOOST_CHECK_EQUAL(db2.head_block_id().str(), b.id().str());
}
@ -241,20 +241,20 @@ BOOST_AUTO_TEST_CASE( fork_blocks )
BOOST_CHECK_EQUAL(db2.head_block_num(), 13);
{
now += db2.block_interval();
auto b = db2.generate_block( now, db2.get_scheduled_witness( 1 ).first, delegate_priv_key );
auto b = db2.generate_block(now, db2.get_scheduled_witness(1).first, delegate_priv_key, database::skip_nothing);
good_block = b;
b.transactions.emplace_back(signed_transaction());
b.transactions.back().operations.emplace_back(transfer_operation());
b.sign(delegate_priv_key);
BOOST_CHECK_EQUAL(b.block_num(), 14);
BOOST_CHECK_THROW(db1.push_block(b), fc::exception);
BOOST_CHECK_THROW(PUSH_BLOCK( db1, b ), fc::exception);
}
BOOST_CHECK_EQUAL(db1.head_block_num(), 13);
BOOST_CHECK_EQUAL(db1.head_block_id().str(), db1_tip);
// assert that db1 switches to new fork with good block
BOOST_CHECK_EQUAL(db2.head_block_num(), 14);
db1.push_block(good_block);
PUSH_BLOCK( db1, good_block );
BOOST_CHECK_EQUAL(db1.head_block_id().str(), db2.head_block_id().str());
} catch (fc::exception& e) {
edump((e.to_detail_string()));
@ -265,7 +265,7 @@ BOOST_AUTO_TEST_CASE( fork_blocks )
BOOST_AUTO_TEST_CASE( undo_pending )
{
try {
fc::time_point_sec now( GRAPHENE_GENESIS_TIMESTAMP );
fc::time_point_sec now(GRAPHENE_GENESIS_TIMESTAMP);
fc::temp_directory data_dir;
{
database db;
@ -278,7 +278,7 @@ BOOST_AUTO_TEST_CASE( undo_pending )
signed_transaction trx;
trx.set_expiration(db.head_block_time() + fc::minutes(1));
trx.operations.push_back(transfer_operation({asset(), account_id_type(), account_id_type(1), asset(10000000)}));
db.push_transaction(trx, ~0);
PUSH_TX( db, trx, ~0 );
now += db.block_interval();
auto b = db.generate_block( now, db.get_scheduled_witness( 1 ).first, delegate_priv_key, ~0 );
@ -293,10 +293,10 @@ BOOST_AUTO_TEST_CASE( undo_pending )
cop.owner = authority(1, key_id_type(), 1);
trx.operations.push_back(cop);
trx.sign( key_id_type(), delegate_priv_key );
db.push_transaction(trx);
PUSH_TX( db, trx );
now += db.block_interval();
auto b = db.generate_block( now, db.get_scheduled_witness( 1 ).first, delegate_priv_key );
auto b = db.generate_block( now, db.get_scheduled_witness( 1 ).first, delegate_priv_key, database::skip_nothing );
BOOST_CHECK(nathan_id(db).name == "nathan");
@ -304,12 +304,12 @@ BOOST_AUTO_TEST_CASE( undo_pending )
trx.set_expiration(db.head_block_time() + db.get_global_properties().parameters.maximum_time_until_expiration-1);
trx.operations.push_back(transfer_operation({asset(1),account_id_type(1), nathan_id, asset(5000)}));
trx.sign( key_id_type(), delegate_priv_key );
db.push_transaction(trx);
PUSH_TX( db, trx );
trx.clear();
trx.set_expiration(db.head_block_time() + db.get_global_properties().parameters.maximum_time_until_expiration-2);
trx.operations.push_back(transfer_operation({asset(1),account_id_type(1), nathan_id, asset(5000)}));
trx.sign( key_id_type(), delegate_priv_key );
db.push_transaction(trx);
PUSH_TX( db, trx );
BOOST_CHECK(db.get_balance(nathan_id, asset_id_type()).amount == 10000);
db.clear_pending();
@ -344,31 +344,31 @@ BOOST_AUTO_TEST_CASE( switch_forks_undo_create )
cop.owner = authority(1, key_id_type(), 1);
trx.operations.push_back(cop);
trx.sign( key_id_type(), delegate_priv_key );
db1.push_transaction(trx);
PUSH_TX( db1, trx );
auto aw = db1.get_global_properties().active_witnesses;
now += db1.block_interval();
auto b = db1.generate_block( now, db1.get_scheduled_witness( 1 ).first, delegate_priv_key );
auto b = db1.generate_block( now, db1.get_scheduled_witness( 1 ).first, delegate_priv_key, database::skip_nothing );
BOOST_CHECK(nathan_id(db1).name == "nathan");
now = fc::time_point_sec( GRAPHENE_GENESIS_TIMESTAMP );
now += db2.block_interval();
b = db2.generate_block( now, db2.get_scheduled_witness( 1 ).first, delegate_priv_key );
db1.push_block(b);
b = db2.generate_block( now, db2.get_scheduled_witness( 1 ).first, delegate_priv_key, database::skip_nothing );
PUSH_BLOCK( db1, b );
aw = db2.get_global_properties().active_witnesses;
now += db2.block_interval();
b = db2.generate_block( now, db2.get_scheduled_witness( 1 ).first, delegate_priv_key );
db1.push_block(b);
b = db2.generate_block( now, db2.get_scheduled_witness( 1 ).first, delegate_priv_key, database::skip_nothing );
PUSH_BLOCK( db1, b );
BOOST_CHECK_THROW(nathan_id(db1), fc::exception);
db2.push_transaction(trx);
PUSH_TX( db2, trx );
aw = db2.get_global_properties().active_witnesses;
now += db2.block_interval();
b = db2.generate_block( now, db2.get_scheduled_witness( 1 ).first, delegate_priv_key );
db1.push_block(b);
b = db2.generate_block( now, db2.get_scheduled_witness( 1 ).first, delegate_priv_key, database::skip_nothing );
PUSH_BLOCK( db1, b );
BOOST_CHECK(nathan_id(db1).name == "nathan");
BOOST_CHECK(nathan_id(db2).name == "nathan");
@ -402,22 +402,22 @@ BOOST_AUTO_TEST_CASE( duplicate_transactions )
cop.owner = authority(1, key_id_type(), 1);
trx.operations.push_back(cop);
trx.sign( key_id_type(), delegate_priv_key );
db1.push_transaction(trx, skip_sigs);
PUSH_TX( db1, trx, skip_sigs );
trx = decltype(trx)();
trx.set_expiration(db1.head_block_time() + fc::minutes(1));
trx.operations.push_back(transfer_operation({asset(), account_id_type(), nathan_id, asset(500)}));
trx.sign( key_id_type(), delegate_priv_key );
db1.push_transaction(trx, skip_sigs);
PUSH_TX( db1, trx, skip_sigs );
BOOST_CHECK_THROW(db1.push_transaction(trx, skip_sigs), fc::exception);
BOOST_CHECK_THROW(PUSH_TX( db1, trx, skip_sigs ), fc::exception);
now += db1.block_interval();
auto b = db1.generate_block( now, db1.get_scheduled_witness( 1 ).first, delegate_priv_key, skip_sigs );
db2.push_block(b, skip_sigs);
PUSH_BLOCK( db2, b, skip_sigs );
BOOST_CHECK_THROW(db1.push_transaction(trx, skip_sigs), fc::exception);
BOOST_CHECK_THROW(db2.push_transaction(trx, skip_sigs), fc::exception);
BOOST_CHECK_THROW(PUSH_TX( db1, trx, skip_sigs ), fc::exception);
BOOST_CHECK_THROW(PUSH_TX( db2, trx, skip_sigs ), fc::exception);
BOOST_CHECK_EQUAL(db1.get_balance(nathan_id, asset_id_type()).amount.value, 500);
BOOST_CHECK_EQUAL(db2.get_balance(nathan_id, asset_id_type()).amount.value, 500);
} catch (fc::exception& e) {
@ -443,7 +443,7 @@ BOOST_AUTO_TEST_CASE( tapos )
const graphene::db::index& account_idx = db1.get_index(protocol_ids, account_object_type);
now += db1.block_interval();
auto b = db1.generate_block( now, db1.get_scheduled_witness( 1 ).first, delegate_priv_key );
auto b = db1.generate_block( now, db1.get_scheduled_witness( 1 ).first, delegate_priv_key, database::skip_nothing );
signed_transaction trx;
//This transaction must be in the next block after its reference, or it is invalid.
@ -459,21 +459,21 @@ BOOST_AUTO_TEST_CASE( tapos )
trx.signatures.clear();
trx.sign( key_id_type(), delegate_priv_key );
db1.push_transaction(trx);
PUSH_TX( db1, trx );
now += db1.block_interval();
b = db1.generate_block( now, db1.get_scheduled_witness( 1 ).first, delegate_priv_key );
b = db1.generate_block( now, db1.get_scheduled_witness( 1 ).first, delegate_priv_key, database::skip_nothing );
trx.operations.clear();
trx.signatures.clear();
trx.operations.push_back(transfer_operation({asset(), account_id_type(), nathan_id, asset(50)}));
trx.sign( key_id_type(), delegate_priv_key );
//relative_expiration is 1, but ref block is 2 blocks old, so this should fail.
BOOST_REQUIRE_THROW(db1.push_transaction(trx, database::skip_transaction_signatures | database::skip_authority_check), fc::exception);
BOOST_REQUIRE_THROW(PUSH_TX( db1, trx, database::skip_transaction_signatures | database::skip_authority_check ), fc::exception);
trx.set_expiration(db1.head_block_id(), 2);
trx.signatures.clear();
trx.sign( key_id_type(), delegate_priv_key );
db1.push_transaction(trx, database::skip_transaction_signatures | database::skip_authority_check);
PUSH_TX( db1, trx, database::skip_transaction_signatures | database::skip_authority_check );
} catch (fc::exception& e) {
edump((e.to_detail_string()));
throw;
@ -498,7 +498,7 @@ BOOST_FIXTURE_TEST_CASE( maintenance_interval, database_fixture )
op.new_options = nathan.options;
op.new_options->votes.insert(nathans_delegate.vote_id);
trx.operations.push_back(op);
db.push_transaction(trx, ~0);
PUSH_TX( db, trx, ~0 );
trx.operations.clear();
}
transfer(account_id_type()(db), nathan, asset(5000));
@ -551,7 +551,7 @@ BOOST_FIXTURE_TEST_CASE( limit_order_expiration, database_fixture )
op.min_to_receive = test->amount(500);
op.expiration = db.head_block_time() + fc::seconds(10);
trx.operations.push_back(op);
auto ptrx = db.push_transaction(trx, ~0);
auto ptrx = PUSH_TX( db, trx, ~0 );
BOOST_CHECK_EQUAL( get_balance(*nathan, *core), 49500 );
@ -564,7 +564,7 @@ BOOST_FIXTURE_TEST_CASE( limit_order_expiration, database_fixture )
BOOST_CHECK_EQUAL( get_balance(*nathan, *core), 49500 );
auto id = limit_itr->id;
generate_blocks(op.expiration);
generate_blocks(op.expiration, false);
test = &get_asset("TEST");
core = &asset_id_type()(db);
nathan = &get_account("nathan");
@ -591,7 +591,7 @@ BOOST_FIXTURE_TEST_CASE( change_block_interval, database_fixture )
cop.proposed_ops.emplace_back(uop);
trx.operations.push_back(cop);
trx.sign(key_id_type(),generate_private_key("genesis"));
db.push_transaction(trx);
PUSH_TX( db, trx );
}
{
proposal_update_operation uop;
@ -600,7 +600,7 @@ BOOST_FIXTURE_TEST_CASE( change_block_interval, database_fixture )
account_id_type(5), account_id_type(6), account_id_type(7), account_id_type(8)};
trx.operations.push_back(uop);
trx.sign(key_id_type(),generate_private_key("genesis"));
db.push_transaction(trx);
PUSH_TX( db, trx );
BOOST_CHECK(proposal_id_type()(db).is_authorized_to_execute(&db));
}
@ -645,7 +645,7 @@ BOOST_FIXTURE_TEST_CASE( force_settlement, database_fixture )
op.new_options.maximum_force_settlement_volume = 9000;
trx.clear();
trx.operations.push_back(op);
db.push_transaction(trx, ~0);
PUSH_TX( db, trx, ~0 );
trx.clear();
}
generate_block();
@ -686,7 +686,7 @@ BOOST_FIXTURE_TEST_CASE( force_settlement, database_fixture )
trx.operations.push_back(pop);
}
trx.sign(key_id_type(),private_key);
db.push_transaction(trx);
PUSH_TX( db, trx );
trx.clear();
asset_settle_operation sop;
@ -698,7 +698,7 @@ BOOST_FIXTURE_TEST_CASE( force_settlement, database_fixture )
trx.sign(key_id_type(),private_key);
//Partially settle a call
force_settlement_id_type settle_id = db.push_transaction(trx).operation_results.front().get<object_id_type>();
force_settlement_id_type settle_id = PUSH_TX( db, trx ).operation_results.front().get<object_id_type>();
trx.clear();
call_order_id_type call_id = db.get_index_type<call_order_index>().indices().get<by_collateral>().begin()->id;
BOOST_CHECK_EQUAL(settle_id(db).balance.amount.value, 50);
@ -716,10 +716,10 @@ BOOST_FIXTURE_TEST_CASE( force_settlement, database_fixture )
trx.operations.push_back(sop);
trx.sign(key_id_type(),private_key);
//Trx has expired by now. Make sure it throws.
BOOST_CHECK_THROW(settle_id = db.push_transaction(trx).operation_results.front().get<object_id_type>(), fc::exception);
BOOST_CHECK_THROW(settle_id = PUSH_TX( db, trx ).operation_results.front().get<object_id_type>(), fc::exception);
trx.set_expiration(db.head_block_time() + fc::minutes(1));
trx.sign(key_id_type(),private_key);
settle_id = db.push_transaction(trx).operation_results.front().get<object_id_type>();
settle_id = PUSH_TX( db, trx ).operation_results.front().get<object_id_type>();
trx.clear();
generate_blocks(settle_id(db).settlement_date);
@ -732,7 +732,7 @@ BOOST_FIXTURE_TEST_CASE( force_settlement, database_fixture )
sop.amount = db.get_balance(nathan_id, bit_usd);
trx.operations.push_back(sop);
trx.sign(key_id_type(),private_key);
settle_id = db.push_transaction(trx).operation_results.front().get<object_id_type>();
settle_id = PUSH_TX( db, trx ).operation_results.front().get<object_id_type>();
trx.clear();
generate_blocks(settle_id(db).settlement_date);

View file

@ -77,7 +77,7 @@ BOOST_AUTO_TEST_CASE( cashback_test )
op.fee = op.calculate_fee(fees); \
trx.operations = {op}; \
trx.sign(registrar_name ## _key_id, registrar_name ## _private_key); \
actor_name ## _id = db.push_transaction(trx).operation_results.front().get<object_id_type>(); \
actor_name ## _id = PUSH_TX( db, trx ).operation_results.front().get<object_id_type>(); \
trx.clear(); \
}

View file

@ -146,17 +146,17 @@ BOOST_AUTO_TEST_CASE( create_account_test )
op.owner.add_authority(account_id_type(9999999999), 10);
trx.operations.back() = op;
op.owner = auth_bak;
BOOST_REQUIRE_THROW(db.push_transaction(trx, ~0), fc::exception);
BOOST_REQUIRE_THROW(PUSH_TX( db, trx, ~0 ), fc::exception);
op.owner = auth_bak;
op.owner.add_authority(key_id_type(9999999999), 10);
trx.operations.back() = op;
BOOST_REQUIRE_THROW(db.push_transaction(trx, ~0), fc::exception);
BOOST_REQUIRE_THROW(PUSH_TX( db, trx, ~0 ), fc::exception);
op.owner = auth_bak;
trx.operations.back() = op;
trx.sign( key_id_type(), fc::ecc::private_key::regenerate(fc::sha256::hash(string("genesis"))) );
trx.validate();
db.push_transaction(trx, ~0);
PUSH_TX( db, trx, ~0 );
const account_object& nathan_account = *db.get_index_type<account_index>().indices().get<by_name>().find("nathan");
BOOST_CHECK(nathan_account.id.space() == protocol_ids);
@ -206,15 +206,15 @@ BOOST_AUTO_TEST_CASE( child_account )
trx.operations.emplace_back(op);
sign(trx, key_id_type(), fc::ecc::private_key::regenerate(fc::sha256::hash(string("genesis"))));
BOOST_REQUIRE_THROW(db.push_transaction(trx), fc::exception);
BOOST_REQUIRE_THROW(PUSH_TX( db, trx ), fc::exception);
sign(trx, nathan_key.id,nathan_private_key);
BOOST_REQUIRE_THROW(db.push_transaction(trx), fc::exception);
BOOST_REQUIRE_THROW(PUSH_TX( db, trx ), fc::exception);
trx.signatures.clear();
op.owner = authority(1, account_id_type(nathan.id), 1);
trx.operations = {op};
sign(trx, key_id_type(), fc::ecc::private_key::regenerate(fc::sha256::hash(string("genesis"))));
sign(trx, nathan_key.id, nathan_private_key);
db.push_transaction(trx);
PUSH_TX( db, trx );
BOOST_CHECK( get_account("nathan/child").active.auths == op.active.auths );
} catch (fc::exception& e) {
@ -235,7 +235,7 @@ BOOST_AUTO_TEST_CASE( update_account )
transfer(account_id_type()(db), nathan, asset(30000));
trx.operations.emplace_back(key_create_operation({asset(),nathan.id,address(nathan_new_key.get_public_key())}));
db.push_transaction(trx, ~0);
PUSH_TX( db, trx, ~0 );
account_update_operation op;
op.account = nathan.id;
@ -245,7 +245,7 @@ BOOST_AUTO_TEST_CASE( update_account )
op.new_options->votes = flat_set<vote_id_type>({active_delegates[0](db).vote_id, active_delegates[5](db).vote_id});
op.new_options->num_committee = 2;
trx.operations.back() = op;
db.push_transaction(trx, ~0);
PUSH_TX( db, trx, ~0 );
BOOST_CHECK(nathan.options.memo_key == key_id_type());
BOOST_CHECK(nathan.active.weight_threshold == 2);
@ -275,7 +275,7 @@ BOOST_AUTO_TEST_CASE( update_account )
op.upgrade_to_lifetime_member = true;
op.fee = op.calculate_fee(db.get_global_properties().parameters.current_fees);
trx.operations = {op};
db.push_transaction(trx, ~0);
PUSH_TX( db, trx, ~0 );
}
BOOST_CHECK( nathan.is_lifetime_member() );
@ -303,7 +303,7 @@ BOOST_AUTO_TEST_CASE( transfer_core_asset )
asset fee = trx.operations.front().get<transfer_operation>().fee;
trx.validate();
db.push_transaction(trx, ~0);
PUSH_TX( db, trx, ~0 );
BOOST_CHECK_EQUAL(get_balance(account_id_type()(db), asset_id_type()(db)),
(genesis_balance.amount - 10000 - fee.amount).value);
@ -322,7 +322,7 @@ BOOST_AUTO_TEST_CASE( transfer_core_asset )
fee = trx.operations.front().get<transfer_operation>().fee;
trx.validate();
db.push_transaction(trx, ~0);
PUSH_TX( db, trx, ~0 );
BOOST_CHECK_EQUAL(get_balance(nathan_account, asset_id_type()(db)), 8000 - fee.amount.value);
BOOST_CHECK_EQUAL(get_balance(account_id_type()(db), asset_id_type()(db)), genesis_balance.amount.value + 2000);
@ -346,7 +346,7 @@ BOOST_AUTO_TEST_CASE( create_delegate )
trx.operations.back() = op;
delegate_id_type delegate_id = db.get_index_type<primary_index<simple_index<delegate_object>>>().get_next_id();
db.push_transaction(trx, ~0);
PUSH_TX( db, trx, ~0 );
const delegate_object& d = delegate_id(db);
BOOST_CHECK(d.delegate_account == account_id_type());
@ -384,11 +384,11 @@ BOOST_AUTO_TEST_CASE( update_mia )
trx.operations.emplace_back(op);
trx.operations.back() = op;
db.push_transaction(trx, ~0);
PUSH_TX( db, trx, ~0 );
std::swap(op.new_options.flags, op.new_options.issuer_permissions);
op.new_issuer = account_id_type();
trx.operations.back() = op;
db.push_transaction(trx, ~0);
PUSH_TX( db, trx, ~0 );
{
asset_publish_feed_operation pop;
@ -402,7 +402,7 @@ BOOST_AUTO_TEST_CASE( update_mia )
pop.feed = feed;
REQUIRE_THROW_WITH_VALUE(pop, feed.maintenance_collateral_ratio, 0);
trx.operations.back() = pop;
db.push_transaction(trx, ~0);
PUSH_TX( db, trx, ~0 );
}
trx.operations.clear();
@ -410,13 +410,13 @@ BOOST_AUTO_TEST_CASE( update_mia )
op.issuer = account_id_type();
op.new_issuer = nathan.id;
trx.operations.emplace_back(op);
db.push_transaction(trx, ~0);
PUSH_TX( db, trx, ~0 );
BOOST_CHECK(bit_usd.issuer == nathan.id);
op.issuer = nathan.id;
op.new_issuer = account_id_type();
trx.operations.back() = op;
db.push_transaction(trx, ~0);
PUSH_TX( db, trx, ~0 );
BOOST_CHECK(bit_usd.issuer == account_id_type());
} catch ( const fc::exception& e ) {
elog( "${e}", ("e", e.to_detail_string() ) );
@ -440,7 +440,7 @@ BOOST_AUTO_TEST_CASE( create_uia )
creator.common_options.flags = charge_market_fee;
creator.common_options.core_exchange_rate = price({asset(2),asset(1,1)});
trx.operations.push_back(std::move(creator));
db.push_transaction(trx, ~0);
PUSH_TX( db, trx, ~0 );
const asset_object& test_asset = test_asset_id(db);
BOOST_CHECK(test_asset.symbol == "TEST");
@ -449,7 +449,7 @@ BOOST_AUTO_TEST_CASE( create_uia )
BOOST_CHECK(test_asset.options.max_supply == 100000000);
BOOST_CHECK(!test_asset.bitasset_data_id.valid());
BOOST_CHECK(test_asset.options.market_fee_percent == GRAPHENE_MAX_MARKET_FEE_PERCENT/100);
BOOST_REQUIRE_THROW(db.push_transaction(trx, ~0), fc::exception);
BOOST_REQUIRE_THROW(PUSH_TX( db, trx, ~0 ), fc::exception);
const asset_dynamic_data_object& test_asset_dynamic_data = test_asset.dynamic_asset_data_id(db);
BOOST_CHECK(test_asset_dynamic_data.current_supply == 0);
@ -499,22 +499,22 @@ BOOST_AUTO_TEST_CASE( update_uia )
op.new_options.core_exchange_rate = price(asset(3), test.amount(5));
trx.operations.back() = op;
db.push_transaction(trx, ~0);
PUSH_TX( db, trx, ~0 );
REQUIRE_THROW_WITH_VALUE(op, new_options.core_exchange_rate, price());
op.new_options.core_exchange_rate = test.options.core_exchange_rate;
op.new_issuer = nathan.id;
trx.operations.back() = op;
db.push_transaction(trx, ~0);
PUSH_TX( db, trx, ~0 );
op.issuer = nathan.id;
op.new_issuer.reset();
op.new_options.flags = transfer_restricted | white_list;
trx.operations.back() = op;
db.push_transaction(trx, ~0);
PUSH_TX( db, trx, ~0 );
REQUIRE_THROW_WITH_VALUE(op, new_options.issuer_permissions, test.options.issuer_permissions & ~white_list);
op.new_options.issuer_permissions = test.options.issuer_permissions & ~white_list;
op.new_options.flags = 0;
trx.operations.back() = op;
db.push_transaction(trx, ~0);
PUSH_TX( db, trx, ~0 );
op.new_options.issuer_permissions = test.options.issuer_permissions;
op.new_options.flags = test.options.flags;
BOOST_CHECK(!(test.options.issuer_permissions & white_list));
@ -522,9 +522,9 @@ BOOST_AUTO_TEST_CASE( update_uia )
REQUIRE_THROW_WITH_VALUE(op, new_options.flags, white_list);
op.new_issuer = account_id_type();
trx.operations.back() = op;
db.push_transaction(trx, ~0);
PUSH_TX( db, trx, ~0 );
op.issuer = account_id_type();
BOOST_REQUIRE_THROW(db.push_transaction(trx, ~0), fc::exception);
BOOST_REQUIRE_THROW(PUSH_TX( db, trx, ~0 ), fc::exception);
op.new_issuer.reset();
} catch(fc::exception& e) {
edump((e.to_detail_string()));
@ -549,7 +549,7 @@ BOOST_AUTO_TEST_CASE( issue_uia )
REQUIRE_THROW_WITH_VALUE(op, issue_to_account, account_id_type(999999999));
trx.operations.back() = op;
db.push_transaction(trx, ~0);
PUSH_TX( db, trx, ~0 );
const asset_dynamic_data_object& test_dynamic_data = test_asset.dynamic_asset_data_id(db);
BOOST_CHECK_EQUAL(get_balance(nathan_account, test_asset), 5000000);
@ -557,7 +557,7 @@ BOOST_AUTO_TEST_CASE( issue_uia )
BOOST_CHECK(test_dynamic_data.accumulated_fees == 0);
BOOST_CHECK(test_dynamic_data.fee_pool == 0);
db.push_transaction(trx, ~0);
PUSH_TX( db, trx, ~0 );
BOOST_CHECK_EQUAL(get_balance(nathan_account, test_asset), 10000000);
BOOST_CHECK(test_dynamic_data.current_supply == 10000000);
@ -580,11 +580,11 @@ BOOST_AUTO_TEST_CASE( transfer_uia )
BOOST_CHECK_EQUAL(get_balance(nathan, uia), 10000000);
trx.operations.push_back(transfer_operation({asset(),nathan.id, genesis.id, uia.amount(5000)}));
db.push_transaction(trx, ~0);
PUSH_TX( db, trx, ~0 );
BOOST_CHECK_EQUAL(get_balance(nathan, uia), 10000000 - 5000);
BOOST_CHECK_EQUAL(get_balance(genesis, uia), 5000);
db.push_transaction(trx, ~0);
PUSH_TX( db, trx, ~0 );
BOOST_CHECK_EQUAL(get_balance(nathan, uia), 10000000 - 10000);
BOOST_CHECK_EQUAL(get_balance(genesis, uia), 10000);
} catch(fc::exception& e) {
@ -782,7 +782,7 @@ BOOST_AUTO_TEST_CASE( uia_fees )
BOOST_CHECK(fee.amount > 0);
asset core_fee = fee*test_asset.options.core_exchange_rate;
trx.operations.push_back(std::move(op));
db.push_transaction(trx, ~0);
PUSH_TX( db, trx, ~0 );
BOOST_CHECK_EQUAL(get_balance(nathan_account, test_asset),
(old_balance - fee - test_asset.amount(100)).amount.value);
@ -791,7 +791,7 @@ BOOST_AUTO_TEST_CASE( uia_fees )
BOOST_CHECK(asset_dynamic.fee_pool == 1000000 - core_fee.amount);
//Do it again, for good measure.
db.push_transaction(trx, ~0);
PUSH_TX( db, trx, ~0 );
BOOST_CHECK_EQUAL(get_balance(nathan_account, test_asset),
(old_balance - fee - fee - test_asset.amount(200)).amount.value);
BOOST_CHECK_EQUAL(get_balance(genesis_account, test_asset), 200);
@ -808,7 +808,7 @@ BOOST_AUTO_TEST_CASE( uia_fees )
BOOST_CHECK_EQUAL(get_balance(nathan_account, asset_id_type()(db)), 20);
trx.operations.emplace_back(std::move(op));
db.push_transaction(trx, ~0);
PUSH_TX( db, trx, ~0 );
BOOST_CHECK_EQUAL(get_balance(nathan_account, asset_id_type()(db)), 0);
BOOST_CHECK_EQUAL(get_balance(nathan_account, test_asset),
@ -855,7 +855,7 @@ BOOST_AUTO_TEST_CASE( delegate_feeds )
asset_update_operation uop(get_asset("BITUSD"));
uop.new_issuer = account_id_type();
trx.operations.push_back(uop);
db.push_transaction(trx, ~0);
PUSH_TX( db, trx, ~0 );
trx.clear();
}
generate_block();
@ -870,7 +870,7 @@ BOOST_AUTO_TEST_CASE( delegate_feeds )
op.feed.settlement_price = price(asset(GRAPHENE_BLOCKCHAIN_PRECISION),bit_usd.amount(30));
// Accept defaults for required collateral
trx.operations.emplace_back(op);
db.push_transaction(trx, ~0);
PUSH_TX( db, trx, ~0 );
{
//Dumb sanity check of some operators. Only here to improve code coverage. :D
@ -892,7 +892,7 @@ BOOST_AUTO_TEST_CASE( delegate_feeds )
op.publisher = active_witnesses[1];
op.feed.settlement_price = price(asset(GRAPHENE_BLOCKCHAIN_PRECISION),bit_usd.amount(25));
trx.operations.back() = op;
db.push_transaction(trx, ~0);
PUSH_TX( db, trx, ~0 );
BOOST_CHECK_EQUAL(bitasset.current_feed.settlement_price.to_real(), GRAPHENE_BLOCKCHAIN_PRECISION / 25.0);
BOOST_CHECK(bitasset.current_feed.maintenance_collateral_ratio == GRAPHENE_DEFAULT_MAINTENANCE_COLLATERAL_RATIO);
@ -902,7 +902,7 @@ BOOST_AUTO_TEST_CASE( delegate_feeds )
// But this delegate is an idiot.
op.feed.maintenance_collateral_ratio = 1000;
trx.operations.back() = op;
db.push_transaction(trx, ~0);
PUSH_TX( db, trx, ~0 );
BOOST_CHECK_EQUAL(bitasset.current_feed.settlement_price.to_real(), GRAPHENE_BLOCKCHAIN_PRECISION / 30.0);
BOOST_CHECK(bitasset.current_feed.maintenance_collateral_ratio == GRAPHENE_DEFAULT_MAINTENANCE_COLLATERAL_RATIO);
@ -913,7 +913,6 @@ BOOST_AUTO_TEST_CASE( delegate_feeds )
}
/**
* Create an order such that when the trade executes at the
* requested price the resulting payout to one party is 0
@ -1195,10 +1194,10 @@ BOOST_AUTO_TEST_CASE( limit_order_fill_or_kill )
trx.operations.clear();
trx.operations.push_back(op);
BOOST_CHECK_THROW(db.push_transaction(trx, ~0), fc::exception);
BOOST_CHECK_THROW(PUSH_TX( db, trx, ~0 ), fc::exception);
op.fill_or_kill = false;
trx.operations.back() = op;
db.push_transaction(trx, ~0);
PUSH_TX( db, trx, ~0 );
} FC_LOG_AND_RETHROW() }
/// Shameless code coverage plugging. Otherwise, these calls never happen.
@ -1246,7 +1245,7 @@ BOOST_AUTO_TEST_CASE( witness_withdraw_pay_test )
trx.visit(operation_set_fee(db.current_fee_schedule()));
trx.validate();
trx.sign(key_id_type(),generate_private_key("genesis"));
db.push_transaction(trx);
PUSH_TX( db, trx );
trx.clear();
BOOST_CHECK_EQUAL(get_balance(*nathan, *core), 8950000000);
@ -1325,7 +1324,7 @@ BOOST_AUTO_TEST_CASE( witness_withdraw_pay_test )
trx.visit(operation_set_fee(db.current_fee_schedule()));
trx.validate();
trx.sign(key_id_type(),generate_private_key("genesis"));
db.push_transaction(trx);
PUSH_TX( db, trx );
trx.clear();
BOOST_CHECK_EQUAL(get_balance(witness->witness_account(db), *core), witness_ppb - 1/*fee*/);
@ -1555,7 +1554,7 @@ BOOST_AUTO_TEST_CASE( vesting_balance_withdraw_test )
create_op.vesting_seconds = vesting_seconds;
tx.operations.push_back( create_op );
processed_transaction ptx = db.push_transaction( tx, ~0 );
processed_transaction ptx = PUSH_TX( db, tx, ~0 );
const vesting_balance_object& vbo = vesting_balance_id_type(
ptx.operation_results[0].get<object_id_type>())(db);

View file

@ -70,7 +70,7 @@ BOOST_AUTO_TEST_CASE( withdraw_permission_create )
}
trx.sign(nathan_key_id, nathan_private_key);
db.push_transaction(trx);
PUSH_TX( db, trx );
trx.clear();
} FC_LOG_AND_RETHROW() }
@ -108,7 +108,7 @@ BOOST_AUTO_TEST_CASE( withdraw_permission_test )
op.amount_to_withdraw = asset(1);
trx.operations.push_back(op);
//Throws because we haven't entered the first withdrawal period yet.
BOOST_REQUIRE_THROW(db.push_transaction(trx), fc::exception);
BOOST_REQUIRE_THROW(PUSH_TX( db, trx ), fc::exception);
//Get to the actual withdrawal period
generate_blocks(permit(db).period_start_time);
@ -122,7 +122,7 @@ BOOST_AUTO_TEST_CASE( withdraw_permission_test )
trx.clear();
trx.operations.push_back(op);
trx.sign(dan_key_id, dan_private_key);
db.push_transaction(trx);
PUSH_TX( db, trx );
// would be legal on its own, but doesn't work because trx already withdrew
REQUIRE_THROW_WITH_VALUE(op, amount_to_withdraw, asset(5));
@ -131,7 +131,7 @@ BOOST_AUTO_TEST_CASE( withdraw_permission_test )
trx.operations.back() = op; // withdraw 1
trx.ref_block_prefix++; // make it different from previous trx so it's non-duplicate
trx.sign(dan_key_id, dan_private_key);
db.push_transaction(trx);
PUSH_TX( db, trx );
trx.clear();
}
@ -162,11 +162,11 @@ BOOST_AUTO_TEST_CASE( withdraw_permission_test )
trx.operations.push_back(op);
trx.sign(dan_key_id, dan_private_key);
//Throws because nathan doesn't have the money
BOOST_CHECK_THROW(db.push_transaction(trx), fc::exception);
BOOST_CHECK_THROW(PUSH_TX( db, trx ), fc::exception);
op.amount_to_withdraw = asset(1);
trx.operations.back() = op;
trx.sign(dan_key_id, dan_private_key);
db.push_transaction(trx);
PUSH_TX( db, trx );
}
BOOST_CHECK_EQUAL(get_balance(nathan_id, asset_id_type()), 0);
@ -196,7 +196,7 @@ BOOST_AUTO_TEST_CASE( withdraw_permission_test )
trx.operations.push_back(op);
trx.sign(dan_key_id, dan_private_key);
//Throws because the permission has expired
BOOST_CHECK_THROW(db.push_transaction(trx), fc::exception);
BOOST_CHECK_THROW(PUSH_TX( db, trx ), fc::exception);
}
} FC_LOG_AND_RETHROW() }
@ -226,7 +226,7 @@ BOOST_AUTO_TEST_CASE( withdraw_permission_nominal_case )
// so tx's have different txid's
trx.ref_block_prefix++;
trx.sign(dan_key_id, dan_private_key);
db.push_transaction(trx);
PUSH_TX( db, trx );
// tx's involving withdraw_permissions can't delete it even
// if no further withdrawals are possible
BOOST_CHECK(db.find_object(permit) != nullptr);
@ -273,7 +273,7 @@ BOOST_AUTO_TEST_CASE( withdraw_permission_update )
REQUIRE_THROW_WITH_VALUE(op, period_start_time, db.head_block_time() - 50);
trx.operations.back() = op;
trx.sign(nathan_key_id, nathan_private_key);
db.push_transaction(trx);
PUSH_TX( db, trx );
}
{
@ -297,7 +297,7 @@ BOOST_AUTO_TEST_CASE( withdraw_permission_delete )
trx.set_expiration(db.head_block_id());
trx.operations.push_back(op);
trx.sign(get_account("nathan").active.auths.begin()->first, generate_private_key("nathan"));
db.push_transaction(trx);
PUSH_TX( db, trx );
} FC_LOG_AND_RETHROW() }
BOOST_AUTO_TEST_CASE( mia_feeds )
@ -313,7 +313,7 @@ BOOST_AUTO_TEST_CASE( mia_feeds )
op.new_issuer = nathan_id;
op.new_options = obj.options;
trx.operations.push_back(op);
db.push_transaction(trx, ~0);
PUSH_TX( db, trx, ~0 );
generate_block();
trx.clear();
}
@ -324,7 +324,7 @@ BOOST_AUTO_TEST_CASE( mia_feeds )
op.new_feed_producers = {dan_id, ben_id, vikram_id};
trx.operations.push_back(op);
trx.sign(nathan_key_id, nathan_private_key);
db.push_transaction(trx);
PUSH_TX( db, trx );
generate_block(database::skip_nothing);
}
{
@ -340,7 +340,7 @@ BOOST_AUTO_TEST_CASE( mia_feeds )
// We'll expire margins after a month
// Accept defaults for required collateral
trx.operations.emplace_back(op);
db.push_transaction(trx, ~0);
PUSH_TX( db, trx, ~0 );
const asset_bitasset_data_object& bitasset = bit_usd.bitasset_data(db);
BOOST_CHECK(bitasset.current_feed.settlement_price.to_real() == GRAPHENE_BLOCKCHAIN_PRECISION / 30.0);
@ -349,7 +349,7 @@ BOOST_AUTO_TEST_CASE( mia_feeds )
op.publisher = ben_id;
op.feed.settlement_price = price(asset(GRAPHENE_BLOCKCHAIN_PRECISION),bit_usd.amount(25));
trx.operations.back() = op;
db.push_transaction(trx, ~0);
PUSH_TX( db, trx, ~0 );
BOOST_CHECK_EQUAL(bitasset.current_feed.settlement_price.to_real(), GRAPHENE_BLOCKCHAIN_PRECISION / 25.0);
BOOST_CHECK(bitasset.current_feed.maintenance_collateral_ratio == GRAPHENE_DEFAULT_MAINTENANCE_COLLATERAL_RATIO);
@ -358,14 +358,14 @@ BOOST_AUTO_TEST_CASE( mia_feeds )
op.feed.settlement_price = price(asset(GRAPHENE_BLOCKCHAIN_PRECISION),bit_usd.amount(40));
op.feed.maintenance_collateral_ratio = 1000;
trx.operations.back() = op;
db.push_transaction(trx, ~0);
PUSH_TX( db, trx, ~0 );
BOOST_CHECK_EQUAL(bitasset.current_feed.settlement_price.to_real(), GRAPHENE_BLOCKCHAIN_PRECISION / 30.0);
BOOST_CHECK(bitasset.current_feed.maintenance_collateral_ratio == GRAPHENE_DEFAULT_MAINTENANCE_COLLATERAL_RATIO);
op.publisher = nathan_id;
trx.operations.back() = op;
BOOST_CHECK_THROW(db.push_transaction(trx, ~0), fc::exception);
BOOST_CHECK_THROW(PUSH_TX( db, trx, ~0 ), fc::exception);
}
} FC_LOG_AND_RETHROW() }
@ -391,7 +391,7 @@ BOOST_AUTO_TEST_CASE( witness_create )
[](vote_id_type id) { return id.type() == vote_id_type::committee; });
trx.operations.push_back(op);
trx.sign(nathan_key_id, nathan_private_key);
db.push_transaction(trx);
PUSH_TX( db, trx );
trx.clear();
}
@ -468,7 +468,7 @@ BOOST_AUTO_TEST_CASE( global_settle_test )
REQUIRE_THROW_WITH_VALUE(op, issuer, account_id_type(2));
trx.operations.back() = op;
trx.sign(nathan_key_id, nathan_private_key);
db.push_transaction(trx);
PUSH_TX( db, trx );
}
BOOST_CHECK_EQUAL(get_balance(valentine_id, bit_usd_id), 0);
@ -502,7 +502,7 @@ BOOST_AUTO_TEST_CASE( worker_create_test )
REQUIRE_THROW_WITH_VALUE(op, work_end_date, op.work_begin_date);
trx.operations.back() = op;
trx.sign(nathan_key_id, nathan_private_key);
db.push_transaction(trx);
PUSH_TX( db, trx );
}
const worker_object& worker = worker_id_type()(db);
@ -532,7 +532,7 @@ BOOST_AUTO_TEST_CASE( worker_pay_test )
op.new_options = nathan_id(db).options;
op.new_options->votes.insert(worker_id_type()(db).vote_for);
trx.operations.push_back(op);
db.push_transaction(trx, ~0);
PUSH_TX( db, trx, ~0 );
trx.clear();
}
{
@ -540,7 +540,7 @@ BOOST_AUTO_TEST_CASE( worker_pay_test )
op.payer = account_id_type();
op.amount_to_burn = asset(GRAPHENE_INITIAL_SUPPLY/2);
trx.operations.push_back(op);
db.push_transaction(trx, ~0);
PUSH_TX( db, trx, ~0 );
trx.clear();
}
@ -557,7 +557,7 @@ BOOST_AUTO_TEST_CASE( worker_pay_test )
trx.set_expiration(db.head_block_id());
trx.operations.push_back(op);
trx.sign(nathan_key_id, nathan_private_key);
db.push_transaction(trx);
PUSH_TX( db, trx );
trx.signatures.clear();
REQUIRE_THROW_WITH_VALUE(op, amount, asset(1));
trx.clear();
@ -572,7 +572,7 @@ BOOST_AUTO_TEST_CASE( worker_pay_test )
op.new_options = nathan_id(db).options;
op.new_options->votes.erase(worker_id_type()(db).vote_for);
trx.operations.push_back(op);
db.push_transaction(trx, ~0);
PUSH_TX( db, trx, ~0 );
trx.clear();
}
@ -592,7 +592,7 @@ BOOST_AUTO_TEST_CASE( worker_pay_test )
REQUIRE_THROW_WITH_VALUE(op, amount, asset(501));
trx.operations.back() = op;
trx.sign(nathan_key_id, nathan_private_key);
db.push_transaction(trx);
PUSH_TX( db, trx );
trx.signatures.clear();
trx.clear();
}
@ -625,7 +625,7 @@ BOOST_AUTO_TEST_CASE( refund_worker_test )
REQUIRE_THROW_WITH_VALUE(op, work_end_date, op.work_begin_date);
trx.operations.back() = op;
trx.sign(nathan_key_id, nathan_private_key);
db.push_transaction(trx);
PUSH_TX( db, trx );
trx.clear();
}
@ -645,7 +645,7 @@ BOOST_AUTO_TEST_CASE( refund_worker_test )
op.new_options = nathan_id(db).options;
op.new_options->votes.insert(worker_id_type()(db).vote_for);
trx.operations.push_back(op);
db.push_transaction(trx, ~0);
PUSH_TX( db, trx, ~0 );
trx.clear();
}
{
@ -653,14 +653,17 @@ BOOST_AUTO_TEST_CASE( refund_worker_test )
op.payer = account_id_type();
op.amount_to_burn = asset(GRAPHENE_INITIAL_SUPPLY/2);
trx.operations.push_back(op);
db.push_transaction(trx, ~0);
PUSH_TX( db, trx, ~0 );
trx.clear();
}
// auto supply = asset_id_type()(db).dynamic_data(db).current_supply;
verify_asset_supplies();
generate_blocks(db.get_dynamic_global_properties().next_maintenance_time);
verify_asset_supplies();
BOOST_CHECK_EQUAL(worker_id_type()(db).worker.get<refund_worker_type>().total_burned.value, 1000);
generate_blocks(db.get_dynamic_global_properties().next_maintenance_time);
verify_asset_supplies();
BOOST_CHECK_EQUAL(worker_id_type()(db).worker.get<refund_worker_type>().total_burned.value, 2000);
generate_blocks(db.get_dynamic_global_properties().next_maintenance_time);
BOOST_CHECK(!db.get(worker_id_type()).is_active(db.head_block_time()));
@ -690,7 +693,7 @@ BOOST_AUTO_TEST_CASE( force_settlement_unavailable )
op.new_options.maximum_force_settlement_volume = 9000;
trx.clear();
trx.operations.push_back(op);
db.push_transaction(trx, ~0);
PUSH_TX( db, trx, ~0 );
trx.clear();
}
generate_block();
@ -730,7 +733,7 @@ BOOST_AUTO_TEST_CASE( force_settlement_unavailable )
trx.operations.push_back(pop);
}
trx.sign(key_id_type(),private_key);
db.push_transaction(trx);
PUSH_TX( db, trx );
trx.clear();
asset_settle_operation sop;
@ -738,7 +741,7 @@ BOOST_AUTO_TEST_CASE( force_settlement_unavailable )
sop.amount = asset(50, bit_usd);
trx.operations = {sop};
//Force settlement is disabled; check that it fails
BOOST_CHECK_THROW(db.push_transaction(trx, ~0), fc::exception);
BOOST_CHECK_THROW(PUSH_TX( db, trx, ~0 ), fc::exception);
{
//Enable force settlement
asset_update_operation op;
@ -748,7 +751,7 @@ BOOST_AUTO_TEST_CASE( force_settlement_unavailable )
op.new_options.flags &= ~disable_force_settle;
trx.operations = {op};
trx.sign(key_id_type(), private_key);
db.push_transaction(trx);
PUSH_TX( db, trx );
trx.operations = {sop};
}
REQUIRE_THROW_WITH_VALUE(sop, amount, asset(999999, bit_usd));
@ -756,7 +759,7 @@ BOOST_AUTO_TEST_CASE( force_settlement_unavailable )
trx.sign(key_id_type(),private_key);
//Partially settle a call
force_settlement_id_type settle_id = db.push_transaction(trx).operation_results.front().get<object_id_type>();
force_settlement_id_type settle_id = PUSH_TX( db, trx ).operation_results.front().get<object_id_type>();
trx.clear();
call_order_id_type call_id = db.get_index_type<call_order_index>().indices().get<by_collateral>().begin()->id;
BOOST_CHECK_EQUAL(settle_id(db).balance.amount.value, 50);
@ -778,7 +781,7 @@ BOOST_AUTO_TEST_CASE( force_settlement_unavailable )
trx.operations.push_back(op);
trx.set_expiration(db.head_block_id());
trx.sign(key_id_type(), private_key);
db.push_transaction(trx);
PUSH_TX( db, trx );
//Check that force settlements were all canceled
BOOST_CHECK(db.get_index_type<force_settlement_index>().indices().empty());
BOOST_CHECK_EQUAL(get_balance(nathan_id, bit_usd), bit_usd(db).dynamic_data(db).current_supply.value);

View file

@ -50,7 +50,7 @@ BOOST_AUTO_TEST_CASE( create_advanced_uia )
creator.common_options.core_exchange_rate = price({asset(2),asset(1,1)});
creator.common_options.whitelist_authorities = creator.common_options.blacklist_authorities = {account_id_type()};
trx.operations.push_back(std::move(creator));
db.push_transaction(trx, ~0);
PUSH_TX( db, trx, ~0 );
const asset_object& test_asset = test_asset_id(db);
BOOST_CHECK(test_asset.symbol == "ADVANCED");
@ -82,16 +82,16 @@ BOOST_AUTO_TEST_CASE( issue_whitelist_uia )
asset_issue_operation op({asset(), advanced.issuer, advanced.amount(1000), nathan.id});
trx.operations.emplace_back(op);
//Fail because nathan is not whitelisted.
BOOST_REQUIRE_THROW(db.push_transaction(trx, ~0), fc::exception);
BOOST_REQUIRE_THROW(PUSH_TX( db, trx, ~0 ), fc::exception);
account_whitelist_operation wop({asset(), account_id_type(), nathan.id, account_whitelist_operation::white_listed});
trx.operations.back() = wop;
db.push_transaction(trx, ~0);
PUSH_TX( db, trx, ~0 );
BOOST_CHECK(nathan.is_authorized_asset(advanced));
trx.operations.back() = op;
db.push_transaction(trx, ~0);
PUSH_TX( db, trx, ~0 );
BOOST_CHECK_EQUAL(get_balance(nathan, advanced), 1000);
} catch(fc::exception& e) {
@ -113,13 +113,13 @@ BOOST_AUTO_TEST_CASE( transfer_whitelist_uia )
transfer_operation op({advanced.amount(0), nathan.id, dan.id, advanced.amount(100)});
trx.operations.push_back(op);
//Fail because dan is not whitelisted.
BOOST_REQUIRE_THROW(db.push_transaction(trx, ~0), fc::exception);
BOOST_REQUIRE_THROW(PUSH_TX( db, trx, ~0 ), fc::exception);
account_whitelist_operation wop({asset(), account_id_type(), dan.id, account_whitelist_operation::white_listed});
trx.operations.back() = wop;
db.push_transaction(trx, ~0);
PUSH_TX( db, trx, ~0 );
trx.operations.back() = op;
db.push_transaction(trx, ~0);
PUSH_TX( db, trx, ~0 );
BOOST_CHECK_EQUAL(get_balance(nathan, advanced), 900);
BOOST_CHECK_EQUAL(get_balance(dan, advanced), 100);
@ -127,16 +127,16 @@ BOOST_AUTO_TEST_CASE( transfer_whitelist_uia )
wop.new_listing |= account_whitelist_operation::black_listed;
wop.account_to_list = nathan.id;
trx.operations.back() = wop;
db.push_transaction(trx, ~0);
PUSH_TX( db, trx, ~0 );
op.amount = advanced.amount(50);
trx.operations.back() = op;
//Fail because nathan is blacklisted
BOOST_REQUIRE_THROW(db.push_transaction(trx, ~0), fc::exception);
BOOST_REQUIRE_THROW(PUSH_TX( db, trx, ~0 ), fc::exception);
std::swap(op.from, op.to);
trx.operations.back() = op;
//Fail because nathan is blacklisted
BOOST_REQUIRE_THROW(db.push_transaction(trx, ~0), fc::exception);
BOOST_REQUIRE_THROW(PUSH_TX( db, trx, ~0 ), fc::exception);
{
asset_update_operation op;
@ -145,12 +145,12 @@ BOOST_AUTO_TEST_CASE( transfer_whitelist_uia )
op.new_options.blacklist_authorities.clear();
op.new_options.blacklist_authorities.insert(dan.id);
trx.operations.back() = op;
db.push_transaction(trx, ~0);
PUSH_TX( db, trx, ~0 );
BOOST_CHECK(advanced.options.blacklist_authorities.find(dan.id) != advanced.options.blacklist_authorities.end());
}
trx.operations.back() = op;
db.push_transaction(trx, ~0);
PUSH_TX( db, trx, ~0 );
BOOST_CHECK_EQUAL(get_balance(nathan, advanced), 950);
BOOST_CHECK_EQUAL(get_balance(dan, advanced), 50);
@ -158,29 +158,29 @@ BOOST_AUTO_TEST_CASE( transfer_whitelist_uia )
wop.account_to_list = nathan.id;
wop.new_listing = account_whitelist_operation::black_listed;
trx.operations.back() = wop;
db.push_transaction(trx, ~0);
PUSH_TX( db, trx, ~0 );
trx.operations.back() = op;
//Fail because nathan is blacklisted
BOOST_CHECK(!nathan.is_authorized_asset(advanced));
BOOST_REQUIRE_THROW(db.push_transaction(trx, ~0), fc::exception);
BOOST_REQUIRE_THROW(PUSH_TX( db, trx, ~0 ), fc::exception);
//Remove nathan from genesis' whitelist, add him to dan's. This should not authorize him to hold ADVANCED.
wop.authorizing_account = account_id_type();
wop.account_to_list = nathan.id;
wop.new_listing = account_whitelist_operation::no_listing;
trx.operations.back() = wop;
db.push_transaction(trx, ~0);
PUSH_TX( db, trx, ~0 );
wop.authorizing_account = dan.id;
wop.account_to_list = nathan.id;
wop.new_listing = account_whitelist_operation::white_listed;
trx.operations.back() = wop;
db.push_transaction(trx, ~0);
PUSH_TX( db, trx, ~0 );
trx.operations.back() = op;
//Fail because nathan is not whitelisted
BOOST_CHECK(!nathan.is_authorized_asset(advanced));
BOOST_REQUIRE_THROW(db.push_transaction(trx, ~0), fc::exception);
BOOST_REQUIRE_THROW(PUSH_TX( db, trx, ~0 ), fc::exception);
} catch(fc::exception& e) {
edump((e.to_detail_string()));
throw;