Compare commits

..

90 Commits

Author SHA1 Message Date
selsta
1b8475003c wallet2: fix refresh function parameters
max_blocks is last on master branch
2023-10-03 06:11:50 +03:00
Boog900
c1093aa33d Fix: long term block weight cache
The long term block weight cache was doing a wrong calculation when
adding a new block to the cache.
2023-10-03 06:11:35 +03:00
Boog900
650cef2279 add a test for the long term weight cache 2023-10-03 06:11:13 +03:00
wowario
3c329005f5 add more seeds 2023-10-03 06:09:10 +03:00
wowario
56b5d10b41 disable mismatched daemon check 2023-10-03 06:09:02 +03:00
wowario
bae8df3f21 remove nudge in daemon_is_outdated 2023-10-02 05:37:52 +03:00
wowario
8f6e5fb500 [README] bump version 2023-10-02 05:23:21 +03:00
wowario
b322839951 update checkpoints 2023-10-02 05:16:02 +03:00
wowario
1e5184a63a remove nudge in num_mainnet_hard_forks 2023-10-02 04:45:17 +03:00
_XxFedexX_
87be033224 Add _xxfedexx_'s PGP key 2023-10-01 22:13:47 +03:00
wowario
c1488d7896 remove rx_set code 2023-10-01 20:00:01 +03:00
wowario
140a5e430a use rx_set_miner_thread after RX_BLOCK_VERSION 2023-10-01 19:51:56 +03:00
thotbot
378e241ff6 Import transaction 2023-10-01 16:46:15 +03:00
wowario
b403a4e6d4 show wallet info 2023-10-01 16:28:28 +03:00
hinto-janaiyo
35a6b6c825 simplewallet/wallet2: set option - show-detailed-prompt 2023-10-01 16:28:12 +03:00
moneromooo-monero
bfc28a3bfe blockchain_prune: faster
on my anecdotal SSD, goes from about 9 hours to 1h20.
2023-10-01 16:27:50 +03:00
moneromooo-monero
27a9a417dc simplewallet: print fully qualified filename for new wallets
from time to time, some people don't realize their wallets get
created in their current working directory
2023-10-01 16:27:07 +03:00
thotbot
e3d5e895cd Misc. network related
- Add interface for bytes sent/received
- Allow wallet refresh while daemon is not synchronized
- emit success boolean for refreshed()
- don't call refreshThreadFunc (we don't need it)
- lower rpc timeout from 3m30s (?!) to 10 seconds
2023-10-01 16:26:03 +03:00
thotbot
5b9e342966 Skip unneeded blocks in fast refresh 2023-10-01 16:25:00 +03:00
thotbot
dc44ccad2d subaddressIndex() 2023-10-01 16:24:31 +03:00
thotbot
fad6c11b6f Print wallet cache 2023-10-01 16:24:17 +03:00
thotbot
493608203f Misc. wallet API and wallet2 changes 2023-10-01 16:23:47 +03:00
thotbot
ce32e59844 Coins 2023-10-01 16:23:32 +03:00
thotbot
c7c1558c1d Offline transaction signing 2023-10-01 16:23:16 +03:00
wowario
176ed83a39 update checkpoints 2023-10-01 16:17:41 +03:00
wowario
51e192d2cc connect to updated seeds 2023-10-01 16:05:16 +03:00
wowario
2ebf9fcfe9 add wowario PGP key 2023-10-01 16:02:49 +03:00
w0wΔri0
938420b2e6 Revoke old pgp key 2023-10-01 16:01:31 +03:00
wowario
4679496727 support old ass BPs 2023-10-01 15:58:35 +03:00
wowario
8780f9fb30 revert sanity check 2023-10-01 15:58:10 +03:00
wowario
7cd57d6479 wallet seed message spacing 2023-10-01 15:57:11 +03:00
wowario
6e22bcadd9 remove warning reusing keys 2023-10-01 15:56:30 +03:00
wowario
02c36da7e5 remove warning about background mining 2023-10-01 15:56:19 +03:00
wowario
d3e753deb5 add clear screen command 2023-10-01 15:56:00 +03:00
wowario
487418b952 wownero chan 2023-10-01 15:54:48 +03:00
wowario
748d6a3184 update README.md 2023-10-01 15:54:20 +03:00
wowario
7ab0cbb19e update checkpoints 2023-10-01 15:53:59 +03:00
wowario
31c5ba00d5 set fork height 2023-10-01 15:53:18 +03:00
wowario
c80566ca00 from v20, limit tx extra size 2023-10-01 15:51:18 +03:00
wowario
dcafb09415 Debug level No incoming connections 2023-10-01 15:49:56 +03:00
wowario
ae54f2e737 update checkpoints 2023-10-01 15:49:37 +03:00
wowario
e1f25be028 uri remainder 2023-10-01 15:49:22 +03:00
wowario
3b15bb4696 update README.md 2023-10-01 15:48:49 +03:00
wowario
e00a7d1638 remove testnet/stagenet fork heights/blocks 2023-10-01 15:45:08 +03:00
wowario
c69dc334fb don't request pre-bulletprooof pruned blocks 2023-10-01 15:44:05 +03:00
wowario
89c0a9de4c change to debug level 2023-10-01 15:43:51 +03:00
wowario
7174ff9bcb rename ringdb-dir 2023-10-01 15:43:21 +03:00
wowario
0fc75eb44e mod variant4_random_math 2023-10-01 15:41:50 +03:00
wowario
fe05821c19 support old BP 2023-10-01 15:41:22 +03:00
wowario
daddd7d231 vote by block 2023-10-01 15:40:48 +03:00
wowario
0871203167 tidy up miner msgs 2023-10-01 15:40:30 +03:00
wowario
de2a8c65cf miner block header signing 2023-10-01 15:40:16 +03:00
wowario
2e18be9977 difficulty is fun 2023-10-01 15:39:53 +03:00
wowario
67f16d765c shorten timestamp check window 2023-10-01 15:39:42 +03:00
wowario
d81ef76d7c limit future blk time to 10 min 2023-10-01 15:39:13 +03:00
wowario
39809d46c6 bump unlock time to 288 blks 2023-10-01 15:39:02 +03:00
wowario
8243f192ab broadcast donation sub-address 2023-10-01 15:38:45 +03:00
wowario
bb391f0d00 revert Preserve commitment format inside transactions #8277 2023-10-01 15:38:19 +03:00
wowario
052e775d24 add systemd file 2023-10-01 15:37:26 +03:00
wowario
2adf97e0d3 update gitian 2023-10-01 15:37:07 +03:00
wowario
b3ce01e702 update Dockerfile 2023-10-01 15:36:34 +03:00
wowario
6a6f6c1424 adjust approx_blockchain_height 2023-10-01 15:35:52 +03:00
wowario
9b2d897043 add wowario gpg key 2023-10-01 15:35:35 +03:00
wowario
37169ebb39 config wallet2 settings 2023-10-01 15:35:23 +03:00
wowario
c92464e27f set dev fund address 2023-10-01 15:34:46 +03:00
wowario
ae7c139056 add seed nodes 2023-10-01 15:34:23 +03:00
wowario
add841d552 set name of daemon stdout 2023-10-01 15:33:36 +03:00
wowario
31f59338d3 set last v1 block 2023-10-01 15:32:54 +03:00
wowario
c9b8d94e83 set pow variants 2023-10-01 15:32:08 +03:00
wowario
8498370447 set quick height for syncing 2023-10-01 15:31:42 +03:00
wowario
c1ef123bad send dump log to wowario 2023-10-01 15:30:46 +03:00
wowario
065e89580f set genesis block timestamp 2023-10-01 15:30:03 +03:00
wowario
5d369a5bf3 set decimal point 2023-10-01 15:29:44 +03:00
wowario
07e3c1a9b8 add forks and checkpoints 2023-10-01 15:25:59 +03:00
wowario
ad27e5892b wownero skin pack 2023-10-01 15:14:40 +03:00
wowario
10f22a4267 bump RX block version 2023-10-01 14:53:51 +03:00
wowario
3709b2684b correct length of addresses 2023-10-01 14:53:30 +03:00
wowario
0901cd95c9 move utilities to debug build 2023-10-01 14:53:07 +03:00
wowario
67e03a315a automatic submodule update 2023-10-01 14:52:54 +03:00
wowario
36edf137e4 Doxygen off 2023-10-01 14:52:22 +03:00
wowario
f36d2f79b8 trezor support off 2023-10-01 14:52:08 +03:00
wowario
d890edf7db turn off tests 2023-10-01 14:51:33 +03:00
wowario
6e1158eaa4 gitian: copy config file 2023-10-01 14:51:21 +03:00
wowario
d1387cbadc add RandomWOW 2023-10-01 14:50:34 +03:00
wowario
82a019cd12 show full version 2023-10-01 14:48:45 +03:00
wowario
b83ff851d2 remove moneropulse urls 2023-10-01 14:48:33 +03:00
wowario
95e7407aa1 remove monero tx bug fixes 2023-10-01 14:44:46 +03:00
wowario
5f6703f2c2 bump ring size to 22 2023-10-01 14:44:21 +03:00
wowario
4c6e685174 initialize genesis block 2023-10-01 14:43:05 +03:00
wowario
92ebb323e1 config cryptonote 2023-10-01 14:42:42 +03:00
154 changed files with 2642 additions and 2084 deletions

4
.gitmodules vendored
View File

@@ -14,6 +14,6 @@
branch = monero
[submodule "external/randomwow"]
path = external/randomwow
url = https://codeberg.org/wownero/RandomWOW
branch = 1.2.1-wow
url = https://git.wownero.com/wownero/RandomWOW
branch = 1.1.10-wow

View File

@@ -1076,38 +1076,26 @@ if(STATIC)
set(Boost_USE_STATIC_LIBS ON)
set(Boost_USE_STATIC_RUNTIME ON)
endif()
# Find Boost headers
set(BOOST_MIN_VER 1.62)
find_package(Boost ${BOOST_MIN_VER} QUIET REQUIRED)
if(NOT Boost_FOUND)
die("Could not find Boost libraries, please make sure you have installed Boost or libboost-all-dev (>=${BOOST_MIN_VER}) or the equivalent")
elseif(Boost_FOUND)
message(STATUS "Found Boost Version: ${Boost_VERSION_STRING}")
set(BOOST_COMPONENTS filesystem thread date_time chrono serialization program_options locale)
# Boost System is header-only since 1.69
if (Boost_VERSION_STRING VERSION_LESS 1.69.0)
list(APPEND BOOST_COMPONENTS system)
endif()
# Boost Regex is header-only since 1.77
if (Boost_VERSION_STRING VERSION_LESS 1.77.0)
list(APPEND BOOST_COMPONENTS regex)
endif()
message(STATUS "Boost components: ${BOOST_COMPONENTS}")
# Find required Boost libraries
find_package(Boost ${BOOST_MIN_VER} QUIET REQUIRED COMPONENTS ${BOOST_COMPONENTS})
set(CMAKE_FIND_LIBRARY_SUFFIXES ${OLD_LIB_SUFFIXES})
endif()
find_package(Boost 1.58 QUIET REQUIRED COMPONENTS system filesystem thread date_time chrono regex serialization program_options locale)
add_definitions(-DBOOST_ASIO_ENABLE_SEQUENTIAL_STRAND_ALLOCATION)
add_definitions(-DBOOST_NO_AUTO_PTR)
add_definitions(-DBOOST_UUID_DISABLE_ALIGNMENT) # This restores UUID's std::has_unique_object_representations property
set(CMAKE_FIND_LIBRARY_SUFFIXES ${OLD_LIB_SUFFIXES})
if(NOT Boost_FOUND)
die("Could not find Boost libraries, please make sure you have installed Boost or libboost-all-dev (>=1.58) or the equivalent")
elseif(Boost_FOUND)
message(STATUS "Found Boost Version: ${Boost_VERSION}")
if (Boost_VERSION VERSION_LESS 10 AND Boost_VERSION VERSION_LESS 1.62.0 AND NOT (OPENSSL_VERSION VERSION_LESS 1.1))
set(BOOST_BEFORE_1_62 true)
endif()
if (NOT Boost_VERSION VERSION_LESS 10 AND Boost_VERSION VERSION_LESS 106200 AND NOT (OPENSSL_VERSION VERSION_LESS 1.1))
set(BOOST_BEFORE_1_62 true)
endif()
if (BOOST_BEFORE_1_62)
message(FATAL_ERROR "Boost ${Boost_VERSION} (older than 1.62) is too old to link with OpenSSL ${OPENSSL_VERSION} (1.1 or newer) found at ${OPENSSL_INCLUDE_DIR} and ${OPENSSL_LIBRARIES}. "
"Update Boost or install OpenSSL 1.0 and set path to it when running cmake: "
"cmake -DOPENSSL_ROOT_DIR='/usr/include/openssl-1.0'")
endif()
endif()
include_directories(SYSTEM ${Boost_INCLUDE_DIRS})
if(MINGW)
@@ -1201,7 +1189,6 @@ endif()
if(NOT ZMQ_LIB)
message(FATAL_ERROR "Could not find required libzmq")
endif()
include_directories(${ZMQ_INCLUDE_PATH})
if(PGM_LIBRARY)
set(ZMQ_LIB "${ZMQ_LIB};${PGM_LIBRARY}")
endif()
@@ -1215,15 +1202,7 @@ if(PROTOLIB_LIBRARY)
set(ZMQ_LIB "${ZMQ_LIB};${PROTOLIB_LIBRARY}")
endif()
if(SODIUM_LIBRARY)
message(STATUS "ZMQ_LIB: ${ZMQ_LIB};${SODIUM_LIBRARY}")
set(ZMQ_LIB "${ZMQ_LIB};${SODIUM_LIBRARY}")
find_path(SODIUM_INCLUDE_PATH sodium/crypto_verify_32.h)
if (SODIUM_INCLUDE_PATH)
message(STATUS "SODIUM_INCLUDE_PATH: ${SODIUM_INCLUDE_PATH}")
include_directories(${SODIUM_INCLUDE_PATH})
else()
message(FATAL_ERROR "Could not find required sodium/crypto_verify_32.h")
endif()
endif()
if(BSD_LIBRARY)
set(ZMQ_LIB "${ZMQ_LIB};${BSD_LIBRARY}")

View File

@@ -48,7 +48,7 @@ all: release-all
depends:
cd contrib/depends && $(MAKE) HOST=$(target) && cd ../.. && mkdir -p build/$(target)/release
cd build/$(target)/release && USE_DEVICE_TREZOR_MANDATORY=1 cmake -DCMAKE_TOOLCHAIN_FILE=$(CURDIR)/contrib/depends/$(target)/share/toolchain.cmake ../../.. && $(MAKE)
cd build/$(target)/release && cmake -DCMAKE_TOOLCHAIN_FILE=$(CURDIR)/contrib/depends/$(target)/share/toolchain.cmake ../../.. && $(MAKE)
cmake-debug:
mkdir -p $(builddir)/debug
@@ -104,7 +104,7 @@ release-all:
release-static:
mkdir -p $(builddir)/release
cd $(builddir)/release && cmake -D BUILD_TESTS=OFF -D USE_DEVICE_TREZOR=OFF -D STATIC=ON -D BUILD_64=ON -D CMAKE_BUILD_TYPE=Release $(topdir) && $(MAKE)
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

View File

@@ -1,12 +1,7 @@
# ~~Mo~~Wownero - Such privacy! Many coins! Wow!
# ~~Mo~~Wownero - Such privacy! Many coins! Wow! 🐕
[<img src="https://suchwow.xyz/data/suchwow/image/to23moqn.jpeg">](https://suchwow.xyz/s/oh-really-9eda16b2/item)
## Introduction
Wownero is a Doge-inspired, CPU-mineable, solo-mining only, privacy-respecting memecoin. It was fairly launched on April Fools' Day in 2018. It is a software fork of Monero, but with a lite version of RandomX, larger ring size, and a fixed supply of 184 million coins emitted over 50 years. Wownero has no trusted setup, premine, or dev tax. Besides betting on online snail racing, the main use case of Wownero is micro-tipping meme creators with sound magic internet money. As a 100% community-driven, free and open source software, Wownero does not depend on billionaire shills or lame ass "influencers."
Unlike Opposing Projects.
Copyright (c) 2014-2023 The Monero Project.
Portions Copyright (c) 2012-2013 The Cryptonote developers.
## Resources
@@ -15,30 +10,33 @@ Unlike Opposing Projects.
- Twitter: [@w0wn3r0](https://twitter.com/w0wn3r0)
- Reddit: [/r/wownero](https://www.reddit.com/r/wownero)
- Mail: [wownero@wownero.org](mailto:wownero@wownero.org)
- Git: [codeberg.org/wownero/wownero](https://codeberg.org/wownero/wownero)
- 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)
- Public Node Status: [monero.fail](https://monero.fail/?chain=wownero&network=mainnet)
- 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
- [NonKYC](https://nonkyc.io/market/WOW_BTC)
- [AltQuick](https://altquick.com/market/Wownero)
- [Majestic Bank](https://majesticbank.sc)
- [TradeOgre](https://tradeogre.com/exchange/BTC-WOW)
## Wallets
### Blockchain Explorers
- Wonero CLI Wallet: [codeberg.org/wownero/wownero](https://codeberg.org/wownero/wownero/releases)
- Wowlet Desktop Wallet: [codeberg.org/wownero/wowlet](https://codeberg.org/wownero/wowlet/releases)
- Stack Wallet iOS & Android Mobile Wallet: [stackwallet.com](https://stackwallet.com)
- Cake Wallet [cakewallet.com](https://cakewallet.com)
- https://explore.wownero.com
- https://muchwow.lol
## Blockchain Explorers
## Introduction
- https://explorer.suchwow.xyz
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.
## Supporting the project
@@ -47,8 +45,11 @@ Wownero is a 100% community-sponsored endeavor. Supporting services are also gra
[<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)
Developers are volunteers doing this mostly for shits and giggles. If you would like to support our shenanigans and stimulant addictions, please consider donating to the dev slush fund.
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.
### Donation Addresses
@@ -62,13 +63,19 @@ XMR: `44SQVPGLufPasUcuUQSZiF5c9BFzjcP8ucDxzzFDgLf1VkCEFaidJ3u2AhSKMhPLKA3jc2iS8w
BTC: `bc1qcw9zglp3fxyl25zswemw7jczlqryms2lsmu464`
### Open Collective
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.
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.
## Release staging and Contributing
**Anyone is welcome to contribute to Wownero's codebase!**
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.
Things to Do, Work in Progress, and Help Wanted tasks are tracked in the [Meta](https://codeberg.org/wownero/meta/issues) repo.
Things to Do, Work in Progress, and Help Wanted tasks are tracked in the [Meta](https://git.wownero.com/wownero/meta/issues) repo.
Join `#wownero` on IRC OFTC to participate in development conversation.
@@ -77,7 +84,7 @@ Join `#wownero` on IRC OFTC to participate in development conversation.
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 | Release Name | Minimum Wownero version | Recommended Wownero version | Details |
| 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
@@ -89,12 +96,14 @@ Dates are provided in the format YYYY-MM-DD.
| - | 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.3.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
| 514,000 | 2023-04-01 | Kunty Karen | v0.11.0.0 | v0.11.1.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
## Installing from a package
Packages are available for
* Arch Linux/Manjaro
@@ -122,22 +131,21 @@ Packaging for your favorite distribution would be a welcome contribution!
* Docker
git clone https://codeberg.org/wownero/wownero && cd wownero
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
* Arch Linux/Manjaro
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 gcc13
git clone https://codeberg.org/wownero/wownero && cd wownero
export CC=gcc-13 CXX=g++-13
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
* 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 gcc-13 g++-13
git clone https://codeberg.org/wownero/wownero && cd wownero
CC="gcc-13" CXX="g++-13" make -j2
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
## Running Binaries
@@ -160,7 +168,7 @@ To run in background:
To run as a systemd service, copy
[wownerod.service](utils/systemd/wownerod.service) to `/etc/systemd/system/` and
[wow.conf](utils/conf/wow.conf) to `/etc/`. The [example
[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](wow.conf).
@@ -188,7 +196,7 @@ HiddenServiceVersion 3
save and close nano
* `sudo /etc/init.d/tor restart && sudo systemctl enable tor`
* copy [wow.conf](utils/conf/wow.conf) file and save it in same directory as `wownerod`.
* 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:
```
@@ -196,16 +204,14 @@ save and close nano
```
* `sudo cat /var/lib/tor/wownero/hostname`
Copy your onion address and share node with others [here](https://monero.fail/?crypto=wownero).
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)
To share your node over p2p, uncomment first line of wownerod.conf and add your onion address.
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)
### Access remote Tor node from CLI wallet
```
./wownero-wallet-cli --proxy 127.0.0.1:9050 --daemon-address iy6ry6uudpzvbd72zsipepukp6nsazjdu72n52vg3isfnxqn342flzad.onion:34568
```
Copyright (c) 2014-2024 The Monero Project.
Portions Copyright (c) 2012-2013 The Cryptonote developers.

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -74,7 +74,6 @@ namespace epee
public:
using char_type = std::uint8_t;
using Ch = char_type;
using value_type = char_type;
//! Increase internal buffer by at least `byte_stream_increase` bytes.
byte_stream() noexcept
@@ -87,7 +86,6 @@ namespace epee
~byte_stream() noexcept = default;
byte_stream& operator=(byte_stream&& rhs) noexcept;
std::uint8_t* data() noexcept { return buffer_.get(); }
const std::uint8_t* data() const noexcept { return buffer_.get(); }
std::uint8_t* tellp() const noexcept { return next_write_; }
std::size_t available() const noexcept { return end_ - next_write_; }

View File

@@ -171,13 +171,6 @@
epee::serialization::store_t_to_json(static_cast<epee::json_rpc::error_response&>(rsp), response_info.m_body); \
return true; \
} \
epee::serialization::storage_entry params_; \
params_ = epee::serialization::storage_entry(epee::serialization::section()); \
if(!ps.get_value("params", params_, nullptr)) \
{ \
epee::serialization::section params_section; \
ps.set_value("params", std::move(params_section), nullptr); \
} \
if(false) return true; //just a stub to have "else if"

View File

@@ -98,18 +98,16 @@ public: \
#define KV_SERIALIZE_VAL_POD_AS_BLOB_FORCE_N(varialble, val_name) \
epee::serialization::selector<is_store>::serialize_t_val_as_blob(this_ref.varialble, stg, hparent_section, val_name);
#define KV_SERIALIZE_VAL_POD_AS_BLOB_N(variable, val_name) \
static_assert(std::is_trivially_copyable<decltype(this_ref.variable)>(), "t_type must be a trivially copyable type."); \
static_assert(std::is_standard_layout<decltype(this_ref.variable)>(), "t_type must be a standard layout type."); \
KV_SERIALIZE_VAL_POD_AS_BLOB_FORCE_N(variable, val_name)
#define KV_SERIALIZE_VAL_POD_AS_BLOB_N(varialble, val_name) \
static_assert(std::is_pod<decltype(this_ref.varialble)>::value, "t_type must be a POD type."); \
KV_SERIALIZE_VAL_POD_AS_BLOB_FORCE_N(varialble, val_name)
#define KV_SERIALIZE_VAL_POD_AS_BLOB_OPT_N(variable, val_name, default_value) \
#define KV_SERIALIZE_VAL_POD_AS_BLOB_OPT_N(varialble, val_name, default_value) \
do { \
static_assert(std::is_trivially_copyable<decltype(this_ref.variable)>(), "t_type must be a trivially copyable type."); \
static_assert(std::is_standard_layout<decltype(this_ref.variable)>(), "t_type must be a standard layout type."); \
bool ret = KV_SERIALIZE_VAL_POD_AS_BLOB_FORCE_N(variable, val_name) \
static_assert(std::is_pod<decltype(this_ref.varialble)>::value, "t_type must be a POD type."); \
bool ret = KV_SERIALIZE_VAL_POD_AS_BLOB_FORCE_N(varialble, val_name); \
if (!ret) \
epee::serialize_default(this_ref.variable, default_value); \
epee::serialize_default(this_ref.varialble, default_value); \
} while(0);
#define KV_SERIALIZE_CONTAINER_POD_AS_BLOB_N(varialble, val_name) \
@@ -120,7 +118,7 @@ public: \
#define KV_SERIALIZE(varialble) KV_SERIALIZE_N(varialble, #varialble)
#define KV_SERIALIZE_VAL_POD_AS_BLOB(varialble) KV_SERIALIZE_VAL_POD_AS_BLOB_N(varialble, #varialble)
#define KV_SERIALIZE_VAL_POD_AS_BLOB_OPT(varialble, def) KV_SERIALIZE_VAL_POD_AS_BLOB_OPT_N(varialble, #varialble, def)
#define KV_SERIALIZE_VAL_POD_AS_BLOB_FORCE(varialble) KV_SERIALIZE_VAL_POD_AS_BLOB_FORCE_N(varialble, #varialble) //skip is_trivially_copyable and is_standard_layout compile time check
#define KV_SERIALIZE_VAL_POD_AS_BLOB_FORCE(varialble) KV_SERIALIZE_VAL_POD_AS_BLOB_FORCE_N(varialble, #varialble) //skip is_pod compile time check
#define KV_SERIALIZE_CONTAINER_POD_AS_BLOB(varialble) KV_SERIALIZE_CONTAINER_POD_AS_BLOB_N(varialble, #varialble)
#define KV_SERIALIZE_OPT(variable,default_value) KV_SERIALIZE_OPT_N(variable, #variable, default_value)

View File

@@ -133,14 +133,17 @@ namespace epee
return {src.data(), src.size()};
}
template<typename T>
constexpr bool has_padding() noexcept
{
return !std::is_standard_layout<T>() || alignof(T) != 1;
}
//! \return Cast data from `src` as `span<const std::uint8_t>`.
template<typename T>
span<const std::uint8_t> to_byte_span(const span<const T> src) noexcept
{
static_assert(!std::is_empty<T>(), "empty value types will not work -> sizeof == 1");
static_assert(std::is_standard_layout<T>(), "type must have standard layout");
static_assert(std::is_trivially_copyable<T>(), "type must be trivially copyable");
static_assert(alignof(T) == 1, "type may have padding");
static_assert(!has_padding<T>(), "source type may have padding");
return {reinterpret_cast<const std::uint8_t*>(src.data()), src.size_bytes()};
}
@@ -150,9 +153,7 @@ namespace epee
{
using value_type = typename T::value_type;
static_assert(!std::is_empty<value_type>(), "empty value types will not work -> sizeof == 1");
static_assert(std::is_standard_layout<value_type>(), "value type must have standard layout");
static_assert(std::is_trivially_copyable<value_type>(), "value type must be trivially copyable");
static_assert(alignof(value_type) == 1, "value type may have padding");
static_assert(!has_padding<value_type>(), "source value type may have padding");
return {reinterpret_cast<std::uint8_t*>(src.data()), src.size() * sizeof(value_type)};
}
@@ -161,9 +162,7 @@ namespace epee
span<const std::uint8_t> as_byte_span(const T& src) noexcept
{
static_assert(!std::is_empty<T>(), "empty types will not work -> sizeof == 1");
static_assert(std::is_standard_layout<T>(), "type must have standard layout");
static_assert(std::is_trivially_copyable<T>(), "type must be trivially copyable");
static_assert(alignof(T) == 1, "type may have padding");
static_assert(!has_padding<T>(), "source type may have padding");
return {reinterpret_cast<const std::uint8_t*>(std::addressof(src)), sizeof(T)};
}
@@ -172,9 +171,7 @@ namespace epee
span<std::uint8_t> as_mut_byte_span(T& src) noexcept
{
static_assert(!std::is_empty<T>(), "empty types will not work -> sizeof == 1");
static_assert(std::is_standard_layout<T>(), "type must have standard layout");
static_assert(std::is_trivially_copyable<T>(), "type must be trivially copyable");
static_assert(alignof(T) == 1, "type may have padding");
static_assert(!has_padding<T>(), "source type may have padding");
return {reinterpret_cast<std::uint8_t*>(std::addressof(src)), sizeof(T)};
}

View File

@@ -37,7 +37,6 @@
#include "misc_log_ex.h"
#include <boost/lexical_cast.hpp>
#include <boost/numeric/conversion/bounds.hpp>
#include <typeinfo>
#include <iomanip>

View File

@@ -31,7 +31,6 @@
#include "mlocker.h"
#include <boost/utility/string_ref.hpp>
#include <boost/algorithm/string.hpp>
#include <sstream>
#include <string>
#include <cstdint>
@@ -70,17 +69,23 @@ namespace string_tools
#ifdef _WIN32
std::string get_current_module_path();
#endif
void set_module_name_and_folder(const std::string& path_to_process_);
bool set_module_name_and_folder(const std::string& path_to_process_);
bool trim_left(std::string& str);
bool trim_right(std::string& str);
//----------------------------------------------------------------------------
inline std::string& trim(std::string& str)
{
boost::trim(str);
trim_left(str);
trim_right(str);
return str;
}
//----------------------------------------------------------------------------
inline std::string trim(const std::string& str)
inline std::string trim(const std::string& str_)
{
return boost::trim_copy(str);
std::string str = str_;
trim_left(str);
trim_right(str);
return str;
}
std::string pad_string(std::string s, size_t n, char c = ' ', bool prepend = false);
@@ -89,7 +94,6 @@ namespace string_tools
std::string pod_to_hex(const t_pod_type& s)
{
static_assert(std::is_standard_layout<t_pod_type>(), "expected standard layout type");
static_assert(alignof(t_pod_type) == 1, "type may have padding");
return to_hex::string(as_byte_span(s));
}
//----------------------------------------------------------------------------
@@ -97,8 +101,6 @@ namespace string_tools
bool hex_to_pod(const boost::string_ref hex_str, t_pod_type& s)
{
static_assert(std::is_standard_layout<t_pod_type>(), "expected standard layout type");
static_assert(alignof(t_pod_type) == 1, "type may have padding");
static_assert(std::is_trivially_copyable<t_pod_type>(), "type must be trivially copyable");
return from_hex::to_buffer(as_mut_byte_span(s), hex_str);
}
//----------------------------------------------------------------------------

View File

@@ -152,11 +152,7 @@ namespace epee
{
std::size_t space_needed = 0;
for (const auto& source : sources)
{
if (std::numeric_limits<std::size_t>::max() - space_needed < source.size())
throw std::bad_alloc{};
space_needed += source.size();
}
if (space_needed)
{
@@ -166,9 +162,9 @@ namespace epee
for (const auto& source : sources)
{
assert(source.size() <= out.size()); // see check above
std::memcpy(out.data(), source.data(), source.size());
out.remove_prefix(source.size());
if (out.remove_prefix(source.size()) < source.size())
throw std::bad_alloc{}; // size_t overflow on space_needed
}
storage_ = std::move(storage);
}

View File

@@ -176,12 +176,11 @@ void mlog_configure(const std::string &filename_base, bool console, const std::s
std::vector<boost::filesystem::path> found_files;
const boost::filesystem::directory_iterator end_itr;
const boost::filesystem::path filename_base_path(filename_base);
const std::string filename_base_name = filename_base_path.filename().string();
const boost::filesystem::path parent_path = filename_base_path.has_parent_path() ? filename_base_path.parent_path() : ".";
for (boost::filesystem::directory_iterator iter(parent_path); iter != end_itr; ++iter)
{
const std::string filename = iter->path().filename().string();
if (filename.size() >= filename_base_name.size() && std::memcmp(filename.data(), filename_base_name.data(), filename_base_name.size()) == 0)
const std::string filename = iter->path().string();
if (filename.size() >= filename_base.size() && std::memcmp(filename.data(), filename_base.data(), filename_base.size()) == 0)
{
found_files.push_back(iter->path());
}
@@ -339,21 +338,11 @@ 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:
@@ -472,9 +461,6 @@ 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);

View File

@@ -238,10 +238,6 @@ 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);

View File

@@ -38,12 +38,9 @@
#include <cstdlib>
#include <string>
#include <type_traits>
#include <system_error>
#include <boost/lexical_cast.hpp>
#include <boost/algorithm/string.hpp>
#include <boost/algorithm/string/predicate.hpp>
#include <boost/utility/string_ref.hpp>
#include <boost/filesystem.hpp>
#include "misc_log_ex.h"
#include "storages/parserse_base_utils.h"
#include "hex.h"
@@ -160,20 +157,46 @@ namespace string_tools
return pname;
}
#endif
void set_module_name_and_folder(const std::string& path_to_process_)
{
boost::filesystem::path path_to_process = path_to_process_;
bool set_module_name_and_folder(const std::string& path_to_process_)
{
std::string path_to_process = path_to_process_;
#ifdef _WIN32
path_to_process = get_current_module_path();
#endif
std::string::size_type a = path_to_process.rfind( '\\' );
if(a == std::string::npos )
{
a = path_to_process.rfind( '/' );
}
if ( a != std::string::npos )
{
get_current_module_name() = path_to_process.substr(a+1, path_to_process.size());
get_current_module_folder() = path_to_process.substr(0, a);
return true;
}else
return false;
get_current_module_name() = path_to_process.filename().string();
get_current_module_folder() = path_to_process.parent_path().string();
}
}
//----------------------------------------------------------------------------
bool trim_left(std::string& str)
{
for(std::string::iterator it = str.begin(); it!= str.end() && isspace(static_cast<unsigned char>(*it));)
str.erase(str.begin());
return true;
}
//----------------------------------------------------------------------------
bool trim_right(std::string& str)
{
for(std::string::reverse_iterator it = str.rbegin(); it!= str.rend() && isspace(static_cast<unsigned char>(*it));)
str.erase( --((it++).base()));
return true;
}
//----------------------------------------------------------------------------
std::string pad_string(std::string s, size_t n, char c, bool prepend)
{
if (s.size() < n)
@@ -186,22 +209,28 @@ namespace string_tools
return s;
}
std::string get_extension(const std::string& str)
{
std::string ext_with_dot = boost::filesystem::path(str).extension().string();
if (ext_with_dot.empty())
return {};
return ext_with_dot.erase(0, 1);
}
std::string get_extension(const std::string& str)
{
std::string res;
std::string::size_type pos = str.rfind('.');
if(std::string::npos == pos)
return res;
res = str.substr(pos+1, str.size()-pos);
return res;
}
//----------------------------------------------------------------------------
std::string cut_off_extension(const std::string& str)
{
return boost::filesystem::path(str).replace_extension("").string();
}
std::string cut_off_extension(const std::string& str)
{
std::string res;
std::string::size_type pos = str.rfind('.');
if(std::string::npos == pos)
return str;
res = str.substr(0, pos);
return res;
}
//----------------------------------------------------------------------------
#ifdef _WIN32
std::wstring utf8_to_utf16(const std::string& str)
{

View File

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

View File

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

View File

@@ -41,10 +41,10 @@ RUN useradd -ms /bin/bash -U ubuntu -G docker
USER ubuntu:docker
WORKDIR $WORKDIR
RUN git clone https://codeberg.org/wownero/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://codeberg.org/wownero/wownero
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://codeberg.org/wownero/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 ..

View File

@@ -26,7 +26,7 @@ packages:
- "cmake"
- "unzip"
remotes:
- "url": "https://codeberg.org/wownero/wownero.git"
- "url": "https://git.wownero.com/wownero/wownero.git"
"dir": "wownero"
files: []
script: |

View File

@@ -5,7 +5,7 @@ import os
import subprocess
import sys
gsigs = 'https://codeberg.org/wownero/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'],
@@ -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://codeberg.org/wownero/wownero', 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')

View File

@@ -26,7 +26,7 @@ packages:
- "python"
- "cmake"
remotes:
- "url": "https://codeberg.org/wownero/wownero.git"
- "url": "https://git.wownero.com/wownero/wownero.git"
"dir": "wownero"
files: []
script: |

View File

@@ -21,7 +21,6 @@ packages:
- "g++-7-arm-linux-gnueabihf"
- "gcc-arm-linux-gnueabihf"
- "g++-arm-linux-gnueabihf"
- "g++-riscv64-linux-gnu"
- "g++-7-multilib"
- "gcc-7-multilib"
- "binutils-arm-linux-gnueabihf"
@@ -38,13 +37,13 @@ packages:
- "python"
- "cmake"
remotes:
- "url": "https://codeberg.org/wownero/wownero.git"
- "url": "https://git.wownero.com/wownero/wownero.git"
"dir": "wownero"
files: []
script: |
WRAP_DIR=$HOME/wrapped
HOSTS="x86_64-linux-gnu arm-linux-gnueabihf aarch64-linux-gnu i686-linux-gnu riscv64-linux-gnu"
HOSTS="x86_64-linux-gnu arm-linux-gnueabihf aarch64-linux-gnu i686-linux-gnu"
FAKETIME_HOST_PROGS=""
FAKETIME_PROGS="date"
HOST_CFLAGS="-O2 -g"
@@ -160,13 +159,7 @@ script: |
fi
export C_INCLUDE_PATH="$EXTRA_INCLUDES"
export CPLUS_INCLUDE_PATH="$EXTRA_INCLUDES"
# glibc only added riscv support in 2.27, disable backwards compatibility
if [ "$i" == "riscv64-linux-gnu" ]; then
BACKCOMPAT_OPTION=OFF
else
BACKCOMPAT_OPTION=ON
fi
cmake .. -DCMAKE_TOOLCHAIN_FILE=${BASEPREFIX}/${i}/share/toolchain.cmake -DBACKCOMPAT=${BACKCOMPAT_OPTION} -DCMAKE_SKIP_RPATH=ON
cmake .. -DCMAKE_TOOLCHAIN_FILE=${BASEPREFIX}/${i}/share/toolchain.cmake -DBACKCOMPAT=ON -DCMAKE_SKIP_RPATH=ON
make ${MAKEOPTS}
chmod 755 bin/*
cp ../utils/conf/wow.conf bin

View File

@@ -24,7 +24,7 @@ packages:
- "python-dev"
- "python-setuptools"
remotes:
- "url": "https://codeberg.org/wownero/wownero.git"
- "url": "https://git.wownero.com/wownero/wownero.git"
"dir": "wownero"
files: []
script: |

View File

@@ -35,7 +35,7 @@ alternatives:
package: "x86_64-w64-mingw32-gcc"
path: "/usr/bin/x86_64-w64-mingw32-gcc-posix"
remotes:
- "url": "https://codeberg.org/wownero/wownero.git"
- "url": "https://git.wownero.com/wownero/wownero.git"
"dir": "wownero"
files: []
script: |

View File

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

View File

@@ -149,11 +149,6 @@ 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)

View File

@@ -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"};
@@ -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
{

Binary file not shown.

View File

@@ -233,7 +233,13 @@ namespace cryptonote
ADD_CHECKPOINT2(489400, "b14f49eae77398117ea93435676100d8b655a804689f73a5a4d0d5e71160d603", "0x1123c39bb52f7e");
ADD_CHECKPOINT2(491200, "cedba73ad35ce7f51aaca2beb36dc32d79ecc716d146eb8211e6a815f3666c4a", "0x11334734abbd17");
ADD_CHECKPOINT2(497100, "2c4c70ac1ada94151f19d67ccf1aa4e846e6067f49f67c85cc03f78e768ea42b", "0x116906bc97a751");
ADD_CHECKPOINT2(691500, "ed8e2507c0938b7eab7b02eccfb3506aeb591e51fbf6cf145fcc60ea2d351025", "0x163a280f2ce8e3");
ADD_CHECKPOINT2(500000, "f4f771261b8c13cd83a9d8fa22e3cfe988564ad4b57dd90e79d5c0e77d61cf6a", "0x1185e7f2357a03");
ADD_CHECKPOINT2(503500, "776f36a17056c3e22bbfb51d5aeabb58000731e9ad549f0f2f8ad1e1bcedf312", "0x11a4884467f53d");
ADD_CHECKPOINT2(509900, "59520faa272fc68e0426c827a38b21cdc1df8f5a37c5fdcbbe00350fece5f3ae", "0x11dc780bd1b580");
ADD_CHECKPOINT2(514000, "1569e712750f19e57aee3f73cc3091a0eea392740bd396ad3570bc96e0e6ffb5", "0x11fff58abe0a82"); //Hard fork to v20
ADD_CHECKPOINT2(516700, "0443c47c5a4e344c3f68a491a3b2f6b78a769cdf9076249c93f187ececf9cc7c", "0x12128a532a59a6");
ADD_CHECKPOINT2(522000, "8c15ae514063bf05e7662ab33b86a4131aa89df0784ce3da7876c5339bc1de3d", "0x123d9c604a7be6");
ADD_CHECKPOINT2(566000, "136e37f5f130dd2dc2d8d30e46e16d74377cb834b7c5be32cd09ee6ad402556c", "0x1318d703b1bff7");
return true;
}

View File

@@ -35,7 +35,6 @@
#include <boost/archive/portable_binary_iarchive.hpp>
#include <boost/filesystem/operations.hpp>
#include "common/util.h"
namespace tools
{
@@ -111,7 +110,7 @@ namespace tools
catch(...)
{
// if failed, try reading in unportable mode
tools::copy_file(file_path, file_path + ".unportable");
boost::filesystem::copy_file(file_path, file_path + ".unportable", boost::filesystem::copy_option::overwrite_if_exists);
data_file.close();
data_file.open( file_path, std::ios_base::binary | std::ios_base::in);
if(data_file.fail())

View File

@@ -115,24 +115,6 @@ static int flock_exnb(int fd)
namespace tools
{
void copy_file(const std::string& from, const std::string& to)
{
using boost::filesystem::path;
#if BOOST_VERSION < 107400
// Remove this preprocessor if/else when we are bumping the boost version.
boost::filesystem::copy_file(
path(from),
path(to),
boost::filesystem::copy_option::overwrite_if_exists);
#else
boost::filesystem::copy_file(
path(from),
path(to),
boost::filesystem::copy_options::overwrite_existing);
#endif
}
std::function<void(int)> signal_handler::m_handler;
private_file::private_file() noexcept : m_handle(), m_filename() {}
@@ -140,7 +122,7 @@ namespace tools
private_file::private_file(std::FILE* handle, std::string&& filename) noexcept
: m_handle(handle), m_filename(std::move(filename)) {}
private_file private_file::create(std::string name, uint32_t extra_flags)
private_file private_file::create(std::string name)
{
#ifdef WIN32
struct close_handle
@@ -193,7 +175,7 @@ namespace tools
name.c_str(),
GENERIC_WRITE, FILE_SHARE_READ,
std::addressof(attributes),
CREATE_NEW, (FILE_ATTRIBUTE_TEMPORARY | FILE_FLAG_DELETE_ON_CLOSE | extra_flags),
CREATE_NEW, (FILE_ATTRIBUTE_TEMPORARY | FILE_FLAG_DELETE_ON_CLOSE),
nullptr
)
};
@@ -212,7 +194,7 @@ namespace tools
}
}
#else
const int fdr = open(name.c_str(), (O_RDONLY | O_CREAT | extra_flags), S_IRUSR);
const int fdr = open(name.c_str(), (O_RDONLY | O_CREAT), S_IRUSR);
if (0 <= fdr)
{
struct stat rstats = {};
@@ -243,23 +225,6 @@ namespace tools
return {};
}
private_file private_file::drop_and_recreate(std::string filename)
{
if (epee::file_io_utils::is_file_exist(filename)) {
boost::system::error_code ec{};
boost::filesystem::remove(filename, ec);
if (ec) {
MERROR("Failed to remove " << filename << ": " << ec.message());
return {};
}
}
#ifdef WIN32
return create(filename);
#else
return create(filename, O_EXCL);
#endif
}
private_file::~private_file() noexcept
{
try

View File

@@ -67,8 +67,6 @@ namespace tools
}
};
void copy_file(const std::string& from, const std::string& to);
//! A file restricted to process owner AND process. Deletes file on destruction.
class private_file {
std::unique_ptr<std::FILE, close_file> m_handle;
@@ -82,11 +80,7 @@ namespace tools
/*! \return File only readable by owner and only used by this process
OR `private_file{}` on error. */
static private_file create(std::string filename, uint32_t extra_flags = 0);
/*! \return Drop and create file only readable by owner and only used
by this process OR `private_file{}` on error. */
static private_file drop_and_recreate(std::string filename);
static private_file create(std::string filename);
private_file(private_file&&) = default;
private_file& operator=(private_file&&) = default;

View File

@@ -171,9 +171,7 @@ namespace crypto {
/* Generate a value filled with random bytes.
*/
template<typename T>
T rand() {
static_assert(std::is_standard_layout<T>(), "cannot write random bytes into non-standard layout type");
static_assert(std::is_trivially_copyable<T>(), "cannot write random bytes into non-trivially copyable type");
typename std::enable_if<std::is_pod<T>::value, T>::type rand() {
typename std::remove_cv<T>::type res;
generate_random_bytes_thread_safe(sizeof(T), (uint8_t*)&res);
return res;
@@ -316,14 +314,8 @@ namespace crypto {
inline std::ostream &operator <<(std::ostream &o, const crypto::public_key &v) {
epee::to_hex::formatted(o, epee::as_byte_span(v)); return o;
}
/* Do NOT overload the << operator for crypto::secret_key here. Use secret_key_explicit_print_ref
* instead to prevent accidental implicit dumping of secret key material to the logs (which has
* happened before). For the same reason, do not overload it for crypto::ec_scalar either since
* crypto::secret_key is a subclass. I'm not sorry that it's obtuse; that's the point, bozo.
*/
struct secret_key_explicit_print_ref { const crypto::secret_key &sk; };
inline std::ostream &operator <<(std::ostream &o, const secret_key_explicit_print_ref v) {
epee::to_hex::formatted(o, epee::as_byte_span(unwrap(unwrap(v.sk)))); return o;
inline std::ostream &operator <<(std::ostream &o, const crypto::secret_key &v) {
epee::to_hex::formatted(o, epee::as_byte_span(v)); return o;
}
inline std::ostream &operator <<(std::ostream &o, const crypto::key_derivation &v) {
epee::to_hex::formatted(o, epee::as_byte_span(v)); return o;

View File

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

View File

@@ -312,7 +312,7 @@ namespace cryptonote
bool r = hwdev.generate_key_derivation(tx_public_key, ack.m_view_secret_key, recv_derivation);
if (!r)
{
MWARNING("key image helper: failed to generate_key_derivation(" << tx_public_key << ", <viewkey>)");
MWARNING("key image helper: failed to generate_key_derivation(" << tx_public_key << ", " << ack.m_view_secret_key << ")");
memcpy(&recv_derivation, rct::identity().bytes, sizeof(recv_derivation));
}
@@ -323,7 +323,7 @@ namespace cryptonote
r = hwdev.generate_key_derivation(additional_tx_public_keys[i], ack.m_view_secret_key, additional_recv_derivation);
if (!r)
{
MWARNING("key image helper: failed to generate_key_derivation(" << additional_tx_public_keys[i] << ", <viewkey>)");
MWARNING("key image helper: failed to generate_key_derivation(" << additional_tx_public_keys[i] << ", " << ack.m_view_secret_key << ")");
}
else
{

View File

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

View File

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

View File

@@ -30,7 +30,6 @@
#pragma once
#include <cstdint>
#include <stdexcept>
#include <string>
#include <boost/uuid/uuid.hpp>

View File

@@ -1242,7 +1242,12 @@ bool Blockchain::switch_to_alternative_blockchain(std::list<block_extended_info>
// just the latter (because the rollback was done above).
rollback_blockchain_switching(disconnected_chain, split_height);
// FIXME: Why do we keep invalid blocks around? Possibly in case we hear
// about them again so we can immediately dismiss them, but needs some
// looking into.
const crypto::hash blkid = cryptonote::get_block_hash(bei.bl);
add_block_as_invalid(bei, blkid);
MERROR("The block was inserted as invalid while connecting new alternative chain, block_id: " << blkid);
m_db->remove_alt_block(blkid);
alt_ch_iter++;
@@ -1250,6 +1255,7 @@ bool Blockchain::switch_to_alternative_blockchain(std::list<block_extended_info>
{
const auto &bei = *alt_ch_to_orph_iter++;
const crypto::hash blkid = cryptonote::get_block_hash(bei.bl);
add_block_as_invalid(bei, blkid);
m_db->remove_alt_block(blkid);
}
return false;
@@ -2459,22 +2465,19 @@ void Blockchain::get_output_key_mask_unlocked(const uint64_t& amount, const uint
bool Blockchain::get_output_distribution(uint64_t amount, uint64_t from_height, uint64_t to_height, uint64_t &start_height, std::vector<uint64_t> &distribution, uint64_t &base) const
{
// rct outputs don't exist before v4
// if (amount == 0)
// {
// switch (m_nettype)
// {
// case STAGENET: start_height = stagenet_hard_forks[3].height; break;
// case TESTNET: start_height = testnet_hard_forks[3].height; break;
// case MAINNET: start_height = 0; break;
// case FAKECHAIN: start_height = 0; break;
// default: return false;
// }
// }
// else
// start_height = 0;
// rct outputs start at genesis on wow
start_height = 0;
if (amount == 0)
{
switch (m_nettype)
{
case STAGENET: start_height = stagenet_hard_forks[3].height; break;
case TESTNET: start_height = testnet_hard_forks[3].height; break;
case MAINNET: start_height = mainnet_hard_forks[3].height; break;
case FAKECHAIN: start_height = 0; break;
default: return false;
}
}
else
start_height = 0;
base = 0;
if (to_height > 0 && to_height < from_height)
@@ -3942,8 +3945,6 @@ void Blockchain::get_dynamic_base_fee_estimate_2021_scaling(uint64_t grace_block
const uint8_t version = get_current_hard_fork_version();
const uint64_t db_height = m_db->height();
CHECK_AND_ASSERT_THROW_MES(grace_blocks <= CRYPTONOTE_REWARD_BLOCKS_WINDOW, "Grace blocks invalid In 2021 fee scaling estimate.");
// we want Mlw = median of max((min(Mbw, 1.7 * Ml), Zm), Ml / 1.7)
// Mbw: block weight for the last 99990 blocks, 0 for the next 10
// Ml: penalty free zone (dynamic), aka long_term_median, aka median of max((min(Mb, 1.7 * Ml), Zm), Ml / 1.7)
@@ -3957,6 +3958,7 @@ void Blockchain::get_dynamic_base_fee_estimate_2021_scaling(uint64_t grace_block
const uint64_t Mlw_penalty_free_zone_for_wallet = std::max<uint64_t>(rm.median(), CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE_V5);
// Msw: median over [100 - grace blocks] past + [grace blocks] future blocks
CHECK_AND_ASSERT_THROW_MES(grace_blocks <= 100, "Grace blocks invalid In 2021 fee scaling estimate.");
std::vector<uint64_t> weights;
get_last_n_blocks_weights(weights, 100 - grace_blocks);
weights.reserve(100);
@@ -5669,7 +5671,7 @@ void Blockchain::cancel()
}
#if defined(PER_BLOCK_CHECKPOINT)
static const char expected_block_hashes_hash[] = "3ee7be44d391f20b389ed17b17443ffa26889ac943a57b4e493b833db67159c5";
static const char expected_block_hashes_hash[] = "9ce2e9f40ff58954d6176e300af1d8da1804b829e1be8565805fea497df40f4b";
void Blockchain::load_compiled_in_block_hashes(const GetCheckpointsCallback& get_checkpoints)
{
if (get_checkpoints == nullptr || !m_fast_sync)

View File

@@ -1840,56 +1840,6 @@ namespace cryptonote
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 jbjareb znantre "
<< ENDL);
MGINFO_MAGENTA(ENDL <<
" ██ ██ █████ ██████ ███████ ███ ██ \n"
" ██ ██ ██ ██ ██ ██ ██ ████ ██ \n"
" █████ ███████ ██████ █████ ██ ██ ██ \n"
" ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ \n"
" ██ ██ ██ ██ ██ ██ ███████ ██ ████ \n"
<< ENDL);
MGINFO_YELLOW(ENDL << "**********************************************************************" << ENDL
<< main_message << ENDL
<< ENDL

View File

@@ -144,7 +144,7 @@ namespace cryptonote
crypto::key_derivation derivation = AUTO_VAL_INIT(derivation);
crypto::public_key out_eph_public_key = AUTO_VAL_INIT(out_eph_public_key);
bool r = crypto::generate_key_derivation(miner_address.m_view_public_key, txkey.sec, derivation);
CHECK_AND_ASSERT_MES(r, false, "while creating outs: failed to generate_key_derivation(" << miner_address.m_view_public_key << ", " << crypto::secret_key_explicit_print_ref{txkey.sec} << ")");
CHECK_AND_ASSERT_MES(r, false, "while creating outs: failed to generate_key_derivation(" << miner_address.m_view_public_key << ", " << txkey.sec << ")");
r = crypto::derive_public_key(derivation, no, miner_address.m_spend_public_key, out_eph_public_key);
CHECK_AND_ASSERT_MES(r, false, "while creating outs: failed to derive_public_key(" << derivation << ", " << no << ", "<< miner_address.m_spend_public_key << ")");
@@ -216,7 +216,7 @@ namespace cryptonote
return addr.m_view_public_key;
}
//---------------------------------------------------------------
bool construct_tx_with_tx_key(const account_keys& sender_account_keys, const std::unordered_map<crypto::public_key, subaddress_index>& subaddresses, std::vector<tx_source_entry>& sources, std::vector<tx_destination_entry>& destinations, const boost::optional<cryptonote::account_public_address>& change_addr, const std::vector<uint8_t> &extra, transaction& tx, const crypto::secret_key &tx_key, const std::vector<crypto::secret_key> &additional_tx_keys, bool rct, const rct::RCTConfig &rct_config, bool shuffle_outs, bool use_view_tags)
bool construct_tx_with_tx_key(const account_keys& sender_account_keys, const std::unordered_map<crypto::public_key, subaddress_index>& subaddresses, std::vector<tx_source_entry>& sources, std::vector<tx_destination_entry>& destinations, const boost::optional<cryptonote::account_public_address>& change_addr, const std::vector<uint8_t> &extra, transaction& tx, uint64_t unlock_time, const crypto::secret_key &tx_key, const std::vector<crypto::secret_key> &additional_tx_keys, bool rct, const rct::RCTConfig &rct_config, bool shuffle_outs, bool use_view_tags)
{
hw::device &hwdev = sender_account_keys.get_device();
@@ -231,7 +231,7 @@ namespace cryptonote
amount_keys.clear();
tx.version = rct ? 2 : 1;
tx.unlock_time = 0;
tx.unlock_time = unlock_time;
tx.extra = extra;
crypto::public_key txkey_pub;
@@ -497,7 +497,7 @@ namespace cryptonote
crypto::generate_ring_signature(tx_prefix_hash, boost::get<txin_to_key>(tx.vin[i]).k_image, keys_ptrs, in_contexts[i].in_ephemeral.sec, src_entr.real_output, sigs.data());
ss_ring_s << "signatures:" << ENDL;
std::for_each(sigs.begin(), sigs.end(), [&](const crypto::signature& s){ss_ring_s << s << ENDL;});
ss_ring_s << "prefix_hash:" << tx_prefix_hash << ENDL << "in_ephemeral_key: " << crypto::secret_key_explicit_print_ref{in_contexts[i].in_ephemeral.sec} << ENDL << "real_output: " << src_entr.real_output << ENDL;
ss_ring_s << "prefix_hash:" << tx_prefix_hash << ENDL << "in_ephemeral_key: " << in_contexts[i].in_ephemeral.sec << ENDL << "real_output: " << src_entr.real_output << ENDL;
i++;
}
@@ -621,7 +621,7 @@ namespace cryptonote
return true;
}
//---------------------------------------------------------------
bool construct_tx_and_get_tx_key(const account_keys& sender_account_keys, const std::unordered_map<crypto::public_key, subaddress_index>& subaddresses, std::vector<tx_source_entry>& sources, std::vector<tx_destination_entry>& destinations, const boost::optional<cryptonote::account_public_address>& change_addr, const std::vector<uint8_t> &extra, transaction& tx, crypto::secret_key &tx_key, std::vector<crypto::secret_key> &additional_tx_keys, bool rct, const rct::RCTConfig &rct_config, bool use_view_tags)
bool construct_tx_and_get_tx_key(const account_keys& sender_account_keys, const std::unordered_map<crypto::public_key, subaddress_index>& subaddresses, std::vector<tx_source_entry>& sources, std::vector<tx_destination_entry>& destinations, const boost::optional<cryptonote::account_public_address>& change_addr, const std::vector<uint8_t> &extra, transaction& tx, uint64_t unlock_time, crypto::secret_key &tx_key, std::vector<crypto::secret_key> &additional_tx_keys, bool rct, const rct::RCTConfig &rct_config, bool use_view_tags)
{
hw::device &hwdev = sender_account_keys.get_device();
hwdev.open_tx(tx_key);
@@ -642,7 +642,7 @@ namespace cryptonote
}
bool shuffle_outs = true;
bool r = construct_tx_with_tx_key(sender_account_keys, subaddresses, sources, destinations, change_addr, extra, tx, tx_key, additional_tx_keys, rct, rct_config, shuffle_outs, use_view_tags);
bool r = construct_tx_with_tx_key(sender_account_keys, subaddresses, sources, destinations, change_addr, extra, tx, unlock_time, tx_key, additional_tx_keys, rct, rct_config, shuffle_outs, use_view_tags);
hwdev.close_tx();
return r;
} catch(...) {
@@ -651,14 +651,14 @@ namespace cryptonote
}
}
//---------------------------------------------------------------
bool construct_tx(const account_keys& sender_account_keys, std::vector<tx_source_entry>& sources, const std::vector<tx_destination_entry>& destinations, const boost::optional<cryptonote::account_public_address>& change_addr, const std::vector<uint8_t> &extra, transaction& tx)
bool construct_tx(const account_keys& sender_account_keys, std::vector<tx_source_entry>& sources, const std::vector<tx_destination_entry>& destinations, const boost::optional<cryptonote::account_public_address>& change_addr, const std::vector<uint8_t> &extra, transaction& tx, uint64_t unlock_time)
{
std::unordered_map<crypto::public_key, cryptonote::subaddress_index> subaddresses;
subaddresses[sender_account_keys.m_account_address.m_spend_public_key] = {0,0};
crypto::secret_key tx_key;
std::vector<crypto::secret_key> additional_tx_keys;
std::vector<tx_destination_entry> destinations_copy = destinations;
return construct_tx_and_get_tx_key(sender_account_keys, subaddresses, sources, destinations_copy, change_addr, extra, tx, tx_key, additional_tx_keys, false, { rct::RangeProofBorromean, 0});
return construct_tx_and_get_tx_key(sender_account_keys, subaddresses, sources, destinations_copy, change_addr, extra, tx, unlock_time, tx_key, additional_tx_keys, false, { rct::RangeProofBorromean, 0});
}
//---------------------------------------------------------------
bool generate_genesis_block(

View File

@@ -119,9 +119,9 @@ namespace cryptonote
//---------------------------------------------------------------
crypto::public_key get_destination_view_key_pub(const std::vector<tx_destination_entry> &destinations, const boost::optional<cryptonote::account_public_address>& change_addr);
bool construct_tx(const account_keys& sender_account_keys, std::vector<tx_source_entry> &sources, const std::vector<tx_destination_entry>& destinations, const boost::optional<cryptonote::account_public_address>& change_addr, const std::vector<uint8_t> &extra, transaction& tx);
bool construct_tx_with_tx_key(const account_keys& sender_account_keys, const std::unordered_map<crypto::public_key, subaddress_index>& subaddresses, std::vector<tx_source_entry>& sources, std::vector<tx_destination_entry>& destinations, const boost::optional<cryptonote::account_public_address>& change_addr, const std::vector<uint8_t> &extra, transaction& tx, const crypto::secret_key &tx_key, const std::vector<crypto::secret_key> &additional_tx_keys, bool rct = false, const rct::RCTConfig &rct_config = { rct::RangeProofBorromean, 0 }, bool shuffle_outs = true, bool use_view_tags = false);
bool construct_tx_and_get_tx_key(const account_keys& sender_account_keys, const std::unordered_map<crypto::public_key, subaddress_index>& subaddresses, std::vector<tx_source_entry>& sources, std::vector<tx_destination_entry>& destinations, const boost::optional<cryptonote::account_public_address>& change_addr, const std::vector<uint8_t> &extra, transaction& tx, crypto::secret_key &tx_key, std::vector<crypto::secret_key> &additional_tx_keys, bool rct = false, const rct::RCTConfig &rct_config = { rct::RangeProofBorromean, 0 }, bool use_view_tags = false);
bool construct_tx(const account_keys& sender_account_keys, std::vector<tx_source_entry> &sources, const std::vector<tx_destination_entry>& destinations, const boost::optional<cryptonote::account_public_address>& change_addr, const std::vector<uint8_t> &extra, transaction& tx, uint64_t unlock_time);
bool construct_tx_with_tx_key(const account_keys& sender_account_keys, const std::unordered_map<crypto::public_key, subaddress_index>& subaddresses, std::vector<tx_source_entry>& sources, std::vector<tx_destination_entry>& destinations, const boost::optional<cryptonote::account_public_address>& change_addr, const std::vector<uint8_t> &extra, transaction& tx, uint64_t unlock_time, const crypto::secret_key &tx_key, const std::vector<crypto::secret_key> &additional_tx_keys, bool rct = false, const rct::RCTConfig &rct_config = { rct::RangeProofBorromean, 0 }, bool shuffle_outs = true, bool use_view_tags = false);
bool construct_tx_and_get_tx_key(const account_keys& sender_account_keys, const std::unordered_map<crypto::public_key, subaddress_index>& subaddresses, std::vector<tx_source_entry>& sources, std::vector<tx_destination_entry>& destinations, const boost::optional<cryptonote::account_public_address>& change_addr, const std::vector<uint8_t> &extra, transaction& tx, uint64_t unlock_time, crypto::secret_key &tx_key, std::vector<crypto::secret_key> &additional_tx_keys, bool rct = false, const rct::RCTConfig &rct_config = { rct::RangeProofBorromean, 0 }, bool use_view_tags = false);
bool generate_output_ephemeral_keys(const size_t tx_version, const cryptonote::account_keys &sender_account_keys, const crypto::public_key &txkey_pub, const crypto::secret_key &tx_key,
const cryptonote::tx_destination_entry &dst_entr, const boost::optional<cryptonote::account_public_address> &change_addr, const size_t output_index,
const bool &need_additional_txkeys, const std::vector<crypto::secret_key> &additional_tx_keys,

View File

@@ -236,15 +236,6 @@ namespace cryptonote
return false;
}
if (!kept_by_block && tx.unlock_time)
{
LOG_PRINT_L1("transaction unlock time is not zero: " << tx.unlock_time);
tvc.m_verifivation_failed = true;
tvc.m_nonzero_unlock_time = true;
tvc.m_no_drop_offense = 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?
@@ -256,7 +247,6 @@ namespace cryptonote
LOG_PRINT_L1("Transaction with id= "<< id << " used already spent key images");
tvc.m_verifivation_failed = true;
tvc.m_double_spend = true;
tvc.m_no_drop_offense = true;
return false;
}
}
@@ -445,14 +435,8 @@ namespace cryptonote
void tx_memory_pool::prune(size_t bytes)
{
CRITICAL_REGION_LOCAL(m_transactions_lock);
// Nothing to do if already empty
if (m_txs_by_fee_and_receive_time.empty())
return;
if (bytes == 0)
bytes = m_txpool_max_weight;
CRITICAL_REGION_LOCAL1(m_blockchain);
LockedTXN lock(m_blockchain.get_db());
bool changed = false;
@@ -497,13 +481,8 @@ namespace cryptonote
reduce_txpool_weight(meta.weight);
remove_transaction_keyimages(tx, txid);
MINFO("Pruned tx " << txid << " from txpool: weight: " << meta.weight << ", fee/byte: " << it->first.first);
auto it_prev = it;
--it_prev;
remove_tx_from_transient_lists(it, txid, !meta.matches(relay_category::broadcasted));
it = it_prev;
it--;
changed = true;
}
catch (const std::exception &e)
@@ -1095,7 +1074,7 @@ namespace cryptonote
// If the total weight is too high, choose the best paying transactions
if (total_weight > max_backlog_weight)
std::stable_sort(tmp.begin(), tmp.end(), [](const auto& a, const auto& b){ return a.fee * b.weight > b.fee * a.weight; });
std::sort(tmp.begin(), tmp.end(), [](const auto& a, const auto& b){ return a.fee * b.weight > b.fee * a.weight; });
backlog.clear();
uint64_t w = 0;
@@ -1848,7 +1827,7 @@ namespace cryptonote
auto sorted_it = find_tx_in_sorted_container(txid);
if (sorted_it == m_txs_by_fee_and_receive_time.end())
{
MDEBUG("Re-adding tx " << txid << " to tx pool, but it was not found in the sorted txs container");
MERROR("Re-adding tx " << txid << " to tx pool, but it was not found in the sorted txs container");
}
else
{

View File

@@ -69,12 +69,11 @@ namespace cryptonote
{
// sort by greatest first, not least
if (a.first.first > b.first.first) return true;
if (a.first.first < b.first.first) return false;
if (a.first.second < b.first.second) return true;
if (a.first.second > b.first.second) return false;
return memcmp(a.second.data, b.second.data, sizeof(crypto::hash)) < 0;
else if (a.first.first < b.first.first) return false;
else if (a.first.second < b.first.second) return true;
else if (a.first.second > b.first.second) return false;
else if (a.second != b.second) return true;
else return false;
}
};

View File

@@ -40,6 +40,15 @@
#undef MONERO_DEFAULT_LOG_CATEGORY
#define MONERO_DEFAULT_LOG_CATEGORY "cn.block_queue"
namespace std {
static_assert(sizeof(size_t) <= sizeof(boost::uuids::uuid), "boost::uuids::uuid too small");
template<> struct hash<boost::uuids::uuid> {
std::size_t operator()(const boost::uuids::uuid &_v) const {
return reinterpret_cast<const std::size_t &>(_v);
}
};
}
namespace cryptonote
{
@@ -463,7 +472,7 @@ bool block_queue::has_spans(const boost::uuids::uuid &connection_id) const
float block_queue::get_speed(const boost::uuids::uuid &connection_id) const
{
boost::unique_lock<boost::recursive_mutex> lock(mutex);
std::unordered_map<boost::uuids::uuid, float, boost::hash<boost::uuids::uuid>> speeds;
std::unordered_map<boost::uuids::uuid, float> speeds;
for (const auto &span: blocks)
{
if (span.blocks.empty())
@@ -471,7 +480,7 @@ float block_queue::get_speed(const boost::uuids::uuid &connection_id) const
// note that the average below does not average over the whole set, but over the
// previous pseudo average and the latest rate: this gives much more importance
// to the latest measurements, which is fine here
const auto i = speeds.find(span.connection_id);
std::unordered_map<boost::uuids::uuid, float>::iterator i = speeds.find(span.connection_id);
if (i == speeds.end())
speeds.insert(std::make_pair(span.connection_id, span.rate));
else

View File

@@ -1693,22 +1693,8 @@ 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);
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;
}
MGINFO_YELLOW("Synced " << current_blockchain_height << "/" << target_blockchain_height
<< progress_message << timing_message);
if (previous_stripe != current_stripe)
notify_new_stripe(context, current_stripe);
}

View File

@@ -396,8 +396,6 @@ namespace levin
for (auto& connection : connections)
{
std::sort(connection.first.begin(), connection.first.end()); // don't leak receive order
connection.first.erase(std::unique(connection.first.begin(), connection.first.end()),
connection.first.end());
make_payload_send_txs(*zone_->p2p, std::move(connection.first), connection.second, zone_->pad_txs, true);
}
@@ -743,14 +741,9 @@ namespace levin
notify::status notify::get_status() const noexcept
{
if (!zone_)
return {false, false, false};
return {false, false};
// `connection_count` is only set when `!noise.empty()`.
const std::size_t connection_count = zone_->connection_count;
bool has_outgoing = connection_count;
if (zone_->noise.empty())
has_outgoing = zone_->p2p->get_out_connections_count();
return {!zone_->noise.empty(), CRYPTONOTE_NOISE_CHANNELS <= connection_count, has_outgoing};
return {!zone_->noise.empty(), CRYPTONOTE_NOISE_CHANNELS <= zone_->connection_count};
}
void notify::new_out_connection()

View File

@@ -75,8 +75,7 @@ namespace levin
struct status
{
bool has_noise;
bool connections_filled; //!< True when has zone has `CRYPTONOTE_NOISE_CHANNELS` outgoing noise channels
bool has_outgoing; //!< True when zone has outgoing connections
bool connections_filled;
};
//! Construct an instance that cannot notify.

View File

@@ -696,16 +696,6 @@ bool t_command_parser_executor::ban(const std::vector<std::string>& args)
std::ifstream ifs(ban_list_path.string());
for (std::string line; std::getline(ifs, line); )
{
// ignore comments after '#' character
const size_t pound_idx = line.find('#');
if (pound_idx != std::string::npos)
line.resize(pound_idx);
// trim whitespace and ignore empty lines
boost::trim(line);
if (line.empty())
continue;
auto subnet = net::get_ipv4_subnet_address(line);
if (subnet)
{

View File

@@ -317,15 +317,13 @@ namespace hw {
{
// sending change to yourself; derivation = a*R
r = generate_key_derivation(txkey_pub, sender_account_keys.m_view_secret_key, derivation);
CHECK_AND_ASSERT_MES(r, false, "at creation outs: failed to generate_key_derivation(" << txkey_pub << ", <viewkey>)");
CHECK_AND_ASSERT_MES(r, false, "at creation outs: failed to generate_key_derivation(" << txkey_pub << ", " << sender_account_keys.m_view_secret_key << ")");
}
else
{
// sending to the recipient; derivation = r*A (or s*C in the subaddress scheme)
const crypto::secret_key &tx_privkey{dst_entr.is_subaddress && need_additional_txkeys ? additional_txkey.sec : tx_key};
r = generate_key_derivation(dst_entr.addr.m_view_public_key, tx_privkey, derivation);
CHECK_AND_ASSERT_MES(r, false, "at creation outs: failed to generate_key_derivation("
<< dst_entr.addr.m_view_public_key << ", " << crypto::secret_key_explicit_print_ref{tx_privkey} << ")");
r = generate_key_derivation(dst_entr.addr.m_view_public_key, dst_entr.is_subaddress && need_additional_txkeys ? additional_txkey.sec : tx_key, derivation);
CHECK_AND_ASSERT_MES(r, false, "at creation outs: failed to generate_key_derivation(" << dst_entr.addr.m_view_public_key << ", " << (dst_entr.is_subaddress && need_additional_txkeys ? additional_txkey.sec : tx_key) << ")");
}
if (need_additional_txkeys)

View File

@@ -527,7 +527,6 @@ namespace hw {
{0x2c97, 0x0004, 0, 0xffa0},
{0x2c97, 0x0005, 0, 0xffa0},
{0x2c97, 0x0006, 0, 0xffa0},
{0x2c97, 0x0007, 0, 0xffa0},
};
bool device_ledger::connect(void) {

View File

@@ -133,7 +133,6 @@ namespace lmdb
//! \pre `!is_end()` \return Current key
K get_key() const noexcept
{
static_assert(std::is_trivially_copyable<K>(), "key is not memcpy safe");
assert(!is_end());
K out;
std::memcpy(std::addressof(out), key.data(), sizeof(out));

View File

@@ -55,7 +55,7 @@ namespace lmdb
static expect<F> get_value(MDB_val value) noexcept
{
static_assert(std::is_same<U, V>(), "bad MONERO_FIELD?");
static_assert(std::is_trivially_copyable<F>(), "F must be memcpy safe");
static_assert(std::is_pod<F>(), "F must be POD");
static_assert(sizeof(F) + offset <= sizeof(U), "bad field type and/or offset");
if (value.mv_size != sizeof(U))

View File

@@ -111,7 +111,6 @@ namespace lmdb
template<typename T, std::size_t offset = 0>
inline int less(MDB_val const* left, MDB_val const* right) noexcept
{
static_assert(std::is_trivially_copyable<T>(), "memcpy will not work");
if (!left || !right || left->mv_size < sizeof(T) + offset || right->mv_size < sizeof(T) + offset)
{
assert("invalid use of custom comparison" == 0);
@@ -128,7 +127,7 @@ namespace lmdb
/*!
A LMDB comparison function that uses `std::memcmp`.
\toaram T has standard layout and an alignment of 1
\toaram T is `!epee::has_padding`
\tparam offset to `T` within the value.
\return The result of `std::memcmp` over the value.
@@ -136,7 +135,7 @@ namespace lmdb
template<typename T, std::size_t offset = 0>
inline int compare(MDB_val const* left, MDB_val const* right) noexcept
{
static_assert(std::is_standard_layout<T>() && alignof(T) == 1, "memcmp will not work");
static_assert(!epee::has_padding<T>(), "memcmp will not work");
if (!left || !right || left->mv_size < sizeof(T) + offset || right->mv_size < sizeof(T) + offset)
{
assert("invalid use of custom comparison" == 0);

View File

@@ -162,8 +162,8 @@ namespace lmdb
G get_value() const noexcept
{
static_assert(std::is_same<U, T>(), "bad MONERO_FIELD usage?");
static_assert(std::is_trivially_copyable<U>(), "value type must be memcpy safe");
static_assert(std::is_trivially_copyable<G>(), "field type must be memcpy safe");
static_assert(std::is_pod<U>(), "value type must be pod");
static_assert(std::is_pod<G>(), "field type must be pod");
static_assert(sizeof(G) + uoffset <= sizeof(U), "bad field and/or offset");
assert(sizeof(G) + uoffset <= values.size());
assert(!is_end());

View File

@@ -206,13 +206,8 @@ namespace multisig
//----------------------------------------------------------------------------------------------------------------------
void multisig_kex_msg::parse_and_validate_msg()
{
CHECK_AND_ASSERT_THROW_MES(MULTISIG_KEX_MSG_V2_MAGIC_1.size() == MULTISIG_KEX_MSG_V2_MAGIC_N.size(),
"Multisig kex msg magic inconsistency.");
CHECK_AND_ASSERT_THROW_MES(MULTISIG_KEX_MSG_V2_MAGIC_1.size() >= MULTISIG_KEX_V1_MAGIC.size(),
"Multisig kex msg magic inconsistency.");
// check message type
CHECK_AND_ASSERT_THROW_MES(m_msg.size() >= MULTISIG_KEX_MSG_V2_MAGIC_1.size(), "Kex message unexpectedly small.");
CHECK_AND_ASSERT_THROW_MES(m_msg.size() > 0, "Kex message unexpectedly empty.");
CHECK_AND_ASSERT_THROW_MES(m_msg.substr(0, MULTISIG_KEX_V1_MAGIC.size()) != MULTISIG_KEX_V1_MAGIC,
"V1 multisig kex messages are deprecated (unsafe).");
CHECK_AND_ASSERT_THROW_MES(m_msg.substr(0, MULTISIG_KEX_MSG_V1_MAGIC.size()) != MULTISIG_KEX_MSG_V1_MAGIC,
@@ -220,6 +215,8 @@ namespace multisig
// deserialize the message
std::string msg_no_magic;
CHECK_AND_ASSERT_THROW_MES(MULTISIG_KEX_MSG_V2_MAGIC_1.size() == MULTISIG_KEX_MSG_V2_MAGIC_N.size(),
"Multisig kex msg magic inconsistency.");
CHECK_AND_ASSERT_THROW_MES(tools::base58::decode(m_msg.substr(MULTISIG_KEX_MSG_V2_MAGIC_1.size()), msg_no_magic),
"Multisig kex msg decoding error.");
binary_archive<false> b_archive{epee::strspan<std::uint8_t>(msg_no_magic)};

View File

@@ -820,6 +820,7 @@ tx_builder_ringct_t::~tx_builder_ringct_t()
bool tx_builder_ringct_t::init(
const cryptonote::account_keys& account_keys,
const std::vector<std::uint8_t>& extra,
const std::uint64_t unlock_time,
const std::uint32_t subaddr_account,
const std::set<std::uint32_t>& subaddr_minor_indices,
std::vector<cryptonote::tx_source_entry>& sources,
@@ -853,7 +854,7 @@ bool tx_builder_ringct_t::init(
// misc. fields
unsigned_tx.version = 2; //rct = 2
unsigned_tx.unlock_time = 0;
unsigned_tx.unlock_time = unlock_time;
// sort inputs
sort_sources(sources);

View File

@@ -71,6 +71,7 @@ public:
bool init(
const cryptonote::account_keys& account_keys,
const std::vector<std::uint8_t>& extra,
const std::uint64_t unlock_time,
const std::uint32_t subaddr_account,
const std::set<std::uint32_t>& subaddr_minor_indices,
std::vector<cryptonote::tx_source_entry>& sources,

View File

@@ -71,7 +71,7 @@ namespace net
struct i2p_serialized
{
std::string host;
std::uint16_t port; //! Leave for compatability with older clients
std::uint16_t port;
BEGIN_KV_SERIALIZE_MAP()
KV_SERIALIZE(host)
@@ -80,7 +80,8 @@ namespace net
};
}
i2p_address::i2p_address(const boost::string_ref host) noexcept
i2p_address::i2p_address(const boost::string_ref host, const std::uint16_t port) noexcept
: port_(port)
{
// this is a private constructor, throw if moved to public
assert(host.size() < sizeof(host_));
@@ -96,19 +97,27 @@ namespace net
}
i2p_address::i2p_address() noexcept
: port_(0)
{
static_assert(sizeof(unknown_host) <= sizeof(host_), "bad buffer size");
std::memcpy(host_, unknown_host, sizeof(unknown_host));
std::memset(host_ + sizeof(unknown_host), 0, sizeof(host_) - sizeof(unknown_host));
}
expect<i2p_address> i2p_address::make(const boost::string_ref address)
expect<i2p_address> i2p_address::make(const boost::string_ref address, const std::uint16_t default_port)
{
boost::string_ref host = address.substr(0, address.rfind(':'));
const boost::string_ref port =
address.substr(host.size() + (host.size() == address.size() ? 0 : 1));
MONERO_CHECK(host_check(host));
std::uint16_t porti = default_port;
if (!port.empty() && !epee::string_tools::get_xtype_from_string(porti, std::string{port}))
return {net::error::invalid_port};
static_assert(b32_length + sizeof(tld) == sizeof(i2p_address::host_), "bad internal host size");
return i2p_address{host};
return i2p_address{host, porti};
}
bool i2p_address::_load(epee::serialization::portable_storage& src, epee::serialization::section* hparent)
@@ -118,21 +127,23 @@ namespace net
{
std::memcpy(host_, in.host.data(), in.host.size());
std::memset(host_ + in.host.size(), 0, sizeof(host_) - in.host.size());
port_ = in.port;
return true;
}
static_assert(sizeof(unknown_host) <= sizeof(host_), "bad buffer size");
std::memcpy(host_, unknown_host, sizeof(unknown_host)); // include null terminator
port_ = 0;
return false;
}
bool i2p_address::store(epee::serialization::portable_storage& dest, epee::serialization::section* hparent) const
{
// Set port to 1 for backwards compatability; zero is invalid port
const i2p_serialized out{std::string{host_}, 1};
const i2p_serialized out{std::string{host_}, port_};
return out.store(dest, hparent);
}
i2p_address::i2p_address(const i2p_address& rhs) noexcept
: port_(rhs.port_)
{
std::memcpy(host_, rhs.host_, sizeof(host_));
}
@@ -141,6 +152,7 @@ namespace net
{
if (this != std::addressof(rhs))
{
port_ = rhs.port_;
std::memcpy(host_, rhs.host_, sizeof(host_));
}
return *this;
@@ -154,12 +166,13 @@ namespace net
bool i2p_address::equal(const i2p_address& rhs) const noexcept
{
return is_same_host(rhs);
return port_ == rhs.port_ && is_same_host(rhs);
}
bool i2p_address::less(const i2p_address& rhs) const noexcept
{
return std::strcmp(host_str(), rhs.host_str()) < 0;
int res = std::strcmp(host_str(), rhs.host_str());
return res < 0 || (res == 0 && port() < rhs.port());
}
bool i2p_address::is_same_host(const i2p_address& rhs) const noexcept
@@ -169,6 +182,20 @@ namespace net
std::string i2p_address::str() const
{
return host_str();
const std::size_t host_length = std::strlen(host_str());
const std::size_t port_length =
port_ == 0 ? 0 : std::numeric_limits<std::uint16_t>::digits10 + 2;
std::string out{};
out.reserve(host_length + port_length);
out.assign(host_str(), host_length);
if (port_ != 0)
{
out.push_back(':');
namespace karma = boost::spirit::karma;
karma::generate(std::back_inserter(out), karma::ushort_, port());
}
return out;
}
}

View File

@@ -50,10 +50,11 @@ namespace net
//! b32 i2p address; internal format not condensed/decoded.
class i2p_address
{
std::uint16_t port_;
char host_[61]; // null-terminated
//! Keep in private, `host.size()` has no runtime check
i2p_address(boost::string_ref host) noexcept;
i2p_address(boost::string_ref host, std::uint16_t port) noexcept;
public:
//! \return Size of internal buffer for host.
@@ -73,7 +74,7 @@ namespace net
with `default_port` being used if port is not specified in
`address`.
*/
static expect<i2p_address> make(boost::string_ref address);
static expect<i2p_address> make(boost::string_ref address, std::uint16_t default_port = 0);
//! Load from epee p2p format, and \return false if not valid tor address
bool _load(epee::serialization::portable_storage& src, epee::serialization::section* hparent);
@@ -102,8 +103,8 @@ namespace net
//! \return Null-terminated `x.b32.i2p` value or `unknown_str()`.
const char* host_str() const noexcept { return host_; }
//! \return `1` to work with I2P socks which considers `0` error.
std::uint16_t port() const noexcept { return 1; }
//! \return Port value or `0` if unspecified.
std::uint16_t port() const noexcept { return port_; }
static constexpr bool is_loopback() noexcept { return false; }
static constexpr bool is_local() noexcept { return false; }

View File

@@ -81,7 +81,7 @@ namespace net
if (host_str_ref.ends_with(".onion"))
return tor_address::make(address, default_port);
if (host_str_ref.ends_with(".i2p"))
return i2p_address::make(address);
return i2p_address::make(address, default_port);
boost::system::error_code ec;
boost::asio::ip::address_v6 v6 = boost::asio::ip::address_v6::from_string(host_str, ec);

View File

@@ -531,16 +531,6 @@ namespace nodetool
std::istringstream iss(banned_ips);
for (std::string line; std::getline(iss, line); )
{
// ignore comments after '#' character
const size_t pound_idx = line.find('#');
if (pound_idx != std::string::npos)
line.resize(pound_idx);
// trim whitespace and ignore empty lines
boost::trim(line);
if (line.empty())
continue;
auto subnet = net::get_ipv4_subnet_address(line);
if (subnet)
{
@@ -724,15 +714,20 @@ namespace nodetool
}
else
{
full_addrs.insert("158.69.60.225:34567"); // explore.wownero.com
full_addrs.insert("159.65.91.59:34567"); // jw
//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
full_addrs.insert("192.99.8.110:34567"); // node.monerodevs.org
full_addrs.insert("37.187.74.171"); // node2.monerodevs.org
full_addrs.insert("88.99.195.15"); // node3.monerodevs.org
full_addrs.insert("172.67.197.39:34567"); // wowmom.0z.network
full_addrs.insert("195.94.188.201:34567"); // spippolatori.it
full_addrs.insert("37.187.74.171:34567"); // node2.monerodevs.org
}
return full_addrs;
}
@@ -864,8 +859,11 @@ namespace nodetool
{
return {
"77uase4p6y6jsjdf6z2kdgpxgh7nkvywagvhurzphbm7vrkyj2d2gdid.onion:34566",
"jhy4hqymdkfj2u7bdi7m2vr5qheom7gjyg7fraktnlyksalhmpbemiqd.onion:34566",
"v2admi6gbeprxnk6i2oscizhgy4v5ixu6iezkhj5udiwbfjjs2w7dnid.onion:34566",
"ttc6kxud3fikyaypn5voknyyvqje7j3wnoevsb7rfjerolynnisurkqd.onion:34566",
"5enbij6tz3n2hw5ixzezfayd5gvckyg4xlktz74gj4l6u7olq7ovr3id.onion:34566",
"ukpgpdd5gqvholcctejvaaig5hb266td6zaszt55eivuf7docoox5lid.onion:34566",
"iorkdy6t4gdtwzn3iblnhy76nu7lhyz2qcvpj4wrspfxyvdrul7u22qd.onion:34566",
};
}
return {};
@@ -873,6 +871,9 @@ namespace nodetool
if (m_nettype == cryptonote::MAINNET)
{
return {
"lrq65qrhpbt5voom2ncvowpes6kvobodkldhpuwhxlsrpugmgmlq.b32.i2p:34565",
"72tbpgeczdtx2q2enbyaqcot7mghbnjenjkmdpyylrssqehr746a.b32.i2p:34565",
"rkel2qy7xv3cc5bnxfrzwgh3jvd4woagd4vlhr3qsdxy6cfkimnq.b32.i2p:34565",
};
}
return {};
@@ -2288,12 +2289,11 @@ namespace nodetool
if (enet::zone::tor < network->first)
break; // unknown network
const auto status = network->second.m_notifier.get_status();
if (network->second.m_connect && status.has_outgoing)
if (network->second.m_connect)
return send(*network);
}
MWARNING("Unable to send " << txs.size() << " transaction(s): anonymity networks had no outgoing connections");
// configuration should not allow this scenario
return enet::zone::invalid;
}
//-----------------------------------------------------------------------------------

View File

@@ -42,7 +42,6 @@
#include <boost/serialization/version.hpp>
#include "net_peerlist_boost_serialization.h"
#include "common/util.h"
namespace nodetool
@@ -201,7 +200,7 @@ namespace nodetool
if (!out)
{
// if failed, try reading in unportable mode
tools::copy_file(path, path + ".unportable");
boost::filesystem::copy_file(path, path + ".unportable", boost::filesystem::copy_option::overwrite_if_exists);
src_file.close();
src_file.open( path , std::ios_base::binary | std::ios_base::in);
if(src_file.fail())

View File

@@ -196,7 +196,7 @@ namespace boost
if (std::strcmp(host, net::i2p_address::unknown_str()) == 0)
na = net::i2p_address::unknown();
else
na = MONERO_UNWRAP(net::i2p_address::make(host));
na = MONERO_UNWRAP(net::i2p_address::make(host, port));
}
template <class Archive, class ver_type>

View File

@@ -329,10 +329,6 @@ namespace rct {
ctkeyV outPk;
xmr_amount txnFee; // contains b
rctSigBase() :
type(RCTTypeNull), message{}, mixRing{}, pseudoOuts{}, ecdhInfo{}, outPk{}, txnFee(0)
{}
template<bool W, template <bool> class Archive>
bool serialize_rctsig_base(Archive<W> &ar, size_t inputs, size_t outputs)
{
@@ -370,17 +366,11 @@ namespace rct {
{
if (type == RCTTypeBulletproof2 || type == RCTTypeCLSAG || type == RCTTypeBulletproofPlus)
{
// Since RCTTypeBulletproof2 enote types, we don't serialize the blinding factor, and only serialize the
// first 8 bytes of ecdhInfo[i].amount
ar.begin_object();
crypto::hash8 trunc_amount; // placeholder variable needed to maintain "strict aliasing"
if (!typename Archive<W>::is_saving()) // loading
if (!typename Archive<W>::is_saving())
memset(ecdhInfo[i].amount.bytes, 0, sizeof(ecdhInfo[i].amount.bytes));
else // saving
memcpy(trunc_amount.data, ecdhInfo[i].amount.bytes, sizeof(trunc_amount));
FIELD_N("amount", trunc_amount);
if (!typename Archive<W>::is_saving()) // loading
memcpy(ecdhInfo[i].amount.bytes, trunc_amount.data, sizeof(trunc_amount));
crypto::hash8 &amount = (crypto::hash8&)ecdhInfo[i].amount;
FIELD(amount);
ar.end_object();
}
else

View File

@@ -1341,8 +1341,6 @@ namespace cryptonote
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");
if ((res.nonzero_unlock_time = tvc.m_nonzero_unlock_time))
add_reason(reason, "tx unlock time is not zero");
const std::string punctuation = reason.empty() ? "" : ": ";
if (tvc.m_verifivation_failed)
{

View File

@@ -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 14
#define CORE_RPC_VERSION_MINOR 13
#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)
@@ -640,7 +640,6 @@ namespace cryptonote
bool too_few_outputs;
bool sanity_check_failed;
bool tx_extra_too_big;
bool nonzero_unlock_time;
BEGIN_KV_SERIALIZE_MAP()
KV_SERIALIZE_PARENT(rpc_access_response_base)
@@ -656,7 +655,6 @@ namespace cryptonote
KV_SERIALIZE(too_few_outputs)
KV_SERIALIZE(sanity_check_failed)
KV_SERIALIZE(tx_extra_too_big)
KV_SERIALIZE(nonzero_unlock_time)
END_KV_SERIALIZE_MAP()
};
typedef epee::misc_utils::struct_init<response_t> response;

View File

@@ -422,16 +422,6 @@ namespace rpc
if (!res.error_details.empty()) res.error_details += " and ";
res.error_details += "too few outputs";
}
if (tvc.m_tx_extra_too_big)
{
if (!res.error_details.empty()) res.error_details += " and ";
res.error_details += "tx_extra too long";
}
if (tvc.m_nonzero_unlock_time)
{
if (!res.error_details.empty()) res.error_details += " and ";
res.error_details += "non-zero unlock time";
}
if (res.error_details.empty())
{
res.error_details = "an unknown issue was found with the transaction";
@@ -520,8 +510,6 @@ namespace rpc
res.info.target_height = res.info.height;
}
m_core.get_blockchain_top(res.info.top_block_height, res.info.top_block_hash);
auto& chain = m_core.get_blockchain_storage();
res.info.wide_difficulty = chain.get_difficulty_for_next_block();

View File

@@ -48,11 +48,6 @@ void GetHeight::Response::doToJson(rapidjson::Writer<epee::byte_stream>& dest) c
void GetHeight::Response::fromJson(const rapidjson::Value& val)
{
if (!val.IsObject())
{
throw json::WRONG_TYPE("json object");
}
GET_FROM_JSON_OBJECT(val, height, height);
}
@@ -66,11 +61,6 @@ void GetBlocksFast::Request::doToJson(rapidjson::Writer<epee::byte_stream>& dest
void GetBlocksFast::Request::fromJson(const rapidjson::Value& val)
{
if (!val.IsObject())
{
throw json::WRONG_TYPE("json object");
}
GET_FROM_JSON_OBJECT(val, block_ids, block_ids);
GET_FROM_JSON_OBJECT(val, start_height, start_height);
GET_FROM_JSON_OBJECT(val, prune, prune);
@@ -86,11 +76,6 @@ void GetBlocksFast::Response::doToJson(rapidjson::Writer<epee::byte_stream>& des
void GetBlocksFast::Response::fromJson(const rapidjson::Value& val)
{
if (!val.IsObject())
{
throw json::WRONG_TYPE("json object");
}
GET_FROM_JSON_OBJECT(val, blocks, blocks);
GET_FROM_JSON_OBJECT(val, start_height, start_height);
GET_FROM_JSON_OBJECT(val, current_height, current_height);
@@ -106,11 +91,6 @@ void GetHashesFast::Request::doToJson(rapidjson::Writer<epee::byte_stream>& dest
void GetHashesFast::Request::fromJson(const rapidjson::Value& val)
{
if (!val.IsObject())
{
throw json::WRONG_TYPE("json object");
}
GET_FROM_JSON_OBJECT(val, known_hashes, known_hashes);
GET_FROM_JSON_OBJECT(val, start_height, start_height);
}
@@ -120,16 +100,10 @@ void GetHashesFast::Response::doToJson(rapidjson::Writer<epee::byte_stream>& des
INSERT_INTO_JSON_OBJECT(dest, hashes, hashes);
INSERT_INTO_JSON_OBJECT(dest, start_height, start_height);
INSERT_INTO_JSON_OBJECT(dest, current_height, current_height);
}
void GetHashesFast::Response::fromJson(const rapidjson::Value& val)
{
if (!val.IsObject())
{
throw json::WRONG_TYPE("json object");
}
GET_FROM_JSON_OBJECT(val, hashes, hashes);
GET_FROM_JSON_OBJECT(val, start_height, start_height);
GET_FROM_JSON_OBJECT(val, current_height, current_height);
@@ -143,11 +117,6 @@ void GetTransactions::Request::doToJson(rapidjson::Writer<epee::byte_stream>& de
void GetTransactions::Request::fromJson(const rapidjson::Value& val)
{
if (!val.IsObject())
{
throw json::WRONG_TYPE("json object");
}
GET_FROM_JSON_OBJECT(val, tx_hashes, tx_hashes);
}
@@ -159,11 +128,6 @@ void GetTransactions::Response::doToJson(rapidjson::Writer<epee::byte_stream>& d
void GetTransactions::Response::fromJson(const rapidjson::Value& val)
{
if (!val.IsObject())
{
throw json::WRONG_TYPE("json object");
}
GET_FROM_JSON_OBJECT(val, txs, txs);
GET_FROM_JSON_OBJECT(val, missed_hashes, missed_hashes);
}
@@ -176,11 +140,6 @@ void KeyImagesSpent::Request::doToJson(rapidjson::Writer<epee::byte_stream>& des
void KeyImagesSpent::Request::fromJson(const rapidjson::Value& val)
{
if (!val.IsObject())
{
throw json::WRONG_TYPE("json object");
}
GET_FROM_JSON_OBJECT(val, key_images, key_images);
}
@@ -191,11 +150,6 @@ void KeyImagesSpent::Response::doToJson(rapidjson::Writer<epee::byte_stream>& de
void KeyImagesSpent::Response::fromJson(const rapidjson::Value& val)
{
if (!val.IsObject())
{
throw json::WRONG_TYPE("json object");
}
GET_FROM_JSON_OBJECT(val, spent_status, spent_status);
}
@@ -207,11 +161,6 @@ void GetTxGlobalOutputIndices::Request::doToJson(rapidjson::Writer<epee::byte_st
void GetTxGlobalOutputIndices::Request::fromJson(const rapidjson::Value& val)
{
if (!val.IsObject())
{
throw json::WRONG_TYPE("json object");
}
GET_FROM_JSON_OBJECT(val, tx_hash, tx_hash);
}
@@ -222,11 +171,6 @@ void GetTxGlobalOutputIndices::Response::doToJson(rapidjson::Writer<epee::byte_s
void GetTxGlobalOutputIndices::Response::fromJson(const rapidjson::Value& val)
{
if (!val.IsObject())
{
throw json::WRONG_TYPE("json object");
}
GET_FROM_JSON_OBJECT(val, output_indices, output_indices);
}
@@ -238,11 +182,6 @@ void SendRawTx::Request::doToJson(rapidjson::Writer<epee::byte_stream>& dest) co
void SendRawTx::Request::fromJson(const rapidjson::Value& val)
{
if (!val.IsObject())
{
throw json::WRONG_TYPE("json object");
}
GET_FROM_JSON_OBJECT(val, tx, tx);
GET_FROM_JSON_OBJECT(val, relay, relay);
}
@@ -255,11 +194,6 @@ void SendRawTx::Response::doToJson(rapidjson::Writer<epee::byte_stream>& dest) c
void SendRawTx::Response::fromJson(const rapidjson::Value& val)
{
if (!val.IsObject())
{
throw json::WRONG_TYPE("json object");
}
GET_FROM_JSON_OBJECT(val, relayed, relayed);
}
@@ -271,11 +205,6 @@ void SendRawTxHex::Request::doToJson(rapidjson::Writer<epee::byte_stream>& dest)
void SendRawTxHex::Request::fromJson(const rapidjson::Value& val)
{
if (!val.IsObject())
{
throw json::WRONG_TYPE("json object");
}
GET_FROM_JSON_OBJECT(val, tx_as_hex, tx_as_hex);
GET_FROM_JSON_OBJECT(val, relay, relay);
}
@@ -290,11 +219,6 @@ void StartMining::Request::doToJson(rapidjson::Writer<epee::byte_stream>& dest)
void StartMining::Request::fromJson(const rapidjson::Value& val)
{
if (!val.IsObject())
{
throw json::WRONG_TYPE("json object");
}
GET_FROM_JSON_OBJECT(val, miner_address, miner_address);
GET_FROM_JSON_OBJECT(val, threads_count, threads_count);
GET_FROM_JSON_OBJECT(val, do_background_mining, do_background_mining);
@@ -342,11 +266,6 @@ void MiningStatus::Response::doToJson(rapidjson::Writer<epee::byte_stream>& dest
void MiningStatus::Response::fromJson(const rapidjson::Value& val)
{
if (!val.IsObject())
{
throw json::WRONG_TYPE("json object");
}
GET_FROM_JSON_OBJECT(val, active, active);
GET_FROM_JSON_OBJECT(val, speed, speed);
GET_FROM_JSON_OBJECT(val, threads_count, threads_count);
@@ -369,11 +288,6 @@ void GetInfo::Response::doToJson(rapidjson::Writer<epee::byte_stream>& dest) con
void GetInfo::Response::fromJson(const rapidjson::Value& val)
{
if (!val.IsObject())
{
throw json::WRONG_TYPE("json object");
}
GET_FROM_JSON_OBJECT(val, info, info);
}
@@ -400,11 +314,6 @@ void GetBlockHash::Request::doToJson(rapidjson::Writer<epee::byte_stream>& dest)
void GetBlockHash::Request::fromJson(const rapidjson::Value& val)
{
if (!val.IsObject())
{
throw json::WRONG_TYPE("json object");
}
GET_FROM_JSON_OBJECT(val, height, height);
}
@@ -415,11 +324,6 @@ void GetBlockHash::Response::doToJson(rapidjson::Writer<epee::byte_stream>& dest
void GetBlockHash::Response::fromJson(const rapidjson::Value& val)
{
if (!val.IsObject())
{
throw json::WRONG_TYPE("json object");
}
GET_FROM_JSON_OBJECT(val, hash, hash);
}
@@ -438,11 +342,6 @@ void GetLastBlockHeader::Response::doToJson(rapidjson::Writer<epee::byte_stream>
void GetLastBlockHeader::Response::fromJson(const rapidjson::Value& val)
{
if (!val.IsObject())
{
throw json::WRONG_TYPE("json object");
}
GET_FROM_JSON_OBJECT(val, header, header);
}
@@ -454,11 +353,6 @@ void GetBlockHeaderByHash::Request::doToJson(rapidjson::Writer<epee::byte_stream
void GetBlockHeaderByHash::Request::fromJson(const rapidjson::Value& val)
{
if (!val.IsObject())
{
throw json::WRONG_TYPE("json object");
}
GET_FROM_JSON_OBJECT(val, hash, hash);
}
@@ -469,11 +363,6 @@ void GetBlockHeaderByHash::Response::doToJson(rapidjson::Writer<epee::byte_strea
void GetBlockHeaderByHash::Response::fromJson(const rapidjson::Value& val)
{
if (!val.IsObject())
{
throw json::WRONG_TYPE("json object");
}
GET_FROM_JSON_OBJECT(val, header, header);
}
@@ -485,11 +374,6 @@ void GetBlockHeaderByHeight::Request::doToJson(rapidjson::Writer<epee::byte_stre
void GetBlockHeaderByHeight::Request::fromJson(const rapidjson::Value& val)
{
if (!val.IsObject())
{
throw json::WRONG_TYPE("json object");
}
GET_FROM_JSON_OBJECT(val, height, height);
}
@@ -500,11 +384,6 @@ void GetBlockHeaderByHeight::Response::doToJson(rapidjson::Writer<epee::byte_str
void GetBlockHeaderByHeight::Response::fromJson(const rapidjson::Value& val)
{
if (!val.IsObject())
{
throw json::WRONG_TYPE("json object");
}
GET_FROM_JSON_OBJECT(val, header, header);
}
@@ -516,11 +395,6 @@ void GetBlockHeadersByHeight::Request::doToJson(rapidjson::Writer<epee::byte_str
void GetBlockHeadersByHeight::Request::fromJson(const rapidjson::Value& val)
{
if (!val.IsObject())
{
throw json::WRONG_TYPE("json object");
}
GET_FROM_JSON_OBJECT(val, heights, heights);
}
@@ -531,11 +405,6 @@ void GetBlockHeadersByHeight::Response::doToJson(rapidjson::Writer<epee::byte_st
void GetBlockHeadersByHeight::Response::fromJson(const rapidjson::Value& val)
{
if (!val.IsObject())
{
throw json::WRONG_TYPE("json object");
}
GET_FROM_JSON_OBJECT(val, headers, headers);
}
@@ -555,11 +424,6 @@ void GetPeerList::Response::doToJson(rapidjson::Writer<epee::byte_stream>& dest)
void GetPeerList::Response::fromJson(const rapidjson::Value& val)
{
if (!val.IsObject())
{
throw json::WRONG_TYPE("json object");
}
GET_FROM_JSON_OBJECT(val, white_list, white_list);
GET_FROM_JSON_OBJECT(val, gray_list, gray_list);
}
@@ -572,11 +436,6 @@ void SetLogLevel::Request::doToJson(rapidjson::Writer<epee::byte_stream>& dest)
void SetLogLevel::Request::fromJson(const rapidjson::Value& val)
{
if (!val.IsObject())
{
throw json::WRONG_TYPE("json object");
}
GET_FROM_JSON_OBJECT(val, level, level);
}
@@ -603,11 +462,6 @@ void GetTransactionPool::Response::doToJson(rapidjson::Writer<epee::byte_stream>
void GetTransactionPool::Response::fromJson(const rapidjson::Value& val)
{
if (!val.IsObject())
{
throw json::WRONG_TYPE("json object");
}
GET_FROM_JSON_OBJECT(val, transactions, transactions);
GET_FROM_JSON_OBJECT(val, key_images, key_images);
}
@@ -620,11 +474,6 @@ void HardForkInfo::Request::doToJson(rapidjson::Writer<epee::byte_stream>& dest)
void HardForkInfo::Request::fromJson(const rapidjson::Value& val)
{
if (!val.IsObject())
{
throw json::WRONG_TYPE("json object");
}
GET_FROM_JSON_OBJECT(val, version, version);
}
@@ -635,11 +484,6 @@ void HardForkInfo::Response::doToJson(rapidjson::Writer<epee::byte_stream>& dest
void HardForkInfo::Response::fromJson(const rapidjson::Value& val)
{
if (!val.IsObject())
{
throw json::WRONG_TYPE("json object");
}
GET_FROM_JSON_OBJECT(val, info, info);
}
@@ -655,11 +499,6 @@ void GetOutputHistogram::Request::doToJson(rapidjson::Writer<epee::byte_stream>&
void GetOutputHistogram::Request::fromJson(const rapidjson::Value& val)
{
if (!val.IsObject())
{
throw json::WRONG_TYPE("json object");
}
GET_FROM_JSON_OBJECT(val, amounts, amounts);
GET_FROM_JSON_OBJECT(val, min_count, min_count);
GET_FROM_JSON_OBJECT(val, max_count, max_count);
@@ -674,11 +513,6 @@ void GetOutputHistogram::Response::doToJson(rapidjson::Writer<epee::byte_stream>
void GetOutputHistogram::Response::fromJson(const rapidjson::Value& val)
{
if (!val.IsObject())
{
throw json::WRONG_TYPE("json object");
}
GET_FROM_JSON_OBJECT(val, histogram, histogram);
}
@@ -690,11 +524,6 @@ void GetOutputKeys::Request::doToJson(rapidjson::Writer<epee::byte_stream>& dest
void GetOutputKeys::Request::fromJson(const rapidjson::Value& val)
{
if (!val.IsObject())
{
throw json::WRONG_TYPE("json object");
}
GET_FROM_JSON_OBJECT(val, outputs, outputs);
}
@@ -705,11 +534,6 @@ void GetOutputKeys::Response::doToJson(rapidjson::Writer<epee::byte_stream>& des
void GetOutputKeys::Response::fromJson(const rapidjson::Value& val)
{
if (!val.IsObject())
{
throw json::WRONG_TYPE("json object");
}
GET_FROM_JSON_OBJECT(val, keys, keys);
}
@@ -728,11 +552,6 @@ void GetRPCVersion::Response::doToJson(rapidjson::Writer<epee::byte_stream>& des
void GetRPCVersion::Response::fromJson(const rapidjson::Value& val)
{
if (!val.IsObject())
{
throw json::WRONG_TYPE("json object");
}
GET_FROM_JSON_OBJECT(val, version, version);
}
@@ -743,11 +562,6 @@ void GetFeeEstimate::Request::doToJson(rapidjson::Writer<epee::byte_stream>& des
void GetFeeEstimate::Request::fromJson(const rapidjson::Value& val)
{
if (!val.IsObject())
{
throw json::WRONG_TYPE("json object");
}
GET_FROM_JSON_OBJECT(val, num_grace_blocks, num_grace_blocks);
}
@@ -761,11 +575,6 @@ void GetFeeEstimate::Response::doToJson(rapidjson::Writer<epee::byte_stream>& de
void GetFeeEstimate::Response::fromJson(const rapidjson::Value& val)
{
if (!val.IsObject())
{
throw json::WRONG_TYPE("json object");
}
GET_FROM_JSON_OBJECT(val, estimated_base_fee, estimated_base_fee);
GET_FROM_JSON_OBJECT(val, fee_mask, fee_mask);
GET_FROM_JSON_OBJECT(val, size_scale, size_scale);
@@ -782,11 +591,6 @@ void GetOutputDistribution::Request::doToJson(rapidjson::Writer<epee::byte_strea
void GetOutputDistribution::Request::fromJson(const rapidjson::Value& val)
{
if (!val.IsObject())
{
throw json::WRONG_TYPE("json object");
}
GET_FROM_JSON_OBJECT(val, amounts, amounts);
GET_FROM_JSON_OBJECT(val, from_height, from_height);
GET_FROM_JSON_OBJECT(val, to_height, to_height);
@@ -801,11 +605,6 @@ void GetOutputDistribution::Response::doToJson(rapidjson::Writer<epee::byte_stre
void GetOutputDistribution::Response::fromJson(const rapidjson::Value& val)
{
if (!val.IsObject())
{
throw json::WRONG_TYPE("json object");
}
GET_FROM_JSON_OBJECT(val, status, status);
GET_FROM_JSON_OBJECT(val, distributions, distributions);
}

View File

@@ -178,7 +178,6 @@ namespace rpc
{
uint64_t height;
uint64_t target_height;
uint64_t top_block_height;
cryptonote::difficulty_type wide_difficulty;
uint64_t difficulty;
uint64_t target;

View File

@@ -158,22 +158,13 @@ void ZmqServer::serve()
if (!pub || sockets[2].revents)
{
expect<std::string> message = net::zmq::receive(rep.get(), read_flags);
if (!message)
{
// EAGAIN can occur when using `zmq_poll`, which doesn't inspect for message validity
if (message != net::zmq::make_error_code(EAGAIN))
MONERO_THROW(message.error(), "Read failure on ZMQ-RPC");
}
else // no errors
{
MDEBUG("Received RPC request: \"" << *message << "\"");
epee::byte_slice response = handler.handle(std::move(*message));
std::string message = MONERO_UNWRAP(net::zmq::receive(rep.get(), read_flags));
MDEBUG("Received RPC request: \"" << message << "\"");
epee::byte_slice response = handler.handle(std::move(message));
const boost::string_ref response_view{reinterpret_cast<const char*>(response.data()), response.size()};
MDEBUG("Sending RPC reply: \"" << response_view << "\"");
MONERO_UNWRAP(net::zmq::send(std::move(response), rep.get()));
}
const boost::string_ref response_view{reinterpret_cast<const char*>(response.data()), response.size()};
MDEBUG("Sending RPC reply: \"" << response_view << "\"");
MONERO_UNWRAP(net::zmq::send(std::move(response), rep.get()));
}
}
}

View File

@@ -42,7 +42,7 @@ namespace serialization
typename std::enable_if<!use_container_varint<T>(), bool>::type
serialize_container_element(Archive& ar, T& e)
{
return do_serialize(ar, e);
return ::do_serialize(ar, e);
}
template<typename Archive, typename T>
@@ -52,7 +52,7 @@ namespace serialization
static constexpr const bool previously_varint = std::is_same<uint64_t, T>() || std::is_same<uint32_t, T>();
if (!previously_varint && ar.varint_bug_backward_compatibility_enabled() && !typename Archive::is_saving())
return do_serialize(ar, e);
return ::do_serialize(ar, e);
ar.serialize_varint(e);
return true;
}

View File

@@ -42,12 +42,14 @@ struct debug_archive : public json_archive<W> {
};
template <class T>
static inline bool do_serialize(debug_archive<true> &ar, T &v)
struct serializer<debug_archive<true>, T>
{
static void serialize(debug_archive<true> &ar, T &v)
{
ar.begin_object();
ar.tag(variant_serialization_traits<debug_archive<true>, T>::get_tag());
do_serialize(static_cast<json_archive<true>&>(ar), v);
serializer<json_archive<true>, T>::serialize(ar, v);
ar.end_object();
ar.stream() << std::endl;
return true;
}
}
};

View File

@@ -31,6 +31,8 @@
#include "cryptonote_basic/difficulty.h"
#include "serialization.h"
template<> struct is_basic_type<cryptonote::difficulty_type> { typedef boost::true_type type; };
template <template <bool> class Archive>
inline bool do_serialize(Archive<false>& ar, cryptonote::difficulty_type &diff)
{

View File

@@ -273,10 +273,7 @@ void toJsonValue(rapidjson::Writer<epee::byte_stream>& dest, const cryptonote::t
{
INSERT_INTO_JSON_OBJECT(dest, signatures, tx.signatures);
}
{
dest.Key("ringct");
toJsonValue(dest, tx.rct_signatures, tx.pruned);
}
INSERT_INTO_JSON_OBJECT(dest, ringct, tx.rct_signatures);
dest.EndObject();
}
@@ -1120,7 +1117,7 @@ void fromJsonValue(const rapidjson::Value& val, cryptonote::rpc::BlockHeaderResp
GET_FROM_JSON_OBJECT(val, response.reward, reward);
}
void toJsonValue(rapidjson::Writer<epee::byte_stream>& dest, const rct::rctSig& sig, const bool prune)
void toJsonValue(rapidjson::Writer<epee::byte_stream>& dest, const rct::rctSig& sig)
{
using boost::adaptors::transform;
@@ -1140,7 +1137,7 @@ void toJsonValue(rapidjson::Writer<epee::byte_stream>& dest, const rct::rctSig&
}
// prunable
if (!prune && (!sig.p.bulletproofs.empty() || !sig.p.bulletproofs_plus.empty() || !sig.p.rangeSigs.empty() || !sig.p.MGs.empty() || !sig.get_pseudo_outs().empty()))
if (!sig.p.bulletproofs.empty() || !sig.p.bulletproofs_plus.empty() || !sig.p.rangeSigs.empty() || !sig.p.MGs.empty() || !sig.get_pseudo_outs().empty())
{
dest.Key("prunable");
dest.StartObject();
@@ -1432,14 +1429,9 @@ void toJsonValue(rapidjson::Writer<epee::byte_stream>& dest, const cryptonote::r
{
dest.StartObject();
const uint64_t difficulty_top64 = (info.wide_difficulty >> 64).convert_to<std::uint64_t>();
const uint64_t cumulative_difficulty_top64 = (info.wide_cumulative_difficulty >> 64).convert_to<std::uint64_t>();
INSERT_INTO_JSON_OBJECT(dest, height, info.height);
INSERT_INTO_JSON_OBJECT(dest, target_height, info.target_height);
INSERT_INTO_JSON_OBJECT(dest, top_block_height, info.top_block_height);
INSERT_INTO_JSON_OBJECT(dest, difficulty, info.difficulty);
INSERT_INTO_JSON_OBJECT(dest, difficulty_top64, difficulty_top64);
INSERT_INTO_JSON_OBJECT(dest, target, info.target);
INSERT_INTO_JSON_OBJECT(dest, tx_count, info.tx_count);
INSERT_INTO_JSON_OBJECT(dest, tx_pool_size, info.tx_pool_size);
@@ -1454,14 +1446,12 @@ void toJsonValue(rapidjson::Writer<epee::byte_stream>& dest, const cryptonote::r
INSERT_INTO_JSON_OBJECT(dest, nettype, info.nettype);
INSERT_INTO_JSON_OBJECT(dest, top_block_hash, info.top_block_hash);
INSERT_INTO_JSON_OBJECT(dest, cumulative_difficulty, info.cumulative_difficulty);
INSERT_INTO_JSON_OBJECT(dest, cumulative_difficulty_top64, cumulative_difficulty_top64);
INSERT_INTO_JSON_OBJECT(dest, block_size_limit, info.block_size_limit);
INSERT_INTO_JSON_OBJECT(dest, block_weight_limit, info.block_weight_limit);
INSERT_INTO_JSON_OBJECT(dest, block_size_median, info.block_size_median);
INSERT_INTO_JSON_OBJECT(dest, block_weight_median, info.block_weight_median);
INSERT_INTO_JSON_OBJECT(dest, adjusted_time, info.adjusted_time);
INSERT_INTO_JSON_OBJECT(dest, start_time, info.start_time);
INSERT_INTO_JSON_OBJECT(dest, version, info.version);
dest.EndObject();
}
@@ -1473,14 +1463,9 @@ void fromJsonValue(const rapidjson::Value& val, cryptonote::rpc::DaemonInfo& inf
throw WRONG_TYPE("json object");
}
uint64_t difficulty_top64 = 0;
uint64_t cumulative_difficulty_top64 = 0;
GET_FROM_JSON_OBJECT(val, info.height, height);
GET_FROM_JSON_OBJECT(val, info.target_height, target_height);
GET_FROM_JSON_OBJECT(val, info.top_block_height, top_block_height);
GET_FROM_JSON_OBJECT(val, info.difficulty, difficulty);
GET_FROM_JSON_OBJECT(val, difficulty_top64, difficulty_top64);
GET_FROM_JSON_OBJECT(val, info.target, target);
GET_FROM_JSON_OBJECT(val, info.tx_count, tx_count);
GET_FROM_JSON_OBJECT(val, info.tx_pool_size, tx_pool_size);
@@ -1495,22 +1480,12 @@ void fromJsonValue(const rapidjson::Value& val, cryptonote::rpc::DaemonInfo& inf
GET_FROM_JSON_OBJECT(val, info.nettype, nettype);
GET_FROM_JSON_OBJECT(val, info.top_block_hash, top_block_hash);
GET_FROM_JSON_OBJECT(val, info.cumulative_difficulty, cumulative_difficulty);
GET_FROM_JSON_OBJECT(val, cumulative_difficulty_top64, cumulative_difficulty_top64);
GET_FROM_JSON_OBJECT(val, info.block_size_limit, block_size_limit);
GET_FROM_JSON_OBJECT(val, info.block_weight_limit, block_weight_limit);
GET_FROM_JSON_OBJECT(val, info.block_size_median, block_size_median);
GET_FROM_JSON_OBJECT(val, info.block_weight_median, block_weight_median);
GET_FROM_JSON_OBJECT(val, info.adjusted_time, adjusted_time);
GET_FROM_JSON_OBJECT(val, info.start_time, start_time);
GET_FROM_JSON_OBJECT(val, info.version, version);
info.wide_difficulty = difficulty_top64;
info.wide_difficulty <<= 64;
info.wide_difficulty += info.difficulty;
info.wide_cumulative_difficulty = cumulative_difficulty_top64;
info.wide_cumulative_difficulty <<= 64;
info.wide_cumulative_difficulty += info.cumulative_difficulty;
}
void toJsonValue(rapidjson::Writer<epee::byte_stream>& dest, const cryptonote::rpc::output_distribution& dist)

View File

@@ -281,7 +281,7 @@ void fromJsonValue(const rapidjson::Value& val, cryptonote::rpc::error& error);
void toJsonValue(rapidjson::Writer<epee::byte_stream>& dest, const cryptonote::rpc::BlockHeaderResponse& response);
void fromJsonValue(const rapidjson::Value& val, cryptonote::rpc::BlockHeaderResponse& response);
void toJsonValue(rapidjson::Writer<epee::byte_stream>& dest, const rct::rctSig& sig, bool prune);
void toJsonValue(rapidjson::Writer<epee::byte_stream>& dest, const rct::rctSig& i);
void fromJsonValue(const rapidjson::Value& val, rct::rctSig& sig);
void fromJsonValue(const rapidjson::Value& val, rct::ctkey& key);

View File

@@ -47,7 +47,7 @@ namespace serialization
typename std::enable_if<!use_pair_varint<T>(), bool>::type
serialize_pair_element(Archive& ar, T& e)
{
return do_serialize(ar, e);
return ::do_serialize(ar, e);
}
template<typename Archive, typename T>
@@ -57,7 +57,7 @@ namespace serialization
static constexpr const bool previously_varint = std::is_same<uint64_t, T>();
if (!previously_varint && ar.varint_bug_backward_compatibility_enabled() && !typename Archive::is_saving())
return do_serialize(ar, e);
return ::do_serialize(ar, e);
ar.serialize_varint(e);
return true;
}

View File

@@ -57,30 +57,73 @@
template <class T>
struct is_blob_type { typedef boost::false_type type; };
/*! \fn do_serialize(Archive &ar, T &v)
/*! \struct has_free_serializer
*
* \brief main function for dispatching serialization for a given pair of archive and value types
* \brief a descriptor for dispatching serialize
*/
template <class T>
struct has_free_serializer { typedef boost::true_type type; };
/*! \struct is_basic_type
*
* \brief a descriptor for dispatching serialize
*/
template <class T>
struct is_basic_type { typedef boost::false_type type; };
template<typename F, typename S>
struct is_basic_type<std::pair<F,S>> { typedef boost::true_type type; };
template<>
struct is_basic_type<std::string> { typedef boost::true_type type; };
/*! \struct serializer
*
* \brief ... wouldn't a class be better?
*
* Types marked true with is_blob_type<T> will be serialized as a blob, integral types will be
* serialized as integers, and types who have a `member_do_serialize` method will be serialized
* using that method. Booleans are serialized like blobs.
* \detailed The logic behind serializing data. Places the archive
* data into the supplied parameter. This dispatches based on the
* supplied \a T template parameter's traits of is_blob_type or it is
* an integral (as defined by the is_integral trait). Depends on the
* \a Archive parameter to have overloaded the serialize_blob(T v,
* size_t size) and serialize_int(T v) base on which trait it
* applied. When the class has neither types, it falls to the
* overloaded method do_serialize(Archive ar) in T to do the work.
*/
template <class Archive, class T>
inline std::enable_if_t<is_blob_type<T>::type::value, bool> do_serialize(Archive &ar, T &v)
{
ar.serialize_blob(&v, sizeof(v));
return true;
}
struct serializer{
static bool serialize(Archive &ar, T &v) {
return serialize(ar, v, typename boost::is_integral<T>::type(), typename is_blob_type<T>::type(), typename is_basic_type<T>::type());
}
template<typename A>
static bool serialize(Archive &ar, T &v, boost::false_type, boost::true_type, A a) {
ar.serialize_blob(&v, sizeof(v));
return true;
}
template<typename A>
static bool serialize(Archive &ar, T &v, boost::true_type, boost::false_type, A a) {
ar.serialize_int(v);
return true;
}
static bool serialize(Archive &ar, T &v, boost::false_type, boost::false_type, boost::false_type) {
//serialize_custom(ar, v, typename has_free_serializer<T>::type());
return v.do_serialize(ar);
}
static bool serialize(Archive &ar, T &v, boost::false_type, boost::false_type, boost::true_type) {
//serialize_custom(ar, v, typename has_free_serializer<T>::type());
return do_serialize(ar, v);
}
static void serialize_custom(Archive &ar, T &v, boost::true_type) {
}
};
/*! \fn do_serialize(Archive &ar, T &v)
*
* \brief just calls the serialize function defined for ar and v...
*/
template <class Archive, class T>
inline std::enable_if_t<boost::is_integral<T>::value, bool> do_serialize(Archive &ar, T &v)
inline bool do_serialize(Archive &ar, T &v)
{
ar.serialize_int(v);
return true;
}
template <class Archive, class T>
inline auto do_serialize(Archive &ar, T &v) -> decltype(v.member_do_serialize(ar), true)
{
return v.member_do_serialize(ar);
return ::serializer<Archive, T>::serialize(ar, v);
}
template <class Archive>
inline bool do_serialize(Archive &ar, bool &v)
@@ -101,6 +144,16 @@ inline bool do_serialize(Archive &ar, bool &v)
typedef boost::true_type type; \
}
/*! \macro FREE_SERIALIZER
*
* \brief adds the has_free_serializer to the type
*/
#define FREE_SERIALIZER(T) \
template<> \
struct has_free_serializer<T> { \
typedef boost::true_type type; \
}
/*! \macro VARIANT_TAG
*
* \brief Adds the tag \tag to the \a Archive of \a Type
@@ -121,7 +174,7 @@ inline bool do_serialize(Archive &ar, bool &v)
*/
#define BEGIN_SERIALIZE() \
template <bool W, template <bool> class Archive> \
bool member_do_serialize(Archive<W> &ar) {
bool do_serialize(Archive<W> &ar) {
/*! \macro BEGIN_SERIALIZE_OBJECT
*
@@ -130,7 +183,7 @@ inline bool do_serialize(Archive &ar, bool &v)
*/
#define BEGIN_SERIALIZE_OBJECT() \
template <bool W, template <bool> class Archive> \
bool member_do_serialize(Archive<W> &ar) { \
bool do_serialize(Archive<W> &ar) { \
ar.begin_object(); \
bool r = do_serialize_object(ar); \
ar.end_object(); \
@@ -144,6 +197,11 @@ inline bool do_serialize(Archive &ar, bool &v)
#define PREPARE_CUSTOM_VECTOR_SERIALIZATION(size, vec) \
::serialization::detail::prepare_custom_vector_serialization(size, vec, typename Archive<W>::is_saving())
/*! \macro PREPARE_CUSTOM_DEQUE_SERIALIZATION
*/
#define PREPARE_CUSTOM_DEQUE_SERIALIZATION(size, vec) \
::serialization::detail::prepare_custom_deque_serialization(size, vec, typename Archive<W>::is_saving())
/*! \macro END_SERIALIZE
* \brief self-explanatory
*/
@@ -151,6 +209,16 @@ inline bool do_serialize(Archive &ar, bool &v)
return ar.good(); \
}
/*! \macro VALUE(f)
* \brief the same as FIELD(f)
*/
#define VALUE(f) \
do { \
ar.tag(#f); \
bool r = ::do_serialize(ar, f); \
if (!r || !ar.good()) return false; \
} while(0);
/*! \macro FIELD_N(t,f)
*
* \brief serializes a field \a f tagged \a t
@@ -158,7 +226,7 @@ inline bool do_serialize(Archive &ar, bool &v)
#define FIELD_N(t, f) \
do { \
ar.tag(t); \
bool r = do_serialize(ar, f); \
bool r = ::do_serialize(ar, f); \
if (!r || !ar.good()) return false; \
} while(0);
@@ -169,7 +237,7 @@ inline bool do_serialize(Archive &ar, bool &v)
#define FIELD(f) \
do { \
ar.tag(#f); \
bool r = do_serialize(ar, f); \
bool r = ::do_serialize(ar, f); \
if (!r || !ar.good()) return false; \
} while(0);
@@ -179,7 +247,7 @@ inline bool do_serialize(Archive &ar, bool &v)
*/
#define FIELDS(f) \
do { \
bool r = do_serialize(ar, f); \
bool r = ::do_serialize(ar, f); \
if (!r || !ar.good()) return false; \
} while(0);
@@ -249,6 +317,17 @@ namespace serialization {
vec.resize(size);
}
template <typename T>
void prepare_custom_deque_serialization(size_t size, std::deque<T>& vec, const boost::mpl::bool_<true>& /*is_saving*/)
{
}
template <typename T>
void prepare_custom_deque_serialization(size_t size, std::deque<T>& vec, const boost::mpl::bool_<false>& /*is_saving*/)
{
vec.resize(size);
}
/*! \fn do_check_stream_state
*
* \brief self explanatory

View File

@@ -39,7 +39,7 @@ namespace serialization
template <typename Archive, class T>
bool serialize_tuple_element(Archive& ar, T& e)
{
return do_serialize(ar, e);
return ::do_serialize(ar, e);
}
template <typename Archive>

View File

@@ -72,7 +72,7 @@ struct variant_reader
{
if(variant_serialization_traits<Archive, current_type>::get_tag() == t) {
current_type x;
if(!do_serialize(ar, x))
if(!::do_serialize(ar, x))
{
ar.set_fail();
return false;
@@ -100,13 +100,19 @@ struct variant_reader<Archive, Variant, TBegin, TBegin>
}
};
template <template <bool> class Archive, typename... T>
static bool do_serialize(Archive<false> &ar, boost::variant<T...> &v) {
using types = typename boost::variant<T...>::types;
typename Archive<false>::variant_tag_type t;
template <template <bool> class Archive, BOOST_VARIANT_ENUM_PARAMS(typename T)>
struct serializer<Archive<false>, boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>>
{
typedef boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> variant_type;
typedef typename Archive<false>::variant_tag_type variant_tag_type;
typedef typename variant_type::types types;
static bool serialize(Archive<false> &ar, variant_type &v) {
variant_tag_type t;
ar.begin_variant();
ar.read_variant_tag(t);
if(!variant_reader<Archive<false>, boost::variant<T...>,
if(!variant_reader<Archive<false>, variant_type,
typename boost::mpl::begin<types>::type,
typename boost::mpl::end<types>::type>::read(ar, v, t))
{
@@ -115,21 +121,27 @@ static bool do_serialize(Archive<false> &ar, boost::variant<T...> &v) {
}
ar.end_variant();
return true;
}
}
};
template <template <bool> class Archive>
struct variant_write_visitor : public boost::static_visitor<bool>
template <template <bool> class Archive, BOOST_VARIANT_ENUM_PARAMS(typename T)>
struct serializer<Archive<true>, boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>>
{
typedef boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> variant_type;
//typedef typename Archive<true>::variant_tag_type variant_tag_type;
struct visitor : public boost::static_visitor<bool>
{
Archive<true> &ar;
variant_write_visitor(Archive<true> &a) : ar(a) { }
visitor(Archive<true> &a) : ar(a) { }
template <class T>
bool operator ()(T &rv) const
{
ar.begin_variant();
ar.write_variant_tag(variant_serialization_traits<Archive<true>, T>::get_tag());
if(!do_serialize(ar, rv))
if(!::do_serialize(ar, rv))
{
ar.set_fail();
return false;
@@ -137,10 +149,9 @@ struct variant_write_visitor : public boost::static_visitor<bool>
ar.end_variant();
return true;
}
};
};
template <template <bool> class Archive, typename... T>
static bool do_serialize(Archive<true> &ar, boost::variant<T...> &v)
{
return boost::apply_visitor(variant_write_visitor<Archive>(ar), v);
}
static bool serialize(Archive<true> &ar, variant_type &v) {
return boost::apply_visitor(visitor(ar), v);
}
};

View File

@@ -155,6 +155,11 @@ typedef cryptonote::simple_wallet sw;
} \
} while(0)
enum TransferType {
Transfer,
TransferLocked,
};
static std::string get_human_readable_timespan(std::chrono::seconds seconds);
static std::string get_human_readable_timespan(uint64_t seconds);
@@ -191,7 +196,9 @@ namespace
const char* USAGE_INCOMING_TRANSFERS("incoming_transfers [available|unavailable] [verbose] [uses] [index=<N1>[,<N2>[,...]]]");
const char* USAGE_PAYMENTS("payments <PID_1> [<PID_2> ... <PID_N>]");
const char* USAGE_PAYMENT_ID("payment_id");
const char* USAGE_TRANSFER("transfer [index=<N1>[,<N2>,...]] [<priority>] [<ring_size>] (<URI> | <address> <amount>) [subtractfeefrom=<D0>[,<D1>,all,...]] [<payment_id>]");
const char* USAGE_TRANSFER("transfer [index=<N1>[,<N2>,...]] [<priority>] [<ring_size>] (<URI> | <address> <amount>) [<payment_id>]");
const char* USAGE_LOCKED_TRANSFER("locked_transfer [index=<N1>[,<N2>,...]] [<priority>] [<ring_size>] (<URI> | <addr> <amount>) <lockblocks> [<payment_id (obsolete)>]");
const char* USAGE_LOCKED_SWEEP_ALL("locked_sweep_all [index=<N1>[,<N2>,...] | index=all] [<priority>] [<ring_size>] <address> <lockblocks> [<payment_id (obsolete)>]");
const char* USAGE_SWEEP_ALL("sweep_all [index=<N1>[,<N2>,...] | index=all] [<priority>] [<ring_size>] [outputs=<N>] <address> [<payment_id (obsolete)>]");
const char* USAGE_SWEEP_ACCOUNT("sweep_account <account> [index=<N1>[,<N2>,...] | index=all] [<priority>] [<ring_size>] [outputs=<N>] <address> [<payment_id (obsolete)>]");
const char* USAGE_SWEEP_BELOW("sweep_below <amount_threshold> [index=<N1>[,<N2>,...]] [<priority>] [<ring_size>] <address> [<payment_id (obsolete)>]");
@@ -524,52 +531,7 @@ namespace
fail_msg_writer() << sw::tr("invalid format for subaddress lookahead; must be <major>:<minor>");
return r;
}
static constexpr const char* SFFD_ARG_NAME{"subtractfeefrom="};
bool parse_subtract_fee_from_outputs
(
const std::string& arg,
tools::wallet2::unique_index_container& subtract_fee_from_outputs,
bool& subtract_fee_from_all,
bool& matches
)
{
matches = false;
if (!boost::string_ref{arg}.starts_with(SFFD_ARG_NAME)) // if arg doesn't match
return true;
matches = true;
const char* arg_end = arg.c_str() + arg.size();
for (const char* p = arg.c_str() + strlen(SFFD_ARG_NAME); p < arg_end;)
{
const char* new_p = nullptr;
const unsigned long dest_index = strtoul(p, const_cast<char**>(&new_p), 10);
if (dest_index == 0 && new_p == p) // numerical conversion failed
{
if (0 != strncmp(p, "all", 3))
{
fail_msg_writer() << tr("Failed to parse subtractfeefrom list");
return false;
}
subtract_fee_from_all = true;
break;
}
else if (dest_index > std::numeric_limits<uint32_t>::max())
{
fail_msg_writer() << tr("Destination index is too large") << ": " << dest_index;
return false;
}
else
{
subtract_fee_from_outputs.insert(dest_index);
p = new_p + 1; // skip the comma
}
}
return true;
}
} // anonymous namespace
}
void simple_wallet::handle_transfer_exception(const std::exception_ptr &e, bool trusted_daemon)
{
@@ -1979,7 +1941,7 @@ bool simple_wallet::rpc_payment_info(const std::vector<std::string> &args)
crypto::public_key pkey;
crypto::secret_key_to_public_key(m_wallet->get_rpc_client_secret_key(), pkey);
message_writer() << tr("RPC client ID: ") << pkey;
message_writer() << tr("RPC client secret key: ") << crypto::secret_key_explicit_print_ref{m_wallet->get_rpc_client_secret_key()};
message_writer() << tr("RPC client secret key: ") << m_wallet->get_rpc_client_secret_key();
if (!m_wallet->get_rpc_payment_info(false, payment_required, credits, diff, credits_per_hash_found, hashing_blob, height, seed_height, seed_hash, next_seed_hash, cookie))
{
fail_msg_writer() << tr("Failed to query daemon");
@@ -3018,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
@@ -3331,7 +3306,15 @@ simple_wallet::simple_wallet()
tr("Show the blockchain height."));
m_cmd_binder.set_handler("transfer", boost::bind(&simple_wallet::on_command, this, &simple_wallet::transfer, _1),
tr(USAGE_TRANSFER),
tr("Transfer <amount> to <address>. If the parameter \"index=<N1>[,<N2>,...]\" is specified, the wallet uses outputs received by addresses of those indices. If omitted, the wallet randomly chooses address indices to be used. In any case, it tries its best not to combine outputs across multiple addresses. <priority> is the priority of the transaction. The higher the priority, the higher the transaction fee. Valid values in priority order (from lowest to highest) are: unimportant, normal, elevated, priority. If omitted, the default value (see the command \"set priority\") is used. <ring_size> is the number of inputs to include for untraceability. Multiple payments can be made at once by adding URI_2 or <address_2> <amount_2> etcetera (before the payment ID, if it's included). The \"subtractfeefrom=\" list allows you to choose which destinations to fund the tx fee from instead of the change output. The fee will be split across the chosen destinations proportionally equally. For example, to make 3 transfers where the fee is taken from the first and third destinations, one could do: \"transfer <addr1> 3 <addr2> 0.5 <addr3> 1 subtractfeefrom=0,2\". Let's say the tx fee is 0.1. The balance would drop by exactly 4.5 XMR including fees, and addr1 & addr3 would receive 2.925 & 0.975 XMR, respectively. Use \"subtractfeefrom=all\" to spread the fee across all destinations."));
tr("Transfer <amount> to <address>. If the parameter \"index=<N1>[,<N2>,...]\" is specified, the wallet uses outputs received by addresses of those indices. If omitted, the wallet randomly chooses address indices to be used. In any case, it tries its best not to combine outputs across multiple addresses. <priority> is the priority of the transaction. The higher the priority, the higher the transaction fee. Valid values in priority order (from lowest to highest) are: unimportant, normal, elevated, priority. If omitted, the default value (see the command \"set priority\") is used. <ring_size> is the number of inputs to include for untraceability. Multiple payments can be made at once by adding URI_2 or <address_2> <amount_2> etcetera (before the payment ID, if it's included)"));
m_cmd_binder.set_handler("locked_transfer",
boost::bind(&simple_wallet::on_command, this, &simple_wallet::locked_transfer,_1),
tr(USAGE_LOCKED_TRANSFER),
tr("Transfer <amount> to <address> and lock it for <lockblocks> (max. 1000000). If the parameter \"index=<N1>[,<N2>,...]\" is specified, the wallet uses outputs received by addresses of those indices. If omitted, the wallet randomly chooses address indices to be used. In any case, it tries its best not to combine outputs across multiple addresses. <priority> is the priority of the transaction. The higher the priority, the higher the transaction fee. Valid values in priority order (from lowest to highest) are: unimportant, normal, elevated, priority. If omitted, the default value (see the command \"set priority\") is used. <ring_size> is the number of inputs to include for untraceability. Multiple payments can be made at once by adding URI_2 or <address_2> <amount_2> etcetera (before the payment ID, if it's included)"));
m_cmd_binder.set_handler("locked_sweep_all",
boost::bind(&simple_wallet::on_command, this, &simple_wallet::locked_sweep_all,_1),
tr(USAGE_LOCKED_SWEEP_ALL),
tr("Send all unlocked balance to an address and lock it for <lockblocks> (max. 1000000). If the parameter \"index=<N1>[,<N2>,...]\" or \"index=all\" is specified, the wallet sweeps outputs received by those or all address indices, respectively. If omitted, the wallet randomly chooses an address index to be used. <priority> is the priority of the sweep. The higher the priority, the higher the transaction fee. Valid values in priority order (from lowest to highest) are: unimportant, normal, elevated, priority. If omitted, the default value (see the command \"set priority\") is used. <ring_size> is the number of inputs to include for untraceability."));
m_cmd_binder.set_handler("sweep_unmixable",
boost::bind(&simple_wallet::on_command, this, &simple_wallet::sweep_unmixable, _1),
tr("Send all unmixable outputs to yourself with ring_size 1"));
@@ -3475,6 +3458,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 "
@@ -3883,6 +3868,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)"
@@ -3951,6 +3937,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]>"));
@@ -4056,7 +4043,7 @@ bool simple_wallet::ask_wallet_create_if_needed()
bool ok = true;
if (!m_restoring)
{
message_writer() << tr("Looking for filename: ") << boost::filesystem::absolute(wallet_path);
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())
@@ -5003,7 +4990,7 @@ boost::optional<epee::wipeable_string> simple_wallet::new_wallet(const boost::pr
"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::absolute(m_wallet->get_keys_file());
success_msg_writer() << tr("Filename: ") << boost::filesystem::complete(m_wallet->get_keys_file());
if (!two_random)
{
@@ -6625,7 +6612,7 @@ bool simple_wallet::on_command(bool (simple_wallet::*cmd)(const std::vector<std:
return (this->*cmd)(args);
}
//----------------------------------------------------------------------------------------------------
bool simple_wallet::transfer_main(const std::vector<std::string> &args_, bool called_by_mms)
bool simple_wallet::transfer_main(int transfer_type, const std::vector<std::string> &args_, bool called_by_mms)
{
// "transfer [index=<N1>[,<N2>,...]] [<priority>] [<ring_size>] <address> <amount> [<payment_id>]"
if (!try_connect_to_daemon())
@@ -6641,7 +6628,7 @@ bool simple_wallet::transfer_main(const std::vector<std::string> &args_, bool ca
local_args.erase(local_args.begin());
}
uint32_t priority = m_wallet->get_default_priority();
uint32_t priority = 0;
if (local_args.size() > 0 && parse_priority(local_args[0], priority))
local_args.erase(local_args.begin());
@@ -6677,7 +6664,7 @@ bool simple_wallet::transfer_main(const std::vector<std::string> &args_, bool ca
return false;
}
const size_t min_args = 1;
const size_t min_args = (transfer_type == TransferLocked) ? 2 : 1;
if(local_args.size() < min_args)
{
fail_msg_writer() << tr("wrong number of arguments");
@@ -6702,25 +6689,24 @@ bool simple_wallet::transfer_main(const std::vector<std::string> &args_, bool ca
}
}
// Parse subtractfeefrom destination list
tools::wallet2::unique_index_container subtract_fee_from_outputs;
bool subtract_fee_from_all = false;
for (auto it = local_args.begin(); it < local_args.end();)
uint64_t locked_blocks = 0;
if (transfer_type == TransferLocked)
{
bool matches = false;
if (!parse_subtract_fee_from_outputs(*it, subtract_fee_from_outputs, subtract_fee_from_all, matches))
try
{
locked_blocks = boost::lexical_cast<uint64_t>(local_args.back());
}
catch (const std::exception &e)
{
fail_msg_writer() << tr("bad locked_blocks parameter:") << " " << local_args.back();
return false;
}
else if (matches)
if (locked_blocks > 1000000)
{
it = local_args.erase(it);
break;
}
else
{
++it;
fail_msg_writer() << tr("Locked blocks too high, max 1000000 (˜4 yrs)");
return false;
}
local_args.pop_back();
}
vector<cryptonote::address_parse_info> dsts_info;
@@ -6819,20 +6805,33 @@ bool simple_wallet::transfer_main(const std::vector<std::string> &args_, bool ca
dsts.push_back(de);
}
if (subtract_fee_from_all)
{
subtract_fee_from_outputs.clear();
for (decltype(subtract_fee_from_outputs)::value_type i = 0; i < dsts.size(); ++i)
subtract_fee_from_outputs.insert(i);
}
SCOPED_WALLET_UNLOCK_ON_BAD_PASSWORD(return false;);
try
{
// figure out what tx will be necessary
auto ptx_vector = m_wallet->create_transactions_2(dsts, fake_outs_count, priority, extra,
m_current_subaddress_account, subaddr_indices, subtract_fee_from_outputs);
std::vector<tools::wallet2::pending_tx> ptx_vector;
uint64_t bc_height, unlock_block = 0;
std::string err;
switch (transfer_type)
{
case TransferLocked:
bc_height = get_daemon_blockchain_height(err);
if (!err.empty())
{
fail_msg_writer() << tr("failed to get blockchain height: ") << err;
return false;
}
unlock_block = bc_height + locked_blocks;
ptx_vector = m_wallet->create_transactions_2(dsts, fake_outs_count, unlock_block /* unlock_time */, priority, extra, m_current_subaddress_account, subaddr_indices);
break;
default:
LOG_ERROR("Unknown transfer method, using default");
/* FALLTHRU */
case Transfer:
ptx_vector = m_wallet->create_transactions_2(dsts, fake_outs_count, 0 /* unlock_time */, priority, extra, m_current_subaddress_account, subaddr_indices);
break;
}
if (ptx_vector.empty())
{
@@ -6942,6 +6941,11 @@ bool simple_wallet::transfer_main(const std::vector<std::string> &args_, bool ca
if (dust_in_fee != 0) prompt << boost::format(tr(", of which %s is dust from change")) % print_money(dust_in_fee);
if (dust_not_in_fee != 0) prompt << tr(".") << ENDL << boost::format(tr("A total of %s from dust change will be sent to dust address"))
% print_money(dust_not_in_fee);
if (transfer_type == TransferLocked)
{
float days = locked_blocks / 720.0f;
prompt << boost::format(tr(".\nThis transaction (including %s change) will unlock on block %llu, in approximately %s days (assuming 2 minutes per block)")) % cryptonote::print_money(change) % ((unsigned long long)unlock_block) % days;
}
if (!process_ring_members(ptx_vector, prompt, m_wallet->print_ring_members()))
return false;
bool default_ring_size = true;
@@ -7061,7 +7065,29 @@ bool simple_wallet::transfer(const std::vector<std::string> &args_)
PRINT_USAGE(USAGE_TRANSFER);
return true;
}
transfer_main(args_, false);
transfer_main(Transfer, args_, false);
return true;
}
//----------------------------------------------------------------------------------------------------
bool simple_wallet::locked_transfer(const std::vector<std::string> &args_)
{
if (args_.size() < 1)
{
PRINT_USAGE(USAGE_LOCKED_TRANSFER);
return true;
}
transfer_main(TransferLocked, args_, false);
return true;
}
//----------------------------------------------------------------------------------------------------
bool simple_wallet::locked_sweep_all(const std::vector<std::string> &args_)
{
if (args_.size() < 1)
{
PRINT_USAGE(USAGE_LOCKED_SWEEP_ALL);
return true;
}
sweep_main(m_current_subaddress_account, 0, true, args_);
return true;
}
//----------------------------------------------------------------------------------------------------
@@ -7173,7 +7199,7 @@ bool simple_wallet::sweep_unmixable(const std::vector<std::string> &args_)
return true;
}
//----------------------------------------------------------------------------------------------------
bool simple_wallet::sweep_main(uint32_t account, uint64_t below, const std::vector<std::string> &args_)
bool simple_wallet::sweep_main(uint32_t account, uint64_t below, bool locked, const std::vector<std::string> &args_)
{
auto print_usage = [this, account, below]()
{
@@ -7253,6 +7279,41 @@ bool simple_wallet::sweep_main(uint32_t account, uint64_t below, const std::vect
return true;
}
uint64_t unlock_block = 0;
if (locked) {
uint64_t locked_blocks = 0;
if (local_args.size() < 2) {
fail_msg_writer() << tr("missing lockedblocks parameter");
return true;
}
try
{
locked_blocks = boost::lexical_cast<uint64_t>(local_args[1]);
}
catch (const std::exception &e)
{
fail_msg_writer() << tr("bad locked_blocks parameter");
return true;
}
if (locked_blocks > 1000000)
{
fail_msg_writer() << tr("Locked blocks too high, max 1000000 (˜4 yrs)");
return true;
}
std::string err;
uint64_t bc_height = get_daemon_blockchain_height(err);
if (!err.empty())
{
fail_msg_writer() << tr("failed to get blockchain height: ") << err;
return true;
}
unlock_block = bc_height + locked_blocks;
local_args.erase(local_args.begin() + 1);
}
size_t outputs = 1;
if (local_args.size() > 0 && local_args[0].substr(0, 8) == "outputs=")
{
@@ -7327,7 +7388,7 @@ bool simple_wallet::sweep_main(uint32_t account, uint64_t below, const std::vect
try
{
// figure out what tx will be necessary
auto ptx_vector = m_wallet->create_transactions_all(below, info.address, info.is_subaddress, outputs, fake_outs_count, priority, extra, account, subaddr_indices);
auto ptx_vector = m_wallet->create_transactions_all(below, info.address, info.is_subaddress, outputs, fake_outs_count, unlock_block /* unlock_time */, priority, extra, account, subaddr_indices);
if (ptx_vector.empty())
{
@@ -7584,7 +7645,7 @@ bool simple_wallet::sweep_single(const std::vector<std::string> &args_)
try
{
// figure out what tx will be necessary
auto ptx_vector = m_wallet->create_transactions_single(ki, info.address, info.is_subaddress, outputs, fake_outs_count, priority, extra);
auto ptx_vector = m_wallet->create_transactions_single(ki, info.address, info.is_subaddress, outputs, fake_outs_count, 0 /* unlock_time */, priority, extra);
if (ptx_vector.empty())
{
@@ -7694,7 +7755,7 @@ bool simple_wallet::sweep_single(const std::vector<std::string> &args_)
//----------------------------------------------------------------------------------------------------
bool simple_wallet::sweep_all(const std::vector<std::string> &args_)
{
sweep_main(m_current_subaddress_account, 0, args_);
sweep_main(m_current_subaddress_account, 0, false, args_);
return true;
}
//----------------------------------------------------------------------------------------------------
@@ -7714,7 +7775,7 @@ bool simple_wallet::sweep_account(const std::vector<std::string> &args_)
}
local_args.erase(local_args.begin());
sweep_main(account, 0, local_args);
sweep_main(account, 0, false, local_args);
return true;
}
//----------------------------------------------------------------------------------------------------
@@ -7732,7 +7793,7 @@ bool simple_wallet::sweep_below(const std::vector<std::string> &args_)
fail_msg_writer() << tr("invalid amount threshold");
return true;
}
sweep_main(m_current_subaddress_account, below, std::vector<std::string>(++args_.begin(), args_.end()));
sweep_main(m_current_subaddress_account, below, false, std::vector<std::string>(++args_.begin(), args_.end()));
return true;
}
//----------------------------------------------------------------------------------------------------
@@ -8078,9 +8139,9 @@ bool simple_wallet::submit_transfer(const std::vector<std::string> &args_)
std::string get_tx_key_stream(crypto::secret_key tx_key, std::vector<crypto::secret_key> additional_tx_keys)
{
ostringstream oss;
oss << epee::string_tools::pod_to_hex(unwrap(unwrap(tx_key)));
oss << epee::string_tools::pod_to_hex(tx_key);
for (size_t i = 0; i < additional_tx_keys.size(); ++i)
oss << epee::string_tools::pod_to_hex(unwrap(unwrap(additional_tx_keys[i])));
oss << epee::string_tools::pod_to_hex(additional_tx_keys[i]);
return oss.str();
}
@@ -8886,22 +8947,6 @@ bool simple_wallet::show_transfers(const std::vector<std::string> &args_)
PAUSE_READLINE();
auto formatter = boost::format("%8.8s %6.6s %8.8s %25.25s %20.20s %64.64s %15.15s %14.14s %s %s - %s");
message_writer(console_color_default, false) << formatter
% "Block"
% "In/Out"
% "Locked?"
% "Timestamp"
% "Amount"
% "Tx Hash"
% "Tx Payment ID"
% "Tx Fee"
% "Destination(s)"
% "Index"
% "Tx Note";
formatter = boost::format("%8.8llu %6.6s %8.8s %25.25s %20.20s %64.64s %15.15s %14.14s %s %s - %s");
for (const auto& transfer : all_transfers)
{
const auto color = transfer.type == "failed" ? console_color_red : transfer.confirmed ? ((transfer.direction == "in" || transfer.direction == "block") ? console_color_green : console_color_magenta) : console_color_default;
@@ -8918,6 +8963,8 @@ bool simple_wallet::show_transfers(const std::vector<std::string> &args_)
}
}
auto formatter = boost::format("%8.8llu %6.6s %8.8s %25.25s %20.20s %s %s %14.14s %s %s - %s");
message_writer(color, false) << formatter
% transfer.block
% transfer.direction
@@ -9436,12 +9483,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;
}
//----------------------------------------------------------------------------------------------------
@@ -11348,7 +11408,7 @@ void simple_wallet::mms_sync(const std::vector<std::string> &args)
void simple_wallet::mms_transfer(const std::vector<std::string> &args)
{
// It's too complicated to check any arguments here, just let 'transfer_main' do the whole job
transfer_main(args, true);
transfer_main(Transfer, args, true);
}
void simple_wallet::mms_delete(const std::vector<std::string> &args)

View File

@@ -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>());
@@ -171,9 +172,11 @@ namespace cryptonote
bool show_incoming_transfers(const std::vector<std::string> &args);
bool show_payments(const std::vector<std::string> &args);
bool show_blockchain_height(const std::vector<std::string> &args);
bool transfer_main(const std::vector<std::string> &args, bool called_by_mms);
bool transfer_main(int transfer_type, const std::vector<std::string> &args, bool called_by_mms);
bool transfer(const std::vector<std::string> &args);
bool sweep_main(uint32_t account, uint64_t below, const std::vector<std::string> &args);
bool locked_transfer(const std::vector<std::string> &args);
bool locked_sweep_all(const std::vector<std::string> &args);
bool sweep_main(uint32_t account, uint64_t below, bool locked, const std::vector<std::string> &args);
bool sweep_all(const std::vector<std::string> &args);
bool sweep_account(const std::vector<std::string> &args);
bool sweep_below(const std::vector<std::string> &args);

View File

@@ -1,5 +1,5 @@
#define DEF_MONERO_VERSION_TAG "@VERSIONTAG@"
#define DEF_MONERO_VERSION "0.11.3.0"
#define DEF_MONERO_VERSION "0.11.1.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@

View File

@@ -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})

122
src/wallet/api/coins.cpp Normal file
View File

@@ -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

34
src/wallet/api/coins.h Normal file
View File

@@ -0,0 +1,34 @@
#ifndef WOWLET_COINS_H
#define WOWLET_COINS_H
#include "wallet/api/wallet2_api.h"
#include "wallet/wallet2.h"
namespace Monero {
class WalletImpl;
class CoinsImpl : public Coins
{
public:
explicit CoinsImpl(WalletImpl * wallet);
~CoinsImpl() override;
int count() const override;
CoinsInfo * coin(int index) const override;
std::vector<CoinsInfo*> getAll() const override;
void refresh() override;
void setFrozen(int index) override;
void thaw(int index) override;
bool isTransferUnlocked(uint64_t unlockTime, uint64_t blockHeight) override;
private:
WalletImpl *m_wallet;
std::vector<CoinsInfo*> m_rows;
mutable boost::shared_mutex m_rowsMutex;
};
}
#endif //WOWLET_COINS_H

View File

@@ -0,0 +1,118 @@
#include "coins_info.h"
using namespace std;
namespace Monero {
CoinsInfo::~CoinsInfo() = default;
CoinsInfoImpl::CoinsInfoImpl()
: m_blockHeight(0)
, m_internalOutputIndex(0)
, m_globalOutputIndex(0)
, m_spent(false)
, m_frozen(false)
, m_spentHeight(0)
, m_amount(0)
, m_rct(false)
, m_keyImageKnown(false)
, m_pkIndex(0)
, m_subaddrAccount(0)
, m_subaddrIndex(0)
, m_unlockTime(0)
, m_unlocked(false)
{
}
CoinsInfoImpl::~CoinsInfoImpl() = default;
uint64_t CoinsInfoImpl::blockHeight() const
{
return m_blockHeight;
}
string CoinsInfoImpl::hash() const
{
return m_hash;
}
size_t CoinsInfoImpl::internalOutputIndex() const {
return m_internalOutputIndex;
}
uint64_t CoinsInfoImpl::globalOutputIndex() const
{
return m_globalOutputIndex;
}
bool CoinsInfoImpl::spent() const
{
return m_spent;
}
bool CoinsInfoImpl::frozen() const
{
return m_frozen;
}
uint64_t CoinsInfoImpl::spentHeight() const
{
return m_spentHeight;
}
uint64_t CoinsInfoImpl::amount() const
{
return m_amount;
}
bool CoinsInfoImpl::rct() const {
return m_rct;
}
bool CoinsInfoImpl::keyImageKnown() const {
return m_keyImageKnown;
}
size_t CoinsInfoImpl::pkIndex() const {
return m_pkIndex;
}
uint32_t CoinsInfoImpl::subaddrIndex() const {
return m_subaddrIndex;
}
uint32_t CoinsInfoImpl::subaddrAccount() const {
return m_subaddrAccount;
}
string CoinsInfoImpl::address() const {
return m_address;
}
string CoinsInfoImpl::addressLabel() const {
return m_addressLabel;
}
string CoinsInfoImpl::keyImage() const {
return m_keyImage;
}
uint64_t CoinsInfoImpl::unlockTime() const {
return m_unlockTime;
}
bool CoinsInfoImpl::unlocked() const {
return m_unlocked;
}
string CoinsInfoImpl::pubKey() const {
return m_pubKey;
}
bool CoinsInfoImpl::coinbase() const {
return m_coinbase;
}
} // namespace
namespace Bitmonero = Monero;

View File

@@ -0,0 +1,67 @@
#ifndef WOWLET_COINS_INFO_H
#define WOWLET_COINS_INFO_H
#include "wallet/api/wallet2_api.h"
#include <string>
#include <ctime>
namespace Monero {
class CoinsImpl;
class CoinsInfoImpl : public CoinsInfo
{
public:
CoinsInfoImpl();
~CoinsInfoImpl();
virtual uint64_t blockHeight() const override;
virtual std::string hash() const override;
virtual size_t internalOutputIndex() const override;
virtual uint64_t globalOutputIndex() const override;
virtual bool spent() const override;
virtual bool frozen() const override;
virtual uint64_t spentHeight() const override;
virtual uint64_t amount() const override;
virtual bool rct() const override;
virtual bool keyImageKnown() const override;
virtual size_t pkIndex() const override;
virtual uint32_t subaddrIndex() const override;
virtual uint32_t subaddrAccount() const override;
virtual std::string address() const override;
virtual std::string addressLabel() const override;
virtual std::string keyImage() const override;
virtual uint64_t unlockTime() const override;
virtual bool unlocked() const override;
virtual std::string pubKey() const override;
virtual bool coinbase() const override;
private:
uint64_t m_blockHeight;
std::string m_hash;
size_t m_internalOutputIndex;
uint64_t m_globalOutputIndex;
bool m_spent;
bool m_frozen;
uint64_t m_spentHeight;
uint64_t m_amount;
bool m_rct;
bool m_keyImageKnown;
size_t m_pkIndex;
uint32_t m_subaddrIndex;
uint32_t m_subaddrAccount;
std::string m_address;
std::string m_addressLabel;
std::string m_keyImage;
uint64_t m_unlockTime;
bool m_unlocked;
std::string m_pubKey;
bool m_coinbase;
friend class CoinsImpl;
};
} // namespace
#endif //WOWLET_COINS_INFO_H

View File

@@ -35,6 +35,7 @@
#include "cryptonote_basic/cryptonote_format_utils.h"
#include "cryptonote_basic/cryptonote_basic_impl.h"
#include "common/base58.h"
#include "string_coding.h"
#include <memory>
#include <vector>
@@ -263,4 +264,50 @@ std::vector<std::string> PendingTransactionImpl::signersKeys() const {
return keys;
}
std::string PendingTransactionImpl::unsignedTxToBin() const {
return m_wallet.m_wallet->dump_tx_to_str(m_pending_tx);
}
std::string PendingTransactionImpl::unsignedTxToBase64() const {
return epee::string_encoding::base64_encode(m_wallet.m_wallet->dump_tx_to_str(m_pending_tx));
}
std::string PendingTransactionImpl::signedTxToHex(int index) const {
auto index_ = static_cast<unsigned>(index);
if (index < 0 || index_ >= m_pending_tx.size()) {
return "";
}
return epee::string_tools::buff_to_hex_nodelimer(cryptonote::tx_to_blob(m_pending_tx[index_].tx));
}
size_t PendingTransactionImpl::signedTxSize(int index) const {
auto index_ = static_cast<unsigned>(index);
if (index < 0 || index_ >= m_pending_tx.size()) {
return 0;
}
return cryptonote::tx_to_blob(m_pending_tx[index_].tx).size();
}
PendingTransactionInfo * PendingTransactionImpl::transaction(int index) const {
if (index < 0)
return nullptr;
auto index_ = static_cast<unsigned>(index);
return index_ < m_pending_tx_info.size() ? m_pending_tx_info[index_] : nullptr;
}
void PendingTransactionImpl::refresh() {
for (auto t : m_pending_tx_info)
delete t;
m_pending_tx_info.clear();
for (const auto& p : m_pending_tx)
m_pending_tx_info.push_back(new PendingTransactionInfoImpl(m_wallet, p));
}
std::vector<PendingTransactionInfo*> PendingTransactionImpl::getAll() const {
return m_pending_tx_info;
}
}

View File

@@ -30,6 +30,7 @@
#include "wallet/api/wallet2_api.h"
#include "wallet/wallet2.h"
#include "pending_transaction_info.h"
#include <string>
#include <vector>
@@ -53,6 +54,13 @@ public:
uint64_t txCount() const override;
std::vector<uint32_t> subaddrAccount() const override;
std::vector<std::set<uint32_t>> subaddrIndices() const override;
std::string unsignedTxToBin() const override;
std::string unsignedTxToBase64() const override;
std::string signedTxToHex(int index) const override;
size_t signedTxSize(int index) const override;
void refresh() override;
std::vector<PendingTransactionInfo*> getAll() const override;
PendingTransactionInfo * transaction(int index) const override;
// TODO: continue with interface;
std::string multisigSignData() override;
@@ -66,6 +74,7 @@ private:
int m_status;
std::string m_errorString;
std::vector<tools::wallet2::pending_tx> m_pending_tx;
std::vector<PendingTransactionInfo*> m_pending_tx_info;
std::unordered_set<crypto::public_key> m_signers;
std::vector<std::string> m_tx_device_aux;
std::vector<crypto::key_image> m_key_images;

View File

@@ -0,0 +1,47 @@
#include "pending_transaction_info.h"
#include "transaction_construction_info.h"
using namespace std;
namespace Monero {
PendingTransactionInfo::~PendingTransactionInfo() = default;
PendingTransactionInfoImpl::PendingTransactionInfoImpl(WalletImpl &wallet, const tools::wallet2::pending_tx & ptx)
: m_wallet(wallet)
, m_ptx(ptx)
, m_constructionData(new TransactionConstructionInfoImpl(wallet, ptx.construction_data))
{
}
PendingTransactionInfoImpl::~PendingTransactionInfoImpl() = default;
uint64_t PendingTransactionInfoImpl::fee() const
{
return m_ptx.fee;
}
uint64_t PendingTransactionInfoImpl::dust() const
{
return m_ptx.dust;
}
bool PendingTransactionInfoImpl::dustAddedToFee() const
{
return m_ptx.dust_added_to_fee;
}
std::string PendingTransactionInfoImpl::txKey() const
{
return epee::string_tools::pod_to_hex(m_ptx.tx_key);
}
TransactionConstructionInfo * PendingTransactionInfoImpl::constructionData() const {
return m_constructionData;
}
// TransactionConstructionInfo::Output TransactionConstructionInfoImpl::change() const {
// return Output(
// {m_ptx.change_dts.amount, m_ptx.change_dts.address(m_wallet.m_wallet->nettype(), crypto::hash())});
// }
}

View File

@@ -0,0 +1,37 @@
#ifndef WOWLET_PENDING_TX_H
#define WOWLET_PENDING_TX_H
#include "wallet/api/wallet2_api.h"
#include "wallet/wallet2.h"
#include "wallet.h"
#include <string>
namespace Monero {
class PendingTransactionImpl;
class PendingTransactionInfoImpl : public PendingTransactionInfo
{
public:
PendingTransactionInfoImpl(WalletImpl &wallet, const tools::wallet2::pending_tx & ptx);
~PendingTransactionInfoImpl() override;
uint64_t fee() const override;
uint64_t dust() const override;
bool dustAddedToFee() const override;
std::string txKey() const override;
TransactionConstructionInfo *constructionData() const override;
// Output change() const override;
private:
friend class WalletImpl;
WalletImpl &m_wallet;
tools::wallet2::pending_tx m_ptx;
TransactionConstructionInfo *m_constructionData;
};
}
#endif //FEATHER_PENDING_TX_H

View File

@@ -67,7 +67,10 @@ void SubaddressImpl::refresh(uint32_t accountIndex)
clearRows();
for (size_t i = 0; i < m_wallet->m_wallet->get_num_subaddresses(accountIndex); ++i)
{
m_rows.push_back(new SubaddressRow(i, m_wallet->m_wallet->get_subaddress_as_str({accountIndex, (uint32_t)i}), m_wallet->m_wallet->get_subaddress_label({accountIndex, (uint32_t)i})));
m_rows.push_back(new SubaddressRow(i,
m_wallet->m_wallet->get_subaddress_as_str({accountIndex, (uint32_t)i}),
m_wallet->m_wallet->get_subaddress_label({accountIndex, (uint32_t)i}),
m_wallet->m_wallet->get_subaddress_used({accountIndex, (uint32_t)i})));
}
}

View File

@@ -0,0 +1,63 @@
#include "transaction_construction_info.h"
using namespace std;
namespace Monero {
TransactionConstructionInfo::~TransactionConstructionInfo() = default;
TransactionConstructionInfo::Input::Input(uint64_t _amount, const std::string &_pubkey)
: amount(_amount), pubkey(_pubkey) {}
TransactionConstructionInfo::Output::Output(uint64_t _amount, const std::string &_address)
: amount(_amount), address(_address) {}
TransactionConstructionInfoImpl::TransactionConstructionInfoImpl(WalletImpl &wallet, const tools::wallet2::tx_construction_data & txcd)
: m_wallet(wallet)
, m_txcd(txcd) {}
TransactionConstructionInfoImpl::~TransactionConstructionInfoImpl() = default;
uint64_t TransactionConstructionInfoImpl::unlockTime() const {
return m_txcd.unlock_time;
}
std::set<std::uint32_t> TransactionConstructionInfoImpl::subaddressIndices() const {
return m_txcd.subaddr_indices;
}
std::vector<std::string> TransactionConstructionInfoImpl::subaddresses() const {
std::vector<std::string> s;
auto major = m_txcd.subaddr_account;
for (const auto &minor : m_txcd.subaddr_indices) {
s.push_back(m_wallet.m_wallet->get_subaddress_as_str({major, minor}));
}
return s;
}
uint64_t TransactionConstructionInfoImpl::minMixinCount() const {
uint64_t min_mixin = -1;
for (const auto &source : m_txcd.sources) {
size_t mixin = source.outputs.size() - 1;
if (mixin < min_mixin)
min_mixin = mixin;
}
return min_mixin;
}
std::vector<TransactionConstructionInfo::Input> TransactionConstructionInfoImpl::inputs() const {
std::vector<Input> inputs;
for (const auto &i : m_txcd.sources) {
inputs.emplace_back(i.amount, epee::string_tools::pod_to_hex(i.real_out_tx_key));
}
return inputs;
}
std::vector<TransactionConstructionInfo::Output> TransactionConstructionInfoImpl::outputs() const {
std::vector<Output> outputs;
for (const auto &o : m_txcd.splitted_dsts) {
outputs.emplace_back(o.amount, o.address(m_wallet.m_wallet->nettype(), crypto::hash()));
}
return outputs;
}
}

View File

@@ -0,0 +1,32 @@
#ifndef WOWLET_TRANSACTION_CONSTRUCTION_INFO_H
#define WOWLET_TRANSACTION_CONSTRUCTION_INFO_H
#include "wallet/api/wallet2_api.h"
#include "wallet/wallet2.h"
#include "wallet.h"
#include <string>
namespace Monero {
class TransactionConstructionInfoImpl : public TransactionConstructionInfo
{
public:
TransactionConstructionInfoImpl(WalletImpl &wallet, const tools::wallet2::tx_construction_data & ptx);
~TransactionConstructionInfoImpl() override;
uint64_t unlockTime() const override;
std::set<std::uint32_t> subaddressIndices() const override;
std::vector<std::string> subaddresses() const override;
uint64_t minMixinCount() const override;
std::vector<Input> inputs() const override;
std::vector<Output> outputs() const override;
private:
friend class WalletImpl;
WalletImpl &m_wallet;
tools::wallet2::tx_construction_data m_txcd;
};
}
#endif //WOWLET_TRANSACTION_CONSTRUCTION_INFO_H

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