提交 5df4a75a 编写于 作者: B Bart Wyatt

merging changes to master @6c355fbf ref EOSIO/eos#203

......@@ -8,7 +8,8 @@
*.wasm
*.s
*.dot
\#*
\.#*
CMakeCache.txt
CMakeFiles
cmake_install.cmake
......
......@@ -15,107 +15,107 @@
"name": "inita",
"owner_key": "EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV",
"active_key": "EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV",
"liquid_balance": "1000000.00000000 EOS"
"liquid_balance": "1000000.0000 EOS"
},{
"name": "initb",
"owner_key": "EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV",
"active_key": "EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV",
"liquid_balance": "1000000.00000000 EOS"
"liquid_balance": "1000000.0000 EOS"
},{
"name": "initc",
"owner_key": "EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV",
"active_key": "EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV",
"liquid_balance": "1000000.00000000 EOS"
"liquid_balance": "1000000.0000 EOS"
},{
"name": "initd",
"owner_key": "EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV",
"active_key": "EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV",
"liquid_balance": "1000000.00000000 EOS"
"liquid_balance": "1000000.0000 EOS"
},{
"name": "inite",
"owner_key": "EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV",
"active_key": "EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV",
"liquid_balance": "1000000.00000000 EOS"
"liquid_balance": "1000000.0000 EOS"
},{
"name": "initf",
"owner_key": "EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV",
"active_key": "EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV",
"liquid_balance": "1000000.00000000 EOS"
"liquid_balance": "1000000.0000 EOS"
},{
"name": "initg",
"owner_key": "EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV",
"active_key": "EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV",
"liquid_balance": "1000000.00000000 EOS"
"liquid_balance": "1000000.0000 EOS"
},{
"name": "inith",
"owner_key": "EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV",
"active_key": "EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV",
"liquid_balance": "1000000.00000000 EOS"
"liquid_balance": "1000000.0000 EOS"
},{
"name": "initi",
"owner_key": "EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV",
"active_key": "EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV",
"liquid_balance": "1000000.00000000 EOS"
"liquid_balance": "1000000.0000 EOS"
},{
"name": "initj",
"owner_key": "EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV",
"active_key": "EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV",
"liquid_balance": "1000000.00000000 EOS"
"liquid_balance": "1000000.0000 EOS"
},{
"name": "initk",
"owner_key": "EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV",
"active_key": "EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV",
"liquid_balance": "1000000.00000000 EOS"
"liquid_balance": "1000000.0000 EOS"
},{
"name": "initl",
"owner_key": "EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV",
"active_key": "EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV",
"liquid_balance": "1000000.00000000 EOS"
"liquid_balance": "1000000.0000 EOS"
},{
"name": "initm",
"owner_key": "EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV",
"active_key": "EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV",
"liquid_balance": "1000000.00000000 EOS"
"liquid_balance": "1000000.0000 EOS"
},{
"name": "initn",
"owner_key": "EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV",
"active_key": "EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV",
"liquid_balance": "1000000.00000000 EOS"
"liquid_balance": "1000000.0000 EOS"
},{
"name": "inito",
"owner_key": "EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV",
"active_key": "EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV",
"liquid_balance": "1000000.00000000 EOS"
"liquid_balance": "1000000.0000 EOS"
},{
"name": "initp",
"owner_key": "EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV",
"active_key": "EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV",
"liquid_balance": "1000000.00000000 EOS"
"liquid_balance": "1000000.0000 EOS"
},{
"name": "initq",
"owner_key": "EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV",
"active_key": "EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV",
"liquid_balance": "1000000.00000000 EOS"
"liquid_balance": "1000000.0000 EOS"
},{
"name": "initr",
"owner_key": "EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV",
"active_key": "EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV",
"liquid_balance": "1000000.00000000 EOS"
"liquid_balance": "1000000.0000 EOS"
},{
"name": "inits",
"owner_key": "EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV",
"active_key": "EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV",
"liquid_balance": "1000000.00000000 EOS"
"liquid_balance": "1000000.0000 EOS"
},{
"name": "initt",
"owner_key": "EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV",
"active_key": "EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV",
"liquid_balance": "1000000.00000000 EOS"
"liquid_balance": "1000000.0000 EOS"
},{
"name": "initu",
"owner_key": "EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV",
"active_key": "EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV",
"liquid_balance": "1000000.00000000 EOS"
"liquid_balance": "1000000.0000 EOS"
}],
"initial_producers": [{
"owner_name": "inita",
......
......@@ -45,7 +45,7 @@ const static AccountName ProducersAccountName = N(producers);
const static PermissionName ActiveName = N(active);
const static PermissionName OwnerName = N(owner);
const static ShareType InitialTokenSupply = Asset::fromString("90000000.00000000 EOS").amount;
const static ShareType InitialTokenSupply = Asset::fromString("90000000.0000 EOS").amount;
const static int BlockIntervalSeconds = 3;
......
......@@ -174,6 +174,7 @@ namespace eos { namespace chain {
generated_transaction_object_type,
producer_object_type,
chain_property_object_type,
account_control_history_object_type, ///< Defined by account_history_plugin
account_transaction_history_object_type, ///< Defined by account_history_plugin
transaction_history_object_type, ///< Defined by account_history_plugin
public_key_history_object_type, ///< Defined by account_history_plugin
......@@ -225,6 +226,7 @@ FC_REFLECT_ENUM(eos::chain::object_type,
(generated_transaction_object_type)
(producer_object_type)
(chain_property_object_type)
(account_control_history_object_type)
(account_transaction_history_object_type)
(transaction_history_object_type)
(public_key_history_object_type)
......
......@@ -3,7 +3,7 @@
#include <eos/types/native.hpp>
/// eos with 8 digits of precision
#define EOS_SYMBOL (int64_t(5) | (uint64_t('E') << 8) | (uint64_t('O') << 16) | (uint64_t('S') << 24))
#define EOS_SYMBOL (int64_t(4) | (uint64_t('E') << 8) | (uint64_t('O') << 16) | (uint64_t('S') << 24))
/// Defined to be largest power of 10 that fits in 53 bits of precision
#define EOS_MAX_SHARE_SUPPLY int64_t(1'000'000'000'000'000ll)
......
......@@ -41,7 +41,8 @@ void account_history_api_plugin::plugin_startup() {
app().get_plugin<http_plugin>().add_api({
CHAIN_RO_CALL(get_transaction),
CHAIN_RO_CALL(get_transactions),
CHAIN_RO_CALL(get_key_accounts)
CHAIN_RO_CALL(get_key_accounts),
CHAIN_RO_CALL(get_controlled_accounts)
});
}
......
#include <eos/account_history_plugin/account_history_plugin.hpp>
#include <eos/account_history_plugin/account_control_history_object.hpp>
#include <eos/account_history_plugin/account_transaction_history_object.hpp>
#include <eos/account_history_plugin/public_key_history_object.hpp>
#include <eos/account_history_plugin/transaction_history_object.hpp>
......@@ -25,6 +26,7 @@ namespace eos {
using chain::AccountName;
using chain::block_id_type;
using chain::PermissionName;
using chain::ProcessedTransaction;
using chain::signed_block;
using boost::multi_index_container;
......@@ -38,6 +40,7 @@ public:
ProcessedTransaction get_transaction(const chain::transaction_id_type& transaction_id) const;
get_transactions_results get_transactions(const AccountName& account_name, const optional<uint32_t>& skip_seq, const optional<uint32_t>& num_seq) const;
vector<AccountName> get_key_accounts(const public_key_type& public_key) const;
vector<AccountName> get_controlled_accounts(const AccountName& controlling_account) const;
void applied_block(const signed_block&);
chain_plugin* chain_plug;
......@@ -60,7 +63,20 @@ private:
bool is_scope_relevant(const eos::types::Vector<AccountName>& scope);
get_transactions_results ordered_transactions(const block_transaction_id_map& block_transaction_ids, const fc::time_point& start_time, const uint32_t begin, const uint32_t end) const;
static void add(chainbase::database& db, const vector<types::KeyPermissionWeight>& keys, const AccountName& account_name, const PermissionName& permission);
static void remove(chainbase::database& db, const AccountName& account_name, const PermissionName& permission);
template<typename MultiIndex, typename LookupType>
static void remove(chainbase::database& db, const AccountName& account_name, const PermissionName& permission)
{
const auto& idx = db.get_index<MultiIndex, LookupType>();
auto& mutatable_idx = db.get_mutable_index<MultiIndex>();
auto range = idx.equal_range( boost::make_tuple( account_name, permission ) );
for (auto acct_perm = range.first; acct_perm != range.second; ++acct_perm)
{
mutatable_idx.remove(*acct_perm);
}
}
static void add(chainbase::database& db, const vector<types::AccountPermissionWeight>& controlling_accounts, const AccountName& account_name, const PermissionName& permission);
bool time_exceeded(const fc::time_point& start_time) const;
static const AccountName NEW_ACCOUNT;
static const AccountName UPDATE_AUTH;
......@@ -252,6 +268,21 @@ vector<AccountName> account_history_plugin_impl::get_key_accounts(const public_k
return vector<AccountName>(accounts.begin(), accounts.end());
}
vector<AccountName> account_history_plugin_impl::get_controlled_accounts(const AccountName& controlling_account) const
{
std::set<AccountName> accounts;
const auto& db = chain_plug->chain().get_database();
db.with_read_lock( [&]() {
const auto& account_control_idx = db.get_index<account_control_history_multi_index, by_controlling>();
auto range = account_control_idx.equal_range( controlling_account );
for (auto obj = range.first; obj != range.second; ++obj)
{
accounts.insert(obj->controlled_account);
}
} );
return vector<AccountName>(accounts.begin(), accounts.end());
}
void account_history_plugin_impl::applied_block(const signed_block& block)
{
const auto block_id = block.id();
......@@ -286,22 +317,30 @@ void account_history_plugin_impl::applied_block(const signed_block& block)
if (msg.type == NEW_ACCOUNT)
{
const auto create = msg.as<types::newaccount>();
auto count = create.owner.keys.size() + create.active.keys.size() + create.recovery.keys.size();
add(db, create.owner.keys, create.name, OWNER);
add(db, create.active.keys, create.name, ACTIVE);
add(db, create.recovery.keys, create.name, RECOVERY);
add(db, create.owner.accounts, create.name, OWNER);
add(db, create.active.accounts, create.name, ACTIVE);
add(db, create.recovery.accounts, create.name, RECOVERY);
}
else if (msg.type == UPDATE_AUTH)
{
const auto update = msg.as<types::updateauth>();
remove(db, update.account, update.permission);
remove<public_key_history_multi_index, by_account_permission>(db, update.account, update.permission);
add(db, update.authority.keys, update.account, update.permission);
remove<account_control_history_multi_index, by_controlled_authority>(db, update.account, update.permission);
add(db, update.authority.accounts, update.account, update.permission);
}
else if (msg.type == DELETE_AUTH)
{
const auto del = msg.as<types::deleteauth>();
remove(db, del.account, del.permission);
}
remove<public_key_history_multi_index, by_account_permission>(db, del.account, del.permission);
remove<account_control_history_multi_index, by_controlled_authority>(db, del.account, del.permission);
}
}
}
}
......@@ -321,15 +360,15 @@ void account_history_plugin_impl::add(chainbase::database& db, const vector<type
}
}
void account_history_plugin_impl::remove(chainbase::database& db, const AccountName& account_name, const PermissionName& permission)
void account_history_plugin_impl::add(chainbase::database& db, const vector<types::AccountPermissionWeight>& controlling_accounts, const AccountName& account_name, const PermissionName& permission)
{
const auto& acct_perm_idx = db.get_index<public_key_history_multi_index, by_account_permission>();
auto& mutatable_acct_perm_idx = db.get_mutable_index<public_key_history_multi_index>();
auto range = acct_perm_idx.equal_range( boost::make_tuple( account_name, permission ) );
for (auto acct_perm = range.first; acct_perm != range.second; ++acct_perm)
for (auto controlling_account : controlling_accounts )
{
mutatable_acct_perm_idx.remove(*acct_perm);
db.create<account_control_history_object>([&](account_control_history_object& obj) {
obj.controlled_account = account_name;
obj.controlled_permission = permission;
obj.controlling_account = controlling_account.permission.account;
});
}
}
......@@ -378,6 +417,7 @@ void account_history_plugin::plugin_startup()
{
my->chain_plug = app().find_plugin<chain_plugin>();
auto& db = my->chain_plug->chain().get_mutable_database();
db.add_index<account_control_history_multi_index>();
db.add_index<account_transaction_history_multi_index>();
db.add_index<public_key_history_multi_index>();
db.add_index<transaction_history_multi_index>();
......@@ -408,5 +448,11 @@ read_only::get_key_accounts_results read_only::get_key_accounts(const get_key_ac
{
return { account_history->get_key_accounts(params.public_key) };
}
read_only::get_controlled_accounts_results read_only::get_controlled_accounts(const get_controlled_accounts_params& params) const
{
return { account_history->get_controlled_accounts(params.controlling_account) };
}
} // namespace account_history_apis
} // namespace eos
#pragma once
#include <chainbase/chainbase.hpp>
#include <eos/chain/types.hpp>
namespace eos {
using chain::AccountName;
using chain::PermissionName;
using chain::shared_vector;
using chain::transaction_id_type;
using namespace boost::multi_index;
class account_control_history_object : public chainbase::object<chain::account_control_history_object_type, account_control_history_object> {
OBJECT_CTOR(account_control_history_object)
id_type id;
AccountName controlled_account;
PermissionName controlled_permission;
AccountName controlling_account;
};
struct by_id;
struct by_controlling;
struct by_controlled_authority;
using account_control_history_multi_index = chainbase::shared_multi_index_container<
account_control_history_object,
indexed_by<
ordered_unique<tag<by_id>, BOOST_MULTI_INDEX_MEMBER(account_control_history_object, account_control_history_object::id_type, id)>,
hashed_non_unique<tag<by_controlling>, BOOST_MULTI_INDEX_MEMBER(account_control_history_object, AccountName, controlling_account), std::hash<AccountName>>,
hashed_non_unique<tag<by_controlled_authority>,
composite_key< account_control_history_object,
member<account_control_history_object, AccountName, &account_control_history_object::controlled_account>,
member<account_control_history_object, PermissionName, &account_control_history_object::controlled_permission>
>,
composite_key_hash< std::hash<AccountName>, std::hash<PermissionName> >
>
>
>;
typedef chainbase::generic_index<account_control_history_multi_index> account_control_history_index;
}
CHAINBASE_SET_INDEX_TYPE( eos::account_control_history_object, eos::account_control_history_multi_index )
FC_REFLECT( eos::account_control_history_object, (controlled_account)(controlled_permission)(controlling_account) )
......@@ -26,6 +26,7 @@ public:
read_only(account_history_const_ptr&& account_history)
: account_history(account_history) {}
struct get_transaction_params {
chain::transaction_id_type transaction_id;
};
......@@ -35,6 +36,7 @@ public:
};
get_transaction_results get_transaction(const get_transaction_params& params) const;
struct get_transactions_params {
chain::AccountName account_name;
optional<uint32_t> skip_seq;
......@@ -52,6 +54,7 @@ public:
get_transactions_results get_transactions(const get_transactions_params& params) const;
struct get_key_accounts_params {
chain::public_key_type public_key;
};
......@@ -59,6 +62,15 @@ public:
vector<chain::AccountName> account_names;
};
get_key_accounts_results get_key_accounts(const get_key_accounts_params& params) const;
struct get_controlled_accounts_params {
chain::AccountName controlling_account;
};
struct get_controlled_accounts_results {
vector<chain::AccountName> controlled_accounts;
};
get_controlled_accounts_results get_controlled_accounts(const get_controlled_accounts_params& params) const;
};
class read_write {
......@@ -99,3 +111,5 @@ FC_REFLECT(eos::account_history_apis::read_only::ordered_transaction_results, (s
FC_REFLECT(eos::account_history_apis::read_only::get_transactions_results, (transactions)(time_limit_exceeded_error) )
FC_REFLECT(eos::account_history_apis::read_only::get_key_accounts_params, (public_key) )
FC_REFLECT(eos::account_history_apis::read_only::get_key_accounts_results, (account_names) )
FC_REFLECT(eos::account_history_apis::read_only::get_controlled_accounts_params, (controlling_account) )
FC_REFLECT(eos::account_history_apis::read_only::get_controlled_accounts_results, (controlled_accounts) )
......@@ -19,7 +19,6 @@ namespace eos {
void plugin_shutdown();
void broadcast_block(const chain::signed_block &sb);
void broadcast_transaction (const chain::SignedTransaction &txn);
private:
std::unique_ptr<class net_plugin_impl> my;
......
......@@ -6,7 +6,7 @@ namespace eos {
using namespace chain;
using namespace fc;
struct handshake_message {
struct handshake_message {
int16_t network_version = 0;
chain_id_type chain_id; ///< used to identify chain
fc::sha256 node_id; ///< used to identify peers and prevent self-connect
......@@ -41,7 +41,7 @@ namespace eos {
};
struct peer_message {
vector<fc::ip::endpoint> peers;
vector<fc::sha256> peers;
};
using net_message = static_variant<handshake_message,
......
......@@ -19,9 +19,11 @@
namespace eos {
using std::vector;
using boost::asio::ip::tcp;
using boost::asio::ip::address_v4;
using boost::asio::ip::host_name;
using fc::time_point;
using fc::time_point_sec;
using eos::chain::transaction_id_type;
......@@ -34,16 +36,6 @@ namespace eos {
using socket_ptr = std::shared_ptr<tcp::socket>;
struct node_transaction_state {
transaction_id_type id;
fc::time_point received;
fc::time_point_sec expires;
vector<char> packed_transaction;
uint32_t block_num = -1; /// block transaction was included in
bool validated = false; /// whether or not our node has validated it
};
/**
* Index by id
* Index by is_known, block_num, validated_time, this is the order we will broadcast
......@@ -105,16 +97,31 @@ namespace eos {
struct handshake_initializer {
static void populate (handshake_message &hello);
static net_plugin_impl* info;
};
class connection : public std::enable_shared_from_this<connection> {
public:
connection( socket_ptr s )
: socket(s)
connection( socket_ptr s, bool try_recon )
: block_state(),
trx_state(),
in_sync_state(),
out_sync_state(),
socket(s),
shared_peers(),
pending_message_size(),
pending_message_buffer(),
remote_node_id(),
last_handshake(),
out_queue(),
try_reconnect (try_recon)
{
wlog( "created connection" );
pending_message_buffer.resize( 1024*1024*4 );
auto *rnd = remote_node_id.data();
rnd[0] = 0;
}
~connection() {
......@@ -126,16 +133,22 @@ namespace eos {
sync_request_index in_sync_state;
sync_request_index out_sync_state;
socket_ptr socket;
std::set<fc::ip::endpoint> shared_peers;
set<fc::sha256> shared_peers;
set<connection_ptr> mutual_peers;
uint32_t pending_message_size;
vector<char> pending_message_buffer;
vector<char> raw_recv;
vector<char> raw_send;
fc::sha256 remote_node_id;
handshake_message last_handshake;
std::deque<net_message> out_queue;
uint32_t mtu;
bool try_reconnect;
void send_handshake ( ) {
dlog ("sending new handshake message" );
handshake_message hello;
handshake_initializer::populate(hello);
send (hello);
......@@ -165,18 +178,18 @@ namespace eos {
fc::raw::pack( ds, m );
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 ) {
if( ec ) {
elog( "Error sending message: ${msg}", ("msg",ec.message() ) );
} else {
if (!out_queue.size()) {
elog ("out_queue underflow!");
} else {
out_queue.pop_front();
}
send_next_message();
}
});
[this,buf=std::move(buffer)]( boost::system::error_code ec, std::size_t bytes_transferred ) {
if( ec ) {
elog( "Error sending message: ${msg}", ("msg",ec.message() ) );
} else {
if (!out_queue.size()) {
elog ("out_queue underflow!");
} else {
out_queue.pop_front();
}
send_next_message();
}
});
}
void write_block_backlog ( ) {
......@@ -198,7 +211,7 @@ namespace eos {
wlog( "write loop exception" );
}
if (out_sync_state.size() == 0) {
send_handshake ();
send_handshake ( );
}
}
......@@ -206,45 +219,74 @@ namespace eos {
}; // class connection
struct node_transaction_state {
transaction_id_type id;
fc::time_point received;
fc::time_point_sec expires;
// vector<char> packed_transaction; //just for the moment
SignedTransaction transaction;
uint32_t block_num = -1; /// block transaction was included in
bool validated = false; /// whether or not our node has validated it
};
struct by_expiry;
typedef multi_index_container<
node_transaction_state,
indexed_by<
ordered_unique<
tag<by_id>, member < node_transaction_state,
transaction_id_type,
&node_transaction_state::id > >,
ordered_non_unique<
tag<by_expiry>, member< node_transaction_state,
fc::time_point_sec,
&node_transaction_state::expires > >
>
>
node_transaction_index;
static boost::thread_specific_ptr<transaction_id_type> last_recd_txn;
static net_plugin_impl *my_impl;
class last_recd_txn_guard {
public:
last_recd_txn_guard (transaction_id_type id) {
transaction_id_type *ptid = new transaction_id_type(id);
last_recd_txn.reset (ptid);
last_recd_txn_guard(transaction_id_type tid ) {
last_recd_txn.reset (new transaction_id_type (tid));
}
~last_recd_txn_guard () {
dlog ("TSS Guard dtor 1");
last_recd_txn.reset (0);
dlog ("TSS Guard dtor 2");
}
};
class net_plugin_impl {
public:
unique_ptr<tcp::acceptor> acceptor;
unique_ptr<tcp::acceptor> acceptor;
tcp::endpoint listen_endpoint;
string p2p_address;
tcp::endpoint listen_endpoint;
string p2p_address;
vector<string> seed_nodes;
std::set<tcp::endpoint> resolved_seed_nodes;
std::set<fc::ip::endpoint> learned_nodes;
vector<string> supplied_peers;
std::set<fc::sha256> resolved_nodes;
std::set<fc::sha256> learned_nodes;
std::set<socket_ptr> pending_sockets;
std::set< connection_ptr > connections;
bool done = false;
int16_t network_version = 0;
chain_id_type chain_id; ///< used to identify chain
fc::sha256 node_id; ///< used to identify peers and prevent self-connect
std::string user_agent_name;
chain_plugin* chain_plug;
int32_t just_send_it_max;
int16_t network_version = 0;
chain_id_type chain_id; ///< used to identify chain
fc::sha256 node_id; ///< used to identify peers and prevent self-connect
string user_agent_name;
chain_plugin* chain_plug;
int32_t just_send_it_max;
vector<node_transaction_state> local_txns;
vector<transaction_id_type> pending_notify;
node_transaction_index local_txns;
vector<transaction_id_type> pending_notify;
void connect( const string& peer_addr ) {
auto host = peer_addr.substr( 0, peer_addr.find(':') );
......@@ -263,20 +305,6 @@ namespace eos {
}
});
}
#if 0
void connect( tcp::endpoint ep) {
auto sock = std::make_shared<tcp::socket>( std::ref( app().get_io_service() ) );
pending_sockets.insert( sock );
sock->async_connect (ep, [ep, sock, this]( const boost::system::error_code& err ) {
pending_sockets.erase( sock );
if( !err ) {
start_session (std::make_shared<connection>(sock));
} else {
elog ("cannot connect to ${addr}:${port}: ${error}",("addr",ep.address().to_string())("port",ep.port())("err",err.message()));
}
});
}
#endif
void connect( std::shared_ptr<tcp::resolver> resolver, tcp::resolver::iterator endpoint_itr ) {
auto sock = std::make_shared<tcp::socket>( std::ref( app().get_io_service() ) );
......@@ -289,8 +317,7 @@ namespace eos {
( const boost::system::error_code& err ) {
pending_sockets.erase( sock );
if( !err ) {
resolved_seed_nodes.insert (sock->remote_endpoint());
start_session( std::make_shared<connection>(sock));
start_session( std::make_shared<connection>(sock, true));
} else {
if( endpoint_itr != tcp::resolver::iterator() ) {
connect( resolver, endpoint_itr );
......@@ -323,7 +350,7 @@ namespace eos {
#endif
void start_session( connection_ptr con ) {
void start_session(connection_ptr con ) {
connections.insert (con);
uint32_t mtu = 1300; // need a way to query this
if (mtu < just_send_it_max) {
......@@ -331,8 +358,7 @@ namespace eos {
}
start_read_message( con );
con->send_handshake();
send_peer_message(*con);
con->send_handshake( );
// for now, we can just use the application main loop.
// con->readloop_complete = bf::async( [=](){ read_loop( con ); } );
......@@ -344,7 +370,7 @@ namespace eos {
auto socket = std::make_shared<tcp::socket>( std::ref( app().get_io_service() ) );
acceptor->async_accept( *socket, [socket,this]( boost::system::error_code ec ) {
if( !ec ) {
start_session( std::make_shared<connection>( socket ) );
start_session( std::make_shared<connection>( socket, false ) );
start_listen_loop();
} else {
elog( "Error accepting connection: ${m}", ("m", ec.message() ) );
......@@ -388,29 +414,31 @@ namespace eos {
return fc::ip::endpoint (addr,ep.port());
}
void send_peer_message (connection &conn) {
void send_peer_message () {
peer_message pm;
pm.peers.resize(connections.size());
for (auto &c : connections) {
fc::ip::endpoint remote = asio_to_fc(c->socket->remote_endpoint());
if (conn.shared_peers.find(remote) == conn.shared_peers.end()) {
pm.peers.push_back(remote);
if ( (c->remote_node_id._hash[0] | c->remote_node_id._hash[1] | c->remote_node_id._hash[2] | c->remote_node_id._hash[0]) == 0 ) {
return;
}
pm.peers.push_back(c->remote_node_id);
}
if (!pm.peers.empty()) {
conn.send (pm);
for (auto &c : connections) {
if (c->out_sync_state.size() == 0) {
c->send(pm);
}
}
}
}
// template<typename T>
void send_all (const SignedTransaction &msg) {
for (auto &c : connections) {
ilog ("send_all bsm: peer in_sync ${insiz} out_sync ${outsiz}", ("insiz",c->in_sync_state.size())("outsiz",c->out_sync_state.size()));
if (c->out_sync_state.size() == 0) {
const auto& bs = c->trx_state.find(msg.id());
if (bs == c->trx_state.end()) {
c->trx_state.insert((transaction_state){msg.id(),true,true,(uint32_t)-1,
fc::time_point(),fc::time_point()});
c->trx_state.insert(transaction_state({msg.id(),true,true,(uint32_t)-1,
fc::time_point(),fc::time_point()}));
}
c->send(msg);
}
......@@ -419,7 +447,6 @@ namespace eos {
void send_all (const block_summary_message &msg) {
for (auto &c : connections) {
ilog ("send_all bsm: peer in_sync ${insiz} out_sync ${outsiz}", ("insiz",c->in_sync_state.size())("outsiz",c->out_sync_state.size()));
const auto& bs = c->block_state.find(msg.block.id());
if (bs == c->block_state.end()) {
c->block_state.insert ((block_state){msg.block.id(),true,true,fc::time_point()});
......@@ -431,7 +458,6 @@ namespace eos {
void send_all (const notice_message &msg) {
for (auto &c : connections) {
ilog ("send_all nm: peer in_sync ${insiz} out_sync ${outsiz}", ("insiz",c->in_sync_state.size())("outsiz",c->out_sync_state.size()));
if (c->out_sync_state.size() == 0) {
for (const auto& b : msg.known_blocks) {
const auto& bs = c->block_state.find(b);
......@@ -494,22 +520,54 @@ namespace eos {
if ( msg.head_num > head) {
shared_fetch (head, msg.head_num);
}
dlog ("setting remote node id = ${n}",("n", msg.node_id));
if ( c->remote_node_id != msg.node_id) {
if (c->try_reconnect) {
dlog ("adding ${pn} to resolved node list", ("pn", msg.node_id));
auto old_id = resolved_nodes.find (c->remote_node_id);
if (old_id != resolved_nodes.end()) {
dlog ("first purging old id");
resolved_nodes.erase(old_id);
}
resolved_nodes.insert (msg.node_id);
}
else {
dlog ("adding ${pn} to learned node list", ("pn", msg.node_id));
auto old_id = learned_nodes.find (c->remote_node_id);
if (old_id != learned_nodes.end()) {
dlog ("first purging old id");
learned_nodes.erase(old_id);
}
learned_nodes.insert (msg.node_id);
}
c->remote_node_id = msg.node_id;
send_peer_message();
}
c->last_handshake = msg;
}
void handle_message (connection_ptr c, const peer_message &msg) {
dlog ("got a peer message with ${pc}", ("pc", msg.peers.size()));
for (auto fcep : msg.peers) {
c->shared_peers.insert (fcep);
tcp::endpoint ep = fc_to_asio (fcep);
if (ep == listen_endpoint) {
dlog ("got a peer message with ${pc} from ${r}", ("pc", msg.peers.size())("r",c->last_handshake.p2p_address));
c->shared_peers.clear();
for (auto pnode : msg.peers) {
if (pnode == node_id) {
dlog ("skipping self peernode");
continue;
}
if (resolved_seed_nodes.find(ep) == resolved_seed_nodes.end() &&
learned_nodes.find (fcep) == learned_nodes.end()) {
learned_nodes.insert (fcep);
if (pnode == c->remote_node_id) {
dlog ("skipping received connection's node");
continue;
}
for (auto &conn : connections) {
if (conn->remote_node_id == pnode) {
c->mutual_peers.insert (conn);
break;
}
}
c->shared_peers.insert (pnode);
}
}
......@@ -542,27 +600,65 @@ namespace eos {
}
void handle_message (connection_ptr c, const request_message &msg) {
dlog ("got a request_message");
#warning ("TODO: implement handling a request_message")
dlog ("got a request message");
// collect a list of transactions that were found.
// collect a second list of transaction ids that were not found but are otherwise known by some peers
// finally, what remains are future(?) transactions
vector< SignedTransaction > send_now;
map <connection_ptr, vector < transaction_id_type > > forward_to;
auto conn_ndx = connections.begin();
for (auto t: msg.req_trx) {
auto txn = local_txns.get<by_id>().find(t);
if (txn != local_txns.end()) {
send_now.push_back(txn->transaction);
}
else {
dlog ("request message looping through peers");
int cycle_count = 4;
auto loop_start = conn_ndx++;
while (conn_ndx != loop_start) {
if (conn_ndx == connections.end()) {
if (--cycle_count == 0) {
dlog ("breaking out of stupid loop");
break;
}
conn_ndx = connections.begin();
continue;
}
if (conn_ndx->get() == c.get()) {
++conn_ndx;
continue;
}
auto txn = conn_ndx->get()->trx_state.get<by_id>().find(t);
if (txn != conn_ndx->get()->trx_state.end()) {
// add to forward_to list
break;
}
++conn_ndx;
}
}
}
if (!send_now.empty()) {
}
}
void handle_message (connection_ptr c, const sync_request_message &msg) {
dlog ("got a sync request message for blocks ${s} to ${e}",
("s",msg.start_block)("e", msg.end_block));
// dlog ("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,msg.start_block-1,time_point::now()};
c->out_sync_state.insert (req);
c->write_block_backlog ();
}
void handle_message (connection_ptr c, const block_summary_message &msg) {
dlog ("got a block summary message blkid = ${b}", ("b",msg.block.id()));
dlog ("got a block summary message blkid = ${b} from peer ${p}", ("b",msg.block.id())("p", c->remote_node_id));
#warning ("TODO: reconstruct actual block from cached transactions")
const auto& itr = c->block_state.get<by_id>();
auto bs = itr.find(msg.block.id());
if (bs == c->block_state.end()) {
dlog ("not found, forwarding on");
c->block_state.insert ((block_state){msg.block.id(),true,true,fc::time_point()});
c->block_state.insert (block_state({msg.block.id(),true,true,fc::time_point()}));
forward (c, msg);
} else {
if (!bs->is_known) {
......@@ -590,12 +686,14 @@ namespace eos {
}
void handle_message (connection_ptr c, const SignedTransaction &msg) {
dlog ("got a SignedTransacton");
chain_controller &cc = chain_plug->chain();
if (!cc.is_known_transaction(msg.id())) {
last_recd_txn_guard tls_guard(msg.id());
chain_plug->accept_transaction (msg);
uint16_t bn = static_cast<uint16_t>(msg.refBlockNum);
node_transaction_state nts = {msg.id(),time_point::now(),msg.expiration,
msg,bn, true};
local_txns.insert(nts);
forward (c, msg);
}
}
......@@ -650,27 +748,29 @@ namespace eos {
void start_reading_pending_buffer( connection_ptr c ) {
boost::asio::async_read( *c->socket,
boost::asio::buffer(c->pending_message_buffer.data(),
c->pending_message_size ),
[this,c]( boost::system::error_code ec, std::size_t bytes_transferred ) {
// ilog( "read buffer handler..." );
if( !ec ) {
try {
auto msg = fc::raw::unpack<net_message>( c->pending_message_buffer );
// ilog( "received message of size: ${s}", ("s",bytes_transferred) );
start_read_message( c );
msgHandler m(*this, c);
msg.visit(m);
return;
} catch ( const fc::exception& e ) {
edump((e.to_detail_string() ));
}
} else {
elog( "Error reading message from connection: ${m}", ("m", ec.message() ) );
}
close( c );
});
boost::asio::buffer(c->pending_message_buffer.data(), c->pending_message_size ),
[this,c]( boost::system::error_code ec, std::size_t bytes_transferred ) {
if( !ec ) {
try {
auto msg = fc::raw::unpack<net_message>( c->pending_message_buffer );
start_read_message( c );
msgHandler m(*this, c);
msg.visit(m);
return;
} catch ( const fc::exception& e ) {
edump((e.to_detail_string() ));
}
} else {
elog( "Error reading message from connection: ${m}", ("m", ec.message() ) );
}
if ( c->try_reconnect ) {
#warning ("TODO: Add reconnect logic after a read failure");
}
else {
close( c );
}
});
}
......@@ -681,8 +781,7 @@ namespace eos {
c.reset ();
}
void send_all_txn (const SignedTransaction&txn) {
dlog ("got signaled about a pending transaction");
void send_all_txn (const SignedTransaction& txn) {
if (last_recd_txn.get() && *last_recd_txn.get() == txn.id()) {
dlog ("skipping our received transacton");
return;
......@@ -702,6 +801,9 @@ namespace eos {
pending_notify.push_back(txn.id());
}
/**
* This one is necessary to hook into the boost notifier api
**/
static void pending_txn (const SignedTransaction& txn) {
my_impl->send_all_txn (txn);
}
......@@ -709,14 +811,12 @@ namespace eos {
}; // class net_plugin_impl
net_plugin_impl* handshake_initializer::info;
void
handshake_initializer::populate (handshake_message &hello) {
hello.network_version = 0;
hello.chain_id = info->chain_id;
hello.node_id = info->node_id;
hello.p2p_address = info->p2p_address;
hello.chain_id = my_impl->chain_id;
hello.node_id = my_impl->node_id;
hello.p2p_address = my_impl->p2p_address;
#if defined( __APPLE__ )
hello.os = "osx";
#elif defined( __linux__ )
......@@ -726,10 +826,10 @@ namespace eos {
#else
hello.os = "other";
#endif
hello.agent = info->user_agent_name;
hello.agent = my_impl->user_agent_name;
chain_controller& cc = info->chain_plug->chain();
chain_controller& cc = my_impl->chain_plug->chain();
try {
hello.last_irreversible_block_id = cc.get_block_id_for_num
(hello.last_irreversible_block_num = cc.last_irreversible_block_num());
......@@ -752,7 +852,6 @@ namespace eos {
net_plugin::net_plugin()
:my( new net_plugin_impl ) {
handshake_initializer::info = my.get();
my_impl = my.get();
}
......@@ -803,7 +902,7 @@ namespace eos {
}
if( options.count( "remote-endpoint" ) ) {
my->seed_nodes = options.at( "remote-endpoint" ).as< vector<string> >();
my->supplied_peers = options.at( "remote-endpoint" ).as< vector<string> >();
}
if (options.count("agent-name")) {
my->user_agent_name = options.at ("agent-name").as< string > ();
......@@ -811,11 +910,12 @@ namespace eos {
my->chain_plug = app().find_plugin<chain_plugin>();
my->chain_plug->get_chain_id(my->chain_id);
fc::rand_pseudo_bytes(my->node_id.data(), my->node_id.data_size());
dlog("my node_id = ${n}", ("n",my->node_id));
my->just_send_it_max = 1300;
}
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());
......@@ -827,7 +927,7 @@ namespace eos {
my->start_listen_loop();
}
for( auto seed_node : my->seed_nodes ) {
for( auto seed_node : my->supplied_peers ) {
my->connect( seed_node );
}
boost::asio::signal_set signals (app().get_io_service(), SIGINT, SIGTERM);
......@@ -851,16 +951,11 @@ namespace eos {
my->close (con);
}
idump((my->connections.size()));
my->acceptor.reset(nullptr);
}
ilog( "exit shutdown" );
} FC_CAPTURE_AND_RETHROW() }
void net_plugin::broadcast_transaction (const SignedTransaction &txn) {
my->pending_txn (txn);
}
void net_plugin::broadcast_block (const chain::signed_block &sb) {
vector<transaction_id_type> trxs;
if (!sb.cycles.empty()) {
......
......@@ -223,7 +223,7 @@ struct launcher_def {
bool do_ssh (const string &cmd, const string &hostname);
void prep_remote_config_dir (eosd_def &node);
void launch (eosd_def &node, string &gts);
void kill (launch_modes mode);
void kill (launch_modes mode, string sig_opt);
void start_all (string &gts, launch_modes mode);
};
......@@ -544,7 +544,7 @@ launcher_def::launch (eosd_def &node, string &gts) {
node_rt_info info;
info.remote = node.remote;
string eosdcmd = "programs/eosd/eosd --data-dir " + node.data_dir;
string eosdcmd = "programs/eosd/eosd --skip-transaction-signatures --data-dir " + node.data_dir;
if (gts.length()) {
eosdcmd += " --genesis-timestamp " + gts;
}
......@@ -559,7 +559,7 @@ launcher_def::launch (eosd_def &node, string &gts) {
exit (-1);
}
string cmd = "cd node.eos_root_dir; kill -TERM `cat " + pidf.string() + "`";
string cmd = "cd node.eos_root_dir; kill -9 `cat " + pidf.string() + "`";
format_ssh (cmd, node.hostname, info.kill_cmd);
}
else {
......@@ -586,7 +586,7 @@ launcher_def::launch (eosd_def &node, string &gts) {
}
void
launcher_def::kill (launch_modes mode) {
launcher_def::kill (launch_modes mode, string sig_opt) {
if (mode == LM_NONE) {
return;
}
......@@ -598,7 +598,7 @@ launcher_def::kill (launch_modes mode) {
if (info.pid_file.length()) {
string pid;
fc::json::from_file(info.pid_file).as<string>(pid);
string kill_cmd = "kill -TERM " + pid;
string kill_cmd = "kill " + sig_opt + " " + pid;
boost::process::system (kill_cmd);
}
else {
......@@ -638,7 +638,7 @@ int main (int argc, char *argv[]) {
launcher_def top;
string gts;
launch_modes mode;
bool do_kill;
string kill_arg;
local_id.initialize();
top.set_options(opts);
......@@ -646,7 +646,7 @@ int main (int argc, char *argv[]) {
opts.add_options()
("timestamp,i",bpo::value<string>(),"set the timestamp for the first block. Use \"now\" to indicate the current time")
("launch,l",bpo::value<string>(), "select a subset of nodes to launch. Currently may be \"all\", \"none\", or \"local\". If not set, the default is to launch all unless an output file is named, in which case it starts none.")
("kill,k","The launcher retrieve the previously started process ids and issue a sigterm to each.")
("kill,k", bpo::value<string>(),"The launcher retrieves the previously started process ids and issue a kill signal to each.")
("help,h","print this list");
......@@ -657,7 +657,8 @@ int main (int argc, char *argv[]) {
if (vmap.count("timestamp"))
gts = vmap["timestamp"].as<string>();
do_kill = vmap.count("kill") > 0;
if (vmap.count("kill"))
kill_arg = vmap["kill"].as<string>();
if (vmap.count("help") > 0) {
opts.print(cerr);
return 0;
......@@ -679,11 +680,14 @@ int main (int argc, char *argv[]) {
}
}
else {
mode = do_kill || top.output.empty() ? LM_ALL : LM_NONE;
mode = !kill_arg.empty() || top.output.empty() ? LM_ALL : LM_NONE;
}
if (do_kill) {
top.kill (mode);
if (!kill_arg.empty()) {
if (kill_arg[0] != '-') {
kill_arg = "-" + kill_arg;
}
top.kill (mode, kill_arg);
}
else {
top.generate();
......
......@@ -32,10 +32,13 @@ Note that the Launcher will not push instances of eosd to the remote hosts, you
Network topology or "shape" describes how the nodes are connected in order to share transaction and block data, and requests for the same. The idea for varying network topology is that there is a trade off between the number of times a node must send a message reporting a new transaction or block, vs the number of times that message must be repeated to ensure all nodes know of it.
The Launcher has definitions of three different network "shapes" based on inter-nodal connections, which can be selected by a command line option, or you can supply your own network topology by editing the Launcher generated configuration file.
####Ring network
This is the simplest network, where each node identifies just the node next to it as it's only peer.
####Star network
A "star" is intended to support the use larger number nodes in the testnet. In this case the number of peers connected to a node and the distribution of those nodes varies based on the number of nodes in the network.
A "star" is intended to support the use larger number nodes in the testnet. In this case the number of peers connected to a node and the distribution of those nodes varies based on the number of nodes in the network.
####Mesh network
In a "mesh" network, each node is connected to as many peer nodes as possible.
......
#!/bin/bash
for a in tn_data_*; do kill `cat $a/eosd.pid`; done
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册