diff --git a/AUTHORS b/AUTHORS index 20bd581e2..54de6e03c 100644 --- a/AUTHORS +++ b/AUTHORS @@ -2,7 +2,7 @@ Duke Leto https://git.hush.is/duke https://github.com/leto Miodrag https://github.com/miodragpop -jahway603 https://git.hush.is/jahway603 https://github.com/jahway603 +jahway603 https://git.hush.is/jahway603 https://codeberg.org/jahway603 https://github.com/jahway603 # The SuperNET Developers diff --git a/antispam b/antispam new file mode 100755 index 000000000..143c8ef32 --- /dev/null +++ b/antispam @@ -0,0 +1,4 @@ +#!/bin/sh + +echo "./src/hush-cli -ac_name=ANTISPAM $@" +./src/hush-cli -ac_name=ANTISPAM "$@" diff --git a/configure.ac b/configure.ac index 728795f41..a972c327e 100644 --- a/configure.ac +++ b/configure.ac @@ -2,8 +2,8 @@ dnl require autoconf 2.60 (AS_ECHO/AS_ECHO_N) AC_PREREQ([2.60]) define(_CLIENT_VERSION_MAJOR, 3) dnl Must be kept in sync with src/clientversion.h , ugh! -define(_CLIENT_VERSION_MINOR, 9) -define(_CLIENT_VERSION_REVISION, 4) +define(_CLIENT_VERSION_MINOR, 10) +define(_CLIENT_VERSION_REVISION, 0) define(_CLIENT_VERSION_BUILD, 50) define(_ZC_BUILD_VAL, m4_if(m4_eval(_CLIENT_VERSION_BUILD < 25), 1, m4_incr(_CLIENT_VERSION_BUILD), m4_eval(_CLIENT_VERSION_BUILD < 50), 1, m4_eval(_CLIENT_VERSION_BUILD - 24), m4_eval(_CLIENT_VERSION_BUILD == 50), 1, , m4_eval(_CLIENT_VERSION_BUILD - 50))) define(_CLIENT_VERSION_SUFFIX, m4_if(m4_eval(_CLIENT_VERSION_BUILD < 25), 1, _CLIENT_VERSION_REVISION-beta$1, m4_eval(_CLIENT_VERSION_BUILD < 50), 1, _CLIENT_VERSION_REVISION-rc$1, m4_eval(_CLIENT_VERSION_BUILD == 50), 1, _CLIENT_VERSION_REVISION, _CLIENT_VERSION_REVISION-$1))) diff --git a/contrib/sda_checkpoints.pl b/contrib/sda_checkpoints.pl old mode 100644 new mode 100755 index ab468af86..e93c497e7 --- a/contrib/sda_checkpoints.pl +++ b/contrib/sda_checkpoints.pl @@ -12,8 +12,8 @@ my $hush = "./src/hush-cli"; my $getblock= "$hush getblock"; my $gethash = "$hush getblockhash"; my $gettree = "$hush getblockmerkletree"; -my $start = shift || 1190000; -my $end = shift || 1260000; +my $start = shift || 1390000; +my $end = shift || 1422000; my $stride = shift || 10000; my $blocks = qx{$hush getblockcount}; @@ -41,8 +41,12 @@ while (1) { chomp $merkle; chomp $blockhash; chomp $blocktime; - $blocktime =~ s/^\s+|\s+$//g ; - print qq{{\n\t"network": "main",\n\t"height": "$block",\n\t"hash": "$blockhash",\n\t$blocktime\n\t"saplingTree": "$merkle"\n},\n}; + $blocktime =~ s/^\s+|\s+$//g; + my $checkpoint = qq{{\n\t"network": "main",\n\t"height": "$block",\n\t"hash": "$blockhash",\n\t$blocktime\n\t"saplingTree": "$merkle"\n}\n}; + my $filename = "$block.json"; + open(FH, '>', $filename) or die $!; + print FH $checkpoint; + close(FH); $block += $stride; } diff --git a/depends/packages/bdb.mk b/depends/packages/bdb.mk index c8f677490..6b8b8e144 100644 --- a/depends/packages/bdb.mk +++ b/depends/packages/bdb.mk @@ -14,7 +14,7 @@ ifneq ($(build_os),darwin) $(package)_config_opts_darwin=--disable-atomicsupport endif $(package)_config_opts_aarch64=--disable-atomicsupport -$(package)_cxxflags=-std=c++11 +$(package)_cxxflags+=-std=c++11 endef define $(package)_preprocess_cmds diff --git a/depends/packages/boost.mk b/depends/packages/boost.mk index fde0c92c3..0062c0bdb 100644 --- a/depends/packages/boost.mk +++ b/depends/packages/boost.mk @@ -22,7 +22,7 @@ $(package)_archiver_$(host_os)=$($(package)_ar) $(package)_toolset_darwin=gcc $(package)_archiver_darwin=$($(package)_ar) $(package)_config_libraries=chrono,filesystem,program_options,system,thread,test -$(package)_cxxflags=-std=c++11 -fvisibility=hidden +$(package)_cxxflags+=-std=c++11 -fvisibility=hidden $(package)_cxxflags_linux=-fPIC endef diff --git a/depends/packages/libcurl.mk b/depends/packages/libcurl.mk index 1ece9ce64..92c319a70 100644 --- a/depends/packages/libcurl.mk +++ b/depends/packages/libcurl.mk @@ -1,10 +1,18 @@ package=libcurl -$(package)_version=7.77.0 + +ifeq ($(host_os),mingw32) +$(package)_version=7.67.0 +$(package)_file_name=curl-$($(package)_version).tar.gz +$(package)_sha256_hash=52af3361cf806330b88b4fe6f483b6844209d47ae196ac46da4de59bb361ab02 +else +$(package)_version=8.4.0 +$(package)_file_name=curl-$($(package)_version).tar.gz +$(package)_sha256_hash=816e41809c043ff285e8c0f06a75a1fa250211bbfb2dc0a037eeef39f1a9e427 +endif + $(package)_dependencies=wolfssl $(package)_download_path=https://curl.haxx.se/download -$(package)_file_name=curl-$($(package)_version).tar.gz -$(package)_sha256_hash=b0a3428acb60fa59044c4d0baae4e4fc09ae9af1d8a3aa84b2e3fbcd99841f77 -$(package)_config_opts_linux=--disable-shared --enable-static --with-wolfssl --without-ssl --prefix=$(host_prefix) --host=$(host) +$(package)_config_opts_linux=--disable-shared --enable-static --without-ssl --prefix=$(host_prefix) --host=$(host) $(package)_config_opts_mingw32=--enable-mingw --disable-shared --enable-static --with-wolfssl --without-ssl --prefix=$(host_prefix) --host=x86_64-w64-mingw32 $(package)_config_opts_darwin=--disable-shared --enable-static --with-wolfssl --without-ssl --prefix=$(host_prefix) $(package)_cflags_darwin=-mmacosx-version-min=10.9 diff --git a/depends/packages/rust.mk b/depends/packages/rust.mk index 6bae892a2..61420a40c 100644 --- a/depends/packages/rust.mk +++ b/depends/packages/rust.mk @@ -7,6 +7,8 @@ $(package)_file_name_darwin=rust-$($(package)_version)-x86_64-apple-darwin.tar.g $(package)_sha256_hash_darwin=f0dfba507192f9b5c330b5984ba71d57d434475f3d62bd44a39201e36fa76304 $(package)_file_name_mingw32=rust-$($(package)_version)-x86_64-pc-windows-gnu.tar.gz $(package)_sha256_hash_mingw32=358e1435347c67dbf33aa9cad6fe501a833d6633ed5d5aa1863d5dffa0349be9 +$(package)_file_name_aarch64_linux=rust-$($(package)_version)-aarch64-unknown-linux-gnu.tar.gz +$(package)_sha256_hash_aarch64_linux=60def40961728212da4b3a9767d5a2ddb748400e150a5f8a6d5aa0e1b8ba1cee # Mapping from GCC canonical hosts to Rust targets # If a mapping is not present, we assume they are identical, unless $host_os is diff --git a/doc/cjdns.md b/doc/cjdns.md new file mode 100644 index 000000000..4b47bb8ac --- /dev/null +++ b/doc/cjdns.md @@ -0,0 +1,115 @@ +# CJDNS support in Hush + +It is possible to run Hush over CJDNS, an encrypted IPv6 network that +uses public-key cryptography for address allocation and a distributed hash table +for routing. + +## What is CJDNS? + +CJDNS is like a distributed, shared VPN with multiple entry points where every +participant can reach any other participant. All participants use addresses from +the `fc00::/8` network (reserved IPv6 range). Installation and configuration is +done outside of Hush, similarly to a VPN (either in the host/OS or on +the network router). See https://github.com/cjdelisle/cjdns#readme and +https://github.com/hyperboria/docs#hyperboriadocs for more information. + +Compared to IPv4/IPv6, CJDNS provides end-to-end encryption and protects nodes +from traffic analysis and filtering. + +Used with Tor and I2P, CJDNS is a complementary option that can enhance network +redundancy and robustness for both the Hush network and individual nodes. + +Each network has different characteristics. For instance, Tor is widely used but +somewhat centralized. I2P connections have a source address and I2P is slow. +CJDNS is fast but does not hide the sender and the recipient from intermediate +routers. + +## Installing CJDNS and finding a peer to connect to the network + +To install and set up CJDNS, follow the instructions at +https://github.com/cjdelisle/cjdns#how-to-install-cjdns. + +You need to initiate an outbound connection to a peer on the CJDNS network +before it will work with your Hush node. This is described in steps +["2. Find a friend"](https://github.com/cjdelisle/cjdns#2-find-a-friend) and +["3. Connect your node to your friend's +node"](https://github.com/cjdelisle/cjdns#3-connect-your-node-to-your-friends-node) +in the CJDNS documentation. + +One quick way to accomplish these two steps is to query for available public +peers on [Hyperboria](https://github.com/hyperboria) by running the following: + +``` +git clone https://github.com/hyperboria/peers hyperboria-peers +cd hyperboria-peers +./testAvailable.py +``` + +For each peer, the `./testAvailable.py` script prints the filename of the peer's +credentials followed by the ping result. + +Choose one or several peers, copy their credentials from their respective files, +paste them into the relevant IPv4 or IPv6 "connectTo" JSON object in the +`cjdroute.conf` file you created in step ["1. Generate a new configuration +file"](https://github.com/cjdelisle/cjdns#1-generate-a-new-configuration-file), +and save the file. + +## Launching CJDNS + +Typically, CJDNS might be launched from its directory with +`sudo ./cjdroute < cjdroute.conf` and it sheds permissions after setting up the +[TUN](https://en.wikipedia.org/wiki/TUN/TAP) interface. You may also [launch it as an +unprivileged user](https://github.com/cjdelisle/cjdns/blob/master/doc/non-root-user.md) +with some additional setup. + +The network connection can be checked by running `./tools/peerStats` from the +CJDNS directory. + +## Run Hush with CJDNS + +Once you are connected to the CJDNS network, the following Hush +configuration option makes CJDNS peers automatically reachable: + +``` +-cjdnsreachable +``` + +When enabled, this option tells Hush that it is running in an +environment where a connection to an `fc00::/8` address will be to the CJDNS +network instead of to an [RFC4193](https://datatracker.ietf.org/doc/html/rfc4193) +IPv6 local network. This helps Hush perform better address management: + - Your node can consider incoming `fc00::/8` connections to be from the CJDNS + network rather than from an IPv6 private one. + - If one of your node's local addresses is `fc00::/8`, then it can choose to + gossip that address to peers. + +## Additional configuration options related to CJDNS + +``` +-onlynet=cjdns +``` + +Make automatic outbound connections only to CJDNS addresses. Inbound and manual +connections are not affected by this option. It can be specified multiple times +to allow multiple networks, e.g. onlynet=cjdns, onlynet=i2p, onlynet=onion. + +CJDNS support was added to Hush in version 3.9.3 and there may be fewer +CJDNS peers than Tor or IP ones. You can use `hush-cli -addrinfo` to see the +number of CJDNS addresses known to your node. + +In general, a node can be run with both an onion service and CJDNS (or any/all +of IPv4/IPv6/onion/I2P/CJDNS), which can provide a potential fallback if one of +the networks has issues. There are a number of ways to configure this; see +[doc/tor.md](https://git.hush.is/hush/hush3/src/branch/master/doc/tor.md) for +details. + +## CJDNS-related information in Hush + +There are several ways to see your CJDNS address in Hush: +- in the "Local addresses" output of CLI `-netinfo` +- in the "localaddresses" output of RPC `getnetworkinfo` + +To see which CJDNS peers your node is connected to, use `hush-cli -netinfo 4` +or the `getpeerinfo` RPC (i.e. `hush-cli getpeerinfo`). + +You can use the `getnodeaddresses` RPC to fetch a number of CJDNS peers known to your node; run `hush-cli help getnodeaddresses` for details. diff --git a/doc/config.md b/doc/config.md index 44df5ece3..e91b2f48d 100644 --- a/doc/config.md +++ b/doc/config.md @@ -38,10 +38,30 @@ Defaults to 1. This is a default option that should not be changed or things wil Defaults to 0. This option enables the "shielded index" which also calculates the "anonset" (anonymity set) also known as the "shielded pool". This data is avaailable in the getchaintxstats RPC, if zindex is enabled. Enabling this feature requires a full rescan or full sync from scratch, which is not done by default. If you don't do one of those things, your zindex stats will be incorrect. -# Mining options +# Mining and Stratum server options These options are only of interest to solo miners and mining pool operators.... +## stratum + +Defaults to off. This option enables a Stratum server. + +## stratumaddress=
+ +Defaults to none. This option sets a Stratum Mining address to use when special address of 'x' is sent by miner. + +## stratumbind= + +Defaults to: bind to all interfaces. This option Binds to given address to listen for Stratum work requests. Use [host]:port notation for IPv6. This option can be specified multiple times. + +## stratumport= + +Defaults to 19031 or 19031 for testnet. This option sets the to listen for Stratum work requests on. + +## stratumallowip= + +No default. This option allows Stratum work requests from specified source. Valid for are a single IP (e.g. 1.2.3.4), a network/netmask (e.g. 1.2.3.4/255.255.255.0) or a network/CIDR (e.g. 1.2.3.4/24). This option can be specified multiple times. + # Other options These options are not commonly used and likely on for advanced users and/or developers... @@ -56,4 +76,4 @@ Defaults to 0 in hushd, defaults to 1 in some GUI wallets. Maintain a timestamp ## spentindex=1 -Defaults to 0 in hushd, defaults to 1 in some GUI wallets. Maintain a full spent index, used to query the spending txid and input index for an outpoint \ No newline at end of file +Defaults to 0 in hushd, defaults to 1 in some GUI wallets. Maintain a full spent index, used to query the spending txid and input index for an outpoint diff --git a/doc/developer-notes.md b/doc/developer-notes.md index 77233221c..d8027f38e 100644 --- a/doc/developer-notes.md +++ b/doc/developer-notes.md @@ -104,6 +104,30 @@ We should also check a recent block height to verify it's working correctly. The * If you stop a node, and restart, are the stats from `getchaintxtstats` correct, i.e. the anonset stats? For instance, `shielded_pool_size` should be close to 500000, if it's close to or exactly 0, something is wrong. * Is there a new file called `zindex.dat` in `~/.hush/HUSH3/` ? * Is `zindex.dat` 149 bytes ? + +# Adding a PoW algorithm + +We will describe here the high-level ideas on how to add a new PoW algorithm to +the Hush codebase. Adding a new PoW algo means adding a new option to the `-ac_algo` +CLI param for HSC's. + + * Add the new value to the end of the `ASSETCHAINS_ALGORITHMS` array in `src/hush_utils.h` + * You cannot add it to the front because the first element is the default "equihash" + * You will also need to add a new constant, such as `ASSETCHAINS_FOOHASH` to `src/hush_globals.h` + * Increase the value of `ASSETCHAINS_NUMALGOS` by one + * This value cannot be automatically be determined by the length of the above array because Equihash has different supported variants of (N,K) values + * Add the new PoW mining library to a subdirectory in src, such as RandomX official code being in `src/RandomX` + * The largest part of adding a new PoW algo is adding a new class to src/miner.cpp + * Originally there was only BitcoinMiner, which was modified from a double-sha256 miner to an equihash miner, without changing the name + * When RandomX was added as an option, many big internals changes were needed to support more than a single miner class + * It is now easier to add PoW algos because the internals support using different miner classes + * Currently BitcoinMiner and RandomXMiner classes have a lot of duplicated code, but this is intentional + * In theory we could refactor the miner classes to share more code, but this means changes to one miner could break another and it is very challenging to test every possibile edge case for mining code + * So code duplication is purposeful, because it isolates the risk of breaking one PoW by changing another. We tried very hard to not break Equihash mining when adding RandomX mining. + * When adding a new mining class, copying the RandomXMiner class is best, since it's newer and does not contain various legacy code that still exists in BitcoinMiner + * So copy RandomXMiner to your new FooMiner, delete all the randomx-specific stuff and add in the PoW mining code + * Some other changes to src/miner.cpp will be needed + * Update `GenerateBitcoins` function to start mining threads with your new algo with `else if(ASSETCHAINS_ALGO == ASSETCHAINS_FOOHASH) { minerThreads->create_thread(&FooMiner)}` # Coding diff --git a/doc/i2p.md b/doc/i2p.md index e01573f9d..583f9ddb2 100644 --- a/doc/i2p.md +++ b/doc/i2p.md @@ -33,12 +33,10 @@ configuration options: none) -i2pacceptincoming - If set and -i2psam is also set then incoming I2P connections are - accepted via the SAM proxy. If this is not set but -i2psam is set - then only outgoing connections will be made to the I2P network. - Ignored if -i2psam is not set. Listening for incoming I2P - connections is done through the SAM proxy, not by binding to a - local address and port (default: 1) + Whether to accept inbound I2P connections (default: 1). Ignored if + -i2psam is not set. Listening for inbound I2P connections is + done through the SAM proxy, not by binding to a local address and + port. ``` In a typical situation, this suffices: @@ -56,6 +54,36 @@ connections if `-i2pacceptincoming=1`. If `-i2pacceptincoming=0` then only outbound I2P connections are made and a different transient I2P address is used for each connection to improve privacy. +## Additional configuration options related to I2P + +``` +-debug=i2p +``` + +Set the `debug=i2p` config logging option to see additional information in the +debug log about your I2P configuration and connections. + +``` +-onlynet=i2p +``` + +Make automatic outbound connections only to I2P addresses. Inbound and manual +connections are not affected by this option. It can be specified multiple times +to allow multiple networks, e.g. onlynet=onion, onlynet=i2p. + +I2P support was added to Hush in version 3.9.3 and there may be fewer I2P +peers than Tor or IP ones. Therefore, using I2P alone without other networks may +make a node more susceptible to [Sybil +attacks](https://en.bitcoin.it/wiki/Weaknesses#Sybil_attack). + +Another consideration with `onlynet=i2p` is that the initial blocks download +phase when syncing up a new node can be very slow. This phase can be sped up by +using other networks, for instance `onlynet=onion`, at the same time. + +In general, a node can be run with both onion and I2P hidden services (or +any/all of IPv4/IPv6/onion/I2P/CJDNS), which can provide a potential fallback if +one of the networks has issues. + ## Persistent vs transient I2P addresses In I2P connections, the connection receiver sees the I2P address of the @@ -136,14 +164,19 @@ port (`TO_PORT`) is always set to 0 and is not in the control of Hush. ## Bandwidth -I2P routers may route a large amount of general network traffic with their -default settings. Check your router's configuration to limit the amount of this -traffic relayed, if desired. +By default, your node shares bandwidth and transit tunnels with the I2P network +in order to increase your anonymity with cover traffic, help the I2P router used +by your node integrate optimally with the network, and give back to the network. +It's important that the nodes of a popular application like Hush contribute +as much to the I2P network as they consume. -With `i2pd`, the amount of bandwidth being shared with the wider network can be -adjusted with the `bandwidth`, `share` and `transittunnels` options in your -`i2pd.conf` file. For example, to limit total I2P traffic to 256KB/s and share -50% of this limit for a maximum of 20 transit tunnels: +It is possible, though strongly discouraged, to change your I2P router +configuration to limit the amount of I2P traffic relayed by your node. + +With `i2pd`, this can be done by adjusting the `bandwidth`, `share` and +`transittunnels` options in your `i2pd.conf` file. For example, to limit total +I2P traffic to 256KB/s and share 50% of this limit for a maximum of 20 transit +tunnels: ``` bandwidth = 256 @@ -153,9 +186,15 @@ share = 50 transittunnels = 20 ``` -If you prefer not to relay any public I2P traffic and only permit I2P traffic -from programs which are connecting via the SAM proxy, e.g. Hush, you -can set the `notransit` option to `true`. - Similar bandwidth configuration options for the Java I2P router can be found in `http://127.0.0.1:7657/config` under the "Bandwidth" tab. + +Before doing this, please see the "Participating Traffic Considerations" section +in [Embedding I2P in your Application](https://geti2p.net/en/docs/applications/embedding). + +In most cases, the default router settings should work fine. + +## Bundling I2P in a Hush application + +Please see the "General Guidance for Developers" section in https://geti2p.net/en/docs/api/samv3 +if you are developing a downstream application that may be bundling I2P with Hush. diff --git a/doc/man/hush-cli.1 b/doc/man/hush-cli.1 index a82565e74..d39016e53 100644 --- a/doc/man/hush-cli.1 +++ b/doc/man/hush-cli.1 @@ -1,9 +1,9 @@ -.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.47.6. -.TH HUSH-CLI "1" "June 2023" "hush-cli v3.9.4" "User Commands" +.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.47.13. +.TH HUSH-CLI "1" "November 2023" "hush-cli v3.10.0" "User Commands" .SH NAME -hush-cli \- manual page for hush-cli v3.9.4 +hush-cli \- manual page for hush-cli v3.10.0 .SH DESCRIPTION -Hush RPC client version v3.9.4\-44595d5ab +Hush RPC client version v3.10.0\-4facbadc6\-dirty .PP In order to ensure you are adequately protecting your privacy when using Hush, please see . diff --git a/doc/man/hush-tx.1 b/doc/man/hush-tx.1 index a4bc4033b..fcec88245 100644 --- a/doc/man/hush-tx.1 +++ b/doc/man/hush-tx.1 @@ -1,9 +1,9 @@ -.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.47.6. -.TH HUSH-TX "1" "June 2023" "hush-tx v3.9.4" "User Commands" +.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.47.13. +.TH HUSH-TX "1" "November 2023" "hush-tx v3.10.0" "User Commands" .SH NAME -hush-tx \- manual page for hush-tx v3.9.4 +hush-tx \- manual page for hush-tx v3.10.0 .SH DESCRIPTION -hush\-tx utility version v3.9.4\-44595d5ab +hush\-tx utility version v3.10.0\-4facbadc6\-dirty .SS "Usage:" .TP hush\-tx [options] [commands] diff --git a/doc/man/hushd.1 b/doc/man/hushd.1 index 627c9c651..fca19a54b 100644 --- a/doc/man/hushd.1 +++ b/doc/man/hushd.1 @@ -1,9 +1,9 @@ -.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.47.6. -.TH HUSHD "1" "June 2023" "hushd v3.9.4" "User Commands" +.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.47.13. +.TH HUSHD "1" "November 2023" "hushd v3.10.0" "User Commands" .SH NAME -hushd \- manual page for hushd v3.9.4 +hushd \- manual page for hushd v3.10.0 .SH DESCRIPTION -Hush Daemon version v3.9.4\-44595d5ab +Hush Daemon version v3.10.0\-4facbadc6\-dirty .PP In order to ensure you are adequately protecting your privacy when using Hush, please see . @@ -78,7 +78,7 @@ applied) .HP \fB\-par=\fR .IP -Set the number of script verification threads (\fB\-6\fR to 16, 0 = auto, <0 = +Set the number of script verification threads (\fB\-8\fR to 16, 0 = auto, <0 = leave that many cores free, default: 0) .HP \fB\-pid=\fR @@ -336,6 +336,10 @@ Set key pool size to (default: 100) .IP Enable auto Sapling note consolidation (default: false) .HP +\fB\-consolidationinterval\fR +.IP +Block interval between consolidations (default: 25) +.HP \fB\-consolidatesaplingaddress=\fR .IP Specify Sapling Address to Consolidate. (default: all) diff --git a/doc/release-process.md b/doc/release-process.md index 93fec2434..497ad0daa 100644 --- a/doc/release-process.md +++ b/doc/release-process.md @@ -122,3 +122,11 @@ Install deps on Linux: ## Platform-specific notes Use `./util/build-mac.sh` to compile on Apple/Mac systems, use `./util/build-win.sh` to build on Windows and `./util/build-arm.sh` to build on ARMv8 systems. + +Use `./util/build-debian-package.sh aarch64` to build a Debian package for aarch64 . + +## Optional things + +### Updating RandomX + +If you need to update the source code of our in tree copy of RandomX, see issue https://git.hush.is/hush/hush3/issues/337#issuecomment-5114 for details. Currently we use RandomX v1.2.1 from the official repo at https://github.com/tevador/RandomX/releases/tag/v1.2.1 diff --git a/doc/relnotes/README.md b/doc/relnotes/README.md index 294f3d299..36da43edb 100644 --- a/doc/relnotes/README.md +++ b/doc/relnotes/README.md @@ -10,6 +10,43 @@ and no longer on Github, since they banned Duke Leto and also because they censor many people around the world and work with evil organizations. +# Hush 3.10.0 "Sassy Siphonophore" + +``` +132 files changed, 6387 insertions(+), 2084 deletions(-) +``` + +This is a MANDATORY release for Hush and *ALL* nodes must upgrade by block height 1605555, which will happen +on approximately Dec 16th 2023. YOU MUST UPGRADE YOUR HUSH FULL NODE TO THIS RELEASE BY DEC 15th 2023. +If you do not, your node will not work correctly and will require a fresh sync to fix. + +This is an OPTIONAL release for DragonX but it is highly recommended for miners and exchanges +to update to this release. + + * Hush and all Hush Smart Chains now use less RAM https://git.hush.is/hush/hush3/issues/283 + * Hush full nodes will use ~2GB less RAM + * DragonX full nodes will use ~30MB less RAM + * Antispam defenses + * Hush and all Hush Smart Chains now make it harder and more expensive for an attacker to send shielded spam. This raises the cost in CPU https://git.hush.is/hush/hush3/commit/14d3ae17851615a69c33cb7eed623b904b140e3d and transaction fees https://git.hush.is/hush/hush3/commit/2308db22eec78d0a10bde0f674243b2700d59e4a for Denial-of-Service attacks. + * New RPC `z_getstats` which reports data about numer of shielded inputs (zins) and shielded outputs (zouts) in transactions. https://git.hush.is/hush/hush3/commit/96ae2d61ca5a392cb476da4c7f6ab1f638839a7f + * Fix a bug where `hush-cli stop` would not stop the node during the "Building Witnesses" rescan phase https://git.hush.is/hush/hush3/issues/330 + * Fix bugs where `abortrescan` couldn't be used when node is start up (RPC warmup) and where it could not abort the rescan if it was in the "Building Witnesses" phase https://git.hush.is/hush/hush3/issues/331 + * Fix bug in `z_mergetoaddress` where docs said you could use `ANY_ZADDR` but you couldn't https://git.hush.is/hush/hush3/commit/7eb9d75b94469c3fc8c028f29b35be9ac764a10c + * RPC `z_listunspent` now returns the text representation of a memo in `memoStr` key + * Upgraded curl to 8.4.0 https://git.hush.is/hush/hush3/issues/325 + * This fixes CVE-2023-38545 which affects very few or potentially no Hush/DragonX users. It could only affect people who compile Hush full node software (not those who use binaries or packages) and who use a malicious SOCKS5 proxy for all network traffic via the operating system. + * New documentation about using CJDNS with Hush: https://git.hush.is/hush/hush3/src/branch/dev/doc/cjdns.md + * Decentralized Devtax for improved scalability and operational security. This is a consensus change. + * DragonX specific changes: + * Updated to latest RandomX v1.2.1 which includes mining optimizations https://git.hush.is/hush/hush3/commit/6029b3d571009991ae9c4aea0397f4d00be6a817 https://git.hush.is/hush/hush3/issues/337 + * Fix RandomX mining memory leak and crash https://git.hush.is/hush/hush3/issues/324 + * This fixes the bug where stopping mining, making a transaction and then starting mining again + * This also avoids an out-of-memory crash when miners change the number of threads of mining + * Fixing this bug lead to a 10% hashrate increase vs the previous release + * Fixed quoting bugs with dragonx-cli script + * For instance, many RPCs such as `dragonx z_sendmany ...` would not previously work because the arguments to the RPC were not quoted correctly. + + # Hush 3.9.4 "Maniacal Manticore" ``` diff --git a/qa/pull-tester/rpc-tests.sh b/qa/pull-tester/rpc-tests.sh index b1cbabec9..bed1a5417 100755 --- a/qa/pull-tester/rpc-tests.sh +++ b/qa/pull-tester/rpc-tests.sh @@ -14,6 +14,7 @@ export BITCOIND=${REAL_BITCOIND} #Run the tests testScripts=( + 'antispam.py' 'dpow.py' 'dpowconfs.py' 'ac_private.py' diff --git a/qa/pull-tester/tests-config.sh.in b/qa/pull-tester/tests-config.sh.in index 5122ba085..47546707b 100755 --- a/qa/pull-tester/tests-config.sh.in +++ b/qa/pull-tester/tests-config.sh.in @@ -11,7 +11,6 @@ EXEEXT="@EXEEXT@" @ENABLE_WALLET_TRUE@ENABLE_WALLET=1 @BUILD_BITCOIN_UTILS_TRUE@ENABLE_UTILS=1 @BUILD_BITCOIND_TRUE@ENABLE_BITCOIND=1 -@ENABLE_PROTON_TRUE@ENABLE_PROTON=1 REAL_BITCOIND="$BUILDDIR/src/hushd${EXEEXT}" REAL_BITCOINCLI="$BUILDDIR/src/hush-cli${EXEEXT}" diff --git a/qa/rpc-tests/antispam.py b/qa/rpc-tests/antispam.py new file mode 100755 index 000000000..9913eef56 --- /dev/null +++ b/qa/rpc-tests/antispam.py @@ -0,0 +1,44 @@ +#!/usr/bin/env python2 +# Copyright (c) 2016-2023 The Hush developers +# Distributed under the GPLv3 software license, see the accompanying +# file COPYING or https://www.gnu.org/licenses/gpl-3.0.en.html + +from test_framework.test_framework import BitcoinTestFramework +from test_framework.authproxy import JSONRPCException +from test_framework.util import ( + assert_equal, + start_nodes, + wait_and_assert_operationid_status, +) + +from decimal import Decimal + +class AntispamTest(BitcoinTestFramework): + + def setup_nodes(self): + return start_nodes(2, self.options.tmpdir, [[ ]] * 2) + + def run_test(self): + # Sanity-check the test harness + assert_equal(self.nodes[0].getblockcount(), 200) + + # make sure we can mine a block + self.nodes[1].generate(1) + self.sync_all() + + # make a new zaddr on each node + saplingAddr0 = self.nodes[0].z_getnewaddress() + saplingAddr1 = self.nodes[1].z_getnewaddress() + + # Verify addresses + assert(saplingAddr0 in self.nodes[0].z_listaddresses()) + assert(saplingAddr1 in self.nodes[1].z_listaddresses()) + assert_equal(self.nodes[0].z_validateaddress(saplingAddr0)['type'], 'sapling') + assert_equal(self.nodes[0].z_validateaddress(saplingAddr1)['type'], 'sapling') + + # Verify balance + assert_equal(self.nodes[0].z_getbalance(saplingAddr0), Decimal('0')) + assert_equal(self.nodes[1].z_getbalance(saplingAddr1), Decimal('0')) + +if __name__ == '__main__': + AntispamTest().main() diff --git a/qa/rpc-tests/test_framework/util.py b/qa/rpc-tests/test_framework/util.py index a0b409970..3280be573 100644 --- a/qa/rpc-tests/test_framework/util.py +++ b/qa/rpc-tests/test_framework/util.py @@ -104,10 +104,10 @@ def initialize_datadir(dirname, n): f.write("showmetrics=0\n"); f.write("rpcuser=hush\n"); f.write("rpcpassword=puppy\n"); - #f.write("port="+str(p2p_port(n))+"\n"); - #rpcport = str(rpc_port(n)) - #f.write("rpcport="+rpcport+"\n"); - #print "RPC port=" + rpcport + f.write("port="+str(p2p_port(n))+"\n"); + rpcport = str(rpc_port(n)) + f.write("rpcport="+rpcport+"\n"); + print "RPC port=" + rpcport f.write("listenonion=0\n"); # TODO: maybe make these optional, via arg to initialize_datadir, defaulted to on for now f.write("addressindex=1\n"); @@ -148,7 +148,7 @@ def initialize_chain(test_dir): rpcs = [] for i in range(4): try: - url = "http://rt:rt@127.0.0.1:%d"%(rpc_port(i),) + url = "http://hush:puppy@127.0.0.1:%d"%(rpc_port(i),) rpcs.append(AuthServiceProxy(url)) except: sys.stderr.write("Error connecting to "+url+"\n") @@ -165,11 +165,13 @@ def initialize_chain(test_dir): for j in range(25): set_node_times(rpcs, block_time) rpcs[peer].generate(1) - block_time += 10*60 + # TODO: HUSH3 has 75s blocktime, other HSCs could be different + block_time += 10*75 # Must sync before next peer starts generating blocks sync_blocks(rpcs) # Shut them down, and clean up cache directories: + print("Stopping nodes") stop_nodes(rpcs) wait_bitcoinds() for i in range(4): @@ -182,8 +184,9 @@ def initialize_chain(test_dir): for i in range(4): from_dir = os.path.join("cache", "node"+str(i)) to_dir = os.path.join(test_dir, "node"+str(i)) + print("Copying " + from_dir + " to " + to_dir) shutil.copytree(from_dir, to_dir) - initialize_datadir(test_dir, i) # Overwrite port/rpcport in hush.conf + initialize_datadir(test_dir, i) # Overwrite port/rpcport in HUSH3.conf def initialize_chain_clean(test_dir, num_nodes): """ @@ -218,9 +221,10 @@ def start_node(i, dirname, extra_args=None, rpchost=None, timewait=None, binary= """ Start a hushd and return RPC connection to it """ + print("Starting node " + str(i)) datadir = os.path.join(dirname, "node"+str(i)) # creating special config in case of cryptocondition asset chain test - if extra_args[0] == '-ac_name=REGTEST': + if len(extra_args) > 0 and extra_args[0] == '-ac_name=REGTEST': configpath = datadir + "/REGTEST.conf" with open(configpath, "w+") as config: config.write("regtest=1\n") @@ -259,7 +263,8 @@ def start_node(i, dirname, extra_args=None, rpchost=None, timewait=None, binary= if os.getenv("PYTHON_DEBUG", ""): print "start_node: calling hush-cli -rpcwait getblockcount returned" devnull.close() - port = extra_args[3] + #port = extra_args[3] + port = rpc_port(i) username = rpc_username() password = rpc_password() url = "http://%s:%s@%s:%d" % (username, password, rpchost or '127.0.0.1', int(port[9:])) @@ -276,6 +281,7 @@ def start_nodes(num_nodes, dirname, extra_args=None, rpchost=None, binary=None): """ Start multiple hushds, return RPC connections to them """ + print("Starting " + str(num_nodes) + " nodes") if extra_args is None: extra_args = [ None for i in range(num_nodes) ] if binary is None: binary = [ None for i in range(num_nodes) ] return [ start_node(i, dirname, extra_args[i], rpchost, binary=binary[i]) for i in range(num_nodes) ] @@ -288,6 +294,7 @@ def check_node(i): return bitcoind_processes[i].returncode def stop_node(node, i): + print("Stopping node " + i) node.stop() bitcoind_processes[i].wait() del bitcoind_processes[i] @@ -298,11 +305,12 @@ def stop_nodes(nodes): del nodes[:] # Emptying array closes connections as a side effect def set_node_times(nodes, t): + print("Setting nodes time to " + t) for node in nodes: node.setmocktime(t) def wait_bitcoinds(): - # Wait for all bitcoinds to cleanly exit + print("Waiting for all nodes to cleanly exit") for bitcoind in bitcoind_processes.values(): bitcoind.wait() bitcoind_processes.clear() diff --git a/qa/rpc-tests/wallet.py b/qa/rpc-tests/wallet.py index c50c028a3..2047f9e0b 100755 --- a/qa/rpc-tests/wallet.py +++ b/qa/rpc-tests/wallet.py @@ -221,7 +221,7 @@ class WalletTest (BitcoinTestFramework): for uTx in unspentTxs: if uTx['txid'] == zeroValueTxid: found = True - assert_equal(uTx['amount'], Decimal('0.00000000')) + assert_equal(uTx['amount'], Decimal('0')) assert(found) #do some -walletbroadcast tests diff --git a/qa/rpc-tests/wallet_sapling.py b/qa/rpc-tests/wallet_sapling.py index c9e796b72..cca928c44 100755 --- a/qa/rpc-tests/wallet_sapling.py +++ b/qa/rpc-tests/wallet_sapling.py @@ -19,9 +19,9 @@ class WalletSaplingTest(BitcoinTestFramework): def setup_nodes(self): return start_nodes(4, self.options.tmpdir, [[ - '-nuparams=5ba81b19:201', # Overwinter - '-nuparams=76b809bb:203', # Sapling - '-experimentalfeatures', '-zmergetoaddress', + #'-nuparams=5ba81b19:201', # Overwinter + #'-nuparams=76b809bb:203', # Sapling + #'-experimentalfeatures', '-zmergetoaddress', ]] * 4) def run_test(self): diff --git a/src/Makefile.am b/src/Makefile.am index e5e2ca248..6178fa19e 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -39,6 +39,7 @@ BITCOIN_INCLUDES += -I$(srcdir)/cryptoconditions/include BITCOIN_INCLUDES += -I$(srcdir)/cryptoconditions/src BITCOIN_INCLUDES += -I$(srcdir)/cryptoconditions/src/asn BITCOIN_INCLUDES += -I$(srcdir)/univalue/include +BITCOIN_INCLUDES += -I$(srcdir)/leveldb/include if TARGET_WINDOWS LIBBITCOIN_SERVER=libbitcoin_server.a -lcurl diff --git a/src/RandomX/CMakeLists.txt b/src/RandomX/CMakeLists.txt index f41f606b9..ebbdff2b6 100644 --- a/src/RandomX/CMakeLists.txt +++ b/src/RandomX/CMakeLists.txt @@ -39,7 +39,7 @@ src/bytecode_machine.cpp src/cpu.cpp src/dataset.cpp src/soft_aes.cpp -src/virtual_memory.cpp +src/virtual_memory.c src/vm_interpreted.cpp src/allocator.cpp src/assembly_generator_x86.cpp @@ -96,7 +96,7 @@ function(add_flag flag) endfunction() # x86-64 -if(ARCH_ID STREQUAL "x86_64" OR ARCH_ID STREQUAL "x86-64" OR ARCH_ID STREQUAL "amd64") +if ((CMAKE_SIZEOF_VOID_P EQUAL 8) AND (ARCH_ID STREQUAL "x86_64" OR ARCH_ID STREQUAL "x86-64" OR ARCH_ID STREQUAL "amd64")) list(APPEND randomx_sources src/jit_compiler_x86.cpp) @@ -173,6 +173,42 @@ if(ARM_ID STREQUAL "aarch64" OR ARM_ID STREQUAL "arm64" OR ARM_ID STREQUAL "armv endif() endif() +# RISC-V +if(ARCH_ID STREQUAL "riscv64") + list(APPEND randomx_sources + src/jit_compiler_rv64_static.S + src/jit_compiler_rv64.cpp) + # cheat because cmake and ccache hate each other + set_property(SOURCE src/jit_compiler_rv64_static.S PROPERTY LANGUAGE C) + set_property(SOURCE src/jit_compiler_rv64_static.S PROPERTY XCODE_EXPLICIT_FILE_TYPE sourcecode.asm) + + # default build uses the RV64GC baseline + set(RVARCH "rv64gc") + + # for native builds, enable Zba and Zbb if supported by the CPU + if(ARCH STREQUAL "native") + enable_language(ASM) + try_run(RANDOMX_ZBA_RUN_FAIL + RANDOMX_ZBA_COMPILE_OK + ${CMAKE_CURRENT_BINARY_DIR}/ + ${CMAKE_CURRENT_SOURCE_DIR}/src/tests/riscv64_zba.s + COMPILE_DEFINITIONS "-march=rv64gc_zba") + if (RANDOMX_ZBA_COMPILE_OK AND NOT RANDOMX_ZBA_RUN_FAIL) + set(RVARCH "${RVARCH}_zba") + endif() + try_run(RANDOMX_ZBB_RUN_FAIL + RANDOMX_ZBB_COMPILE_OK + ${CMAKE_CURRENT_BINARY_DIR}/ + ${CMAKE_CURRENT_SOURCE_DIR}/src/tests/riscv64_zbb.s + COMPILE_DEFINITIONS "-march=rv64gc_zbb") + if (RANDOMX_ZBB_COMPILE_OK AND NOT RANDOMX_ZBB_RUN_FAIL) + set(RVARCH "${RVARCH}_zbb") + endif() + endif() + + add_flag("-march=${RVARCH}") +endif() + set(RANDOMX_INCLUDE "${CMAKE_CURRENT_SOURCE_DIR}/src" CACHE STRING "RandomX Include path") add_library(randomx ${randomx_sources}) diff --git a/src/RandomX/README.md b/src/RandomX/README.md index 4c1dabb65..2c9bdd318 100644 --- a/src/RandomX/README.md +++ b/src/RandomX/README.md @@ -37,7 +37,7 @@ RandomX is written in C++11 and builds a static library with a C API provided by ### Linux -Build dependencies: `cmake` (minimum 2.8.7) and `gcc` (minimum version 4.8, but version 7+ is recommended). +Build dependencies: `cmake` (minimum 3.5) and `gcc` (minimum version 4.8, but version 7+ is recommended). To build optimized binaries for your machine, run: ``` @@ -82,7 +82,7 @@ Intel Core i7-8550U|16G DDR4-2400|Windows 10|hw|200 (4T)|1700 (4T)|350 (8T)| Intel Core i3-3220|4G DDR3-1333|Ubuntu 16.04|soft|42 (4T)|510 (4T)|150 (4T)| Raspberry Pi 3|1G LPDDR2|Ubuntu 16.04|soft|3.5 (4T)|-|20 (4T)| -Note that RandomX currently includes a JIT compiler for x86-64 and ARM64. Other architectures have to use the portable interpreter, which is much slower. +Note that RandomX currently includes a JIT compiler for x86-64, ARM64 and RISCV64. Other architectures have to use the portable interpreter, which is much slower. ### GPU performance @@ -129,6 +129,7 @@ The reference implementation has been validated on the following platforms: * ARMv7+VFPv3 (32-bit, little-endian) * ARMv8 (64-bit, little-endian) * PPC64 (64-bit, big-endian) +* RISCV64 (64-bit, little-endian) ### Can FPGAs mine RandomX? diff --git a/src/RandomX/doc/tevador.asc b/src/RandomX/doc/tevador.asc index b998f1ef2..8bada54bb 100644 --- a/src/RandomX/doc/tevador.asc +++ b/src/RandomX/doc/tevador.asc @@ -1,13 +1,13 @@ -----BEGIN PGP PUBLIC KEY BLOCK----- mDMEXd+PeBYJKwYBBAHaRw8BAQdAZ0nqJ+nRYoScG2QLX62pl+WO1+Mkv6Yyt2Kb -ntGUuLq0G3RldmFkb3IgPHRldmFkb3JAZ21haWwuY29tPoiWBBMWCAA+FiEEMoWj -LVEwdmMs6CUQWijIaue9c6YFAl3fj3gCGwMFCQWnqDgFCwkIBwIGFQoJCAsCBBYC -AwECHgECF4AACgkQWijIaue9c6YBFQD+N1XTUqSCZp9jB/yTHQ9ahSaIUMtmuvdT -So2s+quudP4A/R5wLwukpfGN9UZ4cfpmKCJ9jO1HJ2udmlGMsJbQpDAIuDgEXd+P +ntGUuLq0G3RldmFkb3IgPHRldmFkb3JAZ21haWwuY29tPoiWBBMWCAA+AhsDBQsJ +CAcCBhUKCQgLAgQWAgMBAh4BAheAFiEEMoWjLVEwdmMs6CUQWijIaue9c6YFAmRP +r8MFCQ/ZS2YACgkQWijIaue9c6bR5gEA0tnQ4Al+yOLoRUBQitAV8FU4FLy8Xx8U +IyyivjJ0UhIA/2jwJfMXmJdMKtar8xfIA5mZLLofkEP6hug4knhitpkBuDgEXd+P eBIKKwYBBAGXVQEFAQEHQBNbQuPcDojMCkRb5B5u7Ld/AFLClOh+6ElL+u61rIY/ -AwEIB4h+BBgWCAAmFiEEMoWjLVEwdmMs6CUQWijIaue9c6YFAl3fj3gCGwwFCQWn -qDgACgkQWijIaue9c6YJvgD+IY1Q9mCM1P1iZIoXuafRihXJ7UgVXpQqW2yoaUT3 -bfQA/RkisI2eElYoOjdwPszPP6VfL5+SViwDmDuJG2P5llgE -=V4vd ------END PGP PUBLIC KEY BLOCK----- +AwEIB4h+BBgWCAAmAhsMFiEEMoWjLVEwdmMs6CUQWijIaue9c6YFAmRQoAMFCQ/Z +S2YACgkQWijIaue9c6bUfwD9Hw20kGCaZ8rWghz9W3bc645ys1vPQpQW28CD9w3B +cTMBALsV1xpS2pGwTfn1PUimqESZfTrREmNvOjKSQwe0yicI +=D4lm +-----END PGP PUBLIC KEY BLOCK----- \ No newline at end of file diff --git a/src/RandomX/src/allocator.cpp b/src/RandomX/src/allocator.cpp index 6b48a7e70..bcee0f6b6 100644 --- a/src/RandomX/src/allocator.cpp +++ b/src/RandomX/src/allocator.cpp @@ -29,7 +29,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include "allocator.hpp" #include "intrin_portable.h" -#include "virtual_memory.hpp" +#include "virtual_memory.h" #include "common.hpp" namespace randomx { diff --git a/src/RandomX/src/assembly_generator_x86.cpp b/src/RandomX/src/assembly_generator_x86.cpp index e7e5258b7..1ce31dd55 100644 --- a/src/RandomX/src/assembly_generator_x86.cpp +++ b/src/RandomX/src/assembly_generator_x86.cpp @@ -445,7 +445,7 @@ namespace randomx { } void AssemblyGeneratorX86::h_IMUL_RCP(Instruction& instr, int i) { - uint64_t divisor = instr.getImm32(); + const uint32_t divisor = instr.getImm32(); if (!isZeroOrPowerOf2(divisor)) { registerUsage[instr.dst] = i; asmCode << "\tmov rax, " << randomx_reciprocal(divisor) << std::endl; diff --git a/src/RandomX/src/bytecode_machine.cpp b/src/RandomX/src/bytecode_machine.cpp index 7d8e902d2..1d00d0959 100644 --- a/src/RandomX/src/bytecode_machine.cpp +++ b/src/RandomX/src/bytecode_machine.cpp @@ -243,7 +243,7 @@ namespace randomx { } if (opcode < ceil_IMUL_RCP) { - uint64_t divisor = instr.getImm32(); + const uint32_t divisor = instr.getImm32(); if (!isZeroOrPowerOf2(divisor)) { auto dst = instr.dst % RegistersCount; ibc.type = InstructionType::IMUL_R; diff --git a/src/RandomX/src/common.hpp b/src/RandomX/src/common.hpp index a77feb3bf..f4b85342a 100644 --- a/src/RandomX/src/common.hpp +++ b/src/RandomX/src/common.hpp @@ -116,12 +116,19 @@ namespace randomx { #if defined(_M_X64) || defined(__x86_64__) #define RANDOMX_HAVE_COMPILER 1 + #define RANDOMX_COMPILER_X86 class JitCompilerX86; using JitCompiler = JitCompilerX86; #elif defined(__aarch64__) #define RANDOMX_HAVE_COMPILER 1 + #define RANDOMX_COMPILER_A64 class JitCompilerA64; using JitCompiler = JitCompilerA64; +#elif defined(__riscv) && __riscv_xlen == 64 + #define RANDOMX_HAVE_COMPILER 1 + #define RANDOMX_COMPILER_RV64 + class JitCompilerRV64; + using JitCompiler = JitCompilerRV64; #else #define RANDOMX_HAVE_COMPILER 0 class JitCompilerFallback; diff --git a/src/RandomX/src/dataset.cpp b/src/RandomX/src/dataset.cpp index 675c5abc5..7ebf1bca4 100644 --- a/src/RandomX/src/dataset.cpp +++ b/src/RandomX/src/dataset.cpp @@ -42,7 +42,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "common.hpp" #include "dataset.hpp" -#include "virtual_memory.hpp" +#include "virtual_memory.h" #include "superscalar.hpp" #include "blake2_generator.hpp" #include "reciprocal.h" diff --git a/src/RandomX/src/intrin_portable.h b/src/RandomX/src/intrin_portable.h index 8c09ae885..50020c3e2 100644 --- a/src/RandomX/src/intrin_portable.h +++ b/src/RandomX/src/intrin_portable.h @@ -349,7 +349,7 @@ FORCE_INLINE rx_vec_i128 rx_load_vec_i128(rx_vec_i128 const *p) { #if defined(NATIVE_LITTLE_ENDIAN) return *p; #else - uint32_t* ptr = (uint32_t*)p; + const uint32_t* ptr = (const uint32_t*)p; vec_u c; c.u32[0] = load32(ptr + 0); c.u32[1] = load32(ptr + 1); @@ -375,8 +375,8 @@ FORCE_INLINE void rx_store_vec_i128(rx_vec_i128 *p, rx_vec_i128 b) { FORCE_INLINE rx_vec_f128 rx_cvt_packed_int_vec_f128(const void* addr) { vec_u x; - x.d64[0] = (double)unsigned32ToSigned2sCompl(load32((uint8_t*)addr + 0)); - x.d64[1] = (double)unsigned32ToSigned2sCompl(load32((uint8_t*)addr + 4)); + x.d64[0] = (double)unsigned32ToSigned2sCompl(load32((const uint8_t*)addr + 0)); + x.d64[1] = (double)unsigned32ToSigned2sCompl(load32((const uint8_t*)addr + 4)); return (rx_vec_f128)x.d; } @@ -684,7 +684,7 @@ FORCE_INLINE rx_vec_i128 rx_load_vec_i128(rx_vec_i128 const* p) { #if defined(NATIVE_LITTLE_ENDIAN) return *p; #else - uint32_t* ptr = (uint32_t*)p; + const uint32_t* ptr = (const uint32_t*)p; rx_vec_i128 c; c.u32[0] = load32(ptr + 0); c.u32[1] = load32(ptr + 1); @@ -708,8 +708,8 @@ FORCE_INLINE void rx_store_vec_i128(rx_vec_i128 *p, rx_vec_i128 b) { FORCE_INLINE rx_vec_f128 rx_cvt_packed_int_vec_f128(const void* addr) { rx_vec_f128 x; - x.lo = (double)unsigned32ToSigned2sCompl(load32((uint8_t*)addr + 0)); - x.hi = (double)unsigned32ToSigned2sCompl(load32((uint8_t*)addr + 4)); + x.lo = (double)unsigned32ToSigned2sCompl(load32((const uint8_t*)addr + 0)); + x.hi = (double)unsigned32ToSigned2sCompl(load32((const uint8_t*)addr + 4)); return x; } diff --git a/src/RandomX/src/jit_compiler.hpp b/src/RandomX/src/jit_compiler.hpp index 17fdad4e3..5b76fa5f9 100644 --- a/src/RandomX/src/jit_compiler.hpp +++ b/src/RandomX/src/jit_compiler.hpp @@ -28,10 +28,48 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #pragma once -#if defined(_M_X64) || defined(__x86_64__) +#include "common.hpp" + +namespace randomx { + + struct CodeBuffer { + uint8_t* code; + int32_t codePos; + int32_t rcpCount; + + void emit(const uint8_t* src, int32_t len) { + memcpy(&code[codePos], src, len); + codePos += len; + } + + template + void emit(T src) { + memcpy(&code[codePos], &src, sizeof(src)); + codePos += sizeof(src); + } + + void emitAt(int32_t codePos, const uint8_t* src, int32_t len) { + memcpy(&code[codePos], src, len); + } + + template + void emitAt(int32_t codePos, T src) { + memcpy(&code[codePos], &src, sizeof(src)); + } + }; + + struct CompilerState : public CodeBuffer { + int32_t instructionOffsets[RANDOMX_PROGRAM_SIZE]; + int registerUsage[RegistersCount]; + }; +} + +#if defined(RANDOMX_COMPILER_X86) #include "jit_compiler_x86.hpp" -#elif defined(__aarch64__) +#elif defined(RANDOMX_COMPILER_A64) #include "jit_compiler_a64.hpp" +#elif defined(RANDOMX_COMPILER_RV64) +#include "jit_compiler_rv64.hpp" #else #include "jit_compiler_fallback.hpp" #endif diff --git a/src/RandomX/src/jit_compiler_a64.cpp b/src/RandomX/src/jit_compiler_a64.cpp index fc4634868..5be8f6e42 100644 --- a/src/RandomX/src/jit_compiler_a64.cpp +++ b/src/RandomX/src/jit_compiler_a64.cpp @@ -31,7 +31,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "superscalar.hpp" #include "program.hpp" #include "reciprocal.h" -#include "virtual_memory.hpp" +#include "virtual_memory.h" namespace ARMV8A { @@ -130,8 +130,8 @@ void JitCompilerA64::generateProgram(Program& program, ProgramConfiguration& con // and w16, w10, ScratchpadL3Mask64 emit32(0x121A0000 | 16 | (10 << 5) | ((Log2(RANDOMX_SCRATCHPAD_L3) - 7) << 10), code, codePos); - // and w17, w18, ScratchpadL3Mask64 - emit32(0x121A0000 | 17 | (18 << 5) | ((Log2(RANDOMX_SCRATCHPAD_L3) - 7) << 10), code, codePos); + // and w17, w20, ScratchpadL3Mask64 + emit32(0x121A0000 | 17 | (20 << 5) | ((Log2(RANDOMX_SCRATCHPAD_L3) - 7) << 10), code, codePos); codePos = PrologueSize; literalPos = ImulRcpLiteralsEnd; @@ -149,16 +149,16 @@ void JitCompilerA64::generateProgram(Program& program, ProgramConfiguration& con } // Update spMix2 - // eor w18, config.readReg2, config.readReg3 - emit32(ARMV8A::EOR32 | 18 | (IntRegMap[config.readReg2] << 5) | (IntRegMap[config.readReg3] << 16), code, codePos); + // eor w20, config.readReg2, config.readReg3 + emit32(ARMV8A::EOR32 | 20 | (IntRegMap[config.readReg2] << 5) | (IntRegMap[config.readReg3] << 16), code, codePos); // Jump back to the main loop const uint32_t offset = (((uint8_t*)randomx_program_aarch64_vm_instructions_end) - ((uint8_t*)randomx_program_aarch64)) - codePos; emit32(ARMV8A::B | (offset / 4), code, codePos); - // and w18, w18, CacheLineAlignMask + // and w20, w20, CacheLineAlignMask codePos = (((uint8_t*)randomx_program_aarch64_cacheline_align_mask1) - ((uint8_t*)randomx_program_aarch64)); - emit32(0x121A0000 | 18 | (18 << 5) | ((Log2(RANDOMX_DATASET_BASE_SIZE) - 7) << 10), code, codePos); + emit32(0x121A0000 | 20 | (20 << 5) | ((Log2(RANDOMX_DATASET_BASE_SIZE) - 7) << 10), code, codePos); // and w10, w10, CacheLineAlignMask codePos = (((uint8_t*)randomx_program_aarch64_cacheline_align_mask2) - ((uint8_t*)randomx_program_aarch64)); @@ -181,8 +181,8 @@ void JitCompilerA64::generateProgramLight(Program& program, ProgramConfiguration // and w16, w10, ScratchpadL3Mask64 emit32(0x121A0000 | 16 | (10 << 5) | ((Log2(RANDOMX_SCRATCHPAD_L3) - 7) << 10), code, codePos); - // and w17, w18, ScratchpadL3Mask64 - emit32(0x121A0000 | 17 | (18 << 5) | ((Log2(RANDOMX_SCRATCHPAD_L3) - 7) << 10), code, codePos); + // and w17, w20, ScratchpadL3Mask64 + emit32(0x121A0000 | 17 | (20 << 5) | ((Log2(RANDOMX_SCRATCHPAD_L3) - 7) << 10), code, codePos); codePos = PrologueSize; literalPos = ImulRcpLiteralsEnd; @@ -200,8 +200,8 @@ void JitCompilerA64::generateProgramLight(Program& program, ProgramConfiguration } // Update spMix2 - // eor w18, config.readReg2, config.readReg3 - emit32(ARMV8A::EOR32 | 18 | (IntRegMap[config.readReg2] << 5) | (IntRegMap[config.readReg3] << 16), code, codePos); + // eor w20, config.readReg2, config.readReg3 + emit32(ARMV8A::EOR32 | 20 | (IntRegMap[config.readReg2] << 5) | (IntRegMap[config.readReg3] << 16), code, codePos); // Jump back to the main loop const uint32_t offset = (((uint8_t*)randomx_program_aarch64_vm_instructions_end_light) - ((uint8_t*)randomx_program_aarch64)) - codePos; @@ -434,7 +434,7 @@ void JitCompilerA64::emitAddImmediate(uint32_t dst, uint32_t src, uint32_t imm, } else { - constexpr uint32_t tmp_reg = 18; + constexpr uint32_t tmp_reg = 20; emitMovImmediate(tmp_reg, imm, code, k); // add dst, src, tmp_reg @@ -483,7 +483,7 @@ void JitCompilerA64::emitMemLoadFP(uint32_t src, Instruction& instr, uint8_t* co uint32_t k = codePos; uint32_t imm = instr.getImm32(); - constexpr uint32_t tmp_reg = 18; + constexpr uint32_t tmp_reg = 19; imm &= instr.getModMem() ? (RANDOMX_SCRATCHPAD_L1 - 1) : (RANDOMX_SCRATCHPAD_L2 - 1); emitAddImmediate(tmp_reg, src, imm, code, k); @@ -537,7 +537,7 @@ void JitCompilerA64::h_IADD_M(Instruction& instr, uint32_t& codePos) const uint32_t src = IntRegMap[instr.src]; const uint32_t dst = IntRegMap[instr.dst]; - constexpr uint32_t tmp_reg = 18; + constexpr uint32_t tmp_reg = 20; emitMemLoad(dst, src, instr, code, k); // add dst, dst, tmp_reg @@ -575,7 +575,7 @@ void JitCompilerA64::h_ISUB_M(Instruction& instr, uint32_t& codePos) const uint32_t src = IntRegMap[instr.src]; const uint32_t dst = IntRegMap[instr.dst]; - constexpr uint32_t tmp_reg = 18; + constexpr uint32_t tmp_reg = 20; emitMemLoad(dst, src, instr, code, k); // sub dst, dst, tmp_reg @@ -594,7 +594,7 @@ void JitCompilerA64::h_IMUL_R(Instruction& instr, uint32_t& codePos) if (src == dst) { - src = 18; + src = 20; emitMovImmediate(src, instr.getImm32(), code, k); } @@ -612,7 +612,7 @@ void JitCompilerA64::h_IMUL_M(Instruction& instr, uint32_t& codePos) const uint32_t src = IntRegMap[instr.src]; const uint32_t dst = IntRegMap[instr.dst]; - constexpr uint32_t tmp_reg = 18; + constexpr uint32_t tmp_reg = 20; emitMemLoad(dst, src, instr, code, k); // sub dst, dst, tmp_reg @@ -643,7 +643,7 @@ void JitCompilerA64::h_IMULH_M(Instruction& instr, uint32_t& codePos) const uint32_t src = IntRegMap[instr.src]; const uint32_t dst = IntRegMap[instr.dst]; - constexpr uint32_t tmp_reg = 18; + constexpr uint32_t tmp_reg = 20; emitMemLoad(dst, src, instr, code, k); // umulh dst, dst, tmp_reg @@ -674,7 +674,7 @@ void JitCompilerA64::h_ISMULH_M(Instruction& instr, uint32_t& codePos) const uint32_t src = IntRegMap[instr.src]; const uint32_t dst = IntRegMap[instr.dst]; - constexpr uint32_t tmp_reg = 18; + constexpr uint32_t tmp_reg = 20; emitMemLoad(dst, src, instr, code, k); // smulh dst, dst, tmp_reg @@ -686,34 +686,24 @@ void JitCompilerA64::h_ISMULH_M(Instruction& instr, uint32_t& codePos) void JitCompilerA64::h_IMUL_RCP(Instruction& instr, uint32_t& codePos) { - const uint64_t divisor = instr.getImm32(); + const uint32_t divisor = instr.getImm32(); if (isZeroOrPowerOf2(divisor)) return; uint32_t k = codePos; - constexpr uint32_t tmp_reg = 18; + constexpr uint32_t tmp_reg = 20; const uint32_t dst = IntRegMap[instr.dst]; - constexpr uint64_t N = 1ULL << 63; - const uint64_t q = N / divisor; - const uint64_t r = N % divisor; -#ifdef __GNUC__ - const uint64_t shift = 64 - __builtin_clzll(divisor); -#else - uint64_t shift = 32; - for (uint64_t k = 1U << 31; (k & divisor) == 0; k >>= 1) - --shift; -#endif - const uint32_t literal_id = (ImulRcpLiteralsEnd - literalPos) / sizeof(uint64_t); - literalPos -= sizeof(uint64_t); - *(uint64_t*)(code + literalPos) = (q << shift) + ((r << shift) / divisor); - if (literal_id < 13) + const uint64_t reciprocal = randomx_reciprocal_fast(divisor); + memcpy(code + literalPos, &reciprocal, sizeof(reciprocal)); + + if (literal_id < 12) { - static constexpr uint32_t literal_regs[13] = { 30 << 16, 29 << 16, 28 << 16, 27 << 16, 26 << 16, 25 << 16, 24 << 16, 23 << 16, 22 << 16, 21 << 16, 20 << 16, 11 << 16, 0 }; + static constexpr uint32_t literal_regs[12] = { 30 << 16, 29 << 16, 28 << 16, 27 << 16, 26 << 16, 25 << 16, 24 << 16, 23 << 16, 22 << 16, 21 << 16, 11 << 16, 0 }; // mul dst, dst, literal_reg emit32(ARMV8A::MUL | dst | (dst << 5) | literal_regs[literal_id], code, k); @@ -751,7 +741,7 @@ void JitCompilerA64::h_IXOR_R(Instruction& instr, uint32_t& codePos) if (src == dst) { - src = 18; + src = 20; emitMovImmediate(src, instr.getImm32(), code, k); } @@ -769,7 +759,7 @@ void JitCompilerA64::h_IXOR_M(Instruction& instr, uint32_t& codePos) const uint32_t src = IntRegMap[instr.src]; const uint32_t dst = IntRegMap[instr.dst]; - constexpr uint32_t tmp_reg = 18; + constexpr uint32_t tmp_reg = 20; emitMemLoad(dst, src, instr, code, k); // eor dst, dst, tmp_reg @@ -807,7 +797,7 @@ void JitCompilerA64::h_IROL_R(Instruction& instr, uint32_t& codePos) if (src != dst) { - constexpr uint32_t tmp_reg = 18; + constexpr uint32_t tmp_reg = 20; // sub tmp_reg, xzr, src emit32(ARMV8A::SUB | tmp_reg | (31 << 5) | (src << 16), code, k); @@ -835,7 +825,7 @@ void JitCompilerA64::h_ISWAP_R(Instruction& instr, uint32_t& codePos) uint32_t k = codePos; - constexpr uint32_t tmp_reg = 18; + constexpr uint32_t tmp_reg = 20; emit32(ARMV8A::MOV_REG | tmp_reg | (dst << 16), code, k); emit32(ARMV8A::MOV_REG | dst | (src << 16), code, k); emit32(ARMV8A::MOV_REG | src | (tmp_reg << 16), code, k); @@ -984,7 +974,7 @@ void JitCompilerA64::h_CFROUND(Instruction& instr, uint32_t& codePos) const uint32_t src = IntRegMap[instr.src]; - constexpr uint32_t tmp_reg = 18; + constexpr uint32_t tmp_reg = 20; constexpr uint32_t fpcr_tmp_reg = 8; // ror tmp_reg, src, imm @@ -1008,7 +998,7 @@ void JitCompilerA64::h_ISTORE(Instruction& instr, uint32_t& codePos) const uint32_t src = IntRegMap[instr.src]; const uint32_t dst = IntRegMap[instr.dst]; - constexpr uint32_t tmp_reg = 18; + constexpr uint32_t tmp_reg = 20; uint32_t imm = instr.getImm32(); diff --git a/src/RandomX/src/jit_compiler_a64.hpp b/src/RandomX/src/jit_compiler_a64.hpp index a02824ffb..f8484c083 100644 --- a/src/RandomX/src/jit_compiler_a64.hpp +++ b/src/RandomX/src/jit_compiler_a64.hpp @@ -81,7 +81,7 @@ namespace randomx { static void emit64(uint64_t val, uint8_t* code, uint32_t& codePos) { - *(uint64_t*)(code + codePos) = val; + memcpy(code + codePos, &val, sizeof(val)); codePos += sizeof(val); } diff --git a/src/RandomX/src/jit_compiler_a64_static.S b/src/RandomX/src/jit_compiler_a64_static.S index 4886fcf3c..bc146133a 100644 --- a/src/RandomX/src/jit_compiler_a64_static.S +++ b/src/RandomX/src/jit_compiler_a64_static.S @@ -74,9 +74,9 @@ # x15 -> "r7" # x16 -> spAddr0 # x17 -> spAddr1 -# x18 -> temporary +# x18 -> unused (platform register, don't touch it) # x19 -> temporary -# x20 -> literal for IMUL_RCP +# x20 -> temporary # x21 -> literal for IMUL_RCP # x22 -> literal for IMUL_RCP # x23 -> literal for IMUL_RCP @@ -111,7 +111,7 @@ DECL(randomx_program_aarch64): # Save callee-saved registers sub sp, sp, 192 stp x16, x17, [sp] - stp x18, x19, [sp, 16] + str x19, [sp, 16] stp x20, x21, [sp, 32] stp x22, x23, [sp, 48] stp x24, x25, [sp, 64] @@ -166,7 +166,6 @@ DECL(randomx_program_aarch64): # Read literals ldr x0, literal_x0 ldr x11, literal_x11 - ldr x20, literal_x20 ldr x21, literal_x21 ldr x22, literal_x22 ldr x23, literal_x23 @@ -198,11 +197,11 @@ DECL(randomx_program_aarch64): DECL(randomx_program_aarch64_main_loop): # spAddr0 = spMix1 & ScratchpadL3Mask64; # spAddr1 = (spMix1 >> 32) & ScratchpadL3Mask64; - lsr x18, x10, 32 + lsr x20, x10, 32 # Actual mask will be inserted by JIT compiler and w16, w10, 1 - and w17, w18, 1 + and w17, w20, 1 # x16 = scratchpad + spAddr0 # x17 = scratchpad + spAddr1 @@ -210,31 +209,31 @@ DECL(randomx_program_aarch64_main_loop): add x17, x17, x2 # xor integer registers with scratchpad data (spAddr0) - ldp x18, x19, [x16] - eor x4, x4, x18 + ldp x20, x19, [x16] + eor x4, x4, x20 eor x5, x5, x19 - ldp x18, x19, [x16, 16] - eor x6, x6, x18 + ldp x20, x19, [x16, 16] + eor x6, x6, x20 eor x7, x7, x19 - ldp x18, x19, [x16, 32] - eor x12, x12, x18 + ldp x20, x19, [x16, 32] + eor x12, x12, x20 eor x13, x13, x19 - ldp x18, x19, [x16, 48] - eor x14, x14, x18 + ldp x20, x19, [x16, 48] + eor x14, x14, x20 eor x15, x15, x19 # Load group F registers (spAddr1) - ldpsw x18, x19, [x17] - ins v16.d[0], x18 + ldpsw x20, x19, [x17] + ins v16.d[0], x20 ins v16.d[1], x19 - ldpsw x18, x19, [x17, 8] - ins v17.d[0], x18 + ldpsw x20, x19, [x17, 8] + ins v17.d[0], x20 ins v17.d[1], x19 - ldpsw x18, x19, [x17, 16] - ins v18.d[0], x18 + ldpsw x20, x19, [x17, 16] + ins v18.d[0], x20 ins v18.d[1], x19 - ldpsw x18, x19, [x17, 24] - ins v19.d[0], x18 + ldpsw x20, x19, [x17, 24] + ins v19.d[0], x20 ins v19.d[1], x19 scvtf v16.2d, v16.2d scvtf v17.2d, v17.2d @@ -242,17 +241,17 @@ DECL(randomx_program_aarch64_main_loop): scvtf v19.2d, v19.2d # Load group E registers (spAddr1) - ldpsw x18, x19, [x17, 32] - ins v20.d[0], x18 + ldpsw x20, x19, [x17, 32] + ins v20.d[0], x20 ins v20.d[1], x19 - ldpsw x18, x19, [x17, 40] - ins v21.d[0], x18 + ldpsw x20, x19, [x17, 40] + ins v21.d[0], x20 ins v21.d[1], x19 - ldpsw x18, x19, [x17, 48] - ins v22.d[0], x18 + ldpsw x20, x19, [x17, 48] + ins v22.d[0], x20 ins v22.d[1], x19 - ldpsw x18, x19, [x17, 56] - ins v23.d[0], x18 + ldpsw x20, x19, [x17, 56] + ins v23.d[0], x20 ins v23.d[1], x19 scvtf v20.2d, v20.2d scvtf v21.2d, v21.2d @@ -276,7 +275,6 @@ DECL(randomx_program_aarch64_vm_instructions): literal_x0: .fill 1,8,0 literal_x11: .fill 1,8,0 -literal_x20: .fill 1,8,0 literal_x21: .fill 1,8,0 literal_x22: .fill 1,8,0 literal_x23: .fill 1,8,0 @@ -312,17 +310,17 @@ DECL(randomx_program_aarch64_vm_instructions_end): lsr x10, x9, 32 # mx ^= r[readReg2] ^ r[readReg3]; - eor x9, x9, x18 + eor x9, x9, x20 # Calculate dataset pointer for dataset prefetch - mov w18, w9 + mov w20, w9 DECL(randomx_program_aarch64_cacheline_align_mask1): # Actual mask will be inserted by JIT compiler - and x18, x18, 1 - add x18, x18, x1 + and x20, x20, 1 + add x20, x20, x1 # Prefetch dataset data - prfm pldl2strm, [x18] + prfm pldl2strm, [x20] # mx <-> ma ror x9, x9, 32 @@ -335,17 +333,17 @@ DECL(randomx_program_aarch64_cacheline_align_mask2): DECL(randomx_program_aarch64_xor_with_dataset_line): rx_program_xor_with_dataset_line: # xor integer registers with dataset data - ldp x18, x19, [x10] - eor x4, x4, x18 + ldp x20, x19, [x10] + eor x4, x4, x20 eor x5, x5, x19 - ldp x18, x19, [x10, 16] - eor x6, x6, x18 + ldp x20, x19, [x10, 16] + eor x6, x6, x20 eor x7, x7, x19 - ldp x18, x19, [x10, 32] - eor x12, x12, x18 + ldp x20, x19, [x10, 32] + eor x12, x12, x20 eor x13, x13, x19 - ldp x18, x19, [x10, 48] - eor x14, x14, x18 + ldp x20, x19, [x10, 48] + eor x14, x14, x20 eor x15, x15, x19 DECL(randomx_program_aarch64_update_spMix1): @@ -388,7 +386,7 @@ DECL(randomx_program_aarch64_update_spMix1): # Restore callee-saved registers ldp x16, x17, [sp] - ldp x18, x19, [sp, 16] + ldr x19, [sp, 16] ldp x20, x21, [sp, 32] ldp x22, x23, [sp, 48] ldp x24, x25, [sp, 64] @@ -409,7 +407,7 @@ DECL(randomx_program_aarch64_vm_instructions_end_light): stp x2, x30, [sp, 80] # mx ^= r[readReg2] ^ r[readReg3]; - eor x9, x9, x18 + eor x9, x9, x20 # mx <-> ma ror x9, x9, 32 @@ -451,8 +449,8 @@ DECL(randomx_program_aarch64_light_dataset_offset): # x3 -> end item DECL(randomx_init_dataset_aarch64): - # Save x30 (return address) - str x30, [sp, -16]! + # Save x20 (used as temporary, but must be saved to not break ABI) and x30 (return address) + stp x20, x30, [sp, -16]! # Load pointer to cache memory ldr x0, [x0] @@ -464,8 +462,8 @@ DECL(randomx_init_dataset_aarch64_main_loop): cmp x2, x3 bne DECL(randomx_init_dataset_aarch64_main_loop) - # Restore x30 (return address) - ldr x30, [sp], 16 + # Restore x20 and x30 + ldp x20, x30, [sp], 16 ret diff --git a/src/RandomX/src/jit_compiler_rv64.cpp b/src/RandomX/src/jit_compiler_rv64.cpp new file mode 100644 index 000000000..6f0842e5f --- /dev/null +++ b/src/RandomX/src/jit_compiler_rv64.cpp @@ -0,0 +1,1175 @@ +/* +Copyright (c) 2023 tevador + +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of the copyright holder nor the + names of its contributors may be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#include +#include +#include +#include +#include "jit_compiler_rv64.hpp" +#include "jit_compiler_rv64_static.hpp" +#include "superscalar.hpp" +#include "program.hpp" +#include "reciprocal.h" +#include "virtual_memory.h" + + +namespace { +#define HANDLER_ARGS randomx::CompilerState& state, randomx::Instruction isn, int i + using InstructionHandler = void(HANDLER_ARGS); + extern InstructionHandler* opcodeMap1[256]; +} + +namespace rv64 { + constexpr uint16_t C_LUI = 0x6001; + constexpr uint32_t LUI = 0x00000037; + constexpr uint16_t C_ADDI = 0x0001; + constexpr uint32_t ADDI = 0x00000013; + constexpr uint32_t ADDIW = 0x0000001b; + constexpr uint16_t C_ADD = 0x9002; + constexpr uint32_t ADD = 0x00000033; + constexpr uint32_t SHXADD = 0x20000033; //Zba + constexpr uint32_t SLL = 0x00001033; + constexpr uint32_t SRL = 0x00005033; + constexpr uint32_t SLLI = 0x00001013; + constexpr uint32_t C_SLLI = 0x0002; + constexpr uint32_t SRLI = 0x00005013; + constexpr uint32_t AND = 0x00007033; + constexpr uint32_t ANDI = 0x00007013; + constexpr uint16_t C_AND = 0x8c61; + constexpr uint16_t C_ANDI = 0x8801; + constexpr uint32_t OR = 0x00006033; + constexpr uint16_t C_OR = 0x8c41; + constexpr uint32_t XOR = 0x00004033; + constexpr uint16_t C_XOR = 0x8c21; + constexpr uint32_t LD = 0x00003003; + constexpr uint16_t C_LD = 0x6000; + constexpr uint16_t C_LW = 0x4000; + constexpr uint32_t SD = 0x00003023; + constexpr uint32_t SUB = 0x40000033; + constexpr uint16_t C_SUB = 0x8c01; + constexpr uint32_t MUL = 0x02000033; + constexpr uint32_t MULHU = 0x02003033; + constexpr uint32_t MULH = 0x02001033; + constexpr uint16_t C_MV = 0x8002; + constexpr uint32_t ROR = 0x60005033; //Zbb + constexpr uint32_t RORI = 0x60005013; //Zbb + constexpr uint32_t ROL = 0x60001033; //Zbb + constexpr uint32_t FMV_X_D = 0xe2000053; + constexpr uint32_t FMV_D_X = 0xf2000053; + constexpr uint32_t FMV_D = 0x22000053; + constexpr uint32_t FADD_D = 0x02007053; + constexpr uint32_t FSUB_D = 0x0a007053; + constexpr uint32_t FMUL_D = 0x12007053; + constexpr uint32_t FDIV_D = 0x1a007053; + constexpr uint32_t FSQRT_D = 0x5a007053; + constexpr uint32_t FCVT_D_W = 0xd2000053; + constexpr uint32_t FSRM = 0x00201073; + constexpr uint16_t C_BEQZ = 0xc001; + constexpr uint32_t BEQ = 0x00000063; + constexpr uint16_t C_BNEZ = 0xe001; + constexpr uint32_t JAL = 0x0000006f; + constexpr uint16_t C_RET = 0x8082; +} + +namespace randomx { + + constexpr size_t MaxRandomXInstrCodeSize = 56; //FDIV_M requires 56 bytes of rv64 code + constexpr size_t MaxSuperscalarInstrSize = 12; //IXOR_C requires 12 bytes of rv64 code + constexpr size_t SuperscalarProgramHeader = 136; //overhead per superscalar program + constexpr size_t CodeAlign = 4096; //align code size to a multiple of 4 KiB + constexpr size_t LiteralPoolSize = CodeAlign; + constexpr size_t SuperscalarLiteraPoolSize = RANDOMX_CACHE_ACCESSES * CodeAlign; + constexpr size_t ReserveCodeSize = CodeAlign; //prologue, epilogue + reserve + + constexpr size_t RandomXCodeSize = alignSize(LiteralPoolSize + ReserveCodeSize + MaxRandomXInstrCodeSize * RANDOMX_PROGRAM_SIZE, CodeAlign); + constexpr size_t SuperscalarSize = alignSize(SuperscalarLiteraPoolSize + ReserveCodeSize + (SuperscalarProgramHeader + MaxSuperscalarInstrSize * SuperscalarMaxSize) * RANDOMX_CACHE_ACCESSES, CodeAlign); + + static_assert(RandomXCodeSize < INT32_MAX / 2, "RandomXCodeSize is too large"); + static_assert(SuperscalarSize < INT32_MAX / 2, "SuperscalarSize is too large"); + + constexpr uint32_t CodeSize = RandomXCodeSize + SuperscalarSize; + constexpr uint32_t ExecutableSize = CodeSize - LiteralPoolSize; + + constexpr int32_t LiteralPoolOffset = LiteralPoolSize / 2; + constexpr int32_t SuperScalarLiteralPoolOffset = RandomXCodeSize; + constexpr int32_t SuperScalarLiteralPoolRefOffset = RandomXCodeSize + (RANDOMX_CACHE_ACCESSES - 1) * LiteralPoolSize + LiteralPoolOffset; + constexpr int32_t SuperScalarHashOffset = SuperScalarLiteralPoolOffset + SuperscalarLiteraPoolSize; + + constexpr int maskLog2(uint32_t x, int prev) { + return x == 1 ? prev : maskLog2(x >> 1, prev + 1); + } + + constexpr int32_t unsigned32ToSigned2sCompl(uint32_t x) { + return (-1 == ~0) ? (int32_t)x : (x > INT32_MAX ? (-(int32_t)(UINT32_MAX - x) - 1) : (int32_t)x); + } + + constexpr int MaskL1Shift = 32 - maskLog2(RANDOMX_SCRATCHPAD_L1, 0); + constexpr int MaskL2Shift = 32 - maskLog2(RANDOMX_SCRATCHPAD_L2, 0); + constexpr int MaskL3Shift = 32 - maskLog2(RANDOMX_SCRATCHPAD_L3, 0); + + constexpr int RcpLiteralsOffset = 144; + + constexpr int LiteralPoolReg = 3; //x3 + constexpr int SpadReg = 5; //x5 + constexpr int DataReg = 6; //x6 + constexpr int SuperscalarReg = 7; //x7 + constexpr int SshTmp1Reg = 28; //x28 + constexpr int SshTmp2Reg = 29; //x29 + constexpr int SshPoolReg = 30; //x30 + constexpr int SshRcpReg = 31; //x31 + constexpr int Tmp1Reg = 8; //x8 + constexpr int Tmp2Reg = 9; //x9 + constexpr int Tmp1RegF = 24; //f24 + constexpr int Tmp2RegF = 25; //f25 + constexpr int MaskL1Reg = 10; //x10 + constexpr int MaskL2Reg = 11; //x11 + constexpr int MaskFscalReg = 12; //x12 + constexpr int MaskEclear = 13; //x13 + constexpr int MaskEsetLo = 14; //x14 + constexpr int MaskEsetHi = 15; //x15 + constexpr int MaskL3Reg = 1; //x1 + constexpr int ReturnReg = 1; //x1 + constexpr int SpAddr0Reg = 26; //x26 + constexpr int OffsetXC = -8; //x8-x15 + constexpr int OffsetR = 16; //x16-x23 + constexpr int OffsetF = 0; //f0-f7 + constexpr int OffsetE = 8; //f8-f15 + constexpr int OffsetA = 16; //f16-f23 + constexpr int OffsetRcp = 28; //x28-x31 + constexpr int OffsetRcpF = 22; //f26-f31 + constexpr int OffsetSsh = 8; //x8-x15 + + //destination register (bit 7+) + constexpr int rvrd(int reg) { + return reg << 7; + } + + //first source register (bit 15+) + constexpr int rvrs1(int reg) { + return reg << 15; + } + + //second source register (bit 20+) + constexpr int rvrs2(int reg) { + return reg << 20; + } + + //compressed source register (bit 2+) + constexpr int rvcrs(int reg) { + return reg << 2; + } + + //base instruction: {op} x{rd}, x{rs1}, x{rs2} + constexpr uint32_t rvi(uint32_t op, int rd, int rs1, int rs2 = 0) { + return op | rvrs2(rs2) | rvrs1(rs1) | rvrd(rd); + } + + //compressed instruction: op x{rd}, x{rs} + constexpr uint16_t rvc(uint16_t op, int rd, int rs) { + return op | rvrd(rd) | rvcrs(rs); + } + + //compressed instruction: op x{rd}, imm6 + constexpr uint16_t rvc(uint16_t op, int imm5, int rd, int imm40) { + return op | (imm5 << 12) | rvrd(rd) | (imm40 << 2); + } + + constexpr int regR(int reg) { + return reg + OffsetR; + } + + constexpr int regLoA(int reg) { + return 2 * reg + OffsetA; + } + + constexpr int regHiA(int reg) { + return 2 * reg + OffsetA + 1; + } + + constexpr int regLoF(int reg) { + return 2 * reg + OffsetF; + } + + constexpr int regHiF(int reg) { + return 2 * reg + OffsetF + 1; + } + + constexpr int regLoE(int reg) { + return 2 * reg + OffsetE; + } + + constexpr int regHiE(int reg) { + return 2 * reg + OffsetE + 1; + } + + constexpr int regRcp(int reg) { + return reg + OffsetRcp; + } + + constexpr int regRcpF(int reg) { + return reg + OffsetRcpF; + } + + constexpr int regSS(int reg) { + return reg + OffsetSsh; + } + + static const uint8_t* codeLiterals = (uint8_t*)&randomx_riscv64_literals; + static const uint8_t* codeLiteralsEnd = (uint8_t*)&randomx_riscv64_literals_end; + static const uint8_t* codeDataInit = (uint8_t*)&randomx_riscv64_data_init; + static const uint8_t* codeFixDataCall = (uint8_t*)&randomx_riscv64_fix_data_call; + static const uint8_t* codePrologue = (uint8_t*)&randomx_riscv64_prologue; + static const uint8_t* codeLoopBegin = (uint8_t*)&randomx_riscv64_loop_begin; + static const uint8_t* codeDataRead = (uint8_t*)&randomx_riscv64_data_read; + static const uint8_t* codeDataReadLight = (uint8_t*)&randomx_riscv64_data_read_light; + static const uint8_t* codeFixLoopCall = (uint8_t*)&randomx_riscv64_fix_loop_call; + static const uint8_t* codeSpadStore = (uint8_t*)&randomx_riscv64_spad_store; + static const uint8_t* codeSpadStoreHardAes = (uint8_t*)&randomx_riscv64_spad_store_hardaes; + static const uint8_t* codeSpadStoreSoftAes = (uint8_t*)&randomx_riscv64_spad_store_softaes; + static const uint8_t* codeLoopEnd = (uint8_t*)&randomx_riscv64_loop_end; + static const uint8_t* codeFixContinueLoop = (uint8_t*)&randomx_riscv64_fix_continue_loop; + static const uint8_t* codeEpilogue = (uint8_t*)&randomx_riscv64_epilogue; + static const uint8_t* codeSoftAes = (uint8_t*)&randomx_riscv64_softaes; + static const uint8_t* codeProgramEnd = (uint8_t*)&randomx_riscv64_program_end; + static const uint8_t* codeSshInit = (uint8_t*)&randomx_riscv64_ssh_init; + static const uint8_t* codeSshLoad = (uint8_t*)&randomx_riscv64_ssh_load; + static const uint8_t* codeSshPrefetch = (uint8_t*)&randomx_riscv64_ssh_prefetch; + static const uint8_t* codeSshEnd = (uint8_t*)&randomx_riscv64_ssh_end; + + static const int32_t sizeLiterals = codeLiteralsEnd - codeLiterals; + static const int32_t sizeDataInit = codePrologue - codeDataInit; + static const int32_t sizePrologue = codeLoopBegin - codePrologue; + static const int32_t sizeLoopBegin = codeDataRead - codeLoopBegin; + static const int32_t sizeDataRead = codeDataReadLight - codeDataRead; + static const int32_t sizeDataReadLight = codeSpadStore - codeDataReadLight; + static const int32_t sizeSpadStore = codeSpadStoreHardAes - codeSpadStore; + static const int32_t sizeSpadStoreSoftAes = codeLoopEnd - codeSpadStoreSoftAes; + static const int32_t sizeLoopEnd = codeEpilogue - codeLoopEnd; + static const int32_t sizeEpilogue = codeSoftAes - codeEpilogue; + static const int32_t sizeSoftAes = codeProgramEnd - codeSoftAes; + static const int32_t sizeSshInit = codeSshLoad - codeSshInit; + static const int32_t sizeSshLoad = codeSshPrefetch - codeSshLoad; + static const int32_t sizeSshPrefetch = codeSshEnd - codeSshPrefetch; + + static const int32_t offsetFixDataCall = codeFixDataCall - codeDataInit; + static const int32_t offsetFixLoopCall = codeFixLoopCall - codeDataReadLight; + static const int32_t offsetFixContinueLoop = codeFixContinueLoop - codeLoopEnd; + + static const int32_t LoopTopPos = LiteralPoolSize + sizeDataInit + sizePrologue; + static const int32_t RandomXCodePos = LoopTopPos + sizeLoopBegin; + + static void clearCache(CodeBuffer& buf) { +#ifdef __GNUC__ + __builtin___clear_cache((char*)buf.code, (char*)(buf.code + CodeSize)); +#endif + } + + //emits code to calculate: x{dst} = x{src} + {imm32} + //takes 1-3 isns, 2-10 bytes + static void emitImm32(CodeBuffer& buf, int32_t imm, int dst, int src = 0, int tmp = 0) { + + //lower 12 bits + int32_t limm = (imm << 20) >> 20; + //upper 20 bits + int32_t uimm = (imm >> 12) + (limm < 0); + + //If there are no upper bits, the whole thing + //can be done with a single instruction. + if (uimm == 0) { + //addi x{dst}, x{src}, {limm} + buf.emit(rvi(rv64::ADDI, dst, src, limm)); + return; + } + + //dst1 is the register where imm will be materialized + int dst1 = src != dst ? dst : tmp; + assert(dst1 != 0); + //src1 is the register that will be added to the result + int src1 = src != dst ? src : dst1; + + //load upper bits + if (uimm >= -32 && uimm <= 31) { + //c.lui x{dst1}, {uimm} + buf.emit(rvc(rv64::C_LUI, (uimm < 0), dst1, (uimm & 31))); + } + else { + //lui x{dst1}, {uimm} + buf.emit(rv64::LUI | (uimm << 12) | rvrd(dst1)); + } + //load lower bits + if (limm != 0) { + //Note: this must be addiw NOT addi, otherwise the upper 32 bits + //of the 64-bit register will be incorrect. + //addiw x{dst1}, x{dst1}, {limm} + buf.emit(rvi(rv64::ADDIW, dst1, dst1, limm)); + } + //add src + if (src1 != 0) { + //c.add x{dst}, x{src1} + buf.emit(rvc(rv64::C_ADD, dst, src1)); + } + } + + //x9 = &Scratchpad[isn.imm] + //takes 3 isns, 10 bytes + static void genAddressRegImm(CodeBuffer& buf, const Instruction& isn) { + //signed offset 8-byte aligned + int32_t imm = unsigned32ToSigned2sCompl(isn.getImm32()) & ScratchpadL3Mask; + //x9 = x5 + {imm} + emitImm32(buf, imm, Tmp2Reg, SpadReg, Tmp1Reg); + } + + //x9 = &Scratchpad[isn.src + isn.imm] (for reading) + //takes 5 isns, 12 bytes + static void genAddressReg(CodeBuffer& buf, const Instruction& isn) { + int shift, maskReg; + if (isn.getModMem()) { + shift = MaskL1Shift; + maskReg = MaskL1Reg; + } + else { + shift = MaskL2Shift; + maskReg = MaskL2Reg; + } + int32_t imm = unsigned32ToSigned2sCompl(isn.getImm32()); + imm = (imm << shift) >> shift; + //x9 = x{src} + {imm} + emitImm32(buf, imm, Tmp2Reg, regR(isn.src), Tmp1Reg); + //c.and x9, x{maskReg} + buf.emit(rvc(rv64::C_AND, (Tmp2Reg + OffsetXC), (maskReg + OffsetXC))); + //c.add x9, x{spadReg} + buf.emit(rvc(rv64::C_ADD, Tmp2Reg, SpadReg)); + } + + //x8 = Scratchpad[isn] + static void loadFromScratchpad(CodeBuffer& buf, const Instruction& isn) { + if (isn.src != isn.dst) { + //x9 = &Scratchpad[isn.src + isn.imm] + genAddressReg(buf, isn); + } + else { + ///x9 = &Scratchpad[isn.imm] + genAddressRegImm(buf, isn); + } + //c.ld x8, 0(x9) + buf.emit(rvc(rv64::C_LD, Tmp2Reg + OffsetXC, Tmp1Reg + OffsetXC)); + } + + //x9 = &Scratchpad[isn.dst + isn.imm32] (for writing) + //takes 5 isns, 12-16 bytes + static void genAddressRegDst(CodeBuffer& buf, const Instruction& isn) { + if (isn.getModCond() < StoreL3Condition) { + int shift, maskReg; + if (isn.getModMem()) { + shift = MaskL1Shift; + maskReg = MaskL1Reg; + } + else { + shift = MaskL2Shift; + maskReg = MaskL2Reg; + } + int32_t imm = unsigned32ToSigned2sCompl(isn.getImm32()); + imm = (imm << shift) >> shift; + //x9 = x{dst} + {imm} + emitImm32(buf, imm, Tmp2Reg, regR(isn.dst), Tmp1Reg); + //c.and x9, x{maskReg} + buf.emit(rvc(rv64::C_AND, Tmp2Reg + OffsetXC, maskReg + OffsetXC)); + //c.add x9, x5 + buf.emit(rvc(rv64::C_ADD, Tmp2Reg, SpadReg)); + } + else { + int shift = MaskL3Shift; + int32_t imm = unsigned32ToSigned2sCompl(isn.getImm32()); + imm = (imm << shift) >> shift; + //x9 = x{dst} + {imm} + emitImm32(buf, imm, Tmp2Reg, regR(isn.dst), Tmp1Reg); + //and x9, x9, x1 + buf.emit(rvi(rv64::AND, Tmp2Reg, Tmp2Reg, MaskL3Reg)); + //c.add x9, x5 + buf.emit(rvc(rv64::C_ADD, Tmp2Reg, SpadReg)); + } + } + + static void emitRcpLiteral1(CodeBuffer& buf, uint64_t literal) { + //first 238 at positive offsets + if (buf.rcpCount < 238) { + buf.emitAt(LiteralPoolOffset + RcpLiteralsOffset + buf.rcpCount * 8, literal); + buf.rcpCount++; + } + //next 256 at negative offsets + else if (buf.rcpCount < 494) { + buf.emitAt(buf.rcpCount * 8 - (2048 - RcpLiteralsOffset), literal); + buf.rcpCount++; + } + else { + //checked at compile time, but double-check here + throw std::runtime_error("Literal pool overflow"); + } + } + + static void emitRcpLiteral2(CodeBuffer& buf, uint64_t literal, int32_t numLiterals) { + //store the current literal in the pool + int32_t offset = 2040 - buf.rcpCount * 8; + buf.emitAt(SuperScalarLiteralPoolRefOffset + offset, literal); + buf.rcpCount++; + if (buf.rcpCount >= numLiterals) { + return; + } + //load the next literal + offset -= 8; + int32_t imm = offset & 0xfff; + //ld x31, {offset}(x30) + buf.emit(rvi(rv64::LD, SshRcpReg, SshPoolReg, imm)); + if (imm == 0x800) { + //move pool pointer back 4KB + //c.lui x29, 0xfffff + buf.emit(rvc(rv64::C_LUI, 1, SshTmp2Reg, 31)); + //c.add x30, x29 + buf.emit(rvc(rv64::C_ADD, SshPoolReg, SshTmp2Reg)); + } + } + + static void emitJump(CodeBuffer& buf, int dst, int32_t codePos, int32_t targetPos) { + int32_t imm = targetPos - codePos; + int32_t imm20 = (imm < 0) << 11; + int32_t imm1912 = (imm >> 7) & 8160; + int32_t imm11 = (imm >> 11) & 1; + int32_t imm101 = imm & 2046; + //jal x{dst}, {imm} + buf.emitAt(codePos, rvi(rv64::JAL, dst + imm1912, 0, imm20 + imm101 + imm11)); + } + + static void emitInstruction(CompilerState& state, Instruction isn, int i) { + state.instructionOffsets[i] = state.codePos; + opcodeMap1[isn.opcode](state, isn, i); + } + + static void emitProgramPrefix(CompilerState& state, Program& prog, ProgramConfiguration& pcfg) { + state.codePos = RandomXCodePos; + state.rcpCount = 0; + state.emitAt(LiteralPoolOffset + sizeLiterals, pcfg.eMask[0]); + state.emitAt(LiteralPoolOffset + sizeLiterals + 8, pcfg.eMask[1]); + for (unsigned i = 0; i < RegistersCount; ++i) { + state.registerUsage[i] = -1; + } + for (unsigned i = 0; i < prog.getSize(); ++i) { + Instruction instr = prog(i); + instr.src %= RegistersCount; + instr.dst %= RegistersCount; + emitInstruction(state, instr, i); + } + } + + static void emitProgramSuffix(CompilerState& state, ProgramConfiguration& pcfg) { + state.emit(codeSpadStore, sizeSpadStore); + int32_t fixPos = state.codePos; + state.emit(codeLoopEnd, sizeLoopEnd); + //xor x26, x{readReg0}, x{readReg1} + state.emitAt(fixPos, rvi(rv64::XOR, SpAddr0Reg, regR(pcfg.readReg0), regR(pcfg.readReg1))); + fixPos += offsetFixContinueLoop; + //j LoopTop + emitJump(state, 0, fixPos, LoopTopPos); + state.emit(codeEpilogue, sizeEpilogue); + } + + static void generateSuperscalarCode(CodeBuffer& buf, Instruction isn, const std::vector& reciprocalCache) { + switch ((SuperscalarInstructionType)isn.opcode) + { + case randomx::SuperscalarInstructionType::ISUB_R: + //c.sub x{dst}, x{src} + buf.emit(rvc(rv64::C_SUB, regSS(isn.dst) + OffsetXC, regSS(isn.src) + OffsetXC)); + break; + case randomx::SuperscalarInstructionType::IXOR_R: + //c.xor x{dst}, x{src} + buf.emit(rvc(rv64::C_XOR, regSS(isn.dst) + OffsetXC, regSS(isn.src) + OffsetXC)); + break; + case randomx::SuperscalarInstructionType::IADD_RS: + { + int shift = isn.getModShift(); + if (shift == 0) { + //c.add x{dst}, x{src} + buf.emit(rvc(rv64::C_ADD, regSS(isn.dst), regSS(isn.src))); + } + else { +#ifdef __riscv_zba + //sh{1,2,3}add x{dst}, x{src}, x{dst} + buf.emit(rv64::SHXADD | rvrs2(regSS(isn.dst)) | rvrs1(regSS(isn.src)) | (shift << 13) | rvrd(regSS(isn.dst))); +#else + //slli x28, x{src}, {shift} + buf.emit(rvi(rv64::SLLI, SshTmp1Reg, regSS(isn.src), shift)); + //c.add x{dst}, x28 + buf.emit(rvc(rv64::C_ADD, regSS(isn.dst), SshTmp1Reg)); +#endif + } + } + break; + case randomx::SuperscalarInstructionType::IMUL_R: + //mul x{dst}, x{dst}, x{src} + buf.emit(rvi(rv64::MUL, regSS(isn.dst), regSS(isn.dst), regSS(isn.src))); + break; + case randomx::SuperscalarInstructionType::IROR_C: + { +#ifdef __riscv_zbb + int32_t imm = isn.getImm32() & 63; + //rori x{dst}, x{dst}, {imm} + buf.emit(rvi(rv64::RORI, regSS(isn.dst), regSS(isn.dst), imm)); +#else + int32_t immr = isn.getImm32() & 63; + int32_t imml = -immr & 63; + int32_t imml5 = imml >> 5; + int32_t imml40 = imml & 31; + //srli x28, x{dst}, {immr} + buf.emit(rvi(rv64::SRLI, SshTmp1Reg, regSS(isn.dst), immr)); + //c.slli x{dst}, {imml} + buf.emit(rvc(rv64::C_SLLI, imml5, regSS(isn.dst), imml40)); + //or x{dst}, x{dst}, x28 + buf.emit(rvi(rv64::OR, regSS(isn.dst), regSS(isn.dst), SshTmp1Reg)); +#endif + } + break; + case randomx::SuperscalarInstructionType::IADD_C7: + case randomx::SuperscalarInstructionType::IADD_C8: + case randomx::SuperscalarInstructionType::IADD_C9: + { + int32_t imm = unsigned32ToSigned2sCompl(isn.getImm32()); + //x{dst} = x{dst} + {imm} + emitImm32(buf, imm, regSS(isn.dst), regSS(isn.dst), SshTmp1Reg); + } + break; + case randomx::SuperscalarInstructionType::IXOR_C7: + case randomx::SuperscalarInstructionType::IXOR_C8: + case randomx::SuperscalarInstructionType::IXOR_C9: + { + int32_t imm = unsigned32ToSigned2sCompl(isn.getImm32()); + //x28 = {imm} + emitImm32(buf, imm, SshTmp1Reg); + //xor x{dst}, x{dst}, x28 + buf.emit(rvi(rv64::XOR, regSS(isn.dst), regSS(isn.dst), SshTmp1Reg)); + } + break; + case randomx::SuperscalarInstructionType::IMULH_R: + //mulhu x{dst}, x{dst}, x{src} + buf.emit(rvi(rv64::MULHU, regSS(isn.dst), regSS(isn.dst), regSS(isn.src))); + break; + case randomx::SuperscalarInstructionType::ISMULH_R: + //mulh x{dst}, x{dst}, x{src} + buf.emit(rvi(rv64::MULH, regSS(isn.dst), regSS(isn.dst), regSS(isn.src))); + break; + case randomx::SuperscalarInstructionType::IMUL_RCP: + //mul x{dst}, x{dst}, x31 + buf.emit(rvi(rv64::MUL, regSS(isn.dst), regSS(isn.dst), SshRcpReg)); + //load the next literal into x31 + emitRcpLiteral2(buf, reciprocalCache[isn.getImm32()], reciprocalCache.size()); + break; + default: + UNREACHABLE; + } + } + + size_t JitCompilerRV64::getCodeSize() { + return CodeSize; + } + + JitCompilerRV64::JitCompilerRV64() { + state.code = (uint8_t*)allocMemoryPages(CodeSize); + if (state.code == nullptr) + throw std::runtime_error("allocMemoryPages"); + state.emitAt(LiteralPoolOffset, codeLiterals, sizeLiterals); + state.emitAt(LiteralPoolSize, codeDataInit, sizeDataInit + sizePrologue + sizeLoopBegin); + entryDataInit = state.code + LiteralPoolSize; + entryProgram = state.code + LiteralPoolSize + sizeDataInit; + //jal x1, SuperscalarHash + emitJump(state, ReturnReg, LiteralPoolSize + offsetFixDataCall, SuperScalarHashOffset); + } + + JitCompilerRV64::~JitCompilerRV64() { + freePagedMemory(state.code, CodeSize); + } + + void JitCompilerRV64::enableAll() { + setPagesRWX(entryDataInit, ExecutableSize); + } + + void JitCompilerRV64::enableWriting() { + setPagesRW(entryDataInit, ExecutableSize); + } + + void JitCompilerRV64::enableExecution() { + setPagesRX(entryDataInit, ExecutableSize); + } + + void JitCompilerRV64::generateProgram(Program& prog, ProgramConfiguration& pcfg) { + emitProgramPrefix(state, prog, pcfg); + int32_t fixPos = state.codePos; + state.emit(codeDataRead, sizeDataRead); + //xor x8, x{readReg2}, x{readReg3} + state.emitAt(fixPos, rvi(rv64::XOR, Tmp1Reg, regR(pcfg.readReg2), regR(pcfg.readReg3))); + emitProgramSuffix(state, pcfg); + clearCache(state); + } + + void JitCompilerRV64::generateProgramLight(Program& prog, ProgramConfiguration& pcfg, uint32_t datasetOffset) { + emitProgramPrefix(state, prog, pcfg); + int32_t fixPos = state.codePos; + state.emit(codeDataReadLight, sizeDataReadLight); + //xor x8, x{readReg2}, x{readReg3} + state.emitAt(fixPos, rvi(rv64::XOR, Tmp1Reg, regR(pcfg.readReg2), regR(pcfg.readReg3))); + int32_t imm = datasetOffset / CacheLineSize; + int32_t limm = (imm << 20) >> 20; + int32_t uimm = (imm >> 12) + (limm < 0); + //lui x9, {uimm} + state.emitAt(fixPos + 4, rv64::LUI | (uimm << 12) | rvrd(Tmp2Reg)); + //addi x9, x9, {limm} + state.emitAt(fixPos + 8, rvi(rv64::ADDI, Tmp2Reg, Tmp2Reg, limm)); + fixPos += offsetFixLoopCall; + //jal x1, SuperscalarHash + emitJump(state, ReturnReg, fixPos, SuperScalarHashOffset); + emitProgramSuffix(state, pcfg); + clearCache(state); + } + + void JitCompilerRV64::generateSuperscalarHash(SuperscalarProgram programs[RANDOMX_CACHE_ACCESSES], std::vector& reciprocalCache) { + state.codePos = SuperScalarHashOffset; + state.rcpCount = 0; + state.emit(codeSshInit, sizeSshInit); + for (unsigned j = 0; j < RANDOMX_CACHE_ACCESSES; ++j) { + SuperscalarProgram& prog = programs[j]; + for (unsigned i = 0; i < prog.getSize(); ++i) { + Instruction instr = prog(i); + generateSuperscalarCode(state, instr, reciprocalCache); + } + state.emit(codeSshLoad, sizeSshLoad); + if (j < RANDOMX_CACHE_ACCESSES - 1) { + int32_t fixPos = state.codePos; + state.emit(codeSshPrefetch, sizeSshPrefetch); + //and x7, x{addrReg}, x7 + state.emitAt(fixPos, rvi(rv64::AND, SuperscalarReg, regSS(prog.getAddressRegister()), SuperscalarReg)); + } + } + state.emit(rvc(rv64::C_RET, 0, 0)); + clearCache(state); + } + + static void v1_IADD_RS(HANDLER_ARGS) { + state.registerUsage[isn.dst] = i; + int shift = isn.getModShift(); + if (shift == 0) { + //c.add x{dst}, x{src} + state.emit(rvc(rv64::C_ADD, regR(isn.dst), regR(isn.src))); + } + else { +#ifdef __riscv_zba + //sh{1,2,3}add x{dst}, x{src}, x{dst} + state.emit(rv64::SHXADD | rvrs2(regR(isn.dst)) | rvrs1(regR(isn.src)) | (shift << 13) | rvrd(regR(isn.dst))); +#else + //slli x8, x{src}, {shift} + state.emit(rvi(rv64::SLLI, Tmp1Reg, regR(isn.src), shift)); + //c.add x{dst}, x8 + state.emit(rvc(rv64::C_ADD, regR(isn.dst), Tmp1Reg)); +#endif + } + if (isn.dst == RegisterNeedsDisplacement) { + int32_t imm = unsigned32ToSigned2sCompl(isn.getImm32()); + //x{dst} = x{dst} + {imm} + emitImm32(state, imm, regR(isn.dst), regR(isn.dst), Tmp1Reg); + } + } + + static void v1_IADD_M(HANDLER_ARGS) { + state.registerUsage[isn.dst] = i; + loadFromScratchpad(state, isn); + //c.add x{dst}, x8 + state.emit(rvc(rv64::C_ADD, regR(isn.dst), Tmp1Reg)); + } + + static void v1_ISUB_R(HANDLER_ARGS) { + state.registerUsage[isn.dst] = i; + if (isn.src != isn.dst) { + //sub x{dst}, x{dst}, x{src} + state.emit(rvi(rv64::SUB, regR(isn.dst), regR(isn.dst), regR(isn.src))); + } + else { + int32_t imm = unsigned32ToSigned2sCompl(-isn.getImm32()); //convert to add + //x{dst} = x{dst} + {-imm} + emitImm32(state, imm, regR(isn.dst), regR(isn.dst), Tmp1Reg); + } + } + + static void v1_ISUB_M(HANDLER_ARGS) { + state.registerUsage[isn.dst] = i; + loadFromScratchpad(state, isn); + //sub x{dst}, x{dst}, x8 + state.emit(rvi(rv64::SUB, regR(isn.dst), regR(isn.dst), Tmp1Reg)); + } + + static void v1_IMUL_R(HANDLER_ARGS) { + state.registerUsage[isn.dst] = i; + if (isn.src != isn.dst) { + //mul x{dst}, x{dst}, x{src} + state.emit(rvi(rv64::MUL, regR(isn.dst), regR(isn.dst), regR(isn.src))); + } + else { + int32_t imm = unsigned32ToSigned2sCompl(isn.getImm32()); + //x8 = {imm} + emitImm32(state, imm, Tmp1Reg); + //mul x{dst}, x{dst}, x8 + state.emit(rvi(rv64::MUL, regR(isn.dst), regR(isn.dst), Tmp1Reg)); + } + } + + static void v1_IMUL_M(HANDLER_ARGS) { + state.registerUsage[isn.dst] = i; + loadFromScratchpad(state, isn); + //mul x{dst}, x{dst}, x8 + state.emit(rvi(rv64::MUL, regR(isn.dst), regR(isn.dst), Tmp1Reg)); + } + + static void v1_IMULH_R(HANDLER_ARGS) { + state.registerUsage[isn.dst] = i; + //mulhu x{dst}, x{dst}, x{src} + state.emit(rvi(rv64::MULHU, regR(isn.dst), regR(isn.dst), regR(isn.src))); + } + + static void v1_IMULH_M(HANDLER_ARGS) { + state.registerUsage[isn.dst] = i; + loadFromScratchpad(state, isn); + //mulhu x{dst}, x{dst}, x8 + state.emit(rvi(rv64::MULHU, regR(isn.dst), regR(isn.dst), Tmp1Reg)); + } + + static void v1_ISMULH_R(HANDLER_ARGS) { + state.registerUsage[isn.dst] = i; + //mulh x{dst}, x{dst}, x{src} + state.emit(rvi(rv64::MULH, regR(isn.dst), regR(isn.dst), regR(isn.src))); + } + + static void v1_ISMULH_M(HANDLER_ARGS) { + state.registerUsage[isn.dst] = i; + loadFromScratchpad(state, isn); + //mulh x{dst}, x{dst}, x8 + state.emit(rvi(rv64::MULH, regR(isn.dst), regR(isn.dst), Tmp1Reg)); + } + + static void v1_IMUL_RCP(HANDLER_ARGS) { + const uint32_t divisor = isn.getImm32(); + if (!isZeroOrPowerOf2(divisor)) { + state.registerUsage[isn.dst] = i; + if (state.rcpCount < 4) { + //mul x{dst}, x{dst}, x{rcp} + state.emit(rvi(rv64::MUL, regR(isn.dst), regR(isn.dst), regRcp(state.rcpCount))); + } + else if (state.rcpCount < 10) { + //fmv.x.d x8, f{rcp} + state.emit(rvi(rv64::FMV_X_D, Tmp1Reg, regRcpF(state.rcpCount))); + //mul x{dst}, x{dst}, x8 + state.emit(rvi(rv64::MUL, regR(isn.dst), regR(isn.dst), Tmp1Reg)); + } + else { + int32_t offset = RcpLiteralsOffset + state.rcpCount * 8; + //ld x8, {offset}(x3) + state.emit(rvi(rv64::LD, Tmp1Reg, LiteralPoolReg, offset)); + //mul x{dst}, x{dst}, x8 + state.emit(rvi(rv64::MUL, regR(isn.dst), regR(isn.dst), Tmp1Reg)); + } + emitRcpLiteral1(state, randomx_reciprocal_fast(divisor)); + } + } + + static void v1_INEG_R(HANDLER_ARGS) { + state.registerUsage[isn.dst] = i; + //sub x{dst}, x0, x{dst} + state.emit(rvi(rv64::SUB, regR(isn.dst), 0, regR(isn.dst))); + } + + static void v1_IXOR_R(HANDLER_ARGS) { + state.registerUsage[isn.dst] = i; + if (isn.src != isn.dst) { + //xor x{dst}, x{dst}, x{src} + state.emit(rvi(rv64::XOR, regR(isn.dst), regR(isn.dst), regR(isn.src))); + } + else { + int32_t imm = unsigned32ToSigned2sCompl(isn.getImm32()); + //x8 = {imm} + emitImm32(state, imm, Tmp1Reg); + //xor x{dst}, x{dst}, x8 + state.emit(rvi(rv64::XOR, regR(isn.dst), regR(isn.dst), Tmp1Reg)); + } + } + + static void v1_IXOR_M(HANDLER_ARGS) { + state.registerUsage[isn.dst] = i; + loadFromScratchpad(state, isn); + //xor x{dst}, x{dst}, x8 + state.emit(rvi(rv64::XOR, regR(isn.dst), regR(isn.dst), Tmp1Reg)); + } + + static void v1_IROR_R(HANDLER_ARGS) { + state.registerUsage[isn.dst] = i; +#ifdef __riscv_zbb + if (isn.src != isn.dst) { + //ror x{dst}, x{dst}, x{src} + state.emit(rvi(rv64::ROR, regR(isn.dst), regR(isn.dst), regR(isn.src))); + } + else { + int32_t imm = isn.getImm32() & 63; + //rori x{dst}, x{dst}, {imm} + state.emit(rvi(rv64::RORI, regR(isn.dst), regR(isn.dst), imm)); + } +#else + if (isn.src != isn.dst) { + //sub x8, x0, x{src} + state.emit(rvi(rv64::SUB, Tmp1Reg, 0, regR(isn.src))); + //srl x9, x{dst}, x{src} + state.emit(rvi(rv64::SRL, Tmp2Reg, regR(isn.dst), regR(isn.src))); + //sll x{dst}, x{dst}, x8 + state.emit(rvi(rv64::SLL, regR(isn.dst), regR(isn.dst), Tmp1Reg)); + //or x{dst}, x{dst}, x9 + state.emit(rvi(rv64::OR, regR(isn.dst), regR(isn.dst), Tmp2Reg)); + } + else { + int32_t immr = isn.getImm32() & 63; + int32_t imml = -immr & 63; + int32_t imml5 = imml >> 5; + int32_t imml40 = imml & 31; + //srli x8, x{dst}, {immr} + state.emit(rvi(rv64::SRLI, Tmp1Reg, regR(isn.dst), immr)); + //c.slli x{dst}, {imml} + state.emit(rvc(rv64::C_SLLI, imml5, regR(isn.dst), imml40)); + //or x{dst}, x{dst}, x8 + state.emit(rvi(rv64::OR, regR(isn.dst), regR(isn.dst), Tmp1Reg)); + } +#endif + } + + static void v1_IROL_R(HANDLER_ARGS) { + state.registerUsage[isn.dst] = i; +#ifdef __riscv_zbb + if (isn.src != isn.dst) { + //rol x{dst}, x{dst}, x{src} + state.emit(rvi(rv64::ROL, regR(isn.dst), regR(isn.dst), regR(isn.src))); + } + else { + int32_t imm = -isn.getImm32() & 63; + //rori x{dst}, x{dst}, {imm} + state.emit(rvi(rv64::RORI, regR(isn.dst), regR(isn.dst), imm)); + } +#else + if (isn.src != isn.dst) { + //sub x8, x0, x{src} + state.emit(rvi(rv64::SUB, Tmp1Reg, 0, regR(isn.src))); + //sll x9, x{dst}, x{src} + state.emit(rvi(rv64::SLL, Tmp2Reg, regR(isn.dst), regR(isn.src))); + //srl x{dst}, x{dst}, x8 + state.emit(rvi(rv64::SRL, regR(isn.dst), regR(isn.dst), Tmp1Reg)); + //or x{dst}, x{dst}, x9 + state.emit(rvi(rv64::OR, regR(isn.dst), regR(isn.dst), Tmp2Reg)); + } + else { + int32_t imml = isn.getImm32() & 63; + int32_t immr = -imml & 63; + int32_t imml5 = imml >> 5; + int32_t imml40 = imml & 31; + //srli x8, x{dst}, {immr} + state.emit(rvi(rv64::SRLI, Tmp1Reg, regR(isn.dst), immr)); + //c.slli x{dst}, {imml} + state.emit(rvc(rv64::C_SLLI, imml5, regR(isn.dst), imml40)); + //or x{dst}, x{dst}, x8 + state.emit(rvi(rv64::OR, regR(isn.dst), regR(isn.dst), Tmp1Reg)); + } +#endif + } + + static void v1_ISWAP_R(HANDLER_ARGS) { + if (isn.src != isn.dst) { + state.registerUsage[isn.dst] = i; + state.registerUsage[isn.src] = i; + //c.mv x8, x{dst} + state.emit(rvc(rv64::C_MV, Tmp1Reg, regR(isn.dst))); + //c.mv x{dst}, x{src} + state.emit(rvc(rv64::C_MV, regR(isn.dst), regR(isn.src))); + //c.mv x{src}, x8 + state.emit(rvc(rv64::C_MV, regR(isn.src), Tmp1Reg)); + } + } + + static void v1_FSWAP_R(HANDLER_ARGS) { + //fmv.d f24, f{dst_lo} + state.emit(rvi(rv64::FMV_D, Tmp1RegF, regLoF(isn.dst), regLoF(isn.dst))); + //fmv.d f{dst_lo}, f{dst_hi} + state.emit(rvi(rv64::FMV_D, regLoF(isn.dst), regHiF(isn.dst), regHiF(isn.dst))); + //fmv.d f{dst_hi}, f24 + state.emit(rvi(rv64::FMV_D, regHiF(isn.dst), Tmp1RegF, Tmp1RegF)); + } + + static void v1_FADD_R(HANDLER_ARGS) { + isn.dst %= RegisterCountFlt; + isn.src %= RegisterCountFlt; + //fadd.d f{dst_lo}, f{dst_lo}, f{src_lo} + state.emit(rvi(rv64::FADD_D, regLoF(isn.dst), regLoF(isn.dst), regLoA(isn.src))); + //fadd.d f{dst_hi}, f{dst_hi}, f{src_hi} + state.emit(rvi(rv64::FADD_D, regHiF(isn.dst), regHiF(isn.dst), regHiA(isn.src))); + } + + static void v1_FADD_M(HANDLER_ARGS) { + isn.dst %= RegisterCountFlt; + //x9 = mem + genAddressReg(state, isn); + //lw x8, 0(x9) + state.emit(rvc(rv64::C_LW, Tmp2Reg + OffsetXC, Tmp1Reg + OffsetXC)); + //lw x9, 4(x9) + state.emit(rvc(rv64::C_LW, Tmp2Reg + OffsetXC, 16 + Tmp2Reg + OffsetXC)); + //fcvt.d.w f24, x8 + state.emit(rvi(rv64::FCVT_D_W, Tmp1RegF, Tmp1Reg)); + //fcvt.d.w f25, x9 + state.emit(rvi(rv64::FCVT_D_W, Tmp2RegF, Tmp2Reg)); + //fadd.d f{dst_lo}, f{dst_lo}, f24 + state.emit(rvi(rv64::FADD_D, regLoF(isn.dst), regLoF(isn.dst), Tmp1RegF)); + //fadd.d f{dst_hi}, f{dst_hi}, f25 + state.emit(rvi(rv64::FADD_D, regHiF(isn.dst), regHiF(isn.dst), Tmp2RegF)); + } + + static void v1_FSUB_R(HANDLER_ARGS) { + isn.dst %= RegisterCountFlt; + isn.src %= RegisterCountFlt; + //fsub.d f{dst_lo}, f{dst_lo}, f{src_lo} + state.emit(rvi(rv64::FSUB_D, regLoF(isn.dst), regLoF(isn.dst), regLoA(isn.src))); + //fsub.d f{dst_hi}, f{dst_hi}, f{src_hi} + state.emit(rvi(rv64::FSUB_D, regHiF(isn.dst), regHiF(isn.dst), regHiA(isn.src))); + } + + static void v1_FSUB_M(HANDLER_ARGS) { + isn.dst %= RegisterCountFlt; + //x9 = mem + genAddressReg(state, isn); + //c.lw x8, 0(x9) + state.emit(rvc(rv64::C_LW, Tmp2Reg + OffsetXC, Tmp1Reg + OffsetXC)); + //c.lw x9, 4(x9) + state.emit(rvc(rv64::C_LW, Tmp2Reg + OffsetXC, 16 + Tmp2Reg + OffsetXC)); + //fcvt.d.w f24, x8 + state.emit(rvi(rv64::FCVT_D_W, Tmp1RegF, Tmp1Reg)); + //fcvt.d.w f25, x9 + state.emit(rvi(rv64::FCVT_D_W, Tmp2RegF, Tmp2Reg)); + //fsub.d f{dst_lo}, f{dst_lo}, f24 + state.emit(rvi(rv64::FSUB_D, regLoF(isn.dst), regLoF(isn.dst), Tmp1RegF)); + //fsub.d f{dst_hi}, f{dst_hi}, f25 + state.emit(rvi(rv64::FSUB_D, regHiF(isn.dst), regHiF(isn.dst), Tmp2RegF)); + } + + static void v1_FSCAL_R(HANDLER_ARGS) { + isn.dst %= RegisterCountFlt; + //fmv.x.d x8, f{dst_lo} + state.emit(rvi(rv64::FMV_X_D, Tmp1Reg, regLoF(isn.dst))); + //fmv.x.d x9, f{dst_hi} + state.emit(rvi(rv64::FMV_X_D, Tmp2Reg, regHiF(isn.dst))); + //c.xor x8, x12 + state.emit(rvc(rv64::C_XOR, Tmp1Reg + OffsetXC, MaskFscalReg + OffsetXC)); + //c.xor x9, x12 + state.emit(rvc(rv64::C_XOR, Tmp2Reg + OffsetXC, MaskFscalReg + OffsetXC)); + //fmv.d.x f{dst_lo}, x8 + state.emit(rvi(rv64::FMV_D_X, regLoF(isn.dst), Tmp1Reg)); + //fmv.d.x f{dst_hi}, x9 + state.emit(rvi(rv64::FMV_D_X, regHiF(isn.dst), Tmp2Reg)); + } + + static void v1_FMUL_R(HANDLER_ARGS) { + isn.dst %= RegisterCountFlt; + isn.src %= RegisterCountFlt; + //fmul.d f{dst_lo}, f{dst_lo}, f{src_lo} + state.emit(rvi(rv64::FMUL_D, regLoE(isn.dst), regLoE(isn.dst), regLoA(isn.src))); + //fmul.d f{dst_hi}, f{dst_hi}, f{src_hi} + state.emit(rvi(rv64::FMUL_D, regHiE(isn.dst), regHiE(isn.dst), regHiA(isn.src))); + } + + static void v1_FDIV_M(HANDLER_ARGS) { + isn.dst %= RegisterCountFlt; + //x9 = mem + genAddressReg(state, isn); + //lw x8, 0(x9) + state.emit(rvc(rv64::C_LW, Tmp2Reg + OffsetXC, Tmp1Reg + OffsetXC)); + //lw x9, 4(x9) + state.emit(rvc(rv64::C_LW, Tmp2Reg + OffsetXC, 16 + Tmp2Reg + OffsetXC)); + //fcvt.d.w f24, x8 + state.emit(rvi(rv64::FCVT_D_W, Tmp1RegF, Tmp1Reg)); + //fcvt.d.w f25, x9 + state.emit(rvi(rv64::FCVT_D_W, Tmp2RegF, Tmp2Reg)); + //fmv.x.d x8, f24 + state.emit(rvi(rv64::FMV_X_D, Tmp1Reg, Tmp1RegF)); + //fmv.x.d x9, f25 + state.emit(rvi(rv64::FMV_X_D, Tmp2Reg, Tmp2RegF)); + //c.and x8, x13 + state.emit(rvc(rv64::C_AND, Tmp1Reg + OffsetXC, MaskEclear + OffsetXC)); + //c.and x9, x13 + state.emit(rvc(rv64::C_AND, Tmp2Reg + OffsetXC, MaskEclear + OffsetXC)); + //c.or x8, x14 + state.emit(rvc(rv64::C_OR, Tmp1Reg + OffsetXC, MaskEsetLo + OffsetXC)); + //c.or x9, x15 + state.emit(rvc(rv64::C_OR, Tmp2Reg + OffsetXC, MaskEsetHi + OffsetXC)); + //fmv.d.x f24, x8 + state.emit(rvi(rv64::FMV_D_X, Tmp1RegF, Tmp1Reg)); + //fmv.d.x f25, x9 + state.emit(rvi(rv64::FMV_D_X, Tmp2RegF, Tmp2Reg)); + //fdiv.d f{dst_lo}, f{dst_lo}, f24 + state.emit(rvi(rv64::FDIV_D, regLoE(isn.dst), regLoE(isn.dst), Tmp1RegF)); + //fdiv.d f{dst_hi}, f{dst_hi}, f25 + state.emit(rvi(rv64::FDIV_D, regHiE(isn.dst), regHiE(isn.dst), Tmp2RegF)); + } + + static void v1_FSQRT_R(HANDLER_ARGS) { + isn.dst %= RegisterCountFlt; + //fsqrt.d f{dst_lo}, f{dst_lo} + state.emit(rvi(rv64::FSQRT_D, regLoE(isn.dst), regLoE(isn.dst))); + //fsqrt.d f{dst_hi}, f{dst_hi} + state.emit(rvi(rv64::FSQRT_D, regHiE(isn.dst), regHiE(isn.dst))); + } + + static void v1_CBRANCH(HANDLER_ARGS) { + int reg = isn.dst; + int target = state.registerUsage[reg] + 1; + int shift = isn.getModCond() + ConditionOffset; + int32_t imm = unsigned32ToSigned2sCompl(isn.getImm32()); + imm |= (1UL << shift); + if (ConditionOffset > 0 || shift > 0) + imm &= ~(1UL << (shift - 1)); + //x8 = branchMask + emitImm32(state, (int32_t)ConditionMask << shift, Tmp1Reg); + //x{dst} += {imm} + emitImm32(state, imm, regR(isn.dst), regR(isn.dst), Tmp2Reg); + //and x8, x8, x{dst} + state.emit(rvi(rv64::AND, Tmp1Reg, Tmp1Reg, regR(isn.dst))); + int32_t targetPos = state.instructionOffsets[target]; + int offset = targetPos - state.codePos; + if (offset >= -256) { //C.BEQZ only has a range of 256B + //c.beqz x8, {offset} + int imm8 = 1; //sign bit is always 1 + int imm21 = offset & 6; //offset[2:1] + int imm5 = (offset >> 5) & 1; //offset[5] + int imm43 = offset & 24; //offset[4:3] + int imm76 = (offset >> 3) & 24; //offset[7:6] + state.emit(rvc(rv64::C_BEQZ, imm8, imm43 + (Tmp1Reg + OffsetXC), imm76 + imm21 + imm5)); + } + else if (offset >= -4096) { //BEQ only has a range of 4KB + //beq x8, x0, offset + int imm12 = 1 << 11; //sign bit is always 1 + int imm105 = offset & 2016; //offset[10:5] + int imm41 = offset & 30; //offset[4:1] + int imm11 = (offset >> 11) & 1; //offset[11] + state.emit(rvi(rv64::BEQ, imm41 + imm11, Tmp1Reg, imm12 + imm105)); + } + else { + //c.bnez x8, +6 + state.emit(rvc(rv64::C_BNEZ, Tmp1Reg + OffsetXC, 6)); + //j targetPos + emitJump(state, 0, state.codePos, targetPos); + state.codePos += 4; + } + //mark all registers as used + for (unsigned j = 0; j < RegistersCount; ++j) { + state.registerUsage[j] = i; + } + } + + static void v1_CFROUND(HANDLER_ARGS) { + int32_t imm = (isn.getImm32() - 2) & 63; //-2 to avoid a later left shift to multiply by 4 + if (imm != 0) { +#ifdef __riscv_zbb + //rori x8, x{src}, {imm} + state.emit(rvi(rv64::RORI, Tmp1Reg, regR(isn.src), imm)); +#else + int32_t imml = -imm & 63; + //srli x8, x{src}, {imm} + state.emit(rvi(rv64::SRLI, Tmp1Reg, regR(isn.src), imm)); + //slli x9, x{src}, {imml} + state.emit(rvi(rv64::SLLI, Tmp2Reg, regR(isn.src), imml)); + //c.or x8, x9 + state.emit(rvc(rv64::C_OR, Tmp1Reg + OffsetXC, Tmp2Reg + OffsetXC)); +#endif + //c.andi x8, 12 + state.emit(rvc(rv64::C_ANDI, Tmp1Reg + OffsetXC, 12)); + } + else { + //and x8, x{src}, 12 + state.emit(rvi(rv64::ANDI, Tmp1Reg, regR(isn.src), 12)); + } + //c.add x8, x3 + state.emit(rvc(rv64::C_ADD, Tmp1Reg, LiteralPoolReg)); + //c.lw x8, 64(x8) + state.emit(rvc(rv64::C_LW, Tmp1Reg + OffsetXC, 8 + Tmp1Reg + OffsetXC)); + //fsrm x8 + state.emit(rvi(rv64::FSRM, 0, Tmp1Reg, 0)); + } + + static void v1_ISTORE(HANDLER_ARGS) { + genAddressRegDst(state, isn); + //sd x{src}, 0(x9) + state.emit(rvi(rv64::SD, 0, Tmp2Reg, regR(isn.src))); + } + + static void v1_NOP(HANDLER_ARGS) { + } +} + +#include "instruction_weights.hpp" + +namespace { + +#define INST_HANDLE1(x) REPN(&randomx::v1_##x, WT(x)) +#define INST_HANDLE2(x) REPN(&randomx::v2_##x, WT(x)) + + InstructionHandler* opcodeMap1[256] = { + INST_HANDLE1(IADD_RS) + INST_HANDLE1(IADD_M) + INST_HANDLE1(ISUB_R) + INST_HANDLE1(ISUB_M) + INST_HANDLE1(IMUL_R) + INST_HANDLE1(IMUL_M) + INST_HANDLE1(IMULH_R) + INST_HANDLE1(IMULH_M) + INST_HANDLE1(ISMULH_R) + INST_HANDLE1(ISMULH_M) + INST_HANDLE1(IMUL_RCP) + INST_HANDLE1(INEG_R) + INST_HANDLE1(IXOR_R) + INST_HANDLE1(IXOR_M) + INST_HANDLE1(IROR_R) + INST_HANDLE1(IROL_R) + INST_HANDLE1(ISWAP_R) + INST_HANDLE1(FSWAP_R) + INST_HANDLE1(FADD_R) + INST_HANDLE1(FADD_M) + INST_HANDLE1(FSUB_R) + INST_HANDLE1(FSUB_M) + INST_HANDLE1(FSCAL_R) + INST_HANDLE1(FMUL_R) + INST_HANDLE1(FDIV_M) + INST_HANDLE1(FSQRT_R) + INST_HANDLE1(CBRANCH) + INST_HANDLE1(CFROUND) + INST_HANDLE1(ISTORE) + INST_HANDLE1(NOP) + }; +} \ No newline at end of file diff --git a/src/RandomX/src/jit_compiler_rv64.hpp b/src/RandomX/src/jit_compiler_rv64.hpp new file mode 100644 index 000000000..aaae57e36 --- /dev/null +++ b/src/RandomX/src/jit_compiler_rv64.hpp @@ -0,0 +1,69 @@ +/* +Copyright (c) 2023 tevador + +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of the copyright holder nor the + names of its contributors may be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#pragma once + +#include +#include +#include +#include "jit_compiler.hpp" + +namespace randomx { + + class Program; + struct ProgramConfiguration; + class SuperscalarProgram; + class Instruction; + + class JitCompilerRV64 { + public: + JitCompilerRV64(); + ~JitCompilerRV64(); + void generateProgram(Program&, ProgramConfiguration&); + void generateProgramLight(Program&, ProgramConfiguration&, uint32_t); + void generateSuperscalarHash(SuperscalarProgram programs[RANDOMX_CACHE_ACCESSES], std::vector&); + void generateDatasetInitCode() {} + ProgramFunc* getProgramFunc() { + return (ProgramFunc*)entryProgram; + } + DatasetInitFunc* getDatasetInitFunc() { + return (DatasetInitFunc*)entryDataInit; + } + uint8_t* getCode() { + return state.code; + } + size_t getCodeSize(); + void enableWriting(); + void enableExecution(); + void enableAll(); + private: + CompilerState state; + void* entryDataInit; + void* entryProgram; + }; +} diff --git a/src/RandomX/src/jit_compiler_rv64_static.S b/src/RandomX/src/jit_compiler_rv64_static.S new file mode 100644 index 000000000..240bbf5f4 --- /dev/null +++ b/src/RandomX/src/jit_compiler_rv64_static.S @@ -0,0 +1,1235 @@ +/* +Copyright (c) 2023 tevador + +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of the copyright holder nor the + names of its contributors may be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#define DECL(x) x + +.text +.option rvc + +#include "configuration.h" + +.global DECL(randomx_riscv64_literals) +.global DECL(randomx_riscv64_literals_end) +.global DECL(randomx_riscv64_data_init) +.global DECL(randomx_riscv64_fix_data_call) +.global DECL(randomx_riscv64_prologue) +.global DECL(randomx_riscv64_loop_begin) +.global DECL(randomx_riscv64_data_read) +.global DECL(randomx_riscv64_data_read_light) +.global DECL(randomx_riscv64_fix_loop_call) +.global DECL(randomx_riscv64_spad_store) +.global DECL(randomx_riscv64_spad_store_hardaes) +.global DECL(randomx_riscv64_spad_store_softaes) +.global DECL(randomx_riscv64_loop_end) +.global DECL(randomx_riscv64_fix_continue_loop) +.global DECL(randomx_riscv64_epilogue) +.global DECL(randomx_riscv64_softaes) +.global DECL(randomx_riscv64_program_end) +.global DECL(randomx_riscv64_ssh_init) +.global DECL(randomx_riscv64_ssh_load) +.global DECL(randomx_riscv64_ssh_prefetch) +.global DECL(randomx_riscv64_ssh_end) + +/* The literal pool can fit at most 494 IMUL_RCP literals */ +#if RANDOMX_PROGRAM_SIZE > 494 + #error RANDOMX_PROGRAM_SIZE larger than 494 is not supported. +#endif + +#define RANDOMX_CACHE_MASK (RANDOMX_ARGON_MEMORY*16-1) + +/* shared literal pool: 4 KB */ + /* space for 256 IMUL_RCP literals -2048 */ + /* filled by JIT compiler */ +DECL(randomx_riscv64_literals): +literal_pool: + /* SuperscalarHash constants +0 */ + .dword 6364136223846793005 + .dword 9298411001130361340 + .dword 12065312585734608966 + .dword 9306329213124626780 + .dword 5281919268842080866 + .dword 10536153434571861004 + .dword 3398623926847679864 + .dword 9549104520008361294 + /* CFROUND lookup table +64 */ + .word 0x00000000 /* RTN */ + .word 0x00000002 /* RDN */ + .word 0x00000003 /* RUP */ + .word 0x00000001 /* RTZ */ + /* mask literals +80,+84,+88,+92,+96,+104 */ + .word (RANDOMX_SCRATCHPAD_L1-8) + .word (RANDOMX_SCRATCHPAD_L2-8) + .word (RANDOMX_SCRATCHPAD_L3-64) + .word (RANDOMX_DATASET_BASE_SIZE-64) + .dword 0x80f0000000000000 + .dword 0x00ffffffffffffff +DECL(randomx_riscv64_literals_end): + /* E reg. set masks, +112,+120 */ + .dword 0 /* filled by JIT compiler */ + .dword 0 /* filled by JIT compiler */ + /* soft AES table addresses, +128,+136 */ + .dword 0 /* filled by JIT compiler */ + .dword 0 /* filled by JIT compiler */ + /* space for 238 IMUL_RCP literals, +144 */ + .fill 238,8,0 /* filled by JIT compiler */ + +/* ================================= */ +/* Dataset init function entry point */ +/* ================================= */ + +/* Register allocation: + ---------------------- + x0 -> zero + x1 -> temp/return address + x2 -> stack pointer (sp) + x3 -> literal pool pointer + x5 -> dataset pointer + x6 -> cache pointer + x7 -> temp/itemNumber + x8-x15 -> SuperscalarHash registers + x16 -> itemNumber + x17 -> endItem + x28-x31 -> temp + + Stack layout: + ------------------------ + sp+ + 0 -> return address + 8 -> saved x3 + 16 -> saved x8-x9 + 32 -> caller stack +*/ +DECL(randomx_riscv64_data_init): + addi sp, sp, -32 + /* dataset ptr */ + mv x5, x11 + /* cache->memory */ + ld x6, 0(x10) + /* callee saved registers */ + sd x1, 0(sp) + sd x3, 8(sp) + /* literal pool */ + lla x3, literal_pool + sd x8, 16(sp) + sd x9, 24(sp) + /* startItem */ + mv x16, x12 + /* endItem */ + mv x17, x13 +init_item: + mv x7, x16 +DECL(randomx_riscv64_fix_data_call): + jal superscalar_hash /* JIT compiler will adjust the offset */ + sd x8, 0(x5) + sd x9, 8(x5) + sd x10, 16(x5) + sd x11, 24(x5) + sd x12, 32(x5) + sd x13, 40(x5) + sd x14, 48(x5) + sd x15, 56(x5) + addi x5, x5, 64 + addi x16, x16, 1 + bltu x16, x17, init_item + ld x1, 0(sp) + ld x3, 8(sp) + ld x8, 16(sp) + ld x9, 24(sp) + addi sp, sp, 32 + ret + +/* ====================================== */ +/* Program execution function entry point */ +/* ====================================== */ + +/* Register allocation: + ---------------------- + x0 -> zero + x1 -> temp/scratchpad L3 mask + x2 -> stack pointer (sp) + x3 -> literal pool pointer + x5 -> scratchpad pointer + x6 -> dataset/cache pointer + x7 -> temp/next dataset access + x8 -> temp + x9 -> temp + x10 -> scratchpad L1 mask (0x0000000000003ff8) + x11 -> scratchpad L2 mask (0x000000000003fff8) + x12 -> FSCAL_R mask (0x80f0000000000000) + x13 -> E reg. clear mask (0x00ffffffffffffff) + x14 -> E reg. set mask (0x3*00000000******) + x15 -> E reg. set mask (0x3*00000000******) + x16-x23 -> VM registers "r0"-"r7" + x24 -> iteration counter "ic" + x25 -> VM registers "mx", "ma" + x26 -> spAddr0 + x27 -> spAddr1 + x28-x31 -> temp/literals for IMUL_RCP (4x) + + (Note: We avoid using x4 because it breaks debugging with gdb.) + + f0-f7 -> VM registers "f0"-"f3" + f8-f15 -> VM registers "e0"-"e3" + f16-f23 -> VM registers "a0"-"a3" + f24-f25 -> temp + f26-f31 -> literals for IMUL_RCP (6x) + + Stack layout: + ------------------------ + sp+ + 0 -> return address + 8 -> register file ptr + 16 -> saved x3-x4 + 32 -> saved x8-x9 + 48 -> saved x18-x27 + 128 -> saved f8-f9 + 144 -> saved f18-f27 + 224 -> caller stack +*/ + +DECL(randomx_riscv64_prologue): + addi sp, sp, -224 + /* scratchpad pointer */ + mv x5, x12 + /* register file pointer */ + sd x10, 8(sp) + /* callee saved registers */ + sd x3, 16(sp) + sd x8, 32(sp) + sd x9, 40(sp) + sd x18, 48(sp) + sd x19, 56(sp) + sd x20, 64(sp) + sd x21, 72(sp) + sd x22, 80(sp) + sd x23, 88(sp) + sd x24, 96(sp) + sd x25, 104(sp) + sd x26, 112(sp) + sd x27, 120(sp) + fsd f8, 128(sp) + fsd f9, 136(sp) + fsd f18, 144(sp) + fsd f19, 152(sp) + fsd f20, 160(sp) + fsd f21, 168(sp) + fsd f22, 176(sp) + fsd f23, 184(sp) + fsd f24, 192(sp) + fsd f25, 200(sp) + fsd f26, 208(sp) + fsd f27, 216(sp) + /* iteration counter */ + mv x24, x13 + /* return address */ + sd x1, 0(sp) + /* literal pool */ + lla x3, literal_pool + /* load (ma, mx) */ + ld x25, 0(x11) + /* dataset ptr */ + ld x6, 8(x11) + /* load dataset mask */ + lwu x1, 92(x3) + /* zero registers r0-r3, load a0-a1 */ + li x16, 0 + fld f16, 192(x10) + li x17, 0 + fld f17, 200(x10) + srli x7, x25, 32 /* x7 = ma */ + li x18, 0 + fld f18, 208(x10) + mv x27, x7 /* x27 = ma */ + li x19, 0 + fld f19, 216(x10) + /* set dataset read address */ + and x7, x7, x1 + add x7, x7, x6 + /* zero registers r4-r7, load a2-a3 */ + li x20, 0 + fld f20, 224(x10) + li x21, 0 + fld f21, 232(x10) + li x22, 0 + fld f22, 240(x10) + li x23, 0 + fld f23, 248(x10) + /* load L3 mask */ + lwu x1, 88(x3) + /* load scratchpad masks */ + lwu x10, 80(x3) + lwu x11, 84(x3) + /* set spAddr0, spAddr1 */ + and x26, x25, x1 + and x27, x27, x1 + add x26, x26, x5 + add x27, x27, x5 + /* align L3 mask */ + addi x1, x1, 56 + /* FSCAL, E reg. masks */ + ld x12, 96(x3) + ld x13, 104(x3) + ld x14, 112(x3) + ld x15, 120(x3) + /* IMUL_RCP literals */ + fld f26, 176(x3) + fld f27, 184(x3) + fld f28, 192(x3) + fld f29, 200(x3) + fld f30, 208(x3) + fld f31, 216(x3) + +.balign 4 +DECL(randomx_riscv64_loop_begin): +loop_begin: + /* mix integer registers */ + ld x8, 0(x26) + ld x9, 8(x26) + ld x30, 16(x26) + ld x31, 24(x26) + xor x16, x16, x8 + ld x8, 32(x26) + xor x17, x17, x9 + ld x9, 40(x26) + xor x18, x18, x30 + ld x30, 48(x26) + xor x19, x19, x31 + ld x31, 56(x26) + xor x20, x20, x8 + lw x8, 0(x27) + xor x21, x21, x9 + lw x9, 4(x27) + xor x22, x22, x30 + lw x30, 8(x27) + xor x23, x23, x31 + lw x31, 12(x27) + /* load F registers */ + fcvt.d.w f0, x8 + lw x8, 16(x27) + fcvt.d.w f1, x9 + lw x9, 20(x27) + fcvt.d.w f2, x30 + lw x30, 24(x27) + fcvt.d.w f3, x31 + lw x31, 28(x27) + fcvt.d.w f4, x8 + lw x8, 32(x27) + fcvt.d.w f5, x9 + lw x9, 36(x27) + fcvt.d.w f6, x30 + lw x30, 40(x27) + fcvt.d.w f7, x31 + lw x31, 44(x27) + /* load E registers */ + fcvt.d.w f8, x8 + lw x8, 48(x27) + fcvt.d.w f9, x9 + lw x9, 52(x27) + fcvt.d.w f10, x30 + lw x30, 56(x27) + fcvt.d.w f11, x31 + lw x31, 60(x27) + fcvt.d.w f12, x8 + fmv.x.d x8, f8 + fcvt.d.w f13, x9 + fmv.x.d x9, f9 + fcvt.d.w f14, x30 + fmv.x.d x30, f10 + fcvt.d.w f15, x31 + fmv.x.d x31, f11 + and x8, x8, x13 + and x9, x9, x13 + or x8, x8, x14 + or x9, x9, x15 + and x30, x30, x13 + and x31, x31, x13 + or x30, x30, x14 + or x31, x31, x15 + fmv.d.x f8, x8 + fmv.d.x f9, x9 + fmv.d.x f10, x30 + fmv.d.x f11, x31 + fmv.x.d x8, f12 + fmv.x.d x9, f13 + fmv.x.d x30, f14 + fmv.x.d x31, f15 + and x8, x8, x13 + and x9, x9, x13 + or x8, x8, x14 + or x9, x9, x15 + fmv.d.x f12, x8 + fmv.d.x f13, x9 + and x30, x30, x13 + and x31, x31, x13 + or x30, x30, x14 + or x31, x31, x15 + fmv.d.x f14, x30 + fmv.d.x f15, x31 + /* reload clobbered IMUL_RCP regs */ + ld x28, 144(x3) + ld x29, 152(x3) + ld x30, 160(x3) + ld x31, 168(x3) + +DECL(randomx_riscv64_data_read): + xor x8, x20, x22 /* JIT compiler will adjust the registers */ + /* load dataset mask */ + lwu x1, 92(x3) + /* zero-extend x8 */ +#ifdef __riscv_zba + zext.w x8, x8 +#else + slli x8, x8, 32 + srli x8, x8, 32 +#endif + /* update "mx" */ + xor x25, x25, x8 + /* read dataset and update registers */ + ld x8, 0(x7) + ld x9, 8(x7) + ld x30, 16(x7) + ld x31, 24(x7) + xor x16, x16, x8 + ld x8, 32(x7) + xor x17, x17, x9 + ld x9, 40(x7) + xor x18, x18, x30 + ld x30, 48(x7) + xor x19, x19, x31 + ld x31, 56(x7) + xor x20, x20, x8 + /* calculate the next dataset address */ + and x7, x25, x1 + xor x21, x21, x9 + add x7, x7, x6 + xor x22, x22, x30 + /* prefetch - doesn't seem to have any effect */ + /* ld x0, 0(x7) */ + xor x23, x23, x31 + /* swap mx <-> ma */ +#ifdef __riscv_zbb + rori x25, x25, 32 +#else + srli x9, x25, 32 + slli x25, x25, 32 + or x25, x25, x9 +#endif + +DECL(randomx_riscv64_data_read_light): + xor x8, x20, x22 /* JIT compiler will adjust the registers */ + /* load dataset offset */ + lui x9, 0x02000 /* JIT compiler will adjust the immediate */ + addi x9, x9, -64 + /* load dataset mask */ + lwu x1, 92(x3) + /* swap mx <-> ma */ +#ifdef __riscv_zbb + rori x25, x25, 32 +#else + srli x31, x25, 32 + slli x25, x25, 32 + or x25, x25, x31 +#endif + slli x8, x8, 32 + /* update "mx" */ + xor x25, x25, x8 + /* the next dataset item */ + and x7, x25, x1 + srli x7, x7, 6 + add x7, x7, x9 +DECL(randomx_riscv64_fix_loop_call): + jal superscalar_hash /* JIT compiler will adjust the offset */ + xor x16, x16, x8 + xor x17, x17, x9 + xor x18, x18, x10 + xor x19, x19, x11 + xor x20, x20, x12 + xor x21, x21, x13 + xor x22, x22, x14 + xor x23, x23, x15 + /* restore clobbered registers */ + lwu x10, 80(x3) + lwu x11, 84(x3) + ld x12, 96(x3) + ld x13, 104(x3) + ld x14, 112(x3) + ld x15, 120(x3) + +DECL(randomx_riscv64_spad_store): + /* store integer registers */ + sd x16, 0(x27) + sd x17, 8(x27) + sd x18, 16(x27) + sd x19, 24(x27) + sd x20, 32(x27) + sd x21, 40(x27) + sd x22, 48(x27) + sd x23, 56(x27) + /* XOR and store f0,e0 */ + fmv.x.d x8, f0 + fmv.x.d x9, f8 + fmv.x.d x30, f1 + fmv.x.d x31, f9 + xor x8, x8, x9 + xor x30, x30, x31 + sd x8, 0(x26) + fmv.d.x f0, x8 + sd x30, 8(x26) + fmv.d.x f1, x30 + /* XOR and store f1,e1 */ + fmv.x.d x8, f2 + fmv.x.d x9, f10 + fmv.x.d x30, f3 + fmv.x.d x31, f11 + xor x8, x8, x9 + xor x30, x30, x31 + sd x8, 16(x26) + fmv.d.x f2, x8 + sd x30, 24(x26) + fmv.d.x f3, x30 + /* XOR and store f2,e2 */ + fmv.x.d x8, f4 + fmv.x.d x9, f12 + fmv.x.d x30, f5 + fmv.x.d x31, f13 + xor x8, x8, x9 + xor x30, x30, x31 + sd x8, 32(x26) + fmv.d.x f4, x8 + sd x30, 40(x26) + fmv.d.x f5, x30 + /* XOR and store f3,e3 */ + fmv.x.d x8, f6 + fmv.x.d x9, f14 + fmv.x.d x30, f7 + fmv.x.d x31, f15 + xor x8, x8, x9 + xor x30, x30, x31 + sd x8, 48(x26) + fmv.d.x f6, x8 + sd x30, 56(x26) + fmv.d.x f7, x30 + +DECL(randomx_riscv64_spad_store_hardaes): + nop /* not implemented */ + +DECL(randomx_riscv64_spad_store_softaes): + /* store integer registers */ + sd x16, 0(x27) + sd x17, 8(x27) + sd x18, 16(x27) + sd x19, 24(x27) + sd x20, 32(x27) + sd x21, 40(x27) + sd x22, 48(x27) + sd x23, 56(x27) + /* process f0 with 4 AES rounds */ + fmv.x.d x8, f8 + fmv.x.d x10, f9 + fmv.x.d x30, f0 + fmv.x.d x31, f1 + jal softaes_enc + fmv.x.d x8, f10 + fmv.x.d x10, f11 + jal softaes_enc + fmv.x.d x8, f12 + fmv.x.d x10, f13 + jal softaes_enc + fmv.x.d x8, f14 + fmv.x.d x10, f15 + jal softaes_enc + sd x30, 0(x26) + fmv.d.x f0, x30 + sd x31, 8(x26) + fmv.d.x f1, x31 + /* process f1 with 4 AES rounds */ + fmv.x.d x8, f8 + fmv.x.d x10, f9 + fmv.x.d x30, f2 + fmv.x.d x31, f3 + jal softaes_dec + fmv.x.d x8, f10 + fmv.x.d x10, f11 + jal softaes_dec + fmv.x.d x8, f12 + fmv.x.d x10, f13 + jal softaes_dec + fmv.x.d x8, f14 + fmv.x.d x10, f15 + jal softaes_dec + sd x30, 16(x26) + fmv.d.x f2, x30 + sd x31, 24(x26) + fmv.d.x f3, x31 + /* process f2 with 4 AES rounds */ + fmv.x.d x8, f8 + fmv.x.d x10, f9 + fmv.x.d x30, f4 + fmv.x.d x31, f5 + jal softaes_enc + fmv.x.d x8, f10 + fmv.x.d x10, f11 + jal softaes_enc + fmv.x.d x8, f12 + fmv.x.d x10, f13 + jal softaes_enc + fmv.x.d x8, f14 + fmv.x.d x10, f15 + jal softaes_enc + sd x30, 32(x26) + fmv.d.x f4, x30 + sd x31, 40(x26) + fmv.d.x f5, x31 + /* process f3 with 4 AES rounds */ + fmv.x.d x8, f8 + fmv.x.d x10, f9 + fmv.x.d x30, f6 + fmv.x.d x31, f7 + jal softaes_dec + fmv.x.d x8, f10 + fmv.x.d x10, f11 + jal softaes_dec + fmv.x.d x8, f12 + fmv.x.d x10, f13 + jal softaes_dec + fmv.x.d x8, f14 + fmv.x.d x10, f15 + jal softaes_dec + sd x30, 48(x26) + fmv.d.x f6, x30 + sd x31, 56(x26) + fmv.d.x f7, x31 + /* restore clobbered registers */ + lwu x10, 80(x3) + lwu x11, 84(x3) + ld x12, 96(x3) + ld x13, 104(x3) + ld x14, 112(x3) + ld x15, 120(x3) + +DECL(randomx_riscv64_loop_end): + xor x26, x16, x18 /* JIT compiler will adjust the registers */ + /* load L3 mask */ + lwu x1, 88(x3) + addi x24, x24, -1 + srli x27, x26, 32 + /* set spAddr0, spAddr1 */ + and x26, x26, x1 + and x27, x27, x1 + add x26, x26, x5 + add x27, x27, x5 + /* align L3 mask */ + addi x1, x1, 56 + /* conditional branch doesn't have sufficient range */ + j condition_check +DECL(randomx_riscv64_fix_continue_loop): +continue_loop: + .word 0 /* JIT compiler will write a jump to loop_begin */ +condition_check: + bnez x24, continue_loop + +DECL(randomx_riscv64_epilogue): + /* restore callee saved registers */ + ld x10, 8(sp) + ld x1, 0(sp) + ld x3, 16(sp) + ld x8, 32(sp) + ld x9, 40(sp) + ld x24, 96(sp) + ld x25, 104(sp) + ld x26, 112(sp) + ld x27, 120(sp) + fld f18, 144(sp) + fld f19, 152(sp) + fld f20, 160(sp) + fld f21, 168(sp) + fld f22, 176(sp) + fld f23, 184(sp) + fld f24, 192(sp) + fld f25, 200(sp) + fld f26, 208(sp) + fld f27, 216(sp) + /* save VM registers */ + sd x16, 0(x10) + sd x17, 8(x10) + sd x18, 16(x10) + sd x19, 24(x10) + sd x20, 32(x10) + sd x21, 40(x10) + sd x22, 48(x10) + sd x23, 56(x10) + fsd f0, 64(x10) + fsd f1, 72(x10) + fsd f2, 80(x10) + fsd f3, 88(x10) + fsd f4, 96(x10) + fsd f5, 104(x10) + fsd f6, 112(x10) + fsd f7, 120(x10) + fsd f8, 128(x10) + fsd f9, 136(x10) + fsd f10, 144(x10) + fsd f11, 152(x10) + fsd f12, 160(x10) + fsd f13, 168(x10) + fsd f14, 176(x10) + fsd f15, 184(x10) + /* restore callee saved registers */ + ld x18, 48(sp) + ld x19, 56(sp) + ld x20, 64(sp) + ld x21, 72(sp) + ld x22, 80(sp) + ld x23, 88(sp) + fld f8, 128(sp) + fld f9, 136(sp) + /* restore stack pointer */ + addi sp, sp, 224 + /* return */ + ret + +/* + Soft AES subroutines + in: + x3 = literal pool + x8, x10 = round key + x30, x31 = plaintext + out: + x30, x31 = ciphertext + clobbers: + x8-x11 (limbs) + x12-x13 (LUTs) + x14-x15 (temp) +*/ +DECL(randomx_riscv64_softaes): +softaes_enc: + /* enc. lookup table */ + ld x13, 128(x3) + + /* load the round key into x8, x9, x10, x11 */ + srli x9, x8, 32 + srli x11, x10, 32 +#ifdef __riscv_zba + zext.w x8, x8 + zext.w x10, x10 +#else + slli x8, x8, 32 + slli x10, x10, 32 + srli x8, x8, 32 + srli x10, x10, 32 +#endif + + /* byte 0 */ + andi x14, x30, 255 + srli x30, x30, 8 + addi x12, x13, -2048 +#ifdef __riscv_zba + sh2add x14, x14, x13 +#else + slli x14, x14, 2 + add x14, x14, x13 +#endif + lwu x14, -2048(x14) + + /* byte 1 */ + andi x15, x30, 255 + srli x30, x30, 8 +#ifdef __riscv_zba + sh2add x15, x15, x12 +#else + slli x15, x15, 2 + add x15, x15, x12 +#endif + lwu x15, 1024(x15) + xor x8, x8, x14 + + /* byte 2 */ + andi x14, x30, 255 + srli x30, x30, 8 +#ifdef __riscv_zba + sh2add x14, x14, x13 +#else + slli x14, x14, 2 + add x14, x14, x13 +#endif + lwu x14, 0(x14) + xor x11, x11, x15 + + /* byte 3 */ + andi x15, x30, 255 + srli x30, x30, 8 +#ifdef __riscv_zba + sh2add x15, x15, x13 +#else + slli x15, x15, 2 + add x15, x15, x13 +#endif + lwu x15, 1024(x15) + xor x10, x10, x14 + + /* byte 4 */ + andi x14, x30, 255 + srli x30, x30, 8 +#ifdef __riscv_zba + sh2add x14, x14, x12 +#else + slli x14, x14, 2 + add x14, x14, x12 +#endif + lwu x14, 0(x14) + xor x9, x9, x15 + + /* byte 5 */ + andi x15, x30, 255 + srli x30, x30, 8 +#ifdef __riscv_zba + sh2add x15, x15, x12 +#else + slli x15, x15, 2 + add x15, x15, x12 +#endif + lwu x15, 1024(x15) + xor x9, x9, x14 + + /* byte 6 */ + andi x14, x30, 255 + srli x30, x30, 8 +#ifdef __riscv_zba + sh2add x14, x14, x13 +#else + slli x14, x14, 2 + add x14, x14, x13 +#endif + lwu x14, 0(x14) + xor x8, x8, x15 + + /* byte 7 */ + andi x15, x30, 255 +#ifdef __riscv_zba + sh2add x15, x15, x13 +#else + slli x15, x15, 2 + add x15, x15, x13 +#endif + lwu x15, 1024(x15) + xor x11, x11, x14 + + /* byte 8 */ + andi x14, x31, 255 + srli x31, x31, 8 +#ifdef __riscv_zba + sh2add x14, x14, x12 +#else + slli x14, x14, 2 + add x14, x14, x12 +#endif + lwu x14, 0(x14) + xor x10, x10, x15 + + /* byte 9 */ + andi x15, x31, 255 + srli x31, x31, 8 +#ifdef __riscv_zba + sh2add x15, x15, x12 +#else + slli x15, x15, 2 + add x15, x15, x12 +#endif + lwu x15, 1024(x15) + xor x10, x10, x14 + + /* byte 10 */ + andi x14, x31, 255 + srli x31, x31, 8 +#ifdef __riscv_zba + sh2add x14, x14, x13 +#else + slli x14, x14, 2 + add x14, x14, x13 +#endif + lwu x14, 0(x14) + xor x9, x9, x15 + + /* byte 11 */ + andi x15, x31, 255 + srli x31, x31, 8 +#ifdef __riscv_zba + sh2add x15, x15, x13 +#else + slli x15, x15, 2 + add x15, x15, x13 +#endif + lwu x15, 1024(x15) + xor x8, x8, x14 + + /* byte 12 */ + andi x14, x31, 255 + srli x31, x31, 8 +#ifdef __riscv_zba + sh2add x14, x14, x12 +#else + slli x14, x14, 2 + add x14, x14, x12 +#endif + lwu x14, 0(x14) + xor x11, x11, x15 + + /* byte 13 */ + andi x15, x31, 255 + srli x31, x31, 8 +#ifdef __riscv_zba + sh2add x15, x15, x12 +#else + slli x15, x15, 2 + add x15, x15, x12 +#endif + lwu x15, 1024(x15) + xor x11, x11, x14 + + /* byte 14 */ + andi x14, x31, 255 + srli x31, x31, 8 +#ifdef __riscv_zba + sh2add x14, x14, x13 +#else + slli x14, x14, 2 + add x14, x14, x13 +#endif + lwu x14, 0(x14) + xor x10, x10, x15 + + /* byte 15 */ + andi x15, x31, 255 +#ifdef __riscv_zba + sh2add x15, x15, x13 +#else + slli x15, x15, 2 + add x15, x15, x13 +#endif + lwu x15, 1024(x15) + xor x9, x9, x14 + + slli x11, x11, 32 + slli x9, x9, 32 + or x30, x8, x9 + or x31, x10, x11 + xor x30, x30, x15 + + ret + +softaes_dec: + /* dec. lookup table */ + ld x13, 136(x3) + + /* load the round key into x8, x9, x10, x11 */ + srli x9, x8, 32 + srli x11, x10, 32 +#ifdef __riscv_zba + zext.w x8, x8 + zext.w x10, x10 +#else + slli x8, x8, 32 + slli x10, x10, 32 + srli x8, x8, 32 + srli x10, x10, 32 +#endif + + /* byte 0 */ + andi x14, x30, 255 + srli x30, x30, 8 + addi x12, x13, -2048 +#ifdef __riscv_zba + sh2add x14, x14, x13 +#else + slli x14, x14, 2 + add x14, x14, x13 +#endif + lwu x14, -2048(x14) + + /* byte 1 */ + andi x15, x30, 255 + srli x30, x30, 8 +#ifdef __riscv_zba + sh2add x15, x15, x12 +#else + slli x15, x15, 2 + add x15, x15, x12 +#endif + lwu x15, 1024(x15) + xor x8, x8, x14 + + /* byte 2 */ + andi x14, x30, 255 + srli x30, x30, 8 +#ifdef __riscv_zba + sh2add x14, x14, x13 +#else + slli x14, x14, 2 + add x14, x14, x13 +#endif + lwu x14, 0(x14) + xor x9, x9, x15 + + /* byte 3 */ + andi x15, x30, 255 + srli x30, x30, 8 +#ifdef __riscv_zba + sh2add x15, x15, x13 +#else + slli x15, x15, 2 + add x15, x15, x13 +#endif + lwu x15, 1024(x15) + xor x10, x10, x14 + + /* byte 4 */ + andi x14, x30, 255 + srli x30, x30, 8 +#ifdef __riscv_zba + sh2add x14, x14, x12 +#else + slli x14, x14, 2 + add x14, x14, x12 +#endif + lwu x14, 0(x14) + xor x11, x11, x15 + + /* byte 5 */ + andi x15, x30, 255 + srli x30, x30, 8 +#ifdef __riscv_zba + sh2add x15, x15, x12 +#else + slli x15, x15, 2 + add x15, x15, x12 +#endif + lwu x15, 1024(x15) + xor x9, x9, x14 + + /* byte 6 */ + andi x14, x30, 255 + srli x30, x30, 8 +#ifdef __riscv_zba + sh2add x14, x14, x13 +#else + slli x14, x14, 2 + add x14, x14, x13 +#endif + lwu x14, 0(x14) + xor x10, x10, x15 + + /* byte 7 */ + andi x15, x30, 255 +#ifdef __riscv_zba + sh2add x15, x15, x13 +#else + slli x15, x15, 2 + add x15, x15, x13 +#endif + lwu x15, 1024(x15) + xor x11, x11, x14 + + /* byte 8 */ + andi x14, x31, 255 + srli x31, x31, 8 +#ifdef __riscv_zba + sh2add x14, x14, x12 +#else + slli x14, x14, 2 + add x14, x14, x12 +#endif + lwu x14, 0(x14) + xor x8, x8, x15 + + /* byte 9 */ + andi x15, x31, 255 + srli x31, x31, 8 +#ifdef __riscv_zba + sh2add x15, x15, x12 +#else + slli x15, x15, 2 + add x15, x15, x12 +#endif + lwu x15, 1024(x15) + xor x10, x10, x14 + + /* byte 10 */ + andi x14, x31, 255 + srli x31, x31, 8 +#ifdef __riscv_zba + sh2add x14, x14, x13 +#else + slli x14, x14, 2 + add x14, x14, x13 +#endif + lwu x14, 0(x14) + xor x11, x11, x15 + + /* byte 11 */ + andi x15, x31, 255 + srli x31, x31, 8 +#ifdef __riscv_zba + sh2add x15, x15, x13 +#else + slli x15, x15, 2 + add x15, x15, x13 +#endif + lwu x15, 1024(x15) + xor x8, x8, x14 + + /* byte 12 */ + andi x14, x31, 255 + srli x31, x31, 8 +#ifdef __riscv_zba + sh2add x14, x14, x12 +#else + slli x14, x14, 2 + add x14, x14, x12 +#endif + lwu x14, 0(x14) + xor x9, x9, x15 + + /* byte 13 */ + andi x15, x31, 255 + srli x31, x31, 8 +#ifdef __riscv_zba + sh2add x15, x15, x12 +#else + slli x15, x15, 2 + add x15, x15, x12 +#endif + lwu x15, 1024(x15) + xor x11, x11, x14 + + /* byte 14 */ + andi x14, x31, 255 + srli x31, x31, 8 +#ifdef __riscv_zba + sh2add x14, x14, x13 +#else + slli x14, x14, 2 + add x14, x14, x13 +#endif + lwu x14, 0(x14) + xor x8, x8, x15 + + /* byte 15 */ + andi x15, x31, 255 +#ifdef __riscv_zba + sh2add x15, x15, x13 +#else + slli x15, x15, 2 + add x15, x15, x13 +#endif + lwu x15, 1024(x15) + xor x9, x9, x14 + + slli x11, x11, 32 + slli x9, x9, 32 + or x30, x8, x9 + or x31, x10, x11 + xor x31, x31, x15 + + ret + +DECL(randomx_riscv64_program_end): + nop + + +/* literal pool for SuperscalarHash */ + /* space for remaining IMUL_RCP literals */ +ssh_literal_pool: + /* space for 256 IMUL_RCP literals */ + .fill 256,8,0 + +/* + SuperscalarHash subroutine + in: + x3 = literal pool + x6 = cache + x7 = itemNumber + out: + x8-x15 = 64-byte hash + clobbers: + x7, x28-x31 +*/ +DECL(randomx_riscv64_ssh_init): +superscalar_hash: + ld x30, 0(x3) /* superscalarMul0 */ + addi x8, x7, 1 + ld x9, 8(x3) + li x31, RANDOMX_CACHE_MASK + ld x10, 16(x3) + ld x11, 24(x3) + mul x8, x8, x30 + ld x12, 32(x3) + ld x13, 40(x3) + lla x30, ssh_literal_pool + ld x14, 48(x3) + and x7, x7, x31 + ld x15, 56(x3) + slli x7, x7, 6 + xor x9, x9, x8 + add x7, x7, x6 + xor x10, x10, x8 + /* load the first IMUL_RCP literal */ + ld x31, 2040(x30) + xor x11, x11, x8 + xor x12, x12, x8 + xor x13, x13, x8 + xor x14, x14, x8 + xor x15, x15, x8 + +DECL(randomx_riscv64_ssh_load): + ld x28, 0(x7) + ld x29, 8(x7) + xor x8, x8, x28 + ld x28, 16(x7) + xor x9, x9, x29 + ld x29, 24(x7) + xor x10, x10, x28 + ld x28, 32(x7) + xor x11, x11, x29 + ld x29, 40(x7) + xor x12, x12, x28 + ld x28, 48(x7) + xor x13, x13, x29 + ld x29, 56(x7) + xor x14, x14, x28 + li x7, RANDOMX_CACHE_MASK + xor x15, x15, x29 + +DECL(randomx_riscv64_ssh_prefetch): + and x7, x8, x7 /* JIT compiler will adjust the register */ + slli x7, x7, 6 + add x7, x7, x6 + /* prefetch - doesn't seem to have any effect */ + /* ld x0, 0(x7) */ + +DECL(randomx_riscv64_ssh_end): + nop diff --git a/src/RandomX/src/jit_compiler_rv64_static.hpp b/src/RandomX/src/jit_compiler_rv64_static.hpp new file mode 100644 index 000000000..656623c74 --- /dev/null +++ b/src/RandomX/src/jit_compiler_rv64_static.hpp @@ -0,0 +1,53 @@ +/* +Copyright (c) 2023 tevador + +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of the copyright holder nor the + names of its contributors may be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#pragma once + +extern "C" { + void randomx_riscv64_literals(); + void randomx_riscv64_literals_end(); + void randomx_riscv64_data_init(); + void randomx_riscv64_fix_data_call(); + void randomx_riscv64_prologue(); + void randomx_riscv64_loop_begin(); + void randomx_riscv64_data_read(); + void randomx_riscv64_data_read_light(); + void randomx_riscv64_fix_loop_call(); + void randomx_riscv64_spad_store(); + void randomx_riscv64_spad_store_hardaes(); + void randomx_riscv64_spad_store_softaes(); + void randomx_riscv64_loop_end(); + void randomx_riscv64_fix_continue_loop(); + void randomx_riscv64_epilogue(); + void randomx_riscv64_softaes(); + void randomx_riscv64_program_end(); + void randomx_riscv64_ssh_init(); + void randomx_riscv64_ssh_load(); + void randomx_riscv64_ssh_prefetch(); + void randomx_riscv64_ssh_end(); +} diff --git a/src/RandomX/src/jit_compiler_x86.cpp b/src/RandomX/src/jit_compiler_x86.cpp index 5587e6afb..785ce5f59 100644 --- a/src/RandomX/src/jit_compiler_x86.cpp +++ b/src/RandomX/src/jit_compiler_x86.cpp @@ -34,7 +34,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "superscalar.hpp" #include "program.hpp" #include "reciprocal.h" -#include "virtual_memory.hpp" +#include "virtual_memory.h" namespace randomx { /* @@ -618,7 +618,7 @@ namespace randomx { } void JitCompilerX86::h_IMUL_RCP(Instruction& instr, int i) { - uint64_t divisor = instr.getImm32(); + const uint32_t divisor = instr.getImm32(); if (!isZeroOrPowerOf2(divisor)) { registerUsage[instr.dst] = i; emit(MOV_RAX_I); diff --git a/src/RandomX/src/randomx.cpp b/src/RandomX/src/randomx.cpp index 7daaa46df..a08968e6a 100644 --- a/src/RandomX/src/randomx.cpp +++ b/src/RandomX/src/randomx.cpp @@ -36,7 +36,13 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "cpu.hpp" #include #include + +#if defined(__SSE__) || defined(__SSE2__) || (defined(_M_IX86_FP) && (_M_IX86_FP > 0)) +#define USE_CSR_INTRINSICS +#include +#else #include +#endif extern "C" { @@ -356,8 +362,14 @@ extern "C" { assert(machine != nullptr); assert(inputSize == 0 || input != nullptr); assert(output != nullptr); + +#ifdef USE_CSR_INTRINSICS + const unsigned int fpstate = _mm_getcsr(); +#else fenv_t fpstate; fegetenv(&fpstate); +#endif + alignas(16) uint64_t tempHash[8]; int blakeResult = blake2b(tempHash, sizeof(tempHash), input, inputSize, nullptr, 0); assert(blakeResult == 0); @@ -370,7 +382,12 @@ extern "C" { } machine->run(&tempHash); machine->getFinalResult(output, RANDOMX_HASH_SIZE); + +#ifdef USE_CSR_INTRINSICS + _mm_setcsr(fpstate); +#else fesetenv(&fpstate); +#endif } void randomx_calculate_hash_first(randomx_vm* machine, const void* input, size_t inputSize) { @@ -400,4 +417,15 @@ extern "C" { machine->run(machine->tempHash); machine->getFinalResult(output, RANDOMX_HASH_SIZE); } + + void randomx_calculate_commitment(const void* input, size_t inputSize, const void* hash_in, void* com_out) { + assert(inputSize == 0 || input != nullptr); + assert(hash_in != nullptr); + assert(com_out != nullptr); + blake2b_state state; + blake2b_init(&state, RANDOMX_HASH_SIZE); + blake2b_update(&state, input, inputSize); + blake2b_update(&state, hash_in, RANDOMX_HASH_SIZE); + blake2b_final(&state, com_out, RANDOMX_HASH_SIZE); + } } diff --git a/src/RandomX/src/randomx.h b/src/RandomX/src/randomx.h index 64d18068b..313bcd2e0 100644 --- a/src/RandomX/src/randomx.h +++ b/src/RandomX/src/randomx.h @@ -260,6 +260,17 @@ RANDOMX_EXPORT void randomx_calculate_hash_first(randomx_vm* machine, const void RANDOMX_EXPORT void randomx_calculate_hash_next(randomx_vm* machine, const void* nextInput, size_t nextInputSize, void* output); RANDOMX_EXPORT void randomx_calculate_hash_last(randomx_vm* machine, void* output); +/** + * Calculate a RandomX commitment from a RandomX hash and its input. + * + * @param input is a pointer to memory that was hashed. Must not be NULL. + * @param inputSize is the number of bytes in the input. + * @param hash_in is the output from randomx_calculate_hash* (RANDOMX_HASH_SIZE bytes). + * @param com_out is a pointer to memory where the commitment will be stored. Must not + * be NULL and at least RANDOMX_HASH_SIZE bytes must be available for writing. +*/ +RANDOMX_EXPORT void randomx_calculate_commitment(const void* input, size_t inputSize, const void* hash_in, void* com_out); + #if defined(__cplusplus) } #endif diff --git a/src/RandomX/src/reciprocal.c b/src/RandomX/src/reciprocal.c index 22620f53a..074d1846b 100644 --- a/src/RandomX/src/reciprocal.c +++ b/src/RandomX/src/reciprocal.c @@ -44,36 +44,28 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ret */ -uint64_t randomx_reciprocal(uint64_t divisor) { +uint64_t randomx_reciprocal(uint32_t divisor) { assert(divisor != 0); const uint64_t p2exp63 = 1ULL << 63; + const uint64_t q = p2exp63 / divisor; + const uint64_t r = p2exp63 % divisor; + +#ifdef __GNUC__ + const uint32_t shift = 64 - __builtin_clzll(divisor); +#else + uint32_t shift = 32; + for (uint32_t k = 1U << 31; (k & divisor) == 0; k >>= 1) + --shift; +#endif - uint64_t quotient = p2exp63 / divisor, remainder = p2exp63 % divisor; - - unsigned bsr = 0; //highest set bit in divisor - - for (uint64_t bit = divisor; bit > 0; bit >>= 1) - bsr++; - - for (unsigned shift = 0; shift < bsr; shift++) { - if (remainder >= divisor - remainder) { - quotient = quotient * 2 + 1; - remainder = remainder * 2 - divisor; - } - else { - quotient = quotient * 2; - remainder = remainder * 2; - } - } - - return quotient; + return (q << shift) + ((r << shift) / divisor); } #if !RANDOMX_HAVE_FAST_RECIPROCAL -uint64_t randomx_reciprocal_fast(uint64_t divisor) { +uint64_t randomx_reciprocal_fast(uint32_t divisor) { return randomx_reciprocal(divisor); } diff --git a/src/RandomX/src/reciprocal.h b/src/RandomX/src/reciprocal.h index 8858df2b8..90bd9b6be 100644 --- a/src/RandomX/src/reciprocal.h +++ b/src/RandomX/src/reciprocal.h @@ -40,8 +40,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. extern "C" { #endif -uint64_t randomx_reciprocal(uint64_t); -uint64_t randomx_reciprocal_fast(uint64_t); +uint64_t randomx_reciprocal(uint32_t); +uint64_t randomx_reciprocal_fast(uint32_t); #if defined(__cplusplus) } diff --git a/src/RandomX/src/tests/benchmark.cpp b/src/RandomX/src/tests/benchmark.cpp index 36b0259b6..148521a51 100644 --- a/src/RandomX/src/tests/benchmark.cpp +++ b/src/RandomX/src/tests/benchmark.cpp @@ -96,6 +96,7 @@ void printUsage(const char* executable) { std::cout << " --avx2 use optimized Argon2 for AVX2 CPUs" << std::endl; std::cout << " --auto select the best options for the current CPU" << std::endl; std::cout << " --noBatch calculate hashes one by one (default: batch)" << std::endl; + std::cout << " --commit calculate commitments instead of hashes (default: hashes)" << std::endl; } struct MemoryException : public std::exception { @@ -113,7 +114,7 @@ struct DatasetAllocException : public MemoryException { using MineFunc = void(randomx_vm * vm, std::atomic & atomicNonce, AtomicHash & result, uint32_t noncesCount, int thread, int cpuid); -template +template void mine(randomx_vm* vm, std::atomic& atomicNonce, AtomicHash& result, uint32_t noncesCount, int thread, int cpuid = -1) { if (cpuid >= 0) { int rc = set_thread_affinity(cpuid); @@ -138,6 +139,9 @@ void mine(randomx_vm* vm, std::atomic& atomicNonce, AtomicHash& result } store32(noncePtr, nonce); (batch ? randomx_calculate_hash_next : randomx_calculate_hash)(vm, blockTemplate, sizeof(blockTemplate), &hash); + if (commit) { + randomx_calculate_commitment(blockTemplate, sizeof(blockTemplate), &hash, &hash); + } result.xorWith(hash); if (!batch) { nonce = atomicNonce.fetch_add(1); @@ -146,7 +150,7 @@ void mine(randomx_vm* vm, std::atomic& atomicNonce, AtomicHash& result } int main(int argc, char** argv) { - bool softAes, miningMode, verificationMode, help, largePages, jit, secure; + bool softAes, miningMode, verificationMode, help, largePages, jit, secure, commit; bool ssse3, avx2, autoFlags, noBatch; int noncesCount, threadCount, initThreadCount; uint64_t threadAffinity; @@ -172,10 +176,11 @@ int main(int argc, char** argv) { readOption("--avx2", argc, argv, avx2); readOption("--auto", argc, argv, autoFlags); readOption("--noBatch", argc, argv, noBatch); + readOption("--commit", argc, argv, commit); store32(&seed, seedValue); - std::cout << "RandomX benchmark v1.1.11" << std::endl; + std::cout << "RandomX benchmark v1.2.1" << std::endl; if (help) { printUsage(argv[0]); @@ -280,11 +285,24 @@ int main(int argc, char** argv) { MineFunc* func; if (noBatch) { - func = &mine; + if (commit) { + std::cout << " - hash commitments" << std::endl; + func = &mine; + } + else { + func = &mine; + } } else { - func = &mine; - std::cout << " - batch mode" << std::endl; + if (commit) { + //TODO: support batch mode with commitments + std::cout << " - hash commitments" << std::endl; + func = &mine; + } + else { + std::cout << " - batch mode" << std::endl; + func = &mine; + } } std::cout << "Initializing"; @@ -376,7 +394,7 @@ int main(int argc, char** argv) { randomx_release_cache(cache); std::cout << "Calculated result: "; result.print(std::cout); - if (noncesCount == 1000 && seedValue == 0) + if (noncesCount == 1000 && seedValue == 0 && !commit) std::cout << "Reference result: 10b649a3f15c7c7f88277812f2e74b337a0f20ce909af09199cccb960771cfa1" << std::endl; if (!miningMode) { std::cout << "Performance: " << 1000 * elapsed / noncesCount << " ms per hash" << std::endl; diff --git a/src/RandomX/src/tests/perf-simulation.cpp b/src/RandomX/src/tests/perf-simulation.cpp index 1068a40ef..27f34d8c4 100644 --- a/src/RandomX/src/tests/perf-simulation.cpp +++ b/src/RandomX/src/tests/perf-simulation.cpp @@ -477,7 +477,7 @@ int analyze(randomx::Program& p) { } if (opcode < randomx::ceil_IMUL_RCP) { - uint64_t divisor = instr.getImm32(); + const uint32_t divisor = instr.getImm32(); if (!randomx::isZeroOrPowerOf2(divisor)) { instr.dst = instr.dst % randomx::RegistersCount; instr.opcode |= DST_INT; diff --git a/src/RandomX/src/tests/riscv64_zba.s b/src/RandomX/src/tests/riscv64_zba.s new file mode 100644 index 000000000..e1947e7a6 --- /dev/null +++ b/src/RandomX/src/tests/riscv64_zba.s @@ -0,0 +1,9 @@ +/* RISC-V - test if the Zba extension is present */ + +.text +.global main + +main: + sh1add x6, x6, x7 + li x10, 0 + ret diff --git a/src/RandomX/src/tests/riscv64_zbb.s b/src/RandomX/src/tests/riscv64_zbb.s new file mode 100644 index 000000000..d922043f0 --- /dev/null +++ b/src/RandomX/src/tests/riscv64_zbb.s @@ -0,0 +1,9 @@ +/* RISC-V - test if the Zbb extension is present */ + +.text +.global main + +main: + ror x6, x6, x7 + li x10, 0 + ret diff --git a/src/RandomX/src/tests/tests.cpp b/src/RandomX/src/tests/tests.cpp index 412585b1d..5e1b41a38 100644 --- a/src/RandomX/src/tests/tests.cpp +++ b/src/RandomX/src/tests/tests.cpp @@ -34,6 +34,14 @@ void calcStringHash(const char(&key)[K], const char(&input)[H], void* output) { randomx_calculate_hash(vm, input, H - 1, output); } +template +void calcStringCommitment(const char(&key)[K], const char(&input)[H], void* output) { + initCache(key); + assert(vm != nullptr); + randomx_calculate_hash(vm, input, H - 1, output); + randomx_calculate_commitment(input, H - 1, output, output); +} + template void calcHexHash(const char(&key)[K], const char(&hex)[H], void* output) { initCache(key); @@ -1082,6 +1090,22 @@ int main() { assert(rx_get_rounding_mode() == RoundToNearest); }); + if (RANDOMX_HAVE_COMPILER) { + randomx_destroy_vm(vm); + vm = nullptr; +#ifdef RANDOMX_FORCE_SECURE + vm = randomx_create_vm(RANDOMX_FLAG_DEFAULT | RANDOMX_FLAG_SECURE, cache, nullptr); +#else + vm = randomx_create_vm(RANDOMX_FLAG_DEFAULT, cache, nullptr); +#endif + } + + runTest("Commitment test", stringsEqual(RANDOMX_ARGON_SALT, "RandomX\x03"), []() { + char hash[RANDOMX_HASH_SIZE]; + calcStringCommitment("test key 000", "This is a test", &hash); + assert(equalsHex(hash, "d53ccf348b75291b7be76f0a7ac8208bbced734b912f6fca60539ab6f86be919")); + }); + randomx_destroy_vm(vm); vm = nullptr; diff --git a/src/RandomX/src/virtual_memory.cpp b/src/RandomX/src/virtual_memory.c similarity index 54% rename from src/RandomX/src/virtual_memory.cpp rename to src/RandomX/src/virtual_memory.c index 248d3a2c4..d2cdcda0f 100644 --- a/src/RandomX/src/virtual_memory.cpp +++ b/src/RandomX/src/virtual_memory.c @@ -26,28 +26,24 @@ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include "virtual_memory.hpp" - -#include - #if defined(_WIN32) || defined(__CYGWIN__) #include #else +#define _GNU_SOURCE 1 /* needed for MAP_ANONYMOUS on older platforms */ #ifdef __APPLE__ #include #include #include # if TARGET_OS_OSX -# if TARGET_CPU_ARM64 -# define USE_PTHREAD_JIT_WP 1 -# else -# undef USE_PTHREAD_JIT_WP -# endif +# define USE_PTHREAD_JIT_WP 1 # include +# include +# include # endif #endif #include #include +#include #ifndef MAP_ANONYMOUS #define MAP_ANONYMOUS MAP_ANON #endif @@ -57,27 +53,50 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #define PAGE_EXECUTE_READWRITE (PROT_READ | PROT_WRITE | PROT_EXEC) #endif -#if defined(_WIN32) || defined(__CYGWIN__) -std::string getErrorMessage(const char* function) { - LPSTR messageBuffer = nullptr; - size_t size = FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, - NULL, GetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPSTR)&messageBuffer, 0, NULL); - std::string message(messageBuffer, size); - LocalFree(messageBuffer); - return std::string(function) + std::string(": ") + message; +#include "virtual_memory.h" + +#if defined(USE_PTHREAD_JIT_WP) && defined(MAC_OS_VERSION_11_0) \ + && MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_VERSION_11_0 +static int MacOSchecked, MacOSver; +/* This function is used implicitly by clang's __builtin_available() checker. + * When cross-compiling, the library containing this function doesn't exist, + * and linking will fail because the symbol is unresolved. The function here + * is a quick and dirty hack to get close enough to identify MacOSX 11.0. + */ +static int32_t __isOSVersionAtLeast(int32_t major, int32_t minor, int32_t subminor) { + if (!MacOSchecked) { + struct utsname ut; + int mmaj, mmin; + uname(&ut); + sscanf(ut.release, "%d.%d", &mmaj, &mmin); + // The utsname release version is 9 greater than the canonical OS version + mmaj -= 9; + MacOSver = (mmaj << 8) | mmin; + MacOSchecked = 1; + } + return MacOSver >= ((major << 8) | minor); } +#endif + -void setPrivilege(const char* pszPrivilege, BOOL bEnable) { +#if defined(_WIN32) || defined(__CYGWIN__) +#define Fail(func) do {*errfunc = func; return GetLastError();} while(0) +int setPrivilege(const char* pszPrivilege, BOOL bEnable, char **errfunc) { HANDLE hToken; TOKEN_PRIVILEGES tp; BOOL status; - DWORD error; + DWORD error = 0; + + *errfunc = NULL; if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken)) - throw std::runtime_error(getErrorMessage("OpenProcessToken")); + Fail("OpenProcessToken"); - if (!LookupPrivilegeValue(NULL, pszPrivilege, &tp.Privileges[0].Luid)) - throw std::runtime_error(getErrorMessage("LookupPrivilegeValue")); + if (!LookupPrivilegeValue(NULL, pszPrivilege, &tp.Privileges[0].Luid)) { + *errfunc = "LookupPrivilegeValue"; + error = GetLastError(); + goto out; + } tp.PrivilegeCount = 1; @@ -89,20 +108,28 @@ void setPrivilege(const char* pszPrivilege, BOOL bEnable) { status = AdjustTokenPrivileges(hToken, FALSE, &tp, 0, (PTOKEN_PRIVILEGES)NULL, 0); error = GetLastError(); - if (!status || (error != ERROR_SUCCESS)) - throw std::runtime_error(getErrorMessage("AdjustTokenPrivileges")); + if (!status || (error != ERROR_SUCCESS)) { + *errfunc = "AdjustTokenPrivileges"; + goto out; + } - if (!CloseHandle(hToken)) - throw std::runtime_error(getErrorMessage("CloseHandle")); +out: + if (!CloseHandle(hToken)) { + if (*errfunc == NULL) { + *errfunc = "CloseHandle"; + error = GetLastError(); + } + } + return error; } +#else +#define Fail(func) do {*errfunc = func; return errno;} while(0) #endif -void* allocMemoryPages(std::size_t bytes) { +void* allocMemoryPages(size_t bytes) { void* mem; #if defined(_WIN32) || defined(__CYGWIN__) - mem = VirtualAlloc(nullptr, bytes, MEM_COMMIT, PAGE_READWRITE); - if (mem == nullptr) - throw std::runtime_error(getErrorMessage("allocMemoryPages - VirtualAlloc")); + mem = VirtualAlloc(NULL, bytes, MEM_COMMIT, PAGE_READWRITE); #else #if defined(__NetBSD__) #define RESERVED_FLAGS PROT_MPROTECT(PROT_EXEC) @@ -116,89 +143,95 @@ void* allocMemoryPages(std::size_t bytes) { #define MEXTRA 0 #define PEXTRA 0 #endif - mem = mmap(nullptr, bytes, PAGE_READWRITE | RESERVED_FLAGS | PEXTRA, MAP_ANONYMOUS | MAP_PRIVATE | MEXTRA, -1, 0); + mem = mmap(NULL, bytes, PAGE_READWRITE | RESERVED_FLAGS | PEXTRA, MAP_ANONYMOUS | MAP_PRIVATE | MEXTRA, -1, 0); if (mem == MAP_FAILED) - throw std::runtime_error("allocMemoryPages - mmap failed"); + mem = NULL; #if defined(USE_PTHREAD_JIT_WP) && defined(MAC_OS_VERSION_11_0) \ && MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_VERSION_11_0 if (__builtin_available(macOS 11.0, *)) { - pthread_jit_write_protect_np(false); + pthread_jit_write_protect_np(0); } #endif #endif return mem; } -static inline void pageProtect(void* ptr, std::size_t bytes, int rules) { +static inline int pageProtect(void* ptr, size_t bytes, int rules, char **errfunc) { #if defined(_WIN32) || defined(__CYGWIN__) DWORD oldp; if (!VirtualProtect(ptr, bytes, (DWORD)rules, &oldp)) { - throw std::runtime_error(getErrorMessage("VirtualProtect")); + Fail("VirtualProtect"); } #else if (-1 == mprotect(ptr, bytes, rules)) - throw std::runtime_error("mprotect failed"); + Fail("mprotect"); #endif + return 0; } -void setPagesRW(void* ptr, std::size_t bytes) { +void setPagesRW(void* ptr, size_t bytes) { + char *errfunc; #if defined(USE_PTHREAD_JIT_WP) && defined(MAC_OS_VERSION_11_0) \ && MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_VERSION_11_0 if (__builtin_available(macOS 11.0, *)) { - pthread_jit_write_protect_np(false); + pthread_jit_write_protect_np(0); } else { - pageProtect(ptr, bytes, PAGE_READWRITE); + pageProtect(ptr, bytes, PAGE_READWRITE, &errfunc); } #else - pageProtect(ptr, bytes, PAGE_READWRITE); + pageProtect(ptr, bytes, PAGE_READWRITE, &errfunc); #endif } -void setPagesRX(void* ptr, std::size_t bytes) { +void setPagesRX(void* ptr, size_t bytes) { + char *errfunc; #if defined(USE_PTHREAD_JIT_WP) && defined(MAC_OS_VERSION_11_0) \ && MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_VERSION_11_0 if (__builtin_available(macOS 11.0, *)) { - pthread_jit_write_protect_np(true); + pthread_jit_write_protect_np(1); + __builtin___clear_cache((char*)ptr, ((char*)ptr) + bytes); } else { - pageProtect(ptr, bytes, PAGE_EXECUTE_READ); + pageProtect(ptr, bytes, PAGE_EXECUTE_READ, &errfunc); } #else - pageProtect(ptr, bytes, PAGE_EXECUTE_READ); + pageProtect(ptr, bytes, PAGE_EXECUTE_READ, &errfunc); #endif } -void setPagesRWX(void* ptr, std::size_t bytes) { - pageProtect(ptr, bytes, PAGE_EXECUTE_READWRITE); +void setPagesRWX(void* ptr, size_t bytes) { + char *errfunc; + pageProtect(ptr, bytes, PAGE_EXECUTE_READWRITE, &errfunc); } -void* allocLargePagesMemory(std::size_t bytes) { +void* allocLargePagesMemory(size_t bytes) { void* mem; + char *errfunc; #if defined(_WIN32) || defined(__CYGWIN__) - setPrivilege("SeLockMemoryPrivilege", 1); - auto pageMinimum = GetLargePageMinimum(); - if (pageMinimum > 0) - mem = VirtualAlloc(NULL, alignSize(bytes, pageMinimum), MEM_COMMIT | MEM_RESERVE | MEM_LARGE_PAGES, PAGE_READWRITE); - else - throw std::runtime_error("allocLargePagesMemory - Large pages are not supported"); - if (mem == nullptr) - throw std::runtime_error(getErrorMessage("allocLargePagesMemory - VirtualAlloc")); + if (setPrivilege("SeLockMemoryPrivilege", 1, &errfunc)) + return NULL; + size_t pageMinimum = GetLargePageMinimum(); + if (!pageMinimum) { + errfunc = "No large pages"; + return NULL; + } + mem = VirtualAlloc(NULL, alignSize(bytes, pageMinimum), MEM_COMMIT | MEM_RESERVE | MEM_LARGE_PAGES, PAGE_READWRITE); #else #ifdef __APPLE__ - mem = mmap(nullptr, bytes, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, VM_FLAGS_SUPERPAGE_SIZE_2MB, 0); + mem = mmap(NULL, bytes, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, VM_FLAGS_SUPERPAGE_SIZE_2MB, 0); #elif defined(__FreeBSD__) - mem = mmap(nullptr, bytes, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS | MAP_ALIGNED_SUPER, -1, 0); + mem = mmap(NULL, bytes, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS | MAP_ALIGNED_SUPER, -1, 0); #elif defined(__OpenBSD__) || defined(__NetBSD__) mem = MAP_FAILED; // OpenBSD does not support huge pages #else - mem = mmap(nullptr, bytes, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS | MAP_HUGETLB | MAP_POPULATE, -1, 0); + mem = mmap(NULL, bytes, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS | MAP_HUGETLB | MAP_POPULATE, -1, 0); #endif if (mem == MAP_FAILED) - throw std::runtime_error("allocLargePagesMemory - mmap failed"); + mem = NULL; #endif return mem; } -void freePagedMemory(void* ptr, std::size_t bytes) { +void freePagedMemory(void* ptr, size_t bytes) { #if defined(_WIN32) || defined(__CYGWIN__) VirtualFree(ptr, 0, MEM_RELEASE); #else diff --git a/src/RandomX/src/virtual_memory.hpp b/src/RandomX/src/virtual_memory.h similarity index 80% rename from src/RandomX/src/virtual_memory.hpp rename to src/RandomX/src/virtual_memory.h index 9e8bc29ab..5e8e31d53 100644 --- a/src/RandomX/src/virtual_memory.hpp +++ b/src/RandomX/src/virtual_memory.h @@ -28,15 +28,21 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #pragma once -#include +#ifdef __cplusplus +extern "C" { +#endif -constexpr std::size_t alignSize(std::size_t pos, std::size_t align) { - return ((pos - 1) / align + 1) * align; -} +#include + +#define alignSize(pos, align) (((pos - 1) / align + 1) * align) -void* allocMemoryPages(std::size_t); -void setPagesRW(void*, std::size_t); -void setPagesRX(void*, std::size_t); -void setPagesRWX(void*, std::size_t); -void* allocLargePagesMemory(std::size_t); -void freePagedMemory(void*, std::size_t); +void* allocMemoryPages(size_t); +void setPagesRW(void*, size_t); +void setPagesRX(void*, size_t); +void setPagesRWX(void*, size_t); +void* allocLargePagesMemory(size_t); +void freePagedMemory(void*, size_t); + +#ifdef __cplusplus +} +#endif diff --git a/src/RandomX/vcxproj/randomx-dll.vcxproj b/src/RandomX/vcxproj/randomx-dll.vcxproj index 8b8ea8c08..4eaae9bed 100644 --- a/src/RandomX/vcxproj/randomx-dll.vcxproj +++ b/src/RandomX/vcxproj/randomx-dll.vcxproj @@ -43,7 +43,7 @@ - + @@ -74,7 +74,7 @@ - + diff --git a/src/RandomX/vcxproj/randomx-dll.vcxproj.filters b/src/RandomX/vcxproj/randomx-dll.vcxproj.filters index 68e1b8559..5b51f9f72 100644 --- a/src/RandomX/vcxproj/randomx-dll.vcxproj.filters +++ b/src/RandomX/vcxproj/randomx-dll.vcxproj.filters @@ -87,7 +87,7 @@ Header Files - + Header Files @@ -151,7 +151,7 @@ Source Files - + Source Files diff --git a/src/RandomX/vcxproj/randomx.vcxproj b/src/RandomX/vcxproj/randomx.vcxproj index e0625c88b..cefdc8fb3 100644 --- a/src/RandomX/vcxproj/randomx.vcxproj +++ b/src/RandomX/vcxproj/randomx.vcxproj @@ -156,7 +156,7 @@ SET ERRORLEVEL = 0 - + @@ -198,7 +198,7 @@ SET ERRORLEVEL = 0 - + diff --git a/src/RandomX/vcxproj/randomx.vcxproj.filters b/src/RandomX/vcxproj/randomx.vcxproj.filters index eb4462a59..7f055b5b8 100644 --- a/src/RandomX/vcxproj/randomx.vcxproj.filters +++ b/src/RandomX/vcxproj/randomx.vcxproj.filters @@ -72,7 +72,7 @@ Source Files - + Source Files @@ -164,7 +164,7 @@ Header Files - + Header Files diff --git a/src/cc/Makefile b/src/cc/Makefile index 24b94226a..54f290573 100644 --- a/src/cc/Makefile +++ b/src/cc/Makefile @@ -3,9 +3,9 @@ CC = gcc CC_DARWIN = g++-6 CC_WIN = x86_64-w64-mingw32-gcc-posix CFLAGS = -arch x86_64 -CXXFLAGS_DARWIN = -std=c++11 -arch x86_64 -I/usr/local/Cellar/gcc\@6/6.4.0_2/include/c++/6.4.0/ -I../../depends/$(shell echo `../..//depends/config.guess`/include) -I../univalue/include -I../cryptoconditions/include -I../cryptoconditions/src -I../cryptoconditions/src/asn -I.. -I. -fPIC -c -Wl,-undefined -Wl,dynamic_lookup -dynamiclib -CXXFLAGS = -std=c++11 -I../../depends/$(shell echo `../..//depends/config.guess`/include) -I../univalue/include -I../cryptoconditions/include -I../cryptoconditions/src -I../cryptoconditions/src/asn -I.. -I. -fPIC -shared -c -CXXFLAGS_WIN = -std=c++11 -I../../depends/$(shell echo `../..//depends/config.guess`/include) -I../univalue/include -I../cryptoconditions/include -I../cryptoconditions/src -I../cryptoconditions/src/asn -I.. -I. -fPIC -shared -c +CXXFLAGS_DARWIN = -std=c++11 -arch x86_64 -I/usr/local/Cellar/gcc\@6/6.4.0_2/include/c++/6.4.0/ -I../../depends/$(shell echo `../..//depends/config.guess`/include) -I../univalue/include -I../cryptoconditions/include -I../cryptoconditions/src -I../cryptoconditions/src/asn -I -I../leveldb/include -I.. -I. -fPIC -c -Wl,-undefined -Wl,dynamic_lookup -dynamiclib +CXXFLAGS = -std=c++11 -I../../depends/$(shell echo `../..//depends/config.guess`/include) -I../univalue/include -I../cryptoconditions/include -I../cryptoconditions/src -I../cryptoconditions/src/asn -I../leveldb/include -I.. -I. -fPIC -shared -c +CXXFLAGS_WIN = -std=c++11 -I../../depends/$(shell echo `../..//depends/config.guess`/include) -I../univalue/include -I../cryptoconditions/include -I../cryptoconditions/src -I../cryptoconditions/src/asn -I../leveldb/include -I.. -I. -fPIC -shared -c DEBUGFLAGS = -O0 -D _DEBUG RELEASEFLAGS = -O2 -D NDEBUG -combine -fwhole-program $(info $(OS)) diff --git a/src/cc/Makefile_custom b/src/cc/Makefile_custom index 3989eefa3..5cedceec0 100644 --- a/src/cc/Makefile_custom +++ b/src/cc/Makefile_custom @@ -3,9 +3,9 @@ CC = gcc CC_DARWIN = g++-8 CC_WIN = x86_64-w64-mingw32-gcc-posix CC_AARCH64 = aarch64-linux-gnu-g++ -CFLAGS_DARWIN = -DBUILD_CUSTOMCC -std=c++11 -arch x86_64 -I../secp256k1/include -I../../depends/$(shell echo `../..//depends/config.guess`/include) -I../univalue/include -I../cryptoconditions/include -I../cryptoconditions/src -I../cryptoconditions/src/asn -I.. -I. -fPIC -Wl,-undefined -Wl,dynamic_lookup -Wno-write-strings -shared -dynamiclib -CFLAGS = -Wno-write-strings -DBUILD_CUSTOMCC -std=c++11 -I../secp256k1/include -I../../depends/$(shell echo `../..//depends/config.guess`/include) -I../univalue/include -I../cryptoconditions/include -I../cryptoconditions/src -I../cryptoconditions/src/asn -I.. -I. -fPIC -shared -CFLAGS_WIN = -Wno-write-strings -DBUILD_CUSTOMCC -std=c++11 -I../secp256k1/include -I../../depends/x86_64-w64-mingw32/include -I../univalue/include -I../cryptoconditions/include -I../cryptoconditions/src -I../cryptoconditions/src/asn -I.. -I. -fPIC -shared +CFLAGS_DARWIN = -DBUILD_CUSTOMCC -std=c++11 -arch x86_64 -I../secp256k1/include -I../../depends/$(shell echo `../..//depends/config.guess`/include) -I../univalue/include -I../cryptoconditions/include -I../cryptoconditions/src -I../cryptoconditions/src/asn -I../leveldb/include -I.. -I. -fPIC -Wl,-undefined -Wl,dynamic_lookup -Wno-write-strings -shared -dynamiclib +CFLAGS = -Wno-write-strings -DBUILD_CUSTOMCC -std=c++11 -I../secp256k1/include -I../../depends/$(shell echo `../..//depends/config.guess`/include) -I../univalue/include -I../cryptoconditions/include -I../cryptoconditions/src -I../cryptoconditions/src/asn -I../leveldb/include -I.. -I. -fPIC -shared +CFLAGS_WIN = -Wno-write-strings -DBUILD_CUSTOMCC -std=c++11 -I../secp256k1/include -I../../depends/x86_64-w64-mingw32/include -I../univalue/include -I../cryptoconditions/include -I../cryptoconditions/src -I../cryptoconditions/src/asn -I../leveldb/include -I.. -I. -fPIC -shared DEBUGFLAGS = -O0 -D _DEBUG RELEASEFLAGS = -O2 -D NDEBUG -combine -fwhole-program $(info $(OS)) diff --git a/src/chain.cpp b/src/chain.cpp index 1e87b22e1..0b5ac609d 100644 --- a/src/chain.cpp +++ b/src/chain.cpp @@ -19,12 +19,56 @@ ******************************************************************************/ #include "chain.h" +#include "main.h" +#include "txdb.h" using namespace std; /** * CChain implementation */ +void CBlockIndex::TrimSolution() +{ + AssertLockHeld(cs_main); + + // We can correctly trim a solution as soon as the block index entry has been added + // to leveldb. Updates to the block index entry (to update validity status) will be + // handled by re-reading the solution from the existing db entry. It does not help to + // try to avoid these reads by gating trimming on the validity status: the re-reads are + // efficient anyway because of caching in leveldb, and most of them are unavoidable. + if (HasSolution()) { + std::vector empty; + nSolution.swap(empty); + } +} + +CBlockHeader CBlockIndex::GetBlockHeader() const +{ + AssertLockHeld(cs_main); + + CBlockHeader header; + header.nVersion = nVersion; + if (pprev) { + header.hashPrevBlock = pprev->GetBlockHash(); + } + header.hashMerkleRoot = hashMerkleRoot; + header.hashFinalSaplingRoot = hashFinalSaplingRoot; + header.nTime = nTime; + header.nBits = nBits; + header.nNonce = nNonce; + if (HasSolution()) { + header.nSolution = nSolution; + } else { + CDiskBlockIndex dbindex; + if (!pblocktree->ReadDiskBlockIndex(GetBlockHash(), dbindex)) { + LogPrintf("%s: ReadDiskBlockIndex failed to read index entry of block %s", __func__, GetBlockHash().ToString().c_str()); + throw std::runtime_error("Failed to read index entry"); + } + header.nSolution = dbindex.GetSolution(); + } + return header; +} + void CChain::SetTip(CBlockIndex *pindex) { lastTip = pindex; if (pindex == NULL) { diff --git a/src/chain.h b/src/chain.h index eb94559bd..27ee5adcc 100644 --- a/src/chain.h +++ b/src/chain.h @@ -27,6 +27,7 @@ class CChainPower; #include "pow.h" #include "tinyformat.h" #include "uint256.h" +#include "util/strencodings.h" #include #include @@ -384,8 +385,14 @@ public: unsigned int nTime; unsigned int nBits; uint256 nNonce; +protected: + // The Equihash solution, if it is stored. Once we know that the block index + // entry is present in leveldb, this field can be cleared via the TrimSolution + // method to save memory. std::vector nSolution; +public: + //! (memory only) Sequential id assigned to distinguish order in which blocks are received. uint32_t nSequenceId; @@ -497,23 +504,15 @@ public: return ret; } - CBlockHeader GetBlockHeader() const - { - CBlockHeader block; - block.nVersion = nVersion; - if (pprev) - block.hashPrevBlock = pprev->GetBlockHash(); - block.hashMerkleRoot = hashMerkleRoot; - block.hashFinalSaplingRoot = hashFinalSaplingRoot; - block.nTime = nTime; - block.nBits = nBits; - block.nNonce = nNonce; - block.nSolution = nSolution; - return block; - } + //! Get the block header for this block index. Requires cs_main. + CBlockHeader GetBlockHeader() const; + + //! Clear the Equihash solution to save memory. Requires cs_main. + void TrimSolution(); uint256 GetBlockHash() const { + assert(phashBlock); return *phashBlock; } @@ -540,10 +539,11 @@ public: std::string ToString() const { - return strprintf("CBlockIndex(pprev=%p, nHeight=%d, merkle=%s, hashBlock=%s)", + return strprintf("CBlockIndex(pprev=%p, nHeight=%d, merkle=%s, hashBlock=%s, HasSolution=%s)", pprev, this->chainPower.nHeight, hashMerkleRoot.ToString(), - GetBlockHash().ToString()); + phashBlock ? GetBlockHash().ToString() : "(nil)", + HasSolution()); } //! Check whether this block index entry is valid up to the passed validity level. @@ -555,6 +555,12 @@ public: return ((nStatus & BLOCK_VALID_MASK) >= nUpTo); } + //! Is the Equihash solution stored? + bool HasSolution() const + { + return !nSolution.empty(); + } + //! Raise the validity level of this block index entry. //! Returns true if the validity was changed. bool RaiseValidity(enum BlockStatus nUpTo) @@ -588,8 +594,11 @@ public: hashPrev = uint256(); } - explicit CDiskBlockIndex(const CBlockIndex* pindex) : CBlockIndex(*pindex) { + explicit CDiskBlockIndex(const CBlockIndex* pindex, std::function()> getSolution) : CBlockIndex(*pindex) { hashPrev = (pprev ? pprev->GetBlockHash() : uint256()); + if (!HasSolution()) { + nSolution = getSolution(); + } } ADD_SERIALIZE_METHODS; @@ -670,18 +679,29 @@ public: uint256 GetBlockHash() const { - CBlockHeader block; - block.nVersion = nVersion; - block.hashPrevBlock = hashPrev; - block.hashMerkleRoot = hashMerkleRoot; - block.hashFinalSaplingRoot = hashFinalSaplingRoot; - block.nTime = nTime; - block.nBits = nBits; - block.nNonce = nNonce; - block.nSolution = nSolution; - return block.GetHash(); + return GetBlockHeader().GetHash(); } + //! Get the block header for this block index. + CBlockHeader GetBlockHeader() const + { + CBlockHeader header; + header.nVersion = nVersion; + header.hashPrevBlock = hashPrev; + header.hashMerkleRoot = hashMerkleRoot; + header.hashFinalSaplingRoot = hashFinalSaplingRoot; + header.nTime = nTime; + header.nBits = nBits; + header.nNonce = nNonce; + header.nSolution = nSolution; + return header; + } + + std::vector GetSolution() const + { + assert(HasSolution()); + return nSolution; + } std::string ToString() const { @@ -692,6 +712,13 @@ public: hashPrev.ToString()); return str; } + +private: + //! This method should not be called on a CDiskBlockIndex. + void TrimSolution() + { + assert(!"called CDiskBlockIndex::TrimSolution"); + } }; /** An in-memory indexed chain of blocks. */ diff --git a/src/chainparams.cpp b/src/chainparams.cpp index ef7ab5d70..8b5644c2f 100644 --- a/src/chainparams.cpp +++ b/src/chainparams.cpp @@ -1709,10 +1709,177 @@ void *chainparams_commandline() { (1409000, uint256S("0x0000000078be552c979aaf660ef8b2d6a7f3d6878975f49f6d24c0c4d70fbe07")) (1410000, uint256S("0x000000071ffa758ba71f243c8b4106cdabaaa5ec0df9247af03f5dc9221b58b2")) (1411000, uint256S("0x00000007be4b7695ad2a5ef100899a22efad8b142ecbc8b93d5f8d553f9286d4")) - ,(int64_t) 1688026050, // time of last checkpointed block - (int64_t) 0, // total txs - (double) 2304 // txs in the last day before block 1411911 - + // Generated at 1700673919 via hush3 util/checkpoints.pl by Duke Leto + (1412000, uint256S("0x00000005a2e5b152de36e4bdd21b7a56fa9ef7b941ba14c1da3a34e0536da456")) + (1413000, uint256S("0x00000002fbe858cb07c37c73302bfc7ecdc439640e2957e0af57374bba436e7b")) + (1414000, uint256S("0x0000000388087c44ec64d381ccfc21ca44994bc73cf021027a29a1a55435f47e")) + (1415000, uint256S("0x000000050c7a5ab89ed8f492d49d5b0219bfc4b7d7e0df47970e2ba5ab060881")) + (1416000, uint256S("0x0000000089b17751a091a937758d7c4d23f5a4f77908f3532800981777555ee0")) + (1417000, uint256S("0x00000006fd00bc39dd54c3d25e91c67e53389c104448c427ffdf71302a433507")) + (1418000, uint256S("0x000000011a1a89fb8791931772c8d46c36af7eaa5bba69bd7ea99e29c7d7564f")) + (1419000, uint256S("0x00000001eec836c7ded707633589ba9c0ad2e8a8d229d057a7188b0333a7f1e9")) + (1420000, uint256S("0x0000000720e4e42612867d768dea333e255b9c660401072e1db5c2c0a927cb5e")) + (1421000, uint256S("0x00000004cc70fab5aa3bd1a42e6b8d438804c49b36774e1645f60f3f18b65232")) + (1422000, uint256S("0x000000019491f6abc8f8fd952cc0a3af308bbdd0ce4da5dd7f01c6ab0c60736d")) + (1423000, uint256S("0x0000000062ad7bd69192867a04435bc64665294db0fa623bdf5e38a1555c068b")) + (1424000, uint256S("0x000000041f981f227a1b666ee43441f7824ac3346409e2d0294a21b25c7a0726")) + (1425000, uint256S("0x00000006d9843a9e6d0243925fdc7c60f69fb989667f7b73886a9000dfd2fec6")) + (1426000, uint256S("0x00000004f3cfeff221044c82a0f861474e7804c167f72e6f8c262b188d90c470")) + (1427000, uint256S("0x00000002e172288575b63a479b98f01ff21695dae054c6544323f387a3b563d5")) + (1428000, uint256S("0x00000002dc39e05cae0a37086c464ea14d5ce4b8d64282da4df79f2247f1fc58")) + (1429000, uint256S("0x000000060afd50b0b7a395ebc17b24ee019827d765dddcd6e21874f7caaa8058")) + (1430000, uint256S("0x000000066375bf5edfb65bec45cfa47042b47e3aea87da9236da5b9f4ca70f84")) + (1431000, uint256S("0x000000092227e711eda7da0ba736104e4cc22024f86a52b692b46b562601aad1")) + (1432000, uint256S("0x0000000406a66809c19f82c8e7d852a1105cd315244595be9b7d150c3a5b2df6")) + (1433000, uint256S("0x000000067974e087e9d4a0fb5f99f2693b87f1c9919958e6c30c73723b911728")) + (1434000, uint256S("0x00000001ce76bfbe325a7a01f561cba8cf0b495c2fa3dde8d5363eb9050f0998")) + (1435000, uint256S("0x00000003cffac5408c9735fdcc363e4800dca9da7307284191872026f0d40711")) + (1436000, uint256S("0x00000008c2b156e74fd28df28d30bbc85d54fc8539517c93e1874bf696beaeac")) + (1437000, uint256S("0x000000007bed32c75a3849114f3edc6d5fc89c1956834e0ee9cd3d7988e93d85")) + (1438000, uint256S("0x0000000ad9956fb6821af5ee046d72a7535e359b10c4022038b4d3a371a88709")) + (1439000, uint256S("0x00000006f5e641d27f1068d1884f7e335431d25d4d43faa80dbd34dfe69dcbe4")) + (1440000, uint256S("0x00000001025150e823cedbe98c30f09385017b229bc247420d43854ddb1c4ff0")) + (1441000, uint256S("0x00000003c0d4e0e755be73139682edb6bd5bfaf29bbf0e13b9e7898c30472811")) + (1442000, uint256S("0x00000003aef06aa4c748691f1317ca56bb66cc2ce69fc46e04eb9366178b3d00")) + (1443000, uint256S("0x0000000424fea4f00e4dd2f3bf2656e3ed232a78c872fe11a81d719f0d497ecd")) + (1444000, uint256S("0x000000042b1310f6cc53911a1c4b0b685a7fbd1a243cbcbbabb327291ea4ada4")) + (1445000, uint256S("0x0000000428ce6358cd60e021ccd47ac964549e2bea6360f25e8e9a183b1b151c")) + (1446000, uint256S("0x00000008427a3e76889733a665dccb1f44bc94b8e0acf3107f647d9addf6c0f3")) + (1447000, uint256S("0x000000023db7c81deaceb32e632a127d455a393dd07bdce3fc0752ad765feef5")) + (1448000, uint256S("0x00000004c26f357d2f32549bb5d905e59f21f50311c389a2ed49a96f3e952825")) + (1449000, uint256S("0x000000088dd7f1c8000e5241bbb99fd46c1a4a7e9937efa1f31fd65fc817c38f")) + (1450000, uint256S("0x00000001ba8b62f62c313bad5f3e5e5b1068060e7b52855a703575e8b999e980")) + (1451000, uint256S("0x000000035096c1b0e03ff8fd2896d4d018e106d4ef84d887bdb0d2877d13ad65")) + (1452000, uint256S("0x00000004ea1a7e6bc698d8ed8d2b3b90809f9481472ae36af02437346dc9103a")) + (1453000, uint256S("0x00000007874e5cda4777e65ccdf7b1d74932d551b6828a4f1fd0e5470698eb62")) + (1454000, uint256S("0x000000037a56260f7ed0c67f556e971f059e62a5c12b0f34f2ba7ef54378f0cd")) + (1455000, uint256S("0x0000000104b524dc502b50302b17123ae9e31f59b490ba5db9c862aff128529c")) + (1456000, uint256S("0x000000038d9048ef49690ab9a55f691657c87fd8a16200c211713c4e599a71f7")) + (1457000, uint256S("0x00000002b32aeca0426f15ad677697f4529aa21889f25b51ad121e5a50021e61")) + (1458000, uint256S("0x000000024c2b4c28be496d241ace65ecab0a6552ce4cb0e0d1d9d123f82e195b")) + (1459000, uint256S("0x000000033e8ce63d3b2dbf0a7d5f5ff2e5c053834782305214e5ecd8ef62da3d")) + (1460000, uint256S("0x00000005153ae6e0e3f6dabd9ae9c3e02cbb2cdd61fc9cc697f94a943d3e7c31")) + (1461000, uint256S("0x0000000141c41db3de8251e3257e3a0c587116ffd98563d8d7d31bdddd9912d2")) + (1462000, uint256S("0x000000061ae26bbc87408f5f679b4349fe8b858bc2536de9d1c3ef9d2c09c5e5")) + (1463000, uint256S("0x000000024a8cd2556f99408290bf83bb9a1db7906ef2f88b4e62f412bb8f03f7")) + (1464000, uint256S("0x00000005180b11822bd9609e69ef6fb435ed599049239351df67f595704cb217")) + (1465000, uint256S("0x00000002087d5f2841c788b68fe80f064b5527f5e3d9ad8099def2c779964ea5")) + (1466000, uint256S("0x000000011da08a123c9d98d738d254600dcd2b6cc1af4a5b848656c247bf30c9")) + (1467000, uint256S("0x00000000948ee1f7355e6d9341d90199d58a9ebcff00a9bc016ee279a9aaf26b")) + (1468000, uint256S("0x0000000021ac3a32d6e75c4b5e28949a395bda280216912ae19a6f08541772fe")) + (1469000, uint256S("0x00000001e4e1394a49683163c09bb6f0bd8b8026cbe23dfa444149f5e8a6ac1a")) + (1470000, uint256S("0x00000001be9faf4c236b5925b9d82a843c98fdecb0db32a7b971c7f0e06ae686")) + (1471000, uint256S("0x00000003d804f002ec259e98aab22a71b4324ab84cdae755a4f2e5fab8566f40")) + (1472000, uint256S("0x00000002725f5bad126c8ffdb936259a59f6780115befbcad791299dd2987fe5")) + (1473000, uint256S("0x00000000ae5ad472e5ba6d3ea32f3783b3a2fd5c95934b3975d5bef9f1287130")) + (1474000, uint256S("0x00000006634039acfb185a6c976270d841cf5e96530ceafcaa8fe1fa54c496e0")) + (1475000, uint256S("0x00000007c3b81c84a0ab3c36a9671fa614a323b3f2e1eb101df1e4af53bfcd0d")) + (1476000, uint256S("0x0000000089bf696ae0613165e0870dc0feb84639f5226af2173a6d532f4e0f80")) + (1477000, uint256S("0x00000005eac7c3c470c8c889804704d490def24db86337a6b96437726c0efe36")) + (1478000, uint256S("0x0000000579496eab2c6e7954ed0ea378590854b1f29fcf2d0974cf2572864c32")) + (1479000, uint256S("0x000000056c1bd1d085e0aa3749e5481c93bd3469b4e11e405cb6ca36749c999d")) + (1480000, uint256S("0x000000061fc1275ef78b285aec0a73edc82861a0d390503c3b4c5455d8242acc")) + (1481000, uint256S("0x00000001ef1b909eb2967d55324c8c98885ac0ee5eb11f8ee523bffb7ca6d767")) + (1482000, uint256S("0x000000034b7820b9e82a48f06c0000f7c08191a9cf3ca991c643178d31c4021b")) + (1483000, uint256S("0x000000064240d3f14ea25bf58cc6a0f141e5ec1135e8ab46b24e34c0714f9df1")) + (1484000, uint256S("0x00000005aa675059e1c89ca6d0b8cee7c4c5c39e863b0016d26059c3a70ad6da")) + (1485000, uint256S("0x00000004025ae91d8fefbcf3c840aa7c7fe0d089e195b9eec2c3a781402f9a3c")) + (1486000, uint256S("0x00000005993c81ffa8c5fbc8c7b3e307a06b30bd69ce9c78ccf44743cc27df31")) + (1487000, uint256S("0x00000003a793f8e414881033ba5e91a5b3cf694cf9a32feaf28571abc5d8f479")) + (1488000, uint256S("0x000000086af04eb0f1fa19ca2c6676d27dcd0423290d3ee2cfe5dc37e38ca1a4")) + (1489000, uint256S("0x00000003401859a29cb62fb336bfd5820df7fe201dcbf5a728c1baa856db4eff")) + (1490000, uint256S("0x00000002271c1f284ad47cfc27332ea820045602f62381dd10cdfe77cbf73cce")) + (1491000, uint256S("0x00000005942b01c0bc6834eb445b2f1e0b77c6ab8f6d0bb9ec37f6af42cb7a28")) + (1492000, uint256S("0x000000066687a2d71eb9da2d9f9fe5693b9dbb2e6ed213b143f1e97d257e8a6e")) + (1493000, uint256S("0x00000006179d21ecf0eeda7e9cf3175688da753ab02fb8c8628be41b8c70cd56")) + (1494000, uint256S("0x00000007c1580c43f5a15a1de05296888a794756a7dbcff6d6e5737be634ffc7")) + (1495000, uint256S("0x00000001f834578e0df1cb2d9ef3aaaaede7117a177f13c2597ea39c879a6cb9")) + (1496000, uint256S("0x00000004b6f33c5a4b09a0d98bedef8ba8665af64eef778c398cc8a67caaa27e")) + (1497000, uint256S("0x00000005ba43a1c262e89773e9ab26ebe09c7b9319730104bc77e91c6a245b4a")) + (1498000, uint256S("0x00000003c37a6893d0b5719751cf11b5dac72e191a68fd70da8531c7bb6319f8")) + (1499000, uint256S("0x00000002a1bbdd301b265a26bc05b975bba08ad547560ba34f75133db81a7734")) + (1500000, uint256S("0x0000000015757461b6c1169980a8be062898c1aca4861e45290bb2f07edac0fa")) + (1501000, uint256S("0x0000000696dd6bb52f2d64077a72b7cd66ad2aa1e69f45c492fe5dce87c4a57b")) + (1502000, uint256S("0x00000003fac56b8f410f45d53b55f2d9d9844951ed95fdc9b7e6bb63ddd957d9")) + (1503000, uint256S("0x000000081a33ce3d8160753370f6faebc7fb02ce1f917a6f9a1f4bfaff46d0d5")) + (1504000, uint256S("0x00000002cc3ce9b9eaab5952e8b80d75cedf1789526f8cc79e4c6de814e23c37")) + (1505000, uint256S("0x000000069f24234c9cb3d7879f2d8a792cbbf2a52f959ceeffb222751ef3384f")) + (1506000, uint256S("0x000000035e6a2146f2bc2b566f95544d1c611fbdc485c4275a0b8164ff83b504")) + (1507000, uint256S("0x0000000010fb8d072255b92301d8daf801c618ba06f9f3cf1c2d942fd54a0c92")) + (1508000, uint256S("0x0000000693d977dc0d18e4c0a84ea97b1794e4403639a161968d86e5091e1b24")) + (1509000, uint256S("0x00000006d998c68d962e7a66810517a2acc77a586f5c0aa37a0827dc10cb559a")) + (1510000, uint256S("0x00000003a10174289817f24b4c8f60378e2f075e6bba3fce06e766e5f6eb90f1")) + (1511000, uint256S("0x000000075c33770cc168c0376d00f0a1fd7eae8ad505dc13105f2228ada9637d")) + (1512000, uint256S("0x00000007e1d7d2b27a515fa3564a7f1dd62923eeac3170648bd2110e3aeb8da0")) + (1513000, uint256S("0x00000005e874ac0097e121021510da5fbef99aadd6508f0184370e5db7d92d0e")) + (1514000, uint256S("0x000000005cbaaa65444e19c5ba7c9a9cf1cfe816b23e72645bd6790a2c594c82")) + (1515000, uint256S("0x00000002aa0a9b1ee81651c15268aaf28e746464cab161f788e869d5fc75ff6d")) + (1516000, uint256S("0x000000074bb6c9ce853b2b77f9cb0f3597a63340059b63304348fa888cf211bc")) + (1517000, uint256S("0x00000008ec2a17af3c9e112eef03b320137c601ebd4e1913b21de4fe6891bd42")) + (1518000, uint256S("0x00000002cb2cf01b7318dd7ef40ad1184347d65933aef788474d5598c52dc705")) + (1519000, uint256S("0x00000003593ab8e1450a44c7012ae3ed53b0fb6bb85db0c27c7db945d96b1697")) + (1520000, uint256S("0x00000007fba88eea7c09076fa7693b7ef39feb161bd7d96299deff6f16887ce7")) + (1521000, uint256S("0x00000006e8d2c3a4cc2f10e1303ba732014b9c272b0eb976b8197cacaaaaa637")) + (1522000, uint256S("0x00000004aa5bcf5eff49fc48a3087af01a6f560859dec021e09cc4490b37436b")) + (1523000, uint256S("0x0000000037b4cbc707e343c54b90b7f7ade57ba070840b426419b2edc81e03b3")) + (1524000, uint256S("0x000000010c6b305189974c72d616a054261e21ec445014451f9cd96ea88f2e02")) + (1525000, uint256S("0x0000000308a523f6d277e0bf9433fd30be7b337e5c4d192d32efb3d5bfb87d2e")) + (1526000, uint256S("0x00000004eecd71cf4a6127b0880aa75d90091473f935cbb617173f490cd221ac")) + (1527000, uint256S("0x00000003aae6ffa1caf028842a3598d1fb897b2ae3340356fc045ff93034603e")) + (1528000, uint256S("0x0000000717e163bc49fa1283fca461003a34b65ba06408ff08049708459ac05d")) + (1529000, uint256S("0x00000005eeb301c5f605ba3ed901ee7c48a4b4a16a8929b47a00b8b78b909e4b")) + (1530000, uint256S("0x000000027efbba859044503a52fd35ea1a1fac64e6b159dbdcebcf861f521396")) + (1531000, uint256S("0x0000000469ed4f67494c257dd5faa00d4489816e72db6df1aa12987205de09ee")) + (1532000, uint256S("0x00000000c0c63c420bc00281bf4bc9aca5aa0320810a27ecb0f54de26da815b5")) + (1533000, uint256S("0x000000006c411a8033bd496d49379d9be11859f34aac64756aa407af45ebd9b3")) + (1534000, uint256S("0x0000000270545d0ff5d1fc402b1107db70b915272c268d5c1020f74443847d8c")) + (1535000, uint256S("0x0000000567ad85ae64bc62d9adb18c2ba8c224619779b6949ae09bedae18cee5")) + (1536000, uint256S("0x0000000209e2b8dea101862418a52041e260341251f767103463bd97738f663d")) + (1537000, uint256S("0x000000013bf94f0b0d63962994c5f19e9fa6e4d1017c27e12290645c473b8d9e")) + (1538000, uint256S("0x000000037555de8ef498fd9a3b00dbfc98c3ef28ad7525814809668647f840cf")) + (1539000, uint256S("0x00000001fdc17cca635d7371b9547d92072600300901ad35f721eeece36936fc")) + (1540000, uint256S("0x000000093b7b4861ec7cf9c1262ac89815b515160e383819383ae2bce4d9d15a")) + (1541000, uint256S("0x0000000624f32330e8e8f135650113b21c0e9b90f52b48ab47c0c92048d498b3")) + (1542000, uint256S("0x00000002901ec15b1c2e92f2653ad68f26cd35f0ec744a61c62634db760c1948")) + (1543000, uint256S("0x00000005bbe4ae4c5fba86bd76bf724d282a370766bf4ce3a5d451d7d68ef0c2")) + (1544000, uint256S("0x0000000714aa05fac0400397b72cd18fcf71ba1e48a4b5381b4bb70d5041e8be")) + (1545000, uint256S("0x0000000098ce2f192e658a1a5f531d733e44fcb2f125203632456c24212bf8e0")) + (1546000, uint256S("0x0000000624551ffc4fb44f5307571380b1374ef080d476f086d3debda8dac9ec")) + (1547000, uint256S("0x00000003f5dfd019ae78d63c06e53bdd2859a6f6ee18f9a7ed5159ea60b8e624")) + (1548000, uint256S("0x0000000ba6bde488c90fdb343563c2e039aef07784f7acfe493b8ca5a2fcdd8f")) + (1549000, uint256S("0x0000000442c07f04a734f56aa20e34b6aad2c350041864feec1c5560d4a19e8b")) + (1550000, uint256S("0x00000000b6414f92b836b1a6400976ea986216b28ab041ea038844d3c56683b7")) + (1551000, uint256S("0x0000000396a47bacdbe8463d62ab550700b5cf1257db90a4f4f2737ab6116116")) + (1552000, uint256S("0x00000006236a9a547e548414bc92abb58e53162830bbac1b191b7eab7afa12c8")) + (1553000, uint256S("0x00000002da093d5528e23bb4b537523b44370bfaeddaaf3458c80ede46b9ece5")) + (1554000, uint256S("0x00000001a75e4fa343e5fb83792ca11ce8506e67b8f1abe6b274bd7410360ebb")) + (1555000, uint256S("0x0000000769a649d4cdd9139c233da20a99e28a4ed2657ded422ddaaee07baf9a")) + (1556000, uint256S("0x000000053362cfffc8abdc34e4099efc53ac2f2120ab60ee21be7bc8b926e5c4")) + (1557000, uint256S("0x00000005a1a939861c82007d74c0834684f92e11208a73c6ff3c6f63841b5c54")) + (1558000, uint256S("0x0000000579d9a4d71bba23f68129156fd40b51dd69899be2678d9c5c343c43b2")) + (1559000, uint256S("0x000000012cc2a6d20028bd660a02bb1ff14c8d3e986e933b83621289953aaa7d")) + (1560000, uint256S("0x0000000b6295fcf534ba222c7d68b5ee14445e2519a62c512cfd3010778d044a")) + (1561000, uint256S("0x0000000729a0889e1fde7bef00b6bd82b73433a8e66844c38fef22d16ad7a7e6")) + (1562000, uint256S("0x0000000554f4199bdd1879c1a7e0a56349ae8b009fc8cc80fd7ccfd2938f8bd9")) + (1563000, uint256S("0x000000039b32b23e84a92e71bf7dd6bbea07e7f22c54c5935bfa7bcee489fa08")) + (1564000, uint256S("0x0000000169d3917bedad00142364b2118372bdd924d796de22efdc04f29f4fc7")) + (1565000, uint256S("0x000000010f48b5f7ec0ae3b9012c967e3cc24dc2386a24dd6c14196fbfa62def")) + (1566000, uint256S("0x00000004a0af68f64b01d833bbc3d2f2e9c188a2e70cd3424934f15e305b5a34")) + (1567000, uint256S("0x00000005fb69ecb63114d99bb9866a9957a5002d6fd4056a94c5fa5bec3d9e22")) + (1568000, uint256S("0x0000000497753d29bfaf089510fbb6e31706b96afca39eb46796f3f151e67338")) + (1569000, uint256S("0x000000061681b5b4373f7da084b55195991633a9aca29460e7a0157e486b6d1c")) + (1570000, uint256S("0x000000069f9bdf236df00a42975f1ec785fb915e900e044352043c6ecb1cb34d")) + (1571000, uint256S("0x000000028a3d6120bdd0081e08b42a6e217917fcccffd257e48d6a28f639053a")) + (1572000, uint256S("0x00000006c163fbd8f81f13cbf4c9b8d4bacb451cae439b33d2a70ec9b60b829b")) + (1573000, uint256S("0x000000020b1700e0ece6df3e2cddb4638c2d5f271ce2aa0e6762acc7a992713b")) + (1574000, uint256S("0x00000004e0e2ab9088bb3fa4cfa86225678f236b8405d26b427a0d77b9593c80")) + (1575000, uint256S("0x000000024b035fbfab5c0f3a8a094ffa57a3fc7208ea88423777c5201feb654b")) + (1576000, uint256S("0x00000001b67093fd107d5dd39e75e23103bceca5e32d7e4c27732897492780de")) + (1577000, uint256S("0x00000001cac9f3fd5737948e8cf2265ada33160ba67d94a66cd85f908cbab004")) + (1578000, uint256S("0x00000002db302bc36ed573796784357f4b4996c01d17a0eee0563c229060e1a8")) + ,(int64_t) 1700673191, // time of last checkpointed block + (int64_t) 2400163, // total txs + (double) 1220 // txs in the last day before block 1578008 }; // END HUSH mainnet checkpoint data } else if (strcmp(SMART_CHAIN_SYMBOL,"DRAGONX") == 0) { @@ -2232,9 +2399,393 @@ void *chainparams_commandline() { (510000, uint256S("0x000045c957443966535795a08bc5feffee0f0c59b55d7ba727593dbc459a1c34")) (511000, uint256S("0x00001d9b8898a1a26bec928ded3b3650b6e0b6cf6589f95072fbff5586057716")) (512000, uint256S("0x00006c49e4544ce19a6b3e4a4e82e05fbc3ef1ce9d3dee203cf09f047ec92d30")) - ,(int64_t) 1686842247, // time of last checkpointed block - (int64_t) 523914, // total txs - (double) 1454 // txs in the last day before block 512445 + (513000, uint256S("0x0000585a620e53ace251123b33f40e106a761262d2f3c972fc2b8811435ba20f")) + (514000, uint256S("0x0000393fa870037144940ca55d8160c1a8d502da59fc3197c1156b0af6673d15")) + (515000, uint256S("0x00003c6fc5a0bb67ccaa6c7eddd4e19386d45078982471aa0d9e9895ff53799a")) + (516000, uint256S("0x00002c219d6f22673c1092bbabce56a5cbbbb64f87ec82ef729471200d99f83c")) + (517000, uint256S("0x00001d86620d7cd6a09979763fc54e4adab8c2fbf85c4267a5bebc9c57b011eb")) + (518000, uint256S("0x000059d64e5492cb98ec1c8f696baba3da6e5dac0e9a49957adf0c30df6e1c51")) + (519000, uint256S("0x00005a8cd10c4dfabc4bee6b734ed70aa095c25fcbe879bf4b3d8e18de73d0cb")) + (520000, uint256S("0x000065949a8cd500872a3961e2d5736fee4f84ddb909c1f34969223b0f896fc0")) + (521000, uint256S("0x000027525047176985a35f002bfcf0bfc838fddfb467da7d3a994bcee2230100")) + (522000, uint256S("0x00005dfbd9f73797b39189e7b677d3d02696dc4f20814036f015c5a18d144d41")) + (523000, uint256S("0x00004370f822c1c027c975defd953e4fec60f02b6eaae2a0f0e34ffc0c109f67")) + (524000, uint256S("0x00002840bcce6492e4685fa9a278ace9f8144ec6092f6c0382dd6f6db2e0d637")) + (525000, uint256S("0x00004000bcd7dbebe428be48c0247abfc9c2cf583ac61517c17f6d748b303ce7")) + (526000, uint256S("0x000062a7bc7adfd8963df452ea4f01c547bacaa2c77ff0c728cd74f6c13bee55")) + (527000, uint256S("0x000075be4294dbb03f48a0f042d4e5e0c61b86af6dbbb51a98497ac66c6f60be")) + (528000, uint256S("0x00001c082e744a49944a41eb6d411cef4da29fea9a5d691f5394e74753ddb6ee")) + (529000, uint256S("0x000033f2df7443bb0fd704def1211fd46f69e17f2efaa71ad89a07a662f19447")) + (530000, uint256S("0x00001b24c718558a4c4e08ea1605fc5851706f39b163d2b90e6f89d3bb633330")) + (531000, uint256S("0x000068a1b6fc06c84598d4e1f6ada5fc28f4a35ad1f8ac73fe9e194b3d6f693c")) + (532000, uint256S("0x00000fd8ce5f553c59aeae4872dbe40c59968cd887d28e5d5dc8679c8a8b2c8b")) + (533000, uint256S("0x00003c501980079c65a7affff6ba946c83b16dc1d26b3d543cf2342bc4772a7e")) + (534000, uint256S("0x00000d9542f8f3ef06142d28e71ccd02301f23d1e034655649161b771c8a2717")) + (535000, uint256S("0x00006a4049a70212e50778047963facbb4219773a5cd579a8b561e0f5be54c29")) + (536000, uint256S("0x000067f76538d777945b49185b06707bd205b7b52ccac3734b7e2f4c7ab8a4f9")) + (537000, uint256S("0x0000749689869c525f2950a7c505c33931d9452917d3a2385763bf4d2d0741fd")) + (538000, uint256S("0x00006325cd66e6ca1557bb1793fd082cb18f623951393e1e4168ac9856d33dd3")) + (539000, uint256S("0x00005153466c7801b3b03be72d50615cda701b8caa8e4f800e234c4413d66368")) + (540000, uint256S("0x00000b8dbe1fe69be0c9da5dc22153a6de62d31971e11b991fd69485a81ecccb")) + (541000, uint256S("0x00005019c785dc1a8c9cb87116db8d66e3274d6f5442766e8d3ec903901544c8")) + (542000, uint256S("0x000023728297092f786127737d4a1567b0c2a25c6663703c3094a40de5a764e1")) + (543000, uint256S("0x00003f358514ab25f549124d13d3accb6c0a25733e7f0063917db8883c392151")) + (544000, uint256S("0x0000575c64c3dc7b4f35b4dde172e203ab295be62ffa6d45be6dfa21b0722ce4")) + (545000, uint256S("0x0000500460a844904611820b3aec828f4ae81241b3c1cca05e54cdfccb7afef4")) + (546000, uint256S("0x000074299d0ff2bf246de95724f23ed309e8b9d12e1b126b45206edc7330282c")) + (547000, uint256S("0x000026242bb192f9b1e775072362ee7fd81eaee84ebedc0bac32de3eb3d1964d")) + (548000, uint256S("0x00000433fbda0af11426e98584cab293f1749bdbba31673e4b2213bc9f47d0e1")) + (549000, uint256S("0x0000210248aff1d6d175bdf2ce9f79989956c13bd0c3c8dabb3c3d3b0e06a3e6")) + (550000, uint256S("0x000029c2f399d04f9bda73c132727d12a5c101f20afd7d7d020d5abe8f35d2df")) + (551000, uint256S("0x000084c1cc26236704afd8ae0fb3e6e8b4bf524762e0397650eae55c965136ab")) + (552000, uint256S("0x0000400b7e02ce71392f6f56067397afca0d5344bd5cf5a135739bcf9c02b42d")) + (553000, uint256S("0x000056d0ba072d5e5b8bee481cf580756950be0196e0c0bae131f08effd0011a")) + (554000, uint256S("0x00000856dd4e8a4841b2065c4a2a0fe3c05d66a3f42d53f6850812d58d033e14")) + (555000, uint256S("0x00000cfaee3ce417fcb3a3822da63cea501e0386485a74eff5f22ed05640e871")) + (556000, uint256S("0x00007c178577d145a7dff1fcf71f66d0207fccb9ac3e36bef6d64ccb6eec3508")) + (557000, uint256S("0x00005c4a091b3868f66be76d2d037752059990ab9ae6322a2007b6f5732a6690")) + (558000, uint256S("0x000044442536c02259b84632d7fe6ee73d76cc88cf4bbaab105e8c238b736c36")) + (559000, uint256S("0x00008593c169a4cabf0edee91ae842eb8cc1392270ea8dc9553000a07b5898d0")) + (560000, uint256S("0x0000437b6d663bf1bd44299280d96559c7fceee80dd15909bb430f04169e75e1")) + (561000, uint256S("0x000007d9df6ef7fcabe7e09f06ca0a23b6fce4d0f447b198e4be59246317275c")) + (562000, uint256S("0x000075f98a0c6610b87a01d52621d19d03334e0463bd29f3809e4450c2020a84")) + (563000, uint256S("0x000044a41b5d044b16eea04c7638c49e7cc47157efac851ece0e4d4379302b22")) + (564000, uint256S("0x00003c0f59927b1fb11bee07cc24215ffcf790450e0dde36e7a11e3d81614107")) + (565000, uint256S("0x000077a9fd67eeeca0da1f6b33af856717f9b07867dd615ec03f5f7f228cfbfd")) + (566000, uint256S("0x00007f2b4dddffca860200c50e2e6b44470620a458b98cca605e5789605bc211")) + (567000, uint256S("0x000065fb1b7d7335a0a517ee6cfdf59e57da3b3ec2cef987cf187664a844a02c")) + (568000, uint256S("0x00005d17458233dd11128ce73ef85b1724eea15df792162a08012d08830a815c")) + (569000, uint256S("0x00007c0be6c32678fbad87e682353f63dab380ec92908384abb3baaeb6b6736c")) + (570000, uint256S("0x000070c8008bcf3c2edeb60484503d4f38a6c1790e7a253173edd2fbb3200e8c")) + (571000, uint256S("0x0000121eb903f4281a190384a1aa2a829bf39f26e9691c0634f714919eda806a")) + (572000, uint256S("0x00002159746ea264c72259abdc4c1ab7bf97192ee46b4929ca9072a934710b9c")) + (573000, uint256S("0x00002b3818ba88554534bfc60577ede0dfd6bfa52b3c1fa09a6ee1c5637c8e99")) + (574000, uint256S("0x00000d520ac757f24b221cc9226edcd4d156869c4ac0f08aae15b650a2d2b02c")) + (575000, uint256S("0x000001a04bb7cdee2e607896d5cd735c5c61eadae55d07bab65e417841c675b7")) + (576000, uint256S("0x00003bca98ec02fa0de5c4e78505a323fc544f375e54953ac20d8eeae95886cb")) + (577000, uint256S("0x0000630c7321fdd6d994f70b07e177a047db6986c57fd2bd241801f104c0f313")) + (578000, uint256S("0x00006315654c3acb5e6e71119ef1e9630c545ef0bbf669b6bc48904522c1536c")) + (579000, uint256S("0x000076c2e9f8de87847422c52204cc3921606e7a5afefbe0eecdd511f5f89d04")) + (580000, uint256S("0x0000313f09d83c59644907ca6036f88f82b2bdbbfe5dc91c248a7c9b786dc9fc")) + (581000, uint256S("0x00001bec9efae7cb616e3fa10a633fd77c98f0a0e7994ef34bcd961f0594505a")) + (582000, uint256S("0x00000026a23469d49f5b5ea59211e409b1a2ae9ca9201a32192fbb302388da94")) + (583000, uint256S("0x00004502f499f32f957e83df9a7eea61dbcc5e278acae5d3d3e989957d3d71ad")) + (584000, uint256S("0x000006dff519a0687bd2318d8df706ec23eb10a9a65741e100da90cb7a24c4ae")) + (585000, uint256S("0x00000b114050e479b4647a151444f5f1ebf27b7f4ef0e412225a83d5c0fc872c")) + (586000, uint256S("0x00007782b6fddcd66108cc537e601c27c832406ca947c7877d2fbcfedb119aa0")) + (587000, uint256S("0x0000581ffc434077e9b7df1b1e675a9aa98f7af48a524311eefc62185a96c341")) + (588000, uint256S("0x00000b58b2f21f316a7a424249a5c59e086ecd70d77d1e29bd0fd61515503f07")) + (589000, uint256S("0x000024252a8712b710dabe5aca0fd01e4b336812c7d3620d1f48f2f83c9cde9d")) + (590000, uint256S("0x00005d849ece31d523ec22768684fe8f06826fac681a5e53515799dde5f3c47e")) + (591000, uint256S("0x000066c09b394c4baec74a86acb52ba4133f282d2687ff844e80d1267604b2db")) + (592000, uint256S("0x00000548f8f684f26eec12c2f5ccd8825a457b91d1c4075bc5af79e3e0b733ea")) + (593000, uint256S("0x00003b6eb0b9e00cee3a2c38dfbed8a4eb50c22b5794a55083f895963005fbf1")) + (594000, uint256S("0x000052fd8efae2975a9417575a3c103e42531480430b728f88014c7a49862c70")) + (595000, uint256S("0x000019f7aa5bc508f356fb6b0e25deb30d94257fe302b573f65b908f0dd85db5")) + (596000, uint256S("0x0000551a4c8000f46d4b78444060c998708c20c3c38558886347e959ddab5d71")) + (597000, uint256S("0x000008a3cf44d248337fcb5c2edcbbe99e95de78a8b814556c169c2aa8829e58")) + (598000, uint256S("0x000040de5f2767e0b8517a2d977f63b3704a9e3a73ec3467c81d7d0e5d7bbc2d")) + (599000, uint256S("0x00003bbcdb4fdae10fbffee91333650fc529dc32caacd84e7e3399fb89cd161d")) + (600000, uint256S("0x0000436ae9e88636c65919c5966f9d34a31dc4b65eeaa11f0da4f0dd1dee9149")) + (601000, uint256S("0x00000dc5d8f2ba8821342e3579deb326cfbaaded887d33af51c40e3392e6a4f7")) + (602000, uint256S("0x00007b2aafac9fb53cc6ca0f1d913b34195b5fbb6a2e9109ebab67ba0add21d6")) + (603000, uint256S("0x00003b0cdd0e712cde665f24c0c7ad591618a573dcb59e6f5009005488f8019a")) + (604000, uint256S("0x000050fca9bdd4e9be9dc5ab7aba2102e8b7e8ba8752367aaf1f1acb76573a10")) + (605000, uint256S("0x0000433a13ada8dd84c8e1a50b01aec369596dc15275386b0145a7ac519c6c20")) + (606000, uint256S("0x00006ef55f58c64cd7293898b3ed065129558e0cff65275165392f629908ef63")) + (607000, uint256S("0x00003228eadcd9267b72ee72612b9dc9130e0afa7ebc1ed15e4bdb4dd0bbfd77")) + (608000, uint256S("0x000086b1651bcecc84afe5716e46847d43b0ba7c2e5c4413f40b671683511bf2")) + (609000, uint256S("0x000034966052e04561f6bfbb389dad01bea47d8cd44a6820618c921f66e008ba")) + (610000, uint256S("0x000034a883b6a81b1532959b63a5365343362982bbf37cadcff99d8e60d8e825")) + (611000, uint256S("0x00003aeb64f96418cdd4d2bae7aacc7ad54316bb65dc6cbf38d41861c2dc666a")) + (612000, uint256S("0x000049f102cef61bae1cee19bd50d4f37f90f3e2c67b11b556bb2b02bd3976e3")) + (613000, uint256S("0x000077fe70c0c0e02ed4c99771cf2942ee312569fac2c728f271f17b425a3609")) + (614000, uint256S("0x000063786b5555a2ac21002d3afe8e5d7f548965a60abd146e75c6056c790a25")) + (615000, uint256S("0x000022495d08215a51e3d1209fccb4423d8649ea23e474d7c72fd7bdc6175dc3")) + (616000, uint256S("0x00000544e44551824ac7f2491ad19b2463ee63cf28fb317a21811282da68d0ea")) + (617000, uint256S("0x00003edd4418af458ad224648d1d2b080e5cf76519836d6ee39fb3094e9e8d08")) + (618000, uint256S("0x00008b7128113a91fd7c7230141de8ec0613d0fa502caf384c4026a4af430b0c")) + (619000, uint256S("0x000047f2eaf7db232149e151a714f2fb550b8a8ba30d5b9382dbf367558543c0")) + (620000, uint256S("0x000083e3d11d57f10ca889db4f39a5a1ffcfbc779fb147e2d78c003488a56937")) + (621000, uint256S("0x000054669b9ab9844d3077b687acd5a6ffe41dc4760d24a0b349adc110419cd1")) + (622000, uint256S("0x00002fd67bbd742bfd6ac69836c6e66dea835687a3e0254ab4c2eec0af6013bd")) + (623000, uint256S("0x000058d8ba58d2bfbf9a0b2281b9fee517b7286f21c188b74b70a5e3e31538d3")) + (624000, uint256S("0x0000187c49df0bd5f0b0b959623dc88d54ddc0915631d9fb448c6a1489afdccb")) + (625000, uint256S("0x000078124e3a14bd08b0a1c8d6d4cfd94f1b7215678d2550afedbfcc0b238430")) + (626000, uint256S("0x00002bd802b4710dee8a3f7b79ca7ee7ff8229abfdd75fc1b999e8d3f1214068")) + (627000, uint256S("0x00007e54bad62029382c902d40cf5d32b24f944528985340818dbf5d2d8e63ed")) + (628000, uint256S("0x0000827334e651c03abe2f1306a90e6db15499115d095f9837bab698a90147c6")) + (629000, uint256S("0x0000796aa83d5c501960482dd2df7f7c2046bf255f529d229b4037dac1dd9c64")) + (630000, uint256S("0x00003cae63886df0b0d10fc0915289bce98117b17c1bd5fc4e005f75370c470d")) + (631000, uint256S("0x0000367ceb36052ca267cb71126c395d52cead56b184d97b8f1dbef6c31399f8")) + (632000, uint256S("0x00004a25472d93f6b45b52f40cbe4f96b6645dccf2054742fea6310c5275ac62")) + (633000, uint256S("0x00003e39e64bcaa6e2148e63fd4bf4848ebff537bdda354106c6611d9ed4a661")) + (634000, uint256S("0x00008752aabb421803dad99ff286b141dbb8f9448034b9bf123163eed60d54bc")) + (635000, uint256S("0x000011d4b790a0d94080ff1ff1d75fe3a1371c1117f72520bf71e29b3031e53f")) + (636000, uint256S("0x000039d22dee92b88b9dc801fd80a64bc1a5327323a7734d86b6fa06d5118630")) + (637000, uint256S("0x000020ded38a69de8d8f95a0429aa22f6ffa87777421d7c1e7812af97bedec5b")) + (638000, uint256S("0x00004c7bd96e45c157f47614bc1749ea05021c4c0568556963d3455a328ee8b9")) + (639000, uint256S("0x00004683154e1dd208bf8e263f7096fe65b62eb12d2465a0bdb0d3fc3e68dda0")) + (640000, uint256S("0x0000266d50614b362c3c45f59a016843277cfe0905db3cdcb15a2accd89b97f6")) + (641000, uint256S("0x000033b482977874fbfcd3cce372ee98b4cfba672f00a6c8302260ade7a864fd")) + (642000, uint256S("0x000066980f706965647570772006a43a09f3c1f076683ca8ab3f65623ee90f1b")) + (643000, uint256S("0x000029446689b15ef5cab50e541c96b863c7f97bcf491652ce750e7c928bca62")) + (644000, uint256S("0x00006a7242707969e716d5b184689b1ffde9a19e109df7366f226e24a0220657")) + (645000, uint256S("0x00005f5bdc31fcdd4eb55a02a48a8b73612def26563724a959fd759c592816f6")) + (646000, uint256S("0x000052f597ec93b183e4606bf9ef91f4ab65583ae4572b859326a0afc882c173")) + (647000, uint256S("0x000075ea6529ba397732bf3772330858424e8524d120dc8bebdcde0a002b3fdb")) + (648000, uint256S("0x00006b277691edea33fa3ca4f23691d0a7182f8ebcf9ce00d780abc3cd357b47")) + (649000, uint256S("0x00002c5180f4558a08f9af7dfe25d7b9f0b766c9703bd73f0aef13fde010123c")) + (650000, uint256S("0x000051cb54c7a3308052e8136db2c9615c94bfec0979697f251f20847cce4963")) + (651000, uint256S("0x00003e2d493a06c223e31ccd12e3b45f6d099bbc55b39cd0672d9f0547c02411")) + (652000, uint256S("0x00004f95122c592d3a77071f0ea04e48598b211e95ce69bbf37107240be5bd4d")) + (653000, uint256S("0x0000564d9bd27869d77d874e322b3eb4f88422b7eecdd0f0f1f8846b16df693b")) + (654000, uint256S("0x00003847ffd4976a5e54670c7f226a37cd1677d80aa6d9d23fcff37ee385c84f")) + (655000, uint256S("0x000083c80ce350c84a27b755f8620d57d1937dc2171b22063abd4a43335fb0a1")) + (656000, uint256S("0x00004bee79412b8865ad1bc7d3a4bdf6673cf439faf7d06ce4c25e18278beefc")) + (657000, uint256S("0x000053773f2064b2ef13122b88d9f8cd1403cb5f690480fc8358415c7c6342aa")) + (658000, uint256S("0x00002002beb709452d8e6674e7e202e0767845252dd09ae22277447c580f9466")) + (659000, uint256S("0x000007d0ea4b6b588610a2d8e7e41b1d8bdb788d1b36e16bc1970a30eb7701c4")) + (660000, uint256S("0x000040122c9700917a83fac1ce3790ae0a31d33fb1a9f7327d5d60932c2d61a3")) + (661000, uint256S("0x00007b94c7d9d8e37c4c3f1c244f662fe979fc50a93a10a0648e50658889c479")) + (662000, uint256S("0x0000509f00767d1b1580e946b82fa7da0c4f9d34bc3dbb0d291d2c9b0266e498")) + (663000, uint256S("0x00004a609cc9b256d7583d3a19700f5bcc1b6f3e99ccf5d25f645f03bc4a9299")) + (664000, uint256S("0x000005da1969138a1bc8cc763aef2e4bc266f447df0fa90e70b893b920bb808f")) + (665000, uint256S("0x0000352b38d8442ef68b046d14dc33837e087771ae201dcfc06f16257a65e5c0")) + (666000, uint256S("0x00002ec8bc083ca9f9855301ebc2cbeab83e63630247c74134b960c3e79f58ea")) + (667000, uint256S("0x0000322a13f6c6b53d290e5810b387ef622108565b43705653dc7194f712f7d8")) + (668000, uint256S("0x000052aff29d93c1e52f3bb230c082fc5cddfa11a8f6737ed7369c4a205a1eb1")) + (669000, uint256S("0x00008f2b1d5f21b85d42456a4d1adf6031effc7288725385cefb2d380045eb98")) + (670000, uint256S("0x00000487b1a11a5d1c671e788d8ec240585b35d43e67f4a157c95d2b874e05e9")) + (671000, uint256S("0x00007a4d20bd194b58b0d8322b40905687b8625ca019396f281cc69e236dadde")) + (672000, uint256S("0x000065589b9a13c03084ca14f5dac85f79ac25020cf0bfa60b46eede759d6b1c")) + (673000, uint256S("0x0000496ff7888b6343661d8939faa966491e3a5fae008f265a25541be94811df")) + (674000, uint256S("0x0000827374e8782d4fa84e8dca701696a237fa437c211ca2a1d6eb0a3a9a5425")) + (675000, uint256S("0x00002cc1f83c1e50155f7eb8a587b446957105e3a439cfa39231aaa430b181c3")) + (676000, uint256S("0x00002bd82232186baa40f7066a72bc1374a37b9d2daebb1cb45c702881d53620")) + (677000, uint256S("0x00005af1e66043923b5a998e2e10b07b1923761c4eb6a9dadc06ba35a9cc05b7")) + (678000, uint256S("0x000050e10a55ea1e814af34b1a6b948b1862ef5d80095d69576570bb4d57c18b")) + (679000, uint256S("0x00000fbfc06c8a4063e9269731d3af840215667a2a34117eb6e792b143303cae")) + (680000, uint256S("0x000068e3988fb8e32f2aa408d3414cb9da9748da7d8250fae08dc246317ed65d")) + (681000, uint256S("0x00005255d2baf40602ec07b09486bcb5ef5b1272ec8b2d7fa0fd8a7e91498e32")) + (682000, uint256S("0x0000385522458cb6b4dd4a9b8f651276d616c157e9892e8159fe334bf1e41ba5")) + (683000, uint256S("0x00007f98e027180bfe9244f6a34613835fbf242b053e4d35c4a5c7fe275fd5ce")) + (684000, uint256S("0x00000398b4a299f9e2c2259eb9caf37b612f8b9921842ecd6459104a5c1728c7")) + (685000, uint256S("0x000071fe00ba95387fb8dee3185f07698f1bba98af44af444ebe10fe0222d506")) + (686000, uint256S("0x00006aad8ea1604cbc2bf35ee899ff71bf43be5c7bc38a528a69dc25632451b2")) + (687000, uint256S("0x00001c5353578dbc2433a6bb899bdbf8838e244f6fdac167736043566a5f8b9a")) + (688000, uint256S("0x00005673acc55810e796f5e1202aaf9a219cedb78b22500a367ebe4c21f862d5")) + (689000, uint256S("0x00001a403948a30ed565fda094be582636947a6708562dbae3d7806842a90f69")) + (690000, uint256S("0x0000084caa9255d78ceef4411cd69d319e78eaf98f5062157944682526eaf889")) + (691000, uint256S("0x00003c6d705d2b55087b3fe0cf00fbe9235e04faad5f67c6041a35e0c95e2233")) + (692000, uint256S("0x0000082319d11fe87e8c905b1381fca11c56c94087c8b83a116d0978a9b96713")) + (693000, uint256S("0x0000054e84d1ee41de438f81e98efa858c5cf350a7e4bbbf91696ec018afb5e9")) + (694000, uint256S("0x000059f4bc84ac5a4d1692b7e39cfe5637048fc3c8dd5bf11f9638deeaf2be4a")) + (695000, uint256S("0x00004b912acca69c8324b152c63be6c56b6c96616d8670e3313727de3fdff809")) + (696000, uint256S("0x000060812d53e1948414d700505cad3634dc100c9b4c943919fd2ae2d1f32c7c")) + (697000, uint256S("0x00005aa2aafa94b759c9db1042a38482b8ca41135322300b7ebd95a39db2950a")) + (698000, uint256S("0x0000209fb13efbb40e6f5dac563a53d65becbd897da138bd95166ad3427c4476")) + (699000, uint256S("0x000044ba748f6da341af23bfcf6eeb4c8fd525dd30721f2643eaf63cbfd7723d")) + (700000, uint256S("0x00008edc47c5bb08fa7e565022caff0de4735bc6b3a50ce6ce50df4ec667700b")) + (701000, uint256S("0x00000ded42dec98258c983df777daafed6cfc99f0fdb08afce18b5bec2cea0d7")) + (702000, uint256S("0x0000524d8b89cc67fb2cb824ca6cddb3eef75c3dfe1b4a82c5f84a438af205cd")) + (703000, uint256S("0x00004322186ff4b1a342fe99bfdfc3789878d47313d3eabc0995c1550ef0f34e")) + (704000, uint256S("0x00002c9f1dba514d11cdc2b61b231b658888ab4c418780c1ebbd83bea65082f4")) + (705000, uint256S("0x00009322b4e8212f5ebdcb2ef4847a9d02523aa6ff9d9e4a958116365773ae70")) + (706000, uint256S("0x000095885e9010d3b50f941fe7b4985fbfb28b995b85e7b74923624d9eea559c")) + (707000, uint256S("0x000028dc64df302c6fa105d9eb10298072a25de66cd38c449a0eb3a34a8cc75e")) + (708000, uint256S("0x0000052ffc7e92c94142c99d59930a1bef10ac5239f756b668d7e88baafcd817")) + (709000, uint256S("0x000030ec146822e74348d354ccf6ce82eeddc547e412ec5f3c471c8c86c5b6d0")) + (710000, uint256S("0x000078982d79cfc589556fb27f548885bda5e146b1327bc5bdc0eecbb58c5f46")) + (711000, uint256S("0x000064bdb4bdf8130f3b4238a5f34a93e30828707edbe44d709da995d6f3040c")) + (712000, uint256S("0x00004b0c9fe52ef4864771077d13d56154f354a4d17d571a2f8eefd7ac15f2fa")) + (713000, uint256S("0x0000305af605f5af748bbb2021bb68aa936662c7b1f1f12f002a9f2b1ff4b804")) + (714000, uint256S("0x000001b9360aab6238bb98306a33349a56605096432389e1ec8c4c17f52ac909")) + (715000, uint256S("0x000035a37dfaf08583796f0d6c9fd9187c8c5ab7f4ca72d792c148dca388b1c9")) + (716000, uint256S("0x00000cf4b5e61baa6fcf3599c263041d4edbc26118610f0ad4ad7285cdf6e8c0")) + (717000, uint256S("0x000006b81c040c5ad7538726dd735298bd319ba41021d15eac33d6b3d9b3f49f")) + (718000, uint256S("0x00001851ef32ed7435aa45e983718409ec0451516a7c603261028329fc706c2f")) + (719000, uint256S("0x00001761a4179610235fa0215c6f96e899a9a2b44e409b89bd87da1c974e3c4b")) + (720000, uint256S("0x000048a83b4832a27349ebbd2f73414813c495eca71ae7db3db46ab01606ad79")) + (721000, uint256S("0x0000623d0cb4c9c4f8ce5b5e82a5a91c11526a49d093f779d21dbca3f10ca186")) + (722000, uint256S("0x0000230ca89bbcab6f867b92991eefb8d7eaa999c1bc3e88ec20154a242f2c04")) + (723000, uint256S("0x0000759e37d650242835dd67827cc10f66dd664f078344e1689f51d75fc57daa")) + (724000, uint256S("0x0000173e6ba51cb3b8c239eff1f3e5f326304c1e60a0a75fc126509deb0a4780")) + (725000, uint256S("0x0000048dd2c527da42b919976bcfca2295f0c7606b9adb8c3e81f0d9d8cba6fb")) + (726000, uint256S("0x0000331afc3cde5cd724c02587cde0e628d10f5cfd4809fc1edef72239944007")) + (727000, uint256S("0x00007bbf39744b920d3edff5941fb4d1f4ab15f3c31cb61252ed6f16c921e5df")) + (728000, uint256S("0x00003117719719bd2adff98da1e73acc7b66e440c4d29a8e983bd85044419f9d")) + (729000, uint256S("0x000025e2fc0eb94bd418a21fdbf5f90c717bc5cbf6e92acac3a3b009b1a3642f")) + (730000, uint256S("0x0000592ff5248f0fbf7ef9e39e0560f95975803312dc0d7c8de61cb3183c452b")) + (731000, uint256S("0x00004fb3099863dcf7c09b6ddb6be43357ca72b848b2bc4af71dceb6210ac87f")) + (732000, uint256S("0x000001f13cbd71460cbe1720519491bcc0e92cc00787474af7a26f5e5e31eccf")) + (733000, uint256S("0x0000206b824d514c9fa1ee4da1688765b92befde69427a925edb76207c2b3894")) + (734000, uint256S("0x00007ad519bba141a425208d02a8fa9c6356f079c456a37c593da53befb1e580")) + (735000, uint256S("0x000024bb3077ad1ee51ae6bf04fcd14cfc98bb0bf7d4eeab7efbec48c05a4c80")) + (736000, uint256S("0x0000500f718bb843769d11510234ffee56a6376f4477f36df4abfd936c982737")) + (737000, uint256S("0x000090258d994c3bb5f14ccfd7bcdc33c6023d8faea57936ecad8444df570c59")) + (738000, uint256S("0x00007d613b9ba29af0c2a6afbf3e869ad489802e405a2ae6d01b807b1926e234")) + (739000, uint256S("0x00002d798dd51d62f09cdcd8b04fd39406d1f150dffcd59197c72b5fbc4158d6")) + (740000, uint256S("0x00006901558a74158f7b154635dc1ca20db88135ad4bdf5a27b7110e131a9ad4")) + (741000, uint256S("0x0000797ea4c8080df06c8bf0385e73114ada78520312eed1aac310525a665d31")) + (742000, uint256S("0x0000598add4be1345b741bae74cb53cf354d70ba9308023feb8c44f3edbb75bc")) + (743000, uint256S("0x00000c4cc674e30db554dbbbabad0ef19e7586fba5846d669804662871b4fc5f")) + (744000, uint256S("0x00006292a417fc4053bc2de0703d2b6848a281e7423eb67a56880aec7fd9032e")) + (745000, uint256S("0x00005917cf49f943ba8f7b301601f4cd2ec19e612da8d1e55d88f7fbd07cd4de")) + (746000, uint256S("0x00004ca89cba20b7735cd3bfbb13d47ff639b708c44a61c1e8f8208940510a11")) + (747000, uint256S("0x000001af21f0300a4ea047e6c08594190be99a87bdefc915d78263500bad653f")) + (748000, uint256S("0x0000193010ce9c9ecffb9064c8a2ba4977056e664f0f0f11fea044fe37491331")) + (749000, uint256S("0x0000671675eb405106fddf7b1ba5c3aa58c3975f02ab22215e6a13875b8ee165")) + (750000, uint256S("0x000045d2c9dbf992768e4855d0b533c8066a636c72773c4e9de29c167f255f6b")) + (751000, uint256S("0x00002f1de17d93f381ec118a265f2fd2cbd3d6944c2ce49a7366506827e6d082")) + (752000, uint256S("0x000053b86c2f9e8cb9c91485b2e84972902b2ccc8e26ff7b370a98e0f6ebda22")) + (753000, uint256S("0x00006120dc67344507cd5df80935e6a5ed7e0d6517d26ad858f3e7c3cef14760")) + (754000, uint256S("0x00001f51cb470c709aa77787bc57045ba2fa6c57b840269ed3978293c8830135")) + (755000, uint256S("0x00001575b45b0b20db4e248a8d64525c805d41324dd44d974f109752b9a2750a")) + (756000, uint256S("0x0000287d75aaba029c56d0758655eb98a8b6976257ac2a406e84cbf228ba8689")) + (757000, uint256S("0x0000236b884919dd0a00062ecb138278d92d1532ac0aa0b4f5aa8c6bc3cbe87b")) + (758000, uint256S("0x00006595633e8b84d40afcd11e036160edf30a155cf6df1eac442653ebbf20e4")) + (759000, uint256S("0x000049967003dd0d3ccec6a67ac9e71979d2baee621b7e00b2a79d6e89474bc5")) + (760000, uint256S("0x00003bed363545a3db6a54e6ed60e0494b73e686d138fe60b87253cf64e14b49")) + (761000, uint256S("0x00003b9833902363bab63cebbd86510b022c3d211bfb9357cb16d9a036306317")) + (762000, uint256S("0x000059c89172ecb70a4a599dc4c6d0ece81af2d09645d7e163459f76483b29ff")) + (763000, uint256S("0x00006b73f910a7495f392309fc49c048fb570d354d6f68e1b55a83fe585d5c0e")) + (764000, uint256S("0x00007d0f42736fd57f9d9b28e2a3a014c1b70f39504464f78ae56345c40cf8cc")) + (765000, uint256S("0x000064ac901cac48d977c53efdba1a5f6252c8897a72001d6288a41cb50ea60c")) + (766000, uint256S("0x000020a571e231b3afe577748c0e224df57a37738f4add606efe7a0b28a5e075")) + (767000, uint256S("0x00005f17269fc96784a2f146f5aea75eda1da7e0e863b71d79bc9b491a6610fa")) + (768000, uint256S("0x000014f17adaf27eeab1db7dd1bb25a03579d042d403a8c05585c819d3cdec49")) + (769000, uint256S("0x0000047b0bd5ddb77a5415d5a6c3ba79d9fe71f452cc6264c1fd56b73af74383")) + (770000, uint256S("0x00007385edc0ff7a856aa6921cf5fe7860e915a5d46f6c1676685dedcb8f5271")) + (771000, uint256S("0x000065889c31b9055c4ea88a55b6d91189ad310918d397b859063ae724ed1e24")) + (772000, uint256S("0x000007cf336cf1f316556473f4f66b9d6b716956960c0d9bcb9905540dafbc9b")) + (773000, uint256S("0x000043ae84959c8f0562a9b26dbd2ba02f1bde8c4243c74a0e770b50780c3ce9")) + (774000, uint256S("0x0000507b6b4ab724ad4c7cab6a80e18c728c9377fd4f0b2d0fba863c50b55d4e")) + (775000, uint256S("0x000010825660f5abb7aebb3b60d64a62f5fc83ab259547f46da9c27b63ab5eea")) + (776000, uint256S("0x000013b6812b878b5d05f8f4f5d9b72f14a6dfc8f3c62f522965d4b76e773fb6")) + (777000, uint256S("0x0000029367c70dd7cc0a2561e5e02a608e6114fd5496da97fba27426187eb42d")) + (778000, uint256S("0x000036db0575186a39cdce9e74dd287bee6c2de0967e2e5d894203425284719d")) + (779000, uint256S("0x0000442dcdb9eacdd7e7891b9aa1a59960109bc31d4d74c41735d92e98b8fe1a")) + (780000, uint256S("0x00007078727c38b3dcf92001100fd25f90feede5e8a908ec9607b112cbc073d7")) + (781000, uint256S("0x00007540200124c254bca2750b16e27df38e1a6ba50a29bfe53abacbb8891446")) + (782000, uint256S("0x000058db5be4534b5409192b5fb9fe2c2f39da12518c971befa98961583776f1")) + (783000, uint256S("0x00005a1a81a2f564e1c8939c37f535bdd8e2660ccfaa70d7d1cdc95dd51517b0")) + (784000, uint256S("0x00005cc0c98bd06589af2d3130bf409b4eb85391cf75616fae85aacd46d036f6")) + (785000, uint256S("0x000043c62dcb4306dbc4cef5d778a65cfa70c539eff73c3f8f26856a49fe5eae")) + (786000, uint256S("0x00006596f5f4cca692cad747c1d883a91fb92dc4405a26f071e031c3eb3bc3f8")) + (787000, uint256S("0x000038db38f8e3e341731623b7f0129d7cf87d400e59f2bbe016caf6f5d270f5")) + (788000, uint256S("0x0000125fde93c4decae31e759251dd899d1bd1d3106b4ccca91ad8654c59ea67")) + (789000, uint256S("0x000056fd200edf535cfaa34da9b89512f7027706d579f169237b9b28b7af8b84")) + (790000, uint256S("0x00004d295243452c2946e9205cf3bc59475287c1718676f6e50e67eb9901425a")) + (791000, uint256S("0x00005b0fd53c0c8d6ea717007cfabfe196eacbfe7168bd5b0f48097e6d386db8")) + (792000, uint256S("0x00003e52994334723516d6f860838dafc1b073b58a60a52ba939c2bc7c0aa2aa")) + (793000, uint256S("0x0000658d89055152ffa1c347d3637fd9d43cd3d56891eb779af8f3df705f725f")) + (794000, uint256S("0x00007f557f547b8f0283475eac5670923727f9fbc8bff505ac45f87a631b4722")) + (795000, uint256S("0x00009859a0766efbab8f636bb0558bcc425a4aca527662bc24fed7769de654cb")) + (796000, uint256S("0x00001ddb44be45a829f3a11dfcde700bf73666590a35675e8aa675e27b57912a")) + (797000, uint256S("0x00004b21921081c50d70b966de583c939b1e65181c268fe352f72d3638cb44f8")) + (798000, uint256S("0x00001ad3dd046ec41fe0c22dade01d9c99a01fdd173788606361f949a9fdd320")) + (799000, uint256S("0x00005bd70b917273f3824d52813b15b7ab5fcea8ec309dcaa633c02f1705d3df")) + (800000, uint256S("0x0000640fc41f9dc199d59fe773bb333c13dc2d908ce7ace0a1d066e1fea1e13f")) + (801000, uint256S("0x000020379973ece3b4b7bebd8b01d2e6bb5d0a20ecacc6dfa0cd3237c65cc51d")) + (802000, uint256S("0x00000628c6bdad96cc7514870f5cba7c87052e94c2ce89bbab6f504fcf5044ae")) + (803000, uint256S("0x00007030da49876a11c9987be43f81dc30b0ae0a21b7d31d762b8ca980ef02b8")) + (804000, uint256S("0x00004fcf77675b057bd582cf4c2667f2e2858ff6f70b904f1cb955c6cdbb6dd8")) + (805000, uint256S("0x00001ac86e1c48ba3efd9838d3de04c3a2eaa561bc41597cc0698cb18623bb97")) + (806000, uint256S("0x000009c0d52ea3500e4d7a2aa88e51dfcf3e766da92a7b3cf36377bdecb985c8")) + (807000, uint256S("0x000019de53b77c617ddbad1eb5bde1548519075f5f8cc3f3ce812f99a3c78fb3")) + (808000, uint256S("0x0000711e70d75daa3fd971fa5712a2c43ff7c27856a195a1139c932c32995219")) + (809000, uint256S("0x000053b323a89bbd37abc5059868692f9c2df68431a4b781a36a253fa6ad721e")) + (810000, uint256S("0x00002735c70731b9ed94dabfd5473144a535af478ff04f07e7a198a5062c6516")) + (811000, uint256S("0x000076c3247095eec378a1f599d24efdb39aff39f57f954e797d88f82ddb49cc")) + (812000, uint256S("0x0000295c9fc0ec0403768b02f2310580a25ffa7c1bb70f988ee7d00e79aca30c")) + (813000, uint256S("0x00000a89cd18698c34e77938f982f1041177a3ade727bb0454dad444f55d1d47")) + (814000, uint256S("0x000034b41e2142ea9084dca685a9f6c09ffae63e087b4211350a8aeef5b894f9")) + (815000, uint256S("0x00003798ce72491fe10acc35c4d2252b11e70f41bde2c23a9f5d39f62156363d")) + (816000, uint256S("0x00002f241d3f9ade027e2cf64b1d33dfa85412ea01e59cfdc0f95a17254ae40b")) + (817000, uint256S("0x0000290acf337ba1f9e654942a7185693e6eafca61f4d91e088f63fb1b699b44")) + (818000, uint256S("0x0000098b7241ca6e928945f6f0f6cca48e229f6ec429316d6d16a2821176d0e8")) + (819000, uint256S("0x00006e719dc18f28f96bfba7bdaaed3b150a357a8b0f5cded43d72f18d49e835")) + (820000, uint256S("0x00001df952c416cba92cdac45913475a1e2494e95a4190960e334240efa3d2c4")) + (821000, uint256S("0x000011cf917ec5206c48561b3f860d1d1fbbd247caa9b0801b446541c74a4560")) + (822000, uint256S("0x0000512bb99135f616dd045a14650df532434f4db5d0f1ec0c8c01949dc84c12")) + (823000, uint256S("0x000026b71e291a93b0eab69e37e1146c51bfb38634c6150e78f14244ee202b32")) + (824000, uint256S("0x00001db40132c5a7be5d566d2e2ea01d494137cc946e60a195d90fb67494251e")) + (825000, uint256S("0x000067856552cadc5460d379999008d307233511625744285ec13b0f61289ef2")) + (826000, uint256S("0x000011554c5b351623f70c195df2e94d519d606d7d8c3fe52faf8d7cbe79f51e")) + (827000, uint256S("0x000026404e235fbad5217deaa05cdcefff97c1bf03d3936b6ef798dfbae84a59")) + (828000, uint256S("0x00004f553a5c9f4d1740631a9dffa5bd4e93890485295a52bd1f5ba36868fe22")) + (829000, uint256S("0x0000218e741ad6e0e775943a954186c9cc9d1cc116aefd4e7b6bda00184e5ccc")) + (830000, uint256S("0x0000313d0909651b5f2bcecccf811de988f06ba779ebcec92ddaf733f6e4b2dc")) + (831000, uint256S("0x00007b086c73e29f0bea8a298a2847f82f42f9630e5d1682fb235597a4b324a6")) + (832000, uint256S("0x000072b3999cf87b5c419633816719c80cac0a17891a8951ec1f714a521c2eff")) + (833000, uint256S("0x000075bcab0b6a7ade6eff8aedb76ce76a8f6b0a2580c520724063b61dff3765")) + (834000, uint256S("0x00003f851b1f2f7c6698c9e0806f12a9252ed41038eae2e31799c2eaf94fb76c")) + (835000, uint256S("0x00007549227d77254ff024b5e20d4bb366c569d5be6e4aacf268b73c0fafad32")) + (836000, uint256S("0x00005c3837f6537ff471f77aa1a0a9ccc70d39f91b1f36a686213cdab7a3bfd7")) + (837000, uint256S("0x000044c7c771ef1ee06f8856b48a93cb5a73f08ff2dcdb45d02e621400c1a5a8")) + (838000, uint256S("0x00007cf6b7d34c5e26badd7f02eb191e57764ca890eea70fee06b8d4a25e8af4")) + (839000, uint256S("0x00003c36acd2ce2c47fafd78ba3fba03faedc703290f52fa2a176387c1cc642d")) + (840000, uint256S("0x000067813b167220e4936fef9a0f283e56d6fc83a163fdc44b2b6f003f2dc660")) + (841000, uint256S("0x000024433e3ceb8b9310df1ee1824cff4c28147d9be66ae1cc946a4b3c6fe1a7")) + (842000, uint256S("0x00001e0fbc7a26c349d47b983369891ce7e321bda16c4ce5f01872aad350502c")) + (843000, uint256S("0x0000650dddac5532e8aa0fb7076301493ac82d743517fea3978e27e1bb2d1cf5")) + (844000, uint256S("0x00000a89887a2c3734664bb2ff20051b20772f3946be5700e2d5423bec4c8dc1")) + (845000, uint256S("0x00000c23bc1535ed29fe656dc1ccc23209cf90ca68160fce1861e53b8b7ebbe6")) + (846000, uint256S("0x0000388e10658ee10e6e8b84f8fd31f53f4327b89dfd9c0d345de3f8a99e60ef")) + (847000, uint256S("0x000076958ba49e7269957fffab7b34dd27a760d8c6607ff023506c86d43dd340")) + (848000, uint256S("0x00007d9fd506a29a41cb6c6564c6dca3086355f0283bac6e640ed3358c3bc3ca")) + (849000, uint256S("0x0000336cd0b1dd763d0f9975b2019e93bb4feee6d22d440cd2a74272fb2f33be")) + (850000, uint256S("0x0000612f3aff24eb07160699d27a4469a11fafaddaa323010e88bb3f69cc7316")) + (851000, uint256S("0x000022314332713634c34b35a699ae4648f7a09e175477f7475485068c6f2a87")) + (852000, uint256S("0x00001a7415c2a02b0e2916775d4ae9edc34ac803aedd274b1c925d78a212a295")) + (853000, uint256S("0x00003572645e601576800cdd55d6a58c37c5608cbb51af573e34a29c136bf870")) + (854000, uint256S("0x00002651664ff10eae80bffa2b28aeb93493fdeae60d230b581aa0bbd7885200")) + (855000, uint256S("0x000080ef07f534c70ffedc956fc3bd78951ab0eab50e776ed05aff2ebd75eb37")) + (856000, uint256S("0x00003b3872d24598dcc10849502d2b0a50daf6bceda6f707128542f96687fa19")) + (857000, uint256S("0x0000305befd21df66a1ad45ade766917ab3471bf7781e59d5a87ac0cf8bc1db6")) + (858000, uint256S("0x00006e093156dc22a333f21accb49b8edaf9aa60e49647637a6dab023717813d")) + (859000, uint256S("0x0000182f21dbaaafc38859083105b36905400bab818cf87abe5c0ed52bae608a")) + (860000, uint256S("0x00001999dd005c53141c1728f40bcdd4b7a528ba65b180567300979194b196fa")) + (861000, uint256S("0x00002d3ce5b2bf5af077430b51e5d3d9c0ae8860836271b6862168fe79056632")) + (862000, uint256S("0x00001529bc0df458d3e53abe27b51214a7796c590b324092d3dc8e610883f7be")) + (863000, uint256S("0x00004a63b8657b4880ecfa9e5b9273d180beee36da365e326d82fde2c1b2d988")) + (864000, uint256S("0x00004f8276429ef089105e4c90861cdbd03bbe0fd84447d768bc193a855d5473")) + (865000, uint256S("0x00003b51c77b529800cef1d47dd1586a7500f29ae92cb3b8768ca81f54ddc0a6")) + (866000, uint256S("0x0000294bb5e3779b42741d53fafccf9c32ce7467808966fc693d9dbe4660b512")) + (867000, uint256S("0x000074c7b653bd9a76bd1448298bd864ddf49511da82036a56086870abf9805e")) + (868000, uint256S("0x000051ea7b3d3e3be6f8f23e28756a69f2ce3c44e89dc698261fe6c43801a4cb")) + (869000, uint256S("0x00000d7bdb810c06e78497452fa6ad3477e76928a0e0149949b6857a6ee12b95")) + (870000, uint256S("0x00006f4e756f969adb221afdcddc65979660e39799a9a9103d9d883bcc4c9f72")) + (871000, uint256S("0x0000002fc905a1f7c67431810d1f14de0a2b8c3387bae141484820b1fb584ce5")) + (872000, uint256S("0x000032760631edb2b1999186dd75080ec72bb7217e3c9a206a2ed575abac6538")) + (873000, uint256S("0x000020b1577c9844e736554e4f22c0e01b7a4be8f623799b42780583f68df8c3")) + (874000, uint256S("0x00000593b9d731f4d6499f9674d69ba9e015284b1282f6f6d411cda553530a2c")) + (875000, uint256S("0x00005c62416a0650de882b93d2f713d680b5505b56b07118d402b51192a5c07f")) + (876000, uint256S("0x0000301509a3d2fb62a1878b3b86a8eaab42a84eac37453781c2cf712b2ce747")) + (877000, uint256S("0x00004b13371bb0f27014836f29886ed5018bf08572a27b7b5061c8a1acc7f98e")) + (878000, uint256S("0x0000156bd2d1088f84b7d3e46bd31ee5353a551dbd6a9f2db128c3f9cb67767e")) + (879000, uint256S("0x00001fd3d4255632ffe63481aeb2fdcc683df0b9135bafd15dbb309561cef581")) + (880000, uint256S("0x00008bc77e18736b7876d995db87837974fc4e723353a5339f52361bcceb632f")) + (881000, uint256S("0x00008f9fd5305b1ef6c11d58833ae85c6273931cd2a8b271ed7337e9007a12de")) + (882000, uint256S("0x000071e3325bf3ec8d64e489c0f4c0fc92d5fd79e6793d8240a3d0f8a9be63ca")) + (883000, uint256S("0x00000f18583203aa2b5211cef703581ff212c2343a2c92ee36c10cd695395958")) + (884000, uint256S("0x000074ce09839a1c518c0c9376e1ca0a61318f32f234273e7455de3a9c0dabe0")) + (885000, uint256S("0x000021ed36aed698ec9b35a34523b831c777014bbc87831dee4bdf613bb8cc33")) + (886000, uint256S("0x0000752fe0cacddb169c676d3cf4d4ddb3dde1c94110022c307d338153f8ae23")) + (887000, uint256S("0x000053d1d0fe3221bcfe061ee33346c9f6e067f6e383e5c18d4cd80d4a19916e")) + (888000, uint256S("0x00000e306f9c0fd54d7dcfde614eda0d1d59c3fadf3ed1a20552ce8958c74a27")) + (889000, uint256S("0x00006c8cac10dc846790110c28852de29754a56e3d182566c89916b42ba666f7")) + (890000, uint256S("0x000081163a16d309bfbce119c27c23cff28e99e2f5248d897de84a9d04a7b0c9")) + (891000, uint256S("0x000086b3f5228857dbd9e0181bc7ec1af0f186e5bebdaf5ebd639f53784de48b")) + (892000, uint256S("0x0000189ea1fd4571f85058bfe18fb107b242e51be76a096c5756f8f9d2bf3a80")) + (893000, uint256S("0x00008ef32c3cd2e05c1ff6668bc0398cd754aed04b9ee8b47b3da5ce63cc4a70")) + (894000, uint256S("0x00003681261a9e354a6c39c450ed133e22759b32760d346941b1ffcf78c72637")) + (895000, uint256S("0x00003930f93e5f335699d76ed9feff63a7372c5e42215e2089b52ab06a76c5f7")) + (896000, uint256S("0x00004d0e19dce5d3faf528cb41b636cd405d54129260054fa7b5d047d97c6f7b")) + ,(int64_t) 1700672140, // time of last checkpointed block + (int64_t) 915277, // total txs + (double) 2410 // txs in the last day before block 896461 }; } else { // all other HSC's with no checkpoints diff --git a/src/clientversion.h b/src/clientversion.h index 235661630..ff530f64c 100644 --- a/src/clientversion.h +++ b/src/clientversion.h @@ -29,8 +29,8 @@ //! These need to be macros, as clientversion.cpp's and bitcoin*-res.rc's voodoo requires it // Must be kept in sync with configure.ac , ugh! #define CLIENT_VERSION_MAJOR 3 -#define CLIENT_VERSION_MINOR 9 -#define CLIENT_VERSION_REVISION 4 +#define CLIENT_VERSION_MINOR 10 +#define CLIENT_VERSION_REVISION 0 #define CLIENT_VERSION_BUILD 50 //! Set to true for release, false for prerelease or test build diff --git a/src/consensus/validation.h b/src/consensus/validation.h index 8ae53c89a..f3d7b3b31 100644 --- a/src/consensus/validation.h +++ b/src/consensus/validation.h @@ -29,6 +29,8 @@ static const unsigned char REJECT_MALFORMED = 0x01; static const unsigned char REJECT_INVALID = 0x10; static const unsigned char REJECT_OBSOLETE = 0x11; static const unsigned char REJECT_DUPLICATE = 0x12; +static const unsigned char REJECT_DUPLICATE_OUTPUT_PROOF = 0x13; +static const unsigned char REJECT_DUPLICATE_SPEND_PROOF = 0x14; static const unsigned char REJECT_NONSTANDARD = 0x40; static const unsigned char REJECT_DUST = 0x41; static const unsigned char REJECT_INSUFFICIENTFEE = 0x42; diff --git a/src/dbwrapper.h b/src/dbwrapper.h index 13c6a0e96..d16be9307 100644 --- a/src/dbwrapper.h +++ b/src/dbwrapper.h @@ -12,8 +12,8 @@ #include "util.h" #include "version.h" #include -#include -#include +#include "leveldb/db.h" +#include "leveldb/write_batch.h" static const size_t DBWRAPPER_PREALLOC_KEY_SIZE = 64; static const size_t DBWRAPPER_PREALLOC_VALUE_SIZE = 1024; diff --git a/src/dragonx-cli b/src/dragonx-cli index 5b9eaa511..c8035da79 100755 --- a/src/dragonx-cli +++ b/src/dragonx-cli @@ -10,4 +10,4 @@ cd $DIR DIR="$( cd "$( dirname "$( readlink "${BASH_SOURCE[0]}" )" )" && pwd )" cd $DIR -./hush-cli -ac_name=DRAGONX $@ +./hush-cli -ac_name=DRAGONX "$@" diff --git a/src/hush_bitcoind.h b/src/hush_bitcoind.h index b09c756ad..9c17dad6b 100644 --- a/src/hush_bitcoind.h +++ b/src/hush_bitcoind.h @@ -25,11 +25,12 @@ #include "sietch.h" int32_t hush_notaries(uint8_t pubkeys[64][33],int32_t height,uint32_t timestamp); -int32_t hush_electednotary(int32_t *numnotariesp,uint8_t *pubkey33,int32_t height,uint32_t timestamp); +int32_t hush_findnotary(int32_t *numnotariesp,uint8_t *pubkey33,int32_t height,uint32_t timestamp); int32_t hush_voutupdate(bool fJustCheck,int32_t *isratificationp,int32_t notaryid,uint8_t *scriptbuf,int32_t scriptlen,int32_t height,uint256 txhash,int32_t i,int32_t j,uint64_t *voutmaskp,int32_t *specialtxp,int32_t *notarizedheightp,uint64_t value,int32_t notarized,uint64_t signedmask,uint32_t timestamp); bool EnsureWalletIsAvailable(bool avoidException); extern bool fRequestShutdown; extern CScript HUSH_EARLYTXID_SCRIPTPUB; +extern std::string devtax_scriptpub_for_height(uint32_t nHeight); uint32_t hush_heightstamp(int32_t height); @@ -1548,6 +1549,8 @@ bool hush_appendACscriptpub() static bool didinit = false; if ( didinit ) return didinit; + // HUSH doesn't use earlytxid so we do not need this in this function + //ASSETCHAINS_SCRIPTPUB = devtax_scriptpub_for_height(height); if ( ASSETCHAINS_SCRIPTPUB[ASSETCHAINS_SCRIPTPUB.back()] == 49 && ASSETCHAINS_SCRIPTPUB[ASSETCHAINS_SCRIPTPUB.back()-1] == 51 ) { CTransaction tx; uint256 blockhash; @@ -1616,6 +1619,7 @@ int64_t hush_checkcommission(CBlock *pblock,int32_t height) if(fDebug) fprintf(stderr,"%s at height=%d\n",__func__,height); int64_t checktoshis=0; uint8_t *script,scripthex[8192]; int32_t scriptlen,matched = 0; static bool didinit = false; + ASSETCHAINS_SCRIPTPUB = devtax_scriptpub_for_height(height); if ( ASSETCHAINS_COMMISSION != 0 || ASSETCHAINS_FOUNDERS_REWARD != 0 ) { checktoshis = the_commission(pblock,height); @@ -1728,6 +1732,7 @@ int32_t hush_checkPOW(int32_t slowflag,CBlock *pblock,int32_t height) } if ( failed == 0 && ASSETCHAINS_COMMISSION != 0 ) { if ( height == 1 ) { + ASSETCHAINS_SCRIPTPUB = devtax_scriptpub_for_height(height); if ( ASSETCHAINS_SCRIPTPUB.size() > 1 && ASSETCHAINS_SCRIPTPUB[ASSETCHAINS_SCRIPTPUB.back()] != 49 && ASSETCHAINS_SCRIPTPUB[ASSETCHAINS_SCRIPTPUB.back()-1] != 51 ) { int32_t scriptlen; uint8_t scripthex[10000]; script = (uint8_t *)&pblock->vtx[0].vout[0].scriptPubKey[0]; @@ -1786,13 +1791,13 @@ int32_t hush_checkPOW(int32_t slowflag,CBlock *pblock,int32_t height) int32_t hush_scpublic(uint32_t tiptime) { - // HUSH does not support public blockchains, go use something else if you want no privacy + // HUSH does not support surveillance coins, go use something else if you want no privacy return 0; } -int64_t hush_newcoins(int64_t *zfundsp,int64_t *sproutfundsp,int32_t nHeight,CBlock *pblock) +int64_t hush_newcoins(int64_t *zfundsp,int32_t nHeight,CBlock *pblock) { - CTxDestination address; int32_t i,j,m,n,vout; uint8_t *script; uint256 txid,hashBlock; int64_t zfunds=0,vinsum=0,voutsum=0,sproutfunds=0; + CTxDestination address; int32_t i,j,m,n,vout; uint8_t *script; uint256 txid,hashBlock; int64_t zfunds=0,vinsum=0,voutsum=0; n = pblock->vtx.size(); for (i=0; i 100000*SATOSHIDEN || voutsum-vinsum+zfunds < 0 ) //. fprintf(stderr,"ht.%d vins %.8f, vouts %.8f -> %.8f zfunds %.8f\n",nHeight,dstr(vinsum),dstr(voutsum),dstr(voutsum)-dstr(vinsum),dstr(zfunds)); return(voutsum - vinsum); } -int64_t hush_coinsupply(int64_t *zfundsp,int64_t *sproutfundsp,int32_t height) +int64_t hush_coinsupply(int64_t *zfundsp,int32_t height) { - CBlockIndex *pindex; CBlock block; int64_t zfunds=0,sproutfunds=0,supply = 0; + CBlockIndex *pindex; CBlock block; int64_t zfunds=0,supply = 0; //fprintf(stderr,"coinsupply %d\n",height); - *zfundsp = *sproutfundsp = 0; + *zfundsp = 0; if ( (pindex= hush_chainactive(height)) != 0 ) { while ( pindex != 0 && pindex->GetHeight() > 0 ) @@ -1852,7 +1854,7 @@ int64_t hush_coinsupply(int64_t *zfundsp,int64_t *sproutfundsp,int32_t height) if ( pindex->newcoins == 0 && pindex->zfunds == 0 ) { if ( hush_blockload(block,pindex) == 0 ) { - pindex->newcoins = hush_newcoins(&pindex->zfunds,&pindex->sproutfunds,pindex->GetHeight(),&block); + pindex->newcoins = hush_newcoins(&pindex->zfunds,pindex->GetHeight(),&block); } else { fprintf(stderr,"error loading block.%d\n",pindex->GetHeight()); return(0); @@ -1860,13 +1862,11 @@ int64_t hush_coinsupply(int64_t *zfundsp,int64_t *sproutfundsp,int32_t height) } supply += pindex->newcoins; zfunds += pindex->zfunds; - sproutfunds += pindex->sproutfunds; //printf("start ht.%d new %.8f -> supply %.8f zfunds %.8f -> %.8f\n",pindex->GetHeight(),dstr(pindex->newcoins),dstr(supply),dstr(pindex->zfunds),dstr(zfunds)); pindex = pindex->pprev; } } *zfundsp = zfunds; - *sproutfundsp = sproutfunds; return(supply); } diff --git a/src/hush_defs.h b/src/hush_defs.h index 8ae77797e..75dfc9844 100644 --- a/src/hush_defs.h +++ b/src/hush_defs.h @@ -54,6 +54,12 @@ const uint32_t nHushHardforkHeight2 = 245055; // This height begins Hush DPoW from Hush notaries const uint32_t nHushHardforkHeight3 = 340420; +// This height begins Hush Decentralized Devtax +// ./contrib/block_time.pl 1605555 +// Hush Block 1605555 will happen at roughly: +// Sat Dec 16 10:30:42 2023 Eastern # 1702740642 +// Sat Dec 16 15:30:42 2023 GMT # 1702740642 +const uint32_t nHushHardforkHeight4 = 1605555; const uint32_t nHushHardforkTimestamp = 1580303652; // Jan 29nd 1pm GMT const uint32_t nHushHardforkTimestamp2 = 1594425600; // Jul 11th 12a GMT @@ -61,355 +67,353 @@ const uint32_t nHushHardforkTimestamp2 = 1594425600; // Jul 11th 12a GMT static const uint32_t HUSH_SEASON_TIMESTAMPS[NUM_HUSH_SEASONS] = {1525132800, 1563148800, nHushHardforkTimestamp, nHushHardforkTimestamp2, nHushHardforkTimestamp2*5, nHushHardforkTimestamp2*6, nHushHardforkTimestamp2*7}; // Used by HUSH3+TUSH -// Block 1702100 = nHushHardforkHeight3*5 -static const int32_t HUSH_SEASON_HEIGHTS[NUM_HUSH_SEASONS] = {1,2,nHushHardforkHeight, nHushHardforkHeight2, (int)340000, nHushHardforkHeight3, nHushHardforkHeight3*5}; +static const int32_t HUSH_SEASON_HEIGHTS[NUM_HUSH_SEASONS] = {1,2,nHushHardforkHeight, nHushHardforkHeight2, (int)340000, nHushHardforkHeight3, nHushHardforkHeight4}; // Era array of pubkeys. Add extra seasons to bottom as requried, after adding appropriate info above. -static const char *notaries_elected[NUM_HUSH_SEASONS][NUM_HUSH_NOTARIES][2] = +static const char *notaries_list[NUM_HUSH_SEASONS][NUM_HUSH_NOTARIES][2] = { { // season 1 - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, }, { // season 2 - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, }, { // season 3 - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, }, { - // Season 4 third party NN pubkeys from https://github.com/KomodoPlatform/dPoW/blob/master/dragon/3rd_party - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, + // Season 4 + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, }, { - // Season 5 (fuck season 3.5) https://github.com/KomodoPlatform/dPoW/blob/s4/dragon/3rd_party - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, - { "fuck_jl777", "034ea5e2d1b858e9b026dc5a4ea5bb2e4a5b625a086d9954c94b002d0858987214"}, + // Season 5 + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, + { "unused", "000000000000000000000000000000000000000000000000000000000000000000"}, }, { - // Hush Delayed Proof of Work, Season 6 In The Great History Of DPoW - // NOTE: Hush notaries are proudly anon, where KMD notaries doxx themselves, derpz and lulz + // Season 6 {"RFetqf8WUfWnwNeXdknkm8ojk7EXnYFzrv", "038a1bd41a08f38edda51042988022933c5775dfce81f7bae0b32a9179650352ac"}, {"RV7YSVW89WC9jBDtFG4ubtopDRove4Tfvc", "03c9d35488be73fe4f2dbb1dc011468482d71bac32249f8cce6480bcc574415d19"}, {"RBPFE9oXceZBWTn3Vhne4FUKE9vxGEXUKX", "028a8bb6ded2692b39a69ec2d3c9836ff221815909d5cd65257374aeb66394a002"}, diff --git a/src/hush_globals.h b/src/hush_globals.h index e307f774c..776de8a54 100644 --- a/src/hush_globals.h +++ b/src/hush_globals.h @@ -280,3 +280,78 @@ uint64_t hush_current_supply(uint32_t nHeight) //fprintf(stderr,"cur_money %.8f\n",(double)cur_money/COIN); return(cur_money); } + +// the number of different devtax addresses/scriptpubs +const uint32_t DEVTAX_NUM = 20; + +std::string DEVTAX_DATA[DEVTAX_NUM][2] = { +{"RAMagYNy678TEFvjqE9kmkDX5j3xsK9whE", "76a9140bcca88d9224ec1571d4dd68009305d055ca3a4588ac"}, +{"RAstH3RJSHq2jr9cigVmAdC5kLdeqCU9gu", "76a9141187d31f4b95c3210d2c69acb6853034fb748f8d88ac"}, +{"RCjpaSm3SBnoR7EfM3BGFApx1FgMYZqUqd", "76a91425f1a8f5c0bcb7fb4c351f98fd664bbbc029c65488ac"}, +{"RCoJZfPhyigihrzBx3nBnT2V2fdt8PUEmN", "76a914269a4514eaa07aa928d3d809d6f9b5a8b0a0d84588ac"}, +{"REadVrDc5PdtkuuXhGMcdBfTLKFkYZtp61", "76a9143a24eb5ff34c8395c4159aa74113680960fbae0888ac"}, +{"REJjRATXJ4YqtTTbcSS24HTzVpKc235kzb", "76a914372334851e666ff7932d423b1d614db0ad88f3e988ac"}, +{"REktw85C53o6FN9yuQL4HfL8cEgq9oQzgg", "76a9143c15f6d372a486e0d3da907e0063d990d50a1f9588ac"}, +{"REXWQqh6ibSc3SDZDN1n3tN6H2fjDB3LRs", "76a914398dc193009312742129f00bc12214c2e0ec2cba88ac"}, +{"RFJYpa7sHMes2da1Kd9JZpNEwoz3ut2zxq", "76a91442127c49a163f79898c69906147ca3c7c34924b788ac"}, +{"RFLXxCk7AAtUnxauu8k5BzuhXm6XqfJjLA", "76a914427297ae0417d18b7f9c31b4a51502d4f2a8cd7988ac"}, +{"RHrBQoDnZ5QrtkL7B1zsdFxrNfLuEikf5T", "76a9145dfe2cfe9f6db1c0e6847a35f433d1948d4086a488ac"}, +{"RJDnDj2XHFSbjrBWxW7AA5vv8pQbeiRw5i", "76a9146213f7d7567a97d4b6888d3863ed8d4808acf9c688ac"}, +{"RKf78FsvzJebo41n1ZQGyLxbuh3bmbkmAg", "76a91471d646502b388d9cca69f05bdedc8920918eca4a88ac"}, +{"RL6J7DU69YvJBFSL93RnezR7dJYW93yKN3", "76a9147699d74f361b559ef4cdab6ad2582f68fdd444bd88ac"}, +{"RLDDJMB3fSexorUC7ZkTRjcRLJEkNJZktz", "76a91477e8bd3dc10277540fa7f183936c977c130c397c88ac"}, +{"RR9ufAA8m5Myu5EZd2KdXy9hpD6sY5vE1f", "76a914ae2164e50fd814faa8629907679af2668f8fd08388ac"}, +{"RUBz8fptKNXB5NL3H1ohNGTeKMBv9WRcpd", "76a914cf6e56a04785c9a913d355a2d9c7c7ec1243a4ff88ac"}, +{"RUT8NytuYHqmYXwBkue7ujLWaCKw5ZVc38", "76a914d24b763bdac5fb28513d134743e42302736c0dfd88ac"}, +{"RVF6tWNCrUsubeKLzadH4aeseVwnJPKd8N", "76a914dafd59fd09a4e7cb813fc4dde4515a605e3aceae88ac"}, +{"RVMygLshHa8qvFX1orEi5FGji99BVXUQFy", "76a914dc4a3eb079349b4bb25864af4ddc5cd52faf382d88ac"}, +}; + +// this is a deterministic consensus-changing function. All miners must be able +// to predict the scriptpub for the next block +std::string devtax_scriptpub_for_height(uint32_t nHeight) { + bool ishush3 = strncmp(SMART_CHAIN_SYMBOL, "HUSH3",5) == 0 ? true : false; + bool istush3 = strncmp(SMART_CHAIN_SYMBOL, "TUSH3",5) == 0 ? true : false; + // Fork height for HUSH3 mainnet needs to be decided just before code is merged + // Since it requires all full nodes on the network to have enough time to update. + // For testing, we choose an early blockheight so we can observe the value changing + // from the old fixed value to the new values which cycle + const int DEVTAX_FORK_HEIGHT = ishush3 ? nHushHardforkHeight4 : 5; + + // Decentralized devtax is height-activated + if (nHeight >= DEVTAX_FORK_HEIGHT) { + if (ishush3 || istush3) { + return DEVTAX_DATA[ nHeight % DEVTAX_NUM ][1]; + } else { + // if this is not HUSH3 or a testchain for HUSH3, return it unchanged + return ASSETCHAINS_SCRIPTPUB; + } + } + // return default unchanged if we are less than fork height + return ASSETCHAINS_SCRIPTPUB; +} + +// this is only used by getblocktemplate, so it cannot change consensus of +// blocks < DEVTAX_FORK_HEIGHT but it could affect consensus of later blocks +std::string devtax_address_for_height(uint32_t nHeight) { + const std::string legacy_devtax_address = "RHushEyeDm7XwtaTWtyCbjGQumYyV8vMjn"; + bool ishush3 = strncmp(SMART_CHAIN_SYMBOL, "HUSH3",5) == 0 ? true : false; + bool istush3 = strncmp(SMART_CHAIN_SYMBOL, "TUSH3",5) == 0 ? true : false; + // Fork height for HUSH3 mainnet needs to be decided just before code is merged + // Since it requires all full nodes on the network to have enough time to update. + // For testing, we choose an early blockheight so we can observe the value changing + // from the old fixed value to the new values which cycle + const int DEVTAX_FORK_HEIGHT = ishush3 ? nHushHardforkHeight4 : 5; + + // Decentralized devtax is height-activated + if (nHeight >= DEVTAX_FORK_HEIGHT) { + if (ishush3 || istush3) { + return DEVTAX_DATA[ nHeight % DEVTAX_NUM ][0]; + } else { + // if this is not HUSH3 or TUSH3, return legacy + return legacy_devtax_address; + } + } + // return default unchanged if we are less than fork height + return legacy_devtax_address; +} diff --git a/src/hush_nSPV_fullnode.h b/src/hush_nSPV_fullnode.h index 48ae589d8..d93deb686 100644 --- a/src/hush_nSPV_fullnode.h +++ b/src/hush_nSPV_fullnode.h @@ -124,7 +124,8 @@ int32_t NSPV_setequihdr(struct NSPV_equihdr *hdr,int32_t height) hdr->nTime = pindex->nTime; hdr->nBits = pindex->nBits; hdr->nNonce = pindex->nNonce; - memcpy(hdr->nSolution,&pindex->nSolution[0],sizeof(hdr->nSolution)); + + memcpy(hdr->nSolution,&pindex->GetBlockHeader().nSolution[0],sizeof(hdr->nSolution)); return(sizeof(*hdr)); } return(-1); diff --git a/src/hush_notary.h b/src/hush_notary.h index 8228a475b..52159aa7c 100644 --- a/src/hush_notary.h +++ b/src/hush_notary.h @@ -125,7 +125,7 @@ int32_t hush_notaries(uint8_t pubkeys[64][33],int32_t height,uint32_t timestamp) if ( didinit[hush_season-1] == 0 ) { for (i=0; i= HUSH_NOTARIES_HARDCODED || SMART_CHAIN_SYMBOL[0] != 0 ) { - if ( (*notaryidp= hush_electednotary(&numnotaries,pubkey33,height,timestamp)) >= 0 && numnotaries != 0 ) + if ( (*notaryidp= hush_findnotary(&numnotaries,pubkey33,height,timestamp)) >= 0 && numnotaries != 0 ) { modval = ((height % numnotaries) == *notaryidp); return(modval); diff --git a/src/hush_utils.h b/src/hush_utils.h index 233028898..d03c1e055 100644 --- a/src/hush_utils.h +++ b/src/hush_utils.h @@ -1782,17 +1782,17 @@ void hush_args(char *argv0) USE_EXTERNAL_PUBKEY = 1; if ( IS_HUSH_NOTARY == 0 ) { - // We dont have any chain data yet, so use system clock to guess. - // I think on season change should reccomend notaries to use -notary to avoid needing this. + // We dont have any chain data yet, so use system clock to guess. + // I think on season change should recommend notaries to use -notary to avoid needing this. int32_t hush_season = getacseason(time(NULL)); for (i=0; i<64; i++) { - if ( strcmp(NOTARY_PUBKEY.c_str(),notaries_elected[hush_season-1][i][1]) == 0 ) + if ( strcmp(NOTARY_PUBKEY.c_str(),notaries_list[hush_season-1][i][1]) == 0 ) { IS_HUSH_NOTARY = 1; HUSH_MININGTHREADS = 1; mapArgs ["-genproclimit"] = itostr(HUSH_MININGTHREADS); - fprintf(stderr,"running as notary.%d %s\n",i,notaries_elected[hush_season-1][i][0]); + fprintf(stderr,"running as notary.%d %s\n",i,notaries_list[hush_season-1][i][0]); break; } } @@ -1952,6 +1952,8 @@ void hush_args(char *argv0) ASSETCHAINS_SAPLING = 1; // this corresponds to FR address RHushEyeDm7XwtaTWtyCbjGQumYyV8vMjn ASSETCHAINS_SCRIPTPUB = "76a9145eb10cf64f2bab1b457f1f25e658526155928fac88ac"; + // we do not want to change the magic of HUSH3 mainnet so we do not call devtax_scriptpub_for_height() here, + // instead we call it whenever ASSETCHAINS_SCRIPTPUB is used later on // Over-ride HUSH3 values from CLI params. Changing our blocktime to 75s changes things ASSETCHAINS_REWARD[0] = 0; diff --git a/src/init.cpp b/src/init.cpp index f49e146dd..c27639725 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -458,6 +458,7 @@ std::string HelpMessage(HelpMessageMode mode) strUsage += HelpMessageOpt("-disablewallet", _("Do not load the wallet and disable wallet RPC calls")); strUsage += HelpMessageOpt("-keypool=", strprintf(_("Set key pool size to (default: %u)"), 100)); strUsage += HelpMessageOpt("-consolidation", _("Enable auto Sapling note consolidation (default: false)")); + strUsage += HelpMessageOpt("-consolidationinterval", _("Block interval between consolidations (default: 25)")); strUsage += HelpMessageOpt("-consolidatesaplingaddress=", _("Specify Sapling Address to Consolidate. (default: all)")); strUsage += HelpMessageOpt("-consolidationtxfee", strprintf(_("Fee amount in Puposhis used send consolidation transactions. (default %i)"), DEFAULT_CONSOLIDATION_FEE)); @@ -2435,7 +2436,7 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler) SetRPCWarmupFinished(); if(fDebug) fprintf(stderr,"RPC warmump finished\n"); - uiInterface.InitMessage(_("Hush Full Node Done Loading! :)")); + uiInterface.InitMessage(_("Full Node Done Loading! :)")); #ifdef ENABLE_WALLET if (pwalletMain) { diff --git a/src/main.cpp b/src/main.cpp index 2c037297b..714dc36e6 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1751,7 +1751,31 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa { return error("AcceptToMemoryPool: CheckTransaction failed"); } - + + // Reject duplicate output proofs in a single ztx in mempool + // Migrate this to CheckTransaction() to make it a consensus requirement + { + set vSaplingOutputProof; + BOOST_FOREACH(const OutputDescription& output, tx.vShieldedOutput) + { + if (vSaplingOutputProof.count(output.zkproof)) + return state.Invalid(error("AcceptToMemoryPool: duplicate output proof"),REJECT_DUPLICATE_OUTPUT_PROOF, "bad-txns-duplicate-output-proof"); + vSaplingOutputProof.insert(output.zkproof); + } + } + + // Reject duplicate spend proofs in a single ztx in mempool + // Migrate this to CheckTransaction() to make it a consensus requirement + { + set vSaplingSpendProof; + BOOST_FOREACH(const SpendDescription& spend, tx.vShieldedSpend) + { + if (vSaplingSpendProof.count(spend.zkproof)) + return state.Invalid(error("AcceptToMemoryPool: duplicate spend proof"),REJECT_DUPLICATE_SPEND_PROOF, "bad-txns-duplicate-spend-proof"); + vSaplingSpendProof.insert(spend.zkproof); + } + } + // DoS level set to 10 to be more forgiving. // Check transaction contextually against the set of consensus rules which apply in the next block to be mined. if (!ContextualCheckTransaction(0,0,0,tx, state, nextBlockHeight, (dosLevel == -1) ? 10 : dosLevel)) @@ -1863,8 +1887,6 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa view.GetBestBlock(); nValueIn = view.GetValueIn(chainActive.LastTip()->GetHeight(),&interest,tx,chainActive.LastTip()->nTime); - if ( 0 && interest != 0 ) - fprintf(stderr,"add interest %.8f\n",(double)interest/COIN); // we have all inputs cached now, so switch back to dummy, so we don't need to keep lock on mempool view.SetBackend(dummy); } @@ -3232,7 +3254,8 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin uint256 hashPrevBlock = pindex->pprev == NULL ? uint256() : pindex->pprev->GetBlockHash(); if ( hashPrevBlock != view.GetBestBlock() ) { - fprintf(stderr,"ConnectBlock(): hashPrevBlock != view.GetBestBlock()\n"); + fprintf(stderr,"ConnectBlock(): hashPrevBlock != view.GetBestBlock() %s != %s\n", hashPrevBlock.ToString().c_str(), view.GetBestBlock().ToString().c_str() ); + return state.DoS(1, error("ConnectBlock(): hashPrevBlock != view.GetBestBlock()"), REJECT_INVALID, "hashPrevBlock-not-bestblock"); } @@ -3678,7 +3701,7 @@ bool static FlushStateToDisk(CValidationState &state, FlushStateMode mode) { vFiles.push_back(make_pair(*it, &vinfoBlockFile[*it])); setDirtyFileInfo.erase(it++); } - std::vector vBlocks; + std::vector vBlocks; vBlocks.reserve(setDirtyBlockIndex.size()); for (set::iterator it = setDirtyBlockIndex.begin(); it != setDirtyBlockIndex.end(); ) { vBlocks.push_back(*it); @@ -3687,6 +3710,12 @@ bool static FlushStateToDisk(CValidationState &state, FlushStateMode mode) { if (!pblocktree->WriteBatchSync(vFiles, nLastBlockFile, vBlocks)) { return AbortNode(state, "Files to write to block index database"); } + // Now that we have written the block indices to the database, we do not + // need to store solutions for these CBlockIndex objects in memory. + // cs_main must be held here. + for (CBlockIndex *pblockindex : vBlocks) { + pblockindex->TrimSolution(); + } } // Finally remove any pruned files if (fFlushForPrune) @@ -5113,7 +5142,7 @@ bool ContextualCheckBlockHeader(const CBlockHeader& block, CValidationState& sta // " " << block.GetHash().ToString() << " @ " << block.GetBlockTime() << endl; return state.DoS(100, error("%s: Incorrect diffbits at height %d: %lu vs %lu ", __func__, nHeight, nNextWork, block.nBits), REJECT_INVALID, "bad-diffbits"); } else { - cout << "Ignoring nbits for height=" << nHeight << endl; + // cout << "Ignoring nbits for height=" << nHeight << endl; } } } @@ -6569,7 +6598,11 @@ void static CheckBlockIndex() } } } - // assert(pindex->GetBlockHash() == pindex->GetBlockHeader().GetHash()); // Perhaps too slow + // try { + // assert(pindex->GetBlockHash() == pindex->GetBlockHeader().GetHash()); // Perhaps too slow + // } catch (const runtime_error&) { + // assert(!"Failed to read index entry"); + // } // End: actual consistency checks. // Try descending into the first subnode. diff --git a/src/main.h b/src/main.h index 66357b3d0..cfd9fed19 100644 --- a/src/main.h +++ b/src/main.h @@ -39,6 +39,7 @@ #include "spentindex.h" #include "sync.h" #include "tinyformat.h" +#include "txdb.h" #include "txmempool.h" #include "uint256.h" diff --git a/src/miner.cpp b/src/miner.cpp index ee85a52eb..94033bc32 100644 --- a/src/miner.cpp +++ b/src/miner.cpp @@ -120,6 +120,7 @@ public: extern int8_t ASSETCHAINS_ADAPTIVEPOW; extern uint32_t ASSETCHAINS_RANDOMX; extern bool fRandomXDebug; +extern std::string devtax_scriptpub_for_height(uint32_t nHeight); void UpdateTime(CBlockHeader* pblock, const Consensus::Params& consensusParams, const CBlockIndex* pindexPrev) { @@ -279,11 +280,16 @@ CBlockTemplate* CreateNewBlock(CPubKey _pk,const CScript& _scriptPubKeyIn, int32 vecPriority.reserve(mempool.mapTx.size() + 1); //fprintf(stderr,"%s: going to add txs from mempool\n", __func__); - // now add transactions from the mem pool + // now add transactions from the mempool int32_t Notarizations = 0; uint64_t txvalue; + uint32_t large_zins = 0; // number of ztxs with large number of inputs in block + uint32_t large_zouts = 0; // number of ztxs with large number of outputs in block + const uint32_t LARGE_ZINS_MAX = 1; // max ztxs with large zins per block + const uint32_t LARGE_ZOUTS_MAX = 1; // max ztxs with large zouts per block + const uint32_t LARGE_ZINS_THRESHOLD = 50; // min number of zins to be considered large + const uint32_t LARGE_ZOUTS_THRESHOLD = 10; // min number of zouts to be considered large for (CTxMemPool::indexed_transaction_set::iterator mi = mempool.mapTx.begin(); - mi != mempool.mapTx.end(); ++mi) - { + mi != mempool.mapTx.end(); ++mi) { const CTransaction& tx = mi->GetTx(); int64_t nLockTimeCutoff = (STANDARD_LOCKTIME_VERIFY_FLAGS & LOCKTIME_MEDIAN_TIME_PAST) @@ -466,6 +472,18 @@ CBlockTemplate* CreateNewBlock(CPubKey _pk,const CScript& _scriptPubKeyIn, int32 // fprintf(stderr,"%s: compared first tx from priority queue\n", __func__); vecPriority.pop_back(); + if(tx.vShieldedSpend.size() >= LARGE_ZINS_THRESHOLD && large_zins >= LARGE_ZINS_MAX) { + LogPrintf("%s: skipping ztx %s with %d zins because there are already %d ztxs with large zins\n", + __func__, tx.GetHash().ToString().c_str(), tx.vShieldedSpend.size(), LARGE_ZINS_MAX); + continue; + } + + if(tx.vShieldedOutput.size() >= LARGE_ZOUTS_THRESHOLD && large_zouts >= LARGE_ZOUTS_MAX) { + LogPrintf("%s: skipping ztx %s with %d zouts because there are already %d ztxs with large zouts\n", + __func__, tx.GetHash().ToString().c_str(), tx.vShieldedOutput.size(), LARGE_ZOUTS_MAX); + continue; + } + // Size limits unsigned int nTxSize = ::GetSerializeSize(tx, SER_NETWORK, PROTOCOL_VERSION); // fprintf(stderr,"%s: nTxSize = %u\n", __func__, nTxSize); @@ -576,6 +594,18 @@ CBlockTemplate* CreateNewBlock(CPubKey _pk,const CScript& _scriptPubKeyIn, int32 nBlockSigOps += nTxSigOps; nFees += nTxFees; + if(tx.vShieldedOutput.size() >= LARGE_ZOUTS_THRESHOLD) { + large_zouts++; + LogPrintf("%s: txid=%s has large zouts=%d (%d large zouts in block)\n", __func__, tx.GetHash().ToString().c_str(), + tx.vShieldedOutput.size(), large_zouts ); + } + + if(tx.vShieldedSpend.size() >= LARGE_ZINS_THRESHOLD) { + large_zins++; + LogPrintf("%s: txid=%s has large zins=%d (%d large zins in block)\n", __func__, tx.GetHash().ToString().c_str(), + tx.vShieldedSpend.size(), large_zins ); + } + if (fPrintPriority) { LogPrintf("priority %.1f fee %s txid %s\n",dPriority, feeRate.ToString(), tx.GetHash().ToString()); @@ -630,6 +660,7 @@ CBlockTemplate* CreateNewBlock(CPubKey _pk,const CScript& _scriptPubKeyIn, int32 pblock->vtx[0] = txNew; + ASSETCHAINS_SCRIPTPUB = devtax_scriptpub_for_height(nHeight); if ( nHeight > 1 && SMART_CHAIN_SYMBOL[0] != 0 && (ASSETCHAINS_OVERRIDE_PUBKEY33[0] != 0 || ASSETCHAINS_SCRIPTPUB.size() > 1) && (ASSETCHAINS_COMMISSION != 0 || ASSETCHAINS_FOUNDERS_REWARD != 0) && (commission= the_commission((CBlock*)&pblocktemplate->block,(int32_t)nHeight)) != 0 ) { int32_t i; uint8_t *ptr; @@ -819,6 +850,7 @@ CBlockTemplate* CreateNewBlockWithKey(CReserveKey& reservekey, int32_t nHeight, { CPubKey pubkey; CScript scriptPubKey; uint8_t *script,*ptr; int32_t i,len; // fprintf(stderr,"%s: with nHeight=%d\n", __func__, nHeight); + ASSETCHAINS_SCRIPTPUB = devtax_scriptpub_for_height(nHeight); if ( nHeight == 1 && ASSETCHAINS_COMMISSION != 0 && ASSETCHAINS_SCRIPTPUB[ASSETCHAINS_SCRIPTPUB.back()] != 49 && ASSETCHAINS_SCRIPTPUB[ASSETCHAINS_SCRIPTPUB.back()-1] != 51 ) { if ( ASSETCHAINS_OVERRIDE_PUBKEY33[0] != 0 ) @@ -1072,14 +1104,14 @@ void static RandomXMiner() randomx_dataset *randomxDataset = randomx_alloc_dataset(flags); rxdebug("%s: created dataset\n"); - auto datasetItemCount = randomx_dataset_item_count(); - rxdebug("%s: dataset items=%lu\n", datasetItemCount); - if( randomxDataset == nullptr) { LogPrintf("%s: allocating randomx dataset failed!\n", __func__); return; } + auto datasetItemCount = randomx_dataset_item_count(); + rxdebug("%s: dataset items=%lu\n", datasetItemCount); + char randomxHash[RANDOMX_HASH_SIZE]; rxdebug("%s: created randomxHash of size %d\n", RANDOMX_HASH_SIZE); char randomxKey[82]; // randomx spec says keysize of >60 bytes is implementation-specific @@ -1093,6 +1125,7 @@ void static RandomXMiner() int randomxInterval = GetArg("-ac_randomx_interval",1024); // This lag is 80 mins for 75s blocktime and 64 mins for 60s (default) blocktime for HSCs int randomxBlockLag = GetArg("-ac_randomx_lag", 64); + randomx_vm *myVM = nullptr; try { // fprintf(stderr,"RandomXMiner: mining %s with randomx\n",SMART_CHAIN_SYMBOL); @@ -1169,7 +1202,7 @@ void static RandomXMiner() // randomx_init_dataset(randomxDataset, randomxCache, 0, datasetItemCount); rxdebug("%s: dataset initialized\n"); - randomx_vm *myVM = randomx_create_vm(flags, nullptr, randomxDataset); + myVM = randomx_create_vm(flags, nullptr, randomxDataset); if(myVM == NULL) { LogPrintf("RandomXMiner: Cannot create RandomX VM, aborting!\n"); return; @@ -1395,19 +1428,35 @@ void static RandomXMiner() } catch (const boost::thread_interrupted&) { miningTimer.stop(); c.disconnect(); + + randomx_destroy_vm(myVM); + LogPrintf("%s: destroyed vm via thread interrupt\n", __func__); + randomx_release_dataset(randomxDataset); + rxdebug("%s: released dataset via thread interrupt\n"); + randomx_release_cache(randomxCache); + rxdebug("%s: released cache via thread interrupt\n"); + LogPrintf("HushRandomXMiner terminated\n"); throw; } catch (const std::runtime_error &e) { miningTimer.stop(); c.disconnect(); fprintf(stderr,"RandomXMiner: runtime error: %s\n", e.what()); + + randomx_destroy_vm(myVM); + LogPrintf("%s: destroyed vm because of error\n", __func__); + randomx_release_dataset(randomxDataset); + rxdebug("%s: released dataset because of error\n"); + randomx_release_cache(randomxCache); + rxdebug("%s: released cache because of error\n"); + return; } randomx_release_dataset(randomxDataset); - rxdebug("%s: released dataset\n"); + rxdebug("%s: released dataset in normal exit\n"); randomx_release_cache(randomxCache); - rxdebug("%s: released cache\n"); + rxdebug("%s: released cache in normal exit\n"); miningTimer.stop(); c.disconnect(); } diff --git a/src/net.cpp b/src/net.cpp index b460f3c37..422bccf34 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -2468,7 +2468,7 @@ void RelayTransaction(const CTransaction& tx, const CDataStream& ss) fprintf(stderr, "%s: -testnode=1, no peers, not relaying\n", __func__ ); return; } else { - fprintf(stderr, "%s: Relaying to %lu of %lu peers\n", __func__, newSize, vNodes.size() ); + fprintf(stderr, "%s: Relaying %s to %lu of %lu peers\n", __func__, tx.GetHash().GetHex().c_str(), newSize, vNodes.size() ); } // Only relay to randomly chosen 50% of peers diff --git a/src/rest.cpp b/src/rest.cpp index 36b4279b1..3536d790a 100644 --- a/src/rest.cpp +++ b/src/rest.cpp @@ -151,6 +151,7 @@ static bool rest_headers(HTTPRequest* req, std::vector headers; headers.reserve(count); + CDataStream ssHeader(SER_NETWORK, PROTOCOL_VERSION); { LOCK(cs_main); BlockMap::const_iterator it = mapBlockIndex.find(hash); @@ -161,11 +162,16 @@ static bool rest_headers(HTTPRequest* req, break; pindex = chainActive.Next(pindex); } - } - CDataStream ssHeader(SER_NETWORK, PROTOCOL_VERSION); - BOOST_FOREACH(const CBlockIndex *pindex, headers) { - ssHeader << pindex->GetBlockHeader(); + if (rf == RF_BINARY || rf == RF_HEX) { + try { + for (const CBlockIndex *pindex : headers) { + ssHeader << pindex->GetBlockHeader(); + } + } catch (const std::runtime_error&) { + return RESTERR(req, HTTP_INTERNAL_SERVER_ERROR, "Failed to read index entry"); + } + } } switch (rf) { diff --git a/src/rpc/blockchain.cpp b/src/rpc/blockchain.cpp index 7bdf840da..793dff4ab 100644 --- a/src/rpc/blockchain.cpp +++ b/src/rpc/blockchain.cpp @@ -147,7 +147,7 @@ UniValue blockheaderToJSON(const CBlockIndex* blockindex) result.push_back(Pair("finalsaplingroot", blockindex->hashFinalSaplingRoot.GetHex())); result.push_back(Pair("time", (int64_t)blockindex->nTime)); result.push_back(Pair("nonce", blockindex->nNonce.GetHex())); - result.push_back(Pair("solution", HexStr(blockindex->nSolution))); + result.pushKV("solution", HexStr(blockindex->GetBlockHeader().nSolution)); result.push_back(Pair("bits", strprintf("%08x", blockindex->nBits))); result.push_back(Pair("difficulty", GetDifficulty(blockindex))); result.push_back(Pair("chainwork", blockindex->chainPower.chainWork.GetHex())); @@ -324,7 +324,6 @@ UniValue blockToJSON(const CBlock& block, const CBlockIndex* blockindex, bool tx result.push_back(Pair("blocktype", "mined")); UniValue valuePools(UniValue::VARR); - valuePools.push_back(ValuePoolDesc("sprout", blockindex->nChainSproutValue, blockindex->nSproutValue)); valuePools.push_back(ValuePoolDesc("sapling", blockindex->nChainSaplingValue, blockindex->nSaplingValue)); result.push_back(Pair("valuePools", valuePools)); @@ -694,15 +693,18 @@ UniValue getblockheader(const UniValue& params, bool fHelp, const CPubKey& mypk) CBlockIndex* pblockindex = mapBlockIndex[hash]; - if (!fVerbose) - { - CDataStream ssBlock(SER_NETWORK, PROTOCOL_VERSION); - ssBlock << pblockindex->GetBlockHeader(); - std::string strHex = HexStr(ssBlock.begin(), ssBlock.end()); - return strHex; + try { + if (!fVerbose) { + CDataStream ssBlock(SER_NETWORK, PROTOCOL_VERSION); + ssBlock << pblockindex->GetBlockHeader(); + std::string strHex = HexStr(ssBlock.begin(), ssBlock.end()); + return strHex; + } else { + return blockheaderToJSON(pblockindex); + } + } catch (const runtime_error&) { + throw JSONRPCError(RPC_DATABASE_ERROR, "Failed to read index entry"); } - - return blockheaderToJSON(pblockindex); } UniValue getblock(const UniValue& params, bool fHelp, const CPubKey& mypk) @@ -1310,14 +1312,10 @@ UniValue getblockchaininfo(const UniValue& params, bool fHelp, const CPubKey& my obj.push_back(Pair("chainwork", chainActive.LastTip()->chainPower.chainWork.GetHex())); obj.push_back(Pair("pruned", fPruneMode)); - //SproutMerkleTree tree; - //pcoinsTip->GetSproutAnchorAt(pcoinsTip->GetBestAnchor(SPROUT), tree); - //obj.push_back(Pair("commitments", static_cast(tree.size()))); obj.push_back(Pair("commitments", 0)); CBlockIndex* tip = chainActive.LastTip(); UniValue valuePools(UniValue::VARR); - valuePools.push_back(ValuePoolDesc("sprout", tip->nChainSproutValue, boost::none)); valuePools.push_back(ValuePoolDesc("sapling", tip->nChainSaplingValue, boost::none)); obj.push_back(Pair("valuePools", valuePools)); diff --git a/src/rpc/mining.cpp b/src/rpc/mining.cpp index f422f9287..beea9dad7 100644 --- a/src/rpc/mining.cpp +++ b/src/rpc/mining.cpp @@ -50,6 +50,8 @@ using namespace std; #include "hush_defs.h" extern int32_t ASSETCHAINS_FOUNDERS; +extern std::string devtax_scriptpub_for_height(uint32_t height); +extern std::string devtax_address_for_height(uint32_t height); uint64_t the_commission(const CBlock *pblock,int32_t height); int32_t hush_blockload(CBlock& block,CBlockIndex *pindex); arith_uint256 hush_PoWtarget(int32_t *percPoSp,arith_uint256 target,int32_t height,int32_t goalperc); @@ -161,7 +163,6 @@ UniValue getnetworkhashps(const UniValue& params, bool fHelp, const CPubKey& myp } #ifdef ENABLE_MINING -extern bool VERUS_MINTBLOCKS; UniValue getgenerate(const UniValue& params, bool fHelp, const CPubKey& mypk) { if (fHelp || params.size() != 0) @@ -570,9 +571,6 @@ UniValue getblocktemplate(const UniValue& params, bool fHelp, const CPubKey& myp " }\n" " ,...\n" " ],\n" -// " \"coinbaseaux\" : { (json object) data that should be included in the coinbase's scriptSig content\n" -// " \"flags\" : \"flags\" (string) \n" -// " },\n" // " \"coinbasevalue\" : n, (numeric) maximum allowable input to coinbase transaction, including the generation award and transaction fees (in Satoshis)\n" " \"coinbasetxn\" : { ... }, (json object) information for coinbase transaction\n" " \"target\" : \"xxxx\", (string) The hash target\n" @@ -801,19 +799,23 @@ UniValue getblocktemplate(const UniValue& params, bool fHelp, const CPubKey& myp int index_in_template = i - 1; entry.push_back(Pair("fee", pblocktemplate->vTxFees[index_in_template])); entry.push_back(Pair("sigops", pblocktemplate->vTxSigOps[index_in_template])); + uint32_t nHeight = chainActive.LastTip()->GetHeight()+1; if (tx.IsCoinBase() && coinbasetxn == true ) { // Show founders' reward if it is required if (ASSETCHAINS_FOUNDERS && pblock->vtx[0].vout.size() > 1) { // Correct this if GetBlockTemplate changes the order entry.push_back(Pair("foundersreward", (int64_t)tx.vout[1].nValue)); + entry.push_back(Pair("foundersrewardaddress", devtax_address_for_height(nHeight))); + entry.push_back(Pair("foundersrewardscriptpub", devtax_scriptpub_for_height(nHeight))); } - CAmount nReward = GetBlockSubsidy(chainActive.LastTip()->GetHeight()+1, Params().GetConsensus()); + CAmount nReward = GetBlockSubsidy(nHeight, Params().GetConsensus()); entry.push_back(Pair("coinbasevalue", nReward)); entry.push_back(Pair("required", true)); txCoinbase = entry; - } else + } else { transactions.push_back(entry); + } } UniValue aux(UniValue::VOBJ); @@ -839,7 +841,6 @@ UniValue getblocktemplate(const UniValue& params, bool fHelp, const CPubKey& myp assert(txCoinbase.isObject()); result.push_back(Pair("coinbasetxn", txCoinbase)); } // else { - // result.push_back(Pair("coinbaseaux", aux)); // result.push_back(Pair("coinbasevalue", (int64_t)pblock->vtx[0].vout[0].nValue)); //} result.push_back(Pair("longpollid", chainActive.LastTip()->GetBlockHash().GetHex() + i64tostr(nTransactionsUpdatedLast))); @@ -1036,6 +1037,8 @@ UniValue getblocksubsidy(const UniValue& params, bool fHelp, const CPubKey& mypk UniValue result(UniValue::VOBJ); result.push_back(Pair("miner", ValueFromAmount(nReward))); + // the value of ASSETCHAINS_SCRIPTPUB is not used here, this is just a check if it exists + // so we don't need to call devtax_scriptpub_for_height() if ( strlen(ASSETCHAINS_OVERRIDE_PUBKEY.c_str()) == 66 || ASSETCHAINS_SCRIPTPUB.size() > 1 ) { if ( ASSETCHAINS_FOUNDERS == 0 && ASSETCHAINS_COMMISSION != 0 ) diff --git a/src/rpc/misc.cpp b/src/rpc/misc.cpp index a65c020c2..701b12054 100644 --- a/src/rpc/misc.cpp +++ b/src/rpc/misc.cpp @@ -65,7 +65,7 @@ int32_t hush_whoami(char *pubkeystr,int32_t height,uint32_t timestamp); extern int32_t HUSH_LASTMINED,HUSH_LONGESTCHAIN,IS_HUSH_NOTARY,HUSH_INSYNC; extern char SMART_CHAIN_SYMBOL[HUSH_SMART_CHAIN_MAXLEN]; uint32_t hush_segid32(char *coinaddr); -int64_t hush_coinsupply(int64_t *zfundsp,int64_t *sproutfundsp,int32_t height); +int64_t hush_coinsupply(int64_t *zfundsp,int32_t height); int32_t notarizedtxid_height(char *dest,char *txidstr,int32_t *hushnotarized_heightp); uint64_t hush_notarypayamount(int32_t nHeight, int64_t notarycount); int32_t hush_notaries(uint8_t pubkeys[64][33],int32_t height,uint32_t timestamp); @@ -106,7 +106,7 @@ UniValue getdragonjson(const UniValue& params, bool fHelp, const CPubKey& mypk) // get all current notaries for (int8_t i = 0; i < NUM_HUSH_NOTARIES; i++) { UniValue notary(UniValue::VOBJ); - notary.push_back(notaries_elected[era][i][0]); + notary.push_back(notaries_list[era][i][0]); notaries.push_back(notary); } @@ -145,7 +145,7 @@ UniValue getnotarysendmany(const UniValue& params, bool fHelp, const CPubKey& my for (int i = 0; i 1) throw runtime_error("coinsupply \n" "\nReturn coin supply information at a given block height. If no height is given, the current height is used.\n" @@ -429,7 +429,6 @@ UniValue coinsupply(const UniValue& params, bool fHelp, const CPubKey& mypk) " \"height\" : 420, (integer) The height of this coin supply data\n" " \"supply\" : \"555.0\", (float) The transparent coin supply\n" " \"zfunds\" : \"0.55555\", (float) The shielded coin supply (in zaddrs)\n" - " \"sprout\" : \"0.000\", (float) The sprout coin supply (in zcaddrs)\n" " \"total\" : \"555.55555\", (float) The total coin supply, i.e. sum of supply + zfunds\n" "}\n" "\nExamples:\n" @@ -442,23 +441,22 @@ UniValue coinsupply(const UniValue& params, bool fHelp, const CPubKey& mypk) currentHeight = chainActive.Height(); if (height >= 0 && height <= currentHeight) { - if ( (supply= hush_coinsupply(&zfunds,&sproutfunds,height)) > 0 ) + if ( (supply= hush_coinsupply(&zfunds,height)) > 0 ) { result.push_back(Pair("result", "success")); result.push_back(Pair("coin", SMART_CHAIN_SYMBOL[0] == 0 ? "HUSH" : SMART_CHAIN_SYMBOL)); result.push_back(Pair("height", (int)height)); result.push_back(Pair("supply", ValueFromAmount(supply))); result.push_back(Pair("zfunds", ValueFromAmount(zfunds))); - result.push_back(Pair("sprout", ValueFromAmount(sproutfunds))); result.push_back(Pair("total", ValueFromAmount(zfunds + supply))); if ( ASSETCHAINS_BLOCKTIME > 0 ) { blocks_per_year = 24*3600*365 / ASSETCHAINS_BLOCKTIME; if ( height > blocks_per_year ) { - supply1 = hush_coinsupply(&zf1,&sf1,height - blocks_per_year/12); - supply3 = hush_coinsupply(&zf3,&sf3,height - blocks_per_year/4); - supply12 = hush_coinsupply(&zf12,&sf12,height - blocks_per_year); + supply1 = hush_coinsupply(&zf1,height - blocks_per_year/12); + supply3 = hush_coinsupply(&zf3,height - blocks_per_year/4); + supply12 = hush_coinsupply(&zf12,height - blocks_per_year); if ( supply1 != 0 && supply3 != 0 && supply12 != 0 ) { result.push_back(Pair("lastmonth", ValueFromAmount(supply1+zf1))); diff --git a/src/rpc/server.cpp b/src/rpc/server.cpp index 703cdc7b9..679e6ffc2 100644 --- a/src/rpc/server.cpp +++ b/src/rpc/server.cpp @@ -832,7 +832,8 @@ UniValue CRPCTable::execute(const std::string &strMethod, const UniValue ¶ms pcmd->name != "getnotarysendmany" && pcmd->name != "geterablockheights" && pcmd->name != "getaddressesbyaccount" && pcmd->name != "listaddresses" && pcmd->name != "z_exportwallet" && pcmd->name != "notaries" && pcmd->name != "signmessage" && pcmd->name != "decoderawtransaction" && - pcmd->name != "dumpprivkey" && pcmd->name != "getpeerinfo" && pcmd->name != "getnetworkinfo" ) { + pcmd->name != "dumpprivkey" && pcmd->name != "getpeerinfo" && pcmd->name != "getnetworkinfo" && + pcmd->name != "abortrescan") { throw JSONRPCError(RPC_IN_WARMUP, rpcWarmupStatus); } } diff --git a/src/transaction_builder.cpp b/src/transaction_builder.cpp index 38d7b375b..1ea61b3f8 100644 --- a/src/transaction_builder.cpp +++ b/src/transaction_builder.cpp @@ -182,7 +182,7 @@ boost::optional TransactionBuilder::Build() auto ctx = librustzcash_sapling_proving_ctx_init(); - LogPrintf("%s: Creating Sapling SpendDescriptions\n", __FUNCTION__); + LogPrintf("%s: Creating Sapling SpendDescriptions size=%d\n", __FUNCTION__, spends.size()); // Create Sapling SpendDescriptions for (auto spend : spends) { auto cm = spend.note.cm(); @@ -213,7 +213,7 @@ boost::optional TransactionBuilder::Build() sdesc.rk.begin(), sdesc.zkproof.data())) { librustzcash_sapling_proving_ctx_free(ctx); - LogPrintf("%s: Invalid sapling spend proof!\n", __FUNCTION__); + LogPrintf("%s: Invalid sapling spend proof! note value=%d\n", __FUNCTION__, spend.note.value() ); return boost::none; } diff --git a/src/txdb.cpp b/src/txdb.cpp index dbba3654f..22b70f5d5 100644 --- a/src/txdb.cpp +++ b/src/txdb.cpp @@ -269,18 +269,33 @@ bool CCoinsViewDB::GetStats(CCoinsStats &stats) const { return true; } -bool CBlockTreeDB::WriteBatchSync(const std::vector >& fileInfo, int nLastFile, const std::vector& blockinfo) { +bool CBlockTreeDB::WriteBatchSync(const std::vector >& fileInfo, int nLastFile, const std::vector& blockinfo) { CDBBatch batch(*this); if (fZdebug) fprintf(stderr, "%s: Writing block files\n", __FUNCTION__); - for (std::vector >::const_iterator it=fileInfo.begin(); it != fileInfo.end(); it++) { - batch.Write(make_pair(DB_BLOCK_FILES, it->first), *it->second); + for (const auto& it : fileInfo) { + batch.Write(make_pair(DB_BLOCK_FILES, it.first), *it.second); } batch.Write(DB_LAST_BLOCK, nLastFile); if (fZdebug) fprintf(stderr, "%s: Writing block index\n", __FUNCTION__); - for (std::vector::const_iterator it=blockinfo.begin(); it != blockinfo.end(); it++) { - batch.Write(make_pair(DB_BLOCK_INDEX, (*it)->GetBlockHash()), CDiskBlockIndex(*it)); + for (const auto& it : blockinfo) { + std::pair key = make_pair(DB_BLOCK_INDEX, it->GetBlockHash()); + try { + CDiskBlockIndex dbindex {it, [this, &key]() { + // It can happen that the index entry is written, then the Equihash solution is cleared from memory, + // then the index entry is rewritten. In that case we must read the solution from the old entry. + CDiskBlockIndex dbindex_old; + if (!Read(key, dbindex_old)) { + LogPrintf("%s: Failed to read index entry", __func__); + throw runtime_error("Failed to read index entry"); + } + return dbindex_old.GetSolution(); + }}; + batch.Write(key, dbindex); + } catch (const runtime_error&) { + return false; + } } return WriteBatch(batch, true); } @@ -293,6 +308,11 @@ bool CBlockTreeDB::EraseBatchSync(const std::vector& blockin return WriteBatch(batch, true); } +bool CBlockTreeDB::ReadDiskBlockIndex(const uint256 &blockhash, CDiskBlockIndex &dbindex) const { + return Read(make_pair(DB_BLOCK_INDEX, blockhash), dbindex); +} + + bool CBlockTreeDB::ReadTxIndex(const uint256 &txid, CDiskTxPos &pos) const { return Read(make_pair(DB_TXINDEX, txid), pos); } @@ -692,7 +712,8 @@ bool CBlockTreeDB::LoadBlockIndexGuts() pindexNew->nTime = diskindex.nTime; pindexNew->nBits = diskindex.nBits; pindexNew->nNonce = diskindex.nNonce; - pindexNew->nSolution = diskindex.nSolution; + // the Equihash solution will be loaded lazily from the dbindex entry + // pindexNew->nSolution = diskindex.nSolution; pindexNew->nStatus = diskindex.nStatus; pindexNew->nCachedBranchId = diskindex.nCachedBranchId; pindexNew->nTx = diskindex.nTx; @@ -716,10 +737,24 @@ bool CBlockTreeDB::LoadBlockIndexGuts() //fprintf(stderr,"loadguts ht.%d\n",pindexNew->GetHeight()); // Consistency checks - auto header = pindexNew->GetBlockHeader(); + /* + CBlockHeader header; + { + LOCK(cs_main); + try { + header = pindexNew->GetBlockHeader(); + } catch (const runtime_error&) { + return error("LoadBlockIndex(): failed to read index entry: diskindex hash = %s", + diskindex.GetBlockHash().ToString()); + } + } + if (header.GetHash() != diskindex.GetBlockHash()) + return error("LoadBlockIndex(): inconsistent header vs diskindex hash: header hash = %s, diskindex hash = %s", + header.GetHash().ToString(), diskindex.GetBlockHash().ToString()); if (header.GetHash() != pindexNew->GetBlockHash()) return error("LoadBlockIndex(): block header inconsistency detected: on-disk = %s, in-memory = %s", diskindex.ToString(), pindexNew->ToString()); + if ( 0 ) // POW will be checked before any block is connected { uint8_t pubkey33[33]; @@ -727,6 +762,7 @@ bool CBlockTreeDB::LoadBlockIndexGuts() if (!CheckProofOfWork(header,pubkey33,pindexNew->GetHeight(),Params().GetConsensus())) return error("LoadBlockIndex(): CheckProofOfWork failed: %s", pindexNew->ToString()); } + */ pcursor->Next(); } else { return error("LoadBlockIndex() : failed to read value"); diff --git a/src/txdb.h b/src/txdb.h index 0b0ac376c..927929960 100644 --- a/src/txdb.h +++ b/src/txdb.h @@ -26,6 +26,7 @@ #include "coins.h" #include "dbwrapper.h" +#include "chain.h" #include #include #include @@ -91,12 +92,13 @@ private: CBlockTreeDB(const CBlockTreeDB&); void operator=(const CBlockTreeDB&); public: - bool WriteBatchSync(const std::vector >& fileInfo, int nLastFile, const std::vector& blockinfo); + bool WriteBatchSync(const std::vector >& fileInfo, int nLastFile, const std::vector& blockinfo); bool EraseBatchSync(const std::vector& blockinfo); bool ReadBlockFileInfo(int nFile, CBlockFileInfo &fileinfo) const; bool ReadLastBlockFile(int &nFile) const; bool WriteReindexing(bool fReindex); bool ReadReindexing(bool &fReindex) const; + bool ReadDiskBlockIndex(const uint256 &blockhash, CDiskBlockIndex &dbindex) const; bool ReadTxIndex(const uint256 &txid, CDiskTxPos &pos) const; bool WriteTxIndex(const std::vector > &list); bool ReadSpentIndex(CSpentIndexKey &key, CSpentIndexValue &value) const; diff --git a/src/validationinterface.cpp b/src/validationinterface.cpp index 12cabfac5..62ba5ea80 100644 --- a/src/validationinterface.cpp +++ b/src/validationinterface.cpp @@ -32,7 +32,13 @@ void RegisterValidationInterface(CValidationInterface* pwalletIn) { g_signals.UpdatedTransaction.connect(boost::bind(&CValidationInterface::UpdatedTransaction, pwalletIn, _1)); g_signals.ChainTip.connect(boost::bind(&CValidationInterface::ChainTip, pwalletIn, _1, _2, _3)); g_signals.SetBestChain.connect(boost::bind(&CValidationInterface::SetBestChain, pwalletIn, _1)); - g_signals.Broadcast.connect(boost::bind(&CValidationInterface::ResendWalletTransactions, pwalletIn, _1)); + + if(GetArg("-resendtx", true)) { + g_signals.Broadcast.connect(boost::bind(&CValidationInterface::ResendWalletTransactions, pwalletIn, _1)); + } else { + LogPrintf("%s: automatic resending of wallet transactions disabled\n", __func__); + } + g_signals.BlockChecked.connect(boost::bind(&CValidationInterface::BlockChecked, pwalletIn, _1, _2)); //g_signals.ScriptForMining.connect(boost::bind(&CValidationInterface::GetScriptForMining, pwalletIn, _1)); } @@ -40,7 +46,9 @@ void RegisterValidationInterface(CValidationInterface* pwalletIn) { void UnregisterValidationInterface(CValidationInterface* pwalletIn) { //g_signals.ScriptForMining.disconnect(boost::bind(&CValidationInterface::GetScriptForMining, pwalletIn, _1)); g_signals.BlockChecked.disconnect(boost::bind(&CValidationInterface::BlockChecked, pwalletIn, _1, _2)); - g_signals.Broadcast.disconnect(boost::bind(&CValidationInterface::ResendWalletTransactions, pwalletIn, _1)); + if(GetArg("-resendtx", true)) { + g_signals.Broadcast.disconnect(boost::bind(&CValidationInterface::ResendWalletTransactions, pwalletIn, _1)); + } g_signals.ChainTip.disconnect(boost::bind(&CValidationInterface::ChainTip, pwalletIn, _1, _2, _3)); g_signals.SetBestChain.disconnect(boost::bind(&CValidationInterface::SetBestChain, pwalletIn, _1)); g_signals.UpdatedTransaction.disconnect(boost::bind(&CValidationInterface::UpdatedTransaction, pwalletIn, _1)); @@ -135,9 +143,6 @@ void ThreadNotifyWallets(CBlockIndex *pindexLastTip) while (pindex && pindex != pindexFork) { // Get the Sprout commitment tree as of the start of this block. SproutMerkleTree oldSproutTree; - //TODO: how important is oldSproutTree ? - //assert(pcoinsTip->GetSproutAnchorAt(pindex->hashSproutAnchor, oldSproutTree)); - // Get the Sapling commitment tree as of the start of this block. // We can get this from the `hashFinalSaplingRoot` of the last block // However, this is only reliable if the last block was on or after diff --git a/src/version.h b/src/version.h index 2f44a9d9d..504e38f4a 100644 --- a/src/version.h +++ b/src/version.h @@ -21,7 +21,7 @@ #define HUSH_VERSION_H // network protocol versioning -static const int PROTOCOL_VERSION = 1987425; +static const int PROTOCOL_VERSION = 1987426; //! initial proto version, to be increased after version/verack negotiation static const int INIT_PROTO_VERSION = 209; //! In this version, 'getheaders' was introduced. diff --git a/src/wallet/rpcdump.cpp b/src/wallet/rpcdump.cpp index 79463087d..39b5caf38 100644 --- a/src/wallet/rpcdump.cpp +++ b/src/wallet/rpcdump.cpp @@ -515,14 +515,15 @@ UniValue importwallet_impl(const UniValue& params, bool fHelp, bool fImportZKeys auto addResult = boost::apply_visitor( AddSpendingKeyToWallet(pwalletMain, Params().GetConsensus(), nTime, hdKeypath, seedFpStr, true), spendingkey); if (addResult == KeyAlreadyExists){ - LogPrint("zrpc", "Skipping import of zaddr (key already present)\n"); + LogPrintf("%s: Skipping import of zaddr (key already present)\n", __func__); } else if (addResult == KeyNotAdded) { // Something went wrong fGood = false; + LogPrintf("%s: Skipping import of zaddr (something went wrong)\n", __func__); } continue; } else { - LogPrint("zrpc", "Importing detected an error: invalid spending key. Trying as a transparent key...\n"); + LogPrintf("%s: Importing detected an error: invalid spending key. Trying as a transparent key...\n",__func__); // Not a valid spending key, so carry on and see if it's a Hush transparent address } } diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index cdf16c695..491cab182 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -3304,12 +3304,13 @@ UniValue z_listreceivedaddress(const UniValue& params, bool fHelp,const CPubKey& if (!EnsureWalletIsAvailable(fHelp)) return NullUniValue; - if (fHelp || params.size() > 5 || params.size() == 3) + if (fHelp || params.size() > 5 || params.size() < 1) throw runtime_error( "z_listreceivedaddress\n" "\nReturns received outputs.\n" "\n" "This function only returns information on addresses with full spending keys." + "This function is slow if no filters are given, use z_listreceivedbyaddress if you do not need filters." "\n" "\nArguments:\n" "1. \"hushaddress:\" (string, required) \n" @@ -3349,13 +3350,13 @@ UniValue z_listreceivedaddress(const UniValue& params, bool fHelp,const CPubKey& " \"walletconflicts\": [conflicts], An array of wallet conflicts\n" " \"recieved\": { A list of receives from the transaction\n" " \"transparentReceived\": [{ An Array of txos received for transparent addresses\n" - " \"address\": \"zeroaddress\", (string) Hush transparent address (t-address)\n" + " \"address\": \"hushaddress\", (string) Hush transparent address (t-address)\n" " \"scriptPubKey\": \"script\", (string) Script for the transparent address (t-address)\n" " \"amount\": x.xxxx, (numeric) Value of output being received " + CURRENCY_UNIT + ", positive for receives\n" " \"vout\": : n, (numeric) the vout value\n" " }],\n" " \"saplingReceived\": [{ An Array of utxos/notes received for sapling addresses\n" - " \"address\": \"zeroaddress\", (string) Shielded address (z-address)\n" + " \"address\": \"hushaddress\", (string) Shielded address (z-address)\n" " \"amount\": x.xxxx, (numeric) Value of output being received " + CURRENCY_UNIT + ", positive for receives\n" " \"memo\": xxxxx, (string) hexademical string representation of memo field\n" " \"memoStr\" : \"memo\", (string) Only returned if memo contains valid UTF-8 text.\n" @@ -3375,7 +3376,7 @@ UniValue z_listreceivedaddress(const UniValue& params, bool fHelp,const CPubKey& UniValue ret(UniValue::VARR); - //param values` + //param values int64_t nMinConfirms = 0; int64_t nFilterType = 0; int64_t nFilter = 999999; @@ -3636,6 +3637,224 @@ UniValue z_listsentbyaddress(const UniValue& params, bool fHelp,const CPubKey&) return ret; } +UniValue z_getstats(const UniValue& params, bool fHelp, const CPubKey& mypk) +{ + if (!EnsureWalletIsAvailable(fHelp)) + return NullUniValue; + + if (fHelp || params.size() < 1 || params.size() > 2) + throw runtime_error( + "z_getstats\n" + "\nReturns statistics about ztxs in block height or block height range\n" + "\nArguments:\n" + "1. \"height\" (number, required) The block height\n" + "1. \"end_height\" (number, optional) The ending block height\n" + "\nResult:\n" + "\njson\n" + "\nExamples:\n" + + HelpExampleCli("z_getstats 123", "456") + + HelpExampleRpc("z_getstats 123", "456") + ); + + LOCK2(cs_main, pwalletMain->cs_wallet); + std::string strHeight = params[0].get_str(); + int nHeight = -1; + try { + nHeight = std::stoi(strHeight); + } catch (const std::exception &e) { + throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid block height parameter"); + } + + if (nHeight < 0 || nHeight > chainActive.Height()) { + throw JSONRPCError(RPC_INVALID_PARAMETER, "Block height out of range"); + } + auto strHash = chainActive[nHeight]->GetBlockHash().GetHex(); + uint256 hash(uint256S(strHash)); + + if (mapBlockIndex.count(hash) == 0) + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Block not found"); + + CBlock block; + CBlockIndex* pblockindex = mapBlockIndex[hash]; + + if (fHavePruned && !(pblockindex->nStatus & BLOCK_HAVE_DATA) && pblockindex->nTx > 0) + throw JSONRPCError(RPC_INTERNAL_ERROR, "Block not available (pruned data)"); + + if(!ReadBlockFromDisk(block, pblockindex,1)) + throw JSONRPCError(RPC_INTERNAL_ERROR, "Can't read block from disk"); + + int total_ztxs = 0, total_zins = 0, total_zouts = 0; + int total_ztxs_10_or_more_zins = 0, total_ztxs_10_or_more_zouts = 0; + int total_ztxs_25_or_more_zins = 0, total_ztxs_25_or_more_zouts = 0; + int total_ztxs_50_or_more_zins = 0, total_ztxs_50_or_more_zouts = 0; + int total_ztxs_100_or_more_zins = 0, total_ztxs_100_or_more_zouts = 0; + int largest_zins = 0, largest_zouts = 0; + std::string largest_zins_txid = "", largest_zouts_txid = ""; + UniValue ret(UniValue::VOBJ); + ret.pushKV("start_height", nHeight); + + // given a single block height, we calculate stats for that height + if (params.size() == 1) { + BOOST_FOREACH(const CTransaction&tx, block.vtx) + { + int num_zins, num_zouts = 0; + // ignore coinbase txs which have no zins or zouts + if(!tx.IsCoinBase()) { + num_zouts = tx.vShieldedOutput.size(); + num_zins = tx.vShieldedSpend.size(); + // tx must have some zins and zouts to count towards our stats, + // which ignores shielding coinbase txs, which have only transparent inputs. + // This mostly will only count "z2z" txs but also counts (z,t)=>z and z=>(z,t) + // which are possible but unlikely, since RPCs cannot currently create (z,t)=>z txs + // and z=>(z,t) are disallowed when ac_private=1 + if(num_zins > 0 && num_zouts > 0) { + total_ztxs++; + total_zins += num_zins; + total_zouts += num_zouts; + if (num_zins > largest_zins) { + largest_zins = num_zins; + largest_zins_txid = tx.GetHash().ToString(); + } + if (num_zouts > largest_zouts) { + largest_zouts = num_zouts; + largest_zouts_txid = tx.GetHash().ToString(); + } + if (num_zins >= 10) { + total_ztxs_10_or_more_zins++; + if (num_zins >= 25) { + total_ztxs_25_or_more_zins++; + if (num_zins >= 50) { + total_ztxs_50_or_more_zins++; + if (num_zins >= 100) { + total_ztxs_100_or_more_zins++; + } + } + } + } + if (num_zouts >= 10) { + total_ztxs_10_or_more_zouts++; + if (num_zouts >= 25) { + total_ztxs_25_or_more_zouts++; + if (num_zouts >= 50) { + total_ztxs_50_or_more_zouts++; + if (num_zouts >= 100) { + total_ztxs_100_or_more_zouts++; + } + } + } + } + + + } + } + } + } else { + // given two blocks, we calculate stats for that range + std::string strHeight2 = params[1].get_str(); + int nHeight2 = -1; + try { + nHeight2 = std::stoi(strHeight2); + } catch (const std::exception &e) { + throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid ending block height parameter"); + } + + if (nHeight2 <= nHeight) { + throw JSONRPCError(RPC_INVALID_PARAMETER, "Ending block height must be larger than starting height"); + } + + if (nHeight2 < 0 || nHeight2 > chainActive.Height()) { + throw JSONRPCError(RPC_INVALID_PARAMETER, "Ending block height out of range"); + } + + ret.pushKV("end_height", nHeight2); + + // get the stats for every block in the range + for(int currentHeight = nHeight; currentHeight <= nHeight2; currentHeight++) { + auto strHash = chainActive[currentHeight]->GetBlockHash().GetHex(); + uint256 hash(uint256S(strHash)); + + if (mapBlockIndex.count(hash) == 0) + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Block not found"); + + CBlock block; + CBlockIndex* pblockindex = mapBlockIndex[hash]; + + if (fHavePruned && !(pblockindex->nStatus & BLOCK_HAVE_DATA) && pblockindex->nTx > 0) + throw JSONRPCError(RPC_INTERNAL_ERROR, "Block not available (pruned data)"); + + if(!ReadBlockFromDisk(block, pblockindex,1)) + throw JSONRPCError(RPC_INTERNAL_ERROR, "Can't read block from disk"); + + BOOST_FOREACH(const CTransaction&tx, block.vtx) + { + int num_zins, num_zouts = 0; + // ignore coinbase txs which have no zins or zouts + if(!tx.IsCoinBase()) { + num_zouts = tx.vShieldedOutput.size(); + num_zins = tx.vShieldedSpend.size(); + if(num_zins > 0 && num_zouts > 0) { + total_ztxs++; + total_zins += num_zins; + total_zouts += num_zouts; + } + if (num_zins > largest_zins) { + largest_zins = num_zins; + largest_zins_txid = tx.GetHash().ToString(); + } + if (num_zouts > largest_zouts) { + largest_zouts = num_zouts; + largest_zouts_txid = tx.GetHash().ToString(); + } + if (num_zins >= 10) { + total_ztxs_10_or_more_zins++; + if (num_zins >= 25) { + total_ztxs_25_or_more_zins++; + if (num_zins >= 50) { + total_ztxs_50_or_more_zins++; + if (num_zins >= 100) { + total_ztxs_100_or_more_zins++; + } + } + } + } + if (num_zouts >= 10) { + total_ztxs_10_or_more_zouts++; + if (num_zouts >= 25) { + total_ztxs_25_or_more_zouts++; + if (num_zouts >= 50) { + total_ztxs_50_or_more_zouts++; + if (num_zouts >= 100) { + total_ztxs_100_or_more_zouts++; + } + } + } + } + } + } + } + } + double avg_zins = total_ztxs > 0 ? (double) total_zins / total_ztxs : 0.0; + double avg_zouts = total_ztxs > 0 ? (double) total_zouts / total_ztxs : 0.0; + ret.pushKV("total_ztxs", total_ztxs); + ret.pushKV("total_zins", total_zins); + ret.pushKV("total_zouts", total_zouts); + ret.pushKV("total_ztxs_10_or_more_zins", total_ztxs_10_or_more_zins); + ret.pushKV("total_ztxs_25_or_more_zins", total_ztxs_25_or_more_zins); + ret.pushKV("total_ztxs_50_or_more_zins", total_ztxs_50_or_more_zins); + ret.pushKV("total_ztxs_100_or_more_zins", total_ztxs_100_or_more_zins); + ret.pushKV("total_ztxs_10_or_more_zouts", total_ztxs_10_or_more_zouts); + ret.pushKV("total_ztxs_25_or_more_zouts", total_ztxs_25_or_more_zouts); + ret.pushKV("total_ztxs_50_or_more_zouts", total_ztxs_50_or_more_zouts); + ret.pushKV("total_ztxs_100_or_more_zouts", total_ztxs_100_or_more_zouts); + ret.pushKV("avg_zins", avg_zins); + ret.pushKV("avg_zouts", avg_zouts); + ret.pushKV("largest_zins", largest_zins); + ret.pushKV("largest_zins_txid", largest_zins_txid); + ret.pushKV("largest_zouts", largest_zouts); + ret.pushKV("largest_zouts_txid", largest_zouts_txid); + return ret; +} + UniValue z_anonsetblockdelta(const UniValue& params, bool fHelp, const CPubKey& mypk) { if (!EnsureWalletIsAvailable(fHelp)) @@ -3892,6 +4111,7 @@ UniValue z_listunspent(const UniValue& params, bool fHelp, const CPubKey& mypk) " \"address\" : \"address\", (string) the shielded address\n" " \"amount\": xxxxx, (numeric) the amount of value in the note\n" " \"memo\": xxxxx, (string) hexademical string representation of memo field\n" + " \"memoStr\" : \"memo\", (string) Only returned if memo contains valid UTF-8 text.\n" " \"change\": true|false, (boolean) true if the address that received the note is also one of the sending addresses\n" " }\n" " ,...\n" @@ -3998,6 +4218,14 @@ UniValue z_listunspent(const UniValue& params, bool fHelp, const CPubKey& mypk) obj.push_back(Pair("address", EncodePaymentAddress(entry.address))); obj.push_back(Pair("amount", ValueFromAmount(CAmount(entry.note.value())))); // note.value() is equivalent to plaintext.value() obj.push_back(Pair("memo", HexStr(entry.memo))); + auto memo = entry.memo; + if (memo[0] <= 0xf4) { + auto end = std::find_if(memo.rbegin(), memo.rend(), [](unsigned char v) { return v != 0; }); + std::string memoStr(memo.begin(), end.base()); + if (utf8::is_valid(memoStr)) { + obj.push_back(Pair("memoStr", memoStr)); + } + } if (hasSaplingSpendingKey) { obj.push_back(Pair("change", pwalletMain->IsNoteSaplingChange(nullifierSet, entry.address, entry.op))); } @@ -4252,6 +4480,7 @@ UniValue z_listreceivedbyaddress(const UniValue& params, bool fHelp, const CPubK " \"txid\": xxxxx, (string) the transaction id\n" " \"amount\": xxxxx, (numeric) the amount of value in the note\n" " \"memo\": xxxxx, (string) hexadecimal string representation of memo field\n" + " \"memoStr\" : \"memo\", (string) Only returned if memo contains valid UTF-8 text.\n" " \"confirmations\" : n, (numeric) the number of notarized confirmations (dpowconfs)\n" " \"rawconfirmations\" : n, (numeric) the number of raw confirmations\n" " \"outindex\" (sapling) : n, (numeric) the output index\n" @@ -5449,8 +5678,10 @@ UniValue z_mergetoaddress(const UniValue& params, bool fHelp, const CPubKey& myp if (address == "ANY_TADDR") { useAnyUTXO = true; - } else if (address == "ANY_SAPLING") { + } else if (address == "ANY_ZADDR" || address == "ANY_SAPLING") { useAnySapling = true; + } else if (address == "*") { + useAnyUTXO = useAnySapling = true; } else { CTxDestination taddr = DecodeDestination(address); if (IsValidDestination(taddr)) { @@ -5474,7 +5705,7 @@ UniValue z_mergetoaddress(const UniValue& params, bool fHelp, const CPubKey& myp throw JSONRPCError(RPC_INVALID_PARAMETER, "Cannot specify specific t-addrs when using \"ANY_TADDR\""); } if ((useAnySapling) && zaddrs.size() > 0) { - throw JSONRPCError(RPC_INVALID_PARAMETER, "Cannot specify specific z-addrs when using \"ANY_SAPLING\""); + throw JSONRPCError(RPC_INVALID_PARAMETER, "Cannot specify specific z-addrs when using \"ANY_SAPLING\" or \"ANY_ZADDR\""); } const int nextBlockHeight = chainActive.Height() + 1; @@ -8489,6 +8720,7 @@ static const CRPCCommand commands[] = { "wallet", "z_listunspent", &z_listunspent, false }, { "wallet", "z_getbalance", &z_getbalance, false }, { "wallet", "z_getbalances", &z_getbalances, false }, + { "wallet", "z_getstats", &z_getstats, true }, { "wallet", "z_anonsettxdelta", &z_anonsettxdelta, true }, { "wallet", "z_anonsetblockdelta", &z_anonsetblockdelta, true }, { "wallet", "z_gettotalbalance", &z_gettotalbalance, false }, diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index 96d01260d..3071d46a7 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -67,6 +67,7 @@ bool fPayAtLeastCustomFee = true; CBlockIndex *hush_chainactive(int32_t height); extern std::string DONATION_PUBKEY; +extern int32_t HUSH_LOADINGBLOCKS; int32_t hush_dpowconfs(int32_t height,int32_t numconfs); int tx_height( const uint256 &hash ); bool fTxDeleteEnabled = false; @@ -1146,6 +1147,15 @@ void CWallet::BuildWitnessCache(const CBlockIndex* pindex, bool witnessOnly) LogPrintf("%s: height=%d, startHeight=%d\n", __func__, height, startHeight); while (pblockindex) { + if (ShutdownRequested()) { + LogPrintf("%s: shutdown requested, aborting building witnesses\n", __func__); + break; + } + if(pwalletMain->fAbortRescan) { + LogPrintf("%s: rescan aborted at block %d, stopping witness building\n", pwalletMain->rescanHeight); + pwalletMain->fRescanning = false; + return; + } if (pblockindex->GetHeight() % 100 == 0 && pblockindex->GetHeight() < height - 5) { LogPrintf("Building Witnesses for block %i %.4f complete, %d remaining\n", pblockindex->GetHeight(), pblockindex->GetHeight() / double(height), height - pblockindex->GetHeight() ); @@ -3107,6 +3117,7 @@ std::vector CWallet::ResendWalletTransactionsBefore(int64_t nTime) // Sort them in chronological order multimap mapSorted; uint32_t now = (uint32_t)time(NULL); + LogPrintf("%s: nTime=%ld now=%d\n", __func__, nTime, now); // vector of wallet transactions to delete std::vector vwtxh; @@ -3184,11 +3195,26 @@ void CWallet::ResendWalletTransactions(int64_t nBestBlockTime) if (fFirst) return; + // do not resend during IBD/rescan because some txs will be unconfirmed + // until completion + if(IsInitialBlockDownload()) { + return; + } + if (pwalletMain->fRescanning) { + return; + } + + // do not resend during a reindex or initial loading of blocks + if (HUSH_LOADINGBLOCKS) { + return; + } + // Only do it if there's been a new block since last time if (nBestBlockTime < nLastResend) return; nLastResend = GetTime(); + LogPrintf("%s: nBestBlockTime=%ld nNextResend=%ld nLastResend=%ld time=%ld\n", __func__, nBestBlockTime, nNextResend, nLastResend, GetTime()); // Rebroadcast unconfirmed txes older than 5 minutes before the last // block was found: std::vector relayed = ResendWalletTransactionsBefore(nBestBlockTime-5*60); @@ -3198,15 +3224,11 @@ void CWallet::ResendWalletTransactions(int64_t nBestBlockTime) /** @} */ // end of mapWallet - - - /** @defgroup Actions * * @{ */ - CAmount CWallet::GetBalance() const { CAmount nTotal = 0; diff --git a/src/wallet/walletdb.cpp b/src/wallet/walletdb.cpp index 633962c19..2fe1a19f4 100644 --- a/src/wallet/walletdb.cpp +++ b/src/wallet/walletdb.cpp @@ -1233,8 +1233,13 @@ bool CWalletDB::Recover(CDBEnv& dbenv, const std::string& filename, bool fOnlyKe CDataStream ssKey(row.first, SER_DISK, CLIENT_VERSION); CDataStream ssValue(row.second, SER_DISK, CLIENT_VERSION); string strType, strErr; - bool fReadOK = ReadKeyValue(&dummyWallet, ssKey, ssValue, + bool fReadOK; + { + // Required in LoadKeyMetadata(): + LOCK(dummyWallet.cs_wallet); + fReadOK = ReadKeyValue(&dummyWallet, ssKey, ssValue, wss, strType, strErr); + } if (!IsKeyType(strType)) continue; if (!fReadOK) diff --git a/test_antispam b/test_antispam new file mode 100755 index 000000000..5ccfb4752 --- /dev/null +++ b/test_antispam @@ -0,0 +1,10 @@ +#!/usr/bin/env bash + +# any CLI args given to this script will be passed along +# example: ./test_antispam -debug=blah +#./src/hushd -ac_name=ANTISPAM -ac_private=1 -ac_blocktime=180 -ac_reward=500000000 -ac_supply=55555 -gen=1 -genproclimit=1 -testnode=1 $@ + +./src/hushd -ac_name=ANTISPAM -ac_private=1 -ac_blocktime=180 -ac_reward=500000000 -ac_supply=55555 $@ +# to run via the debugger +# type "run" when gdb prompt appears +#gdb --args ./src/hushd -- -ac_algo=randomx -ac_name=ANTISPAM -ac_private=1 -ac_blocktime=180 -ac_reward=500000000 -ac_supply=55555 -gen=1 -genproclimit=1 -testnode=1 diff --git a/util/README.md b/util/README.md index 0c7408f4d..d11b0e02f 100644 --- a/util/README.md +++ b/util/README.md @@ -12,6 +12,11 @@ Compile Hush full node code. ## build-arm.sh Compile Hush full node code for ARM architecture. +**has not worked for some time** + +## build-arm-xcompile.sh + +Cross-Compile Hush full node code for ARM architecture on an x86 build server. ## build-debian-package.sh diff --git a/util/build-arm-xcompile.sh b/util/build-arm-xcompile.sh new file mode 100755 index 000000000..6be684464 --- /dev/null +++ b/util/build-arm-xcompile.sh @@ -0,0 +1,139 @@ +#!/usr/bin/env bash +# Copyright (c) 2016-2023 The Hush developers +# Distributed under the GPLv3 software license, see the accompanying +# file COPYING or https://www.gnu.org/licenses/gpl-3.0.en.html + +# For use with https://git.hush.is/jahway603/hush-docs/src/branch/master/advanced/cross-compile-hush-full-node-to-aarch64-with-docker.md, +# Please follow that +set -eu -o pipefail + +# Check if cmake, a new dependency for randomx support, is installed on system and exits if it is not +if ! [ -x "$(command -v cmake)" ]; then + echo 'Error: cmake is not installed. Install cmake and try again.' >&2 + exit 1 +fi + +function cmd_pref() { + if type -p "$2" > /dev/null; then + eval "$1=$2" + else + eval "$1=$3" + fi +} +cat <<'EOF' + .~~~~~~~~~~~~~~~~. +{{ Building Hush!! }} + `~~~~~~~~~~~~~~~~` + \ ^__^ + \ (@@)\_______ + (__)\ HUSH )\/\ $ + z zz ||----w | z | +zz zz z || z ||xxx z z|z zz +zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz +zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz +EOF + +# If a g-prefixed version of the command exists, use it preferentially. +function gprefix() { + cmd_pref "$1" "g$2" "$2" +} + +gprefix READLINK readlink +cd "$(dirname "$("$READLINK" -f "$0")")/.." + +# Allow user overrides to $MAKE. Typical usage for users who need it: +# MAKE=gmake ./util/build.sh -j$(nproc) +if [[ -z "${MAKE-}" ]]; then + MAKE=make +fi + +# Allow overrides to $BUILD and $HOST for porters. Most users will not need it. +# BUILD=i686-pc-linux-gnu ./util/build.sh +if [[ -z "${BUILD-}" ]]; then + BUILD="$(./depends/config.guess)" +fi +if [[ -z "${HOST-}" ]]; then + HOST="$BUILD" +fi + +# Allow users to set arbitrary compile flags. Most users will not need this. +if [[ -z "${CONFIGURE_FLAGS-}" ]]; then + CONFIGURE_FLAGS="" +fi + +if [ "x$*" = 'x--help' ] +then + cat ./util/dragon.txt + cat <; + unless($taddr) { + print "Error: Less than $N addresses in $file !\n"; + exit(1); + } + } else { + $taddr = qx{$getnew}; + } + chomp $taddr; + my $j = qx{$validate $taddr}; + my $json = decode_json($j); + my $scriptpub = $json->{scriptPubKey}; + printf qq!{"%s", "%s"},\n!, $taddr, $scriptpub; +} + +print "};\n"; +close($fh) if $file;