Updating code
reviving this project
This commit is contained in:
+19
-6
@@ -1,16 +1,29 @@
|
|||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
# Copyright (c) 2013-2016 The Bitcoin Core developers
|
# Copyright (c) 2013-2016 The Bitcoin Core developers
|
||||||
|
# Copyright (c) 2026 Agrarian Developers
|
||||||
# Distributed under the MIT software license, see the accompanying
|
# Distributed under the MIT software license, see the accompanying
|
||||||
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||||
|
|
||||||
export LC_ALL=C
|
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"
|
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
|
export LIBTOOLIZE
|
||||||
fi
|
fi
|
||||||
which autoreconf >/dev/null || \
|
fi
|
||||||
(echo "configuration failed, please install autoconf first" && exit 1)
|
|
||||||
|
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
|
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)
|
dnl require autoconf 2.60 (AS_ECHO/AS_ECHO_N)
|
||||||
AC_PREREQ([2.60])
|
AC_PREREQ([2.60])
|
||||||
define(_CLIENT_VERSION_MAJOR, 1)
|
define(_CLIENT_VERSION_MAJOR, 1)
|
||||||
@@ -5,7 +9,7 @@ define(_CLIENT_VERSION_MINOR, 0)
|
|||||||
define(_CLIENT_VERSION_REVISION, 0)
|
define(_CLIENT_VERSION_REVISION, 0)
|
||||||
define(_CLIENT_VERSION_BUILD, 0)
|
define(_CLIENT_VERSION_BUILD, 0)
|
||||||
define(_CLIENT_VERSION_IS_RELEASE, true)
|
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_INIT([Agrarian Core],[_CLIENT_VERSION_MAJOR._CLIENT_VERSION_MINOR._CLIENT_VERSION_REVISION],[www.agrarian.org],[agrarian])
|
||||||
AC_CONFIG_SRCDIR([src/main.cpp])
|
AC_CONFIG_SRCDIR([src/main.cpp])
|
||||||
AC_CONFIG_HEADERS([src/config/agrarian-config.h])
|
AC_CONFIG_HEADERS([src/config/agrarian-config.h])
|
||||||
|
|||||||
+49
-209
@@ -1,135 +1,87 @@
|
|||||||
UNIX BUILD NOTES
|
Copyright (c) 2026 Agrarian Developers
|
||||||
====================
|
|
||||||
Some notes on how to build Agrarian Core in Unix.
|
|
||||||
|
|
||||||
Note
|
UNIX Build Notes
|
||||||
---------------------
|
|
||||||
Always use absolute paths to configure and compile Agrarian Core and the dependencies,
|
These notes describe how to build Agrarian Core on Unix-based systems.
|
||||||
For example, when specifying the path of the dependency:
|
|
||||||
|
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
|
../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
|
$BDB_PREFIX must be an absolute path. Using $(pwd) ensures an absolute
|
||||||
the usage of the absolute path.
|
path is used.
|
||||||
|
|
||||||
To Build
|
STANDARD BUILD
|
||||||
---------------------
|
|
||||||
|
|
||||||
```bash
|
|
||||||
./autogen.sh
|
./autogen.sh
|
||||||
./configure
|
./configure
|
||||||
make
|
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
|
Optional: - miniupnpc : UPnP support - libdb4.8 : Berkeley DB (wallet
|
||||||
------------|--------------------|----------------------
|
builds only) - qt : GUI support - protobuf : GUI payment protocol -
|
||||||
libssl | Crypto | Random Number Generation, Elliptic Curve Cryptography
|
libqrencode: QR code support - univalue : JSON parsing (bundled by
|
||||||
libboost | Utility | Library for threading, data structures, etc
|
default) - libzmq3 : ZMQ notifications (>= 4.0.0)
|
||||||
libevent | Networking | OS independent asynchronous networking
|
|
||||||
libgmp | Bignum Arithmetic | Precision arithmetic
|
|
||||||
|
|
||||||
Optional dependencies:
|
See dependencies.md for version details.
|
||||||
|
|
||||||
Library | Purpose | Description
|
MEMORY REQUIREMENTS
|
||||||
------------|------------------|----------------------
|
|
||||||
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)
|
|
||||||
|
|
||||||
For the versions used, see [dependencies.md](dependencies.md)
|
Minimum recommended: 1.5 GB RAM.
|
||||||
|
|
||||||
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:
|
|
||||||
|
|
||||||
|
Low memory systems:
|
||||||
|
|
||||||
./configure CXXFLAGS="--param ggc-min-expand=1 --param ggc-min-heapsize=32768"
|
./configure CXXFLAGS="--param ggc-min-expand=1 --param ggc-min-heapsize=32768"
|
||||||
|
|
||||||
|
UBUNTU / DEBIAN
|
||||||
|
|
||||||
## Linux Distribution Specific Instructions
|
Build tools:
|
||||||
|
|
||||||
### Ubuntu & Debian
|
|
||||||
|
|
||||||
#### Dependency Build Instructions
|
|
||||||
|
|
||||||
Build requirements:
|
|
||||||
|
|
||||||
sudo apt-get install build-essential libtool bsdmainutils autotools-dev autoconf pkg-config automake python3
|
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
|
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`
|
OpenSSL Note: For Ubuntu >= 18.04 or Debian >= Stretch use
|
||||||
above instead of `libssl-dev`. Agrarian Core does not support the use of OpenSSL 1.1, though compilation is still possible
|
libssl1.0-dev. OpenSSL 1.1 is not officially supported.
|
||||||
by passing `--with-incompatible-ssl` to configure (NOT RECOMMENDED!).
|
|
||||||
|
|
||||||
BerkeleyDB is required for the wallet.
|
Berkeley DB 4.8 (wallet support):
|
||||||
|
|
||||||
**For Ubuntu only:** db4.8 packages are available [here](https://launchpad.net/~bitcoin/+archive/bitcoin).
|
|
||||||
You can add the repository using the following command:
|
|
||||||
|
|
||||||
sudo apt-get install software-properties-common
|
sudo apt-get install software-properties-common
|
||||||
sudo add-apt-repository ppa:bitcoin/bitcoin
|
sudo add-apt-repository ppa:bitcoin/bitcoin
|
||||||
sudo apt-get update
|
sudo apt-get update
|
||||||
sudo apt-get install libdb4.8-dev libdb4.8++-dev
|
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
|
Optional:
|
||||||
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):
|
|
||||||
|
|
||||||
sudo apt-get install libminiupnpc-dev
|
sudo apt-get install libminiupnpc-dev
|
||||||
|
|
||||||
ZMQ dependencies (provides ZMQ API):
|
|
||||||
|
|
||||||
sudo apt-get install libzmq3-dev
|
sudo apt-get install libzmq3-dev
|
||||||
|
|
||||||
GUI dependencies:
|
Qt GUI:
|
||||||
|
|
||||||
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:
|
|
||||||
|
|
||||||
sudo apt-get install libqt5gui5 libqt5core5a libqt5dbus5 qttools5-dev qttools5-dev-tools libprotobuf-dev protobuf-compiler
|
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
|
FEDORA
|
||||||
built by default.
|
|
||||||
|
|
||||||
|
Build tools:
|
||||||
### Fedora
|
|
||||||
|
|
||||||
#### Dependency Build Instructions
|
|
||||||
|
|
||||||
Build requirements:
|
|
||||||
|
|
||||||
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
|
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
|
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
|
sudo dnf install qt5-qttools-devel qt5-qtbase-devel protobuf-devel
|
||||||
|
|
||||||
libqrencode (optional) can be installed with:
|
HARDENING
|
||||||
|
|
||||||
sudo dnf install qrencode-devel
|
Enable:
|
||||||
|
|
||||||
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:
|
|
||||||
|
|
||||||
./configure --enable-hardening
|
./configure --enable-hardening
|
||||||
|
|
||||||
|
Disable:
|
||||||
|
|
||||||
./configure --disable-hardening
|
./configure --disable-hardening
|
||||||
|
|
||||||
|
Verify:
|
||||||
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:
|
|
||||||
|
|
||||||
scanelf -e ./agrariand
|
scanelf -e ./agrariand
|
||||||
|
|
||||||
The output should contain:
|
DISABLE WALLET MODE
|
||||||
|
|
||||||
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:
|
|
||||||
|
|
||||||
./configure --disable-wallet
|
./configure --disable-wallet
|
||||||
|
|
||||||
In this case there is no dependency on Berkeley DB 4.8.
|
ARM CROSS COMPILATION
|
||||||
|
|
||||||
|
|
||||||
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:
|
|
||||||
|
|
||||||
sudo apt-get install g++-arm-linux-gnueabihf curl
|
sudo apt-get install g++-arm-linux-gnueabihf curl
|
||||||
|
|
||||||
To build executables for ARM:
|
|
||||||
|
|
||||||
cd depends
|
cd depends
|
||||||
make HOST=arm-linux-gnueabihf NO_QT=1
|
make HOST=arm-linux-gnueabihf NO_QT=1
|
||||||
cd ..
|
cd ..
|
||||||
./autogen.sh
|
./autogen.sh
|
||||||
./configure --prefix=$PWD/depends/arm-linux-gnueabihf --enable-glibc-back-compat --enable-reduce-exports LDFLAGS=-static-libstdc++
|
./configure --prefix=$PWD/depends/arm-linux-gnueabihf --enable-glibc-back-compat --enable-reduce-exports LDFLAGS=-static-libstdc++
|
||||||
make
|
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.
|
SUPPORTED BUILD METHODS
|
||||||
* 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
|
|
||||||
------------------------------------------------------------
|
------------------------------------------------------------
|
||||||
|
|
||||||
The steps below can be performed on Ubuntu (including in a VM) or WSL. The depends system
|
The following methods are known to work:
|
||||||
will also work on other Linux distributions, however the commands for
|
|
||||||
installing the toolchain will be different.
|
|
||||||
|
|
||||||
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 update
|
||||||
sudo apt upgrade
|
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
|
A host toolchain (build-essential) is required because some dependencies
|
||||||
packages (such as `protobuf`) need to build host utilities that are used in the
|
(e.g., protobuf) build host utilities during the process.
|
||||||
build process.
|
|
||||||
|
|
||||||
See [dependencies.md](dependencies.md) for a complete overview.
|
If building the Windows installer (`make deploy`):
|
||||||
|
|
||||||
If you want to build the windows installer with `make deploy` you need [NSIS](https://nsis.sourceforge.io/Main_Page):
|
|
||||||
|
|
||||||
sudo apt install nsis
|
sudo apt install nsis
|
||||||
|
|
||||||
Acquire the source in the usual way:
|
------------------------------------------------------------
|
||||||
|
SOURCE CODE
|
||||||
|
------------------------------------------------------------
|
||||||
|
|
||||||
git clone https://github.com/agrarian-project/agrarian.git
|
git clone https://github.com/agrarian-project/agrarian.git
|
||||||
cd agrarian
|
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
|
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.
|
IMPORTANT (WSL USERS)
|
||||||
This means you cannot use a directory that is located directly on the host Windows file system to perform the build.
|
------------------------------------------------------------
|
||||||
|
|
||||||
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
|
cd depends
|
||||||
make HOST=x86_64-w64-mingw32
|
make HOST=x86_64-w64-mingw32
|
||||||
cd ..
|
cd ..
|
||||||
./autogen.sh # not required when building from tarball
|
./autogen.sh
|
||||||
CONFIG_SITE=$PWD/depends/x86_64-w64-mingw32/share/config.site ./configure --prefix=/
|
CONFIG_SITE=$PWD/depends/x86_64-w64-mingw32/share/config.site \
|
||||||
|
./configure --prefix=/
|
||||||
make
|
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
|
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
|
cd depends
|
||||||
make HOST=i686-w64-mingw32
|
make HOST=i686-w64-mingw32
|
||||||
cd ..
|
cd ..
|
||||||
./autogen.sh # not required when building from tarball
|
./autogen.sh
|
||||||
CONFIG_SITE=$PWD/depends/i686-w64-mingw32/share/config.site ./configure --prefix=/
|
CONFIG_SITE=$PWD/depends/i686-w64-mingw32/share/config.site \
|
||||||
|
./configure --prefix=/
|
||||||
make
|
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
|
INSTALLATION
|
||||||
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:
|
|
||||||
|
To install into a Windows-accessible directory:
|
||||||
|
|
||||||
make install DESTDIR=/mnt/c/workspace/agrarian
|
make install DESTDIR=/mnt/c/workspace/agrarian
|
||||||
|
|
||||||
You can also create an installer using:
|
To build a Windows installer:
|
||||||
|
|
||||||
make deploy
|
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
|
Ubuntu Mingw-w64 packages include two thread models:
|
||||||
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
|
• win32 (default)
|
||||||
required to support win32 threads conflict with some of the classes in the C++11 standard library, in particular std::mutex.
|
• posix
|
||||||
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).
|
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 <windows.h> // needed for VERSIONINFO
|
||||||
#include "clientversion.h" // holds the needed client version information
|
#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 Bitcoin developers
|
||||||
// Copyright (c) 2009-2015 The Dash developers
|
// Copyright (c) 2009-2015 The Dash developers
|
||||||
// Copyright (c) 2015-2018 The PIVX developers
|
// Copyright (c) 2015-2018 The PIVX developers
|
||||||
|
// Copyright (c) 2026 Agrarian Developers
|
||||||
// Distributed under the MIT/X11 software license, see the accompanying
|
// Distributed under the MIT/X11 software license, see the accompanying
|
||||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||||
|
|
||||||
@@ -23,9 +24,6 @@
|
|||||||
#include <univalue.h>
|
#include <univalue.h>
|
||||||
|
|
||||||
#define _(x) std::string(x) /* Keep the _() around in case gettext or such will be used later to translate non-UI */
|
#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;
|
static const int DEFAULT_HTTP_CLIENT_TIMEOUT=900;
|
||||||
|
|
||||||
std::string HelpMessageCli()
|
std::string HelpMessageCli()
|
||||||
@@ -120,9 +118,8 @@ static void http_request_done(struct evhttp_request *req, void *ctx)
|
|||||||
{
|
{
|
||||||
HTTPReply* reply = static_cast<HTTPReply*>(ctx);
|
HTTPReply* reply = static_cast<HTTPReply*>(ctx);
|
||||||
|
|
||||||
if (req == NULL) {
|
if (req == nullptr) {
|
||||||
/* If req is NULL, it means an error occurred while connecting, but
|
/* 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.
|
||||||
* I'm not sure how to find out which one. We also don't really care.
|
|
||||||
*/
|
*/
|
||||||
reply->status = 0;
|
reply->status = 0;
|
||||||
return;
|
return;
|
||||||
@@ -152,14 +149,14 @@ UniValue CallRPC(const string& strMethod, const UniValue& params)
|
|||||||
throw runtime_error("cannot create event_base");
|
throw runtime_error("cannot create event_base");
|
||||||
|
|
||||||
// Synchronously look up hostname
|
// Synchronously look up hostname
|
||||||
struct evhttp_connection *evcon = evhttp_connection_base_new(base, NULL, host.c_str(), port); // TODO RAII
|
struct evhttp_connection* evcon = evhttp_connection_base_new(base, nullptr, host.c_str(), port); // TODO RAII
|
||||||
if (evcon == NULL)
|
if (evcon == nullptr)
|
||||||
throw runtime_error("create connection failed");
|
throw runtime_error("create connection failed");
|
||||||
evhttp_connection_set_timeout(evcon, GetArg("-rpcclienttimeout", DEFAULT_HTTP_CLIENT_TIMEOUT));
|
evhttp_connection_set_timeout(evcon, GetArg("-rpcclienttimeout", DEFAULT_HTTP_CLIENT_TIMEOUT));
|
||||||
|
|
||||||
HTTPReply response;
|
HTTPReply response;
|
||||||
struct evhttp_request* req = evhttp_request_new(http_request_done, (void*)&response); // TODO RAII
|
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");
|
throw runtime_error("create http request failed");
|
||||||
|
|
||||||
// Get credentials
|
// Get credentials
|
||||||
@@ -280,7 +277,7 @@ int CommandLineRPC(int argc, char* argv[])
|
|||||||
strPrint = string("error: ") + e.what();
|
strPrint = string("error: ") + e.what();
|
||||||
nRet = EXIT_FAILURE;
|
nRet = EXIT_FAILURE;
|
||||||
} catch (...) {
|
} catch (...) {
|
||||||
PrintExceptionContinue(NULL, "CommandLineRPC()");
|
PrintExceptionContinue(nullptr, "CommandLineRPC()");
|
||||||
throw;
|
throw;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -305,7 +302,7 @@ int main(int argc, char* argv[])
|
|||||||
PrintExceptionContinue(&e, "AppInitRPC()");
|
PrintExceptionContinue(&e, "AppInitRPC()");
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
} catch (...) {
|
} catch (...) {
|
||||||
PrintExceptionContinue(NULL, "AppInitRPC()");
|
PrintExceptionContinue(nullptr, "AppInitRPC()");
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -315,7 +312,7 @@ int main(int argc, char* argv[])
|
|||||||
} catch (std::exception& e) {
|
} catch (std::exception& e) {
|
||||||
PrintExceptionContinue(&e, "CommandLineRPC()");
|
PrintExceptionContinue(&e, "CommandLineRPC()");
|
||||||
} catch (...) {
|
} catch (...) {
|
||||||
PrintExceptionContinue(NULL, "CommandLineRPC()");
|
PrintExceptionContinue(nullptr, "CommandLineRPC()");
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
// Copyright (c) 2026 Agrarian Developers
|
||||||
|
|
||||||
#include <windows.h> // needed for VERSIONINFO
|
#include <windows.h> // needed for VERSIONINFO
|
||||||
#include "clientversion.h" // holds the needed client version information
|
#include "clientversion.h" // holds the needed client version information
|
||||||
|
|
||||||
|
|||||||
+4
-5
@@ -1,5 +1,6 @@
|
|||||||
// Copyright (c) 2009-2014 The Bitcoin developers
|
// Copyright (c) 2009-2014 The Bitcoin developers
|
||||||
// Copyright (c) 2015-2019 The PIVX developers
|
// Copyright (c) 2015-2019 The PIVX developers
|
||||||
|
// Copyright (c) 2026 Agrarian Developers
|
||||||
// Distributed under the MIT/X11 software license, see the accompanying
|
// Distributed under the MIT/X11 software license, see the accompanying
|
||||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||||
|
|
||||||
@@ -24,8 +25,6 @@
|
|||||||
#include <boost/assign/list_of.hpp>
|
#include <boost/assign/list_of.hpp>
|
||||||
|
|
||||||
using namespace boost::assign;
|
using namespace boost::assign;
|
||||||
using namespace std;
|
|
||||||
|
|
||||||
static bool fCreateBlank;
|
static bool fCreateBlank;
|
||||||
static map<string, UniValue> registers;
|
static map<string, UniValue> registers;
|
||||||
CClientUIInterface uiInterface;
|
CClientUIInterface uiInterface;
|
||||||
@@ -605,7 +604,7 @@ static int CommandLineRawTx(int argc, char* argv[])
|
|||||||
strPrint = string("error: ") + e.what();
|
strPrint = string("error: ") + e.what();
|
||||||
nRet = EXIT_FAILURE;
|
nRet = EXIT_FAILURE;
|
||||||
} catch (...) {
|
} catch (...) {
|
||||||
PrintExceptionContinue(NULL, "CommandLineRawTx()");
|
PrintExceptionContinue(nullptr, "CommandLineRawTx()");
|
||||||
throw;
|
throw;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -626,7 +625,7 @@ int main(int argc, char* argv[])
|
|||||||
PrintExceptionContinue(&e, "AppInitRawTx()");
|
PrintExceptionContinue(&e, "AppInitRawTx()");
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
} catch (...) {
|
} catch (...) {
|
||||||
PrintExceptionContinue(NULL, "AppInitRawTx()");
|
PrintExceptionContinue(nullptr, "AppInitRawTx()");
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -636,7 +635,7 @@ int main(int argc, char* argv[])
|
|||||||
} catch (std::exception& e) {
|
} catch (std::exception& e) {
|
||||||
PrintExceptionContinue(&e, "CommandLineRawTx()");
|
PrintExceptionContinue(&e, "CommandLineRawTx()");
|
||||||
} catch (...) {
|
} catch (...) {
|
||||||
PrintExceptionContinue(NULL, "CommandLineRawTx()");
|
PrintExceptionContinue(nullptr, "CommandLineRawTx()");
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
// Copyright (c) 2026 Agrarian Developers
|
||||||
|
|
||||||
#include <windows.h> // needed for VERSIONINFO
|
#include <windows.h> // needed for VERSIONINFO
|
||||||
#include "clientversion.h" // holds the needed client version information
|
#include "clientversion.h" // holds the needed client version information
|
||||||
|
|
||||||
|
|||||||
+4
-5
@@ -2,6 +2,7 @@
|
|||||||
// Copyright (c) 2009-2014 The Bitcoin developers
|
// Copyright (c) 2009-2014 The Bitcoin developers
|
||||||
// Copyright (c) 2014-2015 The Dash developers
|
// Copyright (c) 2014-2015 The Dash developers
|
||||||
// Copyright (c) 2015-2019 The PIVX developers
|
// Copyright (c) 2015-2019 The PIVX developers
|
||||||
|
// Copyright (c) 2026 Agrarian Developers
|
||||||
// Distributed under the MIT/X11 software license, see the accompanying
|
// Distributed under the MIT/X11 software license, see the accompanying
|
||||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||||
|
|
||||||
@@ -29,13 +30,11 @@
|
|||||||
* \section intro_sec Introduction
|
* \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),
|
* 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
|
* 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.
|
||||||
* 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.
|
* The software is a community-driven open source project, released under the MIT license.
|
||||||
*
|
*
|
||||||
* \section Navigation
|
* \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.
|
||||||
* 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;
|
static bool fDaemon;
|
||||||
@@ -144,7 +143,7 @@ bool AppInit(int argc, char* argv[])
|
|||||||
} catch (std::exception& e) {
|
} catch (std::exception& e) {
|
||||||
PrintExceptionContinue(&e, "AppInit()");
|
PrintExceptionContinue(&e, "AppInit()");
|
||||||
} catch (...) {
|
} catch (...) {
|
||||||
PrintExceptionContinue(NULL, "AppInit()");
|
PrintExceptionContinue(nullptr, "AppInit()");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!fRet) {
|
if (!fRet) {
|
||||||
|
|||||||
+41
-13
@@ -2,11 +2,14 @@
|
|||||||
// Copyright (c) 2009-2014 The Bitcoin developers
|
// Copyright (c) 2009-2014 The Bitcoin developers
|
||||||
// Copyright (c) 2014-2015 The Dash developers
|
// Copyright (c) 2014-2015 The Dash developers
|
||||||
// Copyright (c) 2015-2019 The PIVX developers
|
// Copyright (c) 2015-2019 The PIVX developers
|
||||||
|
// Copyright (c) 2026 Agrarian Developers
|
||||||
// Distributed under the MIT software license, see the accompanying
|
// Distributed under the MIT software license, see the accompanying
|
||||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||||
|
|
||||||
#include "libzerocoin/Params.h"
|
#include "libzerocoin/Params.h"
|
||||||
|
|
||||||
#include "chainparams.h"
|
#include "chainparams.h"
|
||||||
|
#include "chainparamsseeds.h"
|
||||||
#include "random.h"
|
#include "random.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
#include "utilstrencodings.h"
|
#include "utilstrencodings.h"
|
||||||
@@ -23,8 +26,6 @@ struct SeedSpec6 {
|
|||||||
uint16_t port;
|
uint16_t port;
|
||||||
};
|
};
|
||||||
|
|
||||||
#include "chainparamsseeds.h"
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Main network
|
* Main network
|
||||||
*/
|
*/
|
||||||
@@ -69,7 +70,8 @@ static const Checkpoints::CCheckpointData dataTestnet = {
|
|||||||
&mapCheckpointsTestnet,
|
&mapCheckpointsTestnet,
|
||||||
1643790201,
|
1643790201,
|
||||||
0,
|
0,
|
||||||
0};
|
0
|
||||||
|
};
|
||||||
|
|
||||||
static Checkpoints::MapCheckpoints mapCheckpointsRegtest =
|
static Checkpoints::MapCheckpoints mapCheckpointsRegtest =
|
||||||
boost::assign::map_list_of(0, uint256("0x001"));
|
boost::assign::map_list_of(0, uint256("0x001"));
|
||||||
@@ -77,24 +79,24 @@ static const Checkpoints::CCheckpointData dataRegtest = {
|
|||||||
&mapCheckpointsRegtest,
|
&mapCheckpointsRegtest,
|
||||||
1643790201,
|
1643790201,
|
||||||
0,
|
0,
|
||||||
0};
|
0
|
||||||
|
};
|
||||||
|
|
||||||
libzerocoin::ZerocoinParams* CChainParams::Zerocoin_Params(bool useModulusV1) const
|
libzerocoin::ZerocoinParams* CChainParams::Zerocoin_Params(bool useModulusV1) const
|
||||||
{
|
{
|
||||||
assert(this);
|
assert(this);
|
||||||
|
|
||||||
static CBigNum bnHexModulus = 0;
|
static CBigNum bnHexModulus = 0;
|
||||||
if (!bnHexModulus)
|
if (!bnHexModulus)
|
||||||
bnHexModulus.SetHex(zerocoinModulus);
|
bnHexModulus.SetHex(zerocoinModulus);
|
||||||
static libzerocoin::ZerocoinParams ZCParamsHex = libzerocoin::ZerocoinParams(bnHexModulus);
|
static libzerocoin::ZerocoinParams ZCParamsHex = libzerocoin::ZerocoinParams(bnHexModulus);
|
||||||
|
|
||||||
static CBigNum bnDecModulus = 0;
|
static CBigNum bnDecModulus = 0;
|
||||||
if (!bnDecModulus)
|
if (!bnDecModulus)
|
||||||
bnDecModulus.SetDec(zerocoinModulus);
|
bnDecModulus.SetDec(zerocoinModulus);
|
||||||
static libzerocoin::ZerocoinParams ZCParamsDec = libzerocoin::ZerocoinParams(bnDecModulus);
|
static libzerocoin::ZerocoinParams ZCParamsDec = libzerocoin::ZerocoinParams(bnDecModulus);
|
||||||
|
|
||||||
if (useModulusV1)
|
return useModulusV1 ? &ZCParamsHex : &ZCParamsDec;
|
||||||
return &ZCParamsHex;
|
|
||||||
|
|
||||||
return &ZCParamsDec;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class CMainParams : public CChainParams
|
class CMainParams : public CChainParams
|
||||||
@@ -130,7 +132,14 @@ public:
|
|||||||
|
|
||||||
/** Height or Time Based Activations **/
|
/** Height or Time Based Activations **/
|
||||||
nLastPOWBlock = 100;
|
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;
|
nZerocoinStartHeight = 0;
|
||||||
nZerocoinStartTime = 1643790201;
|
nZerocoinStartTime = 1643790201;
|
||||||
nBlockEnforceSerialRange = 1; // Enforce serial range starting this block
|
nBlockEnforceSerialRange = 1; // Enforce serial range starting this block
|
||||||
@@ -165,7 +174,9 @@ public:
|
|||||||
CMutableTransaction txNew;
|
CMutableTransaction txNew;
|
||||||
txNew.vin.resize(1);
|
txNew.vin.resize(1);
|
||||||
txNew.vout.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].nValue = 50 * COIN;
|
||||||
txNew.vout[0].scriptPubKey = CScript() << ParseHex("04fe3d7e5608ebba6d822948eff929c822ad35b5f8ecd00977d0e59ed67da697bd88e0ed8bd58797bde6fe6750236f5dae4cf403af0925c8339f0a91b682254b39") << OP_CHECKSIG;
|
txNew.vout[0].scriptPubKey = CScript() << ParseHex("04fe3d7e5608ebba6d822948eff929c822ad35b5f8ecd00977d0e59ed67da697bd88e0ed8bd58797bde6fe6750236f5dae4cf403af0925c8339f0a91b682254b39") << OP_CHECKSIG;
|
||||||
genesis.vtx.push_back(txNew);
|
genesis.vtx.push_back(txNew);
|
||||||
@@ -258,10 +269,18 @@ public:
|
|||||||
nMinerThreads = 0;
|
nMinerThreads = 0;
|
||||||
nTargetTimespan = 10 * 60;
|
nTargetTimespan = 10 * 60;
|
||||||
nTargetSpacing = 10 * 60;
|
nTargetSpacing = 10 * 60;
|
||||||
|
|
||||||
nLastPOWBlock = 200;
|
nLastPOWBlock = 200;
|
||||||
|
|
||||||
|
// Hybrid consensus: PoS staking permitted from block 2 in testnet as well.
|
||||||
|
nFirstPoSBlock = 2;
|
||||||
|
|
||||||
nMaturity = 15;
|
nMaturity = 15;
|
||||||
nMasternodeCountDrift = 4;
|
nMasternodeCountDrift = 4;
|
||||||
nModifierUpdateBlock = 0;
|
|
||||||
|
// Keep aligned with PoS activation in this chain.
|
||||||
|
nModifierUpdateBlock = 2;
|
||||||
|
|
||||||
nMaxMoneyOut = 43199500 * COIN;
|
nMaxMoneyOut = 43199500 * COIN;
|
||||||
nZerocoinStartHeight = 0;
|
nZerocoinStartHeight = 0;
|
||||||
nZerocoinStartTime = 1643790201;
|
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
|
nProposalEstablishmentTime = 60 * 5; // Proposals must be at least 5 mns old to make it into a test budget
|
||||||
}
|
}
|
||||||
|
|
||||||
const Checkpoints::CCheckpointData& Checkpoints() const
|
const Checkpoints::CCheckpointData& Checkpoints() const
|
||||||
{
|
{
|
||||||
return dataTestnet;
|
return dataTestnet;
|
||||||
@@ -352,10 +372,18 @@ public:
|
|||||||
nTargetTimespan = 24 * 60 * 60; // Agrarian: 1 day
|
nTargetTimespan = 24 * 60 * 60; // Agrarian: 1 day
|
||||||
nTargetSpacing = 1 * 60; // Agrarian: 1 minutes
|
nTargetSpacing = 1 * 60; // Agrarian: 1 minutes
|
||||||
bnProofOfWorkLimit = ~uint256(0) >> 1;
|
bnProofOfWorkLimit = ~uint256(0) >> 1;
|
||||||
|
|
||||||
nLastPOWBlock = 250;
|
nLastPOWBlock = 250;
|
||||||
|
|
||||||
|
// Hybrid consensus: PoS staking permitted from block 2 in regtest as well.
|
||||||
|
nFirstPoSBlock = 2;
|
||||||
|
|
||||||
nMaturity = 20;
|
nMaturity = 20;
|
||||||
nMasternodeCountDrift = 4;
|
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;
|
nMaxMoneyOut = 43199500 * COIN;
|
||||||
nZerocoinStartHeight = 300;
|
nZerocoinStartHeight = 300;
|
||||||
nBlockZerocoinV2 = 300;
|
nBlockZerocoinV2 = 300;
|
||||||
@@ -390,6 +418,7 @@ public:
|
|||||||
fSkipProofOfWorkCheck = true;
|
fSkipProofOfWorkCheck = true;
|
||||||
fTestnetToBeDeprecatedFieldRPC = false;
|
fTestnetToBeDeprecatedFieldRPC = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
const Checkpoints::CCheckpointData& Checkpoints() const
|
const Checkpoints::CCheckpointData& Checkpoints() const
|
||||||
{
|
{
|
||||||
return dataRegtest;
|
return dataRegtest;
|
||||||
@@ -434,7 +463,6 @@ public:
|
|||||||
};
|
};
|
||||||
static CUnitTestParams unitTestParams;
|
static CUnitTestParams unitTestParams;
|
||||||
|
|
||||||
|
|
||||||
static CChainParams* pCurrentParams = 0;
|
static CChainParams* pCurrentParams = 0;
|
||||||
|
|
||||||
CModifiableParams* ModifiableParams()
|
CModifiableParams* ModifiableParams()
|
||||||
|
|||||||
+14
-4
@@ -2,6 +2,7 @@
|
|||||||
// Copyright (c) 2009-2014 The Bitcoin developers
|
// Copyright (c) 2009-2014 The Bitcoin developers
|
||||||
// Copyright (c) 2014-2015 The Dash developers
|
// Copyright (c) 2014-2015 The Dash developers
|
||||||
// Copyright (c) 2015-2019 The PIVX developers
|
// Copyright (c) 2015-2019 The PIVX developers
|
||||||
|
// Copyright (c) 2026 Agrarian Developers
|
||||||
// Distributed under the MIT software license, see the accompanying
|
// Distributed under the MIT software license, see the accompanying
|
||||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||||
|
|
||||||
@@ -15,6 +16,7 @@
|
|||||||
#include "uint256.h"
|
#include "uint256.h"
|
||||||
|
|
||||||
#include "libzerocoin/Params.h"
|
#include "libzerocoin/Params.h"
|
||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
typedef unsigned char MessageStartChars[MESSAGE_START_SIZE];
|
typedef unsigned char MessageStartChars[MESSAGE_START_SIZE];
|
||||||
@@ -63,7 +65,7 @@ public:
|
|||||||
/** Make miner wait to have peers to avoid wasting work */
|
/** Make miner wait to have peers to avoid wasting work */
|
||||||
bool MiningRequiresPeers() const { return fMiningRequiresPeers; }
|
bool MiningRequiresPeers() const { return fMiningRequiresPeers; }
|
||||||
/** Headers first syncing is disabled */
|
/** Headers first syncing is disabled */
|
||||||
bool HeadersFirstSyncingActive() const { return fHeadersFirstSyncingActive; };
|
bool HeadersFirstSyncingActive() const { return fHeadersFirstSyncingActive; }
|
||||||
/** Default value for -checkmempool and -checkblockindex argument */
|
/** Default value for -checkmempool and -checkblockindex argument */
|
||||||
bool DefaultConsistencyChecks() const { return fDefaultConsistencyChecks; }
|
bool DefaultConsistencyChecks() const { return fDefaultConsistencyChecks; }
|
||||||
/** Allow mining of a min-difficulty block */
|
/** Allow mining of a min-difficulty block */
|
||||||
@@ -119,7 +121,13 @@ public:
|
|||||||
|
|
||||||
/** Height or Time Based Activations **/
|
/** Height or Time Based Activations **/
|
||||||
int ModifierUpgradeBlock() const { return nModifierUpdateBlock; }
|
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 LAST_POW_BLOCK() const { return nLastPOWBlock; }
|
||||||
|
|
||||||
int Zerocoin_StartHeight() const { return nZerocoinStartHeight; }
|
int Zerocoin_StartHeight() const { return nZerocoinStartHeight; }
|
||||||
int Zerocoin_Block_EnforceSerialRange() const { return nBlockEnforceSerialRange; }
|
int Zerocoin_Block_EnforceSerialRange() const { return nBlockEnforceSerialRange; }
|
||||||
int Zerocoin_Block_RecalculateAccumulators() const { return nBlockRecalculateAccumulators; }
|
int Zerocoin_Block_RecalculateAccumulators() const { return nBlockRecalculateAccumulators; }
|
||||||
@@ -134,7 +142,7 @@ public:
|
|||||||
CAmount GetSupplyBeforeFakeSerial() const { return nSupplyBeforeFakeSerial; }
|
CAmount GetSupplyBeforeFakeSerial() const { return nSupplyBeforeFakeSerial; }
|
||||||
|
|
||||||
int Zerocoin_Block_Double_Accumulated() const { return nBlockDoubleAccumulated; }
|
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; }
|
int Zerocoin_Block_Public_Spend_Enabled() const { return nPublicZCSpends; }
|
||||||
|
|
||||||
@@ -154,7 +162,11 @@ protected:
|
|||||||
int nToCheckBlockUpgradeMajority;
|
int nToCheckBlockUpgradeMajority;
|
||||||
int64_t nTargetTimespan;
|
int64_t nTargetTimespan;
|
||||||
int64_t nTargetSpacing;
|
int64_t nTargetSpacing;
|
||||||
|
|
||||||
|
// Hybrid PoW/PoS window controls.
|
||||||
|
int nFirstPoSBlock;
|
||||||
int nLastPOWBlock;
|
int nLastPOWBlock;
|
||||||
|
|
||||||
int nMasternodeCountDrift;
|
int nMasternodeCountDrift;
|
||||||
int nMaturity;
|
int nMaturity;
|
||||||
int nModifierUpdateBlock;
|
int nModifierUpdateBlock;
|
||||||
@@ -216,7 +228,6 @@ protected:
|
|||||||
* to test specific features more easily. Test cases should always restore the previous
|
* to test specific features more easily. Test cases should always restore the previous
|
||||||
* values after finalization.
|
* values after finalization.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
class CModifiableParams
|
class CModifiableParams
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@@ -230,7 +241,6 @@ public:
|
|||||||
virtual void setSkipProofOfWorkCheck(bool aSkipProofOfWorkCheck) = 0;
|
virtual void setSkipProofOfWorkCheck(bool aSkipProofOfWorkCheck) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return the currently selected parameters. This won't change after app startup
|
* Return the currently selected parameters. This won't change after app startup
|
||||||
* outside of the unit tests.
|
* outside of the unit tests.
|
||||||
|
|||||||
+1
-3
@@ -1,5 +1,6 @@
|
|||||||
// Copyright (c) 2012-2013 The PPCoin developers
|
// Copyright (c) 2012-2013 The PPCoin developers
|
||||||
// Copyright (c) 2015-2019 The PIVX developers
|
// Copyright (c) 2015-2019 The PIVX developers
|
||||||
|
// Copyright (c) 2026 Agrarian Developers
|
||||||
// Distributed under the MIT/X11 software license, see the accompanying
|
// Distributed under the MIT/X11 software license, see the accompanying
|
||||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||||
|
|
||||||
@@ -13,9 +14,6 @@
|
|||||||
#include "stakeinput.h"
|
#include "stakeinput.h"
|
||||||
#include "utilmoneystr.h"
|
#include "utilmoneystr.h"
|
||||||
#include "zagrchain.h"
|
#include "zagrchain.h"
|
||||||
|
|
||||||
using namespace std;
|
|
||||||
|
|
||||||
bool fTestNet = false; // Params().NetworkID() == CBaseChainParams::TESTNET;
|
bool fTestNet = false; // Params().NetworkID() == CBaseChainParams::TESTNET;
|
||||||
|
|
||||||
// Modifier interval: time to elapse before new modifier is computed
|
// 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) 2012-2013 The PPCoin developers
|
||||||
// Copyright (c) 2015-2019 The PIVX developers
|
// Copyright (c) 2015-2019 The PIVX developers
|
||||||
|
// Copyright (c) 2026 Agrarian Developers
|
||||||
// Distributed under the MIT/X11 software license, see the accompanying
|
// Distributed under the MIT/X11 software license, see the accompanying
|
||||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||||
|
#ifndef AGRARIAN_BITCOIN_KERNEL_H
|
||||||
#ifndef BITCOIN_KERNEL_H
|
#define AGRARIAN_BITCOIN_KERNEL_H
|
||||||
#define BITCOIN_KERNEL_H
|
|
||||||
|
|
||||||
#include "main.h"
|
#include "main.h"
|
||||||
#include "stakeinput.h"
|
#include "stakeinput.h"
|
||||||
|
#include <cstdint>
|
||||||
|
#include <cstddef>
|
||||||
|
#include <cstdint>
|
||||||
|
|
||||||
|
|
||||||
// MODIFIER_INTERVAL: time to elapse before new modifier is computed
|
// 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);
|
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) 2009-2014 The Bitcoin developers
|
||||||
// Copyright (c) 2014-2015 The Dash developers
|
// Copyright (c) 2014-2015 The Dash developers
|
||||||
// Copyright (c) 2015-2019 The PIVX developers
|
// Copyright (c) 2015-2019 The PIVX developers
|
||||||
|
// Copyright (c) 2026 The Agrarian developers
|
||||||
// Distributed under the MIT software license, see the accompanying
|
// Distributed under the MIT software license, see the accompanying
|
||||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||||
|
|
||||||
@@ -1986,22 +1987,40 @@ double ConvertBitsToDouble(unsigned int nBits)
|
|||||||
return dDiff;
|
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 GetBlockValue(int nHeight)
|
||||||
{
|
{
|
||||||
int64_t nSubsidy = 0;
|
return GetBlockValue(nHeight, false);
|
||||||
|
|
||||||
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 nSubsidy;
|
|
||||||
}
|
|
||||||
|
|
||||||
CAmount GetSeeSaw(const CAmount& blockValue, int nMasternodeCount, int nHeight)
|
CAmount GetSeeSaw(const CAmount& blockValue, int nMasternodeCount, int nHeight)
|
||||||
{
|
{
|
||||||
@@ -2911,14 +2930,16 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin
|
|||||||
return true;
|
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"),
|
return state.DoS(100, error("ConnectBlock() : PoS period not active"),
|
||||||
REJECT_INVALID, "PoS-early");
|
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"),
|
return state.DoS(100, error("ConnectBlock() : PoW period ended"),
|
||||||
REJECT_INVALID, "PoW-ended");
|
REJECT_INVALID, "PoW-ended");
|
||||||
|
|
||||||
bool fScriptChecks = pindex->nHeight >= Checkpoints::GetTotalBlocksEstimate();
|
bool fScriptChecks = pindex->nHeight >= Checkpoints::GetTotalBlocksEstimate();
|
||||||
|
|
||||||
// If scripts won't be checked anyways, don't bother seeing if CLTV is activated
|
// 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);
|
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.
|
//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())
|
if (block.IsProofOfWork())
|
||||||
nExpectedMint += nFees;
|
nExpectedMint += nFees;
|
||||||
|
|
||||||
|
|||||||
+35
-57
@@ -2,6 +2,7 @@
|
|||||||
// Copyright (c) 2009-2014 The Bitcoin developers
|
// Copyright (c) 2009-2014 The Bitcoin developers
|
||||||
// Copyright (c) 2014-2015 The Dash developers
|
// Copyright (c) 2014-2015 The Dash developers
|
||||||
// Copyright (c) 2015-2019 The PIVX developers
|
// Copyright (c) 2015-2019 The PIVX developers
|
||||||
|
// Copyright (c) 2026 Agrarian Developers
|
||||||
// Distributed under the MIT software license, see the accompanying
|
// Distributed under the MIT software license, see the accompanying
|
||||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||||
|
|
||||||
@@ -20,8 +21,6 @@
|
|||||||
#include "pow.h"
|
#include "pow.h"
|
||||||
#include "primitives/block.h"
|
#include "primitives/block.h"
|
||||||
#include "primitives/transaction.h"
|
#include "primitives/transaction.h"
|
||||||
#include "zagr/zerocoin.h"
|
|
||||||
#include "zagr/zagrmodule.h"
|
|
||||||
#include "script/script.h"
|
#include "script/script.h"
|
||||||
#include "script/sigcache.h"
|
#include "script/sigcache.h"
|
||||||
#include "script/standard.h"
|
#include "script/standard.h"
|
||||||
@@ -30,6 +29,8 @@
|
|||||||
#include "txmempool.h"
|
#include "txmempool.h"
|
||||||
#include "uint256.h"
|
#include "uint256.h"
|
||||||
#include "undo.h"
|
#include "undo.h"
|
||||||
|
#include "zagr/zerocoin.h"
|
||||||
|
#include "zagr/zagrmodule.h"
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <exception>
|
#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);
|
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) */
|
/** Retrieve an output (from memory pool, or from disk, if possible) */
|
||||||
bool GetOutput(const uint256& hash, unsigned int index, CValidationState& state, CTxOut& out);
|
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);
|
double ConvertBitsToDouble(unsigned int nBits);
|
||||||
int64_t GetMasternodePayment(int nHeight, int64_t blockValue, int nMasternodeCount, bool isZAGRStake);
|
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);
|
unsigned int GetNextWorkRequired(const CBlockIndex* pindexLast, const CBlockHeader* pblock, bool fProofOfStake);
|
||||||
|
|
||||||
bool ActivateBestChain(CValidationState& state, CBlock* pblock = NULL, bool fAlreadyChecked = false);
|
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. */
|
/** Flush all state, indexes and buffers to disk. */
|
||||||
void FlushStateToDisk();
|
void FlushStateToDisk();
|
||||||
|
|
||||||
|
|
||||||
/** (try to) add transaction to memory pool **/
|
/** (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);
|
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));
|
READWRITE(VARINT(nTxOffset));
|
||||||
}
|
}
|
||||||
|
|
||||||
CDiskTxPos(const CDiskBlockPos& blockIn, unsigned int nTxOffsetIn) : CDiskBlockPos(blockIn.nFile, blockIn.nPos), nTxOffset(nTxOffsetIn)
|
CDiskTxPos(const CDiskBlockPos& blockIn, unsigned int nTxOffsetIn) : CDiskBlockPos(blockIn.nFile, blockIn.nPos), nTxOffset(nTxOffsetIn) {}
|
||||||
{
|
CDiskTxPos() { SetNull(); }
|
||||||
}
|
|
||||||
|
|
||||||
CDiskTxPos()
|
|
||||||
{
|
|
||||||
SetNull();
|
|
||||||
}
|
|
||||||
|
|
||||||
void SetNull()
|
void SetNull()
|
||||||
{
|
{
|
||||||
@@ -307,22 +306,9 @@ struct CDiskTxPos : public CDiskBlockPos {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
CAmount GetMinRelayFee(const CTransaction& tx, unsigned int nBytes, bool fAllowFree);
|
CAmount GetMinRelayFee(const CTransaction& tx, unsigned int nBytes, bool fAllowFree);
|
||||||
bool MoneyRange(CAmount nValueOut);
|
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
|
* Check for standard transaction types
|
||||||
* @param[in] mapInputs Map of previous transactions that have outputs we're spending
|
* @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);
|
unsigned int GetP2SHSigOpCount(const CTransaction& tx, const CCoinsViewCache& mapInputs);
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check whether all inputs of this transaction are valid (no double spends, scripts & sigs, amounts)
|
* 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
|
* 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);
|
bool ReadFromDisk(const CDiskBlockPos& pos, const uint256& hashBlock);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Closure representing one script verification
|
* Closure representing one script verification
|
||||||
* Note that this stores references to the spending transaction
|
* Note that this stores references to the spending transaction
|
||||||
@@ -430,8 +414,15 @@ private:
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
CScriptCheck() : ptxTo(0), nIn(0), nFlags(0), cacheStore(false), error(SCRIPT_ERR_UNKNOWN_ERROR) {}
|
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),
|
CScriptCheck(const CCoins& txFromIn, const CTransaction& txToIn, unsigned int nInIn, unsigned int nFlagsIn, bool cacheIn)
|
||||||
ptxTo(&txToIn), nIn(nInIn), nFlags(nFlagsIn), cacheStore(cacheIn), error(SCRIPT_ERR_UNKNOWN_ERROR) {}
|
: scriptPubKey(txFromIn.vout[txToIn.vin[nInIn].prevout.n].scriptPubKey),
|
||||||
|
ptxTo(&txToIn),
|
||||||
|
nIn(nInIn),
|
||||||
|
nFlags(nFlagsIn),
|
||||||
|
cacheStore(cacheIn),
|
||||||
|
error(SCRIPT_ERR_UNKNOWN_ERROR)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
bool operator()();
|
bool operator()();
|
||||||
|
|
||||||
@@ -448,13 +439,11 @@ public:
|
|||||||
ScriptError GetScriptError() const { return error; }
|
ScriptError GetScriptError() const { return error; }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/** Functions for disk access for blocks */
|
/** Functions for disk access for blocks */
|
||||||
bool WriteBlockToDisk(CBlock& block, CDiskBlockPos& pos);
|
bool WriteBlockToDisk(CBlock& block, CDiskBlockPos& pos);
|
||||||
bool ReadBlockFromDisk(CBlock& block, const CDiskBlockPos& pos);
|
bool ReadBlockFromDisk(CBlock& block, const CDiskBlockPos& pos);
|
||||||
bool ReadBlockFromDisk(CBlock& block, const CBlockIndex* pindex);
|
bool ReadBlockFromDisk(CBlock& block, const CBlockIndex* pindex);
|
||||||
|
|
||||||
|
|
||||||
/** Functions for validating blocks and updating the block tree */
|
/** 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.
|
/** 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);
|
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) */
|
/** 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 */
|
/** 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 AcceptBlock(CBlock& block, CValidationState& state, CBlockIndex** pindex, CDiskBlockPos* dbp = NULL, bool fAlreadyCheckedBlock = false);
|
||||||
bool AcceptBlockHeader(const CBlockHeader& block, CValidationState& state, CBlockIndex** ppindex = NULL);
|
bool AcceptBlockHeader(const CBlockHeader& block, CValidationState& state, CBlockIndex** ppindex = NULL);
|
||||||
|
|
||||||
|
|
||||||
class CBlockFileInfo
|
class CBlockFileInfo
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@@ -522,10 +510,7 @@ public:
|
|||||||
nTimeLast = 0;
|
nTimeLast = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
CBlockFileInfo()
|
CBlockFileInfo() { SetNull(); }
|
||||||
{
|
|
||||||
SetNull();
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string ToString() const;
|
std::string ToString() const;
|
||||||
|
|
||||||
@@ -560,6 +545,7 @@ private:
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
CValidationState() : mode(MODE_VALID), nDoS(0), chRejectCode(0), corruptionPossible(false) {}
|
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)
|
bool DoS(int level, bool ret = false, unsigned char chRejectCodeIn = 0, std::string strRejectReasonIn = "", bool corruptionIn = false)
|
||||||
{
|
{
|
||||||
chRejectCode = chRejectCodeIn;
|
chRejectCode = chRejectCodeIn;
|
||||||
@@ -571,12 +557,12 @@ public:
|
|||||||
mode = MODE_INVALID;
|
mode = MODE_INVALID;
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
bool Invalid(bool ret = false,
|
|
||||||
unsigned char _chRejectCode = 0,
|
bool Invalid(bool ret = false, unsigned char _chRejectCode = 0, std::string _strRejectReason = "")
|
||||||
std::string _strRejectReason = "")
|
|
||||||
{
|
{
|
||||||
return DoS(0, ret, _chRejectCode, _strRejectReason);
|
return DoS(0, ret, _chRejectCode, _strRejectReason);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Error(std::string strRejectReasonIn = "")
|
bool Error(std::string strRejectReasonIn = "")
|
||||||
{
|
{
|
||||||
if (mode == MODE_VALID)
|
if (mode == MODE_VALID)
|
||||||
@@ -584,23 +570,17 @@ public:
|
|||||||
mode = MODE_ERROR;
|
mode = MODE_ERROR;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Abort(const std::string& msg)
|
bool Abort(const std::string& msg)
|
||||||
{
|
{
|
||||||
AbortNode(msg);
|
AbortNode(msg);
|
||||||
return Error(msg);
|
return Error(msg);
|
||||||
}
|
}
|
||||||
bool IsValid() const
|
|
||||||
{
|
bool IsValid() const { return mode == MODE_VALID; }
|
||||||
return mode == MODE_VALID;
|
bool IsInvalid() const { return mode == MODE_INVALID; }
|
||||||
}
|
bool IsError() const { return mode == MODE_ERROR; }
|
||||||
bool IsInvalid() const
|
|
||||||
{
|
|
||||||
return mode == MODE_INVALID;
|
|
||||||
}
|
|
||||||
bool IsError() const
|
|
||||||
{
|
|
||||||
return mode == MODE_ERROR;
|
|
||||||
}
|
|
||||||
bool IsInvalid(int& nDoSOut) const
|
bool IsInvalid(int& nDoSOut) const
|
||||||
{
|
{
|
||||||
if (IsInvalid()) {
|
if (IsInvalid()) {
|
||||||
@@ -609,10 +589,8 @@ public:
|
|||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
bool CorruptionPossible() const
|
|
||||||
{
|
bool CorruptionPossible() const { return corruptionPossible; }
|
||||||
return corruptionPossible;
|
|
||||||
}
|
|
||||||
unsigned char GetRejectCode() const { return chRejectCode; }
|
unsigned char GetRejectCode() const { return chRejectCode; }
|
||||||
std::string GetRejectReason() const { return strRejectReason; }
|
std::string GetRejectReason() const { return strRejectReason; }
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
// Copyright (c) 2014-2015 The Dash developers
|
// Copyright (c) 2014-2015 The Dash developers
|
||||||
// Copyright (c) 2015-2019 The PIVX developers
|
// Copyright (c) 2015-2019 The PIVX developers
|
||||||
|
// Copyright (c) 2026 Agrarian Developers
|
||||||
// Distributed under the MIT/X11 software license, see the accompanying
|
// Distributed under the MIT/X11 software license, see the accompanying
|
||||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||||
|
|
||||||
@@ -16,6 +17,17 @@
|
|||||||
#include "util.h"
|
#include "util.h"
|
||||||
#include <boost/filesystem.hpp>
|
#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;
|
CBudgetManager budget;
|
||||||
CCriticalSection cs_budget;
|
CCriticalSection cs_budget;
|
||||||
|
|
||||||
@@ -2159,7 +2171,7 @@ TrxValidationStatus CFinalizedBudget::IsTransactionValid(const CTransaction& txN
|
|||||||
|
|
||||||
bool paid = false;
|
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",
|
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(),
|
nCurrentBudgetPayment, vecBudgetPayments[nCurrentBudgetPayment].payee.ToString().c_str(), out.scriptPubKey.ToString().c_str(),
|
||||||
vecBudgetPayments[nCurrentBudgetPayment].nAmount, out.nValue);
|
vecBudgetPayments[nCurrentBudgetPayment].nAmount, out.nValue);
|
||||||
|
|||||||
+36
-33
@@ -1,10 +1,11 @@
|
|||||||
// Copyright (c) 2014-2015 The Dash developers
|
// Copyright (c) 2014-2015 The Dash developers
|
||||||
// Copyright (c) 2015-2019 The PIVX developers
|
// Copyright (c) 2015-2019 The PIVX developers
|
||||||
|
// Copyright (c) 2026 Agrarian Developers
|
||||||
// Distributed under the MIT/X11 software license, see the accompanying
|
// Distributed under the MIT/X11 software license, see the accompanying
|
||||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||||
|
|
||||||
#ifndef MASTERNODE_BUDGET_H
|
#ifndef AGRARIAN_MASTERNODE_BUDGET_H
|
||||||
#define MASTERNODE_BUDGET_H
|
#define AGRARIAN_MASTERNODE_BUDGET_H
|
||||||
|
|
||||||
#include "base58.h"
|
#include "base58.h"
|
||||||
#include "init.h"
|
#include "init.h"
|
||||||
@@ -14,9 +15,11 @@
|
|||||||
#include "net.h"
|
#include "net.h"
|
||||||
#include "sync.h"
|
#include "sync.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
|
#include <cstdint>
|
||||||
using namespace std;
|
#include <std::map>
|
||||||
|
#include <std::string>
|
||||||
|
#include <utility>
|
||||||
|
#include <std::vector>
|
||||||
extern CCriticalSection cs_budget;
|
extern CCriticalSection cs_budget;
|
||||||
|
|
||||||
class CBudgetManager;
|
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_OLD = (50 * COIN);
|
||||||
static const CAmount BUDGET_FEE_TX = (5 * COIN);
|
static const CAmount BUDGET_FEE_TX = (5 * COIN);
|
||||||
static const int64_t BUDGET_VOTE_UPDATE_MIN = 60 * 60;
|
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<CBudgetProposalBroadcast> vecImmatureBudgetProposals;
|
||||||
extern std::vector<CFinalizedBudgetBroadcast> vecImmatureFinalizedBudgets;
|
extern std::vector<CFinalizedBudgetBroadcast> vecImmatureFinalizedBudgets;
|
||||||
@@ -179,16 +182,16 @@ class CBudgetManager
|
|||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
//hold txes until they mature enough to use
|
//hold txes until they mature enough to use
|
||||||
// XX42 map<uint256, CTransaction> mapCollateral;
|
// XX42 std::map<uint256, CTransaction> mapCollateral;
|
||||||
map<uint256, uint256> mapCollateralTxids;
|
std::map<uint256, uint256> mapCollateralTxids;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// critical section to protect the inner data structures
|
// critical section to protect the inner data structures
|
||||||
mutable CCriticalSection cs;
|
mutable CCriticalSection cs;
|
||||||
|
|
||||||
// keep track of the scanning errors I've seen
|
// keep track of the scanning errors I've seen
|
||||||
map<uint256, CBudgetProposal> mapProposals;
|
std::map<uint256, CBudgetProposal> mapProposals;
|
||||||
map<uint256, CFinalizedBudget> mapFinalizedBudgets;
|
std::map<uint256, CFinalizedBudget> mapFinalizedBudgets;
|
||||||
|
|
||||||
std::map<uint256, CBudgetProposalBroadcast> mapSeenMasternodeBudgetProposals;
|
std::map<uint256, CBudgetProposalBroadcast> mapSeenMasternodeBudgetProposals;
|
||||||
std::map<uint256, CBudgetVote> mapSeenMasternodeBudgetVotes;
|
std::map<uint256, CBudgetVote> mapSeenMasternodeBudgetVotes;
|
||||||
@@ -321,7 +324,7 @@ public:
|
|||||||
std::string strBudgetName;
|
std::string strBudgetName;
|
||||||
int nBlockStart;
|
int nBlockStart;
|
||||||
std::vector<CTxBudgetPayment> vecBudgetPayments;
|
std::vector<CTxBudgetPayment> vecBudgetPayments;
|
||||||
map<uint256, CFinalizedBudgetVote> mapVotes;
|
std::map<uint256, CFinalizedBudgetVote> mapVotes;
|
||||||
uint256 nFeeTXHash;
|
uint256 nFeeTXHash;
|
||||||
int64_t nTime;
|
int64_t nTime;
|
||||||
|
|
||||||
@@ -372,7 +375,7 @@ public:
|
|||||||
void SubmitVote();
|
void SubmitVote();
|
||||||
|
|
||||||
//checks the hashes to make sure we know about them
|
//checks the hashes to make sure we know about them
|
||||||
string GetStatus();
|
std::string GetStatus();
|
||||||
|
|
||||||
uint256 GetHash()
|
uint256 GetHash()
|
||||||
{
|
{
|
||||||
@@ -413,24 +416,24 @@ public:
|
|||||||
CFinalizedBudgetBroadcast(const CFinalizedBudget& other);
|
CFinalizedBudgetBroadcast(const CFinalizedBudget& other);
|
||||||
CFinalizedBudgetBroadcast(std::string strBudgetNameIn, int nBlockStartIn, std::vector<CTxBudgetPayment> vecBudgetPaymentsIn, uint256 nFeeTXHashIn);
|
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)
|
// enable ADL (not necessary in our case, but good practice)
|
||||||
using std::swap;
|
using std::swap;
|
||||||
|
|
||||||
// by swapping the members of two classes,
|
// by swapping the members of two classes,
|
||||||
// the two classes are effectively swapped
|
// the two classes are effectively swapped
|
||||||
swap(first.strBudgetName, second.strBudgetName);
|
std::swap(first.strBudgetName, second.strBudgetName);
|
||||||
swap(first.nBlockStart, second.nBlockStart);
|
std::swap(first.nBlockStart, second.nBlockStart);
|
||||||
first.mapVotes.swap(second.mapVotes);
|
first.mapVotes.std::swap(second.mapVotes);
|
||||||
first.vecBudgetPayments.swap(second.vecBudgetPayments);
|
first.vecBudgetPayments.std::swap(second.vecBudgetPayments);
|
||||||
swap(first.nFeeTXHash, second.nFeeTXHash);
|
std::swap(first.nFeeTXHash, second.nFeeTXHash);
|
||||||
swap(first.nTime, second.nTime);
|
std::swap(first.nTime, second.nTime);
|
||||||
}
|
}
|
||||||
|
|
||||||
CFinalizedBudgetBroadcast& operator=(CFinalizedBudgetBroadcast from)
|
CFinalizedBudgetBroadcast& operator=(CFinalizedBudgetBroadcast from)
|
||||||
{
|
{
|
||||||
swap(*this, from);
|
std::swap(*this, from);
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -478,7 +481,7 @@ public:
|
|||||||
int64_t nTime;
|
int64_t nTime;
|
||||||
uint256 nFeeTXHash;
|
uint256 nFeeTXHash;
|
||||||
|
|
||||||
map<uint256, CBudgetVote> mapVotes;
|
std::map<uint256, CBudgetVote> mapVotes;
|
||||||
//cache object
|
//cache object
|
||||||
|
|
||||||
CBudgetProposal();
|
CBudgetProposal();
|
||||||
@@ -559,27 +562,27 @@ public:
|
|||||||
CBudgetProposalBroadcast(const CBudgetProposalBroadcast& other) : CBudgetProposal(other) {}
|
CBudgetProposalBroadcast(const CBudgetProposalBroadcast& other) : CBudgetProposal(other) {}
|
||||||
CBudgetProposalBroadcast(std::string strProposalNameIn, std::string strURLIn, int nPaymentCount, CScript addressIn, CAmount nAmountIn, int nBlockStartIn, uint256 nFeeTXHashIn);
|
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)
|
// enable ADL (not necessary in our case, but good practice)
|
||||||
using std::swap;
|
using std::swap;
|
||||||
|
|
||||||
// by swapping the members of two classes,
|
// by swapping the members of two classes,
|
||||||
// the two classes are effectively swapped
|
// the two classes are effectively swapped
|
||||||
swap(first.strProposalName, second.strProposalName);
|
std::swap(first.strProposalName, second.strProposalName);
|
||||||
swap(first.nBlockStart, second.nBlockStart);
|
std::swap(first.nBlockStart, second.nBlockStart);
|
||||||
swap(first.strURL, second.strURL);
|
std::swap(first.strURL, second.strURL);
|
||||||
swap(first.nBlockEnd, second.nBlockEnd);
|
std::swap(first.nBlockEnd, second.nBlockEnd);
|
||||||
swap(first.nAmount, second.nAmount);
|
std::swap(first.nAmount, second.nAmount);
|
||||||
swap(first.address, second.address);
|
std::swap(first.address, second.address);
|
||||||
swap(first.nTime, second.nTime);
|
std::swap(first.nTime, second.nTime);
|
||||||
swap(first.nFeeTXHash, second.nFeeTXHash);
|
std::swap(first.nFeeTXHash, second.nFeeTXHash);
|
||||||
first.mapVotes.swap(second.mapVotes);
|
first.mapVotes.std::swap(second.mapVotes);
|
||||||
}
|
}
|
||||||
|
|
||||||
CBudgetProposalBroadcast& operator=(CBudgetProposalBroadcast from)
|
CBudgetProposalBroadcast& operator=(CBudgetProposalBroadcast from)
|
||||||
{
|
{
|
||||||
swap(*this, from);
|
std::swap(*this, from);
|
||||||
return *this;
|
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) 2014-2015 The Dash developers
|
||||||
// Copyright (c) 2015-2019 The PIVX developers
|
// Copyright (c) 2015-2019 The PIVX developers
|
||||||
|
// Copyright (c) 2026 Agrarian Developers
|
||||||
// Distributed under the MIT/X11 software license, see the accompanying
|
// Distributed under the MIT/X11 software license, see the accompanying
|
||||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||||
|
|
||||||
#include "masternode-payments.h"
|
#include "masternode-payments.h"
|
||||||
|
|
||||||
#include "addrman.h"
|
#include "addrman.h"
|
||||||
#include "chainparams.h"
|
#include "chainparams.h"
|
||||||
#include "masternode-budget.h"
|
#include "masternode-budget.h"
|
||||||
@@ -14,8 +16,15 @@
|
|||||||
#include "sync.h"
|
#include "sync.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
#include "utilmoneystr.h"
|
#include "utilmoneystr.h"
|
||||||
|
|
||||||
#include <boost/filesystem.hpp>
|
#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 */
|
/** Object for who's going to get paid on which blocks */
|
||||||
CMasternodePayments masternodePayments;
|
CMasternodePayments masternodePayments;
|
||||||
|
|
||||||
@@ -23,6 +32,26 @@ CCriticalSection cs_vecPayments;
|
|||||||
CCriticalSection cs_mapMasternodeBlocks;
|
CCriticalSection cs_mapMasternodeBlocks;
|
||||||
CCriticalSection cs_mapMasternodePayeeVotes;
|
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
|
// CMasternodePaymentDB
|
||||||
//
|
//
|
||||||
@@ -35,61 +64,81 @@ CMasternodePaymentDB::CMasternodePaymentDB()
|
|||||||
|
|
||||||
bool CMasternodePaymentDB::Write(const CMasternodePayments& objToSave)
|
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
|
// serialize, checksum data up to that point, then append checksum
|
||||||
CDataStream ssObj(SER_DISK, CLIENT_VERSION);
|
CDataStream ssObj(SER_DISK, CLIENT_VERSION);
|
||||||
ssObj << strMagicMessage; // masternode cache file specific magic message
|
ssObj << strMagicMessage; // masternode cache file specific magic message
|
||||||
ssObj << FLATDATA(Params().MessageStart()); // network specific magic number
|
ssObj << FLATDATA(Params().MessageStart()); // network specific magic number
|
||||||
ssObj << objToSave;
|
ssObj << objToSave;
|
||||||
uint256 hash = Hash(ssObj.begin(), ssObj.end());
|
const uint256 hash = Hash(ssObj.begin(), ssObj.end());
|
||||||
ssObj << hash;
|
ssObj << hash;
|
||||||
|
|
||||||
// open output file, and associate with CAutoFile
|
// open output file, and associate with CAutoFile
|
||||||
FILE* file = fopen(pathDB.string().c_str(), "wb");
|
FILE* file = std::fopen(pathDB.string().c_str(), "wb");
|
||||||
CAutoFile fileout(file, SER_DISK, CLIENT_VERSION);
|
if (file == nullptr) {
|
||||||
if (fileout.IsNull())
|
|
||||||
return error("%s : Failed to open file %s", __func__, pathDB.string());
|
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
|
// Write and commit header, data
|
||||||
try {
|
try {
|
||||||
fileout << ssObj;
|
fileout << ssObj;
|
||||||
} catch (std::exception& e) {
|
} catch (const std::exception& e) {
|
||||||
return error("%s : Serialize or I/O error - %s", __func__, e.what());
|
return error("%s : Serialize or I/O error - %s", __func__, e.what());
|
||||||
}
|
}
|
||||||
fileout.fclose();
|
fileout.fclose();
|
||||||
|
|
||||||
LogPrint("masternode", "Written info to mnpayments.dat %dms\n", GetTimeMillis() - nStart);
|
LogPrint("masternode", "Written info to mnpayments.dat %dms\n", GetTimeMillis() - nStart);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
CMasternodePaymentDB::ReadResult CMasternodePaymentDB::Read(CMasternodePayments& objToLoad, bool fDryRun)
|
CMasternodePaymentDB::ReadResult CMasternodePaymentDB::Read(CMasternodePayments& objToLoad, bool fDryRun)
|
||||||
{
|
{
|
||||||
int64_t nStart = GetTimeMillis();
|
const int64_t nStart = GetTimeMillis();
|
||||||
|
|
||||||
// open input file, and associate with CAutoFile
|
// 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);
|
CAutoFile filein(file, SER_DISK, CLIENT_VERSION);
|
||||||
if (filein.IsNull()) {
|
if (filein.IsNull()) {
|
||||||
error("%s : Failed to open file %s", __func__, pathDB.string());
|
error("%s : Failed to open file %s", __func__, pathDB.string());
|
||||||
return FileError;
|
return FileError;
|
||||||
}
|
}
|
||||||
|
|
||||||
// use file size to size memory buffer
|
int fileSize = 0;
|
||||||
int fileSize = boost::filesystem::file_size(pathDB);
|
try {
|
||||||
int dataSize = fileSize - sizeof(uint256);
|
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
|
// Don't try to resize to a negative number if file is small
|
||||||
if (dataSize < 0)
|
if (dataSize < 0) {
|
||||||
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;
|
uint256 hashIn;
|
||||||
|
|
||||||
// read data and checksum from file
|
// read data and checksum from file
|
||||||
try {
|
try {
|
||||||
filein.read((char*)&vchData[0], dataSize);
|
if (dataSize > 0) {
|
||||||
|
filein.read(reinterpret_cast<char*>(&vchData[0]), dataSize);
|
||||||
|
}
|
||||||
filein >> hashIn;
|
filein >> hashIn;
|
||||||
} catch (std::exception& e) {
|
} catch (const std::exception& e) {
|
||||||
error("%s : Deserialize or I/O error - %s", __func__, e.what());
|
error("%s : Deserialize or I/O error - %s", __func__, e.what());
|
||||||
return HashReadError;
|
return HashReadError;
|
||||||
}
|
}
|
||||||
@@ -98,7 +147,7 @@ CMasternodePaymentDB::ReadResult CMasternodePaymentDB::Read(CMasternodePayments&
|
|||||||
CDataStream ssObj(vchData, SER_DISK, CLIENT_VERSION);
|
CDataStream ssObj(vchData, SER_DISK, CLIENT_VERSION);
|
||||||
|
|
||||||
// verify stored checksum matches input data
|
// verify stored checksum matches input data
|
||||||
uint256 hashTmp = Hash(ssObj.begin(), ssObj.end());
|
const uint256 hashTmp = Hash(ssObj.begin(), ssObj.end());
|
||||||
if (hashIn != hashTmp) {
|
if (hashIn != hashTmp) {
|
||||||
error("%s : Checksum mismatch, data corrupted", __func__);
|
error("%s : Checksum mismatch, data corrupted", __func__);
|
||||||
return IncorrectHash;
|
return IncorrectHash;
|
||||||
@@ -112,23 +161,22 @@ CMasternodePaymentDB::ReadResult CMasternodePaymentDB::Read(CMasternodePayments&
|
|||||||
|
|
||||||
// ... verify the message matches predefined one
|
// ... verify the message matches predefined one
|
||||||
if (strMagicMessage != strMagicMessageTmp) {
|
if (strMagicMessage != strMagicMessageTmp) {
|
||||||
error("%s : Invalid masternode payement cache magic message", __func__);
|
error("%s : Invalid masternode payment cache magic message", __func__);
|
||||||
return IncorrectMagicMessage;
|
return IncorrectMagicMessage;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// de-serialize file header (network specific magic number) and ..
|
// de-serialize file header (network specific magic number) and ..
|
||||||
ssObj >> FLATDATA(pchMsgTmp);
|
ssObj >> FLATDATA(pchMsgTmp);
|
||||||
|
|
||||||
// ... verify the network matches ours
|
// ... 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__);
|
error("%s : Invalid network magic number", __func__);
|
||||||
return IncorrectMagicNumber;
|
return IncorrectMagicNumber;
|
||||||
}
|
}
|
||||||
|
|
||||||
// de-serialize data into CMasternodePayments object
|
// de-serialize data into CMasternodePayments object
|
||||||
ssObj >> objToLoad;
|
ssObj >> objToLoad;
|
||||||
} catch (std::exception& e) {
|
} catch (const std::exception& e) {
|
||||||
objToLoad.Clear();
|
objToLoad.Clear();
|
||||||
error("%s : Deserialize or I/O error - %s", __func__, e.what());
|
error("%s : Deserialize or I/O error - %s", __func__, e.what());
|
||||||
return IncorrectFormat;
|
return IncorrectFormat;
|
||||||
@@ -136,6 +184,7 @@ CMasternodePaymentDB::ReadResult CMasternodePaymentDB::Read(CMasternodePayments&
|
|||||||
|
|
||||||
LogPrint("masternode", "Loaded info from mnpayments.dat %dms\n", GetTimeMillis() - nStart);
|
LogPrint("masternode", "Loaded info from mnpayments.dat %dms\n", GetTimeMillis() - nStart);
|
||||||
LogPrint("masternode", " %s\n", objToLoad.ToString());
|
LogPrint("masternode", " %s\n", objToLoad.ToString());
|
||||||
|
|
||||||
if (!fDryRun) {
|
if (!fDryRun) {
|
||||||
LogPrint("masternode", "Masternode payments manager - cleaning....\n");
|
LogPrint("masternode", "Masternode payments manager - cleaning....\n");
|
||||||
objToLoad.CleanPaymentList();
|
objToLoad.CleanPaymentList();
|
||||||
@@ -148,61 +197,63 @@ CMasternodePaymentDB::ReadResult CMasternodePaymentDB::Read(CMasternodePayments&
|
|||||||
|
|
||||||
void DumpMasternodePayments()
|
void DumpMasternodePayments()
|
||||||
{
|
{
|
||||||
int64_t nStart = GetTimeMillis();
|
const int64_t nStart = GetTimeMillis();
|
||||||
|
|
||||||
CMasternodePaymentDB paymentdb;
|
CMasternodePaymentDB paymentdb;
|
||||||
CMasternodePayments tempPayments;
|
CMasternodePayments tempPayments;
|
||||||
|
|
||||||
LogPrint("masternode", "Verifying mnpayments.dat format...\n");
|
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
|
// there was an error and it was not an error on file opening => do not proceed
|
||||||
if (readResult == CMasternodePaymentDB::FileError)
|
if (readResult == CMasternodePaymentDB::FileError) {
|
||||||
LogPrint("masternode","Missing budgets file - mnpayments.dat, will try to recreate\n");
|
LogPrint("masternode", "Missing payments file - mnpayments.dat, will try to recreate\n");
|
||||||
else if (readResult != CMasternodePaymentDB::Ok) {
|
} else if (readResult != CMasternodePaymentDB::Ok) {
|
||||||
LogPrint("masternode", "Error reading mnpayments.dat: ");
|
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");
|
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");
|
LogPrint("masternode", "file format is unknown or invalid, please fix it manually\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
LogPrint("masternode","Writting info to mnpayments.dat...\n");
|
|
||||||
|
LogPrint("masternode", "Writing info to mnpayments.dat...\n");
|
||||||
paymentdb.Write(masternodePayments);
|
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)
|
bool IsBlockValueValid(const CBlock& block, CAmount nExpectedValue, CAmount nMinted)
|
||||||
{
|
{
|
||||||
CBlockIndex* pindexPrev = chainActive.Tip();
|
CBlockIndex* pindexPrev = chainActive.Tip();
|
||||||
if (pindexPrev == NULL) return true;
|
if (pindexPrev == nullptr) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
int nHeight = 0;
|
int nHeight = 0;
|
||||||
if (pindexPrev->GetBlockHash() == block.hashPrevBlock) {
|
if (pindexPrev->GetBlockHash() == block.hashPrevBlock) {
|
||||||
nHeight = pindexPrev->nHeight + 1;
|
nHeight = pindexPrev->nHeight + 1;
|
||||||
} else { // out of order
|
} else { // out of order
|
||||||
BlockMap::iterator mi = mapBlockIndex.find(block.hashPrevBlock);
|
BlockMap::iterator mi = mapBlockIndex.find(block.hashPrevBlock);
|
||||||
if (mi != mapBlockIndex.end() && (*mi).second)
|
if (mi != mapBlockIndex.end() && (*mi).second) {
|
||||||
nHeight = (*mi).second->nHeight + 1;
|
nHeight = (*mi).second->nHeight + 1;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (nHeight == 0) {
|
if (nHeight == 0) {
|
||||||
LogPrint("masternode", "IsBlockValueValid() : WARNING: Couldn't find previous block\n");
|
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
|
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
|
// super blocks will always be on these blocks, max 100 per budgeting
|
||||||
if (nHeight % Params().GetBudgetCycleBlocks() < 100) {
|
if (nHeight % Params().GetBudgetCycleBlocks() < 100) {
|
||||||
return true;
|
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
|
// are these blocks even enabled
|
||||||
if (!IsSporkActive(SPORK_13_ENABLE_SUPERBLOCKS)) {
|
if (!IsSporkActive(SPORK_13_ENABLE_SUPERBLOCKS)) {
|
||||||
@@ -212,14 +263,9 @@ bool IsBlockValueValid(const CBlock& block, CAmount nExpectedValue, CAmount nMin
|
|||||||
if (budget.IsBudgetPaymentBlock(nHeight)) {
|
if (budget.IsBudgetPaymentBlock(nHeight)) {
|
||||||
// the value of the block is evaluated in CheckBlock
|
// the value of the block is evaluated in CheckBlock
|
||||||
return true;
|
return true;
|
||||||
} else {
|
|
||||||
if (nMinted > nExpectedValue) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return nMinted <= nExpectedValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IsBlockPayeeValid(const CBlock& block, int nBlockHeight)
|
bool IsBlockPayeeValid(const CBlock& block, int nBlockHeight)
|
||||||
@@ -231,7 +277,7 @@ bool IsBlockPayeeValid(const CBlock& block, int nBlockHeight)
|
|||||||
return true;
|
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
|
// check if it's a budget block
|
||||||
if (IsSporkActive(SPORK_13_ENABLE_SUPERBLOCKS)) {
|
if (IsSporkActive(SPORK_13_ENABLE_SUPERBLOCKS)) {
|
||||||
@@ -243,38 +289,43 @@ bool IsBlockPayeeValid(const CBlock& block, int nBlockHeight)
|
|||||||
|
|
||||||
if (transactionStatus == TrxValidationStatus::InValid) {
|
if (transactionStatus == TrxValidationStatus::InValid) {
|
||||||
LogPrint("masternode", "Invalid budget payment detected %s\n", txNew.ToString().c_str());
|
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;
|
return false;
|
||||||
|
}
|
||||||
LogPrint("masternode", "Budget enforcement is disabled, accepting block\n");
|
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
|
// If we end here the transaction was either InValid and Budget enforcement is disabled, or
|
||||||
// a double budget payment (status = TrxValidationStatus::DoublePayment) was detected, or no/not enough masternode
|
// a double budget payment (DoublePayment) was detected, or no/not enough masternode
|
||||||
// votes (status = TrxValidationStatus::VoteThreshold) for a finalized budget were found
|
// votes (VoteThreshold) for a finalized budget were found.
|
||||||
// In all cases a masternode will get the payment for this block
|
// In all cases a masternode will get the payment for this block.
|
||||||
|
|
||||||
// check for masternode payee
|
// check for masternode payee
|
||||||
if (masternodePayments.IsTransactionValid(txNew, nBlockHeight))
|
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;
|
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)
|
void FillBlockPayee(CMutableTransaction& txNew, CAmount nFees, bool fProofOfStake, bool fZAGRStake)
|
||||||
{
|
{
|
||||||
CBlockIndex* pindexPrev = chainActive.Tip();
|
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);
|
budget.FillBlockPayee(txNew, nFees, fProofOfStake);
|
||||||
} else {
|
} else {
|
||||||
masternodePayments.FillBlockPayee(txNew, nFees, fProofOfStake, fZAGRStake);
|
masternodePayments.FillBlockPayee(txNew, nFees, fProofOfStake, fZAGRStake);
|
||||||
@@ -285,20 +336,21 @@ std::string GetRequiredPaymentsString(int nBlockHeight)
|
|||||||
{
|
{
|
||||||
if (IsSporkActive(SPORK_13_ENABLE_SUPERBLOCKS) && budget.IsBudgetPaymentBlock(nBlockHeight)) {
|
if (IsSporkActive(SPORK_13_ENABLE_SUPERBLOCKS) && budget.IsBudgetPaymentBlock(nBlockHeight)) {
|
||||||
return budget.GetRequiredPaymentsString(nBlockHeight);
|
return budget.GetRequiredPaymentsString(nBlockHeight);
|
||||||
} else {
|
}
|
||||||
return masternodePayments.GetRequiredPaymentsString(nBlockHeight);
|
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();
|
CBlockIndex* pindexPrev = chainActive.Tip();
|
||||||
if (!pindexPrev) return;
|
if (!pindexPrev) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
bool hasPayment = true;
|
bool hasPayment = true;
|
||||||
CScript payee;
|
CScript payee;
|
||||||
|
|
||||||
//spork
|
// spork / schedule
|
||||||
if (!masternodePayments.GetBlockPayee(pindexPrev->nHeight + 1, payee)) {
|
if (!masternodePayments.GetBlockPayee(pindexPrev->nHeight + 1, payee)) {
|
||||||
// no masternode detected
|
// no masternode detected
|
||||||
CMasternode* winningNode = mnodeman.GetCurrentMasterNode(1);
|
CMasternode* winningNode = mnodeman.GetCurrentMasterNode(1);
|
||||||
@@ -310,24 +362,29 @@ void CMasternodePayments::FillBlockPayee(CMutableTransaction& txNew, int64_t nFe
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
CAmount blockValue = GetBlockValue(pindexPrev->nHeight);
|
const int payHeight = pindexPrev->nHeight + 1;
|
||||||
CAmount masternodePayment = GetMasternodePayment(pindexPrev->nHeight, blockValue, 0, fZAGRStake);
|
const CAmount blockValue = GetBlockValue(payHeight);
|
||||||
|
const CAmount masternodePayment = GetMasternodePayment(payHeight, blockValue, 0, fZAGRStake);
|
||||||
|
|
||||||
if (hasPayment) {
|
if (hasPayment) {
|
||||||
if (fProofOfStake) {
|
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
|
* Stake reward can be split into many different outputs, so we must
|
||||||
* use vout.size() to align with several different cases.
|
* 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.resize(i + 1);
|
||||||
txNew.vout[i].scriptPubKey = payee;
|
txNew.vout[i].scriptPubKey = payee;
|
||||||
txNew.vout[i].nValue = masternodePayment;
|
txNew.vout[i].nValue = masternodePayment;
|
||||||
|
|
||||||
// subtract mn payment from the stake reward
|
// 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;
|
txNew.vout[i - 1].nValue -= masternodePayment;
|
||||||
|
}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
txNew.vout.resize(2);
|
txNew.vout.resize(2);
|
||||||
txNew.vout[1].scriptPubKey = payee;
|
txNew.vout[1].scriptPubKey = payee;
|
||||||
@@ -347,20 +404,20 @@ int CMasternodePayments::GetMinMasternodePaymentsProto()
|
|||||||
{
|
{
|
||||||
if (IsSporkActive(SPORK_10_MASTERNODE_PAY_UPDATED_NODES))
|
if (IsSporkActive(SPORK_10_MASTERNODE_PAY_UPDATED_NODES))
|
||||||
return ActiveProtocol(); // Allow only updated peers
|
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
|
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)
|
void CMasternodePayments::ProcessMessageMasternodePayments(CNode* pfrom, std::string& strCommand, CDataStream& vRecv)
|
||||||
{
|
{
|
||||||
if (!masternodeSync.IsBlockchainSynced()) return;
|
if (!masternodeSync.IsBlockchainSynced()) {
|
||||||
|
return;
|
||||||
if (fLiteMode) return; //disable all Obfuscation/Masternode related functionality
|
}
|
||||||
|
|
||||||
|
if (fLiteMode) {
|
||||||
|
return; // disable all Obfuscation/Masternode related functionality
|
||||||
|
}
|
||||||
|
|
||||||
if (strCommand == "mnget") { // Masternode Payments Request Sync
|
if (strCommand == "mnget") { // Masternode Payments Request Sync
|
||||||
if (fLiteMode) return; //disable all Obfuscation/Masternode related functionality
|
|
||||||
|
|
||||||
int nCountNeeded;
|
int nCountNeeded;
|
||||||
vRecv >> nCountNeeded;
|
vRecv >> nCountNeeded;
|
||||||
|
|
||||||
@@ -375,17 +432,23 @@ void CMasternodePayments::ProcessMessageMasternodePayments(CNode* pfrom, std::st
|
|||||||
pfrom->FulfilledRequest("mnget");
|
pfrom->FulfilledRequest("mnget");
|
||||||
masternodePayments.Sync(pfrom, nCountNeeded);
|
masternodePayments.Sync(pfrom, nCountNeeded);
|
||||||
LogPrint("mnpayments", "mnget - Sent Masternode winners to peer %i\n", pfrom->GetId());
|
LogPrint("mnpayments", "mnget - Sent Masternode winners to peer %i\n", pfrom->GetId());
|
||||||
} else if (strCommand == "mnw") { //Masternode Payments Declare Winner
|
return;
|
||||||
//this is required in litemodef
|
}
|
||||||
|
|
||||||
|
if (strCommand == "mnw") { // Masternode Payments Declare Winner
|
||||||
CMasternodePaymentWinner winner;
|
CMasternodePaymentWinner winner;
|
||||||
vRecv >> winner;
|
vRecv >> winner;
|
||||||
|
|
||||||
if (pfrom->nVersion < ActiveProtocol()) return;
|
if (pfrom->nVersion < ActiveProtocol()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
int nHeight;
|
int nHeight;
|
||||||
{
|
{
|
||||||
TRY_LOCK(cs_main, locked);
|
TRY_LOCK(cs_main, locked);
|
||||||
if (!locked || chainActive.Tip() == NULL) return;
|
if (!locked || chainActive.Tip() == nullptr) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
nHeight = chainActive.Tip()->nHeight;
|
nHeight = chainActive.Tip()->nHeight;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -395,20 +458,18 @@ void CMasternodePayments::ProcessMessageMasternodePayments(CNode* pfrom, std::st
|
|||||||
return;
|
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) {
|
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);
|
LogPrint("mnpayments", "mnw - winner out of range - FirstBlock %d Height %d bestHeight %d\n", nFirstBlock, winner.nBlockHeight, nHeight);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string strError = "";
|
std::string strError;
|
||||||
if (!winner.IsValid(pfrom, strError)) {
|
if (!winner.IsValid(pfrom, strError)) {
|
||||||
// if(strError != "") LogPrint("masternode","mnw - invalid message - %s\n", strError);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!masternodePayments.CanVote(winner.vinMasternode.prevout, winner.nBlockHeight)) {
|
if (!masternodePayments.CanVote(winner.vinMasternode.prevout, winner.nBlockHeight)) {
|
||||||
// LogPrint("masternode","mnw - masternode already voted - %s\n", winner.vinMasternode.prevout.ToStringShort());
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -422,25 +483,20 @@ void CMasternodePayments::ProcessMessageMasternodePayments(CNode* pfrom, std::st
|
|||||||
return;
|
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)) {
|
if (masternodePayments.AddWinningMasternode(winner)) {
|
||||||
winner.Relay();
|
winner.Relay();
|
||||||
masternodeSync.AddedMasternodeWinner(winner.GetHash());
|
masternodeSync.AddedMasternodeWinner(winner.GetHash());
|
||||||
}
|
}
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CMasternodePaymentWinner::Sign(CKey& keyMasternode, CPubKey& pubKeyMasternode)
|
bool CMasternodePaymentWinner::Sign(CKey& keyMasternode, CPubKey& pubKeyMasternode)
|
||||||
{
|
{
|
||||||
std::string errorMessage;
|
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)) {
|
if (!obfuScationSigner.SignMessage(strMessage, errorMessage, vchSig, keyMasternode)) {
|
||||||
LogPrint("masternode", "CMasternodePing::Sign() - Error: %s\n", errorMessage.c_str());
|
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)) {
|
if (mapMasternodeBlocks.count(nBlockHeight)) {
|
||||||
return mapMasternodeBlocks[nBlockHeight].GetPayee(payee);
|
return mapMasternodeBlocks[nBlockHeight].GetPayee(payee);
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -473,16 +528,19 @@ bool CMasternodePayments::IsScheduled(CMasternode& mn, int nNotBlockHeight)
|
|||||||
int nHeight;
|
int nHeight;
|
||||||
{
|
{
|
||||||
TRY_LOCK(cs_main, locked);
|
TRY_LOCK(cs_main, locked);
|
||||||
if (!locked || chainActive.Tip() == NULL) return false;
|
if (!locked || chainActive.Tip() == nullptr) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
nHeight = chainActive.Tip()->nHeight;
|
nHeight = chainActive.Tip()->nHeight;
|
||||||
}
|
}
|
||||||
|
|
||||||
CScript mnpayee;
|
const CScript mnpayee = GetScriptForDestination(mn.pubKeyCollateralAddress.GetID());
|
||||||
mnpayee = GetScriptForDestination(mn.pubKeyCollateralAddress.GetID());
|
|
||||||
|
|
||||||
CScript payee;
|
CScript payee;
|
||||||
for (int64_t h = nHeight; h <= nHeight + 8; h++) {
|
for (int64_t h = nHeight; h <= nHeight + 8; h++) {
|
||||||
if (h == nNotBlockHeight) continue;
|
if (h == nNotBlockHeight) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
if (mapMasternodeBlocks.count(h)) {
|
if (mapMasternodeBlocks.count(h)) {
|
||||||
if (mapMasternodeBlocks[h].GetPayee(payee)) {
|
if (mapMasternodeBlocks[h].GetPayee(payee)) {
|
||||||
if (mnpayee == payee) {
|
if (mnpayee == payee) {
|
||||||
@@ -518,7 +576,6 @@ bool CMasternodePayments::AddWinningMasternode(CMasternodePaymentWinner& winnerI
|
|||||||
}
|
}
|
||||||
|
|
||||||
mapMasternodeBlocks[winnerIn.nBlockHeight].AddPayee(winnerIn.payee, 1);
|
mapMasternodeBlocks[winnerIn.nBlockHeight].AddPayee(winnerIn.payee, 1);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -529,50 +586,60 @@ bool CMasternodeBlockPayees::IsTransactionValid(const CTransaction& txNew)
|
|||||||
int nMaxSignatures = 0;
|
int nMaxSignatures = 0;
|
||||||
int nMasternode_Drift_Count = 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)) {
|
if (IsSporkActive(SPORK_8_MASTERNODE_PAYMENT_ENFORCEMENT)) {
|
||||||
// Get a stable number of masternodes by ignoring newly activated (< 8000 sec old) masternodes
|
// Get a stable number of masternodes by ignoring newly activated (< 8000 sec old) masternodes
|
||||||
nMasternode_Drift_Count = mnodeman.stable_size() + Params().MasternodeCountDrift();
|
nMasternode_Drift_Count = mnodeman.stable_size() + Params().MasternodeCountDrift();
|
||||||
}
|
} else {
|
||||||
else {
|
// Account for the fact that all peers do not see the same masternode count.
|
||||||
//account for the fact that all peers do not see the same masternode count. A allowance of being off our masternode count is given
|
// 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
|
// We only need to look at an increased masternode count because as count increases, the reward decreases.
|
||||||
//for mnPayment >= required, so it only makes sense to check the max node count allowed.
|
// 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();
|
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
|
// require at least 6 signatures
|
||||||
for (CMasternodePayee& payee : vecPayments)
|
for (CMasternodePayee& payee : vecPayments) {
|
||||||
if (payee.nVotes >= nMaxSignatures && payee.nVotes >= MNPAYMENTS_SIGNATURES_REQUIRED)
|
if (payee.nVotes >= nMaxSignatures && payee.nVotes >= MNPAYMENTS_SIGNATURES_REQUIRED) {
|
||||||
nMaxSignatures = payee.nVotes;
|
nMaxSignatures = payee.nVotes;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// if we don't have at least 6 signatures on a payee, approve whichever is the longest chain
|
// 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 (nMaxSignatures < MNPAYMENTS_SIGNATURES_REQUIRED) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
for (CMasternodePayee& payee : vecPayments) {
|
for (CMasternodePayee& payee : vecPayments) {
|
||||||
bool found = false;
|
bool found = false;
|
||||||
for (CTxOut out : txNew.vout) {
|
|
||||||
|
for (const CTxOut& out : txNew.vout) {
|
||||||
if (payee.scriptPubKey == out.scriptPubKey) {
|
if (payee.scriptPubKey == out.scriptPubKey) {
|
||||||
if(out.nValue >= requiredMasternodePayment)
|
if (out.nValue >= requiredMasternodePayment) {
|
||||||
found = true;
|
found = true;
|
||||||
else
|
} else {
|
||||||
LogPrint("masternode","Masternode payment is out of drift range. Paid=%s Min=%s\n", FormatMoney(out.nValue).c_str(), FormatMoney(requiredMasternodePayment).c_str());
|
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 (payee.nVotes >= MNPAYMENTS_SIGNATURES_REQUIRED) {
|
||||||
if (found) return true;
|
if (found) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
CTxDestination address1;
|
CTxDestination address1;
|
||||||
ExtractDestination(payee.scriptPubKey, address1);
|
ExtractDestination(payee.scriptPubKey, address1);
|
||||||
CBitcoinAddress address2(address1);
|
CBitcoinAddress address2(address1);
|
||||||
|
|
||||||
if (strPayeesPossible == "") {
|
if (strPayeesPossible.empty()) {
|
||||||
strPayeesPossible += address2.ToString();
|
strPayeesPossible += address2.ToString();
|
||||||
} else {
|
} else {
|
||||||
strPayeesPossible += "," + address2.ToString();
|
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;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -634,16 +702,18 @@ void CMasternodePayments::CleanPaymentList()
|
|||||||
int nHeight;
|
int nHeight;
|
||||||
{
|
{
|
||||||
TRY_LOCK(cs_main, locked);
|
TRY_LOCK(cs_main, locked);
|
||||||
if (!locked || chainActive.Tip() == NULL) return;
|
if (!locked || chainActive.Tip() == nullptr) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
nHeight = chainActive.Tip()->nHeight;
|
nHeight = chainActive.Tip()->nHeight;
|
||||||
}
|
}
|
||||||
|
|
||||||
// keep up to five cycles for historical sake
|
// 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();
|
std::map<uint256, CMasternodePaymentWinner>::iterator it = mapMasternodePayeeVotes.begin();
|
||||||
while (it != mapMasternodePayeeVotes.end()) {
|
while (it != mapMasternodePayeeVotes.end()) {
|
||||||
CMasternodePaymentWinner winner = (*it).second;
|
const CMasternodePaymentWinner& winner = (*it).second;
|
||||||
|
|
||||||
if (nHeight - winner.nBlockHeight > nLimit) {
|
if (nHeight - winner.nBlockHeight > nLimit) {
|
||||||
LogPrint("mnpayments", "CMasternodePayments::CleanPaymentList - Removing old Masternode payment - block %d\n", winner.nBlockHeight);
|
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;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
int n = mnodeman.GetMasternodeRank(vinMasternode, nBlockHeight - 100, ActiveProtocol());
|
const int n = mnodeman.GetMasternodeRank(vinMasternode, nBlockHeight - 100, ActiveProtocol());
|
||||||
|
|
||||||
if (n > MNPAYMENTS_SIGNATURES_TOTAL) {
|
if (n > MNPAYMENTS_SIGNATURES_TOTAL) {
|
||||||
//It's common to have masternodes mistakenly think they are in the top 10
|
// 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
|
// We don't want to print all of these messages, or punish them unless they're way off.
|
||||||
if (n > MNPAYMENTS_SIGNATURES_TOTAL * 2) {
|
if (n > MNPAYMENTS_SIGNATURES_TOTAL * 2) {
|
||||||
strError = strprintf("Masternode not in the top %d (%d)", MNPAYMENTS_SIGNATURES_TOTAL * 2, n);
|
strError = strprintf("Masternode not in the top %d (%d)", MNPAYMENTS_SIGNATURES_TOTAL * 2, n);
|
||||||
LogPrint("masternode", "CMasternodePaymentWinner::IsValid - %s\n", strError);
|
LogPrint("masternode", "CMasternodePaymentWinner::IsValid - %s\n", strError);
|
||||||
@@ -691,11 +761,12 @@ bool CMasternodePaymentWinner::IsValid(CNode* pnode, std::string& strError)
|
|||||||
|
|
||||||
bool CMasternodePayments::ProcessBlock(int nBlockHeight)
|
bool CMasternodePayments::ProcessBlock(int nBlockHeight)
|
||||||
{
|
{
|
||||||
if (!fMasterNode) return false;
|
if (!fMasterNode) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
// reference node - hybrid mode
|
// reference node - hybrid mode
|
||||||
|
const int n = mnodeman.GetMasternodeRank(activeMasternode.vin, nBlockHeight - 100, ActiveProtocol());
|
||||||
int n = mnodeman.GetMasternodeRank(activeMasternode.vin, nBlockHeight - 100, ActiveProtocol());
|
|
||||||
|
|
||||||
if (n == -1) {
|
if (n == -1) {
|
||||||
LogPrint("mnpayments", "CMasternodePayments::ProcessBlock - Unknown Masternode\n");
|
LogPrint("mnpayments", "CMasternodePayments::ProcessBlock - Unknown Masternode\n");
|
||||||
@@ -707,32 +778,36 @@ bool CMasternodePayments::ProcessBlock(int nBlockHeight)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (nBlockHeight <= nLastBlockHeight) return false;
|
if (nBlockHeight <= nLastBlockHeight) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
CMasternodePaymentWinner newWinner(activeMasternode.vin);
|
CMasternodePaymentWinner newWinner(activeMasternode.vin);
|
||||||
|
|
||||||
if (budget.IsBudgetPaymentBlock(nBlockHeight)) {
|
if (budget.IsBudgetPaymentBlock(nBlockHeight)) {
|
||||||
//is budget payment block -- handled by the budgeting software
|
// budget payment block -- handled by the budgeting software
|
||||||
} else {
|
} 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
|
// 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;
|
int nCount = 0;
|
||||||
CMasternode* pmn = mnodeman.GetNextMasternodeInQueueForPayment(nBlockHeight, true, nCount);
|
CMasternode* pmn = mnodeman.GetNextMasternodeInQueueForPayment(nBlockHeight, true, nCount);
|
||||||
|
|
||||||
if (pmn != NULL) {
|
if (pmn != nullptr) {
|
||||||
LogPrint("masternode", "CMasternodePayments::ProcessBlock() Found by FindOldestNotInVec \n");
|
LogPrint("masternode", "CMasternodePayments::ProcessBlock() Found by FindOldestNotInVec \n");
|
||||||
|
|
||||||
newWinner.nBlockHeight = nBlockHeight;
|
newWinner.nBlockHeight = nBlockHeight;
|
||||||
|
|
||||||
CScript payee = GetScriptForDestination(pmn->pubKeyCollateralAddress.GetID());
|
const CScript payee = GetScriptForDestination(pmn->pubKeyCollateralAddress.GetID());
|
||||||
newWinner.AddPayee(payee);
|
newWinner.AddPayee(payee);
|
||||||
|
|
||||||
CTxDestination address1;
|
CTxDestination address1;
|
||||||
ExtractDestination(payee, address1);
|
ExtractDestination(payee, address1);
|
||||||
CBitcoinAddress address2(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 {
|
} else {
|
||||||
LogPrint("masternode", "CMasternodePayments::ProcessBlock() Failed to find masternode to pay\n");
|
LogPrint("masternode", "CMasternodePayments::ProcessBlock() Failed to find masternode to pay\n");
|
||||||
}
|
}
|
||||||
@@ -771,12 +846,14 @@ bool CMasternodePaymentWinner::SignatureValid()
|
|||||||
{
|
{
|
||||||
CMasternode* pmn = mnodeman.Find(vinMasternode);
|
CMasternode* pmn = mnodeman.Find(vinMasternode);
|
||||||
|
|
||||||
if (pmn != NULL) {
|
if (pmn != nullptr) {
|
||||||
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();
|
||||||
|
|
||||||
std::string errorMessage = "";
|
std::string errorMessage;
|
||||||
if (!obfuScationSigner.VerifyMessage(pmn->pubKeyMasternode, vchSig, strMessage, 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;
|
return true;
|
||||||
@@ -792,36 +869,38 @@ void CMasternodePayments::Sync(CNode* node, int nCountNeeded)
|
|||||||
int nHeight;
|
int nHeight;
|
||||||
{
|
{
|
||||||
TRY_LOCK(cs_main, locked);
|
TRY_LOCK(cs_main, locked);
|
||||||
if (!locked || chainActive.Tip() == NULL) return;
|
if (!locked || chainActive.Tip() == nullptr) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
nHeight = chainActive.Tip()->nHeight;
|
nHeight = chainActive.Tip()->nHeight;
|
||||||
}
|
}
|
||||||
|
|
||||||
int nCount = (mnodeman.CountEnabled() * 1.25);
|
int nCount = static_cast<int>(mnodeman.CountEnabled() * 1.25);
|
||||||
if (nCountNeeded > nCount) nCountNeeded = nCount;
|
if (nCountNeeded > nCount) {
|
||||||
|
nCountNeeded = nCount;
|
||||||
|
}
|
||||||
|
|
||||||
int nInvCount = 0;
|
int nInvCount = 0;
|
||||||
std::map<uint256, CMasternodePaymentWinner>::iterator it = mapMasternodePayeeVotes.begin();
|
std::map<uint256, CMasternodePaymentWinner>::iterator it = mapMasternodePayeeVotes.begin();
|
||||||
while (it != mapMasternodePayeeVotes.end()) {
|
while (it != mapMasternodePayeeVotes.end()) {
|
||||||
CMasternodePaymentWinner winner = (*it).second;
|
const CMasternodePaymentWinner& winner = (*it).second;
|
||||||
if (winner.nBlockHeight >= nHeight - nCountNeeded && winner.nBlockHeight <= nHeight + 20) {
|
if (winner.nBlockHeight >= nHeight - nCountNeeded && winner.nBlockHeight <= nHeight + 20) {
|
||||||
node->PushInventory(CInv(MSG_MASTERNODE_WINNER, winner.GetHash()));
|
node->PushInventory(CInv(MSG_MASTERNODE_WINNER, winner.GetHash()));
|
||||||
nInvCount++;
|
nInvCount++;
|
||||||
}
|
}
|
||||||
++it;
|
++it;
|
||||||
}
|
}
|
||||||
|
|
||||||
node->PushMessage("ssc", MASTERNODE_SYNC_MNW, nInvCount);
|
node->PushMessage("ssc", MASTERNODE_SYNC_MNW, nInvCount);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string CMasternodePayments::ToString() const
|
std::string CMasternodePayments::ToString() const
|
||||||
{
|
{
|
||||||
std::ostringstream info;
|
std::ostringstream info;
|
||||||
|
|
||||||
info << "Votes: " << (int)mapMasternodePayeeVotes.size() << ", Blocks: " << (int)mapMasternodeBlocks.size();
|
info << "Votes: " << (int)mapMasternodePayeeVotes.size() << ", Blocks: " << (int)mapMasternodeBlocks.size();
|
||||||
|
|
||||||
return info.str();
|
return info.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int CMasternodePayments::GetOldestBlock()
|
int CMasternodePayments::GetOldestBlock()
|
||||||
{
|
{
|
||||||
LOCK(cs_mapMasternodeBlocks);
|
LOCK(cs_mapMasternodeBlocks);
|
||||||
@@ -833,13 +912,12 @@ int CMasternodePayments::GetOldestBlock()
|
|||||||
if ((*it).first < nOldestBlock) {
|
if ((*it).first < nOldestBlock) {
|
||||||
nOldestBlock = (*it).first;
|
nOldestBlock = (*it).first;
|
||||||
}
|
}
|
||||||
it++;
|
++it;
|
||||||
}
|
}
|
||||||
|
|
||||||
return nOldestBlock;
|
return nOldestBlock;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int CMasternodePayments::GetNewestBlock()
|
int CMasternodePayments::GetNewestBlock()
|
||||||
{
|
{
|
||||||
LOCK(cs_mapMasternodeBlocks);
|
LOCK(cs_mapMasternodeBlocks);
|
||||||
@@ -851,7 +929,7 @@ int CMasternodePayments::GetNewestBlock()
|
|||||||
if ((*it).first > nNewestBlock) {
|
if ((*it).first > nNewestBlock) {
|
||||||
nNewestBlock = (*it).first;
|
nNewestBlock = (*it).first;
|
||||||
}
|
}
|
||||||
it++;
|
++it;
|
||||||
}
|
}
|
||||||
|
|
||||||
return nNewestBlock;
|
return nNewestBlock;
|
||||||
|
|||||||
+32
-65
@@ -1,16 +1,19 @@
|
|||||||
// Copyright (c) 2014-2015 The Dash developers
|
// Copyright (c) 2014-2015 The Dash developers
|
||||||
// Copyright (c) 2015-2019 The PIVX developers
|
// Copyright (c) 2015-2019 The PIVX developers
|
||||||
|
// Copyright (c) 2026 Agrarian Developers
|
||||||
// Distributed under the MIT/X11 software license, see the accompanying
|
// Distributed under the MIT/X11 software license, see the accompanying
|
||||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||||
|
|
||||||
#ifndef MASTERNODE_PAYMENTS_H
|
#ifndef AGRARIAN_MASTERNODE_PAYMENTS_H
|
||||||
#define MASTERNODE_PAYMENTS_H
|
#define AGRARIAN_MASTERNODE_PAYMENTS_H
|
||||||
|
|
||||||
#include "key.h"
|
#include "key.h"
|
||||||
#include "main.h"
|
#include "main.h"
|
||||||
#include "masternode.h"
|
#include "masternode.h"
|
||||||
|
|
||||||
using namespace std;
|
#include <map>
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
extern CCriticalSection cs_vecPayments;
|
extern CCriticalSection cs_vecPayments;
|
||||||
extern CCriticalSection cs_mapMasternodeBlocks;
|
extern CCriticalSection cs_mapMasternodeBlocks;
|
||||||
@@ -33,8 +36,7 @@ void FillBlockPayee(CMutableTransaction& txNew, CAmount nFees, bool fProofOfStak
|
|||||||
|
|
||||||
void DumpMasternodePayments();
|
void DumpMasternodePayments();
|
||||||
|
|
||||||
/** Save Masternode Payment Data (mnpayments.dat)
|
/** Save Masternode Payment Data (mnpayments.dat) */
|
||||||
*/
|
|
||||||
class CMasternodePaymentDB
|
class CMasternodePaymentDB
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
@@ -63,17 +65,8 @@ public:
|
|||||||
CScript scriptPubKey;
|
CScript scriptPubKey;
|
||||||
int nVotes;
|
int nVotes;
|
||||||
|
|
||||||
CMasternodePayee()
|
CMasternodePayee() : scriptPubKey(CScript()), nVotes(0) {}
|
||||||
{
|
CMasternodePayee(const CScript& payee, int nVotesIn) : scriptPubKey(payee), nVotes(nVotesIn) {}
|
||||||
scriptPubKey = CScript();
|
|
||||||
nVotes = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
CMasternodePayee(CScript payee, int nVotesIn)
|
|
||||||
{
|
|
||||||
scriptPubKey = payee;
|
|
||||||
nVotes = nVotesIn;
|
|
||||||
}
|
|
||||||
|
|
||||||
ADD_SERIALIZE_METHODS;
|
ADD_SERIALIZE_METHODS;
|
||||||
|
|
||||||
@@ -92,18 +85,10 @@ public:
|
|||||||
int nBlockHeight;
|
int nBlockHeight;
|
||||||
std::vector<CMasternodePayee> vecPayments;
|
std::vector<CMasternodePayee> vecPayments;
|
||||||
|
|
||||||
CMasternodeBlockPayees()
|
CMasternodeBlockPayees() : nBlockHeight(0), vecPayments() {}
|
||||||
{
|
explicit CMasternodeBlockPayees(int nBlockHeightIn) : nBlockHeight(nBlockHeightIn), vecPayments() {}
|
||||||
nBlockHeight = 0;
|
|
||||||
vecPayments.clear();
|
|
||||||
}
|
|
||||||
CMasternodeBlockPayees(int nBlockHeightIn)
|
|
||||||
{
|
|
||||||
nBlockHeight = nBlockHeightIn;
|
|
||||||
vecPayments.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
void AddPayee(CScript payeeIn, int nIncrement)
|
void AddPayee(const CScript& payeeIn, int nIncrement)
|
||||||
{
|
{
|
||||||
LOCK(cs_vecPayments);
|
LOCK(cs_vecPayments);
|
||||||
|
|
||||||
@@ -114,8 +99,7 @@ public:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
CMasternodePayee c(payeeIn, nIncrement);
|
vecPayments.emplace_back(payeeIn, nIncrement);
|
||||||
vecPayments.push_back(c);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GetPayee(CScript& payee)
|
bool GetPayee(CScript& payee)
|
||||||
@@ -133,12 +117,14 @@ public:
|
|||||||
return (nVotes > -1);
|
return (nVotes > -1);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool HasPayeeWithVotes(CScript payee, int nVotesReq)
|
bool HasPayeeWithVotes(const CScript& payee, int nVotesReq)
|
||||||
{
|
{
|
||||||
LOCK(cs_vecPayments);
|
LOCK(cs_vecPayments);
|
||||||
|
|
||||||
for (CMasternodePayee& p : 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;
|
return false;
|
||||||
@@ -157,29 +143,17 @@ public:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// for storing the winning payments
|
// For storing the winning payments
|
||||||
class CMasternodePaymentWinner
|
class CMasternodePaymentWinner
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
CTxIn vinMasternode;
|
CTxIn vinMasternode;
|
||||||
|
|
||||||
int nBlockHeight;
|
int nBlockHeight;
|
||||||
CScript payee;
|
CScript payee;
|
||||||
std::vector<unsigned char> vchSig;
|
std::vector<unsigned char> vchSig;
|
||||||
|
|
||||||
CMasternodePaymentWinner()
|
CMasternodePaymentWinner() : vinMasternode(CTxIn()), nBlockHeight(0), payee(CScript()), vchSig() {}
|
||||||
{
|
explicit CMasternodePaymentWinner(const CTxIn& vinIn) : vinMasternode(vinIn), nBlockHeight(0), payee(CScript()), vchSig() {}
|
||||||
nBlockHeight = 0;
|
|
||||||
vinMasternode = CTxIn();
|
|
||||||
payee = CScript();
|
|
||||||
}
|
|
||||||
|
|
||||||
CMasternodePaymentWinner(CTxIn vinIn)
|
|
||||||
{
|
|
||||||
nBlockHeight = 0;
|
|
||||||
vinMasternode = vinIn;
|
|
||||||
payee = CScript();
|
|
||||||
}
|
|
||||||
|
|
||||||
uint256 GetHash()
|
uint256 GetHash()
|
||||||
{
|
{
|
||||||
@@ -187,7 +161,6 @@ public:
|
|||||||
ss << payee;
|
ss << payee;
|
||||||
ss << nBlockHeight;
|
ss << nBlockHeight;
|
||||||
ss << vinMasternode.prevout;
|
ss << vinMasternode.prevout;
|
||||||
|
|
||||||
return ss.GetHash();
|
return ss.GetHash();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -196,11 +169,7 @@ public:
|
|||||||
bool SignatureValid();
|
bool SignatureValid();
|
||||||
void Relay();
|
void Relay();
|
||||||
|
|
||||||
void AddPayee(CScript payeeIn)
|
void AddPayee(const CScript& payeeIn) { payee = payeeIn; }
|
||||||
{
|
|
||||||
payee = payeeIn;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
ADD_SERIALIZE_METHODS;
|
ADD_SERIALIZE_METHODS;
|
||||||
|
|
||||||
@@ -215,7 +184,7 @@ public:
|
|||||||
|
|
||||||
std::string ToString()
|
std::string ToString()
|
||||||
{
|
{
|
||||||
std::string ret = "";
|
std::string ret;
|
||||||
ret += vinMasternode.ToString();
|
ret += vinMasternode.ToString();
|
||||||
ret += ", " + std::to_string(nBlockHeight);
|
ret += ", " + std::to_string(nBlockHeight);
|
||||||
ret += ", " + payee.ToString();
|
ret += ", " + payee.ToString();
|
||||||
@@ -228,7 +197,6 @@ public:
|
|||||||
// Masternode Payments Class
|
// Masternode Payments Class
|
||||||
// Keeps track of who should get paid for which blocks
|
// Keeps track of who should get paid for which blocks
|
||||||
//
|
//
|
||||||
|
|
||||||
class CMasternodePayments
|
class CMasternodePayments
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
@@ -238,13 +206,12 @@ private:
|
|||||||
public:
|
public:
|
||||||
std::map<uint256, CMasternodePaymentWinner> mapMasternodePayeeVotes;
|
std::map<uint256, CMasternodePaymentWinner> mapMasternodePayeeVotes;
|
||||||
std::map<int, CMasternodeBlockPayees> mapMasternodeBlocks;
|
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
|
std::map<uint256, int> mapMasternodesLastVote; // prevout.hash + prevout.n, nBlockHeight
|
||||||
|
|
||||||
CMasternodePayments()
|
CMasternodePayments() : nSyncedFromPeer(0), nLastBlockHeight(0) {}
|
||||||
{
|
|
||||||
nSyncedFromPeer = 0;
|
|
||||||
nLastBlockHeight = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Clear()
|
void Clear()
|
||||||
{
|
{
|
||||||
@@ -264,18 +231,19 @@ public:
|
|||||||
bool IsTransactionValid(const CTransaction& txNew, int nBlockHeight);
|
bool IsTransactionValid(const CTransaction& txNew, int nBlockHeight);
|
||||||
bool IsScheduled(CMasternode& mn, int nNotBlockHeight);
|
bool IsScheduled(CMasternode& mn, int nNotBlockHeight);
|
||||||
|
|
||||||
bool CanVote(COutPoint outMasternode, int nBlockHeight)
|
bool CanVote(const COutPoint& outMasternode, int nBlockHeight)
|
||||||
{
|
{
|
||||||
LOCK(cs_mapMasternodePayeeVotes);
|
LOCK(cs_mapMasternodePayeeVotes);
|
||||||
|
|
||||||
if (mapMasternodesLastVote.count(outMasternode.hash + outMasternode.n)) {
|
const uint256 key = outMasternode.hash + outMasternode.n;
|
||||||
if (mapMasternodesLastVote[outMasternode.hash + outMasternode.n] == nBlockHeight) {
|
if (mapMasternodesLastVote.count(key)) {
|
||||||
|
if (mapMasternodesLastVote[key] == nBlockHeight) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// record this masternode voted
|
// record this masternode voted
|
||||||
mapMasternodesLastVote[outMasternode.hash + outMasternode.n] = nBlockHeight;
|
mapMasternodesLastVote[key] = nBlockHeight;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -297,5 +265,4 @@ public:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#endif // AGRARIAN_MASTERNODE_PAYMENTS_H
|
||||||
#endif
|
|
||||||
|
|||||||
+13
-15
@@ -2,6 +2,7 @@
|
|||||||
// Copyright (c) 2009-2014 The Bitcoin developers
|
// Copyright (c) 2009-2014 The Bitcoin developers
|
||||||
// Copyright (c) 2014-2015 The Dash developers
|
// Copyright (c) 2014-2015 The Dash developers
|
||||||
// Copyright (c) 2015-2019 The PIVX developers
|
// Copyright (c) 2015-2019 The PIVX developers
|
||||||
|
// Copyright (c) 2026 Agrarian Developers
|
||||||
// Distributed under the MIT/X11 software license, see the accompanying
|
// Distributed under the MIT/X11 software license, see the accompanying
|
||||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||||
|
|
||||||
@@ -32,9 +33,6 @@
|
|||||||
|
|
||||||
#include <boost/thread.hpp>
|
#include <boost/thread.hpp>
|
||||||
#include <boost/tuple/tuple.hpp>
|
#include <boost/tuple/tuple.hpp>
|
||||||
|
|
||||||
using namespace std;
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
//
|
//
|
||||||
// AgrarianMiner
|
// AgrarianMiner
|
||||||
@@ -105,7 +103,7 @@ CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn, CWallet* pwallet,
|
|||||||
// Create new block
|
// Create new block
|
||||||
unique_ptr<CBlockTemplate> pblocktemplate(new CBlockTemplate());
|
unique_ptr<CBlockTemplate> pblocktemplate(new CBlockTemplate());
|
||||||
if (!pblocktemplate.get())
|
if (!pblocktemplate.get())
|
||||||
return NULL;
|
return nullptr;
|
||||||
CBlock* pblock = &pblocktemplate->block; // pointer for convenience
|
CBlock* pblock = &pblocktemplate->block; // pointer for convenience
|
||||||
|
|
||||||
// Tip
|
// Tip
|
||||||
@@ -166,7 +164,7 @@ CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn, CWallet* pwallet,
|
|||||||
|
|
||||||
if (!fStakeFound) {
|
if (!fStakeFound) {
|
||||||
LogPrint("staking", "CreateNewBlock(): stake not found\n");
|
LogPrint("staking", "CreateNewBlock(): stake not found\n");
|
||||||
return NULL;
|
return nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -214,7 +212,7 @@ CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn, CWallet* pwallet,
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
COrphan* porphan = NULL;
|
COrphan* porphan = nullptr;
|
||||||
double dPriority = 0;
|
double dPriority = 0;
|
||||||
CAmount nTotalIn = 0;
|
CAmount nTotalIn = 0;
|
||||||
bool fMissingInputs = false;
|
bool fMissingInputs = false;
|
||||||
@@ -521,17 +519,17 @@ CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn, CWallet* pwallet,
|
|||||||
CKey key;
|
CKey key;
|
||||||
if (!pwallet->GetZerocoinKey(bnSerial, key)) {
|
if (!pwallet->GetZerocoinKey(bnSerial, key)) {
|
||||||
LogPrintf("%s: failed to find zAGR with serial %s, unable to sign block\n", __func__, bnSerial.GetHex());
|
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
|
//Sign block with the zAGR key
|
||||||
if (!SignBlockWithKey(*pblock, key)) {
|
if (!SignBlockWithKey(*pblock, key)) {
|
||||||
LogPrintf("BitcoinMiner(): Signing new block with zAGR key failed \n");
|
LogPrintf("BitcoinMiner(): Signing new block with zAGR key failed \n");
|
||||||
return NULL;
|
return nullptr;
|
||||||
}
|
}
|
||||||
} else if (!SignBlock(*pblock, *pwallet)) {
|
} else if (!SignBlock(*pblock, *pwallet)) {
|
||||||
LogPrintf("BitcoinMiner(): Signing new block with UTXO key failed \n");
|
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)) {
|
if (!TestBlockValidity(state, *pblock, pindexPrev, false, false)) {
|
||||||
//LogPrintf("CreateNewBlock() : TestBlockValidity failed\n");
|
//LogPrintf("CreateNewBlock() : TestBlockValidity failed\n");
|
||||||
mempool.clear();
|
mempool.clear();
|
||||||
return NULL;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
// if (pblock->IsZerocoinStake()) {
|
// if (pblock->IsZerocoinStake()) {
|
||||||
@@ -581,7 +579,7 @@ CBlockTemplate* CreateNewBlockWithKey(CReserveKey& reservekey, CWallet* pwallet,
|
|||||||
{
|
{
|
||||||
CPubKey pubkey;
|
CPubKey pubkey;
|
||||||
if (!reservekey.GetReservedKey(pubkey))
|
if (!reservekey.GetReservedKey(pubkey))
|
||||||
return NULL;
|
return nullptr;
|
||||||
|
|
||||||
CScript scriptPubKey = CScript() << ToByteVector(pubkey) << OP_CHECKSIG;
|
CScript scriptPubKey = CScript() << ToByteVector(pubkey) << OP_CHECKSIG;
|
||||||
return CreateNewBlock(scriptPubKey, pwallet, fProofOfStake);
|
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
|
// Process this block the same as if we had received it from another node
|
||||||
CValidationState state;
|
CValidationState state;
|
||||||
if (!ProcessNewBlock(state, NULL, pblock)) {
|
if (!ProcessNewBlock(state, nullptr, pblock)) {
|
||||||
if (pblock->IsZerocoinStake()) {
|
if (pblock->IsZerocoinStake()) {
|
||||||
pwalletMain->zagrTracker->RemovePending(pblock->vtx[1].GetHash());
|
pwalletMain->zagrTracker->RemovePending(pblock->vtx[1].GetHash());
|
||||||
pwalletMain->zagrTracker->ListMints(true, true, true); //update the state
|
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)
|
void GenerateBitcoins(bool fGenerate, CWallet* pwallet, int nThreads)
|
||||||
{
|
{
|
||||||
static boost::thread_group* minerThreads = NULL;
|
static boost::thread_group* minerThreads = nullptr;
|
||||||
fGenerateBitcoins = fGenerate;
|
fGenerateBitcoins = fGenerate;
|
||||||
|
|
||||||
if (nThreads < 0) {
|
if (nThreads < 0) {
|
||||||
@@ -842,10 +840,10 @@ void GenerateBitcoins(bool fGenerate, CWallet* pwallet, int nThreads)
|
|||||||
nThreads = boost::thread::hardware_concurrency();
|
nThreads = boost::thread::hardware_concurrency();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (minerThreads != NULL) {
|
if (minerThreads != nullptr) {
|
||||||
minerThreads->interrupt_all();
|
minerThreads->interrupt_all();
|
||||||
delete minerThreads;
|
delete minerThreads;
|
||||||
minerThreads = NULL;
|
minerThreads = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (nThreads == 0 || !fGenerate)
|
if (nThreads == 0 || !fGenerate)
|
||||||
|
|||||||
+9
-7
@@ -1,14 +1,16 @@
|
|||||||
// Copyright (c) 2009-2010 Satoshi Nakamoto
|
// Copyright (c) 2009-2010 Satoshi Nakamoto
|
||||||
// Copyright (c) 2009-2014 The Bitcoin developers
|
// Copyright (c) 2009-2014 The Bitcoin developers
|
||||||
// Copyright (c) 2016-2018 The PIVX developers
|
// Copyright (c) 2016-2018 The PIVX developers
|
||||||
|
// Copyright (c) 2026 Agrarian Developers
|
||||||
// Distributed under the MIT/X11 software license, see the accompanying
|
// Distributed under the MIT/X11 software license, see the accompanying
|
||||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||||
|
#ifndef AGRARIAN_BITCOIN_MINER_H
|
||||||
#ifndef BITCOIN_MINER_H
|
#define AGRARIAN_BITCOIN_MINER_H
|
||||||
#define BITCOIN_MINER_H
|
#include <cstdint>
|
||||||
|
#include <std::string>
|
||||||
#include <stdint.h>
|
#include <std::vector>
|
||||||
|
#include <memory>
|
||||||
|
#include <utility>
|
||||||
class CBlock;
|
class CBlock;
|
||||||
class CBlockHeader;
|
class CBlockHeader;
|
||||||
class CBlockIndex;
|
class CBlockIndex;
|
||||||
@@ -33,4 +35,4 @@ void BitcoinMiner(CWallet* pwallet, bool fProofOfStake);
|
|||||||
extern double dHashesPerSec;
|
extern double dHashesPerSec;
|
||||||
extern int64_t nHPSTimerStart;
|
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) 2009-2014 The Bitcoin developers
|
||||||
// Copyright (c) 2014-2015 The Dash developers
|
// Copyright (c) 2014-2015 The Dash developers
|
||||||
// Copyright (c) 2015-2018 The PIVX developers
|
// Copyright (c) 2015-2018 The PIVX developers
|
||||||
|
// Copyright (c) 2026 Agrarian Developers
|
||||||
// Distributed under the MIT/X11 software license, see the accompanying
|
// Distributed under the MIT/X11 software license, see the accompanying
|
||||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
// 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 PastDifficultyAverage;
|
||||||
uint256 PastDifficultyAveragePrev;
|
uint256 PastDifficultyAveragePrev;
|
||||||
|
|
||||||
if (BlockLastSolved == NULL || BlockLastSolved->nHeight == 0 || BlockLastSolved->nHeight < PastBlocksMin) {
|
if (BlockLastSolved == nullptr || BlockLastSolved->nHeight == 0 || BlockLastSolved->nHeight < PastBlocksMin) {
|
||||||
return Params().ProofOfWorkLimit().GetCompact();
|
return Params().ProofOfWorkLimit().GetCompact();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -85,7 +86,7 @@ unsigned int GetNextWorkRequired(const CBlockIndex* pindexLast, const CBlockHead
|
|||||||
}
|
}
|
||||||
LastBlockTime = BlockReading->GetBlockTime();
|
LastBlockTime = BlockReading->GetBlockTime();
|
||||||
|
|
||||||
if (BlockReading->pprev == NULL) {
|
if (BlockReading->pprev == nullptr) {
|
||||||
assert(BlockReading);
|
assert(BlockReading);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,14 +2,13 @@
|
|||||||
// Copyright (c) 2009-2014 The Bitcoin developers
|
// Copyright (c) 2009-2014 The Bitcoin developers
|
||||||
// Copyright (c) 2014-2015 The Dash developers
|
// Copyright (c) 2014-2015 The Dash developers
|
||||||
// Copyright (c) 2017-2018 The PIVX developers
|
// Copyright (c) 2017-2018 The PIVX developers
|
||||||
|
// Copyright (c) 2026 Agrarian Developers
|
||||||
// Distributed under the MIT/X11 software license, see the accompanying
|
// Distributed under the MIT/X11 software license, see the accompanying
|
||||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||||
|
#ifndef AGRARIAN_BITCOIN_POW_H
|
||||||
#ifndef BITCOIN_POW_H
|
#define AGRARIAN_BITCOIN_POW_H
|
||||||
#define BITCOIN_POW_H
|
#include <cstdint>
|
||||||
|
#include <cstddef>
|
||||||
#include <stdint.h>
|
|
||||||
|
|
||||||
class CBlockHeader;
|
class CBlockHeader;
|
||||||
class CBlockIndex;
|
class CBlockIndex;
|
||||||
class uint256;
|
class uint256;
|
||||||
@@ -29,4 +28,4 @@ unsigned int GetNextWorkRequired(const CBlockIndex* pindexLast, const CBlockHead
|
|||||||
bool CheckProofOfWork(uint256 hash, unsigned int nBits);
|
bool CheckProofOfWork(uint256 hash, unsigned int nBits);
|
||||||
uint256 GetBlockProof(const CBlockIndex& block);
|
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) 2009-2014 The Bitcoin developers
|
||||||
// Copyright (c) 2014-2015 The Dash developers
|
// Copyright (c) 2014-2015 The Dash developers
|
||||||
// Copyright (c) 2015-2019 The PIVX developers
|
// Copyright (c) 2015-2019 The PIVX developers
|
||||||
|
// Copyright (c) 2026 Agrarian Developers
|
||||||
// Distributed under the MIT software license, see the accompanying
|
// Distributed under the MIT software license, see the accompanying
|
||||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||||
|
|
||||||
@@ -22,7 +23,7 @@
|
|||||||
#include "wallet/wallet.h"
|
#include "wallet/wallet.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <cstdint>
|
||||||
|
|
||||||
#include <boost/assign/list_of.hpp>
|
#include <boost/assign/list_of.hpp>
|
||||||
|
|
||||||
@@ -42,7 +43,7 @@ UniValue GetNetworkHashPS(int lookup, int height)
|
|||||||
if (height >= 0 && height < chainActive.Height())
|
if (height >= 0 && height < chainActive.Height())
|
||||||
pb = chainActive[height];
|
pb = chainActive[height];
|
||||||
|
|
||||||
if (pb == NULL || !pb->nHeight)
|
if (pb == nullptr || !pb->nHeight)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
// If lookup is -1, then use blocks since last difficulty change.
|
// If lookup is -1, then use blocks since last difficulty change.
|
||||||
@@ -172,7 +173,7 @@ UniValue generate(const UniValue& params, bool fHelp)
|
|||||||
++pblock->nNonce;
|
++pblock->nNonce;
|
||||||
}
|
}
|
||||||
CValidationState state;
|
CValidationState state;
|
||||||
if (!ProcessNewBlock(state, NULL, pblock))
|
if (!ProcessNewBlock(state, nullptr, pblock))
|
||||||
throw JSONRPCError(RPC_INTERNAL_ERROR, "ProcessNewBlock, block not accepted");
|
throw JSONRPCError(RPC_INTERNAL_ERROR, "ProcessNewBlock, block not accepted");
|
||||||
++nHeight;
|
++nHeight;
|
||||||
fPoS = nHeight >= Params().LAST_POW_BLOCK();
|
fPoS = nHeight >= Params().LAST_POW_BLOCK();
|
||||||
@@ -201,7 +202,7 @@ UniValue setgenerate(const UniValue& params, bool fHelp)
|
|||||||
"\nTurn off generation\n" + HelpExampleCli("setgenerate", "false") +
|
"\nTurn off generation\n" + HelpExampleCli("setgenerate", "false") +
|
||||||
"\nUsing json rpc\n" + HelpExampleRpc("setgenerate", "true, 1"));
|
"\nUsing json rpc\n" + HelpExampleRpc("setgenerate", "true, 1"));
|
||||||
|
|
||||||
if (pwalletMain == NULL)
|
if (pwalletMain == nullptr)
|
||||||
throw JSONRPCError(RPC_METHOD_NOT_FOUND, "Method not found (disabled)");
|
throw JSONRPCError(RPC_METHOD_NOT_FOUND, "Method not found (disabled)");
|
||||||
|
|
||||||
if (Params().MineBlocksOnDemand())
|
if (Params().MineBlocksOnDemand())
|
||||||
@@ -515,7 +516,7 @@ UniValue getblocktemplate(const UniValue& params, bool fHelp)
|
|||||||
if (pindexPrev != chainActive.Tip() ||
|
if (pindexPrev != chainActive.Tip() ||
|
||||||
(mempool.GetTransactionsUpdated() != nTransactionsUpdatedLast && GetTime() - nStart > 5)) {
|
(mempool.GetTransactionsUpdated() != nTransactionsUpdatedLast && GetTime() - nStart > 5)) {
|
||||||
// Clear pindexPrev so future calls make a new block, despite any failures from here on
|
// 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
|
// Store the chainActive.Tip() used before CreateNewBlock, to avoid races
|
||||||
nTransactionsUpdatedLast = mempool.GetTransactionsUpdated();
|
nTransactionsUpdatedLast = mempool.GetTransactionsUpdated();
|
||||||
@@ -525,7 +526,7 @@ UniValue getblocktemplate(const UniValue& params, bool fHelp)
|
|||||||
// Create new block
|
// Create new block
|
||||||
if (pblocktemplate) {
|
if (pblocktemplate) {
|
||||||
delete pblocktemplate;
|
delete pblocktemplate;
|
||||||
pblocktemplate = NULL;
|
pblocktemplate = nullptr;
|
||||||
}
|
}
|
||||||
CScript scriptDummy = CScript() << OP_TRUE;
|
CScript scriptDummy = CScript() << OP_TRUE;
|
||||||
pblocktemplate = CreateNewBlock(scriptDummy, pwalletMain, false);
|
pblocktemplate = CreateNewBlock(scriptDummy, pwalletMain, false);
|
||||||
@@ -691,7 +692,7 @@ UniValue submitblock(const UniValue& params, bool fHelp)
|
|||||||
CValidationState state;
|
CValidationState state;
|
||||||
submitblock_StateCatcher sc(block.GetHash());
|
submitblock_StateCatcher sc(block.GetHash());
|
||||||
RegisterValidationInterface(&sc);
|
RegisterValidationInterface(&sc);
|
||||||
bool fAccepted = ProcessNewBlock(state, NULL, &block);
|
bool fAccepted = ProcessNewBlock(state, nullptr, &block);
|
||||||
UnregisterValidationInterface(&sc);
|
UnregisterValidationInterface(&sc);
|
||||||
if (fBlockPresent) {
|
if (fBlockPresent) {
|
||||||
if (fAccepted && !sc.found)
|
if (fAccepted && !sc.found)
|
||||||
|
|||||||
+148
-96
@@ -1,6 +1,7 @@
|
|||||||
// Copyright (c) 2009-2010 Satoshi Nakamoto
|
// Copyright (c) 2009-2010 Satoshi Nakamoto
|
||||||
// Copyright (c) 2009-2014 The Bitcoin developers
|
// Copyright (c) 2009-2014 The Bitcoin developers
|
||||||
// Copyright (c) 2016-2019 The PIVX developers
|
// Copyright (c) 2016-2019 The PIVX developers
|
||||||
|
// Copyright (c) 2026 Agrarian Developers
|
||||||
// Distributed under the MIT/X11 software license, see the accompanying
|
// Distributed under the MIT/X11 software license, see the accompanying
|
||||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||||
|
|
||||||
@@ -11,45 +12,55 @@
|
|||||||
#include "uint256.h"
|
#include "uint256.h"
|
||||||
#include "zagr/accumulators.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>
|
#include <boost/thread.hpp>
|
||||||
|
|
||||||
using namespace std;
|
namespace {
|
||||||
using namespace libzerocoin;
|
|
||||||
|
|
||||||
void static BatchWriteCoins(CLevelDBBatch& batch, const uint256& hash, const CCoins& coins)
|
void BatchWriteCoins(CLevelDBBatch& batch, const uint256& hash, const CCoins& coins)
|
||||||
{
|
{
|
||||||
if (coins.IsPruned())
|
if (coins.IsPruned()) {
|
||||||
batch.Erase(make_pair('c', hash));
|
batch.Erase(std::make_pair('c', hash));
|
||||||
else
|
} else {
|
||||||
batch.Write(make_pair('c', hash), coins);
|
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);
|
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
|
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
|
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 CCoinsViewDB::GetBestBlock() const
|
||||||
{
|
{
|
||||||
uint256 hashBestChain;
|
uint256 hashBestChain;
|
||||||
if (!db.Read('B', hashBestChain))
|
if (!db.Read('B', hashBestChain)) {
|
||||||
return uint256(0);
|
return uint256(0);
|
||||||
|
}
|
||||||
return hashBestChain;
|
return hashBestChain;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -58,39 +69,47 @@ bool CCoinsViewDB::BatchWrite(CCoinsMap& mapCoins, const uint256& hashBlock)
|
|||||||
CLevelDBBatch batch;
|
CLevelDBBatch batch;
|
||||||
size_t count = 0;
|
size_t count = 0;
|
||||||
size_t changed = 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) {
|
if (it->second.flags & CCoinsCacheEntry::DIRTY) {
|
||||||
BatchWriteCoins(batch, it->first, it->second.coins);
|
BatchWriteCoins(batch, it->first, it->second.coins);
|
||||||
changed++;
|
++changed;
|
||||||
}
|
}
|
||||||
count++;
|
++count;
|
||||||
CCoinsMap::iterator itOld = it++;
|
|
||||||
|
auto itOld = it++;
|
||||||
mapCoins.erase(itOld);
|
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);
|
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)
|
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)
|
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)
|
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)
|
bool CBlockTreeDB::WriteLastBlockFile(int nFile)
|
||||||
@@ -100,9 +119,9 @@ bool CBlockTreeDB::WriteLastBlockFile(int nFile)
|
|||||||
|
|
||||||
bool CBlockTreeDB::WriteReindexing(bool fReindexing)
|
bool CBlockTreeDB::WriteReindexing(bool fReindexing)
|
||||||
{
|
{
|
||||||
if (fReindexing)
|
if (fReindexing) {
|
||||||
return Write('R', '1');
|
return Write('R', '1');
|
||||||
else
|
}
|
||||||
return Erase('R');
|
return Erase('R');
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -119,53 +138,70 @@ bool CBlockTreeDB::ReadLastBlockFile(int& nFile)
|
|||||||
|
|
||||||
bool CCoinsViewDB::GetStats(CCoinsStats& stats) const
|
bool CCoinsViewDB::GetStats(CCoinsStats& stats) const
|
||||||
{
|
{
|
||||||
/* It seems that there are no "const iterators" for LevelDB. Since we
|
// LevelDB iterators are non-const; we only read so const_cast the wrapper.
|
||||||
only need read operations on it, use a const-cast to get around
|
std::unique_ptr<leveldb::Iterator> pcursor(const_cast<CLevelDBWrapper*>(&db)->NewIterator());
|
||||||
that restriction. */
|
|
||||||
boost::scoped_ptr<leveldb::Iterator> pcursor(const_cast<CLevelDBWrapper*>(&db)->NewIterator());
|
|
||||||
pcursor->SeekToFirst();
|
pcursor->SeekToFirst();
|
||||||
|
|
||||||
CHashWriter ss(SER_GETHASH, PROTOCOL_VERSION);
|
CHashWriter ss(SER_GETHASH, PROTOCOL_VERSION);
|
||||||
stats.hashBlock = GetBestBlock();
|
stats.hashBlock = GetBestBlock();
|
||||||
ss << stats.hashBlock;
|
ss << stats.hashBlock;
|
||||||
|
|
||||||
CAmount nTotalAmount = 0;
|
CAmount nTotalAmount = 0;
|
||||||
|
|
||||||
while (pcursor->Valid()) {
|
while (pcursor->Valid()) {
|
||||||
boost::this_thread::interruption_point();
|
boost::this_thread::interruption_point();
|
||||||
try {
|
try {
|
||||||
leveldb::Slice slKey = pcursor->key();
|
const leveldb::Slice slKey = pcursor->key();
|
||||||
CDataStream ssKey(slKey.data(), slKey.data() + slKey.size(), SER_DISK, CLIENT_VERSION);
|
CDataStream ssKey(slKey.data(), slKey.data() + slKey.size(), SER_DISK, CLIENT_VERSION);
|
||||||
|
|
||||||
char chType;
|
char chType;
|
||||||
ssKey >> chType;
|
ssKey >> chType;
|
||||||
|
|
||||||
if (chType == 'c') {
|
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);
|
CDataStream ssValue(slValue.data(), slValue.data() + slValue.size(), SER_DISK, CLIENT_VERSION);
|
||||||
|
|
||||||
CCoins coins;
|
CCoins coins;
|
||||||
ssValue >> coins;
|
ssValue >> coins;
|
||||||
|
|
||||||
uint256 txhash;
|
uint256 txhash;
|
||||||
ssKey >> txhash;
|
ssKey >> txhash;
|
||||||
|
|
||||||
ss << txhash;
|
ss << txhash;
|
||||||
ss << VARINT(coins.nVersion);
|
ss << VARINT(coins.nVersion);
|
||||||
ss << (coins.fCoinBase ? 'c' : 'n');
|
ss << (coins.fCoinBase ? 'c' : 'n');
|
||||||
ss << VARINT(coins.nHeight);
|
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];
|
const CTxOut& out = coins.vout[i];
|
||||||
if (!out.IsNull()) {
|
if (!out.IsNull()) {
|
||||||
stats.nTransactionOutputs++;
|
++stats.nTransactionOutputs;
|
||||||
ss << VARINT(i + 1);
|
ss << VARINT(i + 1);
|
||||||
ss << out;
|
ss << out;
|
||||||
nTotalAmount += out.nValue;
|
nTotalAmount += out.nValue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
stats.nSerializedSize += 32 + slValue.size();
|
stats.nSerializedSize += 32 + slValue.size();
|
||||||
ss << VARINT(0);
|
ss << VARINT(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
pcursor->Next();
|
pcursor->Next();
|
||||||
} catch (std::exception& e) {
|
} catch (const std::exception& e) {
|
||||||
return error("%s : Deserialize or I/O error - %s", __func__, e.what());
|
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.hashSerialized = ss.GetHash();
|
||||||
stats.nTotalAmount = nTotalAmount;
|
stats.nTotalAmount = nTotalAmount;
|
||||||
return true;
|
return true;
|
||||||
@@ -173,14 +209,15 @@ bool CCoinsViewDB::GetStats(CCoinsStats& stats) const
|
|||||||
|
|
||||||
bool CBlockTreeDB::ReadTxIndex(const uint256& txid, CDiskTxPos& pos)
|
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)
|
bool CBlockTreeDB::WriteTxIndex(const std::vector<std::pair<uint256, CDiskTxPos>>& vect)
|
||||||
{
|
{
|
||||||
CLevelDBBatch batch;
|
CLevelDBBatch batch;
|
||||||
for (std::vector<std::pair<uint256, CDiskTxPos> >::const_iterator it = vect.begin(); it != vect.end(); it++)
|
for (const auto& it : vect) {
|
||||||
batch.Write(make_pair('t', it->first), it->second);
|
batch.Write(std::make_pair('t', it.first), it.second);
|
||||||
|
}
|
||||||
return WriteBatch(batch);
|
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)
|
bool CBlockTreeDB::ReadFlag(const std::string& name, bool& fValue)
|
||||||
{
|
{
|
||||||
char ch;
|
char ch;
|
||||||
if (!Read(std::make_pair('F', name), ch))
|
if (!Read(std::make_pair('F', name), ch)) {
|
||||||
return false;
|
return false;
|
||||||
fValue = ch == '1';
|
}
|
||||||
|
fValue = (ch == '1');
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -210,24 +248,30 @@ bool CBlockTreeDB::ReadInt(const std::string& name, int& nValue)
|
|||||||
|
|
||||||
bool CBlockTreeDB::LoadBlockIndexGuts()
|
bool CBlockTreeDB::LoadBlockIndexGuts()
|
||||||
{
|
{
|
||||||
boost::scoped_ptr<leveldb::Iterator> pcursor(NewIterator());
|
std::unique_ptr<leveldb::Iterator> pcursor(NewIterator());
|
||||||
|
|
||||||
CDataStream ssKeySet(SER_DISK, CLIENT_VERSION);
|
CDataStream ssKeySet(SER_DISK, CLIENT_VERSION);
|
||||||
ssKeySet << make_pair('b', uint256(0));
|
ssKeySet << std::make_pair('b', uint256(0));
|
||||||
pcursor->Seek(ssKeySet.str());
|
pcursor->Seek(ssKeySet.str());
|
||||||
|
|
||||||
// Load mapBlockIndex
|
|
||||||
uint256 nPreviousCheckpoint;
|
uint256 nPreviousCheckpoint;
|
||||||
|
|
||||||
while (pcursor->Valid()) {
|
while (pcursor->Valid()) {
|
||||||
boost::this_thread::interruption_point();
|
boost::this_thread::interruption_point();
|
||||||
try {
|
try {
|
||||||
leveldb::Slice slKey = pcursor->key();
|
const leveldb::Slice slKey = pcursor->key();
|
||||||
CDataStream ssKey(slKey.data(), slKey.data() + slKey.size(), SER_DISK, CLIENT_VERSION);
|
CDataStream ssKey(slKey.data(), slKey.data() + slKey.size(), SER_DISK, CLIENT_VERSION);
|
||||||
|
|
||||||
char chType;
|
char chType;
|
||||||
ssKey >> 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);
|
CDataStream ssValue(slValue.data(), slValue.data() + slValue.size(), SER_DISK, CLIENT_VERSION);
|
||||||
|
|
||||||
CDiskBlockIndex diskindex;
|
CDiskBlockIndex diskindex;
|
||||||
ssValue >> diskindex;
|
ssValue >> diskindex;
|
||||||
|
|
||||||
@@ -247,12 +291,12 @@ bool CBlockTreeDB::LoadBlockIndexGuts()
|
|||||||
pindexNew->nStatus = diskindex.nStatus;
|
pindexNew->nStatus = diskindex.nStatus;
|
||||||
pindexNew->nTx = diskindex.nTx;
|
pindexNew->nTx = diskindex.nTx;
|
||||||
|
|
||||||
//zerocoin
|
// Zerocoin
|
||||||
pindexNew->nAccumulatorCheckpoint = diskindex.nAccumulatorCheckpoint;
|
pindexNew->nAccumulatorCheckpoint = diskindex.nAccumulatorCheckpoint;
|
||||||
pindexNew->mapZerocoinSupply = diskindex.mapZerocoinSupply;
|
pindexNew->mapZerocoinSupply = diskindex.mapZerocoinSupply;
|
||||||
pindexNew->vMintDenominationsInBlock = diskindex.vMintDenominationsInBlock;
|
pindexNew->vMintDenominationsInBlock = diskindex.vMintDenominationsInBlock;
|
||||||
|
|
||||||
//Proof Of Stake
|
// Proof of Stake
|
||||||
pindexNew->nMint = diskindex.nMint;
|
pindexNew->nMint = diskindex.nMint;
|
||||||
pindexNew->nMoneySupply = diskindex.nMoneySupply;
|
pindexNew->nMoneySupply = diskindex.nMoneySupply;
|
||||||
pindexNew->nFlags = diskindex.nFlags;
|
pindexNew->nFlags = diskindex.nFlags;
|
||||||
@@ -261,25 +305,25 @@ bool CBlockTreeDB::LoadBlockIndexGuts()
|
|||||||
pindexNew->nStakeTime = diskindex.nStakeTime;
|
pindexNew->nStakeTime = diskindex.nStakeTime;
|
||||||
pindexNew->hashProofOfStake = diskindex.hashProofOfStake;
|
pindexNew->hashProofOfStake = diskindex.hashProofOfStake;
|
||||||
|
|
||||||
if (pindexNew->nHeight <= Params().LAST_POW_BLOCK()) {
|
// Hybrid PoW+PoS: only enforce PoW proof check for PoW blocks (not just height).
|
||||||
if (!CheckProofOfWork(pindexNew->GetBlockHash(), pindexNew->nBits))
|
// 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());
|
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) {
|
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.
|
// 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);
|
LoadAccumulatorValuesFromDB(pindexNew->nAccumulatorCheckpoint);
|
||||||
|
}
|
||||||
nPreviousCheckpoint = pindexNew->nAccumulatorCheckpoint;
|
nPreviousCheckpoint = pindexNew->nAccumulatorCheckpoint;
|
||||||
}
|
}
|
||||||
|
|
||||||
pcursor->Next();
|
pcursor->Next();
|
||||||
} else {
|
} catch (const std::exception& e) {
|
||||||
break; // if shutdown requested or finished loading block index
|
|
||||||
}
|
|
||||||
} catch (std::exception& e) {
|
|
||||||
return error("%s : Deserialize or I/O error - %s", __func__, e.what());
|
return error("%s : Deserialize or I/O error - %s", __func__, e.what());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -287,7 +331,8 @@ bool CBlockTreeDB::LoadBlockIndexGuts()
|
|||||||
return true;
|
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;
|
CLevelDBBatch batch;
|
||||||
size_t count = 0;
|
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;
|
for (const auto& it : mintInfo) {
|
||||||
uint256 hash = GetPubCoinHash(pubCoin.getValue());
|
const libzerocoin::PublicCoin& pubCoin = it.first;
|
||||||
batch.Write(make_pair('m', hash), it->second);
|
const uint256 hash = GetPubCoinHash(pubCoin.getValue());
|
||||||
|
batch.Write(std::make_pair('m', hash), it.second);
|
||||||
++count;
|
++count;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -313,25 +359,26 @@ bool CZerocoinDB::ReadCoinMint(const CBigNum& bnPubcoin, uint256& hashTx)
|
|||||||
|
|
||||||
bool CZerocoinDB::ReadCoinMint(const uint256& hashPubcoin, 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)
|
bool CZerocoinDB::EraseCoinMint(const CBigNum& bnPubcoin)
|
||||||
{
|
{
|
||||||
uint256 hash = GetPubCoinHash(bnPubcoin);
|
const uint256 hash = GetPubCoinHash(bnPubcoin);
|
||||||
return Erase(make_pair('m', hash));
|
return Erase(std::make_pair('m', hash));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CZerocoinDB::WriteCoinSpendBatch(const std::vector<std::pair<libzerocoin::CoinSpend, uint256>>& spendInfo)
|
bool CZerocoinDB::WriteCoinSpendBatch(const std::vector<std::pair<libzerocoin::CoinSpend, uint256>>& spendInfo)
|
||||||
{
|
{
|
||||||
CLevelDBBatch batch;
|
CLevelDBBatch batch;
|
||||||
size_t count = 0;
|
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);
|
CDataStream ss(SER_GETHASH, 0);
|
||||||
ss << bnSerial;
|
ss << bnSerial;
|
||||||
uint256 hash = Hash(ss.begin(), ss.end());
|
const uint256 hash = Hash(ss.begin(), ss.end());
|
||||||
batch.Write(make_pair('s', hash), it->second);
|
batch.Write(std::make_pair('s', hash), it.second);
|
||||||
++count;
|
++count;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -343,64 +390,69 @@ bool CZerocoinDB::ReadCoinSpend(const CBigNum& bnSerial, uint256& txHash)
|
|||||||
{
|
{
|
||||||
CDataStream ss(SER_GETHASH, 0);
|
CDataStream ss(SER_GETHASH, 0);
|
||||||
ss << bnSerial;
|
ss << bnSerial;
|
||||||
uint256 hash = Hash(ss.begin(), ss.end());
|
const uint256 hash = Hash(ss.begin(), ss.end());
|
||||||
|
return Read(std::make_pair('s', hash), txHash);
|
||||||
return Read(make_pair('s', hash), txHash);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CZerocoinDB::ReadCoinSpend(const uint256& hashSerial, uint256& 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)
|
bool CZerocoinDB::EraseCoinSpend(const CBigNum& bnSerial)
|
||||||
{
|
{
|
||||||
CDataStream ss(SER_GETHASH, 0);
|
CDataStream ss(SER_GETHASH, 0);
|
||||||
ss << bnSerial;
|
ss << bnSerial;
|
||||||
uint256 hash = Hash(ss.begin(), ss.end());
|
const uint256 hash = Hash(ss.begin(), ss.end());
|
||||||
|
return Erase(std::make_pair('s', hash));
|
||||||
return Erase(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);
|
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);
|
CDataStream ssKeySet(SER_DISK, CLIENT_VERSION);
|
||||||
ssKeySet << make_pair(type, uint256(0));
|
ssKeySet << std::make_pair(type, uint256(0));
|
||||||
pcursor->Seek(ssKeySet.str());
|
pcursor->Seek(ssKeySet.str());
|
||||||
// Load mapBlockIndex
|
|
||||||
std::set<uint256> setDelete;
|
std::set<uint256> setDelete;
|
||||||
|
|
||||||
while (pcursor->Valid()) {
|
while (pcursor->Valid()) {
|
||||||
boost::this_thread::interruption_point();
|
boost::this_thread::interruption_point();
|
||||||
try {
|
try {
|
||||||
leveldb::Slice slKey = pcursor->key();
|
const leveldb::Slice slKey = pcursor->key();
|
||||||
CDataStream ssKey(slKey.data(), slKey.data() + slKey.size(), SER_DISK, CLIENT_VERSION);
|
CDataStream ssKey(slKey.data(), slKey.data() + slKey.size(), SER_DISK, CLIENT_VERSION);
|
||||||
|
|
||||||
char chType;
|
char chType;
|
||||||
ssKey >> 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);
|
CDataStream ssValue(slValue.data(), slValue.data() + slValue.size(), SER_DISK, CLIENT_VERSION);
|
||||||
|
|
||||||
uint256 hash;
|
uint256 hash;
|
||||||
ssValue >> hash;
|
ssValue >> hash;
|
||||||
setDelete.insert(hash);
|
setDelete.insert(hash);
|
||||||
|
|
||||||
pcursor->Next();
|
pcursor->Next();
|
||||||
} else {
|
} catch (const std::exception& e) {
|
||||||
break; // if shutdown requested or finished loading block index
|
|
||||||
}
|
|
||||||
} catch (std::exception& e) {
|
|
||||||
return error("%s : Deserialize or I/O error - %s", __func__, e.what());
|
return error("%s : Deserialize or I/O error - %s", __func__, e.what());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto& hash : setDelete) {
|
for (const auto& hash : setDelete) {
|
||||||
if (!Erase(make_pair(type, hash)))
|
if (!Erase(std::make_pair(type, hash))) {
|
||||||
LogPrintf("%s: error failed to delete %s\n", __func__, hash.GetHex());
|
LogPrintf("%s: error failed to delete %s\n", __func__, hash.GetHex());
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -408,16 +460,16 @@ bool CZerocoinDB::WipeCoins(std::string strType)
|
|||||||
bool CZerocoinDB::WriteAccumulatorValue(const uint32_t& nChecksum, const CBigNum& bnValue)
|
bool CZerocoinDB::WriteAccumulatorValue(const uint32_t& nChecksum, const CBigNum& bnValue)
|
||||||
{
|
{
|
||||||
LogPrint("zero", "%s : checksum:%d val:%s\n", __func__, nChecksum, bnValue.GetHex());
|
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)
|
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)
|
bool CZerocoinDB::EraseAccumulatorValue(const uint32_t& nChecksum)
|
||||||
{
|
{
|
||||||
LogPrint("zero", "%s : checksum:%d\n", __func__, 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