Merge branch 'develop' into bug/235-corrupt-chain-file

This commit is contained in:
serkixenos 2022-02-28 11:08:30 -04:00
commit 5755566b16
15 changed files with 488 additions and 314 deletions

View file

@ -19,7 +19,7 @@ build:
- mkdir build
- cd build
- cmake -DCMAKE_BUILD_TYPE=Release ..
- make -j4
- make -j$(nproc)
artifacts:
untracked: true
paths:
@ -49,6 +49,7 @@ test:
dependencies:
- build
script:
- ./build/libraries/fc/tests/all_tests
- ./build/tests/betting_test --log_level=message
- ./build/tests/chain_test --log_level=message
- ./build/tests/cli_test --log_level=message

View file

@ -83,7 +83,6 @@ LIST(APPEND BOOST_COMPONENTS thread
system
filesystem
program_options
signals
serialization
chrono
unit_test_framework

View file

@ -12,7 +12,7 @@ Following dependencies are needed for a clean install of Ubuntu 20.04:
```
sudo apt-get install \
apt-utils autoconf bash build-essential ca-certificates cmake dnsutils \
doxygen expect git graphviz libboost1.67-all-dev libbz2-dev libcurl4-openssl-dev \
doxygen expect git graphviz libboost-all-dev libbz2-dev libcurl4-openssl-dev \
libncurses-dev libreadline-dev libsnappy-dev libssl-dev libtool libzip-dev \
libzmq3-dev locales mc nano net-tools ntp openssh-server pkg-config perl \
python3 python3-jinja2 sudo wget
@ -27,10 +27,18 @@ cd $HOME/src
git clone https://gitlab.com/PBSA/peerplays.git
cd peerplays
git submodule update --init --recursive
# If you want to build Mainnet node
cmake -DCMAKE_BUILD_TYPE=Release
# If you want to build Testnet node
cmake -DCMAKE_BUILD_TYPE=Release -DBUILD_PEERPLAYS_TESTNET=1
# Update -j flag depending on your current system specs;
# Recommended 4GB of RAM per 1 CPU core
# make -j2 for 8GB RAM
# make -j4 for 16GB RAM
# make -j8 for 32GB RAM
make -j$(nproc)
make install # this can install the executable files under /usr/local

View file

@ -3,3 +3,4 @@
find ./libraries/app -regex ".*[c|h]pp" | xargs clang-format -i
find ./libraries/chain/hardfork.d -regex ".*hf" | xargs clang-format -i
find ./libraries/plugins/peerplays_sidechain -regex ".*[c|h]pp" | xargs clang-format -i
find ./programs/cli_wallet -regex ".*[c|h]pp" | xargs clang-format -i

View file

@ -52,27 +52,19 @@ template class fc::api<graphene::app::database_api>;
namespace graphene { namespace app {
template<class T>
optional<T> maybe_id( const string& name_or_id )
{
if( std::isdigit( name_or_id.front() ) )
{
try
{
template <class T>
optional<T> maybe_id(const string &name_or_id) {
if (std::isdigit(name_or_id.front())) {
try {
return fc::variant(name_or_id, 1).as<T>(1);
}
catch (const fc::exception&)
{ // not an ID
} catch (const fc::exception &) { // not an ID
}
}
return optional<T>();
}
std::string object_id_to_string(object_id_type id)
{
std::string object_id = fc::to_string(id.space())
+ "." + fc::to_string(id.type())
+ "." + fc::to_string(id.instance());
std::string object_id_to_string(object_id_type id) {
std::string object_id = fc::to_string(id.space()) + "." + fc::to_string(id.type()) + "." + fc::to_string(id.instance());
return object_id;
}
@ -170,14 +162,17 @@ public:
// Witnesses
vector<optional<witness_object>> get_witnesses(const vector<witness_id_type> &witness_ids) const;
fc::optional<witness_object> get_witness_by_account_id(account_id_type account) const;
fc::optional<witness_object> get_witness_by_account(const std::string account_id_or_name) const;
map<string, witness_id_type> lookup_witness_accounts(const string &lower_bound_name, uint32_t limit) const;
uint64_t get_witness_count() const;
// Committee members
vector<optional<committee_member_object>> get_committee_members(const vector<committee_member_id_type> &committee_member_ids) const;
fc::optional<committee_member_object> get_committee_member_by_account_id(account_id_type account) const;
fc::optional<committee_member_object> get_committee_member_by_account(const std::string account_id_or_name) const;
map<string, committee_member_id_type> lookup_committee_member_accounts(const string &lower_bound_name, uint32_t limit) const;
uint64_t get_committee_member_count() const;
// SON members
vector<optional<son_object>> get_sons(const vector<son_id_type> &son_ids) const;
@ -200,22 +195,24 @@ public:
// Workers
vector<optional<worker_object>> get_workers(const vector<worker_id_type> &witness_ids) const;
vector<worker_object> get_workers_by_account_id(account_id_type account) const;
vector<worker_object> get_workers_by_account(const std::string account_id_or_name) const;
map<string, worker_id_type> lookup_worker_accounts(const string &lower_bound_name, uint32_t limit) const;
uint64_t get_worker_count() const;
// Votes
vector<variant> lookup_vote_ids(const vector<vote_id_type> &votes) const;
vector<vote_id_type> get_votes_ids(const string &account_name_or_id) const;
template<typename IndexType, typename Tag>
vector<variant> get_votes_objects(const vector<vote_id_type> &votes, unsigned int variant_max_depth = 1) const
{
static_assert( std::is_base_of<index,IndexType>::value, "Type must be an index type" );
template <typename IndexType, typename Tag>
vector<variant> get_votes_objects(const vector<vote_id_type> &votes, unsigned int variant_max_depth = 1) const {
static_assert(std::is_base_of<index, IndexType>::value, "Type must be an index type");
vector<variant> result;
const auto &idx = _db.get_index_type<IndexType>().indices().template get<Tag>();
for (auto id : votes) {
auto itr = idx.find(id);
if (itr != idx.end())
result.emplace_back(variant(*itr,variant_max_depth));
result.emplace_back(variant(*itr, variant_max_depth));
}
return result;
}
@ -292,6 +289,8 @@ public:
uint32_t api_limit_lookup_accounts = 1000;
uint32_t api_limit_lookup_witness_accounts = 1000;
uint32_t api_limit_lookup_committee_member_accounts = 1000;
uint32_t api_limit_lookup_son_accounts = 1000;
uint32_t api_limit_lookup_worker_accounts = 1000;
uint32_t api_limit_get_trade_history = 100;
uint32_t api_limit_get_trade_history_by_sequence = 100;
@ -1611,17 +1610,25 @@ vector<optional<witness_object>> database_api_impl::get_witnesses(const vector<w
return result;
}
fc::optional<witness_object> database_api::get_witness_by_account_id(account_id_type account) const {
return my->get_witness_by_account_id(account);
}
fc::optional<witness_object> database_api_impl::get_witness_by_account_id(account_id_type account) const {
const auto &idx = _db.get_index_type<witness_index>().indices().get<by_account>();
auto itr = idx.find(account);
if (itr != idx.end())
return *itr;
return {};
}
fc::optional<witness_object> database_api::get_witness_by_account(const std::string account_id_or_name) const {
return my->get_witness_by_account(account_id_or_name);
}
fc::optional<witness_object> database_api_impl::get_witness_by_account(const std::string account_id_or_name) const {
const auto &idx = _db.get_index_type<witness_index>().indices().get<by_account>();
const account_id_type account = get_account_from_string(account_id_or_name)->id;
auto itr = idx.find(account);
if (itr != idx.end())
return *itr;
return {};
return get_witness_by_account_id(account);
}
map<string, witness_id_type> database_api::lookup_witness_accounts(const string &lower_bound_name, uint32_t limit) const {
@ -1682,17 +1689,25 @@ vector<optional<committee_member_object>> database_api_impl::get_committee_membe
return result;
}
fc::optional<committee_member_object> database_api::get_committee_member_by_account_id(account_id_type account) const {
return my->get_committee_member_by_account_id(account);
}
fc::optional<committee_member_object> database_api_impl::get_committee_member_by_account_id(account_id_type account) const {
const auto &idx = _db.get_index_type<committee_member_index>().indices().get<by_account>();
auto itr = idx.find(account);
if (itr != idx.end())
return *itr;
return {};
}
fc::optional<committee_member_object> database_api::get_committee_member_by_account(const std::string account_id_or_name) const {
return my->get_committee_member_by_account(account_id_or_name);
}
fc::optional<committee_member_object> database_api_impl::get_committee_member_by_account(const std::string account_id_or_name) const {
const auto &idx = _db.get_index_type<committee_member_index>().indices().get<by_account>();
const account_id_type account = get_account_from_string(account_id_or_name)->id;
auto itr = idx.find(account);
if (itr != idx.end())
return *itr;
return {};
return get_committee_member_by_account_id(account);
}
map<string, committee_member_id_type> database_api::lookup_committee_member_accounts(const string &lower_bound_name, uint32_t limit) const {
@ -1723,6 +1738,14 @@ map<string, committee_member_id_type> database_api_impl::lookup_committee_member
return committee_members_by_account_name;
}
uint64_t database_api::get_committee_member_count() const {
return my->get_committee_member_count();
}
uint64_t database_api_impl::get_committee_member_count() const {
return _db.get_index_type<committee_member_index>().indices().size();
}
//////////////////////////////////////////////////////////////////////
// //
// SON members //
@ -1771,7 +1794,10 @@ map<string, son_id_type> database_api::lookup_son_accounts(const string &lower_b
}
map<string, son_id_type> database_api_impl::lookup_son_accounts(const string &lower_bound_name, uint32_t limit) const {
FC_ASSERT(limit <= 1000);
FC_ASSERT(limit <= api_limit_lookup_son_accounts,
"Number of querying accounts can not be greater than ${configured_limit}",
("configured_limit", api_limit_lookup_son_accounts));
const auto &sons_by_id = _db.get_index_type<son_index>().indices().get<by_id>();
// we want to order sons by account name, but that name is in the account object
@ -1927,10 +1953,22 @@ vector<optional<worker_object>> database_api::get_workers(const vector<worker_id
return my->get_workers(worker_ids);
}
vector<worker_object> database_api::get_workers_by_account_id(account_id_type account) const {
return my->get_workers_by_account_id(account);
}
vector<worker_object> database_api::get_workers_by_account(const std::string account_id_or_name) const {
return my->get_workers_by_account(account_id_or_name);
}
map<string, worker_id_type> database_api::lookup_worker_accounts(const string &lower_bound_name, uint32_t limit) const {
return my->lookup_worker_accounts(lower_bound_name, limit);
}
uint64_t database_api::get_worker_count() const {
return my->get_worker_count();
}
vector<optional<worker_object>> database_api_impl::get_workers(const vector<worker_id_type> &worker_ids) const {
vector<optional<worker_object>> result;
result.reserve(worker_ids.size());
@ -1943,9 +1981,8 @@ vector<optional<worker_object>> database_api_impl::get_workers(const vector<work
return result;
}
vector<worker_object> database_api_impl::get_workers_by_account(const std::string account_id_or_name) const {
vector<worker_object> database_api_impl::get_workers_by_account_id(account_id_type account) const {
const auto &idx = _db.get_index_type<worker_index>().indices().get<by_account>();
const account_id_type account = get_account_from_string(account_id_or_name)->id;
auto itr = idx.find(account);
vector<worker_object> result;
@ -1957,6 +1994,40 @@ vector<worker_object> database_api_impl::get_workers_by_account(const std::strin
return result;
}
vector<worker_object> database_api_impl::get_workers_by_account(const std::string account_id_or_name) const {
const account_id_type account = get_account_from_string(account_id_or_name)->id;
return get_workers_by_account_id(account);
}
map<string, worker_id_type> database_api_impl::lookup_worker_accounts(const string &lower_bound_name, uint32_t limit) const {
FC_ASSERT(limit <= api_limit_lookup_worker_accounts,
"Number of querying accounts can not be greater than ${configured_limit}",
("configured_limit", api_limit_lookup_worker_accounts));
const auto &workers_by_id = _db.get_index_type<worker_index>().indices().get<by_id>();
// we want to order workers by account name, but that name is in the account object
// so the worker_index doesn't have a quick way to access it.
// get all the names and look them all up, sort them, then figure out what
// records to return. This could be optimized, but we expect the
// number of witnesses to be few and the frequency of calls to be rare
std::map<std::string, worker_id_type> workers_by_account_name;
for (const worker_object &worker : workers_by_id)
if (auto account_iter = _db.find(worker.worker_account))
if (account_iter->name >= lower_bound_name) // we can ignore anything below lower_bound_name
workers_by_account_name.insert(std::make_pair(account_iter->name, worker.id));
auto end_iter = workers_by_account_name.begin();
while (end_iter != workers_by_account_name.end() && limit--)
++end_iter;
workers_by_account_name.erase(end_iter, workers_by_account_name.end());
return workers_by_account_name;
}
uint64_t database_api_impl::get_worker_count() const {
return _db.get_index_type<worker_index>().indices().size();
}
//////////////////////////////////////////////////////////////////////
// //
// Votes //
@ -2049,8 +2120,7 @@ vector<vote_id_type> database_api_impl::get_votes_ids(const string &account_name
const account_object *account = get_account_from_string(account_name_or_id);
//! Iterate throug votes and fill vector
for( const auto& vote : account->options.votes )
{
for (const auto &vote : account->options.votes) {
result.emplace_back(vote);
}
@ -2060,16 +2130,16 @@ vector<vote_id_type> database_api_impl::get_votes_ids(const string &account_name
votes_info database_api_impl::get_votes(const string &account_name_or_id) const {
votes_info result;
const auto& votes_ids = get_votes_ids(account_name_or_id);
const auto& committee_ids = get_votes_objects<committee_member_index, by_vote_id>(votes_ids);
const auto& witness_ids = get_votes_objects<witness_index, by_vote_id>(votes_ids);
const auto& for_worker_ids = get_votes_objects<worker_index, by_vote_for>(votes_ids);
const auto& against_worker_ids = get_votes_objects<worker_index, by_vote_against>(votes_ids);
const auto& son_ids = get_votes_objects<son_index, by_vote_id>(votes_ids, 5);
const auto &votes_ids = get_votes_ids(account_name_or_id);
const auto &committee_ids = get_votes_objects<committee_member_index, by_vote_id>(votes_ids);
const auto &witness_ids = get_votes_objects<witness_index, by_vote_id>(votes_ids);
const auto &for_worker_ids = get_votes_objects<worker_index, by_vote_for>(votes_ids);
const auto &against_worker_ids = get_votes_objects<worker_index, by_vote_against>(votes_ids);
const auto &son_ids = get_votes_objects<son_index, by_vote_id>(votes_ids, 5);
//! Fill votes info
if(!committee_ids.empty()) {
vector< votes_info_object<committee_member_id_type> > votes_for_committee_members;
if (!committee_ids.empty()) {
vector<votes_info_object<committee_member_id_type>> votes_for_committee_members;
votes_for_committee_members.reserve(committee_ids.size());
for (const auto &committee : committee_ids) {
const auto &committee_obj = committee.as<committee_member_object>(2);
@ -2078,8 +2148,8 @@ votes_info database_api_impl::get_votes(const string &account_name_or_id) const
result.votes_for_committee_members = std::move(votes_for_committee_members);
}
if(!witness_ids.empty()) {
vector< votes_info_object<witness_id_type> > votes_for_witnesses;
if (!witness_ids.empty()) {
vector<votes_info_object<witness_id_type>> votes_for_witnesses;
votes_for_witnesses.reserve(witness_ids.size());
for (const auto &witness : witness_ids) {
const auto &witness_obj = witness.as<witness_object>(2);
@ -2088,8 +2158,8 @@ votes_info database_api_impl::get_votes(const string &account_name_or_id) const
result.votes_for_witnesses = std::move(votes_for_witnesses);
}
if(!for_worker_ids.empty()) {
vector< votes_info_object<worker_id_type> > votes_for_workers;
if (!for_worker_ids.empty()) {
vector<votes_info_object<worker_id_type>> votes_for_workers;
votes_for_workers.reserve(for_worker_ids.size());
for (const auto &for_worker : for_worker_ids) {
const auto &for_worker_obj = for_worker.as<worker_object>(2);
@ -2098,8 +2168,8 @@ votes_info database_api_impl::get_votes(const string &account_name_or_id) const
result.votes_for_workers = std::move(votes_for_workers);
}
if(!against_worker_ids.empty()) {
vector< votes_info_object<worker_id_type> > votes_against_workers;
if (!against_worker_ids.empty()) {
vector<votes_info_object<worker_id_type>> votes_against_workers;
votes_against_workers.reserve(against_worker_ids.size());
for (const auto &against_worker : against_worker_ids) {
const auto &against_worker_obj = against_worker.as<worker_object>(2);
@ -2108,8 +2178,8 @@ votes_info database_api_impl::get_votes(const string &account_name_or_id) const
result.votes_against_workers = std::move(votes_against_workers);
}
if(!son_ids.empty()) {
vector< votes_info_object<son_id_type> > votes_for_sons;
if (!son_ids.empty()) {
vector<votes_info_object<son_id_type>> votes_for_sons;
votes_for_sons.reserve(son_ids.size());
for (const auto &son : son_ids) {
const auto &son_obj = son.as<son_object>(6);
@ -2125,10 +2195,9 @@ vector<account_object> database_api_impl::get_voters_by_id(const vote_id_type &v
vector<account_object> result;
//! We search all accounts that have voted for this vote_id
const auto& account_index = _db.get_index_type<graphene::chain::account_index>().indices().get<by_id>();
for( const auto& account: account_index )
{
if(account.options.votes.count(vote_id) != 0)
const auto &account_index = _db.get_index_type<graphene::chain::account_index>().indices().get<by_id>();
for (const auto &account : account_index) {
if (account.options.votes.count(vote_id) != 0)
result.emplace_back(account);
}
@ -2143,83 +2212,78 @@ voters_info database_api_impl::get_voters(const string &account_name_or_id) cons
std::string owner_account_id;
//! Check if we have account by name
const auto& account_object = get_account_by_name(account_name_or_id);
if(account_object) {
const auto &account_object = get_account_by_name(account_name_or_id);
if (account_object) {
//! It is account
owner_account_id = object_id_to_string( account_object->get_id() );
owner_account_id = object_id_to_string(account_object->get_id());
owner_account_found = true;
}
else {
} else {
//! Check if we have account id
const auto& account_id = maybe_id<account_id_type>(account_name_or_id);
if(account_id) {
const auto &account_id = maybe_id<account_id_type>(account_name_or_id);
if (account_id) {
//! It may be account id
const auto& account_objects = get_accounts({account_name_or_id});
if(!account_objects.empty()){
const auto& account_object = account_objects.front();
if(account_object) {
const auto &account_objects = get_accounts({account_name_or_id});
if (!account_objects.empty()) {
const auto &account_object = account_objects.front();
if (account_object) {
//! It is account object
owner_account_id = object_id_to_string( account_object->get_id() );
owner_account_id = object_id_to_string(account_object->get_id());
owner_account_found = true;
}
}
}
else {
} else {
//! Check if we have committee member id
const auto& committee_member_id = maybe_id<committee_member_id_type>(account_name_or_id);
if(committee_member_id) {
const auto &committee_member_id = maybe_id<committee_member_id_type>(account_name_or_id);
if (committee_member_id) {
//! It may be committee member id
const auto& committee_member_objects = get_committee_members({*committee_member_id});
if(!committee_member_objects.empty()){
const auto& committee_member_object = committee_member_objects.front();
if(committee_member_object) {
const auto &committee_member_objects = get_committee_members({*committee_member_id});
if (!committee_member_objects.empty()) {
const auto &committee_member_object = committee_member_objects.front();
if (committee_member_object) {
//! It is committee member object
owner_account_id = object_id_to_string( committee_member_object->committee_member_account );
owner_account_id = object_id_to_string(committee_member_object->committee_member_account);
owner_account_found = true;
}
}
}
else {
} else {
//! Check if we have witness id
const auto& witness_id = maybe_id<witness_id_type>(account_name_or_id);
if(witness_id) {
const auto &witness_id = maybe_id<witness_id_type>(account_name_or_id);
if (witness_id) {
//! It may be witness id
const auto& witness_objects = get_witnesses({*witness_id});
if(!witness_objects.empty()){
const auto& witness_object = witness_objects.front();
if(witness_object) {
const auto &witness_objects = get_witnesses({*witness_id});
if (!witness_objects.empty()) {
const auto &witness_object = witness_objects.front();
if (witness_object) {
//! It is witness object
owner_account_id = object_id_to_string( witness_object->witness_account );
owner_account_id = object_id_to_string(witness_object->witness_account);
owner_account_found = true;
}
}
}
else {
} else {
//! Check if we have worker id
const auto& worker_id = maybe_id<worker_id_type>(account_name_or_id);
if(worker_id) {
const auto &worker_id = maybe_id<worker_id_type>(account_name_or_id);
if (worker_id) {
//! It may be worker id
const auto& worker_objects = get_workers({*worker_id});
if(!worker_objects.empty()){
const auto& worker_object = worker_objects.front();
if(worker_object) {
const auto &worker_objects = get_workers({*worker_id});
if (!worker_objects.empty()) {
const auto &worker_object = worker_objects.front();
if (worker_object) {
//! It is worker object
owner_account_id = object_id_to_string( worker_object->worker_account );
owner_account_id = object_id_to_string(worker_object->worker_account);
owner_account_found = true;
}
}
}
else {
} else {
//! Check if we have son id
const auto& son_id = maybe_id<son_id_type>(account_name_or_id);
if(son_id) {
const auto &son_id = maybe_id<son_id_type>(account_name_or_id);
if (son_id) {
//! It may be son id
const auto& son_objects = get_sons({*son_id});
if(!son_objects.empty()){
const auto& son_object = son_objects.front();
if(son_object) {
const auto &son_objects = get_sons({*son_id});
if (!son_objects.empty()) {
const auto &son_object = son_objects.front();
if (son_object) {
//! It is son object
owner_account_id = object_id_to_string( son_object->son_account );
owner_account_id = object_id_to_string(son_object->son_account);
owner_account_found = true;
}
}
@ -2231,41 +2295,41 @@ voters_info database_api_impl::get_voters(const string &account_name_or_id) cons
}
//! We didn't find who it was
if(!owner_account_found)
if (!owner_account_found)
FC_THROW_EXCEPTION(database_query_exception, "Wrong account_name_or_id: ${account_name_or_id}", ("account_name_or_id", account_name_or_id));
//! Fill voters_info
const auto& committee_member_object = get_committee_member_by_account(owner_account_id);
const auto& witness_object = get_witness_by_account(owner_account_id);
const auto& worker_objects = get_workers_by_account(owner_account_id);
const auto& son_object = get_son_by_account(owner_account_id);
const auto &committee_member_object = get_committee_member_by_account(owner_account_id);
const auto &witness_object = get_witness_by_account(owner_account_id);
const auto &worker_objects = get_workers_by_account(owner_account_id);
const auto &son_object = get_son_by_account(owner_account_id);
//! Info for committee member voters
if(committee_member_object) {
const auto& committee_member_voters = get_voters_by_id(committee_member_object->vote_id);
if (committee_member_object) {
const auto &committee_member_voters = get_voters_by_id(committee_member_object->vote_id);
voters_info_object voters_for_committee_member;
voters_for_committee_member.vote_id = committee_member_object->vote_id;
voters_for_committee_member.voters.reserve(committee_member_voters.size());
for(const auto& voter: committee_member_voters) {
for (const auto &voter : committee_member_voters) {
voters_for_committee_member.voters.emplace_back(voter.get_id());
}
result.voters_for_committee_member = std::move(voters_for_committee_member);
}
//! Info for witness voters
if(witness_object) {
const auto& witness_voters = get_voters_by_id(witness_object->vote_id);
if (witness_object) {
const auto &witness_voters = get_voters_by_id(witness_object->vote_id);
voters_info_object voters_for_witness;
voters_for_witness.vote_id = witness_object->vote_id;
voters_for_witness.voters.reserve(witness_voters.size());
for(const auto& voter: witness_voters) {
for (const auto &voter : witness_voters) {
voters_for_witness.voters.emplace_back(voter.get_id());
}
result.voters_for_witness = std::move(voters_for_witness);
}
//! Info for worker voters
if(!worker_objects.empty()) {
if (!worker_objects.empty()) {
vector<voters_info_object> voters_for_workers(worker_objects.size());
vector<voters_info_object> voters_against_workers(worker_objects.size());
for (const auto &worker_object : worker_objects) {
@ -2292,12 +2356,12 @@ voters_info database_api_impl::get_voters(const string &account_name_or_id) cons
}
//! Info for son voters
if(son_object) {
const auto& son_voters = get_voters_by_id(son_object->vote_id);
if (son_object) {
const auto &son_voters = get_voters_by_id(son_object->vote_id);
voters_info_object voters_for_son;
voters_for_son.vote_id = son_object->vote_id;
voters_for_son.voters.reserve(son_voters.size());
for(const auto& voter: son_voters) {
for (const auto &voter : son_voters) {
voters_for_son.voters.emplace_back(voter.get_id());
}
result.voters_for_son = std::move(voters_for_son);

View file

@ -56,8 +56,8 @@
#include <graphene/chain/custom_permission_object.hpp>
#include <graphene/chain/nft_object.hpp>
#include <graphene/chain/offer_object.hpp>
#include <graphene/chain/votes_info.hpp>
#include <graphene/chain/voters_info.hpp>
#include <graphene/chain/votes_info.hpp>
#include <graphene/market_history/market_history_plugin.hpp>
@ -560,6 +560,13 @@ public:
* @param account The ID of the account whose witness should be retrieved
* @return The witness object, or null if the account does not have a witness
*/
fc::optional<witness_object> get_witness_by_account_id(account_id_type account) const;
/**
* @brief Get the witness owned by a given account
* @param account_id_or_name The ID or name of the account whose witness should be retrieved
* @return The witness object, or null if the account does not have a witness
*/
fc::optional<witness_object> get_witness_by_account(const std::string account_name_or_id) const;
/**
@ -588,6 +595,13 @@ public:
*/
vector<optional<committee_member_object>> get_committee_members(const vector<committee_member_id_type> &committee_member_ids) const;
/**
* @brief Get the committee_member owned by a given account
* @param account The ID of the account whose committee_member should be retrieved
* @return The committee_member object, or null if the account does not have a committee_member
*/
fc::optional<committee_member_object> get_committee_member_by_account_id(account_id_type account) const;
/**
* @brief Get the committee_member owned by a given account
* @param account_id_or_name The ID or name of the account whose committee_member should be retrieved
@ -603,6 +617,11 @@ public:
*/
map<string, committee_member_id_type> lookup_committee_member_accounts(const string &lower_bound_name, uint32_t limit) const;
/**
* @brief Get the total number of committee_members registered with the blockchain
*/
uint64_t get_committee_member_count() const;
/////////////////
// SON members //
/////////////////
@ -625,7 +644,7 @@ public:
/**
* @brief Get the SON owned by a given account
* @param account The ID of the account whose SON should be retrieved
* @param account_id_or_name The ID of the account whose SON should be retrieved
* @return The SON object, or null if the account does not have a SON
*/
fc::optional<son_object> get_son_by_account(const std::string account_id_or_name) const;
@ -722,11 +741,31 @@ public:
/**
* @brief Return the worker objects associated with this account.
* @param account_id_or_name The ID or name of the account whose worker should be retrieved
* @param account The ID of the account whose workers should be retrieved
* @return The worker object or null if the account does not have a worker
*/
vector<worker_object> get_workers_by_account_id(account_id_type account) const;
/**
* @brief Return the worker objects associated with this account.
* @param account_id_or_name The ID or name of the account whose workers should be retrieved
* @return The worker object or null if the account does not have a worker
*/
vector<worker_object> get_workers_by_account(const std::string account_id_or_name) const;
/**
* @brief Get names and IDs for registered workers
* @param lower_bound_name Lower bound of the first name to return
* @param limit Maximum number of results to return -- must not exceed 1000
* @return Map of worker names to corresponding IDs
*/
map<string, worker_id_type> lookup_worker_accounts(const string &lower_bound_name, uint32_t limit) const;
/**
* @brief Get the total number of workers registered with the blockchain
*/
uint64_t get_worker_count() const;
///////////
// Votes //
///////////
@ -1086,14 +1125,17 @@ FC_API(graphene::app::database_api,
// Witnesses
(get_witnesses)
(get_witness_by_account_id)
(get_witness_by_account)
(lookup_witness_accounts)
(get_witness_count)
// Committee members
(get_committee_members)
(get_committee_member_by_account_id)
(get_committee_member_by_account)
(lookup_committee_member_accounts)
(get_committee_member_count)
// SON members
(get_sons)
@ -1116,7 +1158,10 @@ FC_API(graphene::app::database_api,
// Workers
(get_workers)
(get_workers_by_account_id)
(get_workers_by_account)
(lookup_worker_accounts)
(get_worker_count)
// Votes
(lookup_vote_ids)

@ -1 +1 @@
Subproject commit 86b77c6eb450f97a29c627d3fa9728e25bed933a
Subproject commit 1cc740598f5b7ec480ac76f60e19d0ccb1e1ac97

View file

@ -23,19 +23,11 @@ add_library( peerplays_sidechain
)
if (ENABLE_DEV_FEATURES)
set(ENABLE_MULTIPLE_SONS 1)
set(ENABLE_PEERPLAYS_ASSET_DEPOSITS 1)
endif()
unset(ENABLE_DEV_FEATURES)
unset(ENABLE_DEV_FEATURES CACHE)
if (ENABLE_MULTIPLE_SONS)
message ("Multiple SONs per software instance are supported")
target_compile_definitions(peerplays_sidechain PRIVATE ENABLE_MULTIPLE_SONS)
endif()
unset(ENABLE_MULTIPLE_SONS)
unset(ENABLE_MULTIPLE_SONS CACHE)
if (ENABLE_PEERPLAYS_ASSET_DEPOSITS)
message ("Depositing Peerplays assets enabled")
target_compile_definitions(peerplays_sidechain PRIVATE ENABLE_PEERPLAYS_ASSET_DEPOSITS)

View file

@ -3,7 +3,7 @@
#include <graphene/peerplays_sidechain/sidechain_net_handler.hpp>
#include <string>
#include <zmq.hpp>
#include <zmq_addon.hpp>
#include <boost/signals2.hpp>

View file

@ -176,12 +176,6 @@ void peerplays_sidechain_plugin_impl::plugin_initialize(const boost::program_opt
}
config_ready_son = config_ready_son && !sons.empty();
#ifndef ENABLE_MULTIPLE_SONS
if (sons.size() > 1) {
FC_THROW("Invalid configuration, multiple SON IDs provided");
}
#endif
if (options.count("peerplays-private-key")) {
const std::vector<std::string> key_id_to_wif_pair_strings = options["peerplays-private-key"].as<std::vector<std::string>>();
for (const std::string &key_id_to_wif_pair_string : key_id_to_wif_pair_strings) {

View file

@ -871,16 +871,11 @@ zmq_listener::zmq_listener(std::string _ip, uint32_t _zmq) :
std::vector<zmq::message_t> zmq_listener::receive_multipart() {
std::vector<zmq::message_t> msgs;
int32_t more;
size_t more_size = sizeof(more);
while (true) {
zmq::message_t msg;
socket.recv(&msg, 0);
socket.getsockopt(ZMQ_RCVMORE, &more, &more_size);
if (!more)
break;
msgs.push_back(std::move(msg));
auto res = zmq::recv_multipart(socket, std::back_inserter(msgs));
FC_ASSERT(res);
if (3 != *res) {
elog("zmq::recv_multipart returned: ${res}", ("res", *res));
throw zmq::error_t();
}
return msgs;
@ -902,6 +897,7 @@ void zmq_listener::handle_zmq() {
const auto block_hash = boost::algorithm::hex(std::string(static_cast<char *>(msg[1].data()), msg[1].size()));
event_received(block_hash);
} catch (zmq::error_t &e) {
elog("handle_zmq recv_multipart exception ${str}", ("str", e.what()));
}
}
}

View file

@ -1346,6 +1346,21 @@ class wallet_api
*/
map<string, committee_member_id_type> list_committee_members(const string& lowerbound, uint32_t limit);
/** Lists all workers in the blockchain.
* This returns a list of all account names that own worker, and the associated worker id,
* sorted by name. This lists workers whether they are currently voted in or not.
*
* Use the \c lowerbound and limit parameters to page through the list. To retrieve all workers,
* start by setting \c lowerbound to the empty string \c "", and then each iteration, pass
* the last worker name returned as the \c lowerbound for the next \c list_workers() call.
*
* @param lowerbound the name of the first worker to return. If the named worker does not exist,
* the list will start at the worker that comes after \c lowerbound
* @param limit the maximum number of worker to return (max: 1000)
* @returns a list of worker mapping worker names to worker ids
*/
map<string, worker_id_type> list_workers(const string& lowerbound, uint32_t limit);
/** Returns information about the given SON.
* @param owner_account the name or id of the SON account owner, or the id of the SON
* @returns the information about the SON stored in the block chain
@ -1370,6 +1385,12 @@ class wallet_api
*/
committee_member_object get_committee_member(string owner_account);
/** Returns information about the given worker.
* @param owner_account the name or id of the worker account owner, or the id of the worker
* @returns the information about the workers stored in the block chain
*/
vector<worker_object> get_workers(string owner_account);
/** Creates a SON object owned by the given account.
*
@ -2658,8 +2679,10 @@ FC_API( graphene::wallet::wallet_api,
(get_witness)
(is_witness)
(get_committee_member)
(get_workers)
(list_witnesses)
(list_committee_members)
(list_workers)
(create_son)
(try_create_son)
(update_son)

View file

@ -749,7 +749,7 @@ public:
{
std::string account_id = account_id_to_string(id);
auto rec = _remote_db->get_accounts({account_id}).front();
FC_ASSERT(rec);
FC_ASSERT(rec, "Accout id: ${account_id} doesn't exist", ("account_id", account_id));
return *rec;
}
account_object get_account(string account_name_or_id) const
@ -762,7 +762,7 @@ public:
return get_account(*id);
} else {
auto rec = _remote_db->lookup_account_names({account_name_or_id}).front();
FC_ASSERT( rec && rec->name == account_name_or_id );
FC_ASSERT( rec && rec->name == account_name_or_id, "Account name or id: ${account_name_or_id} doesn't exist", ("account_name_or_id",account_name_or_id ) );
return *rec;
}
}
@ -1961,6 +1961,49 @@ public:
FC_CAPTURE_AND_RETHROW( (owner_account) )
}
vector<worker_object> get_workers(string owner_account)
{
try
{
fc::optional<worker_id_type> worker_id = maybe_id<worker_id_type>(owner_account);
if (worker_id)
{
std::vector<worker_id_type> ids_to_get;
ids_to_get.push_back(*worker_id);
std::vector<fc::optional<worker_object>> worker_objects = _remote_db->get_workers(ids_to_get);
if(!worker_objects.empty()) {
std::vector<worker_object> result;
for (const auto &worker_object : worker_objects) {
if (worker_object)
result.emplace_back(*worker_object);
}
return result;
}
else
FC_THROW("No workers is registered for id ${id}", ("id", owner_account));
}
else
{
// then maybe it's the owner account
try
{
std::string owner_account_id = account_id_to_string(get_account_id(owner_account));
auto workers = _remote_db->get_workers_by_account(owner_account_id);
if (!workers.empty())
return workers;
else
FC_THROW("No workers is registered for account ${account}", ("account", owner_account));
}
catch (const fc::exception&)
{
FC_THROW("No account or worker named ${account}", ("account", owner_account));
}
}
}
FC_CAPTURE_AND_RETHROW( (owner_account) )
}
bool is_witness(string owner_account)
{
try
@ -4471,6 +4514,7 @@ asset wallet_api::get_lottery_balance( asset_id_type lottery_id )const
vector<operation_detail> wallet_api::get_account_history(string name, int limit) const
{
FC_ASSERT(my->get_account(name).name == name, "Account name: ${account_name} doesn't exist", ("account_name", name));
vector<operation_detail> result;
while (limit > 0)
@ -4525,6 +4569,8 @@ vector<operation_detail> wallet_api::get_relative_account_history(string name, u
{
FC_ASSERT( start > 0 || limit <= 100 );
FC_ASSERT(my->get_account(name).name == name, "Account name: ${account_name} doesn't exist", ("account_name", name));
vector<operation_detail> result;
@ -4700,7 +4746,7 @@ account_object wallet_api::get_account(string account_name_or_id) const
asset_object wallet_api::get_asset(string asset_name_or_id) const
{
auto a = my->find_asset(asset_name_or_id);
FC_ASSERT(a);
FC_ASSERT(a, "Asset name or id: ${asset_name_or_id} doesn't exist", ("asset_name_or_id", asset_name_or_id) );
return *a;
}
@ -4723,7 +4769,7 @@ asset_id_type wallet_api::get_asset_id(string asset_symbol_or_id) const
bool wallet_api::import_key(string account_name_or_id, string wif_key)
{
FC_ASSERT(!is_locked());
FC_ASSERT(!is_locked(), "Wallet is locked, please unlock to get all operations available");
// backup wallet
fc::optional<fc::ecc::private_key> optional_private_key = wif_to_key(wif_key);
if (!optional_private_key)
@ -4742,7 +4788,7 @@ bool wallet_api::import_key(string account_name_or_id, string wif_key)
map<string, bool> wallet_api::import_accounts( string filename, string password )
{
FC_ASSERT( !is_locked() );
FC_ASSERT( !is_locked(), "Wallet is locked, please unlock to get all operations available" );
FC_ASSERT( fc::exists( filename ) );
const auto imported_keys = fc::json::from_file<exported_keys>( filename );
@ -4812,7 +4858,7 @@ map<string, bool> wallet_api::import_accounts( string filename, string password
bool wallet_api::import_account_keys( string filename, string password, string src_account_name, string dest_account_name )
{
FC_ASSERT( !is_locked() );
FC_ASSERT( !is_locked(), "Wallet is locked, please unlock to get all operations available" );
FC_ASSERT( fc::exists( filename ) );
bool is_my_account = false;
@ -5027,6 +5073,11 @@ map<string,committee_member_id_type> wallet_api::list_committee_members(const st
return my->_remote_db->lookup_committee_member_accounts(lowerbound, limit);
}
map<string, worker_id_type> wallet_api::list_workers(const string& lowerbound, uint32_t limit)
{
return my->_remote_db->lookup_worker_accounts(lowerbound, limit);
}
son_object wallet_api::get_son(string owner_account)
{
return my->get_son(owner_account);
@ -5047,6 +5098,11 @@ committee_member_object wallet_api::get_committee_member(string owner_account)
return my->get_committee_member(owner_account);
}
vector<worker_object> wallet_api::get_workers(string owner_account)
{
return my->get_workers(owner_account);
}
signed_transaction wallet_api::create_vesting_balance(string owner_account,
string amount,
string asset_symbol,
@ -5351,13 +5407,13 @@ operation wallet_api::get_prototype_operation(string operation_name)
void wallet_api::dbg_make_uia(string creator, string symbol)
{
FC_ASSERT(!is_locked());
FC_ASSERT(!is_locked(), "Wallet is locked, please unlock to get all operations available");
my->dbg_make_uia(creator, symbol);
}
void wallet_api::dbg_make_mia(string creator, string symbol)
{
FC_ASSERT(!is_locked());
FC_ASSERT(!is_locked(), "Wallet is locked, please unlock to get all operations available");
my->dbg_make_mia(creator, symbol);
}
@ -5393,7 +5449,7 @@ vector< variant > wallet_api::network_get_connected_peers()
void wallet_api::flood_network(string prefix, uint32_t number_of_transactions)
{
FC_ASSERT(!is_locked());
FC_ASSERT(!is_locked(), "Wallet is locked, please unlock to get all operations available");
my->flood_network(prefix, number_of_transactions);
}
@ -5872,13 +5928,13 @@ signed_transaction wallet_api::buy( string buyer_account,
signed_transaction wallet_api::borrow_asset(string seller_name, string amount_to_sell,
string asset_symbol, string amount_of_collateral, bool broadcast)
{
FC_ASSERT(!is_locked());
FC_ASSERT(!is_locked(), "Wallet is locked, please unlock to get all operations available");
return my->borrow_asset(seller_name, amount_to_sell, asset_symbol, amount_of_collateral, broadcast);
}
signed_transaction wallet_api::cancel_order(object_id_type order_id, bool broadcast)
{
FC_ASSERT(!is_locked());
FC_ASSERT(!is_locked(), "Wallet is locked, please unlock to get all operations available");
return my->cancel_order(order_id, broadcast);
}
@ -5928,7 +5984,7 @@ map<string,public_key_type> wallet_api::get_blind_accounts()const
}
map<string,public_key_type> wallet_api::get_my_blind_accounts()const
{
FC_ASSERT( !is_locked() );
FC_ASSERT( !is_locked(), "Wallet is locked, please unlock to get all operations available" );
map<string,public_key_type> result;
for( const auto& item : my->_wallet.labeled_keys )
{
@ -5940,7 +5996,7 @@ map<string,public_key_type> wallet_api::get_my_blind_accounts()const
public_key_type wallet_api::create_blind_account( string label, string brain_key )
{
FC_ASSERT( !is_locked() );
FC_ASSERT( !is_locked(), "Wallet is locked, please unlock to get all operations available" );
auto label_itr = my->_wallet.labeled_keys.get<by_label>().find(label);
if( label_itr != my->_wallet.labeled_keys.get<by_label>().end() )
@ -6068,7 +6124,7 @@ blind_confirmation wallet_api::blind_transfer_help( string from_key_or_label,
blind_confirmation confirm;
try {
FC_ASSERT( !is_locked() );
FC_ASSERT( !is_locked(), "Wallet is locked, please unlock to get all operations available" );
public_key_type from_key = get_public_key(from_key_or_label);
public_key_type to_key = get_public_key(to_key_or_label);
@ -6237,7 +6293,7 @@ blind_confirmation wallet_api::transfer_to_blind( string from_account_id_or_name
vector<pair<string, string>> to_amounts,
bool broadcast )
{ try {
FC_ASSERT( !is_locked() );
FC_ASSERT( !is_locked(), "Wallet is locked, please unlock to get all operations available" );
idump((to_amounts));
blind_confirmation confirm;
@ -6317,7 +6373,7 @@ blind_confirmation wallet_api::transfer_to_blind( string from_account_id_or_name
blind_receipt wallet_api::receive_blind_transfer( string confirmation_receipt, string opt_from, string opt_memo )
{
FC_ASSERT( !is_locked() );
FC_ASSERT( !is_locked(), "Wallet is locked, please unlock to get all operations available" );
stealth_confirmation conf(confirmation_receipt);
FC_ASSERT( conf.to );
@ -6459,7 +6515,7 @@ signed_transaction wallet_api::propose_create_sport(
internationalized_string_type name,
bool broadcast /*= false*/)
{
FC_ASSERT( !is_locked() );
FC_ASSERT( !is_locked(), "Wallet is locked, please unlock to get all operations available" );
const chain_parameters& current_params = get_global_properties().parameters;
sport_create_operation sport_create_op;
@ -6487,7 +6543,7 @@ signed_transaction wallet_api::propose_update_sport(
fc::optional<internationalized_string_type> name,
bool broadcast /*= false*/)
{
FC_ASSERT( !is_locked() );
FC_ASSERT( !is_locked() , "Wallet is locked, please unlock to get all operations available" );
const chain_parameters& current_params = get_global_properties().parameters;
sport_update_operation sport_update_op;
@ -6515,7 +6571,7 @@ signed_transaction wallet_api::propose_delete_sport(
sport_id_type sport_id,
bool broadcast /*= false*/)
{
FC_ASSERT( !is_locked() );
FC_ASSERT( !is_locked() , "Wallet is locked, please unlock to get all operations available" );
const chain_parameters& current_params = get_global_properties().parameters;
sport_delete_operation sport_delete_op;
@ -6543,7 +6599,7 @@ signed_transaction wallet_api::propose_create_event_group(
sport_id_type sport_id,
bool broadcast /*= false*/)
{
FC_ASSERT( !is_locked() );
FC_ASSERT( !is_locked(), "Wallet is locked, please unlock to get all operations available" );
const chain_parameters& current_params = get_global_properties().parameters;
event_group_create_operation event_group_create_op;
@ -6573,7 +6629,7 @@ signed_transaction wallet_api::propose_update_event_group(
fc::optional<internationalized_string_type> name,
bool broadcast /*= false*/)
{
FC_ASSERT( !is_locked() );
FC_ASSERT( !is_locked() , "Wallet is locked, please unlock to get all operations available" );
const chain_parameters& current_params = get_global_properties().parameters;
event_group_update_operation event_group_update_op;
@ -6602,7 +6658,7 @@ signed_transaction wallet_api::propose_delete_event_group(
event_group_id_type event_group,
bool broadcast /*= false*/)
{
FC_ASSERT( !is_locked() );
FC_ASSERT( !is_locked() , "Wallet is locked, please unlock to get all operations available" );
const chain_parameters& current_params = get_global_properties().parameters;
event_group_delete_operation event_group_delete_op;
@ -6632,7 +6688,7 @@ signed_transaction wallet_api::propose_create_event(
event_group_id_type event_group_id,
bool broadcast /*= false*/)
{
FC_ASSERT( !is_locked() );
FC_ASSERT( !is_locked() , "Wallet is locked, please unlock to get all operations available" );
const chain_parameters& current_params = get_global_properties().parameters;
event_create_operation event_create_op;
@ -6667,7 +6723,7 @@ signed_transaction wallet_api::propose_update_event(
fc::optional<time_point_sec> start_time,
bool broadcast /*= false*/)
{
FC_ASSERT( !is_locked() );
FC_ASSERT( !is_locked() , "Wallet is locked, please unlock to get all operations available" );
const chain_parameters& current_params = get_global_properties().parameters;
event_update_operation event_update_op;
@ -6700,7 +6756,7 @@ signed_transaction wallet_api::propose_create_betting_market_rules(
internationalized_string_type description,
bool broadcast /*= false*/)
{
FC_ASSERT( !is_locked() );
FC_ASSERT( !is_locked() , "Wallet is locked, please unlock to get all operations available" );
const chain_parameters& current_params = get_global_properties().parameters;
betting_market_rules_create_operation betting_market_rules_create_op;
@ -6730,7 +6786,7 @@ signed_transaction wallet_api::propose_update_betting_market_rules(
fc::optional<internationalized_string_type> description,
bool broadcast /*= false*/)
{
FC_ASSERT( !is_locked() );
FC_ASSERT( !is_locked() , "Wallet is locked, please unlock to get all operations available" );
const chain_parameters& current_params = get_global_properties().parameters;
betting_market_rules_update_operation betting_market_rules_update_op;
@ -6762,7 +6818,7 @@ signed_transaction wallet_api::propose_create_betting_market_group(
asset_id_type asset_id,
bool broadcast /*= false*/)
{
FC_ASSERT( !is_locked() );
FC_ASSERT( !is_locked() , "Wallet is locked, please unlock to get all operations available" );
const chain_parameters& current_params = get_global_properties().parameters;
betting_market_group_create_operation betting_market_group_create_op;
@ -6795,7 +6851,7 @@ signed_transaction wallet_api::propose_update_betting_market_group(
fc::optional<betting_market_group_status> status,
bool broadcast /*= false*/)
{
FC_ASSERT( !is_locked() );
FC_ASSERT( !is_locked() , "Wallet is locked, please unlock to get all operations available" );
const chain_parameters& current_params = get_global_properties().parameters;
betting_market_group_update_operation betting_market_group_update_op;
@ -6827,7 +6883,7 @@ signed_transaction wallet_api::propose_create_betting_market(
internationalized_string_type payout_condition,
bool broadcast /*= false*/)
{
FC_ASSERT( !is_locked() );
FC_ASSERT( !is_locked() , "Wallet is locked, please unlock to get all operations available" );
const chain_parameters& current_params = get_global_properties().parameters;
betting_market_create_operation betting_market_create_op;
@ -6859,7 +6915,7 @@ signed_transaction wallet_api::propose_update_betting_market(
fc::optional<internationalized_string_type> payout_condition,
bool broadcast /*= false*/)
{
FC_ASSERT( !is_locked() );
FC_ASSERT( !is_locked() , "Wallet is locked, please unlock to get all operations available" );
const chain_parameters& current_params = get_global_properties().parameters;
betting_market_update_operation betting_market_update_op;
@ -6891,7 +6947,7 @@ signed_transaction wallet_api::place_bet(string betting_account,
double backer_multiplier,
bool broadcast /*= false*/)
{
FC_ASSERT( !is_locked() );
FC_ASSERT( !is_locked(), "Wallet is locked, please unlock to get all operations available" );
fc::optional<asset_object> asset_obj = get_asset(asset_symbol);
FC_ASSERT(asset_obj, "Could not find asset matching ${asset}", ("asset", asset_symbol));
@ -6916,7 +6972,7 @@ signed_transaction wallet_api::cancel_bet(string betting_account,
bet_id_type bet_id,
bool broadcast /*= false*/)
{
FC_ASSERT( !is_locked() );
FC_ASSERT( !is_locked(), "Wallet is locked, please unlock to get all operations available" );
const chain_parameters& current_params = get_global_properties().parameters;
@ -6939,7 +6995,7 @@ signed_transaction wallet_api::propose_resolve_betting_market_group(
const std::map<betting_market_id_type, betting_market_resolution_type>& resolutions,
bool broadcast /*= false*/)
{
FC_ASSERT( !is_locked() );
FC_ASSERT( !is_locked(), "Wallet is locked, please unlock to get all operations available" );
const chain_parameters& current_params = get_global_properties().parameters;
betting_market_group_resolve_operation betting_market_group_resolve_op;
@ -6967,7 +7023,7 @@ signed_transaction wallet_api::propose_cancel_betting_market_group(
betting_market_group_id_type betting_market_group_id,
bool broadcast /*= false*/)
{
FC_ASSERT( !is_locked() );
FC_ASSERT( !is_locked(), "Wallet is locked, please unlock to get all operations available" );
const chain_parameters& current_params = get_global_properties().parameters;
betting_market_group_cancel_unmatched_bets_operation betting_market_group_cancel_unmatched_bets_op;
@ -6990,7 +7046,7 @@ signed_transaction wallet_api::propose_cancel_betting_market_group(
signed_transaction wallet_api::tournament_create( string creator, tournament_options options, bool broadcast )
{
FC_ASSERT( !is_locked() );
FC_ASSERT( !is_locked(), "Wallet is locked, please unlock to get all operations available" );
account_object creator_account_obj = get_account(creator);
signed_transaction tx;
@ -7011,7 +7067,7 @@ signed_transaction wallet_api::tournament_join( string payer_account,
string buy_in_asset_symbol,
bool broadcast )
{
FC_ASSERT( !is_locked() );
FC_ASSERT( !is_locked(), "Wallet is locked, please unlock to get all operations available" );
account_object payer_account_obj = get_account(payer_account);
account_object player_account_obj = get_account(player_account);
//graphene::chain::tournament_object tournament_obj = my->get_object<graphene::chain::tournament_object>(tournament_id);
@ -7038,7 +7094,7 @@ signed_transaction wallet_api::tournament_leave( string canceling_account,
tournament_id_type tournament_id,
bool broadcast)
{
FC_ASSERT( !is_locked() );
FC_ASSERT( !is_locked(), "Wallet is locked, please unlock to get all operations available" );
account_object player_account_obj = get_account(player_account);
account_object canceling_account_obj = get_account(canceling_account);
//graphene::chain::tournament_object tournament_obj = my->get_object<graphene::chain::tournament_object>(tournament_id);
@ -7083,7 +7139,7 @@ signed_transaction wallet_api::rps_throw(game_id_type game_id,
rock_paper_scissors_gesture gesture,
bool broadcast)
{
FC_ASSERT( !is_locked() );
FC_ASSERT( !is_locked(), "Wallet is locked, please unlock to get all operations available" );
// check whether the gesture is appropriate for the game we're playing
graphene::chain::game_object game_obj = my->get_object<graphene::chain::game_object>(game_id);

View file

@ -27,8 +27,18 @@
#include <iostream>
#include <iterator>
#include <boost/algorithm/string/replace.hpp>
#include <boost/program_options.hpp>
#include <boost/program_options/parsers.hpp>
#include <boost/version.hpp>
#include <fc/interprocess/signals.hpp>
#include <fc/io/json.hpp>
#include <fc/io/stdio.hpp>
#include <fc/log/console_appender.hpp>
#include <fc/log/file_appender.hpp>
#include <fc/log/logger.hpp>
#include <fc/log/logger_config.hpp>
#include <fc/network/http/server.hpp>
#include <fc/network/http/websocket.hpp>
#include <fc/rpc/cli.hpp>
@ -40,25 +50,14 @@
#include <graphene/chain/config.hpp>
#include <graphene/chain/protocol/protocol.hpp>
#include <graphene/egenesis/egenesis.hpp>
#include <graphene/utilities/git_revision.hpp>
#include <graphene/utilities/key_conversion.hpp>
#include <graphene/wallet/wallet.hpp>
#include <fc/interprocess/signals.hpp>
#include <boost/program_options.hpp>
#include <fc/log/console_appender.hpp>
#include <fc/log/file_appender.hpp>
#include <fc/log/logger.hpp>
#include <fc/log/logger_config.hpp>
#include <graphene/utilities/git_revision.hpp>
#include <boost/version.hpp>
#include <boost/algorithm/string/replace.hpp>
#ifdef WIN32
# include <signal.h>
#include <signal.h>
#else
# include <csignal>
#include <csignal>
#endif
using namespace graphene::app;
@ -68,44 +67,57 @@ using namespace graphene::wallet;
using namespace std;
namespace bpo = boost::program_options;
int main( int argc, char** argv )
{
int main(int argc, char **argv) {
try {
boost::program_options::options_description opts;
opts.add_options()
("help,h", "Print this help message and exit.")
("version", "Display the version info and exit")
("server-rpc-endpoint,s", bpo::value<string>()->implicit_value("ws://127.0.0.1:8090"), "Server websocket RPC endpoint")
("server-rpc-user,u", bpo::value<string>(), "Server Username")
("server-rpc-password,p", bpo::value<string>(), "Server Password")
("rpc-endpoint,r", bpo::value<string>()->implicit_value("127.0.0.1:8091"), "Endpoint for wallet websocket RPC to listen on")
("rpc-tls-endpoint,t", bpo::value<string>()->implicit_value("127.0.0.1:8092"), "Endpoint for wallet websocket TLS RPC to listen on")
("rpc-tls-certificate,c", bpo::value<string>()->implicit_value("server.pem"), "PEM certificate for wallet websocket TLS RPC")
("rpc-http-endpoint,H", bpo::value<string>()->implicit_value("127.0.0.1:8093"), "Endpoint for wallet HTTP RPC to listen on")
("daemon,d", "Run the wallet in daemon mode" )
("wallet-file,w", bpo::value<string>()->implicit_value("wallet.json"), "wallet to load")
("chain-id", bpo::value<string>(), "chain ID to connect to");
opts.add_options()("help,h", "Print this help message and exit.");
opts.add_options()("version,v", "Display the version info and exit");
opts.add_options()("server-rpc-endpoint,s", bpo::value<string>()->implicit_value("ws://127.0.0.1:8090"), "Server websocket RPC endpoint");
opts.add_options()("server-rpc-user,u", bpo::value<string>(), "Server Username");
opts.add_options()("server-rpc-password,p", bpo::value<string>(), "Server Password");
opts.add_options()("rpc-endpoint,r", bpo::value<string>()->implicit_value("127.0.0.1:8091"), "Endpoint for wallet websocket RPC to listen on");
opts.add_options()("rpc-tls-endpoint,t", bpo::value<string>()->implicit_value("127.0.0.1:8092"), "Endpoint for wallet websocket TLS RPC to listen on");
opts.add_options()("rpc-tls-certificate,c", bpo::value<string>()->implicit_value("server.pem"), "PEM certificate for wallet websocket TLS RPC");
opts.add_options()("rpc-http-endpoint,H", bpo::value<string>()->implicit_value("127.0.0.1:8093"), "Endpoint for wallet HTTP RPC to listen on");
opts.add_options()("daemon,d", "Run the wallet in daemon mode");
opts.add_options()("wallet-file,w", bpo::value<string>()->implicit_value("wallet.json"), "wallet to load");
opts.add_options()("chain-id", bpo::value<string>(), "chain ID to connect to");
bpo::variables_map options;
bpo::store( bpo::parse_command_line(argc, argv, opts), options );
if( options.count("help") )
try
{
bpo::parsed_options po = bpo::command_line_parser(argc, argv).options(opts).allow_unregistered().run();
std::vector<std::string> unrecognized = bpo::collect_unrecognized(po.options, bpo::include_positional);
if (unrecognized.size() > 0) {
std::cout << "Unknown parameter(s): " << std::endl;
for (auto s : unrecognized) {
std::cout << " " << s << std::endl;
}
return 0;
}
bpo::store(po, options);
}
catch (const boost::program_options::invalid_command_line_syntax & e)
{
std::cout << e.what() << std::endl;
return 0;
}
if (options.count("help")) {
std::cout << opts << "\n";
return 0;
}
if (options.count("version"))
{
if (options.count("version")) {
std::string wallet_version(graphene::utilities::git_revision_description);
const size_t pos = wallet_version.find('/');
if( pos != std::string::npos && wallet_version.size() > pos )
wallet_version = wallet_version.substr( pos + 1 );
std::cerr << "Version: " << wallet_version << "\n";
std::cerr << "Git Revision: " << graphene::utilities::git_revision_sha << "\n";
std::cerr << "Built: " << __DATE__ " at " __TIME__ << "\n";
if (pos != std::string::npos && wallet_version.size() > pos)
wallet_version = wallet_version.substr(pos + 1);
std::cout << "Version: " << wallet_version << "\n";
std::cout << "Git Revision: " << graphene::utilities::git_revision_sha << "\n";
std::cout << "Built: " << __DATE__ " at " __TIME__ << "\n";
std::cout << "SSL: " << OPENSSL_VERSION_TEXT << "\n";
std::cout << "Boost: " << boost::replace_all_copy(std::string(BOOST_LIB_VERSION), "_", ".") << "\n";
return 0;
@ -116,33 +128,33 @@ int main( int argc, char** argv )
fc::path log_dir = data_dir / "logs";
fc::file_appender::config ac;
ac.filename = log_dir / "rpc" / "rpc.log";
ac.flush = true;
ac.rotate = true;
ac.rotation_interval = fc::hours( 1 );
ac.rotation_limit = fc::days( 1 );
ac.filename = log_dir / "rpc" / "rpc.log";
ac.flush = true;
ac.rotate = true;
ac.rotation_interval = fc::hours(1);
ac.rotation_limit = fc::days(1);
std::cout << "Logging RPC to file: " << (data_dir / ac.filename).preferred_string() << "\n";
cfg.appenders.push_back(fc::appender_config( "default", "console", fc::variant(fc::console_appender::config(), 20)));
cfg.appenders.push_back(fc::appender_config( "rpc", "file", fc::variant(ac, 5)));
cfg.appenders.push_back(fc::appender_config("default", "console", fc::variant(fc::console_appender::config(), 20)));
cfg.appenders.push_back(fc::appender_config("rpc", "file", fc::variant(ac, 5)));
cfg.loggers = { fc::logger_config("default"), fc::logger_config( "rpc") };
cfg.loggers = {fc::logger_config("default"), fc::logger_config("rpc")};
cfg.loggers.front().level = fc::log_level::warn;
cfg.loggers.front().appenders = {"default"};
cfg.loggers.back().level = fc::log_level::info;
cfg.loggers.back().appenders = {"rpc"};
fc::configure_logging( cfg );
fc::configure_logging(cfg);
fc::ecc::private_key committee_private_key = fc::ecc::private_key::regenerate(fc::sha256::hash(string("null_key")));
idump( (key_to_wif( committee_private_key ) ) );
idump((key_to_wif(committee_private_key)));
fc::ecc::private_key nathan_private_key = fc::ecc::private_key::regenerate(fc::sha256::hash(string("nathan")));
public_key_type nathan_pub_key = nathan_private_key.get_public_key();
idump( (nathan_pub_key) );
idump( (key_to_wif( nathan_private_key ) ) );
idump((nathan_pub_key));
idump((key_to_wif(nathan_private_key)));
//
// TODO: We read wallet_data twice, once in main() to grab the
@ -152,153 +164,136 @@ int main( int argc, char** argv )
//
wallet_data wdata;
fc::path wallet_file( options.count("wallet-file") ? options.at("wallet-file").as<string>() : "wallet.json");
if( fc::exists( wallet_file ) )
{
wdata = fc::json::from_file( wallet_file ).as<wallet_data>( GRAPHENE_MAX_NESTED_OBJECTS );
if( options.count("chain-id") )
{
fc::path wallet_file(options.count("wallet-file") ? options.at("wallet-file").as<string>() : "wallet.json");
if (fc::exists(wallet_file)) {
wdata = fc::json::from_file(wallet_file).as<wallet_data>(GRAPHENE_MAX_NESTED_OBJECTS);
if (options.count("chain-id")) {
// the --chain-id on the CLI must match the chain ID embedded in the wallet file
if( chain_id_type(options.at("chain-id").as<std::string>()) != wdata.chain_id )
{
if (chain_id_type(options.at("chain-id").as<std::string>()) != wdata.chain_id) {
std::cout << "Chain ID in wallet file does not match specified chain ID\n";
return 1;
}
}
}
else
{
if( options.count("chain-id") )
{
} else {
if (options.count("chain-id")) {
wdata.chain_id = chain_id_type(options.at("chain-id").as<std::string>());
std::cout << "Starting a new wallet with chain ID " << wdata.chain_id.str() << " (from CLI)\n";
}
else
{
} else {
wdata.chain_id = graphene::egenesis::get_egenesis_chain_id();
std::cout << "Starting a new wallet with chain ID " << wdata.chain_id.str() << " (from egenesis)\n";
}
}
// but allow CLI to override
if( options.count("server-rpc-endpoint") )
if (options.count("server-rpc-endpoint"))
wdata.ws_server = options.at("server-rpc-endpoint").as<std::string>();
if( options.count("server-rpc-user") )
if (options.count("server-rpc-user"))
wdata.ws_user = options.at("server-rpc-user").as<std::string>();
if( options.count("server-rpc-password") )
if (options.count("server-rpc-password"))
wdata.ws_password = options.at("server-rpc-password").as<std::string>();
fc::http::websocket_client client;
idump((wdata.ws_server));
auto con = client.connect( wdata.ws_server );
auto con = client.connect(wdata.ws_server);
auto apic = std::make_shared<fc::rpc::websocket_api_connection>(con, GRAPHENE_MAX_NESTED_OBJECTS);
auto remote_api = apic->get_remote_api< login_api >(1);
edump((wdata.ws_user)(wdata.ws_password) );
FC_ASSERT( remote_api->login( wdata.ws_user, wdata.ws_password ), "Failed to log in to API server" );
auto remote_api = apic->get_remote_api<login_api>(1);
edump((wdata.ws_user)(wdata.ws_password));
FC_ASSERT(remote_api->login(wdata.ws_user, wdata.ws_password), "Failed to log in to API server");
auto wapiptr = std::make_shared<wallet_api>( wdata, remote_api );
wapiptr->set_wallet_filename( wallet_file.generic_string() );
auto wapiptr = std::make_shared<wallet_api>(wdata, remote_api);
wapiptr->set_wallet_filename(wallet_file.generic_string());
wapiptr->load_wallet_file();
fc::api<wallet_api> wapi(wapiptr);
auto wallet_cli = std::make_shared<fc::rpc::cli>( GRAPHENE_MAX_NESTED_OBJECTS );
for( auto& name_formatter : wapiptr->get_result_formatters() )
wallet_cli->format_result( name_formatter.first, name_formatter.second );
auto wallet_cli = std::make_shared<fc::rpc::cli>(GRAPHENE_MAX_NESTED_OBJECTS);
for (auto &name_formatter : wapiptr->get_result_formatters())
wallet_cli->format_result(name_formatter.first, name_formatter.second);
boost::signals2::scoped_connection closed_connection(con->closed.connect([wallet_cli]{
boost::signals2::scoped_connection closed_connection(con->closed.connect([wallet_cli] {
cerr << "Server has disconnected us.\n";
wallet_cli->stop();
}));
(void)(closed_connection);
if( wapiptr->is_new() )
{
if (wapiptr->is_new()) {
std::cout << "Please use the set_password method to initialize a new wallet before continuing\n";
wallet_cli->set_prompt( "new >>> " );
wallet_cli->set_prompt("new >>> ");
} else
wallet_cli->set_prompt( "locked >>> " );
wallet_cli->set_prompt("locked >>> ");
boost::signals2::scoped_connection locked_connection(wapiptr->lock_changed.connect([&](bool locked) {
wallet_cli->set_prompt( locked ? "locked >>> " : "unlocked >>> " );
wallet_cli->set_prompt(locked ? "locked >>> " : "unlocked >>> ");
}));
std::shared_ptr<fc::http::websocket_server> _websocket_server;
if( options.count("rpc-endpoint") )
{
if (options.count("rpc-endpoint")) {
_websocket_server = std::make_shared<fc::http::websocket_server>();
_websocket_server->on_connection([&wapi]( const fc::http::websocket_connection_ptr& c ){
_websocket_server->on_connection([&wapi](const fc::http::websocket_connection_ptr &c) {
std::cout << "here... \n";
wlog("." );
wlog(".");
auto wsc = std::make_shared<fc::rpc::websocket_api_connection>(c, GRAPHENE_MAX_NESTED_OBJECTS);
wsc->register_api(wapi);
c->set_session_data( wsc );
c->set_session_data(wsc);
});
ilog( "Listening for incoming RPC requests on ${p}", ("p", options.at("rpc-endpoint").as<string>() ));
_websocket_server->listen( fc::ip::endpoint::from_string(options.at("rpc-endpoint").as<string>()) );
ilog("Listening for incoming RPC requests on ${p}", ("p", options.at("rpc-endpoint").as<string>()));
_websocket_server->listen(fc::ip::endpoint::from_string(options.at("rpc-endpoint").as<string>()));
_websocket_server->start_accept();
}
string cert_pem = "server.pem";
if( options.count( "rpc-tls-certificate" ) )
if (options.count("rpc-tls-certificate"))
cert_pem = options.at("rpc-tls-certificate").as<string>();
std::shared_ptr<fc::http::websocket_tls_server> _websocket_tls_server;
if( options.count("rpc-tls-endpoint") )
{
if (options.count("rpc-tls-endpoint")) {
_websocket_tls_server = std::make_shared<fc::http::websocket_tls_server>(cert_pem);
_websocket_tls_server->on_connection([&]( const fc::http::websocket_connection_ptr& c ){
_websocket_tls_server->on_connection([&](const fc::http::websocket_connection_ptr &c) {
auto wsc = std::make_shared<fc::rpc::websocket_api_connection>(c, GRAPHENE_MAX_NESTED_OBJECTS);
wsc->register_api(wapi);
c->set_session_data( wsc );
c->set_session_data(wsc);
});
ilog( "Listening for incoming TLS RPC requests on ${p}", ("p", options.at("rpc-tls-endpoint").as<string>() ));
_websocket_tls_server->listen( fc::ip::endpoint::from_string(options.at("rpc-tls-endpoint").as<string>()) );
ilog("Listening for incoming TLS RPC requests on ${p}", ("p", options.at("rpc-tls-endpoint").as<string>()));
_websocket_tls_server->listen(fc::ip::endpoint::from_string(options.at("rpc-tls-endpoint").as<string>()));
_websocket_tls_server->start_accept();
}
auto _http_server = std::make_shared<fc::http::server>();
if( options.count("rpc-http-endpoint" ) )
{
ilog( "Listening for incoming HTTP RPC requests on ${p}", ("p", options.at("rpc-http-endpoint").as<string>() ) );
_http_server->listen( fc::ip::endpoint::from_string( options.at( "rpc-http-endpoint" ).as<string>() ) );
if (options.count("rpc-http-endpoint")) {
ilog("Listening for incoming HTTP RPC requests on ${p}", ("p", options.at("rpc-http-endpoint").as<string>()));
_http_server->listen(fc::ip::endpoint::from_string(options.at("rpc-http-endpoint").as<string>()));
//
// due to implementation, on_request() must come AFTER listen()
//
_http_server->on_request(
[&wapi]( const fc::http::request& req, const fc::http::server::response& resp )
{
std::shared_ptr< fc::rpc::http_api_connection > conn =
std::make_shared< fc::rpc::http_api_connection >( GRAPHENE_MAX_NESTED_OBJECTS );
conn->register_api( wapi );
conn->on_request( req, resp );
} );
[&wapi](const fc::http::request &req, const fc::http::server::response &resp) {
std::shared_ptr<fc::rpc::http_api_connection> conn =
std::make_shared<fc::rpc::http_api_connection>(GRAPHENE_MAX_NESTED_OBJECTS);
conn->register_api(wapi);
conn->on_request(req, resp);
});
}
if( !options.count( "daemon" ) )
{
wallet_cli->register_api( wapi );
if (!options.count("daemon")) {
wallet_cli->register_api(wapi);
wallet_cli->start();
wallet_cli->wait();
}
else
{
fc::promise<int>::ptr exit_promise = new fc::promise<int>("UNIX Signal Handler");
fc::set_signal_handler([&exit_promise](int signal) {
exit_promise->set_value(signal);
}, SIGINT);
} else {
fc::promise<int>::ptr exit_promise = new fc::promise<int>("UNIX Signal Handler");
fc::set_signal_handler([&exit_promise](int signal) {
exit_promise->set_value(signal);
},
SIGINT);
ilog( "Entering Daemon Mode, ^C to exit" );
exit_promise->wait();
ilog("Entering Daemon Mode, ^C to exit");
exit_promise->wait();
}
wapi->save_wallet_file(wallet_file.generic_string());
locked_connection.disconnect();
closed_connection.disconnect();
}
catch ( const fc::exception& e )
{
} catch (const fc::exception &e) {
std::cout << e.to_detail_string() << "\n";
return -1;
}

View file

@ -27,7 +27,7 @@
#include <fc/crypto/digest.hpp>
#include <boost/test/auto_unit_test.hpp>
#include <boost/test/unit_test.hpp>
using namespace graphene::chain;