Merge branch 'beatrice' into 'master'
Merge beatrice to master 2022-04 See merge request PBSA/peerplays!84
This commit is contained in:
commit
6a59d9efba
66 changed files with 3960 additions and 1822 deletions
|
|
@ -1,6 +1,5 @@
|
|||
---
|
||||
Language: Cpp
|
||||
# BasedOnStyle: LLVM
|
||||
AccessModifierOffset: -3
|
||||
AlignAfterOpenBracket: Align
|
||||
AlignConsecutiveMacros: false
|
||||
|
|
@ -12,7 +11,7 @@ AlignTrailingComments: true
|
|||
AllowAllArgumentsOnNextLine: true
|
||||
AllowAllConstructorInitializersOnNextLine: false
|
||||
AllowAllParametersOfDeclarationOnNextLine: true
|
||||
AllowShortBlocksOnASingleLine: false
|
||||
AllowShortBlocksOnASingleLine: Never
|
||||
AllowShortCaseLabelsOnASingleLine: false
|
||||
AllowShortFunctionsOnASingleLine: None
|
||||
AllowShortLambdasOnASingleLine: None
|
||||
|
|
@ -57,6 +56,7 @@ ConstructorInitializerAllOnOneLineOrOnePerLine: true
|
|||
ConstructorInitializerIndentWidth: 6
|
||||
ContinuationIndentWidth: 6
|
||||
Cpp11BracedListStyle: true
|
||||
DeriveLineEnding: true
|
||||
DerivePointerAlignment: false
|
||||
DisableFormat: false
|
||||
ExperimentalAutoDetectBinPacking: false
|
||||
|
|
@ -69,12 +69,17 @@ IncludeBlocks: Preserve
|
|||
IncludeCategories:
|
||||
- Regex: '^"(llvm|llvm-c|clang|clang-c)/'
|
||||
Priority: 2
|
||||
SortPriority: 0
|
||||
- Regex: '^(<|"(gtest|gmock|isl|json)/)'
|
||||
Priority: 3
|
||||
SortPriority: 0
|
||||
- Regex: '.*'
|
||||
Priority: 1
|
||||
SortPriority: 0
|
||||
IncludeIsMainRegex: '(Test)?$'
|
||||
IncludeIsMainSourceRegex: ''
|
||||
IndentCaseLabels: false
|
||||
IndentGotoLabels: false
|
||||
IndentPPDirectives: None
|
||||
IndentWidth: 3
|
||||
IndentWrappedFunctionNames: false
|
||||
|
|
@ -110,18 +115,22 @@ SpaceBeforeCtorInitializerColon: true
|
|||
SpaceBeforeInheritanceColon: true
|
||||
SpaceBeforeParens: ControlStatements
|
||||
SpaceBeforeRangeBasedForLoopColon: true
|
||||
SpaceInEmptyBlock: false
|
||||
SpaceInEmptyParentheses: false
|
||||
SpacesBeforeTrailingComments: 1
|
||||
SpacesInAngles: false
|
||||
SpacesInConditionalStatement: false
|
||||
SpacesInContainerLiterals: true
|
||||
SpacesInCStyleCastParentheses: false
|
||||
SpacesInParentheses: false
|
||||
SpacesInSquareBrackets: false
|
||||
Standard: Cpp11
|
||||
SpaceBeforeSquareBrackets: false
|
||||
Standard: Latest
|
||||
StatementMacros:
|
||||
- Q_UNUSED
|
||||
- QT_REQUIRE_VERSION
|
||||
TabWidth: 3
|
||||
UseCRLF: false
|
||||
UseTab: Never
|
||||
...
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
2
.gitmodules
vendored
2
.gitmodules
vendored
|
|
@ -4,6 +4,6 @@
|
|||
ignore = dirty
|
||||
[submodule "libraries/fc"]
|
||||
path = libraries/fc
|
||||
url = https://github.com/peerplays-network/peerplays-fc.git
|
||||
url = https://gitlab.com/PBSA/tools-libs/peerplays-fc.git
|
||||
branch = latest-fc
|
||||
ignore = dirty
|
||||
|
|
|
|||
|
|
@ -83,7 +83,6 @@ LIST(APPEND BOOST_COMPONENTS thread
|
|||
system
|
||||
filesystem
|
||||
program_options
|
||||
signals
|
||||
serialization
|
||||
chrono
|
||||
unit_test_framework
|
||||
|
|
|
|||
88
README.md
88
README.md
|
|
@ -2,95 +2,81 @@ Intro for new developers and witnesses
|
|||
------------------------
|
||||
|
||||
This is a quick introduction to get new developers and witnesses up to speed on Peerplays blockchain. It is intended for witnesses plannig to join a live, already deployed blockchain.
|
||||
# Building on Ubuntu 18.04 LTS and Installation Instructions
|
||||
|
||||
The following dependencies were necessary for a clean install of Ubuntu 18.04 LTS:
|
||||
|
||||
# Building and Installation Instructions
|
||||
|
||||
Officially supported OS is Ubuntu 20.04.
|
||||
|
||||
Following dependencies are needed for a clean install of Ubuntu 20.04:
|
||||
```
|
||||
sudo apt-get install autoconf bash build-essential ca-certificates cmake \
|
||||
doxygen git graphviz libbz2-dev libcurl4-openssl-dev libncurses-dev \
|
||||
libreadline-dev libssl-dev libtool libzmq3-dev locales ntp pkg-config \
|
||||
wget
|
||||
```
|
||||
## Build Boost 1.67.0
|
||||
|
||||
|
||||
```
|
||||
mkdir $HOME/src
|
||||
cd $HOME/src
|
||||
export BOOST_ROOT=$HOME/src/boost_1_67_0
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y autotools-dev build-essential libbz2-dev libicu-dev python-dev
|
||||
wget -c 'http://sourceforge.net/projects/boost/files/boost/1.67.0/boost_1_67_0.tar.bz2/download'\
|
||||
-O boost_1_67_0.tar.bz2
|
||||
tar xjf boost_1_67_0.tar.bz2
|
||||
cd boost_1_67_0/
|
||||
./bootstrap.sh "--prefix=$BOOST_ROOT"
|
||||
./b2 install
|
||||
sudo apt-get install \
|
||||
apt-utils autoconf bash build-essential ca-certificates clang-format cmake
|
||||
dnsutils 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
|
||||
```
|
||||
|
||||
|
||||
## Building Peerplays
|
||||
|
||||
```
|
||||
mkdir $HOME/src
|
||||
cd $HOME/src
|
||||
export BOOST_ROOT=$HOME/src/boost_1_67_0
|
||||
git clone https://github.com/peerplays-network/peerplays.git
|
||||
git clone https://gitlab.com/PBSA/peerplays.git
|
||||
cd peerplays
|
||||
git submodule update --init --recursive
|
||||
|
||||
# If you want to build Mainnet node
|
||||
cmake -DBOOST_ROOT="$BOOST_ROOT" -DCMAKE_BUILD_TYPE=Release
|
||||
cmake -DCMAKE_BUILD_TYPE=Release
|
||||
|
||||
# If you want to build Testnet node
|
||||
cmake -DBOOST_ROOT="$BOOST_ROOT" -DCMAKE_BUILD_TYPE=Release -DBUILD_PEERPLAYS_TESTNET=1
|
||||
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
|
||||
```
|
||||
|
||||
|
||||
## Docker image
|
||||
## Docker images
|
||||
|
||||
Install docker, and add current user to docker group.
|
||||
```
|
||||
# Install docker
|
||||
sudo apt install docker.io
|
||||
|
||||
|
||||
# Add current user to docker group
|
||||
sudo usermod -a -G docker $USER
|
||||
|
||||
# You need to restart your shell session, to apply group membership
|
||||
# Type 'groups' to verify that you are a member of a docker group
|
||||
```
|
||||
|
||||
### Official docker image for Peerplas Mainnet
|
||||
|
||||
```
|
||||
docker pull datasecuritynode/peerplays:latest
|
||||
```
|
||||
|
||||
### Building docker image manually
|
||||
```
|
||||
# Build docker image (from the project root, must be a docker group member)
|
||||
docker build -t peerplays .
|
||||
```
|
||||
|
||||
|
||||
# Start docker image
|
||||
### Start docker image
|
||||
```
|
||||
docker start peerplays
|
||||
|
||||
# Exposed ports
|
||||
# # rpc service:
|
||||
# EXPOSE 8090
|
||||
# # p2p service:
|
||||
# EXPOSE 1776
|
||||
```
|
||||
|
||||
Rest of the instructions on starting the chain remains same.
|
||||
|
||||
Starting A Peerplays Node
|
||||
-----------------
|
||||
|
||||
For Ubuntu 14.04 LTS and up users, see
|
||||
[this](https://github.com/cryptonomex/graphene/wiki/build-ubuntu) and
|
||||
then proceed with:
|
||||
|
||||
git clone https://github.com/peerplays-network/peerplays.git
|
||||
cd peerplays
|
||||
git submodule update --init --recursive
|
||||
cmake -DBOOST_ROOT="$BOOST_ROOT" -DCMAKE_BUILD_TYPE=Release .
|
||||
make
|
||||
./programs/witness_node/witness_node
|
||||
|
||||
Launching the witness creates required directories. Next, **stop the witness** and continue.
|
||||
|
||||
$ vi witness_node_data_dir/config.ini
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
2
docs
2
docs
|
|
@ -1 +1 @@
|
|||
Subproject commit 8df8f66389853df73ab8f6dd73981be2a6957df8
|
||||
Subproject commit 1e924950c2f92b166c34ceb294e8b8c4997a6c4e
|
||||
|
|
@ -15,7 +15,7 @@ add_library( graphene_app
|
|||
#target_link_libraries( graphene_app graphene_market_history graphene_account_history graphene_chain fc graphene_db graphene_net graphene_utilities graphene_debug_witness )
|
||||
target_link_libraries( graphene_app
|
||||
PUBLIC graphene_net graphene_utilities
|
||||
graphene_account_history graphene_accounts_list graphene_affiliate_stats graphene_bookie graphene_debug_witness graphene_elasticsearch graphene_es_objects graphene_generate_genesis graphene_market_history )
|
||||
graphene_account_history graphene_accounts_list graphene_affiliate_stats graphene_bookie graphene_debug_witness graphene_elasticsearch graphene_es_objects graphene_generate_genesis graphene_market_history peerplays_sidechain )
|
||||
|
||||
target_include_directories( graphene_app
|
||||
PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/include"
|
||||
|
|
|
|||
|
|
@ -106,6 +106,10 @@ void login_api::enable_api(const std::string &api_name) {
|
|||
// can only enable this API if the plugin was loaded
|
||||
if (_app.get_plugin("affiliate_stats"))
|
||||
_affiliate_stats_api = std::make_shared<graphene::affiliate_stats::affiliate_stats_api>(std::ref(_app));
|
||||
} else if (api_name == "sidechain_api") {
|
||||
// can only enable this API if the plugin was loaded
|
||||
if (_app.get_plugin("peerplays_sidechain"))
|
||||
_sidechain_api = std::make_shared<graphene::peerplays_sidechain::sidechain_api>(std::ref(_app));
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
|
@ -310,6 +314,11 @@ fc::api<graphene::affiliate_stats::affiliate_stats_api> login_api::affiliate_sta
|
|||
return *_affiliate_stats_api;
|
||||
}
|
||||
|
||||
fc::api<graphene::peerplays_sidechain::sidechain_api> login_api::sidechain() const {
|
||||
FC_ASSERT(_sidechain_api);
|
||||
return *_sidechain_api;
|
||||
}
|
||||
|
||||
vector<order_history_object> history_api::get_fill_order_history(std::string asset_a, std::string asset_b, uint32_t limit) const {
|
||||
FC_ASSERT(_app.chain_database());
|
||||
const auto &db = *_app.chain_database();
|
||||
|
|
|
|||
|
|
@ -401,6 +401,7 @@ public:
|
|||
wild_access.allowed_apis.push_back("crypto_api");
|
||||
wild_access.allowed_apis.push_back("bookie_api");
|
||||
wild_access.allowed_apis.push_back("affiliate_stats_api");
|
||||
wild_access.allowed_apis.push_back("sidechain_api");
|
||||
_apiaccess.permission_map["*"] = wild_access;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -52,6 +52,22 @@ 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 {
|
||||
return fc::variant(name_or_id, 1).as<T>(1);
|
||||
} 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());
|
||||
return object_id;
|
||||
}
|
||||
|
||||
class database_api_impl : public std::enable_shared_from_this<database_api_impl> {
|
||||
public:
|
||||
database_api_impl(graphene::chain::database &db);
|
||||
|
|
@ -146,18 +162,22 @@ 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;
|
||||
fc::optional<son_object> get_son_by_account(account_id_type account) const;
|
||||
fc::optional<son_object> get_son_by_account_id(account_id_type account) const;
|
||||
fc::optional<son_object> get_son_by_account(const std::string account_id_or_name) const;
|
||||
map<string, son_id_type> lookup_son_accounts(const string &lower_bound_name, uint32_t limit) const;
|
||||
uint64_t get_son_count() const;
|
||||
|
||||
|
|
@ -173,8 +193,32 @@ public:
|
|||
fc::optional<sidechain_address_object> get_sidechain_address_by_account_and_sidechain(account_id_type account, sidechain_type sidechain) const;
|
||||
uint64_t get_sidechain_addresses_count() const;
|
||||
|
||||
// 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");
|
||||
|
||||
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));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
votes_info get_votes(const string &account_name_or_id) const;
|
||||
vector<account_object> get_voters_by_id(const vote_id_type &vote_id) const;
|
||||
voters_info get_voters(const string &account_name_or_id) const;
|
||||
|
||||
// Authority / validation
|
||||
std::string get_transaction_hex(const signed_transaction &trx) const;
|
||||
|
|
@ -234,6 +278,9 @@ public:
|
|||
vector<offer_history_object> get_offer_history_by_item(const offer_history_id_type lower_id, const nft_id_type item, uint32_t limit) const;
|
||||
vector<offer_history_object> get_offer_history_by_bidder(const offer_history_id_type lower_id, const account_id_type bidder_account_id, uint32_t limit) const;
|
||||
|
||||
// Account Role
|
||||
vector<account_role_object> get_account_roles_by_owner(account_id_type owner) const;
|
||||
|
||||
uint32_t api_limit_get_lower_bound_symbol = 100;
|
||||
uint32_t api_limit_get_limit_orders = 300;
|
||||
uint32_t api_limit_get_limit_orders_by_account = 101;
|
||||
|
|
@ -242,12 +289,11 @@ 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;
|
||||
|
||||
// Account Role
|
||||
vector<account_role_object> get_account_roles_by_owner(account_id_type owner) const;
|
||||
|
||||
//private:
|
||||
const account_object *get_account_from_string(const std::string &name_or_id,
|
||||
bool throw_if_not_found = true) const;
|
||||
|
|
@ -1552,20 +1598,6 @@ vector<optional<witness_object>> database_api::get_witnesses(const vector<witnes
|
|||
return my->get_witnesses(witness_ids);
|
||||
}
|
||||
|
||||
vector<worker_object> database_api::get_workers_by_account(const std::string account_id_or_name) const {
|
||||
const auto &idx = my->_db.get_index_type<worker_index>().indices().get<by_account>();
|
||||
const account_id_type account = my->get_account_from_string(account_id_or_name)->id;
|
||||
auto itr = idx.find(account);
|
||||
vector<worker_object> result;
|
||||
|
||||
if (itr != idx.end() && itr->worker_account == account) {
|
||||
result.emplace_back(*itr);
|
||||
++itr;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
vector<optional<witness_object>> database_api_impl::get_witnesses(const vector<witness_id_type> &witness_ids) const {
|
||||
vector<optional<witness_object>> result;
|
||||
result.reserve(witness_ids.size());
|
||||
|
|
@ -1578,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 {
|
||||
|
|
@ -1649,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 {
|
||||
|
|
@ -1690,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 //
|
||||
|
|
@ -1712,11 +1768,11 @@ vector<optional<son_object>> database_api_impl::get_sons(const vector<son_id_typ
|
|||
return result;
|
||||
}
|
||||
|
||||
fc::optional<son_object> database_api::get_son_by_account(account_id_type account) const {
|
||||
return my->get_son_by_account(account);
|
||||
fc::optional<son_object> database_api::get_son_by_account_id(account_id_type account) const {
|
||||
return my->get_son_by_account_id(account);
|
||||
}
|
||||
|
||||
fc::optional<son_object> database_api_impl::get_son_by_account(account_id_type account) const {
|
||||
fc::optional<son_object> database_api_impl::get_son_by_account_id(account_id_type account) const {
|
||||
const auto &idx = _db.get_index_type<son_index>().indices().get<by_account>();
|
||||
auto itr = idx.find(account);
|
||||
if (itr != idx.end())
|
||||
|
|
@ -1724,12 +1780,24 @@ fc::optional<son_object> database_api_impl::get_son_by_account(account_id_type a
|
|||
return {};
|
||||
}
|
||||
|
||||
fc::optional<son_object> database_api::get_son_by_account(const std::string account_id_or_name) const {
|
||||
return my->get_son_by_account(account_id_or_name);
|
||||
}
|
||||
|
||||
fc::optional<son_object> database_api_impl::get_son_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_son_by_account_id(account);
|
||||
}
|
||||
|
||||
map<string, son_id_type> database_api::lookup_son_accounts(const string &lower_bound_name, uint32_t limit) const {
|
||||
return my->lookup_son_accounts(lower_bound_name, limit);
|
||||
}
|
||||
|
||||
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
|
||||
|
|
@ -1875,6 +1943,91 @@ uint64_t database_api_impl::get_sidechain_addresses_count() const {
|
|||
return _db.get_index_type<sidechain_address_index>().indices().size();
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// //
|
||||
// Workers //
|
||||
// //
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
vector<optional<worker_object>> database_api::get_workers(const vector<worker_id_type> &worker_ids) const {
|
||||
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());
|
||||
std::transform(worker_ids.begin(), worker_ids.end(), std::back_inserter(result),
|
||||
[this](worker_id_type id) -> optional<worker_object> {
|
||||
if (auto o = _db.find(id))
|
||||
return *o;
|
||||
return {};
|
||||
});
|
||||
return result;
|
||||
}
|
||||
|
||||
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>();
|
||||
auto itr = idx.find(account);
|
||||
vector<worker_object> result;
|
||||
|
||||
if (itr != idx.end() && itr->worker_account == account) {
|
||||
result.emplace_back(*itr);
|
||||
++itr;
|
||||
}
|
||||
|
||||
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 //
|
||||
|
|
@ -1885,6 +2038,22 @@ vector<variant> database_api::lookup_vote_ids(const vector<vote_id_type> &votes)
|
|||
return my->lookup_vote_ids(votes);
|
||||
}
|
||||
|
||||
vector<vote_id_type> database_api::get_votes_ids(const string &account_name_or_id) const {
|
||||
return my->get_votes_ids(account_name_or_id);
|
||||
}
|
||||
|
||||
votes_info database_api::get_votes(const string &account_name_or_id) const {
|
||||
return my->get_votes(account_name_or_id);
|
||||
}
|
||||
|
||||
vector<account_object> database_api::get_voters_by_id(const vote_id_type &vote_id) const {
|
||||
return my->get_voters_by_id(vote_id);
|
||||
}
|
||||
|
||||
voters_info database_api::get_voters(const string &account_name_or_id) const {
|
||||
return my->get_voters(account_name_or_id);
|
||||
}
|
||||
|
||||
vector<variant> database_api_impl::lookup_vote_ids(const vector<vote_id_type> &votes) const {
|
||||
FC_ASSERT(votes.size() < 1000, "Only 1000 votes can be queried at a time");
|
||||
|
||||
|
|
@ -1946,6 +2115,261 @@ vector<variant> database_api_impl::lookup_vote_ids(const vector<vote_id_type> &v
|
|||
return result;
|
||||
}
|
||||
|
||||
vector<vote_id_type> database_api_impl::get_votes_ids(const string &account_name_or_id) const {
|
||||
vector<vote_id_type> result;
|
||||
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) {
|
||||
result.emplace_back(vote);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
//! Fill votes info
|
||||
if (!committee_ids.empty()) {
|
||||
vector<votes_info_object> 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);
|
||||
votes_for_committee_members.emplace_back(votes_info_object{committee_obj.vote_id, committee_obj.id});
|
||||
}
|
||||
result.votes_for_committee_members = std::move(votes_for_committee_members);
|
||||
}
|
||||
|
||||
if (!witness_ids.empty()) {
|
||||
vector<votes_info_object> 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);
|
||||
votes_for_witnesses.emplace_back(votes_info_object{witness_obj.vote_id, witness_obj.id});
|
||||
}
|
||||
result.votes_for_witnesses = std::move(votes_for_witnesses);
|
||||
}
|
||||
|
||||
if (!for_worker_ids.empty()) {
|
||||
vector<votes_info_object> 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);
|
||||
votes_for_workers.emplace_back(votes_info_object{for_worker_obj.vote_for, for_worker_obj.id});
|
||||
}
|
||||
result.votes_for_workers = std::move(votes_for_workers);
|
||||
}
|
||||
|
||||
if (!against_worker_ids.empty()) {
|
||||
vector<votes_info_object> 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);
|
||||
votes_against_workers.emplace_back(votes_info_object{against_worker_obj.vote_against, against_worker_obj.id});
|
||||
}
|
||||
result.votes_against_workers = std::move(votes_against_workers);
|
||||
}
|
||||
|
||||
if (!son_ids.empty()) {
|
||||
vector<votes_info_object> 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);
|
||||
votes_for_sons.emplace_back(votes_info_object{son_obj.vote_id, son_obj.id});
|
||||
}
|
||||
result.votes_for_sons = std::move(votes_for_sons);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
vector<account_object> database_api_impl::get_voters_by_id(const vote_id_type &vote_id) const {
|
||||
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)
|
||||
result.emplace_back(account);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
voters_info database_api_impl::get_voters(const string &account_name_or_id) const {
|
||||
voters_info result;
|
||||
|
||||
//! Find account name
|
||||
bool owner_account_found = false;
|
||||
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) {
|
||||
//! It is account
|
||||
owner_account_id = object_id_to_string(account_object->get_id());
|
||||
owner_account_found = true;
|
||||
} else {
|
||||
//! Check if we have 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) {
|
||||
//! It is account object
|
||||
owner_account_id = object_id_to_string(account_object->get_id());
|
||||
owner_account_found = true;
|
||||
}
|
||||
}
|
||||
} 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) {
|
||||
//! 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) {
|
||||
//! It is committee member object
|
||||
owner_account_id = object_id_to_string(committee_member_object->committee_member_account);
|
||||
owner_account_found = true;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
//! Check if we have 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) {
|
||||
//! It is witness object
|
||||
owner_account_id = object_id_to_string(witness_object->witness_account);
|
||||
owner_account_found = true;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
//! Check if we have 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) {
|
||||
//! It is worker object
|
||||
owner_account_id = object_id_to_string(worker_object->worker_account);
|
||||
owner_account_found = true;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
//! Check if we have 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) {
|
||||
//! It is son object
|
||||
owner_account_id = object_id_to_string(son_object->son_account);
|
||||
owner_account_found = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//! We didn't find who it was
|
||||
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);
|
||||
|
||||
//! Info for committee member voters
|
||||
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) {
|
||||
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);
|
||||
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) {
|
||||
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()) {
|
||||
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) {
|
||||
voters_info_object voters_for_worker;
|
||||
const auto &for_worker_voters = get_voters_by_id(worker_object.vote_for);
|
||||
voters_for_worker.vote_id = worker_object.vote_for;
|
||||
voters_for_worker.voters.reserve(for_worker_voters.size());
|
||||
for (const auto &voter : for_worker_voters) {
|
||||
voters_for_worker.voters.emplace_back(voter.get_id());
|
||||
}
|
||||
voters_for_workers.emplace_back(std::move(voters_for_worker));
|
||||
|
||||
voters_info_object voters_against_worker;
|
||||
const auto &against_worker_voters = get_voters_by_id(worker_object.vote_against);
|
||||
voters_against_worker.vote_id = worker_object.vote_against;
|
||||
voters_against_worker.voters.reserve(against_worker_voters.size());
|
||||
for (const auto &voter : against_worker_voters) {
|
||||
voters_against_worker.voters.emplace_back(voter.get_id());
|
||||
}
|
||||
voters_against_workers.emplace_back(std::move(voters_against_worker));
|
||||
}
|
||||
result.voters_for_workers = std::move(voters_for_workers);
|
||||
result.voters_against_workers = std::move(voters_against_workers);
|
||||
}
|
||||
|
||||
//! Info for son voters
|
||||
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) {
|
||||
voters_for_son.voters.emplace_back(voter.get_id());
|
||||
}
|
||||
result.voters_for_son = std::move(voters_for_son);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// //
|
||||
// Authority / validation //
|
||||
|
|
|
|||
|
|
@ -28,16 +28,15 @@
|
|||
#include <graphene/chain/protocol/confidential.hpp>
|
||||
#include <graphene/chain/protocol/types.hpp>
|
||||
|
||||
#include <graphene/net/node.hpp>
|
||||
|
||||
#include <graphene/accounts_list/accounts_list_plugin.hpp>
|
||||
#include <graphene/market_history/market_history_plugin.hpp>
|
||||
|
||||
#include <graphene/elasticsearch/elasticsearch_plugin.hpp>
|
||||
|
||||
#include <graphene/affiliate_stats/affiliate_stats_api.hpp>
|
||||
#include <graphene/bookie/bookie_api.hpp>
|
||||
#include <graphene/debug_witness/debug_api.hpp>
|
||||
|
||||
#include <graphene/net/node.hpp>
|
||||
#include <graphene/elasticsearch/elasticsearch_plugin.hpp>
|
||||
#include <graphene/market_history/market_history_plugin.hpp>
|
||||
#include <graphene/peerplays_sidechain/sidechain_api.hpp>
|
||||
|
||||
#include <fc/api.hpp>
|
||||
#include <fc/crypto/elliptic.hpp>
|
||||
|
|
@ -405,6 +404,8 @@ public:
|
|||
fc::api<graphene::bookie::bookie_api> bookie() const;
|
||||
/// @brief Retrieve the affiliate_stats API (if available)
|
||||
fc::api<graphene::affiliate_stats::affiliate_stats_api> affiliate_stats() const;
|
||||
/// @brief Retrieve the sidechain_api API (if available)
|
||||
fc::api<graphene::peerplays_sidechain::sidechain_api> sidechain() const;
|
||||
|
||||
/// @brief Called to enable an API, not reflected.
|
||||
void enable_api(const string &api_name);
|
||||
|
|
@ -421,6 +422,7 @@ private:
|
|||
optional<fc::api<graphene::debug_witness::debug_api>> _debug_api;
|
||||
optional<fc::api<graphene::bookie::bookie_api>> _bookie_api;
|
||||
optional<fc::api<graphene::affiliate_stats::affiliate_stats_api>> _affiliate_stats_api;
|
||||
optional<fc::api<graphene::peerplays_sidechain::sidechain_api>> _sidechain_api;
|
||||
};
|
||||
|
||||
}} // namespace graphene::app
|
||||
|
|
@ -498,6 +500,7 @@ FC_API(graphene::app::login_api,
|
|||
(asset)
|
||||
(debug)
|
||||
(bookie)
|
||||
(affiliate_stats))
|
||||
(affiliate_stats)
|
||||
(sidechain))
|
||||
|
||||
// clang-format on
|
||||
|
|
|
|||
|
|
@ -56,6 +56,8 @@
|
|||
#include <graphene/chain/custom_permission_object.hpp>
|
||||
#include <graphene/chain/nft_object.hpp>
|
||||
#include <graphene/chain/offer_object.hpp>
|
||||
#include <graphene/chain/voters_info.hpp>
|
||||
#include <graphene/chain/votes_info.hpp>
|
||||
|
||||
#include <graphene/market_history/market_history_plugin.hpp>
|
||||
|
||||
|
|
@ -558,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;
|
||||
|
||||
/**
|
||||
|
|
@ -586,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
|
||||
|
|
@ -601,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 //
|
||||
/////////////////
|
||||
|
|
@ -619,7 +640,14 @@ public:
|
|||
* @param account 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(account_id_type account) const;
|
||||
fc::optional<son_object> get_son_by_account_id(account_id_type account) const;
|
||||
|
||||
/**
|
||||
* @brief Get the SON owned by a given account
|
||||
* @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;
|
||||
|
||||
/**
|
||||
* @brief Get names and IDs for registered SONs
|
||||
|
|
@ -698,15 +726,46 @@ public:
|
|||
*/
|
||||
uint64_t get_sidechain_addresses_count() const;
|
||||
|
||||
/// WORKERS
|
||||
/////////////
|
||||
// Workers //
|
||||
/////////////
|
||||
|
||||
/**
|
||||
* @brief Get a list of workers by ID
|
||||
* @param worker_ids IDs of the workers to retrieve
|
||||
* @return The workers corresponding to the provided IDs
|
||||
*
|
||||
* This function has semantics identical to @ref get_objects
|
||||
*/
|
||||
vector<optional<worker_object>> get_workers(const vector<worker_id_type> &worker_ids) const;
|
||||
|
||||
/**
|
||||
* @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 //
|
||||
///////////
|
||||
|
|
@ -721,6 +780,39 @@ public:
|
|||
*/
|
||||
vector<variant> lookup_vote_ids(const vector<vote_id_type> &votes) const;
|
||||
|
||||
/**
|
||||
* @brief Get a list of vote_id_type that ID votes for
|
||||
* @param account_name_or_id ID or name of the account to get votes for
|
||||
* @return The list of vote_id_type ID votes for
|
||||
*
|
||||
*/
|
||||
vector<vote_id_type> get_votes_ids(const string &account_name_or_id) const;
|
||||
|
||||
/**
|
||||
* @brief Return the objects account_name_or_id votes for
|
||||
* @param account_name_or_id ID or name of the account to get votes for
|
||||
* @return The votes_info account_name_or_id votes for
|
||||
*
|
||||
*/
|
||||
votes_info get_votes(const string &account_name_or_id) const;
|
||||
|
||||
/**
|
||||
*
|
||||
* @brief Get a list of accounts that votes for vote_id
|
||||
* @param vote_id We search accounts that vote for this ID
|
||||
* @return The accounts that votes for provided ID
|
||||
*
|
||||
*/
|
||||
vector<account_object> get_voters_by_id(const vote_id_type &vote_id) const;
|
||||
|
||||
/**
|
||||
* @brief Return the accounts that votes for account_name_or_id
|
||||
* @param account_name_or_id ID or name of the account to get voters for
|
||||
* @return The voters_info for account_name_or_id
|
||||
*
|
||||
*/
|
||||
voters_info get_voters(const string &account_name_or_id) const;
|
||||
|
||||
////////////////////////////
|
||||
// Authority / validation //
|
||||
////////////////////////////
|
||||
|
|
@ -1033,17 +1125,21 @@ 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)
|
||||
(get_son_by_account_id)
|
||||
(get_son_by_account)
|
||||
(lookup_son_accounts)
|
||||
(get_son_count)
|
||||
|
|
@ -1060,10 +1156,19 @@ FC_API(graphene::app::database_api,
|
|||
(get_sidechain_address_by_account_and_sidechain)
|
||||
(get_sidechain_addresses_count)
|
||||
|
||||
// workers
|
||||
// Workers
|
||||
(get_workers)
|
||||
(get_workers_by_account_id)
|
||||
(get_workers_by_account)
|
||||
(lookup_worker_accounts)
|
||||
(get_worker_count)
|
||||
|
||||
// Votes
|
||||
(lookup_vote_ids)
|
||||
(get_votes_ids)
|
||||
(get_votes)
|
||||
(get_voters_by_id)
|
||||
(get_voters)
|
||||
|
||||
// Authority / validation
|
||||
(get_transaction_hex)
|
||||
|
|
|
|||
|
|
@ -493,4 +493,3 @@ namespace fc {
|
|||
const_cast<int*>(event_obj.my->state_machine.current_state())[0] = (int)status;
|
||||
}
|
||||
} //end namespace fc
|
||||
|
||||
|
|
|
|||
|
|
@ -2034,16 +2034,9 @@ void database::perform_son_tasks()
|
|||
|
||||
void update_son_params(database& db)
|
||||
{
|
||||
if( db.head_block_time() >= HARDFORK_SON2_TIME )
|
||||
if( (db.head_block_time() >= HARDFORK_SON2_TIME) && (db.head_block_time() < HARDFORK_SON3_TIME) )
|
||||
{
|
||||
const auto& gpo = db.get_global_properties();
|
||||
const asset_object& btc_asset = gpo.parameters.btc_asset()(db);
|
||||
if( btc_asset.is_transfer_restricted() ) {
|
||||
db.modify( btc_asset, []( asset_object& ao ) {
|
||||
ao.options.flags = asset_issuer_permission_flags::charge_market_fee |
|
||||
asset_issuer_permission_flags::override_authority;
|
||||
});
|
||||
}
|
||||
db.modify( gpo, []( global_property_object& gpo ) {
|
||||
gpo.parameters.extensions.value.maximum_son_count = 7;
|
||||
});
|
||||
|
|
@ -2274,6 +2267,14 @@ void database::perform_chain_maintenance(const signed_block& next_block, const g
|
|||
p.pending_parameters->extensions.value.hbd_asset = p.parameters.extensions.value.hbd_asset;
|
||||
if( !p.pending_parameters->extensions.value.hive_asset.valid() )
|
||||
p.pending_parameters->extensions.value.hive_asset = p.parameters.extensions.value.hive_asset;
|
||||
|
||||
// the following parameters are not allowed to be changed. So take what is in global property
|
||||
p.pending_parameters->extensions.value.hive_asset = p.parameters.extensions.value.hive_asset;
|
||||
p.pending_parameters->extensions.value.hbd_asset = p.parameters.extensions.value.hbd_asset;
|
||||
p.pending_parameters->extensions.value.btc_asset = p.parameters.extensions.value.btc_asset;
|
||||
p.pending_parameters->extensions.value.son_account = p.parameters.extensions.value.son_account;
|
||||
p.pending_parameters->extensions.value.gpos_period_start = p.parameters.extensions.value.gpos_period_start;
|
||||
|
||||
p.parameters = std::move(*p.pending_parameters);
|
||||
p.pending_parameters.reset();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -344,7 +344,6 @@ namespace graphene { namespace chain {
|
|||
{
|
||||
FC_THROW_EXCEPTION(graphene::chain::no_transition, "No transition");
|
||||
}
|
||||
|
||||
template <class Fsm>
|
||||
void no_transition(canceled_event const& e, Fsm&, int state)
|
||||
{
|
||||
|
|
|
|||
7
libraries/chain/hardfork.d/SON3.hf
Normal file
7
libraries/chain/hardfork.d/SON3.hf
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
#ifndef HARDFORK_SON3_TIME
|
||||
#ifdef BUILD_PEERPLAYS_TESTNET
|
||||
#define HARDFORK_SON3_TIME (fc::time_point_sec::from_iso_string("2022-04-30T00:00:00"))
|
||||
#else
|
||||
#define HARDFORK_SON3_TIME (fc::time_point_sec::from_iso_string("2022-04-30T00:00:00"))
|
||||
#endif
|
||||
#endif
|
||||
|
|
@ -24,12 +24,11 @@
|
|||
#pragma once
|
||||
|
||||
#include <graphene/chain/protocol/types.hpp>
|
||||
#include <graphene/chain/protocol/betting_market.hpp>
|
||||
#include <graphene/db/object.hpp>
|
||||
#include <graphene/db/generic_index.hpp>
|
||||
#include <graphene/chain/protocol/betting_market.hpp>
|
||||
#include <sstream>
|
||||
|
||||
#include <boost/multi_index/composite_key.hpp>
|
||||
#include <sstream>
|
||||
|
||||
namespace graphene { namespace chain {
|
||||
class betting_market_object;
|
||||
|
|
@ -626,7 +625,6 @@ typedef multi_index_container<
|
|||
|
||||
typedef generic_index<betting_market_position_object, betting_market_position_multi_index_type> betting_market_position_index;
|
||||
|
||||
|
||||
template<typename Stream>
|
||||
inline Stream& operator<<( Stream& s, const betting_market_object& betting_market_obj )
|
||||
{
|
||||
|
|
@ -714,12 +712,110 @@ inline Stream& operator>>( Stream& s, betting_market_group_object& betting_marke
|
|||
|
||||
return s;
|
||||
}
|
||||
|
||||
} } // graphene::chain
|
||||
|
||||
FC_REFLECT_DERIVED( graphene::chain::betting_market_rules_object, (graphene::db::object), (name)(description) )
|
||||
FC_REFLECT_DERIVED( graphene::chain::betting_market_group_object, (graphene::db::object), (description)(event_id)(rules_id)(asset_id)(total_matched_bets_amount)(never_in_play)(delay_before_settling)(settling_time) )
|
||||
FC_REFLECT_DERIVED( graphene::chain::betting_market_object, (graphene::db::object), (group_id)(description)(payout_condition)(resolution) )
|
||||
|
||||
FC_REFLECT_DERIVED( graphene::chain::bet_object, (graphene::db::object), (bettor_id)(betting_market_id)(amount_to_bet)(backer_multiplier)(back_or_lay)(end_of_delay) )
|
||||
|
||||
FC_REFLECT_DERIVED( graphene::chain::betting_market_position_object, (graphene::db::object), (bettor_id)(betting_market_id)(pay_if_payout_condition)(pay_if_not_payout_condition)(pay_if_canceled)(pay_if_not_canceled)(fees_collected) )
|
||||
|
||||
namespace fc {
|
||||
|
||||
template<>
|
||||
template<>
|
||||
inline void if_enum<fc::false_type>::from_variant(const variant &vo, graphene::chain::betting_market_object &v, uint32_t max_depth) {
|
||||
from_variant(vo, v, max_depth);
|
||||
}
|
||||
|
||||
template<>
|
||||
template<>
|
||||
inline void if_enum<fc::false_type>::to_variant(const graphene::chain::betting_market_object &v, variant &vo, uint32_t max_depth) {
|
||||
to_variant(v, vo, max_depth);
|
||||
}
|
||||
|
||||
namespace raw { namespace detail {
|
||||
|
||||
template<>
|
||||
template<>
|
||||
inline void if_enum<fc::false_type>::pack(fc::datastream<size_t> &s, const graphene::chain::betting_market_object &v, uint32_t) {
|
||||
s << v;
|
||||
}
|
||||
|
||||
template<>
|
||||
template<>
|
||||
inline void if_enum<fc::false_type>::pack(fc::datastream<char*> &s, const graphene::chain::betting_market_object &v, uint32_t) {
|
||||
s << v;
|
||||
}
|
||||
|
||||
template<>
|
||||
template<>
|
||||
inline void if_enum<fc::false_type>::unpack(fc::datastream<const char*> &s, graphene::chain::betting_market_object &v, uint32_t) {
|
||||
s >> v;
|
||||
}
|
||||
|
||||
} } // namespace fc::raw::detail
|
||||
|
||||
template <>
|
||||
struct get_typename<graphene::chain::betting_market_object> {
|
||||
static const char *name() {
|
||||
return "graphene::chain::betting_market_object";
|
||||
}
|
||||
};
|
||||
template <>
|
||||
struct reflector<graphene::chain::betting_market_object> {
|
||||
typedef graphene::chain::betting_market_object type;
|
||||
typedef fc::true_type is_defined;
|
||||
typedef fc::false_type is_enum;
|
||||
};
|
||||
} // namespace fc
|
||||
|
||||
namespace fc {
|
||||
|
||||
template<>
|
||||
template<>
|
||||
inline void if_enum<fc::false_type>::from_variant(const variant &vo, graphene::chain::betting_market_group_object &v, uint32_t max_depth) {
|
||||
from_variant(vo, v, max_depth);
|
||||
}
|
||||
|
||||
template<>
|
||||
template<>
|
||||
inline void if_enum<fc::false_type>::to_variant(const graphene::chain::betting_market_group_object &v, variant &vo, uint32_t max_depth) {
|
||||
to_variant(v, vo, max_depth);
|
||||
}
|
||||
|
||||
namespace raw { namespace detail {
|
||||
|
||||
template<>
|
||||
template<>
|
||||
inline void if_enum<fc::false_type>::pack(fc::datastream<size_t> &s, const graphene::chain::betting_market_group_object &v, uint32_t) {
|
||||
s << v;
|
||||
}
|
||||
|
||||
template<>
|
||||
template<>
|
||||
inline void if_enum<fc::false_type>::pack(fc::datastream<char*> &s, const graphene::chain::betting_market_group_object &v, uint32_t) {
|
||||
s << v;
|
||||
}
|
||||
|
||||
template<>
|
||||
template<>
|
||||
inline void if_enum<fc::false_type>::unpack(fc::datastream<const char*> &s, graphene::chain::betting_market_group_object &v, uint32_t) {
|
||||
s >> v;
|
||||
}
|
||||
|
||||
} } // namespace fc::raw:detail
|
||||
|
||||
template <>
|
||||
struct get_typename<graphene::chain::betting_market_group_object> {
|
||||
static const char *name() {
|
||||
return "graphene::chain::betting_market_group_object";
|
||||
}
|
||||
};
|
||||
template <>
|
||||
struct reflector<graphene::chain::betting_market_group_object> {
|
||||
typedef graphene::chain::betting_market_group_object type;
|
||||
typedef fc::true_type is_defined;
|
||||
typedef fc::false_type is_enum;
|
||||
};
|
||||
} // namespace fc
|
||||
|
|
|
|||
|
|
@ -158,6 +158,53 @@ typedef generic_index<event_object, event_object_multi_index_type> event_object_
|
|||
return s;
|
||||
}
|
||||
} } // graphene::chain
|
||||
FC_REFLECT(graphene::chain::event_object, (name)(season)(start_time)(event_group_id)(at_least_one_betting_market_group_settled)(scores))
|
||||
|
||||
namespace fc {
|
||||
|
||||
template<>
|
||||
template<>
|
||||
inline void if_enum<fc::false_type>::from_variant(const variant &vo, graphene::chain::event_object &v, uint32_t max_depth) {
|
||||
from_variant(vo, v, max_depth);
|
||||
}
|
||||
|
||||
template<>
|
||||
template<>
|
||||
inline void if_enum<fc::false_type>::to_variant(const graphene::chain::event_object &v, variant &vo, uint32_t max_depth) {
|
||||
to_variant(v, vo, max_depth);
|
||||
}
|
||||
|
||||
namespace raw { namespace detail {
|
||||
|
||||
template<>
|
||||
template<>
|
||||
inline void if_enum<fc::false_type>::pack(fc::datastream<size_t> &s, const graphene::chain::event_object &v, uint32_t) {
|
||||
s << v;
|
||||
}
|
||||
|
||||
template<>
|
||||
template<>
|
||||
inline void if_enum<fc::false_type>::pack(fc::datastream<char*> &s, const graphene::chain::event_object &v, uint32_t) {
|
||||
s << v;
|
||||
}
|
||||
|
||||
template<>
|
||||
template<>
|
||||
inline void if_enum<fc::false_type>::unpack(fc::datastream<const char*> &s, graphene::chain::event_object &v, uint32_t) {
|
||||
s >> v;
|
||||
}
|
||||
|
||||
} } // namespace fc::raw::detail
|
||||
|
||||
template <>
|
||||
struct get_typename<graphene::chain::event_object> {
|
||||
static const char *name() {
|
||||
return "graphene::chain::event_object";
|
||||
}
|
||||
};
|
||||
template <>
|
||||
struct reflector<graphene::chain::event_object> {
|
||||
typedef graphene::chain::event_object type;
|
||||
typedef fc::true_type is_defined;
|
||||
typedef fc::false_type is_enum;
|
||||
};
|
||||
} // namespace fc
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@
|
|||
*/
|
||||
#pragma once
|
||||
|
||||
#include <boost/exception/diagnostic_information.hpp>
|
||||
#include <fc/exception/exception.hpp>
|
||||
#include <graphene/chain/protocol/protocol.hpp>
|
||||
|
||||
|
|
@ -75,6 +76,14 @@
|
|||
elog( "Caught plugin exception: ${e}", ("e", e.to_detail_string() ) ); \
|
||||
throw; \
|
||||
} \
|
||||
catch( const boost::exception& e ) \
|
||||
{ \
|
||||
elog( "Caught plugin boost::exception: ${e}", ("e", boost::diagnostic_information(e) ) ); \
|
||||
} \
|
||||
catch( const std::exception& e ) \
|
||||
{ \
|
||||
elog( "Caught plugin std::exception: ${e}", ("e", e.what() ) ); \
|
||||
} \
|
||||
catch( ... ) \
|
||||
{ \
|
||||
wlog( "Caught unexpected exception in plugin" ); \
|
||||
|
|
|
|||
|
|
@ -23,10 +23,8 @@
|
|||
*/
|
||||
|
||||
#pragma once
|
||||
#include <graphene/chain/match_object.hpp>
|
||||
#include <graphene/chain/rock_paper_scissors.hpp>
|
||||
#include <boost/multi_index/composite_key.hpp>
|
||||
#include <graphene/db/flat_index.hpp>
|
||||
#include <graphene/db/object.hpp>
|
||||
#include <graphene/db/generic_index.hpp>
|
||||
#include <fc/crypto/hex.hpp>
|
||||
#include <sstream>
|
||||
|
|
@ -156,7 +154,6 @@ namespace graphene { namespace chain {
|
|||
|
||||
return s;
|
||||
}
|
||||
|
||||
} }
|
||||
|
||||
FC_REFLECT_ENUM(graphene::chain::game_state,
|
||||
|
|
@ -165,7 +162,52 @@ FC_REFLECT_ENUM(graphene::chain::game_state,
|
|||
(expecting_reveal_moves)
|
||||
(game_complete))
|
||||
|
||||
//FC_REFLECT_TYPENAME(graphene::chain::game_object) // manually serialized
|
||||
FC_REFLECT(graphene::chain::game_object, (players))
|
||||
namespace fc {
|
||||
|
||||
template<>
|
||||
template<>
|
||||
inline void if_enum<fc::false_type>::from_variant(const variant &vo, graphene::chain::game_object &v, uint32_t max_depth) {
|
||||
from_variant(vo, v, max_depth);
|
||||
}
|
||||
|
||||
template<>
|
||||
template<>
|
||||
inline void if_enum<fc::false_type>::to_variant(const graphene::chain::game_object &v, variant &vo, uint32_t max_depth) {
|
||||
to_variant(v, vo, max_depth);
|
||||
}
|
||||
|
||||
namespace raw { namespace detail {
|
||||
|
||||
template<>
|
||||
template<>
|
||||
inline void if_enum<fc::false_type>::pack(fc::datastream<size_t> &s, const graphene::chain::game_object &v, uint32_t) {
|
||||
s << v;
|
||||
}
|
||||
|
||||
template<>
|
||||
template<>
|
||||
inline void if_enum<fc::false_type>::pack(fc::datastream<char*> &s, const graphene::chain::game_object &v, uint32_t) {
|
||||
s << v;
|
||||
}
|
||||
|
||||
template<>
|
||||
template<>
|
||||
inline void if_enum<fc::false_type>::unpack(fc::datastream<const char*> &s, graphene::chain::game_object &v, uint32_t) {
|
||||
s >> v;
|
||||
}
|
||||
|
||||
} } // namespace fc::raw::detail
|
||||
|
||||
template <>
|
||||
struct get_typename<graphene::chain::game_object> {
|
||||
static const char *name() {
|
||||
return "graphene::chain::game_object";
|
||||
}
|
||||
};
|
||||
template <>
|
||||
struct reflector<graphene::chain::game_object> {
|
||||
typedef graphene::chain::game_object type;
|
||||
typedef fc::true_type is_defined;
|
||||
typedef fc::false_type is_enum;
|
||||
};
|
||||
} // namespace fc
|
||||
|
|
|
|||
|
|
@ -1,8 +1,5 @@
|
|||
#pragma once
|
||||
#include <graphene/chain/protocol/tournament.hpp>
|
||||
#include <graphene/chain/rock_paper_scissors.hpp>
|
||||
#include <boost/multi_index/composite_key.hpp>
|
||||
#include <graphene/db/flat_index.hpp>
|
||||
#include <graphene/db/object.hpp>
|
||||
#include <graphene/db/generic_index.hpp>
|
||||
#include <fc/crypto/hex.hpp>
|
||||
#include <sstream>
|
||||
|
|
@ -16,6 +13,7 @@ namespace fc {
|
|||
void from_variant(const fc::variant& v, graphene::chain::match_object& match_obj, uint32_t max_depth = 1);
|
||||
} //end namespace fc
|
||||
|
||||
|
||||
namespace graphene { namespace chain {
|
||||
class database;
|
||||
using namespace graphene::db;
|
||||
|
|
@ -89,6 +87,7 @@ namespace graphene { namespace chain {
|
|||
|
||||
void pack_impl(std::ostream& stream) const;
|
||||
void unpack_impl(std::istream& stream);
|
||||
|
||||
void on_initiate_match(database& db);
|
||||
void on_game_complete(database& db, const game_object& game);
|
||||
game_id_type start_next_game(database& db, match_id_type match_id);
|
||||
|
|
@ -154,7 +153,6 @@ namespace graphene { namespace chain {
|
|||
|
||||
return s;
|
||||
}
|
||||
|
||||
} }
|
||||
|
||||
FC_REFLECT_ENUM(graphene::chain::match_state,
|
||||
|
|
@ -162,6 +160,52 @@ FC_REFLECT_ENUM(graphene::chain::match_state,
|
|||
(match_in_progress)
|
||||
(match_complete))
|
||||
|
||||
//FC_REFLECT_TYPENAME(graphene::chain::match_object) // manually serialized
|
||||
FC_REFLECT(graphene::chain::match_object, (players))
|
||||
namespace fc {
|
||||
|
||||
template<>
|
||||
template<>
|
||||
inline void if_enum<fc::false_type>::from_variant(const variant &vo, graphene::chain::match_object &v, uint32_t max_depth) {
|
||||
from_variant(vo, v, max_depth);
|
||||
}
|
||||
|
||||
template<>
|
||||
template<>
|
||||
inline void if_enum<fc::false_type>::to_variant(const graphene::chain::match_object &v, variant &vo, uint32_t max_depth) {
|
||||
to_variant(v, vo, max_depth);
|
||||
}
|
||||
|
||||
namespace raw { namespace detail {
|
||||
|
||||
template<>
|
||||
template<>
|
||||
inline void if_enum<fc::false_type>::pack(fc::datastream<size_t> &s, const graphene::chain::match_object &v, uint32_t) {
|
||||
s << v;
|
||||
}
|
||||
|
||||
template<>
|
||||
template<>
|
||||
inline void if_enum<fc::false_type>::pack(fc::datastream<char*> &s, const graphene::chain::match_object &v, uint32_t) {
|
||||
s << v;
|
||||
}
|
||||
|
||||
template<>
|
||||
template<>
|
||||
inline void if_enum<fc::false_type>::unpack(fc::datastream<const char*> &s, graphene::chain::match_object &v, uint32_t) {
|
||||
s >> v;
|
||||
}
|
||||
|
||||
} } // namespace fc::raw::detail
|
||||
|
||||
template <>
|
||||
struct get_typename<graphene::chain::match_object> {
|
||||
static const char *name() {
|
||||
return "graphene::chain::match_object";
|
||||
}
|
||||
};
|
||||
template <>
|
||||
struct reflector<graphene::chain::match_object> {
|
||||
typedef graphene::chain::match_object type;
|
||||
typedef fc::true_type is_defined;
|
||||
typedef fc::false_type is_enum;
|
||||
};
|
||||
} // namespace fc
|
||||
|
|
|
|||
|
|
@ -577,6 +577,8 @@ FC_REFLECT_TYPENAME( graphene::chain::fba_accumulator_id_type )
|
|||
FC_REFLECT_TYPENAME( graphene::chain::betting_market_position_id_type )
|
||||
FC_REFLECT_TYPENAME( graphene::chain::global_betting_statistics_id_type )
|
||||
FC_REFLECT_TYPENAME( graphene::chain::tournament_details_id_type )
|
||||
FC_REFLECT_TYPENAME( graphene::chain::game_id_type )
|
||||
FC_REFLECT_TYPENAME( graphene::chain::match_id_type )
|
||||
FC_REFLECT_TYPENAME( graphene::chain::custom_permission_id_type )
|
||||
FC_REFLECT_TYPENAME( graphene::chain::custom_account_authority_id_type )
|
||||
FC_REFLECT_TYPENAME( graphene::chain::offer_history_id_type )
|
||||
|
|
|
|||
|
|
@ -1,8 +1,7 @@
|
|||
#pragma once
|
||||
#include <graphene/chain/protocol/tournament.hpp>
|
||||
#include <graphene/chain/rock_paper_scissors.hpp>
|
||||
#include <boost/multi_index/composite_key.hpp>
|
||||
#include <graphene/db/flat_index.hpp>
|
||||
#include <graphene/db/object.hpp>
|
||||
#include <graphene/db/generic_index.hpp>
|
||||
#include <fc/crypto/hex.hpp>
|
||||
#include <sstream>
|
||||
|
|
@ -154,7 +153,6 @@ namespace graphene { namespace chain {
|
|||
> tournament_details_object_multi_index_type;
|
||||
typedef generic_index<tournament_details_object, tournament_details_object_multi_index_type> tournament_details_index;
|
||||
|
||||
|
||||
template<typename Stream>
|
||||
inline Stream& operator<<( Stream& s, const tournament_object& tournament_obj )
|
||||
{
|
||||
|
|
@ -181,6 +179,7 @@ namespace graphene { namespace chain {
|
|||
|
||||
return s;
|
||||
}
|
||||
|
||||
template<typename Stream>
|
||||
inline Stream& operator>>( Stream& s, tournament_object& tournament_obj )
|
||||
{
|
||||
|
|
@ -230,8 +229,6 @@ namespace graphene { namespace chain {
|
|||
|
||||
flat_set<account_id_type> before_account_ids;
|
||||
};
|
||||
|
||||
|
||||
} }
|
||||
|
||||
FC_REFLECT_DERIVED(graphene::chain::tournament_details_object, (graphene::db::object),
|
||||
|
|
@ -240,8 +237,7 @@ FC_REFLECT_DERIVED(graphene::chain::tournament_details_object, (graphene::db::ob
|
|||
(payers)
|
||||
(players_payers)
|
||||
(matches))
|
||||
//FC_REFLECT_TYPENAME(graphene::chain::tournament_object) // manually serialized
|
||||
FC_REFLECT(graphene::chain::tournament_object, (creator))
|
||||
|
||||
FC_REFLECT_ENUM(graphene::chain::tournament_state,
|
||||
(accepting_registrations)
|
||||
(awaiting_start)
|
||||
|
|
@ -249,3 +245,52 @@ FC_REFLECT_ENUM(graphene::chain::tournament_state,
|
|||
(registration_period_expired)
|
||||
(concluded))
|
||||
|
||||
namespace fc {
|
||||
|
||||
template<>
|
||||
template<>
|
||||
inline void if_enum<fc::false_type>::from_variant(const variant &vo, graphene::chain::tournament_object &v, uint32_t max_depth) {
|
||||
from_variant(vo, v, max_depth);
|
||||
}
|
||||
|
||||
template<>
|
||||
template<>
|
||||
inline void if_enum<fc::false_type>::to_variant(const graphene::chain::tournament_object &v, variant &vo, uint32_t max_depth) {
|
||||
to_variant(v, vo, max_depth);
|
||||
}
|
||||
|
||||
namespace raw { namespace detail {
|
||||
|
||||
template<>
|
||||
template<>
|
||||
inline void if_enum<fc::false_type>::pack(fc::datastream<size_t> &s, const graphene::chain::tournament_object &v, uint32_t) {
|
||||
s << v;
|
||||
}
|
||||
|
||||
template<>
|
||||
template<>
|
||||
inline void if_enum<fc::false_type>::pack(fc::datastream<char*> &s, const graphene::chain::tournament_object &v, uint32_t) {
|
||||
s << v;
|
||||
}
|
||||
|
||||
template<>
|
||||
template<>
|
||||
inline void if_enum<fc::false_type>::unpack(fc::datastream<const char*> &s, graphene::chain::tournament_object &v, uint32_t) {
|
||||
s >> v;
|
||||
}
|
||||
|
||||
} } // namespace fc::raw::detail
|
||||
|
||||
template <>
|
||||
struct get_typename<graphene::chain::tournament_object> {
|
||||
static const char *name() {
|
||||
return "graphene::chain::tournament_object";
|
||||
}
|
||||
};
|
||||
template <>
|
||||
struct reflector<graphene::chain::tournament_object> {
|
||||
typedef graphene::chain::tournament_object type;
|
||||
typedef fc::true_type is_defined;
|
||||
typedef fc::false_type is_enum;
|
||||
};
|
||||
} // namespace fc
|
||||
|
|
|
|||
40
libraries/chain/include/graphene/chain/voters_info.hpp
Normal file
40
libraries/chain/include/graphene/chain/voters_info.hpp
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
#pragma once
|
||||
|
||||
#include <graphene/chain/protocol/vote.hpp>
|
||||
|
||||
namespace graphene { namespace chain {
|
||||
|
||||
/**
|
||||
* @class voters_info_object
|
||||
* @ingroup object
|
||||
*/
|
||||
struct voters_info_object {
|
||||
vote_id_type vote_id;
|
||||
vector<account_id_type> voters;
|
||||
};
|
||||
|
||||
/**
|
||||
* @class voters_info
|
||||
* @brief tracks information about a voters info
|
||||
* @ingroup object
|
||||
*/
|
||||
struct voters_info {
|
||||
optional<voters_info_object> voters_for_committee_member;
|
||||
optional<voters_info_object> voters_for_witness;
|
||||
optional<vector<voters_info_object> > voters_for_workers;
|
||||
optional<vector<voters_info_object> > voters_against_workers;
|
||||
optional<voters_info_object> voters_for_son;
|
||||
};
|
||||
|
||||
} } // graphene::chain
|
||||
|
||||
FC_REFLECT( graphene::chain::voters_info_object,
|
||||
(vote_id)
|
||||
(voters) )
|
||||
|
||||
FC_REFLECT( graphene::chain::voters_info,
|
||||
(voters_for_committee_member)
|
||||
(voters_for_witness)
|
||||
(voters_for_workers)
|
||||
(voters_against_workers)
|
||||
(voters_for_son) )
|
||||
40
libraries/chain/include/graphene/chain/votes_info.hpp
Normal file
40
libraries/chain/include/graphene/chain/votes_info.hpp
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
#pragma once
|
||||
|
||||
#include <graphene/chain/protocol/vote.hpp>
|
||||
|
||||
namespace graphene { namespace chain {
|
||||
|
||||
/**
|
||||
* @class votes_info_object
|
||||
* @ingroup object
|
||||
*/
|
||||
struct votes_info_object {
|
||||
vote_id_type vote_id;
|
||||
object_id_type id;
|
||||
};
|
||||
|
||||
/**
|
||||
* @class votes_info
|
||||
* @brief tracks information about a votes info
|
||||
* @ingroup object
|
||||
*/
|
||||
struct votes_info {
|
||||
optional< vector< votes_info_object > > votes_for_committee_members;
|
||||
optional< vector< votes_info_object > > votes_for_witnesses;
|
||||
optional< vector< votes_info_object > > votes_for_workers;
|
||||
optional< vector< votes_info_object > > votes_against_workers;
|
||||
optional< vector< votes_info_object > > votes_for_sons;
|
||||
};
|
||||
|
||||
} } // graphene::chain
|
||||
|
||||
FC_REFLECT( graphene::chain::votes_info_object,
|
||||
(vote_id)
|
||||
(id) )
|
||||
|
||||
FC_REFLECT( graphene::chain::votes_info,
|
||||
(votes_for_committee_members)
|
||||
(votes_for_witnesses)
|
||||
(votes_for_workers)
|
||||
(votes_against_workers)
|
||||
(votes_for_sons) )
|
||||
|
|
@ -192,6 +192,16 @@ namespace graphene { namespace chain {
|
|||
FC_ASSERT( *extensions.value.betting_rake_fee_percentage <= TOURNAMENT_MAXIMAL_RAKE_FEE_PERCENTAGE,
|
||||
"Rake fee percentage must not be greater than ${max}", ("max", TOURNAMENT_MAXIMAL_RAKE_FEE_PERCENTAGE));
|
||||
}
|
||||
|
||||
if( extensions.value.son_heartbeat_frequency.valid() && extensions.value.son_deregister_time.valid() )
|
||||
FC_ASSERT( *extensions.value.son_heartbeat_frequency < *extensions.value.son_deregister_time );
|
||||
|
||||
if( extensions.value.son_heartbeat_frequency.valid() && extensions.value.son_down_time.valid() )
|
||||
FC_ASSERT( *extensions.value.son_heartbeat_frequency < *extensions.value.son_down_time );
|
||||
|
||||
if( extensions.value.son_heartbeat_frequency.valid() && extensions.value.son_pay_time.valid() )
|
||||
FC_ASSERT( *extensions.value.son_heartbeat_frequency < *extensions.value.son_pay_time );
|
||||
|
||||
}
|
||||
|
||||
} } // graphene::chain
|
||||
|
|
|
|||
|
|
@ -36,7 +36,7 @@ namespace graphene { namespace db {
|
|||
{
|
||||
unordered_map<object_id_type, unique_ptr<object> > old_values;
|
||||
unordered_map<object_id_type, object_id_type> old_index_next_ids;
|
||||
std::unordered_set<object_id_type> new_ids;
|
||||
std::set<object_id_type, std::greater<object_id_type> > new_ids;
|
||||
unordered_map<object_id_type, unique_ptr<object> > removed;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
Subproject commit 488883921936139e8734b99822d3a589afe80da1
|
||||
Subproject commit 6171e973c7fcfc9e0a39eaee2f05da84416a90e6
|
||||
|
|
@ -78,6 +78,8 @@ account_history_plugin_impl::~account_history_plugin_impl()
|
|||
}
|
||||
|
||||
void account_history_plugin_impl::update_account_histories( const signed_block& b )
|
||||
{
|
||||
try \
|
||||
{
|
||||
graphene::chain::database& db = database();
|
||||
vector<optional< operation_history_object > >& hist = db.get_applied_operations();
|
||||
|
|
@ -198,6 +200,19 @@ void account_history_plugin_impl::update_account_histories( const signed_block&
|
|||
skip_oho_id();
|
||||
}
|
||||
}
|
||||
catch( const boost::exception& e )
|
||||
{
|
||||
elog( "Caught account_history_plugin::update_account_histories(...) boost::exception: ${e}", ("e", boost::diagnostic_information(e) ) );
|
||||
}
|
||||
catch( const std::exception& e )
|
||||
{
|
||||
elog( "Caught account_history_plugin::update_account_histories(...) std::exception: ${e}", ("e", e.what() ) );
|
||||
}
|
||||
catch( ... )
|
||||
{
|
||||
wlog( "Caught unexpected exception in account_history_plugin::update_account_histories(...)" );
|
||||
}
|
||||
}
|
||||
|
||||
void account_history_plugin_impl::add_account_history( const account_id_type account_id, const operation_history_id_type op_id )
|
||||
{
|
||||
|
|
|
|||
|
|
@ -29,7 +29,6 @@
|
|||
|
||||
#include <graphene/chain/protocol/types.hpp>
|
||||
#include <graphene/chain/protocol/asset.hpp>
|
||||
#include <graphene/chain/event_object.hpp>
|
||||
#include <graphene/chain/operation_history_object.hpp>
|
||||
|
||||
#include <graphene/affiliate_stats/affiliate_stats_objects.hpp>
|
||||
|
|
|
|||
|
|
@ -157,37 +157,45 @@ fc::variants bookie_api_impl::get_objects(const vector<object_id_type>& ids) con
|
|||
{
|
||||
case event_id_type::type_id:
|
||||
{
|
||||
auto& persistent_events_by_event_id = db->get_index_type<detail::persistent_event_index>().indices().get<by_event_id>();
|
||||
auto iter = persistent_events_by_event_id.find(id.as<event_id_type>());
|
||||
if (iter != persistent_events_by_event_id.end())
|
||||
return iter->ephemeral_event_object.to_variant();
|
||||
const auto &idx = db->get_index_type<event_object_index>();
|
||||
const auto &aidx = dynamic_cast<const base_primary_index &>(idx);
|
||||
const auto &refs = aidx.get_secondary_index<detail::persistent_event_index>();
|
||||
auto iter = refs.ephemeral_event_object.find(id.as<event_id_type>());
|
||||
if (iter != refs.ephemeral_event_object.end())
|
||||
return iter->second.to_variant();
|
||||
else
|
||||
return {};
|
||||
}
|
||||
case bet_id_type::type_id:
|
||||
{
|
||||
auto& persistent_bets_by_bet_id = db->get_index_type<detail::persistent_bet_index>().indices().get<by_bet_id>();
|
||||
auto iter = persistent_bets_by_bet_id.find(id.as<bet_id_type>());
|
||||
if (iter != persistent_bets_by_bet_id.end())
|
||||
return iter->ephemeral_bet_object.to_variant();
|
||||
const auto &idx = db->get_index_type<bet_object_index>();
|
||||
const auto &aidx = dynamic_cast<const base_primary_index &>(idx);
|
||||
const auto &refs = aidx.get_secondary_index<detail::persistent_bet_index>();
|
||||
auto iter = refs.internal.find(id.as<bet_id_type>());
|
||||
if (iter != refs.internal.end())
|
||||
return iter->second.ephemeral_bet_object.to_variant();
|
||||
else
|
||||
return {};
|
||||
}
|
||||
case betting_market_object::type_id:
|
||||
{
|
||||
auto& persistent_betting_markets_by_betting_market_id = db->get_index_type<detail::persistent_betting_market_index>().indices().get<by_betting_market_id>();
|
||||
auto iter = persistent_betting_markets_by_betting_market_id.find(id.as<betting_market_id_type>());
|
||||
if (iter != persistent_betting_markets_by_betting_market_id.end())
|
||||
return iter->ephemeral_betting_market_object.to_variant();
|
||||
const auto &idx = db->get_index_type<betting_market_object_index>();
|
||||
const auto &aidx = dynamic_cast<const base_primary_index &>(idx);
|
||||
const auto &refs = aidx.get_secondary_index<detail::persistent_betting_market_index>();
|
||||
auto iter = refs.ephemeral_betting_market_object.find(id.as<betting_market_id_type>());
|
||||
if (iter != refs.ephemeral_betting_market_object.end())
|
||||
return iter->second.to_variant();
|
||||
else
|
||||
return {};
|
||||
}
|
||||
case betting_market_group_object::type_id:
|
||||
{
|
||||
auto& persistent_betting_market_groups_by_betting_market_group_id = db->get_index_type<detail::persistent_betting_market_group_index>().indices().get<by_betting_market_group_id>();
|
||||
auto iter = persistent_betting_market_groups_by_betting_market_group_id.find(id.as<betting_market_group_id_type>());
|
||||
if (iter != persistent_betting_market_groups_by_betting_market_group_id.end())
|
||||
return iter->ephemeral_betting_market_group_object.to_variant();
|
||||
const auto &idx = db->get_index_type<betting_market_group_object_index>();
|
||||
const auto &aidx = dynamic_cast<const base_primary_index &>(idx);
|
||||
const auto &refs = aidx.get_secondary_index<detail::persistent_betting_market_group_index>();
|
||||
auto iter = refs.internal.find(id.as<betting_market_group_id_type>());
|
||||
if (iter != refs.internal.end())
|
||||
return iter->second.ephemeral_betting_market_group_object.to_variant();
|
||||
else
|
||||
return {};
|
||||
}
|
||||
|
|
@ -203,25 +211,28 @@ std::vector<matched_bet_object> bookie_api_impl::get_matched_bets_for_bettor(acc
|
|||
{
|
||||
std::vector<matched_bet_object> result;
|
||||
std::shared_ptr<graphene::chain::database> db = app.chain_database();
|
||||
auto& persistent_bets_by_bettor_id = db->get_index_type<detail::persistent_bet_index>().indices().get<by_bettor_id>();
|
||||
auto iter = persistent_bets_by_bettor_id.lower_bound(std::make_tuple(bettor_id, true));
|
||||
while (iter != persistent_bets_by_bettor_id.end() &&
|
||||
iter->get_bettor_id() == bettor_id &&
|
||||
iter->is_matched())
|
||||
const auto &idx = db->get_index_type<bet_object_index>();
|
||||
const auto &aidx = dynamic_cast<const base_primary_index &>(idx);
|
||||
const auto &refs = aidx.get_secondary_index<detail::persistent_bet_index>();
|
||||
|
||||
for( const auto& bet_pair : refs.internal )
|
||||
{
|
||||
const auto& bet = bet_pair.second;
|
||||
if( bet.get_bettor_id() == bettor_id && bet.is_matched() )
|
||||
{
|
||||
matched_bet_object match;
|
||||
match.id = iter->ephemeral_bet_object.id;
|
||||
match.bettor_id = iter->ephemeral_bet_object.bettor_id;
|
||||
match.betting_market_id = iter->ephemeral_bet_object.betting_market_id;
|
||||
match.amount_to_bet = iter->ephemeral_bet_object.amount_to_bet;
|
||||
match.back_or_lay = iter->ephemeral_bet_object.back_or_lay;
|
||||
match.end_of_delay = iter->ephemeral_bet_object.end_of_delay;
|
||||
match.amount_matched = iter->amount_matched;
|
||||
match.associated_operations = iter->associated_operations;
|
||||
match.id = bet.ephemeral_bet_object.id;
|
||||
match.bettor_id = bet.ephemeral_bet_object.bettor_id;
|
||||
match.betting_market_id = bet.ephemeral_bet_object.betting_market_id;
|
||||
match.amount_to_bet = bet.ephemeral_bet_object.amount_to_bet;
|
||||
match.back_or_lay = bet.ephemeral_bet_object.back_or_lay;
|
||||
match.end_of_delay = bet.ephemeral_bet_object.end_of_delay;
|
||||
match.amount_matched = bet.amount_matched;
|
||||
match.associated_operations = bet.associated_operations;
|
||||
result.emplace_back(std::move(match));
|
||||
|
||||
++iter;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
@ -231,29 +242,32 @@ std::vector<matched_bet_object> bookie_api_impl::get_all_matched_bets_for_bettor
|
|||
|
||||
std::vector<matched_bet_object> result;
|
||||
std::shared_ptr<graphene::chain::database> db = app.chain_database();
|
||||
auto& persistent_bets_by_bettor_id = db->get_index_type<detail::persistent_bet_index>().indices().get<by_bettor_id>();
|
||||
persistent_bet_multi_index_type::index<by_bettor_id>::type::iterator iter;
|
||||
if (start == bet_id_type())
|
||||
iter = persistent_bets_by_bettor_id.lower_bound(std::make_tuple(bettor_id, true));
|
||||
else
|
||||
iter = persistent_bets_by_bettor_id.lower_bound(std::make_tuple(bettor_id, true, start));
|
||||
while (iter != persistent_bets_by_bettor_id.end() &&
|
||||
iter->get_bettor_id() == bettor_id &&
|
||||
iter->is_matched() &&
|
||||
const auto &idx = db->get_index_type<bet_object_index>();
|
||||
const auto &aidx = dynamic_cast<const base_primary_index &>(idx);
|
||||
const auto &refs = aidx.get_secondary_index<detail::persistent_bet_index>();
|
||||
|
||||
for( const auto& bet_pair : refs.internal )
|
||||
{
|
||||
const auto& bet_id = bet_pair.first;
|
||||
const auto& bet = bet_pair.second;
|
||||
if( bet.get_bettor_id() == bettor_id &&
|
||||
bet.is_matched() &&
|
||||
bet_id > start &&
|
||||
result.size() < limit )
|
||||
{
|
||||
matched_bet_object match;
|
||||
match.id = iter->ephemeral_bet_object.id;
|
||||
match.bettor_id = iter->ephemeral_bet_object.bettor_id;
|
||||
match.betting_market_id = iter->ephemeral_bet_object.betting_market_id;
|
||||
match.amount_to_bet = iter->ephemeral_bet_object.amount_to_bet;
|
||||
match.back_or_lay = iter->ephemeral_bet_object.back_or_lay;
|
||||
match.end_of_delay = iter->ephemeral_bet_object.end_of_delay;
|
||||
match.amount_matched = iter->amount_matched;
|
||||
match.id = bet.ephemeral_bet_object.id;
|
||||
match.bettor_id = bet.ephemeral_bet_object.bettor_id;
|
||||
match.betting_market_id = bet.ephemeral_bet_object.betting_market_id;
|
||||
match.amount_to_bet = bet.ephemeral_bet_object.amount_to_bet;
|
||||
match.back_or_lay = bet.ephemeral_bet_object.back_or_lay;
|
||||
match.end_of_delay = bet.ephemeral_bet_object.end_of_delay;
|
||||
match.amount_matched = bet.amount_matched;
|
||||
match.associated_operations = bet.associated_operations;
|
||||
result.emplace_back(std::move(match));
|
||||
|
||||
++iter;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -59,143 +59,80 @@ namespace detail
|
|||
* We do this by creating a secondary index on bet_object. We don't actually use it
|
||||
* to index any property of the bet, we just use it to register for callbacks.
|
||||
*/
|
||||
class persistent_bet_object_helper : public secondary_index
|
||||
{
|
||||
public:
|
||||
virtual ~persistent_bet_object_helper() {}
|
||||
|
||||
virtual void object_inserted(const object& obj) override;
|
||||
//virtual void object_removed( const object& obj ) override;
|
||||
//virtual void about_to_modify( const object& before ) override;
|
||||
virtual void object_modified(const object& after) override;
|
||||
void set_plugin_instance(bookie_plugin* instance) { _bookie_plugin = instance; }
|
||||
private:
|
||||
bookie_plugin* _bookie_plugin;
|
||||
};
|
||||
|
||||
void persistent_bet_object_helper::object_inserted(const object& obj)
|
||||
void persistent_bet_index::object_inserted(const object& obj)
|
||||
{
|
||||
const bet_object& bet_obj = *boost::polymorphic_downcast<const bet_object*>(&obj);
|
||||
_bookie_plugin->database().create<persistent_bet_object>([&](persistent_bet_object& saved_bet_obj) {
|
||||
saved_bet_obj.ephemeral_bet_object = bet_obj;
|
||||
});
|
||||
if(0 == internal.count(bet_obj.id))
|
||||
internal.insert( {bet_obj.id, bet_obj} );
|
||||
else
|
||||
internal[bet_obj.id] = bet_obj;
|
||||
}
|
||||
void persistent_bet_object_helper::object_modified(const object& after)
|
||||
void persistent_bet_index::object_modified(const object& after)
|
||||
{
|
||||
database& db = _bookie_plugin->database();
|
||||
auto& persistent_bets_by_bet_id = db.get_index_type<persistent_bet_index>().indices().get<by_bet_id>();
|
||||
const bet_object& bet_obj = *boost::polymorphic_downcast<const bet_object*>(&after);
|
||||
auto iter = persistent_bets_by_bet_id.find(bet_obj.id);
|
||||
assert (iter != persistent_bets_by_bet_id.end());
|
||||
if (iter != persistent_bets_by_bet_id.end())
|
||||
db.modify(*iter, [&](persistent_bet_object& saved_bet_obj) {
|
||||
saved_bet_obj.ephemeral_bet_object = bet_obj;
|
||||
});
|
||||
auto iter = internal.find(bet_obj.id);
|
||||
assert (iter != internal.end());
|
||||
if (iter != internal.end())
|
||||
iter->second = bet_obj;
|
||||
}
|
||||
|
||||
//////////// end bet_object ///////////////////
|
||||
class persistent_betting_market_object_helper : public secondary_index
|
||||
{
|
||||
public:
|
||||
virtual ~persistent_betting_market_object_helper() {}
|
||||
|
||||
virtual void object_inserted(const object& obj) override;
|
||||
//virtual void object_removed( const object& obj ) override;
|
||||
//virtual void about_to_modify( const object& before ) override;
|
||||
virtual void object_modified(const object& after) override;
|
||||
void set_plugin_instance(bookie_plugin* instance) { _bookie_plugin = instance; }
|
||||
private:
|
||||
bookie_plugin* _bookie_plugin;
|
||||
};
|
||||
|
||||
void persistent_betting_market_object_helper::object_inserted(const object& obj)
|
||||
void persistent_betting_market_index::object_inserted(const object& obj)
|
||||
{
|
||||
const betting_market_object& betting_market_obj = *boost::polymorphic_downcast<const betting_market_object*>(&obj);
|
||||
_bookie_plugin->database().create<persistent_betting_market_object>([&](persistent_betting_market_object& saved_betting_market_obj) {
|
||||
saved_betting_market_obj.ephemeral_betting_market_object = betting_market_obj;
|
||||
});
|
||||
if(0 == ephemeral_betting_market_object.count(betting_market_obj.id))
|
||||
ephemeral_betting_market_object.insert( {betting_market_obj.id, betting_market_obj} );
|
||||
else
|
||||
ephemeral_betting_market_object[betting_market_obj.id] = betting_market_obj;
|
||||
|
||||
}
|
||||
void persistent_betting_market_object_helper::object_modified(const object& after)
|
||||
void persistent_betting_market_index::object_modified(const object& after)
|
||||
{
|
||||
database& db = _bookie_plugin->database();
|
||||
auto& persistent_betting_markets_by_betting_market_id = db.get_index_type<persistent_betting_market_index>().indices().get<by_betting_market_id>();
|
||||
const betting_market_object& betting_market_obj = *boost::polymorphic_downcast<const betting_market_object*>(&after);
|
||||
auto iter = persistent_betting_markets_by_betting_market_id.find(betting_market_obj.id);
|
||||
assert (iter != persistent_betting_markets_by_betting_market_id.end());
|
||||
if (iter != persistent_betting_markets_by_betting_market_id.end())
|
||||
db.modify(*iter, [&](persistent_betting_market_object& saved_betting_market_obj) {
|
||||
saved_betting_market_obj.ephemeral_betting_market_object = betting_market_obj;
|
||||
});
|
||||
auto iter = ephemeral_betting_market_object.find(betting_market_obj.id);
|
||||
assert (iter != ephemeral_betting_market_object.end());
|
||||
if (iter != ephemeral_betting_market_object.end())
|
||||
iter->second = betting_market_obj;
|
||||
}
|
||||
|
||||
//////////// end betting_market_object ///////////////////
|
||||
class persistent_betting_market_group_object_helper : public secondary_index
|
||||
{
|
||||
public:
|
||||
virtual ~persistent_betting_market_group_object_helper() {}
|
||||
|
||||
virtual void object_inserted(const object& obj) override;
|
||||
//virtual void object_removed( const object& obj ) override;
|
||||
//virtual void about_to_modify( const object& before ) override;
|
||||
virtual void object_modified(const object& after) override;
|
||||
void set_plugin_instance(bookie_plugin* instance) { _bookie_plugin = instance; }
|
||||
private:
|
||||
bookie_plugin* _bookie_plugin;
|
||||
};
|
||||
|
||||
void persistent_betting_market_group_object_helper::object_inserted(const object& obj)
|
||||
void persistent_betting_market_group_index::object_inserted(const object& obj)
|
||||
{
|
||||
const betting_market_group_object& betting_market_group_obj = *boost::polymorphic_downcast<const betting_market_group_object*>(&obj);
|
||||
_bookie_plugin->database().create<persistent_betting_market_group_object>([&](persistent_betting_market_group_object& saved_betting_market_group_obj) {
|
||||
saved_betting_market_group_obj.ephemeral_betting_market_group_object = betting_market_group_obj;
|
||||
});
|
||||
if(0 == internal.count(betting_market_group_obj.id))
|
||||
internal.insert( {betting_market_group_obj.id, betting_market_group_obj} );
|
||||
else
|
||||
internal[betting_market_group_obj.id] = betting_market_group_obj;
|
||||
}
|
||||
void persistent_betting_market_group_object_helper::object_modified(const object& after)
|
||||
void persistent_betting_market_group_index::object_modified(const object& after)
|
||||
{
|
||||
database& db = _bookie_plugin->database();
|
||||
auto& persistent_betting_market_groups_by_betting_market_group_id = db.get_index_type<persistent_betting_market_group_index>().indices().get<by_betting_market_group_id>();
|
||||
const betting_market_group_object& betting_market_group_obj = *boost::polymorphic_downcast<const betting_market_group_object*>(&after);
|
||||
auto iter = persistent_betting_market_groups_by_betting_market_group_id.find(betting_market_group_obj.id);
|
||||
assert (iter != persistent_betting_market_groups_by_betting_market_group_id.end());
|
||||
if (iter != persistent_betting_market_groups_by_betting_market_group_id.end())
|
||||
db.modify(*iter, [&](persistent_betting_market_group_object& saved_betting_market_group_obj) {
|
||||
saved_betting_market_group_obj.ephemeral_betting_market_group_object = betting_market_group_obj;
|
||||
});
|
||||
auto iter = internal.find(betting_market_group_obj.id);
|
||||
assert (iter != internal.end());
|
||||
if (iter != internal.end())
|
||||
iter->second = betting_market_group_obj;
|
||||
}
|
||||
|
||||
//////////// end betting_market_group_object ///////////////////
|
||||
class persistent_event_object_helper : public secondary_index
|
||||
{
|
||||
public:
|
||||
virtual ~persistent_event_object_helper() {}
|
||||
|
||||
virtual void object_inserted(const object& obj) override;
|
||||
//virtual void object_removed( const object& obj ) override;
|
||||
//virtual void about_to_modify( const object& before ) override;
|
||||
virtual void object_modified(const object& after) override;
|
||||
void set_plugin_instance(bookie_plugin* instance) { _bookie_plugin = instance; }
|
||||
private:
|
||||
bookie_plugin* _bookie_plugin;
|
||||
};
|
||||
|
||||
void persistent_event_object_helper::object_inserted(const object& obj)
|
||||
void persistent_event_index::object_inserted(const object& obj)
|
||||
{
|
||||
const event_object& event_obj = *boost::polymorphic_downcast<const event_object*>(&obj);
|
||||
_bookie_plugin->database().create<persistent_event_object>([&](persistent_event_object& saved_event_obj) {
|
||||
saved_event_obj.ephemeral_event_object = event_obj;
|
||||
});
|
||||
if(0 == ephemeral_event_object.count(event_obj.id))
|
||||
ephemeral_event_object.insert( {event_obj.id, event_obj} );
|
||||
else
|
||||
ephemeral_event_object[event_obj.id] = event_obj;
|
||||
}
|
||||
void persistent_event_object_helper::object_modified(const object& after)
|
||||
void persistent_event_index::object_modified(const object& after)
|
||||
{
|
||||
database& db = _bookie_plugin->database();
|
||||
auto& persistent_events_by_event_id = db.get_index_type<persistent_event_index>().indices().get<by_event_id>();
|
||||
const event_object& event_obj = *boost::polymorphic_downcast<const event_object*>(&after);
|
||||
auto iter = persistent_events_by_event_id.find(event_obj.id);
|
||||
assert (iter != persistent_events_by_event_id.end());
|
||||
if (iter != persistent_events_by_event_id.end())
|
||||
db.modify(*iter, [&](persistent_event_object& saved_event_obj) {
|
||||
saved_event_obj.ephemeral_event_object = event_obj;
|
||||
});
|
||||
auto iter = ephemeral_event_object.find(event_obj.id);
|
||||
assert (iter != ephemeral_event_object.end());
|
||||
if (iter != ephemeral_event_object.end())
|
||||
iter->second = event_obj;
|
||||
}
|
||||
|
||||
//////////// end event_object ///////////////////
|
||||
|
|
@ -207,7 +144,6 @@ class bookie_plugin_impl
|
|||
{ }
|
||||
virtual ~bookie_plugin_impl();
|
||||
|
||||
|
||||
/**
|
||||
* Called After a block has been applied and committed. The callback
|
||||
* should not yield and should execute quickly.
|
||||
|
|
@ -299,27 +235,35 @@ void bookie_plugin_impl::on_block_applied( const signed_block& )
|
|||
const asset& amount_bet = bet_matched_op.amount_bet;
|
||||
// object may no longer exist
|
||||
//const bet_object& bet = bet_matched_op.bet_id(db);
|
||||
auto& persistent_bets_by_bet_id = db.get_index_type<persistent_bet_index>().indices().get<by_bet_id>();
|
||||
auto bet_iter = persistent_bets_by_bet_id.find(bet_matched_op.bet_id);
|
||||
assert(bet_iter != persistent_bets_by_bet_id.end());
|
||||
if (bet_iter != persistent_bets_by_bet_id.end())
|
||||
const auto &idx_bet_object = db.get_index_type<bet_object_index>();
|
||||
const auto &aidx_bet_object = dynamic_cast<const base_primary_index &>(idx_bet_object);
|
||||
const auto &refs_bet_object = aidx_bet_object.get_secondary_index<detail::persistent_bet_index>();
|
||||
auto& nonconst_refs_bet_object = const_cast<persistent_bet_index&>(refs_bet_object);
|
||||
|
||||
auto bet_iter = nonconst_refs_bet_object.internal.find(bet_matched_op.bet_id);
|
||||
assert(bet_iter != nonconst_refs_bet_object.internal.end());
|
||||
if (bet_iter != nonconst_refs_bet_object.internal.end())
|
||||
{
|
||||
db.modify(*bet_iter, [&]( persistent_bet_object& obj ) {
|
||||
obj.amount_matched += amount_bet.amount;
|
||||
bet_iter->second.amount_matched += amount_bet.amount;
|
||||
if (is_operation_history_object_stored(op.id))
|
||||
obj.associated_operations.emplace_back(op.id);
|
||||
});
|
||||
const bet_object& bet_obj = bet_iter->ephemeral_bet_object;
|
||||
bet_iter->second.associated_operations.emplace_back(op.id);
|
||||
|
||||
auto& persistent_betting_market_idx = db.get_index_type<persistent_betting_market_index>().indices().get<by_betting_market_id>();
|
||||
auto persistent_betting_market_object_iter = persistent_betting_market_idx.find(bet_obj.betting_market_id);
|
||||
FC_ASSERT(persistent_betting_market_object_iter != persistent_betting_market_idx.end());
|
||||
const betting_market_object& betting_market = persistent_betting_market_object_iter->ephemeral_betting_market_object;
|
||||
const bet_object& bet_obj = bet_iter->second.ephemeral_bet_object;
|
||||
|
||||
auto& persistent_betting_market_group_idx = db.get_index_type<persistent_betting_market_group_index>().indices().get<by_betting_market_group_id>();
|
||||
auto persistent_betting_market_group_object_iter = persistent_betting_market_group_idx.find(betting_market.group_id);
|
||||
FC_ASSERT(persistent_betting_market_group_object_iter != persistent_betting_market_group_idx.end());
|
||||
const betting_market_group_object& betting_market_group = persistent_betting_market_group_object_iter->ephemeral_betting_market_group_object;
|
||||
const auto &idx_betting_market = db.get_index_type<betting_market_object_index>();
|
||||
const auto &aidx_betting_market = dynamic_cast<const base_primary_index &>(idx_betting_market);
|
||||
const auto &refs_betting_market = aidx_betting_market.get_secondary_index<detail::persistent_betting_market_index>();
|
||||
auto persistent_betting_market_object_iter = refs_betting_market.ephemeral_betting_market_object.find(bet_obj.betting_market_id);
|
||||
FC_ASSERT(persistent_betting_market_object_iter != refs_betting_market.ephemeral_betting_market_object.end());
|
||||
const betting_market_object& betting_market = persistent_betting_market_object_iter->second;
|
||||
|
||||
const auto &idx_betting_market_group = db.get_index_type<betting_market_group_object_index>();
|
||||
const auto &aidx_betting_market_group = dynamic_cast<const base_primary_index &>(idx_betting_market_group);
|
||||
const auto &refs_betting_market_group = aidx_betting_market_group.get_secondary_index<detail::persistent_betting_market_group_index>();
|
||||
auto& nonconst_refs_betting_market_group = const_cast<persistent_betting_market_group_index&>(refs_betting_market_group);
|
||||
auto persistent_betting_market_group_object_iter = nonconst_refs_betting_market_group.internal.find(betting_market.group_id);
|
||||
FC_ASSERT(persistent_betting_market_group_object_iter != nonconst_refs_betting_market_group.internal.end());
|
||||
const betting_market_group_object& betting_market_group = persistent_betting_market_group_object_iter->second.ephemeral_betting_market_group_object;
|
||||
|
||||
// if the object is still in the main database, keep the running total there
|
||||
// otherwise, add it directly to the persistent version
|
||||
|
|
@ -330,9 +274,7 @@ void bookie_plugin_impl::on_block_applied( const signed_block& )
|
|||
obj.total_matched_bets_amount += amount_bet.amount;
|
||||
});
|
||||
else
|
||||
db.modify( *persistent_betting_market_group_object_iter, [&]( persistent_betting_market_group_object& obj ){
|
||||
obj.ephemeral_betting_market_group_object.total_matched_bets_amount += amount_bet.amount;
|
||||
});
|
||||
persistent_betting_market_group_object_iter->second.total_matched_bets_amount += amount_bet.amount;
|
||||
}
|
||||
}
|
||||
else if( op.op.which() == operation::tag<event_create_operation>::value )
|
||||
|
|
@ -364,33 +306,35 @@ void bookie_plugin_impl::on_block_applied( const signed_block& )
|
|||
else if ( op.op.which() == operation::tag<bet_canceled_operation>::value )
|
||||
{
|
||||
const bet_canceled_operation& bet_canceled_op = op.op.get<bet_canceled_operation>();
|
||||
auto& persistent_bets_by_bet_id = db.get_index_type<persistent_bet_index>().indices().get<by_bet_id>();
|
||||
auto bet_iter = persistent_bets_by_bet_id.find(bet_canceled_op.bet_id);
|
||||
assert(bet_iter != persistent_bets_by_bet_id.end());
|
||||
if (bet_iter != persistent_bets_by_bet_id.end())
|
||||
const auto &idx_bet_object = db.get_index_type<bet_object_index>();
|
||||
const auto &aidx_bet_object = dynamic_cast<const base_primary_index &>(idx_bet_object);
|
||||
const auto &refs_bet_object = aidx_bet_object.get_secondary_index<detail::persistent_bet_index>();
|
||||
auto& nonconst_refs_bet_object = const_cast<persistent_bet_index&>(refs_bet_object);
|
||||
|
||||
auto bet_iter = nonconst_refs_bet_object.internal.find(bet_canceled_op.bet_id);
|
||||
assert(bet_iter != nonconst_refs_bet_object.internal.end());
|
||||
if (bet_iter != nonconst_refs_bet_object.internal.end())
|
||||
{
|
||||
// ilog("Adding bet_canceled_operation ${canceled_id} to bet ${bet_id}'s associated operations",
|
||||
// ("canceled_id", op.id)("bet_id", bet_canceled_op.bet_id));
|
||||
if (is_operation_history_object_stored(op.id))
|
||||
db.modify(*bet_iter, [&]( persistent_bet_object& obj ) {
|
||||
obj.associated_operations.emplace_back(op.id);
|
||||
});
|
||||
bet_iter->second.associated_operations.emplace_back(op.id);
|
||||
}
|
||||
}
|
||||
else if ( op.op.which() == operation::tag<bet_adjusted_operation>::value )
|
||||
{
|
||||
const bet_adjusted_operation& bet_adjusted_op = op.op.get<bet_adjusted_operation>();
|
||||
auto& persistent_bets_by_bet_id = db.get_index_type<persistent_bet_index>().indices().get<by_bet_id>();
|
||||
auto bet_iter = persistent_bets_by_bet_id.find(bet_adjusted_op.bet_id);
|
||||
assert(bet_iter != persistent_bets_by_bet_id.end());
|
||||
if (bet_iter != persistent_bets_by_bet_id.end())
|
||||
const auto &idx_bet_object = db.get_index_type<bet_object_index>();
|
||||
const auto &aidx_bet_object = dynamic_cast<const base_primary_index &>(idx_bet_object);
|
||||
const auto &refs_bet_object = aidx_bet_object.get_secondary_index<detail::persistent_bet_index>();
|
||||
auto& nonconst_refs_bet_object = const_cast<persistent_bet_index&>(refs_bet_object);
|
||||
|
||||
auto bet_iter = nonconst_refs_bet_object.internal.find(bet_adjusted_op.bet_id);
|
||||
assert(bet_iter != nonconst_refs_bet_object.internal.end());
|
||||
if (bet_iter != nonconst_refs_bet_object.internal.end())
|
||||
{
|
||||
// ilog("Adding bet_adjusted_operation ${adjusted_id} to bet ${bet_id}'s associated operations",
|
||||
// ("adjusted_id", op.id)("bet_id", bet_adjusted_op.bet_id));
|
||||
if (is_operation_history_object_stored(op.id))
|
||||
db.modify(*bet_iter, [&]( persistent_bet_object& obj ) {
|
||||
obj.associated_operations.emplace_back(op.id);
|
||||
});
|
||||
bet_iter->second.associated_operations.emplace_back(op.id);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -472,31 +416,21 @@ void bookie_plugin::plugin_initialize(const boost::program_options::variables_ma
|
|||
database().new_objects.connect([this](const vector<object_id_type>& ids, const flat_set<account_id_type>& impacted_accounts) { my->on_objects_new(ids); });
|
||||
database().removed_objects.connect([this](const vector<object_id_type>& ids, const vector<const object*>& objs, const flat_set<account_id_type>& impacted_accounts) { my->on_objects_removed(ids); });
|
||||
|
||||
|
||||
//auto event_index =
|
||||
database().add_index<primary_index<detail::persistent_event_index> >();
|
||||
database().add_index<primary_index<detail::persistent_betting_market_group_index> >();
|
||||
database().add_index<primary_index<detail::persistent_betting_market_index> >();
|
||||
database().add_index<primary_index<detail::persistent_bet_index> >();
|
||||
const primary_index<bet_object_index>& bet_object_idx = database().get_index_type<primary_index<bet_object_index> >();
|
||||
primary_index<bet_object_index>& nonconst_bet_object_idx = const_cast<primary_index<bet_object_index>&>(bet_object_idx);
|
||||
detail::persistent_bet_object_helper* persistent_bet_object_helper_index = nonconst_bet_object_idx.add_secondary_index<detail::persistent_bet_object_helper>();
|
||||
persistent_bet_object_helper_index->set_plugin_instance(this);
|
||||
nonconst_bet_object_idx.add_secondary_index<detail::persistent_bet_index>();
|
||||
|
||||
const primary_index<betting_market_object_index>& betting_market_object_idx = database().get_index_type<primary_index<betting_market_object_index> >();
|
||||
primary_index<betting_market_object_index>& nonconst_betting_market_object_idx = const_cast<primary_index<betting_market_object_index>&>(betting_market_object_idx);
|
||||
detail::persistent_betting_market_object_helper* persistent_betting_market_object_helper_index = nonconst_betting_market_object_idx.add_secondary_index<detail::persistent_betting_market_object_helper>();
|
||||
persistent_betting_market_object_helper_index->set_plugin_instance(this);
|
||||
nonconst_betting_market_object_idx.add_secondary_index<detail::persistent_betting_market_index>();
|
||||
|
||||
const primary_index<betting_market_group_object_index>& betting_market_group_object_idx = database().get_index_type<primary_index<betting_market_group_object_index> >();
|
||||
primary_index<betting_market_group_object_index>& nonconst_betting_market_group_object_idx = const_cast<primary_index<betting_market_group_object_index>&>(betting_market_group_object_idx);
|
||||
detail::persistent_betting_market_group_object_helper* persistent_betting_market_group_object_helper_index = nonconst_betting_market_group_object_idx.add_secondary_index<detail::persistent_betting_market_group_object_helper>();
|
||||
persistent_betting_market_group_object_helper_index->set_plugin_instance(this);
|
||||
nonconst_betting_market_group_object_idx.add_secondary_index<detail::persistent_betting_market_group_index>();
|
||||
|
||||
const primary_index<event_object_index>& event_object_idx = database().get_index_type<primary_index<event_object_index> >();
|
||||
primary_index<event_object_index>& nonconst_event_object_idx = const_cast<primary_index<event_object_index>&>(event_object_idx);
|
||||
detail::persistent_event_object_helper* persistent_event_object_helper_index = nonconst_event_object_idx.add_secondary_index<detail::persistent_event_object_helper>();
|
||||
persistent_event_object_helper_index->set_plugin_instance(this);
|
||||
nonconst_event_object_idx.add_secondary_index<detail::persistent_event_index>();
|
||||
|
||||
ilog("bookie plugin: plugin_startup() end");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -29,39 +29,21 @@
|
|||
namespace graphene { namespace bookie {
|
||||
using namespace chain;
|
||||
|
||||
enum bookie_object_type
|
||||
{
|
||||
persistent_event_object_type,
|
||||
persistent_betting_market_group_object_type,
|
||||
persistent_betting_market_object_type,
|
||||
persistent_bet_object_type,
|
||||
BOOKIE_OBJECT_TYPE_COUNT ///< Sentry value which contains the number of different object types
|
||||
};
|
||||
|
||||
namespace detail
|
||||
{
|
||||
|
||||
class persistent_event_object : public graphene::db::abstract_object<persistent_event_object>
|
||||
/**
|
||||
* @brief This secondary index will allow a reverse lookup of all events that happened
|
||||
*/
|
||||
class persistent_event_index : public secondary_index
|
||||
{
|
||||
public:
|
||||
static const uint8_t space_id = bookie_objects;
|
||||
static const uint8_t type_id = persistent_event_object_type;
|
||||
virtual void object_inserted( const object& obj ) override;
|
||||
virtual void object_modified( const object& after ) override;
|
||||
|
||||
event_object ephemeral_event_object;
|
||||
|
||||
event_id_type get_event_id() const { return ephemeral_event_object.id; }
|
||||
map< event_id_type, event_object > ephemeral_event_object;
|
||||
};
|
||||
|
||||
typedef object_id<bookie_objects, persistent_event_object_type, persistent_event_object> persistent_event_id_type;
|
||||
|
||||
struct by_event_id;
|
||||
typedef multi_index_container<
|
||||
persistent_event_object,
|
||||
indexed_by<
|
||||
ordered_unique<tag<by_id>, member<object, object_id_type, &object::id> >,
|
||||
ordered_unique<tag<by_event_id>, const_mem_fun<persistent_event_object, event_id_type, &persistent_event_object::get_event_id> > > > persistent_event_multi_index_type;
|
||||
typedef generic_index<persistent_event_object, persistent_event_multi_index_type> persistent_event_index;
|
||||
|
||||
#if 0 // we no longer have competitors, just leaving this here as an example of how to do a secondary index
|
||||
class events_by_competitor_index : public secondary_index
|
||||
{
|
||||
|
|
@ -101,95 +83,122 @@ void events_by_competitor_index::object_modified( const object& after )
|
|||
}
|
||||
#endif
|
||||
|
||||
//////////// betting_market_group_object //////////////////
|
||||
class persistent_betting_market_group_object : public graphene::db::abstract_object<persistent_betting_market_group_object>
|
||||
/**
|
||||
* @brief This secondary index will allow a reverse lookup of all betting_market_group that happened
|
||||
*/
|
||||
class persistent_betting_market_group_index : public secondary_index
|
||||
{
|
||||
public:
|
||||
static const uint8_t space_id = bookie_objects;
|
||||
static const uint8_t type_id = persistent_betting_market_group_object_type;
|
||||
struct internal_type
|
||||
{
|
||||
internal_type() = default;
|
||||
|
||||
internal_type(const betting_market_group_object& other)
|
||||
: ephemeral_betting_market_group_object{other}
|
||||
{}
|
||||
|
||||
internal_type& operator=(const betting_market_group_object& other)
|
||||
{
|
||||
ephemeral_betting_market_group_object = other;
|
||||
return *this;
|
||||
}
|
||||
|
||||
friend bool operator==(const internal_type& lhs, const internal_type& rhs);
|
||||
friend bool operator<(const internal_type& lhs, const internal_type& rhs);
|
||||
friend bool operator>(const internal_type& lhs, const internal_type& rhs);
|
||||
|
||||
betting_market_group_object ephemeral_betting_market_group_object;
|
||||
|
||||
share_type total_matched_bets_amount;
|
||||
|
||||
betting_market_group_id_type get_betting_market_group_id() const { return ephemeral_betting_market_group_object.id; }
|
||||
};
|
||||
|
||||
struct by_betting_market_group_id;
|
||||
typedef multi_index_container<
|
||||
persistent_betting_market_group_object,
|
||||
indexed_by<
|
||||
ordered_unique<tag<by_id>, member<object, object_id_type, &object::id> >,
|
||||
ordered_unique<tag<by_betting_market_group_id>, const_mem_fun<persistent_betting_market_group_object, betting_market_group_id_type, &persistent_betting_market_group_object::get_betting_market_group_id> > > > persistent_betting_market_group_multi_index_type;
|
||||
|
||||
typedef generic_index<persistent_betting_market_group_object, persistent_betting_market_group_multi_index_type> persistent_betting_market_group_index;
|
||||
|
||||
//////////// betting_market_object //////////////////
|
||||
class persistent_betting_market_object : public graphene::db::abstract_object<persistent_betting_market_object>
|
||||
{
|
||||
public:
|
||||
static const uint8_t space_id = bookie_objects;
|
||||
static const uint8_t type_id = persistent_betting_market_object_type;
|
||||
virtual void object_inserted( const object& obj ) override;
|
||||
virtual void object_modified( const object& after ) override;
|
||||
|
||||
betting_market_object ephemeral_betting_market_object;
|
||||
|
||||
share_type total_matched_bets_amount;
|
||||
|
||||
betting_market_id_type get_betting_market_id() const { return ephemeral_betting_market_object.id; }
|
||||
map< betting_market_group_id_type, internal_type > internal;
|
||||
};
|
||||
|
||||
struct by_betting_market_id;
|
||||
typedef multi_index_container<
|
||||
persistent_betting_market_object,
|
||||
indexed_by<
|
||||
ordered_unique<tag<by_id>, member<object, object_id_type, &object::id> >,
|
||||
ordered_unique<tag<by_betting_market_id>, const_mem_fun<persistent_betting_market_object, betting_market_id_type, &persistent_betting_market_object::get_betting_market_id> > > > persistent_betting_market_multi_index_type;
|
||||
inline bool operator==(const persistent_betting_market_group_index::internal_type& lhs, const persistent_betting_market_group_index::internal_type& rhs)
|
||||
{
|
||||
return lhs.ephemeral_betting_market_group_object == rhs.ephemeral_betting_market_group_object;
|
||||
}
|
||||
|
||||
typedef generic_index<persistent_betting_market_object, persistent_betting_market_multi_index_type> persistent_betting_market_index;
|
||||
inline bool operator<(const persistent_betting_market_group_index::internal_type& lhs, const persistent_betting_market_group_index::internal_type& rhs)
|
||||
{
|
||||
return lhs.ephemeral_betting_market_group_object < rhs.ephemeral_betting_market_group_object;
|
||||
}
|
||||
|
||||
//////////// bet_object //////////////////
|
||||
class persistent_bet_object : public graphene::db::abstract_object<persistent_bet_object>
|
||||
inline bool operator>(const persistent_betting_market_group_index::internal_type& lhs, const persistent_betting_market_group_index::internal_type& rhs)
|
||||
{
|
||||
return !operator<(lhs, rhs);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This secondary index will allow a reverse lookup of all betting_market_object that happened
|
||||
*/
|
||||
class persistent_betting_market_index : public secondary_index
|
||||
{
|
||||
public:
|
||||
static const uint8_t space_id = bookie_objects;
|
||||
static const uint8_t type_id = persistent_bet_object_type;
|
||||
virtual void object_inserted( const object& obj ) override;
|
||||
virtual void object_modified( const object& after ) override;
|
||||
|
||||
bet_object ephemeral_bet_object;
|
||||
map< betting_market_id_type, betting_market_object > ephemeral_betting_market_object;
|
||||
};
|
||||
|
||||
// total amount of the bet that matched
|
||||
share_type amount_matched;
|
||||
/**
|
||||
* @brief This secondary index will allow a reverse lookup of all bet_object that happened
|
||||
*/
|
||||
class persistent_bet_index : public secondary_index
|
||||
{
|
||||
public:
|
||||
struct internal_type
|
||||
{
|
||||
internal_type() = default;
|
||||
|
||||
std::vector<operation_history_id_type> associated_operations;
|
||||
internal_type(const bet_object& other)
|
||||
: ephemeral_bet_object{other}
|
||||
{}
|
||||
|
||||
internal_type& operator=(const bet_object& other)
|
||||
{
|
||||
ephemeral_bet_object = other;
|
||||
return *this;
|
||||
}
|
||||
|
||||
bet_id_type get_bet_id() const { return ephemeral_bet_object.id; }
|
||||
account_id_type get_bettor_id() const { return ephemeral_bet_object.bettor_id; }
|
||||
bool is_matched() const { return amount_matched != share_type(); }
|
||||
|
||||
friend bool operator==(const internal_type& lhs, const internal_type& rhs);
|
||||
friend bool operator<(const internal_type& lhs, const internal_type& rhs);
|
||||
friend bool operator>(const internal_type& lhs, const internal_type& rhs);
|
||||
|
||||
bet_object ephemeral_bet_object;
|
||||
// total amount of the bet that matched
|
||||
share_type amount_matched;
|
||||
std::vector<operation_history_id_type> associated_operations;
|
||||
};
|
||||
|
||||
struct by_bet_id;
|
||||
struct by_bettor_id;
|
||||
typedef multi_index_container<
|
||||
persistent_bet_object,
|
||||
indexed_by<
|
||||
ordered_unique<tag<by_id>, member<object, object_id_type, &object::id> >,
|
||||
ordered_unique<tag<by_bet_id>, const_mem_fun<persistent_bet_object, bet_id_type, &persistent_bet_object::get_bet_id> >,
|
||||
ordered_unique<tag<by_bettor_id>,
|
||||
composite_key<
|
||||
persistent_bet_object,
|
||||
const_mem_fun<persistent_bet_object, account_id_type, &persistent_bet_object::get_bettor_id>,
|
||||
const_mem_fun<persistent_bet_object, bool, &persistent_bet_object::is_matched>,
|
||||
const_mem_fun<persistent_bet_object, bet_id_type, &persistent_bet_object::get_bet_id> >,
|
||||
composite_key_compare<
|
||||
std::less<account_id_type>,
|
||||
std::less<bool>,
|
||||
std::greater<bet_id_type> > > > > persistent_bet_multi_index_type;
|
||||
public:
|
||||
virtual void object_inserted( const object& obj ) override;
|
||||
virtual void object_modified( const object& after ) override;
|
||||
|
||||
typedef generic_index<persistent_bet_object, persistent_bet_multi_index_type> persistent_bet_index;
|
||||
map< bet_id_type, internal_type > internal;
|
||||
};
|
||||
|
||||
inline bool operator==(const persistent_bet_index::internal_type& lhs, const persistent_bet_index::internal_type& rhs)
|
||||
{
|
||||
return lhs.ephemeral_bet_object == rhs.ephemeral_bet_object;
|
||||
}
|
||||
|
||||
inline bool operator<(const persistent_bet_index::internal_type& lhs, const persistent_bet_index::internal_type& rhs)
|
||||
{
|
||||
return lhs.ephemeral_bet_object < rhs.ephemeral_bet_object;
|
||||
}
|
||||
|
||||
inline bool operator>(const persistent_bet_index::internal_type& lhs, const persistent_bet_index::internal_type& rhs)
|
||||
{
|
||||
return !operator<(lhs, rhs);
|
||||
}
|
||||
|
||||
} } } //graphene::bookie::detail
|
||||
|
||||
FC_REFLECT_DERIVED( graphene::bookie::detail::persistent_event_object, (graphene::db::object), (ephemeral_event_object) )
|
||||
FC_REFLECT_DERIVED( graphene::bookie::detail::persistent_betting_market_group_object, (graphene::db::object), (ephemeral_betting_market_group_object)(total_matched_bets_amount) )
|
||||
FC_REFLECT_DERIVED( graphene::bookie::detail::persistent_betting_market_object, (graphene::db::object), (ephemeral_betting_market_object) )
|
||||
FC_REFLECT_DERIVED( graphene::bookie::detail::persistent_bet_object, (graphene::db::object), (ephemeral_bet_object)(amount_matched)(associated_operations) )
|
||||
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ add_library( graphene_delayed_node
|
|||
delayed_node_plugin.cpp
|
||||
)
|
||||
|
||||
target_link_libraries( graphene_delayed_node PRIVATE graphene_plugin graphene_accounts_list graphene_affiliate_stats graphene_bookie graphene_debug_witness graphene_elasticsearch graphene_market_history )
|
||||
target_link_libraries( graphene_delayed_node PRIVATE graphene_plugin graphene_accounts_list graphene_affiliate_stats graphene_bookie graphene_debug_witness graphene_elasticsearch graphene_market_history peerplays_sidechain )
|
||||
target_include_directories( graphene_delayed_node
|
||||
PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/include" )
|
||||
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@
|
|||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <boost/algorithm/string.hpp>
|
||||
#include <graphene/elasticsearch/elasticsearch_plugin.hpp>
|
||||
#include <graphene/chain/impacted.hpp>
|
||||
#include <graphene/chain/account_evaluator.hpp>
|
||||
|
|
@ -33,6 +34,15 @@ namespace graphene { namespace elasticsearch {
|
|||
namespace detail
|
||||
{
|
||||
|
||||
const std::string generateIndexName(const fc::time_point_sec& block_date, const std::string& _elasticsearch_index_prefix)
|
||||
{
|
||||
auto block_date_string = block_date.to_iso_string();
|
||||
std::vector<std::string> parts;
|
||||
boost::split(parts, block_date_string, boost::is_any_of("-"));
|
||||
std::string index_name = _elasticsearch_index_prefix + parts[0] + "-" + parts[1];
|
||||
return index_name;
|
||||
}
|
||||
|
||||
class elasticsearch_plugin_impl
|
||||
{
|
||||
public:
|
||||
|
|
@ -48,6 +58,9 @@ class elasticsearch_plugin_impl
|
|||
return _self.database();
|
||||
}
|
||||
|
||||
friend class graphene::elasticsearch::elasticsearch_plugin;
|
||||
|
||||
private:
|
||||
elasticsearch_plugin& _self;
|
||||
primary_index< operation_history_index >* _oho_index;
|
||||
|
||||
|
|
@ -75,6 +88,8 @@ class elasticsearch_plugin_impl
|
|||
std::string bulk_line;
|
||||
std::string index_name;
|
||||
bool is_sync = false;
|
||||
bool is_es_version_7_or_above = true;
|
||||
|
||||
private:
|
||||
bool add_elasticsearch( const account_id_type account_id, const optional<operation_history_object>& oho, const uint32_t block_number );
|
||||
const account_transaction_history_object& addNewEntry(const account_statistics_object& stats_obj,
|
||||
|
|
@ -91,6 +106,7 @@ class elasticsearch_plugin_impl
|
|||
void createBulkLine(const account_transaction_history_object& ath);
|
||||
void prepareBulk(const account_transaction_history_id_type& ath_id);
|
||||
void populateESstruct();
|
||||
void init_program_options(const boost::program_options::variables_map& options);
|
||||
};
|
||||
|
||||
elasticsearch_plugin_impl::~elasticsearch_plugin_impl()
|
||||
|
|
@ -105,7 +121,7 @@ elasticsearch_plugin_impl::~elasticsearch_plugin_impl()
|
|||
bool elasticsearch_plugin_impl::update_account_histories( const signed_block& b )
|
||||
{
|
||||
checkState(b.timestamp);
|
||||
index_name = graphene::utilities::generateIndexName(b.timestamp, _elasticsearch_index_prefix);
|
||||
index_name = generateIndexName(b.timestamp, _elasticsearch_index_prefix);
|
||||
|
||||
graphene::chain::database& db = database();
|
||||
const vector<optional< operation_history_object > >& hist = db.get_applied_operations();
|
||||
|
|
@ -229,6 +245,113 @@ void elasticsearch_plugin_impl::getOperationType(const optional <operation_histo
|
|||
op_type = oho->op.which();
|
||||
}
|
||||
|
||||
struct adaptor_struct
|
||||
{
|
||||
variant adapt(const variant_object& op)
|
||||
{
|
||||
fc::mutable_variant_object o(op);
|
||||
vector<string> keys_to_rename;
|
||||
for (auto& i : o)
|
||||
{
|
||||
auto& element = i.value();
|
||||
if (element.is_object())
|
||||
{
|
||||
const string& name = i.key();
|
||||
const auto& vo = element.get_object();
|
||||
if (vo.contains(name.c_str()))
|
||||
keys_to_rename.emplace_back(name);
|
||||
element = adapt(vo);
|
||||
}
|
||||
else if (element.is_array())
|
||||
adapt(element.get_array());
|
||||
}
|
||||
for (const auto& i : keys_to_rename)
|
||||
{
|
||||
string new_name = i + "_";
|
||||
o[new_name] = variant(o[i]);
|
||||
o.erase(i);
|
||||
}
|
||||
|
||||
if (o.find("memo") != o.end())
|
||||
{
|
||||
auto& memo = o["memo"];
|
||||
if (memo.is_string())
|
||||
{
|
||||
o["memo_"] = o["memo"];
|
||||
o.erase("memo");
|
||||
}
|
||||
else if (memo.is_object())
|
||||
{
|
||||
fc::mutable_variant_object tmp(memo.get_object());
|
||||
if (tmp.find("nonce") != tmp.end())
|
||||
{
|
||||
tmp["nonce"] = tmp["nonce"].as_string();
|
||||
o["memo"] = tmp;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (o.find("new_parameters") != o.end())
|
||||
{
|
||||
auto& tmp = o["new_parameters"];
|
||||
if (tmp.is_object())
|
||||
{
|
||||
fc::mutable_variant_object tmp2(tmp.get_object());
|
||||
if (tmp2.find("current_fees") != tmp2.end())
|
||||
{
|
||||
tmp2.erase("current_fees");
|
||||
o["new_parameters"] = tmp2;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (o.find("owner") != o.end() && o["owner"].is_string())
|
||||
{
|
||||
o["owner_"] = o["owner"].as_string();
|
||||
o.erase("owner");
|
||||
}
|
||||
if (o.find("proposed_ops") != o.end())
|
||||
{
|
||||
o["proposed_ops"] = fc::json::to_string(o["proposed_ops"]);
|
||||
}
|
||||
if (o.find("initializer") != o.end())
|
||||
{
|
||||
o["initializer"] = fc::json::to_string(o["initializer"]);
|
||||
}
|
||||
if (o.find("policy") != o.end())
|
||||
{
|
||||
o["policy"] = fc::json::to_string(o["policy"]);
|
||||
}
|
||||
if (o.find("predicates") != o.end())
|
||||
{
|
||||
o["predicates"] = fc::json::to_string(o["predicates"]);
|
||||
}
|
||||
if (o.find("active_special_authority") != o.end())
|
||||
{
|
||||
o["active_special_authority"] = fc::json::to_string(o["active_special_authority"]);
|
||||
}
|
||||
if (o.find("owner_special_authority") != o.end())
|
||||
{
|
||||
o["owner_special_authority"] = fc::json::to_string(o["owner_special_authority"]);
|
||||
}
|
||||
|
||||
variant v;
|
||||
fc::to_variant(o, v, FC_PACK_MAX_DEPTH);
|
||||
return v;
|
||||
}
|
||||
|
||||
void adapt(fc::variants& v)
|
||||
{
|
||||
for (auto& array_element : v)
|
||||
{
|
||||
if (array_element.is_object())
|
||||
array_element = adapt(array_element.get_object());
|
||||
else if (array_element.is_array())
|
||||
adapt(array_element.get_array());
|
||||
else
|
||||
array_element = array_element.as_string();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
void elasticsearch_plugin_impl::doOperationHistory(const optional <operation_history_object>& oho)
|
||||
{
|
||||
os.trx_in_block = oho->trx_in_block;
|
||||
|
|
@ -255,6 +378,61 @@ void elasticsearch_plugin_impl::doBlock(uint32_t trx_in_block, const signed_bloc
|
|||
bs.trx_id = trx_id;
|
||||
}
|
||||
|
||||
struct operation_visitor
|
||||
{
|
||||
using result_type = void;
|
||||
|
||||
share_type fee_amount;
|
||||
asset_id_type fee_asset;
|
||||
|
||||
asset_id_type transfer_asset_id;
|
||||
share_type transfer_amount;
|
||||
account_id_type transfer_from;
|
||||
account_id_type transfer_to;
|
||||
|
||||
void operator()( const graphene::chain::transfer_operation& o )
|
||||
{
|
||||
fee_asset = o.fee.asset_id;
|
||||
fee_amount = o.fee.amount;
|
||||
|
||||
transfer_asset_id = o.amount.asset_id;
|
||||
transfer_amount = o.amount.amount;
|
||||
transfer_from = o.from;
|
||||
transfer_to = o.to;
|
||||
}
|
||||
|
||||
object_id_type fill_order_id;
|
||||
account_id_type fill_account_id;
|
||||
asset_id_type fill_pays_asset_id;
|
||||
share_type fill_pays_amount;
|
||||
asset_id_type fill_receives_asset_id;
|
||||
share_type fill_receives_amount;
|
||||
//double fill_fill_price;
|
||||
//bool fill_is_maker;
|
||||
|
||||
void operator()( const graphene::chain::fill_order_operation& o )
|
||||
{
|
||||
fee_asset = o.fee.asset_id;
|
||||
fee_amount = o.fee.amount;
|
||||
|
||||
fill_order_id = o.order_id;
|
||||
fill_account_id = o.account_id;
|
||||
fill_pays_asset_id = o.pays.asset_id;
|
||||
fill_pays_amount = o.pays.amount;
|
||||
fill_receives_asset_id = o.receives.asset_id;
|
||||
fill_receives_amount = o.receives.amount;
|
||||
//fill_fill_price = o.fill_price.to_real();
|
||||
//fill_is_maker = o.is_maker;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void operator()( const T& o )
|
||||
{
|
||||
fee_asset = o.fee.asset_id;
|
||||
fee_amount = o.fee.amount;
|
||||
}
|
||||
};
|
||||
|
||||
void elasticsearch_plugin_impl::doVisitor(const optional <operation_history_object>& oho)
|
||||
{
|
||||
graphene::chain::database& db = database();
|
||||
|
|
@ -380,7 +558,8 @@ void elasticsearch_plugin_impl::prepareBulk(const account_transaction_history_id
|
|||
const std::string _id = fc::json::to_string(ath_id);
|
||||
fc::mutable_variant_object bulk_header;
|
||||
bulk_header["_index"] = index_name;
|
||||
bulk_header["_type"] = "data";
|
||||
if( !is_es_version_7_or_above )
|
||||
bulk_header["_type"] = "_doc";
|
||||
bulk_header["_id"] = fc::to_string(ath_id.space_id) + "." + fc::to_string(ath_id.type_id) + "."
|
||||
+ fc::to_string(ath_id.instance.value);
|
||||
prepare = graphene::utilities::createBulk(bulk_header, std::move(bulk_line));
|
||||
|
|
@ -428,6 +607,43 @@ void elasticsearch_plugin_impl::populateESstruct()
|
|||
es.query = "";
|
||||
}
|
||||
|
||||
void elasticsearch_plugin_impl::init_program_options(const boost::program_options::variables_map& options)
|
||||
{
|
||||
if (options.count("elasticsearch-node-url")) {
|
||||
_elasticsearch_node_url = options["elasticsearch-node-url"].as<std::string>();
|
||||
}
|
||||
if (options.count("elasticsearch-bulk-replay")) {
|
||||
_elasticsearch_bulk_replay = options["elasticsearch-bulk-replay"].as<uint32_t>();
|
||||
}
|
||||
if (options.count("elasticsearch-bulk-sync")) {
|
||||
_elasticsearch_bulk_sync = options["elasticsearch-bulk-sync"].as<uint32_t>();
|
||||
}
|
||||
if (options.count("elasticsearch-visitor")) {
|
||||
_elasticsearch_visitor = options["elasticsearch-visitor"].as<bool>();
|
||||
}
|
||||
if (options.count("elasticsearch-basic-auth")) {
|
||||
_elasticsearch_basic_auth = options["elasticsearch-basic-auth"].as<std::string>();
|
||||
}
|
||||
if (options.count("elasticsearch-index-prefix")) {
|
||||
_elasticsearch_index_prefix = options["elasticsearch-index-prefix"].as<std::string>();
|
||||
}
|
||||
if (options.count("elasticsearch-operation-object")) {
|
||||
_elasticsearch_operation_object = options["elasticsearch-operation-object"].as<bool>();
|
||||
}
|
||||
if (options.count("elasticsearch-start-es-after-block")) {
|
||||
_elasticsearch_start_es_after_block = options["elasticsearch-start-es-after-block"].as<uint32_t>();
|
||||
}
|
||||
if (options.count("elasticsearch-operation-string")) {
|
||||
_elasticsearch_operation_string = options["elasticsearch-operation-string"].as<bool>();
|
||||
}
|
||||
if (options.count("elasticsearch-mode")) {
|
||||
const auto option_number = options["elasticsearch-mode"].as<uint16_t>();
|
||||
if(option_number > mode::all)
|
||||
FC_THROW_EXCEPTION(graphene::chain::plugin_exception, "Elasticsearch mode not valid");
|
||||
_elasticsearch_mode = static_cast<mode>(options["elasticsearch-mode"].as<uint16_t>());
|
||||
}
|
||||
}
|
||||
|
||||
} // end namespace detail
|
||||
|
||||
elasticsearch_plugin::elasticsearch_plugin() :
|
||||
|
|
@ -480,42 +696,12 @@ void elasticsearch_plugin::plugin_set_program_options(
|
|||
|
||||
void elasticsearch_plugin::plugin_initialize(const boost::program_options::variables_map& options)
|
||||
{
|
||||
ilog("elasticsearch ACCOUNT HISTORY: plugin_initialize() begin");
|
||||
|
||||
my->_oho_index = database().add_index< primary_index< operation_history_index > >();
|
||||
database().add_index< primary_index< account_transaction_history_index > >();
|
||||
|
||||
if (options.count("elasticsearch-node-url")) {
|
||||
my->_elasticsearch_node_url = options["elasticsearch-node-url"].as<std::string>();
|
||||
}
|
||||
if (options.count("elasticsearch-bulk-replay")) {
|
||||
my->_elasticsearch_bulk_replay = options["elasticsearch-bulk-replay"].as<uint32_t>();
|
||||
}
|
||||
if (options.count("elasticsearch-bulk-sync")) {
|
||||
my->_elasticsearch_bulk_sync = options["elasticsearch-bulk-sync"].as<uint32_t>();
|
||||
}
|
||||
if (options.count("elasticsearch-visitor")) {
|
||||
my->_elasticsearch_visitor = options["elasticsearch-visitor"].as<bool>();
|
||||
}
|
||||
if (options.count("elasticsearch-basic-auth")) {
|
||||
my->_elasticsearch_basic_auth = options["elasticsearch-basic-auth"].as<std::string>();
|
||||
}
|
||||
if (options.count("elasticsearch-index-prefix")) {
|
||||
my->_elasticsearch_index_prefix = options["elasticsearch-index-prefix"].as<std::string>();
|
||||
}
|
||||
if (options.count("elasticsearch-operation-object")) {
|
||||
my->_elasticsearch_operation_object = options["elasticsearch-operation-object"].as<bool>();
|
||||
}
|
||||
if (options.count("elasticsearch-start-es-after-block")) {
|
||||
my->_elasticsearch_start_es_after_block = options["elasticsearch-start-es-after-block"].as<uint32_t>();
|
||||
}
|
||||
if (options.count("elasticsearch-operation-string")) {
|
||||
my->_elasticsearch_operation_string = options["elasticsearch-operation-string"].as<bool>();
|
||||
}
|
||||
if (options.count("elasticsearch-mode")) {
|
||||
const auto option_number = options["elasticsearch-mode"].as<uint16_t>();
|
||||
if(option_number > mode::all)
|
||||
FC_THROW_EXCEPTION(graphene::chain::plugin_exception, "Elasticsearch mode not valid");
|
||||
my->_elasticsearch_mode = static_cast<mode>(options["elasticsearch-mode"].as<uint16_t>());
|
||||
}
|
||||
my->init_program_options( options );
|
||||
|
||||
if(my->_elasticsearch_mode != mode::only_query) {
|
||||
if (my->_elasticsearch_mode == mode::all && !my->_elasticsearch_operation_string)
|
||||
|
|
@ -528,10 +714,7 @@ void elasticsearch_plugin::plugin_initialize(const boost::program_options::varia
|
|||
"Error populating ES database, we are going to keep trying.");
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
void elasticsearch_plugin::plugin_startup()
|
||||
{
|
||||
graphene::utilities::ES es;
|
||||
es.curl = my->curl;
|
||||
es.elasticsearch_url = my->_elasticsearch_node_url;
|
||||
|
|
@ -539,7 +722,17 @@ void elasticsearch_plugin::plugin_startup()
|
|||
|
||||
if(!graphene::utilities::checkES(es))
|
||||
FC_THROW_EXCEPTION(fc::exception, "ES database is not up in url ${url}", ("url", my->_elasticsearch_node_url));
|
||||
|
||||
graphene::utilities::checkESVersion7OrAbove(es, my->is_es_version_7_or_above);
|
||||
|
||||
ilog("elasticsearch ACCOUNT HISTORY: plugin_initialize() end");
|
||||
}
|
||||
|
||||
void elasticsearch_plugin::plugin_startup()
|
||||
{
|
||||
ilog("elasticsearch ACCOUNT HISTORY: plugin_startup() begin");
|
||||
// Nothing to do
|
||||
ilog("elasticsearch ACCOUNT HISTORY: plugin_startup() end");
|
||||
}
|
||||
|
||||
operation_history_object elasticsearch_plugin::get_operation_by_id(operation_history_id_type id)
|
||||
|
|
@ -655,7 +848,7 @@ graphene::utilities::ES elasticsearch_plugin::prepareHistoryQuery(string query)
|
|||
es.curl = curl;
|
||||
es.elasticsearch_url = my->_elasticsearch_node_url;
|
||||
es.index_prefix = my->_elasticsearch_index_prefix;
|
||||
es.endpoint = es.index_prefix + "*/data/_search";
|
||||
es.endpoint = es.index_prefix + "*/_doc/_search";
|
||||
es.query = query;
|
||||
|
||||
return es;
|
||||
|
|
|
|||
|
|
@ -79,62 +79,6 @@ class elasticsearch_plugin : public graphene::app::plugin
|
|||
graphene::utilities::ES prepareHistoryQuery(string query);
|
||||
};
|
||||
|
||||
|
||||
struct operation_visitor
|
||||
{
|
||||
typedef void result_type;
|
||||
|
||||
share_type fee_amount;
|
||||
asset_id_type fee_asset;
|
||||
|
||||
asset_id_type transfer_asset_id;
|
||||
share_type transfer_amount;
|
||||
account_id_type transfer_from;
|
||||
account_id_type transfer_to;
|
||||
|
||||
void operator()( const graphene::chain::transfer_operation& o )
|
||||
{
|
||||
fee_asset = o.fee.asset_id;
|
||||
fee_amount = o.fee.amount;
|
||||
|
||||
transfer_asset_id = o.amount.asset_id;
|
||||
transfer_amount = o.amount.amount;
|
||||
transfer_from = o.from;
|
||||
transfer_to = o.to;
|
||||
}
|
||||
|
||||
object_id_type fill_order_id;
|
||||
account_id_type fill_account_id;
|
||||
asset_id_type fill_pays_asset_id;
|
||||
share_type fill_pays_amount;
|
||||
asset_id_type fill_receives_asset_id;
|
||||
share_type fill_receives_amount;
|
||||
//double fill_fill_price;
|
||||
//bool fill_is_maker;
|
||||
|
||||
void operator()( const graphene::chain::fill_order_operation& o )
|
||||
{
|
||||
fee_asset = o.fee.asset_id;
|
||||
fee_amount = o.fee.amount;
|
||||
|
||||
fill_order_id = o.order_id;
|
||||
fill_account_id = o.account_id;
|
||||
fill_pays_asset_id = o.pays.asset_id;
|
||||
fill_pays_amount = o.pays.amount;
|
||||
fill_receives_asset_id = o.receives.asset_id;
|
||||
fill_receives_amount = o.receives.amount;
|
||||
//fill_fill_price = o.fill_price.to_real();
|
||||
//fill_is_maker = o.is_maker;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void operator()( const T& o )
|
||||
{
|
||||
fee_asset = o.fee.asset_id;
|
||||
fee_amount = o.fee.amount;
|
||||
}
|
||||
};
|
||||
|
||||
struct operation_history_struct {
|
||||
int trx_in_block;
|
||||
int op_in_trx;
|
||||
|
|
@ -197,113 +141,6 @@ struct bulk_struct {
|
|||
optional<visitor_struct> additional_data;
|
||||
};
|
||||
|
||||
struct adaptor_struct {
|
||||
variant adapt(const variant_object& op)
|
||||
{
|
||||
fc::mutable_variant_object o(op);
|
||||
vector<string> keys_to_rename;
|
||||
for (auto i = o.begin(); i != o.end(); ++i)
|
||||
{
|
||||
auto& element = (*i).value();
|
||||
if (element.is_object())
|
||||
{
|
||||
const string& name = (*i).key();
|
||||
auto& vo = element.get_object();
|
||||
if (vo.contains(name.c_str()))
|
||||
keys_to_rename.emplace_back(name);
|
||||
element = adapt(vo);
|
||||
}
|
||||
else if (element.is_array())
|
||||
adapt(element.get_array());
|
||||
}
|
||||
for (const auto& i : keys_to_rename)
|
||||
{
|
||||
string new_name = i + "_";
|
||||
o[new_name] = variant(o[i]);
|
||||
o.erase(i);
|
||||
}
|
||||
|
||||
if (o.find("memo") != o.end())
|
||||
{
|
||||
auto& memo = o["memo"];
|
||||
if (memo.is_string())
|
||||
{
|
||||
o["memo_"] = o["memo"];
|
||||
o.erase("memo");
|
||||
}
|
||||
else if (memo.is_object())
|
||||
{
|
||||
fc::mutable_variant_object tmp(memo.get_object());
|
||||
if (tmp.find("nonce") != tmp.end())
|
||||
{
|
||||
tmp["nonce"] = tmp["nonce"].as_string();
|
||||
o["memo"] = tmp;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (o.find("new_parameters") != o.end())
|
||||
{
|
||||
auto& tmp = o["new_parameters"];
|
||||
if (tmp.is_object())
|
||||
{
|
||||
fc::mutable_variant_object tmp2(tmp.get_object());
|
||||
if (tmp2.find("current_fees") != tmp2.end())
|
||||
{
|
||||
tmp2.erase("current_fees");
|
||||
o["new_parameters"] = tmp2;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (o.find("owner") != o.end() && o["owner"].is_string())
|
||||
{
|
||||
o["owner_"] = o["owner"].as_string();
|
||||
o.erase("owner");
|
||||
}
|
||||
if (o.find("proposed_ops") != o.end())
|
||||
{
|
||||
o["proposed_ops"] = fc::json::to_string(o["proposed_ops"]);
|
||||
}
|
||||
if (o.find("initializer") != o.end())
|
||||
{
|
||||
o["initializer"] = fc::json::to_string(o["initializer"]);
|
||||
}
|
||||
if (o.find("policy") != o.end())
|
||||
{
|
||||
o["policy"] = fc::json::to_string(o["policy"]);
|
||||
}
|
||||
if (o.find("predicates") != o.end())
|
||||
{
|
||||
o["predicates"] = fc::json::to_string(o["predicates"]);
|
||||
}
|
||||
if (o.find("active_special_authority") != o.end())
|
||||
{
|
||||
o["active_special_authority"] = fc::json::to_string(o["active_special_authority"]);
|
||||
}
|
||||
if (o.find("owner_special_authority") != o.end())
|
||||
{
|
||||
o["owner_special_authority"] = fc::json::to_string(o["owner_special_authority"]);
|
||||
}
|
||||
|
||||
|
||||
variant v;
|
||||
fc::to_variant(o, v, FC_PACK_MAX_DEPTH);
|
||||
return v;
|
||||
}
|
||||
|
||||
void adapt(fc::variants& v)
|
||||
{
|
||||
for (auto& array_element : v)
|
||||
{
|
||||
if (array_element.is_object())
|
||||
array_element = adapt(array_element.get_object());
|
||||
else if (array_element.is_array())
|
||||
adapt(array_element.get_array());
|
||||
else
|
||||
array_element = array_element.as_string();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
} } //graphene::elasticsearch
|
||||
|
||||
FC_REFLECT_ENUM( graphene::elasticsearch::mode, (only_save)(only_query)(all) )
|
||||
|
|
|
|||
|
|
@ -66,6 +66,9 @@ class es_objects_plugin_impl
|
|||
bool genesis();
|
||||
void remove_from_database(object_id_type id, std::string index);
|
||||
|
||||
friend class graphene::es_objects::es_objects_plugin;
|
||||
|
||||
private:
|
||||
es_objects_plugin& _self;
|
||||
std::string _es_objects_elasticsearch_url = "http://localhost:9200/";
|
||||
std::string _es_objects_auth = "";
|
||||
|
|
@ -97,10 +100,12 @@ class es_objects_plugin_impl
|
|||
|
||||
uint32_t block_number;
|
||||
fc::time_point_sec block_time;
|
||||
bool is_es_version_7_or_above = true;
|
||||
|
||||
private:
|
||||
template<typename T>
|
||||
void prepareTemplate(T blockchain_object, string index_name);
|
||||
void init_program_options(const boost::program_options::variables_map& options);
|
||||
};
|
||||
|
||||
bool es_objects_plugin_impl::genesis()
|
||||
|
|
@ -523,7 +528,8 @@ void es_objects_plugin_impl::remove_from_database( object_id_type id, std::strin
|
|||
fc::mutable_variant_object delete_line;
|
||||
delete_line["_id"] = string(id);
|
||||
delete_line["_index"] = _es_objects_index_prefix + index;
|
||||
delete_line["_type"] = "data";
|
||||
if( !is_es_version_7_or_above )
|
||||
delete_line["_type"] = "_doc";
|
||||
fc::mutable_variant_object final_delete_line;
|
||||
final_delete_line["delete"] = delete_line;
|
||||
prepare.push_back(fc::json::to_string(final_delete_line));
|
||||
|
|
@ -537,7 +543,8 @@ void es_objects_plugin_impl::prepareTemplate(T blockchain_object, string index_n
|
|||
{
|
||||
fc::mutable_variant_object bulk_header;
|
||||
bulk_header["_index"] = _es_objects_index_prefix + index_name;
|
||||
bulk_header["_type"] = "data";
|
||||
if( !is_es_version_7_or_above )
|
||||
bulk_header["_type"] = "_doc";
|
||||
if(_es_objects_keep_only_current)
|
||||
{
|
||||
bulk_header["_id"] = string(blockchain_object.id);
|
||||
|
|
@ -567,6 +574,72 @@ es_objects_plugin_impl::~es_objects_plugin_impl()
|
|||
}
|
||||
return;
|
||||
}
|
||||
void es_objects_plugin_impl::init_program_options(const boost::program_options::variables_map& options)
|
||||
{
|
||||
if (options.count("es-objects-elasticsearch-url")) {
|
||||
_es_objects_elasticsearch_url = options["es-objects-elasticsearch-url"].as<std::string>();
|
||||
}
|
||||
if (options.count("es-objects-auth")) {
|
||||
_es_objects_auth = options["es-objects-auth"].as<std::string>();
|
||||
}
|
||||
if (options.count("es-objects-bulk-replay")) {
|
||||
_es_objects_bulk_replay = options["es-objects-bulk-replay"].as<uint32_t>();
|
||||
}
|
||||
if (options.count("es-objects-bulk-sync")) {
|
||||
_es_objects_bulk_sync = options["es-objects-bulk-sync"].as<uint32_t>();
|
||||
}
|
||||
if (options.count("es-objects-proposals")) {
|
||||
_es_objects_proposals = options["es-objects-proposals"].as<bool>();
|
||||
}
|
||||
if (options.count("es-objects-accounts")) {
|
||||
_es_objects_accounts = options["es-objects-accounts"].as<bool>();
|
||||
}
|
||||
if (options.count("es-objects-assets")) {
|
||||
_es_objects_assets = options["es-objects-assets"].as<bool>();
|
||||
}
|
||||
if (options.count("es-objects-balances")) {
|
||||
_es_objects_balances = options["es-objects-balances"].as<bool>();
|
||||
}
|
||||
if (options.count("es-objects-limit-orders")) {
|
||||
_es_objects_limit_orders = options["es-objects-limit-orders"].as<bool>();
|
||||
}
|
||||
if (options.count("es-objects-asset-bitasset")) {
|
||||
_es_objects_asset_bitasset = options["es-objects-asset-bitasset"].as<bool>();
|
||||
}
|
||||
if (options.count("es-objects-account-role")) {
|
||||
_es_objects_balances = options["es-objects-account-role"].as<bool>();
|
||||
}
|
||||
if (options.count("es-objects-committee-member")) {
|
||||
_es_objects_balances = options["es-objects-committee-member"].as<bool>();
|
||||
}
|
||||
if (options.count("es-objects-nft")) {
|
||||
_es_objects_balances = options["es-objects-nft"].as<bool>();
|
||||
}
|
||||
if (options.count("es-objects-son")) {
|
||||
_es_objects_balances = options["es-objects-son"].as<bool>();
|
||||
}
|
||||
if (options.count("es-objects-transaction")) {
|
||||
_es_objects_balances = options["es-objects-transaction"].as<bool>();
|
||||
}
|
||||
if (options.count("es-objects-vesting-balance")) {
|
||||
_es_objects_balances = options["es-objects-vesting-balance"].as<bool>();
|
||||
}
|
||||
if (options.count("es-objects-witness")) {
|
||||
_es_objects_balances = options["es-objects-witness"].as<bool>();
|
||||
}
|
||||
if (options.count("es-objects-worker")) {
|
||||
_es_objects_balances = options["es-objects-worker"].as<bool>();
|
||||
}
|
||||
if (options.count("es-objects-index-prefix")) {
|
||||
_es_objects_index_prefix = options["es-objects-index-prefix"].as<std::string>();
|
||||
}
|
||||
if (options.count("es-objects-keep-only-current")) {
|
||||
_es_objects_keep_only_current = options["es-objects-keep-only-current"].as<bool>();
|
||||
}
|
||||
if (options.count("es-objects-start-es-after-block")) {
|
||||
_es_objects_start_es_after_block = options["es-objects-start-es-after-block"].as<uint32_t>();
|
||||
}
|
||||
}
|
||||
|
||||
} // end namespace detail
|
||||
|
||||
|
|
@ -627,69 +700,9 @@ void es_objects_plugin::plugin_set_program_options(
|
|||
|
||||
void es_objects_plugin::plugin_initialize(const boost::program_options::variables_map& options)
|
||||
{
|
||||
if (options.count("es-objects-elasticsearch-url")) {
|
||||
my->_es_objects_elasticsearch_url = options["es-objects-elasticsearch-url"].as<std::string>();
|
||||
}
|
||||
if (options.count("es-objects-auth")) {
|
||||
my->_es_objects_auth = options["es-objects-auth"].as<std::string>();
|
||||
}
|
||||
if (options.count("es-objects-bulk-replay")) {
|
||||
my->_es_objects_bulk_replay = options["es-objects-bulk-replay"].as<uint32_t>();
|
||||
}
|
||||
if (options.count("es-objects-bulk-sync")) {
|
||||
my->_es_objects_bulk_sync = options["es-objects-bulk-sync"].as<uint32_t>();
|
||||
}
|
||||
if (options.count("es-objects-proposals")) {
|
||||
my->_es_objects_proposals = options["es-objects-proposals"].as<bool>();
|
||||
}
|
||||
if (options.count("es-objects-accounts")) {
|
||||
my->_es_objects_accounts = options["es-objects-accounts"].as<bool>();
|
||||
}
|
||||
if (options.count("es-objects-assets")) {
|
||||
my->_es_objects_assets = options["es-objects-assets"].as<bool>();
|
||||
}
|
||||
if (options.count("es-objects-balances")) {
|
||||
my->_es_objects_balances = options["es-objects-balances"].as<bool>();
|
||||
}
|
||||
if (options.count("es-objects-limit-orders")) {
|
||||
my->_es_objects_limit_orders = options["es-objects-limit-orders"].as<bool>();
|
||||
}
|
||||
if (options.count("es-objects-asset-bitasset")) {
|
||||
my->_es_objects_asset_bitasset = options["es-objects-asset-bitasset"].as<bool>();
|
||||
}
|
||||
if (options.count("es-objects-account-role")) {
|
||||
my->_es_objects_balances = options["es-objects-account-role"].as<bool>();
|
||||
}
|
||||
if (options.count("es-objects-committee-member")) {
|
||||
my->_es_objects_balances = options["es-objects-committee-member"].as<bool>();
|
||||
}
|
||||
if (options.count("es-objects-nft")) {
|
||||
my->_es_objects_balances = options["es-objects-nft"].as<bool>();
|
||||
}
|
||||
if (options.count("es-objects-son")) {
|
||||
my->_es_objects_balances = options["es-objects-son"].as<bool>();
|
||||
}
|
||||
if (options.count("es-objects-transaction")) {
|
||||
my->_es_objects_balances = options["es-objects-transaction"].as<bool>();
|
||||
}
|
||||
if (options.count("es-objects-vesting-balance")) {
|
||||
my->_es_objects_balances = options["es-objects-vesting-balance"].as<bool>();
|
||||
}
|
||||
if (options.count("es-objects-witness")) {
|
||||
my->_es_objects_balances = options["es-objects-witness"].as<bool>();
|
||||
}
|
||||
if (options.count("es-objects-worker")) {
|
||||
my->_es_objects_balances = options["es-objects-worker"].as<bool>();
|
||||
}
|
||||
if (options.count("es-objects-index-prefix")) {
|
||||
my->_es_objects_index_prefix = options["es-objects-index-prefix"].as<std::string>();
|
||||
}
|
||||
if (options.count("es-objects-keep-only-current")) {
|
||||
my->_es_objects_keep_only_current = options["es-objects-keep-only-current"].as<bool>();
|
||||
}
|
||||
if (options.count("es-objects-start-es-after-block")) {
|
||||
my->_es_objects_start_es_after_block = options["es-objects-start-es-after-block"].as<uint32_t>();
|
||||
}
|
||||
ilog("elasticsearch OBJECTS: plugin_initialize() begin");
|
||||
|
||||
my->init_program_options( options );
|
||||
|
||||
database().applied_block.connect([this](const signed_block &b) {
|
||||
if(b.block_num() == 1 && my->_es_objects_start_es_after_block == 0) {
|
||||
|
|
@ -721,10 +734,7 @@ void es_objects_plugin::plugin_initialize(const boost::program_options::variable
|
|||
"Error deleting object from ES database, we are going to keep trying.");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void es_objects_plugin::plugin_startup()
|
||||
{
|
||||
graphene::utilities::ES es;
|
||||
es.curl = my->curl;
|
||||
es.elasticsearch_url = my->_es_objects_elasticsearch_url;
|
||||
|
|
@ -733,7 +743,17 @@ void es_objects_plugin::plugin_startup()
|
|||
|
||||
if(!graphene::utilities::checkES(es))
|
||||
FC_THROW_EXCEPTION(fc::exception, "ES database is not up in url ${url}", ("url", my->_es_objects_elasticsearch_url));
|
||||
|
||||
graphene::utilities::checkESVersion7OrAbove(es, my->is_es_version_7_or_above);
|
||||
|
||||
ilog("elasticsearch OBJECTS: plugin_initialize() end");
|
||||
}
|
||||
|
||||
void es_objects_plugin::plugin_startup()
|
||||
{
|
||||
ilog("elasticsearch OBJECTS: plugin_startup() begin");
|
||||
// Nothing to do
|
||||
ilog("elasticsearch OBJECTS: plugin_startup() end");
|
||||
}
|
||||
|
||||
} }
|
||||
|
|
@ -2,6 +2,7 @@ file(GLOB_RECURSE HEADERS "include/graphene/peerplays_sidechain/*.hpp")
|
|||
|
||||
add_library( peerplays_sidechain
|
||||
peerplays_sidechain_plugin.cpp
|
||||
sidechain_api.cpp
|
||||
sidechain_net_manager.cpp
|
||||
sidechain_net_handler.cpp
|
||||
sidechain_net_handler_bitcoin.cpp
|
||||
|
|
@ -23,19 +24,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)
|
||||
|
|
|
|||
|
|
@ -51,6 +51,7 @@ public:
|
|||
fc::ecc::private_key get_private_key(chain::public_key_type public_key);
|
||||
void log_son_proposal_retry(int op_type, object_id_type object_id);
|
||||
bool can_son_participate(int op_type, object_id_type object_id);
|
||||
std::map<sidechain_type, std::vector<std::string>> get_son_listener_log();
|
||||
};
|
||||
|
||||
}} // namespace graphene::peerplays_sidechain
|
||||
|
|
|
|||
|
|
@ -0,0 +1,34 @@
|
|||
#pragma once
|
||||
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include <fc/api.hpp>
|
||||
|
||||
#include <graphene/peerplays_sidechain/peerplays_sidechain_plugin.hpp>
|
||||
|
||||
namespace graphene { namespace app {
|
||||
class application;
|
||||
}} // namespace graphene::app
|
||||
|
||||
namespace graphene { namespace peerplays_sidechain {
|
||||
|
||||
namespace detail {
|
||||
class sidechain_api_impl;
|
||||
}
|
||||
|
||||
class sidechain_api {
|
||||
public:
|
||||
sidechain_api(app::application &_app);
|
||||
virtual ~sidechain_api();
|
||||
|
||||
std::shared_ptr<detail::sidechain_api_impl> my;
|
||||
|
||||
std::map<sidechain_type, std::vector<std::string>> get_son_listener_log();
|
||||
};
|
||||
|
||||
}} // namespace graphene::peerplays_sidechain
|
||||
|
||||
FC_API(graphene::peerplays_sidechain::sidechain_api,
|
||||
(get_son_listener_log))
|
||||
|
|
@ -47,6 +47,9 @@ public:
|
|||
virtual std::string send_sidechain_transaction(const sidechain_transaction_object &sto) = 0;
|
||||
virtual bool settle_sidechain_transaction(const sidechain_transaction_object &sto, asset &settle_amount) = 0;
|
||||
|
||||
void add_to_son_listener_log(std::string trx_id);
|
||||
std::vector<std::string> get_son_listener_log();
|
||||
|
||||
protected:
|
||||
peerplays_sidechain_plugin &plugin;
|
||||
graphene::chain::database &database;
|
||||
|
|
@ -56,6 +59,8 @@ protected:
|
|||
|
||||
std::map<std::string, std::string> private_keys;
|
||||
|
||||
std::vector<std::string> son_listener_log;
|
||||
|
||||
void on_applied_block(const signed_block &b);
|
||||
|
||||
private:
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
||||
|
|
@ -22,6 +22,23 @@ public:
|
|||
};
|
||||
|
||||
class bitcoin_rpc_client {
|
||||
public:
|
||||
enum class multi_type {
|
||||
script,
|
||||
address
|
||||
};
|
||||
struct multi_params {
|
||||
multi_params(multi_type _type, const std::string &_address_or_script, const std::string &_label = "") :
|
||||
type{_type},
|
||||
address_or_script{_address_or_script},
|
||||
label{_label} {
|
||||
}
|
||||
|
||||
multi_type type;
|
||||
std::string address_or_script;
|
||||
std::string label;
|
||||
};
|
||||
|
||||
public:
|
||||
bitcoin_rpc_client(std::string _ip, uint32_t _rpc, std::string _user, std::string _password, std::string _wallet, std::string _wallet_password, bool _debug_rpc_calls);
|
||||
|
||||
|
|
@ -39,18 +56,20 @@ public:
|
|||
std::string getaddressinfo(const std::string &address);
|
||||
std::string getblock(const std::string &block_hash, int32_t verbosity = 2);
|
||||
std::string getrawtransaction(const std::string &txid, const bool verbose = false);
|
||||
std::string getnetworkinfo();
|
||||
std::string gettransaction(const std::string &txid, const bool include_watch_only = false);
|
||||
std::string getblockchaininfo();
|
||||
void importaddress(const std::string &address_or_script, const std::string &label = "", const bool rescan = true, const bool p2sh = false);
|
||||
void importmulti(const std::vector<multi_params> &address_or_script_array, const bool rescan = true);
|
||||
std::vector<btc_txout> listunspent(const uint32_t minconf = 1, const uint32_t maxconf = 9999999);
|
||||
std::vector<btc_txout> listunspent_by_address_and_amount(const std::string &address, double transfer_amount, const uint32_t minconf = 1, const uint32_t maxconf = 9999999);
|
||||
std::string loadwallet(const std::string &filename);
|
||||
std::string sendrawtransaction(const std::string &tx_hex);
|
||||
std::string signrawtransactionwithwallet(const std::string &tx_hash);
|
||||
std::string unloadwallet(const std::string &filename);
|
||||
//std::string walletlock();
|
||||
std::string walletlock();
|
||||
std::string walletprocesspsbt(std::string const &tx_psbt);
|
||||
//bool walletpassphrase(const std::string &passphrase, uint32_t timeout = 60);
|
||||
bool walletpassphrase(const std::string &passphrase, uint32_t timeout = 60);
|
||||
|
||||
private:
|
||||
fc::http::reply send_post_request(std::string body, bool show_log);
|
||||
|
|
@ -105,6 +124,7 @@ private:
|
|||
std::string ip;
|
||||
uint32_t zmq_port;
|
||||
uint32_t rpc_port;
|
||||
uint32_t bitcoin_major_version;
|
||||
std::string rpc_user;
|
||||
std::string rpc_password;
|
||||
std::string wallet;
|
||||
|
|
|
|||
|
|
@ -25,6 +25,8 @@ public:
|
|||
void send_sidechain_transactions();
|
||||
void settle_sidechain_transactions();
|
||||
|
||||
std::map<sidechain_type, std::vector<std::string>> get_son_listener_log();
|
||||
|
||||
private:
|
||||
peerplays_sidechain_plugin &plugin;
|
||||
graphene::chain::database &database;
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@
|
|||
#include <graphene/chain/sidechain_address_object.hpp>
|
||||
#include <graphene/chain/son_wallet_object.hpp>
|
||||
#include <graphene/chain/son_wallet_withdraw_object.hpp>
|
||||
#include <graphene/peerplays_sidechain/sidechain_api.hpp>
|
||||
#include <graphene/peerplays_sidechain/sidechain_net_manager.hpp>
|
||||
#include <graphene/utilities/key_conversion.hpp>
|
||||
|
||||
|
|
@ -44,6 +45,7 @@ public:
|
|||
fc::ecc::private_key get_private_key(chain::public_key_type public_key);
|
||||
void log_son_proposal_retry(int op_type, object_id_type object_id);
|
||||
bool can_son_participate(int op_type, object_id_type object_id);
|
||||
std::map<sidechain_type, std::vector<std::string>> get_son_listener_log();
|
||||
|
||||
void schedule_heartbeat_loop();
|
||||
void heartbeat_loop();
|
||||
|
|
@ -176,12 +178,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) {
|
||||
|
|
@ -534,6 +530,10 @@ bool peerplays_sidechain_plugin_impl::can_son_participate(int op_type, object_id
|
|||
return (itr == son_retry_count.end() || itr->second < retries_threshold);
|
||||
}
|
||||
|
||||
std::map<sidechain_type, std::vector<std::string>> peerplays_sidechain_plugin_impl::get_son_listener_log() {
|
||||
return net_manager->get_son_listener_log();
|
||||
}
|
||||
|
||||
void peerplays_sidechain_plugin_impl::approve_proposals() {
|
||||
|
||||
auto check_approve_proposal = [&](const chain::son_id_type &son_id, const chain::proposal_object &proposal) {
|
||||
|
|
@ -794,4 +794,8 @@ bool peerplays_sidechain_plugin::can_son_participate(int op_type, object_id_type
|
|||
return my->can_son_participate(op_type, object_id);
|
||||
}
|
||||
|
||||
std::map<sidechain_type, std::vector<std::string>> peerplays_sidechain_plugin::get_son_listener_log() {
|
||||
return my->get_son_listener_log();
|
||||
}
|
||||
|
||||
}} // namespace graphene::peerplays_sidechain
|
||||
|
|
|
|||
48
libraries/plugins/peerplays_sidechain/sidechain_api.cpp
Normal file
48
libraries/plugins/peerplays_sidechain/sidechain_api.cpp
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
#include <graphene/peerplays_sidechain/sidechain_api.hpp>
|
||||
|
||||
namespace graphene { namespace peerplays_sidechain {
|
||||
|
||||
namespace detail {
|
||||
|
||||
class sidechain_api_impl {
|
||||
public:
|
||||
sidechain_api_impl(app::application &app);
|
||||
virtual ~sidechain_api_impl();
|
||||
|
||||
std::shared_ptr<graphene::peerplays_sidechain::peerplays_sidechain_plugin> get_plugin();
|
||||
|
||||
std::map<sidechain_type, std::vector<std::string>> get_son_listener_log();
|
||||
|
||||
private:
|
||||
app::application &app;
|
||||
};
|
||||
|
||||
sidechain_api_impl::sidechain_api_impl(app::application &_app) :
|
||||
app(_app) {
|
||||
}
|
||||
|
||||
sidechain_api_impl::~sidechain_api_impl() {
|
||||
}
|
||||
|
||||
std::shared_ptr<graphene::peerplays_sidechain::peerplays_sidechain_plugin> sidechain_api_impl::get_plugin() {
|
||||
return app.get_plugin<graphene::peerplays_sidechain::peerplays_sidechain_plugin>("peerplays_sidechain");
|
||||
}
|
||||
|
||||
std::map<sidechain_type, std::vector<std::string>> sidechain_api_impl::get_son_listener_log() {
|
||||
return get_plugin()->get_son_listener_log();
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
|
||||
sidechain_api::sidechain_api(graphene::app::application &_app) :
|
||||
my(std::make_shared<detail::sidechain_api_impl>(_app)) {
|
||||
}
|
||||
|
||||
sidechain_api::~sidechain_api() {
|
||||
}
|
||||
|
||||
std::map<sidechain_type, std::vector<std::string>> sidechain_api::get_son_listener_log() {
|
||||
return my->get_son_listener_log();
|
||||
}
|
||||
|
||||
}} // namespace graphene::peerplays_sidechain
|
||||
|
|
@ -589,7 +589,7 @@ void sidechain_net_handler::settle_sidechain_transactions() {
|
|||
if (settle_amount.amount != 0) {
|
||||
if (sto.object_id.is<son_wallet_deposit_id_type>()) {
|
||||
asset_issue_operation ai_op;
|
||||
ai_op.fee = asset(2001000);
|
||||
ai_op.fee = database.current_fee_schedule().calculate_fee(ai_op);
|
||||
ai_op.issuer = gpo.parameters.son_account();
|
||||
ai_op.asset_to_issue = settle_amount;
|
||||
ai_op.issue_to_account = database.get<son_wallet_deposit_object>(sto.object_id).peerplays_from;
|
||||
|
|
@ -598,7 +598,7 @@ void sidechain_net_handler::settle_sidechain_transactions() {
|
|||
|
||||
if (sto.object_id.is<son_wallet_withdraw_id_type>()) {
|
||||
asset_reserve_operation ar_op;
|
||||
ar_op.fee = asset(2001000);
|
||||
ar_op.fee = database.current_fee_schedule().calculate_fee(ar_op);
|
||||
ar_op.payer = gpo.parameters.son_account();
|
||||
ar_op.amount_to_reserve = settle_amount;
|
||||
proposal_op.proposed_ops.emplace_back(ar_op);
|
||||
|
|
@ -618,6 +618,17 @@ void sidechain_net_handler::settle_sidechain_transactions() {
|
|||
});
|
||||
}
|
||||
|
||||
void sidechain_net_handler::add_to_son_listener_log(std::string trx_id) {
|
||||
son_listener_log.insert(son_listener_log.begin(), trx_id);
|
||||
if (son_listener_log.size() > 33) {
|
||||
son_listener_log.erase(son_listener_log.end());
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<std::string> sidechain_net_handler::get_son_listener_log() {
|
||||
return son_listener_log;
|
||||
}
|
||||
|
||||
void sidechain_net_handler::on_applied_block(const signed_block &b) {
|
||||
|
||||
const chain::global_property_object &gpo = plugin.database().get_global_properties();
|
||||
|
|
|
|||
|
|
@ -41,6 +41,7 @@ bitcoin_rpc_client::bitcoin_rpc_client(std::string _ip, uint32_t _rpc, std::stri
|
|||
std::string bitcoin_rpc_client::addmultisigaddress(const uint32_t nrequired, const std::vector<std::string> public_keys) {
|
||||
std::string body = std::string("{\"jsonrpc\": \"1.0\", \"id\":\"addmultisigaddress\", "
|
||||
"\"method\": \"addmultisigaddress\", \"params\": [");
|
||||
try {
|
||||
std::string params = std::to_string(nrequired) + ", [";
|
||||
std::string pubkeys = "";
|
||||
for (std::string pubkey : public_keys) {
|
||||
|
|
@ -71,11 +72,16 @@ std::string bitcoin_rpc_client::addmultisigaddress(const uint32_t nrequired, con
|
|||
wlog("Bitcoin RPC call ${function} with body ${body} failed with reply '${msg}'", ("function", __FUNCTION__)("body", body)("msg", ss.str()));
|
||||
}
|
||||
return "";
|
||||
} catch (const boost::exception &ex) {
|
||||
wlog("Bitcoin RPC call ${function} with body ${body} generate exception: '${exception}'", ("function", __FUNCTION__)("body", body)("exception", boost::diagnostic_information(ex)));
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
std::string bitcoin_rpc_client::combinepsbt(const vector<std::string> &psbts) {
|
||||
std::string body = std::string("{\"jsonrpc\": \"1.0\", \"id\":\"combinepsbt\", \"method\": "
|
||||
"\"combinepsbt\", \"params\": [[");
|
||||
try {
|
||||
std::string params = "";
|
||||
for (std::string psbt : psbts) {
|
||||
if (!params.empty()) {
|
||||
|
|
@ -105,11 +111,16 @@ std::string bitcoin_rpc_client::combinepsbt(const vector<std::string> &psbts) {
|
|||
wlog("Bitcoin RPC call ${function} with body ${body} failed with reply '${msg}'", ("function", __FUNCTION__)("body", body)("msg", ss.str()));
|
||||
}
|
||||
return "";
|
||||
} catch (const boost::exception &ex) {
|
||||
wlog("Bitcoin RPC call ${function} with body ${body} generate exception: '${exception}'", ("function", __FUNCTION__)("body", body)("exception", boost::diagnostic_information(ex)));
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
std::string bitcoin_rpc_client::createmultisig(const uint32_t nrequired, const std::vector<std::string> public_keys) {
|
||||
std::string body = std::string("{\"jsonrpc\": \"1.0\", \"id\":\"createmultisig\", "
|
||||
"\"method\": \"createmultisig\", \"params\": [");
|
||||
try {
|
||||
std::string params = std::to_string(nrequired) + ", [";
|
||||
std::string pubkeys = "";
|
||||
for (std::string pubkey : public_keys) {
|
||||
|
|
@ -140,11 +151,16 @@ std::string bitcoin_rpc_client::createmultisig(const uint32_t nrequired, const s
|
|||
wlog("Bitcoin RPC call ${function} with body ${body} failed with reply '${msg}'", ("function", __FUNCTION__)("body", body)("msg", ss.str()));
|
||||
}
|
||||
return "";
|
||||
} catch (const boost::exception &ex) {
|
||||
wlog("Bitcoin RPC call ${function} with body ${body} generate exception: '${exception}'", ("function", __FUNCTION__)("body", body)("exception", boost::diagnostic_information(ex)));
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
std::string bitcoin_rpc_client::createpsbt(const std::vector<btc_txout> &ins, const fc::flat_map<std::string, double> outs) {
|
||||
std::string body("{\"jsonrpc\": \"1.0\", \"id\":\"createpsbt\", "
|
||||
"\"method\": \"createpsbt\", \"params\": [");
|
||||
try {
|
||||
body += "[";
|
||||
bool first = true;
|
||||
for (const auto &entry : ins) {
|
||||
|
|
@ -184,11 +200,16 @@ std::string bitcoin_rpc_client::createpsbt(const std::vector<btc_txout> &ins, co
|
|||
wlog("Bitcoin RPC call ${function} with body ${body} failed with reply '${msg}'", ("function", __FUNCTION__)("body", body)("msg", ss.str()));
|
||||
}
|
||||
return "";
|
||||
} catch (const boost::exception &ex) {
|
||||
wlog("Bitcoin RPC call ${function} with body ${body} generate exception: '${exception}'", ("function", __FUNCTION__)("body", body)("exception", boost::diagnostic_information(ex)));
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
std::string bitcoin_rpc_client::createrawtransaction(const std::vector<btc_txout> &ins, const fc::flat_map<std::string, double> outs) {
|
||||
std::string body("{\"jsonrpc\": \"1.0\", \"id\":\"createrawtransaction\", "
|
||||
"\"method\": \"createrawtransaction\", \"params\": [");
|
||||
try {
|
||||
body += "[";
|
||||
bool first = true;
|
||||
for (const auto &entry : ins) {
|
||||
|
|
@ -228,13 +249,17 @@ std::string bitcoin_rpc_client::createrawtransaction(const std::vector<btc_txout
|
|||
wlog("Bitcoin RPC call ${function} with body ${body} failed with reply '${msg}'", ("function", __FUNCTION__)("body", body)("msg", ss.str()));
|
||||
}
|
||||
return "";
|
||||
} catch (const boost::exception &ex) {
|
||||
wlog("Bitcoin RPC call ${function} with body ${body} generate exception: '${exception}'", ("function", __FUNCTION__)("body", body)("exception", boost::diagnostic_information(ex)));
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
std::string bitcoin_rpc_client::createwallet(const std::string &wallet_name) {
|
||||
std::string body = std::string("{\"jsonrpc\": \"1.0\", \"id\":\"createwallet\", \"method\": "
|
||||
"\"createwallet\", \"params\": [\"" +
|
||||
wallet_name + "\"] }");
|
||||
|
||||
try {
|
||||
const auto reply = send_post_request(body, debug_rpc_calls);
|
||||
|
||||
if (reply.body.empty()) {
|
||||
|
|
@ -256,13 +281,17 @@ std::string bitcoin_rpc_client::createwallet(const std::string &wallet_name) {
|
|||
wlog("Bitcoin RPC call ${function} with body ${body} failed with reply '${msg}'", ("function", __FUNCTION__)("body", body)("msg", ss.str()));
|
||||
}
|
||||
return "";
|
||||
} catch (const boost::exception &ex) {
|
||||
wlog("Bitcoin RPC call ${function} with body ${body} generate exception: '${exception}'", ("function", __FUNCTION__)("body", body)("exception", boost::diagnostic_information(ex)));
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
std::string bitcoin_rpc_client::decodepsbt(std::string const &tx_psbt) {
|
||||
std::string body = std::string("{\"jsonrpc\": \"1.0\", \"id\":\"decodepsbt\", \"method\": "
|
||||
"\"decodepsbt\", \"params\": [\"" +
|
||||
tx_psbt + "\"] }");
|
||||
|
||||
try {
|
||||
const auto reply = send_post_request(body, debug_rpc_calls);
|
||||
|
||||
if (reply.body.empty()) {
|
||||
|
|
@ -284,13 +313,17 @@ std::string bitcoin_rpc_client::decodepsbt(std::string const &tx_psbt) {
|
|||
wlog("Bitcoin RPC call ${function} with body ${body} failed with reply '${msg}'", ("function", __FUNCTION__)("body", body)("msg", ss.str()));
|
||||
}
|
||||
return "";
|
||||
} catch (const boost::exception &ex) {
|
||||
wlog("Bitcoin RPC call ${function} with body ${body} generate exception: '${exception}'", ("function", __FUNCTION__)("body", body)("exception", boost::diagnostic_information(ex)));
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
std::string bitcoin_rpc_client::decoderawtransaction(std::string const &tx_hex) {
|
||||
std::string body = std::string("{\"jsonrpc\": \"1.0\", \"id\":\"decoderawtransaction\", \"method\": "
|
||||
"\"decoderawtransaction\", \"params\": [\"" +
|
||||
tx_hex + "\"] }");
|
||||
|
||||
try {
|
||||
const auto reply = send_post_request(body, debug_rpc_calls);
|
||||
|
||||
if (reply.body.empty()) {
|
||||
|
|
@ -312,13 +345,17 @@ std::string bitcoin_rpc_client::decoderawtransaction(std::string const &tx_hex)
|
|||
wlog("Bitcoin RPC call ${function} with body ${body} failed with reply '${msg}'", ("function", __FUNCTION__)("body", body)("msg", ss.str()));
|
||||
}
|
||||
return "";
|
||||
} catch (const boost::exception &ex) {
|
||||
wlog("Bitcoin RPC call ${function} with body ${body} generate exception: '${exception}'", ("function", __FUNCTION__)("body", body)("exception", boost::diagnostic_information(ex)));
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
std::string bitcoin_rpc_client::encryptwallet(const std::string &passphrase) {
|
||||
std::string body = std::string("{\"jsonrpc\": \"1.0\", \"id\":\"encryptwallet\", \"method\": "
|
||||
"\"encryptwallet\", \"params\": [\"" +
|
||||
passphrase + "\"] }");
|
||||
|
||||
try {
|
||||
const auto reply = send_post_request(body, debug_rpc_calls);
|
||||
|
||||
if (reply.body.empty()) {
|
||||
|
|
@ -340,13 +377,17 @@ std::string bitcoin_rpc_client::encryptwallet(const std::string &passphrase) {
|
|||
wlog("Bitcoin RPC call ${function} with body ${body} failed with reply '${msg}'", ("function", __FUNCTION__)("body", body)("msg", ss.str()));
|
||||
}
|
||||
return "";
|
||||
} catch (const boost::exception &ex) {
|
||||
wlog("Bitcoin RPC call ${function} with body ${body} generate exception: '${exception}'", ("function", __FUNCTION__)("body", body)("exception", boost::diagnostic_information(ex)));
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
uint64_t bitcoin_rpc_client::estimatesmartfee(uint16_t conf_target) {
|
||||
const auto body = std::string("{\"jsonrpc\": \"1.0\", \"id\":\"estimatesmartfee\", "
|
||||
"\"method\": \"estimatesmartfee\", \"params\": [" +
|
||||
std::to_string(conf_target) + std::string("] }"));
|
||||
|
||||
try {
|
||||
const auto reply = send_post_request(body, debug_rpc_calls);
|
||||
|
||||
if (reply.body.empty()) {
|
||||
|
|
@ -377,13 +418,17 @@ uint64_t bitcoin_rpc_client::estimatesmartfee(uint16_t conf_target) {
|
|||
wlog("Bitcoin RPC call ${function} with body ${body} failed with reply '${msg}'", ("function", __FUNCTION__)("body", body)("msg", ss.str()));
|
||||
}
|
||||
return 20000;
|
||||
} catch (const boost::exception &ex) {
|
||||
wlog("Bitcoin RPC call ${function} with body ${body} generate exception: '${exception}'", ("function", __FUNCTION__)("body", body)("exception", boost::diagnostic_information(ex)));
|
||||
return 20000;
|
||||
}
|
||||
}
|
||||
|
||||
std::string bitcoin_rpc_client::finalizepsbt(std::string const &tx_psbt) {
|
||||
std::string body = std::string("{\"jsonrpc\": \"1.0\", \"id\":\"finalizepsbt\", \"method\": "
|
||||
"\"finalizepsbt\", \"params\": [\"" +
|
||||
tx_psbt + "\"] }");
|
||||
|
||||
try {
|
||||
const auto reply = send_post_request(body, debug_rpc_calls);
|
||||
|
||||
if (reply.body.empty()) {
|
||||
|
|
@ -403,13 +448,17 @@ std::string bitcoin_rpc_client::finalizepsbt(std::string const &tx_psbt) {
|
|||
wlog("Bitcoin RPC call ${function} with body ${body} failed with reply '${msg}'", ("function", __FUNCTION__)("body", body)("msg", ss.str()));
|
||||
}
|
||||
return "";
|
||||
} catch (const boost::exception &ex) {
|
||||
wlog("Bitcoin RPC call ${function} with body ${body} generate exception: '${exception}'", ("function", __FUNCTION__)("body", body)("exception", boost::diagnostic_information(ex)));
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
std::string bitcoin_rpc_client::getaddressinfo(const std::string &address) {
|
||||
std::string body = std::string("{\"jsonrpc\": \"1.0\", \"id\":\"getaddressinfo\", \"method\": "
|
||||
"\"getaddressinfo\", \"params\": [\"" +
|
||||
address + "\"] }");
|
||||
|
||||
try {
|
||||
const auto reply = send_post_request(body, debug_rpc_calls);
|
||||
|
||||
if (reply.body.empty()) {
|
||||
|
|
@ -431,13 +480,17 @@ std::string bitcoin_rpc_client::getaddressinfo(const std::string &address) {
|
|||
wlog("Bitcoin RPC call ${function} with body ${body} failed with reply '${msg}'", ("function", __FUNCTION__)("body", body)("msg", ss.str()));
|
||||
}
|
||||
return "";
|
||||
} catch (const boost::exception &ex) {
|
||||
wlog("Bitcoin RPC call ${function} with body ${body} generate exception: '${exception}'", ("function", __FUNCTION__)("body", body)("exception", boost::diagnostic_information(ex)));
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
std::string bitcoin_rpc_client::getblock(const std::string &block_hash, int32_t verbosity) {
|
||||
std::string body = std::string("{\"jsonrpc\": \"1.0\", \"id\":\"getblock\", \"method\": "
|
||||
"\"getblock\", \"params\": [\"" +
|
||||
block_hash + "\", " + std::to_string(verbosity) + "] }");
|
||||
|
||||
try {
|
||||
const auto reply = send_post_request(body, debug_rpc_calls);
|
||||
|
||||
if (reply.body.empty()) {
|
||||
|
|
@ -459,12 +512,46 @@ std::string bitcoin_rpc_client::getblock(const std::string &block_hash, int32_t
|
|||
wlog("Bitcoin RPC call ${function} with body ${body} failed with reply '${msg}'", ("function", __FUNCTION__)("body", body)("msg", ss.str()));
|
||||
}
|
||||
return "";
|
||||
} catch (const boost::exception &ex) {
|
||||
wlog("Bitcoin RPC call ${function} with body ${body} generate exception: '${exception}'", ("function", __FUNCTION__)("body", body)("exception", boost::diagnostic_information(ex)));
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
std::string bitcoin_rpc_client::getnetworkinfo() {
|
||||
std::string body = std::string("{\"jsonrpc\": \"1.0\", \"id\":\"getnetworkinfo\", \"method\": "
|
||||
"\"getnetworkinfo\", \"params\": [] }");
|
||||
try {
|
||||
const auto reply = send_post_request(body, debug_rpc_calls);
|
||||
|
||||
if (reply.body.empty()) {
|
||||
wlog("Bitcoin RPC call ${function} failed", ("function", __FUNCTION__));
|
||||
return "";
|
||||
}
|
||||
|
||||
std::stringstream ss(std::string(reply.body.begin(), reply.body.end()));
|
||||
boost::property_tree::ptree json;
|
||||
boost::property_tree::read_json(ss, json);
|
||||
|
||||
if (reply.status == 200) {
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
if (json.count("error") && !json.get_child("error").empty()) {
|
||||
wlog("Bitcoin RPC call ${function} with body ${body} failed with reply '${msg}'", ("function", __FUNCTION__)("body", body)("msg", ss.str()));
|
||||
}
|
||||
|
||||
return "";
|
||||
} catch (const boost::exception &ex) {
|
||||
wlog("Bitcoin RPC call ${function} with body ${body} generate exception: '${exception}'", ("function", __FUNCTION__)("body", body)("exception", boost::diagnostic_information(ex)));
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
std::string bitcoin_rpc_client::getrawtransaction(const std::string &txid, const bool verbose) {
|
||||
std::string body = std::string("{\"jsonrpc\": \"1.0\", \"id\":\"getrawtransaction\", \"method\": "
|
||||
"\"getrawtransaction\", \"params\": [");
|
||||
|
||||
try {
|
||||
std::string params = "\"" + txid + "\", " + (verbose ? "true" : "false");
|
||||
body = body + params + "] }";
|
||||
|
||||
|
|
@ -487,12 +574,16 @@ std::string bitcoin_rpc_client::getrawtransaction(const std::string &txid, const
|
|||
wlog("Bitcoin RPC call ${function} with body ${body} failed with reply '${msg}'", ("function", __FUNCTION__)("body", body)("msg", ss.str()));
|
||||
}
|
||||
return "";
|
||||
} catch (const boost::exception &ex) {
|
||||
wlog("Bitcoin RPC call ${function} with body ${body} generate exception: '${exception}'", ("function", __FUNCTION__)("body", body)("exception", boost::diagnostic_information(ex)));
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
std::string bitcoin_rpc_client::gettransaction(const std::string &txid, const bool include_watch_only) {
|
||||
std::string body = std::string("{\"jsonrpc\": \"1.0\", \"id\":\"gettransaction\", \"method\": "
|
||||
"\"gettransaction\", \"params\": [");
|
||||
|
||||
try {
|
||||
std::string params = "\"" + txid + "\", " + (include_watch_only ? "true" : "false");
|
||||
body = body + params + "] }";
|
||||
|
||||
|
|
@ -515,12 +606,16 @@ std::string bitcoin_rpc_client::gettransaction(const std::string &txid, const bo
|
|||
wlog("Bitcoin RPC call ${function} with body ${body} failed with reply '${msg}'", ("function", __FUNCTION__)("body", body)("msg", ss.str()));
|
||||
}
|
||||
return "";
|
||||
} catch (const boost::exception &ex) {
|
||||
wlog("Bitcoin RPC call ${function} with body ${body} generate exception: '${exception}'", ("function", __FUNCTION__)("body", body)("exception", boost::diagnostic_information(ex)));
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
std::string bitcoin_rpc_client::getblockchaininfo() {
|
||||
std::string body = std::string("{\"jsonrpc\": \"1.0\", \"id\":\"getblockchaininfo\", \"method\": "
|
||||
"\"getblockchaininfo\", \"params\": [] }");
|
||||
|
||||
try {
|
||||
const auto reply = send_post_request(body, debug_rpc_calls);
|
||||
|
||||
if (reply.body.empty()) {
|
||||
|
|
@ -542,12 +637,16 @@ std::string bitcoin_rpc_client::getblockchaininfo() {
|
|||
wlog("Bitcoin RPC call ${function} with body ${body} failed with reply '${msg}'", ("function", __FUNCTION__)("body", body)("msg", ss.str()));
|
||||
}
|
||||
return "";
|
||||
} catch (const boost::exception &ex) {
|
||||
wlog("Bitcoin RPC call ${function} with body ${body} generate exception: '${exception}'", ("function", __FUNCTION__)("body", body)("exception", boost::diagnostic_information(ex)));
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
void bitcoin_rpc_client::importaddress(const std::string &address_or_script, const std::string &label, const bool rescan, const bool p2sh) {
|
||||
std::string body = std::string("{\"jsonrpc\": \"1.0\", \"id\":\"importaddress\", "
|
||||
"\"method\": \"importaddress\", \"params\": [");
|
||||
|
||||
try {
|
||||
std::string params = "\"" + address_or_script + "\", " +
|
||||
"\"" + label + "\", " +
|
||||
(rescan ? "true" : "false") + ", " +
|
||||
|
|
@ -570,6 +669,63 @@ void bitcoin_rpc_client::importaddress(const std::string &address_or_script, con
|
|||
} else if (json.count("error") && !json.get_child("error").empty()) {
|
||||
wlog("Bitcoin RPC call ${function} with body ${body} failed with reply '${msg}'", ("function", __FUNCTION__)("body", body)("msg", ss.str()));
|
||||
}
|
||||
} catch (const boost::exception &ex) {
|
||||
wlog("Bitcoin RPC call ${function} with body ${body} generate exception: '${exception}'", ("function", __FUNCTION__)("body", body)("exception", boost::diagnostic_information(ex)));
|
||||
}
|
||||
}
|
||||
|
||||
void bitcoin_rpc_client::importmulti(const std::vector<multi_params> &address_or_script_array, const bool rescan) {
|
||||
std::string body = std::string("{\"jsonrpc\": \"1.0\", \"id\":\"importmulti\", "
|
||||
"\"method\": \"importmulti\", \"params\": [");
|
||||
try {
|
||||
std::string argument_1 = "[";
|
||||
for (const auto ¶m : address_or_script_array) {
|
||||
argument_1 += "{\"scriptPubKey\": ";
|
||||
if (param.type == multi_type::address) {
|
||||
argument_1 += "{\"address\": \"" + param.address_or_script + "\"}, \"label\": \"" + param.label + "\"";
|
||||
} else if (param.type == multi_type::script) {
|
||||
argument_1 += "\"" + param.address_or_script + "\", \"internal\": true";
|
||||
} else {
|
||||
FC_THROW("Invalid multi_type.");
|
||||
}
|
||||
argument_1 += ", \"timestamp\": " + std::to_string(fc::time_point_sec::from_iso_string("2022-01-01T00:00:00").sec_since_epoch()) + "}";
|
||||
|
||||
//! Note
|
||||
/* Creation time of the key expressed in UNIX epoch time,
|
||||
or the string "now" to substitute the current synced blockchain time. The timestamp of the oldest
|
||||
key will determine how far back blockchain rescans need to begin for missing wallet transactions.
|
||||
"now" can be specified to bypass scanning, for keys which are known to never have been used, and
|
||||
0 can be specified to scan the entire blockchain. Blocks up to 2 hours before the earliest key
|
||||
creation time of all keys being imported by the importmulti call will be scanned.*/
|
||||
|
||||
if (¶m != &address_or_script_array.back()) {
|
||||
argument_1 += ", ";
|
||||
}
|
||||
}
|
||||
argument_1 += "]";
|
||||
|
||||
std::string argument_2 = std::string{"{\"rescan\": "} + (rescan ? "true" : "false") + "}";
|
||||
body += argument_1 + ", " + argument_2 + "]}";
|
||||
|
||||
const auto reply = send_post_request(body, debug_rpc_calls);
|
||||
|
||||
if (reply.body.empty()) {
|
||||
wlog("Bitcoin RPC call ${function} failed", ("function", __FUNCTION__));
|
||||
return;
|
||||
}
|
||||
|
||||
std::stringstream ss(std::string(reply.body.begin(), reply.body.end()));
|
||||
boost::property_tree::ptree json;
|
||||
boost::property_tree::read_json(ss, json);
|
||||
|
||||
if (reply.status == 200) {
|
||||
return;
|
||||
} else if (json.count("error") && !json.get_child("error").empty()) {
|
||||
wlog("Bitcoin RPC call ${function} with body ${body} failed with reply '${msg}'", ("function", __FUNCTION__)("body", body)("msg", ss.str()));
|
||||
}
|
||||
} catch (const boost::exception &ex) {
|
||||
wlog("Bitcoin RPC call ${function} with body ${body} generate exception: '${exception}'", ("function", __FUNCTION__)("body", body)("exception", boost::diagnostic_information(ex)));
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<btc_txout> bitcoin_rpc_client::listunspent(const uint32_t minconf, const uint32_t maxconf) {
|
||||
|
|
@ -577,9 +733,9 @@ std::vector<btc_txout> bitcoin_rpc_client::listunspent(const uint32_t minconf, c
|
|||
"\"listunspent\", \"params\": [" +
|
||||
std::to_string(minconf) + "," + std::to_string(maxconf) + "] }");
|
||||
|
||||
const auto reply = send_post_request(body, debug_rpc_calls);
|
||||
|
||||
std::vector<btc_txout> result;
|
||||
try {
|
||||
const auto reply = send_post_request(body, debug_rpc_calls);
|
||||
|
||||
if (reply.body.empty()) {
|
||||
wlog("Bitcoin RPC call ${function} failed", ("function", __FUNCTION__));
|
||||
|
|
@ -606,6 +762,10 @@ std::vector<btc_txout> bitcoin_rpc_client::listunspent(const uint32_t minconf, c
|
|||
wlog("Bitcoin RPC call ${function} with body ${body} failed with reply '${msg}'", ("function", __FUNCTION__)("body", body)("msg", ss.str()));
|
||||
}
|
||||
return result;
|
||||
} catch (const boost::exception &ex) {
|
||||
wlog("Bitcoin RPC call ${function} with body ${body} generate exception: '${exception}'", ("function", __FUNCTION__)("body", body)("exception", boost::diagnostic_information(ex)));
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<btc_txout> bitcoin_rpc_client::listunspent_by_address_and_amount(const std::string &address, double minimum_amount, const uint32_t minconf, const uint32_t maxconf) {
|
||||
|
|
@ -618,9 +778,11 @@ std::vector<btc_txout> bitcoin_rpc_client::listunspent_by_address_and_amount(con
|
|||
body += std::to_string(minimum_amount);
|
||||
body += std::string("} ] }");
|
||||
|
||||
std::vector<btc_txout> result;
|
||||
|
||||
try {
|
||||
const auto reply = send_post_request(body, debug_rpc_calls);
|
||||
|
||||
std::vector<btc_txout> result;
|
||||
if (reply.body.empty()) {
|
||||
wlog("Bitcoin RPC call ${function} failed", ("function", __FUNCTION__));
|
||||
return result;
|
||||
|
|
@ -646,13 +808,17 @@ std::vector<btc_txout> bitcoin_rpc_client::listunspent_by_address_and_amount(con
|
|||
wlog("Bitcoin RPC call ${function} with body ${body} failed with reply '${msg}'", ("function", __FUNCTION__)("body", body)("msg", ss.str()));
|
||||
}
|
||||
return result;
|
||||
} catch (const boost::exception &ex) {
|
||||
wlog("Bitcoin RPC call ${function} with body ${body} generate exception: '${exception}'", ("function", __FUNCTION__)("body", body)("exception", boost::diagnostic_information(ex)));
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
std::string bitcoin_rpc_client::loadwallet(const std::string &filename) {
|
||||
std::string body = std::string("{\"jsonrpc\": \"1.0\", \"id\":\"loadwallet\", \"method\": "
|
||||
"\"loadwallet\", \"params\": [\"" +
|
||||
filename + "\"] }");
|
||||
|
||||
try {
|
||||
const auto reply = send_post_request(body, debug_rpc_calls);
|
||||
|
||||
if (reply.body.empty()) {
|
||||
|
|
@ -674,13 +840,17 @@ std::string bitcoin_rpc_client::loadwallet(const std::string &filename) {
|
|||
wlog("Bitcoin RPC call ${function} with body ${body} failed with reply '${msg}'", ("function", __FUNCTION__)("body", body)("msg", ss.str()));
|
||||
}
|
||||
return "";
|
||||
} catch (const boost::exception &ex) {
|
||||
wlog("Bitcoin RPC call ${function} with body ${body} generate exception: '${exception}'", ("function", __FUNCTION__)("body", body)("exception", boost::diagnostic_information(ex)));
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
std::string bitcoin_rpc_client::sendrawtransaction(const std::string &tx_hex) {
|
||||
const auto body = std::string("{\"jsonrpc\": \"1.0\", \"id\":\"sendrawtransaction\", "
|
||||
"\"method\": \"sendrawtransaction\", \"params\": [") +
|
||||
std::string("\"") + tx_hex + std::string("\"") + std::string("] }");
|
||||
|
||||
try {
|
||||
const auto reply = send_post_request(body, debug_rpc_calls);
|
||||
|
||||
if (reply.body.empty()) {
|
||||
|
|
@ -700,6 +870,10 @@ std::string bitcoin_rpc_client::sendrawtransaction(const std::string &tx_hex) {
|
|||
wlog("Bitcoin RPC call ${function} with body ${body} failed with reply '${msg}'", ("function", __FUNCTION__)("body", body)("msg", ss.str()));
|
||||
}
|
||||
return "";
|
||||
} catch (const boost::exception &ex) {
|
||||
wlog("Bitcoin RPC call ${function} with body ${body} generate exception: '${exception}'", ("function", __FUNCTION__)("body", body)("exception", boost::diagnostic_information(ex)));
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
std::string bitcoin_rpc_client::signrawtransactionwithwallet(const std::string &tx_hash) {
|
||||
|
|
@ -708,6 +882,7 @@ std::string bitcoin_rpc_client::signrawtransactionwithwallet(const std::string &
|
|||
std::string params = "\"" + tx_hash + "\"";
|
||||
body = body + params + std::string("]}");
|
||||
|
||||
try {
|
||||
const auto reply = send_post_request(body, debug_rpc_calls);
|
||||
|
||||
if (reply.body.empty()) {
|
||||
|
|
@ -727,13 +902,17 @@ std::string bitcoin_rpc_client::signrawtransactionwithwallet(const std::string &
|
|||
wlog("Bitcoin RPC call ${function} with body ${body} failed with reply '${msg}'", ("function", __FUNCTION__)("body", body)("msg", ss.str()));
|
||||
}
|
||||
return "";
|
||||
} catch (const boost::exception &ex) {
|
||||
wlog("Bitcoin RPC call ${function} with body ${body} generate exception: '${exception}'", ("function", __FUNCTION__)("body", body)("exception", boost::diagnostic_information(ex)));
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
std::string bitcoin_rpc_client::unloadwallet(const std::string &filename) {
|
||||
std::string body = std::string("{\"jsonrpc\": \"1.0\", \"id\":\"unloadwallet\", \"method\": "
|
||||
"\"unloadwallet\", \"params\": [\"" +
|
||||
filename + "\"] }");
|
||||
|
||||
try {
|
||||
const auto reply = send_post_request(body, debug_rpc_calls);
|
||||
|
||||
if (reply.body.empty()) {
|
||||
|
|
@ -755,40 +934,48 @@ std::string bitcoin_rpc_client::unloadwallet(const std::string &filename) {
|
|||
wlog("Bitcoin RPC call ${function} with body ${body} failed with reply '${msg}'", ("function", __FUNCTION__)("body", body)("msg", ss.str()));
|
||||
}
|
||||
return "";
|
||||
} catch (const boost::exception &ex) {
|
||||
wlog("Bitcoin RPC call ${function} with body ${body} generate exception: '${exception}'", ("function", __FUNCTION__)("body", body)("exception", boost::diagnostic_information(ex)));
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
//std::string bitcoin_rpc_client::walletlock() {
|
||||
// std::string body = std::string("{\"jsonrpc\": \"1.0\", \"id\":\"walletlock\", \"method\": "
|
||||
// "\"walletlock\", \"params\": [] }");
|
||||
//
|
||||
// const auto reply = send_post_request(body, debug_rpc_calls);
|
||||
//
|
||||
// if (reply.body.empty()) {
|
||||
// wlog("Bitcoin RPC call ${function} failed", ("function", __FUNCTION__));
|
||||
// return "";
|
||||
// }
|
||||
//
|
||||
// std::stringstream ss(std::string(reply.body.begin(), reply.body.end()));
|
||||
// boost::property_tree::ptree json;
|
||||
// boost::property_tree::read_json(ss, json);
|
||||
//
|
||||
// if (reply.status == 200) {
|
||||
// std::stringstream ss;
|
||||
// boost::property_tree::json_parser::write_json(ss, json.get_child("result"));
|
||||
// return ss.str();
|
||||
// }
|
||||
//
|
||||
// if (json.count("error") && !json.get_child("error").empty()) {
|
||||
// wlog("Bitcoin RPC call ${function} with body ${body} failed with reply '${msg}'", ("function", __FUNCTION__)("body", body)("msg", ss.str()));
|
||||
// }
|
||||
// return "";
|
||||
//}
|
||||
std::string bitcoin_rpc_client::walletlock() {
|
||||
std::string body = std::string("{\"jsonrpc\": \"1.0\", \"id\":\"walletlock\", \"method\": "
|
||||
"\"walletlock\", \"params\": [] }");
|
||||
try {
|
||||
const auto reply = send_post_request(body, debug_rpc_calls);
|
||||
|
||||
if (reply.body.empty()) {
|
||||
wlog("Bitcoin RPC call ${function} failed", ("function", __FUNCTION__));
|
||||
return "";
|
||||
}
|
||||
|
||||
std::stringstream ss(std::string(reply.body.begin(), reply.body.end()));
|
||||
boost::property_tree::ptree json;
|
||||
boost::property_tree::read_json(ss, json);
|
||||
|
||||
if (reply.status == 200) {
|
||||
std::stringstream ss;
|
||||
boost::property_tree::json_parser::write_json(ss, json.get_child("result"));
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
if (json.count("error") && !json.get_child("error").empty()) {
|
||||
wlog("Bitcoin RPC call ${function} with body ${body} failed with reply '${msg}'", ("function", __FUNCTION__)("body", body)("msg", ss.str()));
|
||||
}
|
||||
return "";
|
||||
} catch (const boost::exception &ex) {
|
||||
wlog("Bitcoin RPC call ${function} with body ${body} generate exception: '${exception}'", ("function", __FUNCTION__)("body", body)("exception", boost::diagnostic_information(ex)));
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
std::string bitcoin_rpc_client::walletprocesspsbt(std::string const &tx_psbt) {
|
||||
std::string body = std::string("{\"jsonrpc\": \"1.0\", \"id\":\"walletprocesspsbt\", \"method\": "
|
||||
"\"walletprocesspsbt\", \"params\": [\"" +
|
||||
tx_psbt + "\"] }");
|
||||
|
||||
try {
|
||||
const auto reply = send_post_request(body, debug_rpc_calls);
|
||||
|
||||
if (reply.body.empty()) {
|
||||
|
|
@ -808,33 +995,41 @@ std::string bitcoin_rpc_client::walletprocesspsbt(std::string const &tx_psbt) {
|
|||
wlog("Bitcoin RPC call ${function} with body ${body} failed with reply '${msg}'", ("function", __FUNCTION__)("body", body)("msg", ss.str()));
|
||||
}
|
||||
return "";
|
||||
} catch (const boost::exception &ex) {
|
||||
wlog("Bitcoin RPC call ${function} with body ${body} generate exception: '${exception}'", ("function", __FUNCTION__)("body", body)("exception", boost::diagnostic_information(ex)));
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
//bool bitcoin_rpc_client::walletpassphrase(const std::string &passphrase, uint32_t timeout) {
|
||||
// std::string body = std::string("{\"jsonrpc\": \"1.0\", \"id\":\"walletpassphrase\", \"method\": "
|
||||
// "\"walletpassphrase\", \"params\": [\"" +
|
||||
// passphrase + "\", " + std::to_string(timeout) + "] }");
|
||||
//
|
||||
// const auto reply = send_post_request(body, debug_rpc_calls);
|
||||
//
|
||||
// if (reply.body.empty()) {
|
||||
// wlog("Bitcoin RPC call ${function} failed", ("function", __FUNCTION__));
|
||||
// return false;
|
||||
// }
|
||||
//
|
||||
// std::stringstream ss(std::string(reply.body.begin(), reply.body.end()));
|
||||
// boost::property_tree::ptree json;
|
||||
// boost::property_tree::read_json(ss, json);
|
||||
//
|
||||
// if (reply.status == 200) {
|
||||
// return true;
|
||||
// }
|
||||
//
|
||||
// if (json.count("error") && !json.get_child("error").empty()) {
|
||||
// wlog("Bitcoin RPC call ${function} with body ${body} failed with reply '${msg}'", ("function", __FUNCTION__)("body", body)("msg", ss.str()));
|
||||
// }
|
||||
// return false;
|
||||
//}
|
||||
bool bitcoin_rpc_client::walletpassphrase(const std::string &passphrase, uint32_t timeout) {
|
||||
std::string body = std::string("{\"jsonrpc\": \"1.0\", \"id\":\"walletpassphrase\", \"method\": "
|
||||
"\"walletpassphrase\", \"params\": [\"" +
|
||||
passphrase + "\", " + std::to_string(timeout) + "] }");
|
||||
try {
|
||||
const auto reply = send_post_request(body, debug_rpc_calls);
|
||||
|
||||
if (reply.body.empty()) {
|
||||
wlog("Bitcoin RPC call ${function} failed", ("function", __FUNCTION__));
|
||||
return false;
|
||||
}
|
||||
|
||||
std::stringstream ss(std::string(reply.body.begin(), reply.body.end()));
|
||||
boost::property_tree::ptree json;
|
||||
boost::property_tree::read_json(ss, json);
|
||||
|
||||
if (reply.status == 200) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (json.count("error") && !json.get_child("error").empty()) {
|
||||
wlog("Bitcoin RPC call ${function} with body ${body} failed with reply '${msg}'", ("function", __FUNCTION__)("body", body)("msg", ss.str()));
|
||||
}
|
||||
return false;
|
||||
} catch (const boost::exception &ex) {
|
||||
wlog("Bitcoin RPC call ${function} with body ${body} generate exception: '${exception}'", ("function", __FUNCTION__)("body", body)("exception", boost::diagnostic_information(ex)));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
fc::http::reply bitcoin_rpc_client::send_post_request(std::string body, bool show_log) {
|
||||
fc::http::connection conn;
|
||||
|
|
@ -852,6 +1047,7 @@ fc::http::reply bitcoin_rpc_client::send_post_request(std::string body, bool sho
|
|||
ilog("### Request URL: ${url}", ("url", url));
|
||||
ilog("### Request: ${body}", ("body", body));
|
||||
std::stringstream ss(std::string(reply.body.begin(), reply.body.end()));
|
||||
ilog("### Response status: ${status}", ("status", reply.status));
|
||||
ilog("### Response: ${ss}", ("ss", ss.str()));
|
||||
}
|
||||
|
||||
|
|
@ -871,16 +1067,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 +1093,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()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -970,6 +1162,14 @@ sidechain_net_handler_bitcoin::sidechain_net_handler_bitcoin(peerplays_sidechain
|
|||
}
|
||||
}
|
||||
|
||||
std::string network_info_str = bitcoin_client->getnetworkinfo();
|
||||
std::stringstream network_info_ss(network_info_str);
|
||||
boost::property_tree::ptree network_info_json;
|
||||
boost::property_tree::read_json(network_info_ss, network_info_json);
|
||||
|
||||
bitcoin_major_version = network_info_json.get<uint32_t>("result.version") / 10000;
|
||||
ilog("Bitcoin major version is: '${version}'", ("version", bitcoin_major_version));
|
||||
|
||||
listener = std::unique_ptr<zmq_listener>(new zmq_listener(ip, zmq_port));
|
||||
listener->event_received.connect([this](const std::string &event_data) {
|
||||
std::thread(&sidechain_net_handler_bitcoin::handle_event, this, event_data).detach();
|
||||
|
|
@ -1120,12 +1320,19 @@ bool sidechain_net_handler_bitcoin::process_proposal(const proposal_object &po)
|
|||
std::string tx_vout_s = input.second.get<std::string>("n");
|
||||
tx_vout = std::stoll(tx_vout_s);
|
||||
if (tx_vout == swdo_vout) {
|
||||
if (bitcoin_major_version > 21) {
|
||||
std::string address = input.second.get<std::string>("scriptPubKey.address");
|
||||
if (address == swdo_address) {
|
||||
tx_address = address;
|
||||
}
|
||||
} else {
|
||||
for (auto &address : input.second.get_child("scriptPubKey.addresses")) {
|
||||
if (address.second.data() == swdo_address) {
|
||||
tx_address = address.second.data();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
std::string tx_amount_s = input.second.get<std::string>("value");
|
||||
tx_amount_s.erase(std::remove(tx_amount_s.begin(), tx_amount_s.end(), '.'), tx_amount_s.end());
|
||||
tx_amount = std::stoll(tx_amount_s);
|
||||
|
|
@ -1535,6 +1742,14 @@ bool sidechain_net_handler_bitcoin::settle_sidechain_transaction(const sidechain
|
|||
if (tx_confirmations >= gpo.parameters.son_bitcoin_min_tx_confirmations()) {
|
||||
if (sto.object_id.is<son_wallet_deposit_id_type>()) {
|
||||
for (auto &input : tx_json.get_child("result.vout")) {
|
||||
if (bitcoin_major_version > 21) {
|
||||
std::string address = input.second.get<std::string>("scriptPubKey.address");
|
||||
if (address == tx_address) {
|
||||
std::string tx_amount_s = input.second.get<std::string>("value");
|
||||
tx_amount_s.erase(std::remove(tx_amount_s.begin(), tx_amount_s.end(), '.'), tx_amount_s.end());
|
||||
tx_amount = std::stoll(tx_amount_s);
|
||||
}
|
||||
} else {
|
||||
for (auto &address : input.second.get_child("scriptPubKey.addresses")) {
|
||||
if (address.second.data() == tx_address) {
|
||||
std::string tx_amount_s = input.second.get<std::string>("value");
|
||||
|
|
@ -1544,6 +1759,7 @@ bool sidechain_net_handler_bitcoin::settle_sidechain_transaction(const sidechain
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
settle_amount = asset(tx_amount, database.get_global_properties().parameters.btc_asset());
|
||||
return true;
|
||||
}
|
||||
|
|
@ -1617,7 +1833,7 @@ std::string sidechain_net_handler_bitcoin::create_primary_wallet_transaction(con
|
|||
}
|
||||
|
||||
if (fee_rate >= total_amount) {
|
||||
elog("Failed not enough BTC to transfer from ${fa}", ("fa", prev_pw_address));
|
||||
elog("Not enough BTC to pay the transfer fee, address ${fa}", ("fa", prev_pw_address));
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
|
@ -1651,6 +1867,12 @@ std::string sidechain_net_handler_bitcoin::create_deposit_transaction(const son_
|
|||
uint64_t fee_rate = bitcoin_client->estimatesmartfee();
|
||||
uint64_t min_fee_rate = 1000;
|
||||
fee_rate = std::max(fee_rate, min_fee_rate);
|
||||
|
||||
if (fee_rate >= deposit_amount) {
|
||||
elog("Not enough BTC to pay the transfer fee, address ${da}", ("da", swdo.sidechain_from));
|
||||
return "";
|
||||
}
|
||||
|
||||
deposit_amount -= fee_rate; // Deduct minimum relay fee
|
||||
double transfer_amount = (double)deposit_amount / 100000000.0;
|
||||
|
||||
|
|
@ -1701,7 +1923,7 @@ std::string sidechain_net_handler_bitcoin::create_withdrawal_transaction(const s
|
|||
}
|
||||
|
||||
if ((swwo.withdraw_amount.value > total_amount) || (fee_rate >= swwo.withdraw_amount.value)) {
|
||||
elog("Failed not enough BTC to spend for ${pw}", ("pw", pw_address));
|
||||
elog("Not enough BTC to pay the transfer fee, address ${pw}", ("pw", pw_address));
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
|
@ -1808,6 +2030,8 @@ void sidechain_net_handler_bitcoin::handle_event(const std::string &event_data)
|
|||
if (block.empty())
|
||||
return;
|
||||
|
||||
add_to_son_listener_log("BLOCK : " + event_data);
|
||||
|
||||
auto vins = extract_info_from_block(block);
|
||||
scoped_lock interlock(event_handler_mutex);
|
||||
const auto &sidechain_addresses_idx = database.get_index_type<sidechain_address_index>().indices().get<by_sidechain_and_deposit_address_and_expires>();
|
||||
|
|
@ -1837,6 +2061,9 @@ void sidechain_net_handler_bitcoin::handle_event(const std::string &event_data)
|
|||
sed.peerplays_to = database.get_global_properties().parameters.son_account();
|
||||
price btc_price = database.get<asset_object>(database.get_global_properties().parameters.btc_asset()).options.core_exchange_rate;
|
||||
sed.peerplays_asset = asset(sed.sidechain_amount * btc_price.base.amount / btc_price.quote.amount);
|
||||
|
||||
add_to_son_listener_log("TRX : " + sed.sidechain_transaction_id);
|
||||
|
||||
sidechain_event_data_received(sed);
|
||||
}
|
||||
}
|
||||
|
|
@ -1879,11 +2106,16 @@ std::vector<info_for_vin> sidechain_net_handler_bitcoin::extract_info_from_block
|
|||
for (const auto &o : tx.get_child("vout")) {
|
||||
const auto script = o.second.get_child("scriptPubKey");
|
||||
|
||||
if (bitcoin_major_version > 21) {
|
||||
if (!script.count("address"))
|
||||
continue;
|
||||
} else {
|
||||
if (!script.count("addresses"))
|
||||
continue;
|
||||
}
|
||||
|
||||
for (const auto &addr : script.get_child("addresses")) { // in which cases there can be more addresses?
|
||||
const auto address_base58 = addr.second.get_value<std::string>();
|
||||
auto sort_out_vin = [&](std::string address) {
|
||||
const auto address_base58 = address;
|
||||
info_for_vin vin;
|
||||
vin.out.hash_tx = tx.get_child("txid").get_value<std::string>();
|
||||
string amount = o.second.get_child("value").get_value<std::string>();
|
||||
|
|
@ -1892,6 +2124,14 @@ std::vector<info_for_vin> sidechain_net_handler_bitcoin::extract_info_from_block
|
|||
vin.out.n_vout = o.second.get_child("n").get_value<uint32_t>();
|
||||
vin.address = address_base58;
|
||||
result.push_back(vin);
|
||||
};
|
||||
|
||||
if (bitcoin_major_version > 21) {
|
||||
std::string address = script.get<std::string>("address");
|
||||
sort_out_vin(address);
|
||||
} else {
|
||||
for (const auto &addr : script.get_child("addresses")) // in which cases there can be more addresses?
|
||||
sort_out_vin(addr.second.get_value<std::string>());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1912,6 +2152,8 @@ void sidechain_net_handler_bitcoin::on_changed_objects(const vector<object_id_ty
|
|||
}
|
||||
|
||||
void sidechain_net_handler_bitcoin::on_changed_objects_cb(const vector<object_id_type> &ids, const flat_set<account_id_type> &accounts) {
|
||||
std::vector<bitcoin_rpc_client::multi_params> address_or_script_array;
|
||||
|
||||
for (auto id : ids) {
|
||||
if (id.is<son_wallet_object>()) {
|
||||
const auto &swi = database.get_index_type<son_wallet_index>().indices().get<by_id>();
|
||||
|
|
@ -1923,16 +2165,31 @@ void sidechain_net_handler_bitcoin::on_changed_objects_cb(const vector<object_id
|
|||
|
||||
if (pw_pt.count("address")) {
|
||||
std::string pw_address = pw_pt.get<std::string>("address");
|
||||
bitcoin_client->importaddress(pw_address);
|
||||
address_or_script_array.emplace_back(bitcoin_rpc_client::multi_params{bitcoin_rpc_client::multi_type::address, pw_address});
|
||||
}
|
||||
|
||||
if (pw_pt.count("redeemScript")) {
|
||||
std::string pw_redeem_script = pw_pt.get<std::string>("redeemScript");
|
||||
bitcoin_client->importaddress(pw_redeem_script, "", true, true);
|
||||
address_or_script_array.emplace_back(bitcoin_rpc_client::multi_params{bitcoin_rpc_client::multi_type::script, pw_redeem_script});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//! importmulti all addreses in one bulk
|
||||
if (!address_or_script_array.empty()) {
|
||||
//! Unlock wallet
|
||||
if (!wallet_password.empty()) {
|
||||
if (!bitcoin_client->walletpassphrase(wallet_password))
|
||||
return;
|
||||
}
|
||||
|
||||
//! importmulti
|
||||
bitcoin_client->importmulti(address_or_script_array);
|
||||
|
||||
//! Lock wallet
|
||||
bitcoin_client->walletlock();
|
||||
}
|
||||
}
|
||||
|
||||
// =============================================================================
|
||||
|
|
|
|||
|
|
@ -627,7 +627,7 @@ bool sidechain_net_handler_hive::process_deposit(const son_wallet_deposit_object
|
|||
proposal_op.proposed_ops.emplace_back(swdp_op);
|
||||
|
||||
asset_issue_operation ai_op;
|
||||
ai_op.fee = asset(2001000);
|
||||
ai_op.fee = database.current_fee_schedule().calculate_fee(ai_op);
|
||||
ai_op.issuer = gpo.parameters.son_account();
|
||||
ai_op.asset_to_issue = asset_to_issue;
|
||||
ai_op.issue_to_account = swdo.peerplays_from;
|
||||
|
|
@ -846,6 +846,7 @@ void sidechain_net_handler_hive::hive_listener_loop() {
|
|||
void sidechain_net_handler_hive::handle_event(const std::string &event_data) {
|
||||
std::string block = node_rpc_client->block_api_get_block(std::atoll(event_data.c_str()));
|
||||
if (block != "") {
|
||||
add_to_son_listener_log("BLOCK : " + event_data);
|
||||
std::stringstream ss(block);
|
||||
boost::property_tree::ptree block_json;
|
||||
boost::property_tree::read_json(ss, block_json);
|
||||
|
|
@ -932,6 +933,9 @@ void sidechain_net_handler_hive::handle_event(const std::string &event_data) {
|
|||
sed.peerplays_from = accn;
|
||||
sed.peerplays_to = database.get_global_properties().parameters.son_account();
|
||||
sed.peerplays_asset = asset(sed.sidechain_amount * sidechain_currency_price.base.amount / sidechain_currency_price.quote.amount);
|
||||
|
||||
add_to_son_listener_log("TRX : " + sed.sidechain_transaction_id);
|
||||
|
||||
sidechain_event_data_received(sed);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -98,6 +98,14 @@ void sidechain_net_manager::settle_sidechain_transactions() {
|
|||
}
|
||||
}
|
||||
|
||||
std::map<sidechain_type, std::vector<std::string>> sidechain_net_manager::get_son_listener_log() {
|
||||
std::map<sidechain_type, std::vector<std::string>> result;
|
||||
for (size_t i = 0; i < net_handlers.size(); i++) {
|
||||
result[net_handlers.at(i)->get_sidechain()] = net_handlers.at(i)->get_son_listener_log();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void sidechain_net_manager::on_applied_block(const signed_block &b) {
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -24,7 +24,6 @@
|
|||
#include <graphene/utilities/elasticsearch.hpp>
|
||||
|
||||
#include <boost/algorithm/string/join.hpp>
|
||||
#include <boost/algorithm/string.hpp>
|
||||
#include <fc/log/logger.hpp>
|
||||
#include <fc/io/json.hpp>
|
||||
|
||||
|
|
@ -47,8 +46,36 @@ bool checkES(ES& es)
|
|||
if(doCurl(curl_request).empty())
|
||||
return false;
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
const std::string getESVersion(ES& es)
|
||||
{
|
||||
graphene::utilities::CurlRequest curl_request;
|
||||
curl_request.handler = es.curl;
|
||||
curl_request.url = es.elasticsearch_url;
|
||||
curl_request.auth = es.auth;
|
||||
curl_request.type = "GET";
|
||||
|
||||
fc::variant response = fc::json::from_string(doCurl(curl_request));
|
||||
|
||||
return response["version"]["number"].as_string();
|
||||
}
|
||||
|
||||
void checkESVersion7OrAbove(ES& es, bool& result) noexcept
|
||||
{
|
||||
static const int64_t version_7 = 7;
|
||||
try {
|
||||
const auto es_version = graphene::utilities::getESVersion(es);
|
||||
auto dot_pos = es_version.find('.');
|
||||
result = ( std::stoi(es_version.substr(0,dot_pos)) >= version_7 );
|
||||
}
|
||||
catch( ... )
|
||||
{
|
||||
wlog( "Unable to get ES version, assuming it is 7 or above" );
|
||||
result = true;
|
||||
}
|
||||
}
|
||||
|
||||
const std::string simpleQuery(ES& es)
|
||||
{
|
||||
graphene::utilities::CurlRequest curl_request;
|
||||
|
|
@ -118,13 +145,13 @@ bool handleBulkResponse(long http_code, const std::string& CurlReadBuffer)
|
|||
return true;
|
||||
}
|
||||
|
||||
const std::vector<std::string> createBulk(const fc::mutable_variant_object& bulk_header, const std::string& data)
|
||||
const std::vector<std::string> createBulk(const fc::mutable_variant_object& bulk_header, const std::string&& data)
|
||||
{
|
||||
std::vector<std::string> bulk;
|
||||
fc::mutable_variant_object final_bulk_header;
|
||||
final_bulk_header["index"] = bulk_header;
|
||||
bulk.push_back(fc::json::to_string(final_bulk_header));
|
||||
bulk.push_back(data);
|
||||
bulk.emplace_back(std::move(data));
|
||||
|
||||
return bulk;
|
||||
}
|
||||
|
|
@ -154,15 +181,6 @@ const std::string getEndPoint(ES& es)
|
|||
return doCurl(curl_request);
|
||||
}
|
||||
|
||||
const std::string generateIndexName(const fc::time_point_sec& block_date, const std::string& _elasticsearch_index_prefix)
|
||||
{
|
||||
auto block_date_string = block_date.to_iso_string();
|
||||
std::vector<std::string> parts;
|
||||
boost::split(parts, block_date_string, boost::is_any_of("-"));
|
||||
std::string index_name = _elasticsearch_index_prefix + parts[0] + "-" + parts[1];
|
||||
return index_name;
|
||||
}
|
||||
|
||||
const std::string doCurl(CurlRequest& curl)
|
||||
{
|
||||
std::string CurlReadBuffer;
|
||||
|
|
|
|||
|
|
@ -54,13 +54,14 @@ namespace graphene { namespace utilities {
|
|||
};
|
||||
|
||||
bool SendBulk(ES& es);
|
||||
const std::vector<std::string> createBulk(const fc::mutable_variant_object& bulk_header, const std::string& data);
|
||||
const std::vector<std::string> createBulk(const fc::mutable_variant_object& bulk_header, const std::string&& data);
|
||||
bool checkES(ES& es);
|
||||
const std::string getESVersion(ES& es);
|
||||
void checkESVersion7OrAbove(ES& es, bool& result) noexcept;
|
||||
const std::string simpleQuery(ES& es);
|
||||
bool deleteAll(ES& es);
|
||||
bool handleBulkResponse(long http_code, const std::string& CurlReadBuffer);
|
||||
const std::string getEndPoint(ES& es);
|
||||
const std::string generateIndexName(const fc::time_point_sec& block_date, const std::string& _elasticsearch_index_prefix);
|
||||
const std::string doCurl(CurlRequest& curl);
|
||||
const std::string joinBulkLines(const std::vector<std::string>& bulk);
|
||||
long getResponseCode(CURL *handler);
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
# Doxyfile 1.8.9.1
|
||||
# Doxyfile 1.8.17
|
||||
|
||||
# This file describes the settings to be used by the documentation system
|
||||
# doxygen (www.doxygen.org) for a project.
|
||||
|
|
@ -17,11 +17,11 @@
|
|||
# Project related configuration options
|
||||
#---------------------------------------------------------------------------
|
||||
|
||||
# This tag specifies the encoding used for all characters in the config file
|
||||
# that follow. The default is UTF-8 which is also the encoding used for all text
|
||||
# before the first occurrence of this tag. Doxygen uses libiconv (or the iconv
|
||||
# built into libc) for the transcoding. See http://www.gnu.org/software/libiconv
|
||||
# for the list of possible encodings.
|
||||
# This tag specifies the encoding used for all characters in the configuration
|
||||
# file that follow. The default is UTF-8 which is also the encoding used for all
|
||||
# text before the first occurrence of this tag. Doxygen uses libiconv (or the
|
||||
# iconv built into libc) for the transcoding. See
|
||||
# https://www.gnu.org/software/libiconv/ for the list of possible encodings.
|
||||
# The default value is: UTF-8.
|
||||
|
||||
DOXYFILE_ENCODING = UTF-8
|
||||
|
|
@ -93,6 +93,14 @@ ALLOW_UNICODE_NAMES = NO
|
|||
|
||||
OUTPUT_LANGUAGE = English
|
||||
|
||||
# The OUTPUT_TEXT_DIRECTION tag is used to specify the direction in which all
|
||||
# documentation generated by doxygen is written. Doxygen will use this
|
||||
# information to generate all generated output in the proper direction.
|
||||
# Possible values are: None, LTR, RTL and Context.
|
||||
# The default value is: None.
|
||||
|
||||
OUTPUT_TEXT_DIRECTION = None
|
||||
|
||||
# If the BRIEF_MEMBER_DESC tag is set to YES, doxygen will include brief member
|
||||
# descriptions after the members that are listed in the file and class
|
||||
# documentation (similar to Javadoc). Set to NO to disable this.
|
||||
|
|
@ -179,6 +187,16 @@ SHORT_NAMES = NO
|
|||
|
||||
JAVADOC_AUTOBRIEF = NO
|
||||
|
||||
# If the JAVADOC_BANNER tag is set to YES then doxygen will interpret a line
|
||||
# such as
|
||||
# /***************
|
||||
# as being the beginning of a Javadoc-style comment "banner". If set to NO, the
|
||||
# Javadoc-style will behave just like regular comments and it will not be
|
||||
# interpreted by doxygen.
|
||||
# The default value is: NO.
|
||||
|
||||
JAVADOC_BANNER = NO
|
||||
|
||||
# If the QT_AUTOBRIEF tag is set to YES then doxygen will interpret the first
|
||||
# line (until the first dot) of a Qt-style comment as the brief description. If
|
||||
# set to NO, the Qt-style will behave just like regular Qt-style comments (thus
|
||||
|
|
@ -226,7 +244,12 @@ TAB_SIZE = 4
|
|||
# will allow you to put the command \sideeffect (or @sideeffect) in the
|
||||
# documentation, which will result in a user-defined paragraph with heading
|
||||
# "Side Effects:". You can put \n's in the value part of an alias to insert
|
||||
# newlines.
|
||||
# newlines (in the resulting output). You can put ^^ in the value part of an
|
||||
# alias to insert a newline as if a physical newline was in the original file.
|
||||
# When you need a literal { or } or , in the value part of an alias you have to
|
||||
# escape them by means of a backslash (\), this can lead to conflicts with the
|
||||
# commands \{ and \} for these it is advised to use the version @{ and @} or use
|
||||
# a double escape (\\{ and \\})
|
||||
|
||||
ALIASES =
|
||||
|
||||
|
|
@ -264,17 +287,26 @@ OPTIMIZE_FOR_FORTRAN = NO
|
|||
|
||||
OPTIMIZE_OUTPUT_VHDL = NO
|
||||
|
||||
# Set the OPTIMIZE_OUTPUT_SLICE tag to YES if your project consists of Slice
|
||||
# sources only. Doxygen will then generate output that is more tailored for that
|
||||
# language. For instance, namespaces will be presented as modules, types will be
|
||||
# separated into more groups, etc.
|
||||
# The default value is: NO.
|
||||
|
||||
OPTIMIZE_OUTPUT_SLICE = NO
|
||||
|
||||
# Doxygen selects the parser to use depending on the extension of the files it
|
||||
# parses. With this tag you can assign which parser to use for a given
|
||||
# extension. Doxygen has a built-in mapping, but you can override or extend it
|
||||
# using this tag. The format is ext=language, where ext is a file extension, and
|
||||
# language is one of the parsers supported by doxygen: IDL, Java, Javascript,
|
||||
# C#, C, C++, D, PHP, Objective-C, Python, Fortran (fixed format Fortran:
|
||||
# FortranFixed, free formatted Fortran: FortranFree, unknown formatted Fortran:
|
||||
# Fortran. In the later case the parser tries to guess whether the code is fixed
|
||||
# or free formatted code, this is the default for Fortran type files), VHDL. For
|
||||
# instance to make doxygen treat .inc files as Fortran files (default is PHP),
|
||||
# and .f files as C (default is Fortran), use: inc=Fortran f=C.
|
||||
# language is one of the parsers supported by doxygen: IDL, Java, JavaScript,
|
||||
# Csharp (C#), C, C++, D, PHP, md (Markdown), Objective-C, Python, Slice,
|
||||
# Fortran (fixed format Fortran: FortranFixed, free formatted Fortran:
|
||||
# FortranFree, unknown formatted Fortran: Fortran. In the later case the parser
|
||||
# tries to guess whether the code is fixed or free formatted code, this is the
|
||||
# default for Fortran type files), VHDL, tcl. For instance to make doxygen treat
|
||||
# .inc files as Fortran files (default is PHP), and .f files as C (default is
|
||||
# Fortran), use: inc=Fortran f=C.
|
||||
#
|
||||
# Note: For files without extension you can use no_extension as a placeholder.
|
||||
#
|
||||
|
|
@ -285,7 +317,7 @@ EXTENSION_MAPPING =
|
|||
|
||||
# If the MARKDOWN_SUPPORT tag is enabled then doxygen pre-processes all comments
|
||||
# according to the Markdown format, which allows for more readable
|
||||
# documentation. See http://daringfireball.net/projects/markdown/ for details.
|
||||
# documentation. See https://daringfireball.net/projects/markdown/ for details.
|
||||
# The output of markdown processing is further processed by doxygen, so you can
|
||||
# mix doxygen, HTML, and XML commands with Markdown formatting. Disable only in
|
||||
# case of backward compatibilities issues.
|
||||
|
|
@ -293,6 +325,15 @@ EXTENSION_MAPPING =
|
|||
|
||||
MARKDOWN_SUPPORT = YES
|
||||
|
||||
# When the TOC_INCLUDE_HEADINGS tag is set to a non-zero value, all headings up
|
||||
# to that level are automatically included in the table of contents, even if
|
||||
# they do not have an id attribute.
|
||||
# Note: This feature currently applies only to Markdown headings.
|
||||
# Minimum value: 0, maximum value: 99, default value: 5.
|
||||
# This tag requires that the tag MARKDOWN_SUPPORT is set to YES.
|
||||
|
||||
TOC_INCLUDE_HEADINGS = 5
|
||||
|
||||
# When enabled doxygen tries to link words that correspond to documented
|
||||
# classes, or namespaces to their corresponding documentation. Such a link can
|
||||
# be prevented in individual cases by putting a % sign in front of the word or
|
||||
|
|
@ -318,7 +359,7 @@ BUILTIN_STL_SUPPORT = NO
|
|||
CPP_CLI_SUPPORT = NO
|
||||
|
||||
# Set the SIP_SUPPORT tag to YES if your project consists of sip (see:
|
||||
# http://www.riverbankcomputing.co.uk/software/sip/intro) sources only. Doxygen
|
||||
# https://www.riverbankcomputing.com/software/sip/intro) sources only. Doxygen
|
||||
# will parse them like normal C++ but will assume all classes use public instead
|
||||
# of private inheritance when no explicit protection keyword is present.
|
||||
# The default value is: NO.
|
||||
|
|
@ -343,6 +384,13 @@ IDL_PROPERTY_SUPPORT = YES
|
|||
|
||||
DISTRIBUTE_GROUP_DOC = NO
|
||||
|
||||
# If one adds a struct or class to a group and this option is enabled, then also
|
||||
# any nested class or struct is added to the same group. By default this option
|
||||
# is disabled and one has to add nested compounds explicitly via \ingroup.
|
||||
# The default value is: NO.
|
||||
|
||||
GROUP_NESTED_COMPOUNDS = NO
|
||||
|
||||
# Set the SUBGROUPING tag to YES to allow class member groups of the same type
|
||||
# (for instance a group of public functions) to be put as a subgroup of that
|
||||
# type (e.g. under the Public Functions section). Set it to NO to prevent
|
||||
|
|
@ -417,6 +465,12 @@ EXTRACT_ALL = YES
|
|||
|
||||
EXTRACT_PRIVATE = NO
|
||||
|
||||
# If the EXTRACT_PRIV_VIRTUAL tag is set to YES, documented private virtual
|
||||
# methods of a class will be included in the documentation.
|
||||
# The default value is: NO.
|
||||
|
||||
EXTRACT_PRIV_VIRTUAL = NO
|
||||
|
||||
# If the EXTRACT_PACKAGE tag is set to YES, all members with package or internal
|
||||
# scope will be included in the documentation.
|
||||
# The default value is: NO.
|
||||
|
|
@ -471,8 +525,8 @@ HIDE_UNDOC_MEMBERS = NO
|
|||
HIDE_UNDOC_CLASSES = NO
|
||||
|
||||
# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, doxygen will hide all friend
|
||||
# (class|struct|union) declarations. If set to NO, these declarations will be
|
||||
# included in the documentation.
|
||||
# declarations. If set to NO, these declarations will be included in the
|
||||
# documentation.
|
||||
# The default value is: NO.
|
||||
|
||||
HIDE_FRIEND_COMPOUNDS = NO
|
||||
|
|
@ -495,7 +549,7 @@ INTERNAL_DOCS = NO
|
|||
# names in lower-case letters. If set to YES, upper-case letters are also
|
||||
# allowed. This is useful if you have classes or files whose names only differ
|
||||
# in case and if your file system supports case sensitive file names. Windows
|
||||
# and Mac users are advised to set this option to NO.
|
||||
# (including Cygwin) ands Mac users are advised to set this option to NO.
|
||||
# The default value is: system dependent.
|
||||
|
||||
CASE_SENSE_NAMES = NO
|
||||
|
|
@ -682,7 +736,7 @@ LAYOUT_FILE =
|
|||
# The CITE_BIB_FILES tag can be used to specify one or more bib files containing
|
||||
# the reference definitions. This must be a list of .bib files. The .bib
|
||||
# extension is automatically appended if omitted. This requires the bibtex tool
|
||||
# to be installed. See also http://en.wikipedia.org/wiki/BibTeX for more info.
|
||||
# to be installed. See also https://en.wikipedia.org/wiki/BibTeX for more info.
|
||||
# For LaTeX the style of the bibliography can be controlled using
|
||||
# LATEX_BIB_STYLE. To use this feature you need bibtex and perl available in the
|
||||
# search path. See also \cite for info how to create references.
|
||||
|
|
@ -727,11 +781,18 @@ WARN_IF_DOC_ERROR = YES
|
|||
# This WARN_NO_PARAMDOC option can be enabled to get warnings for functions that
|
||||
# are documented, but have no documentation for their parameters or return
|
||||
# value. If set to NO, doxygen will only warn about wrong or incomplete
|
||||
# parameter documentation, but not about the absence of documentation.
|
||||
# parameter documentation, but not about the absence of documentation. If
|
||||
# EXTRACT_ALL is set to YES then this flag will automatically be disabled.
|
||||
# The default value is: NO.
|
||||
|
||||
WARN_NO_PARAMDOC = NO
|
||||
|
||||
# If the WARN_AS_ERROR tag is set to YES then doxygen will immediately stop when
|
||||
# a warning is encountered.
|
||||
# The default value is: NO.
|
||||
|
||||
WARN_AS_ERROR = NO
|
||||
|
||||
# The WARN_FORMAT tag determines the format of the warning messages that doxygen
|
||||
# can produce. The string should contain the $file, $line, and $text tags, which
|
||||
# will be replaced by the file and line number from which the warning originated
|
||||
|
|
@ -755,7 +816,7 @@ WARN_LOGFILE =
|
|||
# The INPUT tag is used to specify the files and/or directories that contain
|
||||
# documented source files. You may enter file names like myfile.cpp or
|
||||
# directories like /usr/src/myproject. Separate the files or directories with
|
||||
# spaces.
|
||||
# spaces. See also FILE_PATTERNS and EXTENSION_MAPPING
|
||||
# Note: If this tag is empty the current directory is searched.
|
||||
|
||||
INPUT = ${CMAKE_CURRENT_SOURCE_DIR}/include/graphene/wallet/wallet.hpp
|
||||
|
|
@ -763,7 +824,7 @@ INPUT = ${CMAKE_CURRENT_SOURCE_DIR}/include/graphene/wallet/wal
|
|||
# This tag can be used to specify the character encoding of the source files
|
||||
# that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses
|
||||
# libiconv (or the iconv built into libc) for the transcoding. See the libiconv
|
||||
# documentation (see: http://www.gnu.org/software/libiconv) for the list of
|
||||
# documentation (see: https://www.gnu.org/software/libiconv/) for the list of
|
||||
# possible encodings.
|
||||
# The default value is: UTF-8.
|
||||
|
||||
|
|
@ -771,12 +832,19 @@ INPUT_ENCODING = UTF-8
|
|||
|
||||
# If the value of the INPUT tag contains directories, you can use the
|
||||
# FILE_PATTERNS tag to specify one or more wildcard patterns (like *.cpp and
|
||||
# *.h) to filter out the source-files in the directories. If left blank the
|
||||
# following patterns are tested:*.c, *.cc, *.cxx, *.cpp, *.c++, *.java, *.ii,
|
||||
# *.ixx, *.ipp, *.i++, *.inl, *.idl, *.ddl, *.odl, *.h, *.hh, *.hxx, *.hpp,
|
||||
# *.h++, *.cs, *.d, *.php, *.php4, *.php5, *.phtml, *.inc, *.m, *.markdown,
|
||||
# *.md, *.mm, *.dox, *.py, *.f90, *.f, *.for, *.tcl, *.vhd, *.vhdl, *.ucf,
|
||||
# *.qsf, *.as and *.js.
|
||||
# *.h) to filter out the source-files in the directories.
|
||||
#
|
||||
# Note that for custom extensions or not directly supported extensions you also
|
||||
# need to set EXTENSION_MAPPING for the extension otherwise the files are not
|
||||
# read by doxygen.
|
||||
#
|
||||
# If left blank the following patterns are tested:*.c, *.cc, *.cxx, *.cpp,
|
||||
# *.c++, *.java, *.ii, *.ixx, *.ipp, *.i++, *.inl, *.idl, *.ddl, *.odl, *.h,
|
||||
# *.hh, *.hxx, *.hpp, *.h++, *.cs, *.d, *.php, *.php4, *.php5, *.phtml, *.inc,
|
||||
# *.m, *.markdown, *.md, *.mm, *.dox (to be provided as doxygen C comment),
|
||||
# *.doc (to be provided as doxygen C comment), *.txt (to be provided as doxygen
|
||||
# C comment), *.py, *.pyw, *.f90, *.f95, *.f03, *.f08, *.f, *.for, *.tcl, *.vhd,
|
||||
# *.vhdl, *.ucf, *.qsf and *.ice.
|
||||
|
||||
FILE_PATTERNS =
|
||||
|
||||
|
|
@ -862,6 +930,10 @@ IMAGE_PATH =
|
|||
# Note that the filter must not add or remove lines; it is applied before the
|
||||
# code is scanned, but not when the output code is generated. If lines are added
|
||||
# or removed, the anchors will not be placed correctly.
|
||||
#
|
||||
# Note that for custom extensions or not directly supported extensions you also
|
||||
# need to set EXTENSION_MAPPING for the extension otherwise the files are not
|
||||
# properly processed by doxygen.
|
||||
|
||||
INPUT_FILTER =
|
||||
|
||||
|
|
@ -871,6 +943,10 @@ INPUT_FILTER =
|
|||
# (like *.cpp=my_cpp_filter). See INPUT_FILTER for further information on how
|
||||
# filters are used. If the FILTER_PATTERNS tag is empty or if none of the
|
||||
# patterns match the file name, INPUT_FILTER is applied.
|
||||
#
|
||||
# Note that for custom extensions or not directly supported extensions you also
|
||||
# need to set EXTENSION_MAPPING for the extension otherwise the files are not
|
||||
# properly processed by doxygen.
|
||||
|
||||
FILTER_PATTERNS =
|
||||
|
||||
|
|
@ -923,7 +999,7 @@ INLINE_SOURCES = NO
|
|||
STRIP_CODE_COMMENTS = YES
|
||||
|
||||
# If the REFERENCED_BY_RELATION tag is set to YES then for each documented
|
||||
# function all documented functions referencing it will be listed.
|
||||
# entity all documented functions referencing it will be listed.
|
||||
# The default value is: NO.
|
||||
|
||||
REFERENCED_BY_RELATION = NO
|
||||
|
|
@ -955,12 +1031,12 @@ SOURCE_TOOLTIPS = YES
|
|||
# If the USE_HTAGS tag is set to YES then the references to source code will
|
||||
# point to the HTML generated by the htags(1) tool instead of doxygen built-in
|
||||
# source browser. The htags tool is part of GNU's global source tagging system
|
||||
# (see http://www.gnu.org/software/global/global.html). You will need version
|
||||
# (see https://www.gnu.org/software/global/global.html). You will need version
|
||||
# 4.8.6 or higher.
|
||||
#
|
||||
# To use it do the following:
|
||||
# - Install the latest version of global
|
||||
# - Enable SOURCE_BROWSER and USE_HTAGS in the config file
|
||||
# - Enable SOURCE_BROWSER and USE_HTAGS in the configuration file
|
||||
# - Make sure the INPUT points to the root of the source tree
|
||||
# - Run doxygen as normal
|
||||
#
|
||||
|
|
@ -982,6 +1058,35 @@ USE_HTAGS = NO
|
|||
|
||||
VERBATIM_HEADERS = YES
|
||||
|
||||
# If the CLANG_ASSISTED_PARSING tag is set to YES then doxygen will use the
|
||||
# clang parser (see: http://clang.llvm.org/) for more accurate parsing at the
|
||||
# cost of reduced performance. This can be particularly helpful with template
|
||||
# rich C++ code for which doxygen's built-in parser lacks the necessary type
|
||||
# information.
|
||||
# Note: The availability of this option depends on whether or not doxygen was
|
||||
# generated with the -Duse_libclang=ON option for CMake.
|
||||
# The default value is: NO.
|
||||
|
||||
CLANG_ASSISTED_PARSING = NO
|
||||
|
||||
# If clang assisted parsing is enabled you can provide the compiler with command
|
||||
# line options that you would normally use when invoking the compiler. Note that
|
||||
# the include paths will already be set by doxygen for the files and directories
|
||||
# specified with INPUT and INCLUDE_PATH.
|
||||
# This tag requires that the tag CLANG_ASSISTED_PARSING is set to YES.
|
||||
|
||||
CLANG_OPTIONS =
|
||||
|
||||
# If clang assisted parsing is enabled you can provide the clang parser with the
|
||||
# path to the compilation database (see:
|
||||
# http://clang.llvm.org/docs/HowToSetupToolingForLLVM.html) used when the files
|
||||
# were built. This is equivalent to specifying the "-p" option to a clang tool,
|
||||
# such as clang-check. These options will then be passed to the parser.
|
||||
# Note: The availability of this option depends on whether or not doxygen was
|
||||
# generated with the -Duse_libclang=ON option for CMake.
|
||||
|
||||
CLANG_DATABASE_PATH =
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
# Configuration options related to the alphabetical class index
|
||||
#---------------------------------------------------------------------------
|
||||
|
|
@ -1100,7 +1205,7 @@ HTML_EXTRA_FILES =
|
|||
# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. Doxygen
|
||||
# will adjust the colors in the style sheet and background images according to
|
||||
# this color. Hue is specified as an angle on a colorwheel, see
|
||||
# http://en.wikipedia.org/wiki/Hue for more information. For instance the value
|
||||
# https://en.wikipedia.org/wiki/Hue for more information. For instance the value
|
||||
# 0 represents red, 60 is yellow, 120 is green, 180 is cyan, 240 is blue, 300
|
||||
# purple, and 360 is red again.
|
||||
# Minimum value: 0, maximum value: 359, default value: 220.
|
||||
|
|
@ -1129,12 +1234,24 @@ HTML_COLORSTYLE_GAMMA = 80
|
|||
|
||||
# If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML
|
||||
# page will contain the date and time when the page was generated. Setting this
|
||||
# to NO can help when comparing the output of multiple runs.
|
||||
# The default value is: YES.
|
||||
# to YES can help to show when doxygen was last run and thus if the
|
||||
# documentation is up to date.
|
||||
# The default value is: NO.
|
||||
# This tag requires that the tag GENERATE_HTML is set to YES.
|
||||
|
||||
HTML_TIMESTAMP = YES
|
||||
|
||||
# If the HTML_DYNAMIC_MENUS tag is set to YES then the generated HTML
|
||||
# documentation will contain a main index with vertical navigation menus that
|
||||
# are dynamically created via JavaScript. If disabled, the navigation index will
|
||||
# consists of multiple levels of tabs that are statically embedded in every HTML
|
||||
# page. Disable this option to support browsers that do not have JavaScript,
|
||||
# like the Qt help browser.
|
||||
# The default value is: YES.
|
||||
# This tag requires that the tag GENERATE_HTML is set to YES.
|
||||
|
||||
HTML_DYNAMIC_MENUS = YES
|
||||
|
||||
# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML
|
||||
# documentation will contain sections that can be hidden and shown after the
|
||||
# page has loaded.
|
||||
|
|
@ -1158,13 +1275,13 @@ HTML_INDEX_NUM_ENTRIES = 100
|
|||
|
||||
# If the GENERATE_DOCSET tag is set to YES, additional index files will be
|
||||
# generated that can be used as input for Apple's Xcode 3 integrated development
|
||||
# environment (see: http://developer.apple.com/tools/xcode/), introduced with
|
||||
# OSX 10.5 (Leopard). To create a documentation set, doxygen will generate a
|
||||
# environment (see: https://developer.apple.com/xcode/), introduced with OSX
|
||||
# 10.5 (Leopard). To create a documentation set, doxygen will generate a
|
||||
# Makefile in the HTML output directory. Running make will produce the docset in
|
||||
# that directory and running make install will install the docset in
|
||||
# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find it at
|
||||
# startup. See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html
|
||||
# for more information.
|
||||
# startup. See https://developer.apple.com/library/archive/featuredarticles/Doxy
|
||||
# genXcode/_index.html for more information.
|
||||
# The default value is: NO.
|
||||
# This tag requires that the tag GENERATE_HTML is set to YES.
|
||||
|
||||
|
|
@ -1203,7 +1320,7 @@ DOCSET_PUBLISHER_NAME = Publisher
|
|||
# If the GENERATE_HTMLHELP tag is set to YES then doxygen generates three
|
||||
# additional HTML index files: index.hhp, index.hhc, and index.hhk. The
|
||||
# index.hhp is a project file that can be read by Microsoft's HTML Help Workshop
|
||||
# (see: http://www.microsoft.com/en-us/download/details.aspx?id=21138) on
|
||||
# (see: https://www.microsoft.com/en-us/download/details.aspx?id=21138) on
|
||||
# Windows.
|
||||
#
|
||||
# The HTML Help Workshop contains a compiler that can convert all HTML output
|
||||
|
|
@ -1279,7 +1396,7 @@ QCH_FILE =
|
|||
|
||||
# The QHP_NAMESPACE tag specifies the namespace to use when generating Qt Help
|
||||
# Project output. For more information please see Qt Help Project / Namespace
|
||||
# (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#namespace).
|
||||
# (see: https://doc.qt.io/archives/qt-4.8/qthelpproject.html#namespace).
|
||||
# The default value is: org.doxygen.Project.
|
||||
# This tag requires that the tag GENERATE_QHP is set to YES.
|
||||
|
||||
|
|
@ -1287,7 +1404,7 @@ QHP_NAMESPACE = org.doxygen.Project
|
|||
|
||||
# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating Qt
|
||||
# Help Project output. For more information please see Qt Help Project / Virtual
|
||||
# Folders (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#virtual-
|
||||
# Folders (see: https://doc.qt.io/archives/qt-4.8/qthelpproject.html#virtual-
|
||||
# folders).
|
||||
# The default value is: doc.
|
||||
# This tag requires that the tag GENERATE_QHP is set to YES.
|
||||
|
|
@ -1296,7 +1413,7 @@ QHP_VIRTUAL_FOLDER = doc
|
|||
|
||||
# If the QHP_CUST_FILTER_NAME tag is set, it specifies the name of a custom
|
||||
# filter to add. For more information please see Qt Help Project / Custom
|
||||
# Filters (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#custom-
|
||||
# Filters (see: https://doc.qt.io/archives/qt-4.8/qthelpproject.html#custom-
|
||||
# filters).
|
||||
# This tag requires that the tag GENERATE_QHP is set to YES.
|
||||
|
||||
|
|
@ -1304,7 +1421,7 @@ QHP_CUST_FILTER_NAME =
|
|||
|
||||
# The QHP_CUST_FILTER_ATTRS tag specifies the list of the attributes of the
|
||||
# custom filter to add. For more information please see Qt Help Project / Custom
|
||||
# Filters (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#custom-
|
||||
# Filters (see: https://doc.qt.io/archives/qt-4.8/qthelpproject.html#custom-
|
||||
# filters).
|
||||
# This tag requires that the tag GENERATE_QHP is set to YES.
|
||||
|
||||
|
|
@ -1312,7 +1429,7 @@ QHP_CUST_FILTER_ATTRS =
|
|||
|
||||
# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this
|
||||
# project's filter section matches. Qt Help Project / Filter Attributes (see:
|
||||
# http://qt-project.org/doc/qt-4.8/qthelpproject.html#filter-attributes).
|
||||
# https://doc.qt.io/archives/qt-4.8/qthelpproject.html#filter-attributes).
|
||||
# This tag requires that the tag GENERATE_QHP is set to YES.
|
||||
|
||||
QHP_SECT_FILTER_ATTRS =
|
||||
|
|
@ -1405,7 +1522,7 @@ EXT_LINKS_IN_WINDOW = NO
|
|||
|
||||
FORMULA_FONTSIZE = 10
|
||||
|
||||
# Use the FORMULA_TRANPARENT tag to determine whether or not the images
|
||||
# Use the FORMULA_TRANSPARENT tag to determine whether or not the images
|
||||
# generated for formulas are transparent PNGs. Transparent PNGs are not
|
||||
# supported properly for IE 6.0, but are supported on all modern browsers.
|
||||
#
|
||||
|
|
@ -1416,8 +1533,14 @@ FORMULA_FONTSIZE = 10
|
|||
|
||||
FORMULA_TRANSPARENT = YES
|
||||
|
||||
# The FORMULA_MACROFILE can contain LaTeX \newcommand and \renewcommand commands
|
||||
# to create new LaTeX commands to be used in formulas as building blocks. See
|
||||
# the section "Including formulas" for details.
|
||||
|
||||
FORMULA_MACROFILE =
|
||||
|
||||
# Enable the USE_MATHJAX option to render LaTeX formulas using MathJax (see
|
||||
# http://www.mathjax.org) which uses client side Javascript for the rendering
|
||||
# https://www.mathjax.org) which uses client side JavaScript for the rendering
|
||||
# instead of using pre-rendered bitmaps. Use this if you do not have LaTeX
|
||||
# installed or if you want to formulas look prettier in the HTML output. When
|
||||
# enabled you may also need to install MathJax separately and configure the path
|
||||
|
|
@ -1444,8 +1567,8 @@ MATHJAX_FORMAT = HTML-CSS
|
|||
# MATHJAX_RELPATH should be ../mathjax. The default value points to the MathJax
|
||||
# Content Delivery Network so you can quickly see the result without installing
|
||||
# MathJax. However, it is strongly recommended to install a local copy of
|
||||
# MathJax from http://www.mathjax.org before deployment.
|
||||
# The default value is: http://cdn.mathjax.org/mathjax/latest.
|
||||
# MathJax from https://www.mathjax.org before deployment.
|
||||
# The default value is: https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.5/.
|
||||
# This tag requires that the tag USE_MATHJAX is set to YES.
|
||||
|
||||
MATHJAX_RELPATH = http://cdn.mathjax.org/mathjax/latest
|
||||
|
|
@ -1487,7 +1610,7 @@ MATHJAX_CODEFILE =
|
|||
SEARCHENGINE = YES
|
||||
|
||||
# When the SERVER_BASED_SEARCH tag is enabled the search engine will be
|
||||
# implemented using a web server instead of a web client using Javascript. There
|
||||
# implemented using a web server instead of a web client using JavaScript. There
|
||||
# are two flavors of web server based searching depending on the EXTERNAL_SEARCH
|
||||
# setting. When disabled, doxygen will generate a PHP script for searching and
|
||||
# an index file used by the script. When EXTERNAL_SEARCH is enabled the indexing
|
||||
|
|
@ -1506,7 +1629,7 @@ SERVER_BASED_SEARCH = NO
|
|||
#
|
||||
# Doxygen ships with an example indexer (doxyindexer) and search engine
|
||||
# (doxysearch.cgi) which are based on the open source search engine library
|
||||
# Xapian (see: http://xapian.org/).
|
||||
# Xapian (see: https://xapian.org/).
|
||||
#
|
||||
# See the section "External Indexing and Searching" for details.
|
||||
# The default value is: NO.
|
||||
|
|
@ -1519,7 +1642,7 @@ EXTERNAL_SEARCH = NO
|
|||
#
|
||||
# Doxygen ships with an example indexer (doxyindexer) and search engine
|
||||
# (doxysearch.cgi) which are based on the open source search engine library
|
||||
# Xapian (see: http://xapian.org/). See the section "External Indexing and
|
||||
# Xapian (see: https://xapian.org/). See the section "External Indexing and
|
||||
# Searching" for details.
|
||||
# This tag requires that the tag SEARCHENGINE is set to YES.
|
||||
|
||||
|
|
@ -1571,21 +1694,35 @@ LATEX_OUTPUT = latex
|
|||
# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be
|
||||
# invoked.
|
||||
#
|
||||
# Note that when enabling USE_PDFLATEX this option is only used for generating
|
||||
# bitmaps for formulas in the HTML output, but not in the Makefile that is
|
||||
# written to the output directory.
|
||||
# The default file is: latex.
|
||||
# Note that when not enabling USE_PDFLATEX the default is latex when enabling
|
||||
# USE_PDFLATEX the default is pdflatex and when in the later case latex is
|
||||
# chosen this is overwritten by pdflatex. For specific output languages the
|
||||
# default can have been set differently, this depends on the implementation of
|
||||
# the output language.
|
||||
# This tag requires that the tag GENERATE_LATEX is set to YES.
|
||||
|
||||
LATEX_CMD_NAME = latex
|
||||
|
||||
# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to generate
|
||||
# index for LaTeX.
|
||||
# Note: This tag is used in the Makefile / make.bat.
|
||||
# See also: LATEX_MAKEINDEX_CMD for the part in the generated output file
|
||||
# (.tex).
|
||||
# The default file is: makeindex.
|
||||
# This tag requires that the tag GENERATE_LATEX is set to YES.
|
||||
|
||||
MAKEINDEX_CMD_NAME = makeindex
|
||||
|
||||
# The LATEX_MAKEINDEX_CMD tag can be used to specify the command name to
|
||||
# generate index for LaTeX. In case there is no backslash (\) as first character
|
||||
# it will be automatically added in the LaTeX code.
|
||||
# Note: This tag is used in the generated output file (.tex).
|
||||
# See also: MAKEINDEX_CMD_NAME for the part in the Makefile / make.bat.
|
||||
# The default value is: makeindex.
|
||||
# This tag requires that the tag GENERATE_LATEX is set to YES.
|
||||
|
||||
LATEX_MAKEINDEX_CMD = makeindex
|
||||
|
||||
# If the COMPACT_LATEX tag is set to YES, doxygen generates more compact LaTeX
|
||||
# documents. This may be useful for small projects and may help to save some
|
||||
# trees in general.
|
||||
|
|
@ -1604,9 +1741,12 @@ COMPACT_LATEX = NO
|
|||
PAPER_TYPE = a4
|
||||
|
||||
# The EXTRA_PACKAGES tag can be used to specify one or more LaTeX package names
|
||||
# that should be included in the LaTeX output. To get the times font for
|
||||
# instance you can specify
|
||||
# EXTRA_PACKAGES=times
|
||||
# that should be included in the LaTeX output. The package can be specified just
|
||||
# by its name or with the correct syntax as to be used with the LaTeX
|
||||
# \usepackage command. To get the times font for instance you can specify :
|
||||
# EXTRA_PACKAGES=times or EXTRA_PACKAGES={times}
|
||||
# To use the option intlimits with the amsmath package you can specify:
|
||||
# EXTRA_PACKAGES=[intlimits]{amsmath}
|
||||
# If left blank no extra packages will be included.
|
||||
# This tag requires that the tag GENERATE_LATEX is set to YES.
|
||||
|
||||
|
|
@ -1703,12 +1843,28 @@ LATEX_SOURCE_CODE = NO
|
|||
|
||||
# The LATEX_BIB_STYLE tag can be used to specify the style to use for the
|
||||
# bibliography, e.g. plainnat, or ieeetr. See
|
||||
# http://en.wikipedia.org/wiki/BibTeX and \cite for more info.
|
||||
# https://en.wikipedia.org/wiki/BibTeX and \cite for more info.
|
||||
# The default value is: plain.
|
||||
# This tag requires that the tag GENERATE_LATEX is set to YES.
|
||||
|
||||
LATEX_BIB_STYLE = plain
|
||||
|
||||
# If the LATEX_TIMESTAMP tag is set to YES then the footer of each generated
|
||||
# page will contain the date and time when the page was generated. Setting this
|
||||
# to NO can help when comparing the output of multiple runs.
|
||||
# The default value is: NO.
|
||||
# This tag requires that the tag GENERATE_LATEX is set to YES.
|
||||
|
||||
LATEX_TIMESTAMP = NO
|
||||
|
||||
# The LATEX_EMOJI_DIRECTORY tag is used to specify the (relative or absolute)
|
||||
# path from which the emoji images will be read. If a relative path is entered,
|
||||
# it will be relative to the LATEX_OUTPUT directory. If left blank the
|
||||
# LATEX_OUTPUT directory will be used.
|
||||
# This tag requires that the tag GENERATE_LATEX is set to YES.
|
||||
|
||||
LATEX_EMOJI_DIRECTORY =
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
# Configuration options related to the RTF output
|
||||
#---------------------------------------------------------------------------
|
||||
|
|
@ -1748,9 +1904,9 @@ COMPACT_RTF = NO
|
|||
|
||||
RTF_HYPERLINKS = NO
|
||||
|
||||
# Load stylesheet definitions from file. Syntax is similar to doxygen's config
|
||||
# file, i.e. a series of assignments. You only have to provide replacements,
|
||||
# missing definitions are set to their default value.
|
||||
# Load stylesheet definitions from file. Syntax is similar to doxygen's
|
||||
# configuration file, i.e. a series of assignments. You only have to provide
|
||||
# replacements, missing definitions are set to their default value.
|
||||
#
|
||||
# See also section "Doxygen usage" for information on how to generate the
|
||||
# default style sheet that doxygen normally uses.
|
||||
|
|
@ -1759,8 +1915,8 @@ RTF_HYPERLINKS = NO
|
|||
RTF_STYLESHEET_FILE =
|
||||
|
||||
# Set optional variables used in the generation of an RTF document. Syntax is
|
||||
# similar to doxygen's config file. A template extensions file can be generated
|
||||
# using doxygen -e rtf extensionFile.
|
||||
# similar to doxygen's configuration file. A template extensions file can be
|
||||
# generated using doxygen -e rtf extensionFile.
|
||||
# This tag requires that the tag GENERATE_RTF is set to YES.
|
||||
|
||||
RTF_EXTENSIONS_FILE =
|
||||
|
|
@ -1846,6 +2002,13 @@ XML_OUTPUT = xml
|
|||
|
||||
XML_PROGRAMLISTING = NO
|
||||
|
||||
# If the XML_NS_MEMB_FILE_SCOPE tag is set to YES, doxygen will include
|
||||
# namespace members in file scope as well, matching the HTML output.
|
||||
# The default value is: NO.
|
||||
# This tag requires that the tag GENERATE_XML is set to YES.
|
||||
|
||||
XML_NS_MEMB_FILE_SCOPE = NO
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
# Configuration options related to the DOCBOOK output
|
||||
#---------------------------------------------------------------------------
|
||||
|
|
@ -1878,9 +2041,9 @@ DOCBOOK_PROGRAMLISTING = NO
|
|||
#---------------------------------------------------------------------------
|
||||
|
||||
# If the GENERATE_AUTOGEN_DEF tag is set to YES, doxygen will generate an
|
||||
# AutoGen Definitions (see http://autogen.sf.net) file that captures the
|
||||
# structure of the code including all documentation. Note that this feature is
|
||||
# still experimental and incomplete at the moment.
|
||||
# AutoGen Definitions (see http://autogen.sourceforge.net/) file that captures
|
||||
# the structure of the code including all documentation. Note that this feature
|
||||
# is still experimental and incomplete at the moment.
|
||||
# The default value is: NO.
|
||||
|
||||
GENERATE_AUTOGEN_DEF = NO
|
||||
|
|
@ -2047,12 +2210,6 @@ EXTERNAL_GROUPS = YES
|
|||
|
||||
EXTERNAL_PAGES = YES
|
||||
|
||||
# The PERL_PATH should be the absolute path and name of the perl script
|
||||
# interpreter (i.e. the result of 'which perl').
|
||||
# The default file (with absolute path) is: /usr/bin/perl.
|
||||
|
||||
PERL_PATH = /usr/bin/perl
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
# Configuration options related to the dot tool
|
||||
#---------------------------------------------------------------------------
|
||||
|
|
@ -2066,15 +2223,6 @@ PERL_PATH = /usr/bin/perl
|
|||
|
||||
CLASS_DIAGRAMS = YES
|
||||
|
||||
# You can define message sequence charts within doxygen comments using the \msc
|
||||
# command. Doxygen will then run the mscgen tool (see:
|
||||
# http://www.mcternan.me.uk/mscgen/)) to produce the chart and insert it in the
|
||||
# documentation. The MSCGEN_PATH tag allows you to specify the directory where
|
||||
# the mscgen tool resides. If left empty the tool is assumed to be found in the
|
||||
# default search path.
|
||||
|
||||
MSCGEN_PATH =
|
||||
|
||||
# You can include diagrams made with dia in doxygen documentation. Doxygen will
|
||||
# then run dia to produce the diagram and insert it in the documentation. The
|
||||
# DIA_PATH tag allows you to specify the directory where the dia binary resides.
|
||||
|
|
@ -2093,7 +2241,7 @@ HIDE_UNDOC_RELATIONS = YES
|
|||
# http://www.graphviz.org/), a graph visualization toolkit from AT&T and Lucent
|
||||
# Bell Labs. The other options in this section have no effect if this option is
|
||||
# set to NO
|
||||
# The default value is: NO.
|
||||
# The default value is: YES.
|
||||
|
||||
HAVE_DOT = NO
|
||||
|
||||
|
|
@ -2207,7 +2355,8 @@ INCLUDED_BY_GRAPH = YES
|
|||
#
|
||||
# Note that enabling this option will significantly increase the time of a run.
|
||||
# So in most cases it will be better to enable call graphs for selected
|
||||
# functions only using the \callgraph command.
|
||||
# functions only using the \callgraph command. Disabling a call graph can be
|
||||
# accomplished by means of the command \hidecallgraph.
|
||||
# The default value is: NO.
|
||||
# This tag requires that the tag HAVE_DOT is set to YES.
|
||||
|
||||
|
|
@ -2218,7 +2367,8 @@ CALL_GRAPH = NO
|
|||
#
|
||||
# Note that enabling this option will significantly increase the time of a run.
|
||||
# So in most cases it will be better to enable caller graphs for selected
|
||||
# functions only using the \callergraph command.
|
||||
# functions only using the \callergraph command. Disabling a caller graph can be
|
||||
# accomplished by means of the command \hidecallergraph.
|
||||
# The default value is: NO.
|
||||
# This tag requires that the tag HAVE_DOT is set to YES.
|
||||
|
||||
|
|
@ -2241,11 +2391,17 @@ GRAPHICAL_HIERARCHY = YES
|
|||
DIRECTORY_GRAPH = YES
|
||||
|
||||
# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images
|
||||
# generated by dot.
|
||||
# generated by dot. For an explanation of the image formats see the section
|
||||
# output formats in the documentation of the dot tool (Graphviz (see:
|
||||
# http://www.graphviz.org/)).
|
||||
# Note: If you choose svg you need to set HTML_FILE_EXTENSION to xhtml in order
|
||||
# to make the SVG files visible in IE 9+ (other browsers do not have this
|
||||
# requirement).
|
||||
# Possible values are: png, jpg, gif and svg.
|
||||
# Possible values are: png, png:cairo, png:cairo:cairo, png:cairo:gd, png:gd,
|
||||
# png:gd:gd, jpg, jpg:cairo, jpg:cairo:gd, jpg:gd, jpg:gd:gd, gif, gif:cairo,
|
||||
# gif:cairo:gd, gif:gd, gif:gd:gd, svg, png:gd, png:gd:gd, png:cairo,
|
||||
# png:cairo:gd, png:cairo:cairo, png:cairo:gdiplus, png:gdiplus and
|
||||
# png:gdiplus:gdiplus.
|
||||
# The default value is: png.
|
||||
# This tag requires that the tag HAVE_DOT is set to YES.
|
||||
|
||||
|
|
@ -2296,6 +2452,11 @@ DIAFILE_DIRS =
|
|||
|
||||
PLANTUML_JAR_PATH =
|
||||
|
||||
# When using plantuml, the PLANTUML_CFG_FILE tag can be used to specify a
|
||||
# configuration file for plantuml.
|
||||
|
||||
PLANTUML_CFG_FILE =
|
||||
|
||||
# When using plantuml, the specified paths are searched for files specified by
|
||||
# the !include statement in a plantuml block.
|
||||
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
*
|
||||
|
|
@ -1765,6 +1786,55 @@ class wallet_api
|
|||
uint16_t desired_number_of_sons,
|
||||
bool broadcast = false);
|
||||
|
||||
|
||||
/** Broadcast signed transaction for manually sidechain deposit
|
||||
* @param son_name_or_id ID or name of the son account
|
||||
* @param sidechain Sidechain type (bitcoin, HIVE, etc)
|
||||
* @param transaction_id ID of transaction
|
||||
* @param operation_index Index of operation
|
||||
* @param sidechain_from Sidechain address transaction from
|
||||
* @param sidechain_to Sidechain address transaction to
|
||||
* @param sidechain_currency Sidechain currency
|
||||
* @param sidechain_amount Sidechain amount to deposit
|
||||
* @param peerplays_from_name_or_id ID or name of the account transaction from
|
||||
* @param peerplays_to_name_or_id ID or name of the account transaction to
|
||||
* @returns the signed transaction.
|
||||
*/
|
||||
signed_transaction sidechain_deposit_transaction( const string &son_name_or_id,
|
||||
const sidechain_type& sidechain,
|
||||
const string &transaction_id,
|
||||
uint32_t operation_index,
|
||||
const string &sidechain_from,
|
||||
const string &sidechain_to,
|
||||
const string &sidechain_currency,
|
||||
int64_t sidechain_amount,
|
||||
const string &peerplays_from_name_or_id,
|
||||
const string &peerplays_to_name_or_id);
|
||||
|
||||
/** Broadcast signed transaction for manually sidechain withdrawal
|
||||
* @param son_name_or_id ID or name of the son account
|
||||
* @param block_num Block number where original withdrawal transaction is executed
|
||||
* @param sidechain Sidechain type (bitcoin, HIVE, etc)
|
||||
* @param peerplays_uid peerplays_uid
|
||||
* @param peerplays_transaction_id ID of transaction
|
||||
* @param peerplays_from Sidechain address transaction from
|
||||
* @param withdraw_sidechain Withdraw sidechain
|
||||
* @param withdraw_address Withdraw address
|
||||
* @param withdraw_currency Withdraw currency
|
||||
* @param withdraw_amount Withdraw amount
|
||||
* @returns the signed transaction.
|
||||
*/
|
||||
signed_transaction sidechain_withdrawal_transaction(const string &son_name_or_id,
|
||||
uint32_t block_num,
|
||||
const sidechain_type& sidechain,
|
||||
const std::string &peerplays_uid,
|
||||
const std::string &peerplays_transaction_id,
|
||||
const chain::account_id_type &peerplays_from,
|
||||
const sidechain_type& withdraw_sidechain,
|
||||
const std::string &withdraw_address,
|
||||
const std::string &withdraw_currency,
|
||||
const string &withdraw_amount);
|
||||
|
||||
/** Vote for a given witness.
|
||||
*
|
||||
* An account can publish a list of all witnesses they approve of. This
|
||||
|
|
@ -2487,9 +2557,46 @@ class wallet_api
|
|||
bool broadcast = false,
|
||||
bool to_temp = false );
|
||||
|
||||
|
||||
std::map<string,std::function<string(fc::variant,const fc::variants&)>> get_result_formatters() const;
|
||||
|
||||
/**
|
||||
* @brief Get a list of vote_id_type that ID votes for
|
||||
* @param account_name_or_id ID or name of the account to get votes for
|
||||
* @return The list of vote_id_type ID votes for
|
||||
*
|
||||
*/
|
||||
vector<vote_id_type> get_votes_ids(const string &account_name_or_id) const;
|
||||
|
||||
/**
|
||||
* @brief Return the objects account_name_or_id votes for
|
||||
* @param account_name_or_id ID or name of the account to get votes for
|
||||
* @return The votes_info account_name_or_id votes for
|
||||
*
|
||||
*/
|
||||
votes_info get_votes(const string &account_name_or_id) const;
|
||||
|
||||
/**
|
||||
* @brief Get a list of accounts that votes for vote_id
|
||||
* @param vote_id We search accounts that vote for this ID
|
||||
* @return The accounts that votes for provided ID
|
||||
*
|
||||
*/
|
||||
vector<account_object> get_voters_by_id(const vote_id_type &vote_id) const;
|
||||
|
||||
/**
|
||||
* @brief Return the accounts that votes for account_name_or_id
|
||||
* @param account_name_or_id ID or name of the account to get voters for
|
||||
* @return The voters_info for account_name_or_id
|
||||
*
|
||||
*/
|
||||
voters_info get_voters(const string &account_name_or_id) const;
|
||||
|
||||
/**
|
||||
* @brief Demo plugin api
|
||||
* @return The hello world string
|
||||
*/
|
||||
std::map<sidechain_type, std::vector<std::string>> get_son_listener_log() const;
|
||||
|
||||
fc::signal<void(bool)> lock_changed;
|
||||
std::shared_ptr<detail::wallet_api_impl> my;
|
||||
void encrypt_keys();
|
||||
|
|
@ -2626,8 +2733,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)
|
||||
|
|
@ -2643,6 +2752,7 @@ FC_API( graphene::wallet::wallet_api,
|
|||
(get_son_wallets)
|
||||
(add_sidechain_address)
|
||||
(delete_sidechain_address)
|
||||
(sidechain_withdrawal_transaction)
|
||||
(get_sidechain_addresses_by_account)
|
||||
(get_sidechain_addresses_by_sidechain)
|
||||
(get_sidechain_address_by_account_and_sidechain)
|
||||
|
|
@ -2657,6 +2767,7 @@ FC_API( graphene::wallet::wallet_api,
|
|||
(vote_for_committee_member)
|
||||
(vote_for_son)
|
||||
(update_son_votes)
|
||||
(sidechain_deposit_transaction)
|
||||
(vote_for_witness)
|
||||
(update_witness_votes)
|
||||
(set_voting_proxy)
|
||||
|
|
@ -2795,4 +2906,9 @@ FC_API( graphene::wallet::wallet_api,
|
|||
(get_custom_account_authorities_by_permission_id)
|
||||
(get_custom_account_authorities_by_permission_name)
|
||||
(get_active_custom_account_authorities_by_operation)
|
||||
(get_votes_ids)
|
||||
(get_votes)
|
||||
(get_voters_by_id)
|
||||
(get_voters)
|
||||
(get_son_listener_log)
|
||||
)
|
||||
|
|
|
|||
|
|
@ -84,6 +84,7 @@
|
|||
#include <graphene/wallet/api_documentation.hpp>
|
||||
#include <graphene/wallet/reflect_util.hpp>
|
||||
#include <graphene/debug_witness/debug_api.hpp>
|
||||
#include <graphene/peerplays_sidechain/sidechain_api.hpp>
|
||||
|
||||
#ifndef WIN32
|
||||
# include <sys/types.h>
|
||||
|
|
@ -749,7 +750,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 +763,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;
|
||||
}
|
||||
}
|
||||
|
|
@ -1946,7 +1947,7 @@ public:
|
|||
try
|
||||
{
|
||||
account_id_type owner_account_id = get_account_id(owner_account);
|
||||
fc::optional<son_object> son = _remote_db->get_son_by_account(owner_account_id);
|
||||
fc::optional<son_object> son = _remote_db->get_son_by_account_id(owner_account_id);
|
||||
if (son)
|
||||
return *son;
|
||||
else
|
||||
|
|
@ -1961,6 +1962,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
|
||||
|
|
@ -2075,7 +2119,7 @@ public:
|
|||
son_create_op.pay_vb = pay_vb_id;
|
||||
son_create_op.sidechain_public_keys = sidechain_public_keys;
|
||||
|
||||
if (_remote_db->get_son_by_account(son_create_op.owner_account))
|
||||
if (_remote_db->get_son_by_account_id(son_create_op.owner_account))
|
||||
FC_THROW("Account ${owner_account} is already a SON", ("owner_account", owner_account));
|
||||
|
||||
signed_transaction tx;
|
||||
|
|
@ -2201,13 +2245,10 @@ public:
|
|||
std::vector<fc::optional<son_object>> son_objects = _remote_db->get_sons(son_ids);
|
||||
vector<std::string> owners;
|
||||
for(auto obj: son_objects)
|
||||
{
|
||||
if (obj)
|
||||
{
|
||||
std::string acc_id = account_id_to_string(obj->son_account);
|
||||
owners.push_back(acc_id);
|
||||
}
|
||||
}
|
||||
vector< optional< account_object> > accs = _remote_db->get_accounts(owners);
|
||||
std::remove_if(son_objects.begin(), son_objects.end(),
|
||||
[](const fc::optional<son_object>& obj) -> bool { return obj.valid(); });
|
||||
|
|
@ -2216,9 +2257,7 @@ public:
|
|||
std::inserter(result, result.end()),
|
||||
[](fc::optional<account_object>& acct, fc::optional<son_object> son) {
|
||||
FC_ASSERT(acct, "Invalid active SONs list in global properties.");
|
||||
if (son.valid() && son->status != son_status::deregistered)
|
||||
return std::make_pair<string, son_id_type>(string(acct->name), std::move(son->id));
|
||||
return std::make_pair<string, son_id_type>(string(acct->name), std::move(son_id_type()));
|
||||
});
|
||||
return result;
|
||||
} FC_CAPTURE_AND_RETHROW() }
|
||||
|
|
@ -2323,6 +2362,64 @@ public:
|
|||
|
||||
} FC_CAPTURE_AND_RETHROW() }
|
||||
|
||||
signed_transaction sidechain_withdrawal_transaction(const string &son_name_or_id,
|
||||
uint32_t block_num,
|
||||
const sidechain_type& sidechain,
|
||||
const std::string &peerplays_uid,
|
||||
const std::string &peerplays_transaction_id,
|
||||
const chain::account_id_type &peerplays_from,
|
||||
const sidechain_type& withdraw_sidechain,
|
||||
const std::string &withdraw_address,
|
||||
const std::string &withdraw_currency,
|
||||
const string &withdraw_amount)
|
||||
{ try{
|
||||
const global_property_object& gpo = get_global_properties();
|
||||
const auto dynamic_props = get_dynamic_global_properties();
|
||||
const auto son_obj = get_son(son_name_or_id);
|
||||
|
||||
fc::optional<asset_object> peerplays_asset = get_asset(withdraw_currency);
|
||||
FC_ASSERT(peerplays_asset, "Could not find asset matching ${asset}", ("asset", peerplays_asset));
|
||||
const auto asset_val = peerplays_asset->amount_from_string(withdraw_amount);
|
||||
const auto asset_price = peerplays_asset->options.core_exchange_rate;
|
||||
|
||||
price withdraw_currency_price = {};
|
||||
if ("BTC" == withdraw_currency) {
|
||||
fc::optional<asset_object> a = get_asset( gpo.parameters.btc_asset());
|
||||
withdraw_currency_price = a->options.core_exchange_rate;
|
||||
} else
|
||||
if ("HBD" == withdraw_currency) {
|
||||
fc::optional<asset_object> a = get_asset( gpo.parameters.hbd_asset());
|
||||
withdraw_currency_price = a->options.core_exchange_rate;
|
||||
} else
|
||||
if ("HIVE" == withdraw_currency) {
|
||||
fc::optional<asset_object> a = get_asset( gpo.parameters.hive_asset());
|
||||
withdraw_currency_price = a->options.core_exchange_rate;
|
||||
} else {
|
||||
FC_THROW("withdraw_currency ${withdraw_currency}", ("withdraw_currency", withdraw_currency));
|
||||
}
|
||||
|
||||
//! Create transaction
|
||||
signed_transaction son_wallet_withdraw_create_transaction;
|
||||
son_wallet_withdraw_create_operation op;
|
||||
op.payer = son_obj.son_account;
|
||||
op.son_id = son_obj.id;
|
||||
op.timestamp = dynamic_props.time;
|
||||
op.block_num = block_num;
|
||||
op.sidechain = sidechain;
|
||||
op.peerplays_uid = peerplays_uid;
|
||||
op.peerplays_transaction_id = peerplays_transaction_id;
|
||||
op.peerplays_from = peerplays_from;
|
||||
op.peerplays_asset = asset(asset_val.amount * asset_price.base.amount / asset_price.quote.amount);
|
||||
op.withdraw_sidechain = withdraw_sidechain;
|
||||
op.withdraw_address = withdraw_address;
|
||||
op.withdraw_currency = withdraw_currency;
|
||||
op.withdraw_amount = asset_val.amount;
|
||||
|
||||
son_wallet_withdraw_create_transaction.operations.push_back(op);
|
||||
|
||||
return sign_transaction(son_wallet_withdraw_create_transaction, true);
|
||||
} FC_CAPTURE_AND_RETHROW( (withdraw_currency) ) }
|
||||
|
||||
signed_transaction create_witness(string owner_account,
|
||||
string url,
|
||||
bool broadcast /* = false */)
|
||||
|
|
@ -2717,7 +2814,7 @@ public:
|
|||
|
||||
account_object voting_account_object = get_account(voting_account);
|
||||
account_id_type son_account_id = get_account_id(son);
|
||||
fc::optional<son_object> son_obj = _remote_db->get_son_by_account(son_account_id);
|
||||
fc::optional<son_object> son_obj = _remote_db->get_son_by_account_id(son_account_id);
|
||||
if (!son_obj)
|
||||
FC_THROW("Account ${son} is not registered as a son", ("son", son));
|
||||
if (approve)
|
||||
|
|
@ -2761,7 +2858,7 @@ public:
|
|||
for (const std::string& son : sons_to_approve)
|
||||
{
|
||||
account_id_type son_owner_account_id = get_account_id(son);
|
||||
fc::optional<son_object> son_obj = _remote_db->get_son_by_account(son_owner_account_id);
|
||||
fc::optional<son_object> son_obj = _remote_db->get_son_by_account_id(son_owner_account_id);
|
||||
if (!son_obj)
|
||||
FC_THROW("Account ${son} is not registered as a SON", ("son", son));
|
||||
auto insert_result = voting_account_object.options.votes.insert(son_obj->vote_id);
|
||||
|
|
@ -2771,7 +2868,7 @@ public:
|
|||
for (const std::string& son : sons_to_reject)
|
||||
{
|
||||
account_id_type son_owner_account_id = get_account_id(son);
|
||||
fc::optional<son_object> son_obj = _remote_db->get_son_by_account(son_owner_account_id);
|
||||
fc::optional<son_object> son_obj = _remote_db->get_son_by_account_id(son_owner_account_id);
|
||||
if (!son_obj)
|
||||
FC_THROW("Account ${son} is not registered as a SON", ("son", son));
|
||||
unsigned votes_removed = voting_account_object.options.votes.erase(son_obj->vote_id);
|
||||
|
|
@ -2792,6 +2889,81 @@ public:
|
|||
return sign_transaction( tx, broadcast );
|
||||
} FC_CAPTURE_AND_RETHROW( (voting_account)(sons_to_approve)(sons_to_reject)(desired_number_of_sons)(broadcast) ) }
|
||||
|
||||
signed_transaction sidechain_deposit_transaction( const string &son_name_or_id,
|
||||
const sidechain_type& sidechain,
|
||||
const string &transaction_id,
|
||||
uint32_t operation_index,
|
||||
const string &sidechain_from,
|
||||
const string &sidechain_to,
|
||||
const string &sidechain_currency,
|
||||
int64_t sidechain_amount,
|
||||
const string &peerplays_from_name_or_id,
|
||||
const string &peerplays_to_name_or_id )
|
||||
{
|
||||
//! Get data we need to procced transaction
|
||||
const auto dynamic_global_props = get_dynamic_global_properties();
|
||||
const auto global_props = get_global_properties();
|
||||
const auto son_obj = get_son(son_name_or_id);
|
||||
const std::string sidechain_str = [&sidechain](){
|
||||
switch (sidechain) {
|
||||
case sidechain_type::peerplays : return "peerplays";
|
||||
case sidechain_type::bitcoin : return "bitcoin";
|
||||
case sidechain_type::hive : return "hive";
|
||||
default:
|
||||
FC_THROW("Wrong sidechain type: ${sidechain}", ("sidechain", sidechain));
|
||||
}
|
||||
}();
|
||||
const auto peerplays_from_obj = get_account(peerplays_from_name_or_id);
|
||||
const auto peerplays_to_obj = get_account(peerplays_to_name_or_id);
|
||||
const price sidechain_currency_price = [this, &sidechain_currency, &global_props](){
|
||||
if(sidechain_currency == "BTC")
|
||||
{
|
||||
fc::optional<asset_object> asset_obj = get_asset(object_id_to_string(global_props.parameters.btc_asset()));
|
||||
FC_ASSERT(asset_obj, "Could not find asset matching ${asset}", ("asset", "BTC"));
|
||||
return asset_obj->options.core_exchange_rate;
|
||||
}
|
||||
else if(sidechain_currency == "HBD")
|
||||
{
|
||||
fc::optional<asset_object> asset_obj = get_asset(object_id_to_string(global_props.parameters.hbd_asset()));
|
||||
FC_ASSERT(asset_obj, "Could not find asset matching ${asset}", ("asset", "HBD"));
|
||||
return asset_obj->options.core_exchange_rate;
|
||||
}
|
||||
else if(sidechain_currency == "HIVE")
|
||||
{
|
||||
fc::optional<asset_object> asset_obj = get_asset(object_id_to_string(global_props.parameters.hive_asset()));
|
||||
FC_ASSERT(asset_obj, "Could not find asset matching ${asset}", ("asset", "HIVE"));
|
||||
return asset_obj->options.core_exchange_rate;
|
||||
}
|
||||
else
|
||||
{
|
||||
fc::optional<asset_object> asset_obj = get_asset(sidechain_currency);
|
||||
FC_ASSERT(asset_obj, "Could not find asset matching ${asset}", ("asset", sidechain_currency));
|
||||
return asset_obj->options.core_exchange_rate;
|
||||
}
|
||||
}();
|
||||
|
||||
//! Create transaction
|
||||
signed_transaction son_wallet_deposit_create_transaction;
|
||||
son_wallet_deposit_create_operation op;
|
||||
op.payer = son_obj.son_account;
|
||||
op.son_id = son_obj.id;
|
||||
op.timestamp = dynamic_global_props.time;
|
||||
op.block_num = dynamic_global_props.head_block_number;
|
||||
op.sidechain = sidechain;
|
||||
op.sidechain_uid = sidechain_str + "-" + transaction_id + "-" + std::to_string(operation_index);
|
||||
op.sidechain_transaction_id = transaction_id;
|
||||
op.sidechain_from = sidechain_from;
|
||||
op.sidechain_to = sidechain_to;
|
||||
op.sidechain_currency = sidechain_currency;
|
||||
op.sidechain_amount = sidechain_amount;
|
||||
op.peerplays_from = peerplays_from_obj.id;
|
||||
op.peerplays_to = peerplays_to_obj.id;
|
||||
op.peerplays_asset = asset(op.sidechain_amount * sidechain_currency_price.base.amount / sidechain_currency_price.quote.amount);
|
||||
son_wallet_deposit_create_transaction.operations.push_back(op);
|
||||
|
||||
return sign_transaction(son_wallet_deposit_create_transaction, true);
|
||||
}
|
||||
|
||||
signed_transaction vote_for_witness(string voting_account,
|
||||
string witness,
|
||||
bool approve,
|
||||
|
|
@ -4007,6 +4179,26 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
void use_sidechain_api()
|
||||
{
|
||||
if( _remote_sidechain )
|
||||
return;
|
||||
try
|
||||
{
|
||||
_remote_sidechain = _remote_api->sidechain();
|
||||
}
|
||||
catch( const fc::exception& e )
|
||||
{
|
||||
std::cerr << "\nCouldn't get sidechain API. You probably are not configured\n"
|
||||
"to access the sidechain API on the node you are connecting to.\n"
|
||||
"\n"
|
||||
"To fix this problem:\n"
|
||||
"- Please ensure peerplays_sidechain plugin is enabled.\n"
|
||||
"- Please follow the instructions in README.md to set up an apiaccess file.\n"
|
||||
"\n";
|
||||
}
|
||||
}
|
||||
|
||||
void network_add_nodes( const vector<string>& nodes )
|
||||
{
|
||||
use_network_node_api();
|
||||
|
|
@ -4087,6 +4279,52 @@ public:
|
|||
return it->second;
|
||||
}
|
||||
|
||||
vector<vote_id_type> get_votes_ids(const string &account_name_or_id) const
|
||||
{
|
||||
try
|
||||
{
|
||||
return _remote_db->get_votes_ids(account_name_or_id);
|
||||
}
|
||||
FC_CAPTURE_AND_RETHROW( (account_name_or_id) )
|
||||
}
|
||||
|
||||
votes_info get_votes(const string &account_name_or_id) const
|
||||
{
|
||||
try
|
||||
{
|
||||
return _remote_db->get_votes(account_name_or_id);
|
||||
}
|
||||
FC_CAPTURE_AND_RETHROW( (account_name_or_id) )
|
||||
}
|
||||
|
||||
vector<account_object> get_voters_by_id(const vote_id_type &vote_id) const
|
||||
{
|
||||
try
|
||||
{
|
||||
return _remote_db->get_voters_by_id(vote_id);
|
||||
}
|
||||
FC_CAPTURE_AND_RETHROW( (vote_id) )
|
||||
}
|
||||
|
||||
voters_info get_voters(const string &account_name_or_id) const
|
||||
{
|
||||
try
|
||||
{
|
||||
return _remote_db->get_voters(account_name_or_id);
|
||||
}
|
||||
FC_CAPTURE_AND_RETHROW( (account_name_or_id) )
|
||||
}
|
||||
|
||||
std::map<sidechain_type, std::vector<std::string>> get_son_listener_log()
|
||||
{
|
||||
use_sidechain_api();
|
||||
try
|
||||
{
|
||||
return (*_remote_sidechain)->get_son_listener_log();
|
||||
}
|
||||
FC_CAPTURE_AND_RETHROW()
|
||||
}
|
||||
|
||||
string _wallet_filename;
|
||||
wallet_data _wallet;
|
||||
|
||||
|
|
@ -4101,6 +4339,7 @@ public:
|
|||
fc::api<bookie_api> _remote_bookie;
|
||||
optional< fc::api<network_node_api> > _remote_net_node;
|
||||
optional< fc::api<graphene::debug_witness::debug_api> > _remote_debug;
|
||||
optional< fc::api<graphene::peerplays_sidechain::sidechain_api> > _remote_sidechain;
|
||||
|
||||
flat_map<string, operation> _prototype_ops;
|
||||
|
||||
|
|
@ -4184,6 +4423,8 @@ string operation_printer::operator()(const transfer_operation& op) const
|
|||
std::string memo;
|
||||
if( op.memo )
|
||||
{
|
||||
bool is_encrypted = ((op.memo->from != public_key_type()) && (op.memo->to != public_key_type()));
|
||||
if (is_encrypted) {
|
||||
if( wallet.is_locked() )
|
||||
{
|
||||
out << " -- Unlock wallet to see memo.";
|
||||
|
|
@ -4206,6 +4447,10 @@ string operation_printer::operator()(const transfer_operation& op) const
|
|||
elog("Error when decrypting memo: ${e}", ("e", e.to_detail_string()));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
memo = op.memo->get_message(private_key_type(), public_key_type());
|
||||
out << " -- Memo: " << memo;
|
||||
}
|
||||
}
|
||||
fee(op.fee);
|
||||
return memo;
|
||||
|
|
@ -4434,6 +4679,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)
|
||||
|
|
@ -4488,6 +4734,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;
|
||||
|
||||
|
|
@ -4663,7 +4911,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;
|
||||
}
|
||||
|
||||
|
|
@ -4686,7 +4934,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)
|
||||
|
|
@ -4705,7 +4953,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 );
|
||||
|
|
@ -4775,7 +5023,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;
|
||||
|
|
@ -4990,6 +5238,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);
|
||||
|
|
@ -5010,6 +5263,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,
|
||||
|
|
@ -5140,6 +5398,29 @@ signed_transaction wallet_api::delete_sidechain_address(string account,
|
|||
return my->delete_sidechain_address(account, sidechain, broadcast);
|
||||
}
|
||||
|
||||
signed_transaction wallet_api::sidechain_withdrawal_transaction(const string &son_name_or_id,
|
||||
uint32_t block_num,
|
||||
const sidechain_type& sidechain,
|
||||
const std::string &peerplays_uid,
|
||||
const std::string &peerplays_transaction_id,
|
||||
const chain::account_id_type &peerplays_from,
|
||||
const sidechain_type& withdraw_sidechain,
|
||||
const std::string &withdraw_address,
|
||||
const std::string &withdraw_currency,
|
||||
const string &withdraw_amount)
|
||||
{
|
||||
return my->sidechain_withdrawal_transaction(son_name_or_id,
|
||||
block_num,
|
||||
sidechain,
|
||||
peerplays_uid,
|
||||
peerplays_transaction_id,
|
||||
peerplays_from,
|
||||
withdraw_sidechain,
|
||||
withdraw_address,
|
||||
withdraw_currency,
|
||||
withdraw_amount);
|
||||
}
|
||||
|
||||
vector<optional<sidechain_address_object>> wallet_api::get_sidechain_addresses_by_account(string account)
|
||||
{
|
||||
account_id_type account_id = get_account_id(account);
|
||||
|
|
@ -5248,6 +5529,29 @@ signed_transaction wallet_api::update_son_votes(string voting_account,
|
|||
return my->update_son_votes(voting_account, sons_to_approve, sons_to_reject, desired_number_of_sons, broadcast);
|
||||
}
|
||||
|
||||
signed_transaction wallet_api::sidechain_deposit_transaction( const string &son_name_or_id,
|
||||
const sidechain_type& sidechain,
|
||||
const string &transaction_id,
|
||||
uint32_t operation_index,
|
||||
const string &sidechain_from,
|
||||
const string &sidechain_to,
|
||||
const string &sidechain_currency,
|
||||
int64_t sidechain_amount,
|
||||
const string &peerplays_from_name_or_id,
|
||||
const string &peerplays_to_name_or_id)
|
||||
{
|
||||
return my->sidechain_deposit_transaction(son_name_or_id,
|
||||
sidechain,
|
||||
transaction_id,
|
||||
operation_index,
|
||||
sidechain_from,
|
||||
sidechain_to,
|
||||
sidechain_currency,
|
||||
sidechain_amount,
|
||||
peerplays_from_name_or_id,
|
||||
peerplays_to_name_or_id);
|
||||
}
|
||||
|
||||
signed_transaction wallet_api::vote_for_witness(string voting_account,
|
||||
string witness,
|
||||
bool approve,
|
||||
|
|
@ -5314,13 +5618,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);
|
||||
}
|
||||
|
||||
|
|
@ -5356,7 +5660,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);
|
||||
}
|
||||
|
||||
|
|
@ -5835,13 +6139,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);
|
||||
}
|
||||
|
||||
|
|
@ -5891,7 +6195,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 )
|
||||
{
|
||||
|
|
@ -5903,7 +6207,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() )
|
||||
|
|
@ -6031,7 +6335,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);
|
||||
|
||||
|
|
@ -6200,7 +6504,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;
|
||||
|
|
@ -6280,7 +6584,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 );
|
||||
|
||||
|
|
@ -6422,7 +6726,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;
|
||||
|
|
@ -6450,7 +6754,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;
|
||||
|
|
@ -6478,7 +6782,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;
|
||||
|
|
@ -6506,7 +6810,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;
|
||||
|
|
@ -6536,7 +6840,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;
|
||||
|
|
@ -6565,7 +6869,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;
|
||||
|
|
@ -6595,7 +6899,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;
|
||||
|
|
@ -6630,7 +6934,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;
|
||||
|
|
@ -6663,7 +6967,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;
|
||||
|
|
@ -6693,7 +6997,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;
|
||||
|
|
@ -6725,7 +7029,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;
|
||||
|
|
@ -6758,7 +7062,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;
|
||||
|
|
@ -6790,7 +7094,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;
|
||||
|
|
@ -6822,7 +7126,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;
|
||||
|
|
@ -6854,7 +7158,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));
|
||||
|
||||
|
|
@ -6879,7 +7183,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;
|
||||
|
||||
|
|
@ -6902,7 +7206,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;
|
||||
|
|
@ -6930,7 +7234,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;
|
||||
|
|
@ -6953,7 +7257,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;
|
||||
|
|
@ -6974,7 +7278,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);
|
||||
|
|
@ -7001,7 +7305,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);
|
||||
|
|
@ -7046,7 +7350,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);
|
||||
|
|
@ -7582,6 +7886,31 @@ std::vector<matched_bet_object> wallet_api::get_all_matched_bets_for_bettor(acco
|
|||
return( my->_remote_bookie->get_all_matched_bets_for_bettor(bettor_id, start, limit) );
|
||||
}
|
||||
|
||||
vector<vote_id_type> wallet_api::get_votes_ids(const string &account_name_or_id) const
|
||||
{
|
||||
return my->get_votes_ids(account_name_or_id);
|
||||
}
|
||||
|
||||
votes_info wallet_api::get_votes(const string &account_name_or_id) const
|
||||
{
|
||||
return my->get_votes(account_name_or_id);
|
||||
}
|
||||
|
||||
vector<account_object> wallet_api::get_voters_by_id(const vote_id_type &vote_id) const
|
||||
{
|
||||
return my->get_voters_by_id(vote_id);
|
||||
}
|
||||
|
||||
voters_info wallet_api::get_voters(const string &account_name_or_id) const
|
||||
{
|
||||
return my->get_voters(account_name_or_id);
|
||||
}
|
||||
|
||||
std::map<sidechain_type, std::vector<std::string>> wallet_api::get_son_listener_log() const
|
||||
{
|
||||
return my->get_son_listener_log();
|
||||
}
|
||||
|
||||
// default ctor necessary for FC_REFLECT
|
||||
signed_block_with_info::signed_block_with_info( const signed_block& block )
|
||||
: signed_block( block )
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
import json
|
||||
import os
|
||||
import re
|
||||
import xml.etree.ElementTree as etree
|
||||
import defusedxml.ElementTree as etree
|
||||
|
||||
def process_node(path, node):
|
||||
"""
|
||||
|
|
|
|||
|
|
@ -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,21 +50,10 @@
|
|||
#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>
|
||||
#else
|
||||
|
|
@ -68,44 +67,54 @@ 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 );
|
||||
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") )
|
||||
{
|
||||
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";
|
||||
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;
|
||||
|
|
@ -153,28 +162,20 @@ 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 ) )
|
||||
{
|
||||
if (fc::exists(wallet_file)) {
|
||||
wdata = fc::json::from_file(wallet_file).as<wallet_data>(GRAPHENE_MAX_NESTED_OBJECTS);
|
||||
if( options.count("chain-id") )
|
||||
{
|
||||
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";
|
||||
}
|
||||
|
|
@ -213,8 +214,7 @@ int main( int argc, char** argv )
|
|||
}));
|
||||
(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 >>> ");
|
||||
} else
|
||||
|
|
@ -225,8 +225,7 @@ int main( int argc, char** argv )
|
|||
}));
|
||||
|
||||
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) {
|
||||
std::cout << "here... \n";
|
||||
|
|
@ -245,8 +244,7 @@ int main( int argc, char** argv )
|
|||
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) {
|
||||
auto wsc = std::make_shared<fc::rpc::websocket_api_connection>(c, GRAPHENE_MAX_NESTED_OBJECTS);
|
||||
|
|
@ -259,16 +257,14 @@ int main( int argc, char** argv )
|
|||
}
|
||||
|
||||
auto _http_server = std::make_shared<fc::http::server>();
|
||||
if( options.count("rpc-http-endpoint" ) )
|
||||
{
|
||||
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 )
|
||||
{
|
||||
[&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);
|
||||
|
|
@ -276,18 +272,16 @@ int main( int argc, char** argv )
|
|||
});
|
||||
}
|
||||
|
||||
if( !options.count( "daemon" ) )
|
||||
{
|
||||
if (!options.count("daemon")) {
|
||||
wallet_cli->register_api(wapi);
|
||||
wallet_cli->start();
|
||||
wallet_cli->wait();
|
||||
}
|
||||
else
|
||||
{
|
||||
} 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);
|
||||
},
|
||||
SIGINT);
|
||||
|
||||
ilog("Entering Daemon Mode, ^C to exit");
|
||||
exit_promise->wait();
|
||||
|
|
@ -296,9 +290,7 @@ int main( int argc, char** argv )
|
|||
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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -60,8 +60,14 @@ public:
|
|||
create_tx = fixture_.con.wallet_api_ptr->create_account_with_brain_key(
|
||||
bki.brain_priv_key, account_name, "nathan", "nathan", true
|
||||
);
|
||||
|
||||
fixture_.generate_block();
|
||||
|
||||
// save the private key for this new account in the wallet file
|
||||
BOOST_CHECK(fixture_.con.wallet_api_ptr->import_key(account_name, bki.wif_priv_key));
|
||||
|
||||
fixture_.generate_block();
|
||||
|
||||
fixture_.con.wallet_api_ptr->save_wallet_file(fixture_.con.wallet_filename);
|
||||
|
||||
// attempt to give son account some CORE tokens
|
||||
|
|
@ -244,6 +250,28 @@ BOOST_AUTO_TEST_CASE( son_voting )
|
|||
son2_end_votes = son2_obj.total_votes;
|
||||
BOOST_CHECK(son2_end_votes > son2_start_votes);
|
||||
|
||||
//! Get nathan account
|
||||
const auto nathan_account_object = con.wallet_api_ptr->get_account("nathan");
|
||||
|
||||
//! Check son1account voters
|
||||
auto voters_for_son1account = con.wallet_api_ptr->get_voters("son1account");
|
||||
BOOST_REQUIRE(voters_for_son1account.voters_for_son);
|
||||
BOOST_CHECK_EQUAL(voters_for_son1account.voters_for_son->voters.size(), 1);
|
||||
BOOST_CHECK_EQUAL((uint32_t)voters_for_son1account.voters_for_son->voters[0].instance, nathan_account_object.id.instance());
|
||||
|
||||
//! Check son2account voters
|
||||
auto voters_for_son2account = con.wallet_api_ptr->get_voters("son2account");
|
||||
BOOST_REQUIRE(voters_for_son2account.voters_for_son);
|
||||
BOOST_CHECK_EQUAL(voters_for_son2account.voters_for_son->voters.size(), 1);
|
||||
BOOST_CHECK_EQUAL((uint32_t)voters_for_son2account.voters_for_son->voters[0].instance, nathan_account_object.id.instance());
|
||||
|
||||
//! Check votes of nathan
|
||||
auto nathan_votes = con.wallet_api_ptr->get_votes("nathan");
|
||||
BOOST_REQUIRE(nathan_votes.votes_for_sons);
|
||||
BOOST_CHECK_EQUAL(nathan_votes.votes_for_sons->size(), 2);
|
||||
BOOST_CHECK_EQUAL(nathan_votes.votes_for_sons->at(0).id.instance(), son1_obj.id.instance());
|
||||
BOOST_CHECK_EQUAL(nathan_votes.votes_for_sons->at(1).id.instance(), son2_obj.id.instance());
|
||||
|
||||
// Withdraw vote for a son1account
|
||||
BOOST_TEST_MESSAGE("Withdraw vote for a son1account");
|
||||
vote_son1_tx = con.wallet_api_ptr->vote_for_son("nathan", "son1account", false, true);
|
||||
|
|
@ -254,6 +282,17 @@ BOOST_AUTO_TEST_CASE( son_voting )
|
|||
son1_end_votes = son1_obj.total_votes;
|
||||
BOOST_CHECK(son1_end_votes == son1_start_votes);
|
||||
|
||||
//! Check son1account voters
|
||||
voters_for_son1account = con.wallet_api_ptr->get_voters("son1account");
|
||||
BOOST_REQUIRE(voters_for_son1account.voters_for_son);
|
||||
BOOST_CHECK_EQUAL(voters_for_son1account.voters_for_son->voters.size(), 0);
|
||||
|
||||
//! Check votes of nathan
|
||||
nathan_votes = con.wallet_api_ptr->get_votes("nathan");
|
||||
BOOST_REQUIRE(nathan_votes.votes_for_sons);
|
||||
BOOST_CHECK_EQUAL(nathan_votes.votes_for_sons->size(), 1);
|
||||
BOOST_CHECK_EQUAL(nathan_votes.votes_for_sons->at(0).id.instance(), son2_obj.id.instance());
|
||||
|
||||
// Withdraw vote for a son2account
|
||||
BOOST_TEST_MESSAGE("Withdraw vote for a son2account");
|
||||
vote_son2_tx = con.wallet_api_ptr->vote_for_son("nathan", "son2account", false, true);
|
||||
|
|
@ -264,6 +303,15 @@ BOOST_AUTO_TEST_CASE( son_voting )
|
|||
son2_end_votes = son2_obj.total_votes;
|
||||
BOOST_CHECK(son2_end_votes == son2_start_votes);
|
||||
|
||||
//! Check son2account voters
|
||||
voters_for_son2account = con.wallet_api_ptr->get_voters("son2account");
|
||||
BOOST_REQUIRE(voters_for_son2account.voters_for_son);
|
||||
BOOST_CHECK_EQUAL(voters_for_son2account.voters_for_son->voters.size(), 0);
|
||||
|
||||
//! Check votes of nathan
|
||||
nathan_votes = con.wallet_api_ptr->get_votes("nathan");
|
||||
BOOST_CHECK(!nathan_votes.votes_for_sons.valid());
|
||||
|
||||
} catch( fc::exception& e ) {
|
||||
BOOST_TEST_MESSAGE("SON cli wallet tests exception");
|
||||
edump((e.to_detail_string()));
|
||||
|
|
|
|||
|
|
@ -38,6 +38,10 @@ using namespace graphene::chain;
|
|||
using namespace graphene::chain::test;
|
||||
using namespace graphene::app;
|
||||
|
||||
const std::string g_es_url = "http://localhost:9200/";
|
||||
const std::string g_es_index_prefix = "peerplays-";
|
||||
const std::string g_es_ppobjects_prefix = "ppobjects-";
|
||||
|
||||
BOOST_FIXTURE_TEST_SUITE( elasticsearch_tests, database_fixture )
|
||||
|
||||
BOOST_AUTO_TEST_CASE(elasticsearch_account_history) {
|
||||
|
|
@ -48,8 +52,8 @@ BOOST_AUTO_TEST_CASE(elasticsearch_account_history) {
|
|||
|
||||
graphene::utilities::ES es;
|
||||
es.curl = curl;
|
||||
es.elasticsearch_url = "http://localhost:9200/";
|
||||
es.index_prefix = "peerplays-";
|
||||
es.elasticsearch_url = g_es_url;
|
||||
es.index_prefix = g_es_index_prefix;
|
||||
//es.auth = "elastic:changeme";
|
||||
|
||||
// delete all first
|
||||
|
|
@ -71,7 +75,7 @@ BOOST_AUTO_TEST_CASE(elasticsearch_account_history) {
|
|||
//int account_create_op_id = operation::tag<account_create_operation>::value;
|
||||
|
||||
string query = "{ \"query\" : { \"bool\" : { \"must\" : [{\"match_all\": {}}] } } }";
|
||||
es.endpoint = es.index_prefix + "*/data/_count";
|
||||
es.endpoint = es.index_prefix + "*/_doc/_count";
|
||||
es.query = query;
|
||||
|
||||
auto res = graphene::utilities::simpleQuery(es);
|
||||
|
|
@ -79,7 +83,7 @@ BOOST_AUTO_TEST_CASE(elasticsearch_account_history) {
|
|||
auto total = j["count"].as_string();
|
||||
BOOST_CHECK_EQUAL(total, "5");
|
||||
|
||||
es.endpoint = es.index_prefix + "*/data/_search";
|
||||
es.endpoint = es.index_prefix + "*/_doc/_search";
|
||||
res = graphene::utilities::simpleQuery(es);
|
||||
j = fc::json::from_string(res);
|
||||
auto first_id = j["hits"]["hits"][size_t(0)]["_id"].as_string();
|
||||
|
|
@ -91,7 +95,7 @@ BOOST_AUTO_TEST_CASE(elasticsearch_account_history) {
|
|||
|
||||
fc::usleep(fc::milliseconds(1000)); // index.refresh_interval
|
||||
|
||||
es.endpoint = es.index_prefix + "*/data/_count";
|
||||
es.endpoint = es.index_prefix + "*/_doc/_count";
|
||||
res = graphene::utilities::simpleQuery(es);
|
||||
j = fc::json::from_string(res);
|
||||
|
||||
|
|
@ -114,9 +118,9 @@ BOOST_AUTO_TEST_CASE(elasticsearch_account_history) {
|
|||
|
||||
// check the visitor data
|
||||
auto block_date = db.head_block_time();
|
||||
std::string index_name = graphene::utilities::generateIndexName(block_date, "peerplays-");
|
||||
std::string index_name = g_es_index_prefix + block_date.to_iso_string().substr( 0, 7 ); // yyyy-mm
|
||||
|
||||
es.endpoint = index_name + "/data/2.9.12"; // we know last op is a transfer of amount 300
|
||||
es.endpoint = index_name + "/_doc/2.9.12"; // we know last op is a transfer of amount 300
|
||||
res = graphene::utilities::getEndPoint(es);
|
||||
j = fc::json::from_string(res);
|
||||
auto last_transfer_amount = j["_source"]["operation_history"]["op_object"]["amount_"]["amount"].as_string();
|
||||
|
|
@ -137,8 +141,8 @@ BOOST_AUTO_TEST_CASE(elasticsearch_objects) {
|
|||
|
||||
graphene::utilities::ES es;
|
||||
es.curl = curl;
|
||||
es.elasticsearch_url = "http://localhost:9200/";
|
||||
es.index_prefix = "ppobjects-";
|
||||
es.elasticsearch_url = g_es_url;
|
||||
es.index_prefix = g_es_ppobjects_prefix;
|
||||
//es.auth = "elastic:changeme";
|
||||
|
||||
// delete all first
|
||||
|
|
@ -155,7 +159,7 @@ BOOST_AUTO_TEST_CASE(elasticsearch_objects) {
|
|||
fc::usleep(fc::milliseconds(1000));
|
||||
|
||||
string query = "{ \"query\" : { \"bool\" : { \"must\" : [{\"match_all\": {}}] } } }";
|
||||
es.endpoint = es.index_prefix + "*/data/_count";
|
||||
es.endpoint = es.index_prefix + "*/_doc/_count";
|
||||
es.query = query;
|
||||
|
||||
auto res = graphene::utilities::simpleQuery(es);
|
||||
|
|
@ -163,14 +167,14 @@ BOOST_AUTO_TEST_CASE(elasticsearch_objects) {
|
|||
auto total = j["count"].as_string();
|
||||
BOOST_CHECK_EQUAL(total, "2");
|
||||
|
||||
es.endpoint = es.index_prefix + "asset/data/_search";
|
||||
es.endpoint = es.index_prefix + "asset/_doc/_search";
|
||||
res = graphene::utilities::simpleQuery(es);
|
||||
j = fc::json::from_string(res);
|
||||
auto first_id = j["hits"]["hits"][size_t(0)]["_source"]["symbol"].as_string();
|
||||
BOOST_CHECK_EQUAL(first_id, "USD");
|
||||
|
||||
auto bitasset_data_id = j["hits"]["hits"][size_t(0)]["_source"]["bitasset_data_id"].as_string();
|
||||
es.endpoint = es.index_prefix + "bitasset/data/_search";
|
||||
es.endpoint = es.index_prefix + "bitasset/_doc/_search";
|
||||
es.query = "{ \"query\" : { \"bool\": { \"must\" : [{ \"term\": { \"object_id\": \""+bitasset_data_id+"\"}}] } } }";
|
||||
res = graphene::utilities::simpleQuery(es);
|
||||
j = fc::json::from_string(res);
|
||||
|
|
@ -192,11 +196,11 @@ BOOST_AUTO_TEST_CASE(elasticsearch_suite) {
|
|||
|
||||
graphene::utilities::ES es;
|
||||
es.curl = curl;
|
||||
es.elasticsearch_url = "http://localhost:9200/";
|
||||
es.index_prefix = "peerplays-";
|
||||
es.elasticsearch_url = g_es_url;
|
||||
es.index_prefix = g_es_index_prefix;
|
||||
auto delete_account_history = graphene::utilities::deleteAll(es);
|
||||
fc::usleep(fc::milliseconds(1000));
|
||||
es.index_prefix = "ppobjects-";
|
||||
es.index_prefix = g_es_ppobjects_prefix;
|
||||
auto delete_objects = graphene::utilities::deleteAll(es);
|
||||
fc::usleep(fc::milliseconds(1000));
|
||||
|
||||
|
|
@ -218,8 +222,8 @@ BOOST_AUTO_TEST_CASE(elasticsearch_history_api) {
|
|||
|
||||
graphene::utilities::ES es;
|
||||
es.curl = curl;
|
||||
es.elasticsearch_url = "http://localhost:9200/";
|
||||
es.index_prefix = "peerplays-";
|
||||
es.elasticsearch_url = g_es_url;
|
||||
es.index_prefix = g_es_index_prefix;
|
||||
|
||||
auto delete_account_history = graphene::utilities::deleteAll(es);
|
||||
|
||||
|
|
|
|||
|
|
@ -934,6 +934,125 @@ BOOST_FIXTURE_TEST_CASE( change_block_interval, database_fixture )
|
|||
BOOST_CHECK_EQUAL(db.head_block_time().sec_since_epoch() - past_time, 2);
|
||||
} FC_LOG_AND_RETHROW() }
|
||||
|
||||
BOOST_FIXTURE_TEST_CASE( prevent_missconfiguration_blockchain_param, database_fixture )
|
||||
{ try {
|
||||
|
||||
db.modify(db.get_global_properties(), [](global_property_object& p) {
|
||||
p.parameters.committee_proposal_review_period = fc::hours(1).to_seconds();
|
||||
});
|
||||
|
||||
// remeber global properties before we try to change
|
||||
const global_property_object gpo = db.get_global_properties();
|
||||
|
||||
BOOST_TEST_MESSAGE( "Creating a proposal to try with changing some global parameters" );
|
||||
{
|
||||
proposal_create_operation cop = proposal_create_operation::committee_proposal(db.get_global_properties().parameters, db.head_block_time());
|
||||
cop.fee_paying_account = GRAPHENE_TEMP_ACCOUNT;
|
||||
cop.expiration_time = db.head_block_time() + *cop.review_period_seconds + 10;
|
||||
|
||||
committee_member_update_global_parameters_operation uop;
|
||||
|
||||
// this is allowed values and the proposal change should be visible after approving
|
||||
*uop.new_parameters.extensions.value.son_heartbeat_frequency = 100;
|
||||
*uop.new_parameters.extensions.value.son_deregister_time = 120;
|
||||
*uop.new_parameters.extensions.value.son_down_time = 140;
|
||||
*uop.new_parameters.extensions.value.son_pay_time = 160;
|
||||
|
||||
// this change should not be applied. Changing gpos_period_start is not allowed
|
||||
*uop.new_parameters.extensions.value.gpos_period_start = 50;
|
||||
|
||||
// the following changes should not be applied. Changing the assets is not allowed
|
||||
*uop.new_parameters.extensions.value.btc_asset = db.get_global_properties().parameters.hbd_asset();
|
||||
*uop.new_parameters.extensions.value.hbd_asset = db.get_global_properties().parameters.hive_asset();
|
||||
*uop.new_parameters.extensions.value.hive_asset = db.get_global_properties().parameters.btc_asset();
|
||||
|
||||
// this change should not be applied. Changing the son_acccount is not allowed
|
||||
*uop.new_parameters.extensions.value.son_account = GRAPHENE_TEMP_ACCOUNT;
|
||||
|
||||
cop.proposed_ops.emplace_back(uop);
|
||||
|
||||
trx.operations.push_back(cop);
|
||||
db.push_transaction(trx);
|
||||
}
|
||||
|
||||
BOOST_TEST_MESSAGE( "Updating proposal by signing with the committee_member private key" );
|
||||
{
|
||||
proposal_update_operation uop;
|
||||
uop.fee_paying_account = GRAPHENE_TEMP_ACCOUNT;
|
||||
uop.active_approvals_to_add = {get_account("init0").get_id(), get_account("init1").get_id(),
|
||||
get_account("init2").get_id(), get_account("init3").get_id(),
|
||||
get_account("init4").get_id(), get_account("init5").get_id(),
|
||||
get_account("init6").get_id(), get_account("init7").get_id()};
|
||||
trx.operations.push_back(uop);
|
||||
sign( trx, init_account_priv_key );
|
||||
|
||||
db.push_transaction(trx);
|
||||
|
||||
BOOST_CHECK(proposal_id_type()(db).is_authorized_to_execute(db));
|
||||
}
|
||||
|
||||
BOOST_TEST_MESSAGE( "Generating blocks until proposal expires" );
|
||||
generate_blocks(proposal_id_type()(db).expiration_time + 5);
|
||||
|
||||
generate_blocks(db.get_dynamic_global_properties().next_maintenance_time);
|
||||
generate_block(); // get the maintenance skip slots out of the way*/
|
||||
|
||||
BOOST_CHECK_EQUAL( db.get_global_properties().parameters.son_heartbeat_frequency(), 100 );
|
||||
BOOST_CHECK_EQUAL( db.get_global_properties().parameters.son_deregister_time(), 120 );
|
||||
BOOST_CHECK_EQUAL( db.get_global_properties().parameters.son_down_time(), 140 );
|
||||
BOOST_CHECK_EQUAL( db.get_global_properties().parameters.son_pay_time(), 160 );
|
||||
|
||||
BOOST_CHECK_NE( db.get_global_properties().parameters.gpos_period_start(), 50 );
|
||||
|
||||
BOOST_CHECK( db.get_global_properties().parameters.son_account() != GRAPHENE_TEMP_ACCOUNT );
|
||||
|
||||
BOOST_CHECK( gpo.parameters.hbd_asset() == db.get_global_properties().parameters.hbd_asset() );
|
||||
BOOST_CHECK( gpo.parameters.hive_asset() == db.get_global_properties().parameters.hive_asset() );
|
||||
BOOST_CHECK( gpo.parameters.btc_asset() == db.get_global_properties().parameters.btc_asset() );
|
||||
|
||||
} FC_LOG_AND_RETHROW() }
|
||||
|
||||
BOOST_FIXTURE_TEST_CASE( hardfork_son2_time, database_fixture )
|
||||
{ try {
|
||||
|
||||
db.modify(db.get_global_properties(), [](global_property_object& p) {
|
||||
p.parameters.committee_proposal_review_period = fc::hours(1).to_seconds();
|
||||
});
|
||||
|
||||
generate_block();
|
||||
// check that maximum_son_count are not yet updated on 7, it should
|
||||
// be updated on HARDFORK_SON2_TIME
|
||||
BOOST_CHECK_EQUAL(db.get_global_properties().parameters.maximum_son_count(), GRAPHENE_DEFAULT_MAX_SONS);
|
||||
|
||||
generate_blocks(HARDFORK_SON2_TIME);
|
||||
|
||||
// check that flags for assets are set after hardfork_son2_time
|
||||
asset_object btc_asset = get_asset("BTC");
|
||||
uint16_t check_flags{0};
|
||||
check_flags |= asset_issuer_permission_flags::charge_market_fee | asset_issuer_permission_flags::override_authority;
|
||||
uint16_t result = btc_asset.options.flags & check_flags;
|
||||
BOOST_CHECK_EQUAL( result, check_flags);
|
||||
|
||||
// move on next maintenance interval and check that maximum_son_count is updated to 7
|
||||
generate_blocks(db.get_dynamic_global_properties().next_maintenance_time);
|
||||
generate_block(); // get the maintenance skip slots out of the way*/
|
||||
BOOST_CHECK_EQUAL(db.get_global_properties().parameters.maximum_son_count(), 7);
|
||||
|
||||
generate_blocks(HARDFORK_SON3_TIME);
|
||||
// after this hardfork maximum son account should not reset the value
|
||||
// on 7 after maintenance interval anymore. So change the global parameters
|
||||
// and check the value after maintenance interval
|
||||
db.modify(db.get_global_properties(), [](global_property_object& p) {
|
||||
p.parameters.extensions.value.maximum_son_count = 13;
|
||||
});
|
||||
|
||||
generate_blocks(db.get_dynamic_global_properties().next_maintenance_time);
|
||||
generate_block();
|
||||
|
||||
BOOST_CHECK_EQUAL(db.get_global_properties().parameters.maximum_son_count(), 13);
|
||||
|
||||
} FC_LOG_AND_RETHROW() }
|
||||
|
||||
BOOST_FIXTURE_TEST_CASE( pop_block_twice, database_fixture )
|
||||
{
|
||||
try
|
||||
|
|
|
|||
|
|
@ -322,6 +322,18 @@ BOOST_AUTO_TEST_CASE(track_votes_witnesses_enabled)
|
|||
auto witness1_object = db_api1.get_witness_by_account(witness1_id(db).name);
|
||||
BOOST_CHECK_EQUAL(witness1_object->total_votes, 111);
|
||||
|
||||
//! Check witness1 voters
|
||||
const auto voters_for_witness1 = db_api1.get_voters("witness1");
|
||||
BOOST_REQUIRE(voters_for_witness1.voters_for_witness);
|
||||
BOOST_CHECK_EQUAL(voters_for_witness1.voters_for_witness->voters.size(), 1);
|
||||
BOOST_CHECK_EQUAL((uint32_t)voters_for_witness1.voters_for_witness->voters[0].instance, 18);
|
||||
|
||||
//! Check votes of account
|
||||
const auto account_votes = db_api1.get_votes("1.2.18");
|
||||
BOOST_REQUIRE(account_votes.votes_for_witnesses);
|
||||
BOOST_CHECK_EQUAL(account_votes.votes_for_witnesses->size(), 1);
|
||||
BOOST_CHECK_EQUAL(account_votes.votes_for_witnesses->at(0).id.instance(), witness1_object->id.instance());
|
||||
|
||||
} FC_LOG_AND_RETHROW()
|
||||
}
|
||||
|
||||
|
|
@ -501,6 +513,17 @@ BOOST_AUTO_TEST_CASE(track_votes_committee_enabled)
|
|||
auto committee1_object = db_api1.get_committee_member_by_account(committee1_id(db).name);
|
||||
BOOST_CHECK_EQUAL(committee1_object->total_votes, 111);
|
||||
|
||||
//! Check committee1 voters
|
||||
const auto voters_for_committee1 = db_api1.get_voters("committee1");
|
||||
BOOST_REQUIRE(voters_for_committee1.voters_for_committee_member);
|
||||
BOOST_CHECK_EQUAL(voters_for_committee1.voters_for_committee_member->voters.size(), 1);
|
||||
BOOST_CHECK_EQUAL((uint32_t)voters_for_committee1.voters_for_committee_member->voters[0].instance, 18);
|
||||
|
||||
//! Check votes of account
|
||||
const auto account_votes = db_api1.get_votes("1.2.18");
|
||||
BOOST_REQUIRE(account_votes.votes_for_committee_members);
|
||||
BOOST_CHECK_EQUAL(account_votes.votes_for_committee_members->back().id.instance(), committee1_object->id.instance());
|
||||
|
||||
} FC_LOG_AND_RETHROW()
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue