提交 40544bf7 编写于 作者: D Daniel Larimer

Merge branch 'master' of github.com:EOSIO/eos

......@@ -639,11 +639,20 @@ void chain_controller::apply_message( apply_context& context )
} FC_CAPTURE_AND_RETHROW((context.msg)) }
void chain_controller::_apply_transaction(const SignedTransaction& trx)
{ try {
validate_transaction(trx);
auto getAuthority = [&db=_db](const types::AccountPermission& permission) {
auto key = boost::make_tuple(permission.account, permission.permission);
return db.get<permission_object, by_owner>(key).auth;
};
#warning TODO: Use a real chain_id here (where is this stored? Do we still need it?)
auto checker = MakeAuthorityChecker(std::move(getAuthority), trx.get_signature_keys(chain_id_type{}));
for (const auto& requiredAuthority : trx.authorizations)
EOS_ASSERT(checker.satisfied(requiredAuthority), tx_missing_auth, "Transaction is not authorized.");
for (const auto& message : trx.messages) {
process_message(message);
}
......
......@@ -29,33 +29,6 @@
namespace eos { namespace chain {
struct shared_authority {
shared_authority( chainbase::allocator<char> alloc )
:accounts(alloc),keys(alloc)
{}
shared_authority& operator=(const Authority& a) {
threshold = a.threshold;
accounts = decltype(accounts)(a.accounts.begin(), a.accounts.end(), accounts.get_allocator());
keys = decltype(keys)(a.keys.begin(), a.keys.end(), keys.get_allocator());
return *this;
}
shared_authority& operator=(Authority&& a) {
threshold = a.threshold;
accounts.reserve(a.accounts.size());
for (auto& p : a.accounts)
accounts.emplace_back(std::move(p));
keys.reserve(a.keys.size());
for (auto& p : a.keys)
keys.emplace_back(std::move(p));
return *this;
}
UInt32 threshold = 0;
shared_vector<types::AccountPermissionWeight> accounts;
shared_vector<types::KeyPermissionWeight> keys;
};
class account_object : public chainbase::object<account_object_type, account_object> {
OBJECT_CTOR(account_object,(code))
......@@ -78,52 +51,10 @@ namespace eos { namespace chain {
>
>;
class permission_object : public chainbase::object<permission_object_type, permission_object> {
OBJECT_CTOR(permission_object, (auth) )
id_type id;
AccountName owner; ///< the account this permission belongs to
id_type parent; ///< parent permission
PermissionName name; ///< human-readable name for the permission
shared_authority auth; ///< authority required to execute this permission
};
struct by_parent;
struct by_owner;
using permission_index = chainbase::shared_multi_index_container<
permission_object,
indexed_by<
ordered_unique<tag<by_id>, member<permission_object, permission_object::id_type, &permission_object::id>>,
ordered_unique<tag<by_parent>,
composite_key<permission_object,
member<permission_object, permission_object::id_type, &permission_object::parent>,
member<permission_object, permission_object::id_type, &permission_object::id>
>
>,
ordered_unique<tag<by_owner>,
composite_key<permission_object,
member<permission_object, AccountName, &permission_object::owner>,
member<permission_object, PermissionName, &permission_object::name>,
member<permission_object, permission_object::id_type, &permission_object::id>
>
>,
ordered_unique<tag<by_name>,
composite_key<permission_object,
member<permission_object, PermissionName, &permission_object::name>,
member<permission_object, permission_object::id_type, &permission_object::id>
>
>
>
>;
} } // eos::chain
CHAINBASE_SET_INDEX_TYPE(eos::chain::account_object, eos::chain::account_index)
CHAINBASE_SET_INDEX_TYPE(eos::chain::permission_object, eos::chain::permission_index)
FC_REFLECT(chainbase::oid<eos::chain::permission_object>, (_id))
FC_REFLECT(chainbase::oid<eos::chain::account_object>, (_id))
FC_REFLECT(eos::chain::shared_authority, (threshold)(accounts)(keys))
FC_REFLECT(eos::chain::account_object, (id)(name)(vm_type)(vm_version)(code_version)(code)(creation_date))
FC_REFLECT(eos::chain::permission_object, (id)(owner)(parent)(name)(auth))
......@@ -23,7 +23,7 @@
*/
#pragma once
#include <eos/chain/types.hpp>
#include <eos/chain/account_object.hpp>
#include <eos/chain/permission_object.hpp>
#include "multi_index_includes.hpp"
......@@ -57,7 +57,7 @@ namespace eos { namespace chain {
OBJECT_CTOR(action_permission_object)
id_type id;
account_id_type owner; ///< the account whose permission we seek
AccountName owner; ///< the account whose permission we seek
permission_object::id_type scope_permission; ///< the scope permission defined by the contract for the action
permission_object::id_type owner_permission; ///< the owner permission that is required
};
......@@ -69,7 +69,7 @@ namespace eos { namespace chain {
ordered_unique<tag<by_id>, member<action_permission_object, action_permission_object::id_type, &action_permission_object::id>>,
ordered_unique<tag<by_owner_scope>,
composite_key< action_permission_object,
member<action_permission_object, account_id_type, &action_permission_object::owner>,
member<action_permission_object, AccountName, &action_permission_object::owner>,
member<action_permission_object, permission_object::id_type, &action_permission_object::scope_permission>
>
>
......
......@@ -2,26 +2,101 @@
#include <eos/chain/types.hpp>
#include <eos/types/generated.hpp>
namespace eos {
inline bool operator < ( const types::AccountPermission& a, const types::AccountPermission& b ) {
return std::tie( a.account, a.permission ) < std::tie( b.account, b.permission );
namespace eos { namespace chain {
struct shared_authority {
shared_authority( chainbase::allocator<char> alloc )
:accounts(alloc),keys(alloc)
{}
shared_authority& operator=(const Authority& a) {
threshold = a.threshold;
accounts = decltype(accounts)(a.accounts.begin(), a.accounts.end(), accounts.get_allocator());
keys = decltype(keys)(a.keys.begin(), a.keys.end(), keys.get_allocator());
return *this;
}
shared_authority& operator=(Authority&& a) {
threshold = a.threshold;
accounts.reserve(a.accounts.size());
for (auto& p : a.accounts)
accounts.emplace_back(std::move(p));
keys.reserve(a.keys.size());
for (auto& p : a.keys)
keys.emplace_back(std::move(p));
return *this;
}
/**
* Makes sure all keys are unique and sorted and all account permissions are unique and sorted
*/
inline bool validate( types::Authority& auth ) {
const types::KeyPermissionWeight* prev = nullptr;
for( const auto& k : auth.keys ) {
if( !prev ) prev = &k;
else if( prev->key < k.key ) return false;
}
const types::AccountPermissionWeight* pa = nullptr;
for( const auto& a : auth.accounts ) {
if( !pa ) pa = &a;
else if( pa->permission < a.permission ) return false;
}
return true;
UInt32 threshold = 0;
shared_vector<types::AccountPermissionWeight> accounts;
shared_vector<types::KeyPermissionWeight> keys;
};
/**
* @brief This class determines whether a set of signing keys are sufficient to satisfy an authority or not
*
* To determine whether an authority is satisfied or not, we first determine which keys have approved of a message, and
* then determine whether that list of keys is sufficient to satisfy the authority. This class takes a list of keys and
* provides the @ref satisfied method to determine whether that list of keys satisfies a provided authority.
*
* @tparam F A callable which takes a single argument of type @ref AccountPermission and returns the corresponding
* authority
*/
template<typename F>
class AuthorityChecker {
F PermissionToAuthority;
const flat_set<public_key_type>& signingKeys;
public:
AuthorityChecker(F PermissionToAuthority, const flat_set<public_key_type>& signingKeys)
: PermissionToAuthority(PermissionToAuthority), signingKeys(signingKeys) {}
bool satisfied(const types::AccountPermission& permission) const {
return satisfied(PermissionToAuthority(permission));
}
template<typename AuthorityType>
bool satisfied(const AuthorityType& authority) const {
UInt32 weight = 0;
for (const auto& kpw : authority.keys)
if (signingKeys.count(kpw.key)) {
weight += kpw.weight;
if (weight >= authority.threshold)
return true;
}
for (const auto& apw : authority.accounts)
#warning TODO: Recursion limit?
if (satisfied(apw.permission)) {
weight += apw.weight;
if (weight >= authority.threshold)
return true;
}
return false;
}
};
inline bool operator < ( const types::AccountPermission& a, const types::AccountPermission& b ) {
return std::tie( a.account, a.permission ) < std::tie( b.account, b.permission );
}
template<typename F>
AuthorityChecker<F> MakeAuthorityChecker(F&& pta, const flat_set<public_key_type>& signingKeys) {
return AuthorityChecker<F>(std::forward<F>(pta), signingKeys);
}
/**
* Makes sure all keys are unique and sorted and all account permissions are unique and sorted
*/
inline bool validate( types::Authority& auth ) {
const types::KeyPermissionWeight* prev = nullptr;
for( const auto& k : auth.keys ) {
if( !prev ) prev = &k;
else if( prev->key < k.key ) return false;
}
const types::AccountPermissionWeight* pa = nullptr;
for( const auto& a : auth.accounts ) {
if( !pa ) pa = &a;
else if( pa->permission < a.permission ) return false;
}
return true;
}
} } // namespace eos::chain
FC_REFLECT(eos::chain::shared_authority, (threshold)(accounts)(keys))
......@@ -42,9 +42,7 @@ namespace eos { namespace chain {
FC_DECLARE_DERIVED_EXCEPTION( black_swan_exception, eos::chain::chain_exception, 3100000, "black swan" )
FC_DECLARE_DERIVED_EXCEPTION( unknown_block_exception, eos::chain::chain_exception, 3110000, "unknown block" )
FC_DECLARE_DERIVED_EXCEPTION( tx_missing_active_auth, eos::chain::transaction_exception, 3030001, "missing required active authority" )
FC_DECLARE_DERIVED_EXCEPTION( tx_missing_owner_auth, eos::chain::transaction_exception, 3030002, "missing required owner authority" )
FC_DECLARE_DERIVED_EXCEPTION( tx_missing_other_auth, eos::chain::transaction_exception, 3030003, "missing required other authority" )
FC_DECLARE_DERIVED_EXCEPTION( tx_missing_auth, eos::chain::transaction_exception, 3030001, "missing required authority" )
FC_DECLARE_DERIVED_EXCEPTION( tx_irrelevant_sig, eos::chain::transaction_exception, 3030004, "irrelevant signature included" )
FC_DECLARE_DERIVED_EXCEPTION( tx_duplicate_sig, eos::chain::transaction_exception, 3030005, "duplicate signature included" )
FC_DECLARE_DERIVED_EXCEPTION( invalid_committee_approval, eos::chain::transaction_exception, 3030006, "committee account cannot directly approve transaction" )
......
/*
* Copyright (c) 2017, Respective Authors.
*
* The MIT License
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#pragma once
#include <eos/chain/authority.hpp>
#include "multi_index_includes.hpp"
namespace eos { namespace chain {
class permission_object : public chainbase::object<permission_object_type, permission_object> {
OBJECT_CTOR(permission_object, (auth) )
id_type id;
AccountName owner; ///< the account this permission belongs to
id_type parent; ///< parent permission
PermissionName name; ///< human-readable name for the permission
shared_authority auth; ///< authority required to execute this permission
};
struct by_parent;
struct by_owner;
struct by_name;
using permission_index = chainbase::shared_multi_index_container<
permission_object,
indexed_by<
ordered_unique<tag<by_id>, member<permission_object, permission_object::id_type, &permission_object::id>>,
ordered_unique<tag<by_parent>,
composite_key<permission_object,
member<permission_object, permission_object::id_type, &permission_object::parent>,
member<permission_object, permission_object::id_type, &permission_object::id>
>
>,
ordered_unique<tag<by_owner>,
composite_key<permission_object,
member<permission_object, AccountName, &permission_object::owner>,
member<permission_object, PermissionName, &permission_object::name>
>
>,
ordered_unique<tag<by_name>,
composite_key<permission_object,
member<permission_object, PermissionName, &permission_object::name>,
member<permission_object, permission_object::id_type, &permission_object::id>
>
>
>
>;
} } // eos::chain
CHAINBASE_SET_INDEX_TYPE(eos::chain::permission_object, eos::chain::permission_index)
FC_REFLECT(chainbase::oid<eos::chain::permission_object>, (_id))
FC_REFLECT(eos::chain::permission_object, (id)(owner)(parent)(name)(auth))
......@@ -27,6 +27,8 @@
#include <fc/smart_ref_impl.hpp>
#include <algorithm>
#include <boost/range/adaptor/transformed.hpp>
namespace eos { namespace chain {
digest_type SignedTransaction::digest()const {
......@@ -50,16 +52,12 @@ eos::chain::transaction_id_type SignedTransaction::id() const {
}
const signature_type& eos::chain::SignedTransaction::sign(const private_key_type& key, const chain_id_type& chain_id) {
digest_type h = sig_digest( chain_id );
signatures.push_back(key.sign_compact(h));
signatures.push_back(key.sign_compact(sig_digest(chain_id)));
return signatures.back();
}
signature_type eos::chain::SignedTransaction::sign(const private_key_type& key, const chain_id_type& chain_id)const {
digest_type::encoder enc;
fc::raw::pack( enc, chain_id );
fc::raw::pack( enc, static_cast<const types::Transaction&>(*this) );
return key.sign_compact(enc.result());
return key.sign_compact(sig_digest(chain_id));
}
void SignedTransaction::set_reference_block(const block_id_type& reference_block) {
......@@ -74,17 +72,13 @@ bool SignedTransaction::verify_reference_block(const block_id_type& reference_bl
flat_set<public_key_type> SignedTransaction::get_signature_keys( const chain_id_type& chain_id )const
{ try {
auto d = sig_digest( chain_id );
flat_set<public_key_type> result;
for( const auto& sig : signatures )
{
EOS_ASSERT(
result.insert( fc::ecc::public_key(sig,d) ).second,
tx_duplicate_sig,
"Duplicate Signature detected" );
}
return result;
} FC_CAPTURE_AND_RETHROW() }
using boost::adaptors::transformed;
auto SigToKey = transformed([digest = sig_digest(chain_id)](const fc::ecc::compact_signature& signature) {
return public_key_type(fc::ecc::public_key(signature, digest));
});
auto keyRange = signatures | SigToKey;
return {keyRange.begin(), keyRange.end()};
} FC_CAPTURE_AND_RETHROW() }
eos::chain::digest_type SignedTransaction::merkle_digest() const {
digest_type::encoder enc;
......
#include <eos/native_contract/system_contract.hpp>
#include <eos/chain/message_handling_contexts.hpp>
#include <eos/chain/permission_object.hpp>
#include <eos/chain/account_object.hpp>
#include <eos/chain/exceptions.hpp>
#include <eos/chain/global_property_object.hpp>
......@@ -50,9 +51,9 @@ void validate_system_newaccount(message_validate_context& context) {
EOS_ASSERT(context.msg.has_notify(config::StakedBalanceContractName), message_validate_exception,
"Must notify Staked Balance Contract (${name})", ("name", config::StakedBalanceContractName));
EOS_ASSERT( eos::validate(create.owner), message_validate_exception, "Invalid owner authority");
EOS_ASSERT( eos::validate(create.active), message_validate_exception, "Invalid active authority");
EOS_ASSERT( eos::validate(create.recovery), message_validate_exception, "Invalid recovery authority");
EOS_ASSERT( validate(create.owner), message_validate_exception, "Invalid owner authority");
EOS_ASSERT( validate(create.active), message_validate_exception, "Invalid active authority");
EOS_ASSERT( validate(create.recovery), message_validate_exception, "Invalid recovery authority");
}
void precondition_system_newaccount(precondition_validate_context& context) {
......
......@@ -18,6 +18,8 @@ namespace eos {
void plugin_startup();
void plugin_shutdown();
void broadcast_block(const chain::signed_block &sb);
private:
std::unique_ptr<class net_plugin_impl> my;
};
......
......@@ -3,6 +3,7 @@
#include <eos/net_plugin/net_plugin.hpp>
#include <eos/net_plugin/protocol.hpp>
#include <eos/chain/chain_controller.hpp>
#include <eos/chain/exceptions.hpp>
#include <fc/network/ip.hpp>
#include <fc/io/raw.hpp>
......@@ -42,7 +43,7 @@ struct node_transaction_state {
struct transaction_state {
transaction_id_type id;
bool is_known_by_peer = false; ///< true if we sent or received this trx to this peer or received notice from peer
bool is_noticed_to_peer = false; ///< have we sent peer noitce we know it (true if we reeive from this peer)
bool is_noticed_to_peer = false; ///< have we sent peer notice we know it (true if we receive from this peer)
uint32_t block_num = -1; ///< the block number the transaction was included in
time_point validated_time; ///< infinity for unvalidated
time_point requested_time; /// incase we fetch large trx
......@@ -119,8 +120,12 @@ public:
out_queue.push_back( m );
if( out_queue.size() == 1 )
send_next_message();
else {
dlog ("send: out_queue size = ${s}", ("s",out_queue.size()));
}
}
void send_next_message() {
if( !out_queue.size() ) {
if (out_sync_state.size() > 0) {
......@@ -140,7 +145,6 @@ public:
boost::asio::async_write( *socket, boost::asio::buffer( buffer.data(), buffer.size() ),
[this,buf=std::move(buffer)]( boost::system::error_code ec, std::size_t bytes_transferred ) {
ilog( "write message handler..." );
if( ec ) {
elog( "Error sending message: ${msg}", ("msg",ec.message() ) );
} else {
......@@ -152,7 +156,6 @@ public:
void write_block_backlog ( ) {
try {
ilog ("write loop sending backlog ");
if (out_sync_state.size() > 0) {
chain_controller& cc = app().find_plugin<chain_plugin>()->chain();
auto ss = out_sync_state.begin();
......@@ -160,6 +163,7 @@ public:
num <= ss->end_block; num++) {
fc::optional<signed_block> sb = cc.fetch_block_by_number(num);
if (sb) {
dlog("write backlog, block #${num}",("num",num));
send( *sb );
}
ss.get_node()->value().last = num;
......@@ -194,19 +198,20 @@ class net_plugin_impl {
chain_plugin* chain_plug;
void connect( const string& ep ) {
auto host = ep.substr( 0, ep.find(':') );
auto port = ep.substr( host.size()+1, host.size() );
void connect( const string& peer_addr ) {
auto host = peer_addr.substr( 0, peer_addr.find(':') );
auto port = peer_addr.substr( host.size()+1, host.size() );
idump((host)(port));
auto resolver = std::make_shared<tcp::resolver>( std::ref( app().get_io_service() ) );
tcp::resolver::query query( tcp::v4(), host.c_str(), port.c_str() );
// Note: need to add support for IPv6 too
resolver->async_resolve( query,
[resolver,ep,this]( const boost::system::error_code& err, tcp::resolver::iterator endpoint_itr ){
[resolver,peer_addr,this]( const boost::system::error_code& err, tcp::resolver::iterator endpoint_itr ){
if( !err ) {
connect( resolver, endpoint_itr );
} else {
elog( "Unable to resolve ${ep}: ${error}", ( "ep", ep )("error", err.message() ) );
elog( "Unable to resolve ${peer_addr}: ${error}", ( "peer_addr", peer_addr )("error", err.message() ) );
}
});
}
......@@ -271,12 +276,21 @@ class net_plugin_impl {
hello->os = "other";
#endif
hello->agent = user_agent_name;
update_handshake ();
}
void update_handshake () {
hello->last_irreversible_block_id = chain_plug->chain().get_block_id_for_num
(hello->last_irreversible_block_num = chain_plug->chain().last_irreversible_block_num());
try {
hello->last_irreversible_block_id = chain_plug->chain().get_block_id_for_num
(hello->last_irreversible_block_num = chain_plug->chain().last_irreversible_block_num());
ilog ("update_handshake my libnum = ${n}",("n",hello->last_irreversible_block_num));
}
catch (const unknown_block_exception &ex) {
hello->last_irreversible_block_id = fc::sha256::hash(0);
hello->last_irreversible_block_num = 0;
ilog ("update_handshake my libnum = ${n}",("n",hello->last_irreversible_block_num));
}
}
void start_session( connection* con ) {
......@@ -327,7 +341,14 @@ class net_plugin_impl {
);
}
void handle_message (connection &c, handshake_message &msg) {
template<typename T>
void send_all (const T &msg) {
for (auto &c : connections) {
c->send(msg);
}
}
void handle_message (connection &c, const handshake_message &msg) {
if (!hello) {
init_handshake();
}
......@@ -349,6 +370,7 @@ class net_plugin_impl {
}
chain_controller& cc = chain_plug->chain();
uint32_t head = cc.head_block_num ();
ilog ("My head block = ${h} their lib = ${lib}", ("h",head)("lib", msg.last_irreversible_block_num));
if ( msg.last_irreversible_block_num > head) {
uint32_t delta = msg.last_irreversible_block_num - head;
uint32_t count = connections.size();
......@@ -373,47 +395,68 @@ class net_plugin_impl {
}
void handle_message (connection &c, peer_message &msg) {
void handle_message (connection &c, const peer_message &msg) {
ilog ("got a peer message");
}
void handle_message (connection &c, notice_message &msg) {
void handle_message (connection &c, const notice_message &msg) {
ilog ("got a notice message");
}
void handle_message (connection &c, sync_request_message &msg) {
void handle_message (connection &c, const sync_request_message &msg) {
ilog ("got a sync request message for blocks ${s} to ${e}", ("s",msg.start_block)("e", msg.end_block));
sync_state req = {msg.start_block,msg.end_block,0,time_point::now()};
c.out_sync_state.insert (req);
c.write_block_backlog ();
}
void handle_message (connection &c, block_summary_message &msg) {
void handle_message (connection &c, const block_summary_message &msg) {
ilog ("got a block summary message");
}
void handle_message (connection &c, SignedTransaction &msg) {
void handle_message (connection &c, const SignedTransaction &msg) {
ilog ("got a SignedTransacton");
chain_plug->accept_transaction (msg);
}
void handle_message (connection &c, signed_block &msg) {
void handle_message (connection &c, const signed_block &msg) {
uint32_t bn = msg.block_num();
ilog ("got a signed_block, num = ${n}", ("n", bn));
dlog ("got a signed_block, num = ${n}", ("n", bn));
chain_controller &cc = chain_plug->chain();
if (cc.is_known_block(msg.id())) {
ilog ("block id ${id} is known", ("id", msg.id()) );
dlog ("block id ${id} is known", ("id", msg.id()) );
return;
}
uint32_t num = msg.block_num();
bool syncing = false;
for (auto &ss: c.in_sync_state) {
if (num >= ss.end_block) {
continue;
}
const_cast<sync_state&>(ss).last = num;
syncing = true;
break;
}
// TODO: add block to global state
if (!syncing) {
try {
block_id_type id = cc.get_block_id_for_num (num-1);
dlog ("got the prevous block id = ${id}",("id",id));
}
catch (const unknown_block_exception &ex) {
uint32_t head = cc.head_block_num();
dlog ("block num ${n} is not known, head = ${h}",("n",(num-1))("h",head));
sync_state req = {head+1, num-1, 0, time_point::now() };
c.in_sync_state.insert (req);
sync_request_message srm = {req.start_block, req.end_block };
c.send (srm);
syncing = true;
}
}
chain_plug->accept_block(msg, syncing);
}
......@@ -422,37 +465,8 @@ class net_plugin_impl {
connection &c;
msgHandler (net_plugin_impl &imp, connection &conn) : impl(imp), c(conn) {}
void operator()(handshake_message &msg)
{
impl.handle_message (c, msg);
}
void operator()(peer_message &msg)
{
impl.handle_message (c, msg);
}
void operator()(notice_message &msg)
{
impl.handle_message (c, msg);
}
void operator()(sync_request_message &msg)
{
impl.handle_message (c, msg);
}
void operator()(block_summary_message &msg)
{
impl.handle_message (c, msg);
}
void operator()(SignedTransaction &msg)
{
impl.handle_message (c, msg);
}
void operator()(signed_block &msg)
template <typename T>
void operator()(const T &msg) const
{
impl.handle_message (c, msg);
}
......@@ -507,6 +521,7 @@ void net_plugin::set_program_options( options_description& cli, options_descript
("listen-endpoint", bpo::value<string>()->default_value( "127.0.0.1:9876" ), "The local IP address and port to listen for incoming connections.")
("remote-endpoint", bpo::value< vector<string> >()->composing(), "The IP address and port of a remote peer to sync with.")
("public-endpoint", bpo::value<string>()->default_value( "0.0.0.0:9876" ), "The public IP address and port that should be advertized to peers.")
("agent-name", bpo::value<string>()->default_value("EOS Test Agent"), "The name supplied to identify this node amongst the peers.")
;
}
......@@ -524,14 +539,16 @@ void net_plugin::plugin_initialize( const variables_map& options ) {
if( options.count( "remote-endpoint" ) ) {
my->seed_nodes = options.at( "remote-endpoint" ).as< vector<string> >();
}
my->user_agent_name = "EOS Test Agent";
if (options.count("agent-name")) {
my->user_agent_name = options.at ("agent-name").as< string > ();
}
my->chain_plug = app().find_plugin<chain_plugin>();
}
void net_plugin::plugin_startup() {
// boost::asio::ip::tcp::endpoint endpoint(boost::asio::ip::tcp::v4(), port);
if( my->acceptor ) {
my->acceptor->open(my->listen_endpoint.protocol());
my->acceptor->set_option(tcp::acceptor::reuse_address(true));
my->acceptor->bind(my->listen_endpoint);
......@@ -569,4 +586,8 @@ try {
ilog( "exit shutdown" );
} FC_CAPTURE_AND_RETHROW() }
void net_plugin::broadcast_block (const chain::signed_block &sb) {
my->send_all (sb);
}
}
......@@ -5,7 +5,7 @@ add_library( producer_plugin
${HEADERS}
)
target_link_libraries( producer_plugin chain_plugin appbase eos_chain eos_utilities )
target_link_libraries( producer_plugin net_plugin chain_plugin appbase eos_chain eos_utilities )
target_include_directories( producer_plugin
PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/include" )
......
......@@ -22,6 +22,7 @@
* THE SOFTWARE.
*/
#include <eos/producer_plugin/producer_plugin.hpp>
#include <eos/net_plugin/net_plugin.hpp>
#include <eos/chain/producer_object.hpp>
......@@ -304,7 +305,7 @@ block_production_condition::block_production_condition_enum producer_plugin_impl
);
capture("n", block.block_num())("t", block.timestamp)("c", now);
// app().get_plugin<p2p_plugin>().broadcast_block(block);
app().get_plugin<net_plugin>().broadcast_block(block);
return block_production_condition::produced;
}
......
......@@ -9,3 +9,7 @@ endif()
file(GLOB UNIT_TESTS "tests/*.cpp")
add_executable( chain_test ${UNIT_TESTS} ${COMMON_SOURCES} )
target_link_libraries( chain_test eos_native_contract eos_chain chainbase eos_utilities eos_egenesis_none fc ${PLATFORM_SPECIFIC_LIBS} )
file(GLOB SLOW_TESTS "slow_tests/*.cpp")
add_executable( slow_test ${SLOW_TESTS} ${COMMON_SOURCES} )
target_link_libraries( slow_test eos_native_contract eos_chain chainbase eos_utilities eos_egenesis_none fc ${PLATFORM_SPECIFIC_LIBS} )
此差异已折叠。
此差异已折叠。
#include <eos/chain/BlockchainConfiguration.hpp>
#include <eos/chain/authority.hpp>
#include <eos/utilities/rand.hpp>
......@@ -72,9 +73,62 @@ BOOST_AUTO_TEST_CASE(deterministic_distributions)
rng.shuffle(nums);
std::vector<int> c{1, 0, 2};
BOOST_CHECK(std::equal(nums.begin(), nums.end(), c.begin()));
} FC_LOG_AND_RETHROW() }
BOOST_AUTO_TEST_CASE(authority_checker)
{ try {
#define KEY(x) auto x = fc::ecc::private_key::regenerate(fc::sha256::hash(#x)).get_public_key()
KEY(a);
KEY(b);
KEY(c);
auto GetNullAuthority = [](auto){return Authority();};
Authority A(2, {{a, 1}, {b, 1}}, {});
BOOST_CHECK(MakeAuthorityChecker(GetNullAuthority, {a, b}).satisfied(A));
BOOST_CHECK(MakeAuthorityChecker(GetNullAuthority, {a, b, c}).satisfied(A));
BOOST_CHECK(!MakeAuthorityChecker(GetNullAuthority, {a, c}).satisfied(A));
BOOST_CHECK(!MakeAuthorityChecker(GetNullAuthority, {b, c}).satisfied(A));
A = Authority(3, {{a,1},{b,1},{c,1}}, {});
BOOST_CHECK(MakeAuthorityChecker(GetNullAuthority, {c, b, a}).satisfied(A));
BOOST_CHECK(!MakeAuthorityChecker(GetNullAuthority, {a, b}).satisfied(A));
BOOST_CHECK(!MakeAuthorityChecker(GetNullAuthority, {a, c}).satisfied(A));
BOOST_CHECK(!MakeAuthorityChecker(GetNullAuthority, {b, c}).satisfied(A));
A = Authority(1, {{a, 1}, {b, 1}}, {});
BOOST_CHECK(MakeAuthorityChecker(GetNullAuthority, {a}).satisfied(A));
BOOST_CHECK(MakeAuthorityChecker(GetNullAuthority, {b}).satisfied(A));
BOOST_CHECK(!MakeAuthorityChecker(GetNullAuthority, {c}).satisfied(A));
A = Authority(1, {{a, 2}, {b, 1}}, {});
BOOST_CHECK(MakeAuthorityChecker(GetNullAuthority, {a}).satisfied(A));
BOOST_CHECK(MakeAuthorityChecker(GetNullAuthority, {b}).satisfied(A));
BOOST_CHECK(!MakeAuthorityChecker(GetNullAuthority, {c}).satisfied(A));
auto GetCAuthority = [c](auto){return Authority(1, {{c, 1}}, {});};
A = Authority(2, {{a, 2}, {b, 1}}, {{{"hello", "world"}, 1}});
BOOST_CHECK(MakeAuthorityChecker(GetCAuthority, {a}).satisfied(A));
BOOST_CHECK(!MakeAuthorityChecker(GetCAuthority, {b}).satisfied(A));
BOOST_CHECK(!MakeAuthorityChecker(GetCAuthority, {c}).satisfied(A));
BOOST_CHECK(MakeAuthorityChecker(GetCAuthority, {b,c}).satisfied(A));
A = Authority(2, {{a, 1}, {b, 1}}, {{{"hello", "world"}, 1}});
BOOST_CHECK(!MakeAuthorityChecker(GetCAuthority, {a}).satisfied(A));
BOOST_CHECK(!MakeAuthorityChecker(GetCAuthority, {b}).satisfied(A));
BOOST_CHECK(!MakeAuthorityChecker(GetCAuthority, {c}).satisfied(A));
BOOST_CHECK(MakeAuthorityChecker(GetCAuthority, {a,b}).satisfied(A));
BOOST_CHECK(MakeAuthorityChecker(GetCAuthority, {b,c}).satisfied(A));
BOOST_CHECK(MakeAuthorityChecker(GetCAuthority, {a,c}).satisfied(A));
A = Authority(2, {{a, 1}, {b, 1}}, {{{"hello", "world"}, 2}});
BOOST_CHECK(MakeAuthorityChecker(GetCAuthority, {a,b}).satisfied(A));
BOOST_CHECK(MakeAuthorityChecker(GetCAuthority, {c}).satisfied(A));
BOOST_CHECK(!MakeAuthorityChecker(GetCAuthority, {a}).satisfied(A));
BOOST_CHECK(!MakeAuthorityChecker(GetCAuthority, {b}).satisfied(A));
} FC_LOG_AND_RETHROW() }
BOOST_AUTO_TEST_SUITE_END()
......
......@@ -2,7 +2,7 @@
#include <eos/chain/chain_controller.hpp>
#include <eos/chain/exceptions.hpp>
#include <eos/chain/account_object.hpp>
#include <eos/chain/permission_object.hpp>
#include <eos/chain/key_value_object.hpp>
#include <eos/native_contract/producer_objects.hpp>
......@@ -76,70 +76,6 @@ BOOST_FIXTURE_TEST_CASE(create_account, testing_fixture)
}
} FC_LOG_AND_RETHROW() }
// Verify that staking and unstaking works
BOOST_FIXTURE_TEST_CASE(stake, testing_fixture)
{ try {
// Create account sam with default balance of 100, and stake 55 of it
Make_Blockchain(chain);
Make_Account(chain, sam);
Transfer_Asset(chain, inita, sam, Asset(55) );
// MakeAccount should start sam out with some staked balance
BOOST_REQUIRE_EQUAL(chain.get_staked_balance("sam"), Asset(100).amount);
Stake_Asset(chain, sam, Asset(55).amount);
// Check balances
BOOST_CHECK_EQUAL(chain.get_staked_balance("sam"), Asset(155).amount);
BOOST_CHECK_EQUAL(chain.get_unstaking_balance("sam"), Asset(0).amount);
BOOST_CHECK_EQUAL(chain.get_liquid_balance("sam"), Asset(0).amount);
chain.produce_blocks();
// Start unstaking 20, check balances
BOOST_CHECK_THROW(Begin_Unstake_Asset(chain, sam, Asset(156).amount), chain::message_precondition_exception);
Begin_Unstake_Asset(chain, sam, Asset(20).amount);
BOOST_CHECK_EQUAL(chain.get_staked_balance("sam"), Asset(135).amount);
BOOST_CHECK_EQUAL(chain.get_unstaking_balance("sam"), Asset(20).amount);
BOOST_CHECK_EQUAL(chain.get_liquid_balance("sam"), Asset(0).amount);
// Make sure we can't liquidate early
BOOST_CHECK_THROW(Finish_Unstake_Asset(chain, sam, Asset(10).amount), chain::message_precondition_exception);
// Fast forward to when we can liquidate
wlog("Hang on, this will take a minute...");
chain.produce_blocks(config::StakedBalanceCooldownSeconds / config::BlockIntervalSeconds + 1);
BOOST_CHECK_THROW(Finish_Unstake_Asset(chain, sam, Asset(21).amount), chain::message_precondition_exception);
BOOST_CHECK_EQUAL(chain.get_staked_balance("sam"), Asset(135).amount);
BOOST_CHECK_EQUAL(chain.get_unstaking_balance("sam"), Asset(20).amount);
BOOST_CHECK_EQUAL(chain.get_liquid_balance("sam"), Asset(0).amount);
// Liquidate 10 of the 20 unstaking and check balances
Finish_Unstake_Asset(chain, sam, Asset(10).amount);
BOOST_CHECK_EQUAL(chain.get_staked_balance("sam"), Asset(135).amount);
BOOST_CHECK_EQUAL(chain.get_unstaking_balance("sam"), Asset(10).amount);
BOOST_CHECK_EQUAL(chain.get_liquid_balance("sam"), Asset(10).amount);
// Liquidate 2 of the 10 left unstaking and check balances
Finish_Unstake_Asset(chain, sam, Asset(2).amount);
BOOST_CHECK_EQUAL(chain.get_staked_balance("sam"), Asset(135).amount);
BOOST_CHECK_EQUAL(chain.get_unstaking_balance("sam"), Asset(8).amount);
BOOST_CHECK_EQUAL(chain.get_liquid_balance("sam"), Asset(12).amount);
// Ignore the 8 left in unstaking, and begin unstaking 5, which should restake the 8, and start over unstaking 5
Begin_Unstake_Asset(chain, sam, Asset(5).amount);
BOOST_CHECK_EQUAL(chain.get_staked_balance("sam"), Asset(138).amount);
BOOST_CHECK_EQUAL(chain.get_unstaking_balance("sam"), Asset(5).amount);
BOOST_CHECK_EQUAL(chain.get_liquid_balance("sam"), Asset(12).amount);
// Begin unstaking 20, which should only deduct 15 from staked, since 5 was already in unstaking
Begin_Unstake_Asset(chain, sam, Asset(20).amount);
BOOST_CHECK_EQUAL(chain.get_staked_balance("sam"), Asset(123).amount);
BOOST_CHECK_EQUAL(chain.get_unstaking_balance("sam"), Asset(20).amount);
BOOST_CHECK_EQUAL(chain.get_liquid_balance("sam"), Asset(12).amount);
} FC_LOG_AND_RETHROW() }
// Simple test to verify a simple transfer transaction works
BOOST_FIXTURE_TEST_CASE(transfer, testing_fixture)
{ try {
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册