Compare commits

...

86 Commits

Author SHA1 Message Date
jwinterm 6b28de1cdc Merge pull request 'wownero rebase v0.11' (#462) from wowario/wownero:wow-v0.11 into master
1 year ago
wowario e78ef8a3a7
faster sync, drop unconfirmed mempool txs after 1 day
1 year ago
wowario 7e6109d02a
silent compiler warnings
1 year ago
wowario 6fe4ceaf09
wallet seed message spacing
1 year ago
wowario bcdc98a8b0
remove warning reusing keys
1 year ago
wowario 6c97d87295
remove warning about background mining
1 year ago
wowario d10480a12f
add clear screen command
1 year ago
wowario 79a4abdc18
show wallet info
1 year ago
hinto-janaiyo 864255d783
simplewallet/wallet2: set option - show-detailed-prompt
1 year ago
moneromooo-monero 4ac984bc56
blockchain_prune: faster
1 year ago
Offshore Monero 9be78e756b
Turn readline off on OpenBSD because it is broken
1 year ago
moneromooo-monero bd011fcae9
rpc: do not misidentify coinbase txes as pruned
1 year ago
moneromooo-monero 399593a320
heed NO_COLOR environment variable
1 year ago
plowsof d0bacf4f77
win-service: enable auto startup
1 year ago
Jeffrey Ryan f25a655cff
readline_buffer: disable bracketed paste escape sequences
1 year ago
selsta ddfefa5dd5
daemonizer: don't uninstall windows service on exit
1 year ago
moneromooo-monero 22e71f9449
simplewallet: print fully qualified filename for new wallets
1 year ago
wowario 15b7b9d05b
wownero chan
1 year ago
wowario 5022273035
update README.md
1 year ago
wowario c36f266520
update checkpoints
1 year ago
wowario e9e18bdf56
set fork height
1 year ago
wowario 83b5e5ada1
from v20, limit tx extra size
1 year ago
tevador 2944371b43
Add a size limit for tx_extra in tx pool
1 year ago
wowario b06dd76792
use rx_set_miner_thread after RX_BLOCK_VERSION
1 year ago
wowario 8695701058
Debug level No incoming connections
1 year ago
wowario 99682fb3a7
update checkpoints
1 year ago
thotbot e84d5ba8c0
Misc. network related
1 year ago
thotbot 200586592c
Import transaction
1 year ago
dsc b2d752b298
estimate_fee requires new bp+ parameter
1 year ago
thotbot 3d25c90053
Skip unneeded blocks in fast refresh
1 year ago
thotbot fd18ad1e60
subaddressIndex()
1 year ago
thotbot d2a170f6e4
Print wallet cache
1 year ago
thotbot 60ff2f668e
Misc. wallet API and wallet2 changes
1 year ago
thotbot 45a63f10ba
Coins
1 year ago
thotbot a21f06b933
Offline transaction signing
1 year ago
wowario 1080a90d23
uri remainder
1 year ago
wowario ccc2396d92
remove testnet/stagenet fork heights/blocks
1 year ago
wowario 136be529d6
don't request pre-bulletprooof pruned blocks
1 year ago
wowario b5fb9aea88
change to debug level
1 year ago
wowario dfa32f3330
rename ringdb-dir
1 year ago
wowario 6aaee726f1
mod variant4_random_math
1 year ago
wowario a636325df3
support old BP
1 year ago
wowario 47f78dc11a
vote by block
1 year ago
wowario 2d3fa0f1c9
tidy up miner msgs
1 year ago
wowario 7d1b51ebf7
miner block header signing
1 year ago
wowario dd4556c5e1
difficulty is fun
1 year ago
wowario e52d622592
shorten timestamp check window
1 year ago
wowario 6cbf952315
limit future blk time to 10 min
1 year ago
wowario a2013707e2
bump unlock time to 288 blks
1 year ago
wowario 37e2666915
broadcast donation sub-address
1 year ago
wowario 5c42087ec3
revert Preserve commitment format inside transactions #8277
1 year ago
wowario 4f53308b8a
add systemd file
1 year ago
wowario 1812ba449b
update gitian
1 year ago
wowario 930e6e32a0
update Dockerfile
1 year ago
wowario 773072bcd7
adjust approx_blockchain_height
1 year ago
wowario 22a97e4192
update README.md
1 year ago
wowario 095be4ff65
add wowario gpg key
1 year ago
_XxFedexX_ 179db40a4a
Add _xxfedexx_'s PGP key
1 year ago
wowario 540548a0b7
config wallet2 settings
1 year ago
wowario 4f6d49eff6
set dev fund address
1 year ago
wowario 0c28ca0f4d
add seed nodes
1 year ago
wowario 36285ab082
set name of daemon stdout
1 year ago
wowario 327ea9032a
set last v1 block
1 year ago
wowario 5c29f2b10c
set pow variants
1 year ago
wowario 84f49bed65
set quick height for syncing
1 year ago
wowario 970ec88436
send dump log to wowario
1 year ago
wowario 35b1f07d86
set genesis block timestamp
1 year ago
wowario b895d04401
set decimal point
1 year ago
wowario e082e0bc1a
bump RX block version
1 year ago
wowario 250a681db6
correct length of addresses
1 year ago
wowario 8635db2b19
move utilities to debug build
1 year ago
wowario 0992c28663
automatic submodule update
1 year ago
wowario 32ea1c1423
Doxygen off
1 year ago
wowario 53df650a78
trezor support off
1 year ago
wowario 9a4ddf9a1c
turn off tests
1 year ago
wowario 3d7cf87092
gitian: copy config file
1 year ago
wowario a9534ceb46
show full version
1 year ago
wowario d4675d8527
add forks and checkpoints
1 year ago
wowario 9ef26ac926
remove moneropulse urls
1 year ago
wowario 2581457497
remove monero tx bug fixes
1 year ago
wowario e64ad1e325
initialize genesis block
1 year ago
wowario 3817d559d6
bump ring size to 22
1 year ago
wowario 365c3b9517
config cryptonote
1 year ago
wowario d7f76002aa
add RandomWOW
1 year ago
wowario 6526020b08
v0.11 ASCII art
1 year ago
wowario ddef0b1b8b
wownero skin pack
1 year ago

9
.gitmodules vendored

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

@ -359,15 +359,16 @@ if(NOT MANUAL_SUBMODULES)
if (upToDate)
message(STATUS "Submodule '${relative_path}' is up-to-date")
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()
endfunction ()
message(STATUS "Checking submodules")
check_submodule(external/miniupnp)
check_submodule(external/rapidjson)
check_submodule(external/trezor-common)
check_submodule(external/randomx)
#check_submodule(external/trezor-common)
check_submodule(external/randomwow)
check_submodule(external/supercop)
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)
enable_testing()
option(BUILD_DOCUMENTATION "Build the Doxygen documentation." ON)
option(BUILD_DOCUMENTATION "Build the Doxygen documentation." OFF)
option(BUILD_TESTS "Build tests." OFF)
if (CMAKE_BUILD_TYPE STREQUAL "Debug")
set(DEFAULT_BUILD_DEBUG_UTILITIES ON)
@ -777,7 +778,7 @@ else()
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${ARCH_FLAG}")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${ARCH_FLAG}")
set(WARNINGS "-Wall -Wextra -Wpointer-arith -Wundef -Wvla -Wwrite-strings -Wno-error=extra -Wno-error=deprecated-declarations -Wno-unused-parameter -Wno-error=unused-variable -Wno-error=undef -Wno-error=uninitialized")
set(WARNINGS "-Wpointer-arith -Wundef -Wvla -Wwrite-strings -Wno-deprecated-declarations -Wno-unused-parameter -Wno-error=unused-variable -Wno-error=undef -Wno-error=uninitialized")
if(CMAKE_C_COMPILER_ID MATCHES "Clang" OR CMAKE_CXX_COMPILER_ID MATCHES "Clang")
if(ARM)
set(WARNINGS "${WARNINGS} -Wno-error=inline-asm")
@ -1139,7 +1140,9 @@ if (HIDAPI_FOUND OR LibUSB_COMPILE_TEST_PASSED)
endif()
endif()
option(USE_READLINE "Build with GNU readline support." ON)
if(NOT OPENBSD)
option(USE_READLINE "Build with GNU readline support." ON)
endif()
if(USE_READLINE AND NOT DEPENDS)
find_package(Readline)
if(READLINE_FOUND AND GNU_READLINE_FOUND)

@ -41,26 +41,26 @@ RUN set -ex && \
rm -rf /var/lib/apt
COPY --from=builder /src/build/x86_64-linux-gnu/release/bin /usr/local/bin/
# Create monero user
RUN adduser --system --group --disabled-password monero && \
mkdir -p /wallet /home/monero/.bitmonero && \
chown -R monero:monero /home/monero/.bitmonero && \
chown -R monero:monero /wallet
# Create wownero user
RUN adduser --system --group --disabled-password wownero && \
mkdir -p /wallet /home/wownero/.wownero && \
chown -R wownero:wownero /home/wownero/.wownero && \
chown -R wownero:wownero /wallet
# Contains the blockchain
VOLUME /home/monero/.bitmonero
VOLUME /home/wownero/.wownero
# Generate your wallet via accessing the container and run:
# cd /wallet
# monero-wallet-cli
# wownero-wallet-cli
VOLUME /wallet
EXPOSE 18080
EXPOSE 18081
EXPOSE 34567
EXPOSE 34568
# switch to user monero
USER monero
# switch to user wownero
USER wownero
ENTRYPOINT ["monerod"]
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"]
ENTRYPOINT ["wownerod"]
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:
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:
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 ARCH="x86-64" -D BUILD_64=ON -D CMAKE_BUILD_TYPE=Release $(topdir) && $(MAKE)
coverage:
mkdir -p $(builddir)/debug

@ -1,673 +1,162 @@
# Monero
# ~~Mo~~Wownero - Such privacy! Many coins! Wow! 🐕
Copyright (c) 2014-2022 The Monero Project.
Copyright (c) 2014-2023 The Monero Project.
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
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
- 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.
## Translations
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).
 
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).
## Coverage
| Type | Status |
|-----------|--------|
| Coverity | [![Coverity Status](https://scan.coverity.com/projects/9657/badge.svg)](https://scan.coverity.com/projects/9657/)
| 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)
| Coveralls | [![Coveralls Status](https://coveralls.io/repos/github/monero-project/monero/badge.svg?branch=master)](https://coveralls.io/github/monero-project/monero?branch=master)
| License | [![License](https://img.shields.io/badge/license-BSD3-blue.svg)](https://opensource.org/licenses/BSD-3-Clause)
## Resources
- 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 Funding System: [funding.wownero.com](https://funding.wownero.com)
- 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)
- 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)
- Public Node Status: [monero.fail](https://monero.fail/?crypto=wownero)
- 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)
## Exchanges
- [AltQuick](https://altquick.com/market/Wownero)
- [Majestic Bank](https://majesticbank.sc)
- [TradeOgre](https://tradeogre.com/exchange/BTC-WOW)
### Blockchain Explorers
- https://explore.wownero.com
- https://muchwow.lol
## Introduction
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.
Wownero is a privacy-centric memecoin that was fairly launched on April 1, 2018 with no pre-mine, stealth-mine or ICO. Wownero has a maximum supply of around 184 million WOW with a slow and steady emission over 50 years. It is a fork of Monero, but with its own genesis block, so there is no degradation of privacy due to ring signatures using different participants for the same tx outputs on opposing forks.
**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.
**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.
## Supporting the project
**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.
Wownero is a 100% community-sponsored endeavor. Supporting services are also graciously provided by sponsors:
**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.
[<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)
## About this project
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 [WFS proposals](https://funding.wownero.com/proposals) or the dev slush fund.
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.
### Donation Addresses
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.
WOW: `Wo3MWeKwtA918DU4c69hVSNgejdWFCRCuWjShRY66mJkU2Hv58eygJWDJS1MNa2Ge5M1WjUkGHuLqHkweDxwZZU42d16v94mP`
**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.
- view key: `e62e40bfd5ca7e3a7f199602a3c97df511780489e1c1861884b00c28abaea406`
## Supporting the project
XMR: `44SQVPGLufPasUcuUQSZiF5c9BFzjcP8ucDxzzFDgLf1VkCEFaidJ3u2AhSKMhPLKA3jc2iS8wQHFcaigM6fXmo6AnFRn5B`
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).
- view key: `cb83681c31db0c79adf18f25b2a6d05f86db1109385b4928930e2acf49a3ed0b`
The Monero donation address is:
`888tNkZrPN6JsEgekjMnABU4TBzc2Dt29EPAvkRxbANsAnjyPbb3iQ1YBRk1UXcdRsiKc9dhwMVgN5S9cQUiyoogDavup3H`
Viewkey:
`f359631075708155cc3d92a32b75a7d02a5dcf27756707b47a2b31b21c389501`
Base address for restoring with address and viewkey:
`44AFFq5kSiGBoZ4NMDwYtN18obc8AemS33DBLWs3H7otXft3XjrpDtQGv7SqSsaBYBb98uNbr2VBBEt7f2wfn3RVGQBEP3A`
BTC: `bc1qcw9zglp3fxyl25zswemw7jczlqryms2lsmu464`
The Bitcoin donation address is:
`1KTexdemPdxSBcG55heUuTjDRYqbC5ZL8H`
### Open Collective
Core development funding and/or some supporting services are also graciously provided by [sponsors](https://www.getmonero.org/community/sponsorships/):
Open Collective is an online funding platform for open source software and collaborative communities. The platform brings together legal entities that act as a “Fiscal Host”, “Collectives” (unincorporated, community-based projects), and individuals interested in supporting projects with donations. Fiscal hosts hold donations for collectives in trust and handle all the taxes and legal stuff.
[<img width="150" src="https://www.getmonero.org/img/sponsors/tarilabs.png"/>](https://tarilabs.com/)
[<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/)
Wownero is hosted by Open Collective Europe, a Brussels-based non-profit that hosts many other collectives, such as Manjaro, EndeavourOS, Xfce, and peertube.social. If you would like donate to the Wownero Project using this method, you can check out our [Wownero - Open Collective](https://opencollective.com/wownero) page.
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
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.
| Software upgrade block height | Date | Fork version | Minimum Monero version | Recommended Monero version | Details |
| ------------------------------ | -----------| ----------------- | ---------------------- | -------------------------- | ---------------------------------------------------------------------------------- |
| 1009827 | 2016-03-22 | v2 | v0.9.4 | v0.9.4 | Allow only >= ringsize 3, blocktime = 120 seconds, fee-free blocksize 60 kb |
| 1141317 | 2016-09-21 | v3 | v0.9.4 | v0.10.0 | Splits coinbase into denominations |
| 1220516 | 2017-01-05 | v4 | v0.10.1 | v0.10.2.1 | Allow normal and RingCT transactions |
| 1288616 | 2017-04-15 | v5 | v0.10.3.0 | v0.10.3.1 | Adjusted minimum blocksize and fee algorithm |
| 1400000 | 2017-09-16 | v6 | v0.11.0.0 | v0.11.0.0 | Allow only RingCT transactions, allow only >= ringsize 5 |
| 1546000 | 2018-04-06 | v7 | v0.12.0.0 | v0.12.3.0 | Cryptonight variant 1, ringsize >= 7, sorted inputs
| 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)
| 1686275 | 2018-10-19 | v9 | v0.13.0.0 | v0.13.0.4 | bulletproofs required
| 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
| 1788720 | 2019-03-10 | v11 | v0.14.0.0 | v0.14.1.2 | forbid old RingCT transaction format
| 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 |
| Software upgrade block height | Date | Release Name | Minimum Wownero version | Recommended Wownero version | Details |
|-------------------------------|------------| ----------------- |-------------------------|-----------------------------| ---------------------------------------------------------------------------------- |
| 1 | 2018-04-01 | Awesome Akita | v0.1.0.0 | v0.1.0.0 | Cryptonight variant 1, ringsize >= 8, sorted inputs
| 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
| 53,666 | 2018-10-06 | Cool Cage | v0.3.0.0 | v0.3.1.3 | Cryptonight variant 2, LWMA v2, ringsize = 22, MMS
| 63,469 | 2018-11-11 | Dank Doge | v0.4.0.0 | v0.4.0.0 | LWMA v4
| 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
| 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
| 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
| - | 2020-06-28 | Hallucinogenic Hypnotoad | v0.8.0.0 | v0.8.0.2 | Dandelion++ support
| 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
| 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
| 514,000 | 2023-04-01 | Kunty Karen | v0.11.0.0 | v0.11.0.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
X's indicate that these details have not been determined as of commit date.
\* indicates estimate as of commit date
## Release staging schedule and protocol
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.**
## Installing from a package
Packages are available for
* Debian Buster
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
```bash
sudo apt install monero
```
More info and versions in the [Debian package tracker](https://tracker.debian.org/pkg/monero).
* Arch Linux/Manjaro
* Arch Linux [(via Community packages)](https://www.archlinux.org/packages/community/x86_64/monero/):
yay -S wownero-git
```bash
sudo pacman -S monero
```
* Gentoo - Russian hacking tool
* Void Linux:
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
xbps-install -S monero
```
* NixOS
* GuixSD
nix-shell -p wownero
```bash
guix package -i monero
```
Packaging for your favorite distribution would be a welcome contribution!
* 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/)
```bash
brew install monero
```
## Building from Source
* Docker
```bash
# Build using all available cores
docker build -t monero .
git clone https://git.wownero.com/wownero/wownero && cd wownero
docker build -t git-wow:master -m 4g .
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)
docker build --build-arg NPROC=1 -t monero .
* Arch Linux/Manjaro
# either run in foreground
docker run -it -v /monero/chain:/home/monero/.bitmonero -v /monero/wallet:/wallet -p 18080:18080 monero
sudo pacman -Syu && sudo pacman -S base-devel cmake boost openssl zeromq libpgm unbound libsodium git libusb systemd
git clone https://git.wownero.com/wownero/wownero && cd wownero
make -j2
# or in background
docker run -it -d -v /monero/chain:/home/monero/.bitmonero -v /monero/wallet:/wallet -p 18080:18080 monero
```
* Debian/Ubuntu
* The build needs 3 GB space.
* Wait one hour or more
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
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
from which cmake was invoked (repository root by default). To run in the
foreground:
```bash
./bin/monerod
```
./bin/wownerod
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
`--config-file` argument. To specify an option in the configuration file, add
a line with the syntax `argumentname=value`, where `argumentname` is the name
@ -675,186 +164,54 @@ of the argument without the leading dashes, for example, `log-level=1`.
To run in background:
```bash
./bin/monerod --log-file monerod.log --detach
```
./bin/wownerod --log-file wownerod.log --detach
To run as a systemd service, copy
[monerod.service](utils/systemd/monerod.service) to `/etc/systemd/system/` and
[monerod.conf](utils/conf/monerod.conf) to `/etc/`. The [example
service](utils/systemd/monerod.service) assumes that the user `monero` exists
[wownerod.service](utils/systemd/wownerod.service) to `/etc/systemd/system/` and
[wow.conf](wow.conf) to `/etc/`. The [example
service](utils/systemd/wownerod.service) assumes that the user `wownero` exists
and its home is the data directory specified in the [example
config](utils/conf/monerod.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.
config](wow.conf).
### Using Tor on Tails
Once node is synced to network, run the CLI wallet by entering:
TAILS ships with a very restrictive set of firewall rules. Therefore, you need
to add a rule to allow this connection too, in addition to telling torsocks to
allow inbound connections. Full example:
./bin/wownero-wallet-cli
```bash
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
```
Type `help` in CLI wallet to see standard commands (for advanced options, type `help_advanced`).
## Pruning
## Tor Anonymity Network
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.
### Ubuntu
For more detailed information see the ['Pruning' entry in the Moneropedia](https://www.getmonero.org/resources/moneropedia/pruning.html)
* `sudo apt-get update && sudo apt-get install tor -y`
* `sudo nano /etc/tor/torrc`
## 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.
* To use `gdb` in order to obtain a stack trace for a build that has stalled:
Run the build.
Once it stalls, enter the following command:
```bash
gdb /path/to/monerod `pidof monerod`
add the following:
```
Type `thread apply all bt` within gdb in order to obtain the stack trace
* If however the core dumps or segfaults:
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`
HiddenServiceDir /var/lib/tor/wownero/
HiddenServicePort 34569 127.0.0.1:34569
HiddenServicePort 34566 127.0.0.1:34566
HiddenServiceVersion 3
```
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
```
#### 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 ../..
./wownerod --config-file=wow.conf
```
You can then run the monero tools normally. Performance will typically halve.
#### valgrind
* `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)
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:
```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.
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.
./wownero-wallet-cli --proxy 127.0.0.1:9050 --daemon-address iy6ry6uudpzvbd72zsipepukp6nsazjdu72n52vg3isfnxqn342flzad.onion:34568
```

@ -338,11 +338,21 @@ bool is_stdout_a_tty()
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)
{
if (!is_stdout_a_tty())
return;
if (is_nocolor())
return;
switch(color)
{
case console_color_default:
@ -461,6 +471,9 @@ void reset_console_color() {
if (!is_stdout_a_tty())
return;
if (is_nocolor())
return;
#ifdef WIN32
HANDLE h_stdout = GetStdHandle(STD_OUTPUT_HANDLE);
SetConsoleTextAttribute(h_stdout, FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);

@ -238,6 +238,10 @@ static char** attempted_completion(const char* text, int start, int end)
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_callback_handler_install("", handle_line);
stifle_history(500);

@ -41,10 +41,10 @@ RUN useradd -ms /bin/bash -U ubuntu -G docker
USER ubuntu:docker
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; \
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"]
EOF
@ -109,7 +109,7 @@ if [ "$check" != "sign" ]; then
fi
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
git remote add $GH_USER git@github.com:$GH_USER/gitian.sigs.git
cd ..

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

@ -5,7 +5,7 @@ import os
import subprocess
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'
platforms = {'l': ['Linux', 'linux', 'tar.bz2'],
@ -31,10 +31,10 @@ def setup():
subprocess.check_call(['git', 'checkout', 'c0f77ca018cb5332bfd595e0aff0468f77542c23'])
os.makedirs('inputs', exist_ok=True)
os.chdir('inputs')
if os.path.isdir('monero'):
# Remove the potentially stale monero dir. Otherwise you might face submodule mismatches.
subprocess.check_call(['rm', 'monero', '-fR'])
subprocess.check_call(['git', 'clone', args.url, 'monero'])
if os.path.isdir('wownero'):
# Remove the potentially stale wownero dir. Otherwise you might face submodule mismatches.
subprocess.check_call(['rm', 'wownero', '-fR'])
subprocess.check_call(['git', 'clone', args.url, 'wownero'])
os.chdir('..')
make_image_prog = ['bin/make-base-vm', '--suite', 'bionic', '--arch', 'amd64']
if args.docker:
@ -66,10 +66,10 @@ def rebuild():
suffix = platforms[i][2]
print('\nCompiling ' + args.version + ' ' + os_name)
infile = 'inputs/monero/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])
infile = 'inputs/wownero/contrib/gitian/gitian-' + tag_name + '.yml'
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('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')
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')
@ -93,7 +93,7 @@ def build():
os.chdir('builder')
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()
@ -104,7 +104,7 @@ def verify():
for i, v in platforms:
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)
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.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('-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('-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')
@ -178,8 +178,8 @@ def main():
if args.setup:
setup()
os.makedirs('builder/inputs/monero', exist_ok=True)
os.chdir('builder/inputs/monero')
os.makedirs('builder/inputs/wownero', exist_ok=True)
os.chdir('builder/inputs/wownero')
if args.pull:
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()

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

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

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

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

@ -69,4 +69,4 @@ endif()
add_subdirectory(db_drivers)
add_subdirectory(easylogging++)
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 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
HANDLE h_stdout = GetStdHandle(STD_OUTPUT_HANDLE);
switch (color)

@ -0,0 +1 @@
Subproject commit 607bad48f3687c2490d90f8c55efa2dcd7cbc195

1
external/randomx vendored

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

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

@ -241,8 +241,15 @@ void BlockchainDB::add_transaction(const crypto::hash& blk_hash, const std::pair
}
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,
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);
@ -446,582 +453,7 @@ void BlockchainDB::fixup()
LOG_PRINT_L1("Database is opened read only - skipping fixup check");
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);
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)

@ -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_hash = blk_hash;
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;
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.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;
@ -1504,7 +1504,7 @@ void BlockchainLMDB::open(const std::string& filename, const int db_flags)
mdb_env_close(m_env);
m_open = false;
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;
}
// Note that there was a schema change within version 0 as well.

@ -157,7 +157,7 @@ endif()
set_property(TARGET blockchain_import
PROPERTY
OUTPUT_NAME "monero-blockchain-import")
OUTPUT_NAME "wownero-blockchain-import")
install(TARGETS blockchain_import DESTINATION bin)
monero_add_executable(blockchain_export
@ -178,7 +178,7 @@ target_link_libraries(blockchain_export
set_property(TARGET blockchain_export
PROPERTY
OUTPUT_NAME "monero-blockchain-export")
OUTPUT_NAME "wownero-blockchain-export")
install(TARGETS blockchain_export DESTINATION bin)
monero_add_executable(blockchain_blackball
@ -200,7 +200,7 @@ target_link_libraries(blockchain_blackball
set_property(TARGET blockchain_blackball
PROPERTY
OUTPUT_NAME "monero-blockchain-mark-spent-outputs")
OUTPUT_NAME "wownero-blockchain-mark-spent-outputs")
install(TARGETS blockchain_blackball DESTINATION bin)
@ -222,7 +222,7 @@ target_link_libraries(blockchain_usage
set_property(TARGET blockchain_usage
PROPERTY
OUTPUT_NAME "monero-blockchain-usage")
OUTPUT_NAME "wownero-blockchain-usage")
install(TARGETS blockchain_usage DESTINATION bin)
monero_add_executable(blockchain_ancestry
@ -243,7 +243,7 @@ target_link_libraries(blockchain_ancestry
set_property(TARGET blockchain_ancestry
PROPERTY
OUTPUT_NAME "monero-blockchain-ancestry")
OUTPUT_NAME "wownero-blockchain-ancestry")
install(TARGETS blockchain_ancestry DESTINATION bin)
monero_add_executable(blockchain_depth
@ -264,7 +264,7 @@ target_link_libraries(blockchain_depth
set_property(TARGET blockchain_depth
PROPERTY
OUTPUT_NAME "monero-blockchain-depth")
OUTPUT_NAME "wownero-blockchain-depth")
install(TARGETS blockchain_depth DESTINATION bin)
monero_add_executable(blockchain_stats
@ -285,7 +285,7 @@ target_link_libraries(blockchain_stats
set_property(TARGET blockchain_stats
PROPERTY
OUTPUT_NAME "monero-blockchain-stats")
OUTPUT_NAME "wownero-blockchain-stats")
install(TARGETS blockchain_stats DESTINATION bin)
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
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)
monero_add_executable(blockchain_prune
@ -316,7 +316,7 @@ monero_add_executable(blockchain_prune
set_property(TARGET blockchain_prune
PROPERTY
OUTPUT_NAME "monero-blockchain-prune")
OUTPUT_NAME "wownero-blockchain-prune")
install(TARGETS blockchain_prune DESTINATION bin)
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))
{
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;
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))
mlog_set_log(command_line::get_arg(vm, arg_log_level).c_str());
else

@ -132,7 +132,7 @@ static std::string get_default_db_path()
boost::filesystem::path dir = tools::get_default_data_dir();
// remove .bitmonero, replace with .shared-ringdb
dir = dir.remove_filename();
dir /= ".shared-ringdb";
dir /= ".wow-shared-ringdb";
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_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<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 = {
"db-sync-mode"
, "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))
{
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;
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))
mlog_set_log(command_line::get_arg(vm, arg_log_level).c_str());
else

@ -88,12 +88,12 @@ int main(int argc, char* argv[])
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;
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))
mlog_set_log(command_line::get_arg(vm, arg_log_level).c_str());
else

@ -90,12 +90,12 @@ int main(int argc, char* argv[])
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;
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))
mlog_set_log(command_line::get_arg(vm, arg_log_level).c_str());
else

@ -637,7 +637,7 @@ int main(int argc, char* argv[])
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;
return 1;
}
@ -674,7 +674,7 @@ int main(int argc, char* argv[])
}
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))
mlog_set_log(command_line::get_arg(vm, arg_log_level).c_str());
else

@ -52,9 +52,11 @@ using namespace cryptonote;
static std::string db_path;
// default to fast:1
static uint64_t records_per_sync = 128;
static uint64_t records_per_sync = 16 * 65536;
static const size_t slack = 512 * 1024 * 1024;
static std::vector<bool> is_v1;
static std::error_code replace_file(const boost::filesystem::path& replacement_name, const boost::filesystem::path& replaced_name)
{
std::error_code ec = tools::replace_file(replacement_name.string(), replaced_name.string());
@ -89,6 +91,14 @@ static void close(MDB_env *env)
mdb_env_close(env);
}
static void mark_v1_tx(const MDB_val &k, const MDB_val &v)
{
const uint64_t tx_id = *(const uint64_t*)k.mv_data;
if (tx_id >= is_v1.size())
is_v1.resize(tx_id + 1, false);
is_v1[tx_id] = cryptonote::is_v1_tx(cryptonote::blobdata_ref{(const char*)v.mv_data, v.mv_size});
}
static void add_size(MDB_env *env, uint64_t bytes)
{
try
@ -136,7 +146,7 @@ static void check_resize(MDB_env *env, size_t bytes)
add_size(env, size_used + bytes + 2 * slack - mei.me_mapsize);
}
static bool resize_point(size_t nrecords, MDB_env *env, MDB_txn **txn, size_t &bytes)
static bool resize_point(size_t &nrecords, MDB_env *env, MDB_txn **txn, size_t &bytes)
{
if (nrecords % records_per_sync && bytes <= slack / 2)
return false;
@ -146,10 +156,11 @@ static bool resize_point(size_t nrecords, MDB_env *env, MDB_txn **txn, size_t &b
dbr = mdb_txn_begin(env, NULL, 0, txn);
if (dbr) throw std::runtime_error("Failed to create LMDB transaction: " + std::string(mdb_strerror(dbr)));
bytes = 0;
nrecords = 0;
return true;
}
static void copy_table(MDB_env *env0, MDB_env *env1, const char *table, unsigned int flags, unsigned int putflags, int (*cmp)(const MDB_val*, const MDB_val*)=0)
static void copy_table(MDB_env *env0, MDB_env *env1, const char *table, unsigned int flags, unsigned int putflags, int (*cmp)(const MDB_val*, const MDB_val*)=0, void (*f)(const MDB_val&, const MDB_val&) = 0)
{
MDB_dbi dbi0, dbi1;
MDB_txn *txn0, *txn1;
@ -200,6 +211,11 @@ static void copy_table(MDB_env *env0, MDB_env *env1, const char *table, unsigned
dbr = mdb_cursor_open(txn1, dbi1, &cur1);
if (dbr) throw std::runtime_error("Failed to create LMDB cursor: " + std::string(mdb_strerror(dbr)));
if (flags & MDB_DUPSORT)
putflags |= MDB_APPENDDUP;
else
putflags |= MDB_APPEND;
MDB_val k;
MDB_val v;
MDB_cursor_op op = MDB_FIRST;
@ -214,7 +230,8 @@ static void copy_table(MDB_env *env0, MDB_env *env1, const char *table, unsigned
throw std::runtime_error("Failed to enumerate " + std::string(table) + " records: " + std::string(mdb_strerror(ret)));
bytes += k.mv_size + v.mv_size;
if (resize_point(++nrecords, env1, &txn1, bytes))
++nrecords;
if (resize_point(nrecords, env1, &txn1, bytes))
{
dbr = mdb_cursor_open(txn1, dbi1, &cur1);
if (dbr) throw std::runtime_error("Failed to create LMDB cursor: " + std::string(mdb_strerror(dbr)));
@ -223,6 +240,9 @@ static void copy_table(MDB_env *env0, MDB_env *env1, const char *table, unsigned
ret = mdb_cursor_put(cur1, &k, &v, putflags);
if (ret)
throw std::runtime_error("Failed to write " + std::string(table) + " record: " + std::string(mdb_strerror(ret)));
if (f)
(*f)(k, v);
}
mdb_cursor_close(cur1);
@ -235,17 +255,6 @@ static void copy_table(MDB_env *env0, MDB_env *env1, const char *table, unsigned
mdb_dbi_close(env0, dbi0);
}
static bool is_v1_tx(MDB_cursor *c_txs_pruned, MDB_val *tx_id)
{
MDB_val v;
int ret = mdb_cursor_get(c_txs_pruned, tx_id, &v, MDB_SET);
if (ret)
throw std::runtime_error("Failed to find transaction pruned data: " + std::string(mdb_strerror(ret)));
if (v.mv_size == 0)
throw std::runtime_error("Invalid transaction pruned data");
return cryptonote::is_v1_tx(cryptonote::blobdata_ref{(const char*)v.mv_data, v.mv_size});
}
static void prune(MDB_env *env0, MDB_env *env1)
{
MDB_dbi dbi0_blocks, dbi0_txs_pruned, dbi0_txs_prunable, dbi0_tx_indices, dbi1_txs_prunable, dbi1_txs_prunable_tip, dbi1_properties;
@ -324,7 +333,10 @@ static void prune(MDB_env *env0, MDB_env *env1)
mdb_dbi_close(env0, dbi0_blocks);
const uint64_t blockchain_height = stats.ms_entries;
size_t nrecords = 0, bytes = 0;
std::vector<bool> prunable_needed;
// go through all txes tx indices, recording which ones should have their prunable part retained
MINFO("Marking prunable txes");
MDB_cursor_op op = MDB_FIRST;
while (1)
{
@ -336,7 +348,8 @@ static void prune(MDB_env *env0, MDB_env *env1)
const txindex *ti = (const txindex*)v.mv_data;
const uint64_t block_height = ti->data.block_id;
MDB_val_set(kk, ti->data.tx_id);
const uint64_t tx_id = ti->data.tx_id;
MDB_val_set(kk, tx_id);
if (block_height + CRYPTONOTE_PRUNING_TIP_BLOCKS >= blockchain_height)
{
MDEBUG(block_height << "/" << blockchain_height << " is in tip");
@ -344,22 +357,23 @@ static void prune(MDB_env *env0, MDB_env *env1)
dbr = mdb_cursor_put(cur1_txs_prunable_tip, &kk, &vv, 0);
if (dbr) throw std::runtime_error("Failed to write prunable tx tip data: " + std::string(mdb_strerror(dbr)));
bytes += kk.mv_size + vv.mv_size;
}
if (tools::has_unpruned_block(block_height, blockchain_height, pruning_seed) || is_v1_tx(cur0_txs_pruned, &kk))
{
MDB_val vv;
dbr = mdb_cursor_get(cur0_txs_prunable, &kk, &vv, MDB_SET);
if (dbr) throw std::runtime_error("Failed to read prunable tx data: " + std::string(mdb_strerror(dbr)));
bytes += kk.mv_size + vv.mv_size;
if (resize_point(++nrecords, env1, &txn1, bytes))
++nrecords;
if (resize_point(nrecords, env1, &txn1, bytes))
{
dbr = mdb_cursor_open(txn1, dbi1_txs_prunable, &cur1_txs_prunable);
if (dbr) throw std::runtime_error("Failed to create LMDB cursor: " + std::string(mdb_strerror(dbr)));
dbr = mdb_cursor_open(txn1, dbi1_txs_prunable_tip, &cur1_txs_prunable_tip);
if (dbr) throw std::runtime_error("Failed to create LMDB cursor: " + std::string(mdb_strerror(dbr)));
}
dbr = mdb_cursor_put(cur1_txs_prunable, &kk, &vv, 0);
if (dbr) throw std::runtime_error("Failed to write prunable tx data: " + std::string(mdb_strerror(dbr)));
}
if (tx_id >= is_v1.size())
throw std::runtime_error("tx_id out of range of is_v1 vector");
if (tools::has_unpruned_block(block_height, blockchain_height, pruning_seed) || is_v1[tx_id])
{
if (tx_id >= prunable_needed.size())
prunable_needed.resize(tx_id + 1, false);
prunable_needed[tx_id] = true;
}
else
{
@ -367,6 +381,37 @@ static void prune(MDB_env *env0, MDB_env *env1)
}
}
// go through prunable parts, carrying over those we need
MINFO("Copying retained prunable data");
op = MDB_FIRST;
while (1)
{
int ret = mdb_cursor_get(cur0_txs_prunable, &k, &v, op);
op = MDB_NEXT;
if (ret == MDB_NOTFOUND)
break;
if (ret) throw std::runtime_error("Failed to enumerate records: " + std::string(mdb_strerror(ret)));
const uint64_t tx_id = *(const uint64_t*)k.mv_data;
if (tx_id >= prunable_needed.size())
throw std::runtime_error("tx_id out of range of prunable_needed vector");
if (prunable_needed[tx_id])
{
dbr = mdb_cursor_put(cur1_txs_prunable, &k, &v, MDB_APPEND);
if (dbr) throw std::runtime_error("Failed to write prunable tx data: " + std::string(mdb_strerror(dbr)));
bytes += k.mv_size + v.mv_size;
++nrecords;
if (resize_point(nrecords, env1, &txn1, bytes))
{
dbr = mdb_cursor_open(txn1, dbi1_txs_prunable, &cur1_txs_prunable);
if (dbr) throw std::runtime_error("Failed to create LMDB cursor: " + std::string(mdb_strerror(dbr)));
dbr = mdb_cursor_open(txn1, dbi1_txs_prunable_tip, &cur1_txs_prunable_tip);
if (dbr) throw std::runtime_error("Failed to create LMDB cursor: " + std::string(mdb_strerror(dbr)));
}
}
}
mdb_cursor_close(cur1_txs_prunable_tip);
mdb_cursor_close(cur1_txs_prunable);
mdb_cursor_close(cur0_txs_prunable);
@ -419,7 +464,7 @@ static bool parse_db_sync_mode(std::string db_sync_mode, uint64_t &db_flags)
else if(options[0] == "fastest")
{
db_flags = DBF_FASTEST;
records_per_sync = 1000; // default to fastest:async:1000
// default to fastest:async:N
}
else
return false;
@ -455,7 +500,7 @@ int main(int argc, char* argv[])
const command_line::arg_descriptor<std::string> arg_db_sync_mode = {
"db-sync-mode"
, "Specify sync option, using format [safe|fast|fastest]:[nrecords_per_sync]."
, "fast:1000"
, "fast:" + std::to_string(records_per_sync)
};
const command_line::arg_descriptor<bool> arg_copy_pruned_database = {"copy-pruned-database", "Copy database anyway if already pruned"};
@ -483,12 +528,12 @@ int main(int argc, char* argv[])
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;
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))
mlog_set_log(command_line::get_arg(vm, arg_log_level).c_str());
else
@ -601,26 +646,27 @@ int main(int argc, char* argv[])
MDB_env *env0 = NULL, *env1 = NULL;
open(env0, paths[0], db_flags, true);
open(env1, paths[1], db_flags, false);
copy_table(env0, env1, "blocks", MDB_INTEGERKEY, MDB_APPEND);
copy_table(env0, env1, "block_info", MDB_INTEGERKEY | MDB_DUPSORT| MDB_DUPFIXED, MDB_APPENDDUP, BlockchainLMDB::compare_uint64);
copy_table(env0, env1, "blocks", MDB_INTEGERKEY, 0);
copy_table(env0, env1, "block_info", MDB_INTEGERKEY | MDB_DUPSORT| MDB_DUPFIXED, 0, BlockchainLMDB::compare_uint64);
copy_table(env0, env1, "block_heights", MDB_INTEGERKEY | MDB_DUPSORT| MDB_DUPFIXED, 0, BlockchainLMDB::compare_hash32);
//copy_table(env0, env1, "txs", MDB_INTEGERKEY);
copy_table(env0, env1, "txs_pruned", MDB_INTEGERKEY, MDB_APPEND);
copy_table(env0, env1, "txs_prunable_hash", MDB_INTEGERKEY | MDB_DUPSORT | MDB_DUPFIXED, MDB_APPEND);
copy_table(env0, env1, "txs_pruned", MDB_INTEGERKEY, 0, NULL, &mark_v1_tx);
copy_table(env0, env1, "txs_prunable_hash", MDB_INTEGERKEY | MDB_DUPSORT | MDB_DUPFIXED, 0);
// not copied: prunable, prunable_tip
copy_table(env0, env1, "tx_indices", MDB_INTEGERKEY | MDB_DUPSORT | MDB_DUPFIXED, 0, BlockchainLMDB::compare_hash32);
copy_table(env0, env1, "tx_outputs", MDB_INTEGERKEY, MDB_APPEND);
copy_table(env0, env1, "output_txs", MDB_INTEGERKEY | MDB_DUPSORT | MDB_DUPFIXED, MDB_APPENDDUP, BlockchainLMDB::compare_uint64);
copy_table(env0, env1, "output_amounts", MDB_INTEGERKEY | MDB_DUPSORT | MDB_DUPFIXED, MDB_APPENDDUP, BlockchainLMDB::compare_uint64);
copy_table(env0, env1, "spent_keys", MDB_INTEGERKEY | MDB_DUPSORT | MDB_DUPFIXED, MDB_NODUPDATA, BlockchainLMDB::compare_hash32);
copy_table(env0, env1, "txpool_meta", 0, MDB_NODUPDATA, BlockchainLMDB::compare_hash32);
copy_table(env0, env1, "txpool_blob", 0, MDB_NODUPDATA, BlockchainLMDB::compare_hash32);
copy_table(env0, env1, "hf_versions", MDB_INTEGERKEY, MDB_APPEND);
copy_table(env0, env1, "tx_outputs", MDB_INTEGERKEY, 0);
copy_table(env0, env1, "output_txs", MDB_INTEGERKEY | MDB_DUPSORT | MDB_DUPFIXED, 0, BlockchainLMDB::compare_uint64);
copy_table(env0, env1, "output_amounts", MDB_INTEGERKEY | MDB_DUPSORT | MDB_DUPFIXED, 0, BlockchainLMDB::compare_uint64);
copy_table(env0, env1, "spent_keys", MDB_INTEGERKEY | MDB_DUPSORT | MDB_DUPFIXED, 0, BlockchainLMDB::compare_hash32);
copy_table(env0, env1, "txpool_meta", 0, 0, BlockchainLMDB::compare_hash32);
copy_table(env0, env1, "txpool_blob", 0, 0, BlockchainLMDB::compare_hash32);
copy_table(env0, env1, "alt_blocks", 0, 0, BlockchainLMDB::compare_hash32);
copy_table(env0, env1, "hf_versions", MDB_INTEGERKEY, 0);
copy_table(env0, env1, "properties", 0, 0, BlockchainLMDB::compare_string);
if (already_pruned)
{
copy_table(env0, env1, "txs_prunable", MDB_INTEGERKEY, MDB_APPEND, BlockchainLMDB::compare_uint64);
copy_table(env0, env1, "txs_prunable_tip", MDB_INTEGERKEY | MDB_DUPSORT | MDB_DUPFIXED, MDB_NODUPDATA, BlockchainLMDB::compare_uint64);
copy_table(env0, env1, "txs_prunable", MDB_INTEGERKEY, 0, BlockchainLMDB::compare_uint64);
copy_table(env0, env1, "txs_prunable_tip", MDB_INTEGERKEY | MDB_DUPSORT | MDB_DUPFIXED, 0, BlockchainLMDB::compare_uint64);
}
else
{

@ -137,12 +137,12 @@ int main(int argc, char* argv[])
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;
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))
mlog_set_log(command_line::get_arg(vm, arg_log_level).c_str());
else

@ -175,12 +175,12 @@ int main(int argc, char* argv[])
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;
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))
mlog_set_log(command_line::get_arg(vm, arg_log_level).c_str());
else

@ -120,12 +120,12 @@ int main(int argc, char* argv[])
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;
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))
mlog_set_log(command_line::get_arg(vm, arg_log_level).c_str());
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")
list(APPEND GENERATED_SOURCES ${OUTPUT_C_SOURCE})
set(INPUT_DAT_FILE "${BLOB_NAME}.dat")

@ -4,18 +4,12 @@
extern const unsigned char checkpoints[];
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
{
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::STAGENET, {stagenet_blocks, stagenet_blocks_len}},
{cryptonote::network_type::TESTNET, {testnet_blocks, testnet_blocks_len}}
{cryptonote::network_type::MAINNET, {checkpoints, checkpoints_len}}
};
const epee::span<const unsigned char> GetCheckpointsData(cryptonote::network_type network)

Binary file not shown.

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

@ -295,7 +295,7 @@ DNSResolver::DNSResolver() : m_data(new DNSResolverData())
// should be a valid DNSSEC record, and switch to known good
// DNSSEC resolvers if verification fails
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);
if (!valid)
{
@ -419,7 +419,7 @@ namespace dns_utils
std::string address_from_txt_record(const std::string& s)
{
// 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)
return {};
// 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)
{
// 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 {};
@ -554,7 +554,7 @@ bool load_txt_records_from_dns(std::vector<std::string> &good_records, const std
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;
}

@ -46,13 +46,6 @@ namespace tools
// All four MoneroPulse domains have DNSSEC on and valid
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))
@ -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)
{
const char *base = user ? "https://downloads.getmonero.org/" : "https://updates.getmonero.org/";
const char *base = user ? "" : "";
#ifdef _WIN32
static const char *extension = strncmp(buildtag.c_str(), "source", 6) ? (strncmp(buildtag.c_str(), "install-", 8) ? ".zip" : ".exe") : ".tar.bz2";
#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
static const char extension[] = ".tar.bz2";
#endif

@ -676,7 +676,7 @@ std::string get_nix_version_display_string()
{
ub_ctx *ctx = ub_ctx_create();
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
free(unbound);
free(monero);

@ -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 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_free_state(void);
uint64_t rx_seedheight(const uint64_t height);

@ -200,7 +200,6 @@ static inline int v4_random_math_init(struct V4_Instruction* code, const uint64_
memset(data, 0, sizeof(data));
uint64_t tmp = SWAP64LE(height);
memcpy(data, &tmp, sizeof(uint64_t));
data[20] = -38; // change seed
// Set data_index past the last byte in data
// 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
// So we keep track of it and try again if it's not used
bool r8_used;
do {
int latency[9];
int asic_latency[9];
int latency[8];
int asic_latency[8];
// Tracks previous instruction and value of the source operand for registers R0-R3 throughout code execution
// 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
// 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 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;
int total_iterations = 0;
r8_used = false;
// Generate random code to achieve minimal required latency for our abstract CPU
// 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))
{
// Use register R8 as source instead
b = 8;
src_index = 8;
b = a + 4;
src_index = b;
}
// 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].C = 0;
if (src_index == 8)
{
r8_used = true;
}
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
// Get this latency for at least 1 of the 4 registers
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 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
// 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
// Add final instruction to stop the interpreter

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

@ -196,6 +196,11 @@ namespace boost
a & b.timestamp;
a & b.prev_id;
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.tx_hashes;
@ -330,7 +335,7 @@ namespace boost
a & x.type;
if (x.type == rct::RCTTypeNull)
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");
// 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
@ -364,7 +369,7 @@ namespace boost
a & x.type;
if (x.type == rct::RCTTypeNull)
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");
// 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
@ -384,7 +389,7 @@ namespace boost
a & x.p.MGs;
if (ver >= 1u)
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;
}

@ -190,9 +190,9 @@ namespace cryptonote
CHECK_AND_ASSERT_MES(n_amounts == rv.outPk.size(), false, "Internal error filling out V");
rv.p.bulletproofs_plus[0].V.resize(n_amounts);
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)
{
@ -205,7 +205,7 @@ namespace cryptonote
return false;
}
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));
return false;
@ -216,6 +216,26 @@ namespace cryptonote
for (size_t i = 0; i < n_amounts; ++i)
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;
@ -451,6 +471,11 @@ namespace cryptonote
const bool bulletproof_plus = rct::is_rct_bulletproof_plus(rv.type);
if (!bulletproof && !bulletproof_plus)
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);
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");
@ -1113,10 +1138,10 @@ namespace cryptonote
{
switch (decimal_point)
{
case 12:
case 9:
case 6:
case 3:
case 11:
case 8:
case 5:
case 2:
case 0:
default_decimal_point = decimal_point;
break;
@ -1136,16 +1161,16 @@ namespace cryptonote
decimal_point = default_decimal_point;
switch (decimal_point)
{
case 12:
return "monero";
case 9:
return "millinero";
case 6:
return "micronero";
case 3:
return "nanonero";
case 11:
return "wownero";
case 8:
return "verywow";
case 5:
return "muchwow";
case 2:
return "suchwow";
case 0:
return "piconero";
return "dust";
default:
ASSERT_MES_AND_THROW("Invalid decimal point specification: " << decimal_point);
}
@ -1461,33 +1486,6 @@ namespace cryptonote
if (!hash_result)
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;
}
//---------------------------------------------------------------
@ -1517,6 +1515,25 @@ namespace cryptonote
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> res = off;

@ -124,6 +124,8 @@ namespace cryptonote
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);
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);
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 <cstdint>
#include <vector>
#include <boost/math/special_functions/round.hpp>
#include "int-util.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) {
if(timestamps.size() > DIFFICULTY_WINDOW)
if(timestamps.size() > DIFFICULTY_WINDOW_V3)
{
timestamps.resize(DIFFICULTY_WINDOW);
cumulative_difficulties.resize(DIFFICULTY_WINDOW);
timestamps.resize(DIFFICULTY_WINDOW_V3);
cumulative_difficulties.resize(DIFFICULTY_WINDOW_V3);
}
@ -133,17 +134,17 @@ namespace cryptonote {
if (length <= 1) {
return 1;
}
static_assert(DIFFICULTY_WINDOW >= 2, "Window is too small");
assert(length <= DIFFICULTY_WINDOW);
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 <= DIFFICULTY_WINDOW - 2, "Cut length is too large");
if (length <= DIFFICULTY_WINDOW - 2 * DIFFICULTY_CUT) {
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 - 2 * DIFFICULTY_CUT) + 1) / 2;
cut_end = cut_begin + (DIFFICULTY_WINDOW - 2 * DIFFICULTY_CUT);
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];
@ -200,7 +201,7 @@ namespace cryptonote {
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
if(timestamps.size() > DIFFICULTY_WINDOW)
{
@ -214,6 +215,8 @@ namespace cryptonote {
if (length <= 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");
assert(length <= DIFFICULTY_WINDOW);
sort(timestamps.begin(), timestamps.end());
@ -254,4 +257,193 @@ namespace cryptonote {
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(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);
}

@ -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<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<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_idle_threshold_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)
{
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))
{
std::string buff;
@ -523,15 +557,18 @@ namespace cryptonote
bool miner::worker_thread()
{
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) + "]");
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;
uint64_t height = 0;
difficulty_type local_diff = 0;
uint32_t local_template_ver = 0;
block b;
slow_hash_allocate_state();
++m_threads_active;
while(!m_stop)
@ -574,6 +611,29 @@ namespace cryptonote
}
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;
m_gbh(b, height, NULL, tools::get_max_concurrency(), h);
@ -581,7 +641,42 @@ namespace cryptonote
{
//we lucky!
++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;
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;
get_block_hash_t m_gbh;
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<2> m_update_merge_hr_interval;
epee::math_helper::once_a_time_seconds<1> m_autodetect_interval;

@ -53,6 +53,7 @@ namespace cryptonote
bool m_overspend;
bool m_fee_too_low;
bool m_too_few_outputs;
bool m_tx_extra_too_big;
};
struct block_verification_context

@ -40,19 +40,22 @@
#define CRYPTONOTE_MAX_TX_SIZE 1000000
#define CRYPTONOTE_MAX_TX_PER_BLOCK 0x10000000
#define CRYPTONOTE_PUBLIC_ADDRESS_TEXTBLOB_VER 0
#define CRYPTONOTE_MINED_MONEY_UNLOCK_WINDOW_V2 288
#define CRYPTONOTE_MINED_MONEY_UNLOCK_WINDOW 60
#define CURRENT_TRANSACTION_VERSION 2
#define CURRENT_BLOCK_MAJOR_VERSION 1
#define CURRENT_BLOCK_MINOR_VERSION 0
#define CURRENT_BLOCK_MAJOR_VERSION 7
#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_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
// MONEY_SUPPLY - total number coins to be generated
#define MONEY_SUPPLY ((uint64_t)(-1))
#define EMISSION_SPEED_FACTOR_PER_MINUTE (20)
#define FINAL_SUBSIDY_PER_MINUTE ((uint64_t)300000000000) // 3 * pow(10, 11)
#define EMISSION_SPEED_FACTOR_PER_MINUTE (24)
#define FINAL_SUBSIDY_PER_MINUTE ((uint64_t)(0)) // 0
#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
@ -61,9 +64,9 @@
#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_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
#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 ((uint64_t)2000000000) // 2 * pow(10, 9)
@ -76,11 +79,18 @@
#define ORPHANED_BLOCKS_MAX_COUNT 100
#define DIFFICULTY_TARGET_V2 120 // seconds
#define DIFFICULTY_TARGET_V1 60 // seconds - before first fork
#define DIFFICULTY_TARGET_V2 300 // seconds
#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_LAG_V2 3
#define DIFFICULTY_LAG 15 // !!!
#define DIFFICULTY_CUT_V2 12
#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
@ -94,12 +104,12 @@
#define BLOCKS_IDS_SYNCHRONIZING_DEFAULT_COUNT 10000 //by default, blocks ids count in synchronizing
#define BLOCKS_IDS_SYNCHRONIZING_MAX_COUNT 25000 //max blocks ids count in synchronizing
#define BLOCKS_SYNCHRONIZING_DEFAULT_COUNT_PRE_V4 100 //by default, blocks count in blocks downloading
#define BLOCKS_SYNCHRONIZING_DEFAULT_COUNT_PRE_V4 50 //by default, blocks count in blocks downloading
#define BLOCKS_SYNCHRONIZING_DEFAULT_COUNT 20 //by default, blocks count in blocks downloading
#define BLOCKS_SYNCHRONIZING_MAX_COUNT 2048 //must be a power of 2, greater than 128, equal to SEEDHASH_EPOCH_BLOCKS
#define CRYPTONOTE_MEMPOOL_TX_LIVETIME (86400*3) //seconds, three days
#define CRYPTONOTE_MEMPOOL_TX_FROM_ALT_BLOCK_LIVETIME 604800 //seconds, one week
#define CRYPTONOTE_MEMPOOL_TX_LIVETIME 86400 //seconds, one day
#define CRYPTONOTE_MEMPOOL_TX_FROM_ALT_BLOCK_LIVETIME 86400 //seconds, one day
#define CRYPTONOTE_DANDELIONPP_STEMS 2 // number of outgoing stem connections per epoch
@ -131,7 +141,7 @@
#define P2P_LOCAL_WHITE_PEERLIST_LIMIT 1000
#define P2P_LOCAL_GRAY_PEERLIST_LIMIT 5000
#define P2P_DEFAULT_CONNECTIONS_COUNT 12
#define P2P_DEFAULT_CONNECTIONS_COUNT 64
#define P2P_DEFAULT_HANDSHAKE_INTERVAL 60 //secondes
#define P2P_DEFAULT_PACKET_MAX_SIZE 50000000 //50000000 bytes maximum packet size
#define P2P_DEFAULT_PEERS_IN_HANDSHAKE 250
@ -144,8 +154,8 @@
#define P2P_DEFAULT_WHITELIST_CONNECTIONS_PERCENT 70
#define P2P_DEFAULT_ANCHOR_CONNECTIONS_COUNT 2
#define P2P_DEFAULT_SYNC_SEARCH_CONNECTIONS_COUNT 2
#define P2P_DEFAULT_LIMIT_RATE_UP 2048 // kB/s
#define P2P_DEFAULT_LIMIT_RATE_DOWN 8192 // kB/s
#define P2P_DEFAULT_LIMIT_RATE_UP 1048576 // 1GB/s
#define P2P_DEFAULT_LIMIT_RATE_DOWN 1048576 // 1GB/s
#define P2P_FAILED_ADDR_FORGET_SECONDS (60*60) //1 hour
#define P2P_IP_BLOCKTIME (60*60*24) //24 hour
@ -157,7 +167,7 @@
#define RPC_IP_FAILS_BEFORE_BLOCK 3
#define CRYPTONOTE_NAME "bitmonero"
#define CRYPTONOTE_NAME "wownero"
#define CRYPTONOTE_BLOCKCHAINDATA_FILENAME "data.mdb"
#define CRYPTONOTE_BLOCKCHAINDATA_LOCK_FILENAME "lock.mdb"
#define P2P_NET_DATA_FILENAME "p2pstate.bin"
@ -167,26 +177,28 @@
#define THREAD_STACK_SIZE 5 * 1024 * 1024
#define HF_VERSION_DYNAMIC_FEE 4
#define HF_VERSION_MIN_MIXIN_4 6
#define HF_VERSION_MIN_MIXIN_6 7
#define HF_VERSION_MIN_MIXIN_10 8
#define HF_VERSION_MIN_MIXIN_15 15
#define HF_VERSION_MIN_MIXIN_7 7
#define HF_VERSION_MIN_MIXIN_21 9
#define HF_VERSION_ENFORCE_RCT 6
#define HF_VERSION_PER_BYTE_FEE 8
#define HF_VERSION_SMALLER_BP 10
#define HF_VERSION_LONG_TERM_BLOCK_WEIGHT 10
#define HF_VERSION_MIN_2_OUTPUTS 12
#define HF_VERSION_MIN_V2_COINBASE_TX 12
#define HF_VERSION_SAME_MIXIN 12
#define HF_VERSION_REJECT_SIGS_IN_COINBASE 12
#define HF_VERSION_ENFORCE_MIN_AGE 12
#define HF_VERSION_EFFECTIVE_SHORT_TERM_MEDIAN_IN_PENALTY 12
#define HF_VERSION_EXACT_COINBASE 13
#define HF_VERSION_CLSAG 13
#define HF_VERSION_DETERMINISTIC_UNLOCK_TIME 13
#define HF_VERSION_BULLETPROOF_PLUS 15
#define HF_VERSION_VIEW_TAGS 15
#define HF_VERSION_2021_SCALING 15
#define HF_VERSION_PER_BYTE_FEE 12
#define HF_VERSION_SMALLER_BP 13
#define HF_VERSION_LONG_TERM_BLOCK_WEIGHT 13
#define HF_VERSION_MIN_2_OUTPUTS 15
#define HF_VERSION_MIN_V2_COINBASE_TX 15
#define HF_VERSION_SAME_MIXIN 15
#define HF_VERSION_REJECT_SIGS_IN_COINBASE 15
#define HF_VERSION_ENFORCE_MIN_AGE 15
#define HF_VERSION_EFFECTIVE_SHORT_TERM_MEDIAN_IN_PENALTY 15
#define HF_VERSION_EXACT_COINBASE 16
#define HF_VERSION_CLSAG 16
#define HF_VERSION_DETERMINISTIC_UNLOCK_TIME 16
#define HF_VERSION_DYNAMIC_UNLOCK 16
#define HF_VERSION_FIXED_UNLOCK 18
#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 CRYPTONOTE_SCALING_2021_FEE_ROUNDING_PLACES 2
@ -206,6 +218,11 @@
#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
namespace config
{
@ -214,17 +231,17 @@ namespace config
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 CRYPTONOTE_PUBLIC_ADDRESS_BASE58_PREFIX = 18;
uint64_t const CRYPTONOTE_PUBLIC_INTEGRATED_ADDRESS_BASE58_PREFIX = 19;
uint64_t const CRYPTONOTE_PUBLIC_SUBADDRESS_BASE58_PREFIX = 42;
uint16_t const P2P_DEFAULT_PORT = 18080;
uint16_t const RPC_DEFAULT_PORT = 18081;
uint16_t const ZMQ_RPC_DEFAULT_PORT = 18082;
uint64_t const CRYPTONOTE_PUBLIC_ADDRESS_BASE58_PREFIX = 4146;
uint64_t const CRYPTONOTE_PUBLIC_INTEGRATED_ADDRESS_BASE58_PREFIX = 6810;
uint64_t const CRYPTONOTE_PUBLIC_SUBADDRESS_BASE58_PREFIX = 12208;
uint16_t const P2P_DEFAULT_PORT = 34567;
uint16_t const RPC_DEFAULT_PORT = 34568;
uint16_t const ZMQ_RPC_DEFAULT_PORT = 34569;
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
std::string const GENESIS_TX = "013c01ff0001ffffffffffff03029b2e4c0281c0b02e7c53291a94d1d0cbff8883f8024f5142ee494ffbbd08807121017767aafcde9be00dcfd098715ebcf7f410daebc582fda69d24a28e9d0bc890d1";
uint32_t const GENESIS_NONCE = 10000;
std::string const GENESIS_TX = "013c01ff0001ffffffffff1f029b2e4c0281c0b02e7c53291a94d1d0cbff8883f8024f5142ee494ffbbd08807121012a1a936be5d91c01ee876e38c13fab0ee11cbe86011a2bf7740fb5ebd39d267d";
uint32_t const GENESIS_NONCE = 70;
// Hash domain separators
const char HASH_KEY_BULLETPROOF_EXPONENT[] = "bulletproof";
@ -244,7 +261,7 @@ namespace config
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_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 constexpr char HASH_KEY_MULTISIG_TX_PRIVKEYS_SEED[] = "multisig_tx_privkeys_seed";
const constexpr char HASH_KEY_MULTISIG_TX_PRIVKEYS[] = "multisig_tx_privkeys";

@ -367,9 +367,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 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)
timestamp_diff = time(NULL) - 1397818133;
timestamp_diff = time(NULL) - 1522624244;
// create general purpose async service queue
@ -895,17 +895,19 @@ start:
// pop the oldest one from the list. This only requires 1x read per height instead
// of doing 735 (DIFFICULTY_BLOCKS_COUNT).
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)
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;
m_timestamps.push_back(m_db->get_block_timestamp(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());
while (m_difficulties.size() > DIFFICULTY_BLOCKS_COUNT)
while (m_difficulties.size() > difficulty_blocks_count)
m_difficulties.erase(m_difficulties.begin());
m_timestamps_and_difficulties_height = height;
@ -918,7 +920,7 @@ start:
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)
++offset;
@ -964,7 +966,21 @@ start:
}
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);
m_difficulty_for_next_block_top_hash = top_hash;
@ -989,7 +1005,7 @@ start:
MGINFO("START DUMP");
MGINFO(ss.str());
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;
}
@ -1023,11 +1039,13 @@ size_t Blockchain::recalculate_difficulties(boost::optional<uint64_t> start_heig
std::vector<uint64_t> timestamps;
std::vector<difficulty_type> difficulties;
timestamps.reserve(DIFFICULTY_BLOCKS_COUNT + 1);
difficulties.reserve(DIFFICULTY_BLOCKS_COUNT + 1);
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;
timestamps.reserve(difficulty_blocks_count + 1);
difficulties.reserve(difficulty_blocks_count + 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;
if (height == 0)
@ -1042,7 +1060,21 @@ size_t Blockchain::recalculate_difficulties(boost::optional<uint64_t> start_heig
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;
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;
CHECK_AND_ASSERT_THROW_MES(recalculated_cum_diff_256 <= std::numeric_limits<difficulty_type>::max(), "Difficulty overflow!");
@ -1070,9 +1102,9 @@ size_t Blockchain::recalculate_difficulties(boost::optional<uint64_t> start_heig
timestamps.push_back(m_db->get_block_timestamp(height));
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());
difficulties.erase(difficulties.begin());
}
@ -1297,16 +1329,18 @@ difficulty_type Blockchain::get_next_difficulty_for_alternative_chain(const std:
LOG_PRINT_L3("Blockchain::" << __func__);
std::vector<uint64_t> timestamps;
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
// 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);
// 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_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);
size_t main_chain_start_offset = main_chain_stop_offset - main_chain_count;
@ -1321,7 +1355,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?
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)
{
@ -1333,8 +1367,8 @@ difficulty_type Blockchain::get_next_difficulty_for_alternative_chain(const std:
// and timestamps from it alone
else
{
timestamps.resize(static_cast<size_t>(DIFFICULTY_BLOCKS_COUNT));
cumulative_difficulties.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));
size_t count = 0;
size_t max_i = timestamps.size()-1;
// get difficulties and timestamps from most recent blocks in alt chain
@ -1343,7 +1377,7 @@ difficulty_type Blockchain::get_next_difficulty_for_alternative_chain(const std:
timestamps[max_i - count] = bei.bl.timestamp;
cumulative_difficulties[max_i - count] = bei.cumulative_difficulty;
count++;
if(count >= DIFFICULTY_BLOCKS_COUNT)
if(count >= difficulty_blocks_count)
break;
}
}
@ -1352,7 +1386,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;
// 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
@ -1363,6 +1412,46 @@ difficulty_type Blockchain::get_next_difficulty_for_alternative_chain(const std:
// valid output types
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__);
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");
@ -1380,7 +1469,18 @@ bool Blockchain::prevalidate_miner_transaction(const block& b, uint64_t height,
return false;
}
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
if(!check_outs_overflow(b.miner_tx))
@ -1751,7 +1851,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
uint8_t hf_version = b.major_version;
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");
size_t cumulative_weight = txs_weight + get_transaction_weight(b.miner_tx);
#if defined(DEBUG_CREATE_BLOCK_TEMPLATE)
@ -1760,7 +1860,7 @@ bool Blockchain::create_block_template(block& b, const crypto::hash *from_block,
#endif
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");
size_t coinbase_weight = get_transaction_weight(b.miner_tx);
@ -1846,12 +1946,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
{
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;
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());
size_t stop_offset = start_top_height > need_elements ? start_top_height - need_elements : 0;
timestamps.reserve(timestamps.size() + start_top_height - stop_offset);
@ -3104,7 +3206,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 (tx.version >= 2) {
if (tx.rct_signatures.type == rct::RCTTypeBulletproof2)
@ -3116,7 +3218,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 (tx.version >= 2) {
if (tx.rct_signatures.type == rct::RCTTypeBulletproof)
@ -3128,7 +3230,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 (tx.version >= 2) {
if (tx.rct_signatures.type == rct::RCTTypeCLSAG)
@ -3140,31 +3242,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 (tx.version >= 2) {
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
static const char * grandfathered[2] = { "c5151944f0583097ba0c88cd0f43e7fabb3881278aa2f73b3b0a007c5d34e910", "6f2f117cde6fbcf8d4a6ef8974fcac744726574ac38cf25d3322c996b21edd4c" };
crypto::hash h0, h1;
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;
}
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 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 v15, allow bulletproofs plus
// from v18, allow bulletproofs plus
if (hf_version < HF_VERSION_BULLETPROOF_PLUS) {
if (tx.version >= 2) {
const bool bulletproof_plus = rct::is_rct_bulletproof_plus(tx.rct_signatures.type);
@ -3177,7 +3281,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 (tx.version >= 2) {
const bool bulletproof = rct::is_rct_bulletproof(tx.rct_signatures.type);
@ -3190,13 +3294,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))
{
tvc.m_invalid_output = true;
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;
}
//------------------------------------------------------------------
@ -3222,7 +3333,7 @@ bool Blockchain::expand_transaction_2(transaction &tx, const crypto::hash &tx_pr
rv.message = rct::hash2rct(tx_prefix_hash);
// 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");
rv.mixRing.resize(pubkeys[0].size());
@ -3237,7 +3348,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");
rv.mixRing.resize(pubkeys.size());
@ -3256,7 +3367,7 @@ bool Blockchain::expand_transaction_2(transaction &tx, const crypto::hash &tx_pr
}
// II
if (rv.type == rct::RCTTypeFull)
if (rv.type == rct::RCTTypeFull || rv.type == rct::RCTTypeFullBulletproof)
{
if (!tx.pruned)
{
@ -3266,7 +3377,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);
}
}
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)
{
@ -3340,7 +3451,7 @@ bool Blockchain::check_tx_inputs(transaction& tx, tx_verification_context &tvc,
size_t n_unmixable = 0, n_mixable = 0;
size_t min_actual_mixin = std::numeric_limits<size_t>::max();
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)
{
// non txin_to_key inputs will be rejected below
@ -3387,7 +3498,7 @@ bool Blockchain::check_tx_inputs(transaction& tx, tx_verification_context &tvc,
// allowed is when spending unmixable non-RCT outputs in the chain.
// 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.
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)
{
@ -3401,10 +3512,10 @@ bool Blockchain::check_tx_inputs(transaction& tx, tx_verification_context &tvc,
tvc.m_low_mixin = true;
return false;
}
} else if ((hf_version > HF_VERSION_MIN_MIXIN_15 && min_actual_mixin > 15)
|| (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_15 && hf_version >= HF_VERSION_MIN_MIXIN_10+2 && min_actual_mixin > 10)
|| ((hf_version == HF_VERSION_MIN_MIXIN_10 || hf_version == HF_VERSION_MIN_MIXIN_10+1) && min_actual_mixin != 10)
} else if ((hf_version > HF_VERSION_MIN_MIXIN_21 && min_actual_mixin > 21)
|| (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_21 && hf_version >= HF_VERSION_MIN_MIXIN_7+2 && min_actual_mixin > 7)
|| ((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));
@ -3573,6 +3684,7 @@ bool Blockchain::check_tx_inputs(transaction& tx, tx_verification_context &tvc,
return false;
}
case rct::RCTTypeSimple:
case rct::RCTTypeSimpleBulletproof:
case rct::RCTTypeBulletproof:
case rct::RCTTypeBulletproof2:
case rct::RCTTypeCLSAG:
@ -3640,6 +3752,7 @@ bool Blockchain::check_tx_inputs(transaction& tx, tx_verification_context &tvc,
break;
}
case rct::RCTTypeFull:
case rct::RCTTypeFullBulletproof:
{
// check all this, either reconstructed (so should really pass), or not
{
@ -4053,14 +4166,16 @@ uint64_t Blockchain::get_adjusted_time(uint64_t height) const
LOG_PRINT_L3("Blockchain::" << __func__);
// 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));
}
std::vector<uint64_t> timestamps;
// 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);
for(;offset < height; ++offset)
{
@ -4070,7 +4185,7 @@ uint64_t Blockchain::get_adjusted_time(uint64_t height) const
// 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
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
// we don't use the current block's time directly to mitigate timestamp manipulation
@ -4089,7 +4204,9 @@ bool Blockchain::check_block_timestamp(std::vector<uint64_t>& timestamps, const
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;
}
@ -4106,16 +4223,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
{
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;
}
const auto h = m_db->height();
// if not enough blocks, no proper median yet, return true
if(h < BLOCKCHAIN_TIMESTAMP_CHECK_WINDOW)
if(h < blockchain_timestamp_check_window)
{
return true;
}
@ -4123,7 +4243,7 @@ bool Blockchain::check_block_timestamp(const block& b, uint64_t& median_ts) cons
std::vector<uint64_t> timestamps;
// 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);
for(;offset < h; ++offset)
{
@ -5627,7 +5747,7 @@ void Blockchain::cancel()
}
#if defined(PER_BLOCK_CHECKPOINT)
static const char expected_block_hashes_hash[] = "b2da201879dc7a14bcb283875a9608d465b247fdea96fc80a2972b5063259591";
static const char expected_block_hashes_hash[] = "758b237b54248c7d47c699156ea8a77db0dc04cc4f89783cc2b1a5b1a9658e18";
void Blockchain::load_compiled_in_block_hashes(const GetCheckpointsCallback& get_checkpoints)
{
if (get_checkpoints == nullptr || !m_fast_sync)

@ -56,6 +56,9 @@ using namespace epee;
#include "common/notify.h"
#include "hardforks/hardforks.h"
#include "version.h"
#include <iostream>
#include <fstream>
#include <string>
#include <boost/filesystem.hpp>
@ -170,7 +173,7 @@ namespace cryptonote
};
static const command_line::arg_descriptor<std::string> arg_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"
};
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 = {
"block-rate-notify"
, "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 "
"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 "
@ -503,8 +506,8 @@ namespace cryptonote
if (boost::filesystem::exists(old_files / "blockchain.bin"))
{
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("the blockchain anew, or use monero-blockchain-export and monero-blockchain-import to");
MWARNING("Wownero now uses a new format. You can either remove blockchain.bin to start syncing");
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.");
return false;
}
@ -856,7 +859,6 @@ namespace cryptonote
tvc.m_verifivation_failed = true;
return false;
}
return true;
}
//-----------------------------------------------------------------------------------------------
@ -925,6 +927,7 @@ namespace cryptonote
tx_info[n].result = false;
break;
case rct::RCTTypeSimple:
case rct::RCTTypeSimpleBulletproof:
if (!rct::verRctSemanticsSimple(rv))
{
MERROR_VER("rct signature semantics check failed");
@ -935,6 +938,7 @@ namespace cryptonote
}
break;
case rct::RCTTypeFull:
case rct::RCTTypeFullBulletproof:
if (!rct::verRct(rv, true))
{
MERROR_VER("rct signature semantics check failed");
@ -1220,7 +1224,7 @@ namespace cryptonote
//-----------------------------------------------------------------------------------------------
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;
if (block_sync_size > 0)
res = block_sync_size;
@ -1785,6 +1789,27 @@ namespace cryptonote
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
{
return m_mempool.print_pool(short_format);
@ -1802,9 +1827,59 @@ namespace cryptonote
{
std::string main_message;
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
main_message = "The daemon will start synchronizing with the network. This may take a long time to complete.";
MGINFO_MAGENTA(ENDL <<
"\n\n"
" ██ ██ ██ ██ ███ ██ ████████ ██ ██ \n"
" ██ ██ ██ ██ ████ ██ ██ ██ ██ \n"
" █████ ██ ██ ██ ██ ██ ██ ████ \n"
" ██ ██ ██ ██ ██ ██ ██ ██ ██ \n"
" ██ ██ ██████ ██ ████ ██ ██ \n"
<< ENDL);
MGINFO_GREEN(ENDL <<
" m !5! \n"
" !Y?~: .:^~~~~^^::::... ~7J5G: \n"
" ~?JY5P5~ .:!JYJ?!~^::::^^^^^^^^^^::^^~^. \n"
" :77?Y555P5~^7Y5P5J7!~~~!7?77!~^^^:::::...:^^^^^:. \n"
" .77?JJJYYY5PPP5YJYJJYY55YJ?7!!~~~^^^:::.....^~!!!7!^. \n"
" !?J?77??JYY?J55Y5Y55PPP5J??7!~!??7!!~^:.... .:~7???p?!. \n"
" !?J?!!!!77JJ77?YY5PGP55YYYJ??Y5PP5J7!~~~~!~..:~~7J55YJJ7: \n"
" ~?JJ7^::~!?J?!?5555555PGGP55PGB#BPYJJJY55P5Y?7?J?Y5PP555Y?^ \n"
" .JJY?~:::~!7?YYYJY5PPGGGGGGGB#BGPY?JY5PPGGGGP5YY5PGGGGGPPPY7. \n"
" :7JJYY?!:.:~JYJ?JYY5PPPPPGGGGGPYJJJJ?JYPGGBBBBG5J7!7777JPPPP5J~ \n"
" :^77!777!7J!?YY77??JJ55Y55555P5YJ?JJJYYYY5PGB#BPJJY555J?~:JPP5P5JJ. \n"
" ^.~J!7????775JY?777!7JJJJYYYJ??7!7?????J5YY5P55Y5B##B###G5:7PGP5PYJY. \n"
" :.~J7?J???77~YJ!?JYYY7^^^:~JPPPGBBBBBBGPY77~!?~^#&#Y?YG#&&B?7YGGP5PYJ5. \n"
" ~^?!!??7?77!~Y!^~~~~!!^^.:5GGPP5PGB##&&&&B7:!Y?:5&Y!?YB#&&&!^7YGP55PJYY \n"
" ~?!!!?7!7!~~?7^~!!~~!!!!::P5!^~~?5P5PB###B!!P5PY~YGP5PB#&&B^?77YP5Y55J5~ \n"
" !Y?~!7!!~~!7!^^~!^~!7?YYY775Y?~~!JG5!?PGBY:7PPGBGJ?PBBGG5JJGB?!7Y5YY5YY7 \n"
" ^7!77?7!!!!~^^~~~^~!?5PGGGGJ~PBGPPGGGGBBBG:^PGBBBBBGP555PGB###B777Y5YY5JY. \n"
" ?77^:!!~~^:^^^^~^^~7YPGBBBBBPYGGPPGGGPG5J?JGBBBBBGPYJJJJJYPB&##P77?JJJYYY? \n"
" :?!!^^7!^~^^^:^^^^^!5PBBBBBBBGGGP5YY555PPPGBB#BBBG7^::......:G&#B???J??JYYY. \n"
" ^7!!^~7!^^:::^^^:::!PGBBBBBBBBBBB####BBBBBBBBBBBB5^... ....^5##BY?J??7?JJY! \n"
" ~!!!~^!7~^::^^:^:^^~YGBBBBBBBBBBBBBBBBBBBGGGGGGGGP7^.......:^YGBB5?J?7!7??JY. \n"
" ~!!!~^!!~^:^^:^^^^^~75GBBBBBBBBBBBBBBBBBGGGGGGGGPPY?!^:...:^!J5GGY?JJ7!!7??Y! \n"
" ~!!!~^~7~^^~~~~^^^^~~75PGGGGGGGGBGGGGBBBGGGPPPP555Y?!^^^^^^~!?5GGY??J?!!7??J7 \n"
" !!!!~^^7!^~!77!~~~~~~~YPPGGGGGPGGGGGGGGGGGPPPPPP55?~:::...::!5BBGJ7?J?!!??7?! \n"
" :7!!!~^^!7^~7?p?!!~!~~!JPGGGGGGGPPPGGGGGGPPPPPP5Y?~:...:::^~7YBBBG?7p?!!!7?7?? \n"
" ??~!~!~^^7~^??4?!77!!!~JPGGGGGGGGGGPGGGGP5Y?7!~~~^^~!!!!!!7YGBBBBP77?!~~!7?7?7 \n"
" .5J!!~!!~:^^!?7J?7?J77~~75PGGGGGGGGGPPPGGPP5J777?YYY55YYYYYPGBBGGGJ7?7!~~!777: \n"
" ~PY?!!~!!^^!?7?J?????7!775GGBGGGGPPPPPPPGGGGGPPPPPPPGGGGGGBBBBGGGY777!!!!77!. \n"
" JPYY7!~!77777???7!!!7!~!!JPPGGGGGGGGGPPPPPPPPPPPPPPGGGGGGBGBBGGPY!!?!!7777. \n"
" PP55YJJ3?!!7??7~^^^^~!~~!75PGGGGGBBBGGPPPPPPPPPPPPPGGGGGGGGGBG57!77!!2?!^ \n"
" GGGPPP5J!!7?7~^:::^~~!!!77YPPPGGGGGGGGPPPPPPPPPPPPPPGGGGGGGGGGYJY7~!?BP. \n"
" GBGGGGP55YYJ7~^^!~^~77!77775PPPPPP55PPPPPPPPPPPPPPGGGGGGGGGGGGGBPJY5PG~ \n"
" Fve, V'q yvxr gb fcrnx gb gur gur jbjareb znantre "
<< ENDL);
MGINFO_MAGENTA(ENDL <<
" ██ ██ █████ ██████ ███████ ███ ██ \n"
" ██ ██ ██ ██ ██ ██ ██ ████ ██ \n"
" █████ ███████ ██████ █████ ██ ██ ██ \n"
" ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ \n"
" ██ ██ ██ ██ ██ ██ ███████ ██ ████ \n"
<< ENDL);
MGINFO_YELLOW(ENDL << "**********************************************************************" << ENDL
<< main_message << ENDL
<< ENDL
@ -2045,7 +2120,7 @@ namespace cryptonote
MDEBUG("blocks in the last " << seconds[n] / 60 << " minutes: " << b << " (probability " << p << ")");
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;
if (block_rate_notify)

@ -647,6 +647,13 @@ namespace cryptonote
*/
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
*

@ -75,7 +75,7 @@ namespace cryptonote
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.vout.clear();
tx.extra.clear();
@ -171,7 +171,20 @@ namespace cryptonote
tx.version = 1;
//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.invalidate_hashes();
@ -588,7 +601,9 @@ namespace cryptonote
crypto::hash tx_prefix_hash;
get_transaction_prefix_hash(tx, tx_prefix_hash, hwdev);
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);
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
@ -697,7 +712,7 @@ namespace cryptonote
}
rx_slow_hash(hash.data, bd.data(), bd.size(), res.data);
} 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);
}
return true;

@ -37,7 +37,8 @@
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
{

@ -112,8 +112,8 @@ namespace cryptonote
uint64_t get_transaction_weight_limit(uint8_t version)
{
// from v8, limit a tx to 50% of the minimum block weight
if (version >= 8)
// from v12, limit a tx to 50% of the minimum block weight
if (version >= 12)
return get_min_block_weight(version) / 2 - CRYPTONOTE_COINBASE_BLOB_RESERVED_SIZE;
else
return get_min_block_weight(version) - CRYPTONOTE_COINBASE_BLOB_RESERVED_SIZE;
@ -219,6 +219,15 @@ namespace cryptonote
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;
return false;
}
// if the transaction came from a block popped from the chain,
// don't check if we have its key images as spent.
// TODO: Investigate why not?
@ -1421,7 +1430,7 @@ namespace cryptonote
txpool_tx_meta_t 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;
}

@ -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());
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 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;
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) << ") "
@ -1683,8 +1683,22 @@ namespace cryptonote
+ std::to_string(previous_stripe) + " -> " + std::to_string(current_stripe);
if (ELPP->vRegistry()->allowed(el::Level::Debug, "sync-info"))
timing_message += std::string(": ") + m_block_queue.get_overview(current_blockchain_height);
MGINFO_YELLOW("Synced " << current_blockchain_height << "/" << target_blockchain_height
<< progress_message << timing_message);
uint64_t num = (rand() % 4) + 1;
switch (num)
{
case 1:
MGINFO_MAGENTA("*•.¸♡ ♡¸.•* synced *•.¸♡ ♡¸.•* " << current_blockchain_height << "/" << target_blockchain_height << progress_message << timing_message << " ˚ ༘♡ ⋆。˚");
break;
case 2:
MGINFO_YELLOW("ˏˋ°•*⁀➷ pǝɔuʎs ˏˋ°•*⁀➷ " << current_blockchain_height << "/" << target_blockchain_height << progress_message << timing_message << " ︶︶༉‧₊ ☄. *.⋆");
break;
case 3:
MGINFO_BLUE("s ★ y ★ n ★ c ★ e ★ d " << current_blockchain_height << "/" << target_blockchain_height << progress_message << timing_message << " *ೃ༄ *·˚˚ ༘♡ ⋆。˚");
break;
case 4:
MGINFO_GREEN("s ♥ y ♥ n ♥ c ♥ e ♥ d " << current_blockchain_height << "/" << target_blockchain_height << progress_message << timing_message << " ⎯୧◦•◦❥•◦'*•.¸♡ ");
break;
}
if (previous_stripe != current_stripe)
notify_new_stripe(context, current_stripe);
}
@ -2262,7 +2276,7 @@ skip:
}
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();
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);
@ -2484,7 +2498,7 @@ skip:
}
}
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
<< "Use the \"help\" command to see the list of available commands." << ENDL
<< "**********************************************************************");
@ -2936,7 +2950,7 @@ skip:
m_core.set_target_blockchain_height(target);
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;
}
}

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

@ -35,7 +35,7 @@
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 = {
"config-file"

@ -417,7 +417,7 @@ bool t_command_parser_executor::start_mining(const std::vector<std::string>& arg
}
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;
}
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")
{
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 << "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 << "file keeping the same size, re-run this command with the \"confirm\" parameter." << std::endl;
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::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;
std::string usage = m_command_lookup.get_usage();
boost::replace_all(usage, "\n", "\n ");

@ -40,7 +40,7 @@
namespace daemonize
{
std::string const t_executor::NAME = "Monero Daemon";
std::string const t_executor::NAME = "Wownero Daemon";
void t_executor::init_options(
boost::program_options::options_description & configurable_options
@ -58,7 +58,7 @@ namespace daemonize
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};
}

@ -190,7 +190,7 @@ int main(int argc, char const * argv[])
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 << visible_options << std::endl;
return 0;
@ -199,7 +199,7 @@ int main(int argc, char const * argv[])
// Monero 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;
}
@ -293,7 +293,7 @@ int main(int argc, char const * argv[])
tools::set_max_concurrency(command_line::get_arg(vm, daemon_args::arg_max_concurrency));
// 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
{

@ -94,6 +94,7 @@ namespace {
void print_block_header(cryptonote::block_header_response const & header)
{
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
<< "previous hash: " << header.prev_hash << std::endl
<< "nonce: " << boost::lexical_cast<std::string>(header.nonce) << std::endl
@ -590,13 +591,13 @@ bool t_rpc_command_executor::mining_status() {
}
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;
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)
@ -614,8 +615,8 @@ bool t_rpc_command_executor::mining_status() {
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 yearly = 86400ull / mres.block_target * 356 * mres.block_reward * ratio;
tools::msg_writer() << "Expected: " << cryptonote::print_money(daily) << " monero daily, "
<< cryptonote::print_money(monthly) << " monero monthly, " << cryptonote::print_money(yearly) << " yearly";
tools::msg_writer() << "Expected: " << cryptonote::print_money(daily) << " WOW daily, "
<< cryptonote::print_money(monthly) << " WOW monthly, " << cryptonote::print_money(yearly) << " yearly";
}
return true;
@ -1459,10 +1460,10 @@ bool t_rpc_command_executor::print_status()
bool daemon_is_alive = m_rpc_client->check_connection();
if(daemon_is_alive) {
tools::success_msg_writer() << "monerod is running";
tools::success_msg_writer() << "wownerod is running";
}
else {
tools::fail_msg_writer() << "monerod is NOT running";
tools::fail_msg_writer() << "wownerod is NOT running";
}
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.";
}

@ -120,7 +120,7 @@ void fork(const std::string & pidfile)
if (!tmpdir)
tmpdir = 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 mode_t mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH;
if (open(output.c_str(), flags, mode) < 0)

@ -196,7 +196,7 @@ bool install_service(
, 0
//, GENERIC_EXECUTE | GENERIC_READ
, SERVICE_WIN32_OWN_PROCESS
, SERVICE_DEMAND_START
, SERVICE_AUTO_START
, SERVICE_ERROR_NORMAL
, full_command.c_str()
, nullptr

@ -146,9 +146,6 @@ namespace windows {
m_handler.run();
on_state_change_request_(SERVICE_CONTROL_STOP);
// Ensure that the service is uninstalled
uninstall_service(m_name);
}
static void WINAPI on_state_change_request(DWORD control_code)

@ -46,7 +46,7 @@ target_link_libraries(cn_deserialize
set_property(TARGET cn_deserialize
PROPERTY
OUTPUT_NAME "monero-utils-deserialize")
OUTPUT_NAME "wownero-utils-deserialize")
set(object_sizes_sources
@ -67,7 +67,7 @@ target_link_libraries(object_sizes
set_property(TARGET object_sizes
PROPERTY
OUTPUT_NAME "monero-utils-object-sizes")
OUTPUT_NAME "wownero-utils-object-sizes")
set(dns_checks_sources
@ -89,5 +89,5 @@ target_link_libraries(dns_checks
set_property(TARGET dns_checks
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))
{
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;
return 1;
}

@ -121,7 +121,7 @@ int main(int argc, char* argv[])
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;
return 1;
}
@ -129,20 +129,20 @@ int main(int argc, char* argv[])
mlog_configure("", true);
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
#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
lookup(LOOKUP_TXT, {"segheights.moneropulse.org", "segheights.moneropulse.net", "segheights.moneropulse.co", "segheights.moneropulse.se"});
lookup(LOOKUP_TXT, {""});
return 0;
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];
logRESP();
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_SW(this->sw,ok,mask);

@ -50,5 +50,5 @@ add_dependencies(gen_multisig
version)
set_property(TARGET gen_multisig
PROPERTY
OUTPUT_NAME "monero-gen-trusted-multisig")
OUTPUT_NAME "wownero-gen-trusted-multisig")
install(TARGETS gen_multisig DESTINATION bin)

@ -162,12 +162,12 @@ int main(int argc, char* argv[])
bool should_terminate = false;
std::tie(vm, should_terminate) = wallet_args::main(
argc, argv,
"monero-gen-multisig [(--testnet|--stagenet)] [--filename-base=<filename>] [--scheme=M/N] [--threshold=M] [--participants=N]",
"wownero-gen-multisig [(--testnet|--stagenet)] [--filename-base=<filename>] [--scheme=M/N] [--threshold=M] [--participants=N]",
genms::tr("This program generates a set of multisig wallets - use this simpler scheme only if all the participants trust each other"),
desc_params,
boost::program_options::positional_options_description(),
[](const std::string &s, bool emphasis){ tools::scoped_message_writer(emphasis ? epee::console_color_white : epee::console_color_default, true) << s; },
"monero-gen-multisig.log"
"wownero-gen-multisig.log"
);
if (!vm)
return 1;

@ -45,5 +45,5 @@ add_dependencies(gen_ssl_cert
version)
set_property(TARGET gen_ssl_cert
PROPERTY
OUTPUT_NAME "monero-gen-ssl-cert")
OUTPUT_NAME "wownero-gen-ssl-cert")
install(TARGETS gen_ssl_cert DESTINATION bin)

@ -121,13 +121,13 @@ int main(int argc, char* argv[])
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;
return 0;
}
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;
}

@ -32,97 +32,30 @@
#define MONERO_DEFAULT_LOG_CATEGORY "blockchain.hardforks"
const hardfork_t mainnet_hard_forks[] = {
// version 1 from the start of the blockchain
{ 1, 1, 0, 1341378000 },
// version 2 starts from block 1009827, which is on or around the 20th of March, 2016. Fork time finalised on 2015-09-20. No fork voting occurs for the v2 fork.
{ 2, 1009827, 0, 1442763710 },
// version 3 starts from block 1141317, which is on or around the 24th of September, 2016. Fork time finalised on 2016-03-21.
{ 3, 1141317, 0, 1458558528 },
// version 4 starts from block 1220516, which is on or around the 5th of January, 2017. Fork time finalised on 2016-09-18.
{ 4, 1220516, 0, 1483574400 },
// version 5 starts from block 1288616, which is on or around the 15th of April, 2017. Fork time finalised on 2017-03-14.
{ 5, 1288616, 0, 1489520158 },
// version 6 starts from block 1400000, which is on or around the 16th of September, 2017. Fork time finalised on 2017-08-18.
{ 6, 1400000, 0, 1503046577 },
// version 7 starts from block 1546000, which is on or around the 6th of April, 2018. Fork time finalised on 2018-03-17.
{ 7, 1546000, 0, 1521303150 },
// version 8 starts from block 1685555, which is on or around the 18th of October, 2018. Fork time finalised on 2018-09-02.
{ 8, 1685555, 0, 1535889547 },
// version 9 starts from block 1686275, which is on or around the 19th of October, 2018. Fork time finalised on 2018-09-02.
{ 9, 1686275, 0, 1535889548 },
// version 10 starts from block 1788000, which is on or around the 9th of March, 2019. Fork time finalised on 2019-02-10.
{ 10, 1788000, 0, 1549792439 },
// version 11 starts from block 1788720, which is on or around the 10th of March, 2019. Fork time finalised on 2019-02-15.
{ 11, 1788720, 0, 1550225678 },
// version 12 starts from block 1978433, which is on or around the 30th of November, 2019. Fork time finalised on 2019-10-18.
{ 12, 1978433, 0, 1571419280 },
{ 13, 2210000, 0, 1598180817 },
{ 14, 2210720, 0, 1598180818 },
{ 15, 2688888, 0, 1656629117 },
{ 16, 2689608, 0, 1656629118 },
{ 7, 1, 0, 1519605000 },
{ 8, 6969, 0, 1524214739 },
{ 9, 53666, 0, 1538689773 },
{ 10, 63469, 0, 1541700352 },
{ 11, 81769, 0, 1549238400 },
{ 12, 82069, 0, 1549318761 },
{ 13, 114969, 0, 1559292691 },
{ 14, 115257, 0, 1559292774 },
{ 15, 160777, 0, 1573280497 },
{ 16, 253999, 0, 1600576508 },
{ 17, 254287, 0, 1600576524 },
{ 18, 331170, 0, 1623245591 },
{ 19, 331458, 0, 1624793373 },
{ 20, 514000, 0, 1677222289 },
};
const size_t num_mainnet_hard_forks = sizeof(mainnet_hard_forks) / sizeof(mainnet_hard_forks[0]);
const uint64_t mainnet_hard_fork_version_1_till = 1009826;
// since Wownero starts from v7, added + 6 so that the total number of hard forks = version number
const size_t num_mainnet_hard_forks = sizeof(mainnet_hard_forks) / sizeof(mainnet_hard_forks[0]) + 6;
const uint64_t mainnet_hard_fork_version_1_till = 0;
const hardfork_t testnet_hard_forks[] = {
// version 1 from the start of the blockchain
{ 1, 1, 0, 1341378000 },
// version 2 starts from block 624634, which is on or around the 23rd of November, 2015. Fork time finalised on 2015-11-20. No fork voting occurs for the v2 fork.
{ 2, 624634, 0, 1445355000 },
// versions 3-5 were passed in rapid succession from September 18th, 2016
{ 3, 800500, 0, 1472415034 },
{ 4, 801219, 0, 1472415035 },
{ 5, 802660, 0, 1472415036 + 86400*180 }, // add 5 months on testnet to shut the update warning up since there's a large gap to v6
{ 6, 971400, 0, 1501709789 },
{ 7, 1057027, 0, 1512211236 },
{ 8, 1057058, 0, 1533211200 },
{ 9, 1057778, 0, 1533297600 },
{ 10, 1154318, 0, 1550153694 },
{ 11, 1155038, 0, 1550225678 },
{ 12, 1308737, 0, 1569582000 },
{ 13, 1543939, 0, 1599069376 },
{ 14, 1544659, 0, 1599069377 },
{ 15, 1982800, 0, 1652727000 },
{ 16, 1983520, 0, 1652813400 },
};
const size_t num_testnet_hard_forks = sizeof(testnet_hard_forks) / sizeof(testnet_hard_forks[0]);
const uint64_t testnet_hard_fork_version_1_till = 624633;
const uint64_t testnet_hard_fork_version_1_till = 0;
const hardfork_t stagenet_hard_forks[] = {
// version 1 from the start of the blockchain
{ 1, 1, 0, 1341378000 },
// versions 2-7 in rapid succession from March 13th, 2018
{ 2, 32000, 0, 1521000000 },
{ 3, 33000, 0, 1521120000 },
{ 4, 34000, 0, 1521240000 },
{ 5, 35000, 0, 1521360000 },
{ 6, 36000, 0, 1521480000 },
{ 7, 37000, 0, 1521600000 },
{ 8, 176456, 0, 1537821770 },
{ 9, 177176, 0, 1537821771 },
{ 10, 269000, 0, 1550153694 },
{ 11, 269720, 0, 1550225678 },
{ 12, 454721, 0, 1571419280 },
{ 13, 675405, 0, 1598180817 },
{ 14, 676125, 0, 1598180818 },
{ 15, 1151000, 0, 1656629117 },
{ 16, 1151720, 0, 1656629118 },
};
const size_t num_stagenet_hard_forks = sizeof(stagenet_hard_forks) / sizeof(stagenet_hard_forks[0]);

@ -300,10 +300,7 @@ namespace nodetool
private:
const std::vector<std::string> m_seed_nodes_list =
{ "seeds.moneroseeds.se"
, "seeds.moneroseeds.ae.org"
, "seeds.moneroseeds.ch"
, "seeds.moneroseeds.li"
{
};
bool islimitup=false;

@ -685,32 +685,27 @@ namespace nodetool
std::set<std::string> full_addrs;
if (m_nettype == cryptonote::TESTNET)
{
full_addrs.insert("176.9.0.187:28080");
full_addrs.insert("88.99.173.38:28080");
full_addrs.insert("51.79.173.165:28080");
full_addrs.insert("192.99.8.110:28080");
full_addrs.insert("37.187.74.171:28080");
}
else if (m_nettype == cryptonote::STAGENET)
{
full_addrs.insert("176.9.0.187:38080");
full_addrs.insert("88.99.173.38:38080");
full_addrs.insert("51.79.173.165:38080");
full_addrs.insert("192.99.8.110:38080");
full_addrs.insert("37.187.74.171:38080");
}
else if (m_nettype == cryptonote::FAKECHAIN)
{
}
else
{
full_addrs.insert("176.9.0.187:18080");
full_addrs.insert("88.198.163.90:18080");
full_addrs.insert("66.85.74.134:18080");
full_addrs.insert("88.99.173.38:18080");
full_addrs.insert("51.79.173.165:18080");
full_addrs.insert("192.99.8.110:18080");
full_addrs.insert("37.187.74.171:18080");
full_addrs.insert("158.69.60.225:34567"); // explore.wownero.com
full_addrs.insert("159.65.91.59:34567"); // jw
full_addrs.insert("51.161.131.176:34567"); // node.suchwow.xyz
full_addrs.insert("167.114.196.241:34567"); // wowbux.org
full_addrs.insert("142.93.144.79:34567"); // idontwanttogototoronto.wow.fail
full_addrs.insert("51.75.76.161:34567"); // eu-west-1.wow.xmr.pm
full_addrs.insert("145.239.93.75:34567"); // eu-west-2.wow.xmr.pm
full_addrs.insert("88.198.199.23:34567");
full_addrs.insert("167.114.119.46:34567"); // wownero.stackwallet.com
full_addrs.insert("143.198.195.132:34567"); // singapore.muchwow.lol
full_addrs.insert("134.122.53.193:34567"); // amsterdam.muchwow.lol
full_addrs.insert("204.48.28.218:34567"); // nyc.muchwow.lol
}
return full_addrs;
}
@ -841,12 +836,9 @@ namespace nodetool
if (m_nettype == cryptonote::MAINNET)
{
return {
"xwvz3ekocr3dkyxfkmgm2hvbpzx2ysqmaxgter7znnqrhoicygkfswid.onion:18083",
"4pixvbejrvihnkxmduo2agsnmc3rrulrqc7s3cbwwrep6h6hrzsibeqd.onion:18083",
"zbjkbsxc5munw3qusl7j2hpcmikhqocdf4pqhnhtpzw5nt5jrmofptid.onion:18083",
"qz43zul2x56jexzoqgkx2trzwcfnr6l3hbtfcfx54g4r3eahy3bssjyd.onion:18083",
"plowsof3t5hogddwabaeiyrno25efmzfxyro2vligremt7sxpsclfaid.onion:18083",
"plowsoffjexmxalw73tkjmf422gq6575fc7vicuu4javzn2ynnte6tyd.onion:18083",
"77uase4p6y6jsjdf6z2kdgpxgh7nkvywagvhurzphbm7vrkyj2d2gdid.onion:34566",
"v2admi6gbeprxnk6i2oscizhgy4v5ixu6iezkhj5udiwbfjjs2w7dnid.onion:34566",
"ttc6kxud3fikyaypn5voknyyvqje7j3wnoevsb7rfjerolynnisurkqd.onion:34566",
};
}
return {};
@ -854,10 +846,9 @@ namespace nodetool
if (m_nettype == cryptonote::MAINNET)
{
return {
"s3l6ke4ed3df466khuebb4poienoingwof7oxtbo6j4n56sghe3a.b32.i2p:18080",
"sel36x6fibfzujwvt4hf5gxolz6kd3jpvbjqg6o3ud2xtionyl2q.b32.i2p:18080",
"uqj3aphckqtjsitz7kxx5flqpwjlq5ppr3chazfued7xucv3nheq.b32.i2p:18080",
"vdmnehdjkpkg57nthgnjfuaqgku673r5bpbqg56ix6fyqoywgqrq.b32.i2p:18080",
"lrq65qrhpbt5voom2ncvowpes6kvobodkldhpuwhxlsrpugmgmlq.b32.i2p:34565",
"72tbpgeczdtx2q2enbyaqcot7mghbnjenjkmdpyylrssqehr746a.b32.i2p:34565",
"rkel2qy7xv3cc5bnxfrzwgh3jvd4woagd4vlhr3qsdxy6cfkimnq.b32.i2p:34565",
};
}
return {};
@ -2013,13 +2004,6 @@ namespace nodetool
return true;
static const std::vector<std::string> dns_urls = {
"blocklist.moneropulse.se"
, "blocklist.moneropulse.org"
, "blocklist.moneropulse.net"
, "blocklist.moneropulse.no"
, "blocklist.moneropulse.fr"
, "blocklist.moneropulse.de"
, "blocklist.moneropulse.ch"
};
std::vector<std::string> records;
@ -2081,7 +2065,7 @@ namespace nodetool
}
else
{
const el::Level level = el::Level::Warning;
const el::Level level = el::Level::Debug;
MCLOG_RED(level, "global", "No incoming connections - check firewalls/routers allow port " << get_this_peer_port());
}
}

@ -32,6 +32,7 @@ set(ringct_basic_sources
rctCryptoOps.c
multiexp.cc
bulletproofs.cc
bulletproofs2.cc
bulletproofs_plus.cc)
monero_find_all_headers(ringct_basic_private_headers "${CMAKE_CURRENT_SOURCE_DIR}")

@ -70,12 +70,13 @@ static rct::key inner_product(const rct::keyV &a, const rct::keyV &b);
static constexpr size_t maxN = 64;
static constexpr size_t maxM = BULLETPROOF_MAX_OUTPUTS;
static rct::key Hi[maxN*maxM], Gi[maxN*maxM];
static ge_p3 Hi_p3[maxN*maxM], Gi_p3[maxN*maxM];
static std::shared_ptr<straus_cached_data> straus_HiGi_cache;
static std::shared_ptr<pippenger_cached_data> pippenger_HiGi_cache;
static const constexpr rct::key TWO = { {0x02, 0x00, 0x00,0x00 , 0x00, 0x00, 0x00,0x00 , 0x00, 0x00, 0x00,0x00 , 0x00, 0x00, 0x00,0x00 , 0x00, 0x00, 0x00,0x00 , 0x00, 0x00, 0x00,0x00 , 0x00, 0x00, 0x00,0x00 , 0x00, 0x00, 0x00,0x00 } };
static const constexpr rct::key MINUS_ONE = { { 0xec, 0xd3, 0xf5, 0x5c, 0x1a, 0x63, 0x12, 0x58, 0xd6, 0x9c, 0xf7, 0xa2, 0xde, 0xf9, 0xde, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10 } };
static const constexpr rct::key MINUS_INV_EIGHT = { { 0x74, 0xa4, 0x19, 0x7a, 0xf0, 0x7d, 0x0b, 0xf7, 0x05, 0xc2, 0xda, 0x25, 0x2b, 0x5c, 0x0b, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a } };
static const rct::key TWO = { {0x02, 0x00, 0x00,0x00 , 0x00, 0x00, 0x00,0x00 , 0x00, 0x00, 0x00,0x00 , 0x00, 0x00, 0x00,0x00 , 0x00, 0x00, 0x00,0x00 , 0x00, 0x00, 0x00,0x00 , 0x00, 0x00, 0x00,0x00 , 0x00, 0x00, 0x00,0x00 } };
static const rct::key MINUS_ONE = { { 0xec, 0xd3, 0xf5, 0x5c, 0x1a, 0x63, 0x12, 0x58, 0xd6, 0x9c, 0xf7, 0xa2, 0xde, 0xf9, 0xde, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10 } };
static const rct::key MINUS_INV_EIGHT = { { 0x74, 0xa4, 0x19, 0x7a, 0xf0, 0x7d, 0x0b, 0xf7, 0x05, 0xc2, 0xda, 0x25, 0x2b, 0x5c, 0x0b, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a } };
static const rct::keyV oneN = vector_dup(rct::identity(), maxN);
static const rct::keyV twoN = vector_powers(TWO, maxN);
static const rct::key ip12 = inner_product(oneN, twoN);
@ -99,7 +100,8 @@ static inline bool is_reduced(const rct::key &scalar)
static rct::key get_exponent(const rct::key &base, size_t idx)
{
std::string hashed = std::string((const char*)base.bytes, sizeof(base)) + config::HASH_KEY_BULLETPROOF_EXPONENT + tools::get_varint_data(idx);
static const std::string domain_separator(config::HASH_KEY_BULLETPROOF_EXPONENT);
std::string hashed = std::string((const char*)base.bytes, sizeof(base)) + domain_separator + tools::get_varint_data(idx);
rct::key e;
ge_p3 e_p3;
rct::hash_to_p3(e_p3, rct::hash2rct(crypto::cn_fast_hash(hashed.data(), hashed.size())));
@ -119,10 +121,10 @@ static void init_exponents()
data.reserve(maxN*maxM*2);
for (size_t i = 0; i < maxN*maxM; ++i)
{
const rct::key Hi = get_exponent(rct::H, i * 2);
CHECK_AND_ASSERT_THROW_MES(ge_frombytes_vartime(&Hi_p3[i], Hi.bytes) == 0, "ge_frombytes_vartime failed");
const rct::key Gi = get_exponent(rct::H, i * 2 + 1);
CHECK_AND_ASSERT_THROW_MES(ge_frombytes_vartime(&Gi_p3[i], Gi.bytes) == 0, "ge_frombytes_vartime failed");
Hi[i] = get_exponent(rct::H, i * 2);
CHECK_AND_ASSERT_THROW_MES(ge_frombytes_vartime(&Hi_p3[i], Hi[i].bytes) == 0, "ge_frombytes_vartime failed");
Gi[i] = get_exponent(rct::H, i * 2 + 1);
CHECK_AND_ASSERT_THROW_MES(ge_frombytes_vartime(&Gi_p3[i], Gi[i].bytes) == 0, "ge_frombytes_vartime failed");
data.push_back({rct::zero(), Gi_p3[i]});
data.push_back({rct::zero(), Hi_p3[i]});
@ -131,10 +133,11 @@ static void init_exponents()
straus_HiGi_cache = straus_init_cache(data, STRAUS_SIZE_LIMIT);
pippenger_HiGi_cache = pippenger_init_cache(data, 0, PIPPENGER_SIZE_LIMIT);
MINFO("Hi/Gi cache size: " << (sizeof(Hi)+sizeof(Gi))/1024 << " kB");
MINFO("Hi_p3/Gi_p3 cache size: " << (sizeof(Hi_p3)+sizeof(Gi_p3))/1024 << " kB");
MINFO("Straus cache size: " << straus_get_cache_size(straus_HiGi_cache)/1024 << " kB");
MINFO("Pippenger cache size: " << pippenger_get_cache_size(pippenger_HiGi_cache)/1024 << " kB");
size_t cache_size = straus_get_cache_size(straus_HiGi_cache) + pippenger_get_cache_size(pippenger_HiGi_cache);
size_t cache_size = (sizeof(Hi)+sizeof(Hi_p3))*2 + straus_get_cache_size(straus_HiGi_cache) + pippenger_get_cache_size(pippenger_HiGi_cache);
MINFO("Total cache size: " << cache_size/1024 << "kB");
init_done = true;
}
@ -892,8 +895,7 @@ bool bulletproof_VERIFY(const std::vector<const Bulletproof*> &proofs)
multiexp_data.resize(2 * maxMN);
PERF_TIMER_START_BP(VERIFY_line_24_25_invert);
const std::vector<rct::key> inverses = invert(std::move(to_invert));
to_invert.clear();
const std::vector<rct::key> inverses = invert(to_invert);
PERF_TIMER_STOP_BP(VERIFY_line_24_25_invert);
// setup weighted aggregates

@ -42,9 +42,16 @@ Bulletproof bulletproof_PROVE(const rct::key &v, const rct::key &gamma);
Bulletproof bulletproof_PROVE(uint64_t v, const rct::key &gamma);
Bulletproof bulletproof_PROVE(const rct::keyV &v, const rct::keyV &gamma);
Bulletproof bulletproof_PROVE(const std::vector<uint64_t> &v, const rct::keyV &gamma);
Bulletproof bulletproof_PROVE_old(const rct::key &v, const rct::key &gamma);
Bulletproof bulletproof_PROVE_old(uint64_t v, const rct::key &gamma);
Bulletproof bulletproof_PROVE_old(const rct::keyV &v, const rct::keyV &gamma);
Bulletproof bulletproof_PROVE_old(const std::vector<uint64_t> &v, const rct::keyV &gamma);
bool bulletproof_VERIFY(const Bulletproof &proof);
bool bulletproof_VERIFY(const std::vector<const Bulletproof*> &proofs);
bool bulletproof_VERIFY(const std::vector<Bulletproof> &proofs);
bool bulletproof_VERIFY_old(const Bulletproof &proof);
bool bulletproof_VERIFY_old(const std::vector<const Bulletproof*> &proofs);
bool bulletproof_VERIFY_old(const std::vector<Bulletproof> &proofs);
}

File diff suppressed because it is too large Load Diff

@ -133,6 +133,24 @@ namespace rct {
return proof;
}
Bulletproof proveRangeBulletproof_old(key &C, key &mask, uint64_t amount)
{
mask = rct::skGen();
Bulletproof proof = bulletproof_PROVE_old(amount, mask);
CHECK_AND_ASSERT_THROW_MES(proof.V.size() == 1, "V has not exactly one element");
C = proof.V[0];
return proof;
}
Bulletproof proveRangeBulletproof_old(keyV &C, keyV &masks, const std::vector<uint64_t> &amounts)
{
masks = rct::skvGen(amounts.size());
Bulletproof proof = bulletproof_PROVE_old(amounts, masks);
CHECK_AND_ASSERT_THROW_MES(proof.V.size() == amounts.size(), "V does not have the expected size");
C = proof.V;
return proof;
}
bool verBulletproof(const Bulletproof &proof)
{
try { return bulletproof_VERIFY(proof); }
@ -147,6 +165,20 @@ namespace rct {
catch (...) { return false; }
}
bool verBulletproof_old(const Bulletproof &proof)
{
try { return bulletproof_VERIFY_old(proof); }
// we can get deep throws from ge_frombytes_vartime if input isn't valid
catch (...) { return false; }
}
bool verBulletproof_old(const std::vector<const Bulletproof*> &proofs)
{
try { return bulletproof_VERIFY_old(proofs); }
// we can get deep throws from ge_frombytes_vartime if input isn't valid
catch (...) { return false; }
}
BulletproofPlus proveRangeBulletproofPlus(keyV &C, keyV &masks, const std::vector<uint64_t> &amounts, epee::span<const key> sk, hw::device &hwdev)
{
CHECK_AND_ASSERT_THROW_MES(amounts.size() == sk.size(), "Invalid amounts/sk sizes");
@ -617,7 +649,7 @@ namespace rct {
hashes.push_back(hash2rct(h));
keyV kv;
if (rv.type == RCTTypeBulletproof || rv.type == RCTTypeBulletproof2 || rv.type == RCTTypeCLSAG)
if (rv.type == RCTTypeBulletproof || rv.type == RCTTypeBulletproof2 || rv.type == RCTTypeSimpleBulletproof || rv.type == RCTTypeFullBulletproof || rv.type == RCTTypeCLSAG)
{
kv.reserve((6*2+9) * rv.p.bulletproofs.size());
for (const auto &p: rv.p.bulletproofs)
@ -1045,6 +1077,7 @@ namespace rct {
// Note: For txn fees, the last index in the amounts vector should contain that
// Thus the amounts vector will be "one" longer than the destinations vectort
rctSig genRct(const key &message, const ctkeyV & inSk, const keyV & destinations, const vector<xmr_amount> & amounts, const ctkeyM &mixRing, const keyV &amount_keys, unsigned int index, ctkeyV &outSk, const RCTConfig &rct_config, hw::device &hwdev) {
const bool bulletproof = rct_config.range_proof_type != RangeProofBorromean;
CHECK_AND_ASSERT_THROW_MES(amounts.size() == destinations.size() || amounts.size() == destinations.size() + 1, "Different number of amounts/destinations");
CHECK_AND_ASSERT_THROW_MES(amount_keys.size() == destinations.size(), "Different number of amount_keys/destinations");
CHECK_AND_ASSERT_THROW_MES(index < mixRing.size(), "Bad index into mixRing");
@ -1054,10 +1087,11 @@ namespace rct {
CHECK_AND_ASSERT_THROW_MES(inSk.size() < 2, "genRct is not suitable for 2+ rings");
rctSig rv;
rv.type = RCTTypeFull;
rv.type = bulletproof ? RCTTypeFullBulletproof : RCTTypeFull;
rv.message = message;
rv.outPk.resize(destinations.size());
rv.p.rangeSigs.resize(destinations.size());
if (!bulletproof)
rv.p.rangeSigs.resize(destinations.size());
rv.ecdhInfo.resize(destinations.size());
size_t i = 0;
@ -1067,10 +1101,45 @@ namespace rct {
//add destination to sig
rv.outPk[i].dest = copy(destinations[i]);
//compute range proof
rv.p.rangeSigs[i] = proveRange(rv.outPk[i].mask, outSk[i].mask, amounts[i]);
if (!bulletproof)
{
rv.p.rangeSigs[i] = proveRange(rv.outPk[i].mask, outSk[i].mask, amounts[i]);
#ifdef DBG
CHECK_AND_ASSERT_THROW_MES(verRange(rv.outPk[i].mask, rv.p.rangeSigs[i]), "verRange failed on newly created proof");
#endif
}
}
rv.p.bulletproofs.clear();
if (bulletproof)
{
std::vector<uint64_t> proof_amounts;
size_t amounts_proved = 0;
while (amounts_proved < amounts.size())
{
size_t batch_size = 1;
if (rct_config.range_proof_type == RangeProofMultiOutputBulletproof)
while (batch_size * 2 + amounts_proved <= amounts.size())
batch_size *= 2;
rct::keyV C, masks;
std::vector<uint64_t> batch_amounts(batch_size);
for (i = 0; i < batch_size; ++i)
batch_amounts[i] = amounts[i + amounts_proved];
rv.p.bulletproofs.push_back(proveRangeBulletproof_old(C, masks, batch_amounts));
#ifdef DBG
CHECK_AND_ASSERT_THROW_MES(verBulletproof_old(rv.p.bulletproofs.back()), "verBulletproof failed on newly created proof");
#endif
for (i = 0; i < batch_size; ++i)
{
rv.outPk[i + amounts_proved].mask = C[i];
outSk[i + amounts_proved].mask = masks[i];
}
amounts_proved += batch_size;
}
}
for (i = 0; i < outSk.size(); ++i)
{
//mask amount and mask
rv.ecdhInfo[i].mask = copy(outSk[i].mask);
rv.ecdhInfo[i].amount = d2h(amounts[i]);
@ -1196,7 +1265,10 @@ namespace rct {
}
for (i = 0; i < outamounts.size(); ++i)
{
rv.outPk[i].mask = rct::scalarmult8(C[i]);
if (plus)
rv.outPk[i].mask = C[i];
else
rv.outPk[i].mask = rct::scalarmult8(C[i]);
outSk[i].mask = masks[i];
}
}
@ -1234,7 +1306,10 @@ namespace rct {
}
for (i = 0; i < batch_size; ++i)
{
rv.outPk[i + amounts_proved].mask = rct::scalarmult8(C[i]);
if (plus)
rv.outPk[i + amounts_proved].mask = C[i];
else
rv.outPk[i + amounts_proved].mask = rct::scalarmult8(C[i]);
outSk[i + amounts_proved].mask = masks[i];
}
amounts_proved += batch_size;
@ -1306,6 +1381,98 @@ namespace rct {
return genRctSimple(message, inSk, destinations, inamounts, outamounts, txnFee, mixRing, amount_keys, index, outSk, rct_config, hwdev);
}
//RCT simple
//for post-rct only
rctSig genRctSimple_old(const key &message, const ctkeyV & inSk, const keyV & destinations, const vector<xmr_amount> &inamounts, const vector<xmr_amount> &outamounts, xmr_amount txnFee, const ctkeyM & mixRing, const keyV &amount_keys, const std::vector<unsigned int> & index, ctkeyV &outSk, const RCTConfig &rct_config, hw::device &hwdev) {
const bool bulletproof = rct_config.range_proof_type != RangeProofBorromean;
CHECK_AND_ASSERT_THROW_MES(inamounts.size() > 0, "Empty inamounts");
CHECK_AND_ASSERT_THROW_MES(inamounts.size() == inSk.size(), "Different number of inamounts/inSk");
CHECK_AND_ASSERT_THROW_MES(outamounts.size() == destinations.size(), "Different number of amounts/destinations");
CHECK_AND_ASSERT_THROW_MES(amount_keys.size() == destinations.size(), "Different number of amount_keys/destinations");
CHECK_AND_ASSERT_THROW_MES(index.size() == inSk.size(), "Different number of index/inSk");
CHECK_AND_ASSERT_THROW_MES(mixRing.size() == inSk.size(), "Different number of mixRing/inSk");
for (size_t n = 0; n < mixRing.size(); ++n) {
CHECK_AND_ASSERT_THROW_MES(index[n] < mixRing[n].size(), "Bad index into mixRing");
}
rctSig rv;
rv.type = bulletproof ? RCTTypeSimpleBulletproof : RCTTypeSimple;
rv.message = message;
rv.outPk.resize(destinations.size());
if (bulletproof)
rv.p.bulletproofs.resize(destinations.size());
else
rv.p.rangeSigs.resize(destinations.size());
rv.ecdhInfo.resize(destinations.size());
size_t i;
keyV masks(destinations.size()); //sk mask..
outSk.resize(destinations.size());
key sumout = zero();
for (i = 0; i < destinations.size(); i++) {
//add destination to sig
rv.outPk[i].dest = copy(destinations[i]);
//compute range proof
if (bulletproof)
rv.p.bulletproofs[i] = proveRangeBulletproof_old(rv.outPk[i].mask, outSk[i].mask, outamounts[i]);
else
rv.p.rangeSigs[i] = proveRange(rv.outPk[i].mask, outSk[i].mask, outamounts[i]);
#ifdef DBG
if (bulletproof)
CHECK_AND_ASSERT_THROW_MES(verBulletproof_old(rv.p.bulletproofs[i]), "verBulletproof failed on newly created proof");
else
CHECK_AND_ASSERT_THROW_MES(verRange(rv.outPk[i].mask, rv.p.rangeSigs[i]), "verRange failed on newly created proof");
#endif
sc_add(sumout.bytes, outSk[i].mask.bytes, sumout.bytes);
//mask amount and mask
rv.ecdhInfo[i].mask = copy(outSk[i].mask);
rv.ecdhInfo[i].amount = d2h(outamounts[i]);
hwdev.ecdhEncode(rv.ecdhInfo[i], amount_keys[i], rv.type == RCTTypeSimpleBulletproof);
}
//set txn fee
rv.txnFee = txnFee;
// TODO: unused ??
// key txnFeeKey = scalarmultH(d2h(rv.txnFee));
rv.mixRing = mixRing;
keyV &pseudoOuts = bulletproof ? rv.p.pseudoOuts : rv.pseudoOuts;
pseudoOuts.resize(inamounts.size());
rv.p.MGs.resize(inamounts.size());
key sumpouts = zero(); //sum pseudoOut masks
keyV a(inamounts.size());
for (i = 0 ; i < inamounts.size() - 1; i++) {
skGen(a[i]);
sc_add(sumpouts.bytes, a[i].bytes, sumpouts.bytes);
genC(pseudoOuts[i], a[i], inamounts[i]);
}
rv.mixRing = mixRing;
sc_sub(a[i].bytes, sumout.bytes, sumpouts.bytes);
genC(pseudoOuts[i], a[i], inamounts[i]);
DP(pseudoOuts[i]);
key full_message = get_pre_mlsag_hash(rv,hwdev);
for (i = 0 ; i < inamounts.size(); i++) {
rv.p.MGs[i] = proveRctMGSimple(full_message, rv.mixRing[i], inSk[i], a[i], pseudoOuts[i], index[i], hwdev);
}
return rv;
}
rctSig genRctSimple_old(const key &message, const ctkeyV & inSk, const ctkeyV & inPk, const keyV & destinations, const vector<xmr_amount> &inamounts, const vector<xmr_amount> &outamounts, const keyV &amount_keys, xmr_amount txnFee, unsigned int mixin, const RCTConfig &rct_config, hw::device &hwdev) {
std::vector<unsigned int> index;
index.resize(inPk.size());
ctkeyM mixRing;
ctkeyV outSk;
mixRing.resize(inPk.size());
for (size_t i = 0; i < inPk.size(); ++i) {
mixRing[i].resize(mixin+1);
index[i] = populateFromBlockchainSimple(mixRing[i], inPk[i], mixin);
}
return genRctSimple_old(message, inSk, destinations, inamounts, outamounts, txnFee, mixRing, amount_keys, index, outSk, rct_config, hwdev);
}
//RingCT protocol
//genRct:
// creates an rctSig with all data necessary to verify the rangeProofs and that the signer owns one of the
@ -1318,10 +1485,13 @@ namespace rct {
// must know the destination private key to find the correct amount, else will return a random number
bool verRct(const rctSig & rv, bool semantics) {
PERF_TIMER(verRct);
CHECK_AND_ASSERT_MES(rv.type == RCTTypeFull, false, "verRct called on non-full rctSig");
const bool bulletproof = is_rct_bulletproof(rv.type);
CHECK_AND_ASSERT_MES(rv.type == RCTTypeFull || rv.type == RCTTypeFullBulletproof, false, "verRct called on non-full rctSig");
if (semantics)
{
if (rv.type == RCTTypeBulletproof)
CHECK_AND_ASSERT_MES(rv.outPk.size() == rv.p.rangeSigs.size(), false, "Mismatched sizes of outPk and rv.p.rangeSigs");
else
CHECK_AND_ASSERT_MES(rv.outPk.size() == rv.ecdhInfo.size(), false, "Mismatched sizes of outPk and rv.ecdhInfo");
CHECK_AND_ASSERT_MES(rv.p.MGs.size() == 1, false, "full rctSig has not one MG");
}
@ -1336,10 +1506,23 @@ namespace rct {
if (semantics) {
tools::threadpool& tpool = tools::threadpool::getInstanceForCompute();
tools::threadpool::waiter waiter(tpool);
std::deque<bool> results(rv.outPk.size(), false);
std::deque<bool> results(bulletproof ? rv.p.bulletproofs.size() : rv.outPk.size(), false);
DP("range proofs verified?");
for (size_t i = 0; i < rv.outPk.size(); i++)
tpool.submit(&waiter, [&, i] { results[i] = verRange(rv.outPk[i].mask, rv.p.rangeSigs[i]); });
if (rct::is_rct_new_bulletproof(rv.type))
{
for (size_t i = 0; i < rv.p.bulletproofs.size(); i++)
tpool.submit(&waiter, [&, i] { results[i] = verBulletproof(rv.p.bulletproofs[i]); });
}
else if (bulletproof)
{
for (size_t i = 0; i < rv.p.bulletproofs.size(); i++)
tpool.submit(&waiter, [&, i] { results[i] = verBulletproof_old(rv.p.bulletproofs[i]); });
}
else
{
for (size_t i = 0; i < rv.outPk.size(); i++)
tpool.submit(&waiter, [&, i] { results[i] = verRange(rv.outPk[i].mask, rv.p.rangeSigs[i]); });
}
if (!waiter.wait())
return false;
@ -1440,7 +1623,10 @@ namespace rct {
rct::keyV masks(rv.outPk.size());
for (size_t i = 0; i < rv.outPk.size(); i++) {
masks[i] = rv.outPk[i].mask;
if (bulletproof_plus)
masks[i] = rct::scalarmult8(rv.outPk[i].mask);
else
masks[i] = rv.outPk[i].mask;
}
key sumOutpks = addKeys(masks);
DP(sumOutpks);
@ -1626,7 +1812,7 @@ namespace rct {
// uses the attached ecdh info to find the amounts represented by each output commitment
// must know the destination private key to find the correct amount, else will return a random number
xmr_amount decodeRct(const rctSig & rv, const key & sk, unsigned int i, key & mask, hw::device &hwdev) {
CHECK_AND_ASSERT_MES(rv.type == RCTTypeFull, false, "decodeRct called on non-full rctSig");
CHECK_AND_ASSERT_MES(rv.type == RCTTypeFull || rv.type == RCTTypeFullBulletproof, false, "decodeRct called on non-full rctSig");
CHECK_AND_ASSERT_THROW_MES(i < rv.ecdhInfo.size(), "Bad index");
CHECK_AND_ASSERT_THROW_MES(rv.outPk.size() == rv.ecdhInfo.size(), "Mismatched sizes of rv.outPk and rv.ecdhInfo");
@ -1636,6 +1822,8 @@ namespace rct {
mask = ecdh_info.mask;
key amount = ecdh_info.amount;
key C = rv.outPk[i].mask;
if (is_rct_bulletproof_plus(rv.type))
C = scalarmult8(C);
DP("C");
DP(C);
key Ctmp;
@ -1667,6 +1855,8 @@ namespace rct {
mask = ecdh_info.mask;
key amount = ecdh_info.amount;
key C = rv.outPk[i].mask;
if (is_rct_bulletproof_plus(rv.type))
C = scalarmult8(C);
DP("C");
DP(C);
key Ctmp;

@ -127,6 +127,9 @@ namespace rct {
rctSig genRct(const key &message, const ctkeyV & inSk, const ctkeyV & inPk, const keyV & destinations, const std::vector<xmr_amount> & amounts, const keyV &amount_keys, const int mixin, const RCTConfig &rct_config, hw::device &hwdev);
rctSig genRctSimple(const key & message, const ctkeyV & inSk, const ctkeyV & inPk, const keyV & destinations, const std::vector<xmr_amount> & inamounts, const std::vector<xmr_amount> & outamounts, const keyV &amount_keys, xmr_amount txnFee, unsigned int mixin, const RCTConfig &rct_config, hw::device &hwdev);
rctSig genRctSimple(const key & message, const ctkeyV & inSk, const keyV & destinations, const std::vector<xmr_amount> & inamounts, const std::vector<xmr_amount> & outamounts, xmr_amount txnFee, const ctkeyM & mixRing, const keyV &amount_keys, const std::vector<unsigned int> & index, ctkeyV &outSk, const RCTConfig &rct_config, hw::device &hwdev);
rctSig genRctSimple_old(const key & message, const ctkeyV & inSk, const ctkeyV & inPk, const keyV & destinations, const std::vector<xmr_amount> & inamounts, const std::vector<xmr_amount> & outamounts, const keyV &amount_keys, xmr_amount txnFee, unsigned int mixin, const RCTConfig &rct_config, hw::device &hwdev);
rctSig genRctSimple_old(const key & message, const ctkeyV & inSk, const keyV & destinations, const std::vector<xmr_amount> & inamounts, const std::vector<xmr_amount> & outamounts, xmr_amount txnFee, const ctkeyM & mixRing, const keyV &amount_keys, const std::vector<unsigned int> & index, ctkeyV &outSk, const RCTConfig &rct_config, hw::device &hwdev);
bool verRct(const rctSig & rv, bool semantics);
static inline bool verRct(const rctSig & rv) { return verRct(rv, true) && verRct(rv, false); }
bool verRctSemanticsSimple(const rctSig & rv);

@ -193,6 +193,7 @@ namespace rct {
switch (type)
{
case RCTTypeSimple:
case RCTTypeSimpleBulletproof:
case RCTTypeBulletproof:
case RCTTypeBulletproof2:
case RCTTypeCLSAG:
@ -207,6 +208,8 @@ namespace rct {
{
switch (type)
{
case RCTTypeSimpleBulletproof:
case RCTTypeFullBulletproof:
case RCTTypeBulletproof:
case RCTTypeBulletproof2:
case RCTTypeCLSAG:
@ -216,6 +219,23 @@ namespace rct {
}
}
bool is_rct_old_bulletproof(int type)
{
switch (type)
{
case RCTTypeSimpleBulletproof:
case RCTTypeFullBulletproof:
return true;
default:
return false;
}
}
bool is_rct_new_bulletproof(int type)
{
return is_rct_bulletproof(type) && !is_rct_old_bulletproof(type);
}
bool is_rct_bulletproof_plus(int type)
{
switch (type)
@ -238,6 +258,26 @@ namespace rct {
return false;
}
}
size_t n_bulletproof_v1_amounts(const Bulletproof &proof)
{
CHECK_AND_ASSERT_MES(proof.L.size() >= 6, 0, "Invalid bulletproof L size");
CHECK_AND_ASSERT_MES(proof.L.size() <= 31, 0, "Insane bulletproof L size");
return 1 << (proof.L.size() - 6);
}
size_t n_bulletproof_v1_amounts(const std::vector<Bulletproof> &proofs)
{
size_t n = 0;
for (const Bulletproof &proof: proofs)
{
size_t n2 = n_bulletproof_v1_amounts(proof);
CHECK_AND_ASSERT_MES(n2 < std::numeric_limits<uint32_t>::max() - n, 0, "Invalid number of bulletproofs");
if (n2 == 0)
return 0;
n += n2;
}
return n;
}
bool is_rct_clsag(int type)
{
@ -251,22 +291,19 @@ namespace rct {
}
}
static size_t n_bulletproof_amounts_base(const size_t L_size, const size_t R_size, const size_t V_size, const size_t max_outputs)
size_t n_bulletproof_amounts(const Bulletproof &proof)
{
CHECK_AND_ASSERT_MES(L_size >= 6, 0, "Invalid bulletproof L size");
CHECK_AND_ASSERT_MES(L_size == R_size, 0, "Mismatched bulletproof L/R size");
CHECK_AND_ASSERT_MES(proof.L.size() >= 6, 0, "Invalid bulletproof L size");
CHECK_AND_ASSERT_MES(proof.L.size() == proof.R.size(), 0, "Mismatched bulletproof L/R size");
static const size_t extra_bits = 4;
CHECK_AND_ASSERT_MES((1 << extra_bits) == max_outputs, 0, "log2(max_outputs) is out of date");
CHECK_AND_ASSERT_MES(L_size <= 6 + extra_bits, 0, "Invalid bulletproof L size");
CHECK_AND_ASSERT_MES(V_size <= (1u<<(L_size-6)), 0, "Invalid bulletproof V/L");
CHECK_AND_ASSERT_MES(V_size * 2 > (1u<<(L_size-6)), 0, "Invalid bulletproof V/L");
CHECK_AND_ASSERT_MES(V_size > 0, 0, "Empty bulletproof");
return V_size;
static_assert((1 << extra_bits) == BULLETPROOF_MAX_OUTPUTS, "log2(BULLETPROOF_MAX_OUTPUTS) is out of date");
CHECK_AND_ASSERT_MES(proof.L.size() <= 6 + extra_bits, 0, "Invalid bulletproof L size");
CHECK_AND_ASSERT_MES(proof.V.size() <= (1u<<(proof.L.size()-6)), 0, "Invalid bulletproof V/L");
CHECK_AND_ASSERT_MES(proof.V.size() * 2 > (1u<<(proof.L.size()-6)), 0, "Invalid bulletproof V/L");
CHECK_AND_ASSERT_MES(proof.V.size() > 0, 0, "Empty bulletproof");
return proof.V.size();
}
size_t n_bulletproof_amounts(const Bulletproof &proof) { return n_bulletproof_amounts_base(proof.L.size(), proof.R.size(), proof.V.size(), BULLETPROOF_MAX_OUTPUTS); }
size_t n_bulletproof_plus_amounts(const BulletproofPlus &proof) { return n_bulletproof_amounts_base(proof.L.size(), proof.R.size(), proof.V.size(), BULLETPROOF_PLUS_MAX_OUTPUTS); }
size_t n_bulletproof_amounts(const std::vector<Bulletproof> &proofs)
{
size_t n = 0;
@ -281,12 +318,22 @@ namespace rct {
return n;
}
size_t n_bulletproof_plus_amounts(const std::vector<BulletproofPlus> &proofs)
size_t n_bulletproof_max_amounts(const Bulletproof &proof)
{
CHECK_AND_ASSERT_MES(proof.L.size() >= 6, 0, "Invalid bulletproof L size");
CHECK_AND_ASSERT_MES(proof.L.size() == proof.R.size(), 0, "Mismatched bulletproof L/R size");
static const size_t extra_bits = 4;
static_assert((1 << extra_bits) == BULLETPROOF_MAX_OUTPUTS, "log2(BULLETPROOF_MAX_OUTPUTS) is out of date");
CHECK_AND_ASSERT_MES(proof.L.size() <= 6 + extra_bits, 0, "Invalid bulletproof L size");
return 1 << (proof.L.size() - 6);
}
size_t n_bulletproof_max_amounts(const std::vector<Bulletproof> &proofs)
{
size_t n = 0;
for (const BulletproofPlus &proof: proofs)
for (const Bulletproof &proof: proofs)
{
size_t n2 = n_bulletproof_plus_amounts(proof);
size_t n2 = n_bulletproof_max_amounts(proof);
CHECK_AND_ASSERT_MES(n2 < std::numeric_limits<uint32_t>::max() - n, 0, "Invalid number of bulletproofs");
if (n2 == 0)
return 0;
@ -295,24 +342,25 @@ namespace rct {
return n;
}
static size_t n_bulletproof_max_amounts_base(size_t L_size, size_t R_size, size_t max_outputs)
size_t n_bulletproof_plus_amounts(const BulletproofPlus &proof)
{
CHECK_AND_ASSERT_MES(L_size >= 6, 0, "Invalid bulletproof L size");
CHECK_AND_ASSERT_MES(L_size == R_size, 0, "Mismatched bulletproof L/R size");
CHECK_AND_ASSERT_MES(proof.L.size() >= 6, 0, "Invalid bulletproof L size");
CHECK_AND_ASSERT_MES(proof.L.size() == proof.R.size(), 0, "Mismatched bulletproof L/R size");
static const size_t extra_bits = 4;
CHECK_AND_ASSERT_MES((1 << extra_bits) == max_outputs, 0, "log2(max_outputs) is out of date");
CHECK_AND_ASSERT_MES(L_size <= 6 + extra_bits, 0, "Invalid bulletproof L size");
return 1 << (L_size - 6);
static_assert((1 << extra_bits) == BULLETPROOF_PLUS_MAX_OUTPUTS, "log2(BULLETPROOF_PLUS_MAX_OUTPUTS) is out of date");
CHECK_AND_ASSERT_MES(proof.L.size() <= 6 + extra_bits, 0, "Invalid bulletproof L size");
CHECK_AND_ASSERT_MES(proof.V.size() <= (1u<<(proof.L.size()-6)), 0, "Invalid bulletproof V/L");
CHECK_AND_ASSERT_MES(proof.V.size() * 2 > (1u<<(proof.L.size()-6)), 0, "Invalid bulletproof V/L");
CHECK_AND_ASSERT_MES(proof.V.size() > 0, 0, "Empty bulletproof");
return proof.V.size();
}
size_t n_bulletproof_max_amounts(const Bulletproof &proof) { return n_bulletproof_max_amounts_base(proof.L.size(), proof.R.size(), BULLETPROOF_MAX_OUTPUTS); }
size_t n_bulletproof_plus_max_amounts(const BulletproofPlus &proof) { return n_bulletproof_max_amounts_base(proof.L.size(), proof.R.size(), BULLETPROOF_PLUS_MAX_OUTPUTS); }
size_t n_bulletproof_max_amounts(const std::vector<Bulletproof> &proofs)
size_t n_bulletproof_plus_amounts(const std::vector<BulletproofPlus> &proofs)
{
size_t n = 0;
for (const Bulletproof &proof: proofs)
for (const BulletproofPlus &proof: proofs)
{
size_t n2 = n_bulletproof_max_amounts(proof);
size_t n2 = n_bulletproof_plus_amounts(proof);
CHECK_AND_ASSERT_MES(n2 < std::numeric_limits<uint32_t>::max() - n, 0, "Invalid number of bulletproofs");
if (n2 == 0)
return 0;
@ -321,6 +369,16 @@ namespace rct {
return n;
}
size_t n_bulletproof_plus_max_amounts(const BulletproofPlus &proof)
{
CHECK_AND_ASSERT_MES(proof.L.size() >= 6, 0, "Invalid bulletproof L size");
CHECK_AND_ASSERT_MES(proof.L.size() == proof.R.size(), 0, "Mismatched bulletproof L/R size");
static const size_t extra_bits = 4;
static_assert((1 << extra_bits) == BULLETPROOF_PLUS_MAX_OUTPUTS, "log2(BULLETPROOF_PLUS_MAX_OUTPUTS) is out of date");
CHECK_AND_ASSERT_MES(proof.L.size() <= 6 + extra_bits, 0, "Invalid bulletproof L size");
return 1 << (proof.L.size() - 6);
}
size_t n_bulletproof_plus_max_amounts(const std::vector<BulletproofPlus> &proofs)
{
size_t n = 0;

@ -271,8 +271,10 @@ namespace rct {
};
size_t n_bulletproof_amounts(const Bulletproof &proof);
size_t n_bulletproof_v1_amounts(const Bulletproof &proof);
size_t n_bulletproof_max_amounts(const Bulletproof &proof);
size_t n_bulletproof_amounts(const std::vector<Bulletproof> &proofs);
size_t n_bulletproof_v1_amounts(const std::vector<Bulletproof> &proofs);
size_t n_bulletproof_max_amounts(const std::vector<Bulletproof> &proofs);
size_t n_bulletproof_plus_amounts(const BulletproofPlus &proof);
@ -291,10 +293,12 @@ namespace rct {
RCTTypeNull = 0,
RCTTypeFull = 1,
RCTTypeSimple = 2,
RCTTypeBulletproof = 3,
RCTTypeBulletproof2 = 4,
RCTTypeCLSAG = 5,
RCTTypeBulletproofPlus = 6,
RCTTypeFullBulletproof = 3,
RCTTypeSimpleBulletproof = 4,
RCTTypeBulletproof = 5,
RCTTypeBulletproof2 = 6,
RCTTypeCLSAG = 7,
RCTTypeBulletproofPlus = 8,
};
enum RangeProofType { RangeProofBorromean, RangeProofBulletproof, RangeProofMultiOutputBulletproof, RangeProofPaddedBulletproof };
struct RCTConfig {
@ -323,7 +327,7 @@ namespace rct {
FIELD(type)
if (type == RCTTypeNull)
return ar.good();
if (type != RCTTypeFull && type != RCTTypeSimple && type != RCTTypeBulletproof && type != RCTTypeBulletproof2 && type != RCTTypeCLSAG && type != RCTTypeBulletproofPlus)
if (type != RCTTypeFull && type != RCTTypeSimple && type != RCTTypeBulletproof && type != RCTTypeBulletproof2 && type != RCTTypeFullBulletproof && type != RCTTypeSimpleBulletproof && type != RCTTypeCLSAG && type != RCTTypeBulletproofPlus)
return false;
VARINT_FIELD(txnFee)
// inputs/outputs not saved, only here for serialization help
@ -415,9 +419,24 @@ namespace rct {
return false;
if (type == RCTTypeNull)
return ar.good();
if (type != RCTTypeFull && type != RCTTypeSimple && type != RCTTypeBulletproof && type != RCTTypeBulletproof2 && type != RCTTypeCLSAG && type != RCTTypeBulletproofPlus)
if (type != RCTTypeFull && type != RCTTypeSimple && type != RCTTypeBulletproof && type != RCTTypeBulletproof2 && type != RCTTypeFullBulletproof && type != RCTTypeSimpleBulletproof && type != RCTTypeCLSAG && type != RCTTypeBulletproofPlus)
return false;
if (type == RCTTypeBulletproofPlus)
if (type == RCTTypeSimpleBulletproof || type == RCTTypeFullBulletproof)
{
ar.tag("bp");
ar.begin_array();
PREPARE_CUSTOM_VECTOR_SERIALIZATION(outputs, bulletproofs);
if (bulletproofs.size() != outputs)
return false;
for (size_t i = 0; i < outputs; ++i)
{
FIELDS(bulletproofs[i])
if (outputs - i > 1)
ar.delimit_array();
}
ar.end_array();
}
else if (type == RCTTypeBulletproofPlus)
{
uint32_t nbp = bulletproofs_plus.size();
VARINT_FIELD(nbp)
@ -520,7 +539,7 @@ namespace rct {
ar.begin_array();
// we keep a byte for size of MGs, because we don't know whether this is
// a simple or full rct signature, and it's starting to annoy the hell out of me
size_t mg_elements = (type == RCTTypeSimple || type == RCTTypeBulletproof || type == RCTTypeBulletproof2) ? inputs : 1;
size_t mg_elements = (type == RCTTypeSimple || type == RCTTypeBulletproof || type == RCTTypeBulletproof2 || type == RCTTypeSimpleBulletproof) ? inputs : 1;
PREPARE_CUSTOM_VECTOR_SERIALIZATION(mg_elements, MGs);
if (MGs.size() != mg_elements)
return false;
@ -538,7 +557,7 @@ namespace rct {
for (size_t j = 0; j < mixin + 1; ++j)
{
ar.begin_array();
size_t mg_ss2_elements = ((type == RCTTypeSimple || type == RCTTypeBulletproof || type == RCTTypeBulletproof2) ? 1 : inputs) + 1;
size_t mg_ss2_elements = ((type == RCTTypeSimple || type == RCTTypeBulletproof || type == RCTTypeBulletproof2 || type == RCTTypeSimpleBulletproof) ? 1 : inputs) + 1;
PREPARE_CUSTOM_VECTOR_SERIALIZATION(mg_ss2_elements, MGs[i].ss[j]);
if (MGs[i].ss[j].size() != mg_ss2_elements)
return false;
@ -565,7 +584,7 @@ namespace rct {
}
ar.end_array();
}
if (type == RCTTypeBulletproof || type == RCTTypeBulletproof2 || type == RCTTypeCLSAG || type == RCTTypeBulletproofPlus)
if (type == RCTTypeBulletproof || type == RCTTypeBulletproof2 || type == RCTTypeSimpleBulletproof || type == RCTTypeCLSAG || type == RCTTypeBulletproofPlus)
{
ar.tag("pseudoOuts");
ar.begin_array();
@ -597,12 +616,12 @@ namespace rct {
keyV& get_pseudo_outs()
{
return type == RCTTypeBulletproof || type == RCTTypeBulletproof2 || type == RCTTypeCLSAG || type == RCTTypeBulletproofPlus ? p.pseudoOuts : pseudoOuts;
return type == RCTTypeBulletproof || type == RCTTypeSimpleBulletproof || type == RCTTypeBulletproof2 || type == RCTTypeCLSAG || type == RCTTypeBulletproofPlus ? p.pseudoOuts : pseudoOuts;
}
keyV const& get_pseudo_outs() const
{
return type == RCTTypeBulletproof || type == RCTTypeBulletproof2 || type == RCTTypeCLSAG || type == RCTTypeBulletproofPlus ? p.pseudoOuts : pseudoOuts;
return type == RCTTypeBulletproof || type == RCTTypeSimpleBulletproof || type == RCTTypeBulletproof2 || type == RCTTypeCLSAG || type == RCTTypeBulletproofPlus ? p.pseudoOuts : pseudoOuts;
}
BEGIN_SERIALIZE_OBJECT()
@ -714,6 +733,8 @@ namespace rct {
bool is_rct_simple(int type);
bool is_rct_bulletproof(int type);
bool is_rct_old_bulletproof(int type);
bool is_rct_new_bulletproof(int type);
bool is_rct_bulletproof_plus(int type);
bool is_rct_borromean(int type);
bool is_rct_clsag(int type);

@ -545,12 +545,13 @@ namespace cryptonote
if (restricted)
res.database_size = round_up(res.database_size, 5ull* 1024 * 1024 * 1024);
res.update_available = restricted ? false : m_core.is_update_available();
res.version = restricted ? "" : MONERO_VERSION_FULL;
res.version = MONERO_VERSION_FULL;
res.synchronized = check_core_ready();
res.busy_syncing = m_p2p.get_payload_object().is_busy_syncing();
res.restricted = restricted;
res.status = CORE_RPC_STATUS_OK;
res.donation_address = m_core.get_addy();
return true;
}
//------------------------------------------------------------------------------------------------------------------------------
@ -1009,7 +1010,17 @@ namespace cryptonote
CHECK_AND_ASSERT_MES(tx_hash == std::get<0>(tx), false, "mismatched tx hash");
e.tx_hash = *txhi++;
e.prunable_hash = epee::string_tools::pod_to_hex(std::get<2>(tx));
if (req.split || req.prune || std::get<3>(tx).empty())
// coinbase txes do not have signatures to prune, so they appear to be pruned if looking just at prunable data being empty
bool pruned = std::get<3>(tx).empty();
if (pruned)
{
cryptonote::transaction t;
if (cryptonote::parse_and_validate_tx_base_from_blob(std::get<1>(tx), t) && is_coinbase(t))
pruned = false;
}
if (req.split || req.prune || pruned)
{
// use splitted form with pruned and prunable (filled only when prune=false and the daemon has it), leaving as_hex as empty
e.pruned_as_hex = string_tools::buff_to_hex_nodelimer(std::get<1>(tx));
@ -1275,6 +1286,8 @@ namespace cryptonote
add_reason(reason, "fee too low");
if ((res.too_few_outputs = tvc.m_too_few_outputs))
add_reason(reason, "too few outputs");
if ((res.tx_extra_too_big = tvc.m_tx_extra_too_big))
add_reason(reason, "tx-extra too big");
const std::string punctuation = reason.empty() ? "" : ": ";
if (tvc.m_verifivation_failed)
{
@ -1395,15 +1408,15 @@ namespace cryptonote
if (lMiner.is_mining() || lMiner.get_is_background_mining_enabled())
res.address = get_account_address_as_str(nettype(), false, lMiningAdr);
const uint8_t major_version = m_core.get_blockchain_storage().get_current_hard_fork_version();
const unsigned variant = major_version >= 7 ? major_version - 6 : 0;
const unsigned variant = major_version >= 13 ? 6 : major_version >= 11 && major_version <= 12 ? 4 : 2;
switch (variant)
{
case 0: res.pow_algorithm = "Cryptonight"; break;
case 1: res.pow_algorithm = "CNv1 (Cryptonight variant 1)"; break;
case 2: case 3: res.pow_algorithm = "CNv2 (Cryptonight variant 2)"; break;
case 4: case 5: res.pow_algorithm = "CNv4 (Cryptonight variant 4)"; break;
case 6: case 7: case 8: case 9: res.pow_algorithm = "RandomX"; break;
default: res.pow_algorithm = "RandomX"; break; // assumed
case 4: case 5: res.pow_algorithm = "CN/WOW"; break;
case 6: case 7: case 8: case 9: res.pow_algorithm = "RandomWOW"; break;
default: res.pow_algorithm = "RandomWOW"; break; // assumed
}
if (res.is_background_mining_enabled)
{
@ -1887,6 +1900,7 @@ namespace cryptonote
res.blocktemplate_blob = string_tools::buff_to_hex_nodelimer(block_blob);
res.blockhashing_blob = string_tools::buff_to_hex_nodelimer(hashing_blob);
res.status = CORE_RPC_STATUS_OK;
res.vote = 0;
return true;
}
//------------------------------------------------------------------------------------------------------------------------------
@ -2189,6 +2203,11 @@ namespace cryptonote
return false;
}
b.nonce = req.starting_nonce;
if (b.major_version >= HF_VERSION_BLOCK_HEADER_MINER_SIG)
{
b.signature = {};
b.vote = 0;
}
crypto::hash seed_hash = crypto::null_hash;
if (b.major_version >= RX_BLOCK_VERSION && !epee::string_tools::hex_to_pod(template_res.seed_hash, seed_hash))
{
@ -2227,6 +2246,7 @@ namespace cryptonote
bool core_rpc_server::fill_block_header_response(const block& blk, bool orphan_status, uint64_t height, const crypto::hash& hash, block_header_response& response, bool fill_pow_hash)
{
PERF_TIMER(fill_block_header_response);
response.vote = blk.vote;
response.major_version = blk.major_version;
response.minor_version = blk.minor_version;
response.timestamp = blk.timestamp;
@ -3027,7 +3047,7 @@ namespace cryptonote
return true;
}
static const char software[] = "monero";
static const char software[] = "wownero";
#ifdef BUILD_TAG
static const char buildtag[] = BOOST_PP_STRINGIZE(BUILD_TAG);
static const char subdir[] = "cli";

@ -88,7 +88,7 @@ namespace cryptonote
// advance which version they will stop working with
// Don't go over 32767 for any of these
#define CORE_RPC_VERSION_MAJOR 3
#define CORE_RPC_VERSION_MINOR 11
#define CORE_RPC_VERSION_MINOR 12
#define MAKE_CORE_RPC_VERSION(major,minor) (((major)<<16)|(minor))
#define CORE_RPC_VERSION MAKE_CORE_RPC_VERSION(CORE_RPC_VERSION_MAJOR, CORE_RPC_VERSION_MINOR)
@ -592,6 +592,7 @@ namespace cryptonote
bool fee_too_low;
bool too_few_outputs;
bool sanity_check_failed;
bool tx_extra_too_big;
BEGIN_KV_SERIALIZE_MAP()
KV_SERIALIZE_PARENT(rpc_access_response_base)
@ -606,6 +607,7 @@ namespace cryptonote
KV_SERIALIZE(fee_too_low)
KV_SERIALIZE(too_few_outputs)
KV_SERIALIZE(sanity_check_failed)
KV_SERIALIZE(tx_extra_too_big)
END_KV_SERIALIZE_MAP()
};
typedef epee::misc_utils::struct_init<response_t> response;
@ -690,6 +692,7 @@ namespace cryptonote
std::string version;
bool synchronized;
bool restricted;
std::string donation_address;
BEGIN_KV_SERIALIZE_MAP()
KV_SERIALIZE_PARENT(rpc_access_response_base)
@ -732,6 +735,7 @@ namespace cryptonote
KV_SERIALIZE(version)
KV_SERIALIZE(synchronized)
KV_SERIALIZE(restricted)
KV_SERIALIZE(donation_address)
END_KV_SERIALIZE_MAP()
};
typedef epee::misc_utils::struct_init<response_t> response;
@ -922,6 +926,7 @@ namespace cryptonote
std::string next_seed_hash;
blobdata blocktemplate_blob;
blobdata blockhashing_blob;
uint16_t vote;
BEGIN_KV_SERIALIZE_MAP()
KV_SERIALIZE_PARENT(rpc_response_base)
@ -937,6 +942,7 @@ namespace cryptonote
KV_SERIALIZE(blockhashing_blob)
KV_SERIALIZE(seed_hash)
KV_SERIALIZE(next_seed_hash)
KV_SERIALIZE(vote)
END_KV_SERIALIZE_MAP()
};
typedef epee::misc_utils::struct_init<response_t> response;
@ -1130,6 +1136,7 @@ namespace cryptonote
std::string pow_hash;
uint64_t long_term_weight;
std::string miner_tx_hash;
uint16_t vote;
BEGIN_KV_SERIALIZE_MAP()
KV_SERIALIZE(major_version)
@ -1154,6 +1161,7 @@ namespace cryptonote
KV_SERIALIZE(pow_hash)
KV_SERIALIZE_OPT(long_term_weight, (uint64_t)0)
KV_SERIALIZE(miner_tx_hash)
KV_SERIALIZE(vote)
END_KV_SERIALIZE_MAP()
};

@ -540,7 +540,7 @@ namespace rpc
res.info.block_size_median = res.info.block_weight_median = m_core.get_blockchain_storage().get_current_cumulative_block_weight_median();
res.info.adjusted_time = m_core.get_blockchain_storage().get_adjusted_time(res.info.height);
res.info.start_time = (uint64_t)m_core.get_start_time();
res.info.version = MONERO_VERSION;
res.info.version = MONERO_VERSION_FULL;
res.status = Message::STATUS_OK;
res.error_details = "";
@ -895,6 +895,11 @@ namespace rpc
header.minor_version = b.minor_version;
header.timestamp = b.timestamp;
header.nonce = b.nonce;
if (b.major_version >= HF_VERSION_BLOCK_HEADER_MINER_SIG)
{
header.signature = b.signature;
header.vote = b.vote;
}
header.prev_id = b.prev_id;
header.depth = m_core.get_current_blockchain_height() - header.height - 1;

@ -164,6 +164,8 @@ namespace rpc
uint64_t timestamp;
crypto::hash prev_id;
uint32_t nonce;
crypto::signature signature;
uint16_t vote;
uint64_t height;
uint64_t depth;
crypto::hash hash;

@ -313,6 +313,8 @@ void toJsonValue(rapidjson::Writer<epee::byte_stream>& dest, const cryptonote::b
INSERT_INTO_JSON_OBJECT(dest, timestamp, b.timestamp);
INSERT_INTO_JSON_OBJECT(dest, prev_id, b.prev_id);
INSERT_INTO_JSON_OBJECT(dest, nonce, b.nonce);
INSERT_INTO_JSON_OBJECT(dest, signature, b.signature);
INSERT_INTO_JSON_OBJECT(dest, vote, b.vote);
INSERT_INTO_JSON_OBJECT(dest, miner_tx, b.miner_tx);
INSERT_INTO_JSON_OBJECT(dest, tx_hashes, b.tx_hashes);
@ -332,6 +334,8 @@ void fromJsonValue(const rapidjson::Value& val, cryptonote::block& b)
GET_FROM_JSON_OBJECT(val, b.timestamp, timestamp);
GET_FROM_JSON_OBJECT(val, b.prev_id, prev_id);
GET_FROM_JSON_OBJECT(val, b.nonce, nonce);
GET_FROM_JSON_OBJECT(val, b.signature, signature);
GET_FROM_JSON_OBJECT(val, b.vote, vote);
GET_FROM_JSON_OBJECT(val, b.miner_tx, miner_tx);
GET_FROM_JSON_OBJECT(val, b.tx_hashes, tx_hashes);
}
@ -1078,6 +1082,7 @@ void toJsonValue(rapidjson::Writer<epee::byte_stream>& dest, const cryptonote::r
{
dest.StartObject();
INSERT_INTO_JSON_OBJECT(dest, vote, response.vote);
INSERT_INTO_JSON_OBJECT(dest, major_version, response.major_version);
INSERT_INTO_JSON_OBJECT(dest, minor_version, response.minor_version);
INSERT_INTO_JSON_OBJECT(dest, timestamp, response.timestamp);
@ -1099,6 +1104,7 @@ void fromJsonValue(const rapidjson::Value& val, cryptonote::rpc::BlockHeaderResp
throw WRONG_TYPE("json object");
}
GET_FROM_JSON_OBJECT(val, response.vote, vote);
GET_FROM_JSON_OBJECT(val, response.major_version, major_version);
GET_FROM_JSON_OBJECT(val, response.minor_version, minor_version);
GET_FROM_JSON_OBJECT(val, response.timestamp, timestamp);

@ -61,5 +61,5 @@ target_link_libraries(simplewallet
${EXTRA_LIBRARIES})
set_property(TARGET simplewallet
PROPERTY
OUTPUT_NAME "monero-wallet-cli")
OUTPUT_NAME "wownero-wallet-cli")
install(TARGETS simplewallet DESTINATION bin)

@ -183,7 +183,7 @@ namespace
const command_line::arg_descriptor<bool> arg_non_deterministic = {"non-deterministic", sw::tr("Generate non-deterministic view and spend keys"), false};
const command_line::arg_descriptor<uint64_t> arg_restore_height = {"restore-height", sw::tr("Restore from specific blockchain height"), 0};
const command_line::arg_descriptor<std::string> arg_restore_date = {"restore-date", sw::tr("Restore from estimated blockchain height on specified date"), ""};
const command_line::arg_descriptor<bool> arg_do_not_relay = {"do-not-relay", sw::tr("The newly created transaction will not be relayed to the monero network"), false};
const command_line::arg_descriptor<bool> arg_do_not_relay = {"do-not-relay", sw::tr("The newly created transaction will not be relayed to the wownero network"), false};
const command_line::arg_descriptor<bool> arg_create_address_file = {"create-address-file", sw::tr("Create an address file for new wallets"), false};
const command_line::arg_descriptor<std::string> arg_subaddress_lookahead = {"subaddress-lookahead", tools::wallet2::tr("Set subaddress lookahead sizes to <major>:<minor>"), ""};
const command_line::arg_descriptor<bool> arg_use_english_language_names = {"use-english-language-names", sw::tr("Display English language names"), false};
@ -252,7 +252,7 @@ namespace
const char* USAGE_MMS("mms [<subcommand> [<subcommand_parameters>]]");
const char* USAGE_MMS_INIT("mms init <required_signers>/<authorized_signers> <own_label> <own_transport_address>");
const char* USAGE_MMS_INFO("mms info");
const char* USAGE_MMS_SIGNER("mms signer [<number> <label> [<transport_address> [<monero_address>]]]");
const char* USAGE_MMS_SIGNER("mms signer [<number> <label> [<transport_address> [<wownero_address>]]]");
const char* USAGE_MMS_LIST("mms list");
const char* USAGE_MMS_NEXT("mms next [sync]");
const char* USAGE_MMS_SYNC("mms sync");
@ -482,7 +482,7 @@ namespace
std::stringstream prompt;
prompt << sw::tr("For URL: ") << url
<< ", " << dnssec_str << std::endl
<< sw::tr(" Monero Address = ") << addresses[0]
<< sw::tr(" Wownero Address = ") << addresses[0]
<< std::endl
<< sw::tr("Is this OK?")
;
@ -773,7 +773,7 @@ bool simple_wallet::spendkey(const std::vector<std::string> &args/* = std::vecto
std::cout << "secret: On device. Not available" << std::endl;
} else {
SCOPED_WALLET_UNLOCK();
printf("secret: ");
printf("secret (key used for mining): ");
print_secret_key(m_wallet->get_account().get_keys().m_spend_secret_key);
putchar('\n');
}
@ -1633,7 +1633,7 @@ bool simple_wallet::export_raw_multisig(const std::vector<std::string> &args)
for (auto &ptx: txs.m_ptx)
{
const crypto::hash txid = cryptonote::get_transaction_hash(ptx.tx);
const std::string filename = std::string("raw_multisig_monero_tx_") + epee::string_tools::pod_to_hex(txid);
const std::string filename = std::string("raw_multisig_wownero_tx_") + epee::string_tools::pod_to_hex(txid);
if (!filenames.empty())
filenames += ", ";
filenames += filename;
@ -2279,25 +2279,25 @@ bool simple_wallet::public_nodes(const std::vector<std::string> &args)
bool simple_wallet::welcome(const std::vector<std::string> &args)
{
message_writer() << tr("Welcome to Monero, the private cryptocurrency.");
message_writer() << tr("Welcome to Wownero, the private cryptocurrency.");
message_writer() << "";
message_writer() << tr("Monero, like Bitcoin, is a cryptocurrency. That is, it is digital money.");
message_writer() << tr("Unlike Bitcoin, your Monero transactions and balance stay private and are not visible to the world by default.");
message_writer() << tr("Wownero, like Bitcoin, is a cryptocurrency. That is, it is digital money.");
message_writer() << tr("Unlike Bitcoin, your Wownero transactions and balance stay private and are not visible to the world by default.");
message_writer() << tr("However, you have the option of making those available to select parties if you choose to.");
message_writer() << "";
message_writer() << tr("Monero protects your privacy on the blockchain, and while Monero strives to improve all the time,");
message_writer() << tr("no privacy technology can be 100% perfect, Monero included.");
message_writer() << tr("Monero cannot protect you from malware, and it may not be as effective as we hope against powerful adversaries.");
message_writer() << tr("Flaws in Monero may be discovered in the future, and attacks may be developed to peek under some");
message_writer() << tr("of the layers of privacy Monero provides. Be safe and practice defense in depth.");
message_writer() << tr("Wownero protects your privacy on the blockchain, and while Wownero strives to improve all the time,");
message_writer() << tr("no privacy technology can be 100% perfect, Wownero included.");
message_writer() << tr("Wownero cannot protect you from malware, and it may not be as effective as we hope against powerful adversaries.");
message_writer() << tr("Flaws in Wownero may be discovered in the future, and attacks may be developed to peek under some");
message_writer() << tr("of the layers of privacy Wownero provides. Be safe and practice defense in depth.");
message_writer() << "";
message_writer() << tr("Welcome to Monero and financial privacy. For more information see https://GetMonero.org");
message_writer() << tr("Welcome to Wownero and financial privacy. For more information see https://wownero.org");
return true;
}
bool simple_wallet::version(const std::vector<std::string> &args)
{
message_writer() << "Monero '" << MONERO_RELEASE_NAME << "' (v" << MONERO_VERSION_FULL << ")";
message_writer() << "Wownero '" << MONERO_RELEASE_NAME << "' (v" << MONERO_VERSION_FULL << ")";
return true;
}
@ -2433,7 +2433,7 @@ bool simple_wallet::show_qr_code(const std::vector<std::string> &args)
WTEXTON();
try
{
const std::string address = "monero:" + m_wallet->get_subaddress_as_str({m_current_subaddress_account, subaddress_index});
const std::string address = "wownero:" + m_wallet->get_subaddress_as_str({m_current_subaddress_account, subaddress_index});
const qrcodegen::QrCode qr = qrcodegen::QrCode::encodeText(address.c_str(), qrcodegen::QrCode::Ecc::LOW);
for (int y = -2; y < qr.getSize() + 2; y+=2)
{
@ -2633,15 +2633,15 @@ bool simple_wallet::set_unit(const std::vector<std::string> &args/* = std::vecto
const std::string &unit = args[1];
unsigned int decimal_point = CRYPTONOTE_DISPLAY_DECIMAL_POINT;
if (unit == "monero")
if (unit == "wownero")
decimal_point = CRYPTONOTE_DISPLAY_DECIMAL_POINT;
else if (unit == "millinero")
decimal_point = CRYPTONOTE_DISPLAY_DECIMAL_POINT - 3;
else if (unit == "micronero")
decimal_point = CRYPTONOTE_DISPLAY_DECIMAL_POINT - 6;
else if (unit == "nanonero")
decimal_point = CRYPTONOTE_DISPLAY_DECIMAL_POINT - 9;
else if (unit == "piconero")
else if (unit == "verywow")
decimal_point = CRYPTONOTE_DISPLAY_DECIMAL_POINT - 4;
else if (unit == "muchwow")
decimal_point = CRYPTONOTE_DISPLAY_DECIMAL_POINT - 7;
else if (unit == "suchwow")
decimal_point = CRYPTONOTE_DISPLAY_DECIMAL_POINT - 10;
else if (unit == "dust")
decimal_point = 0;
else
{
@ -2980,6 +2980,19 @@ bool simple_wallet::set_show_wallet_name_when_locked(const std::vector<std::stri
return true;
}
bool simple_wallet::set_show_detailed_prompt(const std::vector<std::string> &args/* = std::vector<std::string>()*/)
{
const auto pwd_container = get_and_verify_password();
if (pwd_container)
{
parse_bool_and_use(args[1], [&](bool r) {
m_wallet->show_detailed_prompt(r);
m_wallet->rewrite(m_wallet_file, pwd_container->password());
});
}
return true;
}
bool simple_wallet::set_inactivity_lock_timeout(const std::vector<std::string> &args/* = std::vector<std::string>()*/)
{
#ifdef _WIN32
@ -3141,16 +3154,16 @@ bool simple_wallet::help(const std::vector<std::string> &args/* = std::vector<st
message_writer() << tr("\"balance\" - Show balance.");
message_writer() << tr("\"address all\" - Show all addresses.");
message_writer() << tr("\"address new\" - Create new subaddress.");
message_writer() << tr("\"transfer <address> <amount>\" - Send XMR to an address.");
message_writer() << tr("\"transfer <address> <amount>\" - Send WOW to an address.");
message_writer() << tr("\"show_transfers [in|out|pending|failed|pool]\" - Show transactions.");
message_writer() << tr("\"sweep_all <address>\" - Send whole balance to another wallet.");
message_writer() << tr("\"seed\" - Show secret 25 words that can be used to recover this wallet.");
message_writer() << tr("\"refresh\" - Synchronize wallet with the Monero network.");
message_writer() << tr("\"refresh\" - Synchronize wallet with the Wownero network.");
message_writer() << tr("\"status\" - Check current status of wallet.");
message_writer() << tr("\"version\" - Check software version.");
message_writer() << tr("\"exit\" - Exit wallet.");
message_writer() << "";
message_writer() << tr("\"donate <amount>\" - Donate XMR to the development team.");
message_writer() << tr("\"clear\" - Clear screen.");
message_writer() << tr("\"donate <amount>\" - Donate WOW to the development team.");
message_writer() << "";
}
else if ((args.size() == 1) && (args.front() == "all"))
@ -3270,6 +3283,9 @@ simple_wallet::simple_wallet()
m_cmd_binder.set_handler("refresh",
boost::bind(&simple_wallet::on_command, this, &simple_wallet::refresh, _1),
tr("Synchronize the transactions and balance."));
m_cmd_binder.set_handler("clear",
boost::bind(&simple_wallet::on_command, this, &simple_wallet::clear, _1),
tr("Clear screen."));
m_cmd_binder.set_handler("balance",
boost::bind(&simple_wallet::on_command, this, &simple_wallet::show_balance, _1),
tr(USAGE_SHOW_BALANCE),
@ -3318,12 +3334,12 @@ simple_wallet::simple_wallet()
m_cmd_binder.set_handler("donate",
boost::bind(&simple_wallet::on_command, this, &simple_wallet::donate, _1),
tr(USAGE_DONATE),
tr("Donate <amount> to the development team (donate.getmonero.org)."));
tr("Donate <amount> to the development team (wownero.org)."));
m_cmd_binder.set_handler("sign_transfer",
boost::bind(&simple_wallet::on_command, this, &simple_wallet::sign_transfer, _1),
tr(USAGE_SIGN_TRANSFER),
tr("Sign a transaction from a file. If the parameter \"export_raw\" is specified, transaction raw hex data suitable for the daemon RPC /sendrawtransaction is exported.\n"
"Use the parameter <filename> to specify the file to read from. If not specified, the default \"unsigned_monero_tx\" will be used."));
"Use the parameter <filename> to specify the file to read from. If not specified, the default \"unsigned_wownero_tx\" will be used."));
m_cmd_binder.set_handler("submit_transfer",
boost::bind(&simple_wallet::on_command, this, &simple_wallet::submit_transfer, _1),
tr("Submit a signed transaction from a file."));
@ -3393,8 +3409,8 @@ simple_wallet::simple_wallet()
"ask-password <0|1|2 (or never|action|decrypt)>\n "
" action: ask the password before many actions such as transfer, etc\n "
" decrypt: same as action, but keeps the spend key encrypted in memory when not needed\n "
"unit <monero|millinero|micronero|nanonero|piconero>\n "
" Set the default monero (sub-)unit.\n "
"unit <wownero|verywow|muchwow|suchwow|dust>\n "
" Set the default WOW (sub-)unit.\n "
"min-outputs-count [n]\n "
" Try to keep at least that many outputs of value at least min-outputs-value.\n "
"min-outputs-value [n]\n "
@ -3412,9 +3428,9 @@ simple_wallet::simple_wallet()
"auto-low-priority <1|0>\n "
" Whether to automatically use the low priority fee level when it's safe to do so.\n "
"segregate-pre-fork-outputs <1|0>\n "
" Set this if you intend to spend outputs on both Monero AND a key reusing fork.\n "
" Set this if you intend to spend outputs on both Wownero AND a key reusing fork.\n "
"key-reuse-mitigation2 <1|0>\n "
" Set this if you are not sure whether you will spend on a key reusing Monero fork later.\n "
" Set this if you are not sure whether you will spend on a key reusing Wownero fork later.\n "
"subaddress-lookahead <major>:<minor>\n "
" Set the lookahead sizes for the subaddress hash table.\n "
"segregation-height <n>\n "
@ -3428,7 +3444,7 @@ simple_wallet::simple_wallet()
"track-uses <1|0>\n "
" Whether to keep track of owned outputs uses.\n "
"setup-background-mining <1|0>\n "
" Whether to enable background mining. Set this to support the network and to get a chance to receive new monero.\n "
" Whether to enable background mining. Set this to support the network and to get a chance to receive new WOW.\n "
"device-name <device_name[:device_spec]>\n "
" Device name for hardware wallet.\n "
"export-format <\"binary\"|\"ascii\">\n "
@ -3441,6 +3457,8 @@ simple_wallet::simple_wallet()
" The RPC payment credits balance to target (0 for default).\n "
"show-wallet-name-when-locked <1|0>\n "
" Set this if you would like to display the wallet name when locked.\n "
"show-detailed-prompt <1|0>\n "
" Set this if you would like to display the account, wallet name, and block in the prompt.\n "
"enable-multisig-experimental <1|0>\n "
" Set this to allow multisig commands. Multisig may currently be exploitable if parties do not trust each other.\n "
"inactivity-lock-timeout <unsigned int>\n "
@ -3629,7 +3647,7 @@ simple_wallet::simple_wallet()
m_cmd_binder.set_handler("mms signer",
boost::bind(&simple_wallet::on_command, this, &simple_wallet::mms, _1),
tr(USAGE_MMS_SIGNER),
tr("Set or modify authorized signer info (single-word label, transport address, Monero address), or list all signers"));
tr("Set or modify authorized signer info (single-word label, transport address, Wownero address), or list all signers"));
m_cmd_binder.set_handler("mms list",
boost::bind(&simple_wallet::on_command, this, &simple_wallet::mms, _1),
tr(USAGE_MMS_LIST),
@ -3754,7 +3772,7 @@ simple_wallet::simple_wallet()
m_cmd_binder.set_handler("welcome",
boost::bind(&simple_wallet::on_command, this, &simple_wallet::welcome, _1),
tr(USAGE_WELCOME),
tr("Prints basic info about Monero for first time users"));
tr("Prints basic info about Wownero for first time users"));
m_cmd_binder.set_handler("version",
boost::bind(&simple_wallet::on_command, this, &simple_wallet::version, _1),
tr(USAGE_VERSION),
@ -3849,6 +3867,7 @@ bool simple_wallet::set_variable(const std::vector<std::string> &args)
success_msg_writer() << "device-name = " << m_wallet->device_name();
success_msg_writer() << "export-format = " << (m_wallet->export_format() == tools::wallet2::ExportFormat::Ascii ? "ascii" : "binary");
success_msg_writer() << "show-wallet-name-when-locked = " << m_wallet->show_wallet_name_when_locked();
success_msg_writer() << "show-detailed-prompt = " << m_wallet->show_detailed_prompt();
success_msg_writer() << "inactivity-lock-timeout = " << m_wallet->inactivity_lock_timeout()
#ifdef _WIN32
<< " (disabled on Windows)"
@ -3898,7 +3917,7 @@ bool simple_wallet::set_variable(const std::vector<std::string> &args)
CHECK_SIMPLE_VARIABLE("refresh-type", set_refresh_type, tr("full (slowest, no assumptions); optimize-coinbase (fast, assumes the whole coinbase is paid to a single address); no-coinbase (fastest, assumes we receive no coinbase transaction), default (same as optimize-coinbase)"));
CHECK_SIMPLE_VARIABLE("priority", set_default_priority, tr("0, 1, 2, 3, or 4, or one of ") << join_priority_strings(", "));
CHECK_SIMPLE_VARIABLE("ask-password", set_ask_password, tr("0|1|2 (or never|action|decrypt)"));
CHECK_SIMPLE_VARIABLE("unit", set_unit, tr("monero, millinero, micronero, nanonero, piconero"));
CHECK_SIMPLE_VARIABLE("unit", set_unit, tr("wownero, verywow, muchwow, suchwow, dust"));
CHECK_SIMPLE_VARIABLE("max-reorg-depth", set_max_reorg_depth, tr("unsigned integer"));
CHECK_SIMPLE_VARIABLE("min-outputs-count", set_min_output_count, tr("unsigned integer"));
CHECK_SIMPLE_VARIABLE("min-outputs-value", set_min_output_value, tr("amount"));
@ -3917,6 +3936,7 @@ bool simple_wallet::set_variable(const std::vector<std::string> &args)
CHECK_SIMPLE_VARIABLE("ignore-outputs-below", set_ignore_outputs_below, tr("amount"));
CHECK_SIMPLE_VARIABLE("track-uses", set_track_uses, tr("0 or 1"));
CHECK_SIMPLE_VARIABLE("show-wallet-name-when-locked", set_show_wallet_name_when_locked, tr("1 or 0"));
CHECK_SIMPLE_VARIABLE("show-detailed-prompt", set_show_detailed_prompt, tr("1 or 0"));
CHECK_SIMPLE_VARIABLE("inactivity-lock-timeout", set_inactivity_lock_timeout, tr("unsigned integer (seconds, 0 to disable)"));
CHECK_SIMPLE_VARIABLE("setup-background-mining", set_setup_background_mining, tr("1/yes or 0/no"));
CHECK_SIMPLE_VARIABLE("device-name", set_device_name, tr("<device_name[:device_spec]>"));
@ -4022,6 +4042,7 @@ bool simple_wallet::ask_wallet_create_if_needed()
bool ok = true;
if (!m_restoring)
{
message_writer() << tr("Looking for filename: ") << boost::filesystem::complete(wallet_path);
message_writer() << tr("No wallet found with that name. Confirm creation of new wallet named: ") << wallet_path;
confirm_creation = input_line("", true);
if(std::cin.eof())
@ -4051,8 +4072,8 @@ bool simple_wallet::ask_wallet_create_if_needed()
*/
void simple_wallet::print_seed(const epee::wipeable_string &seed)
{
success_msg_writer(true) << "\n" << boost::format(tr("NOTE: the following %s can be used to recover access to your wallet. "
"Write them down and store them somewhere safe and secure. Please do not store them in "
success_msg_writer(true) << "\n" << boost::format(tr("NOTE: the following %s can be used to recover access to your wallet.\n"
"Write them down and store them somewhere safe and secure. Please do not store them in \n"
"your email or on file storage services outside of your immediate control.\n")) % (m_wallet->multisig() ? tr("string") : tr("25 words"));
// don't log
int space_index = 0;
@ -4712,7 +4733,7 @@ bool simple_wallet::init(const boost::program_options::variables_map& vm)
bool ssl = false;
if (m_wallet->check_connection(NULL, &ssl) && !ssl)
message_writer(console_color_red, true) << boost::format(tr("Using your own without SSL exposes your RPC traffic to monitoring"));
message_writer(console_color_red, true) << boost::format(tr("You are strongly encouraged to connect to the Monero network using your own daemon"));
message_writer(console_color_red, true) << boost::format(tr("You are strongly encouraged to connect to the Wownero network using your own daemon"));
message_writer(console_color_red, true) << boost::format(tr("If you or someone you trust are operating this daemon, you can use --trusted-daemon"));
COMMAND_RPC_GET_INFO::request req;
@ -4733,7 +4754,7 @@ bool simple_wallet::init(const boost::program_options::variables_map& vm)
check_background_mining(password);
if (welcome)
message_writer(console_color_yellow, true) << tr("If you are new to Monero, type \"welcome\" for a brief overview.");
message_writer(console_color_yellow, true) << tr("If you are new to Wownero, type \"welcome\" for a brief overview.");
m_last_activity_time = time(NULL);
return true;
@ -4964,10 +4985,11 @@ boost::optional<epee::wipeable_string> simple_wallet::new_wallet(const boost::pr
"Use the \"help\" command to see a simplified list of available commands.\n"
"Use \"help all\" command to see the list of all available commands.\n"
"Use \"help <command>\" to see a command's documentation.\n"
"Always use the \"exit\" command when closing monero-wallet-cli to save \n"
"Always use the \"exit\" command when closing wownero-wallet-cli to save \n"
"your current session's state. Otherwise, you might need to synchronize \n"
"your wallet again (your wallet keys are NOT at risk in any case).\n")
;
success_msg_writer() << tr("Filename: ") << boost::filesystem::complete(m_wallet->get_keys_file());
if (!two_random)
{
@ -5347,7 +5369,7 @@ void simple_wallet::start_background_mining()
return;
}
}
success_msg_writer() << tr("Background mining enabled. Thank you for supporting the Monero network.");
success_msg_writer() << tr("Background mining enabled. Thank you for supporting the Wownero network.");
}
//----------------------------------------------------------------------------------------------------
void simple_wallet::stop_background_mining()
@ -5375,7 +5397,6 @@ void simple_wallet::stop_background_mining()
return;
}
}
message_writer(console_color_red, false) << tr("Background mining not enabled. Run \"set setup-background-mining 1\" to change.");
}
//----------------------------------------------------------------------------------------------------
void simple_wallet::check_background_mining(const epee::wipeable_string &password)
@ -5383,7 +5404,6 @@ void simple_wallet::check_background_mining(const epee::wipeable_string &passwor
tools::wallet2::BackgroundMiningSetupType setup = m_wallet->setup_background_mining();
if (setup == tools::wallet2::BackgroundMiningNo)
{
message_writer(console_color_red, false) << tr("Background mining not enabled. Run \"set setup-background-mining 1\" to change.");
return;
}
@ -5419,12 +5439,11 @@ void simple_wallet::check_background_mining(const epee::wipeable_string &passwor
{
message_writer() << tr("The daemon is not set up to background mine.");
message_writer() << tr("With background mining enabled, the daemon will mine when idle and not on battery.");
message_writer() << tr("Enabling this supports the network you are using, and makes you eligible for receiving new monero");
message_writer() << tr("Enabling this supports the network you are using, and makes you eligible for receiving new WOW");
std::string accepted = input_line(tr("Do you want to do it now? (Y/Yes/N/No): "));
if (std::cin.eof() || !command_line::is_yes(accepted)) {
m_wallet->setup_background_mining(tools::wallet2::BackgroundMiningNo);
m_wallet->rewrite(m_wallet_file, password);
message_writer(console_color_red, false) << tr("Background mining not enabled. Set setup-background-mining to 1 to change.");
return;
}
m_wallet->setup_background_mining(tools::wallet2::BackgroundMiningYes);
@ -5982,6 +6001,16 @@ bool simple_wallet::refresh(const std::vector<std::string>& args)
return refresh_main(start_height, ResetNone);
}
//----------------------------------------------------------------------------------------------------
bool simple_wallet::clear(const std::vector<std::string>& args)
{
#ifdef HAVE_READLINE
PAUSE_READLINE();
rdln::clear_screen();
#endif
tools::clear_screen();
return true;
}
//----------------------------------------------------------------------------------------------------
bool simple_wallet::show_balance_unlocked(bool detailed)
{
std::string extra;
@ -6480,7 +6509,7 @@ void simple_wallet::check_for_inactivity_lock(bool user)
m_in_command = true;
if (!user)
{
const std::string speech = tr("I locked your Monero wallet to protect you while you were away\nsee \"help set\" to configure/disable");
const std::string speech = tr("tis, tis.. you left the wallet unattended. you will be punished.");
std::vector<std::pair<std::string, size_t>> lines = tools::split_string_by_width(speech, 45);
size_t max_len = 0;
@ -6491,11 +6520,51 @@ void simple_wallet::check_for_inactivity_lock(bool user)
for (size_t i = 0; i < lines.size(); ++i)
tools::msg_writer() << (i == 0 ? "/" : i == lines.size() - 1 ? "\\" : "|") << " " << lines[i].first << std::string(max_len - lines[i].second, ' ') << " " << (i == 0 ? "\\" : i == lines.size() - 1 ? "/" : "|");
tools::msg_writer() << " " << std::string(n_u, '-') << std::endl <<
" \\ (__)" << std::endl <<
" \\ (oo)\\_______" << std::endl <<
" (__)\\ )\\/\\" << std::endl <<
" ||----w |" << std::endl <<
" || ||" << std::endl <<
" \\ ~~~^~^. " << std::endl <<
" \\ :5P~~~~~5~. " << std::endl <<
" \\ :~~~~~:~.~~^ " << std::endl <<
" \\ :.& !!@@~~~.. " << std::endl <<
" .:.@#@@@##^:@. " << std::endl <<
" ^^..#@@@@@@?:.^ " << std::endl <<
" ~.^ ^^J #G@@GG?G.: " << std::endl <<
" ~~~~ .B^#5#BBBJ^JPBBB#BP P " << std::endl <<
" ^^^~? ^^^^^.BBBBBBBBBBBBBBB^ @@@~" << std::endl <<
" ^^^: .GG??GG:BBBBBBBB@BBBBBGBP^ ? ^^ " << std::endl <<
" ^^ ^PPPP5P5##BBBBPGJYJBBBBJJ#B ^ ? ^^^ " << std::endl <<
" .. ^?P!Y 5&#BBBPP.!77!BB@!!~ ? ~!?~~ ? " << std::endl <<
" ..^PP 5~..5PPP!:^:.P5:^:.?~!!^~ ? " << std::endl <<
" .! ~!!~Y??5P@@@@PP@@7 ! ~~^^ ~ " << std::endl <<
" .^^. .^ !!!~YJY &@@@@@&&@@ !: ~ ~ " << std::endl <<
" !!~ YJP#&&@@@@&&@@&P.. . ^ " << std::endl <<
" ~!!. P5#BBB&@@@&&@@&@#P ~ " << std::endl <<
" ~~. GBBBBBB&&&&&&&GBB ~ " << std::endl <<
" ^^: PPGBBBBBBPBBGBBBGGJ ? " << std::endl <<
" #5 @BB 555#BPBBBBBBBPBBBB?? " << std::endl <<
" 5##& .@G JGPPPBBBJBPBBBBBB# " << std::endl <<
" &&&&&& & &&&&&B&#& 7 ? G5PPPPPY5PBBB###~ " << std::endl <<
" ?#&&:&&&&&&&@@&&G &&&&B&&B5P&G ? ? GG5PPP5PP @@?B? " << std::endl <<
" #&@@&&&&@&&&&&&G GG&&&& &&&&&&& ?? JGGGGGB :?J7^ " << std::endl <<
" &&P&&G&&&&G&&&&GG GGG&& 5&&&&&P ? 7.~GGB: !J~!^. " << std::endl <<
" &&GJ@G#GY:J&&&PGG GGGGP 5PPP ? .:~!^:77!^. " << std::endl <<
" Y&5G&@@@@@&#&G7#JG GG55 ? .^~~:~~^.::: " << std::endl <<
" #&P&@@^:@@#GG!J@ PP55 ? :::: ..:::^^^ " << std::endl <<
" B&&5!#@@!# GY@@&&&#&&@ &@@@: ? ..:: :^^^^: " << std::endl <<
" #&&##B@@#?@@@&@&&@@&@@@@@@@@@& ? ..::. ::^^ " << std::endl <<
" ###&@@@J?@&@&@@@@@&@@@@@@@@@@@@. .:::: ::: " << std::endl <<
" ##&@@@??&@@@@&@@&&@@@@&@@@@@@@@ :::: :: " << std::endl <<
" B@@@@@?G@@@@@&@@@@@@@@&@@@@&&@@# :::: ::. " << std::endl <<
" @@@@@?@&@@@@@@@@##&&&&&&#B5B&&@& ::: :::Y " << std::endl <<
" B&@@@@?P#&@@&&@@@^BBGB BBBBB#@@@& ::: :: " << std::endl <<
" #&&# . P#&^&@@@@B##B B###B&@@@ ::: YJ " << std::endl <<
" ###P ~ B#B@@@##B ~ ####&@@@ ::: " << std::endl <<
" ?### ~~ ##B@@@~~ B##B#@@@ .::. " << std::endl <<
" ### ^^:#@@@B ####@@& J.:: " << std::endl <<
" ##B ####@@ 5B##&@ ^::: " << std::endl <<
" ##5 ####&@.##### B##@&@@@@@@ J@@ YBBB " << std::endl <<
" ## ###B#&########B###@@@@@@@@@@@@@@@@@ " << std::endl <<
" #P#### @@@ " << std::endl <<
" #G#. ## GB@@@:@ " << std::endl <<
" B B " << std::endl <<
"" << std::endl;
}
while (1)
@ -6681,7 +6750,7 @@ bool simple_wallet::transfer_main(int transfer_type, const std::vector<std::stri
}
else
{
if (boost::starts_with(local_args[i], "monero:"))
if (boost::starts_with(local_args[i], "wownero:"))
fail_msg_writer() << tr("Invalid last argument: ") << local_args.back() << ": " << error;
else
fail_msg_writer() << tr("Invalid last argument: ") << local_args.back();
@ -6917,7 +6986,7 @@ bool simple_wallet::transfer_main(int transfer_type, const std::vector<std::stri
}
else if (m_wallet->multisig())
{
bool r = m_wallet->save_multisig_tx(ptx_vector, "multisig_monero_tx");
bool r = m_wallet->save_multisig_tx(ptx_vector, "multisig_wownero_tx");
if (!r)
{
fail_msg_writer() << tr("Failed to write transaction(s) to file");
@ -6925,7 +6994,7 @@ bool simple_wallet::transfer_main(int transfer_type, const std::vector<std::stri
}
else
{
success_msg_writer(true) << tr("Unsigned transaction(s) successfully written to file: ") << "multisig_monero_tx";
success_msg_writer(true) << tr("Unsigned transaction(s) successfully written to file: ") << "multisig_wownero_tx";
}
}
else if (m_wallet->get_account().get_device().has_tx_cold_sign())
@ -6954,7 +7023,7 @@ bool simple_wallet::transfer_main(int transfer_type, const std::vector<std::stri
}
else if (m_wallet->watch_only())
{
bool r = m_wallet->save_tx(ptx_vector, "unsigned_monero_tx");
bool r = m_wallet->save_tx(ptx_vector, "unsigned_wownero_tx");
if (!r)
{
fail_msg_writer() << tr("Failed to write transaction(s) to file");
@ -6962,7 +7031,7 @@ bool simple_wallet::transfer_main(int transfer_type, const std::vector<std::stri
}
else
{
success_msg_writer(true) << tr("Unsigned transaction(s) successfully written to file: ") << "unsigned_monero_tx";
success_msg_writer(true) << tr("Unsigned transaction(s) successfully written to file: ") << "unsigned_wownero_tx";
}
}
else
@ -7072,26 +7141,26 @@ bool simple_wallet::sweep_unmixable(const std::vector<std::string> &args_)
if (m_wallet->multisig())
{
CHECK_MULTISIG_ENABLED();
bool r = m_wallet->save_multisig_tx(ptx_vector, "multisig_monero_tx");
bool r = m_wallet->save_multisig_tx(ptx_vector, "multisig_wownero_tx");
if (!r)
{
fail_msg_writer() << tr("Failed to write transaction(s) to file");
}
else
{
success_msg_writer(true) << tr("Unsigned transaction(s) successfully written to file: ") << "multisig_monero_tx";
success_msg_writer(true) << tr("Unsigned transaction(s) successfully written to file: ") << "multisig_wownero_tx";
}
}
else if (m_wallet->watch_only())
{
bool r = m_wallet->save_tx(ptx_vector, "unsigned_monero_tx");
bool r = m_wallet->save_tx(ptx_vector, "unsigned_wownero_tx");
if (!r)
{
fail_msg_writer() << tr("Failed to write transaction(s) to file");
}
else
{
success_msg_writer(true) << tr("Unsigned transaction(s) successfully written to file: ") << "unsigned_monero_tx";
success_msg_writer(true) << tr("Unsigned transaction(s) successfully written to file: ") << "unsigned_wownero_tx";
}
}
else
@ -7377,14 +7446,14 @@ bool simple_wallet::sweep_main(uint32_t account, uint64_t below, bool locked, co
if (m_wallet->multisig())
{
CHECK_MULTISIG_ENABLED();
bool r = m_wallet->save_multisig_tx(ptx_vector, "multisig_monero_tx");
bool r = m_wallet->save_multisig_tx(ptx_vector, "multisig_wownero_tx");
if (!r)
{
fail_msg_writer() << tr("Failed to write transaction(s) to file");
}
else
{
success_msg_writer(true) << tr("Unsigned transaction(s) successfully written to file: ") << "multisig_monero_tx";
success_msg_writer(true) << tr("Unsigned transaction(s) successfully written to file: ") << "multisig_wownero_tx";
}
}
else if (m_wallet->get_account().get_device().has_tx_cold_sign())
@ -7414,14 +7483,14 @@ bool simple_wallet::sweep_main(uint32_t account, uint64_t below, bool locked, co
}
else if (m_wallet->watch_only())
{
bool r = m_wallet->save_tx(ptx_vector, "unsigned_monero_tx");
bool r = m_wallet->save_tx(ptx_vector, "unsigned_wownero_tx");
if (!r)
{
fail_msg_writer() << tr("Failed to write transaction(s) to file");
}
else
{
success_msg_writer(true) << tr("Unsigned transaction(s) successfully written to file: ") << "unsigned_monero_tx";
success_msg_writer(true) << tr("Unsigned transaction(s) successfully written to file: ") << "unsigned_wownero_tx";
}
}
else
@ -7612,14 +7681,14 @@ bool simple_wallet::sweep_single(const std::vector<std::string> &args_)
if (m_wallet->multisig())
{
CHECK_MULTISIG_ENABLED();
bool r = m_wallet->save_multisig_tx(ptx_vector, "multisig_monero_tx");
bool r = m_wallet->save_multisig_tx(ptx_vector, "multisig_wownero_tx");
if (!r)
{
fail_msg_writer() << tr("Failed to write transaction(s) to file");
}
else
{
success_msg_writer(true) << tr("Unsigned transaction(s) successfully written to file: ") << "multisig_monero_tx";
success_msg_writer(true) << tr("Unsigned transaction(s) successfully written to file: ") << "multisig_wownero_tx";
}
}
else if (m_wallet->get_account().get_device().has_tx_cold_sign())
@ -7650,14 +7719,14 @@ bool simple_wallet::sweep_single(const std::vector<std::string> &args_)
}
else if (m_wallet->watch_only())
{
bool r = m_wallet->save_tx(ptx_vector, "unsigned_monero_tx");
bool r = m_wallet->save_tx(ptx_vector, "unsigned_wownero_tx");
if (!r)
{
fail_msg_writer() << tr("Failed to write transaction(s) to file");
}
else
{
success_msg_writer(true) << tr("Unsigned transaction(s) successfully written to file: ") << "unsigned_monero_tx";
success_msg_writer(true) << tr("Unsigned transaction(s) successfully written to file: ") << "unsigned_wownero_tx";
}
}
else
@ -7778,7 +7847,7 @@ bool simple_wallet::donate(const std::vector<std::string> &args_)
if (!payment_id_str.empty())
local_args.push_back(payment_id_str);
if (m_wallet->nettype() == cryptonote::MAINNET)
message_writer() << (boost::format(tr("Donating %s %s to The Monero Project (donate.getmonero.org or %s).")) % amount_str % cryptonote::get_unit(cryptonote::get_default_decimal_point()) % MONERO_DONATION_ADDR).str();
message_writer() << (boost::format(tr("Donating %s %s to The Wownero Project (wownero.org or %s).")) % amount_str % cryptonote::get_unit(cryptonote::get_default_decimal_point()) % MONERO_DONATION_ADDR).str();
else
message_writer() << (boost::format(tr("Donating %s %s to %s.")) % amount_str % cryptonote::get_unit(cryptonote::get_default_decimal_point()) % address_str).str();
transfer(local_args);
@ -7969,7 +8038,7 @@ bool simple_wallet::sign_transfer(const std::vector<std::string> &args_)
}
bool export_raw = false;
std::string unsigned_filename = "unsigned_monero_tx";
std::string unsigned_filename = "unsigned_wownero_tx";
if (args_.size() > 2 || (args_.size() == 2 && args_[0] != "export_raw"))
{
PRINT_USAGE(USAGE_SIGN_TRANSFER);
@ -7993,7 +8062,7 @@ bool simple_wallet::sign_transfer(const std::vector<std::string> &args_)
std::vector<tools::wallet2::pending_tx> ptx;
try
{
bool r = m_wallet->sign_tx(unsigned_filename, "signed_monero_tx", ptx, [&](const tools::wallet2::unsigned_tx_set &tx){ return accept_loaded_tx(tx); }, export_raw);
bool r = m_wallet->sign_tx(unsigned_filename, "signed_wownero_tx", ptx, [&](const tools::wallet2::unsigned_tx_set &tx){ return accept_loaded_tx(tx); }, export_raw);
if (!r)
{
fail_msg_writer() << tr("Failed to sign transaction");
@ -8013,7 +8082,7 @@ bool simple_wallet::sign_transfer(const std::vector<std::string> &args_)
txids_as_text += (", ");
txids_as_text += epee::string_tools::pod_to_hex(get_transaction_hash(t.tx));
}
success_msg_writer(true) << tr("Transaction successfully signed to file ") << "signed_monero_tx" << ", txid " << txids_as_text;
success_msg_writer(true) << tr("Transaction successfully signed to file ") << "signed_wownero_tx" << ", txid " << txids_as_text;
if (export_raw)
{
std::string rawfiles_as_text;
@ -8021,7 +8090,7 @@ bool simple_wallet::sign_transfer(const std::vector<std::string> &args_)
{
if (i > 0)
rawfiles_as_text += ", ";
rawfiles_as_text += "signed_monero_tx_raw" + (ptx.size() == 1 ? "" : ("_" + std::to_string(i)));
rawfiles_as_text += "signed_wownero_tx_raw" + (ptx.size() == 1 ? "" : ("_" + std::to_string(i)));
}
success_msg_writer(true) << tr("Transaction raw hex data exported to ") << rawfiles_as_text;
}
@ -8041,7 +8110,7 @@ bool simple_wallet::submit_transfer(const std::vector<std::string> &args_)
try
{
std::vector<tools::wallet2::pending_tx> ptx_vector;
bool r = m_wallet->load_tx("signed_monero_tx", ptx_vector, [&](const tools::wallet2::signed_tx_set &tx){ return accept_loaded_tx(tx); });
bool r = m_wallet->load_tx("signed_wownero_tx", ptx_vector, [&](const tools::wallet2::signed_tx_set &tx){ return accept_loaded_tx(tx); });
if (!r)
{
fail_msg_writer() << tr("Failed to load transaction from file");
@ -8215,7 +8284,7 @@ bool simple_wallet::get_tx_proof(const std::vector<std::string> &args)
try
{
std::string sig_str = m_wallet->get_tx_proof(txid, info.address, info.is_subaddress, args.size() == 3 ? args[2] : "");
const std::string filename = "monero_tx_proof";
const std::string filename = "wownero_tx_proof";
if (m_wallet->save_to_file(filename, sig_str, true))
success_msg_writer() << tr("signature file saved to: ") << filename;
else
@ -8427,7 +8496,7 @@ bool simple_wallet::get_spend_proof(const std::vector<std::string> &args)
try
{
const std::string sig_str = m_wallet->get_spend_proof(txid, args.size() == 2 ? args[1] : "");
const std::string filename = "monero_spend_proof";
const std::string filename = "wownero_spend_proof";
if (m_wallet->save_to_file(filename, sig_str, true))
success_msg_writer() << tr("signature file saved to: ") << filename;
else
@ -8516,7 +8585,7 @@ bool simple_wallet::get_reserve_proof(const std::vector<std::string> &args)
try
{
const std::string sig_str = m_wallet->get_reserve_proof(account_minreserve, args.size() == 2 ? args[1] : "");
const std::string filename = "monero_reserve_proof";
const std::string filename = "wownero_reserve_proof";
if (m_wallet->save_to_file(filename, sig_str, true))
success_msg_writer() << tr("signature file saved to: ") << filename;
else
@ -9410,12 +9479,25 @@ std::string simple_wallet::get_prompt() const
if (m_locked)
return std::string("[") + tr("locked due to inactivity") + "]";
std::string addr_start = m_wallet->get_subaddress_as_str({m_current_subaddress_account, 0}).substr(0, 6);
std::string prompt = std::string("[") + tr("wallet") + " " + addr_start;
std::string prompt = std::string("[") + tr("account: ") + addr_start;
// Detailed prompt: [account: 4......] [wallet: <file_basename>] [block: xxx]:
const bool show_detailed_prompt = m_wallet->show_detailed_prompt();
if (show_detailed_prompt)
{
std::string path = m_wallet->get_wallet_file();
std::string wallet = path.substr(path.find_last_of("/\\") + 1);
std::string block = std::to_string(m_wallet->get_blockchain_current_height());
prompt += std::string("] [") + tr("wallet: ") + wallet;
prompt += std::string("] [") + tr("block: ") + block;
}
if (!m_wallet->check_connection(NULL))
prompt += tr(" (no daemon)");
else if (!m_wallet->is_synced())
prompt += tr(" (out of sync)");
prompt += "]: ";
{
prompt += tr("] (no daemon): ");
} else if (!m_wallet->is_synced()) {
prompt += tr("] (out of sync): ");
} else {
prompt += "]: ";
}
return prompt;
}
//----------------------------------------------------------------------------------------------------
@ -10606,7 +10688,7 @@ void simple_wallet::commit_or_save(std::vector<tools::wallet2::pending_tx>& ptx_
cryptonote::blobdata blob;
tx_to_blob(ptx.tx, blob);
const std::string blob_hex = epee::string_tools::buff_to_hex_nodelimer(blob);
const std::string filename = "raw_monero_tx" + (ptx_vector.size() == 1 ? "" : ("_" + std::to_string(i++)));
const std::string filename = "raw_wownero_tx" + (ptx_vector.size() == 1 ? "" : ("_" + std::to_string(i++)));
if (m_wallet->save_to_file(filename, blob_hex, true))
success_msg_writer(true) << tr("Transaction successfully saved to ") << filename << tr(", txid ") << txid;
else
@ -10667,12 +10749,12 @@ int main(int argc, char* argv[])
bool should_terminate = false;
std::tie(vm, should_terminate) = wallet_args::main(
argc, argv,
"monero-wallet-cli [--wallet-file=<filename>|--generate-new-wallet=<filename>] [<COMMAND>]",
sw::tr("This is the command line monero wallet. It needs to connect to a monero\ndaemon to work correctly.\nWARNING: Do not reuse your Monero keys on another fork, UNLESS this fork has key reuse mitigations built in. Doing so will harm your privacy."),
"wownero-wallet-cli [--wallet-file=<filename>|--generate-new-wallet=<filename>] [<COMMAND>]",
sw::tr("This is the command line wownero wallet. It needs to connect to a wownero\ndaemon to work correctly."),
desc_params,
positional_options,
[](const std::string &s, bool emphasis){ tools::scoped_message_writer(emphasis ? epee::console_color_white : epee::console_color_default, true) << s; },
"monero-wallet-cli.log"
"wownero-wallet-cli.log"
);
if (!vm)
@ -10859,7 +10941,7 @@ void simple_wallet::list_mms_messages(const std::vector<mms::message> &messages)
void simple_wallet::list_signers(const std::vector<mms::authorized_signer> &signers)
{
message_writer() << boost::format("%2s %-20s %-s") % tr("#") % tr("Label") % tr("Transport Address");
message_writer() << boost::format("%2s %-20s %-s") % "" % tr("Auto-Config Token") % tr("Monero Address");
message_writer() << boost::format("%2s %-20s %-s") % "" % tr("Auto-Config Token") % tr("Wownero Address");
for (size_t i = 0; i < signers.size(); ++i)
{
const mms::authorized_signer &signer = signers[i];
@ -11065,7 +11147,7 @@ void simple_wallet::mms_signer(const std::vector<std::string> &args)
}
if ((args.size() < 2) || (args.size() > 4))
{
fail_msg_writer() << tr("mms signer [<number> <label> [<transport_address> [<monero_address>]]]");
fail_msg_writer() << tr("mms signer [<number> <label> [<transport_address> [<wownero_address>]]]");
return;
}
@ -11084,14 +11166,14 @@ void simple_wallet::mms_signer(const std::vector<std::string> &args)
bool ok = cryptonote::get_account_address_from_str_or_url(info, m_wallet->nettype(), args[3], oa_prompter);
if (!ok)
{
fail_msg_writer() << tr("Invalid Monero address");
fail_msg_writer() << tr("Invalid Wownero address");
return;
}
monero_address = info.address;
const std::vector<mms::message> &messages = ms.get_all_messages();
if ((messages.size() > 0) || state.multisig)
{
fail_msg_writer() << tr("Wallet state does not allow changing Monero addresses anymore");
fail_msg_writer() << tr("Wallet state does not allow changing Wownero addresses anymore");
return;
}
}

@ -53,7 +53,7 @@
#undef MONERO_DEFAULT_LOG_CATEGORY
#define MONERO_DEFAULT_LOG_CATEGORY "wallet.simplewallet"
// Hardcode Monero's donation address (see #1447)
constexpr const char MONERO_DONATION_ADDR[] = "888tNkZrPN6JsEgekjMnABU4TBzc2Dt29EPAvkRxbANsAnjyPbb3iQ1YBRk1UXcdRsiKc9dhwMVgN5S9cQUiyoogDavup3H";
constexpr const char MONERO_DONATION_ADDR[] = "Wo3MWeKwtA918DU4c69hVSNgejdWFCRCuWjShRY66mJkU2Hv58eygJWDJS1MNa2Ge5M1WjUkGHuLqHkweDxwZZU42d16v94mP";
/*!
* \namespace cryptonote
@ -148,6 +148,7 @@ namespace cryptonote
bool set_ignore_outputs_below(const std::vector<std::string> &args = std::vector<std::string>());
bool set_track_uses(const std::vector<std::string> &args = std::vector<std::string>());
bool set_show_wallet_name_when_locked(const std::vector<std::string> &args = std::vector<std::string>());
bool set_show_detailed_prompt(const std::vector<std::string> &args = std::vector<std::string>());
bool set_inactivity_lock_timeout(const std::vector<std::string> &args = std::vector<std::string>());
bool set_setup_background_mining(const std::vector<std::string> &args = std::vector<std::string>());
bool set_device_name(const std::vector<std::string> &args = std::vector<std::string>());
@ -165,6 +166,7 @@ namespace cryptonote
bool set_daemon(const std::vector<std::string> &args);
bool save_bc(const std::vector<std::string> &args);
bool refresh(const std::vector<std::string> &args);
bool clear(const std::vector<std::string> &args);
bool show_balance_unlocked(bool detailed = false);
bool show_balance(const std::vector<std::string> &args = std::vector<std::string>());
bool show_incoming_transfers(const std::vector<std::string> &args);

@ -1,6 +1,6 @@
#define DEF_MONERO_VERSION_TAG "@VERSIONTAG@"
#define DEF_MONERO_VERSION "0.18.2.0"
#define DEF_MONERO_RELEASE_NAME "Fluorine Fermi"
#define DEF_MONERO_VERSION "0.11.0.0"
#define DEF_MONERO_RELEASE_NAME "Kunty Karen"
#define DEF_MONERO_VERSION_FULL DEF_MONERO_VERSION "-" DEF_MONERO_VERSION_TAG
#define DEF_MONERO_VERSION_IS_RELEASE @VERSION_IS_RELEASE@

@ -100,7 +100,7 @@ if(NOT IOS)
${EXTRA_LIBRARIES})
set_property(TARGET wallet_rpc_server
PROPERTY
OUTPUT_NAME "monero-wallet-rpc")
OUTPUT_NAME "wownero-wallet-rpc")
install(TARGETS wallet_rpc_server DESTINATION bin)
endif()

@ -35,12 +35,16 @@ set(wallet_api_sources
wallet_manager.cpp
transaction_info.cpp
transaction_history.cpp
transaction_construction_info.cpp
pending_transaction_info.cpp
pending_transaction.cpp
utils.cpp
address_book.cpp
subaddress.cpp
subaddress_account.cpp
unsigned_transaction.cpp)
unsigned_transaction.cpp
coins.cpp
coins_info.cpp)
set(wallet_api_headers
wallet2_api.h)
@ -50,12 +54,16 @@ set(wallet_api_private_headers
wallet_manager.h
transaction_info.h
transaction_history.h
transaction_construction_info.h
pending_transaction_info.h
pending_transaction.h
common_defines.h
address_book.h
subaddress.h
subaddress_account.h
unsigned_transaction.h)
unsigned_transaction.h
coins.h
coins_info.h)
monero_private_headers(wallet_api
${wallet_api_private_headers})

@ -0,0 +1,122 @@
#include "coins.h"
#include "coins_info.h"
#include "wallet.h"
#include "crypto/hash.h"
#include "wallet/wallet2.h"
#include "common_defines.h"
#include <string>
#include <vector>
using namespace epee;
namespace Monero {
Coins::~Coins() = default;
CoinsImpl::CoinsImpl(WalletImpl *wallet)
: m_wallet(wallet) {}
CoinsImpl::~CoinsImpl()
{
for (auto t : m_rows)
delete t;
}
int CoinsImpl::count() const
{
boost::shared_lock<boost::shared_mutex> lock(m_rowsMutex);
int result = m_rows.size();
return result;
}
CoinsInfo *CoinsImpl::coin(int index) const
{
boost::shared_lock<boost::shared_mutex> lock(m_rowsMutex);
// sanity check
if (index < 0)
return nullptr;
auto index_ = static_cast<unsigned>(index);
return index_ < m_rows.size() ? m_rows[index_] : nullptr;
}
std::vector<CoinsInfo *> CoinsImpl::getAll() const
{
boost::shared_lock<boost::shared_mutex> lock(m_rowsMutex);
return m_rows;
}
void CoinsImpl::refresh()
{
LOG_PRINT_L2("Refreshing coins");
boost::unique_lock<boost::shared_mutex> lock(m_rowsMutex);
boost::shared_lock<boost::shared_mutex> transfers_lock(m_wallet->m_wallet->m_transfers_mutex);
// delete old outputs;
for (auto t : m_rows)
delete t;
m_rows.clear();
for (size_t i = 0; i < m_wallet->m_wallet->get_num_transfer_details(); ++i)
{
const tools::wallet2::transfer_details &td = m_wallet->m_wallet->get_transfer_details(i);
auto ci = new CoinsInfoImpl();
ci->m_blockHeight = td.m_block_height;
ci->m_hash = string_tools::pod_to_hex(td.m_txid);
ci->m_internalOutputIndex = td.m_internal_output_index;
ci->m_globalOutputIndex = td.m_global_output_index;
ci->m_spent = td.m_spent;
ci->m_frozen = td.m_frozen;
ci->m_spentHeight = td.m_spent_height;
ci->m_amount = td.m_amount;
ci->m_rct = td.m_rct;
ci->m_keyImageKnown = td.m_key_image_known;
ci->m_pkIndex = td.m_pk_index;
ci->m_subaddrIndex = td.m_subaddr_index.minor;
ci->m_subaddrAccount = td.m_subaddr_index.major;
ci->m_address = m_wallet->m_wallet->get_subaddress_as_str(td.m_subaddr_index); // todo: this is expensive, cache maybe?
ci->m_addressLabel = m_wallet->m_wallet->get_subaddress_label(td.m_subaddr_index);
ci->m_keyImage = string_tools::pod_to_hex(td.m_key_image);
ci->m_unlockTime = td.m_tx.unlock_time;
ci->m_unlocked = m_wallet->m_wallet->is_transfer_unlocked(td);
ci->m_pubKey = string_tools::pod_to_hex(td.get_public_key());
ci->m_coinbase = td.m_tx.vin.size() == 1 && td.m_tx.vin[0].type() == typeid(cryptonote::txin_gen);
m_rows.push_back(ci);
}
}
void CoinsImpl::setFrozen(int index)
{
try
{
m_wallet->m_wallet->freeze(index);
refresh();
}
catch (const std::exception& e)
{
LOG_ERROR("setLabel: " << e.what());
}
}
void CoinsImpl::thaw(int index)
{
try
{
m_wallet->m_wallet->thaw(index);
refresh();
}
catch (const std::exception& e)
{
LOG_ERROR("thaw: " << e.what());
}
}
bool CoinsImpl::isTransferUnlocked(uint64_t unlockTime, uint64_t blockHeight) {
return m_wallet->m_wallet->is_transfer_unlocked(unlockTime, blockHeight);
}
} // namespace

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

Loading…
Cancel
Save