mirror of
https://codeberg.org/nahuhh/wownero
synced 2026-03-05 06:07:35 -05:00
Compare commits
226 Commits
cake-fixes
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3e302be710 | ||
|
|
b4ea97713d | ||
|
|
3e5fbb4fec | ||
|
|
178f454742 | ||
|
|
345be3361e | ||
|
|
5ad6661274 | ||
|
|
cd1de16fc2 | ||
|
|
c9d4dd1082 | ||
|
|
7d44e42dde | ||
|
|
6481a9ba5e | ||
|
|
e5dc1f749f | ||
|
|
7d01e5fa30 | ||
|
|
f603c70a5f | ||
|
|
d807ab95f1 | ||
|
|
b79968a7d8 | ||
|
|
c7fc4993cb | ||
|
|
4b4882082e | ||
|
|
2f7d418bda | ||
|
|
2d01af02ef | ||
|
|
1ff387c933 | ||
|
|
054abe1fa4 | ||
|
|
d6e7550793 | ||
|
|
194b88bf4f | ||
|
|
50c24fb1bb | ||
|
|
60386e7cf4 | ||
|
|
ff0fb4b6ed | ||
|
|
dd46a31f3c | ||
|
|
9e4ae1a36a | ||
|
|
36a6641000 | ||
|
|
9a8bbc6091 | ||
|
|
916f84b57b | ||
|
|
18399b17a1 | ||
|
|
7f984b6734 | ||
|
|
c826b2f098 | ||
|
|
a3a0dceb6c | ||
|
|
4796f9fa18 | ||
|
|
fb65602fbb | ||
|
|
5fe3cf2349 | ||
|
|
4bbad537aa | ||
|
|
31f5bc908d | ||
|
|
33a9bfed1f | ||
|
|
6728edc0e5 | ||
|
|
669d13edae | ||
|
|
42db984de2 | ||
|
|
fe5350d36a | ||
|
|
1d85179c40 | ||
|
|
7d6b6eee1b | ||
|
|
e8a9afe632 | ||
|
|
b5eb15d75b | ||
|
|
cbe4d95a5b | ||
|
|
611809cd62 | ||
|
|
5336b464df | ||
|
|
5b74f3a8f7 | ||
|
|
53fdd5641a | ||
|
|
37d6a815ff | ||
|
|
6c3f6122cf | ||
|
|
a2ba4811d5 | ||
|
|
75ea6cdc79 | ||
|
|
0882e5085e | ||
|
|
a4b7df3bd3 | ||
|
|
f4a93f581c | ||
|
|
75bd0fa857 | ||
|
|
2a0ac54f75 | ||
|
|
bede30caf2 | ||
|
|
0d7434b17c | ||
|
|
93e10f8017 | ||
|
|
e3df46c1d7 | ||
|
|
dc2f340641 | ||
|
|
45c1adb578 | ||
|
|
eb9944a57d | ||
|
|
4eed6ac172 | ||
|
|
25d070429e | ||
|
|
8ae0fb546c | ||
|
|
ca6a01cf55 | ||
|
|
b90d2892da | ||
|
|
8d8781e35e | ||
|
|
60df4f6e92 | ||
|
|
46e657b0af | ||
|
|
cbeabcaed0 | ||
|
|
29cf2b690f | ||
|
|
2585070fd6 | ||
|
|
dfb9ddbca5 | ||
|
|
9aa0587063 | ||
|
|
6d47fb1b86 | ||
|
|
ffd31aacfb | ||
|
|
ddf62fb149 | ||
|
|
81d424efb0 | ||
|
|
9c306cf2cf | ||
|
|
00e7562e5f | ||
|
|
a883a1c438 | ||
|
|
66eb48c94e | ||
|
|
645111f755 | ||
|
|
d69c44d7a7 | ||
|
|
d82736ad96 | ||
|
|
d7b5232a37 | ||
|
|
ce4214f9dc | ||
|
|
126822f955 | ||
|
|
b34c76d44c | ||
|
|
e37fa68509 | ||
|
|
69d8548576 | ||
|
|
b8c99d6b09 | ||
|
|
7b97b5a96e | ||
|
|
0abb30480f | ||
|
|
8708560330 | ||
|
|
0d147fa64c | ||
|
|
a0b96b5609 | ||
|
|
3cdf08cf48 | ||
|
|
b089f9ee69 | ||
|
|
7cb69fa6bc | ||
|
|
c7d4bf491e | ||
|
|
c6d17a0b39 | ||
|
|
753e4683af | ||
|
|
2676e5ae85 | ||
|
|
bedfa83ea0 | ||
|
|
dffa6766e7 | ||
|
|
1f733fb868 | ||
|
|
956d55c35f | ||
|
|
76feeb64b7 | ||
|
|
61db6497f7 | ||
|
|
6664e3e3b1 | ||
|
|
ebe3fdaff3 | ||
|
|
886595b540 | ||
|
|
b9fddc08b2 | ||
|
|
c5ad937cc1 | ||
|
|
e875a587e2 | ||
|
|
8c254e42e3 | ||
|
|
8dbc361e98 | ||
|
|
738f5038bf | ||
|
|
24ccaba6ef | ||
|
|
1ec7eae036 | ||
|
|
2f0503d7f3 | ||
|
|
b13e597e8e | ||
|
|
19fa7dceac | ||
|
|
f48fc72fb6 | ||
|
|
5930557a94 | ||
|
|
b85f320738 | ||
|
|
026be65bf5 | ||
|
|
1123ae9043 | ||
|
|
755dddd2bc | ||
|
|
dd47d03cf2 | ||
|
|
4634b8b539 | ||
|
|
100a7d06ee | ||
|
|
71567885e6 | ||
|
|
7686af7acf | ||
|
|
8703b8a4cb | ||
|
|
d6b35e97be | ||
|
|
81d4db08eb | ||
|
|
31a7f12d55 | ||
|
|
453a82fd44 | ||
|
|
1744fada96 | ||
|
|
1b7de24e90 | ||
|
|
97e3ce5f18 | ||
|
|
c7cf489585 | ||
|
|
1a931ecc83 | ||
|
|
ef3e18b51b | ||
|
|
b5b72ae05c | ||
|
|
5eb3fc29bb | ||
|
|
c225a1f25b | ||
|
|
ff15cb2f04 | ||
|
|
eeb7c7c546 | ||
|
|
36ee12bd8d | ||
|
|
32b3a56313 | ||
|
|
b23116424d | ||
|
|
7807f569e4 | ||
|
|
68e40ea2a7 | ||
|
|
c6ff0d3820 | ||
|
|
0d2f515ecc | ||
|
|
522d82276e | ||
|
|
4f6f6d9e27 | ||
|
|
3872753202 | ||
|
|
13ed9d501b | ||
|
|
b335433204 | ||
|
|
8a1e49664e | ||
|
|
2f912f8a58 | ||
|
|
81f113dd8c | ||
|
|
f9a7f2a136 | ||
|
|
c97c2ec01c | ||
|
|
51d7a6921c | ||
|
|
f2360a725e | ||
|
|
0cc8f7aaa3 | ||
|
|
b987870553 | ||
|
|
3aabfcfce5 | ||
|
|
8322f9c4f5 | ||
|
|
fbd0b19fc8 | ||
|
|
33e3f72d24 | ||
|
|
052df1b28c | ||
|
|
98ee46f249 | ||
|
|
f5b86342e8 | ||
|
|
dfb990e8bb | ||
|
|
8eab181fe1 | ||
|
|
9a70f43440 | ||
|
|
47d8899c90 | ||
|
|
c09062087e | ||
|
|
9a5f8431b4 | ||
|
|
79107ff68f | ||
|
|
646c3fb0d9 | ||
|
|
c193c5e85d | ||
|
|
d5c667a5ad | ||
|
|
2fe5a5e073 | ||
|
|
95e4fc3602 | ||
|
|
e7d51e5583 | ||
|
|
fe746dca4e | ||
|
|
fe47806afb | ||
|
|
6c38c21dfd | ||
|
|
5435202450 | ||
|
|
d9b765a3af | ||
|
|
72d2a610cd | ||
|
|
2e9542d01a | ||
|
|
0f75585f64 | ||
|
|
eb4df0aa1c | ||
|
|
eae62a07e0 | ||
|
|
14ae81246d | ||
|
|
5b0c27430f | ||
|
|
09a88cc00e | ||
|
|
bdebf680bd | ||
|
|
e0b2123c32 | ||
|
|
2656cdf505 | ||
|
|
1c12d305d6 | ||
|
|
83d0d2338f | ||
|
|
69de381526 | ||
|
|
810f6a6cd2 | ||
|
|
fbcd8da082 | ||
|
|
03d51b7cc4 | ||
|
|
9a89e2d9e4 | ||
|
|
1df5630f23 | ||
|
|
0c04018718 |
2
.gitmodules
vendored
2
.gitmodules
vendored
@@ -14,6 +14,6 @@
|
||||
branch = monero
|
||||
[submodule "external/randomwow"]
|
||||
path = external/randomwow
|
||||
url = https://git.wownero.com/wownero/RandomWOW
|
||||
url = https://codeberg.org/wownero/RandomWOW
|
||||
branch = 1.2.1-wow
|
||||
|
||||
|
||||
@@ -1076,27 +1076,39 @@ if(STATIC)
|
||||
set(Boost_USE_STATIC_LIBS ON)
|
||||
set(Boost_USE_STATIC_RUNTIME ON)
|
||||
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)
|
||||
|
||||
set(CMAKE_FIND_LIBRARY_SUFFIXES ${OLD_LIB_SUFFIXES})
|
||||
# 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 (>=1.58) or the equivalent")
|
||||
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}")
|
||||
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)
|
||||
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()
|
||||
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'")
|
||||
|
||||
# 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()
|
||||
|
||||
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
|
||||
|
||||
include_directories(SYSTEM ${Boost_INCLUDE_DIRS})
|
||||
if(MINGW)
|
||||
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -Wa,-mbig-obj")
|
||||
@@ -1189,6 +1201,7 @@ 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()
|
||||
@@ -1202,7 +1215,15 @@ 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}")
|
||||
|
||||
4
Makefile
4
Makefile
@@ -48,7 +48,7 @@ all: release-all
|
||||
|
||||
depends:
|
||||
cd contrib/depends && $(MAKE) HOST=$(target) && cd ../.. && mkdir -p build/$(target)/release
|
||||
cd build/$(target)/release && cmake -DCMAKE_TOOLCHAIN_FILE=$(CURDIR)/contrib/depends/$(target)/share/toolchain.cmake ../../.. && $(MAKE)
|
||||
cd build/$(target)/release && USE_DEVICE_TREZOR_MANDATORY=1 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 ARCH="x86-64" -D BUILD_64=ON -D CMAKE_BUILD_TYPE=Release $(topdir) && $(MAKE)
|
||||
cd $(builddir)/release && cmake -D BUILD_TESTS=OFF -D USE_DEVICE_TREZOR=OFF -D STATIC=ON -D BUILD_64=ON -D CMAKE_BUILD_TYPE=Release $(topdir) && $(MAKE)
|
||||
|
||||
coverage:
|
||||
mkdir -p $(builddir)/debug
|
||||
|
||||
78
README.md
78
README.md
@@ -1,7 +1,12 @@
|
||||
# ~~Mo~~Wownero - Such privacy! Many coins! Wow! 🐕
|
||||
# ~~Mo~~Wownero - Such privacy! Many coins! Wow!
|
||||
|
||||
Copyright (c) 2014-2023 The Monero Project.
|
||||
Portions Copyright (c) 2012-2013 The Cryptonote developers.
|
||||
[<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.
|
||||
|
||||
## Resources
|
||||
|
||||
@@ -10,33 +15,30 @@ Portions Copyright (c) 2012-2013 The Cryptonote developers.
|
||||
- Twitter: [@w0wn3r0](https://twitter.com/w0wn3r0)
|
||||
- Reddit: [/r/wownero](https://www.reddit.com/r/wownero)
|
||||
- Mail: [wownero@wownero.org](mailto:wownero@wownero.org)
|
||||
- Git: [git.wownero.com/wownero/wownero](https://git.wownero.com/wownero/wownero)
|
||||
- Wownero Funding System: [funding.wownero.com](https://funding.wownero.com)
|
||||
- Wownero Forum: [forum.wownero.com](https://forum.wownero.com)
|
||||
- Git: [codeberg.org/wownero/wownero](https://codeberg.org/wownero/wownero)
|
||||
- Discord: [discord.gg/ykZyAzJhDK](https://discord.com/invite/ykZyAzJhDK)
|
||||
- Telegram: [t.me/wownero](https://t.me/wownero)
|
||||
- Wowlet Desktop Wallet: [git.wownero.com/wowlet/wowlet](https://git.wownero.com/wowlet/wowlet/releases)
|
||||
- Stack Wallet iOS & Android Mobile Wallet: [stackwallet.com](https://stackwallet.com)
|
||||
- Wonerujo Android Mobile Wallet: [google store](https://play.google.com/store/apps/details?id=com.m2049r.wowwallet)
|
||||
- Elite Wallet Android Mobile Wallet: [github](https://github.com/Elite-Labs/EliteWallet)
|
||||
- Public Node Status: [monero.fail](https://monero.fail/?crypto=wownero)
|
||||
- Public Node Status: [monero.fail](https://monero.fail/?chain=wownero&network=mainnet)
|
||||
- Wownero Memes: [suchwow.xyz](https://suchwow.xyz/posts/top)
|
||||
- Market Info: [coinmarketcap.com](https://coinmarketcap.com/currencies/wownero), [coingecko.com](https://www.coingecko.com/en/coins/wownero/usd)
|
||||
|
||||
## 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)
|
||||
|
||||
### Blockchain Explorers
|
||||
## Wallets
|
||||
|
||||
- https://explore.wownero.com
|
||||
- https://muchwow.lol
|
||||
- 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)
|
||||
|
||||
## Introduction
|
||||
## Blockchain Explorers
|
||||
|
||||
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.
|
||||
- https://explorer.suchwow.xyz
|
||||
|
||||
## Supporting the project
|
||||
|
||||
@@ -45,11 +47,8 @@ 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 [WFS proposals](https://funding.wownero.com/proposals) or 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 the dev slush fund.
|
||||
|
||||
### Donation Addresses
|
||||
|
||||
@@ -63,19 +62,13 @@ 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://git.wownero.com/wownero/meta/issues) repo.
|
||||
Things to Do, Work in Progress, and Help Wanted tasks are tracked in the [Meta](https://codeberg.org/wownero/meta/issues) repo.
|
||||
|
||||
Join `#wownero` on IRC OFTC to participate in development conversation.
|
||||
|
||||
@@ -84,7 +77,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
|
||||
@@ -96,14 +89,12 @@ 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.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
|
||||
| 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
|
||||
|
||||
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
|
||||
@@ -131,21 +122,22 @@ Packaging for your favorite distribution would be a welcome contribution!
|
||||
|
||||
* Docker
|
||||
|
||||
git clone https://git.wownero.com/wownero/wownero && cd wownero
|
||||
git clone https://codeberg.org/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 && 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
|
||||
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
|
||||
make -j2
|
||||
|
||||
* Debian/Ubuntu
|
||||
|
||||
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
|
||||
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
|
||||
|
||||
|
||||
## Running Binaries
|
||||
@@ -168,7 +160,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](wow.conf) to `/etc/`. The [example
|
||||
[wow.conf](utils/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).
|
||||
@@ -196,7 +188,7 @@ HiddenServiceVersion 3
|
||||
save and close nano
|
||||
|
||||
* `sudo /etc/init.d/tor restart && sudo systemctl enable tor`
|
||||
* copy [wow.conf](https://git.wownero.com/wownero/wownero/raw/branch/master/wow.conf) file and save it in same directory as `wownerod`.
|
||||
* copy [wow.conf](utils/conf/wow.conf) file and save it in same directory as `wownerod`.
|
||||
* start wownerod like this:
|
||||
|
||||
```
|
||||
@@ -204,14 +196,16 @@ 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) and [here](https://forum.wownero.com/t/wownero-tor-onion-sites/623)
|
||||
|
||||
Copy your onion address and share node with others [here](https://monero.fail/?crypto=wownero).
|
||||
|
||||
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.
|
||||
|
||||
@@ -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)"
|
||||
|
||||
ifneq ($(1),libusb)
|
||||
ifeq ($(filter $(1),libusb unbound),)
|
||||
$(1)_autoconf += --disable-dependency-tracking
|
||||
endif
|
||||
ifneq ($($(1)_nm),)
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
package=expat
|
||||
$(package)_version=2.4.1
|
||||
$(package)_download_path=https://github.com/libexpat/libexpat/releases/download/R_2_4_1
|
||||
$(package)_version=2.6.0
|
||||
$(package)_download_path=https://github.com/libexpat/libexpat/releases/download/R_$(subst .,_,$($(package)_version))/
|
||||
$(package)_file_name=$(package)-$($(package)_version).tar.bz2
|
||||
$(package)_sha256_hash=2f9b6a580b94577b150a7d5617ad4643a4301a6616ff459307df3e225bcfbf40
|
||||
$(package)_sha256_hash=ff60e6a6b6ce570ae012dc7b73169c7fdf4b6bf08c12ed0ec6f55736b78d85ba
|
||||
|
||||
define $(package)_set_vars
|
||||
$(package)_config_opts=--enable-static
|
||||
$(package)_config_opts=--disable-shared
|
||||
$(package)_config_opts=--disable-shared --without-docbook --without-tests --without-examples
|
||||
$(package)_config_opts+=--enable-option-checking --without-xmlwf --with-pic
|
||||
$(package)_config_opts+=--prefix=$(host_prefix)
|
||||
endef
|
||||
|
||||
@@ -23,6 +23,6 @@ define $(package)_stage_cmds
|
||||
endef
|
||||
|
||||
define $(package)_postprocess_cmds
|
||||
rm lib/*.la
|
||||
rm -rf share lib/cmake lib/*.la
|
||||
endef
|
||||
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
package=openssl
|
||||
$(package)_version=3.0.11
|
||||
$(package)_version=3.0.13
|
||||
$(package)_download_path=https://www.openssl.org/source
|
||||
$(package)_file_name=$(package)-$($(package)_version).tar.gz
|
||||
$(package)_sha256_hash=b3425d3bb4a2218d0697eb41f7fc0cdede016ed19ca49d168b78e8d947887f55
|
||||
$(package)_sha256_hash=88525753f79d3bec27d2fa7c66aa0b92b3aa9498dafd93d7cfa4b3780cdae313
|
||||
|
||||
define $(package)_set_vars
|
||||
$(package)_config_env=AR="$($(package)_ar)" ARFLAGS=$($(package)_arflags) RANLIB="$($(package)_ranlib)" CC="$($(package)_cc)"
|
||||
|
||||
@@ -1,18 +1,21 @@
|
||||
package=unbound
|
||||
$(package)_version=1.15.0
|
||||
$(package)_version=1.19.1
|
||||
$(package)_download_path=https://www.nlnetlabs.nl/downloads/$(package)/
|
||||
$(package)_file_name=$(package)-$($(package)_version).tar.gz
|
||||
$(package)_sha256_hash=a480dc6c8937447b98d161fe911ffc76cfaffa2da18788781314e81339f1126f
|
||||
$(package)_sha256_hash=bc1d576f3dd846a0739adc41ffaa702404c6767d2b6082deb9f2f97cbb24a3a9
|
||||
$(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) --with-libexpat=$(host_prefix) --with-ssl=$(host_prefix) --with-libevent=no --without-pythonmodule --disable-flto --with-pthreads --with-libunbound-only
|
||||
$(package)_config_opts=--disable-shared --enable-static --without-pyunbound --prefix=$(host_prefix)
|
||||
$(package)_config_opts+=--with-libexpat=$(host_prefix) --with-ssl=$(host_prefix) --with-libevent=no
|
||||
$(package)_config_opts+=--without-pythonmodule --disable-flto --with-pthreads --with-libunbound-only
|
||||
$(package)_config_opts_linux=--with-pic
|
||||
$(package)_config_opts_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
|
||||
@@ -31,6 +34,3 @@ endef
|
||||
define $(package)_stage_cmds
|
||||
$(MAKE) DESTDIR=$($(package)_staging_dir) install
|
||||
endef
|
||||
|
||||
define $(package)_postprocess_cmds
|
||||
endef
|
||||
|
||||
@@ -144,8 +144,11 @@ elseif(ARCHITECTURE STREQUAL "aarch64")
|
||||
endif()
|
||||
|
||||
if(ARCHITECTURE STREQUAL "riscv64")
|
||||
set(ARCH_ID "riscv64")
|
||||
set(ARCH "rv64gc")
|
||||
if(CMAKE_SYSTEM_NAME STREQUAL "Linux")
|
||||
set(BUILD_TAG "linux-riscv64")
|
||||
endif()
|
||||
set(ARCH_ID "riscv64")
|
||||
set(ARCH "rv64gc")
|
||||
endif()
|
||||
|
||||
if(ARCHITECTURE STREQUAL "i686")
|
||||
|
||||
@@ -74,6 +74,7 @@ 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
|
||||
@@ -86,6 +87,7 @@ 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_; }
|
||||
|
||||
@@ -245,18 +245,8 @@ namespace net_utils
|
||||
}
|
||||
}
|
||||
|
||||
// This magic var determines the maximum length for when copying the body message in
|
||||
// memory is faster/more preferable than the round-trip time for one packet
|
||||
constexpr size_t BODY_NO_COPY_CUTOFF = 128 * 1024; // ~262 KB or ~175 packets
|
||||
|
||||
// Maximum expected total headers bytes
|
||||
constexpr size_t HEADER_RESERVE_SIZE = 2048;
|
||||
|
||||
const bool do_copy_body = body.size() <= BODY_NO_COPY_CUTOFF;
|
||||
const size_t req_buff_cap = HEADER_RESERVE_SIZE + (do_copy_body ? body.size() : 0);
|
||||
|
||||
std::string req_buff{};
|
||||
req_buff.reserve(req_buff_cap);
|
||||
req_buff.reserve(2048);
|
||||
req_buff.append(method.data(), method.size()).append(" ").append(uri.data(), uri.size()).append(" HTTP/1.1\r\n");
|
||||
add_field(req_buff, "Host", m_host_buff);
|
||||
add_field(req_buff, "Content-Length", std::to_string(body.size()));
|
||||
@@ -265,7 +255,9 @@ namespace net_utils
|
||||
for(const auto& field : additional_params)
|
||||
add_field(req_buff, field);
|
||||
|
||||
for (unsigned sends = 0; sends < 2; ++sends)
|
||||
{
|
||||
const std::size_t initial_size = req_buff.size();
|
||||
const auto auth = m_auth.get_auth_field(method, uri);
|
||||
if (auth)
|
||||
add_field(req_buff, *auth);
|
||||
@@ -273,21 +265,11 @@ namespace net_utils
|
||||
req_buff += "\r\n";
|
||||
//--
|
||||
|
||||
if (do_copy_body) // small body
|
||||
{
|
||||
// Copy headers + body together and potentially send one fewer packet
|
||||
req_buff.append(body.data(), body.size());
|
||||
const bool res = m_net_client.send(req_buff, timeout);
|
||||
CHECK_AND_ASSERT_MES(res, false, "HTTP_CLIENT: Failed to SEND");
|
||||
}
|
||||
else // large body
|
||||
{
|
||||
// Send headers and body seperately to avoid copying heavy body message
|
||||
bool res = m_net_client.send(req_buff, timeout);
|
||||
CHECK_AND_ASSERT_MES(res, false, "HTTP_CLIENT: Failed to SEND");
|
||||
bool res = m_net_client.send(req_buff, timeout);
|
||||
CHECK_AND_ASSERT_MES(res, false, "HTTP_CLIENT: Failed to SEND");
|
||||
if(body.size())
|
||||
res = m_net_client.send(body, timeout);
|
||||
CHECK_AND_ASSERT_MES(res, false, "HTTP_CLIENT: Failed to SEND");
|
||||
}
|
||||
CHECK_AND_ASSERT_MES(res, false, "HTTP_CLIENT: Failed to SEND");
|
||||
|
||||
m_response_info.clear();
|
||||
m_state = reciev_machine_state_header;
|
||||
@@ -300,11 +282,19 @@ namespace net_utils
|
||||
return true;
|
||||
}
|
||||
|
||||
if (m_auth.handle_401(m_response_info) == http_client_auth::kParseFailure)
|
||||
switch (m_auth.handle_401(m_response_info))
|
||||
{
|
||||
case http_client_auth::kSuccess:
|
||||
break;
|
||||
case http_client_auth::kBadPassword:
|
||||
sends = 2;
|
||||
break;
|
||||
default:
|
||||
case http_client_auth::kParseFailure:
|
||||
LOG_ERROR("Bad server response for authentication");
|
||||
return false;
|
||||
}
|
||||
req_buff.resize(initial_size); // rollback for new auth generation
|
||||
}
|
||||
LOG_ERROR("Client has incorrect username/password for server requiring authentication");
|
||||
return false;
|
||||
|
||||
@@ -171,6 +171,13 @@
|
||||
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"
|
||||
|
||||
|
||||
|
||||
@@ -98,16 +98,18 @@ 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(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_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_OPT_N(varialble, val_name, default_value) \
|
||||
#define KV_SERIALIZE_VAL_POD_AS_BLOB_OPT_N(variable, val_name, default_value) \
|
||||
do { \
|
||||
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); \
|
||||
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) \
|
||||
if (!ret) \
|
||||
epee::serialize_default(this_ref.varialble, default_value); \
|
||||
epee::serialize_default(this_ref.variable, default_value); \
|
||||
} while(0);
|
||||
|
||||
#define KV_SERIALIZE_CONTAINER_POD_AS_BLOB_N(varialble, val_name) \
|
||||
@@ -118,7 +120,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_pod compile time check
|
||||
#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_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)
|
||||
|
||||
|
||||
@@ -133,17 +133,14 @@ 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(!has_padding<T>(), "source type may have padding");
|
||||
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");
|
||||
return {reinterpret_cast<const std::uint8_t*>(src.data()), src.size_bytes()};
|
||||
}
|
||||
|
||||
@@ -153,7 +150,9 @@ 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(!has_padding<value_type>(), "source value type may have padding");
|
||||
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");
|
||||
return {reinterpret_cast<std::uint8_t*>(src.data()), src.size() * sizeof(value_type)};
|
||||
}
|
||||
|
||||
@@ -162,7 +161,9 @@ 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(!has_padding<T>(), "source type may have padding");
|
||||
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");
|
||||
return {reinterpret_cast<const std::uint8_t*>(std::addressof(src)), sizeof(T)};
|
||||
}
|
||||
|
||||
@@ -171,7 +172,9 @@ 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(!has_padding<T>(), "source type may have padding");
|
||||
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");
|
||||
return {reinterpret_cast<std::uint8_t*>(std::addressof(src)), sizeof(T)};
|
||||
}
|
||||
|
||||
|
||||
@@ -37,6 +37,7 @@
|
||||
#include "misc_log_ex.h"
|
||||
|
||||
#include <boost/lexical_cast.hpp>
|
||||
#include <boost/numeric/conversion/bounds.hpp>
|
||||
#include <typeinfo>
|
||||
#include <iomanip>
|
||||
|
||||
|
||||
@@ -31,6 +31,7 @@
|
||||
#include "mlocker.h"
|
||||
|
||||
#include <boost/utility/string_ref.hpp>
|
||||
#include <boost/algorithm/string.hpp>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include <cstdint>
|
||||
@@ -69,23 +70,17 @@ namespace string_tools
|
||||
#ifdef _WIN32
|
||||
std::string get_current_module_path();
|
||||
#endif
|
||||
bool set_module_name_and_folder(const std::string& path_to_process_);
|
||||
bool trim_left(std::string& str);
|
||||
bool trim_right(std::string& str);
|
||||
void set_module_name_and_folder(const std::string& path_to_process_);
|
||||
//----------------------------------------------------------------------------
|
||||
inline std::string& trim(std::string& str)
|
||||
{
|
||||
trim_left(str);
|
||||
trim_right(str);
|
||||
boost::trim(str);
|
||||
return str;
|
||||
}
|
||||
//----------------------------------------------------------------------------
|
||||
inline std::string trim(const std::string& str_)
|
||||
inline std::string trim(const std::string& str)
|
||||
{
|
||||
std::string str = str_;
|
||||
trim_left(str);
|
||||
trim_right(str);
|
||||
return str;
|
||||
return boost::trim_copy(str);
|
||||
}
|
||||
std::string pad_string(std::string s, size_t n, char c = ' ', bool prepend = false);
|
||||
|
||||
@@ -94,6 +89,7 @@ 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));
|
||||
}
|
||||
//----------------------------------------------------------------------------
|
||||
@@ -101,6 +97,8 @@ 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);
|
||||
}
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
@@ -152,7 +152,11 @@ 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)
|
||||
{
|
||||
@@ -162,9 +166,9 @@ namespace epee
|
||||
|
||||
for (const auto& source : sources)
|
||||
{
|
||||
assert(source.size() <= out.size()); // see check above
|
||||
std::memcpy(out.data(), source.data(), source.size());
|
||||
if (out.remove_prefix(source.size()) < source.size())
|
||||
throw std::bad_alloc{}; // size_t overflow on space_needed
|
||||
out.remove_prefix(source.size());
|
||||
}
|
||||
storage_ = std::move(storage);
|
||||
}
|
||||
|
||||
@@ -176,11 +176,12 @@ 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().string();
|
||||
if (filename.size() >= filename_base.size() && std::memcmp(filename.data(), filename_base.data(), filename_base.size()) == 0)
|
||||
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)
|
||||
{
|
||||
found_files.push_back(iter->path());
|
||||
}
|
||||
@@ -338,11 +339,21 @@ bool is_stdout_a_tty()
|
||||
return is_a_tty.load(std::memory_order_relaxed);
|
||||
}
|
||||
|
||||
static bool is_nocolor()
|
||||
{
|
||||
static const char *no_color_var = getenv("NO_COLOR");
|
||||
static const bool no_color = no_color_var && *no_color_var; // apparently, NO_COLOR=0 means no color too (as per no-color.org)
|
||||
return no_color;
|
||||
}
|
||||
|
||||
void set_console_color(int color, bool bright)
|
||||
{
|
||||
if (!is_stdout_a_tty())
|
||||
return;
|
||||
|
||||
if (is_nocolor())
|
||||
return;
|
||||
|
||||
switch(color)
|
||||
{
|
||||
case console_color_default:
|
||||
@@ -461,6 +472,9 @@ void reset_console_color() {
|
||||
if (!is_stdout_a_tty())
|
||||
return;
|
||||
|
||||
if (is_nocolor())
|
||||
return;
|
||||
|
||||
#ifdef WIN32
|
||||
HANDLE h_stdout = GetStdHandle(STD_OUTPUT_HANDLE);
|
||||
SetConsoleTextAttribute(h_stdout, FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);
|
||||
|
||||
@@ -238,6 +238,10 @@ static char** attempted_completion(const char* text, int start, int end)
|
||||
|
||||
static void install_line_handler()
|
||||
{
|
||||
#if RL_READLINE_VERSION >= 0x0801
|
||||
rl_variable_bind("enable-bracketed-paste", "off");
|
||||
#endif
|
||||
|
||||
rl_attempted_completion_function = attempted_completion;
|
||||
rl_callback_handler_install("", handle_line);
|
||||
stifle_history(500);
|
||||
|
||||
@@ -38,9 +38,12 @@
|
||||
#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"
|
||||
@@ -157,46 +160,20 @@ namespace string_tools
|
||||
return pname;
|
||||
}
|
||||
#endif
|
||||
|
||||
bool set_module_name_and_folder(const std::string& path_to_process_)
|
||||
{
|
||||
std::string path_to_process = path_to_process_;
|
||||
|
||||
void set_module_name_and_folder(const std::string& path_to_process_)
|
||||
{
|
||||
boost::filesystem::path 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)
|
||||
@@ -209,28 +186,22 @@ namespace string_tools
|
||||
return s;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
std::string res;
|
||||
std::string::size_type pos = str.rfind('.');
|
||||
if(std::string::npos == pos)
|
||||
return str;
|
||||
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 cut_off_extension(const std::string& str)
|
||||
{
|
||||
return boost::filesystem::path(str).replace_extension("").string();
|
||||
}
|
||||
|
||||
res = str.substr(0, pos);
|
||||
return res;
|
||||
}
|
||||
//----------------------------------------------------------------------------
|
||||
#ifdef _WIN32
|
||||
std::wstring utf8_to_utf16(const std::string& str)
|
||||
{
|
||||
|
||||
@@ -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.0
|
||||
VERSION=v0.18.3.4
|
||||
./dockrun.sh $VERSION
|
||||
```
|
||||
|
||||
|
||||
@@ -133,7 +133,7 @@ Common setup part:
|
||||
su - gitianuser
|
||||
|
||||
GH_USER=YOUR_GITHUB_USER_NAME
|
||||
VERSION=v0.18.3.0
|
||||
VERSION=v0.18.3.4
|
||||
```
|
||||
|
||||
Where `GH_USER` is your GitHub user name and `VERSION` is the version tag you want to build.
|
||||
|
||||
@@ -41,10 +41,10 @@ RUN useradd -ms /bin/bash -U ubuntu -G docker
|
||||
USER ubuntu:docker
|
||||
WORKDIR $WORKDIR
|
||||
|
||||
RUN git clone https://git.wownero.com/wownero/gitian.sigs.git sigs; \
|
||||
RUN git clone https://codeberg.org/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://git.wownero.com/wownero/wownero
|
||||
git clone https://codeberg.org/wownero/wownero
|
||||
|
||||
CMD ["sleep", "infinity"]
|
||||
EOF
|
||||
@@ -109,7 +109,7 @@ if [ "$check" != "sign" ]; then
|
||||
fi
|
||||
|
||||
if [ ! -d sigs ]; then
|
||||
git clone https://git.wownero.com/wownero/gitian.sigs.git sigs
|
||||
git clone https://codeberg.org/wownero/gitian.sigs.git sigs
|
||||
cd sigs
|
||||
git remote add $GH_USER git@github.com:$GH_USER/gitian.sigs.git
|
||||
cd ..
|
||||
|
||||
@@ -26,7 +26,7 @@ packages:
|
||||
- "cmake"
|
||||
- "unzip"
|
||||
remotes:
|
||||
- "url": "https://git.wownero.com/wownero/wownero.git"
|
||||
- "url": "https://codeberg.org/wownero/wownero.git"
|
||||
"dir": "wownero"
|
||||
files: []
|
||||
script: |
|
||||
|
||||
@@ -5,7 +5,7 @@ import os
|
||||
import subprocess
|
||||
import sys
|
||||
|
||||
gsigs = 'https://git.wownero.com/wownero/gitian.sigs.git'
|
||||
gsigs = 'https://codeberg.org/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://git.wownero.com/wownero/wownero', help='Specify the URL of the repository. Default is %(default)s')
|
||||
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('-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')
|
||||
|
||||
@@ -26,7 +26,7 @@ packages:
|
||||
- "python"
|
||||
- "cmake"
|
||||
remotes:
|
||||
- "url": "https://git.wownero.com/wownero/wownero.git"
|
||||
- "url": "https://codeberg.org/wownero/wownero.git"
|
||||
"dir": "wownero"
|
||||
files: []
|
||||
script: |
|
||||
|
||||
@@ -21,6 +21,7 @@ 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"
|
||||
@@ -37,13 +38,13 @@ packages:
|
||||
- "python"
|
||||
- "cmake"
|
||||
remotes:
|
||||
- "url": "https://git.wownero.com/wownero/wownero.git"
|
||||
- "url": "https://codeberg.org/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"
|
||||
HOSTS="x86_64-linux-gnu arm-linux-gnueabihf aarch64-linux-gnu i686-linux-gnu riscv64-linux-gnu"
|
||||
FAKETIME_HOST_PROGS=""
|
||||
FAKETIME_PROGS="date"
|
||||
HOST_CFLAGS="-O2 -g"
|
||||
@@ -159,7 +160,13 @@ script: |
|
||||
fi
|
||||
export C_INCLUDE_PATH="$EXTRA_INCLUDES"
|
||||
export CPLUS_INCLUDE_PATH="$EXTRA_INCLUDES"
|
||||
cmake .. -DCMAKE_TOOLCHAIN_FILE=${BASEPREFIX}/${i}/share/toolchain.cmake -DBACKCOMPAT=ON -DCMAKE_SKIP_RPATH=ON
|
||||
# glibc only added riscv support in 2.27, disable backwards compatibility
|
||||
if [ "$i" == "riscv64-linux-gnu" ]; then
|
||||
BACKCOMPAT_OPTION=OFF
|
||||
else
|
||||
BACKCOMPAT_OPTION=ON
|
||||
fi
|
||||
cmake .. -DCMAKE_TOOLCHAIN_FILE=${BASEPREFIX}/${i}/share/toolchain.cmake -DBACKCOMPAT=${BACKCOMPAT_OPTION} -DCMAKE_SKIP_RPATH=ON
|
||||
make ${MAKEOPTS}
|
||||
chmod 755 bin/*
|
||||
cp ../utils/conf/wow.conf bin
|
||||
|
||||
@@ -24,7 +24,7 @@ packages:
|
||||
- "python-dev"
|
||||
- "python-setuptools"
|
||||
remotes:
|
||||
- "url": "https://git.wownero.com/wownero/wownero.git"
|
||||
- "url": "https://codeberg.org/wownero/wownero.git"
|
||||
"dir": "wownero"
|
||||
files: []
|
||||
script: |
|
||||
|
||||
@@ -35,7 +35,7 @@ alternatives:
|
||||
package: "x86_64-w64-mingw32-gcc"
|
||||
path: "/usr/bin/x86_64-w64-mingw32-gcc-posix"
|
||||
remotes:
|
||||
- "url": "https://git.wownero.com/wownero/wownero.git"
|
||||
- "url": "https://codeberg.org/wownero/wownero.git"
|
||||
"dir": "wownero"
|
||||
files: []
|
||||
script: |
|
||||
|
||||
@@ -71,13 +71,13 @@ type, and max connections:
|
||||
|
||||
```
|
||||
--anonymous-inbound rveahdfho7wo4b2m.onion:28083,127.0.0.1:28083,25
|
||||
--anonymous-inbound cmeua5767mz2q5jsaelk2rxhf67agrwuetaso5dzbenyzwlbkg2q.b32.i2p:5000,127.0.0.1:30000
|
||||
--anonymous-inbound cmeua5767mz2q5jsaelk2rxhf67agrwuetaso5dzbenyzwlbkg2q.b32.i2p,127.0.0.1:30000
|
||||
```
|
||||
|
||||
which tells `monerod` that a max of 25 inbound Tor connections are being
|
||||
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:5000" and
|
||||
address "cmeua5767mz2q5jsaelk2rxhf67agrwuetaso5dzbenyzwlbkg2q.b32.i2p" 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.
|
||||
|
||||
5
external/easylogging++/easylogging++.cc
vendored
5
external/easylogging++/easylogging++.cc
vendored
@@ -149,6 +149,11 @@ static el::Color colorFromLevel(el::Level level)
|
||||
|
||||
static void setConsoleColor(el::Color color, bool bright)
|
||||
{
|
||||
static const char *no_color_var = getenv("NO_COLOR");
|
||||
static const bool no_color = no_color_var && *no_color_var; // apparently, NO_COLOR=0 means no color too (as per no-color.org)
|
||||
if (no_color)
|
||||
return;
|
||||
|
||||
#if ELPP_OS_WINDOWS
|
||||
HANDLE h_stdout = GetStdHandle(STD_OUTPUT_HANDLE);
|
||||
switch (color)
|
||||
|
||||
@@ -52,11 +52,9 @@ using namespace cryptonote;
|
||||
static std::string db_path;
|
||||
|
||||
// default to fast:1
|
||||
static uint64_t records_per_sync = 16 * 65536;
|
||||
static uint64_t records_per_sync = 128;
|
||||
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());
|
||||
@@ -91,14 +89,6 @@ 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
|
||||
@@ -146,7 +136,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;
|
||||
@@ -156,11 +146,10 @@ static bool resize_point(size_t &nrecords, MDB_env *env, MDB_txn **txn, size_t &
|
||||
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, void (*f)(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)
|
||||
{
|
||||
MDB_dbi dbi0, dbi1;
|
||||
MDB_txn *txn0, *txn1;
|
||||
@@ -211,11 +200,6 @@ 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;
|
||||
@@ -230,8 +214,7 @@ 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;
|
||||
++nrecords;
|
||||
if (resize_point(nrecords, env1, &txn1, bytes))
|
||||
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)));
|
||||
@@ -240,9 +223,6 @@ 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);
|
||||
@@ -255,6 +235,17 @@ 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;
|
||||
@@ -333,10 +324,7 @@ 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)
|
||||
{
|
||||
@@ -348,8 +336,7 @@ 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;
|
||||
const uint64_t tx_id = ti->data.tx_id;
|
||||
MDB_val_set(kk, tx_id);
|
||||
MDB_val_set(kk, ti->data.tx_id);
|
||||
if (block_height + CRYPTONOTE_PRUNING_TIP_BLOCKS >= blockchain_height)
|
||||
{
|
||||
MDEBUG(block_height << "/" << blockchain_height << " is in tip");
|
||||
@@ -357,23 +344,22 @@ 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;
|
||||
|
||||
++nrecords;
|
||||
if (resize_point(nrecords, env1, &txn1, bytes))
|
||||
}
|
||||
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))
|
||||
{
|
||||
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)));
|
||||
}
|
||||
}
|
||||
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;
|
||||
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)));
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -381,37 +367,6 @@ 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);
|
||||
@@ -464,7 +419,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;
|
||||
// default to fastest:async:N
|
||||
records_per_sync = 1000; // default to fastest:async:1000
|
||||
}
|
||||
else
|
||||
return false;
|
||||
@@ -500,7 +455,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:" + std::to_string(records_per_sync)
|
||||
, "fast:1000"
|
||||
};
|
||||
const command_line::arg_descriptor<bool> arg_copy_pruned_database = {"copy-pruned-database", "Copy database anyway if already pruned"};
|
||||
|
||||
@@ -646,27 +601,26 @@ 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, 0);
|
||||
copy_table(env0, env1, "block_info", MDB_INTEGERKEY | MDB_DUPSORT| MDB_DUPFIXED, 0, BlockchainLMDB::compare_uint64);
|
||||
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, "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, 0, NULL, &mark_v1_tx);
|
||||
copy_table(env0, env1, "txs_prunable_hash", MDB_INTEGERKEY | MDB_DUPSORT | MDB_DUPFIXED, 0);
|
||||
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);
|
||||
// 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, 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, "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, "properties", 0, 0, BlockchainLMDB::compare_string);
|
||||
if (already_pruned)
|
||||
{
|
||||
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);
|
||||
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);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
Binary file not shown.
@@ -233,13 +233,7 @@ namespace cryptonote
|
||||
ADD_CHECKPOINT2(489400, "b14f49eae77398117ea93435676100d8b655a804689f73a5a4d0d5e71160d603", "0x1123c39bb52f7e");
|
||||
ADD_CHECKPOINT2(491200, "cedba73ad35ce7f51aaca2beb36dc32d79ecc716d146eb8211e6a815f3666c4a", "0x11334734abbd17");
|
||||
ADD_CHECKPOINT2(497100, "2c4c70ac1ada94151f19d67ccf1aa4e846e6067f49f67c85cc03f78e768ea42b", "0x116906bc97a751");
|
||||
ADD_CHECKPOINT2(500000, "f4f771261b8c13cd83a9d8fa22e3cfe988564ad4b57dd90e79d5c0e77d61cf6a", "0x1185e7f2357a03");
|
||||
ADD_CHECKPOINT2(503500, "776f36a17056c3e22bbfb51d5aeabb58000731e9ad549f0f2f8ad1e1bcedf312", "0x11a4884467f53d");
|
||||
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");
|
||||
ADD_CHECKPOINT2(691500, "ed8e2507c0938b7eab7b02eccfb3506aeb591e51fbf6cf145fcc60ea2d351025", "0x163a280f2ce8e3");
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -35,6 +35,7 @@
|
||||
#include <boost/archive/portable_binary_iarchive.hpp>
|
||||
#include <boost/filesystem/operations.hpp>
|
||||
|
||||
#include "common/util.h"
|
||||
|
||||
namespace tools
|
||||
{
|
||||
@@ -110,7 +111,7 @@ namespace tools
|
||||
catch(...)
|
||||
{
|
||||
// if failed, try reading in unportable mode
|
||||
boost::filesystem::copy_file(file_path, file_path + ".unportable", boost::filesystem::copy_option::overwrite_if_exists);
|
||||
tools::copy_file(file_path, file_path + ".unportable");
|
||||
data_file.close();
|
||||
data_file.open( file_path, std::ios_base::binary | std::ios_base::in);
|
||||
if(data_file.fail())
|
||||
|
||||
@@ -115,6 +115,24 @@ 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() {}
|
||||
@@ -122,7 +140,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)
|
||||
private_file private_file::create(std::string name, uint32_t extra_flags)
|
||||
{
|
||||
#ifdef WIN32
|
||||
struct close_handle
|
||||
@@ -175,7 +193,7 @@ namespace tools
|
||||
name.c_str(),
|
||||
GENERIC_WRITE, FILE_SHARE_READ,
|
||||
std::addressof(attributes),
|
||||
CREATE_NEW, (FILE_ATTRIBUTE_TEMPORARY | FILE_FLAG_DELETE_ON_CLOSE),
|
||||
CREATE_NEW, (FILE_ATTRIBUTE_TEMPORARY | FILE_FLAG_DELETE_ON_CLOSE | extra_flags),
|
||||
nullptr
|
||||
)
|
||||
};
|
||||
@@ -194,7 +212,7 @@ namespace tools
|
||||
}
|
||||
}
|
||||
#else
|
||||
const int fdr = open(name.c_str(), (O_RDONLY | O_CREAT), S_IRUSR);
|
||||
const int fdr = open(name.c_str(), (O_RDONLY | O_CREAT | extra_flags), S_IRUSR);
|
||||
if (0 <= fdr)
|
||||
{
|
||||
struct stat rstats = {};
|
||||
@@ -225,6 +243,23 @@ 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
|
||||
|
||||
@@ -67,6 +67,8 @@ 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;
|
||||
@@ -80,7 +82,11 @@ 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);
|
||||
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);
|
||||
|
||||
private_file(private_file&&) = default;
|
||||
private_file& operator=(private_file&&) = default;
|
||||
|
||||
@@ -171,7 +171,9 @@ namespace crypto {
|
||||
/* Generate a value filled with random bytes.
|
||||
*/
|
||||
template<typename T>
|
||||
typename std::enable_if<std::is_pod<T>::value, T>::type rand() {
|
||||
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::remove_cv<T>::type res;
|
||||
generate_random_bytes_thread_safe(sizeof(T), (uint8_t*)&res);
|
||||
return res;
|
||||
@@ -314,8 +316,14 @@ 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;
|
||||
}
|
||||
inline std::ostream &operator <<(std::ostream &o, const crypto::secret_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::key_derivation &v) {
|
||||
epee::to_hex::formatted(o, epee::as_byte_span(v)); return o;
|
||||
|
||||
@@ -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*/
|
||||
unsigned char buffer[64]; /*the 512-bit message block to be hashed;*/
|
||||
DATA_ALIGN16(unsigned char buffer[64]); /*the 512-bit message block to be hashed;*/
|
||||
} hashState;
|
||||
|
||||
|
||||
@@ -213,16 +213,24 @@ static void E8(hashState *state)
|
||||
/*The compression function F8 */
|
||||
static void F8(hashState *state)
|
||||
{
|
||||
uint64 i;
|
||||
uint64_t* x = (uint64_t*)state->x;
|
||||
|
||||
/*xor the 512-bit message with the fist half of the 1024-bit hash state*/
|
||||
for (i = 0; i < 8; i++) state->x[i >> 1][i & 1] ^= ((uint64*)state->buffer)[i];
|
||||
for (int i = 0; i < 8; ++i) {
|
||||
uint64 b;
|
||||
memcpy(&b, &state->buffer[i << 3], sizeof(b));
|
||||
x[i] ^= b;
|
||||
}
|
||||
|
||||
/*the bijective function E8 */
|
||||
E8(state);
|
||||
|
||||
/*xor the 512-bit message with the second half of the 1024-bit hash state*/
|
||||
for (i = 0; i < 8; i++) state->x[(8+i) >> 1][(8+i) & 1] ^= ((uint64*)state->buffer)[i];
|
||||
for (int i = 0; i < 8; ++i) {
|
||||
uint64 b;
|
||||
memcpy(&b, &state->buffer[i << 3], sizeof(b));
|
||||
x[i + 8] ^= b;
|
||||
}
|
||||
}
|
||||
|
||||
/*before hashing a message, initialize the hash state as H0 */
|
||||
@@ -240,6 +248,7 @@ 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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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 << ", " << ack.m_view_secret_key << ")");
|
||||
MWARNING("key image helper: failed to generate_key_derivation(" << tx_public_key << ", <viewkey>)");
|
||||
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] << ", " << ack.m_view_secret_key << ")");
|
||||
MWARNING("key image helper: failed to generate_key_derivation(" << additional_tx_public_keys[i] << ", <viewkey>)");
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -52,7 +52,7 @@ namespace cryptonote
|
||||
|
||||
// load
|
||||
template <template <bool> class Archive>
|
||||
bool do_serialize(Archive<false>& ar)
|
||||
bool member_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 do_serialize(Archive<true>& ar)
|
||||
bool member_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 do_serialize(Archive<false>& ar)
|
||||
bool member_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 do_serialize(Archive<true>& ar)
|
||||
bool member_do_serialize(Archive<true>& ar)
|
||||
{
|
||||
std::ostringstream oss;
|
||||
binary_archive<true> oar(oss);
|
||||
|
||||
@@ -59,6 +59,7 @@ 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
|
||||
|
||||
@@ -30,6 +30,7 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
#include <boost/uuid/uuid.hpp>
|
||||
|
||||
@@ -1242,12 +1242,7 @@ 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++;
|
||||
|
||||
@@ -1255,7 +1250,6 @@ 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;
|
||||
@@ -2471,7 +2465,7 @@ bool Blockchain::get_output_distribution(uint64_t amount, uint64_t from_height,
|
||||
{
|
||||
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 MAINNET: start_height = 0; break;
|
||||
case FAKECHAIN: start_height = 0; break;
|
||||
default: return false;
|
||||
}
|
||||
@@ -3945,6 +3939,8 @@ 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)
|
||||
@@ -3958,7 +3954,6 @@ void Blockchain::get_dynamic_base_fee_estimate_2021_scaling(uint64_t grace_block
|
||||
const uint64_t Mlw_penalty_free_zone_for_wallet = std::max<uint64_t>(rm.median(), CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE_V5);
|
||||
|
||||
// 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);
|
||||
@@ -5671,7 +5666,7 @@ void Blockchain::cancel()
|
||||
}
|
||||
|
||||
#if defined(PER_BLOCK_CHECKPOINT)
|
||||
static const char expected_block_hashes_hash[] = "9ce2e9f40ff58954d6176e300af1d8da1804b829e1be8565805fea497df40f4b";
|
||||
static const char expected_block_hashes_hash[] = "3ee7be44d391f20b389ed17b17443ffa26889ac943a57b4e493b833db67159c5";
|
||||
void Blockchain::load_compiled_in_block_hashes(const GetCheckpointsCallback& get_checkpoints)
|
||||
{
|
||||
if (get_checkpoints == nullptr || !m_fast_sync)
|
||||
|
||||
@@ -1840,6 +1840,56 @@ 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
|
||||
|
||||
@@ -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 << ", " << txkey.sec << ")");
|
||||
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} << ")");
|
||||
|
||||
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, 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)
|
||||
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)
|
||||
{
|
||||
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 = unlock_time;
|
||||
tx.unlock_time = 0;
|
||||
|
||||
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: " << 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: " << crypto::secret_key_explicit_print_ref{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, 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)
|
||||
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)
|
||||
{
|
||||
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, unlock_time, 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, 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, uint64_t unlock_time)
|
||||
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)
|
||||
{
|
||||
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, unlock_time, 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, tx_key, additional_tx_keys, false, { rct::RangeProofBorromean, 0});
|
||||
}
|
||||
//---------------------------------------------------------------
|
||||
bool generate_genesis_block(
|
||||
|
||||
@@ -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, 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 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 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,
|
||||
|
||||
@@ -236,6 +236,15 @@ 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?
|
||||
@@ -247,6 +256,7 @@ 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;
|
||||
}
|
||||
}
|
||||
@@ -435,8 +445,14 @@ 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;
|
||||
@@ -481,8 +497,13 @@ 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 = it_prev;
|
||||
|
||||
changed = true;
|
||||
}
|
||||
catch (const std::exception &e)
|
||||
@@ -1074,7 +1095,7 @@ namespace cryptonote
|
||||
|
||||
// If the total weight is too high, choose the best paying transactions
|
||||
if (total_weight > max_backlog_weight)
|
||||
std::sort(tmp.begin(), tmp.end(), [](const auto& a, const auto& b){ return a.fee * b.weight > b.fee * a.weight; });
|
||||
std::stable_sort(tmp.begin(), tmp.end(), [](const auto& a, const auto& b){ return a.fee * b.weight > b.fee * a.weight; });
|
||||
|
||||
backlog.clear();
|
||||
uint64_t w = 0;
|
||||
@@ -1827,7 +1848,7 @@ namespace cryptonote
|
||||
auto sorted_it = find_tx_in_sorted_container(txid);
|
||||
if (sorted_it == m_txs_by_fee_and_receive_time.end())
|
||||
{
|
||||
MERROR("Re-adding tx " << txid << " to tx pool, but it was not found in the sorted txs container");
|
||||
MDEBUG("Re-adding tx " << txid << " to tx pool, but it was not found in the sorted txs container");
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -69,11 +69,12 @@ namespace cryptonote
|
||||
{
|
||||
// sort by greatest first, not least
|
||||
if (a.first.first > b.first.first) return true;
|
||||
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;
|
||||
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;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -40,15 +40,6 @@
|
||||
#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
|
||||
{
|
||||
|
||||
@@ -472,7 +463,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> speeds;
|
||||
std::unordered_map<boost::uuids::uuid, float, boost::hash<boost::uuids::uuid>> speeds;
|
||||
for (const auto &span: blocks)
|
||||
{
|
||||
if (span.blocks.empty())
|
||||
@@ -480,7 +471,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
|
||||
std::unordered_map<boost::uuids::uuid, float>::iterator i = speeds.find(span.connection_id);
|
||||
const auto i = speeds.find(span.connection_id);
|
||||
if (i == speeds.end())
|
||||
speeds.insert(std::make_pair(span.connection_id, span.rate));
|
||||
else
|
||||
|
||||
@@ -1693,8 +1693,22 @@ namespace cryptonote
|
||||
+ std::to_string(previous_stripe) + " -> " + std::to_string(current_stripe);
|
||||
if (ELPP->vRegistry()->allowed(el::Level::Debug, "sync-info"))
|
||||
timing_message += std::string(": ") + m_block_queue.get_overview(current_blockchain_height);
|
||||
MGINFO_YELLOW("Synced " << current_blockchain_height << "/" << target_blockchain_height
|
||||
<< progress_message << timing_message);
|
||||
uint64_t num = (rand() % 4) + 1;
|
||||
switch (num)
|
||||
{
|
||||
case 1:
|
||||
MGINFO_MAGENTA("*•.¸♡ ♡¸.•* synced *•.¸♡ ♡¸.•* " << current_blockchain_height << "/" << target_blockchain_height << progress_message << timing_message << " ˚ ༘♡ ⋆。˚");
|
||||
break;
|
||||
case 2:
|
||||
MGINFO_YELLOW("ˏˋ°•*⁀➷ pǝɔuʎs ˏˋ°•*⁀➷ " << current_blockchain_height << "/" << target_blockchain_height << progress_message << timing_message << " ︶︶༉‧₊ ☄. *.⋆");
|
||||
break;
|
||||
case 3:
|
||||
MGINFO_BLUE("s ★ y ★ n ★ c ★ e ★ d " << current_blockchain_height << "/" << target_blockchain_height << progress_message << timing_message << " *ೃ༄ *·˚˚ ༘♡ ⋆。˚");
|
||||
break;
|
||||
case 4:
|
||||
MGINFO_GREEN("s ♥ y ♥ n ♥ c ♥ e ♥ d " << current_blockchain_height << "/" << target_blockchain_height << progress_message << timing_message << " ⎯୧◦•◦❥•◦'*•.¸♡ ");
|
||||
break;
|
||||
}
|
||||
if (previous_stripe != current_stripe)
|
||||
notify_new_stripe(context, current_stripe);
|
||||
}
|
||||
|
||||
@@ -396,6 +396,8 @@ 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);
|
||||
}
|
||||
|
||||
@@ -741,9 +743,14 @@ namespace levin
|
||||
notify::status notify::get_status() const noexcept
|
||||
{
|
||||
if (!zone_)
|
||||
return {false, false};
|
||||
return {false, false, false};
|
||||
|
||||
return {!zone_->noise.empty(), CRYPTONOTE_NOISE_CHANNELS <= zone_->connection_count};
|
||||
// `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};
|
||||
}
|
||||
|
||||
void notify::new_out_connection()
|
||||
|
||||
@@ -75,7 +75,8 @@ namespace levin
|
||||
struct status
|
||||
{
|
||||
bool has_noise;
|
||||
bool connections_filled;
|
||||
bool connections_filled; //!< True when has zone has `CRYPTONOTE_NOISE_CHANNELS` outgoing noise channels
|
||||
bool has_outgoing; //!< True when zone has outgoing connections
|
||||
};
|
||||
|
||||
//! Construct an instance that cannot notify.
|
||||
|
||||
@@ -696,6 +696,16 @@ 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)
|
||||
{
|
||||
|
||||
@@ -317,13 +317,15 @@ 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 << ", " << sender_account_keys.m_view_secret_key << ")");
|
||||
CHECK_AND_ASSERT_MES(r, false, "at creation outs: failed to generate_key_derivation(" << txkey_pub << ", <viewkey>)");
|
||||
}
|
||||
else
|
||||
{
|
||||
// sending to the recipient; derivation = r*A (or s*C in the subaddress scheme)
|
||||
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) << ")");
|
||||
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} << ")");
|
||||
}
|
||||
|
||||
if (need_additional_txkeys)
|
||||
|
||||
@@ -527,6 +527,7 @@ namespace hw {
|
||||
{0x2c97, 0x0004, 0, 0xffa0},
|
||||
{0x2c97, 0x0005, 0, 0xffa0},
|
||||
{0x2c97, 0x0006, 0, 0xffa0},
|
||||
{0x2c97, 0x0007, 0, 0xffa0},
|
||||
};
|
||||
|
||||
bool device_ledger::connect(void) {
|
||||
|
||||
@@ -133,6 +133,7 @@ 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));
|
||||
|
||||
@@ -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_pod<F>(), "F must be POD");
|
||||
static_assert(std::is_trivially_copyable<F>(), "F must be memcpy safe");
|
||||
static_assert(sizeof(F) + offset <= sizeof(U), "bad field type and/or offset");
|
||||
|
||||
if (value.mv_size != sizeof(U))
|
||||
|
||||
@@ -111,6 +111,7 @@ 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);
|
||||
@@ -127,7 +128,7 @@ namespace lmdb
|
||||
/*!
|
||||
A LMDB comparison function that uses `std::memcmp`.
|
||||
|
||||
\toaram T is `!epee::has_padding`
|
||||
\toaram T has standard layout and an alignment of 1
|
||||
\tparam offset to `T` within the value.
|
||||
|
||||
\return The result of `std::memcmp` over the value.
|
||||
@@ -135,7 +136,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(!epee::has_padding<T>(), "memcmp will not work");
|
||||
static_assert(std::is_standard_layout<T>() && alignof(T) == 1, "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);
|
||||
|
||||
@@ -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_pod<U>(), "value type must be pod");
|
||||
static_assert(std::is_pod<G>(), "field type must be pod");
|
||||
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(sizeof(G) + uoffset <= sizeof(U), "bad field and/or offset");
|
||||
assert(sizeof(G) + uoffset <= values.size());
|
||||
assert(!is_end());
|
||||
|
||||
@@ -206,8 +206,13 @@ 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() > 0, "Kex message unexpectedly empty.");
|
||||
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.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,
|
||||
@@ -215,8 +220,6 @@ 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)};
|
||||
|
||||
@@ -820,7 +820,6 @@ 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,
|
||||
@@ -854,7 +853,7 @@ bool tx_builder_ringct_t::init(
|
||||
|
||||
// misc. fields
|
||||
unsigned_tx.version = 2; //rct = 2
|
||||
unsigned_tx.unlock_time = unlock_time;
|
||||
unsigned_tx.unlock_time = 0;
|
||||
|
||||
// sort inputs
|
||||
sort_sources(sources);
|
||||
|
||||
@@ -71,7 +71,6 @@ 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,
|
||||
|
||||
@@ -71,7 +71,7 @@ namespace net
|
||||
struct i2p_serialized
|
||||
{
|
||||
std::string host;
|
||||
std::uint16_t port;
|
||||
std::uint16_t port; //! Leave for compatability with older clients
|
||||
|
||||
BEGIN_KV_SERIALIZE_MAP()
|
||||
KV_SERIALIZE(host)
|
||||
@@ -80,8 +80,7 @@ namespace net
|
||||
};
|
||||
}
|
||||
|
||||
i2p_address::i2p_address(const boost::string_ref host, const std::uint16_t port) noexcept
|
||||
: port_(port)
|
||||
i2p_address::i2p_address(const boost::string_ref host) noexcept
|
||||
{
|
||||
// this is a private constructor, throw if moved to public
|
||||
assert(host.size() < sizeof(host_));
|
||||
@@ -97,27 +96,19 @@ 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, const std::uint16_t default_port)
|
||||
expect<i2p_address> i2p_address::make(const boost::string_ref address)
|
||||
{
|
||||
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, porti};
|
||||
return i2p_address{host};
|
||||
}
|
||||
|
||||
bool i2p_address::_load(epee::serialization::portable_storage& src, epee::serialization::section* hparent)
|
||||
@@ -127,23 +118,21 @@ 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
|
||||
{
|
||||
const i2p_serialized out{std::string{host_}, port_};
|
||||
// Set port to 1 for backwards compatability; zero is invalid port
|
||||
const i2p_serialized out{std::string{host_}, 1};
|
||||
return out.store(dest, hparent);
|
||||
}
|
||||
|
||||
i2p_address::i2p_address(const i2p_address& rhs) noexcept
|
||||
: port_(rhs.port_)
|
||||
{
|
||||
std::memcpy(host_, rhs.host_, sizeof(host_));
|
||||
}
|
||||
@@ -152,7 +141,6 @@ namespace net
|
||||
{
|
||||
if (this != std::addressof(rhs))
|
||||
{
|
||||
port_ = rhs.port_;
|
||||
std::memcpy(host_, rhs.host_, sizeof(host_));
|
||||
}
|
||||
return *this;
|
||||
@@ -166,13 +154,12 @@ namespace net
|
||||
|
||||
bool i2p_address::equal(const i2p_address& rhs) const noexcept
|
||||
{
|
||||
return port_ == rhs.port_ && is_same_host(rhs);
|
||||
return is_same_host(rhs);
|
||||
}
|
||||
|
||||
bool i2p_address::less(const i2p_address& rhs) const noexcept
|
||||
{
|
||||
int res = std::strcmp(host_str(), rhs.host_str());
|
||||
return res < 0 || (res == 0 && port() < rhs.port());
|
||||
return std::strcmp(host_str(), rhs.host_str()) < 0;
|
||||
}
|
||||
|
||||
bool i2p_address::is_same_host(const i2p_address& rhs) const noexcept
|
||||
@@ -182,20 +169,6 @@ namespace net
|
||||
|
||||
std::string i2p_address::str() const
|
||||
{
|
||||
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;
|
||||
return host_str();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -50,11 +50,10 @@ 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, std::uint16_t port) noexcept;
|
||||
i2p_address(boost::string_ref host) noexcept;
|
||||
|
||||
public:
|
||||
//! \return Size of internal buffer for host.
|
||||
@@ -74,7 +73,7 @@ namespace net
|
||||
with `default_port` being used if port is not specified in
|
||||
`address`.
|
||||
*/
|
||||
static expect<i2p_address> make(boost::string_ref address, std::uint16_t default_port = 0);
|
||||
static expect<i2p_address> make(boost::string_ref address);
|
||||
|
||||
//! Load from epee p2p format, and \return false if not valid tor address
|
||||
bool _load(epee::serialization::portable_storage& src, epee::serialization::section* hparent);
|
||||
@@ -103,8 +102,8 @@ namespace net
|
||||
//! \return Null-terminated `x.b32.i2p` value or `unknown_str()`.
|
||||
const char* host_str() const noexcept { return host_; }
|
||||
|
||||
//! \return Port value or `0` if unspecified.
|
||||
std::uint16_t port() const noexcept { return port_; }
|
||||
//! \return `1` to work with I2P socks which considers `0` error.
|
||||
std::uint16_t port() const noexcept { return 1; }
|
||||
|
||||
static constexpr bool is_loopback() noexcept { return false; }
|
||||
static constexpr bool is_local() noexcept { return false; }
|
||||
|
||||
@@ -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, default_port);
|
||||
return i2p_address::make(address);
|
||||
|
||||
boost::system::error_code ec;
|
||||
boost::asio::ip::address_v6 v6 = boost::asio::ip::address_v6::from_string(host_str, ec);
|
||||
|
||||
@@ -531,6 +531,16 @@ 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)
|
||||
{
|
||||
@@ -714,20 +724,15 @@ 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:34567"); // node2.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
|
||||
}
|
||||
return full_addrs;
|
||||
}
|
||||
@@ -859,11 +864,8 @@ namespace nodetool
|
||||
{
|
||||
return {
|
||||
"77uase4p6y6jsjdf6z2kdgpxgh7nkvywagvhurzphbm7vrkyj2d2gdid.onion:34566",
|
||||
"v2admi6gbeprxnk6i2oscizhgy4v5ixu6iezkhj5udiwbfjjs2w7dnid.onion:34566",
|
||||
"ttc6kxud3fikyaypn5voknyyvqje7j3wnoevsb7rfjerolynnisurkqd.onion:34566",
|
||||
"5enbij6tz3n2hw5ixzezfayd5gvckyg4xlktz74gj4l6u7olq7ovr3id.onion:34566",
|
||||
"jhy4hqymdkfj2u7bdi7m2vr5qheom7gjyg7fraktnlyksalhmpbemiqd.onion:34566",
|
||||
"ukpgpdd5gqvholcctejvaaig5hb266td6zaszt55eivuf7docoox5lid.onion:34566",
|
||||
"iorkdy6t4gdtwzn3iblnhy76nu7lhyz2qcvpj4wrspfxyvdrul7u22qd.onion:34566",
|
||||
};
|
||||
}
|
||||
return {};
|
||||
@@ -871,9 +873,6 @@ namespace nodetool
|
||||
if (m_nettype == cryptonote::MAINNET)
|
||||
{
|
||||
return {
|
||||
"lrq65qrhpbt5voom2ncvowpes6kvobodkldhpuwhxlsrpugmgmlq.b32.i2p:34565",
|
||||
"72tbpgeczdtx2q2enbyaqcot7mghbnjenjkmdpyylrssqehr746a.b32.i2p:34565",
|
||||
"rkel2qy7xv3cc5bnxfrzwgh3jvd4woagd4vlhr3qsdxy6cfkimnq.b32.i2p:34565",
|
||||
};
|
||||
}
|
||||
return {};
|
||||
@@ -2289,11 +2288,12 @@ namespace nodetool
|
||||
if (enet::zone::tor < network->first)
|
||||
break; // unknown network
|
||||
|
||||
if (network->second.m_connect)
|
||||
const auto status = network->second.m_notifier.get_status();
|
||||
if (network->second.m_connect && status.has_outgoing)
|
||||
return send(*network);
|
||||
}
|
||||
|
||||
// configuration should not allow this scenario
|
||||
MWARNING("Unable to send " << txs.size() << " transaction(s): anonymity networks had no outgoing connections");
|
||||
return enet::zone::invalid;
|
||||
}
|
||||
//-----------------------------------------------------------------------------------
|
||||
|
||||
@@ -42,6 +42,7 @@
|
||||
#include <boost/serialization/version.hpp>
|
||||
|
||||
#include "net_peerlist_boost_serialization.h"
|
||||
#include "common/util.h"
|
||||
|
||||
|
||||
namespace nodetool
|
||||
@@ -200,7 +201,7 @@ namespace nodetool
|
||||
if (!out)
|
||||
{
|
||||
// if failed, try reading in unportable mode
|
||||
boost::filesystem::copy_file(path, path + ".unportable", boost::filesystem::copy_option::overwrite_if_exists);
|
||||
tools::copy_file(path, path + ".unportable");
|
||||
src_file.close();
|
||||
src_file.open( path , std::ios_base::binary | std::ios_base::in);
|
||||
if(src_file.fail())
|
||||
|
||||
@@ -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, port));
|
||||
na = MONERO_UNWRAP(net::i2p_address::make(host));
|
||||
}
|
||||
|
||||
template <class Archive, class ver_type>
|
||||
|
||||
@@ -329,6 +329,10 @@ 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)
|
||||
{
|
||||
@@ -366,11 +370,17 @@ 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();
|
||||
if (!typename Archive<W>::is_saving())
|
||||
crypto::hash8 trunc_amount; // placeholder variable needed to maintain "strict aliasing"
|
||||
if (!typename Archive<W>::is_saving()) // loading
|
||||
memset(ecdhInfo[i].amount.bytes, 0, sizeof(ecdhInfo[i].amount.bytes));
|
||||
crypto::hash8 &amount = (crypto::hash8&)ecdhInfo[i].amount;
|
||||
FIELD(amount);
|
||||
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));
|
||||
ar.end_object();
|
||||
}
|
||||
else
|
||||
|
||||
@@ -1341,6 +1341,8 @@ 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)
|
||||
{
|
||||
|
||||
@@ -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 13
|
||||
#define CORE_RPC_VERSION_MINOR 14
|
||||
#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,6 +640,7 @@ 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)
|
||||
@@ -655,6 +656,7 @@ 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;
|
||||
|
||||
@@ -422,6 +422,16 @@ 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";
|
||||
@@ -510,6 +520,8 @@ 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();
|
||||
|
||||
@@ -48,6 +48,11 @@ 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);
|
||||
}
|
||||
|
||||
@@ -61,6 +66,11 @@ 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);
|
||||
@@ -76,6 +86,11 @@ 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);
|
||||
@@ -91,6 +106,11 @@ 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);
|
||||
}
|
||||
@@ -100,10 +120,16 @@ 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);
|
||||
@@ -117,6 +143,11 @@ 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);
|
||||
}
|
||||
|
||||
@@ -128,6 +159,11 @@ 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);
|
||||
}
|
||||
@@ -140,6 +176,11 @@ 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);
|
||||
}
|
||||
|
||||
@@ -150,6 +191,11 @@ 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);
|
||||
}
|
||||
|
||||
@@ -161,6 +207,11 @@ 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);
|
||||
}
|
||||
|
||||
@@ -171,6 +222,11 @@ 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);
|
||||
}
|
||||
|
||||
@@ -182,6 +238,11 @@ 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);
|
||||
}
|
||||
@@ -194,6 +255,11 @@ 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);
|
||||
}
|
||||
|
||||
@@ -205,6 +271,11 @@ 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);
|
||||
}
|
||||
@@ -219,6 +290,11 @@ 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);
|
||||
@@ -266,6 +342,11 @@ 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);
|
||||
@@ -288,6 +369,11 @@ 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);
|
||||
}
|
||||
|
||||
@@ -314,6 +400,11 @@ 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);
|
||||
}
|
||||
|
||||
@@ -324,6 +415,11 @@ 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);
|
||||
}
|
||||
|
||||
@@ -342,6 +438,11 @@ 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);
|
||||
}
|
||||
|
||||
@@ -353,6 +454,11 @@ 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);
|
||||
}
|
||||
|
||||
@@ -363,6 +469,11 @@ 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);
|
||||
}
|
||||
|
||||
@@ -374,6 +485,11 @@ 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);
|
||||
}
|
||||
|
||||
@@ -384,6 +500,11 @@ 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);
|
||||
}
|
||||
|
||||
@@ -395,6 +516,11 @@ 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);
|
||||
}
|
||||
|
||||
@@ -405,6 +531,11 @@ 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);
|
||||
}
|
||||
|
||||
@@ -424,6 +555,11 @@ 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);
|
||||
}
|
||||
@@ -436,6 +572,11 @@ 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);
|
||||
}
|
||||
|
||||
@@ -462,6 +603,11 @@ 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);
|
||||
}
|
||||
@@ -474,6 +620,11 @@ 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);
|
||||
}
|
||||
|
||||
@@ -484,6 +635,11 @@ 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);
|
||||
}
|
||||
|
||||
@@ -499,6 +655,11 @@ 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);
|
||||
@@ -513,6 +674,11 @@ 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);
|
||||
}
|
||||
|
||||
@@ -524,6 +690,11 @@ 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);
|
||||
}
|
||||
|
||||
@@ -534,6 +705,11 @@ 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);
|
||||
}
|
||||
|
||||
@@ -552,6 +728,11 @@ 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);
|
||||
}
|
||||
|
||||
@@ -562,6 +743,11 @@ 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);
|
||||
}
|
||||
|
||||
@@ -575,6 +761,11 @@ 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);
|
||||
@@ -591,6 +782,11 @@ 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);
|
||||
@@ -605,6 +801,11 @@ 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);
|
||||
}
|
||||
|
||||
@@ -178,6 +178,7 @@ 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;
|
||||
|
||||
@@ -158,13 +158,22 @@ void ZmqServer::serve()
|
||||
|
||||
if (!pub || sockets[2].revents)
|
||||
{
|
||||
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));
|
||||
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));
|
||||
|
||||
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()));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -42,14 +42,12 @@ struct debug_archive : public json_archive<W> {
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct serializer<debug_archive<true>, T>
|
||||
static inline bool do_serialize(debug_archive<true> &ar, T &v)
|
||||
{
|
||||
static void serialize(debug_archive<true> &ar, T &v)
|
||||
{
|
||||
ar.begin_object();
|
||||
ar.tag(variant_serialization_traits<debug_archive<true>, T>::get_tag());
|
||||
serializer<json_archive<true>, T>::serialize(ar, v);
|
||||
do_serialize(static_cast<json_archive<true>&>(ar), v);
|
||||
ar.end_object();
|
||||
ar.stream() << std::endl;
|
||||
}
|
||||
};
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -31,8 +31,6 @@
|
||||
#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)
|
||||
{
|
||||
|
||||
@@ -273,7 +273,10 @@ void toJsonValue(rapidjson::Writer<epee::byte_stream>& dest, const cryptonote::t
|
||||
{
|
||||
INSERT_INTO_JSON_OBJECT(dest, signatures, tx.signatures);
|
||||
}
|
||||
INSERT_INTO_JSON_OBJECT(dest, ringct, tx.rct_signatures);
|
||||
{
|
||||
dest.Key("ringct");
|
||||
toJsonValue(dest, tx.rct_signatures, tx.pruned);
|
||||
}
|
||||
|
||||
dest.EndObject();
|
||||
}
|
||||
@@ -1117,7 +1120,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)
|
||||
void toJsonValue(rapidjson::Writer<epee::byte_stream>& dest, const rct::rctSig& sig, const bool prune)
|
||||
{
|
||||
using boost::adaptors::transform;
|
||||
|
||||
@@ -1137,7 +1140,7 @@ void toJsonValue(rapidjson::Writer<epee::byte_stream>& dest, const rct::rctSig&
|
||||
}
|
||||
|
||||
// prunable
|
||||
if (!sig.p.bulletproofs.empty() || !sig.p.bulletproofs_plus.empty() || !sig.p.rangeSigs.empty() || !sig.p.MGs.empty() || !sig.get_pseudo_outs().empty())
|
||||
if (!prune && (!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();
|
||||
@@ -1429,9 +1432,14 @@ 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);
|
||||
@@ -1446,12 +1454,14 @@ 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();
|
||||
}
|
||||
@@ -1463,9 +1473,14 @@ 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);
|
||||
@@ -1480,12 +1495,22 @@ 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)
|
||||
|
||||
@@ -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& i);
|
||||
void toJsonValue(rapidjson::Writer<epee::byte_stream>& dest, const rct::rctSig& sig, bool prune);
|
||||
void fromJsonValue(const rapidjson::Value& val, rct::rctSig& sig);
|
||||
|
||||
void fromJsonValue(const rapidjson::Value& val, rct::ctkey& key);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -57,73 +57,30 @@
|
||||
template <class T>
|
||||
struct is_blob_type { typedef boost::false_type type; };
|
||||
|
||||
/*! \struct has_free_serializer
|
||||
*
|
||||
* \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?
|
||||
*
|
||||
* \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>
|
||||
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...
|
||||
* \brief main function for dispatching serialization for a given pair of archive and value types
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
template <class Archive, class T>
|
||||
inline bool do_serialize(Archive &ar, T &v)
|
||||
inline std::enable_if_t<is_blob_type<T>::type::value, bool> do_serialize(Archive &ar, T &v)
|
||||
{
|
||||
return ::serializer<Archive, T>::serialize(ar, v);
|
||||
ar.serialize_blob(&v, sizeof(v));
|
||||
return true;
|
||||
}
|
||||
template <class Archive, class T>
|
||||
inline std::enable_if_t<boost::is_integral<T>::value, 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);
|
||||
}
|
||||
template <class Archive>
|
||||
inline bool do_serialize(Archive &ar, bool &v)
|
||||
@@ -144,16 +101,6 @@ 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
|
||||
@@ -174,7 +121,7 @@ inline bool do_serialize(Archive &ar, bool &v)
|
||||
*/
|
||||
#define BEGIN_SERIALIZE() \
|
||||
template <bool W, template <bool> class Archive> \
|
||||
bool do_serialize(Archive<W> &ar) {
|
||||
bool member_do_serialize(Archive<W> &ar) {
|
||||
|
||||
/*! \macro BEGIN_SERIALIZE_OBJECT
|
||||
*
|
||||
@@ -183,7 +130,7 @@ inline bool do_serialize(Archive &ar, bool &v)
|
||||
*/
|
||||
#define BEGIN_SERIALIZE_OBJECT() \
|
||||
template <bool W, template <bool> class Archive> \
|
||||
bool do_serialize(Archive<W> &ar) { \
|
||||
bool member_do_serialize(Archive<W> &ar) { \
|
||||
ar.begin_object(); \
|
||||
bool r = do_serialize_object(ar); \
|
||||
ar.end_object(); \
|
||||
@@ -197,11 +144,6 @@ 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
|
||||
*/
|
||||
@@ -209,16 +151,6 @@ 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
|
||||
@@ -226,7 +158,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);
|
||||
|
||||
@@ -237,7 +169,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);
|
||||
|
||||
@@ -247,7 +179,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);
|
||||
|
||||
@@ -317,17 +249,6 @@ 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
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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,19 +100,13 @@ struct variant_reader<Archive, Variant, TBegin, TBegin>
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
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;
|
||||
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;
|
||||
ar.begin_variant();
|
||||
ar.read_variant_tag(t);
|
||||
if(!variant_reader<Archive<false>, variant_type,
|
||||
if(!variant_reader<Archive<false>, boost::variant<T...>,
|
||||
typename boost::mpl::begin<types>::type,
|
||||
typename boost::mpl::end<types>::type>::read(ar, v, t))
|
||||
{
|
||||
@@ -121,27 +115,21 @@ struct serializer<Archive<false>, boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>>
|
||||
}
|
||||
ar.end_variant();
|
||||
return true;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
template <template <bool> class Archive, BOOST_VARIANT_ENUM_PARAMS(typename T)>
|
||||
struct serializer<Archive<true>, boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>>
|
||||
template <template <bool> class Archive>
|
||||
struct variant_write_visitor : public boost::static_visitor<bool>
|
||||
{
|
||||
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;
|
||||
|
||||
visitor(Archive<true> &a) : ar(a) { }
|
||||
variant_write_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;
|
||||
@@ -149,9 +137,10 @@ struct serializer<Archive<true>, boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>>
|
||||
ar.end_variant();
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
static bool serialize(Archive<true> &ar, variant_type &v) {
|
||||
return boost::apply_visitor(visitor(ar), v);
|
||||
}
|
||||
};
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
@@ -155,11 +155,6 @@ 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);
|
||||
|
||||
@@ -196,9 +191,7 @@ 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>) [<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_TRANSFER("transfer [index=<N1>[,<N2>,...]] [<priority>] [<ring_size>] (<URI> | <address> <amount>) [subtractfeefrom=<D0>[,<D1>,all,...]] [<payment_id>]");
|
||||
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)>]");
|
||||
@@ -531,7 +524,52 @@ 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)
|
||||
{
|
||||
@@ -1941,7 +1979,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: ") << m_wallet->get_rpc_client_secret_key();
|
||||
message_writer() << tr("RPC client secret key: ") << crypto::secret_key_explicit_print_ref{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");
|
||||
@@ -2980,19 +3018,6 @@ 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
|
||||
@@ -3306,15 +3331,7 @@ 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)"));
|
||||
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."));
|
||||
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."));
|
||||
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"));
|
||||
@@ -3458,8 +3475,6 @@ 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 "
|
||||
@@ -3868,7 +3883,6 @@ 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)"
|
||||
@@ -3937,7 +3951,6 @@ 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]>"));
|
||||
@@ -4043,7 +4056,7 @@ bool simple_wallet::ask_wallet_create_if_needed()
|
||||
bool ok = true;
|
||||
if (!m_restoring)
|
||||
{
|
||||
message_writer() << tr("Looking for filename: ") << boost::filesystem::complete(wallet_path);
|
||||
message_writer() << tr("Looking for filename: ") << boost::filesystem::absolute(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())
|
||||
@@ -4990,7 +5003,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::complete(m_wallet->get_keys_file());
|
||||
success_msg_writer() << tr("Filename: ") << boost::filesystem::absolute(m_wallet->get_keys_file());
|
||||
|
||||
if (!two_random)
|
||||
{
|
||||
@@ -6612,7 +6625,7 @@ bool simple_wallet::on_command(bool (simple_wallet::*cmd)(const std::vector<std:
|
||||
return (this->*cmd)(args);
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
bool simple_wallet::transfer_main(int transfer_type, const std::vector<std::string> &args_, bool called_by_mms)
|
||||
bool simple_wallet::transfer_main(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())
|
||||
@@ -6628,7 +6641,7 @@ bool simple_wallet::transfer_main(int transfer_type, const std::vector<std::stri
|
||||
local_args.erase(local_args.begin());
|
||||
}
|
||||
|
||||
uint32_t priority = 0;
|
||||
uint32_t priority = m_wallet->get_default_priority();
|
||||
if (local_args.size() > 0 && parse_priority(local_args[0], priority))
|
||||
local_args.erase(local_args.begin());
|
||||
|
||||
@@ -6664,7 +6677,7 @@ bool simple_wallet::transfer_main(int transfer_type, const std::vector<std::stri
|
||||
return false;
|
||||
}
|
||||
|
||||
const size_t min_args = (transfer_type == TransferLocked) ? 2 : 1;
|
||||
const size_t min_args = 1;
|
||||
if(local_args.size() < min_args)
|
||||
{
|
||||
fail_msg_writer() << tr("wrong number of arguments");
|
||||
@@ -6689,24 +6702,25 @@ bool simple_wallet::transfer_main(int transfer_type, const std::vector<std::stri
|
||||
}
|
||||
}
|
||||
|
||||
uint64_t locked_blocks = 0;
|
||||
if (transfer_type == TransferLocked)
|
||||
// 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();)
|
||||
{
|
||||
try
|
||||
bool matches = false;
|
||||
if (!parse_subtract_fee_from_outputs(*it, subtract_fee_from_outputs, subtract_fee_from_all, matches))
|
||||
{
|
||||
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;
|
||||
}
|
||||
if (locked_blocks > 1000000)
|
||||
else if (matches)
|
||||
{
|
||||
fail_msg_writer() << tr("Locked blocks too high, max 1000000 (˜4 yrs)");
|
||||
return false;
|
||||
it = local_args.erase(it);
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
++it;
|
||||
}
|
||||
local_args.pop_back();
|
||||
}
|
||||
|
||||
vector<cryptonote::address_parse_info> dsts_info;
|
||||
@@ -6805,33 +6819,20 @@ bool simple_wallet::transfer_main(int transfer_type, const std::vector<std::stri
|
||||
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
|
||||
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;
|
||||
}
|
||||
auto ptx_vector = m_wallet->create_transactions_2(dsts, fake_outs_count, priority, extra,
|
||||
m_current_subaddress_account, subaddr_indices, subtract_fee_from_outputs);
|
||||
|
||||
if (ptx_vector.empty())
|
||||
{
|
||||
@@ -6941,11 +6942,6 @@ bool simple_wallet::transfer_main(int transfer_type, const std::vector<std::stri
|
||||
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;
|
||||
@@ -7065,29 +7061,7 @@ bool simple_wallet::transfer(const std::vector<std::string> &args_)
|
||||
PRINT_USAGE(USAGE_TRANSFER);
|
||||
return true;
|
||||
}
|
||||
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_);
|
||||
transfer_main(args_, false);
|
||||
return true;
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
@@ -7199,7 +7173,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, bool locked, const std::vector<std::string> &args_)
|
||||
bool simple_wallet::sweep_main(uint32_t account, uint64_t below, const std::vector<std::string> &args_)
|
||||
{
|
||||
auto print_usage = [this, account, below]()
|
||||
{
|
||||
@@ -7279,41 +7253,6 @@ bool simple_wallet::sweep_main(uint32_t account, uint64_t below, bool locked, co
|
||||
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=")
|
||||
{
|
||||
@@ -7388,7 +7327,7 @@ bool simple_wallet::sweep_main(uint32_t account, uint64_t below, bool locked, co
|
||||
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, unlock_block /* unlock_time */, priority, extra, account, subaddr_indices);
|
||||
auto ptx_vector = m_wallet->create_transactions_all(below, info.address, info.is_subaddress, outputs, fake_outs_count, priority, extra, account, subaddr_indices);
|
||||
|
||||
if (ptx_vector.empty())
|
||||
{
|
||||
@@ -7645,7 +7584,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, 0 /* unlock_time */, priority, extra);
|
||||
auto ptx_vector = m_wallet->create_transactions_single(ki, info.address, info.is_subaddress, outputs, fake_outs_count, priority, extra);
|
||||
|
||||
if (ptx_vector.empty())
|
||||
{
|
||||
@@ -7755,7 +7694,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, false, args_);
|
||||
sweep_main(m_current_subaddress_account, 0, args_);
|
||||
return true;
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
@@ -7775,7 +7714,7 @@ bool simple_wallet::sweep_account(const std::vector<std::string> &args_)
|
||||
}
|
||||
local_args.erase(local_args.begin());
|
||||
|
||||
sweep_main(account, 0, false, local_args);
|
||||
sweep_main(account, 0, local_args);
|
||||
return true;
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
@@ -7793,7 +7732,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, false, std::vector<std::string>(++args_.begin(), args_.end()));
|
||||
sweep_main(m_current_subaddress_account, below, std::vector<std::string>(++args_.begin(), args_.end()));
|
||||
return true;
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
@@ -8139,9 +8078,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(tx_key);
|
||||
oss << epee::string_tools::pod_to_hex(unwrap(unwrap(tx_key)));
|
||||
for (size_t i = 0; i < additional_tx_keys.size(); ++i)
|
||||
oss << epee::string_tools::pod_to_hex(additional_tx_keys[i]);
|
||||
oss << epee::string_tools::pod_to_hex(unwrap(unwrap(additional_tx_keys[i])));
|
||||
return oss.str();
|
||||
}
|
||||
|
||||
@@ -8947,6 +8886,22 @@ 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;
|
||||
@@ -8963,8 +8918,6 @@ 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
|
||||
@@ -9483,25 +9436,12 @@ 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("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;
|
||||
}
|
||||
std::string prompt = std::string("[") + tr("wallet") + " " + addr_start;
|
||||
if (!m_wallet->check_connection(NULL))
|
||||
{
|
||||
prompt += tr("] (no daemon): ");
|
||||
} else if (!m_wallet->is_synced()) {
|
||||
prompt += tr("] (out of sync): ");
|
||||
} else {
|
||||
prompt += "]: ";
|
||||
}
|
||||
prompt += tr(" (no daemon)");
|
||||
else if (!m_wallet->is_synced())
|
||||
prompt += tr(" (out of sync)");
|
||||
prompt += "]: ";
|
||||
return prompt;
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
@@ -11408,7 +11348,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(Transfer, args, true);
|
||||
transfer_main(args, true);
|
||||
}
|
||||
|
||||
void simple_wallet::mms_delete(const std::vector<std::string> &args)
|
||||
|
||||
@@ -148,7 +148,6 @@ 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>());
|
||||
@@ -172,11 +171,9 @@ 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(int transfer_type, const std::vector<std::string> &args, bool called_by_mms);
|
||||
bool transfer_main(const std::vector<std::string> &args, bool called_by_mms);
|
||||
bool transfer(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_main(uint32_t account, uint64_t below, 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);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#define DEF_MONERO_VERSION_TAG "@VERSIONTAG@"
|
||||
#define DEF_MONERO_VERSION "0.11.1.0"
|
||||
#define DEF_MONERO_VERSION "0.11.3.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@
|
||||
|
||||
@@ -35,16 +35,12 @@ 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
|
||||
coins.cpp
|
||||
coins_info.cpp)
|
||||
unsigned_transaction.cpp)
|
||||
|
||||
set(wallet_api_headers
|
||||
wallet2_api.h)
|
||||
@@ -54,16 +50,12 @@ 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
|
||||
coins.h
|
||||
coins_info.h)
|
||||
unsigned_transaction.h)
|
||||
|
||||
monero_private_headers(wallet_api
|
||||
${wallet_api_private_headers})
|
||||
|
||||
@@ -1,123 +0,0 @@
|
||||
#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);
|
||||
ci->m_description = m_wallet->m_wallet->get_tx_note(td.m_txid);
|
||||
|
||||
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
|
||||
@@ -1,34 +0,0 @@
|
||||
#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
|
||||
@@ -1,122 +0,0 @@
|
||||
#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;
|
||||
}
|
||||
|
||||
string CoinsInfoImpl::description() const {
|
||||
return m_description;
|
||||
}
|
||||
} // namespace
|
||||
|
||||
namespace Bitmonero = Monero;
|
||||
@@ -1,69 +0,0 @@
|
||||
#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;
|
||||
virtual std::string description() 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;
|
||||
std::string m_description;
|
||||
|
||||
friend class CoinsImpl;
|
||||
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
#endif //WOWLET_COINS_INFO_H
|
||||
@@ -35,7 +35,6 @@
|
||||
#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>
|
||||
@@ -79,22 +78,6 @@ std::vector<std::string> PendingTransactionImpl::txid() const
|
||||
return txid;
|
||||
}
|
||||
|
||||
std::vector<std::string> PendingTransactionImpl::hex() const
|
||||
{
|
||||
std::vector<std::string> hexs;
|
||||
for (const auto &pt: m_pending_tx)
|
||||
hexs.push_back(epee::string_tools::buff_to_hex_nodelimer(cryptonote::tx_to_blob(pt.tx)));
|
||||
return hexs;
|
||||
}
|
||||
|
||||
std::vector<std::string> PendingTransactionImpl::txKey() const
|
||||
{
|
||||
std::vector<std::string> keys;
|
||||
for (const auto& pt: m_pending_tx)
|
||||
keys.push_back(epee::string_tools::pod_to_hex(pt.tx_key));
|
||||
return keys;
|
||||
}
|
||||
|
||||
bool PendingTransactionImpl::commit(const std::string &filename, bool overwrite)
|
||||
{
|
||||
|
||||
@@ -280,50 +263,4 @@ 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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -30,7 +30,6 @@
|
||||
|
||||
#include "wallet/api/wallet2_api.h"
|
||||
#include "wallet/wallet2.h"
|
||||
#include "pending_transaction_info.h"
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
@@ -54,20 +53,11 @@ 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;
|
||||
void signMultisigTx() override;
|
||||
std::vector<std::string> signersKeys() const override;
|
||||
std::vector<std::string> hex() const override;
|
||||
std::vector<std::string> txKey() const override;
|
||||
|
||||
private:
|
||||
friend class WalletImpl;
|
||||
@@ -76,7 +66,6 @@ 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;
|
||||
|
||||
@@ -1,47 +0,0 @@
|
||||
#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())});
|
||||
// }
|
||||
}
|
||||
@@ -1,37 +0,0 @@
|
||||
#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
|
||||
@@ -67,10 +67,7 @@ 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_wallet->m_wallet->get_subaddress_used({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})));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,63 +0,0 @@
|
||||
#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;
|
||||
}
|
||||
}
|
||||
@@ -1,32 +0,0 @@
|
||||
#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
Reference in New Issue
Block a user