Compare commits
26 commits
master
...
beatrice_m
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6999bb1326 | ||
|
|
d79cdee927 | ||
|
|
c0b57fce33 | ||
|
|
0b280882af | ||
|
|
54c66b226e | ||
|
|
7a8026df63 | ||
|
|
9b0fb50330 | ||
|
|
b8d03b82a6 | ||
|
|
434837f61f | ||
|
|
709c74505b | ||
|
|
a0f793951c | ||
|
|
5d43b28b1b | ||
|
|
1d7e4fc630 | ||
|
|
c7164bd99d | ||
|
|
62ddd6775d | ||
|
|
e82a3dbcc0 | ||
|
|
7ce73aeb4e | ||
|
|
d28f9b0dbc | ||
|
|
f998c4611a | ||
|
|
a50da70215 | ||
|
|
651e781984 | ||
|
|
a029784a76 | ||
|
|
bec5918586 | ||
|
|
145624d026 | ||
|
|
f25cee8616 | ||
|
|
2716202cdc |
39 changed files with 214540 additions and 8654 deletions
80
.github/ISSUE_TEMPLATE/bug_report.md
vendored
Normal file
80
.github/ISSUE_TEMPLATE/bug_report.md
vendored
Normal file
|
|
@ -0,0 +1,80 @@
|
|||
---
|
||||
name: Bug report
|
||||
about: Create a report to help us improve
|
||||
title: ''
|
||||
labels: ''
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
**Instructions**
|
||||
Please include a detailed Title above. Next, please complete the following sections below:
|
||||
* Bug Description
|
||||
* Impacts
|
||||
* Steps To Reproduce
|
||||
* Expected Behavior
|
||||
* Screenshots (optional)
|
||||
* Host Environment (optional)
|
||||
* Additional Context (optional)
|
||||
|
||||
Finally, press the 'Submit new issue' button. The Core Team will evaluate and prioritize your Bug Report for future development.
|
||||
|
||||
**Bug Description**
|
||||
A clear and concise description of what the bug is.
|
||||
|
||||
**Porting from Bitshares or other Graphene forks**
|
||||
|
||||
Corresponding issues:
|
||||
|
||||
- [FILL in issue1]
|
||||
- [FILL in any other detail]
|
||||
|
||||
Corresponding PR:
|
||||
|
||||
- [fill in corresponding PR link]
|
||||
|
||||
**Impacts**
|
||||
Describe which portion(s) of Peerplays may be impacted by this bug. Please tick at least one box.
|
||||
- [ ] API (the application programming interface)
|
||||
- [ ] Build (the build process or something prior to compiled code)
|
||||
- [ ] CLI (the command line wallet)
|
||||
- [ ] Deployment (the deployment process after building such as Docker, Gitlab, etc.)
|
||||
- [ ] P2P (the peer-to-peer network for transaction/block propagation)
|
||||
- [ ] Performance (system or user efficiency, etc.)
|
||||
- [ ] Protocol (the blockchain logic, consensus, validation, etc.)
|
||||
- [ ] Security (the security of system or user data, etc.)
|
||||
- [ ] UX (the User Experience)
|
||||
- [ ] Other (please add below)
|
||||
|
||||
|
||||
**Steps To Reproduce**
|
||||
Steps to reproduce the behavior (example outlined below):
|
||||
1. Execute API call '...'
|
||||
2. Using JSON payload '...'
|
||||
3. Received response '...'
|
||||
4. See error in screenshot
|
||||
|
||||
**Expected Behavior**
|
||||
A clear and concise description of what you expected to happen.
|
||||
|
||||
**Screenshots (optional)**
|
||||
If applicable, add screenshots to help explain process flow and behavior.
|
||||
|
||||
**Host Environment**
|
||||
Please provide details about the host environment. Much of this information can be found running: `witness_node --version`.
|
||||
- Host OS: [e.g. Ubuntu 18.04 LTS]
|
||||
- Host Physical RAM [e.g. 4GB]
|
||||
- Peerplays Version
|
||||
- OpenSSL Version: [e.g. 1.1.0g]
|
||||
- Boost Version: [e.g. 1.67.0]
|
||||
|
||||
**Additional Context (optional)**
|
||||
Add any other context about the problem here.
|
||||
|
||||
## PBSA / Developer tasks
|
||||
|
||||
- [ ] Evaluate / Prioritize Bug Report
|
||||
- [ ] Refine User Stories / Requirements
|
||||
- [ ] Define Test Cases
|
||||
- [ ] Design / Develop Solution
|
||||
- [ ] Perform QA/Testing
|
||||
- [ ] Update Documentation
|
||||
42
.github/ISSUE_TEMPLATE/build_error.md
vendored
Normal file
42
.github/ISSUE_TEMPLATE/build_error.md
vendored
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
---
|
||||
name: Build Error
|
||||
about: Create a detailed report about an error encountered during the Peerplays build process.
|
||||
|
||||
---
|
||||
|
||||
**Instructions**
|
||||
Please include a detailed Title above. Next, please complete the following sections below:
|
||||
* Build Error
|
||||
* Build Environment
|
||||
* Steps To Reproduce
|
||||
* Console Logs (optional)
|
||||
|
||||
Finally, press the 'Submit new issue' button. The developers/PBSA Team will evaluate and prioritize your Bug Report for future development.
|
||||
|
||||
**Build Error Description**
|
||||
A clear and concise description of what the build error is.
|
||||
|
||||
**Build Environment**
|
||||
Details about the build environment, including the relevant required libraries. Much of this information can be found in the `CMakeFiles/CMakeOutput.log`.
|
||||
- Host OS: [e.g. Ubuntu 18.04 LTS]
|
||||
- Host Physical RAM [e.g. 4GB]
|
||||
- Source Branch/Tag: [e.g. master or 2.0.180425]
|
||||
- OpenSSL Version: [e.g. 1.1.0g]
|
||||
- Boost Version: [e.g. 1.65.1]
|
||||
- C++ Compiler: [e.g. gcc version 4.8.5]
|
||||
|
||||
**Steps To Reproduce**
|
||||
Steps to reproduce the behavior (example outlined below):
|
||||
1. Using installation guide from this URL...
|
||||
2. This is my complete build script...
|
||||
3. It fails at this step with the following output...
|
||||
4. See the error in the console log below...
|
||||
|
||||
**Console Logs (optional)**
|
||||
Please provide the full console log, including all commands entered and their output. This will allow detailed troubleshooting.
|
||||
|
||||
## CORE TEAM TASK LIST
|
||||
- [ ] Evaluate `Build Error`
|
||||
- [ ] Provide build guidance
|
||||
- [ ] <OR> Create `Bug Report`
|
||||
|
||||
43
.github/ISSUE_TEMPLATE/feature_request.md
vendored
Normal file
43
.github/ISSUE_TEMPLATE/feature_request.md
vendored
Normal file
|
|
@ -0,0 +1,43 @@
|
|||
---
|
||||
name: Feature Request
|
||||
about: Suggest an idea for the Peerplays Community & PBSA Team to evaluate and prioritize for development.
|
||||
|
||||
---
|
||||
|
||||
**Instructions**
|
||||
Please include a detailed Title above. Next, please complete the following sections below:
|
||||
* User Story
|
||||
* Impacts
|
||||
* Additional Context (optional)
|
||||
|
||||
Finally, press the 'Submit new issue' button. The Core Team will evaluate and prioritize your Feature Request for future development.
|
||||
|
||||
**User Story**
|
||||
Please tell us about your feature request using the User Story format:
|
||||
As a `<persona>` I want `<some functionality>` so that `<some benefit is realized>`.
|
||||
|
||||
At minimum, please define the `<who>`, `<what>` and `<why>` for your feature request. The `<who>` may be the system software, a component thereof, the end user, etc.; please be specific describing the context. The `<what>` details the solution your feature will provide; please describe the process flow for the functionality. The `<why>` details the benefits the feature will deliver; consider referencing alternative implementations for context.
|
||||
|
||||
**Impacts**
|
||||
Describe which portion(s) of Peerplays that may be impacted by your request. Please tick at least one box.
|
||||
- [ ] API (the application programming interface)
|
||||
- [ ] Build (the build process or something prior to compiled code)
|
||||
- [ ] CLI (the command line wallet)
|
||||
- [ ] Deployment (the deployment process after building such as Docker, Gitlab, etc.)
|
||||
- [ ] P2P (the peer-to-peer network for transaction/block propagation)
|
||||
- [ ] Performance (system or user efficiency, etc.)
|
||||
- [ ] Protocol (the blockchain logic, consensus, validation, etc.)
|
||||
- [ ] Security (the security of system or user data, etc.)
|
||||
- [ ] UX (the User Experience)
|
||||
- [ ] Other (please add below)
|
||||
|
||||
**Additional Context (optional)**
|
||||
Add any other context about your request here.
|
||||
|
||||
## Community / PBSA check list
|
||||
- [ ] Evaluate / Prioritize Feature Request
|
||||
- [ ] Refine User Stories / Requirements
|
||||
- [ ] Define Test Cases
|
||||
- [ ] Design / Develop Solution
|
||||
- [ ] Perform QA/Testing
|
||||
- [ ] Update Documentation
|
||||
53
.github/PULL_REQUEST_TEMPLATE/PULL_REQUEST_TEMPLATE.md
vendored
Normal file
53
.github/PULL_REQUEST_TEMPLATE/PULL_REQUEST_TEMPLATE.md
vendored
Normal file
|
|
@ -0,0 +1,53 @@
|
|||
Please Note:
|
||||
|
||||
|
||||
1. PRs will be reviewed from oldest to newest
|
||||
2. PRs should use PR template in order to be considered for review.
|
||||
3. PRs that do not have one of the PR template completely filled out with all declarations satisfied will not be reviewed.
|
||||
|
||||
|
||||
### Purpose
|
||||
|
||||
(FILL ME IN) This section describes why this PR is here. Usually it would include a reference
|
||||
to the tracking task that it is part or all of the solution for.
|
||||
|
||||
The Tracking issue is [Create the issue if non existent and fill in]
|
||||
|
||||
|
||||
## Instructions to Verify
|
||||
|
||||
**Steps To Reproduce: **
|
||||
|
||||
[Provide Steps to reproduce the issue or patterns/regular expression to look for in the CI]
|
||||
|
||||
**Expected Behavior**
|
||||
|
||||
[Provide Steps to reproduce the issue]
|
||||
|
||||
**Tests Added and available in CI**
|
||||
|
||||
** Screenshots (optional) **
|
||||
** Host Environment (optional) **
|
||||
** Additional Context (optional) **
|
||||
|
||||
### Declarations
|
||||
|
||||
Check these if you believe they are true
|
||||
|
||||
- [ ] The code base is in a better state after this PR
|
||||
- [ ] Is prepared according to the [Release Management & Versioning](https://github.com/peerplays-network/peerplays/wiki/Release-Management-&-Versioning)
|
||||
- [ ] The level of testing this PR includes is appropriate
|
||||
- [ ] All tests pass using the self-service CI/Gitlab.
|
||||
- [ ] Changes to the API is documented
|
||||
- [ ] Testing steps for the QA team / community is shared
|
||||
|
||||
|
||||
### Reviewers
|
||||
|
||||
(FILL ME IN) Reviewer 1 (If possible, assign the Reviewer for the PR)
|
||||
|
||||
(FILL ME IN, optional) Any additional notes to reviewers or testers.
|
||||
|
||||
### FYIs
|
||||
|
||||
(FILL ME IN, Optional) Names of anyone else you wish to be notified of
|
||||
3
.gitmodules
vendored
3
.gitmodules
vendored
|
|
@ -4,6 +4,5 @@
|
|||
ignore = dirty
|
||||
[submodule "libraries/fc"]
|
||||
path = libraries/fc
|
||||
url = https://github.com/peerplays-network/peerplays-fc.git
|
||||
branch = latest-fc
|
||||
url = https://github.com/peerplays-network/peerplays-fc.git
|
||||
ignore = dirty
|
||||
|
|
|
|||
276
README.md
276
README.md
|
|
@ -2,274 +2,26 @@ Intro for new developers and witnesses
|
|||
------------------------
|
||||
|
||||
This is a quick introduction to get new developers and witnesses up to speed on Peerplays blockchain. It is intended for witnesses plannig to join a live, already deployed blockchain.
|
||||
# Building on Ubuntu 18.04 LTS and Installation Instructions
|
||||
|
||||
The following dependencies were necessary for a clean install of Ubuntu 18.04 LTS:
|
||||
|
||||
```
|
||||
sudo apt-get install gcc-5 g++-5 cmake make libbz2-dev\
|
||||
libdb++-dev libdb-dev libssl-dev openssl libreadline-dev\
|
||||
autoconf libtool git
|
||||
```
|
||||
## Build Boost 1.67.0
|
||||
|
||||
|
||||
```
|
||||
mkdir $HOME/src
|
||||
cd $HOME/src
|
||||
export BOOST_ROOT=$HOME/src/boost_1_67_0
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y autotools-dev build-essential libbz2-dev libicu-dev python-dev
|
||||
wget -c 'http://sourceforge.net/projects/boost/files/boost/1.67.0/boost_1_67_0.tar.bz2/download'\
|
||||
-O boost_1_67_0.tar.bz2
|
||||
tar xjf boost_1_67_0.tar.bz2
|
||||
cd boost_1_67_0/
|
||||
./bootstrap.sh "--prefix=$BOOST_ROOT"
|
||||
./b2 install
|
||||
```
|
||||
|
||||
|
||||
## Building Peerplays
|
||||
|
||||
```
|
||||
cd $HOME/src
|
||||
export BOOST_ROOT=$HOME/src/boost_1_67_0
|
||||
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 -j$(nproc)
|
||||
|
||||
make install # this can install the executable files under /usr/local
|
||||
```
|
||||
|
||||
docker build -t peerplays .
|
||||
|
||||
## Docker image
|
||||
|
||||
```
|
||||
# Install docker
|
||||
sudo apt install docker.io
|
||||
|
||||
|
||||
# Add current user to docker group
|
||||
sudo usermod -a -G docker $USER
|
||||
# You need to restart your shell session, to apply group membership
|
||||
# Type 'groups' to verify that you are a member of a docker group
|
||||
|
||||
|
||||
# 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.
|
||||
|
||||
Starting A Peerplays Node
|
||||
Witness Node Setup
|
||||
-----------------
|
||||
For instructions on witness node installation and configuration refer to the Peerplays Documentation here:
|
||||
|
||||
For Ubuntu 14.04 LTS and up users, see
|
||||
[this](https://github.com/cryptonomex/graphene/wiki/build-ubuntu) and
|
||||
then proceed with:
|
||||
https://www.peerplays.tech/witnesses/setting-up-a-witness-node
|
||||
|
||||
git clone https://github.com/peerplays-network/peerplays.git
|
||||
cd peerplays
|
||||
git submodule update --init --recursive
|
||||
cmake -DBOOST_ROOT="$BOOST_ROOT" -DCMAKE_BUILD_TYPE=Release .
|
||||
make
|
||||
./programs/witness_node/witness_node
|
||||
|
||||
Launching the witness creates required directories. Next, **stop the witness** and continue.
|
||||
|
||||
$ vi witness_node_data_dir/config.ini
|
||||
p2p-endpoint = 0.0.0.0:9777
|
||||
rpc-endpoint = 127.0.0.1:8090
|
||||
seed-node = 213.184.225.234:59500
|
||||
|
||||
Start the witness back up
|
||||
|
||||
./programs/witness_node/witness_node
|
||||
|
||||
Upgrading A Peerplays Node
|
||||
|
||||
BOS and MINT Setup
|
||||
-----------------
|
||||
To minimize downtime of your peerplays node when upgrading, one upgrade
|
||||
idea was written in [this steemit
|
||||
article](https://steemit.com/peerplays/@joseph/peerplays-update-setting-a-backup-witness-server-switching-servers).
|
||||
The Bookie Oracle System (BOS) and Manual Intervention Tool (MINT) need to be installed as part of a witness setup.
|
||||
They are both prerequisites for the operation of the BookiePro app.
|
||||
|
||||
Full instructions on BOS and MINT installation can be found here:
|
||||
|
||||
https://www.peerplays.tech/bookie-oracle-suite-bos/intro-bos
|
||||
|
||||
|
||||
Wallet Setup
|
||||
-----------------
|
||||
Then, in a separate terminal window, start the command-line wallet `cli_wallet`:
|
||||
Full instructions on setting up a cli_wallet can be found here:
|
||||
|
||||
./programs/cli_wallet/cli_wallet
|
||||
|
||||
To set your initial password to 'password' use:
|
||||
|
||||
>>> set_password password
|
||||
>>> unlock password
|
||||
|
||||
A list of CLI wallet commands is available
|
||||
[here](https://github.com/PBSA/peerplays/blob/master/libraries/wallet/include/graphene/wallet/wallet.hpp).
|
||||
|
||||
|
||||
Testnet - "Beatrice"
|
||||
----------------------
|
||||
- chain-id - T.B.D.
|
||||
|
||||
Use the `get_private_key_from_password` command
|
||||
---------------------------------
|
||||
You will to generate owner and active keys
|
||||
|
||||
```
|
||||
get_private_key_from_password your_witness_username active the_key_you_received_from_the_faucet
|
||||
```
|
||||
This will reveal an array for your active key `["PPYxxx", "xxxx"]`
|
||||
|
||||
import_keys into your cli_wallet
|
||||
-------------------------------
|
||||
- use the second value in the array returned from the previous step for the private key
|
||||
- be sure to wrap your username in quotes
|
||||
- import the key with this command
|
||||
```
|
||||
import_key "your_witness_username" xxxx
|
||||
```
|
||||
|
||||
Upgrade your account to lifetime membership
|
||||
--------------------------------
|
||||
```
|
||||
upgrade_account your_witness_username true
|
||||
```
|
||||
|
||||
Create your witness (substitute the url for your witness information)
|
||||
-------------------------------
|
||||
- place quotes around url
|
||||
```
|
||||
create_witness your_witness_username "url" true
|
||||
```
|
||||
**Be sure to take note of the block_signing_key**
|
||||
|
||||
IMPORTANT (issue below command using block_signing_key just obtained)
|
||||
```
|
||||
get_private_key block_signing_key
|
||||
```
|
||||
Compare this result to
|
||||
|
||||
```
|
||||
dump_private_keys
|
||||
```
|
||||
You should see 3 pairs of keys. One of the pairs should match your block_signing_key and this is the one you will use in the next step!
|
||||
|
||||
Get your witness id
|
||||
-----------------
|
||||
```
|
||||
get_witness username (note the "id" for your config)
|
||||
```
|
||||
|
||||
Modify your witness_node config.ini to include **your** witness id and private key pair.
|
||||
-------------------------
|
||||
Comment out the existing private-key before adding yours
|
||||
```
|
||||
vim witness_node_data_dir/config.ini
|
||||
|
||||
witness-id = "1.6.x"
|
||||
private-key = ["block_signing_key","private_key_for_your_block_signing_key"]
|
||||
```
|
||||
|
||||
start your witness back up
|
||||
------------------
|
||||
```
|
||||
./programs/witness_node/witness_node
|
||||
```
|
||||
|
||||
If it fails to start, try with these flags (not for permanent use)
|
||||
|
||||
```
|
||||
./programs/witness_node/witness_node --resync --replay
|
||||
```
|
||||
|
||||
Vote for yourself
|
||||
--------------
|
||||
```
|
||||
vote_for_witness your_witness_account your_witness_account true true
|
||||
```
|
||||
|
||||
Ask to be voted in!
|
||||
--------------
|
||||
|
||||
Join @Peerplays Telegram group to find information about the witness group.
|
||||
http://t.me/@peerplayswitness
|
||||
|
||||
You will get logs that look like this:
|
||||
|
||||
```
|
||||
2070264ms th_a application.cpp:506 handle_block ] Got block: #87913 time: 2017-05-27T16:34:30 latency: 264 ms from: bhuz-witness irreversible: 87903 (-10)
|
||||
```
|
||||
|
||||
Assuming you've received votes, you will start producing as a witness at the next maintenance interval (once per hour). You can check your votes with.
|
||||
|
||||
```
|
||||
get_witness your_witness_account
|
||||
```
|
||||
|
||||
systemd
|
||||
----------------
|
||||
It's important for your witness to start when your system boots up. The filepaths here assume that you installed your witness into `/home/ubuntu/peerplays`
|
||||
|
||||
Create a logfile to hold your stdout/err logging
|
||||
```bash
|
||||
sudo touch /var/log/peerplays.log
|
||||
```
|
||||
|
||||
Save this file in your peerplays directory. `vi /home/ubuntu/peerplays/start.sh`
|
||||
```bash
|
||||
#!/bin/bash
|
||||
|
||||
cd /home/ubuntu/peerplays
|
||||
./programs/witness_node/witness_node &> /var/log/peerplays.log
|
||||
```
|
||||
Make it executable
|
||||
```bash
|
||||
chmod 744 /home/ubuntu/peerplays/start.sh
|
||||
```
|
||||
Create this file: `sudo vi /etc/systemd/system/peerplays.service`
|
||||
Note the path for start.sh. Change it to match where your start.sh file is if necessary.
|
||||
```
|
||||
[Unit]
|
||||
Description=Peerplays Witness
|
||||
After=network.target
|
||||
|
||||
[Service]
|
||||
ExecStart=/home/ubuntu/peerplays/start.sh
|
||||
|
||||
[Install]
|
||||
WantedBy = multi-user.target
|
||||
```
|
||||
Enable the service
|
||||
```bash
|
||||
sudo systemctl enable peerplays.service
|
||||
```
|
||||
Make sure you don't get any errors
|
||||
```bash
|
||||
sudo systemctl status peerplays.service
|
||||
```
|
||||
Stop your witness if it is currently running from previous steps, then start it with the service.
|
||||
```bash
|
||||
sudo systemctl start peerplays.service
|
||||
```
|
||||
Check your logfile for entries
|
||||
```bash
|
||||
tail -f /var/log/peerplays.log
|
||||
```
|
||||
|
||||
Running specific tests
|
||||
----------------------
|
||||
|
||||
- `tests/chain_tests -t block_tests/name_of_test`
|
||||
https://www.peerplays.tech/witnesses/setting-up-a-witness-node./cli-wallet-setup
|
||||
|
|
|
|||
2
docs
2
docs
|
|
@ -1 +1 @@
|
|||
Subproject commit 8d8b69d82482101279460fa02f814d0e4030966f
|
||||
Subproject commit 8df8f66389853df73ab8f6dd73981be2a6957df8
|
||||
222008
genesis.json
222008
genesis.json
File diff suppressed because it is too large
Load diff
|
|
@ -182,7 +182,7 @@ namespace graphene { namespace app {
|
|||
void network_broadcast_api::broadcast_transaction(const signed_transaction& trx)
|
||||
{
|
||||
trx.validate();
|
||||
_app.chain_database()->check_tansaction_for_duplicated_operations(trx);
|
||||
database_api( *(_app.chain_database() ) ).check_transaction_for_duplicated_operations(trx);
|
||||
_app.chain_database()->push_transaction(trx);
|
||||
if( _app.p2p_node() != nullptr )
|
||||
_app.p2p_node()->broadcast_transaction(trx);
|
||||
|
|
@ -190,7 +190,7 @@ namespace graphene { namespace app {
|
|||
|
||||
fc::variant network_broadcast_api::broadcast_transaction_synchronous(const signed_transaction& trx)
|
||||
{
|
||||
_app.chain_database()->check_tansaction_for_duplicated_operations(trx);
|
||||
database_api( *(_app.chain_database() ) ).check_transaction_for_duplicated_operations(trx);
|
||||
|
||||
fc::promise<fc::variant>::ptr prom( new fc::promise<fc::variant>() );
|
||||
broadcast_transaction_with_callback( [=]( const fc::variant& v ){
|
||||
|
|
|
|||
|
|
@ -162,10 +162,41 @@ namespace detail {
|
|||
{
|
||||
// t.me/peerplays #seednodes
|
||||
vector<string> seeds = {
|
||||
"ppy-beatrice-seed.blckchnd.com:6666",
|
||||
"159.69.223.206:7777",
|
||||
"51.38.237.243:9666",
|
||||
"pbsa-beatrice.blockchainprojectsbv.com:9195"
|
||||
"seed.ppy.blckchnd.com:6666", // blckchnd
|
||||
"ppy.esteem.ws:7777", // good-karma
|
||||
"peerplays.bitcoiner.me:9777", // bitcoiner
|
||||
"peerplays.roelandp.nl:9777", // roelandp
|
||||
"ppyseed.bacchist.me:42420", // bacchist-witness
|
||||
"5.9.18.213:18828", // pfunk
|
||||
"31.171.244.121:7777", // taconator
|
||||
"seed.peerplaysdb.com:9777", // jesta
|
||||
"ppy-seed.xeldal.com:19777", // xeldal
|
||||
"seed.ppy.altcap.io:61388", // winner.winner.chicken.dinner
|
||||
"seed.peerplaysnodes.com:9777", // wackou
|
||||
"peerplays-seed.privex.io:7777", // someguy123/privex
|
||||
"51.15.78.16:9777", // agoric.systems
|
||||
"212.71.253.163:9777", // xtar
|
||||
"51.15.35.96:9777", // lafona
|
||||
"anyx.ca:9777", // anyx
|
||||
"82.223.108.91:7777", // hiltos-witness
|
||||
"seed.ppy.nuevax.com:9777", // nuevax
|
||||
"peerplays.butler.net:9777", // billbutler-witness
|
||||
"peerplays.bitcoiner.me:9777", // bitcoiner
|
||||
"ppyseed.bacchist.me:42420", // bacchist-witness
|
||||
"peerplays.bhuz.info:9777", // bhuz
|
||||
"node.peerblock.trade:9777", // bitcoinsig
|
||||
"peerplays.crypto.fans:9777", // sc-steemit
|
||||
"54.38.193.20:9777", // royal-flush
|
||||
"ppy001.bts-nodes.net:7777", // baxters-sports-witness
|
||||
"ppy002.bts-nodes.net:7777", // baxters-sports-witness
|
||||
"ppy003.bts-nodes.net:7777", // baxters-sports-witness
|
||||
"ppy004.bts-nodes.net:7777", // baxters-sports-witness
|
||||
"ppy.proxyhosts.info:7777", // baxters-sports-witness
|
||||
"ppyseed.spacemx.tech:9777", // spacecrypt-witness
|
||||
"peerplaysblockchain.net:9777", // houdini-witness
|
||||
"54.37.235.164:7777", // melea-trust
|
||||
"seed01.eifos.org:7777" // eifos
|
||||
"peerplays-seed.lukestokes.info:7777" // lukestokes-witness
|
||||
};
|
||||
|
||||
for( const string& endpoint_string : seeds )
|
||||
|
|
|
|||
|
|
@ -33,6 +33,7 @@
|
|||
#include <fc/smart_ref_impl.hpp>
|
||||
|
||||
#include <fc/crypto/hex.hpp>
|
||||
#include <fc/crypto/digest.hpp>
|
||||
#include <fc/rpc/api_connection.hpp>
|
||||
#include <fc/uint128.hpp>
|
||||
|
||||
|
|
@ -48,11 +49,49 @@
|
|||
#define GET_REQUIRED_FEES_MAX_RECURSION 4
|
||||
|
||||
typedef std::map< std::pair<graphene::chain::asset_id_type, graphene::chain::asset_id_type>, std::vector<fc::variant> > market_queue_type;
|
||||
|
||||
template class fc::api<graphene::app::database_api>;
|
||||
|
||||
namespace {
|
||||
|
||||
struct proposed_operations_digest_accumulator
|
||||
{
|
||||
typedef void result_type;
|
||||
|
||||
void operator()(const graphene::chain::proposal_create_operation& proposal)
|
||||
{
|
||||
for (auto& operation: proposal.proposed_ops)
|
||||
{
|
||||
if( operation.op.which() != graphene::chain::operation::tag<graphene::chain::betting_market_group_create_operation>::value
|
||||
&& operation.op.which() != graphene::chain::operation::tag<graphene::chain::betting_market_create_operation>::value )
|
||||
proposed_operations_digests.push_back(fc::digest(operation.op));
|
||||
}
|
||||
}
|
||||
|
||||
//empty template method is needed for all other operation types
|
||||
//we can ignore them, we are interested in only proposal_create_operation
|
||||
template<class T>
|
||||
void operator()(const T&)
|
||||
{}
|
||||
|
||||
std::vector<fc::sha256> proposed_operations_digests;
|
||||
};
|
||||
|
||||
std::vector<fc::sha256> gather_proposed_operations_digests(const graphene::chain::transaction& trx)
|
||||
{
|
||||
proposed_operations_digest_accumulator digest_accumulator;
|
||||
for (auto& operation: trx.operations)
|
||||
{
|
||||
operation.visit(digest_accumulator);
|
||||
}
|
||||
|
||||
return digest_accumulator.proposed_operations_digests;
|
||||
}
|
||||
}
|
||||
|
||||
namespace graphene { namespace app {
|
||||
|
||||
class database_api_impl;
|
||||
|
||||
class database_api_impl : public std::enable_shared_from_this<database_api_impl>
|
||||
{
|
||||
public:
|
||||
|
|
@ -73,6 +112,7 @@ class database_api_impl : public std::enable_shared_from_this<database_api_impl>
|
|||
map<uint32_t, optional<block_header>> get_block_header_batch(const vector<uint32_t> block_nums)const;
|
||||
optional<signed_block> get_block(uint32_t block_num)const;
|
||||
processed_transaction get_transaction( uint32_t block_num, uint32_t trx_in_block )const;
|
||||
void check_transaction_for_duplicated_operations(const signed_transaction& trx);
|
||||
|
||||
// Globals
|
||||
chain_property_object get_chain_properties()const;
|
||||
|
|
@ -454,6 +494,39 @@ processed_transaction database_api_impl::get_transaction(uint32_t block_num, uin
|
|||
return opt_block->transactions[trx_num];
|
||||
}
|
||||
|
||||
void database_api::check_transaction_for_duplicated_operations(const signed_transaction& trx)
|
||||
{
|
||||
my->check_transaction_for_duplicated_operations(trx);
|
||||
}
|
||||
|
||||
void database_api_impl::check_transaction_for_duplicated_operations(const signed_transaction& trx)
|
||||
{
|
||||
const auto& idx = _db.get_index_type<proposal_index>();
|
||||
const auto& pidx = dynamic_cast<const primary_index<proposal_index>&>(idx);
|
||||
const auto& raidx = pidx.get_secondary_index<graphene::chain::required_approval_index>();
|
||||
|
||||
auto acc_itr = raidx._account_to_proposals.find( GRAPHENE_WITNESS_ACCOUNT );
|
||||
if( acc_itr != raidx._account_to_proposals.end() )
|
||||
{
|
||||
auto& p_set = acc_itr->second;
|
||||
|
||||
std::set<fc::sha256> existed_operations_digests;
|
||||
for( auto p_itr = p_set.begin(); p_itr != p_set.end(); ++p_itr )
|
||||
{
|
||||
for( auto& operation : (*p_itr)(_db).proposed_transaction.operations )
|
||||
{
|
||||
existed_operations_digests.insert( fc::digest(operation) );
|
||||
}
|
||||
}
|
||||
|
||||
auto proposed_operations_digests = gather_proposed_operations_digests(trx);
|
||||
for (auto& digest : proposed_operations_digests)
|
||||
{
|
||||
FC_ASSERT(existed_operations_digests.count(digest) == 0, "Proposed operation is already pending for apsproval.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// //
|
||||
// Globals //
|
||||
|
|
|
|||
|
|
@ -202,6 +202,12 @@ class database_api
|
|||
*/
|
||||
optional<signed_transaction> get_recent_transaction_by_id( const transaction_id_type& id )const;
|
||||
|
||||
/**
|
||||
* TODO
|
||||
*
|
||||
*/
|
||||
void check_transaction_for_duplicated_operations(const signed_transaction& trx);
|
||||
|
||||
/////////////
|
||||
// Globals //
|
||||
/////////////
|
||||
|
|
|
|||
|
|
@ -67,7 +67,6 @@ FC_REFLECT( graphene::app::full_account,
|
|||
(limit_orders)
|
||||
(call_orders)
|
||||
(settle_orders)
|
||||
(proposals)
|
||||
(assets)
|
||||
(withdraws)
|
||||
(proposals)
|
||||
|
|
|
|||
|
|
@ -58,36 +58,37 @@ void_result asset_create_evaluator::do_evaluate( const asset_create_operation& o
|
|||
|
||||
if( d.head_block_time() > HARDFORK_385_TIME )
|
||||
{
|
||||
|
||||
if( d.head_block_time() <= HARDFORK_409_TIME )
|
||||
{
|
||||
auto dotpos = op.symbol.find( '.' );
|
||||
if( dotpos != std::string::npos )
|
||||
if( d.head_block_time() <= HARDFORK_409_TIME )
|
||||
{
|
||||
auto prefix = op.symbol.substr( 0, dotpos );
|
||||
auto asset_symbol_itr = asset_indx.find( op.symbol );
|
||||
FC_ASSERT( asset_symbol_itr != asset_indx.end(), "Asset ${s} may only be created by issuer of ${p}, but ${p} has not been registered",
|
||||
("s",op.symbol)("p",prefix) );
|
||||
FC_ASSERT( asset_symbol_itr->issuer == op.issuer, "Asset ${s} may only be created by issuer of ${p}, ${i}",
|
||||
("s",op.symbol)("p",prefix)("i", op.issuer(d).name) );
|
||||
auto dotpos = op.symbol.find( '.' );
|
||||
if( dotpos != std::string::npos )
|
||||
{
|
||||
auto prefix = op.symbol.substr( 0, dotpos );
|
||||
auto asset_symbol_itr = asset_indx.find( op.symbol );
|
||||
FC_ASSERT( asset_symbol_itr != asset_indx.end(),
|
||||
"Asset ${s} may only be created by issuer of ${p}, but ${p} has not been registered",
|
||||
("s",op.symbol)("p",prefix) );
|
||||
FC_ASSERT( asset_symbol_itr->issuer == op.issuer,
|
||||
"Asset ${s} may only be created by issuer of ${p}, ${i}",
|
||||
("s",op.symbol)("p",prefix)("i", op.issuer(d).name) );
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
auto dotpos = op.symbol.rfind( '.' );
|
||||
if( dotpos != std::string::npos )
|
||||
|
||||
else
|
||||
{
|
||||
auto prefix = op.symbol.substr( 0, dotpos );
|
||||
auto asset_symbol_itr = asset_indx.find( prefix );
|
||||
FC_ASSERT( asset_symbol_itr != asset_indx.end(), "Asset ${s} may only be created by issuer of ${p}, but ${p} has not been registered",
|
||||
("s",op.symbol)("p",prefix) );
|
||||
FC_ASSERT( asset_symbol_itr->issuer == op.issuer, "Asset ${s} may only be created by issuer of ${p}, ${i}",
|
||||
("s",op.symbol)("p",prefix)("i", op.issuer(d).name) );
|
||||
auto dotpos = op.symbol.rfind( '.' );
|
||||
if( dotpos != std::string::npos )
|
||||
{
|
||||
auto prefix = op.symbol.substr( 0, dotpos );
|
||||
auto asset_symbol_itr = asset_indx.find( prefix );
|
||||
FC_ASSERT( asset_symbol_itr != asset_indx.end(),
|
||||
"Asset ${s} may only be created by issuer of ${p}, but ${p} has not been registered",
|
||||
("s",op.symbol)("p",prefix) );
|
||||
FC_ASSERT( asset_symbol_itr->issuer == op.issuer,
|
||||
"Asset ${s} may only be created by issuer of ${p}, ${i}",
|
||||
("s",op.symbol)("p",prefix)("i", op.issuer(d).name) );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
auto dotpos = op.symbol.find( '.' );
|
||||
|
|
|
|||
|
|
@ -23,6 +23,8 @@
|
|||
*/
|
||||
#include <graphene/chain/asset_object.hpp>
|
||||
#include <graphene/chain/database.hpp>
|
||||
#include <graphene/chain/operation_history_object.hpp>
|
||||
#include <graphene/chain/hardfork.hpp>
|
||||
|
||||
#include <fc/io/raw.hpp>
|
||||
#include <fc/uint128.hpp>
|
||||
|
|
@ -185,6 +187,41 @@ vector<account_id_type> asset_object::get_holders( database& db ) const
|
|||
return holders;
|
||||
}
|
||||
|
||||
vector<uint64_t> asset_object::get_ticket_ids( database& db ) const
|
||||
{
|
||||
auto& asset_bal_idx = db.get_index_type< account_balance_index >().indices().get< by_asset_balance >();
|
||||
vector<uint64_t> ids;
|
||||
const auto range = asset_bal_idx.equal_range( boost::make_tuple( get_id() ) );
|
||||
|
||||
for( const account_balance_object& bal : boost::make_iterator_range( range.first, range.second ) )
|
||||
{
|
||||
const auto& stats = bal.owner(db).statistics(db);
|
||||
const account_transaction_history_object* ath = static_cast<const account_transaction_history_object*>(&stats.most_recent_op(db));
|
||||
for( uint64_t balance = bal.balance.value; balance > 0;)
|
||||
{
|
||||
if(ath != nullptr)
|
||||
{
|
||||
const operation_history_object& oho = db.get<operation_history_object>( ath->operation_id );
|
||||
if( oho.op.which() == operation::tag<ticket_purchase_operation>::value && get_id() == oho.op.get<ticket_purchase_operation>().lottery)
|
||||
{
|
||||
uint64_t tickets_count = oho.op.get<ticket_purchase_operation>().tickets_to_buy;
|
||||
ids.insert(ids.end(), tickets_count, oho.id.instance());
|
||||
balance -= tickets_count;
|
||||
assert(balance >= 0);
|
||||
}
|
||||
|
||||
if( ath->next == account_transaction_history_id_type() )
|
||||
{
|
||||
ath = nullptr;
|
||||
break;
|
||||
}
|
||||
else ath = db.find(ath->next);
|
||||
}
|
||||
}
|
||||
}
|
||||
return ids;
|
||||
}
|
||||
|
||||
void asset_object::distribute_benefactors_part( database& db )
|
||||
{
|
||||
transaction_evaluation_state eval( &db );
|
||||
|
|
@ -206,6 +243,7 @@ map< account_id_type, vector< uint16_t > > asset_object::distribute_winners_part
|
|||
transaction_evaluation_state eval( &db );
|
||||
|
||||
auto holders = get_holders( db );
|
||||
vector<uint64_t> ticket_ids = get_ticket_ids(db);
|
||||
FC_ASSERT( dynamic_data( db ).current_supply == holders.size() );
|
||||
map<account_id_type, vector<uint16_t> > structurized_participants;
|
||||
for( account_id_type holder : holders )
|
||||
|
|
@ -234,6 +272,11 @@ map< account_id_type, vector< uint16_t > > asset_object::distribute_winners_part
|
|||
reward_op.lottery = get_id();
|
||||
reward_op.is_benefactor_reward = false;
|
||||
reward_op.winner = holders[winner_num];
|
||||
if(db.head_block_time() > HARDFORK_5050_1_TIME && ticket_ids.size() >= winner_num)
|
||||
{
|
||||
const static_variant<uint64_t, void_t> tkt_id = ticket_ids[winner_num];
|
||||
reward_op.winner_ticket_id = tkt_id;
|
||||
}
|
||||
reward_op.win_percentage = tickets[c];
|
||||
reward_op.amount = asset( jackpot * tickets[c] * ( 1. - sweeps_distribution_percentage / (double)GRAPHENE_100_PERCENT ) / GRAPHENE_100_PERCENT , db.get_balance(id).asset_id );
|
||||
db.apply_operation(eval, reward_op);
|
||||
|
|
|
|||
|
|
@ -44,46 +44,6 @@
|
|||
|
||||
#include <fc/smart_ref_impl.hpp>
|
||||
|
||||
namespace {
|
||||
|
||||
struct proposed_operations_digest_accumulator
|
||||
{
|
||||
typedef void result_type;
|
||||
|
||||
void operator()(const graphene::chain::proposal_create_operation& proposal)
|
||||
{
|
||||
for (auto& operation: proposal.proposed_ops)
|
||||
{
|
||||
proposed_operations_digests.push_back(fc::digest(operation.op));
|
||||
}
|
||||
}
|
||||
|
||||
//empty template method is needed for all other operation types
|
||||
//we can ignore them, we are interested in only proposal_create_operation
|
||||
template<class T>
|
||||
void operator()(const T&)
|
||||
{}
|
||||
|
||||
std::vector<fc::sha256> proposed_operations_digests;
|
||||
};
|
||||
|
||||
std::vector<fc::sha256> gather_proposed_operations_digests(const graphene::chain::transaction& trx)
|
||||
{
|
||||
proposed_operations_digest_accumulator digest_accumulator;
|
||||
|
||||
for (auto& operation: trx.operations)
|
||||
{
|
||||
if( operation.which() != graphene::chain::operation::tag<graphene::chain::betting_market_group_create_operation>::value
|
||||
&& operation.which() != graphene::chain::operation::tag<graphene::chain::betting_market_create_operation>::value )
|
||||
operation.visit(digest_accumulator);
|
||||
else
|
||||
edump( ("Found dup"));
|
||||
}
|
||||
|
||||
return digest_accumulator.proposed_operations_digests;
|
||||
}
|
||||
}
|
||||
|
||||
namespace graphene { namespace chain {
|
||||
|
||||
bool database::is_known_block( const block_id_type& id )const
|
||||
|
|
@ -150,30 +110,6 @@ std::vector<block_id_type> database::get_block_ids_on_fork(block_id_type head_of
|
|||
return result;
|
||||
}
|
||||
|
||||
void database::check_tansaction_for_duplicated_operations(const signed_transaction& trx)
|
||||
{
|
||||
const auto& proposal_index = get_index<proposal_object>();
|
||||
std::set<fc::sha256> existed_operations_digests;
|
||||
|
||||
proposal_index.inspect_all_objects( [&](const object& obj){
|
||||
const proposal_object& proposal = static_cast<const proposal_object&>(obj);
|
||||
auto proposed_operations_digests = gather_proposed_operations_digests( proposal.proposed_transaction );
|
||||
existed_operations_digests.insert( proposed_operations_digests.begin(), proposed_operations_digests.end() );
|
||||
});
|
||||
|
||||
for (auto& pending_transaction: _pending_tx)
|
||||
{
|
||||
auto proposed_operations_digests = gather_proposed_operations_digests(pending_transaction);
|
||||
existed_operations_digests.insert(proposed_operations_digests.begin(), proposed_operations_digests.end());
|
||||
}
|
||||
|
||||
auto proposed_operations_digests = gather_proposed_operations_digests(trx);
|
||||
for (auto& digest: proposed_operations_digests)
|
||||
{
|
||||
FC_ASSERT(existed_operations_digests.count(digest) == 0, "Proposed operation is already pending for approval.");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Push block "may fail" in which case every partial change is unwound. After
|
||||
* push block is successful the block is appended to the chain database on disk.
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
#ifndef HARDFORK_1000_TIME
|
||||
#define HARDFORK_1000_TIME (fc::time_point_sec( 1540000000 ))
|
||||
#define HARDFORK_1000_TIME (fc::time_point_sec( 1550491200 ))
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
// added delete sport and delete event group operations
|
||||
#ifndef HARDFORK_1001_TIME
|
||||
#define HARDFORK_1001_TIME (fc::time_point_sec( 1540000000 ))
|
||||
#define HARDFORK_1001_TIME (fc::time_point_sec( 1550491200 ))
|
||||
#endif
|
||||
|
|
|
|||
4
libraries/chain/hardfork.d/5050-1.hf
Normal file
4
libraries/chain/hardfork.d/5050-1.hf
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
// 5050_1 HARDFORK Thursday, 22 April 2020 20:00:00 GMT
|
||||
#ifndef HARDFORK_5050_1_TIME
|
||||
#define HARDFORK_5050_1_TIME (fc::time_point_sec( 1587585600 ))
|
||||
#endif
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
// Placeholder HF for affiliate reward system
|
||||
#ifndef HARDFORK_999_TIME
|
||||
#define HARDFORK_999_TIME (fc::time_point_sec( 1540000000 ))
|
||||
#define HARDFORK_999_TIME (fc::time_point_sec( 1550491200 ))
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
// bitshares-core #429 rounding issue when creating assets
|
||||
#ifndef HARDFORK_CORE_429_TIME
|
||||
#define HARDFORK_CORE_429_TIME (fc::time_point_sec( 1566784800 ))
|
||||
#define HARDFORK_CORE_429_TIME (fc::time_point_sec( 1568340000 ))
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
// GPOS HARDFORK Monday, 6 January 2020 01:00:00 GMT
|
||||
// GPOS HARDFORK Monday, 17 February 2020 22:00:00 GMT
|
||||
#ifndef HARDFORK_GPOS_TIME
|
||||
#define HARDFORK_GPOS_TIME (fc::time_point_sec( 1578272400 ))
|
||||
#define HARDFORK_GPOS_TIME (fc::time_point_sec( 1581976800 ))
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
#ifndef HARDFORK_SWEEPS_TIME
|
||||
#define HARDFORK_SWEEPS_TIME (fc::time_point_sec( 1566784800 ))
|
||||
#define HARDFORK_SWEEPS_TIME (fc::time_point_sec( 1568340000 ))
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -134,6 +134,7 @@ namespace graphene { namespace chain {
|
|||
optional<lottery_asset_options> lottery_options;
|
||||
time_point_sec get_lottery_expiration() const;
|
||||
vector<account_id_type> get_holders( database& db ) const;
|
||||
vector<uint64_t> get_ticket_ids( database& db ) const;
|
||||
void distribute_benefactors_part( database& db );
|
||||
map< account_id_type, vector< uint16_t > > distribute_winners_part( database& db );
|
||||
void distribute_sweeps_holders_part( database& db );
|
||||
|
|
|
|||
|
|
@ -718,8 +718,8 @@ inline Stream& operator>>( Stream& s, betting_market_group_object& betting_marke
|
|||
} } // graphene::chain
|
||||
|
||||
FC_REFLECT_DERIVED( graphene::chain::betting_market_rules_object, (graphene::db::object), (name)(description) )
|
||||
FC_REFLECT_DERIVED( graphene::chain::betting_market_group_object, (graphene::db::object), (description) )
|
||||
FC_REFLECT_DERIVED( graphene::chain::betting_market_object, (graphene::db::object), (group_id) )
|
||||
FC_REFLECT_DERIVED( graphene::chain::betting_market_group_object, (graphene::db::object), (description)(event_id)(rules_id)(asset_id)(total_matched_bets_amount)(never_in_play)(delay_before_settling)(settling_time) )
|
||||
FC_REFLECT_DERIVED( graphene::chain::betting_market_object, (graphene::db::object), (group_id)(description)(payout_condition)(resolution) )
|
||||
FC_REFLECT_DERIVED( graphene::chain::bet_object, (graphene::db::object), (bettor_id)(betting_market_id)(amount_to_bet)(backer_multiplier)(back_or_lay)(end_of_delay) )
|
||||
|
||||
FC_REFLECT_DERIVED( graphene::chain::betting_market_position_object, (graphene::db::object), (bettor_id)(betting_market_id)(pay_if_payout_condition)(pay_if_not_payout_condition)(pay_if_canceled)(pay_if_not_canceled)(fees_collected) )
|
||||
|
|
|
|||
|
|
@ -23,8 +23,8 @@
|
|||
*/
|
||||
#pragma once
|
||||
|
||||
#define GRAPHENE_SYMBOL "TEST"
|
||||
#define GRAPHENE_ADDRESS_PREFIX "TEST"
|
||||
#define GRAPHENE_SYMBOL "PPY"
|
||||
#define GRAPHENE_ADDRESS_PREFIX "PPY"
|
||||
|
||||
#define GRAPHENE_MIN_ACCOUNT_NAME_LENGTH 1
|
||||
#define GRAPHENE_MAX_ACCOUNT_NAME_LENGTH 63
|
||||
|
|
@ -151,7 +151,7 @@
|
|||
#define GRAPHENE_RECENTLY_MISSED_COUNT_INCREMENT 4
|
||||
#define GRAPHENE_RECENTLY_MISSED_COUNT_DECREMENT 3
|
||||
|
||||
#define GRAPHENE_CURRENT_DB_VERSION "PPY2.3"
|
||||
#define GRAPHENE_CURRENT_DB_VERSION "PPY2.4"
|
||||
|
||||
#define GRAPHENE_IRREVERSIBLE_THRESHOLD (70 * GRAPHENE_1_PERCENT)
|
||||
|
||||
|
|
|
|||
|
|
@ -138,8 +138,6 @@ namespace graphene { namespace chain {
|
|||
void add_checkpoints( const flat_map<uint32_t,block_id_type>& checkpts );
|
||||
const flat_map<uint32_t,block_id_type> get_checkpoints()const { return _checkpoints; }
|
||||
bool before_last_checkpoint()const;
|
||||
|
||||
void check_tansaction_for_duplicated_operations(const signed_transaction& trx);
|
||||
|
||||
bool push_block( const signed_block& b, uint32_t skip = skip_nothing );
|
||||
processed_transaction push_transaction( const signed_transaction& trx, uint32_t skip = skip_nothing );
|
||||
|
|
|
|||
|
|
@ -158,5 +158,6 @@ typedef generic_index<event_object, event_object_multi_index_type> event_object_
|
|||
return s;
|
||||
}
|
||||
} } // graphene::chain
|
||||
FC_REFLECT(graphene::chain::event_object, (name))
|
||||
FC_REFLECT(graphene::chain::event_object, (name)(season)(start_time)(event_group_id)(at_least_one_betting_market_group_settled)(scores))
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -481,13 +481,13 @@ FC_REFLECT( graphene::chain::bet_place_operation,
|
|||
(fee)(bettor_id)(betting_market_id)(amount_to_bet)(backer_multiplier)(back_or_lay)(extensions) )
|
||||
|
||||
FC_REFLECT( graphene::chain::bet_matched_operation::fee_parameters_type, )
|
||||
FC_REFLECT( graphene::chain::bet_matched_operation, (bettor_id)(bet_id)(amount_bet)(backer_multiplier)(guaranteed_winnings_returned) )
|
||||
FC_REFLECT( graphene::chain::bet_matched_operation, (fee)(bettor_id)(bet_id)(amount_bet)(backer_multiplier)(guaranteed_winnings_returned) )
|
||||
|
||||
FC_REFLECT( graphene::chain::bet_cancel_operation::fee_parameters_type, (fee) )
|
||||
FC_REFLECT( graphene::chain::bet_cancel_operation, (fee) (bettor_id) (bet_to_cancel) (extensions) )
|
||||
|
||||
FC_REFLECT( graphene::chain::bet_canceled_operation::fee_parameters_type, )
|
||||
FC_REFLECT( graphene::chain::bet_canceled_operation, (bettor_id)(bet_id)(stake_returned) )
|
||||
FC_REFLECT( graphene::chain::bet_canceled_operation, (fee)(bettor_id)(bet_id)(stake_returned) )
|
||||
|
||||
FC_REFLECT( graphene::chain::bet_adjusted_operation::fee_parameters_type, )
|
||||
FC_REFLECT( graphene::chain::bet_adjusted_operation, (bettor_id)(bet_id)(stake_returned) )
|
||||
FC_REFLECT( graphene::chain::bet_adjusted_operation, (fee) (bettor_id)(bet_id)(stake_returned) )
|
||||
|
|
|
|||
|
|
@ -73,6 +73,13 @@ namespace graphene { namespace chain {
|
|||
return itr->template get<typename Operation::fee_parameters_type>();
|
||||
}
|
||||
|
||||
template<typename Operation>
|
||||
const bool exists()const
|
||||
{
|
||||
auto itr = parameters.find(typename Operation::fee_parameters_type());
|
||||
return itr != parameters.end();
|
||||
}
|
||||
|
||||
/**
|
||||
* @note must be sorted by fee_parameters.which() and have no duplicates
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -52,6 +52,8 @@ namespace graphene { namespace chain {
|
|||
share_type calculate_fee( const fee_parameters_type& k )const;
|
||||
};
|
||||
|
||||
typedef static_variant<uint64_t, void_t> ticket_num;
|
||||
|
||||
/**
|
||||
* @ingroup operations
|
||||
*/
|
||||
|
|
@ -73,7 +75,7 @@ namespace graphene { namespace chain {
|
|||
// true if recieved from benefators section of lottery; false otherwise
|
||||
bool is_benefactor_reward;
|
||||
|
||||
extensions_type extensions;
|
||||
ticket_num winner_ticket_id;
|
||||
|
||||
account_id_type fee_payer()const { return account_id_type(); }
|
||||
void validate()const {};
|
||||
|
|
@ -114,7 +116,7 @@ FC_REFLECT( graphene::chain::ticket_purchase_operation,
|
|||
)
|
||||
FC_REFLECT( graphene::chain::ticket_purchase_operation::fee_parameters_type, (fee) )
|
||||
|
||||
|
||||
FC_REFLECT_TYPENAME( graphene::chain::ticket_num )
|
||||
FC_REFLECT( graphene::chain::lottery_reward_operation,
|
||||
(fee)
|
||||
(lottery)
|
||||
|
|
@ -122,7 +124,7 @@ FC_REFLECT( graphene::chain::lottery_reward_operation,
|
|||
(amount)
|
||||
(win_percentage)
|
||||
(is_benefactor_reward)
|
||||
(extensions)
|
||||
(winner_ticket_id)
|
||||
)
|
||||
FC_REFLECT( graphene::chain::lottery_reward_operation::fee_parameters_type, (fee) )
|
||||
|
||||
|
|
|
|||
|
|
@ -63,10 +63,18 @@ struct proposal_operation_hardfork_visitor
|
|||
FC_ASSERT( !aco.extensions.value.affiliate_distributions.valid(), "Affiliate reward distributions not allowed yet" );
|
||||
}
|
||||
|
||||
void operator()(const sport_create_operation &v) const {
|
||||
FC_ASSERT( block_time >= HARDFORK_1000_TIME, "sport_create_operation not allowed yet!" );
|
||||
}
|
||||
|
||||
void operator()(const sport_update_operation &v) const {
|
||||
FC_ASSERT( block_time >= HARDFORK_1000_TIME, "sport_update_operation not allowed yet!" );
|
||||
}
|
||||
|
||||
void operator()(const sport_delete_operation &v) const {
|
||||
FC_ASSERT( block_time >= HARDFORK_1000_TIME, "sport_delete_operation not allowed yet!" );
|
||||
}
|
||||
|
||||
void operator()(const event_group_create_operation &v) const {
|
||||
FC_ASSERT( block_time >= HARDFORK_1000_TIME, "event_group_create_operation not allowed yet!" );
|
||||
}
|
||||
|
|
@ -75,6 +83,10 @@ struct proposal_operation_hardfork_visitor
|
|||
FC_ASSERT( block_time >= HARDFORK_1000_TIME, "event_group_update_operation not allowed yet!" );
|
||||
}
|
||||
|
||||
void operator()(const event_group_delete_operation &v) const {
|
||||
FC_ASSERT( block_time >= HARDFORK_1000_TIME, "event_group_delete_operation not allowed yet!" );
|
||||
}
|
||||
|
||||
void operator()(const event_create_operation &v) const {
|
||||
FC_ASSERT( block_time >= HARDFORK_1000_TIME, "event_create_operation not allowed yet!" );
|
||||
}
|
||||
|
|
@ -112,7 +124,7 @@ struct proposal_operation_hardfork_visitor
|
|||
}
|
||||
|
||||
void operator()(const bet_cancel_operation &v) const {
|
||||
FC_ASSERT( block_time >= HARDFORK_1000_TIME, "betting_market_group_resolve_operation not allowed yet!" );
|
||||
FC_ASSERT( block_time >= HARDFORK_1000_TIME, "bet_cancel_operation not allowed yet!" );
|
||||
}
|
||||
|
||||
void operator()(const betting_market_group_update_operation &v) const {
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
Subproject commit 9fa98d9a93ada3e84f48812b5c42b053b0dbf9da
|
||||
Subproject commit 0358ca257e4ce9d66c1097cd2e8e2d34ff89a297
|
||||
|
|
@ -370,7 +370,7 @@ void bookie_plugin_impl::on_block_applied( const signed_block& )
|
|||
assert(bet_iter != persistent_bets_by_bet_id.end());
|
||||
if (bet_iter != persistent_bets_by_bet_id.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));
|
||||
if (is_operation_history_object_stored(op.id))
|
||||
db.modify(*bet_iter, [&]( persistent_bet_object& obj ) {
|
||||
|
|
@ -386,7 +386,7 @@ void bookie_plugin_impl::on_block_applied( const signed_block& )
|
|||
assert(bet_iter != persistent_bets_by_bet_id.end());
|
||||
if (bet_iter != persistent_bets_by_bet_id.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));
|
||||
if (is_operation_history_object_stored(op.id))
|
||||
db.modify(*bet_iter, [&]( persistent_bet_object& obj ) {
|
||||
|
|
|
|||
|
|
@ -3012,7 +3012,7 @@ boost::unit_test::test_suite* init_unit_test_suite(int argc, char* argv[]) {
|
|||
std::cout << "Random number generator seeded to " << time(NULL) << std::endl;
|
||||
|
||||
// betting operations don't take effect until HARDFORK 1000
|
||||
GRAPHENE_TESTING_GENESIS_TIMESTAMP = HARDFORK_1000_TIME.sec_since_epoch() + 2;
|
||||
GRAPHENE_TESTING_GENESIS_TIMESTAMP = HARDFORK_1000_TIME.sec_since_epoch() + 15;
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -55,8 +55,10 @@
|
|||
|
||||
using namespace graphene::chain::test;
|
||||
|
||||
//redefining parameters here to as per updated TESTNET parameters to verify unit test cases
|
||||
uint32_t GRAPHENE_TESTING_GENESIS_TIMESTAMP = 1431700002;
|
||||
|
||||
|
||||
namespace graphene { namespace chain {
|
||||
|
||||
using std::cout;
|
||||
|
|
@ -232,8 +234,9 @@ string database_fixture::generate_anon_acct_name()
|
|||
void database_fixture::verify_asset_supplies( const database& db )
|
||||
{
|
||||
//wlog("*** Begin asset supply verification ***");
|
||||
const asset_dynamic_data_object& core_asset_data = db.get_core_asset().dynamic_asset_data_id(db);
|
||||
BOOST_CHECK(core_asset_data.fee_pool == 0);
|
||||
// It seems peerplays by default DO have core fee pool in genesis so commenting this out
|
||||
//const asset_dynamic_data_object& core_asset_data = db.get_core_asset().dynamic_asset_data_id(db);
|
||||
//BOOST_CHECK(core_asset_data.fee_pool == 0);
|
||||
|
||||
const auto& statistics_index = db.get_index_type<account_stats_index>().indices();
|
||||
const auto& balance_index = db.get_index_type<account_balance_index>().indices();
|
||||
|
|
|
|||
|
|
@ -905,7 +905,7 @@ BOOST_AUTO_TEST_CASE( worker_dividends_voting )
|
|||
vote_for(voter1_id, worker.vote_for, voter1_private_key);
|
||||
|
||||
// first maint pass, coefficient will be 1
|
||||
generate_blocks(db.get_dynamic_global_properties().next_maintenance_time);
|
||||
generate_blocks(HARDFORK_GPOS_TIME + fc::hours(12));
|
||||
worker = worker_id_type()(db);
|
||||
BOOST_CHECK_EQUAL(worker.total_votes_for, 100);
|
||||
|
||||
|
|
@ -925,8 +925,8 @@ BOOST_AUTO_TEST_CASE( worker_dividends_voting )
|
|||
generate_blocks(db.get_dynamic_global_properties().next_maintenance_time);
|
||||
|
||||
// worker is getting paid
|
||||
BOOST_CHECK_EQUAL(worker_id_type()(db).worker.get<vesting_balance_worker_type>().balance(db).balance.amount.value, 10);
|
||||
BOOST_CHECK_EQUAL(worker.worker.get<vesting_balance_worker_type>().balance(db).balance.amount.value, 10);
|
||||
BOOST_CHECK_EQUAL(worker_id_type()(db).worker.get<vesting_balance_worker_type>().balance(db).balance.amount.value, 5);
|
||||
BOOST_CHECK_EQUAL(worker.worker.get<vesting_balance_worker_type>().balance(db).balance.amount.value, 5);
|
||||
|
||||
// second maint pass, coefficient will be 0.75
|
||||
worker = worker_id_type()(db);
|
||||
|
|
@ -1009,8 +1009,8 @@ BOOST_AUTO_TEST_CASE( account_multiple_vesting )
|
|||
vote_for(sam_id, witness1.vote_id, sam_private_key);
|
||||
vote_for(patty_id, witness1.vote_id, patty_private_key);
|
||||
|
||||
generate_blocks(db.get_dynamic_global_properties().next_maintenance_time);
|
||||
|
||||
generate_blocks(HARDFORK_GPOS_TIME + fc::hours(12)); //forward 1/2 sub-period so that it consider only gpos votes
|
||||
|
||||
// amount in vested balanced will sum up as voting power
|
||||
witness1 = witness_id_type(1)(db);
|
||||
BOOST_CHECK_EQUAL(witness1.total_votes, 400);
|
||||
|
|
|
|||
|
|
@ -63,6 +63,7 @@ BOOST_AUTO_TEST_CASE( create_lottery_asset_test )
|
|||
lottery_options.end_date = db.head_block_time() + fc::minutes(5);
|
||||
lottery_options.ticket_price = asset(100);
|
||||
lottery_options.winning_tickets = { 5 * GRAPHENE_1_PERCENT, 5 * GRAPHENE_1_PERCENT, 5 * GRAPHENE_1_PERCENT, 10 * GRAPHENE_1_PERCENT, 10 * GRAPHENE_1_PERCENT, 10 * GRAPHENE_1_PERCENT, 10 * GRAPHENE_1_PERCENT, 10 * GRAPHENE_1_PERCENT, 10 * GRAPHENE_1_PERCENT };
|
||||
//lottery_options.winning_tickets = { 75 * GRAPHENE_1_PERCENT };
|
||||
lottery_options.is_active = test_asset_id.instance.value % 2;
|
||||
lottery_options.ending_on_soldout = true;
|
||||
|
||||
|
|
@ -482,4 +483,64 @@ BOOST_AUTO_TEST_CASE( try_to_end_empty_lottery_test )
|
|||
}
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE( lottery_winner_ticket_id_test )
|
||||
{
|
||||
try {
|
||||
asset_id_type test_asset_id = db.get_index<asset_object>().get_next_id();
|
||||
INVOKE( create_lottery_asset_test );
|
||||
auto test_asset = test_asset_id(db);
|
||||
for( int i = 1; i < 4; ++i ) {
|
||||
transfer(account_id_type(), account_id_type(i), asset(2000000));
|
||||
}
|
||||
for( int i = 1; i < 4; ++i ) {
|
||||
if( i == 4 ) continue;
|
||||
ticket_purchase_operation tpo;
|
||||
tpo.buyer = account_id_type(i);
|
||||
tpo.lottery = test_asset.id;
|
||||
tpo.tickets_to_buy = 1;
|
||||
tpo.amount = asset(100);
|
||||
trx.operations.push_back(std::move(tpo));
|
||||
graphene::chain::test::set_expiration(db, trx);
|
||||
PUSH_TX( db, trx, ~0 );
|
||||
trx.operations.clear();
|
||||
}
|
||||
|
||||
for( int i = 1; i < 4; ++i ) {
|
||||
if( i == 4 ) continue;
|
||||
ticket_purchase_operation tpo;
|
||||
tpo.buyer = account_id_type(i);
|
||||
tpo.lottery = test_asset.id;
|
||||
tpo.tickets_to_buy = 1;
|
||||
tpo.amount = asset(100);
|
||||
trx.operations.push_back(std::move(tpo));
|
||||
graphene::chain::test::set_expiration(db, trx);
|
||||
PUSH_TX( db, trx, ~0 );
|
||||
trx.operations.clear();
|
||||
}
|
||||
generate_block();
|
||||
test_asset = test_asset_id(db);
|
||||
uint64_t creator_balance_before_end = db.get_balance( account_id_type(), asset_id_type() ).amount.value;
|
||||
uint64_t jackpot = db.get_balance( test_asset.get_id() ).amount.value;
|
||||
uint16_t winners_part = 0;
|
||||
for( uint8_t win: test_asset.lottery_options->winning_tickets )
|
||||
winners_part += win;
|
||||
|
||||
while( db.head_block_time() < ( test_asset.lottery_options->end_date ) )
|
||||
generate_block();
|
||||
|
||||
auto op_history = get_operation_history( account_id_type(1) ); //Can observe operation 79 to verify winner ticket number
|
||||
for( auto h: op_history ) {
|
||||
idump((h));
|
||||
}
|
||||
|
||||
BOOST_CHECK( db.get_balance( test_asset.get_id() ).amount.value == 0 );
|
||||
uint64_t creator_recieved = db.get_balance( account_id_type(), asset_id_type() ).amount.value - creator_balance_before_end;
|
||||
test_asset = test_asset_id(db);
|
||||
BOOST_CHECK(jackpot * test_asset.lottery_options->benefactors[0].share / GRAPHENE_100_PERCENT == creator_recieved);
|
||||
} catch (fc::exception& e) {
|
||||
edump((e.to_detail_string()));
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_SUITE_END()
|
||||
|
|
|
|||
|
|
@ -9,8 +9,10 @@
|
|||
#include <graphene/chain/proposal_object.hpp>
|
||||
#include <graphene/chain/witness_object.hpp>
|
||||
#include <graphene/chain/protocol/committee_member.hpp>
|
||||
#include <graphene/chain/protocol/sport.hpp>
|
||||
#include <graphene/app/api.hpp>
|
||||
#include <fc/crypto/digest.hpp>
|
||||
#include <graphene/app/database_api.hpp>
|
||||
|
||||
#include "../common/database_fixture.hpp"
|
||||
|
||||
|
|
@ -29,6 +31,27 @@ namespace
|
|||
return transfer;
|
||||
}
|
||||
|
||||
sport_create_operation make_sport_create_operation(std::string s1, std::string s2)
|
||||
{
|
||||
sport_create_operation op;
|
||||
op.name = {{ s1, s2 }};
|
||||
return op;
|
||||
}
|
||||
|
||||
betting_market_group_create_operation make_betting_market_group_create(string s1, string s2)
|
||||
{
|
||||
betting_market_group_create_operation op;
|
||||
op.description = {{ s1, s2 }};
|
||||
return op;
|
||||
}
|
||||
|
||||
betting_market_create_operation make_betting_market_operation(string s1, string s2)
|
||||
{
|
||||
betting_market_create_operation op;
|
||||
op.description = {{ s1, s2 }};
|
||||
return op;
|
||||
}
|
||||
|
||||
committee_member_create_operation make_committee_member_create_operation(const asset& fee, const account_id_type& member, const string& url)
|
||||
{
|
||||
committee_member_create_operation member_create_operation;
|
||||
|
|
@ -49,6 +72,7 @@ namespace
|
|||
fixture.db.create<proposal_object>([&](proposal_object& proposal)
|
||||
{
|
||||
proposal.proposed_transaction = transaction;
|
||||
proposal.required_active_approvals = { GRAPHENE_WITNESS_ACCOUNT };
|
||||
});
|
||||
}
|
||||
|
||||
|
|
@ -89,19 +113,16 @@ namespace
|
|||
}
|
||||
}
|
||||
|
||||
BOOST_FIXTURE_TEST_SUITE( check_tansaction_for_duplicated_operations, database_fixture )
|
||||
BOOST_FIXTURE_TEST_SUITE( check_transaction_for_duplicated_operations, database_fixture )
|
||||
|
||||
BOOST_AUTO_TEST_CASE( test_exception_throwing_for_the_same_operation_proposed_twice )
|
||||
BOOST_AUTO_TEST_CASE( test_exception_throwing_for_the_same_operation_proposed_for_witness_twice )
|
||||
{
|
||||
try
|
||||
{
|
||||
ACTORS((alice))
|
||||
create_proposal(*this, {make_sport_create_operation("SPORT1", "S1")});
|
||||
|
||||
create_proposal(*this, {make_transfer_operation(account_id_type(), alice_id, asset(500))});
|
||||
|
||||
auto trx = make_signed_transaction_with_proposed_operation(*this, {make_transfer_operation(account_id_type(), alice_id, asset(500))});
|
||||
//Modifying from BOOST_CHECK to BOOST_WARN just to make sure users might confuse about this error. If any changes in network_boradcast, would recommend to revert the changes
|
||||
BOOST_WARN_THROW(db.check_tansaction_for_duplicated_operations(trx), fc::exception);
|
||||
auto trx = make_signed_transaction_with_proposed_operation(*this, {make_sport_create_operation("SPORT1", "S1")} );
|
||||
BOOST_CHECK_THROW(graphene::app::database_api(db).check_transaction_for_duplicated_operations(trx), fc::exception);
|
||||
}
|
||||
catch( const fc::exception& e )
|
||||
{
|
||||
|
|
@ -114,10 +135,8 @@ BOOST_AUTO_TEST_CASE( check_passes_without_duplication )
|
|||
{
|
||||
try
|
||||
{
|
||||
ACTORS((alice))
|
||||
|
||||
auto trx = make_signed_transaction_with_proposed_operation(*this, {make_transfer_operation(account_id_type(), alice_id, asset(500))});
|
||||
BOOST_CHECK_NO_THROW(db.check_tansaction_for_duplicated_operations(trx));
|
||||
auto trx = make_signed_transaction_with_proposed_operation(*this, {make_sport_create_operation("SPORT1", "S1")});
|
||||
BOOST_CHECK_NO_THROW(graphene::app::database_api(db).check_transaction_for_duplicated_operations(trx));
|
||||
}
|
||||
catch( const fc::exception& e )
|
||||
{
|
||||
|
|
@ -126,16 +145,14 @@ BOOST_AUTO_TEST_CASE( check_passes_without_duplication )
|
|||
}
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE( check_passes_for_the_same_operation_with_different_assets )
|
||||
BOOST_AUTO_TEST_CASE( check_passes_for_the_same_operation_with_different_names )
|
||||
{
|
||||
try
|
||||
{
|
||||
ACTORS((alice))
|
||||
create_proposal(*this, {make_sport_create_operation("SPORT1", "S1")});
|
||||
|
||||
create_proposal(*this, {make_transfer_operation(account_id_type(), alice_id, asset(500))});
|
||||
|
||||
auto trx = make_signed_transaction_with_proposed_operation(*this, {make_transfer_operation(account_id_type(), alice_id, asset(501))});
|
||||
BOOST_CHECK_NO_THROW(db.check_tansaction_for_duplicated_operations(trx));
|
||||
auto trx = make_signed_transaction_with_proposed_operation(*this, {make_sport_create_operation("SPORT2", "S2")});
|
||||
BOOST_CHECK_NO_THROW(graphene::app::database_api(db).check_transaction_for_duplicated_operations(trx));
|
||||
}
|
||||
catch( const fc::exception& e )
|
||||
{
|
||||
|
|
@ -148,14 +165,11 @@ BOOST_AUTO_TEST_CASE( check_fails_for_duplication_in_transaction_with_several_op
|
|||
{
|
||||
try
|
||||
{
|
||||
ACTORS((alice))
|
||||
create_proposal(*this, {make_sport_create_operation("SPORT1", "S1")});
|
||||
|
||||
create_proposal(*this, {make_transfer_operation(account_id_type(), alice_id, asset(500))});
|
||||
|
||||
auto trx = make_signed_transaction_with_proposed_operation(*this, {make_transfer_operation(account_id_type(), alice_id, asset(501)),
|
||||
make_transfer_operation(account_id_type(), alice_id, asset(500))}); //duplicated one
|
||||
//Modifying from BOOST_CHECK to BOOST_WARN just to make sure users might confuse about this error. If any changes in network_boradcast, would recommend to revert the changes
|
||||
BOOST_WARN_THROW(db.check_tansaction_for_duplicated_operations(trx), fc::exception);
|
||||
auto trx = make_signed_transaction_with_proposed_operation(*this, {make_sport_create_operation("SPORT2", "S2"),
|
||||
make_sport_create_operation("SPORT1", "S1") }); //duplicated one
|
||||
BOOST_CHECK_THROW(graphene::app::database_api(db).check_transaction_for_duplicated_operations(trx), fc::exception);
|
||||
}
|
||||
catch( const fc::exception& e )
|
||||
{
|
||||
|
|
@ -168,15 +182,12 @@ BOOST_AUTO_TEST_CASE( check_fails_for_duplicated_operation_in_existed_proposal_w
|
|||
{
|
||||
try
|
||||
{
|
||||
ACTORS((alice))
|
||||
create_proposal(*this, {make_sport_create_operation("SPORT1", "S1"),
|
||||
make_sport_create_operation("SPORT2", "S2") }); //duplicated one
|
||||
|
||||
create_proposal(*this, {make_transfer_operation(account_id_type(), alice_id, asset(499)),
|
||||
make_transfer_operation(account_id_type(), alice_id, asset(500))}); //duplicated one
|
||||
|
||||
auto trx = make_signed_transaction_with_proposed_operation(*this, {make_transfer_operation(account_id_type(), alice_id, asset(501)),
|
||||
make_transfer_operation(account_id_type(), alice_id, asset(500))}); //duplicated one
|
||||
//Modifying from BOOST_CHECK to BOOST_WARN just to make sure users might confuse about this error. If any changes in network_boradcast, would recommend to revert the changes
|
||||
BOOST_WARN_THROW(db.check_tansaction_for_duplicated_operations(trx), fc::exception);
|
||||
auto trx = make_signed_transaction_with_proposed_operation(*this, {make_sport_create_operation("SPORT3", "S3"),
|
||||
make_sport_create_operation("SPORT2", "S2")}); //duplicated one
|
||||
BOOST_CHECK_THROW(graphene::app::database_api(db).check_transaction_for_duplicated_operations(trx), fc::exception);
|
||||
}
|
||||
catch( const fc::exception& e )
|
||||
{
|
||||
|
|
@ -189,14 +200,11 @@ BOOST_AUTO_TEST_CASE( check_fails_for_duplicated_operation_in_existed_proposal_w
|
|||
{
|
||||
try
|
||||
{
|
||||
ACTORS((alice))
|
||||
create_proposal(*this, {make_sport_create_operation("SPORT1", "S1"),
|
||||
make_sport_create_operation("SPORT2", "S2")}); //duplicated one
|
||||
|
||||
create_proposal(*this, {make_transfer_operation(account_id_type(), alice_id, asset(499)),
|
||||
make_transfer_operation(account_id_type(), alice_id, asset(500))}); //duplicated one
|
||||
|
||||
auto trx = make_signed_transaction_with_proposed_operation(*this, {make_transfer_operation(account_id_type(), alice_id, asset(500))}); //duplicated one
|
||||
//Modifying from BOOST_CHECK to BOOST_WARN just to make sure users might confuse about this error. If any changes in network_boradcast, would recommend to revert the changes
|
||||
BOOST_WARN_THROW(db.check_tansaction_for_duplicated_operations(trx), fc::exception);
|
||||
auto trx = make_signed_transaction_with_proposed_operation(*this, {make_sport_create_operation("SPORT2", "S2")}); //duplicated one
|
||||
BOOST_CHECK_THROW(graphene::app::database_api(db).check_transaction_for_duplicated_operations(trx), fc::exception);
|
||||
}
|
||||
catch( const fc::exception& e )
|
||||
{
|
||||
|
|
@ -209,12 +217,12 @@ BOOST_AUTO_TEST_CASE( check_passes_for_different_operations_types )
|
|||
{
|
||||
try
|
||||
{
|
||||
ACTORS((alice))
|
||||
ACTOR( alice );
|
||||
|
||||
create_proposal(*this, {make_transfer_operation(account_id_type(), alice_id, asset(500))});
|
||||
|
||||
auto trx = make_signed_transaction_with_proposed_operation(*this, {make_committee_member_create_operation(asset(1000), account_id_type(), "test url")});
|
||||
BOOST_CHECK_NO_THROW(db.check_tansaction_for_duplicated_operations(trx));
|
||||
BOOST_CHECK_NO_THROW(graphene::app::database_api(db).check_transaction_for_duplicated_operations(trx));
|
||||
}
|
||||
catch( const fc::exception& e )
|
||||
{
|
||||
|
|
@ -230,8 +238,7 @@ BOOST_AUTO_TEST_CASE( check_fails_for_same_member_create_operations )
|
|||
create_proposal(*this, {make_committee_member_create_operation(asset(1000), account_id_type(), "test url")});
|
||||
|
||||
auto trx = make_signed_transaction_with_proposed_operation(*this, {make_committee_member_create_operation(asset(1000), account_id_type(), "test url")});
|
||||
//Modifying from BOOST_CHECK to BOOST_WARN just to make sure users might confuse about this error. If any changes in network_boradcast, would recommend to revert the changes
|
||||
BOOST_WARN_THROW(db.check_tansaction_for_duplicated_operations(trx), fc::exception);
|
||||
BOOST_CHECK_THROW(graphene::app::database_api(db).check_transaction_for_duplicated_operations(trx), fc::exception);
|
||||
}
|
||||
catch( const fc::exception& e )
|
||||
{
|
||||
|
|
@ -247,7 +254,7 @@ BOOST_AUTO_TEST_CASE( check_passes_for_different_member_create_operations )
|
|||
create_proposal(*this, {make_committee_member_create_operation(asset(1000), account_id_type(), "test url")});
|
||||
|
||||
auto trx = make_signed_transaction_with_proposed_operation(*this, {make_committee_member_create_operation(asset(1001), account_id_type(), "test url")});
|
||||
BOOST_CHECK_NO_THROW(db.check_tansaction_for_duplicated_operations(trx));
|
||||
BOOST_CHECK_NO_THROW(graphene::app::database_api(db).check_transaction_for_duplicated_operations(trx));
|
||||
}
|
||||
catch( const fc::exception& e )
|
||||
{
|
||||
|
|
@ -271,8 +278,7 @@ BOOST_AUTO_TEST_CASE( check_failes_for_several_operations_of_mixed_type )
|
|||
auto trx = make_signed_transaction_with_proposed_operation(*this, {make_transfer_operation(account_id_type(), alice_id, asset(501)), //duplicate
|
||||
make_committee_member_create_operation(asset(1002), account_id_type(), "test url")});
|
||||
|
||||
//Modifying from BOOST_CHECK to BOOST_WARN just to make sure users might confuse about this error. If any changes in network_boradcast, would recommend to revert the changes
|
||||
BOOST_WARN_THROW(db.check_tansaction_for_duplicated_operations(trx), fc::exception);
|
||||
BOOST_CHECK_THROW(graphene::app::database_api(db).check_transaction_for_duplicated_operations(trx), fc::exception);
|
||||
}
|
||||
catch( const fc::exception& e )
|
||||
{
|
||||
|
|
@ -285,20 +291,16 @@ BOOST_AUTO_TEST_CASE( check_failes_for_duplicates_in_pending_transactions_list )
|
|||
{
|
||||
try
|
||||
{
|
||||
ACTORS((alice))
|
||||
ACTOR( alice );
|
||||
generate_blocks( HARDFORK_1000_TIME + 15 );
|
||||
|
||||
fc::ecc::private_key committee_key = init_account_priv_key;
|
||||
auto duplicate = make_sport_create_operation("SPORT1", "S1");
|
||||
|
||||
const account_object& moneyman = create_account("moneyman", init_account_pub_key);
|
||||
const asset_object& core = asset_id_type()(db);
|
||||
push_proposal( *this, GRAPHENE_WITNESS_ACCOUNT(db), {duplicate} );
|
||||
|
||||
transfer(account_id_type()(db), moneyman, core.amount(1000000));
|
||||
auto trx = make_signed_transaction_with_proposed_operation( *this, {duplicate} );
|
||||
|
||||
auto duplicate = make_transfer_operation(alice.id, moneyman.get_id(), asset(100));
|
||||
push_proposal(*this, moneyman, {duplicate});
|
||||
|
||||
auto trx = make_signed_transaction_with_proposed_operation(*this, {duplicate});
|
||||
BOOST_CHECK_THROW(db.check_tansaction_for_duplicated_operations(trx), fc::exception);
|
||||
BOOST_CHECK_THROW(graphene::app::database_api(db).check_transaction_for_duplicated_operations(trx), fc::exception);
|
||||
}
|
||||
catch( const fc::exception& e )
|
||||
{
|
||||
|
|
@ -323,7 +325,7 @@ BOOST_AUTO_TEST_CASE( check_passes_for_no_duplicates_in_pending_transactions_lis
|
|||
push_proposal(*this, moneyman, {make_transfer_operation(alice.id, moneyman.get_id(), asset(100))});
|
||||
|
||||
auto trx = make_signed_transaction_with_proposed_operation(*this, {make_transfer_operation(alice.id, moneyman.get_id(), asset(101))});
|
||||
BOOST_CHECK_NO_THROW(db.check_tansaction_for_duplicated_operations(trx));
|
||||
BOOST_CHECK_NO_THROW(graphene::app::database_api(db).check_transaction_for_duplicated_operations(trx));
|
||||
}
|
||||
catch( const fc::exception& e )
|
||||
{
|
||||
|
|
@ -339,19 +341,19 @@ BOOST_AUTO_TEST_CASE( check_fails_for_several_transactions_with_duplicates_in_pe
|
|||
ACTORS((alice))
|
||||
|
||||
fc::ecc::private_key committee_key = init_account_priv_key;
|
||||
|
||||
|
||||
const account_object& moneyman = create_account("moneyman", init_account_pub_key);
|
||||
const asset_object& core = asset_id_type()(db);
|
||||
|
||||
transfer(account_id_type()(db), moneyman, core.amount(1000000));
|
||||
generate_blocks( HARDFORK_1000_TIME + 15 );
|
||||
auto duplicate = make_sport_create_operation("SPORT1", "S1");
|
||||
push_proposal(*this, moneyman, {make_sport_create_operation("SPORT2", "S2"), duplicate} );
|
||||
|
||||
auto duplicate = make_transfer_operation(alice.id, moneyman.get_id(), asset(100));
|
||||
push_proposal(*this, moneyman, {make_transfer_operation(alice.id, moneyman.get_id(), asset(101)),
|
||||
duplicate});
|
||||
|
||||
auto trx = make_signed_transaction_with_proposed_operation(*this, {duplicate,
|
||||
make_transfer_operation(alice.id, moneyman.get_id(), asset(102))});
|
||||
BOOST_CHECK_THROW(db.check_tansaction_for_duplicated_operations(trx), fc::exception);
|
||||
auto trx = make_signed_transaction_with_proposed_operation(*this,
|
||||
{duplicate, make_sport_create_operation("SPORT3", "S3")} );
|
||||
|
||||
BOOST_CHECK_THROW(graphene::app::database_api(db).check_transaction_for_duplicated_operations(trx), fc::exception);
|
||||
}
|
||||
catch( const fc::exception& e )
|
||||
{
|
||||
|
|
@ -360,63 +362,80 @@ BOOST_AUTO_TEST_CASE( check_fails_for_several_transactions_with_duplicates_in_pe
|
|||
}
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE( check_passes_for_duplicated_betting_market_or_group )
|
||||
BOOST_AUTO_TEST_CASE( check_passes_for_duplicated_betting_market_group_create )
|
||||
{
|
||||
generate_blocks( HARDFORK_1000_TIME + fc::seconds(300) );
|
||||
try
|
||||
{
|
||||
auto duplicate = make_betting_market_group_create( "BMGROUP1", "BMG1" );
|
||||
|
||||
create_proposal(*this, {duplicate} );
|
||||
|
||||
auto trx = make_signed_transaction_with_proposed_operation(*this, {duplicate} );
|
||||
|
||||
BOOST_CHECK_NO_THROW( graphene::app::database_api(db).check_transaction_for_duplicated_operations(trx) );
|
||||
}
|
||||
catch( const fc::exception &e )
|
||||
{
|
||||
edump( ( e.to_detail_string() ) );
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE( check_passes_for_duplicated_betting_market_create )
|
||||
{
|
||||
try
|
||||
{
|
||||
const sport_id_type sport_id = create_sport( {{"SN","SPORT_NAME"}} ).id;
|
||||
const event_group_id_type event_group_id = create_event_group( {{"EG", "EVENT_GROUP"}}, sport_id ).id;
|
||||
const betting_market_rules_id_type betting_market_rules_id =
|
||||
create_betting_market_rules( {{"EN", "Rules"}}, {{"EN", "Some rules"}} ).id;
|
||||
auto duplicate = make_betting_market_operation( "BMARKET1", "BM1" );
|
||||
|
||||
event_create_operation evcop1;
|
||||
evcop1.event_group_id = event_group_id;
|
||||
evcop1.name = {{"NO", "NAME_ONE"}};
|
||||
evcop1.season = {{"NO", "NAME_ONE"}};
|
||||
create_proposal( *this, {duplicate} );
|
||||
|
||||
event_create_operation evcop2;
|
||||
evcop2.event_group_id = event_group_id;
|
||||
evcop2.name = {{"NT", "NAME_TWO"}};
|
||||
evcop2.season = {{"NT", "NAME_TWO"}};
|
||||
auto trx = make_signed_transaction_with_proposed_operation(*this, {duplicate} );
|
||||
|
||||
betting_market_group_create_operation bmgcop;
|
||||
bmgcop.description = {{"NN", "NO_NAME"}};
|
||||
bmgcop.event_id = object_id_type(relative_protocol_ids, 0, 0);
|
||||
bmgcop.rules_id = betting_market_rules_id;
|
||||
bmgcop.asset_id = asset_id_type();
|
||||
|
||||
betting_market_create_operation bmcop;
|
||||
bmcop.group_id = object_id_type(relative_protocol_ids, 0, 1);
|
||||
bmcop.payout_condition.insert( internationalized_string_type::value_type( "CN", "CONDI_NAME" ) );
|
||||
|
||||
proposal_create_operation pcop1 = proposal_create_operation::committee_proposal(
|
||||
db.get_global_properties().parameters,
|
||||
db.head_block_time()
|
||||
);
|
||||
pcop1.review_period_seconds.reset();
|
||||
|
||||
proposal_create_operation pcop2 = pcop1;
|
||||
|
||||
trx.clear();
|
||||
|
||||
pcop1.proposed_ops.emplace_back( evcop1 );
|
||||
pcop1.proposed_ops.emplace_back( bmgcop );
|
||||
pcop1.proposed_ops.emplace_back( bmcop );
|
||||
|
||||
pcop2.proposed_ops.emplace_back( evcop2 );
|
||||
pcop2.proposed_ops.emplace_back( bmgcop );
|
||||
pcop2.proposed_ops.emplace_back( bmcop );
|
||||
|
||||
create_proposal(*this, { pcop1, pcop2 });
|
||||
|
||||
auto trx = make_signed_transaction_with_proposed_operation(*this, { pcop1, pcop2 });
|
||||
BOOST_CHECK_NO_THROW( db.check_tansaction_for_duplicated_operations(trx) );
|
||||
BOOST_CHECK_NO_THROW( graphene::app::database_api(db).check_transaction_for_duplicated_operations(trx) );
|
||||
}
|
||||
catch( const fc::exception& e )
|
||||
catch( const fc::exception &e )
|
||||
{
|
||||
edump((e.to_detail_string()));
|
||||
edump( ( e.to_detail_string() ) );
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE( check_passes_for_duplicated_betting_market_and_betting_market_group_create )
|
||||
{
|
||||
try
|
||||
{
|
||||
auto duplicate_market = make_betting_market_operation( "BMARKET1", "BM1" );
|
||||
auto duplicate_group = make_betting_market_group_create( "BMGROUP1", "BMG1" );
|
||||
|
||||
create_proposal( *this, {duplicate_market, duplicate_group} );
|
||||
|
||||
auto trx = make_signed_transaction_with_proposed_operation(*this, {duplicate_market, duplicate_group} );
|
||||
|
||||
BOOST_CHECK_NO_THROW( graphene::app::database_api(db).check_transaction_for_duplicated_operations(trx) );
|
||||
}
|
||||
catch( const fc::exception &e )
|
||||
{
|
||||
edump( ( e.to_detail_string() ) );
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE( check_passes_for_duplicated_betting_market_in_one_operation )
|
||||
{
|
||||
try
|
||||
{
|
||||
auto duplicate = make_betting_market_operation( "BMARKET1", "BM1" );
|
||||
|
||||
create_proposal( *this, {duplicate, duplicate} );
|
||||
|
||||
auto trx = make_signed_transaction_with_proposed_operation(*this, {duplicate, duplicate} );
|
||||
|
||||
BOOST_CHECK_NO_THROW( graphene::app::database_api(db).check_transaction_for_duplicated_operations(trx) );
|
||||
}
|
||||
catch( const fc::exception &e )
|
||||
{
|
||||
edump( ( e.to_detail_string() ) );
|
||||
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
|
@ -462,4 +481,4 @@ BOOST_AUTO_TEST_CASE( broadcast_transaction_with_callback_test ) {
|
|||
} FC_LOG_AND_RETHROW()
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_SUITE_END()
|
||||
BOOST_AUTO_TEST_SUITE_END()
|
||||
Loading…
Reference in a new issue