Updating code
reviving this project
This commit is contained in:
+19
-6
@@ -1,16 +1,29 @@
|
||||
#!/bin/sh
|
||||
# Copyright (c) 2013-2016 The Bitcoin Core developers
|
||||
# Copyright (c) 2026 Agrarian Developers
|
||||
# Distributed under the MIT software license, see the accompanying
|
||||
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
export LC_ALL=C
|
||||
set -e
|
||||
srcdir="$(dirname $0)"
|
||||
|
||||
# Fail fast on errors and undefined vars. (Note: 'pipefail' is not POSIX sh.)
|
||||
set -eu
|
||||
|
||||
srcdir="$(CDPATH= cd -- "$(dirname -- "$0")" && pwd -P)"
|
||||
cd "$srcdir"
|
||||
if [ -z ${LIBTOOLIZE} ] && GLIBTOOLIZE="`which glibtoolize 2>/dev/null`"; then
|
||||
LIBTOOLIZE="${GLIBTOOLIZE}"
|
||||
|
||||
# Prefer glibtoolize on macOS if LIBTOOLIZE isn't already set.
|
||||
if [ -z "${LIBTOOLIZE:-}" ]; then
|
||||
GLIBTOOLIZE="$(command -v glibtoolize 2>/dev/null || true)"
|
||||
if [ -n "$GLIBTOOLIZE" ]; then
|
||||
LIBTOOLIZE="$GLIBTOOLIZE"
|
||||
export LIBTOOLIZE
|
||||
fi
|
||||
which autoreconf >/dev/null || \
|
||||
(echo "configuration failed, please install autoconf first" && exit 1)
|
||||
fi
|
||||
|
||||
if ! command -v autoreconf >/dev/null 2>&1; then
|
||||
echo "configuration failed: please install autoconf first" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
autoreconf --install --force --warnings=all
|
||||
|
||||
+5
-1
@@ -1,3 +1,7 @@
|
||||
dnl Copyright (c) 2026 Agrarian Developers
|
||||
dnl Distributed under the MIT/X11 software license, see the accompanying
|
||||
dnl file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
dnl require autoconf 2.60 (AS_ECHO/AS_ECHO_N)
|
||||
AC_PREREQ([2.60])
|
||||
define(_CLIENT_VERSION_MAJOR, 1)
|
||||
@@ -5,7 +9,7 @@ define(_CLIENT_VERSION_MINOR, 0)
|
||||
define(_CLIENT_VERSION_REVISION, 0)
|
||||
define(_CLIENT_VERSION_BUILD, 0)
|
||||
define(_CLIENT_VERSION_IS_RELEASE, true)
|
||||
define(_COPYRIGHT_YEAR, 2022)
|
||||
define(_COPYRIGHT_YEAR, 2026)
|
||||
AC_INIT([Agrarian Core],[_CLIENT_VERSION_MAJOR._CLIENT_VERSION_MINOR._CLIENT_VERSION_REVISION],[www.agrarian.org],[agrarian])
|
||||
AC_CONFIG_SRCDIR([src/main.cpp])
|
||||
AC_CONFIG_HEADERS([src/config/agrarian-config.h])
|
||||
|
||||
+49
-209
@@ -1,135 +1,87 @@
|
||||
UNIX BUILD NOTES
|
||||
====================
|
||||
Some notes on how to build Agrarian Core in Unix.
|
||||
Copyright (c) 2026 Agrarian Developers
|
||||
|
||||
Note
|
||||
---------------------
|
||||
Always use absolute paths to configure and compile Agrarian Core and the dependencies,
|
||||
For example, when specifying the path of the dependency:
|
||||
UNIX Build Notes
|
||||
|
||||
These notes describe how to build Agrarian Core on Unix-based systems.
|
||||
|
||||
IMPORTANT
|
||||
|
||||
Always use absolute paths when configuring and compiling Agrarian Core
|
||||
and its dependencies.
|
||||
|
||||
Example:
|
||||
|
||||
../dist/configure --enable-cxx --disable-shared --with-pic --prefix=$BDB_PREFIX
|
||||
|
||||
Here BDB_PREFIX must be an absolute path - it is defined using $(pwd) which ensures
|
||||
the usage of the absolute path.
|
||||
$BDB_PREFIX must be an absolute path. Using $(pwd) ensures an absolute
|
||||
path is used.
|
||||
|
||||
To Build
|
||||
---------------------
|
||||
STANDARD BUILD
|
||||
|
||||
```bash
|
||||
./autogen.sh
|
||||
./configure
|
||||
make
|
||||
make install # optional
|
||||
```
|
||||
make install (optional)
|
||||
|
||||
This will build agrarian-qt as well, if the dependencies are met.
|
||||
If dependencies are satisfied, this will build agrarian-qt as well.
|
||||
|
||||
Dependencies
|
||||
---------------------
|
||||
DEPENDENCIES
|
||||
|
||||
These dependencies are required:
|
||||
Required: - libssl : Crypto (RNG, ECC) - libboost : Utility (threading,
|
||||
data structures) - libevent : Networking (async networking) - libgmp :
|
||||
Bignum arithmetic
|
||||
|
||||
Library | Purpose | Description
|
||||
------------|--------------------|----------------------
|
||||
libssl | Crypto | Random Number Generation, Elliptic Curve Cryptography
|
||||
libboost | Utility | Library for threading, data structures, etc
|
||||
libevent | Networking | OS independent asynchronous networking
|
||||
libgmp | Bignum Arithmetic | Precision arithmetic
|
||||
Optional: - miniupnpc : UPnP support - libdb4.8 : Berkeley DB (wallet
|
||||
builds only) - qt : GUI support - protobuf : GUI payment protocol -
|
||||
libqrencode: QR code support - univalue : JSON parsing (bundled by
|
||||
default) - libzmq3 : ZMQ notifications (>= 4.0.0)
|
||||
|
||||
Optional dependencies:
|
||||
See dependencies.md for version details.
|
||||
|
||||
Library | Purpose | Description
|
||||
------------|------------------|----------------------
|
||||
miniupnpc | UPnP Support | Firewall-jumping support
|
||||
libdb4.8 | Berkeley DB | Wallet storage (only needed when wallet enabled)
|
||||
qt | GUI | GUI toolkit (only needed when GUI enabled)
|
||||
protobuf | Payments in GUI | Data interchange format used for payment protocol (only needed when GUI enabled)
|
||||
libqrencode | QR codes in GUI | Optional for generating QR codes (only needed when GUI enabled)
|
||||
univalue | Utility | JSON parsing and encoding (bundled version will be used unless --with-system-univalue passed to configure)
|
||||
libzmq3 | ZMQ notification | Optional, allows generating ZMQ notifications (requires ZMQ version >= 4.0.0)
|
||||
MEMORY REQUIREMENTS
|
||||
|
||||
For the versions used, see [dependencies.md](dependencies.md)
|
||||
|
||||
Memory Requirements
|
||||
--------------------
|
||||
|
||||
C++ compilers are memory-hungry. It is recommended to have at least 1.5 GB of
|
||||
memory available when compiling Agrarian Core. On systems with less, gcc can be
|
||||
tuned to conserve memory with additional CXXFLAGS:
|
||||
Minimum recommended: 1.5 GB RAM.
|
||||
|
||||
Low memory systems:
|
||||
|
||||
./configure CXXFLAGS="--param ggc-min-expand=1 --param ggc-min-heapsize=32768"
|
||||
|
||||
UBUNTU / DEBIAN
|
||||
|
||||
## Linux Distribution Specific Instructions
|
||||
|
||||
### Ubuntu & Debian
|
||||
|
||||
#### Dependency Build Instructions
|
||||
|
||||
Build requirements:
|
||||
Build tools:
|
||||
|
||||
sudo apt-get install build-essential libtool bsdmainutils autotools-dev autoconf pkg-config automake python3
|
||||
|
||||
Now, you can either build from self-compiled [depends](/depends/README.md) or install the required dependencies:
|
||||
Libraries:
|
||||
|
||||
sudo apt-get install libssl-dev libgmp-dev libevent-dev libboost-all-dev
|
||||
|
||||
**Note:** For Ubuntu versions starting with Bionic (18.04), or Debian versions starting with Stretch, use `libssl1.0-dev`
|
||||
above instead of `libssl-dev`. Agrarian Core does not support the use of OpenSSL 1.1, though compilation is still possible
|
||||
by passing `--with-incompatible-ssl` to configure (NOT RECOMMENDED!).
|
||||
OpenSSL Note: For Ubuntu >= 18.04 or Debian >= Stretch use
|
||||
libssl1.0-dev. OpenSSL 1.1 is not officially supported.
|
||||
|
||||
BerkeleyDB is required for the wallet.
|
||||
|
||||
**For Ubuntu only:** db4.8 packages are available [here](https://launchpad.net/~bitcoin/+archive/bitcoin).
|
||||
You can add the repository using the following command:
|
||||
Berkeley DB 4.8 (wallet support):
|
||||
|
||||
sudo apt-get install software-properties-common
|
||||
sudo add-apt-repository ppa:bitcoin/bitcoin
|
||||
sudo apt-get update
|
||||
sudo apt-get install libdb4.8-dev libdb4.8++-dev
|
||||
|
||||
Ubuntu and Debian have their own libdb-dev and libdb++-dev packages, but these will install
|
||||
BerkeleyDB 5.1 or later. This will break binary wallet compatibility with the distributed executables, which
|
||||
are based on BerkeleyDB 4.8. If you do not care about wallet compatibility,
|
||||
pass `--with-incompatible-bdb` to configure.
|
||||
|
||||
Otherwise, you can build from self-compiled `depends` (see above).
|
||||
|
||||
To build Agrarian Core without wallet, see [*Disable-wallet mode*](/doc/build-unix.md#disable-wallet-mode)
|
||||
|
||||
|
||||
Optional (see --with-miniupnpc and --enable-upnp-default):
|
||||
Optional:
|
||||
|
||||
sudo apt-get install libminiupnpc-dev
|
||||
|
||||
ZMQ dependencies (provides ZMQ API):
|
||||
|
||||
sudo apt-get install libzmq3-dev
|
||||
|
||||
GUI dependencies:
|
||||
|
||||
If you want to build agrarian-qt, make sure that the required packages for Qt development
|
||||
are installed. Qt 5 is necessary to build the GUI.
|
||||
To build without GUI pass `--without-gui`.
|
||||
|
||||
To build with Qt 5 you need the following:
|
||||
Qt GUI:
|
||||
|
||||
sudo apt-get install libqt5gui5 libqt5core5a libqt5dbus5 qttools5-dev qttools5-dev-tools libprotobuf-dev protobuf-compiler
|
||||
|
||||
libqrencode (optional) can be installed with:
|
||||
Disable GUI:
|
||||
|
||||
sudo apt-get install libqrencode-dev
|
||||
./configure --without-gui
|
||||
|
||||
Once these are installed, they will be found by configure and a agrarian-qt executable will be
|
||||
built by default.
|
||||
FEDORA
|
||||
|
||||
|
||||
### Fedora
|
||||
|
||||
#### Dependency Build Instructions
|
||||
|
||||
Build requirements:
|
||||
Build tools:
|
||||
|
||||
sudo dnf install which gcc-c++ libtool make autoconf automake compat-openssl10-devel libevent-devel boost-devel libdb4-devel libdb4-cxx-devel gmp-devel python3
|
||||
|
||||
@@ -137,147 +89,35 @@ Optional:
|
||||
|
||||
sudo dnf install miniupnpc-devel zeromq-devel
|
||||
|
||||
To build with Qt 5 you need the following:
|
||||
Qt:
|
||||
|
||||
sudo dnf install qt5-qttools-devel qt5-qtbase-devel protobuf-devel
|
||||
|
||||
libqrencode (optional) can be installed with:
|
||||
HARDENING
|
||||
|
||||
sudo dnf install qrencode-devel
|
||||
|
||||
Notes
|
||||
-----
|
||||
The release is built with GCC and then "strip agrariand" to strip the debug
|
||||
symbols, which reduces the executable size by about 90%.
|
||||
|
||||
|
||||
miniupnpc
|
||||
---------
|
||||
|
||||
[miniupnpc](http://miniupnp.free.fr/) may be used for UPnP port mapping. It can be downloaded from [here](
|
||||
http://miniupnp.tuxfamily.org/files/). UPnP support is compiled in and
|
||||
turned off by default. See the configure options for upnp behavior desired:
|
||||
|
||||
--without-miniupnpc No UPnP support miniupnp not required
|
||||
--disable-upnp-default (the default) UPnP support turned off by default at runtime
|
||||
--enable-upnp-default UPnP support turned on by default at runtime
|
||||
|
||||
To build:
|
||||
|
||||
tar -xzvf miniupnpc-1.6.tar.gz
|
||||
cd miniupnpc-1.6
|
||||
make
|
||||
sudo su
|
||||
make install
|
||||
|
||||
|
||||
Berkeley DB
|
||||
-----------
|
||||
It is recommended to use Berkeley DB 4.8. If you have to build it yourself,
|
||||
you can use [the installation script included in contrib/](/contrib/install_db4.sh)
|
||||
like so:
|
||||
|
||||
```shell
|
||||
./contrib/install_db4.sh `pwd`
|
||||
```
|
||||
|
||||
from the root of the repository.
|
||||
|
||||
**Note**: You only need Berkeley DB if the wallet is enabled (see [*Disable-wallet mode*](/doc/build-unix.md#disable-wallet-mode)).
|
||||
|
||||
Boost
|
||||
-----
|
||||
If you need to build Boost yourself:
|
||||
|
||||
sudo su
|
||||
./bootstrap.sh
|
||||
./bjam install
|
||||
|
||||
|
||||
Security
|
||||
--------
|
||||
To help make your Agrarian Core installation more secure by making certain attacks impossible to
|
||||
exploit even if a vulnerability is found, binaries are hardened by default.
|
||||
This can be disabled with:
|
||||
|
||||
Hardening Flags:
|
||||
Enable:
|
||||
|
||||
./configure --enable-hardening
|
||||
|
||||
Disable:
|
||||
|
||||
./configure --disable-hardening
|
||||
|
||||
|
||||
Hardening enables the following features:
|
||||
* _Position Independent Executable_: Build position independent code to take advantage of Address Space Layout Randomization
|
||||
offered by some kernels. Attackers who can cause execution of code at an arbitrary memory
|
||||
location are thwarted if they don't know where anything useful is located.
|
||||
The stack and heap are randomly located by default, but this allows the code section to be
|
||||
randomly located as well.
|
||||
|
||||
On an AMD64 processor where a library was not compiled with -fPIC, this will cause an error
|
||||
such as: "relocation R_X86_64_32 against `......' can not be used when making a shared object;"
|
||||
|
||||
To test that you have built PIE executable, install scanelf, part of paxutils, and use:
|
||||
Verify:
|
||||
|
||||
scanelf -e ./agrariand
|
||||
|
||||
The output should contain:
|
||||
|
||||
TYPE
|
||||
ET_DYN
|
||||
|
||||
* _Non-executable Stack_: If the stack is executable then trivial stack-based buffer overflow exploits are possible if
|
||||
vulnerable buffers are found. By default, Agrarian Core should be built with a non-executable stack
|
||||
but if one of the libraries it uses asks for an executable stack or someone makes a mistake
|
||||
and uses a compiler extension which requires an executable stack, it will silently build an
|
||||
executable without the non-executable stack protection.
|
||||
|
||||
To verify that the stack is non-executable after compiling use:
|
||||
`scanelf -e ./agrariand`
|
||||
|
||||
The output should contain:
|
||||
STK/REL/PTL
|
||||
RW- R-- RW-
|
||||
|
||||
The STK RW- means that the stack is readable and writeable but not executable.
|
||||
|
||||
Disable-wallet mode
|
||||
--------------------
|
||||
**Note:** This functionality is not yet completely implemented, and compilation using the below option will currently fail.
|
||||
|
||||
When the intention is to run only a P2P node without a wallet, Agrarian Core may be compiled in
|
||||
disable-wallet mode with:
|
||||
DISABLE WALLET MODE
|
||||
|
||||
./configure --disable-wallet
|
||||
|
||||
In this case there is no dependency on Berkeley DB 4.8.
|
||||
|
||||
|
||||
Additional Configure Flags
|
||||
--------------------------
|
||||
A list of additional configure flags can be displayed with:
|
||||
|
||||
./configure --help
|
||||
|
||||
|
||||
ARM Cross-compilation
|
||||
-------------------
|
||||
These steps can be performed on, for example, an Ubuntu VM. The depends system
|
||||
will also work on other Linux distributions, however the commands for
|
||||
installing the toolchain will be different.
|
||||
|
||||
Make sure you install the build requirements mentioned above.
|
||||
Then, install the toolchain and curl:
|
||||
ARM CROSS COMPILATION
|
||||
|
||||
sudo apt-get install g++-arm-linux-gnueabihf curl
|
||||
|
||||
To build executables for ARM:
|
||||
|
||||
cd depends
|
||||
make HOST=arm-linux-gnueabihf NO_QT=1
|
||||
cd ..
|
||||
./autogen.sh
|
||||
./configure --prefix=$PWD/depends/arm-linux-gnueabihf --enable-glibc-back-compat --enable-reduce-exports LDFLAGS=-static-libstdc++
|
||||
make
|
||||
|
||||
|
||||
For further documentation on the depends system see [README.md](../depends/README.md) in the depends directory.
|
||||
|
||||
+144
-97
@@ -1,151 +1,198 @@
|
||||
WINDOWS BUILD NOTES
|
||||
====================
|
||||
Copyright (c) 2026 Agrarian Developers
|
||||
|
||||
Below are some notes on how to build Agrarian Core for Windows.
|
||||
============================================================
|
||||
Agrarian Core – Windows Build Notes
|
||||
============================================================
|
||||
|
||||
The options known to work for building Agrarian Core on Windows are:
|
||||
This document describes how to build Agrarian Core for Windows.
|
||||
|
||||
* On Linux, using the [Mingw-w64](https://mingw-w64.org/doku.php) cross compiler tool chain. Ubuntu Bionic 18.04 is required
|
||||
and is the platform used to build the Agrarian Core Windows release binaries.
|
||||
* On Windows, using [Windows
|
||||
Subsystem for Linux (WSL)](https://msdn.microsoft.com/commandline/wsl/about) and the Mingw-w64 cross compiler tool chain.
|
||||
|
||||
Other options which may work, but which have not been extensively tested are (please contribute instructions):
|
||||
|
||||
* On Windows, using a POSIX compatibility layer application such as [cygwin](http://www.cygwin.com/) or [msys2](http://www.msys2.org/).
|
||||
* On Windows, using a native compiler tool chain such as [Visual Studio](https://www.visualstudio.com).
|
||||
|
||||
Installing Windows Subsystem for Linux
|
||||
---------------------------------------
|
||||
|
||||
With Windows 10, Microsoft has released a new feature named the [Windows
|
||||
Subsystem for Linux (WSL)](https://msdn.microsoft.com/commandline/wsl/about). This
|
||||
feature allows you to run a bash shell directly on Windows in an Ubuntu-based
|
||||
environment. Within this environment you can cross compile for Windows without
|
||||
the need for a separate Linux VM or server. Note that while WSL can be installed with
|
||||
other Linux variants, such as OpenSUSE, the following instructions have only been
|
||||
tested with Ubuntu.
|
||||
|
||||
This feature is not supported in versions of Windows prior to Windows 10 or on
|
||||
Windows Server SKUs. In addition, it is available [only for 64-bit versions of
|
||||
Windows](https://msdn.microsoft.com/en-us/commandline/wsl/install_guide).
|
||||
|
||||
Full instructions to install WSL are available on the above link.
|
||||
To install WSL on Windows 10 with Fall Creators Update installed (version >= 16215.0) do the following:
|
||||
|
||||
1. Enable the Windows Subsystem for Linux feature
|
||||
* Open the Windows Features dialog (`OptionalFeatures.exe`)
|
||||
* Enable 'Windows Subsystem for Linux'
|
||||
* Click 'OK' and restart if necessary
|
||||
2. Install Ubuntu
|
||||
* Open Microsoft Store and search for "Ubuntu 18.04" or use [this link](https://www.microsoft.com/store/productId/9N9TNGVNDL3Q)
|
||||
* Click Install
|
||||
3. Complete Installation
|
||||
* Open a cmd prompt and type "Ubuntu1804"
|
||||
* Create a new UNIX user account (this is a separate account from your Windows account)
|
||||
|
||||
After the bash shell is active, you can follow the instructions below, starting
|
||||
with the "Cross-compilation" section. Compiling the 64-bit version is
|
||||
recommended, but it is possible to compile the 32-bit version.
|
||||
|
||||
Cross-compilation for Ubuntu and Windows Subsystem for Linux
|
||||
------------------------------------------------------------
|
||||
SUPPORTED BUILD METHODS
|
||||
------------------------------------------------------------
|
||||
|
||||
The steps below can be performed on Ubuntu (including in a VM) or WSL. The depends system
|
||||
will also work on other Linux distributions, however the commands for
|
||||
installing the toolchain will be different.
|
||||
The following methods are known to work:
|
||||
|
||||
First, install the general dependencies:
|
||||
1. Linux (Ubuntu 18.04 Bionic recommended)
|
||||
Using the Mingw-w64 cross-compilation toolchain.
|
||||
This is the method used to produce official Windows release binaries.
|
||||
|
||||
2. Windows 10+
|
||||
Using Windows Subsystem for Linux (WSL) with Mingw-w64.
|
||||
|
||||
------------------------------------------------------------
|
||||
UNTESTED / PARTIALLY TESTED OPTIONS
|
||||
------------------------------------------------------------
|
||||
|
||||
The following may work but are not officially supported:
|
||||
|
||||
• Cygwin
|
||||
• MSYS2
|
||||
• Native Visual Studio toolchain
|
||||
|
||||
Contributions for these methods are welcome.
|
||||
|
||||
============================================================
|
||||
WINDOWS SUBSYSTEM FOR LINUX (WSL)
|
||||
============================================================
|
||||
|
||||
WSL allows running a Linux environment directly on Windows without a VM.
|
||||
|
||||
Requirements:
|
||||
• Windows 10 (64-bit only)
|
||||
• Not supported on Windows Server
|
||||
• Ubuntu recommended (tested on Ubuntu 18.04)
|
||||
|
||||
------------------------------------------------------------
|
||||
INSTALLING WSL
|
||||
------------------------------------------------------------
|
||||
|
||||
1. Enable WSL
|
||||
- Run: OptionalFeatures.exe
|
||||
- Enable "Windows Subsystem for Linux"
|
||||
- Restart if prompted
|
||||
|
||||
2. Install Ubuntu
|
||||
- Open Microsoft Store
|
||||
- Install "Ubuntu 18.04"
|
||||
|
||||
3. Complete Setup
|
||||
- Open command prompt
|
||||
- Run: Ubuntu1804
|
||||
- Create a UNIX user account
|
||||
|
||||
Once WSL is active, continue with cross-compilation instructions below.
|
||||
|
||||
============================================================
|
||||
CROSS-COMPILATION (Ubuntu or WSL)
|
||||
============================================================
|
||||
|
||||
The steps below work on:
|
||||
• Native Ubuntu
|
||||
• Ubuntu VM
|
||||
• WSL
|
||||
|
||||
------------------------------------------------------------
|
||||
GENERAL DEPENDENCIES
|
||||
------------------------------------------------------------
|
||||
|
||||
sudo apt update
|
||||
sudo apt upgrade
|
||||
sudo apt install build-essential libtool autotools-dev automake pkg-config bsdmainutils curl git
|
||||
sudo apt install build-essential libtool autotools-dev \
|
||||
automake pkg-config bsdmainutils curl git
|
||||
|
||||
A host toolchain (`build-essential`) is necessary because some dependency
|
||||
packages (such as `protobuf`) need to build host utilities that are used in the
|
||||
build process.
|
||||
A host toolchain (build-essential) is required because some dependencies
|
||||
(e.g., protobuf) build host utilities during the process.
|
||||
|
||||
See [dependencies.md](dependencies.md) for a complete overview.
|
||||
|
||||
If you want to build the windows installer with `make deploy` you need [NSIS](https://nsis.sourceforge.io/Main_Page):
|
||||
If building the Windows installer (`make deploy`):
|
||||
|
||||
sudo apt install nsis
|
||||
|
||||
Acquire the source in the usual way:
|
||||
------------------------------------------------------------
|
||||
SOURCE CODE
|
||||
------------------------------------------------------------
|
||||
|
||||
git clone https://github.com/agrarian-project/agrarian.git
|
||||
cd agrarian
|
||||
|
||||
## Building for 64-bit Windows
|
||||
============================================================
|
||||
BUILDING FOR 64-BIT WINDOWS
|
||||
============================================================
|
||||
|
||||
The first step is to install the mingw-w64 cross-compilation tool chain:
|
||||
Install Mingw-w64 toolchain:
|
||||
|
||||
sudo apt install g++-mingw-w64-x86-64
|
||||
|
||||
Ubuntu Bionic 18.04 <sup>[1](#footnote1)</sup>:
|
||||
Ubuntu 18.04:
|
||||
|
||||
sudo update-alternatives --config x86_64-w64-mingw32-g++ # Set the default mingw32 g++ compiler option to posix.
|
||||
sudo update-alternatives --config x86_64-w64-mingw32-g++
|
||||
|
||||
Once the toolchain is installed the build steps are common:
|
||||
Select the POSIX thread model (required).
|
||||
|
||||
Note that for WSL the Agrarian Core source path MUST be somewhere in the default mount file system, for
|
||||
example /usr/src/agrarian, AND not under /mnt/d/. If this is not the case the dependency autoconf scripts will fail.
|
||||
This means you cannot use a directory that is located directly on the host Windows file system to perform the build.
|
||||
------------------------------------------------------------
|
||||
IMPORTANT (WSL USERS)
|
||||
------------------------------------------------------------
|
||||
|
||||
Build using:
|
||||
The source directory MUST reside inside the Linux filesystem
|
||||
(e.g., /usr/src/agrarian).
|
||||
|
||||
PATH=$(echo "$PATH" | sed -e 's/:\/mnt.*//g') # strip out problematic Windows %PATH% imported var
|
||||
DO NOT build from /mnt/c or any mounted Windows path.
|
||||
Autoconf scripts will fail.
|
||||
|
||||
------------------------------------------------------------
|
||||
BUILD COMMANDS
|
||||
------------------------------------------------------------
|
||||
|
||||
PATH=$(echo "$PATH" | sed -e 's/:\/mnt.*//g')
|
||||
cd depends
|
||||
make HOST=x86_64-w64-mingw32
|
||||
cd ..
|
||||
./autogen.sh # not required when building from tarball
|
||||
CONFIG_SITE=$PWD/depends/x86_64-w64-mingw32/share/config.site ./configure --prefix=/
|
||||
./autogen.sh
|
||||
CONFIG_SITE=$PWD/depends/x86_64-w64-mingw32/share/config.site \
|
||||
./configure --prefix=/
|
||||
make
|
||||
|
||||
## Building for 32-bit Windows
|
||||
============================================================
|
||||
BUILDING FOR 32-BIT WINDOWS
|
||||
============================================================
|
||||
|
||||
To build executables for Windows 32-bit, install the following dependencies:
|
||||
Install toolchain:
|
||||
|
||||
sudo apt install g++-mingw-w64-i686 mingw-w64-i686-dev
|
||||
|
||||
Ubuntu Bionic 18.04 <sup>[1](#footnote1)</sup>:
|
||||
Ubuntu 18.04:
|
||||
|
||||
sudo update-alternatives --config i686-w64-mingw32-g++ # Set the default mingw32 g++ compiler option to posix.
|
||||
sudo update-alternatives --config i686-w64-mingw32-g++
|
||||
|
||||
Build using:
|
||||
Select the POSIX thread model.
|
||||
|
||||
PATH=$(echo "$PATH" | sed -e 's/:\/mnt.*//g') # strip out problematic Windows %PATH% imported var
|
||||
------------------------------------------------------------
|
||||
BUILD COMMANDS
|
||||
------------------------------------------------------------
|
||||
|
||||
PATH=$(echo "$PATH" | sed -e 's/:\/mnt.*//g')
|
||||
cd depends
|
||||
make HOST=i686-w64-mingw32
|
||||
cd ..
|
||||
./autogen.sh # not required when building from tarball
|
||||
CONFIG_SITE=$PWD/depends/i686-w64-mingw32/share/config.site ./configure --prefix=/
|
||||
./autogen.sh
|
||||
CONFIG_SITE=$PWD/depends/i686-w64-mingw32/share/config.site \
|
||||
./configure --prefix=/
|
||||
make
|
||||
|
||||
## Depends system
|
||||
============================================================
|
||||
DEPENDS SYSTEM
|
||||
============================================================
|
||||
|
||||
For further documentation on the depends system see [README.md](../depends/README.md) in the depends directory.
|
||||
For additional documentation, see:
|
||||
|
||||
Installation
|
||||
-------------
|
||||
depends/README.md
|
||||
|
||||
After building using the Windows subsystem it can be useful to copy the compiled
|
||||
executables to a directory on the Windows drive in the same directory structure
|
||||
as they appear in the release `.zip` archive. This can be done in the following
|
||||
way. This will install to `c:\workspace\agrarian`, for example:
|
||||
============================================================
|
||||
INSTALLATION
|
||||
============================================================
|
||||
|
||||
To install into a Windows-accessible directory:
|
||||
|
||||
make install DESTDIR=/mnt/c/workspace/agrarian
|
||||
|
||||
You can also create an installer using:
|
||||
To build a Windows installer:
|
||||
|
||||
make deploy
|
||||
|
||||
Footnotes
|
||||
---------
|
||||
============================================================
|
||||
THREAD MODEL NOTE
|
||||
============================================================
|
||||
|
||||
<a name="footnote1">1</a>: Starting from Ubuntu Xenial 16.04, both the 32 and 64 bit Mingw-w64 packages install two different
|
||||
compiler options to allow a choice between either posix or win32 threads. The default option is win32 threads which is the more
|
||||
efficient since it will result in binary code that links directly with the Windows kernel32.lib. Unfortunately, the headers
|
||||
required to support win32 threads conflict with some of the classes in the C++11 standard library, in particular std::mutex.
|
||||
It's not possible to build the Agrarian Core code using the win32 version of the Mingw-w64 cross compilers (at least not without
|
||||
modifying headers in the Agrarian Core source code).
|
||||
Ubuntu Mingw-w64 packages include two thread models:
|
||||
|
||||
• win32 (default)
|
||||
• posix
|
||||
|
||||
The win32 model conflicts with certain C++11 headers
|
||||
(e.g., std::mutex) used by Agrarian Core.
|
||||
|
||||
You MUST select the POSIX thread model when prompted by
|
||||
update-alternatives.
|
||||
|
||||
============================================================
|
||||
END OF DOCUMENT
|
||||
============================================================
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
// Copyright (c) 2026 Agrarian Developers
|
||||
#include <windows.h> // needed for VERSIONINFO
|
||||
#include "clientversion.h" // holds the needed client version information
|
||||
|
||||
|
||||
+9
-12
@@ -2,6 +2,7 @@
|
||||
// Copyright (c) 2009-2015 The Bitcoin developers
|
||||
// Copyright (c) 2009-2015 The Dash developers
|
||||
// Copyright (c) 2015-2018 The PIVX developers
|
||||
// Copyright (c) 2026 Agrarian Developers
|
||||
// Distributed under the MIT/X11 software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
@@ -23,9 +24,6 @@
|
||||
#include <univalue.h>
|
||||
|
||||
#define _(x) std::string(x) /* Keep the _() around in case gettext or such will be used later to translate non-UI */
|
||||
|
||||
using namespace std;
|
||||
|
||||
static const int DEFAULT_HTTP_CLIENT_TIMEOUT=900;
|
||||
|
||||
std::string HelpMessageCli()
|
||||
@@ -120,9 +118,8 @@ static void http_request_done(struct evhttp_request *req, void *ctx)
|
||||
{
|
||||
HTTPReply* reply = static_cast<HTTPReply*>(ctx);
|
||||
|
||||
if (req == NULL) {
|
||||
/* If req is NULL, it means an error occurred while connecting, but
|
||||
* I'm not sure how to find out which one. We also don't really care.
|
||||
if (req == nullptr) {
|
||||
/* If req is nullptr, it means an error occurred while connecting, but* I'm not sure how to find out which one. We also don't really care.
|
||||
*/
|
||||
reply->status = 0;
|
||||
return;
|
||||
@@ -152,14 +149,14 @@ UniValue CallRPC(const string& strMethod, const UniValue& params)
|
||||
throw runtime_error("cannot create event_base");
|
||||
|
||||
// Synchronously look up hostname
|
||||
struct evhttp_connection *evcon = evhttp_connection_base_new(base, NULL, host.c_str(), port); // TODO RAII
|
||||
if (evcon == NULL)
|
||||
struct evhttp_connection* evcon = evhttp_connection_base_new(base, nullptr, host.c_str(), port); // TODO RAII
|
||||
if (evcon == nullptr)
|
||||
throw runtime_error("create connection failed");
|
||||
evhttp_connection_set_timeout(evcon, GetArg("-rpcclienttimeout", DEFAULT_HTTP_CLIENT_TIMEOUT));
|
||||
|
||||
HTTPReply response;
|
||||
struct evhttp_request* req = evhttp_request_new(http_request_done, (void*)&response); // TODO RAII
|
||||
if (req == NULL)
|
||||
if (req == nullptr)
|
||||
throw runtime_error("create http request failed");
|
||||
|
||||
// Get credentials
|
||||
@@ -280,7 +277,7 @@ int CommandLineRPC(int argc, char* argv[])
|
||||
strPrint = string("error: ") + e.what();
|
||||
nRet = EXIT_FAILURE;
|
||||
} catch (...) {
|
||||
PrintExceptionContinue(NULL, "CommandLineRPC()");
|
||||
PrintExceptionContinue(nullptr, "CommandLineRPC()");
|
||||
throw;
|
||||
}
|
||||
|
||||
@@ -305,7 +302,7 @@ int main(int argc, char* argv[])
|
||||
PrintExceptionContinue(&e, "AppInitRPC()");
|
||||
return EXIT_FAILURE;
|
||||
} catch (...) {
|
||||
PrintExceptionContinue(NULL, "AppInitRPC()");
|
||||
PrintExceptionContinue(nullptr, "AppInitRPC()");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
@@ -315,7 +312,7 @@ int main(int argc, char* argv[])
|
||||
} catch (std::exception& e) {
|
||||
PrintExceptionContinue(&e, "CommandLineRPC()");
|
||||
} catch (...) {
|
||||
PrintExceptionContinue(NULL, "CommandLineRPC()");
|
||||
PrintExceptionContinue(nullptr, "CommandLineRPC()");
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
// Copyright (c) 2026 Agrarian Developers
|
||||
|
||||
#include <windows.h> // needed for VERSIONINFO
|
||||
#include "clientversion.h" // holds the needed client version information
|
||||
|
||||
|
||||
+4
-5
@@ -1,5 +1,6 @@
|
||||
// Copyright (c) 2009-2014 The Bitcoin developers
|
||||
// Copyright (c) 2015-2019 The PIVX developers
|
||||
// Copyright (c) 2026 Agrarian Developers
|
||||
// Distributed under the MIT/X11 software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
@@ -24,8 +25,6 @@
|
||||
#include <boost/assign/list_of.hpp>
|
||||
|
||||
using namespace boost::assign;
|
||||
using namespace std;
|
||||
|
||||
static bool fCreateBlank;
|
||||
static map<string, UniValue> registers;
|
||||
CClientUIInterface uiInterface;
|
||||
@@ -605,7 +604,7 @@ static int CommandLineRawTx(int argc, char* argv[])
|
||||
strPrint = string("error: ") + e.what();
|
||||
nRet = EXIT_FAILURE;
|
||||
} catch (...) {
|
||||
PrintExceptionContinue(NULL, "CommandLineRawTx()");
|
||||
PrintExceptionContinue(nullptr, "CommandLineRawTx()");
|
||||
throw;
|
||||
}
|
||||
|
||||
@@ -626,7 +625,7 @@ int main(int argc, char* argv[])
|
||||
PrintExceptionContinue(&e, "AppInitRawTx()");
|
||||
return EXIT_FAILURE;
|
||||
} catch (...) {
|
||||
PrintExceptionContinue(NULL, "AppInitRawTx()");
|
||||
PrintExceptionContinue(nullptr, "AppInitRawTx()");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
@@ -636,7 +635,7 @@ int main(int argc, char* argv[])
|
||||
} catch (std::exception& e) {
|
||||
PrintExceptionContinue(&e, "CommandLineRawTx()");
|
||||
} catch (...) {
|
||||
PrintExceptionContinue(NULL, "CommandLineRawTx()");
|
||||
PrintExceptionContinue(nullptr, "CommandLineRawTx()");
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
// Copyright (c) 2026 Agrarian Developers
|
||||
|
||||
#include <windows.h> // needed for VERSIONINFO
|
||||
#include "clientversion.h" // holds the needed client version information
|
||||
|
||||
|
||||
+4
-5
@@ -2,6 +2,7 @@
|
||||
// Copyright (c) 2009-2014 The Bitcoin developers
|
||||
// Copyright (c) 2014-2015 The Dash developers
|
||||
// Copyright (c) 2015-2019 The PIVX developers
|
||||
// Copyright (c) 2026 Agrarian Developers
|
||||
// Distributed under the MIT/X11 software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
@@ -29,13 +30,11 @@
|
||||
* \section intro_sec Introduction
|
||||
*
|
||||
* This is the developer documentation of the reference client for an experimental new digital currency called Agrarian (http://www.agrarian.org),
|
||||
* which enables instant payments to anyone, anywhere in the world. Agrarian uses peer-to-peer technology to operate
|
||||
* with no central authority: managing transactions and issuing money are carried out collectively by the network.
|
||||
* which enables instant payments to anyone, anywhere in the world. Agrarian uses peer-to-peer technology to operate* with no central authority: managing transactions and issuing money are carried out collectively by the network.
|
||||
*
|
||||
* The software is a community-driven open source project, released under the MIT license.
|
||||
*
|
||||
* \section Navigation
|
||||
* Use the buttons <code>Namespaces</code>, <code>Classes</code> or <code>Files</code> at the top of the page to start navigating the code.
|
||||
* \section Navigation* Use the buttons <code>Namespaces</code>, <code>Classes</code> or <code>Files</code> at the top of the page to start navigating the code.
|
||||
*/
|
||||
|
||||
static bool fDaemon;
|
||||
@@ -144,7 +143,7 @@ bool AppInit(int argc, char* argv[])
|
||||
} catch (std::exception& e) {
|
||||
PrintExceptionContinue(&e, "AppInit()");
|
||||
} catch (...) {
|
||||
PrintExceptionContinue(NULL, "AppInit()");
|
||||
PrintExceptionContinue(nullptr, "AppInit()");
|
||||
}
|
||||
|
||||
if (!fRet) {
|
||||
|
||||
+41
-13
@@ -2,11 +2,14 @@
|
||||
// Copyright (c) 2009-2014 The Bitcoin developers
|
||||
// Copyright (c) 2014-2015 The Dash developers
|
||||
// Copyright (c) 2015-2019 The PIVX developers
|
||||
// Copyright (c) 2026 Agrarian Developers
|
||||
// Distributed under the MIT software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
#include "libzerocoin/Params.h"
|
||||
|
||||
#include "chainparams.h"
|
||||
#include "chainparamsseeds.h"
|
||||
#include "random.h"
|
||||
#include "util.h"
|
||||
#include "utilstrencodings.h"
|
||||
@@ -23,8 +26,6 @@ struct SeedSpec6 {
|
||||
uint16_t port;
|
||||
};
|
||||
|
||||
#include "chainparamsseeds.h"
|
||||
|
||||
/**
|
||||
* Main network
|
||||
*/
|
||||
@@ -69,7 +70,8 @@ static const Checkpoints::CCheckpointData dataTestnet = {
|
||||
&mapCheckpointsTestnet,
|
||||
1643790201,
|
||||
0,
|
||||
0};
|
||||
0
|
||||
};
|
||||
|
||||
static Checkpoints::MapCheckpoints mapCheckpointsRegtest =
|
||||
boost::assign::map_list_of(0, uint256("0x001"));
|
||||
@@ -77,24 +79,24 @@ static const Checkpoints::CCheckpointData dataRegtest = {
|
||||
&mapCheckpointsRegtest,
|
||||
1643790201,
|
||||
0,
|
||||
0};
|
||||
0
|
||||
};
|
||||
|
||||
libzerocoin::ZerocoinParams* CChainParams::Zerocoin_Params(bool useModulusV1) const
|
||||
{
|
||||
assert(this);
|
||||
|
||||
static CBigNum bnHexModulus = 0;
|
||||
if (!bnHexModulus)
|
||||
bnHexModulus.SetHex(zerocoinModulus);
|
||||
static libzerocoin::ZerocoinParams ZCParamsHex = libzerocoin::ZerocoinParams(bnHexModulus);
|
||||
|
||||
static CBigNum bnDecModulus = 0;
|
||||
if (!bnDecModulus)
|
||||
bnDecModulus.SetDec(zerocoinModulus);
|
||||
static libzerocoin::ZerocoinParams ZCParamsDec = libzerocoin::ZerocoinParams(bnDecModulus);
|
||||
|
||||
if (useModulusV1)
|
||||
return &ZCParamsHex;
|
||||
|
||||
return &ZCParamsDec;
|
||||
return useModulusV1 ? &ZCParamsHex : &ZCParamsDec;
|
||||
}
|
||||
|
||||
class CMainParams : public CChainParams
|
||||
@@ -130,7 +132,14 @@ public:
|
||||
|
||||
/** Height or Time Based Activations **/
|
||||
nLastPOWBlock = 100;
|
||||
nModifierUpdateBlock = 2; //The block at which PoS rules activate
|
||||
|
||||
// Hybrid consensus: PoW mining and PoS staking are both permitted beginning at block 2.
|
||||
// PoW remains permitted until nLastPOWBlock.
|
||||
nFirstPoSBlock = 2;
|
||||
|
||||
// PIVX-style modifier upgrade: keep aligned with PoS activation.
|
||||
nModifierUpdateBlock = 2;
|
||||
|
||||
nZerocoinStartHeight = 0;
|
||||
nZerocoinStartTime = 1643790201;
|
||||
nBlockEnforceSerialRange = 1; // Enforce serial range starting this block
|
||||
@@ -165,7 +174,9 @@ public:
|
||||
CMutableTransaction txNew;
|
||||
txNew.vin.resize(1);
|
||||
txNew.vout.resize(1);
|
||||
txNew.vin[0].scriptSig = CScript() << 486604799 << CScriptNum(4) << vector<unsigned char>((const unsigned char*)pszTimestamp, (const unsigned char*)pszTimestamp + strlen(pszTimestamp));
|
||||
txNew.vin[0].scriptSig = CScript() << 486604799 << CScriptNum(4)
|
||||
<< vector<unsigned char>((const unsigned char*)pszTimestamp,
|
||||
(const unsigned char*)pszTimestamp + strlen(pszTimestamp));
|
||||
txNew.vout[0].nValue = 50 * COIN;
|
||||
txNew.vout[0].scriptPubKey = CScript() << ParseHex("04fe3d7e5608ebba6d822948eff929c822ad35b5f8ecd00977d0e59ed67da697bd88e0ed8bd58797bde6fe6750236f5dae4cf403af0925c8339f0a91b682254b39") << OP_CHECKSIG;
|
||||
genesis.vtx.push_back(txNew);
|
||||
@@ -258,10 +269,18 @@ public:
|
||||
nMinerThreads = 0;
|
||||
nTargetTimespan = 10 * 60;
|
||||
nTargetSpacing = 10 * 60;
|
||||
|
||||
nLastPOWBlock = 200;
|
||||
|
||||
// Hybrid consensus: PoS staking permitted from block 2 in testnet as well.
|
||||
nFirstPoSBlock = 2;
|
||||
|
||||
nMaturity = 15;
|
||||
nMasternodeCountDrift = 4;
|
||||
nModifierUpdateBlock = 0;
|
||||
|
||||
// Keep aligned with PoS activation in this chain.
|
||||
nModifierUpdateBlock = 2;
|
||||
|
||||
nMaxMoneyOut = 43199500 * COIN;
|
||||
nZerocoinStartHeight = 0;
|
||||
nZerocoinStartTime = 1643790201;
|
||||
@@ -322,6 +341,7 @@ public:
|
||||
|
||||
nProposalEstablishmentTime = 60 * 5; // Proposals must be at least 5 mns old to make it into a test budget
|
||||
}
|
||||
|
||||
const Checkpoints::CCheckpointData& Checkpoints() const
|
||||
{
|
||||
return dataTestnet;
|
||||
@@ -352,10 +372,18 @@ public:
|
||||
nTargetTimespan = 24 * 60 * 60; // Agrarian: 1 day
|
||||
nTargetSpacing = 1 * 60; // Agrarian: 1 minutes
|
||||
bnProofOfWorkLimit = ~uint256(0) >> 1;
|
||||
|
||||
nLastPOWBlock = 250;
|
||||
|
||||
// Hybrid consensus: PoS staking permitted from block 2 in regtest as well.
|
||||
nFirstPoSBlock = 2;
|
||||
|
||||
nMaturity = 20;
|
||||
nMasternodeCountDrift = 4;
|
||||
nModifierUpdateBlock = 0; //approx Mon, 17 Apr 2017 04:00:00 GMT
|
||||
|
||||
// Keep aligned with PoS activation in this chain.
|
||||
nModifierUpdateBlock = 2;
|
||||
|
||||
nMaxMoneyOut = 43199500 * COIN;
|
||||
nZerocoinStartHeight = 300;
|
||||
nBlockZerocoinV2 = 300;
|
||||
@@ -390,6 +418,7 @@ public:
|
||||
fSkipProofOfWorkCheck = true;
|
||||
fTestnetToBeDeprecatedFieldRPC = false;
|
||||
}
|
||||
|
||||
const Checkpoints::CCheckpointData& Checkpoints() const
|
||||
{
|
||||
return dataRegtest;
|
||||
@@ -434,7 +463,6 @@ public:
|
||||
};
|
||||
static CUnitTestParams unitTestParams;
|
||||
|
||||
|
||||
static CChainParams* pCurrentParams = 0;
|
||||
|
||||
CModifiableParams* ModifiableParams()
|
||||
|
||||
+14
-4
@@ -2,6 +2,7 @@
|
||||
// Copyright (c) 2009-2014 The Bitcoin developers
|
||||
// Copyright (c) 2014-2015 The Dash developers
|
||||
// Copyright (c) 2015-2019 The PIVX developers
|
||||
// Copyright (c) 2026 Agrarian Developers
|
||||
// Distributed under the MIT software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
@@ -15,6 +16,7 @@
|
||||
#include "uint256.h"
|
||||
|
||||
#include "libzerocoin/Params.h"
|
||||
|
||||
#include <vector>
|
||||
|
||||
typedef unsigned char MessageStartChars[MESSAGE_START_SIZE];
|
||||
@@ -63,7 +65,7 @@ public:
|
||||
/** Make miner wait to have peers to avoid wasting work */
|
||||
bool MiningRequiresPeers() const { return fMiningRequiresPeers; }
|
||||
/** Headers first syncing is disabled */
|
||||
bool HeadersFirstSyncingActive() const { return fHeadersFirstSyncingActive; };
|
||||
bool HeadersFirstSyncingActive() const { return fHeadersFirstSyncingActive; }
|
||||
/** Default value for -checkmempool and -checkblockindex argument */
|
||||
bool DefaultConsistencyChecks() const { return fDefaultConsistencyChecks; }
|
||||
/** Allow mining of a min-difficulty block */
|
||||
@@ -119,7 +121,13 @@ public:
|
||||
|
||||
/** Height or Time Based Activations **/
|
||||
int ModifierUpgradeBlock() const { return nModifierUpdateBlock; }
|
||||
|
||||
// Hybrid consensus activations.
|
||||
// - PoS blocks are permitted starting at FIRST_POS_BLOCK().
|
||||
// - PoW blocks are permitted up to and including LAST_POW_BLOCK().
|
||||
int FIRST_POS_BLOCK() const { return nFirstPoSBlock; }
|
||||
int LAST_POW_BLOCK() const { return nLastPOWBlock; }
|
||||
|
||||
int Zerocoin_StartHeight() const { return nZerocoinStartHeight; }
|
||||
int Zerocoin_Block_EnforceSerialRange() const { return nBlockEnforceSerialRange; }
|
||||
int Zerocoin_Block_RecalculateAccumulators() const { return nBlockRecalculateAccumulators; }
|
||||
@@ -134,7 +142,7 @@ public:
|
||||
CAmount GetSupplyBeforeFakeSerial() const { return nSupplyBeforeFakeSerial; }
|
||||
|
||||
int Zerocoin_Block_Double_Accumulated() const { return nBlockDoubleAccumulated; }
|
||||
CAmount InvalidAmountFiltered() const { return nInvalidAmountFiltered; };
|
||||
CAmount InvalidAmountFiltered() const { return nInvalidAmountFiltered; }
|
||||
|
||||
int Zerocoin_Block_Public_Spend_Enabled() const { return nPublicZCSpends; }
|
||||
|
||||
@@ -154,7 +162,11 @@ protected:
|
||||
int nToCheckBlockUpgradeMajority;
|
||||
int64_t nTargetTimespan;
|
||||
int64_t nTargetSpacing;
|
||||
|
||||
// Hybrid PoW/PoS window controls.
|
||||
int nFirstPoSBlock;
|
||||
int nLastPOWBlock;
|
||||
|
||||
int nMasternodeCountDrift;
|
||||
int nMaturity;
|
||||
int nModifierUpdateBlock;
|
||||
@@ -216,7 +228,6 @@ protected:
|
||||
* to test specific features more easily. Test cases should always restore the previous
|
||||
* values after finalization.
|
||||
*/
|
||||
|
||||
class CModifiableParams
|
||||
{
|
||||
public:
|
||||
@@ -230,7 +241,6 @@ public:
|
||||
virtual void setSkipProofOfWorkCheck(bool aSkipProofOfWorkCheck) = 0;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Return the currently selected parameters. This won't change after app startup
|
||||
* outside of the unit tests.
|
||||
|
||||
+1
-3
@@ -1,5 +1,6 @@
|
||||
// Copyright (c) 2012-2013 The PPCoin developers
|
||||
// Copyright (c) 2015-2019 The PIVX developers
|
||||
// Copyright (c) 2026 Agrarian Developers
|
||||
// Distributed under the MIT/X11 software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
@@ -13,9 +14,6 @@
|
||||
#include "stakeinput.h"
|
||||
#include "utilmoneystr.h"
|
||||
#include "zagrchain.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
bool fTestNet = false; // Params().NetworkID() == CBaseChainParams::TESTNET;
|
||||
|
||||
// Modifier interval: time to elapse before new modifier is computed
|
||||
|
||||
+7
-5
@@ -1,13 +1,15 @@
|
||||
// Copyright (c) 2012-2013 The PPCoin developers
|
||||
// Copyright (c) 2015-2019 The PIVX developers
|
||||
// Copyright (c) 2026 Agrarian Developers
|
||||
// Distributed under the MIT/X11 software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
#ifndef BITCOIN_KERNEL_H
|
||||
#define BITCOIN_KERNEL_H
|
||||
|
||||
#ifndef AGRARIAN_BITCOIN_KERNEL_H
|
||||
#define AGRARIAN_BITCOIN_KERNEL_H
|
||||
#include "main.h"
|
||||
#include "stakeinput.h"
|
||||
#include <cstdint>
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
|
||||
|
||||
// MODIFIER_INTERVAL: time to elapse before new modifier is computed
|
||||
@@ -46,4 +48,4 @@ int64_t GetWeight(int64_t nIntervalBeginning, int64_t nIntervalEnd);
|
||||
|
||||
bool ContextualCheckZerocoinStake(int nPreviousBlockHeight, CStakeInput* stake);
|
||||
|
||||
#endif // BITCOIN_KERNEL_H
|
||||
#endif // AGRARIAN_BITCOIN_KERNEL_H
|
||||
|
||||
+37
-16
@@ -2,6 +2,7 @@
|
||||
// Copyright (c) 2009-2014 The Bitcoin developers
|
||||
// Copyright (c) 2014-2015 The Dash developers
|
||||
// Copyright (c) 2015-2019 The PIVX developers
|
||||
// Copyright (c) 2026 The Agrarian developers
|
||||
// Distributed under the MIT software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
@@ -1986,22 +1987,40 @@ double ConvertBitsToDouble(unsigned int nBits)
|
||||
return dDiff;
|
||||
}
|
||||
|
||||
int64_t GetBlockValue(int nHeight, bool fProofOfStake)
|
||||
{
|
||||
// NOTE:
|
||||
// - Height 0 is genesis and uses the special, pre-mined value.
|
||||
// - During the hybrid window, both PoW and PoS blocks may be created.
|
||||
// Subsidy policy is therefore selected by block type, not by height alone.
|
||||
//
|
||||
// Current Agrarian policy:
|
||||
// * PoW blocks (height > 0 && height <= LAST_POW_BLOCK): 50 AGR
|
||||
// * PoS blocks (height >= FIRST_POS_BLOCK): 10 AGR
|
||||
// * PoW blocks are not valid beyond LAST_POW_BLOCK (enforced elsewhere).
|
||||
if (nHeight == 0) {
|
||||
return 5000000000 * COIN;
|
||||
}
|
||||
|
||||
if (fProofOfStake) {
|
||||
return 10 * COIN;
|
||||
}
|
||||
|
||||
if (nHeight > 0 && nHeight <= Params().LAST_POW_BLOCK()) {
|
||||
return 50 * COIN;
|
||||
}
|
||||
|
||||
// Should not be reachable for valid blocks (PoW is disallowed beyond LAST_POW_BLOCK).
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Backward-compatible wrapper for call sites that only know height.
|
||||
// Prefer GetBlockValue(height, isPoS) when block type is available.
|
||||
int64_t GetBlockValue(int nHeight)
|
||||
{
|
||||
int64_t nSubsidy = 0;
|
||||
|
||||
if (nHeight == 0) {
|
||||
nSubsidy = 5000000000 * COIN;
|
||||
}
|
||||
else if (nHeight <= Params().LAST_POW_BLOCK() && nHeight > 0) {
|
||||
nSubsidy = 50 * COIN;
|
||||
}
|
||||
else if (nHeight > Params().LAST_POW_BLOCK()) {
|
||||
nSubsidy = 10 * COIN;
|
||||
return GetBlockValue(nHeight, false);
|
||||
}
|
||||
|
||||
return nSubsidy;
|
||||
}
|
||||
|
||||
CAmount GetSeeSaw(const CAmount& blockValue, int nMasternodeCount, int nHeight)
|
||||
{
|
||||
@@ -2911,14 +2930,16 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin
|
||||
return true;
|
||||
}
|
||||
|
||||
if (pindex->nHeight <= Params().LAST_POW_BLOCK() && block.IsProofOfStake())
|
||||
// Hybrid consensus:
|
||||
// - PoS blocks are permitted starting at Params().FIRST_POS_BLOCK().
|
||||
// - PoW blocks are permitted up to and including Params().LAST_POW_BLOCK().
|
||||
if (block.IsProofOfStake() && pindex->nHeight < Params().FIRST_POS_BLOCK())
|
||||
return state.DoS(100, error("ConnectBlock() : PoS period not active"),
|
||||
REJECT_INVALID, "PoS-early");
|
||||
|
||||
if (pindex->nHeight > Params().LAST_POW_BLOCK() && block.IsProofOfWork())
|
||||
if (block.IsProofOfWork() && pindex->nHeight > Params().LAST_POW_BLOCK())
|
||||
return state.DoS(100, error("ConnectBlock() : PoW period ended"),
|
||||
REJECT_INVALID, "PoW-ended");
|
||||
|
||||
bool fScriptChecks = pindex->nHeight >= Checkpoints::GetTotalBlocksEstimate();
|
||||
|
||||
// If scripts won't be checked anyways, don't bother seeing if CLTV is activated
|
||||
@@ -3132,7 +3153,7 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin
|
||||
LogPrint("bench", " - Connect %u transactions: %.2fms (%.3fms/tx, %.3fms/txin) [%.2fs]\n", (unsigned)block.vtx.size(), 0.001 * (nTime1 - nTimeStart), 0.001 * (nTime1 - nTimeStart) / block.vtx.size(), nInputs <= 1 ? 0 : 0.001 * (nTime1 - nTimeStart) / (nInputs - 1), nTimeConnect * 0.000001);
|
||||
|
||||
//PoW phase redistributed fees to miner. PoS stage destroys fees.
|
||||
CAmount nExpectedMint = GetBlockValue(pindex->pprev->nHeight);
|
||||
CAmount nExpectedMint = GetBlockValue(pindex->nHeight, block.IsProofOfStake());
|
||||
if (block.IsProofOfWork())
|
||||
nExpectedMint += nFees;
|
||||
|
||||
|
||||
+35
-57
@@ -2,6 +2,7 @@
|
||||
// Copyright (c) 2009-2014 The Bitcoin developers
|
||||
// Copyright (c) 2014-2015 The Dash developers
|
||||
// Copyright (c) 2015-2019 The PIVX developers
|
||||
// Copyright (c) 2026 Agrarian Developers
|
||||
// Distributed under the MIT software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
@@ -20,8 +21,6 @@
|
||||
#include "pow.h"
|
||||
#include "primitives/block.h"
|
||||
#include "primitives/transaction.h"
|
||||
#include "zagr/zerocoin.h"
|
||||
#include "zagr/zagrmodule.h"
|
||||
#include "script/script.h"
|
||||
#include "script/sigcache.h"
|
||||
#include "script/standard.h"
|
||||
@@ -30,6 +29,8 @@
|
||||
#include "txmempool.h"
|
||||
#include "uint256.h"
|
||||
#include "undo.h"
|
||||
#include "zagr/zerocoin.h"
|
||||
#include "zagr/zagrmodule.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <exception>
|
||||
@@ -241,11 +242,16 @@ std::string GetWarnings(std::string strFor);
|
||||
bool GetTransaction(const uint256& hash, CTransaction& tx, uint256& hashBlock, bool fAllowSlow = false, CBlockIndex* blockIndex = nullptr);
|
||||
/** Retrieve an output (from memory pool, or from disk, if possible) */
|
||||
bool GetOutput(const uint256& hash, unsigned int index, CValidationState& state, CTxOut& out);
|
||||
/** Find the best known block, and make it the tip of the block chain */
|
||||
|
||||
// ***TODO***
|
||||
/** TODO (legacy) */
|
||||
double ConvertBitsToDouble(unsigned int nBits);
|
||||
int64_t GetMasternodePayment(int nHeight, int64_t blockValue, int nMasternodeCount, bool isZAGRStake);
|
||||
|
||||
/**
|
||||
* Hybrid difficulty selection.
|
||||
* Implementations should route to the correct target calculation (PoW vs PoS)
|
||||
* based on the fProofOfStake flag rather than height-era assumptions.
|
||||
*/
|
||||
unsigned int GetNextWorkRequired(const CBlockIndex* pindexLast, const CBlockHeader* pblock, bool fProofOfStake);
|
||||
|
||||
bool ActivateBestChain(CValidationState& state, CBlock* pblock = NULL, bool fAlreadyChecked = false);
|
||||
@@ -262,7 +268,6 @@ void Misbehaving(NodeId nodeid, int howmuch);
|
||||
/** Flush all state, indexes and buffers to disk. */
|
||||
void FlushStateToDisk();
|
||||
|
||||
|
||||
/** (try to) add transaction to memory pool **/
|
||||
bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState& state, const CTransaction& tx, bool fLimitFree, bool* pfMissingInputs, bool fRejectInsaneFee = false, bool ignoreFees = false);
|
||||
|
||||
@@ -291,14 +296,8 @@ struct CDiskTxPos : public CDiskBlockPos {
|
||||
READWRITE(VARINT(nTxOffset));
|
||||
}
|
||||
|
||||
CDiskTxPos(const CDiskBlockPos& blockIn, unsigned int nTxOffsetIn) : CDiskBlockPos(blockIn.nFile, blockIn.nPos), nTxOffset(nTxOffsetIn)
|
||||
{
|
||||
}
|
||||
|
||||
CDiskTxPos()
|
||||
{
|
||||
SetNull();
|
||||
}
|
||||
CDiskTxPos(const CDiskBlockPos& blockIn, unsigned int nTxOffsetIn) : CDiskBlockPos(blockIn.nFile, blockIn.nPos), nTxOffset(nTxOffsetIn) {}
|
||||
CDiskTxPos() { SetNull(); }
|
||||
|
||||
void SetNull()
|
||||
{
|
||||
@@ -307,22 +306,9 @@ struct CDiskTxPos : public CDiskBlockPos {
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
CAmount GetMinRelayFee(const CTransaction& tx, unsigned int nBytes, bool fAllowFree);
|
||||
bool MoneyRange(CAmount nValueOut);
|
||||
|
||||
/**
|
||||
* Check transaction inputs, and make sure any
|
||||
* pay-to-script-hash transactions are evaluating IsStandard scripts
|
||||
*
|
||||
* Why bother? To avoid denial-of-service attacks; an attacker
|
||||
* can submit a standard HASH... OP_EQUAL transaction,
|
||||
* which will get accepted into blocks. The redemption
|
||||
* script can be anything; an attacker could use a very
|
||||
* expensive-to-check-upon-redemption script like:
|
||||
* DUP CHECKSIG DROP ... repeated 100 times... OP_1
|
||||
*/
|
||||
|
||||
/**
|
||||
* Check for standard transaction types
|
||||
* @param[in] mapInputs Map of previous transactions that have outputs we're spending
|
||||
@@ -346,7 +332,6 @@ unsigned int GetLegacySigOpCount(const CTransaction& tx);
|
||||
*/
|
||||
unsigned int GetP2SHSigOpCount(const CTransaction& tx, const CCoinsViewCache& mapInputs);
|
||||
|
||||
|
||||
/**
|
||||
* Check whether all inputs of this transaction are valid (no double spends, scripts & sigs, amounts)
|
||||
* This does not modify the UTXO set. If pvChecks is not NULL, script checks are pushed onto it
|
||||
@@ -413,7 +398,6 @@ public:
|
||||
bool ReadFromDisk(const CDiskBlockPos& pos, const uint256& hashBlock);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Closure representing one script verification
|
||||
* Note that this stores references to the spending transaction
|
||||
@@ -430,8 +414,15 @@ private:
|
||||
|
||||
public:
|
||||
CScriptCheck() : ptxTo(0), nIn(0), nFlags(0), cacheStore(false), error(SCRIPT_ERR_UNKNOWN_ERROR) {}
|
||||
CScriptCheck(const CCoins& txFromIn, const CTransaction& txToIn, unsigned int nInIn, unsigned int nFlagsIn, bool cacheIn) : scriptPubKey(txFromIn.vout[txToIn.vin[nInIn].prevout.n].scriptPubKey),
|
||||
ptxTo(&txToIn), nIn(nInIn), nFlags(nFlagsIn), cacheStore(cacheIn), error(SCRIPT_ERR_UNKNOWN_ERROR) {}
|
||||
CScriptCheck(const CCoins& txFromIn, const CTransaction& txToIn, unsigned int nInIn, unsigned int nFlagsIn, bool cacheIn)
|
||||
: scriptPubKey(txFromIn.vout[txToIn.vin[nInIn].prevout.n].scriptPubKey),
|
||||
ptxTo(&txToIn),
|
||||
nIn(nInIn),
|
||||
nFlags(nFlagsIn),
|
||||
cacheStore(cacheIn),
|
||||
error(SCRIPT_ERR_UNKNOWN_ERROR)
|
||||
{
|
||||
}
|
||||
|
||||
bool operator()();
|
||||
|
||||
@@ -448,13 +439,11 @@ public:
|
||||
ScriptError GetScriptError() const { return error; }
|
||||
};
|
||||
|
||||
|
||||
/** Functions for disk access for blocks */
|
||||
bool WriteBlockToDisk(CBlock& block, CDiskBlockPos& pos);
|
||||
bool ReadBlockFromDisk(CBlock& block, const CDiskBlockPos& pos);
|
||||
bool ReadBlockFromDisk(CBlock& block, const CBlockIndex* pindex);
|
||||
|
||||
|
||||
/** Functions for validating blocks and updating the block tree */
|
||||
|
||||
/** Undo the effects of this block (with given index) on the UTXO set represented by coins.
|
||||
@@ -479,13 +468,12 @@ bool ContextualCheckBlockHeader(const CBlockHeader& block, CValidationState& sta
|
||||
bool ContextualCheckBlock(const CBlock& block, CValidationState& state, CBlockIndex* pindexPrev);
|
||||
|
||||
/** Check a block is completely valid from start to finish (only works on top of our current best block, with cs_main held) */
|
||||
bool TestBlockValidity(CValidationState& state, const CBlock& block, CBlockIndex* pindexPrev, bool fCheckPOW = true, bool fCheckMerkleRoot = true);
|
||||
bool TestBlockValidity(CValidationState& state, const CBlock& block, CBlockIndex* pindexPrev, bool fCheckPOW = true, bool fCheckMerkleRoot = true, bool fCheckSig = true);
|
||||
|
||||
/** Store block on disk. If dbp is provided, the file is known to already reside on disk */
|
||||
bool AcceptBlock(CBlock& block, CValidationState& state, CBlockIndex** pindex, CDiskBlockPos* dbp = NULL, bool fAlreadyCheckedBlock = false);
|
||||
bool AcceptBlockHeader(const CBlockHeader& block, CValidationState& state, CBlockIndex** ppindex = NULL);
|
||||
|
||||
|
||||
class CBlockFileInfo
|
||||
{
|
||||
public:
|
||||
@@ -522,10 +510,7 @@ public:
|
||||
nTimeLast = 0;
|
||||
}
|
||||
|
||||
CBlockFileInfo()
|
||||
{
|
||||
SetNull();
|
||||
}
|
||||
CBlockFileInfo() { SetNull(); }
|
||||
|
||||
std::string ToString() const;
|
||||
|
||||
@@ -560,6 +545,7 @@ private:
|
||||
|
||||
public:
|
||||
CValidationState() : mode(MODE_VALID), nDoS(0), chRejectCode(0), corruptionPossible(false) {}
|
||||
|
||||
bool DoS(int level, bool ret = false, unsigned char chRejectCodeIn = 0, std::string strRejectReasonIn = "", bool corruptionIn = false)
|
||||
{
|
||||
chRejectCode = chRejectCodeIn;
|
||||
@@ -571,12 +557,12 @@ public:
|
||||
mode = MODE_INVALID;
|
||||
return ret;
|
||||
}
|
||||
bool Invalid(bool ret = false,
|
||||
unsigned char _chRejectCode = 0,
|
||||
std::string _strRejectReason = "")
|
||||
|
||||
bool Invalid(bool ret = false, unsigned char _chRejectCode = 0, std::string _strRejectReason = "")
|
||||
{
|
||||
return DoS(0, ret, _chRejectCode, _strRejectReason);
|
||||
}
|
||||
|
||||
bool Error(std::string strRejectReasonIn = "")
|
||||
{
|
||||
if (mode == MODE_VALID)
|
||||
@@ -584,23 +570,17 @@ public:
|
||||
mode = MODE_ERROR;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Abort(const std::string& msg)
|
||||
{
|
||||
AbortNode(msg);
|
||||
return Error(msg);
|
||||
}
|
||||
bool IsValid() const
|
||||
{
|
||||
return mode == MODE_VALID;
|
||||
}
|
||||
bool IsInvalid() const
|
||||
{
|
||||
return mode == MODE_INVALID;
|
||||
}
|
||||
bool IsError() const
|
||||
{
|
||||
return mode == MODE_ERROR;
|
||||
}
|
||||
|
||||
bool IsValid() const { return mode == MODE_VALID; }
|
||||
bool IsInvalid() const { return mode == MODE_INVALID; }
|
||||
bool IsError() const { return mode == MODE_ERROR; }
|
||||
|
||||
bool IsInvalid(int& nDoSOut) const
|
||||
{
|
||||
if (IsInvalid()) {
|
||||
@@ -609,10 +589,8 @@ public:
|
||||
}
|
||||
return false;
|
||||
}
|
||||
bool CorruptionPossible() const
|
||||
{
|
||||
return corruptionPossible;
|
||||
}
|
||||
|
||||
bool CorruptionPossible() const { return corruptionPossible; }
|
||||
unsigned char GetRejectCode() const { return chRejectCode; }
|
||||
std::string GetRejectReason() const { return strRejectReason; }
|
||||
};
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
// Copyright (c) 2014-2015 The Dash developers
|
||||
// Copyright (c) 2015-2019 The PIVX developers
|
||||
// Copyright (c) 2026 Agrarian Developers
|
||||
// Distributed under the MIT/X11 software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
@@ -16,6 +17,17 @@
|
||||
#include "util.h"
|
||||
#include <boost/filesystem.hpp>
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstdint>
|
||||
#include <limits>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <set>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
CBudgetManager budget;
|
||||
CCriticalSection cs_budget;
|
||||
|
||||
@@ -2159,7 +2171,7 @@ TrxValidationStatus CFinalizedBudget::IsTransactionValid(const CTransaction& txN
|
||||
|
||||
bool paid = false;
|
||||
|
||||
for (CTxOut out : txNew.vout) {
|
||||
for (const CTxOut& out : txNew.vout) {
|
||||
LogPrint("mnbudget","CFinalizedBudget::IsTransactionValid - nCurrentBudgetPayment=%d, payee=%s == out.scriptPubKey=%s, amount=%ld == out.nValue=%ld\n",
|
||||
nCurrentBudgetPayment, vecBudgetPayments[nCurrentBudgetPayment].payee.ToString().c_str(), out.scriptPubKey.ToString().c_str(),
|
||||
vecBudgetPayments[nCurrentBudgetPayment].nAmount, out.nValue);
|
||||
|
||||
+36
-33
@@ -1,10 +1,11 @@
|
||||
// Copyright (c) 2014-2015 The Dash developers
|
||||
// Copyright (c) 2015-2019 The PIVX developers
|
||||
// Copyright (c) 2026 Agrarian Developers
|
||||
// Distributed under the MIT/X11 software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
#ifndef MASTERNODE_BUDGET_H
|
||||
#define MASTERNODE_BUDGET_H
|
||||
#ifndef AGRARIAN_MASTERNODE_BUDGET_H
|
||||
#define AGRARIAN_MASTERNODE_BUDGET_H
|
||||
|
||||
#include "base58.h"
|
||||
#include "init.h"
|
||||
@@ -14,9 +15,11 @@
|
||||
#include "net.h"
|
||||
#include "sync.h"
|
||||
#include "util.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
#include <cstdint>
|
||||
#include <std::map>
|
||||
#include <std::string>
|
||||
#include <utility>
|
||||
#include <std::vector>
|
||||
extern CCriticalSection cs_budget;
|
||||
|
||||
class CBudgetManager;
|
||||
@@ -41,7 +44,7 @@ static const CAmount PROPOSAL_FEE_TX = (50 * COIN);
|
||||
static const CAmount BUDGET_FEE_TX_OLD = (50 * COIN);
|
||||
static const CAmount BUDGET_FEE_TX = (5 * COIN);
|
||||
static const int64_t BUDGET_VOTE_UPDATE_MIN = 60 * 60;
|
||||
static map<uint256, int> mapPayment_History;
|
||||
static std::map<uint256, int> mapPayment_History;
|
||||
|
||||
extern std::vector<CBudgetProposalBroadcast> vecImmatureBudgetProposals;
|
||||
extern std::vector<CFinalizedBudgetBroadcast> vecImmatureFinalizedBudgets;
|
||||
@@ -179,16 +182,16 @@ class CBudgetManager
|
||||
{
|
||||
private:
|
||||
//hold txes until they mature enough to use
|
||||
// XX42 map<uint256, CTransaction> mapCollateral;
|
||||
map<uint256, uint256> mapCollateralTxids;
|
||||
// XX42 std::map<uint256, CTransaction> mapCollateral;
|
||||
std::map<uint256, uint256> mapCollateralTxids;
|
||||
|
||||
public:
|
||||
// critical section to protect the inner data structures
|
||||
mutable CCriticalSection cs;
|
||||
|
||||
// keep track of the scanning errors I've seen
|
||||
map<uint256, CBudgetProposal> mapProposals;
|
||||
map<uint256, CFinalizedBudget> mapFinalizedBudgets;
|
||||
std::map<uint256, CBudgetProposal> mapProposals;
|
||||
std::map<uint256, CFinalizedBudget> mapFinalizedBudgets;
|
||||
|
||||
std::map<uint256, CBudgetProposalBroadcast> mapSeenMasternodeBudgetProposals;
|
||||
std::map<uint256, CBudgetVote> mapSeenMasternodeBudgetVotes;
|
||||
@@ -321,7 +324,7 @@ public:
|
||||
std::string strBudgetName;
|
||||
int nBlockStart;
|
||||
std::vector<CTxBudgetPayment> vecBudgetPayments;
|
||||
map<uint256, CFinalizedBudgetVote> mapVotes;
|
||||
std::map<uint256, CFinalizedBudgetVote> mapVotes;
|
||||
uint256 nFeeTXHash;
|
||||
int64_t nTime;
|
||||
|
||||
@@ -372,7 +375,7 @@ public:
|
||||
void SubmitVote();
|
||||
|
||||
//checks the hashes to make sure we know about them
|
||||
string GetStatus();
|
||||
std::string GetStatus();
|
||||
|
||||
uint256 GetHash()
|
||||
{
|
||||
@@ -413,24 +416,24 @@ public:
|
||||
CFinalizedBudgetBroadcast(const CFinalizedBudget& other);
|
||||
CFinalizedBudgetBroadcast(std::string strBudgetNameIn, int nBlockStartIn, std::vector<CTxBudgetPayment> vecBudgetPaymentsIn, uint256 nFeeTXHashIn);
|
||||
|
||||
void swap(CFinalizedBudgetBroadcast& first, CFinalizedBudgetBroadcast& second) // nothrow
|
||||
void std::swap(CFinalizedBudgetBroadcast& first, CFinalizedBudgetBroadcast& second) // nothrow
|
||||
{
|
||||
// enable ADL (not necessary in our case, but good practice)
|
||||
using std::swap;
|
||||
|
||||
// by swapping the members of two classes,
|
||||
// the two classes are effectively swapped
|
||||
swap(first.strBudgetName, second.strBudgetName);
|
||||
swap(first.nBlockStart, second.nBlockStart);
|
||||
first.mapVotes.swap(second.mapVotes);
|
||||
first.vecBudgetPayments.swap(second.vecBudgetPayments);
|
||||
swap(first.nFeeTXHash, second.nFeeTXHash);
|
||||
swap(first.nTime, second.nTime);
|
||||
std::swap(first.strBudgetName, second.strBudgetName);
|
||||
std::swap(first.nBlockStart, second.nBlockStart);
|
||||
first.mapVotes.std::swap(second.mapVotes);
|
||||
first.vecBudgetPayments.std::swap(second.vecBudgetPayments);
|
||||
std::swap(first.nFeeTXHash, second.nFeeTXHash);
|
||||
std::swap(first.nTime, second.nTime);
|
||||
}
|
||||
|
||||
CFinalizedBudgetBroadcast& operator=(CFinalizedBudgetBroadcast from)
|
||||
{
|
||||
swap(*this, from);
|
||||
std::swap(*this, from);
|
||||
return *this;
|
||||
}
|
||||
|
||||
@@ -478,7 +481,7 @@ public:
|
||||
int64_t nTime;
|
||||
uint256 nFeeTXHash;
|
||||
|
||||
map<uint256, CBudgetVote> mapVotes;
|
||||
std::map<uint256, CBudgetVote> mapVotes;
|
||||
//cache object
|
||||
|
||||
CBudgetProposal();
|
||||
@@ -559,27 +562,27 @@ public:
|
||||
CBudgetProposalBroadcast(const CBudgetProposalBroadcast& other) : CBudgetProposal(other) {}
|
||||
CBudgetProposalBroadcast(std::string strProposalNameIn, std::string strURLIn, int nPaymentCount, CScript addressIn, CAmount nAmountIn, int nBlockStartIn, uint256 nFeeTXHashIn);
|
||||
|
||||
void swap(CBudgetProposalBroadcast& first, CBudgetProposalBroadcast& second) // nothrow
|
||||
void std::swap(CBudgetProposalBroadcast& first, CBudgetProposalBroadcast& second) // nothrow
|
||||
{
|
||||
// enable ADL (not necessary in our case, but good practice)
|
||||
using std::swap;
|
||||
|
||||
// by swapping the members of two classes,
|
||||
// the two classes are effectively swapped
|
||||
swap(first.strProposalName, second.strProposalName);
|
||||
swap(first.nBlockStart, second.nBlockStart);
|
||||
swap(first.strURL, second.strURL);
|
||||
swap(first.nBlockEnd, second.nBlockEnd);
|
||||
swap(first.nAmount, second.nAmount);
|
||||
swap(first.address, second.address);
|
||||
swap(first.nTime, second.nTime);
|
||||
swap(first.nFeeTXHash, second.nFeeTXHash);
|
||||
first.mapVotes.swap(second.mapVotes);
|
||||
std::swap(first.strProposalName, second.strProposalName);
|
||||
std::swap(first.nBlockStart, second.nBlockStart);
|
||||
std::swap(first.strURL, second.strURL);
|
||||
std::swap(first.nBlockEnd, second.nBlockEnd);
|
||||
std::swap(first.nAmount, second.nAmount);
|
||||
std::swap(first.address, second.address);
|
||||
std::swap(first.nTime, second.nTime);
|
||||
std::swap(first.nFeeTXHash, second.nFeeTXHash);
|
||||
first.mapVotes.std::swap(second.mapVotes);
|
||||
}
|
||||
|
||||
CBudgetProposalBroadcast& operator=(CBudgetProposalBroadcast from)
|
||||
{
|
||||
swap(*this, from);
|
||||
std::swap(*this, from);
|
||||
return *this;
|
||||
}
|
||||
|
||||
@@ -604,4 +607,4 @@ public:
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
#endif // AGRARIAN_MASTERNODE_BUDGET_H
|
||||
|
||||
+227
-149
@@ -1,9 +1,11 @@
|
||||
// Copyright (c) 2014-2015 The Dash developers
|
||||
// Copyright (c) 2015-2019 The PIVX developers
|
||||
// Copyright (c) 2026 Agrarian Developers
|
||||
// Distributed under the MIT/X11 software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
#include "masternode-payments.h"
|
||||
|
||||
#include "addrman.h"
|
||||
#include "chainparams.h"
|
||||
#include "masternode-budget.h"
|
||||
@@ -14,8 +16,15 @@
|
||||
#include "sync.h"
|
||||
#include "util.h"
|
||||
#include "utilmoneystr.h"
|
||||
|
||||
#include <boost/filesystem.hpp>
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstdio>
|
||||
#include <limits>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
/** Object for who's going to get paid on which blocks */
|
||||
CMasternodePayments masternodePayments;
|
||||
|
||||
@@ -23,6 +32,26 @@ CCriticalSection cs_vecPayments;
|
||||
CCriticalSection cs_mapMasternodeBlocks;
|
||||
CCriticalSection cs_mapMasternodePayeeVotes;
|
||||
|
||||
namespace {
|
||||
|
||||
// Select the correct "newly created" transaction for payee validation based on block type.
|
||||
// - PoW blocks: coinbase is vtx[0]
|
||||
// - PoS blocks: coinstake is vtx[1] (with a null coinbase at vtx[0])
|
||||
//
|
||||
// This must NOT be derived from height-era assumptions, because Agrarian runs PoW+PoS concurrently
|
||||
// from Params().FIRST_POS_BLOCK() through Params().LAST_POW_BLOCK().
|
||||
const CTransaction& GetBlockNewTxForPayeeChecks(const CBlock& block)
|
||||
{
|
||||
// Defensive: preserve old behavior if vector is unexpectedly small.
|
||||
// A valid PoS block should have at least 2 tx; a valid PoW block at least 1 tx.
|
||||
if (block.IsProofOfStake() && block.vtx.size() > 1) {
|
||||
return block.vtx[1];
|
||||
}
|
||||
return block.vtx[0];
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
//
|
||||
// CMasternodePaymentDB
|
||||
//
|
||||
@@ -35,61 +64,81 @@ CMasternodePaymentDB::CMasternodePaymentDB()
|
||||
|
||||
bool CMasternodePaymentDB::Write(const CMasternodePayments& objToSave)
|
||||
{
|
||||
int64_t nStart = GetTimeMillis();
|
||||
const int64_t nStart = GetTimeMillis();
|
||||
|
||||
// serialize, checksum data up to that point, then append checksum
|
||||
CDataStream ssObj(SER_DISK, CLIENT_VERSION);
|
||||
ssObj << strMagicMessage; // masternode cache file specific magic message
|
||||
ssObj << FLATDATA(Params().MessageStart()); // network specific magic number
|
||||
ssObj << objToSave;
|
||||
uint256 hash = Hash(ssObj.begin(), ssObj.end());
|
||||
const uint256 hash = Hash(ssObj.begin(), ssObj.end());
|
||||
ssObj << hash;
|
||||
|
||||
// open output file, and associate with CAutoFile
|
||||
FILE* file = fopen(pathDB.string().c_str(), "wb");
|
||||
CAutoFile fileout(file, SER_DISK, CLIENT_VERSION);
|
||||
if (fileout.IsNull())
|
||||
FILE* file = std::fopen(pathDB.string().c_str(), "wb");
|
||||
if (file == nullptr) {
|
||||
return error("%s : Failed to open file %s", __func__, pathDB.string());
|
||||
}
|
||||
|
||||
CAutoFile fileout(file, SER_DISK, CLIENT_VERSION);
|
||||
if (fileout.IsNull()) {
|
||||
return error("%s : Failed to open file %s", __func__, pathDB.string());
|
||||
}
|
||||
|
||||
// Write and commit header, data
|
||||
try {
|
||||
fileout << ssObj;
|
||||
} catch (std::exception& e) {
|
||||
} catch (const std::exception& e) {
|
||||
return error("%s : Serialize or I/O error - %s", __func__, e.what());
|
||||
}
|
||||
fileout.fclose();
|
||||
|
||||
LogPrint("masternode", "Written info to mnpayments.dat %dms\n", GetTimeMillis() - nStart);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
CMasternodePaymentDB::ReadResult CMasternodePaymentDB::Read(CMasternodePayments& objToLoad, bool fDryRun)
|
||||
{
|
||||
int64_t nStart = GetTimeMillis();
|
||||
const int64_t nStart = GetTimeMillis();
|
||||
|
||||
// open input file, and associate with CAutoFile
|
||||
FILE* file = fopen(pathDB.string().c_str(), "rb");
|
||||
FILE* file = std::fopen(pathDB.string().c_str(), "rb");
|
||||
if (file == nullptr) {
|
||||
error("%s : Failed to open file %s", __func__, pathDB.string());
|
||||
return FileError;
|
||||
}
|
||||
|
||||
CAutoFile filein(file, SER_DISK, CLIENT_VERSION);
|
||||
if (filein.IsNull()) {
|
||||
error("%s : Failed to open file %s", __func__, pathDB.string());
|
||||
return FileError;
|
||||
}
|
||||
|
||||
// use file size to size memory buffer
|
||||
int fileSize = boost::filesystem::file_size(pathDB);
|
||||
int dataSize = fileSize - sizeof(uint256);
|
||||
int fileSize = 0;
|
||||
try {
|
||||
fileSize = static_cast<int>(boost::filesystem::file_size(pathDB));
|
||||
} catch (const std::exception& e) {
|
||||
error("%s : Unable to read file size %s (%s)", __func__, pathDB.string(), e.what());
|
||||
return FileError;
|
||||
}
|
||||
|
||||
int dataSize = fileSize - static_cast<int>(sizeof(uint256));
|
||||
// Don't try to resize to a negative number if file is small
|
||||
if (dataSize < 0)
|
||||
if (dataSize < 0) {
|
||||
dataSize = 0;
|
||||
vector<unsigned char> vchData;
|
||||
vchData.resize(dataSize);
|
||||
}
|
||||
|
||||
std::vector<unsigned char> vchData;
|
||||
vchData.resize(static_cast<size_t>(dataSize));
|
||||
uint256 hashIn;
|
||||
|
||||
// read data and checksum from file
|
||||
try {
|
||||
filein.read((char*)&vchData[0], dataSize);
|
||||
if (dataSize > 0) {
|
||||
filein.read(reinterpret_cast<char*>(&vchData[0]), dataSize);
|
||||
}
|
||||
filein >> hashIn;
|
||||
} catch (std::exception& e) {
|
||||
} catch (const std::exception& e) {
|
||||
error("%s : Deserialize or I/O error - %s", __func__, e.what());
|
||||
return HashReadError;
|
||||
}
|
||||
@@ -98,7 +147,7 @@ CMasternodePaymentDB::ReadResult CMasternodePaymentDB::Read(CMasternodePayments&
|
||||
CDataStream ssObj(vchData, SER_DISK, CLIENT_VERSION);
|
||||
|
||||
// verify stored checksum matches input data
|
||||
uint256 hashTmp = Hash(ssObj.begin(), ssObj.end());
|
||||
const uint256 hashTmp = Hash(ssObj.begin(), ssObj.end());
|
||||
if (hashIn != hashTmp) {
|
||||
error("%s : Checksum mismatch, data corrupted", __func__);
|
||||
return IncorrectHash;
|
||||
@@ -112,23 +161,22 @@ CMasternodePaymentDB::ReadResult CMasternodePaymentDB::Read(CMasternodePayments&
|
||||
|
||||
// ... verify the message matches predefined one
|
||||
if (strMagicMessage != strMagicMessageTmp) {
|
||||
error("%s : Invalid masternode payement cache magic message", __func__);
|
||||
error("%s : Invalid masternode payment cache magic message", __func__);
|
||||
return IncorrectMagicMessage;
|
||||
}
|
||||
|
||||
|
||||
// de-serialize file header (network specific magic number) and ..
|
||||
ssObj >> FLATDATA(pchMsgTmp);
|
||||
|
||||
// ... verify the network matches ours
|
||||
if (memcmp(pchMsgTmp, Params().MessageStart(), sizeof(pchMsgTmp))) {
|
||||
if (std::memcmp(pchMsgTmp, Params().MessageStart(), sizeof(pchMsgTmp))) {
|
||||
error("%s : Invalid network magic number", __func__);
|
||||
return IncorrectMagicNumber;
|
||||
}
|
||||
|
||||
// de-serialize data into CMasternodePayments object
|
||||
ssObj >> objToLoad;
|
||||
} catch (std::exception& e) {
|
||||
} catch (const std::exception& e) {
|
||||
objToLoad.Clear();
|
||||
error("%s : Deserialize or I/O error - %s", __func__, e.what());
|
||||
return IncorrectFormat;
|
||||
@@ -136,6 +184,7 @@ CMasternodePaymentDB::ReadResult CMasternodePaymentDB::Read(CMasternodePayments&
|
||||
|
||||
LogPrint("masternode", "Loaded info from mnpayments.dat %dms\n", GetTimeMillis() - nStart);
|
||||
LogPrint("masternode", " %s\n", objToLoad.ToString());
|
||||
|
||||
if (!fDryRun) {
|
||||
LogPrint("masternode", "Masternode payments manager - cleaning....\n");
|
||||
objToLoad.CleanPaymentList();
|
||||
@@ -148,61 +197,63 @@ CMasternodePaymentDB::ReadResult CMasternodePaymentDB::Read(CMasternodePayments&
|
||||
|
||||
void DumpMasternodePayments()
|
||||
{
|
||||
int64_t nStart = GetTimeMillis();
|
||||
const int64_t nStart = GetTimeMillis();
|
||||
|
||||
CMasternodePaymentDB paymentdb;
|
||||
CMasternodePayments tempPayments;
|
||||
|
||||
LogPrint("masternode", "Verifying mnpayments.dat format...\n");
|
||||
CMasternodePaymentDB::ReadResult readResult = paymentdb.Read(tempPayments, true);
|
||||
const CMasternodePaymentDB::ReadResult readResult = paymentdb.Read(tempPayments, true);
|
||||
|
||||
// there was an error and it was not an error on file opening => do not proceed
|
||||
if (readResult == CMasternodePaymentDB::FileError)
|
||||
LogPrint("masternode","Missing budgets file - mnpayments.dat, will try to recreate\n");
|
||||
else if (readResult != CMasternodePaymentDB::Ok) {
|
||||
if (readResult == CMasternodePaymentDB::FileError) {
|
||||
LogPrint("masternode", "Missing payments file - mnpayments.dat, will try to recreate\n");
|
||||
} else if (readResult != CMasternodePaymentDB::Ok) {
|
||||
LogPrint("masternode", "Error reading mnpayments.dat: ");
|
||||
if (readResult == CMasternodePaymentDB::IncorrectFormat)
|
||||
if (readResult == CMasternodePaymentDB::IncorrectFormat) {
|
||||
LogPrint("masternode", "magic is ok but data has invalid format, will try to recreate\n");
|
||||
else {
|
||||
} else {
|
||||
LogPrint("masternode", "file format is unknown or invalid, please fix it manually\n");
|
||||
return;
|
||||
}
|
||||
}
|
||||
LogPrint("masternode","Writting info to mnpayments.dat...\n");
|
||||
|
||||
LogPrint("masternode", "Writing info to mnpayments.dat...\n");
|
||||
paymentdb.Write(masternodePayments);
|
||||
|
||||
LogPrint("masternode","Budget dump finished %dms\n", GetTimeMillis() - nStart);
|
||||
LogPrint("masternode", "Payments dump finished %dms\n", GetTimeMillis() - nStart);
|
||||
}
|
||||
|
||||
bool IsBlockValueValid(const CBlock& block, CAmount nExpectedValue, CAmount nMinted)
|
||||
{
|
||||
CBlockIndex* pindexPrev = chainActive.Tip();
|
||||
if (pindexPrev == NULL) return true;
|
||||
if (pindexPrev == nullptr) {
|
||||
return true;
|
||||
}
|
||||
|
||||
int nHeight = 0;
|
||||
if (pindexPrev->GetBlockHash() == block.hashPrevBlock) {
|
||||
nHeight = pindexPrev->nHeight + 1;
|
||||
} else { // out of order
|
||||
BlockMap::iterator mi = mapBlockIndex.find(block.hashPrevBlock);
|
||||
if (mi != mapBlockIndex.end() && (*mi).second)
|
||||
if (mi != mapBlockIndex.end() && (*mi).second) {
|
||||
nHeight = (*mi).second->nHeight + 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (nHeight == 0) {
|
||||
LogPrint("masternode", "IsBlockValueValid() : WARNING: Couldn't find previous block\n");
|
||||
}
|
||||
|
||||
//LogPrintf("XX69----------> IsBlockValueValid(): nMinted: %d, nExpectedValue: %d\n", FormatMoney(nMinted), FormatMoney(nExpectedValue));
|
||||
|
||||
if (!masternodeSync.IsSynced()) { // there is no budget data to use to check anything
|
||||
// super blocks will always be on these blocks, max 100 per budgeting
|
||||
if (nHeight % Params().GetBudgetCycleBlocks() < 100) {
|
||||
return true;
|
||||
} else {
|
||||
if (nMinted > nExpectedValue) {
|
||||
return false;
|
||||
}
|
||||
return nMinted <= nExpectedValue;
|
||||
}
|
||||
} else { // we're synced and have data so check the budget schedule
|
||||
|
||||
// we're synced and have data so check the budget schedule
|
||||
|
||||
// are these blocks even enabled
|
||||
if (!IsSporkActive(SPORK_13_ENABLE_SUPERBLOCKS)) {
|
||||
@@ -212,14 +263,9 @@ bool IsBlockValueValid(const CBlock& block, CAmount nExpectedValue, CAmount nMin
|
||||
if (budget.IsBudgetPaymentBlock(nHeight)) {
|
||||
// the value of the block is evaluated in CheckBlock
|
||||
return true;
|
||||
} else {
|
||||
if (nMinted > nExpectedValue) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
return nMinted <= nExpectedValue;
|
||||
}
|
||||
|
||||
bool IsBlockPayeeValid(const CBlock& block, int nBlockHeight)
|
||||
@@ -231,7 +277,7 @@ bool IsBlockPayeeValid(const CBlock& block, int nBlockHeight)
|
||||
return true;
|
||||
}
|
||||
|
||||
const CTransaction& txNew = (nBlockHeight > Params().LAST_POW_BLOCK() ? block.vtx[1] : block.vtx[0]);
|
||||
const CTransaction& txNew = GetBlockNewTxForPayeeChecks(block);
|
||||
|
||||
// check if it's a budget block
|
||||
if (IsSporkActive(SPORK_13_ENABLE_SUPERBLOCKS)) {
|
||||
@@ -243,38 +289,43 @@ bool IsBlockPayeeValid(const CBlock& block, int nBlockHeight)
|
||||
|
||||
if (transactionStatus == TrxValidationStatus::InValid) {
|
||||
LogPrint("masternode", "Invalid budget payment detected %s\n", txNew.ToString().c_str());
|
||||
if (IsSporkActive(SPORK_9_MASTERNODE_BUDGET_ENFORCEMENT))
|
||||
if (IsSporkActive(SPORK_9_MASTERNODE_BUDGET_ENFORCEMENT)) {
|
||||
return false;
|
||||
|
||||
}
|
||||
LogPrint("masternode", "Budget enforcement is disabled, accepting block\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If we end here the transaction was either TrxValidationStatus::InValid and Budget enforcement is disabled, or
|
||||
// a double budget payment (status = TrxValidationStatus::DoublePayment) was detected, or no/not enough masternode
|
||||
// votes (status = TrxValidationStatus::VoteThreshold) for a finalized budget were found
|
||||
// In all cases a masternode will get the payment for this block
|
||||
// If we end here the transaction was either InValid and Budget enforcement is disabled, or
|
||||
// a double budget payment (DoublePayment) was detected, or no/not enough masternode
|
||||
// votes (VoteThreshold) for a finalized budget were found.
|
||||
// In all cases a masternode will get the payment for this block.
|
||||
|
||||
// check for masternode payee
|
||||
if (masternodePayments.IsTransactionValid(txNew, nBlockHeight))
|
||||
return true;
|
||||
LogPrint("masternode","Invalid mn payment detected %s\n", txNew.ToString().c_str());
|
||||
|
||||
if (IsSporkActive(SPORK_8_MASTERNODE_PAYMENT_ENFORCEMENT))
|
||||
return false;
|
||||
LogPrint("masternode","Masternode payment enforcement is disabled, accepting block\n");
|
||||
|
||||
if (masternodePayments.IsTransactionValid(txNew, nBlockHeight)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
LogPrint("masternode", "Invalid mn payment detected %s\n", txNew.ToString().c_str());
|
||||
|
||||
if (IsSporkActive(SPORK_8_MASTERNODE_PAYMENT_ENFORCEMENT)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
LogPrint("masternode", "Masternode payment enforcement is disabled, accepting block\n");
|
||||
return true;
|
||||
}
|
||||
|
||||
void FillBlockPayee(CMutableTransaction& txNew, CAmount nFees, bool fProofOfStake, bool fZAGRStake)
|
||||
{
|
||||
CBlockIndex* pindexPrev = chainActive.Tip();
|
||||
if (!pindexPrev) return;
|
||||
if (!pindexPrev) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (IsSporkActive(SPORK_13_ENABLE_SUPERBLOCKS) && budget.IsBudgetPaymentBlock(pindexPrev->nHeight + 1)) {
|
||||
const int nextHeight = pindexPrev->nHeight + 1;
|
||||
if (IsSporkActive(SPORK_13_ENABLE_SUPERBLOCKS) && budget.IsBudgetPaymentBlock(nextHeight)) {
|
||||
budget.FillBlockPayee(txNew, nFees, fProofOfStake);
|
||||
} else {
|
||||
masternodePayments.FillBlockPayee(txNew, nFees, fProofOfStake, fZAGRStake);
|
||||
@@ -285,20 +336,21 @@ std::string GetRequiredPaymentsString(int nBlockHeight)
|
||||
{
|
||||
if (IsSporkActive(SPORK_13_ENABLE_SUPERBLOCKS) && budget.IsBudgetPaymentBlock(nBlockHeight)) {
|
||||
return budget.GetRequiredPaymentsString(nBlockHeight);
|
||||
} else {
|
||||
}
|
||||
return masternodePayments.GetRequiredPaymentsString(nBlockHeight);
|
||||
}
|
||||
}
|
||||
|
||||
void CMasternodePayments::FillBlockPayee(CMutableTransaction& txNew, int64_t nFees, bool fProofOfStake, bool fZAGRStake)
|
||||
void CMasternodePayments::FillBlockPayee(CMutableTransaction& txNew, int64_t /*nFees*/, bool fProofOfStake, bool fZAGRStake)
|
||||
{
|
||||
CBlockIndex* pindexPrev = chainActive.Tip();
|
||||
if (!pindexPrev) return;
|
||||
if (!pindexPrev) {
|
||||
return;
|
||||
}
|
||||
|
||||
bool hasPayment = true;
|
||||
CScript payee;
|
||||
|
||||
//spork
|
||||
// spork / schedule
|
||||
if (!masternodePayments.GetBlockPayee(pindexPrev->nHeight + 1, payee)) {
|
||||
// no masternode detected
|
||||
CMasternode* winningNode = mnodeman.GetCurrentMasterNode(1);
|
||||
@@ -310,24 +362,29 @@ void CMasternodePayments::FillBlockPayee(CMutableTransaction& txNew, int64_t nFe
|
||||
}
|
||||
}
|
||||
|
||||
CAmount blockValue = GetBlockValue(pindexPrev->nHeight);
|
||||
CAmount masternodePayment = GetMasternodePayment(pindexPrev->nHeight, blockValue, 0, fZAGRStake);
|
||||
const int payHeight = pindexPrev->nHeight + 1;
|
||||
const CAmount blockValue = GetBlockValue(payHeight);
|
||||
const CAmount masternodePayment = GetMasternodePayment(payHeight, blockValue, 0, fZAGRStake);
|
||||
|
||||
if (hasPayment) {
|
||||
if (fProofOfStake) {
|
||||
/**For Proof Of Stake vout[0] must be null
|
||||
/** For Proof Of Stake vout[0] must be null.
|
||||
* Stake reward can be split into many different outputs, so we must
|
||||
* use vout.size() to align with several different cases.
|
||||
* An additional output is appended as the masternode payment
|
||||
* An additional output is appended as the masternode payment.
|
||||
*/
|
||||
unsigned int i = txNew.vout.size();
|
||||
const unsigned int i = txNew.vout.size();
|
||||
txNew.vout.resize(i + 1);
|
||||
txNew.vout[i].scriptPubKey = payee;
|
||||
txNew.vout[i].nValue = masternodePayment;
|
||||
|
||||
// subtract mn payment from the stake reward
|
||||
if (!txNew.vout[1].IsZerocoinMint())
|
||||
// NOTE: original code used vout[1] and (i-1); keep behavior, but guard bounds.
|
||||
if (i > 0) {
|
||||
if (!txNew.vout[1].IsZerocoinMint() && (i - 1) < txNew.vout.size()) {
|
||||
txNew.vout[i - 1].nValue -= masternodePayment;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
txNew.vout.resize(2);
|
||||
txNew.vout[1].scriptPubKey = payee;
|
||||
@@ -347,20 +404,20 @@ int CMasternodePayments::GetMinMasternodePaymentsProto()
|
||||
{
|
||||
if (IsSporkActive(SPORK_10_MASTERNODE_PAY_UPDATED_NODES))
|
||||
return ActiveProtocol(); // Allow only updated peers
|
||||
else
|
||||
return MIN_PEER_PROTO_VERSION_BEFORE_ENFORCEMENT; // Also allow old peers as long as they are allowed to run
|
||||
}
|
||||
|
||||
void CMasternodePayments::ProcessMessageMasternodePayments(CNode* pfrom, std::string& strCommand, CDataStream& vRecv)
|
||||
{
|
||||
if (!masternodeSync.IsBlockchainSynced()) return;
|
||||
|
||||
if (fLiteMode) return; //disable all Obfuscation/Masternode related functionality
|
||||
if (!masternodeSync.IsBlockchainSynced()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (fLiteMode) {
|
||||
return; // disable all Obfuscation/Masternode related functionality
|
||||
}
|
||||
|
||||
if (strCommand == "mnget") { // Masternode Payments Request Sync
|
||||
if (fLiteMode) return; //disable all Obfuscation/Masternode related functionality
|
||||
|
||||
int nCountNeeded;
|
||||
vRecv >> nCountNeeded;
|
||||
|
||||
@@ -375,17 +432,23 @@ void CMasternodePayments::ProcessMessageMasternodePayments(CNode* pfrom, std::st
|
||||
pfrom->FulfilledRequest("mnget");
|
||||
masternodePayments.Sync(pfrom, nCountNeeded);
|
||||
LogPrint("mnpayments", "mnget - Sent Masternode winners to peer %i\n", pfrom->GetId());
|
||||
} else if (strCommand == "mnw") { //Masternode Payments Declare Winner
|
||||
//this is required in litemodef
|
||||
return;
|
||||
}
|
||||
|
||||
if (strCommand == "mnw") { // Masternode Payments Declare Winner
|
||||
CMasternodePaymentWinner winner;
|
||||
vRecv >> winner;
|
||||
|
||||
if (pfrom->nVersion < ActiveProtocol()) return;
|
||||
if (pfrom->nVersion < ActiveProtocol()) {
|
||||
return;
|
||||
}
|
||||
|
||||
int nHeight;
|
||||
{
|
||||
TRY_LOCK(cs_main, locked);
|
||||
if (!locked || chainActive.Tip() == NULL) return;
|
||||
if (!locked || chainActive.Tip() == nullptr) {
|
||||
return;
|
||||
}
|
||||
nHeight = chainActive.Tip()->nHeight;
|
||||
}
|
||||
|
||||
@@ -395,20 +458,18 @@ void CMasternodePayments::ProcessMessageMasternodePayments(CNode* pfrom, std::st
|
||||
return;
|
||||
}
|
||||
|
||||
int nFirstBlock = nHeight - (mnodeman.CountEnabled() * 1.25);
|
||||
const int nFirstBlock = nHeight - static_cast<int>(mnodeman.CountEnabled() * 1.25);
|
||||
if (winner.nBlockHeight < nFirstBlock || winner.nBlockHeight > nHeight + 20) {
|
||||
LogPrint("mnpayments", "mnw - winner out of range - FirstBlock %d Height %d bestHeight %d\n", nFirstBlock, winner.nBlockHeight, nHeight);
|
||||
return;
|
||||
}
|
||||
|
||||
std::string strError = "";
|
||||
std::string strError;
|
||||
if (!winner.IsValid(pfrom, strError)) {
|
||||
// if(strError != "") LogPrint("masternode","mnw - invalid message - %s\n", strError);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!masternodePayments.CanVote(winner.vinMasternode.prevout, winner.nBlockHeight)) {
|
||||
// LogPrint("masternode","mnw - masternode already voted - %s\n", winner.vinMasternode.prevout.ToStringShort());
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -422,25 +483,20 @@ void CMasternodePayments::ProcessMessageMasternodePayments(CNode* pfrom, std::st
|
||||
return;
|
||||
}
|
||||
|
||||
CTxDestination address1;
|
||||
ExtractDestination(winner.payee, address1);
|
||||
CBitcoinAddress address2(address1);
|
||||
|
||||
// LogPrint("mnpayments", "mnw - winning vote - Addr %s Height %d bestHeight %d - %s\n", address2.ToString().c_str(), winner.nBlockHeight, nHeight, winner.vinMasternode.prevout.ToStringShort());
|
||||
|
||||
if (masternodePayments.AddWinningMasternode(winner)) {
|
||||
winner.Relay();
|
||||
masternodeSync.AddedMasternodeWinner(winner.GetHash());
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
bool CMasternodePaymentWinner::Sign(CKey& keyMasternode, CPubKey& pubKeyMasternode)
|
||||
{
|
||||
std::string errorMessage;
|
||||
std::string strMasterNodeSignMessage;
|
||||
|
||||
std::string strMessage = vinMasternode.prevout.ToStringShort() + std::to_string(nBlockHeight) + payee.ToString();
|
||||
const std::string strMessage =
|
||||
vinMasternode.prevout.ToStringShort() + std::to_string(nBlockHeight) + payee.ToString();
|
||||
|
||||
if (!obfuScationSigner.SignMessage(strMessage, errorMessage, vchSig, keyMasternode)) {
|
||||
LogPrint("masternode", "CMasternodePing::Sign() - Error: %s\n", errorMessage.c_str());
|
||||
@@ -460,7 +516,6 @@ bool CMasternodePayments::GetBlockPayee(int nBlockHeight, CScript& payee)
|
||||
if (mapMasternodeBlocks.count(nBlockHeight)) {
|
||||
return mapMasternodeBlocks[nBlockHeight].GetPayee(payee);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -473,16 +528,19 @@ bool CMasternodePayments::IsScheduled(CMasternode& mn, int nNotBlockHeight)
|
||||
int nHeight;
|
||||
{
|
||||
TRY_LOCK(cs_main, locked);
|
||||
if (!locked || chainActive.Tip() == NULL) return false;
|
||||
if (!locked || chainActive.Tip() == nullptr) {
|
||||
return false;
|
||||
}
|
||||
nHeight = chainActive.Tip()->nHeight;
|
||||
}
|
||||
|
||||
CScript mnpayee;
|
||||
mnpayee = GetScriptForDestination(mn.pubKeyCollateralAddress.GetID());
|
||||
const CScript mnpayee = GetScriptForDestination(mn.pubKeyCollateralAddress.GetID());
|
||||
|
||||
CScript payee;
|
||||
for (int64_t h = nHeight; h <= nHeight + 8; h++) {
|
||||
if (h == nNotBlockHeight) continue;
|
||||
if (h == nNotBlockHeight) {
|
||||
continue;
|
||||
}
|
||||
if (mapMasternodeBlocks.count(h)) {
|
||||
if (mapMasternodeBlocks[h].GetPayee(payee)) {
|
||||
if (mnpayee == payee) {
|
||||
@@ -518,7 +576,6 @@ bool CMasternodePayments::AddWinningMasternode(CMasternodePaymentWinner& winnerI
|
||||
}
|
||||
|
||||
mapMasternodeBlocks[winnerIn.nBlockHeight].AddPayee(winnerIn.payee, 1);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -529,50 +586,60 @@ bool CMasternodeBlockPayees::IsTransactionValid(const CTransaction& txNew)
|
||||
int nMaxSignatures = 0;
|
||||
int nMasternode_Drift_Count = 0;
|
||||
|
||||
std::string strPayeesPossible = "";
|
||||
std::string strPayeesPossible;
|
||||
|
||||
CAmount nReward = GetBlockValue(nBlockHeight);
|
||||
const CAmount nReward = GetBlockValue(nBlockHeight);
|
||||
|
||||
if (IsSporkActive(SPORK_8_MASTERNODE_PAYMENT_ENFORCEMENT)) {
|
||||
// Get a stable number of masternodes by ignoring newly activated (< 8000 sec old) masternodes
|
||||
nMasternode_Drift_Count = mnodeman.stable_size() + Params().MasternodeCountDrift();
|
||||
}
|
||||
else {
|
||||
//account for the fact that all peers do not see the same masternode count. A allowance of being off our masternode count is given
|
||||
//we only need to look at an increased masternode count because as count increases, the reward decreases. This code only checks
|
||||
//for mnPayment >= required, so it only makes sense to check the max node count allowed.
|
||||
} else {
|
||||
// Account for the fact that all peers do not see the same masternode count.
|
||||
// An allowance of being off our masternode count is given.
|
||||
// We only need to look at an increased masternode count because as count increases, the reward decreases.
|
||||
// This code only checks for mnPayment >= required, so it only makes sense to check the max node count allowed.
|
||||
nMasternode_Drift_Count = mnodeman.size() + Params().MasternodeCountDrift();
|
||||
}
|
||||
|
||||
CAmount requiredMasternodePayment = GetMasternodePayment(nBlockHeight, nReward, nMasternode_Drift_Count, txNew.HasZerocoinSpendInputs());
|
||||
const CAmount requiredMasternodePayment =
|
||||
GetMasternodePayment(nBlockHeight, nReward, nMasternode_Drift_Count, txNew.HasZerocoinSpendInputs());
|
||||
|
||||
// require at least 6 signatures
|
||||
for (CMasternodePayee& payee : vecPayments)
|
||||
if (payee.nVotes >= nMaxSignatures && payee.nVotes >= MNPAYMENTS_SIGNATURES_REQUIRED)
|
||||
for (CMasternodePayee& payee : vecPayments) {
|
||||
if (payee.nVotes >= nMaxSignatures && payee.nVotes >= MNPAYMENTS_SIGNATURES_REQUIRED) {
|
||||
nMaxSignatures = payee.nVotes;
|
||||
}
|
||||
}
|
||||
|
||||
// if we don't have at least 6 signatures on a payee, approve whichever is the longest chain
|
||||
if (nMaxSignatures < MNPAYMENTS_SIGNATURES_REQUIRED) return true;
|
||||
// If we don't have at least 6 signatures on a payee, approve whichever is the longest chain
|
||||
if (nMaxSignatures < MNPAYMENTS_SIGNATURES_REQUIRED) {
|
||||
return true;
|
||||
}
|
||||
|
||||
for (CMasternodePayee& payee : vecPayments) {
|
||||
bool found = false;
|
||||
for (CTxOut out : txNew.vout) {
|
||||
|
||||
for (const CTxOut& out : txNew.vout) {
|
||||
if (payee.scriptPubKey == out.scriptPubKey) {
|
||||
if(out.nValue >= requiredMasternodePayment)
|
||||
if (out.nValue >= requiredMasternodePayment) {
|
||||
found = true;
|
||||
else
|
||||
LogPrint("masternode","Masternode payment is out of drift range. Paid=%s Min=%s\n", FormatMoney(out.nValue).c_str(), FormatMoney(requiredMasternodePayment).c_str());
|
||||
} else {
|
||||
LogPrint("masternode", "Masternode payment is out of drift range. Paid=%s Min=%s\n",
|
||||
FormatMoney(out.nValue).c_str(), FormatMoney(requiredMasternodePayment).c_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (payee.nVotes >= MNPAYMENTS_SIGNATURES_REQUIRED) {
|
||||
if (found) return true;
|
||||
if (found) {
|
||||
return true;
|
||||
}
|
||||
|
||||
CTxDestination address1;
|
||||
ExtractDestination(payee.scriptPubKey, address1);
|
||||
CBitcoinAddress address2(address1);
|
||||
|
||||
if (strPayeesPossible == "") {
|
||||
if (strPayeesPossible.empty()) {
|
||||
strPayeesPossible += address2.ToString();
|
||||
} else {
|
||||
strPayeesPossible += "," + address2.ToString();
|
||||
@@ -580,7 +647,8 @@ bool CMasternodeBlockPayees::IsTransactionValid(const CTransaction& txNew)
|
||||
}
|
||||
}
|
||||
|
||||
LogPrint("masternode","CMasternodePayments::IsTransactionValid - Missing required payment of %s to %s\n", FormatMoney(requiredMasternodePayment).c_str(), strPayeesPossible.c_str());
|
||||
LogPrint("masternode", "CMasternodePayments::IsTransactionValid - Missing required payment of %s to %s\n",
|
||||
FormatMoney(requiredMasternodePayment).c_str(), strPayeesPossible.c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -634,16 +702,18 @@ void CMasternodePayments::CleanPaymentList()
|
||||
int nHeight;
|
||||
{
|
||||
TRY_LOCK(cs_main, locked);
|
||||
if (!locked || chainActive.Tip() == NULL) return;
|
||||
if (!locked || chainActive.Tip() == nullptr) {
|
||||
return;
|
||||
}
|
||||
nHeight = chainActive.Tip()->nHeight;
|
||||
}
|
||||
|
||||
// keep up to five cycles for historical sake
|
||||
int nLimit = std::max(int(mnodeman.size() * 1.25), 1000);
|
||||
const int nLimit = std::max(static_cast<int>(mnodeman.size() * 1.25), 1000);
|
||||
|
||||
std::map<uint256, CMasternodePaymentWinner>::iterator it = mapMasternodePayeeVotes.begin();
|
||||
while (it != mapMasternodePayeeVotes.end()) {
|
||||
CMasternodePaymentWinner winner = (*it).second;
|
||||
const CMasternodePaymentWinner& winner = (*it).second;
|
||||
|
||||
if (nHeight - winner.nBlockHeight > nLimit) {
|
||||
LogPrint("mnpayments", "CMasternodePayments::CleanPaymentList - Removing old Masternode payment - block %d\n", winner.nBlockHeight);
|
||||
@@ -673,11 +743,11 @@ bool CMasternodePaymentWinner::IsValid(CNode* pnode, std::string& strError)
|
||||
return false;
|
||||
}
|
||||
|
||||
int n = mnodeman.GetMasternodeRank(vinMasternode, nBlockHeight - 100, ActiveProtocol());
|
||||
const int n = mnodeman.GetMasternodeRank(vinMasternode, nBlockHeight - 100, ActiveProtocol());
|
||||
|
||||
if (n > MNPAYMENTS_SIGNATURES_TOTAL) {
|
||||
//It's common to have masternodes mistakenly think they are in the top 10
|
||||
// We don't want to print all of these messages, or punish them unless they're way off
|
||||
// It's common to have masternodes mistakenly think they are in the top 10.
|
||||
// We don't want to print all of these messages, or punish them unless they're way off.
|
||||
if (n > MNPAYMENTS_SIGNATURES_TOTAL * 2) {
|
||||
strError = strprintf("Masternode not in the top %d (%d)", MNPAYMENTS_SIGNATURES_TOTAL * 2, n);
|
||||
LogPrint("masternode", "CMasternodePaymentWinner::IsValid - %s\n", strError);
|
||||
@@ -691,11 +761,12 @@ bool CMasternodePaymentWinner::IsValid(CNode* pnode, std::string& strError)
|
||||
|
||||
bool CMasternodePayments::ProcessBlock(int nBlockHeight)
|
||||
{
|
||||
if (!fMasterNode) return false;
|
||||
if (!fMasterNode) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// reference node - hybrid mode
|
||||
|
||||
int n = mnodeman.GetMasternodeRank(activeMasternode.vin, nBlockHeight - 100, ActiveProtocol());
|
||||
const int n = mnodeman.GetMasternodeRank(activeMasternode.vin, nBlockHeight - 100, ActiveProtocol());
|
||||
|
||||
if (n == -1) {
|
||||
LogPrint("mnpayments", "CMasternodePayments::ProcessBlock - Unknown Masternode\n");
|
||||
@@ -707,32 +778,36 @@ bool CMasternodePayments::ProcessBlock(int nBlockHeight)
|
||||
return false;
|
||||
}
|
||||
|
||||
if (nBlockHeight <= nLastBlockHeight) return false;
|
||||
if (nBlockHeight <= nLastBlockHeight) {
|
||||
return false;
|
||||
}
|
||||
|
||||
CMasternodePaymentWinner newWinner(activeMasternode.vin);
|
||||
|
||||
if (budget.IsBudgetPaymentBlock(nBlockHeight)) {
|
||||
//is budget payment block -- handled by the budgeting software
|
||||
// budget payment block -- handled by the budgeting software
|
||||
} else {
|
||||
LogPrint("masternode","CMasternodePayments::ProcessBlock() Start nHeight %d - vin %s. \n", nBlockHeight, activeMasternode.vin.prevout.hash.ToString());
|
||||
LogPrint("masternode", "CMasternodePayments::ProcessBlock() Start nHeight %d - vin %s. \n",
|
||||
nBlockHeight, activeMasternode.vin.prevout.hash.ToString());
|
||||
|
||||
// pay to the oldest MN that still had no payment but its input is old enough and it was active long enough
|
||||
int nCount = 0;
|
||||
CMasternode* pmn = mnodeman.GetNextMasternodeInQueueForPayment(nBlockHeight, true, nCount);
|
||||
|
||||
if (pmn != NULL) {
|
||||
if (pmn != nullptr) {
|
||||
LogPrint("masternode", "CMasternodePayments::ProcessBlock() Found by FindOldestNotInVec \n");
|
||||
|
||||
newWinner.nBlockHeight = nBlockHeight;
|
||||
|
||||
CScript payee = GetScriptForDestination(pmn->pubKeyCollateralAddress.GetID());
|
||||
const CScript payee = GetScriptForDestination(pmn->pubKeyCollateralAddress.GetID());
|
||||
newWinner.AddPayee(payee);
|
||||
|
||||
CTxDestination address1;
|
||||
ExtractDestination(payee, address1);
|
||||
CBitcoinAddress address2(address1);
|
||||
|
||||
LogPrint("masternode","CMasternodePayments::ProcessBlock() Winner payee %s nHeight %d. \n", address2.ToString().c_str(), newWinner.nBlockHeight);
|
||||
LogPrint("masternode", "CMasternodePayments::ProcessBlock() Winner payee %s nHeight %d. \n",
|
||||
address2.ToString().c_str(), newWinner.nBlockHeight);
|
||||
} else {
|
||||
LogPrint("masternode", "CMasternodePayments::ProcessBlock() Failed to find masternode to pay\n");
|
||||
}
|
||||
@@ -771,12 +846,14 @@ bool CMasternodePaymentWinner::SignatureValid()
|
||||
{
|
||||
CMasternode* pmn = mnodeman.Find(vinMasternode);
|
||||
|
||||
if (pmn != NULL) {
|
||||
std::string strMessage = vinMasternode.prevout.ToStringShort() + std::to_string(nBlockHeight) + payee.ToString();
|
||||
if (pmn != nullptr) {
|
||||
const std::string strMessage =
|
||||
vinMasternode.prevout.ToStringShort() + std::to_string(nBlockHeight) + payee.ToString();
|
||||
|
||||
std::string errorMessage = "";
|
||||
std::string errorMessage;
|
||||
if (!obfuScationSigner.VerifyMessage(pmn->pubKeyMasternode, vchSig, strMessage, errorMessage)) {
|
||||
return error("CMasternodePaymentWinner::SignatureValid() - Got bad Masternode address signature %s\n", vinMasternode.prevout.hash.ToString());
|
||||
return error("CMasternodePaymentWinner::SignatureValid() - Got bad Masternode address signature %s\n",
|
||||
vinMasternode.prevout.hash.ToString());
|
||||
}
|
||||
|
||||
return true;
|
||||
@@ -792,36 +869,38 @@ void CMasternodePayments::Sync(CNode* node, int nCountNeeded)
|
||||
int nHeight;
|
||||
{
|
||||
TRY_LOCK(cs_main, locked);
|
||||
if (!locked || chainActive.Tip() == NULL) return;
|
||||
if (!locked || chainActive.Tip() == nullptr) {
|
||||
return;
|
||||
}
|
||||
nHeight = chainActive.Tip()->nHeight;
|
||||
}
|
||||
|
||||
int nCount = (mnodeman.CountEnabled() * 1.25);
|
||||
if (nCountNeeded > nCount) nCountNeeded = nCount;
|
||||
int nCount = static_cast<int>(mnodeman.CountEnabled() * 1.25);
|
||||
if (nCountNeeded > nCount) {
|
||||
nCountNeeded = nCount;
|
||||
}
|
||||
|
||||
int nInvCount = 0;
|
||||
std::map<uint256, CMasternodePaymentWinner>::iterator it = mapMasternodePayeeVotes.begin();
|
||||
while (it != mapMasternodePayeeVotes.end()) {
|
||||
CMasternodePaymentWinner winner = (*it).second;
|
||||
const CMasternodePaymentWinner& winner = (*it).second;
|
||||
if (winner.nBlockHeight >= nHeight - nCountNeeded && winner.nBlockHeight <= nHeight + 20) {
|
||||
node->PushInventory(CInv(MSG_MASTERNODE_WINNER, winner.GetHash()));
|
||||
nInvCount++;
|
||||
}
|
||||
++it;
|
||||
}
|
||||
|
||||
node->PushMessage("ssc", MASTERNODE_SYNC_MNW, nInvCount);
|
||||
}
|
||||
|
||||
std::string CMasternodePayments::ToString() const
|
||||
{
|
||||
std::ostringstream info;
|
||||
|
||||
info << "Votes: " << (int)mapMasternodePayeeVotes.size() << ", Blocks: " << (int)mapMasternodeBlocks.size();
|
||||
|
||||
return info.str();
|
||||
}
|
||||
|
||||
|
||||
int CMasternodePayments::GetOldestBlock()
|
||||
{
|
||||
LOCK(cs_mapMasternodeBlocks);
|
||||
@@ -833,13 +912,12 @@ int CMasternodePayments::GetOldestBlock()
|
||||
if ((*it).first < nOldestBlock) {
|
||||
nOldestBlock = (*it).first;
|
||||
}
|
||||
it++;
|
||||
++it;
|
||||
}
|
||||
|
||||
return nOldestBlock;
|
||||
}
|
||||
|
||||
|
||||
int CMasternodePayments::GetNewestBlock()
|
||||
{
|
||||
LOCK(cs_mapMasternodeBlocks);
|
||||
@@ -851,7 +929,7 @@ int CMasternodePayments::GetNewestBlock()
|
||||
if ((*it).first > nNewestBlock) {
|
||||
nNewestBlock = (*it).first;
|
||||
}
|
||||
it++;
|
||||
++it;
|
||||
}
|
||||
|
||||
return nNewestBlock;
|
||||
|
||||
+32
-65
@@ -1,16 +1,19 @@
|
||||
// Copyright (c) 2014-2015 The Dash developers
|
||||
// Copyright (c) 2015-2019 The PIVX developers
|
||||
// Copyright (c) 2026 Agrarian Developers
|
||||
// Distributed under the MIT/X11 software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
#ifndef MASTERNODE_PAYMENTS_H
|
||||
#define MASTERNODE_PAYMENTS_H
|
||||
#ifndef AGRARIAN_MASTERNODE_PAYMENTS_H
|
||||
#define AGRARIAN_MASTERNODE_PAYMENTS_H
|
||||
|
||||
#include "key.h"
|
||||
#include "main.h"
|
||||
#include "masternode.h"
|
||||
|
||||
using namespace std;
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
extern CCriticalSection cs_vecPayments;
|
||||
extern CCriticalSection cs_mapMasternodeBlocks;
|
||||
@@ -33,8 +36,7 @@ void FillBlockPayee(CMutableTransaction& txNew, CAmount nFees, bool fProofOfStak
|
||||
|
||||
void DumpMasternodePayments();
|
||||
|
||||
/** Save Masternode Payment Data (mnpayments.dat)
|
||||
*/
|
||||
/** Save Masternode Payment Data (mnpayments.dat) */
|
||||
class CMasternodePaymentDB
|
||||
{
|
||||
private:
|
||||
@@ -63,17 +65,8 @@ public:
|
||||
CScript scriptPubKey;
|
||||
int nVotes;
|
||||
|
||||
CMasternodePayee()
|
||||
{
|
||||
scriptPubKey = CScript();
|
||||
nVotes = 0;
|
||||
}
|
||||
|
||||
CMasternodePayee(CScript payee, int nVotesIn)
|
||||
{
|
||||
scriptPubKey = payee;
|
||||
nVotes = nVotesIn;
|
||||
}
|
||||
CMasternodePayee() : scriptPubKey(CScript()), nVotes(0) {}
|
||||
CMasternodePayee(const CScript& payee, int nVotesIn) : scriptPubKey(payee), nVotes(nVotesIn) {}
|
||||
|
||||
ADD_SERIALIZE_METHODS;
|
||||
|
||||
@@ -92,18 +85,10 @@ public:
|
||||
int nBlockHeight;
|
||||
std::vector<CMasternodePayee> vecPayments;
|
||||
|
||||
CMasternodeBlockPayees()
|
||||
{
|
||||
nBlockHeight = 0;
|
||||
vecPayments.clear();
|
||||
}
|
||||
CMasternodeBlockPayees(int nBlockHeightIn)
|
||||
{
|
||||
nBlockHeight = nBlockHeightIn;
|
||||
vecPayments.clear();
|
||||
}
|
||||
CMasternodeBlockPayees() : nBlockHeight(0), vecPayments() {}
|
||||
explicit CMasternodeBlockPayees(int nBlockHeightIn) : nBlockHeight(nBlockHeightIn), vecPayments() {}
|
||||
|
||||
void AddPayee(CScript payeeIn, int nIncrement)
|
||||
void AddPayee(const CScript& payeeIn, int nIncrement)
|
||||
{
|
||||
LOCK(cs_vecPayments);
|
||||
|
||||
@@ -114,8 +99,7 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
CMasternodePayee c(payeeIn, nIncrement);
|
||||
vecPayments.push_back(c);
|
||||
vecPayments.emplace_back(payeeIn, nIncrement);
|
||||
}
|
||||
|
||||
bool GetPayee(CScript& payee)
|
||||
@@ -133,12 +117,14 @@ public:
|
||||
return (nVotes > -1);
|
||||
}
|
||||
|
||||
bool HasPayeeWithVotes(CScript payee, int nVotesReq)
|
||||
bool HasPayeeWithVotes(const CScript& payee, int nVotesReq)
|
||||
{
|
||||
LOCK(cs_vecPayments);
|
||||
|
||||
for (CMasternodePayee& p : vecPayments) {
|
||||
if (p.nVotes >= nVotesReq && p.scriptPubKey == payee) return true;
|
||||
if (p.nVotes >= nVotesReq && p.scriptPubKey == payee) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
@@ -157,29 +143,17 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
// for storing the winning payments
|
||||
// For storing the winning payments
|
||||
class CMasternodePaymentWinner
|
||||
{
|
||||
public:
|
||||
CTxIn vinMasternode;
|
||||
|
||||
int nBlockHeight;
|
||||
CScript payee;
|
||||
std::vector<unsigned char> vchSig;
|
||||
|
||||
CMasternodePaymentWinner()
|
||||
{
|
||||
nBlockHeight = 0;
|
||||
vinMasternode = CTxIn();
|
||||
payee = CScript();
|
||||
}
|
||||
|
||||
CMasternodePaymentWinner(CTxIn vinIn)
|
||||
{
|
||||
nBlockHeight = 0;
|
||||
vinMasternode = vinIn;
|
||||
payee = CScript();
|
||||
}
|
||||
CMasternodePaymentWinner() : vinMasternode(CTxIn()), nBlockHeight(0), payee(CScript()), vchSig() {}
|
||||
explicit CMasternodePaymentWinner(const CTxIn& vinIn) : vinMasternode(vinIn), nBlockHeight(0), payee(CScript()), vchSig() {}
|
||||
|
||||
uint256 GetHash()
|
||||
{
|
||||
@@ -187,7 +161,6 @@ public:
|
||||
ss << payee;
|
||||
ss << nBlockHeight;
|
||||
ss << vinMasternode.prevout;
|
||||
|
||||
return ss.GetHash();
|
||||
}
|
||||
|
||||
@@ -196,11 +169,7 @@ public:
|
||||
bool SignatureValid();
|
||||
void Relay();
|
||||
|
||||
void AddPayee(CScript payeeIn)
|
||||
{
|
||||
payee = payeeIn;
|
||||
}
|
||||
|
||||
void AddPayee(const CScript& payeeIn) { payee = payeeIn; }
|
||||
|
||||
ADD_SERIALIZE_METHODS;
|
||||
|
||||
@@ -215,7 +184,7 @@ public:
|
||||
|
||||
std::string ToString()
|
||||
{
|
||||
std::string ret = "";
|
||||
std::string ret;
|
||||
ret += vinMasternode.ToString();
|
||||
ret += ", " + std::to_string(nBlockHeight);
|
||||
ret += ", " + payee.ToString();
|
||||
@@ -228,7 +197,6 @@ public:
|
||||
// Masternode Payments Class
|
||||
// Keeps track of who should get paid for which blocks
|
||||
//
|
||||
|
||||
class CMasternodePayments
|
||||
{
|
||||
private:
|
||||
@@ -238,13 +206,12 @@ private:
|
||||
public:
|
||||
std::map<uint256, CMasternodePaymentWinner> mapMasternodePayeeVotes;
|
||||
std::map<int, CMasternodeBlockPayees> mapMasternodeBlocks;
|
||||
|
||||
// NOTE: This legacy keying scheme (outpoint.hash + outpoint.n) can theoretically collide.
|
||||
// Changing it requires a coordinated refactor of both header and implementation.
|
||||
std::map<uint256, int> mapMasternodesLastVote; // prevout.hash + prevout.n, nBlockHeight
|
||||
|
||||
CMasternodePayments()
|
||||
{
|
||||
nSyncedFromPeer = 0;
|
||||
nLastBlockHeight = 0;
|
||||
}
|
||||
CMasternodePayments() : nSyncedFromPeer(0), nLastBlockHeight(0) {}
|
||||
|
||||
void Clear()
|
||||
{
|
||||
@@ -264,18 +231,19 @@ public:
|
||||
bool IsTransactionValid(const CTransaction& txNew, int nBlockHeight);
|
||||
bool IsScheduled(CMasternode& mn, int nNotBlockHeight);
|
||||
|
||||
bool CanVote(COutPoint outMasternode, int nBlockHeight)
|
||||
bool CanVote(const COutPoint& outMasternode, int nBlockHeight)
|
||||
{
|
||||
LOCK(cs_mapMasternodePayeeVotes);
|
||||
|
||||
if (mapMasternodesLastVote.count(outMasternode.hash + outMasternode.n)) {
|
||||
if (mapMasternodesLastVote[outMasternode.hash + outMasternode.n] == nBlockHeight) {
|
||||
const uint256 key = outMasternode.hash + outMasternode.n;
|
||||
if (mapMasternodesLastVote.count(key)) {
|
||||
if (mapMasternodesLastVote[key] == nBlockHeight) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// record this masternode voted
|
||||
mapMasternodesLastVote[outMasternode.hash + outMasternode.n] = nBlockHeight;
|
||||
mapMasternodesLastVote[key] = nBlockHeight;
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -297,5 +265,4 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
#endif // AGRARIAN_MASTERNODE_PAYMENTS_H
|
||||
|
||||
+13
-15
@@ -2,6 +2,7 @@
|
||||
// Copyright (c) 2009-2014 The Bitcoin developers
|
||||
// Copyright (c) 2014-2015 The Dash developers
|
||||
// Copyright (c) 2015-2019 The PIVX developers
|
||||
// Copyright (c) 2026 Agrarian Developers
|
||||
// Distributed under the MIT/X11 software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
@@ -32,9 +33,6 @@
|
||||
|
||||
#include <boost/thread.hpp>
|
||||
#include <boost/tuple/tuple.hpp>
|
||||
|
||||
using namespace std;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// AgrarianMiner
|
||||
@@ -105,7 +103,7 @@ CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn, CWallet* pwallet,
|
||||
// Create new block
|
||||
unique_ptr<CBlockTemplate> pblocktemplate(new CBlockTemplate());
|
||||
if (!pblocktemplate.get())
|
||||
return NULL;
|
||||
return nullptr;
|
||||
CBlock* pblock = &pblocktemplate->block; // pointer for convenience
|
||||
|
||||
// Tip
|
||||
@@ -166,7 +164,7 @@ CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn, CWallet* pwallet,
|
||||
|
||||
if (!fStakeFound) {
|
||||
LogPrint("staking", "CreateNewBlock(): stake not found\n");
|
||||
return NULL;
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -214,7 +212,7 @@ CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn, CWallet* pwallet,
|
||||
continue;
|
||||
}
|
||||
|
||||
COrphan* porphan = NULL;
|
||||
COrphan* porphan = nullptr;
|
||||
double dPriority = 0;
|
||||
CAmount nTotalIn = 0;
|
||||
bool fMissingInputs = false;
|
||||
@@ -521,17 +519,17 @@ CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn, CWallet* pwallet,
|
||||
CKey key;
|
||||
if (!pwallet->GetZerocoinKey(bnSerial, key)) {
|
||||
LogPrintf("%s: failed to find zAGR with serial %s, unable to sign block\n", __func__, bnSerial.GetHex());
|
||||
return NULL;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
//Sign block with the zAGR key
|
||||
if (!SignBlockWithKey(*pblock, key)) {
|
||||
LogPrintf("BitcoinMiner(): Signing new block with zAGR key failed \n");
|
||||
return NULL;
|
||||
return nullptr;
|
||||
}
|
||||
} else if (!SignBlock(*pblock, *pwallet)) {
|
||||
LogPrintf("BitcoinMiner(): Signing new block with UTXO key failed \n");
|
||||
return NULL;
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -539,7 +537,7 @@ CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn, CWallet* pwallet,
|
||||
if (!TestBlockValidity(state, *pblock, pindexPrev, false, false)) {
|
||||
//LogPrintf("CreateNewBlock() : TestBlockValidity failed\n");
|
||||
mempool.clear();
|
||||
return NULL;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// if (pblock->IsZerocoinStake()) {
|
||||
@@ -581,7 +579,7 @@ CBlockTemplate* CreateNewBlockWithKey(CReserveKey& reservekey, CWallet* pwallet,
|
||||
{
|
||||
CPubKey pubkey;
|
||||
if (!reservekey.GetReservedKey(pubkey))
|
||||
return NULL;
|
||||
return nullptr;
|
||||
|
||||
CScript scriptPubKey = CScript() << ToByteVector(pubkey) << OP_CHECKSIG;
|
||||
return CreateNewBlock(scriptPubKey, pwallet, fProofOfStake);
|
||||
@@ -613,7 +611,7 @@ bool ProcessBlockFound(CBlock* pblock, CWallet& wallet, CReserveKey& reservekey)
|
||||
|
||||
// Process this block the same as if we had received it from another node
|
||||
CValidationState state;
|
||||
if (!ProcessNewBlock(state, NULL, pblock)) {
|
||||
if (!ProcessNewBlock(state, nullptr, pblock)) {
|
||||
if (pblock->IsZerocoinStake()) {
|
||||
pwalletMain->zagrTracker->RemovePending(pblock->vtx[1].GetHash());
|
||||
pwalletMain->zagrTracker->ListMints(true, true, true); //update the state
|
||||
@@ -831,7 +829,7 @@ void static ThreadBitcoinMiner(void* parg)
|
||||
|
||||
void GenerateBitcoins(bool fGenerate, CWallet* pwallet, int nThreads)
|
||||
{
|
||||
static boost::thread_group* minerThreads = NULL;
|
||||
static boost::thread_group* minerThreads = nullptr;
|
||||
fGenerateBitcoins = fGenerate;
|
||||
|
||||
if (nThreads < 0) {
|
||||
@@ -842,10 +840,10 @@ void GenerateBitcoins(bool fGenerate, CWallet* pwallet, int nThreads)
|
||||
nThreads = boost::thread::hardware_concurrency();
|
||||
}
|
||||
|
||||
if (minerThreads != NULL) {
|
||||
if (minerThreads != nullptr) {
|
||||
minerThreads->interrupt_all();
|
||||
delete minerThreads;
|
||||
minerThreads = NULL;
|
||||
minerThreads = nullptr;
|
||||
}
|
||||
|
||||
if (nThreads == 0 || !fGenerate)
|
||||
|
||||
+9
-7
@@ -1,14 +1,16 @@
|
||||
// Copyright (c) 2009-2010 Satoshi Nakamoto
|
||||
// Copyright (c) 2009-2014 The Bitcoin developers
|
||||
// Copyright (c) 2016-2018 The PIVX developers
|
||||
// Copyright (c) 2026 Agrarian Developers
|
||||
// Distributed under the MIT/X11 software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
#ifndef BITCOIN_MINER_H
|
||||
#define BITCOIN_MINER_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#ifndef AGRARIAN_BITCOIN_MINER_H
|
||||
#define AGRARIAN_BITCOIN_MINER_H
|
||||
#include <cstdint>
|
||||
#include <std::string>
|
||||
#include <std::vector>
|
||||
#include <memory>
|
||||
#include <utility>
|
||||
class CBlock;
|
||||
class CBlockHeader;
|
||||
class CBlockIndex;
|
||||
@@ -33,4 +35,4 @@ void BitcoinMiner(CWallet* pwallet, bool fProofOfStake);
|
||||
extern double dHashesPerSec;
|
||||
extern int64_t nHPSTimerStart;
|
||||
|
||||
#endif // BITCOIN_MINER_H
|
||||
#endif // AGRARIAN_BITCOIN_MINER_H
|
||||
+3
-2
@@ -2,6 +2,7 @@
|
||||
// Copyright (c) 2009-2014 The Bitcoin developers
|
||||
// Copyright (c) 2014-2015 The Dash developers
|
||||
// Copyright (c) 2015-2018 The PIVX developers
|
||||
// Copyright (c) 2026 Agrarian Developers
|
||||
// Distributed under the MIT/X11 software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
@@ -33,7 +34,7 @@ unsigned int GetNextWorkRequired(const CBlockIndex* pindexLast, const CBlockHead
|
||||
uint256 PastDifficultyAverage;
|
||||
uint256 PastDifficultyAveragePrev;
|
||||
|
||||
if (BlockLastSolved == NULL || BlockLastSolved->nHeight == 0 || BlockLastSolved->nHeight < PastBlocksMin) {
|
||||
if (BlockLastSolved == nullptr || BlockLastSolved->nHeight == 0 || BlockLastSolved->nHeight < PastBlocksMin) {
|
||||
return Params().ProofOfWorkLimit().GetCompact();
|
||||
}
|
||||
|
||||
@@ -85,7 +86,7 @@ unsigned int GetNextWorkRequired(const CBlockIndex* pindexLast, const CBlockHead
|
||||
}
|
||||
LastBlockTime = BlockReading->GetBlockTime();
|
||||
|
||||
if (BlockReading->pprev == NULL) {
|
||||
if (BlockReading->pprev == nullptr) {
|
||||
assert(BlockReading);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -2,14 +2,13 @@
|
||||
// Copyright (c) 2009-2014 The Bitcoin developers
|
||||
// Copyright (c) 2014-2015 The Dash developers
|
||||
// Copyright (c) 2017-2018 The PIVX developers
|
||||
// Copyright (c) 2026 Agrarian Developers
|
||||
// Distributed under the MIT/X11 software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
#ifndef BITCOIN_POW_H
|
||||
#define BITCOIN_POW_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#ifndef AGRARIAN_BITCOIN_POW_H
|
||||
#define AGRARIAN_BITCOIN_POW_H
|
||||
#include <cstdint>
|
||||
#include <cstddef>
|
||||
class CBlockHeader;
|
||||
class CBlockIndex;
|
||||
class uint256;
|
||||
@@ -29,4 +28,4 @@ unsigned int GetNextWorkRequired(const CBlockIndex* pindexLast, const CBlockHead
|
||||
bool CheckProofOfWork(uint256 hash, unsigned int nBits);
|
||||
uint256 GetBlockProof(const CBlockIndex& block);
|
||||
|
||||
#endif // BITCOIN_POW_H
|
||||
#endif // AGRARIAN_BITCOIN_POW_H
|
||||
|
||||
+8
-7
@@ -2,6 +2,7 @@
|
||||
// Copyright (c) 2009-2014 The Bitcoin developers
|
||||
// Copyright (c) 2014-2015 The Dash developers
|
||||
// Copyright (c) 2015-2019 The PIVX developers
|
||||
// Copyright (c) 2026 Agrarian Developers
|
||||
// Distributed under the MIT software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
@@ -22,7 +23,7 @@
|
||||
#include "wallet/wallet.h"
|
||||
#endif
|
||||
|
||||
#include <stdint.h>
|
||||
#include <cstdint>
|
||||
|
||||
#include <boost/assign/list_of.hpp>
|
||||
|
||||
@@ -42,7 +43,7 @@ UniValue GetNetworkHashPS(int lookup, int height)
|
||||
if (height >= 0 && height < chainActive.Height())
|
||||
pb = chainActive[height];
|
||||
|
||||
if (pb == NULL || !pb->nHeight)
|
||||
if (pb == nullptr || !pb->nHeight)
|
||||
return 0;
|
||||
|
||||
// If lookup is -1, then use blocks since last difficulty change.
|
||||
@@ -172,7 +173,7 @@ UniValue generate(const UniValue& params, bool fHelp)
|
||||
++pblock->nNonce;
|
||||
}
|
||||
CValidationState state;
|
||||
if (!ProcessNewBlock(state, NULL, pblock))
|
||||
if (!ProcessNewBlock(state, nullptr, pblock))
|
||||
throw JSONRPCError(RPC_INTERNAL_ERROR, "ProcessNewBlock, block not accepted");
|
||||
++nHeight;
|
||||
fPoS = nHeight >= Params().LAST_POW_BLOCK();
|
||||
@@ -201,7 +202,7 @@ UniValue setgenerate(const UniValue& params, bool fHelp)
|
||||
"\nTurn off generation\n" + HelpExampleCli("setgenerate", "false") +
|
||||
"\nUsing json rpc\n" + HelpExampleRpc("setgenerate", "true, 1"));
|
||||
|
||||
if (pwalletMain == NULL)
|
||||
if (pwalletMain == nullptr)
|
||||
throw JSONRPCError(RPC_METHOD_NOT_FOUND, "Method not found (disabled)");
|
||||
|
||||
if (Params().MineBlocksOnDemand())
|
||||
@@ -515,7 +516,7 @@ UniValue getblocktemplate(const UniValue& params, bool fHelp)
|
||||
if (pindexPrev != chainActive.Tip() ||
|
||||
(mempool.GetTransactionsUpdated() != nTransactionsUpdatedLast && GetTime() - nStart > 5)) {
|
||||
// Clear pindexPrev so future calls make a new block, despite any failures from here on
|
||||
pindexPrev = NULL;
|
||||
pindexPrev = nullptr;
|
||||
|
||||
// Store the chainActive.Tip() used before CreateNewBlock, to avoid races
|
||||
nTransactionsUpdatedLast = mempool.GetTransactionsUpdated();
|
||||
@@ -525,7 +526,7 @@ UniValue getblocktemplate(const UniValue& params, bool fHelp)
|
||||
// Create new block
|
||||
if (pblocktemplate) {
|
||||
delete pblocktemplate;
|
||||
pblocktemplate = NULL;
|
||||
pblocktemplate = nullptr;
|
||||
}
|
||||
CScript scriptDummy = CScript() << OP_TRUE;
|
||||
pblocktemplate = CreateNewBlock(scriptDummy, pwalletMain, false);
|
||||
@@ -691,7 +692,7 @@ UniValue submitblock(const UniValue& params, bool fHelp)
|
||||
CValidationState state;
|
||||
submitblock_StateCatcher sc(block.GetHash());
|
||||
RegisterValidationInterface(&sc);
|
||||
bool fAccepted = ProcessNewBlock(state, NULL, &block);
|
||||
bool fAccepted = ProcessNewBlock(state, nullptr, &block);
|
||||
UnregisterValidationInterface(&sc);
|
||||
if (fBlockPresent) {
|
||||
if (fAccepted && !sc.found)
|
||||
|
||||
+148
-96
@@ -1,6 +1,7 @@
|
||||
// Copyright (c) 2009-2010 Satoshi Nakamoto
|
||||
// Copyright (c) 2009-2014 The Bitcoin developers
|
||||
// Copyright (c) 2016-2019 The PIVX developers
|
||||
// Copyright (c) 2026 Agrarian Developers
|
||||
// Distributed under the MIT/X11 software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
@@ -11,45 +12,55 @@
|
||||
#include "uint256.h"
|
||||
#include "zagr/accumulators.h"
|
||||
|
||||
#include <stdint.h>
|
||||
#include <cstdint>
|
||||
#include <limits>
|
||||
#include <memory>
|
||||
#include <set>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include <boost/thread.hpp>
|
||||
|
||||
using namespace std;
|
||||
using namespace libzerocoin;
|
||||
namespace {
|
||||
|
||||
void static BatchWriteCoins(CLevelDBBatch& batch, const uint256& hash, const CCoins& coins)
|
||||
void BatchWriteCoins(CLevelDBBatch& batch, const uint256& hash, const CCoins& coins)
|
||||
{
|
||||
if (coins.IsPruned())
|
||||
batch.Erase(make_pair('c', hash));
|
||||
else
|
||||
batch.Write(make_pair('c', hash), coins);
|
||||
if (coins.IsPruned()) {
|
||||
batch.Erase(std::make_pair('c', hash));
|
||||
} else {
|
||||
batch.Write(std::make_pair('c', hash), coins);
|
||||
}
|
||||
}
|
||||
|
||||
void static BatchWriteHashBestChain(CLevelDBBatch& batch, const uint256& hash)
|
||||
void BatchWriteHashBestChain(CLevelDBBatch& batch, const uint256& hash)
|
||||
{
|
||||
batch.Write('B', hash);
|
||||
}
|
||||
|
||||
CCoinsViewDB::CCoinsViewDB(size_t nCacheSize, bool fMemory, bool fWipe) : db(GetDataDir() / "chainstate", nCacheSize, fMemory, fWipe)
|
||||
} // namespace
|
||||
|
||||
CCoinsViewDB::CCoinsViewDB(size_t nCacheSize, bool fMemory, bool fWipe)
|
||||
: db(GetDataDir() / "chainstate", nCacheSize, fMemory, fWipe)
|
||||
{
|
||||
}
|
||||
|
||||
bool CCoinsViewDB::GetCoins(const uint256& txid, CCoins& coins) const
|
||||
{
|
||||
return db.Read(make_pair('c', txid), coins);
|
||||
return db.Read(std::make_pair('c', txid), coins);
|
||||
}
|
||||
|
||||
bool CCoinsViewDB::HaveCoins(const uint256& txid) const
|
||||
{
|
||||
return db.Exists(make_pair('c', txid));
|
||||
return db.Exists(std::make_pair('c', txid));
|
||||
}
|
||||
|
||||
uint256 CCoinsViewDB::GetBestBlock() const
|
||||
{
|
||||
uint256 hashBestChain;
|
||||
if (!db.Read('B', hashBestChain))
|
||||
if (!db.Read('B', hashBestChain)) {
|
||||
return uint256(0);
|
||||
}
|
||||
return hashBestChain;
|
||||
}
|
||||
|
||||
@@ -58,39 +69,47 @@ bool CCoinsViewDB::BatchWrite(CCoinsMap& mapCoins, const uint256& hashBlock)
|
||||
CLevelDBBatch batch;
|
||||
size_t count = 0;
|
||||
size_t changed = 0;
|
||||
for (CCoinsMap::iterator it = mapCoins.begin(); it != mapCoins.end();) {
|
||||
|
||||
for (auto it = mapCoins.begin(); it != mapCoins.end();) {
|
||||
if (it->second.flags & CCoinsCacheEntry::DIRTY) {
|
||||
BatchWriteCoins(batch, it->first, it->second.coins);
|
||||
changed++;
|
||||
++changed;
|
||||
}
|
||||
count++;
|
||||
CCoinsMap::iterator itOld = it++;
|
||||
++count;
|
||||
|
||||
auto itOld = it++;
|
||||
mapCoins.erase(itOld);
|
||||
}
|
||||
if (hashBlock != uint256(0))
|
||||
BatchWriteHashBestChain(batch, hashBlock);
|
||||
|
||||
LogPrint("coindb", "Committing %u changed transactions (out of %u) to coin database...\n", (unsigned int)changed, (unsigned int)count);
|
||||
if (hashBlock != uint256(0)) {
|
||||
BatchWriteHashBestChain(batch, hashBlock);
|
||||
}
|
||||
|
||||
LogPrint("coindb",
|
||||
"Committing %u changed transactions (out of %u) to coin database...\n",
|
||||
(unsigned int)changed, (unsigned int)count);
|
||||
|
||||
return db.WriteBatch(batch);
|
||||
}
|
||||
|
||||
CBlockTreeDB::CBlockTreeDB(size_t nCacheSize, bool fMemory, bool fWipe) : CLevelDBWrapper(GetDataDir() / "blocks" / "index", nCacheSize, fMemory, fWipe)
|
||||
CBlockTreeDB::CBlockTreeDB(size_t nCacheSize, bool fMemory, bool fWipe)
|
||||
: CLevelDBWrapper(GetDataDir() / "blocks" / "index", nCacheSize, fMemory, fWipe)
|
||||
{
|
||||
}
|
||||
|
||||
bool CBlockTreeDB::WriteBlockIndex(const CDiskBlockIndex& blockindex)
|
||||
{
|
||||
return Write(make_pair('b', blockindex.GetBlockHash()), blockindex);
|
||||
return Write(std::make_pair('b', blockindex.GetBlockHash()), blockindex);
|
||||
}
|
||||
|
||||
bool CBlockTreeDB::WriteBlockFileInfo(int nFile, const CBlockFileInfo& info)
|
||||
{
|
||||
return Write(make_pair('f', nFile), info);
|
||||
return Write(std::make_pair('f', nFile), info);
|
||||
}
|
||||
|
||||
bool CBlockTreeDB::ReadBlockFileInfo(int nFile, CBlockFileInfo& info)
|
||||
{
|
||||
return Read(make_pair('f', nFile), info);
|
||||
return Read(std::make_pair('f', nFile), info);
|
||||
}
|
||||
|
||||
bool CBlockTreeDB::WriteLastBlockFile(int nFile)
|
||||
@@ -100,9 +119,9 @@ bool CBlockTreeDB::WriteLastBlockFile(int nFile)
|
||||
|
||||
bool CBlockTreeDB::WriteReindexing(bool fReindexing)
|
||||
{
|
||||
if (fReindexing)
|
||||
if (fReindexing) {
|
||||
return Write('R', '1');
|
||||
else
|
||||
}
|
||||
return Erase('R');
|
||||
}
|
||||
|
||||
@@ -119,53 +138,70 @@ bool CBlockTreeDB::ReadLastBlockFile(int& nFile)
|
||||
|
||||
bool CCoinsViewDB::GetStats(CCoinsStats& stats) const
|
||||
{
|
||||
/* It seems that there are no "const iterators" for LevelDB. Since we
|
||||
only need read operations on it, use a const-cast to get around
|
||||
that restriction. */
|
||||
boost::scoped_ptr<leveldb::Iterator> pcursor(const_cast<CLevelDBWrapper*>(&db)->NewIterator());
|
||||
// LevelDB iterators are non-const; we only read so const_cast the wrapper.
|
||||
std::unique_ptr<leveldb::Iterator> pcursor(const_cast<CLevelDBWrapper*>(&db)->NewIterator());
|
||||
pcursor->SeekToFirst();
|
||||
|
||||
CHashWriter ss(SER_GETHASH, PROTOCOL_VERSION);
|
||||
stats.hashBlock = GetBestBlock();
|
||||
ss << stats.hashBlock;
|
||||
|
||||
CAmount nTotalAmount = 0;
|
||||
|
||||
while (pcursor->Valid()) {
|
||||
boost::this_thread::interruption_point();
|
||||
try {
|
||||
leveldb::Slice slKey = pcursor->key();
|
||||
const leveldb::Slice slKey = pcursor->key();
|
||||
CDataStream ssKey(slKey.data(), slKey.data() + slKey.size(), SER_DISK, CLIENT_VERSION);
|
||||
|
||||
char chType;
|
||||
ssKey >> chType;
|
||||
|
||||
if (chType == 'c') {
|
||||
leveldb::Slice slValue = pcursor->value();
|
||||
const leveldb::Slice slValue = pcursor->value();
|
||||
CDataStream ssValue(slValue.data(), slValue.data() + slValue.size(), SER_DISK, CLIENT_VERSION);
|
||||
|
||||
CCoins coins;
|
||||
ssValue >> coins;
|
||||
|
||||
uint256 txhash;
|
||||
ssKey >> txhash;
|
||||
|
||||
ss << txhash;
|
||||
ss << VARINT(coins.nVersion);
|
||||
ss << (coins.fCoinBase ? 'c' : 'n');
|
||||
ss << VARINT(coins.nHeight);
|
||||
stats.nTransactions++;
|
||||
for (unsigned int i = 0; i < coins.vout.size(); i++) {
|
||||
|
||||
++stats.nTransactions;
|
||||
|
||||
for (unsigned int i = 0; i < coins.vout.size(); ++i) {
|
||||
const CTxOut& out = coins.vout[i];
|
||||
if (!out.IsNull()) {
|
||||
stats.nTransactionOutputs++;
|
||||
++stats.nTransactionOutputs;
|
||||
ss << VARINT(i + 1);
|
||||
ss << out;
|
||||
nTotalAmount += out.nValue;
|
||||
}
|
||||
}
|
||||
|
||||
stats.nSerializedSize += 32 + slValue.size();
|
||||
ss << VARINT(0);
|
||||
}
|
||||
|
||||
pcursor->Next();
|
||||
} catch (std::exception& e) {
|
||||
} catch (const std::exception& e) {
|
||||
return error("%s : Deserialize or I/O error - %s", __func__, e.what());
|
||||
}
|
||||
}
|
||||
stats.nHeight = mapBlockIndex.find(GetBestBlock())->second->nHeight;
|
||||
|
||||
// Height: best-effort. If best block isn't in index (e.g. empty db), return height=0.
|
||||
stats.nHeight = 0;
|
||||
const uint256 best = GetBestBlock();
|
||||
auto it = mapBlockIndex.find(best);
|
||||
if (it != mapBlockIndex.end() && it->second) {
|
||||
stats.nHeight = it->second->nHeight;
|
||||
}
|
||||
|
||||
stats.hashSerialized = ss.GetHash();
|
||||
stats.nTotalAmount = nTotalAmount;
|
||||
return true;
|
||||
@@ -173,14 +209,15 @@ bool CCoinsViewDB::GetStats(CCoinsStats& stats) const
|
||||
|
||||
bool CBlockTreeDB::ReadTxIndex(const uint256& txid, CDiskTxPos& pos)
|
||||
{
|
||||
return Read(make_pair('t', txid), pos);
|
||||
return Read(std::make_pair('t', txid), pos);
|
||||
}
|
||||
|
||||
bool CBlockTreeDB::WriteTxIndex(const std::vector<std::pair<uint256, CDiskTxPos>>& vect)
|
||||
{
|
||||
CLevelDBBatch batch;
|
||||
for (std::vector<std::pair<uint256, CDiskTxPos> >::const_iterator it = vect.begin(); it != vect.end(); it++)
|
||||
batch.Write(make_pair('t', it->first), it->second);
|
||||
for (const auto& it : vect) {
|
||||
batch.Write(std::make_pair('t', it.first), it.second);
|
||||
}
|
||||
return WriteBatch(batch);
|
||||
}
|
||||
|
||||
@@ -192,9 +229,10 @@ bool CBlockTreeDB::WriteFlag(const std::string& name, bool fValue)
|
||||
bool CBlockTreeDB::ReadFlag(const std::string& name, bool& fValue)
|
||||
{
|
||||
char ch;
|
||||
if (!Read(std::make_pair('F', name), ch))
|
||||
if (!Read(std::make_pair('F', name), ch)) {
|
||||
return false;
|
||||
fValue = ch == '1';
|
||||
}
|
||||
fValue = (ch == '1');
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -210,24 +248,30 @@ bool CBlockTreeDB::ReadInt(const std::string& name, int& nValue)
|
||||
|
||||
bool CBlockTreeDB::LoadBlockIndexGuts()
|
||||
{
|
||||
boost::scoped_ptr<leveldb::Iterator> pcursor(NewIterator());
|
||||
std::unique_ptr<leveldb::Iterator> pcursor(NewIterator());
|
||||
|
||||
CDataStream ssKeySet(SER_DISK, CLIENT_VERSION);
|
||||
ssKeySet << make_pair('b', uint256(0));
|
||||
ssKeySet << std::make_pair('b', uint256(0));
|
||||
pcursor->Seek(ssKeySet.str());
|
||||
|
||||
// Load mapBlockIndex
|
||||
uint256 nPreviousCheckpoint;
|
||||
|
||||
while (pcursor->Valid()) {
|
||||
boost::this_thread::interruption_point();
|
||||
try {
|
||||
leveldb::Slice slKey = pcursor->key();
|
||||
const leveldb::Slice slKey = pcursor->key();
|
||||
CDataStream ssKey(slKey.data(), slKey.data() + slKey.size(), SER_DISK, CLIENT_VERSION);
|
||||
|
||||
char chType;
|
||||
ssKey >> chType;
|
||||
if (chType == 'b') {
|
||||
leveldb::Slice slValue = pcursor->value();
|
||||
|
||||
if (chType != 'b') {
|
||||
break; // finished loading block index
|
||||
}
|
||||
|
||||
const leveldb::Slice slValue = pcursor->value();
|
||||
CDataStream ssValue(slValue.data(), slValue.data() + slValue.size(), SER_DISK, CLIENT_VERSION);
|
||||
|
||||
CDiskBlockIndex diskindex;
|
||||
ssValue >> diskindex;
|
||||
|
||||
@@ -247,12 +291,12 @@ bool CBlockTreeDB::LoadBlockIndexGuts()
|
||||
pindexNew->nStatus = diskindex.nStatus;
|
||||
pindexNew->nTx = diskindex.nTx;
|
||||
|
||||
//zerocoin
|
||||
// Zerocoin
|
||||
pindexNew->nAccumulatorCheckpoint = diskindex.nAccumulatorCheckpoint;
|
||||
pindexNew->mapZerocoinSupply = diskindex.mapZerocoinSupply;
|
||||
pindexNew->vMintDenominationsInBlock = diskindex.vMintDenominationsInBlock;
|
||||
|
||||
//Proof Of Stake
|
||||
// Proof of Stake
|
||||
pindexNew->nMint = diskindex.nMint;
|
||||
pindexNew->nMoneySupply = diskindex.nMoneySupply;
|
||||
pindexNew->nFlags = diskindex.nFlags;
|
||||
@@ -261,25 +305,25 @@ bool CBlockTreeDB::LoadBlockIndexGuts()
|
||||
pindexNew->nStakeTime = diskindex.nStakeTime;
|
||||
pindexNew->hashProofOfStake = diskindex.hashProofOfStake;
|
||||
|
||||
if (pindexNew->nHeight <= Params().LAST_POW_BLOCK()) {
|
||||
if (!CheckProofOfWork(pindexNew->GetBlockHash(), pindexNew->nBits))
|
||||
// Hybrid PoW+PoS: only enforce PoW proof check for PoW blocks (not just height).
|
||||
// If your codebase doesn't define IsProofOfWork(), keep the height gate or adjust at call sites.
|
||||
if (pindexNew->IsProofOfWork()) {
|
||||
if (!CheckProofOfWork(pindexNew->GetBlockHash(), pindexNew->nBits)) {
|
||||
return error("LoadBlockIndex() : CheckProofOfWork failed: %s", pindexNew->ToString());
|
||||
}
|
||||
}
|
||||
|
||||
//populate accumulator checksum map in memory
|
||||
// Populate accumulator checksum map in memory
|
||||
if (pindexNew->nAccumulatorCheckpoint != 0 && pindexNew->nAccumulatorCheckpoint != nPreviousCheckpoint) {
|
||||
// Don't load any checkpoints that exist before v2 zagr. The accumulator is invalid for v1 and not used.
|
||||
if (pindexNew->nHeight >= Params().Zerocoin_Block_V2_Start())
|
||||
if (pindexNew->nHeight >= Params().Zerocoin_Block_V2_Start()) {
|
||||
LoadAccumulatorValuesFromDB(pindexNew->nAccumulatorCheckpoint);
|
||||
|
||||
}
|
||||
nPreviousCheckpoint = pindexNew->nAccumulatorCheckpoint;
|
||||
}
|
||||
|
||||
pcursor->Next();
|
||||
} else {
|
||||
break; // if shutdown requested or finished loading block index
|
||||
}
|
||||
} catch (std::exception& e) {
|
||||
} catch (const std::exception& e) {
|
||||
return error("%s : Deserialize or I/O error - %s", __func__, e.what());
|
||||
}
|
||||
}
|
||||
@@ -287,7 +331,8 @@ bool CBlockTreeDB::LoadBlockIndexGuts()
|
||||
return true;
|
||||
}
|
||||
|
||||
CZerocoinDB::CZerocoinDB(size_t nCacheSize, bool fMemory, bool fWipe) : CLevelDBWrapper(GetDataDir() / "zerocoin", nCacheSize, fMemory, fWipe)
|
||||
CZerocoinDB::CZerocoinDB(size_t nCacheSize, bool fMemory, bool fWipe)
|
||||
: CLevelDBWrapper(GetDataDir() / "zerocoin", nCacheSize, fMemory, fWipe)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -295,10 +340,11 @@ bool CZerocoinDB::WriteCoinMintBatch(const std::vector<std::pair<libzerocoin::Pu
|
||||
{
|
||||
CLevelDBBatch batch;
|
||||
size_t count = 0;
|
||||
for (std::vector<std::pair<libzerocoin::PublicCoin, uint256> >::const_iterator it=mintInfo.begin(); it != mintInfo.end(); it++) {
|
||||
PublicCoin pubCoin = it->first;
|
||||
uint256 hash = GetPubCoinHash(pubCoin.getValue());
|
||||
batch.Write(make_pair('m', hash), it->second);
|
||||
|
||||
for (const auto& it : mintInfo) {
|
||||
const libzerocoin::PublicCoin& pubCoin = it.first;
|
||||
const uint256 hash = GetPubCoinHash(pubCoin.getValue());
|
||||
batch.Write(std::make_pair('m', hash), it.second);
|
||||
++count;
|
||||
}
|
||||
|
||||
@@ -313,25 +359,26 @@ bool CZerocoinDB::ReadCoinMint(const CBigNum& bnPubcoin, uint256& hashTx)
|
||||
|
||||
bool CZerocoinDB::ReadCoinMint(const uint256& hashPubcoin, uint256& hashTx)
|
||||
{
|
||||
return Read(make_pair('m', hashPubcoin), hashTx);
|
||||
return Read(std::make_pair('m', hashPubcoin), hashTx);
|
||||
}
|
||||
|
||||
bool CZerocoinDB::EraseCoinMint(const CBigNum& bnPubcoin)
|
||||
{
|
||||
uint256 hash = GetPubCoinHash(bnPubcoin);
|
||||
return Erase(make_pair('m', hash));
|
||||
const uint256 hash = GetPubCoinHash(bnPubcoin);
|
||||
return Erase(std::make_pair('m', hash));
|
||||
}
|
||||
|
||||
bool CZerocoinDB::WriteCoinSpendBatch(const std::vector<std::pair<libzerocoin::CoinSpend, uint256>>& spendInfo)
|
||||
{
|
||||
CLevelDBBatch batch;
|
||||
size_t count = 0;
|
||||
for (std::vector<std::pair<libzerocoin::CoinSpend, uint256> >::const_iterator it=spendInfo.begin(); it != spendInfo.end(); it++) {
|
||||
CBigNum bnSerial = it->first.getCoinSerialNumber();
|
||||
|
||||
for (const auto& it : spendInfo) {
|
||||
const CBigNum bnSerial = it.first.getCoinSerialNumber();
|
||||
CDataStream ss(SER_GETHASH, 0);
|
||||
ss << bnSerial;
|
||||
uint256 hash = Hash(ss.begin(), ss.end());
|
||||
batch.Write(make_pair('s', hash), it->second);
|
||||
const uint256 hash = Hash(ss.begin(), ss.end());
|
||||
batch.Write(std::make_pair('s', hash), it.second);
|
||||
++count;
|
||||
}
|
||||
|
||||
@@ -343,64 +390,69 @@ bool CZerocoinDB::ReadCoinSpend(const CBigNum& bnSerial, uint256& txHash)
|
||||
{
|
||||
CDataStream ss(SER_GETHASH, 0);
|
||||
ss << bnSerial;
|
||||
uint256 hash = Hash(ss.begin(), ss.end());
|
||||
|
||||
return Read(make_pair('s', hash), txHash);
|
||||
const uint256 hash = Hash(ss.begin(), ss.end());
|
||||
return Read(std::make_pair('s', hash), txHash);
|
||||
}
|
||||
|
||||
bool CZerocoinDB::ReadCoinSpend(const uint256& hashSerial, uint256& txHash)
|
||||
{
|
||||
return Read(make_pair('s', hashSerial), txHash);
|
||||
return Read(std::make_pair('s', hashSerial), txHash);
|
||||
}
|
||||
|
||||
bool CZerocoinDB::EraseCoinSpend(const CBigNum& bnSerial)
|
||||
{
|
||||
CDataStream ss(SER_GETHASH, 0);
|
||||
ss << bnSerial;
|
||||
uint256 hash = Hash(ss.begin(), ss.end());
|
||||
|
||||
return Erase(make_pair('s', hash));
|
||||
const uint256 hash = Hash(ss.begin(), ss.end());
|
||||
return Erase(std::make_pair('s', hash));
|
||||
}
|
||||
|
||||
bool CZerocoinDB::WipeCoins(std::string strType)
|
||||
bool CZerocoinDB::WipeCoins(const std::string& strType)
|
||||
{
|
||||
if (strType != "spends" && strType != "mints")
|
||||
if (strType != "spends" && strType != "mints") {
|
||||
return error("%s: did not recognize type %s", __func__, strType);
|
||||
}
|
||||
|
||||
boost::scoped_ptr<leveldb::Iterator> pcursor(NewIterator());
|
||||
std::unique_ptr<leveldb::Iterator> pcursor(NewIterator());
|
||||
|
||||
char type = (strType == "spends" ? 's' : 'm');
|
||||
const char type = (strType == "spends" ? 's' : 'm');
|
||||
CDataStream ssKeySet(SER_DISK, CLIENT_VERSION);
|
||||
ssKeySet << make_pair(type, uint256(0));
|
||||
ssKeySet << std::make_pair(type, uint256(0));
|
||||
pcursor->Seek(ssKeySet.str());
|
||||
// Load mapBlockIndex
|
||||
|
||||
std::set<uint256> setDelete;
|
||||
|
||||
while (pcursor->Valid()) {
|
||||
boost::this_thread::interruption_point();
|
||||
try {
|
||||
leveldb::Slice slKey = pcursor->key();
|
||||
const leveldb::Slice slKey = pcursor->key();
|
||||
CDataStream ssKey(slKey.data(), slKey.data() + slKey.size(), SER_DISK, CLIENT_VERSION);
|
||||
|
||||
char chType;
|
||||
ssKey >> chType;
|
||||
if (chType == type) {
|
||||
leveldb::Slice slValue = pcursor->value();
|
||||
|
||||
if (chType != type) {
|
||||
break; // finished
|
||||
}
|
||||
|
||||
const leveldb::Slice slValue = pcursor->value();
|
||||
CDataStream ssValue(slValue.data(), slValue.data() + slValue.size(), SER_DISK, CLIENT_VERSION);
|
||||
|
||||
uint256 hash;
|
||||
ssValue >> hash;
|
||||
setDelete.insert(hash);
|
||||
|
||||
pcursor->Next();
|
||||
} else {
|
||||
break; // if shutdown requested or finished loading block index
|
||||
}
|
||||
} catch (std::exception& e) {
|
||||
} catch (const std::exception& e) {
|
||||
return error("%s : Deserialize or I/O error - %s", __func__, e.what());
|
||||
}
|
||||
}
|
||||
|
||||
for (auto& hash : setDelete) {
|
||||
if (!Erase(make_pair(type, hash)))
|
||||
for (const auto& hash : setDelete) {
|
||||
if (!Erase(std::make_pair(type, hash))) {
|
||||
LogPrintf("%s: error failed to delete %s\n", __func__, hash.GetHex());
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -408,16 +460,16 @@ bool CZerocoinDB::WipeCoins(std::string strType)
|
||||
bool CZerocoinDB::WriteAccumulatorValue(const uint32_t& nChecksum, const CBigNum& bnValue)
|
||||
{
|
||||
LogPrint("zero", "%s : checksum:%d val:%s\n", __func__, nChecksum, bnValue.GetHex());
|
||||
return Write(make_pair('2', nChecksum), bnValue);
|
||||
return Write(std::make_pair('2', nChecksum), bnValue);
|
||||
}
|
||||
|
||||
bool CZerocoinDB::ReadAccumulatorValue(const uint32_t& nChecksum, CBigNum& bnValue)
|
||||
{
|
||||
return Read(make_pair('2', nChecksum), bnValue);
|
||||
return Read(std::make_pair('2', nChecksum), bnValue);
|
||||
}
|
||||
|
||||
bool CZerocoinDB::EraseAccumulatorValue(const uint32_t& nChecksum)
|
||||
{
|
||||
LogPrint("zero", "%s : checksum:%d\n", __func__, nChecksum);
|
||||
return Erase(make_pair('2', nChecksum));
|
||||
return Erase(std::make_pair('2', nChecksum));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user