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
|
Language: Cpp
|
||||||
# BasedOnStyle: LLVM
|
|
||||||
AccessModifierOffset: -3
|
AccessModifierOffset: -3
|
||||||
AlignAfterOpenBracket: Align
|
AlignAfterOpenBracket: Align
|
||||||
AlignConsecutiveMacros: false
|
AlignConsecutiveMacros: false
|
||||||
|
|
@ -12,7 +11,7 @@ AlignTrailingComments: true
|
||||||
AllowAllArgumentsOnNextLine: true
|
AllowAllArgumentsOnNextLine: true
|
||||||
AllowAllConstructorInitializersOnNextLine: false
|
AllowAllConstructorInitializersOnNextLine: false
|
||||||
AllowAllParametersOfDeclarationOnNextLine: true
|
AllowAllParametersOfDeclarationOnNextLine: true
|
||||||
AllowShortBlocksOnASingleLine: false
|
AllowShortBlocksOnASingleLine: Never
|
||||||
AllowShortCaseLabelsOnASingleLine: false
|
AllowShortCaseLabelsOnASingleLine: false
|
||||||
AllowShortFunctionsOnASingleLine: None
|
AllowShortFunctionsOnASingleLine: None
|
||||||
AllowShortLambdasOnASingleLine: None
|
AllowShortLambdasOnASingleLine: None
|
||||||
|
|
@ -57,6 +56,7 @@ ConstructorInitializerAllOnOneLineOrOnePerLine: true
|
||||||
ConstructorInitializerIndentWidth: 6
|
ConstructorInitializerIndentWidth: 6
|
||||||
ContinuationIndentWidth: 6
|
ContinuationIndentWidth: 6
|
||||||
Cpp11BracedListStyle: true
|
Cpp11BracedListStyle: true
|
||||||
|
DeriveLineEnding: true
|
||||||
DerivePointerAlignment: false
|
DerivePointerAlignment: false
|
||||||
DisableFormat: false
|
DisableFormat: false
|
||||||
ExperimentalAutoDetectBinPacking: false
|
ExperimentalAutoDetectBinPacking: false
|
||||||
|
|
@ -69,12 +69,17 @@ IncludeBlocks: Preserve
|
||||||
IncludeCategories:
|
IncludeCategories:
|
||||||
- Regex: '^"(llvm|llvm-c|clang|clang-c)/'
|
- Regex: '^"(llvm|llvm-c|clang|clang-c)/'
|
||||||
Priority: 2
|
Priority: 2
|
||||||
|
SortPriority: 0
|
||||||
- Regex: '^(<|"(gtest|gmock|isl|json)/)'
|
- Regex: '^(<|"(gtest|gmock|isl|json)/)'
|
||||||
Priority: 3
|
Priority: 3
|
||||||
|
SortPriority: 0
|
||||||
- Regex: '.*'
|
- Regex: '.*'
|
||||||
Priority: 1
|
Priority: 1
|
||||||
|
SortPriority: 0
|
||||||
IncludeIsMainRegex: '(Test)?$'
|
IncludeIsMainRegex: '(Test)?$'
|
||||||
|
IncludeIsMainSourceRegex: ''
|
||||||
IndentCaseLabels: false
|
IndentCaseLabels: false
|
||||||
|
IndentGotoLabels: false
|
||||||
IndentPPDirectives: None
|
IndentPPDirectives: None
|
||||||
IndentWidth: 3
|
IndentWidth: 3
|
||||||
IndentWrappedFunctionNames: false
|
IndentWrappedFunctionNames: false
|
||||||
|
|
@ -110,18 +115,22 @@ SpaceBeforeCtorInitializerColon: true
|
||||||
SpaceBeforeInheritanceColon: true
|
SpaceBeforeInheritanceColon: true
|
||||||
SpaceBeforeParens: ControlStatements
|
SpaceBeforeParens: ControlStatements
|
||||||
SpaceBeforeRangeBasedForLoopColon: true
|
SpaceBeforeRangeBasedForLoopColon: true
|
||||||
|
SpaceInEmptyBlock: false
|
||||||
SpaceInEmptyParentheses: false
|
SpaceInEmptyParentheses: false
|
||||||
SpacesBeforeTrailingComments: 1
|
SpacesBeforeTrailingComments: 1
|
||||||
SpacesInAngles: false
|
SpacesInAngles: false
|
||||||
|
SpacesInConditionalStatement: false
|
||||||
SpacesInContainerLiterals: true
|
SpacesInContainerLiterals: true
|
||||||
SpacesInCStyleCastParentheses: false
|
SpacesInCStyleCastParentheses: false
|
||||||
SpacesInParentheses: false
|
SpacesInParentheses: false
|
||||||
SpacesInSquareBrackets: false
|
SpacesInSquareBrackets: false
|
||||||
Standard: Cpp11
|
SpaceBeforeSquareBrackets: false
|
||||||
|
Standard: Latest
|
||||||
StatementMacros:
|
StatementMacros:
|
||||||
- Q_UNUSED
|
- Q_UNUSED
|
||||||
- QT_REQUIRE_VERSION
|
- QT_REQUIRE_VERSION
|
||||||
TabWidth: 3
|
TabWidth: 3
|
||||||
|
UseCRLF: false
|
||||||
UseTab: Never
|
UseTab: Never
|
||||||
...
|
...
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -19,7 +19,7 @@ build:
|
||||||
- mkdir build
|
- mkdir build
|
||||||
- cd build
|
- cd build
|
||||||
- cmake -DCMAKE_BUILD_TYPE=Release ..
|
- cmake -DCMAKE_BUILD_TYPE=Release ..
|
||||||
- make -j4
|
- make -j$(nproc)
|
||||||
artifacts:
|
artifacts:
|
||||||
untracked: true
|
untracked: true
|
||||||
paths:
|
paths:
|
||||||
|
|
@ -49,6 +49,7 @@ test:
|
||||||
dependencies:
|
dependencies:
|
||||||
- build
|
- build
|
||||||
script:
|
script:
|
||||||
|
- ./build/libraries/fc/tests/all_tests
|
||||||
- ./build/tests/betting_test --log_level=message
|
- ./build/tests/betting_test --log_level=message
|
||||||
- ./build/tests/chain_test --log_level=message
|
- ./build/tests/chain_test --log_level=message
|
||||||
- ./build/tests/cli_test --log_level=message
|
- ./build/tests/cli_test --log_level=message
|
||||||
|
|
|
||||||
14
.gitmodules
vendored
14
.gitmodules
vendored
|
|
@ -1,9 +1,9 @@
|
||||||
[submodule "docs"]
|
[submodule "docs"]
|
||||||
path = docs
|
path = docs
|
||||||
url = https://github.com/bitshares/bitshares-core.wiki.git
|
url = https://github.com/bitshares/bitshares-core.wiki.git
|
||||||
ignore = dirty
|
ignore = dirty
|
||||||
[submodule "libraries/fc"]
|
[submodule "libraries/fc"]
|
||||||
path = 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
|
branch = latest-fc
|
||||||
ignore = dirty
|
ignore = dirty
|
||||||
|
|
|
||||||
|
|
@ -83,7 +83,6 @@ LIST(APPEND BOOST_COMPONENTS thread
|
||||||
system
|
system
|
||||||
filesystem
|
filesystem
|
||||||
program_options
|
program_options
|
||||||
signals
|
|
||||||
serialization
|
serialization
|
||||||
chrono
|
chrono
|
||||||
unit_test_framework
|
unit_test_framework
|
||||||
|
|
|
||||||
102
README.md
102
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.
|
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
|
||||||
sudo apt-get install autoconf bash build-essential ca-certificates cmake \
|
|
||||||
doxygen git graphviz libbz2-dev libcurl4-openssl-dev libncurses-dev \
|
Officially supported OS is Ubuntu 20.04.
|
||||||
libreadline-dev libssl-dev libtool libzmq3-dev locales ntp pkg-config \
|
|
||||||
wget
|
Following dependencies are needed for a clean install of Ubuntu 20.04:
|
||||||
```
|
```
|
||||||
## Build Boost 1.67.0
|
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 \
|
||||||
mkdir $HOME/src
|
libssl-dev libtool libzip-dev libzmq3-dev locales mc nano net-tools ntp \
|
||||||
cd $HOME/src
|
openssh-server pkg-config perl python3 python3-jinja2 sudo wget
|
||||||
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
|
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
## Building Peerplays
|
## Building Peerplays
|
||||||
|
|
||||||
```
|
```
|
||||||
|
mkdir $HOME/src
|
||||||
cd $HOME/src
|
cd $HOME/src
|
||||||
export BOOST_ROOT=$HOME/src/boost_1_67_0
|
git clone https://gitlab.com/PBSA/peerplays.git
|
||||||
git clone https://github.com/peerplays-network/peerplays.git
|
|
||||||
cd peerplays
|
cd peerplays
|
||||||
git submodule update --init --recursive
|
git submodule update --init --recursive
|
||||||
|
|
||||||
# If you want to build Mainnet node
|
# 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
|
# 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 -j$(nproc)
|
||||||
|
|
||||||
make install # this can install the executable files under /usr/local
|
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
|
sudo apt install docker.io
|
||||||
|
|
||||||
|
|
||||||
# Add current user to docker group
|
|
||||||
sudo usermod -a -G docker $USER
|
sudo usermod -a -G docker $USER
|
||||||
|
|
||||||
# You need to restart your shell session, to apply group membership
|
# You need to restart your shell session, to apply group membership
|
||||||
# Type 'groups' to verify that you are a member of a docker group
|
# Type 'groups' to verify that you are a member of a docker group
|
||||||
|
|
||||||
|
|
||||||
# Build docker image (from the project root, must be a docker group member)
|
|
||||||
docker build -t peerplays .
|
|
||||||
|
|
||||||
|
|
||||||
# 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.
|
### 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
|
||||||
|
```
|
||||||
|
docker start peerplays
|
||||||
|
```
|
||||||
|
|
||||||
|
Rest of the instructions on starting the chain remains same.
|
||||||
|
|
||||||
Starting A Peerplays Node
|
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.
|
Launching the witness creates required directories. Next, **stop the witness** and continue.
|
||||||
|
|
||||||
$ vi witness_node_data_dir/config.ini
|
$ vi witness_node_data_dir/config.ini
|
||||||
|
|
|
||||||
|
|
@ -3,3 +3,4 @@
|
||||||
find ./libraries/app -regex ".*[c|h]pp" | xargs clang-format -i
|
find ./libraries/app -regex ".*[c|h]pp" | xargs clang-format -i
|
||||||
find ./libraries/chain/hardfork.d -regex ".*hf" | 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 ./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 graphene_market_history graphene_account_history graphene_chain fc graphene_db graphene_net graphene_utilities graphene_debug_witness )
|
||||||
target_link_libraries( graphene_app
|
target_link_libraries( graphene_app
|
||||||
PUBLIC graphene_net graphene_utilities
|
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
|
target_include_directories( graphene_app
|
||||||
PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/include"
|
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
|
// can only enable this API if the plugin was loaded
|
||||||
if (_app.get_plugin("affiliate_stats"))
|
if (_app.get_plugin("affiliate_stats"))
|
||||||
_affiliate_stats_api = std::make_shared<graphene::affiliate_stats::affiliate_stats_api>(std::ref(_app));
|
_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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -310,6 +314,11 @@ fc::api<graphene::affiliate_stats::affiliate_stats_api> login_api::affiliate_sta
|
||||||
return *_affiliate_stats_api;
|
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 {
|
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());
|
FC_ASSERT(_app.chain_database());
|
||||||
const auto &db = *_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("crypto_api");
|
||||||
wild_access.allowed_apis.push_back("bookie_api");
|
wild_access.allowed_apis.push_back("bookie_api");
|
||||||
wild_access.allowed_apis.push_back("affiliate_stats_api");
|
wild_access.allowed_apis.push_back("affiliate_stats_api");
|
||||||
|
wild_access.allowed_apis.push_back("sidechain_api");
|
||||||
_apiaccess.permission_map["*"] = wild_access;
|
_apiaccess.permission_map["*"] = wild_access;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -52,6 +52,22 @@ template class fc::api<graphene::app::database_api>;
|
||||||
|
|
||||||
namespace graphene { namespace app {
|
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> {
|
class database_api_impl : public std::enable_shared_from_this<database_api_impl> {
|
||||||
public:
|
public:
|
||||||
database_api_impl(graphene::chain::database &db);
|
database_api_impl(graphene::chain::database &db);
|
||||||
|
|
@ -146,18 +162,22 @@ public:
|
||||||
|
|
||||||
// Witnesses
|
// Witnesses
|
||||||
vector<optional<witness_object>> get_witnesses(const vector<witness_id_type> &witness_ids) const;
|
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;
|
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;
|
map<string, witness_id_type> lookup_witness_accounts(const string &lower_bound_name, uint32_t limit) const;
|
||||||
uint64_t get_witness_count() const;
|
uint64_t get_witness_count() const;
|
||||||
|
|
||||||
// Committee members
|
// Committee members
|
||||||
vector<optional<committee_member_object>> get_committee_members(const vector<committee_member_id_type> &committee_member_ids) const;
|
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;
|
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;
|
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
|
// SON members
|
||||||
vector<optional<son_object>> get_sons(const vector<son_id_type> &son_ids) const;
|
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;
|
map<string, son_id_type> lookup_son_accounts(const string &lower_bound_name, uint32_t limit) const;
|
||||||
uint64_t get_son_count() 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;
|
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;
|
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
|
// Votes
|
||||||
vector<variant> lookup_vote_ids(const vector<vote_id_type> &votes) const;
|
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
|
// Authority / validation
|
||||||
std::string get_transaction_hex(const signed_transaction &trx) const;
|
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_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;
|
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_lower_bound_symbol = 100;
|
||||||
uint32_t api_limit_get_limit_orders = 300;
|
uint32_t api_limit_get_limit_orders = 300;
|
||||||
uint32_t api_limit_get_limit_orders_by_account = 101;
|
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_accounts = 1000;
|
||||||
uint32_t api_limit_lookup_witness_accounts = 1000;
|
uint32_t api_limit_lookup_witness_accounts = 1000;
|
||||||
uint32_t api_limit_lookup_committee_member_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 = 100;
|
||||||
uint32_t api_limit_get_trade_history_by_sequence = 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:
|
//private:
|
||||||
const account_object *get_account_from_string(const std::string &name_or_id,
|
const account_object *get_account_from_string(const std::string &name_or_id,
|
||||||
bool throw_if_not_found = true) const;
|
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);
|
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>> database_api_impl::get_witnesses(const vector<witness_id_type> &witness_ids) const {
|
||||||
vector<optional<witness_object>> result;
|
vector<optional<witness_object>> result;
|
||||||
result.reserve(witness_ids.size());
|
result.reserve(witness_ids.size());
|
||||||
|
|
@ -1578,17 +1610,25 @@ vector<optional<witness_object>> database_api_impl::get_witnesses(const vector<w
|
||||||
return result;
|
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 {
|
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);
|
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 {
|
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;
|
const account_id_type account = get_account_from_string(account_id_or_name)->id;
|
||||||
auto itr = idx.find(account);
|
return get_witness_by_account_id(account);
|
||||||
if (itr != idx.end())
|
|
||||||
return *itr;
|
|
||||||
return {};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
map<string, witness_id_type> database_api::lookup_witness_accounts(const string &lower_bound_name, uint32_t limit) const {
|
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;
|
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 {
|
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);
|
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 {
|
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;
|
const account_id_type account = get_account_from_string(account_id_or_name)->id;
|
||||||
auto itr = idx.find(account);
|
return get_committee_member_by_account_id(account);
|
||||||
if (itr != idx.end())
|
|
||||||
return *itr;
|
|
||||||
return {};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
map<string, committee_member_id_type> database_api::lookup_committee_member_accounts(const string &lower_bound_name, uint32_t limit) const {
|
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;
|
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 //
|
// SON members //
|
||||||
|
|
@ -1712,11 +1768,11 @@ vector<optional<son_object>> database_api_impl::get_sons(const vector<son_id_typ
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
fc::optional<son_object> database_api::get_son_by_account(account_id_type account) const {
|
fc::optional<son_object> database_api::get_son_by_account_id(account_id_type account) const {
|
||||||
return my->get_son_by_account(account);
|
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>();
|
const auto &idx = _db.get_index_type<son_index>().indices().get<by_account>();
|
||||||
auto itr = idx.find(account);
|
auto itr = idx.find(account);
|
||||||
if (itr != idx.end())
|
if (itr != idx.end())
|
||||||
|
|
@ -1724,12 +1780,24 @@ fc::optional<son_object> database_api_impl::get_son_by_account(account_id_type a
|
||||||
return {};
|
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 {
|
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);
|
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 {
|
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>();
|
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
|
// 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();
|
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 //
|
// Votes //
|
||||||
|
|
@ -1885,6 +2038,22 @@ vector<variant> database_api::lookup_vote_ids(const vector<vote_id_type> &votes)
|
||||||
return my->lookup_vote_ids(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 {
|
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");
|
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;
|
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 //
|
// Authority / validation //
|
||||||
|
|
|
||||||
|
|
@ -28,16 +28,15 @@
|
||||||
#include <graphene/chain/protocol/confidential.hpp>
|
#include <graphene/chain/protocol/confidential.hpp>
|
||||||
#include <graphene/chain/protocol/types.hpp>
|
#include <graphene/chain/protocol/types.hpp>
|
||||||
|
|
||||||
|
#include <graphene/net/node.hpp>
|
||||||
|
|
||||||
#include <graphene/accounts_list/accounts_list_plugin.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/affiliate_stats/affiliate_stats_api.hpp>
|
||||||
#include <graphene/bookie/bookie_api.hpp>
|
#include <graphene/bookie/bookie_api.hpp>
|
||||||
#include <graphene/debug_witness/debug_api.hpp>
|
#include <graphene/debug_witness/debug_api.hpp>
|
||||||
|
#include <graphene/elasticsearch/elasticsearch_plugin.hpp>
|
||||||
#include <graphene/net/node.hpp>
|
#include <graphene/market_history/market_history_plugin.hpp>
|
||||||
|
#include <graphene/peerplays_sidechain/sidechain_api.hpp>
|
||||||
|
|
||||||
#include <fc/api.hpp>
|
#include <fc/api.hpp>
|
||||||
#include <fc/crypto/elliptic.hpp>
|
#include <fc/crypto/elliptic.hpp>
|
||||||
|
|
@ -405,6 +404,8 @@ public:
|
||||||
fc::api<graphene::bookie::bookie_api> bookie() const;
|
fc::api<graphene::bookie::bookie_api> bookie() const;
|
||||||
/// @brief Retrieve the affiliate_stats API (if available)
|
/// @brief Retrieve the affiliate_stats API (if available)
|
||||||
fc::api<graphene::affiliate_stats::affiliate_stats_api> affiliate_stats() const;
|
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.
|
/// @brief Called to enable an API, not reflected.
|
||||||
void enable_api(const string &api_name);
|
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::debug_witness::debug_api>> _debug_api;
|
||||||
optional<fc::api<graphene::bookie::bookie_api>> _bookie_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::affiliate_stats::affiliate_stats_api>> _affiliate_stats_api;
|
||||||
|
optional<fc::api<graphene::peerplays_sidechain::sidechain_api>> _sidechain_api;
|
||||||
};
|
};
|
||||||
|
|
||||||
}} // namespace graphene::app
|
}} // namespace graphene::app
|
||||||
|
|
@ -498,6 +500,7 @@ FC_API(graphene::app::login_api,
|
||||||
(asset)
|
(asset)
|
||||||
(debug)
|
(debug)
|
||||||
(bookie)
|
(bookie)
|
||||||
(affiliate_stats))
|
(affiliate_stats)
|
||||||
|
(sidechain))
|
||||||
|
|
||||||
// clang-format on
|
// clang-format on
|
||||||
|
|
|
||||||
|
|
@ -56,6 +56,8 @@
|
||||||
#include <graphene/chain/custom_permission_object.hpp>
|
#include <graphene/chain/custom_permission_object.hpp>
|
||||||
#include <graphene/chain/nft_object.hpp>
|
#include <graphene/chain/nft_object.hpp>
|
||||||
#include <graphene/chain/offer_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>
|
#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
|
* @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
|
* @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;
|
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;
|
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
|
* @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
|
* @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;
|
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 //
|
// SON members //
|
||||||
/////////////////
|
/////////////////
|
||||||
|
|
@ -619,7 +640,14 @@ public:
|
||||||
* @param account The ID of the account whose SON should be retrieved
|
* @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
|
* @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
|
* @brief Get names and IDs for registered SONs
|
||||||
|
|
@ -698,15 +726,46 @@ public:
|
||||||
*/
|
*/
|
||||||
uint64_t get_sidechain_addresses_count() const;
|
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.
|
* @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
|
* @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;
|
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 //
|
// Votes //
|
||||||
///////////
|
///////////
|
||||||
|
|
@ -721,6 +780,39 @@ public:
|
||||||
*/
|
*/
|
||||||
vector<variant> lookup_vote_ids(const vector<vote_id_type> &votes) const;
|
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 //
|
// Authority / validation //
|
||||||
////////////////////////////
|
////////////////////////////
|
||||||
|
|
@ -1033,17 +1125,21 @@ FC_API(graphene::app::database_api,
|
||||||
|
|
||||||
// Witnesses
|
// Witnesses
|
||||||
(get_witnesses)
|
(get_witnesses)
|
||||||
|
(get_witness_by_account_id)
|
||||||
(get_witness_by_account)
|
(get_witness_by_account)
|
||||||
(lookup_witness_accounts)
|
(lookup_witness_accounts)
|
||||||
(get_witness_count)
|
(get_witness_count)
|
||||||
|
|
||||||
// Committee members
|
// Committee members
|
||||||
(get_committee_members)
|
(get_committee_members)
|
||||||
|
(get_committee_member_by_account_id)
|
||||||
(get_committee_member_by_account)
|
(get_committee_member_by_account)
|
||||||
(lookup_committee_member_accounts)
|
(lookup_committee_member_accounts)
|
||||||
|
(get_committee_member_count)
|
||||||
|
|
||||||
// SON members
|
// SON members
|
||||||
(get_sons)
|
(get_sons)
|
||||||
|
(get_son_by_account_id)
|
||||||
(get_son_by_account)
|
(get_son_by_account)
|
||||||
(lookup_son_accounts)
|
(lookup_son_accounts)
|
||||||
(get_son_count)
|
(get_son_count)
|
||||||
|
|
@ -1060,10 +1156,19 @@ FC_API(graphene::app::database_api,
|
||||||
(get_sidechain_address_by_account_and_sidechain)
|
(get_sidechain_address_by_account_and_sidechain)
|
||||||
(get_sidechain_addresses_count)
|
(get_sidechain_addresses_count)
|
||||||
|
|
||||||
// workers
|
// Workers
|
||||||
|
(get_workers)
|
||||||
|
(get_workers_by_account_id)
|
||||||
(get_workers_by_account)
|
(get_workers_by_account)
|
||||||
|
(lookup_worker_accounts)
|
||||||
|
(get_worker_count)
|
||||||
|
|
||||||
// Votes
|
// Votes
|
||||||
(lookup_vote_ids)
|
(lookup_vote_ids)
|
||||||
|
(get_votes_ids)
|
||||||
|
(get_votes)
|
||||||
|
(get_voters_by_id)
|
||||||
|
(get_voters)
|
||||||
|
|
||||||
// Authority / validation
|
// Authority / validation
|
||||||
(get_transaction_hex)
|
(get_transaction_hex)
|
||||||
|
|
|
||||||
|
|
@ -541,7 +541,7 @@ void betting_market_group_object::dispatch_new_status(database& db, betting_mark
|
||||||
|
|
||||||
} } // graphene::chain
|
} } // graphene::chain
|
||||||
|
|
||||||
namespace fc {
|
namespace fc {
|
||||||
// Manually reflect betting_market_group_object to variant to properly reflect "state"
|
// Manually reflect betting_market_group_object to variant to properly reflect "state"
|
||||||
void to_variant(const graphene::chain::betting_market_group_object& betting_market_group_obj, fc::variant& v, uint32_t max_depth)
|
void to_variant(const graphene::chain::betting_market_group_object& betting_market_group_obj, fc::variant& v, uint32_t max_depth)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -466,7 +466,7 @@ void betting_market_object::on_canceled_event(database& db)
|
||||||
|
|
||||||
} } // graphene::chain
|
} } // graphene::chain
|
||||||
|
|
||||||
namespace fc {
|
namespace fc {
|
||||||
// Manually reflect betting_market_object to variant to properly reflect "state"
|
// Manually reflect betting_market_object to variant to properly reflect "state"
|
||||||
void to_variant(const graphene::chain::betting_market_object& event_obj, fc::variant& v, uint32_t max_depth)
|
void to_variant(const graphene::chain::betting_market_object& event_obj, fc::variant& v, uint32_t max_depth)
|
||||||
{
|
{
|
||||||
|
|
@ -493,4 +493,3 @@ namespace fc {
|
||||||
const_cast<int*>(event_obj.my->state_machine.current_state())[0] = (int)status;
|
const_cast<int*>(event_obj.my->state_machine.current_state())[0] = (int)status;
|
||||||
}
|
}
|
||||||
} //end namespace fc
|
} //end namespace fc
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2034,18 +2034,11 @@ void database::perform_son_tasks()
|
||||||
|
|
||||||
void update_son_params(database& db)
|
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 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 ) {
|
db.modify( gpo, []( global_property_object& gpo ) {
|
||||||
gpo.parameters.extensions.value.maximum_son_count = 7;
|
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;
|
p.pending_parameters->extensions.value.hbd_asset = p.parameters.extensions.value.hbd_asset;
|
||||||
if( !p.pending_parameters->extensions.value.hive_asset.valid() )
|
if( !p.pending_parameters->extensions.value.hive_asset.valid() )
|
||||||
p.pending_parameters->extensions.value.hive_asset = p.parameters.extensions.value.hive_asset;
|
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.parameters = std::move(*p.pending_parameters);
|
||||||
p.pending_parameters.reset();
|
p.pending_parameters.reset();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -47,7 +47,7 @@ namespace graphene { namespace chain {
|
||||||
};
|
};
|
||||||
} }
|
} }
|
||||||
|
|
||||||
FC_REFLECT_ENUM(graphene::chain::event_state,
|
FC_REFLECT_ENUM(graphene::chain::event_state,
|
||||||
(upcoming)
|
(upcoming)
|
||||||
(frozen_upcoming)
|
(frozen_upcoming)
|
||||||
(in_progress)
|
(in_progress)
|
||||||
|
|
@ -61,12 +61,12 @@ namespace graphene { namespace chain {
|
||||||
namespace msm = boost::msm;
|
namespace msm = boost::msm;
|
||||||
namespace mpl = boost::mpl;
|
namespace mpl = boost::mpl;
|
||||||
|
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
|
|
||||||
// Events -- most events happen when the witnesses publish an event_update operation with a new
|
// Events -- most events happen when the witnesses publish an event_update operation with a new
|
||||||
// status, so if they publish an event with the status set to `frozen`, we'll generate a `frozen_event`
|
// status, so if they publish an event with the status set to `frozen`, we'll generate a `frozen_event`
|
||||||
struct upcoming_event
|
struct upcoming_event
|
||||||
{
|
{
|
||||||
database& db;
|
database& db;
|
||||||
upcoming_event(database& db) : db(db) {}
|
upcoming_event(database& db) : db(db) {}
|
||||||
|
|
@ -76,12 +76,12 @@ namespace graphene { namespace chain {
|
||||||
database& db;
|
database& db;
|
||||||
in_progress_event(database& db) : db(db) {}
|
in_progress_event(database& db) : db(db) {}
|
||||||
};
|
};
|
||||||
struct frozen_event
|
struct frozen_event
|
||||||
{
|
{
|
||||||
database& db;
|
database& db;
|
||||||
frozen_event(database& db) : db(db) {}
|
frozen_event(database& db) : db(db) {}
|
||||||
};
|
};
|
||||||
struct finished_event
|
struct finished_event
|
||||||
{
|
{
|
||||||
database& db;
|
database& db;
|
||||||
finished_event(database& db) : db(db) {}
|
finished_event(database& db) : db(db) {}
|
||||||
|
|
@ -104,7 +104,7 @@ namespace graphene { namespace chain {
|
||||||
betting_market_group_resolved_event(database& db, betting_market_group_id_type resolved_group, bool was_canceled) : db(db), resolved_group(resolved_group), was_canceled(was_canceled) {}
|
betting_market_group_resolved_event(database& db, betting_market_group_id_type resolved_group, bool was_canceled) : db(db), resolved_group(resolved_group), was_canceled(was_canceled) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
// event triggered when a betting market group is closed. When we get this,
|
// event triggered when a betting market group is closed. When we get this,
|
||||||
// if all child betting market groups are closed, transition to finished
|
// if all child betting market groups are closed, transition to finished
|
||||||
struct betting_market_group_closed_event
|
struct betting_market_group_closed_event
|
||||||
{
|
{
|
||||||
|
|
@ -127,7 +127,7 @@ namespace graphene { namespace chain {
|
||||||
void on_entry(const upcoming_event& event, event_state_machine_& fsm) {
|
void on_entry(const upcoming_event& event, event_state_machine_& fsm) {
|
||||||
dlog("event ${id} -> upcoming", ("id", fsm.event_obj->id));
|
dlog("event ${id} -> upcoming", ("id", fsm.event_obj->id));
|
||||||
auto& betting_market_group_index = event.db.get_index_type<betting_market_group_object_index>().indices().get<by_event_id>();
|
auto& betting_market_group_index = event.db.get_index_type<betting_market_group_object_index>().indices().get<by_event_id>();
|
||||||
for (const betting_market_group_object& betting_market_group :
|
for (const betting_market_group_object& betting_market_group :
|
||||||
boost::make_iterator_range(betting_market_group_index.equal_range(fsm.event_obj->id)))
|
boost::make_iterator_range(betting_market_group_index.equal_range(fsm.event_obj->id)))
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
|
@ -147,7 +147,7 @@ namespace graphene { namespace chain {
|
||||||
void on_entry(const in_progress_event& event, event_state_machine_& fsm) {
|
void on_entry(const in_progress_event& event, event_state_machine_& fsm) {
|
||||||
dlog("event ${id} -> in_progress", ("id", fsm.event_obj->id));
|
dlog("event ${id} -> in_progress", ("id", fsm.event_obj->id));
|
||||||
auto& betting_market_group_index = event.db.get_index_type<betting_market_group_object_index>().indices().get<by_event_id>();
|
auto& betting_market_group_index = event.db.get_index_type<betting_market_group_object_index>().indices().get<by_event_id>();
|
||||||
for (const betting_market_group_object& betting_market_group :
|
for (const betting_market_group_object& betting_market_group :
|
||||||
boost::make_iterator_range(betting_market_group_index.equal_range(fsm.event_obj->id)))
|
boost::make_iterator_range(betting_market_group_index.equal_range(fsm.event_obj->id)))
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
|
@ -203,7 +203,7 @@ namespace graphene { namespace chain {
|
||||||
|
|
||||||
void freeze_betting_market_groups(const frozen_event& event) {
|
void freeze_betting_market_groups(const frozen_event& event) {
|
||||||
auto& betting_market_group_index = event.db.get_index_type<betting_market_group_object_index>().indices().get<by_event_id>();
|
auto& betting_market_group_index = event.db.get_index_type<betting_market_group_object_index>().indices().get<by_event_id>();
|
||||||
for (const betting_market_group_object& betting_market_group :
|
for (const betting_market_group_object& betting_market_group :
|
||||||
boost::make_iterator_range(betting_market_group_index.equal_range(event_obj->id)))
|
boost::make_iterator_range(betting_market_group_index.equal_range(event_obj->id)))
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
|
|
@ -222,7 +222,7 @@ namespace graphene { namespace chain {
|
||||||
|
|
||||||
void close_all_betting_market_groups(const finished_event& event) {
|
void close_all_betting_market_groups(const finished_event& event) {
|
||||||
auto& betting_market_group_index = event.db.get_index_type<betting_market_group_object_index>().indices().get<by_event_id>();
|
auto& betting_market_group_index = event.db.get_index_type<betting_market_group_object_index>().indices().get<by_event_id>();
|
||||||
for (const betting_market_group_object& betting_market_group :
|
for (const betting_market_group_object& betting_market_group :
|
||||||
boost::make_iterator_range(betting_market_group_index.equal_range(event_obj->id)))
|
boost::make_iterator_range(betting_market_group_index.equal_range(event_obj->id)))
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
|
|
@ -241,7 +241,7 @@ namespace graphene { namespace chain {
|
||||||
|
|
||||||
void cancel_all_betting_market_groups(const canceled_event& event) {
|
void cancel_all_betting_market_groups(const canceled_event& event) {
|
||||||
auto& betting_market_group_index = event.db.template get_index_type<betting_market_group_object_index>().indices().template get<by_event_id>();
|
auto& betting_market_group_index = event.db.template get_index_type<betting_market_group_object_index>().indices().template get<by_event_id>();
|
||||||
for (const betting_market_group_object& betting_market_group :
|
for (const betting_market_group_object& betting_market_group :
|
||||||
boost::make_iterator_range(betting_market_group_index.equal_range(event_obj->id)))
|
boost::make_iterator_range(betting_market_group_index.equal_range(event_obj->id)))
|
||||||
event.db.modify(betting_market_group, [&event](betting_market_group_object& betting_market_group_obj) {
|
event.db.modify(betting_market_group, [&event](betting_market_group_object& betting_market_group_obj) {
|
||||||
betting_market_group_obj.on_canceled_event(event.db, true);
|
betting_market_group_obj.on_canceled_event(event.db, true);
|
||||||
|
|
@ -252,15 +252,15 @@ namespace graphene { namespace chain {
|
||||||
bool all_betting_market_groups_are_closed(const betting_market_group_closed_event& event)
|
bool all_betting_market_groups_are_closed(const betting_market_group_closed_event& event)
|
||||||
{
|
{
|
||||||
auto& betting_market_group_index = event.db.get_index_type<betting_market_group_object_index>().indices().get<by_event_id>();
|
auto& betting_market_group_index = event.db.get_index_type<betting_market_group_object_index>().indices().get<by_event_id>();
|
||||||
for (const betting_market_group_object& betting_market_group :
|
for (const betting_market_group_object& betting_market_group :
|
||||||
boost::make_iterator_range(betting_market_group_index.equal_range(event_obj->id)))
|
boost::make_iterator_range(betting_market_group_index.equal_range(event_obj->id)))
|
||||||
if (betting_market_group.id != event.closed_group)
|
if (betting_market_group.id != event.closed_group)
|
||||||
{
|
{
|
||||||
betting_market_group_status status = betting_market_group.get_status();
|
betting_market_group_status status = betting_market_group.get_status();
|
||||||
if (status != betting_market_group_status::closed &&
|
if (status != betting_market_group_status::closed &&
|
||||||
status != betting_market_group_status::graded &&
|
status != betting_market_group_status::graded &&
|
||||||
status != betting_market_group_status::re_grading &&
|
status != betting_market_group_status::re_grading &&
|
||||||
status != betting_market_group_status::settled &&
|
status != betting_market_group_status::settled &&
|
||||||
status != betting_market_group_status::canceled)
|
status != betting_market_group_status::canceled)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
@ -276,7 +276,7 @@ namespace graphene { namespace chain {
|
||||||
if (event_obj->at_least_one_betting_market_group_settled)
|
if (event_obj->at_least_one_betting_market_group_settled)
|
||||||
return false;
|
return false;
|
||||||
auto& betting_market_group_index = event.db.get_index_type<betting_market_group_object_index>().indices().get<by_event_id>();
|
auto& betting_market_group_index = event.db.get_index_type<betting_market_group_object_index>().indices().get<by_event_id>();
|
||||||
for (const betting_market_group_object& betting_market_group :
|
for (const betting_market_group_object& betting_market_group :
|
||||||
boost::make_iterator_range(betting_market_group_index.equal_range(event_obj->id)))
|
boost::make_iterator_range(betting_market_group_index.equal_range(event_obj->id)))
|
||||||
if (betting_market_group.id != event.resolved_group)
|
if (betting_market_group.id != event.resolved_group)
|
||||||
if (betting_market_group.get_status() != betting_market_group_status::canceled)
|
if (betting_market_group.get_status() != betting_market_group_status::canceled)
|
||||||
|
|
@ -290,7 +290,7 @@ namespace graphene { namespace chain {
|
||||||
event_obj->at_least_one_betting_market_group_settled = true;
|
event_obj->at_least_one_betting_market_group_settled = true;
|
||||||
|
|
||||||
auto& betting_market_group_index = event.db.get_index_type<betting_market_group_object_index>().indices().get<by_event_id>();
|
auto& betting_market_group_index = event.db.get_index_type<betting_market_group_object_index>().indices().get<by_event_id>();
|
||||||
for (const betting_market_group_object& betting_market_group :
|
for (const betting_market_group_object& betting_market_group :
|
||||||
boost::make_iterator_range(betting_market_group_index.equal_range(event_obj->id))) {
|
boost::make_iterator_range(betting_market_group_index.equal_range(event_obj->id))) {
|
||||||
if (betting_market_group.id != event.resolved_group) {
|
if (betting_market_group.id != event.resolved_group) {
|
||||||
betting_market_group_status status = betting_market_group.get_status();
|
betting_market_group_status status = betting_market_group.get_status();
|
||||||
|
|
@ -344,7 +344,6 @@ namespace graphene { namespace chain {
|
||||||
{
|
{
|
||||||
FC_THROW_EXCEPTION(graphene::chain::no_transition, "No transition");
|
FC_THROW_EXCEPTION(graphene::chain::no_transition, "No transition");
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class Fsm>
|
template <class Fsm>
|
||||||
void no_transition(canceled_event const& e, Fsm&, int state)
|
void no_transition(canceled_event const& e, Fsm&, int state)
|
||||||
{
|
{
|
||||||
|
|
@ -372,7 +371,7 @@ namespace graphene { namespace chain {
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
event_object::event_object(const event_object& rhs) :
|
event_object::event_object(const event_object& rhs) :
|
||||||
graphene::db::abstract_object<event_object>(rhs),
|
graphene::db::abstract_object<event_object>(rhs),
|
||||||
name(rhs.name),
|
name(rhs.name),
|
||||||
season(rhs.season),
|
season(rhs.season),
|
||||||
|
|
@ -408,7 +407,7 @@ namespace graphene { namespace chain {
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
bool verify_event_status_constants()
|
bool verify_event_status_constants()
|
||||||
{
|
{
|
||||||
unsigned error_count = 0;
|
unsigned error_count = 0;
|
||||||
|
|
@ -443,19 +442,19 @@ namespace graphene { namespace chain {
|
||||||
dlog("Event status constants are correct");
|
dlog("Event status constants are correct");
|
||||||
else
|
else
|
||||||
wlog("There were ${count} errors in the event status constants", ("count", error_count));
|
wlog("There were ${count} errors in the event status constants", ("count", error_count));
|
||||||
|
|
||||||
return error_count == 0;
|
return error_count == 0;
|
||||||
}
|
}
|
||||||
} // end anonymous namespace
|
} // end anonymous namespace
|
||||||
|
|
||||||
event_status event_object::get_status() const
|
event_status event_object::get_status() const
|
||||||
{
|
{
|
||||||
static bool state_constants_are_correct = verify_event_status_constants();
|
static bool state_constants_are_correct = verify_event_status_constants();
|
||||||
(void)&state_constants_are_correct;
|
(void)&state_constants_are_correct;
|
||||||
event_state state = (event_state)my->state_machine.current_state()[0];
|
event_state state = (event_state)my->state_machine.current_state()[0];
|
||||||
|
|
||||||
ddump((state));
|
ddump((state));
|
||||||
|
|
||||||
switch (state)
|
switch (state)
|
||||||
{
|
{
|
||||||
case event_state::upcoming:
|
case event_state::upcoming:
|
||||||
|
|
@ -523,8 +522,8 @@ namespace graphene { namespace chain {
|
||||||
my->state_machine.process_event(betting_market_group_closed_event(db, closed_group));
|
my->state_machine.process_event(betting_market_group_closed_event(db, closed_group));
|
||||||
}
|
}
|
||||||
|
|
||||||
// These are the only statuses that can be explicitly set by witness operations. The missing
|
// These are the only statuses that can be explicitly set by witness operations. The missing
|
||||||
// status, 'settled', is automatically set when all of the betting market groups have
|
// status, 'settled', is automatically set when all of the betting market groups have
|
||||||
// settled/canceled
|
// settled/canceled
|
||||||
void event_object::dispatch_new_status(database& db, event_status new_status)
|
void event_object::dispatch_new_status(database& db, event_status new_status)
|
||||||
{
|
{
|
||||||
|
|
@ -533,16 +532,16 @@ namespace graphene { namespace chain {
|
||||||
on_upcoming_event(db);
|
on_upcoming_event(db);
|
||||||
break;
|
break;
|
||||||
case event_status::in_progress: // by witnesses when the event starts
|
case event_status::in_progress: // by witnesses when the event starts
|
||||||
on_in_progress_event(db);
|
on_in_progress_event(db);
|
||||||
break;
|
break;
|
||||||
case event_status::frozen: // by witnesses when the event needs to be frozen
|
case event_status::frozen: // by witnesses when the event needs to be frozen
|
||||||
on_frozen_event(db);
|
on_frozen_event(db);
|
||||||
break;
|
break;
|
||||||
case event_status::finished: // by witnesses when the event is complete
|
case event_status::finished: // by witnesses when the event is complete
|
||||||
on_finished_event(db);
|
on_finished_event(db);
|
||||||
break;
|
break;
|
||||||
case event_status::canceled: // by witnesses to cancel the event
|
case event_status::canceled: // by witnesses to cancel the event
|
||||||
on_canceled_event(db);
|
on_canceled_event(db);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
FC_THROW("Status ${new_status} cannot be explicitly set", ("new_status", new_status));
|
FC_THROW("Status ${new_status} cannot be explicitly set", ("new_status", new_status));
|
||||||
|
|
@ -551,7 +550,7 @@ namespace graphene { namespace chain {
|
||||||
|
|
||||||
} } // graphene::chain
|
} } // graphene::chain
|
||||||
|
|
||||||
namespace fc {
|
namespace fc {
|
||||||
// Manually reflect event_object to variant to properly reflect "state"
|
// Manually reflect event_object to variant to properly reflect "state"
|
||||||
void to_variant(const graphene::chain::event_object& event_obj, fc::variant& v, uint32_t max_depth)
|
void to_variant(const graphene::chain::event_object& event_obj, fc::variant& v, uint32_t max_depth)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -547,7 +547,7 @@ namespace graphene { namespace chain {
|
||||||
|
|
||||||
} } // graphene::chain
|
} } // graphene::chain
|
||||||
|
|
||||||
namespace fc {
|
namespace fc {
|
||||||
// Manually reflect game_object to variant to properly reflect "state"
|
// Manually reflect game_object to variant to properly reflect "state"
|
||||||
void to_variant(const graphene::chain::game_object& game_obj, fc::variant& v, uint32_t max_depth)
|
void to_variant(const graphene::chain::game_object& game_obj, fc::variant& v, uint32_t max_depth)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
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,19 +24,18 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <graphene/chain/protocol/types.hpp>
|
#include <graphene/chain/protocol/types.hpp>
|
||||||
|
#include <graphene/chain/protocol/betting_market.hpp>
|
||||||
#include <graphene/db/object.hpp>
|
#include <graphene/db/object.hpp>
|
||||||
#include <graphene/db/generic_index.hpp>
|
#include <graphene/db/generic_index.hpp>
|
||||||
#include <graphene/chain/protocol/betting_market.hpp>
|
|
||||||
#include <sstream>
|
|
||||||
|
|
||||||
#include <boost/multi_index/composite_key.hpp>
|
#include <boost/multi_index/composite_key.hpp>
|
||||||
|
#include <sstream>
|
||||||
|
|
||||||
namespace graphene { namespace chain {
|
namespace graphene { namespace chain {
|
||||||
class betting_market_object;
|
class betting_market_object;
|
||||||
class betting_market_group_object;
|
class betting_market_group_object;
|
||||||
} }
|
} }
|
||||||
|
|
||||||
namespace fc {
|
namespace fc {
|
||||||
void to_variant(const graphene::chain::betting_market_object& betting_market_obj, fc::variant& v, uint32_t max_depth = 1);
|
void to_variant(const graphene::chain::betting_market_object& betting_market_obj, fc::variant& v, uint32_t max_depth = 1);
|
||||||
void from_variant(const fc::variant& v, graphene::chain::betting_market_object& betting_market_obj, uint32_t max_depth = 1);
|
void from_variant(const fc::variant& v, graphene::chain::betting_market_object& betting_market_obj, uint32_t max_depth = 1);
|
||||||
void to_variant(const graphene::chain::betting_market_group_object& betting_market_group_obj, fc::variant& v, uint32_t max_depth = 1);
|
void to_variant(const graphene::chain::betting_market_group_object& betting_market_group_obj, fc::variant& v, uint32_t max_depth = 1);
|
||||||
|
|
@ -626,10 +625,9 @@ typedef multi_index_container<
|
||||||
|
|
||||||
typedef generic_index<betting_market_position_object, betting_market_position_multi_index_type> betting_market_position_index;
|
typedef generic_index<betting_market_position_object, betting_market_position_multi_index_type> betting_market_position_index;
|
||||||
|
|
||||||
|
|
||||||
template<typename Stream>
|
template<typename Stream>
|
||||||
inline Stream& operator<<( Stream& s, const betting_market_object& betting_market_obj )
|
inline Stream& operator<<( Stream& s, const betting_market_object& betting_market_obj )
|
||||||
{
|
{
|
||||||
// pack all fields exposed in the header in the usual way
|
// pack all fields exposed in the header in the usual way
|
||||||
// instead of calling the derived pack, just serialize the one field in the base class
|
// instead of calling the derived pack, just serialize the one field in the base class
|
||||||
// fc::raw::pack<Stream, const graphene::db::abstract_object<betting_market_object> >(s, betting_market_obj);
|
// fc::raw::pack<Stream, const graphene::db::abstract_object<betting_market_object> >(s, betting_market_obj);
|
||||||
|
|
@ -649,7 +647,7 @@ inline Stream& operator<<( Stream& s, const betting_market_object& betting_marke
|
||||||
}
|
}
|
||||||
template<typename Stream>
|
template<typename Stream>
|
||||||
inline Stream& operator>>( Stream& s, betting_market_object& betting_market_obj )
|
inline Stream& operator>>( Stream& s, betting_market_object& betting_market_obj )
|
||||||
{
|
{
|
||||||
// unpack all fields exposed in the header in the usual way
|
// unpack all fields exposed in the header in the usual way
|
||||||
//fc::raw::unpack<Stream, graphene::db::abstract_object<betting_market_object> >(s, betting_market_obj);
|
//fc::raw::unpack<Stream, graphene::db::abstract_object<betting_market_object> >(s, betting_market_obj);
|
||||||
fc::raw::unpack(s, betting_market_obj.id);
|
fc::raw::unpack(s, betting_market_obj.id);
|
||||||
|
|
@ -663,14 +661,14 @@ inline Stream& operator>>( Stream& s, betting_market_object& betting_market_obj
|
||||||
fc::raw::unpack(s, stringified_stream);
|
fc::raw::unpack(s, stringified_stream);
|
||||||
std::istringstream stream(stringified_stream);
|
std::istringstream stream(stringified_stream);
|
||||||
betting_market_obj.unpack_impl(stream);
|
betting_market_obj.unpack_impl(stream);
|
||||||
|
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
template<typename Stream>
|
template<typename Stream>
|
||||||
inline Stream& operator<<( Stream& s, const betting_market_group_object& betting_market_group_obj )
|
inline Stream& operator<<( Stream& s, const betting_market_group_object& betting_market_group_obj )
|
||||||
{
|
{
|
||||||
// pack all fields exposed in the header in the usual way
|
// pack all fields exposed in the header in the usual way
|
||||||
// instead of calling the derived pack, just serialize the one field in the base class
|
// instead of calling the derived pack, just serialize the one field in the base class
|
||||||
// fc::raw::pack<Stream, const graphene::db::abstract_object<betting_market_group_object> >(s, betting_market_group_obj);
|
// fc::raw::pack<Stream, const graphene::db::abstract_object<betting_market_group_object> >(s, betting_market_group_obj);
|
||||||
|
|
@ -693,7 +691,7 @@ inline Stream& operator<<( Stream& s, const betting_market_group_object& betting
|
||||||
}
|
}
|
||||||
template<typename Stream>
|
template<typename Stream>
|
||||||
inline Stream& operator>>( Stream& s, betting_market_group_object& betting_market_group_obj )
|
inline Stream& operator>>( Stream& s, betting_market_group_object& betting_market_group_obj )
|
||||||
{
|
{
|
||||||
// unpack all fields exposed in the header in the usual way
|
// unpack all fields exposed in the header in the usual way
|
||||||
//fc::raw::unpack<Stream, graphene::db::abstract_object<betting_market_group_object> >(s, betting_market_group_obj);
|
//fc::raw::unpack<Stream, graphene::db::abstract_object<betting_market_group_object> >(s, betting_market_group_obj);
|
||||||
fc::raw::unpack(s, betting_market_group_obj.id);
|
fc::raw::unpack(s, betting_market_group_obj.id);
|
||||||
|
|
@ -711,15 +709,113 @@ inline Stream& operator>>( Stream& s, betting_market_group_object& betting_marke
|
||||||
fc::raw::unpack(s, stringified_stream);
|
fc::raw::unpack(s, stringified_stream);
|
||||||
std::istringstream stream(stringified_stream);
|
std::istringstream stream(stringified_stream);
|
||||||
betting_market_group_obj.unpack_impl(stream);
|
betting_market_group_obj.unpack_impl(stream);
|
||||||
|
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
} } // graphene::chain
|
} } // graphene::chain
|
||||||
|
|
||||||
FC_REFLECT_DERIVED( graphene::chain::betting_market_rules_object, (graphene::db::object), (name)(description) )
|
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::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) )
|
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
|
||||||
|
|
|
||||||
|
|
@ -35,7 +35,7 @@ namespace graphene { namespace chain {
|
||||||
class event_object;
|
class event_object;
|
||||||
} }
|
} }
|
||||||
|
|
||||||
namespace fc {
|
namespace fc {
|
||||||
void to_variant(const graphene::chain::event_object& event_obj, fc::variant& v, uint32_t max_depth = 1);
|
void to_variant(const graphene::chain::event_object& event_obj, fc::variant& v, uint32_t max_depth = 1);
|
||||||
void from_variant(const fc::variant& v, graphene::chain::event_object& event_obj, uint32_t max_depth = 1);
|
void from_variant(const fc::variant& v, graphene::chain::event_object& event_obj, uint32_t max_depth = 1);
|
||||||
} //end namespace fc
|
} //end namespace fc
|
||||||
|
|
@ -56,7 +56,7 @@ class event_object : public graphene::db::abstract_object< event_object >
|
||||||
event_object& operator=(const event_object& rhs);
|
event_object& operator=(const event_object& rhs);
|
||||||
|
|
||||||
internationalized_string_type name;
|
internationalized_string_type name;
|
||||||
|
|
||||||
internationalized_string_type season;
|
internationalized_string_type season;
|
||||||
|
|
||||||
optional<time_point_sec> start_time;
|
optional<time_point_sec> start_time;
|
||||||
|
|
@ -114,7 +114,7 @@ typedef generic_index<event_object, event_object_multi_index_type> event_object_
|
||||||
|
|
||||||
template<typename Stream>
|
template<typename Stream>
|
||||||
inline Stream& operator<<( Stream& s, const event_object& event_obj )
|
inline Stream& operator<<( Stream& s, const event_object& event_obj )
|
||||||
{
|
{
|
||||||
fc_elog(fc::logger::get("event"), "In event_obj to_raw");
|
fc_elog(fc::logger::get("event"), "In event_obj to_raw");
|
||||||
// pack all fields exposed in the header in the usual way
|
// pack all fields exposed in the header in the usual way
|
||||||
// instead of calling the derived pack, just serialize the one field in the base class
|
// instead of calling the derived pack, just serialize the one field in the base class
|
||||||
|
|
@ -137,7 +137,7 @@ typedef generic_index<event_object, event_object_multi_index_type> event_object_
|
||||||
}
|
}
|
||||||
template<typename Stream>
|
template<typename Stream>
|
||||||
inline Stream& operator>>( Stream& s, event_object& event_obj )
|
inline Stream& operator>>( Stream& s, event_object& event_obj )
|
||||||
{
|
{
|
||||||
fc_elog(fc::logger::get("event"), "In event_obj from_raw");
|
fc_elog(fc::logger::get("event"), "In event_obj from_raw");
|
||||||
// unpack all fields exposed in the header in the usual way
|
// unpack all fields exposed in the header in the usual way
|
||||||
//fc::raw::unpack<Stream, graphene::db::abstract_object<event_object> >(s, event_obj);
|
//fc::raw::unpack<Stream, graphene::db::abstract_object<event_object> >(s, event_obj);
|
||||||
|
|
@ -154,10 +154,57 @@ typedef generic_index<event_object, event_object_multi_index_type> event_object_
|
||||||
fc::raw::unpack(s, stringified_stream);
|
fc::raw::unpack(s, stringified_stream);
|
||||||
std::istringstream stream(stringified_stream);
|
std::istringstream stream(stringified_stream);
|
||||||
event_obj.unpack_impl(stream);
|
event_obj.unpack_impl(stream);
|
||||||
|
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
} } // graphene::chain
|
} } // 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
|
#pragma once
|
||||||
|
|
||||||
|
#include <boost/exception/diagnostic_information.hpp>
|
||||||
#include <fc/exception/exception.hpp>
|
#include <fc/exception/exception.hpp>
|
||||||
#include <graphene/chain/protocol/protocol.hpp>
|
#include <graphene/chain/protocol/protocol.hpp>
|
||||||
|
|
||||||
|
|
@ -65,19 +66,27 @@
|
||||||
msg \
|
msg \
|
||||||
)
|
)
|
||||||
|
|
||||||
#define GRAPHENE_TRY_NOTIFY( signal, ... ) \
|
#define GRAPHENE_TRY_NOTIFY( signal, ... ) \
|
||||||
try \
|
try \
|
||||||
{ \
|
{ \
|
||||||
signal( __VA_ARGS__ ); \
|
signal( __VA_ARGS__ ); \
|
||||||
} \
|
} \
|
||||||
catch( const graphene::chain::plugin_exception& e ) \
|
catch( const graphene::chain::plugin_exception& e ) \
|
||||||
{ \
|
{ \
|
||||||
elog( "Caught plugin exception: ${e}", ("e", e.to_detail_string() ) ); \
|
elog( "Caught plugin exception: ${e}", ("e", e.to_detail_string() ) ); \
|
||||||
throw; \
|
throw; \
|
||||||
} \
|
} \
|
||||||
catch( ... ) \
|
catch( const boost::exception& e ) \
|
||||||
{ \
|
{ \
|
||||||
wlog( "Caught unexpected exception in plugin" ); \
|
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" ); \
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace graphene { namespace chain {
|
namespace graphene { namespace chain {
|
||||||
|
|
|
||||||
|
|
@ -23,10 +23,8 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
#include <graphene/chain/match_object.hpp>
|
|
||||||
#include <graphene/chain/rock_paper_scissors.hpp>
|
#include <graphene/chain/rock_paper_scissors.hpp>
|
||||||
#include <boost/multi_index/composite_key.hpp>
|
#include <graphene/db/object.hpp>
|
||||||
#include <graphene/db/flat_index.hpp>
|
|
||||||
#include <graphene/db/generic_index.hpp>
|
#include <graphene/db/generic_index.hpp>
|
||||||
#include <fc/crypto/hex.hpp>
|
#include <fc/crypto/hex.hpp>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
|
@ -35,7 +33,7 @@ namespace graphene { namespace chain {
|
||||||
class game_object;
|
class game_object;
|
||||||
} }
|
} }
|
||||||
|
|
||||||
namespace fc {
|
namespace fc {
|
||||||
void to_variant(const graphene::chain::game_object& game_obj, fc::variant& v, uint32_t max_depth = 1);
|
void to_variant(const graphene::chain::game_object& game_obj, fc::variant& v, uint32_t max_depth = 1);
|
||||||
void from_variant(const fc::variant& v, graphene::chain::game_object& game_obj, uint32_t max_depth = 1);
|
void from_variant(const fc::variant& v, graphene::chain::game_object& game_obj, uint32_t max_depth = 1);
|
||||||
} //end namespace fc
|
} //end namespace fc
|
||||||
|
|
@ -82,7 +80,7 @@ namespace graphene { namespace chain {
|
||||||
void on_move(database& db, const game_move_operation& op);
|
void on_move(database& db, const game_move_operation& op);
|
||||||
void on_timeout(database& db);
|
void on_timeout(database& db);
|
||||||
void start_game(database& db, const std::vector<account_id_type>& players);
|
void start_game(database& db, const std::vector<account_id_type>& players);
|
||||||
|
|
||||||
// serialization functions:
|
// serialization functions:
|
||||||
// for serializing to raw, go through a temporary sstream object to avoid
|
// for serializing to raw, go through a temporary sstream object to avoid
|
||||||
// having to implement serialization in the header file
|
// having to implement serialization in the header file
|
||||||
|
|
@ -116,7 +114,7 @@ namespace graphene { namespace chain {
|
||||||
|
|
||||||
template<typename Stream>
|
template<typename Stream>
|
||||||
inline Stream& operator<<( Stream& s, const game_object& game_obj )
|
inline Stream& operator<<( Stream& s, const game_object& game_obj )
|
||||||
{
|
{
|
||||||
// pack all fields exposed in the header in the usual way
|
// pack all fields exposed in the header in the usual way
|
||||||
// instead of calling the derived pack, just serialize the one field in the base class
|
// instead of calling the derived pack, just serialize the one field in the base class
|
||||||
// fc::raw::pack<Stream, const graphene::db::abstract_object<game_object> >(s, game_obj);
|
// fc::raw::pack<Stream, const graphene::db::abstract_object<game_object> >(s, game_obj);
|
||||||
|
|
@ -138,7 +136,7 @@ namespace graphene { namespace chain {
|
||||||
|
|
||||||
template<typename Stream>
|
template<typename Stream>
|
||||||
inline Stream& operator>>( Stream& s, game_object& game_obj )
|
inline Stream& operator>>( Stream& s, game_object& game_obj )
|
||||||
{
|
{
|
||||||
// unpack all fields exposed in the header in the usual way
|
// unpack all fields exposed in the header in the usual way
|
||||||
//fc::raw::unpack<Stream, graphene::db::abstract_object<game_object> >(s, game_obj);
|
//fc::raw::unpack<Stream, graphene::db::abstract_object<game_object> >(s, game_obj);
|
||||||
fc::raw::unpack(s, game_obj.id);
|
fc::raw::unpack(s, game_obj.id);
|
||||||
|
|
@ -153,10 +151,9 @@ namespace graphene { namespace chain {
|
||||||
fc::raw::unpack(s, stringified_stream);
|
fc::raw::unpack(s, stringified_stream);
|
||||||
std::istringstream stream(stringified_stream);
|
std::istringstream stream(stringified_stream);
|
||||||
game_obj.unpack_impl(stream);
|
game_obj.unpack_impl(stream);
|
||||||
|
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
} }
|
} }
|
||||||
|
|
||||||
FC_REFLECT_ENUM(graphene::chain::game_state,
|
FC_REFLECT_ENUM(graphene::chain::game_state,
|
||||||
|
|
@ -165,7 +162,52 @@ FC_REFLECT_ENUM(graphene::chain::game_state,
|
||||||
(expecting_reveal_moves)
|
(expecting_reveal_moves)
|
||||||
(game_complete))
|
(game_complete))
|
||||||
|
|
||||||
//FC_REFLECT_TYPENAME(graphene::chain::game_object) // manually serialized
|
namespace fc {
|
||||||
FC_REFLECT(graphene::chain::game_object, (players))
|
|
||||||
|
|
||||||
|
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
|
#pragma once
|
||||||
#include <graphene/chain/protocol/tournament.hpp>
|
#include <graphene/db/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/generic_index.hpp>
|
#include <graphene/db/generic_index.hpp>
|
||||||
#include <fc/crypto/hex.hpp>
|
#include <fc/crypto/hex.hpp>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
|
@ -11,11 +8,12 @@ namespace graphene { namespace chain {
|
||||||
class match_object;
|
class match_object;
|
||||||
} }
|
} }
|
||||||
|
|
||||||
namespace fc {
|
namespace fc {
|
||||||
void to_variant(const graphene::chain::match_object& match_obj, fc::variant& v, uint32_t max_depth = 1);
|
void to_variant(const graphene::chain::match_object& match_obj, fc::variant& v, uint32_t max_depth = 1);
|
||||||
void from_variant(const fc::variant& v, graphene::chain::match_object& match_obj, uint32_t max_depth = 1);
|
void from_variant(const fc::variant& v, graphene::chain::match_object& match_obj, uint32_t max_depth = 1);
|
||||||
} //end namespace fc
|
} //end namespace fc
|
||||||
|
|
||||||
|
|
||||||
namespace graphene { namespace chain {
|
namespace graphene { namespace chain {
|
||||||
class database;
|
class database;
|
||||||
using namespace graphene::db;
|
using namespace graphene::db;
|
||||||
|
|
@ -89,6 +87,7 @@ namespace graphene { namespace chain {
|
||||||
|
|
||||||
void pack_impl(std::ostream& stream) const;
|
void pack_impl(std::ostream& stream) const;
|
||||||
void unpack_impl(std::istream& stream);
|
void unpack_impl(std::istream& stream);
|
||||||
|
|
||||||
void on_initiate_match(database& db);
|
void on_initiate_match(database& db);
|
||||||
void on_game_complete(database& db, const game_object& game);
|
void on_game_complete(database& db, const game_object& game);
|
||||||
game_id_type start_next_game(database& db, match_id_type match_id);
|
game_id_type start_next_game(database& db, match_id_type match_id);
|
||||||
|
|
@ -106,7 +105,7 @@ namespace graphene { namespace chain {
|
||||||
|
|
||||||
template<typename Stream>
|
template<typename Stream>
|
||||||
inline Stream& operator<<( Stream& s, const match_object& match_obj )
|
inline Stream& operator<<( Stream& s, const match_object& match_obj )
|
||||||
{
|
{
|
||||||
// pack all fields exposed in the header in the usual way
|
// pack all fields exposed in the header in the usual way
|
||||||
// instead of calling the derived pack, just serialize the one field in the base class
|
// instead of calling the derived pack, just serialize the one field in the base class
|
||||||
// fc::raw::pack<Stream, const graphene::db::abstract_object<match_object> >(s, match_obj);
|
// fc::raw::pack<Stream, const graphene::db::abstract_object<match_object> >(s, match_obj);
|
||||||
|
|
@ -132,7 +131,7 @@ namespace graphene { namespace chain {
|
||||||
|
|
||||||
template<typename Stream>
|
template<typename Stream>
|
||||||
inline Stream& operator>>( Stream& s, match_object& match_obj )
|
inline Stream& operator>>( Stream& s, match_object& match_obj )
|
||||||
{
|
{
|
||||||
// unpack all fields exposed in the header in the usual way
|
// unpack all fields exposed in the header in the usual way
|
||||||
//fc::raw::unpack<Stream, graphene::db::abstract_object<match_object> >(s, match_obj);
|
//fc::raw::unpack<Stream, graphene::db::abstract_object<match_object> >(s, match_obj);
|
||||||
fc::raw::unpack(s, match_obj.id);
|
fc::raw::unpack(s, match_obj.id);
|
||||||
|
|
@ -151,10 +150,9 @@ namespace graphene { namespace chain {
|
||||||
fc::raw::unpack(s, stringified_stream);
|
fc::raw::unpack(s, stringified_stream);
|
||||||
std::istringstream stream(stringified_stream);
|
std::istringstream stream(stringified_stream);
|
||||||
match_obj.unpack_impl(stream);
|
match_obj.unpack_impl(stream);
|
||||||
|
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
} }
|
} }
|
||||||
|
|
||||||
FC_REFLECT_ENUM(graphene::chain::match_state,
|
FC_REFLECT_ENUM(graphene::chain::match_state,
|
||||||
|
|
@ -162,6 +160,52 @@ FC_REFLECT_ENUM(graphene::chain::match_state,
|
||||||
(match_in_progress)
|
(match_in_progress)
|
||||||
(match_complete))
|
(match_complete))
|
||||||
|
|
||||||
//FC_REFLECT_TYPENAME(graphene::chain::match_object) // manually serialized
|
namespace fc {
|
||||||
FC_REFLECT(graphene::chain::match_object, (players))
|
|
||||||
|
|
||||||
|
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::betting_market_position_id_type )
|
||||||
FC_REFLECT_TYPENAME( graphene::chain::global_betting_statistics_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::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_permission_id_type )
|
||||||
FC_REFLECT_TYPENAME( graphene::chain::custom_account_authority_id_type )
|
FC_REFLECT_TYPENAME( graphene::chain::custom_account_authority_id_type )
|
||||||
FC_REFLECT_TYPENAME( graphene::chain::offer_history_id_type )
|
FC_REFLECT_TYPENAME( graphene::chain::offer_history_id_type )
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,7 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
#include <graphene/chain/protocol/tournament.hpp>
|
#include <graphene/chain/protocol/tournament.hpp>
|
||||||
#include <graphene/chain/rock_paper_scissors.hpp>
|
|
||||||
#include <boost/multi_index/composite_key.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 <graphene/db/generic_index.hpp>
|
||||||
#include <fc/crypto/hex.hpp>
|
#include <fc/crypto/hex.hpp>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
|
@ -11,7 +10,7 @@ namespace graphene { namespace chain {
|
||||||
class tournament_object;
|
class tournament_object;
|
||||||
} }
|
} }
|
||||||
|
|
||||||
namespace fc {
|
namespace fc {
|
||||||
void to_variant(const graphene::chain::tournament_object& tournament_obj, fc::variant& v, uint32_t max_depth = 1);
|
void to_variant(const graphene::chain::tournament_object& tournament_obj, fc::variant& v, uint32_t max_depth = 1);
|
||||||
void from_variant(const fc::variant& v, graphene::chain::tournament_object& tournament_obj, uint32_t max_depth = 1);
|
void from_variant(const fc::variant& v, graphene::chain::tournament_object& tournament_obj, uint32_t max_depth = 1);
|
||||||
} //end namespace fc
|
} //end namespace fc
|
||||||
|
|
@ -154,10 +153,9 @@ namespace graphene { namespace chain {
|
||||||
> tournament_details_object_multi_index_type;
|
> tournament_details_object_multi_index_type;
|
||||||
typedef generic_index<tournament_details_object, tournament_details_object_multi_index_type> tournament_details_index;
|
typedef generic_index<tournament_details_object, tournament_details_object_multi_index_type> tournament_details_index;
|
||||||
|
|
||||||
|
|
||||||
template<typename Stream>
|
template<typename Stream>
|
||||||
inline Stream& operator<<( Stream& s, const tournament_object& tournament_obj )
|
inline Stream& operator<<( Stream& s, const tournament_object& tournament_obj )
|
||||||
{
|
{
|
||||||
fc_elog(fc::logger::get("tournament"), "In tournament_obj to_raw");
|
fc_elog(fc::logger::get("tournament"), "In tournament_obj to_raw");
|
||||||
// pack all fields exposed in the header in the usual way
|
// pack all fields exposed in the header in the usual way
|
||||||
// instead of calling the derived pack, just serialize the one field in the base class
|
// instead of calling the derived pack, just serialize the one field in the base class
|
||||||
|
|
@ -175,15 +173,16 @@ namespace graphene { namespace chain {
|
||||||
std::ostringstream stream;
|
std::ostringstream stream;
|
||||||
tournament_obj.pack_impl(stream);
|
tournament_obj.pack_impl(stream);
|
||||||
std::string stringified_stream(stream.str());
|
std::string stringified_stream(stream.str());
|
||||||
fc_elog(fc::logger::get("tournament"), "Serialized state ${state} to bytes ${bytes}",
|
fc_elog(fc::logger::get("tournament"), "Serialized state ${state} to bytes ${bytes}",
|
||||||
("state", tournament_obj.get_state())("bytes", fc::to_hex(stringified_stream.c_str(), stringified_stream.size())));
|
("state", tournament_obj.get_state())("bytes", fc::to_hex(stringified_stream.c_str(), stringified_stream.size())));
|
||||||
fc::raw::pack(s, stream.str());
|
fc::raw::pack(s, stream.str());
|
||||||
|
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename Stream>
|
template<typename Stream>
|
||||||
inline Stream& operator>>( Stream& s, tournament_object& tournament_obj )
|
inline Stream& operator>>( Stream& s, tournament_object& tournament_obj )
|
||||||
{
|
{
|
||||||
fc_elog(fc::logger::get("tournament"), "In tournament_obj from_raw");
|
fc_elog(fc::logger::get("tournament"), "In tournament_obj from_raw");
|
||||||
// unpack all fields exposed in the header in the usual way
|
// unpack all fields exposed in the header in the usual way
|
||||||
//fc::raw::unpack<Stream, graphene::db::abstract_object<tournament_object> >(s, tournament_obj);
|
//fc::raw::unpack<Stream, graphene::db::abstract_object<tournament_object> >(s, tournament_obj);
|
||||||
|
|
@ -201,9 +200,9 @@ namespace graphene { namespace chain {
|
||||||
fc::raw::unpack(s, stringified_stream);
|
fc::raw::unpack(s, stringified_stream);
|
||||||
std::istringstream stream(stringified_stream);
|
std::istringstream stream(stringified_stream);
|
||||||
tournament_obj.unpack_impl(stream);
|
tournament_obj.unpack_impl(stream);
|
||||||
fc_elog(fc::logger::get("tournament"), "Deserialized state ${state} from bytes ${bytes}",
|
fc_elog(fc::logger::get("tournament"), "Deserialized state ${state} from bytes ${bytes}",
|
||||||
("state", tournament_obj.get_state())("bytes", fc::to_hex(stringified_stream.c_str(), stringified_stream.size())));
|
("state", tournament_obj.get_state())("bytes", fc::to_hex(stringified_stream.c_str(), stringified_stream.size())));
|
||||||
|
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -230,8 +229,6 @@ namespace graphene { namespace chain {
|
||||||
|
|
||||||
flat_set<account_id_type> before_account_ids;
|
flat_set<account_id_type> before_account_ids;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
} }
|
} }
|
||||||
|
|
||||||
FC_REFLECT_DERIVED(graphene::chain::tournament_details_object, (graphene::db::object),
|
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)
|
(payers)
|
||||||
(players_payers)
|
(players_payers)
|
||||||
(matches))
|
(matches))
|
||||||
//FC_REFLECT_TYPENAME(graphene::chain::tournament_object) // manually serialized
|
|
||||||
FC_REFLECT(graphene::chain::tournament_object, (creator))
|
|
||||||
FC_REFLECT_ENUM(graphene::chain::tournament_state,
|
FC_REFLECT_ENUM(graphene::chain::tournament_state,
|
||||||
(accepting_registrations)
|
(accepting_registrations)
|
||||||
(awaiting_start)
|
(awaiting_start)
|
||||||
|
|
@ -249,3 +245,52 @@ FC_REFLECT_ENUM(graphene::chain::tournament_state,
|
||||||
(registration_period_expired)
|
(registration_period_expired)
|
||||||
(concluded))
|
(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) )
|
||||||
|
|
@ -362,7 +362,7 @@ namespace graphene { namespace chain {
|
||||||
|
|
||||||
} } // graphene::chain
|
} } // graphene::chain
|
||||||
|
|
||||||
namespace fc {
|
namespace fc {
|
||||||
// Manually reflect match_object to variant to properly reflect "state"
|
// Manually reflect match_object to variant to properly reflect "state"
|
||||||
void to_variant(const graphene::chain::match_object& match_obj, fc::variant& v, uint32_t max_depth)
|
void to_variant(const graphene::chain::match_object& match_obj, fc::variant& v, uint32_t max_depth)
|
||||||
{ try {
|
{ try {
|
||||||
|
|
|
||||||
|
|
@ -192,6 +192,16 @@ namespace graphene { namespace chain {
|
||||||
FC_ASSERT( *extensions.value.betting_rake_fee_percentage <= TOURNAMENT_MAXIMAL_RAKE_FEE_PERCENTAGE,
|
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));
|
"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
|
} } // graphene::chain
|
||||||
|
|
|
||||||
|
|
@ -721,7 +721,7 @@ namespace graphene { namespace chain {
|
||||||
}
|
}
|
||||||
} } // graphene::chain
|
} } // graphene::chain
|
||||||
|
|
||||||
namespace fc {
|
namespace fc {
|
||||||
// Manually reflect tournament_object to variant to properly reflect "state"
|
// Manually reflect tournament_object to variant to properly reflect "state"
|
||||||
void to_variant(const graphene::chain::tournament_object& tournament_obj, fc::variant& v, uint32_t max_depth)
|
void to_variant(const graphene::chain::tournament_object& tournament_obj, fc::variant& v, uint32_t max_depth)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -34,10 +34,10 @@ namespace graphene { namespace db {
|
||||||
|
|
||||||
struct undo_state
|
struct undo_state
|
||||||
{
|
{
|
||||||
unordered_map<object_id_type, unique_ptr<object> > old_values;
|
unordered_map<object_id_type, unique_ptr<object> > old_values;
|
||||||
unordered_map<object_id_type, object_id_type> old_index_next_ids;
|
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;
|
unordered_map<object_id_type, unique_ptr<object> > removed;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1 +1 @@
|
||||||
Subproject commit 488883921936139e8734b99822d3a589afe80da1
|
Subproject commit 6171e973c7fcfc9e0a39eaee2f05da84416a90e6
|
||||||
|
|
@ -79,123 +79,138 @@ account_history_plugin_impl::~account_history_plugin_impl()
|
||||||
|
|
||||||
void account_history_plugin_impl::update_account_histories( const signed_block& b )
|
void account_history_plugin_impl::update_account_histories( const signed_block& b )
|
||||||
{
|
{
|
||||||
graphene::chain::database& db = database();
|
try \
|
||||||
vector<optional< operation_history_object > >& hist = db.get_applied_operations();
|
{
|
||||||
bool is_first = true;
|
graphene::chain::database& db = database();
|
||||||
auto skip_oho_id = [&is_first,&db,this]() {
|
vector<optional< operation_history_object > >& hist = db.get_applied_operations();
|
||||||
if( is_first && db._undo_db.enabled() ) // this ensures that the current id is rolled back on undo
|
bool is_first = true;
|
||||||
{
|
auto skip_oho_id = [&is_first,&db,this]() {
|
||||||
db.remove( db.create<operation_history_object>( []( operation_history_object& obj) {} ) );
|
if( is_first && db._undo_db.enabled() ) // this ensures that the current id is rolled back on undo
|
||||||
is_first = false;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
_oho_index->use_next_id();
|
|
||||||
};
|
|
||||||
|
|
||||||
for( optional< operation_history_object >& o_op : hist )
|
|
||||||
{
|
|
||||||
optional<operation_history_object> oho;
|
|
||||||
|
|
||||||
auto create_oho = [&]() {
|
|
||||||
is_first = false;
|
|
||||||
operation_history_object result = db.create<operation_history_object>( [&]( operation_history_object& h )
|
|
||||||
{
|
{
|
||||||
if( o_op.valid() )
|
db.remove( db.create<operation_history_object>( []( operation_history_object& obj) {} ) );
|
||||||
h = *o_op;
|
is_first = false;
|
||||||
} );
|
}
|
||||||
o_op->id = result.id;
|
else
|
||||||
return optional<operation_history_object>(result);
|
_oho_index->use_next_id();
|
||||||
};
|
};
|
||||||
|
|
||||||
if( !o_op.valid() || ( _max_ops_per_account == 0 && _partial_operations ) )
|
for( optional< operation_history_object >& o_op : hist )
|
||||||
{
|
{
|
||||||
// Note: the 2nd and 3rd checks above are for better performance, when the db is not clean,
|
optional<operation_history_object> oho;
|
||||||
// they will break consistency of account_stats.total_ops and removed_ops and most_recent_op
|
|
||||||
skip_oho_id();
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
else if( !_partial_operations )
|
|
||||||
// add to the operation history index
|
|
||||||
oho = create_oho();
|
|
||||||
|
|
||||||
const operation_history_object& op = *o_op;
|
auto create_oho = [&]() {
|
||||||
|
is_first = false;
|
||||||
// get the set of accounts this operation applies to
|
operation_history_object result = db.create<operation_history_object>( [&]( operation_history_object& h )
|
||||||
flat_set<account_id_type> impacted;
|
|
||||||
vector<authority> other;
|
|
||||||
// fee payer is added here
|
|
||||||
operation_get_required_authorities( op.op, impacted, impacted, other,
|
|
||||||
MUST_IGNORE_CUSTOM_OP_REQD_AUTHS( db.head_block_time() ) );
|
|
||||||
|
|
||||||
if( op.op.which() == operation::tag< account_create_operation >::value )
|
|
||||||
impacted.insert( op.result.get<object_id_type>() );
|
|
||||||
else
|
|
||||||
graphene::chain::operation_get_impacted_accounts( op.op, impacted,
|
|
||||||
MUST_IGNORE_CUSTOM_OP_REQD_AUTHS(db.head_block_time()) );
|
|
||||||
if( op.op.which() == operation::tag< lottery_end_operation >::value )
|
|
||||||
{
|
|
||||||
auto lop = op.op.get< lottery_end_operation >();
|
|
||||||
auto asset_object = lop.lottery( db );
|
|
||||||
impacted.insert( asset_object.issuer );
|
|
||||||
for( auto benefactor : asset_object.lottery_options->benefactors )
|
|
||||||
impacted.insert( benefactor.id );
|
|
||||||
}
|
|
||||||
|
|
||||||
for( auto& a : other )
|
|
||||||
for( auto& item : a.account_auths )
|
|
||||||
impacted.insert( item.first );
|
|
||||||
|
|
||||||
// be here, either _max_ops_per_account > 0, or _partial_operations == false, or both
|
|
||||||
// if _partial_operations == false, oho should have been created above
|
|
||||||
// so the only case should be checked here is:
|
|
||||||
// whether need to create oho if _max_ops_per_account > 0 and _partial_operations == true
|
|
||||||
|
|
||||||
// for each operation this account applies to that is in the config link it into the history
|
|
||||||
if( _tracked_accounts.size() == 0 ) // tracking all accounts
|
|
||||||
{
|
|
||||||
// if tracking all accounts, when impacted is not empty (although it will always be),
|
|
||||||
// still need to create oho if _max_ops_per_account > 0 and _partial_operations == true
|
|
||||||
// so always need to create oho if not done
|
|
||||||
if (!impacted.empty() && !oho.valid()) { oho = create_oho(); }
|
|
||||||
|
|
||||||
if( _max_ops_per_account > 0 )
|
|
||||||
{
|
|
||||||
// Note: the check above is for better performance, when the db is not clean,
|
|
||||||
// it breaks consistency of account_stats.total_ops and removed_ops and most_recent_op,
|
|
||||||
// but it ensures it's safe to remove old entries in add_account_history(...)
|
|
||||||
for( auto& account_id : impacted )
|
|
||||||
{
|
{
|
||||||
// we don't do index_account_keys here anymore, because
|
if( o_op.valid() )
|
||||||
// that indexing now happens in observers' post_evaluate()
|
h = *o_op;
|
||||||
|
} );
|
||||||
|
o_op->id = result.id;
|
||||||
|
return optional<operation_history_object>(result);
|
||||||
|
};
|
||||||
|
|
||||||
// add history
|
if( !o_op.valid() || ( _max_ops_per_account == 0 && _partial_operations ) )
|
||||||
add_account_history( account_id, oho->id );
|
{
|
||||||
}
|
// Note: the 2nd and 3rd checks above are for better performance, when the db is not clean,
|
||||||
|
// they will break consistency of account_stats.total_ops and removed_ops and most_recent_op
|
||||||
|
skip_oho_id();
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
}
|
else if( !_partial_operations )
|
||||||
else // tracking a subset of accounts
|
// add to the operation history index
|
||||||
{
|
oho = create_oho();
|
||||||
// whether need to create oho if _max_ops_per_account > 0 and _partial_operations == true ?
|
|
||||||
// the answer: only need to create oho if a tracked account is impacted and need to save history
|
|
||||||
|
|
||||||
if( _max_ops_per_account > 0 )
|
const operation_history_object& op = *o_op;
|
||||||
|
|
||||||
|
// get the set of accounts this operation applies to
|
||||||
|
flat_set<account_id_type> impacted;
|
||||||
|
vector<authority> other;
|
||||||
|
// fee payer is added here
|
||||||
|
operation_get_required_authorities( op.op, impacted, impacted, other,
|
||||||
|
MUST_IGNORE_CUSTOM_OP_REQD_AUTHS( db.head_block_time() ) );
|
||||||
|
|
||||||
|
if( op.op.which() == operation::tag< account_create_operation >::value )
|
||||||
|
impacted.insert( op.result.get<object_id_type>() );
|
||||||
|
else
|
||||||
|
graphene::chain::operation_get_impacted_accounts( op.op, impacted,
|
||||||
|
MUST_IGNORE_CUSTOM_OP_REQD_AUTHS(db.head_block_time()) );
|
||||||
|
if( op.op.which() == operation::tag< lottery_end_operation >::value )
|
||||||
{
|
{
|
||||||
// Note: the check above is for better performance, when the db is not clean,
|
auto lop = op.op.get< lottery_end_operation >();
|
||||||
// it breaks consistency of account_stats.total_ops and removed_ops and most_recent_op,
|
auto asset_object = lop.lottery( db );
|
||||||
// but it ensures it's safe to remove old entries in add_account_history(...)
|
impacted.insert( asset_object.issuer );
|
||||||
for( auto account_id : _tracked_accounts )
|
for( auto benefactor : asset_object.lottery_options->benefactors )
|
||||||
|
impacted.insert( benefactor.id );
|
||||||
|
}
|
||||||
|
|
||||||
|
for( auto& a : other )
|
||||||
|
for( auto& item : a.account_auths )
|
||||||
|
impacted.insert( item.first );
|
||||||
|
|
||||||
|
// be here, either _max_ops_per_account > 0, or _partial_operations == false, or both
|
||||||
|
// if _partial_operations == false, oho should have been created above
|
||||||
|
// so the only case should be checked here is:
|
||||||
|
// whether need to create oho if _max_ops_per_account > 0 and _partial_operations == true
|
||||||
|
|
||||||
|
// for each operation this account applies to that is in the config link it into the history
|
||||||
|
if( _tracked_accounts.size() == 0 ) // tracking all accounts
|
||||||
|
{
|
||||||
|
// if tracking all accounts, when impacted is not empty (although it will always be),
|
||||||
|
// still need to create oho if _max_ops_per_account > 0 and _partial_operations == true
|
||||||
|
// so always need to create oho if not done
|
||||||
|
if (!impacted.empty() && !oho.valid()) { oho = create_oho(); }
|
||||||
|
|
||||||
|
if( _max_ops_per_account > 0 )
|
||||||
{
|
{
|
||||||
if( impacted.find( account_id ) != impacted.end() )
|
// Note: the check above is for better performance, when the db is not clean,
|
||||||
|
// it breaks consistency of account_stats.total_ops and removed_ops and most_recent_op,
|
||||||
|
// but it ensures it's safe to remove old entries in add_account_history(...)
|
||||||
|
for( auto& account_id : impacted )
|
||||||
{
|
{
|
||||||
if (!oho.valid()) { oho = create_oho(); }
|
// we don't do index_account_keys here anymore, because
|
||||||
|
// that indexing now happens in observers' post_evaluate()
|
||||||
|
|
||||||
// add history
|
// add history
|
||||||
add_account_history( account_id, oho->id );
|
add_account_history( account_id, oho->id );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else // tracking a subset of accounts
|
||||||
|
{
|
||||||
|
// whether need to create oho if _max_ops_per_account > 0 and _partial_operations == true ?
|
||||||
|
// the answer: only need to create oho if a tracked account is impacted and need to save history
|
||||||
|
|
||||||
|
if( _max_ops_per_account > 0 )
|
||||||
|
{
|
||||||
|
// Note: the check above is for better performance, when the db is not clean,
|
||||||
|
// it breaks consistency of account_stats.total_ops and removed_ops and most_recent_op,
|
||||||
|
// but it ensures it's safe to remove old entries in add_account_history(...)
|
||||||
|
for( auto account_id : _tracked_accounts )
|
||||||
|
{
|
||||||
|
if( impacted.find( account_id ) != impacted.end() )
|
||||||
|
{
|
||||||
|
if (!oho.valid()) { oho = create_oho(); }
|
||||||
|
// add history
|
||||||
|
add_account_history( account_id, oho->id );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (_partial_operations && ! oho.valid())
|
||||||
|
skip_oho_id();
|
||||||
}
|
}
|
||||||
if (_partial_operations && ! oho.valid())
|
}
|
||||||
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(...)" );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -29,7 +29,6 @@
|
||||||
|
|
||||||
#include <graphene/chain/protocol/types.hpp>
|
#include <graphene/chain/protocol/types.hpp>
|
||||||
#include <graphene/chain/protocol/asset.hpp>
|
#include <graphene/chain/protocol/asset.hpp>
|
||||||
#include <graphene/chain/event_object.hpp>
|
|
||||||
#include <graphene/chain/operation_history_object.hpp>
|
#include <graphene/chain/operation_history_object.hpp>
|
||||||
|
|
||||||
#include <graphene/affiliate_stats/affiliate_stats_objects.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:
|
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>();
|
const auto &idx = db->get_index_type<event_object_index>();
|
||||||
auto iter = persistent_events_by_event_id.find(id.as<event_id_type>());
|
const auto &aidx = dynamic_cast<const base_primary_index &>(idx);
|
||||||
if (iter != persistent_events_by_event_id.end())
|
const auto &refs = aidx.get_secondary_index<detail::persistent_event_index>();
|
||||||
return iter->ephemeral_event_object.to_variant();
|
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
|
else
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
case bet_id_type::type_id:
|
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>();
|
const auto &idx = db->get_index_type<bet_object_index>();
|
||||||
auto iter = persistent_bets_by_bet_id.find(id.as<bet_id_type>());
|
const auto &aidx = dynamic_cast<const base_primary_index &>(idx);
|
||||||
if (iter != persistent_bets_by_bet_id.end())
|
const auto &refs = aidx.get_secondary_index<detail::persistent_bet_index>();
|
||||||
return iter->ephemeral_bet_object.to_variant();
|
auto iter = refs.internal.find(id.as<bet_id_type>());
|
||||||
|
if (iter != refs.internal.end())
|
||||||
|
return iter->second.ephemeral_bet_object.to_variant();
|
||||||
else
|
else
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
case betting_market_object::type_id:
|
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>();
|
const auto &idx = db->get_index_type<betting_market_object_index>();
|
||||||
auto iter = persistent_betting_markets_by_betting_market_id.find(id.as<betting_market_id_type>());
|
const auto &aidx = dynamic_cast<const base_primary_index &>(idx);
|
||||||
if (iter != persistent_betting_markets_by_betting_market_id.end())
|
const auto &refs = aidx.get_secondary_index<detail::persistent_betting_market_index>();
|
||||||
return iter->ephemeral_betting_market_object.to_variant();
|
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
|
else
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
case betting_market_group_object::type_id:
|
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>();
|
const auto &idx = db->get_index_type<betting_market_group_object_index>();
|
||||||
auto iter = persistent_betting_market_groups_by_betting_market_group_id.find(id.as<betting_market_group_id_type>());
|
const auto &aidx = dynamic_cast<const base_primary_index &>(idx);
|
||||||
if (iter != persistent_betting_market_groups_by_betting_market_group_id.end())
|
const auto &refs = aidx.get_secondary_index<detail::persistent_betting_market_group_index>();
|
||||||
return iter->ephemeral_betting_market_group_object.to_variant();
|
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
|
else
|
||||||
return {};
|
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::vector<matched_bet_object> result;
|
||||||
std::shared_ptr<graphene::chain::database> db = app.chain_database();
|
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>();
|
const auto &idx = db->get_index_type<bet_object_index>();
|
||||||
auto iter = persistent_bets_by_bettor_id.lower_bound(std::make_tuple(bettor_id, true));
|
const auto &aidx = dynamic_cast<const base_primary_index &>(idx);
|
||||||
while (iter != persistent_bets_by_bettor_id.end() &&
|
const auto &refs = aidx.get_secondary_index<detail::persistent_bet_index>();
|
||||||
iter->get_bettor_id() == bettor_id &&
|
|
||||||
iter->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;
|
|
||||||
result.emplace_back(std::move(match));
|
|
||||||
|
|
||||||
++iter;
|
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 = 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));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
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::vector<matched_bet_object> result;
|
||||||
std::shared_ptr<graphene::chain::database> db = app.chain_database();
|
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>();
|
const auto &idx = db->get_index_type<bet_object_index>();
|
||||||
persistent_bet_multi_index_type::index<by_bettor_id>::type::iterator iter;
|
const auto &aidx = dynamic_cast<const base_primary_index &>(idx);
|
||||||
if (start == bet_id_type())
|
const auto &refs = aidx.get_secondary_index<detail::persistent_bet_index>();
|
||||||
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() &&
|
|
||||||
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;
|
|
||||||
result.emplace_back(std::move(match));
|
|
||||||
|
|
||||||
++iter;
|
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 = 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));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
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
|
* 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.
|
* 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;
|
void persistent_bet_index::object_inserted(const object& obj)
|
||||||
//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)
|
|
||||||
{
|
{
|
||||||
const bet_object& bet_obj = *boost::polymorphic_downcast<const bet_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) {
|
if(0 == internal.count(bet_obj.id))
|
||||||
saved_bet_obj.ephemeral_bet_object = bet_obj;
|
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);
|
const bet_object& bet_obj = *boost::polymorphic_downcast<const bet_object*>(&after);
|
||||||
auto iter = persistent_bets_by_bet_id.find(bet_obj.id);
|
auto iter = internal.find(bet_obj.id);
|
||||||
assert (iter != persistent_bets_by_bet_id.end());
|
assert (iter != internal.end());
|
||||||
if (iter != persistent_bets_by_bet_id.end())
|
if (iter != internal.end())
|
||||||
db.modify(*iter, [&](persistent_bet_object& saved_bet_obj) {
|
iter->second = bet_obj;
|
||||||
saved_bet_obj.ephemeral_bet_object = bet_obj;
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//////////// end bet_object ///////////////////
|
//////////// 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;
|
void persistent_betting_market_index::object_inserted(const object& obj)
|
||||||
//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)
|
|
||||||
{
|
{
|
||||||
const betting_market_object& betting_market_obj = *boost::polymorphic_downcast<const betting_market_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) {
|
if(0 == ephemeral_betting_market_object.count(betting_market_obj.id))
|
||||||
saved_betting_market_obj.ephemeral_betting_market_object = betting_market_obj;
|
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);
|
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);
|
auto iter = ephemeral_betting_market_object.find(betting_market_obj.id);
|
||||||
assert (iter != persistent_betting_markets_by_betting_market_id.end());
|
assert (iter != ephemeral_betting_market_object.end());
|
||||||
if (iter != persistent_betting_markets_by_betting_market_id.end())
|
if (iter != ephemeral_betting_market_object.end())
|
||||||
db.modify(*iter, [&](persistent_betting_market_object& saved_betting_market_obj) {
|
iter->second = betting_market_obj;
|
||||||
saved_betting_market_obj.ephemeral_betting_market_object = betting_market_obj;
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//////////// end betting_market_object ///////////////////
|
//////////// 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;
|
void persistent_betting_market_group_index::object_inserted(const object& obj)
|
||||||
//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)
|
|
||||||
{
|
{
|
||||||
const betting_market_group_object& betting_market_group_obj = *boost::polymorphic_downcast<const betting_market_group_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) {
|
if(0 == internal.count(betting_market_group_obj.id))
|
||||||
saved_betting_market_group_obj.ephemeral_betting_market_group_object = betting_market_group_obj;
|
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);
|
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);
|
auto iter = internal.find(betting_market_group_obj.id);
|
||||||
assert (iter != persistent_betting_market_groups_by_betting_market_group_id.end());
|
assert (iter != internal.end());
|
||||||
if (iter != persistent_betting_market_groups_by_betting_market_group_id.end())
|
if (iter != internal.end())
|
||||||
db.modify(*iter, [&](persistent_betting_market_group_object& saved_betting_market_group_obj) {
|
iter->second = betting_market_group_obj;
|
||||||
saved_betting_market_group_obj.ephemeral_betting_market_group_object = betting_market_group_obj;
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//////////// end betting_market_group_object ///////////////////
|
//////////// 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;
|
void persistent_event_index::object_inserted(const object& obj)
|
||||||
//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)
|
|
||||||
{
|
{
|
||||||
const event_object& event_obj = *boost::polymorphic_downcast<const event_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) {
|
if(0 == ephemeral_event_object.count(event_obj.id))
|
||||||
saved_event_obj.ephemeral_event_object = event_obj;
|
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);
|
const event_object& event_obj = *boost::polymorphic_downcast<const event_object*>(&after);
|
||||||
auto iter = persistent_events_by_event_id.find(event_obj.id);
|
auto iter = ephemeral_event_object.find(event_obj.id);
|
||||||
assert (iter != persistent_events_by_event_id.end());
|
assert (iter != ephemeral_event_object.end());
|
||||||
if (iter != persistent_events_by_event_id.end())
|
if (iter != ephemeral_event_object.end())
|
||||||
db.modify(*iter, [&](persistent_event_object& saved_event_obj) {
|
iter->second = event_obj;
|
||||||
saved_event_obj.ephemeral_event_object = event_obj;
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//////////// end event_object ///////////////////
|
//////////// end event_object ///////////////////
|
||||||
|
|
@ -207,7 +144,6 @@ class bookie_plugin_impl
|
||||||
{ }
|
{ }
|
||||||
virtual ~bookie_plugin_impl();
|
virtual ~bookie_plugin_impl();
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Called After a block has been applied and committed. The callback
|
* Called After a block has been applied and committed. The callback
|
||||||
* should not yield and should execute quickly.
|
* 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;
|
const asset& amount_bet = bet_matched_op.amount_bet;
|
||||||
// object may no longer exist
|
// object may no longer exist
|
||||||
//const bet_object& bet = bet_matched_op.bet_id(db);
|
//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>();
|
const auto &idx_bet_object = db.get_index_type<bet_object_index>();
|
||||||
auto bet_iter = persistent_bets_by_bet_id.find(bet_matched_op.bet_id);
|
const auto &aidx_bet_object = dynamic_cast<const base_primary_index &>(idx_bet_object);
|
||||||
assert(bet_iter != persistent_bets_by_bet_id.end());
|
const auto &refs_bet_object = aidx_bet_object.get_secondary_index<detail::persistent_bet_index>();
|
||||||
if (bet_iter != persistent_bets_by_bet_id.end())
|
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 ) {
|
bet_iter->second.amount_matched += amount_bet.amount;
|
||||||
obj.amount_matched += amount_bet.amount;
|
if (is_operation_history_object_stored(op.id))
|
||||||
if (is_operation_history_object_stored(op.id))
|
bet_iter->second.associated_operations.emplace_back(op.id);
|
||||||
obj.associated_operations.emplace_back(op.id);
|
|
||||||
});
|
|
||||||
const bet_object& bet_obj = bet_iter->ephemeral_bet_object;
|
|
||||||
|
|
||||||
auto& persistent_betting_market_idx = db.get_index_type<persistent_betting_market_index>().indices().get<by_betting_market_id>();
|
const bet_object& bet_obj = bet_iter->second.ephemeral_bet_object;
|
||||||
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;
|
|
||||||
|
|
||||||
auto& persistent_betting_market_group_idx = db.get_index_type<persistent_betting_market_group_index>().indices().get<by_betting_market_group_id>();
|
const auto &idx_betting_market = db.get_index_type<betting_market_object_index>();
|
||||||
auto persistent_betting_market_group_object_iter = persistent_betting_market_group_idx.find(betting_market.group_id);
|
const auto &aidx_betting_market = dynamic_cast<const base_primary_index &>(idx_betting_market);
|
||||||
FC_ASSERT(persistent_betting_market_group_object_iter != persistent_betting_market_group_idx.end());
|
const auto &refs_betting_market = aidx_betting_market.get_secondary_index<detail::persistent_betting_market_index>();
|
||||||
const betting_market_group_object& betting_market_group = persistent_betting_market_group_object_iter->ephemeral_betting_market_group_object;
|
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
|
// if the object is still in the main database, keep the running total there
|
||||||
// otherwise, add it directly to the persistent version
|
// 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;
|
obj.total_matched_bets_amount += amount_bet.amount;
|
||||||
});
|
});
|
||||||
else
|
else
|
||||||
db.modify( *persistent_betting_market_group_object_iter, [&]( persistent_betting_market_group_object& obj ){
|
persistent_betting_market_group_object_iter->second.total_matched_bets_amount += amount_bet.amount;
|
||||||
obj.ephemeral_betting_market_group_object.total_matched_bets_amount += amount_bet.amount;
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if( op.op.which() == operation::tag<event_create_operation>::value )
|
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 )
|
else if ( op.op.which() == operation::tag<bet_canceled_operation>::value )
|
||||||
{
|
{
|
||||||
const bet_canceled_operation& bet_canceled_op = op.op.get<bet_canceled_operation>();
|
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>();
|
const auto &idx_bet_object = db.get_index_type<bet_object_index>();
|
||||||
auto bet_iter = persistent_bets_by_bet_id.find(bet_canceled_op.bet_id);
|
const auto &aidx_bet_object = dynamic_cast<const base_primary_index &>(idx_bet_object);
|
||||||
assert(bet_iter != persistent_bets_by_bet_id.end());
|
const auto &refs_bet_object = aidx_bet_object.get_secondary_index<detail::persistent_bet_index>();
|
||||||
if (bet_iter != persistent_bets_by_bet_id.end())
|
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",
|
// 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));
|
// ("canceled_id", op.id)("bet_id", bet_canceled_op.bet_id));
|
||||||
if (is_operation_history_object_stored(op.id))
|
bet_iter->second.associated_operations.emplace_back(op.id);
|
||||||
db.modify(*bet_iter, [&]( persistent_bet_object& obj ) {
|
|
||||||
obj.associated_operations.emplace_back(op.id);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if ( op.op.which() == operation::tag<bet_adjusted_operation>::value )
|
else if ( op.op.which() == operation::tag<bet_adjusted_operation>::value )
|
||||||
{
|
{
|
||||||
const bet_adjusted_operation& bet_adjusted_op = op.op.get<bet_adjusted_operation>();
|
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>();
|
const auto &idx_bet_object = db.get_index_type<bet_object_index>();
|
||||||
auto bet_iter = persistent_bets_by_bet_id.find(bet_adjusted_op.bet_id);
|
const auto &aidx_bet_object = dynamic_cast<const base_primary_index &>(idx_bet_object);
|
||||||
assert(bet_iter != persistent_bets_by_bet_id.end());
|
const auto &refs_bet_object = aidx_bet_object.get_secondary_index<detail::persistent_bet_index>();
|
||||||
if (bet_iter != persistent_bets_by_bet_id.end())
|
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",
|
// 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));
|
// ("adjusted_id", op.id)("bet_id", bet_adjusted_op.bet_id));
|
||||||
if (is_operation_history_object_stored(op.id))
|
bet_iter->second.associated_operations.emplace_back(op.id);
|
||||||
db.modify(*bet_iter, [&]( persistent_bet_object& obj ) {
|
|
||||||
obj.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().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); });
|
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> >();
|
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);
|
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>();
|
nonconst_bet_object_idx.add_secondary_index<detail::persistent_bet_index>();
|
||||||
persistent_bet_object_helper_index->set_plugin_instance(this);
|
|
||||||
|
|
||||||
const primary_index<betting_market_object_index>& betting_market_object_idx = database().get_index_type<primary_index<betting_market_object_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);
|
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>();
|
nonconst_betting_market_object_idx.add_secondary_index<detail::persistent_betting_market_index>();
|
||||||
persistent_betting_market_object_helper_index->set_plugin_instance(this);
|
|
||||||
|
|
||||||
const primary_index<betting_market_group_object_index>& betting_market_group_object_idx = database().get_index_type<primary_index<betting_market_group_object_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);
|
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>();
|
nonconst_betting_market_group_object_idx.add_secondary_index<detail::persistent_betting_market_group_index>();
|
||||||
persistent_betting_market_group_object_helper_index->set_plugin_instance(this);
|
|
||||||
|
|
||||||
const primary_index<event_object_index>& event_object_idx = database().get_index_type<primary_index<event_object_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);
|
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>();
|
nonconst_event_object_idx.add_secondary_index<detail::persistent_event_index>();
|
||||||
persistent_event_object_helper_index->set_plugin_instance(this);
|
|
||||||
|
|
||||||
ilog("bookie plugin: plugin_startup() end");
|
ilog("bookie plugin: plugin_startup() end");
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -29,39 +29,21 @@
|
||||||
namespace graphene { namespace bookie {
|
namespace graphene { namespace bookie {
|
||||||
using namespace chain;
|
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
|
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:
|
public:
|
||||||
static const uint8_t space_id = bookie_objects;
|
virtual void object_inserted( const object& obj ) override;
|
||||||
static const uint8_t type_id = persistent_event_object_type;
|
virtual void object_modified( const object& after ) override;
|
||||||
|
|
||||||
event_object ephemeral_event_object;
|
map< event_id_type, event_object > ephemeral_event_object;
|
||||||
|
|
||||||
event_id_type get_event_id() const { return ephemeral_event_object.id; }
|
|
||||||
};
|
};
|
||||||
|
|
||||||
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
|
#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
|
class events_by_competitor_index : public secondary_index
|
||||||
{
|
{
|
||||||
|
|
@ -101,95 +83,122 @@ void events_by_competitor_index::object_modified( const object& after )
|
||||||
}
|
}
|
||||||
#endif
|
#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:
|
public:
|
||||||
static const uint8_t space_id = bookie_objects;
|
struct internal_type
|
||||||
static const uint8_t type_id = persistent_betting_market_group_object_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;
|
betting_market_group_object ephemeral_betting_market_group_object;
|
||||||
|
|
||||||
share_type total_matched_bets_amount;
|
share_type total_matched_bets_amount;
|
||||||
|
};
|
||||||
|
|
||||||
betting_market_group_id_type get_betting_market_group_id() const { return ephemeral_betting_market_group_object.id; }
|
public:
|
||||||
|
virtual void object_inserted( const object& obj ) override;
|
||||||
|
virtual void object_modified( const object& after ) override;
|
||||||
|
|
||||||
|
map< betting_market_group_id_type, internal_type > internal;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct by_betting_market_group_id;
|
inline bool operator==(const persistent_betting_market_group_index::internal_type& lhs, const persistent_betting_market_group_index::internal_type& rhs)
|
||||||
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:
|
return lhs.ephemeral_betting_market_group_object == rhs.ephemeral_betting_market_group_object;
|
||||||
static const uint8_t space_id = bookie_objects;
|
}
|
||||||
static const uint8_t type_id = persistent_betting_market_object_type;
|
|
||||||
|
|
||||||
betting_market_object ephemeral_betting_market_object;
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
share_type total_matched_bets_amount;
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
betting_market_id_type get_betting_market_id() const { return ephemeral_betting_market_object.id; }
|
/**
|
||||||
|
* @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:
|
||||||
|
virtual void object_inserted( const object& obj ) override;
|
||||||
|
virtual void object_modified( const object& after ) override;
|
||||||
|
|
||||||
|
map< betting_market_id_type, betting_market_object > ephemeral_betting_market_object;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct by_betting_market_id;
|
/**
|
||||||
typedef multi_index_container<
|
* @brief This secondary index will allow a reverse lookup of all bet_object that happened
|
||||||
persistent_betting_market_object,
|
*/
|
||||||
indexed_by<
|
class persistent_bet_index : public secondary_index
|
||||||
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;
|
|
||||||
|
|
||||||
typedef generic_index<persistent_betting_market_object, persistent_betting_market_multi_index_type> persistent_betting_market_index;
|
|
||||||
|
|
||||||
//////////// bet_object //////////////////
|
|
||||||
class persistent_bet_object : public graphene::db::abstract_object<persistent_bet_object>
|
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
static const uint8_t space_id = bookie_objects;
|
struct internal_type
|
||||||
static const uint8_t type_id = persistent_bet_object_type;
|
{
|
||||||
|
internal_type() = default;
|
||||||
|
|
||||||
bet_object ephemeral_bet_object;
|
internal_type(const bet_object& other)
|
||||||
|
: ephemeral_bet_object{other}
|
||||||
|
{}
|
||||||
|
|
||||||
// total amount of the bet that matched
|
internal_type& operator=(const bet_object& other)
|
||||||
share_type amount_matched;
|
{
|
||||||
|
ephemeral_bet_object = other;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
std::vector<operation_history_id_type> associated_operations;
|
|
||||||
|
|
||||||
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; }
|
account_id_type get_bettor_id() const { return ephemeral_bet_object.bettor_id; }
|
||||||
bool is_matched() const { return amount_matched != share_type(); }
|
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;
|
||||||
|
};
|
||||||
|
|
||||||
|
public:
|
||||||
|
virtual void object_inserted( const object& obj ) override;
|
||||||
|
virtual void object_modified( const object& after ) override;
|
||||||
|
|
||||||
|
map< bet_id_type, internal_type > internal;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct by_bet_id;
|
inline bool operator==(const persistent_bet_index::internal_type& lhs, const persistent_bet_index::internal_type& rhs)
|
||||||
struct by_bettor_id;
|
{
|
||||||
typedef multi_index_container<
|
return lhs.ephemeral_bet_object == rhs.ephemeral_bet_object;
|
||||||
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;
|
|
||||||
|
|
||||||
typedef generic_index<persistent_bet_object, persistent_bet_multi_index_type> persistent_bet_index;
|
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
|
} } } //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
|
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
|
target_include_directories( graphene_delayed_node
|
||||||
PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/include" )
|
PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/include" )
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -22,6 +22,7 @@
|
||||||
* THE SOFTWARE.
|
* THE SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <boost/algorithm/string.hpp>
|
||||||
#include <graphene/elasticsearch/elasticsearch_plugin.hpp>
|
#include <graphene/elasticsearch/elasticsearch_plugin.hpp>
|
||||||
#include <graphene/chain/impacted.hpp>
|
#include <graphene/chain/impacted.hpp>
|
||||||
#include <graphene/chain/account_evaluator.hpp>
|
#include <graphene/chain/account_evaluator.hpp>
|
||||||
|
|
@ -33,6 +34,15 @@ namespace graphene { namespace elasticsearch {
|
||||||
namespace detail
|
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
|
class elasticsearch_plugin_impl
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
@ -48,6 +58,9 @@ class elasticsearch_plugin_impl
|
||||||
return _self.database();
|
return _self.database();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
friend class graphene::elasticsearch::elasticsearch_plugin;
|
||||||
|
|
||||||
|
private:
|
||||||
elasticsearch_plugin& _self;
|
elasticsearch_plugin& _self;
|
||||||
primary_index< operation_history_index >* _oho_index;
|
primary_index< operation_history_index >* _oho_index;
|
||||||
|
|
||||||
|
|
@ -75,6 +88,8 @@ class elasticsearch_plugin_impl
|
||||||
std::string bulk_line;
|
std::string bulk_line;
|
||||||
std::string index_name;
|
std::string index_name;
|
||||||
bool is_sync = false;
|
bool is_sync = false;
|
||||||
|
bool is_es_version_7_or_above = true;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool add_elasticsearch( const account_id_type account_id, const optional<operation_history_object>& oho, const uint32_t block_number );
|
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,
|
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 createBulkLine(const account_transaction_history_object& ath);
|
||||||
void prepareBulk(const account_transaction_history_id_type& ath_id);
|
void prepareBulk(const account_transaction_history_id_type& ath_id);
|
||||||
void populateESstruct();
|
void populateESstruct();
|
||||||
|
void init_program_options(const boost::program_options::variables_map& options);
|
||||||
};
|
};
|
||||||
|
|
||||||
elasticsearch_plugin_impl::~elasticsearch_plugin_impl()
|
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 )
|
bool elasticsearch_plugin_impl::update_account_histories( const signed_block& b )
|
||||||
{
|
{
|
||||||
checkState(b.timestamp);
|
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();
|
graphene::chain::database& db = database();
|
||||||
const vector<optional< operation_history_object > >& hist = db.get_applied_operations();
|
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();
|
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)
|
void elasticsearch_plugin_impl::doOperationHistory(const optional <operation_history_object>& oho)
|
||||||
{
|
{
|
||||||
os.trx_in_block = oho->trx_in_block;
|
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;
|
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)
|
void elasticsearch_plugin_impl::doVisitor(const optional <operation_history_object>& oho)
|
||||||
{
|
{
|
||||||
graphene::chain::database& db = database();
|
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);
|
const std::string _id = fc::json::to_string(ath_id);
|
||||||
fc::mutable_variant_object bulk_header;
|
fc::mutable_variant_object bulk_header;
|
||||||
bulk_header["_index"] = index_name;
|
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) + "."
|
bulk_header["_id"] = fc::to_string(ath_id.space_id) + "." + fc::to_string(ath_id.type_id) + "."
|
||||||
+ fc::to_string(ath_id.instance.value);
|
+ fc::to_string(ath_id.instance.value);
|
||||||
prepare = graphene::utilities::createBulk(bulk_header, std::move(bulk_line));
|
prepare = graphene::utilities::createBulk(bulk_header, std::move(bulk_line));
|
||||||
|
|
@ -428,6 +607,43 @@ void elasticsearch_plugin_impl::populateESstruct()
|
||||||
es.query = "";
|
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
|
} // end namespace detail
|
||||||
|
|
||||||
elasticsearch_plugin::elasticsearch_plugin() :
|
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)
|
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 > >();
|
my->_oho_index = database().add_index< primary_index< operation_history_index > >();
|
||||||
database().add_index< primary_index< account_transaction_history_index > >();
|
database().add_index< primary_index< account_transaction_history_index > >();
|
||||||
|
|
||||||
if (options.count("elasticsearch-node-url")) {
|
my->init_program_options( options );
|
||||||
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>());
|
|
||||||
}
|
|
||||||
|
|
||||||
if(my->_elasticsearch_mode != mode::only_query) {
|
if(my->_elasticsearch_mode != mode::only_query) {
|
||||||
if (my->_elasticsearch_mode == mode::all && !my->_elasticsearch_operation_string)
|
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.");
|
"Error populating ES database, we are going to keep trying.");
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
void elasticsearch_plugin::plugin_startup()
|
|
||||||
{
|
|
||||||
graphene::utilities::ES es;
|
graphene::utilities::ES es;
|
||||||
es.curl = my->curl;
|
es.curl = my->curl;
|
||||||
es.elasticsearch_url = my->_elasticsearch_node_url;
|
es.elasticsearch_url = my->_elasticsearch_node_url;
|
||||||
|
|
@ -539,7 +722,17 @@ void elasticsearch_plugin::plugin_startup()
|
||||||
|
|
||||||
if(!graphene::utilities::checkES(es))
|
if(!graphene::utilities::checkES(es))
|
||||||
FC_THROW_EXCEPTION(fc::exception, "ES database is not up in url ${url}", ("url", my->_elasticsearch_node_url));
|
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");
|
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)
|
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.curl = curl;
|
||||||
es.elasticsearch_url = my->_elasticsearch_node_url;
|
es.elasticsearch_url = my->_elasticsearch_node_url;
|
||||||
es.index_prefix = my->_elasticsearch_index_prefix;
|
es.index_prefix = my->_elasticsearch_index_prefix;
|
||||||
es.endpoint = es.index_prefix + "*/data/_search";
|
es.endpoint = es.index_prefix + "*/_doc/_search";
|
||||||
es.query = query;
|
es.query = query;
|
||||||
|
|
||||||
return es;
|
return es;
|
||||||
|
|
|
||||||
|
|
@ -79,62 +79,6 @@ class elasticsearch_plugin : public graphene::app::plugin
|
||||||
graphene::utilities::ES prepareHistoryQuery(string query);
|
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 {
|
struct operation_history_struct {
|
||||||
int trx_in_block;
|
int trx_in_block;
|
||||||
int op_in_trx;
|
int op_in_trx;
|
||||||
|
|
@ -197,113 +141,6 @@ struct bulk_struct {
|
||||||
optional<visitor_struct> additional_data;
|
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
|
} } //graphene::elasticsearch
|
||||||
|
|
||||||
FC_REFLECT_ENUM( graphene::elasticsearch::mode, (only_save)(only_query)(all) )
|
FC_REFLECT_ENUM( graphene::elasticsearch::mode, (only_save)(only_query)(all) )
|
||||||
|
|
|
||||||
|
|
@ -66,6 +66,9 @@ class es_objects_plugin_impl
|
||||||
bool genesis();
|
bool genesis();
|
||||||
void remove_from_database(object_id_type id, std::string index);
|
void remove_from_database(object_id_type id, std::string index);
|
||||||
|
|
||||||
|
friend class graphene::es_objects::es_objects_plugin;
|
||||||
|
|
||||||
|
private:
|
||||||
es_objects_plugin& _self;
|
es_objects_plugin& _self;
|
||||||
std::string _es_objects_elasticsearch_url = "http://localhost:9200/";
|
std::string _es_objects_elasticsearch_url = "http://localhost:9200/";
|
||||||
std::string _es_objects_auth = "";
|
std::string _es_objects_auth = "";
|
||||||
|
|
@ -97,10 +100,12 @@ class es_objects_plugin_impl
|
||||||
|
|
||||||
uint32_t block_number;
|
uint32_t block_number;
|
||||||
fc::time_point_sec block_time;
|
fc::time_point_sec block_time;
|
||||||
|
bool is_es_version_7_or_above = true;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
template<typename T>
|
template<typename T>
|
||||||
void prepareTemplate(T blockchain_object, string index_name);
|
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()
|
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;
|
fc::mutable_variant_object delete_line;
|
||||||
delete_line["_id"] = string(id);
|
delete_line["_id"] = string(id);
|
||||||
delete_line["_index"] = _es_objects_index_prefix + index;
|
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;
|
fc::mutable_variant_object final_delete_line;
|
||||||
final_delete_line["delete"] = delete_line;
|
final_delete_line["delete"] = delete_line;
|
||||||
prepare.push_back(fc::json::to_string(final_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;
|
fc::mutable_variant_object bulk_header;
|
||||||
bulk_header["_index"] = _es_objects_index_prefix + index_name;
|
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)
|
if(_es_objects_keep_only_current)
|
||||||
{
|
{
|
||||||
bulk_header["_id"] = string(blockchain_object.id);
|
bulk_header["_id"] = string(blockchain_object.id);
|
||||||
|
|
@ -567,6 +574,72 @@ es_objects_plugin_impl::~es_objects_plugin_impl()
|
||||||
}
|
}
|
||||||
return;
|
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
|
} // 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)
|
void es_objects_plugin::plugin_initialize(const boost::program_options::variables_map& options)
|
||||||
{
|
{
|
||||||
if (options.count("es-objects-elasticsearch-url")) {
|
ilog("elasticsearch OBJECTS: plugin_initialize() begin");
|
||||||
my->_es_objects_elasticsearch_url = options["es-objects-elasticsearch-url"].as<std::string>();
|
|
||||||
}
|
my->init_program_options( options );
|
||||||
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>();
|
|
||||||
}
|
|
||||||
|
|
||||||
database().applied_block.connect([this](const signed_block &b) {
|
database().applied_block.connect([this](const signed_block &b) {
|
||||||
if(b.block_num() == 1 && my->_es_objects_start_es_after_block == 0) {
|
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.");
|
"Error deleting object from ES database, we are going to keep trying.");
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
|
||||||
|
|
||||||
void es_objects_plugin::plugin_startup()
|
|
||||||
{
|
|
||||||
graphene::utilities::ES es;
|
graphene::utilities::ES es;
|
||||||
es.curl = my->curl;
|
es.curl = my->curl;
|
||||||
es.elasticsearch_url = my->_es_objects_elasticsearch_url;
|
es.elasticsearch_url = my->_es_objects_elasticsearch_url;
|
||||||
|
|
@ -733,7 +743,17 @@ void es_objects_plugin::plugin_startup()
|
||||||
|
|
||||||
if(!graphene::utilities::checkES(es))
|
if(!graphene::utilities::checkES(es))
|
||||||
FC_THROW_EXCEPTION(fc::exception, "ES database is not up in url ${url}", ("url", my->_es_objects_elasticsearch_url));
|
FC_THROW_EXCEPTION(fc::exception, "ES database is not up in url ${url}", ("url", my->_es_objects_elasticsearch_url));
|
||||||
ilog("elasticsearch OBJECTS: plugin_startup() begin");
|
|
||||||
|
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
|
add_library( peerplays_sidechain
|
||||||
peerplays_sidechain_plugin.cpp
|
peerplays_sidechain_plugin.cpp
|
||||||
|
sidechain_api.cpp
|
||||||
sidechain_net_manager.cpp
|
sidechain_net_manager.cpp
|
||||||
sidechain_net_handler.cpp
|
sidechain_net_handler.cpp
|
||||||
sidechain_net_handler_bitcoin.cpp
|
sidechain_net_handler_bitcoin.cpp
|
||||||
|
|
@ -23,19 +24,11 @@ add_library( peerplays_sidechain
|
||||||
)
|
)
|
||||||
|
|
||||||
if (ENABLE_DEV_FEATURES)
|
if (ENABLE_DEV_FEATURES)
|
||||||
set(ENABLE_MULTIPLE_SONS 1)
|
|
||||||
set(ENABLE_PEERPLAYS_ASSET_DEPOSITS 1)
|
set(ENABLE_PEERPLAYS_ASSET_DEPOSITS 1)
|
||||||
endif()
|
endif()
|
||||||
unset(ENABLE_DEV_FEATURES)
|
unset(ENABLE_DEV_FEATURES)
|
||||||
unset(ENABLE_DEV_FEATURES CACHE)
|
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)
|
if (ENABLE_PEERPLAYS_ASSET_DEPOSITS)
|
||||||
message ("Depositing Peerplays assets enabled")
|
message ("Depositing Peerplays assets enabled")
|
||||||
target_compile_definitions(peerplays_sidechain PRIVATE ENABLE_PEERPLAYS_ASSET_DEPOSITS)
|
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);
|
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);
|
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);
|
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
|
}} // 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 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;
|
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:
|
protected:
|
||||||
peerplays_sidechain_plugin &plugin;
|
peerplays_sidechain_plugin &plugin;
|
||||||
graphene::chain::database &database;
|
graphene::chain::database &database;
|
||||||
|
|
@ -56,6 +59,8 @@ protected:
|
||||||
|
|
||||||
std::map<std::string, std::string> private_keys;
|
std::map<std::string, std::string> private_keys;
|
||||||
|
|
||||||
|
std::vector<std::string> son_listener_log;
|
||||||
|
|
||||||
void on_applied_block(const signed_block &b);
|
void on_applied_block(const signed_block &b);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@
|
||||||
#include <graphene/peerplays_sidechain/sidechain_net_handler.hpp>
|
#include <graphene/peerplays_sidechain/sidechain_net_handler.hpp>
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <zmq.hpp>
|
#include <zmq_addon.hpp>
|
||||||
|
|
||||||
#include <boost/signals2.hpp>
|
#include <boost/signals2.hpp>
|
||||||
|
|
||||||
|
|
@ -22,6 +22,23 @@ public:
|
||||||
};
|
};
|
||||||
|
|
||||||
class bitcoin_rpc_client {
|
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:
|
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);
|
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 getaddressinfo(const std::string &address);
|
||||||
std::string getblock(const std::string &block_hash, int32_t verbosity = 2);
|
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 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 gettransaction(const std::string &txid, const bool include_watch_only = false);
|
||||||
std::string getblockchaininfo();
|
std::string getblockchaininfo();
|
||||||
void importaddress(const std::string &address_or_script, const std::string &label = "", const bool rescan = true, const bool p2sh = false);
|
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(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::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 loadwallet(const std::string &filename);
|
||||||
std::string sendrawtransaction(const std::string &tx_hex);
|
std::string sendrawtransaction(const std::string &tx_hex);
|
||||||
std::string signrawtransactionwithwallet(const std::string &tx_hash);
|
std::string signrawtransactionwithwallet(const std::string &tx_hash);
|
||||||
std::string unloadwallet(const std::string &filename);
|
std::string unloadwallet(const std::string &filename);
|
||||||
//std::string walletlock();
|
std::string walletlock();
|
||||||
std::string walletprocesspsbt(std::string const &tx_psbt);
|
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:
|
private:
|
||||||
fc::http::reply send_post_request(std::string body, bool show_log);
|
fc::http::reply send_post_request(std::string body, bool show_log);
|
||||||
|
|
@ -105,6 +124,7 @@ private:
|
||||||
std::string ip;
|
std::string ip;
|
||||||
uint32_t zmq_port;
|
uint32_t zmq_port;
|
||||||
uint32_t rpc_port;
|
uint32_t rpc_port;
|
||||||
|
uint32_t bitcoin_major_version;
|
||||||
std::string rpc_user;
|
std::string rpc_user;
|
||||||
std::string rpc_password;
|
std::string rpc_password;
|
||||||
std::string wallet;
|
std::string wallet;
|
||||||
|
|
|
||||||
|
|
@ -25,6 +25,8 @@ public:
|
||||||
void send_sidechain_transactions();
|
void send_sidechain_transactions();
|
||||||
void settle_sidechain_transactions();
|
void settle_sidechain_transactions();
|
||||||
|
|
||||||
|
std::map<sidechain_type, std::vector<std::string>> get_son_listener_log();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
peerplays_sidechain_plugin &plugin;
|
peerplays_sidechain_plugin &plugin;
|
||||||
graphene::chain::database &database;
|
graphene::chain::database &database;
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@
|
||||||
#include <graphene/chain/sidechain_address_object.hpp>
|
#include <graphene/chain/sidechain_address_object.hpp>
|
||||||
#include <graphene/chain/son_wallet_object.hpp>
|
#include <graphene/chain/son_wallet_object.hpp>
|
||||||
#include <graphene/chain/son_wallet_withdraw_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/peerplays_sidechain/sidechain_net_manager.hpp>
|
||||||
#include <graphene/utilities/key_conversion.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);
|
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);
|
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);
|
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 schedule_heartbeat_loop();
|
||||||
void 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();
|
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")) {
|
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>>();
|
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) {
|
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);
|
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() {
|
void peerplays_sidechain_plugin_impl::approve_proposals() {
|
||||||
|
|
||||||
auto check_approve_proposal = [&](const chain::son_id_type &son_id, const chain::proposal_object &proposal) {
|
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);
|
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
|
}} // 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 (settle_amount.amount != 0) {
|
||||||
if (sto.object_id.is<son_wallet_deposit_id_type>()) {
|
if (sto.object_id.is<son_wallet_deposit_id_type>()) {
|
||||||
asset_issue_operation ai_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.issuer = gpo.parameters.son_account();
|
||||||
ai_op.asset_to_issue = settle_amount;
|
ai_op.asset_to_issue = settle_amount;
|
||||||
ai_op.issue_to_account = database.get<son_wallet_deposit_object>(sto.object_id).peerplays_from;
|
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>()) {
|
if (sto.object_id.is<son_wallet_withdraw_id_type>()) {
|
||||||
asset_reserve_operation ar_op;
|
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.payer = gpo.parameters.son_account();
|
||||||
ar_op.amount_to_reserve = settle_amount;
|
ar_op.amount_to_reserve = settle_amount;
|
||||||
proposal_op.proposed_ops.emplace_back(ar_op);
|
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) {
|
void sidechain_net_handler::on_applied_block(const signed_block &b) {
|
||||||
|
|
||||||
const chain::global_property_object &gpo = plugin.database().get_global_properties();
|
const chain::global_property_object &gpo = plugin.database().get_global_properties();
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load diff
|
|
@ -627,7 +627,7 @@ bool sidechain_net_handler_hive::process_deposit(const son_wallet_deposit_object
|
||||||
proposal_op.proposed_ops.emplace_back(swdp_op);
|
proposal_op.proposed_ops.emplace_back(swdp_op);
|
||||||
|
|
||||||
asset_issue_operation ai_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.issuer = gpo.parameters.son_account();
|
||||||
ai_op.asset_to_issue = asset_to_issue;
|
ai_op.asset_to_issue = asset_to_issue;
|
||||||
ai_op.issue_to_account = swdo.peerplays_from;
|
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) {
|
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()));
|
std::string block = node_rpc_client->block_api_get_block(std::atoll(event_data.c_str()));
|
||||||
if (block != "") {
|
if (block != "") {
|
||||||
|
add_to_son_listener_log("BLOCK : " + event_data);
|
||||||
std::stringstream ss(block);
|
std::stringstream ss(block);
|
||||||
boost::property_tree::ptree block_json;
|
boost::property_tree::ptree block_json;
|
||||||
boost::property_tree::read_json(ss, 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_from = accn;
|
||||||
sed.peerplays_to = database.get_global_properties().parameters.son_account();
|
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);
|
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);
|
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) {
|
void sidechain_net_manager::on_applied_block(const signed_block &b) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -24,7 +24,6 @@
|
||||||
#include <graphene/utilities/elasticsearch.hpp>
|
#include <graphene/utilities/elasticsearch.hpp>
|
||||||
|
|
||||||
#include <boost/algorithm/string/join.hpp>
|
#include <boost/algorithm/string/join.hpp>
|
||||||
#include <boost/algorithm/string.hpp>
|
|
||||||
#include <fc/log/logger.hpp>
|
#include <fc/log/logger.hpp>
|
||||||
#include <fc/io/json.hpp>
|
#include <fc/io/json.hpp>
|
||||||
|
|
||||||
|
|
@ -47,8 +46,36 @@ bool checkES(ES& es)
|
||||||
if(doCurl(curl_request).empty())
|
if(doCurl(curl_request).empty())
|
||||||
return false;
|
return false;
|
||||||
return true;
|
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)
|
const std::string simpleQuery(ES& es)
|
||||||
{
|
{
|
||||||
graphene::utilities::CurlRequest curl_request;
|
graphene::utilities::CurlRequest curl_request;
|
||||||
|
|
@ -118,13 +145,13 @@ bool handleBulkResponse(long http_code, const std::string& CurlReadBuffer)
|
||||||
return true;
|
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;
|
std::vector<std::string> bulk;
|
||||||
fc::mutable_variant_object final_bulk_header;
|
fc::mutable_variant_object final_bulk_header;
|
||||||
final_bulk_header["index"] = bulk_header;
|
final_bulk_header["index"] = bulk_header;
|
||||||
bulk.push_back(fc::json::to_string(final_bulk_header));
|
bulk.push_back(fc::json::to_string(final_bulk_header));
|
||||||
bulk.push_back(data);
|
bulk.emplace_back(std::move(data));
|
||||||
|
|
||||||
return bulk;
|
return bulk;
|
||||||
}
|
}
|
||||||
|
|
@ -154,15 +181,6 @@ const std::string getEndPoint(ES& es)
|
||||||
return doCurl(curl_request);
|
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)
|
const std::string doCurl(CurlRequest& curl)
|
||||||
{
|
{
|
||||||
std::string CurlReadBuffer;
|
std::string CurlReadBuffer;
|
||||||
|
|
|
||||||
|
|
@ -54,13 +54,14 @@ namespace graphene { namespace utilities {
|
||||||
};
|
};
|
||||||
|
|
||||||
bool SendBulk(ES& es);
|
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);
|
bool checkES(ES& es);
|
||||||
|
const std::string getESVersion(ES& es);
|
||||||
|
void checkESVersion7OrAbove(ES& es, bool& result) noexcept;
|
||||||
const std::string simpleQuery(ES& es);
|
const std::string simpleQuery(ES& es);
|
||||||
bool deleteAll(ES& es);
|
bool deleteAll(ES& es);
|
||||||
bool handleBulkResponse(long http_code, const std::string& CurlReadBuffer);
|
bool handleBulkResponse(long http_code, const std::string& CurlReadBuffer);
|
||||||
const std::string getEndPoint(ES& es);
|
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 doCurl(CurlRequest& curl);
|
||||||
const std::string joinBulkLines(const std::vector<std::string>& bulk);
|
const std::string joinBulkLines(const std::vector<std::string>& bulk);
|
||||||
long getResponseCode(CURL *handler);
|
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
|
# This file describes the settings to be used by the documentation system
|
||||||
# doxygen (www.doxygen.org) for a project.
|
# doxygen (www.doxygen.org) for a project.
|
||||||
|
|
@ -17,11 +17,11 @@
|
||||||
# Project related configuration options
|
# Project related configuration options
|
||||||
#---------------------------------------------------------------------------
|
#---------------------------------------------------------------------------
|
||||||
|
|
||||||
# This tag specifies the encoding used for all characters in the config file
|
# This tag specifies the encoding used for all characters in the configuration
|
||||||
# that follow. The default is UTF-8 which is also the encoding used for all text
|
# file that follow. The default is UTF-8 which is also the encoding used for all
|
||||||
# before the first occurrence of this tag. Doxygen uses libiconv (or the iconv
|
# text before the first occurrence of this tag. Doxygen uses libiconv (or the
|
||||||
# built into libc) for the transcoding. See http://www.gnu.org/software/libiconv
|
# iconv built into libc) for the transcoding. See
|
||||||
# for the list of possible encodings.
|
# https://www.gnu.org/software/libiconv/ for the list of possible encodings.
|
||||||
# The default value is: UTF-8.
|
# The default value is: UTF-8.
|
||||||
|
|
||||||
DOXYFILE_ENCODING = UTF-8
|
DOXYFILE_ENCODING = UTF-8
|
||||||
|
|
@ -93,6 +93,14 @@ ALLOW_UNICODE_NAMES = NO
|
||||||
|
|
||||||
OUTPUT_LANGUAGE = English
|
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
|
# 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
|
# descriptions after the members that are listed in the file and class
|
||||||
# documentation (similar to Javadoc). Set to NO to disable this.
|
# documentation (similar to Javadoc). Set to NO to disable this.
|
||||||
|
|
@ -179,6 +187,16 @@ SHORT_NAMES = NO
|
||||||
|
|
||||||
JAVADOC_AUTOBRIEF = 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
|
# 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
|
# 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
|
# 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
|
# will allow you to put the command \sideeffect (or @sideeffect) in the
|
||||||
# documentation, which will result in a user-defined paragraph with heading
|
# 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
|
# "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 =
|
ALIASES =
|
||||||
|
|
||||||
|
|
@ -264,17 +287,26 @@ OPTIMIZE_FOR_FORTRAN = NO
|
||||||
|
|
||||||
OPTIMIZE_OUTPUT_VHDL = 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
|
# 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
|
# 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
|
# 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
|
# 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,
|
# language is one of the parsers supported by doxygen: IDL, Java, JavaScript,
|
||||||
# C#, C, C++, D, PHP, Objective-C, Python, Fortran (fixed format Fortran:
|
# Csharp (C#), C, C++, D, PHP, md (Markdown), Objective-C, Python, Slice,
|
||||||
# FortranFixed, free formatted Fortran: FortranFree, unknown formatted Fortran:
|
# Fortran (fixed format Fortran: FortranFixed, free formatted Fortran:
|
||||||
# Fortran. In the later case the parser tries to guess whether the code is fixed
|
# FortranFree, unknown formatted Fortran: Fortran. In the later case the parser
|
||||||
# or free formatted code, this is the default for Fortran type files), VHDL. For
|
# tries to guess whether the code is fixed or free formatted code, this is the
|
||||||
# instance to make doxygen treat .inc files as Fortran files (default is PHP),
|
# default for Fortran type files), VHDL, tcl. For instance to make doxygen treat
|
||||||
# and .f files as C (default is Fortran), use: inc=Fortran f=C.
|
# .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.
|
# 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
|
# If the MARKDOWN_SUPPORT tag is enabled then doxygen pre-processes all comments
|
||||||
# according to the Markdown format, which allows for more readable
|
# 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
|
# 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
|
# mix doxygen, HTML, and XML commands with Markdown formatting. Disable only in
|
||||||
# case of backward compatibilities issues.
|
# case of backward compatibilities issues.
|
||||||
|
|
@ -293,6 +325,15 @@ EXTENSION_MAPPING =
|
||||||
|
|
||||||
MARKDOWN_SUPPORT = YES
|
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
|
# When enabled doxygen tries to link words that correspond to documented
|
||||||
# classes, or namespaces to their corresponding documentation. Such a link can
|
# 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
|
# 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
|
CPP_CLI_SUPPORT = NO
|
||||||
|
|
||||||
# Set the SIP_SUPPORT tag to YES if your project consists of sip (see:
|
# 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
|
# will parse them like normal C++ but will assume all classes use public instead
|
||||||
# of private inheritance when no explicit protection keyword is present.
|
# of private inheritance when no explicit protection keyword is present.
|
||||||
# The default value is: NO.
|
# The default value is: NO.
|
||||||
|
|
@ -343,6 +384,13 @@ IDL_PROPERTY_SUPPORT = YES
|
||||||
|
|
||||||
DISTRIBUTE_GROUP_DOC = NO
|
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
|
# 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
|
# (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
|
# type (e.g. under the Public Functions section). Set it to NO to prevent
|
||||||
|
|
@ -417,6 +465,12 @@ EXTRACT_ALL = YES
|
||||||
|
|
||||||
EXTRACT_PRIVATE = NO
|
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
|
# If the EXTRACT_PACKAGE tag is set to YES, all members with package or internal
|
||||||
# scope will be included in the documentation.
|
# scope will be included in the documentation.
|
||||||
# The default value is: NO.
|
# The default value is: NO.
|
||||||
|
|
@ -471,8 +525,8 @@ HIDE_UNDOC_MEMBERS = NO
|
||||||
HIDE_UNDOC_CLASSES = NO
|
HIDE_UNDOC_CLASSES = NO
|
||||||
|
|
||||||
# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, doxygen will hide all friend
|
# 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
|
# declarations. If set to NO, these declarations will be included in the
|
||||||
# included in the documentation.
|
# documentation.
|
||||||
# The default value is: NO.
|
# The default value is: NO.
|
||||||
|
|
||||||
HIDE_FRIEND_COMPOUNDS = 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
|
# 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
|
# 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
|
# 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.
|
# The default value is: system dependent.
|
||||||
|
|
||||||
CASE_SENSE_NAMES = NO
|
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 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
|
# the reference definitions. This must be a list of .bib files. The .bib
|
||||||
# extension is automatically appended if omitted. This requires the bibtex tool
|
# 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
|
# 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
|
# 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.
|
# 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
|
# 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
|
# are documented, but have no documentation for their parameters or return
|
||||||
# value. If set to NO, doxygen will only warn about wrong or incomplete
|
# 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.
|
# The default value is: NO.
|
||||||
|
|
||||||
WARN_NO_PARAMDOC = 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
|
# 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
|
# 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
|
# 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
|
# 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
|
# documented source files. You may enter file names like myfile.cpp or
|
||||||
# directories like /usr/src/myproject. Separate the files or directories with
|
# 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.
|
# Note: If this tag is empty the current directory is searched.
|
||||||
|
|
||||||
INPUT = ${CMAKE_CURRENT_SOURCE_DIR}/include/graphene/wallet/wallet.hpp
|
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
|
# 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
|
# 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
|
# 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.
|
# possible encodings.
|
||||||
# The default value is: UTF-8.
|
# 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
|
# 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
|
# 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
|
# *.h) to filter out the source-files in the directories.
|
||||||
# following patterns are tested:*.c, *.cc, *.cxx, *.cpp, *.c++, *.java, *.ii,
|
#
|
||||||
# *.ixx, *.ipp, *.i++, *.inl, *.idl, *.ddl, *.odl, *.h, *.hh, *.hxx, *.hpp,
|
# Note that for custom extensions or not directly supported extensions you also
|
||||||
# *.h++, *.cs, *.d, *.php, *.php4, *.php5, *.phtml, *.inc, *.m, *.markdown,
|
# need to set EXTENSION_MAPPING for the extension otherwise the files are not
|
||||||
# *.md, *.mm, *.dox, *.py, *.f90, *.f, *.for, *.tcl, *.vhd, *.vhdl, *.ucf,
|
# read by doxygen.
|
||||||
# *.qsf, *.as and *.js.
|
#
|
||||||
|
# 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 =
|
FILE_PATTERNS =
|
||||||
|
|
||||||
|
|
@ -862,6 +930,10 @@ IMAGE_PATH =
|
||||||
# Note that the filter must not add or remove lines; it is applied before the
|
# 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
|
# code is scanned, but not when the output code is generated. If lines are added
|
||||||
# or removed, the anchors will not be placed correctly.
|
# 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 =
|
INPUT_FILTER =
|
||||||
|
|
||||||
|
|
@ -871,6 +943,10 @@ INPUT_FILTER =
|
||||||
# (like *.cpp=my_cpp_filter). See INPUT_FILTER for further information on how
|
# (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
|
# filters are used. If the FILTER_PATTERNS tag is empty or if none of the
|
||||||
# patterns match the file name, INPUT_FILTER is applied.
|
# 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 =
|
FILTER_PATTERNS =
|
||||||
|
|
||||||
|
|
@ -923,7 +999,7 @@ INLINE_SOURCES = NO
|
||||||
STRIP_CODE_COMMENTS = YES
|
STRIP_CODE_COMMENTS = YES
|
||||||
|
|
||||||
# If the REFERENCED_BY_RELATION tag is set to YES then for each documented
|
# 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.
|
# The default value is: NO.
|
||||||
|
|
||||||
REFERENCED_BY_RELATION = 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
|
# 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
|
# 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
|
# 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.
|
# 4.8.6 or higher.
|
||||||
#
|
#
|
||||||
# To use it do the following:
|
# To use it do the following:
|
||||||
# - Install the latest version of global
|
# - 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
|
# - Make sure the INPUT points to the root of the source tree
|
||||||
# - Run doxygen as normal
|
# - Run doxygen as normal
|
||||||
#
|
#
|
||||||
|
|
@ -982,6 +1058,35 @@ USE_HTAGS = NO
|
||||||
|
|
||||||
VERBATIM_HEADERS = YES
|
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
|
# 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
|
# 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
|
# 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
|
# 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
|
# 0 represents red, 60 is yellow, 120 is green, 180 is cyan, 240 is blue, 300
|
||||||
# purple, and 360 is red again.
|
# purple, and 360 is red again.
|
||||||
# Minimum value: 0, maximum value: 359, default value: 220.
|
# 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
|
# 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
|
# 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.
|
# to YES can help to show when doxygen was last run and thus if the
|
||||||
# The default value is: YES.
|
# documentation is up to date.
|
||||||
|
# The default value is: NO.
|
||||||
# This tag requires that the tag GENERATE_HTML is set to YES.
|
# This tag requires that the tag GENERATE_HTML is set to YES.
|
||||||
|
|
||||||
HTML_TIMESTAMP = 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
|
# 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
|
# documentation will contain sections that can be hidden and shown after the
|
||||||
# page has loaded.
|
# 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
|
# 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
|
# generated that can be used as input for Apple's Xcode 3 integrated development
|
||||||
# environment (see: http://developer.apple.com/tools/xcode/), introduced with
|
# environment (see: https://developer.apple.com/xcode/), introduced with OSX
|
||||||
# OSX 10.5 (Leopard). To create a documentation set, doxygen will generate a
|
# 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
|
# Makefile in the HTML output directory. Running make will produce the docset in
|
||||||
# that directory and running make install will install 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
|
# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find it at
|
||||||
# startup. See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html
|
# startup. See https://developer.apple.com/library/archive/featuredarticles/Doxy
|
||||||
# for more information.
|
# genXcode/_index.html for more information.
|
||||||
# The default value is: NO.
|
# The default value is: NO.
|
||||||
# This tag requires that the tag GENERATE_HTML is set to YES.
|
# 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
|
# 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
|
# 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
|
# 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.
|
# Windows.
|
||||||
#
|
#
|
||||||
# The HTML Help Workshop contains a compiler that can convert all HTML output
|
# 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
|
# The QHP_NAMESPACE tag specifies the namespace to use when generating Qt Help
|
||||||
# Project output. For more information please see Qt Help Project / Namespace
|
# 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.
|
# The default value is: org.doxygen.Project.
|
||||||
# This tag requires that the tag GENERATE_QHP is set to YES.
|
# 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
|
# 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
|
# 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).
|
# folders).
|
||||||
# The default value is: doc.
|
# The default value is: doc.
|
||||||
# This tag requires that the tag GENERATE_QHP is set to YES.
|
# 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
|
# 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
|
# 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).
|
# filters).
|
||||||
# This tag requires that the tag GENERATE_QHP is set to YES.
|
# 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
|
# 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
|
# 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).
|
# filters).
|
||||||
# This tag requires that the tag GENERATE_QHP is set to YES.
|
# 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
|
# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this
|
||||||
# project's filter section matches. Qt Help Project / Filter Attributes (see:
|
# 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.
|
# This tag requires that the tag GENERATE_QHP is set to YES.
|
||||||
|
|
||||||
QHP_SECT_FILTER_ATTRS =
|
QHP_SECT_FILTER_ATTRS =
|
||||||
|
|
@ -1405,7 +1522,7 @@ EXT_LINKS_IN_WINDOW = NO
|
||||||
|
|
||||||
FORMULA_FONTSIZE = 10
|
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
|
# generated for formulas are transparent PNGs. Transparent PNGs are not
|
||||||
# supported properly for IE 6.0, but are supported on all modern browsers.
|
# supported properly for IE 6.0, but are supported on all modern browsers.
|
||||||
#
|
#
|
||||||
|
|
@ -1416,8 +1533,14 @@ FORMULA_FONTSIZE = 10
|
||||||
|
|
||||||
FORMULA_TRANSPARENT = YES
|
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
|
# 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
|
# 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
|
# 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
|
# 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
|
# MATHJAX_RELPATH should be ../mathjax. The default value points to the MathJax
|
||||||
# Content Delivery Network so you can quickly see the result without installing
|
# 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. However, it is strongly recommended to install a local copy of
|
||||||
# MathJax from http://www.mathjax.org before deployment.
|
# MathJax from https://www.mathjax.org before deployment.
|
||||||
# The default value is: http://cdn.mathjax.org/mathjax/latest.
|
# 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.
|
# This tag requires that the tag USE_MATHJAX is set to YES.
|
||||||
|
|
||||||
MATHJAX_RELPATH = http://cdn.mathjax.org/mathjax/latest
|
MATHJAX_RELPATH = http://cdn.mathjax.org/mathjax/latest
|
||||||
|
|
@ -1487,7 +1610,7 @@ MATHJAX_CODEFILE =
|
||||||
SEARCHENGINE = YES
|
SEARCHENGINE = YES
|
||||||
|
|
||||||
# When the SERVER_BASED_SEARCH tag is enabled the search engine will be
|
# 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
|
# 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
|
# 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
|
# 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
|
# Doxygen ships with an example indexer (doxyindexer) and search engine
|
||||||
# (doxysearch.cgi) which are based on the open source search engine library
|
# (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.
|
# See the section "External Indexing and Searching" for details.
|
||||||
# The default value is: NO.
|
# The default value is: NO.
|
||||||
|
|
@ -1519,7 +1642,7 @@ EXTERNAL_SEARCH = NO
|
||||||
#
|
#
|
||||||
# Doxygen ships with an example indexer (doxyindexer) and search engine
|
# Doxygen ships with an example indexer (doxyindexer) and search engine
|
||||||
# (doxysearch.cgi) which are based on the open source search engine library
|
# (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.
|
# Searching" for details.
|
||||||
# This tag requires that the tag SEARCHENGINE is set to YES.
|
# 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
|
# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be
|
||||||
# invoked.
|
# invoked.
|
||||||
#
|
#
|
||||||
# Note that when enabling USE_PDFLATEX this option is only used for generating
|
# Note that when not enabling USE_PDFLATEX the default is latex when enabling
|
||||||
# bitmaps for formulas in the HTML output, but not in the Makefile that is
|
# USE_PDFLATEX the default is pdflatex and when in the later case latex is
|
||||||
# written to the output directory.
|
# chosen this is overwritten by pdflatex. For specific output languages the
|
||||||
# The default file is: latex.
|
# 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.
|
# This tag requires that the tag GENERATE_LATEX is set to YES.
|
||||||
|
|
||||||
LATEX_CMD_NAME = latex
|
LATEX_CMD_NAME = latex
|
||||||
|
|
||||||
# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to generate
|
# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to generate
|
||||||
# index for LaTeX.
|
# 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.
|
# The default file is: makeindex.
|
||||||
# This tag requires that the tag GENERATE_LATEX is set to YES.
|
# This tag requires that the tag GENERATE_LATEX is set to YES.
|
||||||
|
|
||||||
MAKEINDEX_CMD_NAME = makeindex
|
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
|
# 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
|
# documents. This may be useful for small projects and may help to save some
|
||||||
# trees in general.
|
# trees in general.
|
||||||
|
|
@ -1604,9 +1741,12 @@ COMPACT_LATEX = NO
|
||||||
PAPER_TYPE = a4
|
PAPER_TYPE = a4
|
||||||
|
|
||||||
# The EXTRA_PACKAGES tag can be used to specify one or more LaTeX package names
|
# 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
|
# that should be included in the LaTeX output. The package can be specified just
|
||||||
# instance you can specify
|
# by its name or with the correct syntax as to be used with the LaTeX
|
||||||
# EXTRA_PACKAGES=times
|
# \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.
|
# If left blank no extra packages will be included.
|
||||||
# This tag requires that the tag GENERATE_LATEX is set to YES.
|
# 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
|
# The LATEX_BIB_STYLE tag can be used to specify the style to use for the
|
||||||
# bibliography, e.g. plainnat, or ieeetr. See
|
# 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.
|
# The default value is: plain.
|
||||||
# This tag requires that the tag GENERATE_LATEX is set to YES.
|
# This tag requires that the tag GENERATE_LATEX is set to YES.
|
||||||
|
|
||||||
LATEX_BIB_STYLE = plain
|
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
|
# Configuration options related to the RTF output
|
||||||
#---------------------------------------------------------------------------
|
#---------------------------------------------------------------------------
|
||||||
|
|
@ -1748,9 +1904,9 @@ COMPACT_RTF = NO
|
||||||
|
|
||||||
RTF_HYPERLINKS = NO
|
RTF_HYPERLINKS = NO
|
||||||
|
|
||||||
# Load stylesheet definitions from file. Syntax is similar to doxygen's config
|
# Load stylesheet definitions from file. Syntax is similar to doxygen's
|
||||||
# file, i.e. a series of assignments. You only have to provide replacements,
|
# configuration file, i.e. a series of assignments. You only have to provide
|
||||||
# missing definitions are set to their default value.
|
# replacements, missing definitions are set to their default value.
|
||||||
#
|
#
|
||||||
# See also section "Doxygen usage" for information on how to generate the
|
# See also section "Doxygen usage" for information on how to generate the
|
||||||
# default style sheet that doxygen normally uses.
|
# default style sheet that doxygen normally uses.
|
||||||
|
|
@ -1759,8 +1915,8 @@ RTF_HYPERLINKS = NO
|
||||||
RTF_STYLESHEET_FILE =
|
RTF_STYLESHEET_FILE =
|
||||||
|
|
||||||
# Set optional variables used in the generation of an RTF document. Syntax is
|
# 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
|
# similar to doxygen's configuration file. A template extensions file can be
|
||||||
# using doxygen -e rtf extensionFile.
|
# generated using doxygen -e rtf extensionFile.
|
||||||
# This tag requires that the tag GENERATE_RTF is set to YES.
|
# This tag requires that the tag GENERATE_RTF is set to YES.
|
||||||
|
|
||||||
RTF_EXTENSIONS_FILE =
|
RTF_EXTENSIONS_FILE =
|
||||||
|
|
@ -1846,6 +2002,13 @@ XML_OUTPUT = xml
|
||||||
|
|
||||||
XML_PROGRAMLISTING = NO
|
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
|
# 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
|
# 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
|
# AutoGen Definitions (see http://autogen.sourceforge.net/) file that captures
|
||||||
# structure of the code including all documentation. Note that this feature is
|
# the structure of the code including all documentation. Note that this feature
|
||||||
# still experimental and incomplete at the moment.
|
# is still experimental and incomplete at the moment.
|
||||||
# The default value is: NO.
|
# The default value is: NO.
|
||||||
|
|
||||||
GENERATE_AUTOGEN_DEF = NO
|
GENERATE_AUTOGEN_DEF = NO
|
||||||
|
|
@ -2047,12 +2210,6 @@ EXTERNAL_GROUPS = YES
|
||||||
|
|
||||||
EXTERNAL_PAGES = 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
|
# Configuration options related to the dot tool
|
||||||
#---------------------------------------------------------------------------
|
#---------------------------------------------------------------------------
|
||||||
|
|
@ -2066,15 +2223,6 @@ PERL_PATH = /usr/bin/perl
|
||||||
|
|
||||||
CLASS_DIAGRAMS = YES
|
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
|
# 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
|
# 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.
|
# 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
|
# 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
|
# Bell Labs. The other options in this section have no effect if this option is
|
||||||
# set to NO
|
# set to NO
|
||||||
# The default value is: NO.
|
# The default value is: YES.
|
||||||
|
|
||||||
HAVE_DOT = NO
|
HAVE_DOT = NO
|
||||||
|
|
||||||
|
|
@ -2207,7 +2355,8 @@ INCLUDED_BY_GRAPH = YES
|
||||||
#
|
#
|
||||||
# Note that enabling this option will significantly increase the time of a run.
|
# 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
|
# 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.
|
# The default value is: NO.
|
||||||
# This tag requires that the tag HAVE_DOT is set to YES.
|
# 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.
|
# 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
|
# 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.
|
# The default value is: NO.
|
||||||
# This tag requires that the tag HAVE_DOT is set to YES.
|
# This tag requires that the tag HAVE_DOT is set to YES.
|
||||||
|
|
||||||
|
|
@ -2241,11 +2391,17 @@ GRAPHICAL_HIERARCHY = YES
|
||||||
DIRECTORY_GRAPH = YES
|
DIRECTORY_GRAPH = YES
|
||||||
|
|
||||||
# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images
|
# 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
|
# 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
|
# to make the SVG files visible in IE 9+ (other browsers do not have this
|
||||||
# requirement).
|
# 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.
|
# The default value is: png.
|
||||||
# This tag requires that the tag HAVE_DOT is set to YES.
|
# This tag requires that the tag HAVE_DOT is set to YES.
|
||||||
|
|
||||||
|
|
@ -2296,6 +2452,11 @@ DIAFILE_DIRS =
|
||||||
|
|
||||||
PLANTUML_JAR_PATH =
|
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
|
# When using plantuml, the specified paths are searched for files specified by
|
||||||
# the !include statement in a plantuml block.
|
# 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);
|
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.
|
/** Returns information about the given SON.
|
||||||
* @param owner_account the name or id of the SON account owner, or the id of the 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
|
* @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);
|
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.
|
/** Creates a SON object owned by the given account.
|
||||||
*
|
*
|
||||||
|
|
@ -1765,6 +1786,55 @@ class wallet_api
|
||||||
uint16_t desired_number_of_sons,
|
uint16_t desired_number_of_sons,
|
||||||
bool broadcast = false);
|
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.
|
/** Vote for a given witness.
|
||||||
*
|
*
|
||||||
* An account can publish a list of all witnesses they approve of. This
|
* An account can publish a list of all witnesses they approve of. This
|
||||||
|
|
@ -2487,9 +2557,46 @@ class wallet_api
|
||||||
bool broadcast = false,
|
bool broadcast = false,
|
||||||
bool to_temp = false );
|
bool to_temp = false );
|
||||||
|
|
||||||
|
|
||||||
std::map<string,std::function<string(fc::variant,const fc::variants&)>> get_result_formatters() const;
|
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;
|
fc::signal<void(bool)> lock_changed;
|
||||||
std::shared_ptr<detail::wallet_api_impl> my;
|
std::shared_ptr<detail::wallet_api_impl> my;
|
||||||
void encrypt_keys();
|
void encrypt_keys();
|
||||||
|
|
@ -2626,8 +2733,10 @@ FC_API( graphene::wallet::wallet_api,
|
||||||
(get_witness)
|
(get_witness)
|
||||||
(is_witness)
|
(is_witness)
|
||||||
(get_committee_member)
|
(get_committee_member)
|
||||||
|
(get_workers)
|
||||||
(list_witnesses)
|
(list_witnesses)
|
||||||
(list_committee_members)
|
(list_committee_members)
|
||||||
|
(list_workers)
|
||||||
(create_son)
|
(create_son)
|
||||||
(try_create_son)
|
(try_create_son)
|
||||||
(update_son)
|
(update_son)
|
||||||
|
|
@ -2643,6 +2752,7 @@ FC_API( graphene::wallet::wallet_api,
|
||||||
(get_son_wallets)
|
(get_son_wallets)
|
||||||
(add_sidechain_address)
|
(add_sidechain_address)
|
||||||
(delete_sidechain_address)
|
(delete_sidechain_address)
|
||||||
|
(sidechain_withdrawal_transaction)
|
||||||
(get_sidechain_addresses_by_account)
|
(get_sidechain_addresses_by_account)
|
||||||
(get_sidechain_addresses_by_sidechain)
|
(get_sidechain_addresses_by_sidechain)
|
||||||
(get_sidechain_address_by_account_and_sidechain)
|
(get_sidechain_address_by_account_and_sidechain)
|
||||||
|
|
@ -2657,6 +2767,7 @@ FC_API( graphene::wallet::wallet_api,
|
||||||
(vote_for_committee_member)
|
(vote_for_committee_member)
|
||||||
(vote_for_son)
|
(vote_for_son)
|
||||||
(update_son_votes)
|
(update_son_votes)
|
||||||
|
(sidechain_deposit_transaction)
|
||||||
(vote_for_witness)
|
(vote_for_witness)
|
||||||
(update_witness_votes)
|
(update_witness_votes)
|
||||||
(set_voting_proxy)
|
(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_id)
|
||||||
(get_custom_account_authorities_by_permission_name)
|
(get_custom_account_authorities_by_permission_name)
|
||||||
(get_active_custom_account_authorities_by_operation)
|
(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/api_documentation.hpp>
|
||||||
#include <graphene/wallet/reflect_util.hpp>
|
#include <graphene/wallet/reflect_util.hpp>
|
||||||
#include <graphene/debug_witness/debug_api.hpp>
|
#include <graphene/debug_witness/debug_api.hpp>
|
||||||
|
#include <graphene/peerplays_sidechain/sidechain_api.hpp>
|
||||||
|
|
||||||
#ifndef WIN32
|
#ifndef WIN32
|
||||||
# include <sys/types.h>
|
# include <sys/types.h>
|
||||||
|
|
@ -749,7 +750,7 @@ public:
|
||||||
{
|
{
|
||||||
std::string account_id = account_id_to_string(id);
|
std::string account_id = account_id_to_string(id);
|
||||||
auto rec = _remote_db->get_accounts({account_id}).front();
|
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;
|
return *rec;
|
||||||
}
|
}
|
||||||
account_object get_account(string account_name_or_id) const
|
account_object get_account(string account_name_or_id) const
|
||||||
|
|
@ -762,7 +763,7 @@ public:
|
||||||
return get_account(*id);
|
return get_account(*id);
|
||||||
} else {
|
} else {
|
||||||
auto rec = _remote_db->lookup_account_names({account_name_or_id}).front();
|
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;
|
return *rec;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1946,7 +1947,7 @@ public:
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
account_id_type owner_account_id = get_account_id(owner_account);
|
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)
|
if (son)
|
||||||
return *son;
|
return *son;
|
||||||
else
|
else
|
||||||
|
|
@ -1961,6 +1962,49 @@ public:
|
||||||
FC_CAPTURE_AND_RETHROW( (owner_account) )
|
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)
|
bool is_witness(string owner_account)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
|
|
@ -2075,7 +2119,7 @@ public:
|
||||||
son_create_op.pay_vb = pay_vb_id;
|
son_create_op.pay_vb = pay_vb_id;
|
||||||
son_create_op.sidechain_public_keys = sidechain_public_keys;
|
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));
|
FC_THROW("Account ${owner_account} is already a SON", ("owner_account", owner_account));
|
||||||
|
|
||||||
signed_transaction tx;
|
signed_transaction tx;
|
||||||
|
|
@ -2202,11 +2246,8 @@ public:
|
||||||
vector<std::string> owners;
|
vector<std::string> owners;
|
||||||
for(auto obj: son_objects)
|
for(auto obj: son_objects)
|
||||||
{
|
{
|
||||||
if (obj)
|
std::string acc_id = account_id_to_string(obj->son_account);
|
||||||
{
|
owners.push_back(acc_id);
|
||||||
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);
|
vector< optional< account_object> > accs = _remote_db->get_accounts(owners);
|
||||||
std::remove_if(son_objects.begin(), son_objects.end(),
|
std::remove_if(son_objects.begin(), son_objects.end(),
|
||||||
|
|
@ -2216,9 +2257,7 @@ public:
|
||||||
std::inserter(result, result.end()),
|
std::inserter(result, result.end()),
|
||||||
[](fc::optional<account_object>& acct, fc::optional<son_object> son) {
|
[](fc::optional<account_object>& acct, fc::optional<son_object> son) {
|
||||||
FC_ASSERT(acct, "Invalid active SONs list in global properties.");
|
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));
|
|
||||||
return std::make_pair<string, son_id_type>(string(acct->name), std::move(son_id_type()));
|
|
||||||
});
|
});
|
||||||
return result;
|
return result;
|
||||||
} FC_CAPTURE_AND_RETHROW() }
|
} FC_CAPTURE_AND_RETHROW() }
|
||||||
|
|
@ -2323,6 +2362,64 @@ public:
|
||||||
|
|
||||||
} FC_CAPTURE_AND_RETHROW() }
|
} 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,
|
signed_transaction create_witness(string owner_account,
|
||||||
string url,
|
string url,
|
||||||
bool broadcast /* = false */)
|
bool broadcast /* = false */)
|
||||||
|
|
@ -2717,7 +2814,7 @@ public:
|
||||||
|
|
||||||
account_object voting_account_object = get_account(voting_account);
|
account_object voting_account_object = get_account(voting_account);
|
||||||
account_id_type son_account_id = get_account_id(son);
|
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)
|
if (!son_obj)
|
||||||
FC_THROW("Account ${son} is not registered as a son", ("son", son));
|
FC_THROW("Account ${son} is not registered as a son", ("son", son));
|
||||||
if (approve)
|
if (approve)
|
||||||
|
|
@ -2761,7 +2858,7 @@ public:
|
||||||
for (const std::string& son : sons_to_approve)
|
for (const std::string& son : sons_to_approve)
|
||||||
{
|
{
|
||||||
account_id_type son_owner_account_id = get_account_id(son);
|
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)
|
if (!son_obj)
|
||||||
FC_THROW("Account ${son} is not registered as a SON", ("son", son));
|
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);
|
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)
|
for (const std::string& son : sons_to_reject)
|
||||||
{
|
{
|
||||||
account_id_type son_owner_account_id = get_account_id(son);
|
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)
|
if (!son_obj)
|
||||||
FC_THROW("Account ${son} is not registered as a SON", ("son", son));
|
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);
|
unsigned votes_removed = voting_account_object.options.votes.erase(son_obj->vote_id);
|
||||||
|
|
@ -2792,6 +2889,81 @@ public:
|
||||||
return sign_transaction( tx, broadcast );
|
return sign_transaction( tx, broadcast );
|
||||||
} FC_CAPTURE_AND_RETHROW( (voting_account)(sons_to_approve)(sons_to_reject)(desired_number_of_sons)(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,
|
signed_transaction vote_for_witness(string voting_account,
|
||||||
string witness,
|
string witness,
|
||||||
bool approve,
|
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 )
|
void network_add_nodes( const vector<string>& nodes )
|
||||||
{
|
{
|
||||||
use_network_node_api();
|
use_network_node_api();
|
||||||
|
|
@ -4087,6 +4279,52 @@ public:
|
||||||
return it->second;
|
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;
|
string _wallet_filename;
|
||||||
wallet_data _wallet;
|
wallet_data _wallet;
|
||||||
|
|
||||||
|
|
@ -4101,6 +4339,7 @@ public:
|
||||||
fc::api<bookie_api> _remote_bookie;
|
fc::api<bookie_api> _remote_bookie;
|
||||||
optional< fc::api<network_node_api> > _remote_net_node;
|
optional< fc::api<network_node_api> > _remote_net_node;
|
||||||
optional< fc::api<graphene::debug_witness::debug_api> > _remote_debug;
|
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;
|
flat_map<string, operation> _prototype_ops;
|
||||||
|
|
||||||
|
|
@ -4184,27 +4423,33 @@ string operation_printer::operator()(const transfer_operation& op) const
|
||||||
std::string memo;
|
std::string memo;
|
||||||
if( op.memo )
|
if( op.memo )
|
||||||
{
|
{
|
||||||
if( wallet.is_locked() )
|
bool is_encrypted = ((op.memo->from != public_key_type()) && (op.memo->to != public_key_type()));
|
||||||
{
|
if (is_encrypted) {
|
||||||
out << " -- Unlock wallet to see memo.";
|
if( wallet.is_locked() )
|
||||||
} else {
|
{
|
||||||
try {
|
out << " -- Unlock wallet to see memo.";
|
||||||
FC_ASSERT(wallet._keys.count(op.memo->to) || wallet._keys.count(op.memo->from), "Memo is encrypted to a key ${to} or ${from} not in this wallet.", ("to", op.memo->to)("from",op.memo->from));
|
} else {
|
||||||
if( wallet._keys.count(op.memo->to) ) {
|
try {
|
||||||
auto my_key = wif_to_key(wallet._keys.at(op.memo->to));
|
FC_ASSERT(wallet._keys.count(op.memo->to) || wallet._keys.count(op.memo->from), "Memo is encrypted to a key ${to} or ${from} not in this wallet.", ("to", op.memo->to)("from",op.memo->from));
|
||||||
FC_ASSERT(my_key, "Unable to recover private key to decrypt memo. Wallet may be corrupted.");
|
if( wallet._keys.count(op.memo->to) ) {
|
||||||
memo = op.memo->get_message(*my_key, op.memo->from);
|
auto my_key = wif_to_key(wallet._keys.at(op.memo->to));
|
||||||
out << " -- Memo: " << memo;
|
FC_ASSERT(my_key, "Unable to recover private key to decrypt memo. Wallet may be corrupted.");
|
||||||
} else {
|
memo = op.memo->get_message(*my_key, op.memo->from);
|
||||||
auto my_key = wif_to_key(wallet._keys.at(op.memo->from));
|
out << " -- Memo: " << memo;
|
||||||
FC_ASSERT(my_key, "Unable to recover private key to decrypt memo. Wallet may be corrupted.");
|
} else {
|
||||||
memo = op.memo->get_message(*my_key, op.memo->to);
|
auto my_key = wif_to_key(wallet._keys.at(op.memo->from));
|
||||||
out << " -- Memo: " << memo;
|
FC_ASSERT(my_key, "Unable to recover private key to decrypt memo. Wallet may be corrupted.");
|
||||||
|
memo = op.memo->get_message(*my_key, op.memo->to);
|
||||||
|
out << " -- Memo: " << memo;
|
||||||
|
}
|
||||||
|
} catch (const fc::exception& e) {
|
||||||
|
out << " -- could not decrypt memo";
|
||||||
|
elog("Error when decrypting memo: ${e}", ("e", e.to_detail_string()));
|
||||||
}
|
}
|
||||||
} catch (const fc::exception& e) {
|
|
||||||
out << " -- could not decrypt memo";
|
|
||||||
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);
|
fee(op.fee);
|
||||||
|
|
@ -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
|
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;
|
vector<operation_detail> result;
|
||||||
|
|
||||||
while (limit > 0)
|
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( 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;
|
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
|
asset_object wallet_api::get_asset(string asset_name_or_id) const
|
||||||
{
|
{
|
||||||
auto a = my->find_asset(asset_name_or_id);
|
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;
|
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)
|
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
|
// backup wallet
|
||||||
fc::optional<fc::ecc::private_key> optional_private_key = wif_to_key(wif_key);
|
fc::optional<fc::ecc::private_key> optional_private_key = wif_to_key(wif_key);
|
||||||
if (!optional_private_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 )
|
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 ) );
|
FC_ASSERT( fc::exists( filename ) );
|
||||||
|
|
||||||
const auto imported_keys = fc::json::from_file<exported_keys>( 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 )
|
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 ) );
|
FC_ASSERT( fc::exists( filename ) );
|
||||||
|
|
||||||
bool is_my_account = false;
|
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);
|
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)
|
son_object wallet_api::get_son(string owner_account)
|
||||||
{
|
{
|
||||||
return my->get_son(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);
|
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,
|
signed_transaction wallet_api::create_vesting_balance(string owner_account,
|
||||||
string amount,
|
string amount,
|
||||||
string asset_symbol,
|
string asset_symbol,
|
||||||
|
|
@ -5140,6 +5398,29 @@ signed_transaction wallet_api::delete_sidechain_address(string account,
|
||||||
return my->delete_sidechain_address(account, sidechain, broadcast);
|
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)
|
vector<optional<sidechain_address_object>> wallet_api::get_sidechain_addresses_by_account(string account)
|
||||||
{
|
{
|
||||||
account_id_type account_id = get_account_id(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);
|
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,
|
signed_transaction wallet_api::vote_for_witness(string voting_account,
|
||||||
string witness,
|
string witness,
|
||||||
bool approve,
|
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)
|
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);
|
my->dbg_make_uia(creator, symbol);
|
||||||
}
|
}
|
||||||
|
|
||||||
void wallet_api::dbg_make_mia(string creator, string 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);
|
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)
|
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);
|
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,
|
signed_transaction wallet_api::borrow_asset(string seller_name, string amount_to_sell,
|
||||||
string asset_symbol, string amount_of_collateral, bool broadcast)
|
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);
|
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)
|
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);
|
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
|
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;
|
map<string,public_key_type> result;
|
||||||
for( const auto& item : my->_wallet.labeled_keys )
|
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 )
|
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);
|
auto label_itr = my->_wallet.labeled_keys.get<by_label>().find(label);
|
||||||
if( label_itr != my->_wallet.labeled_keys.get<by_label>().end() )
|
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;
|
blind_confirmation confirm;
|
||||||
try {
|
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 from_key = get_public_key(from_key_or_label);
|
||||||
public_key_type to_key = get_public_key(to_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,
|
vector<pair<string, string>> to_amounts,
|
||||||
bool broadcast )
|
bool broadcast )
|
||||||
{ try {
|
{ try {
|
||||||
FC_ASSERT( !is_locked() );
|
FC_ASSERT( !is_locked(), "Wallet is locked, please unlock to get all operations available" );
|
||||||
idump((to_amounts));
|
idump((to_amounts));
|
||||||
|
|
||||||
blind_confirmation confirm;
|
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 )
|
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);
|
stealth_confirmation conf(confirmation_receipt);
|
||||||
FC_ASSERT( conf.to );
|
FC_ASSERT( conf.to );
|
||||||
|
|
||||||
|
|
@ -6422,7 +6726,7 @@ signed_transaction wallet_api::propose_create_sport(
|
||||||
internationalized_string_type name,
|
internationalized_string_type name,
|
||||||
bool broadcast /*= false*/)
|
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;
|
const chain_parameters& current_params = get_global_properties().parameters;
|
||||||
|
|
||||||
sport_create_operation sport_create_op;
|
sport_create_operation sport_create_op;
|
||||||
|
|
@ -6450,7 +6754,7 @@ signed_transaction wallet_api::propose_update_sport(
|
||||||
fc::optional<internationalized_string_type> name,
|
fc::optional<internationalized_string_type> name,
|
||||||
bool broadcast /*= false*/)
|
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;
|
const chain_parameters& current_params = get_global_properties().parameters;
|
||||||
|
|
||||||
sport_update_operation sport_update_op;
|
sport_update_operation sport_update_op;
|
||||||
|
|
@ -6478,7 +6782,7 @@ signed_transaction wallet_api::propose_delete_sport(
|
||||||
sport_id_type sport_id,
|
sport_id_type sport_id,
|
||||||
bool broadcast /*= false*/)
|
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;
|
const chain_parameters& current_params = get_global_properties().parameters;
|
||||||
|
|
||||||
sport_delete_operation sport_delete_op;
|
sport_delete_operation sport_delete_op;
|
||||||
|
|
@ -6506,7 +6810,7 @@ signed_transaction wallet_api::propose_create_event_group(
|
||||||
sport_id_type sport_id,
|
sport_id_type sport_id,
|
||||||
bool broadcast /*= false*/)
|
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;
|
const chain_parameters& current_params = get_global_properties().parameters;
|
||||||
|
|
||||||
event_group_create_operation event_group_create_op;
|
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,
|
fc::optional<internationalized_string_type> name,
|
||||||
bool broadcast /*= false*/)
|
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;
|
const chain_parameters& current_params = get_global_properties().parameters;
|
||||||
|
|
||||||
event_group_update_operation event_group_update_op;
|
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,
|
event_group_id_type event_group,
|
||||||
bool broadcast /*= false*/)
|
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;
|
const chain_parameters& current_params = get_global_properties().parameters;
|
||||||
|
|
||||||
event_group_delete_operation event_group_delete_op;
|
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,
|
event_group_id_type event_group_id,
|
||||||
bool broadcast /*= false*/)
|
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;
|
const chain_parameters& current_params = get_global_properties().parameters;
|
||||||
|
|
||||||
event_create_operation event_create_op;
|
event_create_operation event_create_op;
|
||||||
|
|
@ -6630,7 +6934,7 @@ signed_transaction wallet_api::propose_update_event(
|
||||||
fc::optional<time_point_sec> start_time,
|
fc::optional<time_point_sec> start_time,
|
||||||
bool broadcast /*= false*/)
|
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;
|
const chain_parameters& current_params = get_global_properties().parameters;
|
||||||
|
|
||||||
event_update_operation event_update_op;
|
event_update_operation event_update_op;
|
||||||
|
|
@ -6663,7 +6967,7 @@ signed_transaction wallet_api::propose_create_betting_market_rules(
|
||||||
internationalized_string_type description,
|
internationalized_string_type description,
|
||||||
bool broadcast /*= false*/)
|
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;
|
const chain_parameters& current_params = get_global_properties().parameters;
|
||||||
|
|
||||||
betting_market_rules_create_operation betting_market_rules_create_op;
|
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,
|
fc::optional<internationalized_string_type> description,
|
||||||
bool broadcast /*= false*/)
|
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;
|
const chain_parameters& current_params = get_global_properties().parameters;
|
||||||
|
|
||||||
betting_market_rules_update_operation betting_market_rules_update_op;
|
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,
|
asset_id_type asset_id,
|
||||||
bool broadcast /*= false*/)
|
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;
|
const chain_parameters& current_params = get_global_properties().parameters;
|
||||||
|
|
||||||
betting_market_group_create_operation betting_market_group_create_op;
|
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,
|
fc::optional<betting_market_group_status> status,
|
||||||
bool broadcast /*= false*/)
|
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;
|
const chain_parameters& current_params = get_global_properties().parameters;
|
||||||
|
|
||||||
betting_market_group_update_operation betting_market_group_update_op;
|
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,
|
internationalized_string_type payout_condition,
|
||||||
bool broadcast /*= false*/)
|
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;
|
const chain_parameters& current_params = get_global_properties().parameters;
|
||||||
|
|
||||||
betting_market_create_operation betting_market_create_op;
|
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,
|
fc::optional<internationalized_string_type> payout_condition,
|
||||||
bool broadcast /*= false*/)
|
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;
|
const chain_parameters& current_params = get_global_properties().parameters;
|
||||||
|
|
||||||
betting_market_update_operation betting_market_update_op;
|
betting_market_update_operation betting_market_update_op;
|
||||||
|
|
@ -6854,7 +7158,7 @@ signed_transaction wallet_api::place_bet(string betting_account,
|
||||||
double backer_multiplier,
|
double backer_multiplier,
|
||||||
bool broadcast /*= false*/)
|
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::optional<asset_object> asset_obj = get_asset(asset_symbol);
|
||||||
FC_ASSERT(asset_obj, "Could not find asset matching ${asset}", ("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,
|
bet_id_type bet_id,
|
||||||
bool broadcast /*= false*/)
|
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;
|
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,
|
const std::map<betting_market_id_type, betting_market_resolution_type>& resolutions,
|
||||||
bool broadcast /*= false*/)
|
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;
|
const chain_parameters& current_params = get_global_properties().parameters;
|
||||||
|
|
||||||
betting_market_group_resolve_operation betting_market_group_resolve_op;
|
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,
|
betting_market_group_id_type betting_market_group_id,
|
||||||
bool broadcast /*= false*/)
|
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;
|
const chain_parameters& current_params = get_global_properties().parameters;
|
||||||
|
|
||||||
betting_market_group_cancel_unmatched_bets_operation betting_market_group_cancel_unmatched_bets_op;
|
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 )
|
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);
|
account_object creator_account_obj = get_account(creator);
|
||||||
|
|
||||||
signed_transaction tx;
|
signed_transaction tx;
|
||||||
|
|
@ -6974,7 +7278,7 @@ signed_transaction wallet_api::tournament_join( string payer_account,
|
||||||
string buy_in_asset_symbol,
|
string buy_in_asset_symbol,
|
||||||
bool broadcast )
|
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 payer_account_obj = get_account(payer_account);
|
||||||
account_object player_account_obj = get_account(player_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);
|
//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,
|
tournament_id_type tournament_id,
|
||||||
bool broadcast)
|
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 player_account_obj = get_account(player_account);
|
||||||
account_object canceling_account_obj = get_account(canceling_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);
|
//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,
|
rock_paper_scissors_gesture gesture,
|
||||||
bool broadcast)
|
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
|
// 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);
|
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) );
|
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
|
// default ctor necessary for FC_REFLECT
|
||||||
signed_block_with_info::signed_block_with_info( const signed_block& block )
|
signed_block_with_info::signed_block_with_info( const signed_block& block )
|
||||||
: signed_block( block )
|
: signed_block( block )
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@
|
||||||
import json
|
import json
|
||||||
import os
|
import os
|
||||||
import re
|
import re
|
||||||
import xml.etree.ElementTree as etree
|
import defusedxml.ElementTree as etree
|
||||||
|
|
||||||
def process_node(path, node):
|
def process_node(path, node):
|
||||||
"""
|
"""
|
||||||
|
|
|
||||||
|
|
@ -27,8 +27,18 @@
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <iterator>
|
#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/json.hpp>
|
||||||
#include <fc/io/stdio.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/server.hpp>
|
||||||
#include <fc/network/http/websocket.hpp>
|
#include <fc/network/http/websocket.hpp>
|
||||||
#include <fc/rpc/cli.hpp>
|
#include <fc/rpc/cli.hpp>
|
||||||
|
|
@ -40,25 +50,14 @@
|
||||||
#include <graphene/chain/config.hpp>
|
#include <graphene/chain/config.hpp>
|
||||||
#include <graphene/chain/protocol/protocol.hpp>
|
#include <graphene/chain/protocol/protocol.hpp>
|
||||||
#include <graphene/egenesis/egenesis.hpp>
|
#include <graphene/egenesis/egenesis.hpp>
|
||||||
|
#include <graphene/utilities/git_revision.hpp>
|
||||||
#include <graphene/utilities/key_conversion.hpp>
|
#include <graphene/utilities/key_conversion.hpp>
|
||||||
#include <graphene/wallet/wallet.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
|
#ifdef WIN32
|
||||||
# include <signal.h>
|
#include <signal.h>
|
||||||
#else
|
#else
|
||||||
# include <csignal>
|
#include <csignal>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
using namespace graphene::app;
|
using namespace graphene::app;
|
||||||
|
|
@ -68,44 +67,54 @@ using namespace graphene::wallet;
|
||||||
using namespace std;
|
using namespace std;
|
||||||
namespace bpo = boost::program_options;
|
namespace bpo = boost::program_options;
|
||||||
|
|
||||||
int main( int argc, char** argv )
|
int main(int argc, char **argv) {
|
||||||
{
|
|
||||||
try {
|
try {
|
||||||
|
|
||||||
boost::program_options::options_description opts;
|
boost::program_options::options_description opts;
|
||||||
opts.add_options()
|
opts.add_options()("help,h", "Print this help message and exit.");
|
||||||
("help,h", "Print this help message and exit.")
|
opts.add_options()("version,v", "Display the version info and exit");
|
||||||
("version", "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");
|
||||||
("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");
|
||||||
("server-rpc-user,u", bpo::value<string>(), "Server Username")
|
opts.add_options()("server-rpc-password,p", bpo::value<string>(), "Server Password");
|
||||||
("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");
|
||||||
("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");
|
||||||
("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");
|
||||||
("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");
|
||||||
("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");
|
||||||
("daemon,d", "Run the wallet in daemon mode" )
|
opts.add_options()("wallet-file,w", bpo::value<string>()->implicit_value("wallet.json"), "wallet to load");
|
||||||
("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");
|
||||||
("chain-id", bpo::value<string>(), "chain ID to connect to");
|
|
||||||
|
|
||||||
bpo::variables_map options;
|
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";
|
std::cout << opts << "\n";
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (options.count("version"))
|
if (options.count("version")) {
|
||||||
{
|
|
||||||
std::string wallet_version(graphene::utilities::git_revision_description);
|
std::string wallet_version(graphene::utilities::git_revision_description);
|
||||||
const size_t pos = wallet_version.find('/');
|
const size_t pos = wallet_version.find('/');
|
||||||
if( pos != std::string::npos && wallet_version.size() > pos )
|
if (pos != std::string::npos && wallet_version.size() > pos)
|
||||||
wallet_version = wallet_version.substr( pos + 1 );
|
wallet_version = wallet_version.substr(pos + 1);
|
||||||
std::cerr << "Version: " << wallet_version << "\n";
|
std::cout << "Version: " << wallet_version << "\n";
|
||||||
std::cerr << "Git Revision: " << graphene::utilities::git_revision_sha << "\n";
|
std::cout << "Git Revision: " << graphene::utilities::git_revision_sha << "\n";
|
||||||
std::cerr << "Built: " << __DATE__ " at " __TIME__ << "\n";
|
std::cout << "Built: " << __DATE__ " at " __TIME__ << "\n";
|
||||||
std::cout << "SSL: " << OPENSSL_VERSION_TEXT << "\n";
|
std::cout << "SSL: " << OPENSSL_VERSION_TEXT << "\n";
|
||||||
std::cout << "Boost: " << boost::replace_all_copy(std::string(BOOST_LIB_VERSION), "_", ".") << "\n";
|
std::cout << "Boost: " << boost::replace_all_copy(std::string(BOOST_LIB_VERSION), "_", ".") << "\n";
|
||||||
return 0;
|
return 0;
|
||||||
|
|
@ -116,33 +125,33 @@ int main( int argc, char** argv )
|
||||||
fc::path log_dir = data_dir / "logs";
|
fc::path log_dir = data_dir / "logs";
|
||||||
|
|
||||||
fc::file_appender::config ac;
|
fc::file_appender::config ac;
|
||||||
ac.filename = log_dir / "rpc" / "rpc.log";
|
ac.filename = log_dir / "rpc" / "rpc.log";
|
||||||
ac.flush = true;
|
ac.flush = true;
|
||||||
ac.rotate = true;
|
ac.rotate = true;
|
||||||
ac.rotation_interval = fc::hours( 1 );
|
ac.rotation_interval = fc::hours(1);
|
||||||
ac.rotation_limit = fc::days( 1 );
|
ac.rotation_limit = fc::days(1);
|
||||||
|
|
||||||
std::cout << "Logging RPC to file: " << (data_dir / ac.filename).preferred_string() << "\n";
|
std::cout << "Logging RPC to file: " << (data_dir / ac.filename).preferred_string() << "\n";
|
||||||
|
|
||||||
cfg.appenders.push_back(fc::appender_config( "default", "console", fc::variant(fc::console_appender::config(), 20)));
|
cfg.appenders.push_back(fc::appender_config("default", "console", fc::variant(fc::console_appender::config(), 20)));
|
||||||
cfg.appenders.push_back(fc::appender_config( "rpc", "file", fc::variant(ac, 5)));
|
cfg.appenders.push_back(fc::appender_config("rpc", "file", fc::variant(ac, 5)));
|
||||||
|
|
||||||
cfg.loggers = { fc::logger_config("default"), fc::logger_config( "rpc") };
|
cfg.loggers = {fc::logger_config("default"), fc::logger_config("rpc")};
|
||||||
cfg.loggers.front().level = fc::log_level::warn;
|
cfg.loggers.front().level = fc::log_level::warn;
|
||||||
cfg.loggers.front().appenders = {"default"};
|
cfg.loggers.front().appenders = {"default"};
|
||||||
cfg.loggers.back().level = fc::log_level::info;
|
cfg.loggers.back().level = fc::log_level::info;
|
||||||
cfg.loggers.back().appenders = {"rpc"};
|
cfg.loggers.back().appenders = {"rpc"};
|
||||||
|
|
||||||
fc::configure_logging( cfg );
|
fc::configure_logging(cfg);
|
||||||
|
|
||||||
fc::ecc::private_key committee_private_key = fc::ecc::private_key::regenerate(fc::sha256::hash(string("null_key")));
|
fc::ecc::private_key committee_private_key = fc::ecc::private_key::regenerate(fc::sha256::hash(string("null_key")));
|
||||||
|
|
||||||
idump( (key_to_wif( committee_private_key ) ) );
|
idump((key_to_wif(committee_private_key)));
|
||||||
|
|
||||||
fc::ecc::private_key nathan_private_key = fc::ecc::private_key::regenerate(fc::sha256::hash(string("nathan")));
|
fc::ecc::private_key nathan_private_key = fc::ecc::private_key::regenerate(fc::sha256::hash(string("nathan")));
|
||||||
public_key_type nathan_pub_key = nathan_private_key.get_public_key();
|
public_key_type nathan_pub_key = nathan_private_key.get_public_key();
|
||||||
idump( (nathan_pub_key) );
|
idump((nathan_pub_key));
|
||||||
idump( (key_to_wif( nathan_private_key ) ) );
|
idump((key_to_wif(nathan_private_key)));
|
||||||
|
|
||||||
//
|
//
|
||||||
// TODO: We read wallet_data twice, once in main() to grab the
|
// TODO: We read wallet_data twice, once in main() to grab the
|
||||||
|
|
@ -152,153 +161,136 @@ int main( int argc, char** argv )
|
||||||
//
|
//
|
||||||
wallet_data wdata;
|
wallet_data wdata;
|
||||||
|
|
||||||
fc::path wallet_file( options.count("wallet-file") ? options.at("wallet-file").as<string>() : "wallet.json");
|
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);
|
||||||
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
|
// 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";
|
std::cout << "Chain ID in wallet file does not match specified chain ID\n";
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
else
|
if (options.count("chain-id")) {
|
||||||
{
|
|
||||||
if( options.count("chain-id") )
|
|
||||||
{
|
|
||||||
wdata.chain_id = chain_id_type(options.at("chain-id").as<std::string>());
|
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";
|
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();
|
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";
|
std::cout << "Starting a new wallet with chain ID " << wdata.chain_id.str() << " (from egenesis)\n";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// but allow CLI to override
|
// but allow CLI to override
|
||||||
if( options.count("server-rpc-endpoint") )
|
if (options.count("server-rpc-endpoint"))
|
||||||
wdata.ws_server = options.at("server-rpc-endpoint").as<std::string>();
|
wdata.ws_server = options.at("server-rpc-endpoint").as<std::string>();
|
||||||
if( options.count("server-rpc-user") )
|
if (options.count("server-rpc-user"))
|
||||||
wdata.ws_user = options.at("server-rpc-user").as<std::string>();
|
wdata.ws_user = options.at("server-rpc-user").as<std::string>();
|
||||||
if( options.count("server-rpc-password") )
|
if (options.count("server-rpc-password"))
|
||||||
wdata.ws_password = options.at("server-rpc-password").as<std::string>();
|
wdata.ws_password = options.at("server-rpc-password").as<std::string>();
|
||||||
|
|
||||||
fc::http::websocket_client client;
|
fc::http::websocket_client client;
|
||||||
idump((wdata.ws_server));
|
idump((wdata.ws_server));
|
||||||
auto con = client.connect( wdata.ws_server );
|
auto con = client.connect(wdata.ws_server);
|
||||||
auto apic = std::make_shared<fc::rpc::websocket_api_connection>(con, GRAPHENE_MAX_NESTED_OBJECTS);
|
auto apic = std::make_shared<fc::rpc::websocket_api_connection>(con, GRAPHENE_MAX_NESTED_OBJECTS);
|
||||||
|
|
||||||
auto remote_api = apic->get_remote_api< login_api >(1);
|
auto remote_api = apic->get_remote_api<login_api>(1);
|
||||||
edump((wdata.ws_user)(wdata.ws_password) );
|
edump((wdata.ws_user)(wdata.ws_password));
|
||||||
FC_ASSERT( remote_api->login( wdata.ws_user, wdata.ws_password ), "Failed to log in to API server" );
|
FC_ASSERT(remote_api->login(wdata.ws_user, wdata.ws_password), "Failed to log in to API server");
|
||||||
|
|
||||||
auto wapiptr = std::make_shared<wallet_api>( wdata, remote_api );
|
auto wapiptr = std::make_shared<wallet_api>(wdata, remote_api);
|
||||||
wapiptr->set_wallet_filename( wallet_file.generic_string() );
|
wapiptr->set_wallet_filename(wallet_file.generic_string());
|
||||||
wapiptr->load_wallet_file();
|
wapiptr->load_wallet_file();
|
||||||
|
|
||||||
fc::api<wallet_api> wapi(wapiptr);
|
fc::api<wallet_api> wapi(wapiptr);
|
||||||
|
|
||||||
auto wallet_cli = std::make_shared<fc::rpc::cli>( GRAPHENE_MAX_NESTED_OBJECTS );
|
auto wallet_cli = std::make_shared<fc::rpc::cli>(GRAPHENE_MAX_NESTED_OBJECTS);
|
||||||
for( auto& name_formatter : wapiptr->get_result_formatters() )
|
for (auto &name_formatter : wapiptr->get_result_formatters())
|
||||||
wallet_cli->format_result( name_formatter.first, name_formatter.second );
|
wallet_cli->format_result(name_formatter.first, name_formatter.second);
|
||||||
|
|
||||||
boost::signals2::scoped_connection closed_connection(con->closed.connect([wallet_cli]{
|
boost::signals2::scoped_connection closed_connection(con->closed.connect([wallet_cli] {
|
||||||
cerr << "Server has disconnected us.\n";
|
cerr << "Server has disconnected us.\n";
|
||||||
wallet_cli->stop();
|
wallet_cli->stop();
|
||||||
}));
|
}));
|
||||||
(void)(closed_connection);
|
(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";
|
std::cout << "Please use the set_password method to initialize a new wallet before continuing\n";
|
||||||
wallet_cli->set_prompt( "new >>> " );
|
wallet_cli->set_prompt("new >>> ");
|
||||||
} else
|
} else
|
||||||
wallet_cli->set_prompt( "locked >>> " );
|
wallet_cli->set_prompt("locked >>> ");
|
||||||
|
|
||||||
boost::signals2::scoped_connection locked_connection(wapiptr->lock_changed.connect([&](bool locked) {
|
boost::signals2::scoped_connection locked_connection(wapiptr->lock_changed.connect([&](bool locked) {
|
||||||
wallet_cli->set_prompt( locked ? "locked >>> " : "unlocked >>> " );
|
wallet_cli->set_prompt(locked ? "locked >>> " : "unlocked >>> ");
|
||||||
}));
|
}));
|
||||||
|
|
||||||
std::shared_ptr<fc::http::websocket_server> _websocket_server;
|
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 = std::make_shared<fc::http::websocket_server>();
|
||||||
_websocket_server->on_connection([&wapi]( const fc::http::websocket_connection_ptr& c ){
|
_websocket_server->on_connection([&wapi](const fc::http::websocket_connection_ptr &c) {
|
||||||
std::cout << "here... \n";
|
std::cout << "here... \n";
|
||||||
wlog("." );
|
wlog(".");
|
||||||
auto wsc = std::make_shared<fc::rpc::websocket_api_connection>(c, GRAPHENE_MAX_NESTED_OBJECTS);
|
auto wsc = std::make_shared<fc::rpc::websocket_api_connection>(c, GRAPHENE_MAX_NESTED_OBJECTS);
|
||||||
wsc->register_api(wapi);
|
wsc->register_api(wapi);
|
||||||
c->set_session_data( wsc );
|
c->set_session_data(wsc);
|
||||||
});
|
});
|
||||||
ilog( "Listening for incoming RPC requests on ${p}", ("p", options.at("rpc-endpoint").as<string>() ));
|
ilog("Listening for incoming RPC requests on ${p}", ("p", options.at("rpc-endpoint").as<string>()));
|
||||||
_websocket_server->listen( fc::ip::endpoint::from_string(options.at("rpc-endpoint").as<string>()) );
|
_websocket_server->listen(fc::ip::endpoint::from_string(options.at("rpc-endpoint").as<string>()));
|
||||||
_websocket_server->start_accept();
|
_websocket_server->start_accept();
|
||||||
}
|
}
|
||||||
|
|
||||||
string cert_pem = "server.pem";
|
string cert_pem = "server.pem";
|
||||||
if( options.count( "rpc-tls-certificate" ) )
|
if (options.count("rpc-tls-certificate"))
|
||||||
cert_pem = options.at("rpc-tls-certificate").as<string>();
|
cert_pem = options.at("rpc-tls-certificate").as<string>();
|
||||||
|
|
||||||
std::shared_ptr<fc::http::websocket_tls_server> _websocket_tls_server;
|
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 = std::make_shared<fc::http::websocket_tls_server>(cert_pem);
|
||||||
_websocket_tls_server->on_connection([&]( const fc::http::websocket_connection_ptr& c ){
|
_websocket_tls_server->on_connection([&](const fc::http::websocket_connection_ptr &c) {
|
||||||
auto wsc = std::make_shared<fc::rpc::websocket_api_connection>(c, GRAPHENE_MAX_NESTED_OBJECTS);
|
auto wsc = std::make_shared<fc::rpc::websocket_api_connection>(c, GRAPHENE_MAX_NESTED_OBJECTS);
|
||||||
wsc->register_api(wapi);
|
wsc->register_api(wapi);
|
||||||
c->set_session_data( wsc );
|
c->set_session_data(wsc);
|
||||||
});
|
});
|
||||||
ilog( "Listening for incoming TLS RPC requests on ${p}", ("p", options.at("rpc-tls-endpoint").as<string>() ));
|
ilog("Listening for incoming TLS RPC requests on ${p}", ("p", options.at("rpc-tls-endpoint").as<string>()));
|
||||||
_websocket_tls_server->listen( fc::ip::endpoint::from_string(options.at("rpc-tls-endpoint").as<string>()) );
|
_websocket_tls_server->listen(fc::ip::endpoint::from_string(options.at("rpc-tls-endpoint").as<string>()));
|
||||||
_websocket_tls_server->start_accept();
|
_websocket_tls_server->start_accept();
|
||||||
}
|
}
|
||||||
|
|
||||||
auto _http_server = std::make_shared<fc::http::server>();
|
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>()));
|
||||||
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>()));
|
||||||
_http_server->listen( fc::ip::endpoint::from_string( options.at( "rpc-http-endpoint" ).as<string>() ) );
|
|
||||||
//
|
//
|
||||||
// due to implementation, on_request() must come AFTER listen()
|
// due to implementation, on_request() must come AFTER listen()
|
||||||
//
|
//
|
||||||
_http_server->on_request(
|
_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::shared_ptr< fc::rpc::http_api_connection > conn =
|
std::make_shared<fc::rpc::http_api_connection>(GRAPHENE_MAX_NESTED_OBJECTS);
|
||||||
std::make_shared< fc::rpc::http_api_connection >( GRAPHENE_MAX_NESTED_OBJECTS );
|
conn->register_api(wapi);
|
||||||
conn->register_api( wapi );
|
conn->on_request(req, resp);
|
||||||
conn->on_request( req, resp );
|
});
|
||||||
} );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if( !options.count( "daemon" ) )
|
if (!options.count("daemon")) {
|
||||||
{
|
wallet_cli->register_api(wapi);
|
||||||
wallet_cli->register_api( wapi );
|
|
||||||
wallet_cli->start();
|
wallet_cli->start();
|
||||||
wallet_cli->wait();
|
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) {
|
||||||
fc::promise<int>::ptr exit_promise = new fc::promise<int>("UNIX Signal Handler");
|
exit_promise->set_value(signal);
|
||||||
fc::set_signal_handler([&exit_promise](int signal) {
|
},
|
||||||
exit_promise->set_value(signal);
|
SIGINT);
|
||||||
}, SIGINT);
|
|
||||||
|
|
||||||
ilog( "Entering Daemon Mode, ^C to exit" );
|
ilog("Entering Daemon Mode, ^C to exit");
|
||||||
exit_promise->wait();
|
exit_promise->wait();
|
||||||
}
|
}
|
||||||
|
|
||||||
wapi->save_wallet_file(wallet_file.generic_string());
|
wapi->save_wallet_file(wallet_file.generic_string());
|
||||||
locked_connection.disconnect();
|
locked_connection.disconnect();
|
||||||
closed_connection.disconnect();
|
closed_connection.disconnect();
|
||||||
}
|
} catch (const fc::exception &e) {
|
||||||
catch ( const fc::exception& e )
|
|
||||||
{
|
|
||||||
std::cout << e.to_detail_string() << "\n";
|
std::cout << e.to_detail_string() << "\n";
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -27,7 +27,7 @@
|
||||||
|
|
||||||
#include <fc/crypto/digest.hpp>
|
#include <fc/crypto/digest.hpp>
|
||||||
|
|
||||||
#include <boost/test/auto_unit_test.hpp>
|
#include <boost/test/unit_test.hpp>
|
||||||
|
|
||||||
using namespace graphene::chain;
|
using namespace graphene::chain;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -60,8 +60,14 @@ public:
|
||||||
create_tx = fixture_.con.wallet_api_ptr->create_account_with_brain_key(
|
create_tx = fixture_.con.wallet_api_ptr->create_account_with_brain_key(
|
||||||
bki.brain_priv_key, account_name, "nathan", "nathan", true
|
bki.brain_priv_key, account_name, "nathan", "nathan", true
|
||||||
);
|
);
|
||||||
|
|
||||||
|
fixture_.generate_block();
|
||||||
|
|
||||||
// save the private key for this new account in the wallet file
|
// 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));
|
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);
|
fixture_.con.wallet_api_ptr->save_wallet_file(fixture_.con.wallet_filename);
|
||||||
|
|
||||||
// attempt to give son account some CORE tokens
|
// 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;
|
son2_end_votes = son2_obj.total_votes;
|
||||||
BOOST_CHECK(son2_end_votes > son2_start_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
|
// Withdraw vote for a son1account
|
||||||
BOOST_TEST_MESSAGE("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);
|
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;
|
son1_end_votes = son1_obj.total_votes;
|
||||||
BOOST_CHECK(son1_end_votes == son1_start_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
|
// Withdraw vote for a son2account
|
||||||
BOOST_TEST_MESSAGE("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);
|
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;
|
son2_end_votes = son2_obj.total_votes;
|
||||||
BOOST_CHECK(son2_end_votes == son2_start_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 ) {
|
} catch( fc::exception& e ) {
|
||||||
BOOST_TEST_MESSAGE("SON cli wallet tests exception");
|
BOOST_TEST_MESSAGE("SON cli wallet tests exception");
|
||||||
edump((e.to_detail_string()));
|
edump((e.to_detail_string()));
|
||||||
|
|
|
||||||
|
|
@ -38,6 +38,10 @@ using namespace graphene::chain;
|
||||||
using namespace graphene::chain::test;
|
using namespace graphene::chain::test;
|
||||||
using namespace graphene::app;
|
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_FIXTURE_TEST_SUITE( elasticsearch_tests, database_fixture )
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(elasticsearch_account_history) {
|
BOOST_AUTO_TEST_CASE(elasticsearch_account_history) {
|
||||||
|
|
@ -48,8 +52,8 @@ BOOST_AUTO_TEST_CASE(elasticsearch_account_history) {
|
||||||
|
|
||||||
graphene::utilities::ES es;
|
graphene::utilities::ES es;
|
||||||
es.curl = curl;
|
es.curl = curl;
|
||||||
es.elasticsearch_url = "http://localhost:9200/";
|
es.elasticsearch_url = g_es_url;
|
||||||
es.index_prefix = "peerplays-";
|
es.index_prefix = g_es_index_prefix;
|
||||||
//es.auth = "elastic:changeme";
|
//es.auth = "elastic:changeme";
|
||||||
|
|
||||||
// delete all first
|
// 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;
|
//int account_create_op_id = operation::tag<account_create_operation>::value;
|
||||||
|
|
||||||
string query = "{ \"query\" : { \"bool\" : { \"must\" : [{\"match_all\": {}}] } } }";
|
string query = "{ \"query\" : { \"bool\" : { \"must\" : [{\"match_all\": {}}] } } }";
|
||||||
es.endpoint = es.index_prefix + "*/data/_count";
|
es.endpoint = es.index_prefix + "*/_doc/_count";
|
||||||
es.query = query;
|
es.query = query;
|
||||||
|
|
||||||
auto res = graphene::utilities::simpleQuery(es);
|
auto res = graphene::utilities::simpleQuery(es);
|
||||||
|
|
@ -79,7 +83,7 @@ BOOST_AUTO_TEST_CASE(elasticsearch_account_history) {
|
||||||
auto total = j["count"].as_string();
|
auto total = j["count"].as_string();
|
||||||
BOOST_CHECK_EQUAL(total, "5");
|
BOOST_CHECK_EQUAL(total, "5");
|
||||||
|
|
||||||
es.endpoint = es.index_prefix + "*/data/_search";
|
es.endpoint = es.index_prefix + "*/_doc/_search";
|
||||||
res = graphene::utilities::simpleQuery(es);
|
res = graphene::utilities::simpleQuery(es);
|
||||||
j = fc::json::from_string(res);
|
j = fc::json::from_string(res);
|
||||||
auto first_id = j["hits"]["hits"][size_t(0)]["_id"].as_string();
|
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
|
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);
|
res = graphene::utilities::simpleQuery(es);
|
||||||
j = fc::json::from_string(res);
|
j = fc::json::from_string(res);
|
||||||
|
|
||||||
|
|
@ -114,9 +118,9 @@ BOOST_AUTO_TEST_CASE(elasticsearch_account_history) {
|
||||||
|
|
||||||
// check the visitor data
|
// check the visitor data
|
||||||
auto block_date = db.head_block_time();
|
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);
|
res = graphene::utilities::getEndPoint(es);
|
||||||
j = fc::json::from_string(res);
|
j = fc::json::from_string(res);
|
||||||
auto last_transfer_amount = j["_source"]["operation_history"]["op_object"]["amount_"]["amount"].as_string();
|
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;
|
graphene::utilities::ES es;
|
||||||
es.curl = curl;
|
es.curl = curl;
|
||||||
es.elasticsearch_url = "http://localhost:9200/";
|
es.elasticsearch_url = g_es_url;
|
||||||
es.index_prefix = "ppobjects-";
|
es.index_prefix = g_es_ppobjects_prefix;
|
||||||
//es.auth = "elastic:changeme";
|
//es.auth = "elastic:changeme";
|
||||||
|
|
||||||
// delete all first
|
// delete all first
|
||||||
|
|
@ -155,7 +159,7 @@ BOOST_AUTO_TEST_CASE(elasticsearch_objects) {
|
||||||
fc::usleep(fc::milliseconds(1000));
|
fc::usleep(fc::milliseconds(1000));
|
||||||
|
|
||||||
string query = "{ \"query\" : { \"bool\" : { \"must\" : [{\"match_all\": {}}] } } }";
|
string query = "{ \"query\" : { \"bool\" : { \"must\" : [{\"match_all\": {}}] } } }";
|
||||||
es.endpoint = es.index_prefix + "*/data/_count";
|
es.endpoint = es.index_prefix + "*/_doc/_count";
|
||||||
es.query = query;
|
es.query = query;
|
||||||
|
|
||||||
auto res = graphene::utilities::simpleQuery(es);
|
auto res = graphene::utilities::simpleQuery(es);
|
||||||
|
|
@ -163,14 +167,14 @@ BOOST_AUTO_TEST_CASE(elasticsearch_objects) {
|
||||||
auto total = j["count"].as_string();
|
auto total = j["count"].as_string();
|
||||||
BOOST_CHECK_EQUAL(total, "2");
|
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);
|
res = graphene::utilities::simpleQuery(es);
|
||||||
j = fc::json::from_string(res);
|
j = fc::json::from_string(res);
|
||||||
auto first_id = j["hits"]["hits"][size_t(0)]["_source"]["symbol"].as_string();
|
auto first_id = j["hits"]["hits"][size_t(0)]["_source"]["symbol"].as_string();
|
||||||
BOOST_CHECK_EQUAL(first_id, "USD");
|
BOOST_CHECK_EQUAL(first_id, "USD");
|
||||||
|
|
||||||
auto bitasset_data_id = j["hits"]["hits"][size_t(0)]["_source"]["bitasset_data_id"].as_string();
|
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+"\"}}] } } }";
|
es.query = "{ \"query\" : { \"bool\": { \"must\" : [{ \"term\": { \"object_id\": \""+bitasset_data_id+"\"}}] } } }";
|
||||||
res = graphene::utilities::simpleQuery(es);
|
res = graphene::utilities::simpleQuery(es);
|
||||||
j = fc::json::from_string(res);
|
j = fc::json::from_string(res);
|
||||||
|
|
@ -192,11 +196,11 @@ BOOST_AUTO_TEST_CASE(elasticsearch_suite) {
|
||||||
|
|
||||||
graphene::utilities::ES es;
|
graphene::utilities::ES es;
|
||||||
es.curl = curl;
|
es.curl = curl;
|
||||||
es.elasticsearch_url = "http://localhost:9200/";
|
es.elasticsearch_url = g_es_url;
|
||||||
es.index_prefix = "peerplays-";
|
es.index_prefix = g_es_index_prefix;
|
||||||
auto delete_account_history = graphene::utilities::deleteAll(es);
|
auto delete_account_history = graphene::utilities::deleteAll(es);
|
||||||
fc::usleep(fc::milliseconds(1000));
|
fc::usleep(fc::milliseconds(1000));
|
||||||
es.index_prefix = "ppobjects-";
|
es.index_prefix = g_es_ppobjects_prefix;
|
||||||
auto delete_objects = graphene::utilities::deleteAll(es);
|
auto delete_objects = graphene::utilities::deleteAll(es);
|
||||||
fc::usleep(fc::milliseconds(1000));
|
fc::usleep(fc::milliseconds(1000));
|
||||||
|
|
||||||
|
|
@ -218,8 +222,8 @@ BOOST_AUTO_TEST_CASE(elasticsearch_history_api) {
|
||||||
|
|
||||||
graphene::utilities::ES es;
|
graphene::utilities::ES es;
|
||||||
es.curl = curl;
|
es.curl = curl;
|
||||||
es.elasticsearch_url = "http://localhost:9200/";
|
es.elasticsearch_url = g_es_url;
|
||||||
es.index_prefix = "peerplays-";
|
es.index_prefix = g_es_index_prefix;
|
||||||
|
|
||||||
auto delete_account_history = graphene::utilities::deleteAll(es);
|
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);
|
BOOST_CHECK_EQUAL(db.head_block_time().sec_since_epoch() - past_time, 2);
|
||||||
} FC_LOG_AND_RETHROW() }
|
} 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 )
|
BOOST_FIXTURE_TEST_CASE( pop_block_twice, database_fixture )
|
||||||
{
|
{
|
||||||
try
|
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);
|
auto witness1_object = db_api1.get_witness_by_account(witness1_id(db).name);
|
||||||
BOOST_CHECK_EQUAL(witness1_object->total_votes, 111);
|
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()
|
} 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);
|
auto committee1_object = db_api1.get_committee_member_by_account(committee1_id(db).name);
|
||||||
BOOST_CHECK_EQUAL(committee1_object->total_votes, 111);
|
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()
|
} FC_LOG_AND_RETHROW()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue