Merge branch 'master' into fee_refactor
This commit is contained in:
commit
786c65d4b4
47 changed files with 1084 additions and 466 deletions
3
.gitignore
vendored
3
.gitignore
vendored
|
|
@ -33,3 +33,6 @@ witness_node_data_dir
|
|||
programs/witness_node/object_database/*
|
||||
|
||||
object_database/*
|
||||
|
||||
*.pyc
|
||||
*.pyo
|
||||
|
|
|
|||
41
README.md
41
README.md
|
|
@ -118,15 +118,38 @@ API 0 is accessible using regular JSON-RPC:
|
|||
|
||||
$ curl --data '{"jsonrpc": "2.0", "method": "get_accounts", "params": [["1.2.0"]], "id": 1}' http://127.0.0.1:8090/rpc
|
||||
|
||||
You can use the login API to obtain `network`, `database` and `history` API's. Here is an example of how to call `add_node` from the `network` API:
|
||||
Accessing restricted API's
|
||||
--------------------------
|
||||
|
||||
You can restrict API's to particular users by specifying an `apiaccess` file in `config.ini`. Here is an example `apiaccess` file which allows
|
||||
user `bytemaster` with password `supersecret` to access four different API's:
|
||||
|
||||
{
|
||||
"permission_map" :
|
||||
[
|
||||
[
|
||||
"bytemaster",
|
||||
{
|
||||
"password_hash_b64" : "9e9GF7ooXVb9k4BoSfNIPTelXeGOZ5DrgOYMj94elaY=",
|
||||
"password_salt_b64" : "INDdM6iCi/8=",
|
||||
"allowed_apis" : ["database_api", "network_broadcast_api", "history_api", "network_node_api"]
|
||||
}
|
||||
]
|
||||
]
|
||||
}
|
||||
|
||||
Passwords are stored in `base64` as as salted `sha256` hashes. A simple Python script, `saltpass.py` is avaliable to obtain hash and salt values from a password.
|
||||
A single asterisk `"*"` may be specified as username or password hash to accept any value.
|
||||
|
||||
With the above configuration, here is an example of how to call `add_node` from the `network_node` API:
|
||||
|
||||
{"id":1, "method":"call", "params":[1,"login",["bytemaster", "supersecret"]]}
|
||||
{"id":2, "method":"call", "params":[1,"network",[]]}
|
||||
{"id":2, "method":"call", "params":[1,"network_node",[]]}
|
||||
{"id":3, "method":"call", "params":[2,"add_node",["127.0.0.1:9090"]]}
|
||||
|
||||
Note, the call to `network` is necessary to obtain the correct API identifier for the network API. It is not guaranteed that the network API identifier will always be `2`.
|
||||
Note, the call to `network_node` is necessary to obtain the correct API identifier for the network API. It is not guaranteed that the network API identifier will always be `2`.
|
||||
|
||||
Since the `network` API requires login, it is only accessible over the websocket RPC. Our `doxygen` documentation contains the most up-to-date information
|
||||
Since the `network_node` API requires login, it is only accessible over the websocket RPC. Our `doxygen` documentation contains the most up-to-date information
|
||||
about API's for the [witness node](https://bitshares.github.io/doxygen/namespacegraphene_1_1app.html) and the
|
||||
[wallet](https://bitshares.github.io/doxygen/classgraphene_1_1wallet_1_1wallet__api.html).
|
||||
If you want information which is not available from an API, it might be available
|
||||
|
|
@ -166,7 +189,15 @@ Questions
|
|||
- Is there a way to generate help with parameter names and method descriptions?
|
||||
|
||||
Yes. Documentation of the code base, including APIs, can be generated using Doxygen. Simply run `doxygen` in this directory.
|
||||
We are thinking of integrating Doxygen's XML output format to provide a better `help` command to the CLI wallet.
|
||||
|
||||
If both Doxygen and perl are available in your build environment, the CLI wallet's `help` and `gethelp`
|
||||
commands will display help generated from the doxygen documentation.
|
||||
|
||||
If your CLI wallet's `help` command displays descriptions without parameter names like
|
||||
`signed_transaction transfer(string, string, string, string, string, bool)`
|
||||
it means CMake was unable to find Doxygen or perl during configuration. If found, the
|
||||
output should look like this:
|
||||
`signed_transaction transfer(string from, string to, string amount, string asset_symbol, string memo, bool broadcast)`
|
||||
|
||||
- Is there a way to allow external program to drive `cli_wallet` via websocket, JSONRPC, or HTTP?
|
||||
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@
|
|||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#include <graphene/app/api.hpp>
|
||||
#include <graphene/app/api_access.hpp>
|
||||
#include <graphene/app/application.hpp>
|
||||
#include <graphene/chain/database.hpp>
|
||||
#include <graphene/utilities/key_conversion.hpp>
|
||||
|
|
@ -350,21 +351,53 @@ namespace graphene { namespace app {
|
|||
|
||||
bool login_api::login(const string& user, const string& password)
|
||||
{
|
||||
auto db_api = std::make_shared<database_api>(std::ref(*_app.chain_database()));
|
||||
auto net_api = std::make_shared<network_api>(std::ref(_app));
|
||||
auto hist_api = std::make_shared<history_api>(_app);
|
||||
_database_api = db_api;
|
||||
_network_api = net_api;
|
||||
_history_api = hist_api;
|
||||
optional< api_access_info > acc = _app.get_api_access_info( user );
|
||||
if( !acc.valid() )
|
||||
return false;
|
||||
if( acc->password_hash_b64 != "*" )
|
||||
{
|
||||
std::string password_salt = fc::base64_decode( acc->password_salt_b64 );
|
||||
std::string acc_password_hash = fc::base64_decode( acc->password_hash_b64 );
|
||||
|
||||
fc::sha256 hash_obj = fc::sha256::hash( password + password_salt );
|
||||
if( hash_obj.data_size() != acc_password_hash.length() )
|
||||
return false;
|
||||
if( memcmp( hash_obj.data(), acc_password_hash.c_str(), hash_obj.data_size() ) != 0 )
|
||||
return false;
|
||||
}
|
||||
|
||||
for( const std::string& api_name : acc->allowed_apis )
|
||||
enable_api( api_name );
|
||||
return true;
|
||||
}
|
||||
|
||||
network_api::network_api(application& a):_app(a)
|
||||
void login_api::enable_api( const std::string& api_name )
|
||||
{
|
||||
if( api_name == "database_api" )
|
||||
{
|
||||
_database_api = std::make_shared< database_api >( std::ref( *_app.chain_database() ) );
|
||||
}
|
||||
else if( api_name == "network_broadcast_api" )
|
||||
{
|
||||
_network_broadcast_api = std::make_shared< network_broadcast_api >( std::ref( _app ) );
|
||||
}
|
||||
else if( api_name == "history_api" )
|
||||
{
|
||||
_history_api = std::make_shared< history_api >( _app );
|
||||
}
|
||||
else if( api_name == "network_node_api" )
|
||||
{
|
||||
_network_node_api = std::make_shared< network_node_api >( std::ref(_app) );
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
network_broadcast_api::network_broadcast_api(application& a):_app(a)
|
||||
{
|
||||
_applied_block_connection = _app.chain_database()->applied_block.connect([this](const signed_block& b){ on_applied_block(b); });
|
||||
}
|
||||
|
||||
void network_api::on_applied_block( const signed_block& b )
|
||||
void network_broadcast_api::on_applied_block( const signed_block& b )
|
||||
{
|
||||
if( _callbacks.size() )
|
||||
{
|
||||
|
|
@ -382,18 +415,14 @@ namespace graphene { namespace app {
|
|||
}
|
||||
}
|
||||
|
||||
void network_api::add_node(const fc::ip::endpoint& ep)
|
||||
{
|
||||
_app.p2p_node()->add_node(ep);
|
||||
}
|
||||
|
||||
void network_api::broadcast_transaction(const signed_transaction& trx)
|
||||
void network_broadcast_api::broadcast_transaction(const signed_transaction& trx)
|
||||
{
|
||||
trx.validate();
|
||||
_app.chain_database()->push_transaction(trx);
|
||||
_app.p2p_node()->broadcast_transaction(trx);
|
||||
}
|
||||
void network_api::broadcast_transaction_with_callback( confirmation_callback cb, const signed_transaction& trx)
|
||||
|
||||
void network_broadcast_api::broadcast_transaction_with_callback( confirmation_callback cb, const signed_transaction& trx)
|
||||
{
|
||||
trx.validate();
|
||||
_callbacks[trx.id()] = cb;
|
||||
|
|
@ -401,16 +430,30 @@ namespace graphene { namespace app {
|
|||
_app.p2p_node()->broadcast_transaction(trx);
|
||||
}
|
||||
|
||||
network_node_api::network_node_api( application& a ) : _app( a )
|
||||
{
|
||||
}
|
||||
|
||||
std::vector<net::peer_status> network_api::get_connected_peers() const
|
||||
void network_node_api::add_node(const fc::ip::endpoint& ep)
|
||||
{
|
||||
_app.p2p_node()->add_node(ep);
|
||||
}
|
||||
|
||||
std::vector<net::peer_status> network_node_api::get_connected_peers() const
|
||||
{
|
||||
return _app.p2p_node()->get_connected_peers();
|
||||
}
|
||||
|
||||
fc::api<network_api> login_api::network()const
|
||||
fc::api<network_broadcast_api> login_api::network_broadcast()const
|
||||
{
|
||||
FC_ASSERT(_network_api);
|
||||
return *_network_api;
|
||||
FC_ASSERT(_network_broadcast_api);
|
||||
return *_network_broadcast_api;
|
||||
}
|
||||
|
||||
fc::api<network_node_api> login_api::network_node()const
|
||||
{
|
||||
FC_ASSERT(_network_node_api);
|
||||
return *_network_node_api;
|
||||
}
|
||||
|
||||
fc::api<database_api> login_api::database()const
|
||||
|
|
|
|||
|
|
@ -15,9 +15,10 @@
|
|||
* 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/app/api.hpp>
|
||||
#include <graphene/app/api_access.hpp>
|
||||
#include <graphene/app/application.hpp>
|
||||
#include <graphene/app/plugin.hpp>
|
||||
#include <graphene/app/api.hpp>
|
||||
|
||||
#include <graphene/net/core_messages.hpp>
|
||||
|
||||
|
|
@ -62,6 +63,9 @@ namespace detail {
|
|||
genesis_state_type initial_state;
|
||||
initial_state.initial_parameters.current_fees = fee_schedule::get_default();//->set_all_fees(GRAPHENE_BLOCKCHAIN_PRECISION);
|
||||
initial_state.initial_active_witnesses = 10;
|
||||
initial_state.initial_timestamp = time_point_sec(time_point::now().sec_since_epoch() /
|
||||
initial_state.initial_parameters.block_interval *
|
||||
initial_state.initial_parameters.block_interval);
|
||||
for( int i = 0; i < initial_state.initial_active_witnesses; ++i )
|
||||
{
|
||||
auto name = "init"+fc::to_string(i);
|
||||
|
|
@ -181,12 +185,14 @@ namespace detail {
|
|||
bool clean = !fc::exists(_data_dir / "blockchain/dblock");
|
||||
fc::create_directories(_data_dir / "blockchain/dblock");
|
||||
|
||||
genesis_state_type initial_state;
|
||||
if( _options->count("genesis-json") )
|
||||
initial_state = fc::json::from_file(_options->at("genesis-json").as<boost::filesystem::path>())
|
||||
.as<genesis_state_type>();
|
||||
else
|
||||
initial_state = create_example_genesis();
|
||||
auto initial_state = [&] {
|
||||
ilog("Initializing database...");
|
||||
if( _options->count("genesis-json") )
|
||||
return fc::json::from_file(_options->at("genesis-json").as<boost::filesystem::path>())
|
||||
.as<genesis_state_type>();
|
||||
else
|
||||
return create_example_genesis();
|
||||
};
|
||||
|
||||
if( _options->count("resync-blockchain") )
|
||||
_chain_db->wipe(_data_dir / "blockchain", true);
|
||||
|
|
@ -194,12 +200,29 @@ namespace detail {
|
|||
if( _options->count("replay-blockchain") )
|
||||
{
|
||||
ilog("Replaying blockchain on user request.");
|
||||
_chain_db->reindex(_data_dir/"blockchain", initial_state);
|
||||
_chain_db->reindex(_data_dir/"blockchain", initial_state());
|
||||
} else if( clean )
|
||||
_chain_db->open(_data_dir / "blockchain", initial_state);
|
||||
else {
|
||||
wlog("Detected unclean shutdown. Replaying blockchain...");
|
||||
_chain_db->reindex(_data_dir / "blockchain", initial_state);
|
||||
_chain_db->reindex(_data_dir / "blockchain", initial_state());
|
||||
}
|
||||
|
||||
if( _options->count("apiaccess") )
|
||||
_apiaccess = fc::json::from_file( _options->at("apiaccess").as<boost::filesystem::path>() )
|
||||
.as<api_access>();
|
||||
else
|
||||
{
|
||||
// TODO: Remove this generous default access policy
|
||||
// when the UI logs in properly
|
||||
_apiaccess = api_access();
|
||||
api_access_info wild_access;
|
||||
wild_access.password_hash_b64 = "*";
|
||||
wild_access.password_salt_b64 = "*";
|
||||
wild_access.allowed_apis.push_back( "database_api" );
|
||||
wild_access.allowed_apis.push_back( "network_broadcast_api" );
|
||||
wild_access.allowed_apis.push_back( "history_api" );
|
||||
_apiaccess.permission_map["*"] = wild_access;
|
||||
}
|
||||
|
||||
reset_p2p_node(_data_dir);
|
||||
|
|
@ -207,10 +230,23 @@ namespace detail {
|
|||
reset_websocket_tls_server();
|
||||
} FC_CAPTURE_AND_RETHROW() }
|
||||
|
||||
optional< api_access_info > get_api_access_info(const string& username)const
|
||||
{
|
||||
optional< api_access_info > result;
|
||||
auto it = _apiaccess.permission_map.find(username);
|
||||
if( it == _apiaccess.permission_map.end() )
|
||||
{
|
||||
it = _apiaccess.permission_map.find("*");
|
||||
if( it == _apiaccess.permission_map.end() )
|
||||
return result;
|
||||
}
|
||||
return it->second;
|
||||
}
|
||||
|
||||
/**
|
||||
* If delegate has the item, the network has no need to fetch it.
|
||||
*/
|
||||
virtual bool has_item( const net::item_id& id ) override
|
||||
virtual bool has_item(const net::item_id& id) override
|
||||
{
|
||||
try
|
||||
{
|
||||
|
|
@ -230,7 +266,7 @@ namespace detail {
|
|||
*
|
||||
* @throws exception if error validating the item, otherwise the item is safe to broadcast on.
|
||||
*/
|
||||
virtual bool handle_block( const graphene::net::block_message& blk_msg, bool sync_mode ) override
|
||||
virtual bool handle_block(const graphene::net::block_message& blk_msg, bool sync_mode) override
|
||||
{ try {
|
||||
ilog("Got block #${n} from network", ("n", blk_msg.block.block_num()));
|
||||
try {
|
||||
|
|
@ -241,7 +277,7 @@ namespace detail {
|
|||
}
|
||||
} FC_CAPTURE_AND_RETHROW( (blk_msg)(sync_mode) ) }
|
||||
|
||||
virtual bool handle_transaction( const graphene::net::trx_message& trx_msg, bool sync_mode ) override
|
||||
virtual bool handle_transaction(const graphene::net::trx_message& trx_msg, bool sync_mode) override
|
||||
{ try {
|
||||
ilog("Got transaction from network");
|
||||
_chain_db->push_transaction( trx_msg.trx );
|
||||
|
|
@ -296,18 +332,18 @@ namespace detail {
|
|||
/**
|
||||
* Given the hash of the requested data, fetch the body.
|
||||
*/
|
||||
virtual message get_item( const item_id& id ) override
|
||||
virtual message get_item(const item_id& id) override
|
||||
{ try {
|
||||
ilog("Request for item ${id}", ("id", id));
|
||||
if( id.item_type == graphene::net::block_message_type )
|
||||
{
|
||||
auto opt_block = _chain_db->fetch_block_by_id( id.item_hash );
|
||||
auto opt_block = _chain_db->fetch_block_by_id(id.item_hash);
|
||||
if( !opt_block )
|
||||
elog("Couldn't find block ${id} -- corresponding ID in our chain is ${id2}",
|
||||
("id", id.item_hash)("id2", _chain_db->get_block_id_for_num(block_header::num_from_id(id.item_hash))));
|
||||
FC_ASSERT( opt_block.valid() );
|
||||
ilog("Serving up block #${num}", ("num", opt_block->block_num()));
|
||||
return block_message( std::move(*opt_block) );
|
||||
return block_message(std::move(*opt_block));
|
||||
}
|
||||
return trx_message( _chain_db->get_recent_transaction( id.item_hash ) );
|
||||
} FC_CAPTURE_AND_RETHROW( (id) ) }
|
||||
|
|
@ -332,18 +368,18 @@ namespace detail {
|
|||
* &c.
|
||||
* the last item in the list will be the hash of the most recent block on our preferred chain
|
||||
*/
|
||||
virtual std::vector<item_hash_t> get_blockchain_synopsis( uint32_t item_type,
|
||||
const graphene::net::item_hash_t& reference_point,
|
||||
uint32_t number_of_blocks_after_reference_point ) override
|
||||
virtual std::vector<item_hash_t> get_blockchain_synopsis(uint32_t item_type,
|
||||
const graphene::net::item_hash_t& reference_point,
|
||||
uint32_t number_of_blocks_after_reference_point) override
|
||||
{ try {
|
||||
std::vector<item_hash_t> result;
|
||||
result.reserve(30);
|
||||
auto head_block_num = _chain_db->head_block_num();
|
||||
result.push_back( _chain_db->head_block_id() );
|
||||
result.push_back(_chain_db->head_block_id());
|
||||
auto current = 1;
|
||||
while( current < head_block_num )
|
||||
{
|
||||
result.push_back( _chain_db->get_block_id_for_num( head_block_num - current ) );
|
||||
result.push_back(_chain_db->get_block_id_for_num(head_block_num - current));
|
||||
current = current*2;
|
||||
}
|
||||
std::reverse( result.begin(), result.end() );
|
||||
|
|
@ -358,7 +394,7 @@ namespace detail {
|
|||
* @param item_count the number of items known to the node that haven't been sent to handle_item() yet.
|
||||
* After `item_count` more calls to handle_item(), the node will be in sync
|
||||
*/
|
||||
virtual void sync_status( uint32_t item_type, uint32_t item_count ) override
|
||||
virtual void sync_status(uint32_t item_type, uint32_t item_count) override
|
||||
{
|
||||
// any status reports to GUI go here
|
||||
}
|
||||
|
|
@ -366,7 +402,7 @@ namespace detail {
|
|||
/**
|
||||
* Call any time the number of connected peers changes.
|
||||
*/
|
||||
virtual void connection_count_changed( uint32_t c ) override
|
||||
virtual void connection_count_changed(uint32_t c) override
|
||||
{
|
||||
// any status reports to GUI go here
|
||||
}
|
||||
|
|
@ -412,6 +448,7 @@ namespace detail {
|
|||
|
||||
fc::path _data_dir;
|
||||
const bpo::variables_map* _options = nullptr;
|
||||
api_access _apiaccess;
|
||||
|
||||
std::shared_ptr<graphene::chain::database> _chain_db;
|
||||
std::shared_ptr<graphene::net::node> _p2p_network;
|
||||
|
|
@ -451,6 +488,7 @@ void application::set_program_options(boost::program_options::options_descriptio
|
|||
("server-pem,p", bpo::value<string>()->implicit_value("server.pem"), "The TLS certificate file for this server")
|
||||
("server-pem-password,P", bpo::value<string>()->implicit_value(""), "Password for this certificate")
|
||||
("genesis-json", bpo::value<boost::filesystem::path>(), "File to read Genesis State from")
|
||||
("apiaccess", bpo::value<boost::filesystem::path>(), "JSON file specifying API permissions")
|
||||
;
|
||||
command_line_options.add(configuration_file_options);
|
||||
command_line_options.add_options()
|
||||
|
|
@ -521,6 +559,11 @@ void application::set_block_production(bool producing_blocks)
|
|||
my->_is_block_producer = producing_blocks;
|
||||
}
|
||||
|
||||
optional< api_access_info > application::get_api_access_info( const string& username )const
|
||||
{
|
||||
return my->get_api_access_info( username );
|
||||
}
|
||||
|
||||
void graphene::app::application::add_plugin(const string& name, std::shared_ptr<graphene::app::abstract_plugin> p)
|
||||
{
|
||||
my->_plugins[name] = p;
|
||||
|
|
|
|||
|
|
@ -28,7 +28,6 @@
|
|||
#include <graphene/chain/balance_object.hpp>
|
||||
#include <graphene/net/node.hpp>
|
||||
|
||||
|
||||
#include <graphene/market_history/market_history_plugin.hpp>
|
||||
|
||||
#include <fc/api.hpp>
|
||||
|
|
@ -44,7 +43,7 @@ namespace graphene { namespace app {
|
|||
*
|
||||
* This API exposes accessors on the database which query state tracked by a blockchain validating node. This API is
|
||||
* read-only; all modifications to the database must be performed via transactions. Transactions are broadcast via
|
||||
* the @ref network_api.
|
||||
* the @ref network_broadcast_api.
|
||||
*/
|
||||
class database_api
|
||||
{
|
||||
|
|
@ -331,14 +330,12 @@ namespace graphene { namespace app {
|
|||
};
|
||||
|
||||
/**
|
||||
* @brief The network_api class implements the RPC API for the network
|
||||
*
|
||||
* This API has methods to query the network status, connect to new peers, and send transactions.
|
||||
* @brief The network_broadcast_api class allows broadcasting of transactions.
|
||||
*/
|
||||
class network_api
|
||||
class network_broadcast_api
|
||||
{
|
||||
public:
|
||||
network_api(application& a);
|
||||
network_broadcast_api(application& a);
|
||||
|
||||
struct transaction_confirmation
|
||||
{
|
||||
|
|
@ -366,15 +363,13 @@ namespace graphene { namespace app {
|
|||
void broadcast_transaction_with_callback( confirmation_callback cb, const signed_transaction& trx);
|
||||
|
||||
/**
|
||||
* @brief add_node Connect to a new peer
|
||||
* @param ep The IP/Port of the peer to connect to
|
||||
* @brief Not reflected, thus not accessible to API clients.
|
||||
*
|
||||
* This function is registered to receive the applied_block
|
||||
* signal from the chain database when a block is received.
|
||||
* It then dispatches callbacks to clients who have requested
|
||||
* to be notified when a particular txid is included in a block.
|
||||
*/
|
||||
void add_node(const fc::ip::endpoint& ep);
|
||||
/**
|
||||
* @brief Get status of all current connections to peers
|
||||
*/
|
||||
std::vector<net::peer_status> get_connected_peers() const;
|
||||
|
||||
void on_applied_block( const signed_block& b );
|
||||
private:
|
||||
boost::signals2::scoped_connection _applied_block_connection;
|
||||
|
|
@ -382,6 +377,35 @@ namespace graphene { namespace app {
|
|||
application& _app;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief The network_node_api class allows maintenance of p2p connections.
|
||||
*/
|
||||
class network_node_api
|
||||
{
|
||||
public:
|
||||
network_node_api(application& a);
|
||||
|
||||
/**
|
||||
* @brief add_node Connect to a new peer
|
||||
* @param ep The IP/Port of the peer to connect to
|
||||
*/
|
||||
void add_node(const fc::ip::endpoint& ep);
|
||||
|
||||
/**
|
||||
* @brief Get status of all current connections to peers
|
||||
* @brief Not reflected, thus not accessible to API clients.
|
||||
*
|
||||
* This function is registered to receive the applied_block
|
||||
* signal from the chain database when a block is received.
|
||||
* It then dispatches callbacks to clients who have requested
|
||||
* to be notified when a particular txid is included in a block.
|
||||
*/
|
||||
std::vector<net::peer_status> get_connected_peers() const;
|
||||
|
||||
private:
|
||||
application& _app;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief The login_api class implements the bottom layer of the RPC API
|
||||
*
|
||||
|
|
@ -403,23 +427,29 @@ namespace graphene { namespace app {
|
|||
* has sucessfully authenticated.
|
||||
*/
|
||||
bool login(const string& user, const string& password);
|
||||
/// @brief Retrieve the network API
|
||||
fc::api<network_api> network()const;
|
||||
/// @brief Retrieve the network broadcast API
|
||||
fc::api<network_broadcast_api> network_broadcast()const;
|
||||
/// @brief Retrieve the database API
|
||||
fc::api<database_api> database()const;
|
||||
/// @brief Retrieve the history API
|
||||
fc::api<history_api> history()const;
|
||||
/// @brief Retrieve the network node API
|
||||
fc::api<network_node_api> network_node()const;
|
||||
|
||||
private:
|
||||
/// @brief Called to enable an API, not reflected.
|
||||
void enable_api( const string& api_name );
|
||||
|
||||
application& _app;
|
||||
optional< fc::api<database_api> > _database_api;
|
||||
optional< fc::api<network_api> > _network_api;
|
||||
optional< fc::api<network_broadcast_api> > _network_broadcast_api;
|
||||
optional< fc::api<network_node_api> > _network_node_api;
|
||||
optional< fc::api<history_api> > _history_api;
|
||||
};
|
||||
|
||||
}} // graphene::app
|
||||
|
||||
FC_REFLECT( graphene::app::network_api::transaction_confirmation,
|
||||
FC_REFLECT( graphene::app::network_broadcast_api::transaction_confirmation,
|
||||
(id)(block_num)(trx_num)(trx) )
|
||||
|
||||
FC_API(graphene::app::database_api,
|
||||
|
|
@ -460,13 +490,23 @@ FC_API(graphene::app::database_api,
|
|||
(get_margin_positions)
|
||||
(get_balance_objects)
|
||||
)
|
||||
FC_API(graphene::app::history_api, (get_account_history)(get_market_history)(get_market_history_buckets))
|
||||
FC_API(graphene::app::network_api, (broadcast_transaction)(broadcast_transaction_with_callback)
|
||||
/* (add_node)(get_connected_peers) */
|
||||
)
|
||||
FC_API(graphene::app::history_api,
|
||||
(get_account_history)
|
||||
(get_market_history)
|
||||
(get_market_history_buckets)
|
||||
)
|
||||
FC_API(graphene::app::network_broadcast_api,
|
||||
(broadcast_transaction)
|
||||
(broadcast_transaction_with_callback)
|
||||
)
|
||||
FC_API(graphene::app::network_node_api,
|
||||
(add_node)
|
||||
(get_connected_peers)
|
||||
)
|
||||
FC_API(graphene::app::login_api,
|
||||
(login)
|
||||
(network)
|
||||
(network_broadcast)
|
||||
(database)
|
||||
(history)
|
||||
(network_node)
|
||||
)
|
||||
|
|
|
|||
50
libraries/app/include/graphene/app/api_access.hpp
Normal file
50
libraries/app/include/graphene/app/api_access.hpp
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
/*
|
||||
* Copyright (c) 2015, Cryptonomex, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is provided for evaluation in private test networks only, until September 8, 2015. After this date, this license expires and
|
||||
* the code may not be used, modified or distributed for any purpose. Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted until September 8, 2015, provided that the following conditions are met:
|
||||
*
|
||||
* 1. The code and/or derivative works are used only for private test networks consisting of no more than 10 P2P nodes.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <fc/reflect/reflect.hpp>
|
||||
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace graphene { namespace app {
|
||||
|
||||
struct api_access_info
|
||||
{
|
||||
std::string password_hash_b64;
|
||||
std::string password_salt_b64;
|
||||
std::vector< std::string > allowed_apis;
|
||||
};
|
||||
|
||||
struct api_access
|
||||
{
|
||||
std::map< std::string, api_access_info > permission_map;
|
||||
};
|
||||
|
||||
} } // graphene::app
|
||||
|
||||
FC_REFLECT( graphene::app::api_access_info,
|
||||
(password_hash_b64)
|
||||
(password_salt_b64)
|
||||
(allowed_apis)
|
||||
)
|
||||
|
||||
FC_REFLECT( graphene::app::api_access,
|
||||
(permission_map)
|
||||
)
|
||||
|
|
@ -17,6 +17,7 @@
|
|||
*/
|
||||
#pragma once
|
||||
|
||||
#include <graphene/app/api_access.hpp>
|
||||
#include <graphene/net/node.hpp>
|
||||
#include <graphene/chain/database.hpp>
|
||||
|
||||
|
|
@ -74,6 +75,7 @@ namespace graphene { namespace app {
|
|||
std::shared_ptr<chain::database> chain_database()const;
|
||||
|
||||
void set_block_production(bool producing_blocks);
|
||||
fc::optional< api_access_info > get_api_access_info( const string& username )const;
|
||||
|
||||
private:
|
||||
void add_plugin( const string& name, std::shared_ptr<abstract_plugin> p );
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@
|
|||
#include <graphene/chain/account_object.hpp>
|
||||
#include <graphene/chain/market_evaluator.hpp>
|
||||
#include <graphene/chain/database.hpp>
|
||||
#include <graphene/chain/exceptions.hpp>
|
||||
|
||||
#include <functional>
|
||||
|
||||
|
|
@ -393,6 +394,8 @@ void_result asset_settle_evaluator::do_evaluate(const asset_settle_evaluator::op
|
|||
FC_ASSERT(asset_to_settle->can_force_settle() || bitasset.has_settlement() );
|
||||
if( bitasset.is_prediction_market )
|
||||
FC_ASSERT( bitasset.has_settlement(), "global settlement must occur before force settling a prediction market" );
|
||||
else if( bitasset.current_feed.settlement_price.is_null() )
|
||||
FC_THROW_EXCEPTION(insufficient_feeds, "Cannot force settle with no price feed.");
|
||||
FC_ASSERT(d.get_balance(d.get(op.account), *asset_to_settle) >= op.amount);
|
||||
|
||||
return void_result();
|
||||
|
|
|
|||
|
|
@ -7,27 +7,38 @@ void_result balance_claim_evaluator::do_evaluate(const balance_claim_operation&
|
|||
database& d = db();
|
||||
balance = &op.balance_to_claim(d);
|
||||
|
||||
FC_ASSERT(op.balance_owner_key == balance->owner ||
|
||||
GRAPHENE_ASSERT(
|
||||
op.balance_owner_key == balance->owner ||
|
||||
pts_address(op.balance_owner_key, false, 56) == balance->owner ||
|
||||
pts_address(op.balance_owner_key, true, 56) == balance->owner ||
|
||||
pts_address(op.balance_owner_key, false, 0) == balance->owner ||
|
||||
pts_address(op.balance_owner_key, true, 0) == balance->owner,
|
||||
"balance_owner_key does not match balance's owner");
|
||||
balance_claim_owner_mismatch,
|
||||
"Balance owner key was specified as '${op}' but balance's actual owner is '${bal}'",
|
||||
("op", op.balance_owner_key)
|
||||
("bal", balance->owner)
|
||||
);
|
||||
if( !(d.get_node_properties().skip_flags & (database::skip_authority_check |
|
||||
database::skip_transaction_signatures)) )
|
||||
|
||||
FC_ASSERT(op.total_claimed.asset_id == balance->asset_type());
|
||||
|
||||
if( balance->is_vesting_balance() ) {
|
||||
if( !balance->vesting_policy->is_withdraw_allowed({balance->balance,
|
||||
d.head_block_time(),
|
||||
op.total_claimed}) )
|
||||
FC_THROW_EXCEPTION(invalid_claim_amount,
|
||||
"Attempted to claim ${c} from a vesting balance with ${a} available",
|
||||
("c", op.total_claimed)("a", balance->available(d.head_block_time())));
|
||||
if( d.head_block_time() - balance->last_claim_date < fc::days(1) )
|
||||
FC_THROW_EXCEPTION(balance_claimed_too_often,
|
||||
"Genesis vesting balances may not be claimed more than once per day.");
|
||||
if( balance->is_vesting_balance() )
|
||||
{
|
||||
GRAPHENE_ASSERT(
|
||||
balance->vesting_policy->is_withdraw_allowed(
|
||||
{ balance->balance,
|
||||
d.head_block_time(),
|
||||
op.total_claimed } ),
|
||||
balance_claim_invalid_claim_amount,
|
||||
"Attempted to claim ${c} from a vesting balance with ${a} available",
|
||||
("c", op.total_claimed)("a", balance->available(d.head_block_time()))
|
||||
);
|
||||
GRAPHENE_ASSERT(
|
||||
d.head_block_time() - balance->last_claim_date >= fc::days(1),
|
||||
balance_claim_claimed_too_often,
|
||||
"Genesis vesting balances may not be claimed more than once per day."
|
||||
);
|
||||
return {};
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -193,6 +193,9 @@ void database::initialize_indexes()
|
|||
|
||||
void database::init_genesis(const genesis_state_type& genesis_state)
|
||||
{ try {
|
||||
FC_ASSERT( genesis_state.initial_timestamp != time_point_sec(), "Must initialize genesis timestamp." );
|
||||
FC_ASSERT( genesis_state.initial_timestamp.sec_since_epoch() % GRAPHENE_DEFAULT_BLOCK_INTERVAL == 0,
|
||||
"Genesis timestamp must be divisible by GRAPHENE_DEFAULT_BLOCK_INTERVAL." );
|
||||
FC_ASSERT(genesis_state.initial_witness_candidates.size() > 0,
|
||||
"Cannot start a chain with zero witnesses.");
|
||||
FC_ASSERT(genesis_state.initial_active_witnesses <= genesis_state.initial_witness_candidates.size(),
|
||||
|
|
@ -300,8 +303,8 @@ void database::init_genesis(const genesis_state_type& genesis_state)
|
|||
p.parameters.current_fees->zero_all_fees();
|
||||
|
||||
});
|
||||
create<dynamic_global_property_object>( [&](dynamic_global_property_object& p) {
|
||||
p.time = fc::time_point_sec(GRAPHENE_GENESIS_TIMESTAMP);
|
||||
create<dynamic_global_property_object>([&](dynamic_global_property_object& p) {
|
||||
p.time = genesis_state.initial_timestamp;
|
||||
p.witness_budget = 0;
|
||||
});
|
||||
create<block_summary_object>([&](block_summary_object&) {});
|
||||
|
|
@ -313,13 +316,16 @@ void database::init_genesis(const genesis_state_type& genesis_state)
|
|||
cop.name = account.name;
|
||||
cop.registrar = GRAPHENE_TEMP_ACCOUNT;
|
||||
cop.owner = authority(1, account.owner_key, 1);
|
||||
if( account.owner_key != account.active_key )
|
||||
if( account.active_key == public_key_type() )
|
||||
{
|
||||
cop.active = authority(1, account.owner_key, 1);
|
||||
} else {
|
||||
cop.active = cop.owner;
|
||||
cop.options.memo_key = account.owner_key;
|
||||
}
|
||||
else
|
||||
{
|
||||
cop.active = authority(1, account.active_key, 1);
|
||||
cop.options.memo_key = account.active_key;
|
||||
}
|
||||
cop.options.memo_key = account.owner_key;
|
||||
account_id_type account_id(apply_operation(genesis_eval_state, cop).get<object_id_type>());
|
||||
|
||||
if( account.is_lifetime_member )
|
||||
|
|
@ -457,31 +463,45 @@ void database::init_genesis(const genesis_state_type& genesis_state)
|
|||
adjust_balance(GRAPHENE_COMMITTEE_ACCOUNT, -get_balance(GRAPHENE_COMMITTEE_ACCOUNT,{}));
|
||||
}
|
||||
|
||||
// Create initial witnesses and delegates
|
||||
// Create initial witnesses
|
||||
std::for_each(genesis_state.initial_witness_candidates.begin(), genesis_state.initial_witness_candidates.end(),
|
||||
[&](const genesis_state_type::initial_witness_type& witness) {
|
||||
witness_create_operation op;
|
||||
op.witness_account = get_account_id(witness.owner_name);
|
||||
op.block_signing_key = witness.block_signing_key;
|
||||
op.initial_secret = secret_hash_type::hash( secret_hash_type() );
|
||||
op.witness_account = get_account_id(witness.owner_name);
|
||||
apply_operation(genesis_eval_state, op);
|
||||
});
|
||||
|
||||
// Create initial committee members
|
||||
std::for_each(genesis_state.initial_committee_candidates.begin(), genesis_state.initial_committee_candidates.end(),
|
||||
[&](const genesis_state_type::initial_committee_member_type& member) {
|
||||
delegate_create_operation op;
|
||||
op.delegate_account = get_account_id(member.owner_name);
|
||||
apply_operation(genesis_eval_state, op).get<object_id_type>();
|
||||
apply_operation(genesis_eval_state, op);
|
||||
});
|
||||
|
||||
// Create initial workers
|
||||
std::for_each(genesis_state.initial_worker_candidates.begin(), genesis_state.initial_worker_candidates.end(),
|
||||
[&](const genesis_state_type::initial_worker_type& worker)
|
||||
{
|
||||
worker_create_operation op;
|
||||
op.owner = get_account_id(worker.owner_name);
|
||||
op.work_begin_date = genesis_state.initial_timestamp;
|
||||
op.work_end_date = time_point_sec::maximum();
|
||||
op.daily_pay = worker.daily_pay;
|
||||
op.name = "Genesis-Worker-" + worker.owner_name;
|
||||
op.initializer = vesting_balance_worker_initializer{uint16_t(0)};
|
||||
|
||||
apply_operation(genesis_eval_state, std::move(op));
|
||||
});
|
||||
|
||||
// Set active witnesses
|
||||
modify(get_global_properties(), [&](global_property_object& p) {
|
||||
auto idx = get_index_type<witness_index>().indices();
|
||||
for( auto itr = idx.begin();
|
||||
itr != idx.end() && p.active_witnesses.size() < genesis_state.initial_active_witnesses;
|
||||
++itr )
|
||||
for( int i = 0; i < genesis_state.initial_active_witnesses; ++i )
|
||||
{
|
||||
p.active_witnesses.insert(itr->id);
|
||||
p.witness_accounts.insert(itr->witness_account);
|
||||
p.active_witnesses.insert(i);
|
||||
p.witness_accounts.insert(get(witness_id_type(i)).witness_account);
|
||||
}
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -44,7 +44,11 @@ vector<std::reference_wrapper<const typename Index::object_type>> database::sort
|
|||
[](const ObjectType& o) { return std::cref(o); });
|
||||
std::partial_sort(refs.begin(), refs.begin() + count, refs.end(),
|
||||
[this](const ObjectType& a, const ObjectType& b)->bool {
|
||||
return _vote_tally_buffer[a.vote_id] > _vote_tally_buffer[b.vote_id];
|
||||
share_type oa_vote = _vote_tally_buffer[a.vote_id];
|
||||
share_type ob_vote = _vote_tally_buffer[b.vote_id];
|
||||
if( oa_vote != ob_vote )
|
||||
return oa_vote > ob_vote;
|
||||
return a.vote_id < b.vote_id;
|
||||
});
|
||||
|
||||
refs.resize(count, refs.front());
|
||||
|
|
@ -127,9 +131,10 @@ void database::update_active_witnesses()
|
|||
share_type stake_target = _total_voting_stake / 2;
|
||||
share_type stake_tally = _witness_count_histogram_buffer[0];
|
||||
size_t witness_count = 0;
|
||||
while( (witness_count < _witness_count_histogram_buffer.size() - 1)
|
||||
&& (stake_tally <= stake_target) )
|
||||
stake_tally += _witness_count_histogram_buffer[++witness_count];
|
||||
if( stake_target > 0 )
|
||||
while( (witness_count < _witness_count_histogram_buffer.size() - 1)
|
||||
&& (stake_tally <= stake_target) )
|
||||
stake_tally += _witness_count_histogram_buffer[++witness_count];
|
||||
|
||||
auto wits = sort_votable_objects<witness_index>(std::max(witness_count*2+1, (size_t)GRAPHENE_MIN_WITNESS_COUNT));
|
||||
const global_property_object& gpo = get_global_properties();
|
||||
|
|
@ -192,9 +197,10 @@ void database::update_active_delegates()
|
|||
uint64_t stake_target = _total_voting_stake / 2;
|
||||
uint64_t stake_tally = _committee_count_histogram_buffer[0];
|
||||
size_t delegate_count = 0;
|
||||
while( (delegate_count < _committee_count_histogram_buffer.size() - 1)
|
||||
&& (stake_tally <= stake_target) )
|
||||
stake_tally += _committee_count_histogram_buffer[++delegate_count];
|
||||
if( stake_target > 0 )
|
||||
while( (delegate_count < _committee_count_histogram_buffer.size() - 1)
|
||||
&& (stake_tally <= stake_target) )
|
||||
stake_tally += _committee_count_histogram_buffer[++delegate_count];
|
||||
|
||||
auto delegates = sort_votable_objects<delegate_index>(std::max(delegate_count*2+1, (size_t)GRAPHENE_MIN_DELEGATE_COUNT));
|
||||
|
||||
|
|
@ -396,7 +402,7 @@ void database::perform_chain_maintenance(const signed_block& next_block, const g
|
|||
uint32_t offset = id.instance();
|
||||
// if they somehow managed to specify an illegal offset, ignore it.
|
||||
if( offset < d._vote_tally_buffer.size() )
|
||||
d._vote_tally_buffer[ offset ] += voting_stake;
|
||||
d._vote_tally_buffer[offset] += voting_stake;
|
||||
}
|
||||
|
||||
if( opinion_account.options.num_witness <= props.parameters.maximum_witness_count )
|
||||
|
|
@ -409,7 +415,7 @@ void database::perform_chain_maintenance(const signed_block& next_block, const g
|
|||
// in particular, this takes care of the case where a
|
||||
// member was voting for a high number, then the
|
||||
// parameter was lowered.
|
||||
d._witness_count_histogram_buffer[ offset ] += voting_stake;
|
||||
d._witness_count_histogram_buffer[offset] += voting_stake;
|
||||
}
|
||||
if( opinion_account.options.num_committee <= props.parameters.maximum_committee_count )
|
||||
{
|
||||
|
|
@ -419,7 +425,7 @@ void database::perform_chain_maintenance(const signed_block& next_block, const g
|
|||
// are turned into votes for maximum_committee_count.
|
||||
//
|
||||
// same rationale as for witnesses
|
||||
d._committee_count_histogram_buffer[ offset ] += voting_stake;
|
||||
d._committee_count_histogram_buffer[offset] += voting_stake;
|
||||
}
|
||||
|
||||
d._total_voting_stake += voting_stake;
|
||||
|
|
|
|||
|
|
@ -21,6 +21,8 @@
|
|||
#include <graphene/chain/operation_history_object.hpp>
|
||||
#include <graphene/chain/protocol/fee_schedule.hpp>
|
||||
|
||||
#include <functional>
|
||||
|
||||
namespace graphene { namespace chain {
|
||||
|
||||
database::database()
|
||||
|
|
@ -34,31 +36,10 @@ database::~database(){
|
|||
_pending_block_session->commit();
|
||||
}
|
||||
|
||||
void database::open( const fc::path& data_dir, const genesis_state_type& initial_allocation )
|
||||
{ try {
|
||||
object_database::open( data_dir );
|
||||
|
||||
_block_id_to_block.open(data_dir / "database" / "block_num_to_block");
|
||||
|
||||
if( !find(global_property_id_type()) )
|
||||
{
|
||||
// ilog( "Init Genesis State" );
|
||||
init_genesis(initial_allocation);
|
||||
}
|
||||
|
||||
_pending_block.previous = head_block_id();
|
||||
_pending_block.timestamp = head_block_time();
|
||||
|
||||
auto last_block= _block_id_to_block.last();
|
||||
if( last_block.valid() )
|
||||
_fork_db.start_block( *last_block );
|
||||
|
||||
} FC_CAPTURE_AND_RETHROW( (data_dir) ) }
|
||||
|
||||
void database::reindex(fc::path data_dir, const genesis_state_type& initial_allocation)
|
||||
{ try {
|
||||
wipe(data_dir, false);
|
||||
open(data_dir, initial_allocation);
|
||||
open(data_dir, [&initial_allocation]{return initial_allocation;});
|
||||
|
||||
auto start = fc::time_point::now();
|
||||
auto last_block = _block_id_to_block.last();
|
||||
|
|
@ -70,13 +51,13 @@ void database::reindex(fc::path data_dir, const genesis_state_type& initial_allo
|
|||
//_undo_db.disable();
|
||||
for( uint32_t i = 1; i <= last_block_num; ++i )
|
||||
{
|
||||
apply_block( *_block_id_to_block.fetch_by_number(i), skip_delegate_signature |
|
||||
apply_block(*_block_id_to_block.fetch_by_number(i), skip_delegate_signature |
|
||||
skip_transaction_signatures |
|
||||
skip_undo_block |
|
||||
skip_undo_transaction |
|
||||
skip_transaction_dupe_check |
|
||||
skip_tapos_check |
|
||||
skip_authority_check );
|
||||
skip_authority_check);
|
||||
}
|
||||
//_undo_db.enable();
|
||||
auto end = fc::time_point::now();
|
||||
|
|
|
|||
|
|
@ -23,9 +23,6 @@
|
|||
|
||||
namespace graphene { namespace chain {
|
||||
|
||||
static_assert((GRAPHENE_GENESIS_TIMESTAMP % GRAPHENE_DEFAULT_BLOCK_INTERVAL) == 0,
|
||||
"GRAPHENE_GENESIS_TIMESTAMP must be aligned to a block interval.");
|
||||
|
||||
pair<witness_id_type, bool> database::get_scheduled_witness(uint32_t slot_num)const
|
||||
{
|
||||
if( slot_num == 0 )
|
||||
|
|
|
|||
|
|
@ -17,7 +17,9 @@
|
|||
*/
|
||||
#include <graphene/chain/database.hpp>
|
||||
#include <graphene/chain/evaluator.hpp>
|
||||
#include <graphene/chain/exceptions.hpp>
|
||||
#include <graphene/chain/transaction_evaluation_state.hpp>
|
||||
|
||||
#include <graphene/chain/asset_object.hpp>
|
||||
#include <graphene/chain/account_object.hpp>
|
||||
#include <graphene/chain/delegate_object.hpp>
|
||||
|
|
@ -88,14 +90,24 @@ database& generic_evaluator::db()const { return trx_state->db(); }
|
|||
operation_get_required_authorities( op, active_auths, owner_auths, other_auths );
|
||||
|
||||
for( auto id : active_auths )
|
||||
FC_ASSERT(verify_authority(id(db()), authority::active) ||
|
||||
verify_authority(id(db()), authority::owner), "", ("id", id));
|
||||
GRAPHENE_ASSERT(
|
||||
verify_authority(id(db()), authority::active) ||
|
||||
verify_authority(id(db()), authority::owner),
|
||||
tx_missing_active_auth,
|
||||
"missing required active authority ${id}", ("id", id));
|
||||
|
||||
for( auto id : owner_auths )
|
||||
FC_ASSERT(verify_authority(id(db()), authority::owner), "", ("id", id));
|
||||
GRAPHENE_ASSERT(
|
||||
verify_authority(id(db()), authority::owner),
|
||||
tx_missing_owner_auth,
|
||||
"missing required owner authority ${id}", ("id", id));
|
||||
|
||||
for( const auto& auth : other_auths )
|
||||
FC_ASSERT(trx_state->check_authority(auth), "invalid authority", ("auth",auth)("sigs",trx_state->_sigs));
|
||||
GRAPHENE_ASSERT(
|
||||
trx_state->check_authority(auth),
|
||||
tx_missing_other_auth,
|
||||
"missing required authority ${auth}",
|
||||
("auth",auth)("sigs",trx_state->_sigs));
|
||||
|
||||
} FC_CAPTURE_AND_RETHROW( (op) ) }
|
||||
|
||||
|
|
|
|||
|
|
@ -236,7 +236,7 @@ namespace graphene { namespace chain {
|
|||
|
||||
/**
|
||||
* @brief This secondary index will allow a reverse lookup of all accounts that a particular key or account
|
||||
* is an potential signing authority.
|
||||
* is an potential signing authority.
|
||||
*/
|
||||
class account_member_index : public secondary_index
|
||||
{
|
||||
|
|
|
|||
|
|
@ -86,7 +86,7 @@
|
|||
#define GRAPHENE_DEFAULT_MAX_WITNESSES (1001) // SHOULD BE ODD
|
||||
#define GRAPHENE_DEFAULT_MAX_COMMITTEE (1001) // SHOULD BE ODD
|
||||
#define GRAPHENE_DEFAULT_MAX_PROPOSAL_LIFETIME_SEC (60*60*24*7*4) // Four weeks
|
||||
#define GRAPHENE_DEFAULT_GENESIS_PROPOSAL_REVIEW_PERIOD_SEC (60*60*24*7*2) // Two weeks
|
||||
#define GRAPHENE_DEFAULT_COMMITTEE_PROPOSAL_REVIEW_PERIOD_SEC (60*60*24*7*2) // Two weeks
|
||||
#define GRAPHENE_DEFAULT_NETWORK_PERCENT_OF_FEE (20*GRAPHENE_1_PERCENT)
|
||||
#define GRAPHENE_DEFAULT_LIFETIME_REFERRER_PERCENT_OF_FEE (30*GRAPHENE_1_PERCENT)
|
||||
#define GRAPHENE_DEFAULT_MAX_BULK_DISCOUNT_PERCENT (50*GRAPHENE_1_PERCENT)
|
||||
|
|
@ -100,7 +100,6 @@
|
|||
#define GRAPHENE_DEFAULT_FEE_LIQUIDATION_THRESHOLD GRAPHENE_BLOCKCHAIN_PRECISION * 100;
|
||||
#define GRAPHENE_DEFAULT_ACCOUNTS_PER_FEE_SCALE 1000
|
||||
#define GRAPHENE_DEFAULT_ACCOUNT_FEE_SCALE_BITSHIFTS 4
|
||||
#define GRAPHENE_GENESIS_TIMESTAMP (1431700000) /// Should be divisible by GRAPHENE_DEFAULT_BLOCK_INTERVAL
|
||||
|
||||
#define GRAPHENE_MAX_WORKER_NAME_LENGTH 63
|
||||
|
||||
|
|
@ -139,7 +138,7 @@
|
|||
* Reserved Account IDs with special meaning
|
||||
*/
|
||||
///@{
|
||||
/// Represents the current committee members, two-week review period (GRAPHENE_DEFAULT_GENESIS_PROPOSAL_REVIEW_PERIOD_SEC)
|
||||
/// Represents the current committee members, two-week review period
|
||||
#define GRAPHENE_COMMITTEE_ACCOUNT (graphene::chain::account_id_type(0))
|
||||
/// Represents the current witnesses
|
||||
#define GRAPHENE_WITNESS_ACCOUNT (graphene::chain::account_id_type(1))
|
||||
|
|
|
|||
|
|
@ -69,7 +69,7 @@ namespace graphene { namespace chain {
|
|||
* @class database
|
||||
* @brief tracks the blockchain state in an extensible manner
|
||||
*/
|
||||
class database : public object_database
|
||||
class database : public db::object_database
|
||||
{
|
||||
public:
|
||||
//////////////////// db_management.cpp ////////////////////
|
||||
|
|
@ -93,7 +93,19 @@ namespace graphene { namespace chain {
|
|||
skip_assert_evaluation = 0x400 ///< used while reindexing
|
||||
};
|
||||
|
||||
void open(const fc::path& data_dir, const genesis_state_type& initial_allocation = genesis_state_type());
|
||||
/**
|
||||
* @brief Open a database, creating a new one if necessary
|
||||
*
|
||||
* Opens a database in the specified directory. If no initialized database is found, genesis_loader is called
|
||||
* and its return value is used as the genesis state when initializing the new database
|
||||
*
|
||||
* genesis_loader will not be called if an existing database is found.
|
||||
*
|
||||
* @param data_dir Path to open or create database in
|
||||
* @param genesis_loader A callable object which returns the genesis state to initialize new databases on
|
||||
*/
|
||||
template<typename F>
|
||||
void open(const fc::path& data_dir, F&& genesis_loader);
|
||||
/**
|
||||
* @brief Rebuild object graph from block history and open detabase
|
||||
*
|
||||
|
|
@ -477,4 +489,24 @@ namespace graphene { namespace chain {
|
|||
(void)l;
|
||||
}
|
||||
}
|
||||
|
||||
template<typename F>
|
||||
void database::open(const fc::path& data_dir, F&& genesis_loader)
|
||||
{ try {
|
||||
object_database::open(data_dir);
|
||||
|
||||
_block_id_to_block.open(data_dir / "database" / "block_num_to_block");
|
||||
|
||||
if( !find(global_property_id_type()) )
|
||||
init_genesis(genesis_loader());
|
||||
|
||||
_pending_block.previous = head_block_id();
|
||||
_pending_block.timestamp = head_block_time();
|
||||
|
||||
auto last_block= _block_id_to_block.last();
|
||||
if( last_block.valid() )
|
||||
_fork_db.start_block( *last_block );
|
||||
|
||||
} FC_CAPTURE_AND_RETHROW( (data_dir) ) }
|
||||
|
||||
} }
|
||||
|
|
|
|||
|
|
@ -18,12 +18,121 @@
|
|||
#pragma once
|
||||
|
||||
#include <fc/exception/exception.hpp>
|
||||
#include <graphene/chain/protocol/protocol.hpp>
|
||||
|
||||
#define GRAPHENE_ASSERT( expr, exc_type, ... ) \
|
||||
if( !(expr) ) \
|
||||
{ \
|
||||
FC_THROW_EXCEPTION( exc_type, __VA_ARGS__ ); \
|
||||
}
|
||||
|
||||
#define GRAPHENE_DECLARE_OP_BASE_EXCEPTIONS( op_name ) \
|
||||
FC_DECLARE_DERIVED_EXCEPTION( \
|
||||
op_name ## _validate_exception, \
|
||||
graphene::chain::operation_validate_exception, \
|
||||
3040000 + 100 * operation::tag< op_name ## _operation >::value, \
|
||||
#op_name "_operation validation exception" \
|
||||
) \
|
||||
FC_DECLARE_DERIVED_EXCEPTION( \
|
||||
op_name ## _evaluate_exception, \
|
||||
graphene::chain::operation_evaluate_exception, \
|
||||
3050000 + 100 * operation::tag< op_name ## _operation >::value, \
|
||||
#op_name "_operation evaluation exception" \
|
||||
)
|
||||
|
||||
#define GRAPHENE_DECLARE_OP_VALIDATE_EXCEPTION( exc_name, op_name, seqnum, msg ) \
|
||||
FC_DECLARE_DERIVED_EXCEPTION( \
|
||||
op_name ## _ ## exc_name, \
|
||||
graphene::chain::op_name ## _validate_exception, \
|
||||
3040000 + 100 * operation::tag< op_name ## _operation >::value \
|
||||
+ seqnum, \
|
||||
msg \
|
||||
)
|
||||
|
||||
#define GRAPHENE_DECLARE_OP_EVALUATE_EXCEPTION( exc_name, op_name, seqnum, msg ) \
|
||||
FC_DECLARE_DERIVED_EXCEPTION( \
|
||||
op_name ## _ ## exc_name, \
|
||||
graphene::chain::op_name ## _evaluate_exception, \
|
||||
3050000 + 100 * operation::tag< op_name ## _operation >::value \
|
||||
+ seqnum, \
|
||||
msg \
|
||||
)
|
||||
|
||||
namespace graphene { namespace chain {
|
||||
// registered in chain_database.cpp
|
||||
|
||||
FC_DECLARE_EXCEPTION( chain_exception, 30000, "Blockchain Exception" )
|
||||
FC_DECLARE_DERIVED_EXCEPTION( invalid_pts_address, graphene::chain::chain_exception, 30001, "invalid pts address" )
|
||||
FC_DECLARE_EXCEPTION( chain_exception, 3000000, "blockchain exception" )
|
||||
FC_DECLARE_DERIVED_EXCEPTION( database_query_exception, graphene::chain::chain_exception, 3010000, "database query exception" )
|
||||
FC_DECLARE_DERIVED_EXCEPTION( block_validate_exception, graphene::chain::chain_exception, 3020000, "block validation exception" )
|
||||
FC_DECLARE_DERIVED_EXCEPTION( transaction_exception, graphene::chain::chain_exception, 3030000, "transaction validation exception" )
|
||||
FC_DECLARE_DERIVED_EXCEPTION( operation_validate_exception, graphene::chain::chain_exception, 3040000, "operation validation exception" )
|
||||
FC_DECLARE_DERIVED_EXCEPTION( operation_evaluate_exception, graphene::chain::chain_exception, 3050000, "operation evaluation exception" )
|
||||
FC_DECLARE_DERIVED_EXCEPTION( utility_exception, graphene::chain::chain_exception, 3060000, "utility method exception" )
|
||||
|
||||
FC_DECLARE_DERIVED_EXCEPTION( tx_missing_active_auth, graphene::chain::transaction_exception, 3030001, "missing required active authority" )
|
||||
FC_DECLARE_DERIVED_EXCEPTION( tx_missing_owner_auth, graphene::chain::transaction_exception, 3030002, "missing required owner authority" )
|
||||
FC_DECLARE_DERIVED_EXCEPTION( tx_missing_other_auth, graphene::chain::transaction_exception, 3030003, "missing required other authority" )
|
||||
//FC_DECLARE_DERIVED_EXCEPTION( tx_irrelevant_authority, graphene::chain::transaction_exception, 3030004, "irrelevant authority" )
|
||||
|
||||
FC_DECLARE_DERIVED_EXCEPTION( invalid_pts_address, graphene::chain::utility_exception, 3060001, "invalid pts address" )
|
||||
FC_DECLARE_DERIVED_EXCEPTION( insufficient_feeds, graphene::chain::chain_exception, 37006, "insufficient feeds" )
|
||||
|
||||
GRAPHENE_DECLARE_OP_BASE_EXCEPTIONS( transfer );
|
||||
|
||||
GRAPHENE_DECLARE_OP_EVALUATE_EXCEPTION( from_account_not_whitelisted, transfer, 1, "owner mismatch" )
|
||||
GRAPHENE_DECLARE_OP_EVALUATE_EXCEPTION( to_account_not_whitelisted, transfer, 2, "owner mismatch" )
|
||||
|
||||
//GRAPHENE_DECLARE_OP_BASE_EXCEPTIONS( limit_order_create );
|
||||
//GRAPHENE_DECLARE_OP_BASE_EXCEPTIONS( limit_order_cancel );
|
||||
//GRAPHENE_DECLARE_OP_BASE_EXCEPTIONS( call_order_update );
|
||||
//GRAPHENE_DECLARE_OP_BASE_EXCEPTIONS( account_create );
|
||||
//GRAPHENE_DECLARE_OP_BASE_EXCEPTIONS( account_update );
|
||||
//GRAPHENE_DECLARE_OP_BASE_EXCEPTIONS( account_whitelist );
|
||||
//GRAPHENE_DECLARE_OP_BASE_EXCEPTIONS( account_upgrade );
|
||||
//GRAPHENE_DECLARE_OP_BASE_EXCEPTIONS( account_transfer );
|
||||
//GRAPHENE_DECLARE_OP_BASE_EXCEPTIONS( asset_create );
|
||||
//GRAPHENE_DECLARE_OP_BASE_EXCEPTIONS( asset_update );
|
||||
//GRAPHENE_DECLARE_OP_BASE_EXCEPTIONS( asset_update_bitasset );
|
||||
//GRAPHENE_DECLARE_OP_BASE_EXCEPTIONS( asset_update_feed_producers );
|
||||
//GRAPHENE_DECLARE_OP_BASE_EXCEPTIONS( asset_issue );
|
||||
//GRAPHENE_DECLARE_OP_BASE_EXCEPTIONS( asset_reserve );
|
||||
//GRAPHENE_DECLARE_OP_BASE_EXCEPTIONS( asset_fund_fee_pool );
|
||||
//GRAPHENE_DECLARE_OP_BASE_EXCEPTIONS( asset_settle );
|
||||
//GRAPHENE_DECLARE_OP_BASE_EXCEPTIONS( asset_global_settle );
|
||||
//GRAPHENE_DECLARE_OP_BASE_EXCEPTIONS( asset_publish_feed );
|
||||
//GRAPHENE_DECLARE_OP_BASE_EXCEPTIONS( delegate_create );
|
||||
//GRAPHENE_DECLARE_OP_BASE_EXCEPTIONS( witness_create );
|
||||
//GRAPHENE_DECLARE_OP_BASE_EXCEPTIONS( witness_withdraw_pay );
|
||||
|
||||
GRAPHENE_DECLARE_OP_BASE_EXCEPTIONS( proposal_create );
|
||||
|
||||
GRAPHENE_DECLARE_OP_EVALUATE_EXCEPTION( review_period_required, proposal_create, 1, "review_period required" )
|
||||
GRAPHENE_DECLARE_OP_EVALUATE_EXCEPTION( review_period_insufficient, proposal_create, 2, "review_period insufficient" )
|
||||
|
||||
//GRAPHENE_DECLARE_OP_BASE_EXCEPTIONS( proposal_update );
|
||||
//GRAPHENE_DECLARE_OP_BASE_EXCEPTIONS( proposal_delete );
|
||||
//GRAPHENE_DECLARE_OP_BASE_EXCEPTIONS( withdraw_permission_create );
|
||||
//GRAPHENE_DECLARE_OP_BASE_EXCEPTIONS( withdraw_permission_update );
|
||||
//GRAPHENE_DECLARE_OP_BASE_EXCEPTIONS( withdraw_permission_claim );
|
||||
//GRAPHENE_DECLARE_OP_BASE_EXCEPTIONS( withdraw_permission_delete );
|
||||
//GRAPHENE_DECLARE_OP_BASE_EXCEPTIONS( fill_order );
|
||||
//GRAPHENE_DECLARE_OP_BASE_EXCEPTIONS( global_parameters_update );
|
||||
//GRAPHENE_DECLARE_OP_BASE_EXCEPTIONS( vesting_balance_create );
|
||||
//GRAPHENE_DECLARE_OP_BASE_EXCEPTIONS( vesting_balance_withdraw );
|
||||
//GRAPHENE_DECLARE_OP_BASE_EXCEPTIONS( worker_create );
|
||||
//GRAPHENE_DECLARE_OP_BASE_EXCEPTIONS( custom );
|
||||
//GRAPHENE_DECLARE_OP_BASE_EXCEPTIONS( assert );
|
||||
|
||||
GRAPHENE_DECLARE_OP_BASE_EXCEPTIONS( balance_claim );
|
||||
|
||||
GRAPHENE_DECLARE_OP_EVALUATE_EXCEPTION( claimed_too_often, balance_claim, 1, "balance claimed too often" )
|
||||
GRAPHENE_DECLARE_OP_EVALUATE_EXCEPTION( invalid_claim_amount, balance_claim, 2, "invalid claim amount" )
|
||||
GRAPHENE_DECLARE_OP_EVALUATE_EXCEPTION( owner_mismatch, balance_claim, 3, "owner mismatch" )
|
||||
|
||||
GRAPHENE_DECLARE_OP_BASE_EXCEPTIONS( override_transfer );
|
||||
|
||||
GRAPHENE_DECLARE_OP_EVALUATE_EXCEPTION( not_permitted, override_transfer, 1, "not permitted" )
|
||||
|
||||
/*
|
||||
FC_DECLARE_DERIVED_EXCEPTION( addition_overflow, graphene::chain::chain_exception, 30002, "addition overflow" )
|
||||
FC_DECLARE_DERIVED_EXCEPTION( subtraction_overflow, graphene::chain::chain_exception, 30003, "subtraction overflow" )
|
||||
FC_DECLARE_DERIVED_EXCEPTION( asset_type_mismatch, graphene::chain::chain_exception, 30004, "asset/price mismatch" )
|
||||
|
|
@ -63,8 +172,6 @@ namespace graphene { namespace chain {
|
|||
FC_DECLARE_DERIVED_EXCEPTION( expired_transaction, graphene::chain::evaluation_error, 31010, "expired transaction" )
|
||||
FC_DECLARE_DERIVED_EXCEPTION( invalid_transaction_expiration, graphene::chain::evaluation_error, 31011, "invalid transaction expiration" )
|
||||
FC_DECLARE_DERIVED_EXCEPTION( oversized_transaction, graphene::chain::evaluation_error, 31012, "transaction exceeded the maximum transaction size" )
|
||||
FC_DECLARE_DERIVED_EXCEPTION( balance_claimed_too_often, graphene::chain::evaluation_error, 31013, "balance claimed too often" )
|
||||
FC_DECLARE_DERIVED_EXCEPTION( invalid_claim_amount, graphene::chain::evaluation_error, 31013, "invalid claim amount" )
|
||||
|
||||
FC_DECLARE_DERIVED_EXCEPTION( invalid_account_name, graphene::chain::evaluation_error, 32001, "invalid account name" )
|
||||
FC_DECLARE_DERIVED_EXCEPTION( unknown_account_id, graphene::chain::evaluation_error, 32002, "unknown account id" )
|
||||
|
|
@ -111,5 +218,6 @@ namespace graphene { namespace chain {
|
|||
FC_DECLARE_DERIVED_EXCEPTION( price_multiplication_overflow, graphene::chain::evaluation_error, 38001, "price multiplication overflow" )
|
||||
FC_DECLARE_DERIVED_EXCEPTION( price_multiplication_underflow, graphene::chain::evaluation_error, 38002, "price multiplication underflow" )
|
||||
FC_DECLARE_DERIVED_EXCEPTION( price_multiplication_undefined, graphene::chain::evaluation_error, 38003, "price multiplication undefined product 0*inf" )
|
||||
*/
|
||||
|
||||
} } // graphene::chain
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ struct genesis_state_type {
|
|||
string name;
|
||||
public_key_type owner_key;
|
||||
public_key_type active_key;
|
||||
bool is_lifetime_member;
|
||||
bool is_lifetime_member = false;
|
||||
};
|
||||
struct initial_asset_type {
|
||||
string symbol;
|
||||
|
|
@ -79,36 +79,51 @@ struct genesis_state_type {
|
|||
/// Must correspond to one of the initial accounts
|
||||
string owner_name;
|
||||
};
|
||||
struct initial_worker_type {
|
||||
/// Must correspond to one of the initial accounts
|
||||
string owner_name;
|
||||
share_type daily_pay;
|
||||
};
|
||||
|
||||
chain_parameters initial_parameters;
|
||||
vector<initial_account_type> initial_accounts;
|
||||
vector<initial_asset_type> initial_assets;
|
||||
vector<initial_balance_type> initial_balances;
|
||||
vector<initial_vesting_balance_type> initial_vesting_balances;
|
||||
int initial_active_witnesses = GRAPHENE_DEFAULT_NUM_WITNESSES;
|
||||
vector<initial_witness_type> initial_witness_candidates;
|
||||
// These are only candidates; the chain will have no active committee members at genesis
|
||||
vector<initial_committee_member_type> initial_committee_candidates;
|
||||
time_point_sec initial_timestamp;
|
||||
chain_parameters initial_parameters;
|
||||
vector<initial_account_type> initial_accounts;
|
||||
vector<initial_asset_type> initial_assets;
|
||||
vector<initial_balance_type> initial_balances;
|
||||
vector<initial_vesting_balance_type> initial_vesting_balances;
|
||||
int initial_active_witnesses = GRAPHENE_DEFAULT_NUM_WITNESSES;
|
||||
vector<initial_witness_type> initial_witness_candidates;
|
||||
vector<initial_committee_member_type> initial_committee_candidates;
|
||||
vector<initial_worker_type> initial_worker_candidates;
|
||||
};
|
||||
} } // namespace graphene::chain
|
||||
|
||||
FC_REFLECT(graphene::chain::genesis_state_type::initial_account_type, (name)(owner_key)(active_key)(is_lifetime_member))
|
||||
FC_REFLECT(graphene::chain::genesis_state_type::initial_balance_type,
|
||||
(owner)(asset_symbol)(amount))
|
||||
FC_REFLECT(graphene::chain::genesis_state_type::initial_vesting_balance_type,
|
||||
(owner)(asset_symbol)(amount)(begin_timestamp)(vesting_duration_seconds)(begin_balance))
|
||||
FC_REFLECT(graphene::chain::genesis_state_type::initial_witness_type, (owner_name)(block_signing_key))
|
||||
FC_REFLECT(graphene::chain::genesis_state_type::initial_committee_member_type, (owner_name))
|
||||
FC_REFLECT(graphene::chain::genesis_state_type::initial_asset_type::initial_bitasset_options::initial_collateral_position,
|
||||
(collateral)(debt))
|
||||
FC_REFLECT(graphene::chain::genesis_state_type::initial_asset_type::initial_bitasset_options,
|
||||
(feed_lifetime_sec)(minimum_feeds)(force_settlement_delay_sec)(force_settlement_offset_percent)
|
||||
(maximum_force_settlement_volume)(backing_asset_symbol)(maintenance_collateral_ratio)(collateral_records))
|
||||
|
||||
FC_REFLECT(graphene::chain::genesis_state_type::initial_asset_type,
|
||||
(symbol)(description)(precision)(issuer_name)(max_supply)(market_fee_percent)
|
||||
(issuer_permissions)(flags)(bitasset_options)(initial_accumulated_fees))
|
||||
|
||||
FC_REFLECT(graphene::chain::genesis_state_type::initial_asset_type::initial_bitasset_options,
|
||||
(feed_lifetime_sec)(minimum_feeds)(force_settlement_delay_sec)(force_settlement_offset_percent)
|
||||
(maximum_force_settlement_volume)(backing_asset_symbol)(maintenance_collateral_ratio)(collateral_records))
|
||||
|
||||
FC_REFLECT(graphene::chain::genesis_state_type::initial_asset_type::initial_bitasset_options::initial_collateral_position,
|
||||
(collateral)(debt))
|
||||
|
||||
FC_REFLECT(graphene::chain::genesis_state_type::initial_balance_type,
|
||||
(owner)(asset_symbol)(amount))
|
||||
|
||||
FC_REFLECT(graphene::chain::genesis_state_type::initial_vesting_balance_type,
|
||||
(owner)(asset_symbol)(amount)(begin_timestamp)(vesting_duration_seconds)(begin_balance))
|
||||
|
||||
FC_REFLECT(graphene::chain::genesis_state_type::initial_witness_type, (owner_name)(block_signing_key))
|
||||
|
||||
FC_REFLECT(graphene::chain::genesis_state_type::initial_committee_member_type, (owner_name))
|
||||
|
||||
FC_REFLECT(graphene::chain::genesis_state_type::initial_worker_type, (owner_name)(daily_pay))
|
||||
|
||||
FC_REFLECT(graphene::chain::genesis_state_type,
|
||||
(initial_parameters)(initial_accounts)(initial_assets)(initial_balances)
|
||||
(initial_timestamp)(initial_parameters)(initial_accounts)(initial_assets)(initial_balances)
|
||||
(initial_vesting_balances)(initial_active_witnesses)(initial_witness_candidates)
|
||||
(initial_committee_candidates))
|
||||
(initial_committee_candidates)(initial_worker_candidates))
|
||||
|
|
|
|||
|
|
@ -36,7 +36,7 @@ namespace graphene { namespace chain {
|
|||
smart_ref<fee_schedule> current_fees; ///< current schedule of fees
|
||||
uint8_t block_interval = GRAPHENE_DEFAULT_BLOCK_INTERVAL; ///< interval in seconds between blocks
|
||||
uint32_t maintenance_interval = GRAPHENE_DEFAULT_MAINTENANCE_INTERVAL; ///< interval in sections between blockchain maintenance events
|
||||
uint32_t genesis_proposal_review_period = GRAPHENE_DEFAULT_GENESIS_PROPOSAL_REVIEW_PERIOD_SEC; ///< minimum time in seconds that a proposed transaction requiring genesis authority may not be signed, prior to expiration
|
||||
uint32_t committee_proposal_review_period = GRAPHENE_DEFAULT_COMMITTEE_PROPOSAL_REVIEW_PERIOD_SEC; ///< minimum time in seconds that a proposed transaction requiring genesis authority may not be signed, prior to expiration
|
||||
uint32_t maximum_transaction_size = GRAPHENE_DEFAULT_MAX_TRANSACTION_SIZE; ///< maximum allowable size in bytes for a transaction
|
||||
uint32_t maximum_block_size = GRAPHENE_DEFAULT_MAX_BLOCK_SIZE; ///< maximum allowable size in bytes for a block
|
||||
uint32_t maximum_undo_history = GRAPHENE_DEFAULT_MAX_UNDO_HISTORY; ///< maximum number of undo states to keep in RAM
|
||||
|
|
@ -87,7 +87,7 @@ namespace graphene { namespace chain {
|
|||
"Block size limit is too low" );
|
||||
FC_ASSERT( maximum_time_until_expiration > block_interval,
|
||||
"Maximum transaction expiration time must be greater than a block interval" );
|
||||
FC_ASSERT( maximum_proposal_lifetime - genesis_proposal_review_period > block_interval,
|
||||
FC_ASSERT( maximum_proposal_lifetime - committee_proposal_review_period > block_interval,
|
||||
"Genesis proposal review period must be less than the maximum proposal lifetime" );
|
||||
}
|
||||
};
|
||||
|
|
@ -98,7 +98,7 @@ FC_REFLECT( graphene::chain::chain_parameters,
|
|||
(current_fees)
|
||||
(block_interval)
|
||||
(maintenance_interval)
|
||||
(genesis_proposal_review_period)
|
||||
(committee_proposal_review_period)
|
||||
(maximum_transaction_size)
|
||||
(maximum_block_size)
|
||||
(maximum_undo_history)
|
||||
|
|
|
|||
|
|
@ -38,6 +38,7 @@
|
|||
#include <cstdint>
|
||||
#include <graphene/chain/protocol/address.hpp>
|
||||
#include <graphene/db/object_id.hpp>
|
||||
#include <graphene/chain/protocol/config.hpp>
|
||||
|
||||
namespace graphene { namespace chain {
|
||||
using namespace graphene::db;
|
||||
|
|
@ -316,7 +317,6 @@ namespace graphene { namespace chain {
|
|||
return std::to_string(type()) + ":" + std::to_string(instance());
|
||||
}
|
||||
};
|
||||
|
||||
struct public_key_type
|
||||
{
|
||||
struct binary_key
|
||||
|
|
@ -325,9 +325,7 @@ namespace graphene { namespace chain {
|
|||
uint32_t check;
|
||||
fc::ecc::public_key_data data;
|
||||
};
|
||||
|
||||
fc::ecc::public_key_data key_data;
|
||||
|
||||
public_key_type();
|
||||
public_key_type( const fc::ecc::public_key_data& data );
|
||||
public_key_type( const fc::ecc::public_key& pubkey );
|
||||
|
|
@ -338,12 +336,12 @@ namespace graphene { namespace chain {
|
|||
friend bool operator == ( const public_key_type& p1, const fc::ecc::public_key& p2);
|
||||
friend bool operator == ( const public_key_type& p1, const public_key_type& p2);
|
||||
friend bool operator != ( const public_key_type& p1, const public_key_type& p2);
|
||||
|
||||
// TODO: This is temporary for testing
|
||||
bool is_valid_v1( const std::string& base58str );
|
||||
};
|
||||
|
||||
|
||||
|
||||
} } // graphene::chain
|
||||
|
||||
namespace fc
|
||||
|
|
@ -399,7 +397,6 @@ FC_REFLECT_ENUM( graphene::chain::impl_object_type,
|
|||
|
||||
FC_REFLECT_ENUM( graphene::chain::meta_info_object_type, (meta_account_object_type)(meta_asset_object_type) )
|
||||
|
||||
|
||||
FC_REFLECT_TYPENAME( graphene::chain::share_type )
|
||||
|
||||
FC_REFLECT_TYPENAME( graphene::chain::account_id_type )
|
||||
|
|
|
|||
|
|
@ -30,6 +30,7 @@ namespace graphene { namespace chain {
|
|||
|
||||
struct vesting_balance_worker_initializer
|
||||
{
|
||||
vesting_balance_worker_initializer(uint16_t days=0):pay_vesting_period_days(days){}
|
||||
uint16_t pay_vesting_period_days = 0;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@
|
|||
*/
|
||||
#include <graphene/chain/market_evaluator.hpp>
|
||||
#include <graphene/chain/account_object.hpp>
|
||||
#include <graphene/chain/exceptions.hpp>
|
||||
#include <fc/uint128.hpp>
|
||||
|
||||
namespace graphene { namespace chain {
|
||||
|
|
@ -117,8 +118,8 @@ void_result call_order_update_evaluator::do_evaluate(const call_order_update_ope
|
|||
|
||||
if( _bitasset_data->is_prediction_market )
|
||||
FC_ASSERT( o.delta_collateral.amount == o.delta_debt.amount );
|
||||
else
|
||||
FC_ASSERT( !_bitasset_data->current_feed.settlement_price.is_null() );
|
||||
else if( _bitasset_data->current_feed.settlement_price.is_null() )
|
||||
FC_THROW_EXCEPTION(insufficient_feeds, "Cannot borrow asset with no price feed.");
|
||||
|
||||
if( o.delta_debt.amount < 0 )
|
||||
{
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@
|
|||
#include <graphene/chain/proposal_object.hpp>
|
||||
#include <graphene/chain/account_object.hpp>
|
||||
#include <graphene/chain/protocol/fee_schedule.hpp>
|
||||
#include <graphene/chain/exceptions.hpp>
|
||||
|
||||
namespace graphene { namespace chain {
|
||||
|
||||
|
|
@ -45,8 +46,21 @@ void_result proposal_create_evaluator::do_evaluate(const proposal_create_operati
|
|||
FC_ASSERT( other.size() == 0 ); // TODO: what about other???
|
||||
|
||||
if( auths.find(account_id_type()) != auths.end() )
|
||||
FC_ASSERT( o.review_period_seconds
|
||||
&& *o.review_period_seconds >= global_parameters.genesis_proposal_review_period );
|
||||
{
|
||||
GRAPHENE_ASSERT(
|
||||
o.review_period_seconds.valid(),
|
||||
proposal_create_review_period_required,
|
||||
"Review period not given, but at least ${min} required",
|
||||
("min", global_parameters.committee_proposal_review_period)
|
||||
);
|
||||
GRAPHENE_ASSERT(
|
||||
*o.review_period_seconds >= global_parameters.committee_proposal_review_period,
|
||||
proposal_create_review_period_insufficient,
|
||||
"Review period of ${t} required, but at least ${min} required",
|
||||
("t", *o.review_period_seconds)
|
||||
("min", global_parameters.committee_proposal_review_period)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
for( const op_wrapper& op : o.proposed_ops )
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ proposal_create_operation proposal_create_operation::genesis_proposal(const chai
|
|||
{
|
||||
proposal_create_operation op;
|
||||
op.expiration_time = head_block_time + global_params.maximum_proposal_lifetime;
|
||||
op.review_period_seconds = global_params.genesis_proposal_review_period;
|
||||
op.review_period_seconds = global_params.committee_proposal_review_period;
|
||||
return op;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@
|
|||
*/
|
||||
#include <graphene/chain/transfer_evaluator.hpp>
|
||||
#include <graphene/chain/account_object.hpp>
|
||||
#include <graphene/chain/exceptions.hpp>
|
||||
|
||||
namespace graphene { namespace chain {
|
||||
void_result transfer_evaluator::do_evaluate( const transfer_operation& op )
|
||||
|
|
@ -30,8 +31,20 @@ void_result transfer_evaluator::do_evaluate( const transfer_operation& op )
|
|||
|
||||
if( asset_type.options.flags & white_list )
|
||||
{
|
||||
FC_ASSERT( to_account.is_authorized_asset( asset_type ) );
|
||||
FC_ASSERT( from_account.is_authorized_asset( asset_type ) );
|
||||
GRAPHENE_ASSERT(
|
||||
from_account.is_authorized_asset( asset_type ),
|
||||
transfer_from_account_not_whitelisted,
|
||||
"'from' account ${from} is not whitelisted for asset ${asset}",
|
||||
("from",op.from)
|
||||
("asset",op.amount.asset_id)
|
||||
);
|
||||
GRAPHENE_ASSERT(
|
||||
to_account.is_authorized_asset( asset_type ),
|
||||
transfer_to_account_not_whitelisted,
|
||||
"'to' account ${to} is not whitelisted for asset ${asset}",
|
||||
("to",op.to)
|
||||
("asset",op.amount.asset_id)
|
||||
);
|
||||
}
|
||||
|
||||
if( fee_asset_type.options.flags & white_list )
|
||||
|
|
@ -60,7 +73,12 @@ void_result override_transfer_evaluator::do_evaluate( const override_transfer_op
|
|||
database& d = db();
|
||||
|
||||
const asset_object& asset_type = op.amount.asset_id(d);
|
||||
FC_ASSERT( asset_type.can_override() );
|
||||
GRAPHENE_ASSERT(
|
||||
asset_type.can_override(),
|
||||
override_transfer_not_permitted,
|
||||
"override_transfer not permitted for asset ${asset}",
|
||||
("asset", op.amount.asset_id)
|
||||
);
|
||||
FC_ASSERT( asset_type.issuer == op.issuer );
|
||||
|
||||
const account_object& from_account = op.from(d);
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@
|
|||
#include <graphene/chain/withdraw_permission_object.hpp>
|
||||
#include <graphene/chain/account_object.hpp>
|
||||
#include <graphene/chain/database.hpp>
|
||||
#include <graphene/chain/exceptions.hpp>
|
||||
|
||||
namespace graphene { namespace chain {
|
||||
|
||||
|
|
|
|||
|
|
@ -301,7 +301,7 @@ public:
|
|||
: self(s),
|
||||
_remote_api(rapi),
|
||||
_remote_db(rapi->database()),
|
||||
_remote_net(rapi->network()),
|
||||
_remote_net_broadcast(rapi->network_broadcast()),
|
||||
_remote_hist(rapi->history())
|
||||
{
|
||||
_remote_db->subscribe_to_objects( [=]( const fc::variant& obj )
|
||||
|
|
@ -741,7 +741,7 @@ public:
|
|||
}
|
||||
|
||||
if( broadcast )
|
||||
_remote_net->broadcast_transaction( tx );
|
||||
_remote_net_broadcast->broadcast_transaction( tx );
|
||||
return tx;
|
||||
} FC_CAPTURE_AND_RETHROW( (name)(owner)(active)(registrar_account)(referrer_account)(referrer_percent)(broadcast) ) }
|
||||
|
||||
|
|
@ -868,7 +868,7 @@ public:
|
|||
if( save_wallet )
|
||||
save_wallet_file();
|
||||
if( broadcast )
|
||||
_remote_net->broadcast_transaction( tx );
|
||||
_remote_net_broadcast->broadcast_transaction( tx );
|
||||
return tx;
|
||||
} FC_CAPTURE_AND_RETHROW( (account_name)(registrar_account)(referrer_account)(broadcast) ) }
|
||||
|
||||
|
|
@ -1451,7 +1451,7 @@ public:
|
|||
}
|
||||
|
||||
if( broadcast )
|
||||
_remote_net->broadcast_transaction( tx );
|
||||
_remote_net_broadcast->broadcast_transaction( tx );
|
||||
|
||||
return tx;
|
||||
}
|
||||
|
|
@ -1696,7 +1696,7 @@ public:
|
|||
|
||||
fc::api<login_api> _remote_api;
|
||||
fc::api<database_api> _remote_db;
|
||||
fc::api<network_api> _remote_net;
|
||||
fc::api<network_broadcast_api> _remote_net_broadcast;
|
||||
fc::api<history_api> _remote_hist;
|
||||
|
||||
#ifdef __unix__
|
||||
|
|
@ -2441,7 +2441,7 @@ signed_transaction wallet_api::import_balance( string name_or_id, const vector<s
|
|||
boost::erase(tx.signatures, boost::unique<boost::return_found_end>(boost::sort(tx.signatures)));
|
||||
|
||||
if( broadcast )
|
||||
my->_remote_net->broadcast_transaction(tx);
|
||||
my->_remote_net_broadcast->broadcast_transaction(tx);
|
||||
|
||||
return tx;
|
||||
} FC_CAPTURE_AND_RETHROW( (name_or_id) ) }
|
||||
|
|
|
|||
|
|
@ -365,7 +365,7 @@ int main( int argc, char** argv )
|
|||
detail_ns::js_name<static_variant<address,public_key_type>>::name("key_data");
|
||||
detail_ns::js_name<operation_result>::name("operation_result");
|
||||
detail_ns::js_name<header_extension>::name("header_extension");
|
||||
detail_ns::js_name<parameter_extension>::name("parameter_extension");
|
||||
detail_ns::js_name<worker_initializer>::name("worker_initializer");
|
||||
detail_ns::js_name<static_variant<linear_vesting_policy_initializer,cdd_vesting_policy_initializer>>::name("vesting_policy_initializer");
|
||||
detail_ns::serializer<signed_block>::init();
|
||||
detail_ns::serializer<block_header>::init();
|
||||
|
|
|
|||
|
|
@ -119,7 +119,7 @@ int main(int argc, char** argv) {
|
|||
node.startup_plugins();
|
||||
|
||||
fc::promise<int>::ptr exit_promise = new fc::promise<int>("UNIX Signal Handler");
|
||||
#ifdef __unix__
|
||||
#if defined __APPLE__ || defined __unix__
|
||||
fc::set_signal_handler([&exit_promise](int signal) {
|
||||
exit_promise->set_value(signal);
|
||||
}, SIGINT);
|
||||
|
|
|
|||
23
programs/witness_node/saltpass.py
Executable file
23
programs/witness_node/saltpass.py
Executable file
|
|
@ -0,0 +1,23 @@
|
|||
#!/usr/bin/env python3
|
||||
|
||||
import base64
|
||||
import getpass
|
||||
import hashlib
|
||||
import json
|
||||
import os
|
||||
|
||||
pw = getpass.getpass("enter your password: ")
|
||||
pw_bytes = pw.encode("utf-8")
|
||||
salt_bytes = os.urandom(8)
|
||||
salt_b64 = base64.b64encode( salt_bytes )
|
||||
pw_hash = hashlib.sha256( pw_bytes + salt_bytes ).digest()
|
||||
pw_hash_b64 = base64.b64encode( pw_hash )
|
||||
|
||||
print(json.dumps(
|
||||
{
|
||||
"password_hash_b64" : pw_hash_b64.decode("ascii"),
|
||||
"password_salt_b64" : salt_b64.decode("ascii"),
|
||||
},
|
||||
sort_keys=True,
|
||||
indent=3, separators=(',', ' : ')
|
||||
))
|
||||
50
testnet-shared-accounts.txt
Normal file
50
testnet-shared-accounts.txt
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
"name": "dummy0",
|
||||
"owner_key": "BTS6qkMe8pHmQ4zUetLV1bbVKoQJYTNb1fSUbkQzuzpscYhonWpgk",
|
||||
"active_key": "BTS6qkMe8pHmQ4zUetLV1bbVKoQJYTNb1fSUbkQzuzpscYhonWpgk",
|
||||
"is_lifetime_member": true
|
||||
},{
|
||||
"name": "dummy1",
|
||||
"owner_key": "BTS7wXsTzBBR2QEetjrgxcSmN7Kuzey3RAzQWNNHwbPQsKYxkP6fp",
|
||||
"active_key": "BTS7wXsTzBBR2QEetjrgxcSmN7Kuzey3RAzQWNNHwbPQsKYxkP6fp",
|
||||
"is_lifetime_member": true
|
||||
},{
|
||||
"name": "dummy2",
|
||||
"owner_key": "BTS7rzifzfJxS8RWhev9aU8HDYoJi1EGwJRHG9B2fJKxnZAiF2Rsh",
|
||||
"active_key": "BTS7rzifzfJxS8RWhev9aU8HDYoJi1EGwJRHG9B2fJKxnZAiF2Rsh",
|
||||
"is_lifetime_member": true
|
||||
},{
|
||||
"name": "dummy3",
|
||||
"owner_key": "BTS6QZdcwFEFMtHsfW27YBGTv9KLaLTvgx5wgGrPHeUxDTrYEQJ2d",
|
||||
"active_key": "BTS6QZdcwFEFMtHsfW27YBGTv9KLaLTvgx5wgGrPHeUxDTrYEQJ2d",
|
||||
"is_lifetime_member": true
|
||||
},{
|
||||
"name": "dummy4",
|
||||
"owner_key": "BTS7q5MqhSP2a6CRTWaJk77ZcGdpnv14JbT4cVzbXaoAsWJoCxFJG",
|
||||
"active_key": "BTS7q5MqhSP2a6CRTWaJk77ZcGdpnv14JbT4cVzbXaoAsWJoCxFJG",
|
||||
"is_lifetime_member": true
|
||||
},{
|
||||
"name": "dummy5",
|
||||
"owner_key": "BTS5sRXxgDCnteHLUS623xtxJM5WKKVygwDMzEso6LigwxvprJqBA",
|
||||
"active_key": "BTS5sRXxgDCnteHLUS623xtxJM5WKKVygwDMzEso6LigwxvprJqBA",
|
||||
"is_lifetime_member": true
|
||||
},{
|
||||
"name": "dummy6",
|
||||
"owner_key": "BTS5V4HEQJbVbMjUWASeknQ42NT3NP9bZaygt83XMuvy6v4QMJuSP",
|
||||
"active_key": "BTS5V4HEQJbVbMjUWASeknQ42NT3NP9bZaygt83XMuvy6v4QMJuSP",
|
||||
"is_lifetime_member": true
|
||||
},{
|
||||
"name": "dummy7",
|
||||
"owner_key": "BTS86ukuPAufzKouerZf1dCxjVSmxQPA5kLwvnYEjn9GRqi5qXBop",
|
||||
"active_key": "BTS86ukuPAufzKouerZf1dCxjVSmxQPA5kLwvnYEjn9GRqi5qXBop",
|
||||
"is_lifetime_member": true
|
||||
},{
|
||||
"name": "dummy8",
|
||||
"owner_key": "BTS7Sdg3kQuz2pPT8mA8Yr3mkBe7zr6293mnBmoR36z9xxtRdiMmJ",
|
||||
"active_key": "BTS7Sdg3kQuz2pPT8mA8Yr3mkBe7zr6293mnBmoR36z9xxtRdiMmJ",
|
||||
"is_lifetime_member": true
|
||||
},{
|
||||
"name": "dummy9",
|
||||
"owner_key": "BTS5WCj1mMiiqEE4QRs7xhaFfSaiFroejUp3GuZE9wvfue9nxhPPn",
|
||||
"active_key": "BTS5WCj1mMiiqEE4QRs7xhaFfSaiFroejUp3GuZE9wvfue9nxhPPn",
|
||||
"is_lifetime_member": true
|
||||
},{
|
||||
41
testnet-shared-balances.txt
Normal file
41
testnet-shared-balances.txt
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
"initial_balances": [{
|
||||
"owner": "BTSHYhQcrjVg5kBzCoeeD38eQdncCC5pBgee",
|
||||
"asset_symbol": "CORE",
|
||||
"amount": 100000000000
|
||||
},{
|
||||
"owner": "BTSPgQZg5929ht1NBdEvsGKqoQ7buRu3nKf4",
|
||||
"asset_symbol": "CORE",
|
||||
"amount": 100000000000
|
||||
},{
|
||||
"owner": "BTSC9zrLXSAPUQaVmQPk1S9dMqSzT7jPqYU7",
|
||||
"asset_symbol": "CORE",
|
||||
"amount": 100000000000
|
||||
},{
|
||||
"owner": "BTS93aQPtbbkXwaSjtHaREsNVcCvbfHo93aZ",
|
||||
"asset_symbol": "CORE",
|
||||
"amount": 100000000000
|
||||
},{
|
||||
"owner": "BTS6RM4UfsYFPDuhbmgkvDS9ip8Kvqundvyk",
|
||||
"asset_symbol": "CORE",
|
||||
"amount": 100000000000
|
||||
},{
|
||||
"owner": "BTSNVkZXdqWWSzqHVxvfetMe347is6kEkC4K",
|
||||
"asset_symbol": "CORE",
|
||||
"amount": 100000000000
|
||||
},{
|
||||
"owner": "BTS5GHzWZ64Luoajqsz6JGjTKVMgWYkGV9SQ",
|
||||
"asset_symbol": "CORE",
|
||||
"amount": 100000000000
|
||||
},{
|
||||
"owner": "BTSDCVRFez92bW9doRLjnFCKLJnpM58mgmMb",
|
||||
"asset_symbol": "CORE",
|
||||
"amount": 100000000000
|
||||
},{
|
||||
"owner": "BTS5CCdX3JYLBptYMuCjbsezqGYzN9vG9JCu",
|
||||
"asset_symbol": "CORE",
|
||||
"amount": 100000000000
|
||||
},{
|
||||
"owner": "BTSEQ3yQdr3EMDL2eRqGiceMCpoanaW16Puw",
|
||||
"asset_symbol": "CORE",
|
||||
"amount": 100000000000
|
||||
},{
|
||||
10
testnet-shared-private-keys.txt
Normal file
10
testnet-shared-private-keys.txt
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
5KCNDLVGqvX8p3GcMFun9sMe6XbMvycVTm4bGrkB5aZGWCbAAtr
|
||||
5HvFQ1bcAWk8H1A2qXj1AqSNp93GUAb6b2w5TVfLb1jWL6yNF3f
|
||||
5JSxv2kgaBSm9nGseRNhLhgEKTBmoKJ5CkgLbbk5RW4RBCNsLJC
|
||||
5K5E2TQtrodDFzsqPq3oVFi9rVX15AN8sLE3iTHfVsX1b49y49J
|
||||
5HxC3fwN7VDZXKVkbbX3SzCczh18Fetx8TXBfJ3z3ovDUSPKvVd
|
||||
5KSr4w978PDanQDYtftarcfJVvGe4wedYb1sYbdH6HNpi15heRa
|
||||
5Kan4si6qWvDVpZuqug4c6KQH4zkvDhwspaGQiFKYniJv6qji6t
|
||||
5KcZri5DDsMcDp1DjNeMkZSijkWurPoAoR7gBKTnnetNQ9CpXoJ
|
||||
5K5TRZyEhC6GPgi57t5FhiSMRGVTHEbwXngbBEtCA41gM8LPFhF
|
||||
5KXVG4oP4Vj3RawRpta79UFAg7pWp17FGf4DnrKfkr69ELytDMv
|
||||
|
|
@ -40,7 +40,8 @@ BOOST_AUTO_TEST_CASE( two_node_network )
|
|||
fc::temp_directory app2_dir;
|
||||
fc::temp_file genesis_json;
|
||||
|
||||
fc::time_point_sec now( GRAPHENE_GENESIS_TIMESTAMP );
|
||||
// TODO: Time should be read from the blockchain
|
||||
fc::time_point_sec now( 1431700000 );
|
||||
|
||||
graphene::app::application app1;
|
||||
app1.register_plugin<graphene::account_history::account_history_plugin>();
|
||||
|
|
|
|||
|
|
@ -62,7 +62,7 @@ BOOST_AUTO_TEST_CASE( genesis_and_persistence_bench )
|
|||
|
||||
{
|
||||
database db;
|
||||
db.open(data_dir.path(), genesis_state);
|
||||
db.open(data_dir.path(), [&]{return 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_MAX_SHARE_SUPPLY / account_count);
|
||||
|
|
@ -75,7 +75,7 @@ BOOST_AUTO_TEST_CASE( genesis_and_persistence_bench )
|
|||
database db;
|
||||
|
||||
fc::time_point start_time = fc::time_point::now();
|
||||
db.open(data_dir.path());
|
||||
db.open(data_dir.path(), [&]{return genesis_state;});
|
||||
ilog("Opened database in ${t} milliseconds.", ("t", (fc::time_point::now() - start_time).count() / 1000));
|
||||
|
||||
for( int i = 11; i < account_count + 11; ++i)
|
||||
|
|
|
|||
|
|
@ -48,6 +48,16 @@ database_fixture::database_fixture()
|
|||
: app(), db( *app.chain_database() )
|
||||
{
|
||||
try {
|
||||
int argc = boost::unit_test::framework::master_test_suite().argc;
|
||||
char** argv = boost::unit_test::framework::master_test_suite().argv;
|
||||
for( int i=1; i<argc; i++ )
|
||||
{
|
||||
const std::string arg = argv[i];
|
||||
if( arg == "--record-assert-trip" )
|
||||
fc::enable_record_assert_trip = true;
|
||||
if( arg == "--show-test-names" )
|
||||
std::cout << "running test " << boost::unit_test::framework::current_test_case().p_name << std::endl;
|
||||
}
|
||||
auto ahplugin = app.register_plugin<graphene::account_history::account_history_plugin>();
|
||||
auto mhplugin = app.register_plugin<graphene::market_history::market_history_plugin>();
|
||||
delegate_pub_key = delegate_priv_key.get_public_key();
|
||||
|
|
@ -60,6 +70,8 @@ database_fixture::database_fixture()
|
|||
mhplugin->plugin_set_app(&app);
|
||||
mhplugin->plugin_initialize(options);
|
||||
|
||||
genesis_state.initial_timestamp = time_point_sec( GRAPHENE_TESTING_GENESIS_TIMESTAMP );
|
||||
|
||||
genesis_state.initial_active_witnesses = 10;
|
||||
for( int i = 0; i < genesis_state.initial_active_witnesses; ++i )
|
||||
{
|
||||
|
|
@ -274,7 +286,7 @@ void database_fixture::open_database()
|
|||
{
|
||||
if( !data_dir ) {
|
||||
data_dir = fc::temp_directory();
|
||||
db.open(data_dir->path(), genesis_state);
|
||||
db.open(data_dir->path(), [this]{return genesis_state;});
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -21,8 +21,12 @@
|
|||
#include <graphene/chain/database.hpp>
|
||||
#include <fc/io/json.hpp>
|
||||
|
||||
#include <iostream>
|
||||
|
||||
using namespace graphene::db;
|
||||
|
||||
#define GRAPHENE_TESTING_GENESIS_TIMESTAMP (1431700000)
|
||||
|
||||
#define PUSH_TX \
|
||||
graphene::chain::test::_push_transaction
|
||||
|
||||
|
|
@ -37,13 +41,6 @@ using namespace graphene::db;
|
|||
op.validate(); \
|
||||
op.field = temp; \
|
||||
}
|
||||
#define REQUIRE_OP_VALIDATION_FAILURE( op, field, value ) \
|
||||
{ \
|
||||
const auto temp = op.field; \
|
||||
op.field = value; \
|
||||
BOOST_REQUIRE_THROW( op.validate(), fc::exception ); \
|
||||
op.field = temp; \
|
||||
}
|
||||
#define REQUIRE_OP_EVALUATION_SUCCESS( op, field, value ) \
|
||||
{ \
|
||||
const auto temp = op.field; \
|
||||
|
|
@ -52,17 +49,65 @@ using namespace graphene::db;
|
|||
op.field = temp; \
|
||||
db.push_transaction( trx, ~0 ); \
|
||||
}
|
||||
///Shortcut to require an exception when processing a transaction with an operation containing an expected bad value
|
||||
/// Uses require insteach of check, because these transactions are expected to fail. If they don't, subsequent tests
|
||||
/// may spuriously succeed or fail due to unexpected database state.
|
||||
#define REQUIRE_THROW_WITH_VALUE(op, field, value) \
|
||||
|
||||
#define GRAPHENE_REQUIRE_THROW( expr, exc_type ) \
|
||||
{ \
|
||||
std::string req_throw_info = fc::json::to_string( \
|
||||
fc::mutable_variant_object() \
|
||||
("source_file", __FILE__) \
|
||||
("source_lineno", __LINE__) \
|
||||
("expr", #expr) \
|
||||
("exc_type", #exc_type) \
|
||||
); \
|
||||
if( fc::enable_record_assert_trip ) \
|
||||
std::cout << "GRAPHENE_REQUIRE_THROW begin " \
|
||||
<< req_throw_info << std::endl; \
|
||||
BOOST_REQUIRE_THROW( expr, exc_type ); \
|
||||
if( fc::enable_record_assert_trip ) \
|
||||
std::cout << "GRAPHENE_REQUIRE_THROW end " \
|
||||
<< req_throw_info << std::endl; \
|
||||
}
|
||||
|
||||
#define GRAPHENE_CHECK_THROW( expr, exc_type ) \
|
||||
{ \
|
||||
std::string req_throw_info = fc::json::to_string( \
|
||||
fc::mutable_variant_object() \
|
||||
("source_file", __FILE__) \
|
||||
("source_lineno", __LINE__) \
|
||||
("expr", #expr) \
|
||||
("exc_type", #exc_type) \
|
||||
); \
|
||||
if( fc::enable_record_assert_trip ) \
|
||||
std::cout << "GRAPHENE_CHECK_THROW begin " \
|
||||
<< req_throw_info << std::endl; \
|
||||
BOOST_CHECK_THROW( expr, exc_type ); \
|
||||
if( fc::enable_record_assert_trip ) \
|
||||
std::cout << "GRAPHENE_CHECK_THROW end " \
|
||||
<< req_throw_info << std::endl; \
|
||||
}
|
||||
|
||||
#define REQUIRE_OP_VALIDATION_FAILURE_2( op, field, value, exc_type ) \
|
||||
{ \
|
||||
const auto temp = op.field; \
|
||||
op.field = value; \
|
||||
GRAPHENE_REQUIRE_THROW( op.validate(), exc_type ); \
|
||||
op.field = temp; \
|
||||
}
|
||||
#define REQUIRE_OP_VALIDATION_FAILURE( op, field, value ) \
|
||||
REQUIRE_OP_VALIDATION_FAILURE_2( op, field, value, fc::exception )
|
||||
|
||||
#define REQUIRE_THROW_WITH_VALUE_2(op, field, value, exc_type) \
|
||||
{ \
|
||||
auto bak = op.field; \
|
||||
op.field = value; \
|
||||
trx.operations.back() = op; \
|
||||
op.field = bak; \
|
||||
BOOST_REQUIRE_THROW(db.push_transaction(trx, ~0), fc::exception); \
|
||||
GRAPHENE_REQUIRE_THROW(db.push_transaction(trx, ~0), exc_type); \
|
||||
}
|
||||
|
||||
#define REQUIRE_THROW_WITH_VALUE( op, field, value ) \
|
||||
REQUIRE_THROW_WITH_VALUE_2( op, field, value, fc::exception )
|
||||
|
||||
///This simply resets v back to its default-constructed value. Requires v to have a working assingment operator and
|
||||
/// default constructor.
|
||||
#define RESET(v) v = decltype(v)()
|
||||
|
|
@ -71,7 +116,7 @@ using namespace graphene::db;
|
|||
#define INVOKE(test) ((struct test*)this)->test_method(); trx.clear()
|
||||
|
||||
#define PREP_ACTOR(name) \
|
||||
fc::ecc::private_key name ## _private_key = generate_private_key(BOOST_PP_STRINGIZE(name));
|
||||
fc::ecc::private_key name ## _private_key = generate_private_key(BOOST_PP_STRINGIZE(name));
|
||||
|
||||
#define ACTOR(name) \
|
||||
PREP_ACTOR(name) \
|
||||
|
|
@ -102,8 +147,6 @@ struct database_fixture {
|
|||
fc::ecc::private_key delegate_priv_key = fc::ecc::private_key::regenerate(fc::sha256::hash(string("null_key")) );
|
||||
public_key_type delegate_pub_key;
|
||||
|
||||
fc::time_point_sec genesis_time = fc::time_point_sec( GRAPHENE_GENESIS_TIMESTAMP );
|
||||
fc::time_point_sec now = fc::time_point_sec( GRAPHENE_GENESIS_TIMESTAMP );
|
||||
optional<fc::temp_directory> data_dir;
|
||||
bool skip_key_index_test = false;
|
||||
uint32_t anon_acct_count;
|
||||
|
|
@ -146,10 +189,20 @@ struct database_fixture {
|
|||
);
|
||||
|
||||
void force_global_settle(const asset_object& what, const price& p);
|
||||
void force_settle(account_id_type who, asset what)
|
||||
{ force_settle(who(db), what); }
|
||||
void force_settle(const account_object& who, asset what);
|
||||
void update_feed_producers(asset_id_type mia, flat_set<account_id_type> producers)
|
||||
{ update_feed_producers(mia(db), producers); }
|
||||
void update_feed_producers(const asset_object& mia, flat_set<account_id_type> producers);
|
||||
void publish_feed(asset_id_type mia, account_id_type by, const price_feed& f)
|
||||
{ publish_feed(mia(db), by(db), f); }
|
||||
void publish_feed(const asset_object& mia, const account_object& by, const price_feed& f);
|
||||
void borrow(account_id_type who, asset what, asset collateral)
|
||||
{ borrow(who(db), what, collateral); }
|
||||
void borrow(const account_object& who, asset what, asset collateral);
|
||||
void cover(account_id_type who, asset what, asset collateral_freed)
|
||||
{ cover(who(db), what, collateral_freed); }
|
||||
void cover(const account_object& who, asset what, asset collateral_freed);
|
||||
|
||||
const asset_object& get_asset( const string& symbol )const;
|
||||
|
|
@ -163,7 +216,7 @@ struct database_fixture {
|
|||
uint16_t market_fee_percent = 100 /*1%*/,
|
||||
uint16_t flags = charge_market_fee);
|
||||
const asset_object& create_user_issued_asset( const string& name );
|
||||
const asset_object& create_user_issued_asset( const string& name,
|
||||
const asset_object& create_user_issued_asset( const string& name,
|
||||
const account_object& issuer,
|
||||
uint16_t flags );
|
||||
void issue_uia( const account_object& recipient, asset amount );
|
||||
|
|
|
|||
|
|
@ -22,10 +22,11 @@
|
|||
#include <boost/test/unit_test.hpp>
|
||||
|
||||
#include <graphene/chain/database.hpp>
|
||||
#include <graphene/chain/operations.hpp>
|
||||
#include <graphene/chain/protocol/protocol.hpp>
|
||||
#include <graphene/chain/account_object.hpp>
|
||||
#include <graphene/chain/proposal_object.hpp>
|
||||
#include <graphene/chain/witness_schedule_object.hpp>
|
||||
#include <graphene/chain/vesting_balance_object.hpp>
|
||||
|
||||
#include <fc/crypto/digest.hpp>
|
||||
|
||||
|
|
@ -71,7 +72,7 @@ BOOST_FIXTURE_TEST_CASE( update_account_keys, database_fixture )
|
|||
generate_block( skip_flags );
|
||||
|
||||
db.modify(db.get_global_properties(), [](global_property_object& p) {
|
||||
p.parameters.genesis_proposal_review_period = fc::hours(1).to_seconds();
|
||||
p.parameters.committee_proposal_review_period = fc::hours(1).to_seconds();
|
||||
});
|
||||
|
||||
transaction tx;
|
||||
|
|
@ -206,7 +207,7 @@ BOOST_FIXTURE_TEST_CASE( update_account_keys, database_fixture )
|
|||
trx.sign( *owner_privkey[i] );
|
||||
if( i < int(create_op.owner.weight_threshold-1) )
|
||||
{
|
||||
BOOST_REQUIRE_THROW(db.push_transaction(trx), fc::exception);
|
||||
GRAPHENE_REQUIRE_THROW(db.push_transaction(trx), fc::exception);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -401,4 +402,91 @@ BOOST_FIXTURE_TEST_CASE( generic_scheduler_mc_test, database_fixture )
|
|||
}
|
||||
}
|
||||
|
||||
BOOST_FIXTURE_TEST_CASE( tapos_rollover, database_fixture )
|
||||
{
|
||||
try
|
||||
{
|
||||
ACTORS((alice)(bob));
|
||||
const auto& core = asset_id_type()(db);
|
||||
|
||||
BOOST_TEST_MESSAGE( "Give Alice some money" );
|
||||
transfer(genesis_account, alice_id, asset(10000));
|
||||
generate_block();
|
||||
|
||||
BOOST_TEST_MESSAGE( "Generate up to block 0xFF00" );
|
||||
generate_blocks( 0xFF00 );
|
||||
signed_transaction xfer_tx;
|
||||
|
||||
BOOST_TEST_MESSAGE( "Transfer money at/about 0xFF00" );
|
||||
transfer_operation xfer_op;
|
||||
xfer_op.from = alice_id;
|
||||
xfer_op.to = bob_id;
|
||||
xfer_op.amount = asset(1000);
|
||||
|
||||
xfer_tx.operations.push_back( xfer_op );
|
||||
xfer_tx.set_expiration( db.head_block_id(), 0x1000 );
|
||||
sign( xfer_tx, alice_private_key );
|
||||
PUSH_TX( db, xfer_tx, 0 );
|
||||
generate_block();
|
||||
|
||||
BOOST_TEST_MESSAGE( "Sign new tx's" );
|
||||
xfer_tx.set_expiration( db.head_block_id(), 0x1000 );
|
||||
xfer_tx.signatures.clear();
|
||||
sign( xfer_tx, alice_private_key );
|
||||
|
||||
BOOST_TEST_MESSAGE( "Generate up to block 0x10010" );
|
||||
generate_blocks( 0x110 );
|
||||
|
||||
BOOST_TEST_MESSAGE( "Transfer at/about block 0x10010 using reference block at/about 0xFF00" );
|
||||
PUSH_TX( db, xfer_tx, 0 );
|
||||
generate_block();
|
||||
}
|
||||
catch (fc::exception& e)
|
||||
{
|
||||
edump((e.to_detail_string()));
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
BOOST_FIXTURE_TEST_CASE(bulk_discount, database_fixture)
|
||||
{ try {
|
||||
ACTOR(nathan);
|
||||
// Give nathan ALLLLLL the money!
|
||||
transfer(GRAPHENE_COMMITTEE_ACCOUNT, nathan_id, db.get_balance(GRAPHENE_COMMITTEE_ACCOUNT, asset_id_type()));
|
||||
enable_fees(GRAPHENE_BLOCKCHAIN_PRECISION*10);
|
||||
upgrade_to_lifetime_member(nathan_id);
|
||||
share_type new_fees;
|
||||
while( nathan_id(db).statistics(db).lifetime_fees_paid + new_fees < GRAPHENE_DEFAULT_BULK_DISCOUNT_THRESHOLD_MIN )
|
||||
{
|
||||
transfer(nathan_id, GRAPHENE_COMMITTEE_ACCOUNT, asset(1));
|
||||
new_fees += transfer_operation().calculate_fee(db.current_fee_schedule());
|
||||
}
|
||||
generate_blocks(db.get_dynamic_global_properties().next_maintenance_time);
|
||||
enable_fees(GRAPHENE_BLOCKCHAIN_PRECISION*10);
|
||||
auto old_cashback = nathan_id(db).cashback_balance(db).balance;
|
||||
|
||||
transfer(nathan_id, GRAPHENE_COMMITTEE_ACCOUNT, asset(1));
|
||||
generate_blocks(db.get_dynamic_global_properties().next_maintenance_time);
|
||||
enable_fees(GRAPHENE_BLOCKCHAIN_PRECISION*10);
|
||||
|
||||
BOOST_CHECK_EQUAL(nathan_id(db).cashback_balance(db).balance.amount.value,
|
||||
old_cashback.amount.value + GRAPHENE_BLOCKCHAIN_PRECISION * 8);
|
||||
|
||||
new_fees = 0;
|
||||
while( nathan_id(db).statistics(db).lifetime_fees_paid + new_fees < GRAPHENE_DEFAULT_BULK_DISCOUNT_THRESHOLD_MAX )
|
||||
{
|
||||
transfer(nathan_id, GRAPHENE_COMMITTEE_ACCOUNT, asset(1));
|
||||
new_fees += transfer_operation().calculate_fee(db.current_fee_schedule());
|
||||
}
|
||||
generate_blocks(db.get_dynamic_global_properties().next_maintenance_time);
|
||||
enable_fees(GRAPHENE_BLOCKCHAIN_PRECISION*10);
|
||||
old_cashback = nathan_id(db).cashback_balance(db).balance;
|
||||
|
||||
transfer(nathan_id, GRAPHENE_COMMITTEE_ACCOUNT, asset(1));
|
||||
generate_blocks(db.get_dynamic_global_properties().next_maintenance_time);
|
||||
|
||||
BOOST_CHECK_EQUAL(nathan_id(db).cashback_balance(db).balance.amount.value,
|
||||
old_cashback.amount.value + GRAPHENE_BLOCKCHAIN_PRECISION * 9);
|
||||
} FC_LOG_AND_RETHROW() }
|
||||
|
||||
BOOST_AUTO_TEST_SUITE_END()
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
#include <boost/test/unit_test.hpp>
|
||||
|
||||
#include <graphene/chain/database.hpp>
|
||||
#include <graphene/chain/operations.hpp>
|
||||
#include <graphene/chain/protocol/protocol.hpp>
|
||||
|
||||
#include <graphene/chain/account_object.hpp>
|
||||
#include <graphene/chain/asset_object.hpp>
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@
|
|||
|
||||
#include <graphene/chain/database.hpp>
|
||||
#include <graphene/chain/protocol/protocol.hpp>
|
||||
#include <graphene/chain/exceptions.hpp>
|
||||
|
||||
#include <graphene/chain/account_object.hpp>
|
||||
#include <graphene/chain/asset_object.hpp>
|
||||
|
|
@ -80,7 +81,7 @@ 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, nathan_key1);
|
||||
BOOST_CHECK_THROW(PUSH_TX( db, trx, database::skip_transaction_dupe_check ), fc::exception);
|
||||
GRAPHENE_CHECK_THROW(PUSH_TX( db, trx, database::skip_transaction_dupe_check ), fc::exception);
|
||||
sign(trx, nathan_key2);
|
||||
PUSH_TX( db, trx, database::skip_transaction_dupe_check );
|
||||
BOOST_CHECK_EQUAL(get_balance(nathan, core), old_balance - 500);
|
||||
|
|
@ -100,7 +101,7 @@ BOOST_AUTO_TEST_CASE( any_two_of_three )
|
|||
trx.signatures.clear();
|
||||
//sign(trx, fc::ecc::private_key::generate());
|
||||
sign(trx,nathan_key3);
|
||||
BOOST_CHECK_THROW(PUSH_TX( db, trx, database::skip_transaction_dupe_check ), fc::exception);
|
||||
GRAPHENE_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()));
|
||||
|
|
@ -135,16 +136,16 @@ BOOST_AUTO_TEST_CASE( recursive_accounts )
|
|||
BOOST_TEST_MESSAGE( "Attempting to transfer with no signatures, should fail" );
|
||||
transfer_operation op = {asset(), child.id, account_id_type(), core.amount(500)};
|
||||
trx.operations.push_back(op);
|
||||
BOOST_CHECK_THROW(PUSH_TX( db, trx, database::skip_transaction_dupe_check ), fc::exception);
|
||||
GRAPHENE_CHECK_THROW(PUSH_TX( db, trx, database::skip_transaction_dupe_check ), fc::exception);
|
||||
|
||||
BOOST_TEST_MESSAGE( "Attempting to transfer with parent1 signature, should fail" );
|
||||
sign(trx,parent1_key);
|
||||
BOOST_CHECK_THROW(PUSH_TX( db, trx, database::skip_transaction_dupe_check ), fc::exception);
|
||||
GRAPHENE_CHECK_THROW(PUSH_TX( db, trx, database::skip_transaction_dupe_check ), fc::exception);
|
||||
trx.signatures.clear();
|
||||
|
||||
BOOST_TEST_MESSAGE( "Attempting to transfer with parent2 signature, should fail" );
|
||||
sign(trx,parent2_key);
|
||||
BOOST_CHECK_THROW(PUSH_TX( db, trx, database::skip_transaction_dupe_check ), fc::exception);
|
||||
GRAPHENE_CHECK_THROW(PUSH_TX( db, trx, database::skip_transaction_dupe_check ), fc::exception);
|
||||
|
||||
BOOST_TEST_MESSAGE( "Attempting to transfer with parent1 and parent2 signature, should succeed" );
|
||||
sign(trx,parent1_key);
|
||||
|
|
@ -172,14 +173,14 @@ BOOST_AUTO_TEST_CASE( recursive_accounts )
|
|||
op = {asset(),child.id, account_id_type(), core.amount(500)};
|
||||
trx.operations.push_back(op);
|
||||
BOOST_TEST_MESSAGE( "Attempting transfer with no signatures, should fail" );
|
||||
BOOST_CHECK_THROW(PUSH_TX( db, trx, database::skip_transaction_dupe_check ), fc::exception);
|
||||
GRAPHENE_CHECK_THROW(PUSH_TX( db, trx, database::skip_transaction_dupe_check ), fc::exception);
|
||||
BOOST_TEST_MESSAGE( "Attempting transfer just parent1, should fail" );
|
||||
sign(trx, parent1_key);
|
||||
BOOST_CHECK_THROW(PUSH_TX( db, trx, database::skip_transaction_dupe_check ), fc::exception);
|
||||
GRAPHENE_CHECK_THROW(PUSH_TX( db, trx, database::skip_transaction_dupe_check ), fc::exception);
|
||||
trx.signatures.clear();
|
||||
BOOST_TEST_MESSAGE( "Attempting transfer just parent2, should fail" );
|
||||
sign(trx, parent2_key);
|
||||
BOOST_CHECK_THROW(PUSH_TX( db, trx, database::skip_transaction_dupe_check ), fc::exception);
|
||||
GRAPHENE_CHECK_THROW(PUSH_TX( db, trx, database::skip_transaction_dupe_check ), fc::exception);
|
||||
|
||||
BOOST_TEST_MESSAGE( "Attempting transfer both parents, should succeed" );
|
||||
sign(trx, parent1_key);
|
||||
|
|
@ -216,7 +217,7 @@ BOOST_AUTO_TEST_CASE( recursive_accounts )
|
|||
trx.operations.push_back(op);
|
||||
sign(trx, parent1_key);
|
||||
sign(trx, parent2_key);
|
||||
BOOST_CHECK_THROW(PUSH_TX( db, trx, database::skip_transaction_dupe_check ), fc::exception);
|
||||
GRAPHENE_CHECK_THROW(PUSH_TX( db, trx, database::skip_transaction_dupe_check ), fc::exception);
|
||||
trx.signatures.clear();
|
||||
trx.sign( parent2_key );
|
||||
trx.sign( grandparent_key );
|
||||
|
|
@ -244,7 +245,7 @@ BOOST_AUTO_TEST_CASE( recursive_accounts )
|
|||
sign(trx, grandparent_key);
|
||||
sign(trx, delegate_priv_key);
|
||||
//Fails due to recursion depth.
|
||||
BOOST_CHECK_THROW(PUSH_TX( db, trx, database::skip_transaction_dupe_check ), fc::exception);
|
||||
GRAPHENE_CHECK_THROW(PUSH_TX( db, trx, database::skip_transaction_dupe_check ), fc::exception);
|
||||
BOOST_TEST_MESSAGE( "verify child key can override recursion checks" );
|
||||
trx.signatures.clear();
|
||||
sign(trx, child_key);
|
||||
|
|
@ -268,7 +269,7 @@ BOOST_AUTO_TEST_CASE( recursive_accounts )
|
|||
trx.operations.push_back(op);
|
||||
sign(trx, parent2_key);
|
||||
//Fails due to recursion depth.
|
||||
BOOST_CHECK_THROW(PUSH_TX( db, trx, database::skip_transaction_dupe_check ), fc::exception);
|
||||
GRAPHENE_CHECK_THROW(PUSH_TX( db, trx, database::skip_transaction_dupe_check ), fc::exception);
|
||||
} catch (fc::exception& e) {
|
||||
edump((e.to_detail_string()));
|
||||
throw;
|
||||
|
|
@ -331,11 +332,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<public_key_type>{},flat_set<public_key_type>{}}};
|
||||
trx.sign( genesis_key );
|
||||
//Genesis may not add nathan's approval.
|
||||
BOOST_CHECK_THROW(PUSH_TX( db, trx ), fc::exception);
|
||||
GRAPHENE_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<public_key_type>{},flat_set<public_key_type>{}}};
|
||||
trx.sign( genesis_key );
|
||||
//Genesis has no stake in the transaction.
|
||||
BOOST_CHECK_THROW(PUSH_TX( db, trx ), fc::exception);
|
||||
GRAPHENE_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<public_key_type>{},flat_set<public_key_type>{}}};
|
||||
|
|
@ -366,31 +367,31 @@ BOOST_AUTO_TEST_CASE( genesis_authority )
|
|||
// Signatures are for suckers.
|
||||
db.modify(db.get_global_properties(), [](global_property_object& p) {
|
||||
// Turn the review period WAY down, so it doesn't take long to produce blocks to that point in simulated time.
|
||||
p.parameters.genesis_proposal_review_period = fc::days(1).to_seconds();
|
||||
p.parameters.committee_proposal_review_period = fc::days(1).to_seconds();
|
||||
});
|
||||
|
||||
BOOST_TEST_MESSAGE( "transfering 100000 CORE to nathan, signing with genesis key" );
|
||||
trx.operations.push_back(transfer_operation({asset(), account_id_type(), nathan.id, asset(100000)}));
|
||||
sign(trx, genesis_key);
|
||||
BOOST_CHECK_THROW(PUSH_TX( db, trx ), fc::exception);
|
||||
GRAPHENE_CHECK_THROW(PUSH_TX( db, trx ), fc::exception);
|
||||
|
||||
auto sign = [&] { trx.signatures.clear(); trx.sign(nathan_key); };
|
||||
|
||||
proposal_create_operation pop;
|
||||
pop.proposed_ops.push_back({trx.operations.front()});
|
||||
pop.expiration_time = db.head_block_time() + global_params.genesis_proposal_review_period*2;
|
||||
pop.expiration_time = db.head_block_time() + global_params.committee_proposal_review_period*2;
|
||||
pop.fee_paying_account = nathan.id;
|
||||
trx.operations = {pop};
|
||||
sign();
|
||||
|
||||
// The review period isn't set yet. Make sure it throws.
|
||||
BOOST_REQUIRE_THROW( PUSH_TX( db, trx ), fc::exception );
|
||||
pop.review_period_seconds = global_params.genesis_proposal_review_period / 2;
|
||||
GRAPHENE_REQUIRE_THROW( PUSH_TX( db, trx ), proposal_create_review_period_required );
|
||||
pop.review_period_seconds = global_params.committee_proposal_review_period / 2;
|
||||
trx.operations.back() = pop;
|
||||
sign();
|
||||
// The review period is too short. Make sure it throws.
|
||||
BOOST_REQUIRE_THROW( PUSH_TX( db, trx ), fc::exception );
|
||||
pop.review_period_seconds = global_params.genesis_proposal_review_period;
|
||||
GRAPHENE_REQUIRE_THROW( PUSH_TX( db, trx ), proposal_create_review_period_insufficient );
|
||||
pop.review_period_seconds = global_params.committee_proposal_review_period;
|
||||
trx.operations.back() = pop;
|
||||
sign();
|
||||
proposal_object prop = db.get<proposal_object>(PUSH_TX( db, trx ).operation_results.front().get<object_id_type>());
|
||||
|
|
@ -405,7 +406,7 @@ BOOST_AUTO_TEST_CASE( genesis_authority )
|
|||
generate_block();
|
||||
BOOST_REQUIRE(db.find_object(prop.id));
|
||||
BOOST_CHECK_EQUAL(get_balance(nathan, asset_id_type()(db)), 0);
|
||||
|
||||
|
||||
BOOST_TEST_MESSAGE( "Checking that the proposal is not authorized to execute" );
|
||||
BOOST_REQUIRE(!db.get<proposal_object>(prop.id).is_authorized_to_execute(db));
|
||||
trx.operations.clear();
|
||||
|
|
@ -435,7 +436,7 @@ BOOST_AUTO_TEST_CASE( genesis_authority )
|
|||
trx.operations.back() = uop;
|
||||
trx.sign( genesis_key);
|
||||
// Should throw because the transaction is now in review.
|
||||
BOOST_CHECK_THROW(PUSH_TX( db, trx ), fc::exception);
|
||||
GRAPHENE_CHECK_THROW(PUSH_TX( db, trx ), fc::exception);
|
||||
|
||||
generate_blocks(prop.expiration_time);
|
||||
BOOST_CHECK_EQUAL(get_balance(nathan, asset_id_type()(db)), 100000);
|
||||
|
|
@ -456,7 +457,7 @@ BOOST_FIXTURE_TEST_CASE( fired_delegates, database_fixture )
|
|||
|
||||
db.modify(db.get_global_properties(), [](global_property_object& p) {
|
||||
// Turn the review period WAY down, so it doesn't take long to produce blocks to that point in simulated time.
|
||||
p.parameters.genesis_proposal_review_period = fc::days(1).to_seconds();
|
||||
p.parameters.committee_proposal_review_period = fc::days(1).to_seconds();
|
||||
});
|
||||
|
||||
for( int i = 0; i < 15; ++i )
|
||||
|
|
@ -590,7 +591,7 @@ 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);
|
||||
BOOST_REQUIRE_THROW(PUSH_TX( db, trx ), fc::exception);
|
||||
GRAPHENE_REQUIRE_THROW(PUSH_TX( db, trx ), fc::exception);
|
||||
trx.sign(dan_key);
|
||||
PUSH_TX( db, trx );
|
||||
|
||||
|
|
@ -840,7 +841,7 @@ BOOST_FIXTURE_TEST_CASE( max_authority_membership, database_fixture )
|
|||
generate_block();
|
||||
|
||||
db.modify(db.get_global_properties(), [](global_property_object& p) {
|
||||
p.parameters.genesis_proposal_review_period = fc::hours(1).to_seconds();
|
||||
p.parameters.committee_proposal_review_period = fc::hours(1).to_seconds();
|
||||
});
|
||||
|
||||
transaction tx;
|
||||
|
|
@ -911,7 +912,7 @@ BOOST_FIXTURE_TEST_CASE( max_authority_membership, database_fixture )
|
|||
|
||||
if( num_keys > max_authority_membership )
|
||||
{
|
||||
BOOST_REQUIRE_THROW(PUSH_TX( db, tx, ~0 ), fc::exception);
|
||||
GRAPHENE_REQUIRE_THROW(PUSH_TX( db, tx, ~0 ), fc::exception);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -976,7 +977,7 @@ BOOST_FIXTURE_TEST_CASE( bogus_signature, database_fixture )
|
|||
trx.operations.push_back( xfer_op );
|
||||
BOOST_TEST_MESSAGE( "Invalidating Alices Signature" );
|
||||
// Alice's signature is now invalid
|
||||
BOOST_REQUIRE_THROW( PUSH_TX( db, trx, skip ), fc::exception );
|
||||
GRAPHENE_REQUIRE_THROW( PUSH_TX( db, trx, skip ), fc::exception );
|
||||
// Re-sign, now OK (sig is replaced)
|
||||
BOOST_TEST_MESSAGE( "Resign with Alice's Signature" );
|
||||
trx.signatures.clear();
|
||||
|
|
@ -988,7 +989,7 @@ BOOST_FIXTURE_TEST_CASE( bogus_signature, database_fixture )
|
|||
trx.sign( alice_key );
|
||||
trx.sign( charlie_key );
|
||||
// Signed by third-party Charlie (irrelevant key, not in authority)
|
||||
BOOST_REQUIRE_THROW( PUSH_TX( db, trx, skip ), fc::exception );
|
||||
GRAPHENE_REQUIRE_THROW( PUSH_TX( db, trx, skip ), fc::exception );
|
||||
}
|
||||
FC_LOG_AND_RETHROW()
|
||||
}
|
||||
|
|
@ -1029,7 +1030,7 @@ BOOST_FIXTURE_TEST_CASE( voting_account, database_fixture )
|
|||
trx.operations.push_back(op);
|
||||
trx.sign(vikram_private_key);
|
||||
// Fails because num_committee is larger than the cardinality of committee members being voted for
|
||||
BOOST_CHECK_THROW(PUSH_TX( db, trx ), fc::exception);
|
||||
GRAPHENE_CHECK_THROW(PUSH_TX( db, trx ), fc::exception);
|
||||
op.new_options->num_committee = 3;
|
||||
trx.operations = {op};
|
||||
trx.signatures.clear();
|
||||
|
|
|
|||
|
|
@ -330,7 +330,7 @@ BOOST_AUTO_TEST_CASE( data_fees )
|
|||
|
||||
BOOST_AUTO_TEST_CASE( exceptions )
|
||||
{
|
||||
BOOST_CHECK_THROW(FC_THROW_EXCEPTION(invalid_claim_amount, "Etc"), invalid_claim_amount);
|
||||
GRAPHENE_CHECK_THROW(FC_THROW_EXCEPTION(balance_claim_invalid_claim_amount, "Etc"), balance_claim_invalid_claim_amount);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_SUITE_END()
|
||||
|
|
|
|||
|
|
@ -36,6 +36,9 @@ using namespace graphene::chain;
|
|||
|
||||
genesis_state_type make_genesis() {
|
||||
genesis_state_type genesis_state;
|
||||
|
||||
genesis_state.initial_timestamp = time_point_sec( GRAPHENE_TESTING_GENESIS_TIMESTAMP );
|
||||
|
||||
auto delegate_priv_key = fc::ecc::private_key::regenerate(fc::sha256::hash(string("null_key")));
|
||||
genesis_state.initial_active_witnesses = 10;
|
||||
for( int i = 0; i < genesis_state.initial_active_witnesses; ++i )
|
||||
|
|
@ -117,7 +120,7 @@ BOOST_AUTO_TEST_CASE( block_database_test )
|
|||
BOOST_AUTO_TEST_CASE( generate_empty_blocks )
|
||||
{
|
||||
try {
|
||||
fc::time_point_sec now( GRAPHENE_GENESIS_TIMESTAMP );
|
||||
fc::time_point_sec now( GRAPHENE_TESTING_GENESIS_TIMESTAMP );
|
||||
fc::temp_directory data_dir;
|
||||
signed_block b;
|
||||
|
||||
|
|
@ -126,7 +129,7 @@ BOOST_AUTO_TEST_CASE( generate_empty_blocks )
|
|||
auto delegate_priv_key = fc::ecc::private_key::regenerate(fc::sha256::hash(string("null_key")) );
|
||||
{
|
||||
database db;
|
||||
db.open(data_dir.path(), make_genesis() );
|
||||
db.open(data_dir.path(), make_genesis );
|
||||
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 )
|
||||
|
|
@ -134,25 +137,25 @@ BOOST_AUTO_TEST_CASE( generate_empty_blocks )
|
|||
BOOST_CHECK( db.head_block_id() == b.id() );
|
||||
witness_id_type prev_witness = b.witness;
|
||||
now += db.block_interval();
|
||||
witness_id_type cur_witness = db.get_scheduled_witness( 1 ).first;
|
||||
witness_id_type cur_witness = db.get_scheduled_witness(1).first;
|
||||
BOOST_CHECK( cur_witness != prev_witness );
|
||||
b = db.generate_block( now, cur_witness, delegate_priv_key, database::skip_nothing );
|
||||
b = db.generate_block(now, cur_witness, delegate_priv_key, database::skip_nothing);
|
||||
BOOST_CHECK( b.witness == cur_witness );
|
||||
}
|
||||
db.close();
|
||||
}
|
||||
{
|
||||
database db;
|
||||
db.open(data_dir.path() );
|
||||
db.open(data_dir.path(), []{return genesis_state_type();});
|
||||
BOOST_CHECK_EQUAL( db.head_block_num(), 200 );
|
||||
for( uint32_t i = 0; i < 200; ++i )
|
||||
{
|
||||
BOOST_CHECK( db.head_block_id() == b.id() );
|
||||
witness_id_type prev_witness = b.witness;
|
||||
now += db.block_interval();
|
||||
witness_id_type cur_witness = db.get_scheduled_witness( 1 ).first;
|
||||
witness_id_type cur_witness = db.get_scheduled_witness(1).first;
|
||||
BOOST_CHECK( cur_witness != prev_witness );
|
||||
b = db.generate_block( now, cur_witness, delegate_priv_key, database::skip_nothing );
|
||||
b = db.generate_block(now, cur_witness, delegate_priv_key, database::skip_nothing);
|
||||
}
|
||||
BOOST_CHECK_EQUAL( db.head_block_num(), 400 );
|
||||
}
|
||||
|
|
@ -168,8 +171,8 @@ BOOST_AUTO_TEST_CASE( undo_block )
|
|||
fc::temp_directory data_dir;
|
||||
{
|
||||
database db;
|
||||
db.open(data_dir.path(), make_genesis() );
|
||||
fc::time_point_sec now( GRAPHENE_GENESIS_TIMESTAMP );
|
||||
db.open(data_dir.path(), make_genesis);
|
||||
fc::time_point_sec now( GRAPHENE_TESTING_GENESIS_TIMESTAMP );
|
||||
|
||||
auto delegate_priv_key = fc::ecc::private_key::regenerate(fc::sha256::hash(string("null_key")) );
|
||||
for( uint32_t i = 0; i < 5; ++i )
|
||||
|
|
@ -205,12 +208,12 @@ BOOST_AUTO_TEST_CASE( fork_blocks )
|
|||
try {
|
||||
fc::temp_directory data_dir1;
|
||||
fc::temp_directory data_dir2;
|
||||
fc::time_point_sec now( GRAPHENE_GENESIS_TIMESTAMP );
|
||||
fc::time_point_sec now( GRAPHENE_TESTING_GENESIS_TIMESTAMP );
|
||||
|
||||
database db1;
|
||||
db1.open(data_dir1.path(), make_genesis());
|
||||
db1.open(data_dir1.path(), make_genesis);
|
||||
database db2;
|
||||
db2.open(data_dir2.path(), make_genesis());
|
||||
db2.open(data_dir2.path(), make_genesis);
|
||||
|
||||
auto delegate_priv_key = fc::ecc::private_key::regenerate(fc::sha256::hash(string("null_key")) );
|
||||
for( uint32_t i = 0; i < 10; ++i )
|
||||
|
|
@ -251,7 +254,7 @@ BOOST_AUTO_TEST_CASE( fork_blocks )
|
|||
b.transactions.back().operations.emplace_back(transfer_operation());
|
||||
b.sign(delegate_priv_key);
|
||||
BOOST_CHECK_EQUAL(b.block_num(), 14);
|
||||
BOOST_CHECK_THROW(PUSH_BLOCK( db1, b ), fc::exception);
|
||||
GRAPHENE_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);
|
||||
|
|
@ -269,11 +272,11 @@ 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_TESTING_GENESIS_TIMESTAMP);
|
||||
fc::temp_directory data_dir;
|
||||
{
|
||||
database db;
|
||||
db.open(data_dir.path(), make_genesis());
|
||||
db.open(data_dir.path(), make_genesis);
|
||||
|
||||
auto delegate_priv_key = fc::ecc::private_key::regenerate(fc::sha256::hash(string("null_key")) );
|
||||
public_key_type delegate_pub_key = delegate_priv_key.get_public_key();
|
||||
|
|
@ -331,10 +334,10 @@ BOOST_AUTO_TEST_CASE( switch_forks_undo_create )
|
|||
dir2;
|
||||
database db1,
|
||||
db2;
|
||||
db1.open(dir1.path(), make_genesis());
|
||||
db2.open(dir2.path(), make_genesis());
|
||||
db1.open(dir1.path(), make_genesis);
|
||||
db2.open(dir2.path(), make_genesis);
|
||||
|
||||
fc::time_point_sec now( GRAPHENE_GENESIS_TIMESTAMP );
|
||||
fc::time_point_sec now( GRAPHENE_TESTING_GENESIS_TIMESTAMP );
|
||||
auto delegate_priv_key = fc::ecc::private_key::regenerate(fc::sha256::hash(string("null_key")) );
|
||||
public_key_type delegate_pub_key = delegate_priv_key.get_public_key();
|
||||
const graphene::db::index& account_idx = db1.get_index(protocol_ids, account_object_type);
|
||||
|
|
@ -355,7 +358,7 @@ BOOST_AUTO_TEST_CASE( switch_forks_undo_create )
|
|||
|
||||
BOOST_CHECK(nathan_id(db1).name == "nathan");
|
||||
|
||||
now = fc::time_point_sec( GRAPHENE_GENESIS_TIMESTAMP );
|
||||
now = fc::time_point_sec( GRAPHENE_TESTING_GENESIS_TIMESTAMP );
|
||||
now += db2.block_interval();
|
||||
b = db2.generate_block(now, db2.get_scheduled_witness(1).first, delegate_priv_key, database::skip_nothing);
|
||||
db1.push_block(b);
|
||||
|
|
@ -364,7 +367,7 @@ BOOST_AUTO_TEST_CASE( switch_forks_undo_create )
|
|||
b = db2.generate_block(now, db2.get_scheduled_witness(1).first, delegate_priv_key, database::skip_nothing);
|
||||
db1.push_block(b);
|
||||
|
||||
BOOST_CHECK_THROW(nathan_id(db1), fc::exception);
|
||||
GRAPHENE_CHECK_THROW(nathan_id(db1), fc::exception);
|
||||
|
||||
PUSH_TX( db2, trx );
|
||||
|
||||
|
|
@ -384,13 +387,13 @@ BOOST_AUTO_TEST_CASE( switch_forks_undo_create )
|
|||
BOOST_AUTO_TEST_CASE( duplicate_transactions )
|
||||
{
|
||||
try {
|
||||
fc::time_point_sec now( GRAPHENE_GENESIS_TIMESTAMP );
|
||||
fc::time_point_sec now( GRAPHENE_TESTING_GENESIS_TIMESTAMP );
|
||||
fc::temp_directory dir1,
|
||||
dir2;
|
||||
database db1,
|
||||
db2;
|
||||
db1.open(dir1.path(), make_genesis());
|
||||
db2.open(dir2.path(), make_genesis());
|
||||
db1.open(dir1.path(), make_genesis);
|
||||
db2.open(dir2.path(), make_genesis);
|
||||
|
||||
auto skip_sigs = database::skip_transaction_signatures | database::skip_authority_check;
|
||||
|
||||
|
|
@ -414,14 +417,14 @@ BOOST_AUTO_TEST_CASE( duplicate_transactions )
|
|||
trx.sign( delegate_priv_key );
|
||||
PUSH_TX( db1, trx, skip_sigs );
|
||||
|
||||
BOOST_CHECK_THROW(PUSH_TX( db1, trx, skip_sigs ), fc::exception);
|
||||
GRAPHENE_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 );
|
||||
PUSH_BLOCK( db2, b, skip_sigs );
|
||||
|
||||
BOOST_CHECK_THROW(PUSH_TX( db1, trx, skip_sigs ), fc::exception);
|
||||
BOOST_CHECK_THROW(PUSH_TX( db2, trx, skip_sigs ), fc::exception);
|
||||
GRAPHENE_CHECK_THROW(PUSH_TX( db1, trx, skip_sigs ), fc::exception);
|
||||
GRAPHENE_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) {
|
||||
|
|
@ -433,13 +436,13 @@ BOOST_AUTO_TEST_CASE( duplicate_transactions )
|
|||
BOOST_AUTO_TEST_CASE( tapos )
|
||||
{
|
||||
try {
|
||||
fc::time_point_sec now( GRAPHENE_GENESIS_TIMESTAMP );
|
||||
fc::time_point_sec now( GRAPHENE_TESTING_GENESIS_TIMESTAMP );
|
||||
fc::temp_directory dir1,
|
||||
dir2;
|
||||
database db1,
|
||||
db2;
|
||||
db1.open(dir1.path(), make_genesis());
|
||||
db2.open(dir2.path(), make_genesis());
|
||||
db1.open(dir1.path(), make_genesis);
|
||||
db2.open(dir2.path(), make_genesis);
|
||||
|
||||
const account_object& init1 = *db1.get_index_type<account_index>().indices().get<by_name>().find("init1");
|
||||
|
||||
|
|
@ -448,7 +451,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, database::skip_nothing );
|
||||
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.
|
||||
|
|
@ -464,16 +467,12 @@ BOOST_AUTO_TEST_CASE( tapos )
|
|||
db1.push_transaction(trx);
|
||||
now += db1.block_interval();
|
||||
b = db1.generate_block(now, db1.get_scheduled_witness(1).first, delegate_priv_key, database::skip_nothing);
|
||||
/*
|
||||
now += db1.block_interval();
|
||||
b = db1.generate_block(now, db1.get_scheduled_witness(1).first, delegate_priv_key, database::skip_nothing);
|
||||
*/
|
||||
trx.clear();
|
||||
|
||||
trx.operations.push_back(transfer_operation({asset(), account_id_type(), nathan_id, asset(50)}));
|
||||
trx.sign(delegate_priv_key);
|
||||
//relative_expiration is 1, but ref block is 2 blocks old, so this should fail.
|
||||
BOOST_REQUIRE_THROW(PUSH_TX( db1, trx, database::skip_transaction_signatures | database::skip_authority_check ), fc::exception);
|
||||
GRAPHENE_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(delegate_priv_key);
|
||||
|
|
@ -598,17 +597,17 @@ BOOST_FIXTURE_TEST_CASE( double_sign_check, database_fixture )
|
|||
trx.validate();
|
||||
|
||||
BOOST_TEST_MESSAGE( "Verify that not-signing causes an exception" );
|
||||
BOOST_REQUIRE_THROW( db.push_transaction(trx, 0), fc::exception );
|
||||
GRAPHENE_REQUIRE_THROW( db.push_transaction(trx, 0), fc::exception );
|
||||
|
||||
BOOST_TEST_MESSAGE( "Verify that double-signing causes an exception" );
|
||||
trx.sign(bob_private_key);
|
||||
trx.sign(bob_private_key);
|
||||
BOOST_REQUIRE_THROW( db.push_transaction(trx, 0), fc::exception );
|
||||
GRAPHENE_REQUIRE_THROW( db.push_transaction(trx, 0), fc::exception );
|
||||
|
||||
BOOST_TEST_MESSAGE( "Verify that signing with an extra, unused key fails" );
|
||||
trx.signatures.pop_back();
|
||||
trx.sign(generate_private_key("bogus"));
|
||||
BOOST_REQUIRE_THROW( db.push_transaction(trx, 0), fc::exception );
|
||||
GRAPHENE_REQUIRE_THROW( db.push_transaction(trx, 0), fc::exception );
|
||||
|
||||
BOOST_TEST_MESSAGE( "Verify that signing once with the proper key passes" );
|
||||
trx.signatures.pop_back();
|
||||
|
|
@ -622,7 +621,7 @@ BOOST_FIXTURE_TEST_CASE( change_block_interval, database_fixture )
|
|||
generate_block();
|
||||
|
||||
db.modify(db.get_global_properties(), [](global_property_object& p) {
|
||||
p.parameters.genesis_proposal_review_period = fc::hours(1).to_seconds();
|
||||
p.parameters.committee_proposal_review_period = fc::hours(1).to_seconds();
|
||||
});
|
||||
|
||||
{
|
||||
|
|
@ -773,7 +772,7 @@ BOOST_FIXTURE_TEST_CASE( unimp_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 = PUSH_TX( db, trx ).operation_results.front().get<object_id_type>(), fc::exception);
|
||||
GRAPHENE_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 = PUSH_TX( db, trx ).operation_results.front().get<object_id_type>();
|
||||
|
|
@ -823,13 +822,13 @@ BOOST_FIXTURE_TEST_CASE( pop_block_twice, database_fixture )
|
|||
// Sam is the creator of accounts
|
||||
private_key_type genesis_key = delegate_priv_key;
|
||||
private_key_type sam_key = generate_private_key("sam");
|
||||
account_object sam_account_object = create_account( "sam", sam_key );
|
||||
account_object sam_account_object = create_account("sam", sam_key);
|
||||
|
||||
//Get a sane head block time
|
||||
generate_block( skip_flags );
|
||||
|
||||
db.modify(db.get_global_properties(), [](global_property_object& p) {
|
||||
p.parameters.genesis_proposal_review_period = fc::hours(1).to_seconds();
|
||||
p.parameters.committee_proposal_review_period = fc::hours(1).to_seconds();
|
||||
});
|
||||
|
||||
transaction tx;
|
||||
|
|
@ -839,18 +838,16 @@ BOOST_FIXTURE_TEST_CASE( pop_block_twice, database_fixture )
|
|||
// transfer from genesis account to Sam account
|
||||
transfer(genesis_account_object, sam_account_object, core.amount(100000));
|
||||
|
||||
generate_block( skip_flags );
|
||||
generate_block(skip_flags);
|
||||
|
||||
create_account( "alice" );
|
||||
generate_block( skip_flags );
|
||||
create_account( "bob" );
|
||||
generate_block( skip_flags );
|
||||
create_account("alice");
|
||||
generate_block(skip_flags);
|
||||
create_account("bob");
|
||||
generate_block(skip_flags);
|
||||
|
||||
db.pop_block();
|
||||
db.pop_block();
|
||||
}
|
||||
catch( const fc::exception& e )
|
||||
{
|
||||
} catch(const fc::exception& e) {
|
||||
edump( (e.to_detail_string()) );
|
||||
throw;
|
||||
}
|
||||
|
|
@ -882,73 +879,4 @@ BOOST_FIXTURE_TEST_CASE( witness_scheduler_missed_blocks, database_fixture )
|
|||
});
|
||||
} FC_LOG_AND_RETHROW() }
|
||||
|
||||
BOOST_FIXTURE_TEST_CASE( account_create_fee_scaling, database_fixture )
|
||||
{ try {
|
||||
auto accounts_per_scale = db.get_global_properties().parameters.accounts_per_fee_scale;
|
||||
enable_fees(1);
|
||||
|
||||
BOOST_CHECK_EQUAL(db.get_global_properties().parameters.current_fees.account_create_fee, 1);
|
||||
for( int i = db.get_dynamic_global_properties().accounts_registered_this_interval; i < accounts_per_scale; ++i )
|
||||
create_account("shill" + fc::to_string(i));
|
||||
generate_block();
|
||||
BOOST_CHECK_EQUAL(db.get_global_properties().parameters.current_fees.account_create_fee, 16);
|
||||
for( int i = 0; i < accounts_per_scale; ++i )
|
||||
create_account("moreshills" + fc::to_string(i));
|
||||
generate_block();
|
||||
BOOST_CHECK_EQUAL(db.get_global_properties().parameters.current_fees.account_create_fee, 256);
|
||||
for( int i = 0; i < accounts_per_scale; ++i )
|
||||
create_account("moarshills" + fc::to_string(i));
|
||||
generate_block();
|
||||
BOOST_CHECK_EQUAL(db.get_global_properties().parameters.current_fees.account_create_fee, 4096);
|
||||
|
||||
generate_blocks(db.get_dynamic_global_properties().next_maintenance_time);
|
||||
BOOST_CHECK_EQUAL(db.get_global_properties().parameters.current_fees.account_create_fee, 1);
|
||||
} FC_LOG_AND_RETHROW() }
|
||||
|
||||
BOOST_FIXTURE_TEST_CASE( tapos_rollover, database_fixture )
|
||||
{
|
||||
try
|
||||
{
|
||||
ACTORS((alice)(bob));
|
||||
const auto& core = asset_id_type()(db);
|
||||
|
||||
BOOST_TEST_MESSAGE( "Give Alice some money" );
|
||||
transfer(genesis_account, alice_id, asset(10000));
|
||||
generate_block();
|
||||
|
||||
BOOST_TEST_MESSAGE( "Generate up to block 0xFF00" );
|
||||
generate_blocks( 0xFF00 );
|
||||
signed_transaction xfer_tx;
|
||||
|
||||
BOOST_TEST_MESSAGE( "Transfer money at/about 0xFF00" );
|
||||
transfer_operation xfer_op;
|
||||
xfer_op.from = alice_id;
|
||||
xfer_op.to = bob_id;
|
||||
xfer_op.amount = asset(1000);
|
||||
|
||||
xfer_tx.operations.push_back( xfer_op );
|
||||
xfer_tx.set_expiration( db.head_block_id(), 0x1000 );
|
||||
sign( xfer_tx, alice_private_key );
|
||||
PUSH_TX( db, xfer_tx, 0 );
|
||||
generate_block();
|
||||
|
||||
BOOST_TEST_MESSAGE( "Sign new tx's" );
|
||||
xfer_tx.set_expiration( db.head_block_id(), 0x1000 );
|
||||
xfer_tx.signatures.clear();
|
||||
sign( xfer_tx, alice_private_key );
|
||||
|
||||
BOOST_TEST_MESSAGE( "Generate up to block 0x10010" );
|
||||
generate_blocks( 0x110 );
|
||||
|
||||
BOOST_TEST_MESSAGE( "Transfer at/about block 0x10010 using reference block at/about 0xFF00" );
|
||||
PUSH_TX( db, xfer_tx, 0 );
|
||||
generate_block();
|
||||
}
|
||||
catch (fc::exception& e)
|
||||
{
|
||||
edump((e.to_detail_string()));
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_SUITE_END()
|
||||
|
|
|
|||
|
|
@ -130,45 +130,4 @@ BOOST_AUTO_TEST_CASE( cashback_test )
|
|||
BOOST_CHECK_EQUAL(stud_id(db).cashback_balance(db).balance.amount.value, 25750);
|
||||
} FC_LOG_AND_RETHROW() }
|
||||
|
||||
BOOST_AUTO_TEST_CASE(bulk_discount)
|
||||
{ try {
|
||||
ACTOR(nathan);
|
||||
// Give nathan ALLLLLL the money!
|
||||
transfer(GRAPHENE_COMMITTEE_ACCOUNT, nathan_id, db.get_balance(GRAPHENE_COMMITTEE_ACCOUNT, asset_id_type()));
|
||||
enable_fees(GRAPHENE_BLOCKCHAIN_PRECISION*10);
|
||||
upgrade_to_lifetime_member(nathan_id);
|
||||
share_type new_fees;
|
||||
while( nathan_id(db).statistics(db).lifetime_fees_paid + new_fees < GRAPHENE_DEFAULT_BULK_DISCOUNT_THRESHOLD_MIN )
|
||||
{
|
||||
transfer(nathan_id, GRAPHENE_COMMITTEE_ACCOUNT, asset(1));
|
||||
new_fees += transfer_operation().calculate_fee(db.current_fee_schedule());
|
||||
}
|
||||
generate_blocks(db.get_dynamic_global_properties().next_maintenance_time);
|
||||
enable_fees(GRAPHENE_BLOCKCHAIN_PRECISION*10);
|
||||
auto old_cashback = nathan_id(db).cashback_balance(db).balance;
|
||||
|
||||
transfer(nathan_id, GRAPHENE_COMMITTEE_ACCOUNT, asset(1));
|
||||
generate_blocks(db.get_dynamic_global_properties().next_maintenance_time);
|
||||
enable_fees(GRAPHENE_BLOCKCHAIN_PRECISION*10);
|
||||
|
||||
BOOST_CHECK_EQUAL(nathan_id(db).cashback_balance(db).balance.amount.value,
|
||||
old_cashback.amount.value + GRAPHENE_BLOCKCHAIN_PRECISION * 8);
|
||||
|
||||
new_fees = 0;
|
||||
while( nathan_id(db).statistics(db).lifetime_fees_paid + new_fees < GRAPHENE_DEFAULT_BULK_DISCOUNT_THRESHOLD_MAX )
|
||||
{
|
||||
transfer(nathan_id, GRAPHENE_COMMITTEE_ACCOUNT, asset(1));
|
||||
new_fees += transfer_operation().calculate_fee(db.current_fee_schedule());
|
||||
}
|
||||
generate_blocks(db.get_dynamic_global_properties().next_maintenance_time);
|
||||
enable_fees(GRAPHENE_BLOCKCHAIN_PRECISION*10);
|
||||
old_cashback = nathan_id(db).cashback_balance(db).balance;
|
||||
|
||||
transfer(nathan_id, GRAPHENE_COMMITTEE_ACCOUNT, asset(1));
|
||||
generate_blocks(db.get_dynamic_global_properties().next_maintenance_time);
|
||||
|
||||
BOOST_CHECK_EQUAL(nathan_id(db).cashback_balance(db).balance.amount.value,
|
||||
old_cashback.amount.value + GRAPHENE_BLOCKCHAIN_PRECISION * 9);
|
||||
} FC_LOG_AND_RETHROW() }
|
||||
|
||||
BOOST_AUTO_TEST_SUITE_END()
|
||||
|
|
|
|||
|
|
@ -94,7 +94,7 @@ BOOST_AUTO_TEST_CASE( call_order_update_test )
|
|||
BOOST_REQUIRE_EQUAL( get_balance( dan, core ), 10000000 - 10000 + 5000 );
|
||||
|
||||
BOOST_TEST_MESSAGE( "verifying that attempting to cover the full amount without claiming the collateral fails" );
|
||||
BOOST_REQUIRE_THROW( cover( dan, bitusd.amount(2500), core.amount(0) ), fc::exception );
|
||||
GRAPHENE_REQUIRE_THROW( cover( dan, bitusd.amount(2500), core.amount(0) ), fc::exception );
|
||||
|
||||
cover( dan, bitusd.amount(2500), core.amount(5000));
|
||||
|
||||
|
|
@ -127,14 +127,14 @@ BOOST_AUTO_TEST_CASE( call_order_update_test )
|
|||
BOOST_REQUIRE_EQUAL( get_balance( dan, core ), 10000000 - 20000 );
|
||||
|
||||
BOOST_TEST_MESSAGE( "increasing debt without increasing collateral again" );
|
||||
BOOST_REQUIRE_THROW( borrow( dan, bitusd.amount(80000), asset(0)), fc::exception );
|
||||
GRAPHENE_REQUIRE_THROW( borrow( dan, bitusd.amount(80000), asset(0)), fc::exception );
|
||||
BOOST_TEST_MESSAGE( "attempting to claim all collateral without paying off debt" );
|
||||
BOOST_REQUIRE_THROW( cover( dan, bitusd.amount(0), asset(20000)), fc::exception );
|
||||
GRAPHENE_REQUIRE_THROW( cover( dan, bitusd.amount(0), asset(20000)), fc::exception );
|
||||
BOOST_TEST_MESSAGE( "attempting reduce collateral without paying off any debt" );
|
||||
cover( dan, bitusd.amount(0), asset(1000));
|
||||
|
||||
BOOST_TEST_MESSAGE( "attempting change call price to be below minimum for debt/collateral ratio" );
|
||||
BOOST_REQUIRE_THROW( cover( dan, bitusd.amount(0), asset(0)), fc::exception );
|
||||
GRAPHENE_REQUIRE_THROW( cover( dan, bitusd.amount(0), asset(0)), fc::exception );
|
||||
|
||||
} catch (fc::exception& e) {
|
||||
edump((e.to_detail_string()));
|
||||
|
|
@ -255,7 +255,7 @@ BOOST_AUTO_TEST_CASE( black_swan )
|
|||
force_settle(borrower, bitusd.amount(100));
|
||||
|
||||
BOOST_TEST_MESSAGE( "Verify that we cannot borrow after black swan" );
|
||||
BOOST_REQUIRE_THROW( borrow(borrower, bitusd.amount(1000), asset(2000)), fc::exception );
|
||||
GRAPHENE_REQUIRE_THROW( borrow(borrower, bitusd.amount(1000), asset(2000)), fc::exception );
|
||||
} catch( const fc::exception& e) {
|
||||
edump((e.to_detail_string()));
|
||||
throw;
|
||||
|
|
@ -275,22 +275,22 @@ BOOST_AUTO_TEST_CASE( prediction_market )
|
|||
transfer(genesis_account, nathan_id, asset(init_balance));
|
||||
|
||||
BOOST_TEST_MESSAGE( "Require throw for mismatch collateral amounts" );
|
||||
BOOST_REQUIRE_THROW( borrow( dan, pmark.amount(1000), asset(2000) ), fc::exception );
|
||||
GRAPHENE_REQUIRE_THROW( borrow( dan, pmark.amount(1000), asset(2000) ), fc::exception );
|
||||
|
||||
BOOST_TEST_MESSAGE( "Open position with equal collateral" );
|
||||
borrow( dan, pmark.amount(1000), asset(1000) );
|
||||
|
||||
BOOST_TEST_MESSAGE( "Cover position with unequal asset should fail." );
|
||||
BOOST_REQUIRE_THROW( cover( dan, pmark.amount(500), asset(1000) ), fc::exception );
|
||||
GRAPHENE_REQUIRE_THROW( cover( dan, pmark.amount(500), asset(1000) ), fc::exception );
|
||||
|
||||
BOOST_TEST_MESSAGE( "Cover half of position with equal ammounts" );
|
||||
cover( dan, pmark.amount(500), asset(500) );
|
||||
|
||||
BOOST_TEST_MESSAGE( "Verify that forced settlment fails before global settlement" );
|
||||
BOOST_REQUIRE_THROW( force_settle( dan, pmark.amount(100) ), fc::exception );
|
||||
GRAPHENE_REQUIRE_THROW( force_settle( dan, pmark.amount(100) ), fc::exception );
|
||||
|
||||
BOOST_TEST_MESSAGE( "Shouldn't be allowed to force settle at more than 1 collateral per debt" );
|
||||
BOOST_REQUIRE_THROW( force_global_settle( pmark, pmark.amount(100) / core.amount(105) ), fc::exception );
|
||||
GRAPHENE_REQUIRE_THROW( force_global_settle( pmark, pmark.amount(100) / core.amount(105) ), fc::exception );
|
||||
|
||||
force_global_settle( pmark, pmark.amount(100) / core.amount(95) );
|
||||
|
||||
|
|
@ -328,7 +328,7 @@ 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(PUSH_TX( db, trx, ~0 ), fc::exception);
|
||||
GRAPHENE_REQUIRE_THROW(PUSH_TX( db, trx, ~0 ), fc::exception);
|
||||
op.owner = auth_bak;
|
||||
|
||||
trx.operations.back() = op;
|
||||
|
|
@ -487,7 +487,7 @@ BOOST_AUTO_TEST_CASE( create_mia )
|
|||
BOOST_CHECK(bitusd.symbol == "BITUSD");
|
||||
BOOST_CHECK(bitusd.bitasset_data(db).options.short_backing_asset == asset_id_type());
|
||||
BOOST_CHECK(bitusd.dynamic_asset_data_id(db).current_supply == 0);
|
||||
BOOST_REQUIRE_THROW( create_bitasset("BITUSD"), fc::exception);
|
||||
GRAPHENE_REQUIRE_THROW( create_bitasset("BITUSD"), fc::exception);
|
||||
} catch ( const fc::exception& e ) {
|
||||
elog( "${e}", ("e", e.to_detail_string() ) );
|
||||
throw;
|
||||
|
|
@ -574,7 +574,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(PUSH_TX( db, trx, ~0 ), fc::exception);
|
||||
GRAPHENE_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);
|
||||
|
|
@ -649,7 +649,7 @@ BOOST_AUTO_TEST_CASE( update_uia )
|
|||
trx.operations.back() = op;
|
||||
PUSH_TX( db, trx, ~0 );
|
||||
op.issuer = account_id_type();
|
||||
BOOST_REQUIRE_THROW(PUSH_TX( db, trx, ~0 ), fc::exception);
|
||||
GRAPHENE_REQUIRE_THROW(PUSH_TX( db, trx, ~0 ), fc::exception);
|
||||
op.new_issuer.reset();
|
||||
} catch(fc::exception& e) {
|
||||
edump((e.to_detail_string()));
|
||||
|
|
@ -1078,7 +1078,7 @@ BOOST_AUTO_TEST_CASE( limit_order_fill_or_kill )
|
|||
|
||||
trx.operations.clear();
|
||||
trx.operations.push_back(op);
|
||||
BOOST_CHECK_THROW(PUSH_TX( db, trx, ~0 ), fc::exception);
|
||||
GRAPHENE_CHECK_THROW(PUSH_TX( db, trx, ~0 ), fc::exception);
|
||||
op.fill_or_kill = false;
|
||||
trx.operations.back() = op;
|
||||
PUSH_TX( db, trx, ~0 );
|
||||
|
|
@ -1088,7 +1088,7 @@ BOOST_AUTO_TEST_CASE( limit_order_fill_or_kill )
|
|||
BOOST_AUTO_TEST_CASE( fill_order )
|
||||
{ try {
|
||||
fill_order_operation o;
|
||||
BOOST_CHECK_THROW(o.validate(), fc::exception);
|
||||
GRAPHENE_CHECK_THROW(o.validate(), fc::exception);
|
||||
o.calculate_fee(db.current_fee_schedule());
|
||||
} FC_LOG_AND_RETHROW() }
|
||||
|
||||
|
|
|
|||
|
|
@ -42,8 +42,6 @@ BOOST_FIXTURE_TEST_SUITE( operation_tests, database_fixture )
|
|||
|
||||
BOOST_AUTO_TEST_CASE( withdraw_permission_create )
|
||||
{ try {
|
||||
//ACTORS((nathan)(dan))
|
||||
//idump((nathan)(dan));
|
||||
auto nathan_private_key = generate_private_key("nathan");
|
||||
auto dan_private_key = generate_private_key("dan");
|
||||
account_id_type nathan_id = create_account("nathan", nathan_private_key.get_public_key()).id;
|
||||
|
|
@ -110,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(PUSH_TX( db, trx ), fc::exception);
|
||||
GRAPHENE_REQUIRE_THROW(PUSH_TX( db, trx ), fc::exception);
|
||||
//Get to the actual withdrawal period
|
||||
generate_blocks(permit(db).period_start_time);
|
||||
|
||||
|
|
@ -167,7 +165,7 @@ BOOST_AUTO_TEST_CASE( withdraw_permission_test )
|
|||
trx.operations.push_back(op);
|
||||
trx.sign(dan_private_key);
|
||||
//Throws because nathan doesn't have the money
|
||||
BOOST_CHECK_THROW(PUSH_TX( db, trx ), fc::exception);
|
||||
GRAPHENE_CHECK_THROW(PUSH_TX( db, trx ), fc::exception);
|
||||
op.amount_to_withdraw = asset(1);
|
||||
trx.clear();
|
||||
trx.operations = {op};
|
||||
|
|
@ -202,7 +200,7 @@ BOOST_AUTO_TEST_CASE( withdraw_permission_test )
|
|||
trx.operations.push_back(op);
|
||||
trx.sign(dan_private_key);
|
||||
//Throws because the permission has expired
|
||||
BOOST_CHECK_THROW(PUSH_TX( db, trx ), fc::exception);
|
||||
GRAPHENE_CHECK_THROW(PUSH_TX( db, trx ), fc::exception);
|
||||
}
|
||||
} FC_LOG_AND_RETHROW() }
|
||||
|
||||
|
|
@ -370,7 +368,7 @@ BOOST_AUTO_TEST_CASE( mia_feeds )
|
|||
|
||||
op.publisher = nathan_id;
|
||||
trx.operations.back() = op;
|
||||
BOOST_CHECK_THROW(PUSH_TX( db, trx, ~0 ), fc::exception);
|
||||
GRAPHENE_CHECK_THROW(PUSH_TX( db, trx, ~0 ), fc::exception);
|
||||
}
|
||||
} FC_LOG_AND_RETHROW() }
|
||||
|
||||
|
|
@ -895,7 +893,7 @@ BOOST_AUTO_TEST_CASE( unimp_force_settlement_unavailable )
|
|||
sop.amount = asset(50, bit_usd);
|
||||
trx.operations = {sop};
|
||||
//Force settlement is disabled; check that it fails
|
||||
BOOST_CHECK_THROW(PUSH_TX( db, trx, ~0 ), fc::exception);
|
||||
GRAPHENE_CHECK_THROW(PUSH_TX( db, trx, ~0 ), fc::exception);
|
||||
{
|
||||
//Enable force settlement
|
||||
asset_update_operation op;
|
||||
|
|
@ -969,7 +967,7 @@ BOOST_AUTO_TEST_CASE( assert_op_test )
|
|||
op.predicates.back() = fc::raw::pack(predicate(pred::account_name_eq_lit{ nathan_id, "dan" }));
|
||||
trx.operations.back() = op;
|
||||
trx.sign(nathan_private_key);
|
||||
BOOST_CHECK_THROW( PUSH_TX( db, trx ), fc::exception );
|
||||
GRAPHENE_CHECK_THROW( PUSH_TX( db, trx ), fc::exception );
|
||||
} FC_LOG_AND_RETHROW()
|
||||
}
|
||||
|
||||
|
|
@ -1003,7 +1001,7 @@ BOOST_AUTO_TEST_CASE( balance_object_test )
|
|||
|
||||
genesis_state.initial_accounts.emplace_back("n", n_key.get_public_key());
|
||||
|
||||
db.open(td.path(), genesis_state);
|
||||
db.open(td.path(), [this]{return genesis_state;});
|
||||
const balance_object& balance = balance_id_type()(db);
|
||||
BOOST_CHECK_EQUAL(balance.balance.amount.value, 1);
|
||||
BOOST_CHECK_EQUAL(balance_id_type(1)(db).balance.amount.value, 1);
|
||||
|
|
@ -1016,7 +1014,7 @@ BOOST_AUTO_TEST_CASE( balance_object_test )
|
|||
trx.operations = {op};
|
||||
trx.sign(n_key);
|
||||
// Fail because I'm claiming from an address which hasn't signed
|
||||
BOOST_CHECK_THROW(db.push_transaction(trx), fc::exception);
|
||||
GRAPHENE_CHECK_THROW(db.push_transaction(trx), fc::exception);
|
||||
trx.clear();
|
||||
op.balance_to_claim = balance_id_type();
|
||||
op.balance_owner_key = n_key.get_public_key();
|
||||
|
|
@ -1031,6 +1029,7 @@ BOOST_AUTO_TEST_CASE( balance_object_test )
|
|||
|
||||
auto slot = db.get_slot_at_time(starting_time);
|
||||
db.generate_block(starting_time, db.get_scheduled_witness(slot).first, delegate_priv_key, database::skip_nothing);
|
||||
trx.set_expiration(db.head_block_id());
|
||||
|
||||
const balance_object& vesting_balance_1 = balance_id_type(2)(db);
|
||||
const balance_object& vesting_balance_2 = balance_id_type(3)(db);
|
||||
|
|
@ -1045,12 +1044,11 @@ BOOST_AUTO_TEST_CASE( balance_object_test )
|
|||
op.total_claimed = asset(1);
|
||||
op.balance_owner_key = v1_key.get_public_key();
|
||||
trx.clear();
|
||||
trx.set_expiration(db.head_block_id());
|
||||
trx.operations = {op};
|
||||
trx.sign(n_key);
|
||||
trx.sign(v1_key);
|
||||
// Attempting to claim 1 from a balance with 0 available
|
||||
BOOST_CHECK_THROW(db.push_transaction(trx), invalid_claim_amount);
|
||||
GRAPHENE_CHECK_THROW(db.push_transaction(trx), balance_claim_invalid_claim_amount);
|
||||
|
||||
op.balance_to_claim = vesting_balance_2.id;
|
||||
op.total_claimed.amount = 151;
|
||||
|
|
@ -1060,7 +1058,7 @@ BOOST_AUTO_TEST_CASE( balance_object_test )
|
|||
trx.sign(n_key);
|
||||
trx.sign(v2_key);
|
||||
// Attempting to claim 151 from a balance with 150 available
|
||||
BOOST_CHECK_THROW(db.push_transaction(trx), invalid_claim_amount);
|
||||
GRAPHENE_CHECK_THROW(db.push_transaction(trx), balance_claim_invalid_claim_amount);
|
||||
|
||||
op.balance_to_claim = vesting_balance_2.id;
|
||||
op.total_claimed.amount = 100;
|
||||
|
|
@ -1070,33 +1068,58 @@ BOOST_AUTO_TEST_CASE( balance_object_test )
|
|||
trx.sign(n_key);
|
||||
trx.sign(v2_key);
|
||||
db.push_transaction(trx);
|
||||
|
||||
BOOST_CHECK_EQUAL(db.get_balance(op.deposit_to_account, asset_id_type()).amount.value, 101);
|
||||
BOOST_CHECK_EQUAL(vesting_balance_2.balance.amount.value, 300);
|
||||
|
||||
op.total_claimed.amount = 10;
|
||||
trx.operations = {op};
|
||||
trx.signatures.clear();
|
||||
trx.sign(n_key);
|
||||
trx.sign(v2_key);
|
||||
// Attempting to claim twice within a day
|
||||
BOOST_CHECK_THROW(db.push_transaction(trx), balance_claimed_too_often);
|
||||
GRAPHENE_CHECK_THROW(db.push_transaction(trx), balance_claim_claimed_too_often);
|
||||
|
||||
// TODO: test withdrawing entire vesting_balance_1 balance, remainder of vesting_balance_2 balance
|
||||
// slot = db.get_slot_at_time(vesting_balance_1.vesting_policy->begin_timestamp + 60);
|
||||
// db.generate_block(starting_time, db.get_scheduled_witness(slot).first, delegate_priv_key, database::skip_nothing);
|
||||
db.generate_block(db.get_slot_time(1), db.get_scheduled_witness(1).first, delegate_priv_key, database::skip_nothing);
|
||||
slot = db.get_slot_at_time(vesting_balance_1.vesting_policy->begin_timestamp + 60);
|
||||
db.generate_block(db.get_slot_time(slot), db.get_scheduled_witness(slot).first, delegate_priv_key, database::skip_nothing);
|
||||
trx.set_expiration(db.head_block_id());
|
||||
|
||||
// op.balance_to_claim = vesting_balance_1.id;
|
||||
// op.total_claimed.amount = 500;
|
||||
// op.balance_owner_key = v1_key.get_public_key();
|
||||
// trx.operations = {op};
|
||||
// trx.signatures.clear();
|
||||
// trx.sign(n_key);
|
||||
// trx.sign(v2_key);
|
||||
// db.push_transaction(trx);
|
||||
// BOOST_CHECK(db.find_object(op.balance_to_claim) == nullptr);
|
||||
op.balance_to_claim = vesting_balance_1.id;
|
||||
op.total_claimed.amount = 500;
|
||||
op.balance_owner_key = v1_key.get_public_key();
|
||||
trx.operations = {op};
|
||||
trx.signatures.clear();
|
||||
trx.sign(n_key);
|
||||
trx.sign(v1_key);
|
||||
db.push_transaction(trx);
|
||||
BOOST_CHECK(db.find_object(op.balance_to_claim) == nullptr);
|
||||
BOOST_CHECK_EQUAL(db.get_balance(op.deposit_to_account, asset_id_type()).amount.value, 601);
|
||||
|
||||
op.balance_to_claim = vesting_balance_2.id;
|
||||
op.balance_owner_key = v2_key.get_public_key();
|
||||
op.total_claimed.amount = 10;
|
||||
trx.operations = {op};
|
||||
trx.signatures.clear();
|
||||
trx.sign(n_key);
|
||||
trx.sign(v2_key);
|
||||
// Attempting to claim twice within a day
|
||||
GRAPHENE_CHECK_THROW(db.push_transaction(trx), balance_claim_claimed_too_often);
|
||||
|
||||
db.generate_block(db.get_slot_time(1), db.get_scheduled_witness(1).first, delegate_priv_key, database::skip_nothing);
|
||||
slot = db.get_slot_at_time(db.head_block_time() + fc::days(1));
|
||||
db.generate_block(db.get_slot_time(slot), db.get_scheduled_witness(slot).first, delegate_priv_key, database::skip_nothing);
|
||||
trx.set_expiration(db.head_block_id());
|
||||
|
||||
op.total_claimed = vesting_balance_2.balance;
|
||||
trx.operations = {op};
|
||||
trx.signatures.clear();
|
||||
trx.sign(n_key);
|
||||
trx.sign(v2_key);
|
||||
db.push_transaction(trx);
|
||||
BOOST_CHECK(db.find_object(op.balance_to_claim) == nullptr);
|
||||
BOOST_CHECK_EQUAL(db.get_balance(op.deposit_to_account, asset_id_type()).amount.value, 901);
|
||||
} FC_LOG_AND_RETHROW() }
|
||||
|
||||
// TODO: Write linear VBO tests
|
||||
|
||||
BOOST_AUTO_TEST_SUITE_END()
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@
|
|||
#include <boost/test/unit_test.hpp>
|
||||
|
||||
#include <graphene/chain/database.hpp>
|
||||
#include <graphene/chain/exceptions.hpp>
|
||||
#include <graphene/chain/operations.hpp>
|
||||
|
||||
#include <graphene/chain/account_object.hpp>
|
||||
|
|
@ -84,10 +85,10 @@ BOOST_AUTO_TEST_CASE( override_transfer_test )
|
|||
trx.operations.push_back(otrans);
|
||||
|
||||
BOOST_TEST_MESSAGE( "Require throwing without signature" );
|
||||
BOOST_REQUIRE_THROW( PUSH_TX( db, trx, 0 ), fc::exception);
|
||||
GRAPHENE_REQUIRE_THROW( PUSH_TX( db, trx, 0 ), tx_missing_active_auth );
|
||||
BOOST_TEST_MESSAGE( "Require throwing with dan's signature" );
|
||||
trx.sign( dan_private_key );
|
||||
BOOST_REQUIRE_THROW( PUSH_TX( db, trx, 0 ), fc::exception);
|
||||
GRAPHENE_REQUIRE_THROW( PUSH_TX( db, trx, 0 ), tx_missing_active_auth );
|
||||
BOOST_TEST_MESSAGE( "Pass with issuer's signature" );
|
||||
trx.signatures.clear();
|
||||
trx.sign( sam_private_key );
|
||||
|
|
@ -112,14 +113,14 @@ BOOST_AUTO_TEST_CASE( override_transfer_test2 )
|
|||
trx.operations.push_back(otrans);
|
||||
|
||||
BOOST_TEST_MESSAGE( "Require throwing without signature" );
|
||||
BOOST_REQUIRE_THROW( PUSH_TX( db, trx, 0 ), fc::exception);
|
||||
GRAPHENE_REQUIRE_THROW( PUSH_TX( db, trx, 0 ), fc::exception);
|
||||
BOOST_TEST_MESSAGE( "Require throwing with dan's signature" );
|
||||
trx.sign( dan_private_key );
|
||||
BOOST_REQUIRE_THROW( PUSH_TX( db, trx, 0 ), fc::exception);
|
||||
GRAPHENE_REQUIRE_THROW( PUSH_TX( db, trx, 0 ), fc::exception);
|
||||
BOOST_TEST_MESSAGE( "Fail because overide_authority flag is not set" );
|
||||
trx.signatures.clear();
|
||||
trx.sign( sam_private_key );
|
||||
BOOST_REQUIRE_THROW( PUSH_TX( db, trx, 0 ), fc::exception );
|
||||
GRAPHENE_REQUIRE_THROW( PUSH_TX( db, trx, 0 ), fc::exception );
|
||||
|
||||
BOOST_REQUIRE_EQUAL( get_balance( dan, advanced ), 1000 );
|
||||
BOOST_REQUIRE_EQUAL( get_balance( eric, advanced ), 0 );
|
||||
|
|
@ -137,7 +138,7 @@ 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(PUSH_TX( db, trx, ~0 ), fc::exception);
|
||||
GRAPHENE_REQUIRE_THROW(PUSH_TX( db, trx, ~0 ), fc::exception);
|
||||
|
||||
account_whitelist_operation wop({asset(), account_id_type(), nathan.id, account_whitelist_operation::white_listed});
|
||||
|
||||
|
|
@ -168,7 +169,7 @@ 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(PUSH_TX( db, trx, ~0 ), fc::exception);
|
||||
GRAPHENE_REQUIRE_THROW(PUSH_TX( db, trx, ~0 ), transfer_to_account_not_whitelisted );
|
||||
|
||||
account_whitelist_operation wop({asset(), account_id_type(), dan.id, account_whitelist_operation::white_listed});
|
||||
trx.operations.back() = wop;
|
||||
|
|
@ -187,14 +188,14 @@ BOOST_AUTO_TEST_CASE( transfer_whitelist_uia )
|
|||
op.amount = advanced.amount(50);
|
||||
trx.operations.back() = op;
|
||||
//Fail because nathan is blacklisted
|
||||
BOOST_REQUIRE_THROW(PUSH_TX( db, trx, ~0 ), fc::exception);
|
||||
GRAPHENE_REQUIRE_THROW(PUSH_TX( db, trx, ~0 ), transfer_from_account_not_whitelisted );
|
||||
trx.operations = {asset_reserve_operation{asset(), nathan.id, advanced.amount(10)}};
|
||||
//Fail because nathan is blacklisted
|
||||
BOOST_REQUIRE_THROW(PUSH_TX( db, trx, ~0 ), fc::exception);
|
||||
GRAPHENE_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(PUSH_TX( db, trx, ~0 ), fc::exception);
|
||||
GRAPHENE_REQUIRE_THROW(PUSH_TX( db, trx, ~0 ), fc::exception);
|
||||
|
||||
{
|
||||
asset_update_operation op;
|
||||
|
|
@ -221,7 +222,7 @@ BOOST_AUTO_TEST_CASE( transfer_whitelist_uia )
|
|||
trx.operations.back() = op;
|
||||
//Fail because nathan is blacklisted
|
||||
BOOST_CHECK(!nathan.is_authorized_asset(advanced));
|
||||
BOOST_REQUIRE_THROW(PUSH_TX( db, trx, ~0 ), fc::exception);
|
||||
GRAPHENE_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();
|
||||
|
|
@ -238,7 +239,7 @@ BOOST_AUTO_TEST_CASE( transfer_whitelist_uia )
|
|||
trx.operations.back() = op;
|
||||
//Fail because nathan is not whitelisted
|
||||
BOOST_CHECK(!nathan.is_authorized_asset(advanced));
|
||||
BOOST_REQUIRE_THROW(PUSH_TX( db, trx, ~0 ), fc::exception);
|
||||
GRAPHENE_REQUIRE_THROW(PUSH_TX( db, trx, ~0 ), fc::exception);
|
||||
|
||||
trx.operations = {asset_reserve_operation{asset(), dan.id, advanced.amount(10)}};
|
||||
PUSH_TX(db, trx, ~0);
|
||||
|
|
|
|||
Loading…
Reference in a new issue