Compare commits

...

247 Commits

Author SHA1 Message Date
wowario 589efde6b3
update README
2 weeks ago
jeffro256 cb63c922f8
ringct: fix trunc_amount field name change
2 weeks ago
jeffro256 eeec04520d
Revert "http_client: reduce number of packets sent for small bodies"
2 weeks ago
selsta 3605ec6419
depends: add riscv64 linux build tag
2 weeks ago
dsc dad8e3cadd
Add CoinsInfo->description and 'preferred_inputs' to create_transaction
3 weeks ago
wowario c2d9ac9d16
update checkpoints
3 weeks ago
wowario e707dafd04
bump version
3 weeks ago
dsc aa19aa8fc3
enable refresh thread
3 weeks ago
dsc 269fd51d34
add hex() and txKey() to PendingTransaction
3 weeks ago
dsc ea1ff89671
compile fix
3 weeks ago
wowario a46db6fbf9
Update RandomWOW to 1.2.1-wow
3 weeks ago
wowario 1fb180a69b
add more seeds
3 weeks ago
wowario cf5bfd0cc4
disable mismatched daemon check
3 weeks ago
wowario 6a5303f21b
remove nudge in daemon_is_outdated
3 weeks ago
wowario 5a127e006e
[README] bump version
3 weeks ago
wowario 93e542dc55
update checkpoints
3 weeks ago
wowario cae358334e
remove nudge in num_mainnet_hard_forks
3 weeks ago
_XxFedexX_ f0e9542c06
Add _xxfedexx_'s PGP key
3 weeks ago
wowario 2f3f3b7a6e
remove rx_set code
3 weeks ago
wowario b414a0659d
use rx_set_miner_thread after RX_BLOCK_VERSION
3 weeks ago
thotbot 3f78176f3d
Import transaction
3 weeks ago
moneromooo-monero f438928ed8
simplewallet: print fully qualified filename for new wallets
3 weeks ago
wowario b07e533a8f
show wallet info
3 weeks ago
hinto-janaiyo 8ccfd46a41
simplewallet/wallet2: set option - show-detailed-prompt
3 weeks ago
thotbot e60954b619
Misc. network related
3 weeks ago
thotbot 1ed861bff8
Skip unneeded blocks in fast refresh
3 weeks ago
thotbot 8b467e98a4
subaddressIndex()
3 weeks ago
thotbot 4f8ad5bfac
Print wallet cache
3 weeks ago
thotbot 3234b5fe62
Misc. wallet API and wallet2 changes
3 weeks ago
thotbot e6cc37e9b0
Coins
3 weeks ago
thotbot fcffffdd5d
Offline transaction signing
3 weeks ago
wowario 77ca74ba54
update checkpoints
3 weeks ago
wowario 8d78cedaec
connect to updated seeds
3 weeks ago
wowario e8bec95650
add wowario PGP key
3 weeks ago
wowario 36dc60fdfd
Revoke old pgp key
3 weeks ago
wowario f742aed6a3
support old ass BPs
3 weeks ago
wowario b602ab02ee
revert sanity check
3 weeks ago
wowario f409249b78
wallet seed message spacing
3 weeks ago
wowario 0bb22452ac
remove warning reusing keys
3 weeks ago
wowario 8337a81ef5
remove warning about background mining
3 weeks ago
wowario 6ca2369b67
add clear screen command
3 weeks ago
wowario 934cd71608
wownero chan
3 weeks ago
wowario b2906602a4
update README.md
3 weeks ago
wowario df381eaa84
update checkpoints
3 weeks ago
wowario 83a0e91e23
set fork height
3 weeks ago
wowario 26d039db0a
from v20, limit tx extra size
3 weeks ago
wowario 662a2993d3
Debug level No incoming connections
3 weeks ago
wowario 65570252f2
update checkpoints
3 weeks ago
wowario eff55d073c
uri remainder
3 weeks ago
wowario d1441bc034
update README.md
3 weeks ago
wowario 5e50141c4a
remove testnet/stagenet fork heights/blocks
3 weeks ago
wowario 8c081b4b02
don't request pre-bulletprooof pruned blocks
3 weeks ago
wowario 917970cebf
change to debug level
3 weeks ago
wowario c7190cdd0f
rename ringdb-dir
3 weeks ago
wowario a177241046
mod variant4_random_math
3 weeks ago
wowario e224b4af93
support old BP
3 weeks ago
wowario 0c4915d707
vote by block
3 weeks ago
wowario ff34adf8b7
tidy up miner msgs
3 weeks ago
wowario 48841789cb
miner block header signing
3 weeks ago
wowario 2ddaa7835c
difficulty is fun
3 weeks ago
wowario aa7564806d
shorten timestamp check window
3 weeks ago
wowario a0a90ada1a
limit future blk time to 10 min
3 weeks ago
wowario 7b9bfb73b1
bump unlock time to 288 blks
3 weeks ago
wowario 642beba4af
broadcast donation sub-address
3 weeks ago
wowario cf8e878869
revert Preserve commitment format inside transactions #8277
3 weeks ago
wowario 6afdd7894a
add systemd file
3 weeks ago
wowario 7f01ebbf29
update gitian
3 weeks ago
wowario 6fee906b1c
update Dockerfile
3 weeks ago
wowario 0fd82de0be
adjust approx_blockchain_height
3 weeks ago
wowario 68f1f2b2c3
add wowario gpg key
3 weeks ago
wowario ddf990f394
config wallet2 settings
3 weeks ago
wowario 196a3756d6
set dev fund address
3 weeks ago
wowario 4ed9b68d59
add seed nodes
3 weeks ago
wowario 37195f2128
set name of daemon stdout
3 weeks ago
wowario e71bef4496
set last v1 block
3 weeks ago
wowario a04690c66b
set pow variants
3 weeks ago
wowario 9c3fb6c243
set quick height for syncing
3 weeks ago
wowario 463de38ef5
send dump log to wowario
3 weeks ago
wowario c474334f41
set genesis block timestamp
3 weeks ago
wowario ce3a67ed21
set decimal point
3 weeks ago
wowario fb39891031
add forks and checkpoints
3 weeks ago
wowario 1c44d89030
wownero skin pack
3 weeks ago
wowario da6a2dc2c5
bump RX block version
3 weeks ago
wowario d6a3511d59
correct length of addresses
3 weeks ago
wowario 6b8e245aea
move utilities to debug build
3 weeks ago
wowario 917edfbec9
automatic submodule update
3 weeks ago
wowario 5964374c4b
Doxygen off
3 weeks ago
wowario a5d50332ca
trezor support off
3 weeks ago
wowario 73f52ea6b9
turn off tests
3 weeks ago
wowario 1cae37348a
gitian: copy config file
3 weeks ago
wowario 2b78ff8117
add RandomWOW
3 weeks ago
wowario e5016a6f8e
show full version
3 weeks ago
wowario a93dcc1962
remove moneropulse urls
3 weeks ago
wowario a25032cc1e
remove monero tx bug fixes
3 weeks ago
wowario 2a4e1c6913
bump ring size to 22
3 weeks ago
wowario 3271844ab5
initialize genesis block
3 weeks ago
wowario 7af83ced4c
config cryptonote
3 weeks ago
luigi1111 ef3e18b51b
Merge pull request #9226
3 weeks ago
SChernykh b5b72ae05c Fixed mempool pruning
3 weeks ago
luigi1111 5eb3fc29bb
Merge pull request #9223
3 weeks ago
luigi1111 c225a1f25b
Merge pull request #9224
3 weeks ago
luigi1111 ff15cb2f04
Merge pull request #9220
3 weeks ago
jeffro256 eeb7c7c546
tx_memory_pool: make double spends a no-drop offense
3 weeks ago
SChernykh 36ee12bd8d get_block_template_backlog: better sorting logic
3 weeks ago
selsta 32b3a56313
wallet2: adjust fee during backlog, fix set priority
3 weeks ago
luigi1111 b23116424d
Merge pull request #9217
3 weeks ago
jeffro256 7807f569e4
unit_tests: fix strtoul unit test
3 weeks ago
luigi1111 68e40ea2a7
Merge pull request #9158
1 month ago
luigi1111 c6ff0d3820
Merge pull request #9136
1 month ago
luigi1111 0d2f515ecc
Merge pull request #9190
1 month ago
luigi1111 522d82276e
Merge pull request #9188
1 month ago
luigi1111 4f6f6d9e27
Merge pull request #9178
1 month ago
luigi1111 3872753202
Merge pull request #9159
1 month ago
luigi1111 13ed9d501b
Merge pull request #9156
1 month ago
luigi1111 b335433204
Merge pull request #9145
1 month ago
luigi1111 8a1e49664e
Merge pull request #9142
1 month ago
luigi1111 2f912f8a58
Merge pull request #9130
1 month ago
luigi1111 81f113dd8c
Merge pull request #9008
1 month ago
luigi1111 f9a7f2a136
Merge pull request #8945
1 month ago
selsta c97c2ec01c
docs: omit i2p port number from ANONYMITY_NETWORKS
1 month ago
jeffro256 51d7a6921c
wallet: feature: transfer amount with fee included
1 month ago
selsta f2360a725e
build: prepare v0.18.3.2
1 month ago
selsta 0cc8f7aaa3
cryptonote_core: early out on out of bounds scaling parameter
1 month ago
tobtoht b987870553
depends: openssl: update to 3.0.13
1 month ago
tobtoht 3aabfcfce5
depends: unbound: update to 1.19.1
1 month ago
tobtoht 8322f9c4f5
depends: expat: update to 2.6.0
1 month ago
woodser fbd0b19fc8 remove ARCH=x86-64 from release-static
2 months ago
jeffro256 33e3f72d24
serialization: fix infinite loops and clean up dispatching
2 months ago
Lee *!* Clagett 052df1b28c Zero initialize rctSigBase elements
2 months ago
Lee Clagett 98ee46f249 Disable/fix ports with I2P
2 months ago
Lee *!* Clagett f5b86342e8 Add <cstdint> to aligned test
2 months ago
jeffro256 dfb990e8bb
wallet: mitigate statistical dependence for decoy selection within rings
2 months ago
luigi1111 8eab181fe1
Merge pull request #9080
2 months ago
luigi1111 9a70f43440
Merge pull request #9053
2 months ago
Lee Clagett 47d8899c90 Fix missing checks for IsObject in ZMQ jsonrpc reading
4 months ago
luigi1111 c09062087e
Merge pull request #9051
5 months ago
luigi1111 9a5f8431b4
Merge pull request #9047
5 months ago
luigi1111 79107ff68f
Merge pull request #9046
5 months ago
luigi1111 646c3fb0d9
Merge pull request #9043
5 months ago
luigi1111 c193c5e85d
Merge pull request #9039
5 months ago
luigi1111 d5c667a5ad
Merge pull request #9036
5 months ago
luigi1111 2fe5a5e073
Merge pull request #9034
5 months ago
luigi1111 95e4fc3602
Merge pull request #9029
5 months ago
SChernykh e7d51e5583 JH hash compiler workarounds
5 months ago
Lee *!* Clagett fe746dca4e Fix EAGAIN bug in ZMQ-RPC/ZMQ-PUB
5 months ago
jeffro256 fe47806afb
wallet: fix multisig key memory leak
5 months ago
moneromooo-monero 6c38c21dfd heed NO_COLOR environment variable
5 months ago
Jeffrey Ryan 5435202450
readline_buffer: disable bracketed paste escape sequences
5 months ago
luigi1111 d9b765a3af
Merge pull request #9027
5 months ago
luigi1111 72d2a610cd
Merge pull request #9022
5 months ago
luigi1111 2e9542d01a
Merge pull request #9020
5 months ago
jeffro256 0f75585f64
multisig: better errors for small malformed kex msgs
5 months ago
luigi1111 eb4df0aa1c
Merge pull request #8992
5 months ago
jeffro256 eae62a07e0
ringct: make `rctSigBase` serialization follow strict aliasing rule
5 months ago
jeffro256 14ae81246d
cryptonote_config: include cstdint
5 months ago
selsta 5b0c27430f
gitian: add riscv64 support
5 months ago
tevador 09a88cc00e Update RandomX to 1.2.1
5 months ago
j-berman bdebf680bd wallet2: ensure transfers and sweeps use same fee calc logic
6 months ago
jeffro256 e0b2123c32
http_client: reduce number of packets sent for small bodies
6 months ago
luigi1111 2656cdf505
Merge pull request #9014
6 months ago
luigi1111 1c12d305d6
Merge pull request #9012
6 months ago
luigi1111 83d0d2338f
Merge pull request #9011
6 months ago
Boog900 69de381526
add a test for the long term weight cache
6 months ago
Boog900 810f6a6cd2
Fix: long term block weight cache
6 months ago
selsta fbcd8da082
build: prepare v0.18.3.1
6 months ago
selsta 03d51b7cc4
wallet2: fix refresh function parameters
6 months ago
luigi1111 f9b81a589e
Merge pull request #9001
6 months ago
luigi1111 41157dbc82
Merge pull request #8999
6 months ago
j-berman 9a89e2d9e4 wallet2: call on_reorg callback in handle_reorg
6 months ago
Crypto City 1df5630f23 wallet2: add on_reorg callback
6 months ago
selsta 3f9140e754 storages: change error log category to serialization
6 months ago
jeff 205c80427b
wallet: store watch-only wallet correctly when `change_password()` is called
6 months ago
tobtoht 0c04018718
depends: openssl: update to 3.0.11
6 months ago
luigi1111 533bbc3208
Merge pull request #8988
7 months ago
luigi1111 6e7bd68b18
Merge pull request #8977
7 months ago
luigi1111 031d318ca2
Merge pull request #8941
7 months ago
luigi1111 61e664a258
Merge pull request #8938
7 months ago
selsta 64ed9385a2
build: prepare v0.18.3.0
7 months ago
jeffro256 ba98269ca5
wallet2: fix `store_to()` and `change_password()`
7 months ago
jeffro256 7dbb14b02a
functional_tests: fix multisig tests noutputs assertion
7 months ago
moneromooo-monero 356e6877dc
wallet_rpc_server: chunk refresh to keep responding to RPC while refreshing
7 months ago
moneromooo-monero 633e1b7359
wallet_rpc_server: add --no-initial-sync flag for quicker network binding
7 months ago
luigi1111 eac1b86bb2
Merge pull request #8957
7 months ago
luigi1111 3bebcc4a7d
Merge pull request #8953
7 months ago
luigi1111 9d5c5b5634
Merge pull request #8942
7 months ago
luigi1111 894adef295
Merge pull request #8891
7 months ago
luigi1111 6c7640eb74
Merge pull request #8800
7 months ago
jeffro256 78348bcddd
wallet-rpc: restore from multisig seed
8 months ago
j-berman b51f4a9244 scan_tx: fix custom comparator for == case; fixes #8951
8 months ago
jeffro256 ed05ac6872
wallet2: when checking frozen multisig tx set, don't assume order
9 months ago
j-berman f137a35984 Enforce restricted # pool txs served via RPC + optimize chunked reqs [release-v0.18]
9 months ago
rbrunner7 23f782b211 wallet2, RPC: Optimize RPC calls for periodic refresh from 3 down to 1 call [release-v0.18]
9 months ago
luigi1111 ab826008d6
Merge pull request #8917
9 months ago
luigi1111 4dc727b3f6
Merge pull request #8916
9 months ago
luigi1111 1eb1162923
Merge pull request #8909
9 months ago
luigi1111 3be6c1389e
Merge pull request #8908
9 months ago
luigi1111 5a99b2dfbe
Merge pull request #8905
9 months ago
luigi1111 bd962882d1
Merge pull request #8900
9 months ago
luigi1111 f173bf6e72
Merge pull request #8895
9 months ago
luigi1111 a41453c256
Merge pull request #8892
9 months ago
jeffro256 842478c5a9
core_rpc_server: return ID of submitted block
9 months ago
luigi1111 17ea7665d7
Merge pull request #8883
9 months ago
luigi1111 9f8ae9649a
Merge pull request #8878
9 months ago
luigi1111 11b5139506
Merge pull request #8851
9 months ago
luigi1111 54f0f9eb96
Merge pull request #8845
9 months ago
luigi1111 5c900bb69f
Merge pull request #8831
9 months ago
luigi1111 60e9426ef2
Merge pull request #8566
9 months ago
Crypto City 835896ea24
wallet2: do not lose exception in current thread on refresh
9 months ago
Crypto City 62bb95b25f
wallet2: fix missing exceptions from failing wallet refresh
9 months ago
moneromooo-monero 1924c170d4
protocol: drop peers sending duplicate txes
9 months ago
Lee *!* Clagett aed36a25d6 Set SSL SNI even when server verification is disabled
10 months ago
Lee Clagett c6530d2f5d Add CLSAG serialization to ZMQ code
10 months ago
jeffro256 dc24312bc3 wallet: respect frozen key images in multisig wallets [RELEASE]
10 months ago
j-berman 438554e1ab
properly terminate interrupted TCP connection. fixes #8685
10 months ago
SChernykh 26025cb294 Speed up perf_timer init on x86
10 months ago
jeffro256 cfc62277c0 cryptonote_basic: fix amount overflow detection on 32-bit systems [RELEASE]
10 months ago
jeffro256 aa139f0334 wallet_rpc_server: dedup transfer RPC responses [RELEASE]
10 months ago
tobtoht a4a58eb886
depends: update openssl to 1.1.1u
10 months ago
tobtoht 8dc4abdafe
common: do not use DNS to determine if address is local
10 months ago
luigi1111 1ce32d8536
Merge pull request #8846
11 months ago
Crypto City 1fad8cc919
blockchain: ensure base fee cannot reach 0
11 months ago
tobtoht f983ac7780
fix missing <cstdint> includes
11 months ago
SChernykh 1d1d5fb74c Fixed RandomX initialization when mining from scratch
11 months ago
luigi1111 2f45d5c615
Merge pull request #8766
11 months ago
luigi1111 e06129bb4d
Merge pull request #8805
1 year ago
luigi1111 a371e60a30
Merge pull request #8813
1 year ago
luigi1111 2f62dd5b78
Merge pull request #8811
1 year ago
jeffro256 059b975388 cryptonote core/protocol: don't drop peers for soft offenses
1 year ago
SChernykh c742fa4c6e Fixed deadlock and crash when syncing with full dataset on Windows
1 year ago
selsta 4f1262bae9
build: prepare v0.18.2.2
1 year ago
luigi1111 4f47fd2626
Merge pull request #8801
1 year ago
Crypto City 132804811d
wallet2: fix infinite loop in fake out selection
1 year ago
luigi1111 25645e5d23
Merge pull request #8785
1 year ago
luigi1111 0e2c2ddd9c
Merge pull request #8787
1 year ago
moneromooo-monero c4cfaa4567
p2p: do not log to global when re-blocking a subnet
1 year ago
moneromooo-monero f0e326be58
p2p: avoid spam blocking ipv4 addresses in a blocked subnet
1 year ago
luigi1111 225e5ba571
Merge pull request #8784
1 year ago
luigi1111 66f57299a2
Merge pull request #8781
1 year ago
luigi1111 d7821a02c4
Merge pull request #8779
1 year ago
luigi1111 b4519c6bbd
Merge pull request #8746
1 year ago
selsta cdeb286359
build: prepare v0.18.2.1
1 year ago
tevador 5900ed3706
Add a size limit for tx_extra in tx pool
1 year ago
Jeffrey Ryan c59e0096b6 verRctNonSemanticsSimpleCached: fix fragility
1 year ago
Francois Beutin 14de562a6f
device: Add ledger Stax device id to device detection
1 year ago
j-berman 65e13dbef1 wallet2: fix rescanning tx via scan_tx
1 year ago
almalh ad80f1b357
Handle case where a command line flag is not allowed in the config file
1 year ago
selsta 77d883e507
workflows: update dependencies to fix warnings
1 year ago

@ -27,10 +27,10 @@ jobs:
env: env:
CCACHE_TEMPDIR: /tmp/.ccache-temp CCACHE_TEMPDIR: /tmp/.ccache-temp
steps: steps:
- uses: actions/checkout@v1 - uses: actions/checkout@v3
with: with:
submodules: recursive submodules: recursive
- uses: actions/cache@v2 - uses: actions/cache@v3
with: with:
path: /Users/runner/Library/Caches/ccache path: /Users/runner/Library/Caches/ccache
key: ccache-${{ runner.os }}-build-${{ github.sha }} key: ccache-${{ runner.os }}-build-${{ github.sha }}
@ -51,15 +51,15 @@ jobs:
run: run:
shell: msys2 {0} shell: msys2 {0}
steps: steps:
- uses: actions/checkout@v1 - uses: actions/checkout@v3
with: with:
submodules: recursive submodules: recursive
- uses: actions/cache@v2 - uses: actions/cache@v3
with: with:
path: C:\Users\runneradmin\.ccache path: C:\Users\runneradmin\.ccache
key: ccache-${{ runner.os }}-build-${{ github.sha }} key: ccache-${{ runner.os }}-build-${{ github.sha }}
restore-keys: ccache-${{ runner.os }}-build- restore-keys: ccache-${{ runner.os }}-build-
- uses: eine/setup-msys2@v2 - uses: msys2/setup-msys2@v2
with: with:
update: true update: true
install: mingw-w64-x86_64-toolchain make mingw-w64-x86_64-cmake mingw-w64-x86_64-ccache mingw-w64-x86_64-boost mingw-w64-x86_64-openssl mingw-w64-x86_64-zeromq mingw-w64-x86_64-libsodium mingw-w64-x86_64-hidapi mingw-w64-x86_64-protobuf-c mingw-w64-x86_64-libusb mingw-w64-x86_64-unbound git install: mingw-w64-x86_64-toolchain make mingw-w64-x86_64-cmake mingw-w64-x86_64-ccache mingw-w64-x86_64-boost mingw-w64-x86_64-openssl mingw-w64-x86_64-zeromq mingw-w64-x86_64-libsodium mingw-w64-x86_64-hidapi mingw-w64-x86_64-protobuf-c mingw-w64-x86_64-libusb mingw-w64-x86_64-unbound git
@ -79,10 +79,10 @@ jobs:
matrix: matrix:
os: [ubuntu-22.04, ubuntu-20.04] os: [ubuntu-22.04, ubuntu-20.04]
steps: steps:
- uses: actions/checkout@v1 - uses: actions/checkout@v3
with: with:
submodules: recursive submodules: recursive
- uses: actions/cache@v2 - uses: actions/cache@v3
with: with:
path: ~/.ccache path: ~/.ccache
key: ccache-${{ runner.os }}-build-${{ matrix.os }}-${{ github.sha }} key: ccache-${{ runner.os }}-build-${{ matrix.os }}-${{ github.sha }}
@ -105,10 +105,10 @@ jobs:
env: env:
CCACHE_TEMPDIR: /tmp/.ccache-temp CCACHE_TEMPDIR: /tmp/.ccache-temp
steps: steps:
- uses: actions/checkout@v1 - uses: actions/checkout@v3
with: with:
submodules: recursive submodules: recursive
- uses: actions/cache@v2 - uses: actions/cache@v3
with: with:
path: ~/.ccache path: ~/.ccache
key: ccache-${{ runner.os }}-libwallet-${{ github.sha }} key: ccache-${{ runner.os }}-libwallet-${{ github.sha }}
@ -133,11 +133,11 @@ jobs:
env: env:
CCACHE_TEMPDIR: /tmp/.ccache-temp CCACHE_TEMPDIR: /tmp/.ccache-temp
steps: steps:
- uses: actions/checkout@v1 - uses: actions/checkout@v3
with: with:
submodules: recursive submodules: recursive
- name: ccache - name: ccache
uses: actions/cache@v2 uses: actions/cache@v3
with: with:
path: ~/.ccache path: ~/.ccache
key: ccache-${{ runner.os }}-build-ubuntu-latest-${{ github.sha }} key: ccache-${{ runner.os }}-build-ubuntu-latest-${{ github.sha }}
@ -151,7 +151,7 @@ jobs:
- name: install monero dependencies - name: install monero dependencies
run: ${{env.APT_INSTALL_LINUX}} run: ${{env.APT_INSTALL_LINUX}}
- name: install Python dependencies - name: install Python dependencies
run: pip install requests psutil monotonic zmq run: pip install requests psutil monotonic zmq deepdiff
- name: tests - name: tests
env: env:
CTEST_OUTPUT_ON_FAILURE: ON CTEST_OUTPUT_ON_FAILURE: ON
@ -167,8 +167,9 @@ jobs:
source-archive: source-archive:
runs-on: ubuntu-20.04 runs-on: ubuntu-20.04
steps: steps:
- uses: actions/checkout@v1 - uses: actions/checkout@v3
with: with:
fetch-depth: 0
submodules: recursive submodules: recursive
- name: archive - name: archive
run: | run: |
@ -177,7 +178,7 @@ jobs:
export OUTPUT="$VERSION.tar" export OUTPUT="$VERSION.tar"
echo "OUTPUT=$OUTPUT" >> $GITHUB_ENV echo "OUTPUT=$OUTPUT" >> $GITHUB_ENV
/home/runner/.local/bin/git-archive-all --prefix "$VERSION/" --force-submodules "$OUTPUT" /home/runner/.local/bin/git-archive-all --prefix "$VERSION/" --force-submodules "$OUTPUT"
- uses: actions/upload-artifact@v2 - uses: actions/upload-artifact@v3
with: with:
name: ${{ env.OUTPUT }} name: ${{ env.OUTPUT }}
path: /home/runner/work/monero/monero/${{ env.OUTPUT }} path: /home/runner/work/monero/monero/${{ env.OUTPUT }}

@ -57,19 +57,20 @@ jobs:
packages: "clang-8 gperf cmake python3-zmq libdbus-1-dev libharfbuzz-dev" packages: "clang-8 gperf cmake python3-zmq libdbus-1-dev libharfbuzz-dev"
name: ${{ matrix.toolchain.name }} name: ${{ matrix.toolchain.name }}
steps: steps:
- uses: actions/checkout@v1 - uses: actions/checkout@v3
with: with:
fetch-depth: 0
submodules: recursive submodules: recursive
# Most volatile cache # Most volatile cache
- name: ccache - name: ccache
uses: actions/cache@v2 uses: actions/cache@v3
with: with:
path: ~/.ccache path: ~/.ccache
key: ccache-${{ matrix.toolchain.host }}-${{ github.sha }} key: ccache-${{ matrix.toolchain.host }}-${{ github.sha }}
restore-keys: ccache-${{ matrix.toolchain.host }}- restore-keys: ccache-${{ matrix.toolchain.host }}-
# Less volatile cache # Less volatile cache
- name: depends cache - name: depends cache
uses: actions/cache@v2 uses: actions/cache@v3
with: with:
path: contrib/depends/built path: contrib/depends/built
key: depends-${{ matrix.toolchain.host }}-${{ hashFiles('contrib/depends/packages/*') }} key: depends-${{ matrix.toolchain.host }}-${{ hashFiles('contrib/depends/packages/*') }}
@ -78,7 +79,7 @@ jobs:
depends-${{ matrix.toolchain.host }}- depends-${{ matrix.toolchain.host }}-
# Static cache # Static cache
- name: OSX SDK cache - name: OSX SDK cache
uses: actions/cache@v2 uses: actions/cache@v3
with: with:
path: contrib/depends/sdk-sources path: contrib/depends/sdk-sources
key: sdk-${{ matrix.toolchain.host }}-${{ matrix.toolchain.osx_sdk }} key: sdk-${{ matrix.toolchain.host }}-${{ matrix.toolchain.osx_sdk }}
@ -96,7 +97,7 @@ jobs:
run: | run: |
${{env.CCACHE_SETTINGS}} ${{env.CCACHE_SETTINGS}}
make depends target=${{ matrix.toolchain.host }} -j2 make depends target=${{ matrix.toolchain.host }} -j2
- uses: actions/upload-artifact@v2 - uses: actions/upload-artifact@v3
if: ${{ matrix.toolchain.host == 'x86_64-w64-mingw32' || matrix.toolchain.host == 'x86_64-apple-darwin11' || matrix.toolchain.host == 'x86_64-unknown-linux-gnu' }} if: ${{ matrix.toolchain.host == 'x86_64-w64-mingw32' || matrix.toolchain.host == 'x86_64-apple-darwin11' || matrix.toolchain.host == 'x86_64-unknown-linux-gnu' }}
with: with:
name: ${{ matrix.toolchain.name }} name: ${{ matrix.toolchain.name }}

@ -42,7 +42,7 @@ jobs:
echo \`\`\` >> $GITHUB_STEP_SUMMARY echo \`\`\` >> $GITHUB_STEP_SUMMARY
shasum -a256 * >> $GITHUB_STEP_SUMMARY shasum -a256 * >> $GITHUB_STEP_SUMMARY
echo \`\`\` >> $GITHUB_STEP_SUMMARY echo \`\`\` >> $GITHUB_STEP_SUMMARY
- uses: actions/upload-artifact@v3.1.0 - uses: actions/upload-artifact@v3
with: with:
name: ${{ matrix.operating-system.name }} name: ${{ matrix.operating-system.name }}
path: | path: |

9
.gitmodules vendored

@ -5,12 +5,15 @@
path = external/rapidjson path = external/rapidjson
url = https://github.com/Tencent/rapidjson url = https://github.com/Tencent/rapidjson
[submodule "external/trezor-common"] [submodule "external/trezor-common"]
active = false
path = external/trezor-common path = external/trezor-common
url = https://github.com/trezor/trezor-common.git url = https://github.com/trezor/trezor-common.git
[submodule "external/randomx"]
path = external/randomx
url = https://github.com/tevador/RandomX
[submodule "external/supercop"] [submodule "external/supercop"]
path = external/supercop path = external/supercop
url = https://github.com/monero-project/supercop url = https://github.com/monero-project/supercop
branch = monero branch = monero
[submodule "external/randomwow"]
path = external/randomwow
url = https://git.wownero.com/wownero/RandomWOW
branch = 1.2.1-wow

@ -359,15 +359,16 @@ if(NOT MANUAL_SUBMODULES)
if (upToDate) if (upToDate)
message(STATUS "Submodule '${relative_path}' is up-to-date") message(STATUS "Submodule '${relative_path}' is up-to-date")
else() else()
message(FATAL_ERROR "Submodule '${relative_path}' is not up-to-date. Please update all submodules with\ngit submodule update --init --force\nor run cmake with -DMANUAL_SUBMODULES=1\n") message(STATUS "Initializing submodules")
execute_process(COMMAND git "submodule" "update" "--init" "--recursive" WORKING_DIRECTORY ${CMAKE_SOURCE_DIR})
endif() endif()
endfunction () endfunction ()
message(STATUS "Checking submodules") message(STATUS "Checking submodules")
check_submodule(external/miniupnp) check_submodule(external/miniupnp)
check_submodule(external/rapidjson) check_submodule(external/rapidjson)
check_submodule(external/trezor-common) #check_submodule(external/trezor-common)
check_submodule(external/randomx) check_submodule(external/randomwow)
check_submodule(external/supercop) check_submodule(external/supercop)
endif() endif()
endif() endif()
@ -405,7 +406,7 @@ option(BOOST_IGNORE_SYSTEM_PATHS "Ignore boost system paths for local boost inst
set_property(GLOBAL PROPERTY USE_FOLDERS ON) set_property(GLOBAL PROPERTY USE_FOLDERS ON)
enable_testing() enable_testing()
option(BUILD_DOCUMENTATION "Build the Doxygen documentation." ON) option(BUILD_DOCUMENTATION "Build the Doxygen documentation." OFF)
option(BUILD_TESTS "Build tests." OFF) option(BUILD_TESTS "Build tests." OFF)
if (CMAKE_BUILD_TYPE STREQUAL "Debug") if (CMAKE_BUILD_TYPE STREQUAL "Debug")
set(DEFAULT_BUILD_DEBUG_UTILITIES ON) set(DEFAULT_BUILD_DEBUG_UTILITIES ON)

@ -41,26 +41,26 @@ RUN set -ex && \
rm -rf /var/lib/apt rm -rf /var/lib/apt
COPY --from=builder /src/build/x86_64-linux-gnu/release/bin /usr/local/bin/ COPY --from=builder /src/build/x86_64-linux-gnu/release/bin /usr/local/bin/
# Create monero user # Create wownero user
RUN adduser --system --group --disabled-password monero && \ RUN adduser --system --group --disabled-password wownero && \
mkdir -p /wallet /home/monero/.bitmonero && \ mkdir -p /wallet /home/wownero/.wownero && \
chown -R monero:monero /home/monero/.bitmonero && \ chown -R wownero:wownero /home/wownero/.wownero && \
chown -R monero:monero /wallet chown -R wownero:wownero /wallet
# Contains the blockchain # Contains the blockchain
VOLUME /home/monero/.bitmonero VOLUME /home/wownero/.wownero
# Generate your wallet via accessing the container and run: # Generate your wallet via accessing the container and run:
# cd /wallet # cd /wallet
# monero-wallet-cli # wownero-wallet-cli
VOLUME /wallet VOLUME /wallet
EXPOSE 18080 EXPOSE 34567
EXPOSE 18081 EXPOSE 34568
# switch to user monero # switch to user wownero
USER monero USER wownero
ENTRYPOINT ["monerod"] ENTRYPOINT ["wownerod"]
CMD ["--p2p-bind-ip=0.0.0.0", "--p2p-bind-port=18080", "--rpc-bind-ip=0.0.0.0", "--rpc-bind-port=18081", "--non-interactive", "--confirm-external-bind"] CMD ["--p2p-bind-ip=0.0.0.0", "--p2p-bind-port=34567", "--rpc-bind-ip=0.0.0.0", "--rpc-bind-port=34568", "--non-interactive", "--confirm-external-bind"]

@ -100,11 +100,11 @@ release-test:
release-all: release-all:
mkdir -p $(builddir)/release mkdir -p $(builddir)/release
cd $(builddir)/release && cmake -D BUILD_TESTS=ON -D CMAKE_BUILD_TYPE=Release $(topdir) && $(MAKE) cd $(builddir)/release && cmake -D BUILD_TESTS=OFF -D USE_DEVICE_TREZOR=OFF -D CMAKE_BUILD_TYPE=Release $(topdir) && $(MAKE)
release-static: release-static:
mkdir -p $(builddir)/release mkdir -p $(builddir)/release
cd $(builddir)/release && cmake -D STATIC=ON -D ARCH="x86-64" -D BUILD_64=ON -D CMAKE_BUILD_TYPE=Release $(topdir) && $(MAKE) cd $(builddir)/release && cmake -D BUILD_TESTS=OFF -D USE_DEVICE_TREZOR=OFF -D STATIC=ON -D BUILD_64=ON -D CMAKE_BUILD_TYPE=Release $(topdir) && $(MAKE)
coverage: coverage:
mkdir -p $(builddir)/debug mkdir -p $(builddir)/debug

@ -1,673 +1,164 @@
# Monero # ~~Mo~~Wownero - Such privacy! Many coins! Wow!
Copyright (c) 2014-2022 The Monero Project. [<img src="https://suchwow.xyz/data/suchwow/image/to23moqn.jpeg">](https://suchwow.xyz/s/oh-really-9eda16b2/item)
Portions Copyright (c) 2012-2013 The Cryptonote developers.
## Table of Contents
- [Development resources](#development-resources)
- [Vulnerability response](#vulnerability-response)
- [Research](#research)
- [Announcements](#announcements)
- [Translations](#translations)
- [Coverage](#coverage)
- [Introduction](#introduction)
- [About this project](#about-this-project)
- [Supporting the project](#supporting-the-project)
- [License](#license)
- [Contributing](#contributing)
- [Scheduled software upgrades](#scheduled-software-upgrades)
- [Release staging schedule and protocol](#release-staging-schedule-and-protocol)
- [Compiling Monero from source](#compiling-monero-from-source)
- [Dependencies](#dependencies)
- [Internationalization](#Internationalization)
- [Using Tor](#using-tor)
- [Pruning](#Pruning)
- [Debugging](#Debugging)
- [Known issues](#known-issues)
## Development resources
- Web: [getmonero.org](https://getmonero.org)
- Forum: [forum.getmonero.org](https://forum.getmonero.org)
- Mail: [dev@getmonero.org](mailto:dev@getmonero.org)
- GitHub: [https://github.com/monero-project/monero](https://github.com/monero-project/monero)
- IRC: [#monero-dev on Libera](https://web.libera.chat/#monero-dev)
- It is HIGHLY recommended that you join the #monero-dev IRC channel if you are developing software that uses Monero. Due to the nature of this open source software project, joining this channel and idling is the best way to stay updated on best practices and new developments in the Monero ecosystem. All you need to do is join the IRC channel and idle to stay updated with the latest in Monero development. If you do not, you risk wasting resources on developing integrations that are not compatible with the Monero network. The Monero core team and community continuously make efforts to communicate updates, developments, and documentation via other platforms but for the best information, you need to talk to other Monero developers, and they are on IRC. #monero-dev is about Monero development, not getting help about using Monero, or help about development of other software, including yours, unless it also pertains to Monero code itself. For these cases, checkout #monero.
## Vulnerability response
- Our [Vulnerability Response Process](https://github.com/monero-project/meta/blob/master/VULNERABILITY_RESPONSE_PROCESS.md) encourages responsible disclosure
- We are also available via [HackerOne](https://hackerone.com/monero)
## Research ## Introduction
The [Monero Research Lab](https://src.getmonero.org/resources/research-lab/) is an open forum where the community coordinates research into Monero cryptography, protocols, fungibility, analysis, and more. We welcome collaboration and contributions from outside researchers! Because not all Lab work and publications are distributed as traditional preprints or articles, they may be easy to miss if you are conducting literature reviews for your own Monero research. You are encouraged to get in touch with the Monero research community if you have questions, wish to collaborate, or would like guidance to help avoid unnecessarily duplicating earlier or known work.
The Monero research community is available on IRC in [#monero-research-lab on Libera](https://web.libera.chat/#monero-research-lab), which is also accessible via Matrix.
## Announcements Wownero is a Doge-inspired, CPU-mineable, solo-mining only, privacy-respecting memecoin. It was fairly launched on April Fools' Day in 2018. It is a software fork of Monero, but with a lite version of RandomX, larger ring size, and a fixed supply of 184 million coins emitted over 50 years. Wownero has no trusted setup, premine, or dev tax. Besides betting on online snail racing, the main use case of Wownero is micro-tipping meme creators with sound magic internet money. As a 100% community-driven, free and open source software, Wownero does not depend on billionaire shills or lame ass "influencers."
- You can subscribe to an [announcement listserv](https://lists.getmonero.org) to get critical announcements from the Monero core team. The announcement list can be very helpful for knowing when software updates are needed. Unlike Opposing Projects.
## Translations ## Resources
The CLI wallet is available in different languages. If you want to help translate it, see our self-hosted localization platform, Weblate, on [translate.getmonero.org]( https://translate.getmonero.org/projects/monero/cli-wallet/). Every translation *must* be uploaded on the platform, pull requests directly editing the code in this repository will be closed. If you need help with Weblate, you can find a guide with screenshots [here](https://github.com/monero-ecosystem/monero-translations/blob/master/weblate.md).
&nbsp;
If you need help/support/info about translations, contact the localization workgroup. You can find the complete list of contacts on the repository of the workgroup: [monero-translations](https://github.com/monero-ecosystem/monero-translations#contacts). - IRC: [OFTC #wownero](https://webchat.oftc.net/?channels=wownero)
- Web: [wownero.org](https://wownero.org)
- Twitter: [@w0wn3r0](https://twitter.com/w0wn3r0)
- Reddit: [/r/wownero](https://www.reddit.com/r/wownero)
- Mail: [wownero@wownero.org](mailto:wownero@wownero.org)
- Git: [git.wownero.com/wownero/wownero](https://git.wownero.com/wownero/wownero)
- Wownero Forum: [forum.wownero.com](https://forum.wownero.com)
- Discord: [discord.gg/ykZyAzJhDK](https://discord.com/invite/ykZyAzJhDK)
- Telegram: [t.me/wownero](https://t.me/wownero)
- Public Node Status: [monero.fail](https://monero.fail/?chain=wownero&network=mainnet)
- Wownero Memes: [suchwow.xyz](https://suchwow.xyz/posts/top)
- Market Info: [coinmarketcap.com](https://coinmarketcap.com/currencies/wownero), [coingecko.com](https://www.coingecko.com/en/coins/wownero/usd)
## Coverage ## Exchanges
| Type | Status | - [NonKYC](https://nonkyc.io/market/WOW_BTC)
|-----------|--------| - [neroswap](https://neroswap.com)
| Coverity | [![Coverity Status](https://scan.coverity.com/projects/9657/badge.svg)](https://scan.coverity.com/projects/9657/) - [AltQuick](https://altquick.com/market/Wownero)
| OSS Fuzz | [![Fuzzing Status](https://oss-fuzz-build-logs.storage.googleapis.com/badges/monero.svg)](https://bugs.chromium.org/p/oss-fuzz/issues/list?sort=-opened&can=1&q=proj:monero) - [Majestic Bank](https://majesticbank.sc)
| Coveralls | [![Coveralls Status](https://coveralls.io/repos/github/monero-project/monero/badge.svg?branch=master)](https://coveralls.io/github/monero-project/monero?branch=master) - [TradeOgre](https://tradeogre.com/exchange/BTC-WOW)
| License | [![License](https://img.shields.io/badge/license-BSD3-blue.svg)](https://opensource.org/licenses/BSD-3-Clause)
## Introduction ## Wallets
Monero is a private, secure, untraceable, decentralised digital currency. You are your bank, you control your funds, and nobody can trace your transfers unless you allow them to do so. - Wonero CLI Wallet: [git.wownero.com/wownero/wownero](https://git.wownero.com/wownero/wownero/releases)
- Wowlet Desktop Wallet: [git.wownero.com/wowlet/wowlet](https://git.wownero.com/wowlet/wowlet/releases)
- Stack Wallet iOS & Android Mobile Wallet: [stackwallet.com](https://stackwallet.com)
- Wonerujo Android Mobile Wallet: [google store](https://play.google.com/store/apps/details?id=com.m2049r.wowwallet)
- Elite Wallet Android Mobile Wallet: [github](https://github.com/Elite-Labs/EliteWallet)
**Privacy:** Monero uses a cryptographically sound system to allow you to send and receive funds without your transactions being easily revealed on the blockchain (the ledger of transactions that everyone has). This ensures that your purchases, receipts, and all transfers remain private by default. ## Blockchain Explorers
**Security:** Using the power of a distributed peer-to-peer consensus network, every transaction on the network is cryptographically secured. Individual wallets have a 25-word mnemonic seed that is only displayed once and can be written down to backup the wallet. Wallet files should be encrypted with a strong passphrase to ensure they are useless if ever stolen. - https://explore.wownero.com
- https://explorer.suchwow.xyz
- https://kryfi.com/explorer/wownero
**Untraceability:** By taking advantage of ring signatures, a special property of a certain type of cryptography, Monero is able to ensure that transactions are not only untraceable but have an optional measure of ambiguity that ensures that transactions cannot easily be tied back to an individual user or computer.
**Decentralization:** The utility of Monero depends on its decentralised peer-to-peer consensus network - anyone should be able to run the monero software, validate the integrity of the blockchain, and participate in all aspects of the monero network using consumer-grade commodity hardware. Decentralization of the monero network is maintained by software development that minimizes the costs of running the monero software and inhibits the proliferation of specialized, non-commodity hardware. ## Supporting the project
## About this project
This is the core implementation of Monero. It is open source and completely free to use without restrictions, except for those specified in the license agreement below. There are no restrictions on anyone creating an alternative implementation of Monero that uses the protocol and network in a compatible manner. Wownero is a 100% community-sponsored endeavor. Supporting services are also graciously provided by sponsors:
As with many development projects, the repository on GitHub is considered to be the "staging" area for the latest changes. Before changes are merged into that branch on the main repository, they are tested by individual developers in their own branches, submitted as a pull request, and then subsequently tested by contributors who focus on testing and code reviews. That having been said, the repository should be carefully considered before using it in a production environment, unless there is a patch in the repository for a particular show-stopping issue you are experiencing. It is generally a better idea to use a tagged release for stability. [<img src="https://git.wownero.com/wownero/meta/raw/branch/master/images/macstadium.png"
alt="MacStadium"
height="100">](https://www.macstadium.com)
[<img src="https://git.wownero.com/wownero/meta/raw/branch/master/images/jetbrains.png"
alt="JetBrains"
height="100">](https://www.jetbrains.com)
**Anyone is welcome to contribute to Monero's codebase!** If you have a fix or code change, feel free to submit it as a pull request directly to the "master" branch. In cases where the change is relatively small or does not affect other parts of the codebase, it may be merged in immediately by any one of the collaborators. On the other hand, if the change is particularly large or complex, it is expected that it will be discussed at length either well in advance of the pull request being submitted, or even directly on the pull request. Developers are volunteers doing this mostly for shits and giggles. If you would like to support our shenanigans and stimulant addictions, please consider donating to the dev slush fund.
## Supporting the project ### Donation Addresses
Monero is a 100% community-sponsored endeavor. If you want to join our efforts, the easiest thing you can do is support the project financially. Both Monero and Bitcoin donations can be made to **donate.getmonero.org** if using a client that supports the [OpenAlias](https://openalias.org) standard. Alternatively, you can send XMR to the Monero donation address via the `donate` command (type `help` in the command-line wallet for details). WOW: `Wo3MWeKwtA918DU4c69hVSNgejdWFCRCuWjShRY66mJkU2Hv58eygJWDJS1MNa2Ge5M1WjUkGHuLqHkweDxwZZU42d16v94mP`
The Monero donation address is: - view key: `e62e40bfd5ca7e3a7f199602a3c97df511780489e1c1861884b00c28abaea406`
`888tNkZrPN6JsEgekjMnABU4TBzc2Dt29EPAvkRxbANsAnjyPbb3iQ1YBRk1UXcdRsiKc9dhwMVgN5S9cQUiyoogDavup3H`
Viewkey:
`f359631075708155cc3d92a32b75a7d02a5dcf27756707b47a2b31b21c389501`
Base address for restoring with address and viewkey:
`44AFFq5kSiGBoZ4NMDwYtN18obc8AemS33DBLWs3H7otXft3XjrpDtQGv7SqSsaBYBb98uNbr2VBBEt7f2wfn3RVGQBEP3A`
The Bitcoin donation address is: XMR: `44SQVPGLufPasUcuUQSZiF5c9BFzjcP8ucDxzzFDgLf1VkCEFaidJ3u2AhSKMhPLKA3jc2iS8wQHFcaigM6fXmo6AnFRn5B`
`1KTexdemPdxSBcG55heUuTjDRYqbC5ZL8H`
Core development funding and/or some supporting services are also graciously provided by [sponsors](https://www.getmonero.org/community/sponsorships/): - view key: `cb83681c31db0c79adf18f25b2a6d05f86db1109385b4928930e2acf49a3ed0b`
[<img width="150" src="https://www.getmonero.org/img/sponsors/tarilabs.png"/>](https://tarilabs.com/) BTC: `bc1qcw9zglp3fxyl25zswemw7jczlqryms2lsmu464`
[<img width="150" src="https://www.getmonero.org/img/sponsors/globee.png"/>](https://globee.com/)
[<img width="150" src="https://www.getmonero.org/img/sponsors/symas.png"/>](https://symas.com/)
[<img width="150" src="https://www.getmonero.org/img/sponsors/forked_logo.png"/>](http://www.forked.net/)
[<img width="150" src="https://www.getmonero.org/img/sponsors/macstadium.png"/>](https://www.macstadium.com/)
There are also several mining pools that kindly donate a portion of their fees, [a list of them can be found on our Bitcointalk post](https://bitcointalk.org/index.php?topic=583449.0). ## Release staging and Contributing
## License **Anyone is welcome to contribute to Wownero's codebase!**
See [LICENSE](LICENSE). If you have a fix or code change, feel free to submit it as a pull request. Ahead of a scheduled software upgrade, a development branch will be created with the new release version tag. Pull requests that address bugs should be made to Master. Pull requests that require review and testing (generally, optimizations and new features) should be made to the development branch. All pull requests will be considered safe until the US dollar valuation of 1 Wownero equals $1000. After this valuation has been reached, more research will be needed to introduce experimental cryptography and/or code into the codebase.
## Contributing Things to Do, Work in Progress, and Help Wanted tasks are tracked in the [Meta](https://git.wownero.com/wownero/meta/issues) repo.
If you want to help out, see [CONTRIBUTING](docs/CONTRIBUTING.md) for a set of guidelines. Join `#wownero` on IRC OFTC to participate in development conversation.
## Scheduled software upgrades ## Scheduled software upgrades
Monero uses a fixed-schedule software upgrade (hard fork) mechanism to implement new features. This means that users of Monero (end users and service providers) should run current versions and upgrade their software on a regular schedule. Software upgrades occur during the months of April and October. The required software for these upgrades will be available prior to the scheduled date. Please check the repository prior to this date for the proper Monero software version. Below is the historical schedule and the projected schedule for the next upgrade. Wownero uses a fixed-schedule software upgrade (hard fork) mechanism to implement new features. This means that users of Wownero (end users and service providers) should run current versions and upgrade their software on a regular schedule. The required software for these upgrades will be available prior to the scheduled date. Please check the repository prior to this date for the proper Wownero software version. Below is the historical schedule and the projected schedule for the next upgrade.
Dates are provided in the format YYYY-MM-DD. Dates are provided in the format YYYY-MM-DD.
| Software upgrade block height | Date | Release Name | Minimum Wownero version | Recommended Wownero version | Details |
| Software upgrade block height | Date | Fork version | Minimum Monero version | Recommended Monero version | Details | |-------------------------------|------------| ----------------- |-------------------------|-----------------------------| ---------------------------------------------------------------------------------- |
| ------------------------------ | -----------| ----------------- | ---------------------- | -------------------------- | ---------------------------------------------------------------------------------- | | 1 | 2018-04-01 | Awesome Akita | v0.1.0.0 | v0.1.0.0 | Cryptonight variant 1, ringsize >= 8, sorted inputs
| 1009827 | 2016-03-22 | v2 | v0.9.4 | v0.9.4 | Allow only >= ringsize 3, blocktime = 120 seconds, fee-free blocksize 60 kb | | 69,69 | 2018-04-24 | Busty Brazzers | v0.2.0.0 | v0.2.0.0 | Bulletproofs, LWMA difficulty algorithm, ringsize >= 10, reduce unlock to 4
| 1141317 | 2016-09-21 | v3 | v0.9.4 | v0.10.0 | Splits coinbase into denominations | | 53,666 | 2018-10-06 | Cool Cage | v0.3.0.0 | v0.3.1.3 | Cryptonight variant 2, LWMA v2, ringsize = 22, MMS
| 1220516 | 2017-01-05 | v4 | v0.10.1 | v0.10.2.1 | Allow normal and RingCT transactions | | 63,469 | 2018-11-11 | Dank Doge | v0.4.0.0 | v0.4.0.0 | LWMA v4
| 1288616 | 2017-04-15 | v5 | v0.10.3.0 | v0.10.3.1 | Adjusted minimum blocksize and fee algorithm | | 81,769 | 2019-02-19 | Erotic EggplantEmoji | v0.5.0.0 | v0.5.0.2 | Cryptonight/wow, LWMA v1 with N=144, Updated Bulletproofs, Fee Per Byte, Auto-churn
| 1400000 | 2017-09-16 | v6 | v0.11.0.0 | v0.11.0.0 | Allow only RingCT transactions, allow only >= ringsize 5 | | 114,969 | 2019-06-14 | F For Fappening | v0.6.1.0 | v0.6.1.2 | RandomWOW, new block weight algorithm, slightly more efficient RingCT format
| 1546000 | 2018-04-06 | v7 | v0.12.0.0 | v0.12.3.0 | Cryptonight variant 1, ringsize >= 7, sorted inputs | 160,777 | 2019-11-20 | Gaping Goatse | v0.7.0.0 | v0.7.1.0 | Only allow >= 2 outputs, change to the block median used to calculate penalty, rct sigs in coinbase forbidden, 4 unlock time as protocol rule
| 1685555 | 2018-10-18 | v8 | v0.13.0.0 | v0.13.0.4 | max transaction size at half the penalty free block size, bulletproofs enabled, cryptonight variant 2, fixed ringsize [11](https://youtu.be/KOO5S4vxi0o) | - | 2020-06-28 | Hallucinogenic Hypnotoad | v0.8.0.0 | v0.8.0.2 | Dandelion++ support
| 1686275 | 2018-10-19 | v9 | v0.13.0.0 | v0.13.0.4 | bulletproofs required | 253,999 | 2020-10-09 | Illiterate Illuminati | v0.9.0.0 | v0.9.3.3 | Dynamic coinbase unlock (up to 1 mo.), Deterministic unlock times, Enforce maximum coinbase amount, show_qr_code wallet command, CLSAG
| 1788000 | 2019-03-09 | v10 | v0.14.0.0 | v0.14.1.2 | New PoW based on Cryptonight-R, new block weight algorithm, slightly more efficient RingCT format | 331,170 | 2021-07-04 | Junkie Jeff | v0.10.0.0 | v0.10.2.0 | Bulletproofs+, Miner Block Header Signing, Vote by Block, Change coinbase unlock time to 1 day, Reset difficulty and switch back to Monero's difficulty algorithm
| 1788720 | 2019-03-10 | v11 | v0.14.0.0 | v0.14.1.2 | forbid old RingCT transaction format | 514,000 | 2023-04-01 | Kunty Karen | v0.11.0.0 | v0.11.2.0 | View tags, fee changes, adjusted dynamic block weight algorithm, multisig security fixes, RPC broadcast node donation sub-address, Limit tx_extra max size to ~1kb, 12-hour difficulty adjustment window
| 1978433 | 2019-11-30 | v12 | v0.15.0.0 | v0.16.0.0 | New PoW based on RandomX, only allow >= 2 outputs, change to the block median used to calculate penalty, v1 coinbases are forbidden, rct sigs in coinbase forbidden, 10 block lock time for incoming outputs
| 2210000 | 2020-10-17 | v13 | v0.17.0.0 | v0.17.3.2 | New CLSAG transaction format
| 2210720 | 2020-10-18 | v14 | v0.17.1.1 | v0.17.3.2 | forbid old MLSAG transaction format
| 2688888 | 2022-08-13 | v15 | v0.18.0.0 | v0.18.2.0 | ringsize = 16, bulletproofs+, view tags, adjusted dynamic block weight algorithm
| 2689608 | 2022-08-14 | v16 | v0.18.0.0 | v0.18.2.0 | forbid old v14 transaction format
| XXXXXXX | XXX-XX-XX | XXX | vX.XX.X.X | vX.XX.X.X | XXX |
X's indicate that these details have not been determined as of commit date. X's indicate that these details have not been determined as of commit date.
\* indicates estimate as of commit date \* indicates estimate as of commit date
## Release staging schedule and protocol ## Installing from a package
Approximately three months prior to a scheduled software upgrade, a branch from master will be created with the new release version tag. Pull requests that address bugs should then be made to both master and the new release branch. Pull requests that require extensive review and testing (generally, optimizations and new features) should *not* be made to the release branch.
## Compiling Monero from source
### Dependencies
The following table summarizes the tools and libraries required to build. A
few of the libraries are also included in this repository (marked as
"Vendored"). By default, the build uses the library installed on the system
and ignores the vendored sources. However, if no library is found installed on
the system, then the vendored source will be built and used. The vendored
sources are also used for statically-linked builds because distribution
packages often include only shared library binaries (`.so`) but not static
library archives (`.a`).
| Dep | Min. version | Vendored | Debian/Ubuntu pkg | Arch pkg | Void pkg | Fedora pkg | Optional | Purpose |
| ------------ | ------------- | -------- | -------------------- | ------------ | ------------------ | ------------------- | -------- | --------------- |
| GCC | 5 | NO | `build-essential` | `base-devel` | `base-devel` | `gcc` | NO | |
| CMake | 3.5 | NO | `cmake` | `cmake` | `cmake` | `cmake` | NO | |
| pkg-config | any | NO | `pkg-config` | `base-devel` | `base-devel` | `pkgconf` | NO | |
| Boost | 1.58 | NO | `libboost-all-dev` | `boost` | `boost-devel` | `boost-devel` | NO | C++ libraries |
| OpenSSL | basically any | NO | `libssl-dev` | `openssl` | `libressl-devel` | `openssl-devel` | NO | sha256 sum |
| libzmq | 4.2.0 | NO | `libzmq3-dev` | `zeromq` | `zeromq-devel` | `zeromq-devel` | NO | ZeroMQ library |
| OpenPGM | ? | NO | `libpgm-dev` | `libpgm` | | `openpgm-devel` | NO | For ZeroMQ |
| libnorm[2] | ? | NO | `libnorm-dev` | | | | YES | For ZeroMQ |
| libunbound | 1.4.16 | YES | `libunbound-dev` | `unbound` | `unbound-devel` | `unbound-devel` | NO | DNS resolver |
| libsodium | ? | NO | `libsodium-dev` | `libsodium` | `libsodium-devel` | `libsodium-devel` | NO | cryptography |
| libunwind | any | NO | `libunwind8-dev` | `libunwind` | `libunwind-devel` | `libunwind-devel` | YES | Stack traces |
| liblzma | any | NO | `liblzma-dev` | `xz` | `liblzma-devel` | `xz-devel` | YES | For libunwind |
| libreadline | 6.3.0 | NO | `libreadline6-dev` | `readline` | `readline-devel` | `readline-devel` | YES | Input editing |
| expat | 1.1 | NO | `libexpat1-dev` | `expat` | `expat-devel` | `expat-devel` | YES | XML parsing |
| GTest | 1.5 | YES | `libgtest-dev`[1] | `gtest` | `gtest-devel` | `gtest-devel` | YES | Test suite |
| ccache | any | NO | `ccache` | `ccache` | `ccache` | `ccache` | YES | Compil. cache |
| Doxygen | any | NO | `doxygen` | `doxygen` | `doxygen` | `doxygen` | YES | Documentation |
| Graphviz | any | NO | `graphviz` | `graphviz` | `graphviz` | `graphviz` | YES | Documentation |
| lrelease | ? | NO | `qttools5-dev-tools` | `qt5-tools` | `qt5-tools` | `qt5-linguist` | YES | Translations |
| libhidapi | ? | NO | `libhidapi-dev` | `hidapi` | `hidapi-devel` | `hidapi-devel` | YES | Hardware wallet |
| libusb | ? | NO | `libusb-1.0-0-dev` | `libusb` | `libusb-devel` | `libusbx-devel` | YES | Hardware wallet |
| libprotobuf | ? | NO | `libprotobuf-dev` | `protobuf` | `protobuf-devel` | `protobuf-devel` | YES | Hardware wallet |
| protoc | ? | NO | `protobuf-compiler` | `protobuf` | `protobuf` | `protobuf-compiler` | YES | Hardware wallet |
| libudev | ? | NO | `libudev-dev` | `systemd` | `eudev-libudev-devel` | `systemd-devel` | YES | Hardware wallet |
[1] On Debian/Ubuntu `libgtest-dev` only includes sources and headers. You must
build the library binary manually. This can be done with the following command `sudo apt-get install libgtest-dev && cd /usr/src/gtest && sudo cmake . && sudo make`
then:
* on Debian:
`sudo mv libg* /usr/lib/`
* on Ubuntu:
`sudo mv lib/libg* /usr/lib/`
[2] libnorm-dev is needed if your zmq library was built with libnorm, and not needed otherwise
Install all dependencies at once on Debian/Ubuntu:
```
sudo apt update && sudo apt install build-essential cmake pkg-config libssl-dev libzmq3-dev libunbound-dev libsodium-dev libunwind8-dev liblzma-dev libreadline6-dev libexpat1-dev libpgm-dev qttools5-dev-tools libhidapi-dev libusb-1.0-0-dev libprotobuf-dev protobuf-compiler libudev-dev libboost-chrono-dev libboost-date-time-dev libboost-filesystem-dev libboost-locale-dev libboost-program-options-dev libboost-regex-dev libboost-serialization-dev libboost-system-dev libboost-thread-dev python3 ccache doxygen graphviz
```
Install all dependencies at once on Arch:
```
sudo pacman -Syu --needed base-devel cmake boost openssl zeromq libpgm unbound libsodium libunwind xz readline expat gtest python3 ccache doxygen graphviz qt5-tools hidapi libusb protobuf systemd
```
Install all dependencies at once on Fedora:
```
sudo dnf install gcc gcc-c++ cmake pkgconf boost-devel openssl-devel zeromq-devel openpgm-devel unbound-devel libsodium-devel libunwind-devel xz-devel readline-devel expat-devel gtest-devel ccache doxygen graphviz qt5-linguist hidapi-devel libusbx-devel protobuf-devel protobuf-compiler systemd-devel
```
Install all dependencies at once on openSUSE:
```
sudo zypper ref && sudo zypper in cppzmq-devel libboost_chrono-devel libboost_date_time-devel libboost_filesystem-devel libboost_locale-devel libboost_program_options-devel libboost_regex-devel libboost_serialization-devel libboost_system-devel libboost_thread-devel libexpat-devel libminiupnpc-devel libsodium-devel libunwind-devel unbound-devel cmake doxygen ccache fdupes gcc-c++ libevent-devel libopenssl-devel pkgconf-pkg-config readline-devel xz-devel libqt5-qttools-devel patterns-devel-C-C++-devel_C_C++
```
Install all dependencies at once on macOS with the provided Brewfile:
```
brew update && brew bundle --file=contrib/brew/Brewfile
```
FreeBSD 12.1 one-liner required to build dependencies:
```
pkg install git gmake cmake pkgconf boost-libs libzmq4 libsodium unbound
```
### Cloning the repository
Clone recursively to pull-in needed submodule(s):
```
git clone --recursive https://github.com/monero-project/monero
```
If you already have a repo cloned, initialize and update:
```
cd monero && git submodule init && git submodule update
```
*Note*: If there are submodule differences between branches, you may need
to use `git submodule sync && git submodule update` after changing branches
to build successfully.
### Build instructions
Monero uses the CMake build system and a top-level [Makefile](Makefile) that
invokes cmake commands as needed.
#### On Linux and macOS
* Install the dependencies
* Change to the root of the source code directory, change to the most recent release branch, and build:
```bash
cd monero
git checkout release-v0.18
make
```
*Optional*: If your machine has several cores and enough memory, enable
parallel build by running `make -j<number of threads>` instead of `make`. For
this to be worthwhile, the machine should have one core and about 2GB of RAM
available per thread.
*Note*: The instructions above will compile the most stable release of the
Monero software. If you would like to use and test the most recent software,
use `git checkout master`. The master branch may contain updates that are
both unstable and incompatible with release software, though testing is always
encouraged.
* The resulting executables can be found in `build/release/bin`
* Add `PATH="$PATH:$HOME/monero/build/release/bin"` to `.profile`
* Run Monero with `monerod --detach`
* **Optional**: build and run the test suite to verify the binaries:
```bash
make release-test
```
*NOTE*: `core_tests` test may take a few hours to complete.
* **Optional**: to build binaries suitable for debugging:
```bash
make debug
```
* **Optional**: to build statically-linked binaries:
```bash
make release-static
```
Dependencies need to be built with -fPIC. Static libraries usually aren't, so you may have to build them yourself with -fPIC. Refer to their documentation for how to build them.
* **Optional**: build documentation in `doc/html` (omit `HAVE_DOT=YES` if `graphviz` is not installed):
```bash
HAVE_DOT=YES doxygen Doxyfile
```
* **Optional**: use ccache not to rebuild translation units, that haven't really changed. Monero's CMakeLists.txt file automatically handles it
```bash
sudo apt install ccache
```
#### On the Raspberry Pi
Tested on a Raspberry Pi Zero with a clean install of minimal Raspbian Stretch (2017-09-07 or later) from https://www.raspberrypi.org/downloads/raspbian/. If you are using Raspian Jessie, [please see note in the following section](#note-for-raspbian-jessie-users).
* `apt-get update && apt-get upgrade` to install all of the latest software
* Install the dependencies for Monero from the 'Debian' column in the table above.
* Increase the system swap size:
```bash
sudo /etc/init.d/dphys-swapfile stop
sudo nano /etc/dphys-swapfile
CONF_SWAPSIZE=2048
sudo /etc/init.d/dphys-swapfile start
```
* If using an external hard disk without an external power supply, ensure it gets enough power to avoid hardware issues when syncing, by adding the line "max_usb_current=1" to /boot/config.txt
* Clone Monero and checkout the most recent release version:
```bash
git clone https://github.com/monero-project/monero.git
cd monero
git checkout v0.18.2.0
```
* Build:
```bash
USE_SINGLE_BUILDDIR=1 make release
```
* Wait 4-6 hours
* The resulting executables can be found in `build/release/bin`
* Add `export PATH="$PATH:$HOME/monero/build/release/bin"` to `$HOME/.profile`
* Run `source $HOME/.profile`
* Run Monero with `monerod --detach`
* You may wish to reduce the size of the swap file after the build has finished, and delete the boost directory from your home directory
#### *Note for Raspbian Jessie users:*
If you are using the older Raspbian Jessie image, compiling Monero is a bit more complicated. The version of Boost available in the Debian Jessie repositories is too old to use with Monero, and thus you must compile a newer version yourself. The following explains the extra steps and has been tested on a Raspberry Pi 2 with a clean install of minimal Raspbian Jessie.
* As before, `apt-get update && apt-get upgrade` to install all of the latest software, and increase the system swap size
```bash
sudo /etc/init.d/dphys-swapfile stop
sudo nano /etc/dphys-swapfile
CONF_SWAPSIZE=2048
sudo /etc/init.d/dphys-swapfile start
```
* Then, install the dependencies for Monero except for `libunwind` and `libboost-all-dev`
* Install the latest version of boost (this may first require invoking `apt-get remove --purge libboost*-dev` to remove a previous version if you're not using a clean install):
```bash
cd
wget https://sourceforge.net/projects/boost/files/boost/1.72.0/boost_1_72_0.tar.bz2
tar xvfo boost_1_72_0.tar.bz2
cd boost_1_72_0
./bootstrap.sh
sudo ./b2
```
* Wait ~8 hours
```bash
sudo ./bjam cxxflags=-fPIC cflags=-fPIC -a install
```
* Wait ~4 hours
* From here, follow the [general Raspberry Pi instructions](#on-the-raspberry-pi) from the "Clone Monero and checkout most recent release version" step.
#### On Windows:
Binaries for Windows are built on Windows using the MinGW toolchain within
[MSYS2 environment](https://www.msys2.org). The MSYS2 environment emulates a
POSIX system. The toolchain runs within the environment and *cross-compiles*
binaries that can run outside of the environment as a regular Windows
application.
**Preparing the build environment**
* Download and install the [MSYS2 installer](https://www.msys2.org), either the 64-bit or the 32-bit package, depending on your system.
* Open the MSYS shell via the `MSYS2 Shell` shortcut
* Update packages using pacman:
```bash
pacman -Syu
```
* Exit the MSYS shell using Alt+F4
* Edit the properties for the `MSYS2 Shell` shortcut changing "msys2_shell.bat" to "msys2_shell.cmd -mingw64" for 64-bit builds or "msys2_shell.cmd -mingw32" for 32-bit builds
* Restart MSYS shell via modified shortcut and update packages again using pacman:
```bash
pacman -Syu
```
* Install dependencies:
To build for 64-bit Windows:
```bash
pacman -S mingw-w64-x86_64-toolchain make mingw-w64-x86_64-cmake mingw-w64-x86_64-boost mingw-w64-x86_64-openssl mingw-w64-x86_64-zeromq mingw-w64-x86_64-libsodium mingw-w64-x86_64-hidapi mingw-w64-x86_64-unbound
```
To build for 32-bit Windows:
```bash
pacman -S mingw-w64-i686-toolchain make mingw-w64-i686-cmake mingw-w64-i686-boost mingw-w64-i686-openssl mingw-w64-i686-zeromq mingw-w64-i686-libsodium mingw-w64-i686-hidapi mingw-w64-i686-unbound
```
* Open the MingW shell via `MinGW-w64-Win64 Shell` shortcut on 64-bit Windows
or `MinGW-w64-Win64 Shell` shortcut on 32-bit Windows. Note that if you are
running 64-bit Windows, you will have both 64-bit and 32-bit MinGW shells.
**Cloning**
* To git clone, run:
```bash
git clone --recursive https://github.com/monero-project/monero.git
```
**Building**
* Change to the cloned directory, run:
```bash
cd monero
```
* If you would like a specific [version/tag](https://github.com/monero-project/monero/tags), do a git checkout for that version. eg. 'v0.18.2.0'. If you don't care about the version and just want binaries from master, skip this step:
```bash
git checkout v0.18.2.0
```
* If you are on a 64-bit system, run:
```bash
make release-static-win64
```
* If you are on a 32-bit system, run:
```bash
make release-static-win32
```
* The resulting executables can be found in `build/release/bin`
* **Optional**: to build Windows binaries suitable for debugging on a 64-bit system, run:
```bash
make debug-static-win64
```
* **Optional**: to build Windows binaries suitable for debugging on a 32-bit system, run:
```bash
make debug-static-win32
```
* The resulting executables can be found in `build/debug/bin`
### On FreeBSD:
The project can be built from scratch by following instructions for Linux above(but use `gmake` instead of `make`).
If you are running Monero in a jail, you need to add `sysvsem="new"` to your jail configuration, otherwise lmdb will throw the error message: `Failed to open lmdb environment: Function not implemented`.
Monero is also available as a port or package as `monero-cli`.
### On OpenBSD:
You will need to add a few packages to your system. `pkg_add cmake gmake zeromq libiconv boost`.
The `doxygen` and `graphviz` packages are optional and require the xbase set.
Running the test suite also requires `py-requests` package.
Build monero: `env DEVELOPER_LOCAL_TOOLS=1 BOOST_ROOT=/usr/local gmake release-static`
Note: you may encounter the following error when compiling the latest version of Monero as a normal user:
```
LLVM ERROR: out of memory
c++: error: unable to execute command: Abort trap (core dumped)
```
Then you need to increase the data ulimit size to 2GB and try again: `ulimit -d 2000000`
### On NetBSD:
Check that the dependencies are present: `pkg_info -c libexecinfo boost-headers boost-libs protobuf readline libusb1 zeromq git-base pkgconf gmake cmake | more`, and install any that are reported missing, using `pkg_add` or from your pkgsrc tree. Readline is optional but worth having.
Third-party dependencies are usually under `/usr/pkg/`, but if you have a custom setup, adjust the "/usr/pkg" (below) accordingly.
Clone the monero repository recursively and checkout the most recent release as described above. Then build monero: `gmake BOOST_ROOT=/usr/pkg LDFLAGS="-Wl,-R/usr/pkg/lib" release`. The resulting executables can be found in `build/NetBSD/[Release version]/Release/bin/`.
### On Solaris:
The default Solaris linker can't be used, you have to install GNU ld, then run cmake manually with the path to your copy of GNU ld:
```bash
mkdir -p build/release
cd build/release
cmake -DCMAKE_LINKER=/path/to/ld -D CMAKE_BUILD_TYPE=Release ../..
cd ../..
```
Then you can run make as usual.
### Building portable statically linked binaries
By default, in either dynamically or statically linked builds, binaries target the specific host processor on which the build happens and are not portable to other processors. Portable binaries can be built using the following targets:
* ```make release-static-linux-x86_64``` builds binaries on Linux on x86_64 portable across POSIX systems on x86_64 processors
* ```make release-static-linux-i686``` builds binaries on Linux on x86_64 or i686 portable across POSIX systems on i686 processors
* ```make release-static-linux-armv8``` builds binaries on Linux portable across POSIX systems on armv8 processors
* ```make release-static-linux-armv7``` builds binaries on Linux portable across POSIX systems on armv7 processors
* ```make release-static-linux-armv6``` builds binaries on Linux portable across POSIX systems on armv6 processors
* ```make release-static-win64``` builds binaries on 64-bit Windows portable across 64-bit Windows systems
* ```make release-static-win32``` builds binaries on 64-bit or 32-bit Windows portable across 32-bit Windows systems
### Cross Compiling
You can also cross-compile static binaries on Linux for Windows and macOS with the `depends` system.
* ```make depends target=x86_64-linux-gnu``` for 64-bit linux binaries.
* ```make depends target=x86_64-w64-mingw32``` for 64-bit windows binaries.
* Requires: `python3 g++-mingw-w64-x86-64 wine1.6 bc`
* ```make depends target=x86_64-apple-darwin11``` for macOS binaries.
* Requires: `cmake imagemagick libcap-dev librsvg2-bin libz-dev libbz2-dev libtiff-tools python-dev`
* ```make depends target=i686-linux-gnu``` for 32-bit linux binaries.
* Requires: `g++-multilib bc`
* ```make depends target=i686-w64-mingw32``` for 32-bit windows binaries.
* Requires: `python3 g++-mingw-w64-i686`
* ```make depends target=arm-linux-gnueabihf``` for armv7 binaries.
* Requires: `g++-arm-linux-gnueabihf`
* ```make depends target=aarch64-linux-gnu``` for armv8 binaries.
* Requires: `g++-aarch64-linux-gnu`
* ```make depends target=riscv64-linux-gnu``` for RISC V 64 bit binaries.
* Requires: `g++-riscv64-linux-gnu`
* ```make depends target=x86_64-unknown-freebsd``` for freebsd binaries.
* Requires: `clang-8`
* ```make depends target=arm-linux-android``` for 32bit android binaries
* ```make depends target=aarch64-linux-android``` for 64bit android binaries
The required packages are the names for each toolchain on apt. Depending on your distro, they may have different names. The `depends` system has been tested on Ubuntu 18.04 and 20.04.
Using `depends` might also be easier to compile Monero on Windows than using MSYS. Activate Windows Subsystem for Linux (WSL) with a distro (for example Ubuntu), install the apt build-essentials and follow the `depends` steps as depicted above.
The produced binaries still link libc dynamically. If the binary is compiled on a current distribution, it might not run on an older distribution with an older installation of libc. Passing `-DBACKCOMPAT=ON` to cmake will make sure that the binary will run on systems having at least libc version 2.17.
## Installing Monero from a package
**DISCLAIMER: These packages are not part of this repository or maintained by this project's contributors, and as such, do not go through the same review process to ensure their trustworthiness and security.**
Packages are available for Packages are available for
* Debian Buster * Arch Linux/Manjaro
See the [instructions in the whonix/monero-gui repository](https://gitlab.com/whonix/monero-gui#how-to-install-monero-using-apt-get)
* Debian Bullseye and Sid yay -S wownero-git
```bash * Gentoo - Russian hacking tool
sudo apt install monero
```
More info and versions in the [Debian package tracker](https://tracker.debian.org/pkg/monero).
* Arch Linux [(via Community packages)](https://www.archlinux.org/packages/community/x86_64/monero/): emerge --noreplace eselect-repository
eselect repository enable monero
emaint sync -r monero
echo '*/*::monero ~amd64' >> /etc/portage/package.accept_keywords
emerge net-p2p/wownero
```bash * NixOS
sudo pacman -S monero
```
* Void Linux: nix-shell -p wownero
```bash Packaging for your favorite distribution would be a welcome contribution!
xbps-install -S monero
```
* GuixSD
```bash
guix package -i monero
```
* Gentoo [Monero overlay](https://github.com/gentoo-monero/gentoo-monero) **DISCLAIMER: These packages are not part of this repository, and as such, do not go through the same review process to ensure their trustworthiness and security.**
```bash
emerge --noreplace eselect-repository
eselect repository enable monero
emaint sync -r monero
echo '*/*::monero ~amd64' >> /etc/portage/package.accept_keywords
emerge net-p2p/monero
```
* macOS [(homebrew)](https://brew.sh/) ## Building from Source
```bash
brew install monero
```
* Docker * Docker
```bash git clone https://git.wownero.com/wownero/wownero && cd wownero
# Build using all available cores docker build -t git-wow:master -m 4g .
docker build -t monero . docker run -it -p 34567:34567 -p 34568:34568 -w /home/wownero/build/release/bin git-wow:master bash
# or build using a specific number of cores (reduce RAM requirement) * Arch Linux/Manjaro
docker build --build-arg NPROC=1 -t monero .
# either run in foreground sudo pacman -Syu && sudo pacman -S base-devel cmake boost openssl zeromq libpgm unbound libsodium git libusb systemd
docker run -it -v /monero/chain:/home/monero/.bitmonero -v /monero/wallet:/wallet -p 18080:18080 monero git clone https://git.wownero.com/wownero/wownero && cd wownero
make -j2
# or in background * Debian/Ubuntu
docker run -it -d -v /monero/chain:/home/monero/.bitmonero -v /monero/wallet:/wallet -p 18080:18080 monero
```
* The build needs 3 GB space. sudo apt update && sudo apt install build-essential cmake pkg-config libboost-all-dev libssl-dev libzmq3-dev libunbound-dev libsodium-dev libunwind8-dev liblzma-dev libreadline6-dev libldns-dev libexpat1-dev libpgm-dev libhidapi-dev libusb-1.0-0-dev libprotobuf-dev protobuf-compiler libudev-dev git -y
* Wait one hour or more git clone https://git.wownero.com/wownero/wownero && cd wownero
make -j2
Packaging for your favorite distribution would be a welcome contribution!
## Running monerod ## Running Binaries
The build places the binary in `bin/` sub-directory within the build directory The build places the binary in `bin/` sub-directory within the build directory
from which cmake was invoked (repository root by default). To run in the from which cmake was invoked (repository root by default). To run in the
foreground: foreground:
```bash ./bin/wownerod
./bin/monerod
```
To list all available options, run `./bin/monerod --help`. Options can be To list all available options, run `./bin/wownerod --help`. Options can be
specified either on the command line or in a configuration file passed by the specified either on the command line or in a configuration file passed by the
`--config-file` argument. To specify an option in the configuration file, add `--config-file` argument. To specify an option in the configuration file, add
a line with the syntax `argumentname=value`, where `argumentname` is the name a line with the syntax `argumentname=value`, where `argumentname` is the name
@ -675,186 +166,57 @@ of the argument without the leading dashes, for example, `log-level=1`.
To run in background: To run in background:
```bash ./bin/wownerod --log-file wownerod.log --detach
./bin/monerod --log-file monerod.log --detach
```
To run as a systemd service, copy To run as a systemd service, copy
[monerod.service](utils/systemd/monerod.service) to `/etc/systemd/system/` and [wownerod.service](utils/systemd/wownerod.service) to `/etc/systemd/system/` and
[monerod.conf](utils/conf/monerod.conf) to `/etc/`. The [example [wow.conf](wow.conf) to `/etc/`. The [example
service](utils/systemd/monerod.service) assumes that the user `monero` exists service](utils/systemd/wownerod.service) assumes that the user `wownero` exists
and its home is the data directory specified in the [example and its home is the data directory specified in the [example
config](utils/conf/monerod.conf). config](wow.conf).
If you're on Mac, you may need to add the `--max-concurrency 1` option to
monero-wallet-cli, and possibly monerod, if you get crashes refreshing.
## Internationalization
See [README.i18n.md](docs/README.i18n.md).
## Using Tor
> There is a new, still experimental, [integration with Tor](docs/ANONYMITY_NETWORKS.md). The
> feature allows connecting over IPv4 and Tor simultaneously - IPv4 is used for
> relaying blocks and relaying transactions received by peers whereas Tor is
> used solely for relaying transactions received over local RPC. This provides
> privacy and better protection against surrounding node (sybil) attacks.
While Monero isn't made to integrate with Tor, it can be used wrapped with torsocks, by
setting the following configuration parameters and environment variables:
* `--p2p-bind-ip 127.0.0.1` on the command line or `p2p-bind-ip=127.0.0.1` in
monerod.conf to disable listening for connections on external interfaces.
* `--no-igd` on the command line or `no-igd=1` in monerod.conf to disable IGD
(UPnP port forwarding negotiation), which is pointless with Tor.
* `DNS_PUBLIC=tcp` or `DNS_PUBLIC=tcp://x.x.x.x` where x.x.x.x is the IP of the
desired DNS server, for DNS requests to go over TCP, so that they are routed
through Tor. When IP is not specified, monerod uses the default list of
servers defined in [src/common/dns_utils.cpp](src/common/dns_utils.cpp).
* `TORSOCKS_ALLOW_INBOUND=1` to tell torsocks to allow monerod to bind to interfaces
to accept connections from the wallet. On some Linux systems, torsocks
allows binding to localhost by default, so setting this variable is only
necessary to allow binding to local LAN/VPN interfaces to allow wallets to
connect from remote hosts. On other systems, it may be needed for local wallets
as well.
* Do NOT pass `--detach` when running through torsocks with systemd, (see
[utils/systemd/monerod.service](utils/systemd/monerod.service) for details).
* If you use the wallet with a Tor daemon via the loopback IP (eg, 127.0.0.1:9050),
then use `--untrusted-daemon` unless it is your own hidden service.
Example command line to start monerod through Tor:
```bash
DNS_PUBLIC=tcp torsocks monerod --p2p-bind-ip 127.0.0.1 --no-igd
```
A helper script is in contrib/tor/monero-over-tor.sh. It assumes Tor is installed
already, and runs Tor and Monero with the right configuration.
### Using Tor on Tails
TAILS ships with a very restrictive set of firewall rules. Therefore, you need Once node is synced to network, run the CLI wallet by entering:
to add a rule to allow this connection too, in addition to telling torsocks to
allow inbound connections. Full example:
```bash ./bin/wownero-wallet-cli
sudo iptables -I OUTPUT 2 -p tcp -d 127.0.0.1 -m tcp --dport 18081 -j ACCEPT
DNS_PUBLIC=tcp torsocks ./monerod --p2p-bind-ip 127.0.0.1 --no-igd --rpc-bind-ip 127.0.0.1 \
--data-dir /home/amnesia/Persistent/your/directory/to/the/blockchain
```
## Pruning
As of April 2022, the full Monero blockchain file is about 130 GB. One can store a pruned blockchain, which is about 45 GB.
A pruned blockchain can only serve part of the historical chain data to other peers, but is otherwise identical in
functionality to the full blockchain.
To use a pruned blockchain, it is best to start the initial sync with `--prune-blockchain`. However, it is also possible
to prune an existing blockchain using the `monero-blockchain-prune` tool or using the `--prune-blockchain` `monerod` option
with an existing chain. If an existing chain exists, pruning will temporarily require disk space to store both the full
and pruned blockchains.
For more detailed information see the ['Pruning' entry in the Moneropedia](https://www.getmonero.org/resources/moneropedia/pruning.html)
## Debugging
This section contains general instructions for debugging failed installs or problems encountered with Monero. First, ensure you are running the latest version built from the GitHub repo.
### Obtaining stack traces and core dumps on Unix systems
We generally use the tool `gdb` (GNU debugger) to provide stack trace functionality, and `ulimit` to provide core dumps in builds which crash or segfault. Type `help` in CLI wallet to see standard commands (for advanced options, type `help_advanced`).
* To use `gdb` in order to obtain a stack trace for a build that has stalled: ## Tor Anonymity Network
Run the build. ### Ubuntu
Once it stalls, enter the following command: * `sudo apt-get update && sudo apt-get install tor -y`
* `sudo nano /etc/tor/torrc`
```bash add the following:
gdb /path/to/monerod `pidof monerod`
``` ```
HiddenServiceDir /var/lib/tor/wownero/
Type `thread apply all bt` within gdb in order to obtain the stack trace HiddenServicePort 34569 127.0.0.1:34569
HiddenServicePort 34566 127.0.0.1:34566
* If however the core dumps or segfaults: HiddenServiceVersion 3
Enter `ulimit -c unlimited` on the command line to enable unlimited filesizes for core dumps
Enter `echo core | sudo tee /proc/sys/kernel/core_pattern` to stop cores from being hijacked by other tools
Run the build.
When it terminates with an output along the lines of "Segmentation fault (core dumped)", there should be a core dump file in the same directory as monerod. It may be named just `core`, or `core.xxxx` with numbers appended.
You can now analyse this core dump with `gdb` as follows:
```bash
gdb /path/to/monerod /path/to/dumpfile`
``` ```
save and close nano
Print the stack trace with `bt` * `sudo /etc/init.d/tor restart && sudo systemctl enable tor`
* copy [wow.conf](https://git.wownero.com/wownero/wownero/raw/branch/master/wow.conf) file and save it in same directory as `wownerod`.
* start wownerod like this:
* If a program crashed and cores are managed by systemd, the following can also get a stack trace for that crash:
```bash
coredumpctl -1 gdb
``` ```
./wownerod --config-file=wow.conf
#### To run Monero within gdb:
Type `gdb /path/to/monerod`
Pass command-line options with `--args` followed by the relevant arguments
Type `run` to run monerod
### Analysing memory corruption
There are two tools available:
#### ASAN
Configure Monero with the -D SANITIZE=ON cmake flag, eg:
```bash
cd build/debug && cmake -D SANITIZE=ON -D CMAKE_BUILD_TYPE=Debug ../..
``` ```
You can then run the monero tools normally. Performance will typically halve. * `sudo cat /var/lib/tor/wownero/hostname`
copy your onion address and share node with others [here](https://monero.fail/?crypto=wownero) and [here](https://forum.wownero.com/t/wownero-tor-onion-sites/623)
#### valgrind
Install valgrind and run as `valgrind /path/to/monerod`. It will be very slow. To share your node over p2p, uncomment first line of wownerod.conf and add your onion address.
### LMDB More information on running Tor and i2p nodes is available [here](https://forum.wownero.com/t/how-to-setup-a-full-node-with-tor-i2p/588)
Instructions for debugging suspected blockchain corruption as per @HYC ### Access remote Tor node from CLI wallet
There is an `mdb_stat` command in the LMDB source that can print statistics about the database but it's not routinely built. This can be built with the following command: ```
./wownero-wallet-cli --proxy 127.0.0.1:9050 --daemon-address iy6ry6uudpzvbd72zsipepukp6nsazjdu72n52vg3isfnxqn342flzad.onion:34568
```bash
cd ~/monero/external/db_drivers/liblmdb && make
``` ```
The output of `mdb_stat -ea <path to blockchain dir>` will indicate inconsistencies in the blocks, block_heights and block_info table. Copyright (c) 2014-2024 The Monero Project.
Portions Copyright (c) 2012-2013 The Cryptonote developers.
The output of `mdb_dump -s blocks <path to blockchain dir>` and `mdb_dump -s block_info <path to blockchain dir>` is useful for indicating whether blocks and block_info contain the same keys.
These records are dumped as hex data, where the first line is the key and the second line is the data.
# Known Issues
## Protocols
### Socket-based
Because of the nature of the socket-based protocols that drive monero, certain protocol weaknesses are somewhat unavoidable at this time. While these weaknesses can theoretically be fully mitigated, the effort required (the means) may not justify the ends. As such, please consider taking the following precautions if you are a monero node operator:
- Run `monerod` on a "secured" machine. If operational security is not your forte, at a very minimum, have a dedicated a computer running `monerod` and **do not** browse the web, use email clients, or use any other potentially harmful apps on your `monerod` machine. **Do not click links or load URL/MUA content on the same machine**. Doing so may potentially exploit weaknesses in commands which accept "localhost" and "127.0.0.1".
- If you plan on hosting a public "remote" node, start `monerod` with `--restricted-rpc`. This is a must.
### Blockchain-based
Certain blockchain "features" can be considered "bugs" if misused correctly. Consequently, please consider the following:
- When receiving monero, be aware that it may be locked for an arbitrary time if the sender elected to, preventing you from spending that monero until the lock time expires. You may want to hold off acting upon such a transaction until the unlock time lapses. To get a sense of that time, you can consider the remaining blocktime until unlock as seen in the `show_transfers` command.

@ -145,7 +145,7 @@ $(1)_build_env+=PATH="$(build_prefix)/bin:$(PATH)"
$(1)_stage_env+=PATH="$(build_prefix)/bin:$(PATH)" $(1)_stage_env+=PATH="$(build_prefix)/bin:$(PATH)"
$(1)_autoconf=./configure --host=$($($(1)_type)_host) --prefix=$($($(1)_type)_prefix) $$($(1)_config_opts) CC="$$($(1)_cc)" CXX="$$($(1)_cxx)" $(1)_autoconf=./configure --host=$($($(1)_type)_host) --prefix=$($($(1)_type)_prefix) $$($(1)_config_opts) CC="$$($(1)_cc)" CXX="$$($(1)_cxx)"
ifneq ($(1),libusb) ifeq ($(filter $(1),libusb unbound),)
$(1)_autoconf += --disable-dependency-tracking $(1)_autoconf += --disable-dependency-tracking
endif endif
ifneq ($($(1)_nm),) ifneq ($($(1)_nm),)

@ -1,12 +1,12 @@
package=expat package=expat
$(package)_version=2.4.1 $(package)_version=2.6.0
$(package)_download_path=https://github.com/libexpat/libexpat/releases/download/R_2_4_1 $(package)_download_path=https://github.com/libexpat/libexpat/releases/download/R_$(subst .,_,$($(package)_version))/
$(package)_file_name=$(package)-$($(package)_version).tar.bz2 $(package)_file_name=$(package)-$($(package)_version).tar.bz2
$(package)_sha256_hash=2f9b6a580b94577b150a7d5617ad4643a4301a6616ff459307df3e225bcfbf40 $(package)_sha256_hash=ff60e6a6b6ce570ae012dc7b73169c7fdf4b6bf08c12ed0ec6f55736b78d85ba
define $(package)_set_vars define $(package)_set_vars
$(package)_config_opts=--enable-static $(package)_config_opts=--disable-shared --without-docbook --without-tests --without-examples
$(package)_config_opts=--disable-shared $(package)_config_opts+=--enable-option-checking --without-xmlwf --with-pic
$(package)_config_opts+=--prefix=$(host_prefix) $(package)_config_opts+=--prefix=$(host_prefix)
endef endef
@ -23,6 +23,6 @@ define $(package)_stage_cmds
endef endef
define $(package)_postprocess_cmds define $(package)_postprocess_cmds
rm lib/*.la rm -rf share lib/cmake lib/*.la
endef endef

@ -1,20 +1,19 @@
package=openssl package=openssl
$(package)_version=1.1.1t $(package)_version=3.0.13
$(package)_download_path=https://www.openssl.org/source $(package)_download_path=https://www.openssl.org/source
$(package)_file_name=$(package)-$($(package)_version).tar.gz $(package)_file_name=$(package)-$($(package)_version).tar.gz
$(package)_sha256_hash=8dee9b24bdb1dcbf0c3d1e9b02fb8f6bf22165e807f45adeb7c9677536859d3b $(package)_sha256_hash=88525753f79d3bec27d2fa7c66aa0b92b3aa9498dafd93d7cfa4b3780cdae313
define $(package)_set_vars define $(package)_set_vars
$(package)_config_env=AR="$($(package)_ar)" ARFLAGS=$($(package)_arflags) RANLIB="$($(package)_ranlib)" CC="$($(package)_cc)" $(package)_config_env=AR="$($(package)_ar)" ARFLAGS=$($(package)_arflags) RANLIB="$($(package)_ranlib)" CC="$($(package)_cc)"
$(package)_config_env_android=ANDROID_NDK_HOME="$(host_prefix)/native" PATH="$(host_prefix)/native/bin" CC=clang AR=ar RANLIB=ranlib $(package)_config_env_android=ANDROID_NDK_ROOT="$(host_prefix)/native" PATH="$(host_prefix)/native/bin" CC=clang AR=ar RANLIB=ranlib
$(package)_build_env_android=ANDROID_NDK_HOME="$(host_prefix)/native" $(package)_build_env_android=ANDROID_NDK_ROOT="$(host_prefix)/native"
$(package)_config_opts=--prefix=$(host_prefix) --openssldir=$(host_prefix)/etc/openssl $(package)_config_opts=--prefix=$(host_prefix) --openssldir=$(host_prefix)/etc/openssl --libdir=$(host_prefix)/lib
$(package)_config_opts+=no-capieng $(package)_config_opts+=no-capieng
$(package)_config_opts+=no-dso $(package)_config_opts+=no-dso
$(package)_config_opts+=no-dtls1 $(package)_config_opts+=no-dtls1
$(package)_config_opts+=no-ec_nistp_64_gcc_128 $(package)_config_opts+=no-ec_nistp_64_gcc_128
$(package)_config_opts+=no-gost $(package)_config_opts+=no-gost
$(package)_config_opts+=no-heartbeats
$(package)_config_opts+=no-md2 $(package)_config_opts+=no-md2
$(package)_config_opts+=no-rc5 $(package)_config_opts+=no-rc5
$(package)_config_opts+=no-rdrand $(package)_config_opts+=no-rdrand
@ -22,8 +21,8 @@ $(package)_config_opts+=no-rfc3779
$(package)_config_opts+=no-sctp $(package)_config_opts+=no-sctp
$(package)_config_opts+=no-shared $(package)_config_opts+=no-shared
$(package)_config_opts+=no-ssl-trace $(package)_config_opts+=no-ssl-trace
$(package)_config_opts+=no-ssl2
$(package)_config_opts+=no-ssl3 $(package)_config_opts+=no-ssl3
$(package)_config_opts+=no-tests
$(package)_config_opts+=no-unit-test $(package)_config_opts+=no-unit-test
$(package)_config_opts+=no-weak-ssl-ciphers $(package)_config_opts+=no-weak-ssl-ciphers
$(package)_config_opts+=no-zlib $(package)_config_opts+=no-zlib
@ -49,7 +48,7 @@ $(package)_config_opts_x86_64_freebsd=BSD-x86_64
endef endef
define $(package)_preprocess_cmds define $(package)_preprocess_cmds
sed -i.old 's|"engines", "apps", "test", "util", "tools", "fuzz"|"engines", "tools"|' Configure sed -i.old 's|crypto ssl apps util tools fuzz providers doc|crypto ssl util tools providers|' build.info
endef endef
define $(package)_config_cmds define $(package)_config_cmds

@ -1,17 +1,21 @@
package=unbound package=unbound
$(package)_version=1.15.0 $(package)_version=1.19.1
$(package)_download_path=https://www.nlnetlabs.nl/downloads/$(package)/ $(package)_download_path=https://www.nlnetlabs.nl/downloads/$(package)/
$(package)_file_name=$(package)-$($(package)_version).tar.gz $(package)_file_name=$(package)-$($(package)_version).tar.gz
$(package)_sha256_hash=a480dc6c8937447b98d161fe911ffc76cfaffa2da18788781314e81339f1126f $(package)_sha256_hash=bc1d576f3dd846a0739adc41ffaa702404c6767d2b6082deb9f2f97cbb24a3a9
$(package)_dependencies=openssl expat $(package)_dependencies=openssl expat
$(package)_patches=disable-glibc-reallocarray.patch $(package)_patches=disable-glibc-reallocarray.patch
define $(package)_set_vars define $(package)_set_vars
$(package)_config_opts=--disable-shared --enable-static --without-pyunbound --prefix=$(host_prefix) --with-libexpat=$(host_prefix) --with-ssl=$(host_prefix) --with-libevent=no --without-pythonmodule --disable-flto --with-pthreads --with-libunbound-only $(package)_config_opts=--disable-shared --enable-static --without-pyunbound --prefix=$(host_prefix)
$(package)_config_opts+=--with-libexpat=$(host_prefix) --with-ssl=$(host_prefix) --with-libevent=no
$(package)_config_opts+=--without-pythonmodule --disable-flto --with-pthreads --with-libunbound-only
$(package)_config_opts_linux=--with-pic $(package)_config_opts_linux=--with-pic
$(package)_config_opts_w64=--enable-static-exe --sysconfdir=/etc --prefix=$(host_prefix) --target=$(host_prefix) $(package)_config_opts_w64=--enable-static-exe --sysconfdir=/etc --prefix=$(host_prefix) --target=$(host_prefix)
$(package)_config_opts_x86_64_darwin=ac_cv_func_SHA384_Init=yes
$(package)_build_opts_mingw32=LDFLAGS="$($(package)_ldflags) -lpthread" $(package)_build_opts_mingw32=LDFLAGS="$($(package)_ldflags) -lpthread"
$(package)_cflags_mingw32+="-D_WIN32_WINNT=0x600"
endef endef
define $(package)_preprocess_cmds define $(package)_preprocess_cmds
@ -30,6 +34,3 @@ endef
define $(package)_stage_cmds define $(package)_stage_cmds
$(MAKE) DESTDIR=$($(package)_staging_dir) install $(MAKE) DESTDIR=$($(package)_staging_dir) install
endef endef
define $(package)_postprocess_cmds
endef

@ -144,8 +144,11 @@ elseif(ARCHITECTURE STREQUAL "aarch64")
endif() endif()
if(ARCHITECTURE STREQUAL "riscv64") if(ARCHITECTURE STREQUAL "riscv64")
set(NO_AES ON) if(CMAKE_SYSTEM_NAME STREQUAL "Linux")
set(ARCH "rv64imafdc") set(BUILD_TAG "linux-riscv64")
endif()
set(ARCH_ID "riscv64")
set(ARCH "rv64gc")
endif() endif()
if(ARCHITECTURE STREQUAL "i686") if(ARCHITECTURE STREQUAL "i686")

@ -29,6 +29,7 @@
#include <string> #include <string>
#include <ctime> #include <ctime>
#include <cstdint>
namespace epee namespace epee
{ {

@ -583,11 +583,8 @@ namespace net_utils
break; break;
} }
} }
else if (ec.value())
terminate();
else { else {
cancel_timer(); terminate();
on_interrupted();
} }
}; };
m_strand.post( m_strand.post(

@ -147,6 +147,16 @@ namespace epee
return {reinterpret_cast<const std::uint8_t*>(src.data()), src.size_bytes()}; return {reinterpret_cast<const std::uint8_t*>(src.data()), src.size_bytes()};
} }
//! \return `span<std::uint8_t>` from a STL compatible `src`.
template<typename T>
constexpr span<std::uint8_t> to_mut_byte_span(T& src)
{
using value_type = typename T::value_type;
static_assert(!std::is_empty<value_type>(), "empty value types will not work -> sizeof == 1");
static_assert(!has_padding<value_type>(), "source value type may have padding");
return {reinterpret_cast<std::uint8_t*>(src.data()), src.size() * sizeof(value_type)};
}
//! \return `span<const std::uint8_t>` which represents the bytes at `&src`. //! \return `span<const std::uint8_t>` which represents the bytes at `&src`.
template<typename T> template<typename T>
span<const std::uint8_t> as_byte_span(const T& src) noexcept span<const std::uint8_t> as_byte_span(const T& src) noexcept

@ -30,6 +30,7 @@
#include <boost/utility/string_ref_fwd.hpp> #include <boost/utility/string_ref_fwd.hpp>
#include <string> #include <string>
#include <cstdint>
namespace epee namespace epee
{ {

@ -33,6 +33,9 @@
#include "portable_storage_base.h" #include "portable_storage_base.h"
#include "portable_storage_bin_utils.h" #include "portable_storage_bin_utils.h"
#undef MONERO_DEFAULT_LOG_CATEGORY
#define MONERO_DEFAULT_LOG_CATEGORY "serialization"
#ifdef EPEE_PORTABLE_STORAGE_RECURSION_LIMIT #ifdef EPEE_PORTABLE_STORAGE_RECURSION_LIMIT
#define EPEE_PORTABLE_STORAGE_RECURSION_LIMIT_INTERNAL EPEE_PORTABLE_STORAGE_RECURSION_LIMIT #define EPEE_PORTABLE_STORAGE_RECURSION_LIMIT_INTERNAL EPEE_PORTABLE_STORAGE_RECURSION_LIMIT
#else #else

@ -31,6 +31,9 @@
#include "parserse_base_utils.h" #include "parserse_base_utils.h"
#include "file_io_utils.h" #include "file_io_utils.h"
#undef MONERO_DEFAULT_LOG_CATEGORY
#define MONERO_DEFAULT_LOG_CATEGORY "serialization"
#define EPEE_JSON_RECURSION_LIMIT_INTERNAL 100 #define EPEE_JSON_RECURSION_LIMIT_INTERNAL 100
namespace epee namespace epee

@ -338,11 +338,21 @@ bool is_stdout_a_tty()
return is_a_tty.load(std::memory_order_relaxed); return is_a_tty.load(std::memory_order_relaxed);
} }
static bool is_nocolor()
{
static const char *no_color_var = getenv("NO_COLOR");
static const bool no_color = no_color_var && *no_color_var; // apparently, NO_COLOR=0 means no color too (as per no-color.org)
return no_color;
}
void set_console_color(int color, bool bright) void set_console_color(int color, bool bright)
{ {
if (!is_stdout_a_tty()) if (!is_stdout_a_tty())
return; return;
if (is_nocolor())
return;
switch(color) switch(color)
{ {
case console_color_default: case console_color_default:
@ -461,6 +471,9 @@ void reset_console_color() {
if (!is_stdout_a_tty()) if (!is_stdout_a_tty())
return; return;
if (is_nocolor())
return;
#ifdef WIN32 #ifdef WIN32
HANDLE h_stdout = GetStdHandle(STD_OUTPUT_HANDLE); HANDLE h_stdout = GetStdHandle(STD_OUTPUT_HANDLE);
SetConsoleTextAttribute(h_stdout, FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE); SetConsoleTextAttribute(h_stdout, FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);

@ -496,6 +496,13 @@ void ssl_options_t::configure(
const std::string& host) const const std::string& host) const
{ {
socket.next_layer().set_option(boost::asio::ip::tcp::no_delay(true)); socket.next_layer().set_option(boost::asio::ip::tcp::no_delay(true));
{
// in case server is doing "virtual" domains, set hostname
SSL* const ssl_ctx = socket.native_handle();
if (type == boost::asio::ssl::stream_base::client && !host.empty() && ssl_ctx)
SSL_set_tlsext_host_name(ssl_ctx, host.c_str());
}
/* Using system-wide CA store for client verification is funky - there is /* Using system-wide CA store for client verification is funky - there is
no expected hostname for server to verify against. If server doesn't have no expected hostname for server to verify against. If server doesn't have
@ -513,11 +520,7 @@ void ssl_options_t::configure(
{ {
socket.set_verify_mode(boost::asio::ssl::verify_peer | boost::asio::ssl::verify_fail_if_no_peer_cert); socket.set_verify_mode(boost::asio::ssl::verify_peer | boost::asio::ssl::verify_fail_if_no_peer_cert);
// in case server is doing "virtual" domains, set hostname
SSL* const ssl_ctx = socket.native_handle();
if (type == boost::asio::ssl::stream_base::client && !host.empty() && ssl_ctx)
SSL_set_tlsext_host_name(ssl_ctx, host.c_str());
socket.set_verify_callback([&](const bool preverified, boost::asio::ssl::verify_context &ctx) socket.set_verify_callback([&](const bool preverified, boost::asio::ssl::verify_context &ctx)
{ {
// preverified means it passed system or user CA check. System CA is never loaded // preverified means it passed system or user CA check. System CA is never loaded

@ -238,6 +238,10 @@ static char** attempted_completion(const char* text, int start, int end)
static void install_line_handler() static void install_line_handler()
{ {
#if RL_READLINE_VERSION >= 0x0801
rl_variable_bind("enable-bracketed-paste", "off");
#endif
rl_attempted_completion_function = attempted_completion; rl_attempted_completion_function = attempted_completion;
rl_callback_handler_install("", handle_line); rl_callback_handler_install("", handle_line);
stifle_history(500); stifle_history(500);

@ -57,7 +57,7 @@ The dockrun.sh script will do everything to build the binaries. Just specify the
version to build as its only argument, e.g. version to build as its only argument, e.g.
```bash ```bash
VERSION=v0.18.2.0 VERSION=v0.18.3.2
./dockrun.sh $VERSION ./dockrun.sh $VERSION
``` ```

@ -133,7 +133,7 @@ Common setup part:
su - gitianuser su - gitianuser
GH_USER=YOUR_GITHUB_USER_NAME GH_USER=YOUR_GITHUB_USER_NAME
VERSION=v0.18.2.0 VERSION=v0.18.3.2
``` ```
Where `GH_USER` is your GitHub user name and `VERSION` is the version tag you want to build. Where `GH_USER` is your GitHub user name and `VERSION` is the version tag you want to build.

@ -41,10 +41,10 @@ RUN useradd -ms /bin/bash -U ubuntu -G docker
USER ubuntu:docker USER ubuntu:docker
WORKDIR $WORKDIR WORKDIR $WORKDIR
RUN git clone https://github.com/monero-project/gitian.sigs.git sigs; \ RUN git clone https://git.wownero.com/wownero/gitian.sigs.git sigs; \
git clone https://github.com/devrandom/gitian-builder.git builder; \ git clone https://github.com/devrandom/gitian-builder.git builder; \
cd builder; git checkout c0f77ca018cb5332bfd595e0aff0468f77542c23; mkdir -p inputs var; cd inputs; \ cd builder; git checkout c0f77ca018cb5332bfd595e0aff0468f77542c23; mkdir -p inputs var; cd inputs; \
git clone https://github.com/monero-project/monero git clone https://git.wownero.com/wownero/wownero
CMD ["sleep", "infinity"] CMD ["sleep", "infinity"]
EOF EOF
@ -109,7 +109,7 @@ if [ "$check" != "sign" ]; then
fi fi
if [ ! -d sigs ]; then if [ ! -d sigs ]; then
git clone https://github.com/monero-project/gitian.sigs.git sigs git clone https://git.wownero.com/wownero/gitian.sigs.git sigs
cd sigs cd sigs
git remote add $GH_USER git@github.com:$GH_USER/gitian.sigs.git git remote add $GH_USER git@github.com:$GH_USER/gitian.sigs.git
cd .. cd ..

@ -1,5 +1,5 @@
--- ---
name: "monero-android-0.18" name: "wownero-android-0.11"
enable_cache: true enable_cache: true
suites: suites:
- "bionic" - "bionic"
@ -26,8 +26,8 @@ packages:
- "cmake" - "cmake"
- "unzip" - "unzip"
remotes: remotes:
- "url": "https://github.com/monero-project/monero.git" - "url": "https://git.wownero.com/wownero/wownero.git"
"dir": "monero" "dir": "wownero"
files: [] files: []
script: | script: |
@ -70,7 +70,7 @@ script: |
then then
ABI=$i"eabi" ABI=$i"eabi"
fi fi
NDKDIR="${BUILD_DIR}/monero/contrib/depends/$i/native/bin" NDKDIR="${BUILD_DIR}/wownero/contrib/depends/$i/native/bin"
for prog in ${FAKETIME_HOST_PROGS}; do for prog in ${FAKETIME_HOST_PROGS}; do
WRAPPER=${WRAP_DIR}/${ABI}-${prog} WRAPPER=${WRAP_DIR}/${ABI}-${prog}
echo '#!/usr/bin/env bash' > ${WRAPPER} echo '#!/usr/bin/env bash' > ${WRAPPER}
@ -92,7 +92,7 @@ script: |
export SOURCE_DATE_EPOCH=`date -d 2000-01-01T12:00:00 +%s` export SOURCE_DATE_EPOCH=`date -d 2000-01-01T12:00:00 +%s`
git config --global core.abbrev 9 git config --global core.abbrev 9
cd monero cd wownero
# Set the version string that gets added to the tar archive name # Set the version string that gets added to the tar archive name
version="`git describe`" version="`git describe`"
if [[ $version == *"-"*"-"* ]]; then if [[ $version == *"-"*"-"* ]]; then
@ -120,9 +120,9 @@ script: |
cmake .. -DCMAKE_TOOLCHAIN_FILE=${BASEPREFIX}/${i}/share/toolchain.cmake -DCMAKE_BUILD_TYPE=Release cmake .. -DCMAKE_TOOLCHAIN_FILE=${BASEPREFIX}/${i}/share/toolchain.cmake -DCMAKE_BUILD_TYPE=Release
make ${MAKEOPTS} make ${MAKEOPTS}
chmod 755 bin/* chmod 755 bin/*
cp ../LICENSE ../README.md ../docs/ANONYMITY_NETWORKS.md bin cp ../utils/conf/wow.conf bin
chmod 644 bin/LICENSE bin/*.md chmod 644 bin/wow.conf
DISTNAME=monero-${i}-${version} DISTNAME=wownero-${i}-${version}
mv bin ${DISTNAME} mv bin ${DISTNAME}
find ${DISTNAME}/ | sort | tar --no-recursion --owner=0 --group=0 -c -T - | bzip2 -9 > ${OUTDIR}/${DISTNAME}.tar.bz2 find ${DISTNAME}/ | sort | tar --no-recursion --owner=0 --group=0 -c -T - | bzip2 -9 > ${OUTDIR}/${DISTNAME}.tar.bz2
cd .. cd ..

@ -5,7 +5,7 @@ import os
import subprocess import subprocess
import sys import sys
gsigs = 'https://github.com/monero-project/gitian.sigs.git' gsigs = 'https://git.wownero.com/wownero/gitian.sigs.git'
gbrepo = 'https://github.com/devrandom/gitian-builder.git' gbrepo = 'https://github.com/devrandom/gitian-builder.git'
platforms = {'l': ['Linux', 'linux', 'tar.bz2'], platforms = {'l': ['Linux', 'linux', 'tar.bz2'],
@ -31,10 +31,10 @@ def setup():
subprocess.check_call(['git', 'checkout', 'c0f77ca018cb5332bfd595e0aff0468f77542c23']) subprocess.check_call(['git', 'checkout', 'c0f77ca018cb5332bfd595e0aff0468f77542c23'])
os.makedirs('inputs', exist_ok=True) os.makedirs('inputs', exist_ok=True)
os.chdir('inputs') os.chdir('inputs')
if os.path.isdir('monero'): if os.path.isdir('wownero'):
# Remove the potentially stale monero dir. Otherwise you might face submodule mismatches. # Remove the potentially stale wownero dir. Otherwise you might face submodule mismatches.
subprocess.check_call(['rm', 'monero', '-fR']) subprocess.check_call(['rm', 'wownero', '-fR'])
subprocess.check_call(['git', 'clone', args.url, 'monero']) subprocess.check_call(['git', 'clone', args.url, 'wownero'])
os.chdir('..') os.chdir('..')
make_image_prog = ['bin/make-base-vm', '--suite', 'bionic', '--arch', 'amd64'] make_image_prog = ['bin/make-base-vm', '--suite', 'bionic', '--arch', 'amd64']
if args.docker: if args.docker:
@ -66,10 +66,10 @@ def rebuild():
suffix = platforms[i][2] suffix = platforms[i][2]
print('\nCompiling ' + args.version + ' ' + os_name) print('\nCompiling ' + args.version + ' ' + os_name)
infile = 'inputs/monero/contrib/gitian/gitian-' + tag_name + '.yml' infile = 'inputs/wownero/contrib/gitian/gitian-' + tag_name + '.yml'
subprocess.check_call(['bin/gbuild', '-j', args.jobs, '-m', args.memory, '--commit', 'monero='+args.commit, '--url', 'monero='+args.url, infile]) subprocess.check_call(['bin/gbuild', '-j', args.jobs, '-m', args.memory, '--commit', 'wownero='+args.commit, '--url', 'wownero='+args.url, infile])
subprocess.check_call(['bin/gsign', '-p', args.sign_prog, '--signer', args.signer, '--release', args.version+'-'+tag_name, '--destination', '../sigs/', infile]) subprocess.check_call(['bin/gsign', '-p', args.sign_prog, '--signer', args.signer, '--release', args.version+'-'+tag_name, '--destination', '../sigs/', infile])
subprocess.check_call('mv build/out/monero-*.' + suffix + ' ../out/'+args.version, shell=True) subprocess.check_call('mv build/out/wownero-*.' + suffix + ' ../out/'+args.version, shell=True)
print('Moving var/install.log to var/install-' + tag_name + '.log') print('Moving var/install.log to var/install-' + tag_name + '.log')
subprocess.check_call('mv var/install.log var/install-' + tag_name + '.log', shell=True) subprocess.check_call('mv var/install.log var/install-' + tag_name + '.log', shell=True)
print('Moving var/build.log to var/build-' + tag_name + '.log') print('Moving var/build.log to var/build-' + tag_name + '.log')
@ -93,7 +93,7 @@ def build():
os.chdir('builder') os.chdir('builder')
os.makedirs('inputs', exist_ok=True) os.makedirs('inputs', exist_ok=True)
subprocess.check_call(['make', '-C', 'inputs/monero/contrib/depends', 'download', 'SOURCES_PATH=' + os.getcwd() + '/cache/common']) subprocess.check_call(['make', '-C', 'inputs/wownero/contrib/depends', 'download', 'SOURCES_PATH=' + os.getcwd() + '/cache/common'])
rebuild() rebuild()
@ -104,7 +104,7 @@ def verify():
for i, v in platforms: for i, v in platforms:
print('\nVerifying v'+args.version+' '+v[0]+'\n') print('\nVerifying v'+args.version+' '+v[0]+'\n')
subprocess.check_call(['bin/gverify', '-v', '-d', '../sigs/', '-r', args.version+'-'+v[1], 'inputs/monero/contrib/gitian/gitian-'+v[1]+'.yml']) subprocess.check_call(['bin/gverify', '-v', '-d', '../sigs/', '-r', args.version+'-'+v[1], 'inputs/wownero/contrib/gitian/gitian-'+v[1]+'.yml'])
os.chdir(workdir) os.chdir(workdir)
def main(): def main():
@ -113,7 +113,7 @@ def main():
parser = argparse.ArgumentParser(description='Script for running full Gitian builds.', usage='%(prog)s [options] signer version') parser = argparse.ArgumentParser(description='Script for running full Gitian builds.', usage='%(prog)s [options] signer version')
parser.add_argument('-c', '--commit', action='store_true', dest='commit', help='Indicate that the version argument is for a commit or branch') parser.add_argument('-c', '--commit', action='store_true', dest='commit', help='Indicate that the version argument is for a commit or branch')
parser.add_argument('-p', '--pull', action='store_true', dest='pull', help='Indicate that the version argument is the number of a github repository pull request') parser.add_argument('-p', '--pull', action='store_true', dest='pull', help='Indicate that the version argument is the number of a github repository pull request')
parser.add_argument('-u', '--url', dest='url', default='https://github.com/monero-project/monero', help='Specify the URL of the repository. Default is %(default)s') parser.add_argument('-u', '--url', dest='url', default='https://git.wownero.com/wownero/wownero', help='Specify the URL of the repository. Default is %(default)s')
parser.add_argument('-v', '--verify', action='store_true', dest='verify', help='Verify the Gitian build') parser.add_argument('-v', '--verify', action='store_true', dest='verify', help='Verify the Gitian build')
parser.add_argument('-b', '--build', action='store_true', dest='build', help='Do a Gitian build') parser.add_argument('-b', '--build', action='store_true', dest='build', help='Do a Gitian build')
parser.add_argument('-B', '--buildsign', action='store_true', dest='buildsign', help='Build both signed and unsigned binaries') parser.add_argument('-B', '--buildsign', action='store_true', dest='buildsign', help='Build both signed and unsigned binaries')
@ -178,8 +178,8 @@ def main():
if args.setup: if args.setup:
setup() setup()
os.makedirs('builder/inputs/monero', exist_ok=True) os.makedirs('builder/inputs/wownero', exist_ok=True)
os.chdir('builder/inputs/monero') os.chdir('builder/inputs/wownero')
if args.pull: if args.pull:
subprocess.check_call(['git', 'fetch', args.url, 'refs/pull/'+args.version+'/merge']) subprocess.check_call(['git', 'fetch', args.url, 'refs/pull/'+args.version+'/merge'])
args.commit = subprocess.check_output(['git', 'show', '-s', '--format=%H', 'FETCH_HEAD'], universal_newlines=True).strip() args.commit = subprocess.check_output(['git', 'show', '-s', '--format=%H', 'FETCH_HEAD'], universal_newlines=True).strip()

@ -1,5 +1,5 @@
--- ---
name: "monero-freebsd-0.18" name: "wownero-freebsd-0.11"
enable_cache: true enable_cache: true
suites: suites:
- "bionic" - "bionic"
@ -26,8 +26,8 @@ packages:
- "python" - "python"
- "cmake" - "cmake"
remotes: remotes:
- "url": "https://github.com/monero-project/monero.git" - "url": "https://git.wownero.com/wownero/wownero.git"
"dir": "monero" "dir": "wownero"
files: [] files: []
script: | script: |
@ -87,7 +87,7 @@ script: |
export SOURCE_DATE_EPOCH=`date -d 2000-01-01T12:00:00 +%s` export SOURCE_DATE_EPOCH=`date -d 2000-01-01T12:00:00 +%s`
git config --global core.abbrev 9 git config --global core.abbrev 9
cd monero cd wownero
# Set the version string that gets added to the tar archive name # Set the version string that gets added to the tar archive name
version="`git describe`" version="`git describe`"
if [[ $version == *"-"*"-"* ]]; then if [[ $version == *"-"*"-"* ]]; then
@ -117,9 +117,9 @@ script: |
cmake .. -DCMAKE_TOOLCHAIN_FILE=${BASEPREFIX}/${i}/share/toolchain.cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_SKIP_RPATH=ON cmake .. -DCMAKE_TOOLCHAIN_FILE=${BASEPREFIX}/${i}/share/toolchain.cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_SKIP_RPATH=ON
make ${MAKEOPTS} make ${MAKEOPTS}
chmod 755 bin/* chmod 755 bin/*
cp ../LICENSE ../README.md ../docs/ANONYMITY_NETWORKS.md bin cp ../utils/conf/wow.conf bin
chmod 644 bin/LICENSE bin/*.md chmod 644 bin/wow.conf
DISTNAME=monero-${i}-${version} DISTNAME=wownero-${i}-${version}
mv bin ${DISTNAME} mv bin ${DISTNAME}
find ${DISTNAME}/ | sort | tar --no-recursion --owner=0 --group=0 -c -T - | bzip2 -9 > ${OUTDIR}/${DISTNAME}.tar.bz2 find ${DISTNAME}/ | sort | tar --no-recursion --owner=0 --group=0 -c -T - | bzip2 -9 > ${OUTDIR}/${DISTNAME}.tar.bz2
cd .. cd ..

@ -1,5 +1,5 @@
--- ---
name: "monero-linux-0.18" name: "wownero-linux-0.11"
enable_cache: true enable_cache: true
suites: suites:
- "bionic" - "bionic"
@ -21,6 +21,7 @@ packages:
- "g++-7-arm-linux-gnueabihf" - "g++-7-arm-linux-gnueabihf"
- "gcc-arm-linux-gnueabihf" - "gcc-arm-linux-gnueabihf"
- "g++-arm-linux-gnueabihf" - "g++-arm-linux-gnueabihf"
- "g++-riscv64-linux-gnu"
- "g++-7-multilib" - "g++-7-multilib"
- "gcc-7-multilib" - "gcc-7-multilib"
- "binutils-arm-linux-gnueabihf" - "binutils-arm-linux-gnueabihf"
@ -37,13 +38,13 @@ packages:
- "python" - "python"
- "cmake" - "cmake"
remotes: remotes:
- "url": "https://github.com/monero-project/monero.git" - "url": "https://git.wownero.com/wownero/wownero.git"
"dir": "monero" "dir": "wownero"
files: [] files: []
script: | script: |
WRAP_DIR=$HOME/wrapped WRAP_DIR=$HOME/wrapped
HOSTS="x86_64-linux-gnu arm-linux-gnueabihf aarch64-linux-gnu i686-linux-gnu" HOSTS="x86_64-linux-gnu arm-linux-gnueabihf aarch64-linux-gnu i686-linux-gnu riscv64-linux-gnu"
FAKETIME_HOST_PROGS="" FAKETIME_HOST_PROGS=""
FAKETIME_PROGS="date" FAKETIME_PROGS="date"
HOST_CFLAGS="-O2 -g" HOST_CFLAGS="-O2 -g"
@ -115,7 +116,7 @@ script: |
export SOURCE_DATE_EPOCH=`date -d 2000-01-01T12:00:00 +%s` export SOURCE_DATE_EPOCH=`date -d 2000-01-01T12:00:00 +%s`
git config --global core.abbrev 9 git config --global core.abbrev 9
cd monero cd wownero
# Set the version string that gets added to the tar archive name # Set the version string that gets added to the tar archive name
version="`git describe`" version="`git describe`"
if [[ $version == *"-"*"-"* ]]; then if [[ $version == *"-"*"-"* ]]; then
@ -159,12 +160,18 @@ script: |
fi fi
export C_INCLUDE_PATH="$EXTRA_INCLUDES" export C_INCLUDE_PATH="$EXTRA_INCLUDES"
export CPLUS_INCLUDE_PATH="$EXTRA_INCLUDES" export CPLUS_INCLUDE_PATH="$EXTRA_INCLUDES"
cmake .. -DCMAKE_TOOLCHAIN_FILE=${BASEPREFIX}/${i}/share/toolchain.cmake -DBACKCOMPAT=ON -DCMAKE_SKIP_RPATH=ON # glibc only added riscv support in 2.27, disable backwards compatibility
if [ "$i" == "riscv64-linux-gnu" ]; then
BACKCOMPAT_OPTION=OFF
else
BACKCOMPAT_OPTION=ON
fi
cmake .. -DCMAKE_TOOLCHAIN_FILE=${BASEPREFIX}/${i}/share/toolchain.cmake -DBACKCOMPAT=${BACKCOMPAT_OPTION} -DCMAKE_SKIP_RPATH=ON
make ${MAKEOPTS} make ${MAKEOPTS}
chmod 755 bin/* chmod 755 bin/*
cp ../LICENSE ../README.md ../docs/ANONYMITY_NETWORKS.md bin cp ../utils/conf/wow.conf bin
chmod 644 bin/LICENSE bin/*.md chmod 644 bin/wow.conf
DISTNAME=monero-${i}-${version} DISTNAME=wownero-${i}-${version}
mv bin ${DISTNAME} mv bin ${DISTNAME}
find ${DISTNAME}/ | sort | tar --no-recursion --owner=0 --group=0 -c -T - | bzip2 -9 > ${OUTDIR}/${DISTNAME}.tar.bz2 find ${DISTNAME}/ | sort | tar --no-recursion --owner=0 --group=0 -c -T - | bzip2 -9 > ${OUTDIR}/${DISTNAME}.tar.bz2
cd .. cd ..

@ -1,5 +1,5 @@
--- ---
name: "monero-osx-0.18" name: "wownero-osx-0.11"
enable_cache: true enable_cache: true
suites: suites:
- "bionic" - "bionic"
@ -24,8 +24,8 @@ packages:
- "python-dev" - "python-dev"
- "python-setuptools" - "python-setuptools"
remotes: remotes:
- "url": "https://github.com/monero-project/monero.git" - "url": "https://git.wownero.com/wownero/wownero.git"
"dir": "monero" "dir": "wownero"
files: [] files: []
script: | script: |
WRAP_DIR=$HOME/wrapped WRAP_DIR=$HOME/wrapped
@ -77,7 +77,7 @@ script: |
export PATH=${WRAP_DIR}:${PATH} export PATH=${WRAP_DIR}:${PATH}
git config --global core.abbrev 9 git config --global core.abbrev 9
cd monero cd wownero
# Set the version string that gets added to the tar archive name # Set the version string that gets added to the tar archive name
version="`git describe`" version="`git describe`"
if [[ $version == *"-"*"-"* ]]; then if [[ $version == *"-"*"-"* ]]; then
@ -108,9 +108,9 @@ script: |
cmake .. -DCMAKE_TOOLCHAIN_FILE=${BASEPREFIX}/${i}/share/toolchain.cmake cmake .. -DCMAKE_TOOLCHAIN_FILE=${BASEPREFIX}/${i}/share/toolchain.cmake
make ${MAKEOPTS} make ${MAKEOPTS}
chmod 755 bin/* chmod 755 bin/*
cp ../LICENSE ../README.md ../docs/ANONYMITY_NETWORKS.md bin cp ../utils/conf/wow.conf bin
chmod 644 bin/LICENSE bin/*.md chmod 644 bin/wow.conf
DISTNAME=monero-${i}-${version} DISTNAME=wownero-${i}-${version}
mv bin ${DISTNAME} mv bin ${DISTNAME}
find ${DISTNAME}/ | sort | tar --no-recursion --owner=0 --group=0 -c -T - | bzip2 -9 > ${OUTDIR}/${DISTNAME}.tar.bz2 find ${DISTNAME}/ | sort | tar --no-recursion --owner=0 --group=0 -c -T - | bzip2 -9 > ${OUTDIR}/${DISTNAME}.tar.bz2
cd .. cd ..

@ -1,5 +1,5 @@
--- ---
name: "monero-win-0.18" name: "wownero-win-0.11"
enable_cache: true enable_cache: true
suites: suites:
- "bionic" - "bionic"
@ -35,8 +35,8 @@ alternatives:
package: "x86_64-w64-mingw32-gcc" package: "x86_64-w64-mingw32-gcc"
path: "/usr/bin/x86_64-w64-mingw32-gcc-posix" path: "/usr/bin/x86_64-w64-mingw32-gcc-posix"
remotes: remotes:
- "url": "https://github.com/monero-project/monero.git" - "url": "https://git.wownero.com/wownero/wownero.git"
"dir": "monero" "dir": "wownero"
files: [] files: []
script: | script: |
WRAP_DIR=$HOME/wrapped WRAP_DIR=$HOME/wrapped
@ -91,7 +91,7 @@ script: |
export SOURCE_DATE_EPOCH=`date -d 2000-01-01T12:00:00 +%s` export SOURCE_DATE_EPOCH=`date -d 2000-01-01T12:00:00 +%s`
git config --global core.abbrev 9 git config --global core.abbrev 9
cd monero cd wownero
# Set the version string that gets added to the tar archive name # Set the version string that gets added to the tar archive name
version="`git describe`" version="`git describe`"
if [[ $version == *"-"*"-"* ]]; then if [[ $version == *"-"*"-"* ]]; then
@ -127,8 +127,8 @@ script: |
mkdir build && cd build mkdir build && cd build
cmake .. -DCMAKE_TOOLCHAIN_FILE=${BASEPREFIX}/${i}/share/toolchain.cmake cmake .. -DCMAKE_TOOLCHAIN_FILE=${BASEPREFIX}/${i}/share/toolchain.cmake
make ${MAKEOPTS} make ${MAKEOPTS}
cp ../LICENSE ../README.md ../docs/ANONYMITY_NETWORKS.md bin cp ../utils/conf/wow.conf bin
DISTNAME=monero-${i}-${version} DISTNAME=wownero-${i}-${version}
mv bin ${DISTNAME} mv bin ${DISTNAME}
find ${DISTNAME}/ | sort | zip -X@ ${OUTDIR}/${DISTNAME}.zip find ${DISTNAME}/ | sort | zip -X@ ${OUTDIR}/${DISTNAME}.zip
cd .. && rm -rf build cd .. && rm -rf build

@ -71,13 +71,13 @@ type, and max connections:
``` ```
--anonymous-inbound rveahdfho7wo4b2m.onion:28083,127.0.0.1:28083,25 --anonymous-inbound rveahdfho7wo4b2m.onion:28083,127.0.0.1:28083,25
--anonymous-inbound cmeua5767mz2q5jsaelk2rxhf67agrwuetaso5dzbenyzwlbkg2q.b32.i2p:5000,127.0.0.1:30000 --anonymous-inbound cmeua5767mz2q5jsaelk2rxhf67agrwuetaso5dzbenyzwlbkg2q.b32.i2p,127.0.0.1:30000
``` ```
which tells `monerod` that a max of 25 inbound Tor connections are being which tells `monerod` that a max of 25 inbound Tor connections are being
received at address "rveahdfho7wo4b2m.onion:28083" and forwarded to `monerod` received at address "rveahdfho7wo4b2m.onion:28083" and forwarded to `monerod`
localhost port 28083, and a default max I2P connections are being received at localhost port 28083, and a default max I2P connections are being received at
address "cmeua5767mz2q5jsaelk2rxhf67agrwuetaso5dzbenyzwlbkg2q.b32.i2p:5000" and address "cmeua5767mz2q5jsaelk2rxhf67agrwuetaso5dzbenyzwlbkg2q.b32.i2p" and
forwarded to `monerod` localhost port 30000. forwarded to `monerod` localhost port 30000.
These addresses will be shared with outgoing peers, over the same network type, These addresses will be shared with outgoing peers, over the same network type,
otherwise the peer will not be notified of the peer address by the proxy. otherwise the peer will not be notified of the peer address by the proxy.

@ -69,4 +69,4 @@ endif()
add_subdirectory(db_drivers) add_subdirectory(db_drivers)
add_subdirectory(easylogging++) add_subdirectory(easylogging++)
add_subdirectory(qrcodegen) add_subdirectory(qrcodegen)
add_subdirectory(randomx EXCLUDE_FROM_ALL) add_subdirectory(randomwow EXCLUDE_FROM_ALL)

@ -149,6 +149,11 @@ static el::Color colorFromLevel(el::Level level)
static void setConsoleColor(el::Color color, bool bright) static void setConsoleColor(el::Color color, bool bright)
{ {
static const char *no_color_var = getenv("NO_COLOR");
static const bool no_color = no_color_var && *no_color_var; // apparently, NO_COLOR=0 means no color too (as per no-color.org)
if (no_color)
return;
#if ELPP_OS_WINDOWS #if ELPP_OS_WINDOWS
HANDLE h_stdout = GetStdHandle(STD_OUTPUT_HANDLE); HANDLE h_stdout = GetStdHandle(STD_OUTPUT_HANDLE);
switch (color) switch (color)

@ -0,0 +1 @@
Subproject commit 27b099b6dd6fef6e17f58c6dfe00009e9c5df587

1
external/randomx vendored

@ -1 +0,0 @@
Subproject commit 261d58c77fc5547c0aa7fdfeb58421ba7e0e6e1c

@ -106,15 +106,15 @@ endif()
add_subdirectory(cryptonote_protocol) add_subdirectory(cryptonote_protocol)
if(NOT IOS) if(NOT IOS)
add_subdirectory(simplewallet) add_subdirectory(simplewallet)
add_subdirectory(gen_multisig)
add_subdirectory(gen_ssl_cert)
add_subdirectory(daemonizer) add_subdirectory(daemonizer)
add_subdirectory(daemon) add_subdirectory(daemon)
add_subdirectory(blockchain_utilities)
endif() endif()
if(BUILD_DEBUG_UTILITIES) if(BUILD_DEBUG_UTILITIES)
add_subdirectory(debug_utilities) add_subdirectory(debug_utilities)
add_subdirectory(blockchain_utilities)
add_subdirectory(gen_multisig)
add_subdirectory(gen_ssl_cert)
endif() endif()
if(PER_BLOCK_CHECKPOINT) if(PER_BLOCK_CHECKPOINT)

@ -241,8 +241,15 @@ void BlockchainDB::add_transaction(const crypto::hash& blk_hash, const std::pair
} }
else else
{ {
rct::key commitment;
if (tx.version > 1)
{
commitment = tx.rct_signatures.outPk[i].mask;
if (rct::is_rct_bulletproof_plus(tx.rct_signatures.type))
commitment = rct::scalarmult8(commitment);
}
amount_output_indices[i] = add_output(tx_hash, tx.vout[i], i, tx.unlock_time, amount_output_indices[i] = add_output(tx_hash, tx.vout[i], i, tx.unlock_time,
tx.version > 1 ? &tx.rct_signatures.outPk[i].mask : NULL); tx.version > 1 ? &commitment : NULL);
} }
} }
add_tx_amount_output_indices(tx_id, amount_output_indices); add_tx_amount_output_indices(tx_id, amount_output_indices);
@ -446,582 +453,7 @@ void BlockchainDB::fixup()
LOG_PRINT_L1("Database is opened read only - skipping fixup check"); LOG_PRINT_L1("Database is opened read only - skipping fixup check");
return; return;
} }
// There was a bug that would cause key images for transactions without
// any outputs to not be added to the spent key image set. There are two
// instances of such transactions, in blocks 202612 and 685498.
// The key images below are those from the inputs in those transactions.
// On testnet, there are no such transactions
// See commit 533acc30eda7792c802ea8b6417917fa99b8bc2b for the fix
static const char * const mainnet_genesis_hex = "418015bb9ae982a1975da7d79277c2705727a56894ba0fb246adaabb1f4632e3";
crypto::hash mainnet_genesis_hash;
epee::string_tools::hex_to_pod(mainnet_genesis_hex, mainnet_genesis_hash );
set_batch_transactions(true); set_batch_transactions(true);
batch_start();
if (get_block_hash_from_height(0) == mainnet_genesis_hash)
{
// block 202612 (511 key images in 511 transactions)
static const char * const key_images_202612[] =
{
"51fc647fb27439fbb3672197d2068e4110391edf80d822f58607bd5757cba7f3",
"d8cf1c1bd41f13c4553186e130e6e2c1cd80135ddb418f350088926997a95ca9",
"95d2556c8acd1457dce7bfd9c83b1d82b821a55a9c9588b04b7b5cf562a65949",
"4b5d987fee1bb563a162d23e41741ad73560c003e26a09b6655f09496538daac",
"1d25ea86323d1578579d3894a54b99ea1c3e2dca547c6726c44aef67db958b02",
"92e46fb70be5d9df39ca83c4fc6ae26c594118314bb75502a9c9752a781d0b33",
"924d0cb9060d429be7e59d164a0f80a4dabc3607d44401b26fb93e7182ab435d",
"f63e4a23fec860fd4c3734623891330ac1ff5af251e83a0e6247287818b8a72f",
"5b14c5ef13738d015619b61dacefc2ade3660d25b35ef96330a8f4e2afc26526",
"d5016b012a2fb6ca23fd56ece544d847962264b4aee15efe1465805fd824a8fb",
"0a7f3da1d9dd341cd96829e484b07163099763ac7bd60603b7ee14f7dbcb278d",
"d716c03d7447d2b693f6f61b6ad36bd57344033fc1a11feaf60d569f40014530",
"23154a812e99ce226f6a87087e0812f419aed51289f1c0c359b0b61303b53a36",
"03940341e1a99d5b0c68eacfdf5a20df90d7d0a3d6089d39709cdd964490755c",
"ef09648814cfe071f5d8e9cfde57247ad09409265c4b6c84697bbb046809bd7e",
"8843ec52b0496ca4e895813cfe00bb18ea777d3618e9bd2e200287e888e2f5c7",
"8558bf39baf3df62b5d33cdf97163a365e6c44f4d6deef920730b4982b66449f",
"504d9380ce581de0af97d5800d5ca9e61d78df368907151ab1e567eb6445332a",
"673797763593c23b3ee07b43bd8760365e2c251a8a60a275528ff34a477110cc",
"25178c95e4d402c58d79c160d2c52dd3c45db2c78e6aaa8d24d35c64f19d4957",
"407c3a05dcc8bdcb0446b5d562cf05b4536fc7337344765215130d5f1e7ee906",
"4e7fa771a5455d8ee8295f01181a360cdc6467cc185c2834c7daf9fbf85b6f1d",
"6beb64cb024f9c5c988f942177fc9c1ec5ecfa85b7db0f13a17f9f98e8e46fe7",
"6406bfc4e486e64c889ea15577d66e5835c65c6a39ec081af8ac5acdc153b4b5",
"1b1da638709f9f85898af70ffaa5b88d5a4c9f2663ca92113c400ab25caf553c",
"da49407a9e1ed27abd28076a647177157c42517e2542e9b6a4921fdadf4e8742",
"3c3fdba2a792fddaeb033605163991a09933e8f05c6c934d718e50a613b64d69",
"82c60429171173739fa67c4807cab359620299e6ed2a9da80139b5b1e23c5456",
"0a19e5767e1381ac16f57cfa5aabd8463551d19f069f7f3465c11a8583253f3e",
"d0fae6ffdd4818399eae6224978f170f696150eaf699f2f218abc00c68530f96",
"0937889aeb3af5c64608d9a9f88229a068e53417448f00f9aa5e28c570cca8f8",
"d6072d269753020912524961ce8c6930cf35abe5c4b2bdc7fd678338d20a68fb",
"0e8bc9b06fcc842bdaa7df029bfd1f252d5defc014d58a006c10ab678ecf543f",
"9d42f90520f02c9258be53b123d69ddbce5f33f92a903d3fb4cf3358ff0e07b5",
"1cc05416b12cbe719617158773c3e6173435fc64e1ee44310dc696baecaeaa95",
"266b15222913c11ef6403ee15dc42c8c0e16bc5fa2f49110447802236e045797",
"791b123af3b71ac9497a010610f72207ff8ec642969b5cf0d2891b21e7eee562",
"946d4d7b084dc32495f22b35fc30394144c8e0ba04f3ad6e2c2bfb0173a2266d",
"2c015cb990c1583228d08b2d5de9227b950c3f57364fc1033bca5c0fbfd08c58",
"13fdc41862fd85507f579c69accb9cc6a40f5971bfa41e3caff598a3dcffd2fc",
"64b06d9874a83917c583c9439d1c736083377d67fda2961b623f7124663134c3",
"2fa49cd19e0aa02989991a4c3760f44be800fe8fb4d58b23aca382e10dc0d2d6",
"377628f265f799772e9fb6065be8b6eee200c329f729fe36c25ee179e4d20df9",
"ba94fa79134ce383b6a98b04dc6ad3d1b950e410d50a292bc770f9685e59fe91",
"875c924329f0733e31fe8d8aed70dc1906335b8a9984932b6368ea24edb39765",
"f31f4abb3f5ee42a5aae86d70b3bd9a9c1934933641893864dd333f89719d608",
"2bcd629e125514a780f568d3c2e8b12a2e7fbbee06e652bbeed3e7825508e31c",
"918b43581163ca1963de21bb9ac401756e75c3f00ac8dcfafc139f1ad5d7d998",
"5730dd57fa52749a0d6502b11c9d802ac495875542431310c674a65655b7c2a3",
"03f84b990683e569e2f6143bb963a2a8de411e7c4b7923117b94c7afcb4b43ea",
"b298c8510d35bd2be0ff0753ad7d98d480f4c6490bb67fb93cd4632ea726e8a7",
"0a771afbf9be104c01b89eaeb57073297d35ac8fbbcc0816820fdb9a29d26625",
"713d90d6ca1be1a4e05a5f8441dc528c699caa09eda49c09072f5f8291354c2e",
"988827f45c19330d9404309f63d536a447803cca7cb182ef005b074def09ab7d",
"9dcaa105b4def895f3faee704c250bdc924316f153cb972f3fb565beec0b7942",
"1c06c30afe65b59e9e22d6bb454e4209a03efe53cdbf27b3945d5d75b1b90427",
"49e08c13d1da209ec1aea7b7fbe0daa648e30febeb2aa5ffbaaabdd71a278ac2",
"e1c2e49ab7b829854c46a64772ded35459908e0f563edbcf5c612913b7767046",
"e08bb7d133490ca85a6325d46807170cd07618b6a5f6e1d069e44890cc366fab",
"5c73ca0691cde2f35b7933d6db33f0b642ec70d0bd3f2b0ebbd97754ca67e248",
"6404399151872a521dae767311712225dba65d810ba2feba209204221b5d772d",
"4a0c3aa6cef36f44edf08ad8fb1533d7e1186e317da8a3afb3d81af072043233",
"104b3e1af37cf10b663a7ec8452ea882082018c4d5be4cd49e7f532e2fea64e5",
"e723a46bf9684b4476c3005eb5c26511c58b7eb3c708ddf7470ee30a40834b32",
"18e6f0fa3aa779a73ceefabea27bff3202003fd2c558ec5f5d07920528947d57",
"c97e73eb593ff39e63307220796cc64974c0c8adac860a2559ab47c49bc0c860",
"13c363a962955b00db6d5a68b8307cd900ae9202d9b2deb357b8d433545244ac",
"76a488865151fab977d3639bac6cba4ba9b52aa17d28ac3580775ed0bff393e4",
"a14de587c9f4cd50bb470ecffd10026de97b9b5e327168a0a8906891d39d4319",
"b1d38ee1c4ca8ae2754a719706e6f71865e8c512310061b8d26438fedf78707e",
"772bb8a3f74be96fa84be5fa8f9a8ef355e2df54869c2e8ae6ad2bf54ed5057e",
"3083a7011da36be63e3f7cacd70ab52e364dd58783302f1cb07535a66b5735f5",
"2b1d892e3002aa3201deb4ffe28c0c43b75b8f30c96b5d43f6d5829049ecbd94",
"cb738aabe44c6fb17ade284bf27db0169e309bf8cf9c91c4e4e62856619a4c64",
"1707e04b792f4953f460f217b9bb94c84cef60736a749fb01277cfe0eaaa48c7",
"ab8b6bac9b8a4f00b78acb4bd50ed2758e0fa100964b6f298d2a943eb2af2b30",
"dd317193fef72490f3be01293b29e9c2f94eda10824a76ca74bf39dd7cb40ab2",
"4fb3d995b087af7517fcb79e71f43bac0c4fbda64d89417a40ca4a708f2e8bc1",
"549ba38c31bf926b2cb7e8f7f15d15df6388dce477a3aff0245caa44606849fc",
"7585c14ab9abbffb89d0fa9f00c78ecae9f7c9062e5d4f1fae8453b3951fc60b",
"953f855323f72461b7167e3df0f4fd746a06f5a7f98aa42acdce2eef822a0b2f",
"0931932d57dde94dcfb017179a5a0954b7d671422149738260a365ca44f50eb8",
"a3d179d16a4a275a3bb0f260cee9284db243abad637a9dbe92d02940f1c7ee8c",
"959843f1e76ff0785dafe312c2ea66380fdc32b9d6180920f05f874c74599a80",
"fbc36b3e1718fe6c338968b04caa01a7adb315d206abc63e56768d69e008a65d",
"f054de7eac5e2ea48072e7fb4db93594c5f5d2dfa0afe8266042b6adc80dfdca",
"39dfc68dc6ba8c457b2995562c867cef2f2cf994e8d6776a6b20869e25053f70",
"19ad7ca7629758c22ac83643605c8a32a6665bae8e35dbc9b4ad90343756ebb3",
"e89e80ea5c64cf7840f614f26e35a12c9c3091fa873e63b298835d9eda31a9ea",
"572c1b9a83c947f62331b83009cc2ec9e62eab7260b49929388e6500c45cd917",
"df0b21f679e6c0bf97f7b874e9f07c93c3467b092f3d9e1484e5646fda6eca5f",
"8f3b7c0f4b403af62fe83d3cfac3f1e2572af8afa4cea3f3e2e04291efe84cf6",
"aae8b8db243009d021d8c9897d52ee8125a17212f0a8b85f681ad8950ae45f0e",
"3d45a4957d27447dea83d9ae2ef392a3a86619bfcf8dda2db405a7b304997797",
"a5b0a619a8e3030b691bdba1ed951cd54e4bc2063602eae26d9791fb18e60301",
"14650df217dd64a2905cd058114e761502dff37d40e80789200bc53af29b265f",
"fd6a245ab5e4e6e18d7ba9b37478ce38248f0ab864e5511d2208ae3d25017e5f",
"fbe0be6dd42a11feb5db5ae56fcbbac41041ab04a35f1df075580e960c8eeab0",
"72f3f1213d9bec92ba9705b447d99cd0a6a446e37a3c1c50bb8ece1090bfe56e",
"20df836554e1534f62b2a6df9ce58e11c1b9b4746ce8ee3c462300a8c01f5e76",
"5c3d2a81b7331c86420ad32b6e9a212b73b1c3413724a0f91bf073eba18e2f1f",
"63264ddfb29cd36fc18f3ee6614c4101ba7229bc5ac375f912590d3f0df982f4",
"5ec4eb637761c1c9dbc6aa6649d4410508ef8d25d61ad6caa40c6ee3236d5515",
"270c70940536017915e1cdbc003de7279ec1c94cba1ef6130f4236f7e306e4f0",
"c1d1d57a7c03f6ddeeab5230a4910db8355e2143f473dea6e1d57c2f8d882b76",
"218c030a7fdc9917e9f87e2921e258d34d7740a68b5bee48a392b8a2acf1f347",
"ac47861c01c89ea64abee14cf6e1f317859ed56b69ae66377dc63e6575b7b1eb",
"23bf549c8a03f9870983c8098e974308ec362354b0dcf636c242a88f24fc2718",
"a3ce8b817e5212c851c6b95e693849a396c79b0d04b2a554de9b78933fbea2b7",
"7310120c1cc1961b0d3fce13743c8a7075ae426fe6cccaf83600f24cee106236",
"8fa0630f193777dcc4f5eccd1ad9ceacf80acdf65e52e4e01bf3a2b2fdd0dac6",
"4a5f5c87f67d573d0673f01abaebc26eaa62e6d04627588549cc9e6c142dc994",
"78971cccacc645116f9d380c167f955d54b386a22af112233f7de004fc0c8316",
"badc67216868e1de1bbe044bf0e6070e6ee0353d05c13fa0c43b1897db5219a2",
"c45b2a168bc51cbb615a79f97432cc4bb6b104da9cdc1fc640c930657452f71b",
"c17eda13541d14554c5db542155b08b6bf9cb403d425745b662ebc2b2b9b3a3b",
"313210cd9d2efc1603f07859bae7bd5fb5914f4a631b943f2f6ff5927a4e681a",
"6ee94ec8af4e6828f9b46c590ea55da640ef50e810a247d3e8cdf4b91c42d2c2",
"505b7a4d9f1ba6577aa2a941843f86c205b23b1ea21035925e587022e2f0aeed",
"98e6a7cd687e8192e300a8202999ec31ad57bc34f656f2ae90d148607ff6d29f",
"1be5db002c0a446cc2c1da363e5d08ae045cd8f5e76c8cccd65d5166393c0bdf",
"17c02ac6d390c5c735e1e873c40294220e89071fca08a5da396a131fa1ba8670",
"2540507c39ae6fdcd90de826077f0ca390da126166a25c15c048a60606a27367",
"5ab9328e525c7a017ef4f591d995ad4595d74cbf8ff4112af33b08c70661a304",
"9c105587a96c51d81422f64e46016564d22329760648c95dcac7218f3733f915",
"525afb1b94a75f1edc2b55c700071e14a2166acda003370047c30dba8ea80278",
"745d4a5d9f95ca4efa6261b6bcd4ecacd504b5b901a2ce1353c522a5c0c15dcc",
"5a5a568cd87ba34252ba254e6a320e1a7f52f13e7451bb887efb34ff881785f2",
"1ec50a80198cd830b51f4f7a0222015a268d9b40f04e7f838c7b8dc7abf63b01",
"68836b662d79349cb42f5cef54e6a066157d398cc87d3b13f29fc04e5cf364a5",
"658db317f355a9cbd86f673775cac0c308fe14967428fd283a36e300a6a53b2f",
"677d79a8c467dd9db38f0ef45c2787dd368f701a6b47bf7a5f06112c38da643e",
"2baa455d4066f5d628f9ecd315cb57deca71069db5d0d112ae0aa18a84b6f0d7",
"5e7b0889f351560081360ac2b1429b48b2f7d886227f144e3b198e2f1fa56ed9",
"c3d317fbf26e15add8b4f8f93df9de9b22297b8e4945ebab9ee249d4f72f4e45",
"3c0b705a5c1e31abc7e46d8ff3c148a033f6875454cfb67f8d2a2b9a57a5ba7e",
"a0ab74663561af2adc2d38be3569fbe7aa2454346416ac96e5eb26b1e01b1e2f",
"53526cffdb74327670566c1dacacffb7d30a43a7f1862ff8bab87737bfa5edb6",
"24c5d36ab98d88f87b2c71afb4ea8562e05c7aa0b50f3bc0f9ed50a4cd52989b",
"c3ce4de5f94dff65d11e33a865855a4404259cf45263914c884f79db4f35169d",
"f1009b6dcf30030cff872d636fb96ed233eb6ecb8ffed003c7da64e4f5a02f4c",
"e3729f58614d3b42450d1599d863983ab7e3e5c29fb57aad7958c8923a2627c4",
"31cf4792f7b5ce01b217ec80184edd2a7c49c0b21701f5494ee2c9bac67c28ca",
"b42a5c9c92a656c5bb2b759ce160fdfd245243aeb1786338faea63b62e9a60ce",
"a1efc8d5d0855933d5ac8fe5960c7acacb92fcb09bfbc929e5002f168251e648",
"c4322c7f3682ec94b0dcb42f13b498c36cf575d505aacc8ec8bf67a6a2abf4c9",
"684ee5aa3c98357aeaddcc30c6620939b52aeef729e24b4a46ccafc44f24d831",
"36180f2ae11d105e0efbfbddb94e6b45b08609a383e4e1a8fa3b06d7a8051de9",
"96c2d183eacc87581a0b17b8d07878bc10d436728510715109a7565d9972f8b5",
"3068c9d04d561c7e29e3f621280b61a61885de0e9ec35a66a3116ca7a9e09627",
"2eb94b9673ad6f8f88288fddfceae4baaeccb37bed88a35611d826ba06a5363b",
"fc8cd5fae8b81121001f7767dcd5f185c0fdcc88cce1fbb184ddbcfad697ba54",
"51521da1ecedea6d588d774eb155d936b32a14913c2f11d989bcc5116e65bf41",
"3d23542e597a83dd6307700d79058b920f281c65f832333734d8a0adec510495",
"11d2e01913ff0d4bd21970d709d88e63289492c0bbad7bff99c0d36858a841ca",
"de674f1eee3068d2bc8c2f2897d8556e5deb872869652f7d3a4e5dbc6f1063c8",
"e722d7f728526110c0921791b417afde4af1e87ae48ccc01911786197843104b",
"aaba3a4e2a7d20ab76edfbcccefc27acfd509db3638582c28230e73ffd71d340",
"1385a7209dafb9622dd4274179832e40c7fae19445383c34ef79adb0e4de0c98",
"108408531fca288d74de4a2c596eab8569e355d9ab2f8380f4d24073a6b3fa95",
"294476a86fcd39351ae452cdb8af9584067ec4501ec6182d0062bb154559fed3",
"e64b175e0284c5cb69c8db46344ed43b5ced8abfe3cbf0c197103cfd116944cd",
"cdd73a0f1fa7c14ed2177ae2163035333718847e49dd5cca6775bd20fc7553ad",
"d423d2a374bc66a4587a5e3affa327ca75b8116051320759a3b88a868a7b80d4",
"f13ad1e5b1315557d5497b58516eb3b0759d909725ddd0eb8a0dee439c6c0a48",
"3a600b547a6061186a54e491344fd50cc7d4f0566a386a40aba6545254773728",
"37a6f3f221fe17cc04a65aa544d5135e8297ecaf0853ba784dffacb74feb481b",
"0ca42d67d0f84b28861d63e919e6ce5ad527447fdc53a03d8497a0241bee9376",
"c7dbda42459e6fadb92c416eaef3e04674fc57915a93f3be4e656634c9654075",
"0e34d728ae4fe347a5afecdf886fbd4d48a65c5d0dfab807da6ae95b6b2d7a3a",
"f1bc69257ed510db5b2ed370010b037f452a29c49e36337264b3011ce2516216",
"33f98f6b8a8e202463955998fba3b790199daa893e5471554826cfd9daa5c02f",
"f8a0a37a2c9ebd7022d7cded1ee0318fd363020070b4cdaea800e44dcc1300d2",
"6862714daedb908a4d86a3a3f1e65ec2c29ae61501b4ddcaf184243dd095d71b",
"555cd19a6d21941c1174129b8bbcc70edcf0d6874262ce9e1e542351990d523d",
"2cd6b44326828f23a2aa33699754bfa072c4883f39d53616f6a6b74149b664b6",
"127f45d2eacb565c21c1030fe8054fd0a3a75705bc368924712aa145d414fa47",
"19225e2dae6e1166f21cdab1290194470ded09df9b66f3faad3c1cc9ebcf340f",
"b7b3f53f0539b2b4837b8bb9dae0ccbd200c8d36126d9f50199d68a4293a46d3",
"6b6323be01f27d6d759d9670825e8ebb9c4cd8016351702328df91cef36cfec8",
"020c31cfdfc5b22b10235745b89b311d271cf82f2ba16d03fdf7a8bc8538694b",
"62573218530182b79e40d0113b7d281dace6da33bfcd0f9318558de5e5c76f08",
"37d928416b15982f5bb8be40c5b62fae0b664e412c25891f8860c4242927e610",
"b07ad11134a5c0542d2b418ef3863e8ea8477de68d9310681818ddd40825fdb0",
"4af77cb76bab845b56470c95ce7b8cd84ce49a095984c1f3eed67b0ee344316e",
"e3fdd4668d8726ba6adc401ac662c0cf6b5c1872082c488ed7da966d425fb1c0",
"3dec71c81c7e78e879abc8da8b30e2446edbe98eeb8df9dafe9201ebb4c6a834",
"7105467d9c5e855f1362fbddf820ed5e757997862efc9000317d3830a2f60ef3",
"2821df94b021d3e77e8d9c0f3972340210f5ea2c0935cbf125cfc578d4d6722f",
"114e5807accc337a22598bded30ebf3e0cfd75877e239f10cb043f829c315ab5",
"d658a1c0354628cd7312593ab25d5b9083de8f0def6e8425f188101d256cd136",
"4818d3be9b2a38fcc8c85d6c46f69b502943f79cf2462dfb0b6499e761bcc836",
"92b8c943cb017b5f2d39264640c069f1ecced1d3ce9b3fd755d6df2fddb99458",
"6edbd0fdf064fcbccd4a9e7a8ea520b87cb7faf867f7fe8a5f53625beb575119",
"bf3b49c477dafb06af65bf09851c0fbef9dbc3152a7268d31b55a8e7a9a95860",
"0e234dbadfda1393be2f068182615dbb83736f84f87710b5c7965bdce9f4a26a",
"df5ceae34429e47b92bbd5505ba27666552e0eb619997f359c55699c3252b1ff",
"08c1c7d940d699a91a83249bd578772e8958ffe23179e6150f07b96f1b47ce1e",
"6f919a429270da0022d70062537bdc1b21c43a8abc552d8e366647e5b719d310",
"63c66e5fd5d27f6fda87912ce46fa91a5e5b3634ed147fa2986330fc2696d3fa",
"bde070b75296bca3aa494e7f549cd2bd1ff003776712bc98a3164b139b2054ab",
"66694196dac5b60cf5e0ae05db8f3894fe04d65910686806551f471a0a0472e9",
"0d2e97524b7ce4cf30b54e61b2689df036d099c53d42e2977b1671834bac39e7",
"e081af76e923455f408127862be5c9baf7de6b19b952aa2a1da997d4dfe594c0",
"121bf6ae1596983b703d62fecf60ea7dd3c3909acf1e0911652e7dadb420ed12",
"a25e7b17464df71cd84ad08b17c5268520923bc33fe78c21b756f17353ea39a0",
"e985f078fb44dbfdf3f4f34388f0f233a4e413e02297ee9a7dcc3fcceacd44f9",
"b9184cf45e6e6b112cd863b1719de1bcab2137eb957e8028edca3a204a9ebb96",
"157d177d5e4bcce0040eb4bddb681eacf9e2942e1c542a57ce851b4742a9cc4f",
"0823e06635c9a1a69fd8833d1e48df98d711c1c47c06f27bb384932db1bbe9ee",
"8beeec1fd1bcdecba235b449cc49abca69b6486ed1c0861a2bfb6a43c970b86f",
"349f61a1cfc9112e537522858a0edae732a2f8434cf4780d3d2ec1e96f581cca",
"587cdf72b5914d364f7e214a70481cf1131ee4a09e6b43e52428d2e56b000c13",
"a6aa0c179316534c7b9ffb5f42a2af98d1d3a166bfb413199579f259c7b5e6df",
"f9f3bb1ba8da5899b79186008ecfbd416b49f3b86d94045b91e34a40e41d5cff",
"0cdda65a60b7b4d94e794c9397e01f69fb29309ce4fac83e7392dbba6bc497f9",
"8fa5fce5ad09d43af7218ea5724cff2c4849a59ff73caf3bbca466e3c8538ba8",
"8874ef46008753fcc0b77eb7a4a8560e35966bf5a12bcad4203ad2b4c1f8bfbe",
"a8ee9a3aa2d0c08a951439ffb0e6d10315fc4776997b275de1ec19663e88c2c2",
"9c184cbbff464ab4d5f6bfa78c39bf0880fb93b1574139306a97acb940d415c9",
"5493a38c255c91ca49b958ed417f6c57e5bc444779d8f536f290596a31bc63d3",
"3e1e82b96cc599d9fc55ae74330692ccbfb538a4cc923975fd8876efe4b81552",
"16aaaf820c24c2726e349b0e49bbab72ca6eef7b3a2835de88d0cececa4da684",
"7fa52ba349f7203c3dbc2249f9881101a3318d21869dd59f17abf953d234db65",
"713d8018bb9ba3ab55c3a110120b9d7593514111075ef05f0fdb233ff2ceddc8",
"56063afb495759a0942f1c33f28a4fb8320c6d376cb3c9513249453e45f24a04",
"f9a6bacd9e055749b45174ecf3c3db18b78f3474761948a68adf601f54e59660",
"7ddd7c6d41572f93fe07c0300c34e455b6d1f4372204933bf45035241c8b060c",
"f81021b893a36b201de71330a2ea050b59dbf7560c62fa9cbea9261ab47a0ba2",
"a01fbe4114c18fd534ae1621404d25c08e3b6775a2631ff40279bafd8c9304f4",
"350fad8ebc938c6eb508a1483f385f577794a002bc1229db70a1b0131d174b9d",
"570cb8bce87f532c5051d8c4c864012408e672a7d492669e660251fb1e066bec",
"8cb6efbb129c84eba26d894c4293b476a6e9a1fe969c6ad18b554d2a57885f36",
"f384a98467bf7f084ca31bea121a4ec76e530f523d3225c21ed25a18544a9916",
"da127ab58ce557c2c95c20d6a291c2e5d880fff09dc28927b7bdfec97b995d72",
"a4d95b4f74366ec920d0a0c5d81265688cc18733ffc444cac9b01ae2431568aa",
"5ae2a71470570733422468bb733d53c85b1c8a6e7e6df5c05941556bcf342d1a",
"65a2d161ff0e095d3afe37584dbbe649f1e9cd440755b5a3c5b2a252d5c0b8bc",
"25ef70a8e41bb422ed7996a41160294e33238d6af17a532232f0a50b123431a2",
"f1f0f76ee901664a65b97104296babb9c7422370e99bb677ae07c2ee420e7f40",
"c3c66dda180b0330e75c8139b9f315a8c6b937f55d87d7be42e172bbac60d71e",
"5881786695a9e58e19d79f790c7d9243a847c0269c5770bdd01f5149c2a62a88",
"f2f816d3c8ebc7df06ab68d39223181aacc7be04364d1d4e69a56c33949bb983",
"80a1c3b6b2778d4846ad9fe0bb2dd5afd99aa897f8231bfaac45fde43d602d9f",
"72ad67cb043aa5df0c3dcc2464953a66893259d81c9cc7778c12bca3447fbd58",
"ad72420a7963b8d4536d8eba00b4b989992247cd8c01660e242a8e71edaf0e19",
"999d603d1cf6068e3bb6abe1bca976fa0ab84c4660b29ea8973de8b5cf5fd283",
"e137a5910f02a764c3a3d8f1579ac0c7e3cc34e58933216868efe010332c1e6e",
"10e0fa2362f59317626ae989bd1f962c583339d8d74d76c3e585243d152b91e8",
"1951c652704962f5c6e33a4d4aadfee5d53ce2253644d1ed542da3e278524a07",
"c938bccb7ba6c0217d8ba35ed91502aee051c8ae5bff05e88aab3b322aec936f",
"4d6386c689785edd5beb55911a3a9fc8914838c8192184199589beef8b6ddf9f",
"26f6f45a6468bc4b1f085fd28d63c264ee17564f9e247fc03ee179a0b579dcda",
"235b7bb82b72c61acd5979ca5f2ca740aee805a780ba22e11aae5cd34f6ec760",
"c027ffb585a1e4844b4907490b621b08c7e40a5e6f93e97bd4bb1b615bba9908",
"aa77fc8053d139b998577319de29457b78b1cc8b35a5f3526c0621eaa42ce6e8",
"afd0af9a11c5ae2a7c4a4571ce39ad57d8df70ef146ed83ad8eaff97b2387fb8",
"a1f8fee9f1da9a2b306489d00edf754187b55e97f4fe6f249432fe6c7f44d6be",
"4f12e8a123465a862060efb656299e6bef732e5954b02194308817b243e84d32",
"6a1ca62f7d6952ad2eba1c64035260319baf03deabf856ca860744fc886b3d3a",
"c72dd1fe890d6e4c1f7325a4f224e85aef6cdca8bf9441d228efaf126e02ba63",
"2f6ddcea18d891ef4252e657989de68adcc43c2175d49c0c059c5e49b9dd5aed",
"24efac0f240ed183c30398ee40307623f52113598f66c5864c90fc62643a2aec",
"6ba3ebc935e7cf7fbb446e7f5c12b19c4455e6894412b0eedee4fc945e429e9a",
"3519d6e5bc9649f97d07a07ef5471a553ffce35c7619f4f63e91a2ba38cbb729",
"65e073df352fa9917e5c2475167e6c523b68c1406e1b6e81109e2d4cc87c740d",
"d73bf816c3648a7d53d34be938c454e515efb0c974d5a225f33635540b2db90d",
"bce167790fc86a273db011757d09e2d1148521ce242c2ded58f26cc49993aacb",
"2d4286ed4039916f29602e86f47ea4c5b05998c0198509ca7799fcadfb337e8d",
"9837c495b1af4f76b09177514a0f3e1dceb509c52b91712f3c7d29dc1b91d09b",
"5c848b8291f39759903ce77f151acf40f3ab5afa2d4a45af62b320371c29a697",
"b92df5016ee947ce6a21365d3361977f7f2f6c14025a983c44e13d3e8cc72152",
"71d2f57222a39b1a7ed2df5e6fb23a964439b5a8e7d49b49d87e5cd5354baa75",
"88b44d0198fb15b0c20a97f87e021c744606bfd35eae2874f35c447aa4ac3cd4",
"29bb4c2557714119cd684da2867e689e37e3ca9c912db83ab84746816f6092ab",
"b1836d98a288752675b133b9018fa1edf174f311921d01926c1e1a5900c21029",
"a00645e090c7d96f3155ffbcfc41e526a763b0f53a98151ac4a7d4a5b14066b6",
"78aab09919d17773b0d62799b37bd2e2970f72f5d1eb6472489c367b6135374f",
"eb6123aeb28608f1c97b2bf62ef69f977cd0658a0ab491deebb1e972caa938c5",
"8dd7ef1650b1b30cdf7814ae4d61a237eb0acc3ec3ce0f72b1c25780329c2d7d",
"b1998419be3172858b990eea84fe10bb24b76c219cde277cb4305955fc7e0b65",
"1b10560016c4bc506eef9056dedc2943a17179081e6eaf85b48d37dc20eac3cc",
"1fb1d9d4d408a6734234910f554d272739a0d6fa401918d79b57be62c3f23ba2",
"dec878f54ce36788289b61d32de0d9539032aba22cd15522752f729659c7cc5c",
"fdbfd0773f5a66637b093dabf812197940d1134619a7e60a931b19915b7dab0a",
"21bd2c9aae052a1c187947d2964f2be4afa7b30248409c41a75522e88a4e7977",
"59326adab03416ec1d36699c18e5e4fa13ca1f2212d48c23bfdecb0be7263616",
"bcf263d39457c0aef8ef42fd98f8131198ec4fb203155dd5bcd759e499a9ca5c",
"f1ad083bcd8c7630eef93336d8a971ae8ae37166a6a00ac39684420c5f9afef8",
"d82ee2ac41b36e3c1787a01835bf054070486dc20f6565efedbbc37cd3bf5fa5",
"eba91a0dcbd3986299b0a3e66c116f77bd3421829291fd769522f01da26f107b",
"11016558b7e8c6386c6a3e862691dcba47e33e257f0e7df38901ea7c0eba894c",
"04f02795e34a0030e5186c8e700da8a46b1aa6bc0abed6b35c9c1cd6a73776b9",
"2628dc8ad7fb731d59456b2755a99c6701467125fa69816c21bfccabc31edf6b",
"9b7ca249ee5b45cd264492f30df09f708a7d9caed7beb9a5c6292f22e4c31f85",
"5c42e7caedf382092faaf392174792b3cf5f2fe29cb586387ee55611af0617c9",
"373f2fd5940a01feb79659c8b9099477f6d3e7b570ebb749c2ac336ea4be583d",
"fea22887147adc3a659a14902080b03e86b4b8b16985fdf0bbacaed00d812422",
"6a3e51a1443cff62af9fa12fafc8ea78ae74dac7792c9ae0f436f570ab33eb71",
"796be21e213d6d0cd6fbe2de1555fb73d1cf9edc041a9f1ff1ad583c4ca92460",
"03fcbcb31d3fd17f0eedb45ac5a51678c7c8b2b8498225d05f74e2892f017f72",
"d28da07c6c22daf9ae987b3033c33d3140e5a56fa1ffd7dc5c7853d55a45bcc7",
"fbb0ce02f50018741a12fc08eea80a18067d7bb0fcd96153d40bb8c808473aae",
"2bf7c05a0209b4ea31314f04bd754cd01c58102d7cde8c496c655b6494924354",
"1968a9e6e14ae86a1e02e6078fc4631851fce5dbac6aa34f860defd1ccfd0ded",
"d886181329c9e06462a1407f547d77b38ff2c868b86d8976aa478e1cbb3d66d4",
"0d465e02ff2f8eb0b5fb2fa9a38579c5d66337d4a16b58f8ed28d2d89fc02392",
"3196419015289807880ef24b6781734822d654dc260c0560d00bac65eacd5219",
"fa08390ddc333a2a12248d5ec3e51fff9b782227069fe5a0afbd8eba967ae8d1",
"49ae36a791cb84516688d59a1ed3e5112851d65f265078aa2d433b45fa984c8a",
"35daa428e12c59da6730760979aca3444d8b31149c6febd99fbfefa4b2372082",
"5ef1d697beba612ff31d1dc139817c313a4e2ad3977775943b635c141ef0f2a1",
"674256037ec00edb66b9355fb1d33a30a47a5d1f4bce2dd5475d89f1ea6502db",
"7b6f017bc550933af91eec32a79464f540c5e0c208703e175843ee4e9ffc0a50",
"bf0eb91da1d18dbb18fd9ff36c837387887ba142961176a44889718b2becb9dc",
"3e5ac43a05164b074a2ff6353e9882917c5a3dbe168c2695de895f7decf1a56c",
"35e8f004965347c2b18a000a83dd3a8084b8a4bf00522061ed1179aa1107c413",
"fccb0fff3a24e555ec96f702ec11d420338910d148fc7b039d67568ad3a0e032",
"5cab231048032dbf921b4fafa1951dd2da93bc3740667f31d5a1d5665b141261",
"ffedb24be73441fbcd069f7785ebb865870e0f3ed228190732e4ffd5962bb82d",
"a4fcfec18adf92f4ed822f64d2da9f5ae630885a1bfa626530f641db99aa7a30",
"f98bcee41b0e3deafa1efaa1863750dbfd9bd7430b82529b670867d852230b5d",
"8ab8d5fca047a52364a737c1af57bf656c9ad5049f08ef4c5aa252e61aa72123",
"91318b39ad94c1d58143586b6d90dd6092a9d7487e321f4976967b6ac445ff43",
"fabfbd4569ab018e12d5ffa9b1a40ca8eb2ca60a685817351d90eaa770d5eccb",
"bbc5ef34428d980e2401942ceecfe07cdf21bfb1acae0596ea1d43fccf504f69",
"26943e4201ea407a5667103fe07ca6e08ef76940f274349b0e2e776bcfb0acb6",
"e3b305ffe33e72841f8e2a8688cc5cc27d42aee7624b33b7b6399b42db392437",
"17c5a763dd57e6bcc7c4cf2db0eb5cf3e97116b67fe0dd519c97e4a4d55d5a62",
"bbd260216879ce86af8318ffcf73c9e063ca76dd8bc35d3b6be45b2b4184888b",
"41285591d0595bc42ab663051b410d51af39fe1720592e27acb1a8af72360a76",
"f29acd6068ce494d0c0fe294cad91bb8968e3fff3f595a113227ab545c3ca3e6",
"ec9013c6394528e7dd788ce7cc085ca79fcdfbb37565999d5b4b5a4e39452ecc",
"27829bd7f1a8fcddcad0cc34a3b3fc67d62a2f3e09f8e75d35035c2281e83afd",
"666bea9db4e15087204d076294d221d4cf5864f5d94de38f29132b1934a17ace",
"a3a30924cad3dbda3446e5a6324e0a1390c70f795d5ecfe17ee5c70b14f7d87d",
"19567fe5fdb10711d60aa4d9843e1c49c2a6d2fd1b5cf662e2105606bb7815d3",
"b139f1c3a2f15596b9320334e37e4184d5d584c4a81e72d821a7edcad3aa62d5",
"08f1531e0e3e8f8bae313b2c60a72d5601bf8b60d7a4d2f60e8481650340d250",
"c5895669e1ff182bf1dd6c00dc955265e08ded0952b8ca62a1c63ba11c99f4ca",
"84d1c28153f66c1a4eb5fa0df695e936d83294df31a08d8d8e2d4798d19d8ce0",
"b8699f6af853fdbe897848feb46a05d733363f304eac4c8c1932e6ea4bc062cb",
"10eb3f6c1d0661468d9ed83593e5e9c0b43c6feec6a5405a498194905ea6ed48",
"509e215a600d9cadcbf5d62632ba321d7314764218db00ce8c907e425fccc445",
"e62119b7be84c8eaad41ba7f4a35da403f4ed96b967a3134e89ee8b78f8792c2",
"f790754a95d59ea5ffe6b9b5cc386c600a9e19e8bec997c192764365f1d05376",
"990121b5aa4d6badfb7154db4cdbb4512124bc2f442bebac71ea90b5cc86f203",
"b6983dedaa891eb14c964d84461e5cd37ed27b61771c64978ba83e3ecea194fa",
"00fba1ceaa6aa1e378cd5b22a771d6070250ac37f4e17d7bf1a70b3139e9a860",
"429854e7738abf2ecf46909454039e2fc5a080eb9a3c0c5ea13b07426dac3ad9",
"ceb3e017944b0dd787be219d8629930b3f2e20e22b12dc88fd838488ebb896f3",
"eb9e5d14424c63e675fe771b73ca865f7d38cf334d65e2426e12a0b88c1a2236",
"556ee713449e6e59ac4b8b2e8310180c8f6280484e9db23456526cceb9216168",
"bc89c3aa889e0144ac526a1f861227430dde7e439cc6a7e9b25c9a049c3ca7b3",
"56d070c62ea99be66fff741a8e45fafda5f9ff783e84d5395b251f356ce4e16f",
"ace15859c399e5ecd13b1420d3c3703c6a88dfb4a084f7225e7ba40a4b444fc8",
"f03f1261ab6eb879fe9c5b0028cd400b3ffdfac4344e4c75f6cde3c05ded1f26",
"955b2fda8d0068226f89270028b316b5adac871f1c1c85435479aba14a381b0f",
"422509a98d7461a6b8ec87cbb173b2486577b59ea9b269e01c20567b38b3b3b2",
"007d4de62ad89a4f5985f0cd9b76a7293acf383b4e9e734e813b9df1d57f986f",
"13a04e32948225b7e22aa0137341ebbb811e0743032fac16be9d691a652db2eb",
"8244b11d880a52f9f9e1830a822e6eeeaf0b12fc759f8261bc2f490cb0794f3b",
"27d3415f8f8fd3048a1ee0d9487256dd1b0f9e31be663778efa5b3add63868ec",
"0053f888db916a8905320e253fe2f0666355e6fb6de36f897231920a3edfe39f",
"0bc5c0a2ea47fa3bb8be107e3b9d6b7226b1c8bd16ca1bab8f51b8e1de08aa8b",
"4ca13aaa161c79025b5cd6c9a8ac33554f5ceb479fe293d9a342c865cd9c9948",
"333afbe82e2a3df38bd1ef998f39c5feef2554697aa21b5410c0e95ef9156249",
"587c4fcabd18ff890064171fce3d5be0c4aa1bba46893fb6a827a85ab54d20f3",
"964328e4d51d67c4e2f1fd102a66b861d98199f81d18d660b1b4b52504cd772a",
"196aad5594651efd679d30b9feb0f0d172cf977b4f89aa670ec741a8bf21e669",
"9137bfd66bbf47bfa0bfcbb9f6e71b6eb3fd9776530e9fd30d3dab19e182f35d",
"8217392c4ed2313188f295d94148a027a7f43824a5f5fba33a0b8c1045d509b4",
"be9e12761519a4836e73015544163254877e1c4912fcea67a10e7026421dde75",
"7b5220421a520b876cc6cdba0d3895104d7fac914dca5b93f9fe8b226566b71e",
"5c83fccfeb4bf0eb8a94d43ebc84a81639a32f26c7ef77d0a2b626b7de7befdb",
"132fd6c92cf176f975efdb5ded53470b462a48a2815c6f54a93ce4f935784cc7",
"46a3dba364022d11aa616a2bc20e3be5c4390f38b9446edfa464d90d9af5d48f",
"34b3f3fd8a83905a37762060f51d0b116377b4820b031b8e668e16f46c5b0285",
"f0e397e033dabec859a4b9a9043c5f1fb0dba504764d6bcf2fe9bf2ffd318474",
"85ecf59c7dd3b24ad17f591bc4737f32f1384c370a7a6f2add06a811dc824b6c",
"4d03cdb1e6ad8e066a83654626d8c221433e8d4fd901c671300af37e000177f2",
"61cb9c651893e6401b25f2bdf79c9f3ddc9ffe69cf6c791c420462bd73e347e1",
"85f2686a42158cd5ad327781ecccd1bdcd346941dd4b4edc45f717de6a011800",
"92de2ab82cac528e6d4ccd61e5b7c79591dcad9909c8ad3c8276ece6d48c0f08",
"23a878a06bb94bff33083349149f3c860f2b00bc3fb28f04cbaf717c08af19a3",
"1b1cce18ff0323566b192885d7ced30f9a9531a2580240f2c593a7d5b8580974",
"08fcdec7ea1376d84f3b13a47a4b73c7781c9c7890bb28f712b58af4fd3f24fe",
"03cc08fc4ece807c6495272c412be23b045622cc6b786ed8d5c94156ae678a0e",
"c4d8a61dc3f5dcf4b83f27a90cbc37e816cf4754e12309626ec5679c99087c46",
"b29d00681e29001cdd63c4bc50e5e25715faef692aeebb678c8050e1c095e888",
"ac154617e93f2bb1afa232675f2135437a9cc9700c14c51c40084946596ba11a",
"ce9549de8e68ae89f424dd9e1cde8a4eea2069da667cfcfbe837691d37366668",
"426c45a98e2af35cc9708149f6c086ff5a3972e77d62c627d5e20de5d731cad8",
"7e21bfe240a3d9b77a129c734a1d428dbc890379fbaf862853f48b2f7470b2b0",
"fa090a71f77223a7210de6db18d9aa809e89fb15253aea28131df6c5a7639140",
"7094ad044c5ab025e088b43aa0b947601fabe58ed700a412fd96e4b917ced0c8",
"936d5cdc4f081b6fe36c356af4378d472cd7990303f2ea44da645afd7d5d7f9c",
"05342037d3b69349dce7b95529d4b2a63ceb9d9393217a68f7cc8c958a96c3ea",
"ff9e1c414ef27b1178b1de296526f50520b7ddb06286bf9c47792bfb449e40b6",
"2f2b7bedb34d2854b17ccb702cddd8bc0157e39721d58be0b2ad54ee291fc9f1",
"0d8db1f34140bbf7eb809137018a74af08cb3345b8a3e368cdda8521dab45791",
"b109e4bfabcfe4a1c38be1156d9ca851c75e6aa2e57c0869e40cd9056f571e07",
"5cb363547ca077c806fc69bc8c2006831ab89e72fd778ac1a48fa810934e350e",
"85ee928bb110fd64eae54a91fc8548883e7fc4c60a3c61b505c31cea2d295c86",
"1ec3df7d10ee6fd5f0532ad4fe771e6befc28b0bed0250bf523695d6d49a8246",
"de9db2fc07c866bd7b885fb41522b63d550d0ce2e8ac5e14464a41733c2319e6",
"9a27136422a8f56768db29ba172a7ba26c3c7aa910324e78e5ab3a3268ac3674",
"60213c315119bf9005cb533d1a5b403b4a13c59982fe7773d30fdd8f519f4205",
"40eb61ef1812eb8a4d389599bf449fc86653b2c4986061b952f46fc049de53f4",
"658ef0d8140162b5f04591be13b47456245f531208bbca3260b857ca09b803c5",
"02270fa66255048d724894e2206b4e773cc6a7b6d17ca090cdc25f317d5f53b9",
"2ec6a0147f419161f7198d05be5f93152d9ccc10672db0ea47ff1687c0f0dd15",
"4be1d8ceb96eb80ef7ce30079ded31163272aeccff5c18fe3aaa32ea2f5bed9d",
"04ecaf48f44de87243b17b4c71ebff00020738639336010fa57435a54b623798",
"e313a9feb7cfd1d56ec87b1f1062ff9a80da498f7b761af4bef0cecd1b4c385b",
"ede3748f971f22341f7f5844dc60fc03cdb30c7cc720ebe13ae588c17a78aa94",
"d90c0faa70e39b7c0a8c55457ed6e6478a4e4bf3707b08104326a1ee8377c3ab",
"c79ffd0bbc8d004cc542e212990df6498abddd3deb50fd00ed00a2ff690974d6",
"35c37d88cf73a89c4124b0ee537347c37fdb47156c8b0ecc509efc58236ed3f0",
"a99182f343ccf05e557ffa6df71f03688b2afcf314c59daa774fe78db6f47add",
"01115397a78af8a4ae2727ca7a01843235b626bd3db80888d3dfd0020d4135e2",
"4a55aced578470d2f7280096d7fe8095f294095fba4778d1977d6db9270472f0",
"4624adf8a5633f65b213b8ca46b55cb0ee36c41495f39b1ae70cbd545779b1a0",
"d72bcd5b57a9c47e7bd5e9a1103657d10beb7b6c6d41f2b2985bc3bd3cc74860",
"48baadb9a46293c92f29e7617846171356a42c3b5d18d49a05a7e173993785f7",
"3da927737af8cb0e1c77097e35c54158d18aabfb3051c45bcc7ddfe00b157b1f",
"b4a24bfdb2cb802c8d48a3a18fbfe18622a767fe7eddfca57d4555550ccd1643",
"c58f82ac7c49dcba1721a88358f07636c9df60d3fd383e5789b808dc57a1dc9d",
"5e1f756eff5155df073d30f4452bdafc4adaf4f35960771bf2c1e30137fd7a79",
"be4a332f289338d67bd4834eae3128c488a61d255e972da484b6252b67a46b89",
"d496e4a36238d03a83d8b45cf33d9388aa7568a279b034d1cdd87b457356cc5b",
"a1c5212730ccda34de393210e276bbd44720dda777bcfd602315a3eee582f7dc",
"08914ec63f6ef7fe1d678937dc0f6178883440b26b4aca29fce79068947e8397",
"49e2cd2bd9b974074d9814f93eed371620bd4ea5fbf97a625065704e8fb382d7",
"047c194111818b48ce93a4b006e4a09b9a2650757a87357111796e11e847bf23",
"5955b0baa8265341f35a6f24fdc79066ba3ca9c5354c69b6b37a9ef3a26be556",
"d7c962f3ea1938c5267cca4072548acf3afcce4d438ed62027caa211a5f98e8b",
"c8cfba67cb4ce7e291b35154a50476d9a5c6bbb5d6cbaaa5d2408547fea7b02b",
"de8a940d8a69a64ce264d2ab7320662aef2e391c587cb2aae22a86718d5dffbb",
"94176f1310b26e54d4de48f87b74aa0b60532f184a2268508dece86dd7f85d36",
"9ce6ee3fca56c9256a69df404782301300a6e5e7f5a25a1f6d68c0e9e42584c9",
"7c423c4a220c6ff43ab6432f92b166323c58ee77f8c096ba0b00d52d7bd507e8",
"0b62b9c1ae4d4988720e8d41d980b334458189de0a3dd01699338d7b07c3894e",
"64f45f6f75110624506c53716f2fc1d5fe5f88f82a5bc6a7459ce70eae56dbb3",
"12ffbeb8e52fed161af4d8a015d1a5c45dcb8240e5c8933ce3a88ba2c58f97e8",
"2ee6b7b96043c8ded9fb52f87cdd0d0580ca6f8cef183c8a656394a11c0aa393",
"aaef26b1f5726258bf9ce305a3e54bca65cf68779f90f9d24287245c27362e27",
"ef59588dce57c35d010bea4d209f44c62f0b7c7e65bc0226c0e4971934da9435",
"0e606c2f6f8dcd579faf4739312bd7327ac7796fa44a81780fe0d66fc7761fb9",
"2f307198afdbde5f95989a17e06ce1bb9ff36c441cf3b2248431534fe13bb9fe",
"51418e6df23d450aaacc74ef2df53a6b1693727b70bda9ebc43acfc23d8fb5ea",
"6e9e3ac46705ed80520695b924435b00d2b3079598bf7faca7fd1524be777e5e",
"1e96241e2876aad29ce64f5d7e7fbb8db7265449df816c0d30a96633778c5cb6",
"81788f00eb72696d811f946e65d2c96528c45590874a1defdd46651e9b79a3a1",
"d9aa5a9f1df50e933d7105a5d72b5fe96bfbb9fd4b5b0eaa5e80af12e72d497a",
"e1b6976a732d27fc5d6a96b6d3d0d1d5eaa6ec46bae4665f17e7a43aefc75280",
"9151c75edcec1cc90aa2d2c240ff657b0eef3f5f1ec37418c8854b2493114f1d",
"3e7c12d0132421f08ea0a390cfa325e422a6b35120fb2eb650f108a165237934",
"1ee0e85c7d8a91089c03f37318cdc9127026bf789e3ce4b75046eaa3eebd3458",
"4ae64a3ef66cad847409ce175bd5365c9097fd21647a05730ac6b45841add3c8",
"f0ea0f334cf1d64678a6dab08c07e2f94f339e8389bd17ebc882b5c8b736cbf2",
"da904db96060546ff69e28993ce8183766da9402ac10fae9fc1f1d67ebd83c90",
"db11820615f7b5e47778c45d2e083e77f49b608b587dc09ec26f077aba07a242",
"ff5c726a83bd785484de75bb03b421f9e8e382bf2740120a2fcf72326aa01c75",
"f8643a7efd6304980db323303ab73a6fd4f4ee1047520d39d571580395b97f21",
"8facf9737d07838aedf6030593bfb247d8c29fe8d9b18b2913408627a4424d7e",
"f0672964aa6e4c7dd4768e18827023787386927f4db89fd661444979afb43c18",
"6fd3649c8401f2704ed2be18518b870eb6bf2b9a6689d1b336f05bd8b49017f6",
"ed172dac7de827493e0c0fdd8d3299333acb678e72ed499e0224b389cc1e0fba",
"7f9a8a8cc8e34add11934a1a5882be5978a6d28405cb0a053ec5699a502b1cef",
"6ca829ebd2a0a40994f68c1db7978ec274b45c46e9b351df869a2bfe0630bbd4",
"0bbb017c437573a55db88258a9d9a01188bdd23bb6b26903b137814871661f47",
"9a6358d2541f46b6d05b80fe25a2cb025fbe9e4b227a6275908d5ee31c948569",
"a75d26c6d4ce944024f10e6d23e8b5b888d680120e15dc0e4fee8d8833ee0c6a",
"1d43d33556699b42c124b46e41243abf48727fe488428056fdd174a3861c1e3c",
"7b5bd3fecbaa093f005c4f806ea67846c0df6b04df7729925cb14724f6a8b582",
"6bdf2b54f2f5ab90191261d33dee80fede75896994016422b28db8ba62327d82",
"1a16181b250085a91ccecc118473fa2ab98515e894a7b63b347c24b5be560c7a",
"22d24891755910b48ad632358c26245bdcc375abc41f7e2c9fb3c7773dbf4e22",
"5b70c5d4a373d541619c944fcc3b61259550b0e9fba3eca16f0879e5845b43b9",
"b78f9098c9d76987b7409e63426a8d49972bb4e75289576c680cf96513d44b6d",
"916b53b8e85eb7e0a2a76d6fc8d2163430e7183ccb103d6705f54af4bb070907",
"dc3d78f43110d2aa9df83c5485ec33663ad5452b8cdeb1aeeac9d6b1487fb781",
"3975539ed5402cb9f5ab503584524dd141cc4296b666ec66d807f94f62b1c026",
"bd1f97fd89183643423073f22733880616456ca41960699f18e868cb9ac35508",
"90b468ff0f83460c3dd8cfe778c39d32c6bb1eeff9ac5de7804a4050d3b8073e",
"0e886d49d88b82c9f8dbdd2f38a535992f35ab16629724d746394db3898235fa",
"76c22e965242d1ca5614e829d9028dcad9c4b09393bcbdd318b0365557335fb9",
"59b168488ec8629f820a1efd8fc5a0c2adec4253e61d6a2945a68a9a43be9035",
"ff172b42854eaf2865caa985d2fb6283c5ab19574126623ffd615a761a5bce72",
"cb46ac9ccc024ee74c96e3cf1c13a6949a432e855dfa881b6a307c0e6daac59e",
"9971574924c0f413bf4c0f96bb9c2fbdfea8f475e33a8fb6f15fa40903b63444",
"1a95567deb0f45a8941e2248f33286485984a5e9d86d16c37d42169ad864dc36",
"205fc7f7ec7a83f0bc22d5269c91762cd00adc7428456d799be5a0cd76f08b0f",
"849dd41ef59a722901b7a0deb2c1fd3c110a91a726120a0a119cb7a15cf98438",
"a32880917c714612101af95e5c8d8eb5fb046fdcc68bae76c05b829b3fa73c2e",
"70b38d6d510d13b359dffa910329952c620a4bce4ee7a8552b9bb3a14572394d",
"ef257ab2f4226faa6ba288a6793f026609068effb866c18496a847e8b60b102d",
"e5196ab42ff53c8352288bde6b6b7312cd6f39f7d21b556b0db178d8470d5790",
"ca98f128bf085f2b718f2b3c12da7c4d98887cc94251a2b1705b637611bd83bb",
"79508f0b93a49ec19c5cb05906ca1ba3d3db8ed4f9c6884873d0d7e3e985ea51",
"9088be3f47f9debc63e928739f7163182b49eab044518b151f0b89f6b6aefdd0",
"46b2782fd669b6288a4d7348cf6671360277ba4864cc69bce3497369ac2ec31e",
"0fa5131557db67b430d516530be939ff25882adf68a076602f3dfad8c77c963a",
"3404302cc097d5457244453a4c9990804201ee8161188df811bcb32404998c71",
"856939710dbb90a8eeda875a31f9a52af759bd932b88e7b08df35414c54d4721",
"72569573b9b41d0ac5ce17764a139c6b8b36ef3ca6d92cec625dbcdae758ba22",
"9746da344e435a008d6acb4847211bb676376ecc76c825b5d44a28b89ceeb40e",
"3eafded1595516f032e33ec975f4c9c3a1055d13aa5575cf8a801d6103fdbeb4",
"e88a6d2daa863c0787cc523a2cab45c546fad788951b10d75e2b0954db24cca7",
"38f531e67f88f66de44d3357c8e8f2db456160ca31dd2024c9562f6afd260278",
};
// block 685498 (13 key images in one transaction)
static const char * const key_images_685498[] =
{
"749b7277aa21c70c417f255fb181c3a30b44277edf657eaaebf28a2709dd2a90",
"5a9b3e1a87332d735cedaa2b5623a6a5e99d99f5a2887c8fc84293577e8bf25c",
"bea438768445eb3650cf619bf6758e94035abfe0ccda91d4a58c582df143d835",
"376e237ff4da5e5cbd6e1bba4b01412fa751f2959c0c57006589f382413df429",
"14ac2f2e044f8635a3a42ecb46c575424073c1f6e5ed5e905f516d57f63184b5",
"2d1d2ecb77b69a2901de00897d0509c1b7855a3b2f8eb1afe419008fc03cd15a",
"ea01658f0972b77ae9112d525ec073e3ec5c3b98d5ad912d95ab2636354b70b6",
"d3934864a46101d8c242415282e7fc9ee73ad16cd40355535d226ab45ecdb61a",
"ee379b05c5d02432330ebd4ea9c4f1c87d14c388568d526a0f8a22649a14e453",
"aeb7b842b410b13ca4af7a5ffd5ae6caddc8bfec653df1b945e478839a2e0057",
"451806929d9f5c3a7f365472703871abadc25b2a5a2d75472a45e86cd76c610b",
"272d9b9fcc9e253c08da9caf8233471150019582eaefef461c1f9ceff7e2c337",
"633cdedeb3b96ec4f234c670254c6f721e0b368d00b48c6b26759db7d62cf52d",
};
if (height() > 202612)
{
for (const auto &kis: key_images_202612)
{
crypto::key_image ki;
epee::string_tools::hex_to_pod(kis, ki);
if (!has_key_image(ki))
{
LOG_PRINT_L1("Fixup: adding missing spent key " << ki);
add_spent_key(ki);
}
}
}
if (height() > 685498)
{
for (const auto &kis: key_images_685498)
{
crypto::key_image ki;
epee::string_tools::hex_to_pod(kis, ki);
if (!has_key_image(ki))
{
LOG_PRINT_L1("Fixup: adding missing spent key " << ki);
add_spent_key(ki);
}
}
}
}
batch_stop();
} }
bool BlockchainDB::txpool_tx_matches_category(const crypto::hash& tx_hash, relay_category category) bool BlockchainDB::txpool_tx_matches_category(const crypto::hash& tx_hash, relay_category category)

@ -820,7 +820,7 @@ void BlockchainLMDB::add_block(const block& blk, size_t block_weight, uint64_t l
bi.bi_diff_lo = (cumulative_difficulty & 0xffffffffffffffff).convert_to<uint64_t>(); bi.bi_diff_lo = (cumulative_difficulty & 0xffffffffffffffff).convert_to<uint64_t>();
bi.bi_hash = blk_hash; bi.bi_hash = blk_hash;
bi.bi_cum_rct = num_rct_outs; bi.bi_cum_rct = num_rct_outs;
if (blk.major_version >= 4) if (m_height > 0 && blk.major_version >= 4)
{ {
uint64_t last_height = m_height-1; uint64_t last_height = m_height-1;
MDB_val_set(h, last_height); MDB_val_set(h, last_height);
@ -1351,7 +1351,7 @@ void BlockchainLMDB::open(const std::string& filename, const int db_flags)
if (is_hdd_result) if (is_hdd_result)
{ {
if (is_hdd_result.value()) if (is_hdd_result.value())
MCLOG_RED(el::Level::Warning, "global", "The blockchain is on a rotating drive: this will be very slow, use an SSD if possible"); MCLOG_RED(el::Level::Debug, "global", "The blockchain is on a rotating drive: this will be very slow, use an SSD if possible");
} }
m_folder = filename; m_folder = filename;
@ -1504,7 +1504,7 @@ void BlockchainLMDB::open(const std::string& filename, const int db_flags)
mdb_env_close(m_env); mdb_env_close(m_env);
m_open = false; m_open = false;
MFATAL("Existing lmdb database needs to be converted, which cannot be done on a read-only database."); MFATAL("Existing lmdb database needs to be converted, which cannot be done on a read-only database.");
MFATAL("Please run monerod once to convert the database."); MFATAL("Please run wownerod once to convert the database.");
return; return;
} }
// Note that there was a schema change within version 0 as well. // Note that there was a schema change within version 0 as well.

@ -157,7 +157,7 @@ endif()
set_property(TARGET blockchain_import set_property(TARGET blockchain_import
PROPERTY PROPERTY
OUTPUT_NAME "monero-blockchain-import") OUTPUT_NAME "wownero-blockchain-import")
install(TARGETS blockchain_import DESTINATION bin) install(TARGETS blockchain_import DESTINATION bin)
monero_add_executable(blockchain_export monero_add_executable(blockchain_export
@ -178,7 +178,7 @@ target_link_libraries(blockchain_export
set_property(TARGET blockchain_export set_property(TARGET blockchain_export
PROPERTY PROPERTY
OUTPUT_NAME "monero-blockchain-export") OUTPUT_NAME "wownero-blockchain-export")
install(TARGETS blockchain_export DESTINATION bin) install(TARGETS blockchain_export DESTINATION bin)
monero_add_executable(blockchain_blackball monero_add_executable(blockchain_blackball
@ -200,7 +200,7 @@ target_link_libraries(blockchain_blackball
set_property(TARGET blockchain_blackball set_property(TARGET blockchain_blackball
PROPERTY PROPERTY
OUTPUT_NAME "monero-blockchain-mark-spent-outputs") OUTPUT_NAME "wownero-blockchain-mark-spent-outputs")
install(TARGETS blockchain_blackball DESTINATION bin) install(TARGETS blockchain_blackball DESTINATION bin)
@ -222,7 +222,7 @@ target_link_libraries(blockchain_usage
set_property(TARGET blockchain_usage set_property(TARGET blockchain_usage
PROPERTY PROPERTY
OUTPUT_NAME "monero-blockchain-usage") OUTPUT_NAME "wownero-blockchain-usage")
install(TARGETS blockchain_usage DESTINATION bin) install(TARGETS blockchain_usage DESTINATION bin)
monero_add_executable(blockchain_ancestry monero_add_executable(blockchain_ancestry
@ -243,7 +243,7 @@ target_link_libraries(blockchain_ancestry
set_property(TARGET blockchain_ancestry set_property(TARGET blockchain_ancestry
PROPERTY PROPERTY
OUTPUT_NAME "monero-blockchain-ancestry") OUTPUT_NAME "wownero-blockchain-ancestry")
install(TARGETS blockchain_ancestry DESTINATION bin) install(TARGETS blockchain_ancestry DESTINATION bin)
monero_add_executable(blockchain_depth monero_add_executable(blockchain_depth
@ -264,7 +264,7 @@ target_link_libraries(blockchain_depth
set_property(TARGET blockchain_depth set_property(TARGET blockchain_depth
PROPERTY PROPERTY
OUTPUT_NAME "monero-blockchain-depth") OUTPUT_NAME "wownero-blockchain-depth")
install(TARGETS blockchain_depth DESTINATION bin) install(TARGETS blockchain_depth DESTINATION bin)
monero_add_executable(blockchain_stats monero_add_executable(blockchain_stats
@ -285,7 +285,7 @@ target_link_libraries(blockchain_stats
set_property(TARGET blockchain_stats set_property(TARGET blockchain_stats
PROPERTY PROPERTY
OUTPUT_NAME "monero-blockchain-stats") OUTPUT_NAME "wownero-blockchain-stats")
install(TARGETS blockchain_stats DESTINATION bin) install(TARGETS blockchain_stats DESTINATION bin)
monero_add_executable(blockchain_prune_known_spent_data monero_add_executable(blockchain_prune_known_spent_data
@ -307,7 +307,7 @@ target_link_libraries(blockchain_prune_known_spent_data
set_property(TARGET blockchain_prune_known_spent_data set_property(TARGET blockchain_prune_known_spent_data
PROPERTY PROPERTY
OUTPUT_NAME "monero-blockchain-prune-known-spent-data") OUTPUT_NAME "wownero-blockchain-prune-known-spent-data")
install(TARGETS blockchain_prune_known_spent_data DESTINATION bin) install(TARGETS blockchain_prune_known_spent_data DESTINATION bin)
monero_add_executable(blockchain_prune monero_add_executable(blockchain_prune
@ -316,7 +316,7 @@ monero_add_executable(blockchain_prune
set_property(TARGET blockchain_prune set_property(TARGET blockchain_prune
PROPERTY PROPERTY
OUTPUT_NAME "monero-blockchain-prune") OUTPUT_NAME "wownero-blockchain-prune")
install(TARGETS blockchain_prune DESTINATION bin) install(TARGETS blockchain_prune DESTINATION bin)
target_link_libraries(blockchain_prune target_link_libraries(blockchain_prune

@ -386,12 +386,12 @@ int main(int argc, char* argv[])
if (command_line::get_arg(vm, command_line::arg_help)) if (command_line::get_arg(vm, command_line::arg_help))
{ {
std::cout << "Monero '" << MONERO_RELEASE_NAME << "' (v" << MONERO_VERSION_FULL << ")" << ENDL << ENDL; std::cout << "Wownero '" << MONERO_RELEASE_NAME << "' (v" << MONERO_VERSION_FULL << ")" << ENDL << ENDL;
std::cout << desc_options << std::endl; std::cout << desc_options << std::endl;
return 1; return 1;
} }
mlog_configure(mlog_get_default_log_path("monero-blockchain-ancestry.log"), true); mlog_configure(mlog_get_default_log_path("wownero-blockchain-ancestry.log"), true);
if (!command_line::is_arg_defaulted(vm, arg_log_level)) if (!command_line::is_arg_defaulted(vm, arg_log_level))
mlog_set_log(command_line::get_arg(vm, arg_log_level).c_str()); mlog_set_log(command_line::get_arg(vm, arg_log_level).c_str());
else else

@ -132,7 +132,7 @@ static std::string get_default_db_path()
boost::filesystem::path dir = tools::get_default_data_dir(); boost::filesystem::path dir = tools::get_default_data_dir();
// remove .bitmonero, replace with .shared-ringdb // remove .bitmonero, replace with .shared-ringdb
dir = dir.remove_filename(); dir = dir.remove_filename();
dir /= ".shared-ringdb"; dir /= ".wow-shared-ringdb";
return dir.string(); return dir.string();
} }
@ -1176,7 +1176,7 @@ int main(int argc, char* argv[])
const command_line::arg_descriptor<bool> arg_rct_only = {"rct-only", "Only work on ringCT outputs", false}; const command_line::arg_descriptor<bool> arg_rct_only = {"rct-only", "Only work on ringCT outputs", false};
const command_line::arg_descriptor<bool> arg_check_subsets = {"check-subsets", "Check ring subsets (very expensive)", false}; const command_line::arg_descriptor<bool> arg_check_subsets = {"check-subsets", "Check ring subsets (very expensive)", false};
const command_line::arg_descriptor<bool> arg_verbose = {"verbose", "Verbose output)", false}; const command_line::arg_descriptor<bool> arg_verbose = {"verbose", "Verbose output)", false};
const command_line::arg_descriptor<std::vector<std::string> > arg_inputs = {"inputs", "Path to Monero DB, and path to any fork DBs"}; const command_line::arg_descriptor<std::vector<std::string> > arg_inputs = {"inputs", "Path to Wownero DB, and path to any fork DBs"};
const command_line::arg_descriptor<std::string> arg_db_sync_mode = { const command_line::arg_descriptor<std::string> arg_db_sync_mode = {
"db-sync-mode" "db-sync-mode"
, "Specify sync option, using format [safe|fast|fastest]:[nrecords_per_sync]." , "Specify sync option, using format [safe|fast|fastest]:[nrecords_per_sync]."
@ -1219,12 +1219,12 @@ int main(int argc, char* argv[])
if (command_line::get_arg(vm, command_line::arg_help)) if (command_line::get_arg(vm, command_line::arg_help))
{ {
std::cout << "Monero '" << MONERO_RELEASE_NAME << "' (v" << MONERO_VERSION_FULL << ")" << ENDL << ENDL; std::cout << "Wownero '" << MONERO_RELEASE_NAME << "' (v" << MONERO_VERSION_FULL << ")" << ENDL << ENDL;
std::cout << desc_options << std::endl; std::cout << desc_options << std::endl;
return 1; return 1;
} }
mlog_configure(mlog_get_default_log_path("monero-blockchain-mark-spent-outputs.log"), true); mlog_configure(mlog_get_default_log_path("wownero-blockchain-mark-spent-outputs.log"), true);
if (!command_line::is_arg_defaulted(vm, arg_log_level)) if (!command_line::is_arg_defaulted(vm, arg_log_level))
mlog_set_log(command_line::get_arg(vm, arg_log_level).c_str()); mlog_set_log(command_line::get_arg(vm, arg_log_level).c_str());
else else

@ -88,12 +88,12 @@ int main(int argc, char* argv[])
if (command_line::get_arg(vm, command_line::arg_help)) if (command_line::get_arg(vm, command_line::arg_help))
{ {
std::cout << "Monero '" << MONERO_RELEASE_NAME << "' (v" << MONERO_VERSION_FULL << ")" << ENDL << ENDL; std::cout << "Wownero '" << MONERO_RELEASE_NAME << "' (v" << MONERO_VERSION_FULL << ")" << ENDL << ENDL;
std::cout << desc_options << std::endl; std::cout << desc_options << std::endl;
return 1; return 1;
} }
mlog_configure(mlog_get_default_log_path("monero-blockchain-depth.log"), true); mlog_configure(mlog_get_default_log_path("wownero-blockchain-depth.log"), true);
if (!command_line::is_arg_defaulted(vm, arg_log_level)) if (!command_line::is_arg_defaulted(vm, arg_log_level))
mlog_set_log(command_line::get_arg(vm, arg_log_level).c_str()); mlog_set_log(command_line::get_arg(vm, arg_log_level).c_str());
else else

@ -90,12 +90,12 @@ int main(int argc, char* argv[])
if (command_line::get_arg(vm, command_line::arg_help)) if (command_line::get_arg(vm, command_line::arg_help))
{ {
std::cout << "Monero '" << MONERO_RELEASE_NAME << "' (v" << MONERO_VERSION_FULL << ")" << ENDL << ENDL; std::cout << "Wownero '" << MONERO_RELEASE_NAME << "' (v" << MONERO_VERSION_FULL << ")" << ENDL << ENDL;
std::cout << desc_options << std::endl; std::cout << desc_options << std::endl;
return 1; return 1;
} }
mlog_configure(mlog_get_default_log_path("monero-blockchain-export.log"), true); mlog_configure(mlog_get_default_log_path("wownero-blockchain-export.log"), true);
if (!command_line::is_arg_defaulted(vm, arg_log_level)) if (!command_line::is_arg_defaulted(vm, arg_log_level))
mlog_set_log(command_line::get_arg(vm, arg_log_level).c_str()); mlog_set_log(command_line::get_arg(vm, arg_log_level).c_str());
else else

@ -637,7 +637,7 @@ int main(int argc, char* argv[])
if (command_line::get_arg(vm, command_line::arg_help)) if (command_line::get_arg(vm, command_line::arg_help))
{ {
std::cout << "Monero '" << MONERO_RELEASE_NAME << "' (v" << MONERO_VERSION_FULL << ")" << ENDL << ENDL; std::cout << "Wownero '" << MONERO_RELEASE_NAME << "' (v" << MONERO_VERSION_FULL << ")" << ENDL << ENDL;
std::cout << desc_options << std::endl; std::cout << desc_options << std::endl;
return 1; return 1;
} }
@ -674,7 +674,7 @@ int main(int argc, char* argv[])
} }
m_config_folder = command_line::get_arg(vm, cryptonote::arg_data_dir); m_config_folder = command_line::get_arg(vm, cryptonote::arg_data_dir);
mlog_configure(mlog_get_default_log_path("monero-blockchain-import.log"), true); mlog_configure(mlog_get_default_log_path("wownero-blockchain-import.log"), true);
if (!command_line::is_arg_defaulted(vm, arg_log_level)) if (!command_line::is_arg_defaulted(vm, arg_log_level))
mlog_set_log(command_line::get_arg(vm, arg_log_level).c_str()); mlog_set_log(command_line::get_arg(vm, arg_log_level).c_str());
else else

@ -483,12 +483,12 @@ int main(int argc, char* argv[])
if (command_line::get_arg(vm, command_line::arg_help)) if (command_line::get_arg(vm, command_line::arg_help))
{ {
std::cout << "Monero '" << MONERO_RELEASE_NAME << "' (v" << MONERO_VERSION_FULL << ")" << ENDL << ENDL; std::cout << "Wownero '" << MONERO_RELEASE_NAME << "' (v" << MONERO_VERSION_FULL << ")" << ENDL << ENDL;
std::cout << desc_options << std::endl; std::cout << desc_options << std::endl;
return 1; return 1;
} }
mlog_configure(mlog_get_default_log_path("monero-blockchain-prune.log"), true); mlog_configure(mlog_get_default_log_path("wownero-blockchain-prune.log"), true);
if (!command_line::is_arg_defaulted(vm, arg_log_level)) if (!command_line::is_arg_defaulted(vm, arg_log_level))
mlog_set_log(command_line::get_arg(vm, arg_log_level).c_str()); mlog_set_log(command_line::get_arg(vm, arg_log_level).c_str());
else else

@ -137,12 +137,12 @@ int main(int argc, char* argv[])
if (command_line::get_arg(vm, command_line::arg_help)) if (command_line::get_arg(vm, command_line::arg_help))
{ {
std::cout << "Monero '" << MONERO_RELEASE_NAME << "' (v" << MONERO_VERSION_FULL << ")" << ENDL << ENDL; std::cout << "Wownero '" << MONERO_RELEASE_NAME << "' (v" << MONERO_VERSION_FULL << ")" << ENDL << ENDL;
std::cout << desc_options << std::endl; std::cout << desc_options << std::endl;
return 1; return 1;
} }
mlog_configure(mlog_get_default_log_path("monero-blockchain-prune-known-spent-data.log"), true); mlog_configure(mlog_get_default_log_path("wownero-blockchain-prune-known-spent-data.log"), true);
if (!command_line::is_arg_defaulted(vm, arg_log_level)) if (!command_line::is_arg_defaulted(vm, arg_log_level))
mlog_set_log(command_line::get_arg(vm, arg_log_level).c_str()); mlog_set_log(command_line::get_arg(vm, arg_log_level).c_str());
else else

@ -175,12 +175,12 @@ int main(int argc, char* argv[])
if (command_line::get_arg(vm, command_line::arg_help)) if (command_line::get_arg(vm, command_line::arg_help))
{ {
std::cout << "Monero '" << MONERO_RELEASE_NAME << "' (v" << MONERO_VERSION_FULL << ")" << ENDL << ENDL; std::cout << "Wownero '" << MONERO_RELEASE_NAME << "' (v" << MONERO_VERSION_FULL << ")" << ENDL << ENDL;
std::cout << desc_options << std::endl; std::cout << desc_options << std::endl;
return 1; return 1;
} }
mlog_configure(mlog_get_default_log_path("monero-blockchain-stats.log"), true); mlog_configure(mlog_get_default_log_path("wownero-blockchain-stats.log"), true);
if (!command_line::is_arg_defaulted(vm, arg_log_level)) if (!command_line::is_arg_defaulted(vm, arg_log_level))
mlog_set_log(command_line::get_arg(vm, arg_log_level).c_str()); mlog_set_log(command_line::get_arg(vm, arg_log_level).c_str());
else else

@ -120,12 +120,12 @@ int main(int argc, char* argv[])
if (command_line::get_arg(vm, command_line::arg_help)) if (command_line::get_arg(vm, command_line::arg_help))
{ {
std::cout << "Monero '" << MONERO_RELEASE_NAME << "' (v" << MONERO_VERSION_FULL << ")" << ENDL << ENDL; std::cout << "Wownero '" << MONERO_RELEASE_NAME << "' (v" << MONERO_VERSION_FULL << ")" << ENDL << ENDL;
std::cout << desc_options << std::endl; std::cout << desc_options << std::endl;
return 1; return 1;
} }
mlog_configure(mlog_get_default_log_path("monero-blockchain-usage.log"), true); mlog_configure(mlog_get_default_log_path("wownero-blockchain-usage.log"), true);
if (!command_line::is_arg_defaulted(vm, arg_log_level)) if (!command_line::is_arg_defaulted(vm, arg_log_level))
mlog_set_log(command_line::get_arg(vm, arg_log_level).c_str()); mlog_set_log(command_line::get_arg(vm, arg_log_level).c_str());
else else

@ -41,7 +41,7 @@ const size_t ${BLOB_NAME}_len = sizeof(${BLOB_NAME});
" "
) )
]=]) ]=])
foreach(BLOB_NAME checkpoints testnet_blocks stagenet_blocks) foreach(BLOB_NAME checkpoints)
set(OUTPUT_C_SOURCE "generated_${BLOB_NAME}.c") set(OUTPUT_C_SOURCE "generated_${BLOB_NAME}.c")
list(APPEND GENERATED_SOURCES ${OUTPUT_C_SOURCE}) list(APPEND GENERATED_SOURCES ${OUTPUT_C_SOURCE})
set(INPUT_DAT_FILE "${BLOB_NAME}.dat") set(INPUT_DAT_FILE "${BLOB_NAME}.dat")

@ -4,18 +4,12 @@
extern const unsigned char checkpoints[]; extern const unsigned char checkpoints[];
extern const size_t checkpoints_len; extern const size_t checkpoints_len;
extern const unsigned char stagenet_blocks[];
extern const size_t stagenet_blocks_len;
extern const unsigned char testnet_blocks[];
extern const size_t testnet_blocks_len;
namespace blocks namespace blocks
{ {
const std::unordered_map<cryptonote::network_type, const epee::span<const unsigned char>, std::hash<size_t>> CheckpointsByNetwork = { const std::unordered_map<cryptonote::network_type, const epee::span<const unsigned char>, std::hash<size_t>> CheckpointsByNetwork = {
{cryptonote::network_type::MAINNET, {checkpoints, checkpoints_len}}, {cryptonote::network_type::MAINNET, {checkpoints, checkpoints_len}}
{cryptonote::network_type::STAGENET, {stagenet_blocks, stagenet_blocks_len}},
{cryptonote::network_type::TESTNET, {testnet_blocks, testnet_blocks_len}}
}; };
const epee::span<const unsigned char> GetCheckpointsData(cryptonote::network_type network) const epee::span<const unsigned char> GetCheckpointsData(cryptonote::network_type network)

Binary file not shown.

@ -197,53 +197,50 @@ namespace cryptonote
ADD_CHECKPOINT2(550000, "409f68cddd8e74b37469b41c1e61250d81c5776b42264f416d5d27c4626383ed", "0x5f3d4d03e"); ADD_CHECKPOINT2(550000, "409f68cddd8e74b37469b41c1e61250d81c5776b42264f416d5d27c4626383ed", "0x5f3d4d03e");
return true; return true;
} }
ADD_CHECKPOINT2(1, "771fbcd656ec1464d3a02ead5e18644030007a0fc664c0a964d30922821a8148", "0x2"); ADD_CHECKPOINT2(1, "97f4ce4d7879b3bea54dcec738cd2ebb7952b4e9bb9743262310cd5fec749340", "0x2");
ADD_CHECKPOINT2(10, "c0e3b387e47042f72d8ccdca88071ff96bff1ac7cde09ae113dbb7ad3fe92381", "0x2a974"); ADD_CHECKPOINT2(6969, "aa7b66e8c461065139b55c29538a39c33ceda93e587f84d490ed573d80511c87", "0x118eef693fd"); //Hard fork to v8
ADD_CHECKPOINT2(100, "ac3e11ca545e57c49fca2b4e8c48c03c23be047c43e471e1394528b1f9f80b2d", "0x35d14b"); ADD_CHECKPOINT2(53666, "3f43f56f66ef0c43cf2fd14d0d28fa2aae0ef8f40716773511345750770f1255", "0xb677d6405ae"); //Hard fork to v9
ADD_CHECKPOINT2(1000, "5acfc45acffd2b2e7345caf42fa02308c5793f15ec33946e969e829f40b03876", "0x36a0373"); ADD_CHECKPOINT2(63469, "4e33a9343fc5b86661ec0affaeb5b5a065290602c02d817337e4a979fe5747d8", "0xe7cd9819062"); //Hard fork to v10
ADD_CHECKPOINT2(10000, "c758b7c81f928be3295d45e230646de8b852ec96a821eac3fea4daf3fcac0ca2", "0x60a91390"); ADD_CHECKPOINT2(81769, "41db9fef8d0ccfa78b570ee9525d4f55de77b510c3ae4b08a1d51b9aec9ade1d", "0x150066455b88"); //Hard fork to v11
ADD_CHECKPOINT2(22231, "7cb10e29d67e1c069e6e11b17d30b809724255fee2f6868dc14cfc6ed44dfb25", "0x1e288793d"); ADD_CHECKPOINT2(82069, "fdea800d23d0b2eea19dec8af31e453e883e8315c97e25c8bb3e88ca164f8369", "0x15079b5fdaa8"); //Hard fork to v12
ADD_CHECKPOINT2(29556, "53c484a8ed91e4da621bb2fa88106dbde426fe90d7ef07b9c1e5127fb6f3a7f6", "0x71f64cce8"); ADD_CHECKPOINT2(114969, "b48245956b87f243048fd61021f4b3e5443e57eee7ff8ba4762d18926e80b80c", "0x1ca552b3ec68"); //Hard fork to v13
ADD_CHECKPOINT2(50000, "0fe8758ab06a8b9cb35b7328fd4f757af530a5d37759f9d3e421023231f7b31c", "0x893044b400"); ADD_CHECKPOINT2(115257, "338e056551087fe23d6c4b4280244bc5362b004716d85ec799a775f190f9fea9", "0x1cb25f5d4628"); //Hard fork to v14
ADD_CHECKPOINT2(80000, "a62dcd7b536f22e003ebae8726e9e7276f63d594e264b6f0cd7aab27b66e75e3", "0x5cc113f1076"); ADD_CHECKPOINT2(160777, "9496690579af21f38f00e67e11c2e85a15912fe4f412aad33d1162be1579e755", "0x5376eaa196a8"); //Hard fork to v15
ADD_CHECKPOINT2(202612, "bbd604d2ba11ba27935e006ed39c9bfdd99b76bf4a50654bc1e1e61217962698", "0x73310a259eb2"); ADD_CHECKPOINT2(253999, "755a289fe8a68e96a0f69069ba4007b676ec87dce2e47dfb9647fe5691f49883", "0x172d026ef7fe8"); //Hard fork to v16
ADD_CHECKPOINT2(202613, "e2aa337e78df1f98f462b3b1e560c6b914dec47b610698b7b7d1e3e86b6197c2", "0x733154039b97"); ADD_CHECKPOINT2(254287, "b37cb55abe73965b424f8028bf71bef98d069645077ffa52f0c134907b7734e3", "0x1746622f56668"); //Hard fork to v17
ADD_CHECKPOINT2(202614, "c29e3dc37d8da3e72e506e31a213a58771b24450144305bcba9e70fa4d6ea6fb", "0x73319dc90cb6"); ADD_CHECKPOINT2(256700, "389a8ab95a80e84ec74639c1078bc67b33af208ef00f53bd9609cfc40efa7059", "0x185ace3c1bd68");
ADD_CHECKPOINT2(205000, "5d3d7a26e6dc7535e34f03def711daa8c263785f73ec1fadef8a45880fde8063", "0x75fcc3d85123"); ADD_CHECKPOINT2(271600, "9597cdbdc52ca57d7dbd8f9c0a23a73194ef2ebbcfdc75c21992672706108d43", "0x1e2d2d6a2a9e8");
ADD_CHECKPOINT2(220000, "9613f455933c00e3e33ac315cc6b455ee8aa0c567163836858c2d9caff111553", "0x89cfed0cae3c"); ADD_CHECKPOINT2(278300, "b10dcdf7a51651f60fbcc0447409773eef1458d2c706d9a61daf467571ac19c9", "0x20a83a16d3968");
ADD_CHECKPOINT2(230300, "bae7a80c46859db355556e3a9204a337ae8f24309926a1312323fdecf1920e61", "0x967d13e5baa9"); ADD_CHECKPOINT2(282700, "79c06cafd7cb5f76bcebbf8f1ae16203bb41fd75b284bcd0eb0b457991ab7d4a", "0x22e3baf142de8");
ADD_CHECKPOINT2(230700, "93e631240ceac831da1aebfc5dac8f722c430463024763ebafa888796ceaeedf", "0x96fb9663ebe7"); ADD_CHECKPOINT2(307686, "dfd056b2739c132a07629409a59a028cb7414fac23e3419e79d2f49d66fc3af5", "0x305ba542e3ea8"); // "difficulty": 25800000
ADD_CHECKPOINT2(231350, "b5add137199b820e1ea26640e5c3e121fd85faa86a1e39cf7e6cc097bdeb1131", "0x97b9919177bf"); ADD_CHECKPOINT2(307692, "d822cd72037f62824ec87c9dc11768b45dc2632f697fa372e1885789c90f37fc", "0x305e124633878"); // "difficulty": 1890000
ADD_CHECKPOINT2(232150, "955de8e6b6508af2c24f7334f97beeea651d78e9ade3ab18fec3763be3201aa8", "0x98a038b612e8"); ADD_CHECKPOINT2(307735, "60970378aecdc0a78ccf5154edcc56f23aad8554b49e4716f820461a7588bfdc", "0x3070771b9ba58"); // "difficulty": 17900000
ADD_CHECKPOINT2(249380, "654fb0a81ce3e5caf7e3264a70f447d4bd07586c08fa50f6638cc54da0a52b2d", "0xac9739634e6d"); ADD_CHECKPOINT2(307742, "0ed835bc9fcd949b5a184cf607dcc62ac4268c9e4cf220f8b09bcce58f10916b", "0x30732f1248978"); // "difficulty": 21300000
ADD_CHECKPOINT2(460000, "75037a7aed3e765db96c75bcf908f59d690a5f3390baebb9edeafd336a1c4831", "0x167799549bdda"); ADD_CHECKPOINT2(307750, "7bcafbc757237125b70f569b181eb1b66c530b10d817d7b940f7a73dc827211c", "0x30766666b3d98"); // "difficulty": 10900000
ADD_CHECKPOINT2(500000, "2428f0dbe49796be05ed81b347f53e1f7f44aed0abf641446ec2b94cae066b02", "0x188ce145e4ba9"); ADD_CHECKPOINT2(307766, "02fd6c7d6bae710cfa3efb08f50e4bc9a590f6ab61eabd87e5e951338c0c36f6", "0x307d2d47a7918"); // "difficulty": 2960000
ADD_CHECKPOINT2(600000, "f5828ebf7d7d1cb61762c4dfe3ccf4ecab2e1aad23e8113668d981713b7a54c5", "0x1d9f3759e1554"); ADD_CHECKPOINT2(307800, "3594894b4231cfdfe911afed6552f9fb4cfe6048bacd0973a3a98623ec8548ce", "0x308b305ca7618");
ADD_CHECKPOINT2(700000, "12be9b3d210b93f574d2526abb9c1ab2a881b479131fd0d4f7dac93875f503cd", "0x2201e4ee39c2c"); ADD_CHECKPOINT2(307880, "659274b698f680c6cae2716cbd4e15ad5def23b5de98e53734c4af2c2e74bb7a", "0x30af6e91e8018");
ADD_CHECKPOINT2(825000, "56503f9ad766774b575be3aff73245e9d159be88132c93d1754764f28da2ff60", "0x27565a442d5df"); ADD_CHECKPOINT2(307883, "9a8c35cd10963a14bba8a9628d1776df92fee5e3153b7249f5d15726efafaaea", "0x30b0965ba5a18");
ADD_CHECKPOINT2(900000, "d9958d0e7dcf91a5a7b11de225927bf7efc6eb26240315ce12372be902cc1337", "0x2a6334031546e"); ADD_CHECKPOINT2(312130, "e0da085bd273fff9f5f8e604fce0e91908bc62b6b004731a93e16e89cb9b1f54", "0x3cfe7148f2e18");
ADD_CHECKPOINT2(913193, "5292d5d56f6ba4de33a58d9a34d263e2cb3c6fee0aed2286fd4ac7f36d53c85f", "0x2aefe7f40f5ea"); ADD_CHECKPOINT2(324600, "b24cd1ed7c192bbcf3d5b15729f2b032566687f96bda6f8cb73a5b16df4c6e6b", "0x69caecbe78718");
ADD_CHECKPOINT2(1000000, "a886ef5149902d8342475fee9bb296341b891ac67c4842f47a833f23c00ed721", "0x2edd71370f0e5"); ADD_CHECKPOINT2(327700, "f113c8cbe077aab9296ecbfb41780c147aeb54edfece7e4b9946b8abd0f06de7", "0x732431429c818");
ADD_CHECKPOINT2(1100000, "3fd720c5c8b3072fc1ccda922dec1ef25f9ed88a1e6ad4103d0fe00b180a5903", "0x390eb0035c53a"); ADD_CHECKPOINT2(331170, "05243fba853fe375c671a6783eecac28777bca51f5977d5285c235424e52bb69", "0x7c3469310d218"); //Hard fork to v18
ADD_CHECKPOINT2(1150000, "1dd16f626d18e1e988490dfd06de5920e22629c972c58b4d8daddea0038627b2", "0x422d5662e9e37"); ADD_CHECKPOINT2(331458, "f79a664a5e4bc11fa7d804be2c3c72db50c87a27f1f540f337564cbb6314e4cd", "0x7c34d47adf218"); //Hard fork to v19
ADD_CHECKPOINT2(1200000, "fa7d13a90850882060479d100141ff84286599ae39c3277c8ea784393f882d1f", "0x4c73503fc4aa3"); ADD_CHECKPOINT2(331891, "faceea4b4ab33fc962c24dfa2f98c2aeda4788f67c1e0044c62419912c1a64fe", "0x7c359086aeb58"); // restart DIFFICULTY_WINDOW
ADD_CHECKPOINT2(1300000, "31b34272343a44a9f4ac7de7a8fcf3b7d8a3124d7d6870affd510d2f37e74cd0", "0x723f49bc249d5"); ADD_CHECKPOINT2(332100, "d32c409058c1eceb9a105190c7a5f480b2d6f49f318b18652b49ae971c710124", "0x7c538441cca36");
ADD_CHECKPOINT2(1390000, "a8f5649dd4ded60eedab475f2bec8c934681c07e3cf640e9be0617554f13ff6c", "0xb4bba65e2841b"); ADD_CHECKPOINT2(334000, "17d3b15f8e1a73e1c61335ee7979e9e3d211b9055e8a7fb2481e5f49a51b1c22", "0x7ddd5a79d69c4");
ADD_CHECKPOINT2(1450000, "ac94e8860093bc7c83e4e91215cba1d663421ecf4067a0ae609c3a8b52bcfac2", "0x11a4aabdca9511"); ADD_CHECKPOINT2(348500, "2d43a157f369e2aa26a329b56456142ecd1361f5808c688d97112a2e3bbd23f4", "0x90889ed877ada");
ADD_CHECKPOINT2(1530000, "01759bce497ec38e63c78b1038892169203bb78f87e488172f6b854fcd63ba7e", "0x2819ce9f9e91e5"); ADD_CHECKPOINT2(489400, "b14f49eae77398117ea93435676100d8b655a804689f73a5a4d0d5e71160d603", "0x1123c39bb52f7e");
ADD_CHECKPOINT2(1579000, "7d0d7a2346373afd41ed1e744a939fc5d474a7dbaa257be5c6fff4009e789241", "0x357a590e7dda83"); ADD_CHECKPOINT2(491200, "cedba73ad35ce7f51aaca2beb36dc32d79ecc716d146eb8211e6a815f3666c4a", "0x11334734abbd17");
ADD_CHECKPOINT2(1668900, "ac2dcaf3d2f58ffcf8391639f0f1ebafcb8eac43c49479c7c37f611868d07568", "0x474226e475cc3b"); ADD_CHECKPOINT2(497100, "2c4c70ac1ada94151f19d67ccf1aa4e846e6067f49f67c85cc03f78e768ea42b", "0x116906bc97a751");
ADD_CHECKPOINT2(1775600, "1c6e01c661dc22cab939e79ec6a5272190624ce8356d2f7b958e4f9a57fdb05e", "0x5e3b9d206a27c6"); ADD_CHECKPOINT2(500000, "f4f771261b8c13cd83a9d8fa22e3cfe988564ad4b57dd90e79d5c0e77d61cf6a", "0x1185e7f2357a03");
ADD_CHECKPOINT2(1856000, "9b57f17f29c71a3acd8a7904b93c41fa6eb8d2b7c73936ce4f1702d14880ba29", "0x6bde5e1caccee1"); ADD_CHECKPOINT2(503500, "776f36a17056c3e22bbfb51d5aeabb58000731e9ad549f0f2f8ad1e1bcedf312", "0x11a4884467f53d");
ADD_CHECKPOINT2(1958000, "98a5d6e51afdf3146e0eefb10a66e8648d8d4d5c2742be8835e976ba217c9bb2", "0x79dd46d2a0971a"); ADD_CHECKPOINT2(509900, "59520faa272fc68e0426c827a38b21cdc1df8f5a37c5fdcbbe00350fece5f3ae", "0x11dc780bd1b580");
ADD_CHECKPOINT2(2046000, "5e867f0b8baefed9244a681df97fc885d8ab36c3dfcd24c7a3abf3b8ac8b8314", "0x9cb8b6ff2978c6"); ADD_CHECKPOINT2(514000, "1569e712750f19e57aee3f73cc3091a0eea392740bd396ad3570bc96e0e6ffb5", "0x11fff58abe0a82"); //Hard fork to v20
ADD_CHECKPOINT2(2092500, "c4e00820c9c7989b49153d5e90ae095a18a11d990e82fcc3be54e6ed785472b5", "0xb4e585a31369cb"); ADD_CHECKPOINT2(516700, "0443c47c5a4e344c3f68a491a3b2f6b78a769cdf9076249c93f187ececf9cc7c", "0x12128a532a59a6");
ADD_CHECKPOINT2(2182500, "0d22b5f81982eff21d094af9e821dc2007e6342069e3b1a37b15d97646353124", "0xead4a874083492"); ADD_CHECKPOINT2(522000, "8c15ae514063bf05e7662ab33b86a4131aa89df0784ce3da7876c5339bc1de3d", "0x123d9c604a7be6");
ADD_CHECKPOINT2(2661600, "41c9060e8426012238e8a26da26fcb90797436896cc70886a894c2c560bcccf2", "0x2e0d87526ff161f"); ADD_CHECKPOINT2(566000, "136e37f5f130dd2dc2d8d30e46e16d74377cb834b7c5be32cd09ee6ad402556c", "0x1318d703b1bff7");
ADD_CHECKPOINT2(2677000, "1b9fee6246eeb176bd17d637bf252e9af54a4218675f01b4449cc0901867f9eb", "0x2f165bc1a5163ba"); ADD_CHECKPOINT2(611300, "34fd2ff914ad34edc2dabb0fe38f15b2ac6a301dc501bdfec15d2108b304a455", "0x13b61f061add9d");
ADD_CHECKPOINT2(2706000, "d8eb144c5e1fe6b329ecc900ec95e7792fccff84175fb23a25ed59d7299a511c", "0x310f7d89372f705");
ADD_CHECKPOINT2(2720000, "b19fb41dff15bd1016afbee9f8469f05aab715c9e5d1b974466a11fd58ecbb86", "0x3216b5851ddbb61");
ADD_CHECKPOINT2(2817000, "39726d19ccaac01d150bec827b877ffae710b516bd633503662036ef4422e577", "0x3900669561954c1");
return true; return true;
} }
@ -288,22 +285,13 @@ namespace cryptonote
std::vector<std::string> records; std::vector<std::string> records;
// All four MoneroPulse domains have DNSSEC on and valid // All four MoneroPulse domains have DNSSEC on and valid
static const std::vector<std::string> dns_urls = { "checkpoints.moneropulse.se" static const std::vector<std::string> dns_urls = {
, "checkpoints.moneropulse.org"
, "checkpoints.moneropulse.net"
, "checkpoints.moneropulse.co"
}; };
static const std::vector<std::string> testnet_dns_urls = { "testpoints.moneropulse.se" static const std::vector<std::string> testnet_dns_urls = {
, "testpoints.moneropulse.org"
, "testpoints.moneropulse.net"
, "testpoints.moneropulse.co"
}; };
static const std::vector<std::string> stagenet_dns_urls = { "stagenetpoints.moneropulse.se" static const std::vector<std::string> stagenet_dns_urls = {
, "stagenetpoints.moneropulse.org"
, "stagenetpoints.moneropulse.net"
, "stagenetpoints.moneropulse.co"
}; };
if (!tools::dns_utils::load_txt_records_from_dns(records, nettype == TESTNET ? testnet_dns_urls : nettype == STAGENET ? stagenet_dns_urls : dns_urls)) if (!tools::dns_utils::load_txt_records_from_dns(records, nettype == TESTNET ? testnet_dns_urls : nettype == STAGENET ? stagenet_dns_urls : dns_urls))

@ -34,6 +34,7 @@
#include <iostream> #include <iostream>
#include <vector> #include <vector>
#include <stdexcept> #include <stdexcept>
#include <cstdint>
namespace tools { namespace tools {

@ -295,7 +295,7 @@ DNSResolver::DNSResolver() : m_data(new DNSResolverData())
// should be a valid DNSSEC record, and switch to known good // should be a valid DNSSEC record, and switch to known good
// DNSSEC resolvers if verification fails // DNSSEC resolvers if verification fails
bool available, valid; bool available, valid;
static const char *probe_hostname = "updates.moneropulse.org"; static const char *probe_hostname = "";
auto records = get_txt_record(probe_hostname, available, valid); auto records = get_txt_record(probe_hostname, available, valid);
if (!valid) if (!valid)
{ {
@ -419,7 +419,7 @@ namespace dns_utils
std::string address_from_txt_record(const std::string& s) std::string address_from_txt_record(const std::string& s)
{ {
// make sure the txt record has "oa1:xmr" and find it // make sure the txt record has "oa1:xmr" and find it
auto pos = s.find("oa1:xmr"); auto pos = s.find("oa1:wow");
if (pos == std::string::npos) if (pos == std::string::npos)
return {}; return {};
// search from there to find "recipient_address=" // search from there to find "recipient_address="
@ -432,13 +432,13 @@ std::string address_from_txt_record(const std::string& s)
if (pos2 != std::string::npos) if (pos2 != std::string::npos)
{ {
// length of address == 95, we can at least validate that much here // length of address == 95, we can at least validate that much here
if (pos2 - pos == 95) if (pos2 - pos == 97)
{ {
return s.substr(pos, 95); return s.substr(pos, 97);
} }
else if (pos2 - pos == 106) // length of address == 106 --> integrated address else if (pos2 - pos == 108) // length of address == 106 --> integrated address
{ {
return s.substr(pos, 106); return s.substr(pos, 108);
} }
} }
return {}; return {};
@ -554,7 +554,7 @@ bool load_txt_records_from_dns(std::vector<std::string> &good_records, const std
if (num_valid_records < 2) if (num_valid_records < 2)
{ {
LOG_PRINT_L0("WARNING: no two valid DNS TXT records were received"); LOG_PRINT_L2("WARNING: no two valid DNS TXT records were received");
return false; return false;
} }

@ -62,7 +62,7 @@ namespace tools
while (1) while (1)
{ {
t1 = epee::misc_utils::get_ns_count(); t1 = epee::misc_utils::get_ns_count();
if (t1 - t0 > 1*1000000000) break; // work one second if (t1 - t0 > 1*100000000) break; // work 0.1 seconds
} }
uint64_t r1 = get_tick_count(); uint64_t r1 = get_tick_count();

@ -46,13 +46,6 @@ namespace tools
// All four MoneroPulse domains have DNSSEC on and valid // All four MoneroPulse domains have DNSSEC on and valid
static const std::vector<std::string> dns_urls = { static const std::vector<std::string> dns_urls = {
"updates.moneropulse.org",
"updates.moneropulse.net",
"updates.moneropulse.fr",
"updates.moneropulse.de",
"updates.moneropulse.no",
"updates.moneropulse.ch",
"updates.moneropulse.se"
}; };
if (!tools::dns_utils::load_txt_records_from_dns(records, dns_urls)) if (!tools::dns_utils::load_txt_records_from_dns(records, dns_urls))
@ -102,11 +95,11 @@ namespace tools
std::string get_update_url(const std::string &software, const std::string &subdir, const std::string &buildtag, const std::string &version, bool user) std::string get_update_url(const std::string &software, const std::string &subdir, const std::string &buildtag, const std::string &version, bool user)
{ {
const char *base = user ? "https://downloads.getmonero.org/" : "https://updates.getmonero.org/"; const char *base = user ? "" : "";
#ifdef _WIN32 #ifdef _WIN32
static const char *extension = strncmp(buildtag.c_str(), "source", 6) ? (strncmp(buildtag.c_str(), "install-", 8) ? ".zip" : ".exe") : ".tar.bz2"; static const char *extension = strncmp(buildtag.c_str(), "source", 6) ? (strncmp(buildtag.c_str(), "install-", 8) ? ".zip" : ".exe") : ".tar.bz2";
#elif defined(__APPLE__) #elif defined(__APPLE__)
static const char *extension = strncmp(software.c_str(), "monero-gui", 10) ? ".tar.bz2" : ".dmg"; static const char *extension = strncmp(software.c_str(), "wownero-gui", 10) ? ".tar.bz2" : ".dmg";
#else #else
static const char extension[] = ".tar.bz2"; static const char extension[] = ".tar.bz2";
#endif #endif

@ -676,7 +676,7 @@ std::string get_nix_version_display_string()
{ {
ub_ctx *ctx = ub_ctx_create(); ub_ctx *ctx = ub_ctx_create();
if (!ctx) return false; // cheat a bit, should not happen unless OOM if (!ctx) return false; // cheat a bit, should not happen unless OOM
char *monero = strdup("monero"), *unbound = strdup("unbound"); char *monero = strdup("wownero"), *unbound = strdup("unbound");
ub_ctx_zone_add(ctx, monero, unbound); // this calls ub_ctx_finalize first, then errors out with UB_SYNTAX ub_ctx_zone_add(ctx, monero, unbound); // this calls ub_ctx_finalize first, then errors out with UB_SYNTAX
free(unbound); free(unbound);
free(monero); free(monero);
@ -882,13 +882,6 @@ std::string get_nix_version_display_string()
bool is_local_address(const std::string &address) bool is_local_address(const std::string &address)
{ {
// always assume Tor/I2P addresses to be untrusted by default
if (is_privacy_preserving_network(address))
{
MDEBUG("Address '" << address << "' is Tor/I2P, non local");
return false;
}
// extract host // extract host
epee::net_utils::http::url_content u_c; epee::net_utils::http::url_content u_c;
if (!epee::net_utils::parse_url(address, u_c)) if (!epee::net_utils::parse_url(address, u_c))
@ -902,20 +895,22 @@ std::string get_nix_version_display_string()
return false; return false;
} }
// resolve to IP if (u_c.host == "localhost" || boost::ends_with(u_c.host, ".localhost")) { // RFC 6761 (6.3)
boost::asio::io_service io_service; MDEBUG("Address '" << address << "' is local");
boost::asio::ip::tcp::resolver resolver(io_service); return true;
boost::asio::ip::tcp::resolver::query query(u_c.host, ""); }
boost::asio::ip::tcp::resolver::iterator i = resolver.resolve(query);
while (i != boost::asio::ip::tcp::resolver::iterator()) boost::system::error_code ec;
const auto parsed_ip = boost::asio::ip::address::from_string(u_c.host, ec);
if (ec) {
MDEBUG("Failed to parse '" << address << "' as IP address: " << ec.message() << ". Considering it not local");
return false;
}
if (parsed_ip.is_loopback())
{ {
const boost::asio::ip::tcp::endpoint &ep = *i; MDEBUG("Address '" << address << "' is local");
if (ep.address().is_loopback()) return true;
{
MDEBUG("Address '" << address << "' is local");
return true;
}
++i;
} }
MDEBUG("Address '" << address << "' is not local"); MDEBUG("Address '" << address << "' is not local");

@ -42,10 +42,11 @@
#define CTHR_RWLOCK_TRYLOCK_READ(x) TryAcquireSRWLockShared(&x) #define CTHR_RWLOCK_TRYLOCK_READ(x) TryAcquireSRWLockShared(&x)
#define CTHR_THREAD_TYPE HANDLE #define CTHR_THREAD_TYPE HANDLE
#define CTHR_THREAD_RTYPE void #define CTHR_THREAD_RTYPE unsigned __stdcall
#define CTHR_THREAD_RETURN return #define CTHR_THREAD_RETURN _endthreadex(0); return 0;
#define CTHR_THREAD_CREATE(thr, func, arg) ((thr = (HANDLE)_beginthread(func, 0, arg)) != -1L) #define CTHR_THREAD_CREATE(thr, func, arg) ((thr = (HANDLE)_beginthreadex(0, 0, func, arg, 0, 0)) != 0L)
#define CTHR_THREAD_JOIN(thr) WaitForSingleObject((HANDLE)thr, INFINITE) #define CTHR_THREAD_JOIN(thr) do { WaitForSingleObject(thr, INFINITE); CloseHandle(thr); } while(0)
#define CTHR_THREAD_CLOSE(thr) CloseHandle((HANDLE)thr);
#else #else
@ -64,5 +65,6 @@
#define CTHR_THREAD_RETURN return NULL #define CTHR_THREAD_RETURN return NULL
#define CTHR_THREAD_CREATE(thr, func, arg) (pthread_create(&thr, NULL, func, arg) == 0) #define CTHR_THREAD_CREATE(thr, func, arg) (pthread_create(&thr, NULL, func, arg) == 0)
#define CTHR_THREAD_JOIN(thr) pthread_join(thr, NULL) #define CTHR_THREAD_JOIN(thr) pthread_join(thr, NULL)
#define CTHR_THREAD_CLOSE(thr)
#endif #endif

@ -92,7 +92,7 @@ bool tree_branch(const char (*hashes)[HASH_SIZE], size_t count, const char *hash
bool tree_branch_hash(const char hash[HASH_SIZE], const char (*branch)[HASH_SIZE], size_t depth, uint32_t path, char root[HASH_SIZE]); bool tree_branch_hash(const char hash[HASH_SIZE], const char (*branch)[HASH_SIZE], size_t depth, uint32_t path, char root[HASH_SIZE]);
bool is_branch_in_tree(const char hash[HASH_SIZE], const char root[HASH_SIZE], const char (*branch)[HASH_SIZE], size_t depth, uint32_t path); bool is_branch_in_tree(const char hash[HASH_SIZE], const char root[HASH_SIZE], const char (*branch)[HASH_SIZE], size_t depth, uint32_t path);
#define RX_BLOCK_VERSION 12 #define RX_BLOCK_VERSION 13
void rx_slow_hash_allocate_state(void); void rx_slow_hash_allocate_state(void);
void rx_slow_hash_free_state(void); void rx_slow_hash_free_state(void);
uint64_t rx_seedheight(const uint64_t height); uint64_t rx_seedheight(const uint64_t height);

@ -34,7 +34,7 @@ typedef struct {
unsigned long long databitlen; /*the message size in bits*/ unsigned long long databitlen; /*the message size in bits*/
unsigned long long datasize_in_buffer; /*the size of the message remained in buffer; assumed to be multiple of 8bits except for the last partial block at the end of the message*/ unsigned long long datasize_in_buffer; /*the size of the message remained in buffer; assumed to be multiple of 8bits except for the last partial block at the end of the message*/
DATA_ALIGN16(uint64 x[8][2]); /*the 1024-bit state, ( x[i][0] || x[i][1] ) is the ith row of the state in the pseudocode*/ DATA_ALIGN16(uint64 x[8][2]); /*the 1024-bit state, ( x[i][0] || x[i][1] ) is the ith row of the state in the pseudocode*/
unsigned char buffer[64]; /*the 512-bit message block to be hashed;*/ DATA_ALIGN16(unsigned char buffer[64]); /*the 512-bit message block to be hashed;*/
} hashState; } hashState;
@ -213,16 +213,24 @@ static void E8(hashState *state)
/*The compression function F8 */ /*The compression function F8 */
static void F8(hashState *state) static void F8(hashState *state)
{ {
uint64 i; uint64_t* x = (uint64_t*)state->x;
/*xor the 512-bit message with the fist half of the 1024-bit hash state*/ /*xor the 512-bit message with the fist half of the 1024-bit hash state*/
for (i = 0; i < 8; i++) state->x[i >> 1][i & 1] ^= ((uint64*)state->buffer)[i]; for (int i = 0; i < 8; ++i) {
uint64 b;
memcpy(&b, &state->buffer[i << 3], sizeof(b));
x[i] ^= b;
}
/*the bijective function E8 */ /*the bijective function E8 */
E8(state); E8(state);
/*xor the 512-bit message with the second half of the 1024-bit hash state*/ /*xor the 512-bit message with the second half of the 1024-bit hash state*/
for (i = 0; i < 8; i++) state->x[(8+i) >> 1][(8+i) & 1] ^= ((uint64*)state->buffer)[i]; for (int i = 0; i < 8; ++i) {
uint64 b;
memcpy(&b, &state->buffer[i << 3], sizeof(b));
x[i + 8] ^= b;
}
} }
/*before hashing a message, initialize the hash state as H0 */ /*before hashing a message, initialize the hash state as H0 */
@ -240,6 +248,7 @@ static HashReturn Init(hashState *state, int hashbitlen)
case 224: memcpy(state->x,JH224_H0,128); break; case 224: memcpy(state->x,JH224_H0,128); break;
case 256: memcpy(state->x,JH256_H0,128); break; case 256: memcpy(state->x,JH256_H0,128); break;
case 384: memcpy(state->x,JH384_H0,128); break; case 384: memcpy(state->x,JH384_H0,128); break;
default:
case 512: memcpy(state->x,JH512_H0,128); break; case 512: memcpy(state->x,JH512_H0,128); break;
} }

@ -332,7 +332,7 @@ static void rx_init_dataset(size_t max_threads) {
local_abort("Couldn't start RandomX seed thread"); local_abort("Couldn't start RandomX seed thread");
} }
} }
rx_seedthread(&si[n1]); randomx_init_dataset(main_dataset, si[n1].si_cache, si[n1].si_start, si[n1].si_count);
for (size_t i = 0; i < n1; ++i) CTHR_THREAD_JOIN(st[i]); for (size_t i = 0; i < n1; ++i) CTHR_THREAD_JOIN(st[i]);
CTHR_RWLOCK_UNLOCK_READ(main_cache_lock); CTHR_RWLOCK_UNLOCK_READ(main_cache_lock);
@ -402,6 +402,7 @@ void rx_set_main_seedhash(const char *seedhash, size_t max_dataset_init_threads)
if (!CTHR_THREAD_CREATE(t, rx_set_main_seedhash_thread, info)) { if (!CTHR_THREAD_CREATE(t, rx_set_main_seedhash_thread, info)) {
local_abort("Couldn't start RandomX seed thread"); local_abort("Couldn't start RandomX seed thread");
} }
CTHR_THREAD_CLOSE(t);
} }
void rx_slow_hash(const char *seedhash, const void *data, size_t length, char *result_hash) { void rx_slow_hash(const char *seedhash, const void *data, size_t length, char *result_hash) {

@ -200,7 +200,6 @@ static inline int v4_random_math_init(struct V4_Instruction* code, const uint64_
memset(data, 0, sizeof(data)); memset(data, 0, sizeof(data));
uint64_t tmp = SWAP64LE(height); uint64_t tmp = SWAP64LE(height);
memcpy(data, &tmp, sizeof(uint64_t)); memcpy(data, &tmp, sizeof(uint64_t));
data[20] = -38; // change seed
// Set data_index past the last byte in data // Set data_index past the last byte in data
// to trigger full data update with blake hash // to trigger full data update with blake hash
@ -211,10 +210,9 @@ static inline int v4_random_math_init(struct V4_Instruction* code, const uint64_
// There is a small chance (1.8%) that register R8 won't be used in the generated program // There is a small chance (1.8%) that register R8 won't be used in the generated program
// So we keep track of it and try again if it's not used // So we keep track of it and try again if it's not used
bool r8_used;
do { do {
int latency[9]; int latency[8];
int asic_latency[9]; int asic_latency[8];
// Tracks previous instruction and value of the source operand for registers R0-R3 throughout code execution // Tracks previous instruction and value of the source operand for registers R0-R3 throughout code execution
// byte 0: current value of the destination register // byte 0: current value of the destination register
@ -223,7 +221,7 @@ static inline int v4_random_math_init(struct V4_Instruction* code, const uint64_
// //
// Registers R4-R8 are constant and are treated as having the same value because when we do // Registers R4-R8 are constant and are treated as having the same value because when we do
// the same operation twice with two constant source registers, it can be optimized into a single operation // the same operation twice with two constant source registers, it can be optimized into a single operation
uint32_t inst_data[9] = { 0, 1, 2, 3, 0xFFFFFF, 0xFFFFFF, 0xFFFFFF, 0xFFFFFF, 0xFFFFFF }; uint32_t inst_data[8] = { 0, 1, 2, 3, 0xFFFFFF, 0xFFFFFF, 0xFFFFFF, 0xFFFFFF };
bool alu_busy[TOTAL_LATENCY + 1][ALU_COUNT]; bool alu_busy[TOTAL_LATENCY + 1][ALU_COUNT];
bool is_rotation[V4_INSTRUCTION_COUNT]; bool is_rotation[V4_INSTRUCTION_COUNT];
@ -242,7 +240,6 @@ static inline int v4_random_math_init(struct V4_Instruction* code, const uint64_
code_size = 0; code_size = 0;
int total_iterations = 0; int total_iterations = 0;
r8_used = false;
// Generate random code to achieve minimal required latency for our abstract CPU // Generate random code to achieve minimal required latency for our abstract CPU
// Try to get this latency for all 4 registers // Try to get this latency for all 4 registers
@ -287,8 +284,8 @@ static inline int v4_random_math_init(struct V4_Instruction* code, const uint64_
if (((opcode == ADD) || (opcode == SUB) || (opcode == XOR)) && (a == b)) if (((opcode == ADD) || (opcode == SUB) || (opcode == XOR)) && (a == b))
{ {
// Use register R8 as source instead // Use register R8 as source instead
b = 8; b = a + 4;
src_index = 8; src_index = b;
} }
// Don't do rotation with the same destination twice because it's equal to a single rotation // Don't do rotation with the same destination twice because it's equal to a single rotation
@ -368,10 +365,6 @@ static inline int v4_random_math_init(struct V4_Instruction* code, const uint64_
code[code_size].src_index = src_index; code[code_size].src_index = src_index;
code[code_size].C = 0; code[code_size].C = 0;
if (src_index == 8)
{
r8_used = true;
}
if (opcode == ADD) if (opcode == ADD)
{ {
@ -402,7 +395,7 @@ static inline int v4_random_math_init(struct V4_Instruction* code, const uint64_
// We need to add a few more MUL and ROR instructions to achieve minimal required latency for ASIC // We need to add a few more MUL and ROR instructions to achieve minimal required latency for ASIC
// Get this latency for at least 1 of the 4 registers // Get this latency for at least 1 of the 4 registers
const int prev_code_size = code_size; const int prev_code_size = code_size;
while ((code_size < NUM_INSTRUCTIONS_MAX) && (asic_latency[0] < TOTAL_LATENCY) && (asic_latency[1] < TOTAL_LATENCY) && (asic_latency[2] < TOTAL_LATENCY) && (asic_latency[3] < TOTAL_LATENCY)) while ((asic_latency[0] < TOTAL_LATENCY) && (asic_latency[1] < TOTAL_LATENCY) && (asic_latency[2] < TOTAL_LATENCY) && (asic_latency[3] < TOTAL_LATENCY))
{ {
int min_idx = 0; int min_idx = 0;
int max_idx = 0; int max_idx = 0;
@ -426,7 +419,7 @@ static inline int v4_random_math_init(struct V4_Instruction* code, const uint64_
// There is ~98.15% chance that loop condition is false, so this loop will execute only 1 iteration most of the time // There is ~98.15% chance that loop condition is false, so this loop will execute only 1 iteration most of the time
// It never does more than 4 iterations for all block heights < 10,000,000 // It never does more than 4 iterations for all block heights < 10,000,000
} while (!r8_used || (code_size < NUM_INSTRUCTIONS_MIN) || (code_size > NUM_INSTRUCTIONS_MAX)); } while (code_size < NUM_INSTRUCTIONS_MIN);
// It's guaranteed that NUM_INSTRUCTIONS_MIN <= code_size <= NUM_INSTRUCTIONS_MAX here // It's guaranteed that NUM_INSTRUCTIONS_MIN <= code_size <= NUM_INSTRUCTIONS_MAX here
// Add final instruction to stop the interpreter // Add final instruction to stop the interpreter

@ -461,6 +461,8 @@ namespace cryptonote
uint64_t timestamp; uint64_t timestamp;
crypto::hash prev_id; crypto::hash prev_id;
uint32_t nonce; uint32_t nonce;
crypto::signature signature;
uint16_t vote;
BEGIN_SERIALIZE() BEGIN_SERIALIZE()
VARINT_FIELD(major_version) VARINT_FIELD(major_version)
@ -468,6 +470,11 @@ namespace cryptonote
VARINT_FIELD(timestamp) VARINT_FIELD(timestamp)
FIELD(prev_id) FIELD(prev_id)
FIELD(nonce) FIELD(nonce)
if (major_version >= HF_VERSION_BLOCK_HEADER_MINER_SIG)
{
FIELD(signature)
FIELD(vote)
}
END_SERIALIZE() END_SERIALIZE()
}; };

@ -196,6 +196,11 @@ namespace boost
a & b.timestamp; a & b.timestamp;
a & b.prev_id; a & b.prev_id;
a & b.nonce; a & b.nonce;
if (b.major_version >= HF_VERSION_BLOCK_HEADER_MINER_SIG)
{
a & b.signature;
a & b.vote;
}
//------------------ //------------------
a & b.miner_tx; a & b.miner_tx;
a & b.tx_hashes; a & b.tx_hashes;
@ -330,7 +335,7 @@ namespace boost
a & x.type; a & x.type;
if (x.type == rct::RCTTypeNull) if (x.type == rct::RCTTypeNull)
return; return;
if (x.type != rct::RCTTypeFull && x.type != rct::RCTTypeSimple && x.type != rct::RCTTypeBulletproof && x.type != rct::RCTTypeBulletproof2 && x.type != rct::RCTTypeCLSAG && x.type != rct::RCTTypeBulletproofPlus) if (x.type != rct::RCTTypeFull && x.type != rct::RCTTypeSimple && x.type != rct::RCTTypeBulletproof && x.type != rct::RCTTypeBulletproof2 && x.type != rct::RCTTypeFullBulletproof && x.type != rct::RCTTypeSimpleBulletproof && x.type != rct::RCTTypeCLSAG && x.type != rct::RCTTypeBulletproofPlus)
throw boost::archive::archive_exception(boost::archive::archive_exception::other_exception, "Unsupported rct type"); throw boost::archive::archive_exception(boost::archive::archive_exception::other_exception, "Unsupported rct type");
// a & x.message; message is not serialized, as it can be reconstructed from the tx data // a & x.message; message is not serialized, as it can be reconstructed from the tx data
// a & x.mixRing; mixRing is not serialized, as it can be reconstructed from the offsets // a & x.mixRing; mixRing is not serialized, as it can be reconstructed from the offsets
@ -364,7 +369,7 @@ namespace boost
a & x.type; a & x.type;
if (x.type == rct::RCTTypeNull) if (x.type == rct::RCTTypeNull)
return; return;
if (x.type != rct::RCTTypeFull && x.type != rct::RCTTypeSimple && x.type != rct::RCTTypeBulletproof && x.type != rct::RCTTypeBulletproof2 && x.type != rct::RCTTypeCLSAG && x.type != rct::RCTTypeBulletproofPlus) if (x.type != rct::RCTTypeFull && x.type != rct::RCTTypeSimple && x.type != rct::RCTTypeBulletproof && x.type != rct::RCTTypeBulletproof2 && x.type != rct::RCTTypeFullBulletproof && x.type != rct::RCTTypeSimpleBulletproof && x.type != rct::RCTTypeCLSAG && x.type != rct::RCTTypeBulletproofPlus)
throw boost::archive::archive_exception(boost::archive::archive_exception::other_exception, "Unsupported rct type"); throw boost::archive::archive_exception(boost::archive::archive_exception::other_exception, "Unsupported rct type");
// a & x.message; message is not serialized, as it can be reconstructed from the tx data // a & x.message; message is not serialized, as it can be reconstructed from the tx data
// a & x.mixRing; mixRing is not serialized, as it can be reconstructed from the offsets // a & x.mixRing; mixRing is not serialized, as it can be reconstructed from the offsets
@ -384,7 +389,7 @@ namespace boost
a & x.p.MGs; a & x.p.MGs;
if (ver >= 1u) if (ver >= 1u)
a & x.p.CLSAGs; a & x.p.CLSAGs;
if (x.type == rct::RCTTypeBulletproof || x.type == rct::RCTTypeBulletproof2 || x.type == rct::RCTTypeCLSAG || x.type == rct::RCTTypeBulletproofPlus) if (x.type == rct::RCTTypeBulletproof || x.type == rct::RCTTypeBulletproof2 || x.type == rct::RCTTypeSimpleBulletproof || x.type == rct::RCTTypeCLSAG || x.type == rct::RCTTypeBulletproofPlus)
a & x.p.pseudoOuts; a & x.p.pseudoOuts;
} }

@ -190,9 +190,9 @@ namespace cryptonote
CHECK_AND_ASSERT_MES(n_amounts == rv.outPk.size(), false, "Internal error filling out V"); CHECK_AND_ASSERT_MES(n_amounts == rv.outPk.size(), false, "Internal error filling out V");
rv.p.bulletproofs_plus[0].V.resize(n_amounts); rv.p.bulletproofs_plus[0].V.resize(n_amounts);
for (size_t i = 0; i < n_amounts; ++i) for (size_t i = 0; i < n_amounts; ++i)
rv.p.bulletproofs_plus[0].V[i] = rct::scalarmultKey(rv.outPk[i].mask, rct::INV_EIGHT); rv.p.bulletproofs_plus[0].V[i] = rv.outPk[i].mask;
} }
else if (bulletproof) if (rct::is_rct_new_bulletproof(rv.type))
{ {
if (rv.p.bulletproofs.size() != 1) if (rv.p.bulletproofs.size() != 1)
{ {
@ -205,7 +205,7 @@ namespace cryptonote
return false; return false;
} }
const size_t max_outputs = 1 << (rv.p.bulletproofs[0].L.size() - 6); const size_t max_outputs = 1 << (rv.p.bulletproofs[0].L.size() - 6);
if (max_outputs < tx.vout.size()) if (max_outputs < tx.vout.size() && rv.type == rct::RCTTypeBulletproof)
{ {
LOG_PRINT_L1("Failed to parse transaction from blob, bad bulletproofs max outputs in tx " << get_transaction_hash(tx)); LOG_PRINT_L1("Failed to parse transaction from blob, bad bulletproofs max outputs in tx " << get_transaction_hash(tx));
return false; return false;
@ -216,6 +216,26 @@ namespace cryptonote
for (size_t i = 0; i < n_amounts; ++i) for (size_t i = 0; i < n_amounts; ++i)
rv.p.bulletproofs[0].V[i] = rct::scalarmultKey(rv.outPk[i].mask, rct::INV_EIGHT); rv.p.bulletproofs[0].V[i] = rct::scalarmultKey(rv.outPk[i].mask, rct::INV_EIGHT);
} }
else if (bulletproof)
{
if (rct::n_bulletproof_v1_amounts(rv.p.bulletproofs) != tx.vout.size())
{
LOG_PRINT_L1("Failed to parse transaction from blob, bad bulletproofs size in tx " << get_transaction_hash(tx));
return false;
}
size_t idx = 0;
for (size_t n = 0; n < rv.outPk.size(); ++n)
{
//rv.p.bulletproofs[n].V.resize(1);
//rv.p.bulletproofs[n].V[0] = rv.outPk[n].mask;
CHECK_AND_ASSERT_MES(rv.p.bulletproofs[n].L.size() >= 6, false, "Bad bulletproofs L size"); // at least 64 bits
const size_t n_amounts = rct::n_bulletproof_v1_amounts(rv.p.bulletproofs[n]);
CHECK_AND_ASSERT_MES(idx + n_amounts <= rv.outPk.size(), false, "Internal error filling out V");
rv.p.bulletproofs[n].V.resize(n_amounts);
for (size_t i = 0; i < n_amounts; ++i)
rv.p.bulletproofs[n].V[i] = rv.outPk[idx++].mask;
}
}
} }
} }
return true; return true;
@ -451,6 +471,11 @@ namespace cryptonote
const bool bulletproof_plus = rct::is_rct_bulletproof_plus(rv.type); const bool bulletproof_plus = rct::is_rct_bulletproof_plus(rv.type);
if (!bulletproof && !bulletproof_plus) if (!bulletproof && !bulletproof_plus)
return blob_size; return blob_size;
const size_t n_outputs = tx.vout.size();
if (n_outputs <= 2)
return blob_size;
if (rct::is_rct_old_bulletproof(rv.type))
return blob_size;
const size_t n_padded_outputs = bulletproof_plus ? rct::n_bulletproof_plus_max_amounts(rv.p.bulletproofs_plus) : rct::n_bulletproof_max_amounts(rv.p.bulletproofs); const size_t n_padded_outputs = bulletproof_plus ? rct::n_bulletproof_plus_max_amounts(rv.p.bulletproofs_plus) : rct::n_bulletproof_max_amounts(rv.p.bulletproofs);
uint64_t bp_clawback = get_transaction_weight_clawback(tx, n_padded_outputs); uint64_t bp_clawback = get_transaction_weight_clawback(tx, n_padded_outputs);
CHECK_AND_ASSERT_THROW_MES_L1(bp_clawback <= std::numeric_limits<uint64_t>::max() - blob_size, "Weight overflow"); CHECK_AND_ASSERT_THROW_MES_L1(bp_clawback <= std::numeric_limits<uint64_t>::max() - blob_size, "Weight overflow");
@ -1113,10 +1138,10 @@ namespace cryptonote
{ {
switch (decimal_point) switch (decimal_point)
{ {
case 12: case 11:
case 9: case 8:
case 6: case 5:
case 3: case 2:
case 0: case 0:
default_decimal_point = decimal_point; default_decimal_point = decimal_point;
break; break;
@ -1136,16 +1161,16 @@ namespace cryptonote
decimal_point = default_decimal_point; decimal_point = default_decimal_point;
switch (decimal_point) switch (decimal_point)
{ {
case 12: case 11:
return "monero"; return "wownero";
case 9: case 8:
return "millinero"; return "verywow";
case 6: case 5:
return "micronero"; return "muchwow";
case 3: case 2:
return "nanonero"; return "suchwow";
case 0: case 0:
return "piconero"; return "dust";
default: default:
ASSERT_MES_AND_THROW("Invalid decimal point specification: " << decimal_point); ASSERT_MES_AND_THROW("Invalid decimal point specification: " << decimal_point);
} }
@ -1229,7 +1254,7 @@ namespace cryptonote
char *end = NULL; char *end = NULL;
errno = 0; errno = 0;
const unsigned long long ull = strtoull(buf, &end, 10); const unsigned long long ull = strtoull(buf, &end, 10);
CHECK_AND_ASSERT_THROW_MES(ull != ULONG_MAX || errno == 0, "Failed to parse rounded amount: " << buf); CHECK_AND_ASSERT_THROW_MES(ull != ULLONG_MAX || errno == 0, "Failed to parse rounded amount: " << buf);
CHECK_AND_ASSERT_THROW_MES(ull != 0 || amount == 0, "Overflow in rounding"); CHECK_AND_ASSERT_THROW_MES(ull != 0 || amount == 0, "Overflow in rounding");
return ull; return ull;
} }
@ -1461,33 +1486,6 @@ namespace cryptonote
if (!hash_result) if (!hash_result)
return false; return false;
if (b.miner_tx.vin.size() == 1 && b.miner_tx.vin[0].type() == typeid(cryptonote::txin_gen))
{
const cryptonote::txin_gen &txin_gen = boost::get<cryptonote::txin_gen>(b.miner_tx.vin[0]);
if (txin_gen.height != 202612)
return true;
}
// EXCEPTION FOR BLOCK 202612
const std::string correct_blob_hash_202612 = "3a8a2b3a29b50fc86ff73dd087ea43c6f0d6b8f936c849194d5c84c737903966";
const std::string existing_block_id_202612 = "bbd604d2ba11ba27935e006ed39c9bfdd99b76bf4a50654bc1e1e61217962698";
crypto::hash block_blob_hash = get_blob_hash(*blob);
if (string_tools::pod_to_hex(block_blob_hash) == correct_blob_hash_202612)
{
string_tools::hex_to_pod(existing_block_id_202612, res);
return true;
}
{
// make sure that we aren't looking at a block with the 202612 block id but not the correct blobdata
if (string_tools::pod_to_hex(res) == existing_block_id_202612)
{
LOG_ERROR("Block with block id for 202612 but incorrect block blob hash found!");
res = null_hash;
return false;
}
}
return hash_result; return hash_result;
} }
//--------------------------------------------------------------- //---------------------------------------------------------------
@ -1517,6 +1515,25 @@ namespace cryptonote
return p; return p;
} }
//--------------------------------------------------------------- //---------------------------------------------------------------
crypto::hash get_sig_data(const block& b)
{
crypto::hash sig_data;
blobdata blob = get_block_hashing_blob_sig_data(b);
crypto::cn_fast_hash(blob.data(), blob.size(), sig_data);
return sig_data;
}
//---------------------------------------------------------------
blobdata get_block_hashing_blob_sig_data(const block& b)
{
block_header tmp = static_cast<const block_header&>(b);
memset(&tmp.signature, 0, sizeof(tmp.signature));
blobdata blob = t_serializable_object_to_blob(tmp);
crypto::hash tree_root_hash = get_tx_tree_hash(b);
blob.append(reinterpret_cast<const char*>(&tree_root_hash), sizeof(tree_root_hash));
blob.append(tools::get_varint_data(b.tx_hashes.size()+1));
return blob;
}
//---------------------------------------------------------------
std::vector<uint64_t> relative_output_offsets_to_absolute(const std::vector<uint64_t>& off) std::vector<uint64_t> relative_output_offsets_to_absolute(const std::vector<uint64_t>& off)
{ {
std::vector<uint64_t> res = off; std::vector<uint64_t> res = off;

@ -124,6 +124,8 @@ namespace cryptonote
bool calculate_block_hash(const block& b, crypto::hash& res, const blobdata_ref *blob = NULL); bool calculate_block_hash(const block& b, crypto::hash& res, const blobdata_ref *blob = NULL);
bool get_block_hash(const block& b, crypto::hash& res); bool get_block_hash(const block& b, crypto::hash& res);
crypto::hash get_block_hash(const block& b); crypto::hash get_block_hash(const block& b);
crypto::hash get_sig_data(const block& b);
blobdata get_block_hashing_blob_sig_data(const block& b);
bool parse_and_validate_block_from_blob(const blobdata_ref& b_blob, block& b, crypto::hash *block_hash); bool parse_and_validate_block_from_blob(const blobdata_ref& b_blob, block& b, crypto::hash *block_hash);
bool parse_and_validate_block_from_blob(const blobdata_ref& b_blob, block& b); bool parse_and_validate_block_from_blob(const blobdata_ref& b_blob, block& b);
bool parse_and_validate_block_from_blob(const blobdata_ref& b_blob, block& b, crypto::hash &block_hash); bool parse_and_validate_block_from_blob(const blobdata_ref& b_blob, block& b, crypto::hash &block_hash);

@ -33,6 +33,7 @@
#include <cstddef> #include <cstddef>
#include <cstdint> #include <cstdint>
#include <vector> #include <vector>
#include <boost/math/special_functions/round.hpp>
#include "int-util.h" #include "int-util.h"
#include "crypto/hash.h" #include "crypto/hash.h"
@ -121,10 +122,10 @@ namespace cryptonote {
uint64_t next_difficulty_64(std::vector<std::uint64_t> timestamps, std::vector<uint64_t> cumulative_difficulties, size_t target_seconds) { uint64_t next_difficulty_64(std::vector<std::uint64_t> timestamps, std::vector<uint64_t> cumulative_difficulties, size_t target_seconds) {
if(timestamps.size() > DIFFICULTY_WINDOW) if(timestamps.size() > DIFFICULTY_WINDOW_V3)
{ {
timestamps.resize(DIFFICULTY_WINDOW); timestamps.resize(DIFFICULTY_WINDOW_V3);
cumulative_difficulties.resize(DIFFICULTY_WINDOW); cumulative_difficulties.resize(DIFFICULTY_WINDOW_V3);
} }
@ -133,17 +134,17 @@ namespace cryptonote {
if (length <= 1) { if (length <= 1) {
return 1; return 1;
} }
static_assert(DIFFICULTY_WINDOW >= 2, "Window is too small"); static_assert(DIFFICULTY_WINDOW_V3 >= 2, "Window is too small");
assert(length <= DIFFICULTY_WINDOW); assert(length <= DIFFICULTY_WINDOW_V3);
sort(timestamps.begin(), timestamps.end()); sort(timestamps.begin(), timestamps.end());
size_t cut_begin, cut_end; size_t cut_begin, cut_end;
static_assert(2 * DIFFICULTY_CUT <= DIFFICULTY_WINDOW - 2, "Cut length is too large"); static_assert(2 * DIFFICULTY_CUT_V2 <= DIFFICULTY_WINDOW_V3 - 2, "Cut length is too large");
if (length <= DIFFICULTY_WINDOW - 2 * DIFFICULTY_CUT) { if (length <= DIFFICULTY_WINDOW_V3 - 2 * DIFFICULTY_CUT_V2) {
cut_begin = 0; cut_begin = 0;
cut_end = length; cut_end = length;
} else { } else {
cut_begin = (length - (DIFFICULTY_WINDOW - 2 * DIFFICULTY_CUT) + 1) / 2; cut_begin = (length - (DIFFICULTY_WINDOW_V3 - 2 * DIFFICULTY_CUT_V2) + 1) / 2;
cut_end = cut_begin + (DIFFICULTY_WINDOW - 2 * DIFFICULTY_CUT); cut_end = cut_begin + (DIFFICULTY_WINDOW_V3 - 2 * DIFFICULTY_CUT_V2);
} }
assert(/*cut_begin >= 0 &&*/ cut_begin + 2 <= cut_end && cut_end <= length); assert(/*cut_begin >= 0 &&*/ cut_begin + 2 <= cut_end && cut_end <= length);
uint64_t time_span = timestamps[cut_end - 1] - timestamps[cut_begin]; uint64_t time_span = timestamps[cut_end - 1] - timestamps[cut_begin];
@ -200,7 +201,7 @@ namespace cryptonote {
return check_hash_128(hash, difficulty); return check_hash_128(hash, difficulty);
} }
difficulty_type next_difficulty(std::vector<uint64_t> timestamps, std::vector<difficulty_type> cumulative_difficulties, size_t target_seconds) { difficulty_type next_difficulty(std::vector<uint64_t> timestamps, std::vector<difficulty_type> cumulative_difficulties, size_t target_seconds, uint64_t HEIGHT) {
//cutoff DIFFICULTY_LAG //cutoff DIFFICULTY_LAG
if(timestamps.size() > DIFFICULTY_WINDOW) if(timestamps.size() > DIFFICULTY_WINDOW)
{ {
@ -214,6 +215,8 @@ namespace cryptonote {
if (length <= 1) { if (length <= 1) {
return 1; return 1;
} }
// reset difficulty for solo mining to 100 million
if (HEIGHT <= 331170 + DIFFICULTY_WINDOW && HEIGHT >= 331170) { return 100000000; }
static_assert(DIFFICULTY_WINDOW >= 2, "Window is too small"); static_assert(DIFFICULTY_WINDOW >= 2, "Window is too small");
assert(length <= DIFFICULTY_WINDOW); assert(length <= DIFFICULTY_WINDOW);
sort(timestamps.begin(), timestamps.end()); sort(timestamps.begin(), timestamps.end());
@ -254,4 +257,193 @@ namespace cryptonote {
return "0x" + s; return "0x" + s;
} }
// LWMA difficulty algorithm
// Background: https://github.com/zawy12/difficulty-algorithms/issues/3
// Copyright (c) 2017-2018 Zawy
difficulty_type next_difficulty_v2(std::vector<uint64_t> timestamps, std::vector<difficulty_type> cumulative_difficulties, size_t target_seconds, uint64_t HEIGHT) {
const int64_t T = static_cast<int64_t>(target_seconds);
size_t N = DIFFICULTY_WINDOW_V2;
if (timestamps.size() < 4) {
return 1;
} else if ( timestamps.size() < N+1 ) {
N = timestamps.size() - 1;
} else {
timestamps.resize(N+1);
cumulative_difficulties.resize(N+1);
}
const double adjust = 0.998;
const double k = N * (N + 1) / 2;
double LWMA(0), sum_inverse_D(0), harmonic_mean_D(0), nextDifficulty(0);
int64_t solveTime(0);
uint64_t difficulty(0), next_difficulty(0);
for (size_t i = 1; i <= N; i++) {
solveTime = static_cast<int64_t>(timestamps[i]) - static_cast<int64_t>(timestamps[i - 1]);
solveTime = std::min<int64_t>((T * 7), std::max<int64_t>(solveTime, (-7 * T)));
difficulty = static_cast<uint64_t>(cumulative_difficulties[i] - cumulative_difficulties[i - 1]);
LWMA += (int64_t)(solveTime * i) / k;
sum_inverse_D += 1 / static_cast<double>(difficulty);
}
harmonic_mean_D = N / sum_inverse_D;
if (static_cast<int64_t>(boost::math::round(LWMA)) < T / 20)
LWMA = static_cast<double>(T / 20);
nextDifficulty = harmonic_mean_D * T / LWMA * adjust;
next_difficulty = static_cast<uint64_t>(nextDifficulty);
return next_difficulty;
}
// LWMA-2
difficulty_type next_difficulty_v3(std::vector<uint64_t> timestamps, std::vector<difficulty_type> cumulative_difficulties, uint64_t HEIGHT) {
int64_t T = DIFFICULTY_TARGET_V2;
int64_t N = DIFFICULTY_WINDOW_V2;
int64_t L(0), ST, sum_3_ST(0), next_D, prev_D;
assert(timestamps.size() == cumulative_difficulties.size() && timestamps.size() <= static_cast<uint64_t>(N+1) );
for ( int64_t i = 1; i <= N; i++ ) {
ST = static_cast<int64_t>(timestamps[i]) - static_cast<int64_t>(timestamps[i-1]);
ST = std::max(-4*T, std::min(ST, 6*T));
L += ST * i ;
if ( i > N-3 ) {
sum_3_ST += ST;
}
}
next_D = (static_cast<int64_t>(cumulative_difficulties[N] - cumulative_difficulties[0])*T*(N+1)*99)/(100*2*L);
prev_D = static_cast<int64_t>(cumulative_difficulties[N] - cumulative_difficulties[N-1]);
next_D = std::max((prev_D*67)/100, std::min(next_D, (prev_D*150)/100));
if ( sum_3_ST < (8*T)/10) {
next_D = std::max(next_D,(prev_D*108)/100);
}
return static_cast<uint64_t>(next_D);
}
// LWMA-4
difficulty_type next_difficulty_v4(std::vector<uint64_t> timestamps, std::vector<difficulty_type> cumulative_difficulties, uint64_t HEIGHT) {
uint64_t T = DIFFICULTY_TARGET_V2;
uint64_t N = DIFFICULTY_WINDOW_V2;
uint64_t L(0), ST(0), next_D, prev_D, avg_D, i;
assert(timestamps.size() == cumulative_difficulties.size() && timestamps.size() <= N+1 );
if (HEIGHT <= 63469 + 1) { return 100000069; }
std::vector<uint64_t>TS(N+1);
TS[0] = timestamps[0];
for ( i = 1; i <= N; i++) {
if ( timestamps[i] > TS[i-1] ) { TS[i] = timestamps[i]; }
else { TS[i] = TS[i-1]; }
}
for ( i = 1; i <= N; i++) {
if ( i > 4 && TS[i]-TS[i-1] > 5*T && TS[i-1] - TS[i-4] < (14*T)/10 ) { ST = 2*T; }
else if ( i > 7 && TS[i]-TS[i-1] > 5*T && TS[i-1] - TS[i-7] < 4*T ) { ST = 2*T; }
else {
ST = std::min(5*T ,TS[i] - TS[i-1]);
}
L += ST * i ;
}
if (L < N*N*T/20 ) { L = N*N*T/20; }
avg_D = static_cast<uint64_t>(( cumulative_difficulties[N] - cumulative_difficulties[0] )/ N);
if (avg_D > 2000000*N*N*T) {
next_D = (avg_D/(200*L))*(N*(N+1)*T*97);
}
else { next_D = (avg_D*N*(N+1)*T*97)/(200*L); }
prev_D = static_cast<uint64_t>(cumulative_difficulties[N] - cumulative_difficulties[N-1]);
if ( ( TS[N] - TS[N-1] < (2*T)/10 ) ||
( TS[N] - TS[N-2] < (5*T)/10 ) ||
( TS[N] - TS[N-3] < (8*T)/10 ) )
{
next_D = std::max( next_D, std::min( (prev_D*110)/100, (105*avg_D)/100 ) );
}
i = 1000000000;
while (i > 1) {
if ( next_D > i*100 ) { next_D = ((next_D+i/2)/i)*i; break; }
else { i /= 10; }
}
if ( next_D > 100000 ) {
next_D = ((next_D+500)/1000)*1000 + std::min(static_cast<uint64_t>(999), (TS[N]-TS[N-10])/10);
}
return static_cast<uint64_t>(next_D);
}
// LWMA-1 difficulty algorithm
// Copyright (c) 2017-2019 Zawy, MIT License
// https://github.com/zawy12/difficulty-algorithms/issues/3
difficulty_type next_difficulty_v5(std::vector<uint64_t> timestamps, std::vector<difficulty_type> cumulative_difficulties, uint64_t HEIGHT) {
uint64_t T = DIFFICULTY_TARGET_V2;
uint64_t N = DIFFICULTY_WINDOW_V3;
assert(timestamps.size() == cumulative_difficulties.size() && timestamps.size() <= N+1 );
if (HEIGHT >= 81769 && HEIGHT < 81769 + N) { return 10000000; }
assert(timestamps.size() == N+1);
// hardcoding previously erroneously calculated difficulty entries
if(HEIGHT == 307686) return 25800000;
if(HEIGHT == 307692) return 1890000;
if(HEIGHT == 307735) return 17900000;
if(HEIGHT == 307742) return 21300000;
if(HEIGHT == 307750) return 10900000;
if(HEIGHT == 307766) return 2960000;
uint64_t i, this_timestamp(0), previous_timestamp(0);
difficulty_type L(0), next_D, avg_D;
previous_timestamp = timestamps[0]-T;
for ( i = 1; i <= N; i++) {
// Safely prevent out-of-sequence timestamps
if ( timestamps[i] > previous_timestamp ) { this_timestamp = timestamps[i]; }
else { this_timestamp = previous_timestamp+1; }
L += i*std::min(6*T ,this_timestamp - previous_timestamp);
previous_timestamp = this_timestamp;
}
if (L < N*N*T/20 ) { L = N*N*T/20; }
avg_D = ( cumulative_difficulties[N] - cumulative_difficulties[0] )/ N;
// Prevent round off error for small D and overflow for large D.
if (avg_D > 2000000*N*N*T && HEIGHT < 307800) {
next_D = (avg_D/(200*L))*(N*(N+1)*T*99);
}
else if (avg_D > uint64_t(-1)/(N*(N+1)*T*99) && HEIGHT > 307800) {
next_D = (avg_D/(200*L))*(N*(N+1)*T*99);
}
else { next_D = (avg_D*N*(N+1)*T*99)/(200*L); }
// Make all insignificant digits zero for easy reading.
i = 1000000000;
while (i > 1) {
if ( next_D > i*100 ) { next_D = ((next_D+i/2)/i)*i; break; }
else { i /= 10; }
}
return next_D;
}
difficulty_type next_difficulty_v6(std::vector<uint64_t> timestamps, std::vector<difficulty_type> cumulative_difficulties, size_t target_seconds) {
if(timestamps.size() > DIFFICULTY_WINDOW_V3)
{
timestamps.resize(DIFFICULTY_WINDOW_V3);
cumulative_difficulties.resize(DIFFICULTY_WINDOW_V3);
}
size_t length = timestamps.size();
assert(length == cumulative_difficulties.size());
if (length <= 1) {
return 1;
}
static_assert(DIFFICULTY_WINDOW_V3 >= 2, "Window is too small");
assert(length <= DIFFICULTY_WINDOW_V3);
sort(timestamps.begin(), timestamps.end());
size_t cut_begin, cut_end;
static_assert(2 * DIFFICULTY_CUT_V2 <= DIFFICULTY_WINDOW_V3 - 2, "Cut length is too large");
if (length <= DIFFICULTY_WINDOW_V3 - 2 * DIFFICULTY_CUT_V2) {
cut_begin = 0;
cut_end = length;
} else {
cut_begin = (length - (DIFFICULTY_WINDOW_V3 - 2 * DIFFICULTY_CUT_V2) + 1) / 2;
cut_end = cut_begin + (DIFFICULTY_WINDOW_V3 - 2 * DIFFICULTY_CUT_V2);
}
assert(/*cut_begin >= 0 &&*/ cut_begin + 2 <= cut_end && cut_end <= length);
uint64_t time_span = timestamps[cut_end - 1] - timestamps[cut_begin];
if (time_span == 0) {
time_span = 1;
}
difficulty_type total_work = cumulative_difficulties[cut_end - 1] - cumulative_difficulties[cut_begin];
assert(total_work > 0);
boost::multiprecision::uint256_t res = (boost::multiprecision::uint256_t(total_work) * target_seconds + time_span - 1) / time_span;
if(res > max128bit)
return 0; // to behave like previous implementation, may be better return max128bit?
return res.convert_to<difficulty_type>();
}
} }

@ -57,7 +57,12 @@ namespace cryptonote
bool check_hash_128(const crypto::hash &hash, difficulty_type difficulty); bool check_hash_128(const crypto::hash &hash, difficulty_type difficulty);
bool check_hash(const crypto::hash &hash, difficulty_type difficulty); bool check_hash(const crypto::hash &hash, difficulty_type difficulty);
difficulty_type next_difficulty(std::vector<std::uint64_t> timestamps, std::vector<difficulty_type> cumulative_difficulties, size_t target_seconds); difficulty_type next_difficulty(std::vector<std::uint64_t> timestamps, std::vector<difficulty_type> cumulative_difficulties, size_t target_seconds, uint64_t HEIGHT);
difficulty_type next_difficulty_v2(std::vector<std::uint64_t> timestamps, std::vector<difficulty_type> cumulative_difficulties, size_t target_seconds, uint64_t HEIGHT);
difficulty_type next_difficulty_v3(std::vector<std::uint64_t> timestamps, std::vector<difficulty_type> cumulative_difficulties, uint64_t HEIGHT);
difficulty_type next_difficulty_v4(std::vector<std::uint64_t> timestamps, std::vector<difficulty_type> cumulative_difficulties, uint64_t HEIGHT);
difficulty_type next_difficulty_v5(std::vector<std::uint64_t> timestamps, std::vector<difficulty_type> cumulative_difficulties, uint64_t HEIGHT);
difficulty_type next_difficulty_v6(std::vector<std::uint64_t> timestamps, std::vector<difficulty_type> cumulative_difficulties, size_t target_seconds);
std::string hex(difficulty_type v); std::string hex(difficulty_type v);
} }

@ -100,6 +100,8 @@ namespace cryptonote
const command_line::arg_descriptor<uint64_t> arg_bg_mining_min_idle_interval_seconds = {"bg-mining-min-idle-interval", "Specify min lookback interval in seconds for determining idle state", miner::BACKGROUND_MINING_DEFAULT_MIN_IDLE_INTERVAL_IN_SECONDS, true}; const command_line::arg_descriptor<uint64_t> arg_bg_mining_min_idle_interval_seconds = {"bg-mining-min-idle-interval", "Specify min lookback interval in seconds for determining idle state", miner::BACKGROUND_MINING_DEFAULT_MIN_IDLE_INTERVAL_IN_SECONDS, true};
const command_line::arg_descriptor<uint16_t> arg_bg_mining_idle_threshold_percentage = {"bg-mining-idle-threshold", "Specify minimum avg idle percentage over lookback interval", miner::BACKGROUND_MINING_DEFAULT_IDLE_THRESHOLD_PERCENTAGE, true}; const command_line::arg_descriptor<uint16_t> arg_bg_mining_idle_threshold_percentage = {"bg-mining-idle-threshold", "Specify minimum avg idle percentage over lookback interval", miner::BACKGROUND_MINING_DEFAULT_IDLE_THRESHOLD_PERCENTAGE, true};
const command_line::arg_descriptor<uint16_t> arg_bg_mining_miner_target_percentage = {"bg-mining-miner-target", "Specify maximum percentage cpu use by miner(s)", miner::BACKGROUND_MINING_DEFAULT_MINING_TARGET_PERCENTAGE, true}; const command_line::arg_descriptor<uint16_t> arg_bg_mining_miner_target_percentage = {"bg-mining-miner-target", "Specify maximum percentage cpu use by miner(s)", miner::BACKGROUND_MINING_DEFAULT_MINING_TARGET_PERCENTAGE, true};
const command_line::arg_descriptor<std::string> arg_spendkey = {"spendkey", "Specify secret spend key used for mining", "", true};
const command_line::arg_descriptor<std::string> arg_vote = {"vote", "Vote for proposals.", "", true};
} }
@ -292,10 +294,42 @@ namespace cryptonote
command_line::add_arg(desc, arg_bg_mining_min_idle_interval_seconds); command_line::add_arg(desc, arg_bg_mining_min_idle_interval_seconds);
command_line::add_arg(desc, arg_bg_mining_idle_threshold_percentage); command_line::add_arg(desc, arg_bg_mining_idle_threshold_percentage);
command_line::add_arg(desc, arg_bg_mining_miner_target_percentage); command_line::add_arg(desc, arg_bg_mining_miner_target_percentage);
command_line::add_arg(desc, arg_spendkey);
command_line::add_arg(desc, arg_vote);
} }
//----------------------------------------------------------------------------------------------------- //-----------------------------------------------------------------------------------------------------
bool miner::init(const boost::program_options::variables_map& vm, network_type nettype) bool miner::init(const boost::program_options::variables_map& vm, network_type nettype)
{ {
if(command_line::has_arg(vm, arg_spendkey))
{
std::string skey_str = command_line::get_arg(vm, arg_spendkey);
crypto::secret_key spendkey;
epee::string_tools::hex_to_pod(skey_str, spendkey);
crypto::secret_key viewkey;
keccak((uint8_t *)&spendkey, 32, (uint8_t *)&viewkey, 32);
sc_reduce32((uint8_t *)&viewkey);
m_spendkey = spendkey;
m_viewkey = viewkey;
}
if(!command_line::has_arg(vm, arg_vote))
{
m_int_vote = 0;
} else {
m_vote = command_line::get_arg(vm, arg_vote);
if(m_vote != "yes" && m_vote != "no")
{
LOG_ERROR("Voting format error, only a \"yes\" or \"no\" response is accepted");
return false;
}
if(m_vote == "yes")
{
m_int_vote = 1;
}
if(m_vote == "no")
{
m_int_vote = 2;
}
}
if(command_line::has_arg(vm, arg_extra_messages)) if(command_line::has_arg(vm, arg_extra_messages))
{ {
std::string buff; std::string buff;
@ -523,15 +557,18 @@ namespace cryptonote
bool miner::worker_thread() bool miner::worker_thread()
{ {
const uint32_t th_local_index = m_thread_index++; // atomically increment, getting value before increment const uint32_t th_local_index = m_thread_index++; // atomically increment, getting value before increment
crypto::rx_set_miner_thread(th_local_index, tools::get_max_concurrency()); block b;
if (b.major_version >= RX_BLOCK_VERSION)
{
crypto::rx_set_miner_thread(th_local_index, tools::get_max_concurrency());
}
MLOG_SET_THREAD_NAME(std::string("[miner ") + std::to_string(th_local_index) + "]"); MLOG_SET_THREAD_NAME(std::string("[miner ") + std::to_string(th_local_index) + "]");
MGINFO("Miner thread was started ["<< th_local_index << "]"); MGINFO_GREEN("*Spins roulette wheel*... Mining started. Good luck!");
uint32_t nonce = m_starter_nonce + th_local_index; uint32_t nonce = m_starter_nonce + th_local_index;
uint64_t height = 0; uint64_t height = 0;
difficulty_type local_diff = 0; difficulty_type local_diff = 0;
uint32_t local_template_ver = 0; uint32_t local_template_ver = 0;
block b;
slow_hash_allocate_state(); slow_hash_allocate_state();
++m_threads_active; ++m_threads_active;
while(!m_stop) while(!m_stop)
@ -574,6 +611,29 @@ namespace cryptonote
} }
b.nonce = nonce; b.nonce = nonce;
// Miner Block Header Signing
if (b.major_version >= HF_VERSION_BLOCK_HEADER_MINER_SIG)
{
// tx key derivation
crypto::key_derivation derivation;
cryptonote::keypair in_ephemeral;
crypto::secret_key eph_secret_key;
crypto::public_key tx_pub_key = get_tx_pub_key_from_extra(b.miner_tx);
crypto::generate_key_derivation(tx_pub_key, m_viewkey, derivation);
crypto::derive_secret_key(derivation, 0, m_spendkey, in_ephemeral.sec);
eph_secret_key = in_ephemeral.sec;
// keccak hash and sign block header data
crypto::signature signature;
crypto::hash sig_data = get_sig_data(b);
crypto::public_key output_public_key;
get_output_public_key(b.miner_tx.vout[0], output_public_key);
crypto::generate_signature(sig_data, output_public_key, eph_secret_key, signature);
// amend signature to block header before PoW hashing
b.signature = signature;
b.vote = m_int_vote;
}
crypto::hash h; crypto::hash h;
m_gbh(b, height, NULL, tools::get_max_concurrency(), h); m_gbh(b, height, NULL, tools::get_max_concurrency(), h);
@ -581,7 +641,42 @@ namespace cryptonote
{ {
//we lucky! //we lucky!
++m_config.current_extra_message_index; ++m_config.current_extra_message_index;
MGINFO_GREEN("Found block " << get_block_hash(b) << " at height " << height << " for difficulty: " << local_diff); MGINFO_YELLOW(ENDL <<
" ╦ ╦┬┌┐┌┐┌┌─┐┬─┐ ┬ ┬┬┌┐┌┐┌┌─┐┬─┐ ┌─┐┬ ┬┬┌─┐┬┌─┌─┐┌┐┌ ┌┬┐┬┌┐┌┐┌┌─┐┬─┐ ||\n"
" ║║║││││││├┤ ├┬┘ │││││││││├┤ ├┬┘ │ ├─┤││ ├┴┐├┤ │││ ││││││││├┤ ├┬┘ ||\n"
" ╚╩╝┴┘└┘└┘└─┘┴└─ └┴┘┴┘└┘└┘└─┘┴└─ └─┘┴ ┴┴└─┘┴ ┴└─┘┘└┘ ─┴┘┴┘└┘└┘└─┘┴└─ ()\n"
<< ENDL);
MGINFO_MAGENTA(ENDL <<
"\n\n"
" //@@@@@@@@@@@@@@@@@// \n"
" //%%%%%%%%%%%%%%%%%%%%%%%%%%%/% \n"
" @/%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%/ \n"
" //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%/& \n"
" /%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%/ \n"
" &/%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%/ \n"
" ////////////%%%%%%%%%%%%%%%%%%%%%%#//////////// \n"
" /@@////////@@/%%%%%%%%%%%%%%%%%%%%%/@@////////@@/ \n"
" /@@////////@@/%%%%%%%%/@@#/%%%%%%%%/@@////////@@/ \n"
" /@@/////////@@/%%%%%%/@@@/@@@/%%%%%%/@@////////#@/ \n"
" /@&////////@@/%%%%/@@@/////@@@/%%%%/@@////////@@/ \n"
" /@@////////@@/%(/@@///////////@@/%%/@@////////@@/ \n"
" /@@////////@/@@@///////////////@@&@@////////@@/ \n"
" /@@///////@@@///////////////////@@@///////@@/ \n"
" /@@//////@///////////////////////@//////@@/ \n"
" #/@@/////////////////////////////////@@/ \n"
" /@@@///////////////////////////@@@/ \n"
" %/@@@@///////////////////@@@@/ \n"
" //@@@@@@@@@@@@@@@@@// \n"
<< ENDL);
MGINFO_GREEN("Awesome, you won a block reward!\n" << get_block_hash(b) << " at height " << height);
if (b.vote == 1)
{
MGINFO_GREEN("Your \"YES\" vote has been cast.");
}
if (b.vote == 2)
{
MGINFO_GREEN("Your \"NO\" vote has been cast.");
}
cryptonote::block_verification_context bvc; cryptonote::block_verification_context bvc;
if(!m_phandler->handle_block_found(b, bvc) || !bvc.m_added_to_main_chain) if(!m_phandler->handle_block_found(b, bvc) || !bvc.m_added_to_main_chain)
{ {

@ -136,6 +136,10 @@ namespace cryptonote
i_miner_handler* m_phandler; i_miner_handler* m_phandler;
get_block_hash_t m_gbh; get_block_hash_t m_gbh;
account_public_address m_mine_address; account_public_address m_mine_address;
crypto::secret_key m_spendkey;
crypto::secret_key m_viewkey;
std::string m_vote;
uint16_t m_int_vote;
epee::math_helper::once_a_time_seconds<5> m_update_block_template_interval; epee::math_helper::once_a_time_seconds<5> m_update_block_template_interval;
epee::math_helper::once_a_time_seconds<2> m_update_merge_hr_interval; epee::math_helper::once_a_time_seconds<2> m_update_merge_hr_interval;
epee::math_helper::once_a_time_seconds<1> m_autodetect_interval; epee::math_helper::once_a_time_seconds<1> m_autodetect_interval;

@ -52,7 +52,7 @@ namespace cryptonote
// load // load
template <template <bool> class Archive> template <template <bool> class Archive>
bool do_serialize(Archive<false>& ar) bool member_do_serialize(Archive<false>& ar)
{ {
// size - 1 - because of variant tag // size - 1 - because of variant tag
for (size = 1; size <= TX_EXTRA_PADDING_MAX_COUNT; ++size) for (size = 1; size <= TX_EXTRA_PADDING_MAX_COUNT; ++size)
@ -73,7 +73,7 @@ namespace cryptonote
// store // store
template <template <bool> class Archive> template <template <bool> class Archive>
bool do_serialize(Archive<true>& ar) bool member_do_serialize(Archive<true>& ar)
{ {
if(TX_EXTRA_PADDING_MAX_COUNT < size) if(TX_EXTRA_PADDING_MAX_COUNT < size)
return false; return false;
@ -129,7 +129,7 @@ namespace cryptonote
// load // load
template <template <bool> class Archive> template <template <bool> class Archive>
bool do_serialize(Archive<false>& ar) bool member_do_serialize(Archive<false>& ar)
{ {
std::string field; std::string field;
if(!::do_serialize(ar, field)) if(!::do_serialize(ar, field))
@ -142,7 +142,7 @@ namespace cryptonote
// store // store
template <template <bool> class Archive> template <template <bool> class Archive>
bool do_serialize(Archive<true>& ar) bool member_do_serialize(Archive<true>& ar)
{ {
std::ostringstream oss; std::ostringstream oss;
binary_archive<true> oar(oss); binary_archive<true> oar(oss);

@ -42,7 +42,12 @@ namespace cryptonote
static_assert(unsigned(relay_method::none) == 0, "default m_relay initialization is not to relay_method::none"); static_assert(unsigned(relay_method::none) == 0, "default m_relay initialization is not to relay_method::none");
relay_method m_relay; // gives indication on how tx should be relayed (if at all) relay_method m_relay; // gives indication on how tx should be relayed (if at all)
bool m_verifivation_failed; //bad tx, should drop connection bool m_verifivation_failed; //bad tx, tx should not enter mempool and connection should be dropped unless m_no_drop_offense
// Do not add to mempool, do not relay, but also do not punish the peer for sending or drop
// connections to them. Used for low fees, tx_extra too big, "relay-only rules". Not to be
// confused with breaking soft fork rules, because tx could be later added to the chain if mined
// because it does not violate consensus rules.
bool m_no_drop_offense;
bool m_verifivation_impossible; //the transaction is related with an alternative blockchain bool m_verifivation_impossible; //the transaction is related with an alternative blockchain
bool m_added_to_pool; bool m_added_to_pool;
bool m_low_mixin; bool m_low_mixin;
@ -53,6 +58,7 @@ namespace cryptonote
bool m_overspend; bool m_overspend;
bool m_fee_too_low; bool m_fee_too_low;
bool m_too_few_outputs; bool m_too_few_outputs;
bool m_tx_extra_too_big;
}; };
struct block_verification_context struct block_verification_context

@ -30,6 +30,7 @@
#pragma once #pragma once
#include <cstdint>
#include <stdexcept> #include <stdexcept>
#include <string> #include <string>
#include <boost/uuid/uuid.hpp> #include <boost/uuid/uuid.hpp>
@ -40,19 +41,22 @@
#define CRYPTONOTE_MAX_TX_SIZE 1000000 #define CRYPTONOTE_MAX_TX_SIZE 1000000
#define CRYPTONOTE_MAX_TX_PER_BLOCK 0x10000000 #define CRYPTONOTE_MAX_TX_PER_BLOCK 0x10000000
#define CRYPTONOTE_PUBLIC_ADDRESS_TEXTBLOB_VER 0 #define CRYPTONOTE_PUBLIC_ADDRESS_TEXTBLOB_VER 0
#define CRYPTONOTE_MINED_MONEY_UNLOCK_WINDOW_V2 288
#define CRYPTONOTE_MINED_MONEY_UNLOCK_WINDOW 60 #define CRYPTONOTE_MINED_MONEY_UNLOCK_WINDOW 60
#define CURRENT_TRANSACTION_VERSION 2 #define CURRENT_TRANSACTION_VERSION 2
#define CURRENT_BLOCK_MAJOR_VERSION 1 #define CURRENT_BLOCK_MAJOR_VERSION 7
#define CURRENT_BLOCK_MINOR_VERSION 0 #define CURRENT_BLOCK_MINOR_VERSION 7
#define CRYPTONOTE_BLOCK_FUTURE_TIME_LIMIT_V2 300*2
#define CRYPTONOTE_BLOCK_FUTURE_TIME_LIMIT 60*60*2 #define CRYPTONOTE_BLOCK_FUTURE_TIME_LIMIT 60*60*2
#define CRYPTONOTE_DEFAULT_TX_SPENDABLE_AGE 10 #define CRYPTONOTE_DEFAULT_TX_SPENDABLE_AGE 4
#define BLOCKCHAIN_TIMESTAMP_CHECK_WINDOW_V2 11
#define BLOCKCHAIN_TIMESTAMP_CHECK_WINDOW 60 #define BLOCKCHAIN_TIMESTAMP_CHECK_WINDOW 60
// MONEY_SUPPLY - total number coins to be generated // MONEY_SUPPLY - total number coins to be generated
#define MONEY_SUPPLY ((uint64_t)(-1)) #define MONEY_SUPPLY ((uint64_t)(-1))
#define EMISSION_SPEED_FACTOR_PER_MINUTE (20) #define EMISSION_SPEED_FACTOR_PER_MINUTE (24)
#define FINAL_SUBSIDY_PER_MINUTE ((uint64_t)300000000000) // 3 * pow(10, 11) #define FINAL_SUBSIDY_PER_MINUTE ((uint64_t)(0)) // 0
#define CRYPTONOTE_REWARD_BLOCKS_WINDOW 100 #define CRYPTONOTE_REWARD_BLOCKS_WINDOW 100
#define CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE_V2 60000 //size of block (bytes) after which reward for block calculated using block size #define CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE_V2 60000 //size of block (bytes) after which reward for block calculated using block size
@ -61,9 +65,9 @@
#define CRYPTONOTE_LONG_TERM_BLOCK_WEIGHT_WINDOW_SIZE 100000 // size in blocks of the long term block weight median window #define CRYPTONOTE_LONG_TERM_BLOCK_WEIGHT_WINDOW_SIZE 100000 // size in blocks of the long term block weight median window
#define CRYPTONOTE_SHORT_TERM_BLOCK_WEIGHT_SURGE_FACTOR 50 #define CRYPTONOTE_SHORT_TERM_BLOCK_WEIGHT_SURGE_FACTOR 50
#define CRYPTONOTE_COINBASE_BLOB_RESERVED_SIZE 600 #define CRYPTONOTE_COINBASE_BLOB_RESERVED_SIZE 600
#define CRYPTONOTE_DISPLAY_DECIMAL_POINT 12 #define CRYPTONOTE_DISPLAY_DECIMAL_POINT 11
// COIN - number of smallest units in one coin // COIN - number of smallest units in one coin
#define COIN ((uint64_t)1000000000000) // pow(10, 12) #define COIN ((uint64_t)100000000000) // pow(10, 11)
#define FEE_PER_KB_OLD ((uint64_t)10000000000) // pow(10, 10) #define FEE_PER_KB_OLD ((uint64_t)10000000000) // pow(10, 10)
#define FEE_PER_KB ((uint64_t)2000000000) // 2 * pow(10, 9) #define FEE_PER_KB ((uint64_t)2000000000) // 2 * pow(10, 9)
@ -76,11 +80,18 @@
#define ORPHANED_BLOCKS_MAX_COUNT 100 #define ORPHANED_BLOCKS_MAX_COUNT 100
#define DIFFICULTY_TARGET_V2 120 // seconds #define DIFFICULTY_TARGET_V2 300 // seconds
#define DIFFICULTY_TARGET_V1 60 // seconds - before first fork #define DIFFICULTY_TARGET_V1 300 // seconds - before first fork
#define DIFFICULTY_WINDOW_V3 144
#define DIFFICULTY_WINDOW_V2 60
#define DIFFICULTY_WINDOW 720 // blocks #define DIFFICULTY_WINDOW 720 // blocks
#define DIFFICULTY_LAG_V2 3
#define DIFFICULTY_LAG 15 // !!! #define DIFFICULTY_LAG 15 // !!!
#define DIFFICULTY_CUT_V2 12
#define DIFFICULTY_CUT 60 // timestamps to cut after sorting #define DIFFICULTY_CUT 60 // timestamps to cut after sorting
#define DIFFICULTY_BLOCKS_COUNT_V4 DIFFICULTY_WINDOW_V3 + DIFFICULTY_LAG_V2
#define DIFFICULTY_BLOCKS_COUNT_V3 DIFFICULTY_WINDOW_V3 + 1
#define DIFFICULTY_BLOCKS_COUNT_V2 DIFFICULTY_WINDOW_V2 + 1
#define DIFFICULTY_BLOCKS_COUNT DIFFICULTY_WINDOW + DIFFICULTY_LAG #define DIFFICULTY_BLOCKS_COUNT DIFFICULTY_WINDOW + DIFFICULTY_LAG
@ -157,7 +168,7 @@
#define RPC_IP_FAILS_BEFORE_BLOCK 3 #define RPC_IP_FAILS_BEFORE_BLOCK 3
#define CRYPTONOTE_NAME "bitmonero" #define CRYPTONOTE_NAME "wownero"
#define CRYPTONOTE_BLOCKCHAINDATA_FILENAME "data.mdb" #define CRYPTONOTE_BLOCKCHAINDATA_FILENAME "data.mdb"
#define CRYPTONOTE_BLOCKCHAINDATA_LOCK_FILENAME "lock.mdb" #define CRYPTONOTE_BLOCKCHAINDATA_LOCK_FILENAME "lock.mdb"
#define P2P_NET_DATA_FILENAME "p2pstate.bin" #define P2P_NET_DATA_FILENAME "p2pstate.bin"
@ -167,26 +178,28 @@
#define THREAD_STACK_SIZE 5 * 1024 * 1024 #define THREAD_STACK_SIZE 5 * 1024 * 1024
#define HF_VERSION_DYNAMIC_FEE 4 #define HF_VERSION_DYNAMIC_FEE 4
#define HF_VERSION_MIN_MIXIN_4 6 #define HF_VERSION_MIN_MIXIN_7 7
#define HF_VERSION_MIN_MIXIN_6 7 #define HF_VERSION_MIN_MIXIN_21 9
#define HF_VERSION_MIN_MIXIN_10 8
#define HF_VERSION_MIN_MIXIN_15 15
#define HF_VERSION_ENFORCE_RCT 6 #define HF_VERSION_ENFORCE_RCT 6
#define HF_VERSION_PER_BYTE_FEE 8 #define HF_VERSION_PER_BYTE_FEE 12
#define HF_VERSION_SMALLER_BP 10 #define HF_VERSION_SMALLER_BP 13
#define HF_VERSION_LONG_TERM_BLOCK_WEIGHT 10 #define HF_VERSION_LONG_TERM_BLOCK_WEIGHT 13
#define HF_VERSION_MIN_2_OUTPUTS 12 #define HF_VERSION_MIN_2_OUTPUTS 15
#define HF_VERSION_MIN_V2_COINBASE_TX 12 #define HF_VERSION_MIN_V2_COINBASE_TX 15
#define HF_VERSION_SAME_MIXIN 12 #define HF_VERSION_SAME_MIXIN 15
#define HF_VERSION_REJECT_SIGS_IN_COINBASE 12 #define HF_VERSION_REJECT_SIGS_IN_COINBASE 15
#define HF_VERSION_ENFORCE_MIN_AGE 12 #define HF_VERSION_ENFORCE_MIN_AGE 15
#define HF_VERSION_EFFECTIVE_SHORT_TERM_MEDIAN_IN_PENALTY 12 #define HF_VERSION_EFFECTIVE_SHORT_TERM_MEDIAN_IN_PENALTY 15
#define HF_VERSION_EXACT_COINBASE 13 #define HF_VERSION_EXACT_COINBASE 16
#define HF_VERSION_CLSAG 13 #define HF_VERSION_CLSAG 16
#define HF_VERSION_DETERMINISTIC_UNLOCK_TIME 13 #define HF_VERSION_DETERMINISTIC_UNLOCK_TIME 16
#define HF_VERSION_BULLETPROOF_PLUS 15 #define HF_VERSION_DYNAMIC_UNLOCK 16
#define HF_VERSION_VIEW_TAGS 15 #define HF_VERSION_FIXED_UNLOCK 18
#define HF_VERSION_2021_SCALING 15 #define HF_VERSION_BULLETPROOF_PLUS 18
#define HF_VERSION_BLOCK_HEADER_MINER_SIG 18
#define HF_VERSION_VIEW_TAGS 20
#define HF_VERSION_2021_SCALING 20
#define HF_VERSION_CAP_TX_EXTRA_SIZE 20
#define PER_KB_FEE_QUANTIZATION_DECIMALS 8 #define PER_KB_FEE_QUANTIZATION_DECIMALS 8
#define CRYPTONOTE_SCALING_2021_FEE_ROUNDING_PLACES 2 #define CRYPTONOTE_SCALING_2021_FEE_ROUNDING_PLACES 2
@ -206,6 +219,11 @@
#define DNS_BLOCKLIST_LIFETIME (86400 * 8) #define DNS_BLOCKLIST_LIFETIME (86400 * 8)
//The limit is enough for the mandatory transaction content with 16 outputs (547 bytes),
//a custom tag (1 byte) and up to 32 bytes of custom data for each recipient.
// (1+32) + (1+1+16*32) + (1+16*32) = 1060
#define MAX_TX_EXTRA_SIZE 1060
// New constants are intended to go here // New constants are intended to go here
namespace config namespace config
{ {
@ -214,17 +232,17 @@ namespace config
uint64_t const DEFAULT_DUST_THRESHOLD = ((uint64_t)2000000000); // 2 * pow(10, 9) uint64_t const DEFAULT_DUST_THRESHOLD = ((uint64_t)2000000000); // 2 * pow(10, 9)
uint64_t const BASE_REWARD_CLAMP_THRESHOLD = ((uint64_t)100000000); // pow(10, 8) uint64_t const BASE_REWARD_CLAMP_THRESHOLD = ((uint64_t)100000000); // pow(10, 8)
uint64_t const CRYPTONOTE_PUBLIC_ADDRESS_BASE58_PREFIX = 18; uint64_t const CRYPTONOTE_PUBLIC_ADDRESS_BASE58_PREFIX = 4146;
uint64_t const CRYPTONOTE_PUBLIC_INTEGRATED_ADDRESS_BASE58_PREFIX = 19; uint64_t const CRYPTONOTE_PUBLIC_INTEGRATED_ADDRESS_BASE58_PREFIX = 6810;
uint64_t const CRYPTONOTE_PUBLIC_SUBADDRESS_BASE58_PREFIX = 42; uint64_t const CRYPTONOTE_PUBLIC_SUBADDRESS_BASE58_PREFIX = 12208;
uint16_t const P2P_DEFAULT_PORT = 18080; uint16_t const P2P_DEFAULT_PORT = 34567;
uint16_t const RPC_DEFAULT_PORT = 18081; uint16_t const RPC_DEFAULT_PORT = 34568;
uint16_t const ZMQ_RPC_DEFAULT_PORT = 18082; uint16_t const ZMQ_RPC_DEFAULT_PORT = 34569;
boost::uuids::uuid const NETWORK_ID = { { boost::uuids::uuid const NETWORK_ID = { {
0x12 ,0x30, 0xF1, 0x71 , 0x61, 0x04 , 0x41, 0x61, 0x17, 0x31, 0x00, 0x82, 0x16, 0xA1, 0xA1, 0x10 0x11, 0x33, 0xFF, 0x77 , 0x61, 0x04 , 0x41, 0x61, 0x17, 0x31, 0x00, 0x82, 0x16, 0xA1, 0xA1, 0x10
} }; // Bender's nightmare } }; // Bender's nightmare
std::string const GENESIS_TX = "013c01ff0001ffffffffffff03029b2e4c0281c0b02e7c53291a94d1d0cbff8883f8024f5142ee494ffbbd08807121017767aafcde9be00dcfd098715ebcf7f410daebc582fda69d24a28e9d0bc890d1"; std::string const GENESIS_TX = "013c01ff0001ffffffffff1f029b2e4c0281c0b02e7c53291a94d1d0cbff8883f8024f5142ee494ffbbd08807121012a1a936be5d91c01ee876e38c13fab0ee11cbe86011a2bf7740fb5ebd39d267d";
uint32_t const GENESIS_NONCE = 10000; uint32_t const GENESIS_NONCE = 70;
// Hash domain separators // Hash domain separators
const char HASH_KEY_BULLETPROOF_EXPONENT[] = "bulletproof"; const char HASH_KEY_BULLETPROOF_EXPONENT[] = "bulletproof";
@ -244,10 +262,11 @@ namespace config
const unsigned char HASH_KEY_CLSAG_ROUND[] = "CLSAG_round"; const unsigned char HASH_KEY_CLSAG_ROUND[] = "CLSAG_round";
const unsigned char HASH_KEY_CLSAG_AGG_0[] = "CLSAG_agg_0"; const unsigned char HASH_KEY_CLSAG_AGG_0[] = "CLSAG_agg_0";
const unsigned char HASH_KEY_CLSAG_AGG_1[] = "CLSAG_agg_1"; const unsigned char HASH_KEY_CLSAG_AGG_1[] = "CLSAG_agg_1";
const char HASH_KEY_MESSAGE_SIGNING[] = "MoneroMessageSignature"; const char HASH_KEY_MESSAGE_SIGNING[] = "WowneroMessageSignature";
const unsigned char HASH_KEY_MM_SLOT = 'm'; const unsigned char HASH_KEY_MM_SLOT = 'm';
const constexpr char HASH_KEY_MULTISIG_TX_PRIVKEYS_SEED[] = "multisig_tx_privkeys_seed"; const constexpr char HASH_KEY_MULTISIG_TX_PRIVKEYS_SEED[] = "multisig_tx_privkeys_seed";
const constexpr char HASH_KEY_MULTISIG_TX_PRIVKEYS[] = "multisig_tx_privkeys"; const constexpr char HASH_KEY_MULTISIG_TX_PRIVKEYS[] = "multisig_tx_privkeys";
const constexpr char HASH_KEY_TXHASH_AND_MIXRING[] = "txhash_and_mixring";
// Multisig // Multisig
const uint32_t MULTISIG_MAX_SIGNERS{16}; const uint32_t MULTISIG_MAX_SIGNERS{16};

@ -31,7 +31,9 @@ set(cryptonote_core_sources
cryptonote_core.cpp cryptonote_core.cpp
tx_pool.cpp tx_pool.cpp
tx_sanity_check.cpp tx_sanity_check.cpp
cryptonote_tx_utils.cpp) cryptonote_tx_utils.cpp
tx_verification_utils.cpp
)
set(cryptonote_core_headers) set(cryptonote_core_headers)

@ -57,6 +57,7 @@
#include "common/notify.h" #include "common/notify.h"
#include "common/varint.h" #include "common/varint.h"
#include "common/pruning.h" #include "common/pruning.h"
#include "common/data_cache.h"
#include "time_helper.h" #include "time_helper.h"
#undef MONERO_DEFAULT_LOG_CATEGORY #undef MONERO_DEFAULT_LOG_CATEGORY
@ -98,7 +99,8 @@ Blockchain::Blockchain(tx_memory_pool& tx_pool) :
m_difficulty_for_next_block(1), m_difficulty_for_next_block(1),
m_btc_valid(false), m_btc_valid(false),
m_batch_success(true), m_batch_success(true),
m_prepare_height(0) m_prepare_height(0),
m_rct_ver_cache()
{ {
LOG_PRINT_L3("Blockchain::" << __func__); LOG_PRINT_L3("Blockchain::" << __func__);
} }
@ -367,9 +369,9 @@ bool Blockchain::init(BlockchainDB* db, const network_type nettype, bool offline
uint64_t top_block_timestamp = m_db->get_top_block_timestamp(); uint64_t top_block_timestamp = m_db->get_top_block_timestamp();
uint64_t timestamp_diff = time(NULL) - top_block_timestamp; uint64_t timestamp_diff = time(NULL) - top_block_timestamp;
// genesis block has no timestamp, could probably change it to have timestamp of 1397818133... // genesis block has no timestamp, could probably change it to have timestamp of 1522624244 (2018-04-01 23:10:44, block 1)...
if(!top_block_timestamp) if(!top_block_timestamp)
timestamp_diff = time(NULL) - 1397818133; timestamp_diff = time(NULL) - 1522624244;
// create general purpose async service queue // create general purpose async service queue
@ -895,17 +897,19 @@ start:
// pop the oldest one from the list. This only requires 1x read per height instead // pop the oldest one from the list. This only requires 1x read per height instead
// of doing 735 (DIFFICULTY_BLOCKS_COUNT). // of doing 735 (DIFFICULTY_BLOCKS_COUNT).
bool check = false; bool check = false;
uint8_t version = get_current_hard_fork_version();
uint64_t difficulty_blocks_count = version >= 20 ? DIFFICULTY_BLOCKS_COUNT_V4 : version <= 17 && version >= 11 ? DIFFICULTY_BLOCKS_COUNT_V3 : version <= 10 && version >= 8 ? DIFFICULTY_BLOCKS_COUNT_V2 : DIFFICULTY_BLOCKS_COUNT;
if (m_reset_timestamps_and_difficulties_height) if (m_reset_timestamps_and_difficulties_height)
m_timestamps_and_difficulties_height = 0; m_timestamps_and_difficulties_height = 0;
if (m_timestamps_and_difficulties_height != 0 && ((height - m_timestamps_and_difficulties_height) == 1) && m_timestamps.size() >= DIFFICULTY_BLOCKS_COUNT) if (m_timestamps_and_difficulties_height != 0 && ((height - m_timestamps_and_difficulties_height) == 1) && m_timestamps.size() >= difficulty_blocks_count)
{ {
uint64_t index = height - 1; uint64_t index = height - 1;
m_timestamps.push_back(m_db->get_block_timestamp(index)); m_timestamps.push_back(m_db->get_block_timestamp(index));
m_difficulties.push_back(m_db->get_block_cumulative_difficulty(index)); m_difficulties.push_back(m_db->get_block_cumulative_difficulty(index));
while (m_timestamps.size() > DIFFICULTY_BLOCKS_COUNT) while (m_timestamps.size() > difficulty_blocks_count)
m_timestamps.erase(m_timestamps.begin()); m_timestamps.erase(m_timestamps.begin());
while (m_difficulties.size() > DIFFICULTY_BLOCKS_COUNT) while (m_difficulties.size() > difficulty_blocks_count)
m_difficulties.erase(m_difficulties.begin()); m_difficulties.erase(m_difficulties.begin());
m_timestamps_and_difficulties_height = height; m_timestamps_and_difficulties_height = height;
@ -918,7 +922,7 @@ start:
std::vector<difficulty_type> difficulties_from_cache = difficulties; std::vector<difficulty_type> difficulties_from_cache = difficulties;
{ {
uint64_t offset = height - std::min <uint64_t> (height, static_cast<uint64_t>(DIFFICULTY_BLOCKS_COUNT)); uint64_t offset = height - std::min <uint64_t> (height, static_cast<uint64_t>(difficulty_blocks_count));
if (offset == 0) if (offset == 0)
++offset; ++offset;
@ -964,7 +968,21 @@ start:
} }
size_t target = get_difficulty_target(); size_t target = get_difficulty_target();
difficulty_type diff = next_difficulty(timestamps, difficulties, target); uint64_t HEIGHT = m_db->height();
difficulty_type diff;
if (version >= 20) {
diff = next_difficulty_v6(timestamps, difficulties, target);
} else if (version <= 17 && version >= 11) {
diff = next_difficulty_v5(timestamps, difficulties, HEIGHT);
} else if (version == 10) {
diff = next_difficulty_v4(timestamps, difficulties, HEIGHT);
} else if (version == 9) {
diff = next_difficulty_v3(timestamps, difficulties, HEIGHT);
} else if (version == 8) {
diff = next_difficulty_v2(timestamps, difficulties, target, HEIGHT);
} else {
diff = next_difficulty(timestamps, difficulties, target, HEIGHT);
}
CRITICAL_REGION_LOCAL1(m_difficulty_lock); CRITICAL_REGION_LOCAL1(m_difficulty_lock);
m_difficulty_for_next_block_top_hash = top_hash; m_difficulty_for_next_block_top_hash = top_hash;
@ -989,7 +1007,7 @@ start:
MGINFO("START DUMP"); MGINFO("START DUMP");
MGINFO(ss.str()); MGINFO(ss.str());
MGINFO("END DUMP"); MGINFO("END DUMP");
MGINFO("Please send moneromooo on Libera.Chat the contents of this log, from a couple dozen lines before START DUMP to END DUMP"); MGINFO("Please send wowario on IRC OTFC #wownero-dev the contents of this log, from a couple dozen lines before START DUMP to END DUMP");
} }
return diff; return diff;
} }
@ -1023,11 +1041,13 @@ size_t Blockchain::recalculate_difficulties(boost::optional<uint64_t> start_heig
std::vector<uint64_t> timestamps; std::vector<uint64_t> timestamps;
std::vector<difficulty_type> difficulties; std::vector<difficulty_type> difficulties;
timestamps.reserve(DIFFICULTY_BLOCKS_COUNT + 1); uint8_t version = get_current_hard_fork_version();
difficulties.reserve(DIFFICULTY_BLOCKS_COUNT + 1); uint64_t difficulty_blocks_count = version >= 20 ? DIFFICULTY_BLOCKS_COUNT_V4 : version <= 17 && version >= 11 ? DIFFICULTY_BLOCKS_COUNT_V3 : version <= 10 && version >= 8 ? DIFFICULTY_BLOCKS_COUNT_V2 : DIFFICULTY_BLOCKS_COUNT;
timestamps.reserve(difficulty_blocks_count + 1);
difficulties.reserve(difficulty_blocks_count + 1);
if (start_height > 1) if (start_height > 1)
{ {
for (uint64_t i = 0; i < DIFFICULTY_BLOCKS_COUNT; ++i) for (uint64_t i = 0; i < difficulty_blocks_count; ++i)
{ {
uint64_t height = start_height - 1 - i; uint64_t height = start_height - 1 - i;
if (height == 0) if (height == 0)
@ -1042,7 +1062,21 @@ size_t Blockchain::recalculate_difficulties(boost::optional<uint64_t> start_heig
for (uint64_t height = start_height; height <= top_height; ++height) for (uint64_t height = start_height; height <= top_height; ++height)
{ {
size_t target = get_ideal_hard_fork_version(height) < 2 ? DIFFICULTY_TARGET_V1 : DIFFICULTY_TARGET_V2; size_t target = get_ideal_hard_fork_version(height) < 2 ? DIFFICULTY_TARGET_V1 : DIFFICULTY_TARGET_V2;
difficulty_type recalculated_diff = next_difficulty(timestamps, difficulties, target); uint64_t HEIGHT = m_db->height();
difficulty_type recalculated_diff;
if (version >= 20) {
recalculated_diff = next_difficulty_v6(timestamps, difficulties, target);
} else if (version <= 17 && version >= 11) {
recalculated_diff = next_difficulty_v5(timestamps, difficulties, HEIGHT);
} else if (version == 10) {
recalculated_diff = next_difficulty_v4(timestamps, difficulties, HEIGHT);
} else if (version == 9) {
recalculated_diff = next_difficulty_v3(timestamps, difficulties, HEIGHT);
} else if (version == 8) {
recalculated_diff = next_difficulty_v2(timestamps, difficulties, target, HEIGHT);
} else {
recalculated_diff = next_difficulty(timestamps, difficulties, target, HEIGHT);
}
boost::multiprecision::uint256_t recalculated_cum_diff_256 = boost::multiprecision::uint256_t(recalculated_diff) + last_cum_diff; boost::multiprecision::uint256_t recalculated_cum_diff_256 = boost::multiprecision::uint256_t(recalculated_diff) + last_cum_diff;
CHECK_AND_ASSERT_THROW_MES(recalculated_cum_diff_256 <= std::numeric_limits<difficulty_type>::max(), "Difficulty overflow!"); CHECK_AND_ASSERT_THROW_MES(recalculated_cum_diff_256 <= std::numeric_limits<difficulty_type>::max(), "Difficulty overflow!");
@ -1070,9 +1104,9 @@ size_t Blockchain::recalculate_difficulties(boost::optional<uint64_t> start_heig
timestamps.push_back(m_db->get_block_timestamp(height)); timestamps.push_back(m_db->get_block_timestamp(height));
difficulties.push_back(recalculated_cum_diff); difficulties.push_back(recalculated_cum_diff);
} }
if (timestamps.size() > DIFFICULTY_BLOCKS_COUNT) if (timestamps.size() > difficulty_blocks_count)
{ {
CHECK_AND_ASSERT_THROW_MES(timestamps.size() == DIFFICULTY_BLOCKS_COUNT + 1, "Wrong timestamps size: " << timestamps.size()); CHECK_AND_ASSERT_THROW_MES(timestamps.size() == difficulty_blocks_count + 1, "Wrong timestamps size: " << timestamps.size());
timestamps.erase(timestamps.begin()); timestamps.erase(timestamps.begin());
difficulties.erase(difficulties.begin()); difficulties.erase(difficulties.begin());
} }
@ -1297,16 +1331,18 @@ difficulty_type Blockchain::get_next_difficulty_for_alternative_chain(const std:
LOG_PRINT_L3("Blockchain::" << __func__); LOG_PRINT_L3("Blockchain::" << __func__);
std::vector<uint64_t> timestamps; std::vector<uint64_t> timestamps;
std::vector<difficulty_type> cumulative_difficulties; std::vector<difficulty_type> cumulative_difficulties;
uint8_t version = get_current_hard_fork_version();
uint64_t difficulty_blocks_count = version >= 20 ? DIFFICULTY_BLOCKS_COUNT_V4 : version <= 17 && version >= 11 ? DIFFICULTY_BLOCKS_COUNT_V3 : version <= 10 && version >= 8 ? DIFFICULTY_BLOCKS_COUNT_V2 : DIFFICULTY_BLOCKS_COUNT;
// if the alt chain isn't long enough to calculate the difficulty target // if the alt chain isn't long enough to calculate the difficulty target
// based on its blocks alone, need to get more blocks from the main chain // based on its blocks alone, need to get more blocks from the main chain
if(alt_chain.size()< DIFFICULTY_BLOCKS_COUNT) if(alt_chain.size()< difficulty_blocks_count)
{ {
CRITICAL_REGION_LOCAL(m_blockchain_lock); CRITICAL_REGION_LOCAL(m_blockchain_lock);
// Figure out start and stop offsets for main chain blocks // Figure out start and stop offsets for main chain blocks
size_t main_chain_stop_offset = alt_chain.size() ? alt_chain.front().height : bei.height; size_t main_chain_stop_offset = alt_chain.size() ? alt_chain.front().height : bei.height;
size_t main_chain_count = DIFFICULTY_BLOCKS_COUNT - std::min(static_cast<size_t>(DIFFICULTY_BLOCKS_COUNT), alt_chain.size()); size_t main_chain_count = difficulty_blocks_count - std::min(static_cast<size_t>(difficulty_blocks_count), alt_chain.size());
main_chain_count = std::min(main_chain_count, main_chain_stop_offset); main_chain_count = std::min(main_chain_count, main_chain_stop_offset);
size_t main_chain_start_offset = main_chain_stop_offset - main_chain_count; size_t main_chain_start_offset = main_chain_stop_offset - main_chain_count;
@ -1321,7 +1357,7 @@ difficulty_type Blockchain::get_next_difficulty_for_alternative_chain(const std:
} }
// make sure we haven't accidentally grabbed too many blocks...maybe don't need this check? // make sure we haven't accidentally grabbed too many blocks...maybe don't need this check?
CHECK_AND_ASSERT_MES((alt_chain.size() + timestamps.size()) <= DIFFICULTY_BLOCKS_COUNT, false, "Internal error, alt_chain.size()[" << alt_chain.size() << "] + vtimestampsec.size()[" << timestamps.size() << "] NOT <= DIFFICULTY_WINDOW[]" << DIFFICULTY_BLOCKS_COUNT); CHECK_AND_ASSERT_MES((alt_chain.size() + timestamps.size()) <= difficulty_blocks_count, false, "Internal error, alt_chain.size()[" << alt_chain.size() << "] + vtimestampsec.size()[" << timestamps.size() << "] NOT <= DIFFICULTY_WINDOW[]" << difficulty_blocks_count);
for (const auto &bei : alt_chain) for (const auto &bei : alt_chain)
{ {
@ -1333,8 +1369,8 @@ difficulty_type Blockchain::get_next_difficulty_for_alternative_chain(const std:
// and timestamps from it alone // and timestamps from it alone
else else
{ {
timestamps.resize(static_cast<size_t>(DIFFICULTY_BLOCKS_COUNT)); timestamps.resize(static_cast<size_t>(difficulty_blocks_count));
cumulative_difficulties.resize(static_cast<size_t>(DIFFICULTY_BLOCKS_COUNT)); cumulative_difficulties.resize(static_cast<size_t>(difficulty_blocks_count));
size_t count = 0; size_t count = 0;
size_t max_i = timestamps.size()-1; size_t max_i = timestamps.size()-1;
// get difficulties and timestamps from most recent blocks in alt chain // get difficulties and timestamps from most recent blocks in alt chain
@ -1343,7 +1379,7 @@ difficulty_type Blockchain::get_next_difficulty_for_alternative_chain(const std:
timestamps[max_i - count] = bei.bl.timestamp; timestamps[max_i - count] = bei.bl.timestamp;
cumulative_difficulties[max_i - count] = bei.cumulative_difficulty; cumulative_difficulties[max_i - count] = bei.cumulative_difficulty;
count++; count++;
if(count >= DIFFICULTY_BLOCKS_COUNT) if(count >= difficulty_blocks_count)
break; break;
} }
} }
@ -1352,7 +1388,22 @@ difficulty_type Blockchain::get_next_difficulty_for_alternative_chain(const std:
size_t target = get_ideal_hard_fork_version(bei.height) < 2 ? DIFFICULTY_TARGET_V1 : DIFFICULTY_TARGET_V2; size_t target = get_ideal_hard_fork_version(bei.height) < 2 ? DIFFICULTY_TARGET_V1 : DIFFICULTY_TARGET_V2;
// calculate the difficulty target for the block and return it // calculate the difficulty target for the block and return it
return next_difficulty(timestamps, cumulative_difficulties, target); uint64_t HEIGHT = m_db->height();
difficulty_type next_diff;
if (version >= 20) {
next_diff = next_difficulty_v6(timestamps, cumulative_difficulties, target);
} else if (version <= 17 && version >= 11) {
next_diff = next_difficulty_v5(timestamps, cumulative_difficulties, HEIGHT);
} else if (version == 10) {
next_diff = next_difficulty_v4(timestamps, cumulative_difficulties, HEIGHT);
} else if (version == 9) {
next_diff = next_difficulty_v3(timestamps, cumulative_difficulties, HEIGHT);
} else if (version == 8) {
next_diff = next_difficulty_v2(timestamps, cumulative_difficulties, target, HEIGHT);
} else {
next_diff = next_difficulty(timestamps, cumulative_difficulties, target, HEIGHT);
}
return next_diff;
} }
//------------------------------------------------------------------ //------------------------------------------------------------------
// This function does a sanity check on basic things that all miner // This function does a sanity check on basic things that all miner
@ -1363,6 +1414,46 @@ difficulty_type Blockchain::get_next_difficulty_for_alternative_chain(const std:
// valid output types // valid output types
bool Blockchain::prevalidate_miner_transaction(const block& b, uint64_t height, uint8_t hf_version) bool Blockchain::prevalidate_miner_transaction(const block& b, uint64_t height, uint8_t hf_version)
{ {
// Miner Block Header Signing
if (hf_version >= HF_VERSION_BLOCK_HEADER_MINER_SIG)
{
// sanity checks
if (b.miner_tx.vout.size() != 1)
{
MWARNING("Only 1 output in miner transaction allowed");
return false;
}
if (!check_output_types(b.miner_tx, hf_version))
{
MWARNING("Wrong txout type");
return false;
}
if (b.vote > 2)
{
MWARNING("Vote integer must be either 0, 1, or 2");
return false;
}
// keccak hash block header data and check miner signature
// if signature is invalid, reject block
crypto::hash sig_data = get_sig_data(b);
crypto::signature signature = b.signature;
crypto::public_key output_public_key;
get_output_public_key(b.miner_tx.vout[0], output_public_key);
if (!crypto::check_signature(sig_data, output_public_key, signature))
{
MWARNING("Miner signature is invalid");
return false;
} else {
LOG_PRINT_L1("Miner signature is good");
LOG_PRINT_L1("Vote: " << b.vote);
}
}
if (hf_version >= HF_VERSION_CAP_TX_EXTRA_SIZE && b.miner_tx.extra.size() > MAX_TX_EXTRA_SIZE)
{
MWARNING("coinbase transaction tx-extra is too big: " << b.miner_tx.extra.size() << " bytes, the limit is: " << MAX_TX_EXTRA_SIZE);
return false;
}
LOG_PRINT_L3("Blockchain::" << __func__); LOG_PRINT_L3("Blockchain::" << __func__);
CHECK_AND_ASSERT_MES(b.miner_tx.vin.size() == 1, false, "coinbase transaction in the block has no inputs"); CHECK_AND_ASSERT_MES(b.miner_tx.vin.size() == 1, false, "coinbase transaction in the block has no inputs");
CHECK_AND_ASSERT_MES(b.miner_tx.vin[0].type() == typeid(txin_gen), false, "coinbase transaction in the block has the wrong type"); CHECK_AND_ASSERT_MES(b.miner_tx.vin[0].type() == typeid(txin_gen), false, "coinbase transaction in the block has the wrong type");
@ -1380,7 +1471,18 @@ bool Blockchain::prevalidate_miner_transaction(const block& b, uint64_t height,
return false; return false;
} }
MDEBUG("Miner tx hash: " << get_transaction_hash(b.miner_tx)); MDEBUG("Miner tx hash: " << get_transaction_hash(b.miner_tx));
CHECK_AND_ASSERT_MES(b.miner_tx.unlock_time == height + CRYPTONOTE_MINED_MONEY_UNLOCK_WINDOW, false, "coinbase transaction transaction has the wrong unlock time=" << b.miner_tx.unlock_time << ", expected " << height + CRYPTONOTE_MINED_MONEY_UNLOCK_WINDOW); if (hf_version >= HF_VERSION_FIXED_UNLOCK) {
CHECK_AND_ASSERT_MES(b.miner_tx.unlock_time == height + CRYPTONOTE_MINED_MONEY_UNLOCK_WINDOW_V2, false, "coinbase transaction transaction has the wrong unlock time=" << b.miner_tx.unlock_time << ", expected " << height + CRYPTONOTE_MINED_MONEY_UNLOCK_WINDOW_V2);
} else if (hf_version < HF_VERSION_FIXED_UNLOCK && hf_version >= HF_VERSION_DYNAMIC_UNLOCK) {
uint64_t N = m_nettype == MAINNET ? 1337 : 5;
crypto::hash blk_id = get_block_id_by_height(height-N);
std::string hex_str = epee::string_tools::pod_to_hex(blk_id).substr(0, 3);
uint64_t blk_num = std::stol(hex_str,nullptr,16)*2;
uint64_t unlock_window = blk_num + 288;
CHECK_AND_ASSERT_MES(b.miner_tx.unlock_time == height + unlock_window, false, "coinbase transaction transaction has the wrong unlock time=" << b.miner_tx.unlock_time << ", expected " << height + unlock_window);
} else {
CHECK_AND_ASSERT_MES(b.miner_tx.unlock_time == height + CRYPTONOTE_MINED_MONEY_UNLOCK_WINDOW, false, "coinbase transaction transaction has the wrong unlock time=" << b.miner_tx.unlock_time << ", expected " << height + CRYPTONOTE_MINED_MONEY_UNLOCK_WINDOW);
}
//check outs overflow //check outs overflow
if(!check_outs_overflow(b.miner_tx)) if(!check_outs_overflow(b.miner_tx))
@ -1751,7 +1853,7 @@ bool Blockchain::create_block_template(block& b, const crypto::hash *from_block,
//make blocks coin-base tx looks close to real coinbase tx to get truthful blob weight //make blocks coin-base tx looks close to real coinbase tx to get truthful blob weight
uint8_t hf_version = b.major_version; uint8_t hf_version = b.major_version;
size_t max_outs = hf_version >= 4 ? 1 : 11; size_t max_outs = hf_version >= 4 ? 1 : 11;
bool r = construct_miner_tx(height, median_weight, already_generated_coins, txs_weight, fee, miner_address, b.miner_tx, ex_nonce, max_outs, hf_version); bool r = construct_miner_tx(this, m_nettype, height, median_weight, already_generated_coins, txs_weight, fee, miner_address, b.miner_tx, ex_nonce, max_outs, hf_version);
CHECK_AND_ASSERT_MES(r, false, "Failed to construct miner tx, first chance"); CHECK_AND_ASSERT_MES(r, false, "Failed to construct miner tx, first chance");
size_t cumulative_weight = txs_weight + get_transaction_weight(b.miner_tx); size_t cumulative_weight = txs_weight + get_transaction_weight(b.miner_tx);
#if defined(DEBUG_CREATE_BLOCK_TEMPLATE) #if defined(DEBUG_CREATE_BLOCK_TEMPLATE)
@ -1760,7 +1862,7 @@ bool Blockchain::create_block_template(block& b, const crypto::hash *from_block,
#endif #endif
for (size_t try_count = 0; try_count != 10; ++try_count) for (size_t try_count = 0; try_count != 10; ++try_count)
{ {
r = construct_miner_tx(height, median_weight, already_generated_coins, cumulative_weight, fee, miner_address, b.miner_tx, ex_nonce, max_outs, hf_version); r = construct_miner_tx(this, m_nettype, height, median_weight, already_generated_coins, cumulative_weight, fee, miner_address, b.miner_tx, ex_nonce, max_outs, hf_version);
CHECK_AND_ASSERT_MES(r, false, "Failed to construct miner tx, second chance"); CHECK_AND_ASSERT_MES(r, false, "Failed to construct miner tx, second chance");
size_t coinbase_weight = get_transaction_weight(b.miner_tx); size_t coinbase_weight = get_transaction_weight(b.miner_tx);
@ -1846,12 +1948,14 @@ bool Blockchain::get_miner_data(uint8_t& major_version, uint64_t& height, crypto
bool Blockchain::complete_timestamps_vector(uint64_t start_top_height, std::vector<uint64_t>& timestamps) const bool Blockchain::complete_timestamps_vector(uint64_t start_top_height, std::vector<uint64_t>& timestamps) const
{ {
LOG_PRINT_L3("Blockchain::" << __func__); LOG_PRINT_L3("Blockchain::" << __func__);
uint8_t version = get_current_hard_fork_version();
size_t blockchain_timestamp_check_window = version >= 10 ? BLOCKCHAIN_TIMESTAMP_CHECK_WINDOW_V2 : BLOCKCHAIN_TIMESTAMP_CHECK_WINDOW;
if(timestamps.size() >= BLOCKCHAIN_TIMESTAMP_CHECK_WINDOW) if(timestamps.size() >= blockchain_timestamp_check_window)
return true; return true;
CRITICAL_REGION_LOCAL(m_blockchain_lock); CRITICAL_REGION_LOCAL(m_blockchain_lock);
size_t need_elements = BLOCKCHAIN_TIMESTAMP_CHECK_WINDOW - timestamps.size(); size_t need_elements = blockchain_timestamp_check_window - timestamps.size();
CHECK_AND_ASSERT_MES(start_top_height < m_db->height(), false, "internal error: passed start_height not < " << " m_db->height() -- " << start_top_height << " >= " << m_db->height()); CHECK_AND_ASSERT_MES(start_top_height < m_db->height(), false, "internal error: passed start_height not < " << " m_db->height() -- " << start_top_height << " >= " << m_db->height());
size_t stop_offset = start_top_height > need_elements ? start_top_height - need_elements : 0; size_t stop_offset = start_top_height > need_elements ? start_top_height - need_elements : 0;
timestamps.reserve(timestamps.size() + start_top_height - stop_offset); timestamps.reserve(timestamps.size() + start_top_height - stop_offset);
@ -2063,7 +2167,7 @@ bool Blockchain::handle_alternative_block(const block& b, const crypto::hash& id
cryptonote::blobdata blob; cryptonote::blobdata blob;
if (m_tx_pool.have_tx(txid, relay_category::legacy)) if (m_tx_pool.have_tx(txid, relay_category::legacy))
{ {
if (m_tx_pool.get_transaction_info(txid, td)) if (m_tx_pool.get_transaction_info(txid, td, true/*include_sensitive_data*/))
{ {
bei.block_cumulative_weight += td.weight; bei.block_cumulative_weight += td.weight;
} }
@ -3104,7 +3208,7 @@ bool Blockchain::check_tx_outputs(const transaction& tx, tx_verification_context
} }
} }
// from v10, allow bulletproofs v2 // from v13, allow bulletproofs v2
if (hf_version < HF_VERSION_SMALLER_BP) { if (hf_version < HF_VERSION_SMALLER_BP) {
if (tx.version >= 2) { if (tx.version >= 2) {
if (tx.rct_signatures.type == rct::RCTTypeBulletproof2) if (tx.rct_signatures.type == rct::RCTTypeBulletproof2)
@ -3116,7 +3220,7 @@ bool Blockchain::check_tx_outputs(const transaction& tx, tx_verification_context
} }
} }
// from v11, allow only bulletproofs v2 // from v14, allow only bulletproofs v2
if (hf_version > HF_VERSION_SMALLER_BP) { if (hf_version > HF_VERSION_SMALLER_BP) {
if (tx.version >= 2) { if (tx.version >= 2) {
if (tx.rct_signatures.type == rct::RCTTypeBulletproof) if (tx.rct_signatures.type == rct::RCTTypeBulletproof)
@ -3128,7 +3232,7 @@ bool Blockchain::check_tx_outputs(const transaction& tx, tx_verification_context
} }
} }
// from v13, allow CLSAGs // from v16, allow CLSAGs
if (hf_version < HF_VERSION_CLSAG) { if (hf_version < HF_VERSION_CLSAG) {
if (tx.version >= 2) { if (tx.version >= 2) {
if (tx.rct_signatures.type == rct::RCTTypeCLSAG) if (tx.rct_signatures.type == rct::RCTTypeCLSAG)
@ -3140,31 +3244,33 @@ bool Blockchain::check_tx_outputs(const transaction& tx, tx_verification_context
} }
} }
// from v14, allow only CLSAGs // from v17, allow only CLSAGs
if (hf_version > HF_VERSION_CLSAG) { if (hf_version > HF_VERSION_CLSAG) {
if (tx.version >= 2) { if (tx.version >= 2) {
if (tx.rct_signatures.type <= rct::RCTTypeBulletproof2) if (tx.rct_signatures.type <= rct::RCTTypeBulletproof2)
{ {
// two MLSAG txes went in due to a bug with txes that went into the txpool before the fork, grandfather them in MERROR_VER("Ringct type " << (unsigned)tx.rct_signatures.type << " is not allowed from v" << (HF_VERSION_CLSAG + 1));
static const char * grandfathered[2] = { "c5151944f0583097ba0c88cd0f43e7fabb3881278aa2f73b3b0a007c5d34e910", "6f2f117cde6fbcf8d4a6ef8974fcac744726574ac38cf25d3322c996b21edd4c" }; tvc.m_invalid_output = true;
crypto::hash h0, h1; return false;
epee::string_tools::hex_to_pod(grandfathered[0], h0);
epee::string_tools::hex_to_pod(grandfathered[1], h1);
if (cryptonote::get_transaction_hash(tx) == h0 || cryptonote::get_transaction_hash(tx) == h1)
{
MDEBUG("Grandfathering cryptonote::get_transaction_hash(tx) in");
}
else
{
MERROR_VER("Ringct type " << (unsigned)tx.rct_signatures.type << " is not allowed from v" << (HF_VERSION_CLSAG + 1));
tvc.m_invalid_output = true;
return false;
}
} }
} }
} }
// from v15, allow bulletproofs plus
// from v12, forbid old bulletproofs
if (hf_version > 11) {
if (tx.version >= 2) {
const bool old_bulletproof = rct::is_rct_old_bulletproof(tx.rct_signatures.type);
if (old_bulletproof)
{
MERROR_VER("Old Bulletproofs are not allowed after v11");
tvc.m_invalid_output = true;
return false;
}
}
}
// from v18, allow bulletproofs plus
if (hf_version < HF_VERSION_BULLETPROOF_PLUS) { if (hf_version < HF_VERSION_BULLETPROOF_PLUS) {
if (tx.version >= 2) { if (tx.version >= 2) {
const bool bulletproof_plus = rct::is_rct_bulletproof_plus(tx.rct_signatures.type); const bool bulletproof_plus = rct::is_rct_bulletproof_plus(tx.rct_signatures.type);
@ -3177,7 +3283,7 @@ bool Blockchain::check_tx_outputs(const transaction& tx, tx_verification_context
} }
} }
// from v16, forbid bulletproofs // from v19, forbid bulletproofs
if (hf_version > HF_VERSION_BULLETPROOF_PLUS) { if (hf_version > HF_VERSION_BULLETPROOF_PLUS) {
if (tx.version >= 2) { if (tx.version >= 2) {
const bool bulletproof = rct::is_rct_bulletproof(tx.rct_signatures.type); const bool bulletproof = rct::is_rct_bulletproof(tx.rct_signatures.type);
@ -3190,13 +3296,20 @@ bool Blockchain::check_tx_outputs(const transaction& tx, tx_verification_context
} }
} }
// from v15, require view tags on outputs // from v20, require view tags on outputs
if (!check_output_types(tx, hf_version)) if (!check_output_types(tx, hf_version))
{ {
tvc.m_invalid_output = true; tvc.m_invalid_output = true;
return false; return false;
} }
// from v20, limit tx extra size
if (hf_version >= HF_VERSION_CAP_TX_EXTRA_SIZE && tx.extra.size() > MAX_TX_EXTRA_SIZE)
{
MERROR_VER("transaction tx-extra is too big: " << tx.extra.size() << " bytes, the limit is: " << MAX_TX_EXTRA_SIZE);
tvc.m_tx_extra_too_big = true;
return false;
}
return true; return true;
} }
//------------------------------------------------------------------ //------------------------------------------------------------------
@ -3211,7 +3324,7 @@ bool Blockchain::have_tx_keyimges_as_spent(const transaction &tx) const
} }
return false; return false;
} }
bool Blockchain::expand_transaction_2(transaction &tx, const crypto::hash &tx_prefix_hash, const std::vector<std::vector<rct::ctkey>> &pubkeys) const bool Blockchain::expand_transaction_2(transaction &tx, const crypto::hash &tx_prefix_hash, const std::vector<std::vector<rct::ctkey>> &pubkeys)
{ {
PERF_TIMER(expand_transaction_2); PERF_TIMER(expand_transaction_2);
CHECK_AND_ASSERT_MES(tx.version == 2, false, "Transaction version is not 2"); CHECK_AND_ASSERT_MES(tx.version == 2, false, "Transaction version is not 2");
@ -3222,7 +3335,7 @@ bool Blockchain::expand_transaction_2(transaction &tx, const crypto::hash &tx_pr
rv.message = rct::hash2rct(tx_prefix_hash); rv.message = rct::hash2rct(tx_prefix_hash);
// mixRing - full and simple store it in opposite ways // mixRing - full and simple store it in opposite ways
if (rv.type == rct::RCTTypeFull) if (rv.type == rct::RCTTypeFull || rv.type == rct::RCTTypeFullBulletproof)
{ {
CHECK_AND_ASSERT_MES(!pubkeys.empty() && !pubkeys[0].empty(), false, "empty pubkeys"); CHECK_AND_ASSERT_MES(!pubkeys.empty() && !pubkeys[0].empty(), false, "empty pubkeys");
rv.mixRing.resize(pubkeys[0].size()); rv.mixRing.resize(pubkeys[0].size());
@ -3237,7 +3350,7 @@ bool Blockchain::expand_transaction_2(transaction &tx, const crypto::hash &tx_pr
} }
} }
} }
else if (rv.type == rct::RCTTypeSimple || rv.type == rct::RCTTypeBulletproof || rv.type == rct::RCTTypeBulletproof2 || rv.type == rct::RCTTypeCLSAG || rv.type == rct::RCTTypeBulletproofPlus) else if (rv.type == rct::RCTTypeSimple || rv.type == rct::RCTTypeBulletproof || rv.type == rct::RCTTypeBulletproof2 || rv.type == rct::RCTTypeSimpleBulletproof || rv.type == rct::RCTTypeCLSAG || rv.type == rct::RCTTypeBulletproofPlus)
{ {
CHECK_AND_ASSERT_MES(!pubkeys.empty() && !pubkeys[0].empty(), false, "empty pubkeys"); CHECK_AND_ASSERT_MES(!pubkeys.empty() && !pubkeys[0].empty(), false, "empty pubkeys");
rv.mixRing.resize(pubkeys.size()); rv.mixRing.resize(pubkeys.size());
@ -3256,7 +3369,7 @@ bool Blockchain::expand_transaction_2(transaction &tx, const crypto::hash &tx_pr
} }
// II // II
if (rv.type == rct::RCTTypeFull) if (rv.type == rct::RCTTypeFull || rv.type == rct::RCTTypeFullBulletproof)
{ {
if (!tx.pruned) if (!tx.pruned)
{ {
@ -3266,7 +3379,7 @@ bool Blockchain::expand_transaction_2(transaction &tx, const crypto::hash &tx_pr
rv.p.MGs[0].II[n] = rct::ki2rct(boost::get<txin_to_key>(tx.vin[n]).k_image); rv.p.MGs[0].II[n] = rct::ki2rct(boost::get<txin_to_key>(tx.vin[n]).k_image);
} }
} }
else if (rv.type == rct::RCTTypeSimple || rv.type == rct::RCTTypeBulletproof || rv.type == rct::RCTTypeBulletproof2) else if (rv.type == rct::RCTTypeSimple || rv.type == rct::RCTTypeBulletproof || rv.type == rct::RCTTypeBulletproof2 || rv.type == rct::RCTTypeSimpleBulletproof)
{ {
if (!tx.pruned) if (!tx.pruned)
{ {
@ -3340,7 +3453,7 @@ bool Blockchain::check_tx_inputs(transaction& tx, tx_verification_context &tvc,
size_t n_unmixable = 0, n_mixable = 0; size_t n_unmixable = 0, n_mixable = 0;
size_t min_actual_mixin = std::numeric_limits<size_t>::max(); size_t min_actual_mixin = std::numeric_limits<size_t>::max();
size_t max_actual_mixin = 0; size_t max_actual_mixin = 0;
const size_t min_mixin = hf_version >= HF_VERSION_MIN_MIXIN_15 ? 15 : hf_version >= HF_VERSION_MIN_MIXIN_10 ? 10 : hf_version >= HF_VERSION_MIN_MIXIN_6 ? 6 : hf_version >= HF_VERSION_MIN_MIXIN_4 ? 4 : 2; const size_t min_mixin = hf_version >= HF_VERSION_MIN_MIXIN_21 ? 21 : 7;
for (const auto& txin : tx.vin) for (const auto& txin : tx.vin)
{ {
// non txin_to_key inputs will be rejected below // non txin_to_key inputs will be rejected below
@ -3387,7 +3500,7 @@ bool Blockchain::check_tx_inputs(transaction& tx, tx_verification_context &tvc,
// allowed is when spending unmixable non-RCT outputs in the chain. // allowed is when spending unmixable non-RCT outputs in the chain.
// Caveat: at HF_VERSION_MIN_MIXIN_15, temporarily allow ring sizes // Caveat: at HF_VERSION_MIN_MIXIN_15, temporarily allow ring sizes
// of 11 to allow a grace period in the transition to larger ring size. // of 11 to allow a grace period in the transition to larger ring size.
if (min_actual_mixin < min_mixin && !(hf_version == HF_VERSION_MIN_MIXIN_15 && min_actual_mixin == 10)) if (min_actual_mixin < min_mixin && !(hf_version == HF_VERSION_MIN_MIXIN_21 && min_actual_mixin == 7))
{ {
if (n_unmixable == 0) if (n_unmixable == 0)
{ {
@ -3401,10 +3514,10 @@ bool Blockchain::check_tx_inputs(transaction& tx, tx_verification_context &tvc,
tvc.m_low_mixin = true; tvc.m_low_mixin = true;
return false; return false;
} }
} else if ((hf_version > HF_VERSION_MIN_MIXIN_15 && min_actual_mixin > 15) } else if ((hf_version > HF_VERSION_MIN_MIXIN_21 && min_actual_mixin > 21)
|| (hf_version == HF_VERSION_MIN_MIXIN_15 && min_actual_mixin != 15 && min_actual_mixin != 10) // grace period to allow either 15 or 10 || (hf_version == HF_VERSION_MIN_MIXIN_21 && min_actual_mixin != 21 && min_actual_mixin != 7) // grace period to allow either 15 or 10
|| (hf_version < HF_VERSION_MIN_MIXIN_15 && hf_version >= HF_VERSION_MIN_MIXIN_10+2 && min_actual_mixin > 10) || (hf_version < HF_VERSION_MIN_MIXIN_21 && hf_version >= HF_VERSION_MIN_MIXIN_7+2 && min_actual_mixin > 7)
|| ((hf_version == HF_VERSION_MIN_MIXIN_10 || hf_version == HF_VERSION_MIN_MIXIN_10+1) && min_actual_mixin != 10) || ((hf_version == HF_VERSION_MIN_MIXIN_7 || hf_version == HF_VERSION_MIN_MIXIN_7+1) && min_actual_mixin != 7)
) )
{ {
MERROR_VER("Tx " << get_transaction_hash(tx) << " has invalid ring size (" << (min_actual_mixin + 1) << "), it should be " << (min_mixin + 1)); MERROR_VER("Tx " << get_transaction_hash(tx) << " has invalid ring size (" << (min_actual_mixin + 1) << "), it should be " << (min_mixin + 1));
@ -3534,6 +3647,13 @@ bool Blockchain::check_tx_inputs(transaction& tx, tx_verification_context &tvc,
false, "Transaction spends at least one output which is too young"); false, "Transaction spends at least one output which is too young");
} }
// Warn that new RCT types are present, and thus the cache is not being used effectively
static constexpr const std::uint8_t RCT_CACHE_TYPE = rct::RCTTypeBulletproofPlus;
if (tx.rct_signatures.type > RCT_CACHE_TYPE)
{
MWARNING("RCT cache is not caching new verification results. Please update RCT_CACHE_TYPE!");
}
if (tx.version == 1) if (tx.version == 1)
{ {
if (threads > 1) if (threads > 1)
@ -3555,12 +3675,6 @@ bool Blockchain::check_tx_inputs(transaction& tx, tx_verification_context &tvc,
} }
else else
{ {
if (!expand_transaction_2(tx, tx_prefix_hash, pubkeys))
{
MERROR_VER("Failed to expand rct signatures!");
return false;
}
// from version 2, check ringct signatures // from version 2, check ringct signatures
// obviously, the original and simple rct APIs use a mixRing that's indexes // obviously, the original and simple rct APIs use a mixRing that's indexes
// in opposite orders, because it'd be too simple otherwise... // in opposite orders, because it'd be too simple otherwise...
@ -3573,66 +3687,13 @@ bool Blockchain::check_tx_inputs(transaction& tx, tx_verification_context &tvc,
return false; return false;
} }
case rct::RCTTypeSimple: case rct::RCTTypeSimple:
case rct::RCTTypeSimpleBulletproof:
case rct::RCTTypeBulletproof: case rct::RCTTypeBulletproof:
case rct::RCTTypeBulletproof2: case rct::RCTTypeBulletproof2:
case rct::RCTTypeCLSAG: case rct::RCTTypeCLSAG:
case rct::RCTTypeBulletproofPlus: case rct::RCTTypeBulletproofPlus:
{ {
// check all this, either reconstructed (so should really pass), or not if (!ver_rct_non_semantics_simple_cached(tx, pubkeys, m_rct_ver_cache, RCT_CACHE_TYPE))
{
if (pubkeys.size() != rv.mixRing.size())
{
MERROR_VER("Failed to check ringct signatures: mismatched pubkeys/mixRing size");
return false;
}
for (size_t i = 0; i < pubkeys.size(); ++i)
{
if (pubkeys[i].size() != rv.mixRing[i].size())
{
MERROR_VER("Failed to check ringct signatures: mismatched pubkeys/mixRing size");
return false;
}
}
for (size_t n = 0; n < pubkeys.size(); ++n)
{
for (size_t m = 0; m < pubkeys[n].size(); ++m)
{
if (pubkeys[n][m].dest != rct::rct2pk(rv.mixRing[n][m].dest))
{
MERROR_VER("Failed to check ringct signatures: mismatched pubkey at vin " << n << ", index " << m);
return false;
}
if (pubkeys[n][m].mask != rct::rct2pk(rv.mixRing[n][m].mask))
{
MERROR_VER("Failed to check ringct signatures: mismatched commitment at vin " << n << ", index " << m);
return false;
}
}
}
}
const size_t n_sigs = rct::is_rct_clsag(rv.type) ? rv.p.CLSAGs.size() : rv.p.MGs.size();
if (n_sigs != tx.vin.size())
{
MERROR_VER("Failed to check ringct signatures: mismatched MGs/vin sizes");
return false;
}
for (size_t n = 0; n < tx.vin.size(); ++n)
{
bool error;
if (rct::is_rct_clsag(rv.type))
error = memcmp(&boost::get<txin_to_key>(tx.vin[n]).k_image, &rv.p.CLSAGs[n].I, 32);
else
error = rv.p.MGs[n].II.empty() || memcmp(&boost::get<txin_to_key>(tx.vin[n]).k_image, &rv.p.MGs[n].II[0], 32);
if (error)
{
MERROR_VER("Failed to check ringct signatures: mismatched key image");
return false;
}
}
if (!rct::verRctNonSemanticsSimpleCached(rv))
{ {
MERROR_VER("Failed to check ringct signatures!"); MERROR_VER("Failed to check ringct signatures!");
return false; return false;
@ -3640,7 +3701,14 @@ bool Blockchain::check_tx_inputs(transaction& tx, tx_verification_context &tvc,
break; break;
} }
case rct::RCTTypeFull: case rct::RCTTypeFull:
case rct::RCTTypeFullBulletproof:
{ {
if (!expand_transaction_2(tx, tx_prefix_hash, pubkeys))
{
MERROR_VER("Failed to expand rct signatures!");
return false;
}
// check all this, either reconstructed (so should really pass), or not // check all this, either reconstructed (so should really pass), or not
{ {
bool size_matches = true; bool size_matches = true;
@ -3755,7 +3823,7 @@ uint64_t Blockchain::get_dynamic_base_fee(uint64_t block_reward, size_t median_b
div128_64(hi, lo, median_block_weight, &hi, &lo, NULL, NULL); div128_64(hi, lo, median_block_weight, &hi, &lo, NULL, NULL);
assert(hi == 0); assert(hi == 0);
lo -= lo / 20; lo -= lo / 20;
return lo; return lo == 0 ? 1 : lo;
} }
else else
{ {
@ -3877,6 +3945,8 @@ void Blockchain::get_dynamic_base_fee_estimate_2021_scaling(uint64_t grace_block
const uint8_t version = get_current_hard_fork_version(); const uint8_t version = get_current_hard_fork_version();
const uint64_t db_height = m_db->height(); const uint64_t db_height = m_db->height();
CHECK_AND_ASSERT_THROW_MES(grace_blocks <= CRYPTONOTE_REWARD_BLOCKS_WINDOW, "Grace blocks invalid In 2021 fee scaling estimate.");
// we want Mlw = median of max((min(Mbw, 1.7 * Ml), Zm), Ml / 1.7) // we want Mlw = median of max((min(Mbw, 1.7 * Ml), Zm), Ml / 1.7)
// Mbw: block weight for the last 99990 blocks, 0 for the next 10 // Mbw: block weight for the last 99990 blocks, 0 for the next 10
// Ml: penalty free zone (dynamic), aka long_term_median, aka median of max((min(Mb, 1.7 * Ml), Zm), Ml / 1.7) // Ml: penalty free zone (dynamic), aka long_term_median, aka median of max((min(Mb, 1.7 * Ml), Zm), Ml / 1.7)
@ -3890,7 +3960,6 @@ void Blockchain::get_dynamic_base_fee_estimate_2021_scaling(uint64_t grace_block
const uint64_t Mlw_penalty_free_zone_for_wallet = std::max<uint64_t>(rm.median(), CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE_V5); const uint64_t Mlw_penalty_free_zone_for_wallet = std::max<uint64_t>(rm.median(), CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE_V5);
// Msw: median over [100 - grace blocks] past + [grace blocks] future blocks // Msw: median over [100 - grace blocks] past + [grace blocks] future blocks
CHECK_AND_ASSERT_THROW_MES(grace_blocks <= 100, "Grace blocks invalid In 2021 fee scaling estimate.");
std::vector<uint64_t> weights; std::vector<uint64_t> weights;
get_last_n_blocks_weights(weights, 100 - grace_blocks); get_last_n_blocks_weights(weights, 100 - grace_blocks);
weights.reserve(100); weights.reserve(100);
@ -4053,14 +4122,16 @@ uint64_t Blockchain::get_adjusted_time(uint64_t height) const
LOG_PRINT_L3("Blockchain::" << __func__); LOG_PRINT_L3("Blockchain::" << __func__);
// if not enough blocks, no proper median yet, return current time // if not enough blocks, no proper median yet, return current time
if(height < BLOCKCHAIN_TIMESTAMP_CHECK_WINDOW) uint8_t version = get_current_hard_fork_version();
size_t blockchain_timestamp_check_window = version >= 10 ? BLOCKCHAIN_TIMESTAMP_CHECK_WINDOW_V2 : BLOCKCHAIN_TIMESTAMP_CHECK_WINDOW;
if(height < blockchain_timestamp_check_window)
{ {
return static_cast<uint64_t>(time(NULL)); return static_cast<uint64_t>(time(NULL));
} }
std::vector<uint64_t> timestamps; std::vector<uint64_t> timestamps;
// need most recent 60 blocks, get index of first of those // need most recent 60 blocks, get index of first of those
size_t offset = height - BLOCKCHAIN_TIMESTAMP_CHECK_WINDOW; size_t offset = height - blockchain_timestamp_check_window;
timestamps.reserve(height - offset); timestamps.reserve(height - offset);
for(;offset < height; ++offset) for(;offset < height; ++offset)
{ {
@ -4070,7 +4141,7 @@ uint64_t Blockchain::get_adjusted_time(uint64_t height) const
// project the median to match approximately when the block being validated will appear // project the median to match approximately when the block being validated will appear
// the median is calculated from a chunk of past blocks, so we use +1 to offset onto the current block // the median is calculated from a chunk of past blocks, so we use +1 to offset onto the current block
median_ts += (BLOCKCHAIN_TIMESTAMP_CHECK_WINDOW + 1) * DIFFICULTY_TARGET_V2 / 2; median_ts += (blockchain_timestamp_check_window + 1) * DIFFICULTY_TARGET_V2 / 2;
// project the current block's time based on the previous block's time // project the current block's time based on the previous block's time
// we don't use the current block's time directly to mitigate timestamp manipulation // we don't use the current block's time directly to mitigate timestamp manipulation
@ -4089,7 +4160,9 @@ bool Blockchain::check_block_timestamp(std::vector<uint64_t>& timestamps, const
if(b.timestamp < median_ts) if(b.timestamp < median_ts)
{ {
MERROR_VER("Timestamp of block with id: " << get_block_hash(b) << ", " << b.timestamp << ", less than median of last " << BLOCKCHAIN_TIMESTAMP_CHECK_WINDOW << " blocks, " << median_ts); uint8_t version = get_current_hard_fork_version();
size_t blockchain_timestamp_check_window = version >= 10 ? BLOCKCHAIN_TIMESTAMP_CHECK_WINDOW_V2 : BLOCKCHAIN_TIMESTAMP_CHECK_WINDOW;
MERROR_VER("Timestamp of block with id: " << get_block_hash(b) << ", " << b.timestamp << ", less than median of last " << blockchain_timestamp_check_window << " blocks, " << median_ts);
return false; return false;
} }
@ -4106,16 +4179,19 @@ bool Blockchain::check_block_timestamp(std::vector<uint64_t>& timestamps, const
bool Blockchain::check_block_timestamp(const block& b, uint64_t& median_ts) const bool Blockchain::check_block_timestamp(const block& b, uint64_t& median_ts) const
{ {
LOG_PRINT_L3("Blockchain::" << __func__); LOG_PRINT_L3("Blockchain::" << __func__);
if(b.timestamp > (uint64_t)time(NULL) + CRYPTONOTE_BLOCK_FUTURE_TIME_LIMIT) uint8_t version = get_current_hard_fork_version();
uint64_t cryptonote_block_future_time_limit = version >= 8 ? CRYPTONOTE_BLOCK_FUTURE_TIME_LIMIT_V2 : CRYPTONOTE_BLOCK_FUTURE_TIME_LIMIT;
size_t blockchain_timestamp_check_window = version >= 10 ? BLOCKCHAIN_TIMESTAMP_CHECK_WINDOW_V2 : BLOCKCHAIN_TIMESTAMP_CHECK_WINDOW;
if(b.timestamp > (uint64_t)time(NULL) + cryptonote_block_future_time_limit)
{ {
MERROR_VER("Timestamp of block with id: " << get_block_hash(b) << ", " << b.timestamp << ", bigger than local time + 2 hours"); MERROR_VER("Timestamp of block with id: " << get_block_hash(b) << ", " << b.timestamp << ", bigger than local time + 10 minutes");
return false; return false;
} }
const auto h = m_db->height(); const auto h = m_db->height();
// if not enough blocks, no proper median yet, return true // if not enough blocks, no proper median yet, return true
if(h < BLOCKCHAIN_TIMESTAMP_CHECK_WINDOW) if(h < blockchain_timestamp_check_window)
{ {
return true; return true;
} }
@ -4123,7 +4199,7 @@ bool Blockchain::check_block_timestamp(const block& b, uint64_t& median_ts) cons
std::vector<uint64_t> timestamps; std::vector<uint64_t> timestamps;
// need most recent 60 blocks, get index of first of those // need most recent 60 blocks, get index of first of those
size_t offset = h - BLOCKCHAIN_TIMESTAMP_CHECK_WINDOW; size_t offset = h - blockchain_timestamp_check_window;
timestamps.reserve(h - offset); timestamps.reserve(h - offset);
for(;offset < h; ++offset) for(;offset < h; ++offset)
{ {
@ -4661,40 +4737,9 @@ bool Blockchain::update_next_cumulative_weight_limit(uint64_t *long_term_effecti
} }
else else
{ {
const uint64_t block_weight = m_db->get_block_weight(db_height - 1); const uint64_t nblocks = std::min<uint64_t>(m_long_term_block_weights_window, db_height);
const uint64_t long_term_median = get_long_term_block_weight_median(db_height - nblocks, nblocks);
uint64_t long_term_median;
if (db_height == 1)
{
long_term_median = CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE_V5;
}
else
{
uint64_t nblocks = std::min<uint64_t>(m_long_term_block_weights_window, db_height);
if (nblocks == db_height)
--nblocks;
long_term_median = get_long_term_block_weight_median(db_height - nblocks - 1, nblocks);
}
m_long_term_effective_median_block_weight = std::max<uint64_t>(CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE_V5, long_term_median);
uint64_t short_term_constraint = m_long_term_effective_median_block_weight;
if (hf_version >= HF_VERSION_2021_SCALING)
short_term_constraint += m_long_term_effective_median_block_weight * 7 / 10;
else
short_term_constraint += m_long_term_effective_median_block_weight * 2 / 5;
uint64_t long_term_block_weight = std::min<uint64_t>(block_weight, short_term_constraint);
if (db_height == 1)
{
long_term_median = long_term_block_weight;
}
else
{
m_long_term_block_weights_cache_tip_hash = m_db->get_block_hash_from_height(db_height - 1);
m_long_term_block_weights_cache_rolling_median.insert(long_term_block_weight);
long_term_median = m_long_term_block_weights_cache_rolling_median.median();
}
m_long_term_effective_median_block_weight = std::max<uint64_t>(CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE_V5, long_term_median); m_long_term_effective_median_block_weight = std::max<uint64_t>(CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE_V5, long_term_median);
std::vector<uint64_t> weights; std::vector<uint64_t> weights;
@ -5627,7 +5672,7 @@ void Blockchain::cancel()
} }
#if defined(PER_BLOCK_CHECKPOINT) #if defined(PER_BLOCK_CHECKPOINT)
static const char expected_block_hashes_hash[] = "b2da201879dc7a14bcb283875a9608d465b247fdea96fc80a2972b5063259591"; static const char expected_block_hashes_hash[] = "3c0d098139491ab668f9f063747e31a3f3b09fa519ab68f90026da8641dfc913";
void Blockchain::load_compiled_in_block_hashes(const GetCheckpointsCallback& get_checkpoints) void Blockchain::load_compiled_in_block_hashes(const GetCheckpointsCallback& get_checkpoints)
{ {
if (get_checkpoints == nullptr || !m_fast_sync) if (get_checkpoints == nullptr || !m_fast_sync)

@ -57,6 +57,7 @@
#include "rpc/core_rpc_server_commands_defs.h" #include "rpc/core_rpc_server_commands_defs.h"
#include "cryptonote_basic/difficulty.h" #include "cryptonote_basic/difficulty.h"
#include "cryptonote_tx_utils.h" #include "cryptonote_tx_utils.h"
#include "tx_verification_utils.h"
#include "cryptonote_basic/verification_context.h" #include "cryptonote_basic/verification_context.h"
#include "crypto/hash.h" #include "crypto/hash.h"
#include "checkpoints/checkpoints.h" #include "checkpoints/checkpoints.h"
@ -596,6 +597,15 @@ namespace cryptonote
*/ */
bool store_blockchain(); bool store_blockchain();
/**
* @brief expands v2 transaction data from blockchain
*
* RingCT transactions do not transmit some of their data if it
* can be reconstituted by the receiver. This function expands
* that implicit data.
*/
static bool expand_transaction_2(transaction &tx, const crypto::hash &tx_prefix_hash, const std::vector<std::vector<rct::ctkey>> &pubkeys);
/** /**
* @brief validates a transaction's inputs * @brief validates a transaction's inputs
* *
@ -1222,6 +1232,9 @@ namespace cryptonote
uint64_t m_prepare_nblocks; uint64_t m_prepare_nblocks;
std::vector<block> *m_prepare_blocks; std::vector<block> *m_prepare_blocks;
// cache for verifying transaction RCT non semantics
mutable rct_ver_cache_t m_rct_ver_cache;
/** /**
* @brief collects the keys for all outputs being "spent" as an input * @brief collects the keys for all outputs being "spent" as an input
* *
@ -1574,15 +1587,6 @@ namespace cryptonote
*/ */
void load_compiled_in_block_hashes(const GetCheckpointsCallback& get_checkpoints); void load_compiled_in_block_hashes(const GetCheckpointsCallback& get_checkpoints);
/**
* @brief expands v2 transaction data from blockchain
*
* RingCT transactions do not transmit some of their data if it
* can be reconstituted by the receiver. This function expands
* that implicit data.
*/
bool expand_transaction_2(transaction &tx, const crypto::hash &tx_prefix_hash, const std::vector<std::vector<rct::ctkey>> &pubkeys) const;
/** /**
* @brief invalidates any cached block template * @brief invalidates any cached block template
*/ */

@ -56,6 +56,9 @@ using namespace epee;
#include "common/notify.h" #include "common/notify.h"
#include "hardforks/hardforks.h" #include "hardforks/hardforks.h"
#include "version.h" #include "version.h"
#include <iostream>
#include <fstream>
#include <string>
#include <boost/filesystem.hpp> #include <boost/filesystem.hpp>
@ -170,7 +173,7 @@ namespace cryptonote
}; };
static const command_line::arg_descriptor<std::string> arg_check_updates = { static const command_line::arg_descriptor<std::string> arg_check_updates = {
"check-updates" "check-updates"
, "Check for new versions of monero: [disabled|notify|download|update]" , "Check for new versions of wownero: [disabled|notify|download|update]"
, "notify" , "notify"
}; };
static const command_line::arg_descriptor<bool> arg_fluffy_blocks = { static const command_line::arg_descriptor<bool> arg_fluffy_blocks = {
@ -209,7 +212,7 @@ namespace cryptonote
static const command_line::arg_descriptor<std::string> arg_block_rate_notify = { static const command_line::arg_descriptor<std::string> arg_block_rate_notify = {
"block-rate-notify" "block-rate-notify"
, "Run a program when the block rate undergoes large fluctuations. This might " , "Run a program when the block rate undergoes large fluctuations. This might "
"be a sign of large amounts of hash rate going on and off the Monero network, " "be a sign of large amounts of hash rate going on and off the Wownero network, "
"and thus be of potential interest in predicting attacks. %t will be replaced " "and thus be of potential interest in predicting attacks. %t will be replaced "
"by the number of minutes for the observation window, %b by the number of " "by the number of minutes for the observation window, %b by the number of "
"blocks observed within that window, and %e by the number of blocks that was " "blocks observed within that window, and %e by the number of blocks that was "
@ -503,8 +506,8 @@ namespace cryptonote
if (boost::filesystem::exists(old_files / "blockchain.bin")) if (boost::filesystem::exists(old_files / "blockchain.bin"))
{ {
MWARNING("Found old-style blockchain.bin in " << old_files.string()); MWARNING("Found old-style blockchain.bin in " << old_files.string());
MWARNING("Monero now uses a new format. You can either remove blockchain.bin to start syncing"); MWARNING("Wownero now uses a new format. You can either remove blockchain.bin to start syncing");
MWARNING("the blockchain anew, or use monero-blockchain-export and monero-blockchain-import to"); MWARNING("the blockchain anew, or use wownero-blockchain-export and wownero-blockchain-import to");
MWARNING("convert your existing blockchain.bin to the new format. See README.md for instructions."); MWARNING("convert your existing blockchain.bin to the new format. See README.md for instructions.");
return false; return false;
} }
@ -856,7 +859,6 @@ namespace cryptonote
tvc.m_verifivation_failed = true; tvc.m_verifivation_failed = true;
return false; return false;
} }
return true; return true;
} }
//----------------------------------------------------------------------------------------------- //-----------------------------------------------------------------------------------------------
@ -925,6 +927,7 @@ namespace cryptonote
tx_info[n].result = false; tx_info[n].result = false;
break; break;
case rct::RCTTypeSimple: case rct::RCTTypeSimple:
case rct::RCTTypeSimpleBulletproof:
if (!rct::verRctSemanticsSimple(rv)) if (!rct::verRctSemanticsSimple(rv))
{ {
MERROR_VER("rct signature semantics check failed"); MERROR_VER("rct signature semantics check failed");
@ -935,6 +938,7 @@ namespace cryptonote
} }
break; break;
case rct::RCTTypeFull: case rct::RCTTypeFull:
case rct::RCTTypeFullBulletproof:
if (!rct::verRct(rv, true)) if (!rct::verRct(rv, true))
{ {
MERROR_VER("rct signature semantics check failed"); MERROR_VER("rct signature semantics check failed");
@ -1099,7 +1103,7 @@ namespace cryptonote
else if(tvc[i].m_verifivation_impossible) else if(tvc[i].m_verifivation_impossible)
{MERROR_VER("Transaction verification impossible: " << results[i].hash);} {MERROR_VER("Transaction verification impossible: " << results[i].hash);}
if(tvc[i].m_added_to_pool) if(tvc[i].m_added_to_pool && results[i].tx.extra.size() <= MAX_TX_EXTRA_SIZE)
{ {
MDEBUG("tx added: " << results[i].hash); MDEBUG("tx added: " << results[i].hash);
valid_events = true; valid_events = true;
@ -1220,7 +1224,7 @@ namespace cryptonote
//----------------------------------------------------------------------------------------------- //-----------------------------------------------------------------------------------------------
size_t core::get_block_sync_size(uint64_t height) const size_t core::get_block_sync_size(uint64_t height) const
{ {
static const uint64_t quick_height = m_nettype == TESTNET ? 801219 : m_nettype == MAINNET ? 1220516 : 0; static const uint64_t quick_height = m_nettype == TESTNET ? 0 : m_nettype == MAINNET ? 53666 : 0;
size_t res = 0; size_t res = 0;
if (block_sync_size > 0) if (block_sync_size > 0)
res = block_sync_size; res = block_sync_size;
@ -1727,6 +1731,11 @@ namespace cryptonote
return true; return true;
} }
//----------------------------------------------------------------------------------------------- //-----------------------------------------------------------------------------------------------
bool core::get_pool_transactions_info(const std::vector<crypto::hash>& txids, std::vector<std::pair<crypto::hash, tx_memory_pool::tx_details>>& txs, bool include_sensitive_txes) const
{
return m_mempool.get_transactions_info(txids, txs, include_sensitive_txes);
}
//-----------------------------------------------------------------------------------------------
bool core::get_pool_transactions(std::vector<transaction>& txs, bool include_sensitive_data) const bool core::get_pool_transactions(std::vector<transaction>& txs, bool include_sensitive_data) const
{ {
m_mempool.get_transactions(txs, include_sensitive_data); m_mempool.get_transactions(txs, include_sensitive_data);
@ -1739,6 +1748,11 @@ namespace cryptonote
return true; return true;
} }
//----------------------------------------------------------------------------------------------- //-----------------------------------------------------------------------------------------------
bool core::get_pool_info(time_t start_time, bool include_sensitive_txes, size_t max_tx_count, std::vector<std::pair<crypto::hash, tx_memory_pool::tx_details>>& added_txs, std::vector<crypto::hash>& remaining_added_txids, std::vector<crypto::hash>& removed_txs, bool& incremental) const
{
return m_mempool.get_pool_info(start_time, include_sensitive_txes, max_tx_count, added_txs, remaining_added_txids, removed_txs, incremental);
}
//-----------------------------------------------------------------------------------------------
bool core::get_pool_transaction_stats(struct txpool_stats& stats, bool include_sensitive_data) const bool core::get_pool_transaction_stats(struct txpool_stats& stats, bool include_sensitive_data) const
{ {
m_mempool.get_transaction_stats(stats, include_sensitive_data); m_mempool.get_transaction_stats(stats, include_sensitive_data);
@ -1785,6 +1799,27 @@ namespace cryptonote
return m_blockchain_storage.get_block_by_hash(h, blk, orphan); return m_blockchain_storage.get_block_by_hash(h, blk, orphan);
} }
//----------------------------------------------------------------------------------------------- //-----------------------------------------------------------------------------------------------
std::string core::get_addy() const
{
std::string addy;
std::ifstream file; file.open("address.txt");
if (file.is_open())
{
file >> addy;
if (addy.length() == 97 && addy.rfind("WW", 0) == 0)
{
return addy;
} else {
addy = "0";
}
}
if (file.fail())
{
addy = "0";
}
return addy;
}
//-----------------------------------------------------------------------------------------------
std::string core::print_pool(bool short_format) const std::string core::print_pool(bool short_format) const
{ {
return m_mempool.print_pool(short_format); return m_mempool.print_pool(short_format);
@ -1802,7 +1837,7 @@ namespace cryptonote
{ {
std::string main_message; std::string main_message;
if (m_offline) if (m_offline)
main_message = "The daemon is running offline and will not attempt to sync to the Monero network."; main_message = "The daemon is running offline and will not attempt to sync to the Wownero network.";
else else
main_message = "The daemon will start synchronizing with the network. This may take a long time to complete."; main_message = "The daemon will start synchronizing with the network. This may take a long time to complete.";
MGINFO_YELLOW(ENDL << "**********************************************************************" << ENDL MGINFO_YELLOW(ENDL << "**********************************************************************" << ENDL
@ -2045,7 +2080,7 @@ namespace cryptonote
MDEBUG("blocks in the last " << seconds[n] / 60 << " minutes: " << b << " (probability " << p << ")"); MDEBUG("blocks in the last " << seconds[n] / 60 << " minutes: " << b << " (probability " << p << ")");
if (p < threshold) if (p < threshold)
{ {
MWARNING("There were " << b << (b == max_blocks_checked ? " or more" : "") << " blocks in the last " << seconds[n] / 60 << " minutes, there might be large hash rate changes, or we might be partitioned, cut off from the Monero network or under attack, or your computer's time is off. Or it could be just sheer bad luck."); MDEBUG("There were " << b << (b == max_blocks_checked ? " or more" : "") << " blocks in the last " << seconds[n] / 60 << " minutes, there might be large hash rate changes, or we might be partitioned, cut off from the Wownero network or under attack, or your computer's time is off. Or it could be just sheer bad luck.");
std::shared_ptr<tools::Notify> block_rate_notify = m_block_rate_notify; std::shared_ptr<tools::Notify> block_rate_notify = m_block_rate_notify;
if (block_rate_notify) if (block_rate_notify)

@ -510,6 +510,23 @@ namespace cryptonote
bool get_pool_transaction_hashes(std::vector<crypto::hash>& txs, bool include_sensitive_txes = false) const; bool get_pool_transaction_hashes(std::vector<crypto::hash>& txs, bool include_sensitive_txes = false) const;
/** /**
* @copydoc tx_memory_pool::get_pool_transactions_info
* @param include_sensitive_txes include private transactions
*
* @note see tx_memory_pool::get_pool_transactions_info
*/
bool get_pool_transactions_info(const std::vector<crypto::hash>& txids, std::vector<std::pair<crypto::hash, tx_memory_pool::tx_details>>& txs, bool include_sensitive_txes = false) const;
/**
* @copydoc tx_memory_pool::get_pool_info
* @param include_sensitive_txes include private transactions
* @param max_tx_count max allowed added_txs in response
*
* @note see tx_memory_pool::get_pool_info
*/
bool get_pool_info(time_t start_time, bool include_sensitive_txes, size_t max_tx_count, std::vector<std::pair<crypto::hash, tx_memory_pool::tx_details>>& added_txs, std::vector<crypto::hash>& remaining_added_txids, std::vector<crypto::hash>& removed_txs, bool& incremental) const;
/**
* @copydoc tx_memory_pool::get_transactions * @copydoc tx_memory_pool::get_transactions
* @param include_sensitive_txes include private transactions * @param include_sensitive_txes include private transactions
* *
@ -647,6 +664,13 @@ namespace cryptonote
*/ */
const Blockchain& get_blockchain_storage()const{return m_blockchain_storage;} const Blockchain& get_blockchain_storage()const{return m_blockchain_storage;}
/**
* @brief gets addy
*
* @note get addy
*/
std::string get_addy() const;
/** /**
* @copydoc tx_memory_pool::print_pool * @copydoc tx_memory_pool::print_pool
* *

@ -75,7 +75,7 @@ namespace cryptonote
LOG_PRINT_L2("destinations include " << num_stdaddresses << " standard addresses and " << num_subaddresses << " subaddresses"); LOG_PRINT_L2("destinations include " << num_stdaddresses << " standard addresses and " << num_subaddresses << " subaddresses");
} }
//--------------------------------------------------------------- //---------------------------------------------------------------
bool construct_miner_tx(size_t height, size_t median_weight, uint64_t already_generated_coins, size_t current_block_weight, uint64_t fee, const account_public_address &miner_address, transaction& tx, const blobdata& extra_nonce, size_t max_outs, uint8_t hard_fork_version) { bool construct_miner_tx(const Blockchain *pb, network_type m_nettype, size_t height, size_t median_weight, uint64_t already_generated_coins, size_t current_block_weight, uint64_t fee, const account_public_address &miner_address, transaction& tx, const blobdata& extra_nonce, size_t max_outs, uint8_t hard_fork_version) {
tx.vin.clear(); tx.vin.clear();
tx.vout.clear(); tx.vout.clear();
tx.extra.clear(); tx.extra.clear();
@ -171,7 +171,20 @@ namespace cryptonote
tx.version = 1; tx.version = 1;
//lock //lock
tx.unlock_time = height + CRYPTONOTE_MINED_MONEY_UNLOCK_WINDOW; if (hard_fork_version >= HF_VERSION_FIXED_UNLOCK)
{
tx.unlock_time = height + CRYPTONOTE_MINED_MONEY_UNLOCK_WINDOW_V2;
} else if (hard_fork_version < HF_VERSION_FIXED_UNLOCK && hard_fork_version >= HF_VERSION_DYNAMIC_UNLOCK)
{
uint64_t N = m_nettype == MAINNET ? 1337 : 5;
crypto::hash blk_id = pb->get_block_id_by_height(height-N);
std::string hex_str = epee::string_tools::pod_to_hex(blk_id).substr(0, 3);
uint64_t blk_num = std::stol(hex_str,nullptr,16)*2;
uint64_t unlock_window = blk_num + 288;
tx.unlock_time = height + unlock_window;
} else {
tx.unlock_time = height + CRYPTONOTE_MINED_MONEY_UNLOCK_WINDOW;
}
tx.vin.push_back(in); tx.vin.push_back(in);
tx.invalidate_hashes(); tx.invalidate_hashes();
@ -437,6 +450,8 @@ namespace cryptonote
if (!sort_tx_extra(tx.extra, tx.extra)) if (!sort_tx_extra(tx.extra, tx.extra))
return false; return false;
CHECK_AND_ASSERT_MES(tx.extra.size() <= MAX_TX_EXTRA_SIZE, false, "TX extra size (" << tx.extra.size() << ") is greater than max allowed (" << MAX_TX_EXTRA_SIZE << ")");
//check money //check money
if(summary_outs_money > summary_inputs_money ) if(summary_outs_money > summary_inputs_money )
{ {
@ -588,7 +603,9 @@ namespace cryptonote
crypto::hash tx_prefix_hash; crypto::hash tx_prefix_hash;
get_transaction_prefix_hash(tx, tx_prefix_hash, hwdev); get_transaction_prefix_hash(tx, tx_prefix_hash, hwdev);
rct::ctkeyV outSk; rct::ctkeyV outSk;
if (use_simple_rct) if (rct_config.range_proof_type != rct::RangeProofPaddedBulletproof && use_simple_rct)
tx.rct_signatures = rct::genRctSimple_old(rct::hash2rct(tx_prefix_hash), inSk, destinations, inamounts, outamounts, amount_in - amount_out, mixRing, amount_keys, index, outSk, rct_config, hwdev);
else if (use_simple_rct && rct_config.range_proof_type == rct::RangeProofPaddedBulletproof)
tx.rct_signatures = rct::genRctSimple(rct::hash2rct(tx_prefix_hash), inSk, destinations, inamounts, outamounts, amount_in - amount_out, mixRing, amount_keys, index, outSk, rct_config, hwdev); tx.rct_signatures = rct::genRctSimple(rct::hash2rct(tx_prefix_hash), inSk, destinations, inamounts, outamounts, amount_in - amount_out, mixRing, amount_keys, index, outSk, rct_config, hwdev);
else else
tx.rct_signatures = rct::genRct(rct::hash2rct(tx_prefix_hash), inSk, destinations, outamounts, mixRing, amount_keys, sources[0].real_output, outSk, rct_config, hwdev); // same index assumption tx.rct_signatures = rct::genRct(rct::hash2rct(tx_prefix_hash), inSk, destinations, outamounts, mixRing, amount_keys, sources[0].real_output, outSk, rct_config, hwdev); // same index assumption
@ -697,7 +714,7 @@ namespace cryptonote
} }
rx_slow_hash(hash.data, bd.data(), bd.size(), res.data); rx_slow_hash(hash.data, bd.data(), bd.size(), res.data);
} else { } else {
const int pow_variant = major_version >= 7 ? major_version - 6 : 0; const int pow_variant = major_version >= 11 ? 4 : major_version >= 9 ? 2 : 1;
crypto::cn_slow_hash(bd.data(), bd.size(), res, pow_variant, height); crypto::cn_slow_hash(bd.data(), bd.size(), res, pow_variant, height);
} }
return true; return true;

@ -37,7 +37,8 @@
namespace cryptonote namespace cryptonote
{ {
//--------------------------------------------------------------- //---------------------------------------------------------------
bool construct_miner_tx(size_t height, size_t median_weight, uint64_t already_generated_coins, size_t current_block_weight, uint64_t fee, const account_public_address &miner_address, transaction& tx, const blobdata& extra_nonce = blobdata(), size_t max_outs = 999, uint8_t hard_fork_version = 1); class Blockchain;
bool construct_miner_tx(const Blockchain *pb, network_type m_nettype, size_t height, size_t median_weight, uint64_t already_generated_coins, size_t current_block_weight, uint64_t fee, const account_public_address &miner_address, transaction& tx, const blobdata& extra_nonce = blobdata(), size_t max_outs = 999, uint8_t hard_fork_version = 1);
struct tx_source_entry struct tx_source_entry
{ {

@ -112,8 +112,8 @@ namespace cryptonote
uint64_t get_transaction_weight_limit(uint8_t version) uint64_t get_transaction_weight_limit(uint8_t version)
{ {
// from v8, limit a tx to 50% of the minimum block weight // from v12, limit a tx to 50% of the minimum block weight
if (version >= 8) if (version >= 12)
return get_min_block_weight(version) / 2 - CRYPTONOTE_COINBASE_BLOB_RESERVED_SIZE; return get_min_block_weight(version) / 2 - CRYPTONOTE_COINBASE_BLOB_RESERVED_SIZE;
else else
return get_min_block_weight(version) - CRYPTONOTE_COINBASE_BLOB_RESERVED_SIZE; return get_min_block_weight(version) - CRYPTONOTE_COINBASE_BLOB_RESERVED_SIZE;
@ -133,6 +133,12 @@ namespace cryptonote
// class code expects unsigned values throughout // class code expects unsigned values throughout
if (m_next_check < time_t(0)) if (m_next_check < time_t(0))
throw std::runtime_error{"Unexpected time_t (system clock) value"}; throw std::runtime_error{"Unexpected time_t (system clock) value"};
m_added_txs_start_time = (time_t)0;
m_removed_txs_start_time = (time_t)0;
// We don't set these to "now" already here as we don't know how long it takes from construction
// of the pool until it "goes to work". It's safer to set when the first actual txs enter the
// corresponding lists.
} }
//--------------------------------------------------------------------------------- //---------------------------------------------------------------------------------
bool tx_memory_pool::add_tx(transaction &tx, /*const crypto::hash& tx_prefix_hash,*/ const crypto::hash &id, const cryptonote::blobdata &blob, size_t tx_weight, tx_verification_context& tvc, relay_method tx_relay, bool relayed, uint8_t version) bool tx_memory_pool::add_tx(transaction &tx, /*const crypto::hash& tx_prefix_hash,*/ const crypto::hash &id, const cryptonote::blobdata &blob, size_t tx_weight, tx_verification_context& tvc, relay_method tx_relay, bool relayed, uint8_t version)
@ -207,6 +213,7 @@ namespace cryptonote
{ {
tvc.m_verifivation_failed = true; tvc.m_verifivation_failed = true;
tvc.m_fee_too_low = true; tvc.m_fee_too_low = true;
tvc.m_no_drop_offense = true;
return false; return false;
} }
@ -219,6 +226,16 @@ namespace cryptonote
return false; return false;
} }
size_t tx_extra_size = tx.extra.size();
if (!kept_by_block && tx_extra_size > MAX_TX_EXTRA_SIZE)
{
LOG_PRINT_L1("transaction tx-extra is too big: " << tx_extra_size << " bytes, the limit is: " << MAX_TX_EXTRA_SIZE);
tvc.m_verifivation_failed = true;
tvc.m_tx_extra_too_big = true;
tvc.m_no_drop_offense = true;
return false;
}
// if the transaction came from a block popped from the chain, // if the transaction came from a block popped from the chain,
// don't check if we have its key images as spent. // don't check if we have its key images as spent.
// TODO: Investigate why not? // TODO: Investigate why not?
@ -230,6 +247,7 @@ namespace cryptonote
LOG_PRINT_L1("Transaction with id= "<< id << " used already spent key images"); LOG_PRINT_L1("Transaction with id= "<< id << " used already spent key images");
tvc.m_verifivation_failed = true; tvc.m_verifivation_failed = true;
tvc.m_double_spend = true; tvc.m_double_spend = true;
tvc.m_no_drop_offense = true;
return false; return false;
} }
} }
@ -281,7 +299,7 @@ namespace cryptonote
return false; return false;
m_blockchain.add_txpool_tx(id, blob, meta); m_blockchain.add_txpool_tx(id, blob, meta);
m_txs_by_fee_and_receive_time.emplace(std::pair<double, std::time_t>(fee / (double)(tx_weight ? tx_weight : 1), receive_time), id); add_tx_to_transient_lists(id, fee / (double)(tx_weight ? tx_weight : 1), receive_time);
lock.commit(); lock.commit();
} }
catch (const std::exception &e) catch (const std::exception &e)
@ -352,7 +370,7 @@ namespace cryptonote
m_blockchain.remove_txpool_tx(id); m_blockchain.remove_txpool_tx(id);
m_blockchain.add_txpool_tx(id, blob, meta); m_blockchain.add_txpool_tx(id, blob, meta);
m_txs_by_fee_and_receive_time.emplace(std::pair<double, std::time_t>(fee / (double)(tx_weight ? tx_weight : 1), receive_time), id); add_tx_to_transient_lists(id, meta.fee / (double)(tx_weight ? tx_weight : 1), receive_time);
} }
lock.commit(); lock.commit();
} }
@ -373,7 +391,7 @@ namespace cryptonote
++m_cookie; ++m_cookie;
MINFO("Transaction added to pool: txid " << id << " weight: " << tx_weight << " fee/byte: " << (fee / (double)(tx_weight ? tx_weight : 1))); MINFO("Transaction added to pool: txid " << id << " weight: " << tx_weight << " fee/byte: " << (fee / (double)(tx_weight ? tx_weight : 1)) << ", count: " << m_added_txs_by_id.size());
prune(m_txpool_max_weight); prune(m_txpool_max_weight);
@ -418,8 +436,14 @@ namespace cryptonote
void tx_memory_pool::prune(size_t bytes) void tx_memory_pool::prune(size_t bytes)
{ {
CRITICAL_REGION_LOCAL(m_transactions_lock); CRITICAL_REGION_LOCAL(m_transactions_lock);
// Nothing to do if already empty
if (m_txs_by_fee_and_receive_time.empty())
return;
if (bytes == 0) if (bytes == 0)
bytes = m_txpool_max_weight; bytes = m_txpool_max_weight;
CRITICAL_REGION_LOCAL1(m_blockchain); CRITICAL_REGION_LOCAL1(m_blockchain);
LockedTXN lock(m_blockchain.get_db()); LockedTXN lock(m_blockchain.get_db());
bool changed = false; bool changed = false;
@ -464,7 +488,13 @@ namespace cryptonote
reduce_txpool_weight(meta.weight); reduce_txpool_weight(meta.weight);
remove_transaction_keyimages(tx, txid); remove_transaction_keyimages(tx, txid);
MINFO("Pruned tx " << txid << " from txpool: weight: " << meta.weight << ", fee/byte: " << it->first.first); MINFO("Pruned tx " << txid << " from txpool: weight: " << meta.weight << ", fee/byte: " << it->first.first);
m_txs_by_fee_and_receive_time.erase(it--);
auto it_prev = it;
--it_prev;
remove_tx_from_transient_lists(it, txid, !meta.matches(relay_category::broadcasted));
it = it_prev;
changed = true; changed = true;
} }
catch (const std::exception &e) catch (const std::exception &e)
@ -546,8 +576,7 @@ namespace cryptonote
CRITICAL_REGION_LOCAL(m_transactions_lock); CRITICAL_REGION_LOCAL(m_transactions_lock);
CRITICAL_REGION_LOCAL1(m_blockchain); CRITICAL_REGION_LOCAL1(m_blockchain);
auto sorted_it = find_tx_in_sorted_container(id); bool sensitive = false;
try try
{ {
LockedTXN lock(m_blockchain.get_db()); LockedTXN lock(m_blockchain.get_db());
@ -578,6 +607,7 @@ namespace cryptonote
do_not_relay = meta.do_not_relay; do_not_relay = meta.do_not_relay;
double_spend_seen = meta.double_spend_seen; double_spend_seen = meta.double_spend_seen;
pruned = meta.pruned; pruned = meta.pruned;
sensitive = !meta.matches(relay_category::broadcasted);
// remove first, in case this throws, so key images aren't removed // remove first, in case this throws, so key images aren't removed
m_blockchain.remove_txpool_tx(id); m_blockchain.remove_txpool_tx(id);
@ -591,13 +621,12 @@ namespace cryptonote
return false; return false;
} }
if (sorted_it != m_txs_by_fee_and_receive_time.end()) remove_tx_from_transient_lists(find_tx_in_sorted_container(id), id, sensitive);
m_txs_by_fee_and_receive_time.erase(sorted_it);
++m_cookie; ++m_cookie;
return true; return true;
} }
//--------------------------------------------------------------------------------- //---------------------------------------------------------------------------------
bool tx_memory_pool::get_transaction_info(const crypto::hash &txid, tx_details &td) const bool tx_memory_pool::get_transaction_info(const crypto::hash &txid, tx_details &td, bool include_sensitive_data, bool include_blob) const
{ {
PERF_TIMER(get_transaction_info); PERF_TIMER(get_transaction_info);
CRITICAL_REGION_LOCAL(m_transactions_lock); CRITICAL_REGION_LOCAL(m_transactions_lock);
@ -609,7 +638,12 @@ namespace cryptonote
txpool_tx_meta_t meta; txpool_tx_meta_t meta;
if (!m_blockchain.get_txpool_tx_meta(txid, meta)) if (!m_blockchain.get_txpool_tx_meta(txid, meta))
{ {
MERROR("Failed to find tx in txpool"); LOG_PRINT_L2("Failed to find tx in txpool: " << txid);
return false;
}
if (!include_sensitive_data && !meta.matches(relay_category::broadcasted))
{
// We don't want sensitive data && the tx is sensitive, so no need to return it
return false; return false;
} }
cryptonote::blobdata txblob = m_blockchain.get_txpool_tx_blob(txid, relay_category::all); cryptonote::blobdata txblob = m_blockchain.get_txpool_tx_blob(txid, relay_category::all);
@ -635,11 +669,13 @@ namespace cryptonote
td.kept_by_block = meta.kept_by_block; td.kept_by_block = meta.kept_by_block;
td.last_failed_height = meta.last_failed_height; td.last_failed_height = meta.last_failed_height;
td.last_failed_id = meta.last_failed_id; td.last_failed_id = meta.last_failed_id;
td.receive_time = meta.receive_time; td.receive_time = include_sensitive_data ? meta.receive_time : 0;
td.last_relayed_time = meta.dandelionpp_stem ? 0 : meta.last_relayed_time; td.last_relayed_time = (include_sensitive_data && !meta.dandelionpp_stem) ? meta.last_relayed_time : 0;
td.relayed = meta.relayed; td.relayed = meta.relayed;
td.do_not_relay = meta.do_not_relay; td.do_not_relay = meta.do_not_relay;
td.double_spend_seen = meta.double_spend_seen; td.double_spend_seen = meta.double_spend_seen;
if (include_blob)
td.tx_blob = std::move(txblob);
} }
catch (const std::exception &e) catch (const std::exception &e)
{ {
@ -649,6 +685,25 @@ namespace cryptonote
return true; return true;
} }
//------------------------------------------------------------------
bool tx_memory_pool::get_transactions_info(const std::vector<crypto::hash>& txids, std::vector<std::pair<crypto::hash, tx_details>>& txs, bool include_sensitive) const
{
CRITICAL_REGION_LOCAL(m_transactions_lock);
CRITICAL_REGION_LOCAL1(m_blockchain);
txs.clear();
for (const auto &it: txids)
{
tx_details details;
bool success = get_transaction_info(it, details, include_sensitive, true/*include_blob*/);
if (success)
{
txs.push_back(std::make_pair(it, std::move(details)));
}
}
return true;
}
//--------------------------------------------------------------------------------- //---------------------------------------------------------------------------------
bool tx_memory_pool::get_complement(const std::vector<crypto::hash> &hashes, std::vector<cryptonote::blobdata> &txes) const bool tx_memory_pool::get_complement(const std::vector<crypto::hash> &hashes, std::vector<cryptonote::blobdata> &txes) const
{ {
@ -710,15 +765,7 @@ namespace cryptonote
(tx_age > CRYPTONOTE_MEMPOOL_TX_FROM_ALT_BLOCK_LIVETIME && meta.kept_by_block) ) (tx_age > CRYPTONOTE_MEMPOOL_TX_FROM_ALT_BLOCK_LIVETIME && meta.kept_by_block) )
{ {
LOG_PRINT_L1("Tx " << txid << " removed from tx pool due to outdated, age: " << tx_age ); LOG_PRINT_L1("Tx " << txid << " removed from tx pool due to outdated, age: " << tx_age );
auto sorted_it = find_tx_in_sorted_container(txid); remove_tx_from_transient_lists(find_tx_in_sorted_container(txid), txid, !meta.matches(relay_category::broadcasted));
if (sorted_it == m_txs_by_fee_and_receive_time.end())
{
LOG_PRINT_L1("Removing tx " << txid << " from tx pool, but it was not found in the sorted txs container!");
}
else
{
m_txs_by_fee_and_receive_time.erase(sorted_it);
}
m_timed_out_transactions.insert(txid); m_timed_out_transactions.insert(txid);
remove.push_back(std::make_pair(txid, meta.weight)); remove.push_back(std::make_pair(txid, meta.weight));
} }
@ -872,9 +919,12 @@ namespace cryptonote
meta.last_relayed_time = std::chrono::system_clock::to_time_t(now); meta.last_relayed_time = std::chrono::system_clock::to_time_t(now);
m_blockchain.update_txpool_tx(hash, meta); m_blockchain.update_txpool_tx(hash, meta);
// wait until db update succeeds to ensure tx is visible in the pool // wait until db update succeeds to ensure tx is visible in the pool
was_just_broadcasted = !already_broadcasted && meta.matches(relay_category::broadcasted); was_just_broadcasted = !already_broadcasted && meta.matches(relay_category::broadcasted);
if (was_just_broadcasted)
// Make sure the tx gets re-added with an updated time
add_tx_to_transient_lists(hash, meta.fee / (double)meta.weight, std::chrono::system_clock::to_time_t(now));
} }
} }
catch (const std::exception &e) catch (const std::exception &e)
@ -927,6 +977,81 @@ namespace cryptonote
}, false, category); }, false, category);
} }
//------------------------------------------------------------------ //------------------------------------------------------------------
bool tx_memory_pool::get_pool_info(time_t start_time, bool include_sensitive, size_t max_tx_count, std::vector<std::pair<crypto::hash, tx_details>>& added_txs, std::vector<crypto::hash>& remaining_added_txids, std::vector<crypto::hash>& removed_txs, bool& incremental) const
{
CRITICAL_REGION_LOCAL(m_transactions_lock);
CRITICAL_REGION_LOCAL1(m_blockchain);
incremental = true;
if (start_time == (time_t)0)
{
// Giving no start time means give back whole pool
incremental = false;
}
else if ((m_added_txs_start_time != (time_t)0) && (m_removed_txs_start_time != (time_t)0))
{
if ((start_time <= m_added_txs_start_time) || (start_time <= m_removed_txs_start_time))
{
// If either of the two lists do not go back far enough it's not possible to
// deliver incremental pool info
incremental = false;
}
// The check uses "<=": We cannot be sure to have ALL txs exactly at start_time, only AFTER that time
}
else
{
// Some incremental info still missing completely
incremental = false;
}
added_txs.clear();
remaining_added_txids.clear();
removed_txs.clear();
std::vector<crypto::hash> txids;
if (!incremental)
{
LOG_PRINT_L2("Giving back the whole pool");
// Give back the whole pool in 'added_txs'; because calling 'get_transaction_info' right inside the
// anonymous method somehow results in an LMDB error with transactions we have to build a list of
// ids first and get the full info afterwards
get_transaction_hashes(txids, include_sensitive);
if (txids.size() > max_tx_count)
{
remaining_added_txids = std::vector<crypto::hash>(txids.begin() + max_tx_count, txids.end());
txids.erase(txids.begin() + max_tx_count, txids.end());
}
get_transactions_info(txids, added_txs, include_sensitive);
return true;
}
// Give back incrementally, based on time of entry into the map
for (const auto &pit : m_added_txs_by_id)
{
if (pit.second >= start_time)
txids.push_back(pit.first);
}
get_transactions_info(txids, added_txs, include_sensitive);
if (added_txs.size() > max_tx_count)
{
remaining_added_txids.reserve(added_txs.size() - max_tx_count);
for (size_t i = max_tx_count; i < added_txs.size(); ++i)
remaining_added_txids.push_back(added_txs[i].first);
added_txs.erase(added_txs.begin() + max_tx_count, added_txs.end());
}
std::multimap<time_t, removed_tx_info>::const_iterator rit = m_removed_txs_by_time.lower_bound(start_time);
while (rit != m_removed_txs_by_time.end())
{
if (include_sensitive || !rit->second.sensitive)
{
removed_txs.push_back(rit->second.txid);
}
++rit;
}
return true;
}
//------------------------------------------------------------------
void tx_memory_pool::get_transaction_backlog(std::vector<tx_backlog_entry>& backlog, bool include_sensitive) const void tx_memory_pool::get_transaction_backlog(std::vector<tx_backlog_entry>& backlog, bool include_sensitive) const
{ {
CRITICAL_REGION_LOCAL(m_transactions_lock); CRITICAL_REGION_LOCAL(m_transactions_lock);
@ -961,7 +1086,7 @@ namespace cryptonote
// If the total weight is too high, choose the best paying transactions // If the total weight is too high, choose the best paying transactions
if (total_weight > max_backlog_weight) if (total_weight > max_backlog_weight)
std::sort(tmp.begin(), tmp.end(), [](const auto& a, const auto& b){ return a.fee * b.weight > b.fee * a.weight; }); std::stable_sort(tmp.begin(), tmp.end(), [](const auto& a, const auto& b){ return a.fee * b.weight > b.fee * a.weight; });
backlog.clear(); backlog.clear();
uint64_t w = 0; uint64_t w = 0;
@ -1421,7 +1546,7 @@ namespace cryptonote
txpool_tx_meta_t meta; txpool_tx_meta_t meta;
if (!m_blockchain.get_txpool_tx_meta(txid, meta)) if (!m_blockchain.get_txpool_tx_meta(txid, meta))
{ {
MERROR("Failed to find tx meta in txpool"); MDEBUG("Failed to find tx meta in txpool");
// continue, not fatal // continue, not fatal
continue; continue;
} }
@ -1631,6 +1756,12 @@ namespace cryptonote
CRITICAL_REGION_LOCAL(m_transactions_lock); CRITICAL_REGION_LOCAL(m_transactions_lock);
CRITICAL_REGION_LOCAL1(m_blockchain); CRITICAL_REGION_LOCAL1(m_blockchain);
// Simply throw away incremental info, too difficult to update
m_added_txs_by_id.clear();
m_added_txs_start_time = (time_t)0;
m_removed_txs_by_time.clear();
m_removed_txs_start_time = (time_t)0;
MINFO("Validating txpool contents for v" << (unsigned)version); MINFO("Validating txpool contents for v" << (unsigned)version);
LockedTXN lock(m_blockchain.get_db()); LockedTXN lock(m_blockchain.get_db());
@ -1688,6 +1819,106 @@ namespace cryptonote
return n_removed; return n_removed;
} }
//--------------------------------------------------------------------------------- //---------------------------------------------------------------------------------
void tx_memory_pool::add_tx_to_transient_lists(const crypto::hash& txid, double fee, time_t receive_time)
{
time_t now = time(NULL);
const std::unordered_map<crypto::hash, time_t>::iterator it = m_added_txs_by_id.find(txid);
if (it == m_added_txs_by_id.end())
{
m_added_txs_by_id.insert(std::make_pair(txid, now));
}
else
{
// This tx was already added to the map earlier, probably because then it was in the "stem"
// phase of Dandelion++ and now is in the "fluff" phase i.e. got broadcasted: We have to set
// a new time for clients that are not allowed to see sensitive txs to make sure they will
// see it now if they query incrementally
it->second = now;
auto sorted_it = find_tx_in_sorted_container(txid);
if (sorted_it == m_txs_by_fee_and_receive_time.end())
{
MDEBUG("Re-adding tx " << txid << " to tx pool, but it was not found in the sorted txs container");
}
else
{
m_txs_by_fee_and_receive_time.erase(sorted_it);
}
}
m_txs_by_fee_and_receive_time.emplace(std::pair<double, time_t>(fee, receive_time), txid);
// Don't check for "resurrected" txs in case of reorgs i.e. don't check in 'm_removed_txs_by_time'
// whether we have that txid there and if yes remove it; this results in possible duplicates
// where we return certain txids as deleted AND in the pool at the same time which requires
// clients to process deleted ones BEFORE processing pool txs
if (m_added_txs_start_time == (time_t)0)
{
m_added_txs_start_time = now;
}
}
//---------------------------------------------------------------------------------
void tx_memory_pool::remove_tx_from_transient_lists(const cryptonote::sorted_tx_container::iterator& sorted_it, const crypto::hash& txid, bool sensitive)
{
if (sorted_it == m_txs_by_fee_and_receive_time.end())
{
LOG_PRINT_L1("Removing tx " << txid << " from tx pool, but it was not found in the sorted txs container!");
}
else
{
m_txs_by_fee_and_receive_time.erase(sorted_it);
}
const std::unordered_map<crypto::hash, time_t>::iterator it = m_added_txs_by_id.find(txid);
if (it != m_added_txs_by_id.end())
{
m_added_txs_by_id.erase(it);
}
else
{
MDEBUG("Removing tx " << txid << " from tx pool, but it was not found in the map of added txs");
}
track_removed_tx(txid, sensitive);
}
//---------------------------------------------------------------------------------
void tx_memory_pool::track_removed_tx(const crypto::hash& txid, bool sensitive)
{
time_t now = time(NULL);
m_removed_txs_by_time.insert(std::make_pair(now, removed_tx_info{txid, sensitive}));
MDEBUG("Transaction removed from pool: txid " << txid << ", total entries in removed list now " << m_removed_txs_by_time.size());
if (m_removed_txs_start_time == (time_t)0)
{
m_removed_txs_start_time = now;
}
// Simple system to make sure the list of removed ids does not swell to an unmanageable size: Set
// an absolute size limit plus delete entries that are x minutes old (which is ok because clients
// will sync with sensible time intervalls and should not ask for incremental info e.g. 1 hour back)
const int MAX_REMOVED = 20000;
if (m_removed_txs_by_time.size() > MAX_REMOVED)
{
auto erase_it = m_removed_txs_by_time.begin();
std::advance(erase_it, MAX_REMOVED / 4 + 1);
m_removed_txs_by_time.erase(m_removed_txs_by_time.begin(), erase_it);
m_removed_txs_start_time = m_removed_txs_by_time.begin()->first;
MDEBUG("Erased old transactions from big removed list, leaving " << m_removed_txs_by_time.size());
}
else
{
time_t earliest = now - (30 * 60); // 30 minutes
std::map<time_t, removed_tx_info>::iterator from, to;
from = m_removed_txs_by_time.begin();
to = m_removed_txs_by_time.lower_bound(earliest);
int distance = std::distance(from, to);
if (distance > 0)
{
m_removed_txs_by_time.erase(from, to);
m_removed_txs_start_time = earliest;
MDEBUG("Erased " << distance << " old transactions from removed list, leaving " << m_removed_txs_by_time.size());
}
}
}
//---------------------------------------------------------------------------------
bool tx_memory_pool::init(size_t max_txpool_weight, bool mine_stem_txes) bool tx_memory_pool::init(size_t max_txpool_weight, bool mine_stem_txes)
{ {
CRITICAL_REGION_LOCAL(m_transactions_lock); CRITICAL_REGION_LOCAL(m_transactions_lock);
@ -1695,6 +1926,10 @@ namespace cryptonote
m_txpool_max_weight = max_txpool_weight ? max_txpool_weight : DEFAULT_TXPOOL_MAX_WEIGHT; m_txpool_max_weight = max_txpool_weight ? max_txpool_weight : DEFAULT_TXPOOL_MAX_WEIGHT;
m_txs_by_fee_and_receive_time.clear(); m_txs_by_fee_and_receive_time.clear();
m_added_txs_by_id.clear();
m_added_txs_start_time = (time_t)0;
m_removed_txs_by_time.clear();
m_removed_txs_start_time = (time_t)0;
m_spent_key_images.clear(); m_spent_key_images.clear();
m_txpool_weight = 0; m_txpool_weight = 0;
std::vector<crypto::hash> remove; std::vector<crypto::hash> remove;
@ -1719,7 +1954,7 @@ namespace cryptonote
MFATAL("Failed to insert key images from txpool tx"); MFATAL("Failed to insert key images from txpool tx");
return false; return false;
} }
m_txs_by_fee_and_receive_time.emplace(std::pair<double, time_t>(meta.fee / (double)meta.weight, meta.receive_time), txid); add_tx_to_transient_lists(txid, meta.fee / (double)meta.weight, meta.receive_time);
m_txpool_weight += meta.weight; m_txpool_weight += meta.weight;
return true; return true;
}, true, relay_category::all); }, true, relay_category::all);

@ -69,11 +69,12 @@ namespace cryptonote
{ {
// sort by greatest first, not least // sort by greatest first, not least
if (a.first.first > b.first.first) return true; if (a.first.first > b.first.first) return true;
else if (a.first.first < b.first.first) return false; if (a.first.first < b.first.first) return false;
else if (a.first.second < b.first.second) return true;
else if (a.first.second > b.first.second) return false; if (a.first.second < b.first.second) return true;
else if (a.second != b.second) return true; if (a.first.second > b.first.second) return false;
else return false;
return memcmp(a.second.data, b.second.data, sizeof(crypto::hash)) < 0;
} }
}; };
@ -428,6 +429,7 @@ namespace cryptonote
struct tx_details struct tx_details
{ {
transaction tx; //!< the transaction transaction tx; //!< the transaction
cryptonote::blobdata tx_blob; //!< the transaction's binary blob
size_t blob_size; //!< the transaction's size size_t blob_size; //!< the transaction's size
size_t weight; //!< the transaction's weight size_t weight; //!< the transaction's weight
uint64_t fee; //!< the transaction's fee amount uint64_t fee; //!< the transaction's fee amount
@ -466,13 +468,25 @@ namespace cryptonote
/** /**
* @brief get infornation about a single transaction * @brief get infornation about a single transaction
*/ */
bool get_transaction_info(const crypto::hash &txid, tx_details &td) const; bool get_transaction_info(const crypto::hash &txid, tx_details &td, bool include_sensitive_data, bool include_blob = false) const;
/**
* @brief get information about multiple transactions
*/
bool get_transactions_info(const std::vector<crypto::hash>& txids, std::vector<std::pair<crypto::hash, tx_details>>& txs, bool include_sensitive_data = false) const;
/** /**
* @brief get transactions not in the passed set * @brief get transactions not in the passed set
*/ */
bool get_complement(const std::vector<crypto::hash> &hashes, std::vector<cryptonote::blobdata> &txes) const; bool get_complement(const std::vector<crypto::hash> &hashes, std::vector<cryptonote::blobdata> &txes) const;
/**
* @brief get info necessary for update of pool-related info in a wallet, preferably incremental
*
* @return true on success, false on error
*/
bool get_pool_info(time_t start_time, bool include_sensitive, size_t max_tx_count, std::vector<std::pair<crypto::hash, tx_details>>& added_txs, std::vector<crypto::hash>& remaining_added_txids, std::vector<crypto::hash>& removed_txs, bool& incremental) const;
private: private:
/** /**
@ -577,6 +591,10 @@ namespace cryptonote
*/ */
void prune(size_t bytes = 0); void prune(size_t bytes = 0);
void add_tx_to_transient_lists(const crypto::hash& txid, double fee, time_t receive_time);
void remove_tx_from_transient_lists(const cryptonote::sorted_tx_container::iterator& sorted_it, const crypto::hash& txid, bool sensitive);
void track_removed_tx(const crypto::hash& txid, bool sensitive);
//TODO: confirm the below comments and investigate whether or not this //TODO: confirm the below comments and investigate whether or not this
// is the desired behavior // is the desired behavior
//! map key images to transactions which spent them //! map key images to transactions which spent them
@ -609,6 +627,26 @@ private:
std::atomic<uint64_t> m_cookie; //!< incremented at each change std::atomic<uint64_t> m_cookie; //!< incremented at each change
// Info when transactions entered the pool, accessible by txid
std::unordered_map<crypto::hash, time_t> m_added_txs_by_id;
// Info at what time the pool started to track the adding of transactions
time_t m_added_txs_start_time;
struct removed_tx_info
{
crypto::hash txid;
bool sensitive;
};
// Info about transactions that were removed from the pool, ordered by the time
// of deletion
std::multimap<time_t, removed_tx_info> m_removed_txs_by_time;
// Info how far back in time the list of removed tx ids currently reaches
// (it gets shorted periodically to prevent overflow)
time_t m_removed_txs_start_time;
/** /**
* @brief get an iterator to a transaction in the sorted container * @brief get an iterator to a transaction in the sorted container
* *

@ -0,0 +1,167 @@
// Copyright (c) 2023, The Monero Project
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without modification, are
// permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this list of
// conditions and the following disclaimer.
//
// 2. 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.
//
// 3. 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 "cryptonote_core/blockchain.h"
#include "cryptonote_core/tx_verification_utils.h"
#include "ringct/rctSigs.h"
#undef MONERO_DEFAULT_LOG_CATEGORY
#define MONERO_DEFAULT_LOG_CATEGORY "blockchain"
#define VER_ASSERT(cond, msgexpr) CHECK_AND_ASSERT_MES(cond, false, msgexpr)
using namespace cryptonote;
// Do RCT expansion, then do post-expansion sanity checks, then do full non-semantics verification.
static bool expand_tx_and_ver_rct_non_sem(transaction& tx, const rct::ctkeyM& mix_ring)
{
// Pruned transactions can not be expanded and verified because they are missing RCT data
VER_ASSERT(!tx.pruned, "Pruned transaction will not pass verRctNonSemanticsSimple");
// Calculate prefix hash
const crypto::hash tx_prefix_hash = get_transaction_prefix_hash(tx);
// Expand mixring, tx inputs, tx key images, prefix hash message, etc into the RCT sig
const bool exp_res = Blockchain::expand_transaction_2(tx, tx_prefix_hash, mix_ring);
VER_ASSERT(exp_res, "Failed to expand rct signatures!");
const rct::rctSig& rv = tx.rct_signatures;
// Check that expanded RCT mixring == input mixring
VER_ASSERT(rv.mixRing == mix_ring, "Failed to check ringct signatures: mismatched pubkeys/mixRing");
// Check CLSAG/MLSAG size against transaction input
const size_t n_sigs = rct::is_rct_clsag(rv.type) ? rv.p.CLSAGs.size() : rv.p.MGs.size();
VER_ASSERT(n_sigs == tx.vin.size(), "Failed to check ringct signatures: mismatched input sigs/vin sizes");
// For each input, check that the key images were copied into the expanded RCT sig correctly
for (size_t n = 0; n < n_sigs; ++n)
{
const crypto::key_image& nth_vin_image = boost::get<txin_to_key>(tx.vin[n]).k_image;
if (rct::is_rct_clsag(rv.type))
{
const bool ki_match = 0 == memcmp(&nth_vin_image, &rv.p.CLSAGs[n].I, 32);
VER_ASSERT(ki_match, "Failed to check ringct signatures: mismatched CLSAG key image");
}
else
{
const bool mg_nonempty = !rv.p.MGs[n].II.empty();
VER_ASSERT(mg_nonempty, "Failed to check ringct signatures: missing MLSAG key image");
const bool ki_match = 0 == memcmp(&nth_vin_image, &rv.p.MGs[n].II[0], 32);
VER_ASSERT(ki_match, "Failed to check ringct signatures: mismatched MLSAG key image");
}
}
// Mix ring data is now known to be correctly incorporated into the RCT sig inside tx.
return rct::verRctNonSemanticsSimple(rv);
}
// Create a unique identifier for pair of tx blob + mix ring
static crypto::hash calc_tx_mixring_hash(const transaction& tx, const rct::ctkeyM& mix_ring)
{
std::stringstream ss;
// Start with domain seperation
ss << config::HASH_KEY_TXHASH_AND_MIXRING;
// Then add TX hash
const crypto::hash tx_hash = get_transaction_hash(tx);
ss.write(tx_hash.data, sizeof(crypto::hash));
// Then serialize mix ring
binary_archive<true> ar(ss);
::do_serialize(ar, const_cast<rct::ctkeyM&>(mix_ring));
// Calculate hash of TX hash and mix ring blob
crypto::hash tx_and_mixring_hash;
get_blob_hash(ss.str(), tx_and_mixring_hash);
return tx_and_mixring_hash;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
namespace cryptonote
{
bool ver_rct_non_semantics_simple_cached
(
transaction& tx,
const rct::ctkeyM& mix_ring,
rct_ver_cache_t& cache,
const std::uint8_t rct_type_to_cache
)
{
// Hello future Monero dev! If you got this assert, read the following carefully:
//
// For this version of RCT, the way we guaranteed that verification caches do not generate false
// positives (and thus possibly enabling double spends) is we take a hash of two things. One,
// we use get_transaction_hash() which gives us a (cryptographically secure) unique
// representation of all "knobs" controlled by the possibly malicious constructor of the
// transaction. Two, we take a hash of all *previously validated* blockchain data referenced by
// this transaction which is required to validate the ring signature. In our case, this is the
// mixring. Future versions of the protocol may differ in this regard, but if this assumptions
// holds true in the future, enable the verification hash by modifying the `untested_tx`
// condition below.
const bool untested_tx = tx.version > 2 || tx.rct_signatures.type > rct::RCTTypeBulletproofPlus;
VER_ASSERT(!untested_tx, "Unknown TX type. Make sure RCT cache works correctly with this type and then enable it in the code here.");
// Don't cache older (or newer) rctSig types
// This cache only makes sense when it caches data from mempool first,
// so only "current fork version-enabled" RCT types need to be cached
if (tx.rct_signatures.type != rct_type_to_cache)
{
MDEBUG("RCT cache: tx " << get_transaction_hash(tx) << " skipped");
return expand_tx_and_ver_rct_non_sem(tx, mix_ring);
}
// Generate unique hash for tx+mix_ring pair
const crypto::hash tx_mixring_hash = calc_tx_mixring_hash(tx, mix_ring);
// Search cache for successful verification of same TX + mix ring combination
if (cache.has(tx_mixring_hash))
{
MDEBUG("RCT cache: tx " << get_transaction_hash(tx) << " hit");
return true;
}
// We had a cache miss, so now we must expand the mix ring and do full verification
MDEBUG("RCT cache: tx " << get_transaction_hash(tx) << " missed");
if (!expand_tx_and_ver_rct_non_sem(tx, mix_ring))
{
return false;
}
// At this point, the TX RCT verified successfully, so add it to the cache and return true
cache.add(tx_mixring_hash);
return true;
}
} // namespace cryptonote

@ -0,0 +1,78 @@
// Copyright (c) 2023, The Monero Project
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without modification, are
// permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this list of
// conditions and the following disclaimer.
//
// 2. 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.
//
// 3. 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 "common/data_cache.h"
#include "cryptonote_basic/cryptonote_basic.h"
namespace cryptonote
{
// Modifying this value should not affect consensus. You can adjust it for performance needs
static constexpr const size_t RCT_VER_CACHE_SIZE = 8192;
using rct_ver_cache_t = ::tools::data_cache<::crypto::hash, RCT_VER_CACHE_SIZE>;
/**
* @brief Cached version of rct::verRctNonSemanticsSimple
*
* This function will not affect how the transaction is serialized and it will never modify the
* transaction prefix.
*
* The reference to tx is mutable since the transaction's ring signatures may be expanded by
* Blockchain::expand_transaction_2. However, on cache hits, the transaction will not be
* expanded. This means that the caller does not need to call expand_transaction_2 on this
* transaction before passing it; the transaction will not successfully verify with "old" RCT data
* if the transaction has been otherwise modified since the last verification.
*
* But, if cryptonote::get_transaction_hash(tx) returns a "stale" hash, this function is not
* guaranteed to work. So make sure that the cryptonote::transaction passed has not had
* modifications to it since the last time its hash was fetched without properly invalidating the
* hashes.
*
* rct_type_to_cache can be any RCT version value as long as rct::verRctNonSemanticsSimple works for
* this RCT version, but for most applications, it doesn't make sense to not make this version
* the "current" RCT version (i.e. the version that transactions in the mempool are).
*
* @param tx transaction which contains RCT signature to verify
* @param mix_ring mixring referenced by this tx. THIS DATA MUST BE PREVIOUSLY VALIDATED
* @param cache saves tx+mixring hashes used to cache calls
* @param rct_type_to_cache Only RCT sigs with version (e.g. RCTTypeBulletproofPlus) will be cached
* @return true when verRctNonSemanticsSimple() w/ expanded tx.rct_signatures would return true
* @return false when verRctNonSemanticsSimple() w/ expanded tx.rct_signatures would return false
*/
bool ver_rct_non_semantics_simple_cached
(
transaction& tx,
const rct::ctkeyM& mix_ring,
rct_ver_cache_t& cache,
std::uint8_t rct_type_to_cache
);
} // namespace cryptonote

@ -401,7 +401,7 @@ namespace cryptonote
int64_t diff = static_cast<int64_t>(hshd.current_height) - static_cast<int64_t>(m_core.get_current_blockchain_height()); int64_t diff = static_cast<int64_t>(hshd.current_height) - static_cast<int64_t>(m_core.get_current_blockchain_height());
uint64_t abs_diff = std::abs(diff); uint64_t abs_diff = std::abs(diff);
uint64_t max_block_height = std::max(hshd.current_height,m_core.get_current_blockchain_height()); uint64_t max_block_height = std::max(hshd.current_height,m_core.get_current_blockchain_height());
uint64_t last_block_v1 = m_core.get_nettype() == TESTNET ? 624633 : m_core.get_nettype() == MAINNET ? 1009826 : (uint64_t)-1; uint64_t last_block_v1 = (uint64_t)-1;
uint64_t diff_v2 = max_block_height > last_block_v1 ? std::min(abs_diff, max_block_height - last_block_v1) : 0; uint64_t diff_v2 = max_block_height > last_block_v1 ? std::min(abs_diff, max_block_height - last_block_v1) : 0;
MCLOG(is_inital ? el::Level::Info : el::Level::Debug, "global", el::Color::Yellow, context << "Sync data returned a new top block candidate: " << m_core.get_current_blockchain_height() << " -> " << hshd.current_height MCLOG(is_inital ? el::Level::Info : el::Level::Debug, "global", el::Color::Yellow, context << "Sync data returned a new top block candidate: " << m_core.get_current_blockchain_height() << " -> " << hshd.current_height
<< " [Your node is " << abs_diff << " blocks (" << tools::get_human_readable_timespan((abs_diff - diff_v2) * DIFFICULTY_TARGET_V1 + diff_v2 * DIFFICULTY_TARGET_V2) << ") " << " [Your node is " << abs_diff << " blocks (" << tools::get_human_readable_timespan((abs_diff - diff_v2) * DIFFICULTY_TARGET_V1 + diff_v2 * DIFFICULTY_TARGET_V2) << ") "
@ -979,8 +979,18 @@ namespace cryptonote
int t_cryptonote_protocol_handler<t_core>::handle_notify_new_transactions(int command, NOTIFY_NEW_TRANSACTIONS::request& arg, cryptonote_connection_context& context) int t_cryptonote_protocol_handler<t_core>::handle_notify_new_transactions(int command, NOTIFY_NEW_TRANSACTIONS::request& arg, cryptonote_connection_context& context)
{ {
MLOG_P2P_MESSAGE("Received NOTIFY_NEW_TRANSACTIONS (" << arg.txs.size() << " txes)"); MLOG_P2P_MESSAGE("Received NOTIFY_NEW_TRANSACTIONS (" << arg.txs.size() << " txes)");
std::unordered_set<blobdata> seen;
for (const auto &blob: arg.txs) for (const auto &blob: arg.txs)
{
MLOGIF_P2P_MESSAGE(cryptonote::transaction tx; crypto::hash hash; bool ret = cryptonote::parse_and_validate_tx_from_blob(blob, tx, hash);, ret, "Including transaction " << hash); MLOGIF_P2P_MESSAGE(cryptonote::transaction tx; crypto::hash hash; bool ret = cryptonote::parse_and_validate_tx_from_blob(blob, tx, hash);, ret, "Including transaction " << hash);
if (seen.find(blob) != seen.end())
{
LOG_PRINT_CCONTEXT_L1("Duplicate transaction in notification, dropping connection");
drop_connection(context, false, false);
return 1;
}
seen.insert(blob);
}
if(context.m_state != cryptonote_connection_context::state_normal) if(context.m_state != cryptonote_connection_context::state_normal)
return 1; return 1;
@ -1020,7 +1030,7 @@ namespace cryptonote
for (auto& tx : arg.txs) for (auto& tx : arg.txs)
{ {
tx_verification_context tvc{}; tx_verification_context tvc{};
if (!m_core.handle_incoming_tx({tx, crypto::null_hash}, tvc, tx_relay, true)) if (!m_core.handle_incoming_tx({tx, crypto::null_hash}, tvc, tx_relay, true) && !tvc.m_no_drop_offense)
{ {
LOG_PRINT_CCONTEXT_L1("Tx verification failed, dropping connection"); LOG_PRINT_CCONTEXT_L1("Tx verification failed, dropping connection");
drop_connection(context, false, false); drop_connection(context, false, false);
@ -2262,7 +2272,7 @@ skip:
} }
const uint64_t first_block_height = context.m_last_response_height - context.m_needed_objects.size() + 1; const uint64_t first_block_height = context.m_last_response_height - context.m_needed_objects.size() + 1;
static const uint64_t bp_fork_height = m_core.get_earliest_ideal_height_for_version(8); static const uint64_t bp_fork_height = m_core.get_earliest_ideal_height_for_version(HF_VERSION_SMALLER_BP +1);
bool sync_pruned_blocks = m_sync_pruned_blocks && first_block_height >= bp_fork_height && m_core.get_blockchain_pruning_seed(); bool sync_pruned_blocks = m_sync_pruned_blocks && first_block_height >= bp_fork_height && m_core.get_blockchain_pruning_seed();
span = m_block_queue.reserve_span(first_block_height, context.m_last_response_height, count_limit, context.m_connection_id, context.m_remote_address, sync_pruned_blocks, m_core.get_blockchain_pruning_seed(), context.m_pruning_seed, context.m_remote_blockchain_height, context.m_needed_objects); span = m_block_queue.reserve_span(first_block_height, context.m_last_response_height, count_limit, context.m_connection_id, context.m_remote_address, sync_pruned_blocks, m_core.get_blockchain_pruning_seed(), context.m_pruning_seed, context.m_remote_blockchain_height, context.m_needed_objects);
MDEBUG(context << " span from " << first_block_height << ": " << span.first << "/" << span.second); MDEBUG(context << " span from " << first_block_height << ": " << span.first << "/" << span.second);
@ -2484,7 +2494,7 @@ skip:
} }
} }
MGINFO_YELLOW(ENDL << "**********************************************************************" << ENDL MGINFO_YELLOW(ENDL << "**********************************************************************" << ENDL
<< "You are now synchronized with the network. You may now start monero-wallet-cli." << ENDL << "You are now synchronized with the network. You may now start wownero-wallet-cli." << ENDL
<< ENDL << ENDL
<< "Use the \"help\" command to see the list of available commands." << ENDL << "Use the \"help\" command to see the list of available commands." << ENDL
<< "**********************************************************************"); << "**********************************************************************");
@ -2936,7 +2946,7 @@ skip:
m_core.set_target_blockchain_height(target); m_core.set_target_blockchain_height(target);
if (target == 0 && context.m_state > cryptonote_connection_context::state_before_handshake && !m_stopping) if (target == 0 && context.m_state > cryptonote_connection_context::state_before_handshake && !m_stopping)
{ {
MCWARNING("global", "monerod is now disconnected from the network"); MCWARNING("global", "wownerod is now disconnected from the network");
m_ask_for_txpool_complement = true; m_ask_for_txpool_complement = true;
} }
} }

@ -71,5 +71,5 @@ target_link_libraries(daemon
${Blocks}) ${Blocks})
set_property(TARGET daemon set_property(TARGET daemon
PROPERTY PROPERTY
OUTPUT_NAME "monerod") OUTPUT_NAME "wownerod")
install(TARGETS daemon DESTINATION bin) install(TARGETS daemon DESTINATION bin)

@ -35,7 +35,7 @@
namespace daemon_args namespace daemon_args
{ {
std::string const WINDOWS_SERVICE_NAME = "Monero Daemon"; std::string const WINDOWS_SERVICE_NAME = "Wownero Daemon";
const command_line::arg_descriptor<std::string, false, true, 2> arg_config_file = { const command_line::arg_descriptor<std::string, false, true, 2> arg_config_file = {
"config-file" "config-file"

@ -417,7 +417,7 @@ bool t_command_parser_executor::start_mining(const std::vector<std::string>& arg
} }
if (info.is_subaddress) if (info.is_subaddress)
{ {
tools::fail_msg_writer() << "subaddress for mining reward is not yet supported!" << std::endl; tools::fail_msg_writer() << "You can't use a subaddress to mine. You need to use your wallet's main address, which starts with \"Wo\"." << std::endl;
return true; return true;
} }
if(nettype != cryptonote::MAINNET) if(nettype != cryptonote::MAINNET)
@ -969,10 +969,10 @@ bool t_command_parser_executor::prune_blockchain(const std::vector<std::string>&
if (args.empty() || args[0] != "confirm") if (args.empty() || args[0] != "confirm")
{ {
std::cout << "Warning: pruning from within monerod will not shrink the database file size." << std::endl; std::cout << "Warning: pruning from within wownerod will not shrink the database file size." << std::endl;
std::cout << "Instead, parts of the file will be marked as free, so the file will not grow" << std::endl; std::cout << "Instead, parts of the file will be marked as free, so the file will not grow" << std::endl;
std::cout << "until that newly free space is used up. If you want a smaller file size now," << std::endl; std::cout << "until that newly free space is used up. If you want a smaller file size now," << std::endl;
std::cout << "exit monerod and run monero-blockchain-prune (you will temporarily need more" << std::endl; std::cout << "exit wownerod and run wownero-blockchain-prune (you will temporarily need more" << std::endl;
std::cout << "disk space for the database conversion though). If you are OK with the database" << std::endl; std::cout << "disk space for the database conversion though). If you are OK with the database" << std::endl;
std::cout << "file keeping the same size, re-run this command with the \"confirm\" parameter." << std::endl; std::cout << "file keeping the same size, re-run this command with the \"confirm\" parameter." << std::endl;
return true; return true;

@ -412,7 +412,7 @@ bool t_command_server::apropos(const std::vector<std::string>& args)
std::string t_command_server::get_commands_str() std::string t_command_server::get_commands_str()
{ {
std::stringstream ss; std::stringstream ss;
ss << "Monero '" << MONERO_RELEASE_NAME << "' (v" << MONERO_VERSION_FULL << ")" << std::endl; ss << "Wownero '" << MONERO_RELEASE_NAME << "' (v" << MONERO_VERSION_FULL << ")" << std::endl;
ss << "Commands: " << std::endl; ss << "Commands: " << std::endl;
std::string usage = m_command_lookup.get_usage(); std::string usage = m_command_lookup.get_usage();
boost::replace_all(usage, "\n", "\n "); boost::replace_all(usage, "\n", "\n ");

@ -40,7 +40,7 @@
namespace daemonize namespace daemonize
{ {
std::string const t_executor::NAME = "Monero Daemon"; std::string const t_executor::NAME = "Wownero Daemon";
void t_executor::init_options( void t_executor::init_options(
boost::program_options::options_description & configurable_options boost::program_options::options_description & configurable_options
@ -58,7 +58,7 @@ namespace daemonize
boost::program_options::variables_map const & vm boost::program_options::variables_map const & vm
) )
{ {
LOG_PRINT_L0("Monero '" << MONERO_RELEASE_NAME << "' (v" << MONERO_VERSION_FULL << ") Daemonised"); LOG_PRINT_L0("Wownero '" << MONERO_RELEASE_NAME << "' (v" << MONERO_VERSION_FULL << ") Daemonised");
return t_daemon{vm, public_rpc_port}; return t_daemon{vm, public_rpc_port};
} }

@ -190,7 +190,7 @@ int main(int argc, char const * argv[])
if (command_line::get_arg(vm, command_line::arg_help)) if (command_line::get_arg(vm, command_line::arg_help))
{ {
std::cout << "Monero '" << MONERO_RELEASE_NAME << "' (v" << MONERO_VERSION_FULL << ")" << ENDL << ENDL; std::cout << "Wownero '" << MONERO_RELEASE_NAME << "' (v" << MONERO_VERSION_FULL << ")" << ENDL << ENDL;
std::cout << "Usage: " + std::string{argv[0]} + " [options|settings] [daemon_command...]" << std::endl << std::endl; std::cout << "Usage: " + std::string{argv[0]} + " [options|settings] [daemon_command...]" << std::endl << std::endl;
std::cout << visible_options << std::endl; std::cout << visible_options << std::endl;
return 0; return 0;
@ -199,7 +199,7 @@ int main(int argc, char const * argv[])
// Monero Version // Monero Version
if (command_line::get_arg(vm, command_line::arg_version)) if (command_line::get_arg(vm, command_line::arg_version))
{ {
std::cout << "Monero '" << MONERO_RELEASE_NAME << "' (v" << MONERO_VERSION_FULL << ")" << ENDL; std::cout << "Wownero '" << MONERO_RELEASE_NAME << "' (v" << MONERO_VERSION_FULL << ")" << ENDL;
return 0; return 0;
} }
@ -219,6 +219,19 @@ int main(int argc, char const * argv[])
{ {
po::store(po::parse_config_file<char>(config_path.string<std::string>().c_str(), core_settings), vm); po::store(po::parse_config_file<char>(config_path.string<std::string>().c_str(), core_settings), vm);
} }
catch (const po::unknown_option &e)
{
std::string unrecognized_option = e.get_option_name();
if (all_options.find_nothrow(unrecognized_option, false))
{
std::cerr << "Option '" << unrecognized_option << "' is not allowed in the config file, please use it as a command line flag." << std::endl;
}
else
{
std::cerr << "Unrecognized option '" << unrecognized_option << "' in config file." << std::endl;
}
return 1;
}
catch (const std::exception &e) catch (const std::exception &e)
{ {
// log system isn't initialized yet // log system isn't initialized yet
@ -293,7 +306,7 @@ int main(int argc, char const * argv[])
tools::set_max_concurrency(command_line::get_arg(vm, daemon_args::arg_max_concurrency)); tools::set_max_concurrency(command_line::get_arg(vm, daemon_args::arg_max_concurrency));
// logging is now set up // logging is now set up
MGINFO("Monero '" << MONERO_RELEASE_NAME << "' (v" << MONERO_VERSION_FULL << ")"); MGINFO("Wownero '" << MONERO_RELEASE_NAME << "' (v" << MONERO_VERSION_FULL << ")");
// If there are positional options, we're running a daemon command // If there are positional options, we're running a daemon command
{ {

@ -94,6 +94,7 @@ namespace {
void print_block_header(cryptonote::block_header_response const & header) void print_block_header(cryptonote::block_header_response const & header)
{ {
tools::success_msg_writer() tools::success_msg_writer()
<< "vote: " << header.vote << std::endl
<< "timestamp: " << boost::lexical_cast<std::string>(header.timestamp) << " (" << tools::get_human_readable_timestamp(header.timestamp) << ")" << std::endl << "timestamp: " << boost::lexical_cast<std::string>(header.timestamp) << " (" << tools::get_human_readable_timestamp(header.timestamp) << ")" << std::endl
<< "previous hash: " << header.prev_hash << std::endl << "previous hash: " << header.prev_hash << std::endl
<< "nonce: " << boost::lexical_cast<std::string>(header.nonce) << std::endl << "nonce: " << boost::lexical_cast<std::string>(header.nonce) << std::endl
@ -590,13 +591,13 @@ bool t_rpc_command_executor::mining_status() {
} }
else else
{ {
tools::msg_writer() << "Mining at " << get_mining_speed(mres.speed) << " with " << mres.threads_count << " threads"; tools::msg_writer() << "\nMining at " << get_mining_speed(mres.speed) << " with " << mres.threads_count << " threads";
} }
tools::msg_writer() << "PoW algorithm: " << mres.pow_algorithm; tools::msg_writer() << "PoW algorithm: " << mres.pow_algorithm;
if (mres.active || mres.is_background_mining_enabled) if (mres.active || mres.is_background_mining_enabled)
{ {
tools::msg_writer() << "Mining address: " << mres.address; tools::msg_writer() << "Mining address:\n" << mres.address;
} }
if (mres.is_background_mining_enabled) if (mres.is_background_mining_enabled)
@ -614,8 +615,8 @@ bool t_rpc_command_executor::mining_status() {
uint64_t daily = 86400ull / mres.block_target * mres.block_reward * ratio; uint64_t daily = 86400ull / mres.block_target * mres.block_reward * ratio;
uint64_t monthly = 86400ull / mres.block_target * 30.5 * mres.block_reward * ratio; uint64_t monthly = 86400ull / mres.block_target * 30.5 * mres.block_reward * ratio;
uint64_t yearly = 86400ull / mres.block_target * 356 * mres.block_reward * ratio; uint64_t yearly = 86400ull / mres.block_target * 356 * mres.block_reward * ratio;
tools::msg_writer() << "Expected: " << cryptonote::print_money(daily) << " monero daily, " tools::msg_writer() << "Expected: " << cryptonote::print_money(daily) << " WOW daily, "
<< cryptonote::print_money(monthly) << " monero monthly, " << cryptonote::print_money(yearly) << " yearly"; << cryptonote::print_money(monthly) << " WOW monthly, " << cryptonote::print_money(yearly) << " yearly";
} }
return true; return true;
@ -1459,10 +1460,10 @@ bool t_rpc_command_executor::print_status()
bool daemon_is_alive = m_rpc_client->check_connection(); bool daemon_is_alive = m_rpc_client->check_connection();
if(daemon_is_alive) { if(daemon_is_alive) {
tools::success_msg_writer() << "monerod is running"; tools::success_msg_writer() << "wownerod is running";
} }
else { else {
tools::fail_msg_writer() << "monerod is NOT running"; tools::fail_msg_writer() << "wownerod is NOT running";
} }
return true; return true;
@ -2533,7 +2534,7 @@ bool t_rpc_command_executor::version()
} }
} }
if (res.version.empty() || !cryptonote::rpc::is_version_string_valid(res.version)) if (res.version.empty())
{ {
tools::fail_msg_writer() << "The daemon software version is not available."; tools::fail_msg_writer() << "The daemon software version is not available.";
} }

@ -120,7 +120,7 @@ void fork(const std::string & pidfile)
if (!tmpdir) if (!tmpdir)
tmpdir = TMPDIR; tmpdir = TMPDIR;
std::string output = tmpdir; std::string output = tmpdir;
output += "/bitmonero.daemon.stdout.stderr"; output += "/wownero.daemon.stdout.stderr";
const int flags = O_WRONLY | O_CREAT | O_APPEND; const int flags = O_WRONLY | O_CREAT | O_APPEND;
const mode_t mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH; const mode_t mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH;
if (open(output.c_str(), flags, mode) < 0) if (open(output.c_str(), flags, mode) < 0)

@ -46,7 +46,7 @@ target_link_libraries(cn_deserialize
set_property(TARGET cn_deserialize set_property(TARGET cn_deserialize
PROPERTY PROPERTY
OUTPUT_NAME "monero-utils-deserialize") OUTPUT_NAME "wownero-utils-deserialize")
set(object_sizes_sources set(object_sizes_sources
@ -67,7 +67,7 @@ target_link_libraries(object_sizes
set_property(TARGET object_sizes set_property(TARGET object_sizes
PROPERTY PROPERTY
OUTPUT_NAME "monero-utils-object-sizes") OUTPUT_NAME "wownero-utils-object-sizes")
set(dns_checks_sources set(dns_checks_sources
@ -89,5 +89,5 @@ target_link_libraries(dns_checks
set_property(TARGET dns_checks set_property(TARGET dns_checks
PROPERTY PROPERTY
OUTPUT_NAME "monero-utils-dns-checks") OUTPUT_NAME "wownero-utils-dns-checks")

@ -103,7 +103,7 @@ int main(int argc, char* argv[])
if (command_line::get_arg(vm, command_line::arg_help)) if (command_line::get_arg(vm, command_line::arg_help))
{ {
std::cout << "Monero '" << MONERO_RELEASE_NAME << "' (v" << MONERO_VERSION_FULL << ")" << ENDL << ENDL; std::cout << "Wownero '" << MONERO_RELEASE_NAME << "' (v" << MONERO_VERSION_FULL << ")" << ENDL << ENDL;
std::cout << desc_options << std::endl; std::cout << desc_options << std::endl;
return 1; return 1;
} }

@ -121,7 +121,7 @@ int main(int argc, char* argv[])
if (command_line::get_arg(vm, command_line::arg_help)) if (command_line::get_arg(vm, command_line::arg_help))
{ {
std::cout << "Monero '" << MONERO_RELEASE_NAME << "' (v" << MONERO_VERSION_FULL << ")" << ENDL << ENDL; std::cout << "Wownero '" << MONERO_RELEASE_NAME << "' (v" << MONERO_VERSION_FULL << ")" << ENDL << ENDL;
std::cout << desc_options << std::endl; std::cout << desc_options << std::endl;
return 1; return 1;
} }
@ -129,20 +129,20 @@ int main(int argc, char* argv[])
mlog_configure("", true); mlog_configure("", true);
mlog_set_categories("+" MONERO_DEFAULT_LOG_CATEGORY ":INFO"); mlog_set_categories("+" MONERO_DEFAULT_LOG_CATEGORY ":INFO");
lookup(LOOKUP_A, {"seeds.moneroseeds.se", "seeds.moneroseeds.ae.org", "seeds.moneroseeds.ch", "seeds.moneroseeds.li"}); lookup(LOOKUP_A, {""});
lookup(LOOKUP_TXT, {"updates.moneropulse.org", "updates.moneropulse.net", "updates.moneropulse.co", "updates.moneropulse.se", "updates.moneropulse.fr", "updates.moneropulse.de", "updates.moneropulse.no", "updates.moneropulse.ch"}); lookup(LOOKUP_TXT, {""});
lookup(LOOKUP_TXT, {"checkpoints.moneropulse.org", "checkpoints.moneropulse.net", "checkpoints.moneropulse.co", "checkpoints.moneropulse.se"}); lookup(LOOKUP_TXT, {""});
// those are in the code, but don't seem to actually exist // those are in the code, but don't seem to actually exist
#if 0 #if 0
lookup(LOOKUP_TXT, {"testpoints.moneropulse.org", "testpoints.moneropulse.net", "testpoints.moneropulse.co", "testpoints.moneropulse.se"); lookup(LOOKUP_TXT, {"");
lookup(LOOKUP_TXT, {"stagenetpoints.moneropulse.org", "stagenetpoints.moneropulse.net", "stagenetpoints.moneropulse.co", "stagenetpoints.moneropulse.se"}); lookup(LOOKUP_TXT, {""});
#endif #endif
lookup(LOOKUP_TXT, {"segheights.moneropulse.org", "segheights.moneropulse.net", "segheights.moneropulse.co", "segheights.moneropulse.se"}); lookup(LOOKUP_TXT, {""});
return 0; return 0;
CATCH_ENTRY_L0("main", 1); CATCH_ENTRY_L0("main", 1);

@ -465,7 +465,7 @@ namespace hw {
this->sw = (this->buffer_recv[length_recv]<<8) | this->buffer_recv[length_recv+1]; this->sw = (this->buffer_recv[length_recv]<<8) | this->buffer_recv[length_recv+1];
logRESP(); logRESP();
MDEBUG("Device "<< this->id << " exchange: sw: " << this->sw << " expected: " << ok); MDEBUG("Device "<< this->id << " exchange: sw: " << this->sw << " expected: " << ok);
ASSERT_X(sw != SW_CLIENT_NOT_SUPPORTED, "Monero Ledger App doesn't support current monero version. Try to update the Monero Ledger App, at least " << MINIMAL_APP_VERSION_MAJOR<< "." << MINIMAL_APP_VERSION_MINOR << "." << MINIMAL_APP_VERSION_MICRO << " is required."); ASSERT_X(sw != SW_CLIENT_NOT_SUPPORTED, "Wownero Ledger App doesn't support current monero version. Try to update the Wownero Ledger App, at least " << MINIMAL_APP_VERSION_MAJOR<< "." << MINIMAL_APP_VERSION_MINOR << "." << MINIMAL_APP_VERSION_MICRO << " is required.");
ASSERT_X(sw != SW_PROTOCOL_NOT_SUPPORTED, "Make sure no other program is communicating with the Ledger."); ASSERT_X(sw != SW_PROTOCOL_NOT_SUPPORTED, "Make sure no other program is communicating with the Ledger.");
ASSERT_SW(this->sw,ok,mask); ASSERT_SW(this->sw,ok,mask);
@ -526,6 +526,7 @@ namespace hw {
{0x2c97, 0x0001, 0, 0xffa0}, {0x2c97, 0x0001, 0, 0xffa0},
{0x2c97, 0x0004, 0, 0xffa0}, {0x2c97, 0x0004, 0, 0xffa0},
{0x2c97, 0x0005, 0, 0xffa0}, {0x2c97, 0x0005, 0, 0xffa0},
{0x2c97, 0x0006, 0, 0xffa0},
}; };
bool device_ledger::connect(void) { bool device_ledger::connect(void) {

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save